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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Lambermont <hans@lambermont.dyndns.org>2002-10-12 15:37:38 +0400
committerHans Lambermont <hans@lambermont.dyndns.org>2002-10-12 15:37:38 +0400
commit12315f4d0e0ae993805f141f64cb8c73c5297311 (patch)
tree59b45827cd8293cfb727758989c7a74b40183974
Initial revisionv2.25
-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
-rw-r--r--projectfiles/blender/BLO_decrypt/BLO_decrypt.dsp178
-rw-r--r--projectfiles/blender/BLO_decrypt_stub/BLO_decrypt_stub.dsp133
-rw-r--r--projectfiles/blender/BLO_deflate/BLO_deflate.dsp182
-rw-r--r--projectfiles/blender/BLO_deflate_stub/BLO_deflate_stub.dsp154
-rw-r--r--projectfiles/blender/BLO_encrypt/BLO_encrypt.dsp178
-rw-r--r--projectfiles/blender/BLO_inflate/BLO_inflate.dsp181
-rw-r--r--projectfiles/blender/BLO_readblenfile/BLO_readblenfile.dsp181
-rw-r--r--projectfiles/blender/BLO_readblenfile_stub/BLO_readblenfile_stub.dsp154
-rw-r--r--projectfiles/blender/BLO_readstreamglue/BLO_readstreamglue.dsp185
-rw-r--r--projectfiles/blender/BLO_sign/BLO_sign.dsp178
-rw-r--r--projectfiles/blender/BLO_streamglue_stub/BLO_streamglue_stub.dsp158
-rw-r--r--projectfiles/blender/BLO_verify/BLO_verify.dsp177
-rw-r--r--projectfiles/blender/BLO_writeblenfile/BLO_writeblenfile.dsp181
-rw-r--r--projectfiles/blender/BLO_writestreamglue/BLO_writestreamglue.dsp201
-rw-r--r--projectfiles/blender/BLO_writestreamglue_stub/BLO_writestreamglue_stub.dsp188
-rw-r--r--projectfiles/blender/avi/BL_avi.dsp229
-rw-r--r--projectfiles/blender/blenkernel/BKE_blenkernel.dsp708
-rw-r--r--projectfiles/blender/blenlib/BLI_blenlib.dsp389
-rw-r--r--projectfiles/blender/blenpluginapi/blenpluginapi/blenpluginapi.dsp146
-rw-r--r--projectfiles/blender/bpython/frozen/BPY_frozen.dsp296
-rw-r--r--projectfiles/blender/bpython/intern/BPY_python/BPY_python.dsp275
-rw-r--r--projectfiles/blender/glut/BL_glut.dsp324
-rw-r--r--projectfiles/blender/imbuf/BL_imbuf.dsp356
-rw-r--r--projectfiles/blender/img/BL_img.dsp197
-rw-r--r--projectfiles/blender/loader/BLO_loader.dsp208
-rw-r--r--projectfiles/blender/makesdna/DNA_makesdna.dsp407
-rw-r--r--projectfiles/blender/misc/BL_misc.dsp129
-rw-r--r--projectfiles/blender/radiosity/BRA_radiosity.dsp153
-rw-r--r--projectfiles/blender/render/BRE_render.dsp325
-rw-r--r--projectfiles/blender/renderconverter/BRE_renderconverter.dsp128
-rw-r--r--projectfiles/blender/renderui/BRE_renderui.dsp124
-rw-r--r--projectfiles/blender/src/BL_src.dsp470
-rw-r--r--projectfiles/blender/src/BL_src_cre.dsp129
-rw-r--r--projectfiles/blender/src/BL_src_pub.dsp129
-rw-r--r--projectfiles/blenderpublisher/blenderpublisher.dsp149
-rw-r--r--projectfiles/creator/blendercreator.dsp146
-rw-r--r--projectfiles/creator/blendercreator.dsw1223
-rw-r--r--projectfiles/datatoc/datatoc.dsp100
-rw-r--r--projectfiles/gameengine/blenderhook/KX_blenderhook.dsp191
-rw-r--r--projectfiles/gameengine/converter/KX_converter.dsp296
-rw-r--r--projectfiles/gameengine/expression/EXP_expressions.dsp328
-rw-r--r--projectfiles/gameengine/gamelogic/SCA_gamelogic.dsp388
-rw-r--r--projectfiles/gameengine/gameplayer/axctl/GP_axctl.dsp319
-rw-r--r--projectfiles/gameengine/gameplayer/common/GP_common.dsp281
-rw-r--r--projectfiles/gameengine/gameplayer/ghost/GP_ghost.dsp184
-rw-r--r--projectfiles/gameengine/gameplayer/glut/GP_glut.dsp205
-rw-r--r--projectfiles/gameengine/gameplayer/loader/BlenderLoader/BlenderLoader.dsp206
-rw-r--r--projectfiles/gameengine/gameplayer/netscape/GP_netscape.dsp173
-rw-r--r--projectfiles/gameengine/gameplayer/netscape2/GP_netscape.dsp181
-rw-r--r--projectfiles/gameengine/gameplayer/ps2/GP_ps2.dsp182
-rw-r--r--projectfiles/gameengine/gameplayer/qt/gp.dsp164
-rw-r--r--projectfiles/gameengine/gameplayer/qt/gpplugin.dsp824
-rw-r--r--projectfiles/gameengine/gameplayer/qt/qtgp.dsw323
-rw-r--r--projectfiles/gameengine/gameplayer/sdl/GP_sdl.dsp205
-rw-r--r--projectfiles/gameengine/ketsji/KX_ketsji.dsp628
-rw-r--r--projectfiles/gameengine/ketsji/network/KX_network.dsp212
-rw-r--r--projectfiles/gameengine/network/loopbacknetwork/NG_loopbacknetwork.dsp181
-rw-r--r--projectfiles/gameengine/network/network/NG_network.dsp201
-rw-r--r--projectfiles/gameengine/network/terraplaynetwork/NG_terraplaynetwork.dsp180
-rw-r--r--projectfiles/gameengine/physics/PHY_Physics/PHY_Dummy/PHY_Dummy.dsp102
-rw-r--r--projectfiles/gameengine/physics/PHY_Physics/PHY_Physics.dsp142
-rw-r--r--projectfiles/gameengine/physics/PHY_Physics/PHY_Sumo/PHY_Sumo.dsp150
-rw-r--r--projectfiles/gameengine/rasterizer/RAS_rasterizer.dsp269
-rw-r--r--projectfiles/gameengine/rasterizer/openglrasterizer/RAS_openglrasterizer.dsp197
-rw-r--r--projectfiles/gameengine/scenegraph/SG_scenegraph.dsp209
-rw-r--r--projectfiles/gameengine/sound/SND_sound.dsp277
-rw-r--r--projectfiles/gameengine/sound/dummy/SND_Dummy.dsp181
-rw-r--r--projectfiles/gameengine/sound/fmod/SND_fmod.dsp155
-rw-r--r--projectfiles/gameengine/sound/openal/SND_openal.dsp181
-rw-r--r--projectfiles/kernel/gen_messaging/gen_messaging.dsp181
-rw-r--r--projectfiles/kernel/system/SYS_system.dsp209
-rw-r--r--projectfiles/sumo/fuzzics/SM_fuzzics.dsp209
-rw-r--r--projectfiles/sumo/moto/SM_moto.dsp332
-rw-r--r--projectfiles/sumo/solid/SM_solid.dsp366
-rw-r--r--source/BL-license.txt48
-rw-r--r--source/GPL-license.txt340
-rw-r--r--source/Makefile639
-rw-r--r--source/blender/Makefile46
-rw-r--r--source/blender/avi/AVI_avi.h308
-rw-r--r--source/blender/avi/Makefile37
-rw-r--r--source/blender/avi/intern/Makefile54
-rw-r--r--source/blender/avi/intern/avi.c835
-rw-r--r--source/blender/avi/intern/avi_intern.h53
-rw-r--r--source/blender/avi/intern/avirgb.c144
-rw-r--r--source/blender/avi/intern/avirgb.h33
-rw-r--r--source/blender/avi/intern/codecs.c143
-rw-r--r--source/blender/avi/intern/endian.c207
-rw-r--r--source/blender/avi/intern/endian.h54
-rw-r--r--source/blender/avi/intern/mjpeg.c452
-rw-r--r--source/blender/avi/intern/mjpeg.h33
-rw-r--r--source/blender/avi/intern/options.c127
-rw-r--r--source/blender/avi/intern/rgb32.c88
-rw-r--r--source/blender/avi/intern/rgb32.h33
-rw-r--r--source/blender/blenkernel/BKE_action.h238
-rw-r--r--source/blender/blenkernel/BKE_anim.h52
-rw-r--r--source/blender/blenkernel/BKE_armature.h121
-rw-r--r--source/blender/blenkernel/BKE_bad_level_calls.h143
-rw-r--r--source/blender/blenkernel/BKE_blender.h64
-rw-r--r--source/blender/blenkernel/BKE_bmfont.h64
-rw-r--r--source/blender/blenkernel/BKE_bmfont_types.h61
-rw-r--r--source/blender/blenkernel/BKE_booleanops.h143
-rw-r--r--source/blender/blenkernel/BKE_booleanops_mesh.h122
-rw-r--r--source/blender/blenkernel/BKE_constraint.h64
-rw-r--r--source/blender/blenkernel/BKE_curve.h86
-rw-r--r--source/blender/blenkernel/BKE_deform.h50
-rw-r--r--source/blender/blenkernel/BKE_displist.h117
-rw-r--r--source/blender/blenkernel/BKE_effect.h65
-rw-r--r--source/blender/blenkernel/BKE_endian.h46
-rw-r--r--source/blender/blenkernel/BKE_exotic.h54
-rw-r--r--source/blender/blenkernel/BKE_font.h50
-rw-r--r--source/blender/blenkernel/BKE_global.h224
-rw-r--r--source/blender/blenkernel/BKE_group.h58
-rw-r--r--source/blender/blenkernel/BKE_ika.h59
-rw-r--r--source/blender/blenkernel/BKE_image.h67
-rw-r--r--source/blender/blenkernel/BKE_ipo.h101
-rw-r--r--source/blender/blenkernel/BKE_key.h69
-rw-r--r--source/blender/blenkernel/BKE_lattice.h59
-rw-r--r--source/blender/blenkernel/BKE_library.h69
-rw-r--r--source/blender/blenkernel/BKE_main.h80
-rw-r--r--source/blender/blenkernel/BKE_material.h68
-rw-r--r--source/blender/blenkernel/BKE_mball.h64
-rw-r--r--source/blender/blenkernel/BKE_mesh.h116
-rw-r--r--source/blender/blenkernel/BKE_nla.h46
-rw-r--r--source/blender/blenkernel/BKE_object.h99
-rw-r--r--source/blender/blenkernel/BKE_osa_types.h53
-rw-r--r--source/blender/blenkernel/BKE_packedFile.h61
-rw-r--r--source/blender/blenkernel/BKE_plugin_types.h70
-rw-r--r--source/blender/blenkernel/BKE_property.h54
-rw-r--r--source/blender/blenkernel/BKE_sca.h74
-rw-r--r--source/blender/blenkernel/BKE_scene.h56
-rw-r--r--source/blender/blenkernel/BKE_screen.h40
-rw-r--r--source/blender/blenkernel/BKE_sound.h51
-rw-r--r--source/blender/blenkernel/BKE_subsurf.h43
-rw-r--r--source/blender/blenkernel/BKE_text.h128
-rw-r--r--source/blender/blenkernel/BKE_texture.h85
-rw-r--r--source/blender/blenkernel/BKE_utildefines.h300
-rw-r--r--source/blender/blenkernel/BKE_world.h45
-rw-r--r--source/blender/blenkernel/BKE_writeavi.h50
-rw-r--r--source/blender/blenkernel/Makefile37
-rw-r--r--source/blender/blenkernel/bad_level_call_stubs/Makefile55
-rw-r--r--source/blender/blenkernel/bad_level_call_stubs/stubs.c180
-rw-r--r--source/blender/blenkernel/intern/Makefile74
-rw-r--r--source/blender/blenkernel/intern/action.c873
-rw-r--r--source/blender/blenkernel/intern/anim.c512
-rw-r--r--source/blender/blenkernel/intern/armature.c1451
-rw-r--r--source/blender/blenkernel/intern/blender.c343
-rw-r--r--source/blender/blenkernel/intern/bmfont.c293
-rw-r--r--source/blender/blenkernel/intern/constraint.c732
-rw-r--r--source/blender/blenkernel/intern/curve.c2344
-rw-r--r--source/blender/blenkernel/intern/deform.c120
-rw-r--r--source/blender/blenkernel/intern/displist.c2085
-rw-r--r--source/blender/blenkernel/intern/effect.c854
-rw-r--r--source/blender/blenkernel/intern/exotic.c4081
-rw-r--r--source/blender/blenkernel/intern/font.c656
-rw-r--r--source/blender/blenkernel/intern/group.c329
-rw-r--r--source/blender/blenkernel/intern/ika.c596
-rw-r--r--source/blender/blenkernel/intern/image.c1486
-rw-r--r--source/blender/blenkernel/intern/ipo.c1878
-rw-r--r--source/blender/blenkernel/intern/key.c1212
-rw-r--r--source/blender/blenkernel/intern/lattice.c633
-rw-r--r--source/blender/blenkernel/intern/library.c905
-rw-r--r--source/blender/blenkernel/intern/material.c747
-rw-r--r--source/blender/blenkernel/intern/mball.c1540
-rw-r--r--source/blender/blenkernel/intern/mesh.c1120
-rw-r--r--source/blender/blenkernel/intern/nla.c118
-rw-r--r--source/blender/blenkernel/intern/object.c1681
-rw-r--r--source/blender/blenkernel/intern/packedFile.c638
-rw-r--r--source/blender/blenkernel/intern/property.c269
-rw-r--r--source/blender/blenkernel/intern/sca.c631
-rw-r--r--source/blender/blenkernel/intern/scene.c536
-rw-r--r--source/blender/blenkernel/intern/screen.c53
-rw-r--r--source/blender/blenkernel/intern/sound.c112
-rw-r--r--source/blender/blenkernel/intern/subsurf.c890
-rw-r--r--source/blender/blenkernel/intern/text.c1986
-rw-r--r--source/blender/blenkernel/intern/texture.c2320
-rw-r--r--source/blender/blenkernel/intern/world.c201
-rw-r--r--source/blender/blenkernel/intern/writeavi.c147
-rw-r--r--source/blender/blenlib/BLI_arithb.h758
-rw-r--r--source/blender/blenlib/BLI_blenlib.h325
-rw-r--r--source/blender/blenlib/BLI_dynstr.h89
-rw-r--r--source/blender/blenlib/BLI_editVert.h73
-rw-r--r--source/blender/blenlib/BLI_ghash.h59
-rw-r--r--source/blender/blenlib/BLI_gsqueue.h95
-rw-r--r--source/blender/blenlib/BLI_linklist.h60
-rw-r--r--source/blender/blenlib/BLI_memarena.h58
-rw-r--r--source/blender/blenlib/BLI_rand.h68
-rw-r--r--source/blender/blenlib/BLI_storage_types.h79
-rw-r--r--source/blender/blenlib/BLI_vfontdata.h66
-rw-r--r--source/blender/blenlib/BLI_winstuff.h96
-rw-r--r--source/blender/blenlib/MTC_matrixops.h164
-rw-r--r--source/blender/blenlib/MTC_vectorops.h60
-rw-r--r--source/blender/blenlib/Makefile37
-rw-r--r--source/blender/blenlib/PIL_dynlib.h54
-rw-r--r--source/blender/blenlib/PIL_time.h61
-rw-r--r--source/blender/blenlib/intern/BLI_callbacks.h44
-rw-r--r--source/blender/blenlib/intern/BLI_dynstr.c115
-rw-r--r--source/blender/blenlib/intern/BLI_fileops.h49
-rw-r--r--source/blender/blenlib/intern/BLI_ghash.c184
-rw-r--r--source/blender/blenlib/intern/BLI_linklist.c98
-rw-r--r--source/blender/blenlib/intern/BLI_memarena.c80
-rw-r--r--source/blender/blenlib/intern/BLI_scanfill.h41
-rw-r--r--source/blender/blenlib/intern/BLI_storage.h40
-rw-r--r--source/blender/blenlib/intern/BLI_util.h47
-rw-r--r--source/blender/blenlib/intern/Makefile51
-rw-r--r--source/blender/blenlib/intern/arithb.c2355
-rw-r--r--source/blender/blenlib/intern/dynlib.c146
-rw-r--r--source/blender/blenlib/intern/fileops.c293
-rw-r--r--source/blender/blenlib/intern/gsqueue.c112
-rw-r--r--source/blender/blenlib/intern/matrixops.c440
-rw-r--r--source/blender/blenlib/intern/noise.c390
-rw-r--r--source/blender/blenlib/intern/psfont.c2124
-rw-r--r--source/blender/blenlib/intern/rand.c84
-rw-r--r--source/blender/blenlib/intern/rct.c115
-rw-r--r--source/blender/blenlib/intern/scanfill.c1234
-rw-r--r--source/blender/blenlib/intern/storage.c568
-rw-r--r--source/blender/blenlib/intern/time.c101
-rw-r--r--source/blender/blenlib/intern/util.c828
-rw-r--r--source/blender/blenlib/intern/vectorops.c165
-rw-r--r--source/blender/blenlib/intern/winstuff.c193
-rw-r--r--source/blender/blenloader/BLO_genfile.h39
-rw-r--r--source/blender/blenloader/BLO_readfile.h241
-rw-r--r--source/blender/blenloader/BLO_soundfile.h43
-rw-r--r--source/blender/blenloader/BLO_writefile.h40
-rw-r--r--source/blender/blenloader/Makefile37
-rw-r--r--source/blender/blenloader/intern/Makefile75
-rw-r--r--source/blender/blenloader/intern/genfile.c1098
-rw-r--r--source/blender/blenloader/intern/genfile.h48
-rw-r--r--source/blender/blenloader/intern/readblenentry.c340
-rw-r--r--source/blender/blenloader/intern/readfile.c4810
-rw-r--r--source/blender/blenloader/intern/readfile.h130
-rw-r--r--source/blender/blenloader/intern/writefile.c1788
-rw-r--r--source/blender/blenpluginapi/Makefile37
-rw-r--r--source/blender/blenpluginapi/documentation.h71
-rw-r--r--source/blender/blenpluginapi/floatpatch.h90
-rw-r--r--source/blender/blenpluginapi/iff.h185
-rw-r--r--source/blender/blenpluginapi/intern/Makefile62
-rw-r--r--source/blender/blenpluginapi/intern/pluginapi.c341
-rw-r--r--source/blender/blenpluginapi/plugin.h93
-rw-r--r--source/blender/blenpluginapi/util.h94
-rw-r--r--source/blender/bpython/Makefile37
-rw-r--r--source/blender/bpython/include/BPY_extern.h60
-rw-r--r--source/blender/bpython/include/BPY_objtypes.h38
-rw-r--r--source/blender/bpython/intern/BPY_constobject.c183
-rw-r--r--source/blender/bpython/intern/BPY_constobject.h40
-rw-r--r--source/blender/bpython/intern/BPY_csg.c239
-rw-r--r--source/blender/bpython/intern/BPY_csg.h35
-rw-r--r--source/blender/bpython/intern/BPY_image.c103
-rw-r--r--source/blender/bpython/intern/BPY_ipo.c717
-rw-r--r--source/blender/bpython/intern/BPY_links.c96
-rw-r--r--source/blender/bpython/intern/BPY_listbase_macro.h62
-rw-r--r--source/blender/bpython/intern/BPY_macros.h268
-rw-r--r--source/blender/bpython/intern/BPY_main.c672
-rw-r--r--source/blender/bpython/intern/BPY_main.h86
-rw-r--r--source/blender/bpython/intern/BPY_modules.h47
-rw-r--r--source/blender/bpython/intern/BPY_object.c499
-rw-r--r--source/blender/bpython/intern/BPY_scene.c506
-rw-r--r--source/blender/bpython/intern/BPY_text.c295
-rw-r--r--source/blender/bpython/intern/BPY_tools.c106
-rw-r--r--source/blender/bpython/intern/BPY_tools.h37
-rw-r--r--source/blender/bpython/intern/BPY_types.h39
-rw-r--r--source/blender/bpython/intern/BPY_window.h33
-rw-r--r--source/blender/bpython/intern/Makefile75
-rw-r--r--source/blender/bpython/intern/README22
-rw-r--r--source/blender/bpython/intern/api.h87
-rw-r--r--source/blender/bpython/intern/b_import.c191
-rw-r--r--source/blender/bpython/intern/b_import.h35
-rw-r--r--source/blender/bpython/intern/b_interface.c753
-rw-r--r--source/blender/bpython/intern/b_interface.h184
-rw-r--r--source/blender/bpython/intern/opy_blender.c342
-rw-r--r--source/blender/bpython/intern/opy_datablock.c1299
-rw-r--r--source/blender/bpython/intern/opy_datablock.h193
-rw-r--r--source/blender/bpython/intern/opy_draw.c2679
-rw-r--r--source/blender/bpython/intern/opy_matrix.c173
-rw-r--r--source/blender/bpython/intern/opy_nmesh.c1716
-rw-r--r--source/blender/bpython/intern/opy_nmesh.h93
-rw-r--r--source/blender/bpython/intern/opy_vector.c241
-rw-r--r--source/blender/bpython/intern/opy_vector.h63
-rw-r--r--source/blender/bpython/intern/opy_window.c194
-rw-r--r--source/blender/decrypt/BLO_decrypt.h78
-rw-r--r--source/blender/decrypt/BLO_en_de_cryptHeader.h65
-rw-r--r--source/blender/decrypt/Makefile37
-rw-r--r--source/blender/decrypt/intern/BLO_decrypt.c394
-rw-r--r--source/blender/decrypt/intern/Makefile61
-rw-r--r--source/blender/decrypt/stub/BLO_decryptSTUB.c85
-rw-r--r--source/blender/decrypt/stub/Makefile51
-rw-r--r--source/blender/deflate/BLO_deflate.h58
-rw-r--r--source/blender/deflate/Makefile39
-rw-r--r--source/blender/deflate/intern/BLO_deflate.c210
-rw-r--r--source/blender/deflate/intern/Makefile57
-rw-r--r--source/blender/deflate/stub/BLO_deflateSTUB.c52
-rw-r--r--source/blender/deflate/stub/Makefile55
-rw-r--r--source/blender/deflate/test/Makefile37
-rw-r--r--source/blender/deflate/test/stubbed/Makefile72
-rw-r--r--source/blender/deflate/test/stubbed/stubbed.c203
-rw-r--r--source/blender/encrypt/BLO_encrypt.h50
-rw-r--r--source/blender/encrypt/Makefile37
-rw-r--r--source/blender/encrypt/intern/BLO_encrypt.c229
-rw-r--r--source/blender/encrypt/intern/Makefile60
-rw-r--r--source/blender/imbuf/IMB_imbuf.h479
-rw-r--r--source/blender/imbuf/IMB_imbuf_types.h155
-rw-r--r--source/blender/imbuf/Makefile37
-rw-r--r--source/blender/imbuf/intern/IMB_allocimbuf.h51
-rw-r--r--source/blender/imbuf/intern/IMB_amiga.h44
-rw-r--r--source/blender/imbuf/intern/IMB_bitplanes.h44
-rw-r--r--source/blender/imbuf/intern/IMB_bmp.h43
-rw-r--r--source/blender/imbuf/intern/IMB_cmap.h44
-rw-r--r--source/blender/imbuf/intern/IMB_divers.h42
-rw-r--r--source/blender/imbuf/intern/IMB_filter.h42
-rw-r--r--source/blender/imbuf/intern/IMB_ham.h42
-rw-r--r--source/blender/imbuf/intern/IMB_hamx.h44
-rw-r--r--source/blender/imbuf/intern/IMB_iff.h43
-rw-r--r--source/blender/imbuf/intern/IMB_iris.h43
-rw-r--r--source/blender/imbuf/intern/IMB_jpeg.h45
-rw-r--r--source/blender/imbuf/intern/IMB_png.h43
-rw-r--r--source/blender/imbuf/intern/IMB_targa.h45
-rw-r--r--source/blender/imbuf/intern/Makefile60
-rw-r--r--source/blender/imbuf/intern/allocimbuf.c357
-rw-r--r--source/blender/imbuf/intern/amiga.c536
-rw-r--r--source/blender/imbuf/intern/anim.c1157
-rw-r--r--source/blender/imbuf/intern/antialias.c471
-rw-r--r--source/blender/imbuf/intern/bitplanes.c359
-rw-r--r--source/blender/imbuf/intern/bmp_decode.c191
-rw-r--r--source/blender/imbuf/intern/cmap.c589
-rw-r--r--source/blender/imbuf/intern/cspace.c177
-rw-r--r--source/blender/imbuf/intern/data.c145
-rw-r--r--source/blender/imbuf/intern/dither.c133
-rw-r--r--source/blender/imbuf/intern/divers.c119
-rw-r--r--source/blender/imbuf/intern/filter.c144
-rw-r--r--source/blender/imbuf/intern/ham.c290
-rw-r--r--source/blender/imbuf/intern/hamx.c593
-rw-r--r--source/blender/imbuf/intern/iff.c225
-rw-r--r--source/blender/imbuf/intern/imageprocess.c59
-rw-r--r--source/blender/imbuf/intern/imbuf.h190
-rw-r--r--source/blender/imbuf/intern/imbuf_patch.h114
-rw-r--r--source/blender/imbuf/intern/iris.c727
-rw-r--r--source/blender/imbuf/intern/jpeg.c629
-rw-r--r--source/blender/imbuf/intern/matrix.h86
-rw-r--r--source/blender/imbuf/intern/png_decode.c263
-rw-r--r--source/blender/imbuf/intern/png_encode.c236
-rw-r--r--source/blender/imbuf/intern/readimage.c256
-rw-r--r--source/blender/imbuf/intern/rectop.c135
-rw-r--r--source/blender/imbuf/intern/rotate.c71
-rw-r--r--source/blender/imbuf/intern/scaling.c699
-rw-r--r--source/blender/imbuf/intern/targa.c632
-rw-r--r--source/blender/imbuf/intern/util.c90
-rw-r--r--source/blender/imbuf/intern/writeimage.c145
-rw-r--r--source/blender/img/IMG_Api.h63
-rw-r--r--source/blender/img/Makefile37
-rw-r--r--source/blender/img/intern/IMG_Api.cpp121
-rw-r--r--source/blender/img/intern/IMG_BrushRGBA32.cpp132
-rw-r--r--source/blender/img/intern/IMG_BrushRGBA32.h134
-rw-r--r--source/blender/img/intern/IMG_CanvasRGBA32.cpp82
-rw-r--r--source/blender/img/intern/IMG_CanvasRGBA32.h95
-rw-r--r--source/blender/img/intern/IMG_Color.h149
-rw-r--r--source/blender/img/intern/IMG_Line.cpp33
-rw-r--r--source/blender/img/intern/IMG_Line.h142
-rw-r--r--source/blender/img/intern/IMG_MemPtr.h114
-rw-r--r--source/blender/img/intern/IMG_Pixmap.cpp59
-rw-r--r--source/blender/img/intern/IMG_Pixmap.h186
-rw-r--r--source/blender/img/intern/IMG_PixmapRGBA32.cpp262
-rw-r--r--source/blender/img/intern/IMG_PixmapRGBA32.h261
-rw-r--r--source/blender/img/intern/IMG_Rect.cpp129
-rw-r--r--source/blender/img/intern/IMG_Rect.h200
-rw-r--r--source/blender/img/intern/IMG_Types.h48
-rw-r--r--source/blender/img/intern/Makefile49
-rw-r--r--source/blender/include/BDR_drawaction.h48
-rw-r--r--source/blender/include/BDR_drawmesh.h81
-rw-r--r--source/blender/include/BDR_drawobject.h67
-rw-r--r--source/blender/include/BDR_editcurve.h93
-rw-r--r--source/blender/include/BDR_editface.h56
-rw-r--r--source/blender/include/BDR_editmball.h49
-rw-r--r--source/blender/include/BDR_editobject.h119
-rw-r--r--source/blender/include/BDR_isect.h92
-rw-r--r--source/blender/include/BDR_vpaint.h58
-rw-r--r--source/blender/include/BIF_buttons.h40
-rw-r--r--source/blender/include/BIF_drawimage.h49
-rw-r--r--source/blender/include/BIF_drawoops.h40
-rw-r--r--source/blender/include/BIF_drawscene.h33
-rw-r--r--source/blender/include/BIF_drawseq.h41
-rw-r--r--source/blender/include/BIF_drawtext.h51
-rw-r--r--source/blender/include/BIF_editarmature.h116
-rw-r--r--source/blender/include/BIF_editconstraint.h62
-rw-r--r--source/blender/include/BIF_editdeform.h51
-rw-r--r--source/blender/include/BIF_editfont.h48
-rw-r--r--source/blender/include/BIF_editgroup.h38
-rw-r--r--source/blender/include/BIF_editika.h37
-rw-r--r--source/blender/include/BIF_editkey.h62
-rw-r--r--source/blender/include/BIF_editlattice.h44
-rw-r--r--source/blender/include/BIF_editmesh.h118
-rw-r--r--source/blender/include/BIF_editnla.h38
-rw-r--r--source/blender/include/BIF_editoops.h45
-rw-r--r--source/blender/include/BIF_editsca.h40
-rw-r--r--source/blender/include/BIF_editseq.h59
-rw-r--r--source/blender/include/BIF_editsima.h38
-rw-r--r--source/blender/include/BIF_editsound.h71
-rw-r--r--source/blender/include/BIF_editview.h52
-rw-r--r--source/blender/include/BIF_fsmenu.h72
-rw-r--r--source/blender/include/BIF_gl.h70
-rw-r--r--source/blender/include/BIF_glutil.h189
-rw-r--r--source/blender/include/BIF_graphics.h56
-rw-r--r--source/blender/include/BIF_imasel.h58
-rw-r--r--source/blender/include/BIF_interface.h128
-rw-r--r--source/blender/include/BIF_keyval.h38
-rw-r--r--source/blender/include/BIF_mainqueue.h46
-rw-r--r--source/blender/include/BIF_mywindow.h107
-rw-r--r--source/blender/include/BIF_oops.h68
-rw-r--r--source/blender/include/BIF_poseobject.h65
-rw-r--r--source/blender/include/BIF_previewrender.h38
-rw-r--r--source/blender/include/BIF_renderwin.h49
-rw-r--r--source/blender/include/BIF_resources.h321
-rw-r--r--source/blender/include/BIF_scrarea.h51
-rw-r--r--source/blender/include/BIF_screen.h124
-rw-r--r--source/blender/include/BIF_space.h94
-rw-r--r--source/blender/include/BIF_spacetypes.h60
-rw-r--r--source/blender/include/BIF_tbcallback.h41
-rw-r--r--source/blender/include/BIF_toets.h43
-rw-r--r--source/blender/include/BIF_toolbox.h122
-rw-r--r--source/blender/include/BIF_usiblender.h48
-rw-r--r--source/blender/include/BIF_writeavicodec.h44
-rw-r--r--source/blender/include/BIF_writeimage.h42
-rw-r--r--source/blender/include/BIF_writemovie.h40
-rw-r--r--source/blender/include/BSE_buttons.h46
-rw-r--r--source/blender/include/BSE_drawimasel.h57
-rw-r--r--source/blender/include/BSE_drawipo.h63
-rw-r--r--source/blender/include/BSE_drawnla.h39
-rw-r--r--source/blender/include/BSE_drawoops.h49
-rw-r--r--source/blender/include/BSE_drawview.h64
-rw-r--r--source/blender/include/BSE_edit.h44
-rw-r--r--source/blender/include/BSE_editaction.h56
-rw-r--r--source/blender/include/BSE_editaction_types.h50
-rw-r--r--source/blender/include/BSE_editipo.h142
-rw-r--r--source/blender/include/BSE_editipo_types.h262
-rw-r--r--source/blender/include/BSE_editnla_types.h42
-rw-r--r--source/blender/include/BSE_filesel.h59
-rw-r--r--source/blender/include/BSE_headerbuttons.h84
-rw-r--r--source/blender/include/BSE_sequence.h113
-rw-r--r--source/blender/include/BSE_trans_types.h88
-rw-r--r--source/blender/include/BSE_types.h71
-rw-r--r--source/blender/include/BSE_view.h70
-rw-r--r--source/blender/include/LOD_DependKludge.h40
-rw-r--r--source/blender/include/TPT_DependKludge.h42
-rw-r--r--source/blender/include/blendef.h403
-rw-r--r--source/blender/include/datatoc.h56
-rw-r--r--source/blender/include/editlattice_ext.h41
-rw-r--r--source/blender/include/interface.h130
-rw-r--r--source/blender/include/ipo.h262
-rw-r--r--source/blender/include/keyed_functions.h68
-rw-r--r--source/blender/include/license_key.h94
-rw-r--r--source/blender/include/mydevice.h242
-rw-r--r--source/blender/include/nla.h63
-rw-r--r--source/blender/include/objfnt.h104
-rw-r--r--source/blender/include/particle_effect.h48
-rw-r--r--source/blender/include/playanim_ext.h40
-rw-r--r--source/blender/inflate/BLO_in_de_flateHeader.h59
-rw-r--r--source/blender/inflate/BLO_inflate.h80
-rw-r--r--source/blender/inflate/Makefile37
-rw-r--r--source/blender/inflate/intern/BLO_inflate.c431
-rw-r--r--source/blender/inflate/intern/Makefile55
-rw-r--r--source/blender/makesdna/DNA_ID.h152
-rw-r--r--source/blender/makesdna/DNA_action_types.h102
-rw-r--r--source/blender/makesdna/DNA_actuator_types.h405
-rw-r--r--source/blender/makesdna/DNA_armature_types.h124
-rw-r--r--source/blender/makesdna/DNA_camera_types.h77
-rw-r--r--source/blender/makesdna/DNA_constraint_types.h158
-rw-r--r--source/blender/makesdna/DNA_controller_types.h78
-rw-r--r--source/blender/makesdna/DNA_curve_types.h202
-rw-r--r--source/blender/makesdna/DNA_documentation.h68
-rw-r--r--source/blender/makesdna/DNA_effect_types.h127
-rw-r--r--source/blender/makesdna/DNA_fileglobal_types.h47
-rw-r--r--source/blender/makesdna/DNA_group_types.h100
-rw-r--r--source/blender/makesdna/DNA_ika_types.h91
-rw-r--r--source/blender/makesdna/DNA_image_types.h86
-rw-r--r--source/blender/makesdna/DNA_ipo_types.h302
-rw-r--r--source/blender/makesdna/DNA_key_types.h84
-rw-r--r--source/blender/makesdna/DNA_lamp_types.h96
-rw-r--r--source/blender/makesdna/DNA_lattice_types.h65
-rw-r--r--source/blender/makesdna/DNA_listBase.h63
-rw-r--r--source/blender/makesdna/DNA_material_types.h162
-rw-r--r--source/blender/makesdna/DNA_mesh_types.h229
-rw-r--r--source/blender/makesdna/DNA_meta_types.h100
-rw-r--r--source/blender/makesdna/DNA_nla_types.h71
-rw-r--r--source/blender/makesdna/DNA_object_types.h316
-rw-r--r--source/blender/makesdna/DNA_oops_types.h68
-rw-r--r--source/blender/makesdna/DNA_packedFile_types.h63
-rw-r--r--source/blender/makesdna/DNA_property_types.h67
-rw-r--r--source/blender/makesdna/DNA_radio_types.h52
-rw-r--r--source/blender/makesdna/DNA_scene_types.h346
-rw-r--r--source/blender/makesdna/DNA_screen_types.h152
-rw-r--r--source/blender/makesdna/DNA_scriptlink_types.h63
-rw-r--r--source/blender/makesdna/DNA_sdna_types.h82
-rw-r--r--source/blender/makesdna/DNA_sensor_types.h225
-rw-r--r--source/blender/makesdna/DNA_sequence_types.h158
-rw-r--r--source/blender/makesdna/DNA_sound_types.h190
-rw-r--r--source/blender/makesdna/DNA_space_types.h471
-rw-r--r--source/blender/makesdna/DNA_text_types.h80
-rw-r--r--source/blender/makesdna/DNA_texture_types.h276
-rw-r--r--source/blender/makesdna/DNA_userdef_types.h105
-rw-r--r--source/blender/makesdna/DNA_vec_types.h91
-rw-r--r--source/blender/makesdna/DNA_vfont_types.h59
-rw-r--r--source/blender/makesdna/DNA_view2d_types.h52
-rw-r--r--source/blender/makesdna/DNA_view3d_types.h127
-rw-r--r--source/blender/makesdna/DNA_wave_types.h48
-rw-r--r--source/blender/makesdna/DNA_world_types.h119
-rw-r--r--source/blender/makesdna/Makefile42
-rw-r--r--source/blender/makesdna/intern/Makefile86
-rw-r--r--source/blender/makesdna/intern/dna.c874
-rw-r--r--source/blender/makesdna/intern/makesdna.c1121
-rw-r--r--source/blender/misc/Makefile54
-rw-r--r--source/blender/misc/blendertimer.c77
-rw-r--r--source/blender/misc/blendertimer.h51
-rw-r--r--source/blender/radiosity/Makefile37
-rw-r--r--source/blender/radiosity/extern/include/radio.h170
-rw-r--r--source/blender/radiosity/extern/include/radio_types.h174
-rw-r--r--source/blender/radiosity/intern/Makefile37
-rw-r--r--source/blender/radiosity/intern/source/Makefile60
-rw-r--r--source/blender/radiosity/intern/source/raddisplay.c527
-rw-r--r--source/blender/radiosity/intern/source/radfactors.c956
-rw-r--r--source/blender/radiosity/intern/source/radio.c379
-rw-r--r--source/blender/radiosity/intern/source/radnode.c1095
-rw-r--r--source/blender/radiosity/intern/source/radpostprocess.c871
-rw-r--r--source/blender/radiosity/intern/source/radpreprocess.c787
-rw-r--r--source/blender/readblenfile/BLO_readblenfile.h83
-rw-r--r--source/blender/readblenfile/Makefile37
-rw-r--r--source/blender/readblenfile/intern/BLO_readblenfile.c647
-rw-r--r--source/blender/readblenfile/intern/Makefile54
-rw-r--r--source/blender/readblenfile/stub/BLO_readblenfileSTUB.c90
-rw-r--r--source/blender/readblenfile/stub/Makefile50
-rw-r--r--source/blender/readblenfile/test/Makefile53
-rw-r--r--source/blender/readblenfile/test/test.c54
-rw-r--r--source/blender/readstreamglue/BLO_keyStore.h75
-rw-r--r--source/blender/readstreamglue/BLO_readStreamErrors.h89
-rw-r--r--source/blender/readstreamglue/BLO_readStreamGlue.h96
-rw-r--r--source/blender/readstreamglue/BLO_sys_types.h97
-rw-r--r--source/blender/readstreamglue/Makefile37
-rw-r--r--source/blender/readstreamglue/intern/BLO_keyStore.c128
-rw-r--r--source/blender/readstreamglue/intern/BLO_keyStorePrivate.h64
-rw-r--r--source/blender/readstreamglue/intern/BLO_readStreamGlue.c228
-rw-r--r--source/blender/readstreamglue/intern/BLO_readStreamGlueLoopBack.c80
-rw-r--r--source/blender/readstreamglue/intern/BLO_readStreamGlueLoopBack.h52
-rw-r--r--source/blender/readstreamglue/intern/Makefile66
-rw-r--r--source/blender/render/Makefile37
-rw-r--r--source/blender/render/extern/include/render.h290
-rw-r--r--source/blender/render/extern/include/render_types.h256
-rw-r--r--source/blender/render/intern/Makefile37
-rw-r--r--source/blender/render/intern/include/RE_DummyShadowBuffer.h70
-rw-r--r--source/blender/render/intern/include/RE_ShadowBuffer.h61
-rw-r--r--source/blender/render/intern/include/RE_basicShadowBuffer.h94
-rw-r--r--source/blender/render/intern/include/RE_callbacks.h84
-rw-r--r--source/blender/render/intern/include/edgeRender.h63
-rw-r--r--source/blender/render/intern/include/envmap.h49
-rw-r--r--source/blender/render/intern/include/errorHandler.h69
-rw-r--r--source/blender/render/intern/include/gammaCorrectionTables.h79
-rw-r--r--source/blender/render/intern/include/initrender.h59
-rw-r--r--source/blender/render/intern/include/jitter.h50
-rw-r--r--source/blender/render/intern/include/old_zbuffer_types.h58
-rw-r--r--source/blender/render/intern/include/outerRenderLoop.h43
-rw-r--r--source/blender/render/intern/include/pixelblending.h209
-rw-r--r--source/blender/render/intern/include/pixelblending_types.h61
-rw-r--r--source/blender/render/intern/include/pixelshading.h122
-rw-r--r--source/blender/render/intern/include/renderHelp.h63
-rw-r--r--source/blender/render/intern/include/renderPreAndPost.h43
-rw-r--r--source/blender/render/intern/include/render_intern.h60
-rw-r--r--source/blender/render/intern/include/rendercore.h117
-rw-r--r--source/blender/render/intern/include/rendercore_int.h55
-rw-r--r--source/blender/render/intern/include/shadbuf.h75
-rw-r--r--source/blender/render/intern/include/shadowBuffer.h79
-rw-r--r--source/blender/render/intern/include/texture.h86
-rw-r--r--source/blender/render/intern/include/vanillaRenderPipe.h49
-rw-r--r--source/blender/render/intern/include/vanillaRenderPipe_int.h191
-rw-r--r--source/blender/render/intern/include/vanillaRenderPipe_types.h90
-rw-r--r--source/blender/render/intern/include/zbuf.h180
-rw-r--r--source/blender/render/intern/include/zbuf_int.h203
-rw-r--r--source/blender/render/intern/include/zbuf_types.h78
-rw-r--r--source/blender/render/intern/include/zbufferdatastruct.h99
-rw-r--r--source/blender/render/intern/include/zbufferdatastruct_types.h77
-rw-r--r--source/blender/render/intern/source/Makefile60
-rw-r--r--source/blender/render/intern/source/RE_DummyShadowBuffer.cpp66
-rw-r--r--source/blender/render/intern/source/RE_basicShadowBuffer.cpp734
-rw-r--r--source/blender/render/intern/source/RE_callbacks.c159
-rw-r--r--source/blender/render/intern/source/edgeRender.c952
-rw-r--r--source/blender/render/intern/source/envmap.c689
-rw-r--r--source/blender/render/intern/source/errorHandler.c99
-rw-r--r--source/blender/render/intern/source/gammaCorrectionTables.c168
-rw-r--r--source/blender/render/intern/source/initrender.c1329
-rw-r--r--source/blender/render/intern/source/jitter.c192
-rw-r--r--source/blender/render/intern/source/outerRenderLoop.c515
-rw-r--r--source/blender/render/intern/source/pixelblending.c919
-rw-r--r--source/blender/render/intern/source/pixelshading.c1917
-rw-r--r--source/blender/render/intern/source/renderHelp.c294
-rw-r--r--source/blender/render/intern/source/renderPreAndPost.c94
-rw-r--r--source/blender/render/intern/source/rendercore.c2902
-rw-r--r--source/blender/render/intern/source/renderdatabase.c248
-rw-r--r--source/blender/render/intern/source/shadbuf.c771
-rw-r--r--source/blender/render/intern/source/shadowBuffer.cpp100
-rw-r--r--source/blender/render/intern/source/vanillaRenderPipe.c1654
-rw-r--r--source/blender/render/intern/source/zbuf.c2329
-rw-r--r--source/blender/render/intern/source/zbufferdatastruct.c342
-rw-r--r--source/blender/renderconverter/Makefile37
-rw-r--r--source/blender/renderconverter/RE_renderconverter.h95
-rw-r--r--source/blender/renderconverter/intern/Makefile57
-rw-r--r--source/blender/renderconverter/intern/convertBlenderScene.c2943
-rw-r--r--source/blender/sign/BLO_sign.h50
-rw-r--r--source/blender/sign/Makefile37
-rw-r--r--source/blender/sign/intern/BLO_sign.c227
-rw-r--r--source/blender/sign/intern/Makefile60
-rw-r--r--source/blender/src/.BCkey1
-rw-r--r--source/blender/src/B.blend.c1051
-rw-r--r--source/blender/src/Bfont.c134
-rw-r--r--source/blender/src/Makefile106
-rw-r--r--source/blender/src/blenderbuttons.c1210
-rw-r--r--source/blender/src/booleanops.c795
-rw-r--r--source/blender/src/booleanops_mesh.c302
-rw-r--r--source/blender/src/buttons.c7338
-rw-r--r--source/blender/src/cmap.tga.c88
-rw-r--r--source/blender/src/cmovie.tga.c201
-rw-r--r--source/blender/src/cre/license.jpeg.c34
-rw-r--r--source/blender/src/cre/license_key.c195
-rw-r--r--source/blender/src/drawaction.c583
-rw-r--r--source/blender/src/drawimage.c582
-rw-r--r--source/blender/src/drawimasel.c843
-rw-r--r--source/blender/src/drawipo.c1622
-rw-r--r--source/blender/src/drawmesh.c999
-rw-r--r--source/blender/src/drawnla.c523
-rw-r--r--source/blender/src/drawobject.c3579
-rw-r--r--source/blender/src/drawoops.c437
-rw-r--r--source/blender/src/drawscene.c118
-rw-r--r--source/blender/src/drawseq.c617
-rw-r--r--source/blender/src/drawsound.c207
-rw-r--r--source/blender/src/drawtext.c1101
-rw-r--r--source/blender/src/drawview.c1650
-rw-r--r--source/blender/src/edit.c830
-rw-r--r--source/blender/src/editaction.c1414
-rw-r--r--source/blender/src/editarmature.c2574
-rw-r--r--source/blender/src/editconstraint.c753
-rw-r--r--source/blender/src/editcurve.c3979
-rw-r--r--source/blender/src/editdeform.c345
-rw-r--r--source/blender/src/editface.c1338
-rw-r--r--source/blender/src/editfont.c537
-rw-r--r--source/blender/src/editgroup.c251
-rw-r--r--source/blender/src/editika.c422
-rw-r--r--source/blender/src/editimasel.c383
-rw-r--r--source/blender/src/editipo.c5212
-rw-r--r--source/blender/src/editkey.c654
-rw-r--r--source/blender/src/editlattice.c318
-rw-r--r--source/blender/src/editmball.c301
-rw-r--r--source/blender/src/editmesh.c6387
-rw-r--r--source/blender/src/editnla.c1738
-rw-r--r--source/blender/src/editobject.c5944
-rw-r--r--source/blender/src/editoops.c595
-rw-r--r--source/blender/src/editsca.c2647
-rw-r--r--source/blender/src/editscreen.c2931
-rw-r--r--source/blender/src/editseq.c1855
-rw-r--r--source/blender/src/editsima.c905
-rw-r--r--source/blender/src/editsound.c1017
-rw-r--r--source/blender/src/editview.c1328
-rw-r--r--source/blender/src/eventdebug.c203
-rw-r--r--source/blender/src/filesel.c2376
-rw-r--r--source/blender/src/ghostwinlay.c572
-rw-r--r--source/blender/src/glutil.c411
-rw-r--r--source/blender/src/headerbuttons.c5577
-rw-r--r--source/blender/src/imasel.c900
-rw-r--r--source/blender/src/interface.c4105
-rw-r--r--source/blender/src/keyval.c354
-rw-r--r--source/blender/src/mainqueue.c99
-rw-r--r--source/blender/src/mywindow.c645
-rw-r--r--source/blender/src/oops.c1044
-rw-r--r--source/blender/src/osx_creator_splash.jpg.c971
-rw-r--r--source/blender/src/playanim.c711
-rw-r--r--source/blender/src/poseobject.c222
-rw-r--r--source/blender/src/previewrender.c1074
-rw-r--r--source/blender/src/pub/license_key.c451
-rw-r--r--source/blender/src/pub/osx_publisher_splash.jpg.c984
-rw-r--r--source/blender/src/pub/unix_publisher_splash.jpg.c950
-rw-r--r--source/blender/src/pub/windows_publisher_splash.jpg.c1002
-rw-r--r--source/blender/src/renderwin.c809
-rw-r--r--source/blender/src/resources.c304
-rw-r--r--source/blender/src/scrarea.c66
-rw-r--r--source/blender/src/screendump.c150
-rw-r--r--source/blender/src/sequence.c1647
-rw-r--r--source/blender/src/space.c2974
-rw-r--r--source/blender/src/spacetypes.c137
-rw-r--r--source/blender/src/swapbuffers.c280
-rw-r--r--source/blender/src/toets.c874
-rw-r--r--source/blender/src/toolbox.c1454
-rw-r--r--source/blender/src/unix_creator_splash.jpg.c939
-rw-r--r--source/blender/src/usiblender.c533
-rw-r--r--source/blender/src/view.c1095
-rw-r--r--source/blender/src/vpaint.c1169
-rw-r--r--source/blender/src/windows_creator_splash.jpg.c989
-rw-r--r--source/blender/src/winlay.h74
-rw-r--r--source/blender/src/writeavicodec.c799
-rw-r--r--source/blender/src/writeimage.c110
-rw-r--r--source/blender/src/writemovie.c514
-rw-r--r--source/blender/verify/BLO_sign_verify_Header.h77
-rw-r--r--source/blender/verify/BLO_signer_info.h47
-rw-r--r--source/blender/verify/BLO_verify.h78
-rw-r--r--source/blender/verify/Makefile37
-rw-r--r--source/blender/verify/intern/BLO_verify.c423
-rw-r--r--source/blender/verify/intern/Makefile57
-rw-r--r--source/blender/writeblenfile/BLO_writeblenfile.h60
-rw-r--r--source/blender/writeblenfile/Makefile37
-rw-r--r--source/blender/writeblenfile/intern/BLO_writeblenfile.c348
-rw-r--r--source/blender/writeblenfile/intern/Makefile58
-rw-r--r--source/blender/writeblenfile/test/Makefile54
-rw-r--r--source/blender/writeblenfile/test/test.c44
-rw-r--r--source/blender/writestreamglue/BLO_getPubKey.h40
-rw-r--r--source/blender/writestreamglue/BLO_writeStreamErrors.h85
-rw-r--r--source/blender/writestreamglue/BLO_writeStreamGlue.h90
-rw-r--r--source/blender/writestreamglue/Makefile38
-rw-r--r--source/blender/writestreamglue/intern/BLO_dumpFromMemory.c84
-rw-r--r--source/blender/writestreamglue/intern/BLO_dumpFromMemory.h39
-rw-r--r--source/blender/writestreamglue/intern/BLO_getPubKey.c72
-rw-r--r--source/blender/writestreamglue/intern/BLO_streamGlueControl.c90
-rw-r--r--source/blender/writestreamglue/intern/BLO_writeStreamGlue.c170
-rw-r--r--source/blender/writestreamglue/intern/Makefile71
-rw-r--r--source/blender/writestreamglue/stub/BLO_getPubKeySTUB.c51
-rw-r--r--source/blender/writestreamglue/stub/BLO_keyStoreSTUB.c58
-rw-r--r--source/blender/writestreamglue/stub/BLO_streamGlueControlSTUB.c87
-rw-r--r--source/blender/writestreamglue/stub/BLO_writeStreamGlueSTUB.c61
-rw-r--r--source/blender/writestreamglue/stub/Makefile58
-rw-r--r--source/blender/writestreamglue/test/Makefile37
-rw-r--r--source/blender/writestreamglue/test/readwritetest/Makefile83
-rw-r--r--source/blender/writestreamglue/test/readwritetest/readwritetest.c188
-rw-r--r--source/blender/writestreamglue/test/typetest/Makefile48
-rw-r--r--source/blender/writestreamglue/test/typetest/typetest.c94
-rw-r--r--source/creator/Makefile63
-rw-r--r--source/creator/buildinfo.c37
-rw-r--r--source/creator/creator.c515
-rw-r--r--source/darwin/Makefile47
-rw-r--r--source/darwin/blendercreator.app/Contents/Info.plist53
-rw-r--r--source/darwin/blendercreator.app/Contents/MacOS/blendercreator1
-rw-r--r--source/darwin/blendercreator.app/Contents/PkgInfo1
-rw-r--r--source/darwin/blendercreator.app/Contents/Resources/blender creator icon.icnsbin0 -> 33075 bytes
-rw-r--r--source/darwin/blendercreator.app/Contents/Resources/blender file icon.icnsbin0 -> 48147 bytes
-rw-r--r--source/darwin/blenderplayer.app/Contents/Info.plist47
-rw-r--r--source/darwin/blenderplayer.app/Contents/MacOS/blenderplayer1
-rw-r--r--source/darwin/blenderplayer.app/Contents/PkgInfo1
-rw-r--r--source/darwin/blenderplayer.app/Contents/Resources/blender file icon.icnsbin0 -> 48147 bytes
-rw-r--r--source/darwin/blenderplayer.app/Contents/Resources/blender player icon.icnsbin0 -> 33075 bytes
-rw-r--r--source/darwin/blenderpublisher.app/Contents/Info.plist53
-rw-r--r--source/darwin/blenderpublisher.app/Contents/MacOS/blenderpublisher1
-rw-r--r--source/darwin/blenderpublisher.app/Contents/PkgInfo1
-rw-r--r--source/darwin/blenderpublisher.app/Contents/Resources/blender file icon.icnsbin0 -> 48147 bytes
-rw-r--r--source/darwin/blenderpublisher.app/Contents/Resources/blender publisher icon.icnsbin0 -> 35306 bytes
-rw-r--r--source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp374
-rw-r--r--source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp164
-rw-r--r--source/gameengine/BlenderRoutines/KX_BlenderCanvas.h165
-rw-r--r--source/gameengine/BlenderRoutines/KX_BlenderGL.cpp259
-rw-r--r--source/gameengine/BlenderRoutines/KX_BlenderGL.h66
-rw-r--r--source/gameengine/BlenderRoutines/KX_BlenderInputDevice.cpp32
-rw-r--r--source/gameengine/BlenderRoutines/KX_BlenderInputDevice.h220
-rw-r--r--source/gameengine/BlenderRoutines/KX_BlenderKeyboardDevice.cpp161
-rw-r--r--source/gameengine/BlenderRoutines/KX_BlenderKeyboardDevice.h48
-rw-r--r--source/gameengine/BlenderRoutines/KX_BlenderMouseDevice.cpp177
-rw-r--r--source/gameengine/BlenderRoutines/KX_BlenderMouseDevice.h48
-rw-r--r--source/gameengine/BlenderRoutines/KX_BlenderPolyMaterial.cpp106
-rw-r--r--source/gameengine/BlenderRoutines/KX_BlenderPolyMaterial.h98
-rw-r--r--source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp411
-rw-r--r--source/gameengine/BlenderRoutines/KX_BlenderRenderTools.h100
-rw-r--r--source/gameengine/BlenderRoutines/KX_BlenderSystem.cpp56
-rw-r--r--source/gameengine/BlenderRoutines/KX_BlenderSystem.h51
-rw-r--r--source/gameengine/BlenderRoutines/Makefile75
-rw-r--r--source/gameengine/Converter/BL_ActionActuator.cpp805
-rw-r--r--source/gameengine/Converter/BL_ActionActuator.h126
-rw-r--r--source/gameengine/Converter/BL_ArmatureObject.cpp149
-rw-r--r--source/gameengine/Converter/BL_ArmatureObject.h79
-rw-r--r--source/gameengine/Converter/BL_BlenderDataConversion.cpp1227
-rw-r--r--source/gameengine/Converter/BL_BlenderDataConversion.h54
-rw-r--r--source/gameengine/Converter/BL_DeformableGameObject.cpp62
-rw-r--r--source/gameengine/Converter/BL_DeformableGameObject.h66
-rw-r--r--source/gameengine/Converter/BL_MeshDeformer.cpp165
-rw-r--r--source/gameengine/Converter/BL_MeshDeformer.h72
-rw-r--r--source/gameengine/Converter/BL_SkinDeformer.cpp187
-rw-r--r--source/gameengine/Converter/BL_SkinDeformer.h98
-rw-r--r--source/gameengine/Converter/BL_SkinMeshObject.cpp152
-rw-r--r--source/gameengine/Converter/BL_SkinMeshObject.h184
-rw-r--r--source/gameengine/Converter/BlenderWorldInfo.cpp215
-rw-r--r--source/gameengine/Converter/BlenderWorldInfo.h95
-rw-r--r--source/gameengine/Converter/KX_BlenderScalarInterpolator.cpp81
-rw-r--r--source/gameengine/Converter/KX_BlenderScalarInterpolator.h70
-rw-r--r--source/gameengine/Converter/KX_BlenderSceneConverter.cpp416
-rw-r--r--source/gameengine/Converter/KX_BlenderSceneConverter.h120
-rw-r--r--source/gameengine/Converter/KX_ConvertActuators.cpp909
-rw-r--r--source/gameengine/Converter/KX_ConvertActuators.h48
-rw-r--r--source/gameengine/Converter/KX_ConvertControllers.cpp179
-rw-r--r--source/gameengine/Converter/KX_ConvertControllers.h51
-rw-r--r--source/gameengine/Converter/KX_ConvertProperties.cpp134
-rw-r--r--source/gameengine/Converter/KX_ConvertProperties.h41
-rw-r--r--source/gameengine/Converter/KX_ConvertSensors.cpp658
-rw-r--r--source/gameengine/Converter/KX_ConvertSensors.h47
-rw-r--r--source/gameengine/Converter/KX_IpoConvert.cpp559
-rw-r--r--source/gameengine/Converter/KX_IpoConvert.h54
-rw-r--r--source/gameengine/Converter/Makefile60
-rw-r--r--source/gameengine/Expressions/BoolValue.cpp213
-rw-r--r--source/gameengine/Expressions/BoolValue.h51
-rw-r--r--source/gameengine/Expressions/ConstExpr.cpp132
-rw-r--r--source/gameengine/Expressions/ConstExpr.h46
-rw-r--r--source/gameengine/Expressions/EXP_C-Api.cpp124
-rw-r--r--source/gameengine/Expressions/EXP_C-Api.h68
-rw-r--r--source/gameengine/Expressions/EmptyValue.cpp127
-rw-r--r--source/gameengine/Expressions/EmptyValue.h39
-rw-r--r--source/gameengine/Expressions/ErrorValue.cpp125
-rw-r--r--source/gameengine/Expressions/ErrorValue.h38
-rw-r--r--source/gameengine/Expressions/Expression.cpp75
-rw-r--r--source/gameengine/Expressions/Expression.h133
-rw-r--r--source/gameengine/Expressions/FloatValue.cpp316
-rw-r--r--source/gameengine/Expressions/FloatValue.h48
-rw-r--r--source/gameengine/Expressions/IdentifierExpr.cpp103
-rw-r--r--source/gameengine/Expressions/IdentifierExpr.h55
-rw-r--r--source/gameengine/Expressions/IfExpr.cpp141
-rw-r--r--source/gameengine/Expressions/IfExpr.h49
-rw-r--r--source/gameengine/Expressions/InputParser.cpp648
-rw-r--r--source/gameengine/Expressions/InputParser.h105
-rw-r--r--source/gameengine/Expressions/IntValue.cpp325
-rw-r--r--source/gameengine/Expressions/IntValue.h60
-rw-r--r--source/gameengine/Expressions/KX_HashedPtr.cpp58
-rw-r--r--source/gameengine/Expressions/KX_HashedPtr.h53
-rw-r--r--source/gameengine/Expressions/ListValue.cpp536
-rw-r--r--source/gameengine/Expressions/ListValue.h77
-rw-r--r--source/gameengine/Expressions/Makefile45
-rw-r--r--source/gameengine/Expressions/Operator1Expr.cpp148
-rw-r--r--source/gameengine/Expressions/Operator1Expr.h53
-rw-r--r--source/gameengine/Expressions/Operator2Expr.cpp275
-rw-r--r--source/gameengine/Expressions/Operator2Expr.h59
-rw-r--r--source/gameengine/Expressions/PyObjectPlus.cpp157
-rw-r--r--source/gameengine/Expressions/PyObjectPlus.h135
-rw-r--r--source/gameengine/Expressions/StringValue.cpp139
-rw-r--r--source/gameengine/Expressions/StringValue.h51
-rw-r--r--source/gameengine/Expressions/Value.cpp767
-rw-r--r--source/gameengine/Expressions/Value.h467
-rw-r--r--source/gameengine/Expressions/VectorValue.cpp213
-rw-r--r--source/gameengine/Expressions/VectorValue.h86
-rw-r--r--source/gameengine/Expressions/VoidValue.h68
-rw-r--r--source/gameengine/GameLogic/Makefile47
-rw-r--r--source/gameengine/GameLogic/SCA_ANDController.cpp143
-rw-r--r--source/gameengine/GameLogic/SCA_ANDController.h58
-rw-r--r--source/gameengine/GameLogic/SCA_AlwaysEventManager.cpp67
-rw-r--r--source/gameengine/GameLogic/SCA_AlwaysEventManager.h48
-rw-r--r--source/gameengine/GameLogic/SCA_AlwaysSensor.cpp138
-rw-r--r--source/gameengine/GameLogic/SCA_AlwaysSensor.h62
-rw-r--r--source/gameengine/GameLogic/SCA_EventManager.cpp71
-rw-r--r--source/gameengine/GameLogic/SCA_EventManager.h69
-rw-r--r--source/gameengine/GameLogic/SCA_ExpressionController.cpp161
-rw-r--r--source/gameengine/GameLogic/SCA_ExpressionController.h64
-rw-r--r--source/gameengine/GameLogic/SCA_IActuator.cpp104
-rw-r--r--source/gameengine/GameLogic/SCA_IActuator.h81
-rw-r--r--source/gameengine/GameLogic/SCA_IController.cpp120
-rw-r--r--source/gameengine/GameLogic/SCA_IController.h56
-rw-r--r--source/gameengine/GameLogic/SCA_IInputDevice.cpp138
-rw-r--r--source/gameengine/GameLogic/SCA_IInputDevice.h307
-rw-r--r--source/gameengine/GameLogic/SCA_ILogicBrick.cpp325
-rw-r--r--source/gameengine/GameLogic/SCA_ILogicBrick.h111
-rw-r--r--source/gameengine/GameLogic/SCA_IObject.cpp363
-rw-r--r--source/gameengine/GameLogic/SCA_IObject.h126
-rw-r--r--source/gameengine/GameLogic/SCA_IScene.cpp67
-rw-r--r--source/gameengine/GameLogic/SCA_IScene.h62
-rw-r--r--source/gameengine/GameLogic/SCA_ISensor.cpp328
-rw-r--r--source/gameengine/GameLogic/SCA_ISensor.h130
-rw-r--r--source/gameengine/GameLogic/SCA_KeyboardManager.cpp91
-rw-r--r--source/gameengine/GameLogic/SCA_KeyboardManager.h66
-rw-r--r--source/gameengine/GameLogic/SCA_KeyboardSensor.cpp675
-rw-r--r--source/gameengine/GameLogic/SCA_KeyboardSensor.h158
-rw-r--r--source/gameengine/GameLogic/SCA_LogicManager.cpp461
-rw-r--r--source/gameengine/GameLogic/SCA_LogicManager.h154
-rw-r--r--source/gameengine/GameLogic/SCA_MouseManager.cpp116
-rw-r--r--source/gameengine/GameLogic/SCA_MouseManager.h72
-rw-r--r--source/gameengine/GameLogic/SCA_MouseSensor.cpp273
-rw-r--r--source/gameengine/GameLogic/SCA_MouseSensor.h120
-rw-r--r--source/gameengine/GameLogic/SCA_ORController.cpp135
-rw-r--r--source/gameengine/GameLogic/SCA_ORController.h58
-rw-r--r--source/gameengine/GameLogic/SCA_PropertyActuator.cpp285
-rw-r--r--source/gameengine/GameLogic/SCA_PropertyActuator.h116
-rw-r--r--source/gameengine/GameLogic/SCA_PropertyEventManager.cpp67
-rw-r--r--source/gameengine/GameLogic/SCA_PropertyEventManager.h52
-rw-r--r--source/gameengine/GameLogic/SCA_PropertySensor.cpp420
-rw-r--r--source/gameengine/GameLogic/SCA_PropertySensor.h109
-rw-r--r--source/gameengine/GameLogic/SCA_PythonController.cpp400
-rw-r--r--source/gameengine/GameLogic/SCA_PythonController.h88
-rw-r--r--source/gameengine/GameLogic/SCA_RandomActuator.cpp630
-rw-r--r--source/gameengine/GameLogic/SCA_RandomActuator.h144
-rw-r--r--source/gameengine/GameLogic/SCA_RandomEventManager.cpp64
-rw-r--r--source/gameengine/GameLogic/SCA_RandomEventManager.h53
-rw-r--r--source/gameengine/GameLogic/SCA_RandomNumberGenerator.cpp125
-rw-r--r--source/gameengine/GameLogic/SCA_RandomNumberGenerator.h65
-rw-r--r--source/gameengine/GameLogic/SCA_RandomSensor.cpp191
-rw-r--r--source/gameengine/GameLogic/SCA_RandomSensor.h75
-rw-r--r--source/gameengine/GameLogic/SCA_TimeEventManager.cpp110
-rw-r--r--source/gameengine/GameLogic/SCA_TimeEventManager.h54
-rw-r--r--source/gameengine/GamePlayer/Makefile56
-rw-r--r--source/gameengine/GamePlayer/common/GPC_Canvas.cpp371
-rw-r--r--source/gameengine/GamePlayer/common/GPC_Canvas.h275
-rw-r--r--source/gameengine/GamePlayer/common/GPC_Engine.cpp337
-rw-r--r--source/gameengine/GamePlayer/common/GPC_Engine.h130
-rw-r--r--source/gameengine/GamePlayer/common/GPC_KeyboardDevice.cpp124
-rw-r--r--source/gameengine/GamePlayer/common/GPC_KeyboardDevice.h87
-rw-r--r--source/gameengine/GamePlayer/common/GPC_MouseDevice.cpp207
-rw-r--r--source/gameengine/GamePlayer/common/GPC_MouseDevice.h105
-rw-r--r--source/gameengine/GamePlayer/common/GPC_PolygonMaterial.cpp410
-rw-r--r--source/gameengine/GamePlayer/common/GPC_PolygonMaterial.h87
-rw-r--r--source/gameengine/GamePlayer/common/GPC_RawImage.cpp135
-rw-r--r--source/gameengine/GamePlayer/common/GPC_RawImage.h122
-rw-r--r--source/gameengine/GamePlayer/common/GPC_RawLoadDotBlendArray.cpp9312
-rw-r--r--source/gameengine/GamePlayer/common/GPC_RawLoadDotBlendArray.h40
-rw-r--r--source/gameengine/GamePlayer/common/GPC_RawLogoArrays.cpp1462
-rw-r--r--source/gameengine/GamePlayer/common/GPC_RawLogoArrays.h44
-rw-r--r--source/gameengine/GamePlayer/common/GPC_RenderTools.cpp498
-rw-r--r--source/gameengine/GamePlayer/common/GPC_RenderTools.h176
-rw-r--r--source/gameengine/GamePlayer/common/GPC_System.cpp90
-rw-r--r--source/gameengine/GamePlayer/common/GPC_System.h64
-rw-r--r--source/gameengine/GamePlayer/common/Makefile83
-rw-r--r--source/gameengine/GamePlayer/common/bmfont.cpp301
-rw-r--r--source/gameengine/GamePlayer/common/load.blendbin0 -> 135908 bytes
-rw-r--r--source/gameengine/GamePlayer/common/logo_blender.rawbin0 -> 14720 bytes
-rw-r--r--source/gameengine/GamePlayer/common/logo_blender3d.rawbin0 -> 5984 bytes
-rw-r--r--source/gameengine/GamePlayer/common/logo_nan.rawbin0 -> 3968 bytes
-rw-r--r--source/gameengine/GamePlayer/common/unix/GPU_Canvas.cpp72
-rw-r--r--source/gameengine/GamePlayer/common/unix/GPU_Canvas.h60
-rw-r--r--source/gameengine/GamePlayer/common/unix/GPU_Engine.cpp307
-rw-r--r--source/gameengine/GamePlayer/common/unix/GPU_Engine.h65
-rw-r--r--source/gameengine/GamePlayer/common/unix/GPU_KeyboardDevice.cpp137
-rw-r--r--source/gameengine/GamePlayer/common/unix/GPU_KeyboardDevice.h64
-rw-r--r--source/gameengine/GamePlayer/common/unix/GPU_PolygonMaterial.h57
-rw-r--r--source/gameengine/GamePlayer/common/unix/GPU_System.cpp56
-rw-r--r--source/gameengine/GamePlayer/common/unix/GPU_System.h51
-rw-r--r--source/gameengine/GamePlayer/common/unix/Makefile81
-rw-r--r--source/gameengine/GamePlayer/common/windows/GPW_Canvas.cpp174
-rw-r--r--source/gameengine/GamePlayer/common/windows/GPW_Canvas.h119
-rw-r--r--source/gameengine/GamePlayer/common/windows/GPW_Engine.cpp120
-rw-r--r--source/gameengine/GamePlayer/common/windows/GPW_Engine.h50
-rw-r--r--source/gameengine/GamePlayer/common/windows/GPW_KeyboardDevice.cpp280
-rw-r--r--source/gameengine/GamePlayer/common/windows/GPW_KeyboardDevice.h69
-rw-r--r--source/gameengine/GamePlayer/common/windows/GPW_System.cpp93
-rw-r--r--source/gameengine/GamePlayer/common/windows/GPW_System.h62
-rw-r--r--source/gameengine/GamePlayer/common/windows/Makefile66
-rw-r--r--source/gameengine/GamePlayer/ghost/GPG_Application.cpp607
-rw-r--r--source/gameengine/GamePlayer/ghost/GPG_Application.h138
-rw-r--r--source/gameengine/GamePlayer/ghost/GPG_Canvas.cpp110
-rw-r--r--source/gameengine/GamePlayer/ghost/GPG_Canvas.h64
-rw-r--r--source/gameengine/GamePlayer/ghost/GPG_KeyboardDevice.cpp156
-rw-r--r--source/gameengine/GamePlayer/ghost/GPG_KeyboardDevice.h57
-rw-r--r--source/gameengine/GamePlayer/ghost/GPG_System.cpp56
-rw-r--r--source/gameengine/GamePlayer/ghost/GPG_System.h56
-rw-r--r--source/gameengine/GamePlayer/ghost/GPG_ghost.cpp597
-rw-r--r--source/gameengine/GamePlayer/ghost/Makefile82
-rw-r--r--source/gameengine/Ketsji/KXNetwork/KX_NetworkEventManager.cpp92
-rw-r--r--source/gameengine/Ketsji/KXNetwork/KX_NetworkEventManager.h59
-rw-r--r--source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.cpp208
-rw-r--r--source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.h77
-rw-r--r--source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp258
-rw-r--r--source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h85
-rw-r--r--source/gameengine/Ketsji/KXNetwork/KX_NetworkObjectActuator.cpp31
-rw-r--r--source/gameengine/Ketsji/KXNetwork/KX_NetworkObjectActuator.h31
-rw-r--r--source/gameengine/Ketsji/KXNetwork/KX_NetworkObjectSensor.cpp31
-rw-r--r--source/gameengine/Ketsji/KXNetwork/KX_NetworkObjectSensor.h31
-rw-r--r--source/gameengine/Ketsji/KXNetwork/Makefile48
-rw-r--r--source/gameengine/Ketsji/KX_CDActuator.cpp252
-rw-r--r--source/gameengine/Ketsji/KX_CDActuator.h97
-rw-r--r--source/gameengine/Ketsji/KX_Camera.cpp181
-rw-r--r--source/gameengine/Ketsji/KX_Camera.h114
-rw-r--r--source/gameengine/Ketsji/KX_CameraActuator.cpp368
-rw-r--r--source/gameengine/Ketsji/KX_CameraActuator.h128
-rw-r--r--source/gameengine/Ketsji/KX_CameraIpoSGController.cpp125
-rw-r--r--source/gameengine/Ketsji/KX_CameraIpoSGController.h91
-rw-r--r--source/gameengine/Ketsji/KX_ClientObjectInfo.h46
-rw-r--r--source/gameengine/Ketsji/KX_ConstraintActuator.cpp369
-rw-r--r--source/gameengine/Ketsji/KX_ConstraintActuator.h109
-rw-r--r--source/gameengine/Ketsji/KX_ConstraintWrapper.cpp131
-rw-r--r--source/gameengine/Ketsji/KX_ConstraintWrapper.h57
-rw-r--r--source/gameengine/Ketsji/KX_ConvertPhysicsObject.h110
-rw-r--r--source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp427
-rw-r--r--source/gameengine/Ketsji/KX_EmptyObject.cpp32
-rw-r--r--source/gameengine/Ketsji/KX_EmptyObject.h45
-rw-r--r--source/gameengine/Ketsji/KX_GameActuator.cpp186
-rw-r--r--source/gameengine/Ketsji/KX_GameActuator.h86
-rw-r--r--source/gameengine/Ketsji/KX_GameObject.cpp1096
-rw-r--r--source/gameengine/Ketsji/KX_GameObject.h614
-rw-r--r--source/gameengine/Ketsji/KX_IInterpolator.h46
-rw-r--r--source/gameengine/Ketsji/KX_IPOTransform.h92
-rw-r--r--source/gameengine/Ketsji/KX_IPO_SGController.cpp193
-rw-r--r--source/gameengine/Ketsji/KX_IPO_SGController.h111
-rw-r--r--source/gameengine/Ketsji/KX_IPhysicsController.cpp45
-rw-r--r--source/gameengine/Ketsji/KX_IPhysicsController.h99
-rw-r--r--source/gameengine/Ketsji/KX_IScalarInterpolator.h42
-rw-r--r--source/gameengine/Ketsji/KX_ISceneConverter.h64
-rw-r--r--source/gameengine/Ketsji/KX_ISystem.h55
-rw-r--r--source/gameengine/Ketsji/KX_IpoActuator.cpp643
-rw-r--r--source/gameengine/Ketsji/KX_IpoActuator.h141
-rw-r--r--source/gameengine/Ketsji/KX_KetsjiEngine.cpp1250
-rw-r--r--source/gameengine/Ketsji/KX_KetsjiEngine.h316
-rw-r--r--source/gameengine/Ketsji/KX_Light.cpp75
-rw-r--r--source/gameengine/Ketsji/KX_Light.h50
-rw-r--r--source/gameengine/Ketsji/KX_LightIpoSGController.cpp118
-rw-r--r--source/gameengine/Ketsji/KX_LightIpoSGController.h99
-rw-r--r--source/gameengine/Ketsji/KX_MeshProxy.cpp193
-rw-r--r--source/gameengine/Ketsji/KX_MeshProxy.h66
-rw-r--r--source/gameengine/Ketsji/KX_MotionState.cpp91
-rw-r--r--source/gameengine/Ketsji/KX_MotionState.h54
-rw-r--r--source/gameengine/Ketsji/KX_MouseFocusSensor.cpp353
-rw-r--r--source/gameengine/Ketsji/KX_MouseFocusSensor.h152
-rw-r--r--source/gameengine/Ketsji/KX_NearSensor.cpp262
-rw-r--r--source/gameengine/Ketsji/KX_NearSensor.h61
-rw-r--r--source/gameengine/Ketsji/KX_ObColorIpoSGController.cpp107
-rw-r--r--source/gameengine/Ketsji/KX_ObColorIpoSGController.h77
-rw-r--r--source/gameengine/Ketsji/KX_ObjectActuator.cpp400
-rw-r--r--source/gameengine/Ketsji/KX_ObjectActuator.h140
-rw-r--r--source/gameengine/Ketsji/KX_OrientationInterpolator.cpp56
-rw-r--r--source/gameengine/Ketsji/KX_OrientationInterpolator.h58
-rw-r--r--source/gameengine/Ketsji/KX_PhysicsEngineEnums.h44
-rw-r--r--source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp161
-rw-r--r--source/gameengine/Ketsji/KX_PhysicsObjectWrapper.h58
-rw-r--r--source/gameengine/Ketsji/KX_PhysicsPropertiesobsolete.h60
-rw-r--r--source/gameengine/Ketsji/KX_PositionInterpolator.cpp42
-rw-r--r--source/gameengine/Ketsji/KX_PositionInterpolator.h58
-rw-r--r--source/gameengine/Ketsji/KX_PyConstraintBinding.cpp193
-rw-r--r--source/gameengine/Ketsji/KX_PyConstraintBinding.h43
-rw-r--r--source/gameengine/Ketsji/KX_Python.h38
-rw-r--r--source/gameengine/Ketsji/KX_PythonInit.cpp832
-rw-r--r--source/gameengine/Ketsji/KX_PythonInit.h55
-rw-r--r--source/gameengine/Ketsji/KX_Python_dynamic.h38
-rw-r--r--source/gameengine/Ketsji/KX_Python_static.h38
-rw-r--r--source/gameengine/Ketsji/KX_RadarSensor.cpp220
-rw-r--r--source/gameengine/Ketsji/KX_RadarSensor.h93
-rw-r--r--source/gameengine/Ketsji/KX_RayEventManager.cpp55
-rw-r--r--source/gameengine/Ketsji/KX_RayEventManager.h52
-rw-r--r--source/gameengine/Ketsji/KX_RaySensor.cpp381
-rw-r--r--source/gameengine/Ketsji/KX_RaySensor.h79
-rw-r--r--source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp335
-rw-r--r--source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h133
-rw-r--r--source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp137
-rw-r--r--source/gameengine/Ketsji/KX_SCA_EndObjectActuator.h80
-rw-r--r--source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp182
-rw-r--r--source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h88
-rw-r--r--source/gameengine/Ketsji/KX_SG_NodeRelationships.cpp328
-rw-r--r--source/gameengine/Ketsji/KX_SG_NodeRelationships.h214
-rw-r--r--source/gameengine/Ketsji/KX_ScalarInterpolator.cpp38
-rw-r--r--source/gameengine/Ketsji/KX_ScalarInterpolator.h63
-rw-r--r--source/gameengine/Ketsji/KX_ScalingInterpolator.cpp42
-rw-r--r--source/gameengine/Ketsji/KX_ScalingInterpolator.h61
-rw-r--r--source/gameengine/Ketsji/KX_Scene.cpp977
-rw-r--r--source/gameengine/Ketsji/KX_Scene.h480
-rw-r--r--source/gameengine/Ketsji/KX_SceneActuator.cpp354
-rw-r--r--source/gameengine/Ketsji/KX_SceneActuator.h115
-rw-r--r--source/gameengine/Ketsji/KX_SoundActuator.cpp466
-rw-r--r--source/gameengine/Ketsji/KX_SoundActuator.h106
-rw-r--r--source/gameengine/Ketsji/KX_SumoPhysicsController.cpp204
-rw-r--r--source/gameengine/Ketsji/KX_SumoPhysicsController.h81
-rw-r--r--source/gameengine/Ketsji/KX_TimeCategoryLogger.cpp142
-rw-r--r--source/gameengine/Ketsji/KX_TimeCategoryLogger.h133
-rw-r--r--source/gameengine/Ketsji/KX_TimeLogger.cpp117
-rw-r--r--source/gameengine/Ketsji/KX_TimeLogger.h107
-rw-r--r--source/gameengine/Ketsji/KX_TouchEventManager.cpp117
-rw-r--r--source/gameengine/Ketsji/KX_TouchEventManager.h67
-rw-r--r--source/gameengine/Ketsji/KX_TouchSensor.cpp393
-rw-r--r--source/gameengine/Ketsji/KX_TouchSensor.h146
-rw-r--r--source/gameengine/Ketsji/KX_TrackToActuator.cpp487
-rw-r--r--source/gameengine/Ketsji/KX_TrackToActuator.h85
-rw-r--r--source/gameengine/Ketsji/KX_VertexProxy.cpp217
-rw-r--r--source/gameengine/Ketsji/KX_VertexProxy.h70
-rw-r--r--source/gameengine/Ketsji/KX_VisibilityActuator.cpp161
-rw-r--r--source/gameengine/Ketsji/KX_VisibilityActuator.h80
-rw-r--r--source/gameengine/Ketsji/KX_WorldInfo.cpp38
-rw-r--r--source/gameengine/Ketsji/KX_WorldInfo.h65
-rw-r--r--source/gameengine/Ketsji/KX_WorldIpoController.cpp111
-rw-r--r--source/gameengine/Ketsji/KX_WorldIpoController.h99
-rw-r--r--source/gameengine/Ketsji/Makefile60
-rw-r--r--source/gameengine/Makefile43
-rw-r--r--source/gameengine/Network/LoopBackNetwork/Makefile44
-rw-r--r--source/gameengine/Network/LoopBackNetwork/NG_LoopBackNetworkDeviceInterface.cpp110
-rw-r--r--source/gameengine/Network/LoopBackNetwork/NG_LoopBackNetworkDeviceInterface.h68
-rw-r--r--source/gameengine/Network/Makefile50
-rw-r--r--source/gameengine/Network/NG_NetworkDeviceInterface.h85
-rw-r--r--source/gameengine/Network/NG_NetworkMessage.cpp55
-rw-r--r--source/gameengine/Network/NG_NetworkMessage.h130
-rw-r--r--source/gameengine/Network/NG_NetworkObject.cpp46
-rw-r--r--source/gameengine/Network/NG_NetworkObject.h47
-rw-r--r--source/gameengine/Network/NG_NetworkScene.cpp271
-rw-r--r--source/gameengine/Network/NG_NetworkScene.h102
-rw-r--r--source/gameengine/Network/TerraplayNetwork/Makefile45
-rw-r--r--source/gameengine/Network/TerraplayNetwork/NG_TerraplayNetworkDeviceInterface.cpp192
-rw-r--r--source/gameengine/Network/TerraplayNetwork/NG_TerraplayNetworkDeviceInterface.h70
-rw-r--r--source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp91
-rw-r--r--source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h70
-rw-r--r--source/gameengine/Physics/Dummy/Makefile47
-rw-r--r--source/gameengine/Physics/Makefile40
-rw-r--r--source/gameengine/Physics/Sumo/Fuzzics/Makefile9
-rw-r--r--source/gameengine/Physics/Sumo/Fuzzics/include/SM_Callback.h10
-rw-r--r--source/gameengine/Physics/Sumo/Fuzzics/include/SM_ClientObjectInfo.h15
-rw-r--r--source/gameengine/Physics/Sumo/Fuzzics/include/SM_FhObject.h36
-rw-r--r--source/gameengine/Physics/Sumo/Fuzzics/include/SM_MotionState.h36
-rw-r--r--source/gameengine/Physics/Sumo/Fuzzics/include/SM_Object.h280
-rw-r--r--source/gameengine/Physics/Sumo/Fuzzics/include/SM_Props.h60
-rw-r--r--source/gameengine/Physics/Sumo/Fuzzics/include/SM_Scene.h129
-rw-r--r--source/gameengine/Physics/Sumo/Fuzzics/sample/Makefile25
-rw-r--r--source/gameengine/Physics/Sumo/Fuzzics/sample/particle.cpp705
-rw-r--r--source/gameengine/Physics/Sumo/Fuzzics/sample/particle0.cpp691
-rw-r--r--source/gameengine/Physics/Sumo/Fuzzics/src/Makefile13
-rw-r--r--source/gameengine/Physics/Sumo/Fuzzics/src/SM_FhObject.cpp115
-rw-r--r--source/gameengine/Physics/Sumo/Fuzzics/src/SM_Object.cpp953
-rw-r--r--source/gameengine/Physics/Sumo/Fuzzics/src/SM_Scene.cpp179
-rw-r--r--source/gameengine/Physics/Sumo/Makefile47
-rw-r--r--source/gameengine/Physics/Sumo/SumoPhysicsController.cpp462
-rw-r--r--source/gameengine/Physics/Sumo/SumoPhysicsController.h171
-rw-r--r--source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.cpp103
-rw-r--r--source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h88
-rw-r--r--source/gameengine/Physics/Sumo/convert.txt35
-rw-r--r--source/gameengine/Physics/Sumo/include/interpolator.h27
-rw-r--r--source/gameengine/Physics/Sumo/include/solid.h195
-rw-r--r--source/gameengine/Physics/Sumo/include/solid_broadphase.h38
-rw-r--r--source/gameengine/Physics/Sumo/include/solid_types.h14
-rw-r--r--source/gameengine/Physics/common/Makefile59
-rw-r--r--source/gameengine/Physics/common/PHY_DynamicTypes.h68
-rw-r--r--source/gameengine/Physics/common/PHY_IMotionState.cpp37
-rw-r--r--source/gameengine/Physics/common/PHY_IMotionState.h57
-rw-r--r--source/gameengine/Physics/common/PHY_IPhysicsController.cpp39
-rw-r--r--source/gameengine/Physics/common/PHY_IPhysicsController.h89
-rw-r--r--source/gameengine/Physics/common/PHY_IPhysicsEnvironment.cpp45
-rw-r--r--source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h60
-rw-r--r--source/gameengine/Physics/common/PHY_Pro.h60
-rw-r--r--source/gameengine/Rasterizer/Makefile51
-rw-r--r--source/gameengine/Rasterizer/RAS_BucketManager.cpp156
-rw-r--r--source/gameengine/Rasterizer/RAS_BucketManager.h63
-rw-r--r--source/gameengine/Rasterizer/RAS_CameraData.h42
-rw-r--r--source/gameengine/Rasterizer/RAS_Deformer.h56
-rw-r--r--source/gameengine/Rasterizer/RAS_FramingManager.cpp234
-rw-r--r--source/gameengine/Rasterizer/RAS_FramingManager.h255
-rw-r--r--source/gameengine/Rasterizer/RAS_ICanvas.h172
-rw-r--r--source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp125
-rw-r--r--source/gameengine/Rasterizer/RAS_IPolygonMaterial.h123
-rw-r--r--source/gameengine/Rasterizer/RAS_IRasterizer.h191
-rw-r--r--source/gameengine/Rasterizer/RAS_IRenderTools.cpp76
-rw-r--r--source/gameengine/Rasterizer/RAS_IRenderTools.h196
-rw-r--r--source/gameengine/Rasterizer/RAS_LightObject.h63
-rw-r--r--source/gameengine/Rasterizer/RAS_MaterialBucket.cpp248
-rw-r--r--source/gameengine/Rasterizer/RAS_MaterialBucket.h126
-rw-r--r--source/gameengine/Rasterizer/RAS_MeshObject.cpp635
-rw-r--r--source/gameengine/Rasterizer/RAS_MeshObject.h230
-rw-r--r--source/gameengine/Rasterizer/RAS_ObjectColor.h41
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/Makefile47
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_CheckVertexArrays.cpp61
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_CheckVertexArrays.h37
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp1226
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h226
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.cpp215
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.h62
-rw-r--r--source/gameengine/Rasterizer/RAS_Polygon.cpp142
-rw-r--r--source/gameengine/Rasterizer/RAS_Polygon.h92
-rw-r--r--source/gameengine/Rasterizer/RAS_Rect.h99
-rw-r--r--source/gameengine/Rasterizer/RAS_TexMatrix.h45
-rw-r--r--source/gameengine/Rasterizer/RAS_TexVert.cpp152
-rw-r--r--source/gameengine/Rasterizer/RAS_TexVert.h98
-rw-r--r--source/gameengine/Rasterizer/RAS_texmatrix.cpp133
-rw-r--r--source/gameengine/SceneGraph/Makefile41
-rw-r--r--source/gameengine/SceneGraph/SG_Controller.cpp49
-rw-r--r--source/gameengine/SceneGraph/SG_Controller.h116
-rw-r--r--source/gameengine/SceneGraph/SG_IObject.cpp153
-rw-r--r--source/gameengine/SceneGraph/SG_IObject.h220
-rw-r--r--source/gameengine/SceneGraph/SG_Node.cpp231
-rw-r--r--source/gameengine/SceneGraph/SG_Node.h208
-rw-r--r--source/gameengine/SceneGraph/SG_ParentRelation.h116
-rw-r--r--source/gameengine/SceneGraph/SG_Spatial.cpp283
-rw-r--r--source/gameengine/SceneGraph/SG_Spatial.h205
-rw-r--r--source/icons/Makefile39
-rw-r--r--source/icons/winblender.icobin0 -> 4710 bytes
-rw-r--r--source/icons/winblender.rc2
-rw-r--r--source/icons/winblenderfile.icobin0 -> 4710 bytes
-rw-r--r--source/icons/wincreator.icobin0 -> 4710 bytes
-rw-r--r--source/icons/wincreator.rc2
-rw-r--r--source/icons/winlockedfile.icobin0 -> 4710 bytes
-rw-r--r--source/icons/winplayer.icobin0 -> 4710 bytes
-rw-r--r--source/icons/winplayer.rc1
-rw-r--r--source/icons/winpublisher.icobin0 -> 4710 bytes
-rw-r--r--source/icons/winpublisher.rc3
-rw-r--r--source/kernel/Makefile40
-rw-r--r--source/kernel/gen_messaging/GEN_messaging.h62
-rw-r--r--source/kernel/gen_messaging/Makefile37
-rw-r--r--source/kernel/gen_messaging/intern/Makefile47
-rw-r--r--source/kernel/gen_messaging/intern/messaging.c45
-rw-r--r--source/kernel/gen_system/GEN_DataCache.h78
-rw-r--r--source/kernel/gen_system/GEN_HashedPtr.cpp47
-rw-r--r--source/kernel/gen_system/GEN_HashedPtr.h47
-rw-r--r--source/kernel/gen_system/GEN_Map.h151
-rw-r--r--source/kernel/gen_system/GEN_Matrix4x4.cpp207
-rw-r--r--source/kernel/gen_system/GEN_Matrix4x4.h78
-rw-r--r--source/kernel/gen_system/GEN_SmartPtr.h235
-rw-r--r--source/kernel/gen_system/Makefile43
-rw-r--r--source/kernel/gen_system/SYS_SingletonSystem.cpp99
-rw-r--r--source/kernel/gen_system/SYS_SingletonSystem.h65
-rw-r--r--source/kernel/gen_system/SYS_System.cpp77
-rw-r--r--source/kernel/gen_system/SYS_System.h70
-rw-r--r--source/nan_compile.mk337
-rw-r--r--source/nan_definitions.mk131
-rw-r--r--source/nan_link.mk138
-rw-r--r--source/nan_subdirs.mk63
-rw-r--r--source/nan_warn.mk174
1699 files changed, 444708 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>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/projectfiles/blender/BLO_decrypt/BLO_decrypt.dsp b/projectfiles/blender/BLO_decrypt/BLO_decrypt.dsp
new file mode 100644
index 00000000000..b8457b1f755
--- /dev/null
+++ b/projectfiles/blender/BLO_decrypt/BLO_decrypt.dsp
@@ -0,0 +1,178 @@
+# Microsoft Developer Studio Project File - Name="BLO_decrypt" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=BLO_decrypt - Win32 Profile
+!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 "BLO_decrypt.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 "BLO_decrypt.mak" CFG="BLO_decrypt - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "BLO_decrypt - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_decrypt - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_decrypt - Win32 MT DLL Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_decrypt - Win32 MT DLL Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_decrypt - Win32 Profile" (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)" == "BLO_decrypt - 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 "..\..\..\..\obj\windows\blender\decrypt"
+# 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 "..\..\..source\blender\writestream" /I "..\..\..\source\blender\writestreamglue" /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\lib\windows\blenkey\include" /I "..\..\..\lib\windows\openssl\include" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\decrypt" /I "..\..\..\source\blender\readstreamglue" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\decrypt\BLO_decrypt.lib"
+
+!ELSEIF "$(CFG)" == "BLO_decrypt - 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 "..\..\..\..\obj\windows\blender\decrypt\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 "..\..\..\source\blender\writestreamglue" /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\lib\windows\blenkey\include" /I "..\..\..\lib\windows\openssl\include" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\decrypt" /I "..\..\..\source\blender\readstreamglue" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# SUBTRACT CPP /Fr
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\decrypt\debug\BLO_decrypt.lib"
+
+!ELSEIF "$(CFG)" == "BLO_decrypt - Win32 MT DLL Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "BLO_decrypt___Win32_MT_DLL_Release"
+# PROP BASE Intermediate_Dir "BLO_decrypt___Win32_MT_DLL_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\..\..\..\obj\windows\blender\decrypt\mtdll"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\blender\decrypt\mtdll"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /GX /O2 /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\lib\windows\blenkey\include" /I "..\..\..\lib\windows\openssl\include" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\decrypt" /I "..\..\..\source\blender\readstreamglue" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\..source\blender\writestream" /I "..\..\..\source\blender\writestreamglue" /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\lib\windows\blenkey\include" /I "..\..\..\lib\windows\openssl\include" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\decrypt" /I "..\..\..\source\blender\readstreamglue" /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)" == "BLO_decrypt - Win32 MT DLL Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "BLO_decrypt___Win32_MT_DLL_Debug"
+# PROP BASE Intermediate_Dir "BLO_decrypt___Win32_MT_DLL_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\..\..\..\obj\windows\blender\decrypt\mtdll_debug"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\blender\decrypt\mtdll_debug"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\lib\windows\blenkey\include" /I "..\..\..\lib\windows\openssl\include" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\decrypt" /I "..\..\..\source\blender\readstreamglue" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..source\blender\writestream" /I "..\..\..\source\blender\writestreamglue" /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\lib\windows\blenkey\include" /I "..\..\..\lib\windows\openssl\include" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\decrypt" /I "..\..\..\source\blender\readstreamglue" /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
+
+!ELSEIF "$(CFG)" == "BLO_decrypt - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "BLO_decrypt___Win32_Profile"
+# PROP BASE Intermediate_Dir "BLO_decrypt___Win32_Profile"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "BLO_decrypt___Win32_Profile"
+# PROP Intermediate_Dir "BLO_decrypt___Win32_Profile"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\source\blender\writestreamglue" /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\lib\windows\blenkey\include" /I "..\..\..\lib\windows\openssl\include" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\decrypt" /I "..\..\..\source\blender\readstreamglue" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FR /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /O2 /I "..\..\..\source\blender\writestreamglue" /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\lib\windows\blenkey\include" /I "..\..\..\lib\windows\openssl\include" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\decrypt" /I "..\..\..\source\blender\readstreamglue" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# SUBTRACT CPP /Fr
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\decrypt\debug\BLO_decrypt.lib"
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\decrypt\debug\BLO_decrypt.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "BLO_decrypt - Win32 Release"
+# Name "BLO_decrypt - Win32 Debug"
+# Name "BLO_decrypt - Win32 MT DLL Release"
+# Name "BLO_decrypt - Win32 MT DLL Debug"
+# Name "BLO_decrypt - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\decrypt\intern\BLO_decrypt.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/blender/BLO_decrypt_stub/BLO_decrypt_stub.dsp b/projectfiles/blender/BLO_decrypt_stub/BLO_decrypt_stub.dsp
new file mode 100644
index 00000000000..f681e1d6446
--- /dev/null
+++ b/projectfiles/blender/BLO_decrypt_stub/BLO_decrypt_stub.dsp
@@ -0,0 +1,133 @@
+# Microsoft Developer Studio Project File - Name="BLO_decrypt_stub" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=BLO_decrypt_stub - Win32 Profile
+!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 "BLO_decrypt_stub.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 "BLO_decrypt_stub.mak" CFG="BLO_decrypt_stub - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "BLO_decrypt_stub - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_decrypt_stub - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_decrypt_stub - Win32 Profile" (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)" == "BLO_decrypt_stub - 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 "..\..\..\..\obj\windows\blender\decryptstub"
+# 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 "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\decrypt" /I "..\..\..\source\blender\readstreamglue" /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:"..\..\..\..\obj\windows\blender\decryptstub\BLO_decrypt_stub.lib"
+
+!ELSEIF "$(CFG)" == "BLO_decrypt_stub - 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 "..\..\..\..\obj\windows\blender\decryptstub\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 "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\decrypt" /I "..\..\..\source\blender\readstreamglue" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# SUBTRACT CPP /Fr
+# 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:"..\..\..\..\obj\windows\blender\decryptstub\debug\BLO_decrypt_stub.lib"
+
+!ELSEIF "$(CFG)" == "BLO_decrypt_stub - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "BLO_decrypt_stub___Win32_Profile"
+# PROP BASE Intermediate_Dir "BLO_decrypt_stub___Win32_Profile"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "BLO_decrypt_stub___Win32_Profile"
+# PROP Intermediate_Dir "BLO_decrypt_stub___Win32_Profile"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\decrypt" /I "..\..\..\source\blender\readstreamglue" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FR /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\decrypt" /I "..\..\..\source\blender\readstreamglue" /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 /out:"..\..\..\..\obj\windows\blender\decryptstub\debug\BLO_decrypt_stub.lib"
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\decryptstub\debug\BLO_decrypt_stub.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "BLO_decrypt_stub - Win32 Release"
+# Name "BLO_decrypt_stub - Win32 Debug"
+# Name "BLO_decrypt_stub - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\decrypt\stub\BLO_decryptSTUB.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\decrypt\BLO_decrypt.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\decrypt\BLO_en_de_cryptHeader.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/blender/BLO_deflate/BLO_deflate.dsp b/projectfiles/blender/BLO_deflate/BLO_deflate.dsp
new file mode 100644
index 00000000000..ed8a4a4f1d8
--- /dev/null
+++ b/projectfiles/blender/BLO_deflate/BLO_deflate.dsp
@@ -0,0 +1,182 @@
+# Microsoft Developer Studio Project File - Name="BLO_deflate" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=BLO_deflate - Win32 Profile
+!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 "BLO_deflate.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 "BLO_deflate.mak" CFG="BLO_deflate - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "BLO_deflate - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_deflate - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_deflate - Win32 MT DLL Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_deflate - Win32 MT DLL Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_deflate - Win32 Profile" (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)" == "BLO_deflate - 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\blender\deflate"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\blender\deflate"
+# 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 "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\deflate\\" /I "..\..\..\source\blender\inflate\\" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\writestreamglue" /I "..\..\..\source\blender\readstreamglue" /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
+
+!ELSEIF "$(CFG)" == "BLO_deflate - 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\blender\deflate\debug"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\blender\deflate\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 "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\deflate\\" /I "..\..\..\source\blender\inflate\\" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\writestreamglue" /I "..\..\..\source\blender\readstreamglue" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# SUBTRACT CPP /Fr
+# 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
+
+!ELSEIF "$(CFG)" == "BLO_deflate - Win32 MT DLL Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "BLO_deflate___Win32_MT_DLL_Release"
+# PROP BASE Intermediate_Dir "BLO_deflate___Win32_MT_DLL_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\..\..\..\obj\windows\blender\deflate\mtdll"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\blender\deflate\mtdll"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /GX /O2 /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\deflate\\" /I "..\..\..\source\blender\inflate\\" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\writestreamglue" /I "..\..\..\source\blender\readstreamglue" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\deflate\\" /I "..\..\..\source\blender\inflate\\" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\writestreamglue" /I "..\..\..\source\blender\readstreamglue" /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
+
+!ELSEIF "$(CFG)" == "BLO_deflate - Win32 MT DLL Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "BLO_deflate___Win32_MT_DLL_Debug"
+# PROP BASE Intermediate_Dir "BLO_deflate___Win32_MT_DLL_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\..\..\..\obj\windows\blender\deflate\mtdll_debug"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\blender\deflate\mtdll_debug"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\deflate\\" /I "..\..\..\source\blender\inflate\\" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\writestreamglue" /I "..\..\..\source\blender\readstreamglue" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\deflate\\" /I "..\..\..\source\blender\inflate\\" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\writestreamglue" /I "..\..\..\source\blender\readstreamglue" /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
+
+!ELSEIF "$(CFG)" == "BLO_deflate - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "BLO_deflate___Win32_Profile"
+# PROP BASE Intermediate_Dir "BLO_deflate___Win32_Profile"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "BLO_deflate___Win32_Profile"
+# PROP Intermediate_Dir "BLO_deflate___Win32_Profile"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\deflate\\" /I "..\..\..\source\blender\inflate\\" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\writestreamglue" /I "..\..\..\source\blender\readstreamglue" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FR /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /O2 /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\deflate\\" /I "..\..\..\source\blender\inflate\\" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\writestreamglue" /I "..\..\..\source\blender\readstreamglue" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# SUBTRACT CPP /Fr
+# 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
+
+!ENDIF
+
+# Begin Target
+
+# Name "BLO_deflate - Win32 Release"
+# Name "BLO_deflate - Win32 Debug"
+# Name "BLO_deflate - Win32 MT DLL Release"
+# Name "BLO_deflate - Win32 MT DLL Debug"
+# Name "BLO_deflate - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\deflate\intern\BLO_deflate.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\deflate\BLO_deflate.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/blender/BLO_deflate_stub/BLO_deflate_stub.dsp b/projectfiles/blender/BLO_deflate_stub/BLO_deflate_stub.dsp
new file mode 100644
index 00000000000..44d31b968a1
--- /dev/null
+++ b/projectfiles/blender/BLO_deflate_stub/BLO_deflate_stub.dsp
@@ -0,0 +1,154 @@
+# Microsoft Developer Studio Project File - Name="BLO_deflate_stub" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=BLO_deflate_stub - Win32 MT DLL 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 "BLO_deflate_stub.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 "BLO_deflate_stub.mak" CFG="BLO_deflate_stub - Win32 MT DLL Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "BLO_deflate_stub - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_deflate_stub - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_deflate_stub - Win32 MT DLL Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_deflate_stub - Win32 MT DLL 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)" == "BLO_deflate_stub - 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\blender\deflate_stub"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\blender\deflate_stub"
+# 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 "..\..\..\source\blender\deflate\\" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\streamglue" /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)" == "BLO_deflate_stub - 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\blender\deflate_stub\debug"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\blender\deflate_stub\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 "..\..\..\source\blender\deflate\\" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\streamglue" /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
+
+!ELSEIF "$(CFG)" == "BLO_deflate_stub - Win32 MT DLL Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "BLO_deflate_stub___Win32_MT_DLL_Release"
+# PROP BASE Intermediate_Dir "BLO_deflate_stub___Win32_MT_DLL_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "BLO_deflate_stub___Win32_MT_DLL_Release"
+# PROP Intermediate_Dir "BLO_deflate_stub___Win32_MT_DLL_Release"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /GX /O2 /I "..\..\..\source\blender\deflate\\" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\streamglue" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\..\source\blender\deflate\\" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\streamglue" /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)" == "BLO_deflate_stub - Win32 MT DLL Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "BLO_deflate_stub___Win32_MT_DLL_Debug"
+# PROP BASE Intermediate_Dir "BLO_deflate_stub___Win32_MT_DLL_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "BLO_deflate_stub___Win32_MT_DLL_Debug"
+# PROP Intermediate_Dir "BLO_deflate_stub___Win32_MT_DLL_Debug"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\source\blender\deflate\\" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\streamglue" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\source\blender\deflate\\" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\streamglue" /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 "BLO_deflate_stub - Win32 Release"
+# Name "BLO_deflate_stub - Win32 Debug"
+# Name "BLO_deflate_stub - Win32 MT DLL Release"
+# Name "BLO_deflate_stub - Win32 MT DLL Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\deflate\stub\BLO_deflateSTUB.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\deflate\BLO_deflate.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/blender/BLO_encrypt/BLO_encrypt.dsp b/projectfiles/blender/BLO_encrypt/BLO_encrypt.dsp
new file mode 100644
index 00000000000..9b02fa026a8
--- /dev/null
+++ b/projectfiles/blender/BLO_encrypt/BLO_encrypt.dsp
@@ -0,0 +1,178 @@
+# Microsoft Developer Studio Project File - Name="BLO_encrypt" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=BLO_encrypt - Win32 Profile
+!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 "BLO_encrypt.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 "BLO_encrypt.mak" CFG="BLO_encrypt - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "BLO_encrypt - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_encrypt - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_encrypt - Win32 MT DLL Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_encrypt - Win32 MT DLL Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_encrypt - Win32 Profile" (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)" == "BLO_encrypt - 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 "..\..\..\..\obj\windows\blender\encrypt"
+# 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 "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\writestreamglue" /I "..\..\..\source\blender\encrypt" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\lib\windows\openssl\include" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\lib\windows\blenkey\include" /I "..\..\..\source\blender\decrypt" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\encrypt\BLO_encrypt.lib"
+
+!ELSEIF "$(CFG)" == "BLO_encrypt - 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 "..\..\..\..\obj\windows\blender\encrypt\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 "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\writestreamglue" /I "..\..\..\source\blender\encrypt" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\lib\windows\openssl\include" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\lib\windows\blenkey\include" /I "..\..\..\source\blender\decrypt" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# SUBTRACT CPP /Fr
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\encrypt\debug\BLO_encrypt.lib"
+
+!ELSEIF "$(CFG)" == "BLO_encrypt - Win32 MT DLL Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "BLO_encrypt___Win32_MT_DLL_Release"
+# PROP BASE Intermediate_Dir "BLO_encrypt___Win32_MT_DLL_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\..\..\..\obj\windows\blender\encrypt\mtdll"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\blender\encrypt\mtdll"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /GX /O2 /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\writestreamglue" /I "..\..\..\source\blender\encrypt" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\lib\windows\openssl\include" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\lib\windows\blenkey\include" /I "..\..\..\source\blender\decrypt" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\writestreamglue" /I "..\..\..\source\blender\encrypt" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\lib\windows\openssl\include" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\lib\windows\blenkey\include" /I "..\..\..\source\blender\decrypt" /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)" == "BLO_encrypt - Win32 MT DLL Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "BLO_encrypt___Win32_MT_DLL_Debug"
+# PROP BASE Intermediate_Dir "BLO_encrypt___Win32_MT_DLL_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\..\..\..\obj\windows\blender\encrypt\mtdll_debug"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\blender\encrypt\mtdll_debug"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\writestreamglue" /I "..\..\..\source\blender\encrypt" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\lib\windows\openssl\include" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\lib\windows\blenkey\include" /I "..\..\..\source\blender\decrypt" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\writestreamglue" /I "..\..\..\source\blender\encrypt" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\lib\windows\openssl\include" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\lib\windows\blenkey\include" /I "..\..\..\source\blender\decrypt" /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
+
+!ELSEIF "$(CFG)" == "BLO_encrypt - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "BLO_encrypt___Win32_Profile"
+# PROP BASE Intermediate_Dir "BLO_encrypt___Win32_Profile"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "BLO_encrypt___Win32_Profile"
+# PROP Intermediate_Dir "BLO_encrypt___Win32_Profile"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\writestreamglue" /I "..\..\..\source\blender\encrypt" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\lib\windows\openssl\include" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\lib\windows\blenkey\include" /I "..\..\..\source\blender\decrypt" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FR /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /O2 /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\writestreamglue" /I "..\..\..\source\blender\encrypt" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\lib\windows\openssl\include" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\lib\windows\blenkey\include" /I "..\..\..\source\blender\decrypt" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# SUBTRACT CPP /Fr
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\encrypt\debug\BLO_encrypt.lib"
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\encrypt\debug\BLO_encrypt.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "BLO_encrypt - Win32 Release"
+# Name "BLO_encrypt - Win32 Debug"
+# Name "BLO_encrypt - Win32 MT DLL Release"
+# Name "BLO_encrypt - Win32 MT DLL Debug"
+# Name "BLO_encrypt - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\encrypt\intern\BLO_encrypt.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/blender/BLO_inflate/BLO_inflate.dsp b/projectfiles/blender/BLO_inflate/BLO_inflate.dsp
new file mode 100644
index 00000000000..1ec1ee58801
--- /dev/null
+++ b/projectfiles/blender/BLO_inflate/BLO_inflate.dsp
@@ -0,0 +1,181 @@
+# Microsoft Developer Studio Project File - Name="BLO_inflate" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=BLO_inflate - Win32 Profile
+!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 "BLO_inflate.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 "BLO_inflate.mak" CFG="BLO_inflate - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "BLO_inflate - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_inflate - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_inflate - Win32 MT DLL Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_inflate - Win32 MT DLL Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_inflate - Win32 Profile" (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)" == "BLO_inflate - 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 "..\..\..\..\obj\windows\blender\inflate"
+# 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 "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\inflate" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\blender\writestreamglue" /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:"..\..\..\..\obj\windows\blender\inflate\BLO_inflate.lib"
+
+!ELSEIF "$(CFG)" == "BLO_inflate - 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 "..\..\..\..\obj\windows\blender\inflate\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 "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\inflate" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\blender\writestreamglue" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# SUBTRACT CPP /Fr
+# 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:"..\..\..\..\obj\windows\blender\inflate\debug\BLO_inflate.lib"
+
+!ELSEIF "$(CFG)" == "BLO_inflate - Win32 MT DLL Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "BLO_inflate___Win32_MT_DLL_Release"
+# PROP BASE Intermediate_Dir "BLO_inflate___Win32_MT_DLL_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\..\..\..\obj\windows\blender\inflate\mtdll"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\blender\inflate\mtdll"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /GX /O2 /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\inflate" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\blender\writestreamglue" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\inflate" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\blender\writestreamglue" /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
+
+!ELSEIF "$(CFG)" == "BLO_inflate - Win32 MT DLL Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "BLO_inflate___Win32_MT_DLL_Debug"
+# PROP BASE Intermediate_Dir "BLO_inflate___Win32_MT_DLL_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\..\..\..\obj\windows\blender\inflate\mtdll_debug"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\blender\inflate\mtdll_debug"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\inflate" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\blender\writestreamglue" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\inflate" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\blender\writestreamglue" /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
+
+!ELSEIF "$(CFG)" == "BLO_inflate - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "BLO_inflate___Win32_Profile"
+# PROP BASE Intermediate_Dir "BLO_inflate___Win32_Profile"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "BLO_inflate___Win32_Profile"
+# PROP Intermediate_Dir "BLO_inflate___Win32_Profile"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\inflate" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\blender\writestreamglue" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FR /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\inflate" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\blender\writestreamglue" /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 /out:"..\..\..\..\obj\windows\blender\inflate\debug\BLO_inflate.lib"
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\inflate\debug\BLO_inflate.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "BLO_inflate - Win32 Release"
+# Name "BLO_inflate - Win32 Debug"
+# Name "BLO_inflate - Win32 MT DLL Release"
+# Name "BLO_inflate - Win32 MT DLL Debug"
+# Name "BLO_inflate - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\inflate\intern\BLO_inflate.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\inflate\BLO_inflate.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/blender/BLO_readblenfile/BLO_readblenfile.dsp b/projectfiles/blender/BLO_readblenfile/BLO_readblenfile.dsp
new file mode 100644
index 00000000000..ffc9673530c
--- /dev/null
+++ b/projectfiles/blender/BLO_readblenfile/BLO_readblenfile.dsp
@@ -0,0 +1,181 @@
+# Microsoft Developer Studio Project File - Name="BLO_readblenfile" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=BLO_readblenfile - Win32 Profile
+!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 "BLO_readblenfile.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 "BLO_readblenfile.mak" CFG="BLO_readblenfile - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "BLO_readblenfile - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_readblenfile - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_readblenfile - Win32 MT DLL Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_readblenfile - Win32 MT DLL Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_readblenfile - Win32 Profile" (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)" == "BLO_readblenfile - 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\blender\readblenfile"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\blender\readblenfile"
+# 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 "..\..\..\source\blender\streamglue\\" /I "..\..\..\source\blender\blenloader\\" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\readblenfile\\" /I "..\..\..\source\blender\deflate\\" /I "..\..\..\source\blender\inflate\\" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\readstreamglue" /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
+
+!ELSEIF "$(CFG)" == "BLO_readblenfile - 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\blender\readblenfile\debug"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\blender\readblenfile\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 "..\..\..\source\blender\readstreamglue\\" /I "..\..\..\source\blender\blenloader\\" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\readblenfile\\" /I "..\..\..\source\blender\deflate\\" /I "..\..\..\source\blender\inflate\\" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\readstreamglue" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# SUBTRACT CPP /Fr
+# 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
+
+!ELSEIF "$(CFG)" == "BLO_readblenfile - Win32 MT DLL Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "BLO_readblenfile___Win32_MT_DLL_Release"
+# PROP BASE Intermediate_Dir "BLO_readblenfile___Win32_MT_DLL_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\..\..\..\obj\windows\blender\readblenfile\mtdll"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\blender\readblenfile\mtdll"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /GX /O2 /I "..\..\..\source\blender\streamglue\\" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\readblenfile\\" /I "..\..\..\source\blender\deflate\\" /I "..\..\..\source\blender\inflate\\" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\readstreamglue" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\..\source\blender\streamglue\\" /I "..\..\..\source\blender\blenloader\\" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\readblenfile\\" /I "..\..\..\source\blender\deflate\\" /I "..\..\..\source\blender\inflate\\" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\readstreamglue" /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
+
+!ELSEIF "$(CFG)" == "BLO_readblenfile - Win32 MT DLL Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "BLO_readblenfile___Win32_MT_DLL_Debug"
+# PROP BASE Intermediate_Dir "BLO_readblenfile___Win32_MT_DLL_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\..\..\..\obj\windows\blender\readblenfile\mtdll_debug"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\blender\readblenfile\mtdll_debug"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\readstreamglue\\" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\readblenfile\\" /I "..\..\..\source\blender\deflate\\" /I "..\..\..\source\blender\inflate\\" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\readstreamglue" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\source\blender\readstreamglue\\" /I "..\..\..\source\blender\blenloader\\" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\readblenfile\\" /I "..\..\..\source\blender\deflate\\" /I "..\..\..\source\blender\inflate\\" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\readstreamglue" /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
+
+!ELSEIF "$(CFG)" == "BLO_readblenfile - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "BLO_readblenfile___Win32_Profile"
+# PROP BASE Intermediate_Dir "BLO_readblenfile___Win32_Profile"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "BLO_readblenfile___Win32_Profile"
+# PROP Intermediate_Dir "BLO_readblenfile___Win32_Profile"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\readstreamglue\\" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\readblenfile\\" /I "..\..\..\source\blender\deflate\\" /I "..\..\..\source\blender\inflate\\" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\readstreamglue" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FR /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /I "..\..\..\source\blender\readstreamglue\\" /I "..\..\..\source\blender\blenloader\\" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\readblenfile\\" /I "..\..\..\source\blender\deflate\\" /I "..\..\..\source\blender\inflate\\" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\readstreamglue" /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
+
+!ENDIF
+
+# Begin Target
+
+# Name "BLO_readblenfile - Win32 Release"
+# Name "BLO_readblenfile - Win32 Debug"
+# Name "BLO_readblenfile - Win32 MT DLL Release"
+# Name "BLO_readblenfile - Win32 MT DLL Debug"
+# Name "BLO_readblenfile - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\readblenfile\intern\BLO_readblenfile.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\readblenfile\BLO_readblenfile.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/blender/BLO_readblenfile_stub/BLO_readblenfile_stub.dsp b/projectfiles/blender/BLO_readblenfile_stub/BLO_readblenfile_stub.dsp
new file mode 100644
index 00000000000..c88674354d9
--- /dev/null
+++ b/projectfiles/blender/BLO_readblenfile_stub/BLO_readblenfile_stub.dsp
@@ -0,0 +1,154 @@
+# Microsoft Developer Studio Project File - Name="BLO_readblenfile_stub" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=BLO_readblenfile_stub - Win32 MT DLL 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 "BLO_readblenfile_stub.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 "BLO_readblenfile_stub.mak" CFG="BLO_readblenfile_stub - Win32 MT DLL Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "BLO_readblenfile_stub - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_readblenfile_stub - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_readblenfile_stub - Win32 MT DLL Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_readblenfile_stub - Win32 MT DLL Release" (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)" == "BLO_readblenfile_stub - 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\blender\readblenfile_stub"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\blender\readblenfile_stub"
+# 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 "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\readblenfile\\" /I "..\..\..\source\blender\streamglue\\" /I "..\..\..\source\blender\deflate\\" /I "..\..\..\source\blender\inflate\\" /I "..\..\..\lib\windows\zlib\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)" == "BLO_readblenfile_stub - 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\blender\readblenfile_stub\debug"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\blender\readblenfile_stub\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 "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\readblenfile\\" /I "..\..\..\source\blender\streamglue\\" /I "..\..\..\source\blender\deflate\\" /I "..\..\..\source\blender\inflate\\" /I "..\..\..\lib\windows\zlib\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
+
+!ELSEIF "$(CFG)" == "BLO_readblenfile_stub - Win32 MT DLL Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "MT DLL Debug"
+# PROP BASE Intermediate_Dir "MT DLL Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\..\..\..\obj\windows\blender\readblenfile_stub\mtdll_debug"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\blender\readblenfile_stub\mtdll_debug"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\source\blender\readblenfile\\" /I "..\..\..\source\blender\streamglue\\" /I "..\..\..\source\blender\deflate\\" /I "..\..\..\source\blender\inflate\\" /I "..\..\..\lib\windows\zlib\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\readblenfile\\" /I "..\..\..\source\blender\streamglue\\" /I "..\..\..\source\blender\deflate\\" /I "..\..\..\source\blender\inflate\\" /I "..\..\..\lib\windows\zlib\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
+
+!ELSEIF "$(CFG)" == "BLO_readblenfile_stub - Win32 MT DLL Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "MT DLL Release"
+# PROP BASE Intermediate_Dir "MT DLL Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\..\..\..\obj\windows\blender\readblenfile_stub\mtdll"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\blender\readblenfile_stub\mtdll"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /GX /O2 /I "..\..\..\source\blender\readblenfile\\" /I "..\..\..\source\blender\streamglue\\" /I "..\..\..\source\blender\deflate\\" /I "..\..\..\source\blender\inflate\\" /I "..\..\..\lib\windows\zlib\include" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\readblenfile\\" /I "..\..\..\source\blender\streamglue\\" /I "..\..\..\source\blender\deflate\\" /I "..\..\..\source\blender\inflate\\" /I "..\..\..\lib\windows\zlib\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
+
+!ENDIF
+
+# Begin Target
+
+# Name "BLO_readblenfile_stub - Win32 Release"
+# Name "BLO_readblenfile_stub - Win32 Debug"
+# Name "BLO_readblenfile_stub - Win32 MT DLL Debug"
+# Name "BLO_readblenfile_stub - Win32 MT DLL Release"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\readblenfile\stub\BLO_readblenfileSTUB.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\readblenfile\BLO_readblenfile.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/blender/BLO_readstreamglue/BLO_readstreamglue.dsp b/projectfiles/blender/BLO_readstreamglue/BLO_readstreamglue.dsp
new file mode 100644
index 00000000000..00fcaa235b9
--- /dev/null
+++ b/projectfiles/blender/BLO_readstreamglue/BLO_readstreamglue.dsp
@@ -0,0 +1,185 @@
+# Microsoft Developer Studio Project File - Name="BLO_readstreamglue" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=BLO_readstreamglue - Win32 Profile
+!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 "BLO_readstreamglue.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 "BLO_readstreamglue.mak" CFG="BLO_readstreamglue - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "BLO_readstreamglue - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_readstreamglue - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_readstreamglue - Win32 MT DLL Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_readstreamglue - Win32 MT DLL Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_readstreamglue - Win32 Profile" (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)" == "BLO_readstreamglue - 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 "..\..\..\..\obj\windows\blender\readstreamglue"
+# 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 "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\blender\readstreamglue\stubs" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\blenloader" /I "..\..\..\source\blender\inflate" /I "..\..\..\source\blender\decrypt" /I "..\..\..\source\blender\verify" /I "..\..\..\lib\windows\blenkey\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 /out:"..\..\..\..\obj\windows\blender\readstreamglue\BLO_readstreamglue.lib"
+
+!ELSEIF "$(CFG)" == "BLO_readstreamglue - 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 "..\..\..\..\obj\windows\blender\readstreamglue\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\zlib\include" /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\blender\readstreamglue\stubs" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\blenloader" /I "..\..\..\source\blender\inflate" /I "..\..\..\source\blender\decrypt" /I "..\..\..\source\blender\verify" /I "..\..\..\lib\windows\blenkey\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# SUBTRACT CPP /Fr
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\readstreamglue\debug\BLO_readstreamglue.lib"
+
+!ELSEIF "$(CFG)" == "BLO_readstreamglue - Win32 MT DLL Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "BLO_readstreamglue___Win32_MT_DLL_Release"
+# PROP BASE Intermediate_Dir "BLO_readstreamglue___Win32_MT_DLL_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\..\..\..\obj\windows\blender\readstreamglue\mtdll"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\blender\readstreamglue\mtdll"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /GX /O2 /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\blender\readstreamglue\stubs" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\blenloader" /I "..\..\..\source\blender\inflate" /I "..\..\..\source\blender\decrypt" /I "..\..\..\source\blender\verify" /I "..\..\..\lib\windows\blenkey\include" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\blender\readstreamglue\stubs" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\blenloader" /I "..\..\..\source\blender\inflate" /I "..\..\..\source\blender\decrypt" /I "..\..\..\source\blender\verify" /I "..\..\..\lib\windows\blenkey\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)" == "BLO_readstreamglue - Win32 MT DLL Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "BLO_readstreamglue___Win32_MT_DLL_Debug"
+# PROP BASE Intermediate_Dir "BLO_readstreamglue___Win32_MT_DLL_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\..\..\..\obj\windows\blender\readstreamglue\mtdll_debug"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\blender\readstreamglue\mtdll_debug"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\lib\windows\zlib\include" /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\blender\readstreamglue\stubs" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\blenloader" /I "..\..\..\source\blender\inflate" /I "..\..\..\source\blender\decrypt" /I "..\..\..\source\blender\verify" /I "..\..\..\lib\windows\blenkey\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\..\lib\windows\zlib\include" /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\blender\readstreamglue\stubs" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\blenloader" /I "..\..\..\source\blender\inflate" /I "..\..\..\source\blender\decrypt" /I "..\..\..\source\blender\verify" /I "..\..\..\lib\windows\blenkey\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
+
+!ELSEIF "$(CFG)" == "BLO_readstreamglue - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "BLO_readstreamglue___Win32_Profile"
+# PROP BASE Intermediate_Dir "BLO_readstreamglue___Win32_Profile"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "BLO_readstreamglue___Win32_Profile"
+# PROP Intermediate_Dir "BLO_readstreamglue___Win32_Profile"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\lib\windows\zlib\include" /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\blender\readstreamglue\stubs" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\blenloader" /I "..\..\..\source\blender\inflate" /I "..\..\..\source\blender\decrypt" /I "..\..\..\source\blender\verify" /I "..\..\..\lib\windows\blenkey\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FR /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /I "..\..\lib\windows\zlib\include" /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\blender\readstreamglue\stubs" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\blenloader" /I "..\..\..\source\blender\inflate" /I "..\..\..\source\blender\decrypt" /I "..\..\..\source\blender\verify" /I "..\..\..\lib\windows\blenkey\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 /out:"..\..\..\..\obj\windows\blender\readstreamglue\debug\BLO_readstreamglue.lib"
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\readstreamglue\debug\BLO_readstreamglue.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "BLO_readstreamglue - Win32 Release"
+# Name "BLO_readstreamglue - Win32 Debug"
+# Name "BLO_readstreamglue - Win32 MT DLL Release"
+# Name "BLO_readstreamglue - Win32 MT DLL Debug"
+# Name "BLO_readstreamglue - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\readstreamglue\intern\BLO_keyStore.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\readstreamglue\intern\BLO_readStreamGlue.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\readstreamglue\intern\BLO_readStreamGlueLoopBack.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/blender/BLO_sign/BLO_sign.dsp b/projectfiles/blender/BLO_sign/BLO_sign.dsp
new file mode 100644
index 00000000000..08b2058a143
--- /dev/null
+++ b/projectfiles/blender/BLO_sign/BLO_sign.dsp
@@ -0,0 +1,178 @@
+# Microsoft Developer Studio Project File - Name="BLO_sign" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=BLO_sign - Win32 Profile
+!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 "BLO_sign.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 "BLO_sign.mak" CFG="BLO_sign - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "BLO_sign - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_sign - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_sign - Win32 MT DLL Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_sign - Win32 MT DLL Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_sign - Win32 Profile" (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)" == "BLO_sign - 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 "..\..\..\..\obj\windows\blender\sign"
+# 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 "..\..\..\source\kernel\gen_messaging" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\lib\windows\openssl\include" /I "..\..\..\lib\windows\blenkey\include" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\blender\sign" /I "..\..\..\source\blender\verify" /I "..\..\..\source\blender\writestreamglue" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\sign\BLO_sign.lib"
+
+!ELSEIF "$(CFG)" == "BLO_sign - 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 "..\..\..\..\obj\windows\blender\sign\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 "..\..\..\source\kernel\gen_messaging" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\lib\windows\openssl\include" /I "..\..\..\lib\windows\blenkey\include" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\blender\sign" /I "..\..\..\source\blender\verify" /I "..\..\..\source\blender\writestreamglue" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# SUBTRACT CPP /Fr
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\sign\debug\BLO_sign.lib"
+
+!ELSEIF "$(CFG)" == "BLO_sign - Win32 MT DLL Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "BLO_sign___Win32_MT_DLL_Release"
+# PROP BASE Intermediate_Dir "BLO_sign___Win32_MT_DLL_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\..\..\..\obj\windows\blender\sign\mtdll"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\blender\sign\mtdll"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /GX /O2 /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\lib\windows\openssl\include" /I "..\..\..\lib\windows\blenkey\include" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\blender\sign" /I "..\..\..\source\blender\verify" /I "..\..\..\source\blender\writestreamglue" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\lib\windows\openssl\include" /I "..\..\..\lib\windows\blenkey\include" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\blender\sign" /I "..\..\..\source\blender\verify" /I "..\..\..\source\blender\writestreamglue" /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)" == "BLO_sign - Win32 MT DLL Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "BLO_sign___Win32_MT_DLL_Debug"
+# PROP BASE Intermediate_Dir "BLO_sign___Win32_MT_DLL_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\..\..\..\obj\windows\blender\sign\mtdll_debug"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\blender\sign\mtdll_debug"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\lib\windows\openssl\include" /I "..\..\..\lib\windows\blenkey\include" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\blender\sign" /I "..\..\..\source\blender\verify" /I "..\..\..\source\blender\writestreamglue" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\lib\windows\openssl\include" /I "..\..\..\lib\windows\blenkey\include" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\blender\sign" /I "..\..\..\source\blender\verify" /I "..\..\..\source\blender\writestreamglue" /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
+
+!ELSEIF "$(CFG)" == "BLO_sign - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "BLO_sign___Win32_Profile"
+# PROP BASE Intermediate_Dir "BLO_sign___Win32_Profile"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "BLO_sign___Win32_Profile"
+# PROP Intermediate_Dir "BLO_sign___Win32_Profile"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\lib\windows\openssl\include" /I "..\..\..\lib\windows\blenkey\include" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\blender\sign" /I "..\..\..\source\blender\verify" /I "..\..\..\source\blender\writestreamglue" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FR /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /O2 /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\lib\windows\openssl\include" /I "..\..\..\lib\windows\blenkey\include" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\blender\sign" /I "..\..\..\source\blender\verify" /I "..\..\..\source\blender\writestreamglue" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# SUBTRACT CPP /Fr
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\sign\debug\BLO_sign.lib"
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\sign\debug\BLO_sign.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "BLO_sign - Win32 Release"
+# Name "BLO_sign - Win32 Debug"
+# Name "BLO_sign - Win32 MT DLL Release"
+# Name "BLO_sign - Win32 MT DLL Debug"
+# Name "BLO_sign - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\sign\intern\BLO_sign.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/blender/BLO_streamglue_stub/BLO_streamglue_stub.dsp b/projectfiles/blender/BLO_streamglue_stub/BLO_streamglue_stub.dsp
new file mode 100644
index 00000000000..a00959146da
--- /dev/null
+++ b/projectfiles/blender/BLO_streamglue_stub/BLO_streamglue_stub.dsp
@@ -0,0 +1,158 @@
+# Microsoft Developer Studio Project File - Name="BLO_streamglue_stub" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=BLO_streamglue_stub - Win32 MT DLL 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 "BLO_streamglue_stub.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 "BLO_streamglue_stub.mak" CFG="BLO_streamglue_stub - Win32 MT DLL Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "BLO_streamglue_stub - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_streamglue_stub - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_streamglue_stub - Win32 MT DLL Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_streamglue_stub - Win32 MT DLL 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)" == "BLO_streamglue_stub - 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\blender\streamglue_stub"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\blender\streamglue_stub"
+# 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 "..\..\..\source\blender\streamglue\\" /I "..\..\..\source\blender\writeblenfile\\" /I "..\..\..\source\blender\deflate\\" /I "..\..\..\source\blender\inflate\\" /I "..\..\..\lib\windows\zlib\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)" == "BLO_streamglue_stub - 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\blender\streamglue_stub\debug"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\blender\streamglue_stub\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 "..\..\..\source\blender\streamglue\\" /I "..\..\..\source\blender\writeblenfile\\" /I "..\..\..\source\blender\deflate\\" /I "..\..\..\source\blender\inflate\\" /I "..\..\..\lib\windows\zlib\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
+
+!ELSEIF "$(CFG)" == "BLO_streamglue_stub - Win32 MT DLL Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "BLO_streamglue_stub___Win32_MT_DLL_Release"
+# PROP BASE Intermediate_Dir "BLO_streamglue_stub___Win32_MT_DLL_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "BLO_streamglue_stub___Win32_MT_DLL_Release"
+# PROP Intermediate_Dir "BLO_streamglue_stub___Win32_MT_DLL_Release"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /GX /O2 /I "..\..\..\source\blender\streamglue\\" /I "..\..\..\source\blender\writeblenfile\\" /I "..\..\..\source\blender\deflate\\" /I "..\..\..\source\blender\inflate\\" /I "..\..\..\lib\windows\zlib\include" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\..\source\blender\streamglue\\" /I "..\..\..\source\blender\writeblenfile\\" /I "..\..\..\source\blender\deflate\\" /I "..\..\..\source\blender\inflate\\" /I "..\..\..\lib\windows\zlib\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)" == "BLO_streamglue_stub - Win32 MT DLL Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "BLO_streamglue_stub___Win32_MT_DLL_Debug"
+# PROP BASE Intermediate_Dir "BLO_streamglue_stub___Win32_MT_DLL_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "BLO_streamglue_stub___Win32_MT_DLL_Debug"
+# PROP Intermediate_Dir "BLO_streamglue_stub___Win32_MT_DLL_Debug"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\source\blender\streamglue\\" /I "..\..\..\source\blender\writeblenfile\\" /I "..\..\..\source\blender\deflate\\" /I "..\..\..\source\blender\inflate\\" /I "..\..\..\lib\windows\zlib\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\source\blender\streamglue\\" /I "..\..\..\source\blender\writeblenfile\\" /I "..\..\..\source\blender\deflate\\" /I "..\..\..\source\blender\inflate\\" /I "..\..\..\lib\windows\zlib\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 "BLO_streamglue_stub - Win32 Release"
+# Name "BLO_streamglue_stub - Win32 Debug"
+# Name "BLO_streamglue_stub - Win32 MT DLL Release"
+# Name "BLO_streamglue_stub - Win32 MT DLL Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\streamglue\stub\BLO_streamGlueControlSTUB.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\streamglue\stub\BLO_streamGlueSTUB.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\streamglue\BLO_streamglue.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/blender/BLO_verify/BLO_verify.dsp b/projectfiles/blender/BLO_verify/BLO_verify.dsp
new file mode 100644
index 00000000000..e98d785eb58
--- /dev/null
+++ b/projectfiles/blender/BLO_verify/BLO_verify.dsp
@@ -0,0 +1,177 @@
+# Microsoft Developer Studio Project File - Name="BLO_verify" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=BLO_verify - Win32 Profile
+!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 "BLO_verify.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 "BLO_verify.mak" CFG="BLO_verify - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "BLO_verify - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_verify - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_verify - Win32 MT DLL Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_verify - Win32 MT DLL Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_verify - Win32 Profile" (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)" == "BLO_verify - 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 "..\..\..\..\obj\windows\blender\verify"
+# 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 "..\..\..\source\kernel\gen_messaging" /I "..\..\..\lib\windows\openssl\include" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\verify" /I "..\..\..\source\blender\readstreamglue" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\verify\BLO_verify.lib"
+
+!ELSEIF "$(CFG)" == "BLO_verify - 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 "..\..\..\..\obj\windows\blender\verify\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 "..\..\..\source\kernel\gen_messaging" /I "..\..\..\lib\windows\openssl\include" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\verify" /I "..\..\..\source\blender\readstreamglue" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# SUBTRACT CPP /Fr
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\verify\debug\BLO_verify.lib"
+
+!ELSEIF "$(CFG)" == "BLO_verify - Win32 MT DLL Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "BLO_verify___Win32_MT_DLL_Release"
+# PROP BASE Intermediate_Dir "BLO_verify___Win32_MT_DLL_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\..\..\..\obj\windows\blender\verify\mtdll"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\blender\verify\mtdll"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /GX /O2 /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\lib\windows\openssl\include" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\verify" /I "..\..\..\source\blender\readstreamglue" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\lib\windows\openssl\include" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\verify" /I "..\..\..\source\blender\readstreamglue" /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)" == "BLO_verify - Win32 MT DLL Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "BLO_verify___Win32_MT_DLL_Debug"
+# PROP BASE Intermediate_Dir "BLO_verify___Win32_MT_DLL_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\..\..\..\obj\windows\blender\verify\mtdll_debug"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\blender\verify\mtdll_debug"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\lib\windows\openssl\include" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\verify" /I "..\..\..\source\blender\readstreamglue" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\lib\windows\openssl\include" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\verify" /I "..\..\..\source\blender\readstreamglue" /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
+
+!ELSEIF "$(CFG)" == "BLO_verify - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "BLO_verify___Win32_Profile"
+# PROP BASE Intermediate_Dir "BLO_verify___Win32_Profile"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "BLO_verify___Win32_Profile"
+# PROP Intermediate_Dir "BLO_verify___Win32_Profile"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\lib\windows\openssl\include" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\verify" /I "..\..\..\source\blender\readstreamglue" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FR /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\lib\windows\openssl\include" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\verify" /I "..\..\..\source\blender\readstreamglue" /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 /out:"..\..\..\..\obj\windows\blender\verify\debug\BLO_verify.lib"
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\verify\debug\BLO_verify.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "BLO_verify - Win32 Release"
+# Name "BLO_verify - Win32 Debug"
+# Name "BLO_verify - Win32 MT DLL Release"
+# Name "BLO_verify - Win32 MT DLL Debug"
+# Name "BLO_verify - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\verify\intern\BLO_verify.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/blender/BLO_writeblenfile/BLO_writeblenfile.dsp b/projectfiles/blender/BLO_writeblenfile/BLO_writeblenfile.dsp
new file mode 100644
index 00000000000..63cf90d0b80
--- /dev/null
+++ b/projectfiles/blender/BLO_writeblenfile/BLO_writeblenfile.dsp
@@ -0,0 +1,181 @@
+# Microsoft Developer Studio Project File - Name="BLO_writeblenfile" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=BLO_writeblenfile - Win32 Profile
+!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 "BLO_writeblenfile.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 "BLO_writeblenfile.mak" CFG="BLO_writeblenfile - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "BLO_writeblenfile - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_writeblenfile - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_writeblenfile - Win32 MT_DLL Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_writeblenfile - Win32 MT DLL Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_writeblenfile - Win32 Profile" (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)" == "BLO_writeblenfile - 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\blender\writeblenfile"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\blender\writeblenfile"
+# 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 "..\..\..\source\blender\writestreamglue\\" /I "..\..\..\source\blender\blenloader\\" /I "..\..\..\source\blender\readblenfile" /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\blender\writestreamglue" /I "..\..\..\source\blender\writeblenfile\\" /I "..\..\..\source\blender\deflate\\" /I "..\..\..\source\blender\inflate\\" /I "..\..\..\lib\windows\zlib\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
+
+!ELSEIF "$(CFG)" == "BLO_writeblenfile - 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\blender\writeblenfile\debug"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\blender\writeblenfile\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 "..\..\..\source\blender\blenloader\\" /I "..\..\..\source\blender\readblenfile" /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\blender\writestreamglue" /I "..\..\..\source\blender\writeblenfile\\" /I "..\..\..\source\blender\deflate\\" /I "..\..\..\source\blender\inflate\\" /I "..\..\..\lib\windows\zlib\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# SUBTRACT CPP /Fr
+# 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
+
+!ELSEIF "$(CFG)" == "BLO_writeblenfile - Win32 MT_DLL Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "BLO_writeblenfile___Win32_MT_DLL_Release"
+# PROP BASE Intermediate_Dir "BLO_writeblenfile___Win32_MT_DLL_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "BLO_writeblenfile___Win32_MT_DLL_Release"
+# PROP Intermediate_Dir "BLO_writeblenfile___Win32_MT_DLL_Release"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /GX /O2 /I "..\..\..\source\blender\writestreamglue\\" /I "..\..\..\source\blender\readblenfile" /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\blender\writestreamglue" /I "..\..\..\source\blender\writeblenfile\\" /I "..\..\..\source\blender\deflate\\" /I "..\..\..\source\blender\inflate\\" /I "..\..\..\lib\windows\zlib\include" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "..\..\..\source\blender\writestreamglue\\" /I "..\..\..\source\blender\blenloader\\" /I "..\..\..\source\blender\readblenfile" /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\blender\writestreamglue" /I "..\..\..\source\blender\writeblenfile\\" /I "..\..\..\source\blender\deflate\\" /I "..\..\..\source\blender\inflate\\" /I "..\..\..\lib\windows\zlib\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
+
+!ELSEIF "$(CFG)" == "BLO_writeblenfile - Win32 MT DLL Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "BLO_writeblenfile___Win32_MT_DLL_Debug"
+# PROP BASE Intermediate_Dir "BLO_writeblenfile___Win32_MT_DLL_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\..\..\..\obj\windows\blender\writeblenfile\mtdll_debug"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\blender\writeblenfile\mtdll_debug"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\source\blender\readblenfile" /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\blender\writestreamglue" /I "..\..\..\source\blender\writeblenfile\\" /I "..\..\..\source\blender\deflate\\" /I "..\..\..\source\blender\inflate\\" /I "..\..\..\lib\windows\zlib\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\source\blender\blenloader\\" /I "..\..\..\source\blender\readblenfile" /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\blender\writestreamglue" /I "..\..\..\source\blender\writeblenfile\\" /I "..\..\..\source\blender\deflate\\" /I "..\..\..\source\blender\inflate\\" /I "..\..\..\lib\windows\zlib\include" /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
+
+!ELSEIF "$(CFG)" == "BLO_writeblenfile - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "BLO_writeblenfile___Win32_Profile"
+# PROP BASE Intermediate_Dir "BLO_writeblenfile___Win32_Profile"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "BLO_writeblenfile___Win32_Profile"
+# PROP Intermediate_Dir "BLO_writeblenfile___Win32_Profile"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\source\blender\readblenfile" /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\blender\writestreamglue" /I "..\..\..\source\blender\writeblenfile\\" /I "..\..\..\source\blender\deflate\\" /I "..\..\..\source\blender\inflate\\" /I "..\..\..\lib\windows\zlib\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FR /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /I "..\..\..\source\blender\blenloader\\" /I "..\..\..\source\blender\readblenfile" /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\blender\writestreamglue" /I "..\..\..\source\blender\writeblenfile\\" /I "..\..\..\source\blender\deflate\\" /I "..\..\..\source\blender\inflate\\" /I "..\..\..\lib\windows\zlib\include" /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
+
+!ENDIF
+
+# Begin Target
+
+# Name "BLO_writeblenfile - Win32 Release"
+# Name "BLO_writeblenfile - Win32 Debug"
+# Name "BLO_writeblenfile - Win32 MT_DLL Release"
+# Name "BLO_writeblenfile - Win32 MT DLL Debug"
+# Name "BLO_writeblenfile - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\writeblenfile\intern\BLO_writeblenfile.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\writeblenfile\BLO_writeblenfile.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/blender/BLO_writestreamglue/BLO_writestreamglue.dsp b/projectfiles/blender/BLO_writestreamglue/BLO_writestreamglue.dsp
new file mode 100644
index 00000000000..29c7a920c4d
--- /dev/null
+++ b/projectfiles/blender/BLO_writestreamglue/BLO_writestreamglue.dsp
@@ -0,0 +1,201 @@
+# Microsoft Developer Studio Project File - Name="BLO_writestreamglue" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=BLO_writestreamglue - Win32 Profile
+!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 "BLO_writestreamglue.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 "BLO_writestreamglue.mak" CFG="BLO_writestreamglue - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "BLO_writestreamglue - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_writestreamglue - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_writestreamglue - Win32 MT DLL Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_writestreamglue - Win32 MT DLL Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_writestreamglue - Win32 Profile" (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)" == "BLO_writestreamglue - 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 "..\..\..\..\obj\windows\blender\writestreamglue"
+# 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 "..\..\..\source\kernel\gen_messaging" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\writestreamglue" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\blender\deflate" /I "..\..\..\source\blender\encrypt" /I "..\..\..\source\blender\sign" /I "..\..\..\source\blender\writeblenfile" /I "..\..\..\lib\windows\blenkey\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 /out:"..\..\..\..\obj\windows\blender\writestreamglue\BLO_writestreamglue.lib"
+
+!ELSEIF "$(CFG)" == "BLO_writestreamglue - 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 "..\..\..\..\obj\windows\blender\writestreamglue\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 "..\..\..\source\kernel\gen_messaging" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\writestreamglue" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\blender\deflate" /I "..\..\..\source\blender\encrypt" /I "..\..\..\source\blender\sign" /I "..\..\..\source\blender\writeblenfile" /I "..\..\..\lib\windows\blenkey\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# SUBTRACT CPP /Fr
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\writestreamglue\debug\BLO_writestreamglue.lib"
+
+!ELSEIF "$(CFG)" == "BLO_writestreamglue - Win32 MT DLL Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "BLO_writestreamglue___Win32_MT_DLL_Release"
+# PROP BASE Intermediate_Dir "BLO_writestreamglue___Win32_MT_DLL_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\..\..\..\obj\windows\blender\writestreamglue\mtdll"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\blender\writestreamglue\mtdll"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /GX /O2 /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\writestreamglue" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\blender\deflate" /I "..\..\..\source\blender\encrypt" /I "..\..\..\source\blender\sign" /I "..\..\..\source\blender\writeblenfile" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\writestreamglue" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\blender\deflate" /I "..\..\..\source\blender\encrypt" /I "..\..\..\source\blender\sign" /I "..\..\..\source\blender\writeblenfile" /I "..\..\..\lib\windows\blenkey\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)" == "BLO_writestreamglue - Win32 MT DLL Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "BLO_writestreamglue___Win32_MT_DLL_Debug"
+# PROP BASE Intermediate_Dir "BLO_writestreamglue___Win32_MT_DLL_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\..\..\..\obj\windows\blender\writestreamglue\mtdll_debug"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\blender\writestreamglue\mtdll_debug"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\writestreamglue" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\blender\deflate" /I "..\..\..\source\blender\encrypt" /I "..\..\..\source\blender\sign" /I "..\..\..\source\blender\writeblenfile" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\writestreamglue" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\blender\deflate" /I "..\..\..\source\blender\encrypt" /I "..\..\..\source\blender\sign" /I "..\..\..\source\blender\writeblenfile" /I "..\..\..\lib\windows\blenkey\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
+
+!ELSEIF "$(CFG)" == "BLO_writestreamglue - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "BLO_writestreamglue___Win32_Profile"
+# PROP BASE Intermediate_Dir "BLO_writestreamglue___Win32_Profile"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "BLO_writestreamglue___Win32_Profile"
+# PROP Intermediate_Dir "BLO_writestreamglue___Win32_Profile"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\writestreamglue" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\blender\deflate" /I "..\..\..\source\blender\encrypt" /I "..\..\..\source\blender\sign" /I "..\..\..\source\blender\writeblenfile" /I "..\..\..\lib\windows\blenkey\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FR /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\writestreamglue" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\blender\deflate" /I "..\..\..\source\blender\encrypt" /I "..\..\..\source\blender\sign" /I "..\..\..\source\blender\writeblenfile" /I "..\..\..\lib\windows\blenkey\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 /out:"..\..\..\..\obj\windows\blender\writestreamglue\debug\BLO_writestreamglue.lib"
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\writestreamglue\debug\BLO_writestreamglue.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "BLO_writestreamglue - Win32 Release"
+# Name "BLO_writestreamglue - Win32 Debug"
+# Name "BLO_writestreamglue - Win32 MT DLL Release"
+# Name "BLO_writestreamglue - Win32 MT DLL Debug"
+# Name "BLO_writestreamglue - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\writestreamglue\intern\BLO_dumpFromMemory.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\writestreamglue\intern\BLO_getPubKey.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\writestreamglue\intern\BLO_streamGlueControl.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\writestreamglue\intern\BLO_writeStreamGlue.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\writestreamglue\BLO_getPubKey.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\writestreamglue\BLO_writeStreamErrors.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\writestreamglue\BLO_writeStreamGlue.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/blender/BLO_writestreamglue_stub/BLO_writestreamglue_stub.dsp b/projectfiles/blender/BLO_writestreamglue_stub/BLO_writestreamglue_stub.dsp
new file mode 100644
index 00000000000..02c6d8b99d9
--- /dev/null
+++ b/projectfiles/blender/BLO_writestreamglue_stub/BLO_writestreamglue_stub.dsp
@@ -0,0 +1,188 @@
+# Microsoft Developer Studio Project File - Name="BLO_writestreamglue_stub" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=BLO_writestreamglue_stub - Win32 Profile
+!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 "BLO_writestreamglue_stub.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 "BLO_writestreamglue_stub.mak" CFG="BLO_writestreamglue_stub - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "BLO_writestreamglue_stub - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_writestreamglue_stub - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_writestreamglue_stub - Win32 MT DLL Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_writestreamglue_stub - Win32 MT DLL Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_writestreamglue_stub - Win32 Profile" (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)" == "BLO_writestreamglue_stub - 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 /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\writestreamglue" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\blender\deflate" /I "..\..\..\source\blender\encrypt" /I "..\..\..\source\blender\sign" /I "..\..\..\source\blender\writeblenfile" /I "..\..\..\lib\windows\blenkey\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)" == "BLO_writestreamglue_stub - 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 "..\..\..\source\kernel\gen_messaging" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\writestreamglue" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\blender\deflate" /I "..\..\..\source\blender\encrypt" /I "..\..\..\source\blender\sign" /I "..\..\..\source\blender\writeblenfile" /I "..\..\..\lib\windows\blenkey\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
+
+!ELSEIF "$(CFG)" == "BLO_writestreamglue_stub - Win32 MT DLL Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "BLO_writestreamglue_stub___Win32_MT_DLL_Release"
+# PROP BASE Intermediate_Dir "BLO_writestreamglue_stub___Win32_MT_DLL_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\..\..\..\obj\windows\blender\writestreamglue_stub\mtdll"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\blender\writestreamglue_stub\mtdll"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /GX /O2 /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\writestreamglue" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\blender\deflate" /I "..\..\..\source\blender\encrypt" /I "..\..\..\source\blender\sign" /I "..\..\..\source\blender\writeblenfile" /I "..\..\..\lib\windows\blenkey\include" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\writestreamglue" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\blender\deflate" /I "..\..\..\source\blender\encrypt" /I "..\..\..\source\blender\sign" /I "..\..\..\source\blender\writeblenfile" /I "..\..\..\lib\windows\blenkey\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)" == "BLO_writestreamglue_stub - Win32 MT DLL Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "BLO_writestreamglue_stub___Win32_MT_DLL_Debug"
+# PROP BASE Intermediate_Dir "BLO_writestreamglue_stub___Win32_MT_DLL_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\..\..\..\obj\windows\blender\writestreamglue_stub\mtdll_debug"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\blender\writestreamglue_stub\mtdll_debug"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\writestreamglue" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\blender\deflate" /I "..\..\..\source\blender\encrypt" /I "..\..\..\source\blender\sign" /I "..\..\..\source\blender\writeblenfile" /I "..\..\..\lib\windows\blenkey\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\writestreamglue" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\blender\deflate" /I "..\..\..\source\blender\encrypt" /I "..\..\..\source\blender\sign" /I "..\..\..\source\blender\writeblenfile" /I "..\..\..\lib\windows\blenkey\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
+
+!ELSEIF "$(CFG)" == "BLO_writestreamglue_stub - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "BLO_writestreamglue_stub___Win32_Profile"
+# PROP BASE Intermediate_Dir "BLO_writestreamglue_stub___Win32_Profile"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "BLO_writestreamglue_stub___Win32_Profile"
+# PROP Intermediate_Dir "BLO_writestreamglue_stub___Win32_Profile"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\writestreamglue" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\blender\deflate" /I "..\..\..\source\blender\encrypt" /I "..\..\..\source\blender\sign" /I "..\..\..\source\blender\writeblenfile" /I "..\..\..\lib\windows\blenkey\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\writestreamglue" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\blender\deflate" /I "..\..\..\source\blender\encrypt" /I "..\..\..\source\blender\sign" /I "..\..\..\source\blender\writeblenfile" /I "..\..\..\lib\windows\blenkey\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 "BLO_writestreamglue_stub - Win32 Release"
+# Name "BLO_writestreamglue_stub - Win32 Debug"
+# Name "BLO_writestreamglue_stub - Win32 MT DLL Release"
+# Name "BLO_writestreamglue_stub - Win32 MT DLL Debug"
+# Name "BLO_writestreamglue_stub - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\writestreamglue\stub\BLO_getPubKeySTUB.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\writestreamglue\stub\BLO_keyStoreSTUB.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\writestreamglue\stub\BLO_streamGlueControlSTUB.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\writestreamglue\stub\BLO_writeStreamGlueSTUB.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/blender/avi/BL_avi.dsp b/projectfiles/blender/avi/BL_avi.dsp
new file mode 100644
index 00000000000..add241fa010
--- /dev/null
+++ b/projectfiles/blender/avi/BL_avi.dsp
@@ -0,0 +1,229 @@
+# Microsoft Developer Studio Project File - Name="BL_avi" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=BL_avi - Win32 Profile
+!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 "BL_avi.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 "BL_avi.mak" CFG="BL_avi - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "BL_avi - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "BL_avi - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "BL_avi - Win32 MT DLL Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "BL_avi - Win32 MT DLL Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "BL_avi - Win32 Profile" (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)" == "BL_avi - 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 "..\..\..\..\obj\windows\blender\avi"
+# 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 "..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\avi" /I "..\..\..\source\blender\include" /I "..\..\..\lib\windows\jpeg\include" /I "..\..\..\source\blender\makesdna" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "DWORDS_LITTLEENDIAN" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\avi\BL_avi.lib"
+
+!ELSEIF "$(CFG)" == "BL_avi - 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 "..\..\..\..\obj\windows\blender\avi\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\guardedalloc\include" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\avi" /I "..\..\..\source\blender\include" /I "..\..\..\lib\windows\jpeg\include" /I "..\..\..\source\blender\makesdna" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "DWORDS_LITTLEENDIAN" /YX /J /FD /GZ /c
+# SUBTRACT CPP /Fr
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\avi\debug\BL_avi.lib"
+
+!ELSEIF "$(CFG)" == "BL_avi - Win32 MT DLL Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "BL_avi___Win32_MT_DLL_Debug"
+# PROP BASE Intermediate_Dir "BL_avi___Win32_MT_DLL_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\..\..\..\obj\windows\blender\avi\mtdll_debug"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\blender\avi\mtdll_debug"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /Gm /GX /ZI /Od /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\avi" /I "..\..\..\source\blender\include" /I "..\..\..\lib\windows\jpeg\include" /I "..\..\..\source\blender\makesdna" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "DWORDS_LITTLEENDIAN" /YX /J /FD /GZ /c
+# ADD CPP /nologo /MDd /Gm /GX /ZI /Od /I "..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\avi" /I "..\..\..\source\blender\include" /I "..\..\..\lib\windows\jpeg\include" /I "..\..\..\source\blender\makesdna" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "DWORDS_LITTLEENDIAN" /YX /J /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 /out:"..\..\..\..\..\obj\windows\blender\avi\debug\BL_avi.lib"
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "BL_avi - Win32 MT DLL Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "BL_avi___Win32_MT_DLL_Release"
+# PROP BASE Intermediate_Dir "BL_avi___Win32_MT_DLL_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\..\..\..\obj\windows\blender\avi\mtdll"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\blender\avi\mtdll"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /GX /O2 /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\avi" /I "..\..\..\source\blender\include" /I "..\..\..\lib\windows\jpeg\include" /I "..\..\..\source\blender\makesdna" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "DWORDS_LITTLEENDIAN" /YX /J /FD /c
+# ADD CPP /nologo /MD /GX /O2 /I "..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\avi" /I "..\..\..\source\blender\include" /I "..\..\..\lib\windows\jpeg\include" /I "..\..\..\source\blender\makesdna" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "DWORDS_LITTLEENDIAN" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\..\obj\windows\blender\avi\BL_avi.lib"
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "BL_avi - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "BL_avi___Win32_Profile"
+# PROP BASE Intermediate_Dir "BL_avi___Win32_Profile"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "BL_avi___Win32_Profile"
+# PROP Intermediate_Dir "BL_avi___Win32_Profile"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\avi" /I "..\..\..\source\blender\include" /I "..\..\..\lib\windows\jpeg\include" /I "..\..\..\source\blender\makesdna" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "DWORDS_LITTLEENDIAN" /YX /J /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /O2 /I "..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\avi" /I "..\..\..\source\blender\include" /I "..\..\..\lib\windows\jpeg\include" /I "..\..\..\source\blender\makesdna" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "DWORDS_LITTLEENDIAN" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\avi\debug\BL_avi.lib"
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\avi\profile\BL_avi.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "BL_avi - Win32 Release"
+# Name "BL_avi - Win32 Debug"
+# Name "BL_avi - Win32 MT DLL Debug"
+# Name "BL_avi - Win32 MT DLL Release"
+# Name "BL_avi - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\avi\intern\avi.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\avi\intern\avirgb.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\avi\intern\codecs.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\avi\intern\endian.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\avi\intern\mjpeg.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\avi\intern\options.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\avi\intern\rgb32.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\avi\AVI_avi.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\avi\intern\avi_intern.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\avi\intern\avirgb.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\avi\intern\endian.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\avi\intern\jmf.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\avi\intern\mjpeg.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\avi\intern\rgb32.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/blender/blenkernel/BKE_blenkernel.dsp b/projectfiles/blender/blenkernel/BKE_blenkernel.dsp
new file mode 100644
index 00000000000..71b73c32a33
--- /dev/null
+++ b/projectfiles/blender/blenkernel/BKE_blenkernel.dsp
@@ -0,0 +1,708 @@
+# Microsoft Developer Studio Project File - Name="BKE_blenkernel" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=BKE_blenkernel - Win32 Profile
+!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 "BKE_blenkernel.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 "BKE_blenkernel.mak" CFG="BKE_blenkernel - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "BKE_blenkernel - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "BKE_blenkernel - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "BKE_blenkernel - Win32 MT DLL Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "BKE_blenkernel - Win32 MT DLL Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "BKE_blenkernel - Win32 Profile" (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)" == "BKE_blenkernel - 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 "..\..\..\..\obj\windows\blender\blenkernel"
+# 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 "../../../lib/windows/bsp/include" /I "..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\source\blender\renderconverter" /I "..\..\..\source\blender\render\extern\include" /I "..\..\..\source\blender\avi" /I "..\..\..\source\blender\imbuf" /I "..\..\..\source\kernel\gen_system" /I "..\..\..\source\blender\blenloader" /I "..\..\..\source\blender" /I "..\..\..\source\blender\include" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\blender\bpython\include" /I "..\..\..\source\blender\blenlib" /I "../../../source/gameengine\SoundSystem\\" /I "../../../lib/windows/iksolver/include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\blenkernel\BKE_blenkernel.lib"
+
+!ELSEIF "$(CFG)" == "BKE_blenkernel - 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 "..\..\..\..\obj\windows\blender\blenkernel\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/bsp/include" /I "..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\source\blender\renderconverter" /I "..\..\..\source\blender\render\extern\include" /I "..\..\..\source\blender\avi" /I "..\..\..\source\blender\imbuf" /I "..\..\..\source\kernel\gen_system" /I "..\..\..\source\blender\blenloader" /I "..\..\..\source\blender" /I "..\..\..\source\blender\include" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\blender\bpython\include" /I "..\..\..\source\blender\blenlib" /I "../../../source/gameengine\SoundSystem\\" /I "../../../lib/windows/iksolver/include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /GZ /c
+# SUBTRACT CPP /WX /Fr
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\blenkernel\debug\BKE_blenkernel.lib"
+
+!ELSEIF "$(CFG)" == "BKE_blenkernel - Win32 MT DLL Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "BKE_blenkernel___Win32_MT_DLL_Debug"
+# PROP BASE Intermediate_Dir "BKE_blenkernel___Win32_MT_DLL_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\..\..\..\obj\windows\blender\blenkernel\mtdll_debug"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\blender\blenkernel\mtdll_debug"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /Gm /GX /ZI /Od /I "..\..\..\source\blender\render\extern\include" /I "..\..\..\source\blender\avi" /I "..\..\..\source\blender\imbuf" /I "..\..\..\source\kernel\gen_system" /I "..\..\..\source\gameengine\soundsystem" /I "..\..\..\source\gameengine\soundsystem\snd_openal" /I "..\..\..\source\blender\blenloader" /I "..\..\..\source\blender" /I "..\..\..\source\blender\include" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\blender\bpython\include" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\gameengine\soundsystem\snd_blenderwavecache" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /GZ /c
+# SUBTRACT BASE CPP /WX
+# ADD CPP /nologo /MDd /Gm /GX /ZI /Od /I "..\..\..\source\blenloader" /I "..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\source\blender\renderconverter" /I "..\..\..\source\blender\render\extern\include" /I "..\..\..\source\blender\avi" /I "..\..\..\source\blender\imbuf" /I "..\..\..\source\kernel\gen_system" /I "..\..\..\source\blender\blenloader" /I "..\..\..\source\blender" /I "..\..\..\source\blender\include" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\blender\bpython\include" /I "..\..\..\source\blender\blenlib" /I "../../../source/gameengine\SoundSystem\\" /I "../../../lib/windows/iksolver/include" /I "../../../lib/windows/bsp/include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /GZ /c
+# SUBTRACT CPP /WX
+# 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 /out:"..\..\..\..\..\obj\windows\blender\blenkernel\debug\BKE_blenkernel.lib"
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "BKE_blenkernel - Win32 MT DLL Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "BKE_blenkernel___Win32_MT_DLL_Release"
+# PROP BASE Intermediate_Dir "BKE_blenkernel___Win32_MT_DLL_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\..\..\..\obj\windows\blender\blenkernel\mtdll"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\blender\blenkernel\mtdll"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /GX /O2 /I "..\..\..\source\blender\render\extern\include" /I "..\..\..\source\blender\avi" /I "..\..\..\source\blender\imbuf" /I "..\..\..\source\kernel\gen_system" /I "..\..\..\source\gameengine\soundsystem" /I "..\..\..\source\gameengine\soundsystem\snd_openal" /I "..\..\..\source\blender\blenloader" /I "..\..\..\source\blender" /I "..\..\..\source\blender\include" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\blender\bpython\include" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\gameengine\soundsystem\snd_blenderwavecache" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD CPP /nologo /MD /GX /O2 /I "..\..\..\source\gameengine\soundsystem" /I "..\..\..\source\gameengine\soundsystem\snd_openal" /I "..\..\..\source\gameengine\soundsystem\snd_blenderwavecache" /I "..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\source\blender\renderconverter" /I "..\..\..\source\blender\render\extern\include" /I "..\..\..\source\blender\avi" /I "..\..\..\source\blender\imbuf" /I "..\..\..\source\kernel\gen_system" /I "..\..\..\source\blender\blenloader" /I "..\..\..\source\blender" /I "..\..\..\source\blender\include" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\blender\bpython\include" /I "..\..\..\source\blender\blenlib" /I "../../../source/gameengine\SoundSystem\\" /I "../../../lib/windows/iksolver/include" /I "../../../lib/windows/bsp/include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\..\obj\windows\blender\blenkernel\BKE_blenkernel.lib"
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "BKE_blenkernel - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "BKE_blenkernel___Win32_Profile"
+# PROP BASE Intermediate_Dir "BKE_blenkernel___Win32_Profile"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "BKE_blenkernel___Win32_Profile"
+# PROP Intermediate_Dir "BKE_blenkernel___Win32_Profile"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\source\blender\render\extern\include" /I "..\..\..\source\blender\avi" /I "..\..\..\source\blender\imbuf" /I "..\..\..\source\kernel\gen_system" /I "..\..\..\source\blender\blenloader" /I "..\..\..\source\blender" /I "..\..\..\source\blender\include" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\blender\bpython\include" /I "..\..\..\source\blender\blenlib" /I "../../../source/gameengine\SoundSystem\\" /I "../../../lib/windows/iksolver/include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /GZ /c
+# SUBTRACT BASE CPP /WX
+# ADD CPP /nologo /W3 /Gm /GX /Zi /O2 /I "..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\source\blender\renderconverter" /I "..\..\..\source\blender\render\extern\include" /I "..\..\..\source\blender\avi" /I "..\..\..\source\blender\imbuf" /I "..\..\..\source\kernel\gen_system" /I "..\..\..\source\blender\blenloader" /I "..\..\..\source\blender" /I "..\..\..\source\blender\include" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\blender\bpython\include" /I "..\..\..\source\blender\blenlib" /I "../../../source/gameengine\SoundSystem\\" /I "../../../lib/windows/iksolver/include" /I "../../../lib/windows/bsp/include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\blenkernel\debug\BKE_blenkernel.lib"
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\blenkernel\profile\BKE_blenkernel.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "BKE_blenkernel - Win32 Release"
+# Name "BKE_blenkernel - Win32 Debug"
+# Name "BKE_blenkernel - Win32 MT DLL Debug"
+# Name "BKE_blenkernel - Win32 MT DLL Release"
+# Name "BKE_blenkernel - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\intern\action.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\intern\anim.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\intern\armature.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\intern\blender.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\intern\bmfont.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\intern\constraint.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\intern\curve.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\intern\deform.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\intern\displist.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\intern\effect.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\intern\exotic.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\intern\font.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\intern\group.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\intern\ika.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\intern\image.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\intern\ipo.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\intern\key.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\intern\lattice.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\intern\library.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\intern\material.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\intern\mball.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\intern\mesh.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\intern\nla.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\intern\object.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\intern\packedFile.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\intern\property.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\intern\sca.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\intern\scene.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\intern\screen.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\intern\sound.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\intern\subsurf.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\intern\text.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\intern\texture.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\intern\world.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\intern\writeavi.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_action.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_actuator_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_anim.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_armature.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_armature_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_avi.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_avi_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_bad_level_calls.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_base_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_bgpic_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_blender.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_blenkernel.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_blenkernel_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_bmfont.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_bmfont_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_booleanops.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_camera_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_cfraElem_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_controller_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_curve.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_curve_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_displist.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_editmesh.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_effect.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_effect_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_endian.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_event_codes.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_exotic.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_fastLamp_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_fileglobal_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_font.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_genfile.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_global.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_group.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_group_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_halo_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_ID.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_ika.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_ika_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_image.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_image_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_imbuf_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_ipo.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_ipo_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_key.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_key_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_lamp_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_lampren_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_lattice_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_library.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_main.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_materail_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_material.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_material_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_mball.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_mesh.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_mesh_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_meta_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_object.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_object_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_old_game.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_oops_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_osa_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_packedFile.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_plugin_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_property.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_property_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_pymain.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_readfile.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_render.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_sca.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_scene.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_scene_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_screen.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_screen_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_scriptlink_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_sdna_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_sensor_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_sequence_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_sound.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_sound_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_space_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_spaceimasel_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_strings.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_text.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_text_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_texture.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_texture_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_userdef_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_utildefines.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_vfont_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_view2d_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_view3d_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_vlakren_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_wave_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_world.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_world_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenkernel\BKE_writefile.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/blender/blenlib/BLI_blenlib.dsp b/projectfiles/blender/blenlib/BLI_blenlib.dsp
new file mode 100644
index 00000000000..d4b16e5700b
--- /dev/null
+++ b/projectfiles/blender/blenlib/BLI_blenlib.dsp
@@ -0,0 +1,389 @@
+# Microsoft Developer Studio Project File - Name="BLI_blenlib" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=BLI_blenlib - Win32 Profile
+!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 "BLI_blenlib.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 "BLI_blenlib.mak" CFG="BLI_blenlib - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "BLI_blenlib - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLI_blenlib - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLI_blenlib - Win32 MT DLL Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLI_blenlib - Win32 MT DLL Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLI_blenlib - Win32 Profile" (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)" == "BLI_blenlib - 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 "..\..\..\..\obj\windows\blender\blenlib"
+# 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 "..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\bpython\include" /I "..\..\..\source\blender\makesdna" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\blenlib\BLI_blenlib.lib"
+
+!ELSEIF "$(CFG)" == "BLI_blenlib - 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 "..\..\..\..\obj\windows\blender\blenlib\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\guardedalloc\include" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\bpython\include" /I "..\..\..\source\blender\makesdna" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /GZ /c
+# SUBTRACT CPP /Fr
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\blenlib\debug\BLI_blenlib.lib"
+
+!ELSEIF "$(CFG)" == "BLI_blenlib - Win32 MT DLL Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "BLI_blenlib___Win32_MT_DLL_Debug"
+# PROP BASE Intermediate_Dir "BLI_blenlib___Win32_MT_DLL_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\..\..\..\obj\windows\blender\blenlib\mtdll_debug"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\blender\blenlib\mtdll_debug"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /Gm /GX /ZI /Od /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\bpython\include" /I "..\..\..\source\blender\makesdna" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /GZ /c
+# ADD CPP /nologo /MDd /Gm /GX /ZI /Od /I "..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\bpython\include" /I "..\..\..\source\blender\makesdna" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /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 /out:"..\..\..\..\..\obj\windows\blender\blenlib\debug\BLI_blenlib.lib"
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "BLI_blenlib - Win32 MT DLL Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "BLI_blenlib___Win32_MT_DLL_Release"
+# PROP BASE Intermediate_Dir "BLI_blenlib___Win32_MT_DLL_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\..\..\..\obj\windows\blender\blenlib\mtdll"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\blender\blenlib\mtdll"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /GX /O2 /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\bpython\include" /I "..\..\..\source\blender\makesdna" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD CPP /nologo /MD /GX /O2 /I "..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\bpython\include" /I "..\..\..\source\blender\makesdna" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\..\obj\windows\blender\blenlib\BLI_blenlib.lib"
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "BLI_blenlib - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "BLI_blenlib___Win32_Profile"
+# PROP BASE Intermediate_Dir "BLI_blenlib___Win32_Profile"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "BLI_blenlib___Win32_Profile"
+# PROP Intermediate_Dir "BLI_blenlib___Win32_Profile"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\bpython\include" /I "..\..\..\source\blender\makesdna" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /O2 /I "..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\bpython\include" /I "..\..\..\source\blender\makesdna" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\blenlib\debug\BLI_blenlib.lib"
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\blenlib\profile\BLI_blenlib.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "BLI_blenlib - Win32 Release"
+# Name "BLI_blenlib - Win32 Debug"
+# Name "BLI_blenlib - Win32 MT DLL Debug"
+# Name "BLI_blenlib - Win32 MT DLL Release"
+# Name "BLI_blenlib - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenlib\intern\arithb.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenlib\intern\BLI_dynstr.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenlib\intern\BLI_ghash.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenlib\intern\BLI_linklist.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenlib\intern\BLI_memarena.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenlib\intern\dynlib.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenlib\intern\fileops.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenlib\intern\gsqueue.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenlib\intern\matrixops.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenlib\intern\noise.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenlib\intern\psfont.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenlib\intern\rand.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenlib\intern\rct.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenlib\intern\scanfill.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenlib\intern\storage.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenlib\intern\time.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenlib\intern\util.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenlib\intern\vectorops.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenlib\intern\winstuff.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenlib\BLI_arithb.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenlib\BLI_blenlib.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenlib\BLI_callbacks.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenlib\intern\BLI_callbacks.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenlib\BLI_editVert.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenlib\BLI_fileops.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenlib\intern\BLI_fileops.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenlib\BLI_ghash.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenlib\BLI_linklist.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenlib\BLI_listBase.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenlib\BLI_memarena.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenlib\BLI_memHead.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenlib\BLI_noise.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenlib\BLI_objfnt.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenlib\intern\BLI_objfnt.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenlib\BLI_objfnt_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenlib\BLI_packedFile_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenlib\BLI_psfont.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenlib\intern\BLI_psfont.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenlib\BLI_rct.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenlib\BLI_scanfill.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenlib\intern\BLI_scanfill.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenlib\BLI_storage.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenlib\intern\BLI_storage.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenlib\BLI_storage_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenlib\BLI_util.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenlib\intern\BLI_util.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenlib\BLI_vec_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenlib\BLI_winstuff.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenlib\matrixops.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenlib\MTC_matrixops.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenlib\MTC_vectorops.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenlib\PIL_dynlib.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenlib\PIL_time.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenlib\vectorops.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/blender/blenpluginapi/blenpluginapi/blenpluginapi.dsp b/projectfiles/blender/blenpluginapi/blenpluginapi/blenpluginapi.dsp
new file mode 100644
index 00000000000..37145fec967
--- /dev/null
+++ b/projectfiles/blender/blenpluginapi/blenpluginapi/blenpluginapi.dsp
@@ -0,0 +1,146 @@
+# Microsoft Developer Studio Project File - Name="blenpluginapi" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=blenpluginapi - Win32 Profile
+!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 "blenpluginapi.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 "blenpluginapi.mak" CFG="blenpluginapi - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "blenpluginapi - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "blenpluginapi - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "blenpluginapi - Win32 Profile" (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)" == "blenpluginapi - 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 "..\..\..\..\..\obj\windows\blender\blenpluginapi"
+# 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 "..\..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\..\source\blender" /I "..\..\..\..\source\blender\blenpluginapi" /I "..\..\..\..\source\blender\blenlib" /I "..\..\..\..\source\blender\imbuf" /I "..\..\..\..\source\blender\makesdna" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\..\obj\windows\blender\blenpluginapi.lib"
+
+!ELSEIF "$(CFG)" == "blenpluginapi - 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 "..\..\..\..\..\obj\windows\blender\blenpluginapi\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\guardedalloc\include" /I "..\..\..\..\source\blender" /I "..\..\..\..\source\blender\blenpluginapi" /I "..\..\..\..\source\blender\blenlib" /I "..\..\..\..\source\blender\imbuf" /I "..\..\..\..\source\blender\makesdna" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# SUBTRACT CPP /X
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\..\obj\windows\blender\debug\blenpluginapi.lib"
+
+!ELSEIF "$(CFG)" == "blenpluginapi - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "blenpluginapi___Win32_Profile"
+# PROP BASE Intermediate_Dir "blenpluginapi___Win32_Profile"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "blenpluginapi___Win32_Profile"
+# PROP Intermediate_Dir "blenpluginapi___Win32_Profile"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\..\source\blender" /I "..\..\..\..\source\blender\blenpluginapi" /I "..\..\..\..\source\blender\blenlib" /I "..\..\..\..\source\blender\imbuf" /I "..\..\..\..\source\blender\makesdna" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# SUBTRACT BASE CPP /X
+# ADD CPP /nologo /W3 /Gm /GX /Zi /I "..\..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\..\source\blender" /I "..\..\..\..\source\blender\blenpluginapi" /I "..\..\..\..\source\blender\blenlib" /I "..\..\..\..\source\blender\imbuf" /I "..\..\..\..\source\blender\makesdna" /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 /out:"..\..\..\..\obj\windows\blender\debug\blenpluginapi.lib"
+# ADD LIB32 /nologo /out:"..\..\..\..\..\obj\windows\blender\debug\blenpluginapi.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "blenpluginapi - Win32 Release"
+# Name "blenpluginapi - Win32 Debug"
+# Name "blenpluginapi - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\..\source\blender\blenpluginapi\intern\pluginapi.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\..\..\source\blender\blenpluginapi\documentation.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\blender\blenpluginapi\floatpatch.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\blender\blenpluginapi\iff.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\blender\blenpluginapi\plugin.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\blender\blenpluginapi\util.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/blender/bpython/frozen/BPY_frozen.dsp b/projectfiles/blender/bpython/frozen/BPY_frozen.dsp
new file mode 100644
index 00000000000..1b94bc5fc57
--- /dev/null
+++ b/projectfiles/blender/bpython/frozen/BPY_frozen.dsp
@@ -0,0 +1,296 @@
+# Microsoft Developer Studio Project File - Name="BPY_frozen" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=BPY_frozen - Win32 Profile
+!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 "BPY_frozen.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 "BPY_frozen.mak" CFG="BPY_frozen - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "BPY_frozen - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "BPY_frozen - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "BPY_frozen - Win32 Profile" (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)" == "BPY_frozen - 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 "..\..\..\..\..\obj\windows\blender\bpython\frozen"
+# 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 "..\..\..\..\lib\windows\python\include\python2.0" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD BASE RSC /l 0x413 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\..\obj\windows\blender\bpython\frozen\BPY_frozen.lib"
+
+!ELSEIF "$(CFG)" == "BPY_frozen - 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 "..\..\..\..\..\obj\windows\blender\bpython\frozen\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\python\include\python2.0" /D "WIN32" /D "_MBCS" /D "_LIB" /U "_DEBUG" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x413 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\..\obj\windows\blender\bpython\frozen\debug\BPY_frozen.lib"
+
+!ELSEIF "$(CFG)" == "BPY_frozen - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "BPY_frozen___Win32_Profile"
+# PROP BASE Intermediate_Dir "BPY_frozen___Win32_Profile"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "BPY_frozen___Win32_Profile"
+# PROP Intermediate_Dir "BPY_frozen___Win32_Profile"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\..\lib\windows\python\include\python2.0" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /O2 /I "..\..\..\..\lib\windows\python\include\python2.0" /D "WIN32" /D "_MBCS" /D "_LIB" /U "_DEBUG" /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 /out:"..\..\..\..\..\..\obj\windows\blender\bpython\frozen\debug\BPY_frozen.lib"
+# ADD LIB32 /nologo /out:"..\..\..\..\..\..\obj\windows\blender\bpython\frozen\debug\BPY_frozen.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "BPY_frozen - Win32 Release"
+# Name "BPY_frozen - Win32 Debug"
+# Name "BPY_frozen - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\..\source\blender\bpython\frozen\config.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\blender\bpython\frozen\frozen.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\blender\bpython\frozen\M_beta.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\blender\bpython\frozen\M_beta__Objects.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\blender\bpython\frozen\M_beta__Scenegraph.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\blender\bpython\frozen\M_blenderos.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\blender\bpython\frozen\M_Converter.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\blender\bpython\frozen\M_Converter__importer.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\blender\bpython\frozen\M_Converter__importer__VRMLimporter.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\blender\bpython\frozen\M_Converter__importloader.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\blender\bpython\frozen\M_copy.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\blender\bpython\frozen\M_copy_reg.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\blender\bpython\frozen\M_gzip.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\blender\bpython\frozen\M_mcf.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\blender\bpython\frozen\M_mcf__utils.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\blender\bpython\frozen\M_mcf__utils__hier_rx.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\blender\bpython\frozen\M_mcf__utils__hierobj.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\blender\bpython\frozen\M_mcf__utils__singletonlist.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\blender\bpython\frozen\M_repr.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\blender\bpython\frozen\M_simpleparse.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\blender\bpython\frozen\M_simpleparse__bootstrap.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\blender\bpython\frozen\M_simpleparse__generator.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\blender\bpython\frozen\M_string.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\blender\bpython\frozen\M_TextTools.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\blender\bpython\frozen\M_TextTools__Constants.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\blender\bpython\frozen\M_TextTools__Constants__Sets.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\blender\bpython\frozen\M_TextTools__Constants__TagTables.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\blender\bpython\frozen\M_TextTools__mxTextTools.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\blender\bpython\frozen\M_TextTools__TextTools.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\blender\bpython\frozen\M_types.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\blender\bpython\frozen\M_utils.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\blender\bpython\frozen\M_utils__quat.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\blender\bpython\frozen\M_utils__vect.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\blender\bpython\frozen\M_vrml.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\blender\bpython\frozen\M_vrml__basenodes.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\blender\bpython\frozen\M_vrml__fieldcoercian.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\blender\bpython\frozen\M_vrml__loader.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\blender\bpython\frozen\M_vrml__parser.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\blender\bpython\frozen\M_vrml__scenegraph.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\blender\bpython\frozen\M_vrml__utils.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\blender\bpython\frozen\M_vrml__utils__collapse.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\blender\bpython\frozen\M_vrml__utils__err.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\blender\bpython\frozen\M_vrml__utils__namespace.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\blender\bpython\frozen\M_vrml__utils__typeclasses.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/blender/bpython/intern/BPY_python/BPY_python.dsp b/projectfiles/blender/bpython/intern/BPY_python/BPY_python.dsp
new file mode 100644
index 00000000000..8bed8d0f783
--- /dev/null
+++ b/projectfiles/blender/bpython/intern/BPY_python/BPY_python.dsp
@@ -0,0 +1,275 @@
+# Microsoft Developer Studio Project File - Name="BPY_python" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=BPY_python - Win32 Profile
+!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 "BPY_python.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 "BPY_python.mak" CFG="BPY_python - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "BPY_python - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "BPY_python - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "BPY_python - Win32 Profile" (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)" == "BPY_python - 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 "..\..\..\..\..\..\obj\windows\blender\bpython"
+# 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 "..\..\..\..\..\lib\windows\bmfont\include" /I "..\..\..\..\..\lib\windows\python\include\python2.0" /I "..\..\..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\source\blender\renderconverter" /I "..\..\..\..\..\source\blender\render\extern\include" /I "..\..\..\..\..\source\blender\avi" /I "..\..\..\..\..\source\blender\blenloader" /I "..\..\..\..\..\source\blender" /I "..\..\..\..\..\source\blender\include" /I "..\..\..\..\..\source\blender\blenkernel" /I "..\..\..\..\..\source\blender\makesdna" /I "..\..\..\..\..\source\blender\blenlib" /I "..\..\..\..\..\source\blender\bpython\include" /I "..\..\..\..\..\source\blender\blenlib\intern" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# SUBTRACT CPP /X
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\..\..\obj\windows\blender\bpython\BPY_python.lib"
+
+!ELSEIF "$(CFG)" == "BPY_python - 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 "..\..\..\..\..\..\obj\windows\blender\bpython\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\python\include\python2.0" /I "..\..\..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\..\..\lib\windows\bmfont\include" /I "..\..\..\source\blender\renderconverter" /I "..\..\..\..\..\source\blender\render\extern\include" /I "..\..\..\..\..\source\blender\avi" /I "..\..\..\..\..\source\blender\blenloader" /I "..\..\..\..\..\source\blender" /I "..\..\..\..\..\source\blender\include" /I "..\..\..\..\..\source\blender\blenkernel" /I "..\..\..\..\..\source\blender\makesdna" /I "..\..\..\..\..\source\blender\blenlib" /I "..\..\..\..\..\source\blender\bpython\include" /I "..\..\..\..\..\source\blender\blenlib\intern" /D "WIN32" /D "_MBCS" /D "_LIB" /U "_DEBUG" /YX /J /FD /GZ /c
+# SUBTRACT CPP /u
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\..\..\obj\windows\blender\bpython\debug\BPY_python.lib"
+
+!ELSEIF "$(CFG)" == "BPY_python - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "BPY_python___Win32_Profile"
+# PROP BASE Intermediate_Dir "BPY_python___Win32_Profile"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "BPY_python___Win32_Profile"
+# PROP Intermediate_Dir "BPY_python___Win32_Profile"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\..\..\lib\windows\python\include\python1.5" /I "..\..\..\..\..\source\blender\render\extern\include" /I "..\..\..\..\..\source\blender\avi" /I "..\..\..\..\..\source\blender\blenloader" /I "..\..\..\..\..\source\blender" /I "..\..\..\..\..\source\blender\include" /I "..\..\..\..\..\source\blender\blenkernel" /I "..\..\..\..\..\source\blender\makesdna" /I "..\..\..\..\..\source\blender\blenlib" /I "..\..\..\..\..\source\blender\bpython\include" /I "..\..\..\..\..\source\blender\blenlib\intern" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /J /FD /GZ /c
+# SUBTRACT BASE CPP /X
+# ADD CPP /nologo /W3 /Gm /GX /Zi /O2 /I "..\..\..\..\..\lib\windows\python\include\python2.0" /I "..\..\..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\..\..\lib\windows\bmfont\include" /I "..\..\..\source\blender\renderconverter" /I "..\..\..\..\..\source\blender\render\extern\include" /I "..\..\..\..\..\source\blender\avi" /I "..\..\..\..\..\source\blender\blenloader" /I "..\..\..\..\..\source\blender" /I "..\..\..\..\..\source\blender\include" /I "..\..\..\..\..\source\blender\blenkernel" /I "..\..\..\..\..\source\blender\makesdna" /I "..\..\..\..\..\source\blender\blenlib" /I "..\..\..\..\..\source\blender\bpython\include" /I "..\..\..\..\..\source\blender\blenlib\intern" /D "WIN32" /D "_MBCS" /D "_LIB" /U "_DEBUG" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\..\..\obj\windows\blender\bpython\debug\BPY_python.lib"
+# ADD LIB32 /nologo /out:"..\..\..\..\..\..\obj\windows\blender\bpython\profile\BPY_python.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "BPY_python - Win32 Release"
+# Name "BPY_python - Win32 Debug"
+# Name "BPY_python - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\blender\bpython\intern\b_import.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\blender\bpython\intern\b_interface.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\blender\bpython\intern\BPY_constobject.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\blender\bpython\intern\BPY_image.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\blender\bpython\intern\BPY_ipo.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\blender\bpython\intern\BPY_links.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\blender\bpython\intern\BPY_main.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\blender\bpython\intern\BPY_object.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\blender\bpython\intern\BPY_scene.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\blender\bpython\intern\BPY_text.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\blender\bpython\intern\BPY_tools.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\blender\bpython\intern\opy_blender.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\blender\bpython\intern\opy_datablock.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\blender\bpython\intern\opy_draw.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\blender\bpython\intern\opy_matrix.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\blender\bpython\intern\opy_nmesh.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\blender\bpython\intern\opy_vector.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\blender\bpython\intern\opy_window.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\blender\bpython\intern\api.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\blender\bpython\intern\b_import.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\blender\bpython\intern\b_interface.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\blender\bpython\intern\BPY_constobject.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\blender\bpython\include\BPY_extern.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\blender\bpython\intern\BPY_listbase_macro.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\blender\bpython\intern\BPY_macros.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\blender\bpython\intern\BPY_main.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\blender\bpython\intern\BPY_modules.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\blender\bpython\include\BPY_objtypes.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\blender\bpython\intern\BPY_tools.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\blender\bpython\intern\BPY_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\blender\bpython\intern\BPY_window.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\blender\bpython\intern\opy_datablock.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\blender\bpython\intern\opy_nmesh.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\blender\bpython\intern\opy_vector.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\blender\bpython\intern\py_general.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\blender\bpython\intern\py_gui.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\blender\bpython\intern\py_object_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\blender\bpython\intern\py_objects.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/blender/glut/BL_glut.dsp b/projectfiles/blender/glut/BL_glut.dsp
new file mode 100644
index 00000000000..d9b5da7091e
--- /dev/null
+++ b/projectfiles/blender/glut/BL_glut.dsp
@@ -0,0 +1,324 @@
+# Microsoft Developer Studio Project File - Name="BL_glut" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=BL_glut - Win32 Profile
+!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 "BL_glut.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 "BL_glut.mak" CFG="BL_glut - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "BL_glut - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "BL_glut - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "BL_glut - Win32 Profile" (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)" == "BL_glut - 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 "..\..\..\..\obj\windows\blender\glut"
+# 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 "..\..\..\source\blender\\" /I "..\..\..\lib\windows\glut-3.7\include" /I "..\..\..\source\blender\glut-win" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\glut\BL_glut.lib"
+
+!ELSEIF "$(CFG)" == "BL_glut - 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 "..\..\..\..\obj\windows\blender\glut\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 "..\..\..\lib\windows\glut-3.7\include" /I "..\..\..\source\blender\glut-win" /I "..\..\..\source\blender\\" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /FR /YX /J /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\glut\debug\BL_glut.lib"
+
+!ELSEIF "$(CFG)" == "BL_glut - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "BL_glut___Win32_Profile"
+# PROP BASE Intermediate_Dir "BL_glut___Win32_Profile"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "BL_glut___Win32_Profile"
+# PROP Intermediate_Dir "BL_glut___Win32_Profile"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\lib\windows\glut-3.7\include" /I "..\..\..\source\blender\glut-win" /I "..\..\..\source\blender\\" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /O2 /I "..\..\..\lib\windows\glut-3.7\include" /I "..\..\..\source\blender\glut-win" /I "..\..\..\source\blender\\" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\glut\debug\BL_glut.lib"
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\glut\profile\BL_glut.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "BL_glut - Win32 Release"
+# Name "BL_glut - Win32 Debug"
+# Name "BL_glut - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE="..\..\..\source\blender\glut-win\glut_8x13.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\blender\glut-win\glut_9x15.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\blender\glut-win\glut_bitmap.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\blender\glut-win\glut_blender.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\blender\glut-win\glut_bwidth.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\blender\glut-win\glut_cindex.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\blender\glut-win\glut_cmap.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\blender\glut-win\glut_cursor.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\blender\glut-win\glut_dials.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\blender\glut-win\glut_draw.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\blender\glut-win\glut_dstr.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\blender\glut-win\glut_event.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\blender\glut-win\glut_ext.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\blender\glut-win\glut_fullscrn.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\blender\glut-win\glut_get.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\blender\glut-win\glut_hel10.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\blender\glut-win\glut_hel12.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\blender\glut-win\glut_hel18.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\blender\glut-win\glut_helb10.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\blender\glut-win\glut_helb12.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\blender\glut-win\glut_helb14.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\blender\glut-win\glut_helb8.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\blender\glut-win\glut_init.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\blender\glut-win\glut_input.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\blender\glut-win\glut_mesa.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\blender\glut-win\glut_modifier.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\blender\glut-win\glut_mroman.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\blender\glut-win\glut_overlay.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\blender\glut-win\glut_roman.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\blender\glut-win\glut_scr12.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\blender\glut-win\glut_scr14.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\blender\glut-win\glut_scr15.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\blender\glut-win\glut_shapes.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\blender\glut-win\glut_space.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\blender\glut-win\glut_stroke.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\blender\glut-win\glut_swap.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\blender\glut-win\glut_swidth.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\blender\glut-win\glut_tablet.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\blender\glut-win\glut_teapot.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\blender\glut-win\glut_tr10.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\blender\glut-win\glut_tr24.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\blender\glut-win\glut_util.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\blender\glut-win\glut_vidresize.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\blender\glut-win\glut_warp.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\blender\glut-win\glut_win.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\blender\glut-win\glut_winmisc.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\blender\glut-win\win32_glx.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\blender\glut-win\win32_menu.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\blender\glut-win\win32_util.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\blender\glut-win\win32_x11.c"
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\glut\blenderglut.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/blender/imbuf/BL_imbuf.dsp b/projectfiles/blender/imbuf/BL_imbuf.dsp
new file mode 100644
index 00000000000..9469488a38f
--- /dev/null
+++ b/projectfiles/blender/imbuf/BL_imbuf.dsp
@@ -0,0 +1,356 @@
+# Microsoft Developer Studio Project File - Name="BL_imbuf" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=BL_imbuf - Win32 Profile
+!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 "BL_imbuf.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 "BL_imbuf.mak" CFG="BL_imbuf - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "BL_imbuf - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "BL_imbuf - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "BL_imbuf - Win32 MT DLL Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "BL_imbuf - Win32 MT DLL Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "BL_imbuf - Win32 Profile" (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)" == "BL_imbuf - 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 "..\..\..\..\obj\windows\blender\imbuf"
+# 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 "..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\source\blender\avi" /I "..\..\..\source\blender\imbuf" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\include" /I "..\..\..\lib\windows\jpeg\include" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\lib\windows\png\include" /I "..\..\..\source\blender\makesdna" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\imbuf\BL_imbuf.lib"
+
+!ELSEIF "$(CFG)" == "BL_imbuf - 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 "..\..\..\..\obj\windows\blender\imbuf\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\guardedalloc\include" /I "..\..\..\source\blender\avi" /I "..\..\..\source\blender\imbuf" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\include" /I "..\..\..\lib\windows\jpeg\include" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\lib\windows\png\include" /I "..\..\..\source\blender\makesdna" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\imbuf\debug\BL_imbuf.lib"
+
+!ELSEIF "$(CFG)" == "BL_imbuf - Win32 MT DLL Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "BL_imbuf___Win32_MT_DLL_Debug"
+# PROP BASE Intermediate_Dir "BL_imbuf___Win32_MT_DLL_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\..\..\..\obj\windows\blender\imbuf\mtdll_debug"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\blender\imbuf\mtdll_debug"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /Gm /GX /ZI /Od /I "..\..\..\source\blender\avi" /I "..\..\..\source\blender\imbuf" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\include" /I "..\..\..\lib\windows\jpeg\include" /I "..\..\..\source\blender\makesdna" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /Gm /GX /ZI /Od /I "..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\source\blender\avi" /I "..\..\..\source\blender\imbuf" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\include" /I "..\..\..\lib\windows\jpeg\include" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\lib\windows\png\include" /I "..\..\..\source\blender\makesdna" /D "_DEBUG" /D "WIN32" /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 /out:"..\..\..\..\..\obj\windows\blender\imbuf\debug\BL_imbuf.lib"
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "BL_imbuf - Win32 MT DLL Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "BL_imbuf___Win32_MT_DLL_Release"
+# PROP BASE Intermediate_Dir "BL_imbuf___Win32_MT_DLL_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\..\..\..\obj\windows\blender\imbuf\mtdll"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\blender\imbuf\mtdll"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /GX /O2 /I "..\..\..\source\blender\avi" /I "..\..\..\source\blender\imbuf" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\include" /I "..\..\..\lib\windows\jpeg\include" /I "..\..\..\source\blender\makesdna" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD CPP /nologo /MD /GX /O2 /I "..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\source\blender\avi" /I "..\..\..\source\blender\imbuf" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\include" /I "..\..\..\lib\windows\jpeg\include" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\lib\windows\png\include" /I "..\..\..\source\blender\makesdna" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\..\obj\windows\blender\imbuf\BL_imbuf.lib"
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "BL_imbuf - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "BL_imbuf___Win32_Profile"
+# PROP BASE Intermediate_Dir "BL_imbuf___Win32_Profile"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "BL_imbuf___Win32_Profile"
+# PROP Intermediate_Dir "BL_imbuf___Win32_Profile"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\source\blender\avi" /I "..\..\..\source\blender\imbuf" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\include" /I "..\..\..\lib\windows\jpeg\include" /I "..\..\..\source\blender\makesdna" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /O2 /I "..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\source\blender\avi" /I "..\..\..\source\blender\imbuf" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\include" /I "..\..\..\lib\windows\jpeg\include" /I "..\..\..\lib\windows\png\include" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\makesdna" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\imbuf\debug\BL_imbuf.lib"
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\imbuf\profile\BL_imbuf.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "BL_imbuf - Win32 Release"
+# Name "BL_imbuf - Win32 Debug"
+# Name "BL_imbuf - Win32 MT DLL Debug"
+# Name "BL_imbuf - Win32 MT DLL Release"
+# Name "BL_imbuf - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\imbuf\intern\allocimbuf.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\imbuf\intern\amiga.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\imbuf\intern\anim.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\imbuf\intern\antialias.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\imbuf\intern\bitplanes.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\imbuf\intern\bmp_decode.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\imbuf\intern\cmap.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\imbuf\intern\cspace.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\imbuf\intern\data.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\imbuf\intern\dither.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\imbuf\intern\divers.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\imbuf\intern\filter.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\imbuf\intern\ham.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\imbuf\intern\hamx.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\imbuf\intern\iff.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\imbuf\intern\imageprocess.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\imbuf\intern\iris.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\imbuf\intern\jpeg.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\imbuf\intern\png_decode.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\imbuf\intern\png_encode.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\imbuf\intern\readimage.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\imbuf\intern\rectop.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\imbuf\intern\rotate.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\imbuf\intern\scaling.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\imbuf\intern\targa.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\imbuf\intern\util.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\imbuf\intern\writeimage.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\imbuf\intern\IMB_allocimbuf.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\imbuf\intern\IMB_amiga.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\imbuf\intern\IMB_bitplanes.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\imbuf\intern\IMB_bmp.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\imbuf\intern\IMB_cmap.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\imbuf\intern\IMB_divers.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\imbuf\intern\IMB_filter.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\imbuf\intern\IMB_ham.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\imbuf\intern\IMB_hamx.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\imbuf\intern\IMB_iff.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\imbuf\IMB_imbuf.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\imbuf\IMB_imbuf_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\imbuf\intern\IMB_iris.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\imbuf\intern\IMB_jpeg.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\imbuf\intern\IMB_png.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\imbuf\intern\IMB_targa.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\imbuf\intern\imbuf.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\imbuf\intern\imbuf_patch.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\imbuf\intern\matrix.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/blender/img/BL_img.dsp b/projectfiles/blender/img/BL_img.dsp
new file mode 100644
index 00000000000..5c28983acee
--- /dev/null
+++ b/projectfiles/blender/img/BL_img.dsp
@@ -0,0 +1,197 @@
+# Microsoft Developer Studio Project File - Name="BL_img" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=BL_img - Win32 Profile
+!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 "BL_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 "BL_img.mak" CFG="BL_img - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "BL_img - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "BL_img - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "BL_img - Win32 Profile" (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)" == "BL_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 "Release"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\blender\img"
+# 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 /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\img\BL_img.lib"
+
+!ELSEIF "$(CFG)" == "BL_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 "Debug"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\blender\img\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 "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /GZ /c
+# SUBTRACT CPP /Fr
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\img\debug\BL_img.lib"
+
+!ELSEIF "$(CFG)" == "BL_img - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "BL_img___Win32_Profile"
+# PROP BASE Intermediate_Dir "BL_img___Win32_Profile"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "BL_img___Win32_Profile"
+# PROP Intermediate_Dir "BL_img___Win32_Profile"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /O2 /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\img\debug\BL_img.lib"
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\img\profile\BL_img.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "BL_img - Win32 Release"
+# Name "BL_img - Win32 Debug"
+# Name "BL_img - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\img\intern\IMG_Api.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\img\intern\IMG_BrushRGBA32.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\img\intern\IMG_CanvasRGBA32.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\img\intern\IMG_Line.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\img\intern\IMG_Pixmap.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\img\intern\IMG_PixmapRGBA32.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\img\intern\IMG_Rect.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=..\..\..\source\blender\img\intern\IMG_BrushRGBA32.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\img\intern\IMG_CanvasRGBA32.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\img\intern\IMG_Color.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\img\intern\IMG_Line.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\img\intern\IMG_MemPtr.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\img\intern\IMG_Pixmap.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\img\intern\IMG_PixmapRGBA32.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\img\intern\IMG_Rect.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\img\intern\IMG_Types.h
+# End Source File
+# End Group
+# Begin Group "extern"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\img\IMG_Api.h
+# End Source File
+# End Group
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/blender/loader/BLO_loader.dsp b/projectfiles/blender/loader/BLO_loader.dsp
new file mode 100644
index 00000000000..312d56bf876
--- /dev/null
+++ b/projectfiles/blender/loader/BLO_loader.dsp
@@ -0,0 +1,208 @@
+# Microsoft Developer Studio Project File - Name="BLO_loader" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=BLO_loader - Win32 Profile
+!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 "BLO_loader.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 "BLO_loader.mak" CFG="BLO_loader - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "BLO_loader - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_loader - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_loader - Win32 MT DLL Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_loader - Win32 MT DLL Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "BLO_loader - Win32 Profile" (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)" == "BLO_loader - 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 "..\..\..\..\obj\windows\blender\loader"
+# 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 "..\..\..\source\blender\blenloader" /I "..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\source\blender\include" /I "..\..\..\source\blender\streamglue\\" /I "..\..\..\source\blender\readblenfile\\" /I "..\..\..\source\blender\writeblenfile\\" /I "..\..\..\source\blender\deflate\\" /I "..\..\..\source\blender\inflate\\" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\readblenfile" /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\blender\writestreamglue" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\blender\render\extern\include" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\bpython\include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\loader\BLO_loader.lib"
+
+!ELSEIF "$(CFG)" == "BLO_loader - 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 "..\..\..\..\obj\windows\blender\loader\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\guardedalloc\include" /I "..\..\..\source\blender\include" /I "..\..\..\source\blender\blenloader" /I "..\..\..\source\blender\streamglue\\" /I "..\..\..\source\blender\readblenfile\\" /I "..\..\..\source\blender\writeblenfile\\" /I "..\..\..\source\blender\deflate\\" /I "..\..\..\source\blender\inflate\\" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\readblenfile" /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\blender\writestreamglue" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\blender\render\extern\include" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\bpython\include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /GZ /c
+# SUBTRACT CPP /Fr
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\loader\debug\BLO_loader.lib"
+
+!ELSEIF "$(CFG)" == "BLO_loader - Win32 MT DLL Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "BLO_loader___Win32_MT_DLL_Debug"
+# PROP BASE Intermediate_Dir "BLO_loader___Win32_MT_DLL_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\..\..\..\obj\windows\blender\loader\mtdll_debug"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\blender\loader\mtdll_debug"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /Gm /GX /ZI /Od /I "..\..\..\source\blender\render\extern\include" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\bpython\include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /GZ /c
+# ADD CPP /nologo /MDd /Gm /GX /ZI /Od /I "..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\source\blender\include" /I "..\..\..\source\blender\blenloader" /I "..\..\..\source\blender\streamglue\\" /I "..\..\..\source\blender\readblenfile\\" /I "..\..\..\source\blender\writeblenfile\\" /I "..\..\..\source\blender\deflate\\" /I "..\..\..\source\blender\inflate\\" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\readblenfile" /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\blender\writestreamglue" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\blender\render\extern\include" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\bpython\include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /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 /out:"..\..\..\..\..\obj\windows\blender\loader\debug\BLO_loader.lib"
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "BLO_loader - Win32 MT DLL Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "BLO_loader___Win32_MT_DLL_Release"
+# PROP BASE Intermediate_Dir "BLO_loader___Win32_MT_DLL_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\..\..\..\obj\windows\blender\loader\mtdll"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\blender\loader\mtdll"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /GX /O2 /I "..\..\..\source\blender\render\extern\include" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\bpython\include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD CPP /nologo /MD /GX /O2 /I "..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\source\blender\include" /I "..\..\..\source\blender\blenloader" /I "..\..\..\source\blender\streamglue\\" /I "..\..\..\source\blender\readblenfile\\" /I "..\..\..\source\blender\writeblenfile\\" /I "..\..\..\source\blender\deflate\\" /I "..\..\..\source\blender\inflate\\" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\readblenfile" /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\blender\writestreamglue" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\blender\render\extern\include" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\bpython\include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\..\obj\windows\blender\loader\BLO_loader.lib"
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "BLO_loader - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "BLO_loader___Win32_Profile"
+# PROP BASE Intermediate_Dir "BLO_loader___Win32_Profile"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "BLO_loader___Win32_Profile"
+# PROP Intermediate_Dir "BLO_loader___Win32_Profile"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\blender\blenloader" /I "..\..\..\source\blender\render\extern\include" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\bpython\include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /O2 /I "..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\source\blender\include" /I "..\..\..\source\blender\blenloader" /I "..\..\..\source\blender\streamglue\\" /I "..\..\..\source\blender\readblenfile\\" /I "..\..\..\source\blender\writeblenfile\\" /I "..\..\..\source\blender\deflate\\" /I "..\..\..\source\blender\inflate\\" /I "..\..\..\lib\windows\zlib\include" /I "..\..\..\source\blender\readblenfile" /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\blender\writestreamglue" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\blender\render\extern\include" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\bpython\include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\loader\debug\BLO_loader.lib"
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\loader\profile\BLO_loader.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "BLO_loader - Win32 Release"
+# Name "BLO_loader - Win32 Debug"
+# Name "BLO_loader - Win32 MT DLL Debug"
+# Name "BLO_loader - Win32 MT DLL Release"
+# Name "BLO_loader - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenloader\intern\genfile.c
+# ADD CPP /I "..\..\..\source\blender"
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenloader\intern\readblenentry.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenloader\intern\readfile.c
+# ADD CPP /I "..\..\..\source\blender"
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenloader\intern\writefile.c
+# ADD CPP /I "..\..\..\source\blender"
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenloader\BLO_genfile.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenloader\BLO_readfile.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenloader\BLO_soundfile.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\streamglue\BLO_streamglue.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/blender/makesdna/DNA_makesdna.dsp b/projectfiles/blender/makesdna/DNA_makesdna.dsp
new file mode 100644
index 00000000000..cc95f44b567
--- /dev/null
+++ b/projectfiles/blender/makesdna/DNA_makesdna.dsp
@@ -0,0 +1,407 @@
+# Microsoft Developer Studio Project File - Name="DNA_makesdna" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=DNA_makesdna - Win32 Profile
+!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 "DNA_makesdna.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 "DNA_makesdna.mak" CFG="DNA_makesdna - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "DNA_makesdna - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "DNA_makesdna - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE "DNA_makesdna - Win32 MT DLL Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "DNA_makesdna - Win32 MT DLL Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE "DNA_makesdna - Win32 Profile" (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)" == "DNA_makesdna - 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 "..\..\..\source\blender\makesdna\intern"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\blender\makesdna"
+# 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 "..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo /o"DNA_makesdna.bsc"
+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 libguardedalloc.a BLI_blenlib.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 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 /pdb:"DNA_makesdna.pdb" /machine:I386 /nodefaultlib:"libc.lib" /libpath:"..\..\..\lib\windows\guardedalloc\lib" /libpath:"..\..\..\..\obj\windows\blender\blenlib"
+# SUBTRACT LINK32 /pdb:none
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PostBuild_Desc=Building DNA
+PostBuild_Cmds=CD ..\..\..\source\blender\makesdna\intern\ DNA_makesdna.exe dna.c
+# End Special Build Tool
+
+!ELSEIF "$(CFG)" == "DNA_makesdna - 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 "..\..\..\source\blender\makesdna\intern"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\blender\makesdna\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 "..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /J /FD /GZ /c
+# SUBTRACT CPP /Fr
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo /o"DNA_makesdna.bsc"
+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 libguardedalloc.a BLI_blenlib.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 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 /pdb:"DNA_makesdna.pdb" /debug /machine:I386 /nodefaultlib:"libc.lib" /pdbtype:sept /libpath:"..\..\..\lib\windows\guardedalloc\lib" /libpath:"..\..\..\..\obj\windows\blender\blenlib\debug"
+# SUBTRACT LINK32 /pdb:none
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PostBuild_Desc=Building DNA
+PostBuild_Cmds=CD ..\..\..\source\blender\makesdna\intern\ DNA_makesdna.exe dna.c
+# End Special Build Tool
+
+!ELSEIF "$(CFG)" == "DNA_makesdna - Win32 MT DLL Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "DNA_makesdna___Win32_MT_DLL_Release"
+# PROP BASE Intermediate_Dir "DNA_makesdna___Win32_MT_DLL_Release"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\..\..\source\blender\makesdna\intern"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\blender\makesdna\mtdll"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /J /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo /o"DNA_makesdna.bsc"
+# ADD BSC32 /nologo /o"DNA_makesdna.bsc"
+LINK32=link.exe
+# ADD BASE LINK32 BLI_blenlib.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 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 /pdb:"DNA_makesdna.pdb" /machine:I386 /out:"..\..\..\source\blender\makesdna\intern\DNA_makesdna.exe" /libpath:"..\..\..\..\obj\windows\blender\blenlib"
+# SUBTRACT BASE LINK32 /pdb:none
+# ADD LINK32 libguardedalloc.a 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 /pdb:"DNA_makesdna.pdb" /machine:I386 /nodefaultlib:"libc.lib" /libpath:"..\..\..\lib\windows\guardedalloc\lib" /libpath:"..\..\..\..\obj\windows\blender\blenlib"
+# SUBTRACT LINK32 /pdb:none
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PostBuild_Cmds=CD ..\..\..\source\blender\makesdna\intern\ DNA_makesdna.exe dna.c
+# End Special Build Tool
+
+!ELSEIF "$(CFG)" == "DNA_makesdna - Win32 MT DLL Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "DNA_makesdna___Win32_MT_DLL_Debug"
+# PROP BASE Intermediate_Dir "DNA_makesdna___Win32_MT_DLL_Debug"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\..\..\source\blender\makesdna\intern"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\blender\makesdna\mtdll_debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /J /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /J /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo /o"DNA_makesdna.bsc"
+# ADD BSC32 /nologo /o"DNA_makesdna.bsc"
+LINK32=link.exe
+# ADD BASE LINK32 BLI_blenlib.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 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 /pdb:"DNA_makesdna.pdb" /debug /machine:I386 /out:"..\..\..\source\blender\makesdna\debug\DNA_makesdna.exe" /pdbtype:sept /libpath:"..\..\..\..\obj\windows\blender\blenlib\debug"
+# SUBTRACT BASE LINK32 /pdb:none
+# ADD LINK32 libguardedalloc.a 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 /pdb:"DNA_makesdna.pdb" /debug /machine:I386 /pdbtype:sept /libpath:"..\..\..\lib\windows\guardedalloc\lib"
+# SUBTRACT LINK32 /pdb:none
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PostBuild_Cmds=CD ..\..\..\source\blender\makesdna\intern\ DNA_makesdna.exe dna.c
+# End Special Build Tool
+
+!ELSEIF "$(CFG)" == "DNA_makesdna - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "DNA_makesdna___Win32_Profile0"
+# PROP BASE Intermediate_Dir "DNA_makesdna___Win32_Profile0"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "DNA_makesdna___Win32_Profile0"
+# PROP Intermediate_Dir "DNA_makesdna___Win32_Profile0"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /J /FD /GZ /c
+# ADD CPP /nologo /W3 /GX /O2 /I "..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo /o"DNA_makesdna.bsc"
+# ADD BSC32 /nologo /o"DNA_makesdna.bsc"
+LINK32=link.exe
+# ADD BASE LINK32 BLI_blenlib.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 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 /pdb:"DNA_makesdna.pdb" /debug /machine:I386 /pdbtype:sept /libpath:"..\..\..\..\obj\windows\blender\blenlib\debug"
+# SUBTRACT BASE LINK32 /pdb:none
+# ADD LINK32 libguardedalloc.a BLI_blenlib.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 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 /pdb:"DNA_makesdna.pdb" /debug /machine:I386 /pdbtype:sept /libpath:"..\..\..\lib\windows\guardedalloc\lib" /libpath:"..\..\..\..\obj\windows\blender\blenlib\debug"
+# SUBTRACT LINK32 /pdb:none
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PostBuild_Desc=Building DNA
+PostBuild_Cmds=CD ..\..\..\source\blender\makesdna\intern\ DNA_makesdna.exe dna.c
+# End Special Build Tool
+
+!ENDIF
+
+# Begin Target
+
+# Name "DNA_makesdna - Win32 Release"
+# Name "DNA_makesdna - Win32 Debug"
+# Name "DNA_makesdna - Win32 MT DLL Release"
+# Name "DNA_makesdna - Win32 MT DLL Debug"
+# Name "DNA_makesdna - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\makesdna\intern\makesdna.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\makesdna\DNA_action_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\makesdna\DNA_actuator_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\makesdna\DNA_armature_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\makesdna\DNA_base_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\makesdna\DNA_bgpic_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\makesdna\DNA_camera_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\makesdna\DNA_controller_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\makesdna\DNA_curve_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\makesdna\DNA_effect_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\makesdna\DNA_fileglobal_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\makesdna\DNA_group_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\makesdna\DNA_ID.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\makesdna\DNA_ika_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\makesdna\DNA_image_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\makesdna\DNA_ipo_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\makesdna\DNA_key_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\makesdna\DNA_lamp_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\makesdna\DNA_lattice_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\makesdna\DNA_listBase.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\makesdna\DNA_material_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\makesdna\DNA_memHead.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\makesdna\DNA_mesh_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\makesdna\DNA_meta_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\makesdna\DNA_nla_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\makesdna\DNA_object_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\makesdna\DNA_old_game.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\makesdna\DNA_oops_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\makesdna\DNA_packedFile_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\makesdna\DNA_property_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\makesdna\DNA_radio_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\makesdna\DNA_scene_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\makesdna\DNA_screen_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\makesdna\DNA_scriptlink_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\makesdna\DNA_sdna_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\makesdna\DNA_sensor_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\makesdna\DNA_sequence_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\makesdna\DNA_sound_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\makesdna\DNA_space_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\makesdna\DNA_spaceimasel_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\makesdna\DNA_text_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\makesdna\DNA_texture_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\makesdna\DNA_userdef_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\makesdna\DNA_vec_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\makesdna\DNA_vfont_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\makesdna\DNA_view2d_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\makesdna\DNA_view3d_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\makesdna\DNA_wave_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\makesdna\DNA_world_types.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/projectfiles/blender/misc/BL_misc.dsp b/projectfiles/blender/misc/BL_misc.dsp
new file mode 100644
index 00000000000..42ec7b34f83
--- /dev/null
+++ b/projectfiles/blender/misc/BL_misc.dsp
@@ -0,0 +1,129 @@
+# Microsoft Developer Studio Project File - Name="BL_misc" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=BL_misc - Win32 Profile
+!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 "BL_misc.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 "BL_misc.mak" CFG="BL_misc - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "BL_misc - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "BL_misc - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "BL_misc - Win32 Profile" (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)" == "BL_misc - 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 "..\..\..\..\obj\windows\blender\misc"
+# 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 "..\..\..\source\blender\imbuf" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\include" /I "..\..\..\source\blender" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\blender\render\intern\include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\misc\BL_misc.lib"
+
+!ELSEIF "$(CFG)" == "BL_misc - 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 "..\..\..\..\obj\windows\blender\misc\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 "..\..\..\source\blender\imbuf" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\include" /I "..\..\..\source\blender" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\blender\render\intern\include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /GZ /c
+# SUBTRACT CPP /Fr
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\misc\debug\BL_misc.lib"
+
+!ELSEIF "$(CFG)" == "BL_misc - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "BL_misc___Win32_Profile"
+# PROP BASE Intermediate_Dir "BL_misc___Win32_Profile"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "BL_misc___Win32_Profile"
+# PROP Intermediate_Dir "BL_misc___Win32_Profile"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\source\blender\imbuf" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\include" /I "..\..\..\source\blender" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\blender\render\intern\include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /O2 /I "..\..\..\source\blender\imbuf" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\include" /I "..\..\..\source\blender" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\blender\render\intern\include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\misc\debug\BL_misc.lib"
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\misc\profile\BL_misc.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "BL_misc - Win32 Release"
+# Name "BL_misc - Win32 Debug"
+# Name "BL_misc - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\misc\blendertimer.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\misc\blendertimer.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/blender/radiosity/BRA_radiosity.dsp b/projectfiles/blender/radiosity/BRA_radiosity.dsp
new file mode 100644
index 00000000000..f529e812fd9
--- /dev/null
+++ b/projectfiles/blender/radiosity/BRA_radiosity.dsp
@@ -0,0 +1,153 @@
+# Microsoft Developer Studio Project File - Name="BRA_radiosity" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=BRA_radiosity - Win32 Profile
+!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 "BRA_radiosity.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 "BRA_radiosity.mak" CFG="BRA_radiosity - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "BRA_radiosity - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "BRA_radiosity - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "BRA_radiosity - Win32 Profile" (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)" == "BRA_radiosity - 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 "..\..\..\..\obj\windows\blender\radiosity"
+# 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 "..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\source\blender\imbuf" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\render\extern\include" /I "..\..\..\source\blender\radiosity\extern\include" /I "..\..\..\source\blender" /I "..\..\..\source\blender\include" /I "..\..\..\source\blender\misc" /I "..\..\..\source\blender\makesdna" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\radiosity\BRA_radiosity.lib"
+
+!ELSEIF "$(CFG)" == "BRA_radiosity - 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 "..\..\..\..\obj\windows\blender\radiosity\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\guardedalloc\include" /I "..\..\..\source\blender\imbuf" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\render\extern\include" /I "..\..\..\source\blender\radiosity\extern\include" /I "..\..\..\source\blender" /I "..\..\..\source\blender\include" /I "..\..\..\source\blender\misc" /I "..\..\..\source\blender\makesdna" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /GZ /c
+# SUBTRACT CPP /Fr
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\radiosity\debug\BRA_radiosity.lib"
+
+!ELSEIF "$(CFG)" == "BRA_radiosity - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "BRA_radiosity___Win32_Profile"
+# PROP BASE Intermediate_Dir "BRA_radiosity___Win32_Profile"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "BRA_radiosity___Win32_Profile"
+# PROP Intermediate_Dir "BRA_radiosity___Win32_Profile"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\source\blender\imbuf" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\render\extern\include" /I "..\..\..\source\blender\radiosity\extern\include" /I "..\..\..\source\blender" /I "..\..\..\source\blender\include" /I "..\..\..\source\blender\misc" /I "..\..\..\source\blender\makesdna" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /O2 /I "..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\source\blender\imbuf" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\render\extern\include" /I "..\..\..\source\blender\radiosity\extern\include" /I "..\..\..\source\blender" /I "..\..\..\source\blender\include" /I "..\..\..\source\blender\misc" /I "..\..\..\source\blender\makesdna" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\radiosity\debug\BRA_radiosity.lib"
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\radiosity\profile\BRA_radiosity.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "BRA_radiosity - Win32 Release"
+# Name "BRA_radiosity - Win32 Debug"
+# Name "BRA_radiosity - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\radiosity\intern\source\raddisplay.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\radiosity\intern\source\radfactors.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\radiosity\intern\source\radio.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\radiosity\intern\source\radnode.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\radiosity\intern\source\radpostprocess.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\radiosity\intern\source\radpreprocess.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\radiosity\extern\include\radio.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\radiosity\extern\include\radio_types.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/blender/render/BRE_render.dsp b/projectfiles/blender/render/BRE_render.dsp
new file mode 100644
index 00000000000..5a58246d4b6
--- /dev/null
+++ b/projectfiles/blender/render/BRE_render.dsp
@@ -0,0 +1,325 @@
+# Microsoft Developer Studio Project File - Name="BRE_render" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=BRE_render - Win32 Profile
+!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 "BRE_render.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 "BRE_render.mak" CFG="BRE_render - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "BRE_render - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "BRE_render - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "BRE_render - Win32 Profile" (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)" == "BRE_render - 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 "..\..\..\..\obj\windows\blender\render"
+# 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 "..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\imbuf" /I "..\..\..\source\blender\blenloader" /I "..\..\..\source\blender\include" /I "..\..\..\source\blender\misc" /I "..\..\..\source\kernel" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\radiosity\extern\include" /I "..\..\..\source\blender\render\intern\include" /I "..\..\..\source\blender\render\extern\include" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\blender\bpython\include" /I "..\..\..\source\blender" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\render\BRE_render.lib"
+
+!ELSEIF "$(CFG)" == "BRE_render - 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 "..\..\..\..\obj\windows\blender\render\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\guardedalloc\include" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\imbuf" /I "..\..\..\source\blender\blenloader" /I "..\..\..\source\blender\include" /I "..\..\..\source\blender\misc" /I "..\..\..\source\kernel" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\radiosity\extern\include" /I "..\..\..\source\blender\render\intern\include" /I "..\..\..\source\blender\render\extern\include" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\blender\bpython\include" /I "..\..\..\source\blender" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /GZ /c
+# SUBTRACT CPP /Fr
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\render\debug\BRE_render.lib"
+
+!ELSEIF "$(CFG)" == "BRE_render - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "BRE_render___Win32_Profile"
+# PROP BASE Intermediate_Dir "BRE_render___Win32_Profile"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "BRE_render___Win32_Profile"
+# PROP Intermediate_Dir "BRE_render___Win32_Profile"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\source\blender\imbuf" /I "..\..\..\source\blender\blenloader" /I "..\..\..\source\blender\include" /I "..\..\..\source\blender\misc" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\radiosity\extern\include" /I "..\..\..\source\blender\render\intern\include" /I "..\..\..\source\blender\render\extern\include" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\blender\bpython\include" /I "..\..\..\source\blender" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /O2 /I "..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\kernel\gen_messaging" /I "..\..\..\source\blender\imbuf" /I "..\..\..\source\blender\blenloader" /I "..\..\..\source\blender\include" /I "..\..\..\source\blender\misc" /I "..\..\..\source\kernel" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\radiosity\extern\include" /I "..\..\..\source\blender\render\intern\include" /I "..\..\..\source\blender\render\extern\include" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\blender\bpython\include" /I "..\..\..\source\blender" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\render\debug\BRE_render.lib"
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\render\profile\BRE_render.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "BRE_render - Win32 Release"
+# Name "BRE_render - Win32 Debug"
+# Name "BRE_render - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\render\intern\source\edgeRender.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\render\intern\source\envmap.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\render\intern\source\errorHandler.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\render\intern\source\gammaCorrectionTables.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\render\intern\source\initrender.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\render\intern\source\jitter.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\render\intern\source\outerRenderLoop.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\render\intern\source\pixelblending.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\render\intern\source\pixelshading.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\render\intern\source\RE_basicShadowBuffer.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\render\intern\source\RE_callbacks.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\render\intern\source\RE_DummyShadowBuffer.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\render\intern\source\rendercore.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\render\intern\source\renderdatabase.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\render\intern\source\renderHelp.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\render\intern\source\renderPreAndPost.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\render\intern\source\shadbuf.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\render\intern\source\shadowBuffer.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\render\intern\source\vanillaRenderPipe.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\render\intern\source\zbuf.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\render\intern\source\zbufferdatastruct.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\render\intern\include\edgeRender.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\render\intern\include\envmap.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\render\intern\include\errorHandler.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\render\intern\include\gammaCorrectionTables.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\render\intern\include\initrender.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\render\intern\include\jitter.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\render\intern\include\old_zbuffer_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\render\intern\include\outerRenderLoop.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\render\intern\include\pixelblending.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\render\intern\include\pixelblending_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\render\intern\include\pixelshading.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\render\intern\include\RE_basicShadowBuffer.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\render\intern\include\RE_callbacks.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\render\intern\include\RE_DummyShadowBuffer.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\render\intern\include\RE_ShadowBuffer.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\render\intern\include\rendercore.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\render\intern\include\rendercore_int.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\render\intern\include\renderHelp.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\render\intern\include\renderPreAndPost.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\render\intern\include\shadbuf.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\render\intern\include\shadowBuffer.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\render\intern\include\texture.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\render\intern\include\vanillaRenderPipe.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\render\intern\include\vanillaRenderPipe_int.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\render\intern\include\vanillaRenderPipe_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\render\intern\include\zbuf.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\render\intern\include\zbuf_int.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\render\intern\include\zbuf_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\render\intern\include\zbufferdatastruct.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\render\intern\include\zbufferdatastruct_types.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/blender/renderconverter/BRE_renderconverter.dsp b/projectfiles/blender/renderconverter/BRE_renderconverter.dsp
new file mode 100644
index 00000000000..627ffb7631c
--- /dev/null
+++ b/projectfiles/blender/renderconverter/BRE_renderconverter.dsp
@@ -0,0 +1,128 @@
+# Microsoft Developer Studio Project File - Name="BRE_renderconverter" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=BRE_renderconverter - Win32 Profile
+!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 "BRE_renderconverter.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 "BRE_renderconverter.mak" CFG="BRE_renderconverter - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "BRE_renderconverter - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "BRE_renderconverter - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "BRE_renderconverter - Win32 Profile" (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)" == "BRE_renderconverter - 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 "..\..\..\..\obj\windows\blender\renderconverter"
+# 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 "..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\source\blender\bpython\include" /I "..\..\..\source\blender\misc" /I "..\..\..\source\blender\renderconverter" /I "..\..\..\source\blender\include" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\render\extern\include" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /J /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:"..\..\..\..\obj\windows\blender\renderconverter\BRE_renderconverter.lib"
+
+!ELSEIF "$(CFG)" == "BRE_renderconverter - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "BRE_renderconverter___Win32_Debug"
+# PROP BASE Intermediate_Dir "BRE_renderconverter___Win32_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\blender\render\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\guardedalloc\include" /I "..\..\..\source\blender\bpython\include" /I "..\..\..\source\blender\misc" /I "..\..\..\source\blender\renderconverter" /I "..\..\..\source\blender\include" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\render\extern\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /J /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:"..\..\..\..\obj\windows\blender\renderconverter\debug\BRE_renderconverter.lib"
+
+!ELSEIF "$(CFG)" == "BRE_renderconverter - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "BRE_renderconverter___Win32_Profile"
+# PROP BASE Intermediate_Dir "BRE_renderconverter___Win32_Profile"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "BRE_renderconverter___Win32_Profile"
+# PROP Intermediate_Dir "BRE_renderconverter___Win32_Profile"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\source\blender\bpython\include" /I "..\..\..\source\blender\misc" /I "..\..\..\source\blender\renderconverter" /I "..\..\..\source\blender\include" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\render\extern\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /I "..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\source\blender\bpython\include" /I "..\..\..\source\blender\misc" /I "..\..\..\source\blender\renderconverter" /I "..\..\..\source\blender\include" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\render\extern\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /J /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 /out:"..\..\..\..\obj\windows\blender\renderconverter\debug\BRE_renderconverter.lib"
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\renderconverter\debug\BRE_renderconverter.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "BRE_renderconverter - Win32 Release"
+# Name "BRE_renderconverter - Win32 Debug"
+# Name "BRE_renderconverter - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\renderconverter\intern\convertBlenderScene.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\renderconverter\RE_renderconverter.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/blender/renderui/BRE_renderui.dsp b/projectfiles/blender/renderui/BRE_renderui.dsp
new file mode 100644
index 00000000000..19d6d024727
--- /dev/null
+++ b/projectfiles/blender/renderui/BRE_renderui.dsp
@@ -0,0 +1,124 @@
+# Microsoft Developer Studio Project File - Name="BRE_renderui" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=BRE_renderui - Win32 Profile
+!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 "BRE_renderui.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 "BRE_renderui.mak" CFG="BRE_renderui - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "BRE_renderui - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "BRE_renderui - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "BRE_renderui - Win32 Profile" (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)" == "BRE_renderui - 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 "..\..\..\..\obj\windows\blender\renderui"
+# 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 "..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\source\blender\renderui" /I "..\..\..\source\blender" /I "..\..\..\source\blender\bpython\include" /I "..\..\..\source\blender\misc" /I "..\..\..\source\blender\renderconverter" /I "..\..\..\source\blender\include" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\render\extern\include" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /J /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:"..\..\..\..\obj\windows\blender\renderui\BRE_renderui.lib"
+
+!ELSEIF "$(CFG)" == "BRE_renderui - 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 "..\..\..\..\obj\windows\blender\renderui"
+# 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\guardedalloc\include" /I "..\..\..\source\blender\renderui" /I "..\..\..\source\blender" /I "..\..\..\source\blender\bpython\include" /I "..\..\..\source\blender\misc" /I "..\..\..\source\blender\renderconverter" /I "..\..\..\source\blender\include" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\render\extern\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /J /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:"..\..\..\..\obj\windows\blender\renderui\debug\BRE_renderui.lib"
+
+!ELSEIF "$(CFG)" == "BRE_renderui - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "BRE_renderui___Win32_Profile"
+# PROP BASE Intermediate_Dir "BRE_renderui___Win32_Profile"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "BRE_renderui___Win32_Profile"
+# PROP Intermediate_Dir "BRE_renderui___Win32_Profile"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\source\blender\renderui" /I "..\..\..\source\blender" /I "..\..\..\source\blender\bpython\include" /I "..\..\..\source\blender\misc" /I "..\..\..\source\blender\renderconverter" /I "..\..\..\source\blender\include" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\render\extern\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /I "..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\source\blender\renderui" /I "..\..\..\source\blender" /I "..\..\..\source\blender\bpython\include" /I "..\..\..\source\blender\misc" /I "..\..\..\source\blender\renderconverter" /I "..\..\..\source\blender\include" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\render\extern\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /J /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 /out:"..\..\..\..\obj\windows\blender\renderui\debug\BRE_renderui.lib"
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\renderui\debug\BRE_renderui.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "BRE_renderui - Win32 Release"
+# Name "BRE_renderui - Win32 Debug"
+# Name "BRE_renderui - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\renderui\RE_renderui.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/blender/src/BL_src.dsp b/projectfiles/blender/src/BL_src.dsp
new file mode 100644
index 00000000000..b41ed50162f
--- /dev/null
+++ b/projectfiles/blender/src/BL_src.dsp
@@ -0,0 +1,470 @@
+# Microsoft Developer Studio Project File - Name="BL_src" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=BL_src - Win32 Profile
+!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 "BL_src.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 "BL_src.mak" CFG="BL_src - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "BL_src - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "BL_src - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "BL_src - Win32 Profile" (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)" == "BL_src - 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 "..\..\..\..\obj\windows\blender\src"
+# 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 "..\..\..\source\blender\renderui" /I "..\..\..\source\gameengine\soundsystem\\" /I "..\..\..\lib\windows\python\include\python2.0\\" /I "..\..\..\lib\windows\bmfont\include" /I "..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\source\blender\renderconverter" /I "..\..\..\source\blender\verify" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\gameengine\soundsystem\snd_openal" /I "..\..\..\source\blender\imbuf" /I "..\..\..\source\blender\blenloader" /I "..\..\..\source\kernel\gen_system" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\misc" /I "..\..\..\source\blender\bpython\include" /I "..\..\..\source\blender\radiosity\extern\include" /I "..\..\..\source\blender\render\extern\include" /I "..\..\..\source\blender\include" /I "..\..\..\source\blender" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\gameengine\network" /I "..\..\..\lib\windows\decimation\include" /I "..\..\..\source\blender\blenpluginapi\\" /I "..\..\..\lib\windows\blenkey\include" /I "..\..\..\lib\windows\ghost\include" /I "..\..\..\lib\windows\bsp\include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "_CONSOLE" /D "NAN_GAME" /D "GAME" /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\src\BL_src.lib"
+
+!ELSEIF "$(CFG)" == "BL_src - 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 "..\..\..\..\obj\windows\blender\src\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 "..\..\..\source\blender\renderui" /I "..\..\..\source\gameengine\soundsystem\\" /I "..\..\..\lib\windows\python\include\python2.0\\" /I "..\..\..\lib\windows\bmfont\include" /I "..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\source\blender\renderconverter" /I "..\..\..\source\blender\verify" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\gameengine\soundsystem\snd_openal" /I "..\..\..\source\blender\imbuf" /I "..\..\..\source\blender\blenloader" /I "..\..\..\source\kernel\gen_system" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\misc" /I "..\..\..\source\blender\bpython\include" /I "..\..\..\source\blender\radiosity\extern\include" /I "..\..\..\source\blender\render\extern\include" /I "..\..\..\source\blender\include" /I "..\..\..\source\blender" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\gameengine\network" /I "..\..\..\lib\windows\decimation\include" /I "..\..\..\source\blender\blenpluginapi\\" /I "..\..\..\lib\windows\blenkey\include" /I "..\..\..\lib\windows\ghost\include" /I "..\..\..\lib\windows\bsp\include" /D "WIN32" /D "_MBCS" /D "_LIB" /D "_CONSOLE" /D "NAN_GAME" /D "GAME" /U "_DEBUG" /J /FD /GZ /c
+# SUBTRACT CPP /Fr
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\src\debug\BL_src.lib"
+
+!ELSEIF "$(CFG)" == "BL_src - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "BL_src___Win32_Profile"
+# PROP BASE Intermediate_Dir "BL_src___Win32_Profile"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "BL_src___Win32_Profile"
+# PROP Intermediate_Dir "BL_src___Win32_Profile"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\source\gameengine\soundsystem" /I "..\..\..\source\gameengine\soundsystem\snd_openal" /I "..\..\..\source\blender\imbuf" /I "..\..\..\source\blender\blenloader" /I "..\..\..\source\kernel\gen_system" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\misc" /I "..\..\..\source\blender\bpython\include" /I "..\..\..\source\blender\radiosity\extern\include" /I "..\..\..\source\blender\render\extern\include" /I "..\..\..\source\blender\include" /I "..\..\..\source\blender" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\gameengine\network" /I "..\..\..\lib\windows\decimation\include" /I "..\..\..\source\blender\blenpluginapi\\" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "_CONSOLE" /D "NAN_GAME" /D "GAME" /J /FD /GZ /c
+# SUBTRACT BASE CPP /Fr /YX
+# ADD CPP /nologo /W3 /Gm /GX /Zi /O2 /I "..\..\..\source\gameengine\soundsystem" /I "..\..\..\lib\windows\python\include\python2.0" /I "..\..\..\lib\windows\bmfont\include" /I "..\..\..\source\blender\renderui" /I "..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\source\blender\renderconverter" /I "..\..\..\source\blender\verify" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\gameengine\soundsystem\snd_openal" /I "..\..\..\source\blender\imbuf" /I "..\..\..\source\blender\blenloader" /I "..\..\..\source\kernel\gen_system" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\misc" /I "..\..\..\source\blender\bpython\include" /I "..\..\..\source\blender\radiosity\extern\include" /I "..\..\..\source\blender\render\extern\include" /I "..\..\..\source\blender\include" /I "..\..\..\source\blender" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\gameengine\network" /I "..\..\..\lib\windows\decimation\include" /I "..\..\..\source\blender\blenpluginapi\\" /I "..\..\..\lib\windows\blenkey\include" /I "..\..\..\lib\windows\ghost\include" /D "WIN32" /D "_MBCS" /D "_LIB" /D "_CONSOLE" /D "NAN_GAME" /D "GAME" /U "_DEBUG" /J /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\src\debug\BL_src.lib"
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\src\profile\BL_src.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "BL_src - Win32 Release"
+# Name "BL_src - Win32 Debug"
+# Name "BL_src - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\B.blend.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\Bfont.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\blenderbuttons.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\booleanops.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\booleanops_mesh.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\buttons.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\cmap.tga.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\cmovie.tga.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\makesdna\intern\dna.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\drawaction.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\drawimage.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\drawimasel.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\drawipo.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\drawmesh.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\drawnla.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\drawobject.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\drawoops.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\drawscene.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\drawseq.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\drawsound.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\drawtext.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\drawview.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\edit.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\editaction.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\editarmature.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\editconstraint.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\editcurve.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\editdeform.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\editface.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\editfont.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\editgroup.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\editika.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\editimasel.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\editipo.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\editkey.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\editlattice.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\editmball.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\editmesh.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\editnla.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\editobject.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\editoops.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\editsca.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\editscreen.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\editseq.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\editsima.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\editsound.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\editview.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\eventdebug.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\filesel.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\ghostwinlay.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\glutil.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\headerbuttons.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\imasel.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\interface.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\isect.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\keyval.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\mainqueue.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\mywindow.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\oops.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\osx_creator_splash.jpg.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\playanim.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\blenpluginapi\intern\pluginapi.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\poseobject.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\previewrender.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\renderwin.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\resources.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\scrarea.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\screendump.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\sequence.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\space.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\spacetypes.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\swapbuffers.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\toets.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\toolbox.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\unix_creator_splash.jpg.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\usiblender.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\view.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\vpaint.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\windows_creator_splash.jpg.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\writeavicodec.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\writeimage.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\writemovie.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\include\BIF_previewrender.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\include\BIF_resources.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\include\BIF_spacetypes.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\sound.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\winlay.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/blender/src/BL_src_cre.dsp b/projectfiles/blender/src/BL_src_cre.dsp
new file mode 100644
index 00000000000..f5296032a26
--- /dev/null
+++ b/projectfiles/blender/src/BL_src_cre.dsp
@@ -0,0 +1,129 @@
+# Microsoft Developer Studio Project File - Name="BL_src_cre" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=BL_src_cre - Win32 Profile
+!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 "BL_src_cre.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 "BL_src_cre.mak" CFG="BL_src_cre - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "BL_src_cre - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "BL_src_cre - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "BL_src_cre - Win32 Profile" (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)" == "BL_src_cre - 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 "..\..\..\..\obj\windows\blender\src_cre"
+# 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 "..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\source\blender\renderui" /I "..\..\..\source\gameengine\soundsystem\\" /I "..\..\..\lib\windows\python\include\python2.0\\" /I "..\..\..\source\blender\renderconverter" /I "..\..\..\source\blender\verify" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\gameengine\soundsystem\snd_openal" /I "..\..\..\source\blender\imbuf" /I "..\..\..\source\blender\blenloader" /I "..\..\..\source\kernel\gen_system" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\misc" /I "..\..\..\source\blender\bpython\include" /I "..\..\..\source\blender\radiosity\extern\include" /I "..\..\..\source\blender\render\extern\include" /I "..\..\..\source\blender\include" /I "..\..\..\source\blender" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\gameengine\network" /I "..\..\..\lib\windows\decimation\include" /I "..\..\..\source\blender\blenpluginapi\\" /I "..\..\..\lib\windows\blenkey\include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "_CONSOLE" /D "NAN_GAME" /D "GAME" /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\src\BL_src_cre.lib"
+
+!ELSEIF "$(CFG)" == "BL_src_cre - 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 "..\..\..\..\obj\windows\blender\src_cre\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\guardedalloc\include" /I "..\..\..\source\blender\renderui" /I "..\..\..\source\gameengine\soundsystem\\" /I "..\..\..\lib\windows\python\include\python2.0\\" /I "..\..\..\source\blender\renderconverter" /I "..\..\..\source\blender\verify" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\gameengine\soundsystem\snd_openal" /I "..\..\..\source\blender\imbuf" /I "..\..\..\source\blender\blenloader" /I "..\..\..\source\kernel\gen_system" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\misc" /I "..\..\..\source\blender\bpython\include" /I "..\..\..\source\blender\radiosity\extern\include" /I "..\..\..\source\blender\render\extern\include" /I "..\..\..\source\blender\include" /I "..\..\..\source\blender" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\gameengine\network" /I "..\..\..\lib\windows\decimation\include" /I "..\..\..\source\blender\blenpluginapi\\" /I "..\..\..\lib\windows\blenkey\include" /D "WIN32" /D "_MBCS" /D "_LIB" /D "_CONSOLE" /D "NAN_GAME" /D "GAME" /U "_DEBUG" /J /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\src\debug\BL_src_cre.lib"
+
+!ELSEIF "$(CFG)" == "BL_src_cre - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "BL_src_cre___Win32_Profile"
+# PROP BASE Intermediate_Dir "BL_src_cre___Win32_Profile"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "BL_src_cre___Win32_Profile"
+# PROP Intermediate_Dir "BL_src_cre___Win32_Profile"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\source\gameengine\soundsystem" /I "..\..\..\source\gameengine\soundsystem\snd_openal" /I "..\..\..\source\blender\imbuf" /I "..\..\..\source\blender\blenloader" /I "..\..\..\source\kernel\gen_system" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\misc" /I "..\..\..\source\blender\bpython\include" /I "..\..\..\source\blender\radiosity\extern\include" /I "..\..\..\source\blender\render\extern\include" /I "..\..\..\source\blender\include" /I "..\..\..\source\blender" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\gameengine\network" /I "..\..\..\lib\windows\decimation\include" /I "..\..\..\source\blender\blenpluginapi\\" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "_CONSOLE" /D "NAN_GAME" /D "GAME" /J /FD /GZ /c
+# SUBTRACT BASE CPP /Fr /YX
+# ADD CPP /nologo /W3 /Gm /GX /Zi /O2 /I "..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\source\blender\renderui" /I "..\..\..\source\gameengine\soundsystem\\" /I "..\..\..\lib\windows\python\include\python2.0\\" /I "..\..\..\source\blender\renderconverter" /I "..\..\..\source\blender\verify" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\gameengine\soundsystem\snd_openal" /I "..\..\..\source\blender\imbuf" /I "..\..\..\source\blender\blenloader" /I "..\..\..\source\kernel\gen_system" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\misc" /I "..\..\..\source\blender\bpython\include" /I "..\..\..\source\blender\radiosity\extern\include" /I "..\..\..\source\blender\render\extern\include" /I "..\..\..\source\blender\include" /I "..\..\..\source\blender" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\gameengine\network" /I "..\..\..\lib\windows\decimation\include" /I "..\..\..\source\blender\blenpluginapi\\" /I "..\..\..\lib\windows\blenkey\include" /D "WIN32" /D "_MBCS" /D "_LIB" /D "_CONSOLE" /D "NAN_GAME" /D "GAME" /U "_DEBUG" /J /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\src\debug\BL_src_cre.lib"
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\src\profile\BL_src_cre.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "BL_src_cre - Win32 Release"
+# Name "BL_src_cre - Win32 Debug"
+# Name "BL_src_cre - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\cre\license.jpeg.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\cre\license_key.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/blender/src/BL_src_pub.dsp b/projectfiles/blender/src/BL_src_pub.dsp
new file mode 100644
index 00000000000..77f420d99a3
--- /dev/null
+++ b/projectfiles/blender/src/BL_src_pub.dsp
@@ -0,0 +1,129 @@
+# Microsoft Developer Studio Project File - Name="BL_src_pub" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=BL_src_pub - Win32 Profile
+!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 "BL_src_pub.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 "BL_src_pub.mak" CFG="BL_src_pub - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "BL_src_pub - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "BL_src_pub - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "BL_src_pub - Win32 Profile" (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)" == "BL_src_pub - 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 "..\..\..\..\obj\windows\blender\src_pub"
+# 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 "..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\source\blender\renderui" /I "..\..\..\source\gameengine\soundsystem\\" /I "..\..\..\lib\windows\python\include\python2.0\\" /I "..\..\..\source\blender\renderconverter" /I "..\..\..\source\blender\verify" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\gameengine\soundsystem\snd_openal" /I "..\..\..\source\blender\imbuf" /I "..\..\..\source\blender\blenloader" /I "..\..\..\source\kernel\gen_system" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\misc" /I "..\..\..\source\blender\bpython\include" /I "..\..\..\source\blender\radiosity\extern\include" /I "..\..\..\source\blender\render\extern\include" /I "..\..\..\source\blender\include" /I "..\..\..\source\blender" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\gameengine\network" /I "..\..\..\lib\windows\decimation\include" /I "..\..\..\source\blender\blenpluginapi\\" /I "..\..\..\lib\windows\blenkey\include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "_CONSOLE" /D "NAN_GAME" /D "GAME" /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\src\BL_src_pub.lib"
+
+!ELSEIF "$(CFG)" == "BL_src_pub - 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 "..\..\..\..\obj\windows\blender\src_pub\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\guardedalloc\include" /I "..\..\..\source\blender\renderui" /I "..\..\..\source\gameengine\soundsystem\\" /I "..\..\..\lib\windows\python\include\python2.0\\" /I "..\..\..\source\blender\renderconverter" /I "..\..\..\source\blender\verify" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\gameengine\soundsystem\snd_openal" /I "..\..\..\source\blender\imbuf" /I "..\..\..\source\blender\blenloader" /I "..\..\..\source\kernel\gen_system" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\misc" /I "..\..\..\source\blender\bpython\include" /I "..\..\..\source\blender\radiosity\extern\include" /I "..\..\..\source\blender\render\extern\include" /I "..\..\..\source\blender\include" /I "..\..\..\source\blender" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\gameengine\network" /I "..\..\..\lib\windows\decimation\include" /I "..\..\..\source\blender\blenpluginapi\\" /I "..\..\..\lib\windows\blenkey\include" /D "WIN32" /D "_MBCS" /D "_LIB" /D "_CONSOLE" /D "NAN_GAME" /D "GAME" /U "_DEBUG" /J /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\src\debug\BL_src_pub.lib"
+
+!ELSEIF "$(CFG)" == "BL_src_pub - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "BL_src_pub___Win32_Profile"
+# PROP BASE Intermediate_Dir "BL_src_pub___Win32_Profile"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "BL_src_pub___Win32_Profile"
+# PROP Intermediate_Dir "BL_src_pub___Win32_Profile"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\source\gameengine\soundsystem" /I "..\..\..\source\gameengine\soundsystem\snd_openal" /I "..\..\..\source\blender\imbuf" /I "..\..\..\source\blender\blenloader" /I "..\..\..\source\kernel\gen_system" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\misc" /I "..\..\..\source\blender\bpython\include" /I "..\..\..\source\blender\radiosity\extern\include" /I "..\..\..\source\blender\render\extern\include" /I "..\..\..\source\blender\include" /I "..\..\..\source\blender" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\gameengine\network" /I "..\..\..\lib\windows\decimation\include" /I "..\..\..\source\blender\blenpluginapi\\" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "_CONSOLE" /D "NAN_GAME" /D "GAME" /J /FD /GZ /c
+# SUBTRACT BASE CPP /Fr /YX
+# ADD CPP /nologo /W3 /Gm /GX /Zi /O2 /I "..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\source\blender\renderui" /I "..\..\..\source\gameengine\soundsystem\\" /I "..\..\..\lib\windows\python\include\python2.0\\" /I "..\..\..\source\blender\renderconverter" /I "..\..\..\source\blender\verify" /I "..\..\..\source\blender\readstreamglue" /I "..\..\..\source\gameengine\soundsystem\snd_openal" /I "..\..\..\source\blender\imbuf" /I "..\..\..\source\blender\blenloader" /I "..\..\..\source\kernel\gen_system" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\misc" /I "..\..\..\source\blender\bpython\include" /I "..\..\..\source\blender\radiosity\extern\include" /I "..\..\..\source\blender\render\extern\include" /I "..\..\..\source\blender\include" /I "..\..\..\source\blender" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\gameengine\network" /I "..\..\..\lib\windows\decimation\include" /I "..\..\..\source\blender\blenpluginapi\\" /I "..\..\..\lib\windows\blenkey\include" /D "WIN32" /D "_MBCS" /D "_LIB" /D "_CONSOLE" /D "NAN_GAME" /D "GAME" /U "_DEBUG" /J /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\src\debug\BL_src_pub.lib"
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\blender\src\profile\BL_src_pub.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "BL_src_pub - Win32 Release"
+# Name "BL_src_pub - Win32 Debug"
+# Name "BL_src_pub - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\pub\license_key.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\blender\src\pub\windows_publisher_splash.jpg.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/blenderpublisher/blenderpublisher.dsp b/projectfiles/blenderpublisher/blenderpublisher.dsp
new file mode 100644
index 00000000000..4227db68b0e
--- /dev/null
+++ b/projectfiles/blenderpublisher/blenderpublisher.dsp
@@ -0,0 +1,149 @@
+# Microsoft Developer Studio Project File - Name="blenderpublisher" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=blenderpublisher - Win32 Profile
+!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 "blenderpublisher.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 "blenderpublisher.mak" CFG="blenderpublisher - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "blenderpublisher - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "blenderpublisher - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE "blenderpublisher - Win32 Profile" (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)" == "blenderpublisher - 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 "..\..\..\obj\windows\publisher"
+# 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 "..\..\lib\windows\guardedalloc\include" /I "..\..\source\blender\misc" /I "..\..\source\blender\blenlib" /I "..\..\source\kernel\gen_messaging" /I "..\..\source\blender\include" /I "..\..\source\blender" /I "..\..\source\blender\makesdna" /I "..\..\source\blender\blenkernel" /I "..\..\source\blender\blenloader" /I "..\..\source\blender\bpython\include" /I "..\..\source\blender\render\extern\include" /I "..\..\source\blender\radiosity\extern\include" /I "..\..\source\kernel\gen_system" /I "..\..\source\blender\renderconverter\\" /I "..\..\source\blender\renderui\\" /D "NDEBUG" /D "WIN32" /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 odelib.lib libfrozen.a fmodvc.lib libguardedalloc.a libbsp.a libbmfont.a libghost.a libstring.a ws2_32.lib openal_static.lib dxguid.lib opengl32.lib libjpeg.lib glu32.lib user32.lib gdi32.lib vfw32.lib advapi32.lib ole32.lib libdecimation.a libblenkey.a libeay32.lib libiksolver.a libpng.a libz.a libmoto.a /nologo /subsystem:console /machine:I386 /nodefaultlib:"msvcprt.lib" /nodefaultlib:"glut32.lib" /nodefaultlib:"libcd.lib" /nodefaultlib:"libc.lib" /nodefaultlib:"libcpd.lib" /nodefaultlib:"libcp.lib" /nodefaultlib:"libcmtd.lib" /out:"..\..\..\obj\windows\blenderpublisher.exe" /libpath:"..\..\lib\windows\bsp\lib" /libpath:"..\..\lib\windows\moto\lib" /libpath:"..\..\lib\windows\bmfont\lib" /libpath:"..\..\lib\windows\ghost\lib" /libpath:"..\..\lib\windows\ode-0.03\lib" /libpath:"..\..\lib\windows\python\frozen" /libpath:"..\..\lib\windows\fmod\lib" /libpath:"..\..\lib\windows\guardedalloc\lib" /libpath:"..\..\lib\windows\string\lib" /libpath:"..\..\lib\windows\python\lib" /libpath:"..\..\lib\windows\iksolver\lib\\" /libpath:"..\..\lib\windows\decimation\lib" /libpath:"..\..\lib\windows\openal\lib" /libpath:"..\..\lib\windows\jpeg\lib" /libpath:"..\..\lib\windows\blenkey\lib" /libpath:"..\..\lib\windows\openssl\lib" /libpath:"..\..\lib\windows\zlib\lib\\" /libpath:"..\..\lib\windows\png\lib\\"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "blenderpublisher - 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 "..\..\..\obj\windows\publisher\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 "..\..\source\blender\misc" /I "..\..\lib\windows\guardedalloc\include" /I "..\..\source\blender\blenlib" /I "..\..\source\kernel\gen_messaging" /I "..\..\source\blender\include" /I "..\..\source\blender" /I "..\..\source\blender\makesdna" /I "..\..\source\blender\blenkernel" /I "..\..\source\blender\blenloader" /I "..\..\source\blender\bpython\include" /I "..\..\source\blender\render\extern\include" /I "..\..\source\blender\radiosity\extern\include" /I "..\..\source\kernel\gen_system" /I "..\..\source\blender\renderconverter\\" /I "..\..\source\blender\renderui\\" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# SUBTRACT CPP /Fr
+# ADD BASE RSC /l 0x413 /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 libfrozen.a fmodvc.lib libguardedalloc.a libbsp.a libbmfont.a libghost.a libstring.a ws2_32.lib openal_static.lib dxguid.lib opengl32.lib libjpeg.lib glu32.lib user32.lib gdi32.lib vfw32.lib advapi32.lib ole32.lib libdecimation.a libblenkey.a libeay32.lib libiksolver.a libpng.a libz.a libmoto.a /nologo /subsystem:console /debug /machine:I386 /nodefaultlib:"glut32.lib" /nodefaultlib:"libcd.lib" /nodefaultlib:"libc.lib" /nodefaultlib:"libcpd.lib" /nodefaultlib:"libcp.lib" /nodefaultlib:"libcmt.lib" /nodefaultlib:"libcpmtd.lib" /nodefaultlib:"msvcprtd.lib" /out:"..\..\..\obj\windows\debug\blenderpublisher.exe" /pdbtype:sept /libpath:"..\..\lib\windows\bsp\lib\debug\\" /libpath:"..\..\lib\windows\moto\lib\\" /libpath:"..\..\lib\windows\bmfont\lib\debug" /libpath:"..\..\lib\windows\ghost\lib\debug" /libpath:"..\..\lib\windows\glut-3.7\lib" /libpath:"..\..\lib\windows\ode-0.03\lib" /libpath:"..\..\lib\windows\python\frozen" /libpath:"..\..\lib\windows\fmod\lib" /libpath:"..\..\lib\windows\guardedalloc\lib" /libpath:"..\..\lib\windows\string\lib" /libpath:"..\..\lib\windows\python\lib" /libpath:"..\..\lib\windows\iksolver\lib\\" /libpath:"..\..\lib\windows\decimation\lib" /libpath:"..\..\lib\windows\openal\lib" /libpath:"..\..\lib\windows\jpeg\lib" /libpath:"..\..\lib\windows\blenkey\lib" /libpath:"..\..\lib\windows\openssl\lib" /libpath:"..\..\lib\windows\zlib\lib\\" /libpath:"..\..\lib\windows\png\lib\\"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "blenderpublisher - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "blenderpublisher___Win32_Profile"
+# PROP BASE Intermediate_Dir "blenderpublisher___Win32_Profile"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "blenderpublisher___Win32_Profile"
+# PROP Intermediate_Dir "blenderpublisher___Win32_Profile"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\source\blender\blenlib" /I "..\..\source\kernel\gen_messaging" /I "..\..\source\blender\include" /I "..\..\source\blender" /I "..\..\source\blender\makesdna" /I "..\..\source\blender\blenkernel" /I "..\..\source\blender\blenloader" /I "..\..\source\blender\bpython\include" /I "..\..\source\blender\render\extern\include" /I "..\..\source\blender\radiosity\extern\include" /I "..\..\source\kernel\gen_system" /I "..\..\source\blender\renderconverter\\" /I "..\..\source\blender\renderui\\" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /O2 /I "..\..\lib\windows\guardedalloc\include" /I "..\..\source\blender\misc" /I "..\..\source\blender\blenlib" /I "..\..\source\kernel\gen_messaging" /I "..\..\source\blender\include" /I "..\..\source\blender" /I "..\..\source\blender\makesdna" /I "..\..\source\blender\blenkernel" /I "..\..\source\blender\blenloader" /I "..\..\source\blender\bpython\include" /I "..\..\source\blender\render\extern\include" /I "..\..\source\blender\radiosity\extern\include" /I "..\..\source\kernel\gen_system" /I "..\..\source\blender\renderconverter\\" /I "..\..\source\blender\renderui\\" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# SUBTRACT CPP /Fr
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 ws2_32.lib openal_static.lib dxguid.lib opengl32.lib libjpeg.lib glu32.lib user32.lib gdi32.lib advapi32.lib ole32.lib libdecimation.a libblenkey.a libeay32.lib libiksolver.a libz.a libmoto.a /nologo /subsystem:console /debug /machine:I386 /out:"..\..\..\obj\windows\debug\blenderpublisher.exe" /pdbtype:sept /libpath:"..\..\lib\windows\python\lib" /libpath:"..\..\lib\windows\iksolver\lib\\" /libpath:"..\..\lib\windows\decimation\lib" /libpath:"..\..\lib\windows\openal\lib" /libpath:"..\..\lib\windows\jpeg\lib" /libpath:"..\..\lib\windows\blenkey\lib" /libpath:"..\..\lib\windows\openssl\lib" /libpath:"..\..\lib\windows\zlib\lib\\" /libpath:"..\..\lib\windows\glut-3.7\lib" /libpath:"..\..\lib\windows\moto\lib\\"
+# ADD LINK32 odelib.lib libfrozen.a fmodvc.lib libguardedalloc.a libbsp.a libbmfont.a libghost.a libstring.a ws2_32.lib openal_static.lib dxguid.lib opengl32.lib libjpeg.lib glu32.lib user32.lib gdi32.lib vfw32.lib advapi32.lib ole32.lib libdecimation.a libblenkey.a libeay32.lib libiksolver.a libpng.a libz.a libmoto.a /nologo /subsystem:console /debug /machine:I386 /out:"..\..\..\obj\windows\debug\blenderpublisher.exe" /pdbtype:sept /libpath:"..\..\lib\windows\moto\lib\\" /libpath:"..\..\lib\windows\bmfont\lib" /libpath:"..\..\lib\windows\ghost\lib" /libpath:"..\..\lib\windows\glut-3.7\lib" /libpath:"..\..\lib\windows\ode-0.03\lib" /libpath:"..\..\lib\windows\python\frozen" /libpath:"..\..\lib\windows\fmod\lib" /libpath:"..\..\lib\windows\guardedalloc\lib" /libpath:"..\..\lib\windows\string\lib" /libpath:"..\..\lib\windows\python\lib" /libpath:"..\..\lib\windows\iksolver\lib\\" /libpath:"..\..\lib\windows\decimation\lib" /libpath:"..\..\lib\windows\openal\lib" /libpath:"..\..\lib\windows\jpeg\lib" /libpath:"..\..\lib\windows\blenkey\lib" /libpath:"..\..\lib\windows\openssl\lib" /libpath:"..\..\lib\windows\zlib\lib\\" /libpath:"..\..\lib\windows\png\lib\\"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF
+
+# Begin Target
+
+# Name "blenderpublisher - Win32 Release"
+# Name "blenderpublisher - Win32 Debug"
+# Name "blenderpublisher - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\source\creator\creator.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\source\icons\winpublisher.rc
+# 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"
+# Begin Source File
+
+SOURCE=..\..\source\icons\winblenderfile.ico
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\source\icons\winlockedfile.ico
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\source\icons\winpublisher.ico
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/creator/blendercreator.dsp b/projectfiles/creator/blendercreator.dsp
new file mode 100644
index 00000000000..3421f97bc17
--- /dev/null
+++ b/projectfiles/creator/blendercreator.dsp
@@ -0,0 +1,146 @@
+# Microsoft Developer Studio Project File - Name="blendercreator" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=blendercreator - Win32 Profile
+!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 "blendercreator.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 "blendercreator.mak" CFG="blendercreator - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "blendercreator - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "blendercreator - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE "blendercreator - Win32 Profile" (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)" == "blendercreator - 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 "..\..\..\obj\windows\creator"
+# 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 "..\..\lib\windows\guardedalloc\include" /I "..\..\source\blender\misc" /I "..\..\source\blender\renderui" /I "..\..\source\blender\renderconverter" /I "..\..\source\kernel\gen_messaging" /I "..\..\source\blender\readstreamglue" /I "..\..\source\blender\imbuf" /I "..\..\source\kernel\gen_system" /I "..\..\source\blender\radiosity\extern\include" /I "..\..\source\blender\render\extern\include" /I "..\..\source\blender\blenlib" /I "..\..\source\blender\makesdna" /I "..\..\source\blender\blenkernel" /I "..\..\source\blender\include" /I "..\..\source\blender" /I "..\..\source\blender\blenloader" /I "..\..\source\blender\bpython\include" /I "..\..\source\gameengine\SoundSystem" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+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 odelib.lib libfrozen.a fmodvc.lib libbsp.a libguardedalloc.a libbmfont.a libstring.a libghost.a ws2_32.lib openal_static.lib dxguid.lib opengl32.lib libjpeg.lib glu32.lib user32.lib gdi32.lib vfw32.lib advapi32.lib ole32.lib libdecimation.a libblenkey.a libeay32.lib libiksolver.a libpng.a libz.a libmoto.a /nologo /subsystem:console /machine:I386 /nodefaultlib:"glut32.lib" /nodefaultlib:"libcd.lib" /nodefaultlib:"libc.lib" /nodefaultlib:"libcpd.lib" /nodefaultlib:"libcp.lib" /nodefaultlib:"libcmtd.lib" /out:"..\..\..\obj\windows\blendercreator.exe" /libpath:"..\..\lib\windows\bsp\lib" /libpath:"..\..\lib\windows\ghost\lib" /libpath:"..\..\lib\windows\bmfont\lib" /libpath:"..\..\lib\windows\openal\lib" /libpath:"..\..\lib\windows\iksolver\lib\\" /libpath:"..\..\lib\windows\ode-0.03\lib" /libpath:"..\..\lib\windows\python\frozen" /libpath:"..\..\lib\windows\guardedalloc\lib" /libpath:"..\..\lib\windows\string\lib" /libpath:"..\..\lib\windows\moto\lib" /libpath:"..\..\lib\windows\python\lib" /libpath:"..\..\lib\windows\jpeg\lib" /libpath:"..\..\lib\windows\decimation\lib" /libpath:"..\..\lib\windows\blenkey\lib" /libpath:"..\..\lib\windows\openssl\lib" /libpath:"..\..\lib\windows\zlib\lib\\" /libpath:"..\..\lib\windows\png\lib\\" /libpath:"..\..\lib\windows\fmod\lib"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "blendercreator - 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 "..\..\..\obj\windows\creator\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 "..\..\lib\windows\guardedalloc\include" /I "..\..\source\blender\misc" /I "..\..\source\blender\renderui" /I "..\..\source\blender\renderconverter" /I "..\..\source\kernel\gen_messaging" /I "..\..\source\blender\readstreamglue" /I "..\..\source\blender\imbuf" /I "..\..\source\kernel\gen_system" /I "..\..\source\blender\radiosity\extern\include" /I "..\..\source\blender\render\extern\include" /I "..\..\source\blender\blenlib" /I "..\..\source\blender\makesdna" /I "..\..\source\blender\blenkernel" /I "..\..\source\blender\include" /I "..\..\source\blender" /I "..\..\source\blender\blenloader" /I "..\..\source\blender\bpython\include" /I "..\..\source\gameengine\SoundSystem" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /J /FD /GZ /c
+# SUBTRACT CPP /Fr
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+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 odelib.lib libfrozen.a fmodvc.lib libbsp.a libguardedalloc.a libbmfont.a libstring.a libghost.a ws2_32.lib openal_static.lib dxguid.lib opengl32.lib libjpeg.lib glu32.lib user32.lib gdi32.lib vfw32.lib advapi32.lib ole32.lib libdecimation.a libblenkey.a libeay32.lib libiksolver.a libpng.a libz.a libmoto.a /nologo /subsystem:console /debug /machine:I386 /nodefaultlib:"glut32.lib" /nodefaultlib:"libcd.lib" /nodefaultlib:"libc.lib" /nodefaultlib:"libcpd.lib" /nodefaultlib:"libcp.lib" /nodefaultlib:"libcmt.lib" /out:"..\..\..\obj\windows\debug\blendercreator.exe" /pdbtype:sept /libpath:"..\..\lib\windows\bsp\lib" /libpath:"..\..\lib\windows\ghost\lib\debug" /libpath:"..\..\lib\windows\bmfont\lib\debug" /libpath:"..\..\lib\windows\openal\lib\debug" /libpath:"..\..\lib\windows\iksolver\lib" /libpath:"..\..\lib\windows\ode-0.03\lib" /libpath:"..\..\lib\windows\python\frozen" /libpath:"..\..\lib\windows\guardedalloc\lib" /libpath:"..\..\lib\windows\string\lib" /libpath:"..\..\lib\windows\moto\lib" /libpath:"..\..\lib\windows\python\lib" /libpath:"..\..\lib\windows\jpeg\lib" /libpath:"..\..\lib\windows\decimation\lib" /libpath:"..\..\lib\windows\blenkey\lib" /libpath:"..\..\lib\windows\openssl\lib" /libpath:"..\..\lib\windows\zlib\lib\\" /libpath:"..\..\lib\windows\png\lib\\" /libpath:"..\..\lib\windows\fmod\lib"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "blendercreator - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "blendercreator___Win32_Profile"
+# PROP BASE Intermediate_Dir "blendercreator___Win32_Profile"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "blendercreator___Win32_Profile"
+# PROP Intermediate_Dir "blendercreator___Win32_Profile"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\source\blender\imbuf" /I "..\..\source\kernel\gen_system" /I "..\..\source\blender\radiosity\extern\include" /I "..\..\source\blender\render\extern\include" /I "..\..\source\blender\blenlib" /I "..\..\source\blender\makesdna" /I "..\..\source\blender\blenkernel" /I "..\..\source\blender\include" /I "..\..\source\blender" /I "..\..\source\blender\blenloader" /I "..\..\source\blender\bpython\include" /I "..\..\source\gameengine\SoundSystem" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /J /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /O2 /I "..\..\lib\windows\guardedalloc\include" /I "..\..\source\blender\misc" /I "..\..\source\blender\renderui" /I "..\..\source\blender\renderconverter" /I "..\..\source\kernel\gen_messaging" /I "..\..\source\blender\readstreamglue" /I "..\..\source\blender\imbuf" /I "..\..\source\kernel\gen_system" /I "..\..\source\blender\radiosity\extern\include" /I "..\..\source\blender\render\extern\include" /I "..\..\source\blender\blenlib" /I "..\..\source\blender\makesdna" /I "..\..\source\blender\blenkernel" /I "..\..\source\blender\include" /I "..\..\source\blender" /I "..\..\source\blender\blenloader" /I "..\..\source\blender\bpython\include" /I "..\..\source\gameengine\SoundSystem" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 openal_static.lib dxguid.lib opengl32.lib libjpeg.lib glu32.lib user32.lib gdi32.lib advapi32.lib ole32.lib libdecimation.a libiksolver.a /nologo /subsystem:console /debug /machine:I386 /nodefaultlib:"glut32.lib" /out:"..\..\..\obj\windows\debug\blendercreator.exe" /pdbtype:sept /libpath:"..\..\lib\windows\openal\lib\debug" /libpath:"..\..\lib\windows\glut-3.7\lib" /libpath:"..\..\lib\windows\python\lib" /libpath:"..\..\lib\windows\jpeg\lib" /libpath:"..\..\lib\windows\decimation\lib" /libpath:"..\..\lib\windows\iksolver\lib"
+# SUBTRACT BASE LINK32 /nodefaultlib
+# ADD LINK32 odelib.lib libfrozen.a fmodvc.lib libbsp.a libguardedalloc.a libbmfont.a libstring.a libghost.a ws2_32.lib openal_static.lib dxguid.lib opengl32.lib libjpeg.lib glu32.lib user32.lib gdi32.lib vfw32.lib advapi32.lib ole32.lib libdecimation.a libblenkey.a libeay32.lib libiksolver.a libpng.a libz.a libmoto.a /nologo /subsystem:console /debug /machine:I386 /nodefaultlib:"glut32.lib" /out:"..\..\..\obj\windows\profile\blendercreator.exe" /pdbtype:sept /libpath:"..\..\lib\windows\openal\lib\debug" /libpath:"..\..\lib\windows\iksolver\lib" /libpath:"..\..\lib\windows\glut-3.7\lib" /libpath:"..\..\lib\windows\ode-0.03\lib" /libpath:"..\..\lib\windows\python\frozen" /libpath:"..\..\lib\windows\guardedalloc\lib" /libpath:"..\..\lib\windows\string\lib" /libpath:"..\..\lib\windows\moto\lib" /libpath:"..\..\lib\windows\python\lib" /libpath:"..\..\lib\windows\jpeg\lib" /libpath:"..\..\lib\windows\decimation\lib" /libpath:"..\..\lib\windows\blenkey\lib" /libpath:"..\..\lib\windows\openssl\lib" /libpath:"..\..\lib\windows\zlib\lib\\" /libpath:"..\..\lib\windows\png\lib\\" /libpath:"..\..\lib\windows\fmod\lib"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF
+
+# Begin Target
+
+# Name "blendercreator - Win32 Release"
+# Name "blendercreator - Win32 Debug"
+# Name "blendercreator - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\source\creator\creator.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\source\icons\winblender.rc
+# 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"
+# Begin Source File
+
+SOURCE=..\..\source\icons\winblender.ico
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\source\icons\winblenderfile.ico
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/creator/blendercreator.dsw b/projectfiles/creator/blendercreator.dsw
new file mode 100644
index 00000000000..f2fe8b5b6a3
--- /dev/null
+++ b/projectfiles/creator/blendercreator.dsw
@@ -0,0 +1,1223 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "BKE_blenkernel"=..\blender\blenkernel\BKE_blenkernel.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "BLI_blenlib"=..\blender\blenlib\BLI_blenlib.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "BLO_decrypt"=..\BLENDER\BLO_decrypt\BLO_decrypt.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "BLO_decrypt_stub"=..\blender\BLO_decrypt_stub\BLO_decrypt_stub.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "BLO_deflate"=..\blender\BLO_deflate\BLO_deflate.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "BLO_encrypt"=..\BLENDER\BLO_encrypt\BLO_encrypt.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "BLO_inflate"=..\BLENDER\BLO_inflate\BLO_inflate.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "BLO_loader"=..\blender\loader\BLO_loader.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "BLO_readblenfile"=..\BLENDER\BLO_readblenfile\BLO_readblenfile.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "BLO_readstreamglue"=..\BLENDER\BLO_readstreamglue\BLO_readstreamglue.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "BLO_sign"=..\BLENDER\BLO_sign\BLO_sign.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "BLO_verify"=..\BLENDER\BLO_verify\BLO_verify.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "BLO_writeblenfile"=..\BLENDER\BLO_writeblenfile\BLO_writeblenfile.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "BLO_writestreamglue"=..\BLENDER\BLO_writestreamglue\BLO_writestreamglue.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "BLO_writestreamglue_stub"=..\blender\BLO_writestreamglue_stub\BLO_writestreamglue_stub.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "BL_avi"=..\blender\avi\BL_avi.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "BL_imbuf"=..\blender\imbuf\BL_imbuf.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "BL_img"=..\blender\img\BL_img.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "BL_misc"=..\blender\misc\BL_misc.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "BL_src"=..\blender\src\BL_src.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "BL_src_cre"=..\blender\src\BL_src_cre.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "BL_src_pub"=..\blender\src\BL_src_pub.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "BPY_python"=..\blender\bpython\intern\BPY_python\BPY_python.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "BRA_radiosity"=..\blender\radiosity\BRA_radiosity.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "BRE_render"=..\blender\render\BRE_render.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "BRE_renderconverter"=..\blender\renderconverter\BRE_renderconverter.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "BRE_renderui"=..\blender\renderui\BRE_renderui.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "DNA_makesdna"=..\blender\makesdna\DNA_makesdna.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "EXP_expressions"=..\gameengine\expression\EXP_expressions.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "GP_axctl"=..\gameengine\gameplayer\axctl\GP_axctl.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name KX_converter
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name EXP_expressions
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name SCA_GameLogic
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name KX_ketsji
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name SG_SceneGraph
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name RAS_openglrasterizer
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name RAS_rasterizer
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name SYS_system
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name GP_common
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name KX_network
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name NG_loopbacknetwork
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name NG_network
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name DNA_makesdna
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name gen_messaging
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BLO_verify
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BLO_writestreamglue_stub
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BLO_decrypt
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BLO_inflate
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BLO_loader
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BLO_readblenfile
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BLO_readstreamglue
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BKE_blenkernel
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BL_avi
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BL_imbuf
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BLI_blenlib
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name SND_sound
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name SND_Dummy
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name SND_fmod
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "GP_common"=..\gameengine\gameplayer\common\GP_common.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "GP_ghost"=..\gameengine\gameplayer\ghost\GP_ghost.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name BKE_blenkernel
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BL_avi
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BL_imbuf
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BLI_blenlib
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BLO_loader
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name DNA_makesdna
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name EXP_expressions
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name KX_converter
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name KX_ketsji
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name KX_network
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name NG_loopbacknetwork
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name NG_network
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name RAS_openglrasterizer
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name RAS_rasterizer
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name SCA_GameLogic
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name SG_SceneGraph
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name SND_openal
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name SND_sound
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name SYS_system
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name gen_messaging
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BLO_readblenfile
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BLO_readstreamglue
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BLO_decrypt
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BLO_inflate
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BLO_verify
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BLO_writestreamglue_stub
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name SND_Dummy
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name SND_fmod
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name GP_common
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name PHY_Physics
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name PHY_Dummy
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name SM_solid
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "KX_blenderhook"=..\gameengine\blenderhook\KX_blenderhook.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "KX_converter"=..\gameengine\converter\KX_converter.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "KX_ketsji"=..\gameengine\ketsji\KX_ketsji.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "KX_network"=..\gameengine\ketsji\network\KX_network.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "NG_loopbacknetwork"=..\gameengine\network\loopbacknetwork\NG_loopbacknetwork.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "NG_network"=..\gameengine\network\network\NG_network.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "PHY_Dummy"=..\GAMEENGINE\PHYSICS\PHY_PHYSICS\PHY_Dummy\PHY_Dummy.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "PHY_Physics"=..\gameengine\physics\PHY_Physics\PHY_Physics.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "RAS_openglrasterizer"=..\gameengine\rasterizer\openglrasterizer\RAS_openglrasterizer.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "RAS_rasterizer"=..\gameengine\rasterizer\RAS_rasterizer.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "SCA_GameLogic"=..\gameengine\gamelogic\SCA_GameLogic.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "SG_SceneGraph"=..\gameengine\scenegraph\SG_SceneGraph.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "SM_solid"=..\sumo\solid\SM_solid.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "SND_Dummy"=..\gameengine\sound\dummy\SND_Dummy.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "SND_fmod"=..\gameengine\sound\fmod\SND_fmod.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "SND_openal"=..\gameengine\sound\openal\SND_openal.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "SND_sound"=..\gameengine\sound\SND_sound.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "SSR_server"=..\ssr\SSR_server.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name KX_ketsji
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name SCA_GameLogic
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name EXP_expressions
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name RAS_openglrasterizer
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name RAS_rasterizer
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name SG_SceneGraph
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name NG_network
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name SND_sound
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name GP_common
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name KX_network
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name SND_Dummy
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name SND_openal
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BLO_loader
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name gen_messaging
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name SYS_system
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BKE_blenkernel
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BLI_blenlib
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name KX_converter
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name NG_loopbacknetwork
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BL_avi
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BL_imbuf
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BLO_readblenfile
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BLO_readstreamglue
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name DNA_makesdna
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BLO_decrypt
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BLO_inflate
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BLO_verify
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BLO_writestreamglue_stub
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name SND_fmod
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "SYS_system"=..\kernel\system\SYS_system.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "blendercreator"=.\blendercreator.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name BKE_blenkernel
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BL_avi
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BL_imbuf
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BL_img
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BL_misc
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BLI_blenlib
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BLO_loader
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BRA_radiosity
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BRE_render
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name KX_blenderhook
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name KX_converter
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name EXP_expressions
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name SCA_GameLogic
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name KX_ketsji
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name KX_network
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name SG_SceneGraph
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name NG_loopbacknetwork
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name NG_network
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name RAS_openglrasterizer
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name RAS_rasterizer
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name SND_openal
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name SND_sound
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name SYS_system
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name DNA_makesdna
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name SND_Dummy
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BPY_python
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name decimation
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BLO_inflate
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BLO_writeblenfile
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BLO_readblenfile
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BLO_verify
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name gen_messaging
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BLO_writestreamglue_stub
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BLO_readstreamglue
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BLO_decrypt_stub
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BRE_renderconverter
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BRE_renderui
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BL_src_cre
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name blenpluginapi
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BL_src
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name SND_fmod
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name PHY_Physics
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name PHY_Dummy
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name SM_solid
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "blenderpublisher"=..\blenderpublisher\blenderpublisher.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name BKE_blenkernel
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BL_avi
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BL_imbuf
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BL_img
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BL_misc
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BLI_blenlib
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BLO_decrypt
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BLO_deflate
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BLO_encrypt
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BLO_inflate
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BLO_loader
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BLO_readblenfile
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BLO_readstreamglue
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BLO_sign
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BLO_verify
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BLO_writeblenfile
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BLO_writestreamglue
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BPY_python
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BRA_radiosity
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BRE_render
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name DNA_makesdna
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name EXP_expressions
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name gen_messaging
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name KX_blenderhook
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name KX_converter
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name KX_ketsji
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name KX_network
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name NG_loopbacknetwork
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name NG_network
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name RAS_openglrasterizer
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name RAS_rasterizer
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name SCA_GameLogic
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name SG_SceneGraph
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name SND_Dummy
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name SND_openal
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name SND_sound
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name SYS_system
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BRE_renderconverter
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BRE_renderui
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BL_src_pub
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name blenpluginapi
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name BL_src
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name SND_fmod
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name PHY_Dummy
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name PHY_Physics
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "blenpluginapi"=..\blender\blenpluginapi\blenpluginapi\blenpluginapi.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "datatoc"=..\datatoc\datatoc.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "gen_messaging"=..\KERNEL\gen_messaging\gen_messaging.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/projectfiles/datatoc/datatoc.dsp b/projectfiles/datatoc/datatoc.dsp
new file mode 100644
index 00000000000..4e55182bb2c
--- /dev/null
+++ b/projectfiles/datatoc/datatoc.dsp
@@ -0,0 +1,100 @@
+# Microsoft Developer Studio Project File - Name="datatoc" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=datatoc - 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 "datatoc.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 "datatoc.mak" CFG="datatoc - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "datatoc - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "datatoc - 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)" == "datatoc - 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 ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /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 /nologo /subsystem:console /machine:I386
+
+!ELSEIF "$(CFG)" == "datatoc - 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 ""
+# 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 /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 /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "datatoc - Win32 Release"
+# Name "datatoc - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\release\datafiles\datatoc.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/projectfiles/gameengine/blenderhook/KX_blenderhook.dsp b/projectfiles/gameengine/blenderhook/KX_blenderhook.dsp
new file mode 100644
index 00000000000..c2ceaa48372
--- /dev/null
+++ b/projectfiles/gameengine/blenderhook/KX_blenderhook.dsp
@@ -0,0 +1,191 @@
+# Microsoft Developer Studio Project File - Name="KX_blenderhook" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=KX_blenderhook - Win32 Profile
+!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 "KX_blenderhook.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 "KX_blenderhook.mak" CFG="KX_blenderhook - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "KX_blenderhook - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "KX_blenderhook - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "KX_blenderhook - Win32 Profile" (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)" == "KX_blenderhook - 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 "..\..\..\..\obj\windows\gameengine\blenderhook"
+# 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 "..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\source\gameengine\rasterizer\ras_openglrasterizer" /I "..\..\..\lib\windows\python\include\python2.0" /I "..\..\..\lib\windows\string\include" /I "..\..\..\lib\windows\bmfont\include" /I "..\..\..\source\gameengine\Converter\\" /I "..\..\..\source\blender\imbuf" /I "..\..\..\lib\windows\moto\include" /I "..\..\..\source\gameengine\ketsji" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender" /I "..\..\..\source\blender\include" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\gameengine\rasterizer" /I "..\..\..\source\gameengine\gamelogic" /I "..\..\..\source\kernel\gen_system" /I "..\..\..\source\gameengine\expressions" /I "..\..\..\source\gameengine\network" /I "..\..\..\source\gameengine\scenegraph" /I "..\..\..\source\sumo\include" /I "..\..\..\source\sumo\fuzzics\include" /I "..\..\..\source\gameengine\network\loopbacknetwork" /I "..\..\..\source\gameengine\soundsystem" /I "..\..\..\source\blender\misc" /I "..\..\..\source\blender\blenloader" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\gameengine\blenderhook\KX_blenderhook.lib"
+
+!ELSEIF "$(CFG)" == "KX_blenderhook - 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 "..\..\..\..\obj\windows\gameengine\blenderhook\debug"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\source\gameengine\rasterizer\ras_openglrasterizer" /I "..\..\..\lib\windows\python\include\python2.0" /I "..\..\..\lib\windows\string\include" /I "..\..\..\lib\windows\bmfont\include" /I "..\..\..\source\gameengine\Converter\\" /I "..\..\..\source\blender\imbuf" /I "..\..\..\lib\windows\moto\include" /I "..\..\..\source\gameengine\ketsji" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender" /I "..\..\..\source\blender\include" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\gameengine\rasterizer" /I "..\..\..\source\gameengine\gamelogic" /I "..\..\..\source\kernel\gen_system" /I "..\..\..\source\gameengine\expressions" /I "..\..\..\source\gameengine\network" /I "..\..\..\source\gameengine\scenegraph" /I "..\..\..\source\sumo\include" /I "..\..\..\source\sumo\fuzzics\include" /I "..\..\..\source\gameengine\network\loopbacknetwork" /I "..\..\..\source\gameengine\soundsystem" /I "..\..\..\source\blender\misc" /I "..\..\..\source\blender\blenloader" /D "WIN32" /D "_MBCS" /D "_LIB" /U "_DEBUG" /YX /J /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\gameengine\blenderhook\debug\KX_blenderhook.lib"
+
+!ELSEIF "$(CFG)" == "KX_blenderhook - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "KX_blenderhook___Win32_Profile"
+# PROP BASE Intermediate_Dir "KX_blenderhook___Win32_Profile"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "KX_blenderhook___Win32_Profile"
+# PROP Intermediate_Dir "KX_blenderhook___Win32_Profile"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\lib\windows\python\include\python1.5" /I "..\..\..\source\blender\imbuf" /I "..\..\..\lib\windows\moto\include" /I "..\..\..\source\gameengine\ketsji" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender" /I "..\..\..\source\blender\include" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\gameengine\rasterizer" /I "..\..\..\source\gameengine\gamelogic" /I "..\..\..\source\kernel\gen_system" /I "..\..\..\source\gameengine\expressions" /I "..\..\..\source\gameengine\network" /I "..\..\..\source\gameengine\scenegraph" /I "..\..\..\source\sumo\include" /I "..\..\..\source\sumo\fuzzics\include" /I "..\..\..\source\gameengine\network\loopbacknetwork" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /O2 /I "..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\source\gameengine\rasterizer\ras_openglrasterizer" /I "..\..\..\lib\windows\python\include\python2.0" /I "..\..\..\lib\windows\string\include" /I "..\..\..\lib\windows\bmfont\include" /I "..\..\..\source\gameengine\Converter\\" /I "..\..\..\source\blender\imbuf" /I "..\..\..\lib\windows\moto\include" /I "..\..\..\source\gameengine\ketsji" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender" /I "..\..\..\source\blender\include" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\gameengine\rasterizer" /I "..\..\..\source\gameengine\gamelogic" /I "..\..\..\source\kernel\gen_system" /I "..\..\..\source\gameengine\expressions" /I "..\..\..\source\gameengine\network" /I "..\..\..\source\gameengine\scenegraph" /I "..\..\..\source\sumo\include" /I "..\..\..\source\sumo\fuzzics\include" /I "..\..\..\source\gameengine\network\loopbacknetwork" /I "..\..\..\source\gameengine\soundsystem" /I "..\..\..\source\blender\misc" /I "..\..\..\source\blender\blenloader" /D "WIN32" /D "_MBCS" /D "_LIB" /U "_DEBUG" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\obj\windows\gameengine\blenderhook\debug\KX_blenderhook.lib"
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\gameengine\blenderhook\profile\KX_blenderhook.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "KX_blenderhook - Win32 Release"
+# Name "KX_blenderhook - Win32 Debug"
+# Name "KX_blenderhook - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\BlenderRoutines\BL_KetsjiEmbedStart.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\BlenderRoutines\KX_BlenderCanvas.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\BlenderRoutines\KX_BlenderGL.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\BlenderRoutines\KX_BlenderInputDevice.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\BlenderRoutines\KX_BlenderKeyboardDevice.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\BlenderRoutines\KX_BlenderMouseDevice.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\BlenderRoutines\KX_BlenderPolyMaterial.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\BlenderRoutines\KX_BlenderRenderTools.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\BlenderRoutines\KX_BlenderSystem.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\BlenderRoutines\KX_BlenderCanvas.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\BlenderRoutines\KX_BlenderDevice.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\BlenderRoutines\KX_BlenderGL.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\BlenderRoutines\KX_BlenderInputDevice.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\BlenderRoutines\KX_BlenderKeyboardDevice.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\BlenderRoutines\KX_BlenderMouseDevice.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\BlenderRoutines\KX_BlenderPolyMaterial.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\BlenderRoutines\KX_BlenderRenderTools.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\BlenderRoutines\KX_BlenderSystem.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/gameengine/converter/KX_converter.dsp b/projectfiles/gameengine/converter/KX_converter.dsp
new file mode 100644
index 00000000000..517b722682a
--- /dev/null
+++ b/projectfiles/gameengine/converter/KX_converter.dsp
@@ -0,0 +1,296 @@
+# Microsoft Developer Studio Project File - Name="KX_converter" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=KX_converter - Win32 Profile
+!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 "KX_converter.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 "KX_converter.mak" CFG="KX_converter - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "KX_converter - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "KX_converter - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "KX_converter - Win32 MT DLL Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "KX_converter - Win32 MT DLL Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "KX_converter - Win32 Profile" (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)" == "KX_converter - 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 "..\..\..\..\obj\windows\gameengine\converter"
+# 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 "..\..\..\lib\windows\python\include\python2.0" /I "..\..\..\lib\windows\string\include" /I "..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\source\blender\imbuf" /I "..\..\..\source\kernel\gen_system" /I "..\..\..\source\gameengine\expressions" /I "..\..\..\source\gameengine\BlenderRoutines" /I "..\..\..\source\sumo\include" /I "..\..\..\lib\windows\moto\include" /I "..\..\..\source\sumo\Fuzzics\include" /I "..\..\..\source\gameengine\Ketsji" /I "..\..\..\source\gameengine\SceneGraph" /I "..\..\..\source\gameengine\rasterizer" /I "..\..\..\source\gameengine\rasterizer\ras_openglrasterizer" /I "..\..\..\source\gameengine\gamelogic" /I "..\..\..\source\gameengine\soundsystem" /I "..\..\..\source\gameengine\soundsystem\snd_openal" /I "..\..\..\source\gameengine\soundsystem\snd_blenderwavecache" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\include" /I "..\..\..\source\blender" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\gameengine\network" /I "..\..\..\source\gameengine\ketsji\kxnetwork" /I "..\..\..\source\gameengine\physics" /I "..\..\..\source\gameengine\physics\ode" /I "..\..\..\source\gameengine\physics\dummy" /I "..\..\..\source\gameengine\physics\sumo" /I "..\..\..\source\gameengine\physics\sumo\fuzzics\include" /I "..\..\..\source\gameengine\physics\sumo\include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\gameengine\converter\KX_converter.lib"
+
+!ELSEIF "$(CFG)" == "KX_converter - 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 "..\..\..\..\obj\windows\gameengine\converter\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\python\include\python2.0" /I "..\..\..\lib\windows\string\include" /I "..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\source\blender\imbuf" /I "..\..\..\source\kernel\gen_system" /I "..\..\..\source\gameengine\expressions" /I "..\..\..\source\gameengine\BlenderRoutines" /I "..\..\..\source\sumo\include" /I "..\..\..\lib\windows\moto\include" /I "..\..\..\source\sumo\Fuzzics\include" /I "..\..\..\source\gameengine\Ketsji" /I "..\..\..\source\gameengine\SceneGraph" /I "..\..\..\source\gameengine\rasterizer" /I "..\..\..\source\gameengine\rasterizer\ras_openglrasterizer" /I "..\..\..\source\gameengine\gamelogic" /I "..\..\..\source\gameengine\soundsystem" /I "..\..\..\source\gameengine\soundsystem\snd_openal" /I "..\..\..\source\gameengine\soundsystem\snd_blenderwavecache" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\include" /I "..\..\..\source\blender" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\gameengine\network" /I "..\..\..\source\gameengine\ketsji\kxnetwork" /I "..\..\..\source\gameengine\physics" /I "..\..\..\source\gameengine\physics\ode" /I "..\..\..\source\gameengine\physics\dummy" /I "..\..\..\source\gameengine\physics\sumo" /I "..\..\..\source\gameengine\physics\sumo\fuzzics\include" /I "..\..\..\source\gameengine\physics\sumo\include" /D "WIN32" /D "_MBCS" /D "_LIB" /U "_DEBUG" /YX /J /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\gameengine\converter\debug\KX_converter.lib"
+
+!ELSEIF "$(CFG)" == "KX_converter - Win32 MT DLL Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "KX_converter___Win32_MT_DLL_Debug"
+# PROP BASE Intermediate_Dir "KX_converter___Win32_MT_DLL_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\..\..\..\obj\windows\gameengine\converter\mtdll_debug"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\gameengine\converter\mtdll_debug"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /Gm /GX /ZI /Od /I "..\..\..\source\blender\imbuf" /I "..\..\..\source\kernel\gen_system" /I "..\..\..\source\gameengine\expressions" /I "..\..\..\source\gameengine\BlenderRoutines" /I "..\..\..\source\sumo\include" /I "..\..\..\lib\windows\moto\include" /I "..\..\..\source\sumo\Fuzzics\include" /I "..\..\..\source\gameengine\Ketsji" /I "..\..\..\source\gameengine\SceneGraph" /I "..\..\..\source\gameengine\rasterizer" /I "..\..\..\source\gameengine\rasterizer\ras_openglrasterizer" /I "..\..\..\source\gameengine\gamelogic" /I "..\..\..\source\gameengine\soundsystem" /I "..\..\..\source\gameengine\soundsystem\snd_openal" /I "..\..\..\source\gameengine\soundsystem\snd_blenderwavecache" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\include" /I "..\..\..\source\blender" /I "..\..\..\source\blender\makesdna" /I "..\..\..\lib\windows\python\include\python1.5" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /GZ /c
+# ADD CPP /nologo /MDd /Gm /GX /ZI /Od /I "..\..\..\lib\windows\python\include\python2.0" /I "..\..\..\lib\windows\string\include" /I "..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\source\blender\imbuf" /I "..\..\..\source\kernel\gen_system" /I "..\..\..\source\gameengine\expressions" /I "..\..\..\source\gameengine\BlenderRoutines" /I "..\..\..\source\sumo\include" /I "..\..\..\lib\windows\moto\include" /I "..\..\..\source\sumo\Fuzzics\include" /I "..\..\..\source\gameengine\Ketsji" /I "..\..\..\source\gameengine\SceneGraph" /I "..\..\..\source\gameengine\rasterizer" /I "..\..\..\source\gameengine\rasterizer\ras_openglrasterizer" /I "..\..\..\source\gameengine\gamelogic" /I "..\..\..\source\gameengine\soundsystem" /I "..\..\..\source\gameengine\soundsystem\snd_openal" /I "..\..\..\source\gameengine\soundsystem\snd_blenderwavecache" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\include" /I "..\..\..\source\blender" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\gameengine\network" /I "..\..\..\source\gameengine\ketsji\kxnetwork" /I "..\..\..\source\gameengine\physics" /I "..\..\..\source\gameengine\physics\ode" /I "..\..\..\source\gameengine\physics\dummy" /I "..\..\..\source\gameengine\physics\sumo" /I "..\..\..\source\gameengine\physics\sumo\fuzzics\include" /I "..\..\..\source\gameengine\physics\sumo\include" /D "WIN32" /D "_MBCS" /D "_LIB" /U "_DEBUG" /YX /J /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 /out:"..\..\..\..\..\obj\windows\gameengine\converter\debug\KX_converter.lib"
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "KX_converter - Win32 MT DLL Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "KX_converter___Win32_MT_DLL_Release"
+# PROP BASE Intermediate_Dir "KX_converter___Win32_MT_DLL_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\..\..\..\obj\windows\gameengine\converter\mtdll"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\gameengine\converter\mtdll"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /GX /O2 /I "..\..\..\source\blender\imbuf" /I "..\..\..\source\kernel\gen_system" /I "..\..\..\source\gameengine\expressions" /I "..\..\..\source\gameengine\BlenderRoutines" /I "..\..\..\source\sumo\include" /I "..\..\..\lib\windows\moto\include" /I "..\..\..\source\sumo\Fuzzics\include" /I "..\..\..\source\gameengine\Ketsji" /I "..\..\..\source\gameengine\SceneGraph" /I "..\..\..\source\gameengine\rasterizer" /I "..\..\..\source\gameengine\rasterizer\ras_openglrasterizer" /I "..\..\..\source\gameengine\gamelogic" /I "..\..\..\source\gameengine\soundsystem" /I "..\..\..\source\gameengine\soundsystem\snd_openal" /I "..\..\..\source\gameengine\soundsystem\snd_blenderwavecache" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\include" /I "..\..\..\source\blender" /I "..\..\..\source\blender\makesdna" /I "..\..\..\lib\windows\python\include\python2.0" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD CPP /nologo /MD /GX /O2 /I "..\..\..\lib\windows\python\include\python2.0" /I "..\..\..\lib\windows\string\include" /I "..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\source\blender\imbuf" /I "..\..\..\source\kernel\gen_system" /I "..\..\..\source\gameengine\expressions" /I "..\..\..\source\gameengine\BlenderRoutines" /I "..\..\..\source\sumo\include" /I "..\..\..\lib\windows\moto\include" /I "..\..\..\source\sumo\Fuzzics\include" /I "..\..\..\source\gameengine\Ketsji" /I "..\..\..\source\gameengine\SceneGraph" /I "..\..\..\source\gameengine\rasterizer" /I "..\..\..\source\gameengine\rasterizer\ras_openglrasterizer" /I "..\..\..\source\gameengine\gamelogic" /I "..\..\..\source\gameengine\soundsystem" /I "..\..\..\source\gameengine\soundsystem\snd_openal" /I "..\..\..\source\gameengine\soundsystem\snd_blenderwavecache" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\include" /I "..\..\..\source\blender" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\gameengine\network" /I "..\..\..\source\gameengine\ketsji\kxnetwork" /I "..\..\..\source\gameengine\physics" /I "..\..\..\source\gameengine\physics\ode" /I "..\..\..\source\gameengine\physics\dummy" /I "..\..\..\source\gameengine\physics\sumo" /I "..\..\..\source\gameengine\physics\sumo\fuzzics\include" /I "..\..\..\source\gameengine\physics\sumo\include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\..\obj\windows\gameengine\converter\KX_converter.lib"
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "KX_converter - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "KX_converter___Win32_Profile"
+# PROP BASE Intermediate_Dir "KX_converter___Win32_Profile"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "KX_converter___Win32_Profile"
+# PROP Intermediate_Dir "KX_converter___Win32_Profile"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\lib\windows\python\include\python1.5" /I "..\..\..\lib\windows\python\include\python2.0" /I "..\..\..\source\blender\imbuf" /I "..\..\..\source\kernel\gen_system" /I "..\..\..\source\gameengine\expressions" /I "..\..\..\source\gameengine\BlenderRoutines" /I "..\..\..\source\sumo\include" /I "..\..\..\lib\windows\moto\include" /I "..\..\..\source\sumo\Fuzzics\include" /I "..\..\..\source\gameengine\Ketsji" /I "..\..\..\source\gameengine\SceneGraph" /I "..\..\..\source\gameengine\rasterizer" /I "..\..\..\source\gameengine\rasterizer\ras_openglrasterizer" /I "..\..\..\source\gameengine\gamelogic" /I "..\..\..\source\gameengine\soundsystem" /I "..\..\..\source\gameengine\soundsystem\snd_openal" /I "..\..\..\source\gameengine\soundsystem\snd_blenderwavecache" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\include" /I "..\..\..\source\blender" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\gameengine\network" /I "..\..\..\source\gameengine\ketsji\kxnetwork" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /O2 /I "..\..\..\lib\windows\python\include\python2.0" /I "..\..\..\lib\windows\string\include" /I "..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\source\blender\imbuf" /I "..\..\..\source\kernel\gen_system" /I "..\..\..\source\gameengine\expressions" /I "..\..\..\source\gameengine\BlenderRoutines" /I "..\..\..\source\sumo\include" /I "..\..\..\lib\windows\moto\include" /I "..\..\..\source\sumo\Fuzzics\include" /I "..\..\..\source\gameengine\Ketsji" /I "..\..\..\source\gameengine\SceneGraph" /I "..\..\..\source\gameengine\rasterizer" /I "..\..\..\source\gameengine\rasterizer\ras_openglrasterizer" /I "..\..\..\source\gameengine\gamelogic" /I "..\..\..\source\gameengine\soundsystem" /I "..\..\..\source\gameengine\soundsystem\snd_openal" /I "..\..\..\source\gameengine\soundsystem\snd_blenderwavecache" /I "..\..\..\source\blender\blenlib" /I "..\..\..\source\blender\blenkernel" /I "..\..\..\source\blender\include" /I "..\..\..\source\blender" /I "..\..\..\source\blender\makesdna" /I "..\..\..\source\gameengine\network" /I "..\..\..\source\gameengine\ketsji\kxnetwork" /I "..\..\..\source\gameengine\physics" /I "..\..\..\source\gameengine\physics\ode" /I "..\..\..\source\gameengine\physics\dummy" /I "..\..\..\source\gameengine\physics\sumo" /I "..\..\..\source\gameengine\physics\sumo\fuzzics\include" /I "..\..\..\source\gameengine\physics\sumo\include" /D "WIN32" /D "_MBCS" /D "_LIB" /U "_DEBUG" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\obj\windows\gameengine\converter\debug\KX_converter.lib"
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\gameengine\converter\profile\KX_converter.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "KX_converter - Win32 Release"
+# Name "KX_converter - Win32 Debug"
+# Name "KX_converter - Win32 MT DLL Debug"
+# Name "KX_converter - Win32 MT DLL Release"
+# Name "KX_converter - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Converter\BL_ActionActuator.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Converter\BL_ArmatureObject.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Converter\BL_BlenderDataConversion.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Converter\BL_DeformableGameObject.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Converter\BL_MeshDeformer.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Converter\BL_SkinDeformer.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Converter\BL_SkinMeshObject.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Converter\BlenderWorldInfo.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Converter\KX_BlenderScalarInterpolator.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Converter\KX_BlenderSceneConverter.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Converter\KX_ConvertActuators.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Converter\KX_ConvertControllers.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Converter\KX_ConvertProperties.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Converter\KX_ConvertSensors.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Converter\KX_IpoConvert.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Converter\BL_ActionActuator.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Converter\BL_ArmatureObject.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Converter\BL_BlenderDataConversion.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Converter\BL_DeformableGameObject.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Converter\BL_MeshDeformer.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Converter\BL_SkinDeformer.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Converter\BL_SkinMeshObject.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Converter\BlenderWorldInfo.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Converter\KX_BlenderCanvas.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Converter\KX_BlenderScalarInterpolator.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Converter\KX_BlenderSceneConverter.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Converter\KX_ConvertActuators.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Converter\KX_ConvertControllers.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Converter\KX_ConvertProperties.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Converter\KX_ConvertSensors.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Converter\KX_IpoConvert.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/gameengine/expression/EXP_expressions.dsp b/projectfiles/gameengine/expression/EXP_expressions.dsp
new file mode 100644
index 00000000000..4ba9fdbf266
--- /dev/null
+++ b/projectfiles/gameengine/expression/EXP_expressions.dsp
@@ -0,0 +1,328 @@
+# Microsoft Developer Studio Project File - Name="EXP_expressions" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=EXP_expressions - Win32 Profile
+!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 "EXP_expressions.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 "EXP_expressions.mak" CFG="EXP_expressions - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "EXP_expressions - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "EXP_expressions - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "EXP_expressions - Win32 MT DLL Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "EXP_expressions - Win32 MT DLL Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "EXP_expressions - Win32 Profile" (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)" == "EXP_expressions - 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 "..\..\..\..\obj\windows\gameengine\expressions"
+# 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 "..\..\..\lib\windows\python\include\python2.0" /I "..\..\..\..\lib\windows\python\include\python2.0" /I "..\..\..\lib\windows\string\include" /I "..\..\..\source\kernel\gen_system" /I "..\..\..\source\gameengine\ketsji" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "EXP_PYTHON_EMBEDDING" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\gameengine\expressions\EXP_expressions.lib"
+
+!ELSEIF "$(CFG)" == "EXP_expressions - 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 "..\..\..\..\obj\windows\gameengine\expressions\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\python\include\python2.0" /I "..\..\..\..\lib\windows\python\include\python2.0" /I "..\..\..\lib\windows\string\include" /I "..\..\..\source\kernel\gen_system" /I "..\..\..\source\gameengine\ketsji" /D "WIN32" /D "_MBCS" /D "_LIB" /D "EXP_PYTHON_EMBEDDING" /U "_DEBUG" /YX /J /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\gameengine\expressions\debug\EXP_expressions.lib"
+
+!ELSEIF "$(CFG)" == "EXP_expressions - Win32 MT DLL Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "EXP_expressions___Win32_MT_DLL_Debug"
+# PROP BASE Intermediate_Dir "EXP_expressions___Win32_MT_DLL_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\..\..\..\obj\windows\gameengine\expressions\mtdll_debug"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\gameengine\expressions\mtdll_debug"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /MDd /Gm /GX /ZI /Od /I "..\..\..\source\kernel\gen_system" /I "..\..\..\lib\windows\python\include\python1.5" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "EXP_PYTHON_EMBEDDING" /YX /J /FD /GZ /c
+# ADD CPP /nologo /MDd /Gm /GX /ZI /Od /I "..\..\..\lib\windows\python\include\python2.0" /I "..\..\..\..\lib\windows\python\include\python2.0" /I "..\..\..\lib\windows\string\include" /I "..\..\..\source\kernel\gen_system" /I "..\..\..\source\gameengine\ketsji" /D "WIN32" /D "_MBCS" /D "_LIB" /D "EXP_PYTHON_EMBEDDING" /U "_DEBUG" /YX /J /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 /out:"..\..\..\..\..\obj\windows\gameengine\expressions\debug\EXP_expressions.lib"
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "EXP_expressions - Win32 MT DLL Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "EXP_expressions___Win32_MT_DLL_Release"
+# PROP BASE Intermediate_Dir "EXP_expressions___Win32_MT_DLL_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\..\..\..\obj\windows\gameengine\expressions\mtdll"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\gameengine\expressions\mtdll"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /GX /O2 /I "..\..\..\source\kernel\gen_system" /I "..\..\..\lib\windows\python\include\python2.0" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "EXP_PYTHON_EMBEDDING" /YX /J /FD /c
+# ADD CPP /nologo /MD /GX /O2 /I "..\..\..\lib\windows\python\include\python2.0" /I "..\..\..\..\lib\windows\python\include\python2.0" /I "..\..\..\lib\windows\string\include" /I "..\..\..\source\kernel\gen_system" /I "..\..\..\source\gameengine\ketsji" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "EXP_PYTHON_EMBEDDING" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\..\obj\windows\gameengine\expressions\EXP_expressions.lib"
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "EXP_expressions - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "EXP_expressions___Win32_Profile"
+# PROP BASE Intermediate_Dir "EXP_expressions___Win32_Profile"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "EXP_expressions___Win32_Profile"
+# PROP Intermediate_Dir "EXP_expressions___Win32_Profile"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\source\kernel\gen_system" /I "..\..\..\lib\windows\python\include\python1.5" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "EXP_PYTHON_EMBEDDING" /YX /J /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /O2 /I "..\..\..\lib\windows\python\include\python2.0" /I "..\..\..\..\lib\windows\python\include\python2.0" /I "..\..\..\lib\windows\string\include" /I "..\..\..\source\kernel\gen_system" /I "..\..\..\source\gameengine\ketsji" /D "WIN32" /D "_MBCS" /D "_LIB" /D "EXP_PYTHON_EMBEDDING" /U "_DEBUG" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\obj\windows\gameengine\expressions\debug\EXP_expressions.lib"
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\gameengine\expressions\profile\EXP_expressions.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "EXP_expressions - Win32 Release"
+# Name "EXP_expressions - Win32 Debug"
+# Name "EXP_expressions - Win32 MT DLL Debug"
+# Name "EXP_expressions - Win32 MT DLL Release"
+# Name "EXP_expressions - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Expressions\BoolValue.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Expressions\ConstExpr.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Expressions\EmptyValue.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Expressions\ErrorValue.cpp
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\gameengine\Expressions\EXP_C-Api.cpp"
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Expressions\Expression.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Expressions\FloatValue.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Expressions\IdentifierExpr.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Expressions\IfExpr.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Expressions\InputParser.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Expressions\IntValue.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Expressions\KX_HashedPtr.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Expressions\ListValue.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Expressions\Operator1Expr.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Expressions\Operator2Expr.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Expressions\PyObjectPlus.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Expressions\StringValue.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Expressions\Value.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Expressions\VectorValue.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Expressions\BoolValue.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Expressions\ConstExpr.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Expressions\EmptyValue.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Expressions\ErrorValue.h
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\gameengine\Expressions\EXP_C-Api.h"
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Expressions\Expression.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Expressions\FloatValue.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Expressions\IdentifierExpr.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Expressions\IfExpr.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Expressions\InputParser.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Expressions\IntValue.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Expressions\KX_HashedPtr.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Expressions\ListValue.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Expressions\Operator1Expr.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Expressions\Operator2Expr.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Expressions\PyObjectPlus.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Expressions\StringValue.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Expressions\Value.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Expressions\VectorValue.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Expressions\VoidValue.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/gameengine/gamelogic/SCA_gamelogic.dsp b/projectfiles/gameengine/gamelogic/SCA_gamelogic.dsp
new file mode 100644
index 00000000000..ab85e2f4c9a
--- /dev/null
+++ b/projectfiles/gameengine/gamelogic/SCA_gamelogic.dsp
@@ -0,0 +1,388 @@
+# Microsoft Developer Studio Project File - Name="SCA_GameLogic" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=SCA_GameLogic - Win32 Profile
+!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 "SCA_GameLogic.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 "SCA_GameLogic.mak" CFG="SCA_GameLogic - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "SCA_GameLogic - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "SCA_GameLogic - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "SCA_GameLogic - Win32 MT DLL Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "SCA_GameLogic - Win32 MT DLL Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "SCA_GameLogic - Win32 Profile" (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)" == "SCA_GameLogic - 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 "..\..\..\..\obj\windows\gameengine\gamelogic"
+# 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 "..\..\..\lib\windows\python\include\python2.0" /I "..\..\..\lib\windows\string\include" /I "..\..\..\source\gameengine\ketsji" /I "..\..\..\source\kernel\gen_system" /I "..\..\..\source\gameengine\expressions" /I "..\..\..\lib\windows\moto\include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "EXP_PYTHON_EMBEDDING" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\gameengine\gamelogic\SCA_GameLogic.lib"
+
+!ELSEIF "$(CFG)" == "SCA_GameLogic - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "SCA_GameLogic___Win32_Debug"
+# PROP BASE Intermediate_Dir "SCA_GameLogic___Win32_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\gameengine\gamelogic\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\python\include\python2.0" /I "..\..\..\lib\windows\string\include" /I "..\..\..\source\gameengine\ketsji" /I "..\..\..\source\kernel\gen_system" /I "..\..\..\source\gameengine\expressions" /I "..\..\..\lib\windows\moto\include" /D "WIN32" /D "_MBCS" /D "_LIB" /D "EXP_PYTHON_EMBEDDING" /U "_DEBUG" /YX /J /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\gameengine\gamelogic\debug\SCA_GameLogic.lib"
+
+!ELSEIF "$(CFG)" == "SCA_GameLogic - Win32 MT DLL Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "SCA_GameLogic___Win32_MT_DLL_Debug"
+# PROP BASE Intermediate_Dir "SCA_GameLogic___Win32_MT_DLL_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\..\..\..\obj\windows\gameengine\gamelogic\mtdll_debug"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\gameengine\gamelogic\mtdll_debug"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /Gm /GX /ZI /Od /I "..\..\..\source\kernel\gen_system" /I "..\..\..\source\gameengine\expressions" /I "..\..\..\lib\windows\moto\include" /I "..\..\..\lib\windows\python\include\python1.5" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "EXP_PYTHON_EMBEDDING" /YX /J /FD /GZ /c
+# ADD CPP /nologo /MDd /Gm /GX /ZI /Od /I "..\..\..\lib\windows\python\include\python2.0" /I "..\..\..\lib\windows\string\include" /I "..\..\..\source\gameengine\ketsji" /I "..\..\..\source\kernel\gen_system" /I "..\..\..\source\gameengine\expressions" /I "..\..\..\lib\windows\moto\include" /D "WIN32" /D "_MBCS" /D "_LIB" /D "EXP_PYTHON_EMBEDDING" /U "_DEBUG" /YX /J /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 /out:"..\..\..\..\..\obj\windows\gameengine\gamelogic\debug\SCA_GameLogic.lib"
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "SCA_GameLogic - Win32 MT DLL Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "SCA_GameLogic___Win32_MT_DLL_Release"
+# PROP BASE Intermediate_Dir "SCA_GameLogic___Win32_MT_DLL_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\..\..\..\obj\windows\gameengine\gamelogic\mtdll"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\gameengine\gamelogic\mtdll"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /GX /O2 /I "..\..\..\source\kernel\gen_system" /I "..\..\..\source\gameengine\expressions" /I "..\..\..\lib\windows\moto\include" /I "..\..\..\lib\windows\python\include\python2.0" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "EXP_PYTHON_EMBEDDING" /YX /J /FD /c
+# ADD CPP /nologo /MD /GX /O2 /I "..\..\..\lib\windows\python\include\python2.0" /I "..\..\..\lib\windows\string\include" /I "..\..\..\source\gameengine\ketsji" /I "..\..\..\source\kernel\gen_system" /I "..\..\..\source\gameengine\expressions" /I "..\..\..\lib\windows\moto\include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "EXP_PYTHON_EMBEDDING" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\..\obj\windows\gameengine\gamelogic\SCA_GameLogic.lib"
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "SCA_GameLogic - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "SCA_GameLogic___Win32_Profile"
+# PROP BASE Intermediate_Dir "SCA_GameLogic___Win32_Profile"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "SCA_GameLogic___Win32_Profile"
+# PROP Intermediate_Dir "SCA_GameLogic___Win32_Profile"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\source\kernel\gen_system" /I "..\..\..\source\gameengine\expressions" /I "..\..\..\lib\windows\moto\include" /I "..\..\..\lib\windows\python\include\python1.5" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "EXP_PYTHON_EMBEDDING" /YX /J /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /O2 /I "..\..\..\lib\windows\python\include\python2.0" /I "..\..\..\lib\windows\string\include" /I "..\..\..\source\gameengine\ketsji" /I "..\..\..\source\kernel\gen_system" /I "..\..\..\source\gameengine\expressions" /I "..\..\..\lib\windows\moto\include" /D "WIN32" /D "_MBCS" /D "_LIB" /D "EXP_PYTHON_EMBEDDING" /U "_DEBUG" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\obj\windows\gameengine\gamelogic\debug\SCA_GameLogic.lib"
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\gameengine\gamelogic\profile\SCA_GameLogic.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "SCA_GameLogic - Win32 Release"
+# Name "SCA_GameLogic - Win32 Debug"
+# Name "SCA_GameLogic - Win32 MT DLL Debug"
+# Name "SCA_GameLogic - Win32 MT DLL Release"
+# Name "SCA_GameLogic - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\GameLogic\SCA_AlwaysEventManager.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\GameLogic\SCA_AlwaysSensor.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\GameLogic\SCA_ANDController.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\GameLogic\SCA_EventManager.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\GameLogic\SCA_ExpressionController.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\GameLogic\SCA_IActuator.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\GameLogic\SCA_IController.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\GameLogic\SCA_IInputDevice.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\GameLogic\SCA_ILogicBrick.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\GameLogic\SCA_IObject.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\GameLogic\SCA_IScene.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\GameLogic\SCA_ISensor.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\GameLogic\SCA_KeyboardManager.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\GameLogic\SCA_KeyboardSensor.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\GameLogic\SCA_LogicManager.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\GameLogic\SCA_MouseManager.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\GameLogic\SCA_MouseSensor.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\GameLogic\SCA_ORController.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\GameLogic\SCA_PropertyActuator.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\GameLogic\SCA_PropertyEventManager.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\GameLogic\SCA_PropertySensor.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\GameLogic\SCA_PythonController.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\GameLogic\SCA_RandomActuator.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\GameLogic\SCA_RandomEventManager.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\GameLogic\SCA_RandomNumberGenerator.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\GameLogic\SCA_RandomSensor.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\GameLogic\SCA_TimeEventManager.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\GameLogic\SCA_AlwaysEventManager.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\GameLogic\SCA_AlwaysSensor.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\GameLogic\SCA_ANDController.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\GameLogic\SCA_EventManager.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\GameLogic\SCA_ExpressionController.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\GameLogic\SCA_IActuator.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\GameLogic\SCA_IController.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\GameLogic\SCA_IInputDevice.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\GameLogic\SCA_ILogicBrick.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\GameLogic\SCA_IObject.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\GameLogic\SCA_IScene.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\GameLogic\SCA_ISensor.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\GameLogic\SCA_KeyboardManager.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\GameLogic\SCA_KeyboardSensor.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\GameLogic\SCA_LogicManager.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\GameLogic\SCA_MouseManager.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\GameLogic\SCA_MouseSensor.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\GameLogic\SCA_ORController.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\GameLogic\SCA_PropertyActuator.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\GameLogic\SCA_PropertyEventManager.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\GameLogic\SCA_PropertySensor.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\GameLogic\SCA_PythonController.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\GameLogic\SCA_RandomActuator.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\GameLogic\SCA_RandomEventManager.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\GameLogic\SCA_RandomNumberGenerator.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\GameLogic\SCA_RandomSensor.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\GameLogic\SCA_TimeEventManager.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/gameengine/gameplayer/axctl/GP_axctl.dsp b/projectfiles/gameengine/gameplayer/axctl/GP_axctl.dsp
new file mode 100644
index 00000000000..8650b90a0f0
--- /dev/null
+++ b/projectfiles/gameengine/gameplayer/axctl/GP_axctl.dsp
@@ -0,0 +1,319 @@
+# Microsoft Developer Studio Project File - Name="GP_axctl" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=GP_axctl - Win32 Profile
+!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 "GP_axctl.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 "GP_axctl.mak" CFG="GP_axctl - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "GP_axctl - Win32 MT DLL Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "GP_axctl - Win32 MT DLL Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "GP_axctl - Win32 Profile" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "GP_axctl - Win32 MT DLL Debug"
+
+# PROP BASE Use_MFC 2
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "GP_axctl___Win32_MT_DLL_Debug"
+# PROP BASE Intermediate_Dir "GP_axctl___Win32_MT_DLL_Debug"
+# PROP BASE Target_Ext "ocx"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 2
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\..\..\..\..\obj\windows\gameengine\gameplayer\axctl\mtdll_debug"
+# PROP Intermediate_Dir "..\..\..\..\..\obj\windows\gameengine\gameplayer\axctl\mtdll_debug"
+# PROP Target_Ext "ocx"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\network" /I "..\..\..\..\source\gameengine\network\loopbacknetwork" /I "..\..\..\..\source\gameengine\gameplayer\common" /I "..\..\..\..\source\gameengine\rasterizer" /I "..\..\..\..\source\gameengine\gamelogic" /I "..\..\..\..\source\sumo\include" /I "..\..\..\..\lib\windows\moto\include" /I "..\..\..\..\source\sumo\Fuzzics\include" /I "..\..\..\..\lib\windows\python\include\python1.5" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_WINDLL" /D "_AFXDLL" /D "_MBCS" /D "_USRDLL" /FR /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\..\lib\windows\python\include\python2.0" /I "..\..\..\..\source\kernel\gen_messaging" /I "..\..\..\..\lib\windows\bmfont\include" /I "..\..\..\..\lib\windows\string\include" /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\expressions" /I "..\..\..\..\source\gameengine\ketsji" /I "..\..\..\..\source\gameengine\ketsji\kxnetwork" /I "..\..\..\..\source\gameengine\rasterizer" /I "..\..\..\..\source\gameengine\rasterizer\ras_openglrasterizer" /I "..\..\..\..\source\gameengine\scenegraph" /I "..\..\..\..\source\gameengine\gamelogic" /I "..\..\..\..\source\gameengine\soundsystem" /I "..\..\..\..\source\gameengine\soundsystem\snd_openal" /I "..\..\..\..\source\gameengine\network" /I "..\..\..\..\source\gameengine\network\loopbacknetwork" /I "..\..\..\..\source\sumo\include" /I "..\..\..\..\lib\windows\moto\include" /I "..\..\..\..\source\sumo\fuzzics\include" /I "..\..\..\..\lib\windows\openal\include" /I "..\..\..\..\source\gameengine\gameplayer\common" /I "../../../../source/blender/blenkernel" /I "../../../../source/blender/makesdna" /I "../../../../source/blender/blenlib" /I "../../../../source/blender/blenloader" /I "../../../../source/blender/render/extern/include" /I "../../../../source/blender/imbuf" /I "..\..\..\..\source\gameengine\converter" /I "..\..\..\..\source\gameengine\GamePlayer\common" /I "..\..\..\..\source\gameengine\GamePlayer\common\windows" /I "..\..\..\..\lib\windows\iksolver\include" /D "WIN32" /D "_WINDOWS" /D "_WINDLL" /D "_AFXDLL" /D "_MBCS" /D "_USRDLL" /U "_DEBUG" /YX /FD /GZ /c
+# SUBTRACT CPP /Fr
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG" /d "_AFXDLL"
+# ADD RSC /l 0x409 /d "_DEBUG" /d "_AFXDLL"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 opengl32.lib glu32.lib glaux.lib /nologo /subsystem:windows /dll /debug /machine:I386 /out:"Debug/ActiveXgp.ocx" /pdbtype:sept /libpath:"..\..\..\..\lib\windows\python\lib" /libpath:"..\..\..\..\lib\windows\openal\lib\lib_release"
+# SUBTRACT BASE LINK32 /nodefaultlib
+# ADD LINK32 libmoto.a libguardedalloc.a libbmfont.a libstring.a ws2_32.lib opengl32.lib glu32.lib glaux.lib dxguid.lib ole32.lib vfw32.lib libjpeg.lib libblenkey.a libeay32.lib libz.a libpng.a fmodvc.lib /nologo /subsystem:windows /dll /debug /machine:I386 /nodefaultlib:"libcd.lib" /nodefaultlib:"libc.lib" /nodefaultlib:"libcmtd.lib" /nodefaultlib:"msvcrtd.lib" /nodefaultlib:"mfc42.lib" /nodefaultlib:"mfcs42.lib" /out:"..\..\..\..\..\obj\windows\debug\Blender3DPlugin.ocx" /pdbtype:sept /libpath:"../../../../lib/windows/fmod/lib" /libpath:"../../../../lib/windows/guardedalloc/lib" /libpath:"../../../../lib/windows/openal/lib/debug_MT" /libpath:"../../../../lib/windows/moto/lib" /libpath:"../../../../lib/windows/bmfont/lib" /libpath:"../../../../lib/windows/string/lib" /libpath:"../../../../lib/windows/python/lib" /libpath:"../../../../lib/windows/jpeg/lib" /libpath:"..\..\..\..\lib\windows\openssl\lib\mt_dll" /libpath:"..\..\..\..\lib\windows\zlib\lib\\" /libpath:"..\..\..\..\lib\windows\blenkey\lib\\" /libpath:"..\..\..\..\lib\windows\png\lib"
+# SUBTRACT LINK32 /nodefaultlib
+# Begin Custom Build - Registering ActiveX Control...
+OutDir=.\..\..\..\..\..\obj\windows\gameengine\gameplayer\axctl\mtdll_debug
+TargetPath=\Documents and Settings\maarten\My Documents\obj\windows\debug\Blender3DPlugin.ocx
+InputPath=\Documents and Settings\maarten\My Documents\obj\windows\debug\Blender3DPlugin.ocx
+SOURCE="$(InputPath)"
+
+"$(OutDir)\regsvr32.trg" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ regsvr32 /s /c "$(TargetPath)"
+ echo regsvr32 exec. time > "$(OutDir)\regsvr32.trg"
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "GP_axctl - Win32 MT DLL Release"
+
+# PROP BASE Use_MFC 2
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "GP_axctl___Win32_MT_DLL_Release"
+# PROP BASE Intermediate_Dir "GP_axctl___Win32_MT_DLL_Release"
+# PROP BASE Target_Ext "ocx"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 2
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\..\..\..\..\obj\windows\gameengine\gameplayer\axctl\mtdll"
+# PROP Intermediate_Dir "..\..\..\..\..\obj\windows\gameengine\gameplayer\axctl\mtdll"
+# PROP Target_Ext "ocx"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_WINDLL" /D "_AFXDLL" /D "_MBCS" /D "_USRDLL" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\..\..\source\kernel\gen_messaging" /I "..\..\..\..\lib\windows\python\include\python2.0" /I "..\..\..\..\lib\windows\bmfont\include" /I "..\..\..\..\lib\windows\string\include" /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\expressions" /I "..\..\..\..\source\gameengine\ketsji" /I "..\..\..\..\source\gameengine\ketsji\kxnetwork" /I "..\..\..\..\source\gameengine\rasterizer" /I "..\..\..\..\source\gameengine\rasterizer\ras_openglrasterizer" /I "..\..\..\..\source\gameengine\scenegraph" /I "..\..\..\..\source\gameengine\gamelogic" /I "..\..\..\..\source\gameengine\soundsystem" /I "..\..\..\..\source\gameengine\soundsystem\snd_openal" /I "..\..\..\..\source\gameengine\network" /I "..\..\..\..\source\gameengine\network\loopbacknetwork" /I "..\..\..\..\source\sumo\include" /I "..\..\..\..\lib\windows\moto\include" /I "..\..\..\..\source\sumo\fuzzics\include" /I "..\..\..\..\lib\windows\openal\include" /I "..\..\..\..\source\gameengine\gameplayer\common" /I "../../../../source/blender/blenkernel" /I "../../../../source/blender/makesdna" /I "../../../../source/blender/blenlib" /I "../../../../source/blender/blenloader" /I "../../../../source/blender/render/extern/include" /I "../../../../source/blender/imbuf" /I "..\..\..\..\source\gameengine\converter" /I "..\..\..\..\source\gameengine\GamePlayer\common" /I "..\..\..\..\source\gameengine\GamePlayer\common\windows" /I "..\..\..\..\lib\windows\iksolver\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_WINDLL" /D "_AFXDLL" /D "_MBCS" /D "_USRDLL" /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG" /d "_AFXDLL"
+# ADD RSC /l 0x409 /d "NDEBUG" /d "_AFXDLL"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 opengl32.lib glu32.lib glaux.lib /nologo /subsystem:windows /dll /machine:I386 /out:"Release/ActiveXgp.ocx"
+# ADD LINK32 fmodvc.lib libmoto.a libguardedalloc.a libbmfont.a libstring.a ws2_32.lib opengl32.lib glu32.lib glaux.lib dxguid.lib ole32.lib vfw32.lib libjpeg.lib openal_static.lib libblenkey.a libeay32.lib libz.a libpng.a /nologo /subsystem:windows /dll /machine:I386 /nodefaultlib:"libcd.lib" /nodefaultlib:"libc.lib" /nodefaultlib:"libcmt.lib" /nodefaultlib:"msvcrtd.lib" /out:"..\..\..\..\..\obj\windows\Blender3DPlugin.ocx" /libpath:"../../../../lib/windows/fmod/lib" /libpath:"../../../../lib/windows/guardedalloc/lib" /libpath:"../../../../lib/windows/openal/lib/release_MT" /libpath:"../../../../lib/windows/moto/lib" /libpath:"../../../../lib/windows/bmfont/lib" /libpath:"../../../../lib/windows/string/lib" /libpath:"../../../../lib/windows/python/lib" /libpath:"../../../../lib/windows/jpeg/lib" /libpath:"..\..\..\..\lib\windows\openssl\lib\mt_dll" /libpath:"..\..\..\..\lib\windows\zlib\lib\\" /libpath:"..\..\..\..\lib\windows\blenkey\lib\\" /libpath:"..\..\..\..\lib\windows\png\lib"
+# Begin Custom Build - Registering ActiveX Control...
+OutDir=.\..\..\..\..\..\obj\windows\gameengine\gameplayer\axctl\mtdll
+TargetPath=\Documents and Settings\maarten\My Documents\obj\windows\Blender3DPlugin.ocx
+InputPath=\Documents and Settings\maarten\My Documents\obj\windows\Blender3DPlugin.ocx
+SOURCE="$(InputPath)"
+
+"$(OutDir)\regsvr32.trg" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ regsvr32 /s /c "$(TargetPath)"
+ echo regsvr32 exec. time > "$(OutDir)\regsvr32.trg"
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "GP_axctl - Win32 Profile"
+
+# PROP BASE Use_MFC 2
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "GP_axctl___Win32_Profile"
+# PROP BASE Intermediate_Dir "GP_axctl___Win32_Profile"
+# PROP BASE Target_Ext "ocx"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 2
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "GP_axctl___Win32_Profile"
+# PROP Intermediate_Dir "GP_axctl___Win32_Profile"
+# PROP Target_Ext "ocx"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\expressions" /I "..\..\..\..\source\gameengine\ketsji" /I "..\..\..\..\source\gameengine\ketsji\kxnetwork" /I "..\..\..\..\source\gameengine\rasterizer" /I "..\..\..\..\source\gameengine\rasterizer\ras_openglrasterizer" /I "..\..\..\..\source\gameengine\scenegraph" /I "..\..\..\..\source\gameengine\gamelogic" /I "..\..\..\..\source\gameengine\soundsystem" /I "..\..\..\..\source\gameengine\soundsystem\snd_openal" /I "..\..\..\..\source\gameengine\network" /I "..\..\..\..\source\gameengine\network\loopbacknetwork" /I "..\..\..\..\source\sumo\include" /I "..\..\..\..\lib\windows\moto\include" /I "..\..\..\..\source\sumo\fuzzics\include" /I "..\..\..\..\lib\windows\openal\include" /I "..\..\..\..\lib\windows\python\include\python1.5" /I "..\..\..\..\source\gameengine\gameplayer\common" /I "../../../../source/blender/blenkernel" /I "../../../../source/blender/makesdna" /I "../../../../source/blender/blenlib" /I "../../../../source/blender/blenloader" /I "../../../../source/blender/render/extern/include" /I "../../../../source/blender/imbuf" /I "..\..\..\..\source\gameengine\converter" /I "..\..\..\..\source\gameengine\GamePlayer\common" /I "..\..\..\..\source\gameengine\GamePlayer\common\windows" /I "..\..\..\..\lib\windows\iksolver\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_WINDLL" /D "_AFXDLL" /D "_MBCS" /D "_USRDLL" /YX /FD /GZ /c
+# SUBTRACT BASE CPP /Fr
+# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /O2 /I "..\..\..\..\lib\windows\python\include\python2.0" /I "..\..\..\..\lib\windows\bmfont\include" /I "..\..\..\..\lib\windows\string\include" /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\expressions" /I "..\..\..\..\source\gameengine\ketsji" /I "..\..\..\..\source\gameengine\ketsji\kxnetwork" /I "..\..\..\..\source\gameengine\rasterizer" /I "..\..\..\..\source\gameengine\rasterizer\ras_openglrasterizer" /I "..\..\..\..\source\gameengine\scenegraph" /I "..\..\..\..\source\gameengine\gamelogic" /I "..\..\..\..\source\gameengine\soundsystem" /I "..\..\..\..\source\gameengine\soundsystem\snd_openal" /I "..\..\..\..\source\gameengine\network" /I "..\..\..\..\source\gameengine\network\loopbacknetwork" /I "..\..\..\..\source\sumo\include" /I "..\..\..\..\lib\windows\moto\include" /I "..\..\..\..\source\sumo\fuzzics\include" /I "..\..\..\..\lib\windows\openal\include" /I "..\..\..\..\source\gameengine\gameplayer\common" /I "../../../../source/blender/blenkernel" /I "../../../../source/blender/makesdna" /I "../../../../source/blender/blenlib" /I "../../../../source/blender/blenloader" /I "../../../../source/blender/render/extern/include" /I "../../../../source/blender/imbuf" /I "..\..\..\..\source\gameengine\converter" /I "..\..\..\..\source\gameengine\GamePlayer\common" /I "..\..\..\..\source\gameengine\GamePlayer\common\windows" /I "..\..\..\..\lib\windows\iksolver\include" /D "WIN32" /D "_WINDOWS" /D "_WINDLL" /D "_AFXDLL" /D "_MBCS" /D "_USRDLL" /U "_DEBUG" /YX /FD /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG" /d "_AFXDLL"
+# ADD RSC /l 0x409 /d "_DEBUG" /d "_AFXDLL"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 opengl32.lib glu32.lib glaux.lib dxguid.lib ole32.lib libjpeg.lib openal_static.lib /nologo /subsystem:windows /dll /debug /machine:I386 /out:"..\..\..\..\..\obj\windows\debug\BlenderPlayer.ocx" /pdbtype:sept /libpath:"../../../../lib/windows/python/lib" /libpath:"../../../../lib/windows/jpeg/lib" /libpath:"../../../../lib/windows/openal/lib/debug_MT"
+# SUBTRACT BASE LINK32 /nodefaultlib
+# ADD LINK32 libbmfont.a libstring.a ws2_32.lib opengl32.lib glu32.lib glaux.lib dxguid.lib ole32.lib libjpeg.lib openal_static.lib libblenkey.a libeay32.lib libz.a libpng.a /nologo /subsystem:windows /dll /debug /machine:I386 /out:"..\..\..\..\..\obj\windows\profile\BlenderPlayer.ocx" /pdbtype:sept /libpath:"../../../../lib/windows/openal/lib/debug_MT" /libpath:"../../../../lib/windows/bmfont/lib" /libpath:"../../../../lib/windows/string/lib" /libpath:"../../../../lib/windows/python/lib" /libpath:"../../../../lib/windows/jpeg/lib" /libpath:"..\..\..\..\lib\windows\openssl\lib" /libpath:"..\..\..\..\lib\windows\zlib\lib\\" /libpath:"..\..\..\..\lib\windows\blenkey\lib\\" /libpath:"..\..\..\..\lib\windows\png\lib"
+# SUBTRACT LINK32 /nodefaultlib
+# Begin Custom Build - Registering ActiveX Control...
+OutDir=.\GP_axctl___Win32_Profile
+TargetPath=\Documents and Settings\maarten\My Documents\obj\windows\profile\BlenderPlayer.ocx
+InputPath=\Documents and Settings\maarten\My Documents\obj\windows\profile\BlenderPlayer.ocx
+SOURCE="$(InputPath)"
+
+"$(OutDir)\regsvr32.trg" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ regsvr32 /s /c "$(TargetPath)"
+ echo regsvr32 exec. time > "$(OutDir)\regsvr32.trg"
+
+# End Custom Build
+
+!ENDIF
+
+# Begin Target
+
+# Name "GP_axctl - Win32 MT DLL Debug"
+# Name "GP_axctl - Win32 MT DLL Release"
+# Name "GP_axctl - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\ActiveX\BlenderDataPathProperty.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\ActiveX\BlenderPlayer.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\ActiveX\BlenderPlayer.def
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\ActiveX\BlenderPlayer.odl
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\ActiveX\BlenderPlayer.rc
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\ActiveX\BlenderPlayerCtl.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\ActiveX\BlenderPlayerPpg.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\ActiveX\CControlRefresher.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\blender\makesdna\intern\dna.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\ActiveX\MemoryResource.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\ActiveX\RawImageRsrc.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\ActiveX\SafeControl.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\ActiveX\StdAfx.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\blender\blenkernel\bad_level_call_stubs\stubs.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\ActiveX\BlenderDataPathProperty.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\ActiveX\BlenderPlayer.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\ActiveX\BlenderPlayerCtl.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\ActiveX\BlenderPlayerPpg.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\ActiveX\CControlRefresher.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\ActiveX\MemoryResource.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\ActiveX\RawImageRsrc.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\ActiveX\Resource.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\ActiveX\SafeControl.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"
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\ActiveX\BlenderPlayer.ico
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\ActiveX\BlenderPlayerCtl.bmp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\ActiveX\splash.bmp
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\ActiveX\ActiveXandNetscapeTest.html
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\ActiveX\BlenderPlayer.html
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\ActiveX\BlenderPlayerDuo.html
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\common\load.blend
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\common\logo_blender.raw
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\common\logo_blender3d.raw
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\common\logo_nan.raw
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\ActiveX\ReadMe.txt
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\ActiveX\ReadMeBuilding.txt
+# End Source File
+# End Target
+# End Project
diff --git a/projectfiles/gameengine/gameplayer/common/GP_common.dsp b/projectfiles/gameengine/gameplayer/common/GP_common.dsp
new file mode 100644
index 00000000000..89c4e8d6eca
--- /dev/null
+++ b/projectfiles/gameengine/gameplayer/common/GP_common.dsp
@@ -0,0 +1,281 @@
+# Microsoft Developer Studio Project File - Name="GP_common" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=GP_common - Win32 Profile
+!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 "GP_common.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 "GP_common.mak" CFG="GP_common - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "GP_common - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "GP_common - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "GP_common - Win32 MT DLL Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "GP_common - Win32 MT DLL Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "GP_common - Win32 Profile" (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)" == "GP_common - 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 "..\..\..\..\..\obj\windows\gameengine\gameplayer\common"
+# 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 "..\..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\..\source\gameengine\Converter" /I "..\..\..\..\source\gameengine\soundsystem\snd_dummy" /I "..\..\..\..\lib\windows\python\include\python2.0" /I "..\..\..\..\lib\windows\bmfont\include" /I "..\..\..\..\lib\windows\string\include" /I "..\..\..\lib\windows\string\include" /I "..\..\..\..\source\gameengine\expressions" /I "..\..\..\..\source\gameengine\ketsji" /I "..\..\..\..\source\gameengine\GamePlayer\common\\" /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\ketsji\kxnetwork" /I "..\..\..\..\source\gameengine\rasterizer" /I "..\..\..\..\source\gameengine\rasterizer\ras_openglrasterizer" /I "..\..\..\..\source\gameengine\scenegraph" /I "..\..\..\..\source\gameengine\gamelogic" /I "..\..\..\..\source\gameengine\soundsystem" /I "..\..\..\..\source\gameengine\soundsystem\snd_openal" /I "..\..\..\..\source\gameengine\network" /I "..\..\..\..\source\gameengine\network\loopbacknetwork" /I "..\..\..\..\source\sumo\include" /I "..\..\..\..\lib\windows\moto\include" /I "..\..\..\..\source\sumo\fuzzics\include" /I "..\..\..\..\lib\windows\openal\include" /I "../../../../source/blender/blenkernel" /I "../../../../source/blender/makesdna" /I "../../../../source/blender/blenlib" /I "../../../../source/blender/blenloader" /I "../../../../source/blender/render/extern/include" /I "../../../../source/blender/imbuf" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\..\obj\windows\gameengine\gameplayer\common\GP_common.lib"
+
+!ELSEIF "$(CFG)" == "GP_common - 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 "..\..\..\..\..\obj\windows\gameengine\gameplayer\common\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\python\include\python2.0" /I "..\..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\..\source\gameengine\Converter" /I "..\..\..\..\source\gameengine\soundsystem\snd_dummy" /I "..\..\..\..\lib\windows\bmfont\include" /I "..\..\..\..\lib\windows\string\include" /I "..\..\..\lib\windows\string\include" /I "..\..\..\..\source\gameengine\expressions" /I "..\..\..\..\source\gameengine\ketsji" /I "..\..\..\..\source\gameengine\GamePlayer\common\\" /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\ketsji\kxnetwork" /I "..\..\..\..\source\gameengine\rasterizer" /I "..\..\..\..\source\gameengine\rasterizer\ras_openglrasterizer" /I "..\..\..\..\source\gameengine\scenegraph" /I "..\..\..\..\source\gameengine\gamelogic" /I "..\..\..\..\source\gameengine\soundsystem" /I "..\..\..\..\source\gameengine\soundsystem\snd_openal" /I "..\..\..\..\source\gameengine\network" /I "..\..\..\..\source\gameengine\network\loopbacknetwork" /I "..\..\..\..\source\sumo\include" /I "..\..\..\..\lib\windows\moto\include" /I "..\..\..\..\source\sumo\fuzzics\include" /I "..\..\..\..\lib\windows\openal\include" /I "../../../../source/blender/blenkernel" /I "../../../../source/blender/makesdna" /I "../../../../source/blender/blenlib" /I "../../../../source/blender/blenloader" /I "../../../../source/blender/render/extern/include" /I "../../../../source/blender/imbuf" /D "WIN32" /D "_MBCS" /D "_LIB" /U "_DEBUG" /YX /FD /GZ /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\..\obj\windows\gameengine\gameplayer\common\debug\GP_common.lib"
+
+!ELSEIF "$(CFG)" == "GP_common - Win32 MT DLL Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "GP_common___Win32_MT_DLL_Debug"
+# PROP BASE Intermediate_Dir "GP_common___Win32_MT_DLL_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\..\..\..\..\obj\windows\gameengine\gameplayer\common\mtdll_debug"
+# PROP Intermediate_Dir "..\..\..\..\..\obj\windows\gameengine\gameplayer\common\mtdll_debug"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /MDd /Gm /GX /ZI /Od /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\expressions" /I "..\..\..\..\source\gameengine\ketsji" /I "..\..\..\..\source\gameengine\ketsji\kxnetwork" /I "..\..\..\..\source\gameengine\rasterizer" /I "..\..\..\..\source\gameengine\rasterizer\ras_openglrasterizer" /I "..\..\..\..\source\gameengine\scenegraph" /I "..\..\..\..\source\gameengine\gamelogic" /I "..\..\..\..\source\gameengine\soundsystem" /I "..\..\..\..\source\gameengine\soundsystem\snd_openal" /I "..\..\..\..\source\gameengine\network" /I "..\..\..\..\source\gameengine\network\loopbacknetwork" /I "..\..\..\..\source\sumo\include" /I "..\..\..\..\lib\windows\moto\include" /I "..\..\..\..\source\sumo\fuzzics\include" /I "..\..\..\..\lib\windows\openal\include" /I "..\..\..\..\lib\windows\python\include\python1.5" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /Gm /GX /ZI /Od /I "..\..\..\..\lib\windows\python\include\python2.0" /I "..\..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\..\source\gameengine\Converter" /I "..\..\..\..\source\gameengine\soundsystem\snd_dummy" /I "..\..\..\..\lib\windows\bmfont\include" /I "..\..\..\..\lib\windows\string\include" /I "..\..\..\lib\windows\string\include" /I "..\..\..\..\source\gameengine\expressions" /I "..\..\..\..\source\gameengine\ketsji" /I "..\..\..\..\source\gameengine\GamePlayer\common\\" /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\ketsji\kxnetwork" /I "..\..\..\..\source\gameengine\rasterizer" /I "..\..\..\..\source\gameengine\rasterizer\ras_openglrasterizer" /I "..\..\..\..\source\gameengine\scenegraph" /I "..\..\..\..\source\gameengine\gamelogic" /I "..\..\..\..\source\gameengine\soundsystem" /I "..\..\..\..\source\gameengine\soundsystem\snd_openal" /I "..\..\..\..\source\gameengine\network" /I "..\..\..\..\source\gameengine\network\loopbacknetwork" /I "..\..\..\..\source\sumo\include" /I "..\..\..\..\lib\windows\moto\include" /I "..\..\..\..\source\sumo\fuzzics\include" /I "..\..\..\..\lib\windows\openal\include" /I "../../../../source/blender/blenkernel" /I "../../../../source/blender/makesdna" /I "../../../../source/blender/blenlib" /I "../../../../source/blender/blenloader" /I "../../../../source/blender/render/extern/include" /I "../../../../source/blender/imbuf" /D "WIN32" /D "_MBCS" /D "_LIB" /U "_DEBUG" /YX /FD /GZ /c
+# SUBTRACT CPP /Fr
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\..\obj\windows\gameengine\gameplayer\common\debug\GP_common.lib"
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "GP_common - Win32 MT DLL Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "GP_common___Win32_MT_DLL_Release"
+# PROP BASE Intermediate_Dir "GP_common___Win32_MT_DLL_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\..\..\..\..\obj\windows\gameengine\gameplayer\common\mtdll"
+# PROP Intermediate_Dir "..\..\..\..\..\obj\windows\gameengine\gameplayer\common\mtdll"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /GX /O2 /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\expressions" /I "..\..\..\..\source\gameengine\ketsji" /I "..\..\..\..\source\gameengine\ketsji\kxnetwork" /I "..\..\..\..\source\gameengine\rasterizer" /I "..\..\..\..\source\gameengine\rasterizer\ras_openglrasterizer" /I "..\..\..\..\source\gameengine\scenegraph" /I "..\..\..\..\source\gameengine\gamelogic" /I "..\..\..\..\source\gameengine\soundsystem" /I "..\..\..\..\source\gameengine\soundsystem\snd_openal" /I "..\..\..\..\source\gameengine\network" /I "..\..\..\..\source\gameengine\network\loopbacknetwork" /I "..\..\..\..\source\sumo\include" /I "..\..\..\..\lib\windows\moto\include" /I "..\..\..\..\source\sumo\fuzzics\include" /I "..\..\..\..\lib\windows\openal\include" /I "..\..\..\..\lib\windows\python\include\python2.0" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD CPP /nologo /MD /GX /O2 /I "..\..\..\..\lib\windows\guardedalloc\include" /I "..\..\..\..\source\gameengine\Converter" /I "..\..\..\..\source\gameengine\soundsystem\snd_dummy" /I "..\..\..\..\lib\windows\python\include\python1.5" /I "..\..\..\..\lib\windows\python\include\python2.0" /I "..\..\..\..\lib\windows\bmfont\include" /I "..\..\..\..\lib\windows\string\include" /I "..\..\..\lib\windows\string\include" /I "..\..\..\..\source\gameengine\expressions" /I "..\..\..\..\source\gameengine\ketsji" /I "..\..\..\..\source\gameengine\GamePlayer\common\\" /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\ketsji\kxnetwork" /I "..\..\..\..\source\gameengine\rasterizer" /I "..\..\..\..\source\gameengine\rasterizer\ras_openglrasterizer" /I "..\..\..\..\source\gameengine\scenegraph" /I "..\..\..\..\source\gameengine\gamelogic" /I "..\..\..\..\source\gameengine\soundsystem" /I "..\..\..\..\source\gameengine\soundsystem\snd_openal" /I "..\..\..\..\source\gameengine\network" /I "..\..\..\..\source\gameengine\network\loopbacknetwork" /I "..\..\..\..\source\sumo\include" /I "..\..\..\..\lib\windows\moto\include" /I "..\..\..\..\source\sumo\fuzzics\include" /I "..\..\..\..\lib\windows\openal\include" /I "../../../../source/blender/blenkernel" /I "../../../../source/blender/makesdna" /I "../../../../source/blender/blenlib" /I "../../../../source/blender/blenloader" /I "../../../../source/blender/render/extern/include" /I "../../../../source/blender/imbuf" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\..\obj\windows\gameengine\gameplayer\common\GP_common.lib"
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "GP_common - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "GP_common___Win32_Profile"
+# PROP BASE Intermediate_Dir "GP_common___Win32_Profile"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "GP_common___Win32_Profile"
+# PROP Intermediate_Dir "GP_common___Win32_Profile"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\..\source\gameengine\expressions" /I "..\..\..\..\source\gameengine\ketsji" /I "..\..\..\..\source\gameengine\GamePlayer\common\\" /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\ketsji\kxnetwork" /I "..\..\..\..\source\gameengine\rasterizer" /I "..\..\..\..\source\gameengine\rasterizer\ras_openglrasterizer" /I "..\..\..\..\source\gameengine\scenegraph" /I "..\..\..\..\source\gameengine\gamelogic" /I "..\..\..\..\source\gameengine\soundsystem" /I "..\..\..\..\source\gameengine\soundsystem\snd_openal" /I "..\..\..\..\source\gameengine\network" /I "..\..\..\..\source\gameengine\network\loopbacknetwork" /I "..\..\..\..\source\sumo\include" /I "..\..\..\..\lib\windows\moto\include" /I "..\..\..\..\source\sumo\fuzzics\include" /I "..\..\..\..\lib\windows\openal\include" /I "..\..\..\..\lib\windows\python\include\python1.5" /I "../../../../source/blender/blenkernel" /I "../../../../source/blender/makesdna" /I "../../../../source/blender/blenlib" /I "../../../../source/blender/blenloader" /I "../../../../source/blender/render/extern/include" /I "../../../../source/blender/imbuf" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /FD /GZ /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /O2 /I "..\..\..\..\lib\windows\python\include\python2.0" /I "..\..\..\..\lib\windows\bmfont\include" /I "..\..\..\..\lib\windows\string\include" /I "..\..\..\lib\windows\string\include" /I "..\..\..\..\source\gameengine\expressions" /I "..\..\..\..\source\gameengine\ketsji" /I "..\..\..\..\source\gameengine\GamePlayer\common\\" /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\ketsji\kxnetwork" /I "..\..\..\..\source\gameengine\rasterizer" /I "..\..\..\..\source\gameengine\rasterizer\ras_openglrasterizer" /I "..\..\..\..\source\gameengine\scenegraph" /I "..\..\..\..\source\gameengine\gamelogic" /I "..\..\..\..\source\gameengine\soundsystem" /I "..\..\..\..\source\gameengine\soundsystem\snd_openal" /I "..\..\..\..\source\gameengine\network" /I "..\..\..\..\source\gameengine\network\loopbacknetwork" /I "..\..\..\..\source\sumo\include" /I "..\..\..\..\lib\windows\moto\include" /I "..\..\..\..\source\sumo\fuzzics\include" /I "..\..\..\..\lib\windows\openal\include" /I "../../../../source/blender/blenkernel" /I "../../../../source/blender/makesdna" /I "../../../../source/blender/blenlib" /I "../../../../source/blender/blenloader" /I "../../../../source/blender/render/extern/include" /I "../../../../source/blender/imbuf" /D "WIN32" /D "_MBCS" /D "_LIB" /U "_DEBUG" /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 /out:"..\..\..\..\..\obj\windows\gameengine\gameplayer\common\debug\GP_common.lib"
+# ADD LIB32 /nologo /out:"..\..\..\..\..\obj\windows\gameengine\gameplayer\common\profile\GP_common.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "GP_common - Win32 Release"
+# Name "GP_common - Win32 Debug"
+# Name "GP_common - Win32 MT DLL Debug"
+# Name "GP_common - Win32 MT DLL Release"
+# Name "GP_common - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\common\bmfont.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\common\GPC_Canvas.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\common\GPC_Engine.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\common\GPC_KeyboardDevice.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\common\GPC_MouseDevice.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\common\GPC_PolygonMaterial.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\common\GPC_RawImage.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\common\GPC_RawLoadDotBlendArray.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\common\GPC_RawLogoArrays.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\common\GPC_RenderTools.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\common\GPC_System.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\common\windows\GPW_Canvas.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\common\windows\GPW_Engine.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\common\windows\GPW_KeyboardDevice.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\common\windows\GPW_System.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\common\GPC_Canvas.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\common\GPC_Engine.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\common\GPC_KeyboardDevice.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\common\GPC_MouseDevice.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\common\GPC_PolygonMaterial.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\common\GPC_RenderTools.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\common\GPC_System.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\common\windows\GPW_Canvas.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\common\windows\GPW_Engine.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\common\windows\GPW_KeyboardDevice.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\common\windows\GPW_System.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\common\Makefile
+# End Source File
+# End Target
+# End Project
diff --git a/projectfiles/gameengine/gameplayer/ghost/GP_ghost.dsp b/projectfiles/gameengine/gameplayer/ghost/GP_ghost.dsp
new file mode 100644
index 00000000000..0778a4ed3d2
--- /dev/null
+++ b/projectfiles/gameengine/gameplayer/ghost/GP_ghost.dsp
@@ -0,0 +1,184 @@
+# Microsoft Developer Studio Project File - Name="GP_ghost" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=GP_ghost - Win32 Profile
+!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 "GP_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 "GP_ghost.mak" CFG="GP_ghost - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "GP_ghost - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "GP_ghost - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE "GP_ghost - Win32 Profile" (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)" == "GP_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\"
+# PROP Intermediate_Dir "..\..\..\..\..\obj\windows\gameengine\gameplayer\ghost\"
+# 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 "../../../../lib/windows/moto/include" /I "..\..\..\..\source\gameengine\Physics\Ode" /I "..\..\..\..\source\gameengine\Physics" /I "..\..\..\..\lib\windows\python\include\python2.0" /I "..\..\..\..\lib\windows\bmfont\include" /I "..\..\..\..\source\kernel\gen_messaging" /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\expressions" /I "..\..\..\..\source\gameengine\ketsji" /I "..\..\..\..\source\gameengine\ketsji\kxnetwork" /I "..\..\..\..\source\gameengine\rasterizer" /I "..\..\..\..\source\gameengine\rasterizer\ras_openglrasterizer" /I "..\..\..\..\source\gameengine\scenegraph" /I "..\..\..\..\source\gameengine\gamelogic" /I "..\..\..\..\source\gameengine\soundsystem" /I "..\..\..\..\source\gameengine\soundsystem\snd_openal" /I "..\..\..\..\source\gameengine\network" /I "..\..\..\..\source\gameengine\network\loopbacknetwork" /I "..\..\..\..\source\sumo\include" /I "..\..\..\..\source\sumo\fuzzics\include" /I "..\..\..\..\lib\windows\openal\include" /I "..\..\..\..\source\gameengine\gameplayer\common" /I "../../../../source/blender/blenkernel" /I "../../../../source/blender/makesdna" /I "../../../../source/blender/blenlib" /I "../../../../source/blender/blenloader" /I "../../../../source/blender/readblenfile" /I "../../../../source/blender/render/extern/include" /I "../../../../source/blender/imbuf" /I "..\..\..\..\source\gameengine\converter" /I "..\..\..\..\source\gameengine\gameplayer\common\windows" /I "..\..\..\..\lib\windows\string\include" /I "..\..\..\..\lib\windows\ghost\include" /I "../../../../lib/windows/iksolver/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 libguardedalloc.a libstring.a libghost.a odelib.lib fmodvc.lib libbmfont.a ws2_32.lib kernel32.lib user32.lib gdi32.lib vfw32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib libjpeg.lib opengl32.lib glu32.lib openal_static.lib dxguid.lib libblenkey.a libeay32.lib libpng.a libz.a libmoto.a /nologo /subsystem:console /machine:I386 /nodefaultlib:"libcd.lib" /nodefaultlib:"libc.lib" /nodefaultlib:"msvcrt.lib" /nodefaultlib:"msvcrtd.lib" /nodefaultlib:"msvcprt.lib" /out:"..\..\..\..\..\obj\windows\blenderplayer.exe" /libpath:"..\..\..\..\lib\windows\bmfont\lib" /libpath:"..\..\..\..\lib\windows\guardedalloc\lib" /libpath:"..\..\..\..\lib\windows\string\lib" /libpath:"..\..\..\..\lib\windows\ghost\lib" /libpath:"..\..\..\..\lib\windows\jpeg/lib" /libpath:"..\..\..\..\lib\windows\moto\lib\\" /libpath:"..\..\..\..\lib\windows\png\lib" /libpath:"..\..\..\..\lib\windows\zlib\lib" /libpath:"..\..\..\..\lib\windows\ode-0.03\lib" /libpath:"../../../../lib/windows/fmod/lib" /libpath:"..\..\..\..\lib\windows\python\lib" /libpath:"../../../../lib/windows/openal/lib" /libpath:"..\..\..\..\lib\windows\openssl\lib" /libpath:"..\..\..\..\lib\windows\blenkey\lib\\"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "GP_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\debug"
+# PROP Intermediate_Dir "..\..\..\..\..\obj\windows\gameengine\gameplayer\ghost\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 "../../../../lib/windows/moto/include" /I "..\..\..\..\source\gameengine\Physics\Ode" /I "..\..\..\..\source\gameengine\Physics" /I "..\..\..\..\lib\windows\python\include\python2.0" /I "..\..\..\..\lib\windows\bmfont\include" /I "..\..\..\..\source\kernel\gen_messaging" /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\expressions" /I "..\..\..\..\source\gameengine\ketsji" /I "..\..\..\..\source\gameengine\ketsji\kxnetwork" /I "..\..\..\..\source\gameengine\rasterizer" /I "..\..\..\..\source\gameengine\rasterizer\ras_openglrasterizer" /I "..\..\..\..\source\gameengine\scenegraph" /I "..\..\..\..\source\gameengine\gamelogic" /I "..\..\..\..\source\gameengine\soundsystem" /I "..\..\..\..\source\gameengine\soundsystem\snd_openal" /I "..\..\..\..\source\gameengine\network" /I "..\..\..\..\source\gameengine\network\loopbacknetwork" /I "..\..\..\..\source\sumo\include" /I "..\..\..\..\source\sumo\fuzzics\include" /I "..\..\..\..\lib\windows\openal\include" /I "..\..\..\..\source\gameengine\gameplayer\common" /I "../../../../source/blender/blenkernel" /I "../../../../source/blender/makesdna" /I "../../../../source/blender/blenlib" /I "../../../../source/blender/blenloader" /I "../../../../source/blender/readblenfile" /I "../../../../source/blender/render/extern/include" /I "../../../../source/blender/imbuf" /I "..\..\..\..\source\gameengine\converter" /I "..\..\..\..\source\gameengine\gameplayer\common\windows" /I "..\..\..\..\lib\windows\string\include" /I "..\..\..\..\lib\windows\ghost\include" /I "../../../../lib/windows/iksolver/include" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /U "_DEBUG" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+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 libguardedalloc.a libstring.a libghost.a odelib.lib fmodvc.lib libbmfont.a ws2_32.lib kernel32.lib user32.lib gdi32.lib vfw32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib libjpeg.lib opengl32.lib glu32.lib openal_static.lib dxguid.lib libblenkey.a libeay32.lib libpng.a libz.a libmoto.a /nologo /subsystem:console /debug /machine:I386 /nodefaultlib:"libcd.lib" /nodefaultlib:"libc.lib" /nodefaultlib:"libcmt.lib" /nodefaultlib:"msvcrt.lib" /nodefaultlib:"msvcrtd.lib" /nodefaultlib:"msvcprtd.lib" /out:"..\..\..\..\..\obj\windows\debug/blenderplayer.exe" /pdbtype:sept /libpath:"..\..\..\..\lib\windows\bmfont\lib\debug" /libpath:"..\..\..\..\lib\windows\guardedalloc\lib" /libpath:"..\..\..\..\lib\windows\string\lib\\" /libpath:"..\..\..\..\lib\windows\ghost\lib\debug" /libpath:"..\..\..\..\lib\windows\jpeg\lib" /libpath:"..\..\..\..\lib\windows\moto\lib\\" /libpath:"..\..\..\..\lib\windows\zlib\lib\\" /libpath:"..\..\..\..\lib\windows\png\lib\\" /libpath:"..\..\..\..\lib\windows\ode-0.03\lib" /libpath:"../../../../lib/windows/fmod/lib" /libpath:"..\..\..\..\lib\windows\python\lib" /libpath:"../../../../lib/windows/openal/lib" /libpath:"..\..\..\..\lib\windows\openssl\lib" /libpath:"..\..\..\..\lib\windows\blenkey\lib\\"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "GP_ghost - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "GP_ghost___Win32_Profile"
+# PROP BASE Intermediate_Dir "GP_ghost___Win32_Profile"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "GP_ghost___Win32_Profile"
+# PROP Intermediate_Dir "GP_ghost___Win32_Profile"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /O2 /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\expressions" /I "..\..\..\..\source\gameengine\ketsji" /I "..\..\..\..\source\gameengine\ketsji\kxnetwork" /I "..\..\..\..\source\gameengine\rasterizer" /I "..\..\..\..\source\gameengine\rasterizer\ras_openglrasterizer" /I "..\..\..\..\source\gameengine\scenegraph" /I "..\..\..\..\source\gameengine\gamelogic" /I "..\..\..\..\source\gameengine\soundsystem" /I "..\..\..\..\source\gameengine\soundsystem\snd_openal" /I "..\..\..\..\source\gameengine\network" /I "..\..\..\..\source\gameengine\network\loopbacknetwork" /I "..\..\..\..\source\gameengine\GamePlayer\Netscape\windows_sdk" /I "..\..\..\..\source\sumo\include" /I "..\..\..\..\lib\windows\moto\include" /I "..\..\..\..\source\sumo\fuzzics\include" /I "..\..\..\..\lib\windows\openal\include" /I "..\..\..\..\lib\windows\python\include\python1.5" /I "..\..\..\..\source\gameengine\gameplayer\common" /I "../../../../source/blender/blenkernel" /I "../../../../source/blender/makesdna" /I "../../../../source/blender/blenlib" /I "../../../../source/blender/blenloader" /I "../../../../source/blender/render/extern/include" /I "../../../../source/blender/imbuf" /I "..\..\..\..\source\gameengine\converter" /I "..\..\..\..\source\gameengine\gameplayer\common\windows" /I "..\..\..\..\lib\windows\string\include" /I "..\..\..\..\lib\windows\ghost\include" /I "../../../../lib/windows/iksolver/include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /O2 /I "..\..\..\..\source\gameengine\GamePlayer\Netscape\windows_sdk" /I "..\..\..\..\lib\windows\moto\include" /I "..\..\..\..\source\gameengine\Physics\Ode" /I "..\..\..\..\source\gameengine\Physics" /I "..\..\..\..\lib\windows\python\include\python2.0" /I "..\..\..\..\lib\windows\bmfont\include" /I "..\..\..\..\source\kernel\gen_messaging" /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\expressions" /I "..\..\..\..\source\gameengine\ketsji" /I "..\..\..\..\source\gameengine\ketsji\kxnetwork" /I "..\..\..\..\source\gameengine\rasterizer" /I "..\..\..\..\source\gameengine\rasterizer\ras_openglrasterizer" /I "..\..\..\..\source\gameengine\scenegraph" /I "..\..\..\..\source\gameengine\gamelogic" /I "..\..\..\..\source\gameengine\soundsystem" /I "..\..\..\..\source\gameengine\soundsystem\snd_openal" /I "..\..\..\..\source\gameengine\network" /I "..\..\..\..\source\gameengine\network\loopbacknetwork" /I "..\..\..\..\source\sumo\include" /I "..\..\..\..\source\sumo\fuzzics\include" /I "..\..\..\..\lib\windows\openal\include" /I "..\..\..\..\source\gameengine\gameplayer\common" /I "../../../../source/blender/blenkernel" /I "../../../../source/blender/makesdna" /I "../../../../source/blender/blenlib" /I "../../../../source/blender/blenloader" /I "../../../../source/blender/readblenfile" /I "../../../../source/blender/render/extern/include" /I "../../../../source/blender/imbuf" /I "..\..\..\..\source\gameengine\converter" /I "..\..\..\..\source\gameengine\gameplayer\common\windows" /I "..\..\..\..\lib\windows\string\include" /I "..\..\..\..\lib\windows\ghost\include" /I "../../../../lib/windows/iksolver/include" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /U "_DEBUG" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+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 libjpeg.lib opengl32.lib glu32.lib openal_static.lib dxguid.lib string.lib ghost.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\..\..\lib\windows\python\lib" /libpath:"..\..\..\..\lib\windows\jpeg/lib" /libpath:"../../../../lib/windows/openal/lib" /libpath:"..\..\..\..\lib\windows\string\lib\debug" /libpath:"..\..\..\..\lib\windows\ghost\lib\debug"
+# ADD LINK32 string.lib ghost.lib odelib.lib fmodvc.lib libbmfont.a ws2_32.lib kernel32.lib user32.lib gdi32.lib vfw32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib libjpeg.lib opengl32.lib glu32.lib openal_static.lib dxguid.lib libblenkey.a libeay32.lib libpng.a libz.a libmoto.a /nologo /subsystem:console /debug /machine:I386 /out:"GP_ghost___Win32_Profile/blenderplayer.exe" /pdbtype:sept /libpath:"..\..\..\..\lib\windows\string\lib\debug" /libpath:"..\..\..\..\lib\windows\ghost\lib\debug" /libpath:"..\..\..\..\lib\windows\jpeg/lib" /libpath:"..\..\lib\windows\moto\lib\\" /libpath:"..\..\..\..\lib\windows\zlib\lib\\" /libpath:"..\..\..\..\lib\windows\ode-0.03\lib" /libpath:"../../../../lib/windows/fmod/lib" /libpath:"..\..\..\..\lib\windows\python\lib" /libpath:"../../../../lib/windows/openal/lib" /libpath:"..\..\..\..\lib\windows\openssl\lib" /libpath:"..\..\..\..\lib\windows\blenkey\lib\\"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF
+
+# Begin Target
+
+# Name "GP_ghost - Win32 Release"
+# Name "GP_ghost - Win32 Debug"
+# Name "GP_ghost - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\..\source\blender\makesdna\intern\dna.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\ghost\GPG_Application.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\ghost\GPG_Canvas.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\ghost\GPG_ghost.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\ghost\GPG_KeyboardDevice.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\ghost\GPG_System.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\blender\blenkernel\bad_level_call_stubs\stubs.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\icons\winplayer.rc
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\ghost\GPG_Application.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\ghost\GPG_Canvas.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\ghost\GPG_KeyboardDevice.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\ghost\GPG_System.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"
+# Begin Source File
+
+SOURCE=..\..\..\..\source\icons\winplayer.ico
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\ghost\Makefile
+# End Source File
+# End Target
+# End Project
diff --git a/projectfiles/gameengine/gameplayer/glut/GP_glut.dsp b/projectfiles/gameengine/gameplayer/glut/GP_glut.dsp
new file mode 100644
index 00000000000..496a51f4b89
--- /dev/null
+++ b/projectfiles/gameengine/gameplayer/glut/GP_glut.dsp
@@ -0,0 +1,205 @@
+# Microsoft Developer Studio Project File - Name="GP_glut" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=GP_glut - Win32 Profile
+!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 "GP_glut.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 "GP_glut.mak" CFG="GP_glut - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "GP_glut - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "GP_glut - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE "GP_glut - Win32 Profile" (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)" == "GP_glut - 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 "..\..\..\..\..\obj\windows\gameengine\gameplayer\glut"
+# 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 /W3 /GX /O2 /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\network" /I "..\..\..\..\source\gameengine\network\loopbacknetwork" /I "..\..\..\..\source\gameengine\gameplayer\common" /I "..\..\..\..\source\gameengine\rasterizer" /I "..\..\..\..\source\gameengine\gamelogic" /I "..\..\..\..\source\sumo\include" /I "..\..\..\..\source\sumo\Fuzzics\include" /I "..\..\..\..\lib\windows\glut-3.7\include" /I "..\..\..\..\lib\windows\python\include\python2.0" /I "..\..\source\gameengine\SoundSystem" /I "../../../../lib/windows/moto/include" /D "NDEBUG" /D "WIN32" /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 user32.lib gdi32.lib advapi32.lib dxguid.lib ole32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\..\lib\windows\glut-3.7\lib" /libpath:"..\..\..\..\lib\windows\python\lib" /libpath:"..\..\..\..\lib\windows\openal\lib\lib_release"
+
+!ELSEIF "$(CFG)" == "GP_glut - 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 "..\..\..\..\..\obj\windows\gameengine\gameplayer\glut\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 "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\network" /I "..\..\..\..\source\gameengine\network\loopbacknetwork" /I "..\..\..\..\source\gameengine\gameplayer\common" /I "..\..\..\..\source\gameengine\rasterizer" /I "..\..\..\..\source\gameengine\gamelogic" /I "..\..\..\..\source\sumo\include" /I "..\..\..\..\source\sumo\Fuzzics\include" /I "..\..\..\..\lib\windows\glut-3.7\include" /I "..\..\..\..\lib\windows\python\include\python1.5" /I "..\..\source\gameengine\SoundSystem" /I "../../../../lib/windows/moto/include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /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
+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 user32.lib gdi32.lib advapi32.lib dxguid.lib ole32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\..\..\lib\windows\glut-3.7\lib" /libpath:"..\..\..\..\lib\windows\python\lib" /libpath:"..\..\..\..\lib\windows\openal\lib\lib_release"
+
+!ELSEIF "$(CFG)" == "GP_glut - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "GP_glut___Win32_Profile"
+# PROP BASE Intermediate_Dir "GP_glut___Win32_Profile"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "GP_glut___Win32_Profile"
+# PROP Intermediate_Dir "GP_glut___Win32_Profile"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\network" /I "..\..\..\..\source\gameengine\network\loopbacknetwork" /I "..\..\..\..\source\gameengine\gameplayer\common" /I "..\..\..\..\source\gameengine\rasterizer" /I "..\..\..\..\source\gameengine\gamelogic" /I "..\..\..\..\source\sumo\include" /I "..\..\..\..\lib\windows\moto\include" /I "..\..\..\..\source\sumo\Fuzzics\include" /I "..\..\..\..\lib\windows\glut-3.7\include" /I "..\..\..\..\lib\windows\python\include\python1.5" /I "..\..\source\gameengine\SoundSystem" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /O2 /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\network" /I "..\..\..\..\source\gameengine\network\loopbacknetwork" /I "..\..\..\..\source\gameengine\gameplayer\common" /I "..\..\..\..\source\gameengine\rasterizer" /I "..\..\..\..\source\gameengine\gamelogic" /I "..\..\..\..\source\sumo\include" /I "..\..\..\..\lib\windows\moto\include" /I "..\..\..\..\source\sumo\Fuzzics\include" /I "..\..\..\..\lib\windows\glut-3.7\include" /I "..\..\..\..\lib\windows\python\include\python1.5" /I "..\..\source\gameengine\SoundSystem" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 glu32.lib user32.lib gdi32.lib advapi32.lib dxguid.lib ole32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\..\..\lib\windows\glut-3.7\lib" /libpath:"..\..\..\..\lib\windows\python\lib" /libpath:"..\..\..\..\lib\windows\openal\lib\lib_release"
+# ADD LINK32 glu32.lib user32.lib gdi32.lib advapi32.lib dxguid.lib ole32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\..\..\lib\windows\glut-3.7\lib" /libpath:"..\..\..\..\lib\windows\python\lib" /libpath:"..\..\..\..\lib\windows\openal\lib\lib_release"
+
+!ENDIF
+
+# Begin Target
+
+# Name "GP_glut - Win32 Release"
+# Name "GP_glut - Win32 Debug"
+# Name "GP_glut - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\Glut\GlutGamePlayer.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\Glut\GlutKeyboardDevice.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\Glut\GlutSystem.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\Glut\GlutCanvas.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\Glut\GlutInputDevice.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\Glut\GlutKeyboardDevice.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\Glut\GlutPolygonMaterial.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\Glut\GlutRenderTools.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\Glut\GlutSystem.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
+# Begin Source File
+
+SOURCE=..\..\..\..\lib\windows\openal\lib\alc\ALc.obj
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\lib\windows\openal\lib\alu\ALu.obj
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\lib\windows\openal\lib\alut\ALut.obj
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\lib\windows\openal\lib\OpenAL32\alBuffer.obj
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\lib\windows\openal\lib\OpenAL32\alEax.obj
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\lib\windows\openal\lib\OpenAL32\alError.obj
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\lib\windows\openal\lib\OpenAL32\alExtension.obj
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\lib\windows\openal\lib\OpenAL32\alListener.obj
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\lib\windows\openal\lib\OpenAL32\alSource.obj
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\lib\windows\openal\lib\OpenAL32\alState.obj
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\lib\windows\openal\lib\OpenAL32\OpenAL32.obj
+# End Source File
+# End Target
+# End Project
diff --git a/projectfiles/gameengine/gameplayer/loader/BlenderLoader/BlenderLoader.dsp b/projectfiles/gameengine/gameplayer/loader/BlenderLoader/BlenderLoader.dsp
new file mode 100644
index 00000000000..c9831a3bdcf
--- /dev/null
+++ b/projectfiles/gameengine/gameplayer/loader/BlenderLoader/BlenderLoader.dsp
@@ -0,0 +1,206 @@
+# Microsoft Developer Studio Project File - Name="BlenderLoader" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=BlenderLoader - Win32 Profile
+!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 "BlenderLoader.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 "BlenderLoader.mak" CFG="BlenderLoader - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "BlenderLoader - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "BlenderLoader - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE "BlenderLoader - Win32 Profile" (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)" == "BlenderLoader - 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\gameengine\gameplayer\BlenderLoader"
+# PROP Intermediate_Dir "..\..\..\..\..\..\obj\windows\gameengine\gameplayer\BlenderLoader"
+# 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 /W3 /GX /O2 /I "../../../../../lib/windows/python/include/python2.0" /I "../../../../../source/blender/encrypt" /I "../../../../../source/blender/blenkernel" /I "../../../../../source/blender/makesdna" /I "../../../../../source/blender/blenlib" /I "../../../../../source/blender/blenloader" /I "../../../../../source/blender/render/extern/include" /I "../../../../../source/gameengine/Rasterizer" /I "../../../../../lib\windows\sdl\SDL-1.1.7\include" /I "../../../../../source/gameengine/GameLogic" /I "..\..\..\..\..\source\sumo\include" /I "..\..\..\..\..\lib\windows\moto\include" /I "..\..\..\..\..\source\sumo\Fuzzics\include" /I "..\..\..\..\..\source\kernel\gen_system" /I "../../../../../source/blender/imbuf" /I "../../../../../source/gameengine/SoundSystem" /I "../../../../../source/gameengine/SoundSystem/SND_OpenAL" /I "../../../../../source/gameengine/Ketsji" /I "../../../../../source/gameengine/Expressions" /I "../../../../../source/gameengine/SceneGraph" /I "../../../../../source/gameengine/ketsji/kxnetwork" /I "../../../../../source/gameengine/network" /I "../../../../../source/gameengine/network/loopbacknetwork" /I "../../../../../source/gameengine/GamePlayer/common" /I "../../../../../lib/windows/iksolver/include" /I "../../../../../source/gameengine/SoundSystem/SND_Dummy" /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 libguardedalloc.a libmoto.a sdlmain.lib sdl.lib dxguid.lib ole32.lib libjpeg.lib glu32.lib opengl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"..\..\..\..\..\..\obj\windows\BlenderLoader.exe" /libpath:"../../../../../lib/windows/moto/lib" /libpath:"..\..\..\..\..\lib\windows\guardedalloc\lib" /libpath:"../../../../../lib/windows/python/lib" /libpath:"../../../../../lib/windows/jpeg/lib" /libpath:"../../../../../lib/windows/sdl/SDL-1.1.7\Lib"
+
+!ELSEIF "$(CFG)" == "BlenderLoader - 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\gameengine\gameplayer\BlenderLoader\debug"
+# PROP Intermediate_Dir "..\..\..\..\..\..\obj\windows\gameengine\gameplayer\BlenderLoader\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 "../../../../../lib/windows/python/include/python1.5" /I "../../../../../source/blender/encrypt" /I "../../../../../source/blender/blenkernel" /I "../../../../../source/blender/makesdna" /I "../../../../../source/blender/blenlib" /I "../../../../../source/blender/blenloader" /I "../../../../../source/blender/render/extern/include" /I "../../../../../source/gameengine/Rasterizer" /I "../../../../../lib\windows\sdl\SDL-1.1.7\include" /I "../../../../../source/gameengine/GameLogic" /I "..\..\..\..\..\source\sumo\include" /I "..\..\..\..\..\lib\windows\moto\include" /I "..\..\..\..\..\source\sumo\Fuzzics\include" /I "..\..\..\..\..\source\kernel\gen_system" /I "../../../../../source/blender/imbuf" /I "../../../../../source/gameengine/SoundSystem" /I "../../../../../source/gameengine/SoundSystem/SND_OpenAL" /I "../../../../../source/gameengine/Ketsji" /I "../../../../../source/gameengine/Expressions" /I "../../../../../source/gameengine/SceneGraph" /I "../../../../../source/gameengine/ketsji/kxnetwork" /I "../../../../../source/gameengine/network" /I "../../../../../source/gameengine/network/loopbacknetwork" /I "../../../../../source/gameengine/GamePlayer/common" /I "../../../../../lib/windows/iksolver/include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /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
+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 sdldebug.lib libguardedalloc.a libmoto.a sdlmain.lib sdl.lib dxguid.lib ole32.lib libjpeg.lib glu32.lib opengl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"..\..\..\..\..\..\obj\windows\debug\BlenderLoader.exe" /pdbtype:sept /libpath:"..\..\..\..\..\lib\windows\guardedalloc\lib" /libpath:"../../../../../lib/windows/python/lib" /libpath:"../../../../../lib/windows/jpeg/lib" /libpath:"../../../../../lib/windows/sdl/SDL-1.1.7\Lib"
+
+!ELSEIF "$(CFG)" == "BlenderLoader - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "BlenderLoader___Win32_Profile"
+# PROP BASE Intermediate_Dir "BlenderLoader___Win32_Profile"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "BlenderLoader___Win32_Profile"
+# PROP Intermediate_Dir "BlenderLoader___Win32_Profile"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../../../lib/windows/python/include/python1.5" /I "../../../../../source/blender/blenkernel" /I "../../../../../source/blender/makesdna" /I "../../../../../source/blender/blenlib" /I "../../../../../source/blender/blenloader" /I "../../../../../source/blender/render/extern/include" /I "../../../../../source/gameengine/Rasterizer" /I "../../../../../lib\windows\sdl\SDL-1.1.7\include" /I "../../../../../source/gameengine/GameLogic" /I "..\..\..\..\..\source\sumo\include" /I "..\..\..\..\..\lib\windows\moto\include" /I "..\..\..\..\..\source\sumo\Fuzzics\include" /I "..\..\..\..\..\source\kernel\gen_system" /I "../../../../../source/blender/imbuf" /I "../../../../../source/gameengine/SoundSystem" /I "../../../../../source/gameengine/SoundSystem/SND_OpenAL" /I "../../../../../source/gameengine/Ketsji" /I "../../../../../source/gameengine/Expressions" /I "../../../../../source/gameengine/SceneGraph" /I "../../../../../source/gameengine/ketsji/kxnetwork" /I "../../../../../source/gameengine/network" /I "../../../../../source/gameengine/network/loopbacknetwork" /I "../../../../../source/gameengine/GamePlayer/common" /I "../../../../../lib/windows/iksolver/include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# SUBTRACT BASE CPP /Fr
+# ADD CPP /nologo /W3 /Gm /GX /Zi /O2 /I "../../../../../lib/windows/python/include/python1.5" /I "../../../../../source/blender/encrypt" /I "../../../../../source/blender/blenkernel" /I "../../../../../source/blender/makesdna" /I "../../../../../source/blender/blenlib" /I "../../../../../source/blender/blenloader" /I "../../../../../source/blender/render/extern/include" /I "../../../../../source/gameengine/Rasterizer" /I "../../../../../lib\windows\sdl\SDL-1.1.7\include" /I "../../../../../source/gameengine/GameLogic" /I "..\..\..\..\..\source\sumo\include" /I "..\..\..\..\..\lib\windows\moto\include" /I "..\..\..\..\..\source\sumo\Fuzzics\include" /I "..\..\..\..\..\source\kernel\gen_system" /I "../../../../../source/blender/imbuf" /I "../../../../../source/gameengine/SoundSystem" /I "../../../../../source/gameengine/SoundSystem/SND_OpenAL" /I "../../../../../source/gameengine/Ketsji" /I "../../../../../source/gameengine/Expressions" /I "../../../../../source/gameengine/SceneGraph" /I "../../../../../source/gameengine/ketsji/kxnetwork" /I "../../../../../source/gameengine/network" /I "../../../../../source/gameengine/network/loopbacknetwork" /I "../../../../../source/gameengine/GamePlayer/common" /I "../../../../../lib/windows/iksolver/include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 sdldebug.lib sdlmain.lib sdl.lib dxguid.lib ole32.lib libjpeg.lib glu32.lib opengl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"..\..\..\..\..\..\obj\windows\debug\BlenderLoader.exe" /pdbtype:sept /libpath:"../../../../../lib/windows/python/lib" /libpath:"../../../../../lib/windows/jpeg/lib" /libpath:"../../../../../lib/windows/sdl/SDL-1.1.7\Lib"
+# ADD LINK32 sdldebug.lib libguardedalloc.a libmoto.a sdlmain.lib sdl.lib dxguid.lib ole32.lib libjpeg.lib glu32.lib opengl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"..\..\..\..\..\..\obj\windows\profile\BlenderLoader.exe" /pdbtype:sept /libpath:"..\..\..\..\..\lib\windows\guardedalloc\lib" /libpath:"../../../../../lib/windows/python/lib" /libpath:"../../../../../lib/windows/jpeg/lib" /libpath:"../../../../../lib/windows/sdl/SDL-1.1.7\Lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "BlenderLoader - Win32 Release"
+# Name "BlenderLoader - Win32 Debug"
+# Name "BlenderLoader - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\blender\makesdna\intern\dna.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\gameengine\GamePlayer\Loaders\Blender\loader.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\gameengine\GamePlayer\Loaders\Blender\SDLKeyboardDevice.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\gameengine\GamePlayer\Loaders\Blender\SDLSystem.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\blender\blenkernel\bad_level_call_stubs\stubs.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\gameengine\GamePlayer\Loaders\Blender\SDLCanvas.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\gameengine\GamePlayer\Loaders\Blender\SDLInputDevice.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\gameengine\GamePlayer\Loaders\Blender\SDLKeyboardDevice.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\gameengine\GamePlayer\Loaders\Blender\SDLSystem.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
+# Begin Source File
+
+SOURCE=..\..\..\..\..\lib\windows\openal\lib\alc\ALc.obj
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\lib\windows\openal\lib\alu\ALu.obj
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\lib\windows\openal\lib\alut\ALut.obj
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\lib\windows\openal\lib\OpenAL32\alBuffer.obj
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\lib\windows\openal\lib\OpenAL32\alEax.obj
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\lib\windows\openal\lib\OpenAL32\alError.obj
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\lib\windows\openal\lib\OpenAL32\alExtension.obj
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\lib\windows\openal\lib\OpenAL32\alListener.obj
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\lib\windows\openal\lib\OpenAL32\alSource.obj
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\lib\windows\openal\lib\OpenAL32\alState.obj
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\lib\windows\openal\lib\OpenAL32\OpenAL32.obj
+# End Source File
+# End Target
+# End Project
diff --git a/projectfiles/gameengine/gameplayer/netscape/GP_netscape.dsp b/projectfiles/gameengine/gameplayer/netscape/GP_netscape.dsp
new file mode 100644
index 00000000000..ebed10b597d
--- /dev/null
+++ b/projectfiles/gameengine/gameplayer/netscape/GP_netscape.dsp
@@ -0,0 +1,173 @@
+# Microsoft Developer Studio Project File - Name="GP_netscape" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=GP_netscape - Win32 Profile
+!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 "GP_netscape.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 "GP_netscape.mak" CFG="GP_netscape - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "GP_netscape - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "GP_netscape - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "GP_netscape - Win32 Profile" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "GP_netscape - 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 "C:\Program Files\Netscape\Communicator\Program\Plugins"
+# PROP Intermediate_Dir ".\Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
+# ADD CPP /nologo /W3 /GX /O2 /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\expressions" /I "..\..\..\..\source\gameengine\ketsji" /I "..\..\..\..\source\gameengine\ketsji\kxnetwork" /I "..\..\..\..\source\gameengine\rasterizer" /I "..\..\..\..\source\gameengine\rasterizer\ras_openglrasterizer" /I "..\..\..\..\source\gameengine\scenegraph" /I "..\..\..\..\source\gameengine\gamelogic" /I "..\..\..\..\source\gameengine\soundsystem" /I "..\..\..\..\source\gameengine\soundsystem\snd_openal" /I "..\..\..\..\source\gameengine\network" /I "..\..\..\..\source\gameengine\network\loopbacknetwork" /I "..\..\..\..\source\sumo\include" /I "..\..\..\..\source\sumo\fuzzics\include" /I "..\..\..\..\lib\windows\openal\include" /I "..\..\..\..\lib\windows\python\include\python2.0" /I "..\..\..\..\source\gameengine\gameplayer\common" /I "../../../../source/blender/blenkernel" /I "../../../../source/blender/makesdna" /I "../../../../source/blender/blenlib" /I "../../../../source/blender/blenloader" /I "../../../../source/blender/render/extern/include" /I "../../../../source/blender/imbuf" /I "..\..\..\..\source\gameengine\converter" /I "..\..\..\..\source\gameengine\gameplayer\common\windows" /I "..\..\..\..\source\gameengine\GamePlayer\Netscape\windows_sdk" /I "..\..\..\..\lib\windows\iksolver\include" /I "../../../../lib/windows/moto/include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# 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 /nologo /subsystem:windows /dll /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 libjpeg.lib opengl32.lib glu32.lib libblenkey.a libz.a /nologo /subsystem:windows /dll /machine:I386 /out:"C:\Program Files\Netscape\Communicator\Program\Plugins\NPBlender.dll" /libpath:"../../../../lib/windows/python/lib" /libpath:"../../../../lib/windows/jpeg/lib" /libpath:"../../../../lib/windows/zlib/lib/" /libpath:"..\..\..\..\lib\windows\blenkey\lib" /libpath:"..\..\..\..\lib\windows\openssl\lib" /libpath:"..\..\..\..\lib\windows\iksolver\lib\\"
+
+!ELSEIF "$(CFG)" == "GP_netscape - 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 "C:\Program Files\Netscape\Communicator\Program\Plugins"
+# PROP Intermediate_Dir ".\Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\expressions" /I "..\..\..\..\source\gameengine\ketsji" /I "..\..\..\..\source\gameengine\ketsji\kxnetwork" /I "..\..\..\..\source\gameengine\rasterizer" /I "..\..\..\..\source\gameengine\rasterizer\ras_openglrasterizer" /I "..\..\..\..\source\gameengine\scenegraph" /I "..\..\..\..\source\gameengine\gamelogic" /I "..\..\..\..\source\gameengine\soundsystem" /I "..\..\..\..\source\gameengine\soundsystem\snd_openal" /I "..\..\..\..\source\gameengine\network" /I "..\..\..\..\source\gameengine\network\loopbacknetwork" /I "..\..\..\..\source\gameengine\GamePlayer\Netscape\windows_sdk" /I "..\..\..\..\source\sumo\include" /I "..\..\..\..\source\sumo\fuzzics\include" /I "..\..\..\..\lib\windows\openal\include" /I "..\..\..\..\lib\windows\python\include\python1.5" /I "..\..\..\..\source\gameengine\gameplayer\common" /I "../../../../source/blender/blenkernel" /I "../../../../source/blender/makesdna" /I "../../../../source/blender/blenlib" /I "../../../../source/blender/blenloader" /I "../../../../source/blender/render/extern/include" /I "../../../../source/blender/imbuf" /I "..\..\..\..\source\gameengine\converter" /I "..\..\..\..\source\gameengine\gameplayer\common\windows" /I "..\..\..\..\lib\windows\iksolver\include" /I "../../../../lib/windows/moto/include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# 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 /nologo /subsystem:windows /dll /debug /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 libjpeg.lib opengl32.lib glu32.lib openal_static.lib dxguid.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 libjpeg.lib opengl32.lib glu32.lib openal_static.lib dxguid.lib libblenkey.a libz.a kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib libjpeg.lib opengl32.lib glu32.lib openal_static.lib dxguid.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 libjpeg.lib opengl32.lib glu32.lib openal_static.lib dxguid.lib python15.lib /nologo /subsystem:windows /dll /debug /machine:I386 /out:"C:\Program Files\Netscape\Communicator\Program\Plugins\NPBlender.dll" /libpath:"../../../../lib/windows/python/lib" /libpath:"../../../../lib/windows/jpeg/lib" /libpath:"../../../../lib/windows/openal/lib" /libpath:"../../../../lib/windows/zlib/lib/" /libpath:"..\..\..\..\lib\windows\blenkey\lib" /libpath:"..\..\..\..\lib\windows\openssl\lib" /libpath:"..\..\..\..\lib\windows\iksolver\lib\\"
+
+!ELSEIF "$(CFG)" == "GP_netscape - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "GP_netscape___Win32_Profile"
+# PROP BASE Intermediate_Dir "GP_netscape___Win32_Profile"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "GP_netscape___Win32_Profile"
+# PROP Intermediate_Dir "GP_netscape___Win32_Profile"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\expressions" /I "..\..\..\..\source\gameengine\ketsji" /I "..\..\..\..\source\gameengine\ketsji\kxnetwork" /I "..\..\..\..\source\gameengine\rasterizer" /I "..\..\..\..\source\gameengine\rasterizer\ras_openglrasterizer" /I "..\..\..\..\source\gameengine\scenegraph" /I "..\..\..\..\source\gameengine\gamelogic" /I "..\..\..\..\source\gameengine\soundsystem" /I "..\..\..\..\source\gameengine\soundsystem\snd_openal" /I "..\..\..\..\source\gameengine\network" /I "..\..\..\..\source\gameengine\network\loopbacknetwork" /I "..\..\..\..\source\gameengine\GamePlayer\Netscape\windows_sdk" /I "..\..\..\..\source\sumo\include" /I "..\..\..\..\lib\windows\moto\include" /I "..\..\..\..\source\sumo\fuzzics\include" /I "..\..\..\..\lib\windows\openal\include" /I "..\..\..\..\lib\windows\python\include\python1.5" /I "..\..\..\..\source\gameengine\gameplayer\common" /I "../../../../source/blender/blenkernel" /I "../../../../source/blender/makesdna" /I "../../../../source/blender/blenlib" /I "../../../../source/blender/blenloader" /I "../../../../source/blender/render/extern/include" /I "../../../../source/blender/imbuf" /I "..\..\..\..\source\gameengine\converter" /I "..\..\..\..\source\gameengine\gameplayer\common\windows" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /O2 /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\expressions" /I "..\..\..\..\source\gameengine\ketsji" /I "..\..\..\..\source\gameengine\ketsji\kxnetwork" /I "..\..\..\..\source\gameengine\rasterizer" /I "..\..\..\..\source\gameengine\rasterizer\ras_openglrasterizer" /I "..\..\..\..\source\gameengine\scenegraph" /I "..\..\..\..\source\gameengine\gamelogic" /I "..\..\..\..\source\gameengine\soundsystem" /I "..\..\..\..\source\gameengine\soundsystem\snd_openal" /I "..\..\..\..\source\gameengine\network" /I "..\..\..\..\source\gameengine\network\loopbacknetwork" /I "..\..\..\..\source\gameengine\GamePlayer\Netscape\windows_sdk" /I "..\..\..\..\source\sumo\include" /I "..\..\..\..\lib\windows\moto\include" /I "..\..\..\..\source\sumo\fuzzics\include" /I "..\..\..\..\lib\windows\openal\include" /I "..\..\..\..\lib\windows\python\include\python1.5" /I "..\..\..\..\source\gameengine\gameplayer\common" /I "../../../../source/blender/blenkernel" /I "../../../../source/blender/makesdna" /I "../../../../source/blender/blenlib" /I "../../../../source/blender/blenloader" /I "../../../../source/blender/render/extern/include" /I "../../../../source/blender/imbuf" /I "..\..\..\..\source\gameengine\converter" /I "..\..\..\..\source\gameengine\gameplayer\common\windows" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# SUBTRACT CPP /Fr
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# 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 libjpeg.lib opengl32.lib glu32.lib openal_static.lib dxguid.lib /nologo /subsystem:windows /dll /debug /machine:I386 /out:"C:\Program Files\Netscape\Communicator\Program\Plugins\NPBlender.dll" /libpath:"../../../../lib/windows/python/lib" /libpath:"../../../../lib/windows/jpeg/lib" /libpath:"../../../../lib/windows/openal/lib"
+# 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 libjpeg.lib opengl32.lib glu32.lib openal_static.lib dxguid.lib /nologo /subsystem:windows /dll /debug /machine:I386 /out:"C:\Program Files\Netscape\Communicator\Program\Plugins\NPBlender.dll" /libpath:"../../../../lib/windows/python/lib" /libpath:"../../../../lib/windows/jpeg/lib" /libpath:"../../../../lib/windows/openal/lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "GP_netscape - Win32 Release"
+# Name "GP_netscape - Win32 Debug"
+# Name "GP_netscape - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;for;f90"
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\Netscape\windows\BlenderPlayer.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\blender\makesdna\intern\dna.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\Netscape\windows\netscape_plugin_Plugin.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\Netscape\npblender.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\Netscape\windows\npblender.def
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\Netscape\windows\npblender.rc
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\Netscape\windows\npwin.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\blender\blenkernel\bad_level_call_stubs\stubs.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
+# End Group
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\NSPlugin\autodownload.html
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\Netscape\Testing\NetscapeExample.html
+# End Source File
+# End Target
+# End Project
diff --git a/projectfiles/gameengine/gameplayer/netscape2/GP_netscape.dsp b/projectfiles/gameengine/gameplayer/netscape2/GP_netscape.dsp
new file mode 100644
index 00000000000..2b9a3a1a373
--- /dev/null
+++ b/projectfiles/gameengine/gameplayer/netscape2/GP_netscape.dsp
@@ -0,0 +1,181 @@
+# Microsoft Developer Studio Project File - Name="GP_netscape2" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=GP_netscape2 - Win32 Profile
+!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 "GP_netscape.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 "GP_netscape.mak" CFG="GP_netscape2 - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "GP_netscape2 - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "GP_netscape2 - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "GP_netscape2 - Win32 Profile" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "GP_netscape2 - 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 "C:\Program Files\Netscape\Communicator\Program\Plugins"
+# PROP Intermediate_Dir ".\Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
+# ADD CPP /nologo /W3 /GX /O2 /I "..\..\..\..\source\kernel\gen_messaging" /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\expressions" /I "..\..\..\..\source\gameengine\ketsji" /I "..\..\..\..\source\gameengine\ketsji\kxnetwork" /I "..\..\..\..\source\gameengine\rasterizer" /I "..\..\..\..\source\gameengine\rasterizer\ras_openglrasterizer" /I "..\..\..\..\source\gameengine\scenegraph" /I "..\..\..\..\source\gameengine\gamelogic" /I "..\..\..\..\source\gameengine\soundsystem" /I "..\..\..\..\source\gameengine\soundsystem\snd_openal" /I "..\..\..\..\source\gameengine\network" /I "..\..\..\..\source\gameengine\network\loopbacknetwork" /I "..\..\..\..\source\gameengine\GamePlayer\Netscape2\windows_sdk" /I "..\..\..\..\source\sumo\include" /I "..\..\..\..\lib\windows\moto\include" /I "..\..\..\..\source\sumo\fuzzics\include" /I "..\..\..\..\lib\windows\openal\include" /I "..\..\..\..\lib\windows\python\include\python1.5" /I "..\..\..\..\source\gameengine\gameplayer\common" /I "../../../../source/blender/blenkernel" /I "../../../../source/blender/makesdna" /I "../../../../source/blender/blenlib" /I "../../../../source/blender/blenloader" /I "../../../../source/blender/render/extern/include" /I "../../../../source/blender/imbuf" /I "..\..\..\..\source\gameengine\converter" /I "..\..\..\..\source\gameengine\gameplayer\common\windows" /I "..\..\..\..\source\gameengine\gameplayer\Netscape2\windows" /I "..\..\..\..\lib\windows\iksolver\include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# 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 /nologo /subsystem:windows /dll /machine:I386
+# ADD LINK32 libblenkey.a libeay32.lib libz.a ws2_32.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 libjpeg.lib opengl32.lib glu32.lib openal_static.lib dxguid.lib /nologo /subsystem:windows /dll /machine:I386 /out:"C:\Program Files\Netscape\Communicator\Program\Plugins\npBlender3DPlugin.dll" /libpath:"../../../../lib/windows/python/lib" /libpath:"../../../../lib/windows/jpeg/lib" /libpath:"../../../../lib/windows/zlib/lib/" /libpath:"..\..\..\..\lib\windows\blenkey\lib" /libpath:"..\..\..\..\lib\windows\openssl\lib" /libpath:"..\..\..\..\lib\windows\iksolver\lib\\" /libpath:"../../../../lib/windows/openal/lib"
+
+!ELSEIF "$(CFG)" == "GP_netscape2 - 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 "C:\Program Files\Netscape\Communicator\Program\Plugins"
+# PROP Intermediate_Dir ".\Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\..\..\..\source\kernel\gen_messaging" /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\expressions" /I "..\..\..\..\source\gameengine\ketsji" /I "..\..\..\..\source\gameengine\ketsji\kxnetwork" /I "..\..\..\..\source\gameengine\rasterizer" /I "..\..\..\..\source\gameengine\rasterizer\ras_openglrasterizer" /I "..\..\..\..\source\gameengine\scenegraph" /I "..\..\..\..\source\gameengine\gamelogic" /I "..\..\..\..\source\gameengine\soundsystem" /I "..\..\..\..\source\gameengine\soundsystem\snd_openal" /I "..\..\..\..\source\gameengine\network" /I "..\..\..\..\source\gameengine\network\loopbacknetwork" /I "..\..\..\..\source\gameengine\GamePlayer\Netscape2\windows_sdk" /I "..\..\..\..\source\sumo\include" /I "..\..\..\..\lib\windows\moto\include" /I "..\..\..\..\source\sumo\fuzzics\include" /I "..\..\..\..\lib\windows\openal\include" /I "..\..\..\..\lib\windows\python\include\python1.5" /I "..\..\..\..\source\gameengine\gameplayer\common" /I "../../../../source/blender/blenkernel" /I "../../../../source/blender/makesdna" /I "../../../../source/blender/blenlib" /I "../../../../source/blender/blenloader" /I "../../../../source/blender/render/extern/include" /I "../../../../source/blender/imbuf" /I "..\..\..\..\source\gameengine\converter" /I "..\..\..\..\source\gameengine\gameplayer\common\windows" /I "..\..\..\..\source\gameengine\gameplayer\Netscape2\windows" /I "..\..\..\..\lib\windows\iksolver\include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /FR /YX /FD /c
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# 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 /nologo /subsystem:windows /dll /debug /machine:I386
+# ADD LINK32 libblenkey.a libeay32.lib libz.a ws2_32.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 libjpeg.lib opengl32.lib glu32.lib openal_static.lib dxguid.lib /nologo /subsystem:windows /dll /debug /machine:I386 /out:"C:\Program Files\Netscape\Communicator\Program\Plugins\npBlender3DPlugin.dll" /libpath:"../../../../lib/windows/python/lib" /libpath:"../../../../lib/windows/jpeg/lib" /libpath:"../../../../lib/windows/openal/lib" /libpath:"../../../../lib/windows/zlib/lib/" /libpath:"..\..\..\..\lib\windows\blenkey\lib" /libpath:"..\..\lib\windows\openssl\lib" /libpath:"..\..\lib\windows\iksolver\lib\\"
+
+!ELSEIF "$(CFG)" == "GP_netscape2 - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "GP_netscape2___Win32_Profile"
+# PROP BASE Intermediate_Dir "GP_netscape2___Win32_Profile"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "GP_netscape2___Win32_Profile"
+# PROP Intermediate_Dir "GP_netscape2___Win32_Profile"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\expressions" /I "..\..\..\..\source\gameengine\ketsji" /I "..\..\..\..\source\gameengine\ketsji\kxnetwork" /I "..\..\..\..\source\gameengine\rasterizer" /I "..\..\..\..\source\gameengine\rasterizer\ras_openglrasterizer" /I "..\..\..\..\source\gameengine\scenegraph" /I "..\..\..\..\source\gameengine\gamelogic" /I "..\..\..\..\source\gameengine\soundsystem" /I "..\..\..\..\source\gameengine\soundsystem\snd_openal" /I "..\..\..\..\source\gameengine\network" /I "..\..\..\..\source\gameengine\network\loopbacknetwork" /I "..\..\..\..\source\gameengine\GamePlayer\Netscape\windows_sdk" /I "..\..\..\..\source\sumo\include" /I "..\..\..\..\lib\windows\moto\include" /I "..\..\..\..\source\sumo\fuzzics\include" /I "..\..\..\..\lib\windows\openal\include" /I "..\..\..\..\lib\windows\python\include\python1.5" /I "..\..\..\..\source\gameengine\gameplayer\common" /I "../../../../source/blender/blenkernel" /I "../../../../source/blender/makesdna" /I "../../../../source/blender/blenlib" /I "../../../../source/blender/blenloader" /I "../../../../source/blender/render/extern/include" /I "../../../../source/blender/imbuf" /I "..\..\..\..\source\gameengine\converter" /I "..\..\..\..\source\gameengine\gameplayer\common\windows" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /O2 /I "..\..\..\..\source\kernel\gen_messaging" /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\expressions" /I "..\..\..\..\source\gameengine\ketsji" /I "..\..\..\..\source\gameengine\ketsji\kxnetwork" /I "..\..\..\..\source\gameengine\rasterizer" /I "..\..\..\..\source\gameengine\rasterizer\ras_openglrasterizer" /I "..\..\..\..\source\gameengine\scenegraph" /I "..\..\..\..\source\gameengine\gamelogic" /I "..\..\..\..\source\gameengine\soundsystem" /I "..\..\..\..\source\gameengine\soundsystem\snd_openal" /I "..\..\..\..\source\gameengine\network" /I "..\..\..\..\source\gameengine\network\loopbacknetwork" /I "..\..\..\..\source\gameengine\GamePlayer\Netscape2\windows_sdk" /I "..\..\..\..\source\sumo\include" /I "..\..\..\..\lib\windows\moto\include" /I "..\..\..\..\source\sumo\fuzzics\include" /I "..\..\..\..\lib\windows\openal\include" /I "..\..\..\..\lib\windows\python\include\python1.5" /I "..\..\..\..\source\gameengine\gameplayer\common" /I "../../../../source/blender/blenkernel" /I "../../../../source/blender/makesdna" /I "../../../../source/blender/blenlib" /I "../../../../source/blender/blenloader" /I "../../../../source/blender/render/extern/include" /I "../../../../source/blender/imbuf" /I "..\..\..\..\source\gameengine\converter" /I "..\..\..\..\source\gameengine\gameplayer\common\windows" /I "..\..\..\..\source\gameengine\gameplayer\Netscape2\windows" /I "..\..\..\..\lib\windows\iksolver\include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /YX /FD /c
+# SUBTRACT CPP /Fr
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# 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 libjpeg.lib opengl32.lib glu32.lib openal_static.lib dxguid.lib /nologo /subsystem:windows /dll /debug /machine:I386 /out:"C:\Program Files\Netscape\Communicator\Program\Plugins\NPBlender.dll" /libpath:"../../../../lib/windows/python/lib" /libpath:"../../../../lib/windows/jpeg/lib" /libpath:"../../../../lib/windows/openal/lib"
+# ADD LINK32 libblenkey.a libeay32.lib libz.a ws2_32.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 libjpeg.lib opengl32.lib glu32.lib openal_static.lib dxguid.lib /nologo /subsystem:windows /dll /debug /machine:I386 /out:"C:\Program Files\Netscape\Communicator\Program\Plugins\npBlender3DPlugin.dll" /libpath:"../../../../lib/windows/python/lib" /libpath:"../../../../lib/windows/jpeg/lib" /libpath:"../../../../lib/windows/openal/lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "GP_netscape2 - Win32 Release"
+# Name "GP_netscape2 - Win32 Debug"
+# Name "GP_netscape2 - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;for;f90"
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\Netscape2\windows\Blender3DPlugin.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\blender\makesdna\intern\dna.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\Netscape2\windows\netscape_plugin_Plugin.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\Netscape2\windows\npblender.def
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\Netscape2\windows\npblender.rc
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\Netscape2\npshell.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\Netscape2\windows\npwin.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\Netscape2\windows\plgwnd.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\blender\blenkernel\bad_level_call_stubs\stubs.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\Netscape\plgwnd.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
+# End Group
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\NSPlugin\autodownload.html
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\Netscape\Testing\NetscapeExample.html
+# End Source File
+# End Target
+# End Project
diff --git a/projectfiles/gameengine/gameplayer/ps2/GP_ps2.dsp b/projectfiles/gameengine/gameplayer/ps2/GP_ps2.dsp
new file mode 100644
index 00000000000..84aa94ef1a5
--- /dev/null
+++ b/projectfiles/gameengine/gameplayer/ps2/GP_ps2.dsp
@@ -0,0 +1,182 @@
+# Microsoft Developer Studio Project File - Name="GP_ps2" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=GP_ps2 - Win32 Profile
+!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 "GP_ps2.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 "GP_ps2.mak" CFG="GP_ps2 - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "GP_ps2 - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "GP_ps2 - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE "GP_ps2 - Win32 Profile" (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)" == "GP_ps2 - 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 "..\..\..\..\obj\windows\gameengine\gameplayer\ps2"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /GX /O2 /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\rasterizer" /I "..\..\..\..\source\gameengine\gamelogic" /I "..\..\..\..\source\gameengine\expressions" /I "..\..\..\..\source\sumo\include" /D "NDEBUG" /D "WIN32" /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 /nologo /subsystem:console /machine:I386
+
+!ELSEIF "$(CFG)" == "GP_ps2 - 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 "..\..\..\..\obj\windows\gameengine\gameplayer\ps2\debug"
+# 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 "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\rasterizer" /I "..\..\..\..\source\gameengine\gamelogic" /I "..\..\..\..\source\gameengine\expressions" /I "..\..\..\..\source\sumo\include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /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
+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 /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ELSEIF "$(CFG)" == "GP_ps2 - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "GP_ps2___Win32_Profile"
+# PROP BASE Intermediate_Dir "GP_ps2___Win32_Profile"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "GP_ps2___Win32_Profile"
+# PROP Intermediate_Dir "GP_ps2___Win32_Profile"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\rasterizer" /I "..\..\..\..\source\gameengine\gamelogic" /I "..\..\..\..\source\gameengine\expressions" /I "..\..\..\..\source\sumo\include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /O2 /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\rasterizer" /I "..\..\..\..\source\gameengine\gamelogic" /I "..\..\..\..\source\gameengine\expressions" /I "..\..\..\..\source\sumo\include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+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 /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "GP_ps2 - Win32 Release"
+# Name "GP_ps2 - Win32 Debug"
+# Name "GP_ps2 - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\PS2\DebugActuator.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\PS2\GPC_Init.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\PS2\PS2DualShockDevice.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\PS2\PS2GamePlayer.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\PS2\PS2System.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\PS2\DebugActuator.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\PS2\ExampleEngine.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\PS2\GPC_Init.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\PS2\PS2Canvas.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\PS2\PS2DualShockDevice.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\PS2\PS2InputDevice.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\PS2\PS2Rasterizer.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\PS2\PS2RenderTools.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\PS2\PS2System.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\PS2\SamplePolygonMaterial.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/projectfiles/gameengine/gameplayer/qt/gp.dsp b/projectfiles/gameengine/gameplayer/qt/gp.dsp
new file mode 100644
index 00000000000..cb425649e52
--- /dev/null
+++ b/projectfiles/gameengine/gameplayer/qt/gp.dsp
@@ -0,0 +1,164 @@
+# Microsoft Developer Studio Project File - Name="gp" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=gp - 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 "gp.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 "gp.mak" CFG="gp - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "gp - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "gp - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "gp - 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\gameengine\gameplayer\qt\gp"
+# PROP Intermediate_Dir "..\..\..\..\..\obj\windows\gameengine\gameplayer\qt\gp"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "h:\qtwin\include" /I "..\..\..\..\source\gameengine\Expressions" /I "..\..\..\..\source\gameengine\GameLogic" /I "..\..\..\..\source\gameengine\Ketsji" /I "..\..\..\..\source\gameengine\Ketsji\KXNetwork" /I "..\..\..\..\source\gameengine\Network" /I "..\..\..\..\source\gameengine\Network\LoopBackNetwork" /I "..\..\..\..\source\gameengine\Rasterizer" /I "..\..\..\..\source\gameengine\Rasterizer\RAS_OpenGLRasterizer" /I "..\..\..\..\source\gameengine\SceneGraph" /I "..\..\..\..\source\sumo\Fuzzics\include" /I "..\..\..\..\source\sumo\include" /I "..\..\..\..\lib\windows\moto\include" /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\lib\windows\python\include\python2.0" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# 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 /nologo /subsystem:windows /machine:I386
+# ADD LINK32 opengl32.lib glu32.lib kernel32.lib user32.lib gdi32.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib imm32.lib winmm.lib wsock32.lib h:\qtwin\lib\qt.lib h:\qtwin\lib\qnp.lib python20.lib /nologo /subsystem:windows /machine:I386 /out:"..\..\..\..\..\obj\windows\gp.exe" /libpath:"..\..\..\..\lib\windows\python\lib\\"
+
+!ELSEIF "$(CFG)" == "gp - 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\gameengine\gameplayer\qt\gp\debug"
+# PROP Intermediate_Dir "..\..\..\..\..\obj\windows\gameengine\gameplayer\qt\gp\debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /GX /Od /I "h:\qtwin\include" /I "..\..\..\..\source\gameengine\Expressions" /I "..\..\..\..\source\gameengine\GameLogic" /I "..\..\..\..\source\gameengine\Ketsji" /I "..\..\..\..\source\gameengine\Ketsji\KXNetwork" /I "..\..\..\..\source\gameengine\Network" /I "..\..\..\..\source\gameengine\Network\LoopBackNetwork" /I "..\..\..\..\source\gameengine\Rasterizer" /I "..\..\..\..\source\gameengine\Rasterizer\RAS_OpenGLRasterizer" /I "..\..\..\..\source\gameengine\SceneGraph" /I "..\..\..\..\source\sumo\Fuzzics\include" /I "..\..\..\..\source\sumo\include" /I "..\..\..\..\lib\windows\moto\include" /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\lib\windows\python\include\python1.5" /D "_DEBUG" /D "WIN32"
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x413 /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 /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 opengl32.lib glu32.lib kernel32.lib user32.lib gdi32.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib imm32.lib winmm.lib wsock32.lib h:\qtwin\lib\qt.lib python15_d.lib /nologo /subsystem:windows /debug /machine:I386 /out:"..\..\..\..\..\obj\windows\debug\gp.exe" /libpath:"..\..\..\..\lib\windows\python\lib\\"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF
+
+# Begin Target
+
+# Name "gp - Win32 Release"
+# Name "gp - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\Qt\GP.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\Qt\GP_Init.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\Qt\QtExampleEngine.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\Qt\QtKeyboardDevice.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\Qt\QtOpenGLWidget.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\Qt\QtSystem.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\Qt\DebugActuator.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\Qt\GP_Init.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\Qt\QtExampleEngine.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\Qt\QtInputDevice.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\Qt\QtKeyboardDevice.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\Qt\QtOpenGLWidget.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\Qt\QtRenderTools.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\Qt\QtSystem.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\Qt\SamplePolygonMaterial.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/projectfiles/gameengine/gameplayer/qt/gpplugin.dsp b/projectfiles/gameengine/gameplayer/qt/gpplugin.dsp
new file mode 100644
index 00000000000..9e8305a9353
--- /dev/null
+++ b/projectfiles/gameengine/gameplayer/qt/gpplugin.dsp
@@ -0,0 +1,824 @@
+# Microsoft Developer Studio Project File - Name="gpplugin" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=gpplugin - 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 "gpplugin.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 "gpplugin.mak" CFG="gpplugin - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "gpplugin - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "gpplugin - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "gpplugin - 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\gameengine\gameplayer\qt\gpplugin"
+# PROP Intermediate_Dir "..\..\..\..\..\obj\windows\gameengine\gameplayer\qt\gpplugin"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "GPPLUGIN_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "h:\qtwin\include" /I "..\..\..\..\source\gameengine\Expressions" /I "..\..\..\..\source\gameengine\GameLogic" /I "..\..\..\..\source\gameengine\Ketsji" /I "..\..\..\..\source\gameengine\Ketsji\KXNetwork" /I "..\..\..\..\source\gameengine\Network" /I "..\..\..\..\source\gameengine\Network\LoopBackNetwork" /I "..\..\..\..\source\gameengine\Rasterizer" /I "..\..\..\..\source\gameengine\Rasterizer\RAS_OpenGLRasterizer" /I "..\..\..\..\source\gameengine\SceneGraph" /I "..\..\..\..\source\sumo\Fuzzics\include" /I "..\..\..\..\source\sumo\include" /I "..\..\..\..\lib\windows\moto\include" /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\lib\windows\python\include\python2.0" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "GPPLUGIN_EXPORTS" /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# 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 /nologo /dll /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib imm32.lib winmm.lib wsock32.lib h:\qtwin\lib\qnp.lib h:\qtwin\lib\qt.lib opengl32.lib glu32.lib python20.lib /nologo /dll /machine:I386 /out:"..\..\..\..\..\obj\windows\npWebGP.dll" /libpath:"..\..\..\..\lib\windows\python\lib\\"
+
+!ELSEIF "$(CFG)" == "gpplugin - 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\gameengine\gameplayer\qt\gpplugin\debug"
+# PROP Intermediate_Dir "..\..\..\..\..\obj\windows\gameengine\gameplayer\qt\gpplugin\debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "GPPLUGIN_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /GX /Zi /Od /I "h:\qtwin\include" /I "..\..\..\..\source\gameengine\Expressions" /I "..\..\..\..\source\gameengine\GameLogic" /I "..\..\..\..\source\gameengine\Ketsji" /I "..\..\..\..\source\gameengine\Ketsji\KXNetwork" /I "..\..\..\..\source\gameengine\Network" /I "..\..\..\..\source\gameengine\Network\LoopBackNetwork" /I "..\..\..\..\source\gameengine\Rasterizer" /I "..\..\..\..\source\gameengine\Rasterizer\RAS_OpenGLRasterizer" /I "..\..\..\..\source\gameengine\SceneGraph" /I "..\..\..\..\source\sumo\Fuzzics\include" /I "..\..\..\..\source\sumo\include" /I "..\..\..\..\lib\windows\moto\include" /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\lib\windows\python\include\python1.5" /D "WIN32" /D "PLUGIN" /D "_DEBUG"
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x413 /d "_DEBUG"
+# ADD RSC /l 0x409
+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 /nologo /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib imm32.lib winmm.lib wsock32.lib h:\qtwin\lib\qnp.lib h:\qtwin\lib\qt.lib opengl32.lib glu32.lib python15_d.lib /nologo /subsystem:windows /dll /debug /machine:I386 /def:"..\..\..\..\source\gameengine\GamePlayer\Qt\GP.def" /out:"..\..\..\..\..\obj\windows\debug\npWebGP.dll" /libpath:"..\..\..\..\lib\windows\python\lib"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF
+
+# Begin Target
+
+# Name "gpplugin - Win32 Release"
+# Name "gpplugin - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\Qt\GP.cpp
+DEP_CPP_GP_CP=\
+ "..\..\..\..\..\qtwin\include\qapplication.h"\
+ "..\..\..\..\..\qtwin\include\qarray.h"\
+ "..\..\..\..\..\qtwin\include\qasciidict.h"\
+ "..\..\..\..\..\qtwin\include\qbrush.h"\
+ "..\..\..\..\..\qtwin\include\qcollection.h"\
+ "..\..\..\..\..\qtwin\include\qcolor.h"\
+ "..\..\..\..\..\qtwin\include\qconfig-large.h"\
+ "..\..\..\..\..\qtwin\include\qconfig-medium.h"\
+ "..\..\..\..\..\qtwin\include\qconfig-minimal.h"\
+ "..\..\..\..\..\qtwin\include\qconfig-small.h"\
+ "..\..\..\..\..\qtwin\include\qconfig.h"\
+ "..\..\..\..\..\qtwin\include\qcstring.h"\
+ "..\..\..\..\..\qtwin\include\qcursor.h"\
+ "..\..\..\..\..\qtwin\include\qdatastream.h"\
+ "..\..\..\..\..\qtwin\include\qdialog.h"\
+ "..\..\..\..\..\qtwin\include\qevent.h"\
+ "..\..\..\..\..\qtwin\include\qfeatures.h"\
+ "..\..\..\..\..\qtwin\include\qfont.h"\
+ "..\..\..\..\..\qtwin\include\qfontinfo.h"\
+ "..\..\..\..\..\qtwin\include\qfontmetrics.h"\
+ "..\..\..\..\..\qtwin\include\qframe.h"\
+ "..\..\..\..\..\qtwin\include\qgarray.h"\
+ "..\..\..\..\..\qtwin\include\qgdict.h"\
+ "..\..\..\..\..\qtwin\include\qgl.h"\
+ "..\..\..\..\..\qtwin\include\qglist.h"\
+ "..\..\..\..\..\qtwin\include\qglobal.h"\
+ "..\..\..\..\..\qtwin\include\qiconset.h"\
+ "..\..\..\..\..\qtwin\include\qimage.h"\
+ "..\..\..\..\..\qtwin\include\qintdict.h"\
+ "..\..\..\..\..\qtwin\include\qiodevice.h"\
+ "..\..\..\..\..\qtwin\include\qlist.h"\
+ "..\..\..\..\..\qtwin\include\qmenudata.h"\
+ "..\..\..\..\..\qtwin\include\qmessagebox.h"\
+ "..\..\..\..\..\qtwin\include\qmime.h"\
+ "..\..\..\..\..\qtwin\include\qnamespace.h"\
+ "..\..\..\..\..\qtwin\include\qnp.h"\
+ "..\..\..\..\..\qtwin\include\qobject.h"\
+ "..\..\..\..\..\qtwin\include\qobjectdefs.h"\
+ "..\..\..\..\..\qtwin\include\qpaintdevice.h"\
+ "..\..\..\..\..\qtwin\include\qpainter.h"\
+ "..\..\..\..\..\qtwin\include\qpalette.h"\
+ "..\..\..\..\..\qtwin\include\qpen.h"\
+ "..\..\..\..\..\qtwin\include\qpixmap.h"\
+ "..\..\..\..\..\qtwin\include\qpngio.h"\
+ "..\..\..\..\..\qtwin\include\qpoint.h"\
+ "..\..\..\..\..\qtwin\include\qpointarray.h"\
+ "..\..\..\..\..\qtwin\include\qpopupmenu.h"\
+ "..\..\..\..\..\qtwin\include\qrect.h"\
+ "..\..\..\..\..\qtwin\include\qregexp.h"\
+ "..\..\..\..\..\qtwin\include\qregion.h"\
+ "..\..\..\..\..\qtwin\include\qshared.h"\
+ "..\..\..\..\..\qtwin\include\qsignal.h"\
+ "..\..\..\..\..\qtwin\include\qsize.h"\
+ "..\..\..\..\..\qtwin\include\qsizepolicy.h"\
+ "..\..\..\..\..\qtwin\include\qstring.h"\
+ "..\..\..\..\..\qtwin\include\qstringlist.h"\
+ "..\..\..\..\..\qtwin\include\qstrlist.h"\
+ "..\..\..\..\..\qtwin\include\qstyle.h"\
+ "..\..\..\..\..\qtwin\include\qt_windows.h"\
+ "..\..\..\..\..\qtwin\include\qtranslator.h"\
+ "..\..\..\..\..\qtwin\include\qvaluelist.h"\
+ "..\..\..\..\..\qtwin\include\qwidget.h"\
+ "..\..\..\..\..\qtwin\include\qwindowdefs.h"\
+ "..\..\..\..\..\qtwin\include\qwindowdefs_win.h"\
+ "..\..\..\..\..\qtwin\include\qwmatrix.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\abstract.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\bufferobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\ceval.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\classobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\cobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\complexobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\config.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\dictobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\fileobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\floatobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\funcobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\import.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\intobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\intrcheck.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\listobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\longobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\methodobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\modsupport.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\moduleobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\mymalloc.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\myproto.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\object.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\objimpl.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\patchlevel.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\pydebug.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\pyerrors.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\pyfpe.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\pystate.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\Python.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\pythonrun.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\rangeobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\sliceobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\stringobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\sysmodule.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\traceback.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\tupleobject.h"\
+ "..\..\..\..\source\gameengine\GameLogic\SCA_IInputDevice.h"\
+ "..\..\..\..\source\gameengine\GameLogic\SCA_ISystem.h"\
+ "..\..\..\..\source\gameengine\GamePlayer\Qt\GP_Init.h"\
+ "..\..\..\..\source\gameengine\GamePlayer\Qt\QtInputDevice.h"\
+ "..\..\..\..\source\gameengine\GamePlayer\Qt\QtKeyboardDevice.h"\
+ "..\..\..\..\source\gameengine\GamePlayer\Qt\QtOpenGLWidget.h"\
+ "..\..\..\..\source\gameengine\GamePlayer\Qt\QtRenderTools.h"\
+ "..\..\..\..\source\gameengine\GamePlayer\Qt\QtSystem.h"\
+ "..\..\..\..\source\gameengine\Network\LoopBackNetwork\NG_LoopBackNetworkDeviceInterface.h"\
+ "..\..\..\..\source\gameengine\Network\NG_NetworkDeviceInterface.h"\
+ "..\..\..\..\source\gameengine\Network\NG_NetworkScene.h"\
+ "..\..\..\..\source\gameengine\Rasterizer\RAS_ICanvas.h"\
+ "..\..\..\..\source\gameengine\Rasterizer\RAS_IPolygonMaterial.h"\
+ "..\..\..\..\source\gameengine\Rasterizer\RAS_IRasterizer.h"\
+ "..\..\..\..\source\gameengine\Rasterizer\RAS_IRenderTools.h"\
+ "..\..\..\..\source\gameengine\Rasterizer\RAS_MaterialBucket.h"\
+ "..\..\..\..\source\gameengine\Rasterizer\RAS_TexVert.h"\
+ "..\..\..\..\source\kernel\gen_system\GEN_HashedString.h"\
+ "..\..\..\..\source\kernel\gen_system\GEN_Matrix4x4.h"\
+ "..\..\..\..\source\kernel\gen_system\GEN_StdString.h"\
+ "..\..\..\..\lib\windows\moto\include\GEN_Map.h"\
+ "..\..\..\..\lib\windows\moto\include\GEN_MinMax.h"\
+ "..\..\..\..\lib\windows\moto\include\GEN_Optimize.h"\
+ "..\..\..\..\lib\windows\moto\include\GEN_random.h"\
+ "..\..\..\..\lib\windows\moto\include\GEN_Stream.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_assert.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Matrix3x3.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Matrix3x3.inl"\
+ "..\..\..\..\lib\windows\moto\include\MT_Point2.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Point2.inl"\
+ "..\..\..\..\lib\windows\moto\include\MT_Point3.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Point3.inl"\
+ "..\..\..\..\lib\windows\moto\include\MT_Quaternion.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Quaternion.inl"\
+ "..\..\..\..\lib\windows\moto\include\MT_Scalar.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Transform.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Tuple2.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Tuple3.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Tuple4.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Vector2.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Vector2.inl"\
+ "..\..\..\..\lib\windows\moto\include\MT_Vector3.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Vector3.inl"\
+ "..\..\..\..\lib\windows\moto\include\MT_Vector4.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Vector4.inl"\
+ "..\..\..\..\lib\windows\moto\include\NM_Scalar.h"\
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\Qt\GP_Init.cpp
+DEP_CPP_GP_IN=\
+ "..\..\..\..\lib\windows\python\include\python1.5\abstract.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\bufferobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\ceval.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\classobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\cobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\complexobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\config.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\dictobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\fileobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\floatobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\funcobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\import.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\intobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\intrcheck.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\listobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\longobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\methodobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\modsupport.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\moduleobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\mymalloc.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\myproto.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\object.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\objimpl.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\patchlevel.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\pydebug.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\pyerrors.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\pyfpe.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\pystate.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\Python.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\pythonrun.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\rangeobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\sliceobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\stringobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\sysmodule.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\traceback.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\tupleobject.h"\
+ "..\..\..\..\source\gameengine\Expressions\BoolValue.h"\
+ "..\..\..\..\source\gameengine\Expressions\ListValue.h"\
+ "..\..\..\..\source\gameengine\Expressions\PyObjectPlus.h"\
+ "..\..\..\..\source\gameengine\Expressions\Value.h"\
+ "..\..\..\..\source\gameengine\GameLogic\SCA_AlwaysEventManager.h"\
+ "..\..\..\..\source\gameengine\GameLogic\SCA_AlwaysSensor.h"\
+ "..\..\..\..\source\gameengine\GameLogic\SCA_ANDController.h"\
+ "..\..\..\..\source\gameengine\GameLogic\SCA_EventManager.h"\
+ "..\..\..\..\source\gameengine\GameLogic\SCA_IActuator.h"\
+ "..\..\..\..\source\gameengine\GameLogic\SCA_IController.h"\
+ "..\..\..\..\source\gameengine\GameLogic\SCA_IInputDevice.h"\
+ "..\..\..\..\source\gameengine\GameLogic\SCA_ILogicBrick.h"\
+ "..\..\..\..\source\gameengine\GameLogic\SCA_IObject.h"\
+ "..\..\..\..\source\gameengine\GameLogic\SCA_ISensor.h"\
+ "..\..\..\..\source\gameengine\GameLogic\SCA_ISystem.h"\
+ "..\..\..\..\source\gameengine\GameLogic\SCA_KeyboardManager.h"\
+ "..\..\..\..\source\gameengine\GameLogic\SCA_KeyboardSensor.h"\
+ "..\..\..\..\source\gameengine\GameLogic\SCA_LogicManager.h"\
+ "..\..\..\..\source\gameengine\GameLogic\SCA_PythonController.h"\
+ "..\..\..\..\source\gameengine\GamePlayer\Qt\DebugActuator.h"\
+ "..\..\..\..\source\gameengine\GamePlayer\Qt\QtExampleEngine.h"\
+ "..\..\..\..\source\gameengine\GamePlayer\Qt\SamplePolygonMaterial.h"\
+ "..\..\..\..\source\gameengine\Ketsji\KX_GameObject.h"\
+ "..\..\..\..\source\gameengine\Ketsji\KX_ObjectActuator.h"\
+ "..\..\..\..\source\gameengine\Ketsji\KX_PythonInit.h"\
+ "..\..\..\..\source\gameengine\Ketsji\KX_SoundActuator.h"\
+ "..\..\..\..\source\gameengine\Ketsji\KXNetwork\KX_NetworkEventManager.h"\
+ "..\..\..\..\source\gameengine\Network\LoopBackNetwork\NG_LoopBackNetworkDeviceInterface.h"\
+ "..\..\..\..\source\gameengine\Network\NG_NetworkDeviceInterface.h"\
+ "..\..\..\..\source\gameengine\Network\NG_NetworkScene.h"\
+ "..\..\..\..\source\gameengine\Rasterizer\RAS_BucketManager.h"\
+ "..\..\..\..\source\gameengine\Rasterizer\RAS_ICanvas.h"\
+ "..\..\..\..\source\gameengine\Rasterizer\RAS_IPolygonMaterial.h"\
+ "..\..\..\..\source\gameengine\Rasterizer\RAS_IRasterizer.h"\
+ "..\..\..\..\source\gameengine\Rasterizer\RAS_MaterialBucket.h"\
+ "..\..\..\..\source\gameengine\Rasterizer\RAS_MeshObject.h"\
+ "..\..\..\..\source\gameengine\Rasterizer\RAS_OpenGLRasterizer\RAS_OpenGLRasterizer.h"\
+ "..\..\..\..\source\gameengine\Rasterizer\RAS_Polygon.h"\
+ "..\..\..\..\source\gameengine\Rasterizer\RAS_TexVert.h"\
+ "..\..\..\..\source\gameengine\SceneGraph\SG_IObject.h"\
+ "..\..\..\..\source\gameengine\SceneGraph\SG_Node.h"\
+ "..\..\..\..\source\gameengine\SceneGraph\SG_Spatial.h"\
+ "..\..\..\..\source\kernel\gen_system\GEN_HashedPtr.h"\
+ "..\..\..\..\source\kernel\gen_system\GEN_HashedString.h"\
+ "..\..\..\..\source\kernel\gen_system\GEN_Matrix4x4.h"\
+ "..\..\..\..\source\kernel\gen_system\GEN_StdString.h"\
+ "..\..\..\..\source\sumo\include\solid.h"\
+ "..\..\..\..\source\sumo\include\solid_types.h"\
+ "..\..\..\..\lib\windows\moto\include\GEN_Map.h"\
+ "..\..\..\..\lib\windows\moto\include\GEN_MinMax.h"\
+ "..\..\..\..\lib\windows\moto\include\GEN_Optimize.h"\
+ "..\..\..\..\lib\windows\moto\include\GEN_random.h"\
+ "..\..\..\..\lib\windows\moto\include\GEN_Stream.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_assert.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Matrix3x3.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Matrix3x3.inl"\
+ "..\..\..\..\lib\windows\moto\include\MT_Point2.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Point2.inl"\
+ "..\..\..\..\lib\windows\moto\include\MT_Point3.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Point3.inl"\
+ "..\..\..\..\lib\windows\moto\include\MT_Quaternion.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Quaternion.inl"\
+ "..\..\..\..\lib\windows\moto\include\MT_Scalar.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Transform.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Tuple2.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Tuple3.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Tuple4.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Vector2.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Vector2.inl"\
+ "..\..\..\..\lib\windows\moto\include\MT_Vector3.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Vector3.inl"\
+ "..\..\..\..\lib\windows\moto\include\MT_Vector4.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Vector4.inl"\
+ "..\..\..\..\lib\windows\moto\include\NM_Scalar.h"\
+
+NODEP_CPP_GP_IN=\
+ "..\..\..\..\source\gameengine\GamePlayer\Qt\GPC_OpenALWaveCache.h"\
+ "..\..\..\..\source\gameengine\GamePlayer\Qt\OpenALScene.h"\
+ "..\..\..\..\source\gameengine\GamePlayer\Qt\SND_SoundObject.h"\
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\Qt\QtExampleEngine.cpp
+DEP_CPP_QTEXA=\
+ "..\..\..\..\lib\windows\python\include\python1.5\abstract.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\bufferobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\ceval.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\classobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\cobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\complexobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\config.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\dictobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\fileobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\floatobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\funcobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\import.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\intobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\intrcheck.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\listobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\longobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\methodobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\modsupport.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\moduleobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\mymalloc.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\myproto.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\object.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\objimpl.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\patchlevel.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\pydebug.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\pyerrors.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\pyfpe.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\pystate.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\Python.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\pythonrun.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\rangeobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\sliceobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\stringobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\sysmodule.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\traceback.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\tupleobject.h"\
+ "..\..\..\..\source\gameengine\Expressions\BoolValue.h"\
+ "..\..\..\..\source\gameengine\Expressions\IntValue.h"\
+ "..\..\..\..\source\gameengine\Expressions\ListValue.h"\
+ "..\..\..\..\source\gameengine\Expressions\PyObjectPlus.h"\
+ "..\..\..\..\source\gameengine\Expressions\Value.h"\
+ "..\..\..\..\source\gameengine\GameLogic\SCA_IActuator.h"\
+ "..\..\..\..\source\gameengine\GameLogic\SCA_IInputDevice.h"\
+ "..\..\..\..\source\gameengine\GameLogic\SCA_ILogicBrick.h"\
+ "..\..\..\..\source\gameengine\GameLogic\SCA_IObject.h"\
+ "..\..\..\..\source\gameengine\GameLogic\SCA_ISystem.h"\
+ "..\..\..\..\source\gameengine\GameLogic\SCA_LogicManager.h"\
+ "..\..\..\..\source\gameengine\GamePlayer\Qt\QtExampleEngine.h"\
+ "..\..\..\..\source\gameengine\Ketsji\KX_Camera.h"\
+ "..\..\..\..\source\gameengine\Ketsji\KX_GameObject.h"\
+ "..\..\..\..\source\gameengine\Ketsji\KX_ObjectActuator.h"\
+ "..\..\..\..\source\gameengine\Network\NG_NetworkScene.h"\
+ "..\..\..\..\source\gameengine\Rasterizer\RAS_BucketManager.h"\
+ "..\..\..\..\source\gameengine\Rasterizer\RAS_CameraData.h"\
+ "..\..\..\..\source\gameengine\Rasterizer\RAS_IPolygonMaterial.h"\
+ "..\..\..\..\source\gameengine\Rasterizer\RAS_IRasterizer.h"\
+ "..\..\..\..\source\gameengine\Rasterizer\RAS_IRenderTools.h"\
+ "..\..\..\..\source\gameengine\Rasterizer\RAS_MaterialBucket.h"\
+ "..\..\..\..\source\gameengine\Rasterizer\RAS_MeshObject.h"\
+ "..\..\..\..\source\gameengine\Rasterizer\RAS_Polygon.h"\
+ "..\..\..\..\source\gameengine\Rasterizer\RAS_TexVert.h"\
+ "..\..\..\..\source\gameengine\SceneGraph\SG_IObject.h"\
+ "..\..\..\..\source\gameengine\SceneGraph\SG_Node.h"\
+ "..\..\..\..\source\gameengine\SceneGraph\SG_Spatial.h"\
+ "..\..\..\..\source\kernel\gen_system\GEN_HashedPtr.h"\
+ "..\..\..\..\source\kernel\gen_system\GEN_HashedString.h"\
+ "..\..\..\..\source\kernel\gen_system\GEN_Matrix4x4.h"\
+ "..\..\..\..\source\kernel\gen_system\GEN_StdString.h"\
+ "..\..\..\..\source\sumo\Fuzzics\include\SM_Scene.h"\
+ "..\..\..\..\source\sumo\include\solid.h"\
+ "..\..\..\..\source\sumo\include\solid_types.h"\
+ "..\..\..\..\lib\windows\moto\include\GEN_Map.h"\
+ "..\..\..\..\lib\windows\moto\include\GEN_MinMax.h"\
+ "..\..\..\..\lib\windows\moto\include\GEN_Optimize.h"\
+ "..\..\..\..\lib\windows\moto\include\GEN_random.h"\
+ "..\..\..\..\lib\windows\moto\include\GEN_Stream.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_assert.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Matrix3x3.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Matrix3x3.inl"\
+ "..\..\..\..\lib\windows\moto\include\MT_Point2.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Point2.inl"\
+ "..\..\..\..\lib\windows\moto\include\MT_Point3.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Point3.inl"\
+ "..\..\..\..\lib\windows\moto\include\MT_Quaternion.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Quaternion.inl"\
+ "..\..\..\..\lib\windows\moto\include\MT_Scalar.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Transform.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Tuple2.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Tuple3.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Tuple4.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Vector2.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Vector2.inl"\
+ "..\..\..\..\lib\windows\moto\include\MT_Vector3.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Vector3.inl"\
+ "..\..\..\..\lib\windows\moto\include\MT_Vector4.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Vector4.inl"\
+ "..\..\..\..\lib\windows\moto\include\NM_Scalar.h"\
+
+NODEP_CPP_QTEXA=\
+ "..\..\..\..\source\gameengine\GamePlayer\Qt\OpenALScene.h"\
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\Qt\QtKeyboardDevice.cpp
+DEP_CPP_QTKEY=\
+ "..\..\..\..\source\gameengine\GameLogic\SCA_IInputDevice.h"\
+ "..\..\..\..\source\gameengine\GamePlayer\Qt\QtInputDevice.h"\
+ "..\..\..\..\source\gameengine\GamePlayer\Qt\QtKeyboardDevice.h"\
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\Qt\QtOpenGLWidget.cpp
+DEP_CPP_QTOPE=\
+ "..\..\..\..\..\qtwin\include\qapplication.h"\
+ "..\..\..\..\..\qtwin\include\qarray.h"\
+ "..\..\..\..\..\qtwin\include\qasciidict.h"\
+ "..\..\..\..\..\qtwin\include\qbrush.h"\
+ "..\..\..\..\..\qtwin\include\qcollection.h"\
+ "..\..\..\..\..\qtwin\include\qcolor.h"\
+ "..\..\..\..\..\qtwin\include\qconfig-large.h"\
+ "..\..\..\..\..\qtwin\include\qconfig-medium.h"\
+ "..\..\..\..\..\qtwin\include\qconfig-minimal.h"\
+ "..\..\..\..\..\qtwin\include\qconfig-small.h"\
+ "..\..\..\..\..\qtwin\include\qconfig.h"\
+ "..\..\..\..\..\qtwin\include\qcstring.h"\
+ "..\..\..\..\..\qtwin\include\qcursor.h"\
+ "..\..\..\..\..\qtwin\include\qdatastream.h"\
+ "..\..\..\..\..\qtwin\include\qevent.h"\
+ "..\..\..\..\..\qtwin\include\qfeatures.h"\
+ "..\..\..\..\..\qtwin\include\qfont.h"\
+ "..\..\..\..\..\qtwin\include\qfontinfo.h"\
+ "..\..\..\..\..\qtwin\include\qfontmetrics.h"\
+ "..\..\..\..\..\qtwin\include\qframe.h"\
+ "..\..\..\..\..\qtwin\include\qgarray.h"\
+ "..\..\..\..\..\qtwin\include\qgdict.h"\
+ "..\..\..\..\..\qtwin\include\qgl.h"\
+ "..\..\..\..\..\qtwin\include\qglist.h"\
+ "..\..\..\..\..\qtwin\include\qglobal.h"\
+ "..\..\..\..\..\qtwin\include\qiconset.h"\
+ "..\..\..\..\..\qtwin\include\qintdict.h"\
+ "..\..\..\..\..\qtwin\include\qiodevice.h"\
+ "..\..\..\..\..\qtwin\include\qlist.h"\
+ "..\..\..\..\..\qtwin\include\qmenudata.h"\
+ "..\..\..\..\..\qtwin\include\qmime.h"\
+ "..\..\..\..\..\qtwin\include\qnamespace.h"\
+ "..\..\..\..\..\qtwin\include\qobject.h"\
+ "..\..\..\..\..\qtwin\include\qobjectdefs.h"\
+ "..\..\..\..\..\qtwin\include\qpaintdevice.h"\
+ "..\..\..\..\..\qtwin\include\qpalette.h"\
+ "..\..\..\..\..\qtwin\include\qpixmap.h"\
+ "..\..\..\..\..\qtwin\include\qpoint.h"\
+ "..\..\..\..\..\qtwin\include\qpopupmenu.h"\
+ "..\..\..\..\..\qtwin\include\qrect.h"\
+ "..\..\..\..\..\qtwin\include\qregexp.h"\
+ "..\..\..\..\..\qtwin\include\qregion.h"\
+ "..\..\..\..\..\qtwin\include\qshared.h"\
+ "..\..\..\..\..\qtwin\include\qsignal.h"\
+ "..\..\..\..\..\qtwin\include\qsize.h"\
+ "..\..\..\..\..\qtwin\include\qsizepolicy.h"\
+ "..\..\..\..\..\qtwin\include\qstring.h"\
+ "..\..\..\..\..\qtwin\include\qstringlist.h"\
+ "..\..\..\..\..\qtwin\include\qstyle.h"\
+ "..\..\..\..\..\qtwin\include\qt_windows.h"\
+ "..\..\..\..\..\qtwin\include\qtranslator.h"\
+ "..\..\..\..\..\qtwin\include\qvaluelist.h"\
+ "..\..\..\..\..\qtwin\include\qwidget.h"\
+ "..\..\..\..\..\qtwin\include\qwindowdefs.h"\
+ "..\..\..\..\..\qtwin\include\qwindowdefs_win.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\abstract.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\bufferobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\ceval.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\classobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\cobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\complexobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\config.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\dictobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\fileobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\floatobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\funcobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\import.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\intobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\intrcheck.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\listobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\longobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\methodobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\modsupport.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\moduleobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\mymalloc.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\myproto.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\object.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\objimpl.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\patchlevel.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\pydebug.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\pyerrors.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\pyfpe.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\pystate.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\Python.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\pythonrun.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\rangeobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\sliceobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\stringobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\sysmodule.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\traceback.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\tupleobject.h"\
+ "..\..\..\..\source\gameengine\GameLogic\SCA_IInputDevice.h"\
+ "..\..\..\..\source\gameengine\GameLogic\SCA_ISystem.h"\
+ "..\..\..\..\source\gameengine\GamePlayer\Qt\GP_Init.h"\
+ "..\..\..\..\source\gameengine\GamePlayer\Qt\QtInputDevice.h"\
+ "..\..\..\..\source\gameengine\GamePlayer\Qt\QtKeyboardDevice.h"\
+ "..\..\..\..\source\gameengine\GamePlayer\Qt\QtOpenGLWidget.h"\
+ "..\..\..\..\source\gameengine\GamePlayer\Qt\QtRenderTools.h"\
+ "..\..\..\..\source\gameengine\GamePlayer\Qt\QtSystem.h"\
+ "..\..\..\..\source\gameengine\Rasterizer\RAS_ICanvas.h"\
+ "..\..\..\..\source\gameengine\Rasterizer\RAS_IPolygonMaterial.h"\
+ "..\..\..\..\source\gameengine\Rasterizer\RAS_IRasterizer.h"\
+ "..\..\..\..\source\gameengine\Rasterizer\RAS_IRenderTools.h"\
+ "..\..\..\..\source\gameengine\Rasterizer\RAS_MaterialBucket.h"\
+ "..\..\..\..\source\gameengine\Rasterizer\RAS_TexVert.h"\
+ "..\..\..\..\source\kernel\gen_system\GEN_HashedString.h"\
+ "..\..\..\..\source\kernel\gen_system\GEN_Matrix4x4.h"\
+ "..\..\..\..\source\kernel\gen_system\GEN_StdString.h"\
+ "..\..\..\..\lib\windows\moto\include\GEN_Map.h"\
+ "..\..\..\..\lib\windows\moto\include\GEN_MinMax.h"\
+ "..\..\..\..\lib\windows\moto\include\GEN_Optimize.h"\
+ "..\..\..\..\lib\windows\moto\include\GEN_random.h"\
+ "..\..\..\..\lib\windows\moto\include\GEN_Stream.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_assert.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Matrix3x3.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Matrix3x3.inl"\
+ "..\..\..\..\lib\windows\moto\include\MT_Point2.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Point2.inl"\
+ "..\..\..\..\lib\windows\moto\include\MT_Point3.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Point3.inl"\
+ "..\..\..\..\lib\windows\moto\include\MT_Quaternion.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Quaternion.inl"\
+ "..\..\..\..\lib\windows\moto\include\MT_Scalar.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Transform.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Tuple2.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Tuple3.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Tuple4.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Vector2.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Vector2.inl"\
+ "..\..\..\..\lib\windows\moto\include\MT_Vector3.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Vector3.inl"\
+ "..\..\..\..\lib\windows\moto\include\MT_Vector4.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Vector4.inl"\
+ "..\..\..\..\lib\windows\moto\include\NM_Scalar.h"\
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\Qt\QtSystem.cpp
+DEP_CPP_QTSYS=\
+ "..\..\..\..\..\qtwin\include\qapplication.h"\
+ "..\..\..\..\..\qtwin\include\qarray.h"\
+ "..\..\..\..\..\qtwin\include\qasciidict.h"\
+ "..\..\..\..\..\qtwin\include\qbrush.h"\
+ "..\..\..\..\..\qtwin\include\qcollection.h"\
+ "..\..\..\..\..\qtwin\include\qcolor.h"\
+ "..\..\..\..\..\qtwin\include\qconfig-large.h"\
+ "..\..\..\..\..\qtwin\include\qconfig-medium.h"\
+ "..\..\..\..\..\qtwin\include\qconfig-minimal.h"\
+ "..\..\..\..\..\qtwin\include\qconfig-small.h"\
+ "..\..\..\..\..\qtwin\include\qconfig.h"\
+ "..\..\..\..\..\qtwin\include\qcstring.h"\
+ "..\..\..\..\..\qtwin\include\qcursor.h"\
+ "..\..\..\..\..\qtwin\include\qdatastream.h"\
+ "..\..\..\..\..\qtwin\include\qevent.h"\
+ "..\..\..\..\..\qtwin\include\qfeatures.h"\
+ "..\..\..\..\..\qtwin\include\qfont.h"\
+ "..\..\..\..\..\qtwin\include\qfontinfo.h"\
+ "..\..\..\..\..\qtwin\include\qfontmetrics.h"\
+ "..\..\..\..\..\qtwin\include\qframe.h"\
+ "..\..\..\..\..\qtwin\include\qgarray.h"\
+ "..\..\..\..\..\qtwin\include\qgdict.h"\
+ "..\..\..\..\..\qtwin\include\qgl.h"\
+ "..\..\..\..\..\qtwin\include\qglist.h"\
+ "..\..\..\..\..\qtwin\include\qglobal.h"\
+ "..\..\..\..\..\qtwin\include\qiconset.h"\
+ "..\..\..\..\..\qtwin\include\qintdict.h"\
+ "..\..\..\..\..\qtwin\include\qiodevice.h"\
+ "..\..\..\..\..\qtwin\include\qlist.h"\
+ "..\..\..\..\..\qtwin\include\qmenudata.h"\
+ "..\..\..\..\..\qtwin\include\qmime.h"\
+ "..\..\..\..\..\qtwin\include\qnamespace.h"\
+ "..\..\..\..\..\qtwin\include\qobject.h"\
+ "..\..\..\..\..\qtwin\include\qobjectdefs.h"\
+ "..\..\..\..\..\qtwin\include\qpaintdevice.h"\
+ "..\..\..\..\..\qtwin\include\qpalette.h"\
+ "..\..\..\..\..\qtwin\include\qpixmap.h"\
+ "..\..\..\..\..\qtwin\include\qpoint.h"\
+ "..\..\..\..\..\qtwin\include\qpopupmenu.h"\
+ "..\..\..\..\..\qtwin\include\qrect.h"\
+ "..\..\..\..\..\qtwin\include\qregexp.h"\
+ "..\..\..\..\..\qtwin\include\qregion.h"\
+ "..\..\..\..\..\qtwin\include\qshared.h"\
+ "..\..\..\..\..\qtwin\include\qsignal.h"\
+ "..\..\..\..\..\qtwin\include\qsize.h"\
+ "..\..\..\..\..\qtwin\include\qsizepolicy.h"\
+ "..\..\..\..\..\qtwin\include\qstring.h"\
+ "..\..\..\..\..\qtwin\include\qstringlist.h"\
+ "..\..\..\..\..\qtwin\include\qstyle.h"\
+ "..\..\..\..\..\qtwin\include\qt_windows.h"\
+ "..\..\..\..\..\qtwin\include\qtranslator.h"\
+ "..\..\..\..\..\qtwin\include\qvaluelist.h"\
+ "..\..\..\..\..\qtwin\include\qwidget.h"\
+ "..\..\..\..\..\qtwin\include\qwindowdefs.h"\
+ "..\..\..\..\..\qtwin\include\qwindowdefs_win.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\abstract.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\bufferobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\ceval.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\classobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\cobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\complexobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\config.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\dictobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\fileobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\floatobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\funcobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\import.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\intobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\intrcheck.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\listobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\longobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\methodobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\modsupport.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\moduleobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\mymalloc.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\myproto.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\object.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\objimpl.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\patchlevel.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\pydebug.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\pyerrors.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\pyfpe.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\pystate.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\Python.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\pythonrun.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\rangeobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\sliceobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\stringobject.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\sysmodule.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\traceback.h"\
+ "..\..\..\..\lib\windows\python\include\python1.5\tupleobject.h"\
+ "..\..\..\..\source\gameengine\GameLogic\SCA_IInputDevice.h"\
+ "..\..\..\..\source\gameengine\GameLogic\SCA_ISystem.h"\
+ "..\..\..\..\source\gameengine\GamePlayer\Qt\GP_Init.h"\
+ "..\..\..\..\source\gameengine\GamePlayer\Qt\QtInputDevice.h"\
+ "..\..\..\..\source\gameengine\GamePlayer\Qt\QtKeyboardDevice.h"\
+ "..\..\..\..\source\gameengine\GamePlayer\Qt\QtOpenGLWidget.h"\
+ "..\..\..\..\source\gameengine\GamePlayer\Qt\QtRenderTools.h"\
+ "..\..\..\..\source\gameengine\GamePlayer\Qt\QtSystem.h"\
+ "..\..\..\..\source\gameengine\Network\LoopBackNetwork\NG_LoopBackNetworkDeviceInterface.h"\
+ "..\..\..\..\source\gameengine\Network\NG_NetworkDeviceInterface.h"\
+ "..\..\..\..\source\gameengine\Network\NG_NetworkScene.h"\
+ "..\..\..\..\source\gameengine\Rasterizer\RAS_ICanvas.h"\
+ "..\..\..\..\source\gameengine\Rasterizer\RAS_IPolygonMaterial.h"\
+ "..\..\..\..\source\gameengine\Rasterizer\RAS_IRasterizer.h"\
+ "..\..\..\..\source\gameengine\Rasterizer\RAS_IRenderTools.h"\
+ "..\..\..\..\source\gameengine\Rasterizer\RAS_MaterialBucket.h"\
+ "..\..\..\..\source\gameengine\Rasterizer\RAS_TexVert.h"\
+ "..\..\..\..\source\kernel\gen_system\GEN_HashedString.h"\
+ "..\..\..\..\source\kernel\gen_system\GEN_Matrix4x4.h"\
+ "..\..\..\..\source\kernel\gen_system\GEN_StdString.h"\
+ "..\..\..\..\lib\windows\moto\include\GEN_Map.h"\
+ "..\..\..\..\lib\windows\moto\include\GEN_MinMax.h"\
+ "..\..\..\..\lib\windows\moto\include\GEN_Optimize.h"\
+ "..\..\..\..\lib\windows\moto\include\GEN_random.h"\
+ "..\..\..\..\lib\windows\moto\include\GEN_Stream.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_assert.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Matrix3x3.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Matrix3x3.inl"\
+ "..\..\..\..\lib\windows\moto\include\MT_Point2.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Point2.inl"\
+ "..\..\..\..\lib\windows\moto\include\MT_Point3.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Point3.inl"\
+ "..\..\..\..\lib\windows\moto\include\MT_Quaternion.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Quaternion.inl"\
+ "..\..\..\..\lib\windows\moto\include\MT_Scalar.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Transform.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Tuple2.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Tuple3.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Tuple4.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Vector2.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Vector2.inl"\
+ "..\..\..\..\lib\windows\moto\include\MT_Vector3.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Vector3.inl"\
+ "..\..\..\..\lib\windows\moto\include\MT_Vector4.h"\
+ "..\..\..\..\lib\windows\moto\include\MT_Vector4.inl"\
+ "..\..\..\..\lib\windows\moto\include\NM_Scalar.h"\
+
+NODEP_CPP_QTSYS=\
+ "..\..\..\..\source\gameengine\GamePlayer\Qt\BKE_bad_level_calls.h"\
+ "..\..\..\..\source\gameengine\GamePlayer\Qt\BLO_readfile.h"\
+
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\Qt\DebugActuator.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\Qt\GP_Init.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\Qt\QtExampleEngine.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\Qt\QtInputDevice.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\Qt\QtKeyboardDevice.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\Qt\QtOpenGLWidget.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\Qt\QtRenderTools.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\Qt\QtSystem.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\Qt\resource.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\Qt\SamplePolygonMaterial.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"
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\Qt\GP.rc
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/gameengine/gameplayer/qt/qtgp.dsw b/projectfiles/gameengine/gameplayer/qt/qtgp.dsw
new file mode 100644
index 00000000000..22d9c5db23c
--- /dev/null
+++ b/projectfiles/gameengine/gameplayer/qt/qtgp.dsw
@@ -0,0 +1,323 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "BLO_loader"=..\..\..\blender\loader\BLO_loader.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "EXP_expressions"=..\..\expression\EXP_expressions.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "SCA_GameLogic"=..\..\gamelogic\SCA_GameLogic.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "KX_ketsji"=..\..\ketsji\KX_ketsji.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "KX_network"=..\..\ketsji\network\KX_network.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "SG_SceneGraph"=..\..\scenegraph\SG_SceneGraph.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "NG_loopbacknetwork"=..\..\network\loopbacknetwork\NG_loopbacknetwork.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "NG_network"=..\..\network\network\NG_network.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "RAS_openglrasterizer"=..\..\rasterizer\openglrasterizer\RAS_openglrasterizer.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "RAS_rasterizer"=..\..\rasterizer\RAS_rasterizer.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "SM_fuzzics"=..\..\..\sumo\fuzzics\SM_fuzzics.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "SM_moto"=..\..\..\sumo\moto\SM_moto.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "SM_solid"=..\..\..\sumo\solid\SM_solid.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "SND_openal"=..\..\sound\openal\SND_openal.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "SND_sound"=..\..\sound\SND_sound.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "SYS_system"=..\..\..\kernel\system\SYS_system.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "gp"=.\gp.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name EXP_expressions
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name SCA_GameLogic
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name KX_ketsji
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name KX_network
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name SG_SceneGraph
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name NG_loopbacknetwork
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name NG_network
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name RAS_openglrasterizer
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name RAS_rasterizer
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name SM_fuzzics
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name SM_moto
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name SM_solid
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name SND_openal
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name SND_sound
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name SYS_system
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "gpplugin"=.\gpplugin.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name EXP_expressions
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name SCA_GameLogic
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name KX_ketsji
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name KX_network
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name SG_SceneGraph
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name NG_loopbacknetwork
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name NG_network
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name RAS_openglrasterizer
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name RAS_rasterizer
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name SM_fuzzics
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name SM_moto
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name SM_solid
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name SND_openal
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name SND_sound
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name SYS_system
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/projectfiles/gameengine/gameplayer/sdl/GP_sdl.dsp b/projectfiles/gameengine/gameplayer/sdl/GP_sdl.dsp
new file mode 100644
index 00000000000..4a4f39871cf
--- /dev/null
+++ b/projectfiles/gameengine/gameplayer/sdl/GP_sdl.dsp
@@ -0,0 +1,205 @@
+# Microsoft Developer Studio Project File - Name="GP_sdl" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=GP_sdl - Win32 Profile
+!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 "GP_sdl.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 "GP_sdl.mak" CFG="GP_sdl - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "GP_sdl - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "GP_sdl - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE "GP_sdl - Win32 Profile" (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)" == "GP_sdl - 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 "..\..\..\..\obj\windows\gameengine\gameplayer\sdl"
+# 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 /W3 /GX /O2 /I "..\..\..\..\source\gameengine\network" /I "..\..\..\..\source\gameengine\network\loopbacknetwork" /I "..\..\..\..\source\gameengine\gameplayer\common" /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\gamelogic" /I "..\..\..\..\source\gameengine\Rasterizer" /I "..\..\..\..\source\sumo\include" /I "..\..\..\..\lib\windows\moto\include" /I "..\..\..\..\source\sumo\Fuzzics\include" /I "..\..\..\..\lib\windows\sdl\SDL-1.1.7\include" /I "..\..\..\..\lib\windows\python\include\python2.0" /D "NDEBUG" /D "WIN32" /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 sdl.lib sdlmain.lib kernel32.lib winspool.lib comdlg32.lib shell32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib opengl32.lib user32.lib gdi32.lib advapi32.lib dxguid.lib ole32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\..\lib\windows\sdl\sdl-1.1.7\lib" /libpath:"..\..\..\..\lib\windows\python\lib"
+
+!ELSEIF "$(CFG)" == "GP_sdl - 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 "..\..\..\..\obj\windows\gameengine\gameplayer\sdl\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 "..\..\..\..\source\gameengine\network" /I "..\..\..\..\source\gameengine\network\loopbacknetwork" /I "..\..\..\..\source\gameengine\gameplayer\common" /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\gamelogic" /I "..\..\..\..\source\gameengine\Rasterizer" /I "..\..\..\..\source\sumo\include" /I "..\..\..\..\lib\windows\moto\include" /I "..\..\..\..\source\sumo\Fuzzics\include" /I "..\..\..\..\lib\windows\sdl\SDL-1.1.7\include" /I "..\..\..\..\lib\windows\python\include\python1.5" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /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
+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 sdlmaindebug.lib sdldebug.lib opengl32.lib user32.lib gdi32.lib advapi32.lib dxguid.lib ole32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\..\..\lib\windows\sdl\sdl-1.1.7\lib" /libpath:"..\..\..\..\lib\windows\python\lib" /libpath:"..\..\..\..\lib\windows\openal\lib\lib_release"
+
+!ELSEIF "$(CFG)" == "GP_sdl - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "GP_sdl___Win32_Profile"
+# PROP BASE Intermediate_Dir "GP_sdl___Win32_Profile"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "GP_sdl___Win32_Profile"
+# PROP Intermediate_Dir "GP_sdl___Win32_Profile"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\..\source\gameengine\network" /I "..\..\..\..\source\gameengine\network\loopbacknetwork" /I "..\..\..\..\source\gameengine\gameplayer\common" /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\gamelogic" /I "..\..\..\..\source\gameengine\Rasterizer" /I "..\..\..\..\source\sumo\include" /I "..\..\..\..\lib\windows\moto\include" /I "..\..\..\..\source\sumo\Fuzzics\include" /I "..\..\..\..\lib\windows\sdl\SDL-1.1.7\include" /I "..\..\..\..\lib\windows\python\include\python1.5" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /O2 /I "..\..\..\..\source\gameengine\network" /I "..\..\..\..\source\gameengine\network\loopbacknetwork" /I "..\..\..\..\source\gameengine\gameplayer\common" /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\gamelogic" /I "..\..\..\..\source\gameengine\Rasterizer" /I "..\..\..\..\source\sumo\include" /I "..\..\..\..\lib\windows\moto\include" /I "..\..\..\..\source\sumo\Fuzzics\include" /I "..\..\..\..\lib\windows\sdl\SDL-1.1.7\include" /I "..\..\..\..\lib\windows\python\include\python1.5" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 glu32.lib sdlmaindebug.lib sdldebug.lib opengl32.lib user32.lib gdi32.lib advapi32.lib dxguid.lib ole32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\..\..\lib\windows\sdl\sdl-1.1.7\lib" /libpath:"..\..\..\..\lib\windows\python\lib" /libpath:"..\..\..\..\lib\windows\openal\lib\lib_release"
+# ADD LINK32 glu32.lib sdlmaindebug.lib sdldebug.lib opengl32.lib user32.lib gdi32.lib advapi32.lib dxguid.lib ole32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\..\..\lib\windows\sdl\sdl-1.1.7\lib" /libpath:"..\..\..\..\lib\windows\python\lib" /libpath:"..\..\..\..\lib\windows\openal\lib\lib_release"
+
+!ENDIF
+
+# Begin Target
+
+# Name "GP_sdl - Win32 Release"
+# Name "GP_sdl - Win32 Debug"
+# Name "GP_sdl - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\SDL\main.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\SDL\SDLKeyboardDevice.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\SDL\SDLRenderTools.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\SDL\SDLSystem.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\SDL\SDLCanvas.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\SDL\SDLInputDevice.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\SDL\SDLKeyboardDevice.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\SDL\SDLRenderTools.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\GamePlayer\SDL\SDLSystem.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
+# Begin Source File
+
+SOURCE=..\..\..\..\lib\windows\openal\lib\alc\ALc.obj
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\lib\windows\openal\lib\alu\ALu.obj
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\lib\windows\openal\lib\alut\ALut.obj
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\lib\windows\openal\lib\OpenAL32\alBuffer.obj
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\lib\windows\openal\lib\OpenAL32\alEax.obj
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\lib\windows\openal\lib\OpenAL32\alError.obj
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\lib\windows\openal\lib\OpenAL32\alExtension.obj
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\lib\windows\openal\lib\OpenAL32\alListener.obj
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\lib\windows\openal\lib\OpenAL32\alSource.obj
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\lib\windows\openal\lib\OpenAL32\alState.obj
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\lib\windows\openal\lib\OpenAL32\OpenAL32.obj
+# End Source File
+# End Target
+# End Project
diff --git a/projectfiles/gameengine/ketsji/KX_ketsji.dsp b/projectfiles/gameengine/ketsji/KX_ketsji.dsp
new file mode 100644
index 00000000000..a2016752fd8
--- /dev/null
+++ b/projectfiles/gameengine/ketsji/KX_ketsji.dsp
@@ -0,0 +1,628 @@
+# Microsoft Developer Studio Project File - Name="KX_ketsji" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=KX_ketsji - Win32 Profile
+!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 "KX_ketsji.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 "KX_ketsji.mak" CFG="KX_ketsji - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "KX_ketsji - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "KX_ketsji - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "KX_ketsji - Win32 MT DLL Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "KX_ketsji - Win32 MT DLL Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "KX_ketsji - Win32 Profile" (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)" == "KX_ketsji - 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 "..\..\..\..\obj\windows\gameengine\ketsji"
+# 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 "..\..\..\source\gameengine\physics\common\dummy" /I "..\..\..\lib\windows\python\include\python2.0" /I "..\..\..\lib\windows\string\include" /I "..\..\..\lib\windows\moto\include" /I "..\..\..\source\kernel\gen_system" /I "..\..\..\source\gameengine\soundsystem" /I "..\..\..\source\gameengine\rasterizer" /I "..\..\..\source\gameengine\scenegraph" /I "..\..\..\source\gameengine\gamelogic" /I "..\..\..\source\gameengine\expressions" /I "..\..\..\source\sumo\include" /I "..\..\..\source\sumo\fuzzics\include" /I "..\..\..\source\gameengine\network" /I "..\..\..\source\gameengine\ketsji\kxnetwork" /I "..\..\..\source\gameengine\physics" /I "..\..\..\source\gameengine\physics\common" /I "..\..\..\source\gameengine\physics\dummy" /I "..\..\..\source\gameengine\physics\sumo" /I "..\..\..\source\gameengine\physics\sumo\fuzzics\include" /I "..\..\..\source\gameengine\physics\sumo\include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "EXP_PYTHON_EMBEDDING" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\gameengine\ketsji\KX_ketsji.lib"
+
+!ELSEIF "$(CFG)" == "KX_ketsji - 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 "..\..\..\..\obj\windows\gameengine\ketsji\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 "..\..\..\source\gameengine\physics\common\dummy" /I "..\..\..\lib\windows\python\include\python2.0" /I "..\..\..\lib\windows\string\include" /I "..\..\..\lib\windows\moto\include" /I "..\..\..\source\kernel\gen_system" /I "..\..\..\source\gameengine\soundsystem" /I "..\..\..\source\gameengine\rasterizer" /I "..\..\..\source\gameengine\scenegraph" /I "..\..\..\source\gameengine\gamelogic" /I "..\..\..\source\gameengine\expressions" /I "..\..\..\source\sumo\include" /I "..\..\..\source\sumo\fuzzics\include" /I "..\..\..\source\gameengine\network" /I "..\..\..\source\gameengine\ketsji\kxnetwork" /I "..\..\..\source\gameengine\physics" /I "..\..\..\source\gameengine\physics\common" /I "..\..\..\source\gameengine\physics\dummy" /I "..\..\..\source\gameengine\physics\sumo" /I "..\..\..\source\gameengine\physics\sumo\fuzzics\include" /I "..\..\..\source\gameengine\physics\sumo\include" /D "JANCODEPANCO" /D "WIN32" /D "_MBCS" /D "_LIB" /D "EXP_PYTHON_EMBEDDING" /U "_DEBUG" /YX /J /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\gameengine\ketsji\debug\KX_ketsji.lib"
+
+!ELSEIF "$(CFG)" == "KX_ketsji - Win32 MT DLL Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "KX_ketsji___Win32_MT_DLL_Debug"
+# PROP BASE Intermediate_Dir "KX_ketsji___Win32_MT_DLL_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\..\..\..\obj\windows\gameengine\ketsji\mtdll_debug"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\gameengine\ketsji\mtdll_debug"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /Gm /GX /ZI /Od /I "..\..\..\source\kernel\gen_system" /I "..\..\..\source\gameengine\soundsystem" /I "..\..\..\source\gameengine\rasterizer" /I "..\..\..\source\gameengine\scenegraph" /I "..\..\..\source\gameengine\gamelogic" /I "..\..\..\source\gameengine\expressions" /I "..\..\..\source\sumo\include" /I "..\..\..\source\sumo\fuzzics\include" /I "..\..\..\lib\windows\moto\include" /I "..\..\..\lib\windows\python\include\python1.5" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "EXP_PYTHON_EMBEDDING" /YX /J /FD /GZ /c
+# ADD CPP /nologo /MDd /Gm /GX /ZI /Od /I "..\..\..\source\gameengine\physics\common\dummy" /I "..\..\..\lib\windows\python\include\python2.0" /I "..\..\..\lib\windows\string\include" /I "..\..\..\lib\windows\moto\include" /I "..\..\..\source\kernel\gen_system" /I "..\..\..\source\gameengine\soundsystem" /I "..\..\..\source\gameengine\rasterizer" /I "..\..\..\source\gameengine\scenegraph" /I "..\..\..\source\gameengine\gamelogic" /I "..\..\..\source\gameengine\expressions" /I "..\..\..\source\sumo\include" /I "..\..\..\source\sumo\fuzzics\include" /I "..\..\..\source\gameengine\network" /I "..\..\..\source\gameengine\ketsji\kxnetwork" /I "..\..\..\source\gameengine\physics" /I "..\..\..\source\gameengine\physics\common" /I "..\..\..\source\gameengine\physics\dummy" /I "..\..\..\source\gameengine\physics\sumo" /I "..\..\..\source\gameengine\physics\sumo\fuzzics\include" /I "..\..\..\source\gameengine\physics\sumo\include" /D "WIN32" /D "_MBCS" /D "_LIB" /D "EXP_PYTHON_EMBEDDING" /U "_DEBUG" /YX /J /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 /out:"..\..\..\..\..\obj\windows\gameengine\ketsji\debug\KX_ketsji.lib"
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "KX_ketsji - Win32 MT DLL Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "KX_ketsji___Win32_MT_DLL_Release"
+# PROP BASE Intermediate_Dir "KX_ketsji___Win32_MT_DLL_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\..\..\..\obj\windows\gameengine\ketsji\mtdll"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\gameengine\ketsji\mtdll"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /GX /O2 /I "..\..\..\source\kernel\gen_system" /I "..\..\..\source\gameengine\soundsystem" /I "..\..\..\source\gameengine\rasterizer" /I "..\..\..\source\gameengine\scenegraph" /I "..\..\..\source\gameengine\gamelogic" /I "..\..\..\source\gameengine\expressions" /I "..\..\..\source\sumo\include" /I "..\..\..\source\sumo\fuzzics\include" /I "..\..\..\lib\windows\moto\include" /I "..\..\..\lib\windows\python\include\python2.0" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "EXP_PYTHON_EMBEDDING" /YX /J /FD /c
+# ADD CPP /nologo /MD /GX /O2 /I "..\..\..\source\gameengine\physics\common\dummy" /I "..\..\..\lib\windows\python\include\python2.0" /I "..\..\..\lib\windows\string\include" /I "..\..\..\lib\windows\moto\include" /I "..\..\..\source\kernel\gen_system" /I "..\..\..\source\gameengine\soundsystem" /I "..\..\..\source\gameengine\rasterizer" /I "..\..\..\source\gameengine\scenegraph" /I "..\..\..\source\gameengine\gamelogic" /I "..\..\..\source\gameengine\expressions" /I "..\..\..\source\sumo\include" /I "..\..\..\source\sumo\fuzzics\include" /I "..\..\..\source\gameengine\network" /I "..\..\..\source\gameengine\ketsji\kxnetwork" /I "..\..\..\source\gameengine\physics" /I "..\..\..\source\gameengine\physics\common" /I "..\..\..\source\gameengine\physics\dummy" /I "..\..\..\source\gameengine\physics\sumo" /I "..\..\..\source\gameengine\physics\sumo\fuzzics\include" /I "..\..\..\source\gameengine\physics\sumo\include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "EXP_PYTHON_EMBEDDING" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\..\obj\windows\gameengine\ketsji\KX_ketsji.lib"
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "KX_ketsji - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "KX_ketsji___Win32_Profile"
+# PROP BASE Intermediate_Dir "KX_ketsji___Win32_Profile"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "KX_ketsji___Win32_Profile"
+# PROP Intermediate_Dir "KX_ketsji___Win32_Profile"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\lib\windows\python\include\python1.5" /I "..\..\..\source\kernel\gen_system" /I "..\..\..\source\gameengine\soundsystem" /I "..\..\..\source\gameengine\rasterizer" /I "..\..\..\source\gameengine\scenegraph" /I "..\..\..\source\gameengine\gamelogic" /I "..\..\..\source\gameengine\expressions" /I "..\..\..\source\sumo\include" /I "..\..\..\source\sumo\fuzzics\include" /I "..\..\..\lib\windows\moto\include" /I "..\..\..\source\gameengine\network" /I "..\..\..\source\gameengine\ketsji\kxnetwork" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "EXP_PYTHON_EMBEDDING" /YX /J /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /O2 /I "..\..\..\source\gameengine\physics\dummy" /I "..\..\..\lib\windows\python\include\python2.0" /I "..\..\..\lib\windows\string\include" /I "..\..\..\lib\windows\moto\include" /I "..\..\..\source\kernel\gen_system" /I "..\..\..\source\gameengine\soundsystem" /I "..\..\..\source\gameengine\rasterizer" /I "..\..\..\source\gameengine\scenegraph" /I "..\..\..\source\gameengine\gamelogic" /I "..\..\..\source\gameengine\expressions" /I "..\..\..\source\sumo\include" /I "..\..\..\source\sumo\fuzzics\include" /I "..\..\..\source\gameengine\network" /I "..\..\..\source\gameengine\ketsji\kxnetwork" /I "..\..\..\source\gameengine\physics" /I "..\..\..\source\gameengine\physics\common" /I "..\..\..\source\gameengine\physics\sumo" /I "..\..\..\source\gameengine\physics\sumo\fuzzics\include" /I "..\..\..\source\gameengine\physics\sumo\include" /D "WIN32" /D "_MBCS" /D "_LIB" /D "EXP_PYTHON_EMBEDDING" /U "_DEBUG" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\obj\windows\gameengine\ketsji\debug\KX_ketsji.lib"
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\gameengine\ketsji\profile\KX_ketsji.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "KX_ketsji - Win32 Release"
+# Name "KX_ketsji - Win32 Debug"
+# Name "KX_ketsji - Win32 MT DLL Debug"
+# Name "KX_ketsji - Win32 MT DLL Release"
+# Name "KX_ketsji - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Group "ActuatorsImp"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_CameraActuator.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_CDActuator.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_ConstraintActuator.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_GameActuator.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_IpoActuator.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_ObjectActuator.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_SCA_AddObjectActuator.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_SCA_EndObjectActuator.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_SCA_ReplaceMeshActuator.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_SceneActuator.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_SoundActuator.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_TrackToActuator.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_VisibilityActuator.cpp
+# End Source File
+# End Group
+# Begin Group "SG_ControllersImp"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_CameraIpoSGController.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_IPO_SGController.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_LightIpoSGController.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_ObColorIpoSGController.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_WorldIpoController.cpp
+# End Source File
+# End Group
+# Begin Group "SensorsImp"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_MouseFocusSensor.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_NearSensor.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_RadarSensor.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_RaySensor.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_TouchSensor.cpp
+# End Source File
+# End Group
+# Begin Group "IposImp"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_OrientationInterpolator.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_PositionInterpolator.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_ScalarInterpolator.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_ScalingInterpolator.cpp
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_Camera.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_ConstraintWrapper.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_ConvertPhysicsObjects.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_EmptyObject.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_GameObject.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_IPhysicsController.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_KetsjiEngine.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_Light.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_MeshProxy.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_MotionState.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_MotionState.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_PhysicsObjectWrapper.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_PyConstraintBinding.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_PythonInit.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_RayEventManager.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_Scene.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_SG_NodeRelationships.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_SumoPhysicsController.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_TimeCategoryLogger.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_TimeLogger.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_TouchEventManager.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_VertexProxy.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_WorldInfo.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Group "Actuators"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_CameraActuator.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_CDActuator.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_ConstraintActuator.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_GameActuator.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_IpoActuator.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_ObjectActuator.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_SCA_AddObjectActuator.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_SCA_EndObjectActuator.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_SCA_ReplaceMeshActuator.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_SceneActuator.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_SoundActuator.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_TrackToActuator.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_VisibilityActuator.h
+# End Source File
+# End Group
+# Begin Group "SG_Controllers"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_CameraIpoSGController.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_IPO_SGController.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_LightIpoSGController.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_ObColorIpoSGController.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_PhysicsController.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_WorldIpoController.h
+# End Source File
+# End Group
+# Begin Group "Sensors"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_MouseFocusSensor.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_NearSensor.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_RadarSensor.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_RaySensor.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_TouchSensor.h
+# End Source File
+# End Group
+# Begin Group "Ipos"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_IInterpolator.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_IScalarInterpolator.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_OrientationInterpolator.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_PositionInterpolator.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_ScalarInterpolator.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_ScalingInterpolator.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_Camera.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_ConstraintWrapper.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_ConvertPhysicsObject.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_EmptyObject.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_GameObject.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_IClientObject.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_IPhysicsController.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_IPOTransform.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_ISceneConverter.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_ISystem.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_KetsjiEngine.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_Light.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_MeshProxy.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_OdePhysicsController.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_PhysicsObjectWrapper.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_PyConstraintBinding.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_PythonInit.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_RayEventManager.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_Scene.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_SG_NodeRelationships.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_SumoPhysicsController.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_TimeCategoryLogger.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_TimeLogger.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_TouchEventManager.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_VertexProxy.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Ketsji\KX_WorldInfo.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/gameengine/ketsji/network/KX_network.dsp b/projectfiles/gameengine/ketsji/network/KX_network.dsp
new file mode 100644
index 00000000000..c4fed906988
--- /dev/null
+++ b/projectfiles/gameengine/ketsji/network/KX_network.dsp
@@ -0,0 +1,212 @@
+# Microsoft Developer Studio Project File - Name="KX_network" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=KX_network - Win32 Profile
+!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 "KX_network.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 "KX_network.mak" CFG="KX_network - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "KX_network - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "KX_network - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "KX_network - Win32 MT DLL Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "KX_network - Win32 MT DLL Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "KX_network - Win32 Profile" (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)" == "KX_network - 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 "..\..\..\..\..\obj\windows\gameengine\ketsji\network"
+# 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 "..\..\..\..\lib\windows\python\include\python2.0" /I "..\..\..\..\lib\windows\string\include" /I "..\..\..\..\source\gameengine\ketsji" /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\GameLogic" /I "..\..\..\..\source\gameengine\expressions" /I "..\..\..\..\source\gameengine\Network" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\..\obj\windows\gameengine\ketsji\network\KX_network.lib"
+
+!ELSEIF "$(CFG)" == "KX_network - 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 "..\..\..\..\..\obj\windows\gameengine\ketsji\network\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\python\include\python2.0" /I "..\..\..\..\lib\windows\string\include" /I "..\..\..\..\source\gameengine\ketsji" /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\GameLogic" /I "..\..\..\..\source\gameengine\expressions" /I "..\..\..\..\source\gameengine\Network" /D "WIN32" /D "_MBCS" /D "_LIB" /U "_DEBUG" /YX /J /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\..\obj\windows\gameengine\ketsji\network\debug\KX_network.lib"
+
+!ELSEIF "$(CFG)" == "KX_network - Win32 MT DLL Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "KX_network___Win32_MT_DLL_Debug"
+# PROP BASE Intermediate_Dir "KX_network___Win32_MT_DLL_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\..\..\..\..\obj\windows\gameengine\ketsji\network\mtdll_debug"
+# PROP Intermediate_Dir "..\..\..\..\..\obj\windows\gameengine\ketsji\network\mtdll_debug"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /Gm /GX /ZI /Od /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\GameLogic" /I "..\..\..\..\source\gameengine\expressions" /I "..\..\..\..\source\gameengine\Network" /I "..\..\..\..\lib\windows\python\include\python1.5" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /GZ /c
+# ADD CPP /nologo /MDd /Gm /GX /ZI /Od /I "..\..\..\..\lib\windows\python\include\python2.0" /I "..\..\..\..\lib\windows\string\include" /I "..\..\..\..\source\gameengine\ketsji" /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\GameLogic" /I "..\..\..\..\source\gameengine\expressions" /I "..\..\..\..\source\gameengine\Network" /D "WIN32" /D "_MBCS" /D "_LIB" /U "_DEBUG" /YX /J /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 /out:"..\..\..\..\..\..\obj\windows\gameengine\ketsji\network\debug\KX_network.lib"
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "KX_network - Win32 MT DLL Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "KX_network___Win32_MT_DLL_Release"
+# PROP BASE Intermediate_Dir "KX_network___Win32_MT_DLL_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\..\..\..\..\obj\windows\gameengine\ketsji\network\mtdll"
+# PROP Intermediate_Dir "..\..\..\..\..\obj\windows\gameengine\ketsji\network\mtdll"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /GX /O2 /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\GameLogic" /I "..\..\..\..\source\gameengine\expressions" /I "..\..\..\..\source\gameengine\Network" /I "..\..\..\..\lib\windows\python\include\python2.0" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD CPP /nologo /MD /GX /O2 /I "..\..\..\..\lib\windows\python\include\python2.0" /I "..\..\..\..\lib\windows\string\include" /I "..\..\..\..\source\gameengine\ketsji" /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\GameLogic" /I "..\..\..\..\source\gameengine\expressions" /I "..\..\..\..\source\gameengine\Network" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\..\..\obj\windows\gameengine\ketsji\network\KX_network.lib"
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "KX_network - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "KX_network___Win32_Profile"
+# PROP BASE Intermediate_Dir "KX_network___Win32_Profile"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "KX_network___Win32_Profile"
+# PROP Intermediate_Dir "KX_network___Win32_Profile"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\GameLogic" /I "..\..\..\..\source\gameengine\expressions" /I "..\..\..\..\source\gameengine\Network" /I "..\..\..\..\lib\windows\python\include\python1.5" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /O2 /I "..\..\..\..\lib\windows\python\include\python2.0" /I "..\..\..\..\lib\windows\string\include" /I "..\..\..\..\source\gameengine\ketsji" /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\GameLogic" /I "..\..\..\..\source\gameengine\expressions" /I "..\..\..\..\source\gameengine\Network" /D "WIN32" /D "_MBCS" /D "_LIB" /U "_DEBUG" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\..\obj\windows\gameengine\ketsji\network\debug\KX_network.lib"
+# ADD LIB32 /nologo /out:"..\..\..\..\..\obj\windows\gameengine\ketsji\network\profile\KX_network.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "KX_network - Win32 Release"
+# Name "KX_network - Win32 Debug"
+# Name "KX_network - Win32 MT DLL Debug"
+# Name "KX_network - Win32 MT DLL Release"
+# Name "KX_network - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\Ketsji\KXNetwork\KX_NetworkEventManager.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\Ketsji\KXNetwork\KX_NetworkMessageActuator.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\Ketsji\KXNetwork\KX_NetworkMessageSensor.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\Ketsji\KXNetwork\KX_NetworkObjectActuator.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\Ketsji\KXNetwork\KX_NetworkObjectSensor.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\Ketsji\KXNetwork\KX_NetworkEventManager.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\Ketsji\KXNetwork\KX_NetworkMessageActuator.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\Ketsji\KXNetwork\KX_NetworkMessageSensor.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\Ketsji\KXNetwork\KX_NetworkObjectActuator.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\Ketsji\KXNetwork\KX_NetworkObjectSensor.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/gameengine/network/loopbacknetwork/NG_loopbacknetwork.dsp b/projectfiles/gameengine/network/loopbacknetwork/NG_loopbacknetwork.dsp
new file mode 100644
index 00000000000..317c14d7bed
--- /dev/null
+++ b/projectfiles/gameengine/network/loopbacknetwork/NG_loopbacknetwork.dsp
@@ -0,0 +1,181 @@
+# Microsoft Developer Studio Project File - Name="NG_loopbacknetwork" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=NG_loopbacknetwork - Win32 Profile
+!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 "NG_loopbacknetwork.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 "NG_loopbacknetwork.mak" CFG="NG_loopbacknetwork - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "NG_loopbacknetwork - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "NG_loopbacknetwork - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "NG_loopbacknetwork - Win32 MT DLL Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "NG_loopbacknetwork - Win32 MT DLL Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "NG_loopbacknetwork - Win32 Profile" (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)" == "NG_loopbacknetwork - 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 "..\..\..\..\..\obj\windows\gameengine\network\loopbacknetwork"
+# 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 "..\..\..\..\lib\windows\string\include" /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\Network" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\..\obj\windows\gameengine\network\loopbacknetwork\NG_loopbacknetwork.lib"
+
+!ELSEIF "$(CFG)" == "NG_loopbacknetwork - 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 "..\..\..\..\..\obj\windows\gameengine\network\loopbacknetwork\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\string\include" /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\Network" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /GZ /c
+# SUBTRACT CPP /Fr
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\..\obj\windows\gameengine\network\loopbacknetwork\debug\NG_loopbacknetwork.lib"
+
+!ELSEIF "$(CFG)" == "NG_loopbacknetwork - Win32 MT DLL Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "NG_loopbacknetwork___Win32_MT_DLL_Debug"
+# PROP BASE Intermediate_Dir "NG_loopbacknetwork___Win32_MT_DLL_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\..\..\..\..\obj\windows\gameengine\network\loopbacknetwork\mtdll_debug"
+# PROP Intermediate_Dir "..\..\..\..\..\obj\windows\gameengine\network\loopbacknetwork\mtdll_debug"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /Gm /GX /ZI /Od /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\Network" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /GZ /c
+# ADD CPP /nologo /MDd /Gm /GX /ZI /Od /I "..\..\..\..\lib\windows\string\include" /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\Network" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /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 /out:"..\..\..\..\..\..\obj\windows\gameengine\network\loopbacknetwork\debug\NG_loopbacknetwork.lib"
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "NG_loopbacknetwork - Win32 MT DLL Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "NG_loopbacknetwork___Win32_MT_DLL_Release"
+# PROP BASE Intermediate_Dir "NG_loopbacknetwork___Win32_MT_DLL_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\..\..\..\..\obj\windows\gameengine\network\loopbacknetwork\mtdll"
+# PROP Intermediate_Dir "..\..\..\..\..\obj\windows\gameengine\network\loopbacknetwork\mtdll"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /GX /O2 /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\Network" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD CPP /nologo /MD /GX /O2 /I "..\..\..\..\lib\windows\string\include" /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\Network" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\..\..\obj\windows\gameengine\network\loopbacknetwork\NG_loopbacknetwork.lib"
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "NG_loopbacknetwork - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "NG_loopbacknetwork___Win32_Profile"
+# PROP BASE Intermediate_Dir "NG_loopbacknetwork___Win32_Profile"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "NG_loopbacknetwork___Win32_Profile"
+# PROP Intermediate_Dir "NG_loopbacknetwork___Win32_Profile"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\Network" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /O2 /I "..\..\..\..\lib\windows\string\include" /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\Network" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\..\obj\windows\gameengine\network\loopbacknetwork\debug\NG_loopbacknetwork.lib"
+# ADD LIB32 /nologo /out:"..\..\..\..\..\obj\windows\gameengine\network\loopbacknetwork\profile\NG_loopbacknetwork.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "NG_loopbacknetwork - Win32 Release"
+# Name "NG_loopbacknetwork - Win32 Debug"
+# Name "NG_loopbacknetwork - Win32 MT DLL Debug"
+# Name "NG_loopbacknetwork - Win32 MT DLL Release"
+# Name "NG_loopbacknetwork - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\Network\LoopBackNetwork\NG_LoopBackNetworkDeviceInterface.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\Network\LoopBackNetwork\NG_LoopBackNetworkDeviceInterface.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/gameengine/network/network/NG_network.dsp b/projectfiles/gameengine/network/network/NG_network.dsp
new file mode 100644
index 00000000000..c63316af730
--- /dev/null
+++ b/projectfiles/gameengine/network/network/NG_network.dsp
@@ -0,0 +1,201 @@
+# Microsoft Developer Studio Project File - Name="NG_network" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=NG_network - Win32 Profile
+!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 "NG_network.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 "NG_network.mak" CFG="NG_network - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "NG_network - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "NG_network - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "NG_network - Win32 MT DLL Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "NG_network - Win32 MT DLL Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "NG_network - Win32 Profile" (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)" == "NG_network - 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 "..\..\..\..\..\obj\windows\gameengine\network\network"
+# 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 "..\..\..\..\lib\windows\string\include" /I "..\..\..\..\source\kernel\gen_system" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\..\obj\windows\gameengine\network\network\NG_network.lib"
+
+!ELSEIF "$(CFG)" == "NG_network - 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 "..\..\..\..\..\obj\windows\gameengine\network\network\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\string\include" /I "..\..\..\..\source\kernel\gen_system" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /GZ /c
+# SUBTRACT CPP /Fr
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\..\obj\windows\gameengine\network\network\debug\NG_network.lib"
+
+!ELSEIF "$(CFG)" == "NG_network - Win32 MT DLL Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "NG_network___Win32_MT_DLL_Debug"
+# PROP BASE Intermediate_Dir "NG_network___Win32_MT_DLL_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\..\..\..\..\obj\windows\gameengine\network\network\mtdll_debug"
+# PROP Intermediate_Dir "..\..\..\..\..\obj\windows\gameengine\network\network\mtdll_debug"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /Gm /GX /ZI /Od /I "..\..\..\..\source\kernel\gen_system" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /GZ /c
+# ADD CPP /nologo /MDd /Gm /GX /ZI /Od /I "..\..\..\..\lib\windows\string\include" /I "..\..\..\..\source\kernel\gen_system" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /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 /out:"..\..\..\..\..\..\obj\windows\gameengine\network\network\debug\NG_network.lib"
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "NG_network - Win32 MT DLL Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "NG_network___Win32_MT_DLL_Release"
+# PROP BASE Intermediate_Dir "NG_network___Win32_MT_DLL_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\..\..\..\..\obj\windows\gameengine\network\network\mtdll"
+# PROP Intermediate_Dir "..\..\..\..\..\obj\windows\gameengine\network\network\mtdll"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /GX /O2 /I "..\..\..\..\source\kernel\gen_system" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD CPP /nologo /MD /GX /O2 /I "..\..\..\..\lib\windows\string\include" /I "..\..\..\..\source\kernel\gen_system" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\..\..\obj\windows\gameengine\network\network\NG_network.lib"
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "NG_network - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "NG_network___Win32_Profile"
+# PROP BASE Intermediate_Dir "NG_network___Win32_Profile"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "NG_network___Win32_Profile"
+# PROP Intermediate_Dir "NG_network___Win32_Profile"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\..\source\kernel\gen_system" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /O2 /I "..\..\..\..\lib\windows\string\include" /I "..\..\..\..\source\kernel\gen_system" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\..\obj\windows\gameengine\network\network\debug\NG_network.lib"
+# ADD LIB32 /nologo /out:"..\..\..\..\..\obj\windows\gameengine\network\network\profile\NG_network.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "NG_network - Win32 Release"
+# Name "NG_network - Win32 Debug"
+# Name "NG_network - Win32 MT DLL Debug"
+# Name "NG_network - Win32 MT DLL Release"
+# Name "NG_network - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\Network\NG_NetworkMessage.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\Network\NG_NetworkObject.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\Network\NG_NetworkScene.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\Network\NG_NetworkDeviceInterface.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\Network\NG_NetworkMessage.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\Network\NG_NetworkObject.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\Network\NG_NetworkScene.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/gameengine/network/terraplaynetwork/NG_terraplaynetwork.dsp b/projectfiles/gameengine/network/terraplaynetwork/NG_terraplaynetwork.dsp
new file mode 100644
index 00000000000..818c301f5ae
--- /dev/null
+++ b/projectfiles/gameengine/network/terraplaynetwork/NG_terraplaynetwork.dsp
@@ -0,0 +1,180 @@
+# Microsoft Developer Studio Project File - Name="NG_terraplaynetwork" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=NG_terraplaynetwork - Win32 Profile
+!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 "NG_terraplaynetwork.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 "NG_terraplaynetwork.mak" CFG="NG_terraplaynetwork - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "NG_terraplaynetwork - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "NG_terraplaynetwork - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "NG_terraplaynetwork - Win32 MT DLL Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "NG_terraplaynetwork - Win32 MT DLL Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "NG_terraplaynetwork - Win32 Profile" (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)" == "NG_terraplaynetwork - 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 "..\..\..\..\..\obj\windows\gameengine\network\terraplaynetwork"
+# 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 "..\..\..\..\source\gameengine\network" /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\lib\windows\terraplay\include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\..\obj\windows\gameengine\network\terraplaynetwork\NG_terraplaynetwork.lib"
+
+!ELSEIF "$(CFG)" == "NG_terraplaynetwork - 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 "..\..\..\..\..\obj\windows\gameengine\network\terraplaynetwork\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 "..\..\..\..\source\gameengine\network" /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\lib\windows\terraplay\include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /FR /YX /J /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\..\obj\windows\gameengine\network\terraplaynetwork\debug\NG_terraplaynetwork.lib"
+
+!ELSEIF "$(CFG)" == "NG_terraplaynetwork - Win32 MT DLL Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "NG_terraplaynetwork___Win32_MT_DLL_Debug"
+# PROP BASE Intermediate_Dir "NG_terraplaynetwork___Win32_MT_DLL_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\..\..\..\..\obj\windows\gameengine\network\terraplaynetwork\mtdll_debug"
+# PROP Intermediate_Dir "..\..\..\..\..\obj\windows\gameengine\network\terraplaynetwork\mtdll_debug"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /Gm /GX /ZI /Od /I "..\..\..\..\source\gameengine\network" /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\lib\windows\terraplay\include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /GZ /c
+# ADD CPP /nologo /MDd /Gm /GX /ZI /Od /I "..\..\..\..\source\gameengine\network" /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\lib\windows\terraplay\include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /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 /out:"..\..\..\..\..\..\obj\windows\gameengine\network\terraplaynetwork\debug\NG_terraplaynetwork.lib"
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "NG_terraplaynetwork - Win32 MT DLL Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "NG_terraplaynetwork___Win32_MT_DLL_Release"
+# PROP BASE Intermediate_Dir "NG_terraplaynetwork___Win32_MT_DLL_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\..\..\..\..\obj\windows\gameengine\network\terraplaynetwork\mtdll"
+# PROP Intermediate_Dir "..\..\..\..\..\obj\windows\gameengine\network\terraplaynetwork\mtdll"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /GX /O2 /I "..\..\..\..\source\gameengine\network" /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\lib\windows\terraplay\include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD CPP /nologo /MD /GX /O2 /I "..\..\..\..\source\gameengine\network" /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\lib\windows\terraplay\include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\..\..\obj\windows\gameengine\network\terraplaynetwork\NG_terraplaynetwork.lib"
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "NG_terraplaynetwork - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "NG_terraplaynetwork___Win32_Profile"
+# PROP BASE Intermediate_Dir "NG_terraplaynetwork___Win32_Profile"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "NG_terraplaynetwork___Win32_Profile"
+# PROP Intermediate_Dir "NG_terraplaynetwork___Win32_Profile"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\..\source\gameengine\network" /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\lib\windows\terraplay\include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /O2 /I "..\..\..\..\source\gameengine\network" /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\lib\windows\terraplay\include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\..\obj\windows\gameengine\network\terraplaynetwork\debug\NG_terraplaynetwork.lib"
+# ADD LIB32 /nologo /out:"..\..\..\..\..\obj\windows\gameengine\network\terraplaynetwork\profile\NG_terraplaynetwork.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "NG_terraplaynetwork - Win32 Release"
+# Name "NG_terraplaynetwork - Win32 Debug"
+# Name "NG_terraplaynetwork - Win32 MT DLL Debug"
+# Name "NG_terraplaynetwork - Win32 MT DLL Release"
+# Name "NG_terraplaynetwork - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\Network\TerraplayNetwork\NG_TerraplayNetworkDeviceInterface.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\Network\TerraplayNetwork\NG_TerraplayNetworkDeviceInterface.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/gameengine/physics/PHY_Physics/PHY_Dummy/PHY_Dummy.dsp b/projectfiles/gameengine/physics/PHY_Physics/PHY_Dummy/PHY_Dummy.dsp
new file mode 100644
index 00000000000..f46ea4dffc7
--- /dev/null
+++ b/projectfiles/gameengine/physics/PHY_Physics/PHY_Dummy/PHY_Dummy.dsp
@@ -0,0 +1,102 @@
+# Microsoft Developer Studio Project File - Name="PHY_Dummy" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=PHY_Dummy - 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 "PHY_Dummy.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 "PHY_Dummy.mak" CFG="PHY_Dummy - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "PHY_Dummy - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "PHY_Dummy - 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)" == "PHY_Dummy - 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 /I "../../../../../source/gameengine/physics" /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)" == "PHY_Dummy - 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 "../../../../../source/gameengine/physics/common" /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 "PHY_Dummy - Win32 Release"
+# Name "PHY_Dummy - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\gameengine\Physics\Dummy\DummyPhysicsEnvironment.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\gameengine\Physics\Dummy\DummyPhysicsEnvironment.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/gameengine/physics/PHY_Physics/PHY_Physics.dsp b/projectfiles/gameengine/physics/PHY_Physics/PHY_Physics.dsp
new file mode 100644
index 00000000000..e029a772155
--- /dev/null
+++ b/projectfiles/gameengine/physics/PHY_Physics/PHY_Physics.dsp
@@ -0,0 +1,142 @@
+# Microsoft Developer Studio Project File - Name="PHY_Physics" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=PHY_Physics - 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 "PHY_Physics.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 "PHY_Physics.mak" CFG="PHY_Physics - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "PHY_Physics - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "PHY_Physics - 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)" == "PHY_Physics - 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 /I "common" /I "dummy" /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)" == "PHY_Physics - 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 "common" /I "dummy" /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 "PHY_Physics - Win32 Release"
+# Name "PHY_Physics - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\Physics\common\PHY_IMotionState.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\Physics\common\PHY_IPhysicsController.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\Physics\common\PHY_IPhysicsEnvironment.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\Physics\common\PHY_DynamicTypes.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\Physics\PHY_DynamicTypes.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\Physics\common\PHY_IMotionState.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\Physics\PHY_IMotionState.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\Physics\common\PHY_IPhysicsController.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\Physics\PHY_IPhysicsController.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\Physics\common\PHY_IPhysicsEnvironment.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\Physics\PHY_IPhysicsEnvironment.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\Physics\common\PHY_Pro.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/gameengine/physics/PHY_Physics/PHY_Sumo/PHY_Sumo.dsp b/projectfiles/gameengine/physics/PHY_Physics/PHY_Sumo/PHY_Sumo.dsp
new file mode 100644
index 00000000000..f1e976adbc7
--- /dev/null
+++ b/projectfiles/gameengine/physics/PHY_Physics/PHY_Sumo/PHY_Sumo.dsp
@@ -0,0 +1,150 @@
+# Microsoft Developer Studio Project File - Name="PHY_Sumo" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=PHY_Sumo - 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 "PHY_Sumo.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 "PHY_Sumo.mak" CFG="PHY_Sumo - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "PHY_Sumo - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "PHY_Sumo - 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)" == "PHY_Sumo - 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 /I "../../../../../source/gameengine/physics" /I "../../../../../source/gameengine/physics/sumo" /I "../../../../../source/gameengine/physics/sumo/include" /I "../../../../../source/gameengine/physics/sumo/fuzzics/include" /I "../../../../../lib/windows/Moto/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)" == "PHY_Sumo - 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 "../../../../../source/gameengine/physics" /I "../../../../../source/gameengine/physics/sumo" /I "../../../../../source/gameengine/physics/sumo/include" /I "../../../../../source/gameengine/physics/sumo/fuzzics/include" /I "../../../../../lib/windows/Moto/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 "PHY_Sumo - Win32 Release"
+# Name "PHY_Sumo - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\gameengine\Physics\Sumo\Fuzzics\src\SM_FhObject.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\gameengine\Physics\Sumo\Fuzzics\src\SM_Object.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\gameengine\Physics\Sumo\Fuzzics\src\SM_Scene.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\gameengine\Physics\Sumo\SumoPhysicsController.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\gameengine\Physics\Sumo\SumoPhysicsEnvironment.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\gameengine\Physics\Sumo\Fuzzics\include\SM_Callback.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\gameengine\Physics\Sumo\Fuzzics\include\SM_ClientObjectInfo.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\gameengine\Physics\Sumo\Fuzzics\include\SM_FhObject.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\gameengine\Physics\Sumo\Fuzzics\include\SM_MotionState.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\gameengine\Physics\Sumo\Fuzzics\include\SM_Object.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\gameengine\Physics\Sumo\Fuzzics\include\SM_Props.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\gameengine\Physics\Sumo\Fuzzics\include\SM_Scene.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\gameengine\Physics\Sumo\SumoPhysicsController.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\..\source\gameengine\Physics\Sumo\SumoPhysicsEnvironment.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/gameengine/rasterizer/RAS_rasterizer.dsp b/projectfiles/gameengine/rasterizer/RAS_rasterizer.dsp
new file mode 100644
index 00000000000..34d4e2ee70a
--- /dev/null
+++ b/projectfiles/gameengine/rasterizer/RAS_rasterizer.dsp
@@ -0,0 +1,269 @@
+# Microsoft Developer Studio Project File - Name="RAS_rasterizer" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=RAS_rasterizer - Win32 Profile
+!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 "RAS_rasterizer.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 "RAS_rasterizer.mak" CFG="RAS_rasterizer - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "RAS_rasterizer - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "RAS_rasterizer - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "RAS_rasterizer - Win32 MT DLL Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "RAS_rasterizer - Win32 MT DLL Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "RAS_rasterizer - Win32 Profile" (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)" == "RAS_rasterizer - 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 "..\..\..\..\obj\windows\gameengine\rasterizer"
+# 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 "..\..\..\lib\windows\moto\include\\" /I "..\..\..\lib\windows\string\include" /I "..\..\..\source\kernel\gen_system" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\gameengine\rasterizer\RAS_rasterizer.lib"
+
+!ELSEIF "$(CFG)" == "RAS_rasterizer - 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 "..\..\..\..\obj\windows\gameengine\rasterizer\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\moto\include\\" /I "..\..\..\lib\windows\string\include" /I "..\..\..\source\kernel\gen_system" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /GZ /c
+# SUBTRACT CPP /Fr
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\gameengine\rasterizer\debug\RAS_rasterizer.lib"
+
+!ELSEIF "$(CFG)" == "RAS_rasterizer - Win32 MT DLL Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "RAS_rasterizer___Win32_MT_DLL_Debug"
+# PROP BASE Intermediate_Dir "RAS_rasterizer___Win32_MT_DLL_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\..\..\..\obj\windows\gameengine\rasterizer\mtdll_debug"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\gameengine\rasterizer\mtdll_debug"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /Gm /GX /ZI /Od /I "../../../../lib/windows/moto/include" /I "..\..\..\source\kernel\gen_system" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /GZ /c
+# ADD CPP /nologo /MDd /Gm /GX /ZI /Od /I "../../../lib/windows/moto/include" /I "..\..\..\lib\windows\string\include" /I "..\..\..\source\kernel\gen_system" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /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 /out:"..\..\..\..\..\obj\windows\gameengine\rasterizer\debug\RAS_rasterizer.lib"
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "RAS_rasterizer - Win32 MT DLL Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "RAS_rasterizer___Win32_MT_DLL_Release"
+# PROP BASE Intermediate_Dir "RAS_rasterizer___Win32_MT_DLL_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\..\..\..\obj\windows\gameengine\rasterizer\mtdll"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\gameengine\rasterizer\mtdll"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /GX /O2 /I "../../../../lib/windows/moto/include" /I "..\..\..\source\kernel\gen_system" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD CPP /nologo /MD /GX /O2 /I "../../../lib/windows/moto/include" /I "..\..\..\lib\windows\string\include" /I "..\..\..\source\kernel\gen_system" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\..\obj\windows\gameengine\rasterizer\RAS_rasterizer.lib"
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "RAS_rasterizer - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "RAS_rasterizer___Win32_Profile"
+# PROP BASE Intermediate_Dir "RAS_rasterizer___Win32_Profile"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "RAS_rasterizer___Win32_Profile"
+# PROP Intermediate_Dir "RAS_rasterizer___Win32_Profile"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../../lib/windows/moto/include" /I "..\..\..\source\kernel\gen_system" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /O2 /I "..\..\..\lib\windows\moto\include\\" /I "..\..\..\lib\windows\string\include" /I "..\..\..\source\kernel\gen_system" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\obj\windows\gameengine\rasterizer\debug\RAS_rasterizer.lib"
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\gameengine\rasterizer\profile\RAS_rasterizer.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "RAS_rasterizer - Win32 Release"
+# Name "RAS_rasterizer - Win32 Debug"
+# Name "RAS_rasterizer - Win32 MT DLL Debug"
+# Name "RAS_rasterizer - Win32 MT DLL Release"
+# Name "RAS_rasterizer - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Rasterizer\RAS_BucketManager.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Rasterizer\RAS_FramingManager.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Rasterizer\RAS_IPolygonMaterial.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Rasterizer\RAS_IRenderTools.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Rasterizer\RAS_MaterialBucket.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Rasterizer\RAS_MeshObject.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Rasterizer\RAS_Polygon.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Rasterizer\RAS_texmatrix.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Rasterizer\RAS_TexVert.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Rasterizer\RAS_BucketManager.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Rasterizer\RAS_CameraData.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Rasterizer\RAS_Deformer.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Rasterizer\RAS_FramingManager.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Rasterizer\RAS_ICanvas.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Rasterizer\RAS_IPolygonMaterial.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Rasterizer\RAS_IRasterizer.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Rasterizer\RAS_IRenderTools.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Rasterizer\RAS_LightObject.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Rasterizer\RAS_MaterialBucket.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Rasterizer\RAS_MeshObject.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Rasterizer\RAS_ObjectColor.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Rasterizer\RAS_Polygon.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Rasterizer\RAS_TexMatrix.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\Rasterizer\RAS_TexVert.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/gameengine/rasterizer/openglrasterizer/RAS_openglrasterizer.dsp b/projectfiles/gameengine/rasterizer/openglrasterizer/RAS_openglrasterizer.dsp
new file mode 100644
index 00000000000..c2a3f3c1328
--- /dev/null
+++ b/projectfiles/gameengine/rasterizer/openglrasterizer/RAS_openglrasterizer.dsp
@@ -0,0 +1,197 @@
+# Microsoft Developer Studio Project File - Name="RAS_openglrasterizer" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=RAS_openglrasterizer - Win32 Profile
+!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 "RAS_openglrasterizer.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 "RAS_openglrasterizer.mak" CFG="RAS_openglrasterizer - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "RAS_openglrasterizer - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "RAS_openglrasterizer - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "RAS_openglrasterizer - Win32 MT DLL Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "RAS_openglrasterizer - Win32 MT DLL Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "RAS_openglrasterizer - Win32 Profile" (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)" == "RAS_openglrasterizer - 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 "..\..\..\..\..\obj\windows\gameengine\rasterizer\openglrasterizer"
+# 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 "..\..\..\..\lib\windows\string\include" /I "..\..\..\..\source\kernel\gen_system" /I "../../../../lib/windows/moto/include" /I "..\..\..\..\source\gameengine\Rasterizer" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\..\obj\windows\gameengine\rasterizer\openglrasterizer\RAS_openglrasterizer.lib"
+
+!ELSEIF "$(CFG)" == "RAS_openglrasterizer - 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 "..\..\..\..\..\obj\windows\gameengine\rasterizer\openglrasterizer\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\string\include" /I "..\..\..\..\source\kernel\gen_system" /I "../../../../lib/windows/moto/include" /I "..\..\..\..\source\gameengine\Rasterizer" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /GZ /c
+# SUBTRACT CPP /Fr
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\..\obj\windows\gameengine\rasterizer\openglrasterizer\debug\RAS_openglrasterizer.lib"
+
+!ELSEIF "$(CFG)" == "RAS_openglrasterizer - Win32 MT DLL Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "RAS_openglrasterizer___Win32_MT_DLL_Debug"
+# PROP BASE Intermediate_Dir "RAS_openglrasterizer___Win32_MT_DLL_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\..\..\..\..\obj\windows\gameengine\rasterizer\openglrasterizer\mtdll_debug"
+# PROP Intermediate_Dir "..\..\..\..\..\obj\windows\gameengine\rasterizer\openglrasterizer\mtdll_debug"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /Gm /GX /ZI /Od /I "..\..\..\..\source\kernel\gen_system" /I "../../../../lib/windows/moto/include" /I "..\..\..\..\source\gameengine\Rasterizer" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /GZ /c
+# ADD CPP /nologo /MDd /Gm /GX /ZI /Od /I "..\..\..\..\lib\windows\string\include" /I "..\..\..\..\source\kernel\gen_system" /I "../../../../lib/windows/moto/include" /I "..\..\..\..\source\gameengine\Rasterizer" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /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 /out:"..\..\..\..\..\..\obj\windows\gameengine\rasterizer\openglrasterizer\debug\RAS_openglrasterizer.lib"
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "RAS_openglrasterizer - Win32 MT DLL Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "RAS_openglrasterizer___Win32_MT_DLL_Release"
+# PROP BASE Intermediate_Dir "RAS_openglrasterizer___Win32_MT_DLL_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\..\..\..\..\obj\windows\gameengine\rasterizer\openglrasterizer\mtdll"
+# PROP Intermediate_Dir "..\..\..\..\..\obj\windows\gameengine\rasterizer\openglrasterizer\mtdll"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /GX /O2 /I "..\..\..\..\source\kernel\gen_system" /I ".../../../../lib/windows/moto/include" /I "..\..\..\..\source\gameengine\Rasterizer" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD CPP /nologo /MD /GX /O2 /I "..\..\..\..\lib\windows\string\include" /I "..\..\..\..\source\kernel\gen_system" /I "../../../../lib/windows/moto/include" /I "..\..\..\..\source\gameengine\Rasterizer" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\..\..\obj\windows\gameengine\rasterizer\openglrasterizer\RAS_openglrasterizer.lib"
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "RAS_openglrasterizer - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "RAS_openglrasterizer___Win32_Profile"
+# PROP BASE Intermediate_Dir "RAS_openglrasterizer___Win32_Profile"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "RAS_openglrasterizer___Win32_Profile"
+# PROP Intermediate_Dir "RAS_openglrasterizer___Win32_Profile"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\..\source\kernel\gen_system" /I "../../../../lib/windows/moto/include" /I "..\..\..\..\source\gameengine\Rasterizer" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /O2 /I "..\..\..\..\lib\windows\string\include" /I "..\..\..\..\source\kernel\gen_system" /I "../../../../lib/windows/moto/include" /I "..\..\..\..\source\gameengine\Rasterizer" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\..\obj\windows\gameengine\rasterizer\openglrasterizer\debug\RAS_openglrasterizer.lib"
+# ADD LIB32 /nologo /out:"..\..\..\..\..\obj\windows\gameengine\rasterizer\openglrasterizer\profile\RAS_openglrasterizer.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "RAS_openglrasterizer - Win32 Release"
+# Name "RAS_openglrasterizer - Win32 Debug"
+# Name "RAS_openglrasterizer - Win32 MT DLL Debug"
+# Name "RAS_openglrasterizer - Win32 MT DLL Release"
+# Name "RAS_openglrasterizer - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\Rasterizer\RAS_OpenGLRasterizer\RAS_CheckVertexArrays.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\Rasterizer\RAS_OpenGLRasterizer\RAS_OpenGLRasterizer.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\Rasterizer\RAS_OpenGLRasterizer\RAS_VAOpenGLRasterizer.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\Rasterizer\RAS_OpenGLRasterizer\RAS_CheckVertexArrays.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\Rasterizer\RAS_OpenGLRasterizer\RAS_OpenGLRasterizer.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\Rasterizer\RAS_OpenGLRasterizer\RAS_VAOpenGLRasterizer.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/gameengine/scenegraph/SG_scenegraph.dsp b/projectfiles/gameengine/scenegraph/SG_scenegraph.dsp
new file mode 100644
index 00000000000..6978c86cbdf
--- /dev/null
+++ b/projectfiles/gameengine/scenegraph/SG_scenegraph.dsp
@@ -0,0 +1,209 @@
+# Microsoft Developer Studio Project File - Name="SG_SceneGraph" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=SG_SceneGraph - Win32 Profile
+!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 "SG_SceneGraph.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 "SG_SceneGraph.mak" CFG="SG_SceneGraph - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "SG_SceneGraph - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "SG_SceneGraph - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "SG_SceneGraph - Win32 MT DLL Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "SG_SceneGraph - Win32 MT DLL Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "SG_SceneGraph - Win32 Profile" (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)" == "SG_SceneGraph - 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 "..\..\..\..\obj\windows\gameengine\scenegraph"
+# 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 "../../../lib/windows/moto/include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\gameengine\scenegraph\SG_SceneGraph.lib"
+
+!ELSEIF "$(CFG)" == "SG_SceneGraph - 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 "..\..\..\..\obj\windows\gameengine\scenegraph\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/moto/include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /GZ /c
+# SUBTRACT CPP /Fr
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\gameengine\scenegraph\debug\SG_SceneGraph.lib"
+
+!ELSEIF "$(CFG)" == "SG_SceneGraph - Win32 MT DLL Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "SG_SceneGraph___Win32_MT_DLL_Debug"
+# PROP BASE Intermediate_Dir "SG_SceneGraph___Win32_MT_DLL_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\..\..\..\obj\windows\gameengine\scenegraph\mtdll_debug"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\gameengine\scenegraph\mtdll_debug"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /Gm /GX /ZI /Od /I "../../../../lib/windows/moto/include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /GZ /c
+# ADD CPP /nologo /MDd /Gm /GX /ZI /Od /I "../../../lib/windows/moto/include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /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 /out:"..\..\..\..\..\obj\windows\gameengine\scenegraph\debug\SG_SceneGraph.lib"
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "SG_SceneGraph - Win32 MT DLL Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "SG_SceneGraph___Win32_MT_DLL_Release"
+# PROP BASE Intermediate_Dir "SG_SceneGraph___Win32_MT_DLL_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\..\..\..\obj\windows\gameengine\scenegraph\mtdll"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\gameengine\scenegraph\mtdll"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /GX /O2 /I "../../../../lib/windows/moto/include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD CPP /nologo /MD /GX /O2 /I "../../../lib/windows/moto/include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\..\obj\windows\gameengine\scenegraph\SG_SceneGraph.lib"
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "SG_SceneGraph - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "SG_SceneGraph___Win32_Profile"
+# PROP BASE Intermediate_Dir "SG_SceneGraph___Win32_Profile"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "SG_SceneGraph___Win32_Profile"
+# PROP Intermediate_Dir "SG_SceneGraph___Win32_Profile"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../../lib/windows/moto/include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /O2 /I "../../../lib/windows/moto/include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\obj\windows\gameengine\scenegraph\debug\SG_SceneGraph.lib"
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\gameengine\scenegraph\profile\SG_SceneGraph.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "SG_SceneGraph - Win32 Release"
+# Name "SG_SceneGraph - Win32 Debug"
+# Name "SG_SceneGraph - Win32 MT DLL Debug"
+# Name "SG_SceneGraph - Win32 MT DLL Release"
+# Name "SG_SceneGraph - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\SceneGraph\SG_Controller.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\SceneGraph\SG_IObject.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\SceneGraph\SG_Node.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\SceneGraph\SG_Spatial.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\SceneGraph\SG_Controller.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\SceneGraph\SG_IObject.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\SceneGraph\SG_Node.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\SceneGraph\SG_ParentRelation.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\SceneGraph\SG_Spatial.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/gameengine/sound/SND_sound.dsp b/projectfiles/gameengine/sound/SND_sound.dsp
new file mode 100644
index 00000000000..137fabe825f
--- /dev/null
+++ b/projectfiles/gameengine/sound/SND_sound.dsp
@@ -0,0 +1,277 @@
+# Microsoft Developer Studio Project File - Name="SND_sound" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=SND_sound - Win32 Profile
+!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 "SND_sound.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 "SND_sound.mak" CFG="SND_sound - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "SND_sound - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "SND_sound - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "SND_sound - Win32 MT DLL Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "SND_sound - Win32 MT DLL Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "SND_sound - Win32 Profile" (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)" == "SND_sound - 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 "..\..\..\..\obj\windows\gameengine\soundsystem"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\lib\windows\fmod\include" /I "..\..\..\source\gameengine\soundsystem" /I "..\..\..\source\gameengine\soundsystem\openal" /I "..\..\..\source\gameengine\soundsystem\fmod" /I "..\..\..\source\gameengine\soundsystem\dummy" /I "..\..\..\lib\windows\string\include" /I "../../../lib/windows/moto/include" /I "..\..\..\source\kernel\gen_system" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\gameengine\soundsystem\SND_sound.lib"
+
+!ELSEIF "$(CFG)" == "SND_sound - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "SND_sound___Win32_Debug"
+# PROP BASE Intermediate_Dir "SND_sound___Win32_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\gameengine\soundsystem\debug"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "..\..\..\source\blender\include" /I "..\..\..\lib\windows\fmod\include" /I "..\..\..\source\gameengine\soundsystem" /I "..\..\..\source\gameengine\soundsystem\openal" /I "..\..\..\source\gameengine\soundsystem\fmod" /I "..\..\..\source\gameengine\soundsystem\dummy" /I "..\..\..\lib\windows\string\include" /I "../../../lib/windows/moto/include" /I "..\..\..\source\kernel\gen_system" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# SUBTRACT CPP /Fr
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\gameengine\soundsystem\debug\SND_sound.lib"
+
+!ELSEIF "$(CFG)" == "SND_sound - Win32 MT DLL Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "SND_sound___Win32_MT_DLL_Debug"
+# PROP BASE Intermediate_Dir "SND_sound___Win32_MT_DLL_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\..\..\..\obj\windows\gameengine\soundsystem\mtdll_debug"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\gameengine\soundsystem\mtdll_debug"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /Gm /GX /ZI /Od /I "..\..\..\source\gameengine\soundsystem\snd_openal" /I "../../../../lib/windows/moto/include" /I "..\..\..\source\kernel\gen_system" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /GZ /c
+# ADD CPP /nologo /MDd /Gm /GX /ZI /Od /I "..\..\..\lib\windows\fmod\include" /I "..\..\..\source\gameengine\soundsystem" /I "..\..\..\source\gameengine\soundsystem\openal" /I "..\..\..\source\gameengine\soundsystem\fmod" /I "..\..\..\source\gameengine\soundsystem\dummy" /I "..\..\..\lib\windows\string\include" /I "../../../lib/windows/moto/include" /I "..\..\..\source\kernel\gen_system" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /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 /out:"..\..\..\..\..\obj\windows\gameengine\soundsystem\debug\SND_sound.lib"
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "SND_sound - Win32 MT DLL Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "SND_sound___Win32_MT_DLL_Release"
+# PROP BASE Intermediate_Dir "SND_sound___Win32_MT_DLL_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\..\..\..\obj\windows\gameengine\soundsystem\mtdll"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\gameengine\soundsystem\mtdll"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /GX /O2 /I "../../../../lib/windows/moto/include" /I "..\..\..\source\kernel\gen_system" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD CPP /nologo /MD /GX /O2 /I "..\..\..\lib\windows\fmod\include" /I "..\..\..\source\gameengine\soundsystem" /I "..\..\..\source\gameengine\soundsystem\openal" /I "..\..\..\source\gameengine\soundsystem\fmod" /I "..\..\..\source\gameengine\soundsystem\dummy" /I "..\..\..\lib\windows\string\include" /I "../../../lib/windows/moto/include" /I "..\..\..\source\kernel\gen_system" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\..\obj\windows\gameengine\soundsystem\SND_sound.lib"
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "SND_sound - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "SND_sound___Win32_Profile"
+# PROP BASE Intermediate_Dir "SND_sound___Win32_Profile"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "SND_sound___Win32_Profile"
+# PROP Intermediate_Dir "SND_sound___Win32_Profile"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /O2 /I "../../../../lib/windows/moto/include" /I "..\..\..\source\kernel\gen_system" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /O2 /I "..\..\..\lib\windows\fmod\include" /I "..\..\..\source\gameengine\soundsystem" /I "..\..\..\source\gameengine\soundsystem\openal" /I "..\..\..\source\gameengine\soundsystem\fmod" /I "..\..\..\source\gameengine\soundsystem\dummy" /I "..\..\..\lib\windows\string\include" /I "../../../lib/windows/moto/include" /I "..\..\..\source\kernel\gen_system" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\obj\windows\gameengine\soundsystem\debug\SND_sound.lib"
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\gameengine\soundsystem\profile\SND_sound.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "SND_sound - Win32 Release"
+# Name "SND_sound - Win32 Debug"
+# Name "SND_sound - Win32 MT DLL Debug"
+# Name "SND_sound - Win32 MT DLL Release"
+# Name "SND_sound - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\SoundSystem\intern\SND_AudioDevice.cpp
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\gameengine\SoundSystem\intern\SND_C-api.cpp"
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\SoundSystem\intern\SND_CDObject.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\SoundSystem\intern\SND_DeviceManager.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\SoundSystem\intern\SND_IdObject.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\SoundSystem\intern\SND_Scene.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\SoundSystem\intern\SND_SoundListener.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\SoundSystem\intern\SND_SoundObject.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\SoundSystem\intern\SND_Utils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\SoundSystem\intern\SND_WaveCache.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\SoundSystem\intern\SND_WaveSlot.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\SoundSystem\intern\SND_AudioDevice.h
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\gameengine\SoundSystem\SND_C-api.h"
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\SoundSystem\SND_CDObject.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\SoundSystem\SND_DependKludge.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\SoundSystem\SND_DeviceManager.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\SoundSystem\SND_IAudioDevice.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\SoundSystem\intern\SND_IdObject.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\SoundSystem\SND_Object.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\SoundSystem\SND_Scene.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\SoundSystem\SND_SoundListener.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\SoundSystem\SND_SoundObject.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\SoundSystem\SND_Utils.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\SoundSystem\SND_WaveCache.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\SoundSystem\SND_WaveSlot.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\gameengine\SoundSystem\SoundDefines.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/gameengine/sound/dummy/SND_Dummy.dsp b/projectfiles/gameengine/sound/dummy/SND_Dummy.dsp
new file mode 100644
index 00000000000..918397865e0
--- /dev/null
+++ b/projectfiles/gameengine/sound/dummy/SND_Dummy.dsp
@@ -0,0 +1,181 @@
+# Microsoft Developer Studio Project File - Name="SND_Dummy" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=SND_Dummy - Win32 Profile
+!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 "SND_Dummy.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 "SND_Dummy.mak" CFG="SND_Dummy - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "SND_Dummy - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "SND_Dummy - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "SND_Dummy - Win32 MT DLL Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "SND_Dummy - Win32 MT DLL Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "SND_Dummy - Win32 Profile" (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)" == "SND_Dummy - 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 "..\..\..\..\..\obj\windows\gameengine\soundsystem\dummy"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\lib\windows\string\include" /I "..\..\..\..\source\gameengine\soundsystem\intern" /I "..\..\..\..\source\gameengine\soundsystem" /I "..\..\..\..\lib\windows\string\include" /I "../../../../lib/windows/moto/include" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\..\obj\windows\gameengine\soundsystem\dummy\SND_Dummy.lib"
+
+!ELSEIF "$(CFG)" == "SND_Dummy - 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 "..\..\..\..\..\obj\windows\gameengine\soundsystem\dummy\debug"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\lib\windows\string\include" /I "..\..\..\..\source\gameengine\soundsystem" /I "..\..\..\..\source\gameengine\soundsystem\intern" /I "..\..\..\..\lib\windows\string\include" /I "../../../../lib/windows/moto/include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# SUBTRACT CPP /Fr
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\..\obj\windows\gameengine\soundsystem\dummy\debug\SND_Dummy.lib"
+
+!ELSEIF "$(CFG)" == "SND_Dummy - Win32 MT DLL Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "SND_Dummy___Win32_MT_DLL_Debug"
+# PROP BASE Intermediate_Dir "SND_Dummy___Win32_MT_DLL_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\..\..\..\..\obj\windows\gameengine\soundsystem\dummy\mtdll_debug"
+# PROP Intermediate_Dir "..\..\..\..\..\obj\windows\gameengine\soundsystem\dummy\mtdll_debug"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /Gm /GX /ZI /Od /I "..\..\..\..\source\gameengine\soundsystem" /I "../../../../lib/windows/moto/include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /J /FD /GZ /c
+# ADD CPP /nologo /MDd /Gm /GX /ZI /Od /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\lib\windows\string\include" /I "..\..\..\..\source\gameengine\soundsystem" /I "..\..\..\..\source\gameengine\soundsystem\intern" /I "..\..\..\..\lib\windows\string\include" /I "../../../../lib/windows/moto/include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /J /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 /out:"..\..\..\..\..\..\obj\windows\gameengine\soundsystem\dummy\debug\SND_Dummy.lib"
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "SND_Dummy - Win32 MT DLL Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "SND_Dummy___Win32_MT_DLL_Release"
+# PROP BASE Intermediate_Dir "SND_Dummy___Win32_MT_DLL_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\..\..\..\..\obj\windows\gameengine\soundsystem\dummy\mtdll"
+# PROP Intermediate_Dir "..\..\..\..\..\obj\windows\gameengine\soundsystem\dummy\mtdll"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /GX /O2 /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\soundsystem" /I "../../../../lib/windows/moto/include" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD CPP /nologo /MD /GX /O2 /I "..\..\..\lib\windows\string\include" /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\soundsystem" /I "..\..\..\..\source\gameengine\soundsystem\intern" /I "..\..\..\..\lib\windows\string\include" /I "../../../../lib/windows/moto/include" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\..\..\obj\windows\gameengine\soundsystem\dummy\SND_Dummy.lib"
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "SND_Dummy - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "SND_Dummy___Win32_Profile"
+# PROP BASE Intermediate_Dir "SND_Dummy___Win32_Profile"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "SND_Dummy___Win32_Profile"
+# PROP Intermediate_Dir "SND_Dummy___Win32_Profile"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /O2 /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\soundsystem" /I "../../../../lib/windows/moto/include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /O2 /I "..\..\..\lib\windows\string\include" /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\soundsystem" /I "..\..\..\..\source\gameengine\soundsystem\intern" /I "..\..\..\..\lib\windows\string\include" /I "../../../../lib/windows/moto/include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\..\obj\windows\gameengine\soundsystem\dummy\debug\SND_Dummy.lib"
+# ADD LIB32 /nologo /out:"..\..\..\..\..\obj\windows\gameengine\soundsystem\dummy\profile\SND_Dummy.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "SND_Dummy - Win32 Release"
+# Name "SND_Dummy - Win32 Debug"
+# Name "SND_Dummy - Win32 MT DLL Debug"
+# Name "SND_Dummy - Win32 MT DLL Release"
+# Name "SND_Dummy - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\SoundSystem\dummy\SND_DummyDevice.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\SoundSystem\dummy\SND_DummyDevice.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/gameengine/sound/fmod/SND_fmod.dsp b/projectfiles/gameengine/sound/fmod/SND_fmod.dsp
new file mode 100644
index 00000000000..850e1a3c5ca
--- /dev/null
+++ b/projectfiles/gameengine/sound/fmod/SND_fmod.dsp
@@ -0,0 +1,155 @@
+# Microsoft Developer Studio Project File - Name="SND_fmod" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=SND_fmod - 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 "SND_fmod.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 "SND_fmod.mak" CFG="SND_fmod - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "SND_fmod - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "SND_fmod - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "SND_fmod - Win32 MT DLL Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "SND_fmod - Win32 MT DLL Release" (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)" == "SND_fmod - 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 "..\..\..\..\..\obj\windows\gameengine\soundsystem\fmod"
+# 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 "../../../../source/gameengine/soundsystem/intern" /I "../../../../source/gameengine/soundsystem" /I "..\..\..\..\lib\windows\fmod\include" /I "../../../../lib/windows/moto/include" /I "..\..\..\..\lib\windows\string\include" /I "..\..\..\..\source\kernel\gen_system" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD BASE RSC /l 0x413 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\..\obj\windows\gameengine\soundsystem\fmod\SND_fmod.lib"
+
+!ELSEIF "$(CFG)" == "SND_fmod - 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 "..\..\..\..\..\obj\windows\gameengine\soundsystem\fmod\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 "..\..\..\..\source\gameengine\soundsystem" /I "../../../../source/gameengine/soundsystem/intern" /I "../../../../source/gameengine/soundsystem" /I "../../../../lib/windows/moto/include" /I "..\..\..\..\lib\windows\fmod\include" /I "..\..\..\..\lib\windows\string\include" /I "..\..\..\..\source\kernel\gen_system" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# SUBTRACT CPP /Fr
+# ADD BASE RSC /l 0x413 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\..\obj\windows\gameengine\soundsystem\fmod\debug\SND_fmod.lib"
+
+!ELSEIF "$(CFG)" == "SND_fmod - Win32 MT DLL Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "SND_fmod___Win32_MT_DLL_Debug"
+# PROP BASE Intermediate_Dir "SND_fmod___Win32_MT_DLL_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\..\..\..\..\obj\windows\gameengine\soundsystem\fmod\mtdll\debug"
+# PROP Intermediate_Dir "..\..\..\..\..\obj\windows\gameengine\soundsystem\fmod\mtdll\debug"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../../lib/windows/moto/include" /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\soundsystem" /I "..\..\..\..\lib\windows\fmod\340\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\..\source\gameengine\soundsystem" /I "../../../../source/gameengine/soundsystem/intern" /I "../../../../source/gameengine/soundsystem" /I "../../../../lib/windows/moto/include" /I "..\..\..\..\lib\windows\fmod\include" /I "..\..\..\..\lib\windows\string\include" /I "..\..\..\..\source\kernel\gen_system" /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 /out:"..\..\..\..\..\obj\windows\gameengine\soundsystem\fmod\debug\SND_fmod.lib"
+# ADD LIB32 /nologo /out:"..\..\..\..\..\obj\windows\gameengine\soundsystem\fmod\debug\SND_fmod.lib"
+
+!ELSEIF "$(CFG)" == "SND_fmod - Win32 MT DLL Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "SND_fmod___Win32_MT_DLL_Release"
+# PROP BASE Intermediate_Dir "SND_fmod___Win32_MT_DLL_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\..\..\..\..\obj\windows\gameengine\soundsystem\fmod\mtdll"
+# PROP Intermediate_Dir "..\..\..\..\..\obj\windows\gameengine\soundsystem\fmod\mtdll"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /GX /O2 /I "../../../../lib/windows/moto/include" /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\soundsystem" /I "..\..\..\..\lib\windows\fmod\340\include" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\..\..\source\gameengine\soundsystem" /I "../../../../source/gameengine/soundsystem/intern" /I "../../../../source/gameengine/soundsystem" /I "../../../../lib/windows/moto/include" /I "..\..\..\..\lib\windows\fmod\include" /I "..\..\..\..\lib\windows\string\include" /I "..\..\..\..\source\kernel\gen_system" /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 /out:"..\..\..\..\..\obj\windows\gameengine\soundsystem\fmod\SND_fmod.lib"
+# ADD LIB32 /nologo /out:"..\..\..\..\..\obj\windows\gameengine\soundsystem\fmod\SND_fmod.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "SND_fmod - Win32 Release"
+# Name "SND_fmod - Win32 Debug"
+# Name "SND_fmod - Win32 MT DLL Debug"
+# Name "SND_fmod - Win32 MT DLL Release"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\SoundSystem\fmod\SND_FmodDevice.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\SoundSystem\fmod\SND_FmodDevice.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/gameengine/sound/openal/SND_openal.dsp b/projectfiles/gameengine/sound/openal/SND_openal.dsp
new file mode 100644
index 00000000000..f28201bb3c2
--- /dev/null
+++ b/projectfiles/gameengine/sound/openal/SND_openal.dsp
@@ -0,0 +1,181 @@
+# Microsoft Developer Studio Project File - Name="SND_openal" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=SND_openal - Win32 Profile
+!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 "SND_openal.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 "SND_openal.mak" CFG="SND_openal - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "SND_openal - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "SND_openal - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "SND_openal - Win32 MT DLL Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "SND_openal - Win32 MT DLL Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "SND_openal - Win32 Profile" (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)" == "SND_openal - 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 "..\..\..\..\..\obj\windows\gameengine\soundsystem\openal"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "../../../../source/gameengine/soundsystem/intern" /I "../../../../source/gameengine/soundsystem" /I "..\..\..\..\lib\windows\string\include" /I "../../../../lib/windows/moto/include" /I "..\..\..\..\lib\windows\openal\include" /I "..\..\..\..\source\kernel\gen_system" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\..\obj\windows\gameengine\soundsystem\openal\SND_openal.lib"
+
+!ELSEIF "$(CFG)" == "SND_openal - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "SND_openal___Win32_Debug"
+# PROP BASE Intermediate_Dir "SND_openal___Win32_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "..\..\..\..\..\obj\windows\gameengine\soundsystem\openal\debug"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "..\..\..\..\source\gameengine\soundsystem" /I "../../../../source/gameengine/soundsystem/intern" /I "../../../../source/gameengine/soundsystem" /I "..\..\..\..\lib\windows\string\include" /I "../../../../lib/windows/moto/include" /I "..\..\..\..\lib\windows\openal\include" /I "..\..\..\..\source\kernel\gen_system" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# SUBTRACT CPP /Fr
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\..\obj\windows\gameengine\soundsystem\openal\debug\SND_openal.lib"
+
+!ELSEIF "$(CFG)" == "SND_openal - Win32 MT DLL Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "SND_openal___Win32_MT_DLL_Debug"
+# PROP BASE Intermediate_Dir "SND_openal___Win32_MT_DLL_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\..\..\..\..\obj\windows\gameengine\soundsystem\openal\mtdll_debug"
+# PROP Intermediate_Dir "..\..\..\..\..\obj\windows\gameengine\soundsystem\openal\mtdll_debug"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /Gm /GX /ZI /Od /I "../../../../lib/windows/moto/include" /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\soundsystem" /I "..\..\..\..\lib\windows\openal\include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /GZ /c
+# ADD CPP /nologo /MDd /Gm /GX /ZI /Od /I "..\..\..\..\source\gameengine\soundsystem" /I "../../../../source/gameengine/soundsystem/intern" /I "../../../../source/gameengine/soundsystem" /I "..\..\..\..\lib\windows\string\include" /I "../../../../lib/windows/moto/include" /I "..\..\..\..\lib\windows\openal\include" /I "..\..\..\..\source\kernel\gen_system" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /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 /out:"..\..\..\..\..\..\obj\windows\gameengine\soundsystem\openal\debug\SND_openal.lib"
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "SND_openal - Win32 MT DLL Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "SND_openal___Win32_MT_DLL_Release"
+# PROP BASE Intermediate_Dir "SND_openal___Win32_MT_DLL_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\..\..\..\..\obj\windows\gameengine\soundsystem\openal\mtdll"
+# PROP Intermediate_Dir "..\..\..\..\..\obj\windows\gameengine\soundsystem\openal\mtdll"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /GX /O2 /I "../../../../lib/windows/moto/include" /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\soundsystem" /I "..\..\..\..\lib\windows\openal\include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD CPP /nologo /MD /GX /O2 /I "..\..\..\..\source\gameengine\soundsystem" /I "../../../../source/gameengine/soundsystem/intern" /I "../../../../source/gameengine/soundsystem" /I "..\..\..\..\lib\windows\string\include" /I "../../../../lib/windows/moto/include" /I "..\..\..\..\lib\windows\openal\include" /I "..\..\..\..\source\kernel\gen_system" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\..\..\obj\windows\gameengine\soundsystem\openal\SND_openal.lib"
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "SND_openal - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "SND_openal___Win32_Profile"
+# PROP BASE Intermediate_Dir "SND_openal___Win32_Profile"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "SND_openal___Win32_Profile"
+# PROP Intermediate_Dir "SND_openal___Win32_Profile"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /O2 /I "../../../../lib/windows/moto/include" /I "..\..\..\..\source\kernel\gen_system" /I "..\..\..\..\source\gameengine\soundsystem" /I "..\..\..\..\lib\windows\openal\include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /O2 /I "..\..\..\..\source\gameengine\soundsystem" /I "../../../../source/gameengine/soundsystem/intern" /I "../../../../source/gameengine/soundsystem" /I "..\..\..\..\lib\windows\string\include" /I "../../../../lib/windows/moto/include" /I "..\..\..\..\lib\windows\openal\include" /I "..\..\..\..\source\kernel\gen_system" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\..\obj\windows\gameengine\soundsystem\openal\debug\SND_openal.lib"
+# ADD LIB32 /nologo /out:"..\..\..\..\..\obj\windows\gameengine\soundsystem\openal\profile\SND_openal.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "SND_openal - Win32 Release"
+# Name "SND_openal - Win32 Debug"
+# Name "SND_openal - Win32 MT DLL Debug"
+# Name "SND_openal - Win32 MT DLL Release"
+# Name "SND_openal - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\SoundSystem\openal\SND_OpenALDevice.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\..\..\source\gameengine\SoundSystem\openal\SND_OpenALDevice.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/kernel/gen_messaging/gen_messaging.dsp b/projectfiles/kernel/gen_messaging/gen_messaging.dsp
new file mode 100644
index 00000000000..000a867e3d0
--- /dev/null
+++ b/projectfiles/kernel/gen_messaging/gen_messaging.dsp
@@ -0,0 +1,181 @@
+# Microsoft Developer Studio Project File - Name="gen_messaging" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=gen_messaging - Win32 Profile
+!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 "gen_messaging.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 "gen_messaging.mak" CFG="gen_messaging - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "gen_messaging - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "gen_messaging - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "gen_messaging - Win32 MT DLL Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "gen_messaging - Win32 MT DLL Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "gen_messaging - Win32 Profile" (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)" == "gen_messaging - 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\kernel\gen_messaging"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\kernel\gen_messaging"
+# 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 "..\..\..\source\kernel\gen_messaging" /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)" == "gen_messaging - 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\kernel\gen_messaging\debug"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\kernel\gen_messaging\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 "..\..\..\source\kernel\gen_messaging" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# SUBTRACT CPP /Fr
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "gen_messaging - Win32 MT DLL Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "gen_messaging___Win32_MT_DLL_Release"
+# PROP BASE Intermediate_Dir "gen_messaging___Win32_MT_DLL_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\..\..\..\obj\windows\kernel\gen_messaging\mtdll"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\kernel\gen_messaging\mtdll"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /GX /O2 /I "..\..\..\source\kernel\gen_messaging" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\..\source\kernel\gen_messaging" /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)" == "gen_messaging - Win32 MT DLL Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "gen_messaging___Win32_MT_DLL_Debug"
+# PROP BASE Intermediate_Dir "gen_messaging___Win32_MT_DLL_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\..\..\..\obj\windows\kernel\gen_messaging\mtdll_debug"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\kernel\gen_messaging\mtdll_debug"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\source\kernel\gen_messaging" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\source\kernel\gen_messaging" /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
+
+!ELSEIF "$(CFG)" == "gen_messaging - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "gen_messaging___Win32_Profile"
+# PROP BASE Intermediate_Dir "gen_messaging___Win32_Profile"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "gen_messaging___Win32_Profile"
+# PROP Intermediate_Dir "gen_messaging___Win32_Profile"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\source\kernel\gen_messaging" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FR /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /I "..\..\..\source\kernel\gen_messaging" /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 "gen_messaging - Win32 Release"
+# Name "gen_messaging - Win32 Debug"
+# Name "gen_messaging - Win32 MT DLL Release"
+# Name "gen_messaging - Win32 MT DLL Debug"
+# Name "gen_messaging - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\source\kernel\gen_messaging\intern\messaging.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\..\source\kernel\gen_messaging\GEN_messaging.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/kernel/system/SYS_system.dsp b/projectfiles/kernel/system/SYS_system.dsp
new file mode 100644
index 00000000000..d05cd8498a0
--- /dev/null
+++ b/projectfiles/kernel/system/SYS_system.dsp
@@ -0,0 +1,209 @@
+# Microsoft Developer Studio Project File - Name="SYS_system" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=SYS_system - Win32 Profile
+!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 "SYS_system.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 "SYS_system.mak" CFG="SYS_system - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "SYS_system - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "SYS_system - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "SYS_system - Win32 MT DLL Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "SYS_system - Win32 MT DLL Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "SYS_system - Win32 Profile" (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)" == "SYS_system - 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 "..\..\..\..\obj\windows\gameengine\kernel\gen_system"
+# 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 "..\..\..\lib\windows\string\include" /I "../../../../lib/windows/moto/include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\gameengine\kernel\gen_system\SYS_system.lib"
+
+!ELSEIF "$(CFG)" == "SYS_system - 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 "..\..\..\..\obj\windows\gameengine\kernel\gen_system\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\string\include" /I "../../../../lib/windows/moto/include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /GZ /c
+# SUBTRACT CPP /Fr
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\gameengine\kernel\gen_system\debug\SYS_system.lib"
+
+!ELSEIF "$(CFG)" == "SYS_system - Win32 MT DLL Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "SYS_system___Win32_MT_DLL_Debug"
+# PROP BASE Intermediate_Dir "SYS_system___Win32_MT_DLL_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\..\..\..\obj\windows\gameengine\kernel\gen_system\mtdll_debug"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\gameengine\kernel\gen_system\mtdll_debug"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /MDd /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /GZ /c
+# ADD CPP /nologo /MDd /Gm /GX /ZI /Od /I "..\..\..\lib\windows\string\include" /I "../../../../lib/windows/moto/include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /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 /out:"..\..\..\..\..\obj\windows\gameengine\kernel\gen_system\debug\SYS_system.lib"
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "SYS_system - Win32 MT DLL Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "SYS_system___Win32_MT_DLL_Release"
+# PROP BASE Intermediate_Dir "SYS_system___Win32_MT_DLL_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\..\..\..\obj\windows\gameengine\kernel\gen_system\mtdll"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\gameengine\kernel\gen_system\mtdll"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /GX /O2 /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD CPP /nologo /MD /GX /O2 /I "..\..\..\lib\windows\string\include" /I "../../../../lib/windows/moto/include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\..\obj\windows\gameengine\kernel\gen_system\SYS_system.lib"
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "SYS_system - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "SYS_system___Win32_Profile"
+# PROP BASE Intermediate_Dir "SYS_system___Win32_Profile"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "SYS_system___Win32_Profile"
+# PROP Intermediate_Dir "SYS_system___Win32_Profile"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /O2 /I "..\..\..\lib\windows\string\include" /I "../../../../lib/windows/moto/include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\obj\windows\gameengine\kernel\gen_system\debug\SYS_system.lib"
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\gameengine\kernel\gen_system\profileg\SYS_system.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "SYS_system - Win32 Release"
+# Name "SYS_system - Win32 Debug"
+# Name "SYS_system - Win32 MT DLL Debug"
+# Name "SYS_system - Win32 MT DLL Release"
+# Name "SYS_system - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\source\kernel\gen_system\GEN_HashedPtr.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\kernel\gen_system\SYS_SingletonSystem.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\kernel\gen_system\SYS_System.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\..\source\kernel\gen_system\GEN_DataCache.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\kernel\gen_system\GEN_HashedPtr.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\kernel\gen_system\GEN_Map.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\kernel\gen_system\GEN_SmartPtr.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\kernel\gen_system\SYS_SingletonSystem.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\kernel\gen_system\SYS_System.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/sumo/fuzzics/SM_fuzzics.dsp b/projectfiles/sumo/fuzzics/SM_fuzzics.dsp
new file mode 100644
index 00000000000..d732cb87fed
--- /dev/null
+++ b/projectfiles/sumo/fuzzics/SM_fuzzics.dsp
@@ -0,0 +1,209 @@
+# Microsoft Developer Studio Project File - Name="SM_fuzzics" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=SM_fuzzics - Win32 Profile
+!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 "SM_fuzzics.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 "SM_fuzzics.mak" CFG="SM_fuzzics - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "SM_fuzzics - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "SM_fuzzics - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "SM_fuzzics - Win32 MT DLL Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "SM_fuzzics - Win32 MT DLL Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "SM_fuzzics - Win32 Profile" (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)" == "SM_fuzzics - 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 "..\..\..\..\obj\windows\sumo\fuzzics"
+# 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 "..\..\..\source\sumo\Fuzzics\include" /I "../../../lib/windows/moto/include" /I "..\..\..\source\sumo\include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\sumo\fuzzics\SM_fuzzics.lib"
+
+!ELSEIF "$(CFG)" == "SM_fuzzics - 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 "..\..\..\..\obj\windows\sumo\fuzzics\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 "..\..\..\source\sumo\Fuzzics\include" /I "../../../lib/windows/moto/include" /I "..\..\..\source\sumo\include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /GZ /c
+# SUBTRACT CPP /Fr
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\sumo\fuzzics\debug\SM_fuzzics.lib"
+
+!ELSEIF "$(CFG)" == "SM_fuzzics - Win32 MT DLL Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "SM_fuzzics___Win32_MT_DLL_Debug"
+# PROP BASE Intermediate_Dir "SM_fuzzics___Win32_MT_DLL_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\..\..\..\obj\windows\sumo\fuzzics\mtdll_debug"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\sumo\fuzzics\mtdll_debug"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /Gm /GX /ZI /Od /I "..\..\..\source\sumo\Fuzzics\include" /I "../../../../lib/windows/moto/include" /I "..\..\..\source\sumo\include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /GZ /c
+# ADD CPP /nologo /MDd /Gm /GX /ZI /Od /I "..\..\..\source\sumo\Fuzzics\include" /I "../../../lib/windows/moto/include" /I "..\..\..\source\sumo\include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /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 /out:"..\..\..\..\..\obj\windows\sumo\fuzzics\debug\SM_fuzzics.lib"
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "SM_fuzzics - Win32 MT DLL Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "SM_fuzzics___Win32_MT_DLL_Release"
+# PROP BASE Intermediate_Dir "SM_fuzzics___Win32_MT_DLL_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\..\..\..\obj\windows\sumo\fuzzics\mtdll"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\sumo\fuzzics\mtdll"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /GX /O2 /I "..\..\..\source\sumo\Fuzzics\include" /I "../../../../lib/windows/moto/include" /I "..\..\..\source\sumo\include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD CPP /nologo /MD /GX /O2 /I "..\..\..\source\sumo\Fuzzics\include" /I "../../../lib/windows/moto/include" /I "..\..\..\source\sumo\include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\..\obj\windows\sumo\fuzzics\SM_fuzzics.lib"
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "SM_fuzzics - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "SM_fuzzics___Win32_Profile"
+# PROP BASE Intermediate_Dir "SM_fuzzics___Win32_Profile"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "SM_fuzzics___Win32_Profile"
+# PROP Intermediate_Dir "SM_fuzzics___Win32_Profile"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\source\sumo\Fuzzics\include" /I "../../../../lib/windows/moto/include" /I "..\..\..\source\sumo\include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /O2 /I "..\..\..\source\sumo\Fuzzics\include" /I "../../../lib/windows/moto/include" /I "..\..\..\source\sumo\include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\obj\windows\sumo\fuzzics\debug\SM_fuzzics.lib"
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\sumo\fuzzics\profile\SM_fuzzics.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "SM_fuzzics - Win32 Release"
+# Name "SM_fuzzics - Win32 Debug"
+# Name "SM_fuzzics - Win32 MT DLL Debug"
+# Name "SM_fuzzics - Win32 MT DLL Release"
+# Name "SM_fuzzics - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\source\sumo\Fuzzics\src\SM_FhObject.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\sumo\Fuzzics\src\SM_Object.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\sumo\Fuzzics\src\SM_Scene.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\..\source\sumo\Fuzzics\include\SM_Callback.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\sumo\Fuzzics\include\SM_ClientObjectInfo.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\sumo\Fuzzics\include\SM_FhObject.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\sumo\Fuzzics\include\SM_MotionState.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\sumo\Fuzzics\include\SM_Object.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\sumo\Fuzzics\include\SM_Scene.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/sumo/moto/SM_moto.dsp b/projectfiles/sumo/moto/SM_moto.dsp
new file mode 100644
index 00000000000..ce08d542647
--- /dev/null
+++ b/projectfiles/sumo/moto/SM_moto.dsp
@@ -0,0 +1,332 @@
+# Microsoft Developer Studio Project File - Name="SM_moto" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=SM_moto - Win32 Profile
+!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 "SM_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 "SM_moto.mak" CFG="SM_moto - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "SM_moto - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "SM_moto - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "SM_moto - Win32 MT DLL Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "SM_moto - Win32 MT DLL Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "SM_moto - Win32 Profile" (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)" == "SM_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 "..\..\..\..\obj\windows\sumo\moto"
+# 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 "..\..\..\lib\windows\moto\include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\sumo\moto\SM_moto.lib"
+
+!ELSEIF "$(CFG)" == "SM_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 "..\..\..\..\obj\windows\sumo\moto\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 "..\..\..\source\sumo\MoTo\include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /FR /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\sumo\moto\debug\SM_moto.lib"
+
+!ELSEIF "$(CFG)" == "SM_moto - Win32 MT DLL Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "SM_moto___Win32_MT_DLL_Debug"
+# PROP BASE Intermediate_Dir "SM_moto___Win32_MT_DLL_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\..\..\..\obj\windows\sumo\moto\mtdll_debug"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\sumo\moto\mtdll_debug"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /Gm /GX /ZI /Od /I "..\..\..\source\sumo\MoTo\include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /GZ /c
+# ADD CPP /nologo /MDd /Gm /GX /ZI /Od /I "..\..\..\source\sumo\MoTo\include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /FR /YX /J /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 /out:"..\..\..\..\..\obj\windows\sumo\moto\debug\SM_moto.lib"
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "SM_moto - Win32 MT DLL Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "SM_moto___Win32_MT_DLL_Release"
+# PROP BASE Intermediate_Dir "SM_moto___Win32_MT_DLL_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\..\..\..\obj\windows\sumo\moto\mtdll"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\sumo\moto\mtdll"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /GX /O2 /I "..\..\..\source\sumo\MoTo\include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD CPP /nologo /MD /GX /O2 /I "..\..\..\source\sumo\MoTo\include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\..\obj\windows\sumo\moto\SM_moto.lib"
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "SM_moto - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "SM_moto___Win32_Profile"
+# PROP BASE Intermediate_Dir "SM_moto___Win32_Profile"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "SM_moto___Win32_Profile"
+# PROP Intermediate_Dir "SM_moto___Win32_Profile"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /O2 /I "..\..\..\source\sumo\MoTo\include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /O2 /I "..\..\..\source\sumo\MoTo\include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\obj\windows\sumo\moto\debug\SM_moto.lib"
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\sumo\moto\profile\SM_moto.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "SM_moto - Win32 Release"
+# Name "SM_moto - Win32 Debug"
+# Name "SM_moto - Win32 MT DLL Debug"
+# Name "SM_moto - Win32 MT DLL Release"
+# Name "SM_moto - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\source\sumo\MoTo\src\MT_CmMatrix4x4.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\sumo\MoTo\src\MT_Matrix3x3.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\sumo\MoTo\src\MT_Matrix4x4.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\sumo\MoTo\src\MT_Point3.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\sumo\MoTo\src\MT_Quaternion.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\sumo\MoTo\src\MT_random.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\sumo\MoTo\src\MT_Transform.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\sumo\MoTo\src\MT_Vector2.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\sumo\MoTo\src\MT_Vector3.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\sumo\MoTo\src\MT_Vector4.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\..\source\sumo\MoTo\include\GEN_List.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\sumo\MoTo\include\GEN_Map.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\sumo\MoTo\include\MT_assert.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\sumo\MoTo\include\MT_CmMatrix4x4.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\sumo\MoTo\include\MT_Matrix3x3.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\sumo\MoTo\include\MT_Matrix3x3.inl
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\sumo\MoTo\include\MT_Matrix4x4.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\sumo\MoTo\include\MT_Matrix4x4.inl
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\sumo\MoTo\include\MT_MinMax.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\sumo\MoTo\include\MT_Optimize.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\sumo\MoTo\include\MT_Point2.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\sumo\MoTo\include\MT_Point2.inl
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\sumo\MoTo\include\MT_Point3.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\sumo\MoTo\include\MT_Point3.inl
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\sumo\MoTo\include\MT_Quaternion.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\sumo\MoTo\include\MT_Quaternion.inl
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\sumo\MoTo\include\MT_random.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\sumo\MoTo\include\MT_Scalar.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\sumo\MoTo\include\MT_Stream.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\sumo\MoTo\include\MT_Transform.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\sumo\MoTo\include\MT_Tuple2.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\sumo\MoTo\include\MT_Tuple3.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\sumo\MoTo\include\MT_Tuple4.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\sumo\MoTo\include\MT_Vector2.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\sumo\MoTo\include\MT_Vector2.inl
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\sumo\MoTo\include\MT_Vector3.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\sumo\MoTo\include\MT_Vector3.inl
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\sumo\MoTo\include\MT_Vector4.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\sumo\MoTo\include\MT_Vector4.inl
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\source\sumo\MoTo\include\NM_Scalar.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles/sumo/solid/SM_solid.dsp b/projectfiles/sumo/solid/SM_solid.dsp
new file mode 100644
index 00000000000..064199c38eb
--- /dev/null
+++ b/projectfiles/sumo/solid/SM_solid.dsp
@@ -0,0 +1,366 @@
+# Microsoft Developer Studio Project File - Name="SM_solid" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=SM_solid - Win32 Profile
+!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 "SM_solid.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 "SM_solid.mak" CFG="SM_solid - Win32 Profile"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "SM_solid - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "SM_solid - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "SM_solid - Win32 MT DLL Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "SM_solid - Win32 MT DLL Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "SM_solid - Win32 Profile" (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)" == "SM_solid - 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 "..\..\..\..\obj\windows\sumo\solid"
+# 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 "..\..\..\source\gameengine\physics\sumo\SOLID-3.0\include" /I "../../../lib/windows/moto/include" /I "..\..\..\source\gameengine\physics\sumo\include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /J /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\sumo\solid\SM_solid.lib"
+
+!ELSEIF "$(CFG)" == "SM_solid - 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 "..\..\..\..\obj\windows\sumo\solid\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 "..\..\..\source\gameengine\physics\sumo\SOLID-3.0\include" /I "../../../lib/windows/moto/include" /I "..\..\..\source\gameengine\physics\sumo\include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /GZ /c
+# SUBTRACT CPP /Fr
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\sumo\solid\debug\SM_solid.lib"
+
+!ELSEIF "$(CFG)" == "SM_solid - Win32 MT DLL Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "SM_solid___Win32_MT_DLL_Debug"
+# PROP BASE Intermediate_Dir "SM_solid___Win32_MT_DLL_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\..\..\..\obj\windows\sumo\solid\mtdll_debug"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\sumo\solid\mtdll_debug"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /Gm /GX /ZI /Od /I "..\..\..\source\sumo\SOLID-3.0\include" /I "../../../../lib/windows/moto/include" /I "..\..\..\source\sumo\include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /GZ /c
+# ADD CPP /nologo /MDd /Gm /GX /ZI /Od /I "..\..\..\source\gameengine\physics\sumo\SOLID-3.0\include" /I "../../../lib/windows/moto/include" /I "..\..\..\source\gameengine\physics\sumo\include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /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 /out:"..\..\..\..\..\obj\windows\sumo\solid\debug\SM_solid.lib"
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "SM_solid - Win32 MT DLL Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "SM_solid___Win32_MT_DLL_Release"
+# PROP BASE Intermediate_Dir "SM_solid___Win32_MT_DLL_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\..\..\..\obj\windows\sumo\solid\mtdll"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\sumo\solid\mtdll"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /GX /O2 /I "..\..\..\source\sumo\SOLID-3.0\include" /I "../../../../lib/windows/moto/include" /I "..\..\..\source\sumo\include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD CPP /nologo /MD /GX /O2 /I "..\..\..\source\gameengine\physics\sumo\SOLID-3.0\include" /I "../../../lib/windows/moto/include" /I "..\..\..\source\gameengine\physics\sumo\include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\..\obj\windows\sumo\solid\SM_solid.lib"
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "SM_solid - Win32 Profile"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "SM_solid___Win32_Profile"
+# PROP BASE Intermediate_Dir "SM_solid___Win32_Profile"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "SM_solid___Win32_Profile"
+# PROP Intermediate_Dir "SM_solid___Win32_Profile"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\source\sumo\SOLID-3.0\include" /I "../../../../lib/windows/moto/include" /I "..\..\..\source\sumo\include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /O2 /I "..\..\..\source\gameengine\physics\sumo\SOLID-3.0\include" /I "../../../lib/windows/moto/include" /I "..\..\..\source\gameengine\physics\sumo\include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\..\..\obj\windows\sumo\solid\debug\SM_solid.lib"
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\sumo\solid\profile\SM_solid.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "SM_solid - Win32 Release"
+# Name "SM_solid - Win32 Debug"
+# Name "SM_solid - Win32 MT DLL Debug"
+# Name "SM_solid - Win32 MT DLL Release"
+# Name "SM_solid - Win32 Profile"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE="..\..\..\source\gameengine\Physics\Sumo\SOLID-3.0\src\BBoxTree.cpp"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\gameengine\Physics\Sumo\SOLID-3.0\src\Box.cpp"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\gameengine\Physics\Sumo\SOLID-3.0\src\Complex.cpp"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\gameengine\Physics\Sumo\SOLID-3.0\src\Cone.cpp"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\gameengine\Physics\Sumo\SOLID-3.0\src\Convex.cpp"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\gameengine\Physics\Sumo\SOLID-3.0\src\Cylinder.cpp"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\gameengine\Physics\Sumo\SOLID-3.0\src\DT_BP_C-api.cpp"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\gameengine\Physics\Sumo\SOLID-3.0\src\DT_BP_Endpoint.cpp"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\gameengine\Physics\Sumo\SOLID-3.0\src\DT_BP_Proxy.cpp"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\gameengine\Physics\Sumo\SOLID-3.0\src\DT_BP_Scene.cpp"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\gameengine\Physics\Sumo\SOLID-3.0\src\DT_C-api.cpp"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\gameengine\Physics\Sumo\SOLID-3.0\src\DT_DoubleBase.cpp"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\gameengine\Physics\Sumo\SOLID-3.0\src\DT_Encounter.cpp"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\gameengine\Physics\Sumo\SOLID-3.0\src\DT_FloatBase.cpp"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\gameengine\Physics\Sumo\SOLID-3.0\src\DT_LineSegment.cpp"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\gameengine\Physics\Sumo\SOLID-3.0\src\DT_Object.cpp"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\gameengine\Physics\Sumo\SOLID-3.0\src\DT_RespTable.cpp"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\gameengine\Physics\Sumo\SOLID-3.0\src\DT_Scene.cpp"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\gameengine\Physics\Sumo\SOLID-3.0\src\Polyhedron.cpp"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\gameengine\Physics\Sumo\SOLID-3.0\src\Polytope.cpp"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\gameengine\Physics\Sumo\SOLID-3.0\src\Sphere.cpp"
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE="..\..\..\source\gameengine\Physics\Sumo\SOLID-3.0\include\AlgoTable.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\gameengine\Physics\Sumo\SOLID-3.0\include\BBoxTree.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\gameengine\Physics\Sumo\SOLID-3.0\include\Box.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\gameengine\Physics\Sumo\SOLID-3.0\include\Complex.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\gameengine\Physics\Sumo\SOLID-3.0\include\Cone.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\gameengine\Physics\Sumo\SOLID-3.0\include\Convex.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\gameengine\Physics\Sumo\SOLID-3.0\include\Cylinder.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\gameengine\Physics\Sumo\SOLID-3.0\include\DT_AABBox.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\gameengine\Physics\Sumo\SOLID-3.0\include\DT_BBox.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\gameengine\Physics\Sumo\SOLID-3.0\include\DT_BP_Endpoint.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\gameengine\Physics\Sumo\SOLID-3.0\include\DT_BP_Proxy.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\gameengine\Physics\Sumo\SOLID-3.0\include\DT_BP_Scene.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\gameengine\Physics\Sumo\SOLID-3.0\include\DT_DoubleBase.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\gameengine\Physics\Sumo\SOLID-3.0\include\DT_Encounter.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\gameengine\Physics\Sumo\SOLID-3.0\include\DT_FloatBase.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\gameengine\Physics\Sumo\SOLID-3.0\include\DT_LineSegment.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\gameengine\Physics\Sumo\SOLID-3.0\include\DT_Object.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\gameengine\Physics\Sumo\SOLID-3.0\include\DT_Response.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\gameengine\Physics\Sumo\SOLID-3.0\include\DT_RespTable.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\gameengine\Physics\Sumo\SOLID-3.0\include\DT_Scene.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\gameengine\Physics\Sumo\SOLID-3.0\include\DT_VertexBase.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\gameengine\Physics\Sumo\SOLID-3.0\include\DT_VertexBased.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\gameengine\Physics\Sumo\SOLID-3.0\include\IndexArray.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\gameengine\Physics\Sumo\SOLID-3.0\include\Polyhedron.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\gameengine\Physics\Sumo\SOLID-3.0\include\Polytope.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\gameengine\Physics\Sumo\SOLID-3.0\include\Shape.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\..\source\gameengine\Physics\Sumo\SOLID-3.0\include\Sphere.h"
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/source/BL-license.txt b/source/BL-license.txt
new file mode 100644
index 00000000000..606d3ef6cef
--- /dev/null
+++ b/source/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/source/GPL-license.txt b/source/GPL-license.txt
new file mode 100644
index 00000000000..14db8fc79db
--- /dev/null
+++ b/source/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/source/Makefile b/source/Makefile
new file mode 100644
index 00000000000..2832bdb2478
--- /dev/null
+++ b/source/Makefile
@@ -0,0 +1,639 @@
+#
+# $Id$
+#
+# ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version. The Blender
+# Foundation also sells licenses for use in proprietary software under
+# the Blender License. See http://www.blender.org/BL/ for information
+# about this.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL/BL DUAL LICENSE BLOCK *****
+#
+# Top level makefile. Start looping through subdirs and link.
+#
+
+ifndef NANENV
+ export NANENV := $(shell env | grep NAN_)
+endif
+
+include nan_definitions.mk
+
+DIRS = creator blender kernel sumo gameengine
+
+ifeq ($(OS),windows)
+ DIRS += icons
+endif
+
+ifeq ($(OS),solaris)
+ ifeq ($(CPU),sparc)
+ DIRS += ssr
+ endif
+endif
+
+ifeq ($(OS),freebsd)
+ ifeq ($(OS_VERSION),4.5)
+ DIRS += ssr
+ endif
+endif
+
+########## buildinfo kludge ###################
+CPPFLAGS += -I../Physics/common
+CPPFLAGS += -I../Physics/Dummy
+ifdef NAN_BUILDINFO
+ BUILDINFO_O = $(DIR)/$(DEBUG_DIR)buildinfo.o
+ BUILDINFO_C = $(SRCHOME)/creator/buildinfo.c
+ BUILD_DATE := $(shell date "+%Y-%m-%d")
+ BUILD_TIME := $(shell date "+%H:%M:%S")
+endif
+
+############# set pyplayerlib ##################
+
+PYPLAYERLIB ?= $(PYLIB)
+
+############# libraries ##################
+# COMLIB COMmon LIBraries for all targets
+# BCLIB Blender Creator LIBraries
+# BPLIB Browser Plugin LIBraries
+# SPLIB1 Standalone Player LIBraries (pre COMLIB)
+# SPLIB Standalone Player LIBraries (post COMLIB)
+# PULIB PUblisher LIBraries
+# GRCLIB Gui and Render LIBraries for Creator
+# GRPLIB Gui and Render LIBraries for Publisher
+# LLIBS dynamic system libraries
+# SADD Static OpenGL libraries
+# DADD Dynamic OpenGL libraries
+# NSPLUGLIB PLUGin LIBraries for ns-style api
+# PLUGAPPLIB libs that form the application to be plugged in
+# Note: the order is important here
+
+ GRCLIB = $(OCGDIR)/creator/$(DEBUG_DIR)libcreator.a
+ GRCLIB += $(OCGDIR)/blender/src/$(DEBUG_DIR)libsrccreator.a
+ GRCLIB += $(OCGDIR)/blender/misc/$(DEBUG_DIR)libmisc.a
+ GRCLIB += $(OCGDIR)/blender/radiosity/$(DEBUG_DIR)libradiosity.a
+ GRCLIB += $(NAN_DECIMATION)/lib/libdecimation.a
+ GRCLIB += $(NAN_BSP)/lib/$(DEBUG_DIR)libbsp.a
+ GRCLIB += $(NAN_GHOST)/lib/$(DEBUG_DIR)libghost.a
+ GRCLIB += $(NAN_STRING)/lib/$(DEBUG_DIR)libstring.a
+ GRCLIB += $(OCGDIR)/blender/img/$(DEBUG_DIR)libimg.a
+ GRCLIB += $(OCGDIR)/blender/renderconverter/$(DEBUG_DIR)librenderconverter.a
+ GRCLIB += $(OCGDIR)/blender/render/$(DEBUG_DIR)librender.a
+ GRCLIB += $(OCGDIR)/blender/bpython/$(DEBUG_DIR)libbpython.a
+ GRCLIB += $(NAN_PYTHON)/frozen/libfrozen.a
+
+ GRPLIB = $(OCGDIR)/creator/$(DEBUG_DIR)libcreator.a
+ GRPLIB += $(OCGDIR)/blender/src/$(DEBUG_DIR)libsrcpublisher.a
+ GRPLIB += $(OCGDIR)/blender/misc/$(DEBUG_DIR)libmisc.a
+ GRPLIB += $(OCGDIR)/blender/radiosity/$(DEBUG_DIR)libradiosity.a
+ GRPLIB += $(NAN_DECIMATION)/lib/libdecimation.a
+ GRPLIB += $(NAN_BSP)/lib/$(DEBUG_DIR)libbsp.a
+ GRPLIB += $(NAN_GHOST)/lib/$(DEBUG_DIR)libghost.a
+ GRPLIB += $(NAN_STRING)/lib/$(DEBUG_DIR)libstring.a
+ GRPLIB += $(OCGDIR)/blender/img/$(DEBUG_DIR)libimg.a
+ GRPLIB += $(OCGDIR)/blender/renderconverter/$(DEBUG_DIR)librenderconverter.a
+ GRPLIB += $(OCGDIR)/blender/render/$(DEBUG_DIR)librender.a
+ GRPLIB += $(OCGDIR)/blender/bpython/$(DEBUG_DIR)libbpython.a
+ GRPLIB += $(NAN_PYTHON)/frozen/libfrozen.a
+
+ COMLIB = $(OCGDIR)/blender/blenkernel/$(DEBUG_DIR)libblenkernel.a
+ COMLIB += $(OCGDIR)/blender/blenloader/$(DEBUG_DIR)libblenloader.a
+ COMLIB += $(OCGDIR)/blender/blenpluginapi/$(DEBUG_DIR)libblenpluginapi.a
+ COMLIB += $(OCGDIR)/blender/imbuf/$(DEBUG_DIR)libimbuf.a
+ COMLIB += $(OCGDIR)/blender/blenlib/$(DEBUG_DIR)libblenlib.a
+ COMLIB += $(OCGDIR)/blender/avi/$(DEBUG_DIR)libavi.a
+ COMLIB += $(NAN_JPEG)/lib/libjpeg.a
+ COMLIB += $(OCGDIR)/gameengine/bloutines/$(DEBUG_DIR)libbloutines.a
+ COMLIB += $(OCGDIR)/gameengine/blconverter/$(DEBUG_DIR)libblconverter.a
+ COMLIB += $(OCGDIR)/gameengine/blphys/common/$(DEBUG_DIR)libcommon.a
+ COMLIB += $(OCGDIR)/gameengine/blphys/sumo/$(DEBUG_DIR)libsumo.a
+ COMLIB += $(OCGDIR)/gameengine/blphys/dummy/$(DEBUG_DIR)libdummy.a
+ COMLIB += $(OCGDIR)/gameengine/blphys/common/$(DEBUG_DIR)libcommon.a
+ COMLIB += $(OCGDIR)/gameengine/blphys/sumo/$(DEBUG_DIR)libsumo.a
+ COMLIB += $(OCGDIR)/gameengine/blphys/dummy/$(DEBUG_DIR)libdummy.a
+ COMLIB += $(OCGDIR)/gameengine/ketsji/$(DEBUG_DIR)libketsji.a
+ COMLIB += $(OCGDIR)/gameengine/logic/$(DEBUG_DIR)liblogic.a
+ COMLIB += $(OCGDIR)/gameengine/rasterizer/$(DEBUG_DIR)librasterizer.a
+ COMLIB += $(OCGDIR)/gameengine/OpenGLrasterizer/$(DEBUG_DIR)libOpenGLrasterizer.a
+ COMLIB += $(OCGDIR)/gameengine/expression/$(DEBUG_DIR)libexpression.a
+ COMLIB += $(OCGDIR)/gameengine/scenegraph/$(DEBUG_DIR)libscenegraph.a
+ COMLIB += $(OCGDIR)/sumo/$(DEBUG_DIR)libfuzzics.a
+# COMLIB += $(OCGDIR)/sumo/$(DEBUG_DIR)libsolid.a
+ COMLIB += $(NAN_MOTO)/lib/libmoto.a
+ COMLIB += $(NAN_SND_LIBS)
+ COMLIB += $(OCGDIR)/kernel/gen_system/$(DEBUG_DIR)libgen_system.a
+ COMLIB += $(OCGDIR)/kernel/gen_messaging/$(DEBUG_DIR)libgen_messaging.a
+ COMLIB += $(OCGDIR)/gameengine/ketsji/KXNetwork/$(DEBUG_DIR)libKXNetwork.a
+ COMLIB += $(OCGDIR)/gameengine/Network/$(DEBUG_DIR)libNetwork.a
+ COMLIB += $(OCGDIR)/gameengine/Network/LoopBackNetwork/$(DEBUG_DIR)libLoopBackNetwork.a
+ COMLIB += $(NAN_GUARDEDALLOC)/lib/libguardedalloc.a
+ COMLIB += $(NAN_BMFONT)/lib/$(DEBUG_DIR)libbmfont.a
+ COMLIB += $(NAN_PNG)/lib/libpng.a
+
+ BCLIB = $(NAN_IKSOLVER)/lib/libiksolver.a
+ BCLIB += $(OCGDIR)/blender/readblenfile/$(DEBUG_DIR)libreadblenfile.a
+ BCLIB += $(OCGDIR)/blender/readstreamglue/$(DEBUG_DIR)libreadstreamglue.a
+ BCLIB += $(OCGDIR)/blender/writestreamglueSTUB/$(DEBUG_DIR)libwritestreamglueSTUB.a
+ BCLIB += $(OCGDIR)/blender/inflate/$(DEBUG_DIR)libinflate.a
+ BCLIB += $(OCGDIR)/blender/verify/$(DEBUG_DIR)libverify.a
+ BCLIB += $(OCGDIR)/blender/decryptSTUB/$(DEBUG_DIR)libdecryptSTUB.a
+ BCLIB += $(OCGDIR)/blender/src/$(DEBUG_DIR)libsrccreator.a
+
+ PULIB = $(NAN_IKSOLVER)/lib/libiksolver.a
+ PULIB += $(OCGDIR)/blender/readblenfile/$(DEBUG_DIR)libreadblenfile.a
+ PULIB += $(OCGDIR)/blender/readstreamglue/$(DEBUG_DIR)libreadstreamglue.a
+ PULIB += $(OCGDIR)/blender/writestreamglue/$(DEBUG_DIR)libwritestreamglue.a
+ # toggle 2 writestreamglue libs for the Uber-Publisher :)
+ #PULIB += $(OCGDIR)/blender/writestreamglueSTUB/$(DEBUG_DIR)libwritestreamglueSTUB.a
+ PULIB += $(OCGDIR)/blender/inflate/$(DEBUG_DIR)libinflate.a
+ PULIB += $(OCGDIR)/blender/deflate/$(DEBUG_DIR)libdeflate.a
+ PULIB += $(OCGDIR)/blender/encrypt/$(DEBUG_DIR)libencrypt.a
+ PULIB += $(OCGDIR)/blender/decrypt/$(DEBUG_DIR)libdecrypt.a
+ PULIB += $(OCGDIR)/blender/sign/$(DEBUG_DIR)libsign.a
+ PULIB += $(OCGDIR)/blender/verify/$(DEBUG_DIR)libverify.a
+ PULIB += $(OCGDIR)/blender/writeblenfile/$(DEBUG_DIR)libwriteblenfile.a
+ PULIB += $(OCGDIR)/blender/writestreamglue/$(DEBUG_DIR)libwritestreamglue.a
+ # toggle 2 writestreamglue libs for the Uber-Publisher :)
+ #PULIB += $(OCGDIR)/blender/writestreamglueSTUB/$(DEBUG_DIR)libwritestreamglueSTUB.a
+ PULIB += $(OCGDIR)/blender/readstreamglue/$(DEBUG_DIR)libreadstreamglue.a # KEY_dependkludge fix.. Remove me
+ PULIB += $(OCGDIR)/blender/src/$(DEBUG_DIR)libsrcpublisher.a
+
+ SPLIB1 = $(OCGDIR)/gameengine/GamePlayer/ghost/$(DEBUG_DIR)libghost.a
+ SPLIB1 += $(OCGDIR)/gameengine/GamePlayer/common/$(DEBUG_DIR)libcommon.a
+ SPLIB1 += $(NAN_STRING)/lib/$(DEBUG_DIR)libstring.a
+ SPLIB1 += $(NAN_GHOST)/lib/$(DEBUG_DIR)libghost.a
+
+ SSRLIB1 = $(OCGDIR)/gameengine/GamePlayer/common/$(DEBUG_DIR)libcommon.a
+ SSRLIB1 += $(NAN_STRING)/lib/$(DEBUG_DIR)libstring.a
+ SSRLIB1 += $(NAN_GHOST)/lib/$(DEBUG_DIR)libghost.a
+ SSRLIB1 += $(NAN_PNG)/lib/libpng.a
+
+ SPLIB = $(OCGDIR)/blender/makesdna/$(DEBUG_DIR)DNA.o
+ SPLIB += $(OCGDIR)/blender/readblenfile/$(DEBUG_DIR)libreadblenfile.a
+ SPLIB += $(OCGDIR)/blender/readstreamglue/$(DEBUG_DIR)libreadstreamglue.a
+ # this is used for the plugin. It uses some things from libz.a,
+ # but somehow it consistently fails to resolve these symbols... or
+ # can I just not check them? nm claims they aren't...
+ SPLIB += $(OCGDIR)/blender/inflate/$(DEBUG_DIR)libinflate.a
+ SPLIB += $(OCGDIR)/blender/decrypt/$(DEBUG_DIR)libdecrypt.a
+ SPLIB += $(OCGDIR)/blender/writestreamglueSTUB/$(DEBUG_DIR)libwritestreamglueSTUB.a
+ SPLIB += $(OCGDIR)/blender/verify/$(DEBUG_DIR)libverify.a
+ SPLIB += $(OCGDIR)/blender/blenkernel/blenkernel_blc/$(DEBUG_DIR)libblenkernel_blc.a
+
+ BCLIB += $(NAN_BLENKEY)/lib/libblenkey.a
+ PULIB += $(NAN_BLENKEY)/lib/libblenkey.a
+ SPLIB += $(NAN_BLENKEY)/lib/libblenkey.a
+ ifeq ($(OS),windows)
+ BCLIB += $(NAN_OPENSSL)/lib/libeay32.lib
+ PULIB += $(NAN_OPENSSL)/lib/libeay32.lib
+ SPLIB += $(NAN_OPENSSL)/lib/libeay32.lib
+ else
+ BCLIB += $(NAN_OPENSSL)/lib/libcrypto.a
+ PULIB += $(NAN_OPENSSL)/lib/libcrypto.a
+ SPLIB += $(NAN_OPENSSL)/lib/libcrypto.a
+ endif
+
+ # These three need to be explicitly mentioned on the cl, because
+ # if they are offered as a lib, they are optimized away. (nzc)
+ NSPLUGLIB = $(OCGDIR)/gameengine/GamePlayer/netscape/src/$(DEBUG_DIR)UnixShell.o
+ NSPLUGLIB += $(OCGDIR)/gameengine/GamePlayer/netscape/src/$(DEBUG_DIR)stubs.o
+ NSPLUGLIB += $(OCGDIR)/gameengine/GamePlayer/netscape/src/$(DEBUG_DIR)winstubs.o
+ NSPLUGLIB += $(OCGDIR)/gameengine/GamePlayer/netscape/src/$(DEBUG_DIR)Blender3DPlugin_native_implementation.o
+
+ # Here you can configure what sort of test to make for the plugin.
+# PLUGTESTLIB = $(OCGDIR)/gameengine/GamePlayer/netscape/test/$(DEBUG_DIR)libns_api_test_stub.a
+# PLUGTESTLIB = $(OCGDIR)/gameengine/GamePlayer/netscape/test/$(DEBUG_DIR)libns_api_test_colorcycle.a
+# PLUGTESTLIB = $(OCGDIR)/gameengine/GamePlayer/netscape/test/$(DEBUG_DIR)libns_api_test_gears.a
+ PLUGTESTLIB = $(OCGDIR)/gameengine/GamePlayer/netscape/test/$(DEBUG_DIR)libns_api_test_threaded_gears.a
+
+# XPCOM is done only for Linux for now
+ifeq ($(OS),$(findstring $(OS), "linux"))
+ ifeq ($(CPU),i386)
+ NSPLUGLIB += $(OCGDIR)/gameengine/GamePlayer/netscape/src/$(DEBUG_DIR)XPH_xpcom_hooks.o
+ endif
+endif
+
+ PLUGAPPLIB = $(OCGDIR)/gameengine/GamePlayer/netscape/src/$(DEBUG_DIR)libplugin_ketsji_hooks.a
+
+ifeq ($(OS),$(findstring $(OS), "freebsd linux irix solaris"))
+ NSPLUGLIB += $(OCGDIR)/gameengine/GamePlayer/netscape/src/$(DEBUG_DIR)PLG_X11_windowing.o
+ PLUGAPPLIB += $(OCGDIR)/gameengine/GamePlayer/common/unix/$(DEBUG_DIR)libunix.a
+endif
+ifeq ($(OS),$(findstring $(OS), "windows"))
+ NSPLUGLIB += $(OCGDIR)/gameengine/GamePlayer/netscape/src/$(DEBUG_DIR)PLG_MSWindows_windowing.o
+ NSPLUGLIB += $(OCGDIR)/gameengine/GamePlayer/netscape/src/$(DEBUG_DIR)npB3DPlg.res
+ PLUGAPPLIB += $(OCGDIR)/gameengine/GamePlayer/common/windows/$(DEBUG_DIR)libwindows.a
+endif
+ PLUGAPPLIB += $(OCGDIR)/gameengine/GamePlayer/common/$(DEBUG_DIR)libcommon.a
+
+
+ifeq ($(OS),$(findstring $(OS), "linux"))
+ ifeq ($(CPU),i386)
+ PLUGAPPLIB_XPLINK = $(OCGDIR)/gameengine/GamePlayer/netscape/src/$(DEBUG_DIR)_Blender3DPlugin_implementation_.o
+ endif
+endif
+
+ # A bit silly... but needed to resolve symbols.
+ PLUGREMLIB = $(NAN_STRING)/lib/$(DEBUG_DIR)libstring.a
+ifeq ($(OS),windows)
+ PLUGREMLIB += $(NAN_OPENSSL)/lib/libeay32.lib
+else
+ PLUGREMLIB += $(NAN_OPENSSL)/lib/libcrypto.a
+endif
+
+ SSRLIB = $(OCGDIR)/ssr/$(DEBUG_DIR)GPG_Application.o
+ SSRLIB += $(OCGDIR)/ssr/$(DEBUG_DIR)GPG_Canvas.o
+ SSRLIB += $(OCGDIR)/ssr/$(DEBUG_DIR)GPG_KeyboardDevice.o
+ SSRLIB += $(OCGDIR)/ssr/$(DEBUG_DIR)GPG_System.o
+ SSRLIB += $(OCGDIR)/ssr/$(DEBUG_DIR)GPG_ghost.o
+ SSRLIB += $(OCGDIR)/ssr/$(DEBUG_DIR)createPngFromGL.o
+
+######################## OS dependencies (alphabetic!) ################
+
+include nan_link.mk
+
+ifeq ($(OS),beos)
+ BINTARGETS = blendercreator
+endif
+
+ifeq ($(OS),darwin)
+ # Python
+ PYLIB = $(NAN_PYTHON)/lib/python$(NAN_PYTHON_VERSION)/config/libpython$(NAN_PYTHON_VERSION).a
+ # The only target right now...
+ BINTARGETS = blendercreator.app
+ BINTARGETS += blenderpublisher.app
+ BINTARGETS += blenderplayer.app
+endif
+
+ifeq ($(OS),freebsd)
+ ifeq ($(OS_VERSION),$(findstring $(OS_VERSION), "3.4 4.0"))
+ BINTARGETS = blendercreator blenderstatic
+ else
+ BINTARGETS = blendercreator
+ BINTARGETS += blenderpublisher
+ BINTARGETS += blenderplayer
+ BINTARGETS += plugin
+ ifeq ($(OS_VERSION),4.5)
+ BINTARGETS += blenderssr
+ endif
+ endif
+ PYLIB = $(NAN_PYTHON)/lib/python$(NAN_PYTHON_VERSION)/config/libpython$(NAN_PYTHON_VERSION).a
+ PYLIB += $(NAN_PYTHON)/mxTextTools/libmxtexttools.a
+endif
+
+ifeq ($(OS),irix)
+ BINTARGETS = blendercreator
+ BINTARGETS += blenderpublisher
+ BINTARGETS += blenderplayer
+ BINTARGETS += plugin
+ PYLIB = $(NAN_PYTHON)/lib/python$(NAN_PYTHON_VERSION)/config/libpython$(NAN_PYTHON_VERSION).a
+ PYLIB += $(NAN_PYTHON)/mxTextTools/libmxtexttools.a
+endif
+
+ifeq ($(OS),linux)
+ ifeq ($(CPU),alpha)
+ BINTARGETS = blendercreator
+ BINTARGETS += blenderpublisher
+ BINTARGETS += blenderplayer
+ endif
+ ifeq ($(CPU),i386)
+ BINTARGETS = plugin
+ # BINTARGETS += ptest
+ BINTARGETS += xplink
+ BINTARGETS += blendercreator
+ BINTARGETS += blenderpublisher
+ BINTARGETS += blenderplayer
+ BINTARGETS += blenderstatic
+ endif
+ ifeq ($(CPU),powerpc)
+ BINTARGETS = blendercreator blenderstatic
+ BINTARGETS += blenderpublisher
+ endif
+ PYLIB = $(NAN_PYTHON)/lib/python$(NAN_PYTHON_VERSION)/config/libpython$(NAN_PYTHON_VERSION).a
+ PYLIB += $(NAN_PYTHON)/mxTextTools/libmxtexttools.a
+endif
+
+ifeq ($(OS),openbsd)
+ BINTARGETS = blenderstatic
+ PYLIB = $(NAN_PYTHON)/lib/python$(NAN_PYTHON_VERSION)/config/libpython$(NAN_PYTHON_VERSION).a
+endif
+
+ifeq ($(OS),solaris)
+ BINTARGETS = blendercreator
+ BINTARGETS += blenderpublisher
+ BINTARGETS += blenderplayer
+ ifeq ($(CPU),sparc)
+ BINTARGETS += plugin
+ BINTARGETS += blenderssr
+ endif
+ PYLIB = $(NAN_PYTHON)/lib/python$(NAN_PYTHON_VERSION)/config/libpython$(NAN_PYTHON_VERSION).a
+ PYLIB += $(NAN_PYTHON)/mxTextTools/libmxtexttools.a
+ PYLIB += $(NAN_ZLIB)/lib/libz.a
+
+ BCLIB += $(NAN_ZLIB)/lib/libz.a
+ PULIB += $(NAN_ZLIB)/lib/libz.a
+ SPLIB += $(NAN_ZLIB)/lib/libz.a
+endif
+
+
+# OpenAL libs are already compiled as shared code! Check FMod if we switch to that. (nzc)
+ifeq ($(OS),$(findstring $(OS), "freebsd linux windows"))
+ ifeq ($(CPU),i386)
+ ifeq ($(OS),freebsd)
+ NAN_SND_LIBS = $(OCGDIR)/gameengine/SoundSystem/$(DEBUG_DIR)libSoundSystem.a
+ NAN_SND_LIBS += $(OCGDIR)/gameengine/DummySoundSystem/$(DEBUG_DIR)libDummySoundSystem.a
+ NAN_SND_LIBS += $(OCGDIR)/gameengine/OpenALSoundSystem/$(DEBUG_DIR)libOpenALSoundSystem.a
+ NAN_SND_LIBS += $(NAN_OPENAL)/lib/libopenal.a
+ NAN_SND_LIBS += $(OCGDIR)/gameengine/SoundSystem/$(DEBUG_DIR)libSoundSystem.a
+ else
+ NAN_SND_LIBS = $(OCGDIR)/gameengine/SoundSystem/$(DEBUG_DIR)libSoundSystem.a
+ NAN_SND_LIBS += $(OCGDIR)/gameengine/DummySoundSystem/$(DEBUG_DIR)libDummySoundSystem.a
+ NAN_SND_LIBS += $(OCGDIR)/gameengine/OpenALSoundSystem/$(DEBUG_DIR)libOpenALSoundSystem.a
+ NAN_SND_LIBS += $(NAN_OPENAL)/lib/libopenal.a
+# NAN_SND_LIBS += $(OCGDIR)/gameengine/FmodSoundSystem/$(DEBUG_DIR)libFmodSoundSystem.a
+# NAN_SND_LIBS += $(NAN_FMOD)/lib/libfmod.a
+# NAN_SND_LIBS += $(OCGDIR)/gameengine/FmodSoundSystem/$(DEBUG_DIR)libFmodSoundSystem.a
+ NAN_SND_LIBS += $(OCGDIR)/gameengine/SoundSystem/$(DEBUG_DIR)libSoundSystem.a
+ endif
+ else
+ ifeq ($(OS),windows)
+ NAN_SND_LIBS = $(OCGDIR)/gameengine/SoundSystem/$(DEBUG_DIR)libSoundSystem.a
+ NAN_SND_LIBS += $(OCGDIR)/gameengine/DummySoundSystem/$(DEBUG_DIR)libDummySoundSystem.a
+# NAN_SND_LIBS += $(OCGDIR)/gameengine/OpenALSoundSystem/$(DEBUG_DIR)libOpenALSoundSystem.a
+# NAN_SND_LIBS += $(NAN_OPENAL)/lib/openal_static.lib
+ NAN_SND_LIBS += $(OCGDIR)/gameengine/FmodSoundSystem/$(DEBUG_DIR)libFmodSoundSystem.a
+ NAN_SND_LIBS += $(NAN_FMOD)/lib/fmodvc.lib
+ NAN_SND_LIBS += $(OCGDIR)/gameengine/SoundSystem/$(DEBUG_DIR)libSoundSystem.a
+ else
+ NAN_SND_LIBS = $(OCGDIR)/gameengine/SoundSystem/$(DEBUG_DIR)libSoundSystem.a
+ NAN_SND_LIBS += $(OCGDIR)/gameengine/DummySoundSystem/$(DEBUG_DIR)libDummySoundSystem.a
+ NAN_SND_LIBS += $(OCGDIR)/gameengine/SoundSystem/$(DEBUG_DIR)libSoundSystem.a
+ endif
+ endif
+else
+ NAN_SND_LIBS = $(OCGDIR)/gameengine/SoundSystem/$(DEBUG_DIR)libSoundSystem.a
+ NAN_SND_LIBS += $(OCGDIR)/gameengine/DummySoundSystem/$(DEBUG_DIR)libDummySoundSystem.a
+ NAN_SND_LIBS += $(OCGDIR)/gameengine/SoundSystem/$(DEBUG_DIR)libSoundSystem.a
+endif
+
+ifeq ($(OS),windows)
+ PYLIB = $(NAN_PYTHON)/lib/python20.lib
+ PYPLAYERLIB = $(NAN_PYTHON)/static/*.obj
+ PYPLAYERLIB = $(PYLIB)
+
+ NSPLUGLIB += $(NAN_NSPR)/lib/nspr4.lib
+
+ BINTARGETS = blendercreator
+ BINTARGETS += blenderpublisher
+ BINTARGETS += blenderplayer
+ BINTARGETS += blenderdynplayer
+ BINTARGETS += plugin
+
+ BCLIB += $(OCGDIR)/blender/icons/$(DEBUG_DIR)wincreator.res
+ BCLIB += $(NAN_ZLIB)/lib/libz.a
+ PULIB += $(OCGDIR)/blender/icons/$(DEBUG_DIR)winpublisher.res
+ PULIB += $(NAN_ZLIB)/lib/libz.a
+ SPLIB += $(OCGDIR)/blender/icons/$(DEBUG_DIR)winplayer.res
+ SPLIB += $(NAN_ZLIB)/lib/libz.a
+
+ ifdef NAN_PLAYERSTATIC
+ PYPLAYERLIB = $(NAN_PYTHON)/static/python20.lib
+ BINTARGETS = blenderplayer
+
+ NAN_SND_LIBS = $(OCGDIR)/gameengine/SoundSystem/$(DEBUG_DIR)libSoundSystem.a
+ NAN_SND_LIBS += $(OCGDIR)/gameengine/DummySoundSystem/$(DEBUG_DIR)libDummySoundSystem.a
+ NAN_SND_LIBS += $(OCGDIR)/gameengine/OpenALSoundSystem/$(DEBUG_DIR)libOpenALSoundSystem.a
+ NAN_SND_LIBS += $(NAN_OPENAL)/lib/openal_static.lib
+ NAN_SND_LIBS += $(OCGDIR)/gameengine/SoundSystem/$(DEBUG_DIR)libSoundSystem.a
+
+ PYINCLUDEOK := $(shell diff -qbB gameengine/Ketsji/KX_Python.h gameengine/Ketsji/KX_Python_static.h)
+ ifneq (x$(PYINCLUDEOK),x)
+ DUMMY := $(shell cat gameengine/Ketsji/KX_Python_static.h > gameengine/Ketsji/KX_Python.h)
+ endif
+ else
+ PYINCLUDEOK := $(shell diff -qbB gameengine/Ketsji/KX_Python.h gameengine/Ketsji/KX_Python_dynamic.h)
+ ifneq (x$(PYINCLUDEOK),x)
+ DUMMY := $(shell cat gameengine/Ketsji/KX_Python_dynamic.h > gameengine/Ketsji/KX_Python.h)
+ endif
+ endif
+endif
+
+# prepare for NAN_BUILDINFO compile at the *sigh* link rules below
+
+ifdef NAN_BUILDINFO
+ CSRCS =
+ ALLTARGETS =
+ include nan_compile.mk
+endif
+
+################## target rules ########################
+
+all debug ::
+ @echo "****> Make $@ by $(ID)@$(HOST) at $(MAKE_START) on $(CONFIG_GUESS)"
+ ifdef NANENV
+ @for n in $(NANENV); do \
+ echo " $$n"; \
+ done
+ endif
+
+DIR = $(OCGDIR)
+SOURCEDIR = source
+
+include nan_subdirs.mk
+
+################## target rules ########################
+
+all:: link
+
+debug debuglink::
+ @$(MAKE) link DEBUG_DIR="debug/" NANENV=$(NANENV)
+
+clean:: linkclean debuglinkclean
+
+link: $(BINTARGETS)
+ @echo "****> Build $(MAKE_START) - `date '+%H:%M:%S %d-%b-%Y'`"
+ ifdef NANENV
+ @for n in $(NANENV); do \
+ echo " $$n"; \
+ done
+ endif
+
+linkclean:
+ @$(RM) $(DIR)/blendercreator* \
+ $(DIR)/blenderstatic* \
+ $(DIR)/blenderpublisher* \
+ $(DIR)/blenderplayer*
+
+debuglinkclean:
+ @$(RM) $(DIR)/debug/blendercreator* \
+ $(DIR)/debug/blenderstatic* \
+ $(DIR)/debug/blenderpublisher* \
+ $(DIR)/debug/blenderplayer*
+
+# Shortcut for Tinderbox release builds. Mortals don't use this.
+release:
+ @$(MAKE) -C ../release/ all || exit 1;
+
+############### Linker rules ###############
+
+blendercreator: $(DIR)/$(DEBUG_DIR)blendercreator$(EXT)
+blenderstatic: $(DIR)/$(DEBUG_DIR)blenderstatic
+blenderpublisher: $(DIR)/$(DEBUG_DIR)blenderpublisher$(EXT)
+blenderplayer: $(DIR)/$(DEBUG_DIR)blenderplayer$(EXT)
+blenderdynplayer: $(DIR)/$(DEBUG_DIR)blenderdynplayer$(EXT)
+blenderssr: $(DIR)/$(DEBUG_DIR)libblenderssr$(SOEXT)
+
+blenderplayer.app: blenderplayer
+ @$(MAKE) -C darwin/ APPLICATION=blenderplayer
+
+blenderpublisher.app: blenderpublisher
+ @$(MAKE) -C darwin/ APPLICATION=blenderpublisher
+
+blendercreator.app: blendercreator
+ @$(MAKE) -C darwin/ APPLICATION=blendercreator
+
+# XPCOM connector only for linux so far...
+ifeq ($(OS),linux)
+ xplink: $(DIR)/$(DEBUG_DIR)Blender3DPlugin$(SOEXT)
+endif
+
+# Moz/NS plugin:
+ifeq ($(OS),$(findstring $(OS), "freebsd linux irix solaris"))
+ plugin: $(DIR)/$(DEBUG_DIR)npBlender3DPlugin$(SOEXT)
+ ptest: $(DIR)/$(DEBUG_DIR)npTestPlugin$(SOEXT)
+endif
+# Windows needs a 8.3 name... Why? Dunno...
+ifeq ($(OS),windows)
+ plugin: $(DIR)/$(DEBUG_DIR)npB3DPlg$(SOEXT)
+endif
+
+$(DIR)/$(DEBUG_DIR)blendercreator$(EXT): $(OBJS) $(GRCLIB) $(COMLIB) $(BCLIB)
+ @echo "****> Link $@"
+ ifdef NAN_BUILDINFO
+ $(CCC) $(REL_CFLAGS) -DBUILD_DATE='"$(BUILD_DATE)"' -DBUILD_TIME='"$(BUILD_TIME)"' -DBUILD_PLATFORM='"$(CONFIG_GUESS)"' -DBUILD_TYPE='"dynamic"' $(BUILDINFO_C) -c -o $(BUILDINFO_O) -DNAN_BUILDINFO
+ endif
+ $(CCC) $(LDFLAGS) -o $@ $(BUILDINFO_O) $(OBJS) $(GRCLIB) $(COMLIB) $(BCLIB) $(PYLIB) $(LLIBS) $(DADD) $(LOPTS)
+ ifdef NAN_BUILDINFO
+ /bin/rm $(BUILDINFO_O)
+ endif
+
+$(DIR)/$(DEBUG_DIR)blenderstatic: $(OBJS) $(GRCLIB) $(COMLIB) $(BCLIB)
+ @echo "****> Link $@"
+ ifdef NAN_BUILDINFO
+ $(CCC) $(REL_CFLAGS) -DBUILD_DATE='"$(BUILD_DATE)"' -DBUILD_TIME='"$(BUILD_TIME)"' -DBUILD_PLATFORM='"$(CONFIG_GUESS)"' -DBUILD_TYPE='"static"' $(BUILDINFO_C) -c -o $(BUILDINFO_O) -DNAN_BUILDINFO
+ endif
+ $(CCC) $(LDFLAGS) -o $@ $(BUILDINFO_O) $(OBJS) $(GRCLIB) $(COMLIB) $(BCLIB) $(PYLIB) $(LLIBS) $(SADD) $(LOPTS)
+ ifdef NAN_BUILDINFO
+ /bin/rm $(BUILDINFO_O)
+ endif
+
+$(DIR)/$(DEBUG_DIR)blenderpublisher$(EXT): $(OBJS) $(GRPLIB) $(COMLIB) $(PULIB)
+ @echo "****> Link $@"
+ ifdef NAN_BUILDINFO
+ $(CCC) $(REL_CFLAGS) -DBUILD_DATE='"$(BUILD_DATE)"' -DBUILD_TIME='"$(BUILD_TIME)"' -DBUILD_PLATFORM='"$(CONFIG_GUESS)"' -DBUILD_TYPE='"dynamic"' $(BUILDINFO_C) -c -o $(BUILDINFO_O) -DNAN_BUILDINFO
+ endif
+ $(CCC) $(LDFLAGS) -o $@ $(BUILDINFO_O) $(OBJS) $(GRPLIB) $(COMLIB) $(PULIB) $(PYLIB) $(LLIBS) $(DADD) $(LOPTS)
+ ifdef NAN_BUILDINFO
+ /bin/rm $(BUILDINFO_O)
+ endif
+
+$(DIR)/$(DEBUG_DIR)blenderplayer$(EXT): $(OBJS) $(SPLIB1) $(COMLIB) $(SPLIB)
+ @echo "****> Link $@"
+ ifdef NAN_BUILDINFO
+ $(CCC) $(REL_CFLAGS) -DBUILD_DATE='"$(BUILD_DATE)"' -DBUILD_TIME='"$(BUILD_TIME)"' -DBUILD_PLATFORM='"$(CONFIG_GUESS)"' -DBUILD_TYPE='"dynamic"' $(BUILDINFO_C) -c -o $(BUILDINFO_O) -DNAN_BUILDINFO
+ endif
+ $(CCC) $(LDFLAGS) -o $@ $(BUILDINFO_O) $(OBJS) $(SPLIB1) $(COMLIB) $(SPLIB) $(PYPLAYERLIB) $(LLIBS) $(DADD) $(LOPTS)
+ ifdef NAN_BUILDINFO
+ /bin/rm $(BUILDINFO_O)
+ endif
+
+$(DIR)/$(DEBUG_DIR)blenderdynplayer$(EXT): $(OBJS) $(COMLIB) $(SPLIB)
+ @echo "****> Link $@"
+ ifdef NAN_BUILDINFO
+ $(CCC) $(REL_CFLAGS) -DBUILD_DATE='"$(BUILD_DATE)"' -DBUILD_TIME='"$(BUILD_TIME)"' -DBUILD_PLATFORM='"$(CONFIG_GUESS)"' -DBUILD_TYPE='"dynamic"' $(BUILDINFO_C) -c -o $(BUILDINFO_O) -DNAN_BUILDINFO
+ endif
+ $(CCC) $(LDFLAGS) -o $@ $(BUILDINFO_O) $(OBJS) $(SPLIB1) $(COMLIB) $(SPLIB) $(PYLIB) $(LLIBS) $(DADD) $(LOPTS)
+ ifdef NAN_BUILDINFO
+ /bin/rm $(BUILDINFO_O)
+ endif
+
+ifeq ($(OS),linux)
+$(DIR)/$(DEBUG_DIR)Blender3DPlugin$(SOEXT): $(PLUGAPPLIB_XPLINK)
+ @echo "****> Link $(DIR)/$(DEBUG_DIR)Blender3DPlugin.so"
+ ifdef NAN_BUILDINFO
+ $(CCC) $(REL_CFLAGS) -DBUILD_DATE='"$(BUILD_DATE)"' -DBUILD_TIME='"$(BUILD_TIME)"' -DBUILD_PLATFORM='"$(CONFIG_GUESS)"' -DBUILD_TYPE='"dynamic"' $(BUILDINFO_C) -c -o $(BUILDINFO_O) -DNAN_BUILDINFO
+ endif
+ $(CCC) $(DYNLDFLAGS) -o $@ $(PLUGAPPLIB_XPLINK) $(LOPTS)
+ ifdef NAN_BUILDINFO
+ /bin/rm $(BUILDINFO_O)
+ endif
+endif
+
+# Windows build needs a def file? Why? For exposing functions from the
+# dll to the outside world. However, this is alsi done internally..
+DEFFILE = \\\\server\\nzc\\develop\\source\\gameengine\\GamePlayer\\netscape\\src\\npB3DPlg.def
+
+# Windows needs a specific name format for dll.s so we give it one.
+ifeq ($(OS),windows)
+$(DIR)/$(DEBUG_DIR)npB3DPlg$(SOEXT): $(NSPLUGLIB) $(PLUGAPPLIB) $(COMLIB) $(SPLIB)
+ @echo "****> Link $(DIR)/$(DEBUG_DIR)npBl3DPlg.$(SOEXT)"
+ ifdef NAN_BUILDINFO
+ $(CCC) $(REL_CFLAGS) -DBUILD_DATE='"$(BUILD_DATE)"' -DBUILD_TIME='"$(BUILD_TIME)"' -DBUILD_PLATFORM='"$(CONFIG_GUESS)"' -DBUILD_TYPE='"dynamic"' $(BUILDINFO_C) -c -o $(BUILDINFO_O) -DNAN_BUILDINFO
+ endif
+# $(CCC) $(DYNLDFLAGS) -o $@ $(NSPLUGLIB) $(PLUGAPPLIB) $(COMLIB) $(SPLIB) $(PYLIB) $(PLUGREMLIB) $(LLIBS) $(DADD) $(LOPTS)
+ $(CCC) $(DYNLDFLAGS) -o $@ $(NSPLUGLIB) $(PLUGAPPLIB) $(COMLIB) $(SPLIB) $(PYLIB) $(PLUGREMLIB) $(LLIBS) $(DADD) $(LOPTS) /def:$(DEFFILE)
+ ifdef NAN_BUILDINFO
+ /bin/rm $(BUILDINFO_O)
+ endif
+endif
+
+ifeq ($(OS),$(findstring $(OS), "linux freebsd irix solaris"))
+$(DIR)/$(DEBUG_DIR)npBlender3DPlugin$(SOEXT): $(NSPLUGLIB) $(PLUGAPPLIB) $(COMLIB) $(SPLIB)
+ @echo "****> Link $(DIR)/$(DEBUG_DIR)Blender3DPlugin.so"
+ ifdef NAN_BUILDINFO
+ $(CCC) $(REL_CFLAGS) -DBUILD_DATE='"$(BUILD_DATE)"' -DBUILD_TIME='"$(BUILD_TIME)"' -DBUILD_PLATFORM='"$(CONFIG_GUESS)"' -DBUILD_TYPE='"dynamic"' $(BUILDINFO_C) -c -o $(BUILDINFO_O) -DNAN_BUILDINFO
+ endif
+ $(CCC) $(DYNLDFLAGS) -o $@ $(NSPLUGLIB) $(PLUGAPPLIB) $(COMLIB) $(SPLIB) $(PYLIB) $(PLUGREMLIB) $(LLIBS) $(DADD) $(LOPTS)
+ ifdef NAN_BUILDINFO
+ /bin/rm $(BUILDINFO_O)
+ endif
+
+$(DIR)/$(DEBUG_DIR)npTestPlugin$(SOEXT): $(NSPLUGLIB)
+ @echo "****> Link $@"
+ ifdef NAN_BUILDINFO
+ $(CCC) $(REL_CFLAGS) -DBUILD_DATE='"$(BUILD_DATE)"' -DBUILD_TIME='"$(BUILD_TIME)"' -DBUILD_PLATFORM='"$(CONFIG_GUESS)"' -DBUILD_TYPE='"dynamic"' $(BUILDINFO_C) -c -o $(BUILDINFO_O) -DNAN_BUILDINFO
+ endif
+ $(CCC) $(DYNLDFLAGS) -o $@ $(NSPLUGLIB) $(PLUGTESTLIB) $(LLIBS) $(DADD) $(LOPTS)
+ ifdef NAN_BUILDINFO
+ /bin/rm $(BUILDINFO_O)
+ endif
+endif
+
+$(DIR)/$(DEBUG_DIR)libblenderssr$(SOEXT): $(OBJS) $(SSRLIB1) $(COMLIB) $(SPLIB) $(SSRLIB)
+ @echo "****> Link $@"
+ ifdef NAN_BUILDINFO
+ $(CCC) $(REL_CFLAGS) -DBUILD_DATE='"$(BUILD_DATE)"' -DBUILD_TIME='"$(BUILD_TIME)"' -DBUILD_PLATFORM='"$(CONFIG_GUESS)"' -DBUILD_TYPE='"dynamic"' $(BUILDINFO_C) -c -o $(BUILDINFO_O) -DNAN_BUILDINFO
+ endif
+ $(CCC) $(DYNLDFLAGS) -o $@ $(BUILDINFO_O) $(OBJS) $(SSRLIB) $(SSRLIB1) $(COMLIB) $(SPLIB) $(PYPLAYERLIB) $(LLIBS) $(DADD) $(LOPTS)
+ ifdef NAN_BUILDINFO
+ /bin/rm $(BUILDINFO_O)
+ endif
+
diff --git a/source/blender/Makefile b/source/blender/Makefile
new file mode 100644
index 00000000000..acd297eed6e
--- /dev/null
+++ b/source/blender/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 *****
+#
+#
+
+include nan_definitions.mk
+
+DIRS = blenloader
+DIRS += deflate inflate encrypt decrypt sign verify
+DIRS += writestreamglue readstreamglue writeblenfile readblenfile
+DIRS += avi imbuf img misc render radiosity blenlib blenkernel blenpluginapi
+DIRS += bpython makesdna src renderconverter
+
+DIR = $(OCGDIR)/blender
+SOURCEDIR = source/blender
+TESTDIRS = deflate streamglue
+
+include nan_subdirs.mk
diff --git a/source/blender/avi/AVI_avi.h b/source/blender/avi/AVI_avi.h
new file mode 100644
index 00000000000..5932bbb12cf
--- /dev/null
+++ b/source/blender/avi/AVI_avi.h
@@ -0,0 +1,308 @@
+/**
+ * @mainpage AVI - AVI module external interface
+ *
+ * @section about About the AVI module
+ *
+ * This is external code. It provides avi file import/export and
+ * conversions. It has been adapted to make use of Blender memory
+ * management functions, and because of this it needs module
+ * blenlib. You need to provide this lib when linking with libavi.a .
+ *
+ * @section issues Known issues with AVI
+ *
+ * - avi uses mallocN, freeN from blenlib.
+ * - Not all functions that are used externally are properly
+ * prototyped.
+ *
+ * This header has not been split, since it interleaves type defines
+ * and functions. You would need the types to be able to include the
+ * function headers anyway. And, after all, it is someone else's
+ * code. So we keep it like this.
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 __AVI_H__
+#define __AVI_H__
+
+#include <stdio.h> /* for FILE */
+
+typedef struct _AviChunk {
+ int fcc;
+ int size;
+} AviChunk;
+
+typedef struct _AviList {
+ int fcc;
+ int size;
+ int ids;
+} AviList;
+
+typedef struct _AviMainHeader {
+ int fcc;
+ int size;
+ int MicroSecPerFrame; /* MicroSecPerFrame - timing between frames */
+ int MaxBytesPerSec; /* MaxBytesPerSec - approx bps system must handle */
+ int PaddingGranularity;
+ int Flags;
+#define AVIF_HASINDEX 0x00000010 /* had idx1 chunk */
+#define AVIF_MUSTUSEINDEX 0x00000020 /* must use idx1 chunk to determine order */
+#define AVIF_ISINTERLEAVED 0x00000100 /* AVI file is interleaved */
+#define AVIF_TRUSTCKTYPE 0x00000800
+#define AVIF_WASCAPTUREFILE 0x00010000 /* specially allocated used for capturing real time video */
+#define AVIF_COPYRIGHTED 0x00020000 /* contains copyrighted data */
+
+ int TotalFrames;
+ int InitialFrames; /* InitialFrames - initial frame before interleaving */
+ int Streams;
+ int SuggestedBufferSize;
+ int Width;
+ int Height;
+ int Reserved[4];
+} AviMainHeader;
+
+typedef struct _AviStreamHeader {
+ int fcc;
+ int size;
+ int Type;
+#define AVIST_VIDEO FCC("vids")
+#define AVIST_AUDIO FCC("auds")
+#define AVIST_MIDI FCC("mids")
+#define AVIST_TEXT FCC("txts")
+
+ int Handler;
+ int Flags;
+#define AVISF_DISABLED 0x00000001
+#define AVISF_VIDEO_PALCHANGES 0x00010000
+
+ short Priority;
+ short Language;
+ int InitialFrames;
+ int Scale;
+ int Rate;
+ int Start;
+ int Length;
+ int SuggestedBufferSize;
+ int Quality;
+ int SampleSize;
+ short left;
+ short top;
+ short right;
+ short bottom;
+} AviStreamHeader;
+
+typedef struct _AviBitmapInfoHeader {
+ int fcc;
+ int size;
+ int Size;
+ int Width;
+ int Height;
+ short Planes;
+ short BitCount;
+ int Compression;
+ int SizeImage;
+ int XPelsPerMeter;
+ int YPelsPerMeter;
+ int ClrUsed;
+ int ClrImportant;
+} AviBitmapInfoHeader;
+
+typedef struct _AviMJPEGUnknown {
+ int a;
+ int b;
+ int c;
+ int d;
+ int e;
+ int f;
+ int g;
+} AviMJPEGUnknown;
+
+typedef struct _AviIndexEntry {
+ int ChunkId;
+ int Flags;
+#define AVIIF_LIST 0x00000001
+#define AVIIF_KEYFRAME 0x00000010
+#define AVIIF_NO_TIME 0x00000100
+#define AVIIF_COMPRESSOR 0x0FFF0000
+ int Offset;
+ int Size;
+} AviIndexEntry;
+
+typedef struct _AviIndex {
+ int fcc;
+ int size;
+ AviIndexEntry *entrys;
+} AviIndex;
+
+typedef enum {
+ AVI_FORMAT_RGB24, /* The most basic of forms, 3 bytes per pixel, 1 per r, g, b */
+ AVI_FORMAT_RGB32, /* The second most basic of forms, 4 bytes per pixel, 1 per r, g, b, alpha */
+ AVI_FORMAT_AVI_RGB, /* Same as above, but is in the wierd AVI order (bottom to top, left to right) */
+ AVI_FORMAT_MJPEG /* Motion-JPEG */
+} AviFormat;
+
+typedef struct _AviStreamRec {
+ AviStreamHeader sh;
+ void *sf;
+ int sf_size;
+ AviFormat format;
+} AviStreamRec;
+
+typedef struct _AviMovie {
+ FILE *fp;
+
+ int type;
+#define AVI_MOVIE_READ 0
+#define AVI_MOVIE_WRITE 1
+
+ unsigned long size;
+
+ AviMainHeader *header;
+ AviStreamRec *streams;
+ AviIndexEntry *entries;
+ int index_entries;
+
+ int movi_offset;
+ int read_offset;
+ long *offset_table;
+
+ /* Local data goes here */
+ int interlace;
+ int odd_fields;
+} AviMovie;
+
+typedef enum {
+ AVI_ERROR_NONE=0,
+ AVI_ERROR_COMPRESSION,
+ AVI_ERROR_OPEN,
+ AVI_ERROR_READING,
+ AVI_ERROR_WRITING,
+ AVI_ERROR_FORMAT,
+ AVI_ERROR_ALLOC,
+ AVI_ERROR_FOUND,
+ AVI_ERROR_OPTION
+} AviError;
+
+/* belongs to the option-setting function. */
+typedef enum {
+ AVI_OPTION_WIDTH=0,
+ AVI_OPTION_HEIGHT,
+ AVI_OPTION_QUALITY,
+ AVI_OPTION_FRAMERATE
+} AviOption;
+
+/* The offsets that will always stay the same in AVI files we
+ * write... used to seek around to the places where we need to write
+ * the sizes */
+
+#define AVI_RIFF_SOFF 4L
+#define AVI_HDRL_SOFF 16L
+
+/**
+ * This is a sort of MAKE_ID thing. Used in imbuf :( It is used
+ * through options in the AVI header (AviStreamHeader). */
+#define FCC(ch4) (ch4[0] | ch4[1]<<8 | ch4[2]<<16 | ch4[3] << 24)
+
+/**
+ * Test whether this is an avi-format.
+ */
+int AVI_is_avi (char *name);
+
+
+/**
+ * Open a compressed file, decompress it into memory.
+ */
+AviError AVI_open_compress (char *name, AviMovie *movie, int streams, ...);
+
+/**
+ * Finalize a compressed output stream.
+ */
+AviError AVI_close_compress (AviMovie *movie);
+
+/**
+ * Choose a compression option for <movie>. Possible options are
+ * AVI_OPTION_TYPE_MAIN, AVI_OPTION_TYPE_STRH, AVI_OPTION_TYPE_STRF
+ */
+AviError AVI_set_compress_option (AviMovie *movie,
+ int option_type,
+ int stream,
+ AviOption option,
+ void *opt_data);
+/* Hmmm... there should be some explanantion about what these mean */
+/**
+ * Compression option, for use in avi_set_compress_option
+ */
+#define AVI_OPTION_TYPE_MAIN 0
+/**
+ * Compression option, for use in avi_set_compress_option
+ */
+#define AVI_OPTION_TYPE_STRH 1
+/**
+ * Compression option, for use in avi_set_compress_option
+ */
+#define AVI_OPTION_TYPE_STRF 2
+
+/**
+ * Direct the streams <avist_type> to <movie>. Redirect <stream_num>
+ * streams.
+ */
+int AVI_get_stream (AviMovie *movie, int avist_type, int stream_num);
+
+/**
+ * Open a movie stream from file.
+ */
+AviError AVI_open_movie (char *name, AviMovie *movie);
+
+/**
+ * Read a frame from a movie stream.
+ */
+void *AVI_read_frame (AviMovie *movie,
+ AviFormat format,
+ int frame,
+ int stream);
+/**
+ * Close an open movie stream.
+ */
+AviError AVI_close (AviMovie *movie);
+
+/**
+ * Write frames to a movie stream.
+ */
+AviError AVI_write_frame (AviMovie *movie, int frame_num, ...);
+
+/**
+ * Unused but still external
+ */
+AviError AVI_print_error (AviError error);
+void AVI_set_debug (int mode);
+
+#endif /* __AVI_H__ */
diff --git a/source/blender/avi/Makefile b/source/blender/avi/Makefile
new file mode 100644
index 00000000000..457eebbb516
--- /dev/null
+++ b/source/blender/avi/Makefile
@@ -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 *****
+#
+# Bounces make to subdirectories.
+
+SOURCEDIR = source/blender/avi
+DIRS = intern
+
+include nan_subdirs.mk
diff --git a/source/blender/avi/intern/Makefile b/source/blender/avi/intern/Makefile
new file mode 100644
index 00000000000..71e892e3db6
--- /dev/null
+++ b/source/blender/avi/intern/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 *****
+#
+#
+
+LIBNAME = avi
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+CFLAGS += $(LEVEL1_C_WARNINGS)
+
+ifeq ($(CPU),$(findstring $(CPU), "powerpc mips sparc"))
+ CPPFLAGS += -DWORDS_BIGENDIAN
+else
+ # alpha i386
+ CPPFLAGS += -DWORDS_LITTLEENDIAN
+endif
+
+# the JPEG library
+CPPFLAGS += -I$(NAN_JPEG)/include
+# path to the guarded memory allocator
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+# our own include
+CPPFLAGS += -I..
+
diff --git a/source/blender/avi/intern/avi.c b/source/blender/avi/intern/avi.c
new file mode 100644
index 00000000000..e822e81a7f3
--- /dev/null
+++ b/source/blender/avi/intern/avi.c
@@ -0,0 +1,835 @@
+/**
+ * avi.c
+ *
+ * This is external code.
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 <ctype.h>
+
+#include "AVI_avi.h"
+#include "avi_intern.h"
+
+#include "endian.h"
+
+static int AVI_DEBUG=0;
+static char DEBUG_FCC[4];
+
+#define DEBUG(x) if(AVI_DEBUG) printf("AVI DEBUG: " x);
+
+/* local functions */
+char *fcc_to_char (unsigned int fcc);
+char *tcc_to_char (unsigned int tcc);
+
+
+
+/* implemetation */
+
+unsigned int GET_FCC (FILE *fp) {
+ unsigned char tmp[4];
+
+ tmp[0] = getc(fp);
+ tmp[1] = getc(fp);
+ tmp[2] = getc(fp);
+ tmp[3] = getc(fp);
+
+ return FCC (tmp);
+}
+
+unsigned int GET_TCC (FILE *fp) {
+ char tmp[5];
+
+ tmp[0] = getc(fp);
+ tmp[1] = getc(fp);
+ tmp[2] = 0;
+ tmp[3] = 0;
+
+ return FCC (tmp);
+}
+
+char *fcc_to_char (unsigned int fcc) {
+ DEBUG_FCC[0]= (fcc)&0177;
+ DEBUG_FCC[1]= (fcc>>8)&0177;
+ DEBUG_FCC[2]= (fcc>>16)&0177;
+ DEBUG_FCC[3]= (fcc>>24)&0177;
+
+ return DEBUG_FCC;
+}
+
+char *tcc_to_char (unsigned int tcc) {
+ DEBUG_FCC[0]= (tcc)&0177;
+ DEBUG_FCC[1]= (tcc>>8)&0177;
+ DEBUG_FCC[2]= 0;
+ DEBUG_FCC[3]= 0;
+
+ return DEBUG_FCC;
+}
+
+int AVI_get_stream (AviMovie *movie, int avist_type, int stream_num) {
+ int cur_stream;
+
+ if (movie == NULL)
+ return -AVI_ERROR_OPTION;
+
+ for (cur_stream=0; cur_stream < movie->header->Streams; cur_stream++) {
+ if (movie->streams[cur_stream].sh.Type == avist_type) {
+ if (stream_num == 0)
+ return cur_stream;
+ else
+ stream_num--;
+ }
+ }
+
+ return -AVI_ERROR_FOUND;
+}
+
+static int fcc_get_stream (int fcc) {
+ char fccs[4];
+
+ fccs[0] = fcc;
+ fccs[1] = fcc>>8;
+ fccs[2] = fcc>>16;
+ fccs[3] = fcc>>24;
+
+ return 10*(fccs[0]-'0') + (fccs[1]-'0');
+}
+
+static int fcc_is_data (int fcc) {
+ char fccs[4];
+
+ fccs[0] = fcc;
+ fccs[1] = fcc>>8;
+ fccs[2] = fcc>>16;
+ fccs[3] = fcc>>24;
+
+ if (!isdigit (fccs[0]) || !isdigit (fccs[1]) || (fccs[2] != 'd' && fccs[2] != 'w'))
+ return 0;
+ if (fccs[3] != 'b' && fccs[3] != 'c')
+ return 0;
+
+ return 1;
+}
+
+AviError AVI_print_error (AviError in_error) {
+ int error;
+
+ if ((int) in_error < 0)
+ error = -in_error;
+ else
+ error = in_error;
+
+ switch (error) {
+ case AVI_ERROR_NONE:
+ break;
+ case AVI_ERROR_COMPRESSION:
+ printf ("AVI ERROR: compressed in an unsupported format\n");
+ break;
+ case AVI_ERROR_OPEN:
+ printf ("AVI ERROR: could not open file\n");
+ break;
+ case AVI_ERROR_READING:
+ printf ("AVI ERROR: could not read from file\n");
+ break;
+ case AVI_ERROR_WRITING:
+ printf ("AVI ERROR: could not write to file\n");
+ break;
+ case AVI_ERROR_FORMAT:
+ printf ("AVI ERROR: file is in an illegal or unrecognized format\n");
+ break;
+ case AVI_ERROR_ALLOC:
+ printf ("AVI ERROR: error encountered while allocating memory\n");
+ break;
+ case AVI_ERROR_OPTION:
+ printf ("AVI ERROR: program made illegal request\n");
+ break;
+ case AVI_ERROR_FOUND:
+ printf ("AVI ERROR: movie did not contain expected item\n");
+ break;
+ default:
+ break;
+ }
+
+ return in_error;
+}
+
+void AVI_set_debug (int mode) {
+ AVI_DEBUG= mode;
+}
+
+int AVI_is_avi (char *name) {
+ FILE *fp;
+ int ret;
+
+ fp = fopen (name, "rb");
+ if (fp == NULL)
+ return 0;
+
+ if (GET_FCC (fp) != FCC("RIFF") ||
+ !GET_FCC (fp) ||
+ GET_FCC (fp) != FCC("AVI ")) {
+ ret = 0;
+ } else {
+ ret = 1;
+ }
+
+ fclose(fp);
+ return ret;
+}
+
+AviError AVI_open_movie (char *name, AviMovie *movie) {
+ int temp, fcca, size;
+
+ DEBUG("opening movie\n");
+
+ memset(movie, 0, sizeof(AviMovie));
+
+ movie->type = AVI_MOVIE_READ;
+ movie->fp = fopen (name, "rb");
+ movie->offset_table = NULL;
+
+ if (movie->fp == NULL)
+ return AVI_ERROR_OPEN;
+
+ if (GET_FCC (movie->fp) != FCC("RIFF") ||
+ !(movie->size = GET_FCC (movie->fp)))
+ return AVI_ERROR_FORMAT;
+
+ movie->header = (AviMainHeader *) MEM_mallocN (sizeof (AviMainHeader), "movieheader");
+/* movie->header = (AviMainHeader *) malloc (sizeof (AviMainHeader)); */
+
+ if (GET_FCC (movie->fp) != FCC("AVI ") ||
+ GET_FCC (movie->fp) != FCC("LIST") ||
+ !GET_FCC (movie->fp) ||
+ GET_FCC (movie->fp) != FCC("hdrl") ||
+ (movie->header->fcc = GET_FCC (movie->fp)) != FCC("avih") ||
+ !(movie->header->size = GET_FCC (movie->fp))) {
+ DEBUG("bad initial header info\n");
+ return AVI_ERROR_FORMAT;
+ }
+
+ movie->header->MicroSecPerFrame = GET_FCC(movie->fp);
+ movie->header->MaxBytesPerSec = GET_FCC(movie->fp);
+ movie->header->PaddingGranularity = GET_FCC(movie->fp);
+ movie->header->Flags = GET_FCC(movie->fp);
+ movie->header->TotalFrames = GET_FCC(movie->fp);
+ movie->header->InitialFrames = GET_FCC(movie->fp);
+ movie->header->Streams = GET_FCC(movie->fp);
+ movie->header->SuggestedBufferSize = GET_FCC(movie->fp);
+ movie->header->Width = GET_FCC(movie->fp);
+ movie->header->Height = GET_FCC(movie->fp);
+ movie->header->Reserved[0] = GET_FCC(movie->fp);
+ movie->header->Reserved[1] = GET_FCC(movie->fp);
+ movie->header->Reserved[2] = GET_FCC(movie->fp);
+ movie->header->Reserved[3] = GET_FCC(movie->fp);
+
+ fseek (movie->fp, movie->header->size-14*4, SEEK_CUR);
+
+ if (movie->header->Streams < 1) {
+ DEBUG("streams less than 1\n");
+ return AVI_ERROR_FORMAT;
+ }
+
+ movie->streams = (AviStreamRec *) MEM_callocN (sizeof(AviStreamRec) * movie->header->Streams, "moviestreams");
+/* movie->streams = (AviStreamRec *) */
+/* malloc (sizeof(AviStreamRec) * movie->header->Streams); */
+
+ for (temp=0; temp < movie->header->Streams; temp++) {
+
+ if (GET_FCC(movie->fp) != FCC("LIST") ||
+ !GET_FCC (movie->fp) ||
+ GET_FCC (movie->fp) != FCC ("strl") ||
+ (movie->streams[temp].sh.fcc = GET_FCC (movie->fp)) != FCC ("strh") ||
+ !(movie->streams[temp].sh.size = GET_FCC (movie->fp))) {
+ DEBUG("bad stream header information\n");
+ return AVI_ERROR_FORMAT;
+ }
+
+ movie->streams[temp].sh.Type = GET_FCC (movie->fp);
+ movie->streams[temp].sh.Handler = GET_FCC (movie->fp);
+
+ fcca = movie->streams[temp].sh.Handler;
+
+ if (movie->streams[temp].sh.Type == FCC("vids")) {
+ if (fcca == FCC ("DIB ") ||
+ fcca == FCC ("RGB ") ||
+ fcca == FCC ("rgb ") ||
+ fcca == FCC ("RAW ") ||
+ fcca == 0) {
+ movie->streams[temp].format = AVI_FORMAT_AVI_RGB;
+ } else if (fcca == FCC ("mjpg")||fcca == FCC ("MJPG")) {
+ movie->streams[temp].format = AVI_FORMAT_MJPEG;
+ } else {
+ return AVI_ERROR_COMPRESSION;
+ }
+ }
+
+ movie->streams[temp].sh.Flags = GET_FCC (movie->fp);
+ movie->streams[temp].sh.Priority = GET_TCC (movie->fp);
+ movie->streams[temp].sh.Language = GET_TCC (movie->fp);
+ movie->streams[temp].sh.InitialFrames = GET_FCC (movie->fp);
+ movie->streams[temp].sh.Scale = GET_FCC (movie->fp);
+ movie->streams[temp].sh.Rate = GET_FCC (movie->fp);
+ movie->streams[temp].sh.Start = GET_FCC (movie->fp);
+ movie->streams[temp].sh.Length = GET_FCC (movie->fp);
+ movie->streams[temp].sh.SuggestedBufferSize = GET_FCC (movie->fp);
+ movie->streams[temp].sh.Quality = GET_FCC (movie->fp);
+ movie->streams[temp].sh.SampleSize = GET_FCC (movie->fp);
+ movie->streams[temp].sh.left = GET_TCC (movie->fp);
+ movie->streams[temp].sh.top = GET_TCC (movie->fp);
+ movie->streams[temp].sh.right = GET_TCC (movie->fp);
+ movie->streams[temp].sh.bottom = GET_TCC (movie->fp);
+
+ fseek (movie->fp, movie->streams[temp].sh.size-14*4, SEEK_CUR);
+
+ if (GET_FCC (movie->fp) != FCC("strf")) {
+ DEBUG("no stream format information\n");
+ return AVI_ERROR_FORMAT;
+ }
+
+ movie->streams[temp].sf_size= GET_FCC(movie->fp);
+ if (movie->streams[temp].sh.Type == FCC("vids")) {
+ if (movie->streams[temp].sf_size == sizeof(AviBitmapInfoHeader)-8) {
+ AviBitmapInfoHeader *bi;
+
+ movie->streams[temp].sf= MEM_mallocN(sizeof(AviBitmapInfoHeader), "streamformat");
+/* movie->streams[temp].sf= malloc(sizeof(AviBitmapInfoHeader)); */
+
+ bi= (AviBitmapInfoHeader *) movie->streams[temp].sf;
+
+ bi->fcc= FCC("strf");
+ bi->size= movie->streams[temp].sf_size;
+ bi->Size= GET_FCC(movie->fp);
+ bi->Width= GET_FCC(movie->fp);
+ bi->Height= GET_FCC(movie->fp);
+ bi->Planes= GET_TCC(movie->fp);
+ bi->BitCount= GET_TCC(movie->fp);
+ bi->Compression= GET_FCC(movie->fp);
+ bi->SizeImage= GET_FCC(movie->fp);
+ bi->XPelsPerMeter= GET_FCC(movie->fp);
+ bi->YPelsPerMeter= GET_FCC(movie->fp);
+ bi->ClrUsed= GET_FCC(movie->fp);
+ bi->ClrImportant= GET_FCC(movie->fp);
+
+ fcca = bi->Compression;
+
+ if (fcca == FCC ("DIB ") ||
+ fcca == FCC ("RGB ") ||
+ fcca == FCC ("rgb ") ||
+ fcca == FCC ("RAW ") ||
+ fcca == FCC ("mjpg") ||
+ fcca == FCC ("MJPG") ||
+ fcca == 0) {
+ } else {
+ return AVI_ERROR_COMPRESSION;
+ }
+
+ } else fseek (movie->fp, movie->streams[temp].sf_size, SEEK_CUR);
+ } else fseek (movie->fp, movie->streams[temp].sf_size, SEEK_CUR);
+
+ /* Walk to the next LIST */
+ while (GET_FCC (movie->fp) != FCC("LIST")) {
+ temp= GET_FCC (movie->fp);
+ if (temp<0 || ftell(movie->fp) > movie->size) {
+ DEBUG("incorrect size in header or error in AVI\n");
+ return AVI_ERROR_FORMAT;
+ }
+ fseek(movie->fp, temp, SEEK_CUR);
+ }
+
+ fseek(movie->fp, -4L, SEEK_CUR);
+ }
+
+ while (1) {
+ temp = GET_FCC (movie->fp);
+ size = GET_FCC (movie->fp);
+
+ if (size == 0)
+ break;
+
+ if (temp == FCC("LIST")) {
+ if (GET_FCC(movie->fp) == FCC ("movi"))
+ break;
+ else
+ fseek (movie->fp, size-4, SEEK_CUR);
+ } else {
+ fseek (movie->fp, size, SEEK_CUR);
+ }
+ if (ftell(movie->fp) > movie->size) {
+ DEBUG("incorrect size in header or error in AVI\n");
+ return AVI_ERROR_FORMAT;
+ }
+ }
+
+ movie->movi_offset = ftell (movie->fp);
+ movie->read_offset = movie->movi_offset;
+ if (AVI_DEBUG) printf ("movi_offset is %d\n", movie->movi_offset);
+
+ /* Read in the index if the file has one, otherwise create one */
+ if (movie->header->Flags & AVIF_HASINDEX) {
+ fseek(movie->fp, size-4, SEEK_CUR);
+
+ if (GET_FCC(movie->fp) != FCC("idx1")) {
+ DEBUG("bad index informatio\n");
+ return AVI_ERROR_FORMAT;
+ }
+
+ movie->index_entries = GET_FCC (movie->fp)/sizeof(AviIndexEntry);
+ if (movie->index_entries == 0) {
+ DEBUG("no index entries\n");
+ return AVI_ERROR_FORMAT;
+ }
+
+ movie->entries = (AviIndexEntry *) MEM_mallocN (movie->index_entries * sizeof(AviIndexEntry),"movieentries");
+/* movie->entries = (AviIndexEntry *) */
+/* malloc (movie->index_entries * sizeof(AviIndexEntry)); */
+
+ for (temp=0; temp < movie->index_entries; temp++) {
+ movie->entries[temp].ChunkId = GET_FCC (movie->fp);
+ movie->entries[temp].Flags = GET_FCC (movie->fp);
+ movie->entries[temp].Offset = GET_FCC (movie->fp);
+ movie->entries[temp].Size = GET_FCC (movie->fp);
+
+ if (AVI_DEBUG) printf ("Index entry %04d: ChunkId:%s Flags:%d Offset:%d Size:%d\n", temp, fcc_to_char(movie->entries[temp].ChunkId), movie->entries[temp].Flags, movie->entries[temp].Offset, movie->entries[temp].Size);
+ }
+
+/* Some AVI's have offset entries in absolute coordinates
+ * instead of an offset from the movie beginning... this is...
+ * wacky, but we need to handle it. The wacky offset always
+ * starts at movi_offset it seems... so we'll check that.
+ * Note the the offset needs an extra 4 bytes for some
+ * undetermined reason */
+
+ if (movie->entries[0].Offset == movie->movi_offset)
+ movie->read_offset= 4;
+ }
+
+ DEBUG("movie succesfully opened\n");
+ return AVI_ERROR_NONE;
+}
+
+void *AVI_read_frame (AviMovie *movie, AviFormat format, int frame, int stream) {
+ int cur_frame=-1, i=0, temp;
+ void *buffer;
+
+ /* Retrieve the record number of the desired frame in the index */
+
+ while (cur_frame < frame && i < movie->index_entries) {
+ if (fcc_is_data (movie->entries[i].ChunkId) &&
+ fcc_get_stream (movie->entries[i].ChunkId) == stream)
+ cur_frame++;
+
+ i++;
+ }
+
+ if (cur_frame != frame) return NULL;
+
+ fseek (movie->fp, movie->read_offset + movie->entries[i-1].Offset, SEEK_SET);
+
+ temp = GET_FCC(movie->fp);
+ buffer = MEM_mallocN (temp,"readbuffer");
+/* buffer = malloc(temp); */
+
+ if (fread (buffer, 1, temp, movie->fp) != temp) {
+ MEM_freeN(buffer);
+/* free(buffer); */
+
+ return NULL;
+ }
+
+ buffer = avi_format_convert (movie, stream, buffer, movie->streams[stream].format, format, &temp);
+
+ return buffer;
+}
+
+AviError AVI_close (AviMovie *movie) {
+ int i;
+
+ fclose (movie->fp);
+
+ for (i=0; i < movie->header->Streams; i++) {
+ if (movie->streams[i].sf != NULL)
+ MEM_freeN (movie->streams[i].sf);
+ }
+
+ if (movie->header != NULL)
+ MEM_freeN (movie->header);
+ if (movie->streams!= NULL)
+ MEM_freeN (movie->streams);
+ if (movie->entries != NULL)
+ MEM_freeN (movie->entries);
+ if (movie->offset_table != NULL)
+ MEM_freeN (movie->offset_table);
+
+ return AVI_ERROR_NONE;
+}
+
+AviError AVI_open_compress (char *name, AviMovie *movie, int streams, ...) {
+ va_list ap;
+ AviList list;
+ AviChunk chunk;
+ int i;
+ int header_pos1, header_pos2;
+ int stream_pos1, stream_pos2;
+
+ movie->type = AVI_MOVIE_WRITE;
+ movie->fp = fopen (name, "wb");
+
+ movie->index_entries = 0;
+
+ if (movie->fp == NULL)
+ return AVI_ERROR_OPEN;
+
+ movie->offset_table = (long *) MEM_mallocN ((1+streams*2) * sizeof (long),"offsettable");
+/* movie->offset_table = (long *) malloc ((1+streams*2) * sizeof (long)); */
+
+ for (i=0; i < 1 + streams*2; i++)
+ movie->offset_table[i] = -1L;
+
+ movie->entries = NULL;
+
+ movie->header = (AviMainHeader *) MEM_mallocN (sizeof(AviMainHeader),"movieheader");
+/* movie->header = (AviMainHeader *) malloc (sizeof(AviMainHeader)); */
+
+ movie->header->fcc = FCC("avih");
+ movie->header->size = 56;
+ movie->header->MicroSecPerFrame = 66667;
+ movie->header->MaxBytesPerSec = 0;
+ movie->header->PaddingGranularity = 0;
+ movie->header->Flags = AVIF_HASINDEX | AVIF_MUSTUSEINDEX;
+ movie->header->TotalFrames = 0;
+ movie->header->InitialFrames = 0;
+ movie->header->Streams = streams;
+ movie->header->SuggestedBufferSize = 0;
+ movie->header->Width = 0;
+ movie->header->Height = 0;
+ movie->header->Reserved[0] = 0;
+ movie->header->Reserved[1] = 0;
+ movie->header->Reserved[2] = 0;
+ movie->header->Reserved[3] = 0;
+
+ movie->streams = (AviStreamRec *) MEM_mallocN (sizeof(AviStreamRec) * movie->header->Streams,"moviestreams");
+/* movie->streams = (AviStreamRec *) malloc (sizeof(AviStreamRec) * movie->header->Streams); */
+
+ va_start (ap, streams);
+
+ for (i=0; i < movie->header->Streams; i++) {
+ movie->streams[i].format = va_arg(ap, AviFormat);
+
+ movie->streams[i].sh.fcc = FCC ("strh");
+ movie->streams[i].sh.size = 56;
+ movie->streams[i].sh.Type = avi_get_format_type (movie->streams[i].format);
+ if (movie->streams[i].sh.Type == 0)
+ return AVI_ERROR_FORMAT;
+
+ movie->streams[i].sh.Handler = avi_get_format_fcc (movie->streams[i].format);
+ if (movie->streams[i].sh.Handler == 0)
+ return AVI_ERROR_FORMAT;
+
+ movie->streams[i].sh.Flags = 0;
+ movie->streams[i].sh.Priority = 0;
+ movie->streams[i].sh.Language = 0;
+ movie->streams[i].sh.InitialFrames = 0;
+ movie->streams[i].sh.Scale = 66667;
+ movie->streams[i].sh.Rate = 1000000;
+ movie->streams[i].sh.Start = 0;
+ movie->streams[i].sh.Length = 0;
+ movie->streams[i].sh.SuggestedBufferSize = 0;
+ movie->streams[i].sh.Quality = 10000;
+ movie->streams[i].sh.SampleSize = 0;
+ movie->streams[i].sh.left = 0;
+ movie->streams[i].sh.top = 0;
+ movie->streams[i].sh.right = 0;
+ movie->streams[i].sh.bottom = 0;
+
+ if (movie->streams[i].sh.Type == FCC("vids")) {
+ if (movie->streams[i].format == AVI_FORMAT_MJPEG) {
+ movie->streams[i].sf = MEM_mallocN (sizeof(AviBitmapInfoHeader)
+ + sizeof(AviMJPEGUnknown),"moviestreamformatL");
+/* movie->streams[i].sf = malloc (sizeof(AviBitmapInfoHeader) */
+/* + sizeof(AviMJPEGUnknown)); */
+ movie->streams[i].sf_size = sizeof(AviBitmapInfoHeader) + sizeof(AviMJPEGUnknown);
+ } else {
+ movie->streams[i].sf = MEM_mallocN (sizeof(AviBitmapInfoHeader), "moviestreamformatS");
+/* movie->streams[i].sf = malloc (sizeof(AviBitmapInfoHeader)); */
+ movie->streams[i].sf_size = sizeof(AviBitmapInfoHeader);
+ }
+ ((AviBitmapInfoHeader *) movie->streams[i].sf)->fcc = FCC ("strf");
+ ((AviBitmapInfoHeader *) movie->streams[i].sf)->size = movie->streams[i].sf_size - 8;
+ ((AviBitmapInfoHeader *) movie->streams[i].sf)->Size = movie->streams[i].sf_size - 8;
+ ((AviBitmapInfoHeader *) movie->streams[i].sf)->Width = 0;
+ ((AviBitmapInfoHeader *) movie->streams[i].sf)->Height = 0;
+ ((AviBitmapInfoHeader *) movie->streams[i].sf)->Planes = 1;
+ ((AviBitmapInfoHeader *) movie->streams[i].sf)->BitCount = 24;
+ ((AviBitmapInfoHeader *) movie->streams[i].sf)->Compression = avi_get_format_compression (movie->streams[i].format);
+ ((AviBitmapInfoHeader *) movie->streams[i].sf)->SizeImage = 0;
+ ((AviBitmapInfoHeader *) movie->streams[i].sf)->XPelsPerMeter = 0;
+ ((AviBitmapInfoHeader *) movie->streams[i].sf)->YPelsPerMeter = 0;
+ ((AviBitmapInfoHeader *) movie->streams[i].sf)->ClrUsed = 0;
+ ((AviBitmapInfoHeader *) movie->streams[i].sf)->ClrImportant = 0;
+
+ if (movie->streams[i].format == AVI_FORMAT_MJPEG) {
+ AviMJPEGUnknown *tmp;
+
+ tmp = (AviMJPEGUnknown *) ((char*) movie->streams[i].sf +sizeof(AviBitmapInfoHeader));
+
+ tmp->a = 44;
+ tmp->b = 24;
+ tmp->c = 0;
+ tmp->d = 2;
+ tmp->e = 8;
+ tmp->f = 2;
+ tmp->g = 1;
+ }
+ } else if (movie->streams[i].sh.Type == FCC("auds")) {
+ ;
+ }
+ }
+
+ list.fcc = FCC("RIFF");
+ list.size = 0;
+ list.ids = FCC("AVI ");
+
+ awrite (movie, &list, 1, sizeof(AviList), movie->fp, AVI_LIST);
+
+ list.fcc = FCC("LIST");
+ list.size = 0;
+ list.ids = FCC("hdrl");
+
+ awrite (movie, &list, 1, sizeof(AviList), movie->fp, AVI_LIST);
+
+ header_pos1 = ftell(movie->fp);
+
+ movie->offset_table[0] = ftell(movie->fp);
+
+ awrite (movie, movie->header, 1, sizeof(AviMainHeader), movie->fp, AVI_MAINH);
+
+ for (i=0; i < movie->header->Streams; i++) {
+ list.fcc = FCC("LIST");
+ list.size = 0;
+ list.ids = FCC("strl");
+
+ awrite (movie, &list, 1, sizeof(AviList), movie->fp, AVI_LIST);
+
+ stream_pos1 = ftell(movie->fp);
+
+ movie->offset_table[1+i*2] = ftell(movie->fp);
+ awrite (movie, &movie->streams[i].sh, 1, sizeof(AviStreamHeader), movie->fp, AVI_STREAMH);
+
+ movie->offset_table[1+i*2+1] = ftell(movie->fp);
+ awrite (movie, movie->streams[i].sf, 1, movie->streams[i].sf_size, movie->fp, AVI_BITMAPH);
+
+ stream_pos2 = ftell(movie->fp);
+
+ fseek (movie->fp, stream_pos1-8, SEEK_SET);
+
+ PUT_FCCN((stream_pos2-stream_pos1+4L), movie->fp);
+
+ fseek (movie->fp, stream_pos2, SEEK_SET);
+ }
+
+ if (ftell(movie->fp) < 2024 - 8) {
+ chunk.fcc = FCC("JUNK");
+ chunk.size = 2024-8-ftell(movie->fp);
+
+ awrite (movie, &chunk, 1, sizeof(AviChunk), movie->fp, AVI_CHUNK);
+
+ for (i=0; i < chunk.size; i++)
+ putc(0, movie->fp);
+ }
+
+ header_pos2 = ftell(movie->fp);
+
+ list.fcc = FCC("LIST");
+ list.size = 0;
+ list.ids = FCC("movi");
+
+ awrite (movie, &list, 1, sizeof(AviList), movie->fp, AVI_LIST);
+
+ movie->movi_offset = ftell(movie->fp)-8L;
+
+ fseek (movie->fp, AVI_HDRL_SOFF, SEEK_SET);
+
+ PUT_FCCN((header_pos2-header_pos1+4L), movie->fp);
+
+ return AVI_ERROR_NONE;
+}
+
+AviError AVI_write_frame (AviMovie *movie, int frame_num, ...) {
+ AviList list;
+ AviChunk chunk;
+ AviIndexEntry *temp;
+ va_list ap;
+ int stream;
+ long rec_off;
+ AviFormat format;
+ void *buffer;
+ int size;
+
+ if (frame_num < 0)
+ return AVI_ERROR_OPTION;
+
+ /* Allocate the new memory for the index entry */
+
+ if (frame_num+1 > movie->index_entries) {
+ temp = (AviIndexEntry *) MEM_mallocN ((frame_num+1) *
+ (movie->header->Streams+1) * sizeof(AviIndexEntry),"newidxentry");
+ if (movie->entries != NULL) {
+ memcpy (temp, movie->entries, movie->index_entries * (movie->header->Streams+1)
+ * sizeof(AviIndexEntry));
+ MEM_freeN (movie->entries);
+ }
+
+ movie->entries = temp;
+ movie->index_entries = frame_num+1;
+ }
+
+ /* Slap a new record entry onto the end of the file */
+
+ fseek (movie->fp, 0L, SEEK_END);
+
+ list.fcc = FCC("LIST");
+ list.size = 0;
+ list.ids = FCC("rec ");
+
+ awrite (movie, &list, 1, sizeof(AviList), movie->fp, AVI_LIST);
+
+ rec_off = ftell (movie->fp)-8L;
+
+ /* Write a frame for every stream */
+
+ va_start (ap, frame_num);
+
+ for (stream=0; stream < movie->header->Streams; stream++) {
+ unsigned int tbuf=0;
+
+ format = va_arg (ap, AviFormat);
+ buffer = va_arg (ap, void*);
+ size = va_arg (ap, int);
+
+ /* Convert the buffer into the output format */
+ buffer = avi_format_convert (movie, stream, buffer, format, movie->streams[stream].format, &size);
+
+ /* Write the header info for this data chunk */
+
+ fseek (movie->fp, 0L, SEEK_END);
+
+ chunk.fcc = avi_get_data_id (format, stream);
+ chunk.size = size;
+
+ if (size%4) chunk.size += 4 - size%4;
+
+ awrite (movie, &chunk, 1, sizeof(AviChunk), movie->fp, AVI_CHUNK);
+
+ /* Write the index entry for this data chunk */
+
+ movie->entries[frame_num * (movie->header->Streams+1) + stream + 1].ChunkId = chunk.fcc;
+ movie->entries[frame_num * (movie->header->Streams+1) + stream + 1].Flags = AVIIF_KEYFRAME;
+ movie->entries[frame_num * (movie->header->Streams+1) + stream + 1].Offset = ftell(movie->fp)-12L-movie->movi_offset;
+ movie->entries[frame_num * (movie->header->Streams+1) + stream + 1].Size = chunk.size;
+
+ /* Write the chunk */
+ awrite (movie, buffer, 1, size, movie->fp, AVI_RAW);
+ MEM_freeN (buffer);
+
+ if (size%4) awrite (movie, &tbuf, 1, 4-size%4, movie->fp, AVI_RAW);
+
+ /* Update the stream headers length field */
+ movie->streams[stream].sh.Length++;
+ fseek (movie->fp, movie->offset_table[1+stream*2], SEEK_SET);
+ awrite (movie, &movie->streams[stream].sh, 1, sizeof(AviStreamHeader), movie->fp, AVI_STREAMH);
+ }
+ va_end (ap);
+
+ /* Record the entry for the new record */
+
+ fseek (movie->fp, 0L, SEEK_END);
+
+ movie->entries[frame_num * (movie->header->Streams+1)].ChunkId = FCC("rec ");
+ movie->entries[frame_num * (movie->header->Streams+1)].Flags = AVIIF_LIST;
+ movie->entries[frame_num * (movie->header->Streams+1)].Offset = rec_off-8L-movie->movi_offset;
+ movie->entries[frame_num * (movie->header->Streams+1)].Size = ftell(movie->fp)-(rec_off+4L);
+
+ /* Update the record size */
+ fseek (movie->fp, rec_off, SEEK_SET);
+ PUT_FCCN (movie->entries[frame_num * (movie->header->Streams+1)].Size, movie->fp);
+
+ /* Update the main header information in the file */
+ movie->header->TotalFrames++;
+ fseek (movie->fp, movie->offset_table[0], SEEK_SET);
+ awrite (movie, movie->header, 1, sizeof(AviMainHeader), movie->fp, AVI_MAINH);
+
+ return AVI_ERROR_NONE;
+}
+
+AviError AVI_close_compress (AviMovie *movie) {
+ int temp, movi_size, i;
+
+ fseek (movie->fp, 0L, SEEK_END);
+ movi_size = ftell (movie->fp);
+
+ PUT_FCC ("idx1", movie->fp);
+ PUT_FCCN ((movie->index_entries*(movie->header->Streams+1)*16), movie->fp);
+
+ for (temp=0; temp < movie->index_entries*(movie->header->Streams+1); temp++)
+ awrite (movie, &movie->entries[temp], 1, sizeof(AviIndexEntry), movie->fp, AVI_INDEXE);
+
+ temp = ftell (movie->fp);
+
+ fseek (movie->fp, AVI_RIFF_SOFF, SEEK_SET);
+
+ PUT_FCCN((temp-8L), movie->fp);
+
+ fseek (movie->fp, movie->movi_offset, SEEK_SET);
+
+ PUT_FCCN((movi_size-(movie->movi_offset+4L)),movie->fp);
+
+ fclose (movie->fp);
+
+ for (i=0; i < movie->header->Streams; i++) {
+ if (movie->streams[i].sf != NULL)
+ MEM_freeN (movie->streams[i].sf);
+ }
+ if (movie->header != NULL)
+ MEM_freeN (movie->header);
+ if (movie->entries != NULL)
+ MEM_freeN (movie->entries);
+ if (movie->streams != NULL)
+ MEM_freeN (movie->streams);
+ if (movie->offset_table != NULL)
+ MEM_freeN (movie->offset_table);
+ return AVI_ERROR_NONE;
+}
diff --git a/source/blender/avi/intern/avi_intern.h b/source/blender/avi/intern/avi_intern.h
new file mode 100644
index 00000000000..9aa95524af8
--- /dev/null
+++ b/source/blender/avi/intern/avi_intern.h
@@ -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 *****
+ */
+#ifndef AVI_INTERN_H
+#define AVI_INTERN_H
+
+#include <stdio.h> /* for FILE */
+
+#include "MEM_guardedalloc.h"
+
+unsigned int GET_FCC (FILE *fp);
+unsigned int GET_TCC (FILE *fp);
+
+#define PUT_FCC(ch4, fp) putc(ch4[0],fp); putc(ch4[1],fp); putc(ch4[2],fp); putc(ch4[3],fp)
+#define PUT_FCCN(num, fp) putc((num>>0)&0377,fp); putc((num>>8)&0377,fp); putc((num>>16)&0377,fp); putc((num>>24)&0377,fp)
+#define PUT_TCC(ch2, fp) putc(ch2[0],fp); putc(ch2[1],fp)
+
+void *avi_format_convert (AviMovie *movie, int stream, void *buffer, AviFormat from, AviFormat to, int *size);
+
+int avi_get_data_id(AviFormat format, int stream);
+int avi_get_format_type(AviFormat format);
+int avi_get_format_fcc(AviFormat format);
+int avi_get_format_compression(AviFormat format);
+
+#endif
diff --git a/source/blender/avi/intern/avirgb.c b/source/blender/avi/intern/avirgb.c
new file mode 100644
index 00000000000..051c351a0f8
--- /dev/null
+++ b/source/blender/avi/intern/avirgb.c
@@ -0,0 +1,144 @@
+/**
+ * avirgb.c
+ *
+ * This is external code. Converts rgb-type avi-s.
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "AVI_avi.h"
+#include <stdlib.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+#include "avirgb.h"
+
+/* implementation */
+
+void *avi_converter_from_avi_rgb (AviMovie *movie, int stream, unsigned char *buffer, int *size) {
+ int x, y,i, rowstride;
+ unsigned char *buf;
+ AviBitmapInfoHeader *bi;
+ short bits= 32;
+
+ bi= (AviBitmapInfoHeader *) movie->streams[stream].sf;
+ if (bi) bits= bi->BitCount;
+
+ if (bits==16) {
+ unsigned short *pxl;
+ unsigned char *to;
+ #ifdef WORDS_BIGENDIAN
+ unsigned char *pxla;
+ #endif
+
+ buf = MEM_mallocN (movie->header->Height * movie->header->Width * 3, "fromavirgbbuf");
+
+ y= movie->header->Height;
+ to= buf;
+
+ while (y--) {
+ pxl= (unsigned short *) (buffer + y * movie->header->Width * 2);
+
+ #ifdef WORDS_BIGENDIAN
+ pxla= (unsigned char *)pxl;
+ #endif
+
+ x= movie->header->Width;
+ while (x--) {
+ #ifdef WORDS_BIGENDIAN
+ i= pxla[0];
+ pxla[0]= pxla[1];
+ pxla[1]= i;
+
+ pxla+=2;
+ #endif
+
+ *(to++)= ((*pxl>>10)&0x1f)*8;
+ *(to++)= ((*pxl>>5)&0x1f)*8;
+ *(to++)= (*pxl&0x1f)*8;
+ pxl++;
+ }
+ }
+
+ MEM_freeN (buffer);
+
+ return buf;
+ } else {
+ buf = MEM_mallocN (movie->header->Height * movie->header->Width * 3, "fromavirgbbuf");
+
+ rowstride = movie->header->Width*3;
+ if (bits!=16) if (movie->header->Width%2) rowstride++;
+
+ for (y=0; y < movie->header->Height; y++) {
+ memcpy (&buf[y*movie->header->Width*3], &buffer[((movie->header->Height-1)-y)*rowstride], movie->header->Width*3);
+ }
+
+ for (y=0; y < movie->header->Height*movie->header->Width*3; y+=3) {
+ i = buf[y];
+ buf[y] = buf[y+2];
+ buf[y+2] = i;
+ }
+
+ MEM_freeN (buffer);
+
+ return buf;
+ }
+}
+
+void *avi_converter_to_avi_rgb (AviMovie *movie, int stream, unsigned char *buffer, int *size) {
+ int y, x, i, rowstride;
+ unsigned char *buf;
+
+ *size= movie->header->Height * movie->header->Width * 3;
+ if (movie->header->Width%2) *size+= movie->header->Height;
+
+ buf = MEM_mallocN (*size,"toavirgbbuf");
+
+ rowstride = movie->header->Width*3;
+ if (movie->header->Width%2) rowstride++;
+
+ for (y=0; y < movie->header->Height; y++) {
+ memcpy (&buf[y*rowstride], &buffer[((movie->header->Height-1)-y)*movie->header->Width*3], movie->header->Width*3);
+ }
+
+ for (y=0; y < movie->header->Height; y++) {
+ for (x=0; x < movie->header->Width*3; x+=3) {
+ i = buf[y*rowstride+x];
+ buf[y*rowstride+x] = buf[y*rowstride+x+2];
+ buf[y*rowstride+x+2] = i;
+ }
+ }
+
+ MEM_freeN (buffer);
+
+ return buf;
+}
diff --git a/source/blender/avi/intern/avirgb.h b/source/blender/avi/intern/avirgb.h
new file mode 100644
index 00000000000..56b22af4eb8
--- /dev/null
+++ b/source/blender/avi/intern/avirgb.h
@@ -0,0 +1,33 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 *avi_converter_from_avi_rgb (AviMovie *movie, int stream, unsigned char *buffer, int *size);
+void *avi_converter_to_avi_rgb (AviMovie *movie, int stream, unsigned char *buffer, int *size);
diff --git a/source/blender/avi/intern/codecs.c b/source/blender/avi/intern/codecs.c
new file mode 100644
index 00000000000..fa44dd46c41
--- /dev/null
+++ b/source/blender/avi/intern/codecs.c
@@ -0,0 +1,143 @@
+/**
+ * codecs.c
+ *
+ * This is external code. Identify and convert different avi-files.
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "AVI_avi.h"
+#include "avi_intern.h"
+
+#include "avirgb.h"
+#include "mjpeg.h"
+#include "rgb32.h"
+
+void *avi_format_convert (AviMovie *movie, int stream, void *buffer, AviFormat from, AviFormat to, int *size) {
+ if (from == to)
+ return buffer;
+
+ if (from != AVI_FORMAT_RGB24 &&
+ to != AVI_FORMAT_RGB24)
+ return avi_format_convert(movie, stream,
+ avi_format_convert (movie, stream, buffer, from, AVI_FORMAT_RGB24, size),
+ AVI_FORMAT_RGB24, to, size);
+
+ switch (to) {
+ case AVI_FORMAT_RGB24:
+ switch (from) {
+ case AVI_FORMAT_AVI_RGB:
+ buffer = avi_converter_from_avi_rgb (movie, stream, buffer, size);
+ break;
+ case AVI_FORMAT_MJPEG:
+ buffer = avi_converter_from_mjpeg (movie, stream, buffer, size);
+ break;
+ case AVI_FORMAT_RGB32:
+ buffer = avi_converter_from_rgb32 (movie, stream, buffer, size);
+ break;
+ default:
+ break;
+ }
+ break;
+ case AVI_FORMAT_AVI_RGB:
+ buffer = avi_converter_to_avi_rgb (movie, stream, buffer, size);
+ break;
+ case AVI_FORMAT_MJPEG:
+ buffer = avi_converter_to_mjpeg (movie, stream, buffer, size);
+ break;
+ case AVI_FORMAT_RGB32:
+ buffer = avi_converter_to_rgb32 (movie, stream, buffer, size);
+ break;
+ default:
+ break;
+ }
+
+ return buffer;
+}
+
+int avi_get_data_id (AviFormat format, int stream) {
+ char fcc[5];
+
+ if (avi_get_format_type (format) == FCC("vids"))
+ sprintf (fcc,"%2.2ddc",stream);
+ else if (avi_get_format_type (format) == FCC("auds"))
+ sprintf (fcc,"%2.2ddc",stream);
+ else
+ return 0;
+
+ return FCC(fcc);
+}
+
+int avi_get_format_type (AviFormat format) {
+ switch (format) {
+ case AVI_FORMAT_RGB24:
+ case AVI_FORMAT_RGB32:
+ case AVI_FORMAT_AVI_RGB:
+ case AVI_FORMAT_MJPEG:
+ return FCC("vids");
+ break;
+ default:
+ return 0;
+ break;
+ }
+}
+
+int avi_get_format_fcc (AviFormat format) {
+ switch (format) {
+ case AVI_FORMAT_RGB24:
+ case AVI_FORMAT_RGB32:
+ case AVI_FORMAT_AVI_RGB:
+ return FCC("DIB ");
+ break;
+ case AVI_FORMAT_MJPEG:
+ return FCC("MJPG");
+ break;
+ default:
+ return 0;
+ break;
+ }
+}
+
+int avi_get_format_compression (AviFormat format) {
+ switch (format) {
+ case AVI_FORMAT_RGB24:
+ case AVI_FORMAT_RGB32:
+ case AVI_FORMAT_AVI_RGB:
+ return 0;
+ break;
+ case AVI_FORMAT_MJPEG:
+ return FCC("MJPG");
+ break;
+ default:
+ return 0;
+ break;
+ }
+}
diff --git a/source/blender/avi/intern/endian.c b/source/blender/avi/intern/endian.c
new file mode 100644
index 00000000000..3308d05ce43
--- /dev/null
+++ b/source/blender/avi/intern/endian.c
@@ -0,0 +1,207 @@
+/**
+ * endian.h
+ *
+ * This is external code. Streams bytes to output depending on the
+ * endianness of the system.
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 <stdio.h>
+#include "AVI_avi.h"
+#include "endian.h"
+
+static void invert (int *num) {
+ int new=0,i,j;
+
+ for (j=0; j < 4; j++) {
+ for (i=0; i<8; i++) {
+ new |= ((*num>>(j*8+i))&1)<<((3-j)*8+i);
+ }
+ }
+
+ *num = new;
+}
+
+static void sinvert (short int *num) {
+ short int new=0;
+ int i,j;
+
+ for (j=0; j < 2; j++) {
+ for (i=0; i<8; i++) {
+ new |= ((*num>>(j*8+i))&1)<<((1-j)*8+i);
+ }
+ }
+
+ *num = new;
+}
+
+static void Ichunk (AviChunk *chunk) {
+ invert (&chunk->fcc);
+ invert (&chunk->size);
+}
+
+#ifdef WORDS_BIGENDIAN
+static void Ilist (AviList *list){
+ invert (&list->fcc);
+ invert (&list->size);
+ invert (&list->ids);
+}
+
+static void Imainh (AviMainHeader *mainh) {
+ invert (&mainh->fcc);
+ invert (&mainh->size);
+ invert (&mainh->MicroSecPerFrame);
+ invert (&mainh->MaxBytesPerSec);
+ invert (&mainh->PaddingGranularity);
+ invert (&mainh->Flags);
+ invert (&mainh->TotalFrames);
+ invert (&mainh->InitialFrames);
+ invert (&mainh->Streams);
+ invert (&mainh->SuggestedBufferSize);
+ invert (&mainh->Width);
+ invert (&mainh->Height);
+ invert (&mainh->Reserved[0]);
+ invert (&mainh->Reserved[1]);
+ invert (&mainh->Reserved[2]);
+ invert (&mainh->Reserved[3]);
+}
+
+static void Istreamh (AviStreamHeader *streamh) {
+ invert (&streamh->fcc);
+ invert (&streamh->size);
+ invert (&streamh->Type);
+ invert (&streamh->Handler);
+ invert (&streamh->Flags);
+ sinvert (&streamh->Priority);
+ sinvert (&streamh->Language);
+ invert (&streamh->InitialFrames);
+ invert (&streamh->Scale);
+ invert (&streamh->Rate);
+ invert (&streamh->Start);
+ invert (&streamh->Length);
+ invert (&streamh->SuggestedBufferSize);
+ invert (&streamh->Quality);
+ invert (&streamh->SampleSize);
+ sinvert (&streamh->left);
+ sinvert (&streamh->right);
+ sinvert (&streamh->top);
+ sinvert (&streamh->bottom);
+}
+
+static void Ibitmaph (AviBitmapInfoHeader *bitmaph) {
+ invert (&bitmaph->fcc);
+ invert (&bitmaph->size);
+ invert (&bitmaph->Size);
+ invert (&bitmaph->Width);
+ invert (&bitmaph->Height);
+ sinvert (&bitmaph->Planes);
+ sinvert (&bitmaph->BitCount);
+ invert (&bitmaph->Compression);
+ invert (&bitmaph->SizeImage);
+ invert (&bitmaph->XPelsPerMeter);
+ invert (&bitmaph->YPelsPerMeter);
+ invert (&bitmaph->ClrUsed);
+ invert (&bitmaph->ClrImportant);
+}
+
+static void Imjpegu (AviMJPEGUnknown *mjpgu) {
+ invert (&mjpgu->a);
+ invert (&mjpgu->b);
+ invert (&mjpgu->c);
+ invert (&mjpgu->d);
+ invert (&mjpgu->e);
+ invert (&mjpgu->f);
+ invert (&mjpgu->g);
+}
+
+static void Iindexe (AviIndexEntry *indexe) {
+ invert (&indexe->ChunkId);
+ invert (&indexe->Flags);
+ invert (&indexe->Offset);
+ invert (&indexe->Size);
+}
+#endif /* WORDS_BIGENDIAN */
+
+void awrite (AviMovie *movie, void *datain, int block, int size, FILE *fp, int type) {
+#ifdef WORDS_BIGENDIAN
+ void *data;
+
+ data = malloc (size);
+
+ memcpy (data, datain, size);
+
+ switch (type) {
+ case AVI_RAW:
+ fwrite (data, block, size, fp);
+ break;
+ case AVI_CHUNK:
+ Ichunk ((AviChunk *) data);
+ fwrite (data, block, size, fp);
+ break;
+ case AVI_LIST:
+ Ilist ((AviList *) data);
+ fwrite (data, block, size, fp);
+ break;
+ case AVI_MAINH:
+ Imainh ((AviMainHeader *) data);
+ fwrite (data, block, size, fp);
+ break;
+ case AVI_STREAMH:
+ Istreamh ((AviStreamHeader *) data);
+ fwrite (data, block, size, fp);
+ break;
+ case AVI_BITMAPH:
+ Ibitmaph ((AviBitmapInfoHeader *) data);
+ if (size==sizeof(AviBitmapInfoHeader) + sizeof(AviMJPEGUnknown)) {
+ Imjpegu((AviMJPEGUnknown*)((char*)data+sizeof(AviBitmapInfoHeader)));
+ }
+ fwrite (data, block, size, fp);
+ break;
+ case AVI_MJPEGU:
+ Imjpegu ((AviMJPEGUnknown *) data);
+ fwrite (data, block, size, fp);
+ break;
+ case AVI_INDEXE:
+ Iindexe ((AviIndexEntry *) data);
+ fwrite (data, block, size, fp);
+ break;
+ default:
+ break;
+ }
+
+ free (data);
+#else /* WORDS_BIGENDIAN */
+ fwrite (datain, block, size, fp);
+#endif /* WORDS_BIGENDIAN */
+}
diff --git a/source/blender/avi/intern/endian.h b/source/blender/avi/intern/endian.h
new file mode 100644
index 00000000000..59ccbb2b8fb
--- /dev/null
+++ b/source/blender/avi/intern/endian.h
@@ -0,0 +1,54 @@
+/**
+ * endian.h
+ *
+ * This is external code.
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 AVI_ENDIAN_H
+#define AVI_ENDIAN_H
+
+#include <stdio.h>
+#include "AVI_avi.h"
+
+#define AVI_RAW 0
+#define AVI_CHUNK 1
+#define AVI_LIST 2
+#define AVI_MAINH 3
+#define AVI_STREAMH 4
+#define AVI_BITMAPH 5
+#define AVI_INDEXE 6
+#define AVI_MJPEGU 7
+
+void awrite (AviMovie *movie, void *datain, int block, int size, FILE *fp, int type);
+
+#endif
diff --git a/source/blender/avi/intern/mjpeg.c b/source/blender/avi/intern/mjpeg.c
new file mode 100644
index 00000000000..8831e3ca615
--- /dev/null
+++ b/source/blender/avi/intern/mjpeg.c
@@ -0,0 +1,452 @@
+/**
+ * mjpeg.c
+ *
+ * This is external code. Converts between avi and mpeg/jpeg.
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "AVI_avi.h"
+#include <stdlib.h>
+#include <string.h>
+#include "jpeglib.h"
+#include "jerror.h"
+#include "MEM_guardedalloc.h"
+
+#include "mjpeg.h"
+
+#define PADUP(num, amt) ((num+(amt-1))&~(amt-1))
+
+static void jpegmemdestmgr_build (j_compress_ptr cinfo, unsigned char *buffer, int bufsize);
+static void jpegmemsrcmgr_build (j_decompress_ptr dinfo, unsigned char *buffer, int bufsize);
+
+static int numbytes;
+
+static void add_huff_table (j_decompress_ptr dinfo, JHUFF_TBL **htblptr, const UINT8 *bits, const UINT8 *val) {
+ if (*htblptr == NULL)
+ *htblptr = jpeg_alloc_huff_table((j_common_ptr) dinfo);
+
+ memcpy((*htblptr)->bits, bits, sizeof((*htblptr)->bits));
+ memcpy((*htblptr)->huffval, val, sizeof((*htblptr)->huffval));
+
+ /* Initialize sent_table FALSE so table will be written to JPEG file. */
+ (*htblptr)->sent_table = FALSE;
+}
+
+/* Set up the standard Huffman tables (cf. JPEG standard section K.3) */
+/* IMPORTANT: these are only valid for 8-bit data precision! */
+
+static void std_huff_tables (j_decompress_ptr dinfo) {
+ static const UINT8 bits_dc_luminance[17] =
+ { /* 0-base */
+ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 };
+ static const UINT8 val_dc_luminance[] =
+ {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
+
+ static const UINT8 bits_dc_chrominance[17] =
+ { /* 0-base */
+ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 };
+ static const UINT8 val_dc_chrominance[] =
+ {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
+
+ static const UINT8 bits_ac_luminance[17] =
+ { /* 0-base */
+ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d };
+ static const UINT8 val_ac_luminance[] =
+ {
+ 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
+ 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
+ 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
+ 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
+ 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
+ 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
+ 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+ 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
+ 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
+ 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
+ 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
+ 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
+ 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
+ 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+ 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
+ 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
+ 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
+ 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
+ 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
+ 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
+ 0xf9, 0xfa };
+ static const UINT8 bits_ac_chrominance[17] =
+ { /* 0-base */
+ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 };
+ static const UINT8 val_ac_chrominance[] =
+ {
+ 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
+ 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
+ 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
+ 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
+ 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
+ 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
+ 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
+ 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
+ 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+ 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
+ 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+ 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
+ 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
+ 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
+ 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
+ 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
+ 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
+ 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
+ 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
+ 0xf9, 0xfa };
+
+ add_huff_table(dinfo, &dinfo->dc_huff_tbl_ptrs[0],
+ bits_dc_luminance, val_dc_luminance);
+ add_huff_table(dinfo, &dinfo->ac_huff_tbl_ptrs[0],
+ bits_ac_luminance, val_ac_luminance);
+ add_huff_table(dinfo, &dinfo->dc_huff_tbl_ptrs[1],
+ bits_dc_chrominance, val_dc_chrominance);
+ add_huff_table(dinfo, &dinfo->ac_huff_tbl_ptrs[1],
+ bits_ac_chrominance, val_ac_chrominance);
+}
+
+static int Decode_JPEG(unsigned char *inBuffer, unsigned char *outBuffer, int width, int height, int bufsize) {
+ int rowstride, y;
+ struct jpeg_decompress_struct dinfo;
+ struct jpeg_error_mgr jerr;
+
+ numbytes= 0;
+
+ dinfo.err = jpeg_std_error(&jerr);
+ jpeg_create_decompress(&dinfo);
+ jpegmemsrcmgr_build(&dinfo, inBuffer, bufsize);
+ jpeg_read_header(&dinfo, TRUE);
+ if (dinfo.dc_huff_tbl_ptrs[0] == NULL){
+ std_huff_tables(&dinfo);
+ }
+ dinfo.out_color_space = JCS_RGB;
+ dinfo.dct_method = JDCT_IFAST;
+
+ jpeg_start_decompress(&dinfo);
+
+ rowstride= dinfo.output_width*dinfo.output_components;
+ for (y= 0; y<dinfo.output_height; y++) {
+ jpeg_read_scanlines(&dinfo, (JSAMPARRAY) &outBuffer, 1);
+ outBuffer += rowstride;
+ }
+ jpeg_finish_decompress(&dinfo);
+
+ if (dinfo.output_height >= height) return 0;
+
+ inBuffer+= numbytes;
+ jpegmemsrcmgr_build(&dinfo, inBuffer, bufsize-numbytes);
+
+ numbytes= 0;
+ jpeg_read_header(&dinfo, TRUE);
+ if (dinfo.dc_huff_tbl_ptrs[0] == NULL){
+ std_huff_tables(&dinfo);
+ }
+
+ jpeg_start_decompress(&dinfo);
+ rowstride= dinfo.output_width*dinfo.output_components;
+ for (y= 0; y<dinfo.output_height; y++){
+ jpeg_read_scanlines(&dinfo, (JSAMPARRAY) &outBuffer, 1);
+ outBuffer += rowstride;
+ }
+ jpeg_finish_decompress(&dinfo);
+ jpeg_destroy_decompress(&dinfo);
+
+ return 1;
+}
+
+static void Compress_JPEG(int quality, unsigned char *outbuffer, unsigned char *inBuffer, int width, int height, int bufsize) {
+ int i, y, rowstride;
+ struct jpeg_compress_struct cinfo;
+ struct jpeg_error_mgr jerr;
+ unsigned char marker[60];
+
+ cinfo.err = jpeg_std_error(&jerr);
+ jpeg_create_compress(&cinfo);
+ jpegmemdestmgr_build(&cinfo, outbuffer, bufsize);
+
+ cinfo.image_width = width;
+ cinfo.image_height = height;
+ cinfo.input_components = 3;
+ cinfo.in_color_space = JCS_RGB;
+
+ jpeg_set_defaults(&cinfo);
+ jpeg_set_colorspace (&cinfo, JCS_YCbCr);
+
+ jpeg_set_quality (&cinfo, quality, TRUE);
+
+ cinfo.dc_huff_tbl_ptrs[0]->sent_table = TRUE;
+ cinfo.dc_huff_tbl_ptrs[1]->sent_table = TRUE;
+ cinfo.ac_huff_tbl_ptrs[0]->sent_table = TRUE;
+ cinfo.ac_huff_tbl_ptrs[1]->sent_table = TRUE;
+
+ cinfo.comp_info[0].component_id = 0;
+ cinfo.comp_info[0].v_samp_factor = 1;
+ cinfo.comp_info[1].component_id = 1;
+ cinfo.comp_info[2].component_id = 2;
+
+ cinfo.write_JFIF_header = FALSE;
+
+ jpeg_start_compress(&cinfo, FALSE);
+
+ i=0;
+ marker[i++] = 'A';
+ marker[i++] = 'V';
+ marker[i++] = 'I';
+ marker[i++] = '1';
+ marker[i++] = 0;
+ while (i<60)
+ marker[i++] = 32;
+
+ jpeg_write_marker (&cinfo, JPEG_APP0, marker, 60);
+
+ i=0;
+ while (i<60)
+ marker[i++] = 0;
+
+ jpeg_write_marker (&cinfo, JPEG_COM, marker, 60);
+
+ rowstride= cinfo.image_width*cinfo.input_components;
+ for (y = 0; y < cinfo.image_height; y++){
+ jpeg_write_scanlines(&cinfo, (JSAMPARRAY) &inBuffer, 1);
+ inBuffer += rowstride;
+ }
+ jpeg_finish_compress(&cinfo);
+ jpeg_destroy_compress(&cinfo);
+}
+
+static void interlace(unsigned char *to, unsigned char *from, int width, int height) {
+ int i, rowstride= width*3;
+
+ for (i=0; i<height; i++) {
+ if (i&1)
+ memcpy (&to[i*rowstride], &from[(i/2 + height/2)*rowstride], rowstride);
+ else
+ memcpy (&to[i*rowstride], &from[(i/2)*rowstride], rowstride);
+ }
+}
+
+static void deinterlace(int odd, unsigned char *to, unsigned char *from, int width, int height) {
+ int i, rowstride= width*3;
+
+ for (i=0; i<height; i++) {
+ if ((i&1)==odd)
+ memcpy (&to[(i/2 + height/2)*rowstride], &from[i*rowstride], rowstride);
+ else
+ memcpy (&to[(i/2)*rowstride], &from[i*rowstride], rowstride);
+ }
+}
+
+static int check_and_decode_jpeg(unsigned char *inbuf, unsigned char *outbuf, int width, int height, int bufsize) {
+ /* JPEG's are always multiples of 16, extra is cropped out AVI's */
+ if ((width&0xF) || (height&0xF)) {
+ int i, rrowstride, jrowstride;
+ int jwidth= PADUP(width, 16);
+ int jheight= PADUP(height, 16);
+ unsigned char *tmpbuf= MEM_mallocN(jwidth*jheight*3, "avi.check_and_decode_jpeg");
+ int ret= Decode_JPEG(inbuf, tmpbuf, jwidth, jheight, bufsize);
+
+ /* crop the tmpbuf into the real buffer */
+ rrowstride= width*3;
+ jrowstride= jwidth*3;
+ for (i=0; i<height; i++)
+ memcpy(&outbuf[i*rrowstride], &tmpbuf[i*jrowstride], rrowstride);
+ MEM_freeN(tmpbuf);
+
+ return ret;
+ } else {
+ return Decode_JPEG(inbuf, outbuf, width, height, bufsize);
+ }
+}
+
+static void check_and_compress_jpeg(int quality, unsigned char *outbuf, unsigned char *inbuf, int width, int height, int bufsize) {
+ /* JPEG's are always multiples of 16, extra is ignored in AVI's */
+ if ((width&0xF) || (height&0xF)) {
+ int i, rrowstride, jrowstride;
+ int jwidth= PADUP(width, 16);
+ int jheight= PADUP(height, 16);
+ unsigned char *tmpbuf= MEM_mallocN(jwidth*jheight*3, "avi.check_and_compress_jpeg");
+
+ /* resize the realbuf into the tmpbuf */
+ rrowstride= width*3;
+ jrowstride= jwidth*3;
+ for (i=0; i<jheight; i++) {
+ if (i<height)
+ memcpy(&tmpbuf[i*jrowstride], &inbuf[i*rrowstride], rrowstride);
+ else
+ memset(&tmpbuf[i*jrowstride], 0, rrowstride);
+ memset(&tmpbuf[i*jrowstride+rrowstride], 0, jrowstride-rrowstride);
+ }
+
+ Compress_JPEG(quality, outbuf, tmpbuf, jwidth, jheight, bufsize);
+
+ MEM_freeN(tmpbuf);
+ } else {
+ Compress_JPEG(quality, outbuf, inbuf, width, height, bufsize);
+ }
+}
+
+void *avi_converter_from_mjpeg (AviMovie *movie, int stream, unsigned char *buffer, int *size) {
+ int deint;
+ unsigned char *buf;
+
+ buf= MEM_mallocN (movie->header->Height * movie->header->Width * 3, "avi.avi_converter_from_mjpeg 1");
+
+ deint= check_and_decode_jpeg(buffer, buf, movie->header->Width, movie->header->Height, *size);
+
+ MEM_freeN(buffer);
+
+ if (deint) {
+ buffer = MEM_mallocN (movie->header->Height * movie->header->Width * 3, "avi.avi_converter_from_mjpeg 2");
+ interlace (buffer, buf, movie->header->Width, movie->header->Height);
+ MEM_freeN (buf);
+
+ buf= buffer;
+ }
+
+ return buf;
+}
+
+void *avi_converter_to_mjpeg (AviMovie *movie, int stream, unsigned char *buffer, int *size) {
+ unsigned char *buf;
+ int bufsize= *size;
+
+ numbytes = 0;
+ *size= 0;
+
+ buf = MEM_mallocN (movie->header->Height * movie->header->Width * 3, "avi.avi_converter_to_mjpeg 1");
+ if (!movie->interlace) {
+ check_and_compress_jpeg(movie->streams[stream].sh.Quality/100, buf, buffer, movie->header->Width, movie->header->Height, bufsize);
+ } else {
+ deinterlace (movie->odd_fields, buf, buffer, movie->header->Width, movie->header->Height);
+ MEM_freeN (buffer);
+
+ buffer= buf;
+ buf= MEM_mallocN (movie->header->Height * movie->header->Width * 3, "avi.avi_converter_to_mjpeg 2");
+
+ check_and_compress_jpeg(movie->streams[stream].sh.Quality/100, buf, buffer, movie->header->Width, movie->header->Height/2, bufsize/2);
+ *size+= numbytes;
+ numbytes=0;
+ check_and_compress_jpeg(movie->streams[stream].sh.Quality/100, buf+*size, buffer+(movie->header->Height/2)*movie->header->Width*3, movie->header->Width, movie->header->Height/2, bufsize/2);
+ }
+ *size += numbytes;
+
+ MEM_freeN (buffer);
+ return buf;
+}
+
+
+/* Compression from memory */
+
+static void jpegmemdestmgr_init_destination(j_compress_ptr cinfo) {
+ ;
+}
+
+static boolean jpegmemdestmgr_empty_output_buffer(j_compress_ptr cinfo) {
+ return TRUE;
+}
+
+static void jpegmemdestmgr_term_destination(j_compress_ptr cinfo) {
+ numbytes-= cinfo->dest->free_in_buffer;
+
+ MEM_freeN(cinfo->dest);
+}
+
+static void jpegmemdestmgr_build(j_compress_ptr cinfo, unsigned char *buffer, int bufsize) {
+ cinfo->dest= MEM_mallocN(sizeof(*(cinfo->dest)), "avi.jpegmemdestmgr_build");
+
+ cinfo->dest->init_destination= jpegmemdestmgr_init_destination;
+ cinfo->dest->empty_output_buffer= jpegmemdestmgr_empty_output_buffer;
+ cinfo->dest->term_destination= jpegmemdestmgr_term_destination;
+
+ cinfo->dest->next_output_byte= buffer;
+ cinfo->dest->free_in_buffer= bufsize;
+
+ numbytes= bufsize;
+}
+
+/* Decompression from memory */
+
+static void jpegmemsrcmgr_init_source(j_decompress_ptr dinfo) {
+ ;
+}
+
+static boolean jpegmemsrcmgr_fill_input_buffer(j_decompress_ptr dinfo) {
+ unsigned char *buf= (unsigned char*) dinfo->src->next_input_byte-2;
+
+ /* if we get called, must have run out of data */
+ WARNMS(dinfo, JWRN_JPEG_EOF);
+
+ buf[0]= (JOCTET) 0xFF;
+ buf[1]= (JOCTET) JPEG_EOI;
+
+ dinfo->src->next_input_byte= buf;
+ dinfo->src->bytes_in_buffer= 2;
+
+ return TRUE;
+}
+
+static void jpegmemsrcmgr_skip_input_data(j_decompress_ptr dinfo, long skipcnt) {
+ if (dinfo->src->bytes_in_buffer<skipcnt)
+ skipcnt= dinfo->src->bytes_in_buffer;
+
+ dinfo->src->next_input_byte+= skipcnt;
+ dinfo->src->bytes_in_buffer-= skipcnt;
+}
+
+static void jpegmemsrcmgr_term_source(j_decompress_ptr dinfo) {
+ numbytes-= dinfo->src->bytes_in_buffer;
+
+ MEM_freeN(dinfo->src);
+}
+
+static void jpegmemsrcmgr_build(j_decompress_ptr dinfo, unsigned char *buffer, int bufsize) {
+ dinfo->src= MEM_mallocN(sizeof(*(dinfo->src)), "avi.jpegmemsrcmgr_build");
+
+ dinfo->src->init_source= jpegmemsrcmgr_init_source;
+ dinfo->src->fill_input_buffer= jpegmemsrcmgr_fill_input_buffer;
+ dinfo->src->skip_input_data= jpegmemsrcmgr_skip_input_data;
+ dinfo->src->resync_to_restart= jpeg_resync_to_restart;
+ dinfo->src->term_source= jpegmemsrcmgr_term_source;
+
+ dinfo->src->bytes_in_buffer= bufsize;
+ dinfo->src->next_input_byte= buffer;
+
+ numbytes= bufsize;
+}
diff --git a/source/blender/avi/intern/mjpeg.h b/source/blender/avi/intern/mjpeg.h
new file mode 100644
index 00000000000..d93a69fe1e9
--- /dev/null
+++ b/source/blender/avi/intern/mjpeg.h
@@ -0,0 +1,33 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 *avi_converter_from_mjpeg (AviMovie *movie, int stream, unsigned char *buffer, int *size);
+void *avi_converter_to_mjpeg (AviMovie *movie, int stream, unsigned char *buffer, int *size);
diff --git a/source/blender/avi/intern/options.c b/source/blender/avi/intern/options.c
new file mode 100644
index 00000000000..2c75c5773b7
--- /dev/null
+++ b/source/blender/avi/intern/options.c
@@ -0,0 +1,127 @@
+/**
+ * options.h
+ *
+ * This is external code. Sets some compression related options
+ * (width, height quality, framerate).
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "AVI_avi.h"
+#include "avi_intern.h"
+
+#include "endian.h"
+
+/* avi_set_compress_options gets its own file... now don't WE feel important? */
+
+AviError AVI_set_compress_option (AviMovie *movie, int option_type, int stream, AviOption option, void *opt_data) {
+ int i;
+
+ if (movie->header->TotalFrames != 0) /* Can't change params after we have already started writing frames */
+ return AVI_ERROR_OPTION;
+
+ switch (option_type) {
+ case AVI_OPTION_TYPE_MAIN:
+ switch (option) {
+ case AVI_OPTION_WIDTH:
+ movie->header->Width = *((int *) opt_data);
+ movie->header->SuggestedBufferSize = movie->header->Width*movie->header->Height*3;
+
+ for (i=0; i < movie->header->Streams; i++) {
+ if (avi_get_format_type(movie->streams[i].format) == FCC("vids")) {
+ ((AviBitmapInfoHeader *) movie->streams[i].sf)->Width = *((int *) opt_data);
+ movie->streams[i].sh.SuggestedBufferSize = movie->header->SuggestedBufferSize;
+ movie->streams[i].sh.right = *((int *) opt_data);
+ ((AviBitmapInfoHeader *) movie->streams[i].sf)->SizeImage = movie->header->SuggestedBufferSize;
+ fseek (movie->fp, movie->offset_table[1+i*2+1], SEEK_SET);
+ awrite (movie, movie->streams[i].sf, 1, movie->streams[i].sf_size, movie->fp, AVI_BITMAPH);
+ }
+ }
+
+ break;
+
+ case AVI_OPTION_HEIGHT:
+ movie->header->Height = *((int *) opt_data);
+ movie->header->SuggestedBufferSize = movie->header->Width*movie->header->Height*3;
+
+ for (i=0; i < movie->header->Streams; i++) {
+ if (avi_get_format_type(movie->streams[i].format) == FCC("vids")) {
+ ((AviBitmapInfoHeader *) movie->streams[i].sf)->Height = *((int *) opt_data);
+ movie->streams[i].sh.SuggestedBufferSize = movie->header->SuggestedBufferSize;
+ movie->streams[i].sh.bottom = *((int *) opt_data);
+ ((AviBitmapInfoHeader *) movie->streams[i].sf)->SizeImage = movie->header->SuggestedBufferSize;
+ fseek (movie->fp, movie->offset_table[1+i*2+1], SEEK_SET);
+ awrite (movie, movie->streams[i].sf, 1, movie->streams[i].sf_size, movie->fp, AVI_BITMAPH);
+ }
+ }
+
+ break;
+
+ case AVI_OPTION_QUALITY:
+ for (i=0; i < movie->header->Streams; i++) {
+ if (avi_get_format_type(movie->streams[i].format) == FCC("vids")) {
+ movie->streams[i].sh.Quality = (*((int *) opt_data))*100;
+ fseek (movie->fp, movie->offset_table[1+i*2+1], SEEK_SET);
+ awrite (movie, movie->streams[i].sf, 1, movie->streams[i].sf_size, movie->fp, AVI_BITMAPH);
+ }
+ }
+ break;
+
+ case AVI_OPTION_FRAMERATE:
+ if (1000000/(*((int *) opt_data)))
+ movie->header->MicroSecPerFrame = 1000000/(*((int *) opt_data));
+
+ for (i=0; i < movie->header->Streams; i++) {
+ if (avi_get_format_type(movie->streams[i].format) == FCC("vids")) {
+ movie->streams[i].sh.Scale = movie->header->MicroSecPerFrame;
+ fseek (movie->fp, movie->offset_table[1+i*2+1], SEEK_SET);
+ awrite (movie, movie->streams[i].sf, 1, movie->streams[i].sf_size, movie->fp, AVI_BITMAPH);
+ }
+ }
+
+ }
+
+ fseek (movie->fp, movie->offset_table[0], SEEK_SET);
+ awrite (movie, movie->header, 1, sizeof(AviMainHeader), movie->fp, AVI_MAINH);
+
+ break;
+ case AVI_OPTION_TYPE_STRH:
+ break;
+ case AVI_OPTION_TYPE_STRF:
+ break;
+ default:
+ return AVI_ERROR_OPTION;
+ break;
+ }
+
+ return AVI_ERROR_NONE;
+}
+
diff --git a/source/blender/avi/intern/rgb32.c b/source/blender/avi/intern/rgb32.c
new file mode 100644
index 00000000000..b35bb9a7379
--- /dev/null
+++ b/source/blender/avi/intern/rgb32.c
@@ -0,0 +1,88 @@
+/**
+ * rgb32.c
+ *
+ * This is external code. Converts between rgb32 and avi.
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "AVI_avi.h"
+#include <stdlib.h>
+#include <string.h>
+#include "MEM_guardedalloc.h"
+
+#include "rgb32.h"
+
+void *avi_converter_from_rgb32 (AviMovie *movie, int stream, unsigned char *buffer, int *size) {
+ int y, x, rowstridea, rowstrideb;
+ unsigned char *buf;
+
+ buf = MEM_mallocN (movie->header->Height * movie->header->Width * 3, "fromrgb32buf");
+ *size = movie->header->Height * movie->header->Width * 3;
+
+ rowstridea = movie->header->Width*3;
+ rowstrideb = movie->header->Width*4;
+
+ for (y=0; y < movie->header->Height; y++) {
+ for (x=0; x < movie->header->Width; x++) {
+ buf[y*rowstridea + x*3 + 0] = buffer[y*rowstrideb + x*4 + 3];
+ buf[y*rowstridea + x*3 + 1] = buffer[y*rowstrideb + x*4 + 2];
+ buf[y*rowstridea + x*3 + 2] = buffer[y*rowstrideb + x*4 + 1];
+ }
+ }
+
+ MEM_freeN (buffer);
+
+ return buf;
+}
+
+void *avi_converter_to_rgb32 (AviMovie *movie, int stream, unsigned char *buffer, int *size) {
+ int i;
+ unsigned char *buf;
+ unsigned char *to, *from;
+
+ buf= MEM_mallocN (movie->header->Height * movie->header->Width * 4, "torgb32buf");
+ *size= movie->header->Height * movie->header->Width * 4;
+
+ memset(buf, 255, *size);
+
+ to= buf; from= buffer;
+ i=movie->header->Height*movie->header->Width;
+
+ while(i--) {
+ memcpy(to, from, 3);
+ to+=4; from+=3;
+ }
+
+ MEM_freeN (buffer);
+
+ return buf;
+}
diff --git a/source/blender/avi/intern/rgb32.h b/source/blender/avi/intern/rgb32.h
new file mode 100644
index 00000000000..5ac6bf721de
--- /dev/null
+++ b/source/blender/avi/intern/rgb32.h
@@ -0,0 +1,33 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 *avi_converter_from_rgb32 (AviMovie *movie, int stream, unsigned char *buffer, int *size);
+void *avi_converter_to_rgb32 (AviMovie *movie, int stream, unsigned char *buffer, int *size);
diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h
new file mode 100644
index 00000000000..53fe4a7146c
--- /dev/null
+++ b/source/blender/blenkernel/BKE_action.h
@@ -0,0 +1,238 @@
+/* BKE_action.h May 2001
+ *
+ * Blender kernel action functionality
+ *
+ * Reevan McKay
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BKE_ACTION_H
+#define BKE_ACTION_H
+
+#include "DNA_listBase.h"
+
+/**
+ * The following structures are defined in DNA_action_types.h
+ */
+
+struct bAction;
+struct bActionChannel;
+struct bPose;
+struct bPoseChannel;
+struct Object;
+
+/* Kernel prototypes */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Allocate a new pose channel on the heap and binary copy the
+ * contents of the src pose channel.
+ */
+ struct bPoseChannel *
+copy_pose_channel (
+ const struct bPoseChannel *src
+);
+
+/**
+ * Removes and deallocates all channels from a pose.
+ * Does not free the pose itself.
+ */
+ void
+clear_pose (
+ struct bPose *pose
+);
+
+/* Sets the value of a pose channel */
+ struct bPoseChannel *
+set_pose_channel (
+ struct bPose *pose,
+ struct bPoseChannel *chan
+);
+
+/**
+ * Allocate a new pose on the heap, and copy the src pose and it's channels
+ * into the new pose. *dst is set to the newly allocated structure.
+ */
+ void
+copy_pose(
+ struct bPose **dst,
+ const struct bPose *src,
+ int copyconstraints
+);
+
+/**
+ * Deallocate the action's channels including constraint channels.
+ * does not free the action structure.
+ */
+ void
+free_action(
+ struct bAction * id
+);
+
+ void
+make_local_action(
+ struct bAction *act
+);
+
+ void
+do_all_actions(
+ void
+);
+
+/**
+ * Return a pointer to the pose channel of the given name
+ * from this pose.
+ */
+
+ struct bPoseChannel *
+get_pose_channel (
+ const struct bPose *pose,
+ const char *name
+);
+
+/**
+ * Looks to see if the channel with the given name
+ * already exists in this pose - if not a new one is
+ * allocated and initialized.
+ */
+ void
+verify_pose_channel (
+ struct bPose* pose,
+ const char* name
+);
+
+/**
+ * Allocate a new bAction on the heap and copy
+ * the contents of src into it. If src is NULL NULL is returned.
+ */
+
+ struct bAction*
+copy_action(
+ const struct bAction *src
+);
+
+/**
+ * Some kind of bounding box operation on the action.
+ */
+
+ float
+calc_action_start (
+ const struct bAction *act
+);
+
+ float
+calc_action_end (
+ const struct bAction *act
+);
+
+/**
+ * Evaluate the pose from the given action.
+ * If the pose does not exist, a new one is created.
+ * Some deep calls into blender are made here.
+ */
+ void
+get_pose_from_action (
+ struct bPose **pose,
+ struct bAction *act,
+ float ctime
+);
+
+/**
+ * I think this duplicates the src into *pose.
+ * If the pose does not exist, a new one is created.
+ * If the pose does not contain channels from src
+ * new channels are created.
+ */
+ void
+get_pose_from_pose (
+ struct bPose **pose,
+ const struct bPose *src
+);
+
+ void
+clear_pose_constraint_status (
+ struct Object *ob
+);
+
+/**
+ * Blends the common subset of channels from dst and src.
+ * and writes result to dst.
+ */
+ void
+blend_poses (
+ struct bPose *dst,
+ const struct bPose *src,
+ float srcweight,
+ short mode
+);
+
+/**
+ * Iterate through the action channels of the action
+ * and return the channel with the given name.
+ * Returns NULL if no channel.
+ */
+
+ struct bActionChannel *
+get_named_actionchannel (
+ struct bAction *act,
+ const char *name
+);
+
+#ifdef __cplusplus
+};
+#endif
+
+enum {
+ POSE_BLEND = 0,
+ POSE_ADD
+};
+
+enum {
+ POSE_KEY = 0x10000000,
+ POSE_LOC = 0x00000001,
+ POSE_ROT = 0x00000002,
+ POSE_SIZE = 0x00000004,
+ POSE_UNUSED1 = 0x00000008,
+ POSE_UNUSED2 = 0x00000010,
+ POSE_UNUSED3 = 0x00000020,
+ POSE_UNUSED4 = 0x00000040,
+ POSE_UNUSED5 = 0x00000080,
+ POSE_OBMAT = 0x00000100,
+ POSE_PARMAT = 0x00000200,
+ PCHAN_DONE = 0x00000400
+
+};
+#endif
+
+
diff --git a/source/blender/blenkernel/BKE_anim.h b/source/blender/blenkernel/BKE_anim.h
new file mode 100644
index 00000000000..93faf2d34bc
--- /dev/null
+++ b/source/blender/blenkernel/BKE_anim.h
@@ -0,0 +1,52 @@
+/**
+ * blenlib/BKE_anim.h (mar-2001 nzc);
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BKE_ANIM_H
+#define BKE_ANIM_H
+
+struct Path;
+struct Object;
+struct PartEff;
+struct Scene;
+
+void free_path(struct Path *path);
+void calc_curvepath(struct Object *ob);
+int interval_test(int min, int max, int p1, int cycl);
+int where_on_path(struct Object *ob, float ctime, float *vec, float *dir);
+void frames_duplilist(struct Object *ob);
+void vertex_duplilist(struct Scene *sce, struct Object *par);
+void particle_duplilist(struct Scene *sce, struct Object *par, struct PartEff *paf);
+void free_duplilist(void);
+void make_duplilist(struct Scene *sce, struct Object *ob);
+
+#endif
diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h
new file mode 100644
index 00000000000..4e52d154644
--- /dev/null
+++ b/source/blender/blenkernel/BKE_armature.h
@@ -0,0 +1,121 @@
+/**
+ * blenlib/BKE_armature.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BKE_ARMATURE_H
+#define BKE_ARMATURE_H
+
+struct Bone;
+struct Main;
+struct bArmature;
+struct bPose;
+struct Object;
+struct MDeformVert;
+struct Mesh;
+struct PoseChain;
+struct ListBase;
+
+typedef struct PoseChain
+{
+ struct PoseChain *next, *prev;
+ struct Bone *root;
+ struct Bone *target;
+ struct bPose *pose;
+ float goal[3];
+ float tolerance;
+ int iterations;
+ float goalinv[4][4];
+ struct IK_Chain_Extern *solver;
+} PoseChain;
+
+/* Core armature functionality */
+#ifdef __cplusplus
+extern "C" {
+#endif
+struct bArmature *add_armature(void);
+void free_boneChildren(struct Bone *bone);
+void free_bones (struct bArmature *arm);
+void unlink_armature(struct bArmature *arm);
+void free_armature(struct bArmature *arm);
+void make_local_armature(struct bArmature *arm);
+struct bArmature *copy_armature(struct bArmature *arm);
+void apply_pose_armature (struct bArmature* arm, struct bPose* pose, int doit);
+void calc_armature_deform (struct Object *ob, float *co, int index);
+int verify_boneptr (struct bArmature *arm, struct Bone *tBone);
+void init_armature_deform(struct Object *parent, struct Object *ob);
+struct bArmature* get_armature (struct Object* ob);
+struct Bone *get_named_bone (struct bArmature *arm, const char *name);
+struct Bone *get_indexed_bone (struct bArmature *arm, int index);
+void make_displists_by_armature (struct Object *ob);
+void calc_bone_deform (struct Bone *bone, float weight, float *vec, float *co, float *contrib);
+
+void where_is_armature_time (struct Object *ob, float ctime);
+void where_is_armature (struct Object *ob);
+void where_is_bone1_time (struct Object *ob, struct Bone *bone, float ctime);
+
+/* Handy bone matrix functions */
+void bone_to_mat4(struct Bone *bone, float mat[][4]);
+void bone_to_mat3(struct Bone *bone, float mat[][3]);
+void make_boneMatrixvr (float outmatrix[][4],float delta[3], float roll);
+void make_boneMatrix (float outmatrix[][4], struct Bone *bone);
+void get_bone_root_pos (struct Bone* bone, float vec[3], int posed);
+void get_bone_tip_pos (struct Bone* bone, float vec[3], int posed);
+float get_bone_length (struct Bone *bone);
+void get_objectspace_bone_matrix (struct Bone* bone, float M_accumulatedMatrix[][4], int root, int posed);
+void precalc_bone_irestmat (struct Bone *bone);
+void precalc_armature_posemats (struct bArmature *arm);
+void precalc_bonelist_irestmats (struct ListBase* bonelist);
+void apply_bonemat(struct Bone *bone);
+
+/* void make_armatureParentMatrices (struct bArmature *arm); */
+void precalc_bone_defmat (struct Bone *bone);
+void rebuild_bone_parent_matrix (struct Bone *bone);
+
+/* Animation functions */
+void where_is_bone_time (struct Object *ob, struct Bone *bone, float ctime);
+void where_is_bone (struct Object *ob, struct Bone *bone);
+struct PoseChain *ik_chain_to_posechain (struct Object *ob, struct Bone *bone);
+void solve_posechain (PoseChain *chain);
+void free_posechain (PoseChain *chain);
+
+/* Gameblender hacks */
+void GB_init_armature_deform(struct ListBase *defbase, float premat[][4], float postmat[][4]);
+void GB_calc_armature_deform (float *co, struct MDeformVert *dvert);
+void GB_build_mats (float parmat[][4], float obmat[][4], float premat[][4], float postmat[][4]);
+void GB_validate_defgroups (struct Mesh *mesh, struct ListBase *defbase);
+
+/*void make_boneParentMatrix (struct Bone* bone, float mat[][4]);*/
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/source/blender/blenkernel/BKE_bad_level_calls.h b/source/blender/blenkernel/BKE_bad_level_calls.h
new file mode 100644
index 00000000000..420a915adf6
--- /dev/null
+++ b/source/blender/blenkernel/BKE_bad_level_calls.h
@@ -0,0 +1,143 @@
+/**
+ * blenlib/BKE_bad_level_calls.h (mar-2001 nzc)
+ *
+ * Stuff that definitely does not belong in the kernel! These will all
+ * have to be removed in order to restore sanity.
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BKE_BAD_LEVEL_CALLS_H
+#define BKE_BAD_LEVEL_CALLS_H
+
+/* readfile.c */
+struct PluginSeq;
+void open_plugin_seq(struct PluginSeq *pis, char *seqname);
+struct SpaceButs;
+void set_rects_butspace(struct SpaceButs *buts);
+struct SpaceImaSel;
+void check_imasel_copy(struct SpaceImaSel *simasel);
+struct ScrArea;
+struct bScreen;
+void unlink_screen(struct bScreen *sc);
+void freeAllRad(void);
+void free_editText(void);
+void setscreen(struct bScreen *sc);
+void force_draw_all(void);
+ /* otherwise the WHILE_SEQ doesn't work */
+struct Sequence;
+void build_seqar(struct ListBase *seqbase, struct Sequence ***seqar, int *totseq);
+
+struct ID;
+void BPY_do_pyscript (struct ID *id, short int event);
+
+/* writefile.c */
+struct Oops;
+void free_oops(struct Oops *oops);
+void error(char *str, ...);
+
+/* anim.c */
+extern struct ListBase editNurb;
+
+/* displist.c */
+#include "DNA_world_types.h" /* for render_types */
+#include "render_types.h"
+extern struct RE_Render R;
+float RE_Spec(float, int);
+void waitcursor(int);
+void allqueue(unsigned short event, short val);
+#define REDRAWVIEW3D 0x4010
+struct Material;
+extern struct Material defmaterial;
+
+/* effect.c */
+void RE_jitterate1(float *jit1, float *jit2, int num, float rad1);
+void RE_jitterate2(float *jit1, float *jit2, int num, float rad2);
+
+/* exotic.c */
+void load_editMesh(void);
+void make_editMesh(void);
+void free_editMesh(void);
+void free_editArmature(void);
+void docentre_new(void);
+int saveover(char *str);
+
+/* image.c */
+#include "DNA_image_types.h"
+void free_realtime_image(Image *ima); // has to become a callback, opengl stuff
+void RE_make_existing_file(char *name); // from render, but these funcs should be moved anyway
+
+/* ipo.c */
+void copy_view3d_lock(short val); // was a hack, to make scene layer ipo's possible
+
+/* library.c */
+void allspace(unsigned short event, short val) ;
+#define OOPS_TEST 2
+
+/* mball.c */
+extern ListBase editelems;
+
+/* object.c */
+/* void BPY_free_scriptlink(ScriptLink *slink); */
+/* void BPY_copy_scriptlink(ScriptLink *scriptlink); */
+float *give_cursor(void); // become a callback or argument
+void exit_posemode(int freedata);
+
+/* packedFile.c */
+short pupmenu(char *instr); // will be general callback
+
+/* sca.c */
+#define LEFTMOUSE 0x001 // because of mouse sensor
+
+/* scene.c */
+#include "DNA_sequence_types.h"
+void free_editing(struct Editing *ed); // scenes and sequences problem...
+
+/* texture.c */
+#define FLO 128
+#define INT 96
+struct EnvMap;
+struct Tex;
+void RE_free_envmap(struct EnvMap *env);
+struct EnvMap *RE_copy_envmap(struct EnvMap *env);
+void RE_free_envmapdata(struct EnvMap *env);
+int RE_envmaptex(struct Tex *tex, float *texvec, float *dxt, float *dyt);
+void RE_calc_R_ref(void);
+extern char texstr[15][8]; /* buttons.c */
+
+/* memory for O is declared in the render module... */
+#include "BKE_osa_types.h"
+extern Osa O;
+
+/* editsca.c */
+void make_unique_prop_names(char *str);
+
+#endif
+
diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h
new file mode 100644
index 00000000000..db38a85bfcd
--- /dev/null
+++ b/source/blender/blenkernel/BKE_blender.h
@@ -0,0 +1,64 @@
+/**
+ * blenlib/BKE_blender.h (mar-2001 nzc)
+ *
+ * Blender util stuff?
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BKE_BLENDER_H
+#define BKE_BLENDER_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct ListBase;
+
+#define BLENDER_VERSION 225
+
+int BKE_read_file(char *dir, void *type_r);
+int BKE_read_file_from_memory(char* filebuf, int filelength, void *type_r);
+
+void duplicatelist(struct ListBase *list1, struct ListBase *list2);
+void free_blender(void);
+void initglobals(void);
+
+void pushdata(void *data, int len);
+void popfirst(void *data);
+void poplast(void *data);
+void free_pushpop(void);
+void pushpop_test(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/source/blender/blenkernel/BKE_bmfont.h b/source/blender/blenkernel/BKE_bmfont.h
new file mode 100644
index 00000000000..5fc9045d05e
--- /dev/null
+++ b/source/blender/blenkernel/BKE_bmfont.h
@@ -0,0 +1,64 @@
+/**
+ * blenlib/BKE_bmfont.h (mar-2001 nzc)
+ *
+ *
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BKE_BMFONT_H
+#define BKE_BMFONT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct bmGlyph;
+struct ImBuf;
+struct bmFont;
+
+void printfGlyph(struct bmGlyph * glyph);
+void calcAlpha(struct ImBuf * ibuf);
+void readBitmapFontVersion0(struct ImBuf * ibuf,
+ unsigned char * rect,
+ int step);
+void detectBitmapFont(struct ImBuf *ibuf);
+int locateGlyph(struct bmFont *bmfont, unsigned short unicode);
+void matrixGlyph(struct ImBuf * ibuf, unsigned short unicode,
+ float *centerx, float *centery,
+ float *sizex, float *sizey,
+ float *transx, float *transy,
+ float *movex, float *movey, float *advance);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/source/blender/blenkernel/BKE_bmfont_types.h b/source/blender/blenkernel/BKE_bmfont_types.h
new file mode 100644
index 00000000000..84fa16779dd
--- /dev/null
+++ b/source/blender/blenkernel/BKE_bmfont_types.h
@@ -0,0 +1,61 @@
+/**
+ * blenlib/BKE_bmfont_types.h (mar-2001 nzc)
+ *
+ *
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BKE_BMFONT_TYPES_H
+#define BKE_BMFONT_TYPES_H
+
+#define is_power_of_two(N) ((N ^ (N - 1)) == (2 * N - 1))
+/*
+Moved to IMB_imbuf_types.h where it will live close to the ImBuf type.
+It is used as a userflag bit mask.
+#define IB_BITMAPFONT 1
+*/
+typedef struct bmGlyph {
+ unsigned short unicode;
+ short locx, locy;
+ signed char ofsx, ofsy;
+ unsigned char sizex, sizey;
+ unsigned char advance, reserved;
+} bmGlyph;
+
+typedef struct bmFont {
+ char magic[4];
+ short version;
+ short glyphcount;
+ short xsize, ysize;
+ bmGlyph glyphs[1];
+} bmFont;
+
+#endif
diff --git a/source/blender/blenkernel/BKE_booleanops.h b/source/blender/blenkernel/BKE_booleanops.h
new file mode 100644
index 00000000000..df1906a2c70
--- /dev/null
+++ b/source/blender/blenkernel/BKE_booleanops.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 BKE_BOOLEANOPS_H
+#define BKE_BOOLEANOPS_H
+
+
+struct Mesh;
+struct Object;
+struct Base;
+struct CSG_FaceIteratorDescriptor;
+struct CSG_VertexIteratorDescriptor;
+struct CSG_MeshPropertyDescriptor;
+
+/**
+ * Perform a boolean operation between 2 mesh objects and
+ * add the result as a new mesh into blender data structures.
+ * Assumes you have checked that the 2 objects are infact mesh
+ * objects. Returns 1 on success and zero when it encountered
+ * a problem. In the latter case no object is added and you should
+ * report an appropriate error.
+ */
+extern
+ int
+NewBooleanMesh(
+ struct Base * base,
+ struct Base * base_select,
+ int op_type
+);
+
+
+/**
+ * Functions exposed for use by BKE_booleanops_mesh
+ */
+
+/**
+ * Returns pointers to new mesh descriptors for
+ * the given mesh. Make sure you call FreeMeshDescriptors
+ * after calling this function.
+ */
+
+extern
+ void
+BuildMeshDescriptors(
+ struct Object * ob,
+ struct CSG_FaceIteratorDescriptor * face_it,
+ struct CSG_VertexIteratorDescriptor * vertex_it
+);
+
+extern
+ void
+FreeMeshDescriptors(
+ struct CSG_FaceIteratorDescriptor * face_it,
+ struct CSG_VertexIteratorDescriptor * vertex_it
+);
+
+extern
+ int
+ConvertCSGDescriptorsToMeshObject(
+ struct Object *ob,
+ struct CSG_MeshPropertyDescriptor * props,
+ struct CSG_FaceIteratorDescriptor * face_it,
+ struct CSG_VertexIteratorDescriptor * vertex_it,
+ float parinv[][4]
+);
+
+/**
+ * This little function adds a new mesh object
+ * to the blender object list. It uses ob to duplicate
+ * data as this seems to be easier than cerating a new one.
+ * This new oject contains no faces nor vertices.
+ */
+
+extern
+ struct Object *
+AddNewBlenderMesh(
+ struct Base *base
+);
+
+extern
+ int
+InterpNoUserData(
+ void *d1,
+ void *d2,
+ void *dnew,
+ float epsilon
+);
+
+extern
+ int
+InterpFaceVertexData(
+ void *d1,
+ void *d2,
+ void *dnew,
+ float epsilon
+);
+
+typedef struct {
+ float uv[2];
+ float color[4];
+} FaceVertexData;
+
+typedef struct {
+ struct Material *material;
+
+ /* assorted tface flags */
+ void *tpage;
+ char flag, transp;
+ short mode, tile;
+} FaceData;
+
+
+
+
+#endif
diff --git a/source/blender/blenkernel/BKE_booleanops_mesh.h b/source/blender/blenkernel/BKE_booleanops_mesh.h
new file mode 100644
index 00000000000..9a92df9e3b1
--- /dev/null
+++ b/source/blender/blenkernel/BKE_booleanops_mesh.h
@@ -0,0 +1,122 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BKE_PyBooleanOps_h
+#define BKE_PyBooleanOps_h
+
+#include "CSG_BooleanOps.h"
+
+/**
+ * Internal mesh structure.
+ * Safe to copy by value... hopefully.
+ */
+
+struct Base;
+struct Object;
+struct CSG_MeshDescriptor;
+
+typedef void (*CSG_DestroyMeshFunc)(struct CSG_MeshDescriptor *);
+
+typedef struct CSG_MeshDescriptor {
+ struct Base *base; // Ptr to base of original blender object - used in creating a new object
+ CSG_MeshPropertyDescriptor m_descriptor;
+ CSG_FaceIteratorDescriptor m_face_iterator;
+ CSG_VertexIteratorDescriptor m_vertex_iterator;
+ CSG_DestroyMeshFunc m_destroy_func;
+} CSG_MeshDescriptor;
+
+
+extern
+ int
+CSG_LoadBlenderMesh(
+ struct Object * obj,
+ CSG_MeshDescriptor *output
+);
+
+/**
+ * Destroy the contents of a mesh descriptor.
+ * If the internal descriptor refers to a blender
+ * mesh, no action is performed apart from freeing
+ * internal memory in the desriptor.
+ */
+
+extern
+ void
+CSG_DestroyMeshDescriptor(
+ CSG_MeshDescriptor *mesh
+);
+
+/**
+ * Perform a boolean operation between 2 meshes and return the
+ * result as a new mesh descriptor.
+ * op_type is an integer code of the boolean operation type.
+ * 1 = intersection,
+ * 2 = union,
+ * 3 = difference.
+ */
+
+extern
+ int
+CSG_PerformOp(
+ CSG_MeshDescriptor *mesh1,
+ CSG_MeshDescriptor *mesh2,
+ int op_type,
+ CSG_MeshDescriptor *output
+);
+
+
+
+/**
+ * Add a mesh to blender as a new object.
+ */
+
+extern
+ int
+CSG_AddMeshToBlender(
+ CSG_MeshDescriptor *mesh
+);
+
+/**
+ * Test functionality.
+ */
+
+extern
+ int
+NewBooleanMeshTest(
+ struct Base * base,
+ struct Base * base_select,
+ int op_type
+);
+
+
+
+
+#endif
diff --git a/source/blender/blenkernel/BKE_constraint.h b/source/blender/blenkernel/BKE_constraint.h
new file mode 100644
index 00000000000..2cc323c14ff
--- /dev/null
+++ b/source/blender/blenkernel/BKE_constraint.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 BKE_CONSTRAINT_H
+#define BKE_CONSTRAINT_H
+
+struct bConstraint;
+struct Object;
+struct ListBase;
+struct bConstraintChannel;
+struct bAction;
+struct bArmature;
+
+/* Function prototypes */
+void evaluate_constraint (struct bConstraint *constraint, struct Object *ob, short ownertype, void *ownerdata, float targetmat[][4]);
+void free_constraints (struct ListBase *conlist);
+void copy_constraints (struct ListBase *dst, struct ListBase *src);
+void *copy_constraint_channels (ListBase *dst, ListBase *src);
+struct bConstraintChannel *clone_constraint_channels (struct ListBase *dst, struct ListBase *src, struct bConstraintChannel *oldact);
+void relink_constraints (struct ListBase *list);
+void free_constraint_data (struct bConstraint *con);
+void clear_object_constraint_status (struct Object *ob);
+void do_constraint_channels (struct ListBase *conbase, struct ListBase *chanbase, float ctime);
+short get_constraint_target (struct bConstraint *con, short ownertype, void *ownerdata, float mat[][4], float size[3], float time);
+struct bConstraintChannel *find_constraint_channel (ListBase *list, const char *name);
+void free_constraint_channels (ListBase *chanbase);
+
+/* Constraint target/owner types */
+#define TARGET_OBJECT 1 // string is ""
+#define TARGET_BONE 2 // string is bone-name
+#define TARGET_VERT 3 // string is "VE:#"
+#define TARGET_FACE 4 // string is "FA:#"
+#define TARGET_CV 5 // string is "CV:#"
+
+#endif
diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h
new file mode 100644
index 00000000000..7325594394a
--- /dev/null
+++ b/source/blender/blenkernel/BKE_curve.h
@@ -0,0 +1,86 @@
+/**
+ * blenlib/BKE_curve.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BKE_CURVE_H
+#define BKE_CURVE_H
+
+struct Curve;
+struct ListBase;
+struct Object;
+struct Nurb;
+struct ListBase;
+struct BezTriple;
+struct BevList;
+
+
+int copyintoExtendedArray(float *old, int oldx, int oldy, float *newp, int newx, int newy);
+void unlink_curve( struct Curve *cu);
+void free_curve( struct Curve *cu);
+struct Curve *add_curve(int type);
+struct Curve *copy_curve( struct Curve *cu);
+void make_local_curve( struct Curve *cu);
+void test_curve_type( struct Object *ob);
+void tex_space_curve( struct Curve *cu);
+int count_curveverts( struct ListBase *nurb);
+void freeNurb( struct Nurb *nu);
+void freeNurblist( struct ListBase *lb);
+struct Nurb *duplicateNurb( struct Nurb *nu);
+void duplicateNurblist( struct ListBase *lb1, struct ListBase *lb2);
+void test2DNurb( struct Nurb *nu);
+void minmaxNurb( struct Nurb *nu, float *min, float *max);
+void extend_spline(float * pnts, int in, int out);
+void calcknots(float *knots, short aantal, short order, short type);
+void makecyclicknots(float *knots, short pnts, short order);
+void makeknots( struct Nurb *nu, short uv, short type);
+void basisNurb(float t, short order, short pnts, float *knots, float *basis, int *start, int *end);
+void makeNurbfaces( struct Nurb *nu, float *data);
+void makeNurbcurve_forw(struct Nurb *nu, float *data);
+void makeNurbcurve( struct Nurb *nu, float *data, int dim);
+void maakbez(float q0, float q1, float q2, float q3, float *p, int it);
+void make_orco_surf( struct Curve *cu);
+void makebevelcurve( struct Object *ob, struct ListBase *disp);
+short bevelinside(struct BevList *bl1,struct BevList *bl2);
+int vergxcobev(const void *a1, const void *a2);
+void calc_bevel_sin_cos(float x1, float y1, float x2, float y2, float *sina, float *cosa);
+void alfa_bezpart( struct BezTriple *prevbezt, struct BezTriple *bezt, struct Nurb *nu, float *data_a);
+void makeBevelList( struct Object *ob);
+void calchandleNurb( struct BezTriple *bezt, struct BezTriple *prev, struct BezTriple *next, int mode);
+void calchandlesNurb( struct Nurb *nu);
+void testhandlesNurb( struct Nurb *nu);
+void autocalchandlesNurb( struct Nurb *nu, int flag);
+void autocalchandlesNurb_all(int flag);
+void sethandlesNurb(short code);
+void swapdata(void *adr1, void *adr2, int len);
+void switchdirectionNurb( struct Nurb *nu);
+
+#endif
diff --git a/source/blender/blenkernel/BKE_deform.h b/source/blender/blenkernel/BKE_deform.h
new file mode 100644
index 00000000000..e7494f28fc4
--- /dev/null
+++ b/source/blender/blenkernel/BKE_deform.h
@@ -0,0 +1,50 @@
+/* BKE_deform.h June 2001
+ *
+ * support for deformation groups
+ *
+ * Reevan McKay
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BKE_DEFORM_H
+#define BKE_DEFORM_H
+
+struct Object;
+struct ListBase;
+struct bDeformGroup;
+
+void copy_defgroups (struct ListBase *lb1, struct ListBase *lb2);
+struct bDeformGroup* copy_defgroup (struct bDeformGroup *ingroup);
+void color_temperature (float input, unsigned char *r, unsigned char *g, unsigned char *b);
+
+#endif
+
diff --git a/source/blender/blenkernel/BKE_displist.h b/source/blender/blenkernel/BKE_displist.h
new file mode 100644
index 00000000000..8942a6712d6
--- /dev/null
+++ b/source/blender/blenkernel/BKE_displist.h
@@ -0,0 +1,117 @@
+/* display list (or rather multi purpose list) stuff */
+/*
+ $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BKE_DISPLIST_H
+#define BKE_DISPLIST_H
+
+
+#define DL_POLY 0
+#define DL_SEGM 1
+#define DL_SURF 2
+#define DL_TRIA 3
+#define DL_INDEX3 4
+#define DL_INDEX4 5
+#define DL_VERTCOL 6
+#define DL_VERTS 7
+#define DL_NORS 8
+#define DL_MESH 9
+
+/* EVIL: #define DL_SURFINDEX(cyclu, cyclv, sizeu, sizev) */
+
+/* prototypes */
+
+struct Object;
+struct Curve;
+struct ListBase;
+struct Material;
+struct Bone;
+struct TFace;
+
+typedef struct DispListMesh DispListMesh;
+struct DispListMesh {
+ int totvert, totface;
+ struct MVert *mvert;
+ struct MCol *mcol;
+ struct MFaceInt *mface;
+ struct TFace *tface;
+};
+
+/*
+ * All the different DispList.type's use the
+ * data in the displist structure in fairly
+ * different ways which can be rather confusing,
+ * the best thing to do would be to make a structure
+ * for each displaylist type that has the fields
+ * needed w/ proper names, and then make the actual
+ * DispList structure a typed union.
+ * - zr
+ */
+
+/* needs splitting! */
+typedef struct DispList {
+ struct DispList *next, *prev;
+ short type, flag;
+ int parts, nr;
+ short col, rt; /* rt wordt gebruikt door initrenderNurbs */
+ float *verts, *nors;
+ int *index;
+ unsigned int *col1, *col2;
+ struct DispListMesh *mesh;
+
+ /* Begin NASTY_NLA_STUFF */
+// int *offset, *run; /* Used to index into the bone & weight lists */
+// struct Bone *bones;
+// float *weights;
+ /* End NASTY_NLA_STUFF */
+} DispList;
+
+extern void copy_displist(struct ListBase *lbn, struct ListBase *lb);
+extern void free_disp_elem(DispList *dl);
+extern void free_displist_by_type(struct ListBase *lb, int type);
+extern DispList *find_displist_create(struct ListBase *lb, int type);
+extern DispList *find_displist(struct ListBase *lb, int type);
+extern void addnormalsDispList(struct Object *ob, struct ListBase *lb);
+extern void count_displist(struct ListBase *lb, int *totvert, int *totface);
+extern void curve_to_filledpoly(struct Curve *cu, struct ListBase *dispbase);
+extern void freedisplist(struct ListBase *lb);
+extern void makeDispList(struct Object *ob);
+extern void set_displist_onlyzero(int val);
+extern void shadeDispList(struct Object *ob);
+void freefastshade(void);
+void boundbox_displist(struct Object *ob);
+void imagestodisplist(void);
+void reshadeall_displist(void);
+void test_all_displists(void);
+
+#endif
diff --git a/source/blender/blenkernel/BKE_effect.h b/source/blender/blenkernel/BKE_effect.h
new file mode 100644
index 00000000000..23d504d0607
--- /dev/null
+++ b/source/blender/blenkernel/BKE_effect.h
@@ -0,0 +1,65 @@
+/**
+ * blenlib/BKE_effect.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BKE_EFFECT_H
+#define BKE_EFFECT_H
+
+struct Effect;
+struct ListBase;
+struct Object;
+struct PartEff;
+struct MTex;
+struct Mesh;
+struct WaveEff;
+struct Particle;
+
+struct Effect *add_effect(int type);
+void free_effect(struct Effect *eff);
+void free_effects(struct ListBase *lb);
+struct Effect *copy_effect(struct Effect *eff);
+void copy_act_effect(struct Object *ob);
+void copy_effects(struct ListBase *lbn, struct ListBase *lb);
+void deselectall_eff(struct Object *ob);
+void set_buildvars(struct Object *ob, int *start, int *end);
+struct Particle *new_particle(struct PartEff *paf);
+struct PartEff *give_parteff(struct Object *ob);
+void where_is_particle(struct PartEff *paf, struct Particle *pa, float ctime, float *vec);
+void particle_tex(struct MTex *mtex, struct PartEff *paf, float *co, float *no);
+void make_particle_keys(int depth, int nr, struct PartEff *paf, struct Particle *part, float *force, int deform, struct MTex *mtex);
+void init_mv_jit(float *jit, int num);
+void give_mesh_mvert(struct Mesh *me, int nr, float *co, short *no);
+void build_particle_system(struct Object *ob);
+void calc_wave_deform(struct WaveEff *wav, float ctime, float *co);
+void object_wave(struct Object *ob);
+
+#endif
diff --git a/source/blender/blenkernel/BKE_endian.h b/source/blender/blenkernel/BKE_endian.h
new file mode 100644
index 00000000000..a675ad893c4
--- /dev/null
+++ b/source/blender/blenkernel/BKE_endian.h
@@ -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 *****
+ * Are we little or big endian? From Harbison&Steele.
+ * BKE_ENDIANNESS(a) returns 1 if big endian and returns 0 if little endian
+ */
+#ifndef BKE_ENDIAN_H
+#define BKE_ENDIAN_H
+
+#define BKE_ENDIANNESS(a) { \
+ union { \
+ long l; \
+ char c[sizeof (long)]; \
+ } u; \
+ u.l = 1; \
+ a = (u.c[sizeof (long) - 1] == 1) ? 1 : 0; \
+}
+
+#endif
diff --git a/source/blender/blenkernel/BKE_exotic.h b/source/blender/blenkernel/BKE_exotic.h
new file mode 100644
index 00000000000..7223abb11ab
--- /dev/null
+++ b/source/blender/blenkernel/BKE_exotic.h
@@ -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 *****
+ * dxf/vrml/videoscape external file io function prototypes
+ */
+
+#ifndef BKE_EXOTIC_H
+#define BKE_EXOTIC_H
+
+struct Mesh;
+
+void mcol_to_rgba(unsigned int col, float *r, float *g, float *b, float *a);
+unsigned int *mcol_to_vcol(struct Mesh *me); // used in py_main.c
+
+/**
+ * Reads all 3D fileformats other than Blender fileformat
+ * @retval 0 The file could not be read.
+ * @retval 1 The file was read succesfully.
+ * @attention Used in filesel.c
+ */
+int BKE_read_exotic(char *name);
+
+void write_dxf(char *str);
+void write_vrml(char *str);
+void write_videoscape(char *str);
+
+#endif
diff --git a/source/blender/blenkernel/BKE_font.h b/source/blender/blenkernel/BKE_font.h
new file mode 100644
index 00000000000..51968182663
--- /dev/null
+++ b/source/blender/blenkernel/BKE_font.h
@@ -0,0 +1,50 @@
+/**
+ * blenlib/BKE_vfont.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BKE_VFONT_H
+#define BKE_VFONT_H
+
+struct VFont;
+struct Object;
+struct Curve;
+struct objfnt;
+
+void BKE_font_register_builtin(void *mem, int size);
+
+void free_vfont(struct VFont *sc);
+struct VFont *load_vfont(char *name);
+
+struct chartrans *text_to_curve(struct Object *ob, int mode);
+void font_duplilist(struct Object *par);
+
+#endif
diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h
new file mode 100644
index 00000000000..53c71f03606
--- /dev/null
+++ b/source/blender/blenkernel/BKE_global.h
@@ -0,0 +1,224 @@
+/**
+ * blenlib/BKE_global.h (mar-2001 nzc)
+ *
+ * Global settings, handles, pointers. This is the root for finding
+ * any data in Blender. This block is not serialized, but built anew
+ * for every fresh Blender run.
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BKE_GLOBAL_H
+#define BKE_GLOBAL_H
+
+#include "DNA_listBase.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* forwards */
+struct View3D;
+struct View2D;
+struct SpaceIpo;
+struct SpaceButs;
+struct SpaceImage;
+struct SpaceOops;
+struct SpaceText;
+struct SpaceSound;
+struct SpaceAction;
+struct SpaceNla;
+struct Main;
+struct Scene;
+struct bScreen;
+struct Object;
+struct bSoundListener;
+struct BMF_Font;
+
+typedef struct Global {
+
+ /* active pointers */
+ struct View3D *vd;
+ struct View2D *v2d;
+ struct SpaceIpo *sipo;
+ struct SpaceButs *buts;
+ struct SpaceImage *sima;
+ struct SpaceOops *soops;
+ struct SpaceSound *ssound;
+ struct SpaceAction *saction; /* __NLA */
+ struct SpaceNla *snla;
+ struct Main *main;
+ struct Scene *scene; /* denk aan file.c */
+ struct bScreen *curscreen;
+ struct Object *obedit;
+
+ /* fonts, allocated global data */
+ struct BMF_Font *font, *fonts, *fontss;
+
+ /* strings: lastsaved */
+ char ima[160], sce[160], lib[160];
+
+ /* totalen */
+ short totobj, totlamp, totobjsel, totcurve, totmesh, totmat;
+ int totvert, totface, totvertsel, totfacesel;
+
+ short machine, afbreek, moving, colact, zbuf;
+ short qual, background, imagewin, animspeed;
+ /**
+ * The current version of Blender.
+ */
+ short version;
+ short simulf, fields, order, rt;
+ int f;
+
+ /* Editmode lists */
+ struct ListBase edve;
+ struct ListBase eded;
+ struct ListBase edvl;
+
+ float textcurs[4][2];
+
+ /* Frank's variables */
+ int renderd;
+ int real_sfra, real_efra;
+ int save_over;
+
+ /* Reevan's __NLA variables */
+ struct Object *obpose; /* Current posable object */
+ struct ListBase edbo; /* Armature Editmode bones */
+
+ /* this variable is written to / read from FileGlobal->fileflags */
+ int fileflags;
+
+ /* Janco's playing ground */
+ struct bSoundListener* listener;
+
+ /* Test thingy for Nzc */
+ int magic; /* toggle use of experimental render pipe */
+ int compat; /* toggle compatibility mode for edge rendering */
+ int notonlysolid;/* T-> also edge-render transparent faces */
+ int useRscale; /* bitflag for using colour scaling */
+ int useGscale; /* bitflag for using colour scaling */
+ int useBscale; /* bitflag for using colour scaling */
+ float cscale[4]; /* sliders for colour scaling */
+ int Rhisto; /* flags for making histograms */
+ int Ghisto;
+ int Bhisto;
+
+ /* special versions */
+ short special1, special2;
+
+ int flags;
+
+} Global;
+
+/* **************** GLOBAL ********************* */
+
+/* G.f */
+#define G_DISABLE_OK 1
+#define G_PLAYANIM 2
+#define G_TEST_DUPLI 4
+#define G_SIMULATION 8
+#define G_BACKBUFSEL 16
+#define G_PICKSEL 32
+#define G_DRAWNORMALS 64
+#define G_DRAWFACES 128
+#define G_FACESELECT 256
+#define G_DRAW_EXT 512
+#define G_VERTEXPAINT 1024
+#define G_ALLEDGES 2048
+#define G_DEBUG 4096
+#define G_SCENESCRIPT 8192
+#define G_PROPORTIONAL 16384
+#define G_WEIGHTPAINT 32768 /* __NLA */
+#define G_TEXTUREPAINT 65536
+#define G_NOFROZEN (1 << 17) // frozen modules inactive
+
+/* G.fileflags */
+
+#define G_AUTOPACK_BIT 0
+#define G_FILE_COMPRESS_BIT 1
+#define G_FILE_AUTOPLAY_BIT 2
+#define G_FILE_ENABLE_ALL_FRAMES_BIT 3
+#define G_FILE_SHOW_DEBUG_PROPS_BIT 4
+#define G_FILE_SHOW_FRAMERATE_BIT 5
+#define G_FILE_SHOW_PROFILE_BIT 6
+#define G_FILE_LOCK_BIT 7
+#define G_FILE_SIGN_BIT 8
+#define G_FILE_PUBLISH_BIT 9
+
+#define G_AUTOPACK (1 << G_AUTOPACK_BIT)
+#define G_FILE_COMPRESS (1 << G_FILE_COMPRESS_BIT)
+#define G_FILE_AUTOPLAY (1 << G_FILE_AUTOPLAY_BIT)
+#define G_FILE_ENABLE_ALL_FRAMES (1 << G_FILE_ENABLE_ALL_FRAMES_BIT)
+#define G_FILE_SHOW_DEBUG_PROPS (1 << G_FILE_SHOW_DEBUG_PROPS_BIT)
+#define G_FILE_SHOW_FRAMERATE (1 << G_FILE_SHOW_FRAMERATE_BIT)
+#define G_FILE_SHOW_PROFILE (1 << G_FILE_SHOW_PROFILE_BIT)
+#define G_FILE_LOCK (1 << G_FILE_LOCK_BIT)
+#define G_FILE_SIGN (1 << G_FILE_SIGN_BIT)
+#define G_FILE_PUBLISH (1 << G_FILE_PUBLISH_BIT)
+
+/* G.simulf */
+#define G_LOADFILE 2
+#define G_RESTART 4
+#define G_QUIT 8
+#define G_SETSCENE 16
+
+/* G.flags: double? */
+#define G_FLAGS_AUTOPLAY_BIT 2
+#define G_FLAGS_AUTOPLAY (1 << G_FLAGS_AUTOPLAY_BIT)
+
+/* G.qual */
+#define R_SHIFTKEY 1
+#define L_SHIFTKEY 2
+#define LR_SHIFTKEY 3
+#define R_ALTKEY 4
+#define L_ALTKEY 8
+#define LR_ALTKEY 12
+#define R_CTRLKEY 16
+#define L_CTRLKEY 32
+#define LR_CTRLKEY 48
+
+/* G.order: indicates what endianness the platform where the file was
+ * written had. */
+#define L_ENDIAN 1
+#define B_ENDIAN 0
+
+/* G.special1 */
+#define G_HOLO 1
+
+/* Memory is allocated where? blender.c */
+extern Global G;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/source/blender/blenkernel/BKE_group.h b/source/blender/blenkernel/BKE_group.h
new file mode 100644
index 00000000000..ef000e2c370
--- /dev/null
+++ b/source/blender/blenkernel/BKE_group.h
@@ -0,0 +1,58 @@
+/**
+ * blenlib/BKE_group.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BKE_GROUP_H
+#define BKE_GROUP_H
+struct Group;
+struct GroupKey;
+struct GroupObject;
+struct ObjectKey;
+struct Object;
+
+void free_object_key(struct ObjectKey *ok);
+void free_group_object(struct GroupObject *go);
+void free_group(struct Group *group);
+struct Group *add_group(void);
+void object_to_obkey(struct Object *ob, struct ObjectKey *ok);
+void obkey_to_object(struct ObjectKey *ok, struct Object *ob);
+void add_object_key(struct GroupObject *go, struct GroupKey *gk);
+void add_to_group(struct Group *group, struct Object *ob);
+void rem_from_group(struct Group *group, struct Object *ob);
+void add_group_key(struct Group *group);
+void set_object_key(struct Object *ob, struct ObjectKey *ok);
+void set_group_key(struct Group *group);
+struct Group *find_group(struct Object *ob);
+void set_group_key_name(struct Group *group, char *name);
+void set_group_key_frame(struct Group *group, float frame);
+
+#endif
diff --git a/source/blender/blenkernel/BKE_ika.h b/source/blender/blenkernel/BKE_ika.h
new file mode 100644
index 00000000000..053414d9359
--- /dev/null
+++ b/source/blender/blenkernel/BKE_ika.h
@@ -0,0 +1,59 @@
+/**
+ * blenlib/BKE_ika.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BKE_IKA_H
+#define BKE_IKA_H
+
+struct Ika;
+struct Limb;
+struct Object;
+
+void unlink_ika(struct Ika *ika);
+void free_ika(struct Ika *ika);
+struct Ika *add_ika(void);
+struct Ika *copy_ika(struct Ika *ika);
+void make_local_ika(struct Ika *ika);
+int count_limbs(struct Object *ob);
+void calc_limb(struct Limb *li);
+void calc_ika(struct Ika *ika, struct Limb *li);
+void init_defstate_ika(struct Object *ob);
+void itterate_limb(struct Ika *ika, struct Limb *li);
+void rotate_ika(struct Object *ob, struct Ika *ika);
+void rotate_ika_xy(struct Object *ob, struct Ika *ika);
+void itterate_ika(struct Object *ob);
+void do_all_ikas(void);
+void do_all_visible_ikas(void);
+void init_skel_deform(struct Object *par, struct Object *ob);
+void calc_skel_deform(struct Ika *ika, float *co);
+
+#endif
diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h
new file mode 100644
index 00000000000..4783b66706a
--- /dev/null
+++ b/source/blender/blenkernel/BKE_image.h
@@ -0,0 +1,67 @@
+/**
+ * blenlib/BKE_image.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BKE_IMAGE_H
+#define BKE_IMAGE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct Image;
+struct ImBuf;
+struct Tex;
+struct anim;
+
+void free_image(struct Image *me);
+void free_image_buffers(struct Image *ima);
+struct Image *add_image(char *name);
+void free_unused_animimages(void);
+void makepicstring(char *string, int frame);
+struct anim *openanim(char * name, int flags);
+int calcimanr(int cfra, struct Tex *tex);
+void do_laseroptics_patch(struct ImBuf *ibuf);
+void de_interlace_ng(struct ImBuf *ibuf);
+void de_interlace_st(struct ImBuf *ibuf);
+void load_image(struct Image * ima, int flags, char *relabase, int framenum);
+void ima_ibuf_is_nul(struct Tex *tex);
+int imagewrap(struct Tex *tex, float *texvec);
+int imagewraposa(struct Tex *tex, float *texvec, float *dxt, float *dyt);
+void converttopremul(struct ImBuf *ibuf);
+void makemipmap(struct Image *ima);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/source/blender/blenkernel/BKE_ipo.h b/source/blender/blenkernel/BKE_ipo.h
new file mode 100644
index 00000000000..4a68884d53c
--- /dev/null
+++ b/source/blender/blenkernel/BKE_ipo.h
@@ -0,0 +1,101 @@
+/**
+ * blenlib/BKE_ipo.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BKE_IPO_H
+#define BKE_IPO_H
+
+typedef struct CfraElem {
+ struct CfraElem *next, *prev;
+ float cfra;
+ int sel;
+} CfraElem;
+
+struct Ipo;
+struct IpoCurve;
+struct MTex;
+struct Material;
+struct Object;
+struct Sequence;
+struct ListBase;
+struct BezTriple;
+/* struct IPO_Channel; */
+
+float frame_to_float(int cfra);
+void free_ipo(struct Ipo *ipo);
+struct Ipo *add_ipo(char *name, int idcode);
+struct Ipo *copy_ipo(struct Ipo *ipo);
+void make_local_obipo(struct Ipo *ipo);
+void make_local_matipo(struct Ipo *ipo);
+void make_local_keyipo(struct Ipo *ipo);
+void make_local_ipo(struct Ipo *ipo);
+void calchandles_ipocurve(struct IpoCurve *icu);
+void testhandles_ipocurve(struct IpoCurve *icu);
+void sort_time_ipocurve(struct IpoCurve *icu);
+int test_time_ipocurve(struct IpoCurve *icu);
+void correct_bezpart(float *v1, float *v2, float *v3, float *v4);
+int findzero(float x, float q0, float q1, float q2, float q3, float *o);
+void berekeny(float f1, float f2, float f3, float f4, float *o, int b);
+void berekenx(float *f, float *o, int b);
+float eval_icu(struct IpoCurve *icu, float ipotime);
+void calc_icu(struct IpoCurve *icu, float ctime);
+float calc_ipo_time(struct Ipo *ipo, float ctime);
+void calc_ipo(struct Ipo *ipo, float ctime);
+void write_ipo_poin(void *poin, int type, float val);
+float read_ipo_poin(void *poin, int type);
+void *give_mtex_poin(struct MTex *mtex, int adrcode );
+void *get_ipo_poin(struct ID *id, struct IpoCurve *icu, int *type);
+void set_icu_vars(struct IpoCurve *icu);
+void execute_ipo(struct ID *id, struct Ipo *ipo);
+void do_ipo_nocalc(struct Ipo *ipo);
+void do_ipo(struct Ipo *ipo);
+void do_mat_ipo(struct Material *ma);
+void do_ob_ipo(struct Object *ob);
+void do_seq_ipo(struct Sequence *seq);
+int has_ipo_code(struct Ipo *ipo, int code);
+void do_all_ipos(void);
+int calc_ipo_spec(struct Ipo *ipo, int adrcode, float *ctime);
+void clear_delta_obipo(struct Ipo *ipo);
+void add_to_cfra_elem(struct ListBase *lb, struct BezTriple *bezt);
+void make_cfra_list(struct Ipo *ipo, struct ListBase *elems);
+/* the sort is an IPO_Channel... */
+int IPO_GetChannels(struct Ipo *ipo, short *channels);
+void test_ipo_get(void);
+
+float IPO_GetFloatValue(struct Ipo *ipo,
+/* struct IPO_Channel channel, */
+ /* channels are shorts... bit ugly for now*/
+ short c,
+ float ctime);
+
+
+#endif
diff --git a/source/blender/blenkernel/BKE_key.h b/source/blender/blenkernel/BKE_key.h
new file mode 100644
index 00000000000..4ad76e3943c
--- /dev/null
+++ b/source/blender/blenkernel/BKE_key.h
@@ -0,0 +1,69 @@
+/**
+ * blenlib/BKE_key.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BKE_KEY_H
+#define BKE_KEY_H
+
+struct Key;
+struct KeyBlock;
+struct ID;
+struct ListBase;
+struct Curve;
+struct Object;
+struct Lattice;
+struct Mesh;
+
+void free_key(struct Key *sc);
+struct Key *add_key(struct ID *id);
+struct Key *copy_key(struct Key *key);
+void make_local_key(struct Key *key);
+void sort_keys(struct Key *key);
+void set_four_ipo(float d, float *data, int type);
+void set_afgeleide_four_ipo(float d, float *data, int type);
+int setkeys(float fac, struct ListBase *lb, struct KeyBlock *k[], float *t, int cycl);
+void flerp(int aantal, float *in, float *f0, float *f1, float *f2, float *f3, float *t);
+void cp_key(int start, int end, int tot, char *poin, struct Key *key, struct KeyBlock *k, int mode);
+void cp_cu_key(struct Curve *cu, struct KeyBlock *kb, int start, int end);
+void rel_flerp(int aantal, float *in, float *ref, float *out, float fac);
+void do_rel_key(int start, int end, int tot, char *basispoin, struct Key *key, float ctime, int mode);
+void do_key(int start, int end, int tot, char *poin, struct Key *key, struct KeyBlock **k, float *t, int mode);
+void do_mesh_key(struct Mesh *me);
+void do_cu_key(struct Curve *cu, struct KeyBlock **k, float *t);
+void do_rel_cu_key(struct Curve *cu, float ctime);
+void do_curve_key(struct Curve *cu);
+void do_latt_key(struct Lattice *lt);
+void do_all_keys(void);
+void do_ob_key(struct Object *ob);
+void do_spec_key(struct Key *key);
+
+#endif
diff --git a/source/blender/blenkernel/BKE_lattice.h b/source/blender/blenkernel/BKE_lattice.h
new file mode 100644
index 00000000000..747dc27e175
--- /dev/null
+++ b/source/blender/blenkernel/BKE_lattice.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 *****
+ * june-2001 ton
+ */
+
+#ifndef BKE_LATTICE_H
+#define BKE_LATTICE_H
+
+struct Lattice;
+struct Object;
+struct BPoint;
+
+extern struct Lattice *editLatt;
+extern int lt_applyflag;
+
+
+void resizelattice(struct Lattice *lt);
+struct Lattice *add_lattice(void);
+struct Lattice *copy_lattice(struct Lattice *lt);
+void free_lattice(struct Lattice *lt);
+void make_local_lattice(struct Lattice *lt);
+void calc_lat_fudu(int flag, int res, float *fu, float *du);
+void init_latt_deform(struct Object *oblatt, struct Object *ob);
+void calc_latt_deform(float *co);
+void end_latt_deform(void);
+int object_deform(struct Object *ob);
+struct BPoint *latt_bp(struct Lattice *lt, int u, int v, int w);
+void outside_lattice(struct Lattice *lt);
+
+
+#endif
diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h
new file mode 100644
index 00000000000..4e8c9a61c19
--- /dev/null
+++ b/source/blender/blenkernel/BKE_library.h
@@ -0,0 +1,69 @@
+/**
+ * blenlib/BKE_library.h (mar-2001 nzc)
+ *
+ * Library
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BKE_LIBRARY_TYPES_H
+#define BKE_LIBRARY_TYPES_H
+
+struct ListBase;
+struct ID;
+struct Main;
+struct Library;
+
+void *alloc_libblock(struct ListBase *lb, short type, char *name);
+void *copy_libblock(void *rt);
+
+void id_lib_extern(struct ID *id);
+void id_us_plus(struct ID *id);
+
+int new_id(struct ListBase *lb, struct ID *id, char *name);
+
+struct ListBase *wich_libbase(struct Main *mainlib, short type);
+int set_listbasepointers(struct Main *main, struct ListBase **lb);
+
+void free_libblock(struct ListBase *lb, void *idv);
+void free_libblock_us(struct ListBase *lb, void *idv);
+void free_main(struct Main *mainvar);
+
+void splitIDname(char *name, char *left, int *nr);
+void rename_id(struct ID *id, char *name);
+void test_idbutton(char *name);
+void all_local(void);
+struct ID *find_id(char *type, char *name);
+void clear_id_newpoins(void);
+
+void IDnames_to_pupstring(char **str, char *title, char *extraops, struct ListBase *lb,struct ID* link, short *nr);
+void IPOnames_to_pupstring(char **str, char *title, char *extraops, struct ListBase *lb, struct ID* link, short *nr, int blocktype);
+
+#endif
diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h
new file mode 100644
index 00000000000..2e16db34e00
--- /dev/null
+++ b/source/blender/blenkernel/BKE_main.h
@@ -0,0 +1,80 @@
+/**
+ * blenlib/BKE_main.h (mar-2001 nzc)
+ *
+ * Main is the root of the 'database' of a Blender context. All data
+ * is stuffed into lists, and all these lists are knotted to here. A
+ * Blender file is not much more but a binary dump of these
+ * lists. This list of lists is not serialized itself.
+ *
+ * Oops... this should be a _types.h file.
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BKE_MAIN_H
+#define BKE_MAIN_H
+
+#include "DNA_listBase.h"
+
+struct Library;
+
+typedef struct Main {
+ struct Main *next, *prev;
+ char name[160];
+ short versionfile, rt;
+ struct Library *curlib;
+ ListBase scene;
+ ListBase library;
+ ListBase object;
+ ListBase mesh;
+ ListBase curve;
+ ListBase mball;
+ ListBase mat;
+ ListBase tex;
+ ListBase image;
+ ListBase ika;
+ ListBase wave;
+ ListBase latt;
+ ListBase lamp;
+ ListBase camera;
+ ListBase ipo;
+ ListBase key;
+ ListBase world;
+ ListBase screen;
+ ListBase vfont;
+ ListBase text;
+ ListBase sound;
+ ListBase group;
+ ListBase armature; /* NLA */
+ ListBase action; /* NLA */
+} Main;
+
+
+#endif
diff --git a/source/blender/blenkernel/BKE_material.h b/source/blender/blenkernel/BKE_material.h
new file mode 100644
index 00000000000..8533505776e
--- /dev/null
+++ b/source/blender/blenkernel/BKE_material.h
@@ -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 *****
+ * General operations, lookup, etc. for materials.
+ */
+
+#ifndef BKE_MATERIAL_H
+#define BKE_MATERIAL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct Material;
+struct ID;
+struct Object;
+
+void free_material(struct Material *sc);
+void test_object_materials(struct ID *id);
+void init_material(struct Material *ma);
+struct Material *add_material(char *name);
+struct Material *copy_material(struct Material *ma);
+void make_local_material(struct Material *ma);
+struct Material ***give_matarar(struct Object *ob);
+short *give_totcolp(struct Object *ob);
+struct Material *give_current_material(struct Object *ob, int act);
+ID *material_from(struct Object *ob, int act);
+void assign_material(struct Object *ob, struct Material *ma, int act);
+void new_material_to_objectdata(struct Object *ob);
+void init_render_material(struct Material *ma);
+void init_render_materials(void);
+void end_render_material(struct Material *ma);
+void end_render_materials(void);
+void automatname(struct Material *ma);
+void delete_material_index(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/source/blender/blenkernel/BKE_mball.h b/source/blender/blenkernel/BKE_mball.h
new file mode 100644
index 00000000000..c04ce03f176
--- /dev/null
+++ b/source/blender/blenkernel/BKE_mball.h
@@ -0,0 +1,64 @@
+/**
+ * blenlib/BKE_mball.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BKE_MBALL_H
+#define BKE_MBALL_H
+
+struct MetaBall;
+struct Object;
+struct MetaElem;
+struct VERTICES;
+struct VERTEX;
+struct MB_POINT;
+struct PROCESS;
+struct CUBE;
+struct PROCESS;
+
+void unlink_mball(struct MetaBall *mb);
+void free_mball(struct MetaBall *mb);
+struct MetaBall *add_mball(void);
+struct MetaBall *copy_mball(struct MetaBall *mb);
+void make_local_mball(struct MetaBall *mb);
+void tex_space_mball( struct Object *ob);
+void make_orco_mball( struct Object *ob);
+struct Object *find_basis_mball( struct Object *ob);
+void metaball_polygonize(struct Object *ob);
+void calc_mballco(struct MetaElem *ml, float *vec);
+float densfunc(struct MetaElem *ball, float x, float y, float z);
+float metaball(float x, float y, float z);
+void accum_mballfaces(int i1, int i2, int i3, int i4);
+void *new_pgn_element(int size);
+int nextcwedge (int edge, int face);
+void BKE_freecubetable(void);
+
+#endif
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
new file mode 100644
index 00000000000..1f551f8afe0
--- /dev/null
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -0,0 +1,116 @@
+/**
+ * blenlib/BKE_mesh.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BKE_MESH_H
+#define BKE_MESH_H
+
+/* texflag */
+#define AUTOSPACE 1
+
+/* me->flag (let op alternatieven in blendpsx.h) */
+#define ME_ISDONE 1
+#define ME_NOPUNOFLIP 2
+#define ME_TWOSIDED 4
+#define ME_UVEFFECT 8
+#define ME_VCOLEFFECT 16
+#define ME_AUTOSMOOTH 32
+#define ME_SMESH 64
+#define ME_SUBSURF 128
+
+/* puno (mface) */
+#define ME_FLIPV1 1
+#define ME_FLIPV2 2
+#define ME_FLIPV3 4
+#define ME_FLIPV4 8
+#define ME_PROJXY 16
+#define ME_PROJXZ 32
+#define ME_PROJYZ 64
+
+/* edcode (mface) */
+#define ME_V1V2 1
+#define ME_V2V3 2
+#define ME_V3V1 4
+#define ME_V3V4 4
+#define ME_V4V1 8
+
+/* flag (mface) */
+#define ME_SMOOTH 1
+
+/***/
+
+struct DispList;
+struct ListBase;
+struct MDeformVert;
+struct Mesh;
+struct MFace;
+struct MVert;
+struct Object;
+struct TFace;
+struct VecNor;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void unlink_mesh(struct Mesh *me);
+void free_mesh(struct Mesh *me);
+struct Mesh *add_mesh(void);
+struct Mesh *copy_mesh(struct Mesh *me);
+void make_local_tface(struct Mesh *me);
+void make_local_mesh(struct Mesh *me);
+void boundbox_mesh(struct Mesh *me, float *loc, float *size);
+void tex_space_mesh(struct Mesh *me);
+void make_orco_displist_mesh(struct Object *ob, int subdivlvl);
+void make_orco_mesh(struct Mesh *me);
+void test_index_mface(struct MFace *mface, int nr);
+void test_index_face(struct MFace *mface, struct TFace *tface, int nr);
+void flipnorm_mesh(struct Mesh *me);
+struct Mesh *get_mesh(struct Object *ob);
+void set_mesh(struct Object *ob, struct Mesh *me);
+void mball_to_mesh(struct ListBase *lb, struct Mesh *me);
+void nurbs_to_mesh(struct Object *ob);
+void edge_drawflags_mesh(struct Mesh *me);
+void mcol_to_tface(struct Mesh *me, int freedata);
+void tface_to_mcol(struct Mesh *me);
+void free_dverts(struct MDeformVert *dvert, int totvert);
+void copy_dverts(struct MDeformVert *dst, struct MDeformVert *src, int totvert); /* __NLA */
+int mesh_uses_displist(struct Mesh *me);
+int rendermesh_uses_displist(struct Mesh *me);
+float get_mvert_weight (struct Object *ob, int vert, int defgroup);
+int update_realtime_texture(struct TFace *tface, double time);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h
new file mode 100644
index 00000000000..9f1ad39f7a6
--- /dev/null
+++ b/source/blender/blenkernel/BKE_nla.h
@@ -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 *****
+ */
+
+#ifndef BKE_NLA_H
+#define BKE_NLA_H
+
+struct bActionStrip;
+struct ListBase;
+
+void free_actionstrip(struct bActionStrip* strip);
+void free_nlastrips (struct ListBase *nlalist);
+void copy_nlastrips (struct ListBase *dst, struct ListBase *src);
+void copy_actionstrip (struct bActionStrip **dst, struct bActionStrip **src);
+
+#endif
+
+
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
new file mode 100644
index 00000000000..b29a051a4db
--- /dev/null
+++ b/source/blender/blenkernel/BKE_object.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 *****
+ * General operations, lookup, etc. for blender objects.
+ */
+
+#ifndef BKE_OBJECT_H
+#define BKE_OBJECT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct Base;
+struct Object;
+struct Camera;
+struct BoundBox;
+struct View3D;
+
+void clear_workob(void);
+void copy_baseflags(void);
+void copy_objectflags(void);
+void update_base_layer(struct Object *ob);
+void free_object(struct Object *ob);
+void unlink_object(struct Object *ob);
+int exist_object(struct Object *obtest);
+void *add_camera(void);
+struct Camera *copy_camera(struct Camera *cam);
+void make_local_camera(struct Camera *cam);
+void *add_lamp(void);
+struct Lamp *copy_lamp(struct Lamp *la);
+void make_local_lamp(struct Lamp *la);
+void free_camera(struct Camera *ca);
+void free_lamp(struct Lamp *la);
+void *add_wave(void);
+
+struct Object *add_object(int type);
+void base_init_from_view3d(struct Base *base, struct View3D *v3d);
+
+struct Object *copy_object(struct Object *ob);
+void expand_local_object(struct Object *ob);
+void make_local_object(struct Object *ob);
+void set_mblur_offs(int blur);
+void disable_speed_curve(int val);
+float bsystem_time(struct Object *ob, struct Object *par, float cfra, float ofs);
+void object_to_mat3(struct Object *ob, float mat[][3]);
+void object_to_mat4(struct Object *ob, float mat[][4]);
+void ob_parcurve(struct Object *ob, struct Object *par, float mat[][4]);
+void ob_parlimb(struct Object *ob, struct Object *par, float mat[][4]);
+void ob_parbone(struct Object *ob, struct Object *par, float mat[][4]); /* __NLA */
+void give_parvert(struct Object *par, int nr, float *vec);
+void ob_parvert3(struct Object *ob, struct Object *par, float mat[][4]);
+void set_no_parent_ipo(int val);
+void set_dtime(int dtime);
+void disable_where_script(short on);
+int during_script(void);
+void where_is_object_time(struct Object *ob, float ctime);
+void where_is_object(struct Object *ob);
+void where_is_object_simul(struct Object *ob);
+void what_does_parent1(struct Object *par, int partype, int par1, int par2, int par3);
+void what_does_parent(struct Object *ob);
+struct BoundBox *unit_boundbox(void);
+void minmax_object(struct Object *ob, float *min, float *max);
+void solve_tracking (struct Object *ob, float targetmat[][4]);
+void solve_constraints (struct Object *ob, short obtype, void *obdata, float ctime);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/source/blender/blenkernel/BKE_osa_types.h b/source/blender/blenkernel/BKE_osa_types.h
new file mode 100644
index 00000000000..f6ccf5e7e31
--- /dev/null
+++ b/source/blender/blenkernel/BKE_osa_types.h
@@ -0,0 +1,53 @@
+/**
+ * blenlib/BKE_osa_types.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BKE_OSA_TYPES_H
+#define BKE_OSA_TYPES_H
+
+/* typedef struct Osa */
+typedef struct RE_Osa
+{
+ float dxco[3], dyco[3];
+ float dxlo[3], dylo[3], dxgl[3], dygl[3], dxuv[3], dyuv[3];
+ float dxref[3], dyref[3], dxorn[3], dyorn[3];
+ float dxno[3], dyno[3], dxview, dyview;
+ float dxlv[3], dylv[3];
+ float dxwin[3], dywin[3];
+ float dxsticky[3], dysticky[3];
+} Osa;
+
+/* extern Osa O; */
+/* This one used to be done in render/extern/include/render.h, because
+ memory was allocated in that module. (nzc)*/
+
+#endif
diff --git a/source/blender/blenkernel/BKE_packedFile.h b/source/blender/blenkernel/BKE_packedFile.h
new file mode 100644
index 00000000000..16b6c996aab
--- /dev/null
+++ b/source/blender/blenkernel/BKE_packedFile.h
@@ -0,0 +1,61 @@
+/**
+ * blenlib/BKE_packedFile.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BKE_PACKEDFILE_H
+#define BKE_PACKEDFILE_H
+
+struct PackedFile;
+struct VFont;
+struct bSample;
+struct bSound;
+struct Image;
+
+struct PackedFile * newPackedFile(char * filename);
+struct PackedFile * newPackedFileMemory(void *mem, int memlen);
+
+int seekPackedFile(struct PackedFile * pf, int offset, int whence);
+void rewindPackedFile(struct PackedFile * pf);
+int readPackedFile(struct PackedFile * pf, void * data, int size);
+int countPackedFiles(void);
+void freePackedFile(struct PackedFile * pf);
+void packAll(void);
+int writePackedFile(char * filename, struct PackedFile *pf);
+int checkPackedFile(char * filename, struct PackedFile * pf);
+char * unpackFile(char * abs_name, char * local_name, struct PackedFile * pf, int how);
+int unpackVFont(struct VFont * vfont, int how);
+void create_local_name(char *localname, char *prefix, char *filename);
+int unpackSample(struct bSample *sample, int how);
+int unpackImage(struct Image * ima, int how);
+void unpackAll(int how);
+
+#endif
diff --git a/source/blender/blenkernel/BKE_plugin_types.h b/source/blender/blenkernel/BKE_plugin_types.h
new file mode 100644
index 00000000000..3da89561aac
--- /dev/null
+++ b/source/blender/blenkernel/BKE_plugin_types.h
@@ -0,0 +1,70 @@
+/**
+ * blenlib/BKE_plugin_types.h (mar-2001 nzc)
+ *
+ * Renderrecipe and scene decription. The fact that there is a
+ * hierarchy here is a bit strange, and not desirable.
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BKE_PLUGIN_TYPES_H
+#define BKE_PLUGIN_TYPES_H
+
+struct ImBuf;
+
+typedef int (*TexDoit)(int, void*, float*, float*, float*);
+typedef void (*SeqDoit)(void*, float, float, int, int,
+ struct ImBuf*, struct ImBuf*,
+ struct ImBuf*, struct ImBuf*);
+
+typedef struct VarStruct {
+ int type;
+ char name[16];
+ float def, min, max;
+ char tip[80];
+} VarStruct;
+
+typedef struct _PluginInfo {
+ char *name;
+ char *snames;
+
+ int stypes;
+ int nvars;
+ VarStruct *varstr;
+ float *result;
+ float *cfra;
+
+ void (*init)(void);
+ void (*callback)(int);
+ TexDoit tex_doit;
+ SeqDoit seq_doit;
+} PluginInfo;
+
+#endif
diff --git a/source/blender/blenkernel/BKE_property.h b/source/blender/blenkernel/BKE_property.h
new file mode 100644
index 00000000000..8dd3f3e085b
--- /dev/null
+++ b/source/blender/blenkernel/BKE_property.h
@@ -0,0 +1,54 @@
+/**
+ * blenkernel/BKE_property.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BKE_PROPERTY_H
+#define BKE_PROPERTY_H
+
+struct bProperty;
+struct ListBase;
+struct Object;
+
+void free_property(struct bProperty *prop);
+void free_properties(struct ListBase *lb);
+struct bProperty *copy_property(struct bProperty *prop);
+void copy_properties(struct ListBase *lbn, struct ListBase *lbo);
+void init_property(struct bProperty *prop);
+struct bProperty *new_property(int type);
+struct bProperty *get_property(struct Object *ob, char *name);
+int compare_property(struct bProperty *prop, char *str);
+void set_property(struct bProperty *prop, char *str);
+void add_property(struct bProperty *prop, char *str);
+void set_property_valstr(struct bProperty *prop, char *str);
+void cp_property(struct bProperty *prop1, struct bProperty *prop2);
+
+#endif
diff --git a/source/blender/blenkernel/BKE_sca.h b/source/blender/blenkernel/BKE_sca.h
new file mode 100644
index 00000000000..c3ad581852d
--- /dev/null
+++ b/source/blender/blenkernel/BKE_sca.h
@@ -0,0 +1,74 @@
+/**
+ * blenlib/BKE_sca.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BKE_SCA_H
+#define BKE_SCA_H
+
+struct Text;
+struct bSensor;
+struct Object;
+struct bController;
+struct bActuator;
+
+void unlink_controller(struct bController *cont);
+void unlink_controllers(struct ListBase *lb);
+void free_controller(struct bController *cont);
+void free_controllers(struct ListBase *lb);
+
+void unlink_actuator(struct bActuator *act);
+void unlink_actuators(struct ListBase *lb);
+void free_actuator(struct bActuator *act);
+void free_actuators(struct ListBase *lb);
+
+void free_text_controllers(struct Text *txt);
+void free_sensor(struct bSensor *sens);
+void free_sensors(struct ListBase *lb);
+struct bSensor *copy_sensor(struct bSensor *sens);
+void copy_sensors(struct ListBase *lbn, struct ListBase *lbo);
+void init_sensor(struct bSensor *sens);
+struct bSensor *new_sensor(int type);
+struct bController *copy_controller(struct bController *cont);
+void copy_controllers(struct ListBase *lbn, struct ListBase *lbo);
+void init_controller(struct bController *cont);
+struct bController *new_controller(int type);
+struct bActuator *copy_actuator(struct bActuator *act);
+void copy_actuators(struct ListBase *lbn, struct ListBase *lbo);
+void init_actuator(struct bActuator *act);
+struct bActuator *new_actuator(int type);
+void clear_sca_new_poins_ob(struct Object *ob);
+void clear_sca_new_poins(void);
+void set_sca_new_poins_ob(struct Object *ob);
+void set_sca_new_poins(void);
+void sca_remove_ob_poin(struct Object *obt, struct Object *ob);
+
+#endif
diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h
new file mode 100644
index 00000000000..ff4b4c6f258
--- /dev/null
+++ b/source/blender/blenkernel/BKE_scene.h
@@ -0,0 +1,56 @@
+/**
+ * blenlib/BKE_scene.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BKE_SCENE_H
+#define BKE_SCENE_H
+
+struct Scene;
+struct Object;
+struct Base;
+struct AviCodecData;
+
+void free_avicodecdata(struct AviCodecData *acd);
+void free_scene(struct Scene *me);
+struct Scene *add_scene(char *name);
+int object_in_scene(struct Object *ob, struct Scene *sce);
+void sort_baselist(struct Scene *sce);
+void set_scene_bg(struct Scene *sce);
+void set_scene_name(char *name);
+int next_object(int val, struct Base **base, struct Object **ob);
+struct Object *scene_find_camera(struct Scene *sc);
+
+struct Base *scene_add_base(struct Scene *sce, struct Object *ob);
+void scene_deselect_all(struct Scene *sce);
+void scene_select_base(struct Scene *sce, struct Base *selbase);
+
+#endif
diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h
new file mode 100644
index 00000000000..b64caa6dfef
--- /dev/null
+++ b/source/blender/blenkernel/BKE_screen.h
@@ -0,0 +1,40 @@
+/**
+ * blenlib/BKE_screen.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BKE_SCREEN_H
+#define BKE_SCREEN_H
+
+void free_screen(struct bScreen *sc);
+
+
+#endif
diff --git a/source/blender/blenkernel/BKE_sound.h b/source/blender/blenkernel/BKE_sound.h
new file mode 100644
index 00000000000..3010bc2d87a
--- /dev/null
+++ b/source/blender/blenkernel/BKE_sound.h
@@ -0,0 +1,51 @@
+/**
+ * sound.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BKE_SOUND_H
+#define BKE_SOUND_H
+
+struct PackedFile;
+struct bSound;
+struct bSample;
+struct ListBase;
+
+extern struct ListBase *samples;
+
+/* void *sound_get_listener(void); implemented in src!also declared there now */
+
+void sound_set_packedfile(struct bSample* sample, struct PackedFile* pf);
+struct PackedFile* sound_find_packedfile(struct bSound* sound);
+void sound_free_sample(struct bSample* sample);
+void sound_free_sound(struct bSound* sound);
+
+#endif
diff --git a/source/blender/blenkernel/BKE_subsurf.h b/source/blender/blenkernel/BKE_subsurf.h
new file mode 100644
index 00000000000..745ecb0cdd4
--- /dev/null
+++ b/source/blender/blenkernel/BKE_subsurf.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 *****
+ */
+#ifndef BKE_SUBSURF_H
+#define BKE_SUBSURF_H
+
+struct Mesh;
+struct Object;
+struct Displist;
+
+void subsurf_to_mesh(struct Object *oldob, struct Mesh *newme);
+void subsurf_make_mesh(struct Object *ob, short subdiv);
+void subsurf_make_editmesh(struct Object *ob);
+struct DispList* subsurf_mesh_to_displist(struct Mesh *me, struct DispList *dl, short subdiv);
+
+#endif
diff --git a/source/blender/blenkernel/BKE_text.h b/source/blender/blenkernel/BKE_text.h
new file mode 100644
index 00000000000..43e3bb76b12
--- /dev/null
+++ b/source/blender/blenkernel/BKE_text.h
@@ -0,0 +1,128 @@
+/**
+ * blenlib/BKE_text.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BKE_TEXT_H
+#define BKE_TEXT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct Text;
+struct TextLine;
+
+void free_text (struct Text *text);
+void txt_set_undostate (int u);
+int txt_get_undostate (void);
+struct Text* add_empty_text (void);
+int reopen_text (struct Text *text);
+struct Text* add_text (char *file);
+struct Text* copy_text (struct Text *ta);
+
+void txt_free_cut_buffer (void);
+
+char* txt_to_buf (struct Text *text);
+void txt_clean_text (struct Text *text);
+void txt_order_cursors (struct Text *text);
+int txt_find_string (struct Text *text, char *findstr);
+int txt_has_sel (struct Text *text);
+int txt_get_span (struct TextLine *from, struct TextLine *to);
+void txt_move_up (struct Text *text, short sel);
+void txt_move_down (struct Text *text, short sel);
+void txt_move_left (struct Text *text, short sel);
+void txt_move_right (struct Text *text, short sel);
+void txt_move_bof (struct Text *text, short sel);
+void txt_move_eof (struct Text *text, short sel);
+void txt_move_bol (struct Text *text, short sel);
+void txt_move_eol (struct Text *text, short sel);
+void txt_move_toline (struct Text *text, unsigned int line, short sel);
+void txt_pop_sel (struct Text *text);
+void txt_delete_char (struct Text *text);
+void txt_copy_sel (struct Text *text);
+void txt_sel_all (struct Text *text);
+void txt_sel_line (struct Text *text);
+void txt_print_cutbuffer (void);
+void txt_cut_sel (struct Text *text);
+char* txt_sel_to_buf (struct Text *text);
+void txt_insert_buf (struct Text *text, char *in_buffer);
+void txt_paste (struct Text *text);
+void txt_print_undo (struct Text *text);
+void txt_undo_add_toop (struct Text *text, int op, unsigned int froml, unsigned short fromc, unsigned int tol, unsigned short toc);
+void txt_do_undo (struct Text *text);
+void txt_do_redo (struct Text *text);
+void txt_split_curline (struct Text *text);
+void txt_backspace_char (struct Text *text);
+int txt_add_char (struct Text *text, char add);
+
+
+/* Undo opcodes */
+
+/* Simple main cursor movement */
+#define UNDO_CLEFT 001
+#define UNDO_CRIGHT 002
+#define UNDO_CUP 003
+#define UNDO_CDOWN 004
+
+/* Simple selection cursor movement */
+#define UNDO_SLEFT 005
+#define UNDO_SRIGHT 006
+#define UNDO_SUP 007
+#define UNDO_SDOWN 021
+
+/* Complex movement (opcode is followed
+ * by 4 character line ID + a 2 character
+ * position ID and opcode (repeat)) */
+#define UNDO_CTO 022
+#define UNDO_STO 023
+
+/* Complex editing (opcode is followed
+ * by 1 character ID and opcode (repeat)) */
+#define UNDO_INSERT 024
+#define UNDO_BS 025
+#define UNDO_DEL 026
+
+/* Text block (opcode is followed
+ * by 4 character length ID + the text
+ * block itself + the 4 character length
+ * ID (repeat) and opcode (repeat)) */
+#define UNDO_DBLOCK 027 /* Delete block */
+#define UNDO_IBLOCK 030 /* Insert block */
+
+/* Misc */
+#define UNDO_SWAP 031 /* Swap cursors */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/source/blender/blenkernel/BKE_texture.h b/source/blender/blenkernel/BKE_texture.h
new file mode 100644
index 00000000000..172afcaecd6
--- /dev/null
+++ b/source/blender/blenkernel/BKE_texture.h
@@ -0,0 +1,85 @@
+/**
+ * blenlib/BKE_texture.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BKE_TEXTURE_H
+#define BKE_TEXTURE_H
+
+struct Tex;
+struct MTex;
+struct PluginTex;
+struct LampRen;
+struct ColorBand;
+struct HaloRen;
+
+/* in ColorBand struct */
+#define MAXCOLORBAND 16
+
+
+void free_texture(struct Tex *t);
+int test_dlerr(const char *name, const char *symbol);
+void open_plugin_tex(struct PluginTex *pit);
+struct PluginTex *add_plugin_tex(char *str);
+void free_plugin_tex(struct PluginTex *pit);
+struct ColorBand *add_colorband(void);
+int do_colorband(struct ColorBand *coba);
+void default_tex(struct Tex *tex);
+struct Tex *add_texture(char *name);
+void default_mtex(struct MTex *mtex);
+struct MTex *add_mtex(void);
+struct Tex *copy_texture(struct Tex *tex);
+void make_local_texture(struct Tex *tex);
+void autotexname(struct Tex *tex);
+void init_render_texture(struct Tex *tex);
+void init_render_textures(void);
+void end_render_texture(struct Tex *tex);
+void end_render_textures(void);
+int clouds(struct Tex *tex, float *texvec);
+int blend(struct Tex *tex, float *texvec);
+int wood(struct Tex *tex, float *texvec);
+int marble(struct Tex *tex, float *texvec);
+int magic(struct Tex *tex, float *texvec);
+int stucci(struct Tex *tex, float *texvec);
+int texnoise(struct Tex *tex);
+int plugintex(struct Tex *tex, float *texvec, float *dxt, float *dyt);
+void tubemap(float x, float y, float z, float *adr1, float *adr2);
+void spheremap(float x, float y, float z, float *adr1, float *adr2);
+void do_2d_mapping(struct MTex *mtex, float *t, float *dxt, float *dyt);
+int multitex(struct Tex *tex, float *texvec, float *dxt, float *dyt);
+void do_material_tex(void);
+void do_halo_tex(struct HaloRen *har, float xn, float yn, float *colf);
+void do_sky_tex(void);
+void do_lamp_tex(struct LampRen *la, float *lavec);
+void externtex(struct MTex *mtex, float *vec);
+void externtexcol(struct MTex *mtex, float *orco, char *col);
+void render_realtime_texture(void);
+#endif
diff --git a/source/blender/blenkernel/BKE_utildefines.h b/source/blender/blenkernel/BKE_utildefines.h
new file mode 100644
index 00000000000..65bad0f40b3
--- /dev/null
+++ b/source/blender/blenkernel/BKE_utildefines.h
@@ -0,0 +1,300 @@
+/* util defines -- might go away ?*/
+
+/*
+ $Id$
+
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BKE_UTILDEFINES_H
+#define BKE_UTILDEFINES_H
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#define ELEM(a, b, c) ( (a)==(b) || (a)==(c) )
+#define ELEM3(a, b, c, d) ( ELEM(a, b, c) || (a)==(d) )
+#define ELEM4(a, b, c, d, e) ( ELEM(a, b, c) || ELEM(a, d, e) )
+#define ELEM5(a, b, c, d, e, f) ( ELEM(a, b, c) || ELEM3(a, d, e, f) )
+#define ELEM6(a, b, c, d, e, f, g) ( ELEM(a, b, c) || ELEM4(a, d, e, f, g) )
+#define ELEM7(a, b, c, d, e, f, g, h) ( ELEM3(a, b, c, d) || ELEM4(a, e, f, g, h) )
+#define ELEM8(a, b, c, d, e, f, g, h, i) ( ELEM4(a, b, c, d, e) || ELEM4(a, f, g, h, i) )
+
+
+/* string compare */
+#define STREQ(str, a) ( strcmp((str), (a))==0 )
+#define STREQ2(str, a, b) ( STREQ(str, a) || STREQ(str, b) )
+#define STREQ3(str, a, b, c) ( STREQ2(str, a, b) || STREQ(str, c) )
+
+/* min/max */
+#define MIN2(x,y) ( (x)<(y) ? (x) : (y) )
+#define MIN3(x,y,z) MIN2( MIN2((x),(y)) , (z) )
+#define MIN4(x,y,z,a) MIN2( MIN2((x),(y)) , MIN2((z),(a)) )
+
+#define MAX2(x,y) ( (x)>(y) ? (x) : (y) )
+#define MAX3(x,y,z) MAX2( MAX2((x),(y)) , (z) )
+#define MAX4(x,y,z,a) MAX2( MAX2((x),(y)) , MAX2((z),(a)) )
+
+#define SWAP(type, a, b) { type sw_ap; sw_ap=(a); (a)=(b); (b)=sw_ap; }
+
+#define ABS(a) ( (a)<0 ? (-a) : (a) )
+
+#define VECCOPY(v1,v2) {*(v1)= *(v2); *(v1+1)= *(v2+1); *(v1+2)= *(v2+2);}
+#define QUATCOPY(v1,v2) {*(v1)= *(v2); *(v1+1)= *(v2+1); *(v1+2)= *(v2+2); *(v1+3)= *(v2+3);}
+
+#define INIT_MINMAX(min, max) (min)[0]= (min)[1]= (min)[2]= 1.0e30; (max)[0]= (max)[1]= (max)[2]= -1.0e30;
+
+#define DO_MINMAX(vec, min, max) if( (min)[0]>(vec)[0] ) (min)[0]= (vec)[0]; \
+ if( (min)[1]>(vec)[1] ) (min)[1]= (vec)[1]; \
+ if( (min)[2]>(vec)[2] ) (min)[2]= (vec)[2]; \
+ if( (max)[0]<(vec)[0] ) (max)[0]= (vec)[0]; \
+ if( (max)[1]<(vec)[1] ) (max)[1]= (vec)[1]; \
+ if( (max)[2]<(vec)[2] ) (max)[2]= (vec)[2]; \
+
+#define DO_MINMAX2(vec, min, max) if( (min)[0]>(vec)[0] ) (min)[0]= (vec)[0]; \
+ if( (min)[1]>(vec)[1] ) (min)[1]= (vec)[1]; \
+ if( (max)[0]<(vec)[0] ) (max)[0]= (vec)[0]; \
+ if( (max)[1]<(vec)[1] ) (max)[1]= (vec)[1];
+
+
+/* interferes elsewhere */
+/* deze getallen ook invullen in blender.h SpaceFile: struct dna herkent geen defines */
+#define FILE_MAXDIR 160
+#define FILE_MAXFILE 80
+
+
+/* some misc stuff.... */
+#define CLAMP(a, b, c) if((a)<(b)) (a)=(b); else if((a)>(c)) (a)=(c)
+
+#define KNOTSU(nu) ( (nu)->orderu+ (nu)->pntsu+ (nu->orderu-1)*((nu)->flagu & 1) )
+#define KNOTSV(nu) ( (nu)->orderv+ (nu)->pntsv+ (nu->orderv-1)*((nu)->flagv & 1) )
+
+/* this weirdo pops up in two places ... */
+#if !defined(WIN32) && !defined(__BeOS)
+#define O_BINARY 0
+#endif
+
+/* INTEGER CODES */
+#if defined(__sgi) || defined (__sparc) || defined (__PPC__) || defined (__ppc__) || defined (__BIG_ENDIAN__)
+ /* Big Endian */
+#define MAKE_ID(a,b,c,d) ( (int)(a)<<24 | (int)(b)<<16 | (c)<<8 | (d) )
+#else
+ /* Little Endian */
+#define MAKE_ID(a,b,c,d) ( (int)(d)<<24 | (int)(c)<<16 | (b)<<8 | (a) )
+#endif
+
+#define ID_NEW(a) if( (a) && (a)->id.newid ) (a)= (void *)(a)->id.newid
+
+#define FORM MAKE_ID('F','O','R','M')
+#define DDG1 MAKE_ID('3','D','G','1')
+#define DDG2 MAKE_ID('3','D','G','2')
+#define DDG3 MAKE_ID('3','D','G','3')
+#define DDG4 MAKE_ID('3','D','G','4')
+
+#define GOUR MAKE_ID('G','O','U','R')
+
+#define BLEN MAKE_ID('B','L','E','N')
+#define DER_ MAKE_ID('D','E','R','_')
+#define V100 MAKE_ID('V','1','0','0')
+
+#define DATA MAKE_ID('D','A','T','A')
+#define GLOB MAKE_ID('G','L','O','B')
+#define IMAG MAKE_ID('I','M','A','G')
+
+#define DNA1 MAKE_ID('D','N','A','1')
+#define TEST MAKE_ID('T','E','S','T')
+#define REND MAKE_ID('R','E','N','D')
+#define USER MAKE_ID('U','S','E','R')
+
+#define ENDB MAKE_ID('E','N','D','B')
+
+/* This should, of course, become a function */
+#define DL_SURFINDEX(cyclu, cyclv, sizeu, sizev) \
+ \
+ if( (cyclv)==0 && a==(sizev)-1) break; \
+ if(cyclu) { \
+ p1= sizeu*a; \
+ p2= p1+ sizeu-1; \
+ p3= p1+ sizeu; \
+ p4= p2+ sizeu; \
+ b= 0; \
+ } \
+ else { \
+ p2= sizeu*a; \
+ p1= p2+1; \
+ p4= p2+ sizeu; \
+ p3= p1+ sizeu; \
+ b= 1; \
+ } \
+ if( (cyclv) && a==sizev-1) { \
+ p3-= sizeu*sizev; \
+ p4-= sizeu*sizev; \
+ }
+
+/* This one rotates the bytes in an int */
+#define SWITCH_INT(a) { \
+ char s_i, *p_i; \
+ p_i= (char *)&(a); \
+ s_i=p_i[0]; p_i[0]=p_i[3]; p_i[3]=s_i; \
+ s_i=p_i[1]; p_i[1]=p_i[2]; p_i[2]=s_i; }
+
+/* More brain damage. Only really used by packedFile.c */
+// return values
+#define RET_OK 0
+#define RET_ERROR 1
+/* and these aren't used at all */
+/* #define RET_CANCEL 2 */
+/* #define RET_YES (1 == 1) */
+/* #define RET_NO (1 == 0) */
+
+/* sequence related defines */
+#define WHILE_SEQ(base) { \
+ int totseq_, seq_; Sequence **seqar; \
+ build_seqar( base, &seqar, &totseq_); \
+ for(seq_ = 0; seq_ < totseq_; seq_++) { \
+ seq= seqar[seq_];
+
+
+#define END_SEQ } \
+ if(seqar) MEM_freeN(seqar); \
+ }
+
+
+/* not really sure about these... some kind of event codes ?*/
+/* INFO: 300 */
+/* pas op: ook in filesel.c en editobject.c */
+#define B_INFOSCR 301
+#define B_INFODELSCR 302
+#define B_INFOSCE 304
+#define B_INFODELSCE 305
+#define B_FILEMENU 306
+#define B_PACKFILE 307
+
+/* From iff.h, but seemingly detached from anything else... To which
+ * encoding scheme do they belong? */
+#define AMI (1 << 31)
+#define CDI (1 << 30)
+#define Anim (1 << 29)
+#define TGA (1 << 28)
+#define JPG (1 << 27)
+#define TIM (1 << 26)
+
+#define TIM_CLUT (010)
+#define TIM_4 (TIM | TIM_CLUT | 0)
+#define TIM_8 (TIM | TIM_CLUT | 1)
+#define TIM_16 (TIM | 2)
+#define TIM_24 (TIM | 3)
+
+#define RAWTGA (TGA | 1)
+
+#define JPG_STD (JPG | (0 << 8))
+#define JPG_VID (JPG | (1 << 8))
+#define JPG_JST (JPG | (2 << 8))
+#define JPG_MAX (JPG | (3 << 8))
+#define JPG_MSK (0xffffff00)
+
+#define AM_ham (0x0800 | AMI)
+#define AM_hbrite (0x0080 | AMI)
+#define AM_lace (0x0004 | AMI)
+#define AM_hires (0x8000 | AMI)
+#define AM_hblace (AM_hbrite | AM_lace)
+#define AM_hilace (AM_hires | AM_lace)
+#define AM_hamlace (AM_ham | AM_lace)
+
+#define RGB888 1
+#define RGB555 2
+#define DYUV 3
+#define CLUT8 4
+#define CLUT7 5
+#define CLUT4 6
+#define CLUT3 7
+#define RL7 8
+#define RL3 9
+#define MPLTE 10
+
+#define DYUV1 0
+#define DYUVE 1
+
+#define CD_rgb8 (RGB888 | CDI)
+#define CD_rgb5 (RGB555 | CDI)
+#define CD_dyuv (DYUV | CDI)
+#define CD_clut8 (CLUT8 | CDI)
+#define CD_clut7 (CLUT7 | CDI)
+#define CD_clut4 (CLUT4 | CDI)
+#define CD_clut3 (CLUT3 | CDI)
+#define CD_rl7 (RL7 | CDI)
+#define CD_rl3 (RL3 | CDI)
+#define CD_mplte (MPLTE | CDI)
+
+#define C233 1
+#define YUVX 2
+#define HAMX 3
+#define TANX 4
+
+#define AN_c233 (Anim | C233)
+#define AN_yuvx (Anim | YUVX)
+#define AN_hamx (Anim | HAMX)
+#define AN_tanx (Anim | TANX)
+
+#define IMAGIC 0732
+
+/* This used to reside in render.h. It does some texturing. */
+#define BRICON Tin= (Tin-0.5)*tex->contrast+tex->bright-0.5; \
+ if(Tin<0.0) Tin= 0.0; else if(Tin>1.0) Tin= 1.0;
+
+#define BRICONRGB Tr= tex->rfac*((Tr-0.5)*tex->contrast+tex->bright-0.5); \
+ if(Tr<0.0) Tr= 0.0; else if(Tr>1.0) Tr= 1.0; \
+ Tg= tex->gfac*((Tg-0.5)*tex->contrast+tex->bright-0.5); \
+ if(Tg<0.0) Tg= 0.0; else if(Tg>1.0) Tg= 1.0; \
+ Tb= tex->bfac*((Tb-0.5)*tex->contrast+tex->bright-0.5); \
+ if(Tb<0.0) Tb= 0.0; else if(Tb>1.0) Tb= 1.0;
+
+/* mystifying stuff from blendef... */
+#define SELECT 1
+#define ACTIVE 2
+#define NOT_YET 0
+
+/* ???? */
+#define BTST(a,b) ( ( (a) & 1<<(b) )!=0 )
+#define BSET(a,b) ( (a) | 1<<(b) )
+
+/* needed for material.c*/
+#define REDRAWBUTSMAT 0x4015
+
+/* useless game shit */
+#define MA_FH_NOR 2
+
+
+#endif
diff --git a/source/blender/blenkernel/BKE_world.h b/source/blender/blenkernel/BKE_world.h
new file mode 100644
index 00000000000..0ea13557e03
--- /dev/null
+++ b/source/blender/blenkernel/BKE_world.h
@@ -0,0 +1,45 @@
+/**
+ * blenlib/BKE_world.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BKE_WORLD_H
+#define BKE_WORLD_H
+
+struct World;
+
+void free_world(struct World *sc);
+struct World *add_world(char *name);
+struct World *copy_world(struct World *wrld);
+void make_local_world(struct World *wrld);
+void init_render_world(void);
+
+#endif
diff --git a/source/blender/blenkernel/BKE_writeavi.h b/source/blender/blenkernel/BKE_writeavi.h
new file mode 100644
index 00000000000..f63342ea047
--- /dev/null
+++ b/source/blender/blenkernel/BKE_writeavi.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 *****
+ */
+
+#ifndef BKE_WRITEAVI_H
+#define BKE_WRITEAVI_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void start_avi(void);
+void end_avi(void);
+void append_avi(int frame);
+void makeavistring(char *string);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/source/blender/blenkernel/Makefile b/source/blender/blenkernel/Makefile
new file mode 100644
index 00000000000..239941ec59b
--- /dev/null
+++ b/source/blender/blenkernel/Makefile
@@ -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 *****
+#
+# Bounces make to subdirectories.
+
+SOURCEDIR = source/blender/blenkernel
+DIRS = intern bad_level_call_stubs
+
+include nan_subdirs.mk
diff --git a/source/blender/blenkernel/bad_level_call_stubs/Makefile b/source/blender/blenkernel/bad_level_call_stubs/Makefile
new file mode 100644
index 00000000000..2d98ea5a1af
--- /dev/null
+++ b/source/blender/blenkernel/bad_level_call_stubs/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 *****
+#
+#
+
+LIBNAME = blenkernel_blc
+DIR = $(OCGDIR)/blender/blenkernel/$(LIBNAME)
+
+include nan_compile.mk
+
+CFLAGS += $(LEVEL_2_C_WARNINGS)
+CFLAGS += $(FIX_STUBS_WARNINGS)
+
+ifeq ($(OS),$(findstring $(OS), "beos darwin freebsd linux openbsd solaris windows"))
+ CFLAGS += -funsigned-char
+endif
+
+CPPFLAGS += $(OGL_CPPFLAGS)
+CPPFLAGS += -I../../makesdna
+CPPFLAGS += -I../../include
+CPPFLAGS += -I../../blenlib
+CPPFLAGS += -I../../render/extern/include
+CPPFLAGS += -I$(NAN_IKSOLVER)/include
+
+# path to our own external headerfiles
+CPPFLAGS += -I..
+
diff --git a/source/blender/blenkernel/bad_level_call_stubs/stubs.c b/source/blender/blenkernel/bad_level_call_stubs/stubs.c
new file mode 100644
index 00000000000..239e4f16487
--- /dev/null
+++ b/source/blender/blenkernel/bad_level_call_stubs/stubs.c
@@ -0,0 +1,180 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * BKE_bad_level_calls function stubs
+ */
+
+
+#include "BLI_blenlib.h"
+
+#include "DNA_material_types.h"
+
+#include "BKE_bad_level_calls.h"
+
+int winqueue_break= 0;
+
+/* readfile.c */
+ /* struct PluginSeq; */
+void open_plugin_seq(struct PluginSeq *pis, char *seqname){}
+ /* struct SpaceButs; */
+void set_rects_butspace(struct SpaceButs *buts){}
+ /* struct SpaceImaSel; */
+void check_imasel_copy(struct SpaceImaSel *simasel){}
+ /* struct ScrArea; */
+void unlink_screen(struct bScreen *sc){}
+void freeAllRad(void){}
+void free_editText(void){}
+void free_editArmature(void){}
+
+
+void setscreen(struct bScreen *sc){}
+void force_draw_all(void){}
+ /* otherwise the WHILE_SEQ doesn't work */
+ /* struct Sequence; */
+
+/* MAART: added "seqar = 0; totseq = 0" because the loader will crash without it. */
+void build_seqar(ListBase *seqbase, struct Sequence ***seqar, int *totseq)
+{
+ *seqar = 0;
+ *totseq = 0;
+}
+
+void BPY_do_pyscript(ID *id, short int event){}
+void BPY_free_compiled_text(struct Text *text) {};
+
+/* writefile.c */
+ /* struct Oops; */
+void free_oops(struct Oops *oops){}
+void exit_posemode(int freedata){}
+void error(char *str, ...){}
+
+/* anim.c */
+ListBase editNurb;
+
+/* displist.c */
+#include "DNA_world_types.h" /* for render_types */
+#include "render_types.h"
+struct RE_Render R;
+float RE_Spec(float inp, int hard){}
+void waitcursor(int val){}
+void allqueue(unsigned short event, short val){}
+#define REDRAWVIEW3D 0x4010
+Material defmaterial;
+
+/* effect.c */
+void RE_jitterate1(float *jit1, float *jit2, int num, float rad1){}
+void RE_jitterate2(float *jit1, float *jit2, int num, float rad2){}
+
+/* exotic.c */
+void load_editMesh(void){}
+void make_editMesh(void){}
+void free_editMesh(void){}
+void docentre_new(void){}
+int saveover(char *str){}
+
+/* image.c */
+#include "DNA_image_types.h"
+void free_realtime_image(Image *ima){} // has to become a callback, opengl stuff
+void RE_make_existing_file(char *name){} // from render, but these funcs should be moved anyway
+
+/* ipo.c */
+void copy_view3d_lock(short val){} // was a hack, to make scene layer ipo's possible
+
+/* library.c */
+void allspace(unsigned short event, short val){}
+#define OOPS_TEST 2
+
+/* mball.c */
+ListBase editelems;
+
+/* object.c */
+void BPY_free_scriptlink(ScriptLink *slink){}
+void BPY_copy_scriptlink(ScriptLink *scriptlink){}
+float *give_cursor(void){} // become a callback or argument
+
+
+/* packedFile.c */
+short pupmenu(char *instr){} // will be general callback
+
+/* sca.c */
+#define LEFTMOUSE 0x001 // because of mouse sensor
+
+/* scene.c */
+#include "DNA_sequence_types.h"
+void free_editing(struct Editing *ed){} // scenes and sequences problem...
+void BPY_do_all_scripts (short int event){}
+
+/* IKsolver stubs */
+#include "IK_solver.h"
+extern int IK_LoadChain(IK_Chain_ExternPtr chain,IK_Segment_ExternPtr segments, int num_segs)
+{
+ return 0;
+}
+
+extern int IK_SolveChain(
+ IK_Chain_ExternPtr chain,
+ float goal[3],
+ float tolerance,
+ int max_iterations,
+ float max_angle_change,
+ IK_Segment_ExternPtr output
+ )
+{
+ return 0;
+}
+
+extern void IK_FreeChain(IK_Chain_ExternPtr chain)
+{
+ ;
+}
+
+
+extern IK_Chain_ExternPtr IK_CreateChain(void)
+{
+ return 0;
+}
+
+
+
+/* texture.c */
+#define FLO 128
+#define INT 96
+ /* struct EnvMap; */
+ /* struct Tex; */
+void RE_free_envmap(struct EnvMap *env){}
+struct EnvMap *RE_copy_envmap(struct EnvMap *env){}
+void RE_free_envmapdata(struct EnvMap *env){}
+int RE_envmaptex(struct Tex *tex, float *texvec, float *dxt, float *dyt){}
+void RE_calc_R_ref(void){}
+char texstr[15][8]; /* buttons.c */
+Osa O;
+
+/* editsca.c */
+void make_unique_prop_names(char *str) {}
diff --git a/source/blender/blenkernel/intern/Makefile b/source/blender/blenkernel/intern/Makefile
new file mode 100644
index 00000000000..08202dff9cc
--- /dev/null
+++ b/source/blender/blenkernel/intern/Makefile
@@ -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 *****
+#
+#
+
+LIBNAME = blenkernel
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+ifeq ($(OS),$(findstring $(OS), "beos darwin freebsd openbsd linux solaris windows"))
+ CFLAGS += -funsigned-char
+endif
+
+CFLAGS += $(LEVEL_1_C_WARNINGS)
+
+# OpenGL and Python
+CPPFLAGS += -I$(OPENGL_HEADERS)
+CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION)
+
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+# Reference to the types in makesdna and imbuf
+CPPFLAGS += -I../../makesdna
+CPPFLAGS += -I../../imbuf
+# This mod uses the BLI and BLO module
+CPPFLAGS += -I../../blenlib
+CPPFLAGS += -I../../blenloader
+CPPFLAGS += -I../../bpython/include
+# also avi is used
+CPPFLAGS += -I../../avi
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+
+# we still refer to /include a bit...
+CPPFLAGS += -I../../include
+
+# to include the render stuff:
+CPPFLAGS += -I../../render/extern/include
+
+# for sound
+#CPPFLAGS += -I../../../kernel/gen_system
+
+CPPFLAGS += -I$(NAN_IKSOLVER)/include
+
+# path to our own external headerfiles
+CPPFLAGS += -I..
+
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
new file mode 100644
index 00000000000..9f5de3f34fa
--- /dev/null
+++ b/source/blender/blenkernel/intern/action.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 *****
+ */
+
+#include <string.h>
+#include <math.h>
+#include <stdlib.h> /* for NULL */
+
+#include "MEM_guardedalloc.h"
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+
+#include "BKE_action.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_utildefines.h"
+
+#include "DNA_object_types.h"
+#include "DNA_ipo_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_action_types.h"
+#include "DNA_nla_types.h"
+
+#include "BKE_blender.h"
+#include "BKE_ipo.h"
+#include "BKE_object.h"
+#include "BKE_library.h"
+#include "BKE_anim.h"
+#include "BKE_armature.h"
+
+#include "nla.h"
+
+#include "BKE_constraint.h"
+#include "DNA_constraint_types.h"
+
+/* Local function prototypes */
+static
+ void
+do_pose_constraint_channels(
+ bPose *pose,
+ bAction *act,
+ float ctime
+);
+
+static
+ void
+get_constraint_influence_from_pose (
+ bPose *dst,
+ bPose *src
+);
+
+static
+ void
+blend_constraints(
+ ListBase *dst,
+ const ListBase *src,
+ float srcweight,
+ short mode
+);
+
+static
+ void
+rest_pose (
+ bPose *pose,
+ int clearflag
+);
+
+/* Implementation */
+
+ bPoseChannel *
+get_pose_channel (
+ const bPose *pose,
+ const char *name
+){
+ bPoseChannel *chan;
+
+ for (chan=pose->chanbase.first; chan; chan=chan->next){
+ if (!strcmp (chan->name, name))
+ return chan;
+ }
+
+ return NULL;
+}
+
+static
+ void
+rest_pose (
+ bPose *pose,
+ int clearflag
+){
+ bPoseChannel *chan;
+ int i;
+
+ if (!pose)
+ return;
+
+ for (chan=pose->chanbase.first; chan; chan=chan->next){
+ for (i=0; i<3; i++){
+ chan->loc[i]=0.0;
+ chan->quat[i+1]=0.0;
+ chan->size[i]=1.0;
+ }
+ chan->quat[0]=1.0;
+ if (clearflag)
+ chan->flag =0;
+ }
+}
+
+static
+ void
+blend_constraints(
+ ListBase *dst,
+ const ListBase *src,
+ float srcweight,
+ short mode
+){
+ bConstraint *dcon;
+ const bConstraint *scon;
+ float dstweight;
+
+ switch (mode){
+ case POSE_BLEND:
+ dstweight = 1.0F - srcweight;
+ break;
+ case POSE_ADD:
+ dstweight = 1.0F;
+ break;
+ }
+
+ /* Blend constraints */
+ for (dcon=dst->first; dcon; dcon=dcon->next){
+ for (scon = src->first; scon; scon=scon->next){
+ if (!strcmp(scon->name, dcon->name))
+ break;
+ }
+
+ if (scon){
+ dcon->enforce = (dcon->enforce*dstweight) + (scon->enforce*srcweight);
+ if (mode == POSE_BLEND)
+ dcon->enforce/=2.0;
+
+ if (dcon->enforce>1.0)
+ dcon->enforce=1.0;
+ if (dcon->enforce<0.0)
+ dcon->enforce=0.0;
+
+ }
+ }
+}
+
+ void
+blend_poses (
+ bPose *dst,
+ const bPose *src,
+ float srcweight,
+ short mode
+){
+ bPoseChannel *dchan;
+ const bPoseChannel *schan;
+ float dquat[4], squat[4], mat[3][3];
+ float dstweight;
+ int i;
+
+ switch (mode){
+ case POSE_BLEND:
+ dstweight = 1.0F - srcweight;
+ break;
+ case POSE_ADD:
+ dstweight = 1.0F;
+ break;
+ default :
+ dstweight = 1.0F;
+ }
+
+ for (dchan = dst->chanbase.first; dchan; dchan=dchan->next){
+ schan = get_pose_channel(src, dchan->name);
+ if (schan){
+ if (schan->flag & (POSE_ROT|POSE_LOC|POSE_SIZE)){
+
+ /* Convert both quats to matrices and then back again.
+ * This prevents interpolation problems
+ * This sucks because it is slow and stupid
+ */
+
+ QuatToMat3(dchan->quat, mat);
+ Mat3ToQuat(mat, dquat);
+ QuatToMat3(schan->quat, mat);
+ Mat3ToQuat(mat, squat);
+
+ /* Do the transformation blend */
+ for (i=0; i<3; i++){
+ if (schan->flag & POSE_LOC)
+ dchan->loc[i] = (dchan->loc[i]*dstweight) + (schan->loc[i]*srcweight);
+ if (schan->flag & POSE_SIZE)
+ dchan->size[i] = 1.0f + ((dchan->size[i]-1.0f)*dstweight) + ((schan->size[i]-1.0f)*srcweight);
+ if (schan->flag & POSE_ROT)
+ dchan->quat[i+1] = (dquat[i+1]*dstweight) + (squat[i+1]*srcweight);
+ }
+
+ /* Do one more iteration for the quaternions only and normalize the quaternion if needed */
+ if (schan->flag & POSE_ROT)
+ dchan->quat[0] = 1.0f + ((dquat[0]-1.0f)*dstweight) + ((squat[0]-1.0f)*srcweight);
+ if (mode==POSE_BLEND)
+ NormalQuat (dchan->quat);
+ dchan->flag |= schan->flag;
+ }
+ }
+ }
+}
+
+ void
+clear_pose_constraint_status (
+ Object *ob
+){
+ bPoseChannel *chan;
+
+ if (!ob)
+ return;
+ if (!ob->pose)
+ return;
+
+ for (chan = ob->pose->chanbase.first; chan; chan=chan->next){
+ chan->flag &= ~PCHAN_DONE;
+ }
+}
+
+ float
+calc_action_start (
+ const bAction *act
+){
+ const bActionChannel *chan;
+ const IpoCurve *icu;
+ float size=999999999.0f;
+ int i;
+ int foundvert=0;
+ const bConstraintChannel *conchan;
+
+
+ if (!act)
+ return 0;
+
+ for (chan=act->chanbase.first; chan; chan=chan->next){
+ for (icu=chan->ipo->curve.first; icu; icu=icu->next)
+ for (i=0; i<icu->totvert; i++){
+ size = MIN2 (size, icu->bezt[i].vec[1][0]);
+ foundvert=1;
+
+ }
+ for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next){
+ for (icu=conchan->ipo->curve.first; icu; icu=icu->next)
+ for (i=0; i<icu->totvert; i++){
+ size = MIN2 (size, icu->bezt[i].vec[1][0]);
+ foundvert=1;
+ }
+ }
+ }
+
+ if (!foundvert)
+ return 0;
+ else
+ return size;
+}
+
+ float
+calc_action_end (
+ const bAction *act
+){
+ const bActionChannel *chan;
+ const bConstraintChannel *conchan;
+ const IpoCurve *icu;
+ float size=0;
+ int i;
+
+ if (!act)
+ return 0;
+
+ for (chan=act->chanbase.first; chan; chan=chan->next){
+ for (icu=chan->ipo->curve.first; icu; icu=icu->next)
+ for (i=0; i<icu->totvert; i++)
+ size = MAX2 (size, icu->bezt[i].vec[1][0]);
+
+ for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next){
+ for (icu=conchan->ipo->curve.first; icu; icu=icu->next)
+ for (i=0; i<icu->totvert; i++)
+ size = MAX2 (size, icu->bezt[i].vec[1][0]);
+ }
+ }
+ return size;
+}
+
+ void
+verify_pose_channel (
+ bPose* pose,
+ const char* name
+) {
+ bPoseChannel *chan;
+
+ if (!pose){
+ return;
+ }
+
+ /* See if this channel exists */
+ for (chan=pose->chanbase.first; chan; chan=chan->next){
+ if (!strcmp (name, chan->name))
+ return;
+ }
+
+ /* If not, create it and add it */
+ chan = MEM_callocN(sizeof(bPoseChannel), "verifyPoseChannel");
+
+ strcpy (chan->name, name);
+ chan->loc[0] = chan->loc[1] = chan->loc[2] = 0.0F;
+ chan->quat[1] = chan->quat[2] = chan->quat[3] = 0.0F; chan->quat[0] = 1.0F;
+ chan->size[0] = chan->size[1] = chan->size[2] = 1.0F;
+
+ chan->flag |= POSE_ROT|POSE_SIZE|POSE_LOC;
+
+ BLI_addtail (&pose->chanbase, chan);
+}
+
+ void
+get_pose_from_pose (
+ bPose **pose,
+ const bPose *src
+){
+ const bPoseChannel *pchan;
+ bPoseChannel *newchan;
+
+ if (!src)
+ return;
+ if (!pose)
+ return;
+
+ /* If there is no pose, create one */
+ if (!*pose){
+ *pose=MEM_callocN (sizeof(bPose), "pose");
+ }
+
+ /* Copy the data from the action into the pose */
+ for (pchan=src->chanbase.first; pchan; pchan=pchan->next){
+ newchan = copy_pose_channel(pchan);
+ verify_pose_channel(*pose, pchan->name);
+ set_pose_channel(*pose, newchan);
+ }
+}
+
+static void get_constraint_influence_from_pose (bPose *dst, bPose *src)
+{
+ bConstraint *dcon, *scon;
+
+ if (!src || !dst)
+ return;
+
+ for (dcon = dst->chanbase.first; dcon; dcon=dcon->next){
+ for (scon=src->chanbase.first; scon; scon=scon->next){
+ if (!strcmp(scon->name, dcon->name))
+ break;
+ }
+ if (scon){
+ dcon->enforce = scon->enforce;
+ }
+ }
+}
+
+/* If the pose does not exist, a new one is created */
+
+ void
+get_pose_from_action (
+ bPose **pose,
+ bAction *act,
+ float ctime
+) {
+ bActionChannel *achan;
+ bPoseChannel *pchan;
+ Ipo *ipo;
+ IpoCurve *curve;
+
+
+ if (!act)
+ return;
+ if (!pose)
+ return;
+
+ /* If there is no pose, create one */
+ if (!*pose){
+ *pose=MEM_callocN (sizeof(bPose), "pose");
+ }
+
+ /* Copy the data from the action into the pose */
+ for (achan=act->chanbase.first; achan; achan=achan->next){
+ act->achan= achan;
+
+ ipo = achan->ipo;
+ if (ipo){
+ pchan=MEM_callocN (sizeof(bPoseChannel), "gpfa_poseChannel");
+ strcpy (pchan->name, achan->name);
+
+ act->pchan=pchan;
+ /* Evaluates and sets the internal ipo value */
+ calc_ipo(ipo, ctime);
+
+ /* Set the pchan flags */
+ for (curve = achan->ipo->curve.first; curve; curve=curve->next){
+ /* Skip empty curves */
+ if (!curve->totvert)
+ continue;
+
+ switch (curve->adrcode){
+ case AC_QUAT_X:
+ case AC_QUAT_Y:
+ case AC_QUAT_Z:
+ case AC_QUAT_W:
+ pchan->flag |= POSE_ROT;
+ break;
+ case AC_LOC_X:
+ case AC_LOC_Y:
+ case AC_LOC_Z:
+ pchan->flag |= POSE_LOC;
+ break;
+ case AC_SIZE_X:
+ case AC_SIZE_Y:
+ case AC_SIZE_Z:
+ pchan->flag |= POSE_SIZE;
+ break;
+ }
+ }
+
+ execute_ipo((ID*)act, achan->ipo);
+
+ set_pose_channel(*pose, pchan);
+ }
+ }
+}
+
+ void
+do_all_actions(
+){
+ Base *base;
+ bPose *apose=NULL;
+ bPose *tpose=NULL;
+ Object *ob;
+ bActionStrip *strip;
+ int doit;
+ float striptime, frametime, length, actlength;
+ float blendfac, stripframe;
+
+ int set;
+
+ /* NEW: current scene ob ipo's */
+ base= G.scene->base.first;
+ set= 0;
+
+ while(base) {
+
+ ob = base->object;
+
+ /* Retrieve data from the NLA */
+ if(ob->type==OB_ARMATURE){
+
+ doit=0;
+
+ /* Clear pose */
+ if (apose){
+ clear_pose(apose);
+ MEM_freeN(apose);
+ }
+ /* Clear pose */
+ if (tpose){
+ clear_pose(tpose);
+ MEM_freeN(tpose);
+ }
+
+ copy_pose(&apose, ob->pose, 1);
+ copy_pose(&tpose, ob->pose, 1);
+ rest_pose(apose, 1);
+
+ if (base->object->nlastrips.first){
+ rest_pose(base->object->pose, 0);
+ }
+
+ for (strip=base->object->nlastrips.first; strip; strip=strip->next){
+ doit = 0;
+ if (strip->act){
+
+ /* Determine if the current frame is within the strip's range */
+ length = strip->end-strip->start;
+ actlength = strip->actend-strip->actstart;
+ striptime = (G.scene->r.cfra-(strip->start)) / length;
+ stripframe = (G.scene->r.cfra-(strip->start)) ;
+
+
+ if (striptime>=0.0){
+
+ rest_pose(tpose, 1);
+
+ /* Handle path */
+ if (strip->flag & ACTSTRIP_USESTRIDE){
+ if (ob->parent && ob->parent->type==OB_CURVE){
+ Curve *cu = ob->parent->data;
+ float ctime, pdist;
+
+ if (cu->flag & CU_PATH){
+ /* Ensure we have a valid path */
+ if(cu->path==0 || cu->path->data==0) calc_curvepath(ob->parent);
+
+ /* Find the position on the path */
+ ctime= bsystem_time(ob, ob->parent, (float)G.scene->r.cfra, 0.0);
+
+ if(calc_ipo_spec(cu->ipo, CU_SPEED, &ctime)==0) {
+ ctime /= cu->pathlen;
+ CLAMP(ctime, 0.0, 1.0);
+ }
+ pdist = ctime*cu->path->totdist;
+
+ if (strip->stridelen)
+ striptime = pdist / strip->stridelen;
+ else
+ striptime = 0;
+
+ striptime = (float)fmod (striptime, 1.0);
+
+ frametime = (striptime * actlength) + strip->actstart;
+ get_pose_from_action (&tpose, strip->act, bsystem_time(ob, 0, frametime, 0.0));
+#ifdef __NLA_BLENDCON
+ do_pose_constraint_channels(tpose, strip->act, bsystem_time(ob, 0, frametime, 0.0));
+#endif
+ doit=1;
+ }
+ }
+ }
+
+ /* Handle repeat */
+
+ else if (striptime < 1.0){
+ /* Mod to repeat */
+ striptime*=strip->repeat;
+ striptime = (float)fmod (striptime, 1.0);
+
+ frametime = (striptime * actlength) + strip->actstart;
+ get_pose_from_action (&tpose, strip->act, bsystem_time(ob, 0, frametime, 0.0));
+#ifdef __NLA_BLENDCON
+ do_pose_constraint_channels(tpose, strip->act, bsystem_time(ob, 0, frametime, 0.0));
+#endif
+ doit=1;
+ }
+ /* Handle extend */
+ else{
+ if (strip->flag & ACTSTRIP_HOLDLASTFRAME){
+ striptime = 1.0;
+ frametime = (striptime * actlength) + strip->actstart;
+ get_pose_from_action (&tpose, strip->act, bsystem_time(ob, 0, frametime, 0.0));
+#ifdef __NLA_BLENDCON
+ do_pose_constraint_channels(tpose, strip->act, bsystem_time(ob, 0, frametime, 0.0));
+#endif
+ doit=1;
+ }
+ }
+
+ /* Handle blendin & blendout */
+ if (doit){
+ /* Handle blendin */
+
+ if (strip->blendin>0.0 && stripframe<=strip->blendin && G.scene->r.cfra>=strip->start){
+ blendfac = stripframe/strip->blendin;
+ }
+ else if (strip->blendout>0.0 && stripframe>=(length-strip->blendout) && G.scene->r.cfra<=strip->end){
+ blendfac = (length-stripframe)/(strip->blendout);
+ }
+ else
+ blendfac = 1;
+
+ /* Blend this pose with the accumulated pose */
+ blend_poses (apose, tpose, blendfac, strip->mode);
+#ifdef __NLA_BLENDCON
+ blend_constraints(&apose->chanbase, &tpose->chanbase, blendfac, strip->mode);
+#endif
+ }
+ }
+ if (apose){
+ get_pose_from_pose(&ob->pose, apose);
+#ifdef __NLA_BLENDCON
+ get_constraint_influence_from_pose(ob->pose, apose);
+#endif
+ }
+ }
+
+ }
+
+ /* Do local action (always overrides the nla actions) */
+ /* At the moment, only constraint ipos on the local action have any effect */
+ if(base->object->action) {
+ get_pose_from_action (&ob->pose, ob->action, bsystem_time(ob, 0, (float) G.scene->r.cfra, 0.0));
+ do_pose_constraint_channels(ob->pose, ob->action, bsystem_time(ob, 0, (float) G.scene->r.cfra, 0.0));
+ doit = 1;
+ }
+
+ if (doit)
+ apply_pose_armature(get_armature(ob), ob->pose, 1);
+
+ }
+ base= base->next;
+ if(base==0 && set==0 && G.scene->set) {
+ set= 1;
+ base= G.scene->set->base.first;
+ }
+
+ }
+
+ if (apose){
+ clear_pose(apose);
+ MEM_freeN(apose);
+ apose = NULL;
+ }
+ if (tpose){
+ clear_pose(tpose);
+ MEM_freeN(tpose);
+ apose = NULL;
+ }
+
+}
+
+static void do_pose_constraint_channels(bPose *pose, bAction *act, float ctime)
+{
+ bPoseChannel *pchan;
+ bActionChannel *achan;
+
+ if (!pose || !act)
+ return;
+
+ for (pchan=pose->chanbase.first; pchan; pchan=pchan->next){
+ achan=get_named_actionchannel(act, pchan->name);
+ if (achan)
+ do_constraint_channels(&pchan->constraints, &achan->constraintChannels, ctime);
+ }
+}
+
+ bActionChannel *
+get_named_actionchannel (
+ bAction *act,
+ const char *name
+){
+ bActionChannel *chan;
+
+ if (!act)
+ return NULL;
+
+ for (chan = act->chanbase.first; chan; chan=chan->next){
+ if (!strcmp (chan->name, name))
+ return chan;
+ }
+
+ return NULL;
+}
+
+ void
+clear_pose (
+ bPose *pose
+) {
+ bPoseChannel *chan;
+
+ if (pose->chanbase.first){
+ for (chan = pose->chanbase.first; chan; chan=chan->next){
+ free_constraints(&chan->constraints);
+ }
+ BLI_freelistN (&pose->chanbase);
+ }
+}
+
+ void
+make_local_action(
+ bAction *act
+){
+ Object *ob;
+ bAction *actn;
+ int local=0, lib=0;
+
+ if(act->id.lib==0) return;
+ if(act->id.us==1) {
+ act->id.lib= 0;
+ act->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)act, 0);
+ return;
+ }
+
+ ob= G.main->object.first;
+ while(ob) {
+ if(ob->action==act) {
+ if(ob->id.lib) lib= 1;
+ else local= 1;
+ }
+ ob= ob->id.next;
+ }
+
+ if(local && lib==0) {
+ act->id.lib= 0;
+ act->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)act, 0);
+ }
+ else if(local && lib) {
+ actn= copy_action(act);
+ actn->id.us= 0;
+
+ ob= G.main->object.first;
+ while(ob) {
+ if(ob->action==act) {
+
+ if(ob->id.lib==0) {
+ ob->action = actn;
+ ob->activecon = NULL;
+ actn->id.us++;
+ act->id.us--;
+ }
+ }
+ ob= ob->id.next;
+ }
+ }
+}
+
+
+ void
+free_action(
+ bAction *act
+){
+ bActionChannel *chan;
+
+ /* Free channels */
+ for (chan=act->chanbase.first; chan; chan=chan->next){
+ if (chan->ipo)
+ chan->ipo->id.us--;
+ free_constraint_channels(&chan->constraintChannels);
+ }
+
+ if (act->chanbase.first)
+ BLI_freelistN (&act->chanbase);
+}
+
+ bAction*
+copy_action (
+ const bAction *src
+){
+ bAction *dst = NULL;
+ bActionChannel *dchan, *schan;
+
+ if(!src) return NULL;
+
+ dst= copy_libblock(src);
+ duplicatelist(&(dst->chanbase), &(src->chanbase));
+
+ for (dchan=dst->chanbase.first, schan=src->chanbase.first; dchan; dchan=dchan->next, schan=schan->next){
+ dchan->ipo = copy_ipo(dchan->ipo);
+ copy_constraint_channels(&dchan->constraintChannels, &schan->constraintChannels);
+ }
+ dst->id.flag |= LIB_FAKEUSER;
+ dst->id.us++;
+ return dst;
+}
+
+ bPoseChannel *
+copy_pose_channel (
+ const bPoseChannel* src
+){
+ bPoseChannel *dst;
+
+ if (!src)
+ return NULL;
+
+ dst = MEM_callocN (sizeof(bPoseChannel), "copyPoseChannel");
+ memcpy (dst, src, sizeof(bPoseChannel));
+ dst->prev=dst->next=NULL;
+
+ return dst;
+}
+
+ void
+copy_pose(
+ bPose **dst,
+ const bPose *src,
+ int copycon
+){
+ bPose *outPose;
+ const bPose * inPose;
+ bPoseChannel *newChan;
+ const bPoseChannel *curChan;
+
+ inPose = src;
+
+ if (!inPose){
+ *dst=NULL;
+ return;
+ }
+
+ outPose=MEM_callocN(sizeof(bPose), "pose");
+
+ for (curChan=inPose->chanbase.first; curChan; curChan=curChan->next){
+ newChan=MEM_callocN(sizeof(bPoseChannel), "copyposePoseChannel");
+
+ strcpy (newChan->name, curChan->name);
+ newChan->flag=curChan->flag;
+
+ memcpy (newChan->loc, curChan->loc, sizeof (curChan->loc));
+ memcpy (newChan->size, curChan->size, sizeof (curChan->size));
+ memcpy (newChan->quat, curChan->quat, sizeof (curChan->quat));
+ Mat4CpyMat4 (newChan->obmat, curChan->obmat);
+
+ BLI_addtail (&outPose->chanbase, newChan);
+ if (copycon){
+ copy_constraints(&newChan->constraints, &curChan->constraints);
+ }
+ }
+
+ *dst=outPose;
+}
+
+bPoseChannel *set_pose_channel (bPose *pose, bPoseChannel *chan){
+ /* chan is no longer valid for the calling function.
+ and should not be used by that function after calling
+ this one
+ */
+ bPoseChannel *curChan;
+
+ /* Determine if an equivalent channel exists already */
+ for (curChan=pose->chanbase.first; curChan; curChan=curChan->next){
+ if (!strcmp (curChan->name, chan->name)){
+ if (chan->flag & POSE_ROT)
+ memcpy (curChan->quat, chan->quat, sizeof(chan->quat));
+ if (chan->flag & POSE_SIZE)
+ memcpy (curChan->size, chan->size, sizeof(chan->size));
+ if (chan->flag & POSE_LOC)
+ memcpy (curChan->loc, chan->loc, sizeof(chan->loc));
+ if (chan->flag & PCHAN_DONE)
+ Mat4CpyMat4 (curChan->obmat, chan->obmat);
+
+ curChan->flag |= chan->flag;
+ MEM_freeN (chan);
+ return curChan;
+ }
+ }
+
+ MEM_freeN (chan);
+ return NULL;
+ /* If an equivalent channel doesn't exist, then don't bother setting it. */
+}
+
+
diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c
new file mode 100644
index 00000000000..0fa358b30a0
--- /dev/null
+++ b/source/blender/blenkernel/intern/anim.c
@@ -0,0 +1,512 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 <string.h>
+
+#include "MEM_guardedalloc.h"
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "DNA_listBase.h"
+
+#include "DNA_object_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_key_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_effect_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_scene_types.h"
+
+#include "BKE_global.h"
+#include "BKE_utildefines.h"
+#include "BKE_anim.h"
+#include "BKE_ipo.h"
+#include "BKE_object.h"
+#include "BKE_displist.h"
+#include "BKE_key.h"
+#include "BKE_font.h"
+#include "BKE_effect.h"
+
+#include "BKE_bad_level_calls.h"
+
+ListBase duplilist= {0, 0};
+
+void free_path(Path *path)
+{
+ if(path->data) MEM_freeN(path->data);
+ MEM_freeN(path);
+}
+
+
+void calc_curvepath(Object *ob)
+{
+ BevList *bl;
+ BevPoint *bevp, *bevpn, *bevpfirst, *bevplast;
+ Curve *cu;
+ Nurb *nu;
+ Path *path;
+ float *fp, *dist, *maxdist, x, y, z;
+ float fac, d=0, fac1, fac2;
+ int a, tot, cycl=0;
+ float *ft;
+
+ /* in een pad zitten allemaal punten met gelijke afstand: path->len = aantal pt */
+ /* NU MET BEVELCURVE!!! */
+
+ if(ob==0 || ob->type != OB_CURVE) return;
+ cu= ob->data;
+ if(ob==G.obedit) nu= editNurb.first;
+ else nu= cu->nurb.first;
+
+ if(cu->path) free_path(cu->path);
+ cu->path= 0;
+
+ if((cu->flag & CU_PATH)==0) return;
+
+ bl= cu->bev.first;
+ if(bl==0) {
+ makeDispList(ob);
+ bl= cu->bev.first;
+ }
+ if(bl==0) return;
+
+ cu->path=path= MEM_callocN(sizeof(Path), "path");
+
+ /* als POLY: laatste punt != eerste punt */
+ cycl= (bl->poly!= -1);
+
+ if(cycl) tot= bl->nr;
+ else tot= bl->nr-1;
+
+ path->len= tot+1;
+ /* exception: vector handle paths and polygon paths should be subdivided at least a factor 6 (or more?) */
+ if(path->len<6*nu->pntsu) path->len= 6*nu->pntsu;
+
+ dist= (float *)MEM_mallocN((tot+1)*4, "berekenpaddist");
+
+ /* alle lengtes in *dist */
+ bevp= bevpfirst= (BevPoint *)(bl+1);
+ fp= dist;
+ *fp= 0;
+ for(a=0; a<tot; a++) {
+ fp++;
+ if(cycl && a==tot-1) {
+ x= bevpfirst->x - bevp->x;
+ y= bevpfirst->y - bevp->y;
+ z= bevpfirst->z - bevp->z;
+ }
+ else {
+ x= (bevp+1)->x - bevp->x;
+ y= (bevp+1)->y - bevp->y;
+ z= (bevp+1)->z - bevp->z;
+ }
+ *fp= *(fp-1)+ (float)sqrt(x*x+y*y+z*z);
+
+ bevp++;
+ }
+
+ path->totdist= *fp;
+
+ /* de padpunten in path->data */
+ /* nu ook met TILT */
+ ft= path->data = (float *)MEM_callocN(16*path->len, "pathdata");
+
+ bevp= bevpfirst;
+ bevpn= bevp+1;
+ bevplast= bevpfirst + (bl->nr-1);
+ fp= dist+1;
+ maxdist= dist+tot;
+ fac= 1.0f/((float)path->len-1.0f);
+
+ for(a=0; a<path->len; a++) {
+
+ d= ((float)a)*fac*path->totdist;
+
+ /* we zoeken plek 'd' in het array */
+ while((d>= *fp) && fp<maxdist) {
+ fp++;
+ if(bevp<bevplast) bevp++;
+ bevpn= bevp+1;
+ if(bevpn>bevplast) {
+ if(cycl) bevpn= bevpfirst;
+ else bevpn= bevplast;
+ }
+ }
+
+ fac1= *(fp)- *(fp-1);
+ fac2= *(fp)-d;
+ fac1= fac2/fac1;
+ fac2= 1.0f-fac1;
+
+ ft[0]= fac1*bevp->x+ fac2*(bevpn)->x;
+ ft[1]= fac1*bevp->y+ fac2*(bevpn)->y;
+ ft[2]= fac1*bevp->z+ fac2*(bevpn)->z;
+ ft[3]= fac1*bevp->alfa+ fac2*(bevpn)->alfa;
+
+ ft+= 4;
+
+ }
+
+ MEM_freeN(dist);
+}
+
+int interval_test(int min, int max, int p1, int cycl)
+{
+
+ if(cycl) {
+ if( p1 < min)
+ p1= ((p1 -min) % (max-min+1)) + max+1;
+ else if(p1 > max)
+ p1= ((p1 -min) % (max-min+1)) + min;
+ }
+ else {
+ if(p1 < min) p1= min;
+ else if(p1 > max) p1= max;
+ }
+ return p1;
+}
+
+int where_on_path(Object *ob, float ctime, float *vec, float *dir) /* geeft OK terug */
+{
+ Curve *cu;
+ Nurb *nu;
+ BevList *bl;
+ Path *path;
+ float *fp, *p0, *p1, *p2, *p3, fac;
+ float data[4];
+ int cycl=0, s0, s1, s2, s3;
+
+
+ if(ob==0 || ob->type != OB_CURVE) return 0;
+ cu= ob->data;
+ if(cu->path==0 || cu->path->data==0) calc_curvepath(ob);
+ path= cu->path;
+ fp= path->data;
+
+ /* cyclic testen */
+ bl= cu->bev.first;
+ if(bl && bl->poly> -1) cycl= 1;
+
+ /* ctime is van 0.0-1.0 */
+ ctime *= (path->len-1);
+
+ s1= (int)floor(ctime);
+ fac= (float)(s1+1)-ctime;
+
+ /* path->len is gecorrigeerd voor cyclic, zie boven, is beetje warrig! */
+ s0= interval_test(0, path->len-1-cycl, s1-1, cycl);
+ s1= interval_test(0, path->len-1-cycl, s1, cycl);
+ s2= interval_test(0, path->len-1-cycl, s1+1, cycl);
+ s3= interval_test(0, path->len-1-cycl, s1+2, cycl);
+
+ p0= fp + 4*s0;
+ p1= fp + 4*s1;
+ p2= fp + 4*s2;
+ p3= fp + 4*s3;
+
+ if(cu->flag & CU_FOLLOW) {
+
+ set_afgeleide_four_ipo(1.0f-fac, data, KEY_BSPLINE);
+
+ dir[0]= data[0]*p0[0] + data[1]*p1[0] + data[2]*p2[0] + data[3]*p3[0] ;
+ dir[1]= data[0]*p0[1] + data[1]*p1[1] + data[2]*p2[1] + data[3]*p3[1] ;
+ dir[2]= data[0]*p0[2] + data[1]*p1[2] + data[2]*p2[2] + data[3]*p3[2] ;
+
+ /* compatible maken met vectoquat */
+ dir[0]= -dir[0];
+ dir[1]= -dir[1];
+ dir[2]= -dir[2];
+ }
+
+ nu= cu->nurb.first;
+
+ /* zeker van zijn dat de eerste en laatste frame door de punten gaat */
+ if((nu->type & 7)==CU_POLY) set_four_ipo(1.0f-fac, data, KEY_LINEAR);
+ else if((nu->type & 7)==CU_BEZIER) set_four_ipo(1.0f-fac, data, KEY_LINEAR);
+ else if(s0==s1 || p2==p3) set_four_ipo(1.0f-fac, data, KEY_CARDINAL);
+ else set_four_ipo(1.0f-fac, data, KEY_BSPLINE);
+
+ vec[0]= data[0]*p0[0] + data[1]*p1[0] + data[2]*p2[0] + data[3]*p3[0] ;
+ vec[1]= data[0]*p0[1] + data[1]*p1[1] + data[2]*p2[1] + data[3]*p3[1] ;
+ vec[2]= data[0]*p0[2] + data[1]*p1[2] + data[2]*p2[2] + data[3]*p3[2] ;
+
+ vec[3]= data[0]*p0[3] + data[1]*p1[3] + data[2]*p2[3] + data[3]*p3[3] ;
+
+ return 1;
+}
+
+void frames_duplilist(Object *ob)
+{
+ extern int enable_cu_speed; /* object.c */
+ Object *newob;
+ int cfrao, ok;
+
+ cfrao= G.scene->r.cfra;
+ if(ob->parent==0 && ob->track==0 && ob->ipo==0) return;
+
+ if(ob->transflag & OB_DUPLINOSPEED) enable_cu_speed= 0;
+
+ /* dit om zeker van te zijn dat er iets gezbufferd wordt: in drawobject.c: dt==wire en boundboxclip */
+ if(G.background==0 && ob->type==OB_MESH) {
+ Mesh *me= ob->data;
+ DispList *dl;
+ if(me->disp.first==0) addnormalsDispList(ob, &me->disp);
+ if(ob->dt==OB_SHADED) {
+ dl= ob->disp.first;
+ if(dl==0 || dl->col1==0) shadeDispList(ob);
+ }
+ }
+
+ for(G.scene->r.cfra= ob->dupsta; G.scene->r.cfra<=ob->dupend; G.scene->r.cfra++) {
+
+ ok= 1;
+ if(ob->dupoff) {
+ ok= G.scene->r.cfra - ob->dupsta;
+ ok= ok % (ob->dupon+ob->dupoff);
+ if(ok < ob->dupon) ok= 1;
+ else ok= 0;
+ }
+ if(ok) {
+ newob= MEM_mallocN(sizeof(Object), "newobobj dupli");
+ memcpy(newob, ob, sizeof(Object));
+
+ /* alleen de basis-ball behoeft een displist */
+ if(newob->type==OB_MBALL) newob->disp.first= newob->disp.last= 0;
+
+ BLI_addtail(&duplilist, newob);
+ do_ob_ipo(newob);
+ where_is_object(newob);
+
+ newob->flag |= OB_FROMDUPLI;
+ newob->id.newid= (ID *)ob; /* duplicator bewaren */
+ }
+ }
+
+ G.scene->r.cfra= cfrao;
+ enable_cu_speed= 1;
+ do_ob_ipo(ob);
+}
+
+
+void vertex_duplilist(Scene *sce, Object *par)
+{
+ Object *ob, *newob;
+ Base *base;
+ MVert *mvert;
+ Mesh *me;
+ float vec[3], pvec[3], pmat[4][4], mat[3][3], tmat[4][4];
+ float *q2;
+ int lay, totvert, a;
+
+ Mat4CpyMat4(pmat, par->obmat);
+
+ Mat4One(tmat);
+
+ lay= G.scene->lay;
+
+ base= sce->base.first;
+ while(base) {
+
+ if(base->object->type>0 && (lay & base->lay) && G.obedit!=base->object) {
+ ob= base->object->parent;
+ while(ob) {
+ if(ob==par) {
+
+ ob= base->object;
+ /* mballs have a different dupli handling */
+ if(ob->type!=OB_MBALL) ob->flag |= OB_DONE; /* doesnt render */
+
+ me= par->data;
+ mvert= me->mvert;
+ mvert+= (me->totvert-1);
+ VECCOPY(pvec, mvert->co);
+ Mat4MulVecfl(pmat, pvec);
+
+ mvert= me->mvert;
+ totvert= me->totvert;
+
+ for(a=0; a<totvert; a++, mvert++) {
+
+ /* bereken de extra offset (tov. nulpunt parent) die de kinderen krijgen */
+ VECCOPY(vec, mvert->co);
+ Mat4MulVecfl(pmat, vec);
+ VecSubf(vec, vec, pmat[3]);
+ VecAddf(vec, vec, ob->obmat[3]);
+
+ newob= MEM_mallocN(sizeof(Object), "newobj dupli");
+ memcpy(newob, ob, sizeof(Object));
+ newob->flag |= OB_FROMDUPLI;
+ newob->id.newid= (ID *)par; /* duplicator bewaren */
+
+ /* alleen de basis-ball behoeft een displist */
+ if(newob->type==OB_MBALL) newob->disp.first= newob->disp.last= 0;
+
+ VECCOPY(newob->obmat[3], vec);
+
+ if(par->transflag & OB_DUPLIROT) {
+ VECCOPY(vec, mvert->no);
+ vec[0]= -vec[0]; vec[1]= -vec[1]; vec[2]= -vec[2];
+
+ q2= vectoquat(vec, ob->trackflag, ob->upflag);
+
+ QuatToMat3(q2, mat);
+ Mat4CpyMat4(tmat, newob->obmat);
+ Mat4MulMat43(newob->obmat, tmat, mat);
+ }
+
+ newob->parent= 0;
+ newob->track= 0;
+ /* newob->borig= base; */
+
+ BLI_addtail(&duplilist, newob);
+
+ VECCOPY(pvec, vec);
+
+ }
+ break;
+ }
+ ob= ob->parent;
+ }
+ }
+ base= base->next;
+ }
+}
+
+
+void particle_duplilist(Scene *sce, Object *par, PartEff *paf)
+{
+ Object *ob, *newob;
+ Base *base;
+ Particle *pa;
+ float ctime, vec1[3];
+ float vec[3], tmat[4][4], mat[3][3];
+ float *q2;
+ int lay, a;
+
+ pa= paf->keys;
+ if(pa==0) {
+ build_particle_system(par);
+ pa= paf->keys;
+ if(pa==0) return;
+ }
+
+ ctime= bsystem_time(par, 0, (float)G.scene->r.cfra, 0.0);
+
+ lay= G.scene->lay;
+
+ base= sce->base.first;
+ while(base) {
+
+ if(base->object->type>0 && (base->lay & lay) && G.obedit!=base->object) {
+ ob= base->object->parent;
+ while(ob) {
+ if(ob==par) {
+
+ ob= base->object;
+
+ pa= paf->keys;
+ for(a=0; a<paf->totpart; a++, pa+=paf->totkey) {
+
+ if(ctime > pa->time) {
+ if(ctime < pa->time+pa->lifetime) {
+
+ newob= MEM_mallocN(sizeof(Object), "newobj dupli");
+ memcpy(newob, ob, sizeof(Object));
+ newob->flag |= OB_FROMDUPLI;
+ newob->id.newid= (ID *)par; /* duplicator bewaren */
+
+ /* alleen de basis-ball behoeft een displist */
+ if(newob->type==OB_MBALL) newob->disp.first= newob->disp.last= 0;
+
+ where_is_particle(paf, pa, ctime, vec);
+ if(paf->stype==PAF_VECT) {
+ where_is_particle(paf, pa, ctime+1.0f, vec1);
+
+ VecSubf(vec1, vec1, vec);
+ q2= vectoquat(vec1, ob->trackflag, ob->upflag);
+
+ QuatToMat3(q2, mat);
+ Mat4CpyMat4(tmat, newob->obmat);
+ Mat4MulMat43(newob->obmat, tmat, mat);
+ }
+
+ VECCOPY(newob->obmat[3], vec);
+
+ newob->parent= 0;
+ newob->track= 0;
+
+ BLI_addtail(&duplilist, newob);
+
+ }
+ }
+ }
+ break;
+ }
+ ob= ob->parent;
+ }
+ }
+ base= base->next;
+ }
+}
+
+
+void free_duplilist()
+{
+ Object *ob;
+
+ while( ob= duplilist.first) {
+ BLI_remlink(&duplilist, ob);
+ MEM_freeN(ob);
+ }
+
+}
+
+void make_duplilist(Scene *sce, Object *ob)
+{
+ PartEff *paf;
+
+ if(ob->transflag & OB_DUPLI) {
+ if(ob->transflag & OB_DUPLIVERTS) {
+ if(ob->type==OB_MESH) {
+ if(ob->transflag & OB_DUPLIVERTS) {
+ if( paf=give_parteff(ob) ) particle_duplilist(sce, ob, paf);
+ else vertex_duplilist(sce, ob);
+ }
+ }
+ else if(ob->type==OB_FONT) {
+ font_duplilist(ob);
+ }
+ }
+ else if(ob->transflag & OB_DUPLIFRAMES) frames_duplilist(ob);
+ }
+}
+
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
new file mode 100644
index 00000000000..86ce2faa07c
--- /dev/null
+++ b/source/blender/blenkernel/intern/armature.c
@@ -0,0 +1,1451 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 <string.h>
+#include <stdio.h>
+#include "MEM_guardedalloc.h"
+
+#include "nla.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_action_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_constraint_types.h"
+
+#include "BKE_displist.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_library.h"
+#include "BKE_blender.h"
+#include "BKE_armature.h"
+#include "BKE_action.h"
+#include "BKE_constraint.h"
+#include "BKE_object.h"
+#include "BKE_object.h"
+#include "BKE_deform.h"
+#include "BKE_utildefines.h"
+
+#include "BIF_editdeform.h"
+
+#include "IK_solver.h"
+
+/* Function prototypes */
+
+static void apply_pose_bonechildren (Bone* bone, bPose* pose, int doit);
+static float dist_to_bone (float vec[3], float b1[3], float b2[3]);
+static Bone *get_named_bone_bonechildren (Bone *bone, const char *name);
+static Bone *get_indexed_bone_bonechildren (Bone *bone, int *index);
+/*void make_bone_parent_matrix (Bone* bone);*/
+static void copy_bonechildren (Bone* newBone, Bone* oldBone);
+static void calc_armature_deform_bonechildren (Bone *bone, float *vec, float *co, float *contrib, float obmat[][4]);
+static int verify_boneptr_children (Bone *cBone, Bone *tBone);
+static void where_is_bonelist_time (Object *ob, ListBase *base, float ctime);
+static Bone *get_last_ik_bone (Bone *bone);
+static void precalc_bonelist_posemats(ListBase *bonelist, float parlen);
+
+/* Globals */
+static float g_premat[4][4];
+static float g_postmat[4][4];
+static MDeformVert *g_dverts;
+static ListBase *g_defbase;
+static bArmature *g_defarm;
+
+/* Functions */
+
+float get_bone_length (Bone *bone)
+{
+ float result[3];
+
+ VecSubf (result, bone->tail, bone->head);
+ return (float)sqrt(result[0]*result[0] + result[1]*result[1] + result[2]*result[2]);
+
+}
+
+void apply_bonemat(Bone *bone)
+{
+ float mat[3][3], imat[3][3], tmat[3][3];
+
+ if(!bone)
+ return;
+
+ Mat3CpyMat4(mat, bone->obmat);
+
+ VECCOPY(bone->loc, bone->obmat[3]);
+
+ Mat3ToQuat(mat, bone->quat);
+ QuatToMat3(bone->quat, tmat);
+
+ Mat3Inv(imat, tmat);
+
+ Mat3MulMat3(tmat, imat, mat);
+
+ bone->size[0]= tmat[0][0];
+ bone->size[1]= tmat[1][1];
+ bone->size[2]= tmat[2][2];
+
+}
+
+void GB_build_mats (float parmat[][4], float obmat[][4], float premat[][4], float postmat[][4])
+{
+ float obinv[4][4];
+#if 0
+ Mat4Invert(obinv, obmat);
+ Mat4CpyMat4(premat, obmat);
+ Mat4MulMat4(postmat, parmat, obinv);
+
+ Mat4Invert (postmat, premat);
+#else
+ Mat4Invert(obinv, obmat);
+ Mat4CpyMat4(premat, obmat);
+ Mat4MulMat4(postmat, parmat, obinv);
+
+ Mat4Invert (premat, postmat);
+#endif
+}
+
+void GB_init_armature_deform(ListBase *defbase, float premat[][4], float postmat[][4])
+{
+ g_defbase = defbase;
+ Mat4CpyMat4 (g_premat, premat);
+ Mat4CpyMat4 (g_postmat, postmat);
+
+}
+
+void GB_validate_defgroups (Mesh *mesh, ListBase *defbase)
+{
+ /* Should only be called when the mesh or armature changes */
+ int j, i;
+ MDeformVert *dvert;
+
+ for (j=0; j<mesh->totvert; j++){
+ dvert = mesh->dvert+j;
+ for (i=0; i<dvert->totweight; i++)
+ dvert->dw[i].data = ((bDeformGroup*)BLI_findlink (defbase, dvert->dw[i].def_nr))->data;
+ }
+}
+
+void GB_calc_armature_deform (float *co, MDeformVert *dvert)
+{
+ float vec[3]={0, 0, 0};
+ float contrib = 0;
+ int i;
+ Bone *bone;
+
+ Mat4MulVecfl(g_premat, co);
+
+ for (i=0; i<dvert->totweight; i++){
+ bone = dvert->dw[i].data;
+ if (bone) calc_bone_deform (bone, dvert->dw[i].weight, vec, co, &contrib);
+ }
+
+ if (contrib){
+ vec[0]/=contrib;
+ vec[1]/=contrib;
+ vec[2]/=contrib;
+ }
+
+ VecAddf (co, vec, co);
+ Mat4MulVecfl(g_postmat, co);
+}
+
+static Bone *get_last_ik_bone (Bone *bone)
+{
+ Bone *curBone;
+
+ for (curBone = bone->childbase.first; curBone; curBone=curBone->next){
+ if (curBone->flag & BONE_IK_TOPARENT){
+ return get_last_ik_bone (curBone);
+ }
+ }
+
+ return bone;
+}
+
+#if 0
+static Bone *get_first_ik_bone (Bone *bone)
+{
+ Bone *curBone;
+
+ for (curBone = bone; curBone; curBone=curBone->parent){
+ if (!bone->parent)
+ return curBone;
+ if (!bone->flag & BONE_IK_TOPARENT)
+ return curBone;
+ }
+
+ return bone;
+/* for (curBone = bone->childbase.first; curBone; curBone=curBone->next){
+ if (curBone->flag & BONE_IK_TOPARENT){
+ return get_last_ik_bone (curBone);
+ }
+ }
+*/
+ return bone;
+
+}
+#endif
+
+void where_is_bone(Object *ob, Bone *bone)
+{
+ where_is_bone_time (ob, bone, G.scene->r.cfra);
+}
+
+void where_is_bone_time (Object *ob, Bone *bone, float ctime)
+{
+ where_is_bone1_time (ob, get_last_ik_bone(bone), ctime);
+}
+
+void rebuild_bone_parent_matrix (Bone *bone)
+{
+ if (!bone)
+ return;
+
+ if (bone->parent)
+ rebuild_bone_parent_matrix(bone->parent);
+
+ /* Get the parent inverse */
+ if (bone->parent)
+ Mat4MulMat4(bone->parmat, bone->parent->obmat, bone->parent->parmat);
+ else
+ Mat4One (bone->parmat);
+
+}
+void where_is_bone1_time (Object *ob, Bone *bone, float ctime)
+/* Assumes the pose has already been retrieved from the action */
+/* Also assumes where_is_object has been called for owner */
+{
+ bPose *pose;
+ bPoseChannel *chan;
+ bArmature *arm;
+ float imat[4][4];
+ float totmat[4][4];
+ Object conOb;
+
+ pose = ob->pose;
+ if (!pose)
+ return;
+
+ arm = get_armature(ob);
+
+ /* Ensure there is achannel for this bone*/
+ verify_pose_channel (pose, bone->name);
+
+ /* Search the pose for a channel with the same name, and copy the
+ transformations from the channel into the bone */
+ for (chan=pose->chanbase.first; chan; chan=chan->next){
+ if (!strcmp (chan->name, bone->name)){
+
+#if 1 /* If 1 attempt to use pose caching features */
+ /* Bail out if we've been recalced recently */
+ if (chan->flag & PCHAN_DONE){
+ Mat4CpyMat4 (bone->obmat, chan->obmat);
+ if (bone->parent){
+ if ((bone->flag & BONE_IK_TOPARENT))
+ where_is_bone1_time (ob, bone->parent, ctime);
+ else
+ where_is_bone_time (ob, bone->parent, ctime);
+ }
+ return;
+ }
+ else
+ chan->flag |= PCHAN_DONE;
+#endif
+ break;
+ }
+ }
+
+#if 1
+ /* Ensure parents have been evaluated */
+ if (bone->parent){
+ if ((bone->flag & BONE_IK_TOPARENT))
+ where_is_bone1_time (ob, bone->parent, ctime);
+ else
+ where_is_bone_time (ob, bone->parent, ctime);
+ }
+
+ /* Build the parent matrix : Depreciated */
+// if (bone->parent)
+// Mat4MulMat4(bone->parmat, bone->parent->obmat, bone->parent->parmat);
+// else
+// Mat4One (bone->parmat);
+#endif
+
+ if (arm){
+ if ((arm->flag & ARM_RESTPOS) || ((G.obedit && (ob->data == G.obedit->data)))){
+ Mat4One (bone->obmat);
+ Mat4One (chan->obmat);
+ return;
+ }
+ }
+
+ if (bone->flag & BONE_IK_TOPARENT){
+ bone->loc[0]=bone->loc[1]=bone->loc[2]=0.0F;
+ }
+ bone_to_mat4(bone, bone->obmat);
+
+ /* Do constraints */
+ // clear_workob();
+
+ memset(&conOb, 0, sizeof(Object));
+ conOb.size[0]= conOb.size[1]= conOb.size[2]= 1.0;
+
+ /* Collect the constraints from the pose */
+ conOb.constraints.first = chan->constraints.first;
+ conOb.constraints.last = chan->constraints.last;
+
+ /* Totmat takes bone's obmat to worldspace */
+
+ {
+ float parmat[4][4];
+ float temp[4][4];
+
+ Mat4CpyMat4 (temp, bone->obmat);
+ Mat4One (bone->obmat);
+ get_objectspace_bone_matrix(bone, parmat, 1, 1);
+ Mat4CpyMat4 (bone->obmat, temp);
+ Mat4MulMat4 (totmat, parmat, ob->obmat);
+ }
+
+ /* Build a workob to pass the bone to the constraint solver */
+ conOb.data = ob->data;
+ conOb.type = ob->type;
+ conOb.parent = ob;
+ conOb.trackflag = ob->trackflag;
+ conOb.upflag = ob->upflag;
+
+ VECCOPY(conOb.size, bone->size);
+
+ Mat4MulMat4 (conOb.obmat, bone->obmat, totmat);
+
+ /* Solve */
+ solve_constraints (&conOb, TARGET_BONE, (void*)bone, ctime);
+
+ {
+ float parmat[4][4];
+ float temp[4][4];
+
+ Mat4CpyMat4 (temp, bone->obmat);
+ Mat4One (bone->obmat);
+ get_objectspace_bone_matrix(bone, parmat, 1, 1);
+ Mat4CpyMat4 (bone->obmat, temp);
+ Mat4MulMat4 (totmat, parmat, ob->obmat);
+ }
+
+ VECCOPY(bone->size, conOb.size);
+
+ /* Take out of worldspace */
+ Mat4Invert (imat, totmat);
+ Mat4MulMat4 (bone->obmat, conOb.obmat, imat);
+ Mat4CpyMat4 (chan->obmat, bone->obmat);
+
+}
+
+
+bArmature *get_armature(Object *ob)
+{
+ if(ob==NULL) return NULL;
+ if(ob->type==OB_ARMATURE) return ob->data;
+ else return NULL;
+}
+
+void init_armature_deform(Object *parent, Object *ob)
+{
+ bArmature *arm;
+ bDeformGroup *dg;
+ Bone *curBone;
+ MDeformVert *dvert;
+ int totverts;
+ float obinv[4][4];
+ int i, j;
+
+ arm = get_armature(parent);
+ if (!arm)
+ return;
+
+ if (ob)
+ where_is_object (ob);
+
+#if 1
+ apply_pose_armature (arm, parent->pose, 1); /* Hopefully doit parameter can be set to 0 in future */
+ where_is_armature (parent);
+#else
+ apply_pose_armature (arm, parent->pose, 0);
+#endif
+
+ g_defbase = &ob->defbase;
+ g_defarm = arm;
+
+ Mat4Invert(obinv, ob->obmat);
+ Mat4CpyMat4(g_premat, ob->obmat);
+ Mat4MulMat4(g_postmat, parent->obmat, obinv);
+
+ Mat4Invert (g_premat, g_postmat);
+
+ /* Store the deformation verts */
+ if (ob->type==OB_MESH){
+ g_dverts = ((Mesh*)ob->data)->dvert;
+ totverts = ((Mesh*)ob->data)->totvert;
+ }
+ else{
+ g_dverts=NULL;
+ totverts=0;
+ }
+
+ /* Precalc bone defmats */
+ precalc_armature_posemats (arm);
+
+ for (curBone=arm->bonebase.first; curBone; curBone=curBone->next){
+ precalc_bone_defmat(curBone);
+ }
+
+ /* Validate bone data in bDeformGroups */
+
+ for (dg=g_defbase->first; dg; dg=dg->next)
+ dg->data = (void*)get_named_bone(arm, dg->name);
+
+ if (g_dverts){
+ for (j=0; j<totverts; j++){
+ dvert = g_dverts+j;
+ for (i=0; i<dvert->totweight; i++){
+ bDeformGroup *fg;
+ fg = BLI_findlink (g_defbase, dvert->dw[i].def_nr);
+
+ if (fg)
+ dvert->dw[i].data = fg->data;
+ else
+ dvert->dw[i].data = NULL;
+ }
+ }
+ }
+}
+
+void get_bone_root_pos (Bone* bone, float vec[3], int posed)
+{
+ Bone *curBone;
+ float mat[4][4];
+
+ get_objectspace_bone_matrix(bone, mat, 1, posed);
+ VECCOPY (vec, mat[3]);
+ return;
+
+ rebuild_bone_parent_matrix(bone);
+ if (posed){
+
+ get_objectspace_bone_matrix(bone, mat, 1, posed);
+ VECCOPY (vec, mat[3]);
+ }
+ else {
+ vec[0]=vec[1]=vec[2]=0.0F;
+ for (curBone=bone; curBone; curBone=curBone->parent){
+ if (curBone==bone)
+ VecAddf (vec, vec, curBone->head);
+ else
+ VecAddf (vec, vec, curBone->tail);
+ }
+ }
+}
+
+void get_bone_tip_pos (Bone* bone, float vec[3], int posed)
+{
+ Bone *curBone;
+ float mat[4][4], tmat[4][4], rmat[4][4], bmat[4][4], fmat[4][4];
+
+ get_objectspace_bone_matrix(bone, mat, 0, posed);
+ VECCOPY (vec, mat[3]);
+ return;
+
+ rebuild_bone_parent_matrix(bone);
+ if (posed){
+
+ Mat4One (mat);
+
+ for (curBone = bone; curBone; curBone=curBone->parent){
+ Mat4One (bmat);
+ /* [BMAT] This bone's offset */
+ VECCOPY (bmat[3], curBone->head);
+ if (curBone==bone){
+ Mat4One (tmat);
+ VecSubf (tmat[3], curBone->tail, curBone->head);
+ Mat4MulMat4 (bmat, tmat, curBone->obmat);
+ VecAddf (bmat[3], bmat[3], curBone->head);
+ }
+ else
+ VecAddf (bmat[3], bmat[3], curBone->obmat[3]); // Test
+
+ /* [RMAT] Parent's bone length = parent rotmat * bone length */
+ if (curBone->parent){
+ Mat4One (tmat);
+ VecSubf (tmat[3], curBone->parent->tail, curBone->parent->head);
+ Mat4MulMat4 (rmat, tmat, curBone->parent->obmat);
+ VecSubf (rmat[3], rmat[3], curBone->parent->obmat[3]);
+ }
+ else
+ Mat4One (rmat);
+
+ Mat4MulSerie (fmat, rmat, bmat, mat, 0, 0, 0, 0, 0);
+ Mat4CpyMat4 (mat, fmat);
+ }
+
+ VECCOPY (vec, mat[3]);
+ }
+ else{
+ vec[0]=vec[1]=vec[2]=0.0F;
+ for (curBone=bone; curBone; curBone=curBone->parent){
+ VecAddf (vec, vec, curBone->tail);
+ }
+ }
+}
+
+int verify_boneptr (bArmature *arm, Bone *bone)
+{
+ /* Ensures that a given bone exists in an armature */
+ Bone *curBone;
+
+ if (!arm)
+ return 0;
+
+ for (curBone=arm->bonebase.first; curBone; curBone=curBone->next){
+ if (verify_boneptr_children (curBone, bone))
+ return 1;
+ }
+
+ return 0;
+}
+
+static int verify_boneptr_children (Bone *cBone, Bone *tBone)
+{
+ Bone *curBone;
+
+ if (cBone == tBone)
+ return 1;
+
+ for (curBone=cBone->childbase.first; curBone; curBone=curBone->next){
+ if (verify_boneptr_children (curBone, tBone))
+ return 1;
+ }
+ return 0;
+}
+
+
+static float dist_to_bone (float vec[3], float b1[3], float b2[3])
+{
+/* float dist=0; */
+ float bdelta[3];
+ float pdelta[3];
+ float hsqr, a, l;
+
+ VecSubf (bdelta, b2, b1);
+ l = Normalise (bdelta);
+
+ VecSubf (pdelta, vec, b1);
+
+ a = bdelta[0]*pdelta[0] + bdelta[1]*pdelta[1] + bdelta[2]*pdelta[2];
+ hsqr = ((pdelta[0]*pdelta[0]) + (pdelta[1]*pdelta[1]) + (pdelta[2]*pdelta[2]));
+
+ if (a < 0.0F){
+ //return 100000;
+ /* If we're past the end of the bone, do some weird field attenuation thing */
+ return ((b1[0]-vec[0])*(b1[0]-vec[0]) +(b1[1]-vec[1])*(b1[1]-vec[1]) +(b1[2]-vec[2])*(b1[2]-vec[2])) ;
+ }
+ else if (a > l){
+ //return 100000;
+ /* If we're past the end of the bone, do some weird field attenuation thing */
+ return ((b2[0]-vec[0])*(b2[0]-vec[0]) +(b2[1]-vec[1])*(b2[1]-vec[1]) +(b2[2]-vec[2])*(b2[2]-vec[2])) ;
+ }
+ else {
+ return (hsqr - (a*a));
+ }
+
+
+}
+
+static void calc_armature_deform_bonechildren (Bone *bone, float *vec, float *co, float *contrib, float obmat[][4])
+{
+ Bone *curBone;
+ float root[3];
+ float tip[3];
+ float dist, fac, ifac;
+ float cop[3];
+ float bdsqr;
+
+
+ get_bone_root_pos (bone, root, 0);
+ get_bone_tip_pos (bone, tip, 0);
+
+ bdsqr = bone->dist*bone->dist;
+ VECCOPY (cop, co);
+
+ dist = dist_to_bone(cop, root, tip);
+
+ if ((dist) <= bdsqr){
+ fac = (dist)/bdsqr;
+ ifac = 1.0F-fac;
+
+ ifac*=bone->weight;
+
+ if (!vec)
+ (*contrib) +=ifac;
+ else{
+ ifac*=(1.0F/(*contrib));
+
+ VECCOPY (cop, co);
+
+ Mat4MulVecfl(bone->defmat, cop);
+
+ VecSubf (cop, cop, co); // Make this a delta from the base position
+ cop[0]*=ifac; cop[1]*=ifac; cop[2]*=ifac;
+ VecAddf (vec, vec, cop);
+
+ }
+ }
+
+// calc_bone_deform (bone, bone->weight, vec, co, contrib, obmat);
+ for (curBone = bone->childbase.first; curBone; curBone=curBone->next)
+ calc_armature_deform_bonechildren (curBone, vec, co, contrib, obmat);
+}
+
+void precalc_bone_irestmat (Bone *bone)
+{
+ float restmat[4][4];
+
+ get_objectspace_bone_matrix(bone, restmat, 1, 0);
+ Mat4Invert (bone->irestmat, restmat);
+}
+
+static void precalc_bonelist_posemats(ListBase *bonelist, float parlen)
+{
+ Bone *curBone;
+ float length;
+ float T_parlen[4][4];
+ float T_root[4][4];
+ float M_obmat[4][4];
+ float R_bmat[4][4];
+ float M_accumulatedMatrix[4][4];
+ float delta[3];
+
+ for (curBone = bonelist->first; curBone; curBone=curBone->next){
+
+ /* Get the length translation (length along y axis) */
+ length = get_bone_length(curBone);
+
+ /* Get the bone's root offset (in the parent's coordinate system) */
+ Mat4One (T_root);
+ VECCOPY (T_root[3], curBone->head);
+
+ /* Compose the restmat */
+ VecSubf(delta, curBone->tail, curBone->head);
+ make_boneMatrixvr(R_bmat, delta, curBone->roll);
+
+ /* Retrieve the obmat (user transformation) */
+ Mat4CpyMat4 (M_obmat, curBone->obmat);
+
+ /* Compose the accumulated matrix (i.e. parent matrix * parent translation ) */
+ if (curBone->parent){
+ Mat4One (T_parlen);
+ T_parlen[3][1] = parlen;
+ Mat4MulMat4 (M_accumulatedMatrix, T_parlen, curBone->parent->posemat);
+ }
+ else
+ Mat4One (M_accumulatedMatrix);
+
+ /* Compose the matrix for this bone */
+ Mat4MulSerie (curBone->posemat, M_accumulatedMatrix, T_root, R_bmat, M_obmat, NULL, NULL, NULL, NULL);
+
+ precalc_bonelist_posemats(&curBone->childbase, length);
+ }
+}
+
+void precalc_armature_posemats (bArmature *arm)
+{
+ precalc_bonelist_posemats(&arm->bonebase, 0.0);
+}
+
+void precalc_bone_defmat (Bone *bone)
+{
+ Bone *curBone;
+#if 0
+ float restmat[4][4];
+ float posemat[4][4];
+ float imat[4][4];
+
+ /* Store restmat and restmat inverse - Calculate once when leaving editmode */
+ /* Store all bones' posemats - Do when applied */
+
+ /* EXPENSIVE! Don't do this! */
+ get_objectspace_bone_matrix(bone, restmat, 1, 0);
+ get_objectspace_bone_matrix(bone, posemat, 1, 1);
+ Mat4Invert (imat, restmat);
+ Mat4MulMat4 (bone->defmat, imat, posemat);
+ /* /EXPENSIVE */
+#else
+ Mat4MulMat4 (bone->defmat, bone->irestmat, bone->posemat);
+#endif
+ for (curBone = bone->childbase.first; curBone; curBone=curBone->next){
+ precalc_bone_defmat(curBone);
+ }
+}
+
+void calc_bone_deform (Bone *bone, float weight, float *vec, float *co, float *contrib)
+{
+ float cop[3];
+
+ if (!weight)
+ return;
+
+ VECCOPY (cop, co);
+
+ Mat4MulVecfl(bone->defmat, cop);
+
+ vec[0]+=(cop[0]-co[0])*weight;
+ vec[1]+=(cop[1]-co[1])*weight;
+ vec[2]+=(cop[2]-co[2])*weight;
+
+ (*contrib)+=weight;
+}
+
+void calc_armature_deform (Object *ob, float *co, int index)
+{
+ bArmature *arm;
+ Bone *bone;
+ Bone *curBone;
+ float vec[3];
+ float contrib=0;
+ int i;
+ MDeformVert *dvert = g_dverts+index;
+
+ arm=g_defarm;
+ vec[0]=vec[1]=vec[2]=0;
+
+ /* Apply the object's matrix */
+ Mat4MulVecfl(g_premat, co);
+
+ if (g_dverts){
+ for (i=0; i<dvert->totweight; i++){
+ bone = dvert->dw[i].data;
+ if (bone) calc_bone_deform (bone, dvert->dw[i].weight, vec, co, &contrib);
+ }
+
+ if (contrib){
+ vec[0]/=contrib;
+ vec[1]/=contrib;
+ vec[2]/=contrib;
+ }
+ VecAddf (co, vec, co);
+ Mat4MulVecfl(g_postmat, co);
+ return;
+ }
+
+
+ // Count the number of interested bones
+ for (curBone = arm->bonebase.first; curBone; curBone=curBone->next)
+ calc_armature_deform_bonechildren (curBone, NULL, co, &contrib, ob->obmat);
+
+ // Do the deformation
+ for (curBone = arm->bonebase.first; curBone; curBone=curBone->next)
+ calc_armature_deform_bonechildren (curBone, vec, co, &contrib, ob->obmat);
+
+ VecAddf (co, vec, co);
+ Mat4MulVecfl(g_postmat, co);
+}
+
+void apply_pose_armature (bArmature* arm, bPose* pose, int doit)
+{
+ Bone *curBone;
+ for (curBone = arm->bonebase.first; curBone; curBone=curBone->next){
+ apply_pose_bonechildren (curBone, pose, doit);
+ }
+}
+
+void where_is_armature (Object *ob)
+{
+ where_is_object (ob);
+ where_is_armature_time(ob, (float)G.scene->r.cfra);
+}
+
+void where_is_armature_time (Object *ob, float ctime)
+{
+ bArmature *arm;
+
+ arm = get_armature(ob);
+ if (!arm)
+ return;
+
+ where_is_bonelist_time (ob, &arm->bonebase, ctime);
+
+}
+
+static void where_is_bonelist_time (Object *ob, ListBase *base, float ctime)
+{
+ Bone *curBone;
+
+ for (curBone=base->first; curBone; curBone=curBone->next){
+ if (!curBone->childbase.first)
+ where_is_bone1_time (ob, curBone, ctime);
+
+ where_is_bonelist_time(ob, &curBone->childbase, ctime);
+ }
+}
+static void apply_pose_bonechildren (Bone* bone, bPose* pose, int doit)
+{
+ Bone *curBone;
+ bPoseChannel *chan;
+
+ if (!pose){
+
+ bone->dsize[0]=bone->dsize[1]=bone->dsize[2]=1.0F;
+ bone->size[0]=bone->size[1]=bone->size[2]=1.0F;
+
+ bone->dquat[0]=bone->dquat[1]=bone->dquat[2]=bone->dquat[3]=0;
+ bone->quat[0]=bone->quat[1]=bone->quat[2]=bone->quat[3]=0.0F;
+
+ bone->dloc[0]=bone->dloc[1]=bone->dloc[2]=0.0F;
+ bone->loc[0]=bone->loc[1]=bone->loc[2]=0.0F;
+ }
+
+ // Ensure there is achannel for this bone
+ verify_pose_channel (pose, bone->name);
+
+ // Search the pose for a channel with the same name
+ if (pose){
+ for (chan=pose->chanbase.first; chan; chan=chan->next){
+ if (!strcmp (chan->name, bone->name)){
+ if (chan->flag & POSE_LOC)
+ memcpy (bone->loc, chan->loc, sizeof (bone->loc));
+ if (chan->flag & POSE_SIZE)
+ memcpy (bone->size, chan->size, sizeof (bone->size));
+ if (chan->flag & POSE_ROT)
+ memcpy (bone->quat, chan->quat, sizeof (bone->quat));
+
+ if (doit){
+ bone_to_mat4(bone, bone->obmat);
+ }
+ else{
+ Mat4CpyMat4 (bone->obmat, chan->obmat);
+ }
+
+
+ break;
+ }
+ }
+ }
+
+ for (curBone = bone->childbase.first; curBone; curBone=curBone->next){
+ apply_pose_bonechildren (curBone, pose, doit);
+ }
+}
+
+void make_boneMatrixvr (float outmatrix[][4],float delta[3], float roll)
+/* Calculates the rest matrix of a bone based
+ On its vector and a roll around that vector */
+{
+ float nor[3],axis[3],target[3]={0,1,0};
+ float theta;
+ float rMatrix[3][3], bMatrix[3][3], fMatrix[3][3];
+
+ VECCOPY (nor,delta);
+ Normalise (nor);
+
+ /* Find Axis & Amount for bone matrix*/
+ Crossf (axis,target,nor);
+ Normalise (axis);
+ theta=(float) acos (Inpf (target,nor));
+
+ /* Make Bone matrix*/
+ VecRotToMat3(axis, theta, bMatrix);
+
+ /* Make Roll matrix*/
+ VecRotToMat3(nor, roll, rMatrix);
+
+ /* Combine and output result*/
+ Mat3MulMat3 (fMatrix,rMatrix,bMatrix);
+ Mat4CpyMat3 (outmatrix,fMatrix);
+}
+
+void make_boneMatrix (float outmatrix[][4], Bone *bone)
+/* Calculates the rest matrix of a bone based
+ On its vector and a roll around that vector */
+{
+ float delta[3];
+ float parmat[4][4], imat[4][4], obmat[4][4];
+
+ if (bone->parent){
+ VecSubf (delta, bone->parent->tail, bone->parent->head);
+ make_boneMatrixvr(parmat, delta, bone->parent->roll);
+ }
+ else{
+ Mat4One (parmat);
+ }
+
+ Mat4Invert (imat, parmat);
+
+ VecSubf (delta, bone->tail, bone->head);
+ make_boneMatrixvr(obmat, delta, bone->roll);
+
+ Mat4MulMat4(outmatrix, obmat, imat);
+
+}
+
+
+bArmature *add_armature()
+{
+ bArmature *arm;
+
+ arm= alloc_libblock (&G.main->armature, ID_AR, "Armature");
+
+ if(arm) {
+
+
+ }
+ return arm;
+}
+
+
+void free_boneChildren(Bone *bone)
+{
+ Bone *child;
+
+ if (bone) {
+
+ child=bone->childbase.first;
+ if (child){
+ while (child){
+ free_boneChildren (child);
+ child=child->next;
+ }
+ BLI_freelistN (&bone->childbase);
+ }
+ }
+}
+
+void free_bones (bArmature *arm)
+{
+ Bone *bone;
+ /* Free children (if any) */
+ bone= arm->bonebase.first;
+ if (bone) {
+ while (bone){
+ free_boneChildren (bone);
+ bone=bone->next;
+ }
+ }
+
+
+ BLI_freelistN(&arm->bonebase);
+}
+
+void free_armature(bArmature *arm)
+{
+ if (arm) {
+/* unlink_armature(arm);*/
+ free_bones(arm);
+ }
+}
+
+void make_local_armature(bArmature *arm)
+{
+ int local=0, lib=0;
+ Object *ob;
+ bArmature *newArm;
+
+ if (arm->id.lib==0)
+ return;
+ if (arm->id.us==1) {
+ arm->id.lib= 0;
+ arm->id.flag= LIB_LOCAL;
+ new_id(0, (ID*)arm, 0);
+ return;
+ }
+
+ if(local && lib==0) {
+ arm->id.lib= 0;
+ arm->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)arm, 0);
+ }
+ else if(local && lib) {
+ newArm= copy_armature(arm);
+ newArm->id.us= 0;
+
+ ob= G.main->object.first;
+ while(ob) {
+ if(ob->data==arm) {
+
+ if(ob->id.lib==0) {
+ ob->data= newArm;
+ newArm->id.us++;
+ arm->id.us--;
+ }
+ }
+ ob= ob->id.next;
+ }
+ }
+}
+
+static void copy_bonechildren (Bone* newBone, Bone* oldBone)
+{
+ Bone *curBone, *newChildBone;
+
+ /* Copy this bone's list*/
+ duplicatelist (&newBone->childbase, &oldBone->childbase);
+
+ /* For each child in the list, update it's children*/
+ newChildBone=newBone->childbase.first;
+ for (curBone=oldBone->childbase.first;curBone;curBone=curBone->next){
+ newChildBone->parent=newBone;
+ copy_bonechildren(newChildBone,curBone);
+ newChildBone=newChildBone->next;
+ }
+}
+
+bArmature *copy_armature(bArmature *arm)
+{
+ bArmature *newArm;
+ Bone *oldBone, *newBone;
+
+ newArm= copy_libblock (arm);
+ duplicatelist(&newArm->bonebase, &arm->bonebase);
+
+ /* Duplicate the childrens' lists*/
+ newBone=newArm->bonebase.first;
+ for (oldBone=arm->bonebase.first;oldBone;oldBone=oldBone->next){
+ newBone->parent=NULL;
+ copy_bonechildren (newBone, oldBone);
+ newBone=newBone->next;
+ };
+
+ return newArm;
+}
+
+
+void bone_to_mat3(Bone *bone, float mat[][3]) /* no parent */
+{
+ float smat[3][3];
+ float rmat[3][3];
+/* float q1[4], vec[3];*/
+
+ /* size */
+/* if(bone->ipo) {
+ vec[0]= bone->size[0]+bone->dsize[0];
+ vec[1]= bone->size[1]+bone->dsize[1];
+ vec[2]= bone->size[2]+bone->dsize[2];
+ SizeToMat3(vec, smat);
+ }
+ else
+*/ {
+ SizeToMat3(bone->size, smat);
+ }
+
+ /* rot */
+ /*if(bone->flag & BONE_QUATROT) {
+ if(bone->ipo) {
+ QuatMul(q1, bone->quat, bone->dquat);
+ QuatToMat3(q1, rmat);
+ }
+ else
+ */ {
+ NormalQuat(bone->quat);
+ QuatToMat3(bone->quat, rmat);
+ }
+/* }
+*/
+ Mat3MulMat3(mat, rmat, smat);
+}
+
+void bone_to_mat4(Bone *bone, float mat[][4])
+{
+ float tmat[3][3];
+
+ bone_to_mat3(bone, tmat);
+
+ Mat4CpyMat3(mat, tmat);
+
+ VECCOPY(mat[3], bone->loc);
+// VecAddf(mat[3], mat[3], bone->loc);
+/* if(bone->ipo) {
+ mat[3][0]+= bone->dloc[0];
+ mat[3][1]+= bone->dloc[1];
+ mat[3][2]+= bone->dloc[2];
+ }
+*/
+}
+
+Bone *get_indexed_bone (bArmature *arm, int index)
+/*
+ Walk the list until the index is reached
+*/
+{
+ Bone *bone=NULL, *curBone;
+ int ref=index;
+
+ if (!arm)
+ return NULL;
+
+ for (curBone=arm->bonebase.first; curBone; curBone=curBone->next){
+ bone = get_indexed_bone_bonechildren (curBone, &ref);
+ if (bone)
+ return bone;
+ }
+
+ return bone;
+}
+
+Bone *get_named_bone (bArmature *arm, const char *name)
+/*
+ Walk the list until the bone is found
+*/
+{
+ Bone *bone=NULL, *curBone;
+
+ if (!arm) return NULL;
+
+ for (curBone=arm->bonebase.first; curBone; curBone=curBone->next){
+ bone = get_named_bone_bonechildren (curBone, name);
+ if (bone)
+ return bone;
+ }
+
+ return bone;
+}
+
+static Bone *get_indexed_bone_bonechildren (Bone *bone, int *index)
+{
+ Bone *curBone, *rbone;
+
+ if (!*index)
+ return bone;
+
+ (*index)--;
+
+ for (curBone=bone->childbase.first; curBone; curBone=curBone->next){
+ rbone=get_indexed_bone_bonechildren (curBone, index);
+ if (rbone)
+ return rbone;
+ }
+
+ return NULL;
+}
+
+static Bone *get_named_bone_bonechildren (Bone *bone, const char *name)
+{
+ Bone *curBone, *rbone;
+
+ if (!strcmp (bone->name, name))
+ return bone;
+
+ for (curBone=bone->childbase.first; curBone; curBone=curBone->next){
+ rbone=get_named_bone_bonechildren (curBone, name);
+ if (rbone)
+ return rbone;
+ }
+
+ return NULL;
+}
+
+void make_displists_by_armature (Object *ob)
+{
+ Base *base;
+
+ if (ob){
+ for (base= G.scene->base.first; base; base= base->next){
+ if ((ob==base->object->parent) && (base->lay & G.scene->lay))
+ if (base->object->partype==PARSKEL )
+ makeDispList(base->object);
+ }
+ }
+}
+
+void get_objectspace_bone_matrix (struct Bone* bone, float M_accumulatedMatrix[][4], int root, int posed)
+/* Gets matrix that transforms the bone to object space */
+/* This function is also used to compute the orientation of the bone for display */
+{
+ Bone *curBone;
+
+ Bone *bonelist[256];
+ int bonecount=0, i;
+
+ Mat4One (M_accumulatedMatrix);
+
+ /* Build a list of bones from tip to root */
+ for (curBone=bone; curBone; curBone=curBone->parent){
+ bonelist[bonecount] = curBone;
+ bonecount++;
+ }
+
+ /* Count through the inverted list (i.e. iterate from root to tip)*/
+ for (i=0; i<bonecount; i++){
+ float T_root[4][4];
+ float T_len[4][4];
+ float R_bmat[4][4];
+ float M_obmat[4][4];
+ float M_boneMatrix[4][4];
+ float delta[3];
+
+ curBone = bonelist[bonecount-i-1];
+
+ /* Get the length translation (length along y axis) */
+ Mat4One (T_len);
+ T_len[3][1] = get_bone_length(curBone);
+
+ if ((curBone == bone) && (root))
+ Mat4One (T_len);
+
+ /* Get the bone's root offset (in the parent's coordinate system) */
+ Mat4One (T_root);
+ VECCOPY (T_root[3], curBone->head);
+
+ /* Compose the restmat */
+ VecSubf(delta, curBone->tail, curBone->head);
+ make_boneMatrixvr(R_bmat, delta, curBone->roll);
+
+
+ /* Retrieve the obmat (user transformation) */
+ if (posed)
+ Mat4CpyMat4 (M_obmat, curBone->obmat);
+ else
+ Mat4One (M_obmat);
+
+ /* Compose the matrix for this bone */
+#if 0
+ Mat4MulSerie (M_boneMatrix, M_accumulatedMatrix, T_root, M_obmat, R_bmat, T_len, NULL, NULL, NULL);
+#else
+ Mat4MulSerie (M_boneMatrix, M_accumulatedMatrix, T_root, R_bmat, M_obmat, T_len, NULL, NULL, NULL);
+#endif
+ Mat4CpyMat4 (M_accumulatedMatrix, M_boneMatrix);
+ }
+
+
+}
+
+void solve_posechain (PoseChain *chain)
+{
+ float goal[3];
+ int i;
+ Bone *curBone;
+ float M_obmat[4][4];
+ float M_basischange[4][4];
+ bPoseChannel *chan;
+
+ if (!chain->solver) return;
+
+ /**
+ * Transform the goal from worldspace
+ * to the coordinate system of the root
+ * of the chain. The matrix for this
+ * was computed when the chain was built
+ * in ik_chain_to_posechain
+ */
+
+ VECCOPY (goal, chain->goal);
+ Mat4MulVecfl (chain->goalinv, goal);
+
+ /* Solve the chain */
+
+ IK_SolveChain(chain->solver,
+ goal,
+ chain->tolerance,
+ chain->iterations,
+ 0.1f,
+ chain->solver->segments);
+
+ /* Copy the results back into the bones */
+ for (i = chain->solver->num_segments-1, curBone=chain->target->parent; i>=0; i--, curBone=curBone->parent){
+
+ /* Retrieve the delta rotation from the solver */
+ Mat4One(M_basischange);
+ Mat4CpyMat3(M_basischange, chain->solver->segments[i].basis_change);
+
+
+ /**
+ * Multiply the bone's usertransform by the
+ * basis change to get the new usertransform
+ */
+
+ Mat4CpyMat4 (M_obmat, curBone->obmat);
+ Mat4MulMat4 (curBone->obmat, M_basischange, M_obmat);
+
+ /* Store the solve results on the childrens' channels */
+ for (chan = chain->pose->chanbase.first; chan; chan=chan->next){
+ if (!strcmp (chan->name, curBone->name)){
+ Mat4CpyMat4 (chan->obmat, curBone->obmat);
+ break;
+ }
+ }
+
+ }
+}
+
+void free_posechain (PoseChain *chain)
+{
+ if (chain->solver) {
+ MEM_freeN (chain->solver->segments);
+ chain->solver->segments = NULL;
+ IK_FreeChain(chain->solver);
+ }
+ MEM_freeN (chain);
+}
+
+PoseChain *ik_chain_to_posechain (Object *ob, Bone *bone)
+{
+ IK_Segment_Extern *segs;
+ PoseChain *chain = NULL;
+ Bone *curBone, *rootBone;
+ int segcount, curseg, icurseg;
+ float imat[4][4];
+ Bone *bonelist[256];
+ float rootmat[4][4];
+ float bonespace[4][4];
+
+ /**
+ * Some interesting variables in this function:
+ *
+ * Bone->obmat Bone's user transformation;
+ * It is initialized in where_is_bone1_time
+ *
+ * rootmat Bone's coordinate system, computed by
+ * get_objectspace_bone_matrix. Takes all
+ * parents transformations into account.
+ */
+
+
+
+ /* Ensure that all of the bone parent matrices are correct */
+
+ /* Find the chain's root & count the segments needed */
+ segcount = 0;
+ for (curBone = bone; curBone; curBone=curBone->parent){
+ rootBone = curBone;
+ if (curBone!=bone){
+ bonelist[segcount]=curBone;
+ segcount++;
+ }
+ if (!curBone->parent)
+ break;
+ else if (!(curBone->flag & BONE_IK_TOPARENT))
+ break;
+ }
+
+ if (!segcount)
+ return NULL;
+
+
+ /**
+ * Initialize a record to store information about the original bones
+ * This will be the return value for this function.
+ */
+
+ chain = MEM_callocN(sizeof(PoseChain), "posechain");
+ chain->solver = IK_CreateChain();
+ chain->target = bone;
+ chain->root = rootBone;
+ chain->pose = ob->pose;
+
+ /* Allocate some IK segments */
+ segs = MEM_callocN (sizeof(IK_Segment_Extern)*segcount, "iksegments");
+
+
+ /**
+ * Remove the offset from the first bone in the chain and take the target to chainspace
+ */
+
+
+ get_objectspace_bone_matrix(rootBone, bonespace, 1, 1);
+ Mat4One (rootmat);
+ VECCOPY (rootmat[3], bonespace[3]);
+
+ /* Take the target to bonespace */
+ Mat4MulMat4 (imat, rootmat, ob->obmat);
+ Mat4Invert (chain->goalinv, imat);
+
+
+ /**
+ * Build matrices from the root to the tip
+ * We count backwards through the bone list (which is sorted tip to root)
+ * and forwards through the ik_segment list
+ */
+
+ for (curseg = segcount-1; curseg>=0; curseg--){
+ float M_basismat[4][4];
+ float R_parmat[4][4];
+ float iR_parmat[4][4];
+ float R_bonemat[4][4];
+
+ /* Retrieve the corresponding bone for this segment */
+ icurseg=segcount-curseg-1;
+ curBone = bonelist[curseg];
+
+ /* Get the basis matrix */
+ Mat4One (R_parmat);
+ get_objectspace_bone_matrix(curBone, R_bonemat, 1, 1);
+ R_bonemat[3][0]=R_bonemat[3][1]=R_bonemat[3][2]=0.0F;
+
+ if (curBone->parent && (curBone->flag & BONE_IK_TOPARENT)){
+ get_objectspace_bone_matrix(curBone->parent, R_parmat, 1, 1);
+ R_parmat[3][0]=R_parmat[3][1]=R_parmat[3][2]=0.0F;
+ }
+
+ Mat4Invert(iR_parmat, R_parmat);
+ Mat4MulMat4(M_basismat, R_bonemat, iR_parmat);
+
+ /* Copy the matrix into the basis and transpose */
+ Mat3CpyMat4(segs[icurseg].basis, M_basismat);
+ Mat3Transp(segs[icurseg].basis);
+
+ /* Fill out the IK segment */
+ segs[icurseg].length = get_bone_length(curBone);
+
+ };
+
+ IK_LoadChain(chain->solver, segs, segcount);
+ return chain;
+}
+
+
+
+void precalc_bonelist_irestmats (ListBase* bonelist)
+{
+ Bone *curbone;
+
+ if (!bonelist)
+ return;
+
+ for (curbone = bonelist->first; curbone; curbone=curbone->next){
+ precalc_bone_irestmat(curbone);
+ precalc_bonelist_irestmats(&curbone->childbase);
+ }
+}
diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c
new file mode 100644
index 00000000000..23927fd793c
--- /dev/null
+++ b/source/blender/blenkernel/intern/blender.c
@@ -0,0 +1,343 @@
+
+/* blender.c jan 94 MIXED MODEL
+ *
+ * algemene hulp funkties en data
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 WIN32
+ #include <unistd.h> // for read close
+ #include <sys/param.h> // for MAXPATHLEN
+#else
+ #include <io.h> // for open close read
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h> // for open
+
+#include "MEM_guardedalloc.h"
+#include "DNA_listBase.h"
+#include "DNA_sdna_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_object_types.h"
+#include "DNA_curve_types.h"
+
+#include "BLI_blenlib.h"
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+#include "DNA_screen_types.h"
+
+#include "BKE_library.h"
+#include "BKE_blender.h"
+#include "BKE_displist.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_object.h"
+#include "BKE_scene.h"
+#include "BKE_effect.h"
+#include "BKE_curve.h"
+#include "BKE_font.h"
+
+#include "BKE_bad_level_calls.h" /* for BPY_do_pyscript */
+
+#include "BLO_readfile.h" /* for BLO_read_file */
+
+#include "BKE_bad_level_calls.h" // for freeAllRad editNurb free_editMesh free_editText free_editArmature
+#include "BKE_utildefines.h" // O_BINARY FALSE
+
+#include "nla.h"
+
+Global G;
+UserDef U;
+
+char versionstr[48]= "";
+
+/* ************************************************ */
+/* pushpop faciliteit: om tijdelijk data te bewaren */
+
+ListBase ppmain={0, 0};
+
+typedef struct PushPop {
+ struct PushPop *next, *prev;
+ void *data;
+ int len;
+} PushPop;
+
+void pushdata(void *data, int len)
+{
+ PushPop *pp;
+
+ pp= MEM_mallocN(sizeof(PushPop), "pushpop");
+ BLI_addtail(&ppmain, pp);
+ pp->data= MEM_mallocN(len, "pushpop");
+ pp->len= len;
+ memcpy(pp->data, data, len);
+}
+
+void popfirst(void *data)
+{
+ PushPop *pp;
+
+ pp= ppmain.first;
+ if(pp) {
+ memcpy(data, pp->data, pp->len);
+ BLI_remlink(&ppmain, pp);
+ MEM_freeN(pp->data);
+ MEM_freeN(pp);
+ }
+ else printf("error in popfirst\n");
+}
+
+void poplast(void *data)
+{
+ PushPop *pp;
+
+ pp= ppmain.last;
+ if(pp) {
+ memcpy(data, pp->data, pp->len);
+ BLI_remlink(&ppmain, pp);
+ MEM_freeN(pp->data);
+ MEM_freeN(pp);
+ }
+ else printf("error in poplast\n");
+}
+
+void free_pushpop()
+{
+ PushPop *pp;
+
+ pp= ppmain.first;
+ while(pp) {
+ BLI_remlink(&ppmain, pp);
+ MEM_freeN(pp->data);
+ MEM_freeN(pp);
+ }
+}
+
+void pushpop_test()
+{
+ if(ppmain.first) printf("pushpop not empty\n");
+ free_pushpop();
+}
+
+
+
+/* ********** vrijgeven ********** */
+
+void free_blender(void)
+{
+ free_main(G.main);
+ G.main= NULL;
+
+ IMB_freeImBufdata(); /* imbuf lib */
+}
+
+void duplicatelist(ListBase *list1, ListBase *list2) /* kopie van 2 naar 1 */
+{
+ struct Link *link1, *link2;
+
+ list1->first= list1->last= 0;
+
+ link2= list2->first;
+ while(link2) {
+
+ link1= MEM_dupallocN(link2);
+ BLI_addtail(list1, link1);
+
+ link2= link2->next;
+ }
+}
+
+void initglobals(void)
+{
+ memset(&G, 0, sizeof(Global));
+
+ U.savetime= 1;
+
+ G.animspeed= 4;
+
+ G.main= MEM_callocN(sizeof(Main), "initglobals");
+
+ strcpy(G.ima, "//");
+
+ G.version= BLENDER_VERSION;
+
+ G.order= 1;
+ G.order= (((char*)&G.order)[0])?L_ENDIAN:B_ENDIAN;
+
+ sprintf(versionstr, "www.blender.nl %d", G.version);
+
+ clear_workob(); /* object.c */
+}
+
+/***/
+
+static void clear_global(void) {
+ extern short winqueue_break; /* screen.c */
+
+ freeAllRad();
+ free_main(G.main); /* free all lib data */
+ freefastshade(); /* anders oude lampgegevens */
+
+
+ /* hangende vars voorkomen */
+ R.backbuf= 0;
+
+ /* force all queues to be left */
+ winqueue_break= 1;
+
+ if (G.obedit) {
+ freeNurblist(&editNurb);
+ free_editMesh();
+ free_editText();
+ free_editArmature();
+ }
+
+ G.curscreen= NULL;
+ G.scene= NULL;
+ G.main= NULL;
+
+ G.obedit= NULL;
+ G.obpose= NULL;
+ G.saction= NULL;
+ G.buts= NULL;
+ G.v2d= NULL;
+ G.vd= NULL;
+ G.soops= NULL;
+ G.sima= NULL;
+ G.sipo= NULL;
+
+ G.f &= ~(G_WEIGHTPAINT + G_VERTEXPAINT + G_FACESELECT);
+}
+
+static void setup_app_data(BlendFileData *bfd, char *filename) {
+ Object *ob;
+
+ clear_global();
+
+ G.save_over = 1;
+
+ G.main= bfd->main;
+ if (bfd->user) {
+ U= *bfd->user;
+ MEM_freeN(bfd->user);
+ }
+
+ R.winpos= bfd->winpos;
+ R.displaymode= bfd->displaymode;
+ G.curscreen= bfd->curscreen;
+ G.fileflags= bfd->fileflags;
+
+ G.scene= G.curscreen->scene;
+
+ /* weinig DispListen, wel text_to_curve */
+ // this should be removed!!! But first a better displist system (ton)
+ for (ob= G.main->object.first; ob; ob= ob->id.next) {
+ if(ob->type==OB_FONT) {
+ Curve *cu= ob->data;
+ if(cu->nurb.first==0) text_to_curve(ob, 0);
+ }
+ else if(ob->type==OB_MESH) {
+ makeDispList(ob);
+ if(ob->effect.first) object_wave(ob);
+ }
+ }
+
+ if (!G.background) {
+ setscreen(G.curscreen);
+ }
+ /* baseflags */
+ set_scene_bg(G.scene);
+
+ if (G.f & G_SCENESCRIPT) {
+ BPY_do_pyscript(&G.scene->id, SCRIPT_ONLOAD);
+ }
+
+ strcpy(G.sce, filename);
+ strcpy(G.main->name, filename); /* is gegarandeerd current file */
+
+ MEM_freeN(bfd);
+}
+
+int BKE_read_file(char *dir, void *type_r) {
+ BlendReadError bre;
+ BlendFileData *bfd;
+
+ if (!G.background)
+ waitcursor(1);
+
+ bfd= BLO_read_from_file(dir, &bre);
+ if (bfd) {
+ if (type_r)
+ *((BlenFileType*)type_r)= bfd->type;
+
+ setup_app_data(bfd, dir);
+ } else {
+ error("Loading %s failed: %s", dir, BLO_bre_as_string(bre));
+ }
+
+ if (!G.background)
+ waitcursor(0);
+
+ return (bfd?1:0);
+}
+
+int BKE_read_file_from_memory(char* filebuf, int filelength, void *type_r)
+{
+ BlendReadError bre;
+ BlendFileData *bfd;
+
+ if (!G.background)
+ waitcursor(1);
+
+ bfd= BLO_read_from_memory(filebuf, filelength, &bre);
+ if (bfd) {
+ if (type_r)
+ *((BlenFileType*)type_r)= bfd->type;
+
+ setup_app_data(bfd, "<memory>");
+ } else {
+ error("Loading failed: %s", BLO_bre_as_string(bre));
+ }
+
+ if (!G.background)
+ waitcursor(0);
+
+ return (bfd?1:0);
+}
diff --git a/source/blender/blenkernel/intern/bmfont.c b/source/blender/blenkernel/intern/bmfont.c
new file mode 100644
index 00000000000..c5c4221a076
--- /dev/null
+++ b/source/blender/blenkernel/intern/bmfont.c
@@ -0,0 +1,293 @@
+/**
+ * bmfont.c
+ *
+ * 04-10-2000 frank
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ *
+ */
+
+/**
+ * Two external functions:
+ *
+ * void detectBitmapFont(ImBuf *ibuf)
+ * detects if an image buffer contains a bitmap font. It makes the
+ * specific bitmap data which is stored in the bitmap invisible to blender.
+ *
+ * void matrixGlyph(ImBuf * ibuf, unsigned short unicode, *float x 7)
+ * returns all the information about the character (unicode) in the floats
+ *
+ * Room for improvement:
+ * add kerning data in the bitmap
+ * all calculations in matrixGlyph() are static and could be done during
+ * initialization
+ */
+
+#include <stdio.h>
+
+#include "MEM_guardedalloc.h"
+#include "BLI_blenlib.h"
+#include "BKE_global.h"
+#include "IMB_imbuf_types.h"
+
+#include "BKE_bmfont.h"
+#include "BKE_bmfont_types.h"
+
+void printfGlyph(bmGlyph * glyph)
+{
+ printf("unicode: %d '%c'\n", glyph->unicode, glyph->unicode);
+ printf(" locx: %4d locy: %4d\n", glyph->locx, glyph->locy);
+ printf(" sizex: %3d sizey: %3d\n", glyph->sizex, glyph->sizey);
+ printf(" ofsx: %3d ofsy: %3d\n", glyph->ofsx, glyph->ofsy);
+ printf(" advan: %3d reser: %3d\n", glyph->advance, glyph->reserved);
+}
+
+#define MAX2(x,y) ( (x)>(y) ? (x) : (y) )
+#define MAX3(x,y,z) MAX2( MAX2((x),(y)) , (z) )
+
+void calcAlpha(ImBuf * ibuf)
+{
+ int i;
+ char * rect;
+
+ if (ibuf) {
+ rect = (char *) ibuf->rect;
+ for (i = ibuf->x * ibuf->y ; i > 0 ; i--) {
+ rect[3] = MAX3(rect[0], rect[1], rect[2]);
+ rect += 4;
+ }
+ }
+}
+
+void readBitmapFontVersion0(ImBuf * ibuf, unsigned char * rect, int step)
+{
+ int glyphcount, bytes, i, index, linelength, ysize;
+ unsigned char * buffer;
+ bmFont * bmfont;
+
+ linelength = ibuf->x * step;
+
+ glyphcount = (rect[6 * step] << 8) | rect[7 * step];
+ bytes = ((glyphcount - 1) * sizeof(bmGlyph)) + sizeof(bmFont);
+
+ ysize = (bytes + (ibuf->x - 1)) / ibuf->x;
+
+ if (ysize < ibuf->y) {
+ // we're first going to copy all data into a liniar buffer.
+ // step can be 4 or 1 bytes, and the data is not sequential because
+ // the bitmap was flipped vertically.
+
+ buffer = MEM_mallocN(bytes, "readBitmapFontVersion0:buffer");
+
+ index = 0;
+ for (i = 0; i < bytes; i++) {
+ buffer[i] = rect[index];
+ index += step;
+ if (index >= linelength) {
+ // we've read one line, no skip to the line *before* that
+ rect -= linelength;
+ index -= linelength;
+ }
+ }
+
+ // we're now going to endian convert the data
+
+ bmfont = MEM_mallocN(bytes, "readBitmapFontVersion0:bmfont");
+ index = 0;
+
+ // first read the header
+ bmfont->magic[0] = buffer[index++];
+ bmfont->magic[1] = buffer[index++];
+ bmfont->magic[2] = buffer[index++];
+ bmfont->magic[3] = buffer[index++];
+ bmfont->version = (buffer[index] << 8) | buffer[index + 1]; index += 2;
+ bmfont->glyphcount = (buffer[index] << 8) | buffer[index + 1]; index += 2;
+ bmfont->xsize = (buffer[index] << 8) | buffer[index + 1]; index += 2;
+ bmfont->ysize = (buffer[index] << 8) | buffer[index + 1]; index += 2;
+
+ for (i = 0; i < bmfont->glyphcount; i++) {
+ bmfont->glyphs[i].unicode = (buffer[index] << 8) | buffer[index + 1]; index += 2;
+ bmfont->glyphs[i].locx = (buffer[index] << 8) | buffer[index + 1]; index += 2;
+ bmfont->glyphs[i].locy = (buffer[index] << 8) | buffer[index + 1]; index += 2;
+ bmfont->glyphs[i].ofsx = buffer[index++];
+ bmfont->glyphs[i].ofsy = buffer[index++];
+ bmfont->glyphs[i].sizex = buffer[index++];
+ bmfont->glyphs[i].sizey = buffer[index++];
+ bmfont->glyphs[i].advance = buffer[index++];
+ bmfont->glyphs[i].reserved = buffer[index++];
+ if (G.f & G_DEBUG) {
+ printfGlyph(&bmfont->glyphs[i]);
+ }
+ }
+
+ MEM_freeN(buffer);
+
+ if (G.f & G_DEBUG) {
+ printf("Oldy = %d Newy = %d\n", ibuf->y, ibuf->y - ysize);
+ printf("glyphcount = %d\n", glyphcount);
+ printf("bytes = %d\n", bytes);
+ }
+
+ // we've read the data from the image. Now we're going
+ // to crop the image vertically so only the bitmap data
+ // remains visible
+
+ ibuf->y -= ysize;
+ ibuf->userdata = bmfont;
+ ibuf->userflags |= IB_BITMAPFONT;
+
+ if (ibuf->depth < 32) {
+ // we're going to fake alpha here:
+ calcAlpha(ibuf);
+ }
+ } else {
+ printf("readBitmapFontVersion0: corrupted bitmapfont\n");
+ }
+}
+
+void detectBitmapFont(ImBuf *ibuf)
+{
+ unsigned char * rect;
+ unsigned short version;
+ long i;
+
+ if (ibuf != NULL) {
+ // bitmap must have an x size that is a power of two
+ if (is_power_of_two(ibuf->x)) {
+ rect = (unsigned char *) (ibuf->rect + (ibuf->x * (ibuf->y - 1)));
+ // printf ("starts with: %s %c %c %c %c\n", rect, rect[0], rect[1], rect[2], rect[3]);
+ if (rect[0] == 'B' && rect[1] == 'F' && rect[2] == 'N' && rect[3] == 'T') {
+ // printf("found 8bit font !\n");
+ // round y size down
+ // do the 8 bit font stuff. (not yet)
+ } else {
+ // we try all 4 possible combinations
+ for (i = 0; i < 4; i++) {
+ if (rect[0] == 'B' && rect[4] == 'F' && rect[8] == 'N' && rect[12] == 'T') {
+ // printf("found 24bit font !\n");
+ // We're going to parse the file:
+
+ version = (rect[16] << 8) | rect[20];
+
+ if (version == 0) {
+ readBitmapFontVersion0(ibuf, rect, 4);
+ } else {
+ printf("detectBitmapFont :Unsupported version %d\n", version);
+ }
+
+ // on succes ibuf->userdata points to the bitmapfont
+ if (ibuf->userdata) {
+ break;
+ }
+ }
+ rect++;
+ }
+ }
+ }
+ }
+}
+
+int locateGlyph(bmFont *bmfont, unsigned short unicode)
+{
+ int min, max, current = 0;
+
+ if (bmfont) {
+ min = 0;
+ max = bmfont->glyphcount;
+ while (1) {
+ // look halfway for glyph
+ current = (min + max) >> 1;
+
+ if (bmfont->glyphs[current].unicode == unicode) {
+ break;
+ } else if (bmfont->glyphs[current].unicode < unicode) {
+ // have to move up
+ min = current;
+ } else {
+ // have to move down
+ max = current;
+ }
+
+ if (max - min <= 1) {
+ // unable to locate glyph
+ current = 0;
+ break;
+ }
+ }
+ }
+
+ return(current);
+}
+
+void matrixGlyph(ImBuf * ibuf, unsigned short unicode,
+ float *centerx, float *centery,
+ float *sizex, float *sizey,
+ float *transx, float *transy,
+ float *movex, float *movey,
+ float *advance)
+{
+ int index;
+ bmFont *bmfont;
+
+ *centerx = *centery = 0.0;
+ *sizex = *sizey = 1.0;
+ *transx = *transy = 0.0;
+ *movex = *movey = 0.0;
+ *advance = 1.0;
+
+ if (ibuf) {
+ bmfont = ibuf->userdata;
+ if (bmfont && (ibuf->userflags & IB_BITMAPFONT)) {
+ index = locateGlyph(bmfont, unicode);
+ if (index) {
+
+ *sizex = (bmfont->glyphs[index].sizex) / (float) (bmfont->glyphs[0].sizex);
+ *sizey = (bmfont->glyphs[index].sizey) / (float) (bmfont->glyphs[0].sizey);
+
+ *transx = bmfont->glyphs[index].locx / (float) ibuf->x;
+ *transy = (ibuf->y - bmfont->glyphs[index].locy) / (float) ibuf->y;
+
+ *centerx = bmfont->glyphs[0].locx / (float) ibuf->x;
+ *centery = (ibuf->y - bmfont->glyphs[0].locy) / (float) ibuf->y;
+
+ // 2.0 units is the default size of an object
+
+ *movey = 1.0f - *sizey + 2.0f * (bmfont->glyphs[index].ofsy - bmfont->glyphs[0].ofsy) / (float) bmfont->glyphs[0].sizey;
+ *movex = *sizex - 1.0f + 2.0f * (bmfont->glyphs[index].ofsx - bmfont->glyphs[0].ofsx) / (float) bmfont->glyphs[0].sizex;
+
+ *advance = 2.0f * bmfont->glyphs[index].advance / (float) bmfont->glyphs[0].advance;
+
+ // printfGlyph(&bmfont->glyphs[index]);
+ // printf("%c %d %0.5f %0.5f %0.5f %0.5f %0.5f \n", unicode, index, *sizex, *sizey, *transx, *transy, *advance);
+ }
+ }
+ }
+}
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
new file mode 100644
index 00000000000..9c1a4607dca
--- /dev/null
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -0,0 +1,732 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 <string.h>
+
+#include "MEM_guardedalloc.h"
+#include "nla.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_constraint_types.h"
+#include "DNA_object_types.h"
+#include "DNA_action_types.h"
+#include "DNA_curve_types.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_action.h"
+#include "BKE_armature.h"
+#include "BKE_blender.h"
+#include "BKE_constraint.h"
+#include "BKE_object.h"
+#include "BKE_ipo.h"
+#include "BKE_global.h"
+#include "BKE_library.h"
+
+#include "blendef.h"
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+/* Local function prototypes */
+static void constraint_target_to_mat4 (Object *ob, const char *substring, float mat[][4], float size[3], float ctime);
+
+/* Functions */
+
+bConstraintChannel *find_constraint_channel (ListBase *list, const char *name){
+ bConstraintChannel *chan;
+
+ for (chan = list->first; chan; chan=chan->next){
+ if (!strcmp(name, chan->name)){
+ return chan;
+ }
+ }
+ return NULL;
+}
+
+void do_constraint_channels (ListBase *conbase, ListBase *chanbase, float ctime)
+{
+ bConstraint *con;
+ bConstraintChannel *chan;
+ IpoCurve *icu;
+
+ for (con=conbase->first; con; con=con->next){
+ chan = find_constraint_channel(chanbase, con->name);
+ if (chan && chan->ipo){
+ calc_ipo(chan->ipo, ctime);
+ for (icu=chan->ipo->curve.first; icu; icu=icu->next){
+ switch (icu->adrcode){
+ case CO_ENFORCE:
+ con->enforce = icu->curval;
+ if (con->enforce<0) con->enforce=0;
+ else if (con->enforce>1) con->enforce=1;
+ break;
+ }
+ }
+ }
+ }
+}
+
+void Mat4BlendMat4(float out[][4], float dst[][4], float src[][4], float srcweight)
+{
+ float squat[4], dquat[4], fquat[4];
+ float ssize[3], dsize[3], fsize[4];
+ float sloc[3], dloc[3], floc[3];
+ float mat3[3][3], dstweight;
+ float qmat[3][3], smat[3][3];
+ int i;
+
+
+ dstweight = 1.0F-srcweight;
+
+ Mat3CpyMat4(mat3, dst);
+ Mat3ToQuat(mat3, dquat);
+ Mat3ToSize(mat3, dsize);
+ VECCOPY (dloc, dst[3]);
+
+ Mat3CpyMat4(mat3, src);
+ Mat3ToQuat(mat3, squat);
+ Mat3ToSize(mat3, ssize);
+ VECCOPY (sloc, src[3]);
+
+ /* Do the actual blend */
+ for (i=0; i<3; i++){
+ floc[i] = (dloc[i]*dstweight) + (sloc[i]*srcweight);
+ fsize[i] = 1.0f + ((dsize[i]-1.0f)*dstweight) + ((ssize[i]-1.0f)*srcweight);
+ fquat[i+1] = (dquat[i+1]*dstweight) + (squat[i+1]*srcweight);
+ }
+
+ /* Do one more iteration for the quaternions only and normalize the quaternion if needed */
+ fquat[0] = 1.0f + ((dquat[0]-1.0f)*dstweight) + ((squat[0]-1.0f)*srcweight);
+ NormalQuat (fquat);
+
+ QuatToMat3(fquat, qmat);
+ SizeToMat3(fsize, smat);
+
+ Mat3MulMat3(mat3, qmat, smat);
+ Mat4CpyMat3(out, mat3);
+ VECCOPY (out[3], floc);
+}
+
+static void constraint_target_to_mat4 (Object *ob, const char *substring, float mat[][4], float size[3], float ctime)
+{
+
+ /* Update the location of the target object */
+ where_is_object_time (ob, ctime);
+
+ /* Case OBJECT */
+ if (!strlen(substring)){
+ Mat4CpyMat4 (mat, ob->obmat);
+ VECCOPY (size, ob->size);
+ return;
+ }
+
+ /* Case BONE */
+ else {
+ bArmature *arm;
+ Bone *bone;
+ float bmat[4][4];
+ float bsize[3]={1, 1, 1};
+
+ arm = get_armature(ob);
+
+ /**
+ * Locate the bone (if there is one)
+ * Ensures that the bone's transformation is fully constrained
+ * (Cyclical relationships are disallowed elsewhere)
+ */
+ bone = get_named_bone(arm, substring);
+ if (bone){
+ where_is_bone_time(ob, bone, ctime);
+ get_objectspace_bone_matrix(bone, bmat, 1, 1);
+ VECCOPY(bsize, bone->size);
+ }
+ else
+ Mat4One (bmat);
+
+ /**
+ * Multiply the objectspace bonematrix by the skeletons's global
+ * transform to obtain the worldspace transformation of the target
+ */
+ VECCOPY(size, bsize);
+ Mat4MulMat4 (mat, bmat, ob->obmat);
+
+ return;
+ }
+}
+
+void clear_object_constraint_status (Object *ob)
+{
+ bConstraint *con;
+
+ if (!ob) return;
+
+ /* Clear the object's constraints */
+ for (con = ob->constraints.first; con; con=con->next){
+ con->flag &= ~CONSTRAINT_DONE;
+ }
+
+ /* Clear the object's subdata constraints */
+ switch (ob->type){
+ case OB_ARMATURE:
+ {
+ clear_pose_constraint_status (ob);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+short get_constraint_target (bConstraint *con, short ownertype, void* ownerdata, float mat[][4], float size[3], float ctime)
+{
+ short valid=0;
+
+ switch (con->type){
+ case CONSTRAINT_TYPE_NULL:
+ {
+ Mat4One(mat);
+ }
+ break;
+ case CONSTRAINT_TYPE_ACTION:
+ {
+ if (ownertype == TARGET_BONE){
+ bActionConstraint *data = (bActionConstraint*)con->data;
+ bPose *pose=NULL;
+ bPoseChannel *pchan=NULL;
+ float tempmat[4][4], imat[4][4], ans[4][4], restmat[4][4], irestmat[4][4];
+ float tempmat3[3][3];
+ float eul[3], size[3];
+ float s,t;
+ Bone *curBone;
+ Bone tbone;
+ int i;
+
+ curBone = (Bone*)ownerdata;
+
+ if (data->tar){
+ constraint_target_to_mat4(data->tar, data->subtarget, tempmat, size, ctime);
+ valid=1;
+ }
+ else
+ Mat4One (tempmat);
+
+ /* If this is a bone, undo parent transforms */
+ if (strlen(data->subtarget)){
+ Bone* bone;
+
+ Mat4Invert(imat, data->tar->obmat);
+ bone = get_named_bone(get_armature(data->tar), data->subtarget);
+ if (bone){
+ get_objectspace_bone_matrix(bone, restmat, 1, 0);
+ Mat4Invert(irestmat, restmat);
+ }
+ }
+ else{
+ Mat4One(imat);
+ Mat4One(irestmat);
+ }
+
+ Mat4MulSerie(ans, imat, tempmat, irestmat, NULL, NULL, NULL, NULL, NULL);
+
+ Mat3CpyMat4(tempmat3, ans);
+ Mat3ToEul(tempmat3, eul);
+
+ eul[0]*=(float)(180.0/M_PI);
+ eul[1]*=(float)(180.0/M_PI);
+ eul[2]*=(float)(180.0/M_PI);
+
+ /* Target is the animation */
+ s = (eul[data->type]-data->min)/(data->max-data->min);
+ if (s<0)
+ s=0;
+ if (s>1)
+ s=1;
+
+ t = ( s * (data->end-data->start)) + data->start;
+
+ /* Get the appropriate information from the action */
+ pose = MEM_callocN(sizeof(bPose), "pose");
+
+ verify_pose_channel(pose, curBone->name);
+ get_pose_from_action (&pose, data->act, t);
+
+ /* Find the appropriate channel */
+ pchan = get_pose_channel(pose, curBone->name);
+ if (pchan){
+ memset(&tbone, 0x00, sizeof(Bone));
+
+ VECCOPY (tbone.loc, pchan->loc);
+ VECCOPY (tbone.size, pchan->size);
+ for (i=0; i<4; i++)
+ tbone.quat[i]=pchan->quat[i];
+
+ bone_to_mat4(&tbone, mat);
+
+ }
+ else{
+ Mat4One(mat);
+ }
+ /* Clean up */
+ clear_pose(pose);
+ MEM_freeN(pose);
+ }
+
+ }
+ break;
+ case CONSTRAINT_TYPE_LOCLIKE:
+ {
+ bLocateLikeConstraint *data = (bLocateLikeConstraint*)con->data;
+
+ if (data->tar){
+ constraint_target_to_mat4(data->tar, data->subtarget, mat, size, ctime);
+ valid=1;
+ }
+ else
+ Mat4One (mat);
+ }
+ break;
+ case CONSTRAINT_TYPE_ROTLIKE:
+ {
+ bRotateLikeConstraint *data;
+ data = (bRotateLikeConstraint*)con->data;
+
+ if (data->tar){
+ constraint_target_to_mat4(data->tar, data->subtarget, mat, size, ctime);
+ valid=1;
+ }
+ else
+ Mat4One (mat);
+ }
+ break;
+ case CONSTRAINT_TYPE_TRACKTO:
+ {
+ bTrackToConstraint *data;
+ data = (bTrackToConstraint*)con->data;
+
+ if (data->tar){
+ constraint_target_to_mat4(data->tar, data->subtarget, mat, size, ctime);
+ valid=1;
+ }
+ else
+ Mat4One (mat);
+ }
+ break;
+ case CONSTRAINT_TYPE_KINEMATIC:
+ {
+ bTrackToConstraint *data;
+ data = (bTrackToConstraint*)con->data;
+
+ if (data->tar){
+ constraint_target_to_mat4(data->tar, data->subtarget, mat, size, ctime);
+ valid=1;
+ }
+ else
+ Mat4One (mat);
+ }
+ break;
+ default:
+ Mat4One(mat);
+ break;
+ }
+
+ return valid;
+}
+
+void relink_constraints (struct ListBase *list)
+{
+ bConstraint *con;
+
+ for (con = list->first; con; con=con->next){
+ switch (con->type){
+ case CONSTRAINT_TYPE_KINEMATIC:
+ {
+ bKinematicConstraint *data;
+ data = con->data;
+
+ ID_NEW(data->tar);
+ }
+ break;
+ case CONSTRAINT_TYPE_NULL:
+ {
+ }
+ break;
+ case CONSTRAINT_TYPE_TRACKTO:
+ {
+ bTrackToConstraint *data;
+ data = con->data;
+
+ ID_NEW(data->tar);
+ }
+ break;
+ case CONSTRAINT_TYPE_ACTION:
+ {
+ bActionConstraint *data;
+ data = con->data;
+
+ ID_NEW(data->tar);
+ }
+ break;
+ case CONSTRAINT_TYPE_LOCLIKE:
+ {
+ bLocateLikeConstraint *data;
+ data = con->data;
+
+ ID_NEW(data->tar);
+ }
+ break;
+ case CONSTRAINT_TYPE_ROTLIKE:
+ {
+ bRotateLikeConstraint *data;
+ data = con->data;
+
+ ID_NEW(data->tar);
+ }
+ break;
+ }
+ }
+}
+
+void *copy_constraint_channels (ListBase *dst, ListBase *src)
+{
+ bConstraintChannel *dchan, *schan;
+ bConstraintChannel *newact=NULL;
+
+ dst->first=dst->last=NULL;
+ duplicatelist(dst, src);
+
+ for (dchan=dst->first, schan=src->first; dchan; dchan=dchan->next, schan=schan->next){
+ dchan->ipo = copy_ipo(schan->ipo);
+ }
+
+ return newact;
+}
+
+bConstraintChannel *clone_constraint_channels (ListBase *dst, ListBase *src, bConstraintChannel *oldact)
+{
+ bConstraintChannel *dchan, *schan;
+ bConstraintChannel *newact=NULL;
+
+ dst->first=dst->last=NULL;
+ duplicatelist(dst, src);
+
+ for (dchan=dst->first, schan=src->first; dchan; dchan=dchan->next, schan=schan->next){
+ id_us_plus((ID *)dchan->ipo);
+ if (schan==oldact)
+ newact=dchan;
+ }
+
+ return newact;
+}
+
+void copy_constraints (ListBase *dst, ListBase *src)
+{
+ bConstraint *con;
+
+ dst->first=dst->last=NULL;
+
+ duplicatelist (dst, src);
+
+ /* Update specific data */
+ if (!dst->first)
+ return;
+
+ for (con = dst->first; con; con=con->next){
+ switch (con->type){
+ case CONSTRAINT_TYPE_ACTION:
+ {
+ bActionConstraint *data;
+
+ con->data = MEM_dupallocN (con->data);
+ data = (bActionConstraint*) con->data;
+ }
+ break;
+ case CONSTRAINT_TYPE_LOCLIKE:
+ {
+ bLocateLikeConstraint *data;
+
+ con->data = MEM_dupallocN (con->data);
+ data = (bLocateLikeConstraint*) con->data;
+ }
+ break;
+ case CONSTRAINT_TYPE_ROTLIKE:
+ {
+ bRotateLikeConstraint *data;
+
+ con->data = MEM_dupallocN (con->data);
+ data = (bRotateLikeConstraint*) con->data;
+ }
+ break;
+ case CONSTRAINT_TYPE_NULL:
+ {
+ con->data = NULL;
+ }
+ break;
+ case CONSTRAINT_TYPE_TRACKTO:
+ {
+ bTrackToConstraint *data;
+
+ con->data = MEM_dupallocN (con->data);
+ data = (bTrackToConstraint*) con->data;
+ }
+ break;
+ case CONSTRAINT_TYPE_KINEMATIC:
+ {
+ bKinematicConstraint *data;
+
+ con->data = MEM_dupallocN (con->data);
+ data = (bKinematicConstraint*) con->data;
+ }
+ break;
+ default:
+ con->data = MEM_dupallocN (con->data);
+ break;
+ }
+ }
+}
+
+void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype, void *ownerdata, float targetmat[][4])
+/* ob is likely to be a workob */
+{
+ float M_oldmat[4][4];
+ float M_identity[4][4];
+ float enforce = 1.0;
+
+ if (!constraint || !ob)
+ return;
+
+ Mat4One (M_identity);
+
+ /* We've already been calculated */
+ if (constraint->flag & CONSTRAINT_DONE){
+ return;
+ }
+
+ switch (constraint->type){
+ case CONSTRAINT_TYPE_ACTION:
+ {
+ float temp[4][4];
+ bActionConstraint *data;
+
+ data = constraint->data;
+ Mat4CpyMat4 (temp, ob->obmat);
+
+ Mat4MulMat4(ob->obmat, targetmat, temp);
+ }
+ break;
+ case CONSTRAINT_TYPE_LOCLIKE:
+ {
+ bLocateLikeConstraint *data;
+
+ data = constraint->data;
+
+ if (data->flag & LOCLIKE_X)
+ ob->obmat[3][0] = targetmat[3][0];
+ if (data->flag & LOCLIKE_Y)
+ ob->obmat[3][1] = targetmat[3][1];
+ if (data->flag & LOCLIKE_Z)
+ ob->obmat[3][2] = targetmat[3][2];
+ }
+ break;
+ case CONSTRAINT_TYPE_ROTLIKE:
+ {
+ float tmat[4][4];
+ float size[3];
+
+ Mat4ToSize(ob->obmat, size);
+
+ Mat4CpyMat4 (tmat, targetmat);
+ Mat4Ortho(tmat);
+
+ ob->obmat[0][0] = tmat[0][0]*size[0];
+ ob->obmat[0][1] = tmat[0][1]*size[1];
+ ob->obmat[0][2] = tmat[0][2]*size[2];
+
+ ob->obmat[1][0] = tmat[1][0]*size[0];
+ ob->obmat[1][1] = tmat[1][1]*size[1];
+ ob->obmat[1][2] = tmat[1][2]*size[2];
+
+ ob->obmat[2][0] = tmat[2][0]*size[0];
+ ob->obmat[2][1] = tmat[2][1]*size[1];
+ ob->obmat[2][2] = tmat[2][2]*size[2];
+ }
+ break;
+ case CONSTRAINT_TYPE_NULL:
+ {
+ }
+ break;
+ case CONSTRAINT_TYPE_TRACKTO:
+ {
+ bTrackToConstraint *data;
+ float size[3];
+
+ data=(bTrackToConstraint*)constraint->data;
+
+ if (data->tar){
+
+ Mat4ToSize (ob->obmat, size);
+
+ Mat4CpyMat4 (M_oldmat, ob->obmat);
+
+ // Clear the object's rotation
+ ob->obmat[0][0]=ob->size[0];
+ ob->obmat[0][1]=0;
+ ob->obmat[0][2]=0;
+ ob->obmat[1][0]=0;
+ ob->obmat[1][1]=ob->size[1];
+ ob->obmat[1][2]=0;
+ ob->obmat[2][0]=0;
+ ob->obmat[2][1]=0;
+ ob->obmat[2][2]=ob->size[2];
+
+ solve_tracking(ob, targetmat);
+ }
+ }
+ break;
+ case CONSTRAINT_TYPE_KINEMATIC:
+ {
+ bKinematicConstraint *data;
+ float imat[4][4];
+ float temp[4][4];
+ float totmat[4][4];
+
+ data=(bKinematicConstraint*)constraint->data;
+
+ if (data->tar && ownertype==TARGET_BONE && ownerdata){
+ Bone *curBone = (Bone*)ownerdata;
+ PoseChain *chain;
+ Object *armob;
+
+ /* Retrieve the owner armature object from the workob */
+ armob = ob->parent;
+
+ /* Make an IK chain */
+ chain = ik_chain_to_posechain(armob, curBone);
+ if (!chain)
+ return;
+ chain->iterations = data->iterations;
+ chain->tolerance = data->tolerance;
+
+
+ {
+ float parmat[4][4];
+
+ /* Take the obmat to objectspace */
+ Mat4CpyMat4 (temp, curBone->obmat);
+ Mat4One (curBone->obmat);
+ get_objectspace_bone_matrix(curBone, parmat, 1, 1);
+ Mat4CpyMat4 (curBone->obmat, temp);
+ Mat4MulMat4 (totmat, parmat, ob->parent->obmat);
+
+ Mat4Invert (imat, totmat);
+
+ Mat4CpyMat4 (temp, ob->obmat);
+ Mat4MulMat4 (ob->obmat, temp, imat);
+ }
+
+
+ /* Solve it */
+ if (chain->solver){
+ VECCOPY (chain->goal, targetmat[3]);
+ solve_posechain(chain);
+ }
+
+ free_posechain(chain);
+
+ {
+ float parmat[4][4];
+
+ /* Take the obmat to worldspace */
+ Mat4CpyMat4 (temp, curBone->obmat);
+ Mat4One (curBone->obmat);
+ get_objectspace_bone_matrix(curBone, parmat, 1, 1);
+ Mat4CpyMat4 (curBone->obmat, temp);
+ Mat4MulMat4 (totmat, parmat, ob->parent->obmat);
+
+ Mat4CpyMat4 (temp, ob->obmat);
+ Mat4MulMat4 (ob->obmat, temp, totmat);
+
+ }
+ }
+ }
+ break;
+ case CONSTRAINT_TYPE_FOLLOWPATH:
+ break;
+ default:
+ printf ("Error: Unknown constraint type\n");
+ break;
+ }
+
+}
+
+void free_constraint_data (bConstraint *con)
+{
+ if (con->data){
+ switch (con->type){
+ default:
+ break;
+ };
+
+ MEM_freeN (con->data);
+ }
+}
+
+void free_constraints (ListBase *conlist)
+{
+ bConstraint *con;
+
+ /* Do any specific freeing */
+ for (con=conlist->first; con; con=con->next)
+ {
+ free_constraint_data (con);
+ };
+
+ /* Free the whole list */
+ BLI_freelistN(conlist);
+}
+
+void free_constraint_channels (ListBase *chanbase)
+{
+ bConstraintChannel *chan;
+
+ for (chan=chanbase->first; chan; chan=chan->next)
+ {
+ if (chan->ipo){
+ chan->ipo->id.us--;
+ }
+ }
+
+ BLI_freelistN(chanbase);
+} \ No newline at end of file
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c
new file mode 100644
index 00000000000..1f0c838e816
--- /dev/null
+++ b/source/blender/blenkernel/intern/curve.c
@@ -0,0 +1,2344 @@
+
+/* curve.c MIXED MODEL
+ *
+ * maart 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 *****
+ */
+
+#define STRUBI hack
+
+#include <math.h> // floor
+#include <string.h>
+#include <stdlib.h>
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+#include "MEM_guardedalloc.h"
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "DNA_object_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_material_types.h"
+#include "DNA_mesh_types.h"
+
+/* for dereferencing pointers */
+#include "DNA_ID.h"
+#include "DNA_vfont_types.h"
+#include "DNA_key_types.h"
+#include "DNA_ipo_types.h"
+
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_utildefines.h" // VECCOPY
+#include "BKE_object.h"
+#include "BKE_mesh.h"
+#include "BKE_curve.h"
+#include "BKE_displist.h"
+#include "BKE_ipo.h"
+#include "BKE_anim.h"
+#include "BKE_library.h"
+#include "BKE_key.h"
+
+
+/* globals */
+
+extern ListBase editNurb; /* editcurve.c */
+
+/* local */
+int cu_isectLL(float *v1, float *v2, float *v3, float *v4,
+ short cox, short coy,
+ float *labda, float *mu, float *vec);
+
+
+#ifdef STRUBI
+/* hotfix; copies x*y array into extended (x+dx)*(y+dy) array
+old[] and new[] can be the same ! */
+int copyintoExtendedArray(float *old, int oldx, int oldy, float *new, int newx, int newy)
+{
+ int x, y;
+ float *oldp, *newp;
+ if (newx < oldx || newy < oldy) return 0;
+
+
+ for (y = newy - 1; y >= oldy; y--) {
+ for (x = newx - 1; x >= 0; x--) {
+ newp = new + 3 * (y * newx + x);
+ newp[0] = 0.0; newp[1] = 0.0; newp[2] = 0.0;
+ }
+ }
+
+ for (; y >= 0; y--) {
+
+ for (x = newx - 1; x >= oldx; x--) {
+ newp = new + 3 * (y * newx + x);
+ newp[0] = 0.0; newp[1] = 0.0; newp[2] = 0.0;
+ }
+ for (; x >= 0; x--) {
+ oldp = old + 3 * (y * oldx + x);
+ newp = new + 3 * (y * newx + x);
+ VECCOPY(newp, oldp);
+ }
+ }
+ return 1;
+}
+#endif
+
+void unlink_curve(Curve *cu)
+{
+ int a;
+
+ for(a=0; a<cu->totcol; a++) {
+ if(cu->mat[a]) cu->mat[a]->id.us--;
+ cu->mat[a]= 0;
+ }
+ if(cu->vfont) cu->vfont->id.us--;
+ cu->vfont= 0;
+ if(cu->key) cu->key->id.us--;
+ cu->key= 0;
+ if(cu->ipo) cu->ipo->id.us--;
+ cu->ipo= 0;
+}
+
+
+/* niet curve zelf vrijgeven */
+void free_curve(Curve *cu)
+{
+
+ freeNurblist(&cu->nurb);
+ BLI_freelistN(&cu->bev);
+ freedisplist(&cu->disp);
+
+ unlink_curve(cu);
+
+ if(cu->mat) MEM_freeN(cu->mat);
+ if(cu->str) MEM_freeN(cu->str);
+ if(cu->bb) MEM_freeN(cu->bb);
+ if(cu->path) free_path(cu->path);
+}
+
+Curve *add_curve(int type)
+{
+ Curve *cu;
+ char *str;
+
+ if(type==OB_CURVE) str= "Curve";
+ else if(type==OB_SURF) str= "Surf";
+ else str= "Text";
+
+ cu= alloc_libblock(&G.main->curve, ID_CU, str);
+
+ cu->size[0]= cu->size[1]= cu->size[2]= 1.0;
+ cu->flag= CU_FRONT+CU_BACK;
+ cu->pathlen= 100;
+ cu->resolu= cu->resolv= 6;
+ cu->width= 1.0;
+ cu->spacing= cu->linedist= 1.0;
+ cu->fsize= 1.0;
+ cu->texflag= AUTOSPACE;
+
+ cu->bb= unit_boundbox();
+
+ return cu;
+}
+
+Curve *copy_curve(Curve *cu)
+{
+ Curve *cun;
+ int a;
+
+ cun= copy_libblock(cu);
+ cun->nurb.first= cun->nurb.last= 0;
+ duplicateNurblist( &(cun->nurb), &(cu->nurb));
+
+ cun->mat= MEM_dupallocN(cu->mat);
+ for(a=0; a<cun->totcol; a++) {
+ id_us_plus((ID *)cun->mat[a]);
+ }
+
+ cun->str= MEM_dupallocN(cu->str);
+ cun->bb= MEM_dupallocN(cu->bb);
+
+ cun->key= copy_key(cu->key);
+ if(cun->key) cun->key->from= (ID *)cun;
+
+ cun->disp.first= cun->disp.last= 0;
+ cun->bev.first= cun->bev.last= 0;
+ cun->path= 0;
+
+ /* ook single user ipo */
+ if(cun->ipo) cun->ipo= copy_ipo(cun->ipo);
+
+ id_us_plus((ID *)cun->vfont);
+
+ return cun;
+}
+
+void make_local_curve(Curve *cu)
+{
+ Object *ob = 0;
+ Curve *cun;
+ int local=0, lib=0;
+
+ /* - zijn er alleen lib users: niet doen
+ * - zijn er alleen locale users: flag zetten
+ * - mixed: copy
+ */
+
+ if(cu->id.lib==0) return;
+
+ if(cu->vfont) cu->vfont->id.lib= 0;
+
+ if(cu->id.us==1) {
+ cu->id.lib= 0;
+ cu->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)cu, 0);
+ return;
+ }
+
+ ob= G.main->object.first;
+ while(ob) {
+ if(ob->data==cu) {
+ if(ob->id.lib) lib= 1;
+ else local= 1;
+ }
+ ob= ob->id.next;
+ }
+
+ if(local && lib==0) {
+ cu->id.lib= 0;
+ cu->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)cu, 0);
+ }
+ else if(local && lib) {
+ cun= copy_curve(cu);
+ cun->id.us= 0;
+
+ ob= G.main->object.first;
+ while(ob) {
+ if(ob->data==cu) {
+
+ if(ob->id.lib==0) {
+ ob->data= cun;
+ cun->id.us++;
+ cu->id.us--;
+ }
+ }
+ ob= ob->id.next;
+ }
+ }
+}
+
+
+void test_curve_type(Object *ob)
+{
+ Nurb *nu;
+ Curve *cu;
+
+ cu= ob->data;
+ if(cu->vfont) {
+ ob->type= OB_FONT;
+ return;
+ }
+ else {
+ nu= cu->nurb.first;
+ while(nu) {
+ if(nu->pntsv>1) {
+ ob->type= OB_SURF;
+ return;
+ }
+ nu= nu->next;
+ }
+ }
+ ob->type= OB_CURVE;
+}
+
+void tex_space_curve(Curve *cu)
+{
+ DispList *dl;
+ BoundBox *bb;
+ float *data, min[3], max[3], loc[3], size[3];
+ int tot, doit= 0;
+
+ if(cu->bb==0) cu->bb= MEM_callocN(sizeof(BoundBox), "boundbox");
+ bb= cu->bb;
+
+ INIT_MINMAX(min, max);
+
+ dl= cu->disp.first;
+ while(dl) {
+
+ if(dl->type==DL_INDEX3 || dl->type==DL_INDEX3) tot= dl->nr;
+ else tot= dl->nr*dl->parts;
+
+ if(tot) doit= 1;
+ data= dl->verts;
+ while(tot--) {
+ DO_MINMAX(data, min, max);
+ data+= 3;
+ }
+ dl= dl->next;
+ }
+
+ if(doit) {
+ loc[0]= (min[0]+max[0])/2.0f;
+ loc[1]= (min[1]+max[1])/2.0f;
+ loc[2]= (min[2]+max[2])/2.0f;
+
+ size[0]= (max[0]-min[0])/2.0f;
+ size[1]= (max[1]-min[1])/2.0f;
+ size[2]= (max[2]-min[2])/2.0f;
+ }
+ else {
+ loc[0]= loc[1]= loc[2]= 0.0f;
+ size[0]= size[1]= size[2]= 1.0f;
+ }
+
+ bb->vec[0][0]=bb->vec[1][0]=bb->vec[2][0]=bb->vec[3][0]= loc[0]-size[0];
+ bb->vec[4][0]=bb->vec[5][0]=bb->vec[6][0]=bb->vec[7][0]= loc[0]+size[0];
+
+ bb->vec[0][1]=bb->vec[1][1]=bb->vec[4][1]=bb->vec[5][1]= loc[1]-size[1];
+ bb->vec[2][1]=bb->vec[3][1]=bb->vec[6][1]=bb->vec[7][1]= loc[1]+size[1];
+
+ bb->vec[0][2]=bb->vec[3][2]=bb->vec[4][2]=bb->vec[7][2]= loc[2]-size[2];
+ bb->vec[1][2]=bb->vec[2][2]=bb->vec[5][2]=bb->vec[6][2]= loc[2]+size[2];
+
+ if(cu->texflag & AUTOSPACE) {
+ VECCOPY(cu->loc, loc);
+ VECCOPY(cu->size, size);
+ cu->rot[0]= cu->rot[1]= cu->rot[2]= 0.0;
+
+ if(cu->size[0]==0.0) cu->size[0]= 1.0;
+ else if(cu->size[0]>0.0 && cu->size[0]<0.00001) cu->size[0]= 0.00001;
+ else if(cu->size[0]<0.0 && cu->size[0]> -0.00001) cu->size[0]= -0.00001;
+
+ if(cu->size[1]==0.0) cu->size[1]= 1.0;
+ else if(cu->size[1]>0.0 && cu->size[1]<0.00001) cu->size[1]= 0.00001;
+ else if(cu->size[1]<0.0 && cu->size[1]> -0.00001) cu->size[1]= -0.00001;
+
+ if(cu->size[2]==0.0) cu->size[2]= 1.0;
+ else if(cu->size[2]>0.0 && cu->size[2]<0.00001) cu->size[2]= 0.00001;
+ else if(cu->size[2]<0.0 && cu->size[2]> -0.00001) cu->size[2]= -0.00001;
+
+ }
+}
+
+
+int count_curveverts(ListBase *nurb)
+{
+ Nurb *nu;
+ int tot=0;
+
+ nu= nurb->first;
+ while(nu) {
+ if(nu->bezt) tot+= 3*nu->pntsu;
+ else if(nu->bp) tot+= nu->pntsu*nu->pntsv;
+
+ nu= nu->next;
+ }
+ return tot;
+}
+
+
+
+/* **************** NURBS ROUTINES ******************** */
+
+void freeNurb(Nurb *nu)
+{
+
+ if(nu==0) return;
+
+ if(nu->bezt) MEM_freeN(nu->bezt);
+ nu->bezt= 0;
+ if(nu->bp) MEM_freeN(nu->bp);
+ nu->bp= 0;
+ if(nu->knotsu) MEM_freeN(nu->knotsu);
+ nu->knotsu= 0;
+ if(nu->knotsv) MEM_freeN(nu->knotsv);
+ nu->knotsv= 0;
+ /* if(nu->trim.first) freeNurblist(&(nu->trim)); */
+
+ MEM_freeN(nu);
+
+}
+
+
+void freeNurblist(ListBase *lb)
+{
+ Nurb *nu, *next;
+
+ if(lb==0) return;
+
+ nu= lb->first;
+ while(nu) {
+ next= nu->next;
+ freeNurb(nu);
+ nu= next;
+ }
+ lb->first= lb->last= 0;
+}
+
+Nurb *duplicateNurb(Nurb *nu)
+{
+ Nurb *newnu;
+ int len;
+
+ newnu= (Nurb*)MEM_mallocN(sizeof(Nurb),"duplicateNurb");
+ if(newnu==0) return 0;
+ memcpy(newnu, nu, sizeof(Nurb));
+
+ if(nu->bezt) {
+ newnu->bezt=
+ (BezTriple*)MEM_mallocN((nu->pntsu)* sizeof(BezTriple),"duplicateNurb2");
+ memcpy(newnu->bezt, nu->bezt, nu->pntsu*sizeof(BezTriple));
+ }
+ else {
+ len= nu->pntsu*nu->pntsv;
+ newnu->bp=
+ (BPoint*)MEM_mallocN((len)* sizeof(BPoint),"duplicateNurb3");
+ memcpy(newnu->bp, nu->bp, len*sizeof(BPoint));
+
+ newnu->knotsu=newnu->knotsv= 0;
+
+ if(nu->knotsu) {
+ len= KNOTSU(nu);
+ if(len) {
+ newnu->knotsu= MEM_mallocN(len*sizeof(float), "duplicateNurb4");
+ memcpy(newnu->knotsu, nu->knotsu, sizeof(float)*len);
+ }
+ }
+ if(nu->pntsv>1 && nu->knotsv) {
+ len= KNOTSV(nu);
+ if(len) {
+ newnu->knotsv= MEM_mallocN(len*sizeof(float), "duplicateNurb5");
+ memcpy(newnu->knotsv, nu->knotsv, sizeof(float)*len);
+ }
+ }
+ }
+ return newnu;
+}
+
+void duplicateNurblist(ListBase *lb1, ListBase *lb2)
+{
+ Nurb *nu, *nun;
+
+ freeNurblist(lb1);
+
+ nu= lb2->first;
+ while(nu) {
+ nun= duplicateNurb(nu);
+ BLI_addtail(lb1, nun);
+
+ nu= nu->next;
+ }
+}
+
+void test2DNurb(Nurb *nu)
+{
+ BezTriple *bezt;
+ BPoint *bp;
+ int a;
+
+ if( nu->type== CU_BEZIER+CU_2D ) {
+ a= nu->pntsu;
+ bezt= nu->bezt;
+ while(a--) {
+ bezt->vec[0][2]= 0.0;
+ bezt->vec[1][2]= 0.0;
+ bezt->vec[2][2]= 0.0;
+ bezt++;
+ }
+ }
+ else if(nu->type & CU_2D) {
+ a= nu->pntsu*nu->pntsv;
+ bp= nu->bp;
+ while(a--) {
+ bp->vec[2]= 0.0;
+ bp++;
+ }
+ }
+}
+
+void minmaxNurb(Nurb *nu, float *min, float *max)
+{
+ BezTriple *bezt;
+ BPoint *bp;
+ int a;
+
+ if( (nu->type & 7)==CU_BEZIER ) {
+ a= nu->pntsu;
+ bezt= nu->bezt;
+ while(a--) {
+ DO_MINMAX(bezt->vec[0], min, max);
+ DO_MINMAX(bezt->vec[1], min, max);
+ DO_MINMAX(bezt->vec[2], min, max);
+ bezt++;
+ }
+ }
+ else {
+ a= nu->pntsu*nu->pntsv;
+ bp= nu->bp;
+ while(a--) {
+ DO_MINMAX(bp->vec, min, max);
+ bp++;
+ }
+ }
+
+}
+
+/* ~~~~~~~~~~~~~~~~~~~~Non Uniform Rational B Spline berekeningen ~~~~~~~~~~~ */
+
+
+/* voor de goede orde: eigenlijk horen hier doubles gebruikt te worden */
+
+void extend_spline(float * pnts, int in, int out)
+{
+ float *_pnts;
+ double * add;
+ int i, j, k;
+
+ _pnts = pnts;
+ add = (double*)MEM_mallocN((in)* sizeof(double), "extend_spline");
+
+ for (k = 3; k > 0; k--){
+ pnts = _pnts;
+
+ /* punten kopieren naar add */
+ for (i = 0; i < in; i++){
+ add[i] = *pnts;
+ pnts += 3;
+ }
+
+ /* inverse forward differencen */
+ for (i = 0; i < in - 1; i++){
+ for (j = in - 1; j > i; j--){
+ add[j] -= add[j - 1];
+ }
+ }
+
+ pnts = _pnts;
+ for (i = out; i > 0; i--){
+ *pnts = (float)(add[0]);
+ pnts += 3;
+ for (j = 0; j < in - 1; j++){
+ add[j] += add[j+1];
+ }
+ }
+
+ _pnts++;
+ }
+
+ MEM_freeN(add);
+}
+
+
+void calcknots(float *knots, short aantal, short order, short type)
+/* knots: aantal pnts NIET gecorrigeerd voor cyclic */
+/* aantal, order, type; 0: uniform, 1: endpoints, 2: bezier */
+{
+ float k;
+ int a;
+
+ if(type==0) {
+ for(a=0;a<aantal+order;a++) {
+ knots[a]= (float)a;
+ }
+ }
+ else if(type==1) {
+ k= 0.0;
+ for(a=1;a<=aantal+order;a++) {
+ knots[a-1]= k;
+ if(a>=order && a<=aantal) k+= 1.0;
+ }
+ }
+ else if(type==2) {
+ if(order==4) {
+ k= 0.34;
+ for(a=0;a<aantal+order;a++) {
+ knots[a]= (float)floor(k);
+ k+= (1.0/3.0);
+ }
+ }
+ else if(order==3) {
+ k= 0.6;
+ for(a=0;a<aantal+order;a++) {
+ if(a>=order && a<=aantal) k+= (0.5);
+ knots[a]= (float)floor(k);
+ }
+ }
+ }
+}
+
+void makecyclicknots(float *knots, short pnts, short order)
+/* pnts, order: aantal pnts NIET gecorrigeerd voor cyclic */
+{
+ int a, b;
+
+ if(knots==0) return;
+
+ /* eerst lange rijen (order -1) dezelfde knots aan uiteinde verwijderen */
+ if(order>2) {
+ b= pnts+order-1;
+ for(a=1; a<order-1; a++) {
+ if(knots[b]!= knots[b-a]) break;
+ }
+ if(a==order-1) knots[pnts+order-2]+= 1.0;
+ }
+
+ b= order;
+ for(a=pnts+order-1; a<pnts+order+order-1; a++) {
+ knots[a]= knots[a-1]+ (knots[b]-knots[b-1]);
+ b--;
+ }
+}
+
+
+void makeknots(Nurb *nu, short uv, short type) /* 0: uniform, 1: endpoints, 2: bezier */
+{
+ if( (nu->type & 7)==CU_NURBS ) {
+ if(uv & 1) {
+ if(nu->knotsu) MEM_freeN(nu->knotsu);
+ if(nu->pntsu>1) {
+ nu->knotsu= MEM_callocN(4+sizeof(float)*KNOTSU(nu), "makeknots");
+ calcknots(nu->knotsu, nu->pntsu, nu->orderu, type);
+ if(nu->flagu & 1) makecyclicknots(nu->knotsu, nu->pntsu, nu->orderu);
+ }
+ else nu->knotsu= 0;
+ }
+ if(uv & 2) {
+ if(nu->knotsv) MEM_freeN(nu->knotsv);
+ if(nu->pntsv>1) {
+ nu->knotsv= MEM_callocN(4+sizeof(float)*KNOTSV(nu), "makeknots");
+ calcknots(nu->knotsv, nu->pntsv, nu->orderv, type);
+ if(nu->flagv & 1) makecyclicknots(nu->knotsv, nu->pntsv, nu->orderv);
+ }
+ else nu->knotsv= 0;
+ }
+ }
+}
+
+void basisNurb(float t, short order, short pnts, float *knots, float *basis, int *start, int *end)
+{
+ float d, e;
+ int i, i1 = 0, i2 = 0 ,j, orderpluspnts;
+
+ orderpluspnts= order+pnts;
+
+ /* this is for float inaccuracy */
+ if(t < knots[0]) t= knots[0];
+ else if(t > knots[orderpluspnts-1]) t= knots[orderpluspnts-1];
+
+ /* dit stuk is order '1' */
+ for(i=0;i<orderpluspnts-1;i++) {
+ if(knots[i]!=knots[i+1] && t>= knots[i] && t<=knots[i+1]) {
+ basis[i]= 1.0;
+ i1= i-order+1;
+ if(i1<0) i1= 0;
+ i2= i;
+ i++;
+ while(i<orderpluspnts-1) {
+ basis[i]= 0.0;
+ i++;
+ }
+ break;
+ }
+ else basis[i]= 0.0;
+ }
+ basis[i]= 0.0;
+
+ /* printf("u %f\n", t); for(k=0;k<orderpluspnts;k++) printf(" %2.2f",basis[k]); printf("\n"); */
+
+ /* dit is order 2,3,... */
+ for(j=2; j<=order; j++) {
+
+ if(i2+j>= orderpluspnts) i2= orderpluspnts-j-1;
+
+ for(i= i1; i<=i2; i++) {
+ if(basis[i]!=0.0)
+ d= ((t-knots[i])*basis[i]) / (knots[i+j-1]-knots[i]);
+ else
+ d= 0.0;
+
+ if(basis[i+1]!=0.0)
+ e= ((knots[i+j]-t)*basis[i+1]) / (knots[i+j]-knots[i+1]);
+ else
+ e= 0.0;
+
+ basis[i]= d+e;
+ }
+ }
+
+ *start= 1000;
+ *end= 0;
+
+ for(i=i1; i<=i2; i++) {
+ if(basis[i]>0.0) {
+ *end= i;
+ if(*start==1000) *start= i;
+ }
+ }
+}
+
+
+void makeNurbfaces(Nurb *nu, float *data)
+/* data moet 3*4*resolu*resolv lang zijn en op nul staan */
+{
+ BPoint *bp;
+ float *basisu, *basis, *basisv, *sum, *fp, *in;
+ float u, v, ustart, uend, ustep, vstart, vend, vstep, sumdiv;
+ int i, j, iofs, jofs, cycl, len, resolu, resolv;
+ int istart, iend, jsta, jen, *jstart, *jend, ratcomp;
+
+ if(nu->knotsu==0 || nu->knotsv==0) return;
+ if(nu->orderu>nu->pntsu) return;
+ if(nu->orderv>nu->pntsv) return;
+ if(data==0) return;
+
+ /* alloceren en vars goedzetten */
+ len= nu->pntsu*nu->pntsv;
+ if(len==0) return;
+ sum= (float *)MEM_callocN(sizeof(float)*len, "makeNurbfaces1");
+
+ resolu= nu->resolu;
+ resolv= nu->resolv;
+ len= resolu*resolv;
+ if(len==0) {
+ MEM_freeN(sum);
+ return;
+ }
+
+ bp= nu->bp;
+ i= nu->pntsu*nu->pntsv;
+ ratcomp=0;
+ while(i--) {
+ if(bp->vec[3]!=1.0) {
+ ratcomp= 1;
+ break;
+ }
+ bp++;
+ }
+
+ fp= nu->knotsu;
+ ustart= fp[nu->orderu-1];
+ if(nu->flagu & 1) uend= fp[nu->pntsu+nu->orderu-1];
+ else uend= fp[nu->pntsu];
+ ustep= (uend-ustart)/(resolu-1+(nu->flagu & 1));
+ basisu= (float *)MEM_mallocN(sizeof(float)*KNOTSU(nu), "makeNurbfaces3");
+
+ fp= nu->knotsv;
+ vstart= fp[nu->orderv-1];
+
+ if(nu->flagv & 1) vend= fp[nu->pntsv+nu->orderv-1];
+ else vend= fp[nu->pntsv];
+ vstep= (vend-vstart)/(resolv-1+(nu->flagv & 1));
+ len= KNOTSV(nu);
+ basisv= (float *)MEM_mallocN(sizeof(float)*len*resolv, "makeNurbfaces3");
+ jstart= (int *)MEM_mallocN(sizeof(float)*resolv, "makeNurbfaces4");
+ jend= (int *)MEM_mallocN(sizeof(float)*resolv, "makeNurbfaces5");
+
+ /* voorberekenen basisv en jstart,jend */
+ if(nu->flagv & 1) cycl= nu->orderv-1;
+ else cycl= 0;
+ v= vstart;
+ basis= basisv;
+ while(resolv--) {
+ basisNurb(v, nu->orderv, (short)(nu->pntsv+cycl), nu->knotsv, basis, jstart+resolv, jend+resolv);
+ basis+= KNOTSV(nu);
+ v+= vstep;
+ }
+
+ if(nu->flagu & 1) cycl= nu->orderu-1;
+ else cycl= 0;
+ in= data;
+ u= ustart;
+ while(resolu--) {
+
+ basisNurb(u, nu->orderu, (short)(nu->pntsu+cycl), nu->knotsu, basisu, &istart, &iend);
+
+ basis= basisv;
+ resolv= nu->resolv;
+ while(resolv--) {
+
+ jsta= jstart[resolv];
+ jen= jend[resolv];
+
+ /* bereken sum */
+ sumdiv= 0.0;
+ fp= sum;
+
+ for(j= jsta; j<=jen; j++) {
+
+ if(j>=nu->pntsv) jofs= (j - nu->pntsv);
+ else jofs= j;
+ bp= nu->bp+ nu->pntsu*jofs+istart-1;
+
+ for(i= istart; i<=iend; i++, fp++) {
+
+ if(i>= nu->pntsu) {
+ iofs= i- nu->pntsu;
+ bp= nu->bp+ nu->pntsu*jofs+iofs;
+ }
+ else bp++;
+
+ if(ratcomp) {
+ *fp= basisu[i]*basis[j]*bp->vec[3];
+ sumdiv+= *fp;
+ }
+ else *fp= basisu[i]*basis[j];
+ }
+ }
+
+ if(ratcomp) {
+ fp= sum;
+ for(j= jsta; j<=jen; j++) {
+ for(i= istart; i<=iend; i++, fp++) {
+ *fp/= sumdiv;
+ }
+ }
+ }
+
+ /* een! (1.0) echt punt nu */
+ fp= sum;
+ for(j= jsta; j<=jen; j++) {
+
+ if(j>=nu->pntsv) jofs= (j - nu->pntsv);
+ else jofs= j;
+ bp= nu->bp+ nu->pntsu*jofs+istart-1;
+
+ for(i= istart; i<=iend; i++, fp++) {
+
+ if(i>= nu->pntsu) {
+ iofs= i- nu->pntsu;
+ bp= nu->bp+ nu->pntsu*jofs+iofs;
+ }
+ else bp++;
+
+ if(*fp!=0.0) {
+ in[0]+= (*fp) * bp->vec[0];
+ in[1]+= (*fp) * bp->vec[1];
+ in[2]+= (*fp) * bp->vec[2];
+ }
+ }
+ }
+
+ in+=3;
+ basis+= KNOTSV(nu);
+ }
+ u+= ustep;
+ }
+
+ /* vrijgeven */
+ MEM_freeN(sum);
+ MEM_freeN(basisu);
+ MEM_freeN(basisv);
+ MEM_freeN(jstart);
+ MEM_freeN(jend);
+}
+
+
+void makeNurbcurve_forw(Nurb *nu, float *data)
+/* *data: moet 3*4*pntsu*resolu lang zijn en op nul staan */
+{
+ BPoint *bp;
+ float *basisu, *sum, *fp, *in;
+ float u, ustart, uend, ustep, sumdiv;
+ int i, j, k, len, resolu, istart, iend;
+ int wanted, org;
+
+ if(nu->knotsu==0) return;
+ if(data==0) return;
+
+ /* alloceren en vars goedzetten */
+ len= nu->pntsu;
+ if(len==0) return;
+ sum= (float *)MEM_callocN(sizeof(float)*len, "makeNurbcurve1");
+
+ resolu= nu->resolu*nu->pntsu;
+ if(resolu==0) {
+ MEM_freeN(sum);
+ return;
+ }
+
+ fp= nu->knotsu;
+ ustart= fp[nu->orderu-1];
+ uend= fp[nu->pntsu];
+ ustep= (uend-ustart)/(resolu-1);
+ basisu= (float *)MEM_mallocN(sizeof(float)*(nu->orderu+nu->pntsu), "makeNurbcurve3");
+
+ in= data;
+ u= ustart;
+ for (k = nu->orderu - 1; k < nu->pntsu; k++){
+
+ wanted = (int)((nu->knotsu[k+1] - nu->knotsu[k]) / ustep);
+ org = 4; /* gelijk aan order */
+ if (org > wanted) org = wanted;
+
+ for (j = org; j > 0; j--){
+
+ basisNurb(u, nu->orderu, nu->pntsu, nu->knotsu, basisu, &istart, &iend);
+ /* bereken sum */
+ sumdiv= 0.0;
+ fp= sum;
+ for(i= istart; i<=iend; i++, fp++) {
+ /* hier nog rationele component doen */
+ *fp= basisu[i];
+ sumdiv+= *fp;
+ }
+ if(sumdiv!=0.0) if(sumdiv<0.999 || sumdiv>1.001) {
+ /* is dit normaliseren ook nodig? */
+ fp= sum;
+ for(i= istart; i<=iend; i++, fp++) {
+ *fp/= sumdiv;
+ }
+ }
+
+ /* een! (1.0) echt punt nu */
+ fp= sum;
+ bp= nu->bp+ istart;
+ for(i= istart; i<=iend; i++, bp++, fp++) {
+
+ if(*fp!=0.0) {
+ in[0]+= (*fp) * bp->vec[0];
+ in[1]+= (*fp) * bp->vec[1];
+ in[2]+= (*fp) * bp->vec[2];
+ }
+ }
+
+ in+=3;
+
+ u+= ustep;
+ }
+
+ if (wanted > org){
+ extend_spline(in - 3 * org, org, wanted);
+ in += 3 * (wanted - org);
+ u += ustep * (wanted - org);
+ }
+ }
+
+ /* vrijgeven */
+ MEM_freeN(sum);
+ MEM_freeN(basisu);
+}
+
+
+void makeNurbcurve(Nurb *nu, float *data, int dim)
+/* data moet dim*4*pntsu*resolu lang zijn en op nul staan */
+{
+ BPoint *bp;
+ float u, ustart, uend, ustep, sumdiv;
+ float *basisu, *sum, *fp, *in;
+ int i, len, resolu, istart, iend, cycl;
+
+ if(nu->knotsu==0) return;
+ if(nu->orderu>nu->pntsu) return;
+ if(data==0) return;
+
+ /* alloceren en vars goedzetten */
+ len= nu->pntsu;
+ if(len==0) return;
+ sum= (float *)MEM_callocN(sizeof(float)*len, "makeNurbcurve1");
+
+ resolu= nu->resolu*nu->pntsu;
+ if(resolu==0) {
+ MEM_freeN(sum);
+ return;
+ }
+
+ fp= nu->knotsu;
+ ustart= fp[nu->orderu-1];
+ if(nu->flagu & 1) uend= fp[nu->pntsu+nu->orderu-1];
+ else uend= fp[nu->pntsu];
+ ustep= (uend-ustart)/(resolu-1+(nu->flagu & 1));
+ basisu= (float *)MEM_mallocN(sizeof(float)*KNOTSU(nu), "makeNurbcurve3");
+
+ if(nu->flagu & 1) cycl= nu->orderu-1;
+ else cycl= 0;
+
+ in= data;
+ u= ustart;
+ while(resolu--) {
+
+ basisNurb(u, nu->orderu, (short)(nu->pntsu+cycl), nu->knotsu, basisu, &istart, &iend);
+ /* bereken sum */
+ sumdiv= 0.0;
+ fp= sum;
+ bp= nu->bp+ istart-1;
+ for(i= istart; i<=iend; i++, fp++) {
+
+ if(i>=nu->pntsu) bp= nu->bp+(i - nu->pntsu);
+ else bp++;
+
+ *fp= basisu[i]*bp->vec[3];
+ sumdiv+= *fp;
+ }
+ if(sumdiv!=0.0) if(sumdiv<0.999 || sumdiv>1.001) {
+ /* is dit normaliseren ook nodig? */
+ fp= sum;
+ for(i= istart; i<=iend; i++, fp++) {
+ *fp/= sumdiv;
+ }
+ }
+
+ /* een! (1.0) echt punt nu */
+ fp= sum;
+ bp= nu->bp+ istart-1;
+ for(i= istart; i<=iend; i++, fp++) {
+
+ if(i>=nu->pntsu) bp= nu->bp+(i - nu->pntsu);
+ else bp++;
+
+ if(*fp!=0.0) {
+
+ in[0]+= (*fp) * bp->vec[0];
+ in[1]+= (*fp) * bp->vec[1];
+ if(dim>=3) {
+ in[2]+= (*fp) * bp->vec[2];
+ if(dim==4) in[3]+= (*fp) * bp->alfa;
+ }
+ }
+ }
+
+ in+= dim;
+
+ u+= ustep;
+ }
+
+ /* vrijgeven */
+ MEM_freeN(sum);
+ MEM_freeN(basisu);
+}
+
+void maakbez(float q0, float q1, float q2, float q3, float *p, int it)
+{
+ float rt0,rt1,rt2,rt3,f;
+ int a;
+
+ f= (float)it;
+ rt0= q0;
+ rt1= 3.0f*(q1-q0)/f;
+ f*= f;
+ rt2= 3.0f*(q0-2.0f*q1+q2)/f;
+ f*= it;
+ rt3= (q3-q0+3.0f*(q1-q2))/f;
+
+ q0= rt0;
+ q1= rt1+rt2+rt3;
+ q2= 2*rt2+6*rt3;
+ q3= 6*rt3;
+
+ for(a=0; a<=it; a++) {
+ *p= q0;
+ p+= 3;
+ q0+= q1;
+ q1+= q2;
+ q2+= q3;
+ }
+}
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+void make_orco_surf(Curve *cu)
+{
+ Nurb *nu;
+ int a, b, tot=0;
+ int sizeu, sizev;// ###
+ float *data;
+
+
+ /* eerst voorspellen hoelang datablok moet worden */
+ nu= cu->nurb.first;
+ while(nu) {
+#ifdef STRUBI
+/* this is a bad hack: as we want to avoid the seam in a cyclic nurbs
+texture wrapping, reserve extra orco data space to save these extra needed
+vertex based UV coordinates for the meridian vertices.
+Vertices on the 0/2pi boundary are not duplicated inside the displist but later in
+the renderface/vert construction.
+
+See also blenderWorldManipulation.c: init_render_surf()
+
+*/
+
+ sizeu = nu->resolu; sizev = nu->resolv;
+ if (nu->flagu & CU_CYCLIC) sizeu++;
+ if (nu->flagv & CU_CYCLIC) sizev++;
+ if(nu->pntsv>1) tot+= sizeu * sizev;
+#else
+ if(nu->pntsv>1) tot+= nu->resolu*nu->resolv;
+#endif
+ nu= nu->next;
+ }
+ /* makeNurbfaces wil nullen */
+ data= cu->orco= MEM_callocN(3*sizeof(float)*tot, "make_orco");
+
+ nu= cu->nurb.first;
+ while(nu) {
+ if(nu->pntsv>1) {
+ sizeu = nu->resolu;
+ sizev = nu->resolv;
+#ifdef STRUBI
+ if (nu->flagu & CU_CYCLIC) sizeu++;
+ if (nu->flagv & CU_CYCLIC) sizev++;
+#endif
+
+ if(cu->flag & CU_UV_ORCO) {
+ for(b=0; b< sizeu; b++) {
+ for(a=0; a< sizev; a++) {
+
+ if(sizev <2) data[0]= 0.0f;
+ else data[0]= -1.0f + 2.0f*((float)a)/(sizev - 1);
+
+ if(sizeu <2) data[1]= 0.0f;
+ else data[1]= -1.0f + 2.0f*((float)b)/(sizeu - 1);
+
+ data[2]= 0.0;
+
+ data+= 3;
+ }
+ }
+ }
+ else {
+ makeNurbfaces(nu, data);
+#ifdef STRUBI
+ for(b=0; b< nu->resolu; b++) {
+ for(a=0; a< nu->resolv; a++) {
+ data = cu->orco + 3 * (b * nu->resolv + a);
+ data[0]= (data[0]-cu->loc[0])/cu->size[0];
+ data[1]= (data[1]-cu->loc[1])/cu->size[1];
+ data[2]= (data[2]-cu->loc[2])/cu->size[2];
+ }
+ }
+ copyintoExtendedArray(cu->orco, nu->resolv, nu->resolu, cu->orco, sizev, sizeu);
+ /* copy U/V-cyclic orco's */
+ if (nu->flagv & CU_CYCLIC) {
+ b = sizeu - 1;
+ for(a=0; a< sizev; a++) {
+ data = cu->orco + 3 * (b * sizev + a);
+ VECCOPY(data, cu->orco + 3*a);
+ }
+ }
+ if (nu->flagu & CU_CYCLIC) {
+ a = sizev - 1;
+ for(b=0; b< sizeu; b++) {
+ data = cu->orco + 3 * (b * sizev + a);
+ VECCOPY(data, cu->orco + 3 * b*sizev);
+ }
+ }
+
+#else
+ tot= sizeu * sizev;
+ while(tot--) {
+ data[0]= (data[0]-cu->loc[0])/cu->size[0];
+ data[1]= (data[1]-cu->loc[1])/cu->size[1];
+ data[2]= (data[2]-cu->loc[2])/cu->size[2];
+
+ data+= 3;
+ }
+#endif
+ }
+ }
+ nu= nu->next;
+ }
+ /* loadkeypostype(22, base, base); */
+
+}
+
+
+
+/* ***************** BEVEL ****************** */
+
+void makebevelcurve(Object *ob, ListBase *disp)
+{
+ DispList *dl, *dlnew;
+ Curve *bevcu, *cu;
+ float *fp, facx, facy, hoek, dhoek;
+ int nr, a;
+
+ cu= ob->data;
+
+ if(cu->bevobj && cu->bevobj!=ob) {
+ if(cu->bevobj->type==OB_CURVE) {
+ bevcu= cu->bevobj->data;
+ if(bevcu->ext1==0.0 && bevcu->ext2==0.0) {
+ facx= cu->bevobj->size[0];
+ facy= cu->bevobj->size[1];
+
+ dl= bevcu->disp.first;
+ if(dl==0) {
+ makeDispList(cu->bevobj);
+ dl= bevcu->disp.first;
+ }
+ while(dl) {
+ if ELEM(dl->type, DL_POLY, DL_SEGM) {
+ dlnew= MEM_mallocN(sizeof(DispList), "makebevelcurve1");
+ *dlnew= *dl;
+ dlnew->verts= MEM_mallocN(3*sizeof(float)*dl->parts*dl->nr, "makebevelcurve1");
+ memcpy(dlnew->verts, dl->verts, 3*sizeof(float)*dl->parts*dl->nr);
+
+ BLI_addtail(disp, dlnew);
+ fp= dlnew->verts;
+ nr= dlnew->parts*dlnew->nr;
+ while(nr--) {
+ fp[2]= fp[1]*facy;
+ fp[1]= -fp[0]*facx;
+ fp[0]= 0.0;
+ fp+= 3;
+ }
+ }
+ dl= dl->next;
+ }
+ }
+ }
+ }
+ else if(cu->ext2==0.0) {
+ dl= MEM_callocN(sizeof(DispList), "makebevelcurve2");
+ dl->verts= MEM_mallocN(2*3*sizeof(float), "makebevelcurve2");
+ BLI_addtail(disp, dl);
+ dl->type= DL_SEGM;
+ dl->parts= 1;
+ dl->nr= 2;
+ fp= dl->verts;
+ fp[0]= fp[1]= 0.0;
+ fp[2]= -cu->ext1;
+ fp[3]= fp[4]= 0.0;
+ fp[5]= cu->ext1;
+ }
+ else {
+ nr= 4+2*cu->bevresol;
+
+ dl= MEM_callocN(sizeof(DispList), "makebevelcurve3");
+ dl->verts= MEM_mallocN(nr*3*sizeof(float), "makebevelcurve3");
+ BLI_addtail(disp, dl);
+ dl->type= DL_SEGM;
+ dl->parts= 1;
+ dl->nr= nr;
+
+ /* eerst cirkel maken */
+ fp= dl->verts;
+ hoek= -0.5*M_PI;
+ dhoek= (float)(M_PI/(nr-2));
+ for(a=0; a<nr; a++) {
+ fp[0]= 0.0;
+ fp[1]= (float)(cos(hoek)*(cu->ext2));
+ fp[2]= (float)(sin(hoek)*(cu->ext2));
+ hoek+= dhoek;
+ fp+= 3;
+ if(cu->ext1!=0.0 && a==((nr/2)-1) ) {
+ VECCOPY(fp, fp-3);
+ fp+=3;
+ a++;
+ }
+ }
+ if(cu->ext1==0.0) dl->nr--;
+ else {
+ fp= dl->verts;
+ for(a=0; a<nr; a++) {
+ if(a<=(nr/2-1)) fp[2]-= (cu->ext1);
+ else fp[2]+= (cu->ext1);
+ fp+= 3;
+ }
+ }
+ }
+
+}
+
+int cu_isectLL(float *v1, float *v2, float *v3, float *v4, short cox, short coy, float *labda, float *mu, float *vec)
+{
+ /* return:
+ -1: colliniar
+ 0: no intersection of segments
+ 1: exact intersection of segments
+ 2: cross-intersection of segments
+ */
+ float deler;
+
+ deler= (v1[cox]-v2[cox])*(v3[coy]-v4[coy])-(v3[cox]-v4[cox])*(v1[coy]-v2[coy]);
+ if(deler==0.0) return -1;
+
+ *labda= (v1[coy]-v3[coy])*(v3[cox]-v4[cox])-(v1[cox]-v3[cox])*(v3[coy]-v4[coy]);
+ *labda= -(*labda/deler);
+
+ deler= v3[coy]-v4[coy];
+ if(deler==0) {
+ deler=v3[cox]-v4[cox];
+ *mu= -(*labda*(v2[cox]-v1[cox])+v1[cox]-v3[cox])/deler;
+ } else {
+ *mu= -(*labda*(v2[coy]-v1[coy])+v1[coy]-v3[coy])/deler;
+ }
+ vec[cox]= *labda*(v2[cox]-v1[cox])+v1[cox];
+ vec[coy]= *labda*(v2[coy]-v1[coy])+v1[coy];
+
+ if(*labda>=0.0 && *labda<=1.0 && *mu>=0.0 && *mu<=1.0) {
+ if(*labda==0.0 || *labda==1.0 || *mu==0.0 || *mu==1.0) return 1;
+ return 2;
+ }
+ return 0;
+}
+
+
+short bevelinside(BevList *bl1,BevList *bl2)
+{
+ /* is bl2 INSIDE bl1 ? met links-rechts methode en "labda's" */
+ /* geeft als correct gat 1 terug */
+ BevPoint *bevp, *prevbevp;
+ float min,max,vec[3],hvec1[3],hvec2[3],lab,mu;
+ int nr, links=0,rechts=0,mode;
+
+ /* neem eerste vertex van het mogelijke gat */
+
+ bevp= (BevPoint *)(bl2+1);
+ hvec1[0]= bevp->x;
+ hvec1[1]= bevp->y;
+ hvec1[2]= 0.0;
+ VECCOPY(hvec2,hvec1);
+ hvec2[0]+=1000;
+
+ /* test deze met alle edges van mogelijk omringende poly */
+ /* tel aantal overgangen links en rechts */
+
+ bevp= (BevPoint *)(bl1+1);
+ nr= bl1->nr;
+ prevbevp= bevp+(nr-1);
+
+ while(nr--) {
+ min= prevbevp->y;
+ max= bevp->y;
+ if(max<min) {
+ min= max;
+ max= prevbevp->y;
+ }
+ if(min!=max) {
+ if(min<=hvec1[1] && max>=hvec1[1]) {
+ /* er is een overgang, snijpunt berekenen */
+ mode= cu_isectLL(&(prevbevp->x),&(bevp->x),hvec1,hvec2,0,1,&lab,&mu,vec);
+ /* als lab==0.0 of lab==1.0 dan snijdt de edge exact de overgang
+ * alleen toestaan voor lab= 1.0 (of andersom, maakt niet uit)
+ */
+ if(mode>=0 && lab!=0.0) {
+ if(vec[0]<hvec1[0]) links++;
+ else rechts++;
+ }
+ }
+ }
+ prevbevp= bevp;
+ bevp++;
+ }
+
+ if( (links & 1) && (rechts & 1) ) return 1;
+ return 0;
+}
+
+
+struct bevelsort {
+ float left;
+ BevList *bl;
+ int dir;
+};
+
+int vergxcobev(const void *a1, const void *a2)
+{
+ const struct bevelsort *x1=a1,*x2=a2;
+
+ if( x1->left > x2->left ) return 1;
+ else if( x1->left < x2->left) return -1;
+ return 0;
+}
+
+/* deze kan niet zomaar door atan2 vervangen worden, maar waarom? */
+
+void calc_bevel_sin_cos(float x1, float y1, float x2, float y2, float *sina, float *cosa)
+{
+ float t01, t02, x3, y3;
+
+ t01= (float)sqrt(x1*x1+y1*y1);
+ t02= (float)sqrt(x2*x2+y2*y2);
+ if(t01==0.0) t01= 1.0;
+ if(t02==0.0) t02= 1.0;
+
+ x1/=t01;
+ y1/=t01;
+ x2/=t02;
+ y2/=t02;
+
+ t02= x1*x2+y1*y2;
+ if(fabs(t02)>=1.0) t02= .5*M_PI;
+ else t02= (saacos(t02))/2.0f;
+
+ t02= (float)sin(t02);
+ if(t02==0.0) t02= 1.0;
+
+ x3= x1-x2;
+ y3= y1-y2;
+ if(x3==0 && y3==0) {
+ /* printf("x3 en y3 nul \n"); */
+ x3= y1;
+ y3= -x1;
+ } else {
+ t01= (float)sqrt(x3*x3+y3*y3);
+ x3/=t01;
+ y3/=t01;
+ }
+
+ *sina= -y3/t02;
+ *cosa= x3/t02;
+
+}
+
+void alfa_bezpart(BezTriple *prevbezt, BezTriple *bezt, Nurb *nu, float *data_a)
+{
+ BezTriple *pprev, *next, *last;
+ float fac, dfac, t[4];
+ int a;
+
+ last= nu->bezt+(nu->pntsu-1);
+
+ /* een punt terug */
+ if(prevbezt==nu->bezt) {
+ if(nu->flagu & 1) pprev= last;
+ else pprev= prevbezt;
+ }
+ else pprev= prevbezt-1;
+
+ /* een punt verder */
+ if(bezt==last) {
+ if(nu->flagu & 1) next= nu->bezt;
+ else next= bezt;
+ }
+ else next= bezt+1;
+
+ fac= 0.0;
+ dfac= 1.0f/(float)nu->resolu;
+
+ for(a=0; a<nu->resolu; a++, fac+= dfac) {
+
+ set_four_ipo(fac, t, KEY_BSPLINE);
+
+ data_a[a]= t[0]*pprev->alfa + t[1]*prevbezt->alfa + t[2]*bezt->alfa + t[3]*next->alfa;
+ }
+}
+
+void makeBevelList(Object *ob)
+{
+ /* - alle curves omzetten in poly's, met aangegeven resol en vlaggen voor dubbele punten
+ - eventueel intelligent punten verwijderen (geval Nurb)
+ - scheiden in verschillende blokken met Boundbox
+ - Autogat detectie */
+ Curve *cu;
+ Nurb *nu;
+ BezTriple *bezt, *prevbezt;
+ BPoint *bp;
+ BevList *bl, *blnew, *blnext;
+ BevPoint *bevp, *bevp2, *bevp1 = NULL, *bevp0;
+ float *data, *data_a, *v1, *v2, min, inp, x1, x2, y1, y2, vec[3];
+ struct bevelsort *sortdata, *sd, *sd1;
+ int a, b, len, nr, poly;
+
+ /* deze fie moet object hebben in verband met tflag en upflag */
+ cu= ob->data;
+
+ /* STAP 1: POLY'S MAKEN */
+
+ BLI_freelistN(&(cu->bev));
+ if(ob==G.obedit) nu= editNurb.first;
+ else nu= cu->nurb.first;
+
+ while(nu) {
+ if(nu->pntsu>1) {
+
+ if((nu->type & 7)==CU_POLY) {
+
+ len= nu->pntsu;
+ bl= MEM_callocN(sizeof(BevList)+len*sizeof(BevPoint), "makeBevelList");
+ BLI_addtail(&(cu->bev), bl);
+
+ if(nu->flagu & 1) bl->poly= 0;
+ else bl->poly= -1;
+ bl->nr= len;
+ bl->flag= 0;
+ bevp= (BevPoint *)(bl+1);
+ bp= nu->bp;
+
+ while(len--) {
+ bevp->x= bp->vec[0];
+ bevp->y= bp->vec[1];
+ bevp->z= bp->vec[2];
+ bevp->alfa= bp->alfa;
+ bevp->f1= 1;
+ bevp++;
+ bp++;
+ }
+ }
+ else if((nu->type & 7)==CU_BEZIER) {
+
+ len= nu->resolu*(nu->pntsu+ (nu->flagu & 1) -1)+1; /* voor laatste punt niet cyclic */
+ bl= MEM_callocN(sizeof(BevList)+len*sizeof(BevPoint), "makeBevelList");
+ BLI_addtail(&(cu->bev), bl);
+
+ if(nu->flagu & 1) bl->poly= 0;
+ else bl->poly= -1;
+ bevp= (BevPoint *)(bl+1);
+
+ a= nu->pntsu-1;
+ bezt= nu->bezt;
+ if(nu->flagu & 1) {
+ a++;
+ prevbezt= nu->bezt+(nu->pntsu-1);
+ }
+ else {
+ prevbezt= bezt;
+ bezt++;
+ }
+
+ data= MEM_mallocN(3*sizeof(float)*(nu->resolu+1), "makeBevelList2");
+ data_a= MEM_callocN(sizeof(float)*(nu->resolu+1), "data_a");
+
+ while(a--) {
+ if(prevbezt->h2==HD_VECT && bezt->h1==HD_VECT) {
+
+ bevp->x= prevbezt->vec[1][0];
+ bevp->y= prevbezt->vec[1][1];
+ bevp->z= prevbezt->vec[1][2];
+ bevp->alfa= prevbezt->alfa;
+ bevp->f1= 1;
+ bevp->f2= 0;
+ bevp++;
+ bl->nr++;
+ bl->flag= 1;
+ }
+ else {
+ v1= prevbezt->vec[1];
+ v2= bezt->vec[0];
+
+ /* altijd alle drie doen: anders blijft data hangen */
+ maakbez(v1[0], v1[3], v2[0], v2[3], data, nu->resolu);
+ maakbez(v1[1], v1[4], v2[1], v2[4], data+1, nu->resolu);
+ maakbez(v1[2], v1[5], v2[2], v2[5], data+2, nu->resolu);
+
+ if((nu->type & CU_2D)==0) {
+ if(cu->flag & CU_3D) {
+ alfa_bezpart(prevbezt, bezt, nu, data_a);
+ }
+ }
+
+
+ /* met handlecodes dubbele punten aangeven */
+ if(prevbezt->h1==prevbezt->h2) {
+ if(prevbezt->h1==0 || prevbezt->h1==HD_VECT) bevp->f1= 1;
+ }
+ else {
+ if(prevbezt->h1==0 || prevbezt->h1==HD_VECT) bevp->f1= 1;
+ else if(prevbezt->h2==0 || prevbezt->h2==HD_VECT) bevp->f1= 1;
+ }
+
+ v1= data;
+ v2= data_a;
+ nr= nu->resolu;
+
+ while(nr--) {
+ bevp->x= v1[0];
+ bevp->y= v1[1];
+ bevp->z= v1[2];
+ bevp->alfa= v2[0];
+ bevp++;
+ v1+=3;
+ v2++;
+ }
+ bl->nr+= nu->resolu;
+
+ }
+ prevbezt= bezt;
+ bezt++;
+ }
+
+ MEM_freeN(data);
+ MEM_freeN(data_a);
+
+ if((nu->flagu & 1)==0) { /* niet cyclic: endpoint */
+ bevp->x= prevbezt->vec[1][0];
+ bevp->y= prevbezt->vec[1][1];
+ bevp->z= prevbezt->vec[1][2];
+ bl->nr++;
+ }
+
+ }
+ else if((nu->type & 7)==CU_NURBS) {
+ if(nu->pntsv==1) {
+ len= nu->resolu*nu->pntsu;
+ bl= MEM_mallocN(sizeof(BevList)+len*sizeof(BevPoint), "makeBevelList3");
+ BLI_addtail(&(cu->bev), bl);
+ bl->nr= len;
+ bl->flag= 0;
+ if(nu->flagu & 1) bl->poly= 0;
+ else bl->poly= -1;
+ bevp= (BevPoint *)(bl+1);
+
+ data= MEM_callocN(4*sizeof(float)*len, "makeBevelList4"); /* moet op nul staan */
+ makeNurbcurve(nu, data, 4);
+
+ v1= data;
+ while(len--) {
+ bevp->x= v1[0];
+ bevp->y= v1[1];
+ bevp->z= v1[2];
+ bevp->alfa= v1[3];
+
+ bevp->f1= bevp->f2= 0;
+ bevp++;
+ v1+=4;
+ }
+ MEM_freeN(data);
+ }
+ }
+ }
+ nu= nu->next;
+ }
+
+ /* STAP 2: DUBBELE PUNTEN EN AUTOMATISCHE RESOLUTIE, DATABLOKKEN VERKLEINEN */
+ bl= cu->bev.first;
+ while(bl) {
+ nr= bl->nr;
+ bevp1= (BevPoint *)(bl+1);
+ bevp0= bevp1+(nr-1);
+ nr--;
+ while(nr--) {
+ if( fabs(bevp0->x-bevp1->x)<0.00001 ) {
+ if( fabs(bevp0->y-bevp1->y)<0.00001 ) {
+ if( fabs(bevp0->z-bevp1->z)<0.00001 ) {
+ bevp0->f2= 1;
+ bl->flag++;
+ }
+ }
+ }
+ bevp0= bevp1;
+ bevp1++;
+ }
+ bl= bl->next;
+ }
+ bl= cu->bev.first;
+ while(bl) {
+ blnext= bl->next;
+ if(bl->flag) {
+ nr= bl->nr- bl->flag+1; /* +1 want vectorbezier zet ook flag */
+ blnew= MEM_mallocN(sizeof(BevList)+nr*sizeof(BevPoint), "makeBevelList");
+ memcpy(blnew, bl, sizeof(BevList));
+ blnew->nr= 0;
+ BLI_remlink(&(cu->bev), bl);
+ BLI_insertlinkbefore(&(cu->bev),blnext,blnew); /* zodat bevlijst met nurblijst gelijk loopt */
+ bevp0= (BevPoint *)(bl+1);
+ bevp1= (BevPoint *)(blnew+1);
+ nr= bl->nr;
+ while(nr--) {
+ if(bevp0->f2==0) {
+ memcpy(bevp1, bevp0, sizeof(BevPoint));
+ bevp1++;
+ blnew->nr++;
+ }
+ bevp0++;
+ }
+ MEM_freeN(bl);
+ blnew->flag= 0;
+ }
+ bl= blnext;
+ }
+
+ /* STAP 3: POLY'S TELLEN EN AUTOGAT */
+ bl= cu->bev.first;
+ poly= 0;
+ while(bl) {
+ if(bl->poly>=0) {
+ poly++;
+ bl->poly= poly;
+ bl->gat= 0;
+ }
+ bl= bl->next;
+ }
+
+
+ /* meest linkse punten vinden, tevens richting testen */
+ if(poly>0) {
+ sd= sortdata= MEM_mallocN(sizeof(struct bevelsort)*poly, "makeBevelList5");
+ bl= cu->bev.first;
+ while(bl) {
+ if(bl->poly>0) {
+
+ min= 300000.0;
+ bevp= (BevPoint *)(bl+1);
+ nr= bl->nr;
+ while(nr--) {
+ if(min>bevp->x) {
+ min= bevp->x;
+ bevp1= bevp;
+ }
+ bevp++;
+ }
+ sd->bl= bl;
+ sd->left= min;
+
+ bevp= (BevPoint *)(bl+1);
+ if(bevp1== bevp) bevp0= bevp+ (bl->nr-1);
+ else bevp0= bevp1-1;
+ bevp= bevp+ (bl->nr-1);
+ if(bevp1== bevp) bevp2= (BevPoint *)(bl+1);
+ else bevp2= bevp1+1;
+
+ inp= (bevp1->x- bevp0->x)*(bevp0->y- bevp2->y)
+ +(bevp0->y- bevp1->y)*(bevp0->x- bevp2->x);
+
+ if(inp>0.0) sd->dir= 1;
+ else sd->dir= 0;
+
+ sd++;
+ }
+
+ bl= bl->next;
+ }
+ qsort(sortdata,poly,sizeof(struct bevelsort), vergxcobev);
+
+ sd= sortdata+1;
+ for(a=1; a<poly; a++, sd++) {
+ bl= sd->bl; /* is bl een gat? */
+ sd1= sortdata+ (a-1);
+ for(b=a-1; b>=0; b--, sd1--) { /* alle polys links ervan */
+ if(bevelinside(sd1->bl, bl)) {
+ bl->gat= 1- sd1->bl->gat;
+ break;
+ }
+ }
+ }
+
+ /* draairichting */
+ if((cu->flag & CU_3D)==0) {
+ sd= sortdata;
+ for(a=0; a<poly; a++, sd++) {
+ if(sd->bl->gat==sd->dir) {
+ bl= sd->bl;
+ bevp1= (BevPoint *)(bl+1);
+ bevp2= bevp1+ (bl->nr-1);
+ nr= bl->nr/2;
+ while(nr--) {
+ SWAP(BevPoint, *bevp1, *bevp2);
+ bevp1++;
+ bevp2--;
+ }
+ }
+ }
+ }
+ MEM_freeN(sortdata);
+ }
+
+ /* STAP 4: COSINUSSEN */
+ bl= cu->bev.first;
+ while(bl) {
+
+ if(bl->nr==2) { /* 2 pnt, apart afhandelen: KAN DAT NIET AFGESCHAFT? */
+ bevp2= (BevPoint *)(bl+1);
+ bevp1= bevp2+1;
+
+ x1= bevp1->x- bevp2->x;
+ y1= bevp1->y- bevp2->y;
+
+ calc_bevel_sin_cos(x1, y1, -x1, -y1, &(bevp1->sina), &(bevp1->cosa));
+ bevp2->sina= bevp1->sina;
+ bevp2->cosa= bevp1->cosa;
+
+ if(cu->flag & CU_3D) { /* 3D */
+ float *quat, q[4];
+
+ vec[0]= bevp1->x - bevp2->x;
+ vec[1]= bevp1->y - bevp2->y;
+ vec[2]= bevp1->z - bevp2->z;
+
+ quat= vectoquat(vec, 5, 1);
+
+ Normalise(vec);
+ q[0]= (float)cos(0.5*bevp1->alfa);
+ x1= (float)sin(0.5*bevp1->alfa);
+ q[1]= x1*vec[0];
+ q[2]= x1*vec[1];
+ q[3]= x1*vec[2];
+ QuatMul(quat, q, quat);
+
+ QuatToMat3(quat, bevp1->mat);
+ Mat3CpyMat3(bevp2->mat, bevp1->mat);
+ }
+
+ }
+ else if(bl->nr>2) {
+ bevp2= (BevPoint *)(bl+1);
+ bevp1= bevp2+(bl->nr-1);
+ bevp0= bevp1-1;
+
+
+ nr= bl->nr;
+
+ while(nr--) {
+
+ if(cu->flag & CU_3D) { /* 3D */
+ float *quat, q[4];
+
+ vec[0]= bevp2->x - bevp0->x;
+ vec[1]= bevp2->y - bevp0->y;
+ vec[2]= bevp2->z - bevp0->z;
+
+ Normalise(vec);
+
+ quat= vectoquat(vec, 5, 1);
+
+ q[0]= (float)cos(0.5*bevp1->alfa);
+ x1= (float)sin(0.5*bevp1->alfa);
+ q[1]= x1*vec[0];
+ q[2]= x1*vec[1];
+ q[3]= x1*vec[2];
+ QuatMul(quat, q, quat);
+
+ QuatToMat3(quat, bevp1->mat);
+ }
+
+ x1= bevp1->x- bevp0->x;
+ x2= bevp1->x- bevp2->x;
+ y1= bevp1->y- bevp0->y;
+ y2= bevp1->y- bevp2->y;
+
+ calc_bevel_sin_cos(x1, y1, x2, y2, &(bevp1->sina), &(bevp1->cosa));
+
+
+ bevp0= bevp1;
+ bevp1= bevp2;
+ bevp2++;
+ }
+ /* niet cyclic gevallen corrigeren */
+ if(bl->poly== -1) {
+ if(bl->nr>2) {
+ bevp= (BevPoint *)(bl+1);
+ bevp1= bevp+1;
+ bevp->sina= bevp1->sina;
+ bevp->cosa= bevp1->cosa;
+ Mat3CpyMat3(bevp->mat, bevp1->mat);
+ bevp= (BevPoint *)(bl+1);
+ bevp+= (bl->nr-1);
+ bevp1= bevp-1;
+ bevp->sina= bevp1->sina;
+ bevp->cosa= bevp1->cosa;
+ Mat3CpyMat3(bevp->mat, bevp1->mat);
+ }
+ }
+ }
+ bl= bl->next;
+ }
+}
+
+/* ****************** HANDLES ************** */
+
+/*
+ * handlecodes:
+ * 1: niets, 1:auto, 2:vector, 3:aligned
+ */
+
+
+void calchandleNurb(BezTriple *bezt,BezTriple *prev, BezTriple *next, int mode)
+{
+ float *p1,*p2,*p3,pt[3];
+ float dx1,dy1,dz1,dx,dy,dz,vx,vy,vz,len,len1,len2;
+
+ if(bezt->h1==0 && bezt->h2==0) return;
+
+ p2= bezt->vec[1];
+
+ if(prev==0) {
+ p3= next->vec[1];
+ pt[0]= 2*p2[0]- p3[0];
+ pt[1]= 2*p2[1]- p3[1];
+ pt[2]= 2*p2[2]- p3[2];
+ p1= pt;
+ }
+ else p1= prev->vec[1];
+
+ if(next==0) {
+ pt[0]= 2*p2[0]- p1[0];
+ pt[1]= 2*p2[1]- p1[1];
+ pt[2]= 2*p2[2]- p1[2];
+ p3= pt;
+ }
+ else p3= next->vec[1];
+
+ if(mode && bezt->h1==HD_AUTO && prev) {
+ dx= p2[0] - (p1[0]+p1[3])/2.0f;
+ dy= p2[1] - (p1[1]+p1[4])/2.0f;
+ dz= p2[2] - (p1[2]+p1[5])/2.0f;
+ }
+ else {
+ dx= p2[0]- p1[0];
+ dy= p2[1]- p1[1];
+ dz= p2[2]- p1[2];
+ }
+ len1= (float)sqrt(dx*dx+dy*dy+dz*dz);
+
+ if(mode && bezt->h2==HD_AUTO && next) {
+ dx1= (p3[0]+p3[-3])/2.0f - p2[0];
+ dy1= (p3[1]+p3[-2])/2.0f - p2[1];
+ dz1= (p3[2]+p3[-1])/2.0f - p2[2];
+ }
+ else {
+ dx1= p3[0]- p2[0];
+ dy1= p3[1]- p2[1];
+ dz1= p3[2]- p2[2];
+ }
+ len2= (float)sqrt(dx1*dx1+dy1*dy1+dz1*dz1);
+
+ if(len1==0.0f) len1=1.0f;
+ if(len2==0.0f) len2=1.0f;
+
+
+ if(bezt->h1==HD_AUTO || bezt->h2==HD_AUTO) { /* auto */
+ vx= dx1/len2 + dx/len1;
+ vy= dy1/len2 + dy/len1;
+ vz= dz1/len2 + dz/len1;
+ len= 2.71f*(float)sqrt(vx*vx + vy*vy + vz*vz);
+ if(len!=0.0f) {
+
+ if(len1>5.0f*len2) len1= 5.0f*len2;
+ if(len2>5.0f*len1) len2= 5.0f*len1;
+
+ if(bezt->h1==HD_AUTO) {
+ len1/=len;
+ *(p2-3)= *p2-vx*len1;
+ *(p2-2)= *(p2+1)-vy*len1;
+ *(p2-1)= *(p2+2)-vz*len1;
+ }
+ if(bezt->h2==HD_AUTO) {
+ len2/=len;
+ *(p2+3)= *p2+vx*len2;
+ *(p2+4)= *(p2+1)+vy*len2;
+ *(p2+5)= *(p2+2)+vz*len2;
+ }
+ }
+ }
+
+ if(bezt->h1==HD_VECT) { /* vector */
+ dx/=3.0;
+ dy/=3.0;
+ dz/=3.0;
+ *(p2-3)= *p2-dx;
+ *(p2-2)= *(p2+1)-dy;
+ *(p2-1)= *(p2+2)-dz;
+ }
+ if(bezt->h2==HD_VECT) {
+ dx1/=3.0;
+ dy1/=3.0;
+ dz1/=3.0;
+ *(p2+3)= *p2+dx1;
+ *(p2+4)= *(p2+1)+dy1;
+ *(p2+5)= *(p2+2)+dz1;
+ }
+
+ len2= VecLenf(p2, p2+3);
+ len1= VecLenf(p2, p2-3);
+ if(len1==0.0) len1=1.0;
+ if(len2==0.0) len2=1.0;
+ if(bezt->f1 & 1) { /* volgorde van berekenen */
+ if(bezt->h2==HD_ALIGN) { /* aligned */
+ len= len2/len1;
+ p2[3]= p2[0]+len*(p2[0]-p2[-3]);
+ p2[4]= p2[1]+len*(p2[1]-p2[-2]);
+ p2[5]= p2[2]+len*(p2[2]-p2[-1]);
+ }
+ if(bezt->h1==HD_ALIGN) {
+ len= len1/len2;
+ p2[-3]= p2[0]+len*(p2[0]-p2[3]);
+ p2[-2]= p2[1]+len*(p2[1]-p2[4]);
+ p2[-1]= p2[2]+len*(p2[2]-p2[5]);
+ }
+ }
+ else {
+ if(bezt->h1==HD_ALIGN) {
+ len= len1/len2;
+ p2[-3]= p2[0]+len*(p2[0]-p2[3]);
+ p2[-2]= p2[1]+len*(p2[1]-p2[4]);
+ p2[-1]= p2[2]+len*(p2[2]-p2[5]);
+ }
+ if(bezt->h2==HD_ALIGN) { /* aligned */
+ len= len2/len1;
+ p2[3]= p2[0]+len*(p2[0]-p2[-3]);
+ p2[4]= p2[1]+len*(p2[1]-p2[-2]);
+ p2[5]= p2[2]+len*(p2[2]-p2[-1]);
+ }
+ }
+}
+
+void calchandlesNurb(Nurb *nu) /* wel eerst (zonodig) de handlevlaggen zetten */
+{
+ BezTriple *bezt, *prev, *next;
+ short a;
+
+ if((nu->type & 7)!=1) return;
+ if(nu->pntsu<2) return;
+
+ a= nu->pntsu;
+ bezt= nu->bezt;
+ if(nu->flagu & 1) prev= bezt+(a-1);
+ else prev= 0;
+ next= bezt+1;
+
+ while(a--) {
+ calchandleNurb(bezt, prev, next, 0);
+ prev= bezt;
+ if(a==1) {
+ if(nu->flagu & 1) next= nu->bezt;
+ else next= 0;
+ }
+ else next++;
+
+ bezt++;
+ }
+}
+
+
+void testhandlesNurb(Nurb *nu)
+{
+ /* Te gebruiken als er iets an de handles is veranderd.
+ * Loopt alle BezTriples af met de volgende regels:
+ * FASE 1: types veranderen?
+ * Autocalchandles: worden ligned als NOT(000 || 111)
+ * Vectorhandles worden 'niets' als (selected en andere niet)
+ * FASE 2: handles herbereken
+ */
+ BezTriple *bezt;
+ short flag, a;
+
+ if((nu->type & 7)!=CU_BEZIER) return;
+
+ bezt= nu->bezt;
+ a= nu->pntsu;
+ while(a--) {
+ flag= 0;
+ if(bezt->f1 & 1) flag++;
+ if(bezt->f2 & 1) flag += 2;
+ if(bezt->f3 & 1) flag += 4;
+
+ if( !(flag==0 || flag==7) ) {
+ if(bezt->h1==HD_AUTO) { /* auto */
+ bezt->h1= HD_ALIGN;
+ }
+ if(bezt->h2==HD_AUTO) { /* auto */
+ bezt->h2= HD_ALIGN;
+ }
+
+ if(bezt->h1==HD_VECT) { /* vector */
+ if(flag < 4) bezt->h1= 0;
+ }
+ if(bezt->h2==HD_VECT) { /* vector */
+ if( flag > 3) bezt->h2= 0;
+ }
+ }
+ bezt++;
+ }
+
+ calchandlesNurb(nu);
+}
+
+void autocalchandlesNurb(Nurb *nu, int flag)
+{
+ /* Kijkt naar de coordinaten van de handles en berekent de soort */
+
+ BezTriple *bezt2, *bezt1, *bezt0;
+ int i, align, leftsmall, rightsmall;
+
+ if(nu==0 || nu->bezt==0) return;
+
+ bezt2 = nu->bezt;
+ bezt1 = bezt2 + (nu->pntsu-1);
+ bezt0 = bezt1 - 1;
+ i = nu->pntsu;
+
+ while(i--) {
+
+ align= leftsmall= rightsmall= 0;
+
+ /* linker handle: */
+ if(flag==0 || (bezt1->f1 & flag) ) {
+ bezt1->h1= 0;
+ /* afstand te klein: vectorhandle */
+ if( VecLenf( bezt1->vec[1], bezt0->vec[1] ) < 0.0001) {
+ bezt1->h1= HD_VECT;
+ leftsmall= 1;
+ }
+ else {
+ /* aligned handle? */
+ if(DistVL2Dfl(bezt1->vec[1], bezt1->vec[0], bezt1->vec[2]) < 0.0001) {
+ align= 1;
+ bezt1->h1= HD_ALIGN;
+ }
+ /* of toch vector handle? */
+ if(DistVL2Dfl(bezt1->vec[0], bezt1->vec[1], bezt0->vec[1]) < 0.0001)
+ bezt1->h1= HD_VECT;
+
+ }
+ }
+ /* rechter handle: */
+ if(flag==0 || (bezt1->f3 & flag) ) {
+ bezt1->h2= 0;
+ /* afstand te klein: vectorhandle */
+ if( VecLenf( bezt1->vec[1], bezt2->vec[1] ) < 0.0001) {
+ bezt1->h2= HD_VECT;
+ rightsmall= 1;
+ }
+ else {
+ /* aligned handle? */
+ if(align) bezt1->h2= HD_ALIGN;
+
+ /* of toch vector handle? */
+ if(DistVL2Dfl(bezt1->vec[2], bezt1->vec[1], bezt2->vec[1]) < 0.0001)
+ bezt1->h2= HD_VECT;
+
+ }
+ }
+ if(leftsmall && bezt1->h2==HD_ALIGN) bezt1->h2= 0;
+ if(rightsmall && bezt1->h1==HD_ALIGN) bezt1->h1= 0;
+
+ /* onzalige combinatie: */
+ if(bezt1->h1==HD_ALIGN && bezt1->h2==HD_VECT) bezt1->h1= 0;
+ if(bezt1->h2==HD_ALIGN && bezt1->h1==HD_VECT) bezt1->h2= 0;
+
+ bezt0= bezt1;
+ bezt1= bezt2;
+ bezt2++;
+ }
+
+ calchandlesNurb(nu);
+}
+
+void autocalchandlesNurb_all(int flag)
+{
+ Nurb *nu;
+
+ nu= editNurb.first;
+ while(nu) {
+ autocalchandlesNurb(nu, flag);
+ nu= nu->next;
+ }
+}
+
+void sethandlesNurb(short code)
+{
+ /* code==1: set autohandle */
+ /* code==2: set vectorhandle */
+ /* als code==3 (HD_ALIGN) toggelt het, vectorhandles worden HD_FREE */
+ Nurb *nu;
+ BezTriple *bezt;
+ short a, ok=0;
+
+ if(code==1 || code==2) {
+ nu= editNurb.first;
+ while(nu) {
+ if( (nu->type & 7)==1) {
+ bezt= nu->bezt;
+ a= nu->pntsu;
+ while(a--) {
+ if(bezt->f1 || bezt->f3) {
+ if(bezt->f1) bezt->h1= code;
+ if(bezt->f3) bezt->h2= code;
+ if(bezt->h1!=bezt->h2) {
+ if ELEM(bezt->h1, HD_ALIGN, HD_AUTO) bezt->h1= HD_FREE;
+ if ELEM(bezt->h2, HD_ALIGN, HD_AUTO) bezt->h2= HD_FREE;
+ }
+ }
+ bezt++;
+ }
+ calchandlesNurb(nu);
+ }
+ nu= nu->next;
+ }
+ }
+ else {
+ /* is er 1 handle NIET vrij: alles vrijmaken, else ALIGNED maken */
+
+ nu= editNurb.first;
+ while(nu) {
+ if( (nu->type & 7)==1) {
+ bezt= nu->bezt;
+ a= nu->pntsu;
+ while(a--) {
+ if(bezt->f1 && bezt->h1) ok= 1;
+ if(bezt->f3 && bezt->h2) ok= 1;
+ if(ok) break;
+ bezt++;
+ }
+ }
+ nu= nu->next;
+ }
+ if(ok) ok= HD_FREE;
+ else ok= HD_ALIGN;
+
+ nu= editNurb.first;
+ while(nu) {
+ if( (nu->type & 7)==1) {
+ bezt= nu->bezt;
+ a= nu->pntsu;
+ while(a--) {
+ if(bezt->f1) bezt->h1= ok;
+ if(bezt->f3 ) bezt->h2= ok;
+
+ bezt++;
+ }
+ calchandlesNurb(nu);
+ }
+ nu= nu->next;
+ }
+ }
+}
+
+void swapdata(void *adr1, void *adr2, int len)
+{
+
+ if(len<=0) return;
+
+ if(len<65) {
+ char adr[64];
+
+ memcpy(adr, adr1, len);
+ memcpy(adr1, adr2, len);
+ memcpy(adr2, adr, len);
+ }
+ else {
+ char *adr;
+
+ adr= (char *)malloc(len);
+ memcpy(adr, adr1, len);
+ memcpy(adr1, adr2, len);
+ memcpy(adr2, adr, len);
+ free(adr);
+ }
+}
+
+void switchdirectionNurb(Nurb *nu)
+{
+ BezTriple *bezt1, *bezt2;
+ BPoint *bp1, *bp2;
+ float *fp1, *fp2, *tempf;
+ int a, b;
+
+ if(nu->pntsu==1 && nu->pntsv==1) return;
+
+ if((nu->type & 7)==CU_BEZIER) {
+ a= nu->pntsu;
+ bezt1= nu->bezt;
+ bezt2= bezt1+(a-1);
+ if(a & 1) a+= 1; /* bij oneven ook van middelste inhoud swappen */
+ a/= 2;
+ while(a>0) {
+ if(bezt1!=bezt2) SWAP(BezTriple, *bezt1, *bezt2);
+
+ swapdata(bezt1->vec[0], bezt1->vec[2], 12);
+ if(bezt1!=bezt2) swapdata(bezt2->vec[0], bezt2->vec[2], 12);
+
+ SWAP(char, bezt1->h1, bezt1->h2);
+ SWAP(short, bezt1->f1, bezt1->f3);
+
+ if(bezt1!=bezt2) {
+ SWAP(char, bezt2->h1, bezt2->h2);
+ SWAP(short, bezt2->f1, bezt2->f3);
+ bezt1->alfa= -bezt1->alfa;
+ bezt2->alfa= -bezt2->alfa;
+ }
+ a--;
+ bezt1++;
+ bezt2--;
+ }
+ }
+ else if(nu->pntsv==1) {
+ a= nu->pntsu;
+ bp1= nu->bp;
+ bp2= bp1+(a-1);
+ a/= 2;
+ while(bp1!=bp2 && a>0) {
+ SWAP(BPoint, *bp1, *bp2);
+ a--;
+ bp1->alfa= -bp1->alfa;
+ bp2->alfa= -bp2->alfa;
+ bp1++;
+ bp2--;
+ }
+ if((nu->type & 7)==CU_NURBS) {
+ /* de knots omkeren */
+ a= KNOTSU(nu);
+ fp1= nu->knotsu;
+ fp2= fp1+(a-1);
+ a/= 2;
+ while(fp1!=fp2 && a>0) {
+ SWAP(float, *fp1, *fp2);
+ a--;
+ fp1++;
+ fp2--;
+ }
+ /* en weer in stijgende lijn maken */
+ a= KNOTSU(nu);
+ fp1= nu->knotsu;
+ fp2=tempf= MEM_mallocN(sizeof(float)*a, "switchdirect");
+ while(a--) {
+ fp2[0]= fabs(fp1[1]-fp1[0]);
+ fp1++;
+ fp2++;
+ }
+
+ a= KNOTSU(nu)-1;
+ fp1= nu->knotsu;
+ fp2= tempf;
+ fp1[0]= 0.0;
+ fp1++;
+ while(a--) {
+ fp1[0]= fp1[-1]+fp2[0];
+ fp1++;
+ fp2++;
+ }
+ MEM_freeN(tempf);
+ }
+ }
+ else {
+
+ for(b=0; b<nu->pntsv; b++) {
+
+ bp1= nu->bp+b*nu->pntsu;
+ a= nu->pntsu;
+ bp2= bp1+(a-1);
+ a/= 2;
+
+ while(bp1!=bp2 && a>0) {
+ SWAP(BPoint, *bp1, *bp2);
+ a--;
+ bp1++;
+ bp2--;
+ }
+ }
+ }
+}
diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c
new file mode 100644
index 00000000000..76983001bb6
--- /dev/null
+++ b/source/blender/blenkernel/intern/deform.c
@@ -0,0 +1,120 @@
+/* deform.c June 2001
+ *
+ * support for deformation groups
+ *
+ * Reevan McKay
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+
+#include "DNA_object_types.h"
+
+#include "BKE_deform.h"
+
+
+void color_temperature (float input, unsigned char *r, unsigned char *g, unsigned char *b)
+{
+
+ /* blue to red */
+
+ float fr = (float)(*r);
+ float fg = (float)(*g);
+ float fb = (float)(*b);
+
+ if (input < 0.0F)
+ input = 0.0F;
+
+ if (input > 1.0F)
+ input = 1.0F;
+
+ if (input<=0.25f){
+ fr=0.0f;
+ fg=255.0f * (input*4.0f);
+ fb=255.0f;
+ }
+ else if (input<=0.50f){
+ fr=0.0f;
+ fg=255.0f;
+ fb=255.0f * (1.0f-((input-0.25f)*4.0f));
+ }
+ else if (input<=0.75){
+ fr=255.0f * ((input-0.50f)*4.0f);
+ fg=255.0f;
+ fb=0.0f;
+ }
+ else if (input<=1.0){
+ fr=255.0f;
+ fg=255.0f * (1.0f-((input-0.75f)*4.0f));
+ fb=0.0f;
+ }
+
+ (*r) = (unsigned char)(fr * ((input/2.0f)+0.5f));
+ (*g) = (unsigned char)(fg * ((input/2.0f)+0.5f));
+ (*b) = (unsigned char)(fb * ((input/2.0f)+0.5f));
+
+
+};
+
+void copy_defgroups(ListBase *outbase, ListBase *inbase)
+{
+ bDeformGroup *defgroup, *defgroupn;
+
+ outbase->first= outbase->last= 0;
+
+ for (defgroup = inbase->first; defgroup; defgroup=defgroup->next){
+ defgroupn= copy_defgroup(defgroup);
+ BLI_addtail(outbase, defgroupn);
+ }
+}
+
+bDeformGroup* copy_defgroup (bDeformGroup *ingroup)
+{
+ bDeformGroup *outgroup;
+
+ if (!ingroup)
+ return NULL;
+
+ outgroup=MEM_callocN(sizeof(bDeformGroup), "deformGroup");
+
+ /* For now, just copy everything over. */
+ memcpy (outgroup, ingroup, sizeof(bDeformGroup));
+
+ outgroup->next=outgroup->prev=NULL;
+
+ return outgroup;
+}
+
diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c
new file mode 100644
index 00000000000..b9f9d59c5e3
--- /dev/null
+++ b/source/blender/blenkernel/intern/displist.c
@@ -0,0 +1,2085 @@
+
+/* displist.c GRAPHICS
+ *
+ *
+ * maart 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 <math.h>
+#include <stdio.h>
+#include <string.h>
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+#include "MEM_guardedalloc.h"
+
+#include "nla.h" /* For __NLA: Please do not remove yet */
+
+#include "IMB_imbuf_types.h"
+
+#include "DNA_texture_types.h"
+#include "DNA_meta_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_listBase.h"
+#include "DNA_lamp_types.h"
+#include "DNA_object_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_image_types.h"
+#include "DNA_material_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_lattice_types.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+
+#include "BKE_bad_level_calls.h"
+#include "BKE_utildefines.h"
+#include "BKE_global.h"
+#include "BKE_displist.h"
+#include "BKE_object.h"
+#include "BKE_world.h"
+#include "BKE_mesh.h"
+#include "BKE_effect.h"
+#include "BKE_mball.h"
+#include "BKE_material.h"
+#include "BKE_curve.h"
+#include "BKE_anim.h"
+#include "BKE_screen.h"
+#include "BKE_texture.h"
+#include "BKE_library.h"
+#include "BKE_font.h"
+#include "BKE_lattice.h"
+#include "BKE_scene.h"
+#include "BKE_subsurf.h"
+
+/***/
+
+typedef struct _FastLamp FastLamp;
+struct _FastLamp {
+ FastLamp *next;
+
+ short type, mode, lay, rt;
+ float co[3];
+ float vec[3];
+ float dist, distkw, att1, att2, spotsi, spotbl, r, g, b;
+};
+
+/***/
+
+static FastLamp *fastlamplist= NULL;
+static float fviewmat[4][4];
+
+static void displistmesh_free(DispListMesh *dlm) {
+ // also check on mvert and mface, can be NULL after decimator (ton)
+ if( dlm->mvert) MEM_freeN(dlm->mvert);
+ if (dlm->mface) MEM_freeN(dlm->mface);
+ if (dlm->mcol) MEM_freeN(dlm->mcol);
+ if (dlm->tface) MEM_freeN(dlm->tface);
+ MEM_freeN(dlm);
+}
+
+static DispListMesh *displistmesh_copy(DispListMesh *odlm) {
+ DispListMesh *ndlm= MEM_dupallocN(odlm);
+ ndlm->mvert= MEM_dupallocN(odlm->mvert);
+ ndlm->mface= MEM_dupallocN(odlm->mface);
+ if (odlm->mcol) ndlm->mcol= MEM_dupallocN(odlm->mcol);
+ if (odlm->tface) ndlm->tface= MEM_dupallocN(odlm->tface);
+
+ return ndlm;
+}
+
+void free_disp_elem(DispList *dl)
+{
+ if(dl) {
+ if(dl->verts) MEM_freeN(dl->verts);
+ if(dl->nors) MEM_freeN(dl->nors);
+ if(dl->index) MEM_freeN(dl->index);
+ if(dl->col1) MEM_freeN(dl->col1);
+ if(dl->col2) MEM_freeN(dl->col2);
+ if(dl->mesh) displistmesh_free(dl->mesh);
+ MEM_freeN(dl);
+ }
+}
+
+void freedisplist(ListBase *lb)
+{
+ DispList *dl;
+
+ dl= lb->first;
+ while(dl) {
+ BLI_remlink(lb, dl);
+ free_disp_elem(dl);
+ dl= lb->first;
+ }
+}
+
+void free_displist_by_type(ListBase *lb, int type)
+{
+ DispList *dl;
+
+ for (dl= lb->first; dl; ) {
+ DispList *next= dl->next;
+
+ if (dl->type==type) {
+ BLI_remlink(lb, dl);
+ free_disp_elem(dl);
+ }
+
+ dl= next;
+ }
+}
+
+DispList *find_displist_create(ListBase *lb, int type)
+{
+ DispList *dl;
+
+ dl= lb->first;
+ while(dl) {
+ if(dl->type==type) return dl;
+ dl= dl->next;
+ }
+
+ dl= MEM_callocN(sizeof(DispList), "find_disp");
+ dl->type= type;
+ BLI_addtail(lb, dl);
+
+ return dl;
+}
+
+DispList *find_displist(ListBase *lb, int type)
+{
+ DispList *dl;
+
+ dl= lb->first;
+ while(dl) {
+ if(dl->type==type) return dl;
+ dl= dl->next;
+ }
+
+ return 0;
+}
+
+void copy_displist(ListBase *lbn, ListBase *lb)
+{
+ DispList *dln, *dl;
+
+ lbn->first= lbn->last= 0;
+
+ dl= lb->first;
+ while(dl) {
+
+ dln= MEM_dupallocN(dl);
+ BLI_addtail(lbn, dln);
+ dln->verts= MEM_dupallocN(dl->verts);
+ dln->nors= MEM_dupallocN(dl->nors);
+ dln->index= MEM_dupallocN(dl->index);
+ dln->col1= MEM_dupallocN(dl->col1);
+ dln->col2= MEM_dupallocN(dl->col2);
+ if (dl->mesh)
+ dln->mesh= displistmesh_copy(dl->mesh);
+
+ dl= dl->next;
+ }
+}
+
+static void initfastshade(void)
+{
+ Base *base;
+ Object *ob;
+ Lamp *la;
+ FastLamp *fl;
+ float mat[4][4];
+
+ R.vlr= 0;
+
+ init_render_world();
+
+ if(fastlamplist) return;
+ if(G.scene->camera==0) G.scene->camera= scene_find_camera(G.scene);
+ if(G.scene->camera==0) return;
+
+ /* uit roteerscene gejat */
+ where_is_object(G.scene->camera);
+ Mat4CpyMat4(R.viewinv, G.scene->camera->obmat);
+ Mat4Ortho(R.viewinv);
+ Mat4Invert(fviewmat, R.viewinv);
+
+
+ /* initrendertexture(); */
+
+ base= G.scene->base.first;
+ while(base) {
+ ob= base->object;
+ if( ob->type==OB_LAMP && (base->lay & G.scene->lay)) {
+
+ Mat4MulMat4(mat, ob->obmat, fviewmat);
+
+ la= ob->data;
+ fl= MEM_mallocN(sizeof(FastLamp), "initfastshade2");
+
+ fl->next= fastlamplist;
+ fastlamplist= fl;
+
+ fl->type= la->type;
+ fl->mode= la->mode;
+ fl->lay= base->lay;
+
+ fl->vec[0]= mat[2][0];
+ fl->vec[1]= mat[2][1];
+ fl->vec[2]= mat[2][2];
+ Normalise(fl->vec);
+
+ fl->co[0]= mat[3][0];
+ fl->co[1]= mat[3][1];
+ fl->co[2]= mat[3][2];
+
+ fl->dist= la->dist;
+ fl->distkw= fl->dist*fl->dist;
+ fl->att1= la->att1;
+ fl->att2= la->att2;
+
+ fl->spotsi= (float)cos( M_PI*la->spotsize/360.0 );
+ fl->spotbl= (1.0f-fl->spotsi)*la->spotblend;
+
+ fl->r= la->energy*la->r;
+ fl->g= la->energy*la->g;
+ fl->b= la->energy*la->b;
+ }
+
+ if(base->next==0 && G.scene->set && base==G.scene->base.last) base= G.scene->set->base.first;
+ else base= base->next;
+ }
+}
+
+
+void freefastshade()
+{
+ while (fastlamplist) {
+ FastLamp *fl= fastlamplist;
+ fastlamplist= fl->next;
+
+ MEM_freeN(fl);
+ }
+}
+
+
+static void fastshade(float *co, float *nor, float *orco, Material *ma, char *col1, char *col2, char *vertcol)
+{
+ FastLamp *fl;
+ float i, t, inp, soft, inpr, inpg, inpb, isr=0, isg=0, isb=0, lv[3], lampdist, ld;
+ float inpr1, inpg1, inpb1, isr1=0, isg1=0, isb1=0;
+ int a, back;
+
+ if(ma==0) return;
+ R.mat= ma;
+ R.matren= ma->ren;
+ ma= R.matren;
+
+ if(ma->mode & MA_VERTEXCOLP) {
+ if(vertcol) {
+ ma->r= vertcol[3]/255.0;
+ ma->g= vertcol[2]/255.0;
+ ma->b= vertcol[1]/255.0;
+ }
+ }
+
+ if(ma->texco) {
+ VECCOPY(R.lo, orco);
+ VECCOPY(R.vn, nor);
+
+ if(ma->texco & TEXCO_GLOB) {
+ VECCOPY(R.gl, R.lo);
+ }
+ if(ma->texco & TEXCO_WINDOW) {
+ VECCOPY(R.winco, R.lo);
+ }
+ if(ma->texco & TEXCO_STICKY) {
+ VECCOPY(R.sticky, R.lo);
+ }
+ if(ma->texco & TEXCO_UV) {
+ VECCOPY(R.uv, R.lo);
+ }
+ if(ma->texco & TEXCO_OBJECT) {
+ VECCOPY(R.co, R.lo);
+ }
+ if(ma->texco & TEXCO_NORM) {
+ VECCOPY(R.orn, R.vn);
+ }
+ if(ma->texco & TEXCO_REFL) {
+
+ inp= 2.0*(R.vn[2]);
+ R.ref[0]= (inp*R.vn[0]);
+ R.ref[1]= (inp*R.vn[1]);
+ R.ref[2]= (-1.0+inp*R.vn[2]);
+ }
+
+ if(ma->mode & MA_VERTEXCOLP) {
+ R.mat->r= ma->r;
+ R.mat->g= ma->g;
+ R.mat->b= ma->b;
+ }
+ do_material_tex();
+ }
+
+ if(ma->mode & MA_SHLESS) {
+ if(vertcol && (ma->mode & (MA_VERTEXCOL+MA_VERTEXCOLP))== MA_VERTEXCOL ) {
+ col1[3]= vertcol[3]*ma->r;
+ col1[2]= vertcol[2]*ma->g;
+ col1[1]= vertcol[1]*ma->b;
+ }
+ else {
+ col1[3]= (255.0*ma->r);
+ col1[2]= (255.0*ma->g);
+ col1[1]= (255.0*ma->b);
+ }
+ if(col2) {
+ col2[3]= col1[3];
+ col2[2]= col1[2];
+ col2[1]= col1[1];
+ }
+ return;
+ }
+
+ if( vertcol && (ma->mode & (MA_VERTEXCOL+MA_VERTEXCOLP))== MA_VERTEXCOL ) {
+ inpr= inpr1= ma->emit+vertcol[3]/255.0;
+ inpg= inpg1= ma->emit+vertcol[2]/255.0;
+ inpb= inpb1= ma->emit+vertcol[1]/255.0;
+ }
+ else {
+ inpr= inpg= inpb= inpr1= inpg1= inpb1= ma->emit;
+ }
+
+ /* col[0]= (255.0*ma->r); */
+ /* col[1]= (255.0*ma->g); */
+ /* col[2]= (255.0*ma->b); */
+
+ for (fl= fastlamplist; fl; fl= fl->next) {
+ /* if(fl->mode & LA_LAYER) if((fl->lay & ma->lay)==0) continue; */
+
+ if(fl->type==LA_SUN || fl->type==LA_HEMI) {
+ VECCOPY(lv, fl->vec);
+ lampdist= 1.0;
+ }
+ else {
+ lv[0]= fl->co[0] - co[0];
+ lv[1]= fl->co[1] - co[1];
+ lv[2]= fl->co[2] - co[2];
+ ld= sqrt(lv[0]*lv[0]+lv[1]*lv[1]+lv[2]*lv[2]);
+ lv[0]/=ld;
+ lv[1]/=ld;
+ lv[2]/=ld;
+
+ if(fl->mode & LA_QUAD) {
+ t= 1.0;
+ if(fl->att1>0.0)
+ t= fl->dist/(fl->dist+fl->att1*ld);
+ if(fl->att2>0.0)
+ t*= fl->distkw/(fl->distkw+fl->att2*ld*ld);
+
+ lampdist= t;
+ }
+ else {
+ lampdist= (fl->dist/(fl->dist+ld));
+ }
+
+ if(fl->mode & LA_SPHERE) {
+ t= fl->dist - ld;
+ if(t<0.0) continue;
+
+ t/= fl->dist;
+ lampdist*= (t);
+ }
+ }
+
+ if(fl->type==LA_SPOT) {
+ inp= lv[0]*fl->vec[0]+lv[1]*fl->vec[1]+lv[2]*fl->vec[2];
+ if(inp<fl->spotsi) continue;
+ else {
+ t= inp-fl->spotsi;
+ i= 1.0;
+ soft= 1.0;
+ if(t<fl->spotbl && fl->spotbl!=0.0) {
+ /* zachte gebied */
+ i= t/fl->spotbl;
+ t= i*i;
+ soft= (3.0*t-2.0*t*i);
+ inp*= soft;
+ }
+
+ lampdist*=inp;
+ }
+ }
+
+ inp= nor[0]*lv[0]+ nor[1]*lv[1]+ nor[2]*lv[2];
+
+ back= 0;
+ if(inp<0.0) {
+ back= 1;
+ inp= -inp;
+ }
+ inp*= lampdist*ma->ref;
+
+ if(back==0) {
+ inpr+= inp*fl->r;
+ inpg+= inp*fl->g;
+ inpb+= inp*fl->b;
+ } else if(col2) {
+ inpr1+= inp*fl->r;
+ inpg1+= inp*fl->g;
+ inpb1+= inp*fl->b;
+ }
+ if(ma->spec) {
+
+ lv[2]+= 1.0;
+ Normalise(lv);
+ t= nor[0]*lv[0]+nor[1]*lv[1]+nor[2]*lv[2];
+ if(t>0) {
+ t= ma->spec*lampdist*RE_Spec(t, ma->har);
+ if(back==0) {
+ isr+= t*(fl->r * ma->specr);
+ isg+= t*(fl->g * ma->specg);
+ isb+= t*(fl->b * ma->specb);
+ }
+ else if(col2) {
+ isr1+= t*(fl->r * ma->specr);
+ isg1+= t*(fl->g * ma->specg);
+ isb1+= t*(fl->b * ma->specb);
+ }
+ }
+ }
+
+ }
+
+ a= 256*(inpr*ma->r + ma->ambr +isr);
+ if(a>255) col1[3]= 255;
+ else col1[3]= a;
+ a= 256*(inpg*ma->g + ma->ambg +isg);
+ if(a>255) col1[2]= 255;
+ else col1[2]= a;
+ a= 256*(inpb*ma->b + ma->ambb +isb);
+ if(a>255) col1[1]= 255;
+ else col1[1]= a;
+
+ if(col2) {
+ a= 256*(inpr1*ma->r + ma->ambr +isr1);
+ if(a>255) col2[3]= 255;
+ else col2[3]= a;
+ a= 256*(inpr1*ma->g + ma->ambg +isg1);
+ if(a>255) col2[2]= 255;
+ else col2[2]= a;
+ a= 256*(inpr1*ma->b + ma->ambb +isb1);
+ if(a>255) col2[1]= 255;
+ else col2[1]= a;
+ }
+
+}
+
+void addnormalsDispList(Object *ob, ListBase *lb)
+{
+ DispList *dl = NULL;
+ Mesh *me;
+ MVert *ve1, *ve2, *ve3, *ve4;
+ MFace *mface;
+ float *vdata, *ndata, nor[3];
+ float *v1, *v2, *v3, *v4;
+ float *n1, *n2, *n3, *n4;
+ int a, b, p1, p2, p3, p4;
+
+
+ if(ob->type==OB_MESH) {
+
+ me= get_mesh(ob);
+
+ if (mesh_uses_displist(me)) {
+ DispList *dl= find_displist(&me->disp, DL_MESH);
+
+ if (dl && !dl->nors) {
+ DispListMesh *dlm= dl->mesh;
+ int i;
+
+ dl->nors= MEM_mallocN(sizeof(*dl->nors)*3*dlm->totface, "meshnormals");
+
+ for (i=0; i<dlm->totface; i++) {
+ MFaceInt *mf= &dlm->mface[i];
+ float *no= &dl->nors[i*3];
+
+ if (mf->v3) {
+ if (mf->v4)
+ CalcNormFloat4(dlm->mvert[mf->v1].co, dlm->mvert[mf->v2].co, dlm->mvert[mf->v3].co, dlm->mvert[mf->v4].co, no);
+ else
+ CalcNormFloat(dlm->mvert[mf->v1].co, dlm->mvert[mf->v2].co, dlm->mvert[mf->v3].co, no);
+ }
+ }
+ }
+ } else {
+ if(me->totface==0) return;
+
+ if(me->disp.first==0) {
+ dl= MEM_callocN(sizeof(DispList), "meshdisp");
+ dl->type= DL_NORS;
+ dl->parts= 1;
+ dl->nr= me->totface;
+ BLI_addtail(&me->disp, dl);
+ }
+
+ if(dl->nors==0) {
+ dl->nors= MEM_mallocN(sizeof(float)*3*me->totface, "meshnormals");
+ n1= dl->nors;
+ mface= me->mface;
+ a= me->totface;
+ while(a--) {
+ if(mface->v3) {
+ ve1= me->mvert+mface->v1;
+ ve2= me->mvert+mface->v2;
+ ve3= me->mvert+mface->v3;
+ ve4= me->mvert+mface->v4;
+
+ if(mface->v4) CalcNormFloat4(ve1->co, ve2->co, ve3->co, ve4->co, n1);
+ else CalcNormFloat(ve1->co, ve2->co, ve3->co, n1);
+ }
+ n1+= 3;
+ mface++;
+ }
+ }
+ }
+
+ return;
+ }
+
+ dl= lb->first;
+
+ while(dl) {
+ if(dl->type==DL_INDEX3) {
+ if(dl->nors==0) {
+ dl->nors= MEM_callocN(sizeof(float)*3, "dlnors");
+ if(dl->verts[2]<0.0) dl->nors[2]= -1.0;
+ else dl->nors[2]= 1.0;
+ }
+ }
+ else if(dl->type==DL_SURF) {
+ if(dl->nors==0) {
+ dl->nors= MEM_callocN(sizeof(float)*3*dl->nr*dl->parts, "dlnors");
+
+ vdata= dl->verts;
+ ndata= dl->nors;
+
+ for(a=0; a<dl->parts; a++) {
+
+ DL_SURFINDEX(dl->flag & 1, dl->flag & 2, dl->nr, dl->parts);
+
+ v1= vdata+ 3*p1;
+ n1= ndata+ 3*p1;
+ v2= vdata+ 3*p2;
+ n2= ndata+ 3*p2;
+ v3= vdata+ 3*p3;
+ n3= ndata+ 3*p3;
+ v4= vdata+ 3*p4;
+ n4= ndata+ 3*p4;
+
+ for(; b<dl->nr; b++) {
+
+ CalcNormFloat4(v1, v3, v4, v2, nor);
+
+ VecAddf(n1, n1, nor);
+ VecAddf(n2, n2, nor);
+ VecAddf(n3, n3, nor);
+ VecAddf(n4, n4, nor);
+
+ v2= v1; v1+= 3;
+ v4= v3; v3+= 3;
+ n2= n1; n1+= 3;
+ n4= n3; n3+= 3;
+ }
+ }
+ a= dl->parts*dl->nr;
+ v1= ndata;
+ while(a--) {
+ Normalise(v1);
+ v1+= 3;
+ }
+ }
+ }
+ dl= dl->next;
+ }
+}
+
+
+void shadeDispList(Object *ob)
+{
+ MFace *mface;
+ MVert *mvert;
+ DispList *dl, *dlob, *dldeform;
+ Material *ma = NULL;
+ Mesh *me;
+ Curve *cu;
+/* extern Material defmaterial; *//* initrender.c, already in bad lev calls*/
+ float *orco, imat[3][3], tmat[4][4], mat[4][4], vec[3], xn, yn, zn;
+ float *fp, *nor, n1[3];
+ unsigned int *col1, *col2, *vertcol;
+ int a, lastmat= -1, need_orco = 0;
+
+ if(ob->flag & OB_FROMDUPLI) return;
+ initfastshade();
+
+ Mat4MulMat4(mat, ob->obmat, fviewmat);
+
+ Mat4Invert(tmat, mat);
+ Mat3CpyMat4(imat, tmat);
+
+ /* we halen de dl_verts eruit, deform info */
+ dldeform= find_displist(&ob->disp, DL_VERTS);
+ if(dldeform) BLI_remlink(&ob->disp, dldeform);
+
+ /* Metaballs hebben de standaard displist aan het Object zitten */
+ if(ob->type!=OB_MBALL) freedisplist(&ob->disp);
+
+ if((R.flag & R_RENDERING)==0) {
+ need_orco= 0;
+ for(a=0; a<ob->totcol; a++) {
+ ma= give_current_material(ob, a+1);
+ if(ma) {
+ init_render_material(ma);
+ if(ma->ren->texco & TEXCO_ORCO) need_orco= 1;
+ }
+ }
+ }
+ if(ob->type==OB_MESH) {
+
+ me= ob->data;
+
+ if (mesh_uses_displist(me)) {
+ if (need_orco) {
+ make_orco_displist_mesh(ob, me->subdiv);
+ orco= me->orco;
+ }
+
+ dl= me->disp.first;
+ while(dl) {
+ if(dl->type==DL_MESH) {
+ DispListMesh *dlm= dl->mesh;
+ int i;
+
+ dlob= MEM_callocN(sizeof(DispList), "displistshade");
+ BLI_addtail(&ob->disp, dlob);
+ dlob->type= DL_VERTCOL;
+
+ dlob->col1= MEM_mallocN(sizeof(*dlob->col1)*dlm->totface*4, "col1");
+ if (me->flag & ME_TWOSIDED)
+ dlob->col2= MEM_mallocN(sizeof(*dlob->col2)*dlm->totface*4, "col1");
+
+ for (i=0; i<dlm->totface; i++) {
+ MFaceInt *mf= &dlm->mface[i];
+
+ if (mf->v3) {
+ int j, vidx[4], nverts= mf->v4?4:3;
+ unsigned int *col1base= &dlob->col1[i*4];
+ unsigned int *col2base= dlob->col2?&dlob->col2[i*4]:NULL;
+ MCol *mcolbase= dlm->mcol?&dlm->mcol[i*4]:NULL;
+ float nor[3];
+
+ ma= give_current_material(ob, mf->mat_nr+1);
+ if(ma==0) ma= &defmaterial;
+
+ vidx[0]= mf->v1;
+ vidx[1]= mf->v2;
+ vidx[2]= mf->v3;
+ vidx[3]= mf->v4;
+
+ if (mf->v4)
+ CalcNormFloat4(dlm->mvert[mf->v1].co, dlm->mvert[mf->v2].co, dlm->mvert[mf->v3].co, dlm->mvert[mf->v4].co, nor);
+ else
+ CalcNormFloat(dlm->mvert[mf->v1].co, dlm->mvert[mf->v2].co, dlm->mvert[mf->v3].co, nor);
+
+ n1[0]= imat[0][0]*nor[0]+imat[0][1]*nor[1]+imat[0][2]*nor[2];
+ n1[1]= imat[1][0]*nor[0]+imat[1][1]*nor[1]+imat[1][2]*nor[2];
+ n1[2]= imat[2][0]*nor[0]+imat[2][1]*nor[1]+imat[2][2]*nor[2];
+ Normalise(n1);
+
+ for (j=0; j<nverts; j++) {
+ MVert *mv= &dlm->mvert[vidx[j]];
+ unsigned int *col1= &col1base[j];
+ unsigned int *col2= col2base?&col2base[j]:NULL;
+ MCol *mcol= mcolbase?&mcolbase[j]:NULL;
+
+ VECCOPY(vec, mv->co);
+ Mat4MulVecfl(mat, vec);
+
+ if (need_orco && orco)
+ fastshade(vec, n1, &orco[vidx[j]*3], ma, (char *)col1, (char*)col2, (char*) mcol);
+ else
+ fastshade(vec, n1, mv->co, ma, (char *)col1, (char*)col2, (char*) mcol);
+ }
+ }
+ }
+ }
+ dl= dl->next;
+ }
+
+ if (need_orco && orco) {
+ MEM_freeN(me->orco);
+ me->orco= NULL;
+ }
+ }
+ else if(me->totvert>0) {
+
+ if(me->orco==0 && need_orco) {
+ make_orco_mesh(me);
+ }
+ orco= me->orco;
+ /* ms= me->msticky; */
+
+ dl= me->disp.first;
+ if(dl==0 || dl->nors==0) addnormalsDispList(ob, &me->disp);
+ dl= me->disp.first;
+ if(dl==0 || dl->nors==0) return;
+ nor= dl->nors;
+
+ dl= MEM_callocN(sizeof(DispList), "displistshade");
+ BLI_addtail(&ob->disp, dl);
+ dl->type= DL_VERTCOL;
+ col1= dl->col1= MEM_mallocN(4*sizeof(int)*me->totface, "col1");
+ col2= 0;
+ if(me->tface) tface_to_mcol(me);
+ vertcol= (unsigned int *)me->mcol;
+
+ if( me->flag & ME_TWOSIDED) {
+ col2= dl->col2= MEM_mallocN(4*sizeof(int)*me->totface, "col2");
+ }
+
+ /* even geen puno's */
+ mvert= me->mvert;
+ a= me->totvert;
+ while(FALSE || a--) {
+
+ VECCOPY(vec, mvert->co);
+ Mat4MulVecfl(mat, vec);
+
+ xn= mvert->no[0];
+ yn= mvert->no[1];
+ zn= mvert->no[2];
+
+ /* transpose ! */
+ n1[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn;
+ n1[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn;
+ n1[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn;
+ Normalise(n1);
+
+ mvert++;
+ }
+
+ mface= me->mface;
+ a= me->totface;
+ while(a--) {
+
+ if(mface->v3) {
+
+ /* transpose ! */
+ n1[0]= imat[0][0]*nor[0]+imat[0][1]*nor[1]+imat[0][2]*nor[2];
+ n1[1]= imat[1][0]*nor[0]+imat[1][1]*nor[1]+imat[1][2]*nor[2];
+ n1[2]= imat[2][0]*nor[0]+imat[2][1]*nor[1]+imat[2][2]*nor[2];
+ Normalise(n1);
+
+ if(lastmat!=mface->mat_nr) {
+ ma= give_current_material(ob, mface->mat_nr+1);
+ if(ma==0) ma= &defmaterial;
+ lastmat= mface->mat_nr;
+ }
+
+ mvert= me->mvert+mface->v1;
+ VECCOPY(vec, mvert->co);
+ Mat4MulVecfl(mat, vec);
+
+ if(orco) fastshade(vec, n1, orco+3*mface->v1, ma, (char *)col1, (char *)col2, (char *)vertcol);
+ else fastshade(vec, n1, mvert->co, ma, (char *)col1, (char *)col2, (char *)vertcol);
+ col1++;
+ if(vertcol) vertcol++;
+ if(col2) col2++;
+
+ mvert= me->mvert+mface->v2;
+ VECCOPY(vec, mvert->co);
+ Mat4MulVecfl(mat, vec);
+
+ if(orco) fastshade(vec, n1, orco+3*mface->v2, ma, (char *)col1, (char *)col2, (char *)vertcol);
+ else fastshade(vec, n1, mvert->co, ma, (char *)col1, (char *)col2, (char *)vertcol);
+ col1++;
+ if(vertcol) vertcol++;
+ if(col2) col2++;
+
+ mvert= me->mvert+mface->v3;
+ VECCOPY(vec, mvert->co);
+ Mat4MulVecfl(mat, vec);
+
+ if(orco) fastshade(vec, n1, orco+3*mface->v3, ma, (char *)col1, (char *)col2, (char *)vertcol);
+ else fastshade(vec, n1, mvert->co, ma, (char *)col1, (char *)col2, (char *)vertcol);
+ col1++;
+ if(vertcol) vertcol++;
+ if(col2) col2++;
+
+ if(mface->v4) {
+ mvert= me->mvert+mface->v4;
+ VECCOPY(vec, mvert->co);
+ Mat4MulVecfl(mat, vec);
+
+ if(orco) fastshade(vec, n1, orco+3*mface->v4, ma, (char *)col1, (char *)col2, (char *)vertcol);
+ else fastshade(vec, n1, mvert->co, ma, (char *)col1, (char *)col2, (char *)vertcol);
+ }
+ col1++;
+ if(vertcol) vertcol++;
+ if(col2) col2++;
+
+ }
+ else {
+ col1+=4;
+ if(vertcol) vertcol+=4;
+ if(col2) col2+=4;
+ }
+
+ nor+= 3;
+ mface++;
+ }
+
+ if(me->orco) {
+ MEM_freeN(me->orco);
+ me->orco= 0;
+ }
+ if(me->tface) {
+ MEM_freeN(me->mcol);
+ me->mcol= 0;
+ }
+ }
+ }
+ else if ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT) {
+
+ /* nu hebben we wel de normalen nodig */
+ cu= ob->data;
+ dl= cu->disp.first;
+
+ while(dl) {
+ dlob= MEM_callocN(sizeof(DispList), "displistshade");
+ BLI_addtail(&ob->disp, dlob);
+ dlob->type= DL_VERTCOL;
+ dlob->parts= dl->parts;
+ dlob->nr= dl->nr;
+
+ if(dl->type==DL_INDEX3) {
+ col1= dlob->col1= MEM_mallocN(sizeof(int)*dl->nr, "col1");
+ }
+ else {
+ col1= dlob->col1= MEM_mallocN(sizeof(int)*dl->parts*dl->nr, "col1");
+ }
+
+
+ ma= give_current_material(ob, dl->col+1);
+ if(ma==0) ma= &defmaterial;
+
+ if(dl->type==DL_INDEX3) {
+ if(dl->nors) {
+ /* er is maar 1 normaal */
+ n1[0]= imat[0][0]*dl->nors[0]+imat[0][1]*dl->nors[1]+imat[0][2]*dl->nors[2];
+ n1[1]= imat[1][0]*dl->nors[0]+imat[1][1]*dl->nors[1]+imat[1][2]*dl->nors[2];
+ n1[2]= imat[2][0]*dl->nors[0]+imat[2][1]*dl->nors[1]+imat[2][2]*dl->nors[2];
+ Normalise(n1);
+
+ fp= dl->verts;
+
+ a= dl->nr;
+ while(a--) {
+ VECCOPY(vec, fp);
+ Mat4MulVecfl(mat, vec);
+
+ fastshade(vec, n1, fp, ma, (char *)col1, 0, 0);
+
+ fp+= 3; col1++;
+ }
+ }
+ }
+ else if(dl->type==DL_SURF) {
+ if(dl->nors) {
+ a= dl->nr*dl->parts;
+ fp= dl->verts;
+ nor= dl->nors;
+
+ while(a--) {
+ VECCOPY(vec, fp);
+ Mat4MulVecfl(mat, vec);
+
+ n1[0]= imat[0][0]*nor[0]+imat[0][1]*nor[1]+imat[0][2]*nor[2];
+ n1[1]= imat[1][0]*nor[0]+imat[1][1]*nor[1]+imat[1][2]*nor[2];
+ n1[2]= imat[2][0]*nor[0]+imat[2][1]*nor[1]+imat[2][2]*nor[2];
+ Normalise(n1);
+
+ fastshade(vec, n1, fp, ma, (char *)col1, 0, 0);
+
+ fp+= 3; nor+= 3; col1++;
+ }
+ }
+ }
+ dl= dl->next;
+ }
+ }
+ else if(ob->type==OB_MBALL) {
+ /* normalen zijn er al */
+ dl= ob->disp.first;
+
+ while(dl) {
+
+ if(dl->type==DL_INDEX4) {
+ if(dl->nors) {
+
+ if(dl->col1) MEM_freeN(dl->col1);
+ col1= dl->col1= MEM_mallocN(sizeof(int)*dl->nr, "col1");
+
+ ma= give_current_material(ob, dl->col+1);
+ if(ma==0) ma= &defmaterial;
+
+ fp= dl->verts;
+ nor= dl->nors;
+
+ a= dl->nr;
+ while(a--) {
+ VECCOPY(vec, fp);
+ Mat4MulVecfl(mat, vec);
+
+ /* transpose ! */
+ n1[0]= imat[0][0]*nor[0]+imat[0][1]*nor[1]+imat[0][2]*nor[2];
+ n1[1]= imat[1][0]*nor[0]+imat[1][1]*nor[1]+imat[1][2]*nor[2];
+ n1[2]= imat[2][0]*nor[0]+imat[2][1]*nor[1]+imat[2][2]*nor[2];
+ Normalise(n1);
+
+ fastshade(vec, n1, fp, ma, (char *)col1, 0, 0);
+
+ fp+= 3; col1++; nor+= 3;
+ }
+ }
+ }
+ dl= dl->next;
+ }
+ }
+
+ if((R.flag & R_RENDERING)==0) {
+ for(a=0; a<ob->totcol; a++) {
+ ma= give_current_material(ob, a+1);
+ if(ma) end_render_material(ma);
+ }
+ }
+
+ /* deze was er tijdelijk uitgehaald */
+ if(dldeform) BLI_addtail(&ob->disp, dldeform);
+}
+
+void reshadeall_displist(void)
+{
+ DispList *dldeform;
+ Base *base;
+ Object *ob;
+
+ freefastshade();
+
+ base= G.scene->base.first;
+ while(base) {
+ if(base->lay & G.scene->lay) {
+
+ ob= base->object;
+
+ /* we halen de dl_verts eruit, deform info */
+ dldeform= find_displist(&ob->disp, DL_VERTS);
+ if(dldeform) BLI_remlink(&ob->disp, dldeform);
+
+ /* Metaballs hebben de standaard displist aan het Object zitten */
+ if(ob->type==OB_MBALL) shadeDispList(ob);
+ else freedisplist(&ob->disp);
+
+ if(dldeform) BLI_addtail(&ob->disp, dldeform);
+ }
+ base= base->next;
+ }
+}
+
+void count_displist(ListBase *lb, int *totvert, int *totface)
+{
+ DispList *dl;
+
+ dl= lb->first;
+ while(dl) {
+
+ switch(dl->type) {
+ case DL_SURF:
+ *totvert+= dl->nr*dl->parts;
+ *totface+= (dl->nr-1)*(dl->parts-1);
+ break;
+ case DL_INDEX3:
+ case DL_INDEX4:
+ *totvert+= dl->nr;
+ *totface+= dl->parts;
+ break;
+ case DL_POLY:
+ case DL_SEGM:
+ *totvert+= dl->nr*dl->parts;
+ }
+
+ dl= dl->next;
+ }
+}
+
+static void curve_to_displist(ListBase *nubase, ListBase *dispbase)
+{
+ Nurb *nu;
+ DispList *dl;
+ BezTriple *bezt, *prevbezt;
+ BPoint *bp;
+ float *data, *v1, *v2;
+ int a, len;
+
+ nu= nubase->first;
+
+ while(nu) {
+ if(nu->hide==0) {
+ if((nu->type & 7)==CU_BEZIER) {
+
+ /* tellen */
+ len= 0;
+ a= nu->pntsu-1;
+ if(nu->flagu & 1) a++;
+
+ prevbezt= nu->bezt;
+ bezt= prevbezt+1;
+ while(a--) {
+ if(a==0 && (nu->flagu & 1)) bezt= nu->bezt;
+
+ if(prevbezt->h2==HD_VECT && bezt->h1==HD_VECT) len++;
+ else len+= nu->resolu;
+
+ if(a==0 && (nu->flagu & 1)==0) len++;
+
+ prevbezt= bezt;
+ bezt++;
+ }
+
+ dl= MEM_callocN(sizeof(DispList), "makeDispListbez");
+ /* len+1 i.v.m. maakbez */
+ dl->verts= MEM_callocN( (len+1)*3*sizeof(float), "dlverts");
+ BLI_addtail(dispbase, dl);
+ dl->parts= 1;
+ dl->nr= len;
+ dl->col= nu->mat_nr;
+
+ data= dl->verts;
+
+ if(nu->flagu & 1) {
+ dl->type= DL_POLY;
+ a= nu->pntsu;
+ }
+ else {
+ dl->type= DL_SEGM;
+ a= nu->pntsu-1;
+ }
+
+ prevbezt= nu->bezt;
+ bezt= prevbezt+1;
+
+ while(a--) {
+ if(a==0 && dl->type== DL_POLY) bezt= nu->bezt;
+
+ if(prevbezt->h2==HD_VECT && bezt->h1==HD_VECT) {
+ VECCOPY(data, prevbezt->vec[1]);
+ data+= 3;
+ }
+ else {
+ v1= prevbezt->vec[1];
+ v2= bezt->vec[0];
+ maakbez(v1[0], v1[3], v2[0], v2[3], data, nu->resolu);
+ maakbez(v1[1], v1[4], v2[1], v2[4], data+1, nu->resolu);
+ if((nu->type & 8)==0)
+ maakbez(v1[2], v1[5], v2[2], v2[5], data+2, nu->resolu);
+ data+= 3*nu->resolu;
+ }
+
+ if(a==0 && dl->type==DL_SEGM) {
+ VECCOPY(data, bezt->vec[1]);
+ }
+
+ prevbezt= bezt;
+ bezt++;
+ }
+ }
+ else if((nu->type & 7)==CU_NURBS) {
+ len= nu->pntsu*nu->resolu;
+ dl= MEM_callocN(sizeof(DispList), "makeDispListsurf");
+ dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts");
+ BLI_addtail(dispbase, dl);
+ dl->parts= 1;
+ dl->nr= len;
+ dl->col= nu->mat_nr;
+
+ data= dl->verts;
+ if(nu->flagu & 1) dl->type= DL_POLY;
+ else dl->type= DL_SEGM;
+ makeNurbcurve(nu, data, 3);
+ }
+ else if((nu->type & 7)==CU_POLY) {
+ len= nu->pntsu;
+ dl= MEM_callocN(sizeof(DispList), "makeDispListpoly");
+ dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts");
+ BLI_addtail(dispbase, dl);
+ dl->parts= 1;
+ dl->nr= len;
+ dl->col= nu->mat_nr;
+
+ data= dl->verts;
+ if(nu->flagu & 1) dl->type= DL_POLY;
+ else dl->type= DL_SEGM;
+
+ a= len;
+ bp= nu->bp;
+ while(a--) {
+ VECCOPY(data, bp->vec);
+ bp++;
+ data+= 3;
+ }
+ }
+ }
+ nu= nu->next;
+ }
+}
+
+
+static void filldisplist(ListBase *dispbase, ListBase *to)
+{
+ EditVert *eve, *v1, *vlast;
+ EditVlak *evl;
+ DispList *dlnew=0, *dl;
+ float *f1;
+ int colnr=0, cont=1, tot, a, *index;
+ long totvert;
+
+ if(dispbase==0) return;
+ if(dispbase->first==0) return;
+
+ /* tijd= clock(); */
+ /* bit-wise and comes after == .... so this doesn't work... */
+/* if(G.f & G_PLAYANIM == 0) waitcursor(1); */
+ if( !(G.f & G_PLAYANIM) ) waitcursor(1);
+
+ while(cont) {
+ cont= 0;
+ totvert=0;
+
+ dl= dispbase->first;
+ while(dl) {
+
+ if(dl->type==DL_POLY) {
+ if(colnr<dl->col) cont= 1;
+ else if(colnr==dl->col) {
+
+ colnr= dl->col;
+
+ /* editverts en edges maken */
+ f1= dl->verts;
+ a= dl->nr;
+ eve= v1= 0;
+
+ while(a--) {
+ vlast= eve;
+
+ eve= BLI_addfillvert(f1);
+ totvert++;
+
+ if(vlast==0) v1= eve;
+ else {
+ BLI_addfilledge(vlast, eve);
+ }
+ f1+=3;
+ }
+
+ if(eve!=0 && v1!=0) {
+ BLI_addfilledge(eve, v1);
+ }
+ }
+ }
+ dl= dl->next;
+ }
+
+ /* to make edgefill work
+ G.obedit can be 0 on file load */
+ if (G.obedit) {
+ BLI_setScanFillObjectRef(G.obedit);
+ BLI_setScanFillColourRef(&G.obedit->actcol);
+ }
+
+ if(totvert && BLI_edgefill(0)!=0) {
+
+ /* vlakken tellen */
+ tot= 0;
+ evl= fillvlakbase.first;
+ while(evl) {
+ tot++;
+ evl= evl->next;
+ }
+
+ if(tot) {
+ dlnew= MEM_callocN(sizeof(DispList), "filldisplist");
+ dlnew->type= DL_INDEX3;
+ dlnew->col= colnr;
+ dlnew->nr= totvert;
+ dlnew->parts= tot;
+
+ dlnew->index= MEM_mallocN(tot*3*sizeof(int), "dlindex");
+ dlnew->verts= MEM_mallocN(totvert*3*sizeof(float), "dlverts");
+
+ /* vertdata */
+ f1= dlnew->verts;
+ totvert= 0;
+ eve= fillvertbase.first;
+ while(eve) {
+ VECCOPY(f1, eve->co);
+ f1+= 3;
+
+ /* indexnummer */
+ eve->vn= (EditVert *)totvert;
+ totvert++;
+
+ eve= eve->next;
+ }
+
+ /* indexdata */
+ evl= fillvlakbase.first;
+ index= dlnew->index;
+ while(evl) {
+ index[0]= (long)evl->v1->vn;
+ index[1]= (long)evl->v2->vn;
+ index[2]= (long)evl->v3->vn;
+
+ index+= 3;
+ evl= evl->next;
+ }
+ }
+
+ BLI_addhead(to, dlnew);
+
+ }
+ BLI_end_edgefill();
+
+ colnr++;
+ }
+
+ /* poly's niet vrijgeven. nodig voor wireframe display */
+
+ /* same as above ... */
+/* if(G.f & G_PLAYANIM == 0) waitcursor(0); */
+ if( !(G.f & G_PLAYANIM) ) waitcursor(0);
+ /* printf("time: %d\n",(clock()-tijd)/1000); */
+
+}
+
+static void bevels_to_filledpoly(Curve *cu, ListBase *dispbase)
+{
+ ListBase front, back;
+ DispList *dl, *dlnew;
+ float *fp, *fp1;
+ int a, dpoly;
+
+ front.first= front.last= back.first= back.last= 0;
+
+ if(cu->flag & CU_3D) return;
+ if( (cu->flag & (CU_FRONT+CU_BACK))==0 ) return;
+
+ dl= dispbase->first;
+ while(dl) {
+ if(dl->type==DL_SURF) {
+ if(dl->flag==2) {
+ if(cu->flag & CU_BACK) {
+ dlnew= MEM_callocN(sizeof(DispList), "filldisp");
+ BLI_addtail(&front, dlnew);
+ dlnew->verts= fp1= MEM_mallocN(sizeof(float)*3*dl->parts, "filldisp1");
+ dlnew->nr= dl->parts;
+ dlnew->parts= 1;
+ dlnew->type= DL_POLY;
+ dlnew->col= dl->col;
+
+ fp= dl->verts;
+ dpoly= 3*dl->nr;
+
+ a= dl->parts;
+ while(a--) {
+ VECCOPY(fp1, fp);
+ fp1+= 3;
+ fp+= dpoly;
+ }
+ }
+ if(cu->flag & CU_FRONT) {
+ dlnew= MEM_callocN(sizeof(DispList), "filldisp");
+ BLI_addtail(&back, dlnew);
+ dlnew->verts= fp1= MEM_mallocN(sizeof(float)*3*dl->parts, "filldisp1");
+ dlnew->nr= dl->parts;
+ dlnew->parts= 1;
+ dlnew->type= DL_POLY;
+ dlnew->col= dl->col;
+
+ fp= dl->verts+3*(dl->nr-1);
+ dpoly= 3*dl->nr;
+
+ a= dl->parts;
+ while(a--) {
+ VECCOPY(fp1, fp);
+ fp1+= 3;
+ fp+= dpoly;
+ }
+ }
+ }
+ }
+ dl= dl->next;
+ }
+
+ filldisplist(&front, dispbase);
+ filldisplist(&back, dispbase);
+
+ freedisplist(&front);
+ freedisplist(&back);
+
+ filldisplist(dispbase, dispbase);
+
+}
+
+void curve_to_filledpoly(Curve *cu, ListBase *dispbase)
+{
+ DispList *dl;
+ Nurb *nu;
+
+ dl= dispbase->first;
+
+ if(cu->flag & CU_3D) return;
+
+ nu= cu->nurb.first;
+ while(nu) {
+ if(nu->flagu & CU_CYCLIC) break;
+ nu= nu->next;
+ }
+ if(nu==0) return;
+
+ if(dl->type==DL_SURF) bevels_to_filledpoly(cu, dispbase);
+ else {
+ if(cu->flag & CU_FRONT) filldisplist(dispbase, dispbase);
+ }
+}
+
+
+static int dl_onlyzero= 0;
+
+void set_displist_onlyzero(int val)
+{
+ dl_onlyzero= val;
+}
+
+void makeDispList(Object *ob)
+{
+ Mesh *me;
+ Nurb *nu;
+ Curve *cu;
+ BPoint *bp;
+ ListBase dlbev, *dispbase;
+ DispList *dl, *dlb;
+ BevList *bl;
+ BevPoint *bevp;
+ float *data, *fp1, widfac, vec[3];
+ int len, a, b, draw=0;
+
+ if(ob==0) return;
+ if(ob->flag & OB_FROMDUPLI) return;
+ freedisplist(&(ob->disp));
+
+ if(ob->type==OB_MESH) {
+ me= ob->data;
+
+ freedisplist(&(me->disp));
+
+ tex_space_mesh(ob->data);
+
+ object_deform(ob);
+
+ if(ob->effect.first) object_wave(ob);
+
+ if ((me->flag & ME_SUBSURF) && me->subdiv>0) {
+ if (ob==G.obedit)
+ subsurf_make_editmesh(ob);
+ else
+ subsurf_make_mesh(ob, me->subdiv);
+ }
+ }
+ else if(ob->type==OB_MBALL) {
+ ob= find_basis_mball(ob);
+
+ metaball_polygonize(ob);
+ tex_space_mball(ob);
+ }
+ else if(ob->type==OB_SURF) {
+
+ draw= ob->dt;
+ cu= ob->data;
+ dispbase= &(cu->disp);
+ if(dl_onlyzero && dispbase->first) return;
+ freedisplist(dispbase);
+
+ if(ob==G.obedit) nu= editNurb.first;
+ else nu= cu->nurb.first;
+
+ while(nu) {
+ if(nu->hide==0) {
+ if(nu->pntsv==1) {
+ if(draw==0) len= nu->pntsu;
+ else len= nu->pntsu*nu->resolu;
+
+ dl= MEM_callocN(sizeof(DispList), "makeDispListsurf");
+ dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts");
+
+ BLI_addtail(dispbase, dl);
+ dl->parts= 1;
+ dl->nr= len;
+ dl->col= nu->mat_nr;
+
+ data= dl->verts;
+ if(nu->flagu & 1) dl->type= DL_POLY;
+ else dl->type= DL_SEGM;
+
+ if(draw==0) {
+ bp= nu->bp;
+ while(len--) {
+ VECCOPY(data, bp->vec);
+ bp++;
+ data+= 3;
+ }
+ }
+ else makeNurbcurve(nu, data, 3);
+ }
+ else {
+ if(draw==0 && ob==G.obedit) ;
+ else {
+ if(draw==0) len= nu->pntsu*nu->pntsv;
+ else len= nu->resolu*nu->resolv;
+
+ dl= MEM_callocN(sizeof(DispList), "makeDispListsurf");
+ dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts");
+ BLI_addtail(dispbase, dl);
+
+ if(draw==0) {
+ dl->parts= nu->pntsv;
+ dl->nr= nu->pntsu;
+ if(nu->flagu & 1) dl->flag|= 1;
+ if(nu->flagv & 1) dl->flag|= 2;
+ }
+ else {
+ dl->parts= nu->resolu; /* andersom want makeNurbfaces gaat zo */
+ dl->nr= nu->resolv;
+ if(nu->flagv & 1) dl->flag|= 1; /* ook andersom ! */
+ if(nu->flagu & 1) dl->flag|= 2;
+ }
+ dl->col= nu->mat_nr;
+
+ data= dl->verts;
+ dl->type= DL_SURF;
+
+ if(draw==0) {
+ bp= nu->bp;
+ while(len--) {
+ VECCOPY(data, bp->vec);
+ bp++;
+ data+= 3;
+ }
+ }
+ else makeNurbfaces(nu, data);
+ }
+ }
+ }
+ nu= nu->next;
+ }
+
+ tex_space_curve(cu);
+
+ if(ob!=G.obedit) object_deform(ob);
+ }
+ else if ELEM(ob->type, OB_CURVE, OB_FONT) {
+
+ draw= ob->dt;
+ cu= ob->data;
+ dispbase= &(cu->disp);
+ if(dl_onlyzero && dispbase->first) return;
+ freedisplist(dispbase);
+
+ if(cu->path) free_path(cu->path);
+ cu->path= 0;
+
+ BLI_freelistN(&(cu->bev));
+
+ if(ob==G.obedit) {
+ if(ob->type==OB_CURVE) curve_to_displist(&editNurb, dispbase);
+ else curve_to_displist(&cu->nurb, dispbase);
+ if(cu->flag & CU_PATH) makeBevelList(ob);
+ }
+ else if(cu->ext1==0.0 && cu->ext2==0.0 && cu->bevobj==0 && cu->width==1.0) {
+ curve_to_displist(&cu->nurb, dispbase);
+ if(cu->flag & CU_PATH) makeBevelList(ob);
+ }
+ else {
+
+ makeBevelList(ob);
+
+ dlbev.first= dlbev.last= 0;
+ if(cu->ext1!=0.0 || cu->ext2!=0.0 || cu->bevobj) {
+ if(ob->dt!=0) makebevelcurve(ob, &dlbev);
+ }
+
+ /* met bevellist werken */
+ widfac= cu->width-1.0;
+ bl= cu->bev.first;
+ nu= cu->nurb.first;
+ while(bl) {
+ if(dlbev.first==0) {
+ dl= MEM_callocN(sizeof(DispList), "makeDispListbev");
+ dl->verts= MEM_callocN(3*sizeof(float)*bl->nr, "dlverts");
+ BLI_addtail(dispbase, dl);
+ if(bl->poly!= -1) dl->type= DL_POLY;
+ else dl->type= DL_SEGM;
+ dl->parts= 1;
+ dl->nr= bl->nr;
+ dl->col= nu->mat_nr;
+
+ a= dl->nr;
+ bevp= (BevPoint *)(bl+1);
+ data= dl->verts;
+ while(a--) {
+ data[0]= bevp->x+widfac*bevp->sina;
+ data[1]= bevp->y+widfac*bevp->cosa;
+ data[2]= bevp->z;
+ bevp++;
+ data+=3;
+ }
+ }
+ else {
+ /* voor iedere stuk van de bevel een aparte dispblok maken */
+ dlb= dlbev.first;
+ while(dlb) {
+ dl= MEM_callocN(sizeof(DispList), "makeDispListbev1");
+ dl->verts= MEM_callocN(3*sizeof(float)*dlb->nr*bl->nr, "dlverts");
+ BLI_addtail(dispbase, dl);
+ /* dl->type= dlb->type; */
+
+ dl->type= DL_SURF;
+ dl->flag= 0;
+ if(dlb->type==DL_POLY) dl->flag++;
+ if(bl->poly>=0) dl->flag+=2;
+
+ dl->parts= bl->nr;
+ dl->nr= dlb->nr;
+ dl->col= nu->mat_nr;
+
+ data= dl->verts;
+ bevp= (BevPoint *)(bl+1);
+ a= bl->nr;
+ while(a--) { /* voor ieder punt van poly een bevelstuk maken */
+
+ /* roteer bevelstuk en schrijf in data */
+ fp1= dlb->verts;
+ b= dlb->nr;
+
+ while(b--) {
+ if(cu->flag & CU_3D) {
+
+ vec[0]= fp1[1]+widfac;
+ vec[1]= fp1[2];
+ vec[2]= 0.0;
+
+ Mat3MulVecfl(bevp->mat, vec);
+
+ data[0]= bevp->x+ vec[0];
+ data[1]= bevp->y+ vec[1];
+ data[2]= bevp->z+ vec[2];
+ }
+ else {
+ data[0]= bevp->x+ (fp1[1]+widfac)*bevp->sina;
+ data[1]= bevp->y+ (fp1[1]+widfac)*bevp->cosa;
+ data[2]= bevp->z+ fp1[2];
+ }
+
+ data+=3;
+ fp1+=3;
+ }
+
+ bevp++;
+ }
+
+ dlb= dlb->next;
+ }
+ }
+
+ bl= bl->next;
+ nu= nu->next;
+ }
+
+ if(cu->ext1!=0.0 || cu->ext2!=0.0 || cu->bevobj) {
+ freedisplist(&dlbev);
+ }
+ }
+
+ if(ob!=G.obedit) object_deform(ob);
+
+ tex_space_curve(cu);
+
+ }
+}
+
+
+/*******************************/
+/***** OUTLINE *****/
+/*******************************/
+
+typedef struct Sample{
+ short x, y;
+} Sample;
+
+typedef struct Segment{
+ /* coordinaten */
+ struct Segment * next, * prev;
+ float co[2];
+} Segment;
+
+
+
+static int dflt_in_out(struct ImBuf * ibuf, int x, int y)
+{
+ unsigned char * rect;
+
+ if (ibuf == 0) return (0);
+ if (x < 0 || y < 0 || x >= ibuf->x || y >= ibuf->y || ibuf->rect == 0) return (-1);
+
+ rect = (unsigned char *) (ibuf->rect + (y * ibuf->x) + x);
+ if (rect[0] > 0x81) return (1);
+ return(0);
+}
+
+
+static Sample * outline(struct ImBuf * ibuf,
+ int (*in_or_out)(struct ImBuf *, int, int))
+{
+ static int dirs[8][2] = {
+ {-1, 0}, {-1, 1}, {0, 1}, {1, 1},
+ {1, 0}, {1, -1}, {0, -1}, {-1, -1}
+ };
+
+ int dir, x, y, in, i;
+ int count, sampcount;
+ int startx = 0, starty = 0;
+ Sample * samp, * oldsamp;
+
+ /* wat erin gaat:
+ * 1 - plaatje waarvan outline berekent moet worden,
+ * 2 - pointer naar functie die bepaalt welke pixel in of uit is
+ */
+
+ if (ibuf == 0) return (0);
+ if (ibuf->rect == 0) return (0);
+
+ if (in_or_out == 0) in_or_out = dflt_in_out;
+ in = in_or_out(ibuf, 0, 0);
+
+ /* zoek naar eerste overgang en ga van daar uit 'zoeken' */
+ for (y = 0; y < ibuf->y; y++) {
+ for (x = 0; x < ibuf->x; x++) {
+ if (in_or_out(ibuf, x, y) != in) {
+ /* eerste 'andere' punt gevonden !! */
+
+ if (x != startx) dir = 0;
+ else dir = 6;
+
+ startx = x; starty = y;
+ count = 1;
+ sampcount = 2000;
+ samp = MEM_mallocN(sampcount * sizeof(Sample), "wire_samples");
+
+ do{
+ samp[count].x = x; samp[count].y = y;
+ count++;
+
+ if (count >= sampcount) {
+ oldsamp = samp;
+ samp = MEM_mallocN(2 * sampcount * sizeof(Sample), "wire_samples");
+ memcpy(samp, oldsamp, sampcount * sizeof(Sample));
+ sampcount *= 2;
+ MEM_freeN(oldsamp);
+ }
+
+ i = 0;
+ while(in_or_out(ibuf, x + dirs[dir][0], y + dirs[dir][1]) == in) {
+ dir = (dir + 1) & 0x7;
+ if (i++ == 9) break;
+ }
+
+ if (i >= 8) {
+ /* dit moet een losse punt geweest zijn */
+ break;
+ }
+
+ x += dirs[dir][0];
+ y += dirs[dir][1];
+ dir = (dir - 3) & 0x7;
+ } while(x != startx || y != starty);
+
+ if (i >= 8) {
+ /* losse punten patch */
+ MEM_freeN(samp);
+ } else {
+ count = count - 1;
+ samp[0].x = count >> 16;
+ samp[0].y = count;
+ return(samp);
+ }
+ }
+ }
+ }
+ /* printf("geen overgang \n"); */
+ return(0);
+}
+
+
+
+/*******************************/
+/***** WIREFRAME *****/
+/*******************************/
+
+
+static float DistToLine2D(short *v1, short *v2, short *v3) /* met formule van Hesse :GEEN LIJNSTUK! */
+{
+ float a[2],deler;
+
+ a[0] = v2[1]-v3[1];
+ a[1] = v3[0]-v2[0];
+ deler = sqrt(a[0]*a[0]+a[1]*a[1]);
+ if(deler == 0.0) return 0;
+
+ return fabs((v1[0]-v2[0])*a[0]+(v1[1]-v2[1])*a[1])/deler;
+
+}
+
+static float ComputeMaxShpError(Sample *samp, int first, int last, int *splitPoint)
+ /* samp: Array of digitized points */
+ /* first, last: Indices defining region */
+ /* splitpoint: Point of maximum error */
+{
+ int i;
+ float maxDist; /* Maximum error */
+ float dist; /* Current error */
+
+ *splitPoint = (last - first + 1) / 2;
+ maxDist = 0.0;
+
+ for (i = first + 1; i < last; i++) {
+ dist = DistToLine2D((short *)(samp+i), (short *)(samp+first), (short *)(samp+last));
+
+ if (dist >= maxDist) {
+ maxDist = dist;
+ *splitPoint = i;
+ }
+ }
+
+ return (maxDist);
+}
+
+
+static void FitPoly(Sample *samp, int first, int last, float shperr, ListBase *seglist)
+ /* Samp: Array of digitized points */
+ /* first,last: Indices of first and last pts in region */
+ /* spherr: User-defined error squared */
+{
+ Segment * seg; /* Control points segment*/
+ float maxError; /* Maximum fitting error */
+ int splitPoint; /* Point to split point set at */
+ int nPts; /* Number of points in subset */
+
+ nPts = last - first + 1;
+
+ /* Use heuristic if region only has two points in it */
+
+ seg = MEM_mallocN(sizeof(Segment), "wure_segment");
+
+ seg->co[0] = samp[first].x;
+ seg->co[1] = samp[first].y;
+
+ if (nPts == 2) {
+ BLI_addtail(seglist, seg);
+ return;
+ }
+
+ maxError = ComputeMaxShpError(samp, first, last, &splitPoint);
+ if (maxError < shperr) {
+ BLI_addtail(seglist, seg);
+ return;
+ }
+
+ /* Fitting failed -- split at max error point and fit recursively */
+
+ FitPoly(samp, first, splitPoint, shperr, seglist);
+ FitPoly(samp, splitPoint, last, shperr, seglist);
+
+ MEM_freeN(seg);
+}
+
+
+static void ibuf2wire(ListBase * wireframe, struct ImBuf * ibuf)
+{
+ int count;
+ Sample * samp;
+
+ /* eerst een lijst met samples maken */
+
+ samp = outline(ibuf, 0);
+ if (samp == 0) return;
+
+ count = (samp[0].x << 16) + samp[0].y;
+ if (count) FitPoly(samp, 1, count, 1.0, wireframe); /* was 3.0. Frank */
+
+ MEM_freeN(samp);
+}
+
+
+
+void imagestodisplist(void)
+{
+ Base *base;
+ Object *ob;
+ Material *ma;
+ Tex *tex;
+ Mesh *me;
+ ListBase _wireframe, *wireframe;
+ DispList *dl;
+ Segment *seg;
+ float *data, xfac, yfac, xsi, ysi, vec[3];
+ int tot;
+
+ _wireframe.first= 0;
+ _wireframe.last= 0;
+ wireframe = &_wireframe;
+
+ init_render_textures();
+
+ base= G.scene->base.first;
+ while(base) {
+ if(( (base->flag & SELECT) && (base->lay & G.scene->lay) ) ) {
+ if( base->object->type==OB_MESH) {
+ ob= base->object;
+ me= ob->data;
+
+ ma= give_current_material(ob, 1);
+
+ if(ma && ma->mtex[0] && ma->mtex[0]->tex) {
+ tex= ma->mtex[0]->tex;
+
+ /* dit zorgt voor correct laden van nieuwe imbufs */
+ externtex(ma->mtex[0], vec);
+
+ if(tex->type==TEX_IMAGE && tex->ima && tex->ima->ibuf) {
+
+ ob->dtx |= OB_DRAWIMAGE;
+
+ ibuf2wire(wireframe, tex->ima->ibuf);
+
+ tot= 0;
+ seg = wireframe->first;
+ while (seg) {
+ tot++;
+ seg = seg->next;
+ }
+
+ if(tot) {
+ freedisplist(&(ob->disp));
+
+ dl= MEM_callocN(sizeof(DispList), "makeDispListimage");
+ dl->verts= MEM_callocN(3*sizeof(float)*tot, "dlverts");
+
+ BLI_addtail(&(ob->disp), dl);
+ dl->type= DL_POLY;
+ dl->parts= 1;
+ dl->nr= tot;
+
+ xsi= 0.5*(tex->ima->ibuf->x);
+ ysi= 0.5*(tex->ima->ibuf->y);
+ xfac= me->size[0]/xsi;
+ yfac= me->size[1]/ysi;
+
+ data= dl->verts;
+ seg = wireframe->first;
+ while (seg) {
+ data[0]= xfac*(seg->co[0]-xsi);
+ data[1]= yfac*(seg->co[1]-ysi);
+ data+= 3;
+ seg = seg->next;
+ }
+ BLI_freelistN(wireframe);
+ }
+ }
+ }
+ }
+ }
+ base= base->next;
+ }
+
+ end_render_textures();
+
+ allqueue(REDRAWVIEW3D, 0);
+}
+
+/* on frame change */
+
+void test_all_displists(void)
+{
+ Base *base;
+ Object *ob;
+ unsigned int lay;
+
+ /* background */
+ lay= G.scene->lay;
+
+ base= G.scene->base.first;
+ while(base) {
+ if(base->lay & lay) {
+ ob= base->object;
+
+
+ if(ob->type==OB_MBALL && ob->ipo) {
+ // find metaball object holding the displist
+ // WARNING: if more metaballs have IPO's the displist
+ // is recalculated to often...
+
+ if(ob->disp.first == NULL) {
+ ob= find_basis_mball(ob);
+ }
+
+ makeDispList(ob);
+ }
+ else if(ob->parent) {
+
+ if (ob->parent->type == OB_LATTICE)
+ makeDispList(ob);
+ else if ((ob->parent->type == OB_IKA) && (ob->partype == PARSKEL))
+ makeDispList(ob);
+#ifdef __NLA
+ else if ((ob->parent->type==OB_ARMATURE) && (ob->partype == PARSKEL))
+ makeDispList(ob);
+
+#endif
+ }
+
+ if ELEM(ob->type, OB_CURVE, OB_SURF) {
+ if(ob!=G.obedit) {
+ if( ((Curve *)(ob->data))->key ) makeDispList(ob);
+ }
+ }
+ else if(ob->type==OB_FONT) {
+ Curve *cu= ob->data;
+ if(cu->textoncurve) {
+ if( ((Curve *)cu->textoncurve->data)->key ) {
+ text_to_curve(ob, 0);
+ makeDispList(ob);
+ }
+ }
+ }
+ else if(ob->type==OB_MESH) {
+ if(ob->effect.first) object_wave(ob);
+ if(ob!=G.obedit) {
+ if( ((Mesh *)(ob->data))->key ) makeDispList(ob);
+ }
+ }
+
+ }
+ if(base->next==0 && G.scene->set && base==G.scene->base.last) base= G.scene->set->base.first;
+ else base= base->next;
+ }
+}
+
+
+void boundbox_displist(Object *ob)
+{
+ BoundBox *bb=0;
+ float min[3], max[3];
+ DispList *dl;
+ float *vert;
+ int a, tot=0;
+
+ INIT_MINMAX(min, max);
+
+ if(ob->type==OB_MESH) {
+ Mesh *me= ob->data;
+
+ dl= find_displist(&ob->disp, DL_VERTS);
+ if(!dl) return;
+
+ if(me->bb==0) me->bb= MEM_callocN(sizeof(BoundBox), "boundbox");
+ bb= me->bb;
+
+ vert= dl->verts;
+ for(a=0; a<dl->nr; a++, vert+=3) {
+ DO_MINMAX(vert, min, max);
+ }
+ }
+ else if(ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
+ Curve *cu= ob->data;
+
+ if(cu->bb==0) cu->bb= MEM_callocN(sizeof(BoundBox), "boundbox");
+ bb= cu->bb;
+
+ dl= cu->disp.first;
+
+ while (dl) {
+ if(dl->type==DL_INDEX3 || dl->type==DL_INDEX3) tot= dl->nr;
+ else tot= dl->nr*dl->parts;
+
+ vert= dl->verts;
+ for(a=0; a<tot; a++, vert+=3) {
+ DO_MINMAX(vert, min, max);
+ }
+
+ dl= dl->next;
+ }
+ }
+
+ if(bb) {
+ bb->vec[0][0]=bb->vec[1][0]=bb->vec[2][0]=bb->vec[3][0]= min[0];
+ bb->vec[4][0]=bb->vec[5][0]=bb->vec[6][0]=bb->vec[7][0]= max[0];
+
+ bb->vec[0][1]=bb->vec[1][1]=bb->vec[4][1]=bb->vec[5][1]= min[1];
+ bb->vec[2][1]=bb->vec[3][1]=bb->vec[6][1]=bb->vec[7][1]= max[1];
+
+ bb->vec[0][2]=bb->vec[3][2]=bb->vec[4][2]=bb->vec[7][2]= min[2];
+ bb->vec[1][2]=bb->vec[2][2]=bb->vec[5][2]=bb->vec[6][2]= max[2];
+ }
+}
+
diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c
new file mode 100644
index 00000000000..c39ad72ecdf
--- /dev/null
+++ b/source/blender/blenkernel/intern/effect.c
@@ -0,0 +1,854 @@
+/* effect.c MIX MODEL
+ *
+ * dec 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 <math.h>
+#include <stdlib.h>
+
+#include "MEM_guardedalloc.h"
+#include "DNA_listBase.h"
+#include "DNA_effect_types.h"
+#include "DNA_object_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_material_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_key_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_lattice_types.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_rand.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_bad_level_calls.h"
+#include "BKE_global.h"
+#include "BKE_material.h"
+#include "BKE_effect.h"
+#include "BKE_key.h"
+#include "BKE_ipo.h"
+#include "BKE_screen.h"
+#include "BKE_texture.h"
+#include "BKE_blender.h"
+#include "BKE_object.h"
+#include "BKE_displist.h"
+#include "BKE_lattice.h"
+
+
+Effect *add_effect(int type)
+{
+ Effect *eff=0;
+ BuildEff *bld;
+ PartEff *paf;
+ WaveEff *wav;
+ int a;
+
+ switch(type) {
+ case EFF_BUILD:
+ bld= MEM_callocN(sizeof(BuildEff), "neweff");
+ eff= (Effect *)bld;
+
+ bld->sfra= 1.0;
+ bld->len= 100.0;
+ break;
+
+ case EFF_PARTICLE:
+ paf= MEM_callocN(sizeof(PartEff), "neweff");
+ eff= (Effect *)paf;
+
+ paf->sta= 1.0;
+ paf->end= 100.0;
+ paf->lifetime= 50.0;
+ for(a=0; a<PAF_MAXMULT; a++) {
+ paf->life[a]= 50.0;
+ paf->child[a]= 4;
+ paf->mat[a]= 1;
+ }
+
+ paf->totpart= 1000;
+ paf->totkey= 8;
+ paf->staticstep= 5;
+ paf->defvec[2]= 1.0f;
+ paf->nabla= 0.05f;
+
+ break;
+
+ case EFF_WAVE:
+ wav= MEM_callocN(sizeof(WaveEff), "neweff");
+ eff= (Effect *)wav;
+
+ wav->flag |= (WAV_X+WAV_Y+WAV_CYCL);
+
+ wav->height= 0.5f;
+ wav->width= 1.5f;
+ wav->speed= 0.5f;
+ wav->narrow= 1.5f;
+ wav->lifetime= 0.0f;
+ wav->damp= 10.0f;
+
+ break;
+ }
+
+ eff->type= eff->buttype= type;
+ eff->flag |= SELECT;
+
+ return eff;
+}
+
+void free_effect(Effect *eff)
+{
+ PartEff *paf;
+
+ if(eff->type==EFF_PARTICLE) {
+ paf= (PartEff *)eff;
+ if(paf->keys) MEM_freeN(paf->keys);
+ }
+ MEM_freeN(eff);
+}
+
+
+void free_effects(ListBase *lb)
+{
+ Effect *eff;
+
+ eff= lb->first;
+ while(eff) {
+ BLI_remlink(lb, eff);
+ free_effect(eff);
+ eff= lb->first;
+ }
+}
+
+Effect *copy_effect(Effect *eff)
+{
+ Effect *effn;
+
+ effn= MEM_dupallocN(eff);
+ if(effn->type==EFF_PARTICLE) ((PartEff *)effn)->keys= 0;
+
+ return effn;
+}
+
+void copy_act_effect(Object *ob)
+{
+ /* return de aktieve eff gekopieerd */
+ Effect *effn, *eff;
+
+ eff= ob->effect.first;
+ while(eff) {
+ if(eff->flag & SELECT) {
+
+ effn= copy_effect(eff);
+ BLI_addtail(&ob->effect, effn);
+
+ eff->flag &= ~SELECT;
+ return;
+
+ }
+ eff= eff->next;
+ }
+
+ /* als tie hier komt: new effect */
+ eff= add_effect(EFF_BUILD);
+ BLI_addtail(&ob->effect, eff);
+
+}
+
+void copy_effects(ListBase *lbn, ListBase *lb)
+{
+ Effect *eff, *effn;
+
+ lbn->first= lbn->last= 0;
+
+ eff= lb->first;
+ while(eff) {
+ effn= copy_effect(eff);
+ BLI_addtail(lbn, effn);
+
+ eff= eff->next;
+ }
+
+}
+
+void deselectall_eff(Object *ob)
+{
+ Effect *eff= ob->effect.first;
+
+ while(eff) {
+ eff->flag &= ~SELECT;
+ eff= eff->next;
+ }
+}
+
+void set_buildvars(Object *ob, int *start, int *end)
+{
+ BuildEff *bld;
+ float ctime;
+
+ bld= ob->effect.first;
+ while(bld) {
+ if(bld->type==EFF_BUILD) {
+ ctime= bsystem_time(ob, 0, (float)G.scene->r.cfra, bld->sfra-1.0f);
+ if(ctime < 0.0) {
+ *end= *start;
+ }
+ else if(ctime < bld->len) {
+ *end= *start+ (int)((*end - *start)*ctime/bld->len);
+ }
+
+ return;
+ }
+ bld= bld->next;
+ }
+}
+
+/* ***************** PARTICLES ***************** */
+
+Particle *new_particle(PartEff *paf)
+{
+ static Particle *pa;
+ static int cur;
+
+ /* afspraak: als paf->keys==0: alloc */
+ if(paf->keys==0) {
+ pa= paf->keys= MEM_callocN( paf->totkey*paf->totpart*sizeof(Particle), "particlekeys" );
+ cur= 0;
+ }
+ else {
+ if(cur && cur<paf->totpart) pa+=paf->totkey;
+ cur++;
+ }
+ return pa;
+}
+
+PartEff *give_parteff(Object *ob)
+{
+ PartEff *paf;
+
+ paf= ob->effect.first;
+ while(paf) {
+ if(paf->type==EFF_PARTICLE) return paf;
+ paf= paf->next;
+ }
+ return 0;
+}
+
+void where_is_particle(PartEff *paf, Particle *pa, float ctime, float *vec)
+{
+ Particle *p[4];
+ float dt, t[4];
+ int a;
+
+ if(paf->totkey==1) {
+ VECCOPY(vec, pa->co);
+ return;
+ }
+
+ /* eerst op zoek naar de eerste particlekey */
+ a= (int)((paf->totkey-1)*(ctime-pa->time)/pa->lifetime);
+ if(a>=paf->totkey) a= paf->totkey-1;
+
+ pa+= a;
+
+ if(a>0) p[0]= pa-1; else p[0]= pa;
+ p[1]= pa;
+
+ if(a+1<paf->totkey) p[2]= pa+1; else p[2]= pa;
+ if(a+2<paf->totkey) p[3]= pa+2; else p[3]= p[2];
+
+ if(p[1]==p[2]) dt= 0.0;
+ else dt= (ctime-p[1]->time)/(p[2]->time - p[1]->time);
+
+ if(paf->flag & PAF_BSPLINE) set_four_ipo(dt, t, KEY_BSPLINE);
+ else set_four_ipo(dt, t, KEY_CARDINAL);
+
+ vec[0]= t[0]*p[0]->co[0] + t[1]*p[1]->co[0] + t[2]*p[2]->co[0] + t[3]*p[3]->co[0];
+ vec[1]= t[0]*p[0]->co[1] + t[1]*p[1]->co[1] + t[2]*p[2]->co[1] + t[3]*p[3]->co[1];
+ vec[2]= t[0]*p[0]->co[2] + t[1]*p[1]->co[2] + t[2]*p[2]->co[2] + t[3]*p[3]->co[2];
+
+}
+
+
+void particle_tex(MTex *mtex, PartEff *paf, float *co, float *no)
+{
+ extern float Tin, Tr, Tg, Tb;
+ float old;
+
+ externtex(mtex, co);
+
+ if(paf->texmap==PAF_TEXINT) {
+ Tin*= paf->texfac;
+ no[0]+= Tin*paf->defvec[0];
+ no[1]+= Tin*paf->defvec[1];
+ no[2]+= Tin*paf->defvec[2];
+ }
+ else if(paf->texmap==PAF_TEXRGB) {
+ no[0]+= (Tr-0.5f)*paf->texfac;
+ no[1]+= (Tg-0.5f)*paf->texfac;
+ no[2]+= (Tb-0.5f)*paf->texfac;
+ }
+ else { /* PAF_TEXGRAD */
+
+ old= Tin;
+ co[0]+= paf->nabla;
+ externtex(mtex, co);
+ no[0]+= (old-Tin)*paf->texfac;
+
+ co[0]-= paf->nabla;
+ co[1]+= paf->nabla;
+ externtex(mtex, co);
+ no[1]+= (old-Tin)*paf->texfac;
+
+ co[1]-= paf->nabla;
+ co[2]+= paf->nabla;
+ externtex(mtex, co);
+ no[2]+= (old-Tin)*paf->texfac;
+
+ }
+}
+
+void make_particle_keys(int depth, int nr, PartEff *paf, Particle *part, float *force, int deform, MTex *mtex)
+{
+ Particle *pa, *opa = NULL;
+ float damp, deltalife;
+ int b, rt1, rt2;
+
+ damp= 1.0f-paf->damp;
+ pa= part;
+
+ /* startsnelheid: random */
+ if(paf->randfac!=0.0) {
+ pa->no[0]+= (float)(paf->randfac*( BLI_drand() -0.5));
+ pa->no[1]+= (float)(paf->randfac*( BLI_drand() -0.5));
+ pa->no[2]+= (float)(paf->randfac*( BLI_drand() -0.5));
+ }
+
+ /* startsnelheid: texture */
+ if(mtex && paf->texfac!=0.0) {
+ particle_tex(mtex, paf, pa->co, pa->no);
+ }
+
+ /* keys */
+ if(paf->totkey>1) {
+
+ deltalife= pa->lifetime/(paf->totkey-1);
+ opa= pa;
+ pa++;
+
+ b= paf->totkey-1;
+ while(b--) {
+ /* nieuwe tijd */
+ pa->time= opa->time+deltalife;
+
+ /* nieuwe plek */
+ pa->co[0]= opa->co[0] + deltalife*opa->no[0];
+ pa->co[1]= opa->co[1] + deltalife*opa->no[1];
+ pa->co[2]= opa->co[2] + deltalife*opa->no[2];
+
+ /* nieuwe snelheid */
+ pa->no[0]= opa->no[0] + deltalife*force[0];
+ pa->no[1]= opa->no[1] + deltalife*force[1];
+ pa->no[2]= opa->no[2] + deltalife*force[2];
+
+ /* snelheid: texture */
+ if(mtex && paf->texfac!=0.0) {
+ particle_tex(mtex, paf, pa->co, pa->no);
+ }
+ if(damp!=1.0) {
+ pa->no[0]*= damp;
+ pa->no[1]*= damp;
+ pa->no[2]*= damp;
+ }
+
+ opa= pa;
+ pa++;
+ /* opa wordt onderin ook gebruikt */
+ }
+ }
+
+ if(deform) {
+ /* alle keys deformen */
+ pa= part;
+ b= paf->totkey;
+ while(b--) {
+ calc_latt_deform(pa->co);
+ pa++;
+ }
+ }
+
+ /* de grote vermenigvuldiging */
+ if(depth<PAF_MAXMULT && paf->mult[depth]!=0.0) {
+
+ /* uit gemiddeld 'mult' deel van de particles ontstaan 'child' nieuwe */
+ damp = (float)nr;
+ rt1= (int)(damp*paf->mult[depth]);
+ rt2= (int)((damp+1.0)*paf->mult[depth]);
+ if(rt1!=rt2) {
+
+ for(b=0; b<paf->child[depth]; b++) {
+ pa= new_particle(paf);
+ *pa= *opa;
+ pa->lifetime= paf->life[depth];
+ if(paf->randlife!=0.0) {
+ pa->lifetime*= 1.0f+ (float)(paf->randlife*( BLI_drand() - 0.5));
+ }
+ pa->mat_nr= paf->mat[depth];
+
+ make_particle_keys(depth+1, b, paf, pa, force, deform, mtex);
+ }
+ }
+ }
+}
+
+void init_mv_jit(float *jit, int num)
+{
+ float *jit2, x, rad1, rad2, rad3;
+ int i;
+
+ if(num==0) return;
+
+ rad1= (float)(1.0/sqrt((float)num));
+ rad2= (float)(1.0/((float)num));
+ rad3= (float)sqrt((float)num)/((float)num);
+
+ BLI_srand(31415926 + num);
+ x= 0;
+ for(i=0; i<2*num; i+=2) {
+
+ jit[i]= x+ (float)(rad1*(0.5-BLI_drand()));
+ jit[i+1]= ((float)i/2)/num +(float)(rad1*(0.5-BLI_drand()));
+
+ jit[i]-= (float)floor(jit[i]);
+ jit[i+1]-= (float)floor(jit[i+1]);
+
+ x+= rad3;
+ x -= (float)floor(x);
+ }
+
+ jit2= MEM_mallocN(12 + 2*sizeof(float)*num, "initjit");
+
+ for (i=0 ; i<4 ; i++) {
+ RE_jitterate1(jit, jit2, num, rad1);
+ RE_jitterate1(jit, jit2, num, rad1);
+ RE_jitterate2(jit, jit2, num, rad2);
+ }
+ MEM_freeN(jit2);
+}
+
+
+void give_mesh_mvert(Mesh *me, int nr, float *co, short *no)
+{
+ static float *jit=0;
+ static int jitlevel=1;
+ MVert *mvert;
+ MFace *mface;
+ float u, v, *v1, *v2, *v3, *v4;
+ int curface, curjit;
+ short *n1, *n2, *n3, *n4;
+
+ /* signal */
+ if(me==0) {
+ if(jit) MEM_freeN(jit);
+ jit= 0;
+ return;
+ }
+
+ if(me->totface==0 || nr<me->totvert) {
+ mvert= me->mvert + (nr % me->totvert);
+ VECCOPY(co, mvert->co);
+ VECCOPY(no, mvert->no);
+ }
+ else {
+
+ nr-= me->totvert;
+
+ if(jit==0) {
+ jitlevel= nr/me->totface;
+ if(jitlevel==0) jitlevel= 1;
+ if(jitlevel>100) jitlevel= 100;
+
+ jit= MEM_callocN(2+ jitlevel*2*sizeof(float), "jit");
+ init_mv_jit(jit, jitlevel);
+
+ }
+
+ curjit= nr/me->totface;
+ curjit= curjit % jitlevel;
+
+ curface= nr % me->totface;
+
+ mface= me->mface;
+ mface+= curface;
+
+ v1= (me->mvert+(mface->v1))->co;
+ v2= (me->mvert+(mface->v2))->co;
+ n1= (me->mvert+(mface->v1))->no;
+ n2= (me->mvert+(mface->v2))->no;
+ if(mface->v3==0) {
+ v3= (me->mvert+(mface->v2))->co;
+ v4= (me->mvert+(mface->v1))->co;
+ n3= (me->mvert+(mface->v2))->no;
+ n4= (me->mvert+(mface->v1))->no;
+ }
+ else if(mface->v4==0) {
+ v3= (me->mvert+(mface->v3))->co;
+ v4= (me->mvert+(mface->v1))->co;
+ n3= (me->mvert+(mface->v3))->no;
+ n4= (me->mvert+(mface->v1))->no;
+ }
+ else {
+ v3= (me->mvert+(mface->v3))->co;
+ v4= (me->mvert+(mface->v4))->co;
+ n3= (me->mvert+(mface->v3))->no;
+ n4= (me->mvert+(mface->v4))->no;
+ }
+
+ u= jit[2*curjit];
+ v= jit[2*curjit+1];
+
+ co[0]= (float)((1.0-u)*(1.0-v)*v1[0] + (1.0-u)*(v)*v2[0] + (u)*(v)*v3[0] + (u)*(1.0-v)*v4[0]);
+ co[1]= (float)((1.0-u)*(1.0-v)*v1[1] + (1.0-u)*(v)*v2[1] + (u)*(v)*v3[1] + (u)*(1.0-v)*v4[1]);
+ co[2]= (float)((1.0-u)*(1.0-v)*v1[2] + (1.0-u)*(v)*v2[2] + (u)*(v)*v3[2] + (u)*(1.0-v)*v4[2]);
+
+ no[0]= (short)((1.0-u)*(1.0-v)*n1[0] + (1.0-u)*(v)*n2[0] + (u)*(v)*n3[0] + (u)*(1.0-v)*n4[0]);
+ no[1]= (short)((1.0-u)*(1.0-v)*n1[1] + (1.0-u)*(v)*n2[1] + (u)*(v)*n3[1] + (u)*(1.0-v)*n4[1]);
+ no[2]= (short)((1.0-u)*(1.0-v)*n1[2] + (1.0-u)*(v)*n2[2] + (u)*(v)*n3[2] + (u)*(1.0-v)*n4[2]);
+
+ }
+}
+
+
+void build_particle_system(Object *ob)
+{
+ Object *par;
+ PartEff *paf;
+ Particle *pa;
+ Mesh *me;
+ MVert *mvert;
+ MTex *mtexmove=0;
+ Material *ma;
+ float framelenont, ftime, dtime, force[3], imat[3][3], vec[3];
+ float fac, prevobmat[4][4], sfraont, co[3];
+ int deform=0, a, cur, cfraont, cfralast, totpart;
+ short no[3];
+
+ if(ob->type!=OB_MESH) return;
+ me= ob->data;
+ if(me->totvert==0) return;
+
+ ma= give_current_material(ob, 1);
+ if(ma) {
+ mtexmove= ma->mtex[7];
+ }
+
+ paf= give_parteff(ob);
+ if(paf==0) return;
+
+ waitcursor(1);
+
+ disable_speed_curve(1);
+
+ /* alle particles genereren */
+ if(paf->keys) MEM_freeN(paf->keys);
+ paf->keys= 0;
+ new_particle(paf);
+
+ cfraont= G.scene->r.cfra;
+ cfralast= -1000;
+ framelenont= G.scene->r.framelen;
+ G.scene->r.framelen= 1.0;
+ sfraont= ob->sf;
+ ob->sf= 0.0;
+
+ /* mult generaties? */
+ totpart= paf->totpart;
+ for(a=0; a<PAF_MAXMULT; a++) {
+ if(paf->mult[a]!=0.0) {
+ /* interessante formule! opdezewijze is na 'x' generaties het totale aantal paf->totpart */
+ totpart= (int)(totpart / (1.0+paf->mult[a]*paf->child[a]));
+ }
+ else break;
+ }
+
+ ftime= paf->sta;
+ dtime= (paf->end - paf->sta)/totpart;
+
+ /* hele hiera onthouden */
+ par= ob;
+ while(par) {
+ pushdata(par, sizeof(Object));
+ par= par->parent;
+ }
+
+ /* alles op eerste frame zetten */
+ G.scene->r.cfra= cfralast= (int)floor(ftime);
+ par= ob;
+ while(par) {
+ /* do_ob_ipo(par); */
+ do_ob_key(par);
+ par= par->parent;
+ }
+ do_mat_ipo(ma);
+
+ if((paf->flag & PAF_STATIC)==0) {
+ where_is_object(ob);
+ Mat4CpyMat4(prevobmat, ob->obmat);
+ Mat4Invert(ob->imat, ob->obmat);
+ Mat3CpyMat4(imat, ob->imat);
+ }
+ else {
+ Mat4One(prevobmat);
+ Mat3One(imat);
+ }
+
+ BLI_srand(paf->seed);
+
+ /* gaat anders veuls te hard */
+ force[0]= paf->force[0]*0.05f;
+ force[1]= paf->force[1]*0.05f;
+ force[2]= paf->force[2]*0.05f;
+
+ deform= (ob->parent && ob->parent->type==OB_LATTICE);
+ if(deform) init_latt_deform(ob->parent, 0);
+
+ /* init */
+ give_mesh_mvert(me, totpart, co, no);
+
+ for(a=0; a<totpart; a++, ftime+=dtime) {
+
+ pa= new_particle(paf);
+ pa->time= ftime;
+
+ /* ob op juiste tijd zetten */
+
+ if((paf->flag & PAF_STATIC)==0) {
+
+ cur= (int)floor(ftime) + 1 ; /* + 1 heeft een reden: (obmat/prevobmat) anders beginnen b.v. komeetstaartjes te laat */
+ if(cfralast != cur) {
+ G.scene->r.cfra= cfralast= cur;
+
+ /* later bijgevoegd: blur? */
+ bsystem_time(ob, ob->parent, (float)G.scene->r.cfra, 0.0);
+
+ par= ob;
+ while(par) {
+ /* do_ob_ipo(par); */
+ par->ctime= -1234567.0;
+ do_ob_key(par);
+ par= par->parent;
+ }
+ do_mat_ipo(ma);
+ Mat4CpyMat4(prevobmat, ob->obmat);
+ where_is_object(ob);
+ Mat4Invert(ob->imat, ob->obmat);
+ Mat3CpyMat4(imat, ob->imat);
+ }
+ }
+ /* coordinaat ophalen */
+ if(paf->flag & PAF_FACE) give_mesh_mvert(me, a, co, no);
+ else {
+ mvert= me->mvert + (a % me->totvert);
+ VECCOPY(co, mvert->co);
+ VECCOPY(no, mvert->no);
+ }
+
+ VECCOPY(pa->co, co);
+
+ if(paf->flag & PAF_STATIC);
+ else {
+ Mat4MulVecfl(ob->obmat, pa->co);
+
+ VECCOPY(vec, co);
+ Mat4MulVecfl(prevobmat, vec);
+
+ /* eerst even startsnelheid: object */
+ VecSubf(pa->no, pa->co, vec);
+ VecMulf(pa->no, paf->obfac);
+
+ /* nu juiste interframe co berekenen */
+ fac= (ftime- (float)floor(ftime));
+ pa->co[0]= fac*pa->co[0] + (1.0f-fac)*vec[0];
+ pa->co[1]= fac*pa->co[1] + (1.0f-fac)*vec[1];
+ pa->co[2]= fac*pa->co[2] + (1.0f-fac)*vec[2];
+ }
+
+ /* startsnelheid: normaal */
+ if(paf->normfac!=0.0) {
+ /* sp= mvert->no; */
+ /* transpose ! */
+ vec[0]= imat[0][0]*no[0] + imat[0][1]*no[1] + imat[0][2]*no[2];
+ vec[1]= imat[1][0]*no[0] + imat[1][1]*no[1] + imat[1][2]*no[2];
+ vec[2]= imat[2][0]*no[0] + imat[2][1]*no[1] + imat[2][2]*no[2];
+
+ Normalise(vec);
+ VecMulf(vec, paf->normfac);
+ VecAddf(pa->no, pa->no, vec);
+ }
+ pa->lifetime= paf->lifetime;
+ if(paf->randlife!=0.0) {
+ pa->lifetime*= 1.0f+ (float)(paf->randlife*( BLI_drand() - 0.5));
+ }
+ pa->mat_nr= 1;
+
+ make_particle_keys(0, a, paf, pa, force, deform, mtexmove);
+ }
+
+ if(deform) end_latt_deform();
+
+ /* restore */
+ G.scene->r.cfra= cfraont;
+ G.scene->r.framelen= framelenont;
+ give_mesh_mvert(0, 0, 0, 0);
+
+
+ /* hele hiera terug */
+ par= ob;
+ while(par) {
+ popfirst(par);
+ /* geen ob->ipo doen: insertkey behouden */
+ do_ob_key(par);
+ par= par->parent;
+ }
+
+ /* restore: NA popfirst */
+ ob->sf= sfraont;
+
+ disable_speed_curve(0);
+
+ waitcursor(0);
+
+}
+
+/* ************* WAVE **************** */
+
+void calc_wave_deform(WaveEff *wav, float ctime, float *co)
+{
+ /* co is in lokale coords */
+ float lifefac, x, y, amplit;
+
+ /* mag eigenlijk niet voorkomen */
+ if((wav->flag & (WAV_X+WAV_Y))==0) return;
+
+ lifefac= wav->height;
+
+ if( wav->lifetime!=0.0) {
+ x= ctime - wav->timeoffs;
+ if(x>wav->lifetime) {
+
+ lifefac= x-wav->lifetime;
+
+ if(lifefac > wav->damp) lifefac= 0.0;
+ else lifefac= (float)(wav->height*(1.0 - sqrt(lifefac/wav->damp)));
+ }
+ }
+ if(lifefac==0.0) return;
+
+ x= co[0]-wav->startx;
+ y= co[1]-wav->starty;
+
+ if(wav->flag & WAV_X) {
+ if(wav->flag & WAV_Y) amplit= (float)sqrt( (x*x + y*y));
+ else amplit= x;
+ }
+ else amplit= y;
+
+ /* zo maaktie mooie cirkels */
+ amplit-= (ctime-wav->timeoffs)*wav->speed;
+
+ if(wav->flag & WAV_CYCL) {
+ amplit = (float)fmod(amplit-wav->width, 2.0*wav->width) + wav->width;
+ }
+
+ /* GAUSSIAN */
+
+ if(amplit> -wav->width && amplit<wav->width) {
+
+ amplit = amplit*wav->narrow;
+ amplit= (float)(1.0/exp(amplit*amplit) - wav->minfac);
+
+ co[2]+= lifefac*amplit;
+ }
+}
+
+void object_wave(Object *ob)
+{
+ WaveEff *wav;
+ DispList *dl;
+ Mesh *me;
+ MVert *mvert;
+ float *fp, ctime;
+ int a, first;
+
+ /* is er een mave */
+ wav= ob->effect.first;
+ while(wav) {
+ if(wav->type==EFF_WAVE) break;
+ wav= wav->next;
+ }
+ if(wav==0) return;
+
+ if(ob->type==OB_MESH) {
+
+ ctime= bsystem_time(ob, 0, (float)G.scene->r.cfra, 0.0);
+ first= 1;
+
+ me= ob->data;
+ dl= find_displist_create(&ob->disp, DL_VERTS);
+
+ if(dl->verts) MEM_freeN(dl->verts);
+ dl->nr= me->totvert;
+ dl->verts= MEM_mallocN(3*4*me->totvert, "wave");
+
+ wav= ob->effect.first;
+ while(wav) {
+ if(wav->type==EFF_WAVE) {
+
+ /* voorberekenen */
+ wav->minfac= (float)(1.0/exp(wav->width*wav->narrow*wav->width*wav->narrow));
+ if(wav->damp==0) wav->damp= 10.0f;
+
+ mvert= me->mvert;
+ fp= dl->verts;
+
+ for(a=0; a<me->totvert; a++, mvert++, fp+=3) {
+ if(first) VECCOPY(fp, mvert->co);
+ calc_wave_deform(wav, ctime, fp);
+ }
+ first= 0;
+ }
+ wav= wav->next;
+ }
+ }
+}
diff --git a/source/blender/blenkernel/intern/exotic.c b/source/blender/blenkernel/intern/exotic.c
new file mode 100644
index 00000000000..104b1b24efe
--- /dev/null
+++ b/source/blender/blenkernel/intern/exotic.c
@@ -0,0 +1,4081 @@
+/* exotic.c mei 95 MIXED MODEL
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * eigen videoscape formaat:
+ *
+ *
+ * lamp:
+ * 3DG2
+ aantal_lampen
+
+ type
+ spsi spbl
+ r, g, b, energy
+ locx, locy, locz
+ vecx, vecy, vecz
+
+
+ curve / nurbs:
+ 3DG3
+ 5 of 11 (curve of surf)
+ aantal_nurbs
+ extr1 extr2
+
+ mat[0][0] mat[0][1] mat[0][2] mat[0][3]
+ mat[1][0] mat[1][1] mat[1][2] mat[1][3]
+ ...
+
+ type
+ pntsu, pntsv
+ resolu, resolv
+ orderu, orderv
+ flagu, flagv
+
+ (als type==nurb) x y z w
+ x y z w
+ ...
+ (als type==bez) xyz xyz xyz h1 h2 h3
+ xyz xyz xyz h1 h2 h3
+ ...
+ *
+ *
+ */
+
+
+#include <ctype.h> /* isdigit, isspace */
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
+#ifndef WIN32
+#include <unistd.h>
+#else
+#include "BLI_winstuff.h"
+#include <io.h>
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_object_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_material_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_image_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_userdef_types.h"
+
+#include "BKE_bad_level_calls.h"
+#include "BKE_utildefines.h"
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_mesh.h"
+#include "BKE_library.h"
+#include "BKE_global.h"
+#include "BKE_object.h"
+#include "BKE_material.h"
+#include "BKE_exotic.h"
+/* #include "BKE_error.h" */
+#include "BKE_screen.h"
+#include "BKE_displist.h"
+#include "BKE_curve.h"
+
+#include "BPY_extern.h"
+
+/***/
+
+static int is_dxf(char *str);
+static void dxf_read(char *filename);
+
+/***/
+
+static void read_videoscape_mesh(char *str)
+{
+ Object *ob;
+ Mesh *me;
+ MVert *mvert;
+ MFace *mface;
+ Material *ma;
+ FILE *fp;
+ float *vertdata, *vd, min[3], max[3], cent[3], ftemp;
+ unsigned int color[32], col;
+ int totcol, a, b, verts, tottria=0, totquad=0, totedge=0, poly, nr0, nr, first;
+ short end;
+ char s[50];
+
+ fp= fopen(str, "rb");
+ if(fp==NULL) {
+ error("Can't read file");
+ return;
+ }
+
+ fscanf(fp, "%40s", s);
+
+ fscanf(fp, "%d\n", &verts);
+ if(verts<=0) {
+ fclose(fp);
+ error("Read error");
+ return;
+ }
+
+ if(verts>65000) {
+ error("too many vertices");
+ fclose(fp);
+ return;
+ }
+
+ INIT_MINMAX(min, max);
+ vd= vertdata= MEM_mallocN(sizeof(float)*3*verts, "videoscapelezer");
+
+ for(a=0; a<verts; a++) {
+ fscanf(fp, "%f %f %f", vd, vd+1, vd+2);
+ DO_MINMAX(vd, min, max);
+ vd+=3;
+ }
+
+ /* de vlakken en kleuren tellen */
+ for(a=0; a<32; a++) color[a]= 0;
+ totcol= 0;
+ end= 1;
+ while(end>0) {
+ end= fscanf(fp,"%d", &poly);
+ if(end<=0) break;
+
+ if(poly==3) tottria++;
+ else if(poly==4) totquad++;
+ else totedge+= poly;
+
+ for(a=0;a<poly;a++) {
+ end= fscanf(fp,"%d", &nr);
+ if(end<=0) break;
+ }
+ if(end<=0) break;
+
+ end= fscanf(fp,"%i\n", &col);
+ col &= 0xF0F0F0;
+ for(a=0; a<totcol; a++) {
+ if(color[a]==col) break;
+ }
+ if(a>=totcol && totcol<32) {
+ color[totcol]= col;
+ totcol++;
+ }
+ }
+
+ if(totedge+tottria+totquad>65000) {
+ printf(" var1: %d, var2: %d, var3: %d \n", totedge, tottria, totquad);
+ error("too many faces");
+ MEM_freeN(vertdata);
+ fclose(fp);
+ return;
+ }
+
+ /* nieuw object */
+ ob= add_object(OB_MESH);
+ me= ob->data;
+ me->totvert= verts;
+ me->totface= totedge+tottria+totquad;
+
+ me->mvert= MEM_callocN(me->totvert*sizeof(MVert), "mverts");
+ if(me->totface) me->mface= MEM_callocN(me->totface*sizeof(MFace), "mface");
+
+ /* kleuren */
+ if(totcol) {
+ ob->mat= MEM_callocN(sizeof(void *)*totcol, "ob->mat");
+ me->mat= MEM_callocN(sizeof(void *)*totcol, "me->mat");
+ me->totcol= totcol;
+ ob->totcol= (unsigned char) me->totcol;
+ ob->actcol= 1;
+ }
+
+ /* materialen */
+ for(a=0; a<totcol; a++) {
+ ma= G.main->mat.first;
+ while(ma) {
+ if(ma->mtex[0]==0) {
+ col= rgb_to_cpack(ma->r, ma->g, ma->b);
+ if(color[a]==col) {
+ me->mat[a]= ma;
+ ma->id.us++;
+ break;
+ }
+ }
+ ma= ma->id.next;
+ }
+ if(ma==0) {
+ ma= add_material("ext");
+ me->mat[a]= ma;
+ cpack_to_rgb(color[a], cent, cent+1, cent+2);
+ ma->r= cent[0];
+ ma->g= cent[1];
+ ma->b= cent[2];
+ automatname(ma);
+ }
+ }
+
+ /* verts */
+
+ cent[0]= (min[0]+max[0])/2.0f;
+ cent[1]= (min[1]+max[1])/2.0f;
+ cent[2]= (min[2]+max[2])/2.0f;
+ VECCOPY(ob->loc, cent);
+
+ a= me->totvert;
+ vd= vertdata;
+ mvert= me->mvert;
+ while(a--) {
+ VecSubf(mvert->co, vd, cent);
+ mvert++;
+ vd+= 3;
+ }
+
+ /* faces */
+ if(me->totface) {
+ rewind(fp);
+
+ fscanf(fp, "%40s", s);
+ fscanf(fp, "%d\n", &verts);
+ /* fake read */
+ for(a=0;a<verts;a++) {
+ fscanf(fp, "%f %f %f", &ftemp, &ftemp, &ftemp);
+ }
+
+ a= me->totface;
+ mface= me->mface;
+ while(a--) {
+ end= fscanf(fp,"%d", &poly);
+ if(end<=0) break;
+
+ if(poly==3 || poly==4) {
+ fscanf(fp,"%d", &nr);
+ mface->v1= MIN2(nr, me->totvert-1);
+ fscanf(fp,"%d", &nr);
+ mface->v2= MIN2(nr, me->totvert-1);
+ fscanf(fp,"%d", &nr);
+ mface->v3= MIN2(nr, me->totvert-1);
+ if(poly==4) {
+ if( fscanf(fp,"%d", &nr) <=0 ) break;
+ mface->v4= MIN2(nr, me->totvert-1);
+ }
+ mface->edcode= 3;
+
+ test_index_mface(mface, poly);
+
+ mface++;
+ }
+ else {
+ if( fscanf(fp,"%d", &nr0) <=0) break;
+ first= nr0;
+ for(b=1; b<poly; b++) {
+ end= fscanf(fp,"%d", &nr);
+ if(end<=0) break;
+ nr= MIN2(nr, me->totvert-1);
+ mface->v1= nr;
+ mface->v2= nr0;
+ nr0= nr;
+ mface++;
+ a--;
+ }
+ mface->v1= first;
+ mface->v2= nr;
+ mface->edcode= 1;
+ mface++;
+ if(end<=0) break;
+ }
+ end= fscanf(fp,"%i", &col);
+ col &= 0xF0F0F0;
+ if(end<=0) break;
+
+ for(b=0; b<totcol; b++) {
+ if(color[b]==col) {
+ (mface-1)->mat_nr= b;
+ break;
+ }
+ }
+ }
+ }
+
+ fclose(fp);
+ MEM_freeN(vertdata);
+
+ G.obedit= ob;
+ make_editMesh();
+ load_editMesh();
+ free_editMesh();
+ G.obedit= 0;
+ tex_space_mesh(me);
+ waitcursor(1);
+}
+
+static void read_radiogour(char *str)
+{
+ Object *ob;
+ Mesh *me;
+ MVert *mvert;
+ MFace *mface;
+ FILE *fp;
+ float *vertdata, *vd, min[3], max[3], cent[3], ftemp;
+ unsigned int *colv, *colf, *colvertdata;
+ int itemp, a, b, verts, tottria=0, totquad=0, totedge=0, poly, nr0, nr, first;
+ short end;
+ char s[50];
+
+ fp= fopen(str, "rb");
+ if(fp==NULL) {
+ error("Can't read file");
+ return;
+ }
+
+ fscanf(fp, "%40s", s);
+
+ fscanf(fp, "%d\n", &verts);
+ if(verts<=0) {
+ fclose(fp);
+ error("Read error");
+ return;
+ }
+
+ if(verts>65000) {
+ error("too many vertices");
+ fclose(fp);
+ return;
+ }
+
+ INIT_MINMAX(min, max);
+ vd= vertdata= MEM_mallocN(sizeof(float)*3*verts, "videoscapelezer");
+ colv= colvertdata= MEM_mallocN(verts*sizeof(float), "coldata");
+
+ for(a=0; a<verts; a++) {
+ fscanf(fp, "%f %f %f %i", vd, vd+1, vd+2, colv);
+ DO_MINMAX(vd, min, max);
+ vd+=3;
+ colv++;
+ }
+
+ /* de vlakken tellen */
+ end= 1;
+ while(end>0) {
+ end= fscanf(fp,"%d", &poly);
+ if(end<=0) break;
+
+ if(poly==3) tottria++;
+ else if(poly==4) totquad++;
+ else totedge+= poly;
+
+ for(a=0;a<poly;a++) {
+ end= fscanf(fp,"%d", &nr);
+ if(end<=0) break;
+ }
+ if(end<=0) break;
+
+ }
+
+ if(totedge+tottria+totquad>65000) {
+ printf(" var1: %d, var2: %d, var3: %d \n", totedge, tottria, totquad);
+ error("too many faces");
+ MEM_freeN(vertdata);
+ MEM_freeN(colvertdata);
+ fclose(fp);
+ return;
+ }
+
+ /* nieuw object */
+ ob= add_object(OB_MESH);
+ me= ob->data;
+ me->totvert= verts;
+ me->totface= totedge+tottria+totquad;
+ me->flag= 0;
+ me->mvert= MEM_callocN(me->totvert*sizeof(MVert), "mverts");
+ if(me->totface) me->mface= MEM_callocN(me->totface*sizeof(MFace), "mface");
+
+ /* verts */
+
+ cent[0]= (min[0]+max[0])/2.0f;
+ cent[1]= (min[1]+max[1])/2.0f;
+ cent[2]= (min[2]+max[2])/2.0f;
+ VECCOPY(ob->loc, cent);
+
+ a= me->totvert;
+ vd= vertdata;
+ mvert= me->mvert;
+ while(a--) {
+ VecSubf(mvert->co, vd, cent);
+ mvert++;
+ vd+= 3;
+ }
+
+ /* faces */
+ if(me->totface) {
+ rewind(fp);
+
+ fscanf(fp, "%40s", s);
+ fscanf(fp, "%d\n", &verts);
+ for(a=0;a<verts;a++) {
+ fscanf(fp, "%f %f %f %i", &ftemp, &ftemp, &ftemp, &itemp);
+ }
+
+ a= me->totface;
+ mface= me->mface;
+ while(a--) {
+ end= fscanf(fp,"%d", &poly);
+ if(end<=0) break;
+
+ if(poly==3 || poly==4) {
+ fscanf(fp,"%d", &nr);
+ mface->v1= MIN2(nr, me->totvert-1);
+ fscanf(fp,"%d", &nr);
+ mface->v2= MIN2(nr, me->totvert-1);
+ fscanf(fp,"%d", &nr);
+ mface->v3= MIN2(nr, me->totvert-1);
+ if(poly==4) {
+ if( fscanf(fp,"%d", &nr) <=0 ) break;
+ mface->v4= MIN2(nr, me->totvert-1);
+ }
+ mface->edcode= 3;
+
+ test_index_mface(mface, poly);
+
+ mface++;
+ }
+ else {
+ if( fscanf(fp,"%d", &nr0) <=0) break;
+ first= nr0;
+ for(b=1; b<poly; b++) {
+ end= fscanf(fp,"%d", &nr);
+ if(end<=0) break;
+ nr= MIN2(nr, me->totvert-1);
+ mface->v1= nr;
+ mface->v2= nr0;
+ nr0= nr;
+ mface++;
+ a--;
+ }
+ mface->v1= first;
+ mface->v2= nr;
+ mface->edcode= 1;
+ mface->flag= ME_SMOOTH;
+
+ mface++;
+ if(end<=0) break;
+ }
+ }
+
+ /* mcol is per vlak 4 kleuren */
+ me->mcol= MEM_mallocN(4*sizeof(int)*me->totface, "mcol");
+ colf= (unsigned int *)me->mcol;
+
+ a= me->totface;
+ mface= me->mface;
+ while(a--) {
+
+ colf[0]= colvertdata[mface->v1];
+ colf[1]= colvertdata[mface->v2];
+ colf[2]= colvertdata[mface->v3];
+ colf[3]= colvertdata[mface->v4];
+
+ colf+= 4;
+ mface++;
+ }
+
+ MEM_freeN(colvertdata);
+ }
+
+ fclose(fp);
+ MEM_freeN(vertdata);
+
+ G.obedit= ob;
+ make_editMesh();
+ load_editMesh();
+ free_editMesh();
+
+ G.obedit= 0;
+ tex_space_mesh(me);
+
+ waitcursor(1);
+}
+
+
+static void read_videoscape_lamp(char *str)
+{
+ Object *ob;
+ Lamp *la;
+ FILE *fp;
+ float vec[3], *q1;
+ int tot, val;
+ char s[50];
+
+ fp= fopen(str, "rb");
+ if(fp==NULL) {
+ error("Can't read file");
+ return;
+ }
+
+ fscanf(fp, "%40s", s);
+ fscanf(fp, "%d\n", &tot);
+
+ while(tot--) {
+ ob= add_object(OB_LAMP);
+ la= ob->data;
+
+ fscanf(fp, "%d\n", &val);
+ la->type= val;
+ if(la->type==1) la->type= LA_SPOT;
+ else if(la->type==2) la->type= LA_SUN;
+
+ fscanf(fp, "%f %f\n", &la->spotsize, &la->spotblend);
+
+ fscanf(fp, "%f %f %f %f\n", &la->r, &la->g, &la->b, &la->energy);
+
+ fscanf(fp, "%f %f %f\n", ob->loc, ob->loc+1, ob->loc+2);
+ val= fscanf(fp, "%f %f %f\n", vec, vec+1, vec+2);
+ q1= vectoquat(vec, 5, 2);
+ QuatToEul(q1, ob->rot);
+
+ if(val<=0) break;
+
+ }
+ fclose(fp);
+}
+
+static void read_videoscape_nurbs(char *str)
+{
+ Object *ob;
+ Curve *cu;
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ FILE *fp;
+ float tmat[4][4], omat[3][3], imat[3][3], mat[3][3];
+ int a, tot, type, val;
+ char s[50];
+
+ fp= fopen(str, "rb");
+ if(fp==NULL) {
+ error("Can't read file");
+ return;
+ }
+
+ fscanf(fp, "%40s", s);
+ fscanf(fp, "%d\n", &type);
+
+ if(type==5) ob= add_object(OB_SURF);
+ else ob= add_object(OB_CURVE);
+ cu= ob->data;
+
+ fscanf(fp, "%d\n", &tot);
+ fscanf(fp, "%d %d\n", &type, &val);
+
+ cu->ext1= 0.002f*type;
+ cu->ext2= 0.002f*val;
+
+ for(a=0; a<4; a++) fscanf(fp, "%e %e %e %e\n", tmat[a], tmat[a]+1, tmat[a]+2, tmat[a]+3);
+
+ VECCOPY(ob->loc, tmat[3]);
+
+ Mat3CpyMat4(omat, tmat);
+ Mat3ToEul(omat, ob->rot);
+ EulToMat3(ob->rot, mat);
+ Mat3Inv(imat, mat);
+ Mat3MulMat3(tmat, imat, omat);
+
+ while(tot--) {
+ nu= (Nurb*)MEM_callocN(sizeof(Nurb),"nu from exotic");
+ BLI_addtail(&cu->nurb, nu);
+
+ fscanf(fp, "%d\n", &type);
+ nu->type= type;
+
+ fscanf(fp, "%d %d\n", &type, &val);
+ nu->pntsu= type; nu->pntsv= val;
+ fscanf(fp, "%d %d\n", &type, &val);
+ nu->resolu= type; nu->resolv= val;
+ fscanf(fp, "%d %d\n", &type, &val);
+ nu->orderu= type; nu->orderv= val;
+ fscanf(fp, "%d %d\n", &type, &val);
+ nu->flagu= type; nu->flagv= val;
+
+ if( (nu->type & 7)==CU_BEZIER) {
+ a= nu->pntsu;
+ nu->bezt= bezt= MEM_callocN(a*sizeof(BezTriple), "bezt from exotic");
+ while(a--) {
+ fscanf(fp, "%f %f %f ", bezt->vec[0], bezt->vec[0]+1, bezt->vec[0]+2);
+ Mat4MulVecfl(tmat, bezt->vec[0]);
+ fscanf(fp, "%f %f %f ", bezt->vec[1], bezt->vec[1]+1, bezt->vec[1]+2);
+ Mat4MulVecfl(tmat, bezt->vec[1]);
+ fscanf(fp, "%f %f %f ", bezt->vec[2], bezt->vec[2]+1, bezt->vec[2]+2);
+ Mat4MulVecfl(tmat, bezt->vec[2]);
+ fscanf(fp, "%d %d\n", &type, &val);
+ bezt->h1= type;
+ bezt->h2= val;
+ bezt++;
+ }
+ }
+ else {
+ a= nu->pntsu*nu->pntsv;
+ if(a) {
+ nu->bp= bp= MEM_callocN(a*sizeof(BPoint), "bp from exotic");
+ while(a--) {
+ fscanf(fp, "%f %f %f %f\n", bp->vec, bp->vec+1, bp->vec+2, bp->vec+3);
+ Mat4MulVecfl(tmat, bp->vec);
+ bp++;
+ }
+
+ val= KNOTSU(nu);
+ nu->knotsu= MEM_mallocN(sizeof(float)*val, "knots");
+ for(a=0; a<val; a++) fscanf(fp, "%f\n", nu->knotsu+a);
+
+ if(nu->pntsv>1) {
+ val= KNOTSV(nu);
+ nu->knotsv= MEM_mallocN(sizeof(float)*val, "knots");
+ for(a=0; a<val; a++) fscanf(fp, "%f\n", nu->knotsv+a);
+ }
+ }
+ else {
+ BLI_remlink(&cu->nurb, nu);
+ MEM_freeN(nu);
+ }
+ }
+ }
+ fclose(fp);
+ makeDispList(ob);
+}
+
+static void read_videoscape(char *str)
+{
+ int file, type;
+ unsigned short val, numlen;
+ char name[FILE_MAXDIR+FILE_MAXFILE], head[FILE_MAXFILE], tail[FILE_MAXFILE];
+
+ strcpy(name, str);
+
+ while( TRUE ) {
+ file= open(name, O_BINARY|O_RDONLY);
+ if(file<=0) break;
+ else {
+ read(file, &type, 4);
+ close(file);
+
+ if(type==DDG1) read_videoscape_mesh(name);
+ else if(type==DDG2) read_videoscape_lamp(name);
+ else if(type==DDG3) read_videoscape_nurbs(name);
+ }
+
+ val = BLI_stringdec(name, head, tail, &numlen);
+ BLI_stringenc(name, head, tail, numlen, val + 1);
+
+ }
+}
+
+
+/* ***************** INVENTOR ******************* */
+
+
+#define IV_MAXSTACK 500000
+#define IV_MAXFIELD 10
+#define IV_MAXCOL 16
+
+static float *iv_data_stack;
+static float ivcolors[IV_MAXCOL][3];
+static Object *ivsurf;
+static ListBase ivbase;
+
+struct IvNode {
+ struct IvNode *next, *prev;
+ char *nodename;
+ char *fieldname[IV_MAXFIELD];
+ int datalen[IV_MAXFIELD];
+ float *data[IV_MAXFIELD];
+};
+
+static int iv_curcol=0;
+
+static int iv_colornumber(struct IvNode *iv)
+{
+ float *fp, fr = 0.0, fg = 0.0, fb = 0.0;
+ int a;
+ char *cp;
+
+ /* terugzoeken naar laatste materiaal */
+ while(iv) {
+ if( strcmp(iv->nodename, "Material")==0) {
+ fp= iv->data[0];
+ if(fp==0) fp= iv->data[1];
+ if(fp) {
+ fr= fp[0];
+ fg= fp[1];
+ fb= fp[2];
+ }
+ break;
+ }
+ else if( strcmp(iv->nodename, "BaseColor")==0) {
+ fp= iv->data[0];
+ fr= fp[0];
+ fg= fp[1];
+ fb= fp[2];
+ break;
+ }
+ else if( strcmp(iv->nodename, "PackedColor")==0) {
+ cp= (char *)iv->data[0];
+ fr= cp[3]/255.0f;
+ fg= cp[2]/255.0f;
+ fb= cp[1]/255.0f;
+ break;
+ }
+ iv= iv->prev;
+
+ }
+ if(iv==0) return 0;
+ if(iv->datalen[0]<3) return 0;
+
+ for(a=0; a<iv_curcol; a++) {
+
+ if(ivcolors[a][0]== fr)
+ if(ivcolors[a][1]== fg)
+ if(ivcolors[a][2]== fb) return a+1
+ ;
+ }
+
+ if(a>=IV_MAXCOL) a= IV_MAXCOL-1;
+ iv_curcol= a+1;
+ ivcolors[a][0]= fr;
+ ivcolors[a][1]= fg;
+ ivcolors[a][2]= fb;
+
+ return iv_curcol;
+}
+
+static int iv_finddata(struct IvNode *iv, char *field, int fieldnr)
+{
+ /* zoek naar "field", tel lengte data en maak datablok. return skipdata */
+ float *fp;
+ int len, stackcount, skipdata=0;
+ char *cpa, terminator, str[64];
+ long i;
+
+ len= strlen(field);
+
+ cpa= iv->nodename+1;
+ while( *cpa != '}' ) {
+
+ if( *cpa == *field ) {
+ if( strncmp(cpa, field, len)==0 ) {
+ iv->fieldname[fieldnr]= cpa;
+
+ /* lezen tot aan eerste karakter */
+ cpa+= len;
+ skipdata+= len;
+ *cpa= 0;
+ cpa++;
+ skipdata++;
+
+ while( *cpa==32 || *cpa==13 || *cpa==10 || *cpa==9) cpa++;
+ if( *cpa=='[' ) {
+ terminator= ']';
+ cpa++;
+ skipdata++;
+ }
+ else terminator= 13;
+
+ stackcount= 0;
+ fp= iv_data_stack;
+
+ while( *cpa!=terminator && *cpa != '}' ) {
+
+ /* in fact, isdigit should include the dot and minus */
+ if( (isdigit(*cpa) || *cpa=='.' || *cpa=='-') && (isspace(cpa[-1]) || cpa[-1]==0 || cpa[-1]==',') ) {
+ if(cpa[1]=='x') {
+ memcpy(str, cpa, 16);
+ str[16]= 0;
+
+ sscanf(str, "%x", (int *)fp);
+ }
+ else {
+ /* atof doesn't stop after the first float
+ * in a long string at Windows... so we copy
+ * the float to a new string then atof... */
+
+ i=strpbrk(cpa, ", \n")-cpa;
+
+ if (i>63) *fp= 0.0;
+ else {
+ memcpy(str, cpa, i);
+ str[i]=0;
+
+ *fp= (float) atof(str);
+ }
+ }
+
+ stackcount++;
+ if(stackcount>=IV_MAXSTACK) {
+ printf("stackoverflow in IV read\n");
+ break;
+ }
+ fp++;
+ }
+ cpa++;
+ skipdata++;
+ }
+
+ iv->datalen[fieldnr]= stackcount;
+ if(stackcount) {
+ iv->data[fieldnr]= MEM_mallocN(sizeof(float)*stackcount, "iv_finddata");
+ memcpy(iv->data[fieldnr], iv_data_stack, sizeof(float)*stackcount);
+ }
+ else iv->data[fieldnr]= 0;
+
+ return skipdata;
+ }
+ }
+ cpa++;
+ skipdata++;
+ }
+
+ return skipdata;
+}
+
+static void read_iv_index(float *data, float *baseadr, float *index, int nr, int coordtype)
+{
+ /* in data schrijven: baseadr met offset index (aantal nr)*/
+ float *fp;
+ int ofs;
+
+ while(nr--) {
+ ofs= (int) *index;
+ fp= baseadr+coordtype*ofs;
+ VECCOPY(data, fp);
+ data+= 3;
+ index++;
+ }
+}
+
+
+
+static void read_inventor(char *str, struct ListBase *listb)
+{
+ struct IvNode *iv, *ivp, *ivn;
+ char *maindata, *md, *cpa;
+ float *index, *data, *fp;
+ int file, filelen, count, face, nr = 0;
+ int skipdata, ok, a, b, tot, first, colnr, coordtype, polytype, *idata;
+ struct DispList *dl;
+
+ ivbase.first= ivbase.last= 0;
+ iv_curcol= 0;
+ ivsurf= 0;
+
+ file= open(str, O_BINARY|O_RDONLY);
+ if(file== -1) {
+ error("Can't read file\n");
+ return;
+ }
+ filelen= BLI_filesize(file);
+
+ maindata= MEM_mallocN(filelen, "leesInventor");
+ read(file, maindata, filelen);
+ close(file);
+
+ iv_data_stack= MEM_mallocN(sizeof(float)*IV_MAXSTACK, "ivstack");
+
+ /* eerste preprocess: commentar eruit */
+ md= maindata+20;
+ count= 20;
+ while(count<filelen) {
+ if( *md=='#' ) { /* comment */
+ while( *md!=13 && *md!=10) { /* enters */
+ *md= 32;
+ md++;
+ count++;
+ if(count>=filelen) break;
+ }
+ }
+ md++;
+ count++;
+ }
+
+
+ /* we gaan alles ordenen: welke zijn de nodes en de fields? */
+ md= maindata;
+ count= 0;
+ while(count<filelen) {
+ if( *md=='{' ) { /* terug lezen */
+
+ cpa= md-1;
+ while( *cpa==32 || *cpa==13 || *cpa==10 || *cpa==9) { /* spaties/enters/tab weg */
+ *cpa= 0;
+ cpa--;
+ }
+
+ while( *cpa>32 && *cpa<128) cpa--;
+ cpa++;
+ *md= 0;
+
+ ok= 0;
+ skipdata= 0;
+ iv= MEM_callocN(sizeof(struct IvNode), "leesInventor");
+ iv->nodename= cpa;
+
+ if(strcmp(cpa, "Coordinate3")==0 || strcmp(cpa, "Coordinate4")==0) {
+ skipdata= iv_finddata(iv, "point", 0);
+ ok= 1;
+ }
+ else if(strcmp(cpa, "VertexProperty")==0) {
+ skipdata= iv_finddata(iv, "vertex", 0);
+ ok= 1;
+ }
+ else if(strcmp(cpa, "IndexedLineSet")==0) {
+ skipdata= iv_finddata(iv, "coordIndex", 0);
+ ok= 1;
+ }
+ else if(strcmp(cpa, "IndexedTriangleMesh")==0) {
+ skipdata= iv_finddata(iv, "coordIndex", 0);
+ ok= 1;
+ }
+ else if(strcmp(cpa, "IndexedFaceSet")==0) {
+ skipdata= iv_finddata(iv, "coordIndex", 0);
+ ok= 1;
+ }
+ else if(strcmp(cpa, "FaceSet")==0) {
+ skipdata= iv_finddata(iv, "numVertices", 0);
+ ok= 1;
+ }
+ else if(strcmp(cpa, "Material")==0) {
+ iv_finddata(iv, "diffuseColor", 0);
+ iv_finddata(iv, "ambientColor", 1);
+ ok= 1;
+ }
+ else if(strcmp(cpa, "BaseColor")==0) {
+ iv_finddata(iv, "rgb", 0);
+ ok= 1;
+ }
+ else if(strcmp(cpa, "PackedColor")==0) {
+ iv_finddata(iv, "rgba", 0);
+ ok= 1;
+ }
+ else if(strcmp(cpa, "QuadMesh")==0) {
+ iv_finddata(iv, "verticesPerColumn", 0);
+ iv_finddata(iv, "verticesPerRow", 1);
+
+ ok= 1;
+ }
+ else if(strcmp(cpa, "IndexedTriangleStripSet")==0) {
+ skipdata= iv_finddata(iv, "coordIndex", 0);
+ ok= 1;
+ }
+ else if(strcmp(cpa, "TriangleStripSet")==0) {
+ skipdata= iv_finddata(iv, "numVertices", 0);
+ ok= 1;
+ }
+ else if(strcmp(cpa, "IndexedNurbsSurface")==0 || strcmp(cpa, "NurbsSurface")==0) {
+ iv_finddata(iv, "numUControlPoints", 0);
+ iv_finddata(iv, "numVControlPoints", 1);
+ iv_finddata(iv, "uKnotVector", 2);
+ iv_finddata(iv, "vKnotVector", 3);
+ ok= 1;
+ }
+ else {
+ /* naar 't einde */
+ while( *md != '}') {
+ md++;
+ count++;
+ if(count<filelen) break;
+ }
+ }
+
+
+ if(ok) {
+ BLI_addtail(&ivbase, iv);
+ md+= skipdata;
+ count+= skipdata;
+ }
+ else MEM_freeN(iv);
+
+ }
+ md++;
+ count++;
+ }
+
+ /* nodes samenvoegen */
+ iv= ivbase.first;
+
+ while(iv) {
+ ivn= iv->next;
+
+ if( strncmp(iv->nodename, "Indexed", 7)==0) {
+ /* terugzoeken: zelfde naam? */
+
+ ivp= iv->prev;
+ while(ivp) {
+ if(strcmp(iv->nodename, ivp->nodename)==0) break;
+
+ if(strcmp(ivp->nodename, "Coordinate3")==0 ||
+ strcmp(ivp->nodename, "Coordinate4")==0 ||
+ strcmp(ivp->nodename, "VertexProperty")==0) {
+ ivp= 0;
+ break;
+ }
+ ivp= ivp->prev;
+ }
+
+ if(ivp) {
+ /* iv bij ivp voegen */
+
+ tot= iv->datalen[0] + ivp->datalen[0];
+ if(tot) {
+ data= MEM_mallocN(tot*sizeof(float), "samenvoeg iv");
+ memcpy(data, ivp->data[0], sizeof(float)*ivp->datalen[0]);
+ memcpy(data+ivp->datalen[0], iv->data[0], sizeof(float)*iv->datalen[0]);
+
+ ivp->datalen[0]+= iv->datalen[0];
+ MEM_freeN(ivp->data[0]);
+ ivp->data[0]= data;
+
+ BLI_remlink(&ivbase, iv);
+ MEM_freeN(iv->data[0]);
+ MEM_freeN(iv);
+ }
+ }
+ }
+
+ iv= ivn;
+ }
+
+
+ /* Nodes omzetten naar DispLists */
+ iv= ivbase.first;
+ while(iv) {
+
+ /* printf(" Node: %s\n", iv->nodename); */
+ /* if(iv->fieldname[0]) printf(" Field: %s len %d\n", iv->fieldname[0], iv->datalen[0]); */
+ coordtype= 3;
+
+ if( strcmp(iv->nodename, "IndexedLineSet")==0 ) {
+
+ colnr= iv_colornumber(iv);
+
+ /* terugzoeken naar data */
+ ivp= iv;
+ while(ivp->prev) {
+ ivp= ivp->prev;
+ if( strcmp(ivp->nodename, "Coordinate3")==0 ) {
+ coordtype= 3;
+ break;
+ }
+ if( strcmp(ivp->nodename, "Coordinate4")==0 ) {
+ coordtype= 4;
+ break;
+ }
+ }
+ if(ivp) {
+
+ /* tel het aantal lijnen */
+ tot= 0;
+ index= iv->data[0];
+ for(a=0; a<iv->datalen[0]-1; a++) {
+ if(index[0]!= -1 && index[1]!= -1) tot++;
+ index++;
+ }
+
+ tot*= 2; /* aantal vertices */
+ dl= MEM_callocN(sizeof(struct DispList)+tot*3*sizeof(float), "leesInventor1");
+ BLI_addtail(listb, dl);
+ dl->type= DL_SEGM;
+ dl->nr= 2;
+ dl->parts= tot/2;
+ dl->col= colnr;
+ data= (float *)(dl+1);
+
+ index= iv->data[0];
+ for(a=0; a<iv->datalen[0]-1; a++) {
+ if(index[0]!= -1 && index[1]!= -1) {
+ read_iv_index(data, ivp->data[0], index, 2, coordtype);
+ data+= 6;
+ }
+ index++;
+ }
+ }
+ }
+ else if( strcmp(iv->nodename, "FaceSet")==0 ) {
+
+ colnr= iv_colornumber(iv);
+
+ /* terugzoeken naar data */
+ ivp= iv;
+ while(ivp->prev) {
+ ivp= ivp->prev;
+ if( strcmp(ivp->nodename, "Coordinate3")==0 ) {
+ coordtype= 3;
+ break;
+ }
+ if( strcmp(ivp->nodename, "Coordinate4")==0 ) {
+ coordtype= 4;
+ break;
+ }
+ }
+
+ if(ivp) {
+ /* tel het aantal driehoeken */
+ tot= 0;
+
+ index= iv->data[0];
+ polytype= (int) index[0];
+
+ for(a=0; a<iv->datalen[0]; a++) {
+ if(index[0]== polytype) tot++; /* een soort? */
+ index++;
+ }
+
+
+ tot*= polytype; /* aantal vertices */
+ dl= MEM_callocN(sizeof(struct DispList)+tot*3*sizeof(float), "leesInventor4");
+ BLI_addtail(listb, dl);
+ dl->type= DL_POLY;
+ dl->nr= polytype;
+ dl->parts= tot/polytype;
+ dl->col= colnr;
+ data= (float *)(dl+1);
+
+ index= ivp->data[0];
+ first= 1;
+ for(a=0; a<iv->datalen[0]; a++) {
+
+ VECCOPY(data, index);
+ data+= 3;
+ index+= 3;
+
+ VECCOPY(data, index);
+ data+= 3;
+ index+= 3;
+
+ VECCOPY(data, index);
+ data+= 3;
+ index+= 3;
+
+ if(polytype==4) {
+ VECCOPY(data, index);
+ data+= 3;
+ index+= 3;
+ }
+ }
+ }
+ }
+ else if( strcmp(iv->nodename, "TriangleStripSet")==0 ) {
+
+ colnr= iv_colornumber(iv);
+
+ /* terugzoeken naar data */
+ ivp= iv;
+ while(ivp->prev) {
+ ivp= ivp->prev;
+ if( strcmp(ivp->nodename, "Coordinate3")==0 ) {
+ coordtype= 3;
+ break;
+ }
+ if( strcmp(ivp->nodename, "Coordinate4")==0 ) {
+ coordtype= 4;
+ break;
+ }
+ }
+
+ if(ivp) {
+ /* tel het aantal driehoeken */
+ tot= 0;
+ face= 0;
+
+ index= iv->data[0]; /* afmeting strip */
+
+ for(a=0; a<iv->datalen[0]; a++) {
+ tot+= (int) index[0];
+ face+= ((int) index[0]) - 2;
+ index++;
+ }
+
+ dl= MEM_callocN(sizeof(struct DispList), "leesInventor4");
+ dl->verts= MEM_callocN( tot*3*sizeof(float), "dl verts");
+ dl->index= MEM_callocN( face*3*sizeof(int), "dl index");
+
+ dl->type= DL_INDEX3;
+ dl->nr= tot;
+ dl->parts= face;
+
+ BLI_addtail(listb, dl);
+ dl->col= colnr;
+
+ index= iv->data[0]; /* afmeting strip */
+ fp= ivp->data[0]; /* vertices */
+ data= dl->verts;
+ idata= dl->index;
+ first= 0;
+
+ for(a=0; a<iv->datalen[0]; a++) {
+
+ /* vertices */
+ for(b=0; b<index[0]; b++) {
+ VECCOPY(data, fp);
+ data+= 3;
+ fp+= coordtype;
+ }
+
+ /* indices */
+ for(b=0; b<index[0]-2; b++) {
+ idata[0]= first;
+ idata[1]= first+1;
+ idata[2]= first+2;
+ first++;
+ idata+= 3;
+ }
+ first+= 2;
+
+ index++;
+ }
+ }
+ }
+ else if( strcmp(iv->nodename, "IndexedFaceSet")==0 ) {
+
+ colnr= iv_colornumber(iv);
+
+ /* terugzoeken naar data */
+ ivp= iv;
+ while(ivp->prev) {
+ ivp= ivp->prev;
+ if( strcmp(ivp->nodename, "Coordinate3")==0 ) {
+ coordtype= 3;
+ break;
+ }
+ if( strcmp(ivp->nodename, "Coordinate4")==0 ) {
+ coordtype= 4;
+ break;
+ }
+ }
+ if(ivp) {
+
+ /* tel het aantal driehoeken */
+ face= 0;
+ index= iv->data[0];
+ for(a=0; a<iv->datalen[0]-2; a++) {
+ if(index[0]!= -1 && index[1]!= -1 && index[2]!= -1) face++;
+ index++;
+ }
+
+ /* aantal vertices */
+ tot= ivp->datalen[0]/coordtype;
+
+ if(tot) {
+ dl= MEM_callocN(sizeof(struct DispList), "leesInventor5");
+ BLI_addtail(listb, dl);
+ dl->type= DL_INDEX3;
+ dl->nr= tot;
+ dl->parts= face;
+ dl->col= colnr;
+
+ dl->verts= MEM_callocN( tot*3*sizeof(float), "dl verts");
+ dl->index= MEM_callocN(sizeof(int)*3*face, "dl index");
+
+ /* vertices */
+ fp= ivp->data[0];
+ data= dl->verts;
+ for(b=tot; b>0; b--) {
+ VECCOPY(data, fp);
+ data+= 3;
+ fp+= coordtype;
+ }
+
+ /* indices */
+ index= iv->data[0];
+ idata= dl->index;
+ first= 1;
+
+ for(a=0; a<iv->datalen[0]-2; a++) {
+
+ if(index[0]!= -1 && index[1]!= -1 && index[2]!= -1) {
+
+ /* deze truuk is om poly's met meer dan 3 vertices correct te vullen */
+ if(first) {
+ nr= (int) index[0];
+ first= 0;
+ }
+ idata[0]= nr;
+ idata[1]= (int) index[1];
+ idata[2]= (int) index[2];
+ idata+= 3;
+ }
+ else first= 1;
+
+ index++;
+ }
+ }
+ }
+ }
+ else if( strcmp(iv->nodename, "IndexedTriangleMesh")==0 ||
+ strcmp(iv->nodename, "IndexedTriangleStripSet")==0 ) {
+
+ colnr= iv_colornumber(iv);
+
+ /* terugzoeken naar data */
+ ivp= iv;
+ while(ivp->prev) {
+ ivp= ivp->prev;
+ if( strcmp(ivp->nodename, "Coordinate3")==0 ) {
+ coordtype= 3;
+ break;
+ }
+ if( strcmp(ivp->nodename, "Coordinate4")==0 ) {
+ coordtype= 4;
+ break;
+ }
+ }
+ if(ivp) {
+
+ /* tel het aantal driehoeken */
+ face= 0;
+ index= iv->data[0];
+ for(a=0; a<iv->datalen[0]-2; a++) {
+ if(index[0]!= -1 && index[1]!= -1 && index[2]!= -1) face++;
+ index++;
+ }
+
+ /* aantal vertices */
+ tot= ivp->datalen[0]/coordtype;
+
+ dl= MEM_callocN(sizeof(struct DispList), "leesInventor6");
+ BLI_addtail(listb, dl);
+ dl->type= DL_INDEX3;
+ dl->nr= tot;
+ dl->parts= face;
+ dl->col= colnr;
+
+ dl->verts= MEM_callocN( tot*3*sizeof(float), "dl verts");
+ dl->index= MEM_callocN(sizeof(int)*3*face, "dl index");
+
+ /* vertices */
+ fp= ivp->data[0];
+ data= dl->verts;
+ for(b=tot; b>0; b--) {
+ VECCOPY(data, fp);
+ data+= 3;
+ fp+= coordtype;
+ }
+
+ /* indices */
+ index= iv->data[0];
+ idata= dl->index;
+
+ for(a=iv->datalen[0]-2; a>0; a--) {
+
+ if(index[0]!= -1 && index[1]!= -1 && index[2]!= -1) {
+ idata[0]= (int) index[0];
+ idata[1]= (int) index[1];
+ idata[2]= (int) index[2];
+ idata+= 3;
+ }
+ index++;
+ }
+ }
+ }
+ else if( strcmp(iv->nodename, "QuadMesh")==0 ) {
+
+ colnr= iv_colornumber(iv);
+
+ /* terugzoeken naar data */
+ ivp= iv;
+ while(ivp->prev) {
+ ivp= ivp->prev;
+ if( strcmp(ivp->nodename, "Coordinate3")==0 ) {
+ coordtype= 3;
+ break;
+ }
+ if( strcmp(ivp->nodename, "VertexProperty")==0 ) {
+ coordtype= 3;
+ break;
+ }
+ if( strcmp(ivp->nodename, "Coordinate4")==0 ) {
+ coordtype= 4;
+ break;
+ }
+ }
+
+ if(ivp) {
+ tot= (int) (floor(*(iv->data[0])+0.5) * floor(*(iv->data[1])+0.5));
+
+ if(tot>0) {
+ dl= MEM_callocN(sizeof(struct DispList)+tot*3*sizeof(float), "leesInventor8");
+ BLI_addtail(listb, dl);
+ dl->type= DL_SURF;
+ dl->parts= (int) floor(*(iv->data[0])+0.5);
+ dl->nr= (int) floor(*(iv->data[1])+0.5);
+ dl->col= colnr;
+ data= (float *)(dl+1);
+ memcpy(data, ivp->data[0], tot*3*sizeof(float));
+ }
+ }
+ }
+ else if(strcmp(iv->nodename, "IndexedNurbsSurface")==0 || strcmp(iv->nodename, "NurbsSurface")==0) {
+
+ colnr= iv_colornumber(iv);
+
+ /* terugzoeken naar data */
+ ivp= iv;
+ while(ivp->prev) {
+ ivp= ivp->prev;
+ if( strcmp(ivp->nodename, "Coordinate3")==0 ) {
+ coordtype= 3;
+ break;
+ }
+ if( strcmp(ivp->nodename, "Coordinate4")==0 ) {
+ coordtype= 4;
+ break;
+ }
+ }
+ if(ivp) {
+ a= (int) *(iv->data[0]);
+ b= (int) *(iv->data[1]);
+
+ tot= a*b;
+
+ if( (a>=4 || b>=4) && tot>6) {
+ Object *ob;
+ Curve *cu;
+ Nurb *nu;
+ BPoint *bp;
+
+ if(ivsurf==0) {
+ ob= add_object(OB_SURF);
+ ivsurf= ob;
+ }
+ else ob= ivsurf;
+ cu= ob->data;
+ nu = (Nurb*) MEM_callocN(sizeof(Nurb),"addNurbprim") ;
+ BLI_addtail(&cu->nurb, nu);
+ nu->type= CU_NURBS;
+
+ nu->pntsu= a;
+ nu->pntsv= b;
+ nu->resolu= 2*a;
+ nu->resolv= 2*b;
+
+ nu->flagu= 0;
+ nu->flagv= 0;
+
+ nu->bp = bp =
+ (BPoint*)MEM_callocN(tot * sizeof(BPoint), "addNurbprim3");
+ a= tot;
+ data= ivp->data[0];
+ while(a--) {
+ VECCOPY(bp->vec, data);
+ if(coordtype==4) {
+ bp->vec[3]= data[3];
+ VecMulf(bp->vec, 1.0f/data[3]);
+ }
+ else bp->vec[3]= 1.0;
+ data+= coordtype;
+ bp++;
+ }
+
+ /* iv->datalen[2] / [3] is aantal knots */
+ nu->orderu= iv->datalen[2] - nu->pntsu;
+ nu->orderv= iv->datalen[3] - nu->pntsv;
+
+ nu->knotsu= MEM_mallocN( sizeof(float)*(iv->datalen[2]), "knots");
+ memcpy(nu->knotsu, iv->data[2], sizeof(float)*(iv->datalen[2]));
+ nu->knotsv= MEM_mallocN( sizeof(float)*(iv->datalen[3]), "knots");
+ memcpy(nu->knotsv, iv->data[3], sizeof(float)*(iv->datalen[3]));
+
+ switchdirectionNurb(nu);
+
+ }
+ else {
+ dl= MEM_callocN(sizeof(struct DispList)+tot*3*sizeof(float), "leesInventor3");
+ BLI_addtail(listb, dl);
+ dl->type= DL_SURF;
+ dl->nr= (int) *(iv->data[0]);
+ dl->parts= (int) *(iv->data[1]);
+ dl->col= colnr;
+ data= (float *)(dl+1);
+
+ a= tot;
+ fp= ivp->data[0];
+ while(a--) {
+ VECCOPY(data, fp);
+ fp+= coordtype;
+ data+= 3;
+ }
+ }
+ }
+ }
+ iv= iv->next;
+ }
+
+ /* vrijgeven */
+ iv= ivbase.first;
+ while(iv) {
+ for(a=0; a<IV_MAXFIELD; a++) {
+ if(iv->data[a]) MEM_freeN(iv->data[a]);
+ }
+ iv= iv->next;
+ }
+
+ BLI_freelistN(&ivbase);
+ MEM_freeN(maindata);
+ MEM_freeN(iv_data_stack);
+
+}
+
+/* ************************************************************ */
+
+static void displist_to_mesh(DispList *dlfirst)
+{
+ Object *ob;
+ Mesh *me;
+ Material *ma;
+ DispList *dl;
+ MVert *mvert;
+ MFace *mface;
+ float *data, vec[3], min[3], max[3];
+ int a, b, startve, *idata, totedge=0, tottria=0, totquad=0, totvert=0, totvlak, totcol=0, colnr;
+ int p1, p2, p3, p4;
+
+ /* eerst tellen */
+ INIT_MINMAX(min, max);
+
+ dl= dlfirst;
+ while(dl) {
+
+ /* PATCH 1 (polyfill) kan hier niet, er wordt geen listbase meegegeven. eerder doen! */
+ /* PATCH 2 */
+ if(dl->type==DL_SEGM && dl->nr>2) {
+ data= (float *)(dl+1);
+ if(data[0]==data[3*(dl->nr-1)]) {
+ if(data[1]==data[3*(dl->nr-1)+1]) {
+ if(data[2]==data[3*(dl->nr-1)+2]) {
+ dl->type= DL_POLY;
+ dl->nr--;
+ }
+ }
+ }
+ }
+
+ /* kleuren */
+ if(dl->col > totcol) totcol= dl->col;
+
+ /* afmeting en tellen */
+ if(dl->type==DL_SURF) {
+ a= dl->nr;
+ b= dl->parts;
+ if(dl->flag & 1) a++;
+ if(dl->flag & 2) b++;
+
+ totquad+= a*b;
+
+ totvert+= dl->nr*dl->parts;
+
+ data= (float *)(dl+1);
+ for(a= dl->nr*dl->parts; a>0; a--) {
+ DO_MINMAX(data, min, max);
+ data+= 3;
+ }
+ }
+ else if(dl->type==DL_POLY) {
+ if(dl->nr==3 || dl->nr==4) {
+ if(dl->nr==3) tottria+= dl->parts;
+ else totquad+= dl->parts;
+
+ totvert+= dl->nr*dl->parts;
+
+ data= (float *)(dl+1);
+ for(a= dl->nr*dl->parts; a>0; a--) {
+ DO_MINMAX(data, min, max);
+ data+= 3;
+ }
+ }
+ else if(dl->nr>4) {
+
+ tottria+= dl->nr*dl->parts;
+ totvert+= dl->nr*dl->parts;
+
+ data= (float *)(dl+1);
+ for(a= dl->nr*dl->parts; a>0; a--) {
+ DO_MINMAX(data, min, max);
+ data+= 3;
+ }
+
+ }
+ }
+ else if(dl->type==DL_INDEX3) {
+ tottria+= dl->parts;
+ totvert+= dl->nr;
+
+ data= dl->verts;
+ for(a= dl->nr; a>0; a--) {
+ DO_MINMAX(data, min, max);
+ data+= 3;
+ }
+ }
+ else if(dl->type==DL_SEGM) {
+
+ tottria+= (dl->nr-1)*dl->parts;
+ totvert+= dl->nr*dl->parts;
+
+ data= (float *)(dl+1);
+ for(a= dl->nr*dl->parts; a>0; a--) {
+ DO_MINMAX(data, min, max);
+ data+= 3;
+ }
+ }
+
+ dl= dl->next;
+ }
+
+ if(totvert==0) {
+ return;
+ }
+ if(totvert>=65000 || tottria>=65000) {
+ if (totvert>=65000) {
+ error("Too many vertices (%d)", totvert);
+ } else {
+ error("Too many faces (%d)", tottria);
+ }
+
+ return;
+ }
+
+ if(totcol>16) {
+ error("Found more than 16 different colors");
+ totcol= 16;
+ }
+
+ vec[0]= (min[0]+max[0])/2;
+ vec[1]= (min[1]+max[1])/2;
+ vec[2]= (min[2]+max[2])/2;
+
+ ob= add_object(OB_MESH);
+ VECCOPY(ob->loc, vec);
+ where_is_object(ob);
+
+ me= ob->data;
+
+ /* kleuren */
+ if(totcol) {
+ ob->mat= MEM_callocN(sizeof(void *)*totcol, "ob->mat");
+ me->mat= MEM_callocN(sizeof(void *)*totcol, "me->mat");
+ me->totcol= totcol;
+ ob->totcol= (unsigned char) me->totcol;
+ ob->actcol= 1;
+ }
+
+ /* materialen */
+ for(a=0; a<totcol; a++) {
+ ma= G.main->mat.first;
+ while(ma) {
+ if(ma->mtex[0]==0) {
+ if(ivcolors[a][0]==ma->r && ivcolors[a][1]==ma->g && ivcolors[a][2]==ma->b) {
+ me->mat[a]= ma;
+ ma->id.us++;
+ break;
+ }
+ }
+ ma= ma->id.next;
+ }
+ if(ma==0) {
+ ma= add_material("ext");
+ me->mat[a]= ma;
+ ma->r= ivcolors[a][0];
+ ma->g= ivcolors[a][1];
+ ma->b= ivcolors[a][2];
+ automatname(ma);
+ }
+ }
+
+ totvlak= totquad+tottria+totedge;
+
+ printf("Import: %d vertices %d faces\n", totvert, totvlak);
+
+ if(totvert) me->mvert= MEM_callocN(totvert*sizeof(MVert), "mvert");
+ if(totvlak) me->mface= MEM_callocN(totvlak*sizeof(MFace), "mface");
+ me->totvert= totvert;
+ me->totface= totvlak;
+
+ mvert= me->mvert;
+ mface= me->mface;
+
+ startve= 0;
+
+ dl= dlfirst;
+ while(dl) {
+
+ colnr= (dl->col>15 ? 15: dl->col);
+ if(colnr) colnr--;
+
+ if(dl->type==DL_SURF) {
+ data= (float *)(dl+1);
+
+ for(a=dl->parts*dl->nr; a>0; a--) {
+ mvert->co[0]= data[0] -vec[0];
+ mvert->co[1]= data[1] -vec[1];
+ mvert->co[2]= data[2] -vec[2];
+
+ data+=3;
+ mvert++;
+ }
+
+ for(a=0; a<dl->parts; a++) {
+
+ DL_SURFINDEX(dl->flag & 1, dl->flag & 2, dl->nr, dl->parts);
+ p1+= startve;
+ p2+= startve;
+ p3+= startve;
+ p4+= startve;
+
+ for(; b<dl->nr; b++) {
+
+ mface->v1= p1;
+ mface->v2= p2;
+ mface->v3= p4;
+ mface->v4= p3;
+
+ mface->mat_nr= colnr;
+ test_index_mface(mface, 4);
+
+ mface++;
+
+ p4= p3;
+ p3++;
+ p2= p1;
+ p1++;
+ }
+ }
+
+ startve += dl->parts*dl->nr;
+
+ }
+ else if(dl->type==DL_POLY) {
+
+ if(dl->nr==3 || dl->nr==4) {
+ data= (float *)(dl+1);
+
+ for(a=dl->parts*dl->nr; a>0; a--) {
+ mvert->co[0]= data[0] -vec[0];
+ mvert->co[1]= data[1] -vec[1];
+ mvert->co[2]= data[2] -vec[2];
+ data+=3;
+ mvert++;
+ }
+
+ for(a=0; a<dl->parts; a++) {
+ if(dl->nr==3) {
+ mface->v1= startve+a*dl->nr;
+ mface->v2= startve+a*dl->nr+1;
+ mface->v3= startve+a*dl->nr+2;
+ mface->mat_nr= colnr;
+ test_index_mface(mface, 3);
+ mface++;
+ }
+ else {
+ mface->v1= startve+a*dl->nr;
+ mface->v2= startve+a*dl->nr+1;
+ mface->v3= startve+a*dl->nr+2;
+ mface->v4= startve+a*dl->nr+3;
+ mface->mat_nr= colnr;
+ test_index_mface(mface, 4);
+ mface++;
+ }
+ }
+ startve += dl->parts*dl->nr;
+ }
+ else if(dl->nr>4) {
+ data= (float *)(dl+1);
+
+ for(a=dl->parts*dl->nr; a>0; a--) {
+ mvert->co[0]= data[0] -vec[0];
+ mvert->co[1]= data[1] -vec[1];
+ mvert->co[2]= data[2] -vec[2];
+
+ data+=3;
+ mvert++;
+ }
+
+ for(b=0; b<dl->parts; b++) {
+ for(a=0; a<dl->nr; a++) {
+ mface->v1= startve+a;
+
+ if(a==dl->nr-1) mface->v2= startve;
+ else mface->v2= startve+a+1;
+
+ mface->mat_nr= colnr;
+ test_index_mface(mface, 2);
+
+ mface++;
+ }
+ startve += dl->nr;
+ }
+ }
+ }
+ else if(dl->type==DL_INDEX3) {
+ data= dl->verts;
+
+ for(a=dl->nr; a>0; a--) {
+ mvert->co[0]= data[0] -vec[0];
+ mvert->co[1]= data[1] -vec[1];
+ mvert->co[2]= data[2] -vec[2];
+ data+=3;
+ mvert++;
+ }
+
+ idata= dl->index;
+ for(b=dl->parts; b>0; b--) {
+ mface->v1= startve+idata[0];
+ mface->v2= startve+idata[1];
+ mface->v3= startve+idata[2];
+ mface->mat_nr= colnr;
+
+ if (mface->v1>me->totvert-1) mface->v1= me->totvert-1;
+ if (mface->v2>me->totvert-1) mface->v2= me->totvert-1;
+ if (mface->v3>me->totvert-1) mface->v3= me->totvert-1;
+
+ test_index_mface(mface, 3);
+ mface++;
+ idata+= 3;
+ }
+ startve += dl->nr;
+ }
+ else if(dl->type==DL_SEGM) {
+ data= (float *)(dl+1);
+
+ for(a=dl->parts*dl->nr; a>0; a--) {
+ mvert->co[0]= data[0] -vec[0];
+ mvert->co[1]= data[1] -vec[1];
+ mvert->co[2]= data[2] -vec[2];
+ data+=3;
+ mvert++;
+ }
+
+ for(b=0; b<dl->parts; b++) {
+ for(a=0; a<dl->nr-1; a++) {
+ mface->v1= startve+a;
+ mface->v2= startve+a+1;
+ mface->mat_nr= colnr;
+ test_index_mface(mface, 2);
+ mface++;
+ }
+ startve += dl->nr;
+ }
+ }
+ dl= dl->next;
+ }
+
+ G.obedit= ob;
+ make_editMesh();
+ load_editMesh();
+ free_editMesh();
+
+ G.obedit= 0;
+ tex_space_mesh(me);
+
+}
+
+static void displist_to_objects(ListBase *lbase)
+{
+ DispList *dl, *first, *prev, *next;
+ ListBase tempbase;
+ int maxaantal, curcol, totvert=0, vert;
+
+ /* eerst dit: is nu nog actief */
+ if(ivsurf) {
+ where_is_object(ivsurf);
+ docentre_new();
+ }
+
+ dl= lbase->first;
+ while(dl) {
+ next= dl->next;
+
+ /* PATCH 1: polyfill */
+ if(dl->type==DL_POLY && dl->nr>4) {
+ /* oplossing: bij elkaar in aparte listbase zetten */
+ ;
+ }
+ /* PATCH 2: poly's van 2 punten */
+ if(dl->type==DL_POLY && dl->nr==2) dl->type= DL_SEGM;
+
+ dl= next;
+ }
+
+ /* vertices tellen */
+
+ dl= lbase->first;
+ while(dl) {
+
+ if(dl->type==DL_SURF) totvert+= dl->nr*dl->parts;
+ else if(dl->type==DL_POLY) {
+ if(dl->nr==3 || dl->nr==4) totvert+= dl->nr*dl->parts;
+ else if(dl->nr>4) totvert+= dl->nr*dl->parts;
+ }
+ else if(dl->type==DL_INDEX3) totvert+= dl->nr;
+ else if(dl->type==DL_SEGM) totvert+= dl->nr*dl->parts;
+
+ dl= dl->next;
+ }
+
+ if(totvert==0) {
+
+ if(ivsurf==0) error("Found no data");
+ if(lbase->first) BLI_freelistN(lbase);
+
+ return;
+ }
+
+ maxaantal= 32000;
+
+ if(totvert>maxaantal) {
+
+ /* probeer kleuren bij elkaar te zetten */
+ curcol= 0;
+ tempbase.first= tempbase.last= 0;
+
+ while(lbase->first) {
+ dl= lbase->first;
+ while(dl) {
+ next= dl->next;
+ if(dl->col==curcol) {
+ BLI_remlink(lbase, dl);
+ BLI_addtail(&tempbase, dl);
+ dl->col= 0;
+ }
+
+ dl= next;
+ }
+
+ /* in tempbase zitten alle kleuren 'curcol' */
+ totvert= 0;
+ dl= first= tempbase.first;
+ while(dl) {
+ vert= 0;
+
+ if(dl->type==DL_SURF) vert= dl->nr*dl->parts;
+ else if(dl->type==DL_POLY) {
+ if(dl->nr==3 || dl->nr==4) vert= dl->nr*dl->parts;
+ else if(dl->nr>4) vert= dl->nr*dl->parts;
+ }
+ else if(dl->type==DL_INDEX3) totvert+= dl->nr;
+ else if(dl->type==DL_SEGM) vert= dl->nr*dl->parts;
+
+ totvert+= vert;
+ if(totvert > maxaantal || dl->next==0) {
+ if(dl->next==0) {
+ displist_to_mesh(first);
+ }
+ else if(dl->prev) {
+ prev= dl->prev;
+ prev->next= 0;
+ displist_to_mesh(first);
+ prev->next= dl;
+ first= dl;
+ totvert= 0;
+ }
+ }
+
+ dl= dl->next;
+ }
+
+ freedisplist(&tempbase);
+
+ curcol++;
+ }
+ }
+ else displist_to_mesh(lbase->first);
+
+ freedisplist(lbase);
+
+}
+
+int BKE_read_exotic(char *name)
+{
+ ListBase lbase={0, 0};
+ int file, len;
+ char str[32];
+ int *s0 = (int*) str;
+ int retval = 0;
+
+ // make sure we're not trying to read a directory....
+
+ len= strlen(name);
+ if (name[len-1] !='/' && name[len-1] != '\\') {
+ file = open(name, O_BINARY|O_RDONLY);
+
+ if (file <= 0) {
+ error("Can't open file: %s", name);
+ } else {
+ read(file, str, 31);
+ close(file);
+
+ if ((*s0 != FORM) && (strncmp(str, "BLEN", 4) != 0)) {
+
+ waitcursor(1);
+
+ if(*s0==GOUR) {
+ if(G.obedit) {
+ error("Unable to perform function in EditMode");
+ } else {
+ read_radiogour(name);
+ retval = 1;
+ }
+ }
+ else if ELEM4(*s0, DDG1, DDG2, DDG3, DDG4) {
+ if(G.obedit) {
+ error("Unable to perform function in EditMode");
+ } else {
+ read_videoscape(name);
+ retval = 1;
+ }
+ }
+ else if(strncmp(str, "#Inventor V1.0", 14)==0) {
+ if( strncmp(str+15, "ascii", 5)==0) {
+ read_inventor(name, &lbase);
+ displist_to_objects(&lbase);
+ retval = 1;
+ } else {
+ error("Can only read Inventor 1.0 ascii");
+ }
+ }
+ else if((strncmp(str, "#VRML V1.0 asc", 14)==0)) {
+ read_inventor(name, &lbase);
+ displist_to_objects(&lbase);
+ retval = 1;
+ }
+ else if(is_dxf(name)) {
+ dxf_read(name);
+ retval = 1;
+ }
+ // TODO: this should not be in the kernel...
+ else { // unknown format, call Python importloader
+ if (BPY_call_importloader(name)) {
+ retval = 1;
+ } else {
+ error("Unknown file type or error, check console");
+ }
+
+ }
+ waitcursor(0);
+ }
+ }
+ }
+
+ if (retval == 1) {
+ strcpy(G.sce, name);
+ }
+
+ return (retval);
+}
+
+
+/* ************************ WRITE ************************** */
+
+
+char videosc_dir[160]= {0, 0};
+
+
+static void write_videoscape_mesh(Object *ob, char *str)
+{
+ Mesh *me;
+ Material *ma;
+ MVert *mvert;
+ MFace *mface;
+ FILE *fp;
+ EditVert *eve;
+ EditVlak *evl;
+ unsigned int kleur[32];
+ float co[3];
+ int a;
+ long tot;
+ char *cp;
+
+ if(ob && ob->type==OB_MESH);
+ else {
+ return;
+ }
+
+ kleur[0]= 0x00C0C0C0;
+ if(G.order==L_ENDIAN) SWITCH_INT(kleur[0]);
+
+ cp= (char *)kleur;
+ for(a=0; a<ob->totcol; a++, cp+=4) {
+
+ ma= give_current_material(ob, a+1);
+ if(ma) {
+ cp[0]= (unsigned char) (255.0*ma->emit);
+ cp[1]= (unsigned char) (255.0*ma->b);
+ cp[2]= (unsigned char) (255.0*ma->g);
+ cp[3]= (unsigned char) (255.0*ma->r);
+ }
+ else kleur[a]= 0x00C0C0C0;
+
+ if(G.order==L_ENDIAN) SWITCH_INT(kleur[a]);
+
+ if(a>30) break;
+ }
+
+ fp= fopen(str, "wb");
+ if(fp==NULL) return;
+
+ fprintf(fp,"3DG1\n");
+
+ if(G.obedit) {
+
+ fprintf(fp, "%d\n", G.totvert);
+
+ tot= 0;
+ eve= G.edve.first;
+ while(eve) {
+ VECCOPY(co, eve->co);
+ Mat4MulVecfl(ob->obmat, co);
+ fprintf(fp, "%f %f %f\n", co[0], co[1], co[2] );
+ eve->vn= (struct EditVert *)tot;
+ tot++;
+ eve= eve->next;
+ }
+ evl= G.edvl.first;
+ while(evl) {
+
+ if(evl->v4==0) {
+ fprintf(fp, "3 %p %p %p 0x%x\n", evl->v1->vn, evl->v2->vn, evl->v3->vn, kleur[evl->mat_nr]);
+ }
+ else {
+ fprintf(fp, "4 %p %p %p %p 0x%x\n", evl->v1->vn, evl->v2->vn, evl->v3->vn, evl->v4->vn, kleur[evl->mat_nr]);
+ }
+ evl= evl->next;
+ }
+ }
+ else {
+ DispList *dl;
+ float *extverts=0;
+
+ dl= find_displist(&ob->disp, DL_VERTS);
+ if(dl) extverts= dl->verts;
+
+ me= ob->data;
+
+ fprintf(fp, "%d\n", me->totvert);
+
+ mvert= me->mvert;
+ mface= me->mface;
+ for(a=0; a<me->totvert; a++, mvert++) {
+ if(extverts) {
+ VECCOPY(co, extverts);
+ extverts+= 3;
+ }
+ else {
+ VECCOPY(co, mvert->co);
+ }
+ Mat4MulVecfl(ob->obmat, co);
+ fprintf(fp, "%f %f %f\n", co[0], co[1], co[2] );
+ }
+ for(a=0; a<me->totface; a++, mface++) {
+ if(mface->v3==0) {
+ fprintf(fp, "2 %d %d 0x%x\n", mface->v1, mface->v2, kleur[mface->mat_nr]);
+ }
+ else if(mface->v4==0) {
+ fprintf(fp, "3 %d %d %d 0x%x\n", mface->v1, mface->v2, mface->v3, kleur[mface->mat_nr]);
+ }
+ else {
+ fprintf(fp, "4 %d %d %d %d 0x%x\n", mface->v1, mface->v2, mface->v3, mface->v4, kleur[mface->mat_nr]);
+ }
+ }
+ }
+
+ fclose(fp);
+
+}
+
+
+void write_videoscape(char *str)
+{
+ Base *base;
+ int file, val, lampdone=0;
+ unsigned short numlen;
+ char head[FILE_MAXFILE], tail[FILE_MAXFILE];
+
+ if(BLI_testextensie(str,".trace")) str[ strlen(str)-6]= 0;
+ if(BLI_testextensie(str,".blend")) str[ strlen(str)-6]= 0;
+ if(BLI_testextensie(str,".ble")) str[ strlen(str)-4]= 0;
+ if(BLI_testextensie(str,".obj")==0) strcat(str, ".obj");
+
+ file= open(str,O_BINARY|O_RDONLY);
+ close(file);
+ if(file>-1) if(saveover(str)==0) return;
+
+ strcpy(videosc_dir, str);
+
+ base= G.scene->base.first;
+ while(base) {
+ if((base->flag & SELECT) && (base->lay & G.scene->lay)) {
+ if(base->object->type==OB_MESH) {
+ write_videoscape_mesh(base->object, str);
+ val = BLI_stringdec(str, head, tail, &numlen);
+ BLI_stringenc(str, head, tail, numlen, val + 1);
+ }
+ else if(base->object->type==OB_CURVE || base->object->type==OB_SURF) {
+ /* write_videoscape_nurbs(base->object, str); */
+ /* val = stringdec(str, head, tail, &numlen); */
+ /* stringenc(str, head, tail, numlen, val + 1); */
+ }
+ else if(lampdone==0 && base->object->type==OB_LAMP) {
+ /* lampdone= 1; */
+ /* write_videoscape_lamps(str); */
+ /* val = stringdec(str, head, tail, &numlen); */
+ /* stringenc(str, head, tail, numlen, val + 1); */
+ }
+ }
+ base= base->next;
+ }
+
+
+ /* weggooien als nog hogere nummers bestaan */
+ while(remove(str)==0) {
+
+ val = BLI_stringdec(str, head, tail, &numlen);
+ BLI_stringenc(str, head, tail, numlen, val + 1);
+ }
+}
+
+/* ******************************* WRITE VRML ***************************** */
+
+static void replace_chars(char *str1, char *str2)
+{
+ int a= strlen(str2);
+
+ str1[a]= 0;
+ while(a--) {
+ if(str2[a]=='.' || str2[a]==' ') str1[a]= '_';
+ else str1[a]= str2[a];
+ }
+}
+
+
+static void write_material_vrml(FILE *fp, Material *ma)
+{
+ char str[32];
+
+ replace_chars(str, ma->id.name+2);
+
+ fprintf(fp, "\tDEF %s\n", str);
+ fprintf(fp, "\tMaterial {\n");
+
+ fprintf(fp, "\t\tdiffuseColor %f %f %f\n", ma->r, ma->g, ma->b);
+ fprintf(fp, "\t\tspecularColor %f %f %f\n", ma->specr, ma->specg, ma->specb);
+ fprintf(fp, "\t\tshininess %f \n", ((float)ma->har)/100.0);
+ fprintf(fp, "\t\ttransparency %f \n", 1.0-ma->alpha);
+
+ fprintf(fp, "\t}\n");
+
+}
+
+unsigned int *mcol_to_vcol(Mesh *me)
+{
+ MFace *mface;
+ unsigned int *mcol, *mcoln, *mcolmain;
+ int a;
+
+ if(me->totface==0 || me->mcol==0) return 0;
+
+ mcoln= mcolmain= MEM_mallocN(sizeof(int)*me->totvert, "mcoln");
+ mcol = (unsigned int *)me->mcol;
+ mface= me->mface;
+
+ for(a=me->totface; a>0; a--, mface++) {
+ mcoln[mface->v1]= mcol[0];
+ mcoln[mface->v2]= mcol[1];
+ if(mface->v3) mcoln[mface->v3]= mcol[2];
+ if(mface->v4) mcoln[mface->v4]= mcol[3];
+
+ mcol+= 4;
+ }
+
+ return mcolmain;
+}
+
+void mcol_to_rgba(unsigned int col, float *r, float *g, float *b, float *a)
+{
+ char *cp;
+
+ cp = (char *)&col;
+
+ *r= cp[3];
+ *r /= 255.0;
+
+ *g= cp[2];
+ *g /= 255.0;
+
+ *b= cp[1];
+ *b /= 255.0;
+
+ *a= cp[0];
+ *a /= 255.0;
+}
+
+static void write_mesh_vrml(FILE *fp, Mesh *me)
+{
+ Material *ma;
+ MVert *mvert;
+ MFace *mface;
+ TFace *tface;
+ Image *ima;
+ int a, b, totcol;
+ char str[32];
+
+ replace_chars(str, me->id.name+2);
+
+ fprintf(fp, "\tDEF %s\n", str);
+ fprintf(fp, "\tSeparator {\n");
+
+ if(me->tface) {
+ ima= ((TFace *)me->tface)->tpage;
+ if(ima) {
+ fprintf(fp, "\t\tTexture2 {\n");
+ fprintf(fp, "\t\t\tfilename %s\n", ima->name);
+ fprintf(fp, "\t\t\twrapS REPEAT \n");
+ fprintf(fp, "\t\t\twrapT REPEAT \n");
+ fprintf(fp, "\t\t}\n");
+ }
+ tface_to_mcol(me);
+ }
+
+ if(me->mcol) {
+ unsigned int *mcol, *mcolmain;
+ float r, g, b, cola;
+
+ fprintf(fp, "\t\tMaterial {\n");
+ fprintf(fp, "\t\t\tdiffuseColor [\n");
+
+ a= me->totvert;
+ mcol= mcolmain= mcol_to_vcol(me);
+ if(mcol) {
+ while(a--) {
+ mcol_to_rgba(*mcol, &r, &g, &b, &cola);
+ fprintf(fp, "\t\t\t\t %f %f %f,\n", r, g, b);
+ mcol++;
+ }
+ MEM_freeN(mcolmain);
+ }
+ fprintf(fp, "\t\t\t]\n");
+ fprintf(fp, "\t\t}\n");
+
+ fprintf(fp, "\t\tMaterialBinding { value PER_VERTEX_INDEXED }\n");
+ }
+
+
+ fprintf(fp, "\t\tCoordinate3 {\n");
+ fprintf(fp, "\t\t\tpoint [\n");
+
+ a= me->totvert;
+ mvert= me->mvert;
+ while(a--) {
+ fprintf(fp, "\t\t\t\t %f %f %f,\n", mvert->co[0], mvert->co[1], mvert->co[2]);
+ mvert++;
+ }
+ fprintf(fp, "\t\t\t]\n");
+ fprintf(fp, "\t\t}\n");
+
+
+ totcol= me->totcol;
+ if(totcol==0) totcol= 1;
+
+ for(b=0; b<totcol; b++) {
+
+ if(me->mcol==0) {
+ if(me->mat) {
+ ma= me->mat[b];
+ if(ma) {
+ replace_chars(str, ma->id.name+2);
+
+ fprintf(fp, "\t\tUSE %s\n\n", str);
+ }
+ }
+ }
+
+ if(me->tface) {
+ fprintf(fp, "\t\tTextureCoordinate2 {\n");
+ fprintf(fp, "\t\t\tpoint [\n");
+
+ a= me->totface;
+ mface= me->mface;
+ tface= me->tface;
+ while(a--) {
+ if(mface->mat_nr==b) {
+ fprintf(fp, "\t\t\t\t %f %f,\n", tface->uv[0][0], tface->uv[0][1]);
+ fprintf(fp, "\t\t\t\t %f %f,\n", tface->uv[3][0], tface->uv[3][1]);
+ if(mface->v3) fprintf(fp, "\t\t\t\t %f %f,\n", tface->uv[2][0], tface->uv[2][1]);
+ if(mface->v4) fprintf(fp, "\t\t\t\t %f %f,\n", tface->uv[1][0], tface->uv[1][1]);
+ }
+ mface++;
+ tface++;
+ }
+ fprintf(fp, "\t\t\t]\n");
+ fprintf(fp, "\t\t}\n");
+ }
+
+ fprintf(fp, "\t\tIndexedFaceSet {\n");
+ fprintf(fp, "\t\t\tcoordIndex [\n");
+
+ a= me->totface;
+ mface= me->mface;
+ while(a--) {
+ if(mface->mat_nr==b) {
+ if(mface->v4) fprintf(fp, "\t\t\t\t %d, %d, %d, %d, -1,\n", mface->v1, mface->v2, mface->v3, mface->v4);
+ else if(mface->v3) fprintf(fp, "\t\t\t\t %d, %d, %d, -1,\n", mface->v1, mface->v2, mface->v3);
+ }
+ mface++;
+ }
+ fprintf(fp, "\t\t\t]\n");
+ fprintf(fp, "\t\t}\n");
+
+ }
+
+ fprintf(fp, "\t}\n");
+
+ if(me->tface) {
+ MEM_freeN(me->mcol);
+ me->mcol= 0;
+ }
+
+}
+
+static void write_camera_vrml(FILE *fp, Object *ob)
+{
+ Camera *cam;
+
+ if(ob==0) return;
+ Mat4Invert(ob->imat, ob->obmat);
+
+ fprintf(fp, "\tMatrixTransform {\n");
+
+ fprintf(fp, "\tmatrix \n");
+
+ fprintf(fp, "\t\t%f %f %f %f\n", ob->imat[0][0], ob->imat[0][1], ob->imat[0][2], ob->imat[0][3]);
+ fprintf(fp, "\t\t%f %f %f %f\n", ob->imat[1][0], ob->imat[1][1], ob->imat[1][2], ob->imat[1][3]);
+ fprintf(fp, "\t\t%f %f %f %f\n", ob->imat[2][0], ob->imat[2][1], ob->imat[2][2], ob->imat[2][3]);
+ fprintf(fp, "\t\t%f %f %f %f\n", ob->imat[3][0], ob->imat[3][1], ob->imat[3][2], ob->imat[3][3]);
+
+ fprintf(fp, "\t}\n");
+
+ cam= ob->data;
+
+ fprintf(fp, "\tPerspectiveCamera {\n");
+ fprintf(fp, "\t\tfocalDistance %f\n", cam->lens/10.0);
+
+ fprintf(fp, "\t}\n");
+
+}
+
+static void write_object_vrml(FILE *fp, Object *ob)
+{
+ ID *id;
+ char str[32];
+
+ fprintf(fp, "\tSeparator {\n");
+ fprintf(fp, "\t\tMatrixTransform {\n");
+
+ fprintf(fp, "\t\tmatrix \n");
+
+ fprintf(fp, "\t\t\t%f %f %f %f\n", ob->obmat[0][0], ob->obmat[0][1], ob->obmat[0][2], ob->obmat[0][3]);
+ fprintf(fp, "\t\t\t%f %f %f %f\n", ob->obmat[1][0], ob->obmat[1][1], ob->obmat[1][2], ob->obmat[1][3]);
+ fprintf(fp, "\t\t\t%f %f %f %f\n", ob->obmat[2][0], ob->obmat[2][1], ob->obmat[2][2], ob->obmat[2][3]);
+ fprintf(fp, "\t\t\t%f %f %f %f\n", ob->obmat[3][0], ob->obmat[3][1], ob->obmat[3][2], ob->obmat[3][3]);
+
+ fprintf(fp, "\t\t}\n");
+
+ id= ob->data;
+
+ replace_chars(str, id->name+2);
+
+ fprintf(fp, "\t\tUSE %s\n", str);
+ fprintf(fp, "\t}\n");
+}
+
+
+void write_vrml(char *str)
+{
+ Mesh *me;
+ Material *ma;
+ Base *base;
+ FILE *fp;
+
+ if(BLI_testextensie(str,".blend")) str[ strlen(str)-6]= 0;
+ if(BLI_testextensie(str,".ble")) str[ strlen(str)-4]= 0;
+ if(BLI_testextensie(str,".wrl")==0) strcat(str, ".wrl");
+
+ if(saveover(str)==0) return;
+
+ fp= fopen(str, "w");
+
+ if(fp==NULL) {
+ error("Can't write file");
+ return;
+ }
+ strcpy(videosc_dir, str);
+
+ waitcursor(1);
+
+ /* FIRST: write all the datablocks */
+
+ fprintf(fp, "#VRML V1.0 ascii\n\n# Blender V2.0\n\n# 'Switch' is used as a hack, to ensure it is not part of the drawing\n\n");
+ fprintf(fp, "Separator {\n");
+ fprintf(fp, "Switch {\n");
+
+ ma= G.main->mat.first;
+ while(ma) {
+ if(ma->id.us) {
+ write_material_vrml(fp, ma);
+ }
+ ma= ma->id.next;
+ }
+
+ me= G.main->mesh.first;
+ while(me) {
+ if(me->id.us) {
+ write_mesh_vrml(fp, me);
+ }
+ me= me->id.next;
+ }
+
+ /* THEN:Hidden Objects */
+ fprintf(fp, "\n\t# Hidden Objects, in invisible layers\n\n");
+ base= G.scene->base.first;
+ while(base) {
+ if(base->object->type== OB_MESH) {
+ if( (base->lay & G.scene->lay)==0 ) {
+ write_object_vrml(fp, base->object);
+ }
+ }
+ base= base->next;
+ }
+
+ fprintf(fp, "}\n");
+ fprintf(fp, "\n# Visible Objects\n\n");
+ fprintf(fp, "Separator {\n");
+
+ /* The camera */
+
+ write_camera_vrml(fp, G.scene->camera);
+
+ /* THEN:The Objects */
+
+ base= G.scene->base.first;
+ while(base) {
+ if(base->object->type== OB_MESH) {
+ if(base->lay & G.scene->lay) {
+ write_object_vrml(fp, base->object);
+ }
+ }
+ base= base->next;
+ }
+
+ fprintf(fp, "}\n");
+ fprintf(fp, "}\n");
+
+ fclose(fp);
+
+ waitcursor(0);
+}
+
+
+/* ******************************* WRITE DXF ***************************** */
+
+#define write_group(id,data) fprintf(fp, "%d\n%s\n", id, data)
+
+/* A completely wacky function to try and make good
+indexed (AutoCAD index) values out of straight rgb
+ones... crazy */
+
+static int rgb_to_dxf_col (float rf, float gf, float bf)
+{
+ int r= (int) (rf*255.0f);
+ int g= (int) (gf*255.0f);
+ int b= (int) (bf*255.0f);
+ float h,s,v;
+ int ret;
+
+ /* Grayscale value */
+ if (((int)r/10)==((int)g/10) && ((int)g/10)==((int)b/10)) ret= 250+((int)r/51);
+ /* A nice chroma value */
+ else {
+ rgb_to_hsv (rf,gf,bf,&h,&s,&v);
+
+ ret= (int) (10.0f + (h*239.0f));
+ CLAMP(ret,10,249);
+
+ /* If its whitish make the index odd */
+ if (s<.5 || v>.5) if(ret%2) ret++;
+ }
+
+ return ret;
+}
+
+/* And its completely wacky complement */
+
+static void dxf_col_to_rgb (int cid, float *rf, float *gf, float *bf)
+{
+ float h, s, v;
+
+ /* Grayscale values */
+ if (cid>=250 && cid <= 255) {
+ *rf= *gf= *bf= (float) ((cid-250)*51)/255;
+ CLAMP(*rf, 0.0, 1.0);
+ CLAMP(*gf, 0.0, 1.0);
+ CLAMP(*bf, 0.0, 1.0);
+
+ /* Pure values */
+ } else if (cid<10) {
+ switch (cid) {
+ case 1:
+ *rf=1.0;
+ *gf=0.0;
+ *bf=0.0;
+ break;
+ case 2:
+ *rf=1.0;
+ *gf=1.0;
+ *bf=0.0;
+ break;
+ case 3:
+ *gf=1.0;
+ *rf=0.0;
+ *bf=0.0;
+ break;
+ case 4:
+ *rf=0.0;
+ *gf=1.0;
+ *bf=1.0;
+ break;
+ case 5:
+ *rf=0.0;
+ *gf=0.0;
+ *bf=1.0;
+ break;
+ case 6:
+ *rf=1.0;
+ *gf=0.0;
+ *bf=1.0;
+ break;
+ case 7:
+ default:
+ *rf= *gf= *bf= 1.0;
+ break;
+ }
+ } else {
+ /* Get chroma values */
+
+ h= (float) (cid-10)/239;
+ CLAMP(h, 0.0, 1.0);
+
+ /* If its odd make it a bit whitish */
+ if (cid%2) { s=.75; v= 0.25;
+ } else { s= 0.25; v= 0.75;}
+
+ hsv_to_rgb (h, s, v, rf, gf, bf);
+ }
+}
+
+static void write_mesh_dxf(FILE *fp, Mesh *me)
+{
+ Material *ma;
+ MVert *mvert;
+ MFace *mface;
+ int a;
+ char str[32];
+
+ replace_chars(str, me->id.name+2);
+
+ write_group(0, "BLOCK");
+
+ write_group(2, str); /* The name */
+
+ write_group(8, "Meshes"); /* DXF Layer */
+ write_group(70, "64"); /* DXF block flags */
+
+ write_group(10, "0.0"); /* X of base */
+ write_group(20, "0.0"); /* Y of base */
+ write_group(30, "0.0"); /* Z of base */
+
+ write_group(3, str); /* The name (again) */
+
+ write_group(0, "POLYLINE"); /* Start the mesh */
+ write_group(66, "1"); /* Vertices follow flag */
+ write_group(8,"Meshes"); /* DXF Layer */
+
+ if (me->totcol) {
+ ma= me->mat[0];
+ if(ma) {
+ sprintf(str,"%d",rgb_to_dxf_col(ma->r,ma->g,ma->b));
+ write_group(62, str); /* Color index */
+ }
+ }
+
+ write_group(70, "64"); /* Polymesh mesh flag */
+
+ fprintf(fp, "71\n%d\n", me->totvert); /* Total vertices */
+ fprintf(fp, "72\n%d\n", me->totface); /* Total faces */
+
+ /* Write the vertices */
+ a= me->totvert;
+ mvert= me->mvert;
+ while(a--) {
+ write_group(0, "VERTEX"); /* Start a new vertex */
+ write_group(8, "Meshes"); /* DXF Layer */
+ fprintf (fp, "10\n%f\n", mvert->co[0]); /* X cord */
+ fprintf (fp, "20\n%f\n", mvert->co[1]); /* Y cord */
+ fprintf (fp, "30\n%f\n", mvert->co[2]); /* Z cord */
+ write_group(70, "192"); /* Polymesh vertex flag */
+
+ mvert++;
+ }
+
+ /* Write the face entries */
+ a= me->totface;
+ mface= me->mface;
+ while(a--) {
+ if (mface->v4 || mface->v3) {
+ write_group(0, "VERTEX"); /* Start a new face */
+ write_group(8, "Meshes");
+
+ /* Write a face color */
+ if (me->totcol) {
+ ma= me->mat[mface->mat_nr];
+ if(ma) {
+ sprintf(str,"%d",rgb_to_dxf_col(ma->r,ma->g,ma->b));
+ write_group(62, str); /* Color index */
+ }
+ }
+ else write_group(62, "254"); /* Color Index */
+
+ /* Not sure what this really corresponds too */
+ write_group(10, "0.0"); /* X of base */
+ write_group(20, "0.0"); /* Y of base */
+ write_group(30, "0.0"); /* Z of base */
+
+ write_group(70, "128"); /* Polymesh face flag */
+
+ if(mface->v4) {
+ fprintf (fp, "71\n%d\n", mface->v1+1);
+ fprintf (fp, "72\n%d\n", mface->v2+1);
+ fprintf (fp, "73\n%d\n", mface->v3+1);
+ fprintf (fp, "74\n%d\n", mface->v4+1);
+ } else if(mface->v3) {
+ fprintf (fp, "71\n%d\n", mface->v1+1);
+ fprintf (fp, "72\n%d\n", mface->v2+1);
+ fprintf (fp, "73\n%d\n", mface->v3+1);
+ }
+ }
+ mface++;
+ }
+
+ write_group(0, "SEQEND");
+
+ write_group(0, "ENDBLK");
+}
+
+static void write_object_dxf(FILE *fp, Object *ob, int layer)
+{
+ ID *id;
+ char str[32];
+
+ id= ob->data;
+
+ write_group(0, "INSERT"); /* Start an insert group */
+
+ sprintf(str, "%d", layer);
+ write_group(8, str);
+
+ replace_chars(str, id->name+2);
+ write_group(2, str);
+
+ fprintf (fp, "10\n%f\n", ob->loc[0]); /* X of base */
+ fprintf (fp, "20\n%f\n", ob->loc[1]); /* Y of base */
+ fprintf (fp, "30\n%f\n", ob->loc[2]); /* Z of base */
+
+ fprintf (fp, "41\n%f\n", ob->size[0]); /* X scale */
+ fprintf (fp, "42\n%f\n", ob->size[1]); /* Y scale */
+ fprintf (fp, "43\n%f\n", ob->size[2]); /* Z scale */
+
+ fprintf (fp, "50\n%f\n", (float) ob->rot[2]*180/M_PI); /* Can only write the Z rot */
+}
+
+void write_dxf(char *str)
+{
+ Mesh *me;
+ Base *base;
+ FILE *fp;
+
+ if(BLI_testextensie(str,".blend")) str[ strlen(str)-6]= 0;
+ if(BLI_testextensie(str,".ble")) str[ strlen(str)-4]= 0;
+ if(BLI_testextensie(str,".dxf")==0) strcat(str, ".dxf");
+
+ if (BLI_exists(str))
+ if(saveover(str)==0)
+ return;
+
+ fp= fopen(str, "w");
+
+ if(fp==NULL) {
+ error("Can't write file");
+ return;
+ }
+ strcpy(videosc_dir, str);
+
+ waitcursor(1);
+
+ /* The header part of the DXF */
+
+ write_group(0, "SECTION");
+ write_group(2, "HEADER");
+ write_group(0, "ENDSEC");
+
+ /* The blocks part of the DXF */
+
+ write_group(0, "SECTION");
+ write_group(2, "BLOCKS");
+
+ /* Write all the meshes */
+ me= G.main->mesh.first;
+ while(me) {
+ if(me->id.us) {
+ write_mesh_dxf(fp, me);
+ }
+ me= me->id.next;
+ }
+
+ write_group(0, "ENDSEC");
+
+ /* The entities part of the DXF */
+
+ write_group(0, "SECTION");
+ write_group(2, "ENTITIES");
+
+ /* Write all the mesh objects */
+ base= G.scene->base.first;
+ while(base) {
+ if(base->object->type== OB_MESH) {
+ write_object_dxf(fp, base->object, base->lay);
+ }
+ base= base->next;
+ }
+
+ write_group(0, "ENDSEC");
+
+ /* Thats all */
+
+ write_group(0, "EOF");
+ fclose(fp);
+
+ waitcursor(0);
+}
+
+
+static int dxf_line;
+static FILE *dxf_fp;
+
+/* exotic.c(2863) : note C6311: c:/Program Files/Microsoft Visual
+ * Studio/VC98/include\ctype.h(268) : see previous definition of
+ * 'iswspace' */
+#define ton_iswspace(c) (c==' '||c=='\n'||c=='\t')
+
+static void clean_wspace (char *str)
+{
+ char *from, *to;
+ char t;
+
+ from= str;
+ to=str;
+
+ while (*from!=0) {
+ t= *from;
+ *to= t;
+
+ if(!ton_iswspace(*from)) to++;
+ from++;
+ }
+ *to=0;
+}
+
+static int all_wspace(char *str)
+{
+ while(*str != 0) {
+ if (!ton_iswspace(*str)) return 0;
+ str++;
+ }
+
+ return 1;
+}
+
+static int all_digits(char *str)
+{
+ while(*str != 0) {
+ if (!isdigit(*str)) return 0;
+ str++;
+ }
+
+ return 1;
+}
+
+static int dxf_get_layer_col(char *layer)
+{
+ return 1;
+}
+
+static int dxf_get_layer_num(char *layer)
+{
+ int ret = 1;
+
+ if (all_digits(layer) && atoi(layer)<(1<<20)) ret= atoi(layer);
+ if (ret == 0) ret = 1;
+
+ return ret;
+}
+
+static void dos_clean(char *str)
+{
+ while (*str) {
+ if (*str == 0x0d) {
+ *str='\n';
+ *(++str)= 0;
+ break;
+ }
+ str++;
+ }
+}
+
+static int read_groupf(char *str)
+{
+ short c;
+ int ret=-1;
+ char tmp[256];
+
+ strcpy(str, " ");
+
+ while ((c=getc(dxf_fp)) && ton_iswspace(c));
+ ungetc(c, dxf_fp);
+ if (c==EOF) return -1;
+
+ fgets(tmp, 255, dxf_fp);
+
+ dos_clean(tmp);
+
+ if(sscanf(tmp, "%d\n", &ret)!=1) return -2;
+
+ fgets(tmp, 255, dxf_fp);
+
+ dos_clean(tmp);
+
+ if (!all_wspace(tmp)) {
+ if (sscanf(tmp, "%s\n", str)!=1) return -2;
+ }
+
+ clean_wspace(str);
+ dxf_line+=2;
+
+ return ret;
+}
+
+#define id_test(id) if(id<0) {char errmsg[128];fclose(dxf_fp); if(id==-1) sprintf(errmsg, "Error inputting dxf, near line %d", dxf_line); else if(id==-2) sprintf(errmsg, "Error reading dxf, near line %d", dxf_line);error(errmsg); return;}
+
+#define read_group(id,str) {id= read_groupf(str); id_test(id);}
+
+#define group_is(idtst,str) (id==idtst&&strcmp(val,str)==0)
+#define group_isnt(idtst,str) (id!=idtst||strcmp(val,str)!=0)
+#define id_check(idtst,str) if(group_isnt(idtst,str)) { fclose(dxf_fp); error("Error parsing dxf, near line %d", dxf_line); return;}
+
+static int id;
+static char val[256];
+
+static short error_exit=0;
+static short hasbumped=0;
+
+static int is_dxf(char *str)
+{
+ dxf_line=0;
+
+ dxf_fp= fopen(str, "r");
+ if (dxf_fp==NULL) return 0;
+
+ id= read_groupf(val);
+ if ((id==0 && strcmp(val, "SECTION")==0)||id==999) return 1;
+
+ fclose(dxf_fp);
+
+ return 0;
+}
+
+/* NOTES ON THE READER */
+/*
+ --
+ It turns out that most DXF writers like (LOVE) to
+ write meshes as a long string of 3DFACE entities.
+ This means the natural way to read a DXF file
+ (every entity corresponds to an object) is completely
+ unusable, reading in 10,000 faces each as an
+ object just doesn't cut it. Thus the 3DFACE
+ entry reader holds state, and only finalizes to
+ an object when a) the layer name changes, b) the
+ entry type changes, c) we are done reading.
+
+ PS... I decided to do the same thing with LINES,
+ apparently the same thing happens sometimes as
+ well.
+
+ PPS... I decided to do the same thing with everything.
+ Now it is all really nasty and should be rewritten.
+*/
+
+static void dxf_add_mat (Object *ob, Mesh *me, float color[3], char *layer)
+{
+ Material *ma;
+
+ if (!me) return;
+
+ if(ob) ob->mat= MEM_callocN(sizeof(void *)*1, "ob->mat");
+ if(ob) ob->totcol= 1;
+ if(ob) ob->actcol= 1;
+
+ me->totcol= 1;
+ me->mat= MEM_callocN(sizeof(void *)*1, "me->mat");
+
+ if (color[0]<0) {
+ if (strlen(layer)) dxf_col_to_rgb(dxf_get_layer_col(layer), &color[0], &color[1], &color[2]);
+ color[0]= color[1]= color[2]= 0.8f;
+ }
+
+ ma= G.main->mat.first;
+ while(ma) {
+ if(ma->mtex[0]==0) {
+ if(color[0]==ma->r && color[1]==ma->g && color[2]==ma->b) {
+ me->mat[0]= ma;
+ ma->id.us++;
+ break;
+ }
+ }
+ ma= ma->id.next;
+ }
+ if(ma==0) {
+ ma= add_material("ext");
+ me->mat[0]= ma;
+ ma->r= color[0];
+ ma->g= color[1];
+ ma->b= color[2];
+ automatname(ma);
+ }
+}
+
+ /* General DXF vars */
+static float cent[3]={0.0, 0.0, 0.0};
+static char layname[32]="";
+static char entname[32]="";
+static float color[3]={-1.0, -1.0, -1.0};
+static float *vcenter;
+static float zerovec[3]= {0.0, 0.0, 0.0};
+
+#define reset_vars cent[0]= cent[1]= cent[2]=0.0; strcpy(layname, ""); color[0]= color[1]= color[2]= -1.0
+
+static void dxf_read_point(int noob) {
+ /* Blender vars */
+ Object *ob;
+ Mesh *me;
+ MVert *mvert;
+
+ reset_vars;
+
+ read_group(id, val);
+ while(id!=0) {
+ if (id==8) {
+ BLI_strncpy(layname, val, sizeof(layname));
+ } else if (id==10) {
+ cent[0]= (float) atof(val);
+ } else if (id==20) {
+ cent[1]= (float) atof(val);
+ } else if (id==30) {
+ cent[2]= (float) atof(val);
+ } else if (id==60) {
+ /* short invisible= atoi(val); */
+ } else if (id==62) {
+ int colorid= atoi(val);
+
+ CLAMP(colorid, 1, 255);
+ dxf_col_to_rgb(colorid, &color[0], &color[1], &color[2]);
+ }
+ read_group(id, val);
+ }
+
+ if (noob) {
+ ob= NULL;
+ me= add_mesh(); G.totmesh++;
+ ((ID *)me)->us=0;
+
+ if (strlen(entname)) new_id(&G.main->mesh, (ID *)me, entname);
+ else if (strlen(layname)) new_id(&G.main->mesh, (ID *)me, layname);
+
+ vcenter= zerovec;
+ } else {
+ ob= add_object(OB_MESH);
+ if (strlen(entname)) new_id(&G.main->object, (ID *)ob, entname);
+ else if (strlen(layname)) new_id(&G.main->object, (ID *)ob, layname);
+
+ if (strlen(layname)) ob->lay= dxf_get_layer_num(layname);
+ else ob->lay= G.scene->lay;
+
+ me= ob->data;
+
+ vcenter= ob->loc;
+ }
+ me->totvert= 1; /* Its a line dude */
+ me->totface= 0;
+
+ me->mvert= MEM_callocN(me->totvert*sizeof(MVert), "mverts");
+ me->mface= NULL;
+
+ dxf_add_mat (ob, me, color, layname);
+
+ mvert= me->mvert;
+ mvert->co[0]= mvert->co[1]= mvert->co[2]= 0;
+
+ if (ob) VECCOPY(ob->loc, cent);
+
+ if (!noob) {
+ G.obedit= ob;
+ make_editMesh();
+ load_editMesh();
+ free_editMesh();
+ waitcursor(1); /* patch yah... */
+
+ G.obedit= 0;
+ }
+ tex_space_mesh(me);
+
+ hasbumped=1;
+}
+
+ /* Line state vars */
+static Object *linehold=NULL;
+static Mesh *linemhold=NULL;
+
+static char oldllay[32];
+static short lwasline=0; /* last was face 3d? */
+
+static void dxf_close_line(void)
+{
+ linemhold=NULL;
+ if (linehold==NULL) return;
+
+ G.obedit= linehold;
+ make_editMesh();
+ load_editMesh();
+ free_editMesh();
+ waitcursor(1); /* patch yah... */
+
+ G.obedit= 0;
+ tex_space_mesh(linehold->data);
+
+ linehold=NULL;
+}
+
+static void dxf_read_line(int noob) {
+ /* Entity specific vars */
+ float epoint[3]={0.0, 0.0, 0.0};
+ short vspace=0; /* Whether or not coords are relative */
+
+ /* Blender vars */
+ Object *ob;
+ Mesh *me;
+ MVert *mvert, *vtmp;
+ MFace *mface, *ftmp;
+
+ reset_vars;
+
+ read_group(id, val);
+ while(id!=0) {
+ if (id==8) {
+ BLI_strncpy(layname, val, sizeof(layname));
+ } else if (id==10) {
+ cent[0]= (float) atof(val);
+ } else if (id==20) {
+ cent[1]= (float) atof(val);
+ } else if (id==30) {
+ cent[2]= (float) atof(val);
+ } else if (id==11) {
+ epoint[0]= (float) atof(val);
+ } else if (id==21) {
+ epoint[1]= (float) atof(val);
+ } else if (id==31) {
+ epoint[2]= (float) atof(val);
+ } else if (id==60) {
+ /* short invisible= atoi(val); */
+ } else if (id==62) {
+ int colorid= atoi(val);
+
+ CLAMP(colorid, 1, 255);
+ dxf_col_to_rgb(colorid, &color[0], &color[1], &color[2]);
+ } else if (id==67) {
+ vspace= atoi(val);
+ }
+ read_group(id, val);
+ }
+
+ /* Check to see if we need to make a new object */
+
+ if(!lwasline || strcmp(layname, oldllay)!=0) dxf_close_line();
+ if(linemhold != NULL && linemhold->totvert>65000) dxf_close_line();
+
+ if (linemhold==NULL) {
+ if (noob) {
+ ob= NULL;
+ me= add_mesh(); G.totmesh++;
+ ((ID *)me)->us=0;
+
+ if (strlen(entname)) new_id(&G.main->mesh, (ID *)me, entname);
+ else if (strlen(layname)) new_id(&G.main->mesh, (ID *)me, layname);
+
+ vcenter= zerovec;
+ } else {
+ ob= add_object(OB_MESH);
+ if (strlen(entname)) new_id(&G.main->object, (ID *)ob, entname);
+ else if (strlen(layname)) new_id(&G.main->object, (ID *)ob, layname);
+
+ if (strlen(layname)) ob->lay= dxf_get_layer_num(layname);
+ else ob->lay= G.scene->lay;
+
+ me= ob->data;
+
+ vcenter= ob->loc;
+ }
+
+ me->totvert=0;
+ me->totface=0;
+ me->mvert=NULL;
+ me->mface=NULL;
+
+ strcpy(oldllay, layname);
+
+ if(ob) VECCOPY(ob->loc, cent);
+
+ dxf_add_mat (ob, me, color, layname);
+
+ linehold= ob;
+ linemhold= me;
+ } else {
+ ob= linehold;
+ me= linemhold;
+ }
+
+ me->totvert+= 2;
+ me->totface++;
+
+ vtmp= MEM_callocN(me->totvert*sizeof(MVert), "mverts");
+ ftmp= MEM_callocN(me->totface*sizeof(MFace), "mface");
+
+ if(me->mvert) {
+ memcpy(vtmp, me->mvert, (me->totvert-2)*sizeof(MVert));
+ MEM_freeN(me->mvert);
+ }
+ me->mvert= vtmp;
+ vtmp=NULL;
+
+ if(me->mface) {
+ memcpy(ftmp, me->mface, (me->totface-1)*sizeof(MFace));
+ MEM_freeN(me->mface);
+ }
+ me->mface= ftmp;
+ ftmp=NULL;
+
+ mvert= &me->mvert[(me->totvert-2)];
+ VecSubf(mvert->co, cent, vcenter);
+
+ mvert++;
+ if (vspace) { VECCOPY(mvert->co, epoint);
+ } else VecSubf(mvert->co, epoint, vcenter);
+
+ mface= &(((MFace*)me->mface)[me->totface-1]);
+ mface->v1= me->totvert-2;
+ mface->v2= me->totvert-1;
+
+ mface->edcode= 1;
+ mface->mat_nr= 0;
+
+ hasbumped=1;
+}
+
+ /* 2D Polyline state vars */
+static Object *p2dhold=NULL;
+static Mesh *p2dmhold=NULL;
+static char oldplay[32];
+static short lwasp2d=0;
+
+static void dxf_close_2dpoly(void)
+{
+ p2dmhold= NULL;
+ if (p2dhold==NULL) return;
+
+ G.obedit= p2dhold;
+ make_editMesh();
+ load_editMesh();
+ free_editMesh();
+ waitcursor(1); /* patch yah... */
+
+ G.obedit= 0;
+ tex_space_mesh(p2dhold->data);
+
+ p2dhold=NULL;
+}
+
+static void dxf_read_polyline(int noob) {
+ /* Entity specific vars */
+ short vspace=0; /* Whether or not coords are relative */
+ int flag=0;
+ int vflags=0;
+ int vids[4];
+ int nverts;
+
+ /* Blender vars */
+ Object *ob;
+ Mesh *me;
+ float vert[3];
+
+ MVert *mvert, *vtmp;
+ MFace *mface, *ftmp;
+
+ reset_vars;
+
+ read_group(id, val);
+ while(id!=0) {
+ if (id==8) {
+ BLI_strncpy(layname, val, sizeof(layname));
+ } else if (id==10) {
+ cent[0]= (float) atof(val);
+ } else if (id==20) {
+ cent[1]= (float) atof(val);
+ } else if (id==30) {
+ cent[2]= (float) atof(val);
+ } else if (id==60) {
+ /* short invisible= atoi(val); */
+ } else if (id==62) {
+ int colorid= atoi(val);
+
+ CLAMP(colorid, 1, 255);
+ dxf_col_to_rgb(colorid, &color[0], &color[1], &color[2]);
+ } else if (id==67) {
+ vspace= atoi(val);
+ } else if (id==70) {
+ flag= atoi(val);
+ }
+ read_group(id, val);
+ }
+
+ if (flag&1) {
+ if(!lwasp2d || strcmp(layname, oldplay)!=0) dxf_close_2dpoly();
+ if(p2dmhold != NULL && p2dmhold->totvert>65000) dxf_close_2dpoly();
+
+ if (p2dmhold==NULL) {
+ if (noob) {
+ ob= NULL;
+ me= add_mesh(); G.totmesh++;
+ ((ID *)me)->us=0;
+
+ if (strlen(entname)) new_id(&G.main->mesh, (ID *)me, entname);
+ else if (strlen(layname)) new_id(&G.main->mesh, (ID *)me, layname);
+
+ vcenter= zerovec;
+ } else {
+ ob= add_object(OB_MESH);
+ if (strlen(entname)) new_id(&G.main->object, (ID *)ob, entname);
+ else if (strlen(layname)) new_id(&G.main->object, (ID *)ob, layname);
+
+ if (strlen(layname)) ob->lay= dxf_get_layer_num(layname);
+ else ob->lay= G.scene->lay;
+
+ me= ob->data;
+
+ vcenter= ob->loc;
+ }
+ me->totvert=0;
+ me->totface=0;
+ me->mvert=NULL;
+ me->mface=NULL;
+
+ strcpy(oldplay, layname);
+
+ if(ob) VECCOPY(ob->loc, cent);
+
+ dxf_add_mat (ob, me, color, layname);
+
+ p2dhold= ob;
+ p2dmhold= me;
+ } else {
+ ob= p2dhold;
+ me= p2dmhold;
+ }
+
+ nverts=0;
+ while (group_is(0, "VERTEX")) {
+ read_group(id, val);
+ while(id!=0) {
+ if (id==10) {
+ vert[0]= (float) atof(val);
+ } else if (id==20) {
+ vert[1]= (float) atof(val);
+ } else if (id==30) {
+ vert[2]= (float) atof(val);
+ }
+ read_group(id, val);
+ }
+ nverts++;
+ me->totvert++;
+
+ vtmp= MEM_callocN(me->totvert*sizeof(MVert), "mverts");
+
+ if (me->mvert) {
+ memcpy (vtmp, me->mvert, (me->totvert-1)*sizeof(MVert));
+ MEM_freeN(me->mvert);
+ }
+ me->mvert= vtmp;
+ vtmp= NULL;
+
+ mvert= &me->mvert[me->totvert-1];
+
+ if (vspace) { VECCOPY(mvert->co, vert);
+ } else VecSubf(mvert->co, vert, vcenter);
+ }
+
+ me->totface++;
+ ftmp= MEM_callocN(me->totface*sizeof(MFace), "mface");
+
+ if(me->mface) {
+ memcpy(ftmp, me->mface, (me->totface-1)*sizeof(MFace));
+ MEM_freeN(me->mface);
+ }
+ me->mface= ftmp;
+ ftmp=NULL;
+
+ mface= &(((MFace*)me->mface)[me->totface-1]);
+
+ mface->v1= (me->totvert-nverts)+0;
+ mface->v2= (me->totvert-nverts)+1;
+ mface->v3= (me->totvert-nverts)+2;
+ if (nverts==4) mface->v4= (me->totvert-nverts)+3;
+
+ mface->edcode= 3;
+ mface->mat_nr= 0;
+
+ test_index_mface(mface, nverts);
+
+ lwasp2d=1;
+ } else if (flag&64) {
+ if (noob) {
+ ob= NULL;
+ me= add_mesh(); G.totmesh++;
+ ((ID *)me)->us=0;
+
+ if (strlen(entname)) new_id(&G.main->mesh, (ID *)me, entname);
+ else if (strlen(layname)) new_id(&G.main->mesh, (ID *)me, layname);
+
+ vcenter= zerovec;
+ } else {
+ ob= add_object(OB_MESH);
+ if (strlen(entname)) new_id(&G.main->object, (ID *)ob, entname);
+ else if (strlen(layname)) new_id(&G.main->object, (ID *)ob, layname);
+
+ if (strlen(layname)) ob->lay= dxf_get_layer_num(layname);
+ else ob->lay= G.scene->lay;
+
+ me= ob->data;
+
+ vcenter= ob->loc;
+ }
+ me->totvert=0;
+ me->totface=0;
+ me->mvert=NULL;
+ me->mface=NULL;
+
+ if(ob) VECCOPY(ob->loc, cent);
+
+ dxf_add_mat (ob, me, color, layname);
+
+ while (group_is(0, "VERTEX")) {
+ vflags= 0;
+ vids[0]= vids[1]= vids[2]= vids[3]= 0;
+
+ vflags=0;
+ read_group(id, val);
+ while(id!=0) {
+ if(id==8) {
+ ; /* Layer def, skip */
+ } else if (id==10) {
+ vert[0]= (float) atof(val);
+ } else if (id==20) {
+ vert[1]= (float) atof(val);
+ } else if (id==30) {
+ vert[2]= (float) atof(val);
+ } else if (id==70) {
+ vflags= atoi(val);
+ } else if (id==71) {
+ vids[0]= abs(atoi(val));
+ } else if (id==72) {
+ vids[1]= abs(atoi(val));
+ } else if (id==73) {
+ vids[2]= abs(atoi(val));
+ } else if (id==74) {
+ vids[3]= abs(atoi(val));
+ }
+ read_group(id, val);
+ }
+
+ if (vflags & 128 && vflags & 64) {
+ me->totvert++;
+
+ /* If we are nearing the limit scan to the next entry */
+ if(me->totvert > 65000) while(group_isnt(0, "SEQEND")) read_group(id, val);
+
+ vtmp= MEM_callocN(me->totvert*sizeof(MVert), "mverts");
+
+ if(me->mvert) {
+ memcpy(vtmp, me->mvert, (me->totvert-1)*sizeof(MVert));
+ MEM_freeN(me->mvert);
+ }
+ me->mvert= vtmp;
+ vtmp=NULL;
+
+ mvert= &me->mvert[(me->totvert-1)];
+
+ if (vspace) { VECCOPY(mvert->co, vert);
+ } else VecSubf(mvert->co, vert, vcenter);
+
+ } else if (vflags & 128) {
+ if(vids[2]==0) {
+ error("(PL) Error parsing dxf, not enough vertices near line %d", dxf_line);
+
+ error_exit=1;
+ fclose(dxf_fp);
+ return;
+ }
+
+ me->totface++;
+
+ ftmp= MEM_callocN(me->totface*sizeof(MFace), "mfaces");
+
+ if(me->mface) {
+ memcpy(ftmp, me->mface, (me->totface-1)*sizeof(MFace));
+ MEM_freeN(me->mface);
+ }
+ me->mface= ftmp;
+ ftmp=NULL;
+
+ mface= &(((MFace*)me->mface)[me->totface-1]);
+ mface->v1= vids[0]-1;
+ mface->v2= vids[1]-1;
+ mface->v3= vids[2]-1;
+
+ if(vids[3])
+ mface->v4= vids[3]-1;
+
+ mface->edcode= 3;
+ mface->mat_nr= 0;
+
+ if(vids[3])
+ test_index_mface(mface, 4);
+ else
+ test_index_mface(mface, 3);
+ } else {
+ error("Error parsing dxf, unknown polyline information near %d", dxf_line);
+
+ error_exit=1;
+ fclose(dxf_fp);
+ return;
+ }
+
+ }
+
+ if (!noob) {
+ G.obedit= ob;
+ make_editMesh();
+ load_editMesh();
+ free_editMesh();
+ waitcursor(1); /* patch yah... */
+ G.obedit= 0;
+ }
+ tex_space_mesh(me);
+ }
+}
+
+ /* 3D Face state vars */
+static Object *f3dhold=NULL;
+static Mesh *f3dmhold=NULL;
+static char oldflay[32];
+static short lwasf3d=0; /* last was face 3d? */
+
+static void dxf_close_3dface(void)
+{
+ f3dmhold= NULL;
+ if (f3dhold==NULL) return;
+
+ G.obedit= f3dhold;
+ make_editMesh();
+ load_editMesh();
+ free_editMesh();
+ waitcursor(1); /* patch yah... */
+ G.obedit= 0;
+ tex_space_mesh(f3dhold->data);
+
+ f3dhold=NULL;
+}
+
+static void dxf_read_3dface(int noob)
+{
+ /* Entity specific vars */
+ float vert2[3]={0.0, 0.0, 0.0};
+ float vert3[3]={0.0, 0.0, 0.0};
+ float vert4[3]={0.0, 0.0, 0.0};
+ short vspace=0;
+
+ int nverts=0;
+
+ /* Blender vars */
+ Object *ob;
+ Mesh *me;
+ MVert *mvert, *vtmp;
+ MFace *mface, *ftmp;
+
+ reset_vars;
+
+ read_group(id, val);
+ while(id!=0) {
+ if (id==8) {
+ BLI_strncpy(layname, val, sizeof(layname));
+
+ /* First vert/origin */
+ } else if (id==10) {
+ cent[0]= (float) atof(val);
+ if (nverts<1)nverts++;
+ } else if (id==20) {
+ cent[1]= (float) atof(val);
+ if (nverts<1)nverts++;
+ } else if (id==30) {
+ cent[2]= (float) atof(val);
+ if (nverts<1)nverts++;
+
+ /* Second vert */
+ } else if (id==11) {
+ vert2[0]= (float) atof(val);
+ if (nverts<2)nverts++;
+ } else if (id==21) {
+ vert2[1]= (float) atof(val);
+ if (nverts<2)nverts++;
+ } else if (id==31) {
+ vert2[2]= (float) atof(val);
+ if (nverts<2)nverts++;
+
+ /* Third vert */
+ } else if (id==12) {
+ vert3[0]= (float) atof(val);
+ if (nverts<3)nverts++;
+ } else if (id==22) {
+ vert3[1]= (float) atof(val);
+ if (nverts<3)nverts++;
+ } else if (id==32) {
+ vert3[2]= (float) atof(val);
+ if (nverts<3)nverts++;
+
+ /* Fourth vert */
+ } else if (id==13) {
+ vert4[0]= (float) atof(val);
+ if (nverts<4)nverts++;
+ } else if (id==23) {
+ vert4[1]= (float) atof(val);
+ if (nverts<4)nverts++;
+ } else if (id==33) {
+ vert4[2]= (float) atof(val);
+ if (nverts<4)nverts++;
+
+ /* Other */
+ } else if (id==60) {
+ /* short invisible= atoi(val); */
+ } else if (id==62) {
+ int colorid= atoi(val);
+
+ CLAMP(colorid, 1, 255);
+ dxf_col_to_rgb(colorid, &color[0], &color[1], &color[2]);
+ } else if (id==67) {
+ vspace= atoi(val);
+ }
+ read_group(id, val);
+ }
+
+ /* Check to see if we need to make a new object */
+
+ if(!lwasf3d || strcmp(layname, oldflay)!=0) dxf_close_3dface();
+ if(f3dmhold != NULL && f3dmhold->totvert>65000) dxf_close_3dface();
+
+ if(nverts<3) {
+ error("(3DF) Error parsing dxf, not enough vertices near line %d", dxf_line);
+
+ error_exit=1;
+ fclose(dxf_fp);
+ return;
+ }
+
+ if (f3dmhold==NULL) {
+ if (noob) {
+ ob= NULL;
+ me= add_mesh(); G.totmesh++;
+ ((ID *)me)->us=0;
+
+ if (strlen(entname)) new_id(&G.main->mesh, (ID *)me, entname);
+ else if (strlen(layname)) new_id(&G.main->mesh, (ID *)me, layname);
+
+ vcenter= zerovec;
+ } else {
+ ob= add_object(OB_MESH);
+ if (strlen(entname)) new_id(&G.main->object, (ID *)ob, entname);
+ else if (strlen(layname)) new_id(&G.main->object, (ID *)ob, layname);
+
+ if (strlen(layname)) ob->lay= dxf_get_layer_num(layname);
+ else ob->lay= G.scene->lay;
+
+ me= ob->data;
+
+ vcenter= ob->loc;
+ }
+ me->totvert=0;
+ me->totface=0;
+ me->mvert=NULL;
+ me->mface=NULL;
+
+ strcpy(oldflay, layname);
+
+ if(ob) VECCOPY(ob->loc, cent);
+
+ dxf_add_mat (ob, me, color, layname);
+
+ f3dhold= ob;
+ f3dmhold= me;
+ } else {
+ ob= f3dhold;
+ me= f3dmhold;
+ }
+
+ me->totvert+= nverts;
+ me->totface++;
+
+ vtmp= MEM_callocN(me->totvert*sizeof(MVert), "mverts");
+ ftmp= MEM_callocN(me->totface*sizeof(MFace), "mface");
+
+ if(me->mvert) {
+ memcpy(vtmp, me->mvert, (me->totvert-nverts)*sizeof(MVert));
+ MEM_freeN(me->mvert);
+ }
+ me->mvert= vtmp;
+ vtmp=NULL;
+
+ if(me->mface) {
+ memcpy(ftmp, me->mface, (me->totface-1)*sizeof(MFace));
+ MEM_freeN(me->mface);
+ }
+ me->mface= ftmp;
+ ftmp=NULL;
+
+ mvert= &me->mvert[(me->totvert-nverts)];
+ VecSubf(mvert->co, cent, vcenter);
+
+ mvert++;
+ if (vspace) { VECCOPY(mvert->co, vert2);
+ } else VecSubf(mvert->co, vert2, vcenter);
+
+ mvert++;
+ if (vspace) { VECCOPY(mvert->co, vert3);
+ } else VecSubf(mvert->co, vert3, vcenter);
+
+ if (nverts==4) {
+ mvert++;
+ if (vspace) { VECCOPY(mvert->co, vert4);
+ } else VecSubf(mvert->co, vert4, vcenter);
+ }
+
+ mface= &(((MFace*)me->mface)[me->totface-1]);
+ mface->v1= (me->totvert-nverts)+0;
+ mface->v2= (me->totvert-nverts)+1;
+ mface->v3= (me->totvert-nverts)+2;
+
+ if (nverts==4)
+ mface->v4= (me->totvert-nverts)+3;
+
+ mface->edcode= 3;
+ mface->mat_nr= 0;
+
+ test_index_mface(mface, nverts);
+
+ hasbumped=1;
+}
+
+static void dxf_read(char *filename)
+{
+ dxf_line=0;
+
+ dxf_fp= fopen(filename, "r");
+ if (dxf_fp==NULL) return;
+
+ while (1) {
+ read_group(id, val);
+ if (group_is(0, "EOF")) break;
+
+ if (id==999) continue;
+ id_check(0, "SECTION");
+
+ read_group(id, val);
+ if (group_is(2, "HEADER")) {
+ } else if (group_is(2, "TABLES")) {
+ } else if (group_is(2, "OBJECTS")) {
+ } else if (group_is(2, "CLASSES")) {
+ } else if (group_is(2, "BLOCKS")) {
+ while(1) {
+ read_group(id, val);
+ if (group_is(0, "BLOCK")) {
+ while(group_isnt(0, "ENDBLK")) {
+ read_group(id, val);
+ if(id==2) {
+ BLI_strncpy(entname, val, sizeof(entname));
+ } else if (id==3) {
+ /* Now the object def should follow */
+ if(strlen(entname)==0) {
+ error("Error parsing dxf, no mesh name near %d", dxf_line);
+ fclose(dxf_fp);
+ return;
+ }
+
+ /* Now the object def should follow */
+ while(group_isnt(0, "ENDBLK")) {
+ read_group(id, val);
+ if(group_is(0, "POLYLINE")) {
+ dxf_read_polyline(1);
+ if(error_exit) return;
+ lwasf3d=0;
+ lwasline=0;
+
+ while(group_isnt(0, "SEQEND")) read_group(id, val);
+ } else if(group_is(0, "ATTRIB")) {
+ while(group_isnt(0, "SEQEND")) read_group(id, val);
+ lwasf3d=0;
+ lwasp2d=0;
+ lwasline=0;
+ } else if(group_is(0, "POINT")) {
+ dxf_read_point(1);
+ if(error_exit) return;
+ lwasf3d=0;
+ lwasp2d=0;
+ lwasline=0;
+ } else if(group_is(0, "LINE")) {
+ dxf_read_line(1);
+ if(error_exit) return;
+ lwasline=1;
+ lwasp2d=0;
+ lwasf3d=0;
+ } else if(group_is(0, "3DFACE")) {
+ dxf_read_3dface(1);
+ if(error_exit) return;
+ lwasf3d=1;
+ lwasp2d=0;
+ lwasline=0;
+ } else if (group_is(0, "ENDBLK")) {
+ break;
+ }
+ }
+ } else if (group_is(0, "ENDBLK")) {
+ break;
+ }
+ }
+ while(id!=0) read_group(id, val);
+ } else if(group_is(0, "ENDSEC")) {
+ break;
+ }
+ }
+ } else if (group_is(2, "ENTITIES")) {
+ while(group_isnt(0, "ENDSEC")) {
+ char obname[32]="";
+ char layname[32]="";
+ float cent[3]={0.0, 0.0, 0.0};
+ float obsize[3]={1.0, 1.0, 1.0};
+ float obrot[3]={0.0, 0.0, 0.0};
+ int i;
+
+ if(!hasbumped) read_group(id, val);
+ hasbumped=0;
+ if (group_is(0, "INSERT")) {
+ Base *base;
+ Object *ob;
+ void *obdata;
+
+ read_group(id, val);
+ while(id!=0) {
+ if(id==2) {
+ BLI_strncpy(obname, val, sizeof(obname));
+ } else if (id==8) {
+ BLI_strncpy(layname, val, sizeof(layname));
+ } else if (id==10) {
+ cent[0]= (float) atof(val);
+ } else if (id==20) {
+ cent[1]= (float) atof(val);
+ } else if (id==30) {
+ cent[2]= (float) atof(val);
+ } else if (id==41) {
+ obsize[0]= (float) atof(val);
+ } else if (id==42) {
+ obsize[1]= (float) atof(val);
+ } else if (id==43) {
+ obsize[2]= (float) atof(val);
+ } else if (id==50) {
+ obrot[2]= (float) (atof(val)*M_PI/180.0);
+ } else if (id==60) {
+ /* short invisible= atoi(val); */
+ }
+
+ read_group(id, val);
+ }
+
+ if(strlen(obname)==0) {
+ error("Error parsing dxf, no object name near %d", dxf_line);
+ fclose(dxf_fp);
+ return;
+ }
+
+ obdata= find_id("ME", obname);
+
+ if (obdata) {
+ ob= alloc_libblock(&G.main->object, ID_OB, obname);
+
+ ob->type= OB_MESH;
+
+ ob->dt= OB_SHADED;
+ if(U.flag & MAT_ON_OB) ob->colbits= -1;
+
+ ob->trackflag= OB_POSY;
+ ob->upflag= OB_POSZ;
+
+ ob->ipoflag = OB_OFFS_OB+OB_OFFS_PARENT;
+
+ ob->dupon= 1; ob->dupoff= 0;
+ ob->dupsta= 1; ob->dupend= 100;
+
+ G.totobj++;
+
+ ob->data= obdata;
+ ((ID*)ob->data)->us++;
+
+ VECCOPY(ob->loc, cent);
+ VECCOPY(ob->size, obsize);
+ VECCOPY(ob->rot, obrot);
+
+ ob->mat= MEM_callocN(sizeof(void *)*1, "ob->mat");
+ ob->totcol= (unsigned char) ((Mesh*)ob->data)->totcol;
+ ob->actcol= 1;
+
+ for (i=0; i<ob->totcol; i++) ob->mat[i]= ((Mesh*)ob->data)->mat[i];
+
+ if (strlen(layname)) ob->lay= dxf_get_layer_num(layname);
+ else ob->lay= G.scene->lay;
+
+ /* aan de scene hangen */
+ base= MEM_callocN( sizeof(Base), "add_base");
+ BLI_addhead(&G.scene->base, base);
+
+ base->lay= ob->lay;
+
+ base->object= ob;
+
+ G.obedit= ob;
+ make_editMesh();
+ load_editMesh();
+ free_editMesh();
+ waitcursor(1); /* patch yah... */
+ G.obedit= 0;
+ tex_space_mesh(ob->data);
+ }
+
+ hasbumped=1;
+
+ lwasf3d=0;
+ lwasp2d=0;
+ lwasline=0;
+ } else if(group_is(0, "POLYLINE")) {
+ dxf_read_polyline(0);
+ if(error_exit) return;
+ lwasf3d=0;
+ lwasline=0;
+
+ while(group_isnt(0, "SEQEND")) read_group(id, val);
+ } else if(group_is(0, "ATTRIB")) {
+ while(group_isnt(0, "SEQEND")) read_group(id, val);
+ lwasf3d=0;
+ lwasp2d=0;
+ lwasline=0;
+ } else if(group_is(0, "POINT")) {
+ dxf_read_point(0);
+ if(error_exit) return;
+ lwasf3d=0;
+ lwasp2d=0;
+ lwasline=0;
+ } else if(group_is(0, "LINE")) {
+ dxf_read_line(0);
+ if(error_exit) return;
+ lwasline=1;
+ lwasp2d=0;
+ lwasf3d=0;
+ } else if(group_is(0, "3DFACE")) {
+ dxf_read_3dface(0);
+ if(error_exit) return;
+ lwasline=0;
+ lwasp2d=0;
+ lwasf3d=1;
+ } else if(group_is(0, "ENDSEC")) {
+ break;
+ }
+ }
+ }
+
+ while(group_isnt(0, "ENDSEC")) read_group(id, val);
+ }
+ id_check(0, "EOF");
+
+ fclose (dxf_fp);
+
+ /* Close any remaining state held stuff */
+ dxf_close_3dface();
+ dxf_close_2dpoly();
+ dxf_close_line();
+}
diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c
new file mode 100644
index 00000000000..4f6b6c4b0c2
--- /dev/null
+++ b/source/blender/blenkernel/intern/font.c
@@ -0,0 +1,656 @@
+
+/* font.c MIXED MODEL
+ *
+ * maart 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 <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <stdlib.h>
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+#include "MEM_guardedalloc.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+#include "BLI_vfontdata.h"
+
+#include "DNA_packedFile_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_vfont_types.h"
+#include "DNA_scene_types.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_bad_level_calls.h"
+
+#include "BKE_packedFile.h"
+
+#include "BKE_library.h"
+#include "BKE_font.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_screen.h"
+#include "BKE_anim.h"
+#include "BKE_curve.h"
+#include "BKE_displist.h"
+
+/* Nieuwe opzet voor vectorfont:
+ *
+ * geen PDrawfont meer, alles meteen naar Nurb en BezTriple
+ *
+ */
+
+struct chartrans {
+ float xof, yof;
+ float rot;
+ short linenr,charnr;
+};
+
+void free_vfont(struct VFont *vf)
+{
+ int i;
+
+ if (vf == 0) return;
+
+ if (vf->data) {
+ for (i = 0; i < MAX_VF_CHARS; i++){
+ while (vf->data->nurbsbase[i].first) {
+ Nurb *nu = vf->data->nurbsbase[i].first;
+ if (nu->bezt) MEM_freeN(nu->bezt);
+ BLI_freelinkN(&vf->data->nurbsbase[i], nu);
+ }
+ }
+
+ MEM_freeN(vf->data);
+ vf->data = NULL;
+ }
+
+ if (vf->packedfile) {
+ freePackedFile(vf->packedfile);
+ vf->packedfile = NULL;
+ }
+}
+
+static void *builtin_font_data= NULL;
+static int builtin_font_size= 0;
+
+void BKE_font_register_builtin(void *mem, int size)
+{
+ builtin_font_data= mem;
+ builtin_font_size= size;
+}
+
+static PackedFile *get_builtin_packedfile(void)
+{
+ if (!builtin_font_data) {
+ printf("Internal error, builtin font not loaded");
+
+ return NULL;
+ } else {
+ void *mem= MEM_mallocN(builtin_font_size, "vfd_builtin");
+
+ memcpy(mem, builtin_font_data, builtin_font_size);
+
+ return newPackedFileMemory(mem, builtin_font_size);
+ }
+}
+
+static VFontData *vfont_get_data(VFont *vfont)
+{
+ if (!vfont->data) {
+ PackedFile *pf;
+
+ if (BLI_streq(vfont->name, "<builtin>")) {
+ pf= get_builtin_packedfile();
+ } else {
+ if (vfont->packedfile) {
+ pf= vfont->packedfile;
+ } else {
+ pf= newPackedFile(vfont->name);
+ }
+ }
+
+ if (pf) {
+ vfont->data= BLI_vfontdata_from_psfont(pf);
+
+ if (pf != vfont->packedfile) {
+ freePackedFile(pf);
+ }
+ }
+ }
+
+ return vfont->data;
+}
+
+VFont *load_vfont(char *name)
+{
+ char filename[FILE_MAXFILE];
+ VFont *vfont= NULL;
+ PackedFile *pf;
+ int is_builtin;
+
+ if (BLI_streq(name, "<builtin>")) {
+ strcpy(filename, name);
+
+ pf= get_builtin_packedfile();
+ is_builtin= 1;
+ } else {
+ char dir[FILE_MAXDIR];
+
+ strcpy(dir, name);
+ BLI_splitdirstring(dir, filename);
+
+ pf= newPackedFile(name);
+ is_builtin= 0;
+ }
+
+ if (pf) {
+ VFontData *vfd;
+
+ waitcursor(1);
+
+ vfd= BLI_vfontdata_from_psfont(pf);
+
+ if (vfd) {
+ vfont = alloc_libblock(&G.main->vfont, ID_VF, filename);
+ vfont->data = vfd;
+
+ BLI_strncpy(vfont->name, name, sizeof(vfont->name));
+
+ // if autopack is on store the packedfile in de font structure
+ if (!is_builtin && (G.fileflags & G_AUTOPACK)) {
+ vfont->packedfile = pf;
+ }
+ }
+ if (!vfont || vfont->packedfile != pf) {
+ freePackedFile(pf);
+ }
+
+ waitcursor(0);
+ }
+
+ return vfont;
+}
+
+static void buildchar(Curve *cu, unsigned char ascii, float ofsx, float ofsy, float rot)
+{
+ BezTriple *bezt1, *bezt2;
+ Nurb *nu1, *nu2;
+ float *fp, fsize, shear, x, si, co;
+ VFontData *vfd;
+ int i;
+
+ vfd= vfont_get_data(cu->vfont);
+ if (!vfd) return;
+
+ /* maak een kopie op afstand ofsx, ofsy met shear*/
+ fsize= cu->fsize;
+ shear= cu->shear;
+ si= (float)sin(rot);
+ co= (float)cos(rot);
+
+ nu1 = vfd->nurbsbase[ascii].first;
+ while(nu1)
+ {
+ bezt1 = nu1->bezt;
+ if (bezt1){
+ nu2 =(Nurb*) MEM_mallocN(sizeof(Nurb),"duplichar_nurb");
+ if (nu2 == 0) break;
+ memcpy(nu2, nu1, sizeof(struct Nurb));
+ nu2->resolu= cu->resolu;
+ nu2->bp = 0;
+ nu2->knotsu = nu2->knotsv = 0;
+ nu2->flag= ME_SMOOTH;
+ /* nu2->trim.first = 0; */
+ /* nu2->trim.last = 0; */
+ i = nu2->pntsu;
+
+ bezt2 = (BezTriple*)MEM_mallocN(i * sizeof(BezTriple),"duplichar_bezt2");
+ if (bezt2 == 0){
+ MEM_freeN(nu2);
+ break;
+ }
+ memcpy(bezt2, bezt1, i * sizeof(struct BezTriple));
+ nu2->bezt = bezt2;
+
+ if (shear != 0.0) {
+ bezt2 = nu2->bezt;
+
+ for (i= nu2->pntsu; i > 0; i--) {
+ bezt2->vec[0][0] += shear * bezt2->vec[0][1];
+ bezt2->vec[1][0] += shear * bezt2->vec[1][1];
+ bezt2->vec[2][0] += shear * bezt2->vec[2][1];
+ bezt2++;
+ }
+ }
+ if(rot!=0.0) {
+ bezt2= nu2->bezt;
+ for (i=nu2->pntsu; i > 0; i--) {
+ fp= bezt2->vec[0];
+
+ x= fp[0];
+ fp[0]= co*x + si*fp[1];
+ fp[1]= -si*x + co*fp[1];
+ x= fp[3];
+ fp[3]= co*x + si*fp[4];
+ fp[4]= -si*x + co*fp[4];
+ x= fp[6];
+ fp[6]= co*x + si*fp[7];
+ fp[7]= -si*x + co*fp[7];
+
+ bezt2++;
+ }
+ }
+ bezt2 = nu2->bezt;
+
+ for (i= nu2->pntsu; i > 0; i--) {
+ fp= bezt2->vec[0];
+
+ fp[0]= (fp[0]+ofsx)*fsize;
+ fp[1]= (fp[1]+ofsy)*fsize;
+ fp[3]= (fp[3]+ofsx)*fsize;
+ fp[4]= (fp[4]+ofsy)*fsize;
+ fp[6]= (fp[6]+ofsx)*fsize;
+ fp[7]= (fp[7]+ofsy)*fsize;
+ bezt2++;
+ }
+
+ BLI_addtail(&(cu->nurb), nu2);
+ }
+ nu1 = nu1->next;
+ }
+}
+
+
+struct chartrans *text_to_curve(Object *ob, int mode)
+{
+ VFont *vfont;
+ VFontData *vfd;
+ Curve *cu, *cucu;
+ struct chartrans *chartransdata, *ct;
+ float distfac, tabfac, ctime, dtime, tvec[4], vec[4], rotvec[3], minx, maxx, miny, maxy;
+ float cmat[3][3], timeofs, si, co, sizefac;
+ float *f, maxlen=0, xof, yof, xtrax, linedist, *linedata, *linedata2;
+ int i, slen, oldflag;
+ short cnr=0, lnr=0;
+ char ascii, *mem;
+
+ /* opmerking: berekeningen altijd tot en met de '\0' van de string omdat
+ de cursor op die plek moet kunnen staan */
+
+ if(ob->type!=OB_FONT) return 0;
+
+ cu= ob->data;
+
+ vfont= cu->vfont;
+ if (vfont==0) return 0;
+ if (cu->str==0) return 0;
+
+ vfd= vfont_get_data(vfont);
+ if (!vfd) return 0;
+
+ /* aantal regels tellen */
+ mem= cu->str;
+ slen = strlen(mem);
+ cu->lines= 1;
+ for (i= 0; i<=slen; i++, mem++) {
+ ascii = *mem;
+ if(ascii== '\n' || ascii== '\r') cu->lines++;
+ }
+
+ /* bereken ofset en rotatie van iedere letter */
+ ct = chartransdata =
+ (struct chartrans*)MEM_callocN((slen+1)* sizeof(struct chartrans),"buildtext");
+ linedata= MEM_mallocN(sizeof(float)*cu->lines,"buildtext2");
+ linedata2= MEM_mallocN(sizeof(float)*cu->lines,"buildtext2");
+ xof= cu->xof;
+ yof= cu->yof;
+
+ xtrax= 0.5f*cu->spacing-0.5f;
+ linedist= cu->linedist;
+
+ for (i = 0 ; i<=slen ; i++) {
+ ascii = cu->str[i];
+ if(ascii== '\n' || ascii== '\r' || ascii==0) {
+ ct->xof= xof;
+ ct->yof= yof;
+ ct->linenr= lnr;
+ ct->charnr= cnr;
+
+ /* alleen lege regels mogen kleiner dan 1 zijn */
+ if( linedist<1.0) {
+ if(i<slen && (cu->str[i+1]=='\r' || cu->str[i+1]=='\n')) yof-= linedist;
+ else yof-= 1.0;
+ }
+ else yof-= linedist;
+
+ maxlen= MAX2(maxlen, xof);
+ linedata[lnr]= xof;
+ linedata2[lnr]= cnr;
+ xof= cu->xof;
+ lnr++;
+ cnr= 0;
+ }
+ else if(ascii==9) { /* TAB */
+ ct->xof= xof;
+ ct->yof= yof;
+ ct->linenr= lnr;
+ ct->charnr= cnr++;
+
+ tabfac= (xof-cu->xof+0.01f);
+ tabfac= (float)(2.0*ceil(tabfac/2.0));
+ xof= cu->xof+tabfac;
+ }
+ else {
+ ct->xof= xof;
+ ct->yof= yof;
+ ct->linenr= lnr;
+ ct->charnr= cnr++;
+
+ xof += vfd->width[ascii] + xtrax;
+ }
+ ct++;
+ }
+
+ /* met alle fontsettings plekken letters berekenen */
+ if(cu->spacemode!=CU_LEFT && lnr>1) {
+ ct= chartransdata;
+
+ if(cu->spacemode==CU_RIGHT) {
+ for(i=0;i<lnr;i++) linedata[i]= maxlen-linedata[i];
+ for (i=0; i<=slen; i++) {
+ ct->xof+= linedata[ct->linenr];
+ ct++;
+ }
+ } else if(cu->spacemode==CU_MIDDLE) {
+ for(i=0;i<lnr;i++) linedata[i]= (maxlen-linedata[i])/2;
+ for (i=0; i<=slen; i++) {
+ ct->xof+= linedata[ct->linenr];
+ ct++;
+ }
+ } else if(cu->spacemode==CU_FLUSH) {
+ for(i=0;i<lnr;i++)
+ if(linedata2[i]>1)
+ linedata[i]= (maxlen-linedata[i])/(linedata2[i]-1);
+ for (i=0; i<=slen; i++) {
+ ct->xof+= ct->charnr*linedata[ct->linenr];
+ ct++;
+ }
+ }
+ }
+
+ /* TEXT ON CURVE */
+ if(cu->textoncurve) {
+ cucu= cu->textoncurve->data;
+
+ oldflag= cucu->flag;
+ cucu->flag |= (CU_PATH+CU_FOLLOW);
+
+ if(cucu->path==0) calc_curvepath(cu->textoncurve);
+ if(cucu->path) {
+
+
+ Mat3CpyMat4(cmat, cu->textoncurve->obmat);
+ sizefac= Normalise(cmat[0])/cu->fsize;
+
+ minx=miny= 1.0e20f;
+ maxx=maxy= -1.0e20f;
+ ct= chartransdata;
+ for (i=0; i<=slen; i++, ct++) {
+ if(minx>ct->xof) minx= ct->xof;
+ if(maxx<ct->xof) maxx= ct->xof;
+ if(miny>ct->yof) miny= ct->yof;
+ if(maxy<ct->yof) maxy= ct->yof;
+ }
+
+ /* we zetten de x-coordinaat exact op de curve, de y wordt geroteerd */
+
+ /* de lengte correctie */
+ distfac= sizefac*cucu->path->totdist/(maxx-minx);
+ timeofs= 0.0;
+
+ if(distfac > 1.0) {
+ /* pad langer dan tekst: spacemode doet mee */
+ distfac= 1.0f/distfac;
+
+ if(cu->spacemode==CU_RIGHT) {
+ timeofs= 1.0f-distfac;
+ }
+ else if(cu->spacemode==CU_MIDDLE) {
+ timeofs= (1.0f-distfac)/2.0f;
+ }
+ else if(cu->spacemode==CU_FLUSH) distfac= 1.0f;
+
+ }
+ else distfac= 1.0;
+
+ distfac/= (maxx-minx);
+
+ timeofs+= distfac*cu->xof; /* niet cyclic */
+
+ ct= chartransdata;
+ for (i=0; i<=slen; i++, ct++) {
+
+ /* roteren rond centrum letter */
+ ascii = cu->str[i];
+ dtime= distfac*0.35f*vfd->width[ascii]; /* Waarom is 0.5 te groot? */
+ dtime= distfac*0.0f*vfd->width[ascii]; /* Waarom is 0.5 te groot? */
+
+ ctime= timeofs + distfac*( ct->xof - minx);
+ CLAMP(ctime, 0.0, 1.0);
+
+ /* de goede plek EN de goede rotatie apart berekenen */
+ where_on_path(cu->textoncurve, ctime, vec, tvec);
+ where_on_path(cu->textoncurve, ctime+dtime, tvec, rotvec);
+
+ VecMulf(vec, sizefac);
+
+ ct->rot= (float)(M_PI-atan2(rotvec[1], rotvec[0]));
+
+ si= (float)sin(ct->rot);
+ co= (float)cos(ct->rot);
+
+ yof= ct->yof;
+
+ ct->xof= vec[0] + si*yof;
+ ct->yof= vec[1] + co*yof;
+
+ }
+ cucu->flag= oldflag;
+ }
+ }
+
+
+ if(mode==FO_CURSUP || mode==FO_CURSDOWN) {
+ /* 2: curs omhoog
+ 3: curs omlaag */
+ ct= chartransdata+cu->pos;
+
+ if(mode==FO_CURSUP && ct->linenr==0);
+ else if(mode==FO_CURSDOWN && ct->linenr==lnr);
+ else {
+ if(mode==FO_CURSUP) lnr= ct->linenr-1;
+ else lnr= ct->linenr+1;
+ cnr= ct->charnr;
+ /* zoek karakter met lnr en cnr */
+ cu->pos= 0;
+ ct= chartransdata;
+ for (i= 0; i<slen; i++) {
+ if(ct->linenr==lnr) {
+ if(ct->charnr==cnr) break;
+ if( (ct+1)->charnr==0) break;
+ }
+ else if(ct->linenr>lnr) break;
+ cu->pos++;
+ ct++;
+ }
+ }
+ }
+
+ /* eerst cursor */
+ if(ob==G.obedit) {
+ ct= chartransdata+cu->pos;
+ si= (float)sin(ct->rot);
+ co= (float)cos(ct->rot);
+
+ f= G.textcurs[0];
+
+ f[0]= cu->fsize*(-0.1f*co + ct->xof);
+ f[1]= cu->fsize*(0.1f*si + ct->yof);
+
+ f[2]= cu->fsize*(0.1f*co + ct->xof);
+ f[3]= cu->fsize*(-0.1f*si + ct->yof);
+
+ f[4]= cu->fsize*( 0.1f*co + 0.8f*si + ct->xof);
+ f[5]= cu->fsize*(-0.1f*si + 0.8f*co + ct->yof);
+
+ f[6]= cu->fsize*(-0.1f*co + 0.8f*si + ct->xof);
+ f[7]= cu->fsize*( 0.1f*si + 0.8f*co + ct->yof);
+
+ }
+
+ if(mode==0) {
+ /* nurbdata maken */
+
+ freeNurblist(&cu->nurb);
+
+ ct= chartransdata;
+ for (i= 0; i<slen; i++) {
+ ascii = cu->str[i];
+ buildchar(cu, ascii, ct->xof, ct->yof, ct->rot);
+ ct++;
+ }
+ }
+
+ MEM_freeN(linedata);
+ MEM_freeN(linedata2);
+
+ if(mode==FO_DUPLI) {
+ return chartransdata;
+ }
+
+ MEM_freeN(chartransdata);
+ return 0;
+}
+
+
+/* ***************** DUPLI ***************** */
+
+static Object *find_family_object(Object **obar, char *family, char ch)
+{
+ Object *ob;
+ int flen;
+
+ if( obar[ch] ) return obar[ch];
+
+ flen= strlen(family);
+
+ ob= G.main->object.first;
+ while(ob) {
+ if( ob->id.name[flen+2]==ch ) {
+ if( strncmp(ob->id.name+2, family, flen)==0 ) break;
+ }
+ ob= ob->id.next;
+ }
+
+ obar[ch]= ob;
+
+ return ob;
+}
+
+
+void font_duplilist(Object *par)
+{
+ extern ListBase duplilist;
+ Object *ob, *newob, *obar[256];
+ Curve *cu;
+ struct chartrans *ct, *chartransdata;
+ float vec[3], pmat[4][4], fsize, xof, yof;
+ int slen, a;
+
+ Mat4CpyMat4(pmat, par->obmat);
+
+ /* in par staat een familienaam, deze gebruiken om objecten te vinden */
+
+ chartransdata= text_to_curve(par, FO_DUPLI);
+ if(chartransdata==0) return;
+
+ memset(obar, 0, 256*4);
+
+ cu= par->data;
+ slen= strlen(cu->str);
+ fsize= cu->fsize;
+ xof= cu->xof;
+ yof= cu->yof;
+
+ ct= chartransdata;
+ set_displist_onlyzero(1);
+
+ for(a=0; a<slen; a++, ct++) {
+
+ ob= find_family_object(obar, cu->family, cu->str[a]);
+ if(ob) {
+
+ makeDispList(ob);
+
+ vec[0]= fsize*(ct->xof - xof);
+ vec[1]= fsize*(ct->yof - yof);
+ vec[2]= 0.0;
+
+ Mat4MulVecfl(pmat, vec);
+
+ newob= MEM_mallocN(sizeof(Object), "newobj dupli");
+ memcpy(newob, ob, sizeof(Object));
+ newob->flag |= OB_FROMDUPLI;
+ newob->id.newid= (ID *)par; /* duplicator bewaren */
+ newob->totcol= par->totcol; /* voor give_current_material */
+
+ Mat4CpyMat4(newob->obmat, par->obmat);
+ VECCOPY(newob->obmat[3], vec);
+
+ newob->parent= 0;
+ newob->track= 0;
+
+ BLI_addtail(&duplilist, newob);
+ }
+
+ }
+ set_displist_onlyzero(0);
+ MEM_freeN(chartransdata);
+}
diff --git a/source/blender/blenkernel/intern/group.c b/source/blender/blenkernel/intern/group.c
new file mode 100644
index 00000000000..6f01d028326
--- /dev/null
+++ b/source/blender/blenkernel/intern/group.c
@@ -0,0 +1,329 @@
+/* group.c sept 2000
+ * - cleaned up mar-01 nzc
+ *
+ *
+ * ton roosendaal
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_ID.h"
+#include "DNA_group_types.h"
+#include "DNA_object_types.h"
+#include "DNA_ipo_types.h"
+
+#include "BLI_blenlib.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+
+#include "BKE_library.h"
+#include "BKE_group.h"
+#include "BKE_object.h"
+#include "BKE_ipo.h"
+
+void free_object_key(ObjectKey *ok)
+{
+ if(ok->ipo) ok->ipo->id.us--;
+
+ MEM_freeN(ok);
+}
+
+void free_group_object(GroupObject *go)
+{
+ ObjectKey *ok;
+
+ while(go->okey.first) {
+ ok= go->okey.first;
+ BLI_remlink(&go->okey, ok);
+ free_object_key(ok);
+ }
+ MEM_freeN(go);
+}
+
+
+void free_group(Group *group)
+{
+ /* don't free group itself */
+ GroupObject *go;
+
+ BLI_freelistN(&group->gkey);
+
+ while(group->gobject.first) {
+ go= group->gobject.first;
+ BLI_remlink(&group->gobject, go);
+ free_group_object(go);
+ }
+
+}
+
+Group *add_group()
+{
+ Group *group;
+
+ group = alloc_libblock(&G.main->group, ID_GR, "Group");
+ return group;
+}
+
+/* assumes 'ok' is unitialized */
+void object_to_obkey(Object *ob, ObjectKey *ok)
+{
+ ok->partype= ob->partype;
+ ok->par1= ob->par1;
+ ok->par2= ob->par2;
+ ok->par3= ob->par3;
+
+ ok->parent= ob->parent;
+ ok->track= ob->track;
+
+ ok->ipo= copy_ipo(ob->ipo);
+
+ memcpy(ok->loc, ob->loc, 7*3*sizeof(float));
+ memcpy(ok->quat, ob->quat, 2*4*sizeof(float));
+ memcpy(ok->obmat, ob->obmat, 3*4*4*sizeof(float));
+
+ ok->lay= ob->lay;
+ ok->transflag= ob->transflag;
+ ok->trackflag= ob->transflag;
+ ok->upflag= ob->upflag;
+ ok->sf= ob->sf;
+ ok->ctime= ob->ctime;
+
+
+}
+
+void obkey_to_object(ObjectKey *ok, Object *ob)
+{
+ ob->partype= ok->partype;
+ ob->par1= ok->par1;
+ ob->par2= ok->par2;
+ ob->par3= ok->par3;
+
+ ob->parent= ok->parent;
+ ob->track= ok->track;
+
+ /* pretty tricky, this makes ob->ipo blocks with users 'hanging around' */
+ if(ob->ipo) {
+ free_libblock_us(&G.main->ipo, ob->ipo);
+ }
+ ob->ipo= copy_ipo(ok->ipo);
+
+ memcpy(ob->loc, ok->loc, 7*3*sizeof(float));
+ memcpy(ob->quat, ok->quat, 2*4*sizeof(float));
+ memcpy(ob->obmat, ok->obmat, 3*4*4*sizeof(float));
+
+ ob->lay= ok->lay;
+ ob->transflag= ok->transflag;
+ ob->trackflag= ok->transflag;
+ ob->upflag= ok->upflag;
+ ob->sf= ok->sf;
+ ob->ctime= ok->ctime;
+}
+
+/* current ob position */
+void add_object_key(GroupObject *go, GroupKey *gk)
+{
+ ObjectKey *ok;
+
+ /* check if there already is a key */
+ ok= go->okey.first;
+ while(ok) {
+ if(ok->gkey == gk) break;
+ ok= ok->next;
+ }
+
+ if(ok) {
+ BLI_remlink(&go->okey, ok);
+ free_object_key(ok);
+ }
+ ok= MEM_mallocN(sizeof(ObjectKey), "objectkey");
+ ok->gkey= gk;
+
+ object_to_obkey(go->ob, ok);
+
+ BLI_addtail(&go->okey, ok);
+
+}
+
+/* external */
+void add_to_group(Group *group, Object *ob)
+{
+ GroupObject *go;
+ GroupKey *gk;
+
+ /* check if the object has been added already */
+ go= group->gobject.first;
+ while(go) {
+ if(go->ob==ob) return;
+ go= go->next;
+ }
+
+ go= MEM_callocN(sizeof(GroupObject), "groupobject");
+ BLI_addtail( &group->gobject, go);
+
+ go->ob= ob;
+
+ /* keys? */
+ gk= group->gkey.first;
+ while(gk) {
+ add_object_key(go, gk);
+ gk= gk->next;
+ }
+}
+
+void rem_from_group(Group *group, Object *ob)
+{
+ GroupObject *go, *gon;
+ ObjectKey *ok;
+
+ go= group->gobject.first;
+ while(go) {
+ gon= go->next;
+ if(go->ob==ob) {
+ BLI_remlink(&group->gobject, go);
+ free_group_object(go);
+ }
+ else {
+ ok= go->okey.first;
+ while(ok) {
+ if(ok->parent==ob) ok->parent= NULL;
+ if(ok->track==ob) ok->track= NULL;
+ ok= ok->next;
+ }
+ }
+ go= gon;
+ }
+}
+
+void add_group_key(Group *group)
+{
+ GroupObject *go;
+ GroupKey *gk;
+ int nr=10;
+ extern char colname_array[][20]; /* material.c */
+
+ gk= group->gkey.first;
+ while(gk) {
+ nr++;
+ gk= gk->next;
+ }
+
+ gk= MEM_callocN(sizeof(GroupKey), "groupkey");
+ BLI_addtail(&group->gkey, gk);
+ strcpy(gk->name, colname_array[ nr % 120 ]);
+
+ go= group->gobject.first;
+ while(go) {
+ add_object_key(go, gk);
+ go= go->next;
+ }
+
+ group->active= gk;
+}
+
+void set_object_key(Object *ob, ObjectKey *ok)
+{
+ obkey_to_object(ok, ob);
+}
+
+void set_group_key(Group *group)
+{
+ /* sets active */
+ GroupObject *go;
+ ObjectKey *ok;
+
+ if(group->active==NULL) return;
+
+ go= group->gobject.first;
+ while(go) {
+ ok= go->okey.first;
+ while(ok) {
+ if(ok->gkey==group->active) {
+ set_object_key(go->ob, ok);
+ break;
+ }
+ ok= ok->next;
+ }
+ go= go->next;
+ }
+
+}
+
+Group *find_group(Object *ob)
+{
+ Group *group= G.main->group.first;
+ GroupObject *go;
+
+ while(group) {
+
+ go= group->gobject.first;
+ while(go) {
+ if(go->ob==ob) return group;
+ go= go->next;
+ }
+ group= group->id.next;
+ }
+ return NULL;
+}
+
+void set_group_key_name(Group *group, char *name)
+{
+ GroupKey *gk;
+
+ if(group==NULL) return;
+
+ gk= group->gkey.first;
+ while(gk) {
+ if(strcmp(name, gk->name)==0) break;
+ gk= gk->next;
+ }
+
+ if(gk) {
+ group->active= gk;
+ set_group_key(group);
+ }
+}
+
+void set_group_key_frame(Group *group, float frame)
+{
+ GroupObject *go;
+
+ if(group==NULL) return;
+
+ go= group->gobject.first;
+ while(go) {
+ where_is_object_time(go->ob, frame);
+ go= go->next;
+ }
+}
diff --git a/source/blender/blenkernel/intern/ika.c b/source/blender/blenkernel/intern/ika.c
new file mode 100644
index 00000000000..885c64f0397
--- /dev/null
+++ b/source/blender/blenkernel/intern/ika.c
@@ -0,0 +1,596 @@
+
+/* ika.c MIXED MODEL
+ *
+ * april 96
+ *
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 <stdlib.h>
+
+#include "MEM_guardedalloc.h"
+
+/* types */
+#include "DNA_ika_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_view3d_types.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+/* functions */
+#include "BKE_blender.h"
+#include "BKE_library.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_object.h"
+#include "BKE_ika.h"
+
+/* Let's go! */
+#define TOLER 0.000076
+#define CLAMP(a, b, c) if((a)<(b)) (a)=(b); else if((a)>(c)) (a)=(c)
+
+
+void unlink_ika(Ika *ika)
+{
+ /* loskoppelen: */
+
+
+}
+
+/* niet Ika zelf vrijgeven */
+void free_ika(Ika *ika)
+{
+
+ /* unimplemented!!! */
+ unlink_ika(ika);
+
+ BLI_freelistN(&ika->limbbase);
+
+ if(ika->def) MEM_freeN(ika->def);
+}
+
+Ika *add_ika()
+{
+ Ika *ika;
+
+ ika= alloc_libblock(&G.main->ika, ID_IK, "Ika");
+ ika->flag = IK_GRABEFF | IK_XYCONSTRAINT;
+
+ ika->xyconstraint= 0.5f;
+ ika->mem= 0.3f;
+ ika->iter= 6;
+
+ return ika;
+}
+
+Ika *copy_ika(Ika *ika)
+{
+ Ika *ikan;
+
+ ikan= copy_libblock(ika);
+
+ duplicatelist(&ikan->limbbase, &ika->limbbase);
+
+ ikan->def= MEM_dupallocN(ikan->def);
+
+ return ikan;
+}
+
+void make_local_ika(Ika *ika)
+{
+ Object *ob;
+ Ika *ikan;
+ int local=0, lib=0;
+
+ /* - zijn er alleen lib users: niet doen
+ * - zijn er alleen locale users: flag zetten
+ * - mixed: copy
+ */
+
+ if(ika->id.lib==0) return;
+ if(ika->id.us==1) {
+ ika->id.lib= 0;
+ ika->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)ika, 0);
+ return;
+ }
+
+ ob= G.main->object.first;
+ while(ob) {
+ if(ob->data==ika) {
+ if(ob->id.lib) lib= 1;
+ else local= 1;
+ }
+ ob= ob->id.next;
+ }
+
+ if(local && lib==0) {
+ ika->id.lib= 0;
+ ika->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)ika, 0);
+ }
+ else if(local && lib) {
+ ikan= copy_ika(ika);
+ ikan->id.us= 0;
+
+ ob= G.main->object.first;
+ while(ob) {
+ if(ob->data==ika) {
+
+ if(ob->id.lib==0) {
+ ob->data= ikan;
+ ikan->id.us++;
+ ika->id.us--;
+ }
+ }
+ ob= ob->id.next;
+ }
+ }
+}
+
+int count_limbs(Object *ob)
+{
+ int tot=0;
+ Ika *ika;
+ Limb *li;
+
+ if(ob->type!=OB_IKA) return 0;
+ ika= ob->data;
+
+ li= ika->limbbase.first;
+ while(li) {
+ tot++;
+ li= li->next;
+ }
+ return tot;
+}
+
+/* ************************************************** */
+
+
+/* aan hand van eff[] de len en alpha */
+void calc_limb(Limb *li)
+{
+ Limb *prev= li;
+ float vec[2], alpha= 0.0;
+
+ /* alpha van 'parents' */
+ while( (prev=prev->prev) ) {
+ alpha+= prev->alpha;
+ }
+
+ if(li->prev) {
+ vec[0]= -li->prev->eff[0];
+ vec[1]= -li->prev->eff[1];
+ }
+ else vec[0]= vec[1]= 0.0;
+
+ vec[0]+= li->eff[0];
+ vec[1]+= li->eff[1];
+
+ li->alpha= (float)atan2(vec[1], vec[0]) - alpha;
+ li->len= (float)sqrt(vec[0]*vec[0] + vec[1]*vec[1]);
+
+}
+
+/* aan hand van len en alpha worden de eindpunten berekend */
+void calc_ika(Ika *ika, Limb *li)
+{
+ float alpha=0.0, co, si;
+
+ if(li) {
+ Limb *prev= li;
+ while((prev=prev->prev)) {
+ alpha+= prev->alpha;
+ }
+ }
+ else li= ika->limbbase.first;
+
+ while(li) {
+ if(li->alpha != li->alpha) li->alpha= 0.0f; /* NaN patch */
+
+ alpha+= li->alpha;
+
+ co= (float)cos(alpha);
+ si= (float)sin(alpha);
+
+ li->eff[0]= co*li->len;
+ li->eff[1]= si*li->len;
+
+ if(li->prev) {
+ li->eff[0]+= li->prev->eff[0];
+ li->eff[1]+= li->prev->eff[1];
+ }
+
+ if(li->next==0) {
+ ika->eff[0]= li->eff[0];
+ ika->eff[1]= li->eff[1];
+ }
+
+ li= li->next;
+ }
+}
+
+void init_defstate_ika(Object *ob)
+{
+ Ika *ika;
+ Limb *li;
+
+ ika= ob->data;
+ ika->totx= 0.0;
+ ika->toty= 0.0;
+ li= ika->limbbase.first;
+
+ calc_ika(ika, 0); /* correcte eindpunten */
+
+ while(li) {
+ li->alphao= li->alpha;
+ li->leno= li->len;
+
+ li= li->next;
+ }
+ ika->eff[2]= 0.0;
+ VecMat4MulVecfl(ika->effg, ob->obmat, ika->eff);
+}
+
+void itterate_limb(Ika *ika, Limb *li)
+{
+ float da, n1[2], n2[2], len1, len2;
+
+ if(li->prev) {
+ n1[0]= ika->eff[0] - li->prev->eff[0];
+ n1[1]= ika->eff[1] - li->prev->eff[1];
+ n2[0]= ika->effn[0] - li->prev->eff[0];
+ n2[1]= ika->effn[1] - li->prev->eff[1];
+ }
+ else {
+ n1[0]= ika->eff[0];
+ n1[1]= ika->eff[1];
+ n2[0]= ika->effn[0];
+ n2[1]= ika->effn[1];
+ }
+ len1= (float)sqrt(n1[0]*n1[0] + n1[1]*n1[1]);
+ len2= (float)sqrt(n2[0]*n2[0] + n2[1]*n2[1]);
+
+ da= (1.0f-li->fac)*saacos( (n1[0]*n2[0]+n1[1]*n2[1])/(len1*len2) );
+
+ if(n1[0]*n2[1] < n1[1]*n2[0]) da= -da;
+
+ li->alpha+= da;
+
+}
+
+void rotate_ika(Object *ob, Ika *ika)
+{
+ Limb *li;
+ float len2, da, n1[2], n2[2];
+
+ /* terug roteren */
+ euler_rot(ob->rot, -ika->toty, 'y');
+ ika->toty= 0.0;
+
+ where_is_object(ob);
+
+ Mat4Invert(ob->imat, ob->obmat);
+ VecMat4MulVecfl(ika->effn, ob->imat, ika->effg);
+
+ li= ika->limbbase.last;
+ if(li==0) return;
+
+ n1[0]= ika->eff[0];
+ n2[0]= ika->effn[0];
+ n2[1]= ika->effn[2];
+
+ len2= (float)sqrt(n2[0]*n2[0] + n2[1]*n2[1]);
+
+ if(len2>TOLER) {
+ da= (n2[0])/(len2);
+ if(n1[0]<0.0) da= -da;
+
+ /* als de x comp bijna nul is kan dit gebeuren */
+ if(da<=-1.0+TOLER || da>=1.0) ;
+ else {
+
+ da= saacos( da );
+ if(n1[0]*n2[1] > 0.0) da= -da;
+
+ euler_rot(ob->rot, da, 'y');
+ ika->toty= da;
+ }
+ }
+}
+
+void rotate_ika_xy(Object *ob, Ika *ika)
+{
+ Limb *li;
+ float ang, da, n1[3], n2[3], axis[3], quat[4];
+
+ /* terug roteren */
+ euler_rot(ob->rot, -ika->toty, 'y');
+ euler_rot(ob->rot, -ika->totx, 'x');
+
+ where_is_object(ob);
+
+ Mat4Invert(ob->imat, ob->obmat);
+ VecMat4MulVecfl(ika->effn, ob->imat, ika->effg);
+
+ li= ika->limbbase.last;
+ if(li==0) return;
+
+ /* ika->eff = old situation */
+ /* ika->effn = desired situation */
+
+ *(n1)= *(ika->effn);
+ *(n1+1)= *(ika->effn+1);
+ *(n1+2)= 0.0;
+
+ *(n2)= *(ika->effn);
+ *(n2+1)= *(ika->effn+1);
+ *(n2+2)= *(ika->effn+2);
+
+ Normalise(n1);
+ Normalise(n2);
+
+ ang= n1[0]*n2[0] + n1[1]*n2[1] + n1[2]*n2[2];
+ ang= saacos(ang);
+
+ if(ang<-0.0000001 || ang>0.00000001) {
+ Crossf(axis, n1, n2);
+ Normalise(axis);
+ quat[0]= (float)cos(0.5*ang);
+ da= (float)sin(0.5*ang);
+ quat[1]= da*axis[0];
+ quat[2]= da*axis[1];
+ quat[3]= da*axis[2];
+
+ QuatToEul(quat, axis);
+
+ ika->totx= axis[0];
+ CLAMP(ika->totx, -ika->xyconstraint, ika->xyconstraint);
+ ika->toty= axis[1];
+ CLAMP(ika->toty, -ika->xyconstraint, ika->xyconstraint);
+ }
+
+ euler_rot(ob->rot, ika->totx, 'x');
+ euler_rot(ob->rot, ika->toty, 'y');
+}
+
+void itterate_ika(Object *ob)
+{
+ Ika *ika;
+ Limb *li;
+ int it = 0;
+
+ ika= ob->data;
+ if((ika->flag & IK_GRABEFF)==0) return;
+
+ disable_where_script(1);
+ /* memory: grote tijdsprongen afvangen */
+ it= abs(ika->lastfra - G.scene->r.cfra);
+ ika->lastfra= G.scene->r.cfra;
+ if(it>10) {
+
+ /* one itteration extra */
+ itterate_ika(ob);
+ }
+ else {
+ li= ika->limbbase.first;
+ while(li) {
+ li->alpha= (1.0f-ika->mem)*li->alpha + ika->mem*li->alphao;
+ if(li->fac==1.0f) li->fac= 0.05f; /* oude files: kan weg in juni 96 */
+ li= li->next;
+ }
+ }
+ calc_ika(ika, 0);
+
+ /* effector heeft parent? */
+ if(ika->parent) {
+
+ if(ika->partype==PAROBJECT) {
+ if(ika->parent->ctime != (float) G.scene->r.cfra) where_is_object(ika->parent);
+ *(ika->effg)= *(ika->parent->obmat[3]);
+ *(ika->effg+1)= *(ika->parent->obmat[3]+1);
+ *(ika->effg+2)= *(ika->parent->obmat[3]+2);
+ }
+ else {
+ what_does_parent1(ika->parent, ika->partype, ika->par1, 0, 0);
+ *(ika->effg)= *(workob.obmat[3]);
+ *(ika->effg+1)= *(workob.obmat[3]+1);
+ *(ika->effg+2)= *(workob.obmat[3]+2);
+ }
+ }
+
+
+ /* y-as goed draaien */
+ if(ika->flag & IK_XYCONSTRAINT)
+ rotate_ika_xy(ob, ika);
+ else
+ rotate_ika(ob, ika);
+
+ it= ika->iter;
+ while(it--) {
+
+ where_is_object(ob);
+ Mat4Invert(ob->imat, ob->obmat);
+ VecMat4MulVecfl(ika->effn, ob->imat, ika->effg);
+ /* forward: dan gaan ook de eerste limbs */
+ li= ika->limbbase.first;
+ while(li) {
+
+ itterate_limb(ika, li);
+
+ /* zet je calc_ika() buiten deze lus: lange kettingen instabiel */
+ calc_ika(ika, li);
+
+ li= li->next;
+ }
+
+ where_is_object(ob);
+ Mat4Invert(ob->imat, ob->obmat);
+ VecMat4MulVecfl(ika->effn, ob->imat, ika->effg);
+
+ /* backward */
+ li= ika->limbbase.last;
+ while(li) {
+
+ itterate_limb(ika, li);
+
+ /* zet je calc_ika() buiten deze lus: lange kettingen instabiel */
+ calc_ika(ika, li);
+
+ li= li->prev;
+ }
+ }
+
+ disable_where_script(0);
+}
+
+
+void do_all_ikas()
+{
+ Base *base = 0;
+
+ base= G.scene->base.first;
+ while(base) {
+
+ if(base->object->type==OB_IKA) itterate_ika(base->object);
+
+ base= base->next;
+ }
+}
+
+void do_all_visible_ikas()
+{
+ Base *base = 0;
+
+ base= G.scene->base.first;
+ while(base) {
+ if(base->lay & G.scene->lay) {
+ if(base->object->type==OB_IKA) itterate_ika(base->object);
+ }
+ base= base->next;
+ }
+}
+
+/* ******************** DEFORM ************************ */
+
+
+void init_skel_deform(Object *par, Object *ob)
+{
+ Deform *def;
+ Ika *ika;
+ int a;
+
+ /* deform:
+ *
+ * ob_vec * ob_obmat * def_imat (weight fie) * def_obmat * ob_imat = ob_vec'
+ *
+ * <----- premat ----> <---- postmat ---->
+ */
+
+ if(par->type!=OB_IKA) return;
+
+ Mat4Invert(ob->imat, ob->obmat);
+
+ ika= par->data;
+ a= ika->totdef;
+ def= ika->def;
+ while(a--) {
+
+ what_does_parent1(def->ob, def->partype, def->par1, def->par2, def->par3);
+
+ Mat4MulMat4(def->premat, ob->obmat, def->imat);
+ Mat4MulMat4(def->postmat, workob.obmat, ob->imat);
+
+ def++;
+ }
+}
+
+
+void calc_skel_deform(Ika *ika, float *co)
+{
+ Deform *def;
+ int a;
+ float totw=0.0, weight, fac, len, vec[3], totvec[3];
+
+ def= ika->def;
+ if(def==0) return;
+ a= ika->totdef;
+ totvec[0]=totvec[1]=totvec[2]= 0.0;
+
+ while(a--) {
+
+ VecMat4MulVecfl(vec, def->premat, co);
+
+ len= (float)sqrt(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]);
+
+ if(def->vec[0]==0.0f) len= 2.0f*len;
+ else len= len + (float)sqrt( (vec[0]+def->vec[0])*(vec[0]+def->vec[0]) + vec[1]*vec[1] + vec[2]*vec[2]);
+
+ /* def->vec[0]= len limb */
+
+ weight= 1.0f/(0.001f+len);
+ weight*= weight;
+ weight*= weight;
+ weight*= def->fac;
+
+ len -= def->vec[0];
+
+ if(def->dist != 0.0) {
+ if(len >= def->dist) {
+ weight= 0.0;
+ }
+ else {
+ fac= (def->dist - len)/def->dist;
+ weight*= fac;
+ }
+ }
+ if(weight > 0.0) {
+ Mat4MulVecfl(def->postmat, vec);
+
+ VecMulf(vec, weight);
+ VecAddf(totvec, totvec, vec);
+
+ totw+= weight;
+ }
+ def++;
+ }
+
+ if(totw==0.0) return;
+
+ co[0]= totvec[0]/totw;
+ co[1]= totvec[1]/totw;
+ co[2]= totvec[2]/totw;
+
+}
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
new file mode 100644
index 00000000000..7e3e5eca3aa
--- /dev/null
+++ b/source/blender/blenkernel/intern/image.c
@@ -0,0 +1,1486 @@
+/* image.c MIX MODEL
+ *
+ * maart 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 <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <math.h>
+#ifndef WIN32
+#include <unistd.h>
+#else
+#include <io.h>
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "DNA_texture_types.h"
+#include "DNA_image_types.h"
+#include "DNA_packedFile_types.h"
+
+#include "BLI_blenlib.h"
+
+#include "BKE_bad_level_calls.h"
+#include "BKE_utildefines.h"
+
+#include "BKE_global.h"
+#include "BKE_main.h"
+
+#include "BKE_image.h"
+#include "BKE_bmfont.h"
+#include "BKE_screen.h"
+#include "BKE_texture.h"
+#include "BKE_packedFile.h"
+#include "BKE_library.h"
+
+void clipx_rctf_swap(rctf *stack, short *count, float x1, float x2);
+void clipy_rctf_swap(rctf *stack, short *count, float y1, float y2);
+float square_rctf(rctf *rf);
+float clipx_rctf(rctf *rf, float x1, float x2);
+float clipy_rctf(rctf *rf, float y1, float y2);
+void boxsample(struct ImBuf *ibuf,
+ float minx, float miny, float maxx, float maxy,
+ float *rcol, float *gcol, float *bcol, float *acol);
+void boxsampleclip(struct ImBuf *ibuf, rctf *rf, float *rcol,
+ float *gcol, float *bcol, float *acol);
+void filtersample(struct ImBuf *ibuf,
+ float fx, float fy,
+ float *rcol, float *gcol, float *bcol, float *acol);
+
+
+
+/* If defined: check arguments on call */
+/* #define IMAGE_C_ARG_CHECK */
+
+/* Communicate with texture channels. */
+extern float Tin, Tr, Tg, Tb, Ta;
+
+int Talpha;
+int imaprepeat, imapextend;
+
+
+/*
+ *
+ * Talpha==TRUE betekent: lees alpha uit plaatje. Dit betekent niet dat Ta
+ * niet gebruikt moet worden, hier kan info over rand van image in staan!
+ *
+ */
+
+void free_image_buffers(Image *ima)
+{
+ int a;
+
+ if(ima->ibuf) {
+ if (ima->ibuf->userdata) {
+ MEM_freeN(ima->ibuf->userdata);
+ ima->ibuf->userdata = 0;
+ }
+ IMB_freeImBuf(ima->ibuf);
+ ima->ibuf= 0;
+ }
+ if(ima->anim) IMB_free_anim(ima->anim);
+ ima->anim= 0;
+
+ for(a=0; a<BLI_ARRAY_NELEMS(ima->mipmap); a++) {
+ if(ima->mipmap[a]) IMB_freeImBuf(ima->mipmap[a]);
+ ima->mipmap[a]= 0;
+ }
+
+ free_realtime_image(ima);
+}
+
+
+void free_image(Image *ima)
+{
+
+ free_image_buffers(ima);
+ if (ima->packedfile) {
+ freePackedFile(ima->packedfile);
+ ima->packedfile = NULL;
+ }
+}
+
+
+Image *add_image(char *name)
+{
+ Image *ima;
+ int file, len;
+ char *libname, str[256], strtest[256];
+
+ strcpy(str, name);
+ BLI_convertstringcode(str, G.sce, G.scene->r.cfra);
+
+ file= open(str, O_BINARY|O_RDONLY);
+ if(file== -1) return 0;
+ close(file);
+
+ /* eerst zoeken naar eenzelfde ima */
+ ima= G.main->image.first;
+ while(ima) {
+ strcpy(strtest, ima->name);
+ BLI_convertstringcode(strtest, G.sce, G.scene->r.cfra);
+ if( strcmp(strtest, str)==0 ) {
+ if(ima->anim==0 || ima->id.us==0) {
+ strcpy(ima->name, name); /* for stringcode */
+ ima->id.us++;
+ ima->ok= 1;
+ return ima;
+ }
+ }
+ ima= ima->id.next;
+ }
+
+ len= strlen(name);
+
+ while (len > 0 && name[len - 1] != '/' && name[len - 1] != '\\') len--;
+ libname= name+len;
+
+ ima= alloc_libblock(&G.main->image, ID_IM, libname);
+ strcpy(ima->name, name);
+ ima->ok= 1;
+
+ ima->xrep= ima->yrep= 1;
+
+ return ima;
+}
+
+void free_unused_animimages()
+{
+ Image *ima, *nima;
+
+ ima= G.main->image.first;
+ while(ima) {
+ nima= ima->id.next;
+ if(ima->id.us==0) {
+ if(ima->flag & IMA_FROMANIM) free_libblock(&G.main->image, ima);
+ }
+ ima= nima;
+ }
+}
+
+
+/* *********** LEZEN EN SCHRIJVEN ************** */
+
+void makepicstring(char *string, int frame)
+{
+ short i,len;
+ char num[10], *extension;
+
+ if (string==0) return;
+
+ extension= "";
+
+ strcpy(string, G.scene->r.pic);
+ BLI_convertstringcode(string, G.sce, G.scene->r.cfra);
+
+ len= strlen(string);
+
+ /* kan ook: sprintf(num, "%04d", frame); */
+
+ i=4-sprintf(num,"%d",frame);
+ for(;i>0;i--){
+ string[len]='0';
+ len++;
+ }
+ string[len]=0;
+ strcat(string,num);
+
+ if(G.scene->r.imtype== R_IRIS) {
+ extension= ".rgb";
+ }
+ else if(G.scene->r.imtype==R_IRIZ) {
+ extension= ".rgb";
+ }
+ else if(G.scene->r.imtype==R_PNG) {
+ extension= ".png";
+ }
+ else if(G.scene->r.imtype==R_TARGA) {
+ extension= ".tga";
+ }
+ else if(G.scene->r.imtype==R_RAWTGA) {
+ extension= ".tga";
+ }
+ else if(G.scene->r.imtype==R_JPEG90) {
+ extension= ".jpg";
+ }
+
+ if(G.scene->r.scemode & R_EXTENSION) strcat(string, extension);
+
+}
+
+/* ******** IMAGWRAPPING INIT ************* */
+
+void converttopremul(struct ImBuf *ibuf)
+{
+ int x, y, val;
+ char *cp;
+
+ if(ibuf==0) return;
+ if(ibuf->depth==24) { /* alpha op 255 zetten */
+
+ cp= (char *)(ibuf->rect);
+ for(y=0; y<ibuf->y; y++) {
+ for(x=0; x<ibuf->x; x++, cp+=4) {
+ cp[3]= 255;
+ }
+ }
+ return;
+ }
+
+ cp= (char *)(ibuf->rect);
+ for(y=0; y<ibuf->y; y++) {
+ for(x=0; x<ibuf->x; x++, cp+=4) {
+ if(cp[3]==0) {
+ cp[0]= cp[1]= cp[2]= 0;
+ }
+ else if(cp[3]!=255) {
+ val= cp[3];
+ cp[0]= (cp[0]*val)>>8;
+ cp[1]= (cp[1]*val)>>8;
+ cp[2]= (cp[2]*val)>>8;
+ }
+ }
+ }
+}
+
+
+
+void makemipmap(Image *ima)
+{
+ struct ImBuf *ibuf;
+ int minsize, curmap=0;
+
+ ibuf= ima->ibuf;
+ minsize= MIN2(ibuf->x, ibuf->y);
+
+ while(minsize>3 && curmap<BLI_ARRAY_NELEMS(ima->mipmap)) {
+
+ ibuf= IMB_dupImBuf(ibuf);
+ IMB_filter(ibuf);
+ ima->mipmap[curmap]= (struct ImBuf *)IMB_onehalf(ibuf);
+ IMB_freeImBuf(ibuf);
+ ibuf= ima->mipmap[curmap];
+
+ curmap++;
+ minsize= MIN2(ibuf->x, ibuf->y);
+ }
+}
+
+struct anim *openanim(char * name, int flags)
+{
+ struct anim * anim;
+ struct ImBuf * ibuf;
+
+ anim = IMB_open_anim(name, flags);
+ if (anim == 0) return(0);
+
+
+ ibuf = IMB_anim_absolute(anim, 0);
+ if (ibuf == 0) {
+ printf("anim_absolute 0 failed\n");
+ IMB_free_anim(anim);
+ return(0);
+ }
+ IMB_freeImBuf(ibuf);
+
+ return(anim);
+}
+
+int calcimanr(int cfra, Tex *tex)
+{
+ int imanr, len, a, fra, dur;
+
+ /* hier (+fie_ima/2-1) zorgt ervoor dat correct wordt gedeeld */
+
+ if(tex->frames==0) return 1;
+
+ cfra= cfra-tex->sfra+1;
+
+ /* cyclic */
+ if(tex->len==0) len= (tex->fie_ima*tex->frames)/2;
+ else len= tex->len;
+
+ if(tex->imaflag & TEX_ANIMCYCLIC) {
+ cfra= ( (cfra) % len );
+ if(cfra < 0) cfra+= len;
+ if(cfra==0) cfra= len;
+ }
+
+ if(cfra<1) cfra= 1;
+ else if(cfra>len) cfra= len;
+
+ /* omzetten current frame naar current field */
+ cfra= 2*(cfra);
+ if(R.flag & R_SEC_FIELD) cfra++;
+
+
+ /* transformeren naar images space */
+ imanr= (cfra+tex->fie_ima-2)/tex->fie_ima;
+
+ if(imanr>tex->frames) imanr= tex->frames;
+ imanr+= tex->offset;
+
+ /* zijn er plaatjes die langer duren? */
+ for(a=0; a<4; a++) {
+ if(tex->fradur[a][0]) {
+
+ fra= tex->fradur[a][0];
+ dur= tex->fradur[a][1]-1;
+
+ while(dur>0 && imanr>fra) {
+ imanr--;
+ dur--;
+ }
+ }
+ }
+
+
+ return imanr;
+}
+
+void do_laseroptics_patch(ImBuf *ibuf)
+{
+ char *rt;
+ float fac;
+ int a, val;
+
+ rt= (char *)ibuf->rect;
+ a= ibuf->x*ibuf->y;
+
+ if(ibuf->flags & IB_fields) a+= a;
+
+ while(a--) {
+
+ fac= (rt[1]+rt[2]+rt[3])/765.0f;
+ val= (int)((255.0/0.8)*(fac-0.1));
+
+ if(val<0) val= 0; else if(val>255) val= 255;
+
+ rt[0]= rt[1]= rt[2]= rt[3]= val;
+
+ rt+= 4;
+ }
+}
+
+void de_interlace_ng(struct ImBuf *ibuf) /* neogeo fields */
+{
+ struct ImBuf * tbuf1, * tbuf2;
+
+ if (ibuf == 0) return;
+ if (ibuf->flags & IB_fields) return;
+ ibuf->flags |= IB_fields;
+
+ if (ibuf->rect) {
+ /* kopieen aanmaken */
+ tbuf1 = IMB_allocImBuf(ibuf->x, (short)(ibuf->y >> 1), (unsigned char)32, (int)IB_rect, (unsigned char)0);
+ tbuf2 = IMB_allocImBuf(ibuf->x, (short)(ibuf->y >> 1), (unsigned char)32, (int)IB_rect, (unsigned char)0);
+
+ ibuf->x *= 2;
+ /* These rectop calls are broken!!! I added a trailing 0 arg... */
+ IMB_rectop(tbuf1, ibuf, 0, 0, 0, 0, 32767, 32767, IMB_rectcpy, 0);
+ IMB_rectop(tbuf2, ibuf, 0, 0, tbuf2->x, 0, 32767, 32767, IMB_rectcpy, 0);
+
+ ibuf->x /= 2;
+ IMB_rectop(ibuf, tbuf1, 0, 0, 0, 0, 32767, 32767, IMB_rectcpy, 0);
+ IMB_rectop(ibuf, tbuf2, 0, tbuf2->y, 0, 0, 32767, 32767, IMB_rectcpy, 0);
+
+ IMB_freeImBuf(tbuf1);
+ IMB_freeImBuf(tbuf2);
+ }
+ ibuf->y /= 2;
+}
+
+void de_interlace_st(struct ImBuf *ibuf) /* standard fields */
+{
+ struct ImBuf * tbuf1, * tbuf2;
+
+ if (ibuf == 0) return;
+ if (ibuf->flags & IB_fields) return;
+ ibuf->flags |= IB_fields;
+
+ if (ibuf->rect) {
+ /* kopieen aanmaken */
+ tbuf1 = IMB_allocImBuf(ibuf->x, (short)(ibuf->y >> 1), (unsigned char)32, IB_rect, 0);
+ tbuf2 = IMB_allocImBuf(ibuf->x, (short)(ibuf->y >> 1), (unsigned char)32, IB_rect, 0);
+
+ ibuf->x *= 2;
+ /* These are brolenm as well... */
+ IMB_rectop(tbuf1, ibuf, 0, 0, 0, 0, 32767, 32767, IMB_rectcpy, 0);
+ IMB_rectop(tbuf2, ibuf, 0, 0, tbuf2->x, 0, 32767, 32767, IMB_rectcpy, 0);
+
+ ibuf->x /= 2;
+ IMB_rectop(ibuf, tbuf2, 0, 0, 0, 0, 32767, 32767, IMB_rectcpy, 0);
+ IMB_rectop(ibuf, tbuf1, 0, tbuf2->y, 0, 0, 32767, 32767, IMB_rectcpy, 0);
+
+ IMB_freeImBuf(tbuf1);
+ IMB_freeImBuf(tbuf2);
+ }
+ ibuf->y /= 2;
+}
+
+/*
+load_image handles reading the image from disk or from the packedfile.
+*/
+
+void load_image(Image * ima, int flags, char *relabase, int framenum)
+{
+ char name[FILE_MAXDIR + FILE_MAXFILE];
+
+ if (ima->ibuf == NULL) {
+
+ // is there a PackedFile with this image ?;
+ if (ima->packedfile) {
+ ima->ibuf = IMB_ibImageFromMemory((int *) ima->packedfile->data, ima->packedfile->size, flags);
+ } else {
+ strcpy(name, ima->name);
+ BLI_convertstringcode(name, relabase, framenum);
+
+ ima->ibuf = IMB_loadiffname(name , flags);
+ }
+ // check if the image is a font image...
+ // printf("Checking for font\n");
+
+ if (ima->ibuf) {
+ detectBitmapFont(ima->ibuf);
+ }
+ }
+}
+
+void ima_ibuf_is_nul(Tex *tex)
+{
+ void (*de_interlacefunc)(struct ImBuf *ibuf);
+ Image *ima;
+ int a, fra;
+ char str[FILE_MAXDIR+FILE_MAXFILE], *cp;
+
+ ima= tex->ima;
+ if(ima==0) return;
+
+ waitcursor(1);
+
+ strcpy(str, ima->name);
+ BLI_convertstringcode(str, G.sce, G.scene->r.cfra);
+
+ if(tex->imaflag & TEX_STD_FIELD) de_interlacefunc= de_interlace_st;
+ else de_interlacefunc= de_interlace_ng;
+
+ if(tex->imaflag & TEX_ANIM5) {
+
+ if(ima->anim==0) ima->anim = openanim(str, IB_cmap | IB_rect);
+ if (ima->anim) {
+
+ ima->lastquality= R.osa;
+ fra= ima->lastframe-1;
+ if(fra<0) fra= 0;
+ ima->ibuf = IMB_anim_absolute(ima->anim, fra);
+
+ /* patch ivm textbutton met naam ima (B_NAMEIMA) */
+ if(ima->ibuf) {
+ strcpy(ima->ibuf->name, ima->name);
+ if (tex->imaflag & TEX_FIELDS) de_interlacefunc(ima->ibuf);
+ }
+ }
+ else error("Not an anim");
+
+ } else {
+ // create a packedfile for this image when autopack is on
+ // for performance (IMB_loadiffname uses mmap) we don't do this by default
+ if ((ima->packedfile == NULL) && (G.fileflags & G_AUTOPACK)) {
+ ima->packedfile = newPackedFile(str);
+ }
+
+ load_image(ima, IB_rect, G.sce, G.scene->r.cfra);
+
+ if (tex->imaflag & TEX_FIELDS) de_interlacefunc(ima->ibuf);
+
+ ima->lastquality= R.osa;
+ }
+
+ if(ima->ibuf) {
+
+ /* stringcodes ook in ibuf. ibuf->name wordt als 'undo' gebruikt (buttons.c) */
+ strcpy(ima->ibuf->name, ima->name);
+
+ if(ima->ibuf->cmap) {
+
+ if(tex->imaflag & TEX_ANIM5) {
+
+ if(tex->imaflag & TEX_MORKPATCH) {
+ /**** PATCH OM KLEUR 2 GOED TE KUNNEN ZETTEN MORKRAMIA */
+ if(ima->ibuf->maxcol > 4) {
+ cp= (char *)(ima->ibuf->cmap+2);
+ cp[0]= 0x80;
+ }
+ }
+
+ IMB_applycmap(ima->ibuf);
+ IMB_convert_rgba_to_abgr(ima->ibuf->x*ima->ibuf->y, ima->ibuf->rect);
+
+ }
+
+ converttopremul(ima->ibuf);
+ }
+
+ if(R.osa) {
+
+ if(tex->imaflag & TEX_ANTISCALE) {
+ IMB_clever_double(ima->ibuf);
+ IMB_antialias(ima->ibuf);
+ }
+ else if(tex->imaflag & TEX_ANTIALI) IMB_antialias(ima->ibuf);
+ }
+
+ if(tex->imaflag & TEX_LASOPPATCH) {
+ do_laseroptics_patch(ima->ibuf);
+ }
+
+ }
+
+ if(ima->ibuf==0) ima->ok= 0;
+
+ for(a=0; a<BLI_ARRAY_NELEMS(ima->mipmap); a++) {
+ if(ima->mipmap[a]) IMB_freeImBuf(ima->mipmap[a]);
+ ima->mipmap[a]= 0;
+ }
+
+ if((R.flag & R_RENDERING)==0) waitcursor(0);
+
+}
+
+
+
+/* *********** IMAGEWRAPPING ****************** */
+
+
+int imagewrap(Tex *tex, float *texvec)
+{
+ Image *ima;
+ struct ImBuf *ibuf;
+ float fx, fy, val1, val2, val3;
+ int ofs, x, y;
+ char *rect;
+
+ ima= tex->ima;
+
+ if(ima==0 || ima->ok== 0) {
+ Tin= Ta= Tr= Tg= Tb= 0.0;
+ return 0;
+ }
+
+ if(ima->ibuf==0) ima_ibuf_is_nul(tex);
+
+ if (ima->ok) {
+
+ ibuf = ima->ibuf;
+
+ if( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) {
+ ibuf->rect+= (ibuf->x*ibuf->y);
+ }
+
+ if(tex->imaflag & TEX_IMAROT) {
+ fy= texvec[0];
+ fx= texvec[1];
+ }
+ else {
+ fx= texvec[0];
+ fy= texvec[1];
+ }
+
+ x = (int)(fx*ibuf->x);
+ y = (int)(fy*ibuf->y);
+
+ if(tex->extend == TEX_CLIPCUBE) {
+ if(x<0 || y<0 || x>=ibuf->x || y>=ibuf->y || texvec[2]<-1.0 || texvec[2]>1.0) {
+ Tin= 0;
+ return 0;
+ }
+ }
+ else if(tex->extend == TEX_CLIP) {
+ if(x<0 || y<0 || x>=ibuf->x || y>=ibuf->y) {
+ Tin= 0;
+ return 0;
+ }
+ }
+ else {
+ if(tex->extend==TEX_EXTEND) {
+ if(x>=ibuf->x) x = ibuf->x-1;
+ else if(x<0) x= 0;
+ }
+ else {
+ x= x % ibuf->x;
+ if(x<0) x+= ibuf->x;
+ }
+ if(tex->extend==TEX_EXTEND) {
+ if(y>=ibuf->y) y = ibuf->y-1;
+ else if(y<0) y= 0;
+ }
+ else {
+ y= y % ibuf->y;
+ if(y<0) y+= ibuf->y;
+ }
+ }
+
+ ofs = y * ibuf->x + x;
+ rect = (char *)( ibuf->rect+ ofs);
+
+ Talpha= 0;
+ if(tex->imaflag & TEX_USEALPHA) {
+ if(tex->imaflag & TEX_CALCALPHA);
+ else Talpha= 1;
+ }
+
+ Tr = ((float)rect[0])/255.0f;
+ Tg = ((float)rect[1])/255.0f;
+ Tb = ((float)rect[2])/255.0f;
+
+ if(tex->nor) {
+ /* bump: drie samples nemen */
+ val1= Tr+Tg+Tb;
+
+ if(x<ibuf->x-1) {
+ rect+=4;
+ val2= ((float)(rect[0]+rect[1]+rect[2]))/255.0f;
+ rect-=4;
+ }
+ else val2= val1;
+
+ if(y<ibuf->y-1) {
+ rect+= 4*ibuf->x;
+ val3= ((float)(rect[0]+rect[1]+rect[2]))/255.0f;
+ }
+ else val3= val1;
+
+ /* niet x en y verwisselen! */
+ tex->nor[0]= (val1-val2);
+ tex->nor[1]= (val1-val3);
+ }
+
+ BRICONRGB;
+
+ if(Talpha) Ta= Tin= ((float)rect[3])/255.0f;
+ else if(tex->imaflag & TEX_CALCALPHA) {
+ Ta= Tin= MAX3(Tr, Tg, Tb);
+ }
+ else Ta= Tin= 1.0;
+
+ if(tex->flag & TEX_NEGALPHA) Ta= 1.0f-Ta;
+
+ if( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) {
+ ibuf->rect-= (ibuf->x*ibuf->y);
+ }
+ }
+
+ if(tex->flag & TEX_COLORBAND) do_colorband(tex->coba);
+
+ if(tex->nor) return 3;
+ else return 1;
+}
+
+void clipx_rctf_swap(rctf *stack, short *count, float x1, float x2)
+/* rctf *stack; */
+/* short *count; */
+/* float x1, x2; */
+{
+ rctf *rf, *newrct;
+ short a;
+
+ a= *count;
+ rf= stack;
+ for(;a>0;a--) {
+ if(rf->xmin<x1) {
+ if(rf->xmax<x1) {
+ rf->xmin+= (x2-x1);
+ rf->xmax+= (x2-x1);
+ }
+ else {
+ if(rf->xmax>x2) rf->xmax= x2;
+ newrct= stack+ *count;
+ (*count)++;
+
+ newrct->xmax= x2;
+ newrct->xmin= rf->xmin+(x2-x1);
+ newrct->ymin= rf->ymin;
+ newrct->ymax= rf->ymax;
+
+ if(newrct->xmin==newrct->xmax) (*count)--;
+
+ rf->xmin= x1;
+ }
+ }
+ else if(rf->xmax>x2) {
+ if(rf->xmin>x2) {
+ rf->xmin-= (x2-x1);
+ rf->xmax-= (x2-x1);
+ }
+ else {
+ if(rf->xmin<x1) rf->xmin= x1;
+ newrct= stack+ *count;
+ (*count)++;
+
+ newrct->xmin= x1;
+ newrct->xmax= rf->xmax-(x2-x1);
+ newrct->ymin= rf->ymin;
+ newrct->ymax= rf->ymax;
+
+ if(newrct->xmin==newrct->xmax) (*count)--;
+
+ rf->xmax= x2;
+ }
+ }
+ rf++;
+ }
+
+}
+
+void clipy_rctf_swap(rctf *stack, short *count, float y1, float y2)
+/* rctf *stack; */
+/* short *count; */
+/* float y1, y2; */
+{
+ rctf *rf, *newrct;
+ short a;
+
+ a= *count;
+ rf= stack;
+ for(;a>0;a--) {
+ if(rf->ymin<y1) {
+ if(rf->ymax<y1) {
+ rf->ymin+= (y2-y1);
+ rf->ymax+= (y2-y1);
+ }
+ else {
+ if(rf->ymax>y2) rf->ymax= y2;
+ newrct= stack+ *count;
+ (*count)++;
+
+ newrct->ymax= y2;
+ newrct->ymin= rf->ymin+(y2-y1);
+ newrct->xmin= rf->xmin;
+ newrct->xmax= rf->xmax;
+
+ if(newrct->ymin==newrct->ymax) (*count)--;
+
+ rf->ymin= y1;
+ }
+ }
+ else if(rf->ymax>y2) {
+ if(rf->ymin>y2) {
+ rf->ymin-= (y2-y1);
+ rf->ymax-= (y2-y1);
+ }
+ else {
+ if(rf->ymin<y1) rf->ymin= y1;
+ newrct= stack+ *count;
+ (*count)++;
+
+ newrct->ymin= y1;
+ newrct->ymax= rf->ymax-(y2-y1);
+ newrct->xmin= rf->xmin;
+ newrct->xmax= rf->xmax;
+
+ if(newrct->ymin==newrct->ymax) (*count)--;
+
+ rf->ymax= y2;
+ }
+ }
+ rf++;
+ }
+
+}
+
+
+
+float square_rctf(rctf *rf)
+/* rctf *rf; */
+{
+ float x, y;
+
+ x= rf->xmax- rf->xmin;
+ y= rf->ymax- rf->ymin;
+ return (x*y);
+}
+
+float clipx_rctf(rctf *rf, float x1, float x2)
+/* rctf *rf; */
+/* float x1, x2; */
+{
+ float size;
+
+ size= rf->xmax - rf->xmin;
+
+ if(rf->xmin<x1) {
+ rf->xmin= x1;
+ }
+ if(rf->xmax>x2) {
+ rf->xmax= x2;
+ }
+ if(rf->xmin > rf->xmax) {
+ rf->xmin = rf->xmax;
+ return 0.0;
+ }
+ else if(size!=0.0) {
+ return (rf->xmax - rf->xmin)/size;
+ }
+ return 1.0;
+}
+
+float clipy_rctf(rctf *rf, float y1, float y2)
+/* rctf *rf; */
+/* float y1, y2; */
+{
+ float size;
+
+ size= rf->ymax - rf->ymin;
+/* PRINT(f, size); */
+ if(rf->ymin<y1) {
+ rf->ymin= y1;
+ }
+ if(rf->ymax>y2) {
+ rf->ymax= y2;
+ }
+/* PRINT(f, size); */
+ if(rf->ymin > rf->ymax) {
+ rf->ymin = rf->ymax;
+ return 0.0;
+ }
+ else if(size!=0.0) {
+ return (rf->ymax - rf->ymin)/size;
+ }
+ return 1.0;
+
+}
+
+void boxsampleclip(struct ImBuf *ibuf, rctf *rf, float *rcol,
+ float *gcol, float *bcol, float *acol) /* return kleur 0.0-1.0 */
+/* struct ImBuf *ibuf; */
+/* rctf *rf; */
+/* float *rcol, *gcol, *bcol, *acol; */
+{
+ /* sample box, is reeds geclipt en minx enz zijn op ibuf size gezet.
+ * Vergroot uit met antialiased edges van de pixels */
+
+ float muly,mulx,div;
+ int ofs;
+ int x, y, startx, endx, starty, endy;
+ char *rect;
+
+ startx= (int)floor(rf->xmin);
+ endx= (int)floor(rf->xmax);
+ starty= (int)floor(rf->ymin);
+ endy= (int)floor(rf->ymax);
+
+ if(startx < 0) startx= 0;
+ if(starty < 0) starty= 0;
+ if(endx>=ibuf->x) endx= ibuf->x-1;
+ if(endy>=ibuf->y) endy= ibuf->y-1;
+
+ if(starty==endy && startx==endx) {
+
+ ofs = starty*ibuf->x + startx;
+ rect = (char *)(ibuf->rect +ofs);
+ *rcol= ((float)rect[0])/255.0f;
+ *gcol= ((float)rect[1])/255.0f;
+ *bcol= ((float)rect[2])/255.0f;
+ /* alpha is globaal, reeds gezet in functie imagewraposa() */
+ if(Talpha) {
+ *acol= ((float)rect[3])/255.0f;
+ }
+ }
+ else {
+ div= *rcol= *gcol= *bcol= *acol= 0.0;
+ for(y=starty;y<=endy;y++) {
+ ofs = y*ibuf->x +startx;
+ rect = (char *)(ibuf->rect+ofs);
+
+ muly= 1.0;
+
+ if(starty==endy);
+ else {
+ if(y==starty) muly= 1.0f-(rf->ymin - y);
+ if(y==endy) muly= (rf->ymax - y);
+ }
+ if(startx==endx) {
+ mulx= muly;
+ if(Talpha) *acol+= mulx*rect[3];
+ *rcol+= mulx*rect[0];
+ *gcol+= mulx*rect[1];
+ *bcol+= mulx*rect[2];
+ div+= mulx;
+ }
+ else {
+ for(x=startx;x<=endx;x++) {
+ mulx= muly;
+ if(x==startx) mulx*= 1.0f-(rf->xmin - x);
+ if(x==endx) mulx*= (rf->xmax - x);
+
+ if(mulx==1.0) {
+ if(Talpha) *acol+= rect[3];
+ *rcol+= rect[0];
+ *gcol+= rect[1];
+ *bcol+= rect[2];
+ div+= 1.0;
+ }
+ else {
+ if(Talpha) *acol+= mulx*rect[3];
+ *rcol+= mulx*rect[0];
+ *gcol+= mulx*rect[1];
+ *bcol+= mulx*rect[2];
+ div+= mulx;
+ }
+ rect+=4;
+ }
+ }
+ }
+ if(div!=0.0) {
+ div*= 255.0;
+
+ *bcol/= div;
+ *gcol/= div;
+ *rcol/= div;
+
+ if(Talpha) *acol/= div;
+ }
+ else {
+ *rcol= *gcol= *bcol= *acol= 0.0;
+ }
+ }
+}
+
+void boxsample(struct ImBuf *ibuf,
+ float minx, float miny, float maxx, float maxy,
+ float *rcol, float *gcol, float *bcol, float *acol) /* return kleur 0.0-1.0 */
+/* struct ImBuf *ibuf; */
+/* float minx, miny, maxx, maxy; */
+/* float *rcol, *gcol, *bcol, *acol; */
+{
+ /* Sample box, doet clip. minx enz lopen van 0.0 - 1.0 .
+ * Vergroot uit met antialiased edges van de pixels.
+ * Als global imaprepeat is gezet, worden
+ * de weggeclipte stukken ook gesampled.
+ */
+ rctf *rf, stack[8];
+ float opp, tot, r, g, b, a, alphaclip= 1.0;
+ short count=1;
+
+ rf= stack;
+ rf->xmin= minx*(ibuf->x);
+ rf->xmax= maxx*(ibuf->x);
+ rf->ymin= miny*(ibuf->y);
+ rf->ymax= maxy*(ibuf->y);
+
+ if(imapextend);
+ else if(imaprepeat) clipx_rctf_swap(stack, &count, 0.0, (float)(ibuf->x));
+ else {
+ alphaclip= clipx_rctf(rf, 0.0, (float)(ibuf->x));
+
+ if(alphaclip<=0.0) {
+ *rcol= *bcol= *gcol= *acol= 0.0;
+ return;
+ }
+ }
+
+ if(imapextend);
+ else if(imaprepeat) clipy_rctf_swap(stack, &count, 0.0, (float)(ibuf->y));
+ else {
+ alphaclip*= clipy_rctf(rf, 0.0, (float)(ibuf->y));
+
+ if(alphaclip<=0.0) {
+ *rcol= *bcol= *gcol= *acol= 0.0;
+ return;
+ }
+ }
+
+ if(count>1) {
+ tot= *rcol= *bcol= *gcol= *acol= 0.0;
+ while(count--) {
+ boxsampleclip(ibuf, rf, &r, &g, &b, &a);
+
+ opp= square_rctf(rf);
+ tot+= opp;
+
+ *rcol+= opp*r;
+ *gcol+= opp*g;
+ *bcol+= opp*b;
+ if(Talpha) *acol+= opp*a;
+ rf++;
+ }
+ if(tot!= 0.0) {
+ *rcol/= tot;
+ *gcol/= tot;
+ *bcol/= tot;
+ if(Talpha) *acol/= tot;
+ }
+ }
+ else {
+ boxsampleclip(ibuf, rf, rcol, gcol, bcol, acol);
+ }
+
+ if(Talpha==0) *acol= 1.0;
+
+ if(alphaclip!=1.0) {
+ /* this is for laer investigation, premul or not? */
+ /* *rcol*= alphaclip; */
+ /* *gcol*= alphaclip; */
+ /* *bcol*= alphaclip; */
+ *acol*= alphaclip;
+ }
+}
+
+void filtersample(struct ImBuf *ibuf,
+ float fx, float fy,
+ float *rcol, float *gcol, float *bcol, float *acol)
+ /* return kleur 0.0-1.0 */
+/* struct ImBuf *ibuf; */ /* fx en fy tussen 0.0 en 1.0 */
+/* float fx, fy; */
+/* float *rcol, *gcol, *bcol, *acol; */
+{
+ /* met weighted filter 3x3
+ * de linker of rechter kolom is altijd 0
+ * en de bovenste of onderste rij is altijd 0
+ */
+
+ int fac, fac1, fac2, fracx, fracy, filt[4];
+ int ix, iy, x4;
+ unsigned int r=0, g=0, b=0, a=0;
+ char *rowcol, *rfilt[4];
+
+ ix= (int)( 256.0*fx );
+ fracx= (ix & 255);
+ ix= (ix>>8);
+ iy= (int)( 256.0*fy );
+ fracy= (iy & 255);
+ iy= (iy>>8);
+
+ if(ix>=ibuf->x) ix= ibuf->x-1;
+ if(iy>=ibuf->y) iy= ibuf->y-1;
+
+ rowcol= (char *)(ibuf->rect+ iy*ibuf->x +ix);
+
+ rfilt[0]= rfilt[1]= rfilt[2]= rfilt[3]= rowcol;
+ x4= 4*ibuf->x;
+
+ if(fracx<128) {
+ if(ix>0) {
+ rfilt[0]-= 4;
+ rfilt[2]-=4;
+ }
+ else if(imaprepeat) {
+ rfilt[0]+= x4-4;
+ rfilt[2]+= x4-4;
+ }
+
+ if(fracy<128) {
+ /* geval linksonder */
+ fac1= 128+fracy;
+ fac2= 128-fracy;
+
+ if(iy>0) {
+ rfilt[3]-= x4;
+ rfilt[2]-= x4;
+ }
+ else if(imaprepeat) {
+ fac= x4*(ibuf->y-1) ;
+ rfilt[3]+= fac;
+ rfilt[2]+= fac;
+ }
+ }
+ else {
+ /* geval linksboven */
+ fac2= 384-fracy;
+ fac1= fracy-128;
+
+ if(iy<ibuf->y-1) {
+ rfilt[1]+= x4;
+ rfilt[0]+= x4;
+ }
+ else if(imaprepeat) {
+ fac= x4*(ibuf->y-1) ;
+ rfilt[1]-= fac;
+ rfilt[0]-= fac;
+ }
+ }
+
+ filt[1]=filt[3]= 128+ fracx;
+ filt[0]=filt[2]= 128- fracx;
+ filt[0]*= fac1;
+ filt[1]*= fac1;
+ filt[2]*= fac2;
+ filt[3]*= fac2;
+ }
+ else {
+ if(fracy<128) {
+ /* geval rechtsonder */
+ fac1= 128+fracy;
+ fac2= 128-fracy;
+
+ if(iy>0) {
+ rfilt[3]-= x4;
+ rfilt[2]-= x4;
+ }
+ else if(imaprepeat) {
+ fac= x4*(ibuf->y-1) ;
+ rfilt[3]+= fac;
+ rfilt[2]+= fac;
+ }
+ }
+ else {
+ /* geval rechtsboven */
+ fac2= 384-fracy;
+ fac1= fracy-128;
+
+ if(iy<ibuf->y-1) {
+ rfilt[1]+= x4;
+ rfilt[0]+= x4;
+ }
+ else if(imaprepeat) {
+ fac= x4*(ibuf->y-1) ;
+ rfilt[1]-= fac;
+ rfilt[0]-= fac;
+ }
+ }
+ filt[0]=filt[2]= 384-fracx;
+ filt[1]=filt[3]= fracx-128;
+ filt[0]*= fac1;
+ filt[1]*= fac1;
+ filt[2]*= fac2;
+ filt[3]*= fac2;
+
+ if(ix<ibuf->x-1) {
+ rfilt[1]+= 4;
+ rfilt[3]+=4;
+ }
+ else if(imaprepeat) {
+ rfilt[1]-= x4-4;
+ rfilt[3]-= x4-4;
+ }
+ }
+
+ for(fac=3; fac>=0; fac--) {
+ rowcol= rfilt[fac];
+ r+= filt[fac]*rowcol[0];
+ g+= filt[fac]*rowcol[1];
+ b+= filt[fac]*rowcol[2];
+ if(Talpha) a+= filt[fac]*rowcol[3]; /* alpha is globaal */
+ }
+ *rcol= ((float)r)/16777216.0f;
+ *gcol= ((float)g)/16777216.0f;
+ *bcol= ((float)b)/16777216.0f;
+ if(Talpha) *acol= ((float)a)/16777216.0f;
+
+}
+
+
+int imagewraposa(Tex *tex, float *texvec, float *dxt, float *dyt)
+{
+ struct Image *ima;
+ struct ImBuf *ibuf, *previbuf;
+ float fx, fy, minx, maxx, miny, maxy, dx, dy, fac1, fac2, fac3, fac4;
+ float maxd, pixsize, val1, val2, val3;
+ int curmap;
+
+#ifdef IMAGE_C_ARG_CHECK
+ if (!tex) {
+ printf("imagewraposa: null pointer to texture\n");
+ }
+#endif
+
+ ima= tex->ima;
+#ifdef IMAGE_C_ARG_CHECK
+ if (!ima) {
+ printf("imagewraposa: null pointer to image\n");
+ }
+#endif
+
+ Tin= Ta= Tr= Tg= Tb= 0.0;
+
+ if(ima==0 || ima->ok== 0) {
+ return 0;
+ }
+
+ if(ima->ibuf==0) ima_ibuf_is_nul(tex);
+
+ if (ima->ok) {
+
+ if(tex->imaflag & TEX_MIPMAP) {
+ if(ima->mipmap[0]==0) makemipmap(ima);
+ }
+
+ ibuf = ima->ibuf;
+
+ if( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) {
+ ibuf->rect+= (ibuf->x*ibuf->y);
+ }
+
+ Talpha= 0;
+ if(tex->imaflag & TEX_USEALPHA) {
+ if(tex->imaflag & TEX_CALCALPHA);
+ else Talpha= 1;
+ }
+
+ if(tex->imaflag & TEX_IMAROT) {
+ fy= texvec[0];
+ fx= texvec[1];
+ }
+ else {
+ fx= texvec[0];
+ fy= texvec[1];
+ }
+
+
+ if(ibuf->flags & IB_fields) {
+ if(R.r.mode & R_FIELDS) { /* field render */
+ if(R.flag & R_SEC_FIELD) { /* correctie voor tweede field */
+ /* fac1= 0.5/( (float)ibuf->y ); */
+ /* fy-= fac1; */
+ }
+ else { /* eerste field */
+ fac1= 0.5f/( (float)ibuf->y );
+ fy+= fac1;
+ }
+ }
+ }
+
+ /* pixel coordinaten */
+
+ minx= MIN3(dxt[0],dyt[0],dxt[0]+dyt[0] );
+ maxx= MAX3(dxt[0],dyt[0],dxt[0]+dyt[0] );
+ miny= MIN3(dxt[1],dyt[1],dxt[1]+dyt[1] );
+ maxy= MAX3(dxt[1],dyt[1],dxt[1]+dyt[1] );
+
+ /* tex_sharper afgeschaft */
+
+ minx= tex->filtersize*(maxx-minx)/2.0f;
+ miny= tex->filtersize*(maxy-miny)/2.0f;
+
+ if(tex->imaflag & TEX_IMAROT) SWAP(float, minx, miny);
+
+ if(minx>0.25) minx= 0.25;
+ else if(minx<0.00001f) minx= 0.00001f; /* zijvlakken van eenheidskubus */
+ if(miny>0.25) miny= 0.25;
+ else if(miny<0.00001f) miny= 0.00001f;
+
+
+ /* repeat en clip */
+
+ /* let op: imaprepeat is globale waarde (zie boxsample) */
+ imaprepeat= (tex->extend==TEX_REPEAT);
+ imapextend= (tex->extend==TEX_EXTEND);
+
+
+ if(tex->extend == TEX_CLIPCUBE) {
+ if(fx+minx<0.0 || fy+miny<0.0 || fx-minx>1.0 || fy-miny>1.0 || texvec[2]<-1.0 || texvec[2]>1.0) {
+ Tin= 0;
+ return 0;
+ }
+ }
+ else if(tex->extend == TEX_CLIP) {
+ if(fx+minx<0.0 || fy+miny<0.0 || fx-minx>1.0 || fy-miny>1.0) {
+ Tin= 0.0;
+ return 0;
+ }
+ }
+ else {
+ if(tex->extend==TEX_EXTEND) {
+ if(fx>1.0) fx = 1.0;
+ else if(fx<0.0) fx= 0.0;
+ }
+ else {
+ if(fx>1.0) fx -= (int)(fx);
+ else if(fx<0.0) fx+= 1-(int)(fx);
+ }
+
+ if(tex->extend==TEX_EXTEND) {
+ if(fy>1.0) fy = 1.0;
+ else if(fy<0.0) fy= 0.0;
+ }
+ else {
+ if(fy>1.0) fy -= (int)(fy);
+ else if(fy<0.0) fy+= 1-(int)(fy);
+ }
+ }
+
+ /* keuze: */
+ if(tex->imaflag & TEX_MIPMAP) {
+
+ dx= minx;
+ dy= miny;
+ maxd= MAX2(dx, dy);
+ if(maxd>0.5) maxd= 0.5;
+
+ pixsize = 1.0f/ (float) MIN2(ibuf->x, ibuf->y);
+
+ curmap= 0;
+ previbuf= ibuf;
+ while(curmap<BLI_ARRAY_NELEMS(ima->mipmap) && ima->mipmap[curmap]) {
+ if(maxd < pixsize) break;
+ previbuf= ibuf;
+ ibuf= ima->mipmap[curmap];
+ pixsize= 1.0f / (float)MIN2(ibuf->x, ibuf->y); /* hier stond 1.0 */
+ curmap++;
+ }
+
+ if(previbuf!=ibuf || (tex->imaflag & TEX_INTERPOL)) {
+ /* minmaal 1 pixel sampelen */
+ if (minx < 0.5f / ima->ibuf->x) minx = 0.5f / ima->ibuf->x;
+ if (miny < 0.5f / ima->ibuf->y) miny = 0.5f / ima->ibuf->y;
+ }
+
+ if(tex->nor) {
+ /* beetje extra filter */
+ minx*= 1.35f;
+ miny*= 1.35f;
+
+ boxsample(ibuf, fx-2.0f*minx, fy-2.0f*miny, fx+minx, fy+miny, &Tr, &Tg, &Tb, &Ta);
+ val1= Tr+Tg+Tb;
+ boxsample(ibuf, fx-minx, fy-2.0f*miny, fx+2.0f*minx, fy+miny, &fac1, &fac2, &fac3, &fac4);
+ val2= fac1+fac2+fac3;
+ boxsample(ibuf, fx-2.0f*minx, fy-miny, fx+minx, fy+2.0f*miny, &fac1, &fac2, &fac3, &fac4);
+ val3= fac1+fac2+fac3;
+
+ if(previbuf!=ibuf) { /* interpoleren */
+
+ boxsample(previbuf, fx-2.0f*minx, fy-2.0f*miny, fx+minx, fy+miny, &fac1, &fac2, &fac3, &fac4);
+
+ /* rgb berekenen */
+ dx= 2.0f*(pixsize-maxd)/pixsize;
+ if(dx>=1.0f) {
+ Ta= fac4; Tb= fac3;
+ Tg= fac2; Tr= fac1;
+ }
+ else {
+ dy= 1.0f-dx;
+ Tb= dy*Tb+ dx*fac3;
+ Tg= dy*Tg+ dx*fac2;
+ Tr= dy*Tr+ dx*fac1;
+ if(Talpha) Ta= dy*Ta+ dx*fac4;
+ }
+
+ val1= dy*val1+ dx*(fac1+fac2+fac3);
+ boxsample(previbuf, fx-minx, fy-2.0f*miny, fx+2.0f*minx, fy+miny, &fac1, &fac2, &fac3, &fac4);
+ val2= dy*val2+ dx*(fac1+fac2+fac3);
+ boxsample(previbuf, fx-2.0f*minx, fy-miny, fx+minx, fy+2.0f*miny, &fac1, &fac2, &fac3, &fac4);
+ val3= dy*val3+ dx*(fac1+fac2+fac3);
+ }
+
+ /* niet x en y verwisselen! */
+ tex->nor[0]= (val1-val2);
+ tex->nor[1]= (val1-val3);
+
+ }
+ else {
+ maxx= fx+minx;
+ minx= fx-minx;
+ maxy= fy+miny;
+ miny= fy-miny;
+
+ boxsample(ibuf, minx, miny, maxx, maxy, &Tr, &Tg, &Tb, &Ta);
+
+ if(previbuf!=ibuf) { /* interpoleren */
+ boxsample(previbuf, minx, miny, maxx, maxy, &fac1, &fac2, &fac3, &fac4);
+
+ fx= 2.0f*(pixsize-maxd)/pixsize;
+
+ if(fx>=1.0) {
+ Ta= fac4; Tb= fac3;
+ Tg= fac2; Tr= fac1;
+ } else {
+ fy= 1.0f-fx;
+ Tb= fy*Tb+ fx*fac3;
+ Tg= fy*Tg+ fx*fac2;
+ Tr= fy*Tr+ fx*fac1;
+ if(Talpha) Ta= fy*Ta+ fx*fac4;
+ }
+ }
+ }
+ }
+ else {
+ if((tex->imaflag & TEX_INTERPOL)) {
+ /* minmaal 1 pixel sampelen */
+ if (minx < 0.5f / ima->ibuf->x) minx = 0.5f / ima->ibuf->x;
+ if (miny < 0.5f / ima->ibuf->y) miny = 0.5f / ima->ibuf->y;
+ }
+
+ if(tex->nor) {
+
+ /* beetje extra filter */
+ minx*= 1.35f;
+ miny*= 1.35f;
+
+ boxsample(ibuf, fx-2.0f*minx, fy-2.0f*miny, fx+minx, fy+miny, &Tr, &Tg, &Tb, &Ta);
+ val1= Tr+Tg+Tb;
+
+ boxsample(ibuf, fx-minx, fy-2.0f*miny, fx+2.0f*minx, fy+miny, &fac1, &fac2, &fac3, &fac4);
+ val2= fac1+fac2+fac3;
+
+ boxsample(ibuf, fx-2.0f*minx, fy-miny, fx+miny, fy+2.0f*miny, &fac1, &fac2, &fac3, &fac4);
+ val3= fac1+fac2+fac3;
+
+ /* niet x en y verwisselen! */
+ tex->nor[0]= (val1-val2);
+ tex->nor[1]= (val1-val3);
+
+ }
+ else {
+ boxsample(ibuf, fx-minx, fy-miny, fx+minx, fy+miny, &Tr, &Tg, &Tb, &Ta);
+ }
+
+ }
+
+ BRICONRGB;
+
+ if(tex->imaflag & TEX_CALCALPHA) {
+ Ta= Tin= MAX3(Tr, Tg, Tb);
+ }
+ else Tin= Ta;
+ if(tex->flag & TEX_NEGALPHA) Ta= 1.0f-Ta;
+
+ if( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) {
+ ibuf->rect-= (ibuf->x*ibuf->y);
+ }
+
+ }
+ else {
+ Tin= 0.0f;
+ return 0;
+ }
+
+ if(tex->flag & TEX_COLORBAND) do_colorband(tex->coba);
+
+ if(tex->nor) return 3;
+ else return 1;
+}
+
diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c
new file mode 100644
index 00000000000..cab1efba716
--- /dev/null
+++ b/source/blender/blenkernel/intern/ipo.c
@@ -0,0 +1,1878 @@
+/* ipo.c MIXED MODEL
+ *
+ * jan 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 <math.h>
+#include <stdio.h>
+#include <string.h>
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+#include "MEM_guardedalloc.h"
+
+#include "DNA_ika_types.h"
+#include "DNA_sequence_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_sound_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_key_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_material_types.h"
+#include "DNA_object_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_ipo_types.h"
+#include "DNA_action_types.h"
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "BKE_bad_level_calls.h"
+#include "BKE_utildefines.h"
+
+#include "BKE_main.h"
+#include "BKE_global.h"
+#include "BKE_library.h"
+#include "BKE_curve.h"
+#include "BKE_object.h"
+#include "BKE_blender.h"
+#include "BKE_ipo.h"
+#include "BKE_constraint.h"
+
+#define SMALL -1.0e-10
+
+/* Dit array is ervoor zodat defines zoals OB_LOC_X niet persee 0 hoeft te zijn.
+ Ook voor toekomstige backward compatibility.
+ Zo kan met een for-next lus alles worden afgelopen */
+
+int co_ar[CO_TOTIPO]= {
+ CO_ENFORCE
+};
+
+int ob_ar[OB_TOTIPO]= {
+ OB_LOC_X, OB_LOC_Y, OB_LOC_Z, OB_DLOC_X, OB_DLOC_Y, OB_DLOC_Z,
+ OB_ROT_X, OB_ROT_Y, OB_ROT_Z, OB_DROT_X, OB_DROT_Y, OB_DROT_Z,
+ OB_SIZE_X, OB_SIZE_Y, OB_SIZE_Z, OB_DSIZE_X, OB_DSIZE_Y, OB_DSIZE_Z,
+ OB_LAY, OB_TIME, OB_EFF_X, OB_EFF_Y, OB_EFF_Z, OB_COL_A
+};
+
+int ac_ar[AC_TOTIPO]= {
+ AC_LOC_X, AC_LOC_Y, AC_LOC_Z,
+ AC_QUAT_W, AC_QUAT_X, AC_QUAT_Y, AC_QUAT_Z,
+ AC_SIZE_X, AC_SIZE_Y, AC_SIZE_Z
+};
+
+int ma_ar[MA_TOTIPO]= {
+ MA_COL_R, MA_COL_G, MA_COL_B,
+ MA_SPEC_R, MA_SPEC_G, MA_SPEC_B,
+ MA_MIR_R, MA_MIR_G, MA_MIR_B,
+ MA_REF, MA_ALPHA, MA_EMIT, MA_AMB,
+ MA_SPEC, MA_HARD, MA_SPTR, MA_ANG,
+ MA_MODE, MA_HASIZE,
+
+ MA_MAP1+MAP_OFS_X, MA_MAP1+MAP_OFS_Y, MA_MAP1+MAP_OFS_Z,
+ MA_MAP1+MAP_SIZE_X, MA_MAP1+MAP_SIZE_Y, MA_MAP1+MAP_SIZE_Z,
+ MA_MAP1+MAP_R, MA_MAP1+MAP_G, MA_MAP1+MAP_B,
+ MA_MAP1+MAP_DVAR, MA_MAP1+MAP_COLF, MA_MAP1+MAP_NORF, MA_MAP1+MAP_VARF
+};
+
+int seq_ar[SEQ_TOTIPO]= {
+ SEQ_FAC1
+};
+
+int cu_ar[CU_TOTIPO]= {
+ CU_SPEED
+};
+
+int key_ar[KEY_TOTIPO]= {
+ KEY_SPEED, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
+ 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+ 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
+};
+
+int wo_ar[WO_TOTIPO]= {
+ WO_HOR_R, WO_HOR_G, WO_HOR_B, WO_ZEN_R, WO_ZEN_G, WO_ZEN_B,
+ WO_EXPOS, WO_MISI, WO_MISTDI, WO_MISTSTA, WO_MISTHI,
+ WO_STAR_R, WO_STAR_G, WO_STAR_B, WO_STARDIST, WO_STARSIZE,
+
+ MA_MAP1+MAP_OFS_X, MA_MAP1+MAP_OFS_Y, MA_MAP1+MAP_OFS_Z,
+ MA_MAP1+MAP_SIZE_X, MA_MAP1+MAP_SIZE_Y, MA_MAP1+MAP_SIZE_Z,
+ MA_MAP1+MAP_R, MA_MAP1+MAP_G, MA_MAP1+MAP_B,
+ MA_MAP1+MAP_DVAR, MA_MAP1+MAP_COLF, MA_MAP1+MAP_NORF, MA_MAP1+MAP_VARF
+};
+
+int la_ar[LA_TOTIPO]= {
+ LA_ENERGY, LA_COL_R, LA_COL_G, LA_COL_B,
+ LA_DIST, LA_SPOTSI, LA_SPOTBL,
+ LA_QUAD1, LA_QUAD2, LA_HALOINT,
+
+ MA_MAP1+MAP_OFS_X, MA_MAP1+MAP_OFS_Y, MA_MAP1+MAP_OFS_Z,
+ MA_MAP1+MAP_SIZE_X, MA_MAP1+MAP_SIZE_Y, MA_MAP1+MAP_SIZE_Z,
+ MA_MAP1+MAP_R, MA_MAP1+MAP_G, MA_MAP1+MAP_B,
+ MA_MAP1+MAP_DVAR, MA_MAP1+MAP_COLF, MA_MAP1+MAP_NORF, MA_MAP1+MAP_VARF
+};
+
+int cam_ar[CAM_TOTIPO]= {
+ CAM_LENS, CAM_STA, CAM_END
+};
+
+int snd_ar[SND_TOTIPO]= {
+ SND_VOLUME, SND_PITCH, SND_PANNING, SND_ATTEN
+};
+
+
+
+float frame_to_float(int cfra) /* zie ook bsystem_time in object.c */
+{
+ extern float bluroffs; /* object.c */
+ float ctime;
+
+ ctime= (float)cfra;
+ if(R.flag & R_SEC_FIELD) {
+ if((R.r.mode & R_FIELDSTILL)==0) ctime+= 0.5;
+ }
+ ctime+= bluroffs;
+ ctime*= G.scene->r.framelen;
+
+ return ctime;
+}
+
+/* niet ipo zelf vrijgeven */
+void free_ipo(Ipo *ipo)
+{
+ IpoCurve *icu;
+
+ icu= ipo->curve.first;
+ while(icu) {
+ if(icu->bezt) MEM_freeN(icu->bezt);
+ icu= icu->next;
+ }
+ BLI_freelistN(&ipo->curve);
+}
+
+Ipo *add_ipo(char *name, int idcode)
+{
+ Ipo *ipo;
+
+ ipo= alloc_libblock(&G.main->ipo, ID_IP, name);
+ ipo->blocktype= idcode;
+
+ return ipo;
+}
+
+Ipo *copy_ipo(Ipo *ipo)
+{
+ Ipo *ipon;
+ IpoCurve *icu;
+
+ if(ipo==0) return 0;
+
+ ipon= copy_libblock(ipo);
+
+ duplicatelist(&(ipon->curve), &(ipo->curve));
+
+ icu= ipon->curve.first;
+ while(icu) {
+ icu->bezt= MEM_dupallocN(icu->bezt);
+ icu= icu->next;
+ }
+
+ return ipon;
+}
+
+void make_local_obipo(Ipo *ipo)
+{
+ Object *ob;
+ Ipo *ipon;
+ int local=0, lib=0;
+
+ /* - zijn er alleen lib users: niet doen
+ * - zijn er alleen locale users: flag zetten
+ * - mixed: copy
+ */
+
+ ob= G.main->object.first;
+ while(ob) {
+ if(ob->ipo==ipo) {
+ if(ob->id.lib) lib= 1;
+ else local= 1;
+ }
+ ob= ob->id.next;
+ }
+
+ if(local && lib==0) {
+ ipo->id.lib= 0;
+ ipo->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)ipo, 0);
+ }
+ else if(local && lib) {
+ ipon= copy_ipo(ipo);
+ ipon->id.us= 0;
+
+ ob= G.main->object.first;
+ while(ob) {
+ if(ob->ipo==ipo) {
+
+ if(ob->id.lib==0) {
+ ob->ipo= ipon;
+ ipon->id.us++;
+ ipo->id.us--;
+ }
+ }
+ ob= ob->id.next;
+ }
+ }
+}
+
+void make_local_matipo(Ipo *ipo)
+{
+ Material *ma;
+ Ipo *ipon;
+ int local=0, lib=0;
+
+ /* - zijn er alleen lib users: niet doen
+ * - zijn er alleen locale users: flag zetten
+ * - mixed: copy
+ */
+
+ ma= G.main->mat.first;
+ while(ma) {
+ if(ma->ipo==ipo) {
+ if(ma->id.lib) lib= 1;
+ else local= 1;
+ }
+ ma= ma->id.next;
+ }
+
+ if(local && lib==0) {
+ ipo->id.lib= 0;
+ ipo->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)ipo, 0);
+ }
+ else if(local && lib) {
+ ipon= copy_ipo(ipo);
+ ipon->id.us= 0;
+
+ ma= G.main->mat.first;
+ while(ma) {
+ if(ma->ipo==ipo) {
+
+ if(ma->id.lib==0) {
+ ma->ipo= ipon;
+ ipon->id.us++;
+ ipo->id.us--;
+ }
+ }
+ ma= ma->id.next;
+ }
+ }
+}
+
+void make_local_keyipo(Ipo *ipo)
+{
+ Key *key;
+ Ipo *ipon;
+ int local=0, lib=0;
+
+ /* - zijn er alleen lib users: niet doen
+ * - zijn er alleen locale users: flag zetten
+ * - mixed: copy
+ */
+
+ key= G.main->key.first;
+ while(key) {
+ if(key->ipo==ipo) {
+ if(key->id.lib) lib= 1;
+ else local= 1;
+ }
+ key= key->id.next;
+ }
+
+ if(local && lib==0) {
+ ipo->id.lib= 0;
+ ipo->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)ipo, 0);
+ }
+ else if(local && lib) {
+ ipon= copy_ipo(ipo);
+ ipon->id.us= 0;
+
+ key= G.main->key.first;
+ while(key) {
+ if(key->ipo==ipo) {
+
+ if(key->id.lib==0) {
+ key->ipo= ipon;
+ ipon->id.us++;
+ ipo->id.us--;
+ }
+ }
+ key= key->id.next;
+ }
+ }
+}
+
+
+void make_local_ipo(Ipo *ipo)
+{
+
+ if(ipo->id.lib==0) return;
+ if(ipo->id.us==1) {
+ ipo->id.lib= 0;
+ ipo->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)ipo, 0);
+ return;
+ }
+
+ if(ipo->blocktype==ID_OB) make_local_obipo(ipo);
+ else if(ipo->blocktype==ID_MA) make_local_matipo(ipo);
+ else if(ipo->blocktype==ID_KE) make_local_keyipo(ipo);
+
+}
+
+
+void calchandles_ipocurve(IpoCurve *icu)
+{
+ BezTriple *bezt, *prev, *next;
+ int a;
+
+ a= icu->totvert;
+ if(a<2) return;
+
+ bezt= icu->bezt;
+ prev= 0;
+ next= bezt+1;
+
+ while(a--) {
+
+ if(bezt->vec[0][0]>bezt->vec[1][0]) bezt->vec[0][0]= bezt->vec[1][0];
+ if(bezt->vec[2][0]<bezt->vec[1][0]) bezt->vec[2][0]= bezt->vec[1][0];
+
+ calchandleNurb(bezt, prev, next, 1); /* 1==speciale autohandle */
+
+ prev= bezt;
+ if(a==1) {
+ next= 0;
+ }
+ else next++;
+
+ /* voor automatische ease in en out */
+ if(bezt->h1==HD_AUTO && bezt->h2==HD_AUTO) {
+ if(a==0 || a==icu->totvert-1) {
+ if(icu->extrap==IPO_HORIZ) {
+ bezt->vec[0][1]= bezt->vec[2][1]= bezt->vec[1][1];
+ }
+ }
+ }
+
+ bezt++;
+ }
+}
+
+void testhandles_ipocurve(IpoCurve *icu)
+{
+ /* Te gebruiken als er iets aan de handles is veranderd.
+ * Loopt alle BezTriples af met de volgende regels:
+ * FASE 1: types veranderen?
+ * Autocalchandles: worden ligned als NOT(000 || 111)
+ * Vectorhandles worden 'niets' als (selected en andere niet)
+ * FASE 2: handles herberekenen
+ */
+ BezTriple *bezt;
+ int flag, a;
+
+ bezt= icu->bezt;
+ if(bezt==0) return;
+
+ a= icu->totvert;
+ while(a--) {
+ flag= 0;
+ if(bezt->f1 & 1) flag++;
+ if(bezt->f2 & 1) flag += 2;
+ if(bezt->f3 & 1) flag += 4;
+
+ if( !(flag==0 || flag==7) ) {
+ if(bezt->h1==HD_AUTO) { /* auto */
+ bezt->h1= HD_ALIGN;
+ }
+ if(bezt->h2==HD_AUTO) { /* auto */
+ bezt->h2= HD_ALIGN;
+ }
+
+ if(bezt->h1==HD_VECT) { /* vector */
+ if(flag < 4) bezt->h1= 0;
+ }
+ if(bezt->h2==HD_VECT) { /* vector */
+ if( flag > 3) bezt->h2= 0;
+ }
+ }
+ bezt++;
+ }
+
+ calchandles_ipocurve(icu);
+}
+
+
+void sort_time_ipocurve(IpoCurve *icu)
+{
+ BezTriple *bezt;
+ int a, ok= 1;
+
+ while(ok) {
+ ok= 0;
+
+ if(icu->bezt) {
+ bezt= icu->bezt;
+ a= icu->totvert;
+ while(a--) {
+ if(a>0) {
+ if( bezt->vec[1][0] > (bezt+1)->vec[1][0]) {
+ SWAP(BezTriple, *bezt, *(bezt+1));
+ ok= 1;
+ }
+ }
+ if(bezt->vec[0][0]>=bezt->vec[1][0] && bezt->vec[2][0]<=bezt->vec[1][0]) {
+ SWAP(float, bezt->vec[0][0], bezt->vec[2][0]);
+ SWAP(float, bezt->vec[0][1], bezt->vec[2][1]);
+ }
+ else {
+ if(bezt->vec[0][0]>bezt->vec[1][0]) bezt->vec[0][0]= bezt->vec[1][0];
+ if(bezt->vec[2][0]<bezt->vec[1][0]) bezt->vec[2][0]= bezt->vec[1][0];
+ }
+ bezt++;
+ }
+ }
+ else {
+
+ }
+ }
+}
+
+int test_time_ipocurve(IpoCurve *icu)
+{
+ BezTriple *bezt;
+ int a;
+
+ if(icu->bezt) {
+ bezt= icu->bezt;
+ a= icu->totvert-1;
+ while(a--) {
+ if( bezt->vec[1][0] > (bezt+1)->vec[1][0]) {
+ return 1;
+ }
+ bezt++;
+ }
+ }
+ else {
+
+ }
+
+ return 0;
+}
+
+void correct_bezpart(float *v1, float *v2, float *v3, float *v4)
+{
+ /* de totale lengte van de handles mag niet langer zijn
+ * dan de horizontale afstand tussen de punten (v1-v4)
+ */
+ float h1[2], h2[2], len1, len2, len, fac;
+
+ h1[0]= v1[0]-v2[0];
+ h1[1]= v1[1]-v2[1];
+ h2[0]= v4[0]-v3[0];
+ h2[1]= v4[1]-v3[1];
+
+ len= v4[0]- v1[0];
+ len1= (float)fabs(h1[0]);
+ len2= (float)fabs(h2[0]);
+
+ if(len1+len2==0.0) return;
+ if(len1+len2 > len) {
+ fac= len/(len1+len2);
+
+ v2[0]= (v1[0]-fac*h1[0]);
+ v2[1]= (v1[1]-fac*h1[1]);
+
+ v3[0]= (v4[0]-fac*h2[0]);
+ v3[1]= (v4[1]-fac*h2[1]);
+
+ }
+}
+
+/* *********************** ARITH *********************** */
+
+int findzero(float x, float q0, float q1, float q2, float q3, float *o)
+{
+ double c0, c1, c2, c3, a, b, c, p, q, d, t, phi;
+ int nr= 0;
+
+ c0= q0-x;
+ c1= 3*(q1-q0);
+ c2= 3*(q0-2*q1+q2);
+ c3= q3-q0+3*(q1-q2);
+
+ if(c3!=0.0) {
+ a= c2/c3;
+ b= c1/c3;
+ c= c0/c3;
+ a= a/3;
+
+ p= b/3-a*a;
+ q= (2*a*a*a-a*b+c)/2;
+ d= q*q+p*p*p;
+
+ if(d>0.0) {
+ t= sqrt(d);
+ o[0]= (float)(Sqrt3d(-q+t)+Sqrt3d(-q-t)-a);
+ if(o[0]>= SMALL && o[0]<=1.000001) return 1;
+ else return 0;
+ }
+ else if(d==0.0) {
+ t= Sqrt3d(-q);
+ o[0]= (float)(2*t-a);
+ if(o[0]>=SMALL && o[0]<=1.000001) nr++;
+ o[nr]= (float)(-t-a);
+ if(o[nr]>=SMALL && o[nr]<=1.000001) return nr+1;
+ else return nr;
+ }
+ else {
+ phi= acos(-q/sqrt(-(p*p*p)));
+ t= sqrt(-p);
+ p= cos(phi/3);
+ q= sqrt(3-3*p*p);
+ o[0]= (float)(2*t*p-a);
+ if(o[0]>=SMALL && o[0]<=1.000001) nr++;
+ o[nr]= (float)(-t*(p+q)-a);
+ if(o[nr]>=SMALL && o[nr]<=1.000001) nr++;
+ o[nr]= (float)(-t*(p-q)-a);
+ if(o[nr]>=SMALL && o[nr]<=1.000001) return nr+1;
+ else return nr;
+ }
+ }
+ else {
+ a=c2;
+ b=c1;
+ c=c0;
+
+ if(a!=0.0) {
+ p=b*b-4*a*c;
+ if(p>0) {
+ p= sqrt(p);
+ o[0]= (float)((-b-p)/(2*a));
+ if(o[0]>=SMALL && o[0]<=1.000001) nr++;
+ o[nr]= (float)((-b+p)/(2*a));
+ if(o[nr]>=SMALL && o[nr]<=1.000001) return nr+1;
+ else return nr;
+ }
+ else if(p==0) {
+ o[0]= (float)(-b/(2*a));
+ if(o[0]>=SMALL && o[0]<=1.000001) return 1;
+ else return 0;
+ }
+ }
+ else if(b!=0.0) {
+ o[0]= (float)(-c/b);
+ if(o[0]>=SMALL && o[0]<=1.000001) return 1;
+ else return 0;
+ }
+ else if(c==0.0) {
+ o[0]= 0.0;
+ return 1;
+ }
+ return 0;
+ }
+}
+
+void berekeny(float f1, float f2, float f3, float f4, float *o, int b)
+{
+ float t, c0, c1, c2, c3;
+ int a;
+
+ c0= f1;
+ c1= 3.0f*(f2 - f1);
+ c2= 3.0f*(f1 - 2.0f*f2 + f3);
+ c3= f4 - f1 + 3.0f*(f2-f3);
+
+ for(a=0; a<b; a++) {
+ t= o[a];
+ o[a]= c0+t*c1+t*t*c2+t*t*t*c3;
+ }
+}
+void berekenx(float *f, float *o, int b)
+{
+ float t, c0, c1, c2, c3;
+ int a;
+
+ c0= f[0];
+ c1= 3*(f[3]-f[0]);
+ c2= 3*(f[0]-2*f[3]+f[6]);
+ c3= f[9]-f[0]+3*(f[3]-f[6]);
+ for(a=0; a<b; a++) {
+ t= o[a];
+ o[a]= c0+t*c1+t*t*c2+t*t*t*c3;
+ }
+}
+
+float eval_icu(IpoCurve *icu, float ipotime)
+{
+ BezTriple *bezt, *prevbezt;
+ float v1[2], v2[2], v3[2], v4[2], opl[32], dx, fac;
+ float cycdx, cycdy, ofs, cycyofs, cvalue = 0.0;
+ int a, b;
+
+ cycyofs= 0.0;
+
+ if(icu->bezt) {
+ prevbezt= icu->bezt;
+ bezt= prevbezt+1;
+ a= icu->totvert-1;
+
+ /* cyclic? */
+ if(icu->extrap & IPO_CYCL) {
+ ofs= icu->bezt->vec[1][0];
+ cycdx= (icu->bezt+icu->totvert-1)->vec[1][0] - ofs;
+ cycdy= (icu->bezt+icu->totvert-1)->vec[1][1] - icu->bezt->vec[1][1];
+ if(cycdx!=0.0) {
+
+ if(icu->extrap & IPO_DIR) {
+ cycyofs= (float)floor((ipotime-ofs)/cycdx);
+ cycyofs*= cycdy;
+ }
+
+ ipotime= (float)(fmod(ipotime-ofs, cycdx)+ofs);
+ if(ipotime<ofs) ipotime+= cycdx;
+ }
+ }
+
+ /* uiteinden? */
+
+ if(prevbezt->vec[1][0]>=ipotime) {
+ if( (icu->extrap & IPO_DIR) && icu->ipo!=IPO_CONST) {
+ dx= prevbezt->vec[1][0]-ipotime;
+ fac= prevbezt->vec[1][0]-prevbezt->vec[0][0];
+ if(fac!=0.0) {
+ fac= (prevbezt->vec[1][1]-prevbezt->vec[0][1])/fac;
+ cvalue= prevbezt->vec[1][1]-fac*dx;
+ }
+ else cvalue= prevbezt->vec[1][1];
+ }
+ else cvalue= prevbezt->vec[1][1];
+
+ cvalue+= cycyofs;
+ }
+ else if( (prevbezt+a)->vec[1][0]<=ipotime) {
+ if( (icu->extrap & IPO_DIR) && icu->ipo!=IPO_CONST) {
+ prevbezt+= a;
+ dx= ipotime-prevbezt->vec[1][0];
+ fac= prevbezt->vec[2][0]-prevbezt->vec[1][0];
+
+ if(fac!=0) {
+ fac= (prevbezt->vec[2][1]-prevbezt->vec[1][1])/fac;
+ cvalue= prevbezt->vec[1][1]+fac*dx;
+ }
+ else cvalue= prevbezt->vec[1][1];
+ }
+ else cvalue= (prevbezt+a)->vec[1][1];
+
+ cvalue+= cycyofs;
+ }
+ else {
+ while(a--) {
+ if(prevbezt->vec[1][0]<=ipotime && bezt->vec[1][0]>=ipotime) {
+ if(icu->ipo==IPO_CONST) {
+ cvalue= prevbezt->vec[1][1]+cycyofs;
+ }
+ else if(icu->ipo==IPO_LIN) {
+ fac= bezt->vec[1][0]-prevbezt->vec[1][0];
+ if(fac==0) cvalue= cycyofs+prevbezt->vec[1][1];
+ else {
+ fac= (ipotime-prevbezt->vec[1][0])/fac;
+ cvalue= cycyofs+prevbezt->vec[1][1]+ fac*(bezt->vec[1][1]-prevbezt->vec[1][1]);
+ }
+ }
+ else {
+ v1[0]= prevbezt->vec[1][0];
+ v1[1]= prevbezt->vec[1][1];
+ v2[0]= prevbezt->vec[2][0];
+ v2[1]= prevbezt->vec[2][1];
+
+ v3[0]= bezt->vec[0][0];
+ v3[1]= bezt->vec[0][1];
+ v4[0]= bezt->vec[1][0];
+ v4[1]= bezt->vec[1][1];
+
+ correct_bezpart(v1, v2, v3, v4);
+
+ b= findzero(ipotime, v1[0], v2[0], v3[0], v4[0], opl);
+ if(b) {
+ berekeny(v1[1], v2[1], v3[1], v4[1], opl, 1);
+ cvalue= opl[0]+cycyofs;
+ break;
+ }
+ }
+ }
+ prevbezt= bezt;
+ bezt++;
+ }
+ }
+ }
+
+ if(icu->ymin < icu->ymax) {
+ if(cvalue < icu->ymin) cvalue= icu->ymin;
+ else if(cvalue > icu->ymax) cvalue= icu->ymax;
+ }
+
+ return cvalue;
+}
+
+void calc_icu(IpoCurve *icu, float ctime)
+{
+ icu->curval= eval_icu(icu, ctime);
+}
+
+float calc_ipo_time(Ipo *ipo, float ctime)
+{
+
+ if(ipo && ipo->blocktype==ID_OB) {
+ IpoCurve *icu= ipo->curve.first;
+
+ while(icu) {
+ if (icu->adrcode==OB_TIME) {
+ calc_icu(icu, ctime);
+ return 10.0f*icu->curval;
+ }
+ icu= icu->next;
+ }
+ }
+
+ return ctime;
+}
+
+void calc_ipo(Ipo *ipo, float ctime)
+{
+ IpoCurve *icu;
+
+ icu= ipo->curve.first;
+ while(icu) {
+
+ if( (icu->flag & IPO_LOCK)==0) calc_icu(icu, ctime);
+
+ icu= icu->next;
+ }
+}
+
+/* ************************************** */
+/* DO THE IPO! */
+/* ************************************** */
+
+void write_ipo_poin(void *poin, int type, float val)
+{
+
+ switch(type) {
+ case IPO_FLOAT:
+ *( (float *)poin)= val;
+ break;
+ case IPO_FLOAT_DEGR:
+ *( (float *)poin)= (float)(val*M_PI_2/9.0);
+ break;
+ case IPO_INT:
+ case IPO_INT_BIT:
+ case IPO_LONG:
+ *( (int *)poin)= (int)val;
+ break;
+ case IPO_SHORT:
+ case IPO_SHORT_BIT:
+ *( (short *)poin)= (short)val;
+ break;
+ case IPO_CHAR:
+ case IPO_CHAR_BIT:
+ *( (char *)poin)= (char)val;
+ break;
+ }
+}
+
+float read_ipo_poin(void *poin, int type)
+{
+ float val = 0.0;
+
+ switch(type) {
+ case IPO_FLOAT:
+ val= *( (float *)poin);
+ break;
+ case IPO_FLOAT_DEGR:
+ val= *( (float *)poin);
+ val = (float)(val/(M_PI_2/9.0));
+ break;
+ case IPO_INT:
+ case IPO_INT_BIT:
+ case IPO_LONG:
+ val= (float)(*( (int *)poin));
+ break;
+ case IPO_SHORT:
+ case IPO_SHORT_BIT:
+ val= *( (short *)poin);
+ break;
+ case IPO_CHAR:
+ case IPO_CHAR_BIT:
+ val= *( (char *)poin);
+ break;
+ }
+ return val;
+}
+
+void *give_mtex_poin(MTex *mtex, int adrcode )
+{
+ void *poin=0;
+
+ switch(adrcode) {
+ case MAP_OFS_X:
+ poin= &(mtex->ofs[0]); break;
+ case MAP_OFS_Y:
+ poin= &(mtex->ofs[1]); break;
+ case MAP_OFS_Z:
+ poin= &(mtex->ofs[2]); break;
+ case MAP_SIZE_X:
+ poin= &(mtex->size[0]); break;
+ case MAP_SIZE_Y:
+ poin= &(mtex->size[1]); break;
+ case MAP_SIZE_Z:
+ poin= &(mtex->size[2]); break;
+ case MAP_R:
+ poin= &(mtex->r); break;
+ case MAP_G:
+ poin= &(mtex->g); break;
+ case MAP_B:
+ poin= &(mtex->b); break;
+ case MAP_DVAR:
+ poin= &(mtex->def_var); break;
+ case MAP_COLF:
+ poin= &(mtex->colfac); break;
+ case MAP_NORF:
+ poin= &(mtex->norfac); break;
+ case MAP_VARF:
+ poin= &(mtex->varfac); break;
+ }
+
+ return poin;
+}
+
+/* GS reads the memory pointed at in a specific ordering. There are,
+ * however two definitions for it. I have jotted them down here, both,
+ * but I think the first one is actually used. The thing is that
+ * big-endian systems might read this the wrong way round. OTOH, we
+ * constructed the IDs that are read out with this macro explicitly as
+ * well. I expect we'll sort it out soon... */
+
+/* from blendef: */
+#define GS(a) (*((short *)(a)))
+
+/* from misc_util: flip the bytes from x */
+/* #define GS(x) (((unsigned char *)(x))[0] << 8 | ((unsigned char *)(x))[1]) */
+
+void *get_ipo_poin(ID *id, IpoCurve *icu, int *type)
+{
+ void *poin= 0;
+ Object *ob;
+ Material *ma;
+ MTex *mtex;
+ Ika *ika= 0;
+ Lamp *la;
+ Sequence *seq;
+ World *wo;
+ bAction *act;
+ bActionChannel *achan;
+ bPoseChannel *pchan;
+
+ *type= IPO_FLOAT;
+
+
+ if( GS(id->name)==ID_OB) {
+
+ ob= (Object *)id;
+
+ if(ob->type==OB_IKA) ika= ob->data;
+
+ switch(icu->adrcode) {
+ case OB_LOC_X:
+ poin= &(ob->loc[0]); break;
+ case OB_LOC_Y:
+ poin= &(ob->loc[1]); break;
+ case OB_LOC_Z:
+ poin= &(ob->loc[2]); break;
+ case OB_DLOC_X:
+ poin= &(ob->dloc[0]); break;
+ case OB_DLOC_Y:
+ poin= &(ob->dloc[1]); break;
+ case OB_DLOC_Z:
+ poin= &(ob->dloc[2]); break;
+
+ case OB_ROT_X:
+ poin= &(ob->rot[0]); *type= IPO_FLOAT_DEGR; break;
+ case OB_ROT_Y:
+ poin= &(ob->rot[1]); *type= IPO_FLOAT_DEGR; break;
+ case OB_ROT_Z:
+ poin= &(ob->rot[2]); *type= IPO_FLOAT_DEGR; break;
+ case OB_DROT_X:
+ poin= &(ob->drot[0]); *type= IPO_FLOAT_DEGR; break;
+ case OB_DROT_Y:
+ poin= &(ob->drot[1]); *type= IPO_FLOAT_DEGR; break;
+ case OB_DROT_Z:
+ poin= &(ob->drot[2]); *type= IPO_FLOAT_DEGR; break;
+
+ case OB_SIZE_X:
+ poin= &(ob->size[0]); break;
+ case OB_SIZE_Y:
+ poin= &(ob->size[1]); break;
+ case OB_SIZE_Z:
+ poin= &(ob->size[2]); break;
+ case OB_DSIZE_X:
+ poin= &(ob->dsize[0]); break;
+ case OB_DSIZE_Y:
+ poin= &(ob->dsize[1]); break;
+ case OB_DSIZE_Z:
+ poin= &(ob->dsize[2]); break;
+
+ case OB_LAY:
+ poin= &(ob->lay); *type= IPO_INT_BIT; break;
+
+ case OB_EFF_X: /* OB_COL_R */
+ if(ika) poin= &(ika->effg[0]);
+ else poin= &(ob->col[0]);
+ break;
+ case OB_EFF_Y: /* OB_COL_G */
+ if(ika) poin= &(ika->effg[1]);
+ else poin= &(ob->col[1]);
+ break;
+ case OB_EFF_Z: /* OB_COL_B */
+ if(ika) poin= &(ika->effg[2]);
+ else poin= &(ob->col[2]);
+ break;
+ case OB_COL_A:
+ poin= &(ob->col[3]);
+ break;
+ }
+ }
+ else if (GS(id->name)==ID_AC){
+ act= (bAction *)id;
+ achan = act->achan;
+ pchan = act->pchan;
+ if (!pchan || !achan)
+ return NULL;
+ switch (icu->adrcode){
+ case AC_QUAT_W:
+ poin= &(pchan->quat[0]); break;
+ case AC_QUAT_X:
+ poin= &(pchan->quat[1]); break;
+ case AC_QUAT_Y:
+ poin= &(pchan->quat[2]); break;
+ case AC_QUAT_Z:
+ poin= &(pchan->quat[3]); break;
+ case AC_LOC_X:
+ poin= &(pchan->loc[0]); break;
+ case AC_LOC_Y:
+ poin= &(pchan->loc[1]); break;
+ case AC_LOC_Z:
+ poin= &(pchan->loc[2]); break;
+ case AC_SIZE_X:
+ poin= &(pchan->size[0]); break;
+ case AC_SIZE_Y:
+ poin= &(pchan->size[1]); break;
+ case AC_SIZE_Z:
+ poin= &(pchan->size[2]); break;
+ };
+ }
+
+ else if( GS(id->name)==ID_MA) {
+
+ ma= (Material *)id;
+
+ switch(icu->adrcode) {
+ case MA_COL_R:
+ poin= &(ma->r); break;
+ case MA_COL_G:
+ poin= &(ma->g); break;
+ case MA_COL_B:
+ poin= &(ma->b); break;
+ case MA_SPEC_R:
+ poin= &(ma->specr); break;
+ case MA_SPEC_G:
+ poin= &(ma->specg); break;
+ case MA_SPEC_B:
+ poin= &(ma->specb); break;
+ case MA_MIR_R:
+ poin= &(ma->mirr); break;
+ case MA_MIR_G:
+ poin= &(ma->mirg); break;
+ case MA_MIR_B:
+ poin= &(ma->mirb); break;
+ case MA_REF:
+ poin= &(ma->ref); break;
+ case MA_ALPHA:
+ poin= &(ma->alpha); break;
+ case MA_EMIT:
+ poin= &(ma->emit); break;
+ case MA_AMB:
+ poin= &(ma->amb); break;
+ case MA_SPEC:
+ poin= &(ma->spec); break;
+ case MA_HARD:
+ poin= &(ma->har); *type= IPO_SHORT; break;
+ case MA_SPTR:
+ poin= &(ma->spectra); break;
+ case MA_ANG:
+ poin= &(ma->ang); break;
+ case MA_MODE:
+ poin= &(ma->mode); *type= IPO_INT_BIT; break;
+ case MA_HASIZE:
+ poin= &(ma->hasize); break;
+ }
+
+ if(poin==0) {
+ mtex= 0;
+ if(icu->adrcode & MA_MAP1) mtex= ma->mtex[0];
+ else if(icu->adrcode & MA_MAP2) mtex= ma->mtex[1];
+ else if(icu->adrcode & MA_MAP3) mtex= ma->mtex[2];
+ else if(icu->adrcode & MA_MAP4) mtex= ma->mtex[3];
+ else if(icu->adrcode & MA_MAP5) mtex= ma->mtex[4];
+ else if(icu->adrcode & MA_MAP6) mtex= ma->mtex[5];
+ else if(icu->adrcode & MA_MAP7) mtex= ma->mtex[6];
+ else if(icu->adrcode & MA_MAP8) mtex= ma->mtex[7];
+
+ if(mtex) {
+ poin= give_mtex_poin(mtex, icu->adrcode & (MA_MAP1-1) );
+ }
+ }
+ }
+ else if( GS(id->name)==ID_SEQ) {
+ seq= (Sequence *)id;
+
+ switch(icu->adrcode) {
+ case SEQ_FAC1:
+ poin= &(seq->facf0); break;
+ }
+ }
+ else if( GS(id->name)==ID_CU) {
+
+ poin= &(icu->curval);
+
+ }
+ else if( GS(id->name)==ID_KE) {
+
+ poin= &(icu->curval);
+
+ }
+ else if(GS(id->name)==ID_WO) {
+
+ wo= (World *)id;
+
+ switch(icu->adrcode) {
+ case WO_HOR_R:
+ poin= &(wo->horr); break;
+ case WO_HOR_G:
+ poin= &(wo->horg); break;
+ case WO_HOR_B:
+ poin= &(wo->horb); break;
+ case WO_ZEN_R:
+ poin= &(wo->zenr); break;
+ case WO_ZEN_G:
+ poin= &(wo->zeng); break;
+ case WO_ZEN_B:
+ poin= &(wo->zenb); break;
+
+ case WO_EXPOS:
+ poin= &(wo->exposure); break;
+
+ case WO_MISI:
+ poin= &(wo->misi); break;
+ case WO_MISTDI:
+ poin= &(wo->mistdist); break;
+ case WO_MISTSTA:
+ poin= &(wo->miststa); break;
+ case WO_MISTHI:
+ poin= &(wo->misthi); break;
+
+ case WO_STAR_R:
+ poin= &(wo->starr); break;
+ case WO_STAR_G:
+ poin= &(wo->starg); break;
+ case WO_STAR_B:
+ poin= &(wo->starb); break;
+
+ case WO_STARDIST:
+ poin= &(wo->stardist); break;
+ case WO_STARSIZE:
+ poin= &(wo->starsize); break;
+ }
+
+ if(poin==0) {
+ mtex= 0;
+ if(icu->adrcode & MA_MAP1) mtex= wo->mtex[0];
+ else if(icu->adrcode & MA_MAP2) mtex= wo->mtex[1];
+ else if(icu->adrcode & MA_MAP3) mtex= wo->mtex[2];
+ else if(icu->adrcode & MA_MAP4) mtex= wo->mtex[3];
+ else if(icu->adrcode & MA_MAP5) mtex= wo->mtex[4];
+ else if(icu->adrcode & MA_MAP6) mtex= wo->mtex[5];
+ else if(icu->adrcode & MA_MAP7) mtex= wo->mtex[6];
+ else if(icu->adrcode & MA_MAP8) mtex= wo->mtex[7];
+
+ if(mtex) {
+ poin= give_mtex_poin(mtex, icu->adrcode & (MA_MAP1-1) );
+ }
+ }
+ }
+ else if( GS(id->name)==ID_LA) {
+
+ la= (Lamp *)id;
+
+ switch(icu->adrcode) {
+ case LA_ENERGY:
+ poin= &(la->energy); break;
+ case LA_COL_R:
+ poin= &(la->r); break;
+ case LA_COL_G:
+ poin= &(la->g); break;
+ case LA_COL_B:
+ poin= &(la->b); break;
+ case LA_DIST:
+ poin= &(la->dist); break;
+ case LA_SPOTSI:
+ poin= &(la->spotsize); break;
+ case LA_SPOTBL:
+ poin= &(la->spotblend); break;
+ case LA_QUAD1:
+ poin= &(la->att1); break;
+ case LA_QUAD2:
+ poin= &(la->att2); break;
+ case LA_HALOINT:
+ poin= &(la->haint); break;
+ }
+
+ if(poin==0) {
+ mtex= 0;
+ if(icu->adrcode & MA_MAP1) mtex= la->mtex[0];
+ else if(icu->adrcode & MA_MAP2) mtex= la->mtex[1];
+ else if(icu->adrcode & MA_MAP3) mtex= la->mtex[2];
+ else if(icu->adrcode & MA_MAP4) mtex= la->mtex[3];
+ else if(icu->adrcode & MA_MAP5) mtex= la->mtex[4];
+ else if(icu->adrcode & MA_MAP6) mtex= la->mtex[5];
+ else if(icu->adrcode & MA_MAP7) mtex= la->mtex[6];
+ else if(icu->adrcode & MA_MAP8) mtex= la->mtex[7];
+
+ if(mtex) {
+ poin= give_mtex_poin(mtex, icu->adrcode & (MA_MAP1-1) );
+ }
+ }
+ }
+ else if(GS(id->name)==ID_CA) {
+ Camera *ca= (Camera *)id;
+
+ switch(icu->adrcode) {
+ case CAM_LENS:
+ poin= &(ca->lens); break;
+ case CAM_STA:
+ poin= &(ca->clipsta); break;
+ case CAM_END:
+ poin= &(ca->clipend); break;
+ }
+ }
+ else if(GS(id->name)==ID_SO) {
+ bSound *snd= (bSound *)id;
+
+ switch(icu->adrcode) {
+ case SND_VOLUME:
+ poin= &(snd->volume); break;
+ case SND_PITCH:
+ poin= &(snd->pitch); break;
+ case SND_PANNING:
+ poin= &(snd->panning); break;
+ case SND_ATTEN:
+ poin= &(snd->attenuation); break;
+ }
+ }
+
+ return poin;
+}
+
+void set_icu_vars(IpoCurve *icu)
+{
+
+ icu->ymin= icu->ymax= 0.0;
+ icu->ipo= IPO_BEZ;
+
+ if(icu->blocktype==ID_OB) {
+
+ if(icu->adrcode==OB_LAY) {
+ icu->ipo= IPO_CONST;
+ icu->vartype= IPO_BITS;
+ }
+
+ }
+ else if(icu->blocktype==ID_MA) {
+
+ if(icu->adrcode < MA_MAP1) {
+ switch(icu->adrcode) {
+ case MA_HASIZE:
+ icu->ymax= 10000.0; break;
+ case MA_HARD:
+ icu->ymax= 128.0; break;
+ case MA_SPEC:
+ icu->ymax= 2.0; break;
+ case MA_MODE:
+ icu->ipo= IPO_CONST;
+ icu->vartype= IPO_BITS;
+ break;
+
+ default:
+ icu->ymax= 1.0;
+ break;
+ }
+ }
+ else {
+ switch(icu->adrcode & (MA_MAP1-1)) {
+ case MAP_OFS_X:
+ case MAP_OFS_Y:
+ case MAP_OFS_Z:
+ case MAP_SIZE_X:
+ case MAP_SIZE_Y:
+ case MAP_SIZE_Z:
+ icu->ymax= 1000.0;
+ icu->ymin= -1000.0;
+
+ break;
+ case MAP_R:
+ case MAP_G:
+ case MAP_B:
+ case MAP_DVAR:
+ case MAP_COLF:
+ case MAP_VARF:
+ icu->ymax= 1.0;
+ break;
+ case MAP_NORF:
+ icu->ymax= 5.0;
+ break;
+ }
+ }
+ }
+ else if(icu->blocktype==ID_SEQ) {
+
+ icu->ymax= 1.0;
+
+ }
+ else if(icu->blocktype==ID_CU) {
+
+ icu->ymax= 1.0;
+
+ }
+ else if(icu->blocktype==ID_WO) {
+
+ if(icu->adrcode < MA_MAP1) {
+ switch(icu->adrcode) {
+ case WO_EXPOS:
+ icu->ymax= 5.0; break;
+ case WO_MISTDI:
+ case WO_MISTSTA:
+ case WO_MISTHI:
+ case WO_STARDIST:
+ case WO_STARSIZE:
+ break;
+
+ default:
+ icu->ymax= 1.0;
+ break;
+ }
+ }
+ else {
+ switch(icu->adrcode & (MA_MAP1-1)) {
+ case MAP_OFS_X:
+ case MAP_OFS_Y:
+ case MAP_OFS_Z:
+ case MAP_SIZE_X:
+ case MAP_SIZE_Y:
+ case MAP_SIZE_Z:
+ icu->ymax= 100.0;
+ icu->ymin= -100.0;
+
+ break;
+ case MAP_R:
+ case MAP_G:
+ case MAP_B:
+ case MAP_DVAR:
+ case MAP_COLF:
+ case MAP_NORF:
+ case MAP_VARF:
+ icu->ymax= 1.0;
+ }
+ }
+ }
+ else if(icu->blocktype==ID_LA) {
+ if(icu->adrcode < MA_MAP1) {
+ switch(icu->adrcode) {
+ case LA_ENERGY:
+ case LA_DIST:
+ break;
+
+ case LA_COL_R:
+ case LA_COL_G:
+ case LA_COL_B:
+ case LA_SPOTBL:
+ case LA_QUAD1:
+ case LA_QUAD2:
+ icu->ymax= 1.0; break;
+ case LA_SPOTSI:
+ icu->ymax= 180.0; break;
+ case LA_HALOINT:
+ icu->ymax= 5.0; break;
+ }
+ }
+ else {
+ switch(icu->adrcode & (MA_MAP1-1)) {
+ case MAP_OFS_X:
+ case MAP_OFS_Y:
+ case MAP_OFS_Z:
+ case MAP_SIZE_X:
+ case MAP_SIZE_Y:
+ case MAP_SIZE_Z:
+ icu->ymax= 100.0;
+ icu->ymin= -100.0;
+ break;
+ case MAP_R:
+ case MAP_G:
+ case MAP_B:
+ case MAP_DVAR:
+ case MAP_COLF:
+ case MAP_NORF:
+ case MAP_VARF:
+ icu->ymax= 1.0;
+ }
+ }
+ }
+ else if(icu->blocktype==ID_CA) {
+
+ switch(icu->adrcode) {
+ case CAM_LENS:
+ icu->ymin= 5.0;
+ icu->ymax= 1000.0; break;
+ case CAM_STA:
+ icu->ymin= 0.001f;
+ break;
+ case CAM_END:
+ icu->ymin= 0.1f;
+ }
+ }
+ else if(icu->blocktype==ID_SO) {
+
+ switch(icu->adrcode) {
+ case SND_VOLUME:
+ icu->ymin= 0.0;
+ icu->ymax= 1.0;
+ break;
+ case SND_PITCH:
+ icu->ymin= -12.0;
+ icu->ymin= 12.0;
+ break;
+ case SND_PANNING:
+ icu->ymin= 0.0;
+ icu->ymax= 1.0;
+ break;
+ case SND_ATTEN:
+ icu->ymin= 0.0;
+ icu->ymin= 1.0;
+ break;
+ }
+ }
+}
+
+
+void execute_ipo(ID *id, Ipo *ipo)
+{
+ IpoCurve *icu;
+ void *poin;
+ int type;
+
+ if(ipo==0) return;
+
+ icu= ipo->curve.first;
+ while(icu) {
+ poin= get_ipo_poin(id, icu, &type);
+ if(poin) write_ipo_poin(poin, type, icu->curval);
+ icu= icu->next;
+ }
+}
+
+/* exception: it does calc for objects...
+ * now find out why this routine was used anyway!
+ */
+void do_ipo_nocalc(Ipo *ipo)
+{
+ Object *ob;
+ Material *ma;
+ World *wo;
+ Lamp *la;
+ Camera *ca;
+ bSound *snd;
+
+ if(ipo==0) return;
+
+ switch(ipo->blocktype) {
+ case ID_OB:
+ ob= G.main->object.first;
+ while(ob) {
+ if(ob->ipo==ipo) {
+ do_ob_ipo(ob);
+ /* execute_ipo((ID *)ob, ipo); */
+ }
+ ob= ob->id.next;
+ }
+ break;
+ case ID_MA:
+ ma= G.main->mat.first;
+ while(ma) {
+ if(ma->ipo==ipo) execute_ipo((ID *)ma, ipo);
+ ma= ma->id.next;
+ }
+ break;
+ case ID_WO:
+ wo= G.main->world.first;
+ while(wo) {
+ if(wo->ipo==ipo) execute_ipo((ID *)wo, ipo);
+ wo= wo->id.next;
+ }
+ break;
+ case ID_LA:
+ la= G.main->lamp.first;
+ while(la) {
+ if(la->ipo==ipo) execute_ipo((ID *)la, ipo);
+ la= la->id.next;
+ }
+ break;
+ case ID_CA:
+ ca= G.main->camera.first;
+ while(ca) {
+ if(ca->ipo==ipo) execute_ipo((ID *)ca, ipo);
+ ca= ca->id.next;
+ }
+ break;
+ case ID_SO:
+ snd= G.main->sound.first;
+ while(snd) {
+ if(snd->ipo==ipo) execute_ipo((ID *)snd, ipo);
+ snd= snd->id.next;
+ }
+ break;
+ }
+}
+
+void do_ipo(Ipo *ipo)
+{
+ if(ipo) {
+ float ctime= frame_to_float(G.scene->r.cfra);
+ calc_ipo(ipo, ctime);
+
+ do_ipo_nocalc(ipo);
+ }
+}
+
+
+
+void do_mat_ipo(Material *ma)
+{
+ float ctime;
+
+ if(ma==0 || ma->ipo==0) return;
+
+ ctime= frame_to_float(G.scene->r.cfra);
+ /* if(ob->ipoflag & OB_OFFS_OB) ctime-= ob->sf; */
+
+ calc_ipo(ma->ipo, ctime);
+
+ execute_ipo((ID *)ma, ma->ipo);
+}
+
+void do_ob_ipo(Object *ob)
+{
+ float ctime;
+ unsigned int lay;
+
+ if(ob->ipo==0) return;
+
+ /* hier NIET ob->ctime zetten: bijv bij parent in onzichtb. layer */
+
+ ctime= bsystem_time(ob, 0, (float) G.scene->r.cfra, 0.0);
+
+ calc_ipo(ob->ipo, ctime);
+
+ /* Patch: de localview onthouden */
+ lay= ob->lay & 0xFF000000;
+
+ execute_ipo((ID *)ob, ob->ipo);
+
+ ob->lay |= lay;
+ if(ob->id.name[2]=='S' && ob->id.name[3]=='C' && ob->id.name[4]=='E') {
+ if(strcmp(G.scene->id.name+2, ob->id.name+6)==0) {
+ G.scene->lay= ob->lay;
+ copy_view3d_lock(0);
+ /* hier geen REDRAW: gaat rondzingen! */
+ }
+ }
+}
+
+void do_seq_ipo(Sequence *seq)
+{
+ float ctime, div;
+
+ /* seq_ipo gaat iets anders: beide fields direkt berekenen */
+
+ if(seq->ipo) {
+ ctime= frame_to_float(G.scene->r.cfra - seq->startdisp);
+ div= (seq->enddisp - seq->startdisp)/100.0f;
+ if(div==0) return;
+
+ /* tweede field */
+ calc_ipo(seq->ipo, (ctime+0.5f)/div);
+ execute_ipo((ID *)seq, seq->ipo);
+ seq->facf1= seq->facf0;
+
+ /* eerste field */
+ calc_ipo(seq->ipo, ctime/div);
+ execute_ipo((ID *)seq, seq->ipo);
+
+ }
+ else seq->facf1= seq->facf0= 1.0f;
+}
+
+int has_ipo_code(Ipo *ipo, int code)
+{
+ IpoCurve *icu;
+
+ if(ipo==0) return 0;
+
+ icu= ipo->curve.first;
+ while(icu) {
+
+ if(icu->adrcode==code) return 1;
+
+ icu= icu->next;
+ }
+ return 0;
+}
+
+void do_all_ipos()
+{
+ Base *base;
+ Material *ma;
+ World *wo;
+ Ipo *ipo;
+ Lamp *la;
+ Camera *ca;
+ bSound *snd;
+ float ctime;
+ int set;
+
+ ctime= frame_to_float(G.scene->r.cfra);
+
+ ipo= G.main->ipo.first;
+ while(ipo) {
+ if(ipo->id.us && ipo->blocktype!=ID_OB) {
+ calc_ipo(ipo, ctime);
+ }
+ ipo= ipo->id.next;
+ }
+
+ /* NEW: current scene ob ipo's */
+ base= G.scene->base.first;
+ set= 0;
+ while(base) {
+
+ /* Do object ipos */
+ do_constraint_channels(&base->object->constraints, &base->object->constraintChannels, ctime);
+
+ if(base->object->ipo) {
+ /* per object ipo ook de calc_ipo doen: ivm mogelijke timeoffs */
+ do_ob_ipo(base->object);
+ if(base->object->type==OB_MBALL) where_is_object(base->object);
+ }
+ base= base->next;
+
+ if(base==0 && set==0 && G.scene->set) {
+ set= 1;
+ base= G.scene->set->base.first;
+ }
+ }
+
+ ma= G.main->mat.first;
+ while(ma) {
+ if(ma->ipo) execute_ipo((ID *)ma, ma->ipo);
+ ma= ma->id.next;
+ }
+
+ wo= G.main->world.first;
+ while(wo) {
+ if(wo->ipo) execute_ipo((ID *)wo, wo->ipo);
+ wo= wo->id.next;
+ }
+
+ la= G.main->lamp.first;
+ while(la) {
+ if(la->ipo) execute_ipo((ID *)la, la->ipo);
+ la= la->id.next;
+ }
+
+ ca= G.main->camera.first;
+ while(ca) {
+ if(ca->ipo) execute_ipo((ID *)ca, ca->ipo);
+ ca= ca->id.next;
+ }
+
+ snd= G.main->sound.first;
+ while(snd) {
+ if(snd->ipo) execute_ipo((ID *)snd, snd->ipo);
+ snd= snd->id.next;
+ }
+
+ /* voor het geval dat... LET OP: 2x */
+ base= G.scene->base.first;
+ while(base) {
+
+ /* alleen layer updaten als ipo */
+ if( has_ipo_code(base->object->ipo, OB_LAY) ) {
+ base->lay= base->object->lay;
+ }
+
+ base= base->next;
+ }
+
+ /* voor het geval dat...*/
+ if(G.scene->set) {
+ base= G.scene->set->base.first;
+ while(base) {
+
+ /* alleen layer updaten als ipo */
+ if( has_ipo_code(base->object->ipo, OB_LAY) ) {
+ base->lay= base->object->lay;
+ }
+
+ base= base->next;
+ }
+ }
+}
+
+
+int calc_ipo_spec(Ipo *ipo, int adrcode, float *ctime)
+{
+ IpoCurve *icu;
+
+ if(ipo==0) return 0;
+
+ icu= ipo->curve.first;
+ while(icu) {
+ if(icu->adrcode == adrcode) {
+ if(icu->flag & IPO_LOCK);
+ else calc_icu(icu, *ctime);
+
+ *ctime= icu->curval;
+ return 1;
+ }
+ icu= icu->next;
+ }
+
+ return 0;
+}
+
+
+/* ************************** */
+
+void clear_delta_obipo(Ipo *ipo)
+{
+ Object *ob;
+
+ if(ipo==0) return;
+
+ ob= G.main->object.first;
+ while(ob) {
+ if(ob->id.lib==0) {
+ if(ob->ipo==ipo) {
+ memset(&ob->dloc, 0, 12);
+ memset(&ob->drot, 0, 12);
+ memset(&ob->dsize, 0, 12);
+ }
+ }
+ ob= ob->id.next;
+ }
+}
+
+void add_to_cfra_elem(ListBase *lb, BezTriple *bezt)
+{
+ CfraElem *ce, *cen;
+
+ ce= lb->first;
+ while(ce) {
+
+ if( ce->cfra==bezt->vec[1][0] ) {
+ /* doen ivm dubbele keys */
+ if(bezt->f2 & 1) ce->sel= bezt->f2;
+ return;
+ }
+ else if(ce->cfra > bezt->vec[1][0]) break;
+
+ ce= ce->next;
+ }
+
+ cen= MEM_callocN(sizeof(CfraElem), "add_to_cfra_elem");
+ if(ce) BLI_insertlinkbefore(lb, ce, cen);
+ else BLI_addtail(lb, cen);
+
+ cen->cfra= bezt->vec[1][0];
+ cen->sel= bezt->f2;
+}
+
+
+
+void make_cfra_list(Ipo *ipo, ListBase *elems)
+{
+ IpoCurve *icu;
+ CfraElem *ce;
+ BezTriple *bezt;
+ int a;
+
+ if(ipo->blocktype==ID_OB) {
+ icu= ipo->curve.first;
+ while(icu) {
+ if(icu->flag & IPO_VISIBLE) {
+ switch(icu->adrcode) {
+ case OB_DLOC_X:
+ case OB_DLOC_Y:
+ case OB_DLOC_Z:
+ case OB_DROT_X:
+ case OB_DROT_Y:
+ case OB_DROT_Z:
+ case OB_DSIZE_X:
+ case OB_DSIZE_Y:
+ case OB_DSIZE_Z:
+
+ case OB_LOC_X:
+ case OB_LOC_Y:
+ case OB_LOC_Z:
+ case OB_ROT_X:
+ case OB_ROT_Y:
+ case OB_ROT_Z:
+ case OB_SIZE_X:
+ case OB_SIZE_Y:
+ case OB_SIZE_Z:
+ bezt= icu->bezt;
+ if(bezt) {
+ a= icu->totvert;
+ while(a--) {
+ add_to_cfra_elem(elems, bezt);
+ bezt++;
+ }
+ }
+ break;
+ }
+ }
+ icu= icu->next;
+ }
+ }
+ if(ipo->showkey==0) {
+ /* alle keys deselecteren */
+ ce= elems->first;
+ while(ce) {
+ ce->sel= 0;
+ ce= ce->next;
+ }
+ }
+}
+
+/* *********************** INTERFACE FOR KETSJI ********** */
+
+
+int IPO_GetChannels(Ipo *ipo, IPO_Channel *channels)
+{
+ /* channels is max 32 items, allocated by calling function */
+
+ IpoCurve *icu;
+ int total=0;
+
+ if(ipo==NULL) return 0;
+
+ icu= ipo->curve.first;
+ while(icu) {
+
+ channels[total]= icu->adrcode;
+ total++;
+ if(total>31) break;
+
+ icu= icu->next;
+ }
+
+ return total;
+}
+
+
+
+/* Get the float value for channel 'channel' at time 'ctime' */
+
+float IPO_GetFloatValue(Ipo *ipo, IPO_Channel channel, float ctime)
+{
+ if(ipo==NULL) return 0;
+
+ calc_ipo_spec(ipo, channel, &ctime);
+
+ if (OB_ROT_X <= channel && channel <= OB_DROT_Z) {
+ ctime *= (float)(M_PI_2/9.0);
+ }
+
+ return ctime;
+}
+
+
+void test_ipo_get()
+{
+ Object *ob;
+ int tot;
+ IPO_Channel chan[32];
+
+ ob = (G.scene->basact ? G.scene->basact->object : 0);
+
+ if(ob==NULL) return;
+ if(ob->ipo==NULL) return;
+
+ tot= IPO_GetChannels(ob->ipo, chan);
+ printf("tot %d \n", tot);
+
+ while(tot--) {
+ printf("var1 %d \n", chan[tot]);
+ }
+
+ printf("var1 %f \n", IPO_GetFloatValue(ob->ipo, chan[0], 10.0));
+}
diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c
new file mode 100644
index 00000000000..d3ea2da204b
--- /dev/null
+++ b/source/blender/blenkernel/intern/key.c
@@ -0,0 +1,1212 @@
+
+/* key.c MIXED MODEL
+ *
+ * mei 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 <math.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_key_types.h"
+#include "DNA_ipo_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_lattice_types.h"
+
+#include "BLI_blenlib.h"
+#include "BKE_utildefines.h"
+#include "BKE_bad_level_calls.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_library.h"
+#include "BKE_blender.h"
+#include "BKE_curve.h"
+#include "BKE_object.h"
+#include "BKE_mesh.h"
+#include "BKE_key.h"
+#include "BKE_ipo.h"
+#include "BKE_lattice.h"
+
+
+#define KEY_BPOINT 1
+#define KEY_BEZTRIPLE 2
+
+int slurph_opt= 1;
+
+
+void free_key(Key *key)
+{
+ KeyBlock *kb;
+
+ if(key->ipo) key->ipo->id.us--;
+
+
+ while( (kb= key->block.first) ) {
+
+ if(kb->data) MEM_freeN(kb->data);
+
+ BLI_remlink(&key->block, kb);
+ MEM_freeN(kb);
+ }
+
+}
+
+/* GS reads the memory pointed at in a specific ordering. There are,
+ * however two definitions for it. I have jotted them down here, both,
+ * but I think the first one is actually used. The thing is that
+ * big-endian systems might read this the wrong way round. OTOH, we
+ * constructed the IDs that are read out with this macro explicitly as
+ * well. I expect we'll sort it out soon... */
+
+/* from blendef: */
+#define GS(a) (*((short *)(a)))
+
+/* from misc_util: flip the bytes from x */
+/* #define GS(x) (((unsigned char *)(x))[0] << 8 | ((unsigned char *)(x))[1]) */
+
+Key *add_key(ID *id) /* algemeen */
+{
+ Key *key;
+ char *el;
+
+ key= alloc_libblock(&G.main->key, ID_KE, "Key");
+
+ key->type= KEY_NORMAL;
+ key->from= id;
+
+ if( GS(id->name)==ID_ME) {
+ el= key->elemstr;
+
+ el[0]= 3;
+ el[1]= IPO_FLOAT;
+ el[2]= 0;
+
+ key->elemsize= 12;
+ }
+ else if( GS(id->name)==ID_LT) {
+ el= key->elemstr;
+
+ el[0]= 3;
+ el[1]= IPO_FLOAT;
+ el[2]= 0;
+
+ key->elemsize= 12;
+ }
+ else if( GS(id->name)==ID_CU) {
+ el= key->elemstr;
+
+ el[0]= 4;
+ el[1]= IPO_BPOINT;
+ el[2]= 0;
+
+ key->elemsize= 16;
+ }
+
+ return key;
+}
+
+Key *copy_key(Key *key)
+{
+ Key *keyn;
+ KeyBlock *kbn, *kb;
+
+ if(key==0) return 0;
+
+ keyn= copy_libblock(key);
+
+ keyn->ipo= copy_ipo(key->ipo);
+
+ duplicatelist(&keyn->block, &key->block);
+
+ kb= key->block.first;
+ kbn= keyn->block.first;
+ while(kbn) {
+
+ if(kbn->data) kbn->data= MEM_dupallocN(kbn->data);
+ if( kb==key->refkey ) keyn->refkey= kbn;
+
+ kbn= kbn->next;
+ kb= kb->next;
+ }
+
+ return keyn;
+}
+
+void make_local_key(Key *key)
+{
+
+ /* - zijn er alleen lib users: niet doen
+ * - zijn er alleen locale users: flag zetten
+ * - mixed: copy
+ */
+ if(key==0) return;
+
+ key->id.lib= 0;
+ new_id(0, (ID *)key, 0);
+ make_local_ipo(key->ipo);
+}
+
+
+void sort_keys(Key *key)
+{
+ KeyBlock *kb;
+ int doit=1;
+
+ while(doit) {
+ doit= 0;
+
+ kb= key->block.first;
+ while(kb) {
+ if(kb->next) {
+ if(kb->pos > kb->next->pos) {
+ BLI_remlink(&key->block, kb);
+
+ /* insertlink(lb, prevlink, newlink): newlink komt na prevlink */
+ BLI_insertlink(&key->block, kb->next, kb);
+
+ doit= 1;
+ break;
+ }
+ }
+ kb= kb->next;
+ }
+ }
+
+}
+
+/**************** do the key ****************/
+
+
+void set_four_ipo(float d, float *data, int type)
+{
+ float d2, d3, fc;
+
+ if(type==KEY_LINEAR) {
+ data[0]= 0.0f;
+ data[1]= 1.0f-d;
+ data[2]= d;
+ data[3]= 0.0f;
+ }
+ else {
+ d2= d*d;
+ d3= d2*d;
+
+ if(type==KEY_CARDINAL) {
+
+ fc= 0.71f;
+
+ data[0]= -fc*d3 +2.0f*fc*d2 -fc*d;
+ data[1]= (2.0f-fc)*d3 +(fc-3.0f)*d2 +1.0f;
+ data[2]= (fc-2.0f)*d3 +(3.0f-2.0f*fc)*d2 +fc*d;
+ data[3]= fc*d3 -fc*d2;
+ }
+ else if(type==KEY_BSPLINE) {
+
+ data[0]= -0.1666f*d3 +0.5f*d2 -0.5f*d +0.16666f;
+ data[1]= 0.5f*d3 -d2 +0.6666f;
+ data[2]= -0.5f*d3 +0.5f*d2 +0.5f*d +0.1666f;
+ data[3]= 0.1666f*d3 ;
+ }
+ }
+}
+
+void set_afgeleide_four_ipo(float d, float *data, int type)
+{
+ float d2, fc;
+
+ if(type==KEY_LINEAR) {
+
+ }
+ else {
+ d2= d*d;
+
+ if(type==KEY_CARDINAL) {
+
+ fc= 0.71f;
+
+ data[0]= -3.0f*fc*d2 +4.0f*fc*d -fc;
+ data[1]= 3.0f*(2.0f-fc)*d2 +2.0f*(fc-3.0f)*d;
+ data[2]= 3.0f*(fc-2.0f)*d2 +2.0f*(3.0f-2.0f*fc)*d +fc;
+ data[3]= 3.0f*fc*d2 -2.0f*fc*d;
+ }
+ else if(type==KEY_BSPLINE) {
+
+ data[0]= -0.1666f*3.0f*d2 +d -0.5f;
+ data[1]= 1.5f*d2 -2.0f*d;
+ data[2]= -1.5f*d2 +d +0.5f;
+ data[3]= 0.1666f*3.0f*d2 ;
+ }
+ }
+}
+
+int setkeys(float fac, ListBase *lb, KeyBlock *k[], float *t, int cycl)
+{
+ /* return 1 betekent k[2] is de positie, 0 is interpoleren */
+ KeyBlock *k1, *firstkey;
+ float d, dpos, ofs=0, lastpos, temp, fval[4];
+ short bsplinetype;
+
+ firstkey= lb->first;
+ k1= lb->last;
+ lastpos= k1->pos;
+ dpos= lastpos - firstkey->pos;
+
+ if(fac < firstkey->pos) fac= firstkey->pos;
+ else if(fac > k1->pos) fac= k1->pos;
+
+ k1=k[0]=k[1]=k[2]=k[3]= firstkey;
+ t[0]=t[1]=t[2]=t[3]= k1->pos;
+
+ /* if(fac<0.0 || fac>1.0) return 1; */
+
+ if(k1->next==0) return 1;
+
+ if(cycl) { /* voorsorteren */
+ k[2]= k1->next;
+ k[3]= k[2]->next;
+ if(k[3]==0) k[3]=k1;
+ while(k1) {
+ if(k1->next==0) k[0]=k1;
+ k1=k1->next;
+ }
+ k1= k[1];
+ t[0]= k[0]->pos;
+ t[1]+= dpos;
+ t[2]= k[2]->pos + dpos;
+ t[3]= k[3]->pos + dpos;
+ fac+= dpos;
+ ofs= dpos;
+ if(k[3]==k[1]) {
+ t[3]+= dpos;
+ ofs= 2.0f*dpos;
+ }
+ if(fac<t[1]) fac+= dpos;
+ k1= k[3];
+ }
+ else { /* voorsorteren */
+ /* waarom dit voorsorteren niet eerder gedaan? voor juist interpoleren in begin noodz. */
+ k[2]= k1->next;
+ t[2]= k[2]->pos;
+ k[3]= k[2]->next;
+ if(k[3]==0) k[3]= k[2];
+ t[3]= k[3]->pos;
+ k1= k[3];
+ }
+
+ while( t[2]<fac ) { /* goede plek vinden */
+ if(k1->next==0) {
+ if(cycl) {
+ k1= firstkey;
+ ofs+= dpos;
+ }
+ else if(t[2]==t[3]) break;
+ }
+ else k1= k1->next;
+
+ t[0]= t[1];
+ k[0]= k[1];
+ t[1]= t[2];
+ k[1]= k[2];
+ t[2]= t[3];
+ k[2]= k[3];
+ t[3]= k1->pos+ofs;
+ k[3]= k1;
+
+ if(ofs>2.1+lastpos) break;
+ }
+
+ bsplinetype= 0;
+ if(k[1]->type==KEY_BSPLINE || k[2]->type==KEY_BSPLINE) bsplinetype= 1;
+
+
+ if(cycl==0) {
+ if(bsplinetype==0) { /* B spline gaat niet door de punten */
+ if(fac<=t[1]) { /* fac voor 1e key */
+ t[2]= t[1];
+ k[2]= k[1];
+ return 1;
+ }
+ if(fac>=t[2] ) { /* fac na 2e key */
+ return 1;
+ }
+ }
+ else if(fac>t[2]) { /* laatste key */
+ fac= t[2];
+ k[3]= k[2];
+ t[3]= t[2];
+ }
+ }
+
+ d= t[2]-t[1];
+ if(d==0.0) {
+ if(bsplinetype==0) {
+ return 1; /* beide keys gelijk */
+ }
+ }
+ else d= (fac-t[1])/d;
+
+ /* interpolatie */
+
+ set_four_ipo(d, t, k[1]->type);
+
+ if(k[1]->type != k[2]->type) {
+ set_four_ipo(d, fval, k[2]->type);
+
+ temp= 1.0f-d;
+ t[0]= temp*t[0]+ d*fval[0];
+ t[1]= temp*t[1]+ d*fval[1];
+ t[2]= temp*t[2]+ d*fval[2];
+ t[3]= temp*t[3]+ d*fval[3];
+ }
+
+ return 0;
+
+}
+
+void flerp(int aantal, float *in, float *f0, float *f1, float *f2, float *f3, float *t)
+{
+ int a;
+
+ for(a=0; a<aantal; a++) {
+ in[a]= t[0]*f0[a]+t[1]*f1[a]+t[2]*f2[a]+t[3]*f3[a];
+ }
+}
+
+void cp_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *k, int mode)
+{
+ float ktot = 0.0, kd = 0.0;
+ int elemsize, poinsize = 0, a, *ofsp, ofs[32], flagflo=0;
+ char *k1;
+ char *cp, elemstr[8];
+
+ if(key->from==0) return;
+
+ if( GS(key->from->name)==ID_ME ) {
+ ofs[0]= sizeof(MVert);
+ ofs[1]= 0;
+ poinsize= ofs[0];
+ }
+ else if( GS(key->from->name)==ID_LT ) {
+ ofs[0]= sizeof(BPoint);
+ ofs[1]= 0;
+ poinsize= ofs[0];
+ }
+ else if( GS(key->from->name)==ID_CU ) {
+ if(mode==KEY_BPOINT) ofs[0]= sizeof(BPoint);
+ else ofs[0]= sizeof(BezTriple);
+
+ ofs[1]= 0;
+ poinsize= ofs[0];
+ }
+
+
+ if(end>tot) end= tot;
+
+ k1= k->data;
+
+ if(tot != k->totelem) {
+ ktot= 0.0;
+ flagflo= 1;
+ if(k->totelem) {
+ kd= k->totelem/(float)tot;
+ }
+ else return;
+ }
+
+ /* deze uitzondering is om slurphing mogelijk te maken */
+ if(start!=0) {
+
+ poin+= poinsize*start;
+
+ if(flagflo) {
+ ktot+= start*kd;
+ a= (int)floor(ktot);
+ if(a) {
+ ktot-= a;
+ k1+= a*key->elemsize;
+ }
+ }
+ else k1+= start*key->elemsize;
+ }
+
+
+ if(mode==KEY_BEZTRIPLE) {
+ elemstr[0]= 1;
+ elemstr[1]= IPO_BEZTRIPLE;
+ elemstr[2]= 0;
+ }
+
+ /* alleen in dit stuk, hierboven niet! */
+ elemsize= key->elemsize;
+ if(mode==KEY_BEZTRIPLE) elemsize*= 3;
+
+ for(a=start; a<end; a++) {
+ cp= key->elemstr;
+ if(mode==KEY_BEZTRIPLE) cp= elemstr;
+
+ ofsp= ofs;
+
+ while( cp[0] ) {
+
+ switch(cp[1]) {
+ case IPO_FLOAT:
+
+ memcpy(poin, k1, 4*cp[0]);
+ poin+= ofsp[0];
+
+ break;
+ case IPO_BPOINT:
+ memcpy(poin, k1, 3*4);
+ memcpy(poin+16, k1+12, 4);
+
+ poin+= ofsp[0];
+
+ break;
+ case IPO_BEZTRIPLE:
+ memcpy(poin, k1, 4*12);
+ poin+= ofsp[0];
+
+ break;
+ }
+
+ cp+= 2; ofsp++;
+ }
+
+ /* gaan we moeilijk doen */
+ if(flagflo) {
+ ktot+= kd;
+ while(ktot>=1.0) {
+ ktot-= 1.0;
+ k1+= elemsize;
+ }
+ }
+ else k1+= elemsize;
+
+ if(mode==KEY_BEZTRIPLE) a+=2;
+ }
+}
+
+void cp_cu_key(Curve *cu, KeyBlock *kb, int start, int end)
+{
+ Nurb *nu;
+ int a, step = 0, tot, a1, a2;
+ char *poin;
+
+ tot= count_curveverts(&cu->nurb);
+ nu= cu->nurb.first;
+ a= 0;
+ while(nu) {
+ if(nu->bp) {
+
+ step= nu->pntsu*nu->pntsv;
+
+ /* uitzondering omdat keys graag met volledige blokken werken */
+ poin= (char *)nu->bp->vec;
+ poin -= a*sizeof(BPoint);
+
+ a1= MAX2(a, start);
+ a2= MIN2(a+step, end);
+
+ if(a1<a2) cp_key(a1, a2, tot, poin, cu->key, kb, KEY_BPOINT);
+ }
+ else if(nu->bezt) {
+
+ step= 3*nu->pntsu;
+
+ poin= (char *)nu->bezt->vec;
+ poin -= a*sizeof(BezTriple);
+
+ a1= MAX2(a, start);
+ a2= MIN2(a+step, end);
+
+ if(a1<a2) cp_key(a1, a2, tot, poin, cu->key, kb, KEY_BEZTRIPLE);
+
+ }
+ a+= step;
+ nu=nu->next;
+ }
+}
+
+
+void rel_flerp(int aantal, float *in, float *ref, float *out, float fac)
+{
+ int a;
+
+ for(a=0; a<aantal; a++) {
+ in[a]-= fac*(ref[a]-out[a]);
+ }
+}
+
+
+
+void do_rel_key(int start, int end, int tot, char *basispoin, Key *key, float ctime, int mode)
+{
+ KeyBlock *kb;
+ IpoCurve *icu;
+ float fac[32], fval;
+ int *ofsp, ofs[3], elemsize, a, b;
+ char *cp, *poin, *reffrom, *from, elemstr[8];
+
+ if(key->from==0) return;
+ if(key->ipo==0) return;
+
+ if( GS(key->from->name)==ID_ME ) {
+ ofs[0]= sizeof(MVert);
+ ofs[1]= 0;
+ }
+ else if( GS(key->from->name)==ID_LT ) {
+ ofs[0]= sizeof(BPoint);
+ ofs[1]= 0;
+ }
+ else if( GS(key->from->name)==ID_CU ) {
+ if(mode==KEY_BPOINT) ofs[0]= sizeof(BPoint);
+ else ofs[0]= sizeof(BezTriple);
+
+ ofs[1]= 0;
+ }
+
+ if(end>tot) end= tot;
+
+ /* in geval beztriple */
+ elemstr[0]= 1; /* aantal ipofloats */
+ elemstr[1]= IPO_BEZTRIPLE;
+ elemstr[2]= 0;
+
+ /* alleen in dit stuk, hierboven niet! */
+ elemsize= key->elemsize;
+ if(mode==KEY_BEZTRIPLE) elemsize*= 3;
+
+ /* step one: fetch ipo values */
+ icu= key->ipo->curve.first;
+ for(a=0; a<KEY_TOTIPO; a++) fac[a]= 0.0;
+ while(icu) {
+ fac[icu->adrcode]= icu->curval;
+ icu= icu->next;
+ }
+
+ /* step 2 init */
+ cp_key(start, end, tot, basispoin, key, key->refkey, mode);
+
+ /* step 3: do it */
+
+ a= 1;
+ kb= key->block.first;
+ while(kb) {
+
+ if(kb!=key->refkey) {
+ fval= fac[a];
+ a++;
+ if(a==32) break;
+
+ /* no difference allowed */
+ if(kb->totelem==tot) {
+
+ poin= basispoin;
+ reffrom= key->refkey->data;
+ from= kb->data;
+
+ poin+= start*ofs[0];
+ reffrom+= elemsize*start;
+ from+= elemsize*start;
+
+ for(b=start; b<end; b++) {
+
+ cp= key->elemstr;
+ if(mode==KEY_BEZTRIPLE) cp= elemstr;
+
+ ofsp= ofs;
+
+ while( cp[0] ) { /* cp[0]==aantal */
+
+ switch(cp[1]) {
+ case IPO_FLOAT:
+ rel_flerp(cp[0], (float *)poin, (float *)reffrom, (float *)from, fval);
+
+ break;
+ case IPO_BPOINT:
+ rel_flerp(3, (float *)poin, (float *)reffrom, (float *)from, fval);
+ rel_flerp(1, (float *)(poin+16), (float *)(reffrom+16), (float *)(from+16), fval);
+
+ break;
+ case IPO_BEZTRIPLE:
+ rel_flerp(9, (float *)poin, (float *)reffrom, (float *)from, fval);
+
+ break;
+ }
+
+ poin+= ofsp[0];
+
+ cp+= 2;
+ ofsp++;
+ }
+
+ reffrom+= elemsize;
+ from+= elemsize;
+
+ }
+ }
+ }
+ kb= kb->next;
+ }
+}
+
+
+void do_key(int start, int end, int tot, char *poin, Key *key, KeyBlock **k, float *t, int mode)
+{
+ float k1tot = 0.0, k2tot = 0.0, k3tot = 0.0, k4tot = 0.0;
+ float k1d = 0.0, k2d = 0.0, k3d = 0.0, k4d = 0.0;
+ int a, ofs[32], *ofsp;
+ int flagdo= 15, flagflo=0, elemsize, poinsize=0;
+ char *k1, *k2, *k3, *k4;
+ char *cp, elemstr[8];;
+
+ if(key->from==0) return;
+
+ if( GS(key->from->name)==ID_ME ) {
+ ofs[0]= sizeof(MVert);
+ ofs[1]= 0;
+ poinsize= ofs[0];
+ }
+ else if( GS(key->from->name)==ID_LT ) {
+ ofs[0]= sizeof(BPoint);
+ ofs[1]= 0;
+ poinsize= ofs[0];
+ }
+ else if( GS(key->from->name)==ID_CU ) {
+ if(mode==KEY_BPOINT) ofs[0]= sizeof(BPoint);
+ else ofs[0]= sizeof(BezTriple);
+
+ ofs[1]= 0;
+ poinsize= ofs[0];
+ }
+
+ if(end>tot) end= tot;
+
+ k1= k[0]->data;
+ k2= k[1]->data;
+ k3= k[2]->data;
+ k4= k[3]->data;
+
+ /* testen op meer of minder punten (per key!) */
+ if(tot != k[0]->totelem) {
+ k1tot= 0.0;
+ flagflo |= 1;
+ if(k[0]->totelem) {
+ k1d= k[0]->totelem/(float)tot;
+ }
+ else flagdo -= 1;
+ }
+ if(tot != k[1]->totelem) {
+ k2tot= 0.0;
+ flagflo |= 2;
+ if(k[0]->totelem) {
+ k2d= k[1]->totelem/(float)tot;
+ }
+ else flagdo -= 2;
+ }
+ if(tot != k[2]->totelem) {
+ k3tot= 0.0;
+ flagflo |= 4;
+ if(k[0]->totelem) {
+ k3d= k[2]->totelem/(float)tot;
+ }
+ else flagdo -= 4;
+ }
+ if(tot != k[3]->totelem) {
+ k4tot= 0.0;
+ flagflo |= 8;
+ if(k[0]->totelem) {
+ k4d= k[3]->totelem/(float)tot;
+ }
+ else flagdo -= 8;
+ }
+
+ /* deze uitzondering is om slurphing mogelijk te maken */
+ if(start!=0) {
+
+ poin+= poinsize*start;
+
+ if(flagdo & 1) {
+ if(flagflo & 1) {
+ k1tot+= start*k1d;
+ a= (int)floor(k1tot);
+ if(a) {
+ k1tot-= a;
+ k1+= a*key->elemsize;
+ }
+ }
+ else k1+= start*key->elemsize;
+ }
+ if(flagdo & 2) {
+ if(flagflo & 2) {
+ k2tot+= start*k2d;
+ a= (int)floor(k2tot);
+ if(a) {
+ k2tot-= a;
+ k2+= a*key->elemsize;
+ }
+ }
+ else k2+= start*key->elemsize;
+ }
+ if(flagdo & 4) {
+ if(flagflo & 4) {
+ k3tot+= start*k3d;
+ a= (int)floor(k3tot);
+ if(a) {
+ k3tot-= a;
+ k3+= a*key->elemsize;
+ }
+ }
+ else k3+= start*key->elemsize;
+ }
+ if(flagdo & 8) {
+ if(flagflo & 8) {
+ k4tot+= start*k4d;
+ a= (int)floor(k4tot);
+ if(a) {
+ k4tot-= a;
+ k4+= a*key->elemsize;
+ }
+ }
+ else k4+= start*key->elemsize;
+ }
+
+ }
+
+ /* in geval beztriple */
+ elemstr[0]= 1; /* aantal ipofloats */
+ elemstr[1]= IPO_BEZTRIPLE;
+ elemstr[2]= 0;
+
+ /* alleen in dit stuk, hierboven niet! */
+ elemsize= key->elemsize;
+ if(mode==KEY_BEZTRIPLE) elemsize*= 3;
+
+ for(a=start; a<end; a++) {
+
+ cp= key->elemstr;
+ if(mode==KEY_BEZTRIPLE) cp= elemstr;
+
+ ofsp= ofs;
+
+ while( cp[0] ) { /* cp[0]==aantal */
+
+ switch(cp[1]) {
+ case IPO_FLOAT:
+ flerp(cp[0], (float *)poin, (float *)k1, (float *)k2, (float *)k3, (float *)k4, t);
+ poin+= ofsp[0];
+
+ break;
+ case IPO_BPOINT:
+ flerp(3, (float *)poin, (float *)k1, (float *)k2, (float *)k3, (float *)k4, t);
+ flerp(1, (float *)(poin+16), (float *)(k1+12), (float *)(k2+12), (float *)(k3+12), (float *)(k4+12), t);
+
+ poin+= ofsp[0];
+
+ break;
+ case IPO_BEZTRIPLE:
+ flerp(9, (void *)poin, (void *)k1, (void *)k2, (void *)k3, (void *)k4, t);
+ poin+= ofsp[0];
+
+ break;
+ }
+
+
+ cp+= 2;
+ ofsp++;
+ }
+ /* gaan we moeilijk doen: als keys van lengte verschillen */
+ if(flagdo & 1) {
+ if(flagflo & 1) {
+ k1tot+= k1d;
+ while(k1tot>=1.0) {
+ k1tot-= 1.0;
+ k1+= elemsize;
+ }
+ }
+ else k1+= elemsize;
+ }
+ if(flagdo & 2) {
+ if(flagflo & 2) {
+ k2tot+= k2d;
+ while(k2tot>=1.0) {
+ k2tot-= 1.0;
+ k2+= elemsize;
+ }
+ }
+ else k2+= elemsize;
+ }
+ if(flagdo & 4) {
+ if(flagflo & 4) {
+ k3tot+= k3d;
+ while(k3tot>=1.0) {
+ k3tot-= 1.0;
+ k3+= elemsize;
+ }
+ }
+ else k3+= elemsize;
+ }
+ if(flagdo & 8) {
+ if(flagflo & 8) {
+ k4tot+= k4d;
+ while(k4tot>=1.0) {
+ k4tot-= 1.0;
+ k4+= elemsize;
+ }
+ }
+ else k4+= elemsize;
+ }
+
+ if(mode==KEY_BEZTRIPLE) a+= 2;
+ }
+}
+
+
+
+void do_mesh_key(Mesh *me)
+{
+ KeyBlock *k[4];
+ float cfra, ctime, t[4], delta, loc[3], size[3];
+ int a, flag = 0, step;
+
+ if(me->totvert==0) return;
+ if(me->key==0) return;
+ if(me->key->block.first==0) return;
+
+ if(me->key->slurph && me->key->type!=KEY_RELATIVE ) {
+ delta= me->key->slurph;
+ delta/= me->totvert;
+
+ step= 1;
+ if(me->totvert>100 && slurph_opt) {
+ step= me->totvert/50;
+ delta*= step;
+ /* in do_key en cp_key wordt a>tot afgevangen */
+ }
+
+ cfra= G.scene->r.cfra;
+
+ for(a=0; a<me->totvert; a+=step, cfra+= delta) {
+
+ ctime= bsystem_time(0, 0, cfra, 0.0);
+ if(calc_ipo_spec(me->key->ipo, KEY_SPEED, &ctime)==0) {
+ ctime /= 100.0;
+ CLAMP(ctime, 0.0, 1.0);
+ }
+
+ flag= setkeys(ctime, &me->key->block, k, t, 0);
+ if(flag==0) {
+
+ do_key(a, a+step, me->totvert, (char *)me->mvert->co, me->key, k, t, 0);
+ }
+ else {
+ cp_key(a, a+step, me->totvert, (char *)me->mvert->co, me->key, k[2], 0);
+ }
+ }
+
+ if(flag && k[2]==me->key->refkey) tex_space_mesh(me);
+ else boundbox_mesh(me, loc, size);
+
+ }
+ else {
+
+ ctime= bsystem_time(0, 0, (float)G.scene->r.cfra, 0.0);
+ if(calc_ipo_spec(me->key->ipo, KEY_SPEED, &ctime)==0) {
+ ctime /= 100.0;
+ CLAMP(ctime, 0.0, 1.0);
+ }
+
+ if(me->key->type==KEY_RELATIVE) {
+ do_rel_key(0, me->totvert, me->totvert, (char *)me->mvert->co, me->key, ctime, 0);
+ }
+ else {
+ flag= setkeys(ctime, &me->key->block, k, t, 0);
+ if(flag==0) {
+
+ do_key(0, me->totvert, me->totvert, (char *)me->mvert->co, me->key, k, t, 0);
+ }
+ else {
+ cp_key(0, me->totvert, me->totvert, (char *)me->mvert->co, me->key, k[2], 0);
+
+ }
+
+ if(flag && k[2]==me->key->refkey) tex_space_mesh(me);
+ else boundbox_mesh(me, loc, size);
+ }
+ }
+}
+
+void do_cu_key(Curve *cu, KeyBlock **k, float *t)
+{
+ Nurb *nu;
+ int a, step = 0, tot;
+ char *poin;
+
+ tot= count_curveverts(&cu->nurb);
+ nu= cu->nurb.first;
+ a= 0;
+ while(nu) {
+ if(nu->bp) {
+
+ step= nu->pntsu*nu->pntsv;
+
+ /* uitzondering omdat keys graag met volledige blokken werken */
+ poin= (char *)nu->bp->vec;
+ poin -= a*sizeof(BPoint);
+
+ do_key(a, a+step, tot, poin, cu->key, k, t, KEY_BPOINT);
+ }
+ else if(nu->bezt) {
+
+ step= 3*nu->pntsu;
+
+ poin= (char *)nu->bezt->vec;
+ poin -= a*sizeof(BezTriple);
+
+ do_key(a, a+step, tot, poin, cu->key, k, t, KEY_BEZTRIPLE);
+
+ }
+ a+= step;
+ nu=nu->next;
+ }
+}
+
+void do_rel_cu_key(Curve *cu, float ctime)
+{
+ Nurb *nu;
+ int a, step = 0, tot;
+ char *poin;
+
+ tot= count_curveverts(&cu->nurb);
+ nu= cu->nurb.first;
+ a= 0;
+ while(nu) {
+ if(nu->bp) {
+
+ step= nu->pntsu*nu->pntsv;
+
+ /* uitzondering omdat keys graag met volledige blokken werken */
+ poin= (char *)nu->bp->vec;
+ poin -= a*sizeof(BPoint);
+
+ do_rel_key(a, a+step, tot, poin, cu->key, ctime, KEY_BPOINT);
+ }
+ else if(nu->bezt) {
+
+ step= 3*nu->pntsu;
+
+ poin= (char *)nu->bezt->vec;
+ poin -= a*sizeof(BezTriple);
+
+ do_rel_key(a, a+step, tot, poin, cu->key, ctime, KEY_BEZTRIPLE);
+
+ }
+ a+= step;
+ nu=nu->next;
+ }
+}
+
+void do_curve_key(Curve *cu)
+{
+ KeyBlock *k[4];
+ float cfra, ctime, t[4], delta;
+ int a, flag = 0, step = 0, tot;
+
+ tot= count_curveverts(&cu->nurb);
+
+ if(tot==0) return;
+ if(cu->key==0) return;
+ if(cu->key->block.first==0) return;
+
+ if(cu->key->slurph) {
+ delta= cu->key->slurph;
+ delta/= tot;
+
+ step= 1;
+ if(tot>100 && slurph_opt) {
+ step= tot/50;
+ delta*= step;
+ /* in do_key en cp_key wordt a>tot afgevangen */
+ }
+
+ cfra= G.scene->r.cfra;
+
+ for(a=0; a<tot; a+=step, cfra+= delta) {
+
+ ctime= bsystem_time(0, 0, cfra, 0.0);
+ if(calc_ipo_spec(cu->key->ipo, KEY_SPEED, &ctime)==0) {
+ ctime /= 100.0;
+ CLAMP(ctime, 0.0, 1.0);
+ }
+
+ flag= setkeys(ctime, &cu->key->block, k, t, 0);
+ if(flag==0) {
+
+ /* do_key(a, a+step, tot, (char *)cu->mvert->co, cu->key, k, t, 0); */
+ }
+ else {
+ /* cp_key(a, a+step, tot, (char *)cu->mvert->co, cu->key, k[2],0); */
+ }
+ }
+
+ if(flag && k[2]==cu->key->refkey) tex_space_curve(cu);
+
+
+ }
+ else {
+
+ ctime= bsystem_time(0, 0, (float)G.scene->r.cfra, 0.0);
+ if(calc_ipo_spec(cu->key->ipo, KEY_SPEED, &ctime)==0) {
+ ctime /= 100.0;
+ CLAMP(ctime, 0.0, 1.0);
+ }
+
+ if(cu->key->type==KEY_RELATIVE) {
+ do_rel_cu_key(cu, ctime);
+ }
+ else {
+ flag= setkeys(ctime, &cu->key->block, k, t, 0);
+
+ if(flag==0) do_cu_key(cu, k, t);
+ else cp_cu_key(cu, k[2], 0, tot);
+
+ if(flag && k[2]==cu->key->refkey) tex_space_curve(cu);
+ }
+ }
+}
+
+void do_latt_key(Lattice *lt)
+{
+ KeyBlock *k[4];
+ float delta, cfra, ctime, t[4];
+ int a, tot, flag;
+
+ if(lt->key==0) return;
+ if(lt->key->block.first==0) return;
+
+ tot= lt->pntsu*lt->pntsv*lt->pntsw;
+
+ if(lt->key->slurph) {
+ delta= lt->key->slurph;
+ delta/= (float)tot;
+
+ cfra= G.scene->r.cfra;
+
+ for(a=0; a<tot; a++, cfra+= delta) {
+
+ ctime= bsystem_time(0, 0, cfra, 0.0);
+ if(calc_ipo_spec(lt->key->ipo, KEY_SPEED, &ctime)==0) {
+ ctime /= 100.0;
+ CLAMP(ctime, 0.0, 1.0);
+ }
+
+ flag= setkeys(ctime, &lt->key->block, k, t, 0);
+ if(flag==0) {
+
+ do_key(a, a+1, tot, (char *)lt->def->vec, lt->key, k, t, 0);
+ }
+ else {
+ cp_key(a, a+1, tot, (char *)lt->def->vec, lt->key, k[2], 0);
+ }
+ }
+ }
+ else {
+ ctime= bsystem_time(0, 0, (float)G.scene->r.cfra, 0.0);
+ if(calc_ipo_spec(lt->key->ipo, KEY_SPEED, &ctime)==0) {
+ ctime /= 100.0;
+ CLAMP(ctime, 0.0, 1.0);
+ }
+
+ if(lt->key->type==KEY_RELATIVE) {
+ do_rel_key(0, tot, tot, (char *)lt->def->vec, lt->key, ctime, 0);
+ }
+ else {
+
+ flag= setkeys(ctime, &lt->key->block, k, t, 0);
+ if(flag==0) {
+ do_key(0, tot, tot, (char *)lt->def->vec, lt->key, k, t, 0);
+ }
+ else {
+ cp_key(0, tot, tot, (char *)lt->def->vec, lt->key, k[2], 0);
+ }
+ }
+ }
+
+ if(lt->flag & LT_OUTSIDE) outside_lattice(lt);
+}
+
+
+
+void do_all_keys()
+{
+ Key *key;
+ int idcode;
+
+ key= G.main->key.first;
+ while(key) {
+ if(key->from) {
+ idcode= GS(key->from->name);
+
+ if(idcode==ID_ME) do_mesh_key( (Mesh *)key->from);
+ else if(idcode==ID_CU) do_curve_key( (Curve *)key->from);
+ else if(idcode==ID_LT) do_latt_key( (Lattice *)key->from);
+ }
+ key= key->id.next;
+ }
+}
+
+void do_ob_key(Object *ob)
+{
+ if(ob->type==OB_MESH) do_mesh_key( ob->data);
+ else if(ob->type==OB_CURVE) do_curve_key( ob->data);
+ else if(ob->type==OB_SURF) do_curve_key( ob->data);
+ else if(ob->type==OB_LATTICE) do_latt_key( ob->data);
+}
+
+void do_spec_key(Key *key)
+{
+ int idcode;
+
+ if(key==0) return;
+
+ idcode= GS(key->from->name);
+
+ if(idcode==ID_ME) do_mesh_key( (Mesh *)key->from);
+ else if(idcode==ID_CU) do_curve_key( (Curve *)key->from);
+ else if(idcode==ID_LT) do_latt_key( (Lattice *)key->from);
+
+}
diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c
new file mode 100644
index 00000000000..a6895d2a8ea
--- /dev/null
+++ b/source/blender/blenkernel/intern/lattice.c
@@ -0,0 +1,633 @@
+/**
+ * lattice.c MIXED MODEL
+ * june 2001 ton
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 <string.h>
+#include <math.h>
+#include <stdlib.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_lattice_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_key_types.h"
+#include "DNA_ika_types.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_armature.h"
+#include "BKE_library.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_screen.h"
+#include "BKE_displist.h"
+#include "BKE_lattice.h"
+#include "BKE_key.h"
+#include "BKE_object.h"
+#include "BKE_ika.h"
+
+Lattice *editLatt=0, *deformLatt=0;
+
+float *latticedata=0, latmat[4][4];
+int lt_applyflag= 0;
+
+void resizelattice(Lattice *lt)
+{
+ BPoint *bp;
+ int u, v, w;
+ float vec[3], fu, fv, fw, du=0.0, dv=0.0, dw=0.0;
+
+
+ MEM_freeN(lt->def);
+ lt->def= MEM_callocN(lt->pntsu*lt->pntsv*lt->pntsw*sizeof(BPoint), "lattice bp");
+
+ bp= lt->def;
+
+ while(lt->pntsu*lt->pntsv*lt->pntsw > 32000) {
+ if( lt->pntsu>=lt->pntsv && lt->pntsu>=lt->pntsw) lt->pntsu--;
+ else if( lt->pntsv>=lt->pntsu && lt->pntsv>=lt->pntsw) lt->pntsv--;
+ else lt->pntsw--;
+ }
+
+ calc_lat_fudu(lt->flag, lt->pntsu, &fu, &du);
+ calc_lat_fudu(lt->flag, lt->pntsv, &fv, &dv);
+ calc_lat_fudu(lt->flag, lt->pntsw, &fw, &dw);
+
+ vec[2]= fw;
+ for(w=0; w<lt->pntsw; w++) {
+ vec[1]= fv;
+ for(v=0; v<lt->pntsv; v++) {
+ vec[0]= fu;
+ for(u=0; u<lt->pntsu; u++, bp++) {
+ VECCOPY(bp->vec, vec);
+ vec[0]+= du;
+ }
+ vec[1]+= dv;
+ }
+ vec[2]+= dw;
+ }
+}
+
+Lattice *add_lattice()
+{
+ Lattice *lt;
+
+ lt= alloc_libblock(&G.main->latt, ID_LT, "Lattice");
+
+ lt->pntsu=lt->pntsv=lt->pntsw= 2;
+ lt->flag= LT_GRID;
+
+ lt->typeu= lt->typev= lt->typew= KEY_BSPLINE;
+
+ /* tijdelijk */
+ lt->def= MEM_callocN(sizeof(BPoint), "lattvert");
+
+ resizelattice(lt); /* maakt een regelmatige lattice */
+
+ return lt;
+}
+
+Lattice *copy_lattice(Lattice *lt)
+{
+ Lattice *ltn;
+
+ ltn= copy_libblock(lt);
+ ltn->def= MEM_dupallocN(lt->def);
+
+ id_us_plus((ID *)ltn->ipo);
+
+ ltn->key= copy_key(ltn->key);
+ if(ltn->key) ltn->key->from= (ID *)ltn;
+
+ return ltn;
+}
+
+void free_lattice(Lattice *lt)
+{
+ if(lt->def) MEM_freeN(lt->def);
+}
+
+
+void make_local_lattice(Lattice *lt)
+{
+ Object *ob;
+ Lattice *ltn;
+ int local=0, lib=0;
+
+ /* - zijn er alleen lib users: niet doen
+ * - zijn er alleen locale users: flag zetten
+ * - mixed: copy
+ */
+
+ if(lt->id.lib==0) return;
+ if(lt->id.us==1) {
+ lt->id.lib= 0;
+ lt->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)lt, 0);
+ return;
+ }
+
+ ob= G.main->object.first;
+ while(ob) {
+ if(ob->data==lt) {
+ if(ob->id.lib) lib= 1;
+ else local= 1;
+ }
+ ob= ob->id.next;
+ }
+
+ if(local && lib==0) {
+ lt->id.lib= 0;
+ lt->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)lt, 0);
+ }
+ else if(local && lib) {
+ ltn= copy_lattice(lt);
+ ltn->id.us= 0;
+
+ ob= G.main->object.first;
+ while(ob) {
+ if(ob->data==lt) {
+
+ if(ob->id.lib==0) {
+ ob->data= ltn;
+ ltn->id.us++;
+ lt->id.us--;
+ }
+ }
+ ob= ob->id.next;
+ }
+ }
+}
+
+
+
+void calc_lat_fudu(int flag, int res, float *fu, float *du)
+{
+
+ if(res==1) {
+ *fu= 0.0;
+ *du= 0.0;
+ }
+ else if(flag & LT_GRID) {
+ *fu= -0.5f*(res-1);
+ *du= 1.0f;
+ }
+ else {
+ *fu= -1.0f;
+ *du= 2.0f/(res-1);
+ }
+
+}
+
+void init_latt_deform(Object *oblatt, Object *ob)
+{
+ /* we maken een array met alle verschillen */
+ BPoint *bp;
+ float *fp, imat[4][4];
+ float vec[3], fu, fv, fw, du=0.0, dv=0.0, dw=0.0;
+ int u, v, w;
+
+ if(oblatt==G.obedit) deformLatt= editLatt;
+ else deformLatt= oblatt->data;
+
+ fp= latticedata= MEM_mallocN(sizeof(float)*3*deformLatt->pntsu*deformLatt->pntsv*deformLatt->pntsw, "latticedata");
+
+ bp= deformLatt->def;
+
+ if(ob) where_is_object(ob);
+
+ /* bijv bij particle systeem: ob==0 */
+ if(ob==0) {
+ /* in deformspace, matrix berekenen */
+ Mat4Invert(latmat, oblatt->obmat);
+
+ /* terug: in deform array verwerken */
+ Mat4Invert(imat, latmat);
+ }
+ else {
+ /* in deformspace, matrix berekenen */
+ Mat4Invert(imat, oblatt->obmat);
+ Mat4MulMat4(latmat, ob->obmat, imat);
+
+ /* terug: in deform array verwerken */
+ Mat4Invert(imat, latmat);
+ }
+ calc_lat_fudu(deformLatt->flag, deformLatt->pntsu, &fu, &du);
+ calc_lat_fudu(deformLatt->flag, deformLatt->pntsv, &fv, &dv);
+ calc_lat_fudu(deformLatt->flag, deformLatt->pntsw, &fw, &dw);
+
+ /* we berekenen hier steeds de u v w lattice coordinaten, weinig reden ze te onthouden */
+
+ vec[2]= fw;
+ for(w=0; w<deformLatt->pntsw; w++) {
+ vec[1]= fv;
+ for(v=0; v<deformLatt->pntsv; v++) {
+ vec[0]= fu;
+ for(u=0; u<deformLatt->pntsu; u++, bp++) {
+
+ VecSubf(fp, bp->vec, vec);
+ Mat4Mul3Vecfl(imat, fp);
+
+ vec[0]+= du;
+ fp+= 3;
+ }
+ vec[1]+= dv;
+ }
+ vec[2]+= dw;
+ }
+}
+
+void calc_latt_deform(float *co)
+{
+ Lattice *lt;
+ float fu, du, u, v, w, tu[4], tv[4], tw[4];
+ float *fpw, *fpv, *fpu, vec[3];
+ int ui, vi, wi, uu, vv, ww;
+
+ if(latticedata==0) return;
+
+ lt= deformLatt; /* kortere notatie! */
+
+ /* co is in lokale coords, met latmat behandelen */
+
+ VECCOPY(vec, co);
+ Mat4MulVecfl(latmat, vec);
+
+ /* u v w coords */
+
+ if(lt->pntsu>1) {
+ calc_lat_fudu(lt->flag, lt->pntsu, &fu, &du);
+ u= (vec[0]-fu)/du;
+ ui= (int)floor(u);
+ u -= ui;
+ set_four_ipo(u, tu, lt->typeu);
+ }
+ else {
+ tu[0]= tu[2]= tu[3]= 0.0; tu[1]= 1.0;
+ ui= 0;
+ }
+
+ if(lt->pntsv>1) {
+ calc_lat_fudu(lt->flag, lt->pntsv, &fu, &du);
+ v= (vec[1]-fu)/du;
+ vi= (int)floor(v);
+ v -= vi;
+ set_four_ipo(v, tv, lt->typev);
+ }
+ else {
+ tv[0]= tv[2]= tv[3]= 0.0; tv[1]= 1.0;
+ vi= 0;
+ }
+
+ if(lt->pntsw>1) {
+ calc_lat_fudu(lt->flag, lt->pntsw, &fu, &du);
+ w= (vec[2]-fu)/du;
+ wi= (int)floor(w);
+ w -= wi;
+ set_four_ipo(w, tw, lt->typew);
+ }
+ else {
+ tw[0]= tw[2]= tw[3]= 0.0; tw[1]= 1.0;
+ wi= 0;
+ }
+
+ for(ww= wi-1; ww<=wi+2; ww++) {
+ w= tw[ww-wi+1];
+
+ if(w!=0.0) {
+ if(ww>0) {
+ if(ww<lt->pntsw) fpw= latticedata + 3*ww*lt->pntsu*lt->pntsv;
+ else fpw= latticedata + 3*(lt->pntsw-1)*lt->pntsu*lt->pntsv;
+ }
+ else fpw= latticedata;
+
+ for(vv= vi-1; vv<=vi+2; vv++) {
+ v= w*tv[vv-vi+1];
+
+ if(v!=0.0) {
+ if(vv>0) {
+ if(vv<lt->pntsv) fpv= fpw + 3*vv*lt->pntsu;
+ else fpv= fpw + 3*(lt->pntsv-1)*lt->pntsu;
+ }
+ else fpv= fpw;
+
+ for(uu= ui-1; uu<=ui+2; uu++) {
+ u= v*tu[uu-ui+1];
+
+ if(u!=0.0) {
+ if(uu>0) {
+ if(uu<lt->pntsu) fpu= fpv + 3*uu;
+ else fpu= fpv + 3*(lt->pntsu-1);
+ }
+ else fpu= fpv;
+
+ co[0]+= u*fpu[0];
+ co[1]+= u*fpu[1];
+ co[2]+= u*fpu[2];
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+
+void end_latt_deform()
+{
+
+ MEM_freeN(latticedata);
+ latticedata= 0;
+}
+
+
+int object_deform(Object *ob)
+{
+ Mesh *me;
+ Curve *cu;
+ DispList *dl;
+ MVert *mvert;
+ float *fp;
+ int a, tot;
+
+ if(ob->parent==0) return 0;
+
+ /* altijd proberen in deze fie de hele deform te doen: apply! */
+
+ if(ob->parent->type==OB_LATTICE) {
+
+ init_latt_deform(ob->parent, ob);
+
+ if(ob->type==OB_MESH) {
+ me= ob->data;
+
+ dl= find_displist_create(&ob->disp, DL_VERTS);
+
+ mvert= me->mvert;
+ if(dl->verts) MEM_freeN(dl->verts);
+ dl->nr= me->totvert;
+ dl->verts= fp= MEM_mallocN(3*sizeof(float)*me->totvert, "deform1");
+
+ for(a=0; a<me->totvert; a++, mvert++, fp+=3) {
+ if(lt_applyflag) calc_latt_deform(mvert->co);
+ else {
+ VECCOPY(fp, mvert->co);
+ calc_latt_deform(fp);
+ }
+ }
+ }
+ else if ELEM(ob->type, OB_CURVE, OB_SURF) {
+
+ cu= ob->data;
+ if(lt_applyflag) {
+ Nurb *nu;
+ BPoint *bp;
+
+ nu= cu->nurb.first;
+ while(nu) {
+ if(nu->bp) {
+ a= nu->pntsu*nu->pntsv;
+ bp= nu->bp;
+ while(a--) {
+ calc_latt_deform(bp->vec);
+ bp++;
+ }
+ }
+ nu= nu->next;
+ }
+ }
+
+ /* when apply, do this too, looks more interactive */
+ dl= cu->disp.first;
+ while(dl) {
+
+ fp= dl->verts;
+
+ if(dl->type==DL_INDEX3) tot=dl->parts;
+ else tot= dl->nr*dl->parts;
+
+ for(a=0; a<tot; a++, fp+=3) {
+ calc_latt_deform(fp);
+ }
+
+ dl= dl->next;
+ }
+ }
+ end_latt_deform();
+
+ boundbox_displist(ob);
+
+ return 1;
+ }
+ else if(ob->parent->type==OB_ARMATURE) {
+ if (ob->partype != PARSKEL){
+ return 0;
+ }
+
+ init_armature_deform (ob->parent, ob);
+
+ switch (ob->type){
+ case OB_MESH:
+ me= ob->data;
+
+ dl= find_displist_create(&ob->disp, DL_VERTS);
+
+ mvert= me->mvert;
+ if(dl->verts) MEM_freeN(dl->verts);
+ dl->nr= me->totvert;
+ dl->verts= fp= MEM_mallocN(3*sizeof(float)*me->totvert, "deform1");
+
+ for(a=0; a<me->totvert; a++, mvert++, fp+=3) {
+ if(lt_applyflag){
+ calc_armature_deform(ob->parent, mvert->co, a);
+ }
+ else {
+ VECCOPY(fp, mvert->co);
+ calc_armature_deform(ob->parent, fp, a);
+ }
+ }
+
+ break;
+ default:
+ break;
+ }
+
+ boundbox_displist(ob);
+ return 1;
+ }
+ else if(ob->parent->type==OB_IKA) {
+
+ Ika *ika;
+
+ if(ob->partype!=PARSKEL) return 0;
+
+ ika= ob->parent->data;
+ if(ika->def==0) return 0;
+
+ init_skel_deform(ob->parent, ob);
+
+ if(ob->type==OB_MESH) {
+ me= ob->data;
+
+ dl= find_displist_create(&ob->disp, DL_VERTS);
+
+ mvert= me->mvert;
+ if(dl->verts) MEM_freeN(dl->verts);
+ dl->nr= me->totvert;
+ dl->verts= fp= MEM_mallocN(3*sizeof(float)*me->totvert, "deform1");
+
+ for(a=0; a<me->totvert; a++, mvert++, fp+=3) {
+ if(lt_applyflag) calc_skel_deform(ika, mvert->co);
+ else {
+ VECCOPY(fp, mvert->co);
+ calc_skel_deform(ika, fp);
+ }
+ }
+ }
+ else if ELEM(ob->type, OB_CURVE, OB_SURF) {
+
+ cu= ob->data;
+ if(lt_applyflag) {
+ Nurb *nu;
+ BPoint *bp;
+
+ nu= cu->nurb.first;
+ while(nu) {
+ if(nu->bp) {
+ a= nu->pntsu*nu->pntsv;
+ bp= nu->bp;
+ while(a--) {
+ calc_skel_deform(ika, bp->vec);
+ bp++;
+ }
+ }
+ nu= nu->next;
+ }
+ }
+
+ /* when apply, do this too, looks more interactive */
+ dl= cu->disp.first;
+ while(dl) {
+
+ fp= dl->verts;
+ tot= dl->nr*dl->parts;
+ for(a=0; a<tot; a++, fp+=3) {
+ calc_skel_deform(ika, fp);
+ }
+
+ dl= dl->next;
+ }
+ }
+
+ boundbox_displist(ob);
+
+ return 1;
+ }
+
+ return 0;
+
+}
+
+BPoint *latt_bp(Lattice *lt, int u, int v, int w)
+{
+ return lt->def+ u + v*lt->pntsu + w*lt->pntsu*lt->pntsv;
+}
+
+void outside_lattice(Lattice *lt)
+{
+ BPoint *bp, *bp1, *bp2;
+ int u, v, w;
+ float fac1, du=0.0, dv=0.0, dw=0.0;
+
+ bp= lt->def;
+
+ if(lt->pntsu>1) du= 1.0f/((float)lt->pntsu-1);
+ if(lt->pntsv>1) dv= 1.0f/((float)lt->pntsv-1);
+ if(lt->pntsw>1) dw= 1.0f/((float)lt->pntsw-1);
+
+ for(w=0; w<lt->pntsw; w++) {
+
+ for(v=0; v<lt->pntsv; v++) {
+
+ for(u=0; u<lt->pntsu; u++, bp++) {
+ if(u==0 || v==0 || w==0 || u==lt->pntsu-1 || v==lt->pntsv-1 || w==lt->pntsw-1);
+ else {
+
+ bp->hide= 1;
+ bp->f1 &= ~SELECT;
+
+ /* u extrema */
+ bp1= latt_bp(lt, 0, v, w);
+ bp2= latt_bp(lt, lt->pntsu-1, v, w);
+
+ fac1= du*u;
+ bp->vec[0]= (1.0f-fac1)*bp1->vec[0] + fac1*bp2->vec[0];
+ bp->vec[1]= (1.0f-fac1)*bp1->vec[1] + fac1*bp2->vec[1];
+ bp->vec[2]= (1.0f-fac1)*bp1->vec[2] + fac1*bp2->vec[2];
+
+ /* v extrema */
+ bp1= latt_bp(lt, u, 0, w);
+ bp2= latt_bp(lt, u, lt->pntsv-1, w);
+
+ fac1= dv*v;
+ bp->vec[0]+= (1.0f-fac1)*bp1->vec[0] + fac1*bp2->vec[0];
+ bp->vec[1]+= (1.0f-fac1)*bp1->vec[1] + fac1*bp2->vec[1];
+ bp->vec[2]+= (1.0f-fac1)*bp1->vec[2] + fac1*bp2->vec[2];
+
+ /* w extrema */
+ bp1= latt_bp(lt, u, v, 0);
+ bp2= latt_bp(lt, u, v, lt->pntsw-1);
+
+ fac1= dw*w;
+ bp->vec[0]+= (1.0f-fac1)*bp1->vec[0] + fac1*bp2->vec[0];
+ bp->vec[1]+= (1.0f-fac1)*bp1->vec[1] + fac1*bp2->vec[1];
+ bp->vec[2]+= (1.0f-fac1)*bp1->vec[2] + fac1*bp2->vec[2];
+
+ VecMulf(bp->vec, 0.3333333f);
+
+ }
+ }
+
+ }
+
+ }
+
+}
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
new file mode 100644
index 00000000000..97ede69280c
--- /dev/null
+++ b/source/blender/blenkernel/intern/library.c
@@ -0,0 +1,905 @@
+
+/* library.c aug 94 MIXED MODEL
+ *
+ * jan 95
+ *
+ * afhandeling ID's en libraries
+ * allocceren en vrijgeven alle library data
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+#include "MEM_guardedalloc.h"
+
+/* all types are needed here, in order to do memory operations */
+#include "DNA_ID.h"
+#include "DNA_listBase.h"
+#include "DNA_scene_types.h"
+#include "DNA_object_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_lattice_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_meta_types.h"
+#include "DNA_material_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_ika_types.h"
+#include "DNA_image_types.h"
+#include "DNA_wave_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_ipo_types.h"
+#include "DNA_key_types.h"
+#include "DNA_world_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_vfont_types.h"
+#include "DNA_text_types.h"
+#include "DNA_sound_types.h"
+#include "DNA_group_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_action_types.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_dynstr.h"
+
+#include "BKE_bad_level_calls.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+#include "BKE_global.h"
+#include "BKE_sound.h"
+#include "BKE_object.h"
+#include "BKE_screen.h"
+#include "BKE_mesh.h"
+#include "BKE_material.h"
+#include "BKE_curve.h"
+#include "BKE_mball.h"
+ #include "BKE_text.h"
+#include "BKE_texture.h"
+#include "BKE_scene.h"
+#include "BKE_image.h"
+#include "BKE_ika.h"
+#include "BKE_ipo.h"
+#include "BKE_key.h"
+#include "BKE_world.h"
+#include "BKE_font.h"
+#include "BKE_group.h"
+#include "BKE_lattice.h"
+#include "BKE_armature.h"
+#include "BKE_action.h"
+
+#define MAX_IDPUP 30 /* was 24 */
+#define MAX_LIBARRAY 100 /* was 30 */
+
+/* ************* ALGEMEEN ************************ */
+
+void id_lib_extern(ID *id)
+{
+ if(id) {
+ if(id->flag & LIB_INDIRECT) {
+ id->flag -= LIB_INDIRECT;
+ id->flag |= LIB_EXTERN;
+ }
+ }
+}
+
+void id_us_plus(ID *id)
+{
+ if(id) {
+ id->us++;
+ if(id->flag & LIB_INDIRECT) {
+ id->flag -= LIB_INDIRECT;
+ id->flag |= LIB_EXTERN;
+ }
+ }
+}
+
+ListBase *wich_libbase(Main *mainlib, short type)
+{
+ switch( type ) {
+ case ID_SCE:
+ return &(mainlib->scene);
+ case ID_LI:
+ return &(mainlib->library);
+ case ID_OB:
+ return &(mainlib->object);
+ case ID_ME:
+ return &(mainlib->mesh);
+ case ID_CU:
+ return &(mainlib->curve);
+ case ID_MB:
+ return &(mainlib->mball);
+ case ID_MA:
+ return &(mainlib->mat);
+ case ID_TE:
+ return &(mainlib->tex);
+ case ID_IM:
+ return &(mainlib->image);
+ case ID_IK:
+ return &(mainlib->ika);
+ case ID_WV:
+ return &(mainlib->wave);
+ case ID_LT:
+ return &(mainlib->latt);
+ case ID_LA:
+ return &(mainlib->lamp);
+ case ID_CA:
+ return &(mainlib->camera);
+ case ID_IP:
+ return &(mainlib->ipo);
+ case ID_KE:
+ return &(mainlib->key);
+ case ID_WO:
+ return &(mainlib->world);
+ case ID_SCR:
+ return &(mainlib->screen);
+ case ID_VF:
+ return &(mainlib->vfont);
+ case ID_TXT:
+ return &(mainlib->text);
+ case ID_SO:
+ return &(mainlib->sound);
+ case ID_SAMPLE:
+ /* declared as an external in sound.h !!! */
+ return (samples);
+ case ID_GR:
+ return &(mainlib->group);
+ case ID_AR:
+ return &(mainlib->armature);
+ case ID_AC:
+ return &(mainlib->action);
+ }
+ return 0;
+}
+
+int set_listbasepointers(Main *main, ListBase **lb)
+{
+ /* BACKWARDS! let op volgorde van vrijgeven! (mesh<->mat) */
+
+ lb[0]= &(main->ipo);
+ lb[1]= &(main->key);
+ lb[2]= &(main->image);
+ lb[3]= &(main->tex);
+ lb[4]= &(main->mat);
+ lb[5]= &(main->vfont);
+
+ /* Important!: When adding a new object type,
+ * the specific data should be inserted here
+ */
+
+ lb[6]= &(main->armature);
+ lb[7]= &(main->action);
+
+ lb[8]= &(main->mesh);
+ lb[9]= &(main->curve);
+ lb[10]= &(main->mball);
+ lb[11]= &(main->ika);
+ lb[12]= &(main->wave);
+ lb[13]= &(main->latt);
+ lb[14]= &(main->lamp);
+ lb[15]= &(main->camera);
+
+ lb[16]= &(main->world);
+ lb[17]= &(main->screen);
+ lb[18]= &(main->object);
+ lb[19]= &(main->scene);
+ lb[20]= &(main->library);
+ lb[21]= &(main->text);
+ lb[22]= &(main->sound);
+ lb[23]= &(main->group);
+
+ lb[24]= samples;
+ lb[25]= 0;
+
+ return 25;
+}
+
+/* *********** ALLOC EN FREE *****************
+
+free_libblock(ListBase *lb, ID *id )
+ lijstbasis en datablok geven, alleen ID wordt uitgelezen
+
+void *alloc_libblock(ListBase *lb, type, name)
+ hangt in lijst en geeft nieuw ID
+
+ ***************************** */
+
+static ID *alloc_libblock_notest(short type)
+{
+ ID *id= 0;
+
+ switch( type ) {
+ case ID_SCE:
+ id= MEM_callocN(sizeof(Scene), "scene");
+ break;
+ case ID_LI:
+ id= MEM_callocN(sizeof(Library), "library");
+ break;
+ case ID_OB:
+ id= MEM_callocN(sizeof(Object), "object");
+ break;
+ case ID_ME:
+ id= MEM_callocN(sizeof(Mesh), "mesh");
+ break;
+ case ID_CU:
+ id= MEM_callocN(sizeof(Curve), "curve");
+ break;
+ case ID_MB:
+ id= MEM_callocN(sizeof(MetaBall), "mball");
+ break;
+ case ID_MA:
+ id= MEM_callocN(sizeof(Material), "mat");
+ break;
+ case ID_TE:
+ id= MEM_callocN(sizeof(Tex), "tex");
+ break;
+ case ID_IM:
+ id= MEM_callocN(sizeof(Image), "image");
+ break;
+ case ID_IK:
+ id= MEM_callocN(sizeof(Ika), "ika");
+ break;
+ case ID_WV:
+ id= MEM_callocN(sizeof(Wave), "wave");
+ break;
+ case ID_LT:
+ id= MEM_callocN(sizeof(Lattice), "latt");
+ break;
+ case ID_LA:
+ id= MEM_callocN(sizeof(Lamp), "lamp");
+ break;
+ case ID_CA:
+ id= MEM_callocN(sizeof(Camera), "camera");
+ break;
+ case ID_IP:
+ id= MEM_callocN(sizeof(Ipo), "ipo");
+ break;
+ case ID_KE:
+ id= MEM_callocN(sizeof(Key), "key");
+ break;
+ case ID_WO:
+ id= MEM_callocN(sizeof(World), "world");
+ break;
+ case ID_SCR:
+ id= MEM_callocN(sizeof(bScreen), "screen");
+ break;
+ case ID_VF:
+ id= MEM_callocN(sizeof(VFont), "vfont");
+ break;
+ case ID_TXT:
+ id= MEM_callocN(sizeof(Text), "text");
+ break;
+ case ID_SO:
+ id= MEM_callocN(sizeof(bSound), "sound");
+ break;
+ case ID_SAMPLE:
+ id = MEM_callocN(sizeof(bSample), "sound");
+ break;
+ case ID_GR:
+ id= MEM_callocN(sizeof(Group), "sound");
+ break;
+ case ID_AR:
+ id = MEM_callocN(sizeof(bArmature), "armature");
+ break;
+ case ID_AC:
+ id = MEM_callocN(sizeof(bAction), "action");
+ break;
+ }
+ return id;
+}
+
+// used everywhere in blenkernel and text.c
+void *alloc_libblock(ListBase *lb, short type, char *name)
+{
+ ID *id= 0;
+
+ id= alloc_libblock_notest(type);
+ if(id) {
+ BLI_addtail(lb, id);
+ id->us= 1;
+ *( (short *)id->name )= type;
+ new_id(lb, id, name);
+ /* alfabetisch opnieuw invoegen: zit in new_id */
+ }
+ return id;
+}
+
+/* GS reads the memory pointed at in a specific ordering. There are,
+ * however two definitions for it. I have jotted them down here, both,
+ * but I think the first one is actually used. The thing is that
+ * big-endian systems might read this the wrong way round. OTOH, we
+ * constructed the IDs that are read out with this macro explicitly as
+ * well. I expect we'll sort it out soon... */
+
+/* from blendef: */
+#define GS(a) (*((short *)(a)))
+
+/* from misc_util: flip the bytes from x */
+/*#define GS(x) (((unsigned char *)(x))[0] << 8 | ((unsigned char *)(x))[1]) */
+
+// used everywhere in blenkernel and text.c
+void *copy_libblock(void *rt)
+{
+ ID *idn, *id;
+ ListBase *lb;
+ char *cp, *cpn;
+ int idn_len;
+
+ id= rt;
+
+ lb= wich_libbase(G.main, GS(id->name));
+ idn= alloc_libblock(lb, GS(id->name), id->name+2);
+
+ idn_len= MEM_allocN_len(idn);
+ if(idn_len - sizeof(ID) > 0) {
+ cp= (char *)id;
+ cpn= (char *)idn;
+ memcpy(cpn+sizeof(ID), cp+sizeof(ID), idn_len - sizeof(ID));
+ }
+
+ id->newid= idn;
+ idn->flag |= LIB_NEW;
+
+ return idn;
+}
+
+static void free_library(Library *lib)
+{
+ /* no freeing needed for libraries yet */
+}
+
+// used in headerbuttons.c image.c mesh.c screen.c sound.c and library.c
+void free_libblock(ListBase *lb, void *idv)
+{
+ ID *id= idv;
+
+ switch( GS(id->name) ) { /* GetShort uit util.h */
+ case ID_SCE:
+ free_scene((Scene *)id);
+ break;
+ case ID_LI:
+ free_library((Library *)id);
+ break;
+ case ID_OB:
+ free_object((Object *)id);
+ break;
+ case ID_ME:
+ free_mesh((Mesh *)id);
+ break;
+ case ID_CU:
+ free_curve((Curve *)id);
+ break;
+ case ID_MB:
+ free_mball((MetaBall *)id);
+ break;
+ case ID_MA:
+ free_material((Material *)id);
+ break;
+ case ID_TE:
+ free_texture((Tex *)id);
+ break;
+ case ID_IM:
+ free_image((Image *)id);
+ break;
+ case ID_IK:
+ free_ika((Ika *)id);
+ break;
+ case ID_WV:
+ /* free_wave(id); */
+ break;
+ case ID_LT:
+ free_lattice((Lattice *)id);
+ break;
+ case ID_LA:
+ free_lamp((Lamp *)id);
+ break;
+ case ID_CA:
+/* free_camera(id); */
+ /* cast wasn't here before... spooky... */
+ free_camera((Camera*) id);
+ break;
+ case ID_IP:
+ free_ipo((Ipo *)id);
+ break;
+ case ID_KE:
+ free_key((Key *)id);
+ break;
+ case ID_WO:
+ free_world((World *)id);
+ break;
+ case ID_SCR:
+ free_screen((bScreen *)id);
+ break;
+ case ID_VF:
+ free_vfont((VFont *)id);
+ break;
+ case ID_TXT:
+ free_text((Text *)id);
+ break;
+ case ID_SO:
+ sound_free_sound((bSound *)id);
+ break;
+ case ID_SAMPLE:
+ sound_free_sample((bSample *)id);
+ break;
+ case ID_GR:
+ free_group((Group *)id);
+ break;
+ case ID_AR:
+ free_armature((bArmature *)id);
+ break;
+ case ID_AC:
+ free_action((bAction *)id);
+ break;
+ }
+
+ BLI_remlink(lb, id);
+ MEM_freeN(id);
+
+ /* should not be here!! this is an interface-thing */
+ allspace(OOPS_TEST, 0);
+}
+
+void free_libblock_us(ListBase *lb, void *idv) /* test users */
+{
+ ID *id= idv;
+
+ id->us--;
+
+ if(id->us<0) {
+ if(id->lib) printf("ERROR block %s %s users %d\n", id->lib->name, id->name, id->us);
+ else printf("ERROR block %s users %d\n", id->name, id->us);
+ }
+ if(id->us==0) {
+ if( GS(id->name)==ID_OB ) unlink_object((Object *)id);
+
+ free_libblock(lb, id);
+ }
+}
+
+
+void free_main(Main *mainvar)
+{
+ /* ook aanroepen bij file inlezen, erase all, etc */
+ ListBase *lbarray[MAX_LIBARRAY];
+ int a;
+
+ a= set_listbasepointers(mainvar, lbarray);
+ while(a--) {
+ ListBase *lb= lbarray[a];
+ ID *id;
+
+ while (id= lb->first) {
+ free_libblock(lb, id);
+ }
+ }
+
+ MEM_freeN(mainvar);
+}
+
+/* ***************** ID ************************ */
+
+// only used in exotic.c
+ID *find_id(char *type, char *name) /* type: "OB" of "MA" etc */
+{
+ ID *id;
+ ListBase *lb;
+
+ lb= wich_libbase(G.main, GS(type));
+
+ id= lb->first;
+ while(id) {
+ if( strcmp(id->name+2, name)==0 ) return id;
+ id= id->next;
+ }
+ return 0;
+}
+
+static void get_flags_for_id(ID *id, char *buf) {
+ int isfake= id->flag & LIB_FAKEUSER;
+
+ /* Writeout the flags for the entry, note there
+ * is a small hack that writes 5 spaces instead
+ * of 4 if no flags are displayed... this makes
+ * things usually line up ok - better would be
+ * to have that explicit, oh well - zr
+ */
+
+ if (id->us<0)
+ sprintf(buf, "-1W ");
+ else if (!id->lib && !isfake && id->us)
+ sprintf(buf, " ");
+ else
+ sprintf(buf, "%c%c%c ", id->lib?'L':' ', isfake?'F':' ', (id->us==0)?'O':' ');
+}
+
+static void IDnames_to_dyn_pupstring(DynStr *pupds, ListBase *lb, ID *link, short *nr)
+{
+ int i, nids= BLI_countlist(lb);
+
+ *nr= -1;
+
+ if (nids>MAX_IDPUP) {
+ BLI_dynstr_append(pupds, "DataBrowse %x-2");
+ } else {
+ ID *id;
+
+ for (i=0, id= lb->first; id; id= id->next, i++) {
+ char buf[32];
+
+ if (id==link)
+ *nr= i+1;
+
+ get_flags_for_id(id, buf);
+
+ BLI_dynstr_append(pupds, buf);
+ BLI_dynstr_append(pupds, id->name+2);
+
+ if(id->next)
+ BLI_dynstr_append(pupds, "|");
+ }
+ }
+}
+
+ /* Silly routine, the only difference between the one
+ * above is that it only adds items with a matching
+ * blocktype... this should be unified somehow... - zr
+ */
+static void IPOnames_to_dyn_pupstring(DynStr *pupds, ListBase *lb, ID *link, short *nr, int blocktype)
+{
+ ID *id;
+ int i, nids;
+
+ for (id= lb->first, nids= 0; id; id= id->next) {
+ Ipo *ipo= (Ipo*) id;
+
+ if (ipo->blocktype==blocktype)
+ nids++;
+ }
+
+ if (nids>MAX_IDPUP) {
+ BLI_dynstr_append(pupds, "DataBrowse %x-2");
+ } else {
+ for (i=0, id= lb->first; id; id= id->next) {
+ Ipo *ipo= (Ipo*) id;
+
+ if (ipo->blocktype==blocktype) {
+ char buf[32];
+
+ if (id==link)
+ *nr= i+1;
+
+ get_flags_for_id(id, buf);
+
+ BLI_dynstr_append(pupds, buf);
+ BLI_dynstr_append(pupds, id->name+2);
+
+ if(id->next)
+ BLI_dynstr_append(pupds, "|");
+
+ i++;
+ }
+ }
+ }
+}
+
+// used by headerbuttons.c buttons.c editobject.c editseq.c
+void IDnames_to_pupstring(char **str, char *title, char *extraops, ListBase *lb, ID *link, short *nr)
+{
+ DynStr *pupds= BLI_dynstr_new();
+
+ if (title) {
+ BLI_dynstr_append(pupds, title);
+ BLI_dynstr_append(pupds, "%t|");
+ }
+
+ IDnames_to_dyn_pupstring(pupds, lb, link, nr);
+
+ if (extraops) {
+ if (BLI_dynstr_get_len(pupds))
+ BLI_dynstr_append(pupds, "|");
+ BLI_dynstr_append(pupds, extraops);
+ }
+
+ *str= BLI_dynstr_get_cstring(pupds);
+ BLI_dynstr_free(pupds);
+}
+
+// only used by headerbuttons.c
+void IPOnames_to_pupstring(char **str, char *title, char *extraops, ListBase *lb, ID *link, short *nr, int blocktype)
+{
+ DynStr *pupds= BLI_dynstr_new();
+
+ if (title) {
+ BLI_dynstr_append(pupds, title);
+ BLI_dynstr_append(pupds, "%t|");
+ }
+
+ IPOnames_to_dyn_pupstring(pupds, lb, link, nr, blocktype);
+
+ if (extraops) {
+ if (BLI_dynstr_get_len(pupds))
+ BLI_dynstr_append(pupds, "|");
+ BLI_dynstr_append(pupds, extraops);
+ }
+
+ *str= BLI_dynstr_get_cstring(pupds);
+ BLI_dynstr_free(pupds);
+}
+
+// used by buttons.c library.c mball.c
+void splitIDname(char *name, char *left, int *nr)
+{
+ int a;
+
+ *nr= 0;
+ strncpy(left, name, 21);
+
+ a= strlen(name);
+ if(a>1 && name[a-1]=='.') return;
+
+ while(a--) {
+ if( name[a]=='.' ) {
+ left[a]= 0;
+ *nr= atol(name+a+1);
+ return;
+ }
+ if( isdigit(name[a])==0 ) break;
+
+ left[a]= 0;
+ }
+ strcpy(left, name);
+}
+
+static void sort_alpha_id(ListBase *lb, ID *id)
+{
+ ID *idtest;
+
+ /* alfabetisch opnieuw invoegen */
+ if(lb->first!=lb->last) {
+ BLI_remlink(lb, id);
+
+ idtest= lb->first;
+ while(idtest) {
+ if(strcasecmp(idtest->name, id->name)>0 || idtest->lib) {
+ BLI_insertlinkbefore(lb, idtest, id);
+ break;
+ }
+ idtest= idtest->next;
+ }
+ /* als laatste */
+ if(idtest==0) {
+ BLI_addtail(lb, id);
+ }
+ }
+
+}
+
+int new_id(ListBase *lb, ID *id, char *tname)
+/* alleen locale blokken: externe en indirekte hebben al een unieke ID */
+/* return 1: nieuwe naam gemaakt */
+{
+ ID *idtest;
+ int nr= 0, nrtest, maxtest=32, a;
+ char aname[32], *name, left[24], leftest[24], in_use[32];
+
+ /* - naam splitsen
+ * - zoeken
+ */
+
+ if(id->lib) return 0;
+
+ if(tname==0) name= id->name+2;
+ else {
+ /* tname can be const */
+ strncpy(aname, tname, 21);
+ name= aname;
+
+ if( strlen(name) > 21 ) name[21]= 0;
+ }
+
+ if(lb==0) lb= wich_libbase(G.main, GS(id->name));
+
+ /* eerste fase: bestaat de id al? */
+ idtest= lb->first;
+ while(idtest) {
+
+ if(id!=idtest && idtest->lib==0) {
+
+ /* niet alphabetic testen! */
+ /* optim */
+ if( idtest->name[2] == name[0] ) {
+ if(strcmp(name, idtest->name+2)==0) break;
+ }
+ }
+
+ idtest= idtest->next;
+ }
+
+ /* if there is no double return */
+ if(idtest==0) {
+ strcpy(id->name+2, name);
+ return 0;
+ }
+
+ memset(in_use, 0, maxtest);
+
+ splitIDname(name, left, &nr);
+ if(nr>999 && strlen(left)>16) left[16]= 0;
+ else if(strlen(left)>17) left[17]= 0;
+
+
+ idtest= lb->first;
+ while(idtest) {
+
+ if(id!=idtest && idtest->lib==0) {
+
+ splitIDname(idtest->name+2, leftest, &nrtest);
+ if(strcmp(left, leftest)==0) {
+
+ if(nrtest<maxtest) in_use[nrtest]= 1;
+ if(nr <= nrtest) nr= nrtest+1;
+ }
+ }
+
+ idtest= idtest->next;
+ }
+
+ for(a=0; a<maxtest; a++) {
+ if(a>=nr) break;
+ if( in_use[a]==0 ) {
+ nr= a;
+ break;
+ }
+ }
+
+ if(nr==0) sprintf(id->name+2, "%s", left);
+ else {
+ if (nr >= 1000 && strlen(left) > 16) {
+ // this would overflow name buffer
+ left[16]= 0;
+ return (new_id(lb, id, left));
+ }
+ /* this format specifier is fucked... */
+ sprintf(id->name+2, "%s.%0.3d", left, nr);
+ }
+
+ sort_alpha_id(lb, id);
+
+ return 1;
+}
+
+// next to indirect usage in read/writefile also in editobject.c scene.c
+void clear_id_newpoins()
+{
+ ListBase *lbarray[MAX_LIBARRAY];
+ ID *id;
+ int a;
+
+ a= set_listbasepointers(G.main, lbarray);
+ while(a--) {
+ id= lbarray[a]->first;
+ while(id) {
+ id->newid= 0;
+ id->flag &= ~LIB_NEW;
+ id= id->next;
+ }
+ }
+}
+
+void all_local(void)
+{
+ ListBase *lbarray[MAX_LIBARRAY], tempbase={0, 0};
+ ID *id, *idn;
+ int a;
+
+ a= set_listbasepointers(G.main, lbarray);
+ while(a--) {
+ id= lbarray[a]->first;
+
+ while(id) {
+ id->newid= 0;
+ id->flag &= ~(LIB_EXTERN|LIB_INDIRECT|LIB_NEW);
+
+ idn= id->next; /* id wordt mogelijk opnieuw ingevoegd */
+ if(id->lib) {
+ id->lib= 0;
+ new_id(lbarray[a], id, 0); /* new_id doet dit alleen bij dubbele namen */
+ sort_alpha_id(lbarray[a], id);
+ }
+ else {
+ /* patch: testen of de zaak wel alphabetisch is */
+/*
+ if(idn) {
+ if(strcasecmp(id->name, idn->name)>0) {
+ remlink(lbarray[a], id);
+ addtail(&tempbase, id);
+ }
+ else if(id->prev) {
+ idp= id->prev;
+ if(strcasecmp(idp->name, id->name)>0) {
+ remlink(lbarray[a], id);
+ addtail(&tempbase, id);
+ }
+ }
+ }
+*/
+ }
+
+ id= idn;
+ }
+
+ /* patch2: zorgen dat de zaak wel alphabetisch is */
+ while( (id=tempbase.first) ) {
+ BLI_remlink(&tempbase, id);
+ BLI_addtail(lbarray[a], id);
+ new_id(lbarray[a], id, 0);
+ }
+ }
+}
+
+
+void test_idbutton(char *name)
+{
+ /* vanuit buttons: als naam al bestaat: new_id aanroepen */
+ ListBase *lb;
+ ID *idtest;
+
+
+ lb= wich_libbase(G.main, GS(name-2) );
+ if(lb==0) return;
+
+ /* zoek welke id */
+ idtest= lb->first;
+ while(idtest) {
+ if( strcmp(idtest->name+2, name)==0) break;
+ idtest= idtest->next;
+ }
+
+ if(idtest) if( new_id(lb, idtest, name)==0 ) sort_alpha_id(lb, idtest);
+}
+
+void rename_id(ID *id, char *name)
+{
+ ListBase *lb;
+
+ strncpy(id->name+2, name, 21);
+ lb= wich_libbase(G.main, GS(id->name) );
+
+ new_id(lb, id, name);
+}
+
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
new file mode 100644
index 00000000000..71d0e95031d
--- /dev/null
+++ b/source/blender/blenkernel/intern/material.c
@@ -0,0 +1,747 @@
+
+/* material.c MIX MODEL
+ *
+ * maart 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 <string.h>
+#include "MEM_guardedalloc.h"
+
+#include "DNA_material_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_meta_types.h"
+#include "DNA_scene_types.h"
+
+#include "BLI_blenlib.h"
+
+#include "BKE_bad_level_calls.h"
+#include "BKE_utildefines.h"
+
+#include "BKE_global.h"
+#include "BKE_main.h"
+
+#include "BKE_mesh.h"
+#include "BKE_library.h"
+#include "BKE_displist.h"
+#include "BPY_extern.h"
+#include "BKE_material.h"
+
+void free_material(Material *ma)
+{
+ int a;
+ MTex *mtex;
+
+ BPY_free_scriptlink(&ma->scriptlink);
+
+ if(ma->ren) MEM_freeN(ma->ren);
+ ma->ren= 0;
+
+ for(a=0; a<8; a++) {
+ mtex= ma->mtex[a];
+ if(mtex && mtex->tex) mtex->tex->id.us--;
+ if(mtex) MEM_freeN(mtex);
+ }
+}
+
+void init_material(Material *ma)
+{
+ ma->lay= 1;
+ ma->r= ma->g= ma->b= ma->ref= 0.8f;
+ ma->specr= ma->specg= ma->specb= 1.0f;
+ ma->mirr= ma->mirg= ma->mirb= 1.0f;
+ ma->amb= 0.5f;
+ ma->alpha= 1.0f;
+ ma->spec= ma->hasize= 0.5f;
+ ma->har= 50;
+ ma->starc= ma->ringc= 4;
+ ma->linec= 12;
+ ma->flarec= 1;
+ ma->flaresize= ma->subsize= 1.0f;
+ ma->friction= 0.5f;
+
+ ma->mode= MA_TRACEBLE+MA_SHADOW;
+}
+
+Material *add_material(char *name)
+{
+ Material *ma;
+
+ ma= alloc_libblock(&G.main->mat, ID_MA, name);
+
+ init_material(ma);
+
+ return ma;
+}
+
+Material *copy_material(Material *ma)
+{
+ Material *man;
+ int a;
+
+ man= copy_libblock(ma);
+
+ id_us_plus((ID *)man->ipo);
+
+ for(a=0; a<8; a++) {
+ if(ma->mtex[a]) {
+ man->mtex[a]= MEM_mallocN(sizeof(MTex), "copymaterial");
+ memcpy(man->mtex[a], ma->mtex[a], sizeof(MTex));
+ id_us_plus((ID *)man->mtex[a]->tex);
+ }
+ }
+
+ BPY_copy_scriptlink(&ma->scriptlink);
+
+ return man;
+}
+
+void make_local_material(Material *ma)
+{
+ Object *ob;
+ Mesh *me;
+ Curve *cu;
+ MetaBall *mb;
+ Material *man;
+ int a, local=0, lib=0;
+
+ /* - zijn er alleen lib users: niet doen
+ * - zijn er alleen locale users: flag zetten
+ * - mixed: copy
+ */
+
+ if(ma->id.lib==0) return;
+ if(ma->id.us==1) {
+ ma->id.lib= 0;
+ ma->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)ma, 0);
+ for(a=0; a<8; a++) {
+ if(ma->mtex[a]) id_lib_extern((ID *)ma->mtex[a]->tex);
+ }
+
+ return;
+ }
+
+ /* test objects */
+ ob= G.main->object.first;
+ while(ob) {
+ if(ob->mat) {
+ for(a=0; a<ob->totcol; a++) {
+ if(ob->mat[a]==ma) {
+ if(ob->id.lib) lib= 1;
+ else local= 1;
+ }
+ }
+ }
+ ob= ob->id.next;
+ }
+ /* test meshes */
+ me= G.main->mesh.first;
+ while(me) {
+ if(me->mat) {
+ for(a=0; a<me->totcol; a++) {
+ if(me->mat[a]==ma) {
+ if(me->id.lib) lib= 1;
+ else local= 1;
+ }
+ }
+ }
+ me= me->id.next;
+ }
+ /* test curves */
+ cu= G.main->curve.first;
+ while(cu) {
+ if(cu->mat) {
+ for(a=0; a<cu->totcol; a++) {
+ if(cu->mat[a]==ma) {
+ if(cu->id.lib) lib= 1;
+ else local= 1;
+ }
+ }
+ }
+ cu= cu->id.next;
+ }
+ /* test mballs */
+ mb= G.main->mball.first;
+ while(mb) {
+ if(mb->mat) {
+ for(a=0; a<mb->totcol; a++) {
+ if(mb->mat[a]==ma) {
+ if(mb->id.lib) lib= 1;
+ else local= 1;
+ }
+ }
+ }
+ mb= mb->id.next;
+ }
+
+ if(local && lib==0) {
+ ma->id.lib= 0;
+ ma->id.flag= LIB_LOCAL;
+
+ for(a=0; a<8; a++) {
+ if(ma->mtex[a]) id_lib_extern((ID *)ma->mtex[a]->tex);
+ }
+
+ new_id(0, (ID *)ma, 0);
+ }
+ else if(local && lib) {
+ man= copy_material(ma);
+ man->id.us= 0;
+
+ /* do objects */
+ ob= G.main->object.first;
+ while(ob) {
+ if(ob->mat) {
+ for(a=0; a<ob->totcol; a++) {
+ if(ob->mat[a]==ma) {
+ if(ob->id.lib==0) {
+ ob->mat[a]= man;
+ man->id.us++;
+ ma->id.us--;
+ }
+ }
+ }
+ }
+ ob= ob->id.next;
+ }
+ /* do meshes */
+ me= G.main->mesh.first;
+ while(me) {
+ if(me->mat) {
+ for(a=0; a<me->totcol; a++) {
+ if(me->mat[a]==ma) {
+ if(me->id.lib==0) {
+ me->mat[a]= man;
+ man->id.us++;
+ ma->id.us--;
+ }
+ }
+ }
+ }
+ me= me->id.next;
+ }
+ /* do curves */
+ cu= G.main->curve.first;
+ while(cu) {
+ if(cu->mat) {
+ for(a=0; a<cu->totcol; a++) {
+ if(cu->mat[a]==ma) {
+ if(cu->id.lib==0) {
+ cu->mat[a]= man;
+ man->id.us++;
+ ma->id.us--;
+ }
+ }
+ }
+ }
+ cu= cu->id.next;
+ }
+ /* do mballs */
+ mb= G.main->mball.first;
+ while(mb) {
+ if(mb->mat) {
+ for(a=0; a<mb->totcol; a++) {
+ if(mb->mat[a]==ma) {
+ if(mb->id.lib==0) {
+ mb->mat[a]= man;
+ man->id.us++;
+ ma->id.us--;
+ }
+ }
+ }
+ }
+ mb= mb->id.next;
+ }
+ }
+}
+
+Material ***give_matarar(Object *ob)
+{
+ Mesh *me;
+ Curve *cu;
+ MetaBall *mb;
+
+ if(ob->type==OB_MESH) {
+ me= ob->data;
+ return &(me->mat);
+ }
+ else if ELEM3(ob->type, OB_CURVE, OB_FONT, OB_SURF) {
+ cu= ob->data;
+ return &(cu->mat);
+ }
+ else if(ob->type==OB_MBALL) {
+ mb= ob->data;
+ return &(mb->mat);
+ }
+ return 0;
+}
+
+short *give_totcolp(Object *ob)
+{
+ Mesh *me;
+ Curve *cu;
+ MetaBall *mb;
+
+ if(ob->type==OB_MESH) {
+ me= ob->data;
+ return &(me->totcol);
+ }
+ else if ELEM3(ob->type, OB_CURVE, OB_FONT, OB_SURF) {
+ cu= ob->data;
+ return &(cu->totcol);
+ }
+ else if(ob->type==OB_MBALL) {
+ mb= ob->data;
+ return &(mb->totcol);
+ }
+ return 0;
+}
+
+Material *give_current_material(Object *ob, int act)
+{
+ Material ***matarar, *ma;
+
+ if(ob==0) return 0;
+ if(ob->totcol==0) return 0;
+
+ if(act>ob->totcol) act= ob->totcol;
+ else if(act==0) act= 1;
+
+ if( BTST(ob->colbits, act-1) ) { /* aan object */
+ ma= ob->mat[act-1];
+ }
+ else { /* aan data */
+ matarar= give_matarar(ob);
+
+ if(matarar && *matarar) ma= (*matarar)[act-1];
+ else ma= 0;
+
+ }
+
+ return ma;
+}
+
+ID *material_from(Object *ob, int act)
+{
+
+ if(ob==0) return 0;
+
+ if(ob->totcol==0) return ob->data;
+ if(act==0) act= 1;
+
+ if( BTST(ob->colbits, act-1) ) return (ID *)ob;
+ else return ob->data;
+}
+
+/* GS reads the memory pointed at in a specific ordering. There are,
+ * however two definitions for it. I have jotted them down here, both,
+ * but I think the first one is actually used. The thing is that
+ * big-endian systems might read this the wrong way round. OTOH, we
+ * constructed the IDs that are read out with this macro explicitly as
+ * well. I expect we'll sort it out soon... */
+
+/* from blendef: */
+#define GS(a) (*((short *)(a)))
+
+/* from misc_util: flip the bytes from x */
+/* #define GS(x) (((unsigned char *)(x))[0] << 8 | ((unsigned char *)(x))[1]) */
+
+void test_object_materials(ID *id)
+{
+ /* ob mat-array evenlang maken als obdata mat-array */
+ Object *ob;
+ Mesh *me;
+ Curve *cu;
+ MetaBall *mb;
+ Material **newmatar;
+ int totcol=0;
+
+ if(id==0) return;
+
+ if( GS(id->name)==ID_ME ) {
+ me= (Mesh *)id;
+ totcol= me->totcol;
+ }
+ else if( GS(id->name)==ID_CU ) {
+ cu= (Curve *)id;
+ totcol= cu->totcol;
+ }
+ else if( GS(id->name)==ID_MB ) {
+ mb= (MetaBall *)id;
+ totcol= mb->totcol;
+ }
+ else return;
+
+ ob= G.main->object.first;
+ while(ob) {
+
+ if(ob->data==id) {
+
+ if(totcol==0) {
+ if(ob->totcol) {
+ MEM_freeN(ob->mat);
+ ob->mat= 0;
+ }
+ }
+ else if(ob->totcol<totcol) {
+ newmatar= MEM_callocN(sizeof(void *)*totcol, "newmatar");
+ if(ob->totcol) {
+ memcpy(newmatar, ob->mat, sizeof(void *)*ob->totcol);
+ MEM_freeN(ob->mat);
+ }
+ ob->mat= newmatar;
+ }
+ ob->totcol= totcol;
+ if(ob->totcol && ob->actcol==0) ob->actcol= 1;
+ if(ob->actcol>ob->totcol) ob->actcol= ob->totcol;
+ }
+ ob= ob->id.next;
+ }
+}
+
+
+void assign_material(Object *ob, Material *ma, int act)
+{
+ Material *mao, **matar, ***matarar;
+ short *totcolp;
+
+ if(act>MAXMAT) return;
+ if(act<1) act= 1;
+
+ /* test arraylens */
+
+ totcolp= give_totcolp(ob);
+ matarar= give_matarar(ob);
+
+ if(totcolp==0 || matarar==0) return;
+
+ if( act > *totcolp) {
+ matar= MEM_callocN(sizeof(void *)*act, "matarray1");
+ if( *totcolp) {
+ memcpy(matar, *matarar, sizeof(void *)*( *totcolp ));
+ MEM_freeN(*matarar);
+ }
+ *matarar= matar;
+ *totcolp= act;
+ }
+
+ if(act > ob->totcol) {
+ matar= MEM_callocN(sizeof(void *)*act, "matarray2");
+ if( ob->totcol) {
+ memcpy(matar, ob->mat, sizeof(void *)*( ob->totcol ));
+ MEM_freeN(ob->mat);
+ }
+ ob->mat= matar;
+ ob->totcol= act;
+ }
+
+ /* doe 't */
+
+ if( BTST(ob->colbits, act-1) ) { /* aan object */
+ mao= ob->mat[act-1];
+ if(mao) mao->id.us--;
+ ob->mat[act-1]= ma;
+ }
+ else { /* aan data */
+ mao= (*matarar)[act-1];
+ if(mao) mao->id.us--;
+ (*matarar)[act-1]= ma;
+ }
+ id_us_plus((ID *)ma);
+ test_object_materials(ob->data);
+}
+
+void new_material_to_objectdata(Object *ob)
+{
+ Material *ma;
+
+ if(ob==0) return;
+ if(ob->totcol>=MAXMAT) return;
+
+ ma= give_current_material(ob, ob->actcol);
+ if(ma==0) {
+ ma= add_material("Material");
+ ma->id.us= 0;
+ }
+
+ if(ob->actcol) {
+ if( BTST(ob->colbits, ob->actcol-1) ) {
+ ob->colbits= BSET(ob->colbits, ob->totcol);
+ }
+ }
+
+ assign_material(ob, ma, ob->totcol+1);
+ ob->actcol= ob->totcol;
+}
+
+
+void init_render_material(Material *ma)
+{
+ MTex *mtex;
+ int a, needuv=0;
+
+ if(ma->ren) return;
+
+ if(ma->flarec==0) ma->flarec= 1;
+
+ ma->ren= MEM_mallocN(sizeof(Material), "initrendermaterial");
+ memcpy(ma->ren, ma, sizeof(Material));
+
+ /* alle texcoflags van mtex adden */
+ ma= ma->ren;
+ ma->texco= 0;
+ ma->mapto= 0;
+ for(a=0; a<8; a++) {
+ mtex= ma->mtex[a];
+ if(mtex && mtex->tex) {
+
+ /* force std. ref mapping for envmap */
+ if(mtex->tex->type==TEX_ENVMAP) {
+/* mtex->texco= TEXCO_REFL; */
+/* mtex->projx= PROJ_X; */
+/* mtex->projy= PROJ_Y; */
+/* mtex->projz= PROJ_Z; */
+/* mtex->mapping= MTEX_FLAT; */
+ }
+ /* hier niet testen op mtex->object en mtex->texco op TEXCO_ORCO zetten: mtex is linked! */
+
+ ma->texco |= mtex->texco;
+ ma->mapto |= mtex->mapto;
+ if(R.osa) {
+ if ELEM3(mtex->tex->type, TEX_IMAGE, TEX_PLUGIN, TEX_ENVMAP) ma->texco |= TEXCO_OSA;
+ }
+
+ if(ma->texco & (511)) needuv= 1;
+
+ if(mtex->object) mtex->object->flag |= OB_DO_IMAT;
+
+ }
+ }
+ if(ma->mode & MA_ZTRA) {
+ /* if(ma->alpha==0.0 || ma->alpha==1.0) */
+ R.flag |= R_ZTRA;
+ }
+ if(ma->mode & MA_VERTEXCOLP) ma->mode |= MA_VERTEXCOL;
+
+ if(ma->mode & (MA_VERTEXCOL|MA_FACETEXTURE)) {
+ needuv= 1;
+ if(R.osa) ma->texco |= TEXCO_OSA; /* for texfaces */
+ }
+ if(needuv) ma->texco |= NEED_UV;
+
+ ma->ambr= ma->amb*R.wrld.ambr;
+ ma->ambg= ma->amb*R.wrld.ambg;
+ ma->ambb= ma->amb*R.wrld.ambb;
+
+}
+
+void init_render_materials()
+{
+ Material *ma;
+
+ ma= G.main->mat.first;
+ while(ma) {
+ if(ma->id.us) init_render_material(ma);
+ ma= ma->id.next;
+ }
+
+}
+
+void end_render_material(Material *ma)
+{
+
+ if(ma->ren) MEM_freeN(ma->ren);
+ ma->ren= 0;
+
+ if(ma->mode & (MA_VERTEXCOLP|MA_FACETEXTURE)) {
+ if( !(ma->mode & MA_HALO) ) {
+ ma->r= ma->g= ma->b= 1.0;
+ }
+ }
+}
+
+void end_render_materials()
+{
+ Material *ma;
+
+ ma= G.main->mat.first;
+ while(ma) {
+ if(ma->id.us) end_render_material(ma);
+ ma= ma->id.next;
+ }
+
+}
+
+
+/* ****************** */
+
+char colname_array[125][20]= {
+"Black","DarkRed","HalveRed","Red","Red",
+"DarkGreen","DarkOlive","Brown","Chocolate","OrangeRed",
+"HalveGreen","GreenOlive","DryOlive","Goldenrod","DarkOrange",
+"LightGreen","Chartreuse","YellowGreen","Yellow","Gold",
+"Green","LawnGreen","GreenYellow","LightOlive","Yellow",
+"DarkBlue","DarkPurple","HotPink","VioletPink","RedPink",
+"SlateGray","DarkGrey","PalePurple","IndianRed","Tomato",
+"SeaGreen","PaleGreen","GreenKhaki","LightBrown","LightSalmon",
+"SpringGreen","PaleGreen","MediumOlive","YellowBrown","LightGold",
+"LightGreen","LightGreen","LightGreen","GreenYellow","PaleYellow",
+"HalveBlue","DarkSky","HalveMagenta","VioletRed","DeepPink",
+"SteelBlue","SkyBlue","Orchid","LightHotPink","HotPink",
+"SeaGreen","SlateGray","MediumGrey","Burlywood","LightPink",
+"SpringGreen","Aquamarine","PaleGreen","Khaki","PaleOrange",
+"SpringGreen","SeaGreen","PaleGreen","PaleWhite","YellowWhite",
+"LightBlue","Purple","MediumOrchid","Magenta","Magenta",
+"RoyalBlue","SlateBlue","MediumOrchid","Orchid","Magenta",
+"DeepSkyBlue","LightSteelBlue","LightSkyBlue","Violet","LightPink",
+"Cyaan","DarkTurquoise","SkyBlue","Grey","Snow",
+"Mint","Mint","Aquamarine","MintCream","Ivory",
+"Blue","Blue","DarkMagenta","DarkOrchid","Magenta",
+"SkyBlue","RoyalBlue","LightSlateBlue","MediumOrchid","Magenta",
+"DodgerBlue","SteelBlue","MediumPurple","PalePurple","Plum",
+"DeepSkyBlue","PaleBlue","LightSkyBlue","PalePurple","Thistle",
+"Cyan","ColdBlue","PaleTurquoise","GhostWhite","White"
+};
+
+void automatname(Material *ma)
+{
+ int nr, r, g, b;
+ float ref;
+
+ if(ma==0) return;
+ if(ma->mode & MA_SHLESS) ref= 1.0;
+ else ref= ma->ref;
+
+ r= (int)(4.99*(ref*ma->r));
+ g= (int)(4.99*(ref*ma->g));
+ b= (int)(4.99*(ref*ma->b));
+ nr= r + 5*g + 25*b;
+ if(nr>124) nr= 124;
+ new_id(&G.main->mat, (ID *)ma, colname_array[nr]);
+
+}
+
+
+void delete_material_index()
+{
+ Material *mao, ***matarar;
+ Object *ob, *obt;
+ Mesh *me;
+ Curve *cu;
+ Nurb *nu;
+ MFace *mface;
+ short *totcolp;
+ int a, actcol;
+
+ if(G.obedit) {
+ error("Unable to perform function in EditMode");
+ return;
+ }
+ ob= ((G.scene->basact)? (G.scene->basact->object) : 0) ;
+ if(ob==0 || ob->totcol==0) return;
+
+ /* neem als uitgangspunt de mesh/curve/mball, verwijder 1 index, EN bij alle ob's
+ * die ook zelfde ob->data hebben
+ *
+ * Daarna ook indexen in mesh/curve/mball wijzigen!!!
+ */
+
+ totcolp= give_totcolp(ob);
+ matarar= give_matarar(ob);
+
+ /* we deleten de actcol */
+ if(ob->totcol) {
+ mao= (*matarar)[ob->actcol-1];
+ if(mao) mao->id.us--;
+ }
+
+ for(a=ob->actcol; a<ob->totcol; a++) {
+ (*matarar)[a-1]= (*matarar)[a];
+ }
+ (*totcolp)--;
+
+ if(*totcolp==0) {
+ MEM_freeN(*matarar);
+ *matarar= 0;
+ }
+
+ actcol= ob->actcol;
+ obt= G.main->object.first;
+ while(obt) {
+
+ if(obt->data==ob->data) {
+
+ /* LET OP: actcol hier niet van ob of van obt pakken (kan nul worden) */
+ mao= obt->mat[actcol-1];
+ if(mao) mao->id.us--;
+
+ for(a=actcol; a<obt->totcol; a++) obt->mat[a-1]= obt->mat[a];
+ obt->totcol--;
+ if(obt->actcol > obt->totcol) obt->actcol= obt->totcol;
+
+ if(obt->totcol==0) {
+ MEM_freeN(obt->mat);
+ obt->mat= 0;
+ }
+ }
+ obt= obt->id.next;
+ }
+ allqueue(REDRAWBUTSMAT, 0);
+
+
+ /* indexen van mesh goedzetten */
+
+ if(ob->type==OB_MESH) {
+ me= get_mesh(ob);
+ mface= me->mface;
+ a= me->totface;
+ while(a--) {
+ if(mface->mat_nr && mface->mat_nr>=actcol-1) mface->mat_nr--;
+ mface++;
+ }
+ makeDispList(ob);
+ }
+ else if ELEM(ob->type, OB_CURVE, OB_SURF) {
+ cu= ob->data;
+ nu= cu->nurb.first;
+
+ while(nu) {
+ if(nu->mat_nr && nu->mat_nr>=actcol-1) nu->mat_nr--;
+ nu= nu->next;
+ }
+ makeDispList(ob);
+ }
+}
diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c
new file mode 100644
index 00000000000..9f09191f9d2
--- /dev/null
+++ b/source/blender/blenkernel/intern/mball.c
@@ -0,0 +1,1540 @@
+/* mball.c MIXED MODEL
+ *
+ * mei 95
+ *
+ *
+ *
+ * METABALLS ontstaan vanuit een Object (naam zonder nr), hier zit de DispList en boundbox,
+ * alle objecten met zelfde naam (en een nr) worden hieraan toegevoegd.
+ *
+ * De texture coordinaten zitten als loos element in de displist.
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 <string.h>
+#include <math.h>
+#include <stdlib.h>
+#include "MEM_guardedalloc.h"
+
+#include "DNA_material_types.h"
+#include "DNA_object_types.h"
+#include "DNA_meta_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_mesh_types.h"
+
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_bad_level_calls.h"
+
+#include "BKE_global.h"
+#include "BKE_main.h"
+
+/* #include "BKE_object.h" */
+#include "BKE_scene.h"
+#include "BKE_blender.h"
+#include "BKE_library.h"
+#include "BKE_displist.h"
+#include "BKE_mball.h"
+
+/* Functions */
+
+
+
+void unlink_mball(MetaBall *mb)
+{
+ int a;
+
+ for(a=0; a<mb->totcol; a++) {
+ if(mb->mat[a]) mb->mat[a]->id.us--;
+ mb->mat[a]= 0;
+ }
+
+
+}
+
+
+/* niet mball zelf vrijgeven */
+void free_mball(MetaBall *mb)
+{
+
+ unlink_mball(mb);
+
+ if(mb->mat) MEM_freeN(mb->mat);
+ if(mb->bb) MEM_freeN(mb->bb);
+ BLI_freelistN(&mb->elems);
+ if(mb->disp.first) freedisplist(&mb->disp);
+}
+
+MetaBall *add_mball()
+{
+ MetaBall *mb;
+
+ mb= alloc_libblock(&G.main->mball, ID_MB, "Meta");
+
+ mb->size[0]= mb->size[1]= mb->size[2]= 1.0;
+ mb->texflag= AUTOSPACE;
+
+ mb->wiresize= 0.4f;
+ mb->rendersize= 0.2f;
+ mb->thresh= 0.6f;
+
+ return mb;
+}
+
+MetaBall *copy_mball(MetaBall *mb)
+{
+ MetaBall *mbn;
+ int a;
+
+ mbn= copy_libblock(mb);
+
+ duplicatelist(&mbn->elems, &mb->elems);
+
+ mbn->mat= MEM_dupallocN(mb->mat);
+ for(a=0; a<mbn->totcol; a++) {
+ id_us_plus((ID *)mbn->mat[a]);
+ }
+ mbn->bb= MEM_dupallocN(mb->bb);
+
+ return mbn;
+}
+
+void make_local_mball(MetaBall *mb)
+{
+ Object *ob;
+ MetaBall *mbn;
+ int local=0, lib=0;
+
+ /* - zijn er alleen lib users: niet doen
+ * - zijn er alleen locale users: flag zetten
+ * - mixed: copy
+ */
+
+ if(mb->id.lib==0) return;
+ if(mb->id.us==1) {
+ mb->id.lib= 0;
+ mb->id.flag= LIB_LOCAL;
+ return;
+ }
+
+ ob= G.main->object.first;
+ while(ob) {
+ if(ob->data==mb) {
+ if(ob->id.lib) lib= 1;
+ else local= 1;
+ }
+ ob= ob->id.next;
+ }
+
+ if(local && lib==0) {
+ mb->id.lib= 0;
+ mb->id.flag= LIB_LOCAL;
+ }
+ else if(local && lib) {
+ mbn= copy_mball(mb);
+ mbn->id.us= 0;
+
+ ob= G.main->object.first;
+ while(ob) {
+ if(ob->data==mb) {
+
+ if(ob->id.lib==0) {
+ ob->data= mbn;
+ mbn->id.us++;
+ mb->id.us--;
+ }
+ }
+ ob= ob->id.next;
+ }
+ }
+}
+
+
+void tex_space_mball(Object *ob)
+{
+ DispList *dl;
+ BoundBox *bb;
+ float *data, min[3], max[3], loc[3], size[3];
+ int tot, doit=0;
+
+ if(ob->bb==0) ob->bb= MEM_callocN(sizeof(BoundBox), "mb boundbox");
+ bb= ob->bb;
+
+ /* Weird one, this. */
+/* INIT_MINMAX(min, max); */
+ (min)[0]= (min)[1]= (min)[2]= 1.0e30f;
+ (max)[0]= (max)[1]= (max)[2]= -1.0e30f;
+
+ dl= ob->disp.first;
+ while(dl) {
+ tot= dl->nr;
+ if(tot) doit= 1;
+ data= dl->verts;
+ while(tot--) {
+ /* Also weird... but longer. From utildefines. */
+ DO_MINMAX(data, min, max);
+ data+= 3;
+ }
+ dl= dl->next;
+ }
+
+ if(doit) {
+ loc[0]= (min[0]+max[0])/2.0f;
+ loc[1]= (min[1]+max[1])/2.0f;
+ loc[2]= (min[2]+max[2])/2.0f;
+
+ size[0]= (max[0]-min[0])/2.0f;
+ size[1]= (max[1]-min[1])/2.0f;
+ size[2]= (max[2]-min[2])/2.0f;
+ }
+ else {
+ loc[0]= loc[1]= loc[2]= 0.0f;
+ size[0]= size[1]= size[2]= 1.0f;
+ }
+
+ bb->vec[0][0]=bb->vec[1][0]=bb->vec[2][0]=bb->vec[3][0]= loc[0]-size[0];
+ bb->vec[4][0]=bb->vec[5][0]=bb->vec[6][0]=bb->vec[7][0]= loc[0]+size[0];
+
+ bb->vec[0][1]=bb->vec[1][1]=bb->vec[4][1]=bb->vec[5][1]= loc[1]-size[1];
+ bb->vec[2][1]=bb->vec[3][1]=bb->vec[6][1]=bb->vec[7][1]= loc[1]+size[1];
+
+ bb->vec[0][2]=bb->vec[3][2]=bb->vec[4][2]=bb->vec[7][2]= loc[2]-size[2];
+ bb->vec[1][2]=bb->vec[2][2]=bb->vec[5][2]=bb->vec[6][2]= loc[2]+size[2];
+
+}
+
+void make_orco_mball(Object *ob)
+{
+ BoundBox *bb;
+ DispList *dl;
+ float *data;
+ float loc[3], size[3];
+ int a;
+
+ /* size en loc restoren */
+ bb= ob->bb;
+ loc[0]= (bb->vec[0][0]+bb->vec[4][0])/2.0f;
+ size[0]= bb->vec[4][0]-loc[0];
+ loc[1]= (bb->vec[0][1]+bb->vec[2][1])/2.0f;
+ size[1]= bb->vec[2][1]-loc[1];
+ loc[2]= (bb->vec[0][2]+bb->vec[1][2])/2.0f;
+ size[2]= bb->vec[1][2]-loc[2];
+
+ dl= ob->disp.first;
+ data= dl->verts;
+ a= dl->nr;
+ while(a--) {
+ data[0]= (data[0]-loc[0])/size[0];
+ data[1]= (data[1]-loc[1])/size[1];
+ data[2]= (data[2]-loc[2])/size[2];
+
+ data+= 3;
+ }
+}
+
+
+Object *find_basis_mball(Object *basis)
+{
+ Base *base;
+ int basisnr;
+ char basisname[32];
+
+ splitIDname(basis->id.name+2, basisname, &basisnr);
+
+ for (base= G.scene->base.first; base && basisnr; base= base->next) {
+ Object *ob= base->object;
+
+ if (ob!=basis && ob->type==OB_MBALL) {
+ char obname[32];
+ int obnr;
+
+ splitIDname(ob->id.name+2, obname, &obnr);
+
+ if ((strcmp(obname, basisname)==0) && obnr<basisnr) {
+ basis= ob;
+ basisnr= obnr;
+ }
+ }
+ }
+
+ return basis;
+}
+
+
+/* ******************** ARITH ************************* */
+
+/* DANKBAAR GEBRUIK GEMAAKT VAN (EN COMPLEET VERANDERD) :
+ * C code from the article
+ * "An Implicit Surface Polygonizer"
+ * by Jules Bloomenthal, jbloom@beauty.gmu.edu
+ * in "Graphics Gems IV", Academic Press, 1994
+
+ * Authored by Jules Bloomenthal, Xerox PARC.
+ * Copyright (c) Xerox Corporation, 1991. All rights reserved.
+ * Permission is granted to reproduce, use and distribute this code for
+ * any and all purposes, provided that this notice appears in all copies. */
+
+#define RES 12 /* # converge iterations */
+
+#define L 0 /* left direction: -x, -i */
+#define R 1 /* right direction: +x, +i */
+#define B 2 /* bottom direction: -y, -j */
+#define T 3 /* top direction: +y, +j */
+#define N 4 /* near direction: -z, -k */
+#define F 5 /* far direction: +z, +k */
+#define LBN 0 /* left bottom near corner */
+#define LBF 1 /* left bottom far corner */
+#define LTN 2 /* left top near corner */
+#define LTF 3 /* left top far corner */
+#define RBN 4 /* right bottom near corner */
+#define RBF 5 /* right bottom far corner */
+#define RTN 6 /* right top near corner */
+#define RTF 7 /* right top far corner */
+
+/* the LBN corner of cube (i, j, k), corresponds with location
+ * (start.x+(i-0.5)*size, start.y+(j-0.5)*size, start.z+(k-0.5)*size) */
+
+#define HASHBIT (5)
+#define HASHSIZE (size_t)(1<<(3*HASHBIT)) /* hash table size (32768) */
+
+#define HASH(i,j,k) ((((( (i) & 31)<<5) | ( (j) & 31))<<5 ) | ( (k) & 31) )
+
+#define MB_BIT(i, bit) (((i)>>(bit))&1)
+#define FLIP(i,bit) ((i)^1<<(bit)) /* flip the given bit of i */
+
+typedef struct point { /* a three-dimensional point */
+ float x, y, z; /* its coordinates */
+} MB_POINT;
+
+typedef struct vertex { /* surface vertex */
+ MB_POINT position, normal; /* position and surface normal */
+} VERTEX;
+
+typedef struct vertices { /* list of vertices in polygonization */
+ int count, max; /* # vertices, max # allowed */
+ VERTEX *ptr; /* dynamically allocated */
+} VERTICES;
+
+typedef struct corner { /* corner of a cube */
+ int i, j, k; /* (i, j, k) is index within lattice */
+ float x, y, z, value; /* location and function value */
+ struct corner *next;
+} CORNER;
+
+typedef struct cube { /* partitioning cell (cube) */
+ int i, j, k; /* lattice location of cube */
+ CORNER *corners[8]; /* eight corners */
+} CUBE;
+
+typedef struct cubes { /* linked list of cubes acting as stack */
+ CUBE cube; /* a single cube */
+ struct cubes *next; /* remaining elements */
+} CUBES;
+
+typedef struct centerlist { /* list of cube locations */
+ int i, j, k; /* cube location */
+ struct centerlist *next; /* remaining elements */
+} CENTERLIST;
+
+typedef struct edgelist { /* list of edges */
+ int i1, j1, k1, i2, j2, k2; /* edge corner ids */
+ int vid; /* vertex id */
+ struct edgelist *next; /* remaining elements */
+} EDGELIST;
+
+typedef struct intlist { /* list of integers */
+ int i; /* an integer */
+ struct intlist *next; /* remaining elements */
+} INTLIST;
+
+typedef struct intlists { /* list of list of integers */
+ INTLIST *list; /* a list of integers */
+ struct intlists *next; /* remaining elements */
+} INTLISTS;
+
+typedef struct process { /* parameters, function, storage */
+ /* what happens here? floats, I think. */
+ /* float (*function)(void); */ /* implicit surface function */
+ float (*function)(float, float, float);
+ float size, delta; /* cube size, normal delta */
+ int bounds; /* cube range within lattice */
+ MB_POINT start; /* start point on surface */
+ CUBES *cubes; /* active cubes */
+ VERTICES vertices; /* surface vertices */
+ CENTERLIST **centers; /* cube center hash table */
+ CORNER **corners; /* corner value hash table */
+ EDGELIST **edges; /* edge and vertex id hash table */
+} PROCESS;
+
+/* Some declarations are in order !!! */
+
+/* these should go into a header ! But the compiler doesn't like that,
+ * for some reason */
+
+void freepolygonize(PROCESS *p);
+void docube(CUBE *cube, PROCESS *p);
+void testface(int i, int j, int k, CUBE* old,
+ int bit, int c1, int c2, int c3, int c4, PROCESS *p);
+CORNER *setcorner (PROCESS* p, int i, int j, int k);
+int vertid (CORNER *c1, CORNER *c2, PROCESS *p);
+int setcenter(CENTERLIST *table[], int i, int j, int k);
+int otherface (int edge, int face);
+void makecubetable (void);
+void setedge (EDGELIST *table[],
+ int i1, int j1,
+ int k1, int i2,
+ int j2, int k2,
+ int vid);
+int getedge (EDGELIST *table[],
+ int i1, int j1, int k1,
+ int i2, int j2, int k2);
+void addtovertices (VERTICES *vertices, VERTEX v);
+void vnormal (MB_POINT *point, PROCESS *p, MB_POINT *v);
+void converge (MB_POINT *p1, MB_POINT *p2, float v,
+ float (*function)(float, float, float), MB_POINT *p);
+void polygonize(PROCESS *mbproc);
+float init_meta(Object *ob);
+
+/* **************** METABALL ************************ */
+
+/* void converge (MB_POINT *p1, MB_POINT *p2, float v, float (*function)(void), MB_POINT *p); */
+
+void calc_mballco(MetaElem *ml, float *vec)
+{
+ if(ml->mat) {
+ Mat4MulVecfl(ml->mat, vec);
+ }
+}
+
+
+float thresh= 0.6f;
+int totelem=0;
+MetaElem **mainb;
+
+float densfunc(MetaElem *ball, float x, float y, float z)
+{
+ float dist2 = 0.0, dx, dy, dz;
+ float vec[3];
+
+ if(ball->imat) {
+ vec[0]= x;
+ vec[1]= y;
+ vec[2]= z;
+ Mat4MulVecfl(ball->imat, vec);
+ dx= ball->x - vec[0];
+ dy= ball->y - vec[1];
+ dz= ball->z - vec[2];
+ }
+ else {
+ dx= ball->x - x;
+ dy= ball->y - y;
+ dz= ball->z - z;
+ }
+
+ if(ball->type==MB_BALL) {
+ dist2= (dx*dx + dy*dy + dz*dz);
+ }
+ else if(ball->type & MB_TUBEZ) {
+ if(ball->type==MB_TUBEZ) {
+ if( dz > ball->len) dz-= ball->len;
+ else if(dz< -ball->len) dz+= ball->len;
+ else dz= 0.0;
+ }
+ else if(ball->type==MB_TUBEY) {
+ if( dy > ball->len) dy-= ball->len;
+ else if(dy< -ball->len) dy+= ball->len;
+ else dy= 0.0;
+ }
+ else {
+ if( dx > ball->len) dx-= ball->len;
+ else if(dx< -ball->len) dx+= ball->len;
+ else dx= 0.0;
+ }
+ dist2= (dx*dx + dy*dy + dz*dz);
+ }
+ /* else if(ball->type==MB_CIRCLE) { */
+ /* dist2= 0.5-dz; */
+ /* } */
+
+ if(ball->flag & MB_NEGATIVE) {
+
+ dist2= 1.0f-(dist2/ball->rad2);
+ if(dist2 < 0.0) return 0.5f;
+
+ return 0.5f-ball->s*dist2*dist2*dist2;
+
+ }
+ else {
+ dist2= 1.0f-(dist2/ball->rad2);
+ if(dist2 < 0.0) return -0.5f;
+
+ return ball->s*dist2*dist2*dist2 -0.5f;
+
+ /* return ball->s*sin( dist2); */
+
+ }
+
+}
+
+
+float metaball(float x, float y, float z)
+/* float x, y, z; */
+{
+ float dens=0;
+ int a;
+
+ for(a=0; a<totelem; a++) {
+ dens+= densfunc( mainb[a], x, y, z);
+ }
+
+ return thresh - dens;
+}
+
+/* ******************************************** */
+
+int *indices=0;
+int totindex, curindex;
+
+
+void accum_mballfaces(int i1, int i2, int i3, int i4)
+{
+ int *newi, *cur;
+ /* static int i=0; I would like to delete altogether, but I don't dare to, yet */
+
+ if(totindex==curindex) {
+ totindex+= 256;
+ newi= MEM_mallocN(4*sizeof(int)*totindex, "vertindex");
+
+ if(indices) {
+ memcpy(newi, indices, 4*sizeof(int)*(totindex-256));
+ MEM_freeN(indices);
+ }
+ indices= newi;
+ }
+
+ cur= indices+4*curindex;
+
+ /* voorkomen dat nulcodes voorkomen */
+ if(i3==0) {
+ if(i4) {
+ i3= i4;
+ i4= i1;
+ i1= i2;
+ i2= 0;
+ }
+ else {
+ i3= i2;
+ i2= i1;
+ i1= 0;
+ }
+ }
+
+ cur[0]= i1;
+ cur[1]= i2;
+ cur[2]= i3;
+ cur[3]= i4;
+
+ curindex++;
+
+}
+
+/* ******************* MEMORY MANAGEMENT *********************** */
+
+struct pgn_elements {
+ struct pgn_elements *next, *prev;
+ char *data;
+
+};
+
+void *new_pgn_element(int size)
+{
+ /* gedurende het polygonizeren worden duizenden elementen aangemaakt en
+ * nooit (tussendoor) vrijgegeven. Alleen op eind is vrijgeven nodig.
+ */
+ int blocksize= 16384;
+ static int offs= 0; /* het huidige vrije adres */
+ static struct pgn_elements *cur= 0;
+ static ListBase lb= {0, 0};
+ void *adr;
+
+ if(size>10000 || size==0) {
+ printf("incorrect use of new_pgn_element\n");
+ /* exit(0); */
+ }
+ else if(size== -1) {
+ cur= lb.first;
+ while(cur) {
+ MEM_freeN(cur->data);
+ cur= cur->next;
+ }
+ BLI_freelistN(&lb);
+
+ return NULL;
+ }
+
+ size= 4*( (size+3)/4 );
+
+ if(cur) {
+ if(size+offs < blocksize) {
+ adr= (void *) (cur->data+offs);
+ offs+= size;
+ return adr;
+ }
+ }
+
+ cur= MEM_callocN( sizeof(struct pgn_elements), "newpgn");
+ cur->data= MEM_callocN(blocksize, "newpgn");
+ BLI_addtail(&lb, cur);
+
+ offs= size;
+ return cur->data;
+}
+
+void freepolygonize(PROCESS *p)
+{
+ MEM_freeN(p->corners);
+ MEM_freeN(p->edges);
+ MEM_freeN(p->centers);
+
+ new_pgn_element(-1);
+
+ if(p->vertices.ptr) MEM_freeN(p->vertices.ptr);
+}
+
+/**** Cubical Polygonization (optional) ****/
+
+
+#define LB 0 /* left bottom edge */
+#define LT 1 /* left top edge */
+#define LN 2 /* left near edge */
+#define LF 3 /* left far edge */
+#define RB 4 /* right bottom edge */
+#define RT 5 /* right top edge */
+#define RN 6 /* right near edge */
+#define RF 7 /* right far edge */
+#define BN 8 /* bottom near edge */
+#define BF 9 /* bottom far edge */
+#define TN 10 /* top near edge */
+#define TF 11 /* top far edge */
+
+static INTLISTS *cubetable[256];
+
+/* edge: LB, LT, LN, LF, RB, RT, RN, RF, BN, BF, TN, TF */
+static int corner1[12] = {
+ LBN,LTN,LBN,LBF,RBN,RTN,RBN,RBF,LBN,LBF,LTN,LTF};
+static int corner2[12] = {
+ LBF,LTF,LTN,LTF,RBF,RTF,RTN,RTF,RBN,RBF,RTN,RTF};
+static int leftface[12] = {
+ B, L, L, F, R, T, N, R, N, B, T, F};
+/* face on left when going corner1 to corner2 */
+static int rightface[12] = {
+ L, T, N, L, B, R, R, F, B, F, N, T};
+/* face on right when going corner1 to corner2 */
+
+
+/* docube: triangulate the cube directly, without decomposition */
+
+void docube(CUBE *cube, PROCESS *p)
+{
+ INTLISTS *polys;
+ CORNER *c1, *c2;
+ int i, index = 0, count, indexar[8];
+
+ for (i = 0; i < 8; i++) if (cube->corners[i]->value > 0.0) index += (1<<i);
+
+ for (polys = cubetable[index]; polys; polys = polys->next) {
+ INTLIST *edges;
+
+ count = 0;
+
+ for (edges = polys->list; edges; edges = edges->next) {
+ c1 = cube->corners[corner1[edges->i]];
+ c2 = cube->corners[corner2[edges->i]];
+
+ indexar[count] = vertid(c1, c2, p);
+ count++;
+ }
+ if(count>2) {
+ switch(count) {
+ case 3:
+ accum_mballfaces(indexar[2], indexar[1], indexar[0], 0);
+ break;
+ case 4:
+ if(indexar[0]==0) accum_mballfaces(indexar[0], indexar[3], indexar[2], indexar[1]);
+ else accum_mballfaces(indexar[3], indexar[2], indexar[1], indexar[0]);
+ break;
+ case 5:
+ if(indexar[0]==0) accum_mballfaces(indexar[0], indexar[3], indexar[2], indexar[1]);
+ else accum_mballfaces(indexar[3], indexar[2], indexar[1], indexar[0]);
+
+ accum_mballfaces(indexar[4], indexar[3], indexar[0], 0);
+ break;
+ case 6:
+ if(indexar[0]==0) {
+ accum_mballfaces(indexar[0], indexar[3], indexar[2], indexar[1]);
+ accum_mballfaces(indexar[0], indexar[5], indexar[4], indexar[3]);
+ }
+ else {
+ accum_mballfaces(indexar[3], indexar[2], indexar[1], indexar[0]);
+ accum_mballfaces(indexar[5], indexar[4], indexar[3], indexar[0]);
+ }
+ break;
+ case 7:
+ if(indexar[0]==0) {
+ accum_mballfaces(indexar[0], indexar[3], indexar[2], indexar[1]);
+ accum_mballfaces(indexar[0], indexar[5], indexar[4], indexar[3]);
+ }
+ else {
+ accum_mballfaces(indexar[3], indexar[2], indexar[1], indexar[0]);
+ accum_mballfaces(indexar[5], indexar[4], indexar[3], indexar[0]);
+ }
+
+ accum_mballfaces(indexar[6], indexar[5], indexar[0], 0);
+
+ break;
+ }
+ }
+ }
+}
+
+
+/* testface: given cube at lattice (i, j, k), and four corners of face,
+ * if surface crosses face, compute other four corners of adjacent cube
+ * and add new cube to cube stack */
+
+void testface(int i, int j, int k, CUBE* old, int bit, int c1, int c2, int c3, int c4, PROCESS *p)
+/* CUBE *old; */
+/* PROCESS *p; */
+/* int i, j, k, bit, c1, c2, c3, c4; */
+{
+ CUBE newc;
+ CUBES *oldcubes = p->cubes;
+ CORNER *corn1, *corn2, *corn3, *corn4;
+ int n, pos;
+
+ corn1= old->corners[c1];
+ corn2= old->corners[c2];
+ corn3= old->corners[c3];
+ corn4= old->corners[c4];
+
+ pos = corn1->value > 0.0 ? 1 : 0;
+
+ /* test if no surface crossing */
+ if( (corn2->value > 0) == pos && (corn3->value > 0) == pos && (corn4->value > 0) == pos) return;
+ /* test if cube out of bounds */
+ if ( abs(i) > p->bounds || abs(j) > p->bounds || abs(k) > p->bounds) return;
+ /* test if already visited (always as last) */
+ if (setcenter(p->centers, i, j, k)) return;
+
+
+ /* create new cube and add cube to top of stack: */
+ p->cubes = (CUBES *) new_pgn_element(sizeof(CUBES));
+ p->cubes->next = oldcubes;
+
+ newc.i = i;
+ newc.j = j;
+ newc.k = k;
+ for (n = 0; n < 8; n++) newc.corners[n] = NULL;
+
+ newc.corners[FLIP(c1, bit)] = corn1;
+ newc.corners[FLIP(c2, bit)] = corn2;
+ newc.corners[FLIP(c3, bit)] = corn3;
+ newc.corners[FLIP(c4, bit)] = corn4;
+
+ if(newc.corners[0]==0) newc.corners[0] = setcorner(p, i, j, k);
+ if(newc.corners[1]==0) newc.corners[1] = setcorner(p, i, j, k+1);
+ if(newc.corners[2]==0) newc.corners[2] = setcorner(p, i, j+1, k);
+ if(newc.corners[3]==0) newc.corners[3] = setcorner(p, i, j+1, k+1);
+ if(newc.corners[4]==0) newc.corners[4] = setcorner(p, i+1, j, k);
+ if(newc.corners[5]==0) newc.corners[5] = setcorner(p, i+1, j, k+1);
+ if(newc.corners[6]==0) newc.corners[6] = setcorner(p, i+1, j+1, k);
+ if(newc.corners[7]==0) newc.corners[7] = setcorner(p, i+1, j+1, k+1);
+
+ p->cubes->cube= newc;
+}
+
+/* setcorner: return corner with the given lattice location
+ set (and cache) its function value */
+
+CORNER *setcorner (PROCESS* p, int i, int j, int k)
+/* int i, j, k; */
+/* PROCESS *p; */
+{
+ /* for speed, do corner value caching here */
+ CORNER *c;
+ int index;
+
+ /* bestaat corner al? */
+ index = HASH(i, j, k);
+ c = p->corners[index];
+
+ for (; c != NULL; c = c->next) {
+ if (c->i == i && c->j == j && c->k == k) {
+ return c;
+ }
+ }
+
+ c = (CORNER *) new_pgn_element(sizeof(CORNER));
+
+ c->i = i;
+ c->x = p->start.x+((float)i-0.5f)*p->size;
+ c->j = j;
+ c->y = p->start.y+((float)j-0.5f)*p->size;
+ c->k = k;
+ c->z = p->start.z+((float)k-0.5f)*p->size;
+ c->value = p->function(c->x, c->y, c->z);
+
+ c->next = p->corners[index];
+ p->corners[index] = c;
+
+ return c;
+}
+
+
+/* nextcwedge: return next clockwise edge from given edge around given face */
+
+int nextcwedge (int edge, int face)
+{
+ switch (edge) {
+ case LB:
+ return (face == L)? LF : BN;
+ case LT:
+ return (face == L)? LN : TF;
+ case LN:
+ return (face == L)? LB : TN;
+ case LF:
+ return (face == L)? LT : BF;
+ case RB:
+ return (face == R)? RN : BF;
+ case RT:
+ return (face == R)? RF : TN;
+ case RN:
+ return (face == R)? RT : BN;
+ case RF:
+ return (face == R)? RB : TF;
+ case BN:
+ return (face == B)? RB : LN;
+ case BF:
+ return (face == B)? LB : RF;
+ case TN:
+ return (face == T)? LT : RN;
+ case TF:
+ return (face == T)? RT : LF;
+ }
+ return 0;
+}
+
+
+/* otherface: return face adjoining edge that is not the given face */
+
+int otherface (int edge, int face)
+/* int edge, face; */
+{
+ int other = leftface[edge];
+ return face == other? rightface[edge] : other;
+}
+
+
+/* makecubetable: create the 256 entry table for cubical polygonization */
+
+void makecubetable (void)
+{
+ static int isdone= 0;
+ int i, e, c, done[12], pos[8];
+
+ if(isdone) return;
+ isdone= 1;
+
+ for (i = 0; i < 256; i++) {
+ for (e = 0; e < 12; e++) done[e] = 0;
+ for (c = 0; c < 8; c++) pos[c] = MB_BIT(i, c);
+ for (e = 0; e < 12; e++)
+ if (!done[e] && (pos[corner1[e]] != pos[corner2[e]])) {
+ INTLIST *ints = 0;
+ INTLISTS *lists = (INTLISTS *) MEM_callocN(sizeof(INTLISTS), "mball_intlist");
+ int start = e, edge = e;
+
+ /* get face that is to right of edge from pos to neg corner: */
+ int face = pos[corner1[e]]? rightface[e] : leftface[e];
+
+ while (1) {
+ edge = nextcwedge(edge, face);
+ done[edge] = 1;
+ if (pos[corner1[edge]] != pos[corner2[edge]]) {
+ INTLIST *tmp = ints;
+
+ ints = (INTLIST *) MEM_callocN(sizeof(INTLIST), "mball_intlist");
+ ints->i = edge;
+ ints->next = tmp; /* add edge to head of list */
+
+ if (edge == start) break;
+ face = otherface(edge, face);
+ }
+ }
+ lists->list = ints; /* add ints to head of table entry */
+ lists->next = cubetable[i];
+ cubetable[i] = lists;
+ }
+ }
+}
+
+void BKE_freecubetable(void)
+{
+ int i;
+ INTLISTS *lists, *nlists;
+ INTLIST *ints, *nints;
+
+ for (i = 0; i < 256; i++) {
+ lists= cubetable[i];
+ while(lists) {
+ nlists= lists->next;
+
+ ints= lists->list;
+ while(ints) {
+ nints= ints->next;
+ MEM_freeN(ints);
+ ints= nints;
+ }
+
+ MEM_freeN(lists);
+ lists= nlists;
+ }
+ cubetable[i]= 0;
+ }
+}
+
+/**** Storage ****/
+
+/* setcenter: set (i,j,k) entry of table[]
+ * return 1 if already set; otherwise, set and return 0 */
+
+int setcenter(CENTERLIST *table[], int i, int j, int k)
+/* CENTERLIST *table[]; */
+/* int i, j, k; */
+{
+ int index;
+ CENTERLIST *newc, *l, *q;
+
+ index= HASH(i, j, k);
+ q= table[index];
+
+ for (l = q; l != NULL; l = l->next) {
+ if (l->i == i && l->j == j && l->k == k) return 1;
+ }
+
+ newc = (CENTERLIST *) new_pgn_element(sizeof(CENTERLIST));
+ newc->i = i;
+ newc->j = j;
+ newc->k = k;
+ newc->next = q;
+ table[index] = newc;
+
+ return 0;
+}
+
+
+/* setedge: set vertex id for edge */
+
+void setedge (EDGELIST *table[],
+ int i1, int j1,
+ int k1, int i2,
+ int j2, int k2,
+ int vid)
+/* EDGELIST *table[]; */
+/* int i1, j1, k1, i2, j2, k2, vid; */
+{
+ unsigned int index;
+ EDGELIST *newe;
+
+ if (i1>i2 || (i1==i2 && (j1>j2 || (j1==j2 && k1>k2)))) {
+ int t=i1;
+ i1=i2;
+ i2=t;
+ t=j1;
+ j1=j2;
+ j2=t;
+ t=k1;
+ k1=k2;
+ k2=t;
+ }
+ index = HASH(i1, j1, k1) + HASH(i2, j2, k2);
+ newe = (EDGELIST *) new_pgn_element(sizeof(EDGELIST));
+ newe->i1 = i1;
+ newe->j1 = j1;
+ newe->k1 = k1;
+ newe->i2 = i2;
+ newe->j2 = j2;
+ newe->k2 = k2;
+ newe->vid = vid;
+ newe->next = table[index];
+ table[index] = newe;
+}
+
+
+/* getedge: return vertex id for edge; return -1 if not set */
+
+int getedge (EDGELIST *table[],
+ int i1, int j1, int k1,
+ int i2, int j2, int k2)
+/* EDGELIST *table[]; */
+/* int i1, j1, k1, i2, j2, k2; */
+{
+ EDGELIST *q;
+
+ if (i1>i2 || (i1==i2 && (j1>j2 || (j1==j2 && k1>k2)))) {
+ int t=i1;
+ i1=i2;
+ i2=t;
+ t=j1;
+ j1=j2;
+ j2=t;
+ t=k1;
+ k1=k2;
+ k2=t;
+ }
+ q = table[HASH(i1, j1, k1)+HASH(i2, j2, k2)];
+ for (; q != NULL; q = q->next)
+ if (q->i1 == i1 && q->j1 == j1 && q->k1 == k1 &&
+ q->i2 == i2 && q->j2 == j2 && q->k2 == k2)
+ return q->vid;
+ return -1;
+}
+
+
+/**** Vertices ****/
+
+#undef R
+
+
+
+/* vertid: return index for vertex on edge:
+ * c1->value and c2->value are presumed of different sign
+ * return saved index if any; else compute vertex and save */
+
+/* addtovertices: add v to sequence of vertices */
+
+void addtovertices (VERTICES *vertices, VERTEX v)
+/* VERTICES *vertices; */
+/* VERTEX v; */
+{
+ if (vertices->count == vertices->max) {
+ int i;
+ VERTEX *newv;
+ vertices->max = vertices->count == 0 ? 10 : 2*vertices->count;
+ newv = (VERTEX *) MEM_callocN(vertices->max * sizeof(VERTEX), "addtovertices");
+
+ for (i = 0; i < vertices->count; i++) newv[i] = vertices->ptr[i];
+
+ if (vertices->ptr != NULL) MEM_freeN(vertices->ptr);
+ vertices->ptr = newv;
+ }
+ vertices->ptr[vertices->count++] = v;
+}
+
+/* vnormal: compute unit length surface normal at point */
+
+void vnormal (MB_POINT *point, PROCESS *p, MB_POINT *v)
+/* MB_POINT *point, *v; */
+/* PROCESS *p; */
+{
+ float delta= 0.2f*p->delta;
+ float f = p->function(point->x, point->y, point->z);
+
+ v->x = p->function(point->x+delta, point->y, point->z)-f;
+ v->y = p->function(point->x, point->y+delta, point->z)-f;
+ v->z = p->function(point->x, point->y, point->z+delta)-f;
+ f = (float)sqrt(v->x*v->x + v->y*v->y + v->z*v->z);
+
+ if (f != 0.0) {
+ v->x /= f;
+ v->y /= f;
+ v->z /= f;
+ }
+
+ if(FALSE) {
+ /* if(R.flag & R_RENDERING) { */
+ MB_POINT temp;
+
+ delta*= 2.0;
+
+ f = p->function(point->x, point->y, point->z);
+
+ temp.x = p->function(point->x+delta, point->y, point->z)-f;
+ temp.y = p->function(point->x, point->y+delta, point->z)-f;
+ temp.z = p->function(point->x, point->y, point->z+delta)-f;
+ f = (float)sqrt(temp.x*temp.x + temp.y*temp.y + temp.z*temp.z);
+
+ if (f != 0.0) {
+ temp.x /= f;
+ temp.y /= f;
+ temp.z /= f;
+
+ v->x+= temp.x;
+ v->y+= temp.y;
+ v->z+= temp.z;
+
+ f = (float)sqrt(v->x*v->x + v->y*v->y + v->z*v->z);
+
+ if (f != 0.0) {
+ v->x /= f;
+ v->y /= f;
+ v->z /= f;
+ }
+ }
+ }
+
+}
+
+
+int vertid (CORNER *c1, CORNER *c2, PROCESS *p)
+/* CORNER *c1, *c2; */
+/* PROCESS *p; */
+{
+ VERTEX v;
+ MB_POINT a, b;
+ int vid = getedge(p->edges, c1->i, c1->j, c1->k, c2->i, c2->j, c2->k);
+
+ if (vid != -1) return vid; /* previously computed */
+ a.x = c1->x;
+ a.y = c1->y;
+ a.z = c1->z;
+ b.x = c2->x;
+ b.y = c2->y;
+ b.z = c2->z;
+
+ converge(&a, &b, c1->value, p->function, &v.position); /* position */
+ vnormal(&v.position, p, &v.normal);
+
+ addtovertices(&p->vertices, v); /* save vertex */
+ vid = p->vertices.count-1;
+ setedge(p->edges, c1->i, c1->j, c1->k, c2->i, c2->j, c2->k, vid);
+
+ return vid;
+}
+
+
+
+
+/* converge: from two points of differing sign, converge to zero crossing */
+/* watch it: p1 and p2 are used to calculate */
+
+void converge (MB_POINT *p1, MB_POINT *p2, float v,
+ float (*function)(float, float, float), MB_POINT *p)
+{
+ int i = 0;
+ MB_POINT *pos, *neg;
+
+ if (v < 0) {
+ pos= p2;
+ neg= p1;
+ }
+ else {
+ pos= p1;
+ neg= p2;
+ }
+ while (1) {
+ p->x = 0.5f*(pos->x + neg->x);
+ p->y = 0.5f*(pos->y + neg->y);
+ p->z = 0.5f*(pos->z + neg->z);
+
+ if (i++ == RES) return;
+
+ if ((function(p->x, p->y, p->z)) > 0.0) {
+ pos->x = p->x;
+ pos->y = p->y;
+ pos->z = p->z;
+ }
+ else {
+ neg->x = p->x;
+ neg->y = p->y;
+ neg->z = p->z;
+ }
+ }
+}
+
+/* ************************************** */
+
+
+void polygonize(PROCESS *mbproc)
+{
+ MB_POINT in, out;
+ CUBE c;
+ CUBES *ncube;
+/* CORNER *setcorner(); */
+ int a, n, i, j, k;
+
+ mbproc->vertices.count = mbproc->vertices.max = 0;
+ mbproc->vertices.ptr = NULL;
+
+ /* allocate hash tables and build cube polygon table: */
+ mbproc->centers = MEM_callocN(HASHSIZE * sizeof(CENTERLIST *), "mbproc->centers");
+ mbproc->corners = MEM_callocN(HASHSIZE * sizeof(CORNER *), "mbproc->corners");
+ mbproc->edges = MEM_callocN(2*HASHSIZE * sizeof(EDGELIST *), "mbproc->edges");
+ makecubetable();
+
+ /* find first point on balls */
+ for(a=0; a<totelem; a++) {
+
+ in.x= mainb[a]->x;
+ in.y= mainb[a]->y;
+ in.z= mainb[a]->z;
+ calc_mballco(mainb[a], (float *)&in);
+
+ /* added factor 2.0 to be sure it always finds the ball... still unsure why! */
+
+ out.x= in.x + 2.0f*mainb[a]->rad;
+ out.y= in.y + 2.0f*mainb[a]->rad;
+ out.z= in.z + 2.0f*mainb[a]->rad;
+ calc_mballco(mainb[a], (float *)&out);
+
+ converge(&in, &out, -1.0, mbproc->function, &mbproc->start);
+
+ /* NEW1: zorg voor correcte uitgangspositie */
+ i= (int)floor(mbproc->start.x/mbproc->size );
+ j= (int)floor(mbproc->start.y/mbproc->size );
+ k= (int)floor(mbproc->start.z/mbproc->size );
+
+ mbproc->start.x= mbproc->start.y= mbproc->start.z= 0.0;
+
+/* dit gaat niet altijd goed: soms wordt een bal niet gevonden. waarom? */
+
+ /* test if cube has been found before */
+ if( setcenter(mbproc->centers, i, j, k)==0 ) {
+
+ /* push cube on stack: */
+ ncube= (CUBES *) new_pgn_element(sizeof(CUBES));
+ ncube->next= mbproc->cubes;
+ mbproc->cubes= ncube;
+
+ ncube->cube.i= i;
+ ncube->cube.j= j;
+ ncube->cube.k= k;
+
+ /* set corners of initial cube: */
+ for (n = 0; n < 8; n++)
+ ncube->cube.corners[n] = setcorner(mbproc, i+MB_BIT(n,2), j+MB_BIT(n,1), k+MB_BIT(n,0));
+ }
+
+ /* we do a triple test and add a cube if necessary */
+ i++;
+
+ /* test if cube has been found before */
+ if( setcenter(mbproc->centers, i, j, k)==0 ) {
+
+ /* push cube on stack: */
+ ncube= (CUBES *) new_pgn_element(sizeof(CUBES));
+ ncube->next= mbproc->cubes;
+ mbproc->cubes= ncube;
+
+ ncube->cube.i= i;
+ ncube->cube.j= j;
+ ncube->cube.k= k;
+
+ /* set corners of initial cube: */
+ for (n = 0; n < 8; n++)
+ ncube->cube.corners[n] = setcorner(mbproc, i+MB_BIT(n,2), j+MB_BIT(n,1), k+MB_BIT(n,0));
+ }
+
+ i--;
+ j++;
+
+ /* test if cube has been found before */
+ if( setcenter(mbproc->centers, i, j, k)==0 ) {
+
+ /* push cube on stack: */
+ ncube= (CUBES *) new_pgn_element(sizeof(CUBES));
+ ncube->next= mbproc->cubes;
+ mbproc->cubes= ncube;
+
+ ncube->cube.i= i;
+ ncube->cube.j= j;
+ ncube->cube.k= k;
+
+ /* set corners of initial cube: */
+ for (n = 0; n < 8; n++)
+ ncube->cube.corners[n] = setcorner(mbproc, i+MB_BIT(n,2), j+MB_BIT(n,1), k+MB_BIT(n,0));
+ }
+
+ j--;
+ k++;
+
+ /* test if cube has been found before */
+ if( setcenter(mbproc->centers, i, j, k)==0 ) {
+
+ /* push cube on stack: */
+ ncube= (CUBES *) new_pgn_element(sizeof(CUBES));
+ ncube->next= mbproc->cubes;
+ mbproc->cubes= ncube;
+
+ ncube->cube.i= i;
+ ncube->cube.j= j;
+ ncube->cube.k= k;
+
+ /* set corners of initial cube: */
+ for (n = 0; n < 8; n++)
+ ncube->cube.corners[n] = setcorner(mbproc, i+MB_BIT(n,2), j+MB_BIT(n,1), k+MB_BIT(n,0));
+ }
+
+ i++;
+ j++;
+
+ /* test if cube has been found before */
+ if( setcenter(mbproc->centers, i, j, k)==0 ) {
+
+ /* push cube on stack: */
+ ncube= (CUBES *) new_pgn_element(sizeof(CUBES));
+ ncube->next= mbproc->cubes;
+ mbproc->cubes= ncube;
+
+ ncube->cube.i= i;
+ ncube->cube.j= j;
+ ncube->cube.k= k;
+
+ /* set corners of initial cube: */
+ for (n = 0; n < 8; n++)
+ ncube->cube.corners[n] = setcorner(mbproc, i+MB_BIT(n,2), j+MB_BIT(n,1), k+MB_BIT(n,0));
+ }
+ }
+
+ while (mbproc->cubes != NULL) { /* process active cubes till none left */
+ c = mbproc->cubes->cube;
+
+ /* polygonize the cube directly: */
+ docube(&c, mbproc);
+
+ /* pop current cube from stack */
+ mbproc->cubes = mbproc->cubes->next;
+
+ /* test six face directions, maybe add to stack: */
+ testface(c.i-1, c.j, c.k, &c, 2, LBN, LBF, LTN, LTF, mbproc);
+ testface(c.i+1, c.j, c.k, &c, 2, RBN, RBF, RTN, RTF, mbproc);
+ testface(c.i, c.j-1, c.k, &c, 1, LBN, LBF, RBN, RBF, mbproc);
+ testface(c.i, c.j+1, c.k, &c, 1, LTN, LTF, RTN, RTF, mbproc);
+ testface(c.i, c.j, c.k-1, &c, 0, LBN, LTN, RBN, RTN, mbproc);
+ testface(c.i, c.j, c.k+1, &c, 0, LBF, LTF, RBF, RTF, mbproc);
+ }
+
+}
+
+float init_meta(Object *ob) /* return totsize */
+{
+ Base *base;
+ Object *bob;
+ MetaBall *mb;
+ MetaElem *ml;
+ float size, totsize, (*mat)[4] = NULL, (*imat)[4] = NULL, obinv[4][4], vec[3];
+ int a, obnr;
+ char obname[32];
+
+ Mat4Invert(obinv, ob->obmat);
+ totelem= 0;
+
+ splitIDname(ob->id.name+2, obname, &obnr);
+
+ /* hoofdarray maken */
+
+ next_object(0, 0, 0);
+ while(next_object(1, &base, &bob)) {
+
+ if(bob->type==OB_MBALL) {
+ ml= 0;
+ if(bob==ob) {
+ mat= imat= 0;
+ mb= ob->data;
+
+ if(ob==G.obedit) ml= editelems.first;
+ else if(G.obedit && G.obedit->type==OB_MBALL && G.obedit->data==mb) ml= editelems.first;
+ else ml= mb->elems.first;
+ }
+ else {
+ char name[32];
+ int nr;
+
+ splitIDname(bob->id.name+2, name, &nr);
+ if( strcmp(obname, name)==0 ) {
+ mb= bob->data;
+
+ if(G.obedit && G.obedit->type==OB_MBALL && G.obedit->data==mb)
+ ml= editelems.first;
+ else ml= mb->elems.first;
+
+ /* mat is de matrix om van deze mball in de basis-mbal te komen */
+ mat= new_pgn_element(4*4*sizeof(float));
+ Mat4MulMat4(mat, bob->obmat, obinv);
+
+ imat= new_pgn_element(4*4*sizeof(float));
+ Mat4Invert(imat, mat);
+
+ }
+ }
+ while(ml && totelem<MB_MAXELEM) {
+ a= totelem;
+
+ /* kopie maken i.v.m. duplicates */
+ mainb[a]= new_pgn_element(sizeof(MetaElem));
+ *(mainb[a])= *ml;
+
+ /* if(mainb[a]->flag & MB_NEGATIVE) mainb[a]->s= 1.0-mainb[a]->s; */
+ mainb[a]->rad2= mainb[a]->rad*mainb[a]->rad;
+
+ mainb[a]->mat= (float*) mat;
+ mainb[a]->imat= (float*) imat;
+
+ ml= ml->next;
+ totelem++;
+
+ }
+ }
+ }
+
+ /* totsize (= 'manhattan' straal) berekenen */
+ totsize= 0.0;
+ for(a=0; a<totelem; a++) {
+
+ vec[0]= mainb[a]->x + mainb[a]->rad;
+ vec[1]= mainb[a]->y + mainb[a]->rad;
+ vec[2]= mainb[a]->z + mainb[a]->rad;
+
+ if(mainb[a]->type==MB_TUBEX) vec[0]+= mainb[a]->len;
+ if(mainb[a]->type==MB_TUBEY) vec[1]+= mainb[a]->len;
+ if(mainb[a]->type==MB_TUBEZ) vec[2]+= mainb[a]->len;
+
+ calc_mballco(mainb[a], vec);
+
+ size= (float)fabs( vec[0] );
+ if( size > totsize ) totsize= size;
+ size= (float)fabs( vec[1] );
+ if( size > totsize ) totsize= size;
+ size= (float)fabs( vec[2] );
+ if( size > totsize ) totsize= size;
+
+ vec[0]= mainb[a]->x - mainb[a]->rad;
+ vec[1]= mainb[a]->y - mainb[a]->rad;
+ vec[2]= mainb[a]->z - mainb[a]->rad;
+
+ calc_mballco(mainb[a], vec);
+
+ size= (float)fabs( vec[0] );
+ if( size > totsize ) totsize= size;
+ size= (float)fabs( vec[1] );
+ if( size > totsize ) totsize= size;
+ size= (float)fabs( vec[2] );
+ if( size > totsize ) totsize= size;
+ }
+
+ for(a=0; a<totelem; a++) {
+ thresh+= densfunc( mainb[a], 2.0f*totsize, 2.0f*totsize, 2.0f*totsize);
+ }
+
+ return totsize;
+}
+
+void metaball_polygonize(Object *ob)
+{
+ PROCESS mbproc;
+ MetaBall *mb;
+ DispList *dl;
+ int a, nr_cubes;
+ float *ve, *no, totsize, width;
+
+ mb= ob->data;
+
+ freedisplist(&ob->disp);
+ curindex= totindex= 0;
+ indices= 0;
+ thresh= mb->thresh;
+
+ if(G.moving && mb->flag==MB_UPDATE_FAST) return;
+
+ mainb= MEM_mallocN(sizeof(void *)*MB_MAXELEM, "mainb");
+
+ totsize= init_meta(ob);
+ if(totelem==0) {
+ MEM_freeN(mainb);
+ return;
+ }
+
+ /* width is afmeting per polygoniseerkubus */
+ if(R.flag & R_RENDERING) width= mb->rendersize;
+ else {
+ width= mb->wiresize;
+ if(G.moving && mb->flag==MB_UPDATE_HALFRES) width*= 2;
+ }
+ /* nr_cubes is voor de veiligheid, minmaal de totsize */
+ nr_cubes= (int)(0.5+totsize/width);
+
+ /* init process */
+ mbproc.function = metaball;
+ mbproc.size = width;
+ mbproc.bounds = nr_cubes;
+ mbproc.cubes= 0;
+ mbproc.delta = width/(float)(RES*RES);
+
+ polygonize(&mbproc);
+
+ MEM_freeN(mainb);
+
+ if(curindex) {
+
+ dl= MEM_callocN(sizeof(DispList), "mbaldisp");
+ BLI_addtail(&ob->disp, dl);
+ dl->type= DL_INDEX4;
+ dl->nr= mbproc.vertices.count;
+ dl->parts= curindex;
+
+ dl->index= indices;
+ indices= 0;
+
+ a= mbproc.vertices.count;
+ dl->verts= ve= MEM_mallocN(sizeof(float)*3*a, "mballverts");
+ dl->nors= no= MEM_mallocN(sizeof(float)*3*a, "mballnors");
+
+ for(a=0; a<mbproc.vertices.count; a++, no+=3, ve+=3) {
+ ve[0]= mbproc.vertices.ptr[a].position.x;
+ ve[1]= mbproc.vertices.ptr[a].position.y;
+ ve[2]= mbproc.vertices.ptr[a].position.z;
+
+ no[0]= mbproc.vertices.ptr[a].normal.x;
+ no[1]= mbproc.vertices.ptr[a].normal.y;
+ no[2]= mbproc.vertices.ptr[a].normal.z;
+ }
+ }
+
+ freepolygonize(&mbproc);
+
+}
+
+
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
new file mode 100644
index 00000000000..720d02ee7bb
--- /dev/null
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -0,0 +1,1120 @@
+
+/* mesh.c MIXED MODEL
+ *
+ * jan/maart 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 *****
+ */
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_ID.h"
+#include "DNA_curve_types.h"
+#include "DNA_material_types.h"
+#include "DNA_object_types.h"
+#include "DNA_image_types.h"
+#include "DNA_key_types.h"
+#include "DNA_mesh_types.h"
+
+#include "BKE_main.h"
+#include "BKE_global.h"
+#include "BKE_mesh.h"
+#include "BKE_subsurf.h"
+#include "BKE_displist.h"
+#include "BKE_library.h"
+#include "BKE_material.h"
+#include "BKE_key.h"
+/* these 2 are only used by conversion functions */
+#include "BKE_curve.h"
+/* -- */
+#include "BKE_object.h"
+#include "BKE_utildefines.h"
+#include "BKE_bad_level_calls.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_editVert.h"
+#include "BLI_arithb.h"
+
+
+
+int update_realtime_texture(TFace *tface, double time)
+{
+ Image *ima;
+ int inc = 0;
+ float diff;
+ int newframe;
+
+ ima = tface->tpage;
+
+ if (!ima)
+ return 0;
+
+ if (ima->lastupdate<0)
+ ima->lastupdate = 0;
+
+ if (ima->lastupdate>time)
+ ima->lastupdate=(float)time;
+
+ if(ima->tpageflag & IMA_TWINANIM) {
+ if(ima->twend >= ima->xrep*ima->yrep) ima->twend= ima->xrep*ima->yrep-1;
+
+ /* check: zit de bindcode niet het array? Vrijgeven. (nog doen) */
+
+ diff = (float)(time-ima->lastupdate);
+
+ inc = (int)(diff*(float)ima->animspeed);
+
+ ima->lastupdate+=((float)inc/(float)ima->animspeed);
+
+ newframe = ima->lastframe+inc;
+
+ if (newframe > (int)ima->twend)
+ newframe = (int)ima->twsta-1 + (newframe-ima->twend)%(ima->twend-ima->twsta);
+
+ ima->lastframe = newframe;
+ }
+ return inc;
+}
+
+float get_mvert_weight (Object *ob, int vert, int defgroup)
+{
+ int i;
+ Mesh *me;
+ float result;
+
+ me=ob->data;
+
+ if (!me->dvert)
+ return 0.0F;
+
+ result=0.0F;
+
+ for (i=0; i<me->dvert[vert].totweight; i++){
+ if (me->dvert[vert].dw[i].def_nr==defgroup)
+ result+=me->dvert[vert].dw[i].weight;
+ }
+
+ return result;
+}
+
+void unlink_mesh(Mesh *me)
+{
+ int a;
+
+ if(me==0) return;
+
+ for(a=0; a<me->totcol; a++) {
+ if(me->mat[a]) me->mat[a]->id.us--;
+ me->mat[a]= 0;
+ }
+ if(me->key) me->key->id.us--;
+ me->key= 0;
+
+ if(me->texcomesh) me->texcomesh= 0;
+}
+
+
+/* niet mesh zelf vrijgeven */
+void free_mesh(Mesh *me)
+{
+
+ unlink_mesh(me);
+
+ if(me->mat) MEM_freeN(me->mat);
+ if(me->orco) MEM_freeN(me->orco);
+ if(me->mface) MEM_freeN(me->mface);
+ if(me->tface) MEM_freeN(me->tface);
+ if(me->mvert) MEM_freeN(me->mvert);
+ if(me->dvert) free_dverts(me->dvert, me->totvert);
+ if(me->mcol) MEM_freeN(me->mcol);
+ if(me->msticky) MEM_freeN(me->msticky);
+ if(me->bb) MEM_freeN(me->bb);
+ if(me->disp.first) freedisplist(&me->disp);
+}
+
+void copy_dverts(MDeformVert *dst, MDeformVert *src, int copycount)
+{
+ /* Assumes dst is already set up */
+ int i;
+
+ if (!src || !dst)
+ return;
+
+ memcpy (dst, src, copycount * sizeof(MDeformVert));
+
+ for (i=0; i<copycount; i++){
+ if (src[i].dw){
+ dst[i].dw = MEM_callocN (sizeof(MDeformWeight)*src[i].totweight, "copy_deformWeight");
+ memcpy (dst[i].dw, src[i].dw, sizeof (MDeformWeight)*src[i].totweight);
+ }
+ }
+
+}
+void free_dverts(MDeformVert *dvert, int totvert)
+{
+ /* Instead of freeing the verts directly,
+ call this function to delete any special
+ vert data */
+ int i;
+
+ if (!dvert)
+ return;
+
+ /* Free any special data from the verts */
+ for (i=0; i<totvert; i++){
+ if (dvert[i].dw) MEM_freeN (dvert[i].dw);
+ }
+ MEM_freeN (dvert);
+}
+
+Mesh *add_mesh()
+{
+ Mesh *me;
+
+ me= alloc_libblock(&G.main->mesh, ID_ME, "Mesh");
+
+ me->size[0]= me->size[1]= me->size[2]= 1.0;
+ me->smoothresh= 30;
+ me->texflag= AUTOSPACE;
+ me->flag= ME_TWOSIDED;
+ me->subdiv= 1;
+ me->subdivr = 1;
+ me->bb= unit_boundbox();
+
+ return me;
+}
+
+Mesh *copy_mesh(Mesh *me)
+{
+ Mesh *men;
+ int a;
+
+ men= copy_libblock(me);
+
+ men->mat= MEM_dupallocN(me->mat);
+ for(a=0; a<men->totcol; a++) {
+ id_us_plus((ID *)men->mat[a]);
+ }
+ id_us_plus((ID *)men->texcomesh);
+ men->mface= MEM_dupallocN(me->mface);
+
+ men->tface= MEM_dupallocN(me->tface);
+
+ men->dface= 0;
+ men->mvert= MEM_dupallocN(me->mvert);
+ memcpy (men->mvert, me->mvert, sizeof (MVert)*me->totvert);
+ if (me->dvert){
+ men->dvert = MEM_mallocN (sizeof (MDeformVert)*me->totvert, "MDeformVert");
+ copy_dverts(men->dvert, me->dvert, me->totvert);
+ }
+
+ men->mcol= MEM_dupallocN(me->mcol);
+ men->msticky= MEM_dupallocN(me->msticky);
+ men->texcomesh= 0;
+ men->orco= 0;
+ men->bb= MEM_dupallocN(men->bb);
+
+ copy_displist(&men->disp, &me->disp);
+
+ men->key= copy_key(me->key);
+ if(men->key) men->key->from= (ID *)men;
+
+ return men;
+}
+
+void make_local_tface(Mesh *me)
+{
+ TFace *tface;
+ Image *ima;
+ int a;
+
+ if(me->tface==0) return;
+
+ a= me->totface;
+ tface= me->tface;
+ while(a--) {
+
+ /* speciaal geval: ima altijd meteen lokaal */
+ if(tface->tpage) {
+ ima= tface->tpage;
+ if(ima->id.lib) {
+ ima->id.lib= 0;
+ ima->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)ima, 0);
+ }
+ }
+ tface++;
+ }
+
+}
+
+void make_local_mesh(Mesh *me)
+{
+ Object *ob;
+ Mesh *men;
+ int local=0, lib=0;
+
+ /* - zijn er alleen lib users: niet doen
+ * - zijn er alleen locale users: flag zetten
+ * - mixed: copy
+ */
+
+ if(me->id.lib==0) return;
+ if(me->id.us==1) {
+ me->id.lib= 0;
+ me->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)me, 0);
+
+ if(me->tface) make_local_tface(me);
+
+ return;
+ }
+
+ ob= G.main->object.first;
+ while(ob) {
+ if( me==get_mesh(ob) ) {
+ if(ob->id.lib) lib= 1;
+ else local= 1;
+ }
+ ob= ob->id.next;
+ }
+
+ if(local && lib==0) {
+ me->id.lib= 0;
+ me->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)me, 0);
+
+ if(me->tface) make_local_tface(me);
+
+ }
+ else if(local && lib) {
+ men= copy_mesh(me);
+ men->id.us= 0;
+
+ ob= G.main->object.first;
+ while(ob) {
+ if( me==get_mesh(ob) ) {
+ if(ob->id.lib==0) {
+ set_mesh(ob, men);
+ }
+ }
+ ob= ob->id.next;
+ }
+ }
+}
+
+void boundbox_mesh(Mesh *me, float *loc, float *size)
+{
+ MVert *mvert;
+ BoundBox *bb;
+ float min[3], max[3];
+ float mloc[3], msize[3];
+ int a;
+
+ if(me->bb==0) me->bb= MEM_callocN(sizeof(BoundBox), "boundbox");
+ bb= me->bb;
+
+ INIT_MINMAX(min, max);
+
+ if (!loc) loc= mloc;
+ if (!size) size= msize;
+
+ mvert= me->mvert;
+ for(a=0; a<me->totvert; a++, mvert++) {
+ DO_MINMAX(mvert->co, min, max);
+ }
+
+ if(me->totvert) {
+ loc[0]= (min[0]+max[0])/2.0f;
+ loc[1]= (min[1]+max[1])/2.0f;
+ loc[2]= (min[2]+max[2])/2.0f;
+
+ size[0]= (max[0]-min[0])/2.0f;
+ size[1]= (max[1]-min[1])/2.0f;
+ size[2]= (max[2]-min[2])/2.0f;
+ }
+ else {
+ loc[0]= loc[1]= loc[2]= 0.0;
+ size[0]= size[1]= size[2]= 0.0;
+ }
+
+ bb->vec[0][0]=bb->vec[1][0]=bb->vec[2][0]=bb->vec[3][0]= loc[0]-size[0];
+ bb->vec[4][0]=bb->vec[5][0]=bb->vec[6][0]=bb->vec[7][0]= loc[0]+size[0];
+
+ bb->vec[0][1]=bb->vec[1][1]=bb->vec[4][1]=bb->vec[5][1]= loc[1]-size[1];
+ bb->vec[2][1]=bb->vec[3][1]=bb->vec[6][1]=bb->vec[7][1]= loc[1]+size[1];
+
+ bb->vec[0][2]=bb->vec[3][2]=bb->vec[4][2]=bb->vec[7][2]= loc[2]-size[2];
+ bb->vec[1][2]=bb->vec[2][2]=bb->vec[5][2]=bb->vec[6][2]= loc[2]+size[2];
+}
+
+void tex_space_mesh(Mesh *me)
+{
+ KeyBlock *kb;
+ float *fp, loc[3], size[3], min[3], max[3];
+ int a;
+
+ boundbox_mesh(me, loc, size);
+
+ if(me->texflag & AUTOSPACE) {
+ if(me->key) {
+ kb= me->key->refkey;
+ if (kb) {
+
+ INIT_MINMAX(min, max);
+
+ fp= kb->data;
+ for(a=0; a<kb->totelem; a++, fp+=3) {
+ DO_MINMAX(fp, min, max);
+ }
+ if(kb->totelem) {
+ loc[0]= (min[0]+max[0])/2.0f; loc[1]= (min[1]+max[1])/2.0f; loc[2]= (min[2]+max[2])/2.0f;
+ size[0]= (max[0]-min[0])/2.0f; size[1]= (max[1]-min[1])/2.0f; size[2]= (max[2]-min[2])/2.0f;
+ }
+ else {
+ loc[0]= loc[1]= loc[2]= 0.0;
+ size[0]= size[1]= size[2]= 0.0;
+ }
+
+ }
+ }
+
+ VECCOPY(me->loc, loc);
+ VECCOPY(me->size, size);
+ me->rot[0]= me->rot[1]= me->rot[2]= 0.0;
+
+ if(me->size[0]==0.0) me->size[0]= 1.0;
+ else if(me->size[0]>0.0 && me->size[0]<0.00001) me->size[0]= 0.00001;
+ else if(me->size[0]<0.0 && me->size[0]> -0.00001) me->size[0]= -0.00001;
+
+ if(me->size[1]==0.0) me->size[1]= 1.0;
+ else if(me->size[1]>0.0 && me->size[1]<0.00001) me->size[1]= 0.00001;
+ else if(me->size[1]<0.0 && me->size[1]> -0.00001) me->size[1]= -0.00001;
+
+ if(me->size[2]==0.0) me->size[2]= 1.0;
+ else if(me->size[2]>0.0 && me->size[2]<0.00001) me->size[2]= 0.00001;
+ else if(me->size[2]<0.0 && me->size[2]> -0.00001) me->size[2]= -0.00001;
+ }
+
+}
+
+void make_orco_displist_mesh(Object *ob, int subdivlvl)
+{
+ Mesh *me;
+ DispList *dl;
+ DispListMesh *dlm;
+ int i;
+
+ me= ob->data;
+
+ /* if there's a key, set the first one */
+ if(me->key && me->texcomesh==0) {
+ cp_key(0, me->totvert, me->totvert, (char*) me->mvert->co, me->key, me->key->refkey, 0);
+ }
+
+ /* Rebuild the displist */
+ dl= subsurf_mesh_to_displist(me, NULL, (short)subdivlvl);
+
+ /* Restore correct key */
+ do_ob_key(ob);
+
+ /* XXX Assume dl is a DL_MESH (it is),
+ * should be explicit -zr
+ */
+ dlm= dl->mesh;
+
+ me->orco= MEM_mallocN(dlm->totvert*3*sizeof(float), "mesh displist orco");
+
+ for (i=0; i<dlm->totvert; i++) {
+ float *fp= &me->orco[i*3];
+ VECCOPY(fp, dlm->mvert[i].co);
+ }
+
+ for(i=0; i<dlm->totvert; i++) {
+ float *fp= &me->orco[i*3];
+ fp[0]= (fp[0]-me->loc[0])/me->size[0];
+ fp[1]= (fp[1]-me->loc[1])/me->size[1];
+ fp[2]= (fp[2]-me->loc[2])/me->size[2];
+ }
+
+ free_disp_elem(dl);
+}
+
+void make_orco_mesh(Mesh *me)
+{
+ MVert *mvert;
+ KeyBlock *kb;
+ float *orco, *fp;
+ int a, totvert;
+
+ totvert= me->totvert;
+ if(totvert==0) return;
+ orco= me->orco= MEM_mallocN(sizeof(float)*3*totvert, "orco mesh");
+
+ if(me->key && me->texcomesh==0) {
+ kb= me->key->refkey;
+ if (kb) { /***** BUG *****/
+ fp= kb->data;
+
+ for(a=0; a<totvert; a++, orco+=3) {
+ orco[0]= (fp[0]-me->loc[0])/me->size[0];
+ orco[1]= (fp[1]-me->loc[1])/me->size[1];
+ orco[2]= (fp[2]-me->loc[2])/me->size[2];
+
+ /* mvert alleen ophogen als totvert <= kb->totelem */
+ if(a<kb->totelem) fp+=3;
+ }
+ }
+ }
+ else {
+ if(me->texcomesh) {
+ me= me->texcomesh;
+ }
+
+ mvert= me->mvert;
+ for(a=0; a<totvert; a++, orco+=3) {
+ orco[0]= (mvert->co[0]-me->loc[0])/me->size[0];
+ orco[1]= (mvert->co[1]-me->loc[1])/me->size[1];
+ orco[2]= (mvert->co[2]-me->loc[2])/me->size[2];
+
+ /* mvert alleen ophogen als totvert <= me->totvert */
+ if(a<me->totvert) mvert++;
+ }
+ }
+}
+
+/** rotates the vertices of a face in case v[2] or v[3] (vertex index)
+ * is = 0.
+ * Helaas, the MFace structure has no pointer to its
+ * texture face, therefore, texture can not be fixed inside
+ * this function.
+ *
+ * see also blender/src/editmesh.c, fix_faceindices()
+
+ * THIS FUNCTION WILL BE DINOSOURCE. For the moment, another hack
+ is added to fix texture coordinates / vertex colors:
+
+ void test_index_face(MFace *mface, TFace *tface, int nr)
+ */
+
+void test_index_mface(MFace *mface, int nr)
+{
+ int a;
+
+
+ /* first test if the face is legal */
+
+ if(mface->v3 && mface->v3==mface->v4) {
+ mface->v4= 0;
+ nr--;
+ }
+ if(mface->v2 && mface->v2==mface->v3) {
+ mface->v3= mface->v4;
+ mface->v4= 0;
+ nr--;
+ }
+ if(mface->v1==mface->v2) {
+ mface->v2= mface->v3;
+ mface->v3= mface->v4;
+ mface->v4= 0;
+ nr--;
+ }
+
+ /* voorkom dat een nul op de verkeerde plek staat */
+ if(nr==2) {
+ if(mface->v2==0) SWAP(int, mface->v1, mface->v2);
+ }
+ else if(nr==3) {
+ if(mface->v3==0) {
+ SWAP(int, mface->v1, mface->v2);
+ SWAP(int, mface->v2, mface->v3);
+
+ a= mface->edcode;
+ mface->edcode= 0;
+ if(a & ME_V1V2) mface->edcode |= ME_V3V1;
+ if(a & ME_V2V3) mface->edcode |= ME_V1V2;
+ if(a & ME_V3V1) mface->edcode |= ME_V2V3;
+
+ a= mface->puno;
+ mface->puno &= ~15;
+ if(a & ME_FLIPV1) mface->puno |= ME_FLIPV2;
+ if(a & ME_FLIPV2) mface->puno |= ME_FLIPV3;
+ if(a & ME_FLIPV3) mface->puno |= ME_FLIPV1;
+ }
+ }
+ else if(nr==4) {
+ if(mface->v3==0 || mface->v4==0) {
+ SWAP(int, mface->v1, mface->v3);
+ SWAP(int, mface->v2, mface->v4);
+ a= mface->edcode;
+ mface->edcode= 0;
+ if(a & ME_V1V2) mface->edcode |= ME_V3V4;
+ if(a & ME_V2V3) mface->edcode |= ME_V2V3;
+ if(a & ME_V3V4) mface->edcode |= ME_V1V2;
+ if(a & ME_V4V1) mface->edcode |= ME_V4V1;
+
+ a= mface->puno;
+ mface->puno &= ~15;
+ if(a & ME_FLIPV1) mface->puno |= ME_FLIPV3;
+ if(a & ME_FLIPV2) mface->puno |= ME_FLIPV4;
+ if(a & ME_FLIPV3) mface->puno |= ME_FLIPV1;
+ if(a & ME_FLIPV4) mface->puno |= ME_FLIPV2;
+ }
+ }
+}
+
+/** This function should die as soon as there is another mesh
+ structure. Functionality is the same as
+
+ void test_index_mface()
+
+ but it fixes texture coordinates as well.
+*/
+
+#define UVCOPY(t, s) memcpy(t, s, 2 * sizeof(float));
+void test_index_face(MFace *mface, TFace *tface, int nr)
+{
+ int a;
+ float tmpuv[2];
+ unsigned int tmpcol;
+
+
+ /* first test if the face is legal */
+
+ if(mface->v3 && mface->v3==mface->v4) {
+ mface->v4= 0;
+ nr--;
+ }
+ if(mface->v2 && mface->v2==mface->v3) {
+ mface->v3= mface->v4;
+ mface->v4= 0;
+ nr--;
+ }
+ if(mface->v1==mface->v2) {
+ mface->v2= mface->v3;
+ mface->v3= mface->v4;
+ mface->v4= 0;
+ nr--;
+ }
+
+ /* voorkom dat een nul op de verkeerde plek staat */
+ if(nr==2) {
+ if(mface->v2==0) SWAP(int, mface->v1, mface->v2);
+ }
+ else if(nr==3) {
+ if(mface->v3==0) {
+ SWAP(int, mface->v1, mface->v2);
+ SWAP(int, mface->v2, mface->v3);
+ /* rotate face UV coordinates, too */
+ UVCOPY(tmpuv, tface->uv[0]);
+ UVCOPY(tface->uv[0], tface->uv[1]);
+ UVCOPY(tface->uv[1], tface->uv[2]);
+ UVCOPY(tface->uv[2], tmpuv);
+ /* same with vertex colours */
+ tmpcol = tface->col[0];
+ tface->col[0] = tface->col[1];
+ tface->col[1] = tface->col[2];
+ tface->col[2] = tmpcol;
+
+
+ a= mface->edcode;
+ mface->edcode= 0;
+ if(a & ME_V1V2) mface->edcode |= ME_V3V1;
+ if(a & ME_V2V3) mface->edcode |= ME_V1V2;
+ if(a & ME_V3V1) mface->edcode |= ME_V2V3;
+
+ a= mface->puno;
+ mface->puno &= ~15;
+ if(a & ME_FLIPV1) mface->puno |= ME_FLIPV2;
+ if(a & ME_FLIPV2) mface->puno |= ME_FLIPV3;
+ if(a & ME_FLIPV3) mface->puno |= ME_FLIPV1;
+ }
+ }
+ else if(nr==4) {
+ if(mface->v3==0 || mface->v4==0) {
+ SWAP(int, mface->v1, mface->v3);
+ SWAP(int, mface->v2, mface->v4);
+ /* swap UV coordinates */
+ UVCOPY(tmpuv, tface->uv[0]);
+ UVCOPY(tface->uv[0], tface->uv[2]);
+ UVCOPY(tface->uv[2], tmpuv);
+ UVCOPY(tmpuv, tface->uv[1]);
+ UVCOPY(tface->uv[1], tface->uv[3]);
+ UVCOPY(tface->uv[3], tmpuv);
+ /* swap vertex colours */
+ tmpcol = tface->col[0];
+ tface->col[0] = tface->col[2];
+ tface->col[2] = tmpcol;
+ tmpcol = tface->col[1];
+ tface->col[1] = tface->col[3];
+ tface->col[3] = tmpcol;
+
+ a= mface->edcode;
+ mface->edcode= 0;
+ if(a & ME_V1V2) mface->edcode |= ME_V3V4;
+ if(a & ME_V2V3) mface->edcode |= ME_V2V3;
+ if(a & ME_V3V4) mface->edcode |= ME_V1V2;
+ if(a & ME_V4V1) mface->edcode |= ME_V4V1;
+
+ a= mface->puno;
+ mface->puno &= ~15;
+ if(a & ME_FLIPV1) mface->puno |= ME_FLIPV3;
+ if(a & ME_FLIPV2) mface->puno |= ME_FLIPV4;
+ if(a & ME_FLIPV3) mface->puno |= ME_FLIPV1;
+ if(a & ME_FLIPV4) mface->puno |= ME_FLIPV2;
+ }
+ }
+}
+
+void flipnorm_mesh(Mesh *me)
+{
+ MFace *mface;
+ MVert *mvert;
+ DispList *dl;
+ float *fp;
+ int a, temp;
+
+ mvert= me->mvert;
+ a= me->totvert;
+ while(a--) {
+ mvert->no[0]= -mvert->no[0];
+ mvert->no[1]= -mvert->no[1];
+ mvert->no[2]= -mvert->no[2];
+ mvert++;
+ }
+
+ mface= me->mface;
+ a= me->totface;
+ while(a--) {
+ if(mface->v3) {
+ if(mface->v4) {
+ SWAP(int, mface->v4, mface->v1);
+ SWAP(int, mface->v3, mface->v2);
+ test_index_mface(mface, 4);
+ temp= mface->puno;
+ mface->puno &= ~15;
+ if(temp & ME_FLIPV1) mface->puno |= ME_FLIPV4;
+ if(temp & ME_FLIPV2) mface->puno |= ME_FLIPV3;
+ if(temp & ME_FLIPV3) mface->puno |= ME_FLIPV2;
+ if(temp & ME_FLIPV4) mface->puno |= ME_FLIPV1;
+ }
+ else {
+ SWAP(int, mface->v3, mface->v1);
+ test_index_mface(mface, 3);
+ temp= mface->puno;
+ mface->puno &= ~15;
+ if(temp & ME_FLIPV1) mface->puno |= ME_FLIPV3;
+ if(temp & ME_FLIPV2) mface->puno |= ME_FLIPV2;
+ if(temp & ME_FLIPV3) mface->puno |= ME_FLIPV1;
+ }
+ }
+ mface++;
+ }
+
+ if(me->disp.first) {
+ dl= me->disp.first;
+ fp= dl->nors;
+ if(fp) {
+ a= dl->nr;
+ while(a--) {
+ fp[0]= -fp[0];
+ fp[1]= -fp[1];
+ fp[2]= -fp[2];
+ fp+= 3;
+ }
+ }
+ }
+}
+
+Mesh *get_mesh(Object *ob)
+{
+
+ if(ob==0) return 0;
+ if(ob->type==OB_MESH) return ob->data;
+ else return 0;
+}
+
+void set_mesh(Object *ob, Mesh *me)
+{
+ Mesh *old=0;
+
+ if(ob==0) return;
+
+ if(ob->type==OB_MESH) {
+ old= ob->data;
+ old->id.us--;
+ ob->data= me;
+ id_us_plus((ID *)me);
+ }
+
+ test_object_materials((ID *)me);
+}
+
+void mball_to_mesh(ListBase *lb, Mesh *me)
+{
+ DispList *dl;
+ MVert *mvert;
+ MFace *mface;
+ float *nors, *verts;
+ int a, *index;
+
+ dl= lb->first;
+ if(dl==0) return;
+
+ if(dl->type==DL_INDEX4) {
+ me->flag= ME_NOPUNOFLIP;
+ me->totvert= dl->nr;
+ me->totface= dl->parts;
+
+ me->mvert=mvert= MEM_callocN(dl->nr*sizeof(MVert), "mverts");
+ a= dl->nr;
+ nors= dl->nors;
+ verts= dl->verts;
+ while(a--) {
+ VECCOPY(mvert->co, verts);
+ mvert->no[0]= (short int)(nors[0]*32767.0);
+ mvert->no[1]= (short int)(nors[1]*32767.0);
+ mvert->no[2]= (short int)(nors[2]*32767.0);
+ mvert++;
+ nors+= 3;
+ verts+= 3;
+ }
+
+ me->mface=mface= MEM_callocN(dl->parts*sizeof(MFace), "mface");
+ a= dl->parts;
+ index= dl->index;
+ while(a--) {
+ mface->v1= index[0];
+ mface->v2= index[1];
+ mface->v3= index[2];
+ mface->v4= index[3];
+
+ mface->puno= 0;
+ mface->edcode= ME_V1V2+ME_V2V3;
+ mface->flag = ME_SMOOTH;
+
+ mface++;
+ index+= 4;
+ }
+ }
+}
+
+void nurbs_to_mesh(Object *ob)
+{
+ Object *ob1;
+ DispList *dl;
+ Mesh *me;
+ Curve *cu;
+ MVert *mvert;
+ MFace *mface;
+ float *data;
+ int a, b, ofs, vertcount, startvert, totvert=0, totvlak=0;
+ int p1, p2, p3, p4, *index;
+
+ cu= ob->data;
+
+ if(ob->type==OB_CURVE) {
+ /* regel: dl->type INDEX3 altijd vooraan in lijst */
+ dl= cu->disp.first;
+ if(dl->type!=DL_INDEX3) {
+ curve_to_filledpoly(ob->data, &cu->disp);
+ }
+ }
+
+ /* tellen */
+ dl= cu->disp.first;
+ while(dl) {
+ if(dl->type==DL_SEGM) {
+ totvert+= dl->parts*dl->nr;
+ totvlak+= dl->parts*(dl->nr-1);
+ }
+ else if(dl->type==DL_POLY) {
+ /* cyclic polys are filled. except when 3D */
+ if(cu->flag & CU_3D) {
+ totvert+= dl->parts*dl->nr;
+ totvlak+= dl->parts*dl->nr;
+ }
+ }
+ else if(dl->type==DL_SURF) {
+ totvert+= dl->parts*dl->nr;
+ totvlak+= (dl->parts-1+((dl->flag & 2)==2))*(dl->nr-1+(dl->flag & 1));
+ }
+ else if(dl->type==DL_INDEX3) {
+ totvert+= dl->nr;
+ totvlak+= dl->parts;
+ }
+ dl= dl->next;
+ }
+ if(totvert==0) {
+ error("can't convert");
+ return;
+ }
+
+ /* mesh maken */
+ me= add_mesh();
+ me->totvert= totvert;
+ me->totface= totvlak;
+
+ me->totcol= cu->totcol;
+ me->mat= cu->mat;
+ cu->mat= 0;
+ cu->totcol= 0;
+
+ mvert=me->mvert= MEM_callocN(me->totvert*sizeof(MVert), "cumesh1");
+ mface=me->mface= MEM_callocN(me->totface*sizeof(MFace), "cumesh2");
+
+ /* verts en vlakken */
+ vertcount= 0;
+
+ dl= cu->disp.first;
+ while(dl) {
+ if(dl->type==DL_SEGM) {
+ startvert= vertcount;
+ a= dl->parts*dl->nr;
+ data= dl->verts;
+ while(a--) {
+ VECCOPY(mvert->co, data);
+ data+=3;
+ vertcount++;
+ mvert++;
+ }
+
+ for(a=0; a<dl->parts; a++) {
+ ofs= a*dl->nr;
+ for(b=1; b<dl->nr; b++) {
+ mface->v1= startvert+ofs+b-1;
+ mface->v2= startvert+ofs+b;
+ mface->edcode= ME_V1V2;
+ test_index_mface(mface, 2);
+ mface++;
+ }
+ }
+
+ }
+ else if(dl->type==DL_POLY) {
+ /* cyclic polys are filled */
+ /* startvert= vertcount;
+ a= dl->parts*dl->nr;
+ data= dl->verts;
+ while(a--) {
+ VECCOPY(mvert->co, data);
+ data+=3;
+ vertcount++;
+ mvert++;
+ }
+
+ for(a=0; a<dl->parts; a++) {
+ ofs= a*dl->nr;
+ for(b=0; b<dl->nr; b++) {
+ mface->v1= startvert+ofs+b;
+ if(b==dl->nr-1) mface->v2= startvert+ofs;
+ else mface->v2= startvert+ofs+b+1;
+ mface->edcode= ME_V1V2;
+ test_index_mface(mface, 2);
+ mface++;
+ }
+ }
+ */
+ }
+ else if(dl->type==DL_INDEX3) {
+ startvert= vertcount;
+ a= dl->nr;
+ data= dl->verts;
+ while(a--) {
+ VECCOPY(mvert->co, data);
+ data+=3;
+ vertcount++;
+ mvert++;
+ }
+
+ a= dl->parts;
+ index= dl->index;
+ while(a--) {
+ mface->v1= startvert+index[0];
+ mface->v2= startvert+index[1];
+ mface->v3= startvert+index[2];
+ mface->v4= 0;
+
+ mface->puno= 7;
+ mface->edcode= ME_V1V2+ME_V2V3;
+ test_index_mface(mface, 3);
+
+ mface++;
+ index+= 3;
+ }
+
+
+ }
+ else if(dl->type==DL_SURF) {
+ startvert= vertcount;
+ a= dl->parts*dl->nr;
+ data= dl->verts;
+ while(a--) {
+ VECCOPY(mvert->co, data);
+ data+=3;
+ vertcount++;
+ mvert++;
+ }
+
+ for(a=0; a<dl->parts; a++) {
+
+ if( (dl->flag & 2)==0 && a==dl->parts-1) break;
+
+ if(dl->flag & 1) { /* p2 -> p1 -> */
+ p1= startvert+ dl->nr*a; /* p4 -> p3 -> */
+ p2= p1+ dl->nr-1; /* -----> volgende rij */
+ p3= p1+ dl->nr;
+ p4= p2+ dl->nr;
+ b= 0;
+ }
+ else {
+ p2= startvert+ dl->nr*a;
+ p1= p2+1;
+ p4= p2+ dl->nr;
+ p3= p1+ dl->nr;
+ b= 1;
+ }
+ if( (dl->flag & 2) && a==dl->parts-1) {
+ p3-= dl->parts*dl->nr;
+ p4-= dl->parts*dl->nr;
+ }
+
+ for(; b<dl->nr; b++) {
+ mface->v1= p1;
+ mface->v2= p3;
+ mface->v3= p4;
+ mface->v4= p2;
+ mface->mat_nr= (unsigned char)dl->col;
+ mface->edcode= ME_V1V2+ME_V2V3;
+ test_index_mface(mface, 4);
+ mface++;
+
+ p4= p3;
+ p3++;
+ p2= p1;
+ p1++;
+ }
+ }
+
+ }
+
+ dl= dl->next;
+ }
+
+ if(ob->data) {
+ free_libblock(&G.main->curve, ob->data);
+ }
+ ob->data= me;
+ ob->type= OB_MESH;
+
+ tex_space_mesh(me);
+
+ /* andere users */
+ ob1= G.main->object.first;
+ while(ob1) {
+ if(ob1->data==cu) {
+ ob1->type= OB_MESH;
+
+ ob1->data= ob->data;
+ id_us_plus((ID *)ob->data);
+ }
+ ob1= ob1->id.next;
+ }
+
+}
+
+void edge_drawflags_mesh(Mesh *me)
+{
+ MFace *mface;
+ int a;
+
+ mface= me->mface;
+ for(a=0; a<me->totface; a++, mface++) {
+ mface->edcode= ME_V1V2|ME_V2V3|ME_V3V4|ME_V4V1;
+ }
+}
+
+void tface_to_mcol(Mesh *me)
+{
+ TFace *tface;
+ unsigned int *mcol;
+ int a;
+
+ me->mcol= MEM_mallocN(4*sizeof(int)*me->totface, "nepmcol");
+ mcol= (unsigned int *)me->mcol;
+
+ a= me->totface;
+ tface= me->tface;
+ while(a--) {
+ memcpy(mcol, tface->col, 16);
+ mcol+= 4;
+ tface++;
+ }
+}
+
+void mcol_to_tface(Mesh *me, int freedata)
+{
+ TFace *tface;
+ unsigned int *mcol;
+ int a;
+
+ a= me->totface;
+ tface= me->tface;
+ mcol= (unsigned int *)me->mcol;
+ while(a--) {
+ memcpy(tface->col, mcol, 16);
+ mcol+= 4;
+ tface++;
+ }
+
+ if(freedata) {
+ MEM_freeN(me->mcol);
+ me->mcol= 0;
+ }
+}
+
+int mesh_uses_displist(Mesh *me) {
+ return (me->flag&ME_SUBSURF && (me->subdiv>0));
+}
+
+int rendermesh_uses_displist(Mesh *me) {
+ return (me->flag&ME_SUBSURF);
+}
diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c
new file mode 100644
index 00000000000..40851b27c6c
--- /dev/null
+++ b/source/blender/blenkernel/intern/nla.c
@@ -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 *****
+ */
+
+#include <stdlib.h>
+
+#include "BKE_nla.h"
+#include "BKE_blender.h"
+
+#include "BLI_blenlib.h"
+
+#include "DNA_space_types.h"
+#include "DNA_nla_types.h"
+#include "DNA_action_types.h"
+#include "DNA_ID.h"
+#include "DNA_ipo_types.h"
+
+#include "MEM_guardedalloc.h"
+
+void copy_actionstrip (bActionStrip **dst, bActionStrip **src){
+ bActionStrip *dstrip;
+ bActionStrip *sstrip = *src;
+
+ if (!*src){
+ *dst=NULL;
+ return;
+ }
+
+ *dst = MEM_dupallocN(sstrip);
+
+ dstrip = *dst;
+ if (dstrip->act)
+ dstrip->act->id.us++;
+
+ if (dstrip->ipo)
+ dstrip->ipo->id.us++;
+}
+
+void copy_nlastrips (ListBase *dst, ListBase *src)
+{
+ bActionStrip *strip;
+
+ dst->first=dst->last=NULL;
+
+ duplicatelist (dst, src);
+
+ /* Update specific data */
+ if (!dst->first)
+ return;
+
+ for (strip = dst->first; strip; strip=strip->next){
+ if (strip->act)
+ strip->act->id.us++;
+ if (strip->ipo)
+ strip->ipo->id.us++;
+ }
+}
+
+
+void free_actionstrip(bActionStrip* strip)
+{
+ if (!strip)
+ return;
+
+ if (strip->act){
+ strip->act->id.us--;
+ strip->act = NULL;
+ }
+ if (strip->ipo){
+ strip->ipo->id.us--;
+ strip->ipo = NULL;
+ }
+}
+
+void free_nlastrips (ListBase *nlalist)
+{
+ bActionStrip *strip;
+
+ if (!nlalist->first)
+ return;
+
+ /* Do any specific freeing */
+ for (strip=nlalist->first; strip; strip=strip->next)
+ {
+ free_actionstrip (strip);
+ };
+
+ /* Free the whole list */
+ BLI_freelistN(nlalist);
+}
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
new file mode 100644
index 00000000000..c6c91d00609
--- /dev/null
+++ b/source/blender/blenkernel/intern/object.c
@@ -0,0 +1,1681 @@
+/* object.c MIXED MODEL
+ *
+ * jan 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 <string.h>
+#include <math.h>
+#include <stdio.h>
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+#include "MEM_guardedalloc.h"
+
+#include "DNA_action_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_constraint_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_group_types.h"
+#include "DNA_ika_types.h"
+#include "DNA_ipo_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_lattice_types.h"
+#include "DNA_material_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_world_types.h"
+
+#include "BKE_armature.h"
+#include "BKE_action.h"
+#include "BKE_deform.h"
+#include "BKE_nla.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_bad_level_calls.h"
+
+#include "BKE_main.h"
+#include "BKE_global.h"
+
+#include "BKE_object.h"
+#include "BKE_blender.h"
+#include "BKE_screen.h"
+#include "BKE_ipo.h"
+#include "BKE_ika.h"
+#include "BKE_library.h"
+#include "BKE_mesh.h"
+#include "BKE_curve.h"
+#include "BKE_mball.h"
+#include "BKE_effect.h"
+#include "BKE_sca.h"
+#include "BPY_extern.h"
+#include "BKE_displist.h"
+#include "BKE_property.h"
+#include "BKE_anim.h"
+#include "BKE_group.h"
+#include "BKE_lattice.h"
+#include "BKE_constraint.h"
+#include "BKE_scene.h"
+
+/* Local function protos */
+static void solve_parenting (Object *ob, Object *par, float slowmat[][4], int simul);
+
+float originmat[3][3]; /* na where_is_object(), kan her en der gebruikt worden */
+Object workob;
+
+void clear_workob(void)
+{
+ memset(&workob, 0, sizeof(Object));
+
+ workob.size[0]= workob.size[1]= workob.size[2]= 1.0;
+
+}
+
+void copy_baseflags()
+{
+ Base *base= G.scene->base.first;
+
+ while(base) {
+ base->object->flag= base->flag;
+ base= base->next;
+ }
+}
+
+void copy_objectflags()
+{
+ Base *base= G.scene->base.first;
+
+ while(base) {
+ base->flag= base->object->flag;
+ base= base->next;
+ }
+}
+
+void update_base_layer(Object *ob)
+{
+ Base *base= G.scene->base.first;
+
+ while (base) {
+ if (base->object == ob) base->lay= ob->lay;
+ base= base->next;
+ }
+}
+
+/* niet object zelf vrijgeven */
+void free_object(Object *ob)
+{
+ int a;
+
+ /* specifieke data loskoppelen */
+ if(ob->data) {
+ ID *id= ob->data;
+ id->us--;
+ if(id->us==0) {
+ if(ob->type==OB_MESH) unlink_mesh(ob->data);
+ else if(ob->type==OB_CURVE) unlink_curve(ob->data);
+ else if(ob->type==OB_MBALL) unlink_mball(ob->data);
+ }
+ ob->data= 0;
+ }
+
+ for(a=0; a<ob->totcol; a++) {
+ if(ob->mat[a]) ob->mat[a]->id.us--;
+ }
+ if(ob->mat) MEM_freeN(ob->mat);
+ ob->mat= 0;
+ if(ob->bb) MEM_freeN(ob->bb);
+ ob->bb= 0;
+ if(ob->path) free_path(ob->path);
+ ob->path= 0;
+ if(ob->ipo) ob->ipo->id.us--;
+ if(ob->action) ob->action->id.us--;
+ if(ob->defbase.first)
+ BLI_freelistN(&ob->defbase);
+ if(ob->pose) {
+ clear_pose(ob->pose);
+ MEM_freeN(ob->pose);
+ }
+ free_effects(&ob->effect);
+ BLI_freelistN(&ob->network);
+ free_properties(&ob->prop);
+
+ free_sensors(&ob->sensors);
+ free_controllers(&ob->controllers);
+ free_actuators(&ob->actuators);
+
+ free_constraints(&ob->constraints);
+ free_constraint_channels(&ob->constraintChannels);
+ free_nlastrips(&ob->nlastrips);
+
+ freedisplist(&ob->disp);
+
+ BPY_free_scriptlink(&ob->scriptlink);
+}
+
+void unlink_object(Object *ob)
+{
+ Object *obt;
+ Material *mat;
+ World *wrld;
+ bScreen *sc;
+ Scene *sce;
+ Curve *cu;
+ Tex *tex;
+ Group *group;
+ int a;
+
+ unlink_controllers(&ob->controllers);
+ unlink_actuators(&ob->actuators);
+
+ /* alle objecten aflopen: parents en bevels */
+ obt= G.main->object.first;
+ while(obt) {
+ if(obt->id.lib==0) {
+ if(obt->parent==ob) {
+ obt->parent= 0;
+ if(ob->type==OB_LATTICE) freedisplist(&obt->disp);
+ }
+ if(obt->track==ob) obt->track= 0;
+ if ELEM(obt->type, OB_CURVE, OB_FONT) {
+ cu= obt->data;
+ if(cu->bevobj==ob) cu->bevobj= 0;
+ if(cu->textoncurve==ob) cu->textoncurve= 0;
+ }
+ if(obt->type==OB_IKA) {
+ Ika *ika= obt->data;
+ Deform *def= ika->def;
+
+ if(ika->parent==ob) ika->parent= 0;
+ a= ika->totdef;
+ while(a--) {
+ if(def->ob==ob) {
+ ika->totdef= 0;
+ MEM_freeN(ika->def);
+ ika->def= 0;
+ break;
+ }
+ def++;
+ }
+ }
+ sca_remove_ob_poin(obt, ob);
+ }
+ obt= obt->id.next;
+ }
+
+ /* materialen */
+ mat= G.main->mat.first;
+ while(mat) {
+
+ for(a=0; a<8; a++) {
+ if(mat->mtex[a] && ob==mat->mtex[a]->object) {
+ /* eigenlijk testen op lib */
+ mat->mtex[a]->object= 0;
+ }
+ }
+
+ mat= mat->id.next;
+ }
+
+ /* textures */
+ tex= G.main->tex.first;
+ while(tex) {
+ if(tex->env) {
+ if(tex->env->object == ob) tex->env->object= 0;
+ }
+ tex= tex->id.next;
+ }
+
+ /* mballs */
+ if(ob->type==OB_MBALL) {
+ obt= find_basis_mball(ob);
+ if(obt) freedisplist(&obt->disp);
+ }
+
+ /* worlds */
+ wrld= G.main->world.first;
+ while(wrld) {
+ if(wrld->id.lib==0) {
+ for(a=0; a<6; a++) {
+ if(wrld->mtex[a] && ob==wrld->mtex[a]->object)
+ wrld->mtex[a]->object =0;
+ }
+ }
+
+ wrld= wrld->id.next;
+ }
+
+ /* scene's */
+ sce= G.main->scene.first;
+ while(sce) {
+ if(sce->id.lib==0) {
+ if(sce->camera==ob) sce->camera= 0;
+ }
+ sce= sce->id.next;
+ }
+ /* keys */
+
+ /* screens */
+ sc= G.main->screen.first;
+ while(sc) {
+ ScrArea *sa= sc->areabase.first;
+ while(sa) {
+ SpaceLink *sl;
+
+ for (sl= sa->spacedata.first; sl; sl= sl->next) {
+ if(sl->spacetype==SPACE_VIEW3D) {
+ View3D *v3d= (View3D*) sl;
+
+ if(v3d->camera==ob) {
+ v3d->camera= 0;
+ if(v3d->persp>1) v3d->persp= 1;
+ }
+ if(v3d->localvd && v3d->localvd->camera==ob ) {
+ v3d->localvd->camera= 0;
+ if(v3d->localvd->persp>1) v3d->localvd->persp= 1;
+ }
+ }
+ }
+
+ sa= sa->next;
+ }
+ sc= sc->id.next;
+ }
+
+ /* groups */
+ group= G.main->group.first;
+ while(group) {
+ rem_from_group(group, ob);
+ group= group->id.next;
+ }
+}
+
+int exist_object(Object *obtest)
+{
+ Object *ob;
+
+ ob= G.main->object.first;
+ while(ob) {
+ if(ob==obtest) return 1;
+ ob= ob->id.next;
+ }
+ return 0;
+}
+
+void *add_camera()
+{
+ Camera *cam;
+
+ cam= alloc_libblock(&G.main->camera, ID_CA, "Camera");
+
+ cam->lens= 35.0f;
+ cam->clipsta= 0.1f;
+ cam->clipend= 100.0f;
+ cam->drawsize= 0.5f;
+ cam->netsta= 0.5f;
+ cam->netend= 10.0f;
+ cam->hold= 50;
+
+ return cam;
+}
+
+Camera *copy_camera(Camera *cam)
+{
+ Camera *camn;
+
+ camn= copy_libblock(cam);
+ id_us_plus((ID *)camn->ipo);
+
+ BPY_copy_scriptlink(&camn->scriptlink);
+
+ return camn;
+}
+
+
+
+void make_local_camera(Camera *cam)
+{
+ Object *ob;
+ Camera *camn;
+ int local=0, lib=0;
+
+ /* - zijn er alleen lib users: niet doen
+ * - zijn er alleen locale users: flag zetten
+ * - mixed: copy
+ */
+
+ if(cam->id.lib==0) return;
+ if(cam->id.us==1) {
+ cam->id.lib= 0;
+ cam->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)cam, 0);
+ return;
+ }
+
+ ob= G.main->object.first;
+ while(ob) {
+ if(ob->data==cam) {
+ if(ob->id.lib) lib= 1;
+ else local= 1;
+ }
+ ob= ob->id.next;
+ }
+
+ if(local && lib==0) {
+ cam->id.lib= 0;
+ cam->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)cam, 0);
+ }
+ else if(local && lib) {
+ camn= copy_camera(cam);
+ camn->id.us= 0;
+
+ ob= G.main->object.first;
+ while(ob) {
+ if(ob->data==cam) {
+
+ if(ob->id.lib==0) {
+ ob->data= camn;
+ camn->id.us++;
+ cam->id.us--;
+ }
+ }
+ ob= ob->id.next;
+ }
+ }
+}
+
+
+
+void *add_lamp(void)
+{
+ Lamp *la;
+
+ la= alloc_libblock(&G.main->lamp, ID_LA, "Lamp");
+
+ la->r= la->g= la->b= 1.0;
+ la->haint= la->energy= 1.0;
+ la->dist= 20.0f;
+ la->spotsize= 45.0f;
+ la->spotblend= 0.15f;
+ la->att2= 1.0f;
+ la->mode= LA_SHAD;
+ la->bufsize= 512;
+ la->clipsta= 0.5f;
+ la->clipend= 40.0f;
+ la->shadspotsize= 45.0f;
+ la->samp= 3;
+ la->bias= 1.0f;
+ la->soft= 3.0f;
+
+ return la;
+}
+
+Lamp *copy_lamp(Lamp *la)
+{
+ Lamp *lan;
+ int a;
+
+ lan= copy_libblock(la);
+
+ for(a=0; a<8; a++) {
+ if(lan->mtex[a]) {
+ lan->mtex[a]= MEM_mallocN(sizeof(MTex), "copylamptex");
+ memcpy(lan->mtex[a], la->mtex[a], sizeof(MTex));
+ id_us_plus((ID *)lan->mtex[a]->tex);
+ }
+ }
+
+ id_us_plus((ID *)lan->ipo);
+
+ BPY_copy_scriptlink(&la->scriptlink);
+
+ return lan;
+}
+
+void make_local_lamp(Lamp *la)
+{
+ Object *ob;
+ Lamp *lan;
+ int local=0, lib=0;
+
+ /* - zijn er alleen lib users: niet doen
+ * - zijn er alleen locale users: flag zetten
+ * - mixed: copy
+ */
+
+ if(la->id.lib==0) return;
+ if(la->id.us==1) {
+ la->id.lib= 0;
+ la->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)la, 0);
+ return;
+ }
+
+ ob= G.main->object.first;
+ while(ob) {
+ if(ob->data==la) {
+ if(ob->id.lib) lib= 1;
+ else local= 1;
+ }
+ ob= ob->id.next;
+ }
+
+ if(local && lib==0) {
+ la->id.lib= 0;
+ la->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)la, 0);
+ }
+ else if(local && lib) {
+ lan= copy_lamp(la);
+ lan->id.us= 0;
+
+ ob= G.main->object.first;
+ while(ob) {
+ if(ob->data==la) {
+
+ if(ob->id.lib==0) {
+ ob->data= lan;
+ lan->id.us++;
+ la->id.us--;
+ }
+ }
+ ob= ob->id.next;
+ }
+ }
+}
+
+void free_camera(Camera *ca)
+{
+ BPY_free_scriptlink(&ca->scriptlink);
+}
+
+void free_lamp(Lamp *la)
+{
+ MTex *mtex;
+ int a;
+
+ /* scriptlinks */
+
+ BPY_free_scriptlink(&la->scriptlink);
+
+ for(a=0; a<8; a++) {
+ mtex= la->mtex[a];
+ if(mtex && mtex->tex) mtex->tex->id.us--;
+ if(mtex) MEM_freeN(mtex);
+ }
+ la->ipo= 0;
+}
+
+void *add_wave()
+{
+ return 0;
+}
+
+
+/* *************************************************** */
+
+static void *add_obdata_from_type(int type)
+{
+ switch (type) {
+ case OB_MESH: G.totmesh++; return add_mesh();
+ case OB_CURVE: G.totcurve++; return add_curve(OB_CURVE);
+ case OB_SURF: G.totcurve++; return add_curve(OB_SURF);
+ case OB_FONT: return add_curve(OB_FONT);
+ case OB_MBALL: return add_mball();
+ case OB_CAMERA: return add_camera();
+ case OB_LAMP: G.totlamp++; return add_lamp();
+ case OB_IKA: return add_ika();
+ case OB_LATTICE: return add_lattice();
+ case OB_WAVE: return add_wave();
+ case OB_ARMATURE: return add_armature();
+ case OB_EMPTY: return NULL;
+ default:
+ printf("add_obdata_from_type: Internal error, bad type: %d\n", type);
+ return NULL;
+ }
+}
+
+static char *get_obdata_defname(int type)
+{
+ switch (type) {
+ case OB_MESH: return "Mesh";
+ case OB_CURVE: return "Curve";
+ case OB_SURF: return "Surf";
+ case OB_FONT: return "Font";
+ case OB_MBALL: return "Mball";
+ case OB_CAMERA: return "Camera";
+ case OB_LAMP: return "Lamp";
+ case OB_IKA: return "Ika";
+ case OB_LATTICE: return "Lattice";
+ case OB_WAVE: return "Wave";
+ case OB_ARMATURE: return "Armature";
+ case OB_EMPTY: return "Empty";
+ default:
+ printf("get_obdata_defname: Internal error, bad type: %d\n", type);
+ return "Empty";
+ }
+}
+
+/* algemene add: in G.scene, met layer uit area en default naam */
+/* maakt alle minimaal nodige datablokken aan, zonder vertices etc. */
+Object *add_object(int type)
+{
+ Object *ob;
+ Base *base;
+ char name[32];
+
+ if (G.obpose)
+ exit_posemode(1);
+
+ strcpy(name, get_obdata_defname(type));
+
+ ob= alloc_libblock(&G.main->object, ID_OB, name);
+ G.totobj++;
+
+ /* default object vars */
+ ob->type= type;
+ /* ob->transflag= OB_QUAT; */
+
+ QuatOne(ob->quat);
+ QuatOne(ob->dquat);
+
+ ob->col[0]= ob->col[1]= ob->col[2]= 0.0;
+ ob->col[3]= 1.0;
+
+ ob->loc[0]= ob->loc[1]= ob->loc[2]= 0.0;
+ ob->rot[0]= ob->rot[1]= ob->rot[2]= 0.0;
+ ob->size[0]= ob->size[1]= ob->size[2]= 1.0;
+
+ Mat4One(ob->parentinv);
+ Mat4One(ob->obmat);
+ ob->dt= OB_SHADED;
+ if(U.flag & MAT_ON_OB) ob->colbits= -1;
+
+ if(type==OB_CAMERA || type==OB_LAMP) {
+ ob->trackflag= OB_NEGZ;
+ ob->upflag= OB_POSY;
+ }
+ else {
+ ob->trackflag= OB_POSY;
+ ob->upflag= OB_POSZ;
+ }
+ ob->ipoflag = OB_OFFS_OB+OB_OFFS_PARENT;
+
+ ob->dupon= 1; ob->dupoff= 0;
+ ob->dupsta= 1; ob->dupend= 100;
+
+ /* Gameengine defaults*/
+ ob->mass= ob->inertia= 1.0f;
+ ob->formfactor= 0.4f;
+ ob->damping= 0.04f;
+ ob->rdamping= 0.1f;
+ ob->anisotropicFriction[0] = 1.0f;
+ ob->anisotropicFriction[1] = 1.0f;
+ ob->anisotropicFriction[2] = 1.0f;
+ ob->gameflag= OB_PROP;
+
+ ob->data= add_obdata_from_type(type);
+
+ ob->lay= G.scene->lay;
+
+ base= scene_add_base(G.scene, ob);
+ scene_select_base(G.scene, base);
+
+ return ob;
+}
+
+void base_init_from_view3d(Base *base, View3D *v3d)
+{
+ Object *ob= base->object;
+
+ if (v3d->localview) {
+ base->lay= ob->lay= v3d->layact + v3d->lay;
+ VECCOPY(ob->loc, v3d->cursor);
+ } else {
+ base->lay= ob->lay= v3d->layact;
+ VECCOPY(ob->loc, G.scene->cursor);
+ }
+
+ v3d->viewquat[0]= -v3d->viewquat[0];
+ if (ob->transflag & OB_QUAT) {
+ QUATCOPY(ob->quat, v3d->viewquat);
+ } else {
+ QuatToEul(v3d->viewquat, ob->rot);
+ }
+ v3d->viewquat[0]= -v3d->viewquat[0];
+}
+
+Object *copy_object(Object *ob)
+{
+ Object *obn;
+ int a;
+ bConstraintChannel *actcon;
+
+ obn= copy_libblock(ob);
+
+ if(ob->totcol) {
+ obn->mat= MEM_dupallocN(ob->mat);
+ }
+
+ if(ob->bb) obn->bb= MEM_dupallocN(ob->bb);
+ obn->path= 0;
+ obn->flag &= ~OB_FROMGROUP;
+
+ copy_effects(&obn->effect, &ob->effect);
+
+ obn->network.first= obn->network.last= 0;
+
+ BPY_copy_scriptlink(&ob->scriptlink);
+
+ copy_properties(&obn->prop, &ob->prop);
+ copy_sensors(&obn->sensors, &ob->sensors);
+ copy_controllers(&obn->controllers, &ob->controllers);
+ copy_actuators(&obn->actuators, &ob->actuators);
+
+ copy_pose(&obn->pose, ob->pose, 1);
+ copy_defgroups(&obn->defbase, &ob->defbase);
+ copy_nlastrips(&obn->nlastrips, &ob->nlastrips);
+ copy_constraints (&obn->constraints, &ob->constraints);
+
+ actcon = clone_constraint_channels (&obn->constraintChannels, &ob->constraintChannels, ob->activecon);
+ /* If the active constraint channel was in this list, update it */
+ if (actcon)
+ obn->activecon = actcon;
+
+ /* usernummers ophogen */
+ id_us_plus((ID *)obn->data);
+ id_us_plus((ID *)obn->ipo);
+ id_us_plus((ID *)obn->action);
+ for(a=0; a<obn->totcol; a++) id_us_plus((ID *)obn->mat[a]);
+
+ obn->disp.first= obn->disp.last= 0;
+
+ return obn;
+}
+
+void expand_local_object(Object *ob)
+{
+ int a;
+
+ id_lib_extern((ID *)ob->action);
+ id_lib_extern((ID *)ob->ipo);
+ id_lib_extern((ID *)ob->data);
+
+ for(a=0; a<ob->totcol; a++) {
+ id_lib_extern((ID *)ob->mat[a]);
+ }
+}
+
+void make_local_object(Object *ob)
+{
+ Object *obn;
+ Scene *sce;
+ Base *base;
+ int local=0, lib=0;
+
+ /* - zijn er alleen lib users: niet doen
+ * - zijn er alleen locale users: flag zetten
+ * - mixed: copy
+ */
+
+ if(ob->id.lib==0) return;
+ if(ob->id.us==1) {
+ ob->id.lib= 0;
+ ob->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)ob, 0);
+
+ }
+ else {
+ sce= G.main->scene.first;
+ while(sce) {
+ base= sce->base.first;
+ while(base) {
+ if(base->object==ob) {
+ if(sce->id.lib) lib++;
+ else local++;
+ break;
+ }
+ base= base->next;
+ }
+ sce= sce->id.next;
+ }
+
+ if(local && lib==0) {
+ ob->id.lib= 0;
+ ob->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)ob, 0);
+ }
+ else if(local && lib) {
+ obn= copy_object(ob);
+ obn->id.us= 0;
+
+ sce= G.main->scene.first;
+ while(sce) {
+ if(sce->id.lib==0) {
+ base= sce->base.first;
+ while(base) {
+ if(base->object==ob) {
+ base->object= obn;
+ obn->id.us++;
+ ob->id.us--;
+ }
+ base= base->next;
+ }
+ }
+ sce= sce->id.next;
+ }
+ }
+ }
+
+ expand_local_object(ob);
+}
+
+/* *************** CALC ****************** */
+
+/* er zit ook een tijdberekening in de drawobject() */
+
+float bluroffs= 0.0;
+int no_speed_curve= 0;
+
+void set_mblur_offs(int blur)
+{
+ bluroffs= R.r.blurfac*((float)blur);
+ bluroffs/= (float)R.r.osa;
+}
+
+void disable_speed_curve(int val)
+{
+ no_speed_curve= val;
+}
+
+float bsystem_time(Object *ob, Object *par, float cfra, float ofs)
+{
+ /* geeft float terug ( zie ook frame_to_float in ipo.c) */
+
+ if(no_speed_curve==0) if(ob && ob->ipo) cfra= calc_ipo_time(ob->ipo, cfra);
+
+ /* tweede field */
+ if(R.flag & R_SEC_FIELD) {
+ if(R.r.mode & R_FIELDSTILL); else cfra+= .5;
+ }
+
+ /* motion blur */
+ cfra+= bluroffs;
+
+ /* global time */
+ cfra*= G.scene->r.framelen;
+
+ /* ofset frames */
+ if(ob && (ob->ipoflag & OB_OFFS_PARENT)) {
+ if((ob->partype & PARSLOW)==0) cfra-= ob->sf;
+ }
+
+ cfra-= ofs;
+
+ return cfra;
+}
+
+void object_to_mat3(Object *ob, float mat[][3]) /* no parent */
+{
+ float smat[3][3], vec[3];
+ float rmat[3][3];
+ float q1[4];
+
+ /* size */
+ if(ob->ipo) {
+ vec[0]= ob->size[0]+ob->dsize[0];
+ vec[1]= ob->size[1]+ob->dsize[1];
+ vec[2]= ob->size[2]+ob->dsize[2];
+ SizeToMat3(vec, smat);
+ }
+ else {
+ SizeToMat3(ob->size, smat);
+ }
+
+ /* rot */
+ if(ob->transflag & OB_QUAT) {
+ if(ob->ipo) {
+ QuatMul(q1, ob->quat, ob->dquat);
+ QuatToMat3(q1, rmat);
+ }
+ else {
+ QuatToMat3(ob->quat, rmat);
+ }
+ }
+ else {
+ if(ob->ipo) {
+ vec[0]= ob->rot[0]+ob->drot[0];
+ vec[1]= ob->rot[1]+ob->drot[1];
+ vec[2]= ob->rot[2]+ob->drot[2];
+ EulToMat3(vec, rmat);
+ }
+ else {
+ EulToMat3(ob->rot, rmat);
+ }
+ }
+ Mat3MulMat3(mat, rmat, smat);
+}
+
+void object_to_mat4(Object *ob, float mat[][4])
+{
+ float tmat[3][3];
+
+ object_to_mat3(ob, tmat);
+
+ Mat4CpyMat3(mat, tmat);
+
+ VECCOPY(mat[3], ob->loc);
+ if(ob->ipo) {
+ mat[3][0]+= ob->dloc[0];
+ mat[3][1]+= ob->dloc[1];
+ mat[3][2]+= ob->dloc[2];
+ }
+}
+
+int enable_cu_speed= 1;
+
+void ob_parcurve(Object *ob, Object *par, float mat[][4])
+{
+ Curve *cu;
+ float q[4], vec[4], dir[3], *quat, x1, ctime;
+
+ Mat4One(mat);
+
+ cu= par->data;
+ if(cu->path==0 || cu->path->data==0) calc_curvepath(par);
+ if(cu->path==0) return;
+
+ /* uitzondering afvangen: curve paden die als duplicator worden gebruikt */
+ if(enable_cu_speed) {
+ ctime= bsystem_time(ob, par, (float)G.scene->r.cfra, 0.0);
+
+ if(calc_ipo_spec(cu->ipo, CU_SPEED, &ctime)==0) {
+ ctime /= cu->pathlen;
+ CLAMP(ctime, 0.0, 1.0);
+ }
+ }
+ else {
+ ctime= G.scene->r.cfra - ob->sf;
+ ctime /= cu->pathlen;
+
+ CLAMP(ctime, 0.0, 1.0);
+ }
+
+ if( where_on_path(par, ctime, vec, dir) ) {
+
+ if(cu->flag & CU_FOLLOW) {
+ quat= vectoquat(dir, ob->trackflag, ob->upflag);
+
+ Normalise(dir);
+ q[0]= (float)cos(0.5*vec[3]);
+ x1= (float)sin(0.5*vec[3]);
+ q[1]= -x1*dir[0];
+ q[2]= -x1*dir[1];
+ q[3]= -x1*dir[2];
+ QuatMul(quat, q, quat);
+
+ QuatToMat4(quat, mat);
+ }
+
+ VECCOPY(mat[3], vec);
+
+ }
+}
+
+void ob_parbone(Object *ob, Object *par, float mat[][4])
+{
+ Bone *bone;
+ bArmature *arm;
+
+ Mat4One(mat);
+ arm=get_armature(par);
+ if (!arm)
+ return;
+
+ /* Make sure the bone is still valid */
+ bone = get_named_bone(arm, ob->parsubstr);
+ if (!bone){
+ printf ("Lost bone %s\n", ob->parsubstr);
+ return;
+ }
+
+ apply_pose_armature(arm, par->pose, 1); /* Hopefully can set doit parameter in the future */
+ where_is_bone (par, bone);
+
+ /* Translate by negative bone */
+ get_objectspace_bone_matrix(bone, mat, 0, 1);
+
+}
+
+void ob_parlimb(Object *ob, Object *par, float mat[][4])
+{
+ Ika *ika;
+ Limb *li;
+ float ang=0.0;
+ int cur=0;
+
+ /* in lokale ob space */
+ Mat4One(mat);
+
+ ika= par->data;
+ li= ika->limbbase.first;
+ while(li) {
+ ang+= li->alpha;
+ if(cur==ob->par1 || li->next==0) break;
+
+ cur++;
+ li= li->next;
+ }
+
+ mat[0][0]= (float)cos(ang);
+ mat[1][0]= (float)-sin(ang);
+ mat[0][1]= (float)sin(ang);
+ mat[1][1]= (float)cos(ang);
+
+ mat[3][0]= li->eff[0];
+ mat[3][1]= li->eff[1];
+
+}
+
+void give_parvert(Object *par, int nr, float *vec)
+{
+ Mesh *me;
+ MVert *mvert;
+ EditVert *eve;
+/* extern ListBase editNurb; already in bad lev calls */
+ Nurb *nu;
+ Curve *cu;
+ BPoint *bp;
+ DispList *dl;
+ BezTriple *bezt;
+ float *fp;
+ int a, count;
+
+ vec[0]=vec[1]=vec[2]= 0.0;
+
+ if(par->type==OB_MESH) {
+ if(par==G.obedit) {
+ if(nr >= G.totvert) nr= 0;
+
+ count= 0;
+ eve= G.edve.first;
+ while(eve) {
+ if(count==nr) {
+ memcpy(vec, eve->co, 12);
+ break;
+ }
+ eve= eve->next;
+ count++;
+ }
+ }
+ else {
+ me= par->data;
+ if(me->totvert) {
+ if(nr >= me->totvert) nr= 0;
+
+ /* is er deform */
+ dl= find_displist(&par->disp, DL_VERTS);
+ if(dl) {
+ fp= dl->verts+3*nr;
+ VECCOPY(vec, fp);
+ }
+ else {
+ mvert= me->mvert + nr;
+ VECCOPY(vec, mvert->co);
+ }
+ }
+ }
+ }
+ else if ELEM(par->type, OB_CURVE, OB_SURF) {
+
+ cu= par->data;
+ nu= cu->nurb.first;
+ if(par==G.obedit) nu= editNurb.first;
+
+ count= 0;
+ while(nu) {
+ if((nu->type & 7)==CU_BEZIER) {
+ bezt= nu->bezt;
+ a= nu->pntsu;
+ while(a--) {
+ if(count==nr) {
+ VECCOPY(vec, bezt->vec[1]);
+ break;
+ }
+ count++;
+ bezt++;
+ }
+ }
+ else {
+ bp= nu->bp;
+ a= nu->pntsu*nu->pntsv;
+ while(a--) {
+ if(count==nr) {
+ memcpy(vec, bp->vec, 12);
+ break;
+ }
+ count++;
+ bp++;
+ }
+ }
+ nu= nu->next;
+ }
+
+ }
+ else if(par->type==OB_IKA) {
+ Ika *ika= par->data;
+ Limb *li= ika->limbbase.first;
+ int cur= 1;
+ if(nr) {
+ while(li) {
+ if(cur==nr || li->next==0) break;
+ cur++;
+ li= li->next;
+ }
+ vec[0]= li->eff[0];
+ vec[1]= li->eff[1];
+ }
+ }
+ else return;
+}
+
+void ob_parvert3(Object *ob, Object *par, float mat[][4])
+{
+ float cmat[3][3], v1[3], v2[3], v3[3], q[4];
+
+ /* in lokale ob space */
+ Mat4One(mat);
+
+ if ELEM3(par->type, OB_MESH, OB_SURF, OB_CURVE) {
+
+ give_parvert(par, ob->par1, v1);
+ give_parvert(par, ob->par2, v2);
+ give_parvert(par, ob->par3, v3);
+
+ triatoquat(v1, v2, v3, q);
+ QuatToMat3(q, cmat);
+ Mat4CpyMat3(mat, cmat);
+
+ if(ob->type==OB_CURVE) {
+ VECCOPY(mat[3], v1);
+ }
+ else {
+ VecAddf(mat[3], v1, v2);
+ VecAddf(mat[3], mat[3], v3);
+ VecMulf(mat[3], 0.3333333f);
+ }
+ }
+}
+
+static int no_parent_ipo=0;
+void set_no_parent_ipo(int val)
+{
+ no_parent_ipo= val;
+}
+
+static float timefac= 1.0; /* 50 Hz, dtime:2 */
+void set_dtime(int dtime)
+{
+ timefac= ((float)(dtime-1))/2.0f;
+}
+
+static int during_script_flag=0;
+void disable_where_script(short on)
+{
+ during_script_flag= on;
+}
+
+int during_script(void) {
+ return during_script_flag;
+}
+
+void where_is_object_time(Object *ob, float ctime)
+{
+ Object *par;
+ float *fp1, *fp2, slowmat[4][4] = MAT4_UNITY;
+ float stime, fac1, fac2;
+ int a;
+ int pop;
+
+ /* nieuwe versie: correcte parent+vertexparent en track+parent */
+ /* deze berekent alleen de directe relatie met de parent en track */
+ /* hij is sneller, maar moet wel de timeoffs in de gaten houden */
+
+ if(ob==0) return;
+
+ if( ctime != ob->ctime) {
+ ob->ctime= ctime;
+
+ if(ob->ipo) {
+
+ stime= bsystem_time(ob, 0, ctime, 0.0);
+
+ calc_ipo(ob->ipo, stime);
+ execute_ipo((ID *)ob, ob->ipo);
+ }
+ }
+
+
+ if(ob->type==OB_IKA) {
+ Ika *ika= ob->data;
+ if(ika->parent) where_is_object_time(ika->parent, ctime);
+ }
+
+ if(ob->parent) {
+ par= ob->parent;
+
+ if(ob->ipoflag & OB_OFFS_PARENT) ctime-= ob->sf;
+
+ pop= 0;
+ if(no_parent_ipo==0 && ctime != par->ctime) {
+
+ // alleen voor ipo systemen?
+ pushdata(par, sizeof(Object));
+ pop= 1;
+
+ where_is_object_time(par, ctime);
+ }
+
+ solve_parenting(ob, par, slowmat, 0);
+
+ if(pop) {
+ poplast(par);
+ }
+
+ if(ob->partype & PARSLOW) {
+ // framerate meetellen
+
+ fac1= (float)(timefac/(1.0+ fabs(ob->sf)));
+ if(fac1>=1.0) return;
+ fac2= 1.0f-fac1;
+
+ fp1= ob->obmat[0];
+ fp2= slowmat[0];
+ for(a=0; a<16; a++, fp1++, fp2++) {
+ fp1[0]= fac1*fp1[0] + fac2*fp2[0];
+ }
+ }
+
+ }
+ else {
+ object_to_mat4(ob, ob->obmat);
+ }
+
+ /* Handle tracking */
+ if(ob->track) {
+ if( ctime != ob->track->ctime) where_is_object_time(ob->track, ctime);
+ solve_tracking (ob, ob->track->obmat);
+
+ }
+
+ solve_constraints (ob, TARGET_OBJECT, NULL, ctime);
+
+ if(ob->scriptlink.totscript && !during_script()) {
+ BPY_do_pyscript((ID *)ob, SCRIPT_REDRAW);
+ }
+}
+
+static void solve_parenting (Object *ob, Object *par, float slowmat[][4], int simul)
+{
+ float totmat[4][4];
+ float tmat[4][4];
+ float obmat[4][4];
+ float vec[3];
+ int ok;
+
+ object_to_mat4(ob, obmat);
+
+ if(ob->partype & PARSLOW) Mat4CpyMat4(slowmat, ob->obmat);
+
+
+ switch(ob->partype & PARTYPE) {
+ case PAROBJECT:
+ ok= 0;
+ if(par->type==OB_CURVE) {
+ if( ((Curve *)par->data)->flag & CU_PATH ) {
+ ob_parcurve(ob, par, tmat);
+ ok= 1;
+ }
+ }
+
+ if(ok) Mat4MulSerie(totmat, par->obmat, tmat,
+ NULL, NULL, NULL, NULL, NULL, NULL);
+ else Mat4CpyMat4(totmat, par->obmat);
+
+ break;
+ case PARBONE:
+ ob_parbone(ob, par, tmat);
+ Mat4MulSerie(totmat, par->obmat, tmat,
+ NULL, NULL, NULL, NULL, NULL, NULL);
+ break;
+ case PARLIMB:
+ ob_parlimb(ob, par, tmat);
+ Mat4MulSerie(totmat, par->obmat, tmat,
+ NULL, NULL, NULL, NULL, NULL, NULL);
+ break;
+
+ case PARVERT1:
+ Mat4One(totmat);
+ if (simul){
+ VECCOPY(totmat[3], par->obmat[3]);
+ }
+ else{
+ give_parvert(par, ob->par1, vec);
+ VecMat4MulVecfl(totmat[3], par->obmat, vec);
+ }
+ break;
+ case PARVERT3:
+ ob_parvert3(ob, par, tmat);
+
+ Mat4MulSerie(totmat, par->obmat, tmat,
+ NULL, NULL, NULL, NULL, NULL, NULL);
+ break;
+
+ case PARSKEL:
+#if 0
+ if (ob!=G.obedit)
+ Mat4One(totmat);
+ else
+ Mat4CpyMat4(totmat, par->obmat);
+ break;
+#else
+ Mat4CpyMat4(totmat, par->obmat);
+#endif
+ }
+
+ // totaal
+ Mat4MulSerie(tmat, totmat, ob->parentinv,
+ NULL, NULL, NULL, NULL, NULL, NULL);
+ Mat4MulSerie(ob->obmat, tmat, obmat,
+ NULL, NULL, NULL, NULL, NULL, NULL);
+
+ if (simul){
+
+ }
+ else{
+ // >>>>>>>>>>>>>>>>>>
+ // dit is een extern bruikbare originmat
+ Mat3CpyMat4(originmat, tmat);
+
+ // origin, voor hulplijntje
+ if( (ob->partype & 15)==PARSKEL ) {
+ VECCOPY(ob->orig, par->obmat[3]);
+ }
+ else {
+ VECCOPY(ob->orig, totmat[3]);
+ }
+ }
+
+}
+void solve_tracking (Object *ob, float targetmat[][4])
+{
+ float *quat;
+ float vec[3];
+ float totmat[3][3];
+ float tmat[4][4];
+
+ VecSubf(vec, ob->obmat[3], targetmat[3]);
+ quat= vectoquat(vec, ob->trackflag, ob->upflag);
+ QuatToMat3(quat, totmat);
+
+ if(ob->parent && (ob->transflag & OB_POWERTRACK)) {
+ /* 'tijdelijk' : parent info wissen */
+ object_to_mat4(ob, tmat);
+ tmat[0][3]= ob->obmat[0][3];
+ tmat[1][3]= ob->obmat[1][3];
+ tmat[2][3]= ob->obmat[2][3];
+ tmat[3][0]= ob->obmat[3][0];
+ tmat[3][1]= ob->obmat[3][1];
+ tmat[3][2]= ob->obmat[3][2];
+ tmat[3][3]= ob->obmat[3][3];
+ }
+ else Mat4CpyMat4(tmat, ob->obmat);
+
+ Mat4MulMat34(ob->obmat, totmat, tmat);
+
+}
+
+void where_is_object(Object *ob)
+{
+
+ /* deze zijn gememcopied */
+ if(ob->flag & OB_FROMDUPLI) return;
+
+ where_is_object_time(ob, (float)G.scene->r.cfra);
+}
+
+
+void where_is_object_simul(Object *ob)
+/* It seems that this function is only called
+for a lamp that is the child of another object */
+{
+ Object *par;
+ Ipo *ipo;
+ float *fp1, *fp2;
+ float slowmat[4][4];
+ float fac1, fac2;
+ int a;
+
+ /* nieuwe versie: correcte parent+vertexparent en track+parent */
+ /* deze berekent alleen de directe relatie met de parent en track */
+ /* GEEN TIMEOFFS */
+
+ /* geen ipo! (ivm dloc en realtime-ipos) */
+ ipo= ob->ipo;
+ ob->ipo= NULL;
+
+ if(ob->parent) {
+ par= ob->parent;
+
+ solve_parenting(ob, par, slowmat, 1);
+
+ if(ob->partype & PARSLOW) {
+
+ fac1= (float)(1.0/(1.0+ fabs(ob->sf)));
+ fac2= 1.0f-fac1;
+ fp1= ob->obmat[0];
+ fp2= slowmat[0];
+ for(a=0; a<16; a++, fp1++, fp2++) {
+ fp1[0]= fac1*fp1[0] + fac2*fp2[0];
+ }
+ }
+
+ }
+ else {
+ object_to_mat4(ob, ob->obmat);
+ }
+
+ if(ob->track)
+ solve_tracking(ob, ob->track->obmat);
+
+ solve_constraints(ob, TARGET_OBJECT, NULL, G.scene->r.cfra);
+
+ /* LET OP!!! */
+ ob->ipo= ipo;
+
+}
+extern void Mat4BlendMat4(float out[][4], float dst[][4], float src[][4], float srcweight);
+
+void solve_constraints (Object *ob, short obtype, void *obdata, float ctime)
+{
+ bConstraint *con;
+ float tmat[4][4], focusmat[4][4], lastmat[4][4];
+ int i, clear=1, tot=0;
+ float a;
+ float aquat[4], quat[4];
+ float aloc[3], loc[3];
+ float asize[3], size[3];
+ float oldmat[4][4];
+ float smat[3][3], rmat[3][3], mat[3][3];
+ float enf;
+
+ for (con = ob->constraints.first; con; con=con->next){
+ /* Clear accumulators if necessary*/
+ if (clear){
+ clear=0;
+ a=0;
+ tot=0;
+ memset(aquat, 0, sizeof(float)*4);
+ memset(aloc, 0, sizeof(float)*3);
+ memset(asize, 0, sizeof(float)*3);
+ }
+
+ /* Check this constraint only if it has some enforcement */
+ // if (con->enforce > 0)
+ if (!(con->flag & CONSTRAINT_DISABLE))
+ {
+ if (con->enforce==0)
+ enf = 0.001f;
+ enf = con->enforce;
+
+ /* Get the targetmat */
+ get_constraint_target(con, obtype, obdata, tmat, size, ctime);
+
+ Mat4CpyMat4(focusmat, tmat);
+
+ /* Extract the components & accumulate */
+ Mat4ToQuat(focusmat, quat);
+ VECCOPY(loc, focusmat[3]);
+
+ a+=enf;
+ tot++;
+
+ for(i=0; i<3; i++){
+ aquat[i+1]+=(quat[i+1]) * enf;
+ aloc[i]+=(loc[i]) * enf;
+ asize[i]+=(size[i]-1.0f) * enf;
+ }
+ aquat[0]+=(quat[0])*enf;
+ Mat4CpyMat4(lastmat, focusmat);
+ }
+
+ /* If the next constraint is not the same type (or there isn't one),
+ * then evaluate the accumulator & request a clear */
+ if ((!con->next)||(con->next && con->next->type!=con->type))
+ {
+ clear=1;
+ Mat4CpyMat4(oldmat, ob->obmat);
+
+ /* If we have several inputs, do a blend of them */
+ if (tot){
+ if (tot>1){
+ if (a){
+ for (i=0; i<3; i++){
+ asize[i]=1.0f + (asize[i]/(a));
+ aloc[i]=(aloc[i]/a);
+ }
+
+ NormalQuat(aquat);
+
+ QuatToMat3(aquat, rmat);
+ SizeToMat3(asize, smat);
+ Mat3MulMat3(mat, rmat, smat);
+ Mat4CpyMat3(focusmat, mat);
+ VECCOPY(focusmat[3], aloc);
+
+ evaluate_constraint(con, ob, obtype, obdata, focusmat);
+ }
+
+ }
+ /* If we only have one, blend with the current obmat */
+ else{
+ float solution[4][4];
+ float delta[4][4];
+ float imat[4][4];
+ float identity[4][4];
+ float worldmat[4][4];
+
+ if (con->type!=CONSTRAINT_TYPE_KINEMATIC){
+ /* If we're not an IK constraint, solve the constraint then blend it to the previous one */
+ evaluate_constraint(con, ob, obtype, obdata, lastmat);
+
+ Mat4CpyMat4 (solution, ob->obmat);
+
+ /* Interpolate the enforcement */
+ Mat4Invert (imat, oldmat);
+ Mat4MulMat4 (delta, solution, imat);
+
+ Mat4One(identity);
+ Mat4BlendMat4(delta, identity, delta, a);
+ Mat4MulMat4 (ob->obmat, delta, oldmat);
+
+ }
+ else{
+ /* Interpolate the target between the chain's unconstrained endpoint and the effector loc */
+ if (obtype==TARGET_BONE){
+ get_objectspace_bone_matrix(obdata, oldmat, 1, 1);
+
+ Mat4MulMat4(worldmat, oldmat, ob->parent->obmat);
+
+ Mat4BlendMat4(focusmat, worldmat, lastmat, a);
+
+ evaluate_constraint(con, ob, obtype, obdata, focusmat);
+ }
+ }
+ }
+ }
+ }
+ }
+}
+void what_does_parent1(Object *par, int partype, int par1, int par2, int par3)
+{
+
+ clear_workob();
+ Mat4One(workob.parentinv);
+ workob.parent= par;
+ if(par)
+ workob.track= par->track; /* LET OP: NIET ECHT NETJES */
+ workob.partype= partype;
+ workob.par1= par1;
+ workob.par2= par2;
+ workob.par3= par3;
+
+ if (par){
+ workob.constraints.first = par->constraints.first;
+ workob.constraints.last = par->constraints.last;
+ }
+
+ where_is_object(&workob);
+}
+
+
+void what_does_parent(Object *ob)
+{
+
+ clear_workob();
+ Mat4One(workob.obmat);
+ Mat4One(workob.parentinv);
+ workob.parent= ob->parent;
+ workob.track= ob->track;
+
+ workob.trackflag= ob->trackflag;
+ workob.upflag= ob->upflag;
+
+ workob.partype= ob->partype;
+ workob.par1= ob->par1;
+ workob.par2= ob->par2;
+ workob.par3= ob->par3;
+
+ workob.constraints.first = ob->constraints.first;
+ workob.constraints.last = ob->constraints.last;
+
+ strcpy (workob.parsubstr, ob->parsubstr);
+
+ where_is_object(&workob);
+}
+
+BoundBox *unit_boundbox()
+{
+ BoundBox *bb;
+
+ bb= MEM_mallocN(sizeof(BoundBox), "bb");
+
+ bb->vec[0][0]=bb->vec[1][0]=bb->vec[2][0]=bb->vec[3][0]= -1.0;
+ bb->vec[4][0]=bb->vec[5][0]=bb->vec[6][0]=bb->vec[7][0]= 1.0;
+
+ bb->vec[0][1]=bb->vec[1][1]=bb->vec[4][1]=bb->vec[5][1]= -1.0;
+ bb->vec[2][1]=bb->vec[3][1]=bb->vec[6][1]=bb->vec[7][1]= 1.0;
+
+ bb->vec[0][2]=bb->vec[3][2]=bb->vec[4][2]=bb->vec[7][2]= -1.0;
+ bb->vec[1][2]=bb->vec[2][2]=bb->vec[5][2]=bb->vec[6][2]= 1.0;
+
+ return bb;
+}
+
+void minmax_object(Object *ob, float *min, float *max)
+{
+ BoundBox bb;
+ Mesh *me;
+ Curve *cu;
+ float vec[3];
+ int a;
+
+ switch(ob->type) {
+
+ case OB_CURVE:
+ case OB_FONT:
+ case OB_SURF:
+ cu= ob->data;
+
+ if(cu->bb==0) tex_space_curve(cu);
+ bb= *(cu->bb);
+
+ for(a=0; a<8; a++) {
+ Mat4MulVecfl(ob->obmat, bb.vec[a]);
+ DO_MINMAX(bb.vec[a], min, max);
+ }
+ break;
+
+ case OB_MESH:
+ me= get_mesh(ob);
+
+ if(me) {
+ if(me->bb==0) tex_space_mesh(me);
+ bb= *(me->bb);
+
+ for(a=0; a<8; a++) {
+ Mat4MulVecfl(ob->obmat, bb.vec[a]);
+ DO_MINMAX(bb.vec[a], min, max);
+ }
+ }
+ if(min[0] < max[0] ) break;
+
+ /* else here no break!!!, mesh can be zero sized */
+
+ default:
+ DO_MINMAX(ob->obmat[3], min, max);
+
+ VECCOPY(vec, ob->obmat[3]);
+ VecAddf(vec, vec, ob->size);
+ DO_MINMAX(vec, min, max);
+
+ VECCOPY(vec, ob->obmat[3]);
+ VecSubf(vec, vec, ob->size);
+ DO_MINMAX(vec, min, max);
+ break;
+ }
+}
+
+
diff --git a/source/blender/blenkernel/intern/packedFile.c b/source/blender/blenkernel/intern/packedFile.c
new file mode 100644
index 00000000000..991b4a8c840
--- /dev/null
+++ b/source/blender/blenkernel/intern/packedFile.c
@@ -0,0 +1,638 @@
+/**
+ * blenkernel/packedFile.c - (cleaned up mar-01 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 <fcntl.h>
+#include <sys/stat.h>
+#ifndef WIN32
+#include <unistd.h>
+#else
+#include <io.h>
+#endif
+#include <string.h>
+#include "MEM_guardedalloc.h"
+
+#include "DNA_image_types.h"
+#include "DNA_sound_types.h"
+#include "DNA_vfont_types.h"
+#include "DNA_packedFile_types.h"
+
+
+#include "BLI_blenlib.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_bad_level_calls.h"
+
+#include "BKE_global.h"
+#include "BKE_main.h"
+
+#include "BKE_screen.h"
+
+#include "BKE_sound.h"
+//#include "sound.h"
+
+#include "BKE_image.h"
+#include "BKE_font.h"
+#include "BKE_packedFile.h"
+
+int seekPackedFile(PackedFile * pf, int offset, int whence)
+{
+ int oldseek = -1, seek = 0;
+
+ if (pf) {
+ oldseek = pf->seek;
+ switch(whence) {
+ case SEEK_CUR:
+ seek = oldseek + offset;
+ break;
+ case SEEK_END:
+ seek = pf->size + offset;
+ break;
+ case SEEK_SET:
+ seek = offset;
+ break;
+ default:
+ oldseek = -1;
+ }
+ if (seek < 0) {
+ seek = 0;
+ } else if (seek > pf->size) {
+ seek = pf->size;
+ }
+ pf->seek = seek;
+ }
+
+ return(oldseek);
+}
+
+void rewindPackedFile(PackedFile * pf)
+{
+ seekPackedFile(pf, 0, SEEK_SET);
+}
+
+int readPackedFile(PackedFile * pf, void * data, int size)
+{
+ if ((pf != NULL) && (size >= 0) && (data != NULL)) {
+ if (size + pf->seek > pf->size) {
+ size = pf->size - pf->seek;
+ }
+
+ if (size > 0) {
+ memcpy(data, ((char *) pf->data) + pf->seek, size);
+ } else {
+ size = 0;
+ }
+
+ pf->seek += size;
+ } else {
+ size = -1;
+ }
+
+ return(size);
+}
+
+int countPackedFiles()
+{
+ int count = 0;
+ Image *ima;
+ VFont *vf;
+ bSample *sample;
+
+ // let's check if there are packed files...
+ ima = G.main->image.first;
+ while (ima) {
+ if (ima->packedfile) {
+ count++;
+ }
+ ima= ima->id.next;
+ }
+
+ vf = G.main->vfont.first;
+ while (vf) {
+ if (vf->packedfile) {
+ count++;
+ }
+ vf = vf->id.next;
+ }
+
+ sample = samples->first;
+ while (sample) {
+ if (sample->packedfile) {
+ count++;
+ }
+ sample = sample->id.next;
+ }
+
+ return(count);
+}
+
+void freePackedFile(PackedFile * pf)
+{
+ if (pf) {
+ MEM_freeN(pf->data);
+ MEM_freeN(pf);
+ } else {
+ printf("freePackedFile: Trying to free a NULL pointer\n");
+ }
+}
+
+PackedFile * newPackedFileMemory(void *mem, int memlen)
+{
+ PackedFile * pf = MEM_callocN(sizeof(*pf), "PackedFile");
+ pf->data = mem;
+ pf->size = memlen;
+
+ return pf;
+}
+
+PackedFile * newPackedFile(char * filename)
+{
+ PackedFile * pf = NULL;
+ int file, filelen;
+ char name[FILE_MAXDIR+FILE_MAXFILE];
+ void * data;
+
+ waitcursor(1);
+
+ // convert relative filenames to absolute filenames
+
+ strcpy(name, filename);
+ BLI_convertstringcode(name, G.sce, G.scene->r.cfra);
+
+ // open the file
+ // and create a PackedFile structure
+
+ file= open(name, O_BINARY|O_RDONLY);
+ if (file <= 0) {
+ // error("Can't open file: %s", name);
+ } else {
+ filelen = BLI_filesize(file);
+
+ if (filelen == 0) {
+ // MEM_mallocN complains about MEM_mallocN(0, "bla");
+ // we don't care....
+ data = MEM_mallocN(1, "packFile");
+ } else {
+ data = MEM_mallocN(filelen, "packFile");
+ }
+ if (read(file, data, filelen) == filelen) {
+ pf = newPackedFileMemory(data, filelen);
+ }
+
+ close(file);
+ }
+
+ waitcursor(0);
+
+ return (pf);
+}
+
+void packAll()
+{
+ Image *ima;
+ VFont *vf;
+ bSample *sample;
+
+ ima = G.main->image.first;
+ while (ima) {
+ if (ima->packedfile == NULL) {
+ ima->packedfile = newPackedFile(ima->name);
+ }
+ ima= ima->id.next;
+ }
+
+ vf = G.main->vfont.first;
+ while (vf) {
+ if (vf->packedfile == NULL) {
+ vf->packedfile = newPackedFile(vf->name);
+ }
+ vf = vf->id.next;
+ }
+
+
+ sample = samples->first;
+ while (sample) {
+ if (sample->packedfile == NULL) {
+ sound_set_packedfile(sample, newPackedFile(sample->name));
+ }
+ sample = sample->id.next;
+ }
+}
+
+
+/*
+
+// attempt to create a function that generates an unique filename
+// this will work when all funtions in fileops.c understand relative filenames...
+
+char * find_new_name(char * name)
+{
+ char tempname[FILE_MAXDIR + FILE_MAXFILE];
+ char * newname;
+
+ if (fop_exists(name)) {
+ for (number = 1; number <= 999; number++) {
+ sprintf(tempname, "%s.%03d", name, number);
+ if (! fop_exists(tempname)) {
+ break;
+ }
+ }
+ }
+
+ newname = mallocN(strlen(tempname) + 1, "find_new_name");
+ strcpy(newname, tempname);
+
+ return(newname);
+}
+
+*/
+
+int writePackedFile(char * filename, PackedFile *pf)
+{
+ int file, number, remove_tmp = FALSE;
+ int ret_value = RET_OK;
+ char name[FILE_MAXDIR + FILE_MAXFILE];
+ char tempname[FILE_MAXDIR + FILE_MAXFILE];
+/* void * data; */
+
+ waitcursor(1);
+
+ strcpy(name, filename);
+ BLI_convertstringcode(name, G.sce, G.scene->r.cfra);
+
+ if (BLI_exists(name)) {
+ for (number = 1; number <= 999; number++) {
+ sprintf(tempname, "%s.%03d_", name, number);
+ if (! BLI_exists(tempname)) {
+ if (BLI_copy_fileops(name, tempname) == RET_OK) {
+ remove_tmp = TRUE;
+ }
+ break;
+ }
+ }
+ }
+
+ // make sure the path to the file exists...
+ RE_make_existing_file(name);
+
+ file = open(name, O_BINARY + O_WRONLY + O_CREAT + O_TRUNC, 0666);
+ if (file >= 0) {
+ if (write(file, pf->data, pf->size) != pf->size) {
+ error("Error writing file: %s", name);
+ ret_value = RET_ERROR;
+ }
+ close(file);
+ } else {
+ error("Error creating file: %s", name);
+ ret_value = RET_ERROR;
+ }
+
+ if (remove_tmp) {
+ if (ret_value == RET_ERROR) {
+ if (BLI_rename(tempname, name) == RET_ERROR) {
+ error("Error restoring tempfile. Check files: '%s' '%s'", tempname, name);
+ }
+ } else {
+ if (BLI_delete(tempname, 0, 0) == RET_ERROR) {
+ error("Error deleting '%s' (ignored)");
+ }
+ }
+ }
+
+ waitcursor(0);
+
+ return (ret_value);
+}
+
+/*
+
+This function compares a packed file to a 'real' file.
+It returns an integer indicating if:
+
+PF_EQUAL - the packed file and original file are identical
+PF_DIFFERENT - the packed file and original file differ
+PF_NOFILE - the original file doens't exist
+
+*/
+
+int checkPackedFile(char * filename, PackedFile * pf)
+{
+ struct stat st;
+ int ret_val, i, len, file;
+ char buf[4096];
+ char name[FILE_MAXDIR + FILE_MAXFILE];
+
+ strcpy(name, filename);
+ BLI_convertstringcode(name, G.sce, G.scene->r.cfra);
+
+ if (stat(name, &st)) {
+ ret_val = PF_NOFILE;
+ } else if (st.st_size != pf->size) {
+ ret_val = PF_DIFFERS;
+ } else {
+ // we'll have to compare the two...
+
+ file = open(name, O_BINARY | O_RDONLY);
+ if (file < 0) {
+ ret_val = PF_NOFILE;
+ } else {
+ ret_val = PF_EQUAL;
+
+ for (i = 0; i < pf->size; i += sizeof(buf)) {
+ len = pf->size - i;
+ if (len > sizeof(buf)) {
+ len = sizeof(buf);
+ }
+
+ if (read(file, buf, len) != len) {
+ // read error ...
+ ret_val = PF_DIFFERS;
+ break;
+ } else {
+ if (memcmp(buf, ((char *)pf->data) + i, len)) {
+ ret_val = PF_DIFFERS;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ return(ret_val);
+}
+
+/*
+
+unpackFile() looks at the existing files (abs_name, local_name) and a packed file.
+If how == PF_ASK it offers the user a couple of options what to do with the packed file.
+
+It returns a char * to the existing file name / new file name or NULL when
+there was an error or when the user desides to cancel the operation.
+
+*/
+
+char * unpackFile(char * abs_name, char * local_name, PackedFile * pf, int how)
+{
+ char menu[6 * (FILE_MAXDIR + FILE_MAXFILE + 100)];
+ char line[FILE_MAXDIR + FILE_MAXFILE + 100];
+ char * newname = NULL, * temp = NULL;
+
+ // char newabs[FILE_MAXDIR + FILE_MAXFILE];
+ // char newlocal[FILE_MAXDIR + FILE_MAXFILE];
+
+ if (pf != NULL) {
+ if (how == PF_ASK) {
+ strcpy(menu, "UnPack file%t");
+
+ if (strcmp(abs_name, local_name)) {
+ switch (checkPackedFile(local_name, pf)) {
+ case PF_NOFILE:
+ sprintf(line, "|Create %s%%x%d", local_name, PF_WRITE_LOCAL);
+ strcat(menu, line);
+ break;
+ case PF_EQUAL:
+ sprintf(line, "|Use %s (identical)%%x%d", local_name, PF_USE_LOCAL);
+ strcat(menu, line);
+ break;
+ case PF_DIFFERS:
+ sprintf(line, "|Use %s (differs)%%x%d", local_name, PF_USE_LOCAL);
+ strcat(menu, line);
+ sprintf(line, "|Overwrite %s%%x%d", local_name, PF_WRITE_LOCAL);
+ strcat(menu, line);
+ break;
+ }
+ // sprintf(line, "|%%x%d", PF_INVALID);
+ // strcat(menu, line);
+ }
+
+ switch (checkPackedFile(abs_name, pf)) {
+ case PF_NOFILE:
+ sprintf(line, "|Create %s%%x%d", abs_name, PF_WRITE_ORIGINAL);
+ strcat(menu, line);
+ break;
+ case PF_EQUAL:
+ sprintf(line, "|Use %s (identical)%%x%d", abs_name, PF_USE_ORIGINAL);
+ strcat(menu, line);
+ break;
+ case PF_DIFFERS:
+ sprintf(line, "|Use %s (differs)%%x%d", abs_name, PF_USE_ORIGINAL);
+ strcat(menu, line);
+ sprintf(line, "|Overwrite %s%%x%d", abs_name, PF_WRITE_ORIGINAL);
+ strcat(menu, line);
+ break;
+ }
+
+ how = pupmenu(menu);
+ }
+
+ switch (how) {
+ case -1:
+ case PF_KEEP:
+ break;
+ case PF_USE_LOCAL:
+ // if file exists use it
+ if (BLI_exists(local_name)) {
+ temp = local_name;
+ break;
+ }
+ // else fall through and create it
+ case PF_WRITE_LOCAL:
+ if (writePackedFile(local_name, pf) == RET_OK) {
+ temp = local_name;
+ }
+ break;
+ case PF_USE_ORIGINAL:
+ // if file exists use it
+ if (BLI_exists(abs_name)) {
+ temp = abs_name;
+ break;
+ }
+ // else fall through and create it
+ case PF_WRITE_ORIGINAL:
+ if (writePackedFile(abs_name, pf) == RET_OK) {
+ temp = abs_name;
+ }
+ break;
+ default:
+ printf("unpackFile: unknown return_value %d\n", how);
+ break;
+ }
+
+ if (temp) {
+ newname = MEM_mallocN(strlen(temp) + 1, "unpack_file newname");
+ strcpy(newname, temp);
+ }
+ }
+
+ return (newname);
+}
+
+
+int unpackVFont(VFont * vfont, int how)
+{
+ char localname[FILE_MAXDIR + FILE_MAXFILE], fi[FILE_MAXFILE];
+ char * newname;
+ int ret_value = RET_ERROR;
+
+ if (vfont != NULL) {
+ strcpy(localname, vfont->name);
+ BLI_splitdirstring(localname, fi);
+
+ sprintf(localname, "//fonts/%s", fi);
+
+ newname = unpackFile(vfont->name, localname, vfont->packedfile, how);
+ if (newname != NULL) {
+ ret_value = RET_OK;
+ freePackedFile(vfont->packedfile);
+ vfont->packedfile = 0;
+ strcpy(vfont->name, newname);
+ MEM_freeN(newname);
+ }
+ }
+
+ return (ret_value);
+}
+
+/*
+create_local_name() creates a relative (starting with //) name.
+Because it is allowed to have /'s and \'s in blenderobject names
+we have to remove these first.
+*/
+
+
+void create_local_name(char *localname, char *prefix, char *filename)
+{
+ char tempname[FILE_MAXDIR + FILE_MAXFILE];
+ int i, len;
+
+ strcpy(tempname, filename);
+ len = strlen(tempname);
+
+ for (i = 0; i < len ; i++) {
+ switch (tempname[i])
+ {
+ case '/':
+ case '\\':
+ case ' ':
+ tempname[i] = '_';
+ break;
+ }
+ }
+
+ strcpy(localname, prefix);
+ strcat(localname, tempname);
+}
+
+
+int unpackSample(bSample *sample, int how)
+{
+ char localname[FILE_MAXDIR + FILE_MAXFILE];
+ char * newname;
+ int ret_value = RET_ERROR;
+ PackedFile *pf;
+
+ if (sample != NULL) {
+ create_local_name(localname, "//samples/", sample->id.name + 2);
+
+ newname = unpackFile(sample->name, localname, sample->packedfile, how);
+ if (newname != NULL) {
+ strcpy(sample->name, newname);
+ MEM_freeN(newname);
+
+ pf = sample->packedfile;
+ // because samples and sounds can point to the
+ // same packedfile we have to check them all
+ sound_set_packedfile(sample, NULL);
+ freePackedFile(pf);
+
+ ret_value = RET_OK;
+ }
+ }
+
+ return(ret_value);
+}
+
+int unpackImage(Image * ima, int how)
+{
+ char localname[FILE_MAXDIR + FILE_MAXFILE];
+ char * newname;
+ int ret_value = RET_ERROR;
+
+ if (ima != NULL) {
+ create_local_name(localname, "//textures/", ima->id.name + 2);
+
+ newname = unpackFile(ima->name, localname, ima->packedfile, how);
+ if (newname != NULL) {
+ ret_value = RET_OK;
+ freePackedFile(ima->packedfile);
+ ima->packedfile = 0;
+ strcpy(ima->name, newname);
+ MEM_freeN(newname);
+ free_image_buffers(ima);
+ }
+ }
+
+ return(ret_value);
+}
+
+void unpackAll(int how)
+{
+ Image *ima;
+ VFont *vf;
+ bSample *sample;
+
+ ima = G.main->image.first;
+ while (ima) {
+ if (ima->packedfile) {
+ unpackImage(ima, how);
+ }
+ ima= ima->id.next;
+ }
+
+ vf = G.main->vfont.first;
+ while (vf) {
+ if (vf->packedfile) {
+ unpackVFont(vf, how);
+ }
+ vf = vf->id.next;
+ }
+
+ sample = samples->first;
+ while (sample) {
+ if (sample->packedfile) {
+ unpackSample(sample, how);
+ }
+ sample = sample->id.next;
+ }
+}
diff --git a/source/blender/blenkernel/intern/property.c b/source/blender/blenkernel/intern/property.c
new file mode 100644
index 00000000000..d097dba0db0
--- /dev/null
+++ b/source/blender/blenkernel/intern/property.c
@@ -0,0 +1,269 @@
+
+/* property.c june 2000
+ *
+ * ton roosendaal
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 <string.h>
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_property_types.h"
+#include "DNA_object_types.h"
+#include "DNA_listBase.h"
+
+
+#include "BLI_blenlib.h"
+#include "BKE_bad_level_calls.h"
+#include "BKE_property.h"
+
+void free_property(bProperty *prop)
+{
+
+ if(prop->poin && prop->poin != &prop->data) MEM_freeN(prop->poin);
+ MEM_freeN(prop);
+
+}
+
+void free_properties(ListBase *lb)
+{
+ bProperty *prop;
+
+ while( (prop= lb->first) ) {
+ BLI_remlink(lb, prop);
+ free_property(prop);
+ }
+}
+
+bProperty *copy_property(bProperty *prop)
+{
+ bProperty *propn;
+
+ propn= MEM_dupallocN(prop);
+ if(prop->poin && prop->poin != &prop->data) {
+ propn->poin= MEM_dupallocN(prop->poin);
+ }
+ else propn->poin= &propn->data;
+
+ return propn;
+}
+
+void copy_properties(ListBase *lbn, ListBase *lbo)
+{
+ bProperty *prop, *propn;
+
+ lbn->first= lbn->last= 0;
+ prop= lbo->first;
+ while(prop) {
+ propn= copy_property(prop);
+ BLI_addtail(lbn, propn);
+ prop= prop->next;
+ }
+
+
+}
+
+void init_property(bProperty *prop)
+{
+ /* also use when property changes type */
+
+ if(prop->poin && prop->poin != &prop->data) MEM_freeN(prop->poin);
+ prop->poin= 0;
+
+ prop->otype= prop->type;
+ prop->data= 0;
+
+ switch(prop->type) {
+ case PROP_BOOL:
+ prop->poin= &prop->data;
+ break;
+ case PROP_INT:
+ prop->poin= &prop->data;
+ break;
+ case PROP_FLOAT:
+ prop->poin= &prop->data;
+ break;
+ case PROP_STRING:
+ prop->poin= MEM_callocN(MAX_PROPSTRING, "property string");
+ break;
+ case PROP_TIME:
+ prop->poin= &prop->data;
+ break;
+ }
+}
+
+
+bProperty *new_property(int type)
+{
+ bProperty *prop;
+
+ prop= MEM_callocN(sizeof(bProperty), "property");
+ prop->type= type;
+
+ init_property(prop);
+
+ strcpy(prop->name, "prop");
+
+ return prop;
+}
+
+bProperty *get_property(Object *ob, char *name)
+{
+ bProperty *prop;
+
+ prop= ob->prop.first;
+ while(prop) {
+ if( strcmp(prop->name, name)==0 ) return prop;
+ prop= prop->next;
+ }
+ return NULL;
+}
+
+/* negative: prop is smaller
+ * positive: prop is larger
+ */
+int compare_property(bProperty *prop, char *str)
+{
+// extern int Gdfra; /* sector.c */
+ float fvalue, ftest;
+
+ switch(prop->type) {
+ case PROP_BOOL:
+ if(strcasecmp(str, "true")==0) {
+ if(prop->data==1) return 0;
+ else return 1;
+ }
+ else if(strcasecmp(str, "false")==0) {
+ if(prop->data==0) return 0;
+ else return 1;
+ }
+ /* no break, do prop_int too! */
+
+ case PROP_INT:
+ return prop->data - atoi(str);
+
+ case PROP_FLOAT:
+ case PROP_TIME:
+ // WARNING: untested for PROP_TIME
+ // function isn't used currently
+ fvalue= *((float *)&prop->data);
+ ftest= (float)atof(str);
+ if( fvalue > ftest) return 1;
+ else if( fvalue < ftest) return -1;
+ return 0;
+
+ case PROP_STRING:
+ return strcmp(prop->poin, str);
+ }
+
+ return 0;
+}
+
+void set_property(bProperty *prop, char *str)
+{
+// extern int Gdfra; /* sector.c */
+
+ switch(prop->type) {
+ case PROP_BOOL:
+ if(strcasecmp(str, "true")==0) prop->data= 1;
+ else if(strcasecmp(str, "false")==0) prop->data= 0;
+ else prop->data= (atoi(str)!=0);
+ break;
+ case PROP_INT:
+ prop->data= atoi(str);
+ break;
+ case PROP_FLOAT:
+ case PROP_TIME:
+ *((float *)&prop->data)= (float)atof(str);
+ break;
+ case PROP_STRING:
+ strcpy(prop->poin, str);
+ break;
+ }
+
+}
+
+void add_property(bProperty *prop, char *str)
+{
+// extern int Gdfra; /* sector.c */
+
+ switch(prop->type) {
+ case PROP_BOOL:
+ case PROP_INT:
+ prop->data+= atoi(str);
+ break;
+ case PROP_FLOAT:
+ case PROP_TIME:
+ *((float *)&prop->data)+= (float)atof(str);
+ break;
+ case PROP_STRING:
+ /* strcpy(prop->poin, str); */
+ break;
+ }
+}
+
+/* reads value of property, sets it in chars in str */
+void set_property_valstr(bProperty *prop, char *str)
+{
+// extern int Gdfra; /* sector.c */
+
+ if(str == NULL) return;
+
+ switch(prop->type) {
+ case PROP_BOOL:
+ case PROP_INT:
+ sprintf(str, "%d", prop->data);
+ break;
+ case PROP_FLOAT:
+ case PROP_TIME:
+ sprintf(str, "%f", *((float *)&prop->data));
+ break;
+ case PROP_STRING:
+ BLI_strncpy(str, prop->poin, MAX_PROPSTRING);
+ break;
+ }
+}
+
+void cp_property(bProperty *prop1, bProperty *prop2)
+{
+ char str[128];
+
+ set_property_valstr(prop2, str);
+
+ set_property(prop1, str);
+}
diff --git a/source/blender/blenkernel/intern/sca.c b/source/blender/blenkernel/intern/sca.c
new file mode 100644
index 00000000000..a105b240942
--- /dev/null
+++ b/source/blender/blenkernel/intern/sca.c
@@ -0,0 +1,631 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * these all are linked to objects (listbase)
+ * all data is 'direct data', not Blender lib data.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "MEM_guardedalloc.h"
+
+#include "nla.h" /* For __NLA: Important, do not remove */
+#include "DNA_text_types.h"
+#include "DNA_controller_types.h"
+#include "DNA_sensor_types.h"
+#include "DNA_actuator_types.h"
+#include "DNA_object_types.h"
+
+#include "BLI_blenlib.h"
+#include "BKE_bad_level_calls.h"
+#include "BKE_utildefines.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_blender.h"
+#include "BKE_sca.h"
+
+void free_text_controllers(Text *txt)
+{
+ Object *ob;
+ bController *cont;
+
+ ob= G.main->object.first;
+ while(ob) {
+ cont= ob->controllers.first;
+ while(cont) {
+ if(cont->type==CONT_PYTHON) {
+ bPythonCont *pc;
+
+ pc= cont->data;
+ if(pc->text==txt) pc->text= NULL;
+ }
+ cont= cont->next;
+ }
+ ob= ob->id.next;
+ }
+}
+
+
+/* ******************* SENSORS ************************ */
+
+void free_sensor(bSensor *sens)
+{
+ if(sens->links) MEM_freeN(sens->links);
+ if(sens->data) MEM_freeN(sens->data);
+ MEM_freeN(sens);
+
+}
+
+void free_sensors(ListBase *lb)
+{
+ bSensor *sens;
+
+ while((sens= lb->first)) {
+ BLI_remlink(lb, sens);
+ free_sensor(sens);
+ }
+}
+
+bSensor *copy_sensor(bSensor *sens)
+{
+ bSensor *sensn;
+
+ sensn= MEM_dupallocN(sens);
+ sensn->flag |= SENS_NEW;
+ if(sens->data) {
+ sensn->data= MEM_dupallocN(sens->data);
+ }
+
+ if(sens->links) sensn->links= MEM_dupallocN(sens->links);
+
+ return sensn;
+}
+
+void copy_sensors(ListBase *lbn, ListBase *lbo)
+{
+ bSensor *sens, *sensn;
+
+ lbn->first= lbn->last= 0;
+ sens= lbo->first;
+ while(sens) {
+ sensn= copy_sensor(sens);
+ BLI_addtail(lbn, sensn);
+ sens= sens->next;
+ }
+}
+
+void init_sensor(bSensor *sens)
+{
+ /* also use when sensor changes type */
+ bNearSensor *ns;
+ bMouseSensor *ms;
+
+ if(sens->data) MEM_freeN(sens->data);
+ sens->data= NULL;
+ sens->pulse = 0;
+
+ switch(sens->type) {
+ case SENS_ALWAYS:
+ sens->pulse = 1;
+ break;
+ case SENS_TOUCH:
+ sens->data= MEM_callocN(sizeof(bTouchSensor), "touchsens");
+ break;
+ case SENS_NEAR:
+ ns=sens->data= MEM_callocN(sizeof(bNearSensor), "nearsens");
+ ns->dist= 1.0;
+ ns->resetdist= 2.0;
+ break;
+ case SENS_KEYBOARD:
+ sens->data= MEM_callocN(sizeof(bKeyboardSensor), "keysens");
+ break;
+ case SENS_PROPERTY:
+ sens->data= MEM_callocN(sizeof(bPropertySensor), "propsens");
+ break;
+ case SENS_MOUSE:
+ ms=sens->data= MEM_callocN(sizeof(bMouseSensor), "mousesens");
+ ms->type= LEFTMOUSE;
+ break;
+ case SENS_COLLISION:
+ sens->data= MEM_callocN(sizeof(bCollisionSensor), "colsens");
+ break;
+ case SENS_RADAR:
+ sens->data= MEM_callocN(sizeof(bRadarSensor), "radarsens");
+ break;
+ case SENS_RANDOM:
+ sens->data= MEM_callocN(sizeof(bRandomSensor), "randomsens");
+ break;
+ case SENS_RAY:
+ sens->data= MEM_callocN(sizeof(bRaySensor), "raysens");
+ break;
+ case SENS_MESSAGE:
+ sens->data= MEM_callocN(sizeof(bMessageSensor), "messagesens");
+ break;
+ default:
+ ; /* this is very severe... I cannot make any memory for this */
+ /* logic brick... */
+ }
+}
+
+bSensor *new_sensor(int type)
+{
+ bSensor *sens;
+
+ sens= MEM_callocN(sizeof(bSensor), "Sensor");
+ sens->type= type;
+ sens->flag= SENS_SHOW;
+
+ init_sensor(sens);
+
+ strcpy(sens->name, "sensor");
+ make_unique_prop_names(sens->name);
+
+ return sens;
+}
+
+/* ******************* CONTROLLERS ************************ */
+
+void unlink_controller(bController *cont)
+{
+ bSensor *sens;
+ Object *ob;
+ int a, removed;
+
+ /* check for controller pointers in sensors */
+ ob= G.main->object.first;
+ while(ob) {
+ sens= ob->sensors.first;
+ while(sens) {
+ removed= 0;
+ for(a=0; a<sens->totlinks; a++) {
+ if(removed) (sens->links)[a-1] = (sens->links)[a];
+ else if((sens->links)[a] == cont) removed= 1;
+ }
+ if(removed) {
+ sens->totlinks--;
+
+ if(sens->totlinks==0) {
+ MEM_freeN(sens->links);
+ sens->links= NULL;
+ }
+ }
+ sens= sens->next;
+ }
+ ob= ob->id.next;
+ }
+}
+
+void unlink_controllers(ListBase *lb)
+{
+ bController *cont;
+
+ for (cont= lb->first; cont; cont= cont->next)
+ unlink_controller(cont);
+}
+
+void free_controller(bController *cont)
+{
+ if(cont->links) MEM_freeN(cont->links);
+
+ /* the controller itself */
+ if(cont->data) MEM_freeN(cont->data);
+ MEM_freeN(cont);
+
+}
+
+void free_controllers(ListBase *lb)
+{
+ bController *cont;
+
+ while((cont= lb->first)) {
+ BLI_remlink(lb, cont);
+ if(cont->slinks) MEM_freeN(cont->slinks);
+ free_controller(cont);
+ }
+}
+
+bController *copy_controller(bController *cont)
+{
+ bController *contn;
+
+ cont->mynew=contn= MEM_dupallocN(cont);
+ contn->flag |= CONT_NEW;
+ if(cont->data) {
+ contn->data= MEM_dupallocN(cont->data);
+ }
+
+ if(cont->links) contn->links= MEM_dupallocN(cont->links);
+ contn->slinks= NULL;
+ contn->totslinks= 0;
+
+ return contn;
+}
+
+void copy_controllers(ListBase *lbn, ListBase *lbo)
+{
+ bController *cont, *contn;
+
+ lbn->first= lbn->last= 0;
+ cont= lbo->first;
+ while(cont) {
+ contn= copy_controller(cont);
+ BLI_addtail(lbn, contn);
+ cont= cont->next;
+ }
+}
+
+void init_controller(bController *cont)
+{
+ /* also use when controller changes type, leave actuators... */
+
+ if(cont->data) MEM_freeN(cont->data);
+ cont->data= 0;
+
+ switch(cont->type) {
+ case CONT_EXPRESSION:
+ cont->data= MEM_callocN(sizeof(bExpressionCont), "expcont");
+ break;
+ case CONT_PYTHON:
+ cont->data= MEM_callocN(sizeof(bPythonCont), "pycont");
+ break;
+ }
+}
+
+bController *new_controller(int type)
+{
+ bController *cont;
+
+ cont= MEM_callocN(sizeof(bController), "Controller");
+ cont->type= type;
+ cont->flag= CONT_SHOW;
+
+ init_controller(cont);
+
+ strcpy(cont->name, "cont");
+ make_unique_prop_names(cont->name);
+
+ return cont;
+}
+
+/* ******************* ACTUATORS ************************ */
+
+void unlink_actuator(bActuator *act)
+{
+ bController *cont;
+ Object *ob;
+ int a, removed;
+
+ /* check for actuator pointers in controllers */
+ ob= G.main->object.first;
+ while(ob) {
+ cont= ob->controllers.first;
+ while(cont) {
+ removed= 0;
+ for(a=0; a<cont->totlinks; a++) {
+ if(removed) (cont->links)[a-1] = (cont->links)[a];
+ else if((cont->links)[a] == act) removed= 1;
+ }
+ if(removed) {
+ cont->totlinks--;
+
+ if(cont->totlinks==0) {
+ MEM_freeN(cont->links);
+ cont->links= NULL;
+ }
+ }
+ cont= cont->next;
+ }
+ ob= ob->id.next;
+ }
+}
+
+void unlink_actuators(ListBase *lb)
+{
+ bActuator *act;
+
+ for (act= lb->first; act; act= act->next)
+ unlink_actuator(act);
+}
+
+void free_actuator(bActuator *act)
+{
+ if(act->data) MEM_freeN(act->data);
+ MEM_freeN(act);
+}
+
+void free_actuators(ListBase *lb)
+{
+ bActuator *act;
+
+ while((act= lb->first)) {
+ BLI_remlink(lb, act);
+ free_actuator(act);
+ }
+}
+
+bActuator *copy_actuator(bActuator *act)
+{
+ bActuator *actn;
+
+ act->mynew=actn= MEM_dupallocN(act);
+ actn->flag |= ACT_NEW;
+ if(act->data) {
+ actn->data= MEM_dupallocN(act->data);
+ }
+
+ return actn;
+}
+
+void copy_actuators(ListBase *lbn, ListBase *lbo)
+{
+ bActuator *act, *actn;
+
+ lbn->first= lbn->last= 0;
+ act= lbo->first;
+ while(act) {
+ actn= copy_actuator(act);
+ BLI_addtail(lbn, actn);
+ act= act->next;
+ }
+}
+
+void init_actuator(bActuator *act)
+{
+ /* also use when actuator changes type */
+ bObjectActuator *oa;
+
+ if(act->data) MEM_freeN(act->data);
+ act->data= 0;
+
+ switch(act->type) {
+#ifdef __NLA
+ case ACT_ACTION:
+ act->data= MEM_callocN(sizeof(bActionActuator), "actionact");
+ break;
+#endif
+ case ACT_SOUND:
+ act->data= MEM_callocN(sizeof(bSoundActuator), "soundact");
+ break;
+ case ACT_CD:
+ act->data= MEM_callocN(sizeof(bCDActuator), "cdact");
+ break;
+ case ACT_OBJECT:
+ act->data= MEM_callocN(sizeof(bObjectActuator), "objectact");
+ oa= act->data;
+ oa->flag= 15;
+ break;
+ case ACT_IPO:
+ act->data= MEM_callocN(sizeof(bIpoActuator), "ipoact");
+ break;
+ case ACT_PROPERTY:
+ act->data= MEM_callocN(sizeof(bPropertyActuator), "propact");
+ break;
+ case ACT_CAMERA:
+ act->data= MEM_callocN(sizeof(bCameraActuator), "camact");
+ break;
+ case ACT_EDIT_OBJECT:
+ act->data= MEM_callocN(sizeof(bEditObjectActuator), "editobact");
+ break;
+ case ACT_CONSTRAINT:
+ act->data= MEM_callocN(sizeof(bConstraintActuator), "cons act");
+ break;
+ case ACT_SCENE:
+ act->data= MEM_callocN(sizeof(bSceneActuator), "scene act");
+ break;
+ case ACT_GROUP:
+ act->data= MEM_callocN(sizeof(bGroupActuator), "group act");
+ break;
+ case ACT_RANDOM:
+ act->data= MEM_callocN(sizeof(bRandomActuator), "random act");
+ break;
+ case ACT_MESSAGE:
+ act->data= MEM_callocN(sizeof(bMessageActuator), "message act");
+ break;
+ case ACT_GAME:
+ act->data= MEM_callocN(sizeof(bGameActuator), "game act");
+ break;
+ case ACT_VISIBILITY:
+ act->data= MEM_callocN(sizeof(bVisibilityActuator), "visibility act");
+ break;
+ default:
+ ; /* this is very severe... I cannot make any memory for this */
+ /* logic brick... */
+ }
+}
+
+bActuator *new_actuator(int type)
+{
+ bActuator *act;
+
+ act= MEM_callocN(sizeof(bActuator), "Actuator");
+ act->type= type;
+ act->flag= ACT_SHOW;
+
+ init_actuator(act);
+
+ strcpy(act->name, "act");
+ make_unique_prop_names(act->name);
+
+ return act;
+}
+
+/* ******************** GENERAL ******************* */
+
+void clear_sca_new_poins_ob(Object *ob)
+{
+ bSensor *sens;
+ bController *cont;
+ bActuator *act;
+
+ sens= ob->sensors.first;
+ while(sens) {
+ sens->flag &= ~SENS_NEW;
+ sens= sens->next;
+ }
+ cont= ob->controllers.first;
+ while(cont) {
+ cont->mynew= NULL;
+ cont->flag &= ~CONT_NEW;
+ cont= cont->next;
+ }
+ act= ob->actuators.first;
+ while(act) {
+ act->mynew= NULL;
+ act->flag &= ~ACT_NEW;
+ act= act->next;
+ }
+}
+
+void clear_sca_new_poins()
+{
+ Object *ob;
+
+ ob= G.main->object.first;
+ while(ob) {
+ clear_sca_new_poins_ob(ob);
+ ob= ob->id.next;
+ }
+}
+
+void set_sca_new_poins_ob(Object *ob)
+{
+ bSensor *sens;
+ bController *cont;
+ bActuator *act;
+ int a;
+
+ sens= ob->sensors.first;
+ while(sens) {
+ if(sens->flag & SENS_NEW) {
+ for(a=0; a<sens->totlinks; a++) {
+ if(sens->links[a] && sens->links[a]->mynew)
+ sens->links[a]= sens->links[a]->mynew;
+ }
+ }
+ sens= sens->next;
+ }
+
+ cont= ob->controllers.first;
+ while(cont) {
+ if(cont->flag & CONT_NEW) {
+ for(a=0; a<cont->totlinks; a++) {
+ if( cont->links[a] && cont->links[a]->mynew)
+ cont->links[a]= cont->links[a]->mynew;
+ }
+ }
+ cont= cont->next;
+ }
+
+
+ act= ob->actuators.first;
+ while(act) {
+ if(act->flag & ACT_NEW) {
+ if(act->type==ACT_EDIT_OBJECT) {
+ bEditObjectActuator *eoa= act->data;
+ ID_NEW(eoa->ob);
+ }
+ else if(act->type==ACT_SCENE) {
+ bSceneActuator *sca= act->data;
+ ID_NEW(sca->camera);
+ }
+ else if(act->type==ACT_CAMERA) {
+ bCameraActuator *ca= act->data;
+ ID_NEW(ca->ob);
+ }
+ else if(act->type==ACT_SCENE) {
+ bSceneActuator *sca= act->data;
+ ID_NEW(sca->camera);
+ }
+ }
+ act= act->next;
+ }
+}
+
+
+void set_sca_new_poins()
+{
+ Object *ob;
+
+ ob= G.main->object.first;
+ while(ob) {
+ set_sca_new_poins_ob(ob);
+ ob= ob->id.next;
+ }
+}
+
+void sca_remove_ob_poin(Object *obt, Object *ob)
+{
+ bSensor *sens;
+ bMessageSensor *ms;
+ bActuator *act;
+ bCameraActuator *ca;
+ bSceneActuator *sa;
+ bEditObjectActuator *eoa;
+ bPropertyActuator *pa;
+ bMessageActuator *ma;
+
+ sens= obt->sensors.first;
+ while(sens) {
+ switch(sens->type) {
+ case SENS_MESSAGE:
+ ms= sens->data;
+ if(ms->fromObject==ob) ms->fromObject= NULL;
+ }
+ sens= sens->next;
+ }
+
+ act= obt->actuators.first;
+ while(act) {
+ switch(act->type) {
+ case ACT_CAMERA:
+ ca= act->data;
+ if(ca->ob==ob) ca->ob= NULL;
+ break;
+ case ACT_PROPERTY:
+ pa= act->data;
+ if(pa->ob==ob) pa->ob= NULL;
+ break;
+ case ACT_SCENE:
+ sa= act->data;
+ if(sa->camera==ob) sa->camera= NULL;
+ break;
+ case ACT_EDIT_OBJECT:
+ eoa= act->data;
+ if(eoa->ob==ob) eoa->ob= NULL;
+ break;
+ case ACT_MESSAGE:
+ ma= act->data;
+ if(ma->toObject==ob) ma->toObject= NULL;
+ break;
+
+ }
+ act= act->next;
+ }
+}
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
new file mode 100644
index 00000000000..d1da1d4d1b6
--- /dev/null
+++ b/source/blender/blenkernel/intern/scene.c
@@ -0,0 +1,536 @@
+
+/* scene.c MIXED MODEL
+ *
+ * jan 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 <stdio.h>
+
+#ifndef WIN32
+#include <unistd.h>
+#else
+#include "BLI_winstuff.h"
+#include <io.h>
+#endif
+#include "MEM_guardedalloc.h"
+
+#include "nla.h" /* for __NLA : IMPORTANT Do not delete me yet! */
+#ifdef __NLA /* for __NLA : IMPORTANT Do not delete me yet! */
+#include "DNA_armature_types.h" /* for __NLA : IMPORTANT Do not delete me yet! */
+#include "BKE_armature.h" /* for __NLA : IMPORTANT Do not delete me yet! */
+#include "BKE_action.h" /* for __NLA : IMPORTANT Do not delete me yet! */
+#endif /* for __NLA : IMPORTANT Do not delete me yet! */
+
+#include "DNA_constraint_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scriptlink_types.h"
+#include "DNA_meta_types.h"
+#include "DNA_ika_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_material_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_group_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_userdef_types.h"
+
+#include "BLI_blenlib.h"
+
+#include "BKE_bad_level_calls.h"
+#include "BKE_utildefines.h"
+
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_anim.h"
+
+#include "BKE_library.h"
+
+#include "BPY_extern.h"
+#include "BKE_scene.h"
+#include "BKE_world.h"
+#include "BKE_ipo.h"
+#include "BKE_ika.h"
+#include "BKE_key.h"
+
+void free_avicodecdata(AviCodecData *acd)
+{
+ if (acd) {
+ if (acd->lpFormat){
+ MEM_freeN(acd->lpFormat);
+ acd->lpFormat = NULL;
+ acd->cbFormat = 0;
+ }
+ if (acd->lpParms){
+ MEM_freeN(acd->lpParms);
+ acd->lpParms = NULL;
+ acd->cbParms = 0;
+ }
+ }
+}
+
+/* niet scene zelf vrijgeven */
+void free_scene(Scene *sce)
+{
+ Base *base;
+
+ base= sce->base.first;
+ while(base) {
+ base->object->id.us--;
+ base= base->next;
+ }
+ /* pas op: niet objects vrijgeven! */
+
+ BLI_freelistN(&sce->base);
+ free_editing(sce->ed);
+ if(sce->radio) MEM_freeN(sce->radio);
+ if(sce->fcam) MEM_freeN(sce->fcam);
+ sce->radio= 0;
+
+ BPY_free_scriptlink(&sce->scriptlink);
+ if (sce->r.avicodecdata) {
+ free_avicodecdata(sce->r.avicodecdata);
+ MEM_freeN(sce->r.avicodecdata);
+ sce->r.avicodecdata = NULL;
+ }
+}
+
+Scene *add_scene(char *name)
+{
+ Scene *sce;
+
+ sce= alloc_libblock(&G.main->scene, ID_SCE, name);
+ sce->lay= 1;
+
+ sce->r.mode= R_GAMMA;
+ sce->r.cfra= 1;
+ sce->r.sfra= 1;
+ sce->r.efra= 250;
+ sce->r.xsch= 320;
+ sce->r.ysch= 256;
+ sce->r.xasp= 1;
+ sce->r.yasp= 1;
+ sce->r.xparts= 1;
+ sce->r.yparts= 1;
+ sce->r.size= 100;
+ sce->r.planes= 24;
+ sce->r.quality= 90;
+ sce->r.framapto= 100;
+ sce->r.images= 100;
+ sce->r.framelen= 1.0;
+ sce->r.frs_sec= 25;
+
+ sce->r.xplay= 640;
+ sce->r.yplay= 480;
+ sce->r.freqplay= 60;
+ sce->r.depth= 32;
+
+ sce->r.stereomode = 1; // no stereo
+
+ strcpy(sce->r.backbuf, "//backbuf");
+ strcpy(sce->r.pic, U.renderdir);
+ strcpy(sce->r.ftype, "//ftype");
+
+ BLI_init_rctf(&sce->r.safety, 0.1f, 0.9f, 0.1f, 0.9f);
+ sce->r.osa= 8;
+
+ return sce;
+}
+
+int object_in_scene(Object *ob, Scene *sce)
+{
+ Base *base;
+
+ base= sce->base.first;
+ while(base) {
+ if(base->object == ob) return 1;
+ base= base->next;
+ }
+ return 0;
+}
+
+void sort_baselist(Scene *sce)
+{
+ /* alles in volgorde van parent en track */
+ ListBase tempbase, noparentbase, notyetbase;
+ Base *base, *test=NULL;
+ Object *par;
+ int doit, domore= 0, lastdomore=1;
+
+
+ /* volgorde gelijk houden als er niets veranderd is! */
+ /* hier waren problemen met campos array's: volgorde camera's is van belang */
+
+ while(domore!=lastdomore) {
+
+ lastdomore= domore;
+ domore= 0;
+ tempbase.first= tempbase.last= 0;
+ noparentbase.first= noparentbase.last= 0;
+ notyetbase.first= notyetbase.last= 0;
+
+ while( (base= sce->base.first) ) {
+ BLI_remlink(&sce->base, base);
+
+ par= 0;
+ if(base->object->type==OB_IKA) {
+ Ika *ika= base->object->data;
+ par= ika->parent;
+ }
+
+ if(par || base->object->parent || base->object->track) {
+
+ doit= 0;
+ if(base->object->parent) doit++;
+ if(base->object->track) doit++;
+
+ /* Count constraints */
+ {
+ bConstraint *con;
+ for (con = base->object->constraints.first; con; con=con->next){
+ switch (con->type){
+ case CONSTRAINT_TYPE_KINEMATIC:
+ {
+ bKinematicConstraint *data=con->data;
+ if (data->tar) doit++;
+ }
+ break;
+ case CONSTRAINT_TYPE_TRACKTO:
+ {
+ bTrackToConstraint *data=con->data;
+ if (data->tar) doit++;
+ }
+ break;
+ case CONSTRAINT_TYPE_NULL:
+ break;
+ case CONSTRAINT_TYPE_ROTLIKE:
+ {
+ bRotateLikeConstraint *data=con->data;
+ if (data->tar) doit++;
+
+ }
+ break;
+ case CONSTRAINT_TYPE_LOCLIKE:
+ {
+ bLocateLikeConstraint *data=con->data;
+ if (data->tar) doit++;
+ }
+ break;
+ case CONSTRAINT_TYPE_ACTION:
+ {
+ bActionConstraint *data=con->data;
+ if (data->tar) doit++;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ if(par) doit++;
+
+ test= tempbase.first;
+ while(test) {
+
+ if(test->object==base->object->parent) doit--;
+ if(test->object==base->object->track) doit--;
+ if(test->object==par) doit--;
+
+ /* Decrement constraints */
+ {
+ bConstraint *con;
+ for (con = base->object->constraints.first; con; con=con->next){
+ switch (con->type){
+ case CONSTRAINT_TYPE_KINEMATIC:
+ {
+ bKinematicConstraint *data=con->data;
+ if (test->object == data->tar && test->object!=base->object) doit--;
+ }
+ break;
+ case CONSTRAINT_TYPE_TRACKTO:
+ {
+ bTrackToConstraint *data=con->data;
+ if (test->object == data->tar && test->object!=base->object) doit--;
+ }
+ break;
+ case CONSTRAINT_TYPE_NULL:
+ break;
+ case CONSTRAINT_TYPE_ROTLIKE:
+ {
+ bRotateLikeConstraint *data=con->data;
+ if (test->object == data->tar && test->object!=base->object) doit--;
+
+ }
+ break;
+ case CONSTRAINT_TYPE_LOCLIKE:
+ {
+ bLocateLikeConstraint *data=con->data;
+ if (test->object == data->tar && test->object!=base->object) doit--;
+ }
+ break;
+ case CONSTRAINT_TYPE_ACTION:
+ {
+ bActionConstraint *data=con->data;
+ if (test->object == data->tar && test->object!=base->object) doit--;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ if(doit==0) break;
+ test= test->next;
+ }
+
+ if(test) BLI_insertlink(&tempbase, test, base);
+ else {
+ BLI_addhead(&tempbase, base);
+ domore++;
+ }
+
+ }
+ else BLI_addtail(&noparentbase, base);
+
+ }
+ sce->base= noparentbase;
+ addlisttolist(&sce->base, &tempbase);
+ addlisttolist(&sce->base, &notyetbase);
+
+ }
+}
+
+
+void set_scene_bg(Scene *sce)
+{
+ Base *base;
+ Object *ob;
+ Group *group;
+ GroupObject *go;
+ int flag;
+
+ G.scene= sce;
+
+ /* objecten deselecteren (voor dataselect) */
+ ob= G.main->object.first;
+ while(ob) {
+ ob->flag &= ~(SELECT|OB_FROMGROUP);
+ ob= ob->id.next;
+ }
+
+ /* group flags again */
+ group= G.main->group.first;
+ while(group) {
+ go= group->gobject.first;
+ while(go) {
+ if(go->ob) go->ob->flag |= OB_FROMGROUP;
+ go= go->next;
+ }
+ group= group->id.next;
+ }
+
+ /* baselijst sorteren */
+ sort_baselist(sce);
+
+ /* layers en flags uit bases naar objecten kopieeren */
+ base= G.scene->base.first;
+ while(base) {
+
+ base->object->lay= base->lay;
+
+ base->flag &= ~OB_FROMGROUP;
+ flag= base->object->flag & OB_FROMGROUP;
+ base->flag |= flag;
+
+ base->object->ctime= -1234567.0; /* forceer ipo */
+ base= base->next;
+ }
+
+ do_all_ipos(); /* layers/materials */
+
+ BPY_do_all_scripts(SCRIPT_FRAMECHANGED);
+ do_all_keys();
+#ifdef __NLA
+ do_all_actions();
+#endif
+ do_all_ikas();
+
+
+}
+
+void set_scene_name(char *name)
+{
+ Scene *sce;
+
+ for (sce= G.main->scene.first; sce; sce= sce->id.next) {
+ if (BLI_streq(name, sce->id.name+2)) {
+ set_scene_bg(sce);
+ return;
+ }
+ }
+
+ error("Can't find scene: %s", name);
+}
+
+/* used by metaballs
+ * doesnt return the original duplicated object, only dupli's
+ */
+int next_object(int val, Base **base, Object **ob)
+{
+ extern ListBase duplilist;
+ static Object *dupob;
+ static int fase;
+ int run_again=1;
+
+ /* init */
+ if(val==0) {
+ fase= F_START;
+ dupob= 0;
+ }
+ else {
+
+ /* run_again is set when a duplilist has been ended */
+ while(run_again) {
+ run_again= 0;
+
+
+
+ /* de eerste base */
+ if(fase==F_START) {
+ *base= G.scene->base.first;
+ if(*base) {
+ *ob= (*base)->object;
+ fase= F_SCENE;
+ }
+ else {
+ /* uitzondering: een lege scene */
+ if(G.scene->set && G.scene->set->base.first) {
+ *base= G.scene->set->base.first;
+ *ob= (*base)->object;
+ fase= F_SET;
+ }
+ }
+ }
+ else {
+ if(*base && fase!=F_DUPLI) {
+ *base= (*base)->next;
+ if(*base) *ob= (*base)->object;
+ else {
+ if(fase==F_SCENE) {
+ /* de scene is klaar, we gaan door met de set */
+ if(G.scene->set && G.scene->set->base.first) {
+ *base= G.scene->set->base.first;
+ *ob= (*base)->object;
+ fase= F_SET;
+ }
+ }
+ }
+ }
+ }
+
+ if(*base == 0) fase= F_START;
+ else {
+ if(fase!=F_DUPLI) {
+ if( (*base)->object->transflag & OB_DUPLI) {
+
+ make_duplilist(G.scene, (*base)->object);
+ dupob= duplilist.first;
+
+ }
+ }
+ /* dupli's afhandelen */
+ if(dupob) {
+
+ *ob= dupob;
+ fase= F_DUPLI;
+
+ dupob= dupob->id.next;
+ }
+ else if(fase==F_DUPLI) {
+ fase= F_SCENE;
+ free_duplilist();
+ run_again= 1;
+ }
+
+ }
+ }
+ }
+
+ return fase;
+}
+
+Object *scene_find_camera(Scene *sc)
+{
+ Base *base;
+
+ for (base= sc->base.first; base; base= base->next)
+ if (base->object->type==OB_CAMERA)
+ return base->object;
+
+ return NULL;
+}
+
+
+Base *scene_add_base(Scene *sce, Object *ob)
+{
+ Base *b= MEM_callocN(sizeof(*b), "scene_add_base");
+ BLI_addhead(&sce->base, b);
+
+ b->object= ob;
+ b->flag= ob->flag;
+ b->lay= ob->lay;
+
+ return b;
+}
+
+void scene_deselect_all(Scene *sce)
+{
+ Base *b;
+
+ for (b= sce->base.first; b; b= b->next) {
+ b->flag&= ~SELECT;
+ b->object->flag= b->flag;
+ }
+}
+
+void scene_select_base(Scene *sce, Base *selbase)
+{
+ scene_deselect_all(sce);
+
+ selbase->flag |= SELECT;
+ selbase->object->flag= selbase->flag;
+
+ sce->basact= selbase;
+}
diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c
new file mode 100644
index 00000000000..1f04c20cc72
--- /dev/null
+++ b/source/blender/blenkernel/intern/screen.c
@@ -0,0 +1,53 @@
+
+/* screen.c dec/jan 93/94 GRAPHICS
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 <string.h>
+#include <stdio.h>
+#include <math.h>
+
+#include "DNA_screen_types.h"
+
+#include "BKE_bad_level_calls.h"
+
+#include "BLI_blenlib.h"
+
+/* don't free screen itself */
+void free_screen(bScreen *sc)
+{
+ unlink_screen(sc);
+
+ BLI_freelistN(&sc->vertbase);
+ BLI_freelistN(&sc->edgebase);
+ BLI_freelistN(&sc->areabase);
+}
diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c
new file mode 100644
index 00000000000..6f8c46bb877
--- /dev/null
+++ b/source/blender/blenkernel/intern/sound.c
@@ -0,0 +1,112 @@
+/**
+ * sound.c (mar-2001 nzc)
+ *
+ * $Id$
+ */
+
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+
+#include "DNA_scene_types.h"
+#include "DNA_sound_types.h"
+#include "DNA_packedFile_types.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_sound.h"
+#include "BKE_packedFile.h"
+
+ListBase _samples = {0,0}, *samples = &_samples;
+
+void sound_free_sound(bSound *sound)
+{
+ /* this crashes blender, PLEASE fix! */
+ // still crashes :(
+ //if (sound) {
+ // sound_set_sample(sound, NULL);
+ //}
+
+}
+
+void sound_free_sample(bSample *sample)
+{
+ if (sample) {
+ if (sample->data != &sample->fakedata[0] && sample->data != NULL) {
+ MEM_freeN(sample->data);
+ sample->data = &sample->fakedata[0];
+ }
+
+ if (sample->packedfile) {
+ freePackedFile(sample->packedfile); //FIXME: crashes sometimes
+ sample->packedfile = NULL;
+ }
+
+ if (sample->alindex != SAMPLE_INVALID) {
+// AUD_free_sample(sample->snd_sample);
+ sample->alindex = SAMPLE_INVALID;
+ }
+
+ sample->type = SAMPLE_INVALID;
+ }
+}
+
+
+
+void sound_set_packedfile(bSample *sample, PackedFile *pf)
+{
+ bSound *sound;
+
+ if (sample) {
+ sample->packedfile = pf;
+ sound = G.main->sound.first;
+ while (sound) {
+ if (sound->sample == sample) {
+ sound->newpackedfile = pf;
+ if (pf == NULL) {
+ strcpy(sound->name, sample->name);
+ }
+ }
+ sound = sound->id.next;
+ }
+ }
+}
+
+PackedFile* sound_find_packedfile(bSound *sound)
+{
+ bSound *search;
+ PackedFile *pf = NULL;
+ char soundname[FILE_MAXDIR + FILE_MAXFILE], searchname[FILE_MAXDIR + FILE_MAXFILE];
+
+ // convert sound->name to abolute filename
+ strcpy(soundname, sound->name);
+ BLI_convertstringcode(soundname, G.sce, G.scene->r.cfra);
+
+ search = G.main->sound.first;
+ while (search) {
+ if (search->sample && search->sample->packedfile) {
+ strcpy(searchname, search->sample->name);
+ BLI_convertstringcode(searchname, G.sce, G.scene->r.cfra);
+
+ if (BLI_streq(searchname, soundname)) {
+ pf = search->sample->packedfile;
+ break;
+ }
+ }
+
+ if (search->newpackedfile) {
+ strcpy(searchname, search->name);
+ BLI_convertstringcode(searchname, G.sce, G.scene->r.cfra);
+ if (BLI_streq(searchname, soundname)) {
+ pf = search->newpackedfile;
+ break;
+ }
+ }
+ search = search->id.next;
+ }
+
+ return (pf);
+}
diff --git a/source/blender/blenkernel/intern/subsurf.c b/source/blender/blenkernel/intern/subsurf.c
new file mode 100644
index 00000000000..3f747fb684f
--- /dev/null
+++ b/source/blender/blenkernel/intern/subsurf.c
@@ -0,0 +1,890 @@
+
+/* subsurf.c MIXED MODEL
+ *
+ * jun 2001
+ *
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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
+#include "BLI_winstuff.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include "MEM_guardedalloc.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+
+#include "BKE_bad_level_calls.h"
+#include "BKE_global.h"
+#include "BKE_mesh.h"
+#include "BKE_subsurf.h"
+#include "BKE_displist.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_editVert.h"
+#include "BLI_arithb.h"
+#include "BLI_linklist.h"
+#include "BLI_memarena.h"
+
+/*
+ * TODO
+ *
+ * make uvco's && vcol's properly subdivided
+ * - requires moving uvco and vcol data to vertices
+ * (where it belongs?), or making sharedness explicit
+ * remove/integrate zsl functions
+ * clean up uvco && vcol stuff
+ * add option to update subsurf only after done transverting
+ * decouple display subdivlevel and render subdivlevel
+ * look into waves/particles with subsurfs
+ * groan... make it work with sticky?
+ * U check if storing tfaces (clut, tpage) in a displist is
+ * going to be a mem problem (for example, on duplicate)
+ * U write game blender convert routine
+ * U thorough rendering check + background
+ *
+ */
+
+/****/
+
+static float *Vec2Cpy(float *t, float *a) {
+ t[0]= a[0];
+ t[1]= a[1];
+ return t;
+}
+static float *Vec3Cpy(float *t, float *a) {
+ t[0]= a[0];
+ t[1]= a[1];
+ t[2]= a[2];
+ return t;
+}
+
+static float *Vec2CpyI(float *t, float x, float y) {
+ t[0]= x;
+ t[1]= y;
+ return t;
+}
+static float *Vec3CpyI(float *t, float x, float y, float z) {
+ t[0]= x;
+ t[1]= y;
+ t[2]= z;
+ return t;
+}
+
+static float *Vec2AvgT(float *t, float *a, float *b) {
+ t[0]= (a[0]+b[0])*0.5f;
+ t[1]= (a[1]+b[1])*0.5f;
+ return t;
+}
+static float *Vec3AvgT(float *t, float *a, float *b) {
+ t[0]= (a[0]+b[0])*0.5f;
+ t[1]= (a[1]+b[1])*0.5f;
+ t[2]= (a[2]+b[2])*0.5f;
+ return t;
+}
+
+static float *Vec3AddT(float *t, float *a, float *b) {
+ t[0]= a[0]+b[0];
+ t[1]= a[1]+b[1];
+ t[2]= a[2]+b[2];
+ return t;
+}
+static float *Vec2Add(float *ta, float *b) {
+ ta[0]+= b[0];
+ ta[1]+= b[1];
+ ta[2]+= b[2];
+ return ta;
+}
+
+static float *Vec3MulNT(float *t, float *a, float n) {
+ t[0]= a[0]*n;
+ t[1]= a[1]*n;
+ t[2]= a[2]*n;
+ return t;
+}
+
+static float *Vec3Add(float *ta, float *b) {
+ ta[0]+= b[0];
+ ta[1]+= b[1];
+ ta[2]+= b[2];
+ return ta;
+}
+
+static float *Vec3MulN(float *ta, float n) {
+ ta[0]*= n;
+ ta[1]*= n;
+ ta[2]*= n;
+ return ta;
+}
+
+/****/
+
+typedef struct _HyperVert HyperVert;
+typedef struct _HyperEdge HyperEdge;
+typedef struct _HyperFace HyperFace;
+typedef struct _HyperMesh HyperMesh;
+
+struct _HyperVert {
+ HyperVert *next;
+
+ float co[3];
+
+ HyperVert *nmv;
+ LinkNode *edges, *faces;
+};
+
+struct _HyperEdge {
+ HyperEdge *next;
+
+ HyperVert *v[2];
+ HyperVert *ep;
+
+ LinkNode *faces;
+};
+
+struct _HyperFace {
+ HyperFace *next;
+
+ int nverts;
+ HyperVert **verts;
+ HyperEdge **edges;
+
+ HyperVert *mid;
+
+ unsigned char (*vcol)[4];
+ float (*uvco)[2];
+
+ /* for getting back tface, matnr, etc */
+ union {
+ int ind;
+ EditVlak *ef;
+ } orig;
+};
+
+struct _HyperMesh {
+ HyperVert *verts;
+ HyperEdge *edges;
+ HyperFace *faces;
+ Mesh *orig_me;
+ short hasuvco, hasvcol;
+
+ MemArena *arena;
+};
+
+/***/
+
+static HyperEdge *hypervert_find_edge(HyperVert *v, HyperVert *to) {
+ LinkNode *l;
+
+ for (l= v->edges; l; l= l->next) {
+ HyperEdge *e= l->link;
+
+ if ((e->v[0]==v&&e->v[1]==to) || (e->v[1]==v&&e->v[0]==to))
+ return e;
+ }
+
+ return NULL;
+}
+
+static int hyperedge_is_boundary(HyperEdge *e) {
+ /* len(e->faces) <= 1 */
+ return (!e->faces || !e->faces->next);
+}
+
+static int hypervert_is_boundary(HyperVert *v) {
+ LinkNode *l;
+
+ for (l= v->edges; l; l= l->next)
+ if (hyperedge_is_boundary(l->link))
+ return 1;
+
+ return 0;
+}
+
+static HyperVert *hyperedge_other_vert(HyperEdge *e, HyperVert *a) {
+ return (a==e->v[0])?e->v[1]:e->v[0];
+}
+
+static HyperVert *hypermesh_add_vert(HyperMesh *hme, float *co) {
+ HyperVert *hv= BLI_memarena_alloc(hme->arena, sizeof(*hv));
+
+ hv->nmv= NULL;
+ hv->edges= NULL;
+ hv->faces= NULL;
+
+ Vec3Cpy(hv->co, co);
+
+ hv->next= hme->verts;
+ hme->verts= hv;
+
+ return hv;
+}
+
+static HyperEdge *hypermesh_add_edge(HyperMesh *hme, HyperVert *v1, HyperVert *v2) {
+ HyperEdge *he= BLI_memarena_alloc(hme->arena, sizeof(*he));
+
+ BLI_linklist_prepend_arena(&v1->edges, he, hme->arena);
+ BLI_linklist_prepend_arena(&v2->edges, he, hme->arena);
+
+ he->v[0]= v1;
+ he->v[1]= v2;
+ he->ep= NULL;
+ he->faces= NULL;
+
+ he->next= hme->edges;
+ hme->edges= he;
+
+ return he;
+}
+
+static HyperFace *hypermesh_add_face(HyperMesh *hme, HyperVert **verts, int nverts) {
+ HyperFace *f= BLI_memarena_alloc(hme->arena, sizeof(*f));
+ HyperVert *last;
+ int j;
+
+ f->mid= NULL;
+ f->vcol= NULL;
+ f->uvco= NULL;
+
+ f->nverts= nverts;
+ f->verts= BLI_memarena_alloc(hme->arena, sizeof(*f->verts)*f->nverts);
+ f->edges= BLI_memarena_alloc(hme->arena, sizeof(*f->edges)*f->nverts);
+
+ last= verts[nverts-1];
+ for (j=0; j<nverts; j++) {
+ HyperVert *v= verts[j];
+ HyperEdge *e= hypervert_find_edge(v, last);
+
+ if (!e)
+ e= hypermesh_add_edge(hme, v, last);
+
+ f->verts[j]= v;
+ f->edges[j]= e;
+
+ BLI_linklist_prepend_arena(&v->faces, f, hme->arena);
+ BLI_linklist_prepend_arena(&e->faces, f, hme->arena);
+
+ last= v;
+ }
+
+ f->next= hme->faces;
+ hme->faces= f;
+
+ return f;
+}
+
+static HyperMesh *hypermesh_new(void) {
+ HyperMesh *hme= MEM_mallocN(sizeof(*hme), "hme");
+
+ hme->verts= NULL;
+ hme->edges= NULL;
+ hme->faces= NULL;
+ hme->orig_me= NULL;
+ hme->hasuvco= hme->hasvcol= 0;
+ hme->arena= BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE);
+
+ return hme;
+}
+
+static HyperMesh *hypermesh_from_mesh(Mesh *me, DispList *dlverts) {
+ HyperMesh *hme= hypermesh_new();
+ HyperVert **vert_tbl;
+ MFace *mface= me->mface;
+ int i, j;
+
+ hme->orig_me= me;
+ if (me->tface)
+ hme->hasvcol= hme->hasuvco= 1;
+ else if (me->mcol)
+ hme->hasvcol= 1;
+
+ vert_tbl= MEM_mallocN(sizeof(*vert_tbl)*me->totvert, "vert_tbl");
+
+ for (i= 0; i<me->totvert; i++) {
+ if (dlverts)
+ vert_tbl[i]= hypermesh_add_vert(hme, &dlverts->verts[i*3]);
+ else
+ vert_tbl[i]= hypermesh_add_vert(hme, me->mvert[i].co);
+ }
+
+ for (i=0; i<me->totface; i++) {
+ MFace *mf= &mface[i];
+
+ if (mf->v3) {
+ int nverts= mf->v4?4:3;
+ HyperVert *verts[4];
+ HyperFace *f;
+
+ verts[0]= vert_tbl[mf->v1];
+ verts[1]= vert_tbl[mf->v2];
+ verts[2]= vert_tbl[mf->v3];
+ if (nverts>3)
+ verts[3]= vert_tbl[mf->v4];
+
+ f= hypermesh_add_face(hme, verts, nverts);
+ f->orig.ind= i;
+
+ if (hme->hasuvco) {
+ TFace *tf= &((TFace*) me->tface)[i];
+
+ f->uvco= BLI_memarena_alloc(hme->arena, sizeof(*f->uvco)*nverts);
+ for (j=0; j<nverts; j++)
+ Vec2Cpy(f->uvco[j], tf->uv[j]);
+
+ f->vcol= BLI_memarena_alloc(hme->arena, sizeof(*f->vcol)*nverts);
+ for (j=0; j<nverts; j++)
+ *((unsigned int*) f->vcol[j])= tf->col[j];
+ } else if (hme->hasvcol) {
+ MCol *mcol= &me->mcol[i*4];
+
+ f->vcol= BLI_memarena_alloc(hme->arena, sizeof(*f->vcol)*nverts);
+ for (j=0; j<nverts; j++)
+ *((unsigned int*) f->vcol[j])= *((unsigned int*) &mcol[j]);
+ }
+ } else {
+ hypermesh_add_edge(hme, vert_tbl[mf->v1], vert_tbl[mf->v2]);
+ }
+ }
+
+ MEM_freeN(vert_tbl);
+
+ return hme;
+}
+
+static HyperMesh *hypermesh_from_editmesh(EditVert *everts, EditEdge *eedges, EditVlak *efaces) {
+ HyperMesh *hme= hypermesh_new();
+ EditVert *ev, *prevev;
+ EditEdge *ee;
+ EditVlak *ef;
+
+ /* hack, tuck the new hypervert pointer into
+ * the ev->prev link so we can find it easy,
+ * then restore real prev links later.
+ */
+ for (ev= everts; ev; ev= ev->next)
+ ev->prev= (EditVert*) hypermesh_add_vert(hme, ev->co);
+
+ for (ee= eedges; ee; ee= ee->next)
+ hypermesh_add_edge(hme, (HyperVert*) ee->v1->prev, (HyperVert*) ee->v2->prev);
+
+ for (ef= efaces; ef; ef= ef->next) {
+ int nverts= ef->v4?4:3;
+ HyperVert *verts[4];
+ HyperFace *f;
+
+ verts[0]= (HyperVert*) ef->v1->prev;
+ verts[1]= (HyperVert*) ef->v2->prev;
+ verts[2]= (HyperVert*) ef->v3->prev;
+ if (nverts>3)
+ verts[3]= (HyperVert*) ef->v4->prev;
+
+ f= hypermesh_add_face(hme, verts, nverts);
+ f->orig.ef= ef;
+ }
+
+ /* see hack above, restore the prev links */
+ for (prevev= NULL, ev= everts; ev; prevev= ev, ev= ev->next)
+ ev->prev= prevev;
+
+ return hme;
+}
+
+static void VColAvgT(unsigned char *t, unsigned char *a, unsigned char *b) {
+ t[0]= (a[0]+b[0])>>1;
+ t[1]= (a[1]+b[1])>>1;
+ t[2]= (a[2]+b[2])>>1;
+ t[3]= (a[3]+b[3])>>1;
+}
+
+static void hypermesh_subdivide(HyperMesh *me, HyperMesh *nme) {
+ HyperVert *v;
+ HyperEdge *e;
+ HyperFace *f;
+ LinkNode *link;
+ float co[3];
+ int j, k, count;
+
+ for (f= me->faces; f; f= f->next) {
+ Vec3CpyI(co, 0.0, 0.0, 0.0);
+ for (j=0; j<f->nverts; j++)
+ Vec3Add(co, f->verts[j]->co);
+ Vec3MulN(co, (float)(1.0/f->nverts));
+
+ f->mid= hypermesh_add_vert(nme, co);
+ }
+
+ for (e= me->edges; e; e= e->next) {
+ if (hyperedge_is_boundary(e)) {
+ Vec3AvgT(co, e->v[0]->co, e->v[1]->co);
+ } else {
+ Vec3AddT(co, e->v[0]->co, e->v[1]->co);
+ for (count=2, link= e->faces; link; count++, link= link->next) {
+ f= (HyperFace *) link->link;
+ Vec3Add(co, f->mid->co);
+ }
+ Vec3MulN(co, (float)(1.0/count));
+ }
+
+ e->ep= hypermesh_add_vert(nme, co);
+ }
+
+ for (v= me->verts; v; v= v->next) {
+ float q[3], r[3], s[3];
+
+ if (hypervert_is_boundary(v)) {
+ Vec3CpyI(r, 0.0, 0.0, 0.0);
+
+ for (count= 0, link= v->edges; link; link= link->next) {
+ if (hyperedge_is_boundary(link->link)) {
+ HyperVert *ov= hyperedge_other_vert(link->link, v);
+
+ Vec3Add(r, ov->co);
+ count++;
+ }
+ }
+
+ /* I believe CC give the factors as
+ 3/2k and 1/4k, but that doesn't make
+ sense (to me) as they don't sum to unity...
+ It's rarely important.
+ */
+ Vec3MulNT(s, v->co, 0.75f);
+ Vec3Add(s, Vec3MulN(r, (float)(1.0/(4.0*count))));
+ } else {
+ Vec3Cpy(q, Vec3Cpy(r, Vec3CpyI(s, 0.0f, 0.0f, 0.0f)));
+
+ for (count=0, link= v->faces; link; count++, link= link->next) {
+ f= (HyperFace *) link->link;
+ Vec3Add(q, f->mid->co);
+ }
+ Vec3MulN(q, (float)(1.0/count));
+
+ for (count=0, link= v->edges; link; count++, link= link->next) {
+ e= (HyperEdge *) link->link;
+ Vec3Add(r, hyperedge_other_vert(e, v)->co);
+ }
+ Vec3MulN(r, (float)(1.0/count));
+
+ Vec3MulNT(s, v->co, (float)(count-2));
+
+ Vec3Add(s, q);
+ Vec3Add(s, r);
+ Vec3MulN(s, (float)(1.0/count));
+ }
+
+ v->nmv= hypermesh_add_vert(nme, s);
+ }
+
+ for (e= me->edges; e; e= e->next) {
+ hypermesh_add_edge(nme, e->v[0]->nmv, e->ep);
+ hypermesh_add_edge(nme, e->v[1]->nmv, e->ep);
+ }
+
+ for (f= me->faces; f; f= f->next) {
+ int last= f->nverts-1;
+ unsigned char vcol_mid[4];
+ unsigned char vcol_edge[4][4];
+ float uvco_mid[2];
+ float uvco_edge[4][4];
+
+ if (me->hasvcol) {
+ int t[4]= {0, 0, 0, 0};
+ for (j=0; j<f->nverts; j++) {
+ t[0]+= f->vcol[j][0];
+ t[1]+= f->vcol[j][1];
+ t[2]+= f->vcol[j][2];
+ t[3]+= f->vcol[j][3];
+ }
+ vcol_mid[0]= t[0]/f->nverts;
+ vcol_mid[1]= t[1]/f->nverts;
+ vcol_mid[2]= t[2]/f->nverts;
+ vcol_mid[3]= t[3]/f->nverts;
+
+ for (j=0; j<f->nverts; last= j, j++)
+ VColAvgT(vcol_edge[j], f->vcol[last], f->vcol[j]);
+ last= f->nverts-1;
+ }
+ if (me->hasuvco) {
+ Vec2CpyI(uvco_mid, 0.0, 0.0);
+ for (j=0; j<f->nverts; j++)
+ Vec2Add(uvco_mid, f->uvco[j]);
+ Vec3MulN(uvco_mid, (float)(1.0/f->nverts));
+
+ for (j=0; j<f->nverts; last= j, j++)
+ Vec2AvgT(uvco_edge[j], f->uvco[last], f->uvco[j]);
+ last= f->nverts-1;
+ }
+
+ for (j=0; j<f->nverts; last=j, j++) {
+ HyperVert *nv[4];
+ HyperFace *nf;
+
+ nv[0]= f->verts[last]->nmv;
+ nv[1]= f->edges[j]->ep;
+ nv[2]= f->mid;
+ nv[3]= f->edges[last]->ep;
+
+ nf= hypermesh_add_face(nme, nv, 4);
+ nf->orig= f->orig;
+
+ if (me->hasvcol) {
+ nf->vcol= BLI_memarena_alloc(nme->arena, sizeof(*nf->vcol)*4);
+
+ for (k=0; k<4; k++) {
+ nf->vcol[0][k]= f->vcol[last][k];
+ nf->vcol[1][k]= vcol_edge[j][k];
+ nf->vcol[2][k]= vcol_mid[k];
+ nf->vcol[3][k]= vcol_edge[last][k];
+ }
+ }
+ if (me->hasuvco) {
+ nf->uvco= BLI_memarena_alloc(nme->arena, sizeof(*nf->uvco)*4);
+
+ Vec2Cpy(nf->uvco[0], f->uvco[last]);
+ Vec2Cpy(nf->uvco[1], uvco_edge[j]);
+ Vec2Cpy(nf->uvco[2], uvco_mid);
+ Vec2Cpy(nf->uvco[3], uvco_edge[last]);
+ }
+ }
+ }
+}
+
+static void hypermesh_free(HyperMesh *me) {
+ BLI_memarena_free(me->arena);
+
+ MEM_freeN(me);
+}
+
+/*****/
+
+static void add_mvert_normals_from_mfaces(MVert *mverts, int nmverts, MFaceInt *mfaces, int nmfaces) {
+ float (*tnorms)[3]= MEM_callocN(nmverts*sizeof(*tnorms), "tnorms");
+ int i;
+
+ for (i=0; i<nmfaces; i++) {
+ MFaceInt *mf= &mfaces[i];
+ float f_no[3];
+
+ if (!mf->v3)
+ continue;
+
+ if (mf->v4)
+ CalcNormFloat4(mverts[mf->v1].co, mverts[mf->v2].co, mverts[mf->v3].co, mverts[mf->v4].co, f_no);
+ else
+ CalcNormFloat(mverts[mf->v1].co, mverts[mf->v2].co, mverts[mf->v3].co, f_no);
+
+ Vec3Add(tnorms[mf->v1], f_no);
+ Vec3Add(tnorms[mf->v2], f_no);
+ Vec3Add(tnorms[mf->v3], f_no);
+ if (mf->v4)
+ Vec3Add(tnorms[mf->v4], f_no);
+ }
+ for (i=0; i<nmverts; i++) {
+ MVert *mv= &mverts[i];
+ float *no= tnorms[i];
+
+ Normalise(no);
+ mv->no[0]= (short)(no[0]*32767.0);
+ mv->no[1]= (short)(no[1]*32767.0);
+ mv->no[2]= (short)(no[2]*32767.0);
+ }
+
+ MEM_freeN(tnorms);
+}
+
+static int hypermesh_get_nverts(HyperMesh *hme) {
+ HyperVert *v;
+ int count= 0;
+
+ for (v= hme->verts; v; v= v->next)
+ count++;
+
+ return count;
+}
+
+static int hypermesh_get_nfaces(HyperMesh *hme) {
+ HyperFace *f;
+ int count= 0;
+
+ for (f= hme->faces; f; f= f->next)
+ count++;
+
+ return count;
+}
+
+static int hypermesh_get_nlines(HyperMesh *hme) {
+ HyperEdge *e;
+ int n= 0;
+
+ for (e= hme->edges; e; e= e->next)
+ if (!e->faces)
+ n++;
+
+ return n;
+}
+
+static int editface_is_hidden(EditVlak *ef) {
+ return (ef->v1->h || ef->v2->h || ef->v3->h || (ef->v4 && ef->v4->h));
+}
+
+static int hypermesh_get_nhidden(HyperMesh *hme) {
+ int count= 0;
+
+ /* hme->orig_me==NULL if we are working on an editmesh */
+ if (!hme->orig_me) {
+ HyperFace *f;
+
+ for (f= hme->faces; f; f= f->next)
+ if (editface_is_hidden(f->orig.ef))
+ count++;
+ }
+
+ return count;
+}
+
+static DispList *hypermesh_to_displist(HyperMesh *hme) {
+ int nverts= hypermesh_get_nverts(hme);
+ int nfaces= hypermesh_get_nfaces(hme) + hypermesh_get_nlines(hme) - hypermesh_get_nhidden(hme);
+ DispList *dl= MEM_callocN(sizeof(*dl), "dl");
+ DispListMesh *dlm= MEM_callocN(sizeof(*dlm), "dlmesh");
+ HyperFace *f;
+ HyperVert *v;
+ HyperEdge *e;
+ TFace *tfaces;
+ MFace *mfaces;
+ MFaceInt *mf;
+ int i, j;
+
+ /* hme->orig_me==NULL if we are working on an editmesh */
+ if (hme->orig_me) {
+ tfaces= hme->orig_me->tface;
+ mfaces= hme->orig_me->mface;
+ } else {
+ tfaces= NULL;
+ mfaces= NULL;
+ }
+
+ dl->type= DL_MESH;
+ dl->mesh= dlm;
+
+ dlm->totvert= nverts;
+ dlm->totface= nfaces;
+ dlm->mvert= MEM_mallocN(dlm->totvert*sizeof(*dlm->mvert), "dlm->mvert");
+ dlm->mface= MEM_mallocN(dlm->totface*sizeof(*dlm->mface), "dlm->mface");
+
+ if (hme->hasuvco)
+ dlm->tface= MEM_callocN(dlm->totface*sizeof(*dlm->tface), "dlm->tface");
+ else if (hme->hasvcol)
+ dlm->mcol= MEM_mallocN(dlm->totface*4*sizeof(*dlm->mcol), "dlm->mcol");
+
+ for (i=0, v= hme->verts; i<nverts; i++, v= v->next) {
+ MVert *mv= &dlm->mvert[i];
+ Vec3Cpy(mv->co, v->co);
+ v->nmv= (void*) i;
+ }
+
+ mf= dlm->mface;
+ for (i=0, f= hme->faces; f; i++, f= f->next) {
+ int voff= (((int) f->verts[3]->nmv)==0)?1:0;
+
+ if (!hme->orig_me && editface_is_hidden(f->orig.ef))
+ continue;
+
+ /* compensate for blender's [braindead] way of encoding
+ * nverts by face vertices, if necessary.
+ */
+
+ mf->v1= (int) f->verts[(0+voff)%4]->nmv;
+ mf->v2= (int) f->verts[(1+voff)%4]->nmv;
+ mf->v3= (int) f->verts[(2+voff)%4]->nmv;
+ mf->v4= (int) f->verts[(3+voff)%4]->nmv;
+
+ if (hme->orig_me) {
+ MFace *origmf= &mfaces[f->orig.ind];
+
+ mf->mat_nr= origmf->mat_nr;
+ mf->flag= origmf->flag;
+ mf->puno= 0;
+ mf->edcode= ME_V1V2|ME_V2V3|ME_V3V4|ME_V4V1;
+ } else {
+ EditVlak *origef= f->orig.ef;
+
+ mf->mat_nr= origef->mat_nr;
+ mf->flag= origef->flag;
+ mf->puno= 0;
+ mf->edcode= ME_V1V2|ME_V2V3|ME_V3V4|ME_V4V1;
+ }
+
+ if (hme->hasuvco) {
+ TFace *origtf, *tf= &dlm->tface[i];
+
+ if (hme->orig_me)
+ origtf= &tfaces[f->orig.ind];
+ else
+ origtf= f->orig.ef->tface;
+
+ for (j=0; j<4; j++) {
+ Vec2Cpy(tf->uv[j], f->uvco[(j+voff)%4]);
+ tf->col[j]= *((unsigned int*) f->vcol[(j+voff)%4]);
+ }
+
+ tf->tpage= origtf->tpage;
+ tf->flag= origtf->flag;
+ tf->transp= origtf->transp;
+ tf->mode= origtf->mode;
+ tf->tile= origtf->tile;
+ } else if (hme->hasvcol) {
+ MCol *mcolbase= &dlm->mcol[i*4];
+
+ for (j=0; j<4; j++)
+ *((unsigned int*) &mcolbase[j])= *((unsigned int*) f->vcol[(j+voff)%4]);
+ }
+
+ mf++;
+ }
+
+ for (e= hme->edges; e; e= e->next) {
+ if (!e->faces) {
+ mf->v1= (int) e->v[0]->nmv;
+ mf->v2= (int) e->v[1]->nmv;
+ mf->v3= 0;
+ mf->v4= 0;
+
+ mf->mat_nr= 0;
+ mf->flag= 0;
+ mf->puno= 0;
+ mf->edcode= ME_V1V2;
+
+ mf++;
+ }
+ }
+
+ add_mvert_normals_from_mfaces(dlm->mvert, dlm->totvert, dlm->mface, dlm->totface);
+
+ return dl;
+}
+
+static DispList *subsurf_subdivide_to_displist(HyperMesh *hme, short subdiv) {
+ DispList *dl;
+ int i;
+
+ for (i= 0; i<subdiv; i++) {
+ HyperMesh *tmp= hypermesh_new();
+ tmp->hasvcol= hme->hasvcol;
+ tmp->hasuvco= hme->hasuvco;
+ tmp->orig_me= hme->orig_me;
+
+ hypermesh_subdivide(hme, tmp);
+ hypermesh_free(hme);
+
+ hme= tmp;
+ }
+
+ dl= hypermesh_to_displist(hme);
+ hypermesh_free(hme);
+
+ return dl;
+}
+
+void subsurf_make_editmesh(Object *ob) {
+ if (G.eded.first) {
+ Mesh *me= ob->data;
+ HyperMesh *hme= hypermesh_from_editmesh(G.edve.first, G.eded.first, G.edvl.first);
+
+ free_displist_by_type(&me->disp, DL_MESH);
+ BLI_addtail(&me->disp, subsurf_subdivide_to_displist(hme, me->subdiv));
+ }
+}
+
+void subsurf_make_mesh(Object *ob, short subdiv) {
+ Mesh *me= ob->data;
+
+ if (me->totface) {
+ HyperMesh *hme= hypermesh_from_mesh(me, find_displist(&ob->disp, DL_VERTS));
+
+ free_displist_by_type(&me->disp, DL_MESH);
+ BLI_addtail(&me->disp, subsurf_subdivide_to_displist(hme, subdiv));
+ }
+}
+
+void subsurf_to_mesh(Object *oldob, Mesh *me) {
+ Mesh *oldme= oldob->data;
+
+ if (oldme->totface) {
+ HyperMesh *hme= hypermesh_from_mesh(oldme, NULL);
+ DispList *dl= subsurf_subdivide_to_displist(hme, oldme->subdiv);
+ DispListMesh *dlm= dl->mesh;
+ MFace *mfaces;
+ int i;
+
+ if (dlm->totvert>65000)
+ error("Too many vertices");
+ else {
+ me->totface= dlm->totface;
+ me->totvert= dlm->totvert;
+
+ me->mvert= MEM_dupallocN(dlm->mvert);
+ me->mface= mfaces= MEM_mallocN(sizeof(*mfaces)*me->totface, "me->mface");
+ me->tface= MEM_dupallocN(dlm->tface);
+ me->mcol= MEM_dupallocN(dlm->mcol);
+
+ for (i=0; i<me->totface; i++) {
+ MFace *mf= &mfaces[i];
+ MFaceInt *oldmf= &dlm->mface[i];
+
+ mf->v1= oldmf->v1;
+ mf->v2= oldmf->v2;
+ mf->v3= oldmf->v3;
+ mf->v4= oldmf->v4;
+ mf->flag= oldmf->flag;
+ mf->mat_nr= oldmf->mat_nr;
+ mf->puno= 0;
+ mf->edcode= ME_V1V2|ME_V2V3|ME_V3V4|ME_V4V1;
+ }
+ }
+
+ free_disp_elem(dl);
+ }
+}
+
+DispList* subsurf_mesh_to_displist(Mesh *me, DispList *dl, short subdiv)
+{
+ HyperMesh *hme;
+
+ hme= hypermesh_from_mesh(me, dl);
+
+ return subsurf_subdivide_to_displist(hme, subdiv);
+}
diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c
new file mode 100644
index 00000000000..7f1c6f4935b
--- /dev/null
+++ b/source/blender/blenkernel/intern/text.c
@@ -0,0 +1,1986 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 <ctype.h> /* isprint() */
+#include <string.h> /* strstr */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+
+#include "DNA_text_types.h"
+
+#include "BKE_bad_level_calls.h"
+#include "BKE_utildefines.h"
+#include "BKE_text.h"
+#include "BKE_library.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+
+#include "BPY_extern.h" // Blender Python library
+
+/***************/ /*
+
+How Texts should work
+--
+A text should relate to a file as follows -
+(Text *)->name should be the place where the
+ file will or has been saved.
+
+(Text *)->flags has the following bits
+ TXT_ISDIRTY - should always be set if the file in mem. differs from
+ the file on disk, or if there is no file on disk.
+ TXT_ISTMP - should always be set if the (Text *)->name file has not
+ been written before, and attempts to save should result
+ in "Save over?"
+ TXT_ISMEM - should always be set if the Text has not been mapped to
+ a file, in which case (Text *)->name may be NULL or garbage.
+ TXT_ISEXT - should always be set if the Text is not to be written into
+ the .blend
+ TXT_ISSCRIPT - should be set if the user has designated the text
+ as a script.
+
+->>> see also: /makesdna/DNA_text_types.h
+
+Display
+--
+The st->top determines at what line the top of the text is displayed.
+If the user moves the cursor the st containing that cursor should
+be popped ... other st's retain their own top location.
+
+*/ /***************/
+
+
+/****************/ /*
+ Undo
+
+Undo/Redo works by storing
+events in a queue, and a pointer
+to the current position in the
+queue...
+
+Events are stored using an
+arbitrary op-code system
+to keep track of
+a) the two cursors (normal and selected)
+b) input (visible and control (ie backspace))
+
+input data is stored as its
+ASCII value, the opcodes are
+then selected to not conflict.
+
+opcodes with data in between are
+written at the beginning and end
+of the data to allow undo and redo
+to simply check the code at the current
+undo position
+
+*/ /***************/
+
+/***/
+
+static void txt_pop_first(Text *text);
+static void txt_pop_last(Text *text);
+static void txt_undo_add_op(Text *text, int op);
+static void txt_undo_add_block(Text *text, int op, char *buf);
+static void txt_delete_line(Text *text, TextLine *line);
+
+/***/
+
+static char *txt_cut_buffer= NULL;
+static unsigned char undoing;
+
+/* allow to switch off undoing externally */
+void txt_set_undostate(int u)
+{
+ undoing = u;
+}
+
+int txt_get_undostate(void)
+{
+ return undoing;
+}
+
+void free_text(Text *text)
+{
+ TextLine *tmp;
+
+ for (tmp= text->lines.first; tmp; tmp= tmp->next)
+ MEM_freeN(tmp->line);
+
+ BLI_freelistN(&text->lines);
+
+ if(text->name) MEM_freeN(text->name);
+ MEM_freeN(text->undo_buf);
+}
+
+Text *add_empty_text(void)
+{
+ Text *ta;
+ TextLine *tmp;
+
+ ta= alloc_libblock(&G.main->text, ID_TXT, "Text");
+ ta->id.us= 1;
+
+ ta->name= NULL;
+
+ ta->undo_pos= -1;
+ ta->undo_len= TXT_INIT_UNDO;
+ ta->undo_buf= MEM_mallocN(ta->undo_len, "undo buf");
+
+ ta->nlines=1;
+ ta->flags= TXT_ISDIRTY | TXT_ISTMP | TXT_ISMEM;
+
+ ta->lines.first= ta->lines.last= NULL;
+
+ tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline");
+ tmp->line= (char*) MEM_mallocN(1, "textline_string");
+
+ tmp->line[0]=0;
+ tmp->len= 0;
+
+ tmp->next= NULL;
+ tmp->prev= NULL;
+
+ BLI_addhead(&ta->lines, tmp);
+
+ ta->curl= ta->lines.first;
+ ta->curc= 0;
+ ta->sell= ta->lines.first;
+ ta->selc= 0;
+
+ return ta;
+}
+
+// this function removes any control characters from
+// a textline
+
+static void cleanup_textline(TextLine * tl)
+{
+ int i;
+
+ for (i = 0; i < tl->len; i++ ) {
+ if (tl->line[i] < ' ' && tl->line[i] != '\t') {
+ memmove(tl->line + i, tl->line + i + 1, tl->len - i);
+ tl->len--;
+ i--;
+ }
+ }
+}
+
+int reopen_text(Text *text)
+{
+ FILE *fp;
+ int i, llen, len;
+ unsigned char *buffer;
+ TextLine *tmp;
+ char sdir[FILE_MAXDIR];
+ char sfile[FILE_MAXFILE];
+
+ if (!text || !text->name) return 0;
+
+ BLI_split_dirfile(text->name, sdir, sfile);
+
+ fp= fopen(text->name, "r");
+ if(fp==NULL) return 0;
+
+ /* free memory: */
+
+ for (tmp= text->lines.first; tmp; tmp= tmp->next)
+ MEM_freeN(tmp->line);
+
+ BLI_freelistN(&text->lines);
+
+ text->lines.first= text->lines.last= NULL;
+ text->curl= text->sell= NULL;
+
+ /* clear undo buffer */
+ MEM_freeN(text->undo_buf);
+ text->undo_pos= -1;
+ text->undo_len= TXT_INIT_UNDO;
+ text->undo_buf= MEM_mallocN(text->undo_len, "undo buf");
+
+ text->flags= TXT_ISDIRTY | TXT_ISTMP;
+
+ fseek(fp, 0L, SEEK_END);
+ len= ftell(fp);
+ fseek(fp, 0L, SEEK_SET);
+
+ text->undo_pos= -1;
+
+ buffer= MEM_mallocN(len, "text_buffer");
+ // under windows fread can return less then len bytes because
+ // of CR stripping
+ len = fread(buffer, 1, len, fp);
+
+ fclose(fp);
+
+ text->nlines=0;
+ i=0;
+ llen=0;
+ for(i=0; i<len; i++) {
+ if (buffer[i]=='\n') {
+ tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline");
+ tmp->line= (char*) MEM_mallocN(llen+1, "textline_string");
+
+ if(llen) memcpy(tmp->line, &buffer[i-llen], llen);
+ tmp->line[llen]=0;
+ tmp->len= llen;
+
+ cleanup_textline(tmp);
+
+ BLI_addtail(&text->lines, tmp);
+ text->nlines++;
+
+ llen=0;
+ continue;
+ }
+ llen++;
+ }
+
+ if (llen!=0 || text->nlines==0) {
+ tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline");
+ tmp->line= (char*) MEM_mallocN(llen+1, "textline_string");
+
+ if(llen) memcpy(tmp->line, &buffer[i-llen], llen);
+
+ tmp->line[llen]=0;
+ tmp->len= llen;
+
+ cleanup_textline(tmp);
+
+ BLI_addtail(&text->lines, tmp);
+ text->nlines++;
+ }
+
+ text->curl= text->sell= text->lines.first;
+ text->curc= text->selc= 0;
+
+ MEM_freeN(buffer);
+ return 1;
+}
+
+Text *add_text(char *file)
+{
+ FILE *fp;
+ int i, llen, len;
+ unsigned char *buffer;
+ TextLine *tmp;
+ Text *ta;
+ char sdir[FILE_MAXDIR];
+ char sfile[FILE_MAXFILE];
+
+ BLI_split_dirfile(file, sdir, sfile);
+
+ fp= fopen(file, "r");
+ if(fp==NULL) return NULL;
+
+ ta= alloc_libblock(&G.main->text, ID_TXT, sfile);
+ ta->id.us= 1;
+
+ ta->lines.first= ta->lines.last= NULL;
+ ta->curl= ta->sell= NULL;
+
+/* ta->flags= TXT_ISTMP | TXT_ISEXT; */
+ ta->flags= TXT_ISTMP;
+
+ fseek(fp, 0L, SEEK_END);
+ len= ftell(fp);
+ fseek(fp, 0L, SEEK_SET);
+
+ ta->name= MEM_mallocN(strlen(file)+1, "text_name");
+ strcpy(ta->name, file);
+
+ ta->undo_pos= -1;
+ ta->undo_len= TXT_INIT_UNDO;
+ ta->undo_buf= MEM_mallocN(ta->undo_len, "undo buf");
+
+ buffer= MEM_mallocN(len, "text_buffer");
+ // under windows fread can return less then len bytes because
+ // of CR stripping
+ len = fread(buffer, 1, len, fp);
+
+ fclose(fp);
+
+ ta->nlines=0;
+ i=0;
+ llen=0;
+ for(i=0; i<len; i++) {
+ if (buffer[i]=='\n') {
+ tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline");
+ tmp->line= (char*) MEM_mallocN(llen+1, "textline_string");
+
+ if(llen) memcpy(tmp->line, &buffer[i-llen], llen);
+ tmp->line[llen]=0;
+ tmp->len= llen;
+
+ cleanup_textline(tmp);
+
+ BLI_addtail(&ta->lines, tmp);
+ ta->nlines++;
+
+ llen=0;
+ continue;
+ }
+ llen++;
+ }
+
+ if (llen!=0 || ta->nlines==0) {
+ tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline");
+ tmp->line= (char*) MEM_mallocN(llen+1, "textline_string");
+
+ if(llen) memcpy(tmp->line, &buffer[i-llen], llen);
+
+ tmp->line[llen]=0;
+ tmp->len= llen;
+
+ cleanup_textline(tmp);
+
+ BLI_addtail(&ta->lines, tmp);
+ ta->nlines++;
+ }
+
+ ta->curl= ta->sell= ta->lines.first;
+ ta->curc= ta->selc= 0;
+
+ MEM_freeN(buffer);
+
+ return ta;
+}
+
+Text *copy_text(Text *ta)
+{
+ Text *tan;
+ TextLine *line, *tmp;
+
+ tan= copy_libblock(ta);
+
+ tan->name= MEM_mallocN(strlen(ta->name)+1, "text_name");
+ strcpy(tan->name, ta->name);
+
+ tan->flags = ta->flags | TXT_ISDIRTY | TXT_ISTMP;
+
+ tan->lines.first= tan->lines.last= NULL;
+ tan->curl= tan->sell= NULL;
+
+ tan->nlines= ta->nlines;
+
+ line= ta->lines.first;
+ /* Walk down, reconstructing */
+ while (line) {
+ tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline");
+ tmp->line= MEM_mallocN(line->len+1, "textline_string");
+ strcpy(tmp->line, line->line);
+
+ tmp->len= line->len;
+
+ BLI_addtail(&tan->lines, tmp);
+
+ line= line->next;
+ }
+
+ tan->curl= tan->sell= tan->lines.first;
+ tan->curc= tan->selc= 0;
+
+ return tan;
+}
+
+/*****************************/
+/* Editing utility functions */
+/*****************************/
+
+static void make_new_line (TextLine *line, char *newline)
+{
+ MEM_freeN(line->line);
+
+ line->line= newline;
+ line->len= strlen(newline);
+}
+
+static TextLine *txt_new_line(char *str)
+{
+ TextLine *tmp;
+
+ if(!str) str= "";
+
+ tmp= (TextLine *) MEM_mallocN(sizeof(TextLine), "textline");
+ tmp->line= MEM_mallocN(strlen(str)+1, "textline_string");
+ strcpy(tmp->line, str);
+
+ tmp->len= strlen(str);
+ tmp->next= tmp->prev= NULL;
+
+ return tmp;
+}
+
+static TextLine *txt_new_linen(char *str, int n)
+{
+ TextLine *tmp;
+
+ if(!str) str= "";
+
+ tmp= (TextLine *) MEM_mallocN(sizeof(TextLine), "textline");
+ tmp->line= MEM_mallocN(n+1, "textline_string");
+ BLI_strncpy(tmp->line, str, n+1);
+
+ tmp->len= strlen(tmp->line);
+ tmp->next= tmp->prev= NULL;
+
+ return tmp;
+}
+
+void txt_clean_text (Text *text)
+{
+ TextLine **top, **bot;
+
+ if (!text) return;
+
+ if (!text->lines.first) {
+ if (text->lines.last) text->lines.first= text->lines.last;
+ else text->lines.first= text->lines.last= txt_new_line(NULL);
+ }
+
+ if (!text->lines.last) text->lines.last= text->lines.first;
+
+ top= (TextLine **) &text->lines.first;
+ bot= (TextLine **) &text->lines.last;
+
+ while ((*top)->prev) *top= (*top)->prev;
+ while ((*bot)->next) *bot= (*bot)->next;
+
+ if(!text->curl) {
+ if(text->sell) text->curl= text->sell;
+ else text->curl= text->lines.first;
+ text->curc= 0;
+ }
+
+ if(!text->sell) {
+ text->sell= text->curl;
+ text->selc= 0;
+ }
+}
+
+int txt_get_span (TextLine *from, TextLine *to)
+{
+ int ret=0;
+ TextLine *tmp= from;
+
+ if (!to || !from) return 0;
+ if (from==to) return 0;
+
+ /* Look forwards */
+ while (tmp) {
+ if (tmp == to) return ret;
+ ret++;
+ tmp= tmp->next;
+ }
+
+ /* Look backwards */
+ if (!tmp) {
+ tmp= from;
+ ret=0;
+ while(tmp) {
+ if (tmp == to) break;
+ ret--;
+ tmp= tmp->prev;
+ }
+ if(!tmp) ret=0;
+ }
+
+ return ret;
+}
+
+static int txt_illegal_char (char c)
+{
+ if (isprint(c) || c=='\t') return 0;
+
+ return 1;
+}
+
+static void txt_make_dirty (Text *text)
+{
+ text->flags |= TXT_ISDIRTY;
+ if (text->compiled) BPY_free_compiled_text(text);
+}
+
+/****************************/
+/* Cursor utility functions */
+/****************************/
+
+static void txt_curs_cur (Text *text, TextLine ***linep, int **charp)
+{
+ *linep= &text->curl; *charp= &text->curc;
+}
+
+static void txt_curs_sel (Text *text, TextLine ***linep, int **charp)
+{
+ *linep= &text->sell; *charp= &text->selc;
+}
+
+static void txt_curs_first (Text *text, TextLine **linep, int *charp)
+{
+ if (text->curl==text->sell) {
+ *linep= text->curl;
+ if (text->curc<text->selc) *charp= text->curc;
+ else *charp= text->selc;
+ } else if (txt_get_span(text->lines.first, text->curl)<txt_get_span(text->lines.first, text->sell)) {
+ *linep= text->curl;
+ *charp= text->curc;
+ } else {
+ *linep= text->sell;
+ *charp= text->selc;
+ }
+}
+
+/****************************/
+/* Cursor movement functions */
+/****************************/
+
+void txt_move_up(Text *text, short sel)
+{
+ TextLine **linep;
+ int *charp, old;
+
+ if (!text) return;
+ if(sel) txt_curs_sel(text, &linep, &charp);
+ else { txt_pop_first(text); txt_curs_cur(text, &linep, &charp); }
+ if (!*linep) return;
+ old= *charp;
+
+ if((*linep)->prev) {
+ *linep= (*linep)->prev;
+ if (*charp > (*linep)->len) {
+ *charp= (*linep)->len;
+ if(!undoing) txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, txt_get_span(text->lines.first, (*linep)->next), old, txt_get_span(text->lines.first, *linep), (unsigned short) *charp);
+ } else {
+ if(!undoing) txt_undo_add_op(text, sel?UNDO_SUP:UNDO_CUP);
+ }
+ } else {
+ *charp= 0;
+ if(!undoing) txt_undo_add_op(text, sel?UNDO_SUP:UNDO_CUP);
+ }
+
+ if(!sel) txt_pop_sel(text);
+}
+
+void txt_move_down(Text *text, short sel)
+{
+ TextLine **linep;
+ int *charp, old;
+
+ if (!text) return;
+ if(sel) txt_curs_sel(text, &linep, &charp);
+ else { txt_pop_last(text); txt_curs_cur(text, &linep, &charp); }
+ if (!*linep) return;
+ old= *charp;
+
+ if((*linep)->next) {
+ *linep= (*linep)->next;
+ if (*charp > (*linep)->len) {
+ *charp= (*linep)->len;
+ if(!undoing) txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, txt_get_span(text->lines.first, (*linep)->prev), old, txt_get_span(text->lines.first, *linep), (unsigned short)*charp);
+ } else
+ if(!undoing) txt_undo_add_op(text, sel?UNDO_SDOWN:UNDO_CDOWN);
+ } else {
+ *charp= (*linep)->len;
+ if(!undoing) txt_undo_add_op(text, sel?UNDO_SDOWN:UNDO_CDOWN);
+ }
+
+ if(!sel) txt_pop_sel(text);
+}
+
+void txt_move_left(Text *text, short sel)
+{
+ TextLine **linep;
+ int *charp, oundoing= undoing;
+
+ if (!text) return;
+ if(sel) txt_curs_sel(text, &linep, &charp);
+ else { txt_pop_first(text); txt_curs_cur(text, &linep, &charp); }
+ if (!*linep) return;
+
+ undoing= 1;
+ if (*charp== 0) {
+ if ((*linep)->prev) {
+ txt_move_up(text, sel);
+ *charp= (*linep)->len;
+ }
+ } else {
+ (*charp)--;
+ }
+ undoing= oundoing;
+ if(!undoing) txt_undo_add_op(text, sel?UNDO_SLEFT:UNDO_CLEFT);
+
+ if(!sel) txt_pop_sel(text);
+}
+
+void txt_move_right(Text *text, short sel)
+{
+ TextLine **linep;
+ int *charp, oundoing= undoing;
+
+ if (!text) return;
+ if(sel) txt_curs_sel(text, &linep, &charp);
+ else { txt_pop_last(text); txt_curs_cur(text, &linep, &charp); }
+ if (!*linep) return;
+
+ undoing= 1;
+ if (*charp== (*linep)->len) {
+ if ((*linep)->next) {
+ txt_move_down(text, sel);
+ *charp= 0;
+ }
+ } else {
+ (*charp)++;
+ }
+ undoing= oundoing;
+ if(!undoing) txt_undo_add_op(text, sel?UNDO_SRIGHT:UNDO_CRIGHT);
+
+ if(!sel) txt_pop_sel(text);
+}
+
+void txt_move_bol (Text *text, short sel)
+{
+ TextLine **linep;
+ int *charp, old;
+
+ if (!text) return;
+ if(sel) txt_curs_sel(text, &linep, &charp);
+ else txt_curs_cur(text, &linep, &charp);
+ if (!*linep) return;
+ old= *charp;
+
+ *charp= 0;
+
+ if(!sel) txt_pop_sel(text);
+ if(!undoing) txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, txt_get_span(text->lines.first, *linep), old, txt_get_span(text->lines.first, *linep), (unsigned short)*charp);
+}
+
+void txt_move_eol (Text *text, short sel)
+{
+ TextLine **linep;
+ int *charp, old;
+
+ if (!text) return;
+ if(sel) txt_curs_sel(text, &linep, &charp);
+ else txt_curs_cur(text, &linep, &charp);
+ if (!*linep) return;
+ old= *charp;
+
+ *charp= (*linep)->len;
+
+ if(!sel) txt_pop_sel(text);
+ if(!undoing) txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, txt_get_span(text->lines.first, *linep), old, txt_get_span(text->lines.first, *linep), (unsigned short)*charp);
+}
+
+void txt_move_bof (Text *text, short sel)
+{
+ TextLine **linep;
+ int *charp, old;
+
+ if (!text) return;
+ if(sel) txt_curs_sel(text, &linep, &charp);
+ else txt_curs_cur(text, &linep, &charp);
+ if (!*linep) return;
+ old= *charp;
+
+ *linep= text->lines.first;
+ *charp= 0;
+
+ if(!sel) txt_pop_sel(text);
+ if(!undoing) txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, txt_get_span(text->lines.first, *linep), old, txt_get_span(text->lines.first, *linep), (unsigned short)*charp);
+}
+
+void txt_move_eof (Text *text, short sel)
+{
+ TextLine **linep;
+ int *charp, old;
+
+ if (!text) return;
+ if(sel) txt_curs_sel(text, &linep, &charp);
+ else txt_curs_cur(text, &linep, &charp);
+ if (!*linep) return;
+ old= *charp;
+
+ *linep= text->lines.last;
+ *charp= (*linep)->len;
+
+ if(!sel) txt_pop_sel(text);
+ if(!undoing) txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, txt_get_span(text->lines.first, *linep), old, txt_get_span(text->lines.first, *linep), (unsigned short)*charp);
+}
+
+void txt_move_toline (Text *text, unsigned int line, short sel)
+{
+ TextLine **linep, *oldl;
+ int *charp, oldc;
+ unsigned int i;
+
+ if (!text) return;
+ if(sel) txt_curs_sel(text, &linep, &charp);
+ else txt_curs_cur(text, &linep, &charp);
+ if (!*linep) return;
+ oldc= *charp;
+ oldl= *linep;
+
+ *linep= text->lines.first;
+ for (i=0; i<line; i++) {
+ if ((*linep)->next) *linep= (*linep)->next;
+ else break;
+ }
+ *charp= 0;
+
+ if(!sel) txt_pop_sel(text);
+ if(!undoing) txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, txt_get_span(text->lines.first, oldl), oldc, txt_get_span(text->lines.first, *linep), (unsigned short)*charp);
+}
+
+/****************************/
+/* Text selection functions */
+/****************************/
+
+static void txt_curs_swap (Text *text)
+{
+ TextLine *tmpl;
+ int tmpc;
+
+ tmpl= text->curl;
+ text->curl= text->sell;
+ text->sell= tmpl;
+
+ tmpc= text->curc;
+ text->curc= text->selc;
+ text->selc= tmpc;
+
+ if(!undoing) txt_undo_add_op(text, UNDO_SWAP);
+}
+
+static void txt_pop_first (Text *text)
+{
+
+ if (txt_get_span(text->curl, text->sell)<0 ||
+ (text->curl==text->sell && text->curc>text->selc)) {
+ txt_curs_swap(text);
+ }
+
+ if(!undoing) txt_undo_add_toop(text, UNDO_STO,
+ txt_get_span(text->lines.first, text->sell),
+ text->selc,
+ txt_get_span(text->lines.first, text->curl),
+ text->curc);
+
+ txt_pop_sel(text);
+}
+
+static void txt_pop_last (Text *text)
+{
+ if (txt_get_span(text->curl, text->sell)>0 ||
+ (text->curl==text->sell && text->curc<text->selc)) {
+ txt_curs_swap(text);
+ }
+
+ if(!undoing) txt_undo_add_toop(text, UNDO_STO,
+ txt_get_span(text->lines.first, text->sell),
+ text->selc,
+ txt_get_span(text->lines.first, text->curl),
+ text->curc);
+
+ txt_pop_sel(text);
+}
+
+/* never used: CVS 1.19 */
+/* static void txt_pop_selr (Text *text) */
+
+void txt_pop_sel (Text *text)
+{
+ text->sell= text->curl;
+ text->selc= text->curc;
+}
+
+void txt_order_cursors(Text *text)
+{
+ if (!text) return;
+ if (!text->curl) return;
+ if (!text->sell) return;
+
+ /* Flip so text->curl is before text->sell */
+ if (txt_get_span(text->curl, text->sell)<0 ||
+ (text->curl==text->sell && text->curc>text->selc))
+ txt_curs_swap(text);
+}
+
+int txt_has_sel(Text *text)
+{
+ return ((text->curl!=text->sell) || (text->curc!=text->selc));
+}
+
+static void txt_delete_sel (Text *text)
+{
+ TextLine *tmpl;
+ char *buf;
+
+ if (!text) return;
+ if (!text->curl) return;
+ if (!text->sell) return;
+
+ if (!txt_has_sel(text)) return;
+
+ txt_order_cursors(text);
+
+ if(!undoing) {
+ buf= txt_sel_to_buf(text);
+ txt_undo_add_block(text, UNDO_DBLOCK, buf);
+ MEM_freeN(buf);
+ }
+
+ buf= MEM_mallocN(text->curc+(text->sell->len - text->selc)+1, "textline_string");
+
+ strncpy(buf, text->curl->line, text->curc);
+ strcpy(buf+text->curc, text->sell->line + text->selc);
+ buf[text->curc+(text->sell->len - text->selc)]=0;
+
+ make_new_line(text->curl, buf);
+
+ tmpl= text->sell;
+ while (tmpl != text->curl) {
+ tmpl= tmpl->prev;
+ if (!tmpl) break;
+
+ txt_delete_line(text, tmpl->next);
+ }
+
+ text->sell= text->curl;
+ text->selc= text->curc;
+}
+
+void txt_sel_all (Text *text)
+{
+ if (!text) return;
+
+ text->curl= text->lines.first;
+ text->curc= 0;
+
+ text->sell= text->lines.last;
+ text->selc= text->sell->len;
+}
+
+void txt_sel_line (Text *text)
+{
+ if (!text) return;
+ if (!text->curl) return;
+
+ text->curc= 0;
+ text->sell= text->curl;
+ text->selc= text->sell->len;
+}
+
+/***************************/
+/* Cut and paste functions */
+/***************************/
+
+void txt_print_cutbuffer (void)
+{
+ printf ("Cut buffer\n--\n%s\n--\n", txt_cut_buffer);
+}
+
+char *txt_to_buf (Text *text)
+{
+ int length;
+ TextLine *tmp, *linef, *linel;
+ int charf, charl;
+ char *buf;
+
+ if (!text) return NULL;
+ if (!text->curl) return NULL;
+ if (!text->sell) return NULL;
+
+ linef= text->lines.first;
+ charf= 0;
+
+ linel= text->lines.last;
+ charl= linel->len;
+
+ if (linef == text->lines.last) {
+ length= charl-charf;
+
+ buf= MEM_mallocN(length+2, "text buffer");
+
+ BLI_strncpy(buf, linef->line + charf, length+1);
+ buf[length]=0;
+ } else {
+ length= linef->len - charf;
+ length+= charl;
+ length+= 2; /* For the 2 '\n' */
+
+ tmp= linef->next;
+ while (tmp && tmp!= linel) {
+ length+= tmp->len+1;
+ tmp= tmp->next;
+ }
+
+ buf= MEM_mallocN(length+1, "cut buffer");
+
+ strncpy(buf, linef->line + charf, linef->len-charf);
+ length= linef->len - charf;
+
+ buf[length++]='\n';
+
+ tmp= linef->next;
+ while (tmp && tmp!=linel) {
+ strncpy(buf+length, tmp->line, tmp->len);
+ length+= tmp->len;
+
+ buf[length++]='\n';
+
+ tmp= tmp->next;
+ }
+ strncpy(buf+length, linel->line, charl);
+ length+= charl;
+
+ /* python compiler wants an empty end line */
+ buf[length++]='\n';
+ buf[length]=0;
+ }
+
+ return buf;
+}
+
+int txt_find_string(Text *text, char *findstr)
+{
+ TextLine *tl, *startl;
+ char *s= NULL;
+
+ if (!text || !text->curl || !text->sell) return 0;
+
+ txt_order_cursors(text);
+
+ tl= startl= text->sell;
+
+ s= strstr(&tl->line[text->selc], findstr);
+ while (!s) {
+ tl= tl->next;
+ if (!tl)
+ tl= text->lines.first;
+
+ s= strstr(tl->line, findstr);
+ if (tl==startl)
+ break;
+ }
+
+ if (s) {
+ text->curl= text->sell= tl;
+ text->curc= (int) (s-tl->line);
+ text->selc= text->curc + strlen(findstr);
+
+ return 1;
+ } else
+ return 0;
+}
+
+void txt_cut_sel (Text *text)
+{
+ txt_copy_sel(text);
+
+ txt_delete_sel(text);
+}
+
+char *txt_sel_to_buf (Text *text)
+{
+ char *buf;
+ int length=0;
+ TextLine *tmp, *linef, *linel;
+ int charf, charl;
+
+ if (!text) return NULL;
+ if (!text->curl) return NULL;
+ if (!text->sell) return NULL;
+
+ if (text->curl==text->sell) {
+ linef= linel= text->curl;
+
+ if (text->curc < text->selc) {
+ charf= text->curc;
+ charl= text->selc;
+ } else{
+ charf= text->selc;
+ charl= text->curc;
+ }
+ } else if (txt_get_span(text->curl, text->sell)<0) {
+ linef= text->sell;
+ linel= text->curl;
+
+ charf= text->selc;
+ charl= text->curc;
+ } else {
+ linef= text->curl;
+ linel= text->sell;
+
+ charf= text->curc;
+ charl= text->selc;
+ }
+
+ if (linef == linel) {
+ length= charl-charf;
+
+ buf= MEM_mallocN(length+1, "sel buffer");
+
+ BLI_strncpy(buf, linef->line + charf, length+1);
+ } else {
+ length+= linef->len - charf;
+ length+= charl;
+ length++; /* For the '\n' */
+
+ tmp= linef->next;
+ while (tmp && tmp!= linel) {
+ length+= tmp->len+1;
+ tmp= tmp->next;
+ }
+
+ buf= MEM_mallocN(length+1, "sel buffer");
+
+ strncpy(buf, linef->line+ charf, linef->len-charf);
+ length= linef->len-charf;
+
+ buf[length++]='\n';
+
+ tmp= linef->next;
+ while (tmp && tmp!=linel) {
+ strncpy(buf+length, tmp->line, tmp->len);
+ length+= tmp->len;
+
+ buf[length++]='\n';
+
+ tmp= tmp->next;
+ }
+ strncpy(buf+length, linel->line, charl);
+ length+= charl;
+
+ buf[length]=0;
+ }
+
+ return buf;
+}
+
+void txt_copy_sel (Text *text)
+{
+ int length=0;
+ TextLine *tmp, *linef, *linel;
+ int charf, charl;
+
+ if (!text) return;
+ if (!text->curl) return;
+ if (!text->sell) return;
+
+ if (!txt_has_sel(text)) return;
+
+ if (txt_cut_buffer) MEM_freeN(txt_cut_buffer);
+ txt_cut_buffer= NULL;
+
+ if (text->curl==text->sell) {
+ linef= linel= text->curl;
+
+ if (text->curc < text->selc) {
+ charf= text->curc;
+ charl= text->selc;
+ } else{
+ charf= text->selc;
+ charl= text->curc;
+ }
+ } else if (txt_get_span(text->curl, text->sell)<0) {
+ linef= text->sell;
+ linel= text->curl;
+
+ charf= text->selc;
+ charl= text->curc;
+ } else {
+ linef= text->curl;
+ linel= text->sell;
+
+ charf= text->curc;
+ charl= text->selc;
+ }
+
+ if (linef == linel) {
+ length= charl-charf;
+
+ txt_cut_buffer= MEM_mallocN(length+1, "cut buffera");
+
+ BLI_strncpy(txt_cut_buffer, linef->line + charf, length+1);
+ } else {
+ length+= linef->len - charf;
+ length+= charl;
+ length++; /* For the '\n' */
+
+ tmp= linef->next;
+ while (tmp && tmp!= linel) {
+ length+= tmp->len+1;
+ tmp= tmp->next;
+ }
+
+ txt_cut_buffer= MEM_mallocN(length+1, "cut bufferb");
+
+ strncpy(txt_cut_buffer, linef->line+ charf, linef->len-charf);
+ length= linef->len-charf;
+
+ txt_cut_buffer[length++]='\n';
+
+ tmp= linef->next;
+ while (tmp && tmp!=linel) {
+ strncpy(txt_cut_buffer+length, tmp->line, tmp->len);
+ length+= tmp->len;
+
+ txt_cut_buffer[length++]='\n';
+
+ tmp= tmp->next;
+ }
+ strncpy(txt_cut_buffer+length, linel->line, charl);
+ length+= charl;
+
+ txt_cut_buffer[length]=0;
+ }
+}
+
+void txt_insert_buf(Text *text, char *in_buffer)
+{
+ int i=0, l=0, j, u, len;
+ TextLine *add;
+
+ if (!text) return;
+ if (!in_buffer) return;
+
+ txt_delete_sel(text);
+
+ if(!undoing) txt_undo_add_block (text, UNDO_IBLOCK, in_buffer);
+
+ u= undoing;
+ undoing= 1;
+
+ /* Read the first line (or as close as possible */
+ while (in_buffer[i] && in_buffer[i]!='\n') {
+ txt_add_char(text, in_buffer[i]);
+ i++;
+ }
+
+ if (in_buffer[i]=='\n') txt_split_curline(text);
+ else { undoing = u; return; }
+ i++;
+
+ /* Read as many full lines as we can */
+ len= strlen(in_buffer);
+
+ while (i<len) {
+ l=0;
+
+ while (in_buffer[i] && in_buffer[i]!='\n') {
+ i++; l++;
+ }
+
+ if(in_buffer[i]=='\n') {
+ add= txt_new_linen(in_buffer +(i-l), l);
+ BLI_insertlinkbefore(&text->lines, text->curl, add);
+ i++;
+ } else {
+ for (j= i-l; j<i && j<(int)strlen(in_buffer); j++) {
+ txt_add_char(text, in_buffer[j]);
+ }
+ break;
+ }
+ }
+
+ undoing= u;
+}
+
+void txt_free_cut_buffer(void)
+{
+ if (txt_cut_buffer) MEM_freeN(txt_cut_buffer);
+}
+
+void txt_paste(Text *text)
+{
+ txt_insert_buf(text, txt_cut_buffer);
+}
+
+/******************/
+/* Undo functions */
+/******************/
+
+#define MAX_UNDO_TEST(x) \
+ while (text->undo_pos+x >= text->undo_len) { \
+ if(text->undo_len*2 > TXT_MAX_UNDO) { \
+ error("Undo limit reached, buffer cleared\n"); \
+ MEM_freeN(text->undo_buf); \
+ text->undo_len= TXT_INIT_UNDO; \
+ text->undo_buf= MEM_mallocN(text->undo_len, "undo buf"); \
+ text->undo_pos=-1; \
+ return; \
+ } else { \
+ void *tmp= text->undo_buf; \
+ text->undo_buf= MEM_callocN(text->undo_len*2, "undo buf"); \
+ memcpy(text->undo_buf, tmp, text->undo_len); \
+ text->undo_len*=2; \
+ MEM_freeN(tmp); \
+ } \
+ }
+
+static void dump_buffer(Text *text) {
+ int i= 0;
+
+ while (i++<text->undo_pos) printf("%d: %d %c\n", i, text->undo_buf[i], text->undo_buf[i]);
+}
+
+void txt_print_undo(Text *text)
+{
+ int i= 0;
+ int op;
+ char *ops;
+ int linep, charp;
+
+ dump_buffer(text);
+
+ printf ("---< Undo Buffer >---\n");
+
+ printf ("UndoPosition is %d\n", text->undo_pos);
+
+ while (i<=text->undo_pos) {
+ op= text->undo_buf[i];
+
+ if (op==UNDO_CLEFT) {
+ ops= "Cursor left";
+ } else if (op==UNDO_CRIGHT) {
+ ops= "Cursor right";
+ } else if (op==UNDO_CUP) {
+ ops= "Cursor up";
+ } else if (op==UNDO_CDOWN) {
+ ops= "Cursor down";
+ } else if (op==UNDO_SLEFT) {
+ ops= "Selection left";
+ } else if (op==UNDO_SRIGHT) {
+ ops= "Selection right";
+ } else if (op==UNDO_SUP) {
+ ops= "Selection up";
+ } else if (op==UNDO_SDOWN) {
+ ops= "Selection down";
+ } else if (op==UNDO_STO) {
+ ops= "Selection ";
+ } else if (op==UNDO_CTO) {
+ ops= "Cursor ";
+ } else if (op==UNDO_INSERT) {
+ ops= "Insert";
+ } else if (op==UNDO_BS) {
+ ops= "Backspace";
+ } else if (op==UNDO_DEL) {
+ ops= "Delete";
+ } else if (op==UNDO_SWAP) {
+ ops= "Cursor swap";
+ } else if (op==UNDO_DBLOCK) {
+ ops= "Delete text block";
+ } else if (op==UNDO_IBLOCK) {
+ ops= "Insert text block";
+ } else {
+ ops= "Unknown";
+ }
+
+ printf ("Op (%o) at %d = %s", op, i, ops);
+ if (op==UNDO_INSERT || op==UNDO_BS || op==UNDO_DEL) {
+ i++;
+ printf (" - Char is %c", text->undo_buf[i]);
+ i++;
+ } else if (op==UNDO_STO || op==UNDO_CTO) {
+ i++;
+
+ charp= text->undo_buf[i]; i++;
+ charp= charp+(text->undo_buf[i]<<8); i++;
+
+ linep= text->undo_buf[i]; i++;
+ linep= linep+(text->undo_buf[i]<<8); i++;
+ linep= linep+(text->undo_buf[i]<<16); i++;
+ linep= linep+(text->undo_buf[i]<<24); i++;
+
+ printf ("to <%d, %d> ", linep, charp);
+
+ charp= text->undo_buf[i]; i++;
+ charp= charp+(text->undo_buf[i]<<8); i++;
+
+ linep= text->undo_buf[i]; i++;
+ linep= linep+(text->undo_buf[i]<<8); i++;
+ linep= linep+(text->undo_buf[i]<<16); i++;
+ linep= linep+(text->undo_buf[i]<<24); i++;
+
+ printf ("from <%d, %d>", linep, charp);
+ } else if (op==UNDO_DBLOCK || op==UNDO_IBLOCK) {
+ i++;
+
+ linep= text->undo_buf[i]; i++;
+ linep= linep+(text->undo_buf[i]<<8); i++;
+ linep= linep+(text->undo_buf[i]<<16); i++;
+ linep= linep+(text->undo_buf[i]<<24); i++;
+
+ printf (" (length %d) <", linep);
+
+ while (linep>0) {
+ putchar(text->undo_buf[i]);
+ linep--; i++;
+ }
+
+ linep= text->undo_buf[i]; i++;
+ linep= linep+(text->undo_buf[i]<<8); i++;
+ linep= linep+(text->undo_buf[i]<<16); i++;
+ linep= linep+(text->undo_buf[i]<<24); i++;
+ printf ("> (%d)", linep);
+ }
+
+ printf (" %d\n", i);
+ i++;
+ }
+}
+
+static void txt_undo_add_op(Text *text, int op)
+{
+ MAX_UNDO_TEST(2);
+
+ text->undo_pos++;
+ text->undo_buf[text->undo_pos]= op;
+ text->undo_buf[text->undo_pos+1]= 0;
+}
+
+static void txt_undo_add_block(Text *text, int op, char *buf)
+{
+ unsigned int length;
+
+ length= strlen(buf);
+
+ MAX_UNDO_TEST(length+11);
+
+ text->undo_pos++;
+ text->undo_buf[text->undo_pos]= op;
+
+ text->undo_pos++;
+ text->undo_buf[text->undo_pos]= (length)&0xff;
+ text->undo_pos++;
+ text->undo_buf[text->undo_pos]= (length>>8)&0xff;
+ text->undo_pos++;
+ text->undo_buf[text->undo_pos]= (length>>16)&0xff;
+ text->undo_pos++;
+ text->undo_buf[text->undo_pos]= (length>>24)&0xff;
+
+ text->undo_pos++;
+ strncpy(text->undo_buf+text->undo_pos, buf, length);
+ text->undo_pos+=length;
+
+ text->undo_buf[text->undo_pos]= (length)&0xff;
+ text->undo_pos++;
+ text->undo_buf[text->undo_pos]= (length>>8)&0xff;
+ text->undo_pos++;
+ text->undo_buf[text->undo_pos]= (length>>16)&0xff;
+ text->undo_pos++;
+ text->undo_buf[text->undo_pos]= (length>>24)&0xff;
+
+ text->undo_pos++;
+ text->undo_buf[text->undo_pos]= op;
+
+ text->undo_buf[text->undo_pos+1]= 0;
+}
+
+void txt_undo_add_toop(Text *text, int op, unsigned int froml, unsigned short fromc, unsigned int tol, unsigned short toc)
+{
+ MAX_UNDO_TEST(15);
+
+ if (froml==tol && fromc==toc) return;
+
+ text->undo_pos++;
+ text->undo_buf[text->undo_pos]= op;
+
+ text->undo_pos++;
+ text->undo_buf[text->undo_pos]= (fromc)&0xff;
+ text->undo_pos++;
+ text->undo_buf[text->undo_pos]= (fromc>>8)&0xff;
+
+ text->undo_pos++;
+ text->undo_buf[text->undo_pos]= (froml)&0xff;
+ text->undo_pos++;
+ text->undo_buf[text->undo_pos]= (froml>>8)&0xff;
+ text->undo_pos++;
+ text->undo_buf[text->undo_pos]= (froml>>16)&0xff;
+ text->undo_pos++;
+ text->undo_buf[text->undo_pos]= (froml>>24)&0xff;
+
+ text->undo_pos++;
+ text->undo_buf[text->undo_pos]= (toc)&0xff;
+ text->undo_pos++;
+ text->undo_buf[text->undo_pos]= (toc>>8)&0xff;
+
+ text->undo_pos++;
+ text->undo_buf[text->undo_pos]= (tol)&0xff;
+ text->undo_pos++;
+ text->undo_buf[text->undo_pos]= (tol>>8)&0xff;
+ text->undo_pos++;
+ text->undo_buf[text->undo_pos]= (tol>>16)&0xff;
+ text->undo_pos++;
+ text->undo_buf[text->undo_pos]= (tol>>24)&0xff;
+
+ text->undo_pos++;
+ text->undo_buf[text->undo_pos]= op;
+
+ text->undo_buf[text->undo_pos+1]= 0;
+}
+
+static void txt_undo_add_charop(Text *text, int op, char c)
+{
+ MAX_UNDO_TEST(4);
+
+ text->undo_pos++;
+ text->undo_buf[text->undo_pos]= op;
+ text->undo_pos++;
+ text->undo_buf[text->undo_pos]= c;
+ text->undo_pos++;
+ text->undo_buf[text->undo_pos]= op;
+ text->undo_buf[text->undo_pos+1]= 0;
+}
+
+void txt_do_undo(Text *text)
+{
+ int op= text->undo_buf[text->undo_pos], i;
+ unsigned int linep;
+ unsigned short charp;
+ TextLine *holdl;
+ int holdc, holdln;
+ char *buf;
+
+ if (text->undo_pos<0) {
+ return;
+ }
+
+ text->undo_pos--;
+
+ undoing= 1;
+
+ switch(op) {
+ case UNDO_CLEFT:
+ txt_move_right(text, 0);
+ break;
+
+ case UNDO_CRIGHT:
+ txt_move_left(text, 0);
+ break;
+
+ case UNDO_CUP:
+ txt_move_down(text, 0);
+ break;
+
+ case UNDO_CDOWN:
+ txt_move_up(text, 0);
+ break;
+
+ case UNDO_SLEFT:
+ txt_move_right(text, 1);
+ break;
+
+ case UNDO_SRIGHT:
+ txt_move_left(text, 1);
+ break;
+
+ case UNDO_SUP:
+ txt_move_down(text, 1);
+ break;
+
+ case UNDO_SDOWN:
+ txt_move_up(text, 1);
+ break;
+
+ case UNDO_CTO:
+ case UNDO_STO:
+ text->undo_pos--;
+ text->undo_pos--;
+ text->undo_pos--;
+ text->undo_pos--;
+
+ text->undo_pos--;
+ text->undo_pos--;
+
+ linep= text->undo_buf[text->undo_pos]; text->undo_pos--;
+ linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
+ linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
+ linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
+
+ charp= text->undo_buf[text->undo_pos]; text->undo_pos--;
+ charp= (charp<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
+
+ if (op==UNDO_CTO) {
+ txt_move_toline(text, linep, 0);
+ text->curc= charp;
+ txt_pop_sel(text);
+ } else {
+ txt_move_toline(text, linep, 1);
+ text->selc= charp;
+ }
+
+ text->undo_pos--;
+ break;
+
+ case UNDO_INSERT:
+ txt_backspace_char(text);
+ text->undo_pos--;
+ text->undo_pos--;
+ break;
+
+ case UNDO_BS:
+ txt_add_char(text, text->undo_buf[text->undo_pos]);
+ text->undo_pos--;
+ text->undo_pos--;
+ break;
+
+ case UNDO_DEL:
+ txt_add_char(text, text->undo_buf[text->undo_pos]);
+ txt_move_left(text, 0);
+ text->undo_pos--;
+ text->undo_pos--;
+ break;
+
+ case UNDO_SWAP:
+ txt_curs_swap(text);
+ txt_do_undo(text); /* swaps should appear transparent */
+ break;
+
+ case UNDO_DBLOCK:
+ linep= text->undo_buf[text->undo_pos]; text->undo_pos--;
+ linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
+ linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
+ linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
+
+ buf= MEM_mallocN(linep+1, "dblock buffer");
+ for (i=0; i < (int)linep; i++){
+ buf[(linep-1)-i]= text->undo_buf[text->undo_pos];
+ text->undo_pos--;
+ }
+ buf[i]= 0;
+
+ txt_curs_first(text, &holdl, &holdc);
+ holdln= txt_get_span(text->lines.first, holdl);
+
+ txt_insert_buf(text, buf);
+ MEM_freeN(buf);
+
+ text->curl= text->lines.first;
+ while (holdln>0) {
+ if(text->curl->next)
+ text->curl= text->curl->next;
+
+ holdln--;
+ }
+ text->curc= holdc;
+
+ linep= text->undo_buf[text->undo_pos]; text->undo_pos--;
+ linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
+ linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
+ linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
+
+ text->undo_pos--;
+
+ break;
+
+ case UNDO_IBLOCK:
+ linep= text->undo_buf[text->undo_pos]; text->undo_pos--;
+ linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
+ linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
+ linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
+
+ txt_delete_sel(text);
+ while (linep>0) {
+ txt_backspace_char(text);
+ text->undo_pos--;
+ linep--;
+ }
+
+ text->undo_pos--;
+ text->undo_pos--;
+ text->undo_pos--;
+ text->undo_pos--;
+
+ text->undo_pos--;
+
+ break;
+
+ default:
+ error("Undo buffer error - resetting");
+ text->undo_pos= -1;
+
+ break;
+ }
+
+ undoing= 0;
+}
+
+void txt_do_redo(Text *text)
+{
+ char op;
+ unsigned int linep;
+ unsigned short charp;
+ char *buf;
+
+ text->undo_pos++;
+ op= text->undo_buf[text->undo_pos];
+
+ if (!op) {
+ text->undo_pos--;
+ return;
+ }
+
+ undoing= 1;
+
+ switch(op) {
+ case UNDO_CLEFT:
+ txt_move_left(text, 0);
+ break;
+
+ case UNDO_CRIGHT:
+ txt_move_right(text, 0);
+ break;
+
+ case UNDO_CUP:
+ txt_move_up(text, 0);
+ break;
+
+ case UNDO_CDOWN:
+ txt_move_down(text, 0);
+ break;
+
+ case UNDO_SLEFT:
+ txt_move_left(text, 1);
+ break;
+
+ case UNDO_SRIGHT:
+ txt_move_right(text, 1);
+ break;
+
+ case UNDO_SUP:
+ txt_move_up(text, 1);
+ break;
+
+ case UNDO_SDOWN:
+ txt_move_down(text, 1);
+ break;
+
+ case UNDO_INSERT:
+ text->undo_pos++;
+ txt_add_char(text, text->undo_buf[text->undo_pos]);
+ text->undo_pos++;
+ break;
+
+ case UNDO_BS:
+ text->undo_pos++;
+ txt_backspace_char(text);
+ text->undo_pos++;
+ break;
+
+ case UNDO_DEL:
+ text->undo_pos++;
+ txt_delete_char(text);
+ text->undo_pos++;
+ break;
+
+ case UNDO_SWAP:
+ txt_curs_swap(text);
+ txt_do_undo(text); /* swaps should appear transparent a*/
+ break;
+
+ case UNDO_CTO:
+ case UNDO_STO:
+ text->undo_pos++;
+ text->undo_pos++;
+
+ text->undo_pos++;
+ text->undo_pos++;
+ text->undo_pos++;
+ text->undo_pos++;
+
+ text->undo_pos++;
+
+ charp= text->undo_buf[text->undo_pos];
+ text->undo_pos++;
+ charp= charp+(text->undo_buf[text->undo_pos]<<8);
+
+ text->undo_pos++;
+ linep= text->undo_buf[text->undo_pos]; text->undo_pos++;
+ linep= linep+(text->undo_buf[text->undo_pos]<<8); text->undo_pos++;
+ linep= linep+(text->undo_buf[text->undo_pos]<<16); text->undo_pos++;
+ linep= linep+(text->undo_buf[text->undo_pos]<<24); text->undo_pos++;
+
+ if (op==UNDO_CTO) {
+ txt_move_toline(text, linep, 0);
+ text->curc= charp;
+ txt_pop_sel(text);
+ } else {
+ txt_move_toline(text, linep, 1);
+ text->selc= charp;
+ }
+
+ break;
+
+ case UNDO_DBLOCK:
+ text->undo_pos++;
+ linep= text->undo_buf[text->undo_pos]; text->undo_pos++;
+ linep= linep+(text->undo_buf[text->undo_pos]<<8); text->undo_pos++;
+ linep= linep+(text->undo_buf[text->undo_pos]<<16); text->undo_pos++;
+ linep= linep+(text->undo_buf[text->undo_pos]<<24); text->undo_pos++;
+
+ txt_delete_sel(text);
+ text->undo_pos+=linep;
+
+ text->undo_pos++;
+ text->undo_pos++;
+ text->undo_pos++;
+ text->undo_pos++;
+
+ break;
+
+ case UNDO_IBLOCK:
+ text->undo_pos++;
+ linep= text->undo_buf[text->undo_pos]; text->undo_pos++;
+ linep= linep+(text->undo_buf[text->undo_pos]<<8); text->undo_pos++;
+ linep= linep+(text->undo_buf[text->undo_pos]<<16); text->undo_pos++;
+ linep= linep+(text->undo_buf[text->undo_pos]<<24); text->undo_pos++;
+
+ buf= MEM_mallocN(linep+1, "iblock buffer");
+ memcpy (buf, &text->undo_buf[text->undo_pos], linep);
+ text->undo_pos+= linep;
+ buf[linep]= 0;
+
+ txt_insert_buf(text, buf);
+ MEM_freeN(buf);
+
+ linep= text->undo_buf[text->undo_pos]; text->undo_pos++;
+ linep= linep+(text->undo_buf[text->undo_pos]<<8); text->undo_pos++;
+ linep= linep+(text->undo_buf[text->undo_pos]<<16); text->undo_pos++;
+ linep= linep+(text->undo_buf[text->undo_pos]<<24); text->undo_pos++;
+
+ break;
+
+ default:
+ error("Undo buffer error - resetting");
+ text->undo_pos= -1;
+
+ break;
+ }
+
+ undoing= 0;
+}
+
+/**************************/
+/* Line editing functions */
+/**************************/
+
+void txt_split_curline (Text *text) {
+ TextLine *ins;
+ char *left, *right;
+
+ if (!text) return;
+ if (!text->curl) return;
+
+ txt_delete_sel(text);
+
+ /* Make the two half strings */
+
+ left= MEM_mallocN(text->curc+1, "textline_string");
+ if (text->curc) memcpy(left, text->curl->line, text->curc);
+ left[text->curc]=0;
+
+ right= MEM_mallocN(text->curl->len - text->curc+1, "textline_string");
+ if (text->curl->len - text->curc) memcpy(right, text->curl->line+text->curc, text->curl->len-text->curc);
+ right[text->curl->len - text->curc]=0;
+
+ MEM_freeN(text->curl->line);
+
+ /* Make the new TextLine */
+
+ ins= MEM_mallocN(sizeof(TextLine), "textline");
+ ins->line= left;
+ ins->len= text->curc;
+
+ text->curl->line= right;
+ text->curl->len= text->curl->len - text->curc;
+
+ BLI_insertlinkbefore(&text->lines, text->curl, ins);
+
+ text->curc=0;
+
+ txt_make_dirty(text);
+ txt_clean_text(text);
+
+ txt_pop_sel(text);
+ if(!undoing) txt_undo_add_charop(text, UNDO_INSERT, '\n');
+}
+
+static void txt_delete_line (Text *text, TextLine *line)
+{
+ if (!text) return;
+ if (!text->curl) return;
+
+ BLI_remlink (&text->lines, line);
+
+ if (line->line) MEM_freeN(line->line);
+ MEM_freeN(line);
+
+ txt_make_dirty(text);
+ txt_clean_text(text);
+}
+
+static void txt_combine_lines (Text *text, TextLine *linea, TextLine *lineb)
+{
+ char *tmp;
+
+ if (!text) return;
+
+ if(!linea || !lineb) return;
+
+ tmp= MEM_mallocN(linea->len+lineb->len+1, "textline_string");
+
+ strcpy(tmp, linea->line);
+ strcat(tmp, lineb->line);
+
+ make_new_line(linea, tmp);
+
+ txt_delete_line(text, lineb);
+
+ txt_make_dirty(text);
+ txt_clean_text(text);
+}
+
+void txt_delete_char (Text *text)
+{
+ char c='\n';
+
+ if (!text) return;
+ if (!text->curl) return;
+
+ if (txt_has_sel(text)) {
+ txt_delete_sel(text);
+ return;
+ }
+
+ if (text->curc== text->curl->len) { /* Appending two lines */
+ if (text->curl->next) {
+ txt_combine_lines(text, text->curl, text->curl->next);
+ txt_pop_sel(text);
+ }
+ } else { /* Just deleting a char */
+ int i= text->curc;
+
+ c= text->curl->line[i];
+ while(i< text->curl->len) {
+ text->curl->line[i]= text->curl->line[i+1];
+ i++;
+ }
+ text->curl->len--;
+
+ txt_pop_sel(text);
+ }
+
+ txt_make_dirty(text);
+ txt_clean_text(text);
+
+ if(!undoing) txt_undo_add_charop(text, UNDO_DEL, c);
+}
+
+void txt_backspace_char (Text *text) {
+ char c='\n';
+
+ if (!text) return;
+ if (!text->curl) return;
+
+ if (txt_has_sel(text)) {
+ txt_delete_sel(text);
+ return;
+ }
+
+ if (text->curc==0) { /* Appending two lines */
+ if (text->curl->prev) {
+ text->curl= text->curl->prev;
+ text->curc= text->curl->len;
+
+ txt_combine_lines(text, text->curl, text->curl->next);
+ txt_pop_sel(text);
+ }
+ } else { /* Just backspacing a char */
+ int i= text->curc-1;
+
+ c= text->curl->line[i];
+ while(i< text->curl->len) {
+ text->curl->line[i]= text->curl->line[i+1];
+ i++;
+ }
+ text->curl->len--;
+ text->curc--;
+
+ txt_pop_sel(text);
+ }
+
+ txt_make_dirty(text);
+ txt_clean_text(text);
+
+ if(!undoing) txt_undo_add_charop(text, UNDO_BS, c);
+}
+
+int txt_add_char (Text *text, char add) {
+ int len;
+ char *tmp;
+
+ if (!text) return 0;
+ if (!text->curl) return 0;
+
+ if (add=='\n') {
+ txt_split_curline(text);
+ return 1;
+ }
+
+ if(txt_illegal_char(add)) return 0;
+
+ txt_delete_sel(text);
+
+ tmp= MEM_mallocN(text->curl->len+2, "textline_string");
+
+ if(text->curc) memcpy(tmp, text->curl->line, text->curc);
+ tmp[text->curc]= add;
+
+ len= text->curl->len - text->curc;
+ if(len>0) memcpy(tmp+text->curc+1, text->curl->line+text->curc, len);
+ tmp[text->curl->len+1]=0;
+
+ make_new_line(text->curl, tmp);
+
+ text->curc++;
+
+ txt_pop_sel(text);
+
+ txt_make_dirty(text);
+ txt_clean_text(text);
+
+ if(!undoing) txt_undo_add_charop(text, UNDO_INSERT, add);
+ return 1;
+}
diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c
new file mode 100644
index 00000000000..eed8a39d6ce
--- /dev/null
+++ b/source/blender/blenkernel/intern/texture.c
@@ -0,0 +1,2320 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 <string.h>
+#include <math.h>
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "PIL_dynlib.h"
+
+#include "MTC_matrixops.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_rand.h"
+
+#include "DNA_texture_types.h"
+#include "DNA_key_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_material_types.h"
+#include "DNA_image_types.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "BKE_osa_types.h"
+#include "BKE_plugin_types.h"
+
+#include "BKE_bad_level_calls.h"
+#include "BKE_utildefines.h"
+
+#include "BKE_global.h"
+#include "BKE_main.h"
+
+#include "BKE_library.h"
+#include "BKE_image.h"
+#include "BKE_texture.h"
+#include "BKE_key.h"
+#include "BKE_ipo.h"
+
+
+/* These vars form the texture channel */
+float Tin, Tr, Tg, Tb, Ta, Txtra;
+extern int Talpha;
+
+
+/* ------------------------------------------------------------------------- */
+
+/* Alle support voor plugin textures: */
+int test_dlerr(const char *name, const char *symbol)
+{
+ char *err;
+
+ err= PIL_dynlib_get_error_as_string(NULL);
+ if(err) {
+ printf("var1: %s, var2: %s, var3: %s\n", name, symbol, err);
+ return 1;
+ }
+
+ return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+
+void open_plugin_tex(PluginTex *pit)
+{
+ int (*version)(void);
+
+ /* init all the happy variables */
+ pit->doit= 0;
+ pit->pname= 0;
+ pit->stnames= 0;
+ pit->varstr= 0;
+ pit->result= 0;
+ pit->cfra= 0;
+ pit->version= 0;
+
+ /* clear the error list */
+ PIL_dynlib_get_error_as_string(NULL);
+
+ /* no PIL_dynlib_close! multiple opened plugins... */
+ /* if(pit->handle) PIL_dynlib_close(pit->handle); */
+ /* pit->handle= 0; */
+
+ /* open the needed object */
+ pit->handle= PIL_dynlib_open(pit->name);
+ if(test_dlerr(pit->name, pit->name)) return;
+
+ if (pit->handle != 0) {
+ /* find the address of the version function */
+ version= (int (*)(void)) PIL_dynlib_find_symbol(pit->handle, "plugin_tex_getversion");
+ if (test_dlerr(pit->name, "plugin_tex_getversion")) return;
+
+ if (version != 0) {
+ pit->version= version();
+ if (pit->version==2 || pit->version==3) {
+ int (*info_func)(PluginInfo *);
+ PluginInfo *info= (PluginInfo*) MEM_mallocN(sizeof(PluginInfo), "plugin_info");
+
+ info_func= (int (*)(PluginInfo *))PIL_dynlib_find_symbol(pit->handle, "plugin_getinfo");
+ if (!test_dlerr(pit->name, "plugin_getinfo")) {
+
+ info_func(info);
+
+ pit->doit= (int(*)(void)) info->tex_doit;
+ pit->callback= (void(*)(unsigned short)) info->callback;
+ pit->stypes= info->stypes;
+ pit->vars= info->nvars;
+ pit->pname= info->name;
+ pit->stnames= info->snames;
+ pit->varstr= info->varstr;
+ pit->result= info->result;
+ pit->cfra= info->cfra;
+ if (info->init) info->init();
+ }
+ MEM_freeN(info);
+ } else {
+ printf ("Plugin returned unrecognized version number\n");
+ return;
+ }
+ }
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
+PluginTex *add_plugin_tex(char *str)
+{
+ PluginTex *pit;
+ VarStruct *varstr;
+ int a;
+
+ pit= MEM_callocN(sizeof(PluginTex), "plugintex");
+
+ strcpy(pit->name, str);
+ open_plugin_tex(pit);
+
+ if(pit->doit==0) {
+ if(pit->handle==0) error("no plugin: %s", str);
+ else error("in plugin: %s", str);
+ MEM_freeN(pit);
+ return NULL;
+ }
+
+ varstr= pit->varstr;
+ for(a=0; a<pit->vars; a++, varstr++) {
+ if( (varstr->type & FLO)==FLO)
+ pit->data[a]= varstr->def;
+ else if( (varstr->type & INT)==INT)
+ *((int *)(pit->data+a))= (int) varstr->def;
+ }
+
+ return pit;
+}
+
+/* ------------------------------------------------------------------------- */
+
+void free_plugin_tex(PluginTex *pit)
+{
+ if(pit==0) return;
+
+ /* geen PIL_dynlib_close: dezelfde plugin kan meerdere keren geopend zijn: 1 handle */
+ MEM_freeN(pit);
+}
+
+/* ****************** COLORBAND ******************* */
+
+ColorBand *add_colorband()
+{
+ ColorBand *coba;
+ int a;
+
+ coba= MEM_callocN( sizeof(ColorBand), "colorband");
+
+ coba->data[0].r= 0.0;
+ coba->data[0].g= 0.0;
+ coba->data[0].b= 0.0;
+ coba->data[0].a= 0.0;
+ coba->data[0].pos= 0.0;
+
+ coba->data[1].r= 0.0;
+ coba->data[1].g= 1.0;
+ coba->data[1].b= 1.0;
+ coba->data[1].a= 1.0;
+ coba->data[1].pos= 1.0;
+
+ for(a=2; a<MAXCOLORBAND; a++) {
+ coba->data[a].r= 0.5;
+ coba->data[a].g= 0.5;
+ coba->data[a].b= 0.5;
+ coba->data[a].a= 1.0;
+ coba->data[a].pos= 0.5;
+ }
+
+ coba->tot= 2;
+
+ return coba;
+}
+
+/* ------------------------------------------------------------------------- */
+
+int do_colorband(ColorBand *coba)
+{
+ CBData *cbd1, *cbd2, *cbd0, *cbd3;
+ float fac, mfac, t[4];
+ int a;
+
+ if(coba->tot==0) return 0;
+ Talpha= 1;
+
+ cbd1= coba->data;
+
+ if(Tin <= cbd1->pos) { /* helemaal links */
+ Tr= cbd1->r;
+ Tg= cbd1->g;
+ Tb= cbd1->b;
+ Ta= cbd1->a;
+ }
+ else {
+ /* we zoeken de eerste pos > Tin */
+
+ for(a=0; a<coba->tot; a++, cbd1++) if(cbd1->pos >= Tin) break;
+
+ if(a==coba->tot) { /* helemaal rechts */
+ cbd1--;
+ Tr= cbd1->r;
+ Tg= cbd1->g;
+ Tb= cbd1->b;
+ Ta= cbd1->a;
+ }
+ else {
+ cbd2= cbd1-1;
+ fac= (Tin-cbd1->pos)/(cbd2->pos-cbd1->pos);
+
+ if(coba->ipotype==2) {
+ /* ipo van r naar l: 3 2 1 0 */
+
+ if(a>=coba->tot-1) cbd0= cbd1;
+ else cbd0= cbd1+1;
+ if(a<2) cbd3= cbd2;
+ else cbd3= cbd2-1;
+
+ set_four_ipo(fac, t, KEY_BSPLINE);
+
+ Tr= t[3]*cbd3->r +t[2]*cbd2->r +t[1]*cbd1->r +t[0]*cbd0->r;
+ Tg= t[3]*cbd3->g +t[2]*cbd2->g +t[1]*cbd1->g +t[0]*cbd0->g;
+ Tb= t[3]*cbd3->b +t[2]*cbd2->b +t[1]*cbd1->b +t[0]*cbd0->b;
+ Ta= t[3]*cbd3->a +t[2]*cbd2->a +t[1]*cbd1->a +t[0]*cbd0->a;
+ CLAMP(Tr, 0.0, 1.0);
+ CLAMP(Tg, 0.0, 1.0);
+ CLAMP(Tb, 0.0, 1.0);
+ CLAMP(Ta, 0.0, 1.0);
+ }
+ else {
+
+ if(coba->ipotype==1) { /* EASE */
+ mfac= fac*fac;
+ fac= 3.0f*mfac-2.0f*mfac*fac;
+ }
+ mfac= 1.0f-fac;
+
+ Tr= mfac*cbd1->r + fac*cbd2->r;
+ Tg= mfac*cbd1->g + fac*cbd2->g;
+ Tb= mfac*cbd1->b + fac*cbd2->b;
+ Ta= mfac*cbd1->a + fac*cbd2->a;
+ }
+ }
+ }
+ return 1; /* OK */
+}
+
+/* ******************* TEX ************************ */
+
+void free_texture(Tex *tex)
+{
+ free_plugin_tex(tex->plugin);
+ if(tex->coba) MEM_freeN(tex->coba);
+ if(tex->env) RE_free_envmap(tex->env);
+}
+
+/* ------------------------------------------------------------------------- */
+
+void default_tex(Tex *tex)
+{
+ tex->stype= 0;
+ tex->imaflag= TEX_INTERPOL+TEX_MIPMAP;
+ tex->extend= TEX_REPEAT;
+ tex->cropxmin= tex->cropymin= 0.0;
+ tex->cropxmax= tex->cropymax= 1.0;
+ tex->xrepeat= tex->yrepeat= 1;
+ tex->fie_ima= 2;
+ tex->sfra= 1;
+ tex->frames= 0;
+ tex->offset= 0;
+ tex->noisesize= 0.25;
+ tex->noisedepth= 2;
+ tex->turbul= 5.0;
+ tex->bright= 1.0;
+ tex->contrast= tex->filtersize= 1.0;
+ tex->rfac= 1.0;
+ tex->gfac= 1.0;
+ tex->bfac= 1.0;
+
+}
+
+/* ------------------------------------------------------------------------- */
+
+Tex *add_texture(char *name)
+{
+ Tex *tex;
+
+ tex= alloc_libblock(&G.main->tex, ID_TE, name);
+
+ default_tex(tex);
+
+ return tex;
+}
+
+/* ------------------------------------------------------------------------- */
+
+void default_mtex(MTex *mtex)
+{
+ mtex->texco= TEXCO_ORCO;
+ mtex->mapto= MAP_COL;
+ mtex->object= 0;
+ mtex->projx= PROJ_X;
+ mtex->projy= PROJ_Y;
+ mtex->projz= PROJ_Z;
+ mtex->mapping= MTEX_FLAT;
+ mtex->ofs[0]= 0.0;
+ mtex->ofs[1]= 0.0;
+ mtex->ofs[2]= 0.0;
+ mtex->size[0]= 1.0;
+ mtex->size[1]= 1.0;
+ mtex->size[2]= 1.0;
+ mtex->tex= 0;
+ mtex->texflag= 0;
+ mtex->colormodel= 0;
+ mtex->r= 1.0;
+ mtex->g= 0.0;
+ mtex->b= 1.0;
+ mtex->k= 1.0;
+ mtex->def_var= 1.0;
+ mtex->blendtype= MTEX_BLEND;
+ mtex->colfac= 1.0;
+ mtex->norfac= 0.5;
+ mtex->varfac= 1.0;
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+MTex *add_mtex()
+{
+ MTex *mtex;
+
+ mtex= MEM_callocN(sizeof(MTex), "add_mtex");
+
+ default_mtex(mtex);
+
+ return mtex;
+}
+
+/* ------------------------------------------------------------------------- */
+
+Tex *copy_texture(Tex *tex)
+{
+ Tex *texn;
+
+ texn= copy_libblock(tex);
+ if(texn->type==TEX_IMAGE) id_us_plus((ID *)texn->ima);
+ else texn->ima= 0;
+
+ if(texn->plugin) {
+ texn->plugin= MEM_dupallocN(texn->plugin);
+ open_plugin_tex(texn->plugin);
+ }
+
+ if(texn->coba) texn->coba= MEM_dupallocN(texn->coba);
+ if(texn->env) texn->env= RE_copy_envmap(texn->env);
+
+ return texn;
+}
+
+/* ------------------------------------------------------------------------- */
+
+void make_local_texture(Tex *tex)
+{
+ Tex *texn;
+ Material *ma;
+ World *wrld;
+ Lamp *la;
+ int a, local=0, lib=0;
+
+ /* - zijn er alleen lib users: niet doen
+ * - zijn er alleen locale users: flag zetten
+ * - mixed: copy
+ */
+
+ if(tex->id.lib==0) return;
+
+ /* speciaal geval: ima altijd meteen lokaal */
+ if(tex->ima) {
+ tex->ima->id.lib= 0;
+ tex->ima->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)tex->ima, 0);
+ }
+
+ if(tex->id.us==1) {
+ tex->id.lib= 0;
+ tex->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)tex, 0);
+
+ return;
+ }
+
+ ma= G.main->mat.first;
+ while(ma) {
+ for(a=0; a<8; a++) {
+ if(ma->mtex[a] && ma->mtex[a]->tex==tex) {
+ if(ma->id.lib) lib= 1;
+ else local= 1;
+ }
+ }
+ ma= ma->id.next;
+ }
+ la= G.main->lamp.first;
+ while(la) {
+ for(a=0; a<8; a++) {
+ if(la->mtex[a] && la->mtex[a]->tex==tex) {
+ if(la->id.lib) lib= 1;
+ else local= 1;
+ }
+ }
+ la= la->id.next;
+ }
+ wrld= G.main->world.first;
+ while(wrld) {
+ for(a=0; a<8; a++) {
+ if(wrld->mtex[a] && wrld->mtex[a]->tex==tex) {
+ if(wrld->id.lib) lib= 1;
+ else local= 1;
+ }
+ }
+ wrld= wrld->id.next;
+ }
+
+ if(local && lib==0) {
+ tex->id.lib= 0;
+ tex->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)tex, 0);
+ }
+ else if(local && lib) {
+ texn= copy_texture(tex);
+ texn->id.us= 0;
+
+ ma= G.main->mat.first;
+ while(ma) {
+ for(a=0; a<8; a++) {
+ if(ma->mtex[a] && ma->mtex[a]->tex==tex) {
+ if(ma->id.lib==0) {
+ ma->mtex[a]->tex= texn;
+ texn->id.us++;
+ tex->id.us--;
+ }
+ }
+ }
+ ma= ma->id.next;
+ }
+ la= G.main->lamp.first;
+ while(la) {
+ for(a=0; a<8; a++) {
+ if(la->mtex[a] && la->mtex[a]->tex==tex) {
+ if(la->id.lib==0) {
+ la->mtex[a]->tex= texn;
+ texn->id.us++;
+ tex->id.us--;
+ }
+ }
+ }
+ la= la->id.next;
+ }
+ wrld= G.main->world.first;
+ while(wrld) {
+ for(a=0; a<8; a++) {
+ if(wrld->mtex[a] && wrld->mtex[a]->tex==tex) {
+ if(wrld->id.lib==0) {
+ wrld->mtex[a]->tex= texn;
+ texn->id.us++;
+ tex->id.us--;
+ }
+ }
+ }
+ wrld= wrld->id.next;
+ }
+
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
+void autotexname(Tex *tex)
+{
+/* extern char texstr[15][8]; *//* buttons.c, already in bad lev calls*/
+ Image *ima;
+ char di[FILE_MAXDIR], fi[FILE_MAXFILE];
+
+ if(tex) {
+ if(tex->type==TEX_IMAGE) {
+ ima= tex->ima;
+ if(ima) {
+ strcpy(di, ima->name);
+ BLI_splitdirstring(di, fi);
+ strcpy(di, "I.");
+ strcat(di, fi);
+ new_id(&G.main->tex, (ID *)tex, di);
+ }
+ else new_id(&G.main->tex, (ID *)tex, texstr[tex->type]);
+ }
+ else if(tex->type==TEX_PLUGIN && tex->plugin) new_id(&G.main->tex, (ID *)tex, tex->plugin->pname);
+ else new_id(&G.main->tex, (ID *)tex, texstr[tex->type]);
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
+void init_render_texture(Tex *tex)
+{
+ Image *ima;
+ int imanr;
+ unsigned short numlen;
+ char name[256], head[FILE_MAXFILE], tail[FILE_MAXFILE];
+
+ /* is also used as signal */
+ tex->nor= 0;
+
+ /* imap testen */
+ if(tex->frames && tex->ima && tex->ima->name) { /* frames */
+ strcpy(name, tex->ima->name);
+
+ imanr= calcimanr(G.scene->r.cfra, tex);
+
+ if(tex->imaflag & TEX_ANIM5) {
+ if(tex->ima->lastframe != imanr) {
+ if(tex->ima->ibuf) IMB_freeImBuf(tex->ima->ibuf);
+ tex->ima->ibuf= 0;
+ tex->ima->lastframe= imanr;
+ }
+ }
+ else {
+ /* voor patch field-ima rendering */
+ tex->ima->lastframe= imanr;
+
+ BLI_stringdec(name, head, tail, &numlen);
+ BLI_stringenc(name, head, tail, numlen, imanr);
+
+ ima= add_image(name);
+
+ if(ima) {
+ ima->flag |= IMA_FROMANIM;
+
+ if(tex->ima) tex->ima->id.us--;
+ tex->ima= ima;
+
+ ima->ok= 1;
+ }
+ }
+ }
+ if(tex->imaflag & (TEX_ANTIALI+TEX_ANTISCALE)) {
+ if(tex->ima && tex->ima->lastquality<R.osa) {
+ if(tex->ima->ibuf) IMB_freeImBuf(tex->ima->ibuf);
+ tex->ima->ibuf= 0;
+ }
+ }
+
+ if(tex->type==TEX_PLUGIN) {
+ if(tex->plugin && tex->plugin->doit) {
+ if(tex->plugin->cfra) {
+ *(tex->plugin->cfra)= frame_to_float(G.scene->r.cfra);
+ }
+ }
+ }
+ else if(tex->type==TEX_ENVMAP) {
+ /* just in case */
+ tex->imaflag= TEX_INTERPOL | TEX_MIPMAP;
+ tex->extend= TEX_CLIP;
+
+ if(tex->env) {
+ /* temporal solution: layer 21 is to indicate an anvmap object */
+ tex->env->notlay |= (1<<20);
+ if(tex->env->object) tex->env->object->lay |= (1<<20);
+
+ if(R.flag & R_RENDERING) {
+ if(tex->env->stype==ENV_ANIM) RE_free_envmapdata(tex->env);
+ }
+ }
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
+void init_render_textures()
+{
+ Tex *tex;
+
+ tex= G.main->tex.first;
+ while(tex) {
+ if(tex->id.us) init_render_texture(tex);
+ tex= tex->id.next;
+ }
+
+ free_unused_animimages();
+}
+
+/* ------------------------------------------------------------------------- */
+
+void end_render_texture(Tex *tex)
+{
+
+
+}
+
+/* ------------------------------------------------------------------------- */
+
+void end_render_textures()
+{
+ Tex *tex;
+
+ tex= G.main->tex.first;
+ while(tex) {
+ if(tex->id.us) end_render_texture(tex);
+ tex= tex->id.next;
+ }
+
+}
+
+
+/* ************************** */
+
+int clouds(Tex *tex, float *texvec)
+{
+ float (*turbfunc)(float, float, float, float, int);
+
+ if(tex->noisetype==TEX_NOISESOFT) turbfunc= BLI_turbulence;
+ else turbfunc= BLI_turbulence1;
+
+ Tin= turbfunc(tex->noisesize, texvec[0], texvec[1], texvec[2], tex->noisedepth);
+
+ if(tex->stype==1) {
+
+ Tr= Tin;
+ Tg= turbfunc(tex->noisesize, texvec[1], texvec[0], texvec[2], tex->noisedepth);
+
+ Tb= turbfunc(tex->noisesize,texvec[1],texvec[2],texvec[0], tex->noisedepth);
+
+ BRICONRGB;
+ Ta= 1.0;
+
+ return 1;
+ }
+
+ BRICON;
+
+ if(tex->flag & TEX_COLORBAND) return do_colorband(tex->coba);
+
+ return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+
+int blend(Tex *tex, float *texvec)
+{
+ float x, y, t;
+
+ if(tex->flag & TEX_FLIPBLEND) {
+ x= texvec[1];
+ y= texvec[0];
+ }
+ else {
+ x= texvec[0];
+ y= texvec[1];
+ }
+
+ if(tex->stype==0) { /* lin */
+ Tin= (1.0+x)/2.0;
+ }
+ else if(tex->stype==1) { /* quad */
+ Tin= (1.0+x)/2.0;
+ if(Tin<0.0) Tin= 0.0;
+ else Tin*= Tin;
+ }
+ else if(tex->stype==2) { /* ease */
+ Tin= (1.0+x)/2.0;
+ if(Tin<=.0) Tin= 0.0;
+ else if(Tin>=1.0) Tin= 1.0;
+ else {
+ t= Tin*Tin;
+ Tin= (3.0*t-2.0*t*Tin);
+ }
+ }
+ else if(tex->stype==3) { /* diag */
+ Tin= (2.0+x+y)/4.0;
+ }
+ else { /* sphere */
+ Tin= 1.0-sqrt(x*x+ y*y+texvec[2]*texvec[2]);
+ if(Tin<0.0) Tin= 0.0;
+ if(tex->stype==5) Tin*= Tin; /* halo */
+ }
+
+ BRICON;
+ if(tex->flag & TEX_COLORBAND) return do_colorband(tex->coba);
+
+ return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+
+int wood(Tex *tex, float *texvec)
+{
+ float (*noisefunc)(float, float, float, float);
+
+ if(tex->noisetype==TEX_NOISESOFT) noisefunc= BLI_hnoise;
+ else noisefunc= BLI_hnoisep;
+
+
+ if(tex->stype==0) {
+ Tin= 0.5+0.5*sin( (texvec[0]+texvec[1]+texvec[2])*10.0 );
+ }
+ else if(tex->stype==1) {
+ Tin= 0.5+0.5*sin( sqrt(texvec[0]*texvec[0]+texvec[1]*texvec[1]+texvec[2]*texvec[2])*20.0 );
+ }
+ else if(tex->stype==2) {
+ Tin= noisefunc(tex->noisesize, texvec[0], texvec[1], texvec[2]);
+ Tin= 0.5+ 0.5*sin(tex->turbul*Tin+(texvec[0]+texvec[1]+texvec[2])*10.0);
+ }
+ else if(tex->stype==3) {
+ Tin= noisefunc(tex->noisesize, texvec[0], texvec[1], texvec[2]);
+ Tin= 0.5+ 0.5*sin(tex->turbul*Tin+(sqrt(texvec[0]*texvec[0]+texvec[1]*texvec[1]+texvec[2]*texvec[2]))*20.0);
+ }
+
+
+ BRICON;
+ if(tex->flag & TEX_COLORBAND) return do_colorband(tex->coba);
+
+ return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+
+int marble(Tex *tex, float *texvec)
+{
+ float n;
+ float (*turbfunc)(float, float, float, float, int);
+
+ if(tex->noisetype==TEX_NOISESOFT) turbfunc= BLI_turbulence;
+ else turbfunc= BLI_turbulence1;
+
+ n= 5.0*(texvec[0]+texvec[1]+texvec[2]);
+
+ Tin = 0.5+0.5*sin(n+tex->turbul*turbfunc(tex->noisesize, texvec[0],texvec[1],texvec[2], tex->noisedepth));
+
+ switch (tex->stype) {
+ case 1:
+ Tin= sqrt(Tin);
+ break;
+ case 2:
+ Tin= sqrt(Tin);
+ Tin= sqrt(Tin);
+ break;
+ }
+
+ BRICON;
+ if(tex->flag & TEX_COLORBAND) return do_colorband(tex->coba);
+
+ return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+
+int magic(Tex *tex, float *texvec)
+{
+ float x, y, z, turb=1.0;
+ int n;
+
+ n= tex->noisedepth;
+ turb= tex->turbul/5.0;
+
+ x= sin( ( texvec[0]+texvec[1]+texvec[2])*5.0 );
+ y= cos( (-texvec[0]+texvec[1]-texvec[2])*5.0 );
+ z= -cos( (-texvec[0]-texvec[1]+texvec[2])*5.0 );
+ if(n>0) {
+ x*= turb;
+ y*= turb;
+ z*= turb;
+ y= -cos(x-y+z);
+ y*= turb;
+ if(n>1) {
+ x= cos(x-y-z);
+ x*= turb;
+ if(n>2) {
+ z= sin(-x-y-z);
+ z*= turb;
+ if(n>3) {
+ x= -cos(-x+y-z);
+ x*= turb;
+ if(n>4) {
+ y= -sin(-x+y+z);
+ y*= turb;
+ if(n>5) {
+ y= -cos(-x+y+z);
+ y*= turb;
+ if(n>6) {
+ x= cos(x+y+z);
+ x*= turb;
+ if(n>7) {
+ z= sin(x+y-z);
+ z*= turb;
+ if(n>8) {
+ x= -cos(-x-y+z);
+ x*= turb;
+ if(n>9) {
+ y= -sin(x-y+z);
+ y*= turb;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if(turb!=0.0) {
+ turb*= 2.0;
+ x/= turb;
+ y/= turb;
+ z/= turb;
+ }
+ Tr= 0.5-x;
+ Tg= 0.5-y;
+ Tb= 0.5-z;
+
+ BRICONRGB;
+ Ta= 1.0;
+
+ return 1;
+}
+
+/* ------------------------------------------------------------------------- */
+
+int stucci(Tex *tex, float *texvec)
+{
+ float b2, vec[3];
+ float ofs;
+ float (*noisefunc)(float, float, float, float);
+
+ if(tex->nor == NULL) return 0;
+
+ if(tex->noisetype==TEX_NOISESOFT) noisefunc= BLI_hnoise;
+ else noisefunc= BLI_hnoisep;
+
+ ofs= tex->turbul/200.0;
+
+ b2= noisefunc(tex->noisesize, texvec[0], texvec[1], texvec[2]);
+ if(tex->stype) ofs*=(b2*b2);
+ vec[0]= b2-noisefunc(tex->noisesize, texvec[0]+ofs, texvec[1], texvec[2]);
+ vec[1]= b2-noisefunc(tex->noisesize, texvec[0], texvec[1]+ofs, texvec[2]);
+ vec[2]= b2-noisefunc(tex->noisesize, texvec[0], texvec[1], texvec[2]+ofs);
+
+ if(tex->stype==1) {
+ tex->nor[0]= vec[0];
+ tex->nor[1]= vec[1];
+ tex->nor[2]= vec[2];
+ }
+ else {
+ tex->nor[0]= -vec[0];
+ tex->nor[1]= -vec[1];
+ tex->nor[2]= -vec[2];
+ }
+
+ return 2;
+}
+
+/* ------------------------------------------------------------------------- */
+
+int texnoise(Tex *tex)
+{
+ float div=3.0;
+ int val, ran, loop;
+
+ ran= BLI_rand();
+ val= (ran & 3);
+
+ loop= tex->noisedepth;
+ while(loop--) {
+ ran= (ran>>2);
+ val*= (ran & 3);
+ div*= 3.0;
+ }
+
+ Tin= ((float)val)/div;;
+
+ BRICON;
+ if(tex->flag & TEX_COLORBAND) return do_colorband(tex->coba);
+
+ return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+
+int plugintex(Tex *tex, float *texvec, float *dxt, float *dyt)
+{
+ PluginTex *pit;
+ int rgbnor=0;
+
+ Tin= 0.0;
+
+ pit= tex->plugin;
+ if(pit && pit->doit) {
+ VECCOPY(pit->result+5, R.vn);
+
+ if(R.osatex) rgbnor= ((TexDoit)pit->doit)(tex->stype, pit->data, texvec, dxt, dyt);
+ else rgbnor= ((TexDoit)pit->doit)(tex->stype, pit->data, texvec, 0, 0);
+
+ Tin= pit->result[0];
+
+ if(rgbnor & TEX_NOR) {
+ if(tex->nor) {
+ VECCOPY(tex->nor, pit->result+5);
+ }
+ }
+
+ if(rgbnor & TEX_RGB) {
+ Tr= pit->result[1];
+ Tg= pit->result[2];
+ Tb= pit->result[3];
+ Ta= pit->result[4];
+
+ BRICONRGB;
+ }
+
+ BRICON;
+ if(tex->flag & TEX_COLORBAND) rgbnor |= do_colorband(tex->coba);
+ }
+
+ return rgbnor;
+}
+
+/* *************** PROJEKTIES ******************* */
+
+void tubemap(float x, float y, float z, float *adr1, float *adr2)
+{
+ float len;
+
+ *adr2 = (z + 1.0) / 2.0;
+
+ len= sqrt(x*x+y*y);
+ if(len>0) {
+ *adr1 = (1.0 - (atan2(x/len,y/len) / M_PI)) / 2.0;
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
+void spheremap(float x, float y, float z, float *adr1, float *adr2)
+{
+ float len;
+
+ len= sqrt(x*x+y*y+z*z);
+ if(len>0.0) {
+
+ if(x==0.0 && y==0.0) *adr1= 0.0; /* anders domain error */
+ else *adr1 = (1.0 - atan2(x,y)/M_PI )/2.0;
+
+ z/=len;
+ *adr2 = 1.0- saacos(z)/M_PI;
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
+static int cubemap_glob(MTex *mtex, float x, float y, float z, float *adr1, float *adr2)
+{
+ float x1, y1, z1, nor[3];
+ int ret;
+
+ VECCOPY(nor, R.vn);
+ MTC_Mat4Mul3Vecfl(R.viewinv, nor);
+
+ x1= fabs(nor[0]);
+ y1= fabs(nor[1]);
+ z1= fabs(nor[2]);
+
+ if(z1>=x1 && z1>=y1) {
+ *adr1 = (x + 1.0) / 2.0;
+ *adr2 = (y + 1.0) / 2.0;
+ ret= 0;
+ }
+ else if(y1>=x1 && y1>=z1) {
+ *adr1 = (x + 1.0) / 2.0;
+ *adr2 = (z + 1.0) / 2.0;
+ ret= 1;
+ }
+ else {
+ *adr1 = (y + 1.0) / 2.0;
+ *adr2 = (z + 1.0) / 2.0;
+ ret= 2;
+ }
+ return ret;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static int cubemap(MTex *mtex, float x, float y, float z, float *adr1, float *adr2)
+{
+ int proj[4], ret= 0;
+
+ if(R.vlr && R.vlr->mface) {
+ int index;
+ /* the mtex->proj{xyz} have type char. maybe this should be wider? */
+ /* casting to int ensures that the index type is right. */
+ index = (int) mtex->projx;
+ proj[index]= ME_PROJXY;
+
+ index = (int) mtex->projy;
+ proj[index]= ME_PROJXZ;
+
+ index = (int) mtex->projz;
+ proj[index]= ME_PROJYZ;
+
+ if(R.vlr->mface->puno & proj[1]) {
+ *adr1 = (x + 1.0) / 2.0;
+ *adr2 = (y + 1.0) / 2.0;
+ }
+ else if(R.vlr->mface->puno & proj[2]) {
+ *adr1 = (x + 1.0) / 2.0;
+ *adr2 = (z + 1.0) / 2.0;
+ ret= 1;
+ }
+ else {
+ *adr1 = (y + 1.0) / 2.0;
+ *adr2 = (z + 1.0) / 2.0;
+ ret= 2;
+ }
+ } else
+ return cubemap_glob(mtex, x, y, z, adr1, adr2);
+
+ return ret;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static int cubemap_ob(MTex *mtex, float x, float y, float z, float *adr1, float *adr2)
+{
+ float x1, y1, z1, nor[3];
+ int ret;
+
+ VECCOPY(nor, R.vn);
+ if(mtex->object) MTC_Mat4Mul3Vecfl(mtex->object->imat, nor);
+
+ x1= fabs(nor[0]);
+ y1= fabs(nor[1]);
+ z1= fabs(nor[2]);
+
+ if(z1>=x1 && z1>=y1) {
+ *adr1 = (x + 1.0) / 2.0;
+ *adr2 = (y + 1.0) / 2.0;
+ ret= 0;
+ }
+ else if(y1>=x1 && y1>=z1) {
+ *adr1 = (x + 1.0) / 2.0;
+ *adr2 = (z + 1.0) / 2.0;
+ ret= 1;
+ }
+ else {
+ *adr1 = (y + 1.0) / 2.0;
+ *adr2 = (z + 1.0) / 2.0;
+ ret= 2;
+ }
+ return ret;
+}
+
+/* ------------------------------------------------------------------------- */
+
+void do_2d_mapping(MTex *mtex, float *t, float *dxt, float *dyt)
+{
+ Tex *tex;
+ float fx, fy, fac1, area[8];
+ int ok, proj, areaflag= 0, wrap;
+
+ wrap= mtex->mapping;
+ tex= mtex->tex;
+
+ if(R.osa==0) {
+
+ if(wrap==MTEX_FLAT) {
+ fx = (t[0] + 1.0) / 2.0;
+ fy = (t[1] + 1.0) / 2.0;
+ }
+ else if(wrap==MTEX_TUBE) tubemap(t[0], t[1], t[2], &fx, &fy);
+ else if(wrap==MTEX_SPHERE) spheremap(t[0], t[1], t[2], &fx, &fy);
+ else {
+ if(mtex->texco==TEXCO_OBJECT) cubemap_ob(mtex, t[0], t[1], t[2], &fx, &fy);
+ else if(mtex->texco==TEXCO_GLOB) cubemap_glob(mtex, t[0], t[1], t[2], &fx, &fy);
+ else cubemap(mtex, t[0], t[1], t[2], &fx, &fy);
+ }
+
+ /* repeat */
+ if(tex->xrepeat>1) {
+ fx *= tex->xrepeat;
+ if(fx>1.0) fx -= (int)(fx);
+ else if(fx<0.0) fx+= 1-(int)(fx);
+ }
+ if(tex->yrepeat>1) {
+ fy *= tex->yrepeat;
+ if(fy>1.0) fy -= (int)(fy);
+ else if(fy<0.0) fy+= 1-(int)(fy);
+ }
+
+ /* crop */
+ if(tex->cropxmin!=0.0 || tex->cropxmax!=1.0) {
+ fac1= tex->cropxmax - tex->cropxmin;
+ fx= tex->cropxmin+ fx*fac1;
+ }
+ if(tex->cropymin!=0.0 || tex->cropymax!=1.0) {
+ fac1= tex->cropymax - tex->cropymin;
+ fy= tex->cropymin+ fy*fac1;
+ }
+
+ t[0]= fx;
+ t[1]= fy;
+ }
+ else {
+
+ if(wrap==MTEX_FLAT) {
+ fx= (t[0] + 1.0) / 2.0;
+ fy= (t[1] + 1.0) / 2.0;
+ dxt[0]/= 2.0;
+ dxt[1]/= 2.0;
+ dyt[0]/= 2.0;
+ dyt[1]/= 2.0;
+ }
+ else if ELEM(wrap, MTEX_TUBE, MTEX_SPHERE) {
+ /* uitzondering: de naad achter (y<0.0) */
+ ok= 1;
+ if(t[1]<=0.0) {
+ fx= t[0]+dxt[0];
+ fy= t[0]+dyt[0];
+ if(fx>=0.0 && fy>=0.0 && t[0]>=0.0);
+ else if(fx<=0.0 && fy<=0.0 && t[0]<=0.0);
+ else ok= 0;
+ }
+ if(ok) {
+ if(wrap==MTEX_TUBE) {
+ tubemap(t[0], t[1], t[2], area, area+1);
+ tubemap(t[0]+dxt[0], t[1]+dxt[1], t[2]+dxt[2], area+2, area+3);
+ tubemap(t[0]+dyt[0], t[1]+dyt[1], t[2]+dyt[2], area+4, area+5);
+ }
+ else {
+ spheremap(t[0], t[1], t[2],area,area+1);
+ spheremap(t[0]+dxt[0], t[1]+dxt[1], t[2]+dxt[2], area+2, area+3);
+ spheremap(t[0]+dyt[0], t[1]+dyt[1], t[2]+dyt[2], area+4, area+5);
+ }
+ areaflag= 1;
+ }
+ else {
+ if(wrap==MTEX_TUBE) tubemap(t[0], t[1], t[2], &fx, &fy);
+ else spheremap(t[0], t[1], t[2], &fx, &fy);
+ dxt[0]/= 2.0;
+ dxt[1]/= 2.0;
+ dyt[0]/= 2.0;
+ dyt[1]/= 2.0;
+ }
+ }
+ else {
+
+ if(mtex->texco==TEXCO_OBJECT) proj = cubemap_ob(mtex, t[0], t[1], t[2], &fx, &fy);
+ else if (mtex->texco==TEXCO_GLOB) proj = cubemap_glob(mtex, t[0], t[1], t[2], &fx, &fy);
+ else proj = cubemap(mtex, t[0], t[1], t[2], &fx, &fy);
+
+ if(proj==1) {
+ dxt[1]= dxt[2];
+ dyt[1]= dyt[2];
+ }
+ else if(proj==2) {
+ dxt[0]= dxt[1];
+ dyt[0]= dyt[1];
+ dxt[1]= dxt[2];
+ dyt[1]= dyt[2];
+ }
+ dxt[0]/= 2.0;
+ dxt[1]/= 2.0;
+ dyt[0]/= 2.0;
+ dyt[1]/= 2.0;
+ }
+
+ /* als area dan dxt[] en dyt[] opnieuw berekenen */
+ if(areaflag) {
+ fx= area[0];
+ fy= area[1];
+ dxt[0]= area[2]-fx;
+ dxt[1]= area[3]-fy;
+ dyt[0]= area[4]-fx;
+ dyt[1]= area[5]-fy;
+ }
+
+ /* repeat */
+ if(tex->xrepeat>1) {
+ fx *= tex->xrepeat;
+ dxt[0]*= tex->xrepeat;
+ dyt[0]*= tex->xrepeat;
+ if(fx>1.0) fx -= (int)(fx);
+ else if(fx<0.0) fx+= 1-(int)(fx);
+ }
+ if(tex->yrepeat>1) {
+ fy *= tex->yrepeat;
+ dxt[1]*= tex->yrepeat;
+ dyt[1]*= tex->yrepeat;
+ if(fy>1.0) fy -= (int)(fy);
+ else if(fy<0.0) fy+= 1-(int)(fy);
+ }
+
+ /* crop */
+ if(tex->cropxmin!=0.0 || tex->cropxmax!=1.0) {
+ fac1= tex->cropxmax - tex->cropxmin;
+ fx= tex->cropxmin+ fx*fac1;
+ dxt[0]*= fac1;
+ dyt[0]*= fac1;
+ }
+ if(tex->cropymin!=0.0 || tex->cropymax!=1.0) {
+ fac1= tex->cropymax - tex->cropymin;
+ fy= tex->cropymin+ fy*fac1;
+ dxt[1]*= fac1;
+ dyt[1]*= fac1;
+ }
+
+ t[0]= fx;
+ t[1]= fy;
+
+ }
+}
+
+
+/* ************************************** */
+
+int multitex(Tex *tex, float *texvec, float *dxt, float *dyt)
+{
+
+
+ switch(tex->type) {
+
+ case 0:
+ Tin= 0.0;
+ return 0;
+ case TEX_CLOUDS:
+ return clouds(tex, texvec);
+ case TEX_WOOD:
+ return wood(tex, texvec);
+ case TEX_MARBLE:
+ return marble(tex, texvec);
+ case TEX_MAGIC:
+ return magic(tex, texvec);
+ case TEX_BLEND:
+ return blend(tex, texvec);
+ case TEX_STUCCI:
+ Tin= 0.0;
+ return stucci(tex, texvec);
+ case TEX_NOISE:
+ return texnoise(tex);
+ case TEX_IMAGE:
+ if(R.osatex) return imagewraposa(tex, texvec, dxt, dyt);
+ else return imagewrap(tex, texvec);
+ break;
+ case TEX_PLUGIN:
+ return plugintex(tex, texvec, dxt, dyt);
+ break;
+ case TEX_ENVMAP:
+ return RE_envmaptex(tex, texvec, dxt, dyt);
+ break;
+ }
+ return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+
+void do_material_tex()
+{
+ Object *ob;
+ Material *mat_col, *mat_colspec, *mat_colmir, *mat_ref;
+ Material *mat_spec, *mat_har, *mat_emit, *mat_alpha;
+ MTex *mtex;
+ Tex *tex;
+ float *co = NULL, *dx = NULL, *dy = NULL, fact,
+ facm, factt, facmm, facmul = 0.0, stencilTin=1.0;
+ float texvec[3], dxt[3], dyt[3], tempvec[3], norvec[3];
+ int tex_nr, rgbnor= 0;
+
+ /* hier flag testen of er wel tex is */
+
+ mat_col=mat_colspec=mat_colmir=mat_ref=mat_spec=mat_har=mat_emit=mat_alpha= R.mat;
+
+ tex_nr= 0;
+ if(R.mat->septex) tex_nr= R.mat->texact;
+
+ for(; tex_nr<8; tex_nr++) {
+ if(R.mat->mtex[tex_nr]) {
+ mtex= R.mat->mtex[tex_nr];
+
+ tex= mtex->tex;
+ if(tex==0) continue;
+
+ /* welke coords */
+ if(mtex->texco==TEXCO_ORCO) {
+ co= R.lo; dx= O.dxlo; dy= O.dylo;
+ }
+ else if(mtex->texco==TEXCO_STICKY) {
+ co= R.sticky; dx= O.dxsticky; dy= O.dysticky;
+ }
+ else if(mtex->texco==TEXCO_OBJECT) {
+ ob= mtex->object;
+ if(ob) {
+ co= tempvec;
+ dx= dxt;
+ dy= dyt;
+ VECCOPY(tempvec, R.co);
+ MTC_Mat4MulVecfl(ob->imat, tempvec);
+ if(R.osatex) {
+ VECCOPY(dxt, O.dxco);
+ VECCOPY(dyt, O.dyco);
+ MTC_Mat4Mul3Vecfl(ob->imat, dxt);
+ MTC_Mat4Mul3Vecfl(ob->imat, dyt);
+ }
+ }
+ else {
+ /* als object niet bestaat geen orco's gebruiken (zijn niet geinitialiseerd */
+ co= R.co;
+ dx= O.dxco; dy= O.dyco;
+ }
+ }
+ else if(mtex->texco==TEXCO_REFL) {
+ co= R.ref; dx= O.dxref; dy= O.dyref;
+ }
+ else if(mtex->texco==TEXCO_NORM) {
+ co= R.orn; dx= O.dxno; dy= O.dyno;
+ }
+ else if(mtex->texco==TEXCO_GLOB) {
+ co= R.gl; dx= O.dxco; dy= O.dyco;
+ }
+ else if(mtex->texco==TEXCO_UV) {
+ co= R.uv; dx= O.dxuv; dy= O.dyuv;
+ }
+ else if(mtex->texco==TEXCO_WINDOW) {
+ co= R.winco; dx= O.dxwin; dy= O.dywin;
+ }
+
+ /* de pointer defines if bumping happens */
+ if(mtex->mapto & MAP_NORM) {
+ tex->nor= norvec;
+ norvec[0]= norvec[1]= norvec[2]= 0.0;
+ }
+ else tex->nor= 0;
+
+ if(tex->type==TEX_IMAGE) {
+
+ /* nieuw: eerst coords verwisselen, dan map, dan trans/scale */
+
+ /* placement */
+ if(mtex->projx) texvec[0]= co[mtex->projx-1];
+ else texvec[0]= 0.0;
+ if(mtex->projy) texvec[1]= co[mtex->projy-1];
+ else texvec[1]= 0.0;
+ if(mtex->projz) texvec[2]= co[mtex->projz-1];
+ else texvec[2]= 0.0;
+
+ if(R.osatex) {
+
+ if(mtex->projx) {
+ dxt[0]= dx[mtex->projx-1];
+ dyt[0]= dy[mtex->projx-1];
+ }
+ else dxt[0]= 0.0;
+ if(mtex->projy) {
+ dxt[1]= dx[mtex->projy-1];
+ dyt[1]= dy[mtex->projy-1];
+ }
+ else dxt[1]= 0.0;
+ if(mtex->projx) {
+ dxt[2]= dx[mtex->projz-1];
+ dyt[2]= dy[mtex->projz-1];
+ }
+ else dxt[2]= 0.0;
+ }
+
+ do_2d_mapping(mtex, texvec, dxt, dyt);
+
+ /* translate en scale */
+ texvec[0]= mtex->size[0]*(texvec[0]-0.5) +mtex->ofs[0]+0.5;
+ texvec[1]= mtex->size[1]*(texvec[1]-0.5) +mtex->ofs[1]+0.5;
+ if(R.osatex) {
+ dxt[0]= mtex->size[0]*dxt[0];
+ dxt[1]= mtex->size[1]*dxt[1];
+ dyt[0]= mtex->size[0]*dyt[0];
+ dyt[1]= mtex->size[1]*dyt[1];
+ }
+ }
+ else {
+
+ /* placement */
+ if(mtex->projx) texvec[0]= mtex->size[0]*(co[mtex->projx-1]+mtex->ofs[0]);
+ else texvec[0]= mtex->size[0]*(mtex->ofs[0]);
+
+ if(mtex->projy) texvec[1]= mtex->size[1]*(co[mtex->projy-1]+mtex->ofs[1]);
+ else texvec[1]= mtex->size[1]*(mtex->ofs[1]);
+
+ if(mtex->projz) texvec[2]= mtex->size[2]*(co[mtex->projz-1]+mtex->ofs[2]);
+ else texvec[2]= mtex->size[2]*(mtex->ofs[2]);
+
+ if(R.osatex) {
+ if(mtex->projx) {
+ dxt[0]= mtex->size[0]*dx[mtex->projx-1];
+ dyt[0]= mtex->size[0]*dy[mtex->projx-1];
+ }
+ else dxt[0]= 0.0;
+ if(mtex->projy) {
+ dxt[1]= mtex->size[1]*dx[mtex->projy-1];
+ dyt[1]= mtex->size[1]*dy[mtex->projy-1];
+ }
+ else dxt[1]= 0.0;
+ if(mtex->projx) {
+ dxt[2]= mtex->size[2]*dx[mtex->projz-1];
+ dyt[2]= mtex->size[2]*dy[mtex->projz-1];
+ }
+ else dxt[2]= 0.0;
+ }
+ }
+
+ rgbnor= multitex(tex, texvec, dxt, dyt);
+
+ /* texture output */
+
+ if( (rgbnor & TEX_RGB) && (mtex->texflag & MTEX_RGBTOINT)) {
+ Tin= (0.35*Tr+0.45*Tg+0.2*Tb);
+ rgbnor-= 1;
+ }
+ if(mtex->texflag & MTEX_NEGATIVE) {
+ if(rgbnor & TEX_RGB) {
+ Tr= 1.0-Tr;
+ Tg= 1.0-Tg;
+ Tb= 1.0-Tb;
+ }
+ Tin= 1.0-Tin;
+ }
+ if(mtex->texflag & MTEX_STENCIL) {
+ if(rgbnor & TEX_RGB) {
+ fact= Ta;
+ Ta*= stencilTin;
+ stencilTin*= fact;
+ }
+ else {
+ fact= Tin;
+ Tin*= stencilTin;
+ stencilTin*= fact;
+ }
+ }
+ else {
+ if(rgbnor & TEX_RGB) Ta*= stencilTin;
+ else Tin*= stencilTin;
+ }
+
+ if(tex->nor && (rgbnor & TEX_NOR)==0) {
+ /* make our own normal */
+ if(rgbnor & TEX_RGB) {
+ tex->nor[0]= Tr;
+ tex->nor[1]= Tg;
+ tex->nor[2]= Tb;
+ }
+ else {
+ float co= 0.5*cos(Tin-0.5);
+ float si= 0.5*sin(Tin-0.5);
+ float f1, f2;
+
+ f1= R.vn[0];
+ f2= R.vn[1];
+ tex->nor[0]= f1*co+f2*si;
+ tex->nor[1]= f2*co-f1*si;
+ f1= R.vn[1];
+ f2= R.vn[2];
+ tex->nor[1]= f1*co+f2*si;
+ tex->nor[2]= f2*co-f1*si;
+ }
+ }
+
+
+ /* mapping */
+ if(mtex->mapto & (MAP_COL+MAP_COLSPEC+MAP_COLMIR)) {
+
+ if((rgbnor & TEX_RGB)==0) {
+ Tr= mtex->r;
+ Tg= mtex->g;
+ Tb= mtex->b;
+ }
+ else if(mtex->mapto & MAP_ALPHA) {
+ if(mtex->texflag & MTEX_ALPHAMIX) Tin= Ta;
+ else Tin= stencilTin;
+ }
+ else Tin= Ta;
+
+ fact= Tin*mtex->colfac;
+ facm= 1.0-fact;
+ if(mtex->blendtype==MTEX_MUL) facm= 1.0-mtex->colfac;
+ if(mtex->blendtype==MTEX_SUB) fact= -fact;
+
+ if(mtex->mapto & MAP_COL) {
+ if(mtex->blendtype==MTEX_BLEND) {
+ R.matren->r= (fact*Tr + facm*mat_col->r);
+ R.matren->g= (fact*Tg + facm*mat_col->g);
+ R.matren->b= (fact*Tb + facm*mat_col->b);
+ }
+ else if(mtex->blendtype==MTEX_MUL) {
+ R.matren->r= (facm+fact*Tr)*mat_col->r;
+ R.matren->g= (facm+fact*Tg)*mat_col->g;
+ R.matren->b= (facm+fact*Tb)*mat_col->b;
+ }
+ else {
+ R.matren->r= (fact*Tr + mat_col->r);
+ R.matren->g= (fact*Tg + mat_col->g);
+ R.matren->b= (fact*Tb + mat_col->b);
+ }
+ mat_col= R.matren;
+ }
+ if(mtex->mapto & MAP_COLSPEC) {
+ if(mtex->blendtype==MTEX_BLEND) {
+ R.matren->specr= (fact*Tr + facm*mat_colspec->specr);
+ R.matren->specg= (fact*Tg + facm*mat_colspec->specg);
+ R.matren->specb= (fact*Tb + facm*mat_colspec->specb);
+ }
+ else if(mtex->blendtype==MTEX_MUL) {
+ R.matren->specr= (facm+fact*Tr)*mat_colspec->specr;
+ R.matren->specg= (facm+fact*Tg)*mat_colspec->specg;
+ R.matren->specb= (facm+fact*Tb)*mat_colspec->specb;
+ }
+ else {
+ R.matren->specr= (fact*Tr + mat_colspec->specr);
+ R.matren->specg= (fact*Tg + mat_colspec->specg);
+ R.matren->specb= (fact*Tb + mat_colspec->specb);
+ }
+ mat_colspec= R.matren;
+ }
+ if(mtex->mapto & MAP_COLMIR) {
+ if(mtex->blendtype==MTEX_BLEND) {
+ R.refcol[0]= fact + facm*R.refcol[0];
+
+ R.refcol[1]= fact*Tr + facm*R.refcol[1];
+ R.refcol[2]= fact*Tg + facm*R.refcol[2];
+ R.refcol[3]= fact*Tb + facm*R.refcol[3];
+ }
+ else if(mtex->blendtype==MTEX_MUL) {
+ R.matren->mirr= (facm+fact*Tr)*mat_colmir->mirr;
+ R.matren->mirg= (facm+fact*Tg)*mat_colmir->mirg;
+ R.matren->mirb= (facm+fact*Tb)*mat_colmir->mirb;
+ }
+ else {
+ R.matren->mirr= (fact*Tr + mat_colmir->mirr);
+ R.matren->mirg= (fact*Tg + mat_colmir->mirg);
+ R.matren->mirb= (fact*Tb + mat_colmir->mirb);
+ }
+ mat_colmir= R.matren;
+ }
+ }
+ if( (mtex->mapto & MAP_NORM) ) {
+ if(tex->nor) {
+
+ if(mtex->maptoneg & MAP_NORM) tex->norfac= -mtex->norfac;
+ else tex->norfac= mtex->norfac;
+
+ R.vn[0]+= tex->norfac*tex->nor[0];
+ R.vn[1]+= tex->norfac*tex->nor[1];
+ R.vn[2]+= tex->norfac*tex->nor[2];
+
+ Normalise(R.vn);
+
+ /* hierdoor wordt de bump aan de volgende texture doorgegeven */
+ R.orn[0]= R.vn[0];
+ R.orn[1]= -R.vn[1];
+ R.orn[2]= R.vn[2];
+
+ /* reflection vector */
+ RE_calc_R_ref();
+ }
+ }
+
+ if(mtex->mapto & MAP_VARS) {
+ if(rgbnor & TEX_RGB) {
+ if(Talpha) Tin= Ta;
+ else Tin= (0.35*Tr+0.45*Tg+0.2*Tb);
+ }
+
+ fact= Tin*mtex->varfac;
+ facm= 1.0-fact;
+ if(mtex->blendtype==MTEX_MUL) facmul= 1.0-mtex->varfac;
+ if(mtex->blendtype==MTEX_SUB) fact= -fact;
+
+ if(mtex->mapto & MAP_REF) {
+ if(mtex->maptoneg & MAP_REF) {factt= facm; facmm= fact;}
+ else {factt= fact; facmm= facm;}
+
+ if(mtex->blendtype==MTEX_BLEND)
+ R.matren->ref= factt*mtex->def_var+ facmm*mat_ref->ref;
+ else if(mtex->blendtype==MTEX_MUL)
+ R.matren->ref= (facmul+factt)*mat_ref->ref;
+ else {
+ R.matren->ref= factt+mat_ref->ref;
+ if(R.matren->ref<0.0) R.matren->ref= 0.0;
+ }
+ mat_ref= R.matren;
+ }
+ if(mtex->mapto & MAP_SPEC) {
+ if(mtex->maptoneg & MAP_SPEC) {factt= facm; facmm= fact;}
+ else {factt= fact; facmm= facm;}
+
+ if(mtex->blendtype==MTEX_BLEND)
+ R.matren->spec= factt*mtex->def_var+ facmm*mat_spec->spec;
+ else if(mtex->blendtype==MTEX_MUL)
+ R.matren->spec= (facmul+factt)*mat_spec->spec;
+ else {
+ R.matren->spec= factt+mat_spec->spec;
+ if(R.matren->spec<0.0) R.matren->spec= 0.0;
+ }
+ mat_spec= R.matren;
+ }
+ if(mtex->mapto & MAP_EMIT) {
+ if(mtex->maptoneg & MAP_EMIT) {factt= facm; facmm= fact;}
+ else {factt= fact; facmm= facm;}
+
+ if(mtex->blendtype==MTEX_BLEND)
+ R.matren->emit= factt*mtex->def_var+ facmm*mat_emit->emit;
+ else if(mtex->blendtype==MTEX_MUL)
+ R.matren->emit= (facmul+factt)*mat_emit->emit;
+ else {
+ R.matren->emit= factt+mat_emit->emit;
+ if(R.matren->emit<0.0) R.matren->emit= 0.0;
+ }
+ mat_emit= R.matren;
+ }
+ if(mtex->mapto & MAP_ALPHA) {
+ if(mtex->maptoneg & MAP_ALPHA) {factt= facm; facmm= fact;}
+ else {factt= fact; facmm= facm;}
+
+ if(mtex->blendtype==MTEX_BLEND)
+ R.matren->alpha= factt*mtex->def_var+ facmm*mat_alpha->alpha;
+ else if(mtex->blendtype==MTEX_MUL)
+ R.matren->alpha= (facmul+factt)*mat_alpha->alpha;
+ else {
+ R.matren->alpha= factt+mat_alpha->alpha;
+ if(R.matren->alpha<0.0) R.matren->alpha= 0.0;
+ else if(R.matren->alpha>1.0) R.matren->alpha= 1.0;
+ }
+ mat_alpha= R.matren;
+ }
+ if(mtex->mapto & MAP_HAR) {
+ if(mtex->maptoneg & MAP_HAR) {factt= facm; facmm= fact;}
+ else {factt= fact; facmm= facm;}
+
+ if(mtex->blendtype==MTEX_BLEND) {
+ R.matren->har= 128.0*factt*mtex->def_var+ facmm*mat_har->har;
+ } else if(mtex->blendtype==MTEX_MUL) {
+ R.matren->har= (facmul+factt)*mat_har->har;
+ } else {
+ R.matren->har= 128.0*factt+mat_har->har;
+ if(R.matren->har<1) R.matren->har= 1;
+ }
+ mat_har= R.matren;
+ }
+ }
+ }
+
+ if(R.mat->septex) break;
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
+void do_halo_tex(HaloRen *har, float xn, float yn, float *colf)
+{
+ MTex *mtex;
+ float texvec[3], dxt[3], dyt[3], fact, facm, dx;
+ int rgb;
+
+ mtex= har->mat->mtex[0];
+ if(mtex->tex==0) return;
+ /* no normal mapping */
+ mtex->tex->nor= 0;
+
+ texvec[0]= xn/har->rad;
+ texvec[1]= yn/har->rad;
+ texvec[2]= 0.0;
+
+ R.osatex= (har->mat->texco & TEXCO_OSA);
+
+ /* placement */
+ if(mtex->projx) texvec[0]= mtex->size[0]*(texvec[mtex->projx-1]+mtex->ofs[0]);
+ else texvec[0]= mtex->size[0]*(mtex->ofs[0]);
+
+ if(mtex->projy) texvec[1]= mtex->size[1]*(texvec[mtex->projy-1]+mtex->ofs[1]);
+ else texvec[1]= mtex->size[1]*(mtex->ofs[1]);
+
+ if(mtex->projz) texvec[2]= mtex->size[2]*(texvec[mtex->projz-1]+mtex->ofs[2]);
+ else texvec[2]= mtex->size[2]*(mtex->ofs[2]);
+
+ if(R.osatex) {
+
+ dx= 1.0/har->rad;
+
+ if(mtex->projx) {
+ dxt[0]= mtex->size[0]*dx;
+ dyt[0]= mtex->size[0]*dx;
+ }
+ else dxt[0]= 0.0;
+ if(mtex->projy) {
+ dxt[1]= mtex->size[1]*dx;
+ dyt[1]= mtex->size[1]*dx;
+ }
+ else dxt[1]= 0.0;
+ if(mtex->projz) {
+ dxt[2]= 0.0;
+ dyt[2]= 0.0;
+ }
+ else dxt[2]= 0.0;
+
+ }
+
+
+ if(mtex->tex->type==TEX_IMAGE) do_2d_mapping(mtex, texvec, dxt, dyt);
+
+ rgb= multitex(mtex->tex, texvec, dxt, dyt);
+
+ /* texture uitgang */
+ if(rgb && (mtex->texflag & MTEX_RGBTOINT)) {
+ Tin= (0.35*Tr+0.45*Tg+0.2*Tb);
+ rgb= 0;
+ }
+ if(mtex->texflag & MTEX_NEGATIVE) {
+ if(rgb) {
+ Tr= 1.0-Tr;
+ Tg= 1.0-Tg;
+ Tb= 1.0-Tb;
+ }
+ else Tin= 1.0-Tin;
+ }
+
+ /* mapping */
+ if(mtex->mapto & MAP_COL) {
+
+ if(rgb==0) {
+ Tr= mtex->r;
+ Tg= mtex->g;
+ Tb= mtex->b;
+ }
+ else if(mtex->mapto & MAP_ALPHA) {
+ if(mtex->texflag & MTEX_ALPHAMIX) Tin= Ta;
+ else Tin= 1.0;
+ }
+ else Tin= Ta;
+
+ fact= Tin*mtex->colfac;
+ facm= 1.0-fact;
+
+ if(mtex->blendtype==MTEX_MUL) {
+ facm= 1.0-mtex->colfac;
+ }
+ else fact*= 256;
+
+ if(mtex->blendtype==MTEX_SUB) fact= -fact;
+
+ if(mtex->blendtype==MTEX_BLEND) {
+ colf[0]= (fact*Tr + facm*har->r);
+ colf[1]= (fact*Tg + facm*har->g);
+ colf[2]= (fact*Tb + facm*har->b);
+ }
+ else if(mtex->blendtype==MTEX_MUL) {
+ colf[0]= (facm+fact*Tr)*har->r;
+ colf[1]= (facm+fact*Tg)*har->g;
+ colf[2]= (facm+fact*Tb)*har->b;
+ }
+ else {
+ colf[0]= (fact*Tr + har->r);
+ colf[1]= (fact*Tg + har->g);
+ colf[2]= (fact*Tb + har->b);
+
+ CLAMP(colf[0], 0.0, 1.0);
+ CLAMP(colf[1], 0.0, 1.0);
+ CLAMP(colf[2], 0.0, 1.0);
+ }
+ }
+ if(mtex->mapto & MAP_ALPHA) {
+ if(rgb) {
+ if(Talpha) Tin= Ta;
+ else Tin= (0.35*Tr+0.45*Tg+0.2*Tb);
+ }
+
+ colf[3]*= Tin;
+ }
+
+ R.osatex= 0;
+}
+
+/* ------------------------------------------------------------------------- */
+
+void do_sky_tex()
+{
+ World *wrld_hor, *wrld_zen;
+ MTex *mtex;
+ float *co, fact, facm, factt, facmm, facmul = 0.0, stencilTin=1.0;
+ float tempvec[3], texvec[3], dxt[3], dyt[3];
+ int tex_nr, rgb= 0, ok;
+
+
+ /* hier flag testen of er wel tex is */
+
+ wrld_hor= wrld_zen= G.scene->world;
+
+ /* The 6 here is rather arbitrary, it seems. */
+ for(tex_nr=0; tex_nr<6; tex_nr++) {
+ if(R.wrld.mtex[tex_nr]) {
+ mtex= R.wrld.mtex[tex_nr];
+
+ if(mtex->tex==0) continue;
+ /* if(mtex->mapto==0) continue; */
+
+ /* welke coords */
+ co= R.lo;
+
+ /* Grab the mapping settings for this texture */
+ if(mtex->texco==TEXCO_OBJECT) {
+ Object *ob= mtex->object;
+ if(ob) {
+ VECCOPY(tempvec, R.lo);
+ MTC_Mat4MulVecfl(ob->imat, tempvec);
+ co= tempvec;
+ }
+ }
+
+ /* placement */
+ if(mtex->projx) texvec[0]= mtex->size[0]*(co[mtex->projx-1]+mtex->ofs[0]);
+ else texvec[0]= mtex->size[0]*(mtex->ofs[0]);
+
+ if(mtex->projy) texvec[1]= mtex->size[1]*(co[mtex->projy-1]+mtex->ofs[1]);
+ else texvec[1]= mtex->size[1]*(mtex->ofs[1]);
+
+ if(mtex->projz) texvec[2]= mtex->size[2]*(co[mtex->projz-1]+mtex->ofs[2]);
+ else texvec[2]= mtex->size[2]*(mtex->ofs[2]);
+
+ /* texture */
+ if(mtex->tex->type==TEX_IMAGE) do_2d_mapping(mtex, texvec, dxt, dyt);
+
+ rgb= multitex(mtex->tex, texvec, dxt, dyt);
+
+ /* texture uitgang */
+ if(rgb && (mtex->texflag & MTEX_RGBTOINT)) {
+ Tin= (0.35*Tr+0.45*Tg+0.2*Tb);
+ rgb= 0;
+ }
+ if(mtex->texflag & MTEX_NEGATIVE) {
+ if(rgb) {
+ Tr= 1.0-Tr;
+ Tg= 1.0-Tg;
+ Tb= 1.0-Tb;
+ }
+ else Tin= 1.0-Tin;
+ }
+ if(mtex->texflag & MTEX_STENCIL) {
+ if(rgb) {
+
+ }
+ else {
+ fact= Tin;
+ Tin*= stencilTin;
+ stencilTin*= fact;
+ }
+ }
+ else {
+ if(rgb) ;
+ else Tin*= stencilTin;
+ }
+
+ /* colour mapping */
+ if(mtex->mapto & (WOMAP_HORIZ+WOMAP_ZENUP+WOMAP_ZENDOWN)) {
+
+ if(rgb==0) {
+ Tr= mtex->r;
+ Tg= mtex->g;
+ Tb= mtex->b;
+ }
+ else Tin= 1.0;
+
+ fact= Tin*mtex->colfac;
+ facm= 1.0-fact;
+ if(mtex->blendtype==MTEX_MUL) facm= 1.0-mtex->colfac;
+ if(mtex->blendtype==MTEX_SUB) fact= -fact;
+
+ if(mtex->mapto & WOMAP_HORIZ) {
+ if(mtex->blendtype==MTEX_BLEND) {
+ R.wrld.horr= (fact*Tr + facm*wrld_hor->horr);
+ R.wrld.horg= (fact*Tg + facm*wrld_hor->horg);
+ R.wrld.horb= (fact*Tb + facm*wrld_hor->horb);
+ }
+ else if(mtex->blendtype==MTEX_MUL) {
+ R.wrld.horr= (facm+fact*Tr)*wrld_hor->horr;
+ R.wrld.horg= (facm+fact*Tg)*wrld_hor->horg;
+ R.wrld.horb= (facm+fact*Tb)*wrld_hor->horb;
+ }
+ else {
+ R.wrld.horr= (fact*Tr + wrld_hor->horr);
+ R.wrld.horg= (fact*Tg + wrld_hor->horg);
+ R.wrld.horb= (fact*Tb + wrld_hor->horb);
+ }
+ wrld_hor= &R.wrld;
+ }
+ if(mtex->mapto & (WOMAP_ZENUP+WOMAP_ZENDOWN)) {
+ ok= 0;
+ if(R.wrld.skytype & WO_SKYREAL) {
+ if((R.wrld.skytype & WO_ZENUP)) {
+ if(mtex->mapto & WOMAP_ZENUP) ok= 1;
+ }
+ else if(mtex->mapto & WOMAP_ZENDOWN) ok= 1;
+ }
+ else ok= 1;
+
+ if(ok) {
+
+ if(mtex->blendtype==MTEX_BLEND) {
+ R.wrld.zenr= (fact*Tr + facm*wrld_zen->zenr);
+ R.wrld.zeng= (fact*Tg + facm*wrld_zen->zeng);
+ R.wrld.zenb= (fact*Tb + facm*wrld_zen->zenb);
+ }
+ else if(mtex->blendtype==MTEX_MUL) {
+ R.wrld.zenr= (facm+fact*Tr)*wrld_zen->zenr;
+ R.wrld.zeng= (facm+fact*Tg)*wrld_zen->zeng;
+ R.wrld.zenb= (facm+fact*Tb)*wrld_zen->zenb;
+ }
+ else {
+ R.wrld.zenr= (fact*Tr + wrld_zen->zenr);
+ R.wrld.zeng= (fact*Tg + wrld_zen->zeng);
+ R.wrld.zenb= (fact*Tb + wrld_zen->zenb);
+ }
+ wrld_zen= &R.wrld;
+ }
+ else {
+ /* anders blijft zenRGB hangen */
+ R.wrld.zenr= wrld_zen->zenr;
+ R.wrld.zeng= wrld_zen->zeng;
+ R.wrld.zenb= wrld_zen->zenb;
+ }
+ }
+ }
+ if(mtex->mapto & WOMAP_BLEND) {
+ if(rgb) Tin= (0.35*Tr+0.45*Tg+0.2*Tb);
+
+ fact= Tin*mtex->varfac;
+ facm= 1.0-fact;
+ if(mtex->blendtype==MTEX_MUL) facmul= 1.0-mtex->varfac;
+ if(mtex->blendtype==MTEX_SUB) fact= -fact;
+
+ factt= fact; facmm= facm;
+
+ if(mtex->blendtype==MTEX_BLEND)
+ R.inprz= factt*mtex->def_var+ facmm*R.inprz;
+ else if(mtex->blendtype==MTEX_MUL)
+ R.inprz= (facmul+factt)*R.inprz;
+ else {
+ R.inprz= factt+R.inprz;
+ }
+ }
+ }
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+/* explicit lampren stuff should be factored out! or rather, the
+ texturing stuff might need to go...*/
+void do_lamp_tex(LampRen *la, float *lavec)
+{
+ Object *ob;
+ LampRen *la_col;
+ MTex *mtex;
+ Tex *tex;
+ float *co = NULL, *dx = NULL, *dy = NULL, fact, facm, stencilTin=1.0;
+ float texvec[3], dxt[3], dyt[3], tempvec[3];
+ int tex_nr, rgb= 0;
+
+ /* hier flag testen of er wel tex is */
+
+ la_col= la->org;
+
+ tex_nr= 0;
+
+ for(; tex_nr<6; tex_nr++) {
+
+ if(la->mtex[tex_nr]) {
+ mtex= la->mtex[tex_nr];
+
+ tex= mtex->tex;
+ if(tex==0) continue;
+
+ /* welke coords */
+ if(mtex->texco==TEXCO_OBJECT) {
+ ob= mtex->object;
+ if(ob) {
+ co= tempvec;
+ dx= dxt;
+ dy= dyt;
+ VECCOPY(tempvec, R.co);
+ MTC_Mat4MulVecfl(ob->imat, tempvec);
+ if(R.osatex) {
+ VECCOPY(dxt, O.dxco);
+ VECCOPY(dyt, O.dyco);
+ MTC_Mat4Mul3Vecfl(ob->imat, dxt);
+ MTC_Mat4Mul3Vecfl(ob->imat, dyt);
+ }
+ }
+ else {
+ co= R.co;
+ dx= O.dxco; dy= O.dyco;
+ }
+ }
+ else if(mtex->texco==TEXCO_GLOB) {
+ co= R.gl; dx= O.dxco; dy= O.dyco;
+ VECCOPY(R.gl, R.co);
+ MTC_Mat4MulVecfl(R.viewinv, R.gl);
+ }
+ else if(mtex->texco==TEXCO_VIEW) {
+
+ VECCOPY(tempvec, lavec);
+ MTC_Mat3MulVecfl(la->imat, tempvec);
+
+ tempvec[0]*= la->spottexfac;
+ tempvec[1]*= la->spottexfac;
+ co= tempvec;
+
+ dx= dxt; dy= dyt;
+ if(R.osatex) {
+ VECCOPY(dxt, O.dxlv);
+ VECCOPY(dyt, O.dylv);
+ /* need some matrix conversion here? la->imat is a [3][3] matrix!!! **/
+ MTC_Mat3MulVecfl(la->imat, dxt);
+ MTC_Mat3MulVecfl(la->imat, dyt);
+
+ VecMulf(dxt, la->spottexfac);
+ VecMulf(dyt, la->spottexfac);
+ }
+ }
+
+
+ /* placement */
+ if(mtex->projx) texvec[0]= mtex->size[0]*(co[mtex->projx-1]+mtex->ofs[0]);
+ else texvec[0]= mtex->size[0]*(mtex->ofs[0]);
+
+ if(mtex->projy) texvec[1]= mtex->size[1]*(co[mtex->projy-1]+mtex->ofs[1]);
+ else texvec[1]= mtex->size[1]*(mtex->ofs[1]);
+
+ if(mtex->projz) texvec[2]= mtex->size[2]*(co[mtex->projz-1]+mtex->ofs[2]);
+ else texvec[2]= mtex->size[2]*(mtex->ofs[2]);
+
+ if(R.osatex) {
+ if(mtex->projx) {
+ dxt[0]= mtex->size[0]*dx[mtex->projx-1];
+ dyt[0]= mtex->size[0]*dy[mtex->projx-1];
+ }
+ else dxt[0]= 0.0;
+ if(mtex->projy) {
+ dxt[1]= mtex->size[1]*dx[mtex->projy-1];
+ dyt[1]= mtex->size[1]*dy[mtex->projy-1];
+ }
+ else dxt[1]= 0.0;
+ if(mtex->projx) {
+ dxt[2]= mtex->size[2]*dx[mtex->projz-1];
+ dyt[2]= mtex->size[2]*dy[mtex->projz-1];
+ }
+ else dxt[2]= 0.0;
+ }
+
+ /* texture */
+ if(tex->type==TEX_IMAGE) {
+ do_2d_mapping(mtex, texvec, dxt, dyt);
+
+ if(mtex->mapto & MAP_NORM) {
+ /* de pointer bepaalt of er gebumpt wordt */
+ tex->nor= R.vn;
+ if(mtex->maptoneg & MAP_NORM) tex->norfac= -mtex->norfac;
+ else tex->norfac= mtex->norfac;
+ }
+ else tex->nor= 0;
+ }
+
+ rgb= multitex(tex, texvec, dxt, dyt);
+
+
+
+ /* texture uitgang */
+ if(rgb && (mtex->texflag & MTEX_RGBTOINT)) {
+ Tin= (0.35*Tr+0.45*Tg+0.2*Tb);
+ rgb= 0;
+ }
+ if(mtex->texflag & MTEX_NEGATIVE) {
+ if(rgb) {
+ Tr= 1.0-Tr;
+ Tg= 1.0-Tg;
+ Tb= 1.0-Tb;
+ }
+ else Tin= 1.0-Tin;
+ }
+ if(mtex->texflag & MTEX_STENCIL) {
+ if(rgb) {
+ fact= Ta;
+ Ta*= stencilTin;
+ stencilTin*= fact;
+ }
+ else {
+ fact= Tin;
+ Tin*= stencilTin;
+ stencilTin*= fact;
+ }
+ }
+ else {
+ if(rgb) Ta*= stencilTin;
+ else Tin*= stencilTin;
+ }
+
+ /* mapping */
+ if(mtex->mapto & LAMAP_COL) {
+
+ if(rgb==0) {
+ Tr= mtex->r;
+ Tg= mtex->g;
+ Tb= mtex->b;
+ }
+ else if(mtex->mapto & MAP_ALPHA) {
+ if(mtex->texflag & MTEX_ALPHAMIX) Tin= Ta;
+ else Tin= stencilTin;
+ }
+ else Tin= Ta;
+
+ Tr*= la->energy;
+ Tg*= la->energy;
+ Tb*= la->energy;
+
+ fact= Tin*mtex->colfac;
+ facm= 1.0-fact;
+ if(mtex->blendtype==MTEX_MUL) facm= 1.0-mtex->colfac;
+ if(mtex->blendtype==MTEX_SUB) fact= -fact;
+
+ if(mtex->blendtype==MTEX_BLEND) {
+ la->r= (fact*Tr + facm*la_col->r);
+ la->g= (fact*Tg + facm*la_col->g);
+ la->b= (fact*Tb + facm*la_col->b);
+ }
+ else if(mtex->blendtype==MTEX_MUL) {
+ la->r= (facm+fact*Tr)*la_col->r;
+ la->g= (facm+fact*Tg)*la_col->g;
+ la->b= (facm+fact*Tb)*la_col->b;
+ }
+ else {
+ la->r= (fact*Tr + la_col->r);
+ la->g= (fact*Tg + la_col->g);
+ la->b= (fact*Tb + la_col->b);
+ }
+ la_col= la; /* Is it just me or is this a useless statement? */
+ }
+
+ }
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
+void externtex(MTex *mtex, float *vec)
+{
+ Tex *tex;
+ float dxt[3], dyt[3], texvec[3];
+ int rgb;
+
+ tex= mtex->tex;
+ if(tex==0) return;
+
+ R.osatex= 0;
+ R.vlr= 0;
+
+ /* placement */
+ if(mtex->projx) texvec[0]= mtex->size[0]*(vec[mtex->projx-1]+mtex->ofs[0]);
+ else texvec[0]= mtex->size[0]*(mtex->ofs[0]);
+
+ if(mtex->projy) texvec[1]= mtex->size[1]*(vec[mtex->projy-1]+mtex->ofs[1]);
+ else texvec[1]= mtex->size[1]*(mtex->ofs[1]);
+
+ if(mtex->projz) texvec[2]= mtex->size[2]*(vec[mtex->projz-1]+mtex->ofs[2]);
+ else texvec[2]= mtex->size[2]*(mtex->ofs[2]);
+
+ /* texture */
+ if(tex->type==TEX_IMAGE) {
+ do_2d_mapping(mtex, texvec, dxt, dyt);
+
+ if(mtex->mapto & MAP_NORM) {
+ /* de pointer bepaalt of er gebumpt wordt */
+ tex->nor= R.vn;
+ if(mtex->maptoneg & MAP_NORM) tex->norfac= -mtex->norfac;
+ else tex->norfac= mtex->norfac;
+ }
+ else tex->nor= 0;
+ }
+
+ rgb= multitex(tex, texvec, dxt, dyt);
+ if(rgb) {
+ Tin= (0.35*Tr+0.45*Tg+0.2*Tb);
+ }
+ else {
+ Tr= mtex->r;
+ Tg= mtex->g;
+ Tb= mtex->b;
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
+void externtexcol(MTex *mtex, float *orco, char *col)
+{
+ int temp;
+ float b1;
+
+ if(mtex->tex==0) return;
+
+ externtex(mtex, orco);
+
+ b1= 1.0-Tin;
+
+ temp= 255*(Tin*Tr)+b1*col[0];
+ if(temp>255) col[0]= 255; else col[0]= temp;
+ temp= 255*(Tin*Tg)+b1*col[1];
+ if(temp>255) col[1]= 255; else col[1]= temp;
+ temp= 255*(Tin*Tb)+b1*col[2];
+ if(temp>255) col[2]= 255; else col[2]= temp;
+
+}
+
+/* ------------------------------------------------------------------------- */
+
+void render_realtime_texture()
+{
+ static Tex tex;
+ static int firsttime= 1;
+ float texvec[2], dx[2], dy[2];
+
+ if(firsttime) {
+ default_tex(&tex);
+ tex.type= TEX_IMAGE;
+ firsttime= 0;
+ }
+
+ tex.ima = R.vlr->tface->tpage;
+ if(tex.ima) {
+
+ texvec[0]= 0.5+0.5*R.uv[0];
+ texvec[1]= 0.5+0.5*R.uv[1];
+ if(R.osatex) {
+ dx[0]= 0.5*O.dxuv[0];
+ dx[1]= 0.5*O.dxuv[1];
+ dy[0]= 0.5*O.dyuv[0];
+ dy[1]= 0.5*O.dyuv[1];
+ }
+
+ if(R.osatex) imagewraposa(&tex, texvec, dx, dy);
+ else imagewrap(&tex, texvec);
+
+ R.vcol[0]*= Tr;
+ R.vcol[1]*= Tg;
+ R.vcol[2]*= Tb;
+ }
+
+
+}
+
+/* eof */
diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c
new file mode 100644
index 00000000000..d0f3ba4cb1a
--- /dev/null
+++ b/source/blender/blenkernel/intern/world.c
@@ -0,0 +1,201 @@
+
+/* world.c MIX MODEL
+ *
+ * april 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 <string.h>
+#include <math.h>
+#include "MEM_guardedalloc.h"
+
+#include "DNA_world_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_scriptlink_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_object_types.h"
+#include "DNA_camera_types.h"
+
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "BKE_bad_level_calls.h"
+#include "BKE_utildefines.h"
+
+#include "BKE_library.h"
+#include "BKE_world.h"
+#include "BKE_global.h"
+#include "BPY_extern.h"
+#include "BKE_main.h"
+
+
+void free_world(World *wrld)
+{
+ MTex *mtex;
+ int a;
+
+ BPY_free_scriptlink(&wrld->scriptlink);
+
+ for(a=0; a<8; a++) {
+ mtex= wrld->mtex[a];
+ if(mtex && mtex->tex) mtex->tex->id.us--;
+ if(mtex) MEM_freeN(mtex);
+ }
+ wrld->ipo= 0;
+}
+
+
+World *add_world(char *name)
+{
+ World *wrld;
+
+ wrld= alloc_libblock(&G.main->world, ID_WO, name);
+
+ wrld->horb= 0.6f;
+ wrld->skytype= WO_SKYBLEND;
+ wrld->exposure= 1.0f;
+ wrld->stardist= 15.0f;
+ wrld->starsize= 2.0f;
+ wrld->gravity= 9.8f;
+
+ return wrld;
+}
+
+World *copy_world(World *wrld)
+{
+ World *wrldn;
+ int a;
+
+ wrldn= copy_libblock(wrld);
+
+ for(a=0; a<8; a++) {
+ if(wrld->mtex[a]) {
+ wrldn->mtex[a]= MEM_mallocN(sizeof(MTex), "copymaterial");
+ memcpy(wrldn->mtex[a], wrld->mtex[a], sizeof(MTex));
+ id_us_plus((ID *)wrldn->mtex[a]->tex);
+ }
+ }
+
+ BPY_copy_scriptlink(&wrld->scriptlink);
+
+ id_us_plus((ID *)wrldn->ipo);
+
+ return wrldn;
+}
+
+void make_local_world(World *wrld)
+{
+ Scene *sce;
+ World *wrldn;
+ int local=0, lib=0;
+
+ /* - zijn er alleen lib users: niet doen
+ * - zijn er alleen locale users: flag zetten
+ * - mixed: copy
+ */
+
+ if(wrld->id.lib==0) return;
+ if(wrld->id.us==1) {
+ wrld->id.lib= 0;
+ wrld->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)wrld, 0);
+ return;
+ }
+
+ sce= G.main->scene.first;
+ while(sce) {
+ if(sce->world==wrld) {
+ if(sce->id.lib) lib= 1;
+ else local= 1;
+ }
+ sce= sce->id.next;
+ }
+
+ if(local && lib==0) {
+ wrld->id.lib= 0;
+ wrld->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)wrld, 0);
+ }
+ else if(local && lib) {
+ wrldn= copy_world(wrld);
+ wrldn->id.us= 0;
+
+ sce= G.main->scene.first;
+ while(sce) {
+ if(sce->world==wrld) {
+ if(sce->id.lib==0) {
+ sce->world= wrldn;
+ wrldn->id.us++;
+ wrld->id.us--;
+ }
+ }
+ sce= sce->id.next;
+ }
+ }
+}
+
+
+void init_render_world()
+{
+ int a;
+ char *cp;
+
+ if(G.scene->world) {
+ R.wrld= *(G.scene->world);
+
+ cp= (char *)&R.wrld.fastcol;
+
+ cp[0]= 255.0*R.wrld.horr;
+ cp[1]= 255.0*R.wrld.horg;
+ cp[2]= 255.0*R.wrld.horb;
+ cp[3]= 1;
+
+ VECCOPY(R.grvec, R.viewmat[2]);
+ Normalise(R.grvec);
+ Mat3CpyMat4(R.imat, R.viewinv);
+
+ for(a=0; a<6; a++) if(R.wrld.mtex[a] && R.wrld.mtex[a]->tex) R.wrld.skytype |= WO_SKYTEX;
+
+ if(G.scene->camera && G.scene->camera->type==OB_CAMERA) {
+ Camera *cam= G.scene->camera->data;
+ if(cam->type==CAM_ORTHO) {
+ /* dit is maar ongeveer */
+ R.wrld.miststa+= (float)fabs(R.viewmat[3][2]);
+ }
+ }
+ }
+ else {
+ memset(&R.wrld, 0, sizeof(World));
+ R.wrld.exposure= 1.0;
+ }
+}
diff --git a/source/blender/blenkernel/intern/writeavi.c b/source/blender/blenkernel/intern/writeavi.c
new file mode 100644
index 00000000000..109553c816e
--- /dev/null
+++ b/source/blender/blenkernel/intern/writeavi.c
@@ -0,0 +1,147 @@
+/**
+ * Functions for writing avi-format files.
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 <string.h>
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+#include "MEM_guardedalloc.h"
+#include "BLI_blenlib.h"
+
+#include "AVI_avi.h"
+
+#include "BKE_bad_level_calls.h"
+#include "BKE_global.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+static AviMovie *avi=NULL;
+static int sframe;
+
+void makeavistring (char *string)
+{
+ char txt[64];
+
+ if (string==0) return;
+
+ strcpy(string, G.scene->r.pic);
+ BLI_convertstringcode(string, G.sce, G.scene->r.cfra);
+
+ RE_make_existing_file(string);
+
+ if (strcasecmp(string + strlen(string) - 4, ".avi")) {
+ sprintf(txt, "%04d_%04d.avi", (G.scene->r.sfra) , (G.scene->r.efra) );
+ strcat(string, txt);
+ }
+}
+
+void start_avi(void)
+{
+ int x, y;
+ char name[256];
+ AviFormat format;
+ int quality, framerate;
+
+ makeavistring(name);
+
+ sframe = (G.scene->r.sfra);
+ x = R.rectx;
+ y = R.recty;
+
+ quality= R.r.quality;
+ framerate= R.r.frs_sec;
+
+ avi = MEM_mallocN (sizeof(AviMovie), "avimovie");
+
+ if (R.r.imtype != AVI_FORMAT_MJPEG) format = AVI_FORMAT_AVI_RGB;
+ else format = AVI_FORMAT_MJPEG;
+
+ if (AVI_open_compress (name, avi, 1, format) != AVI_ERROR_NONE) {
+ error("open movie");
+ MEM_freeN (avi);
+ avi = NULL;
+ return;
+ }
+
+ AVI_set_compress_option (avi, AVI_OPTION_TYPE_MAIN, 0, AVI_OPTION_WIDTH, &x);
+ AVI_set_compress_option (avi, AVI_OPTION_TYPE_MAIN, 0, AVI_OPTION_HEIGHT, &y);
+ AVI_set_compress_option (avi, AVI_OPTION_TYPE_MAIN, 0, AVI_OPTION_QUALITY, &quality);
+ AVI_set_compress_option (avi, AVI_OPTION_TYPE_MAIN, 0, AVI_OPTION_FRAMERATE, &framerate);
+
+ avi->interlace= 0;
+ avi->odd_fields= 0;
+/* avi->interlace= R.r.mode & R_FIELDS; */
+/* avi->odd_fields= (R.r.mode & R_ODDFIELD)?1:0; */
+
+ printf("Created avi: %s\n", name);
+}
+
+void append_avi(int frame)
+{
+ unsigned int *rt1, *rt2, *temp;
+ int y;
+
+ if (avi == NULL) {
+ G.afbreek = 1;
+ return;
+ }
+
+ /* note that libavi free's the buffer... stupid interface - zr */
+ temp = MEM_mallocN(R.rectx*R.recty*4, "append_avi buf");
+
+ rt1= temp;
+ rt2= R.rectot + (R.recty-1)*R.rectx;
+ for (y=0; y < R.recty; y++, rt1+= R.rectx, rt2-= R.rectx) {
+ memcpy (rt1, rt2, R.rectx*4);
+ }
+
+ IMB_convert_rgba_to_abgr(R.rectx*R.recty, temp);
+
+ AVI_write_frame (avi, (frame-sframe), AVI_FORMAT_RGB32,
+ temp, R.rectx*R.recty*4);
+ printf ("added frame %3d (frame %3d in avi): ", frame, frame-sframe);
+}
+
+void end_avi(void)
+{
+ if (avi == NULL) return;
+
+ AVI_close_compress (avi);
+ MEM_freeN (avi);
+ avi= NULL;
+}
diff --git a/source/blender/blenlib/BLI_arithb.h b/source/blender/blenlib/BLI_arithb.h
new file mode 100644
index 00000000000..3c3fad3dcf2
--- /dev/null
+++ b/source/blender/blenlib/BLI_arithb.h
@@ -0,0 +1,758 @@
+#undef TEST_ACTIVE
+//#define ACTIVE 1
+/**
+ * blenlib/BLI_arithb.h mar 2001 Nzc
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 old math stuff from Ton. These will slowly phase out in favour
+ * of MTC calls. (or even MoTO :) )
+ * */
+
+#ifndef BLI_ARITHB_H
+#define BLI_ARITHB_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MAT4_UNITY {{ 1.0, 0.0, 0.0, 0.0},\
+ { 0.0, 1.0, 0.0, 0.0},\
+ { 0.0, 0.0, 1.0, 0.0},\
+ { 0.0, 0.0, 0.0, 1.0}}
+
+#define MAT3_UNITY {{ 1.0, 0.0, 0.0},\
+ { 0.0, 1.0, 0.0},\
+ { 0.0, 0.0, 1.0}}
+
+
+/* matrix operations */
+/* void Mat4MulMat4(float m1[][4], float m2[][4], float m3[][4]); */
+/* void Mat3MulVecfl(float mat[][3], float *vec); */
+/* or **mat, but it's the same */
+/*void Mat3MulVecd(float mat[][3], double *vec); */
+
+/* void Mat4MulVecfl(float mat[][4], float *vec); */
+/* void Mat4MulSerie(float answ[][4], float m1[][4], float m2[][4], */
+/* float m3[][4], float m4[][4], float m5[][4], */
+/* float m6[][4], float m7[][4], float m8[][4]); */
+/* int Mat4Invert(float inverse[][4], float mat[][4]); */
+
+/* m2 to m1 */
+/* void Mat3CpyMat4(float m1p[][3], float m2p[][4]); */
+/* void Mat3CpyMat4(float *m1p, float *m2p); */
+
+/* m1 to m2 */
+/* void Mat3CpyMat3(float m1p[][3], float m2p[][3]); */
+/* void Mat3CpyMat3(float *m1p, float *m2p); */
+
+/* m2 to m1 */
+/* void Mat4CpyMat3(float m1p[][4], float m2p[][3]); */
+
+/* M1 = M3*M2 */
+/* void Mat3MulMat3(float m1[][3], float m2[][3], float m3[][3]); */
+/*void Mat3MulMat3(float *m1, float *m3, float *m2); */
+
+/* m1 = m2 * m3, ignore the elements on the 4th row/column of m3 */
+/*void Mat3IsMat3MulMat4(float m1[][3], float m2[][3], float m3[][4]); */
+
+/* m1 to m2 */
+/* void Mat4CpyMat4(float m1[][4], float m2[][4]); */
+/* void Mat4CpyMat4(float *m1, float *m2); */
+
+
+/* void Mat4Ortho(float mat[][4]); */
+/* void Mat4Mul3Vecfl(float mat[][4], float *vec); */
+/* void Mat4MulVec4fl(float mat[][4], float *vec); */
+/* void Mat4SwapMat4(float *m1, float *m2); */
+
+/* void Mat3Inv(float m1[][3], float m2[][3]); */
+/* void Mat4One(float m[][4]); */
+/* void Mat3One(float m[][3]); */
+
+
+ void
+CalcCent3f(
+ float *cent, const float *v1, const float *v2, const float *v3
+);
+
+ void
+CalcCent4f(
+ float *cent, const float *v1,
+ const float *v2, const float *v3,
+ const float *v4
+);
+
+ void
+Crossf(
+ float *c, const float *a, const float *b
+);
+
+/**
+ * Euler conversion routines
+ */
+
+ void
+EulToMat3(
+ const float *eul,
+ float mat[][3]
+);
+ void
+EulToMat4(
+ const float* eul,
+ float mat[][4]
+);
+
+ void
+Mat3ToEul(
+ const float tmat[][3],
+ float *eul
+);
+
+/**
+ * @section Quaternion arithmetic routines
+ */
+
+ void
+QuatToEul(
+ const float *quat,
+ float *eul
+);
+ void
+QuatOne(
+ float *
+);
+ void
+QuatMul(
+ float *,
+ const float *,
+ const float *
+);
+ void
+NormalQuat(
+ float *
+);
+ void
+VecRotToQuat(
+ const float *vec,
+ float phi,
+ float *quat
+);
+ void
+QuatSub(
+ float *q,
+ const float *q1,
+ float *q2
+);
+
+/**
+ * @section matrix multiplication can copying routines
+ */
+
+ void
+Mat3MulFloat(
+ float *m,
+ float f
+);
+ void
+Mat4MulFloat(
+ float *m,
+ float f
+);
+ void
+Mat4MulFloat3(
+ float *m,
+ float f
+);
+ void
+Mat3Transp(
+ float mat[][3]
+);
+ void
+Mat4Transp(
+ float mat[][4]
+);
+ int
+Mat4Invert(
+ float inverse[][4],
+ const float mat[][4]
+);
+ void
+Mat4InvertSimp(
+ float inverse[][4],
+ const float mat[][4]
+);
+ void
+Mat4Inv(
+ float *m1,
+ const float *m2
+);
+ void
+Mat4InvGG(
+ float out[][4],
+ const float in[][4]
+);
+ void
+Mat3CpyMat4(
+ float m1[][3],
+ const float m2[][4]
+);
+
+ void
+Mat3Inv(
+ float m1[][3],
+ const float m2[][3]
+);
+
+ void
+Mat4CpyMat3(
+ float m1[][4],
+ const float m2[][3]
+);
+
+ float
+Det2x2(
+ float a,float b,float c,float d
+);
+
+ float
+Det3x3(
+ float a1, float a2, float a3,
+ float b1, float b2, float b3,
+ float c1, float c2, float c3
+);
+
+ float
+Det4x4(
+ const float m[][4]
+);
+
+ void
+Mat4Adj(
+ float out[][4],
+ const float in[][4]
+);
+ void
+Mat3Adj(
+ float m1[][3],
+ const float m[][3]
+);
+ void
+Mat4MulMat4(
+ float m1[][4],
+ const float m2[][4],
+ const float m3[][4]
+);
+ void
+subMat4MulMat4(
+ float *m1,
+ const float *m2,
+ const float *m3
+);
+#ifndef TEST_ACTIVE
+ void
+Mat3MulMat3(
+ float m1[][3],
+ const float m3[][3],
+ const float m2[][3]
+);
+#else
+ void
+Mat3MulMat3(
+ float *m1,
+ const float *m3,
+ const float *m2
+);
+#endif
+ void
+Mat4MulMat34(
+ float (*m1)[4],
+ const float (*m3)[3],
+ const float (*m2)[4]
+);
+ void
+Mat4CpyMat4(
+ float m1[][4],
+ const float m2[][4]
+);
+ void
+Mat4SwapMat4(
+ float *m1,
+ float *m2
+);
+ void
+Mat3CpyMat3(
+ float m1[][3],
+ const float m2[][3]
+);
+ void
+Mat3MulSerie(
+ float answ[][3],
+ const float m1[][3], const float m2[][3], const float m3[][3],
+ const float m4[][3], const float m5[][3], const float m6[][3],
+ const float m7[][3], const float m8[][3]
+);
+ void
+Mat4MulSerie(
+ float answ[][4],
+ const float m1[][4],
+ const float m2[][4], const float m3[][4], const float m4[][4],
+ const float m5[][4], const float m6[][4], const float m7[][4],
+ const float m8[][4]
+);
+ void
+Mat4Clr(
+ float *m
+);
+ void
+Mat3Clr(
+ float *m
+);
+ void
+Mat3One(
+ float m[][3]
+);
+ void
+Mat4MulVec(
+ const float mat[][4],
+ int *vec
+);
+ void
+VecMat4MulVecfl(
+ float *in,
+ const float mat[][4],
+ const float *vec
+);
+ void
+Mat4MulMat43(
+ float (*m1)[4],
+ const float (*m3)[4],
+ const float (*m2)[3]
+);
+
+ void
+Mat3IsMat3MulMat4(
+ float m1[][3],
+ const float m2[][3],
+ const float m3[][4]
+);
+ void
+Mat4One(
+ float m[][4]
+);
+ void
+Mat4Mul3Vecfl(
+ const float mat[][4],
+ float *vec
+);
+ void
+Mat4MulVec4fl(
+ const float mat[][4],
+ float *vec
+);
+ void
+Mat3MulVec(
+ const float mat[][3],
+ int *vec
+);
+ void
+Mat4MulVecfl(
+ const float mat[][4],
+ float *vec
+);
+ void
+Mat4ToQuat(
+ const float m[][4],
+ float *q
+);
+ void
+VecUpMat3old(
+ const float *vec,
+ float mat[][3],
+ short axis
+);
+ int
+FloatCompare(
+ const float *v1,
+ const float *v2,
+ float limit
+);
+ float
+Normalise(
+ float *n
+);
+ float
+CalcNormFloat(
+ const float *v1,
+ const float *v2,
+ const float *v3,
+ float *n
+);
+
+ float
+CalcNormFloat4(
+ const float *v1,
+ const float *v2,
+ const float *v3,
+ const float *v4,
+ float *n
+);
+ float
+VecLenf(
+ const float *v1,
+ const float *v2
+);
+ void
+VecMulf(
+ float *v1,
+ float f
+);
+ int
+VecCompare(
+ const float *v1,
+ const float *v2,
+ float limit
+);
+ float
+Sqrt3f(
+ float f
+);
+ double
+Sqrt3d(
+ double d
+);
+
+ void
+euler_rot(
+ float *beul,
+ float ang,
+ char axis
+);
+ float
+saacos(
+ float fac
+);
+ float
+sasqrt(
+ float fac
+);
+ float
+Inpf(
+ const float *v1,
+ const float *v2
+);
+ void
+VecSubf(
+ float *v,
+ const float *v1,
+ const float *v2
+);
+ void
+VecAddf(
+ float *v,
+ const float *v1,
+ const float *v2
+);
+ void
+VecUpMat3(
+ float *vec,
+ float mat[][3],
+ short axis
+);
+ float
+DistVL2Dfl(
+ const float *v1,
+ const float *v2,
+ const float *v3
+);
+ float
+PdistVL2Dfl(
+ const float *v1,
+ const float *v2,
+ const float *v3
+);
+ float
+AreaF2Dfl(
+ const float *v1,
+ const float *v2,
+ const float *v3
+);
+ float
+AreaQ3Dfl(
+ const float *v1,
+ const float *v2,
+ const float *v3,
+ const float *v4
+);
+ float
+AreaT3Dfl(
+ const float *v1,
+ const float *v2,
+ const float *v3
+);
+ float
+AreaPoly3Dfl(
+ int nr,
+ const float *verts,
+ const float *normal
+);
+ void
+VecRotToMat3(
+ const float *vec,
+ float phi,
+ float mat[][3]
+);
+ float *
+vectoquat(
+ const float *vec,
+ short axis,
+ short upflag
+);
+
+ void
+i_lookat(
+ float vx, float vy,
+ float vz, float px,
+ float py, float pz,
+ float twist, float mat[][4]
+);
+ void
+i_window(
+ float left, float right,
+ float bottom, float top,
+ float nearClip, float farClip,
+ float mat[][4]
+);
+
+ void
+hsv_to_rgb(
+ float h, float s,
+ float v, float *r,
+ float *g, float *b
+);
+
+ void
+rgb_to_hsv(
+ float r, float g, float b,
+ float *lh, float *ls, float *lv
+);
+ unsigned int
+hsv_to_cpack(
+ float h, float s, float v
+);
+ unsigned int
+rgb_to_cpack(
+ float r, float g, float b
+);
+ void
+cpack_to_rgb(
+ unsigned int col,
+ float *r, float *g, float *b
+);
+
+ void
+EulToQuat(
+ const float *eul,
+ float *quat
+);
+
+ void
+Mat3MulVecfl(
+ const float mat[][3],
+ float *vec
+);
+ void
+Mat3MulVecd(
+ const float mat[][3],
+ double *vec
+);
+ void
+Mat3TransMulVecfl(
+ const float mat[][3],
+ float *vec
+);
+ void
+VecStar(
+ float mat[][3],
+ const float *vec
+);
+ short
+EenheidsMat(
+ float mat[][3]
+);
+ void
+printmatrix3(
+ const char *str, const float m[][3]
+);
+ void
+QuatToMat3(
+ const float *q,
+ float m[][3]
+);
+ void
+QuatToMat4(
+ const float *q,
+ float m[][4]
+);
+ void
+QuatToSpher(
+ const float *quat,
+ float *sph
+);
+ void
+Mat3ToSpher(
+ const float *mat,
+ float *sph
+);
+ void
+Mat3ToQuat_is_ok(
+ const float wmat[][3],
+ float *q
+);
+ void
+i_ortho(
+ float left, float right,
+ float bottom, float top,
+ float nearClip, float farClip,
+ float matrix[][4]
+);
+ void
+i_polarview(
+ float dist, float azimuth, float incidence, float twist,
+ float Vm[][4]
+);
+ void
+Mat3Ortho(
+ float mat[][3]
+);
+ void
+Mat4Ortho(
+ float mat[][4]
+);
+ void
+VecCopyf(
+ float *v1,
+ const float *v2
+);
+ int
+VecLen(
+ const int *v1,
+ const int *v2
+);
+ void
+CalcNormShort(
+ const short *v1,
+ const short *v2,
+ const short *v3,
+ float *n
+) /* is ook uitprodukt */;
+
+ void
+CalcNormLong(
+ const int* v1,
+ const int*v2,
+ const int*v3,
+ float *n
+);
+ void
+MinMax3(
+ float *min,
+ float *max,
+ const float *vec
+);
+ void
+Mat3ToEuln(
+ const float tmat[][3],
+ float *eul
+);
+ void
+SizeToMat3(
+ const float *size,
+ float mat[][3]
+);
+ void
+printmatrix4(
+ const char *str,
+ const float m[][4]
+);
+/* uit Sig.Proc.85 pag 253 */
+ void
+Mat3ToQuat(
+ const float wmat[][3],
+ float *q
+);
+ void
+i_translate(
+ float Tx,
+ float Ty,
+ float Tz,
+ float mat[][4]
+);
+ void
+i_multmatrix(
+ const float icand[][4],
+ float Vm[][4]
+);
+ void
+i_rotate(
+ float angle,
+ char axis,
+ float mat[][4]
+);
+ void
+VecMidf(
+ float *v, const float *v1, const float *v2
+);
+ void
+Mat3ToSize(
+ const float mat[][3], float *size
+);
+ void
+Mat4ToSize(
+ const float mat[][4], float *size
+);
+ void
+triatoquat(
+ const float *v1,
+ const float *v2,
+ const float *v3, float *quat
+);
+ void
+MinMaxRGB(
+ short c[]
+);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/source/blender/blenlib/BLI_blenlib.h b/source/blender/blenlib/BLI_blenlib.h
new file mode 100644
index 00000000000..5d27f60e95f
--- /dev/null
+++ b/source/blender/blenlib/BLI_blenlib.h
@@ -0,0 +1,325 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * @mainpage BLI - Blender LIbrary external interface
+ *
+ * @section about About the BLI module
+ *
+ * This is the external interface of the Blender Library. If you find
+ * a call to a BLI function that is not prototyped here, please add a
+ * prototype here. The library offers mathematical operations (mainly
+ * vector and matrix calculus), an abstraction layer for file i/o,
+ * functions for calculating Perlin noise, scanfilling services for
+ * triangles, and a system for guarded memory
+ * allocation/deallocation. There is also a patch to make MS Windows
+ * behave more or less Posix-compliant.
+ *
+ * @section issues Known issues with BLI
+ *
+ * - blenlib is written in C.
+ * - The posix-compliancy may move to a separate lib that deals with
+ * platform dependencies. (There are other platform-dependent
+ * fixes as well.)
+ * - The file i/o has some redundant code. It should be cleaned.
+ * - arithb.c is a very messy matrix library. We need a better
+ * solution.
+ * - vectorops.c is close to superfluous. It may disappear in the
+ * near future.
+ *
+ * @section dependencies Dependencies
+ *
+ * - The blenlib uses type defines from makesdna/, and functions from
+ * standard libraries.
+ *
+ * $Id$
+*/
+
+#ifndef BLI_BLENLIB_H
+#define BLI_BLENLIB_H
+
+#include "DNA_listBase.h" /* braindamage for the masses... needed
+ because fillvlakbase and fillvertbase are
+ used outside */
+
+extern ListBase fillvlakbase;
+extern ListBase fillvertbase;
+/**
+ * @attention Defined in scanfill.c
+ */
+extern ListBase filledgebase;
+extern int totblock;
+
+struct chardesc;
+struct direntry;
+struct rctf;
+struct rcti;
+struct EditVert;
+struct PackedFile;
+struct LinkNode;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* BLI_util.h */
+char *BLI_gethome(void);
+void BLI_make_file_string(char *relabase, char *string, char *dir, char *file);
+void BLI_make_exist(char *dir);
+void BLI_split_dirfile(char *string, char *dir, char *file);
+int BLI_testextensie(char *str, char *ext);
+void addlisttolist(ListBase *list1, ListBase *list2);
+void BLI_insertlink(struct ListBase *listbase, void *vprevlink, void *vnewlink);
+void * BLI_findlink(struct ListBase *listbase, int number);
+void BLI_freelistN(struct ListBase *listbase);
+void BLI_addtail(struct ListBase *listbase, void *vlink);
+void BLI_remlink(struct ListBase *listbase, void *vlink);
+void BLI_newname(char * name, int add);
+int BLI_stringdec(char *string, char *kop, char *staart, unsigned short *numlen);
+void BLI_stringenc(char *string, char *kop, char *staart, unsigned short numlen, int pic);
+void BLI_addhead(struct ListBase *listbase, void *vlink);
+void BLI_insertlinkbefore(struct ListBase *listbase, void *vnextlink, void *vnewlink);
+void BLI_freelist(struct ListBase *listbase);
+int BLI_countlist(struct ListBase *listbase);
+void BLI_freelinkN(ListBase *listbase, void *vlink);
+void BLI_splitdirstring(char *di,char *fi);
+
+ /**
+ * Blender's path code replacement function.
+ * Bases @a path strings leading with "//" by the
+ * directory @a basepath, and replaces instances of
+ * '#' with the @a framenum. Results are written
+ * back into @a path.
+ *
+ * @a path The path to convert
+ * @a basepath The directory to base relative paths with.
+ * @a framenum The framenumber to replace the frame code with.
+ * @retval Returns true if the path was relative (started with "//").
+ */
+int BLI_convertstringcode(char *path, char *basepath, int framenum);
+
+void BLI_makestringcode(char *fromfile, char *str);
+
+ /**
+ * Duplicates the cstring @a str into a newly mallocN'd
+ * string and returns it.
+ *
+ * @param str The string to be duplicated
+ * @retval Returns the duplicated string
+ */
+char* BLI_strdup(char *str);
+
+ /**
+ * Duplicates the first @a len bytes of cstring @a str
+ * into a newly mallocN'd string and returns it. @a str
+ * is assumed to be at least len bytes long.
+ *
+ * @param str The string to be duplicated
+ * @param len The number of bytes to duplicate
+ * @retval Returns the duplicated string
+ */
+char* BLI_strdupn(char *str, int len);
+
+ /**
+ * Like strncpy but ensures dst is always
+ * '\0' terminated.
+ *
+ * @param dst Destination for copy
+ * @param src Source string to copy
+ * @param maxncpy Maximum number of characters to copy (generally
+ * the size of dst)
+ * @retval Returns dst
+ */
+char* BLI_strncpy(char *dst, char *src, int maxncpy);
+
+ /**
+ * Compare two strings
+ *
+ * @retval True if the strings are equal, false otherwise.
+ */
+int BLI_streq(char *a, char *b);
+
+ /**
+ * Compare two strings without regard to case.
+ *
+ * @retval True if the strings are equal, false otherwise.
+ */
+int BLI_strcaseeq(char *a, char *b);
+
+ /**
+ * Read a file as ASCII lines. An empty list is
+ * returned if the file cannot be opened or read.
+ *
+ * @attention The returned list should be free'd with
+ * BLI_free_file_lines.
+ *
+ * @param name The name of the file to read.
+ * @retval A list of strings representing the file lines.
+ */
+struct LinkNode *BLI_read_file_as_lines(char *name);
+
+ /**
+ * Free the list returned by BLI_read_file_as_lines.
+ */
+void BLI_free_file_lines(struct LinkNode *lines);
+
+ /**
+ * Checks if name is a fully qualified filename to an executable.
+ * If not it searches $PATH for the file. On Windows it also
+ * adds the correct extension (.com .exe etc) from
+ * $PATHEXT if necessary. Also on Windows it translates
+ * the name to its 8.3 version to prevent problems with
+ * spaces and stuff. Final result is returned in fullname.
+ *
+ * @param fullname The full path and full name of the executable
+ * @param name The name of the executable (usually argv[0]) to be checked
+ */
+void BLI_where_am_i(char *fullname, char *name);
+
+/* BLI_storage.h */
+int BLI_filesize(int file);
+double BLI_diskfree(char *dir);
+char * BLI_getwdN(char * dir);
+void BLI_hide_dot_files(int set);
+unsigned int BLI_getdir(char *dirname, struct direntry **filelist);
+
+/**
+ * @attention Do not confuse with BLI_exists
+ */
+int BLI_exist(char *name);
+
+/* BLI_fileops.h */
+void BLI_recurdir_fileops(char *dirname);
+int BLI_link(char *file, char *to);
+int BLI_backup(char *file, char *from, char *to);
+
+
+/**
+ * @attention Do not confuse with BLI_exist
+ */
+int BLI_exists(char *file);
+int BLI_copy_fileops(char *file, char *to);
+int BLI_rename(char *from, char *to);
+int BLI_delete(char *file, int dir, int recursive);
+int BLI_move(char *file, char *to);
+int BLI_touch(char *file);
+char *BLI_last_slash(char *string);
+
+/* BLI_rct.c */
+/**
+ * Determine if a rect is empty. An empty
+ * rect is one with a zero (or negative)
+ * width or height.
+ *
+ * @return True if @a rect is empty.
+ */
+int BLI_rcti_is_empty(struct rcti * rect);
+void BLI_init_rctf(struct rctf *rect, float xmin, float xmax, float ymin, float ymax);
+int BLI_in_rcti(struct rcti * rect, int x, int y);
+int BLI_in_rctf(struct rctf *rect, float x, float y);
+int BLI_isect_rctf(struct rctf *src1, struct rctf *src2, struct rctf *dest);
+/* why oh why doesn't this work? */
+//void BLI_union_rctf(struct rctf *rct1, struct rctf *rct2);
+void BLI_union_rctf(struct rctf *rcta, struct rctf *rctb);
+
+/* scanfill.c: used in displist only... */
+struct EditVert *BLI_addfillvert(float *vec);
+struct EditEdge *BLI_addfilledge(struct EditVert *v1, struct EditVert *v2);
+int BLI_edgefill(int mode); /* DE HOOFD FILL ROUTINE */
+void BLI_end_edgefill(void);
+
+/* noise.h: */
+float BLI_hnoise(float noisesize, float x, float y, float z);
+float BLI_hnoisep(float noisesize, float x, float y, float z);
+float BLI_turbulence(float noisesize, float x, float y, float z, int nr);
+float BLI_turbulence1(float noisesize, float x, float y, float z, int nr);
+
+/* These callbacks are needed to make the lib finction properly */
+
+/**
+ * Set a function taking a char* as argument to flag errors. If the
+ * callback is not set, the error is discarded.
+ * @param f The function to use as callback
+ * @attention used in creator.c
+ */
+void BLI_setErrorCallBack(void (*f)(char*));
+
+/**
+ * Set a function to be able to interrupt the execution of processing
+ * in this module. If the function returns true, the execution will
+ * terminate gracefully. If the callback is not set, interruption is
+ * not possible.
+ * @param f The function to use as callback
+ * @attention used in creator.c
+ */
+void BLI_setInterruptCallBack(int (*f)(void));
+
+/**
+ * Before scanfilling is done, these two references need to be set. If
+ * the object reference is NULL, the function will fail. If the object
+ * is set, but no colour is available, colour can be omitted.
+ *
+ * @attention Also see BLI_setScanFillColourRef
+ */
+void BLI_setScanFillObjectRef(void* ob);
+
+/**
+ * Before scanfilling is done, these two references need to be set. If
+ * the object reference is NULL, the function will fail. If the object
+ * is set, but no colour is available, colour can be omitted.
+ *
+ * @attention Also see BLI_setScanFillObjectRef
+ */
+void BLI_setScanFillColourRef(char* c);
+
+#define PRNTSUB(type,arg) printf(#arg ": %" #type " ", arg)
+#define PRINT(t,v) {PRNTSUB(t,v); printf("\n");}
+#define PRINT2(t1,v1,t2,v2) {PRNTSUB(t1,v1); PRNTSUB(t2,v2); printf("\n");}
+#define PRINT3(t1,v1,t2,v2,t3,v3) {PRNTSUB(t1,v1); PRNTSUB(t2,v2); PRNTSUB(t3,v3); printf("\n");}
+#define PRINT4(t1,v1,t2,v2,t3,v3,t4,v4) {PRNTSUB(t1,v1); PRNTSUB(t2,v2); PRNTSUB(t3,v3); PRNTSUB(t4,v4); printf("\n");}
+
+/**
+ * @param array The array in question
+ * @retval The number of elements in the array.
+ */
+#define BLI_ARRAY_NELEMS(array) (sizeof((array))/sizeof((array)[0]))
+
+/**
+ * @param strct The structure of interest
+ * @param member The name of a member field of @a strct
+ * @retval The offset in bytes of @a member within @a strct
+ */
+#define BLI_STRUCT_OFFSET(strct, member) (((struct) 0).(membr))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/source/blender/blenlib/BLI_dynstr.h b/source/blender/blenlib/BLI_dynstr.h
new file mode 100644
index 00000000000..ada4a41b7f8
--- /dev/null
+++ b/source/blender/blenlib/BLI_dynstr.h
@@ -0,0 +1,89 @@
+/**
+ * @file BLI_dynstr.h
+ *
+ * A dynamically sized string ADT.
+ * This ADT is designed purely for dynamic string creation
+ * through appending, not for general usage, the intent is
+ * to build up dynamic strings using a DynStr object, then
+ * convert it to a c-string and work with that.
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BLI_DYNSTR_H
+#define BLI_DYNSTR_H
+
+struct DynStr;
+
+ /** The abstract DynStr type */
+typedef struct DynStr DynStr;
+
+ /**
+ * Create a new DynStr.
+ *
+ * @return Pointer to a new DynStr.
+ */
+DynStr* BLI_dynstr_new (void);
+
+ /**
+ * Append a c-string to a DynStr.
+ *
+ * @param ds The DynStr to append to.
+ * @param cstr The c-string to append.
+ */
+void BLI_dynstr_append (DynStr *ds, char *cstr);
+
+ /**
+ * Find the length of a DynStr.
+ *
+ * @param ds The DynStr of interest.
+ * @return The length of @a ds.
+ */
+int BLI_dynstr_get_len (DynStr *ds);
+
+ /**
+ * Get a DynStr's contents as a c-string.
+ * <i> The returned c-string should be free'd
+ * using BLI_freeN. </i>
+ *
+ * @param ds The DynStr of interest.
+ * @return The contents of @a ds as a c-string.
+ */
+char* BLI_dynstr_get_cstring (DynStr *ds);
+
+ /**
+ * Free the DynStr
+ *
+ * @param ds The DynStr to free.
+ */
+void BLI_dynstr_free (DynStr *ds);
+
+#endif
diff --git a/source/blender/blenlib/BLI_editVert.h b/source/blender/blenlib/BLI_editVert.h
new file mode 100644
index 00000000000..4ee30493113
--- /dev/null
+++ b/source/blender/blenlib/BLI_editVert.h
@@ -0,0 +1,73 @@
+/**
+ * blenlib/BLI_editVert.h mar 2001 Nzc
+ *
+ * Some editing types needed in the lib (unfortunately) for
+ * scanfill.c
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BLI_EDITVERT_H
+#define BLI_EDITVERT_H
+
+typedef struct EditVert
+{
+ struct EditVert *next, *prev, *vn;
+ float no[3];
+ float co[3];
+ short xs, ys;
+ char f, h, f1, hash;
+ int totweight; /* __NLA */
+ struct MDeformWeight *dw; /* __NLA */
+} EditVert;
+
+typedef struct EditEdge
+{
+ struct EditEdge *next, *prev;
+ struct EditVert *v1, *v2, *vn;
+ short f,h;
+ short f1, dir;
+} EditEdge;
+
+typedef struct EditVlak
+{
+ struct EditVlak *next, *prev;
+ struct EditVert *v1, *v2, *v3, *v4;
+ struct EditEdge *e1, *e2, *e3, *e4;
+ float n[3];
+ float uv[4][2];
+ unsigned int col[4];
+ struct TFace *tface; /* a pointer to original tface. */
+ char mat_nr, flag;
+ char f, f1;
+} EditVlak;
+
+#endif
diff --git a/source/blender/blenlib/BLI_ghash.h b/source/blender/blenlib/BLI_ghash.h
new file mode 100644
index 00000000000..7af59a504f3
--- /dev/null
+++ b/source/blender/blenlib/BLI_ghash.h
@@ -0,0 +1,59 @@
+/**
+ * A general (pointer -> pointer) hash table ADT
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BLI_GHASH_H
+#define BLI_GHASH_H
+
+struct GHash;
+typedef struct GHash GHash;
+
+typedef unsigned int (*GHashHashFP) (void *key);
+typedef int (*GHashCmpFP) (void *a, void *b);
+typedef void (*GHashKeyFreeFP) (void *key);
+typedef void (*GHashValFreeFP) (void *val);
+
+GHash* BLI_ghash_new (GHashHashFP hashfp, GHashCmpFP cmpfp);
+void BLI_ghash_free (GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp);
+
+void BLI_ghash_insert (GHash *gh, void *key, void *val);
+void* BLI_ghash_lookup (GHash *gh, void *key);
+int BLI_ghash_haskey (GHash *gh, void *key);
+
+unsigned int BLI_ghashutil_ptrhash (void *key);
+int BLI_ghashutil_ptrcmp (void *a, void *b);
+
+unsigned int BLI_ghashutil_strhash (void *key);
+int BLI_ghashutil_strcmp (void *a, void *b);
+
+#endif
diff --git a/source/blender/blenlib/BLI_gsqueue.h b/source/blender/blenlib/BLI_gsqueue.h
new file mode 100644
index 00000000000..483f58a0185
--- /dev/null
+++ b/source/blender/blenlib/BLI_gsqueue.h
@@ -0,0 +1,95 @@
+/*
+ * A generic structure queue (a queue for fixed length
+ * (generally small) structures.
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BLI_GSQUEUE_H
+#define BLI_GSQUEUE_H
+
+typedef struct _GSQueue GSQueue;
+
+ /**
+ * Create a new GSQueue.
+ *
+ * @param elem_size The size of the structures in the queue.
+ * @retval The new queue
+ */
+GSQueue* BLI_gsqueue_new (int elem_size);
+
+ /**
+ * Query if the queue is empty
+ */
+int BLI_gsqueue_is_empty(GSQueue *gq);
+
+ /**
+ * Access the item at the head of the queue
+ * without removing it.
+ *
+ * @param item_r A pointer to an appropriatly
+ * sized structure (the size passed to BLI_gsqueue_new)
+ */
+void BLI_gsqueue_peek (GSQueue *gq, void *item_r);
+
+ /**
+ * Access the item at the head of the queue
+ * and remove it.
+ *
+ * @param item_r A pointer to an appropriatly
+ * sized structure (the size passed to BLI_gsqueue_new).
+ * Can be NULL if desired.
+ */
+void BLI_gsqueue_pop (GSQueue *gq, void *item_r);
+
+ /**
+ * Push an element onto the tail of the queue.
+ *
+ * @param item A pointer to an appropriatly
+ * sized structure (the size passed to BLI_gsqueue_new).
+ */
+void BLI_gsqueue_push (GSQueue *gq, void *item);
+
+ /**
+ * Push an element back onto the head of the queue (so
+ * it would be returned from the next call to BLI_gsqueue_pop).
+ *
+ * @param item A pointer to an appropriatly
+ * sized structure (the size passed to BLI_gsqueue_new).
+ */
+void BLI_qsueue_pushback (GSQueue *gq, void *item);
+
+ /**
+ * Free the queue
+ */
+void BLI_gsqueue_free (GSQueue *gq);
+
+#endif /* BLI_GSQUEUE_H */
diff --git a/source/blender/blenlib/BLI_linklist.h b/source/blender/blenlib/BLI_linklist.h
new file mode 100644
index 00000000000..eaa3a0ad2c5
--- /dev/null
+++ b/source/blender/blenlib/BLI_linklist.h
@@ -0,0 +1,60 @@
+/*
+ * Routines for working with singly linked lists
+ * of 'links' - pointers to other data.
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BLI_LINKLIST_H
+#define BLI_LINKLIST_H
+
+struct MemArena;
+
+typedef void (*LinkNodeFreeFP)(void *link);
+typedef void (*LinkNodeApplyFP)(void *link);
+
+struct LinkNode;
+typedef struct LinkNode {
+ struct LinkNode *next;
+ void *link;
+} LinkNode;
+
+int BLI_linklist_length (struct LinkNode *list);
+
+void BLI_linklist_reverse (struct LinkNode **listp);
+
+void BLI_linklist_prepend (struct LinkNode **listp, void *ptr);
+void BLI_linklist_prepend_arena (struct LinkNode **listp, void *ptr, struct MemArena *ma);
+
+void BLI_linklist_free (struct LinkNode *list, LinkNodeFreeFP freefunc);
+void BLI_linklist_apply (struct LinkNode *list, LinkNodeApplyFP applyfunc);
+
+#endif
diff --git a/source/blender/blenlib/BLI_memarena.h b/source/blender/blenlib/BLI_memarena.h
new file mode 100644
index 00000000000..4aa2c21452e
--- /dev/null
+++ b/source/blender/blenlib/BLI_memarena.h
@@ -0,0 +1,58 @@
+/*
+ * Memory arena ADT
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * Memory arena's are commonly used when the program
+ * needs to quickly allocate lots of little bits of
+ * data, which are all freed at the same moment.
+ *
+ */
+
+#ifndef BLI_MEMARENA_H
+#define BLI_MEMARENA_H
+
+ /* A reasonable standard buffer size, big
+ * enough to not cause much internal fragmentation,
+ * small enough not to waste resources
+ */
+#define BLI_MEMARENA_STD_BUFSIZE 4096
+
+struct MemArena;
+typedef struct MemArena MemArena;
+
+
+struct MemArena* BLI_memarena_new (int bufsize);
+void BLI_memarena_free (struct MemArena *ma);
+
+void* BLI_memarena_alloc (struct MemArena *ma, int size);
+
+#endif
diff --git a/source/blender/blenlib/BLI_rand.h b/source/blender/blenlib/BLI_rand.h
new file mode 100644
index 00000000000..05dc746e7e0
--- /dev/null
+++ b/source/blender/blenlib/BLI_rand.h
@@ -0,0 +1,68 @@
+/**
+ * @file BLI_rand.h
+ *
+ * Random number functions.
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BLI_RAND_H
+#define BLI_RAND_H
+
+ /** Seed the random number generator */
+void BLI_srand (unsigned int seed);
+
+ /** Return a pseudo-random number N where 0<=N<(2^31) */
+int BLI_rand (void);
+
+ /** Return a pseudo-random number N where 0.0<=N<1.0 */
+double BLI_drand (void);
+
+ /** Return a pseudo-random number N where 0.0f<=N<1.0f */
+float BLI_frand (void);
+
+ /** Fills a block of memory starting at @a addr
+ * and extending @a len bytes with pseudo-random
+ * contents. This routine does not use nor modify
+ * the state of the BLI random number generator.
+ */
+void BLI_fillrand (void *addr, int len);
+
+ /** Stores the BLI randum number generator state
+ * into the buffer in @a loc_r.
+ */
+void BLI_storerand (unsigned int loc_r[2]);
+
+ /** Retores the BLI randum number generator state
+ * from the buffer in @a loc.
+ */
+void BLI_restorerand (unsigned int loc[2]);
+
+#endif
diff --git a/source/blender/blenlib/BLI_storage_types.h b/source/blender/blenlib/BLI_storage_types.h
new file mode 100644
index 00000000000..9d5264c4cd1
--- /dev/null
+++ b/source/blender/blenlib/BLI_storage_types.h
@@ -0,0 +1,79 @@
+/**
+ * blenlib/BLI_storage_types.h
+ *
+ * Some types for dealing with directories
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BLI_STORAGE_TYPES_H
+#define BLI_STORAGE_TYPES_H
+
+#include <sys/stat.h>
+
+#define HDRSIZE 512
+#define NAMSIZE 200
+
+struct header{
+ char name[NAMSIZE];
+ unsigned int size;
+ unsigned int chksum;
+ char fill[HDRSIZE-NAMSIZE-2*sizeof(unsigned int)];
+};
+
+#ifdef WIN32
+typedef unsigned int mode_t;
+#endif
+
+struct direntry{
+ char *string;
+ mode_t type;
+ char *relname;
+ struct stat s;
+ unsigned int flags;
+ char size[16];
+ char mode1[4];
+ char mode2[4];
+ char mode3[4];
+ char owner[16];
+ char time[8];
+ char date[16];
+ char extra[16];
+ void *poin;
+ int nr;
+};
+
+struct dirlink
+{
+ struct dirlink *next,*prev;
+ char *name;
+};
+
+#endif /* BLI_STORAGE_TYPES_H */
diff --git a/source/blender/blenlib/BLI_vfontdata.h b/source/blender/blenlib/BLI_vfontdata.h
new file mode 100644
index 00000000000..3f2b03cba05
--- /dev/null
+++ b/source/blender/blenlib/BLI_vfontdata.h
@@ -0,0 +1,66 @@
+/**
+ * @file BLI_vfontdata.h
+ *
+ * A structure to represent vector fonts,
+ * and to load them from PostScript fonts.
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BLI_VFONTDATA_H
+#define BLI_VFONTDATA_H
+
+#include "DNA_listBase.h"
+
+struct PackedFile;
+
+#define MAX_VF_CHARS 256
+
+typedef struct VFontData {
+ ListBase nurbsbase[MAX_VF_CHARS];
+ float resol[MAX_VF_CHARS];
+ float width[MAX_VF_CHARS];
+ float *points[MAX_VF_CHARS];
+} VFontData;
+
+/**
+ * Construct a new VFontData structure from
+ * PostScript font data in a PackedFile.
+ *
+ * @param pf The font data.
+ * @retval A new VFontData structure, or NULL
+ * if unable to load.
+ */
+ VFontData*
+BLI_vfontdata_from_psfont(
+ struct PackedFile *pf);
+
+#endif
diff --git a/source/blender/blenlib/BLI_winstuff.h b/source/blender/blenlib/BLI_winstuff.h
new file mode 100644
index 00000000000..c376709ab84
--- /dev/null
+++ b/source/blender/blenlib/BLI_winstuff.h
@@ -0,0 +1,96 @@
+/**
+ * Compatibility-like things for windows.
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+#pragma warning(once: 4761 4305 4244 4018)
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+#undef near
+#undef far
+#undef rad
+#undef rad1
+#undef rad2
+#undef rad3
+#undef vec
+#undef rect
+#undef rct1
+#undef rct2
+
+#define near clipsta
+#define far clipend
+
+#undef small
+
+#ifndef __WINSTUFF_H__
+#define __WINSTUFF_H__
+
+#define M_PI 3.14159265358979323846
+#define M_PI_2 1.57079632679489661923
+#define M_SQRT2 1.41421356237309504880
+#define M_SQRT1_2 0.70710678118654752440
+
+#define MAXPATHLEN MAX_PATH
+
+#define S_ISREG(x) ((x&S_IFMT) == S_IFREG)
+#define S_ISDIR(x) ((x&S_IFMT) == S_IFDIR)
+
+typedef unsigned int mode_t;
+
+struct dirent {
+ int d_ino;
+ int d_off;
+ unsigned short d_reclen;
+ char *d_name;
+};
+
+typedef struct _DIR {
+ HANDLE handle;
+ WIN32_FIND_DATA data;
+ char path[MAX_PATH];
+ long dd_loc;
+ long dd_size;
+ char dd_buf[4096];
+ void *dd_direct;
+
+ struct dirent direntry;
+} DIR;
+
+void RegisterBlendExtension(char * str);
+int strcasecmp (char *s1, char *s2);
+int strncasecmp (char *s1, char *s2, int n);
+DIR *opendir (const char *path);
+struct dirent *readdir(DIR *dp);
+int closedir (DIR *dp);
+
+#endif /* __WINSTUFF_H__ */
diff --git a/source/blender/blenlib/MTC_matrixops.h b/source/blender/blenlib/MTC_matrixops.h
new file mode 100644
index 00000000000..2a57ba34136
--- /dev/null
+++ b/source/blender/blenlib/MTC_matrixops.h
@@ -0,0 +1,164 @@
+/*
+ * matrixops.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 MATRIXOPS_H
+#define MATRIXOPS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ------------------------------------------------------------------------- */
+/* need rewriting: */
+/**
+ * copy the left upp3 3 by 3 of m2 to m1
+ */
+void MTC_Mat3CpyMat4(float m1[][3], float m2[][4]);
+
+/* ------------------------------------------------------------------------- */
+/* operations based on 4 by 4 matrices */
+
+/**
+ * Copy m1 to m2
+ */
+void MTC_Mat4CpyMat4(float m1[][4], float m2[][4]);
+
+/**
+ * Multiply all matrices after the first, leave the result in the
+ * first argument
+ */
+void MTC_Mat4MulSerie(float answ[][4],
+ float m1[][4], float m2[][4], float m3[][4],
+ float m4[][4], float m5[][4], float m6[][4],
+ float m7[][4], float m8[][4]);
+
+/**
+ * m1 = m2 matprod m3
+ */
+void MTC_Mat4MulMat4(float m1[][4], float m2[][4], float m3[][4]);
+
+/**
+ * Do vec^t prod mat, result in vec. Ignore vec[3] (vec is a
+ * float[3])
+ */
+void MTC_Mat4MulVecfl(float mat[][4], float *vec);
+
+/**
+ * Invert mat, result in inverse. Always returns 1
+ */
+int MTC_Mat4Invert(float inverse[][4], float mat[][4]);
+
+/**
+ * Make the set of mat orthonormal (mat should already be orthogonal)?
+ * (doesn't appear to normalise properly?)
+ */
+void MTC_Mat4Ortho(float mat[][4]);
+
+/**
+ * vec = mat prod vec, result in vec, ignore fourth component entirely
+ * (4th component is _not_ accessed!!! vec is 3d)
+ */
+void MTC_Mat4Mul3Vecfl(float mat[][4], float *vec);
+
+/**
+ * vec = mat prod vec, result in vec
+ */
+void MTC_Mat4MulVec4fl(float mat[][4], float *vec);
+
+/**
+ * Set <m> to the 4-D unity matrix
+ */
+void MTC_Mat4One(float m[][4]);
+
+/**
+ * Swap matrices m1 and m2
+ */
+void MTC_Mat4SwapMat4(float m1[][4], float m2[][4]);
+
+/**
+ * Copy m2 to the top-left 3x3 of m1, don't touch the remaining elements.
+ */
+void MTC_Mat4CpyMat3nc(float m1[][4], float m2[][3]);
+
+/**
+ * m1 = m2 * m3, but only the top-left 3x3
+ */
+void MTC_Mat4MulMat33(float m1[][3], float m2[][4], float m3[][3]);
+
+/* ------------------------------------------------------------------------- */
+/* Operations based on 3 by 3 matrices */
+/**
+ * Do vec^t prod mat, result in vec.(vex is 3d)
+ */
+void MTC_Mat3MulVecfl(float mat[][3], float *vec);
+
+/**
+ * Copy m1 to m2
+ */
+void MTC_Mat3CpyMat3(float m1[][3], float m2[][3]);
+
+/**
+ * m1 = m2 prod m3
+ */
+void MTC_Mat3MulMat3(float m1[][3], float m3[][3], float m2[][3]);
+
+/**
+ * vec = vec prod mat
+ */
+void MTC_Mat3MulVecd(float mat[][3], double *vec);
+
+/**
+ * Guess: invert matrix
+ * result goes to m1
+ */
+void MTC_Mat3Inv(float m1[][3], float m2[][3]);
+
+/**
+ * Sort of a determinant matrix? Doesn't seem very adjoint to me...
+ * result goes to m1
+ */
+void MTC_Mat3Adj(float m1[][3], float m[][3]);
+
+/**
+ * Set <m> to the 3D unity matrix
+ */
+void MTC_Mat3One(float m[][3]);
+
+/* ------------------------------------------------------------------------- */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MATRIXOPS_H */
diff --git a/source/blender/blenlib/MTC_vectorops.h b/source/blender/blenlib/MTC_vectorops.h
new file mode 100644
index 00000000000..34cff44b9ae
--- /dev/null
+++ b/source/blender/blenlib/MTC_vectorops.h
@@ -0,0 +1,60 @@
+/*
+ * vectorops.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 VECTOROPS_H
+#define VECTOROPS_H
+
+/* ------------------------------------------------------------------------- */
+
+void MTC_diff3Int(int v1[3], int v2[3], int v3[3]);
+void MTC_cross3Int(int v1[3], int v2[3], int v3[3]);
+int MTC_dot3Int(int v1[3], int v2[3]);
+
+void MTC_diff3Float(float v1[3], float v2[3], float v3[3]);
+void MTC_cross3Float(float v1[3], float v2[3], float v3[3]);
+float MTC_dot3Float(float v1[3], float v2[3]);
+void MTC_cp3Float(float v1[3], float v2[3]);
+/**
+ * Copy vector with a minus sign (so a = -b)
+ */
+void MTC_cp3FloatInv(float v1[3], float v2[3]);
+
+void MTC_swapInt(int *i1, int *i2);
+
+void MTC_diff3DFF(double v1[3], float v2[3], float v3[3]);
+void MTC_cross3Double(double v1[3], double v2[3], double v3[3]);
+float MTC_normalise3DF(float n[3]);
+
+/* ------------------------------------------------------------------------- */
+#endif /* VECTOROPS_H */
diff --git a/source/blender/blenlib/Makefile b/source/blender/blenlib/Makefile
new file mode 100644
index 00000000000..12ee8c5ad8c
--- /dev/null
+++ b/source/blender/blenlib/Makefile
@@ -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 *****
+#
+# Bounces make to subdirectories.
+
+SOURCEDIR = source/blender/blenlib
+DIRS = intern
+
+include nan_subdirs.mk
diff --git a/source/blender/blenlib/PIL_dynlib.h b/source/blender/blenlib/PIL_dynlib.h
new file mode 100644
index 00000000000..2831b749385
--- /dev/null
+++ b/source/blender/blenlib/PIL_dynlib.h
@@ -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 *****
+ */
+#ifndef __PIL_DYNLIB_H__
+#define __PIL_DYNLIB_H__
+
+typedef struct PILdynlib PILdynlib;
+
+ PILdynlib*
+PIL_dynlib_open(
+ char *name);
+
+ void*
+PIL_dynlib_find_symbol(
+ PILdynlib* lib,
+ char *symname);
+
+ char*
+PIL_dynlib_get_error_as_string(
+ PILdynlib* lib);
+
+ void
+PIL_dynlib_close(
+ PILdynlib* lib);
+
+#endif /* __PIL_DYNLIB_H__ */
diff --git a/source/blender/blenlib/PIL_time.h b/source/blender/blenlib/PIL_time.h
new file mode 100644
index 00000000000..dbb4f5d5bbe
--- /dev/null
+++ b/source/blender/blenlib/PIL_time.h
@@ -0,0 +1,61 @@
+/**
+ * @file PIL_time.h
+ *
+ * Platform independant time functions.
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 PIL_TIME_H
+#define PIL_TIME_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern
+ /** Return an indication of time, expressed as
+ * seconds since some fixed point. Successive calls
+ * are guarenteed to generate values greator than or
+ * equal to the last call.
+ */
+double PIL_check_seconds_timer (void);
+
+ /**
+ * Platform-independant sleep function.
+ * @param ms Number of milliseconds to sleep
+ */
+void PIL_sleep_ms (int ms);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/source/blender/blenlib/intern/BLI_callbacks.h b/source/blender/blenlib/intern/BLI_callbacks.h
new file mode 100644
index 00000000000..072a274176d
--- /dev/null
+++ b/source/blender/blenlib/intern/BLI_callbacks.h
@@ -0,0 +1,44 @@
+/**
+ * blenlib/BLI_editVert.h mar 2001 Nzc
+ *
+ * These callbacks are needed in the lib
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BLI_CALLBACKS_H
+#define BLI_CALLBACKS_H
+
+// This is blenlib internal only
+void callLocalErrorCallBack(char* msg);
+int callLocalInterruptCallBack(void);
+
+#endif
diff --git a/source/blender/blenlib/intern/BLI_dynstr.c b/source/blender/blenlib/intern/BLI_dynstr.c
new file mode 100644
index 00000000000..c9b7737427a
--- /dev/null
+++ b/source/blender/blenlib/intern/BLI_dynstr.c
@@ -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 *****
+ * Dynamically sized string ADT
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_dynstr.h"
+
+/***/
+
+typedef struct DynStrElem DynStrElem;
+struct DynStrElem {
+ DynStrElem *next;
+
+ char *str;
+};
+
+struct DynStr {
+ DynStrElem *elems, *last;
+ int curlen;
+};
+
+/***/
+
+DynStr *BLI_dynstr_new(void) {
+ DynStr *ds= MEM_mallocN(sizeof(*ds), "DynStr");
+ ds->elems= ds->last= NULL;
+ ds->curlen= 0;
+
+ return ds;
+}
+
+void BLI_dynstr_append(DynStr *ds, char *cstr) {
+ DynStrElem *dse= malloc(sizeof(*dse));
+ int cstrlen= strlen(cstr);
+
+ dse->str= malloc(cstrlen+1);
+ memcpy(dse->str, cstr, cstrlen+1);
+ dse->next= NULL;
+
+ if (!ds->last)
+ ds->last= ds->elems= dse;
+ else
+ ds->last= ds->last->next= dse;
+
+ ds->curlen+= cstrlen;
+}
+
+int BLI_dynstr_get_len(DynStr *ds) {
+ return ds->curlen;
+}
+
+char *BLI_dynstr_get_cstring(DynStr *ds) {
+ char *s, *rets= MEM_mallocN(ds->curlen+1, "dynstr_cstring");
+ DynStrElem *dse;
+
+ for (s= rets, dse= ds->elems; dse; dse= dse->next) {
+ int slen= strlen(dse->str);
+
+ memcpy(s, dse->str, slen);
+
+ s+= slen;
+ }
+ rets[ds->curlen]= '\0';
+
+ return rets;
+}
+
+void BLI_dynstr_free(DynStr *ds) {
+ DynStrElem *dse;
+
+ for (dse= ds->elems; dse; ) {
+ DynStrElem *n= dse->next;
+
+ free(dse->str);
+ free(dse);
+
+ dse= n;
+ }
+
+ MEM_freeN(ds);
+}
diff --git a/source/blender/blenlib/intern/BLI_fileops.h b/source/blender/blenlib/intern/BLI_fileops.h
new file mode 100644
index 00000000000..22248d4f5e6
--- /dev/null
+++ b/source/blender/blenlib/intern/BLI_fileops.h
@@ -0,0 +1,49 @@
+/**
+ * blenlib/BLI_listBase.h mar 2001 Nzc
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * More low-level fileops from Daniel Dunbar. Two functions were also
+ * defined in storage.c. These are the old fop_ prefixes. There is
+ * definitely some redundancy here!
+ * */
+
+#ifndef BLI_FILEOPS_H
+#define BLI_FILEOPS_H
+
+char *first_slash(char *string);
+
+/* only for the sane unix world: direct calls to system functions :( */
+#ifndef WIN32
+void BLI_setCmdCallBack(int (*f)(char*));
+#endif
+
+#endif
diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c
new file mode 100644
index 00000000000..d0f1f78fb73
--- /dev/null
+++ b/source/blender/blenlib/intern/BLI_ghash.c
@@ -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 *****
+ * A general (pointer -> pointer) hash table ADT
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_ghash.h"
+
+/***/
+
+static unsigned int hashsizes[]= {
+ 1, 3, 5, 11, 17, 37, 67, 131, 257, 521, 1031, 2053, 4099, 8209,
+ 16411, 32771, 65537, 131101, 262147, 524309, 1048583, 2097169,
+ 4194319, 8388617, 16777259, 33554467, 67108879, 134217757,
+ 268435459
+};
+
+/***/
+
+typedef struct Entry Entry;
+struct Entry {
+ Entry *next;
+
+ void *key, *val;
+};
+
+struct GHash {
+ GHashHashFP hashfp;
+ GHashCmpFP cmpfp;
+
+ Entry **buckets;
+ int nbuckets, nentries, cursize;
+};
+
+/***/
+
+GHash *BLI_ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp) {
+ GHash *gh= MEM_mallocN(sizeof(*gh), "GHash");
+ gh->hashfp= hashfp;
+ gh->cmpfp= cmpfp;
+
+ gh->cursize= 0;
+ gh->nentries= 0;
+ gh->nbuckets= hashsizes[gh->cursize];
+
+ gh->buckets= malloc(gh->nbuckets*sizeof(*gh->buckets));
+ memset(gh->buckets, 0, gh->nbuckets*sizeof(*gh->buckets));
+
+ return gh;
+}
+
+void BLI_ghash_insert(GHash *gh, void *key, void *val) {
+ unsigned int hash= gh->hashfp(key)%gh->nbuckets;
+ Entry *e= malloc(sizeof(*e));
+
+ e->key= key;
+ e->val= val;
+ e->next= gh->buckets[hash];
+ gh->buckets[hash]= e;
+
+ if (++gh->nentries>gh->nbuckets*3) {
+ Entry *e, **old= gh->buckets;
+ int i, nold= gh->nbuckets;
+
+ gh->nbuckets= hashsizes[++gh->cursize];
+ gh->buckets= malloc(gh->nbuckets*sizeof(*gh->buckets));
+ memset(gh->buckets, 0, gh->nbuckets*sizeof(*gh->buckets));
+
+ for (i=0; i<nold; i++) {
+ for (e= old[i]; e;) {
+ Entry *n= e->next;
+
+ hash= gh->hashfp(e->key)%gh->nbuckets;
+ e->next= gh->buckets[hash];
+ gh->buckets[hash]= e;
+
+ e= n;
+ }
+ }
+
+ free(old);
+ }
+}
+
+void* BLI_ghash_lookup(GHash *gh, void *key) {
+ unsigned int hash= gh->hashfp(key)%gh->nbuckets;
+ Entry *e;
+
+ for (e= gh->buckets[hash]; e; e= e->next)
+ if (gh->cmpfp(key, e->key)==0)
+ return e->val;
+
+ return NULL;
+}
+
+int BLI_ghash_haskey(GHash *gh, void *key) {
+ unsigned int hash= gh->hashfp(key)%gh->nbuckets;
+ Entry *e;
+
+ for (e= gh->buckets[hash]; e; e= e->next)
+ if (gh->cmpfp(key, e->key)==0)
+ return 1;
+
+ return 0;
+}
+
+void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp) {
+ int i;
+
+ for (i=0; i<gh->nbuckets; i++) {
+ Entry *e;
+
+ for (e= gh->buckets[i]; e; ) {
+ Entry *n= e->next;
+
+ if (keyfreefp) keyfreefp(e->key);
+ if (valfreefp) valfreefp(e->val);
+ free(e);
+
+ e= n;
+ }
+ }
+
+ free(gh->buckets);
+ MEM_freeN(gh);
+}
+
+/***/
+
+unsigned int BLI_ghashutil_ptrhash(void *key) {
+ return (unsigned int) key;
+}
+int BLI_ghashutil_ptrcmp(void *a, void *b) {
+ if (a==b)
+ return 0;
+ else
+ return (a<b)?-1:1;
+}
+
+unsigned int BLI_ghashutil_strhash(void *ptr) {
+ char *s= ptr;
+ unsigned int i= 0;
+ unsigned char c;
+
+ while (c= *s++)
+ i= i*37 + c;
+
+ return i;
+}
+int BLI_ghashutil_strcmp(void *a, void *b) {
+ return strcmp(a, b);
+}
diff --git a/source/blender/blenlib/intern/BLI_linklist.c b/source/blender/blenlib/intern/BLI_linklist.c
new file mode 100644
index 00000000000..0c1275b6389
--- /dev/null
+++ b/source/blender/blenlib/intern/BLI_linklist.c
@@ -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 *****
+ * Support for linked lists.
+ */
+
+#include "MEM_guardedalloc.h"
+#include "BLI_blenlib.h"
+#include "BLI_linklist.h"
+#include "BLI_memarena.h"
+
+int BLI_linklist_length(LinkNode *list) {
+ if (0) {
+ return list?(1+BLI_linklist_length(list->next)):0;
+ } else {
+ int len;
+
+ for (len=0; list; list= list->next)
+ len++;
+
+ return len;
+ }
+}
+
+void BLI_linklist_reverse(LinkNode **listp) {
+ LinkNode *rhead= NULL, *cur= *listp;
+
+ while (cur) {
+ LinkNode *next= cur->next;
+
+ cur->next= rhead;
+ rhead= cur;
+
+ cur= next;
+ }
+
+ *listp= rhead;
+}
+
+void BLI_linklist_prepend(LinkNode **listp, void *ptr) {
+ LinkNode *nlink= MEM_mallocN(sizeof(*nlink), "nlink");
+ nlink->link= ptr;
+
+ nlink->next= *listp;
+ *listp= nlink;
+}
+
+void BLI_linklist_prepend_arena(LinkNode **listp, void *ptr, MemArena *ma) {
+ LinkNode *nlink= BLI_memarena_alloc(ma, sizeof(*nlink));
+ nlink->link= ptr;
+
+ nlink->next= *listp;
+ *listp= nlink;
+}
+
+void BLI_linklist_free(LinkNode *list, LinkNodeFreeFP freefunc) {
+ while (list) {
+ LinkNode *next= list->next;
+
+ if (freefunc)
+ freefunc(list->link);
+ MEM_freeN(list);
+
+ list= next;
+ }
+}
+
+void BLI_linklist_apply(LinkNode *list, LinkNodeApplyFP applyfunc) {
+ for (; list; list= list->next)
+ applyfunc(list->link);
+}
diff --git a/source/blender/blenlib/intern/BLI_memarena.c b/source/blender/blenlib/intern/BLI_memarena.c
new file mode 100644
index 00000000000..596624fcc9e
--- /dev/null
+++ b/source/blender/blenlib/intern/BLI_memarena.c
@@ -0,0 +1,80 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * Efficient memory allocation for lots of similar small chunks.
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_memarena.h"
+#include "BLI_linklist.h"
+
+struct MemArena {
+ unsigned char *curbuf;
+ int bufsize, cursize;
+
+ LinkNode *bufs;
+};
+
+MemArena *BLI_memarena_new(int bufsize) {
+ MemArena *ma= MEM_callocN(sizeof(*ma), "memarena");
+ ma->bufsize= bufsize;
+
+ return ma;
+}
+void BLI_memarena_free(MemArena *ma) {
+ BLI_linklist_free(ma->bufs, MEM_freeN);
+ MEM_freeN(ma);
+}
+
+ /* amt must be power of two */
+#define PADUP(num, amt) ((num+(amt-1))&~(amt-1))
+
+void *BLI_memarena_alloc(MemArena *ma, int size) {
+ void *ptr;
+
+ /* ensure proper alignment by rounding
+ * size up to multiple of 8 */
+ size= PADUP(size, 8);
+
+ if (size>=ma->cursize) {
+ ma->cursize= (size>ma->bufsize)?size:ma->bufsize;
+ ma->curbuf= MEM_mallocN(ma->cursize, "ma->curbuf");
+
+ BLI_linklist_prepend(&ma->bufs, ma->curbuf);
+ }
+
+ ptr= ma->curbuf;
+ ma->curbuf+= size;
+ ma->cursize-= size;
+
+ return ptr;
+}
diff --git a/source/blender/blenlib/intern/BLI_scanfill.h b/source/blender/blenlib/intern/BLI_scanfill.h
new file mode 100644
index 00000000000..405830b7a39
--- /dev/null
+++ b/source/blender/blenlib/intern/BLI_scanfill.h
@@ -0,0 +1,41 @@
+/**
+ * blenlib/BLI_scanfill.h mar 2001 Nzc
+ *
+ * Filling meshes.
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BLI_SCANFILL_H
+#define BLI_SCANFILL_H
+
+
+#endif
diff --git a/source/blender/blenlib/intern/BLI_storage.h b/source/blender/blenlib/intern/BLI_storage.h
new file mode 100644
index 00000000000..ba5385f70bf
--- /dev/null
+++ b/source/blender/blenlib/intern/BLI_storage.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 *****
+ */
+#ifndef BLI_STORAGE_H
+#define BLI_STORAGE_H
+
+#include "BLI_storage_types.h"
+
+void BLI_adddirstrings(void);
+void BLI_builddir(char *dirname, char *relname);
+int BLI_compare(struct direntry *entry1, struct direntry *entry2);
+
+#endif /* BLI_STORAGE_H */
diff --git a/source/blender/blenlib/intern/BLI_util.h b/source/blender/blenlib/intern/BLI_util.h
new file mode 100644
index 00000000000..2f78c1acc0c
--- /dev/null
+++ b/source/blender/blenlib/intern/BLI_util.h
@@ -0,0 +1,47 @@
+/**
+ * blenlib/BLI_storage_types.h
+ *
+ * Some types for dealing with directories
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BLI_UTIL_H
+#define BLI_UTIL_H
+
+#define mallocstructN(x,y,name) (x*)MEM_mallocN((y)* sizeof(x),name)
+#define callocstructN(x,y,name) (x*)MEM_callocN((y)* sizeof(x),name)
+
+
+struct ListBase;
+
+/* void addlisttolist(struct ListBase *list1, struct ListBase *list2); */
+
+#endif
diff --git a/source/blender/blenlib/intern/Makefile b/source/blender/blenlib/intern/Makefile
new file mode 100644
index 00000000000..ccca2fccf11
--- /dev/null
+++ b/source/blender/blenlib/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 *****
+#
+#
+
+LIBNAME = blenlib
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+ifeq ($(OS),$(findstring $(OS), "beos darwin freebsd linux openbsd solaris windows"))
+ CFLAGS += -funsigned-char
+endif
+
+CPPFLAGS += $(LEVEL_2_C_WARNINGS)
+
+# path to SDNA types
+CPPFLAGS += -I../../makesdna
+# path to our own external headerfiles
+CPPFLAGS += -I..
+# path to the guarded memory allocator
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+
diff --git a/source/blender/blenlib/intern/arithb.c b/source/blender/blenlib/intern/arithb.c
new file mode 100644
index 00000000000..49f5772c6c3
--- /dev/null
+++ b/source/blender/blenlib/intern/arithb.c
@@ -0,0 +1,2355 @@
+
+/* formules voor blender
+ *
+ * sort of cleaned up mar-01 nzc
+ *
+ * Functions here get counterparts with MTC prefixes. Basically, we phase
+ * out the calls here in favour of fully prototyped versions.
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/* ************************ FUNKTIES **************************** */
+
+#include <math.h>
+#include <sys/types.h>
+#include <string.h>
+#include <float.h>
+
+#ifdef __sun__
+#include <strings.h>
+#endif
+
+#if !defined(__sgi) && !defined(WIN32)
+#include <sys/time.h>
+#include <unistd.h>
+#endif
+
+#include <stdio.h>
+#include "BLI_arithb.h"
+
+/* A few small defines. Keep'em local! */
+#define SMALL_NUMBER 1.e-8
+#define ABS(x) ((x) < 0 ? -(x) : (x))
+#define SWAP(type, a, b) { type sw_ap; sw_ap=(a); (a)=(b); (b)=sw_ap; }
+
+
+#if defined(WIN32) || defined(__APPLE__)
+#include <stdlib.h>
+#define M_PI 3.14159265358979323846
+#define M_SQRT2 1.41421356237309504880
+
+#endif /* defined(WIN32) || defined(__APPLE__) */
+
+
+float saacos(float fac)
+{
+ if(fac<= -1.0f) return (float)M_PI;
+ else if(fac>=1.0f) return 0.0;
+ else return (float)acos(fac);
+}
+
+float sasqrt(float fac)
+{
+ if(fac<=0.0) return 0.0;
+ return (float)sqrt(fac);
+}
+
+float Normalise(float *n)
+{
+ float d;
+
+ d= n[0]*n[0]+n[1]*n[1]+n[2]*n[2];
+ /* FLT_EPSILON is too large! A larger value causes normalise errors in a scaled down utah teapot */
+ if(d>0.0000000000001) {
+ d= (float)sqrt(d);
+
+ n[0]/=d;
+ n[1]/=d;
+ n[2]/=d;
+ } else {
+ n[0]=n[1]=n[2]= 0.0;
+ d= 0.0;
+ }
+ return d;
+}
+
+void Crossf(float *c, const float *a, const float *b)
+{
+ c[0] = a[1] * b[2] - a[2] * b[1];
+ c[1] = a[2] * b[0] - a[0] * b[2];
+ c[2] = a[0] * b[1] - a[1] * b[0];
+}
+
+float Inpf(const float *v1, const float *v2)
+{
+ return v1[0]*v2[0]+v1[1]*v2[1]+v1[2]*v2[2];
+}
+
+void Mat3Transp(float mat[][3])
+{
+ float t;
+
+ t = mat[0][1] ;
+ mat[0][1] = mat[1][0] ;
+ mat[1][0] = t;
+ t = mat[0][2] ;
+ mat[0][2] = mat[2][0] ;
+ mat[2][0] = t;
+ t = mat[1][2] ;
+ mat[1][2] = mat[2][1] ;
+ mat[2][1] = t;
+}
+
+void Mat4Transp(float mat[][4])
+{
+ float t;
+
+ t = mat[0][1] ;
+ mat[0][1] = mat[1][0] ;
+ mat[1][0] = t;
+ t = mat[0][2] ;
+ mat[0][2] = mat[2][0] ;
+ mat[2][0] = t;
+ t = mat[0][3] ;
+ mat[0][3] = mat[3][0] ;
+ mat[3][0] = t;
+
+ t = mat[1][2] ;
+ mat[1][2] = mat[2][1] ;
+ mat[2][1] = t;
+ t = mat[1][3] ;
+ mat[1][3] = mat[3][1] ;
+ mat[3][1] = t;
+
+ t = mat[2][3] ;
+ mat[2][3] = mat[3][2] ;
+ mat[3][2] = t;
+}
+
+
+/*
+ * invertmat -
+ * computes the inverse of mat and puts it in inverse. Returns
+ * TRUE on success (i.e. can always find a pivot) and FALSE on failure.
+ * Uses Gaussian Elimination with partial (maximal column) pivoting.
+ *
+ * Mark Segal - 1992
+ */
+
+int Mat4Invert(float inverse[][4], const float mat[][4])
+{
+ int i, j, k;
+ double temp;
+ float tempmat[4][4];
+ float max;
+ int maxj;
+
+ /* Set inverse to identity */
+ for (i=0; i<4; i++)
+ for (j=0; j<4; j++)
+ inverse[i][j] = 0;
+ for (i=0; i<4; i++)
+ inverse[i][i] = 1;
+
+ /* Copy original matrix so we don't mess it up */
+ for(i = 0; i < 4; i++)
+ for(j = 0; j <4; j++)
+ tempmat[i][j] = mat[i][j];
+
+ for(i = 0; i < 4; i++) {
+ /* Look for row with max pivot */
+ max = ABS(tempmat[i][i]);
+ maxj = i;
+ for(j = i + 1; j < 4; j++) {
+ if(ABS(tempmat[j][i]) > max) {
+ max = ABS(tempmat[j][i]);
+ maxj = j;
+ }
+ }
+ /* Swap rows if necessary */
+ if (maxj != i) {
+ for( k = 0; k < 4; k++) {
+ SWAP(float, tempmat[i][k], tempmat[maxj][k]);
+ SWAP(float, inverse[i][k], inverse[maxj][k]);
+ }
+ }
+
+ temp = tempmat[i][i];
+ if (temp == 0)
+ return 0; /* No non-zero pivot */
+ for(k = 0; k < 4; k++) {
+ tempmat[i][k] = (float)(tempmat[i][k]/temp);
+ inverse[i][k] = (float)(inverse[i][k]/temp);
+ }
+ for(j = 0; j < 4; j++) {
+ if(j != i) {
+ temp = tempmat[j][i];
+ for(k = 0; k < 4; k++) {
+ tempmat[j][k] -= (float)(tempmat[i][k]*temp);
+ inverse[j][k] -= (float)(inverse[i][k]*temp);
+ }
+ }
+ }
+ }
+ return 1;
+}
+#ifdef TEST_ACTIVE
+void Mat4InvertSimp(float inverse[][4], const float mat[][4])
+{
+ /* alleen HOEK bewarende Matrices */
+ /* gebaseerd op GG IV pag 205 */
+ float scale;
+
+ scale= mat[0][0]*mat[0][0] + mat[1][0]*mat[1][0] + mat[2][0]*mat[2][0];
+ if(scale==0.0) return;
+
+ scale= 1.0/scale;
+
+ /* transpose en scale */
+ inverse[0][0]= scale*mat[0][0];
+ inverse[1][0]= scale*mat[0][1];
+ inverse[2][0]= scale*mat[0][2];
+ inverse[0][1]= scale*mat[1][0];
+ inverse[1][1]= scale*mat[1][1];
+ inverse[2][1]= scale*mat[1][2];
+ inverse[0][2]= scale*mat[2][0];
+ inverse[1][2]= scale*mat[2][1];
+ inverse[2][2]= scale*mat[2][2];
+
+ inverse[3][0]= -(inverse[0][0]*mat[3][0] + inverse[1][0]*mat[3][1] + inverse[2][0]*mat[3][2]);
+ inverse[3][1]= -(inverse[0][1]*mat[3][0] + inverse[1][1]*mat[3][1] + inverse[2][1]*mat[3][2]);
+ inverse[3][2]= -(inverse[0][2]*mat[3][0] + inverse[1][2]*mat[3][1] + inverse[2][2]*mat[3][2]);
+
+ inverse[0][3]= inverse[1][3]= inverse[2][3]= 0.0;
+ inverse[3][3]= 1.0;
+}
+#endif
+/* struct Matrix4; */
+
+#ifdef TEST_ACTIVE
+/* this seems to be unused.. */
+
+void Mat4Inv(float *m1, const float *m2)
+{
+
+/* This gets me into trouble: */
+ float mat1[3][3], mat2[3][3];
+
+/* void Mat3Inv(); */
+/* void Mat3CpyMat4(); */
+/* void Mat4CpyMat3(); */
+
+ Mat3CpyMat4((float*)mat2,m2);
+ Mat3Inv((float*)mat1, (float*) mat2);
+ Mat4CpyMat3(m1, mat1);
+
+}
+#endif
+
+
+float Det2x2(float a,float b,float c,float d)
+{
+
+ return a*d - b*c;
+}
+
+
+
+float Det3x3(float a1, float a2, float a3,
+ float b1, float b2, float b3,
+ float c1, float c2, float c3 )
+{
+ float ans;
+
+ ans = a1 * Det2x2( b2, b3, c2, c3 )
+ - b1 * Det2x2( a2, a3, c2, c3 )
+ + c1 * Det2x2( a2, a3, b2, b3 );
+
+ return ans;
+}
+
+float Det4x4(const float m[][4])
+{
+ float ans;
+ float a1,a2,a3,a4,b1,b2,b3,b4,c1,c2,c3,c4,d1,d2,d3,d4;
+
+ a1= m[0][0];
+ b1= m[0][1];
+ c1= m[0][2];
+ d1= m[0][3];
+
+ a2= m[1][0];
+ b2= m[1][1];
+ c2= m[1][2];
+ d2= m[1][3];
+
+ a3= m[2][0];
+ b3= m[2][1];
+ c3= m[2][2];
+ d3= m[2][3];
+
+ a4= m[3][0];
+ b4= m[3][1];
+ c4= m[3][2];
+ d4= m[3][3];
+
+ ans = a1 * Det3x3( b2, b3, b4, c2, c3, c4, d2, d3, d4)
+ - b1 * Det3x3( a2, a3, a4, c2, c3, c4, d2, d3, d4)
+ + c1 * Det3x3( a2, a3, a4, b2, b3, b4, d2, d3, d4)
+ - d1 * Det3x3( a2, a3, a4, b2, b3, b4, c2, c3, c4);
+
+ return ans;
+}
+
+
+void Mat4Adj(float out[][4], const float in[][4]) /* out = ADJ(in) */
+{
+ float a1, a2, a3, a4, b1, b2, b3, b4;
+ float c1, c2, c3, c4, d1, d2, d3, d4;
+
+ a1= in[0][0];
+ b1= in[0][1];
+ c1= in[0][2];
+ d1= in[0][3];
+
+ a2= in[1][0];
+ b2= in[1][1];
+ c2= in[1][2];
+ d2= in[1][3];
+
+ a3= in[2][0];
+ b3= in[2][1];
+ c3= in[2][2];
+ d3= in[2][3];
+
+ a4= in[3][0];
+ b4= in[3][1];
+ c4= in[3][2];
+ d4= in[3][3];
+
+
+ out[0][0] = Det3x3( b2, b3, b4, c2, c3, c4, d2, d3, d4);
+ out[1][0] = - Det3x3( a2, a3, a4, c2, c3, c4, d2, d3, d4);
+ out[2][0] = Det3x3( a2, a3, a4, b2, b3, b4, d2, d3, d4);
+ out[3][0] = - Det3x3( a2, a3, a4, b2, b3, b4, c2, c3, c4);
+
+ out[0][1] = - Det3x3( b1, b3, b4, c1, c3, c4, d1, d3, d4);
+ out[1][1] = Det3x3( a1, a3, a4, c1, c3, c4, d1, d3, d4);
+ out[2][1] = - Det3x3( a1, a3, a4, b1, b3, b4, d1, d3, d4);
+ out[3][1] = Det3x3( a1, a3, a4, b1, b3, b4, c1, c3, c4);
+
+ out[0][2] = Det3x3( b1, b2, b4, c1, c2, c4, d1, d2, d4);
+ out[1][2] = - Det3x3( a1, a2, a4, c1, c2, c4, d1, d2, d4);
+ out[2][2] = Det3x3( a1, a2, a4, b1, b2, b4, d1, d2, d4);
+ out[3][2] = - Det3x3( a1, a2, a4, b1, b2, b4, c1, c2, c4);
+
+ out[0][3] = - Det3x3( b1, b2, b3, c1, c2, c3, d1, d2, d3);
+ out[1][3] = Det3x3( a1, a2, a3, c1, c2, c3, d1, d2, d3);
+ out[2][3] = - Det3x3( a1, a2, a3, b1, b2, b3, d1, d2, d3);
+ out[3][3] = Det3x3( a1, a2, a3, b1, b2, b3, c1, c2, c3);
+}
+
+void Mat4InvGG(float out[][4], const float in[][4]) /* van Graphic Gems I, out= INV(in) */
+{
+ int i, j;
+ float det;
+
+ /* calculate the adjoint matrix */
+
+ Mat4Adj(out,in);
+
+ det = Det4x4(out);
+
+ if ( fabs( det ) < SMALL_NUMBER) {
+ return;
+ }
+
+ /* scale the adjoint matrix to get the inverse */
+
+ for (i=0; i<4; i++)
+ for(j=0; j<4; j++)
+ out[i][j] = out[i][j] / det;
+
+ /* de laatste factor is niet altijd 1. Hierdoor moet eigenlijk nog gedeeld worden */
+}
+
+
+void Mat3Inv(float m1[][3], const float m2[][3])
+{
+ short a,b;
+ float det;
+
+ /* eerst adjoint */
+ Mat3Adj(m1,m2);
+
+ /* dan det oude mat! */
+ det= m2[0][0]* (m2[1][1]*m2[2][2] - m2[1][2]*m2[2][1])
+ -m2[1][0]* (m2[0][1]*m2[2][2] - m2[0][2]*m2[2][1])
+ +m2[2][0]* (m2[0][1]*m2[1][2] - m2[0][2]*m2[1][1]);
+
+ if(det==0) det=1;
+ det= 1/det;
+ for(a=0;a<3;a++) {
+ for(b=0;b<3;b++) {
+ m1[a][b]*=det;
+ }
+ }
+}
+
+void Mat3Adj(float m1[][3], const float m[][3])
+{
+ m1[0][0]=m[1][1]*m[2][2]-m[1][2]*m[2][1];
+ m1[0][1]= -m[0][1]*m[2][2]+m[0][2]*m[2][1];
+ m1[0][2]=m[0][1]*m[1][2]-m[0][2]*m[1][1];
+
+ m1[1][0]= -m[1][0]*m[2][2]+m[1][2]*m[2][0];
+ m1[1][1]=m[0][0]*m[2][2]-m[0][2]*m[2][0];
+ m1[1][2]= -m[0][0]*m[1][2]+m[0][2]*m[1][0];
+
+ m1[2][0]=m[1][0]*m[2][1]-m[1][1]*m[2][0];
+ m1[2][1]= -m[0][0]*m[2][1]+m[0][1]*m[2][0];
+ m1[2][2]=m[0][0]*m[1][1]-m[0][1]*m[1][0];
+}
+
+void Mat4MulMat4(float m1[][4], const float m2[][4], const float m3[][4])
+{
+ /* matrix product: m1[j][k] = m2[j][i].m3[i][k] */
+
+ m1[0][0] = m2[0][0]*m3[0][0] + m2[0][1]*m3[1][0] + m2[0][2]*m3[2][0] + m2[0][3]*m3[3][0];
+ m1[0][1] = m2[0][0]*m3[0][1] + m2[0][1]*m3[1][1] + m2[0][2]*m3[2][1] + m2[0][3]*m3[3][1];
+ m1[0][2] = m2[0][0]*m3[0][2] + m2[0][1]*m3[1][2] + m2[0][2]*m3[2][2] + m2[0][3]*m3[3][2];
+ m1[0][3] = m2[0][0]*m3[0][3] + m2[0][1]*m3[1][3] + m2[0][2]*m3[2][3] + m2[0][3]*m3[3][3];
+
+ m1[1][0] = m2[1][0]*m3[0][0] + m2[1][1]*m3[1][0] + m2[1][2]*m3[2][0] + m2[1][3]*m3[3][0];
+ m1[1][1] = m2[1][0]*m3[0][1] + m2[1][1]*m3[1][1] + m2[1][2]*m3[2][1] + m2[1][3]*m3[3][1];
+ m1[1][2] = m2[1][0]*m3[0][2] + m2[1][1]*m3[1][2] + m2[1][2]*m3[2][2] + m2[1][3]*m3[3][2];
+ m1[1][3] = m2[1][0]*m3[0][3] + m2[1][1]*m3[1][3] + m2[1][2]*m3[2][3] + m2[1][3]*m3[3][3];
+
+ m1[2][0] = m2[2][0]*m3[0][0] + m2[2][1]*m3[1][0] + m2[2][2]*m3[2][0] + m2[2][3]*m3[3][0];
+ m1[2][1] = m2[2][0]*m3[0][1] + m2[2][1]*m3[1][1] + m2[2][2]*m3[2][1] + m2[2][3]*m3[3][1];
+ m1[2][2] = m2[2][0]*m3[0][2] + m2[2][1]*m3[1][2] + m2[2][2]*m3[2][2] + m2[2][3]*m3[3][2];
+ m1[2][3] = m2[2][0]*m3[0][3] + m2[2][1]*m3[1][3] + m2[2][2]*m3[2][3] + m2[2][3]*m3[3][3];
+
+ m1[3][0] = m2[3][0]*m3[0][0] + m2[3][1]*m3[1][0] + m2[3][2]*m3[2][0] + m2[3][3]*m3[3][0];
+ m1[3][1] = m2[3][0]*m3[0][1] + m2[3][1]*m3[1][1] + m2[3][2]*m3[2][1] + m2[3][3]*m3[3][1];
+ m1[3][2] = m2[3][0]*m3[0][2] + m2[3][1]*m3[1][2] + m2[3][2]*m3[2][2] + m2[3][3]*m3[3][2];
+ m1[3][3] = m2[3][0]*m3[0][3] + m2[3][1]*m3[1][3] + m2[3][2]*m3[2][3] + m2[3][3]*m3[3][3];
+
+}
+#ifdef TEST_ACTIVE
+void subMat4MulMat4(float *m1, const float *m2, const float *m3)
+{
+
+ m1[0]= m2[0]*m3[0] + m2[1]*m3[4] + m2[2]*m3[8];
+ m1[1]= m2[0]*m3[1] + m2[1]*m3[5] + m2[2]*m3[9];
+ m1[2]= m2[0]*m3[2] + m2[1]*m3[6] + m2[2]*m3[10];
+ m1[3]= m2[0]*m3[3] + m2[1]*m3[7] + m2[2]*m3[11] + m2[3];
+ m1+=4;
+ m2+=4;
+ m1[0]= m2[0]*m3[0] + m2[1]*m3[4] + m2[2]*m3[8];
+ m1[1]= m2[0]*m3[1] + m2[1]*m3[5] + m2[2]*m3[9];
+ m1[2]= m2[0]*m3[2] + m2[1]*m3[6] + m2[2]*m3[10];
+ m1[3]= m2[0]*m3[3] + m2[1]*m3[7] + m2[2]*m3[11] + m2[3];
+ m1+=4;
+ m2+=4;
+ m1[0]= m2[0]*m3[0] + m2[1]*m3[4] + m2[2]*m3[8];
+ m1[1]= m2[0]*m3[1] + m2[1]*m3[5] + m2[2]*m3[9];
+ m1[2]= m2[0]*m3[2] + m2[1]*m3[6] + m2[2]*m3[10];
+ m1[3]= m2[0]*m3[3] + m2[1]*m3[7] + m2[2]*m3[11] + m2[3];
+}
+#endif
+
+#ifndef TEST_ACTIVE
+void Mat3MulMat3(float m1[][3], const float m3[][3], const float m2[][3])
+#else
+void Mat3MulMat3(float *m1, const float *m3, const float *m2)
+#endif
+{
+ /* m1[i][j] = m2[i][k]*m3[k][j], args are flipped! */
+#ifndef TEST_ACTIVE
+ m1[0][0]= m2[0][0]*m3[0][0] + m2[0][1]*m3[1][0] + m2[0][2]*m3[2][0];
+ m1[0][1]= m2[0][0]*m3[0][1] + m2[0][1]*m3[1][1] + m2[0][2]*m3[2][1];
+ m1[0][2]= m2[0][0]*m3[0][2] + m2[0][1]*m3[1][2] + m2[0][2]*m3[2][2];
+
+ m1[1][0]= m2[1][0]*m3[0][0] + m2[1][1]*m3[1][0] + m2[1][2]*m3[2][0];
+ m1[1][1]= m2[1][0]*m3[0][1] + m2[1][1]*m3[1][1] + m2[1][2]*m3[2][1];
+ m1[1][2]= m2[1][0]*m3[0][2] + m2[1][1]*m3[1][2] + m2[1][2]*m3[2][2];
+
+ m1[2][0]= m2[2][0]*m3[0][0] + m2[2][1]*m3[1][0] + m2[2][2]*m3[2][0];
+ m1[2][1]= m2[2][0]*m3[0][1] + m2[2][1]*m3[1][1] + m2[2][2]*m3[2][1];
+ m1[2][2]= m2[2][0]*m3[0][2] + m2[2][1]*m3[1][2] + m2[2][2]*m3[2][2];
+#else
+ m1[0]= m2[0]*m3[0] + m2[1]*m3[3] + m2[2]*m3[6];
+ m1[1]= m2[0]*m3[1] + m2[1]*m3[4] + m2[2]*m3[7];
+ m1[2]= m2[0]*m3[2] + m2[1]*m3[5] + m2[2]*m3[8];
+ m1+=3;
+ m2+=3;
+ m1[0]= m2[0]*m3[0] + m2[1]*m3[3] + m2[2]*m3[6];
+ m1[1]= m2[0]*m3[1] + m2[1]*m3[4] + m2[2]*m3[7];
+ m1[2]= m2[0]*m3[2] + m2[1]*m3[5] + m2[2]*m3[8];
+ m1+=3;
+ m2+=3;
+ m1[0]= m2[0]*m3[0] + m2[1]*m3[3] + m2[2]*m3[6];
+ m1[1]= m2[0]*m3[1] + m2[1]*m3[4] + m2[2]*m3[7];
+ m1[2]= m2[0]*m3[2] + m2[1]*m3[5] + m2[2]*m3[8];
+#endif
+} /* end of void Mat3MulMat3(float m1[][3], float m3[][3], float m2[][3]) */
+
+void Mat4MulMat43(float (*m1)[4], const float (*m3)[4], const float (*m2)[3])
+{
+ m1[0][0]= m2[0][0]*m3[0][0] + m2[0][1]*m3[1][0] + m2[0][2]*m3[2][0];
+ m1[0][1]= m2[0][0]*m3[0][1] + m2[0][1]*m3[1][1] + m2[0][2]*m3[2][1];
+ m1[0][2]= m2[0][0]*m3[0][2] + m2[0][1]*m3[1][2] + m2[0][2]*m3[2][2];
+ m1[1][0]= m2[1][0]*m3[0][0] + m2[1][1]*m3[1][0] + m2[1][2]*m3[2][0];
+ m1[1][1]= m2[1][0]*m3[0][1] + m2[1][1]*m3[1][1] + m2[1][2]*m3[2][1];
+ m1[1][2]= m2[1][0]*m3[0][2] + m2[1][1]*m3[1][2] + m2[1][2]*m3[2][2];
+ m1[2][0]= m2[2][0]*m3[0][0] + m2[2][1]*m3[1][0] + m2[2][2]*m3[2][0];
+ m1[2][1]= m2[2][0]*m3[0][1] + m2[2][1]*m3[1][1] + m2[2][2]*m3[2][1];
+ m1[2][2]= m2[2][0]*m3[0][2] + m2[2][1]*m3[1][2] + m2[2][2]*m3[2][2];
+}
+/* m1 = m2 * m3, ignore the elements on the 4th row/column of m3*/
+void Mat3IsMat3MulMat4(float m1[][3], const float m2[][3], const float m3[][4])
+{
+ /* m1[i][j] = m2[i][k] * m3[k][j] */
+ m1[0][0] = m2[0][0] * m3[0][0] + m2[0][1] * m3[1][0] +m2[0][2] * m3[2][0];
+ m1[0][1] = m2[0][0] * m3[0][1] + m2[0][1] * m3[1][1] +m2[0][2] * m3[2][1];
+ m1[0][2] = m2[0][0] * m3[0][2] + m2[0][1] * m3[1][2] +m2[0][2] * m3[2][2];
+
+ m1[1][0] = m2[1][0] * m3[0][0] + m2[1][1] * m3[1][0] +m2[1][2] * m3[2][0];
+ m1[1][1] = m2[1][0] * m3[0][1] + m2[1][1] * m3[1][1] +m2[1][2] * m3[2][1];
+ m1[1][2] = m2[1][0] * m3[0][2] + m2[1][1] * m3[1][2] +m2[1][2] * m3[2][2];
+
+ m1[2][0] = m2[2][0] * m3[0][0] + m2[2][1] * m3[1][0] +m2[2][2] * m3[2][0];
+ m1[2][1] = m2[2][0] * m3[0][1] + m2[2][1] * m3[1][1] +m2[2][2] * m3[2][1];
+ m1[2][2] = m2[2][0] * m3[0][2] + m2[2][1] * m3[1][2] +m2[2][2] * m3[2][2];
+}
+
+
+
+void Mat4MulMat34(float (*m1)[4], const float (*m3)[3], const float (*m2)[4])
+{
+ m1[0][0]= m2[0][0]*m3[0][0] + m2[0][1]*m3[1][0] + m2[0][2]*m3[2][0];
+ m1[0][1]= m2[0][0]*m3[0][1] + m2[0][1]*m3[1][1] + m2[0][2]*m3[2][1];
+ m1[0][2]= m2[0][0]*m3[0][2] + m2[0][1]*m3[1][2] + m2[0][2]*m3[2][2];
+ m1[1][0]= m2[1][0]*m3[0][0] + m2[1][1]*m3[1][0] + m2[1][2]*m3[2][0];
+ m1[1][1]= m2[1][0]*m3[0][1] + m2[1][1]*m3[1][1] + m2[1][2]*m3[2][1];
+ m1[1][2]= m2[1][0]*m3[0][2] + m2[1][1]*m3[1][2] + m2[1][2]*m3[2][2];
+ m1[2][0]= m2[2][0]*m3[0][0] + m2[2][1]*m3[1][0] + m2[2][2]*m3[2][0];
+ m1[2][1]= m2[2][0]*m3[0][1] + m2[2][1]*m3[1][1] + m2[2][2]*m3[2][1];
+ m1[2][2]= m2[2][0]*m3[0][2] + m2[2][1]*m3[1][2] + m2[2][2]*m3[2][2];
+}
+
+void Mat4CpyMat4(float m1[][4], const float m2[][4])
+{
+ memcpy(m1, m2, 4*4*sizeof(float));
+}
+
+void Mat4SwapMat4(float *m1, float *m2)
+{
+ float t;
+ int i;
+
+ for(i=0;i<16;i++) {
+ t= *m1;
+ *m1= *m2;
+ *m2= t;
+ m1++;
+ m2++;
+ }
+}
+
+typedef float Mat3Row[3];
+typedef float Mat4Row[4];
+
+#ifdef TEST_ACTIVE
+void Mat3CpyMat4(float *m1p, const float *m2p)
+#else
+void Mat3CpyMat4(float m1[][3], const float m2[][4])
+#endif
+{
+#ifdef TEST_ACTIVE
+ int i, j;
+ Mat3Row *m1= (Mat3Row *)m1p;
+ Mat4Row *m2= (Mat4Row *)m2p;
+ for ( i = 0; i++; i < 3) {
+ for (j = 0; j++; j < 3) {
+ m1p[3*i + j] = m2p[4*i + j];
+ }
+ }
+#endif
+ m1[0][0]= m2[0][0];
+ m1[0][1]= m2[0][1];
+ m1[0][2]= m2[0][2];
+
+ m1[1][0]= m2[1][0];
+ m1[1][1]= m2[1][1];
+ m1[1][2]= m2[1][2];
+
+ m1[2][0]= m2[2][0];
+ m1[2][1]= m2[2][1];
+ m1[2][2]= m2[2][2];
+}
+
+/* Butched. See .h for comment */
+/* void Mat4CpyMat3(float m1[][4], float m2[][3]) */
+#ifdef TEST_ACTIVE
+void Mat4CpyMat3(float* m1, const float *m2)
+{
+ int i;
+ for (i = 0; i < 3; i++) {
+ m1[(4*i)] = m2[(3*i)];
+ m1[(4*i) + 1]= m2[(3*i) + 1];
+ m1[(4*i) + 2]= m2[(3*i) + 2];
+ m1[(4*i) + 3]= 0.0;
+ i++;
+ }
+
+ m1[12]=m1[13]= m1[14]= 0.0;
+ m1[15]= 1.0;
+}
+#else
+
+void Mat4CpyMat3(float m1[][4], const float m2[][3]) /* no clear */
+{
+ m1[0][0]= m2[0][0];
+ m1[0][1]= m2[0][1];
+ m1[0][2]= m2[0][2];
+
+ m1[1][0]= m2[1][0];
+ m1[1][1]= m2[1][1];
+ m1[1][2]= m2[1][2];
+
+ m1[2][0]= m2[2][0];
+ m1[2][1]= m2[2][1];
+ m1[2][2]= m2[2][2];
+
+ /* Reevan's Bugfix */
+ m1[0][3]=0.0F;
+ m1[1][3]=0.0F;
+ m1[2][3]=0.0F;
+
+ m1[3][0]=0.0F;
+ m1[3][1]=0.0F;
+ m1[3][2]=0.0F;
+ m1[3][3]=1.0F;
+
+
+}
+#endif
+
+void Mat3CpyMat3(float m1[][3], const float m2[][3])
+{
+ /* destination comes first: */
+ memcpy(&m1[0], &m2[0], 9*sizeof(float));
+}
+
+void Mat3MulSerie(float answ[][3],
+ const float m1[][3], const float m2[][3], const float m3[][3],
+ const float m4[][3], const float m5[][3], const float m6[][3],
+ const float m7[][3], const float m8[][3])
+{
+ float temp[3][3];
+
+ if(m1==0 || m2==0) return;
+
+
+ Mat3MulMat3(answ, m2, m1);
+ if(m3) {
+ Mat3MulMat3(temp, m3, answ);
+ if(m4) {
+ Mat3MulMat3(answ, m4, temp);
+ if(m5) {
+ Mat3MulMat3(temp, m5, answ);
+ if(m6) {
+ Mat3MulMat3(answ, m6, temp);
+ if(m7) {
+ Mat3MulMat3(temp, m7, answ);
+ if(m8) {
+ Mat3MulMat3(answ, m8, temp);
+ }
+ else Mat3CpyMat3(answ, temp);
+ }
+ }
+ else Mat3CpyMat3(answ, temp);
+ }
+ }
+ else Mat3CpyMat3(answ, temp);
+ }
+}
+
+void Mat4MulSerie(float answ[][4], const float m1[][4],
+ const float m2[][4], const float m3[][4], const float m4[][4],
+ const float m5[][4], const float m6[][4], const float m7[][4],
+ const float m8[][4])
+{
+ float temp[4][4];
+
+ if(m1==0 || m2==0) return;
+
+ Mat4MulMat4(answ, m2, m1);
+ if(m3) {
+ Mat4MulMat4(temp, m3, answ);
+ if(m4) {
+ Mat4MulMat4(answ, m4, temp);
+ if(m5) {
+ Mat4MulMat4(temp, m5, answ);
+ if(m6) {
+ Mat4MulMat4(answ, m6, temp);
+ if(m7) {
+ Mat4MulMat4(temp, m7, answ);
+ if(m8) {
+ Mat4MulMat4(answ, m8, temp);
+ }
+ else Mat4CpyMat4(answ, temp);
+ }
+ }
+ else Mat4CpyMat4(answ, temp);
+ }
+ }
+ else Mat4CpyMat4(answ, temp);
+ }
+}
+
+
+
+void Mat4Clr(float *m)
+{
+ memset(m, 0, 4*4*sizeof(float));
+}
+
+void Mat3Clr(float *m)
+{
+ memset(m, 0, 3*3*sizeof(float));
+}
+
+void Mat4One(float m[][4])
+{
+
+ m[0][0]= m[1][1]= m[2][2]= m[3][3]= 1.0;
+ m[0][1]= m[0][2]= m[0][3]= 0.0;
+ m[1][0]= m[1][2]= m[1][3]= 0.0;
+ m[2][0]= m[2][1]= m[2][3]= 0.0;
+ m[3][0]= m[3][1]= m[3][2]= 0.0;
+}
+
+void Mat3One(float m[][3])
+{
+
+ m[0][0]= m[1][1]= m[2][2]= 1.0;
+ m[0][1]= m[0][2]= 0.0;
+ m[1][0]= m[1][2]= 0.0;
+ m[2][0]= m[2][1]= 0.0;
+}
+
+void Mat4MulVec(const float mat[][4], int *vec)
+{
+ int x,y;
+
+ x=vec[0];
+ y=vec[1];
+ vec[0]=(int)(x*mat[0][0] + y*mat[1][0] + mat[2][0]*vec[2] + mat[3][0]);
+ vec[1]=(int)(x*mat[0][1] + y*mat[1][1] + mat[2][1]*vec[2] + mat[3][1]);
+ vec[2]=(int)(x*mat[0][2] + y*mat[1][2] + mat[2][2]*vec[2] + mat[3][2]);
+}
+
+void Mat4MulVecfl(const float mat[][4], float *vec)
+{
+ float x,y;
+
+ x=vec[0];
+ y=vec[1];
+ vec[0]=x*mat[0][0] + y*mat[1][0] + mat[2][0]*vec[2] + mat[3][0];
+ vec[1]=x*mat[0][1] + y*mat[1][1] + mat[2][1]*vec[2] + mat[3][1];
+ vec[2]=x*mat[0][2] + y*mat[1][2] + mat[2][2]*vec[2] + mat[3][2];
+}
+
+void VecMat4MulVecfl(float *in, const float mat[][4], const float *vec)
+{
+ float x,y;
+
+ x=vec[0];
+ y=vec[1];
+ in[0]= x*mat[0][0] + y*mat[1][0] + mat[2][0]*vec[2] + mat[3][0];
+ in[1]= x*mat[0][1] + y*mat[1][1] + mat[2][1]*vec[2] + mat[3][1];
+ in[2]= x*mat[0][2] + y*mat[1][2] + mat[2][2]*vec[2] + mat[3][2];
+}
+
+void Mat4Mul3Vecfl(const float mat[][4], float *vec)
+{
+ float x,y;
+
+ x= vec[0];
+ y= vec[1];
+ vec[0]= x*mat[0][0] + y*mat[1][0] + mat[2][0]*vec[2];
+ vec[1]= x*mat[0][1] + y*mat[1][1] + mat[2][1]*vec[2];
+ vec[2]= x*mat[0][2] + y*mat[1][2] + mat[2][2]*vec[2];
+}
+
+void Mat4MulVec4fl(const float mat[][4], float *vec)
+{
+ float x,y,z;
+
+ x=vec[0];
+ y=vec[1];
+ z= vec[2];
+ vec[0]=x*mat[0][0] + y*mat[1][0] + z*mat[2][0] + mat[3][0]*vec[3];
+ vec[1]=x*mat[0][1] + y*mat[1][1] + z*mat[2][1] + mat[3][1]*vec[3];
+ vec[2]=x*mat[0][2] + y*mat[1][2] + z*mat[2][2] + mat[3][2]*vec[3];
+ vec[3]=x*mat[0][3] + y*mat[1][3] + z*mat[2][3] + mat[3][3]*vec[3];
+}
+
+void Mat3MulVec(const float mat[][3], int *vec)
+{
+ int x,y;
+
+ x=vec[0];
+ y=vec[1];
+ vec[0]= (int)(x*mat[0][0] + y*mat[1][0] + mat[2][0]*vec[2]);
+ vec[1]= (int)(x*mat[0][1] + y*mat[1][1] + mat[2][1]*vec[2]);
+ vec[2]= (int)(x*mat[0][2] + y*mat[1][2] + mat[2][2]*vec[2]);
+}
+
+void Mat3MulVecfl(const float mat[][3], float *vec)
+{
+ float x,y;
+
+ x=vec[0];
+ y=vec[1];
+ vec[0]= x*mat[0][0] + y*mat[1][0] + mat[2][0]*vec[2];
+ vec[1]= x*mat[0][1] + y*mat[1][1] + mat[2][1]*vec[2];
+ vec[2]= x*mat[0][2] + y*mat[1][2] + mat[2][2]*vec[2];
+}
+
+void Mat3MulVecd(const float mat[][3], double *vec)
+{
+ double x,y;
+
+ x=vec[0];
+ y=vec[1];
+ vec[0]= x*mat[0][0] + y*mat[1][0] + mat[2][0]*vec[2];
+ vec[1]= x*mat[0][1] + y*mat[1][1] + mat[2][1]*vec[2];
+ vec[2]= x*mat[0][2] + y*mat[1][2] + mat[2][2]*vec[2];
+}
+
+void Mat3TransMulVecfl(const float mat[][3], float *vec)
+{
+ float x,y;
+
+ x=vec[0];
+ y=vec[1];
+ vec[0]= x*mat[0][0] + y*mat[0][1] + mat[0][2]*vec[2];
+ vec[1]= x*mat[1][0] + y*mat[1][1] + mat[1][2]*vec[2];
+ vec[2]= x*mat[2][0] + y*mat[2][1] + mat[2][2]*vec[2];
+}
+
+void Mat3MulFloat(float *m, float f)
+{
+ int i;
+
+ for(i=0;i<9;i++) m[i]*=f;
+}
+
+void Mat4MulFloat(float *m, float f)
+{
+ int i;
+
+ for(i=0;i<12;i++) m[i]*=f; /* tot 12 tellen: zonder vector */
+}
+
+
+void Mat4MulFloat3(float *m, float f) /* alleen de scale component */
+{
+ int i,j;
+
+ for(i=0; i<3; i++) {
+ for(j=0; j<3; j++) {
+
+ m[4*i+j] *= f;
+ }
+ }
+}
+
+void VecStar(float mat[][3], const float *vec)
+{
+
+ mat[0][0]= mat[1][1]= mat[2][2]= 0.0;
+ mat[0][1]= -vec[2];
+ mat[0][2]= vec[1];
+ mat[1][0]= vec[2];
+ mat[1][2]= -vec[0];
+ mat[2][0]= -vec[1];
+ mat[2][1]= vec[0];
+
+}
+#ifdef TEST_ACTIVE
+short EenheidsMat(float mat[][3])
+{
+
+ if(mat[0][0]==1.0 && mat[0][1]==0.0 && mat[0][2]==0.0)
+ if(mat[1][0]==0.0 && mat[1][1]==1.0 && mat[1][2]==0.0)
+ if(mat[2][0]==0.0 && mat[2][1]==0.0 && mat[2][2]==1.0)
+ return 1;
+ return 0;
+}
+#endif
+
+int FloatCompare(const float *v1, const float *v2, float limit)
+{
+
+ if( fabs(v1[0]-v2[0])<limit ) {
+ if( fabs(v1[1]-v2[1])<limit ) {
+ if( fabs(v1[2]-v2[2])<limit ) return 1;
+ }
+ }
+ return 0;
+}
+
+void printmatrix4(const char *str, const float m[][4])
+{
+ printf("%s\n", str);
+ printf("%f %f %f %f\n",m[0][0],m[0][1],m[0][2],m[0][3]);
+ printf("%f %f %f %f\n",m[1][0],m[1][1],m[1][2],m[1][3]);
+ printf("%f %f %f %f\n",m[2][0],m[2][1],m[2][2],m[2][3]);
+ printf("%f %f %f %f\n",m[3][0],m[3][1],m[3][2],m[3][3]);
+ printf("\n");
+
+}
+
+void printmatrix3(const char *str, const float m[][3])
+{
+ printf("%s\n", str);
+ printf("%f %f %f\n",m[0][0],m[0][1],m[0][2]);
+ printf("%f %f %f\n",m[1][0],m[1][1],m[1][2]);
+ printf("%f %f %f\n",m[2][0],m[2][1],m[2][2]);
+ printf("\n");
+
+}
+
+/* **************** QUATERNIONS ********** */
+
+
+void QuatMul(float *q, const float *q1, const float *q2)
+{
+ float t0,t1,t2;
+
+ t0= q1[0]*q2[0]-q1[1]*q2[1]-q1[2]*q2[2]-q1[3]*q2[3];
+ t1= q1[0]*q2[1]+q1[1]*q2[0]+q1[2]*q2[3]-q1[3]*q2[2];
+ t2= q1[0]*q2[2]+q1[2]*q2[0]+q1[3]*q2[1]-q1[1]*q2[3];
+ q[3]= q1[0]*q2[3]+q1[3]*q2[0]+q1[1]*q2[2]-q1[2]*q2[1];
+ q[0]=t0;
+ q[1]=t1;
+ q[2]=t2;
+}
+
+void QuatSub(float *q, const float *q1, float *q2)
+{
+ q2[0]= -q2[0];
+ QuatMul(q, q1, q2);
+ q2[0]= -q2[0];
+}
+
+
+void QuatToMat3(const float *q, float m[][3])
+{
+ double q0, q1, q2, q3, qda,qdb,qdc,qaa,qab,qac,qbb,qbc,qcc;
+
+ q0= M_SQRT2 * q[0];
+ q1= M_SQRT2 * q[1];
+ q2= M_SQRT2 * q[2];
+ q3= M_SQRT2 * q[3];
+
+ qda= q0*q1;
+ qdb= q0*q2;
+ qdc= q0*q3;
+ qaa= q1*q1;
+ qab= q1*q2;
+ qac= q1*q3;
+ qbb= q2*q2;
+ qbc= q2*q3;
+ qcc= q3*q3;
+
+ m[0][0]= (float)(1.0-qbb-qcc);
+ m[0][1]= (float)(qdc+qab);
+ m[0][2]= (float)(-qdb+qac);
+
+ m[1][0]= (float)(-qdc+qab);
+ m[1][1]= (float)(1.0-qaa-qcc);
+ m[1][2]= (float)(qda+qbc);
+
+ m[2][0]= (float)(qdb+qac);
+ m[2][1]= (float)(-qda+qbc);
+ m[2][2]= (float)(1.0-qaa-qbb);
+}
+
+
+void QuatToMat4(const float *q, float m[][4])
+{
+ double q0, q1, q2, q3, qda,qdb,qdc,qaa,qab,qac,qbb,qbc,qcc;
+
+ q0= M_SQRT2 * q[0];
+ q1= M_SQRT2 * q[1];
+ q2= M_SQRT2 * q[2];
+ q3= M_SQRT2 * q[3];
+
+ qda= q0*q1;
+ qdb= q0*q2;
+ qdc= q0*q3;
+ qaa= q1*q1;
+ qab= q1*q2;
+ qac= q1*q3;
+ qbb= q2*q2;
+ qbc= q2*q3;
+ qcc= q3*q3;
+
+ m[0][0]= (float)(1.0-qbb-qcc);
+ m[0][1]= (float)(qdc+qab);
+ m[0][2]= (float)(-qdb+qac);
+ m[0][3]= 0.0f;
+
+ m[1][0]= (float)(-qdc+qab);
+ m[1][1]= (float)(1.0-qaa-qcc);
+ m[1][2]= (float)(qda+qbc);
+ m[1][3]= 0.0f;
+
+ m[2][0]= (float)(qdb+qac);
+ m[2][1]= (float)(-qda+qbc);
+ m[2][2]= (float)(1.0-qaa-qbb);
+ m[2][3]= 0.0f;
+
+ m[3][0]= m[3][1]= m[3][2]= 0.0f;
+ m[3][3]= 1.0f;
+}
+
+void Mat3ToQuat(const float wmat[][3], float *q) /* uit Sig.Proc.85 pag 253 */
+{
+ double tr, s;
+ float mat[3][3];
+
+ /* voor de netheid: op kopie werken */
+ Mat3CpyMat3(mat, wmat);
+ Mat3Ortho(mat); /* dit moet EN op eind NormalQuat */
+
+ tr= 0.25*(1.0+mat[0][0]+mat[1][1]+mat[2][2]);
+
+ if(tr>FLT_EPSILON) {
+ s= sqrt( tr);
+ q[0]= (float)s;
+ s*= 4.0;
+ q[1]= (float)((mat[1][2]-mat[2][1])/s);
+ q[2]= (float)((mat[2][0]-mat[0][2])/s);
+ q[3]= (float)((mat[0][1]-mat[1][0])/s);
+ }
+ else {
+ q[0]= 0.0f;
+ s= -0.5*(mat[1][1]+mat[2][2]);
+
+ if(s>FLT_EPSILON) {
+ s= sqrt(s);
+ q[1]= (float)s;
+ q[2]= (float)(mat[0][1]/(2*s));
+ q[3]= (float)(mat[0][2]/(2*s));
+ }
+ else {
+ q[1]= 0.0f;
+ s= 0.5*(1.0-mat[2][2]);
+
+ if(s>FLT_EPSILON) {
+ s= sqrt(s);
+ q[2]= (float)s;
+ q[3]= (float)(mat[1][2]/(2*s));
+ }
+ else {
+ q[2]= 0.0f;
+ q[3]= 1.0f;
+ }
+ }
+ }
+ NormalQuat(q);
+}
+
+void Mat3ToQuat_is_ok(const float wmat[][3], float *q)
+{
+ float mat[3][3], matr[3][3], matn[3][3], q1[4], q2[4], hoek, si, co, nor[3];
+
+ /* voor de netheid: op kopie werken */
+ Mat3CpyMat3(mat, wmat);
+ Mat3Ortho(mat);
+
+ /* roteer z-as matrix op z-as */
+
+ nor[0] = mat[2][1]; /* uitprodukt met (0,0,1) */
+ nor[1] = -mat[2][0];
+ nor[2] = 0.0;
+ Normalise(nor);
+
+ co= mat[2][2];
+ hoek= 0.5f*saacos(co);
+
+ co= (float)cos(hoek);
+ si= (float)sin(hoek);
+ q1[0]= co;
+ q1[1]= -nor[0]*si; /* hier negatief, waarom is een raadsel */
+ q1[2]= -nor[1]*si;
+ q1[3]= -nor[2]*si;
+
+ /* roteer x-as van mat terug volgens inverse q1 */
+ QuatToMat3(q1, matr);
+ Mat3Inv(matn, matr);
+ Mat3MulVecfl(matn, mat[0]);
+
+ /* en zet de x-asssen gelijk */
+ hoek= (float)(0.5*atan2(mat[0][1], mat[0][0]));
+
+ co= (float)cos(hoek);
+ si= (float)sin(hoek);
+ q2[0]= co;
+ q2[1]= 0.0f;
+ q2[2]= 0.0f;
+ q2[3]= si;
+
+ QuatMul(q, q1, q2);
+}
+
+
+void Mat4ToQuat(const float m[][4], float *q)
+{
+ float mat[3][3];
+
+ Mat3CpyMat4(mat, m);
+ Mat3ToQuat(mat, q);
+
+}
+
+void QuatOne(float *q)
+{
+ q[0]= q[2]= q[3]= 0.0;
+ q[1]= 1.0;
+}
+
+void NormalQuat(float *q)
+{
+ float len;
+
+ len= (float)sqrt(q[0]*q[0]+q[1]*q[1]+q[2]*q[2]+q[3]*q[3]);
+ if(len!=0.0) {
+ q[0]/= len;
+ q[1]/= len;
+ q[2]/= len;
+ q[3]/= len;
+ } else {
+ q[1]= 1.0f;
+ q[0]= q[2]= q[3]= 0.0f;
+ }
+}
+
+float *vectoquat(const float *vec, short axis, short upflag)
+{
+ static float q1[4];
+ float q2[4], nor[3], *fp, mat[3][3], hoek, si, co, x2, y2, z2, len1;
+
+ /* eerst roteer naar as */
+ if(axis>2) {
+ x2= vec[0] ; y2= vec[1] ; z2= vec[2];
+ axis-= 3;
+ }
+ else {
+ x2= -vec[0] ; y2= -vec[1] ; z2= -vec[2];
+ }
+
+ q1[0]=1.0;
+ q1[1]=q1[2]=q1[3]= 0.0;
+
+ len1= (float)sqrt(x2*x2+y2*y2+z2*z2);
+ if(len1 == 0.0) return(q1);
+
+ /* nasty! I need a good routine for this...
+ * problem is a rotation of an Y axis to the negative Y-axis for example.
+ */
+
+ if(axis==0) { /* x-as */
+ nor[0]= 0.0;
+ nor[1]= -z2;
+ nor[2]= y2;
+
+ if( fabs(y2)+fabs(z2)<0.0001 ) {
+ nor[1]= 1.0;
+ }
+
+ co= x2;
+ }
+ else if(axis==1) { /* y-as */
+ nor[0]= z2;
+ nor[1]= 0.0;
+ nor[2]= -x2;
+
+ if( fabs(x2)+fabs(z2)<0.0001 ) {
+ nor[2]= 1.0;
+ }
+
+ co= y2;
+ }
+ else { /* z-as */
+ nor[0]= -y2;
+ nor[1]= x2;
+ nor[2]= 0.0;
+
+ if( fabs(x2)+fabs(y2)<0.0001 ) {
+ nor[0]= 1.0;
+ }
+
+ co= z2;
+ }
+ co/= len1;
+
+ Normalise(nor);
+
+ hoek= 0.5f*saacos(co);
+ si= (float)sin(hoek);
+ q1[0]= (float)cos(hoek);
+ q1[1]= nor[0]*si;
+ q1[2]= nor[1]*si;
+ q1[3]= nor[2]*si;
+
+ if(axis!=upflag) {
+ QuatToMat3(q1, mat);
+
+ fp= mat[2];
+ if(axis==0) {
+ if(upflag==1) hoek= (float)(0.5*atan2(fp[2], fp[1]));
+ else hoek= (float)(-0.5*atan2(fp[1], fp[2]));
+ }
+ else if(axis==1) {
+ if(upflag==0) hoek= (float)(-0.5*atan2(fp[2], fp[0]));
+ else hoek= (float)(0.5*atan2(fp[0], fp[2]));
+ }
+ else {
+ if(upflag==0) hoek= (float)(0.5*atan2(-fp[1], -fp[0]));
+ else hoek= (float)(-0.5*atan2(-fp[0], -fp[1]));
+ }
+
+ co= (float)cos(hoek);
+ si= (float)(sin(hoek)/len1);
+ q2[0]= co;
+ q2[1]= x2*si;
+ q2[2]= y2*si;
+ q2[3]= z2*si;
+
+ QuatMul(q1,q2,q1);
+ }
+
+ return(q1);
+}
+
+void VecUpMat3old(const float *vec, float mat[][3], short axis)
+{
+ float inp, up[3];
+ short cox = 0, coy = 0, coz = 0;
+
+ /* up varieeren heeft geen zin, is eigenlijk helemaal geen up!
+ */
+
+ up[0]= 0.0;
+ up[1]= 0.0;
+ up[2]= 1.0;
+
+ if(axis==0) {
+ cox= 0; coy= 1; coz= 2; /* Y up Z tr */
+ }
+ if(axis==1) {
+ cox= 1; coy= 2; coz= 0; /* Z up X tr */
+ }
+ if(axis==2) {
+ cox= 2; coy= 0; coz= 1; /* X up Y tr */
+ }
+ if(axis==3) {
+ cox= 0; coy= 2; coz= 1; /* */
+ }
+ if(axis==4) {
+ cox= 1; coy= 0; coz= 2; /* */
+ }
+ if(axis==5) {
+ cox= 2; coy= 1; coz= 0; /* Y up X tr */
+ }
+
+ mat[coz][0]= vec[0];
+ mat[coz][1]= vec[1];
+ mat[coz][2]= vec[2];
+ Normalise((float *)mat[coz]);
+
+ inp= mat[coz][0]*up[0] + mat[coz][1]*up[1] + mat[coz][2]*up[2];
+ mat[coy][0]= up[0] - inp*mat[coz][0];
+ mat[coy][1]= up[1] - inp*mat[coz][1];
+ mat[coy][2]= up[2] - inp*mat[coz][2];
+
+ Normalise((float *)mat[coy]);
+
+ Crossf(mat[cox], mat[coy], mat[coz]);
+
+}
+
+void VecUpMat3(float *vec, float mat[][3], short axis)
+{
+ float inp;
+ short cox = 0, coy = 0, coz = 0;
+
+ /* up varieeren heeft geen zin, is eigenlijk helemaal geen up!
+ * zie VecUpMat3old
+ */
+
+ if(axis==0) {
+ cox= 0; coy= 1; coz= 2; /* Y up Z tr */
+ }
+ if(axis==1) {
+ cox= 1; coy= 2; coz= 0; /* Z up X tr */
+ }
+ if(axis==2) {
+ cox= 2; coy= 0; coz= 1; /* X up Y tr */
+ }
+ if(axis==3) {
+ cox= 0; coy= 1; coz= 2; /* Y op -Z tr */
+ vec[0]= -vec[0];
+ vec[1]= -vec[1];
+ vec[2]= -vec[2];
+ }
+ if(axis==4) {
+ cox= 1; coy= 0; coz= 2; /* */
+ }
+ if(axis==5) {
+ cox= 2; coy= 1; coz= 0; /* Y up X tr */
+ }
+
+ mat[coz][0]= vec[0];
+ mat[coz][1]= vec[1];
+ mat[coz][2]= vec[2];
+ Normalise((float *)mat[coz]);
+
+ inp= mat[coz][2];
+ mat[coy][0]= - inp*mat[coz][0];
+ mat[coy][1]= - inp*mat[coz][1];
+ mat[coy][2]= 1.0f - inp*mat[coz][2];
+
+ Normalise((float *)mat[coy]);
+
+ Crossf(mat[cox], mat[coy], mat[coz]);
+
+}
+
+
+/* **************** VIEW / PROJEKTIE ******************************** */
+
+
+void i_ortho(
+ float left, float right,
+ float bottom, float top,
+ float nearClip, float farClip,
+ float matrix[][4]
+){
+ float Xdelta, Ydelta, Zdelta;
+
+ Xdelta = right - left;
+ Ydelta = top - bottom;
+ Zdelta = farClip - nearClip;
+ if (Xdelta == 0.0 || Ydelta == 0.0 || Zdelta == 0.0) {
+ return;
+ }
+ Mat4One(matrix);
+ matrix[0][0] = 2.0f/Xdelta;
+ matrix[3][0] = -(right + left)/Xdelta;
+ matrix[1][1] = 2.0f/Ydelta;
+ matrix[3][1] = -(top + bottom)/Ydelta;
+ matrix[2][2] = -2.0f/Zdelta; /* note: negate Z */
+ matrix[3][2] = -(farClip + nearClip)/Zdelta;
+}
+
+void i_window(
+ float left, float right,
+ float bottom, float top,
+ float nearClip, float farClip,
+ float mat[][4]
+){
+ float Xdelta, Ydelta, Zdelta;
+
+ Xdelta = right - left;
+ Ydelta = top - bottom;
+ Zdelta = farClip - nearClip;
+
+ if (Xdelta == 0.0 || Ydelta == 0.0 || Zdelta == 0.0) {
+ return;
+ }
+ mat[0][0] = nearClip * 2.0f/Xdelta;
+ mat[1][1] = nearClip * 2.0f/Ydelta;
+ mat[2][0] = (right + left)/Xdelta; /* note: negate Z */
+ mat[2][1] = (top + bottom)/Ydelta;
+ mat[2][2] = -(farClip + nearClip)/Zdelta;
+ mat[2][3] = -1.0f;
+ mat[3][2] = (-2.0f * nearClip * farClip)/Zdelta;
+ mat[0][1] = mat[0][2] = mat[0][3] =
+ mat[1][0] = mat[1][2] = mat[1][3] =
+ mat[3][0] = mat[3][1] = mat[3][3] = 0.0;
+
+}
+
+void i_translate(float Tx, float Ty, float Tz, float mat[][4])
+{
+ mat[3][0] += (Tx*mat[0][0] + Ty*mat[1][0] + Tz*mat[2][0]);
+ mat[3][1] += (Tx*mat[0][1] + Ty*mat[1][1] + Tz*mat[2][1]);
+ mat[3][2] += (Tx*mat[0][2] + Ty*mat[1][2] + Tz*mat[2][2]);
+}
+
+void i_multmatrix(const float icand[][4], float Vm[][4])
+{
+ int row, col;
+ float temp[4][4];
+
+ for(row=0 ; row<4 ; row++)
+ for(col=0 ; col<4 ; col++)
+ temp[row][col] = icand[row][0] * Vm[0][col]
+ + icand[row][1] * Vm[1][col]
+ + icand[row][2] * Vm[2][col]
+ + icand[row][3] * Vm[3][col];
+ Mat4CpyMat4(Vm, temp);
+}
+
+void i_rotate(float angle, char axis, float mat[][4])
+{
+ int col;
+ float temp[4];
+ float cosine, sine;
+
+ for(col=0; col<4 ; col++) /* init temp to zero matrix */
+ temp[col] = 0;
+
+ angle = (float)(angle*(3.1415926535/180.0));
+ cosine = (float)cos(angle);
+ sine = (float)sin(angle);
+ switch(axis){
+ case 'x':
+ case 'X':
+ for(col=0 ; col<4 ; col++)
+ temp[col] = cosine*mat[1][col] + sine*mat[2][col];
+ for(col=0 ; col<4 ; col++) {
+ mat[2][col] = - sine*mat[1][col] + cosine*mat[2][col];
+ mat[1][col] = temp[col];
+ }
+ break;
+
+ case 'y':
+ case 'Y':
+ for(col=0 ; col<4 ; col++)
+ temp[col] = cosine*mat[0][col] - sine*mat[2][col];
+ for(col=0 ; col<4 ; col++) {
+ mat[2][col] = sine*mat[0][col] + cosine*mat[2][col];
+ mat[0][col] = temp[col];
+ }
+ break;
+
+ case 'z':
+ case 'Z':
+ for(col=0 ; col<4 ; col++)
+ temp[col] = cosine*mat[0][col] + sine*mat[1][col];
+ for(col=0 ; col<4 ; col++) {
+ mat[1][col] = - sine*mat[0][col] + cosine*mat[1][col];
+ mat[0][col] = temp[col];
+ }
+ break;
+ }
+}
+
+void i_polarview(float dist, float azimuth, float incidence, float twist, float Vm[][4])
+{
+
+ Mat4One(Vm);
+
+ i_translate(0.0, 0.0, -dist, Vm);
+ i_rotate(-twist,'z', Vm);
+ i_rotate(-incidence,'x', Vm);
+ i_rotate(-azimuth,'z', Vm);
+}
+
+void i_lookat(float vx, float vy, float vz, float px, float py, float pz, float twist, float mat[][4])
+{
+ float sine, cosine, hyp, hyp1, dx, dy, dz;
+ float mat1[4][4];
+
+ Mat4One(mat);
+ Mat4One(mat1);
+
+ i_rotate(-twist,'z', mat);
+
+ dx = px - vx;
+ dy = py - vy;
+ dz = pz - vz;
+ hyp = dx * dx + dz * dz; /* hyp squared */
+ hyp1 = (float)sqrt(dy*dy + hyp);
+ hyp = (float)sqrt(hyp); /* the real hyp */
+
+ if (hyp1 != 0.0) { /* rotate X */
+ sine = -dy / hyp1;
+ cosine = hyp /hyp1;
+ } else {
+ sine = 0;
+ cosine = 1.0f;
+ }
+ mat1[1][1] = cosine;
+ mat1[1][2] = sine;
+ mat1[2][1] = -sine;
+ mat1[2][2] = cosine;
+
+ i_multmatrix(mat1, mat);
+
+ mat1[1][1] = mat1[2][2] = 1.0f; /* be careful here to reinit */
+ mat1[1][2] = mat1[2][1] = 0.0; /* those modified by the last */
+
+ /* paragraph */
+ if (hyp != 0.0f) { /* rotate Y */
+ sine = dx / hyp;
+ cosine = -dz / hyp;
+ } else {
+ sine = 0;
+ cosine = 1.0f;
+ }
+ mat1[0][0] = cosine;
+ mat1[0][2] = -sine;
+ mat1[2][0] = sine;
+ mat1[2][2] = cosine;
+
+ i_multmatrix(mat1, mat);
+ i_translate(-vx,-vy,-vz, mat); /* translate viewpoint to origin */
+}
+
+
+
+
+
+/* ************************************************ */
+
+void Mat3Ortho(float mat[][3])
+{
+ Normalise(mat[0]);
+ Normalise(mat[1]);
+ Normalise(mat[2]);
+}
+
+void Mat4Ortho(float mat[][4])
+{
+ float len;
+
+ len= Normalise(mat[0]);
+ if(len!=0.0) mat[0][3]/= len;
+ len= Normalise(mat[1]);
+ if(len!=0.0) mat[1][3]/= len;
+ len= Normalise(mat[2]);
+ if(len!=0.0) mat[2][3]/= len;
+}
+
+void VecCopyf(float *v1, const float *v2)
+{
+
+ v1[0]= v2[0];
+ v1[1]= v2[1];
+ v1[2]= v2[2];
+}
+
+int VecLen(const int *v1, const int *v2)
+{
+ float x,y,z;
+
+ x=(float)(v1[0]-v2[0]);
+ y=(float)(v1[1]-v2[1]);
+ z=(float)(v1[2]-v2[2]);
+ return (int)floor(sqrt(x*x+y*y+z*z));
+}
+
+float VecLenf(const float *v1, const float *v2)
+{
+ float x,y,z;
+
+ x=v1[0]-v2[0];
+ y=v1[1]-v2[1];
+ z=v1[2]-v2[2];
+ return (float)sqrt(x*x+y*y+z*z);
+}
+
+void VecAddf(float *v, const float *v1, const float *v2)
+{
+ v[0]= v1[0]+ v2[0];
+ v[1]= v1[1]+ v2[1];
+ v[2]= v1[2]+ v2[2];
+}
+
+void VecSubf(float *v, const float *v1, const float *v2)
+{
+ v[0]= v1[0]- v2[0];
+ v[1]= v1[1]- v2[1];
+ v[2]= v1[2]- v2[2];
+}
+
+void VecMidf(float *v, const float *v1, const float *v2)
+{
+ v[0]= 0.5f*(v1[0]+ v2[0]);
+ v[1]= 0.5f*(v1[1]+ v2[1]);
+ v[2]= 0.5f*(v1[2]+ v2[2]);
+}
+
+void VecMulf(float *v1, float f)
+{
+
+ v1[0]*= f;
+ v1[1]*= f;
+ v1[2]*= f;
+}
+
+int VecCompare(const float *v1, const float *v2, float limit)
+{
+ if( fabs(v1[0]-v2[0])<limit )
+ if( fabs(v1[1]-v2[1])<limit )
+ if( fabs(v1[2]-v2[2])<limit ) return 1;
+ return 0;
+}
+
+void CalcNormShort(const short *v1, const short *v2, const short *v3, float *n) /* is ook uitprodukt */
+{
+ float n1[3],n2[3];
+
+ n1[0]= (float)(v1[0]-v2[0]);
+ n2[0]= (float)(v2[0]-v3[0]);
+ n1[1]= (float)(v1[1]-v2[1]);
+ n2[1]= (float)(v2[1]-v3[1]);
+ n1[2]= (float)(v1[2]-v2[2]);
+ n2[2]= (float)(v2[2]-v3[2]);
+ n[0]= n1[1]*n2[2]-n1[2]*n2[1];
+ n[1]= n1[2]*n2[0]-n1[0]*n2[2];
+ n[2]= n1[0]*n2[1]-n1[1]*n2[0];
+ Normalise(n);
+}
+
+void CalcNormLong(const int* v1, const int*v2, const int*v3, float *n)
+{
+ float n1[3],n2[3];
+
+ n1[0]= (float)(v1[0]-v2[0]);
+ n2[0]= (float)(v2[0]-v3[0]);
+ n1[1]= (float)(v1[1]-v2[1]);
+ n2[1]= (float)(v2[1]-v3[1]);
+ n1[2]= (float)(v1[2]-v2[2]);
+ n2[2]= (float)(v2[2]-v3[2]);
+ n[0]= n1[1]*n2[2]-n1[2]*n2[1];
+ n[1]= n1[2]*n2[0]-n1[0]*n2[2];
+ n[2]= n1[0]*n2[1]-n1[1]*n2[0];
+ Normalise(n);
+}
+
+float CalcNormFloat(const float *v1, const float *v2, const float *v3, float *n)
+{
+ float n1[3],n2[3];
+
+ n1[0]= v1[0]-v2[0];
+ n2[0]= v2[0]-v3[0];
+ n1[1]= v1[1]-v2[1];
+ n2[1]= v2[1]-v3[1];
+ n1[2]= v1[2]-v2[2];
+ n2[2]= v2[2]-v3[2];
+ n[0]= n1[1]*n2[2]-n1[2]*n2[1];
+ n[1]= n1[2]*n2[0]-n1[0]*n2[2];
+ n[2]= n1[0]*n2[1]-n1[1]*n2[0];
+ return Normalise(n);
+}
+
+float CalcNormFloat4(const float *v1, const float *v2, const float *v3, const float *v4, float *n)
+{
+ /* real cross! */
+ float n1[3],n2[3];
+
+ n1[0]= v1[0]-v3[0];
+ n1[1]= v1[1]-v3[1];
+ n1[2]= v1[2]-v3[2];
+
+ n2[0]= v2[0]-v4[0];
+ n2[1]= v2[1]-v4[1];
+ n2[2]= v2[2]-v4[2];
+
+ n[0]= n1[1]*n2[2]-n1[2]*n2[1];
+ n[1]= n1[2]*n2[0]-n1[0]*n2[2];
+ n[2]= n1[0]*n2[1]-n1[1]*n2[0];
+
+ return Normalise(n);
+}
+
+
+void CalcCent3f(float *cent, const float *v1, const float *v2, const float *v3)
+{
+
+ cent[0]= 0.33333f*(v1[0]+v2[0]+v3[0]);
+ cent[1]= 0.33333f*(v1[1]+v2[1]+v3[1]);
+ cent[2]= 0.33333f*(v1[2]+v2[2]+v3[2]);
+}
+
+void CalcCent4f(float *cent, const float *v1, const float *v2, const float *v3, const float *v4)
+{
+
+ cent[0]= 0.25f*(v1[0]+v2[0]+v3[0]+v4[0]);
+ cent[1]= 0.25f*(v1[1]+v2[1]+v3[1]+v4[1]);
+ cent[2]= 0.25f*(v1[2]+v2[2]+v3[2]+v4[2]);
+}
+
+float Sqrt3f(float f)
+{
+ if(f==0.0) return 0;
+ if(f<0) return (float)(-exp(log(-f)/3));
+ else return (float)(exp(log(f)/3));
+}
+
+double Sqrt3d(double d)
+{
+ if(d==0.0) return 0;
+ if(d<0) return -exp(log(-d)/3);
+ else return exp(log(d)/3);
+}
+ /* afstand v1 tot lijn v2-v3 */
+float DistVL2Dfl(const float *v1,const float *v2,const float *v3) /* met formule van Hesse :GEEN LIJNSTUK! */
+{
+ float a[2],deler;
+
+ a[0]= v2[1]-v3[1];
+ a[1]= v3[0]-v2[0];
+ deler= (float)sqrt(a[0]*a[0]+a[1]*a[1]);
+ if(deler== 0.0f) return 0;
+
+ return (float)(fabs((v1[0]-v2[0])*a[0]+(v1[1]-v2[1])*a[1])/deler);
+
+}
+
+float PdistVL2Dfl(const float *v1,const float *v2,const float *v3) /* PointDist: WEL LIJNSTUK */
+{
+ float labda, rc[2], pt[2], len;
+
+ rc[0]= v3[0]-v2[0];
+ rc[1]= v3[1]-v2[1];
+ len= rc[0]*rc[0]+ rc[1]*rc[1];
+ if(len==0.0) {
+ rc[0]= v1[0]-v2[0];
+ rc[1]= v1[1]-v2[1];
+ return (float)(sqrt(rc[0]*rc[0]+ rc[1]*rc[1]));
+ }
+
+ labda= ( rc[0]*(v1[0]-v2[0]) + rc[1]*(v1[1]-v2[1]) )/len;
+ if(labda<=0.0) {
+ pt[0]= v2[0];
+ pt[1]= v2[1];
+ }
+ else if(labda>=1.0) {
+ pt[0]= v3[0];
+ pt[1]= v3[1];
+ }
+ else {
+ pt[0]= labda*rc[0]+v2[0];
+ pt[1]= labda*rc[1]+v2[1];
+ }
+
+ rc[0]= pt[0]-v1[0];
+ rc[1]= pt[1]-v1[1];
+ return (float)sqrt(rc[0]*rc[0]+ rc[1]*rc[1]);
+}
+
+float AreaF2Dfl(const float *v1,const float *v2,const float *v3)
+{
+ return (float)(0.5*fabs( (v1[0]-v2[0])*(v2[1]-v3[1]) + (v1[1]-v2[1])*(v3[0]-v2[0]) ));
+}
+
+
+float AreaQ3Dfl(const float *v1,const float *v2,const float *v3, const float *v4) /* only convex Quadrilaterals */
+{
+ float len, vec1[3], vec2[3], n[3];
+
+ VecSubf(vec1, v2, v1);
+ VecSubf(vec2, v4, v1);
+ Crossf(n, vec1, vec2);
+ len= Normalise(n);
+
+ VecSubf(vec1, v4, v3);
+ VecSubf(vec2, v2, v3);
+ Crossf(n, vec1, vec2);
+ len+= Normalise(n);
+
+ return (len/2.0f);
+}
+
+float AreaT3Dfl(const float *v1,const float *v2,const float *v3) /* Triangles */
+{
+ float len, vec1[3], vec2[3], n[3];
+
+ VecSubf(vec1, v3, v2);
+ VecSubf(vec2, v1, v2);
+ Crossf(n, vec1, vec2);
+ len= Normalise(n);
+
+ return (len/2.0f);
+}
+
+#define MAX2(x,y) ( (x)>(y) ? (x) : (y) )
+#define MAX3(x,y,z) MAX2( MAX2((x),(y)) , (z) )
+
+
+float AreaPoly3Dfl(int nr, const float *verts, const float *normal)
+{
+ float x, y, z, area, max;
+ const float *cur, *prev;
+ int a, px=0, py=1;
+
+ /* first: find dominant axis: 0==X, 1==Y, 2==Z */
+ x= (float)fabs(normal[0]);
+ y= (float)fabs(normal[1]);
+ z= (float)fabs(normal[2]);
+ max = MAX3(x, y, z);
+ if(max==y) py=2;
+ else if(max==x) {
+ px=1;
+ py= 2;
+ }
+
+ /* The Trapezium Area Rule */
+ prev= verts+3*(nr-1);
+ cur= verts;
+ area= 0;
+ for(a=0; a<nr; a++) {
+ area+= (cur[px]-prev[px])*(cur[py]+prev[py]);
+ prev= cur;
+ cur+=3;
+ }
+
+ return (float)fabs(0.5*area/max);
+}
+
+void MinMax3(float *min, float *max, const float *vec)
+{
+ if(min[0]>vec[0]) min[0]= vec[0];
+ if(min[1]>vec[1]) min[1]= vec[1];
+ if(min[2]>vec[2]) min[2]= vec[2];
+
+ if(max[0]<vec[0]) max[0]= vec[0];
+ if(max[1]<vec[1]) max[1]= vec[1];
+ if(max[2]<vec[2]) max[2]= vec[2];
+}
+
+/* ************ EULER *************** */
+
+void EulToMat3(const float *eul, float mat[][3])
+{
+ double ci, cj, ch, si, sj, sh, cc, cs, sc, ss;
+
+ ci = cos(eul[0]);
+ cj = cos(eul[1]);
+ ch = cos(eul[2]);
+ si = sin(eul[0]);
+ sj = sin(eul[1]);
+ sh = sin(eul[2]);
+ cc = ci*ch;
+ cs = ci*sh;
+ sc = si*ch;
+ ss = si*sh;
+
+ mat[0][0] = (float)(cj*ch);
+ mat[1][0] = (float)(sj*sc-cs);
+ mat[2][0] = (float)(sj*cc+ss);
+ mat[0][1] = (float)(cj*sh);
+ mat[1][1] = (float)(sj*ss+cc);
+ mat[2][1] = (float)(sj*cs-sc);
+ mat[0][2] = (float)-sj;
+ mat[1][2] = (float)(cj*si);
+ mat[2][2] = (float)(cj*ci);
+
+}
+
+void EulToMat4(const float *eul,float mat[][4])
+{
+ double ci, cj, ch, si, sj, sh, cc, cs, sc, ss;
+
+ ci = cos(eul[0]);
+ cj = cos(eul[1]);
+ ch = cos(eul[2]);
+ si = sin(eul[0]);
+ sj = sin(eul[1]);
+ sh = sin(eul[2]);
+ cc = ci*ch;
+ cs = ci*sh;
+ sc = si*ch;
+ ss = si*sh;
+
+ mat[0][0] = (float)(cj*ch);
+ mat[1][0] = (float)(sj*sc-cs);
+ mat[2][0] = (float)(sj*cc+ss);
+ mat[0][1] = (float)(cj*sh);
+ mat[1][1] = (float)(sj*ss+cc);
+ mat[2][1] = (float)(sj*cs-sc);
+ mat[0][2] = (float)-sj;
+ mat[1][2] = (float)(cj*si);
+ mat[2][2] = (float)(cj*ci);
+
+
+ mat[3][0]= mat[3][1]= mat[3][2]= mat[0][3]= mat[1][3]= mat[2][3]= 0.0f;
+ mat[3][3]= 1.0f;
+}
+
+
+void Mat3ToEul(
+ const float tmat[][3], float *eul
+){
+ float cy, quat[4], mat[3][3];
+
+ Mat3ToQuat(tmat, quat);
+ QuatToMat3(quat, mat);
+ Mat3CpyMat3(mat, tmat);
+ Mat3Ortho(mat);
+
+ cy = (float)sqrt(mat[0][0]*mat[0][0] + mat[0][1]*mat[0][1]);
+
+ if (cy > 16.0*FLT_EPSILON) {
+ eul[0] = (float)atan2(mat[1][2], mat[2][2]);
+ eul[1] = (float)atan2(-mat[0][2], cy);
+ eul[2] = (float)atan2(mat[0][1], mat[0][0]);
+ } else {
+ eul[0] = (float)atan2(-mat[2][1], mat[1][1]);
+ eul[1] = (float)atan2(-mat[0][2], cy);
+ eul[2] = 0.0f;
+ }
+}
+
+void Mat3ToEuln(const float tmat[][3], float *eul)
+{
+ float sin1, cos1, sin2, cos2, sin3, cos3;
+
+ sin1 = -tmat[2][0];
+ cos1 = (float)sqrt(1 - sin1*sin1);
+
+ if ( fabs(cos1) > FLT_EPSILON ) {
+ sin2 = tmat[2][1] / cos1;
+ cos2 = tmat[2][2] / cos1;
+ sin3 = tmat[1][0] / cos1;
+ cos3 = tmat[0][0] / cos1;
+ }
+ else {
+ sin2 = -tmat[1][2];
+ cos2 = tmat[1][1];
+ sin3 = 0.0;
+ cos3 = 1.0;
+ }
+
+ eul[0] = (float)atan2(sin3, cos3);
+ eul[1] = (float)atan2(sin1, cos1);
+ eul[2] = (float)atan2(sin2, cos2);
+
+}
+
+
+void QuatToEul(const float *quat, float *eul)
+{
+ float mat[3][3];
+
+ QuatToMat3(quat, mat);
+ Mat3ToEul(mat, eul);
+}
+
+void QuatToSpher(const float *quat, float *sph)
+/* Not working 100% yet I don't think... */
+{
+ float tx, ty, tz;
+ float qw, qx, qy, qz;
+ float cos_theta;
+ float sin_theta;
+
+ qx = quat[0];
+ qy = quat[1];
+ qz = quat[2];
+ qw = quat[3];
+
+ cos_theta = qw;
+ sin_theta = (float)sqrt(1.0 - cos_theta * cos_theta);
+
+ if (fabs(sin_theta) < 0.0005)
+ sin_theta = 1.0;
+
+ tx = qx / sin_theta;
+ ty = qy / sin_theta;
+ tz = qz / sin_theta;
+
+ /* Lattitude */
+ sph[0] = -(float)asin(ty);
+
+ /* Longitude */
+ if (tx*tx + tz*tz <0.0005)
+ sph[1] = 0.0;
+ else
+ sph[1] = (float)atan2(tx, tz);
+
+ if (sph[1] < 0.0)
+ sph[1] +=(float)(M_PI*2);
+
+ /* Roll */
+ sph[2] = (float)(acos(cos_theta) * 2.0) ;
+}
+
+void Mat3ToSpher (const float *mat3, float *sph)
+{
+ float quat[4];
+
+ Mat3ToQuat(mat3, quat);
+ QuatToSpher(quat, sph);
+}
+
+
+void EulToQuat(const float *eul, float *quat)
+{
+ float ti, tj, th, ci, cj, ch, si, sj, sh, cc, cs, sc, ss;
+
+ ti = eul[0]*0.5f; tj = eul[1]*0.5f; th = eul[2]*0.5f;
+ ci = (float)cos(ti); cj = (float)cos(tj); ch = (float)cos(th);
+ si = (float)sin(ti); sj = (float)sin(tj); sh = (float)sin(th);
+ cc = ci*ch; cs = ci*sh; sc = si*ch; ss = si*sh;
+
+ quat[0] = cj*cc + sj*ss;
+ quat[1] = cj*sc - sj*cs;
+ quat[2] = cj*ss + sj*cc;
+ quat[3] = cj*cs - sj*sc;
+}
+
+void VecRotToMat3(const float *vec, float phi, float mat[][3])
+{
+ /* rotation of phi radials around vec */
+ float vx, vx2, vy, vy2, vz, vz2, co, si;
+
+ vx= vec[0];
+ vy= vec[1];
+ vz= vec[2];
+ vx2= vx*vx;
+ vy2= vy*vy;
+ vz2= vz*vz;
+ co= (float)cos(phi);
+ si= (float)sin(phi);
+
+ mat[0][0]= vx2+co*(1.0f-vx2);
+ mat[0][1]= vx*vy*(1.0f-co)+vz*si;
+ mat[0][2]= vz*vx*(1.0f-co)-vy*si;
+ mat[1][0]= vx*vy*(1.0f-co)-vz*si;
+ mat[1][1]= vy2+co*(1.0f-vy2);
+ mat[1][2]= vy*vz*(1.0f-co)+vx*si;
+ mat[2][0]= vz*vx*(1.0f-co)+vy*si;
+ mat[2][1]= vy*vz*(1.0f-co)-vx*si;
+ mat[2][2]= vz2+co*(1.0f-vz2);
+
+}
+
+void VecRotToQuat(const float *vec, float phi, float *quat)
+{
+ /* rotation of phi radials around vec */
+ float si;
+
+ quat[1]= vec[0];
+ quat[2]= vec[1];
+ quat[3]= vec[2];
+
+ if( Normalise(quat+1) == 0.0) {
+ QuatOne(quat);
+ }
+ else {
+ quat[0]= (float)cos( phi/2.0 );
+ si= (float)sin( phi/2.0 );
+ quat[1] *= si;
+ quat[2] *= si;
+ quat[3] *= si;
+ }
+}
+
+void euler_rot(float *beul, float ang, char axis)
+{
+ float eul[3], mat1[3][3], mat2[3][3], totmat[3][3];
+
+ eul[0]= eul[1]= eul[2]= 0.0;
+ if(axis=='x') eul[0]= ang;
+ else if(axis=='y') eul[1]= ang;
+ else eul[2]= ang;
+
+ EulToMat3(eul, mat1);
+ EulToMat3(beul, mat2);
+
+ Mat3MulMat3(totmat, mat2, mat1);
+
+ Mat3ToEul(totmat, beul);
+
+}
+
+
+
+void SizeToMat3(const float *size, float mat[][3])
+{
+ mat[0][0]= size[0];
+ mat[0][1]= 0.0;
+ mat[0][2]= 0.0;
+ mat[1][1]= size[1];
+ mat[1][0]= 0.0;
+ mat[1][2]= 0.0;
+ mat[2][2]= size[2];
+ mat[2][1]= 0.0;
+ mat[2][0]= 0.0;
+}
+
+void Mat3ToSize(const float mat[][3], float *size)
+{
+ float vec[3];
+
+
+ VecCopyf(vec, mat[0]);
+ size[0]= Normalise(vec);
+ VecCopyf(vec, mat[1]);
+ size[1]= Normalise(vec);
+ VecCopyf(vec, mat[2]);
+ size[2]= Normalise(vec);
+
+}
+
+void Mat4ToSize(const float mat[][4], float *size)
+{
+ float vec[3];
+
+
+ VecCopyf(vec, mat[0]);
+ size[0]= Normalise(vec);
+ VecCopyf(vec, mat[1]);
+ size[1]= Normalise(vec);
+ VecCopyf(vec, mat[2]);
+ size[2]= Normalise(vec);
+}
+
+/* ************* SPECIALS ******************* */
+
+void triatoquat(const float *v1, const float *v2, const float *v3, float *quat)
+{
+ /* denkbeeldige x-as, y-as driehoek wordt geroteerd */
+ float vec[3], q1[4], q2[4], n[3], si, co, hoek, mat[3][3], imat[3][3];
+
+ /* eerst z-as op vlaknormaal */
+ CalcNormFloat(v1, v2, v3, vec);
+
+ n[0]= vec[1];
+ n[1]= -vec[0];
+ n[2]= 0.0;
+ Normalise(n);
+
+ if(n[0]==0.0 && n[1]==0.0) n[0]= 1.0;
+
+ hoek= -0.5f*saacos(vec[2]);
+ co= (float)cos(hoek);
+ si= (float)sin(hoek);
+ q1[0]= co;
+ q1[1]= n[0]*si;
+ q1[2]= n[1]*si;
+ q1[3]= 0.0f;
+
+ /* v1-v2 lijn terug roteren */
+ QuatToMat3(q1, mat);
+ Mat3Inv(imat, mat);
+ VecSubf(vec, v2, v1);
+ Mat3MulVecfl(imat, vec);
+
+ /* welke hoek maakt deze lijn met x-as? */
+ vec[2]= 0.0;
+ Normalise(vec);
+
+ hoek= (float)(0.5*atan2(vec[1], vec[0]));
+ co= (float)cos(hoek);
+ si= (float)sin(hoek);
+ q2[0]= co;
+ q2[1]= 0.0f;
+ q2[2]= 0.0f;
+ q2[3]= si;
+
+ QuatMul(quat, q1, q2);
+}
+
+void MinMaxRGB(short c[])
+{
+ if(c[0]>255) c[0]=255;
+ else if(c[0]<0) c[0]=0;
+ if(c[1]>255) c[1]=255;
+ else if(c[1]<0) c[1]=0;
+ if(c[2]>255) c[2]=255;
+ else if(c[2]<0) c[2]=0;
+}
+
+void hsv_to_rgb(float h, float s, float v, float *r, float *g, float *b)
+{
+ int i;
+ float f, p, q, t;
+
+ h *= 360.0f;
+
+ if(s==0 && 0) {
+ *r = v;
+ *g = v;
+ *b = v;
+ }
+ else {
+ if(h==360) h = 0;
+
+ h /= 60;
+ i = (int)floor(h);
+ f = h - i;
+ p = v*(1.0f-s);
+ q = v*(1.0f-(s*f));
+ t = v*(1.0f-(s*(1.0f-f)));
+
+ switch (i) {
+ case 0 :
+ *r = v;
+ *g = t;
+ *b = p;
+ break;
+ case 1 :
+ *r = q;
+ *g = v;
+ *b = p;
+ break;
+ case 2 :
+ *r = p;
+ *g = v;
+ *b = t;
+ break;
+ case 3 :
+ *r = p;
+ *g = q;
+ *b = v;
+ break;
+ case 4 :
+ *r = t;
+ *g = p;
+ *b = v;
+ break;
+ case 5 :
+ *r = v;
+ *g = p;
+ *b = q;
+ break;
+ }
+ }
+}
+
+void rgb_to_hsv(float r, float g, float b, float *lh, float *ls, float *lv)
+{
+ float h, s, v;
+ float cmax, cmin, cdelta;
+ float rc, gc, bc;
+
+ cmax = r;
+ cmin = r;
+ cmax = (g>cmax ? g:cmax);
+ cmin = (g<cmin ? g:cmin);
+ cmax = (b>cmax ? b:cmax);
+ cmin = (b<cmin ? b:cmin);
+
+ v = cmax; /* value */
+ if (cmax!=0.0)
+ s = (cmax - cmin)/cmax;
+ else {
+ s = 0.0;
+ h = 0.0;
+ }
+ if (s == 0.0)
+ h = -1.0;
+ else {
+ cdelta = cmax-cmin;
+ rc = (cmax-r)/cdelta;
+ gc = (cmax-g)/cdelta;
+ bc = (cmax-b)/cdelta;
+ if (r==cmax)
+ h = bc-gc;
+ else
+ if (g==cmax)
+ h = 2.0f+rc-bc;
+ else
+ h = 4.0f+gc-rc;
+ h = h*60.0f;
+ if (h<0.0f)
+ h += 360.0f;
+ }
+
+ *ls = s;
+ *lh = h/360.0f;
+ if( *lh < 0.0) *lh= 0.0;
+ *lv = v;
+}
+
+/* Bij afspraak is cpack een getal dat als 0xFFaa66 of zo kan worden uitgedrukt. Is dus gevoelig voor endian.
+ * Met deze define wordt het altijd goed afgebeeld
+ */
+
+unsigned int hsv_to_cpack(float h, float s, float v)
+{
+ short r, g, b;
+ float rf, gf, bf;
+ unsigned int col;
+
+ hsv_to_rgb(h, s, v, &rf, &gf, &bf);
+
+ r= (short)(rf*255.0f);
+ g= (short)(gf*255.0f);
+ b= (short)(bf*255.0f);
+
+ col= ( r + (g*256) + (b*256*256) );
+ return col;
+}
+
+
+unsigned int rgb_to_cpack(float r, float g, float b)
+{
+ int ir, ig, ib;
+
+ ir= (int)floor(255.0*r);
+ if(ir<0) ir= 0; else if(ir>255) ir= 255;
+ ig= (int)floor(255.0*g);
+ if(ig<0) ig= 0; else if(ig>255) ig= 255;
+ ib= (int)floor(255.0*b);
+ if(ib<0) ib= 0; else if(ib>255) ib= 255;
+
+ return (ir+ (ig*256) + (ib*256*256));
+}
+
+void cpack_to_rgb(unsigned int col, float *r, float *g, float *b)
+{
+
+ *r= (float)((col)&0xFF);
+ *r /= 255.0f;
+
+ *g= (float)(((col)>>8)&0xFF);
+ *g /= 255.0f;
+
+ *b= (float)(((col)>>16)&0xFF);
+ *b /= 255.0f;
+}
diff --git a/source/blender/blenlib/intern/dynlib.c b/source/blender/blenlib/intern/dynlib.c
new file mode 100644
index 00000000000..c232be3c206
--- /dev/null
+++ b/source/blender/blenlib/intern/dynlib.c
@@ -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 *****
+ */
+#include <stdlib.h>
+
+#include "../PIL_dynlib.h"
+
+/*
+ * XXX, should use mallocN so we can see
+ * handle's not being released. fixme zr
+ */
+
+#ifdef WIN32
+
+#include <windows.h>
+
+struct PILdynlib {
+ void *handle;
+};
+
+PILdynlib *PIL_dynlib_open(char *name) {
+ void *handle= LoadLibrary(name);
+
+ if (handle) {
+ PILdynlib *lib= malloc(sizeof(*lib));
+ lib->handle= handle;
+
+ return lib;
+ } else {
+ return NULL;
+ }
+}
+
+void *PIL_dynlib_find_symbol(PILdynlib* lib, char *symname) {
+ return GetProcAddress(lib->handle, symname);
+}
+
+char *PIL_dynlib_get_error_as_string(PILdynlib* lib) {
+ int err= GetLastError();
+
+ if (err) {
+ static char buf[1024];
+
+ if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ err,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ buf,
+ sizeof(buf),
+ NULL))
+ return buf;
+ }
+
+ return NULL;
+}
+
+void PIL_dynlib_close(PILdynlib *lib) {
+ FreeLibrary(lib->handle);
+
+ free(lib);
+}
+
+#else
+#ifdef __APPLE__
+
+PILdynlib *PIL_dynlib_open(char *name) {
+ return NULL;
+}
+
+void *PIL_dynlib_find_symbol(PILdynlib* lib, char *symname) {
+ return NULL;
+}
+
+char *PIL_dynlib_get_error_as_string(PILdynlib* lib) {
+ return "Plugins are currently unsupported on OSX";
+}
+
+void PIL_dynlib_close(PILdynlib *lib) {
+ ;
+}
+
+#else /* Unix */
+
+#include <dlfcn.h>
+
+struct PILdynlib {
+ void *handle;
+};
+
+PILdynlib *PIL_dynlib_open(char *name) {
+ void *handle= dlopen(name, RTLD_LAZY);
+
+ if (handle) {
+ PILdynlib *lib= malloc(sizeof(*lib));
+ lib->handle= handle;
+
+ return lib;
+ } else {
+ return NULL;
+ }
+}
+
+void *PIL_dynlib_find_symbol(PILdynlib* lib, char *symname) {
+ return dlsym(lib->handle, symname);
+}
+
+char *PIL_dynlib_get_error_as_string(PILdynlib* lib) {
+ return dlerror();
+}
+
+void PIL_dynlib_close(PILdynlib *lib) {
+ dlclose(lib->handle);
+
+ free(lib);
+}
+
+#endif
+#endif
diff --git a/source/blender/blenlib/intern/fileops.c b/source/blender/blenlib/intern/fileops.c
new file mode 100644
index 00000000000..02f54e60df6
--- /dev/null
+++ b/source/blender/blenlib/intern/fileops.c
@@ -0,0 +1,293 @@
+/*
+ * blenlib/fileops.h
+ *
+ * cleaned up (a bit) mar-01 nzc
+ *
+ * More low-level file things.
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 <string.h>
+#include <stdio.h>
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#else
+#include <sys/param.h>
+#endif
+
+#include "BLI_blenlib.h"
+#include "BLI_storage.h"
+#include "BLI_fileops.h"
+#include "BLI_callbacks.h"
+
+/* implementations: */
+char *first_slash(char *string) {
+ char *ffslash, *fbslash;
+
+ ffslash= strchr(string, '/');
+ fbslash= strchr(string, '\\');
+
+ if (!ffslash) return fbslash;
+ else if (!fbslash) return ffslash;
+
+ if ((int)ffslash < (int)fbslash) return ffslash;
+ else return fbslash;
+}
+
+char *BLI_last_slash(char *string) {
+ char *lfslash, *lbslash;
+
+ lfslash= strrchr(string, '/');
+ lbslash= strrchr(string, '\\');
+
+ if (!lfslash) return lbslash;
+ else if (!lbslash) return lfslash;
+
+ if ((int)lfslash < (int)lbslash) return lbslash;
+ else return lfslash;
+}
+
+#ifdef WIN32
+
+static char str[MAXPATHLEN+12];
+
+int BLI_delete(char *file, int dir, int recursive) {
+ int err;
+
+ if (recursive) {
+ callLocalErrorCallBack("Recursive delete is unsupported on Windows");
+ err= 1;
+ } else if (dir) {
+ err= !RemoveDirectory(file);
+ if (err) printf ("Unable to remove directory");
+ } else {
+ err= !DeleteFile(file);
+ if (err) callLocalErrorCallBack("Unable to delete file");
+ }
+
+ return err;
+}
+
+int BLI_touch(char *file) {
+ callLocalErrorCallBack("Touching files is unsupported on Windows");
+
+ return 1;
+}
+
+int BLI_move(char *file, char *to) {
+ int err;
+
+ // windows doesn't support moveing to a directory
+ // it has to be 'mv filename filename' and not
+ // 'mv filename destdir'
+
+ strcpy(str, to);
+ // points 'to' to a directory ?
+ if (BLI_last_slash(str) == (str + strlen(str) - 1)) {
+ if (BLI_last_slash(file) != NULL) {
+ strcat(str, BLI_last_slash(file) + 1);
+ }
+ }
+
+ err= !MoveFile(file, str);
+ if (err) {
+ callLocalErrorCallBack("Unable to move file");
+ printf(" Move from '%s' to '%s' failed\n", file, str);
+ }
+
+ return err;
+}
+
+
+int BLI_copy_fileops(char *file, char *to) {
+ int err;
+
+ // windows doesn't support copying to a directory
+ // it has to be 'cp filename filename' and not
+ // 'cp filename destdir'
+
+ strcpy(str, to);
+ // points 'to' to a directory ?
+ if (BLI_last_slash(str) == (str + strlen(str) - 1)) {
+ if (BLI_last_slash(file) != NULL) {
+ strcat(str, BLI_last_slash(file) + 1);
+ }
+ }
+
+ err= !CopyFile(file,str,FALSE);
+
+ if (err) {
+ callLocalErrorCallBack("Unable to copy file!");
+ printf(" Copy from '%s' to '%s' failed\n", file, str);
+ }
+
+ return err;
+}
+
+int BLI_link(char *file, char *to) {
+ callLocalErrorCallBack("Linking files is unsupported on Windows");
+
+ return 1;
+}
+
+int BLI_backup(char *file, char *from, char *to) {
+ callLocalErrorCallBack("Backing up files is unsupported on Windows");
+
+ return 1;
+}
+
+int BLI_exists(char *file) {
+ return (GetFileAttributes(file) != 0xFFFFFFFF);
+}
+
+void BLI_recurdir_fileops(char *dirname) {
+ char *lslash;
+ char tmp[MAXPATHLEN];
+
+ // First remove possible slash at the end of the dirname.
+ // This routine otherwise tries to create
+ // blah1/blah2/ (with slash) after creating
+ // blah1/blah2 (without slash)
+
+ strcpy(tmp, dirname);
+ lslash= BLI_last_slash(tmp);
+
+ if (lslash == tmp + strlen(tmp) - 1) {
+ *lslash = 0;
+ }
+
+ if (BLI_exists(tmp)) return;
+
+ lslash= BLI_last_slash(tmp);
+ if (lslash) {
+ /* Split about the last slash and recurse */
+ *lslash = 0;
+ BLI_recurdir_fileops(tmp);
+ }
+
+ if (!CreateDirectory(dirname, NULL))
+ callLocalErrorCallBack("Unable to create directory\n");
+}
+
+int BLI_rename(char *from, char *to) {
+ if (!BLI_exists(from)) return 0;
+
+ if (BLI_exists(to))
+ if(BLI_delete(to, 0, 0)) return 1;
+
+ return rename(from, to);
+}
+
+#else /* The sane UNIX world */
+
+/*
+ * but the sane UNIX world is tied to the interface, and the system
+ * timer, and... We implement a callback mechanism. The system will
+ * have to initialise the callback before the functions will work!
+ * */
+static char str[MAXPATHLEN+12];
+
+int BLI_delete(char *file, int dir, int recursive) {
+ if (recursive) sprintf(str, "/bin/rm -rf %s", file);
+ else if (dir) sprintf(str, "/bin/rmdir \"%s\"", file);
+ else sprintf(str, "/bin/rm -f \"%s\"", file);
+
+ return system(str);
+}
+
+int BLI_touch(char *file)
+{
+
+ if( BLI_exists("/bin/touch") )
+ sprintf(str, "/bin/touch %s", file);
+ else
+ sprintf(str, "/usr/bin/touch %s", file);
+
+ return system(str);
+}
+
+int BLI_move(char *file, char *to) {
+ sprintf(str, "/bin/mv -f %s %s", file, to);
+
+ return system(str);
+}
+
+int BLI_copy_fileops(char *file, char *to) {
+ sprintf(str, "/bin/cp -rf \"%s\" %s", file, to);
+
+ return system(str);
+}
+
+int BLI_link(char *file, char *to) {
+ sprintf(str, "/bin/ln -f %s %s", file, to);
+
+ return system(str);
+}
+
+int BLI_backup(char *file, char *from, char *to) {
+ sprintf(str, "/bin/su root -c 'cd %s; /bin/tar cf - \"%s\" | (/bin/cd %s; /bin/tar xf -)'", from, file, to);
+
+ return system(str);
+}
+
+int BLI_exists(char *file) {
+ return BLI_exist(file);
+}
+
+void BLI_recurdir_fileops(char *dirname) {
+ char *lslash;
+ char tmp[MAXPATHLEN];
+
+ if (BLI_exists(dirname)) return;
+
+ strcpy(tmp, dirname);
+
+ lslash= BLI_last_slash(tmp);
+ if (lslash) {
+ /* Split about the last slash and recurse */
+ *lslash = 0;
+ BLI_recurdir_fileops(tmp);
+ }
+
+ mkdir(dirname, 0777);
+}
+
+int BLI_rename(char *from, char *to) {
+ if (!BLI_exists(from)) return 0;
+
+ if (BLI_exists(to)) if(BLI_delete(to, 0, 0)) return 1;
+
+ return rename(from, to);
+}
+
+#endif
diff --git a/source/blender/blenlib/intern/gsqueue.c b/source/blender/blenlib/intern/gsqueue.c
new file mode 100644
index 00000000000..eb49fe92cb1
--- /dev/null
+++ b/source/blender/blenlib/intern/gsqueue.c
@@ -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 *****
+ */
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_gsqueue.h"
+
+typedef struct _GSQueueElem GSQueueElem;
+struct _GSQueueElem {
+ GSQueueElem *next;
+};
+
+struct _GSQueue {
+ GSQueueElem *head;
+ GSQueueElem *tail;
+ int elem_size;
+};
+
+GSQueue *BLI_gsqueue_new(int elem_size)
+{
+ GSQueue *gq= MEM_mallocN(sizeof(*gq), "gqueue_new");
+ gq->head= gq->tail= NULL;
+ gq->elem_size= elem_size;
+
+ return gq;
+}
+
+int BLI_gsqueue_is_empty(GSQueue *gq)
+{
+ return (gq->head==NULL);
+}
+
+void BLI_gsqueue_peek(GSQueue *gq, void *item_r)
+{
+ memcpy(item_r, &gq->head[1], gq->elem_size);
+}
+void BLI_gsqueue_pop(GSQueue *gq, void *item_r)
+{
+ GSQueueElem *elem= gq->head;
+ if (elem==gq->tail) {
+ gq->head= gq->tail= NULL;
+ } else {
+ gq->head= gq->head->next;
+ }
+
+ if (item_r) memcpy(item_r, &elem[1], gq->elem_size);
+ MEM_freeN(elem);
+}
+void BLI_gsqueue_push(GSQueue *gq, void *item)
+{
+ GSQueueElem *elem= MEM_mallocN(sizeof(*elem)+gq->elem_size, "gqueue_push");
+ memcpy(&elem[1], item, gq->elem_size);
+ elem->next= NULL;
+
+ if (BLI_gsqueue_is_empty(gq)) {
+ gq->tail= gq->head= elem;
+ } else {
+ gq->tail= gq->tail->next= elem;
+ }
+}
+void BLI_gsqueue_pushback(GSQueue *gq, void *item)
+{
+ GSQueueElem *elem= MEM_mallocN(sizeof(*elem)+gq->elem_size, "gqueue_push");
+ memcpy(&elem[1], item, gq->elem_size);
+ elem->next= gq->head;
+
+ if (BLI_gsqueue_is_empty(gq)) {
+ gq->head= gq->tail= elem;
+ } else {
+ gq->head= elem;
+ }
+}
+
+void BLI_gsqueue_free(GSQueue *gq)
+{
+ while (gq->head) {
+ BLI_gsqueue_pop(gq, NULL);
+ }
+ MEM_freeN(gq);
+}
+
+
diff --git a/source/blender/blenlib/intern/matrixops.c b/source/blender/blenlib/intern/matrixops.c
new file mode 100644
index 00000000000..f33596d803a
--- /dev/null
+++ b/source/blender/blenlib/intern/matrixops.c
@@ -0,0 +1,440 @@
+/*
+ *
+ * Some matrix operations.
+ *
+ * Always use
+ * - vector with x components : float x[3], int x[3], 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 <string.h>
+#include "MTC_matrixops.h"
+#include "MTC_vectorops.h"
+/* ------------------------------------------------------------------------- */
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+#ifdef __sun__
+#include <strings.h>
+#endif
+
+#define ABS(x) ((x) < 0 ? -(x) : (x))
+#define SWAP(type, a, b) { type sw_ap; sw_ap=(a); (a)=(b); (b)=sw_ap; }
+
+void MTC_Mat4CpyMat4(float m1[][4], float m2[][4])
+{
+ memcpy(m1, m2, 4*4*sizeof(float));
+}
+
+/* ------------------------------------------------------------------------- */
+
+void MTC_Mat4MulSerie(float answ[][4],
+ float m1[][4], float m2[][4], float m3[][4],
+ float m4[][4], float m5[][4], float m6[][4],
+ float m7[][4], float m8[][4])
+{
+ float temp[4][4];
+
+ if(m1==0 || m2==0) return;
+
+ MTC_Mat4MulMat4(answ, m2, m1);
+ if(m3) {
+ MTC_Mat4MulMat4(temp, m3, answ);
+ if(m4) {
+ MTC_Mat4MulMat4(answ, m4, temp);
+ if(m5) {
+ MTC_Mat4MulMat4(temp, m5, answ);
+ if(m6) {
+ MTC_Mat4MulMat4(answ, m6, temp);
+ if(m7) {
+ MTC_Mat4MulMat4(temp, m7, answ);
+ if(m8) {
+ MTC_Mat4MulMat4(answ, m8, temp);
+ }
+ else MTC_Mat4CpyMat4(answ, temp);
+ }
+ }
+ else MTC_Mat4CpyMat4(answ, temp);
+ }
+ }
+ else MTC_Mat4CpyMat4(answ, temp);
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+void MTC_Mat4MulMat4(float m1[][4], float m2[][4], float m3[][4])
+{
+ /* matrix product: c[j][k] = a[j][i].b[i][k] */
+
+ m1[0][0] = m2[0][0]*m3[0][0] + m2[0][1]*m3[1][0] + m2[0][2]*m3[2][0] + m2[0][3]*m3[3][0];
+ m1[0][1] = m2[0][0]*m3[0][1] + m2[0][1]*m3[1][1] + m2[0][2]*m3[2][1] + m2[0][3]*m3[3][1];
+ m1[0][2] = m2[0][0]*m3[0][2] + m2[0][1]*m3[1][2] + m2[0][2]*m3[2][2] + m2[0][3]*m3[3][2];
+ m1[0][3] = m2[0][0]*m3[0][3] + m2[0][1]*m3[1][3] + m2[0][2]*m3[2][3] + m2[0][3]*m3[3][3];
+
+ m1[1][0] = m2[1][0]*m3[0][0] + m2[1][1]*m3[1][0] + m2[1][2]*m3[2][0] + m2[1][3]*m3[3][0];
+ m1[1][1] = m2[1][0]*m3[0][1] + m2[1][1]*m3[1][1] + m2[1][2]*m3[2][1] + m2[1][3]*m3[3][1];
+ m1[1][2] = m2[1][0]*m3[0][2] + m2[1][1]*m3[1][2] + m2[1][2]*m3[2][2] + m2[1][3]*m3[3][2];
+ m1[1][3] = m2[1][0]*m3[0][3] + m2[1][1]*m3[1][3] + m2[1][2]*m3[2][3] + m2[1][3]*m3[3][3];
+
+ m1[2][0] = m2[2][0]*m3[0][0] + m2[2][1]*m3[1][0] + m2[2][2]*m3[2][0] + m2[2][3]*m3[3][0];
+ m1[2][1] = m2[2][0]*m3[0][1] + m2[2][1]*m3[1][1] + m2[2][2]*m3[2][1] + m2[2][3]*m3[3][1];
+ m1[2][2] = m2[2][0]*m3[0][2] + m2[2][1]*m3[1][2] + m2[2][2]*m3[2][2] + m2[2][3]*m3[3][2];
+ m1[2][3] = m2[2][0]*m3[0][3] + m2[2][1]*m3[1][3] + m2[2][2]*m3[2][3] + m2[2][3]*m3[3][3];
+
+ m1[3][0] = m2[3][0]*m3[0][0] + m2[3][1]*m3[1][0] + m2[3][2]*m3[2][0] + m2[3][3]*m3[3][0];
+ m1[3][1] = m2[3][0]*m3[0][1] + m2[3][1]*m3[1][1] + m2[3][2]*m3[2][1] + m2[3][3]*m3[3][1];
+ m1[3][2] = m2[3][0]*m3[0][2] + m2[3][1]*m3[1][2] + m2[3][2]*m3[2][2] + m2[3][3]*m3[3][2];
+ m1[3][3] = m2[3][0]*m3[0][3] + m2[3][1]*m3[1][3] + m2[3][2]*m3[2][3] + m2[3][3]*m3[3][3];
+
+}
+/* ------------------------------------------------------------------------- */
+
+void MTC_Mat4MulVecfl(float mat[][4], float *vec)
+{
+ float x,y;
+
+ x=vec[0];
+ y=vec[1];
+ vec[0]=x*mat[0][0] + y*mat[1][0] + mat[2][0]*vec[2] + mat[3][0];
+ vec[1]=x*mat[0][1] + y*mat[1][1] + mat[2][1]*vec[2] + mat[3][1];
+ vec[2]=x*mat[0][2] + y*mat[1][2] + mat[2][2]*vec[2] + mat[3][2];
+}
+
+/* ------------------------------------------------------------------------- */
+void MTC_Mat3MulVecfl(float mat[][3], float *vec)
+{
+ float x,y;
+
+ x=vec[0];
+ y=vec[1];
+ vec[0]= x*mat[0][0] + y*mat[1][0] + mat[2][0]*vec[2];
+ vec[1]= x*mat[0][1] + y*mat[1][1] + mat[2][1]*vec[2];
+ vec[2]= x*mat[0][2] + y*mat[1][2] + mat[2][2]*vec[2];
+}
+
+/* ------------------------------------------------------------------------- */
+
+int MTC_Mat4Invert(float inverse[][4], float mat[][4])
+{
+ int i, j, k;
+ double temp;
+ float tempmat[4][4];
+ float max;
+ int maxj;
+
+ /* Set inverse to identity */
+ for (i=0; i<4; i++)
+ for (j=0; j<4; j++)
+ inverse[i][j] = 0;
+ for (i=0; i<4; i++)
+ inverse[i][i] = 1;
+
+ /* Copy original matrix so we don't mess it up */
+ for(i = 0; i < 4; i++)
+ for(j = 0; j <4; j++)
+ tempmat[i][j] = mat[i][j];
+
+ for(i = 0; i < 4; i++) {
+ /* Look for row with max pivot */
+ max = ABS(tempmat[i][i]);
+ maxj = i;
+ for(j = i + 1; j < 4; j++) {
+ if(ABS(tempmat[j][i]) > max) {
+ max = ABS(tempmat[j][i]);
+ maxj = j;
+ }
+ }
+ /* Swap rows if necessary */
+ if (maxj != i) {
+ for( k = 0; k < 4; k++) {
+ SWAP(float, tempmat[i][k], tempmat[maxj][k]);
+ SWAP(float, inverse[i][k], inverse[maxj][k]);
+ }
+ }
+
+ temp = tempmat[i][i];
+ if (temp == 0)
+ return 0; /* No non-zero pivot */
+ for(k = 0; k < 4; k++) {
+ tempmat[i][k] /= temp;
+ inverse[i][k] /= temp;
+ }
+ for(j = 0; j < 4; j++) {
+ if(j != i) {
+ temp = tempmat[j][i];
+ for(k = 0; k < 4; k++) {
+ tempmat[j][k] -= tempmat[i][k]*temp;
+ inverse[j][k] -= inverse[i][k]*temp;
+ }
+ }
+ }
+ }
+ return 1;
+}
+
+/* ------------------------------------------------------------------------- */
+void MTC_Mat3CpyMat4(float m1[][3], float m2[][4])
+{
+
+ m1[0][0]= m2[0][0];
+ m1[0][1]= m2[0][1];
+ m1[0][2]= m2[0][2];
+
+ m1[1][0]= m2[1][0];
+ m1[1][1]= m2[1][1];
+ m1[1][2]= m2[1][2];
+
+ m1[2][0]= m2[2][0];
+ m1[2][1]= m2[2][1];
+ m1[2][2]= m2[2][2];
+}
+
+/* ------------------------------------------------------------------------- */
+
+void MTC_Mat3CpyMat3(float m1[][3], float m2[][3])
+{
+ memcpy(m1, m2, 3*3*sizeof(float));
+}
+
+/* ------------------------------------------------------------------------- */
+/* void Mat3MulMat3(float m1[][3], float m3[][3], float m2[][3]) */
+void MTC_Mat3MulMat3(float m1[][3], float m3[][3], float m2[][3])
+{
+ /* be careful about this rewrite... */
+ /* m1[i][j] = m2[i][k]*m3[k][j], args are flipped! */
+ m1[0][0]= m2[0][0]*m3[0][0] + m2[0][1]*m3[1][0] + m2[0][2]*m3[2][0];
+ m1[0][1]= m2[0][0]*m3[0][1] + m2[0][1]*m3[1][1] + m2[0][2]*m3[2][1];
+ m1[0][2]= m2[0][0]*m3[0][2] + m2[0][1]*m3[1][2] + m2[0][2]*m3[2][2];
+
+ m1[1][0]= m2[1][0]*m3[0][0] + m2[1][1]*m3[1][0] + m2[1][2]*m3[2][0];
+ m1[1][1]= m2[1][0]*m3[0][1] + m2[1][1]*m3[1][1] + m2[1][2]*m3[2][1];
+ m1[1][2]= m2[1][0]*m3[0][2] + m2[1][1]*m3[1][2] + m2[1][2]*m3[2][2];
+
+ m1[2][0]= m2[2][0]*m3[0][0] + m2[2][1]*m3[1][0] + m2[2][2]*m3[2][0];
+ m1[2][1]= m2[2][0]*m3[0][1] + m2[2][1]*m3[1][1] + m2[2][2]*m3[2][1];
+ m1[2][2]= m2[2][0]*m3[0][2] + m2[2][1]*m3[1][2] + m2[2][2]*m3[2][2];
+
+/* m1[0]= m2[0]*m3[0] + m2[1]*m3[3] + m2[2]*m3[6]; */
+/* m1[1]= m2[0]*m3[1] + m2[1]*m3[4] + m2[2]*m3[7]; */
+/* m1[2]= m2[0]*m3[2] + m2[1]*m3[5] + m2[2]*m3[8]; */
+/* m1+=3; */
+/* m2+=3; */
+/* m1[0]= m2[0]*m3[0] + m2[1]*m3[3] + m2[2]*m3[6]; */
+/* m1[1]= m2[0]*m3[1] + m2[1]*m3[4] + m2[2]*m3[7]; */
+/* m1[2]= m2[0]*m3[2] + m2[1]*m3[5] + m2[2]*m3[8]; */
+/* m1+=3; */
+/* m2+=3; */
+/* m1[0]= m2[0]*m3[0] + m2[1]*m3[3] + m2[2]*m3[6]; */
+/* m1[1]= m2[0]*m3[1] + m2[1]*m3[4] + m2[2]*m3[7]; */
+/* m1[2]= m2[0]*m3[2] + m2[1]*m3[5] + m2[2]*m3[8]; */
+} /* end of void Mat3MulMat3(float m1[][3], float m3[][3], float m2[][3]) */
+
+/* ------------------------------------------------------------------------- */
+
+void MTC_Mat4Ortho(float mat[][4])
+{
+ float len;
+
+ len= MTC_normalise3DF(mat[0]);
+ if(len!=0.0) mat[0][3]/= len;
+ len= MTC_normalise3DF(mat[1]);
+ if(len!=0.0) mat[1][3]/= len;
+ len= MTC_normalise3DF(mat[2]);
+ if(len!=0.0) mat[2][3]/= len;
+}
+
+/* ------------------------------------------------------------------------- */
+
+void MTC_Mat4Mul3Vecfl(float mat[][4], float *vec)
+{
+ float x,y;
+ /* vec = mat^T dot vec !!! or vec a row, then vec = vec dot mat*/
+
+ x= vec[0];
+ y= vec[1];
+ vec[0]= x*mat[0][0] + y*mat[1][0] + mat[2][0]*vec[2];
+ vec[1]= x*mat[0][1] + y*mat[1][1] + mat[2][1]*vec[2];
+ vec[2]= x*mat[0][2] + y*mat[1][2] + mat[2][2]*vec[2];
+}
+
+/* ------------------------------------------------------------------------- */
+
+void MTC_Mat4One(float m[][4])
+{
+
+ m[0][0]= m[1][1]= m[2][2]= m[3][3]= 1.0;
+ m[0][1]= m[0][2]= m[0][3]= 0.0;
+ m[1][0]= m[1][2]= m[1][3]= 0.0;
+ m[2][0]= m[2][1]= m[2][3]= 0.0;
+ m[3][0]= m[3][1]= m[3][2]= 0.0;
+}
+
+
+/* ------------------------------------------------------------------------- */
+/* Result is a 3-vector!*/
+void MTC_Mat3MulVecd(float mat[][3], double *vec)
+{
+ double x,y;
+
+ /* vec = mat^T dot vec !!! or vec a row, then vec = vec dot mat*/
+ x=vec[0];
+ y=vec[1];
+ vec[0]= x * mat[0][0] + y * mat[1][0] + mat[2][0] * vec[2];
+ vec[1]= x * mat[0][1] + y * mat[1][1] + mat[2][1] * vec[2];
+ vec[2]= x * mat[0][2] + y * mat[1][2] + mat[2][2] * vec[2];
+}
+
+/* ------------------------------------------------------------------------- */
+
+void MTC_Mat3Inv(float m1[][3], float m2[][3])
+{
+ short a,b;
+ float det;
+
+ /* eerst adjoint */
+ MTC_Mat3Adj(m1,m2);
+
+ /* dan det oude mat! */
+ det= m2[0][0]* (m2[1][1]*m2[2][2] - m2[1][2]*m2[2][1])
+ -m2[1][0]* (m2[0][1]*m2[2][2] - m2[0][2]*m2[2][1])
+ +m2[2][0]* (m2[0][1]*m2[1][2] - m2[0][2]*m2[1][1]);
+
+ if(det==0) det=1;
+ det= 1/det;
+ for(a=0;a<3;a++) {
+ for(b=0;b<3;b++) {
+ m1[a][b]*=det;
+ }
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
+void MTC_Mat3Adj(float m1[][3], float m[][3])
+{
+ m1[0][0]=m[1][1]*m[2][2]-m[1][2]*m[2][1];
+ m1[0][1]= -m[0][1]*m[2][2]+m[0][2]*m[2][1];
+ m1[0][2]=m[0][1]*m[1][2]-m[0][2]*m[1][1];
+
+ m1[1][0]= -m[1][0]*m[2][2]+m[1][2]*m[2][0];
+ m1[1][1]=m[0][0]*m[2][2]-m[0][2]*m[2][0];
+ m1[1][2]= -m[0][0]*m[1][2]+m[0][2]*m[1][0];
+
+ m1[2][0]=m[1][0]*m[2][1]-m[1][1]*m[2][0];
+ m1[2][1]= -m[0][0]*m[2][1]+m[0][1]*m[2][0];
+ m1[2][2]=m[0][0]*m[1][1]-m[0][1]*m[1][0];
+}
+
+/* ------------------------------------------------------------------------- */
+
+void MTC_Mat3One(float m[][3])
+{
+
+ m[0][0]= m[1][1]= m[2][2]= 1.0;
+ m[0][1]= m[0][2]= 0.0;
+ m[1][0]= m[1][2]= 0.0;
+ m[2][0]= m[2][1]= 0.0;
+}
+
+/* ------------------------------------------------------------------------- */
+
+void MTC_Mat4SwapMat4(float m1[][4], float m2[][4])
+{
+ float t;
+ int i, j;
+
+ for(i = 0; i < 4; i++) {
+ for (j = 0; j < 4; j++) {
+ t = m1[i][j];
+ m1[i][j] = m2[i][j];
+ m2[i][j] = t;
+ }
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
+void MTC_Mat4MulVec4fl(float mat[][4], float *vec)
+{
+ float x,y,z;
+
+ x = vec[0];
+ y = vec[1];
+ z = vec[2];
+ vec[0] = x*mat[0][0] + y*mat[1][0] + z*mat[2][0] + mat[3][0]*vec[3];
+ vec[1] = x*mat[0][1] + y*mat[1][1] + z*mat[2][1] + mat[3][1]*vec[3];
+ vec[2] = x*mat[0][2] + y*mat[1][2] + z*mat[2][2] + mat[3][2]*vec[3];
+ vec[3] = x*mat[0][3] + y*mat[1][3] + z*mat[2][3] + mat[3][3]*vec[3];
+}
+
+/* ------------------------------------------------------------------------- */
+
+void MTC_Mat4CpyMat3nc(float m1[][4], float m2[][3]) /* no clear */
+{
+ m1[0][0]= m2[0][0];
+ m1[0][1]= m2[0][1];
+ m1[0][2]= m2[0][2];
+
+ m1[1][0]= m2[1][0];
+ m1[1][1]= m2[1][1];
+ m1[1][2]= m2[1][2];
+
+ m1[2][0]= m2[2][0];
+ m1[2][1]= m2[2][1];
+ m1[2][2]= m2[2][2];
+}
+
+/* ------------------------------------------------------------------------- */
+
+void MTC_Mat4MulMat33(float m1[][3], float m2[][4], float m3[][3])
+{
+ /* m1_i_j = m2_i_k * m3_k_j ? */
+
+ m1[0][0] = m2[0][0]*m3[0][0] + m2[0][1]*m3[1][0] + m2[0][2]*m3[2][0];
+ m1[0][1] = m2[0][0]*m3[0][1] + m2[0][1]*m3[1][1] + m2[0][2]*m3[2][1];
+ m1[0][2] = m2[0][0]*m3[0][2] + m2[0][1]*m3[1][2] + m2[0][2]*m3[2][2];
+
+ m1[1][0] = m2[1][0]*m3[0][0] + m2[1][1]*m3[1][0] + m2[1][2]*m3[2][0];
+ m1[1][1] = m2[1][0]*m3[0][1] + m2[1][1]*m3[1][1] + m2[1][2]*m3[2][1];
+ m1[1][2] = m2[1][0]*m3[0][2] + m2[1][1]*m3[1][2] + m2[1][2]*m3[2][2];
+
+ m1[2][0] = m2[2][0]*m3[0][0] + m2[2][1]*m3[1][0] + m2[2][2]*m3[2][0];
+ m1[2][1] = m2[2][0]*m3[0][1] + m2[2][1]*m3[1][1] + m2[2][2]*m3[2][1];
+ m1[2][2] = m2[2][0]*m3[0][2] + m2[2][1]*m3[1][2] + m2[2][2]*m3[2][2];
+
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* eof */
diff --git a/source/blender/blenlib/intern/noise.c b/source/blender/blenlib/intern/noise.c
new file mode 100644
index 00000000000..124b520ed11
--- /dev/null
+++ b/source/blender/blenlib/intern/noise.c
@@ -0,0 +1,390 @@
+/*
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "BLI_blenlib.h"
+
+#ifdef _WIN32
+#pragma warning (once : 4244) // "conversion from double to float"
+#pragma warning (once : 4305) // "truncation from const double to float"
+#endif
+
+/* local */
+float noise3_perlin(float vec[3]);
+float turbulence_perlin(float *point, float lofreq, float hifreq);
+float turbulencep(float noisesize, float x, float y, float z, int nr);
+
+
+#define HASHVEC(x,y,z) hashvectf+3*hash[ (hash[ (hash[(z) & 255]+(y)) & 255]+(x)) & 255]
+
+
+unsigned char hash[512]= {
+0xA2,0xA0,0x19,0x3B,0xF8,0xEB,0xAA,0xEE,0xF3,0x1C,0x67,0x28,0x1D,0xED,0x0,0xDE,0x95,0x2E,0xDC,0x3F,0x3A,0x82,0x35,0x4D,0x6C,0xBA,0x36,0xD0,0xF6,0xC,0x79,0x32,0xD1,0x59,0xF4,0x8,0x8B,0x63,0x89,0x2F,0xB8,0xB4,0x97,0x83,0xF2,0x8F,0x18,0xC7,0x51,0x14,0x65,0x87,0x48,0x20,0x42,0xA8,0x80,0xB5,0x40,0x13,0xB2,0x22,0x7E,0x57,
+0xBC,0x7F,0x6B,0x9D,0x86,0x4C,0xC8,0xDB,0x7C,0xD5,0x25,0x4E,0x5A,0x55,0x74,0x50,0xCD,0xB3,0x7A,0xBB,0xC3,0xCB,0xB6,0xE2,0xE4,0xEC,0xFD,0x98,0xB,0x96,0xD3,0x9E,0x5C,0xA1,0x64,0xF1,0x81,0x61,0xE1,0xC4,0x24,0x72,0x49,0x8C,0x90,0x4B,0x84,0x34,0x38,0xAB,0x78,0xCA,0x1F,0x1,0xD7,0x93,0x11,0xC1,0x58,0xA9,0x31,0xF9,0x44,0x6D,
+0xBF,0x33,0x9C,0x5F,0x9,0x94,0xA3,0x85,0x6,0xC6,0x9A,0x1E,0x7B,0x46,0x15,0x30,0x27,0x2B,0x1B,0x71,0x3C,0x5B,0xD6,0x6F,0x62,0xAC,0x4F,0xC2,0xC0,0xE,0xB1,0x23,0xA7,0xDF,0x47,0xB0,0x77,0x69,0x5,0xE9,0xE6,0xE7,0x76,0x73,0xF,0xFE,0x6E,0x9B,0x56,0xEF,0x12,0xA5,0x37,0xFC,0xAE,0xD9,0x3,0x8E,0xDD,0x10,0xB9,0xCE,0xC9,0x8D,
+0xDA,0x2A,0xBD,0x68,0x17,0x9F,0xBE,0xD4,0xA,0xCC,0xD2,0xE8,0x43,0x3D,0x70,0xB7,0x2,0x7D,0x99,0xD8,0xD,0x60,0x8A,0x4,0x2C,0x3E,0x92,0xE5,0xAF,0x53,0x7,0xE0,0x29,0xA6,0xC5,0xE3,0xF5,0xF7,0x4A,0x41,0x26,0x6A,0x16,0x5E,0x52,0x2D,0x21,0xAD,0xF0,0x91,0xFF,0xEA,0x54,0xFA,0x66,0x1A,0x45,0x39,0xCF,0x75,0xA4,0x88,0xFB,0x5D,
+0xA2,0xA0,0x19,0x3B,0xF8,0xEB,0xAA,0xEE,0xF3,0x1C,0x67,0x28,0x1D,0xED,0x0,0xDE,0x95,0x2E,0xDC,0x3F,0x3A,0x82,0x35,0x4D,0x6C,0xBA,0x36,0xD0,0xF6,0xC,0x79,0x32,0xD1,0x59,0xF4,0x8,0x8B,0x63,0x89,0x2F,0xB8,0xB4,0x97,0x83,0xF2,0x8F,0x18,0xC7,0x51,0x14,0x65,0x87,0x48,0x20,0x42,0xA8,0x80,0xB5,0x40,0x13,0xB2,0x22,0x7E,0x57,
+0xBC,0x7F,0x6B,0x9D,0x86,0x4C,0xC8,0xDB,0x7C,0xD5,0x25,0x4E,0x5A,0x55,0x74,0x50,0xCD,0xB3,0x7A,0xBB,0xC3,0xCB,0xB6,0xE2,0xE4,0xEC,0xFD,0x98,0xB,0x96,0xD3,0x9E,0x5C,0xA1,0x64,0xF1,0x81,0x61,0xE1,0xC4,0x24,0x72,0x49,0x8C,0x90,0x4B,0x84,0x34,0x38,0xAB,0x78,0xCA,0x1F,0x1,0xD7,0x93,0x11,0xC1,0x58,0xA9,0x31,0xF9,0x44,0x6D,
+0xBF,0x33,0x9C,0x5F,0x9,0x94,0xA3,0x85,0x6,0xC6,0x9A,0x1E,0x7B,0x46,0x15,0x30,0x27,0x2B,0x1B,0x71,0x3C,0x5B,0xD6,0x6F,0x62,0xAC,0x4F,0xC2,0xC0,0xE,0xB1,0x23,0xA7,0xDF,0x47,0xB0,0x77,0x69,0x5,0xE9,0xE6,0xE7,0x76,0x73,0xF,0xFE,0x6E,0x9B,0x56,0xEF,0x12,0xA5,0x37,0xFC,0xAE,0xD9,0x3,0x8E,0xDD,0x10,0xB9,0xCE,0xC9,0x8D,
+0xDA,0x2A,0xBD,0x68,0x17,0x9F,0xBE,0xD4,0xA,0xCC,0xD2,0xE8,0x43,0x3D,0x70,0xB7,0x2,0x7D,0x99,0xD8,0xD,0x60,0x8A,0x4,0x2C,0x3E,0x92,0xE5,0xAF,0x53,0x7,0xE0,0x29,0xA6,0xC5,0xE3,0xF5,0xF7,0x4A,0x41,0x26,0x6A,0x16,0x5E,0x52,0x2D,0x21,0xAD,0xF0,0x91,0xFF,0xEA,0x54,0xFA,0x66,0x1A,0x45,0x39,0xCF,0x75,0xA4,0x88,0xFB,0x5D,
+};
+
+
+float hashvectf[768]= {
+0.33783,0.715698,-0.611206,-0.944031,-0.326599,-0.045624,-0.101074,-0.416443,-0.903503,0.799286,0.49411,-0.341949,-0.854645,0.518036,0.033936,0.42514,-0.437866,-0.792114,-0.358948,0.597046,0.717377,-0.985413,0.144714,0.089294,-0.601776,-0.33728,-0.723907,-0.449921,0.594513,0.666382,0.208313,-0.10791,
+0.972076,0.575317,0.060425,0.815643,0.293365,-0.875702,-0.383453,0.293762,0.465759,0.834686,-0.846008,-0.233398,-0.47934,-0.115814,0.143036,-0.98291,0.204681,-0.949036,-0.239532,0.946716,-0.263947,0.184326,-0.235596,0.573822,0.784332,0.203705,-0.372253,-0.905487,0.756989,-0.651031,0.055298,0.497803,
+0.814697,-0.297363,-0.16214,0.063995,-0.98468,-0.329254,0.834381,0.441925,0.703827,-0.527039,-0.476227,0.956421,0.266113,0.119781,0.480133,0.482849,0.7323,-0.18631,0.961212,-0.203125,-0.748474,-0.656921,-0.090393,-0.085052,-0.165253,0.982544,-0.76947,0.628174,-0.115234,0.383148,0.537659,0.751068,
+0.616486,-0.668488,-0.415924,-0.259979,-0.630005,0.73175,0.570953,-0.087952,0.816223,-0.458008,0.023254,0.888611,-0.196167,0.976563,-0.088287,-0.263885,-0.69812,-0.665527,0.437134,-0.892273,-0.112793,-0.621674,-0.230438,0.748566,0.232422,0.900574,-0.367249,0.22229,-0.796143,0.562744,-0.665497,-0.73764,
+0.11377,0.670135,0.704803,0.232605,0.895599,0.429749,-0.114655,-0.11557,-0.474243,0.872742,0.621826,0.604004,-0.498444,-0.832214,0.012756,0.55426,-0.702484,0.705994,-0.089661,-0.692017,0.649292,0.315399,-0.175995,-0.977997,0.111877,0.096954,-0.04953,0.994019,0.635284,-0.606689,-0.477783,-0.261261,
+-0.607422,-0.750153,0.983276,0.165436,0.075958,-0.29837,0.404083,-0.864655,-0.638672,0.507721,0.578156,0.388214,0.412079,0.824249,0.556183,-0.208832,0.804352,0.778442,0.562012,0.27951,-0.616577,0.781921,-0.091522,0.196289,0.051056,0.979187,-0.121216,0.207153,-0.970734,-0.173401,-0.384735,0.906555,
+0.161499,-0.723236,-0.671387,0.178497,-0.006226,-0.983887,-0.126038,0.15799,0.97934,0.830475,-0.024811,0.556458,-0.510132,-0.76944,0.384247,0.81424,0.200104,-0.544891,-0.112549,-0.393311,-0.912445,0.56189,0.152222,-0.813049,0.198914,-0.254517,-0.946381,-0.41217,0.690979,-0.593811,-0.407257,0.324524,
+0.853668,-0.690186,0.366119,-0.624115,-0.428345,0.844147,-0.322296,-0.21228,-0.297546,-0.930756,-0.273071,0.516113,0.811798,0.928314,0.371643,0.007233,0.785828,-0.479218,-0.390778,-0.704895,0.058929,0.706818,0.173248,0.203583,0.963562,0.422211,-0.904297,-0.062469,-0.363312,-0.182465,0.913605,0.254028,
+-0.552307,-0.793945,-0.28891,-0.765747,-0.574554,0.058319,0.291382,0.954803,0.946136,-0.303925,0.111267,-0.078156,0.443695,-0.892731,0.182098,0.89389,0.409515,-0.680298,-0.213318,0.701141,0.062469,0.848389,-0.525635,-0.72879,-0.641846,0.238342,-0.88089,0.427673,0.202637,-0.532501,-0.21405,0.818878,
+0.948975,-0.305084,0.07962,0.925446,0.374664,0.055817,0.820923,0.565491,0.079102,0.25882,0.099792,-0.960724,-0.294617,0.910522,0.289978,0.137115,0.320038,-0.937408,-0.908386,0.345276,-0.235718,-0.936218,0.138763,0.322754,0.366577,0.925934,-0.090637,0.309296,-0.686829,-0.657684,0.66983,0.024445,
+0.742065,-0.917999,-0.059113,-0.392059,0.365509,0.462158,-0.807922,0.083374,0.996399,-0.014801,0.593842,0.253143,-0.763672,0.974976,-0.165466,0.148285,0.918976,0.137299,0.369537,0.294952,0.694977,0.655731,0.943085,0.152618,-0.295319,0.58783,-0.598236,0.544495,0.203796,0.678223,0.705994,-0.478821,
+-0.661011,0.577667,0.719055,-0.1698,-0.673828,-0.132172,-0.965332,0.225006,-0.981873,-0.14502,0.121979,0.763458,0.579742,0.284546,-0.893188,0.079681,0.442474,-0.795776,-0.523804,0.303802,0.734955,0.67804,-0.007446,0.15506,0.986267,-0.056183,0.258026,0.571503,-0.778931,-0.681549,-0.702087,-0.206116,
+-0.96286,-0.177185,0.203613,-0.470978,-0.515106,0.716095,-0.740326,0.57135,0.354095,-0.56012,-0.824982,-0.074982,-0.507874,0.753204,0.417969,-0.503113,0.038147,0.863342,0.594025,0.673553,-0.439758,-0.119873,-0.005524,-0.992737,0.098267,-0.213776,0.971893,-0.615631,0.643951,0.454163,0.896851,-0.441071,
+0.032166,-0.555023,0.750763,-0.358093,0.398773,0.304688,0.864929,-0.722961,0.303589,0.620544,-0.63559,-0.621948,-0.457306,-0.293243,0.072327,0.953278,-0.491638,0.661041,-0.566772,-0.304199,-0.572083,-0.761688,0.908081,-0.398956,0.127014,-0.523621,-0.549683,-0.650848,-0.932922,-0.19986,0.299408,0.099426,
+0.140869,0.984985,-0.020325,-0.999756,-0.002319,0.952667,0.280853,-0.11615,-0.971893,0.082581,0.220337,0.65921,0.705292,-0.260651,0.733063,-0.175537,0.657043,-0.555206,0.429504,-0.712189,0.400421,-0.89859,0.179352,0.750885,-0.19696,0.630341,0.785675,-0.569336,0.241821,-0.058899,-0.464111,0.883789,
+0.129608,-0.94519,0.299622,-0.357819,0.907654,0.219238,-0.842133,-0.439117,-0.312927,-0.313477,0.84433,0.434479,-0.241211,0.053253,0.968994,0.063873,0.823273,0.563965,0.476288,0.862152,-0.172516,0.620941,-0.298126,0.724915,0.25238,-0.749359,-0.612122,-0.577545,0.386566,0.718994,-0.406342,-0.737976,
+0.538696,0.04718,0.556305,0.82959,-0.802856,0.587463,0.101166,-0.707733,-0.705963,0.026428,0.374908,0.68457,0.625092,0.472137,0.208405,-0.856506,-0.703064,-0.581085,-0.409821,-0.417206,-0.736328,0.532623,-0.447876,-0.20285,-0.870728,0.086945,-0.990417,0.107086,0.183685,0.018341,-0.982788,0.560638,
+-0.428864,0.708282,0.296722,-0.952576,-0.0672,0.135773,0.990265,0.030243,-0.068787,0.654724,0.752686,0.762604,-0.551758,0.337585,-0.819611,-0.407684,0.402466,-0.727844,-0.55072,-0.408539,-0.855774,-0.480011,0.19281,0.693176,-0.079285,0.716339,0.226013,0.650116,-0.725433,0.246704,0.953369,-0.173553,
+-0.970398,-0.239227,-0.03244,0.136383,-0.394318,0.908752,0.813232,0.558167,0.164368,0.40451,0.549042,-0.731323,-0.380249,-0.566711,0.730865,0.022156,0.932739,0.359741,0.00824,0.996552,-0.082306,0.956635,-0.065338,-0.283722,-0.743561,0.008209,0.668579,-0.859589,-0.509674,0.035767,-0.852234,0.363678,
+-0.375977,-0.201965,-0.970795,-0.12915,0.313477,0.947327,0.06546,-0.254028,-0.528259,0.81015,0.628052,0.601105,0.49411,-0.494385,0.868378,0.037933,0.275635,-0.086426,0.957336,-0.197937,0.468903,-0.860748,0.895599,0.399384,0.195801,0.560791,0.825012,-0.069214,0.304199,-0.849487,0.43103,0.096375,
+0.93576,0.339111,-0.051422,0.408966,-0.911072,0.330444,0.942841,-0.042389,-0.452362,-0.786407,0.420563,0.134308,-0.933472,-0.332489,0.80191,-0.566711,-0.188934,-0.987946,-0.105988,0.112518,-0.24408,0.892242,-0.379791,-0.920502,0.229095,-0.316376,0.7789,0.325958,0.535706,-0.912872,0.185211,-0.36377,
+-0.184784,0.565369,-0.803833,-0.018463,0.119537,0.992615,-0.259247,-0.935608,0.239532,-0.82373,-0.449127,-0.345947,-0.433105,0.659515,0.614349,-0.822754,0.378845,-0.423676,0.687195,-0.674835,-0.26889,-0.246582,-0.800842,0.545715,-0.729187,-0.207794,0.651978,0.653534,-0.610443,-0.447388,0.492584,-0.023346,
+0.869934,0.609039,0.009094,-0.79306,0.962494,-0.271088,-0.00885,0.2659,-0.004913,0.963959,0.651245,0.553619,-0.518951,0.280548,-0.84314,0.458618,-0.175293,-0.983215,0.049805,0.035339,-0.979919,0.196045,-0.982941,0.164307,-0.082245,0.233734,-0.97226,-0.005005,-0.747253,-0.611328,0.260437,0.645599,
+0.592773,0.481384,0.117706,-0.949524,-0.29068,-0.535004,-0.791901,-0.294312,-0.627167,-0.214447,0.748718,-0.047974,-0.813477,-0.57959,-0.175537,0.477264,-0.860992,0.738556,-0.414246,-0.53183,0.562561,-0.704071,0.433289,-0.754944,0.64801,-0.100586,0.114716,0.044525,-0.992371,0.966003,0.244873,-0.082764,
+};
+
+
+float BLI_hnoise(float noisesize, float x, float y, float z)
+{
+ register float cn1, cn2, cn3, cn4, cn5, cn6, i, *h;
+ float ox, oy, oz, jx, jy, jz;
+ float n= 0.5;
+ int ix, iy, iz, b00, b01, b10, b11, b20, b21;
+
+ if(noisesize==0.0) return 0.0;
+
+ x= (1.0+x)/noisesize;
+ y= (1.0+y)/noisesize;
+ z= (1.0+z)/noisesize;
+
+ ox= (x- (ix= (int)floor(x)) );
+ oy= (y- (iy= (int)floor(y)) );
+ oz= (z- (iz= (int)floor(z)) );
+
+ jx= ox-1;
+ jy= oy-1;
+ jz= oz-1;
+
+ cn1=ox*ox; cn2=oy*oy; cn3=oz*oz;
+ cn4=jx*jx; cn5=jy*jy; cn6=jz*jz;
+
+ cn1= 1.0-3.0*cn1+2.0*cn1*ox;
+ cn2= 1.0-3.0*cn2+2.0*cn2*oy;
+ cn3= 1.0-3.0*cn3+2.0*cn3*oz;
+ cn4= 1.0-3.0*cn4-2.0*cn4*jx;
+ cn5= 1.0-3.0*cn5-2.0*cn5*jy;
+ cn6= 1.0-3.0*cn6-2.0*cn6*jz;
+
+ b00= hash[ hash[ix & 255]+(iy & 255)];
+ b10= hash[ hash[(ix+1) & 255]+(iy & 255)];
+ b01= hash[ hash[ix & 255]+((iy+1) & 255)];
+ b11= hash[ hash[(ix+1) & 255]+((iy+1) & 255)];
+
+ b20=iz & 255; b21= (iz+1) & 255;
+
+ /* 0 */
+ i= (cn1*cn2*cn3);
+ h=hashvectf+ 3*hash[b20+b00];
+ n+= i*(h[0]*ox+h[1]*oy+h[2]*oz);
+ /* 1 */
+ i= (cn1*cn2*cn6);
+ h=hashvectf+ 3*hash[b21+b00];
+ n+= i*(h[0]*ox+h[1]*oy+h[2]*jz);
+ /* 2 */
+ i= (cn1*cn5*cn3);
+ h=hashvectf+ 3*hash[b20+b01];
+ n+= i*(h[0]*ox+h[1]*jy+h[2]*oz);
+ /* 3 */
+ i= (cn1*cn5*cn6);
+ h=hashvectf+ 3*hash[b21+b01];
+ n+= i*(h[0]*ox+h[1]*jy+h[2]*jz);
+ /* 4 */
+ i= cn4*cn2*cn3;
+ h=hashvectf+ 3*hash[b20+b10];
+ n+= i*(h[0]*jx+h[1]*oy+h[2]*oz);
+ /* 5 */
+ i= cn4*cn2*cn6;
+ h=hashvectf+ 3*hash[b21+b10];
+ n+= i*(h[0]*jx+h[1]*oy+h[2]*jz);
+ /* 6 */
+ i= cn4*cn5*cn3;
+ h=hashvectf+ 3*hash[b20+b11];
+ n+= i*(h[0]*jx+h[1]*jy+h[2]*oz);
+ /* 7 */
+ i= (cn4*cn5*cn6);
+ h=hashvectf+ 3*hash[b21+b11];
+ n+= i*(h[0]*jx+h[1]*jy+h[2]*jz);
+
+ if(n<0.0) n=0.0; else if(n>1.0) n=1.0 ;
+ return n;
+}
+
+
+
+
+float BLI_turbulence(float noisesize, float x, float y, float z, int nr)
+{
+ float s, d= 0.5, div=1.0;
+
+ s= BLI_hnoise(noisesize, x, y, z);
+
+ while(nr>0) {
+
+ s+= d*BLI_hnoise(noisesize*d, x, y, z);
+ div+= d;
+ d*= 0.5;
+
+ nr--;
+ }
+ return s/div;
+}
+
+float BLI_turbulence1(float noisesize, float x, float y, float z, int nr)
+{
+ float s, d= 0.5, div=1.0;
+
+ s= fabs( (-1.0+2.0*BLI_hnoise(noisesize, x, y, z)));
+
+ while(nr>0) {
+
+ s+= fabs(d* (-1.0+2.0*BLI_hnoise(noisesize*d, x, y, z)));
+ div+= d;
+ d*= 0.5;
+
+ nr--;
+ }
+ return s/div;
+}
+
+
+
+
+/* ********************* VAN PERLIN HIMSELF: ******************** */
+
+
+static char p[512+2]= {
+0xA2,0xA0,0x19,0x3B,0xF8,0xEB,0xAA,0xEE,0xF3,0x1C,0x67,0x28,0x1D,0xED,0x0,0xDE,0x95,0x2E,0xDC,0x3F,0x3A,0x82,0x35,0x4D,0x6C,0xBA,0x36,0xD0,0xF6,0xC,0x79,0x32,0xD1,0x59,0xF4,0x8,0x8B,0x63,0x89,0x2F,0xB8,0xB4,0x97,0x83,0xF2,0x8F,0x18,0xC7,0x51,0x14,0x65,0x87,0x48,0x20,0x42,0xA8,0x80,0xB5,0x40,0x13,0xB2,0x22,0x7E,0x57,
+0xBC,0x7F,0x6B,0x9D,0x86,0x4C,0xC8,0xDB,0x7C,0xD5,0x25,0x4E,0x5A,0x55,0x74,0x50,0xCD,0xB3,0x7A,0xBB,0xC3,0xCB,0xB6,0xE2,0xE4,0xEC,0xFD,0x98,0xB,0x96,0xD3,0x9E,0x5C,0xA1,0x64,0xF1,0x81,0x61,0xE1,0xC4,0x24,0x72,0x49,0x8C,0x90,0x4B,0x84,0x34,0x38,0xAB,0x78,0xCA,0x1F,0x1,0xD7,0x93,0x11,0xC1,0x58,0xA9,0x31,0xF9,0x44,0x6D,
+0xBF,0x33,0x9C,0x5F,0x9,0x94,0xA3,0x85,0x6,0xC6,0x9A,0x1E,0x7B,0x46,0x15,0x30,0x27,0x2B,0x1B,0x71,0x3C,0x5B,0xD6,0x6F,0x62,0xAC,0x4F,0xC2,0xC0,0xE,0xB1,0x23,0xA7,0xDF,0x47,0xB0,0x77,0x69,0x5,0xE9,0xE6,0xE7,0x76,0x73,0xF,0xFE,0x6E,0x9B,0x56,0xEF,0x12,0xA5,0x37,0xFC,0xAE,0xD9,0x3,0x8E,0xDD,0x10,0xB9,0xCE,0xC9,0x8D,
+0xDA,0x2A,0xBD,0x68,0x17,0x9F,0xBE,0xD4,0xA,0xCC,0xD2,0xE8,0x43,0x3D,0x70,0xB7,0x2,0x7D,0x99,0xD8,0xD,0x60,0x8A,0x4,0x2C,0x3E,0x92,0xE5,0xAF,0x53,0x7,0xE0,0x29,0xA6,0xC5,0xE3,0xF5,0xF7,0x4A,0x41,0x26,0x6A,0x16,0x5E,0x52,0x2D,0x21,0xAD,0xF0,0x91,0xFF,0xEA,0x54,0xFA,0x66,0x1A,0x45,0x39,0xCF,0x75,0xA4,0x88,0xFB,0x5D,
+0xA2,0xA0,0x19,0x3B,0xF8,0xEB,0xAA,0xEE,0xF3,0x1C,0x67,0x28,0x1D,0xED,0x0,0xDE,0x95,0x2E,0xDC,0x3F,0x3A,0x82,0x35,0x4D,0x6C,0xBA,0x36,0xD0,0xF6,0xC,0x79,0x32,0xD1,0x59,0xF4,0x8,0x8B,0x63,0x89,0x2F,0xB8,0xB4,0x97,0x83,0xF2,0x8F,0x18,0xC7,0x51,0x14,0x65,0x87,0x48,0x20,0x42,0xA8,0x80,0xB5,0x40,0x13,0xB2,0x22,0x7E,0x57,
+0xBC,0x7F,0x6B,0x9D,0x86,0x4C,0xC8,0xDB,0x7C,0xD5,0x25,0x4E,0x5A,0x55,0x74,0x50,0xCD,0xB3,0x7A,0xBB,0xC3,0xCB,0xB6,0xE2,0xE4,0xEC,0xFD,0x98,0xB,0x96,0xD3,0x9E,0x5C,0xA1,0x64,0xF1,0x81,0x61,0xE1,0xC4,0x24,0x72,0x49,0x8C,0x90,0x4B,0x84,0x34,0x38,0xAB,0x78,0xCA,0x1F,0x1,0xD7,0x93,0x11,0xC1,0x58,0xA9,0x31,0xF9,0x44,0x6D,
+0xBF,0x33,0x9C,0x5F,0x9,0x94,0xA3,0x85,0x6,0xC6,0x9A,0x1E,0x7B,0x46,0x15,0x30,0x27,0x2B,0x1B,0x71,0x3C,0x5B,0xD6,0x6F,0x62,0xAC,0x4F,0xC2,0xC0,0xE,0xB1,0x23,0xA7,0xDF,0x47,0xB0,0x77,0x69,0x5,0xE9,0xE6,0xE7,0x76,0x73,0xF,0xFE,0x6E,0x9B,0x56,0xEF,0x12,0xA5,0x37,0xFC,0xAE,0xD9,0x3,0x8E,0xDD,0x10,0xB9,0xCE,0xC9,0x8D,
+0xDA,0x2A,0xBD,0x68,0x17,0x9F,0xBE,0xD4,0xA,0xCC,0xD2,0xE8,0x43,0x3D,0x70,0xB7,0x2,0x7D,0x99,0xD8,0xD,0x60,0x8A,0x4,0x2C,0x3E,0x92,0xE5,0xAF,0x53,0x7,0xE0,0x29,0xA6,0xC5,0xE3,0xF5,0xF7,0x4A,0x41,0x26,0x6A,0x16,0x5E,0x52,0x2D,0x21,0xAD,0xF0,0x91,0xFF,0xEA,0x54,0xFA,0x66,0x1A,0x45,0x39,0xCF,0x75,0xA4,0x88,0xFB,0x5D,
+0xA2,0xA0};
+
+
+float g[512+2][3]= {
+0.33783,0.715698,-0.611206,-0.944031,-0.326599,-0.045624,-0.101074,-0.416443,-0.903503,0.799286,0.49411,-0.341949,-0.854645,0.518036,0.033936,0.42514,-0.437866,-0.792114,-0.358948,0.597046,0.717377,-0.985413,0.144714,0.089294,-0.601776,-0.33728,-0.723907,-0.449921,0.594513,0.666382,0.208313,-0.10791,
+0.972076,0.575317,0.060425,0.815643,0.293365,-0.875702,-0.383453,0.293762,0.465759,0.834686,-0.846008,-0.233398,-0.47934,-0.115814,0.143036,-0.98291,0.204681,-0.949036,-0.239532,0.946716,-0.263947,0.184326,-0.235596,0.573822,0.784332,0.203705,-0.372253,-0.905487,0.756989,-0.651031,0.055298,0.497803,
+0.814697,-0.297363,-0.16214,0.063995,-0.98468,-0.329254,0.834381,0.441925,0.703827,-0.527039,-0.476227,0.956421,0.266113,0.119781,0.480133,0.482849,0.7323,-0.18631,0.961212,-0.203125,-0.748474,-0.656921,-0.090393,-0.085052,-0.165253,0.982544,-0.76947,0.628174,-0.115234,0.383148,0.537659,0.751068,
+0.616486,-0.668488,-0.415924,-0.259979,-0.630005,0.73175,0.570953,-0.087952,0.816223,-0.458008,0.023254,0.888611,-0.196167,0.976563,-0.088287,-0.263885,-0.69812,-0.665527,0.437134,-0.892273,-0.112793,-0.621674,-0.230438,0.748566,0.232422,0.900574,-0.367249,0.22229,-0.796143,0.562744,-0.665497,-0.73764,
+0.11377,0.670135,0.704803,0.232605,0.895599,0.429749,-0.114655,-0.11557,-0.474243,0.872742,0.621826,0.604004,-0.498444,-0.832214,0.012756,0.55426,-0.702484,0.705994,-0.089661,-0.692017,0.649292,0.315399,-0.175995,-0.977997,0.111877,0.096954,-0.04953,0.994019,0.635284,-0.606689,-0.477783,-0.261261,
+-0.607422,-0.750153,0.983276,0.165436,0.075958,-0.29837,0.404083,-0.864655,-0.638672,0.507721,0.578156,0.388214,0.412079,0.824249,0.556183,-0.208832,0.804352,0.778442,0.562012,0.27951,-0.616577,0.781921,-0.091522,0.196289,0.051056,0.979187,-0.121216,0.207153,-0.970734,-0.173401,-0.384735,0.906555,
+0.161499,-0.723236,-0.671387,0.178497,-0.006226,-0.983887,-0.126038,0.15799,0.97934,0.830475,-0.024811,0.556458,-0.510132,-0.76944,0.384247,0.81424,0.200104,-0.544891,-0.112549,-0.393311,-0.912445,0.56189,0.152222,-0.813049,0.198914,-0.254517,-0.946381,-0.41217,0.690979,-0.593811,-0.407257,0.324524,
+0.853668,-0.690186,0.366119,-0.624115,-0.428345,0.844147,-0.322296,-0.21228,-0.297546,-0.930756,-0.273071,0.516113,0.811798,0.928314,0.371643,0.007233,0.785828,-0.479218,-0.390778,-0.704895,0.058929,0.706818,0.173248,0.203583,0.963562,0.422211,-0.904297,-0.062469,-0.363312,-0.182465,0.913605,0.254028,
+-0.552307,-0.793945,-0.28891,-0.765747,-0.574554,0.058319,0.291382,0.954803,0.946136,-0.303925,0.111267,-0.078156,0.443695,-0.892731,0.182098,0.89389,0.409515,-0.680298,-0.213318,0.701141,0.062469,0.848389,-0.525635,-0.72879,-0.641846,0.238342,-0.88089,0.427673,0.202637,-0.532501,-0.21405,0.818878,
+0.948975,-0.305084,0.07962,0.925446,0.374664,0.055817,0.820923,0.565491,0.079102,0.25882,0.099792,-0.960724,-0.294617,0.910522,0.289978,0.137115,0.320038,-0.937408,-0.908386,0.345276,-0.235718,-0.936218,0.138763,0.322754,0.366577,0.925934,-0.090637,0.309296,-0.686829,-0.657684,0.66983,0.024445,
+0.742065,-0.917999,-0.059113,-0.392059,0.365509,0.462158,-0.807922,0.083374,0.996399,-0.014801,0.593842,0.253143,-0.763672,0.974976,-0.165466,0.148285,0.918976,0.137299,0.369537,0.294952,0.694977,0.655731,0.943085,0.152618,-0.295319,0.58783,-0.598236,0.544495,0.203796,0.678223,0.705994,-0.478821,
+-0.661011,0.577667,0.719055,-0.1698,-0.673828,-0.132172,-0.965332,0.225006,-0.981873,-0.14502,0.121979,0.763458,0.579742,0.284546,-0.893188,0.079681,0.442474,-0.795776,-0.523804,0.303802,0.734955,0.67804,-0.007446,0.15506,0.986267,-0.056183,0.258026,0.571503,-0.778931,-0.681549,-0.702087,-0.206116,
+-0.96286,-0.177185,0.203613,-0.470978,-0.515106,0.716095,-0.740326,0.57135,0.354095,-0.56012,-0.824982,-0.074982,-0.507874,0.753204,0.417969,-0.503113,0.038147,0.863342,0.594025,0.673553,-0.439758,-0.119873,-0.005524,-0.992737,0.098267,-0.213776,0.971893,-0.615631,0.643951,0.454163,0.896851,-0.441071,
+0.032166,-0.555023,0.750763,-0.358093,0.398773,0.304688,0.864929,-0.722961,0.303589,0.620544,-0.63559,-0.621948,-0.457306,-0.293243,0.072327,0.953278,-0.491638,0.661041,-0.566772,-0.304199,-0.572083,-0.761688,0.908081,-0.398956,0.127014,-0.523621,-0.549683,-0.650848,-0.932922,-0.19986,0.299408,0.099426,
+0.140869,0.984985,-0.020325,-0.999756,-0.002319,0.952667,0.280853,-0.11615,-0.971893,0.082581,0.220337,0.65921,0.705292,-0.260651,0.733063,-0.175537,0.657043,-0.555206,0.429504,-0.712189,0.400421,-0.89859,0.179352,0.750885,-0.19696,0.630341,0.785675,-0.569336,0.241821,-0.058899,-0.464111,0.883789,
+0.129608,-0.94519,0.299622,-0.357819,0.907654,0.219238,-0.842133,-0.439117,-0.312927,-0.313477,0.84433,0.434479,-0.241211,0.053253,0.968994,0.063873,0.823273,0.563965,0.476288,0.862152,-0.172516,0.620941,-0.298126,0.724915,0.25238,-0.749359,-0.612122,-0.577545,0.386566,0.718994,-0.406342,-0.737976,
+0.538696,0.04718,0.556305,0.82959,-0.802856,0.587463,0.101166,-0.707733,-0.705963,0.026428,0.374908,0.68457,0.625092,0.472137,0.208405,-0.856506,-0.703064,-0.581085,-0.409821,-0.417206,-0.736328,0.532623,-0.447876,-0.20285,-0.870728,0.086945,-0.990417,0.107086,0.183685,0.018341,-0.982788,0.560638,
+-0.428864,0.708282,0.296722,-0.952576,-0.0672,0.135773,0.990265,0.030243,-0.068787,0.654724,0.752686,0.762604,-0.551758,0.337585,-0.819611,-0.407684,0.402466,-0.727844,-0.55072,-0.408539,-0.855774,-0.480011,0.19281,0.693176,-0.079285,0.716339,0.226013,0.650116,-0.725433,0.246704,0.953369,-0.173553,
+-0.970398,-0.239227,-0.03244,0.136383,-0.394318,0.908752,0.813232,0.558167,0.164368,0.40451,0.549042,-0.731323,-0.380249,-0.566711,0.730865,0.022156,0.932739,0.359741,0.00824,0.996552,-0.082306,0.956635,-0.065338,-0.283722,-0.743561,0.008209,0.668579,-0.859589,-0.509674,0.035767,-0.852234,0.363678,
+-0.375977,-0.201965,-0.970795,-0.12915,0.313477,0.947327,0.06546,-0.254028,-0.528259,0.81015,0.628052,0.601105,0.49411,-0.494385,0.868378,0.037933,0.275635,-0.086426,0.957336,-0.197937,0.468903,-0.860748,0.895599,0.399384,0.195801,0.560791,0.825012,-0.069214,0.304199,-0.849487,0.43103,0.096375,
+0.93576,0.339111,-0.051422,0.408966,-0.911072,0.330444,0.942841,-0.042389,-0.452362,-0.786407,0.420563,0.134308,-0.933472,-0.332489,0.80191,-0.566711,-0.188934,-0.987946,-0.105988,0.112518,-0.24408,0.892242,-0.379791,-0.920502,0.229095,-0.316376,0.7789,0.325958,0.535706,-0.912872,0.185211,-0.36377,
+-0.184784,0.565369,-0.803833,-0.018463,0.119537,0.992615,-0.259247,-0.935608,0.239532,-0.82373,-0.449127,-0.345947,-0.433105,0.659515,0.614349,-0.822754,0.378845,-0.423676,0.687195,-0.674835,-0.26889,-0.246582,-0.800842,0.545715,-0.729187,-0.207794,0.651978,0.653534,-0.610443,-0.447388,0.492584,-0.023346,
+0.869934,0.609039,0.009094,-0.79306,0.962494,-0.271088,-0.00885,0.2659,-0.004913,0.963959,0.651245,0.553619,-0.518951,0.280548,-0.84314,0.458618,-0.175293,-0.983215,0.049805,0.035339,-0.979919,0.196045,-0.982941,0.164307,-0.082245,0.233734,-0.97226,-0.005005,-0.747253,-0.611328,0.260437,0.645599,
+0.592773,0.481384,0.117706,-0.949524,-0.29068,-0.535004,-0.791901,-0.294312,-0.627167,-0.214447,0.748718,-0.047974,-0.813477,-0.57959,-0.175537,0.477264,-0.860992,0.738556,-0.414246,-0.53183,0.562561,-0.704071,0.433289,-0.754944,0.64801,-0.100586,0.114716,0.044525,-0.992371,0.966003,0.244873,-0.082764,
+0.33783,0.715698,-0.611206,-0.944031,-0.326599,-0.045624,-0.101074,-0.416443,-0.903503,0.799286,0.49411,-0.341949,-0.854645,0.518036,0.033936,0.42514,-0.437866,-0.792114,-0.358948,0.597046,0.717377,-0.985413,0.144714,0.089294,-0.601776,-0.33728,-0.723907,-0.449921,0.594513,0.666382,0.208313,-0.10791,
+0.972076,0.575317,0.060425,0.815643,0.293365,-0.875702,-0.383453,0.293762,0.465759,0.834686,-0.846008,-0.233398,-0.47934,-0.115814,0.143036,-0.98291,0.204681,-0.949036,-0.239532,0.946716,-0.263947,0.184326,-0.235596,0.573822,0.784332,0.203705,-0.372253,-0.905487,0.756989,-0.651031,0.055298,0.497803,
+0.814697,-0.297363,-0.16214,0.063995,-0.98468,-0.329254,0.834381,0.441925,0.703827,-0.527039,-0.476227,0.956421,0.266113,0.119781,0.480133,0.482849,0.7323,-0.18631,0.961212,-0.203125,-0.748474,-0.656921,-0.090393,-0.085052,-0.165253,0.982544,-0.76947,0.628174,-0.115234,0.383148,0.537659,0.751068,
+0.616486,-0.668488,-0.415924,-0.259979,-0.630005,0.73175,0.570953,-0.087952,0.816223,-0.458008,0.023254,0.888611,-0.196167,0.976563,-0.088287,-0.263885,-0.69812,-0.665527,0.437134,-0.892273,-0.112793,-0.621674,-0.230438,0.748566,0.232422,0.900574,-0.367249,0.22229,-0.796143,0.562744,-0.665497,-0.73764,
+0.11377,0.670135,0.704803,0.232605,0.895599,0.429749,-0.114655,-0.11557,-0.474243,0.872742,0.621826,0.604004,-0.498444,-0.832214,0.012756,0.55426,-0.702484,0.705994,-0.089661,-0.692017,0.649292,0.315399,-0.175995,-0.977997,0.111877,0.096954,-0.04953,0.994019,0.635284,-0.606689,-0.477783,-0.261261,
+-0.607422,-0.750153,0.983276,0.165436,0.075958,-0.29837,0.404083,-0.864655,-0.638672,0.507721,0.578156,0.388214,0.412079,0.824249,0.556183,-0.208832,0.804352,0.778442,0.562012,0.27951,-0.616577,0.781921,-0.091522,0.196289,0.051056,0.979187,-0.121216,0.207153,-0.970734,-0.173401,-0.384735,0.906555,
+0.161499,-0.723236,-0.671387,0.178497,-0.006226,-0.983887,-0.126038,0.15799,0.97934,0.830475,-0.024811,0.556458,-0.510132,-0.76944,0.384247,0.81424,0.200104,-0.544891,-0.112549,-0.393311,-0.912445,0.56189,0.152222,-0.813049,0.198914,-0.254517,-0.946381,-0.41217,0.690979,-0.593811,-0.407257,0.324524,
+0.853668,-0.690186,0.366119,-0.624115,-0.428345,0.844147,-0.322296,-0.21228,-0.297546,-0.930756,-0.273071,0.516113,0.811798,0.928314,0.371643,0.007233,0.785828,-0.479218,-0.390778,-0.704895,0.058929,0.706818,0.173248,0.203583,0.963562,0.422211,-0.904297,-0.062469,-0.363312,-0.182465,0.913605,0.254028,
+-0.552307,-0.793945,-0.28891,-0.765747,-0.574554,0.058319,0.291382,0.954803,0.946136,-0.303925,0.111267,-0.078156,0.443695,-0.892731,0.182098,0.89389,0.409515,-0.680298,-0.213318,0.701141,0.062469,0.848389,-0.525635,-0.72879,-0.641846,0.238342,-0.88089,0.427673,0.202637,-0.532501,-0.21405,0.818878,
+0.948975,-0.305084,0.07962,0.925446,0.374664,0.055817,0.820923,0.565491,0.079102,0.25882,0.099792,-0.960724,-0.294617,0.910522,0.289978,0.137115,0.320038,-0.937408,-0.908386,0.345276,-0.235718,-0.936218,0.138763,0.322754,0.366577,0.925934,-0.090637,0.309296,-0.686829,-0.657684,0.66983,0.024445,
+0.742065,-0.917999,-0.059113,-0.392059,0.365509,0.462158,-0.807922,0.083374,0.996399,-0.014801,0.593842,0.253143,-0.763672,0.974976,-0.165466,0.148285,0.918976,0.137299,0.369537,0.294952,0.694977,0.655731,0.943085,0.152618,-0.295319,0.58783,-0.598236,0.544495,0.203796,0.678223,0.705994,-0.478821,
+-0.661011,0.577667,0.719055,-0.1698,-0.673828,-0.132172,-0.965332,0.225006,-0.981873,-0.14502,0.121979,0.763458,0.579742,0.284546,-0.893188,0.079681,0.442474,-0.795776,-0.523804,0.303802,0.734955,0.67804,-0.007446,0.15506,0.986267,-0.056183,0.258026,0.571503,-0.778931,-0.681549,-0.702087,-0.206116,
+-0.96286,-0.177185,0.203613,-0.470978,-0.515106,0.716095,-0.740326,0.57135,0.354095,-0.56012,-0.824982,-0.074982,-0.507874,0.753204,0.417969,-0.503113,0.038147,0.863342,0.594025,0.673553,-0.439758,-0.119873,-0.005524,-0.992737,0.098267,-0.213776,0.971893,-0.615631,0.643951,0.454163,0.896851,-0.441071,
+0.032166,-0.555023,0.750763,-0.358093,0.398773,0.304688,0.864929,-0.722961,0.303589,0.620544,-0.63559,-0.621948,-0.457306,-0.293243,0.072327,0.953278,-0.491638,0.661041,-0.566772,-0.304199,-0.572083,-0.761688,0.908081,-0.398956,0.127014,-0.523621,-0.549683,-0.650848,-0.932922,-0.19986,0.299408,0.099426,
+0.140869,0.984985,-0.020325,-0.999756,-0.002319,0.952667,0.280853,-0.11615,-0.971893,0.082581,0.220337,0.65921,0.705292,-0.260651,0.733063,-0.175537,0.657043,-0.555206,0.429504,-0.712189,0.400421,-0.89859,0.179352,0.750885,-0.19696,0.630341,0.785675,-0.569336,0.241821,-0.058899,-0.464111,0.883789,
+0.129608,-0.94519,0.299622,-0.357819,0.907654,0.219238,-0.842133,-0.439117,-0.312927,-0.313477,0.84433,0.434479,-0.241211,0.053253,0.968994,0.063873,0.823273,0.563965,0.476288,0.862152,-0.172516,0.620941,-0.298126,0.724915,0.25238,-0.749359,-0.612122,-0.577545,0.386566,0.718994,-0.406342,-0.737976,
+0.538696,0.04718,0.556305,0.82959,-0.802856,0.587463,0.101166,-0.707733,-0.705963,0.026428,0.374908,0.68457,0.625092,0.472137,0.208405,-0.856506,-0.703064,-0.581085,-0.409821,-0.417206,-0.736328,0.532623,-0.447876,-0.20285,-0.870728,0.086945,-0.990417,0.107086,0.183685,0.018341,-0.982788,0.560638,
+-0.428864,0.708282,0.296722,-0.952576,-0.0672,0.135773,0.990265,0.030243,-0.068787,0.654724,0.752686,0.762604,-0.551758,0.337585,-0.819611,-0.407684,0.402466,-0.727844,-0.55072,-0.408539,-0.855774,-0.480011,0.19281,0.693176,-0.079285,0.716339,0.226013,0.650116,-0.725433,0.246704,0.953369,-0.173553,
+-0.970398,-0.239227,-0.03244,0.136383,-0.394318,0.908752,0.813232,0.558167,0.164368,0.40451,0.549042,-0.731323,-0.380249,-0.566711,0.730865,0.022156,0.932739,0.359741,0.00824,0.996552,-0.082306,0.956635,-0.065338,-0.283722,-0.743561,0.008209,0.668579,-0.859589,-0.509674,0.035767,-0.852234,0.363678,
+-0.375977,-0.201965,-0.970795,-0.12915,0.313477,0.947327,0.06546,-0.254028,-0.528259,0.81015,0.628052,0.601105,0.49411,-0.494385,0.868378,0.037933,0.275635,-0.086426,0.957336,-0.197937,0.468903,-0.860748,0.895599,0.399384,0.195801,0.560791,0.825012,-0.069214,0.304199,-0.849487,0.43103,0.096375,
+0.93576,0.339111,-0.051422,0.408966,-0.911072,0.330444,0.942841,-0.042389,-0.452362,-0.786407,0.420563,0.134308,-0.933472,-0.332489,0.80191,-0.566711,-0.188934,-0.987946,-0.105988,0.112518,-0.24408,0.892242,-0.379791,-0.920502,0.229095,-0.316376,0.7789,0.325958,0.535706,-0.912872,0.185211,-0.36377,
+-0.184784,0.565369,-0.803833,-0.018463,0.119537,0.992615,-0.259247,-0.935608,0.239532,-0.82373,-0.449127,-0.345947,-0.433105,0.659515,0.614349,-0.822754,0.378845,-0.423676,0.687195,-0.674835,-0.26889,-0.246582,-0.800842,0.545715,-0.729187,-0.207794,0.651978,0.653534,-0.610443,-0.447388,0.492584,-0.023346,
+0.869934,0.609039,0.009094,-0.79306,0.962494,-0.271088,-0.00885,0.2659,-0.004913,0.963959,0.651245,0.553619,-0.518951,0.280548,-0.84314,0.458618,-0.175293,-0.983215,0.049805,0.035339,-0.979919,0.196045,-0.982941,0.164307,-0.082245,0.233734,-0.97226,-0.005005,-0.747253,-0.611328,0.260437,0.645599,
+0.592773,0.481384,0.117706,-0.949524,-0.29068,-0.535004,-0.791901,-0.294312,-0.627167,-0.214447,0.748718,-0.047974,-0.813477,-0.57959,-0.175537,0.477264,-0.860992,0.738556,-0.414246,-0.53183,0.562561,-0.704071,0.433289,-0.754944,0.64801,-0.100586,0.114716,0.044525,-0.992371,0.966003,0.244873,-0.082764,
+0.33783,0.715698,-0.611206,-0.944031,-0.326599,-0.045624};
+
+
+
+#define DOT(a,b) (a[0] * b[0] + a[1] * b[1] + a[2] * b[2])
+
+#define setup(i,b0,b1,r0,r1) \
+ t = vec[i] + 10000.; \
+ b0 = ((int)t) & 255; \
+ b1 = (b0+1) & 255; \
+ r0 = t - (int)t; \
+ r1 = r0 - 1.;
+
+
+float noise3_perlin(float vec[3])
+{
+ int bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11;
+ float rx0, rx1, ry0, ry1, rz0, rz1, *q, sx, sy, sz, a, b, c, d, t, u, v;
+ register int i, j;
+
+
+ setup(0, bx0,bx1, rx0,rx1);
+ setup(1, by0,by1, ry0,ry1);
+ setup(2, bz0,bz1, rz0,rz1);
+
+ i = p[ bx0 ];
+ j = p[ bx1 ];
+
+ b00 = p[ i + by0 ];
+ b10 = p[ j + by0 ];
+ b01 = p[ i + by1 ];
+ b11 = p[ j + by1 ];
+
+#define at(rx,ry,rz) ( rx * q[0] + ry * q[1] + rz * q[2] )
+
+#define surve(t) ( t * t * (3. - 2. * t) )
+
+#define lerp(t, a, b) ( a + t * (b - a) )
+
+ sx = surve(rx0);
+ sy = surve(ry0);
+ sz = surve(rz0);
+
+
+ q = g[ b00 + bz0 ] ;
+ u = at(rx0,ry0,rz0);
+ q = g[ b10 + bz0 ] ;
+ v = at(rx1,ry0,rz0);
+ a = lerp(sx, u, v);
+
+ q = g[ b01 + bz0 ] ;
+ u = at(rx0,ry1,rz0);
+ q = g[ b11 + bz0 ] ;
+ v = at(rx1,ry1,rz0);
+ b = lerp(sx, u, v);
+
+ c = lerp(sy, a, b); /* interpolate in y at lo x */
+
+ q = g[ b00 + bz1 ] ;
+ u = at(rx0,ry0,rz1);
+ q = g[ b10 + bz1 ] ;
+ v = at(rx1,ry0,rz1);
+ a = lerp(sx, u, v);
+
+ q = g[ b01 + bz1 ] ;
+ u = at(rx0,ry1,rz1);
+ q = g[ b11 + bz1 ] ;
+ v = at(rx1,ry1,rz1);
+ b = lerp(sx, u, v);
+
+ d = lerp(sy, a, b); /* interpolate in y at hi x */
+
+ return 1.5 * lerp(sz, c, d); /* interpolate in z */
+}
+
+
+float turbulence_perlin(float *point, float lofreq, float hifreq)
+{
+ float freq, t, p[3];
+
+ p[0] = point[0] + 123.456;
+ p[1] = point[1];
+ p[2] = point[2];
+
+ t = 0;
+ for (freq = lofreq ; freq < hifreq ; freq *= 2.) {
+ t += fabs(noise3_perlin(p)) / freq;
+ p[0] *= 2.;
+ p[1] *= 2.;
+ p[2] *= 2.;
+ }
+ return t - 0.3; /* readjust to make mean value = 0.0 */
+}
+
+
+
+/* *************** AANROEPEN ALS: *************** */
+
+float BLI_hnoisep(float noisesize, float x, float y, float z)
+{
+ float vec[3];
+
+ vec[0]= x/noisesize;
+ vec[1]= y/noisesize;
+ vec[2]= z/noisesize;
+
+ return noise3_perlin(vec);
+}
+
+float turbulencep(float noisesize, float x, float y, float z, int nr)
+{
+ float vec[3];
+
+ vec[0]= x/noisesize;
+ vec[1]= y/noisesize;
+ vec[2]= z/noisesize;
+ nr++;
+ return turbulence_perlin(vec, 1.0, (float)(1<<nr));
+}
+
diff --git a/source/blender/blenlib/intern/psfont.c b/source/blender/blenlib/intern/psfont.c
new file mode 100644
index 00000000000..ea2525c1f90
--- /dev/null
+++ b/source/blender/blenlib/intern/psfont.c
@@ -0,0 +1,2124 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * fromtype1 - Convert an Adobe type 1 font into .of or .sf format.
+ * Paul Haeberli - 1990
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_vfontdata.h"
+#include "BLI_blenlib.h"
+
+#include "DNA_packedFile_types.h"
+#include "DNA_curve_types.h"
+
+ /* ObjFnt types */
+
+typedef struct chardesc {
+ short movex, movey; /* advance */
+ short llx, lly; /* bounding box */
+ short urx, ury;
+ short *data; /* char data */
+ long datalen;
+} chardesc;
+
+typedef struct objfnt {
+ struct objfnt *freeaddr; /* if freeaddr != 0, objfnt is one chunck */
+ short type;
+ short charmin, charmax;
+ short my_nchars;
+ short scale;
+ chardesc *my_chars;
+} objfnt;
+
+#define OFMAGIC 0x93339333
+
+#define TM_TYPE 1
+#define PO_TYPE 2
+#define SP_TYPE 3
+
+/* ops for tmesh characters */
+
+#define TM_BGNTMESH (1)
+#define TM_SWAPTMESH (2)
+#define TM_ENDBGNTMESH (3)
+#define TM_RETENDTMESH (4)
+#define TM_RET (5)
+
+/* ops for poly characters */
+
+#define PO_BGNLOOP (1)
+#define PO_ENDBGNLOOP (2)
+#define PO_RETENDLOOP (3)
+#define PO_RET (4)
+
+/* ops for spline characters */
+
+#define SP_MOVETO (1)
+#define SP_LINETO (2)
+#define SP_CURVETO (3)
+#define SP_CLOSEPATH (4)
+#define SP_RETCLOSEPATH (5)
+#define SP_RET (6)
+
+
+#define MIN_ASCII ' '
+#define MAX_ASCII '~'
+#define NASCII (256 - 32)
+
+#define NOBBOX (30000)
+
+typedef struct pschar {
+ char *name;
+ int code;
+ int prog;
+} pschar;
+
+ /***/
+
+#define SKIP 4
+#define LINELEN 2048
+#define NOTHEX (100)
+#define MC1 52845
+#define MC2 22719
+#define MAXSUBRS 1000
+#define MAXCHARS 1000
+#define MAXTRIES 30
+
+/* some local thingies */
+static void rcurveto( int dx1, int dy1, int dx2, int dy2, int dx3, int dy3);
+static void makeobjfont(int savesplines);
+static void drawchar(int c);
+static void runprog(void);
+static int chartoindex(objfnt *fnt, int c);
+static short STDtoISO(short c);
+static char * newfgets(char * s, int n, PackedFile * pf);
+static int readfontmatrix(PackedFile * pf, float mat[2][2]);
+static char mdecrypt(char cipher);
+static void decryptall(void);
+static int decodetype1(PackedFile * pf, char *outname);
+static void fakefopen(void);
+static char *fakefread(int n);
+static void setcharlist(void);
+static void initpcstack(void);
+static char *poppc(void);
+static void initstack(void);
+static void push(int val);
+static int pop(void);
+static void initretstack(void);
+static void retpush(int val);
+static int retpop(void);
+static void subr1(void);
+static void subr2(void);
+static void subr0(void);
+static void append_poly_offset(short ofsx, short ofsy, short * data);
+static void append_spline_offset(short ofsx, short ofsy, short * data);
+static void setwidth(int w, int x);
+static void poly_beginchar(void);
+static void poly_endchar(void);
+static void poly_close(void);
+static void poly_pnt(float x, float y);
+static void spline_beginchar(void);
+static void spline_endchar(void);
+static void spline_close(void);
+static void spline_line(float x0, float y0, float x1, float y1);
+static void spline_curveto(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3);
+static void savestart(int x, int y);
+static void sbpoint( int x, int y);
+static void rmoveto( int x, int y);
+static void drawline(float x0, float y0, float x1, float y1, float dx0, float dy0, float dx1, float dy1);
+static void rlineto( int x, int y);
+static void closepath(void);
+static void bezadapt( float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, float beztol);
+static void drawbez( float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3);
+static int docommand(int cmd);
+
+/* some local vars */
+static int startx, starty;
+static int curx, cury;
+static int nextx, nexty;
+static int delx, dely;
+static int started;
+
+
+/* postscript commands */
+#define HSTEM (1)
+#define VSTEM (3)
+#define VMOVETO (4)
+#define RLINETO (5)
+#define HLINETO (6)
+#define VLINETO (7)
+#define RRCURVETO (8)
+#define CLOSEPATH (9)
+#define CALLSUBR (10)
+#define RETURN (11)
+#define HSBW (13)
+#define ENDCHAR (14)
+#define RMOVETO (21)
+#define HMOVETO (22)
+#define VHCURVETO (30)
+#define HVCURVETO (31)
+#define DOTSECTION (256+0)
+#define VSTEM3 (256+1)
+#define HSTEM3 (256+2)
+#define SEAC (256+6)
+#define SBW (256+7)
+#define DIV (256+12)
+#define CALLOTHERSUBR (256+16)
+#define POP (256+17)
+#define SETCURRENTPOINT (256+33)
+#define WHAT0 (0)
+
+/* some dirt for windows */
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+static char oneline[LINELEN];
+static objfnt *fnt;
+
+static unsigned short int mr;
+
+static char *bindat;
+static int datbytes;
+static int firsted;
+static short chardata[2000];
+static int nshorts;
+
+static int thecharwidth, thesidebearing;
+static int npnts, nloops;
+static int nvertpos;
+
+static int fakepos;
+static int fakemax;
+
+static float beztol = 100.0;
+
+/* extern: uit de libfm */
+
+static char *my_subrs[MAXSUBRS];
+static unsigned int my_sublen[MAXSUBRS];
+static char *my_chars[MAXCHARS];
+static unsigned int my_charlen[MAXCHARS];
+static char *my_charname[MAXCHARS];
+static int my_nsubrs, my_nchars;
+
+static short sidebearing[MAXCHARS];
+static char tok[LINELEN];
+static int sp_npnts, sp_nloops;
+
+/*
+ * interpreter globals
+ */
+
+
+static float mat[2][2];
+static char *pcstack[100];
+static char *pc;
+static int pcsp;
+static int coordpos;
+static int coordsave[7][2];
+static int incusp;
+static int retstack[1000];
+static int retsp;
+static int stack[1000];
+static int sp;
+static int savesplines = 1;
+
+static pschar ISOcharlist[NASCII] = {
+ "/space", 040, 0,
+ "/exclam", 041, 0,
+ "/quotedbl", 042, 0,
+ "/numbersign", 043, 0,
+ "/dollar", 044, 0,
+ "/percent", 045, 0,
+ "/ampersand", 046, 0,
+ "/quoteright", 047, 0,
+
+ "/parenleft", 050, 0,
+ "/parenright", 051, 0,
+ "/asterisk", 052, 0,
+ "/plus", 053, 0,
+ "/comma", 054, 0,
+ "/hyphen", 055, 0,
+ "/period", 056, 0,
+ "/slash", 057, 0,
+
+ "/zero", 060, 0,
+ "/one", 061, 0,
+ "/two", 062, 0,
+ "/three", 063, 0,
+ "/four", 064, 0,
+ "/five", 065, 0,
+ "/six", 066, 0,
+ "/seven", 067, 0,
+
+ "/eight", 070, 0,
+ "/nine", 071, 0,
+ "/colon", 072, 0,
+ "/semicolon", 073, 0,
+ "/less", 074, 0,
+ "/equal", 075, 0,
+ "/greater", 076, 0,
+ "/question", 077, 0,
+
+ "/at", 0100, 0,
+ "/A", 0101, 0,
+ "/B", 0102, 0,
+ "/C", 0103, 0,
+ "/D", 0104, 0,
+ "/E", 0105, 0,
+ "/F", 0106, 0,
+ "/G", 0107, 0,
+
+ "/H", 0110, 0,
+ "/I", 0111, 0,
+ "/J", 0112, 0,
+ "/K", 0113, 0,
+ "/L", 0114, 0,
+ "/M", 0115, 0,
+ "/N", 0116, 0,
+ "/O", 0117, 0,
+
+ "/P", 0120, 0,
+ "/Q", 0121, 0,
+ "/R", 0122, 0,
+ "/S", 0123, 0,
+ "/T", 0124, 0,
+ "/U", 0125, 0,
+ "/V", 0126, 0,
+ "/W", 0127, 0,
+
+ "/X", 0130, 0,
+ "/Y", 0131, 0,
+ "/Z", 0132, 0,
+ "/bracketleft", 0133, 0,
+ "/backslash", 0134, 0,
+ "/bracketright", 0135, 0,
+ "/asciicircum", 0136, 0,
+ "/underscore", 0137, 0,
+
+ "/quoteleft", 0140, 0,
+ "/a", 0141, 0,
+ "/b", 0142, 0,
+ "/c", 0143, 0,
+ "/d", 0144, 0,
+ "/e", 0145, 0,
+ "/f", 0146, 0,
+ "/g", 0147, 0,
+
+ "/h", 0150, 0,
+ "/i", 0151, 0,
+ "/j", 0152, 0,
+ "/k", 0153, 0,
+ "/l", 0154, 0,
+ "/m", 0155, 0,
+ "/n", 0156, 0,
+ "/o", 0157, 0,
+
+ "/p", 0160, 0,
+ "/q", 0161, 0,
+ "/r", 0162, 0,
+ "/s", 0163, 0,
+ "/t", 0164, 0,
+ "/u", 0165, 0,
+ "/v", 0166, 0,
+ "/w", 0167, 0,
+
+ "/x", 0170, 0,
+ "/y", 0171, 0,
+ "/z", 0172, 0,
+ "/braceleft", 0173, 0,
+ "/bar", 0174, 0,
+ "/braceright", 0175, 0,
+ "/asciitilde", 0176, 0,
+ "/", 0177, 0,
+
+
+ /* nonstandard defs */
+
+ "/quotedblleft", 0200, 0,
+ "/quotedblright", 0201, 0,
+ "/quotedblbase", 0202, 0,
+ "/quotesinglbase", 0203, 0,
+ "/guilsinglleft", 0204, 0,
+ "/guilsinglright", 0205, 0,
+ "/endash", 0206, 0,
+ "/dagger", 0207, 0,
+
+ "/daggerdbl", 0210, 0,
+ "/trademark", 0211, 0,
+ "/bullet", 0212, 0,
+ "/perthousand", 0213, 0,
+ "/Lslash", 0214, 0,
+ "/OE", 0215, 0,
+ "/lslash", 0216, 0,
+ "/oe", 0217, 0,
+
+ /* endnonstandard defs */
+
+ "/dotlessi", 0220, 0,
+ "/grave", 0221, 0,
+ "/acute", 0222, 0,
+ "/circumflex", 0223, 0,
+ "/tilde", 0224, 0,
+ "/", 0225, 0,
+ "/breve", 0226, 0,
+ "/dotaccent", 0227, 0,
+
+ "/", 0230, 0,
+ "/", 0231, 0,
+ "/ring", 0232, 0,
+ "/", 0233, 0,
+ "/", 0234, 0,
+ "/hungarumlaut", 0235, 0,
+ "/ogonek", 0236, 0,
+ "/caron", 0237, 0,
+
+ "/", 0240, 0,
+ "/exclamdown", 0241, 0,
+ "/cent", 0242, 0,
+ "/sterling", 0243, 0,
+ "/florin", 0244, 0,
+ "/yen", 0245, 0,
+ "/brokenbar", 0246, 0,
+ "/section", 0247, 0,
+
+ "/dieresis", 0250, 0,
+ "/copyright", 0251, 0,
+ "/ordfeminine", 0252, 0,
+ "/guillemotleft", 0253, 0,
+ "/logicalnot", 0254, 0,
+ "/hyphen", 0255, 0,
+ "/registered", 0256, 0,
+ "/macron", 0257, 0,
+
+ "/degree", 0260, 0,
+ "/plusminus", 0261, 0,
+ "/twosuperior", 0262, 0,
+ "/threesuperior", 0263, 0,
+ "/acute", 0264, 0,
+ "/mu", 0265, 0,
+ "/paragraph", 0266, 0,
+ "/periodcentered", 0267, 0,
+
+ "/cedilla", 0270, 0,
+ "/onesuperior", 0271, 0,
+ "/ordmasculine", 0272, 0,
+ "/guillemotright", 0273, 0,
+ "/onequarter", 0274, 0,
+ "/onehalf", 0275, 0,
+ "/threequarters", 0276, 0,
+ "/questiondown", 0277, 0,
+
+ "/Agrave", 0300, 0,
+ "/Aacute", 0301, 0,
+ "/Acircumflex", 0302, 0,
+ "/Atilde", 0303, 0,
+ "/Adieresis", 0304, 0,
+ "/Aring", 0305, 0,
+ "/AE", 0306, 0,
+ "/Ccedilla", 0307, 0,
+
+ "/Egrave", 0310, 0,
+ "/Eacute", 0311, 0,
+ "/Ecircumflex", 0312, 0,
+ "/Edieresis", 0313, 0,
+ "/Igrave", 0314, 0,
+ "/Iacute", 0315, 0,
+ "/Icircumflex", 0316, 0,
+ "/Idieresis", 0317, 0,
+
+ "/Eth", 0320, 0,
+ "/Ntilde", 0321, 0,
+ "/Ograve", 0322, 0,
+ "/Oacute", 0323, 0,
+ "/Ocircumflex", 0324, 0,
+ "/Otilde", 0325, 0,
+ "/Odieresis", 0326, 0,
+ "/multiply", 0327, 0,
+
+ "/Oslash", 0330, 0,
+ "/Ugrave", 0331, 0,
+ "/Uacute", 0332, 0,
+ "/Ucircumflex", 0333, 0,
+ "/Udieresis", 0334, 0,
+ "/Yacute", 0335, 0,
+ "/Thorn", 0336, 0,
+ "/germandbls", 0337, 0,
+
+ "/agrave", 0340, 0,
+ "/aacute", 0341, 0,
+ "/acircumflex", 0342, 0,
+ "/atilde", 0343, 0,
+ "/adieresis", 0344, 0,
+ "/aring", 0345, 0,
+ "/ae", 0346, 0,
+ "/ccedilla", 0347, 0,
+
+ "/egrave", 0350, 0,
+ "/eacute", 0351, 0,
+ "/ecircumflex", 0352, 0,
+ "/edieresis", 0353, 0,
+ "/igrave", 0354, 0,
+ "/iacute", 0355, 0,
+ "/icircumflex", 0356, 0,
+ "/idieresis", 0357, 0,
+
+ "/eth", 0360, 0,
+ "/ntilde", 0361, 0,
+ "/ograve", 0362, 0,
+ "/oacute", 0363, 0,
+ "/ocircumflex", 0364, 0,
+ "/otilde", 0365, 0,
+ "/odieresis", 0366, 0,
+ "/divide", 0367, 0,
+
+ "/oslash", 0370, 0,
+ "/ugrave", 0371, 0,
+ "/uacute", 0372, 0,
+ "/ucircumflex", 0373, 0,
+ "/udieresis", 0374, 0,
+ "/yacute", 0375, 0,
+ "/thorn", 0376, 0,
+ "/ydieresis", 0377, 0,
+};
+
+
+static short STDvsISO [][2] = {
+ 0341, 0306, /* AE */
+ 0351, 0330, /* Oslash */
+ 0302, 0222, /* acute */
+ 0361, 0346, /* ae */
+ 0306, 0226, /* breve */
+ 0317, 0237, /* caron */
+ 0313, 0270, /* cedilla */
+ 0303, 0223, /* circumflex */
+ 0250, 0244, /* currency */
+ 0310, 0250, /* dieresis */
+ 0307, 0227, /* dotaccent */
+ 0365, 0220, /* dotlessi */
+ 0373, 0337, /* germandbls */
+ 0301, 0221, /* grave */
+ 0315, 0235, /* hungarumlaut */
+ 0055, 0255, /* hyphen */
+ 0305, 0257, /* macron */
+ 0316, 0236, /* ogenek */
+ 0343, 0252, /* ordfeminine */
+ 0353, 0272, /* ordmasculine */
+ 0371, 0370, /* oslash */
+ 0264, 0267, /* periodcentered */
+ 0312, 0232, /* ring */
+ 0304, 0224, /* tilde */
+};
+
+/* from objfont.c de rest zit in lfm_s !!*/
+
+/* START 5.2 */
+
+static int chartoindex(objfnt *fnt, int c)
+{
+ if(c<fnt->charmin)
+ return -1;
+ if(c>fnt->charmax)
+ return -1;
+ return c-fnt->charmin;
+}
+
+
+static chardesc *getchardesc(objfnt *fnt, int c)
+{
+ int index;
+
+ index = chartoindex(fnt,c);
+ if(index<0)
+ return 0;
+ return fnt->my_chars+index;
+}
+
+static objfnt *newobjfnt(int type, int charmin, int charmax, int fscale)
+{
+ objfnt *fnt;
+
+ fnt = (objfnt *)MEM_mallocN(sizeof(objfnt), "newobjfnt");
+ fnt->freeaddr = 0;
+ fnt->type = type;
+ fnt->charmin = charmin;
+ fnt->charmax = charmax;
+ fnt->my_nchars = fnt->charmax-fnt->charmin+1;
+ fnt->scale = fscale;
+ fnt->my_chars = (chardesc *)MEM_mallocN(fnt->my_nchars*sizeof(chardesc), "newobjfnt2");
+ memset(fnt->my_chars, 0, fnt->my_nchars*sizeof(chardesc));
+ return fnt;
+}
+
+
+static void addchardata (objfnt * fnt, int c, short * data, int nshorts)
+{
+ int index;
+ chardesc *cd;
+
+ index = chartoindex(fnt,c);
+ if(index<0) {
+ fprintf(stderr,"Addchardata bad poop\n");
+ return;
+ }
+ cd = fnt->my_chars+index;
+ fnt->freeaddr = 0;
+ cd->datalen = nshorts*sizeof(short);
+ cd->data = (short *)MEM_mallocN(cd->datalen, "addchardata");
+ memcpy(cd->data, data, cd->datalen);
+}
+
+static void addcharmetrics(objfnt *fnt, int c, int movex, int movey)
+{
+ int index;
+ chardesc *cd;
+
+ index = chartoindex(fnt,c);
+ if(index<0) {
+ fprintf(stderr,"Addcharmetrics bad poop\n");
+ return;
+ }
+ cd = fnt->my_chars+index;
+ cd->movex = movex;
+ cd->movey = movey;
+}
+
+
+static void fakechar(objfnt *fnt, int c, int width)
+{
+ short chardata[1];
+
+ chardata[0] = PO_RET;
+ addchardata(fnt,c,chardata,1);
+ addcharmetrics(fnt,c,width,0);
+}
+
+
+static void freeobjfnt(objfnt * fnt)
+{
+ int i;
+ chardesc *cd;
+
+ cd = fnt->my_chars;
+ for(i=0; i<fnt->my_nchars; i++) {
+ if(cd->data)
+ MEM_freeN(cd->data);
+ cd++;
+ }
+ MEM_freeN(fnt->my_chars);
+ MEM_freeN(fnt);
+}
+
+
+/* END 5.2 */
+
+static short STDtoISO(short c)
+{
+ short i = (sizeof(STDvsISO) / (2 * sizeof(short))) - 1;
+
+ for (;i >= 0; i--){
+ if (STDvsISO[i][0] == c) return (STDvsISO[i][1]);
+ }
+ return(c);
+}
+
+
+/*
+ * read the font matrix out of the font file
+ *
+ */
+
+static char * newfgets(char * s, int n, PackedFile * pf){
+ int read = 0;
+ int c;
+ char * p;
+
+ p = s;
+ while (n > 0){
+ c = ((char *) pf->data)[pf->seek];
+ pf->seek++;
+ if (pf->seek > pf->size){
+ if (read == 0) return (0);
+ *p = 0;
+ return(s);
+ }
+ if (c == 10 || c == 13){
+ *p = 0;
+ return(s);
+ }
+ *p++ = c;
+ n--;
+ }
+ *p = 0;
+ return(s);
+}
+
+static int readfontmatrix(PackedFile * pf, float mat[2][2])
+{
+ char *cptr;
+ float a, b, c, d, e, f;
+
+ pf->seek = 0;
+
+ /* look for the FontMatrix def */
+ while(1) {
+ if(!newfgets(oneline, LINELEN, pf)) {
+ fprintf(stderr,"fromtype1: no FontMatrix found\n");
+ return(-1);
+ }
+ cptr = strchr(oneline,'/');
+ if(cptr) {
+ if(strncmp(cptr,"/FontMatrix",11) == 0) {
+ cptr = strchr(cptr,'[');
+ if(!cptr) {
+ fprintf(stderr,"fromtype1: bad FontMatrix line\n");
+ return(-1);
+ }
+ sscanf(cptr+1,"%f %f %f %f %f %f\n",&a,&b,&c,&d,&e,&f);
+ break;
+ }
+ }
+ }
+
+ mat[0][0] = 1000.0*a;
+ mat[1][0] = 1000.0*b;
+ mat[0][1] = 1000.0*c;
+ mat[1][1] = 1000.0*d;
+
+ return(0);
+}
+
+/*
+ * Decryption support
+ *
+ *
+ */
+static void resetdecrypt(int n)
+{
+ mr = n;
+}
+
+
+
+/*
+ * decryption subroutines
+ *
+ */
+
+static char mdecrypt(char cipher)
+{
+ char plain;
+
+ plain = (cipher^(mr>>8));
+ mr = (cipher+mr)*MC1 + MC2;
+ return plain;
+}
+
+static void decryptdata(char * cptr, int n)
+{
+ while(n--) {
+ *cptr = mdecrypt(*cptr);
+ cptr++;
+ }
+}
+
+static int decryptprogram(char *buf, int len)
+{
+ int i;
+
+ resetdecrypt(4330);
+ for(i=0; i<len; i++) {
+ if(i<SKIP)
+ mdecrypt(buf[i]);
+ else
+ buf[i-SKIP] = mdecrypt(buf[i]);
+ }
+ return len-SKIP;
+}
+
+static void decryptall(void)
+{
+ int i;
+
+ for(i=0; i<my_nsubrs; i++)
+ my_sublen[i] = decryptprogram(my_subrs[i],my_sublen[i]);
+ for(i=0; i<my_nchars; i++)
+ my_charlen[i] = decryptprogram(my_chars[i],my_charlen[i]);
+}
+
+
+/*
+ * decode the eexec part of the file
+ *
+ */
+
+static int decodetype1(PackedFile * pf, char *outname)
+{
+ char *hptr, *bptr;
+ int i, totlen, hexbytes, c;
+ char *hexdat;
+ char hextab[256];
+
+ /* make hex table */
+ if(!firsted) {
+ for(i=0; i<256; i++) {
+ if(i>='0' && i<='9')
+ hextab[i] = i-'0';
+ else if(i>='a' && i<='f')
+ hextab[i] = 10+i-'a';
+ else if(i>='A' && i<='F')
+ hextab[i] = 10+i-'A';
+ else
+ hextab[i] = NOTHEX;
+ }
+ }
+
+ pf->seek = 0;
+
+ /* allocate buffers */
+ totlen = pf->size;
+ hexdat = (char *)MEM_mallocN(totlen, "hexdat");
+ bindat = (char *)MEM_mallocN(totlen, "bindat");
+
+ /* look for eexec part of file */
+ while(1) {
+ if(!newfgets(oneline, LINELEN, pf)) {
+ fprintf(stderr,"fromtype1: no currentfile eexec found\n");
+ return(-1);
+ }
+ oneline[16] = 0;
+ if(strcmp(oneline,"currentfile eexe") == 0)
+ break;
+ }
+
+ /* initialize decryption variables */
+ mr = 55665;
+
+ /* first byte == 0 for binary data (???) */
+
+ c = ((char *) pf->data)[pf->seek];
+
+ if (hextab[c] != NOTHEX){
+ /* read all the hex bytes into the hex buffer */
+ hexbytes = 0;
+ while(newfgets(oneline, LINELEN, pf)) {
+ hptr = (char *)oneline;
+ while(*hptr) {
+ if(hextab[*hptr] != NOTHEX)
+ hexdat[hexbytes++] = *hptr;
+ hptr++;
+ }
+ }
+
+ /* check number of hex bytes */
+ if(hexbytes & 1)
+ hexbytes--;
+ datbytes = hexbytes/2;
+
+ /* translate hex data to binary */
+ hptr = hexdat;
+ bptr = bindat;
+ c = datbytes;
+ while(c--) {
+ *bptr++ = (hextab[hptr[0]]<<4)+hextab[hptr[1]];
+ hptr += 2;
+ }
+
+ /* decrypt the data */
+ decryptdata(bindat,datbytes);
+
+ } else {
+ datbytes = pf->size - pf->seek;
+ memcpy(bindat, ((char *) pf->data) + pf->seek, datbytes);
+
+ if ((bindat[2] << 8 + bindat[3]) == 0x800){
+ /* order data (remove 6 bytes headers) */
+ i = datbytes;
+ hptr = bptr = bindat + 4;
+ hptr += 2;
+
+ while (i > 0){
+ if (i > 2046) c = 2046;
+ else c = i;
+
+ memcpy(bptr, hptr, c);
+ bptr += 2046;
+ hptr += 2046 + 6;
+ i -= 2046 + 6;
+ datbytes -= 6;
+ }
+
+ /* decrypt the data */
+ decryptdata(bindat+4,datbytes);
+ } else{
+ decryptdata(bindat+6,datbytes-6);
+ }
+ }
+
+#ifdef DEBUG
+ outf = fopen(outname,"wb");
+ fwrite(bindat,datbytes,1,outf);
+ fclose(outf);
+#endif
+
+ MEM_freeN(hexdat);
+
+ return 1;
+}
+
+/*
+ * fake file reading funcs
+ *
+ *
+ */
+
+static void fakefopen(void)
+{
+ fakepos = 0;
+ fakemax = datbytes;
+}
+
+
+static void fakegettoken(char *str)
+{
+ int c;
+ char *cptr;
+ char *start;
+
+ start = (char *) str;
+ cptr = bindat+fakepos;
+ c = *cptr++;
+ fakepos++;
+ if(c != '\n') {
+ while(isspace(c)) {
+ c = *cptr++;
+ fakepos++;
+ }
+ while (fakepos<fakemax && !isspace(c)) {
+ *str++ = c;
+ c = *cptr++;
+ fakepos++;
+ }
+ if(c == '\n')
+ fakepos--;
+ }
+ *str = 0;
+ if(fakepos>fakemax) {
+ fprintf(stderr,"fromtype1: unexpected eof\n");
+ strcpy(start, "end");
+ }
+}
+
+static int fakefgets(char *buf,int max)
+{
+ char *cptr;
+
+ cptr = (char *)(bindat+fakepos);
+ while(max--) {
+ *buf++ = *cptr;
+ fakepos++;
+ if(*cptr == 10 || *cptr == 13)
+ return 1;
+ cptr++;
+ if(fakepos>fakemax)
+ return 0;
+ }
+ return 0;
+}
+
+static char *fakefread(int n)
+{
+ fakepos += n;
+ return bindat+fakepos-n;
+}
+
+static void applymat(float mat[][2], float *x, float *y)
+{
+ float tx, ty;
+
+ tx = ((*x)*mat[0][0])+((*y)*mat[0][1]);
+ ty = ((*x)*mat[1][0])+((*y)*mat[1][1]);
+ *x = tx;
+ *y = ty;
+}
+
+static void setcharlist(void)
+{
+ char *name, found;
+ int i, j;
+
+ for(i=0; i<NASCII; i++) ISOcharlist[i].prog = -1;
+
+ for(j=0; j<my_nchars; j++) {
+ name = my_charname[j];
+ if(name) {
+ found = 0;
+ for(i=0; i<NASCII; i++) {
+ if(ISOcharlist[i].name && (strcmp(name,ISOcharlist[i].name) == 0)){
+ ISOcharlist[i].prog = j;
+ found = 1;
+ }
+ }
+ /*if (found == 0) printf("no match found for: %s\n", name);*/
+ MEM_freeN(name);
+ my_charname[j] = 0;
+ }
+ }
+}
+
+
+static objfnt * objfnt_from_psfont(PackedFile * pf)
+{
+ int i, k, index;
+ int nread, namelen;
+ char *cptr;
+
+ fnt = 0;
+ bindat = 0;
+
+ /* read the font matrix from the font */
+ if (readfontmatrix(pf,mat)) return(0);
+
+ /* decode the font data */
+ decodetype1(pf, "/usr/tmp/type1.dec");
+
+ /* open the input file */
+ fakefopen();
+
+ /* look for the /Subrs def and get my_nsubrs */
+ while(1) {
+ if(!fakefgets(oneline,LINELEN)) {
+ fprintf(stderr,"fromtype1: no /Subrs found\n");
+ my_nsubrs = 0;
+ fakefopen();
+ break;
+ }
+ cptr = strchr(oneline,'/');
+ if(cptr) {
+ if(strncmp(cptr,"/Subrs",6) == 0) {
+ my_nsubrs = atoi(cptr+6);
+ break;
+ }
+ }
+ }
+
+ /* read the Subrs in one by one */
+ for(i=0; i<my_nsubrs; i++)
+ my_sublen[i] = 0;
+ for(i=0; i<my_nsubrs; i++) {
+ for(k=0; k<MAXTRIES; k++) {
+ fakegettoken(tok);
+ if(strcmp(tok,"dup") == 0)
+ break;
+ }
+ if(k == MAXTRIES) {
+ fprintf(stderr,"dup for subr %d not found in range\n", i);
+ /*exit(1);*/
+ }
+
+ /* get the Subr index here */
+ fakegettoken(tok);
+ index = atoi(tok);
+
+ /* check to make sure it is in range */
+ if(index<0 || index>my_nsubrs) {
+ fprintf(stderr,"bad Subr index %d\n",index);
+ /*exit(1);*/
+ }
+
+ /* get the number of bytes to read */
+ fakegettoken(tok);
+ nread = atoi(tok);
+ fakegettoken(tok);
+
+ /* read in the subroutine */
+ my_sublen[index] = nread;
+ my_subrs[index] = fakefread(nread);
+ fakegettoken(tok);
+ }
+
+ /* look for the CharStrings */
+ while(1) {
+ fakegettoken(tok);
+ cptr = strchr(tok,'/');
+ if(cptr && strcmp(cptr,"/CharStrings") == 0)
+ break;
+ }
+
+ fakegettoken(tok); /* skip my_ncharscrings */
+ fakegettoken(tok); /* skip dict */
+ fakegettoken(tok); /* skip dup */
+ fakegettoken(tok); /* skip begin */
+ fakegettoken(tok); /* skip newline */
+
+ /* read the CharStrings one by one */
+ my_nchars = 0;
+ for(i=0; i<MAXCHARS; i++) {
+
+ /* check for end */
+ fakegettoken(tok);
+ if(strcmp(tok,"end") == 0)
+ break;
+
+ /* get the char name and allocate space for it */
+ namelen = strlen(tok);
+ my_charname[i] = (char *)MEM_mallocN(namelen+1, "my_charname");
+ strcpy(my_charname[i],tok);
+
+ /* get the number of bytes to read */
+ fakegettoken(tok);
+ nread = atoi(tok);
+ fakegettoken(tok);
+
+ /* read in the char description */
+ my_charlen[i] = nread;
+ my_chars[i] = fakefread(nread);
+
+ /* skip the end of line */
+ fakegettoken(tok);
+ fakegettoken(tok);
+ my_nchars++;
+ }
+
+ /* decrypt the character descriptions */
+ decryptall();
+ setcharlist();
+
+ /* make the obj font */
+ makeobjfont(savesplines);
+
+ if (bindat) MEM_freeN(bindat);
+ /* system("rm /usr/tmp/type1.dec"); */
+
+ return (fnt);
+}
+
+
+
+
+/*
+ * pc stack support
+ *
+ */
+
+static void initpcstack(void)
+{
+ pcsp = 0;
+}
+
+static void pushpc(char *pc)
+{
+ pcstack[pcsp] = pc;
+ pcsp++;
+}
+
+static char *poppc(void)
+{
+ pcsp--;
+ if(pcsp<0) {
+ fprintf(stderr,"\nYUCK: pc stack under flow\n");
+ pcsp = 0;
+ return 0;
+ }
+ return pcstack[pcsp];
+}
+
+/*
+ * Data stack support
+ *
+ */
+
+static void initstack(void)
+{
+ sp = 0;
+}
+
+static void push(int val)
+/* int val; */
+{
+ stack[sp] = val;
+ sp++;
+}
+
+static int pop(void)
+{
+ sp--;
+ if(sp<0) {
+ fprintf(stderr,"\nYUCK: stack under flow\n");
+ sp = 0;
+ return 0;
+ }
+ return stack[sp];
+}
+
+/*
+ * call/return data stack
+ *
+ */
+
+static void initretstack(void)
+{
+ retsp = 0;
+}
+
+static void retpush(int val)
+/* int val; */
+{
+ retstack[retsp] = val;
+ retsp++;
+}
+
+static int retpop(void)
+{
+ retsp--;
+ if(retsp<0) {
+ fprintf(stderr,"\nYUCK: ret stack under flow\n");
+ retsp = 0;
+ return 0;
+ }
+ return retstack[retsp];
+}
+
+
+/*
+ * execute the program:
+ *
+ *
+ */
+
+static void getmove(int *x, int *y)
+{
+ *x = delx;
+ *y = dely;
+ /* printf("ingetmove\n"); */
+}
+
+static void getpos(int *x, int *y)
+{
+ *x = curx;
+ *y = cury;
+}
+
+static void subr1(void)
+{
+ coordpos = 0;
+ incusp = 1;
+}
+
+static void subr2(void)
+{
+ int x, y;
+
+ getmove(&x,&y);
+ if(coordpos>=7) {
+ fprintf(stderr,"subr2: bad poop\n");
+ /*exit(1);*/
+ }
+ coordsave[coordpos][0] = x;
+ coordsave[coordpos][1] = y;
+ coordpos++;
+}
+
+static void subr0(void)
+{
+ int x0, y0;
+ int x1, y1;
+ int x2, y2;
+ int x3, y3;
+ int xpos, ypos, noise;
+
+ ypos = pop();
+ xpos = pop();
+ noise = pop();
+ if(coordpos!=7) {
+ fprintf(stderr,"subr0: bad poop\n");
+ /*exit(1);*/
+ }
+ x0 = coordsave[0][0];
+ y0 = coordsave[0][1];
+
+ x1 = coordsave[1][0]+x0;
+ y1 = coordsave[1][1]+y0;
+ x2 = coordsave[2][0];
+ y2 = coordsave[2][1];
+ x3 = coordsave[3][0];
+ y3 = coordsave[3][1];
+ rcurveto(x1,y1,x1+x2,y1+y2,x1+x2+x3,y1+y2+y3);
+ x1 = coordsave[4][0];
+ y1 = coordsave[4][1];
+ x2 = coordsave[5][0];
+ y2 = coordsave[5][1];
+ x3 = coordsave[6][0];
+ y3 = coordsave[6][1];
+ rcurveto(x1,y1,x1+x2,y1+y2,x1+x2+x3,y1+y2+y3);
+ getpos(&x0,&y0);
+ retpush(y0);
+ retpush(x0);
+ incusp = 0;
+}
+
+static void append_poly_offset(short ofsx, short ofsy, short * data)
+{
+ int nverts;
+
+ if (data == 0) return;
+
+ while(1) {
+ switch(chardata[nshorts++] = *data++) {
+ case PO_BGNLOOP:
+ nshorts --; /* voor de eerste keer */
+ break;
+ case PO_RETENDLOOP:
+ case PO_RET:
+ return;
+ }
+ nverts = chardata[nshorts++] = *data++;
+ while(nverts--) {
+ chardata[nshorts++] = (*data++) + ofsx;
+ chardata[nshorts++] = (*data++) + ofsy;
+ }
+ }
+}
+
+
+static void append_spline_offset(short ofsx, short ofsy, short * data)
+{
+ int nverts = 0;
+
+ if (data == 0) return;
+
+ while(1) {
+ switch(chardata[nshorts++] = *data++) {
+ case SP_MOVETO:
+ case SP_LINETO:
+ nverts = 1;
+ break;
+ case SP_CURVETO:
+ nverts = 3;
+ break;
+ case SP_RETCLOSEPATH:
+ case SP_RET:
+ return;
+ }
+
+ for (; nverts > 0; nverts--) {
+ chardata[nshorts++] = (*data++) + ofsx;
+ chardata[nshorts++] = (*data++) + ofsy;
+ }
+ }
+}
+
+
+
+/*
+ * graphics follows
+ *
+ *
+ */
+
+
+/* poly output stuff */
+
+static void setwidth(int w, int x)
+{
+ thecharwidth = w;
+ thesidebearing = x;
+}
+
+static void poly_beginchar(void)
+{
+ npnts = 0;
+ nloops = 0;
+}
+
+static void poly_endchar(void)
+{
+ if(nloops == 0)
+ chardata[nshorts++] = PO_RET;
+ else
+ chardata[nshorts++] = PO_RETENDLOOP;
+}
+
+static void poly_close(void)
+{
+ chardata[nvertpos] = npnts;
+ npnts = 0;
+}
+
+static void poly_pnt(float x, float y)
+{
+ int ix, iy;
+
+ applymat(mat,&x,&y);
+ ix = floor(x);
+ iy = floor(y);
+ if(npnts == 0) {
+ if(nloops == 0) {
+ chardata[nshorts++] = PO_BGNLOOP;
+ nvertpos = nshorts++;
+ } else {
+ chardata[nshorts++] = PO_ENDBGNLOOP;
+ nvertpos = nshorts++;
+ }
+ nloops++;
+ }
+ chardata[nshorts++] = ix;
+ chardata[nshorts++] = iy;
+ npnts++;
+
+}
+
+/* spline output stuff */
+
+static void spline_beginchar(void)
+{
+ sp_npnts = 0;
+ sp_nloops = 0;
+}
+
+static void spline_endchar(void)
+{
+ if(sp_nloops == 0)
+ chardata[nshorts++] = SP_RET;
+ else
+ chardata[nshorts++] = SP_RETCLOSEPATH;
+}
+
+static void spline_close(void)
+{
+ chardata[nshorts++] = SP_CLOSEPATH;
+ sp_npnts = 0;
+ sp_nloops = 0;
+}
+
+static void spline_line(float x0, float y0, float x1, float y1)
+{
+ applymat(mat,&x0,&y0);
+ applymat(mat,&x1,&y1);
+
+ if(sp_npnts == 0) {
+ chardata[nshorts++] = SP_MOVETO;
+ chardata[nshorts++] = floor(x0);
+ chardata[nshorts++] = floor(y0);
+ sp_npnts++;
+ sp_nloops++;
+ }
+ chardata[nshorts++] = SP_LINETO;
+ chardata[nshorts++] = floor(x1);
+ chardata[nshorts++] = floor(y1);
+ sp_npnts++;
+}
+
+static void spline_curveto(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3)
+{
+ applymat(mat,&x0,&y0);
+ applymat(mat,&x1,&y1);
+ applymat(mat,&x2,&y2);
+ applymat(mat,&x3,&y3);
+
+ if(sp_npnts == 0) {
+ chardata[nshorts++] = SP_MOVETO;
+ chardata[nshorts++] = floor(x0);
+ chardata[nshorts++] = floor(y0);
+ sp_npnts++;
+ sp_nloops++;
+ }
+ chardata[nshorts++] = SP_CURVETO;
+ chardata[nshorts++] = floor(x1);
+ chardata[nshorts++] = floor(y1);
+ chardata[nshorts++] = floor(x2);
+ chardata[nshorts++] = floor(y2);
+ chardata[nshorts++] = floor(x3);
+ chardata[nshorts++] = floor(y3);
+}
+
+static void savestart(int x, int y)
+{
+ startx = x;
+ starty = y;
+ started = 1;
+}
+
+static void sbpoint( int x, int y)
+{
+ curx = x;
+ cury = y;
+}
+
+static void rmoveto( int x, int y)
+{
+ if(incusp) {
+ delx = x;
+ dely = y;
+ } else {
+ curx += x;
+ cury += y;
+ savestart(curx,cury);
+ }
+}
+
+static void drawline(float x0, float y0, float x1, float y1, float dx0, float dy0, float dx1, float dy1)
+{
+ if(x0!=x1 || y0!=y1)
+ poly_pnt(x1,y1);
+}
+
+
+static void rlineto( int x, int y)
+{
+ float dx, dy;
+
+ nextx = curx + x;
+ nexty = cury + y;
+ dx = nextx-curx;
+ dy = nexty-cury;
+ if (savesplines) spline_line( curx, cury, nextx, nexty);
+ else drawline( curx, cury, nextx, nexty,dx,dy,dx,dy);
+ curx = nextx;
+ cury = nexty;
+}
+
+static void closepath(void)
+{
+ float dx, dy;
+
+ if(started) {
+ dx = startx-curx;
+ dy = starty-cury;
+ if (savesplines) {
+ spline_close();
+ } else {
+ drawline( curx, cury, startx, starty,dx,dy,dx,dy);
+ poly_close();
+ }
+ started = 0;
+ }
+}
+
+static void bezadapt( float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, float beztol)
+{
+ float ax0,ay0,ax1,ay1,ax2,ay2,ax3,ay3;
+ float bx0,by0,bx1,by1,bx2,by2,bx3,by3;
+ float midx, midy;
+ float linx, liny, dx, dy, mag;
+
+ midx = (x0+3*x1+3*x2+x3)/8.0;
+ midy = (y0+3*y1+3*y2+y3)/8.0;
+ linx = (x0+x3)/2.0;
+ liny = (y0+y3)/2.0;
+ dx = midx-linx;
+ dy = midy-liny;
+ mag = dx*dx+dy*dy;
+ if(mag<(beztol*beztol))
+ drawline(x0,y0,x3,y3,x1-x0,y1-y0,x3-x2,y3-y2);
+ else {
+ ax0 = x0;
+ ay0 = y0;
+ ax1 = (x0+x1)/2;
+ ay1 = (y0+y1)/2;
+ ax2 = (x0+2*x1+x2)/4;
+ ay2 = (y0+2*y1+y2)/4;
+ ax3 = midx;
+ ay3 = midy;
+ bezadapt(ax0,ay0,ax1,ay1,ax2,ay2,ax3,ay3,beztol);
+
+ bx0 = midx;
+ by0 = midy;
+ bx1 = (x1+2*x2+x3)/4;
+ by1 = (y1+2*y2+y3)/4;
+ bx2 = (x2+x3)/2;
+ by2 = (y2+y3)/2;
+ bx3 = x3;
+ by3 = y3;
+ bezadapt(bx0,by0,bx1,by1,bx2,by2,bx3,by3,beztol);
+ }
+}
+
+static void drawbez( float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3)
+{
+ bezadapt(x0,y0,x1,y1,x2,y2,x3,y3,beztol);
+}
+
+
+static void rcurveto( int dx1, int dy1, int dx2, int dy2, int dx3, int dy3)
+{
+ int x0, y0;
+ int x1, y1;
+ int x2, y2;
+ int x3, y3;
+
+ x0 = curx;
+ y0 = cury;
+ x1 = curx+dx1;
+ y1 = cury+dy1;
+ x2 = curx+dx2;
+ y2 = cury+dy2;
+ x3 = curx+dx3;
+ y3 = cury+dy3;
+
+ if (savesplines) {
+ spline_curveto( x0, y0, x1, y1, x2, y2, x3, y3);
+ } else{
+ drawbez( x0, y0, x1, y1, x2, y2, x3, y3);
+ }
+ curx = x3;
+ cury = y3;
+}
+
+/*
+ * saveobjfont -
+ * save an object font.
+ *
+ */
+
+/* generic routines */
+
+static void makeobjfont(int savesplines)
+{
+ int i, c;
+
+ if(savesplines)
+ fnt = newobjfnt(SP_TYPE, 32, 32+NASCII-1, 9840);
+ else
+ fnt = newobjfnt(PO_TYPE, 32, 32+NASCII-1, 9840);
+
+ for(i=0; i<NASCII; i++) {
+ c = i+32;
+ if(ISOcharlist[i].prog>=0) {
+ /*printf("decoding %s\n", ISOcharlist[i].name);*/
+
+ nshorts = 0;
+ drawchar(ISOcharlist[i].prog);
+ addchardata(fnt,c,chardata,nshorts);
+ addcharmetrics(fnt,c,thecharwidth,0);
+ sidebearing[c] = thesidebearing;
+ } else if(c == ' ') {
+ printf("faking space %d\n",i);
+ fakechar(fnt,' ',400);
+ }
+ }
+}
+
+/*
+ * run the character program
+ *
+ *
+ */
+
+static void drawchar(int c)
+{
+ if (savesplines) {
+ spline_beginchar();
+ } else {
+ poly_beginchar();
+ }
+ initstack();
+ initpcstack();
+ initretstack();
+ pc = my_chars[c];
+ runprog();
+ if (savesplines){
+ spline_endchar();
+ } else {
+ poly_endchar();
+ }
+}
+
+static int docommand(int cmd)
+{
+ int x, y, w, c1, c2;
+ int dx1, dy1;
+ int dx2, dy2;
+ int dx3, dy3;
+ float fdx1, fdy1;
+ int i, sub, n;
+ char *subpc;
+ chardesc *cd;
+ short *ndata;
+
+ switch(cmd) {
+ case WHAT0:
+ fprintf(stderr,"\nYUCK: WHAT0\n");
+ break;
+ case HSTEM:
+ pop();
+ pop();
+ /*printf("hstem: %d %d\n", pop(), pop());*/
+ break;
+ case VSTEM:
+ pop();
+ pop();
+ /*printf("vstem: %d %d\n", pop(), pop());*/
+ break;
+ case VMOVETO:
+ y = pop();
+ rmoveto(0,y);
+ break;
+ case RLINETO:
+ y = pop();
+ x = pop();
+ rlineto(x,y);
+ break;
+ case HLINETO:
+ x = pop();
+ rlineto(x,0);
+ break;
+ case VLINETO:
+ y = pop();
+ rlineto(0,y);
+ break;
+ case RRCURVETO:
+ dy3 = pop();
+ dx3 = pop();
+ dy2 = pop();
+ dx2 = pop();
+ dy1 = pop();
+ dx1 = pop();
+ rcurveto(dx1,dy1,dx1+dx2,dy1+dy2,dx1+dx2+dx3,dy1+dy2+dy3);
+ break;
+ case CLOSEPATH:
+ closepath();
+ break;
+ case CALLSUBR:
+ sub = pop();
+ subpc = my_subrs[sub];
+ if(!subpc) {
+ fprintf(stderr,"\nYUCK no sub addr\n");
+ }
+ pushpc(pc);
+ pc = subpc;
+ break;
+ case RETURN:
+ pc = poppc();
+ break;
+ case HSBW:
+ w = pop();
+ x = pop();
+ setwidth(w, x);
+ sbpoint(x,0);
+ break;
+ case ENDCHAR:
+ closepath();
+ break;
+ case RMOVETO:
+ y = pop();
+ x = pop();
+ rmoveto(x,y);
+ break;
+ case HMOVETO:
+ x = pop();
+ rmoveto(x,0);
+ break;
+ case VHCURVETO:
+ dy3 = 0;
+ dx3 = pop();
+ dy2 = pop();
+ dx2 = pop();
+ dy1 = pop();
+ dx1 = 0;
+ rcurveto(dx1,dy1,dx1+dx2,dy1+dy2,dx1+dx2+dx3,dy1+dy2+dy3);
+ break;
+ case HVCURVETO:
+ dy3 = pop();
+ dx3 = 0;
+ dy2 = pop();
+ dx2 = pop();
+ dy1 = 0;
+ dx1 = pop();
+ rcurveto(dx1,dy1,dx1+dx2,dy1+dy2,dx1+dx2+dx3,dy1+dy2+dy3);
+ break;
+ case DOTSECTION:
+ break;
+ case VSTEM3:
+ /*printf("vstem3\n");*/
+ pop();
+ pop();
+ pop();
+ pop();
+ pop();
+ pop();
+ break;
+ case HSTEM3:
+ /*printf("hstem3\n");*/
+ pop();
+ pop();
+ pop();
+ pop();
+ pop();
+ pop();
+ break;
+ case SEAC:
+ if (0) {
+ printf("seac: %3d %3d %3d %3d %3d\n", pop(), pop(), pop(), pop(), pop());
+ } else{
+ c2 = STDtoISO(pop()); /* accent */
+ c1 = STDtoISO(pop()); /* letter */
+
+ cd = getchardesc(fnt, c1);
+ if (cd) {
+ memcpy(chardata, cd->data, cd->datalen);
+ nshorts = cd->datalen / sizeof(short);
+ }
+
+ cd = getchardesc(fnt, c2);
+ if (cd && cd->data && cd->datalen) {
+ ndata = cd->data;
+
+ if (nshorts) {
+ if (savesplines) {
+ switch (chardata[nshorts - 1]){
+ case SP_RET:
+ nshorts--;
+ break;
+ case SP_RETCLOSEPATH:
+ chardata[nshorts - 1] = SP_CLOSEPATH;
+ break;
+ }
+ } else {
+ switch (chardata[nshorts - 1]){
+ case PO_RET:
+ printf("PO_RET in character disription ?\n");
+ nshorts--;
+ break;
+ case PO_RETENDLOOP:
+ if (ndata[0] == PO_BGNLOOP) {
+ chardata[nshorts - 1] = PO_ENDBGNLOOP;
+ } else {
+ printf("new character doesn't start with PO_BGNLOOP ?\n");
+ }
+ break;
+ }
+ }
+ }
+
+ /* i.p.v. the sidebearing[c1] moet misschen thesidebearing gebruikt worden */
+
+ dy1 = pop();
+ dx1 = pop() + sidebearing[c1] - sidebearing[c2];
+ pop();
+
+ fdx1 = dx1;
+ fdy1 = dy1;
+ applymat(mat, &fdx1, &fdy1);
+ dx1 = floor(fdx1);
+ dy1 = floor(fdy1);
+
+ if (savesplines) {
+ append_spline_offset(dx1, dy1, ndata);
+ } else{
+ append_poly_offset(dx1, dy1, ndata);
+ }
+
+ /*printf("first: %d %d\n", cd->data[0], cd->data[1]);*/
+ }
+ fflush(stdout);
+ }
+ break;
+ case SBW:
+ w = pop();
+ y = pop();
+ fprintf(stderr,"sbw: width: %d %d\n",w,y);
+ y = pop();
+ x = pop();
+ fprintf(stderr,"sbw: side: %d %d\n",x,y);
+ setwidth(w, x);
+ sbpoint(x,y);
+ break;
+ case DIV:
+ x = pop();
+ y = pop();
+ push(x/y);
+ break;
+ case CALLOTHERSUBR:
+ sub = pop();
+ n = pop();
+ if(sub == 0)
+ subr0();
+ else if(sub == 1)
+ subr1();
+ else if(sub == 2)
+ subr2();
+ else {
+ for(i=0; i<n; i++) {
+ retpush(pop());
+ }
+ }
+ break;
+ case POP:
+ push(retpop());
+ break;
+ case SETCURRENTPOINT:
+ y = pop();
+ x = pop();
+ sbpoint(x,y);
+ break;
+ default:
+ /*fprintf(stderr,"\nYUCK bad instruction %d\n",cmd);*/
+ break;
+ }
+ if(pc == 0 || cmd == ENDCHAR || cmd == WHAT0 || cmd == SEAC)
+ return 0;
+ else
+ return 1;
+}
+
+
+/*
+ * Character interpreter
+ *
+ */
+
+static void runprog(void)
+{
+ int v, w, num, cmd;
+
+ while(1) {
+ v = *pc++;
+ if(v>=0 && v<=31) {
+ if(v == 12) {
+ w = *pc++;
+ cmd = 256+w;
+ } else
+ cmd = v;
+ if(!docommand(cmd)) {
+ return;
+ }
+ } else if(v>=32 && v<=246) {
+ num = v-139;
+ push(num);
+ } else if(v>=247 && v<=250) {
+ w = *pc++;
+ num = (v-247)*256+w+108;
+ push(num);
+ } else if(v>=251 && v<=254) {
+ w = *pc++;
+ num = -(v-251)*256-w-108;
+ push(num);
+ } else if(v == 255) {
+ num = *pc++;
+ num <<= 8;
+ num |= *pc++;
+ num <<= 8;
+ num |= *pc++;
+ num <<= 8;
+ num |= *pc++;
+ push(num);
+ }
+ }
+}
+
+/***/
+
+static VFontData *objfnt_to_vfontdata(objfnt *fnt)
+{
+ VFontData *vfd;
+ chardesc *cd;
+ short *_data, *data;
+ int a, i, count, stop, ready, meet;
+ short first[2], last[2];
+ struct Nurb *nu;
+ struct BezTriple *bezt, *bez2;
+ float scale, dx, dy;
+
+ if (!fnt || (fnt->type!=SP_TYPE)) {
+ return NULL;
+ }
+
+ vfd= MEM_callocN(sizeof(*vfd), "VFontData");
+ scale = 10.0/(float)fnt->scale; /* na IRIX 6.2, schaal klopte niet meer */
+
+ for (i = 0; i < MAX_VF_CHARS; i++) {
+ cd = getchardesc(fnt, i);
+ if (cd && cd->data && cd->datalen) {
+ vfd->width[i] = scale * cd->movex;
+
+ _data = data = cd->data;
+
+ do{
+ /* eerst even tellen */
+ _data = data;
+ count = 0;
+ ready = stop = 0;
+
+ do{
+ switch(*data++){
+ case SP_MOVETO:
+ first[0] = data[0];
+ first[1] = data[1];
+ case SP_LINETO:
+ count++;
+ last[0] = data[0];
+ last[1] = data[1];
+ data += 2;
+ break;
+ case SP_CURVETO:
+ count++;
+ last[0] = data[4];
+ last[1] = data[5];
+ data += 6;
+ break;
+ case SP_RET:
+ case SP_RETCLOSEPATH:
+ stop = 1;
+ ready = 1;
+ break;
+ case SP_CLOSEPATH:
+ stop = 1;
+ break;
+ }
+ } while (!stop);
+
+ if (last[0] == first[0] && last[1] == first[1]) meet = 1;
+ else meet = 0;
+
+ /* is er meer dan 1 uniek punt ?*/
+
+ if (count - meet > 0) {
+ data = _data;
+ nu = (Nurb*)MEM_callocN(sizeof(struct Nurb),"objfnt_nurb");
+ bezt = (BezTriple*)MEM_callocN((count)* sizeof(BezTriple),"objfnt_bezt") ;
+ if (nu != 0 && bezt != 0) {
+ BLI_addtail(&vfd->nurbsbase[i], nu);
+ nu->type= CU_BEZIER+CU_2D;
+ nu->pntsu = count;
+ nu->resolu= 8;
+ nu->flagu= 1;
+ nu->bezt = bezt;
+ stop = 0;
+
+ /* punten inlezen */
+ do {
+ switch(*data++){
+ case SP_MOVETO:
+ bezt->vec[1][0] = scale * *data++;
+ bezt->vec[1][1] = scale * *data++;
+
+ break;
+ case SP_LINETO:
+ bez2 = bezt++;
+ bezt->vec[1][0] = scale * *data++;
+ bezt->vec[1][1] = scale * *data++;
+ /* vector handles */
+ bezt->h1= HD_VECT;
+ bez2->h2= HD_VECT;
+ dx = (bezt->vec[1][0] - bez2->vec[1][0]) / 3.0;
+ dy = (bezt->vec[1][1] - bez2->vec[1][1]) / 3.0;
+ bezt->vec[0][0] = bezt->vec[1][0] - dx;
+ bezt->vec[0][1] = bezt->vec[1][1] - dy;
+ bez2->vec[2][0] = bez2->vec[1][0] + dx;
+ bez2->vec[2][1] = bez2->vec[1][1] + dy;
+ break;
+
+ case SP_CURVETO:
+ bezt->vec[2][0] = scale * *data++;
+ bezt->vec[2][1] = scale * *data++;
+ bezt->h2= HD_ALIGN;
+ bezt++;
+ bezt->vec[0][0] = scale * *data++;
+ bezt->vec[0][1] = scale * *data++;
+ bezt->vec[1][0] = scale * *data++;
+ bezt->vec[1][1] = scale * *data++;
+ bezt->h1= HD_ALIGN;
+ break;
+
+ case SP_RET:
+ case SP_RETCLOSEPATH:
+ stop = 1;
+ ready = 1;
+ break;
+ case SP_CLOSEPATH:
+ stop = 1;
+ break;
+ }
+ } while (stop == 0);
+
+ if (meet) {
+ /* kopieer handles */
+ nu->bezt->vec[0][0] = bezt->vec[0][0];
+ nu->bezt->vec[0][1] = bezt->vec[0][1];
+ /* en vergeet laatste punt */
+ nu->pntsu--;
+ }
+ else {
+ /* vector handles */
+ bez2 = nu->bezt;
+ dx = (bezt->vec[1][0] - bez2->vec[1][0]) / 3.0;
+ dy = (bezt->vec[1][1] - bez2->vec[1][1]) / 3.0;
+ bezt->vec[2][0] = bezt->vec[1][0] - dx;
+ bezt->vec[2][1] = bezt->vec[1][1] - dy;
+ bez2->vec[0][0] = bez2->vec[1][0] + dx;
+ bez2->vec[0][1] = bez2->vec[1][1] + dy;
+ bezt->h2= bez2->h1= HD_VECT;
+ }
+
+ /* verboden handle combinaties */
+ a= nu->pntsu;
+ bezt= nu->bezt;
+ while(a--) {
+ if(bezt->h1!=HD_ALIGN && bezt->h2==HD_ALIGN) bezt->h2= 0;
+ else if(bezt->h2!=HD_ALIGN && bezt->h1==HD_ALIGN) bezt->h1= 0;
+ bezt++;
+ }
+
+ }
+ else {
+ if (nu) MEM_freeN(nu);
+ if (bezt) MEM_freeN(bezt);
+ }
+ }
+ _data = data;
+ } while (ready == 0);
+ }
+ }
+
+ return vfd;
+}
+
+VFontData *BLI_vfontdata_from_psfont(PackedFile *pf)
+{
+ objfnt *fnt= objfnt_from_psfont(pf);
+ VFontData *vfd= NULL;
+
+ if (fnt) {
+ vfd= objfnt_to_vfontdata(fnt);
+ freeobjfnt(fnt);
+ }
+
+ return vfd;
+}
diff --git a/source/blender/blenlib/intern/rand.c b/source/blender/blenlib/intern/rand.c
new file mode 100644
index 00000000000..bf29d57c2cf
--- /dev/null
+++ b/source/blender/blenlib/intern/rand.c
@@ -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 *****
+ */
+#include "PIL_time.h"
+#include "BLI_rand.h"
+
+#ifdef WIN32
+typedef unsigned __int64 r_uint64;
+#else
+typedef unsigned long long r_uint64;
+#endif
+
+#define MULTIPLIER 0x5DEECE66D
+#define ADDEND 0xB
+
+#define LOWSEED 0x330E
+
+static r_uint64 X= 0;
+
+void BLI_srand(unsigned int seed) {
+ X= (((r_uint64) seed)<<16) | LOWSEED;
+}
+
+int BLI_rand(void) {
+ X= (MULTIPLIER*X + ADDEND)&0x0000FFFFFFFFFFFF;
+ return (int) (X>>17);
+}
+
+double BLI_drand(void) {
+ return (double) BLI_rand()/0x80000000;
+}
+
+float BLI_frand(void) {
+ return (float) BLI_rand()/0x80000000;
+}
+
+void BLI_storerand(unsigned int loc_r[2]) {
+ loc_r[0]= (unsigned int) (X>>32);
+ loc_r[1]= (unsigned int) (X&0xFFFFFFFF);
+}
+
+void BLI_restorerand(unsigned int loc[2]) {
+ X= ((r_uint64) loc[0])<<32;
+ X|= loc[1];
+}
+
+void BLI_fillrand(void *addr, int len) {
+ unsigned char *p= addr;
+ unsigned int save[2];
+
+ BLI_storerand(save);
+
+ BLI_srand((unsigned int) (PIL_check_seconds_timer()*0x7FFFFFFF));
+ while (len--) *p++= BLI_rand()&0xFF;
+ BLI_restorerand(save);
+}
diff --git a/source/blender/blenlib/intern/rct.c b/source/blender/blenlib/intern/rct.c
new file mode 100644
index 00000000000..373edd1af5a
--- /dev/null
+++ b/source/blender/blenlib/intern/rct.c
@@ -0,0 +1,115 @@
+/*
+ *
+ * rct.c
+ *
+ * april 95
+ *
+ * $Id$
+ *
+ * A minimalist lib for functions doing stuff with rectangle structs.
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "DNA_vec_types.h"
+#include "BLI_blenlib.h"
+
+int BLI_rcti_is_empty(rcti * rect)
+{
+ return ((rect->xmax<=rect->xmin) ||
+ (rect->ymax<=rect->ymin));
+}
+
+int BLI_in_rcti(rcti * rect, int x, int y)
+{
+
+ if(x<rect->xmin) return 0;
+ if(x>rect->xmax) return 0;
+ if(y<rect->ymin) return 0;
+ if(y>rect->ymax) return 0;
+ return 1;
+}
+
+int BLI_in_rctf(rctf *rect, float x, float y)
+{
+
+ if(x<rect->xmin) return 0;
+ if(x>rect->xmax) return 0;
+ if(y<rect->ymin) return 0;
+ if(y>rect->ymax) return 0;
+ return 1;
+}
+
+void BLI_union_rctf(rctf *rct1, rctf *rct2)
+{
+
+ if(rct1->xmin>rct2->xmin) rct1->xmin= rct2->xmin;
+ if(rct1->xmax<rct2->xmax) rct1->xmax= rct2->xmax;
+ if(rct1->ymin>rct2->ymin) rct1->ymin= rct2->ymin;
+ if(rct1->ymax<rct2->ymax) rct1->ymax= rct2->ymax;
+}
+
+void BLI_init_rctf(rctf *rect, float xmin, float xmax, float ymin, float ymax)
+{
+ rect->xmin= xmin;
+ rect->xmax= xmax;
+ rect->ymin= ymin;
+ rect->ymax= ymax;
+}
+
+int BLI_isect_rctf(rctf *src1, rctf *src2, rctf *dest)
+{
+ float xmin, xmax;
+ float ymin, ymax;
+
+ xmin = (src1->xmin) > (src2->xmin) ? (src1->xmin) : (src2->xmin);
+ xmax = (src1->xmax) < (src2->xmax) ? (src1->xmax) : (src2->xmax);
+ ymin = (src1->ymin) > (src2->ymin) ? (src1->ymin) : (src2->ymin);
+ ymax = (src1->ymax) < (src2->ymax) ? (src1->ymax) : (src2->ymax);
+
+ if(xmax>=xmin && ymax>=ymin) {
+ if(dest) {
+ dest->xmin = xmin;
+ dest->xmax = xmax;
+ dest->ymin = ymin;
+ dest->ymax = ymax;
+ }
+ return 1;
+ }
+ else {
+ if(dest) {
+ dest->xmin = 0;
+ dest->xmax = 0;
+ dest->ymin = 0;
+ dest->ymax = 0;
+ }
+ return 0;
+ }
+}
diff --git a/source/blender/blenlib/intern/scanfill.c b/source/blender/blenlib/intern/scanfill.c
new file mode 100644
index 00000000000..a6a1771148f
--- /dev/null
+++ b/source/blender/blenlib/intern/scanfill.c
@@ -0,0 +1,1234 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * (uit traces) maart 95
+ */
+
+#include <stdio.h>
+#include <math.h>
+#include <stdlib.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+
+#include "BLI_util.h"
+#include "DNA_listBase.h"
+#include "BLI_editVert.h"
+#include "BLI_arithb.h"
+#include "BLI_scanfill.h"
+#include "BLI_callbacks.h"
+
+/* callbacks for errors and interrupts and some goo */
+static void (*BLI_localErrorCallBack)(char*) = NULL;
+static int (*BLI_localInterruptCallBack)(void) = NULL;
+static void *objectref = NULL;
+static char *colourref = NULL;
+
+
+void BLI_setScanFillObjectRef(void* ob)
+{
+ objectref = ob;
+}
+
+void BLI_setScanFillColourRef(char* c)
+{
+ colourref = c;
+}
+
+void BLI_setErrorCallBack(void (*f)(char*))
+{
+ BLI_localErrorCallBack = f;
+}
+
+void BLI_setInterruptCallBack(int (*f)(void))
+{
+ BLI_localInterruptCallBack = f;
+}
+
+/* just flush the error to /dev/null if the error handler is missing */
+void callLocalErrorCallBack(char* msg)
+{
+ if (BLI_localErrorCallBack) {
+ BLI_localErrorCallBack(msg);
+ }
+}
+
+/* ignore if the interrupt wasn't set */
+int callLocalInterruptCallBack(void)
+{
+ if (BLI_localInterruptCallBack) {
+ return BLI_localInterruptCallBack();
+ } else {
+ return 0;
+ }
+}
+
+
+/* local types */
+typedef struct PolyFill {
+ int edges,verts;
+ float min[3],max[3];
+ short f,nr;
+} PolyFill;
+
+typedef struct ScFillVert {
+ EditVert *v1;
+ EditEdge *first,*last;
+ short f,f1;
+} ScFillVert;
+
+
+/* local funcs */
+int vergscdata(const void *a1, const void *a2);
+int vergpoly(const void *a1, const void *a2);
+void *new_mem_element(int size);
+void addfillvlak(EditVert *v1, EditVert *v2, EditVert *v3);
+int boundinside(PolyFill *pf1, PolyFill *pf2);
+int boundisect(PolyFill *pf2, PolyFill *pf1);
+void mergepolysSimp(PolyFill *pf1, PolyFill *pf2) /* pf2 bij pf1 */;
+EditEdge *existfilledge(EditVert *v1, EditVert *v2);
+short addedgetoscanvert(ScFillVert *sc, EditEdge *eed);
+short testedgeside(float *v1, float *v2, float *v3);
+short testedgeside2(float *v1, float *v2, float *v3);
+short boundinsideEV(EditEdge *eed, EditVert *eve) /* is eve binnen boundbox eed */;
+void testvertexnearedge(void);
+void scanfill(PolyFill *pf);
+void fill_mesh(void);
+ScFillVert *addedgetoscanlist(EditEdge *eed, int len);
+void splitlist(ListBase *tempve, ListBase *temped, short nr);
+
+/* This one is also used in isect.c Keep it here until we know what to do with isect.c */
+#define COMPLIMIT 0.0003
+
+ScFillVert *scdata;
+
+ListBase fillvertbase = {0,0};
+ListBase filledgebase = {0,0};
+ListBase fillvlakbase = {0,0};
+
+short cox, coy;
+
+/* **** FUNKTIES VOOR QSORT *************************** */
+
+
+int vergscdata(const void *a1, const void *a2)
+{
+ const ScFillVert *x1=a1,*x2=a2;
+
+ if( x1->v1->co[coy] < x2->v1->co[coy] ) return 1;
+ else if( x1->v1->co[coy] > x2->v1->co[coy]) return -1;
+ else if( x1->v1->co[cox] > x2->v1->co[cox] ) return 1;
+ else if( x1->v1->co[cox] < x2->v1->co[cox]) return -1;
+
+ return 0;
+}
+
+int vergpoly(const void *a1, const void *a2)
+{
+ const PolyFill *x1=a1, *x2=a2;
+
+ if( x1->min[cox] > x2->min[cox] ) return 1;
+ else if( x1->min[cox] < x2->min[cox] ) return -1;
+ else if( x1->min[coy] > x2->min[coy] ) return 1;
+ else if( x1->min[coy] < x2->min[coy] ) return -1;
+
+ return 0;
+}
+
+/* ************* MEMORY MANAGEMENT ************* */
+
+struct mem_elements {
+ struct mem_elements *next, *prev;
+ char *data;
+};
+
+void *new_mem_element(int size)
+{
+ /* Alleen als gedurende het werken duizenden elementen worden aangemaakt en
+ * nooit (tussendoor) vrijgegeven. Op eind is vrijgeven nodig (-1).
+ */
+ int blocksize= 16384;
+ static int offs= 0; /* het huidige vrije adres */
+ static struct mem_elements *cur= 0;
+ static ListBase lb= {0, 0};
+ void *adr;
+
+ if(size>10000 || size==0) {
+ printf("incorrect use of new_mem_element\n");
+ }
+ else if(size== -1) {
+ cur= lb.first;
+ while(cur) {
+ MEM_freeN(cur->data);
+ cur= cur->next;
+ }
+ BLI_freelistN(&lb);
+
+ return NULL;
+ }
+
+ size= 4*( (size+3)/4 );
+
+ if(cur) {
+ if(size+offs < blocksize) {
+ adr= (void *) (cur->data+offs);
+ offs+= size;
+ return adr;
+ }
+ }
+
+ cur= MEM_callocN( sizeof(struct mem_elements), "newmem");
+ cur->data= MEM_callocN(blocksize, "newmem");
+ BLI_addtail(&lb, cur);
+
+ offs= size;
+ return cur->data;
+}
+
+void BLI_end_edgefill(void)
+{
+ new_mem_element(-1);
+
+ fillvertbase.first= fillvertbase.last= 0;
+ filledgebase.first= filledgebase.last= 0;
+ fillvlakbase.first= fillvlakbase.last= 0;
+}
+
+/* **** FILL ROUTINES *************************** */
+
+EditVert *BLI_addfillvert(float *vec)
+{
+ EditVert *eve;
+
+ eve= new_mem_element(sizeof(EditVert));
+ BLI_addtail(&fillvertbase, eve);
+
+ if(vec) {
+ *(eve->co) = *(vec);
+ *(eve->co + 1) = *(vec + 1);
+ *(eve->co + 2) = *(vec + 2);
+ }
+/* VECCOPY(eve->co, vec); */
+
+ return eve;
+}
+
+EditEdge *BLI_addfilledge(EditVert *v1, EditVert *v2)
+{
+ EditEdge *newed;
+
+ newed= new_mem_element(sizeof(EditEdge));
+ BLI_addtail(&filledgebase, newed);
+
+ newed->v1= v1;
+ newed->v2= v2;
+
+ return newed;
+}
+
+void addfillvlak(EditVert *v1, EditVert *v2, EditVert *v3)
+{
+ /* maakt geen edges aan */
+ EditVlak *evl;
+
+ evl= new_mem_element(sizeof(EditVlak));
+ BLI_addtail(&fillvlakbase, evl);
+
+ evl->v1= v1;
+ evl->v2= v2;
+ evl->v3= v3;
+ evl->f= 2;
+ /* G.obedit is Object*, actcol is char */
+/* if(G.obedit && G.obedit->actcol) evl->mat_nr= G.obedit->actcol-1; */
+ if (objectref && colourref && *colourref) {
+ evl->mat_nr = *colourref - 1;
+ } else {
+ evl->mat_nr = 0;
+ }
+}
+
+
+int boundinside(PolyFill *pf1, PolyFill *pf2)
+{
+ /* is pf2 INSIDE pf1 ? met boundingbox */
+ /* eerst testen of poly's bestaan */
+
+ if(pf1->edges==0 || pf2->edges==0) return 0;
+
+ if(pf2->max[cox]<pf1->max[cox])
+ if(pf2->max[coy]<pf1->max[coy])
+ if(pf2->min[cox]>pf1->min[cox])
+ if(pf2->min[coy]>pf1->min[coy]) return 1;
+ return 0;
+}
+
+int boundisect(PolyFill *pf2, PolyFill *pf1)
+{
+ /* is pf2 aangeraakt door pf1 ? met boundingbox */
+ /* eerst testen of poly's bestaan */
+
+ if(pf1->edges==0 || pf2->edges==0) return 0;
+
+ if(pf2->max[cox] < pf1->min[cox] ) return 0;
+ if(pf2->max[coy] < pf1->min[coy] ) return 0;
+
+ if(pf2->min[cox] > pf1->max[cox] ) return 0;
+ if(pf2->min[coy] > pf1->max[coy] ) return 0;
+
+ /* samenvoegen */
+ if(pf2->max[cox]<pf1->max[cox]) pf2->max[cox]= pf1->max[cox];
+ if(pf2->max[coy]<pf1->max[coy]) pf2->max[coy]= pf1->max[coy];
+
+ if(pf2->min[cox]>pf1->min[cox]) pf2->min[cox]= pf1->min[cox];
+ if(pf2->min[coy]>pf1->min[coy]) pf2->min[coy]= pf1->min[coy];
+
+ return 1;
+}
+
+
+
+
+
+void mergepolysSimp(PolyFill *pf1, PolyFill *pf2) /* pf2 bij pf1 */
+/* PolyFill *pf1,*pf2; */
+{
+ EditVert *eve;
+ EditEdge *eed;
+
+ /* alle oude polynummers vervangen */
+ eve= fillvertbase.first;
+ while(eve) {
+ if(eve->xs== pf2->nr) eve->xs= pf1->nr;
+ eve= eve->next;
+ }
+ eed= filledgebase.first;
+ while(eed) {
+ if(eed->f1== pf2->nr) eed->f1= pf1->nr;
+ eed= eed->next;
+ }
+
+ pf1->verts+= pf2->verts;
+ pf1->edges+= pf2->edges;
+ pf2->verts= pf2->edges= 0;
+ pf1->f= (pf1->f | pf2->f);
+}
+
+
+
+EditEdge *existfilledge(EditVert *v1, EditVert *v2)
+/* EditVert *v1,*v2; */
+{
+ EditEdge *eed;
+
+ eed= filledgebase.first;
+ while(eed) {
+ if(eed->v1==v1 && eed->v2==v2) return eed;
+ if(eed->v2==v1 && eed->v1==v2) return eed;
+ eed= eed->next;
+ }
+ return 0;
+}
+
+
+short testedgeside(float *v1, float *v2, float *v3) /* is v3 rechts van v1-v2 ? Met uizondering: v3==v1 || v3==v2*/
+/* float *v1,*v2,*v3; */
+{
+ float inp;
+
+ inp= (v2[cox]-v1[cox])*(v1[coy]-v3[coy])
+ +(v1[coy]-v2[coy])*(v1[cox]-v3[cox]);
+
+ if(inp<0.0) return 0;
+ else if(inp==0) {
+ if(v1[cox]==v3[cox] && v1[coy]==v3[coy]) return 0;
+ if(v2[cox]==v3[cox] && v2[coy]==v3[coy]) return 0;
+ }
+ return 1;
+}
+
+short testedgeside2(float *v1, float *v2, float *v3) /* is v3 rechts van v1-v2 ? niet doorsnijden! */
+/* float *v1,*v2,*v3; */
+{
+ float inp;
+
+ inp= (v2[cox]-v1[cox])*(v1[coy]-v3[coy])
+ +(v1[coy]-v2[coy])*(v1[cox]-v3[cox]);
+
+ if(inp<=0.0) return 0;
+ return 1;
+}
+
+short addedgetoscanvert(ScFillVert *sc, EditEdge *eed)
+/* ScFillVert *sc; */
+/* EditEdge *eed; */
+{
+ /* zoek eerste edge die rechts van eed ligt en stop eed daarvoor */
+ EditEdge *ed;
+ float fac,fac1,x,y;
+
+ if(sc->first==0) {
+ sc->first= sc->last= eed;
+ eed->prev= eed->next=0;
+ return 1;
+ }
+
+ x= eed->v1->co[cox];
+ y= eed->v1->co[coy];
+
+ fac1= eed->v2->co[coy]-y;
+ if(fac1==0.0) {
+ fac1= 1.0e10*(eed->v2->co[cox]-x);
+
+ }
+ else fac1= (x-eed->v2->co[cox])/fac1;
+
+ ed= sc->first;
+ while(ed) {
+
+ if(ed->v2==eed->v2) return 0;
+
+ fac= ed->v2->co[coy]-y;
+ if(fac==0.0) {
+ fac= 1.0e10*(ed->v2->co[cox]-x);
+
+ }
+ else fac= (x-ed->v2->co[cox])/fac;
+ if(fac>fac1) break;
+
+ ed= ed->next;
+ }
+ if(ed) BLI_insertlinkbefore((ListBase *)&(sc->first), ed, eed);
+ else BLI_addtail((ListBase *)&(sc->first),eed);
+
+ return 1;
+}
+
+
+ScFillVert *addedgetoscanlist(EditEdge *eed, int len)
+/* EditEdge *eed; */
+/* int len; */
+{
+ /* voegt edge op juiste plek in ScFillVert list */
+ /* geeft sc terug als edge al bestaat */
+ ScFillVert *sc,scsearch;
+ EditVert *eve;
+
+ /* welke vert is linksboven */
+ if(eed->v1->co[coy] == eed->v2->co[coy]) {
+ if(eed->v1->co[cox] > eed->v2->co[cox]) {
+ eve= eed->v1;
+ eed->v1= eed->v2;
+ eed->v2= eve;
+ }
+ }
+ else if(eed->v1->co[coy] < eed->v2->co[coy]) {
+ eve= eed->v1;
+ eed->v1= eed->v2;
+ eed->v2= eve;
+ }
+ /* zoek plek in lijst */
+ scsearch.v1= eed->v1;
+ sc= (ScFillVert *)bsearch(&scsearch,scdata,len,
+ sizeof(ScFillVert), vergscdata);
+
+ if(sc==0) printf("Error in search edge: %x\n",eed);
+ else if(addedgetoscanvert(sc,eed)==0) return sc;
+
+ return 0;
+}
+
+short boundinsideEV(EditEdge *eed, EditVert *eve) /* is eve binnen boundbox eed */
+/* EditEdge *eed; */
+/* EditVert *eve; */
+{
+ float minx,maxx,miny,maxy;
+
+ if(eed->v1->co[cox]<eed->v2->co[cox]) {
+ minx= eed->v1->co[cox];
+ maxx= eed->v2->co[cox];
+ } else {
+ minx= eed->v2->co[cox];
+ maxx= eed->v1->co[cox];
+ }
+ if(eve->co[cox]>=minx && eve->co[cox]<=maxx) {
+ if(eed->v1->co[coy]<eed->v2->co[coy]) {
+ miny= eed->v1->co[coy];
+ maxy= eed->v2->co[coy];
+ } else {
+ miny= eed->v2->co[coy];
+ maxy= eed->v1->co[coy];
+ }
+ if(eve->co[coy]>=miny && eve->co[coy]<=maxy) return 1;
+ }
+ return 0;
+}
+
+
+void testvertexnearedge(void)
+{
+ /* alleen de vertices met ->h==1 worden getest op
+ nabijheid van edge, zo ja invoegen */
+
+ EditVert *eve;
+ EditEdge *eed,*ed1;
+ float dist,vec1[2],vec2[2],vec3[2];
+
+ eve= fillvertbase.first;
+ while(eve) {
+ if(eve->h==1) {
+ vec3[0]= eve->co[cox];
+ vec3[1]= eve->co[coy];
+ /* de bewuste edge vinden waar eve aan zit */
+ ed1= filledgebase.first;
+ while(ed1) {
+ if(ed1->v1==eve || ed1->v2==eve) break;
+ ed1= ed1->next;
+ }
+ if(ed1->v1==eve) {
+ ed1->v1= ed1->v2;
+ ed1->v2= eve;
+ }
+ eed= filledgebase.first;
+ while(eed) {
+ if(eve!=eed->v1 && eve!=eed->v2 && eve->xs==eed->f1) {
+ if(FloatCompare(eve->co,eed->v1->co, COMPLIMIT)) {
+ ed1->v2= eed->v1;
+ eed->v1->h++;
+ eve->h= 0;
+ break;
+ }
+ else if(FloatCompare(eve->co,eed->v2->co, COMPLIMIT)) {
+ ed1->v2= eed->v2;
+ eed->v2->h++;
+ eve->h= 0;
+ break;
+ }
+ else {
+ vec1[0]= eed->v1->co[cox];
+ vec1[1]= eed->v1->co[coy];
+ vec2[0]= eed->v2->co[cox];
+ vec2[1]= eed->v2->co[coy];
+ if(boundinsideEV(eed,eve)) {
+ dist= DistVL2Dfl(vec1,vec2,vec3);
+ if(dist<COMPLIMIT) {
+ /* nieuwe edge */
+ ed1= BLI_addfilledge(eed->v1, eve);
+
+ /* printf("fill: vertex near edge %x\n",eve); */
+ ed1->f= ed1->h= 0;
+ ed1->f1= eed->f1;
+ eed->v1= eve;
+ eve->h= 3;
+ break;
+ }
+ }
+ }
+ }
+ eed= eed->next;
+ }
+ }
+ eve= eve->next;
+ }
+}
+
+void splitlist(ListBase *tempve, ListBase *temped, short nr)
+/* ListBase *tempve,*temped; */
+/* short nr; */
+{
+ /* alles zit in de templist, alleen poly nr naar fillist schrijven */
+ EditVert *eve,*nextve;
+ EditEdge *eed,*nexted;
+
+ addlisttolist(tempve,&fillvertbase);
+ addlisttolist(temped,&filledgebase);
+
+ eve= tempve->first;
+ while(eve) {
+ nextve= eve->next;
+ if(eve->xs==nr) {
+ BLI_remlink(tempve,eve);
+ BLI_addtail(&fillvertbase,eve);
+ }
+ eve= nextve;
+ }
+ eed= temped->first;
+ while(eed) {
+ nexted= eed->next;
+ if(eed->f1==nr) {
+ BLI_remlink(temped,eed);
+ BLI_addtail(&filledgebase,eed);
+ }
+ eed= nexted;
+ }
+}
+
+
+void scanfill(PolyFill *pf)
+{
+ ScFillVert *sc = NULL, *sc1;
+ EditVert *eve,*v1,*v2,*v3;
+ EditEdge *eed,*nexted,*ed1,*ed2,*ed3;
+ float miny = 0.0;
+ int a,b,verts, maxvlak, totvlak;
+ short nr, test, twoconnected=0;
+
+ nr= pf->nr;
+ verts= pf->verts;
+
+ /* PRINTS
+ eve= fillvertbase.first;
+ while(eve) {
+ printf("vert: %x co: %f %f\n",eve,eve->co[cox],eve->co[coy]);
+ eve= eve->next;
+ }
+ eed= filledgebase.first;
+ while(eed) {
+ printf("edge: %x verts: %x %x\n",eed,eed->v1,eed->v2);
+ eed= eed->next;
+ } */
+
+ /* STAP 0: alle nul lange edges eruit */
+ eed= filledgebase.first;
+ while(eed) {
+ if(eed->v1->co[cox]==eed->v2->co[cox]) {
+ if(eed->v1->co[coy]==eed->v2->co[coy]) {
+ if(eed->v1->f==255 && eed->v2->f!=255) {
+ eed->v2->f= 255;
+ eed->v2->vn= eed->v1->vn;
+ }
+ else if(eed->v2->f==255 && eed->v1->f!=255) {
+ eed->v1->f= 255;
+ eed->v1->vn= eed->v2->vn;
+ }
+ else if(eed->v2->f==255 && eed->v1->f==255) {
+ eed->v1->vn= eed->v2->vn;
+ }
+ else {
+ eed->v2->f= 255;
+ eed->v2->vn= eed->v1;
+ }
+ }
+ }
+ eed= eed->next;
+ }
+
+ /* STAP 1: maak ahv van FillVert en FillEdge lijsten een gesorteerde
+ ScFillVert lijst
+ */
+ sc= scdata= (ScFillVert *)MEM_callocN(pf->verts*sizeof(ScFillVert),"Scanfill1");
+ eve= fillvertbase.first;
+ verts= 0;
+ while(eve) {
+ if(eve->xs==nr) {
+ if(eve->f!= 255) {
+ verts++;
+ eve->f= 0; /* vlag later voor connectedges */
+ sc->v1= eve;
+ sc++;
+ }
+ }
+ eve= eve->next;
+ }
+
+ qsort(scdata, verts, sizeof(ScFillVert), vergscdata);
+
+ sc= scdata;
+ eed= filledgebase.first;
+ while(eed) {
+ nexted= eed->next;
+ eed->f= 0;
+ BLI_remlink(&filledgebase,eed);
+ if(eed->v1->f==255) {
+ v1= eed->v1;
+ while(eed->v1->f==255 && eed->v1->vn!=v1) eed->v1= eed->v1->vn;
+ }
+ if(eed->v2->f==255) {
+ v2= eed->v2;
+ while(eed->v2->f==255 && eed->v2->vn!=v2) eed->v2= eed->v2->vn;
+ }
+ if(eed->v1!=eed->v2) addedgetoscanlist(eed,verts);
+
+ eed= nexted;
+ }
+ /*
+ sc= scdata;
+ for(a=0;a<verts;a++) {
+ printf("\nscvert: %x\n",sc->v1);
+ eed= sc->first;
+ while(eed) {
+ printf(" ed %x %x %x\n",eed,eed->v1,eed->v2);
+ eed= eed->next;
+ }
+ sc++;
+ }*/
+
+
+ /* STAP 2: FILL LUS */
+
+ if(pf->f==0) twoconnected= 1;
+
+ /* (tijdelijke) beveiliging: nooit veel meer vlakken dan vertices */
+ totvlak= 0;
+ maxvlak= 2*verts; /* 2*verts: cirkel in driehoek, beide gevuld */
+
+ sc= scdata;
+ for(a=0;a<verts;a++) {
+ /* printf("VERTEX %d %x\n",a,sc->v1); */
+ ed1= sc->first;
+ while(ed1) { /* connectflags zetten */
+ nexted= ed1->next;
+ if(ed1->v1->h==1 || ed1->v2->h==1) {
+ BLI_remlink((ListBase *)&(sc->first),ed1);
+ BLI_addtail(&filledgebase,ed1);
+ if(ed1->v1->h>1) ed1->v1->h--;
+ if(ed1->v2->h>1) ed1->v2->h--;
+ }
+ else ed1->v2->f= 1;
+
+ ed1= nexted;
+ }
+ while(sc->first) { /* zolang er edges zijn */
+ ed1= sc->first;
+ ed2= ed1->next;
+
+ if(callLocalInterruptCallBack()) break;
+ if(totvlak>maxvlak) {
+ /* printf("Fill error: endless loop. Escaped at vert %d, tot: %d.\n", a, verts); */
+ a= verts;
+ break;
+ }
+ if(ed2==0) {
+ sc->first=sc->last= 0;
+ /* printf("maar 1 edge aan vert\n"); */
+ BLI_addtail(&filledgebase,ed1);
+ ed1->v2->f= 0;
+ ed1->v1->h--;
+ ed1->v2->h--;
+ } else {
+ /* test rest vertices */
+ v1= ed1->v2;
+ v2= ed1->v1;
+ v3= ed2->v2;
+ /* hieronder komt voor bij serie overlappende edges */
+ if(v1==v2 || v2==v3) break;
+ /* printf("test verts %x %x %x\n",v1,v2,v3); */
+ miny = ( (v1->co[coy])<(v3->co[coy]) ? (v1->co[coy]) : (v3->co[coy]) );
+/* miny= MIN2(v1->co[coy],v3->co[coy]); */
+ sc1= sc+1;
+ test= 0;
+
+ for(b=a+1;b<verts;b++) {
+ if(sc1->v1->f==0) {
+ if(sc1->v1->co[coy] <= miny) break;
+
+ if(testedgeside(v1->co,v2->co,sc1->v1->co))
+ if(testedgeside(v2->co,v3->co,sc1->v1->co))
+ if(testedgeside(v3->co,v1->co,sc1->v1->co)) {
+ /* punt in driehoek */
+
+ test= 1;
+ break;
+ }
+ }
+ sc1++;
+ }
+ if(test) {
+ /* nieuwe edge maken en overnieuw beginnen */
+ /* printf("add new edge %x %x and start again\n",v2,sc1->v1); */
+
+ ed3= BLI_addfilledge(v2, sc1->v1);
+ BLI_remlink(&filledgebase, ed3);
+ BLI_insertlinkbefore((ListBase *)&(sc->first), ed2, ed3);
+ ed3->v2->f= 1;
+ ed3->f= 2;
+ ed3->v1->h++;
+ ed3->v2->h++;
+ }
+ else {
+ /* nieuwe driehoek */
+ /* printf("add vlak %x %x %x\n",v1,v2,v3); */
+ addfillvlak(v1, v2, v3);
+ totvlak++;
+ BLI_remlink((ListBase *)&(sc->first),ed1);
+ BLI_addtail(&filledgebase,ed1);
+ ed1->v2->f= 0;
+ ed1->v1->h--;
+ ed1->v2->h--;
+ /* ed2 mag ook weg als het een oude is */
+ if(ed2->f==0 && twoconnected) {
+ BLI_remlink((ListBase *)&(sc->first),ed2);
+ BLI_addtail(&filledgebase,ed2);
+ ed2->v2->f= 0;
+ ed2->v1->h--;
+ ed2->v2->h--;
+ }
+
+ /* nieuwe edge */
+ ed3= BLI_addfilledge(v1, v3);
+ BLI_remlink(&filledgebase, ed3);
+ ed3->f= 2;
+ ed3->v1->h++;
+ ed3->v2->h++;
+
+ /* printf("add new edge %x %x\n",v1,v3); */
+ sc1= addedgetoscanlist(ed3, verts);
+
+ if(sc1) { /* ed3 bestaat al: verwijderen*/
+ /* printf("Edge bestaat al\n"); */
+ ed3->v1->h--;
+ ed3->v2->h--;
+
+ if(twoconnected) ed3= sc1->first;
+ else ed3= 0;
+ while(ed3) {
+ if( (ed3->v1==v1 && ed3->v2==v3) || (ed3->v1==v3 && ed3->v2==v1) ) {
+ BLI_remlink((ListBase *)&(sc1->first),ed3);
+ BLI_addtail(&filledgebase,ed3);
+ ed3->v1->h--;
+ ed3->v2->h--;
+ break;
+ }
+ ed3= ed3->next;
+ }
+ }
+
+ }
+ }
+ /* test op loze edges */
+ ed1= sc->first;
+ while(ed1) {
+ nexted= ed1->next;
+ if(ed1->v1->h<2 || ed1->v2->h<2) {
+ BLI_remlink((ListBase *)&(sc->first),ed1);
+ BLI_addtail(&filledgebase,ed1);
+ if(ed1->v1->h>1) ed1->v1->h--;
+ if(ed1->v2->h>1) ed1->v2->h--;
+ }
+
+ ed1= nexted;
+ }
+ }
+ sc++;
+ }
+
+ MEM_freeN(scdata);
+}
+
+
+
+int BLI_edgefill(int mode) /* DE HOOFD FILL ROUTINE */
+{
+ /*
+ - fill werkt met eigen lijsten, eerst aanmaken dus (geen vlakken)
+ - geef vertices in ->vn de oude pointer mee
+ - alleen xs en ys worden hier niet gebruikt: daar kan je iets in verstoppen
+ - edge flag ->f wordt 2 als het nieuwe edge betreft
+ - mode: & 1 is kruispunten testen, edges maken (NOG DOEN )
+ */
+ ListBase tempve, temped;
+ EditVert *eve;
+ EditEdge *eed,*nexted;
+ PolyFill *pflist,*pf;
+ float *minp, *maxp, *v1, *v2, norm[3], len;
+ short a,c,poly=0,ok=0,toggle=0;
+
+ /* variabelen resetten*/
+ eve= fillvertbase.first;
+ while(eve) {
+ eve->f= 0;
+ eve->xs= 0;
+ eve->h= 0;
+ eve= eve->next;
+ }
+
+ /* eerst de vertices testen op aanwezigheid in edges */
+ /* plus flaggen resetten */
+ eed= filledgebase.first;
+ while(eed) {
+ eed->f= eed->f1= eed->h= 0;
+ eed->v1->f= 1;
+ eed->v2->f= 1;
+
+ eed= eed->next;
+ }
+
+ eve= fillvertbase.first;
+ while(eve) {
+ if(eve->f & 1) {
+ ok=1;
+ break;
+ }
+ eve= eve->next;
+ }
+
+ if(ok==0) return 0;
+
+ /* NEW NEW! projektie bepalen: met beste normaal */
+ /* pak de eerste drie verschillende verts */
+
+ /* DIT STUK IS NOG STEEDS TAMELIJK ZWAK! */
+
+ eve= fillvertbase.last;
+ len= 0.0;
+ v1= eve->co;
+ v2= 0;
+ eve= fillvertbase.first;
+ while(eve) {
+ if(v2) {
+ if( FloatCompare(v2, eve->co, 0.0003)==0) {
+ len= CalcNormFloat(v1, v2, eve->co, norm);
+ if(len != 0.0) break;
+ }
+ }
+ else if(FloatCompare(v1, eve->co, 0.0003)==0) {
+ v2= eve->co;
+ }
+ eve= eve->next;
+ }
+
+ if(len==0.0) return 0; /* geen fill mogelijk */
+
+ norm[0]= fabs(norm[0]);
+ norm[1]= fabs(norm[1]);
+ norm[2]= fabs(norm[2]);
+
+ if(norm[2]>=norm[0] && norm[2]>=norm[1]) {
+ cox= 0; coy= 1;
+ }
+ else if(norm[1]>=norm[0] && norm[1]>=norm[2]) {
+ cox= 0; coy= 2;
+ }
+ else {
+ cox= 1; coy= 2;
+ }
+
+ /* STAP 1: AANTAL POLY'S TELLEN */
+ eve= fillvertbase.first;
+ while(eve) {
+ /* pak eerste vertex zonder polynummer */
+ if(eve->xs==0) {
+ poly++;
+ /* nu een soort select connected */
+ ok= 1;
+ eve->xs= poly;
+
+ while(ok) {
+
+ ok= 0;
+ toggle++;
+ if(toggle & 1) eed= filledgebase.first;
+ else eed= filledgebase.last;
+
+ while(eed) {
+ if(eed->v1->xs==0 && eed->v2->xs==poly) {
+ eed->v1->xs= poly;
+ eed->f1= poly;
+ ok= 1;
+ }
+ else if(eed->v2->xs==0 && eed->v1->xs==poly) {
+ eed->v2->xs= poly;
+ eed->f1= poly;
+ ok= 1;
+ }
+ else if(eed->f1==0) {
+ if(eed->v1->xs==poly && eed->v2->xs==poly) {
+ eed->f1= poly;
+ ok= 1;
+ }
+ }
+ if(toggle & 1) eed= eed->next;
+ else eed= eed->prev;
+ }
+ }
+ }
+ eve= eve->next;
+ }
+ /* printf("aantal poly's: %d\n",poly); */
+
+ /* STAP 2: LOSSE EDGES EN SLIERTEN VERWIJDEREN */
+ eed= filledgebase.first;
+ while(eed) {
+ if(eed->v1->h++ >250) break;
+ if(eed->v2->h++ >250) break;
+ eed= eed->next;
+ }
+ if(eed) {
+ /* anders kan hierna niet met zekerheid vertices worden gewist */
+ callLocalErrorCallBack("No vertices with 250 edges allowed!");
+ return 0;
+ }
+
+ /* doet alleen vertices met ->h==1 */
+ testvertexnearedge();
+
+ ok= 1;
+ while(ok) {
+ ok= 0;
+ toggle++;
+ if(toggle & 1) eed= filledgebase.first;
+ else eed= filledgebase.last;
+ while(eed) {
+ if(toggle & 1) nexted= eed->next;
+ else nexted= eed->prev;
+ if(eed->v1->h==1) {
+ eed->v2->h--;
+ BLI_remlink(&fillvertbase,eed->v1);
+ BLI_remlink(&filledgebase,eed);
+ ok= 1;
+ }
+ else if(eed->v2->h==1) {
+ eed->v1->h--;
+ BLI_remlink(&fillvertbase,eed->v2);
+ BLI_remlink(&filledgebase,eed);
+ ok= 1;
+ }
+ eed= nexted;
+ }
+ }
+ if(filledgebase.first==0) {
+ /* printf("All edges removed\n"); */
+ return 0;
+ }
+
+
+ /* STAND VAN ZAKEN:
+ - eve->f :1= aanwezig in edges
+ - eve->xs :polynummer
+ - eve->h :aantal edges aan vertex
+ - eve->vn :bewaren! oorspronkelijke vertexnummer
+
+ - eed->f :
+ - eed->f1 :polynummer
+*/
+
+
+ /* STAP 3: POLYFILL STRUCT MAKEN */
+ pflist= (PolyFill *)MEM_callocN(poly*sizeof(PolyFill),"edgefill");
+ pf= pflist;
+ for(a=1;a<=poly;a++) {
+ pf->nr= a;
+ pf->min[0]=pf->min[1]=pf->min[2]= 1.0e20;
+ pf->max[0]=pf->max[1]=pf->max[2]= -1.0e20;
+ pf++;
+ }
+ eed= filledgebase.first;
+ while(eed) {
+ pflist[eed->f1-1].edges++;
+ eed= eed->next;
+ }
+
+ eve= fillvertbase.first;
+ while(eve) {
+ pflist[eve->xs-1].verts++;
+ minp= pflist[eve->xs-1].min;
+ maxp= pflist[eve->xs-1].max;
+
+ minp[cox]= (minp[cox])<(eve->co[cox]) ? (minp[cox]) : (eve->co[cox]);
+ minp[coy]= (minp[coy])<(eve->co[coy]) ? (minp[coy]) : (eve->co[coy]);
+ maxp[cox]= (maxp[cox])>(eve->co[cox]) ? (maxp[cox]) : (eve->co[cox]);
+ maxp[coy]= (maxp[coy])>(eve->co[coy]) ? (maxp[coy]) : (eve->co[coy]);
+ if(eve->h>2) pflist[eve->xs-1].f= 1;
+
+ eve= eve->next;
+ }
+
+ /* STAP 4: GATEN OF BOUNDS VINDEN EN SAMENVOEGEN
+ * ( bounds alleen om grote hoeveelheden een beetje in stukjes te verdelen,
+ * de edgefill heeft van zichzelf een adequate autogat!!!
+ * LET OP: WERKT ALLEEN ALS POLY'S GESORTEERD ZIJN!!! */
+
+ if(poly>1) {
+ short *polycache, *pc;
+
+ /* dus: eerst sorteren */
+ qsort(pflist, poly, sizeof(PolyFill), vergpoly);
+
+ /*pf= pflist;
+ for(a=1;a<=poly;a++) {
+ printf("poly:%d edges:%d verts:%d flag: %d\n",a,pf->edges,pf->verts,pf->f);
+ PRINT2(f, f, pf->min[0], pf->min[1]);
+ pf++;
+ }*/
+
+ polycache= pc= MEM_callocN(sizeof(short)*poly, "polycache");
+ pf= pflist;
+ for(a=0; a<poly; a++, pf++) {
+ for(c=a+1;c<poly;c++) {
+
+ /* als 'a' inside 'c': samenvoegen (ook bbox)
+ * Pas Op: 'a' kan ook inside andere poly zijn.
+ */
+ if(boundisect(pf, pflist+c)) {
+ *pc= c;
+ pc++;
+ }
+ /* alleen voor opt! */
+ /* else if(pf->max[cox] < (pflist+c)->min[cox]) break; */
+
+ }
+ while(pc!=polycache) {
+ pc--;
+ mergepolysSimp(pf, pflist+ *pc);
+ }
+ }
+ MEM_freeN(polycache);
+ }
+
+ pf= pflist;
+ /* printf("na merge\n");
+ for(a=1;a<=poly;a++) {
+ printf("poly:%d edges:%d verts:%d flag: %d\n",a,pf->edges,pf->verts,pf->f);
+ pf++;
+ } */
+
+ /* STAP 5: DRIEHOEKEN MAKEN */
+
+ tempve.first= fillvertbase.first;
+ tempve.last= fillvertbase.last;
+ temped.first= filledgebase.first;
+ temped.last= filledgebase.last;
+ fillvertbase.first=fillvertbase.last= 0;
+ filledgebase.first=filledgebase.last= 0;
+
+ pf= pflist;
+ for(a=0;a<poly;a++) {
+ if(pf->edges>1) {
+ splitlist(&tempve,&temped,pf->nr);
+ scanfill(pf);
+ }
+ pf++;
+ }
+ addlisttolist(&fillvertbase,&tempve);
+ addlisttolist(&filledgebase,&temped);
+
+ /* evl= fillvlakbase.first;
+ while(evl) {
+ printf("nieuw vlak %x %x %x\n",evl->v1,evl->v2,evl->v3);
+ evl= evl->next;
+ }*/
+
+
+ /* VRIJGEVEN */
+
+ MEM_freeN(pflist);
+ return 1;
+
+}
+
+/*
+ MOVED TO EDITMESH.C since it's really bad to leave it here
+
+void fill_mesh(void)
+{
+ EditVert *eve,*v1;
+ EditEdge *eed,*e1,*nexted;
+ EditVlak *evl,*nextvl;
+ short ok;
+
+ if(G.obedit==0 || (G.obedit->type!=OB_MESH)) return;
+
+ waitcursor(1);
+
+ / * alle selected vertices kopieeren * /
+ eve= G.edve.first;
+ while(eve) {
+ if(eve->f & 1) {
+ v1= addfillvert(eve->co);
+ eve->vn= v1;
+ v1->vn= eve;
+ v1->h= 0;
+ }
+ eve= eve->next;
+ }
+ / * alle selected edges kopieeren * /
+ eed= G.eded.first;
+ while(eed) {
+ if( (eed->v1->f & 1) && (eed->v2->f & 1) ) {
+ e1= addfilledge(eed->v1->vn, eed->v2->vn);
+ e1->v1->h++;
+ e1->v2->h++;
+ }
+ eed= eed->next;
+ }
+ / * van alle selected vlakken vertices en edges verwijderen om dubbels te voorkomen * /
+ / * alle edges tellen punten op, vlakken trekken af,
+ edges met vertices ->h<2 verwijderen * /
+ evl= G.edvl.first;
+ ok= 0;
+ while(evl) {
+ nextvl= evl->next;
+ if( vlakselectedAND(evl, 1) ) {
+ evl->v1->vn->h--;
+ evl->v2->vn->h--;
+ evl->v3->vn->h--;
+ if(evl->v4) evl->v4->vn->h--;
+ ok= 1;
+
+ }
+ evl= nextvl;
+ }
+ if(ok) { / * er zijn vlakken geselecteerd * /
+ eed= filledgebase.first;
+ while(eed) {
+ nexted= eed->next;
+ if(eed->v1->h<2 || eed->v2->h<2) {
+ remlink(&filledgebase,eed);
+ }
+ eed= nexted;
+ }
+ }
+
+ / * tijd=clock(); * /
+
+ ok= edgefill(0);
+
+ / * printf("time: %d\n",(clock()-tijd)/1000); * /
+
+ if(ok) {
+ evl= fillvlakbase.first;
+ while(evl) {
+ addvlaklist(evl->v1->vn, evl->v2->vn, evl->v3->vn, 0, evl);
+ evl= evl->next;
+ }
+ }
+ / * else printf("fill error\n"); * /
+
+ end_edgefill();
+
+ waitcursor(0);
+
+ countall();
+ allqueue(REDRAWVIEW3D, 0);
+}
+
+MOVED TO editmesh.c !!!!! (you bastards!)
+
+ */
diff --git a/source/blender/blenlib/intern/storage.c b/source/blender/blenlib/intern/storage.c
new file mode 100644
index 00000000000..1f86fcbf54b
--- /dev/null
+++ b/source/blender/blenlib/intern/storage.c
@@ -0,0 +1,568 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * Reorganised mar-01 nzc
+ * Some really low-level file thingies.
+ */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h> /* voorkomt dat je bij malloc type moet aangeven */
+
+#ifdef WIN32
+
+#include <windows.h>
+#include "BLI_winstuff.h"
+#include <sys/types.h>
+#include <io.h>
+#include <direct.h>
+#endif
+
+#ifndef WIN32
+#include <dirent.h>
+#endif
+
+#include <time.h>
+#include <sys/stat.h>
+
+#if defined(__sgi) || defined(__sun__)
+#include <sys/statfs.h>
+#endif
+
+#ifdef __FreeBSD__
+#include <sys/param.h>
+#include <sys/mount.h>
+#endif
+
+#if defined(linux) || defined(__CYGWIN32__)
+#include <sys/vfs.h>
+#endif
+
+#ifdef __BeOS
+struct statfs {
+ int f_bsize;
+ int f_bfree;
+};
+#endif
+
+#ifdef __APPLE__
+/* For statfs */
+#include <sys/param.h>
+#include <sys/mount.h>
+#endif /* __APPLE__ */
+
+
+#include <fcntl.h>
+#if !defined(__BeOS) && !defined(WIN32)
+#include <sys/mtio.h> /* tape comando's */
+#endif
+#include <string.h> /* strcpy etc.. */
+
+#ifndef WIN32
+#include <sys/ioctl.h>
+#include <unistd.h> /* */
+#include <pwd.h>
+#endif
+
+/* MAART: #ifndef __FreeBSD__ */
+#if !defined(__FreeBSD__) && !defined(__APPLE__)
+#include <malloc.h>
+#endif
+
+/* lib includes */
+#include "MEM_guardedalloc.h"
+
+#include "DNA_listBase.h"
+#include "BLI_blenlib.h"
+#include "BLI_storage.h"
+#include "BLI_storage_types.h"
+
+#include "BLI_util.h"
+#include "BLI_linklist.h"
+
+/* functions */
+void BLI_buildpwtable(struct passwd **pwtable);
+void BLI_freepwtable(struct passwd *pwtable);
+char *BLI_findpwtable(struct passwd *pwtable, unsigned short user);
+
+/* vars: */
+static int totnum,actnum;
+static struct direntry *files;
+
+static struct ListBase dirbase_={
+ 0,0};
+static struct ListBase *dirbase = &dirbase_;
+
+
+char *BLI_getwdN(char *dir)
+{
+ char *pwd;
+
+ if (dir) {
+ pwd = getenv("PWD");
+ if (pwd){
+ strcpy(dir, pwd);
+ return(dir);
+ }
+ /* 160 is FILE_MAXDIR in filesel.c */
+ return( getcwd(dir, 160) );
+ }
+ return(0);
+}
+
+
+int BLI_compare(struct direntry *entry1, struct direntry *entry2)
+{
+ /* type is gelijk aan stat.st_mode */
+
+ if (S_ISDIR(entry1->type)){
+ if (S_ISDIR(entry2->type)==0) return (-1);
+ } else{
+ if (S_ISDIR(entry2->type)) return (1);
+ }
+ if (S_ISREG(entry1->type)){
+ if (S_ISREG(entry2->type)==0) return (-1);
+ } else{
+ if (S_ISREG(entry2->type)) return (1);
+ }
+ if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) return (-1);
+ if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1);
+ return (strcasecmp(entry1->relname,entry2->relname));
+}
+
+
+double BLI_diskfree(char *dir)
+{
+#ifdef WIN32
+ DWORD sectorspc, bytesps, freec, clusters;
+ char tmp[4];
+
+ tmp[0]='\\'; tmp[1]=0; /* Just a failsafe */
+ if (dir[0]=='/' || dir[0]=='\\') {
+ tmp[0]='\\';
+ tmp[1]=0;
+ } else if (dir[1]==':') {
+ tmp[0]=dir[0];
+ tmp[1]=':';
+ tmp[2]='\\';
+ tmp[3]=0;
+ }
+
+ GetDiskFreeSpace(tmp,&sectorspc, &bytesps, &freec, &clusters);
+
+ return (double) (freec*bytesps*sectorspc);
+#else
+ struct statfs disk;
+ char name[100],*slash;
+
+
+ strcpy(name,dir);
+
+ if(strlen(name)){
+ slash = strrchr(name,'/');
+ if (slash) slash[1] = 0;
+ } else strcpy(name,"/");
+
+#if defined __FreeBSD__ || defined linux
+ if (statfs(name, &disk)) return(-1);
+#endif
+#ifdef __BeOS
+ return -1;
+#endif
+#if defined __sgi || defined __sun__
+
+ if (statfs(name, &disk, sizeof(struct statfs), 0)){
+ /* printf("diskfree: Couldn't get information about %s.\n",dir); */
+ return(-1);
+ }
+#endif
+
+ return ( ((double) disk.f_bsize) * ((double) disk.f_bfree));
+#endif
+}
+
+static int hide_dot= 0;
+
+void BLI_hide_dot_files(int set)
+{
+ if(set) hide_dot= 1;
+ else hide_dot= 0;
+}
+
+void BLI_builddir(char *dirname, char *relname)
+{
+ struct dirent *fname;
+ struct dirlink *dlink;
+ int rellen, newnum = 0, seen_ = 0, seen__ = 0;
+ char buf[256];
+ DIR *dir;
+
+ strcpy(buf,relname);
+ rellen=strlen(relname);
+
+ if (rellen){
+ buf[rellen]='/';
+ rellen++;
+ }
+
+ if (chdir(dirname) == -1){
+ perror(dirname);
+ return;
+ }
+
+ if (dir = (DIR *)opendir(".")){
+ while ((fname = (struct dirent*) readdir(dir)) != NULL) {
+
+ if(hide_dot && fname->d_name[0]=='.' && fname->d_name[1]!='.' && fname->d_name[1]!=0);
+ else {
+
+ dlink = (struct dirlink *)malloc(sizeof(struct dirlink));
+ if (dlink){
+ strcpy(buf+rellen,fname->d_name);
+
+ dlink->name = strdup(buf);
+
+ if (dlink->name[0] == '.') {
+ if (dlink->name[1] == 0) seen_ = 1;
+ else if (dlink->name[1] == '.') {
+ if (dlink->name[2] == 0) seen__ = 1;
+ }
+ }
+ BLI_addhead(dirbase,dlink);
+ newnum++;
+ }
+ }
+ }
+
+ if (newnum){
+#ifndef WIN32
+ if (seen_ == 0) { /* Cachefs PATCH */
+ dlink = (struct dirlink *)malloc(sizeof(struct dirlink));
+ strcpy(buf+rellen,"./.");
+ dlink->name = strdup(buf);
+ BLI_addhead(dirbase,dlink);
+ newnum++;
+ }
+ if (seen__ == 0) { /* MAC PATCH */
+ dlink = (struct dirlink *)malloc(sizeof(struct dirlink));
+ strcpy(buf+rellen,"./..");
+ dlink->name = strdup(buf);
+ BLI_addhead(dirbase,dlink);
+ newnum++;
+ }
+#endif
+
+ if (files) files=(struct direntry *)realloc(files,(totnum+newnum) * sizeof(struct direntry));
+ else files=(struct direntry *)malloc(newnum * sizeof(struct direntry));
+
+ if (files){
+ dlink = (struct dirlink *) dirbase->first;
+ while(dlink){
+ memset(&files[actnum], 0 , sizeof(struct direntry));
+ files[actnum].relname = dlink->name;
+ stat(dlink->name,&files[actnum].s);
+ files[actnum].type=files[actnum].s.st_mode;
+ files[actnum].flags = 0;
+ totnum++;
+ actnum++;
+ dlink = dlink->next;
+ }
+ } else{
+ printf("Couldn't get memory for dir\n");
+ exit(1);
+ }
+
+ BLI_freelist(dirbase);
+ if (files) qsort(files, actnum, sizeof(struct direntry), (int (*)(const void *,const void*))BLI_compare);
+ } else {
+ printf("%s empty directory\n",dirname);
+ }
+
+ closedir(dir);
+ } else {
+ printf("%s non-existant directory\n",dirname);
+ }
+}
+
+#ifndef WIN32
+void BLI_buildpwtable(struct passwd **pwtable)
+{
+ int count=0,slen;
+ struct passwd *pw,*pwtab;
+
+ do{
+ pw=getpwent();
+ if (pw){
+ count++;
+ }
+ }while(pw);
+ endpwent();
+
+ pwtab = (struct passwd *)calloc(count+1,sizeof(struct passwd));
+ count=0;
+ do{
+ pw=getpwent();
+ if (pw){
+ pwtab[count] = *pw;
+ slen = strlen(pw->pw_name);
+ pwtab[count].pw_name = malloc(slen+1);
+ strcpy(pwtab[count].pw_name,pw->pw_name);
+ count ++;
+ }
+ }while(pw);
+ pwtab[count].pw_name = 0;
+ endpwent();
+
+ *(pwtable) = pwtab;
+}
+
+void BLI_freepwtable(struct passwd *pwtable)
+{
+ int count=0;
+
+ do{
+ if (pwtable[count].pw_name) free(pwtable[count].pw_name);
+ else break;
+ count++;
+ }while (1);
+
+ free(pwtable);
+}
+
+
+char *BLI_findpwtable(struct passwd *pwtable, ushort user)
+{
+ static char string[32];
+
+ while (pwtable->pw_name){
+ if (pwtable->pw_uid == user){
+ return (pwtable->pw_name);
+ }
+ pwtable++;
+ }
+ sprintf(string, "%d", user);
+ return (string);
+}
+#endif
+
+
+void BLI_adddirstrings()
+{
+ char datum[100];
+ char buf[250];
+ char size[250];
+ static char * types[8] = {"---", "--x", "-w-", "-wx", "r--", "r-x", "rw-", "rwx"};
+ int num, mode;
+ int num1, num2, num3, num4, st_size;
+#ifndef WIN32
+ struct passwd *pwtable;
+#endif
+ struct direntry * file;
+ struct tm *tm;
+
+#ifndef WIN32
+ BLI_buildpwtable(&pwtable);
+#endif
+
+ file = &files[0];
+
+ for(num=0;num<actnum;num++){
+#ifdef WIN32
+ mode = 0;
+ strcpy(file->mode1, types[0]);
+ strcpy(file->mode2, types[0]);
+ strcpy(file->mode3, types[0]);
+#else
+ mode = file->s.st_mode;
+
+ strcpy(file->mode1, types[(mode & 0700) >> 6]);
+ strcpy(file->mode2, types[(mode & 0070) >> 3]);
+ strcpy(file->mode3, types[(mode & 0007)]);
+
+ if (((mode & S_ISGID) == S_ISGID) && (file->mode2[2]=='-'))file->mode2[2]='l';
+
+ if (mode & (S_ISUID | S_ISGID)){
+ if (file->mode1[2]=='x') file->mode1[2]='s';
+ else file->mode1[2]='S';
+
+ if (file->mode2[2]=='x')file->mode2[2]='s';
+ }
+
+ if (mode & S_ISVTX){
+ if (file->mode3[2] == 'x') file->mode3[2] = 't';
+ else file->mode3[2] = 'T';
+ }
+#endif
+
+#ifdef WIN32
+ strcpy(files[num].owner,"user");
+#else
+ strcpy(files[num].owner, BLI_findpwtable(pwtable,files[num].s.st_uid));
+#endif
+
+ tm= localtime(&files[num].s.st_mtime);
+ strftime(files[num].time, 8, "%H:%M", tm);
+ strftime(files[num].date, 16, "%d-%b-%y", tm);
+
+ st_size= (int)files[num].s.st_size;
+
+ num1= st_size % 1000;
+ num2= st_size/1000;
+ num2= num2 % 1000;
+ num3= st_size/(1000*1000);
+ num3= num3 % 1000;
+ num4= st_size/(1000*1000*1000);
+ num4= num4 % 1000;
+
+ if(num4) sprintf(files[num].size, "%3d %03d %03d %03d", num4, num3, num2, num1);
+ else if(num3) sprintf(files[num].size, "%7d %03d %03d", num3, num2, num1);
+ else if(num2) sprintf(files[num].size, "%11d %03d", num2, num1);
+ else if(num1) sprintf(files[num].size, "%15d", num1);
+ else sprintf(files[num].size, "");
+
+ strftime(datum, 32, "%d-%b-%y %R", tm);
+
+ if (st_size < 1000) {
+ sprintf(size, "%10d", st_size);
+ } else if (st_size < 1000 * 1000) {
+ sprintf(size, "%6d %03d", st_size / 1000, st_size % 1000);
+ } else if (st_size < 100 * 1000 * 1000) {
+ sprintf(size, "%2d %03d %03d", st_size / (1000 * 1000), (st_size / 1000) % 1000, st_size % 1000);
+ } else {
+ sprintf(size, "> %4.1f M", st_size / (1024.0 * 1024.0));
+ sprintf(size, "%10d", st_size);
+ }
+
+ sprintf(buf,"%s %s %10s %s", files[num].date, files[num].time, size,
+ files[num].relname);
+
+ sprintf(buf,"%s %s %s %7s %s %s %10s %s", file->mode1, file->mode2, file->mode3, files[num].owner, files[num].date, files[num].time, size,
+ files[num].relname);
+
+ files[num].string=malloc(strlen(buf)+1);
+ if (files[num].string){
+ strcpy(files[num].string,buf);
+ }
+
+ file++;
+ }
+#ifndef WIN32
+ BLI_freepwtable(pwtable);
+#endif
+}
+
+unsigned int BLI_getdir(char *dirname, struct direntry **filelist)
+{
+ // reset global variables
+ // memory stored in files is free()'d in
+ // filesel.c:freefilelist()
+
+ actnum = totnum = 0;
+ files = 0;
+
+ BLI_builddir(dirname,"");
+ BLI_adddirstrings();
+
+ if (files) {
+ *(filelist) = files;
+ } else {
+ // keep blender happy. Blender stores this in a variable
+ // where 0 has special meaning.....
+ *(filelist) = files = malloc(sizeof(struct direntry));
+ }
+
+ return(actnum);
+}
+
+
+int BLI_filesize(int file)
+{
+ struct stat buf;
+
+ if (file <= 0) return (-1);
+ fstat(file, &buf);
+ return (buf.st_size);
+}
+
+
+
+int BLI_exist(char *name)
+{
+ struct stat st;
+
+ if (stat(name,&st)) return(0);
+ return(st.st_mode);
+}
+
+LinkNode *BLI_read_file_as_lines(char *name)
+{
+ FILE *fp= fopen(name, "r");
+ LinkNode *lines= NULL;
+ char *buf;
+ int size;
+
+ if (!fp) return NULL;
+
+ fseek(fp, 0, SEEK_END);
+ size= ftell(fp);
+ fseek(fp, 0, SEEK_SET);
+
+ buf= malloc(size);
+ if (buf) {
+ int i, last= 0;
+
+ /*
+ * size = because on win32 reading
+ * all the bytes in the file will return
+ * less bytes because of crnl changes.
+ */
+ size= fread(buf, 1, size, fp);
+ for (i=0; i<=size; i++) {
+ if (i==size || buf[i]=='\n') {
+ char *line= BLI_strdupn(&buf[last], i-last);
+
+ BLI_linklist_prepend(&lines, line);
+ last= i+1;
+ }
+ }
+
+ free(buf);
+ }
+
+ fclose(fp);
+
+ BLI_linklist_reverse(&lines);
+ return lines;
+}
+
+void BLI_free_file_lines(LinkNode *lines)
+{
+ BLI_linklist_free(lines, (void(*)(void*)) MEM_freeN);
+}
diff --git a/source/blender/blenlib/intern/time.c b/source/blender/blenlib/intern/time.c
new file mode 100644
index 00000000000..832a6c8b2e9
--- /dev/null
+++ b/source/blender/blenlib/intern/time.c
@@ -0,0 +1,101 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "PIL_time.h"
+
+#ifdef WIN32
+
+#include <windows.h>
+
+double PIL_check_seconds_timer(void)
+{
+ static int hasperfcounter= -1; /* -1==unknown */
+ static double perffreq;
+
+ if (hasperfcounter==-1) {
+ __int64 ifreq;
+ hasperfcounter= QueryPerformanceFrequency((LARGE_INTEGER*) &ifreq);
+ perffreq= (double) ifreq;
+ }
+
+ if (hasperfcounter) {
+ __int64 count;
+
+ QueryPerformanceCounter((LARGE_INTEGER*) &count);
+
+ return count/perffreq;
+ } else {
+ static double accum= 0.0;
+ static int ltick= 0;
+ int ntick= GetTickCount();
+
+ if (ntick<ltick) {
+ accum+= (0xFFFFFFFF-ltick+ntick)/1000.0;
+ } else {
+ accum+= (ntick-ltick)/1000.0;
+ }
+
+ ltick= ntick;
+ return accum;
+ }
+}
+
+void PIL_sleep_ms(int ms)
+{
+ Sleep(ms);
+}
+
+#else
+
+#include <unistd.h>
+#include <sys/time.h>
+
+double PIL_check_seconds_timer(void)
+{
+ struct timeval tv;
+ struct timezone tz;
+
+ gettimeofday(&tv, &tz);
+
+ return ((double) tv.tv_sec + tv.tv_usec/1000000.0);
+}
+
+void PIL_sleep_ms(int ms)
+{
+ if (ms>=1000) {
+ sleep(ms/1000);
+ ms= (ms%1000);
+ }
+
+ usleep(ms*1000);
+}
+
+#endif
diff --git a/source/blender/blenlib/intern/util.c b/source/blender/blenlib/intern/util.c
new file mode 100644
index 00000000000..f3a2d4f3970
--- /dev/null
+++ b/source/blender/blenlib/intern/util.c
@@ -0,0 +1,828 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * Diverse string, file, list operations.
+ */
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "DNA_listBase.h"
+#include "BLI_storage.h"
+#include "BLI_storage_types.h"
+
+#include "BLI_util.h"
+
+#ifndef WIN32
+#include <unistd.h>
+#else
+#include <io.h>
+#endif
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+
+#ifndef WIN32
+#include <sys/time.h>
+#endif
+
+/* local */
+
+static int add_win32_extension(char *name);
+
+/* implementation */
+
+/* Ripped this from blender.c
+ */
+void addlisttolist(ListBase *list1, ListBase *list2)
+{
+
+ if(list2->first==0) return;
+
+ if(list1->first==0) {
+ list1->first= list2->first;
+ list1->last= list2->last;
+ }
+ else {
+ ((struct Link *)list1->last)->next= list2->first;
+ ((struct Link *)list2->first)->prev= list1->last;
+ list1->last= list2->last;
+ }
+ list2->first= list2->last= 0;
+}
+
+int BLI_stringdec(char *string, char *kop, char *staart, unsigned short *numlen)
+{
+ unsigned short len, len2, nums = 0, nume = 0;
+ short i, found = 0;
+
+ len2 = len = strlen( string);
+
+ if (len > 6) {
+ if (strncasecmp(string + len - 6, ".blend", 6) == 0) len -= 6;
+ else if (strncasecmp(string + len - 6, ".trace", 6) == 0) len -= 6;
+ }
+
+ if (len == len2) {
+ if (len > 4) {
+ /* .jf0 en .jf1 voor jstreams afvangen */
+ if (strncasecmp(string + len - 4, ".jf", 3) == 0) len -= 4;
+ else if (strncasecmp(string + len - 4, ".tga", 4) == 0) len -= 4;
+ else if (strncasecmp(string + len - 4, ".jpg", 4) == 0) len -= 4;
+ else if (strncasecmp(string + len - 4, ".png", 4) == 0) len -= 4;
+ else if (strncasecmp(string + len - 4, ".txt", 4) == 0) len -= 4;
+ else if (strncasecmp(string + len - 4, ".cyc", 4) == 0) len -= 4;
+ else if (strncasecmp(string + len - 4, ".enh", 4) == 0) len -= 4;
+ else if (strncasecmp(string + len - 4, ".rgb", 4) == 0) len -= 4;
+ else if (strncasecmp(string + len - 4, ".psx", 4) == 0) len -= 4;
+ else if (strncasecmp(string + len - 4, ".ble", 4) == 0) len -= 4;
+ }
+ }
+
+ for (i = len - 1; i >= 0; i--){
+ if (string[i] == '/') break;
+ if (isdigit(string[i])) {
+ if (found){
+ nums = i;
+ }
+ else{
+ nume = i;
+ nums = i;
+ found = 1;
+ }
+ }
+ else{
+ if (found) break;
+ }
+ }
+ if (found){
+ if (staart) strcpy(staart,&string[nume+1]);
+ if (kop) {
+ strcpy(kop,string);
+ kop[nums]=0;
+ }
+ if (numlen) *numlen = nume-nums+1;
+ return ((int)atoi(&(string[nums])));
+ }
+ if (staart) strcpy(staart, string + len);
+ if (kop) {
+ strncpy(kop, string, len);
+ kop[len] = 0;
+ }
+ if (numlen) *numlen=0;
+ return 0;
+}
+
+
+void BLI_stringenc(char *string, char *kop, char *staart, unsigned short numlen, int pic)
+{
+ char numstr[10]="";
+ unsigned short len,i;
+
+ strcpy(string,kop);
+
+ if (pic>0 || numlen==4) {
+ len= sprintf(numstr,"%d",pic);
+
+ for(i=len;i<numlen;i++){
+ strcat(string,"0");
+ }
+ strcat(string,numstr);
+ }
+ strcat(string,staart);
+}
+
+
+void BLI_newname(char * name, int add)
+{
+ char head[128], tail[128];
+ int pic;
+ unsigned short digits;
+
+ pic = BLI_stringdec(name, head, tail, &digits);
+
+ /* gaan we van 100 -> 99 of van 10 naar 9 */
+ if (add < 0 && digits < 4 && digits > 0) {
+ int i, exp;
+ exp = 1;
+ for (i = digits; i > 1; i--) exp *= 10;
+ if (pic >= exp && (pic + add) < exp) digits--;
+ }
+
+ pic += add;
+
+ if(digits==4 && pic<0) pic= 0;
+ BLI_stringenc(name, head, tail, digits, pic);
+}
+
+
+void BLI_addhead(ListBase *listbase, void *vlink)
+{
+ struct Link *link= vlink;
+
+ if (link == 0) return;
+ if (listbase == 0) return;
+
+ link->next = listbase->first;
+ link->prev = 0;
+
+ if (listbase->first) ((struct Link *)listbase->first)->prev = link;
+ if (listbase->last == 0) listbase->last = link;
+ listbase->first = link;
+}
+
+
+void BLI_addtail(ListBase *listbase, void *vlink)
+{
+ struct Link *link= vlink;
+
+ if (link == 0) return;
+ if (listbase == 0) return;
+
+ link->next = 0;
+ link->prev = listbase->last;
+
+ if (listbase->last) ((struct Link *)listbase->last)->next = link;
+ if (listbase->first == 0) listbase->first = link;
+ listbase->last = link;
+}
+
+
+void BLI_remlink(ListBase *listbase, void *vlink)
+{
+ struct Link *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;
+}
+
+
+void BLI_freelinkN(ListBase *listbase, void *vlink)
+{
+ struct Link *link= vlink;
+
+ if (link == 0) return;
+ if (listbase == 0) return;
+
+ BLI_remlink(listbase,link);
+ MEM_freeN(link);
+}
+
+
+void BLI_insertlink(ListBase *listbase, void *vprevlink, void *vnewlink)
+{
+ struct Link *prevlink= vprevlink, *newlink= vnewlink;
+
+ /* newlink komt na prevlink */
+
+ if (newlink == 0) return;
+ if (listbase == 0) return;
+
+ if(listbase->first==0) { /* lege lijst */
+ listbase->first= newlink;
+ listbase->last= newlink;
+ return;
+ }
+ if (prevlink== 0) { /* inserten voor eerste element */
+ newlink->next= listbase->first;
+ newlink->prev= 0;
+ newlink->next->prev= newlink;
+ listbase->first= newlink;
+ return;
+ }
+
+ if (listbase->last== prevlink) /* aan einde lijst */
+ listbase->last = newlink;
+
+ newlink->next= prevlink->next;
+ prevlink->next= newlink;
+ if(newlink->next) newlink->next->prev= newlink;
+ newlink->prev= prevlink;
+}
+
+void BLI_insertlinkbefore(ListBase *listbase, void *vnextlink, void *vnewlink)
+{
+ struct Link *nextlink= vnextlink, *newlink= vnewlink;
+
+ /* newlink komt voor nextlink */
+
+ if (newlink == 0) return;
+ if (listbase == 0) return;
+
+ if(listbase->first==0) { /* lege lijst */
+ listbase->first= newlink;
+ listbase->last= newlink;
+ return;
+ }
+ if (nextlink== 0) { /* inserten aan einde lijst */
+ newlink->prev= listbase->last;
+ newlink->next= 0;
+ ((struct Link *)listbase->last)->next= newlink;
+ listbase->last= newlink;
+ return;
+ }
+
+ if (listbase->first== nextlink) /* aan begin lijst */
+ listbase->first = newlink;
+
+ newlink->next= nextlink;
+ newlink->prev= nextlink->prev;
+ nextlink->prev= newlink;
+ if(newlink->prev) newlink->prev->next= newlink;
+}
+
+
+void BLI_freelist(ListBase *listbase)
+{
+ struct Link *link,*next;
+
+ if (listbase == 0) return;
+ link= listbase->first;
+ while(link) {
+ next= link->next;
+ free(link);
+ link= next;
+ }
+ listbase->first=0;
+ listbase->last=0;
+}
+
+void BLI_freelistN(ListBase *listbase)
+{
+ struct Link *link,*next;
+
+ if (listbase == 0) return;
+ link= listbase->first;
+ while(link) {
+ next= link->next;
+ MEM_freeN(link);
+ link= next;
+ }
+ listbase->first=0;
+ listbase->last=0;
+}
+
+
+int BLI_countlist(ListBase *listbase)
+{
+ Link * link;
+ int count = 0;
+
+ if (listbase){
+ link = listbase->first;
+ while(link) {
+ count++;
+ link= link->next;
+ }
+ }
+ return(count);
+}
+
+void * BLI_findlink(ListBase *listbase, int number)
+{
+ Link * link = NULL;
+
+ if (number >= 0) {
+ link = listbase->first;
+ while (link != NULL && number != 0) {
+ number--;
+ link = link->next;
+ }
+ }
+
+ return (link);
+}
+
+
+char *BLI_strdupn(char *str, int len) {
+ char *n= MEM_mallocN(len+1, "strdup");
+ memcpy(n, str, len);
+ n[len]= '\0';
+
+ return n;
+}
+char *BLI_strdup(char *str) {
+ return BLI_strdupn(str, strlen(str));
+}
+
+char *BLI_strncpy(char *dst, char *src, int maxncpy) {
+ int srclen= strlen(src);
+ int cpylen= (srclen>(maxncpy-1))?(maxncpy-1):srclen;
+
+ memcpy(dst, src, cpylen);
+ dst[cpylen]= '\0';
+
+ return dst;
+}
+
+int BLI_streq(char *a, char *b) {
+ return (strcmp(a, b)==0);
+}
+int BLI_strcaseeq(char *a, char *b) {
+ return (strcasecmp(a, b)==0);
+}
+
+void BLI_makestringcode(char *fromfile, char *str)
+{
+ char *slash, len, temp[512];
+
+ strcpy(temp, fromfile);
+
+ /* Find the last slash */
+ slash = (strrchr(temp, '/')>strrchr(temp, '\\'))
+ ? strrchr(temp, '/') : strrchr(temp, '\\');
+ if(slash) {
+ *(slash+1)= 0;
+ len= strlen(temp);
+ if(len) {
+ if(strncmp(str, temp, len)==0) {
+ temp[0]= '/';
+ temp[1]= '/';
+ strcpy(temp+2, str+len);
+ strcpy(str, temp);
+ }
+ }
+ }
+}
+
+int BLI_convertstringcode(char *path, char *basepath, int framenum)
+{
+ int len, wasrelative= (strncmp(path, "//", 2)==0);
+
+ if (path[0] == '/' && path[1] == '/') {
+ char *filepart= BLI_strdup(path+2); /* skip code */
+ char *lslash= BLI_last_slash(basepath);
+
+ if (lslash) {
+ int baselen= (int) (lslash-basepath) + 1;
+
+ memcpy(path, basepath, baselen);
+ strcpy(path+baselen, filepart);
+ } else {
+ strcpy(path, filepart);
+ }
+
+ MEM_freeN(filepart);
+ }
+
+ len= strlen(path);
+ if(len && path[len-1]=='#') {
+ sprintf(path+len-1, "%04d", framenum);
+ }
+
+ return wasrelative;
+}
+
+void BLI_splitdirstring(char *di,char *fi)
+{
+ char *lslash= BLI_last_slash(di);
+
+ if (lslash) {
+ strcpy(fi, lslash+1);
+ *(lslash+1)=0;
+ } else {
+ strcpy(fi, di);
+ di[0]= 0;
+ }
+}
+
+char *BLI_gethome(void) {
+
+ #ifdef __BeOS
+ return "/boot/home/"; /* BeOS 4.5: doubleclick at icon doesnt give home env */
+
+ #elif !defined(WIN32)
+ return getenv("HOME");
+
+ #else /* Windows */
+ char * ret;
+ static char dir[512];
+
+ ret = getenv("HOME");
+ if(ret) {
+ if (BLI_exists(ret)) return ret;
+ }
+
+ // add user profile support for WIN 2K / NT
+ ret = getenv("USERPROFILE");
+ if (ret) {
+ if (BLI_exists(ret)) { /* from fop, also below... */
+ sprintf(dir, "%s/Application Data/Not a Number/Blender", ret);
+ BLI_recurdir_fileops(dir);
+ if (BLI_exists(dir)) {
+ return(dir);
+ } else {
+ return(ret);
+ }
+ }
+ }
+
+ ret = getenv("WINDOWS");
+ if (ret) {
+ if(BLI_exists(ret)) return ret;
+ }
+
+ ret = getenv("WINDIR");
+ if (ret) {
+ if(BLI_exists(ret)) return ret;
+ }
+
+ return "C:\\Temp";
+ #endif
+}
+
+static void char_switch(char *string, char from, char to)
+{
+ while (*string != 0) {
+ if (*string == from) *string = to;
+ string++;
+ }
+}
+
+void BLI_make_exist(char *dir)
+{
+ int a;
+
+ #ifdef WIN32
+ char_switch(dir, '/', '\\');
+ #else
+ char_switch(dir, '\\', '/');
+ #endif
+
+ a = strlen(dir);
+
+#ifdef WIN32
+ while(BLI_exists(dir) == 0){
+ a --;
+ while(dir[a] != '\\'){
+ a--;
+ if (a <= 0) break;
+ }
+ if (a >= 0) dir[a+1] = 0;
+ else {
+ strcpy(dir,"\\");
+ break;
+ }
+ }
+#else
+ while(BLI_exist(dir) == 0){
+ a --;
+ while(dir[a] != '/'){
+ a--;
+ if (a <= 0) break;
+ }
+ if (a >= 0) dir[a+1] = 0;
+ else {
+ strcpy(dir,"/");
+ break;
+ }
+ }
+#endif
+}
+
+void BLI_make_file_string(char *relabase, char *string, char *dir, char *file)
+{
+
+ if (!string || !dir || !file) return; /* We don't want any NULLs */
+
+ string[0]= 0; /* ton */
+
+ /* Resolve relative references */
+ if (relabase && dir[0] == '/' && dir[1] == '/') {
+ char *lslash;
+
+ /* Get the file name, chop everything past the last slash (ie. the filename) */
+ strcpy(string, relabase);
+
+ lslash= (strrchr(string, '/')>strrchr(string, '\\'))?strrchr(string, '/'):strrchr(string, '\\');
+
+ if(lslash) *(lslash+1)= 0;
+
+ dir+=2; /* Skip over the relative reference */
+ }
+
+ strcat(string, dir);
+
+ /* Make sure string ends in one (and only one) slash */
+ if (string[strlen(string)-1] != '/' && string[strlen(string)-1] != '\\')
+ strcat(string, "/");
+
+ while (*file && (*file == '/' || *file == '\\')) /* Trim slashes from the front of file */
+ file++;
+
+ strcat (string, file);
+
+ /* Push all slashes to the system preferred direction */
+ #ifdef WIN32
+ char_switch(string, '/', '\\');
+ #else
+ char_switch(string, '\\', '/');
+ #endif
+}
+
+int BLI_testextensie(char *str, char *ext)
+{
+ short a, b;
+ int retval;
+
+ a= strlen(str);
+ b= strlen(ext);
+
+ if(a==0 || b==0 || b>=a) {
+ retval = 0;
+ } else if (strcasecmp(ext, str + a - b)) {
+ retval = 0;
+ } else {
+ retval = 1;
+ }
+
+ return (retval);
+}
+
+void BLI_split_dirfile(char *string, char *dir, char *file)
+{
+ int a;
+
+ dir[0]= 0;
+ file[0]= 0;
+
+#ifdef WIN32
+ if (strlen(string)) {
+ if (string[0] == '/' || string[0] == '\\') {
+ strcpy(dir, string);
+ } else if (string[1] == ':' && string[2] == '\\') {
+ strcpy(dir, string);
+ } else {
+ BLI_getwdN(dir);
+ strcat(dir,"/");
+ strcat(dir,string);
+ strcpy(string,dir);
+ }
+
+ BLI_make_exist(dir);
+
+ if (S_ISDIR(BLI_exist(dir))) {
+ strcpy(file,string + strlen(dir));
+
+ if (strrchr(file,'\\')) strcpy(file,strrchr(file,'\\')+1);
+
+ if (a = strlen(dir)) {
+ if (dir[a-1] != '\\') strcat(dir,"\\");
+ }
+ }
+ else {
+ a = strlen(dir) - 1;
+ while(a>0 && dir[a] != '\\') a--;
+ dir[a + 1] = 0;
+ strcpy(file, string + strlen(dir));
+ }
+
+ }
+ else {
+ strcpy(dir, "\\");
+ file[0]=0;
+ }
+#else
+ if (strlen(string)) {
+ if (string[0] == '/') {
+ strcpy(dir, string);
+ } else if (string[1] == ':' && string[2] == '\\') {
+ string+=2;
+ strcpy(dir, string);
+ } else {
+ BLI_getwdN(dir);
+ strcat(dir,"/");
+ strcat(dir,string);
+ strcpy(string,dir);
+ }
+
+ BLI_make_exist(dir);
+
+ if (S_ISDIR(BLI_exist(dir))) {
+ strcpy(file,string + strlen(dir));
+
+ if (strrchr(file,'/')) strcpy(file,strrchr(file,'/')+1);
+
+ if ( (a = strlen(dir)) ) {
+ if (dir[a-1] != '/') strcat(dir,"/");
+ }
+ }
+ else {
+ a = strlen(dir) - 1;
+ while(dir[a] != '/') a--;
+ dir[a + 1] = 0;
+ strcpy(file, string + strlen(dir));
+ }
+ }
+ else {
+ BLI_getwdN(dir);
+ strcat(dir, "/");
+ file[0] = 0;
+ }
+#endif
+}
+
+// copies from BKE_utildefines
+#ifndef FILE_MAXDIR
+#define FILE_MAXDIR 160
+#endif
+
+#ifndef FILE_MAXFILE
+#define FILE_MAXFILE 80
+#endif
+
+static int add_win32_extension(char *name)
+{
+ int retval = 0;
+ int type;
+
+ type = BLI_exist(name);
+ if ((type == 0) || S_ISDIR(type)) {
+#ifdef _WIN32
+ char filename[FILE_MAXDIR+FILE_MAXFILE];
+ char ext[FILE_MAXDIR+FILE_MAXFILE];
+ char *extensions = getenv("PATHEXT");
+ if (extensions) {
+ char *temp;
+ do {
+ strcpy(filename, name);
+ temp = strstr(extensions, ";");
+ if (temp) {
+ strncpy(ext, extensions, temp - extensions);
+ ext[temp - extensions] = 0;
+ extensions = temp + 1;
+ strcat(filename, ext);
+ } else {
+ strcat(filename, extensions);
+ }
+
+ type = BLI_exist(filename);
+ if (type && (! S_ISDIR(type))) {
+ retval = 1;
+ strcpy(name, filename);
+ break;
+ }
+ } while (temp);
+ }
+#endif
+ } else {
+ retval = 1;
+ }
+
+ return (retval);
+}
+
+void BLI_where_am_i(char *fullname, char *name)
+{
+ char filename[FILE_MAXDIR+FILE_MAXFILE];
+ char *path, *temp;
+ int len;
+#ifdef _WIN32
+ char *seperator = ";";
+ char *slash = "\\";
+#else
+ char *seperator = ":";
+ char *slash = "/";
+#endif
+
+ if (name && fullname && strlen(name)) {
+ strcpy(fullname, name);
+ if (name[0] == '.') {
+ // relative path, prepend cwd
+ BLI_getwdN(fullname);
+ len = strlen(fullname);
+ if (len && fullname[len -1] != slash[0]) {
+ strcat(fullname, slash);
+ }
+ strcat(fullname, name);
+ add_win32_extension(fullname);
+ } else if (BLI_last_slash(name)) {
+ // full path
+ strcpy(fullname, name);
+ add_win32_extension(fullname);
+ } else {
+ // search for binary in $PATH
+ path = getenv("PATH");
+ if (path) {
+ do {
+ temp = strstr(path, seperator);
+ if (temp) {
+ strncpy(filename, path, temp - path);
+ filename[temp - path] = 0;
+ path = temp + 1;
+ } else {
+ strncpy(filename, path, sizeof(filename));
+ }
+ len = strlen(filename);
+ if (len && filename[len - 1] != slash[0]) {
+ strcat(filename, slash);
+ }
+ strcat(filename, name);
+ if (add_win32_extension(filename)) {
+ strcpy(fullname, filename);
+ break;
+ }
+ } while (temp);
+ }
+ }
+#ifndef NDEBUG
+ if (strcmp(name, fullname)) {
+ printf("guessing '%s' == '%s'\n", name, fullname);
+ }
+#endif
+
+#ifdef _WIN32
+ // in windows change long filename to short filename because
+ // win2k doesn't know how to parse a commandline with lots of
+ // spaces and double-quotes. There's another solution to this
+ // with spawnv(P_WAIT, bprogname, argv) instead of system() but
+ // that's even uglier
+ GetShortPathName(fullname, fullname, FILE_MAXDIR+FILE_MAXFILE);
+#ifndef NDEBUG
+ printf("Shortname = '%s'\n", fullname);
+#endif
+#endif
+ }
+}
+
diff --git a/source/blender/blenlib/intern/vectorops.c b/source/blender/blenlib/intern/vectorops.c
new file mode 100644
index 00000000000..9314e7fca3e
--- /dev/null
+++ b/source/blender/blenlib/intern/vectorops.c
@@ -0,0 +1,165 @@
+/*
+ *
+ * Some vector operations.
+ *
+ * Always use
+ * - vector with x components : float x[3], int x[3], 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 *****
+ */
+
+/* ------------------------------------------------------------------------- */
+/* General format: op(a, b, c): a = b op c */
+/* Copying is done cp <from, to> */
+/* ------------------------------------------------------------------------- */
+
+#include "MTC_vectorops.h"
+#include <math.h>
+
+void MTC_diff3Int(int v1[3], int v2[3], int v3[3])
+{
+ v1[0] = v2[0] - v3[0];
+ v1[1] = v2[1] - v3[1];
+ v1[2] = v2[2] - v3[2];
+}
+
+/* ------------------------------------------------------------------------- */
+void MTC_diff3Float(float v1[3], float v2[3], float v3[3])
+{
+ v1[0] = v2[0] - v3[0];
+ v1[1] = v2[1] - v3[1];
+ v1[2] = v2[2] - v3[2];
+}
+
+/* ------------------------------------------------------------------------- */
+
+void MTC_cross3Int(int v1[3], int v2[3], int v3[3])
+{
+ v1[0] = v2[1]*v3[2] - v2[2]*v3[1];
+ v1[1] = v2[2]*v3[0] - v2[0]*v3[2];
+ v1[2] = v2[0]*v3[1] - v2[1]*v3[0];
+}
+
+/* ------------------------------------------------------------------------- */
+
+void MTC_cross3Float(float v1[3], float v2[3], float v3[3])
+{
+ v1[0] = v2[1]*v3[2] - v2[2]*v3[1];
+ v1[1] = v2[2]*v3[0] - v2[0]*v3[2];
+ v1[2] = v2[0]*v3[1] - v2[1]*v3[0];
+}
+/* ------------------------------------------------------------------------- */
+
+void MTC_cross3Double(double v1[3], double v2[3], double v3[3])
+{
+ v1[0] = v2[1]*v3[2] - v2[2]*v3[1];
+ v1[1] = v2[2]*v3[0] - v2[0]*v3[2];
+ v1[2] = v2[0]*v3[1] - v2[1]*v3[0];
+}
+
+/* ------------------------------------------------------------------------- */
+
+int MTC_dot3Int(int v1[3], int v2[3])
+{
+ return (v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]);
+}
+
+/* ------------------------------------------------------------------------- */
+
+float MTC_dot3Float(float v1[3], float v2[3])
+{
+ return (v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]);
+}
+
+/* ------------------------------------------------------------------------- */
+
+void MTC_cp3Float(float v1[3], float v2[3])
+{
+ v2[0] = v1[0];
+ v2[1] = v1[1];
+ v2[2] = v1[2];
+}
+
+/* ------------------------------------------------------------------------- */
+
+void MTC_cp3FloatInv(float v1[3], float v2[3])
+{
+ v2[0] = -v1[0];
+ v2[1] = -v1[1];
+ v2[2] = -v1[2];
+}
+
+/* ------------------------------------------------------------------------- */
+
+void MTC_swapInt(int *i1, int *i2)
+{
+ int swap;
+ swap = *i1;
+ *i1 = *i2;
+ *i2 = swap;
+}
+
+/* ------------------------------------------------------------------------- */
+
+void MTC_diff3DFF(double v1[3], float v2[3], float v3[3])
+{
+ v1[0] = v2[0] - v3[0];
+ v1[1] = v2[1] - v3[1];
+ v1[2] = v2[2] - v3[2];
+}
+
+/* ------------------------------------------------------------------------- */
+float MTC_normalise3DF(float n[3])
+{
+ float d;
+
+ d= n[0]*n[0]+n[1]*n[1]+n[2]*n[2];
+ /* FLT_EPSILON is too large! A larger value causes normalise errors in */
+ /* a scaled down utah teapot */
+ if(d>0.0000000000001) {
+
+ /* d= sqrt(d); This _should_ be sqrt, but internally it's a double*/
+ /* anyway. This is safe. */
+ d = sqrt(d);
+
+ n[0]/=d;
+ n[1]/=d;
+ n[2]/=d;
+ } else {
+ n[0]=n[1]=n[2]= 0.0;
+ d= 0.0;
+ }
+ return d;
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* eof */
diff --git a/source/blender/blenlib/intern/winstuff.c b/source/blender/blenlib/intern/winstuff.c
new file mode 100644
index 00000000000..91062297cda
--- /dev/null
+++ b/source/blender/blenlib/intern/winstuff.c
@@ -0,0 +1,193 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * Windows-posix compatibility layer, windows-specific functions.
+ */
+
+#ifdef WIN32
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_util.h"
+#include "BLI_winstuff.h"
+
+
+void RegisterBlendExtension(char * str) {
+ LONG lresult;
+ HKEY hkey = 0;
+ DWORD dwd = 0;
+ char buffer[128];
+
+ lresult = RegCreateKeyEx(HKEY_CLASSES_ROOT, "blendfile\\shell\\open\\command", 0,
+ "", REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, &dwd);
+
+ if (lresult == ERROR_SUCCESS) {
+ sprintf(buffer, "\"%s\" \"%%1\"", str);
+ lresult = RegSetValueEx(hkey, NULL, 0, REG_SZ, buffer, strlen(buffer) + 1);
+ RegCloseKey(hkey);
+ }
+
+ lresult = RegCreateKeyEx(HKEY_CLASSES_ROOT, "blendfile\\DefaultIcon", 0,
+ "", REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, &dwd);
+
+ if (lresult == ERROR_SUCCESS) {
+ sprintf(buffer, "\"%s\",1", str);
+ lresult = RegSetValueEx(hkey, NULL, 0, REG_SZ, buffer, strlen(buffer) + 1);
+ RegCloseKey(hkey);
+ }
+
+ lresult = RegCreateKeyEx(HKEY_CLASSES_ROOT, ".blend", 0,
+ "", REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, &dwd);
+
+ if (lresult == ERROR_SUCCESS) {
+ sprintf(buffer, "%s", "blendfile");
+ lresult = RegSetValueEx(hkey, NULL, 0, REG_SZ, buffer, strlen(buffer) + 1);
+ RegCloseKey(hkey);
+ }
+}
+
+static void strlower (char *str) {
+ while (*str) {
+ *str= tolower(*str);
+ str++;
+ }
+}
+
+static void strnlower (char *str, int n) {
+ while (n>0 && *str) {
+ *str= tolower(*str);
+ str++;
+ n--;
+ }
+}
+
+int strcasecmp (char *s1, char *s2) {
+ char *st1, *st2;
+ int r;
+
+ st1= MEM_mallocN(strlen(s1)+1, "temp string");
+ strcpy(st1, s1);
+
+ st2= MEM_mallocN(strlen(s2)+1, "temp string");
+ strcpy(st2, s2);
+
+ strlower(st1);
+ strlower(st2);
+ r= strcmp (st1, st2);
+
+ MEM_freeN(st1);
+ MEM_freeN(st2);
+
+ return r;
+}
+
+int strncasecmp (char *s1, char *s2, int n) {
+ char *st1, *st2;
+ int r;
+
+ st1= MEM_mallocN(n, "temp string");
+ memcpy(st1, s1, n);
+
+ st2= MEM_mallocN(n, "temp string");
+ memcpy(st2, s2, n);
+
+ strnlower(st1, n);
+ strnlower(st2, n);
+
+ r= strncmp (st1, st2, n);
+
+ MEM_freeN(st1);
+ MEM_freeN(st2);
+
+ return r;
+}
+
+DIR *opendir (const char *path) {
+ if (GetFileAttributes(path) & FILE_ATTRIBUTE_DIRECTORY) {
+ DIR *newd= MEM_mallocN(sizeof(DIR), "opendir");
+
+ newd->handle = INVALID_HANDLE_VALUE;
+ sprintf(newd->path, "%s/*.*",path);
+
+ newd->direntry.d_ino= 0;
+ newd->direntry.d_off= 0;
+ newd->direntry.d_reclen= 0;
+ newd->direntry.d_name= NULL;
+
+ return newd;
+ } else {
+ return NULL;
+ }
+}
+
+struct dirent *readdir(DIR *dp) {
+ if (dp->direntry.d_name) {
+ MEM_freeN(dp->direntry.d_name);
+ dp->direntry.d_name= NULL;
+ }
+
+ if (dp->handle==INVALID_HANDLE_VALUE) {
+ dp->handle= FindFirstFile(dp->path, &(dp->data));
+ if (dp->handle==INVALID_HANDLE_VALUE)
+ return NULL;
+
+ dp->direntry.d_name= BLI_strdup(dp->data.cFileName);
+
+ return &dp->direntry;
+ } else if (FindNextFile (dp->handle, &(dp->data))) {
+ dp->direntry.d_name= BLI_strdup(dp->data.cFileName);
+
+ return &dp->direntry;
+ } else {
+ return NULL;
+ }
+}
+
+int closedir (DIR *dp) {
+ if (dp->direntry.d_name) MEM_freeN(dp->direntry.d_name);
+ if (dp->handle!=INVALID_HANDLE_VALUE) FindClose(dp->handle);
+
+ MEM_freeN(dp);
+
+ return 0;
+}
+
+#else
+
+void BLI_WINSTUFF_C_IS_EMPTY_FOR_UNIX(void)
+{
+ /*intentionally empty*/
+}
+
+#endif
diff --git a/source/blender/blenloader/BLO_genfile.h b/source/blender/blenloader/BLO_genfile.h
new file mode 100644
index 00000000000..2e14c9d8fff
--- /dev/null
+++ b/source/blender/blenloader/BLO_genfile.h
@@ -0,0 +1,39 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * external genfile function prototypes
+ */
+
+#ifndef BLO_GENFILE_H
+#define BLO_GENFILE_H
+
+int BLO_findstruct_offset(char *structname, char *member);// used by py_main.c
+
+#endif
diff --git a/source/blender/blenloader/BLO_readfile.h b/source/blender/blenloader/BLO_readfile.h
new file mode 100644
index 00000000000..3487334db93
--- /dev/null
+++ b/source/blender/blenloader/BLO_readfile.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 *****
+ * external readfile function prototypes
+ */
+#ifndef BLO_READFILE_H
+#define BLO_READFILE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct SpaceFile;
+struct LinkNode;
+struct Main;
+struct UserDef;
+struct bScreen;
+struct Scene;
+
+typedef struct BlendHandle BlendHandle;
+
+typedef enum BlenFileType {
+ BLENFILETYPE_BLEND= 1,
+ BLENFILETYPE_PUB= 2,
+ BLENFILETYPE_RUNTIME= 3
+} BlenFileType;
+
+typedef enum {
+ BRE_NONE,
+
+ BRE_UNABLE_TO_OPEN,
+ BRE_UNABLE_TO_READ,
+
+ BRE_OUT_OF_MEMORY,
+ BRE_INTERNAL_ERROR,
+
+ BRE_NOT_A_BLEND,
+ BRE_NOT_A_PUBFILE,
+ BRE_INCOMPLETE,
+ BRE_CORRUPT,
+
+ BRE_TOO_NEW,
+ BRE_NOT_ALLOWED,
+
+ BRE_NO_SCREEN,
+ BRE_NO_SCENE,
+
+ BRE_INVALID
+} BlendReadError;
+
+typedef struct BlendFileData {
+ struct Main* main;
+ struct UserDef* user;
+
+ int winpos;
+ int fileflags;
+ int displaymode;
+
+ struct bScreen* curscreen;
+ struct Scene* curscene;
+
+ BlenFileType type;
+} BlendFileData;
+
+ /**
+ * Open a blender file from a pathname. The function
+ * returns NULL and sets the @a error_r argument if
+ * it cannot open the file.
+ *
+ * @param file The path of the file to open.
+ * @param error_r If the return value is NULL, an error
+ * code indicating the cause of the failure.
+ * @return The data of the file.
+ */
+BlendFileData* BLO_read_from_file (char *file, BlendReadError *error_r);
+
+ /**
+ * Open a blender file from memory. The function
+ * returns NULL and sets the @a error_r argument if
+ * it cannot open the file.
+ *
+ * @param mem The file data.
+ * @param memsize The length of @a mem.
+ * @param error_r If the return value is NULL, an error
+ * code indicating the cause of the failure.
+ * @return The data of the file.
+ */
+BlendFileData* BLO_read_from_memory (void *mem, int memsize, BlendReadError *error_r);
+
+
+/**
+ * Convert a BlendReadError to a human readable string.
+ * The string is static and does not need to be free'd.
+ *
+ * @param error The error to return a string for.
+ * @return A static human readable string representation
+ * of @a error.
+ */
+ char*
+BLO_bre_as_string(
+ BlendReadError error);
+
+/**
+ * Free's a BlendFileData structure and _all_ the
+ * data associated with it (the userdef data, and
+ * the main libblock data).
+ *
+ * @param bfd The structure to free.
+ */
+ void
+BLO_blendfiledata_free(
+ BlendFileData *bfd);
+
+/**
+ * Convert an idcode into a name.
+ *
+ * @param code The code to convert.
+ * @return A static string representing the name of
+ * the code.
+ */
+ char*
+BLO_idcode_to_name(
+ int code);
+
+/**
+ * Convert a name into an idcode (ie. ID_SCE)
+ *
+ * @param name The name to convert.
+ * @return The code for the name, or 0 if invalid.
+ */
+ int
+BLO_idcode_from_name(
+ char *name);
+
+/**
+ * Open a blendhandle from a file path.
+ *
+ * @param file The file path to open.
+ * @return A handle on success, or NULL on failure.
+ */
+ BlendHandle*
+BLO_blendhandle_from_file(
+ char *file);
+
+/**
+ * Gets the names of all the datablocks in a file
+ * of a certain type (ie. All the scene names in
+ * a file).
+ *
+ * @param bh The blendhandle to access.
+ * @param ofblocktype The type of names to get.
+ * @return A BLI_linklist of strings. The string links
+ * should be freed with malloc.
+ */
+ struct LinkNode*
+BLO_blendhandle_get_datablock_names(
+ BlendHandle *bh,
+ int ofblocktype);
+
+/**
+ * Gets the names of all the datablock groups in a
+ * file. (ie. file contains Scene, Mesh, and Lamp
+ * datablocks).
+ *
+ * @param bh The blendhandle to access.
+ * @return A BLI_linklist of strings. The string links
+ * should be freed with malloc.
+ */
+ struct LinkNode*
+BLO_blendhandle_get_linkable_groups(
+ BlendHandle *bh);
+
+/**
+ * Close and free a blendhandle. The handle
+ * becomes invalid after this call.
+ *
+ * @param bh The handle to close.
+ */
+ void
+BLO_blendhandle_close(
+ BlendHandle *bh);
+
+ /***/
+
+char *BLO_gethome(void);
+int BLO_has_bfile_extension(char *str);
+
+void BLO_library_append(struct SpaceFile *sfile, char *dir, int idcode);
+
+
+/* Ick ick ick, why are internal loader functions
+ * being exported out of the loader? IMHO readstreamglue
+ * should not need to know anything about the loader,
+ * but this is a point of contention. - zr
+ */
+ void*
+blo_readstreamfile_begin(
+ void *endControl);
+
+ int
+blo_readstreamfile_process(
+ void *filedataVoidPtr,
+ unsigned char *data,
+ unsigned int dataIn);
+
+ int
+blo_readstreamfile_end(
+ void *filedataVoidPtr);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/source/blender/blenloader/BLO_soundfile.h b/source/blender/blenloader/BLO_soundfile.h
new file mode 100644
index 00000000000..aa2c2c443b3
--- /dev/null
+++ b/source/blender/blenloader/BLO_soundfile.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 *****
+ */
+#ifndef BLO_SOUNDFILE_H
+#define BLO_SOUNDFILE_H
+
+#include "DNA_sound_types.h"
+#include "DNA_packedFile_types.h"
+
+struct bSound;
+struct PackedFile;
+
+//void sound_read_wav_data(bSound * sound, PackedFile * pf);
+
+#endif
diff --git a/source/blender/blenloader/BLO_writefile.h b/source/blender/blenloader/BLO_writefile.h
new file mode 100644
index 00000000000..b771d438bfc
--- /dev/null
+++ b/source/blender/blenloader/BLO_writefile.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 *****
+ * external writefile function prototypes
+ */
+
+#ifndef BLO_WRITEFILE_H
+#define BLO_WRITEFILE_H
+
+int BLO_write_file(char *dir, int write_flags, char **error_r);
+void BLO_write_runtime(char *file, char *exename);
+
+#endif
diff --git a/source/blender/blenloader/Makefile b/source/blender/blenloader/Makefile
new file mode 100644
index 00000000000..0d7cd16453e
--- /dev/null
+++ b/source/blender/blenloader/Makefile
@@ -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 *****
+#
+# Bounces make to subdirectories.
+
+SOURCEDIR = source/blender/blenloader
+DIRS = intern
+
+include nan_subdirs.mk
diff --git a/source/blender/blenloader/intern/Makefile b/source/blender/blenloader/intern/Makefile
new file mode 100644
index 00000000000..bbda61c53f5
--- /dev/null
+++ b/source/blender/blenloader/intern/Makefile
@@ -0,0 +1,75 @@
+#
+# $Id$
+#
+# ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version. The Blender
+# Foundation also sells licenses for use in proprietary software under
+# the Blender License. See http://www.blender.org/BL/ for information
+# about this.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2001-2002 by 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 = blenloader
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+CFLAGS += $(LEVEL_2_C_WARNINGS)
+
+ifeq ($(OS),$(findstring $(OS), "beos darwin freebsd linux openbsd solaris windows"))
+ CFLAGS += -funsigned-char
+endif
+
+# OpenGL and Python
+CPPFLAGS += $(OGL_CPPFLAGS)
+CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION)
+
+# zlib
+ifeq ($(OS),$(findstring $(OS), "solaris windows"))
+ CPPFLAGS += -I$(NAN_ZLIB)/include
+endif
+
+# streaming write function
+CPPFLAGS += -I../../writestreamglue
+CPPFLAGS += -I../../readstreamglue
+
+# initiate a streaming read pipe
+CPPFLAGS += -I../../readblenfile
+
+# This mod uses the GEN, DNA, BLI and BKE modules
+CPPFLAGS += -I../../../kernel/gen_messaging
+CPPFLAGS += -I../../makesdna
+CPPFLAGS += -I../../blenlib
+# path to the guarded memory allocator
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+CPPFLAGS += -I../../blenkernel
+CPPFLAGS += -I../../render/extern/include/
+CPPFLAGS += -I../../bpython/include
+
+# we still refer to /include a bit...
+CPPFLAGS += -I../../include
+
+# path to our own external headerfiles
+CPPFLAGS += -I..
diff --git a/source/blender/blenloader/intern/genfile.c b/source/blender/blenloader/intern/genfile.c
new file mode 100644
index 00000000000..6d897b500bd
--- /dev/null
+++ b/source/blender/blenloader/intern/genfile.c
@@ -0,0 +1,1098 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * DNA handling
+ */
+
+#ifndef WIN32
+#include <unistd.h> // for read close
+#else
+#include <io.h> // for open close read
+#endif
+
+#include <string.h> // strncmp
+#include <stdio.h> // for printf
+#include <stdlib.h> // for atoi
+#include <fcntl.h> // for open O_RDONLY
+
+#include "MEM_guardedalloc.h" // for MEM_freeN MEM_mallocN MEM_callocN
+#include "BLI_blenlib.h" // for BLI_filesize
+
+#include "BKE_utildefines.h" // for O_BINARY TRUE MIN2
+
+#include "DNA_sdna_types.h" // for SDNA ;-)
+
+#include "BLO_writefile.h"
+#include "BLO_genfile.h"
+
+#include "genfile.h"
+
+
+/*
+ * - pas op: geen beveiling tegen dubbele structen
+ * - struct niet in DNA file: twee hekjes erboven (#<enter>#<enter>)
+Aanmaken structDNA: alleen wanneer includes wijzigen.
+File Syntax:
+ SDNA (4 bytes) (voor fileherkenning)
+ NAME (4 bytes)
+ <nr> (4 bytes) aantal namen (int)
+ <string>
+ <string>
+ ...
+ ...
+ TYPE (4 bytes)
+ <nr> aantal types (int)
+ <string>
+ <string>
+ ...
+ ...
+ TLEN (4 bytes)
+ <len> (short)
+ <len>
+ ...
+ ...
+ STRC (4 bytes)
+ <nr> aantal structen (int)
+ <typenr><nr_of_elems> <typenr><namenr> <typenr><namenr> ...
+
+!!Denk aan integer en short aligned schrijven/lezen!!
+
+Bij het wegschrijven van files worden namen structen aangegeven
+met type= findstruct_nr(SDNA *, char *), 'type' correspondeert met nummer
+structarray in structDNA.
+
+Voor het moment: complete DNA file appenden achter blenderfile.
+In toekomst nadenken over slimmere methode (alleen gebruikte
+structen?, voorgeprepareerde DNA files? (TOT, OB, MAT )
+
+TOEGESTANE EN GETESTE WIJZIGINGEN IN STRUCTS:
+ - type verandering (bij chars naar float wordt door 255 gedeeld)
+ - plek in struct (alles kan door elkaar)
+ - struct in struct (in struct etc, is recursief)
+ - nieuwe elementen toevoegen (standaard op 0)
+ - elementen eruit (worden niet meer ingelezen)
+ - array's groter/kleiner
+ - verschillende typepointers met zelfde naam worden altijd gekopieerd.
+(NOG) NIET:
+ - float-array (vec[3]) naar struct van floats (vec3f)
+GEDAAN:
+ - DNA file in (achter) blender-executable plakken voor upward
+ compatibility Gebruikte methode: het makesdna programma schrijft
+ een c-file met een met spaties gevuld char-array van de juiste
+ lengte. Makesdna maakt er een .o van en vult de spaties met de
+ DNA file.
+ - endian compatibility
+ - 32 bits en 64 bits pointers
+LET OP:
+ - uint mag niet in een struct, gebruik unsigned int. (backwards
+ compatibility vanwege 64 bits code!)
+ - structen moeten altijd (intern) 4/8-aligned en short-aligned zijn.
+ de SDNA routine test hierop en print duidelijke errors.
+ DNA files met align errors zijn onbruikbaar!
+ - switch_endian doet alleen long long pointers,
+ zodat ze veilig gecast kunnen worden naar 32 bits
+ - casten van 64 naar 32 bits poinetrs: >>3.
+*/
+
+/* local */
+static int le_int(int temp);
+static short le_short(short temp);
+
+/* ************************* ENDIAN STUFF ********************** */
+
+static short le_short(short temp)
+{
+ short new;
+ char *rt=(char *)&temp, *rtn=(char *)&new;
+
+ rtn[0]= rt[1];
+ rtn[1]= rt[0];
+
+ return new;
+}
+
+
+static int le_int(int temp)
+{
+ int new;
+ char *rt=(char *)&temp, *rtn=(char *)&new;
+
+ rtn[0]= rt[3];
+ rtn[1]= rt[2];
+ rtn[2]= rt[1];
+ rtn[3]= rt[0];
+
+ return new;
+}
+
+
+/* ************************* MAKEN DNA ********************** */
+
+/* allowed duplicate code from makesdna.c */
+static int arraysize(char *astr, int len)
+{
+ int a, mul=1;
+ char str[100], *cp=0;
+
+ memcpy(str, astr, len+1);
+
+ for(a=0; a<len; a++) {
+ if( str[a]== '[' ) {
+ cp= &(str[a+1]);
+ }
+ else if( str[a]==']' && cp) {
+ str[a]= 0;
+ mul*= atoi(cp);
+ }
+ }
+
+ return mul;
+}
+
+/* ************************* END MAKEN DNA ********************** */
+
+/* ************************* DIV ********************** */
+
+void dna_freestructDNA(struct SDNA *sdna)
+{
+ MEM_freeN(sdna->data);
+ MEM_freeN(sdna->names);
+ MEM_freeN(sdna->types);
+ MEM_freeN(sdna->structs);
+
+ MEM_freeN(sdna);
+}
+
+static int elementsize(struct SDNA *sdna, short type, short name)
+/* aanroepen met nummers uit struct-array */
+{
+ int mul, namelen, len;
+ char *cp;
+
+ cp= sdna->names[name];
+ len= 0;
+
+ namelen= strlen(cp);
+ /* is het een pointer of functiepointer? */
+ if(cp[0]=='*' || cp[1]=='*') {
+ /* heeft de naam een extra lente? (array) */
+ mul= 1;
+ if( cp[namelen-1]==']') mul= arraysize(cp, namelen);
+
+ len= sdna->pointerlen*mul;
+ }
+ else if( sdna->typelens[type] ) {
+ /* heeft de naam een extra lente? (array) */
+ mul= 1;
+ if( cp[namelen-1]==']') mul= arraysize(cp, namelen);
+
+ len= mul*sdna->typelens[type];
+
+ }
+
+ return len;
+}
+
+#if 0
+static void printstruct(struct SDNA *sdna, short strnr)
+{
+ /* geef het structnummer door, is voor debug */
+ int b, nr;
+ short *sp;
+
+ sp= sdna->structs[strnr];
+
+ printf("struct %s\n", sdna->types[ sp[0] ]);
+ nr= sp[1];
+ sp+= 2;
+
+ for(b=0; b< nr; b++, sp+= 2) {
+ printf(" %s %s\n", sdna->types[sp[0]], sdna->names[sp[1]]);
+ }
+}
+#endif
+
+static short *findstruct_name(struct SDNA *sdna, char *str)
+{
+ int a;
+ short *sp=0;
+
+
+ for(a=0; a<sdna->nr_structs; a++) {
+
+ sp= sdna->structs[a];
+
+ if(strcmp( sdna->types[ sp[0] ], str )==0) return sp;
+ }
+
+ return 0;
+}
+
+int dna_findstruct_nr(struct SDNA *sdna, char *str)
+{
+ short *sp=0;
+ int a;
+
+ if(sdna->lastfind<sdna->nr_structs) {
+ sp= sdna->structs[sdna->lastfind];
+ if(strcmp( sdna->types[ sp[0] ], str )==0) return sdna->lastfind;
+ }
+
+ for(a=0; a<sdna->nr_structs; a++) {
+
+ sp= sdna->structs[a];
+
+ if(strcmp( sdna->types[ sp[0] ], str )==0) {
+ sdna->lastfind= a;
+ return a;
+ }
+ }
+
+ return -1;
+}
+
+/* ************************* END DIV ********************** */
+
+/* ************************* LEZEN DNA ********************** */
+
+static void init_structDNA(struct SDNA *sdna, int do_endian_swap)
+/* in sdna->data staat de data, uit elkaar pulken */
+{
+ int *data, *verg;
+ long nr;
+ short *sp;
+ char str[8], *cp;
+
+ verg= (int *)str;
+ data= (int *)sdna->data;
+
+ strcpy(str, "SDNA");
+ if( *data == *verg ) {
+
+ data++;
+
+ /* laad namen array */
+ strcpy(str, "NAME");
+ if( *data == *verg ) {
+ data++;
+
+ if(do_endian_swap) sdna->nr_names= le_int(*data);
+ else sdna->nr_names= *data;
+
+ data++;
+ sdna->names= MEM_callocN( sizeof(void *)*sdna->nr_names, "sdnanames");
+ }
+ else {
+ printf("NAME error in SDNA file\n");
+ return;
+ }
+
+ nr= 0;
+ cp= (char *)data;
+ while(nr<sdna->nr_names) {
+ sdna->names[nr]= cp;
+ while( *cp) cp++;
+ cp++;
+ nr++;
+ }
+ nr= (long)cp; /* BUS error voorkomen */
+ nr= (nr+3) & ~3;
+ cp= (char *)nr;
+
+ /* laad typenamen array */
+ data= (int *)cp;
+ strcpy(str, "TYPE");
+ if( *data == *verg ) {
+ data++;
+
+ if(do_endian_swap) sdna->nr_types= le_int(*data);
+ else sdna->nr_types= *data;
+
+ data++;
+ sdna->types= MEM_callocN( sizeof(void *)*sdna->nr_types, "sdnatypes");
+ }
+ else {
+ printf("TYPE error in SDNA file\n");
+ return;
+ }
+
+ nr= 0;
+ cp= (char *)data;
+ while(nr<sdna->nr_types) {
+ sdna->types[nr]= cp;
+
+ /* met deze patch kunnen structnamen gewijzigd worden */
+ /* alleen gebruiken voor conflicten met systeem-structen (opengl/X) */
+
+ if( *cp == 'b') {
+ /* struct Screen was already used by X, 'bScreen' replaces the old IrisGL 'Screen' struct */
+ if( strcmp("bScreen", cp)==0 ) sdna->types[nr]= cp+1;
+ }
+
+ while( *cp) cp++;
+ cp++;
+ nr++;
+ }
+ nr= (long)cp; /* BUS error voorkomen */
+ nr= (nr+3) & ~3;
+ cp= (char *)nr;
+
+ /* laad typelen array */
+ data= (int *)cp;
+ strcpy(str, "TLEN");
+ if( *data == *verg ) {
+ data++;
+ sp= (short *)data;
+ sdna->typelens= sp;
+
+ if(do_endian_swap) {
+ short a, *spo= sp;
+
+ a= sdna->nr_types;
+ while(a--) {
+ spo[0]= le_short(spo[0]);
+ spo++;
+ }
+ }
+
+ sp+= sdna->nr_types;
+ }
+ else {
+ printf("TLEN error in SDNA file\n");
+ return;
+ }
+ if(sdna->nr_types & 1) sp++; /* BUS error voorkomen */
+
+ /* laad structen array */
+ data= (int *)sp;
+ strcpy(str, "STRC");
+ if( *data == *verg ) {
+ data++;
+
+ if(do_endian_swap) sdna->nr_structs= le_int(*data);
+ else sdna->nr_structs= *data;
+
+ data++;
+ sdna->structs= MEM_callocN( sizeof(void *)*sdna->nr_structs, "sdnastrcs");
+ }
+ else {
+ printf("STRC error in SDNA file\n");
+ return;
+ }
+
+ nr= 0;
+ sp= (short *)data;
+ while(nr<sdna->nr_structs) {
+ sdna->structs[nr]= sp;
+
+ if(do_endian_swap) {
+ short a;
+
+ sp[0]= le_short(sp[0]);
+ sp[1]= le_short(sp[1]);
+
+ a= sp[1];
+ sp+= 2;
+ while(a--) {
+ sp[0]= le_short(sp[0]);
+ sp[1]= le_short(sp[1]);
+ sp+= 2;
+ }
+ }
+ else {
+ sp+= 2*sp[1]+2;
+ }
+
+ nr++;
+ }
+
+ /* finally pointerlen: use struct ListBase to test it, never change the size of it! */
+ sp= findstruct_name(sdna, "ListBase");
+
+ sdna->pointerlen= sdna->typelens[ sp[0] ]/2;
+
+ if(sp[1]!=2 || (sdna->pointerlen!=4 && sdna->pointerlen!=8)) {
+ printf("ListBase struct error! Needs it to calculate pointerize.\n");
+ exit(0);
+ }
+
+ }
+}
+
+struct SDNA *dna_sdna_from_data(void *data, int datalen, int do_endian_swap)
+{
+ struct SDNA *sdna= MEM_mallocN(sizeof(*sdna), "sdna");
+
+ sdna->lastfind= 0;
+
+ sdna->datalen= datalen;
+ sdna->data= MEM_mallocN(datalen, "sdna_data");
+ memcpy(sdna->data, data, datalen);
+
+ init_structDNA(sdna, do_endian_swap);
+
+ return sdna;
+}
+ /* XXX, this routine was added because at one
+ * point I thought using the dna more would be
+ * nice, but really thats a flawed idea, you
+ * already know about your memory structures when
+ * you are compiling no need to redirect that
+ * through the DNA, the python stuff should be
+ * changed to not use this routine (a bit
+ * o' work). - zr
+ */
+int BLO_findstruct_offset(char *structname, char *member)
+{
+ extern char DNAstr[]; /* DNA.c */
+ extern int DNAlen;
+
+ struct SDNA *sdna;
+ int a, offset;
+ short *sp;
+
+ sdna= dna_sdna_from_data(DNAstr, DNAlen, 0);
+
+ sp= findstruct_name(sdna, structname);
+
+ if(sp) {
+ a= sp[1]; /* aantal elems */
+ sp+= 2;
+ offset= 0;
+
+ while(a--) {
+ if(strcmp(sdna->names[sp[1]], member)==0) {
+ dna_freestructDNA(sdna);
+ return offset;
+ }
+
+ offset+= elementsize(sdna, sp[0], sp[1]);
+ sp+= 2;
+ }
+ }
+
+ dna_freestructDNA(sdna);
+ return -1;
+}
+
+/* ******************** END LEZEN DNA ********************** */
+
+/* ******************* AFHANDELEN DNA ***************** */
+
+static void recurs_test_compflags(struct SDNA *sdna, char *compflags, int structnr)
+{
+ int a, b, typenr, elems;
+ short *sp;
+ char *cp;
+
+ /* loop alle structen af en test of deze struct in andere zit */
+ sp= sdna->structs[structnr];
+ typenr= sp[0];
+
+ for(a=0; a<sdna->nr_structs; a++) {
+ if(a!=structnr && compflags[a]==1) {
+ sp= sdna->structs[a];
+ elems= sp[1];
+ sp+= 2;
+ for(b=0; b<elems; b++, sp+=2) {
+ if(sp[0]==typenr) {
+ cp= sdna->names[ sp[1] ];
+ if(cp[0]!= '*') {
+ compflags[a]= 2;
+ recurs_test_compflags(sdna, compflags, a);
+ }
+ }
+ }
+ }
+ }
+
+}
+
+ /* Unsure of exact function - compares the sdna argument to
+ * newsdna and sets up the information necessary to convert
+ * data written with a dna of oldsdna to inmemory data with a
+ * structure defined by the newsdna sdna (I think). -zr
+ */
+char *dna_get_structDNA_compareflags(struct SDNA *sdna, struct SDNA *newsdna)
+{
+ /* flag: 0:bestaat niet meer (of nog niet)
+ * 1: is gelijk
+ * 2: is anders
+ */
+ int a, b;
+ short *spold, *spcur;
+ char *str1, *str2;
+ char *compflags;
+
+ if(sdna->nr_structs==0) {
+ printf("error: file without SDNA\n");
+ return NULL;
+ }
+
+ compflags= MEM_callocN(sdna->nr_structs, "compflags");
+
+ /* We lopen alle structs in 'sdna' af, vergelijken ze met
+ * de structs in 'newsdna'
+ */
+
+ for(a=0; a<sdna->nr_structs; a++) {
+ spold= sdna->structs[a];
+
+ /* type zoeken in cur */
+ spcur= findstruct_name(newsdna, sdna->types[spold[0]]);
+
+ if(spcur) {
+ compflags[a]= 2;
+
+ /* lengte en aantal elems vergelijken */
+ if( spcur[1] == spold[1]) {
+ if( newsdna->typelens[spcur[0]] == sdna->typelens[spold[0]] ) {
+
+ /* evenlang en evenveel elems, nu per type en naam */
+ b= spold[1];
+ spold+= 2;
+ spcur+= 2;
+ while(b > 0) {
+ str1= newsdna->types[spcur[0]];
+ str2= sdna->types[spold[0]];
+ if(strcmp(str1, str2)!=0) break;
+
+ str1= newsdna->names[spcur[1]];
+ str2= sdna->names[spold[1]];
+ if(strcmp(str1, str2)!=0) break;
+
+ /* naam gelijk, type gelijk, nu nog pointersize, dit geval komt haast nooit voor! */
+ if(str1[0]=='*') {
+ if(sdna->pointerlen!=newsdna->pointerlen) break;
+ }
+
+ b--;
+ spold+= 2;
+ spcur+= 2;
+ }
+ if(b==0) compflags[a]= 1;
+
+ }
+ }
+
+ }
+ }
+
+ /* eerste struct in util.h is struct Link, deze wordt in de compflags overgeslagen (als # 0).
+ * Vuile patch! Nog oplossen....
+ */
+ compflags[0]= 1;
+
+ /* Aangezien structen in structen kunnen zitten gaan we recursief
+ * vlaggen zetten als er een struct veranderd is
+ */
+ for(a=0; a<sdna->nr_structs; a++) {
+ if(compflags[a]==2) recurs_test_compflags(sdna, compflags, a);
+ }
+
+/*
+ for(a=0; a<sdna->nr_structs; a++) {
+ if(compflags[a]==2) {
+ spold= sdna->structs[a];
+ printf("changed: %s\n", sdna->types[ spold[0] ]);
+ }
+ }
+*/
+
+ return compflags;
+}
+
+static void cast_elem(char *ctype, char *otype, char *name, char *curdata, char *olddata)
+{
+ double val = 0.0;
+ int arrlen, curlen=1, oldlen=1, ctypenr, otypenr;
+
+ arrlen= arraysize(name, strlen(name));
+
+ /* otypenr bepalen */
+ if(strcmp(otype, "char")==0) otypenr= 0;
+ else if((strcmp(otype, "uchar")==0)||(strcmp(otype, "unsigned char")==0)) otypenr= 1;
+ else if(strcmp(otype, "short")==0) otypenr= 2;
+ else if((strcmp(otype, "ushort")==0)||(strcmp(otype, "unsigned short")==0)) otypenr= 3;
+ else if(strcmp(otype, "int")==0) otypenr= 4;
+ else if(strcmp(otype, "long")==0) otypenr= 5;
+ else if((strcmp(otype, "ulong")==0)||(strcmp(otype, "unsigned long")==0)) otypenr= 6;
+ else if(strcmp(otype, "float")==0) otypenr= 7;
+ else if(strcmp(otype, "double")==0) otypenr= 8;
+ else return;
+
+ /* ctypenr bepalen */
+ if(strcmp(ctype, "char")==0) ctypenr= 0;
+ else if((strcmp(ctype, "uchar")==0)||(strcmp(ctype, "unsigned char")==0)) ctypenr= 1;
+ else if(strcmp(ctype, "short")==0) ctypenr= 2;
+ else if((strcmp(ctype, "ushort")==0)||(strcmp(ctype, "unsigned short")==0)) ctypenr= 3;
+ else if(strcmp(ctype, "int")==0) ctypenr= 4;
+ else if(strcmp(ctype, "long")==0) ctypenr= 5;
+ else if((strcmp(ctype, "ulong")==0)||(strcmp(ctype, "unsigned long")==0)) ctypenr= 6;
+ else if(strcmp(ctype, "float")==0) ctypenr= 7;
+ else if(strcmp(ctype, "double")==0) ctypenr= 8;
+ else return;
+
+ /* lengtes bepalen */
+ if(otypenr < 2) oldlen= 1;
+ else if(otypenr < 4) oldlen= 2;
+ else if(otypenr < 8) oldlen= 4;
+ else oldlen= 8;
+
+ if(ctypenr < 2) curlen= 1;
+ else if(ctypenr < 4) curlen= 2;
+ else if(ctypenr < 8) curlen= 4;
+ else curlen= 8;
+
+ while(arrlen>0) {
+ switch(otypenr) {
+ case 0:
+ val= *olddata; break;
+ case 1:
+ val= *( (unsigned char *)olddata); break;
+ case 2:
+ val= *( (short *)olddata); break;
+ case 3:
+ val= *( (unsigned short *)olddata); break;
+ case 4:
+ val= *( (int *)olddata); break;
+ case 5:
+ val= *( (int *)olddata); break;
+ case 6:
+ val= *( (unsigned int *)olddata); break;
+ case 7:
+ val= *( (float *)olddata); break;
+ case 8:
+ val= *( (double *)olddata); break;
+ }
+
+ switch(ctypenr) {
+ case 0:
+ *curdata= val; break;
+ case 1:
+ *( (unsigned char *)curdata)= val; break;
+ case 2:
+ *( (short *)curdata)= val; break;
+ case 3:
+ *( (unsigned short *)curdata)= val; break;
+ case 4:
+ *( (int *)curdata)= val; break;
+ case 5:
+ *( (int *)curdata)= val; break;
+ case 6:
+ *( (unsigned int *)curdata)= val; break;
+ case 7:
+ if(otypenr<2) val/= 255;
+ *( (float *)curdata)= val; break;
+ case 8:
+ if(otypenr<2) val/= 255;
+ *( (double *)curdata)= val; break;
+ }
+
+ olddata+= oldlen;
+ curdata+= curlen;
+ arrlen--;
+ }
+}
+
+static void cast_pointer(int curlen, int oldlen, char *name, char *curdata, char *olddata)
+{
+#ifdef WIN32
+ __int64 lval;
+#else
+ long long lval;
+#endif
+ int arrlen;
+
+ arrlen= arraysize(name, strlen(name));
+
+ while(arrlen>0) {
+
+ if(curlen==oldlen) {
+ memcpy(curdata, olddata, curlen);
+ }
+ else if(curlen==4 && oldlen==8) {
+#ifdef WIN32
+ lval= *( (__int64 *)olddata );
+#else
+ lval= *( (long long *)olddata );
+#endif
+ *((int *)curdata) = lval>>3; /* is natuurlijk een beetje een gok! */
+ }
+ else if(curlen==8 && oldlen==4) {
+#ifdef WIN32
+ *( (__int64 *)curdata ) = *((int *)olddata);
+#else
+ *( (long long *)curdata ) = *((int *)olddata);
+#endif
+ }
+ else {
+ /* voor debug */
+ printf("errpr: illegal pointersize! \n");
+ }
+
+ olddata+= oldlen;
+ curdata+= curlen;
+ arrlen--;
+
+ }
+}
+
+static int elem_strcmp(char *name, char *oname)
+{
+ int a=0;
+
+ /* strcmp without array part */
+
+ while(TRUE) {
+ if(name[a] != oname[a]) return 1;
+ if(name[a]=='[') break;
+ if(name[a]==0) break;
+ a++;
+ }
+ if(name[a] != oname[a]) return 1;
+ return 0;
+}
+
+static char *find_elem(struct SDNA *sdna, char *type, char *name, short *old, char *olddata, short **sppo)
+{
+ int a, elemcount, len;
+ char *otype, *oname;
+
+ /* without arraypart, so names can differ: return old namenr and type */
+
+ /* in old staat de oude struct */
+ elemcount= old[1];
+ old+= 2;
+ for(a=0; a<elemcount; a++, old+=2) {
+
+ otype= sdna->types[old[0]];
+ oname= sdna->names[old[1]];
+
+ len= elementsize(sdna, old[0], old[1]);
+
+ if( elem_strcmp(name, oname)==0 ) { /* naam gelijk */
+ if( strcmp(type, otype)==0 ) { /* type gelijk */
+ if(sppo) *sppo= old;
+ return olddata;
+ }
+
+ return 0;
+ }
+
+ olddata+= len;
+ }
+ return 0;
+}
+
+static void reconstruct_elem(struct SDNA *newsdna, struct SDNA *oldsdna, char *type, char *name, char *curdata, short *old, char *olddata)
+{
+ /* regels: testen op NAAM:
+ - naam volledig gelijk:
+ - type casten
+ - naam gedeeltelijk gelijk (array anders)
+ - type gelijk: memcpy
+ - types casten
+ (nzc 2-4-2001 I want the 'unsigned' bit to be parsed as well. Where
+ can I force this?
+ */
+ int a, elemcount, len, array, oldsize, cursize, mul;
+ char *otype, *oname, *cp;
+
+ /* is 'name' een array? */
+ cp= name;
+ array= 0;
+ while( *cp && *cp!='[') {
+ cp++; array++;
+ }
+ if( *cp!= '[' ) array= 0;
+
+ /* in old staat de oude struct */
+ elemcount= old[1];
+ old+= 2;
+ for(a=0; a<elemcount; a++, old+=2) {
+ otype= oldsdna->types[old[0]];
+ oname= oldsdna->names[old[1]];
+ len= elementsize(oldsdna, old[0], old[1]);
+
+ if( strcmp(name, oname)==0 ) { /* naam gelijk */
+
+ if( name[0]=='*') { /* pointer afhandelen */
+ cast_pointer(newsdna->pointerlen, oldsdna->pointerlen, name, curdata, olddata);
+ }
+ else if( strcmp(type, otype)==0 ) { /* type gelijk */
+ memcpy(curdata, olddata, len);
+ }
+ else cast_elem(type, otype, name, curdata, olddata);
+
+ return;
+ }
+ else if(array) { /* de naam is een array */
+
+ if( strncmp(name, oname, array)==0 ) { /* basis gelijk */
+
+ cursize= arraysize(name, strlen(name));
+ oldsize= arraysize(oname, strlen(oname));
+
+ if( name[0]=='*') { /* pointer afhandelen */
+ if(cursize>oldsize) cast_pointer(newsdna->pointerlen, oldsdna->pointerlen, oname, curdata, olddata);
+ else cast_pointer(newsdna->pointerlen, oldsdna->pointerlen, name, curdata, olddata);
+ }
+ else if(name[0]=='*' || strcmp(type, otype)==0 ) { /* type gelijk */
+ mul= len/oldsize;
+ mul*= MIN2(cursize, oldsize);
+ memcpy(curdata, olddata, mul);
+ }
+ else {
+ if(cursize>oldsize) cast_elem(type, otype, oname, curdata, olddata);
+ else cast_elem(type, otype, name, curdata, olddata);
+ }
+ return;
+ }
+ }
+ olddata+= len;
+ }
+}
+
+static void reconstruct_struct(struct SDNA *newsdna, struct SDNA *oldsdna, char *compflags, int oldSDNAnr, char *data, int curSDNAnr, char *cur)
+{
+ /* Recursief!
+ * Per element van cur_struct data lezen uit old_struct.
+ * Als element een struct is, recursief aanroepen.
+ */
+ int a, elemcount, elen, eleno, mul, mulo, firststructtypenr;
+ short *spo, *spc, *sppo;
+ char *name, *nameo, *type, *cpo, *cpc;
+
+ if(oldSDNAnr== -1) return;
+ if(curSDNAnr== -1) return;
+
+ if( compflags[oldSDNAnr]==1 ) { /* bij recurs: testen op gelijk */
+
+ spo= oldsdna->structs[oldSDNAnr];
+ elen= oldsdna->typelens[ spo[0] ];
+ memcpy( cur, data, elen);
+
+ return;
+ }
+
+ firststructtypenr= *(newsdna->structs[0]);
+
+ spo= oldsdna->structs[oldSDNAnr];
+ spc= newsdna->structs[curSDNAnr];
+
+ elemcount= spc[1];
+
+ spc+= 2;
+ cpc= cur;
+ for(a=0; a<elemcount; a++, spc+=2) {
+ type= newsdna->types[spc[0]];
+ name= newsdna->names[spc[1]];
+
+ elen= elementsize(newsdna, spc[0], spc[1]);
+
+ /* testen: is type een struct? */
+ if(spc[0]>=firststructtypenr && name[0]!='*') {
+
+ /* waar start de oude struct data (is ie er wel?) */
+ cpo= find_elem(oldsdna, type, name, spo, data, &sppo);
+
+ if(cpo) {
+ oldSDNAnr= dna_findstruct_nr(oldsdna, type);
+ curSDNAnr= dna_findstruct_nr(newsdna, type);
+
+ /* array! */
+ mul= arraysize(name, strlen(name));
+ nameo= oldsdna->names[sppo[1]];
+ mulo= arraysize(nameo, strlen(nameo));
+
+ eleno= elementsize(oldsdna, sppo[0], sppo[1]);
+
+ elen/= mul;
+ eleno/= mulo;
+
+ while(mul--) {
+ reconstruct_struct(newsdna, oldsdna, compflags, oldSDNAnr, cpo, curSDNAnr, cpc);
+ cpo+= eleno;
+ cpc+= elen;
+
+ /* new struct array larger than old */
+ mulo--;
+ if(mulo<=0) break;
+ }
+ }
+ else cpc+= elen;
+ }
+ else {
+
+ reconstruct_elem(newsdna, oldsdna, type, name, cpc, spo, data);
+ cpc+= elen;
+
+ }
+ }
+}
+
+void dna_switch_endian_struct(struct SDNA *oldsdna, int oldSDNAnr, char *data)
+{
+ /* Recursief!
+ * Als element een struct is, recursief aanroepen.
+ */
+ int a, mul, elemcount, elen, elena, firststructtypenr;
+ short *spo, *spc, skip;
+ char *name, *type, *cpo, *cur, cval;
+
+ if(oldSDNAnr== -1) return;
+ firststructtypenr= *(oldsdna->structs[0]);
+
+ spo= spc= oldsdna->structs[oldSDNAnr];
+
+ elemcount= spo[1];
+
+ spc+= 2;
+ cur= data;
+
+ for(a=0; a<elemcount; a++, spc+=2) {
+ type= oldsdna->types[spc[0]];
+ name= oldsdna->names[spc[1]];
+
+ /* elementsize = including arraysize */
+ elen= elementsize(oldsdna, spc[0], spc[1]);
+
+ /* testen: is type een struct? */
+ if(spc[0]>=firststructtypenr && name[0]!='*') {
+ /* waar start de oude struct data (is ie er wel?) */
+ cpo= find_elem(oldsdna, type, name, spo, data, 0);
+ if(cpo) {
+ oldSDNAnr= dna_findstruct_nr(oldsdna, type);
+
+ mul= arraysize(name, strlen(name));
+ elena= elen/mul;
+
+ while(mul--) {
+ dna_switch_endian_struct(oldsdna, oldSDNAnr, cpo);
+ cpo += elena;
+ }
+ }
+ }
+ else {
+
+ if( name[0]=='*' ) {
+ if(oldsdna->pointerlen==8) {
+
+ mul= arraysize(name, strlen(name));
+ cpo= cur;
+ while(mul--) {
+ cval= cpo[0]; cpo[0]= cpo[7]; cpo[7]= cval;
+ cval= cpo[1]; cpo[1]= cpo[6]; cpo[6]= cval;
+ cval= cpo[2]; cpo[2]= cpo[5]; cpo[5]= cval;
+ cval= cpo[3]; cpo[3]= cpo[4]; cpo[4]= cval;
+
+ cpo+= 8;
+ }
+
+ }
+ }
+ else {
+
+ if( spc[0]==2 || spc[0]==3 ) { /* short-ushort */
+
+ /* uitzondering: variable die blocktype/ipowin heet: van ID_ afgeleid */
+ skip= 0;
+ if(name[0]=='b' && name[1]=='l') {
+ if(strcmp(name, "blocktype")==0) skip= 1;
+ }
+ else if(name[0]=='i' && name[1]=='p') {
+ if(strcmp(name, "ipowin")==0) skip= 1;
+ }
+
+ if(skip==0) {
+ mul= arraysize(name, strlen(name));
+ cpo= cur;
+ while(mul--) {
+ cval= cpo[0];
+ cpo[0]= cpo[1];
+ cpo[1]= cval;
+ cpo+= 2;
+ }
+ }
+ }
+ else if(spc[0]>3 && spc[0]<8) { /* int-long-ulong-float */
+
+ mul= arraysize(name, strlen(name));
+ cpo= cur;
+ while(mul--) {
+ cval= cpo[0];
+ cpo[0]= cpo[3];
+ cpo[3]= cval;
+ cval= cpo[1];
+ cpo[1]= cpo[2];
+ cpo[2]= cval;
+ cpo+= 4;
+ }
+ }
+ }
+ }
+ cur+= elen;
+ }
+}
+
+void *dna_reconstruct(struct SDNA *newsdna, struct SDNA *oldsdna, char *compflags, int oldSDNAnr, int blocks, void *data)
+{
+ int a, curSDNAnr, curlen=0, oldlen;
+ short *spo, *spc;
+ char *cur, *type, *cpc, *cpo;
+
+ /* oldSDNAnr == structnr, we zoeken het corresponderende 'cur' nummer */
+ spo= oldsdna->structs[oldSDNAnr];
+ type= oldsdna->types[ spo[0] ];
+ oldlen= oldsdna->typelens[ spo[0] ];
+ curSDNAnr= dna_findstruct_nr(newsdna, type);
+
+ /* data goedzetten en nieuwe calloc doen */
+ if(curSDNAnr >= 0) {
+ spc= newsdna->structs[curSDNAnr];
+ curlen= newsdna->typelens[ spc[0] ];
+ }
+ if(curlen==0) {
+ return NULL;
+ }
+
+ cur= MEM_callocN( blocks*curlen, "reconstruct");
+ cpc= cur;
+ cpo= data;
+ for(a=0; a<blocks; a++) {
+ reconstruct_struct(newsdna, oldsdna, compflags, oldSDNAnr, cpo, curSDNAnr, cpc);
+ cpc+= curlen;
+ cpo+= oldlen;
+ }
+
+ return cur;
+}
+
diff --git a/source/blender/blenloader/intern/genfile.h b/source/blender/blenloader/intern/genfile.h
new file mode 100644
index 00000000000..a861dbd9d9f
--- /dev/null
+++ b/source/blender/blenloader/intern/genfile.h
@@ -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 *****
+ * blenloader genfile private function prototypes
+ */
+
+#ifndef GENFILE_H
+#define GENFILE_H
+
+struct SDNA;
+
+int dna_findstruct_nr(struct SDNA *sdna, char *str);
+char *dna_get_structDNA_compareflags(struct SDNA *sdna, struct SDNA *newsdna);
+void dna_switch_endian_struct(struct SDNA *oldsdna, int oldSDNAnr, char *data);
+void *dna_reconstruct(struct SDNA *newsdna, struct SDNA *oldsdna, char *compflags, int oldSDNAnr, int blocks, void *data);
+
+struct SDNA *dna_sdna_from_data(void *data, int datalen, int do_endian_swap);
+void dna_freestructDNA(struct SDNA *sdna);
+
+
+#endif
diff --git a/source/blender/blenloader/intern/readblenentry.c b/source/blender/blenloader/intern/readblenentry.c
new file mode 100644
index 00000000000..2f4723e6b8c
--- /dev/null
+++ b/source/blender/blenloader/intern/readblenentry.c
@@ -0,0 +1,340 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * .blend file reading entry point
+ */
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_ghash.h"
+#include "BLI_linklist.h"
+
+#include "DNA_sdna_types.h"
+#include "DNA_space_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_ID.h"
+
+#include "BKE_utildefines.h" // for ENDB
+
+#include "BKE_main.h"
+#include "BKE_library.h" // for free_main
+
+#include "BLO_readfile.h"
+#include "readfile.h"
+
+#include "BLO_readblenfile.h"
+
+ /**
+ * IDType stuff, I plan to move this
+ * out into its own file + prefix, and
+ * make sure all IDType handling goes through
+ * these routines.
+ */
+
+typedef struct {
+ unsigned short code;
+ char *name;
+
+ int flags;
+#define IDTYPE_FLAGS_ISLINKABLE (1<<0)
+} IDType;
+
+static IDType idtypes[]= {
+ { ID_AC, "Action", IDTYPE_FLAGS_ISLINKABLE},
+ { ID_AR, "Armature", IDTYPE_FLAGS_ISLINKABLE},
+ { ID_CA, "Camera", IDTYPE_FLAGS_ISLINKABLE},
+ { ID_CU, "Curve", IDTYPE_FLAGS_ISLINKABLE},
+ { ID_GR, "Group", 0},
+ { ID_ID, "ID", 0},
+ { ID_IK, "Ika", IDTYPE_FLAGS_ISLINKABLE},
+ { ID_IM, "Image", IDTYPE_FLAGS_ISLINKABLE},
+ { ID_IP, "Ipo", IDTYPE_FLAGS_ISLINKABLE},
+ { ID_KE, "Key", 0},
+ { ID_LA, "Lamp", IDTYPE_FLAGS_ISLINKABLE},
+ { ID_LF, "Life", 0},
+ { ID_LI, "Library", 0},
+ { ID_LT, "Lattice", IDTYPE_FLAGS_ISLINKABLE},
+ { ID_MA, "Material", IDTYPE_FLAGS_ISLINKABLE},
+ { ID_MB, "Metaball", IDTYPE_FLAGS_ISLINKABLE},
+ { ID_ME, "Mesh", IDTYPE_FLAGS_ISLINKABLE},
+ { ID_OB, "Object", IDTYPE_FLAGS_ISLINKABLE},
+ { ID_SAMPLE, "Sample", 0},
+ { ID_SCE, "Scene", IDTYPE_FLAGS_ISLINKABLE},
+ { ID_SCR, "Screen", 0},
+ { ID_SEQ, "Sequence", 0},
+ { ID_SE, "Sector", 0},
+ { ID_SO, "Sound", IDTYPE_FLAGS_ISLINKABLE},
+ { ID_TE, "Texture", IDTYPE_FLAGS_ISLINKABLE},
+ { ID_TXT, "Text", IDTYPE_FLAGS_ISLINKABLE},
+ { ID_VF, "VFont", IDTYPE_FLAGS_ISLINKABLE},
+ { ID_WO, "World", IDTYPE_FLAGS_ISLINKABLE},
+ { ID_WV, "Wave", 0},
+};
+static int nidtypes= sizeof(idtypes)/sizeof(idtypes[0]);
+
+static IDType *idtype_from_name(char *str) {
+ int i= nidtypes;
+
+ while (i--)
+ if (BLI_streq(str, idtypes[i].name))
+ return &idtypes[i];
+
+ return NULL;
+}
+static IDType *idtype_from_code(int code) {
+ int i= nidtypes;
+
+ while (i--)
+ if (code==idtypes[i].code)
+ return &idtypes[i];
+
+ return NULL;
+}
+
+static int bheadcode_is_idcode(int code) {
+ return idtype_from_code(code)?1:0;
+}
+
+static int idcode_is_linkable(int code) {
+ IDType *idt= idtype_from_code(code);
+ return idt?(idt->flags&IDTYPE_FLAGS_ISLINKABLE):0;
+}
+
+char *BLO_idcode_to_name(int code) {
+ IDType *idt= idtype_from_code(code);
+
+ return idt?idt->name:NULL;
+}
+
+int BLO_idcode_from_name(char *name) {
+ IDType *idt= idtype_from_name(name);
+
+ return idt?idt->code:0;
+}
+
+ /* Access routines used by filesel. */
+
+BlendHandle *BLO_blendhandle_from_file(char *file) {
+ return (BlendHandle*) blo_openblenderfile(file);
+}
+
+void BLO_blendhandle_print_sizes(BlendHandle *bh, void *fp) {
+ FileData *fd= (FileData*) bh;
+ BHead *bhead;
+
+ fprintf(fp, "[\n");
+ for (bhead= blo_firstbhead(fd); bhead; bhead= blo_nextbhead(fd, bhead)) {
+ if (bhead->code==ENDB)
+ break;
+ else {
+ short *sp= fd->filesdna->structs[bhead->SDNAnr];
+ char *name= fd->filesdna->types[ sp[0] ];
+ char buf[4];
+
+ buf[0]= (bhead->code>>24)&0xFF;
+ buf[1]= (bhead->code>>16)&0xFF;
+ buf[2]= (bhead->code>>8)&0xFF;
+ buf[3]= (bhead->code>>0)&0xFF;
+
+ buf[0]= buf[0]?buf[0]:' ';
+ buf[1]= buf[1]?buf[1]:' ';
+ buf[2]= buf[2]?buf[2]:' ';
+ buf[3]= buf[3]?buf[3]:' ';
+
+ fprintf(fp, "['%.4s', '%s', %d, %d], \n", buf, name, bhead->nr, bhead->len+sizeof(BHead));
+ }
+ }
+ fprintf(fp, "]\n");
+}
+
+LinkNode *BLO_blendhandle_get_datablock_names(BlendHandle *bh, int ofblocktype) {
+ FileData *fd= (FileData*) bh;
+ LinkNode *names= NULL;
+ BHead *bhead;
+
+ for (bhead= blo_firstbhead(fd); bhead; bhead= blo_nextbhead(fd, bhead)) {
+ if (bhead->code==ofblocktype) {
+ ID *id= (ID*) (bhead+1);
+
+ BLI_linklist_prepend(&names, strdup(id->name+2));
+ } else if (bhead->code==ENDB)
+ break;
+ }
+
+ return names;
+}
+
+LinkNode *BLO_blendhandle_get_linkable_groups(BlendHandle *bh) {
+ FileData *fd= (FileData*) bh;
+ GHash *gathered= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+ LinkNode *names= NULL;
+ BHead *bhead;
+
+ for (bhead= blo_firstbhead(fd); bhead; bhead= blo_nextbhead(fd, bhead)) {
+ if (bhead->code==ENDB) {
+ break;
+ } else if (bheadcode_is_idcode(bhead->code)) {
+ if (idcode_is_linkable(bhead->code)) {
+ char *str= BLO_idcode_to_name(bhead->code);
+
+ if (!BLI_ghash_haskey(gathered, str)) {
+ BLI_linklist_prepend(&names, strdup(str));
+ BLI_ghash_insert(gathered, str, NULL);
+ }
+ }
+ }
+ }
+
+ BLI_ghash_free(gathered, NULL, NULL);
+
+ return names;
+}
+
+void BLO_blendhandle_close(BlendHandle *bh) {
+ FileData *fd= (FileData*) bh;
+
+ blo_freefiledata(fd);
+}
+
+ /**********/
+
+BlendFileData *BLO_read_from_file(char *file, BlendReadError *error_r) {
+ BlendFileData *bfd = NULL;
+ FileData *fd;
+
+ fd = blo_openblenderfile(file);
+ if (fd) {
+ bfd= blo_read_file_internal(fd, error_r);
+ if (bfd) {
+ bfd->type= BLENFILETYPE_BLEND;
+ strcpy(bfd->main->name, file);
+ }
+ blo_freefiledata(fd);
+ } else if (blo_is_a_runtime(file)) {
+ bfd= blo_read_runtime(file, error_r);
+ if (bfd) {
+ bfd->type= BLENFILETYPE_RUNTIME;
+ strcpy(bfd->main->name, file);
+ }
+ } else {
+ bfd= BLO_readblenfilename(file, error_r);
+ if (bfd) {
+ bfd->type= BLENFILETYPE_PUB;
+ strcpy(bfd->main->name, file);
+ }
+ }
+
+ return bfd;
+}
+
+BlendFileData *BLO_read_from_memory(void *mem, int memsize, BlendReadError *error_r) {
+ BlendFileData *bfd = NULL;
+ FileData *fd;
+
+ fd = blo_openblendermemory(mem, memsize);
+ if (fd) {
+ bfd= blo_read_file_internal(fd, error_r);
+ if (bfd) {
+ bfd->type= BLENFILETYPE_BLEND;
+ strcpy(bfd->main->name, "");
+ }
+ blo_freefiledata(fd);
+ } else {
+ bfd= BLO_readblenfilememory(mem, memsize, error_r);
+ if (bfd) {
+ bfd->type= BLENFILETYPE_PUB;
+ strcpy(bfd->main->name, "");
+ }
+ }
+
+ return bfd;
+}
+
+void BLO_blendfiledata_free(BlendFileData *bfd) {
+ if (bfd->main) {
+ free_main(bfd->main);
+ }
+
+ if (bfd->user) {
+ MEM_freeN(bfd->user);
+ }
+
+ MEM_freeN(bfd);
+}
+
+char *BLO_bre_as_string(BlendReadError error) {
+ switch (error) {
+ case BRE_NONE:
+ return "No error";
+
+ case BRE_UNABLE_TO_OPEN:
+ return "Unable to open";
+ case BRE_UNABLE_TO_READ:
+ return "Unable to read";
+
+ case BRE_OUT_OF_MEMORY:
+ return "Out of memory";
+ case BRE_INTERNAL_ERROR:
+ return "<internal error>";
+
+ case BRE_NOT_A_BLEND:
+ return "File is not a Blender file";
+ case BRE_NOT_A_PUBFILE:
+ return "File is not a compressed, locked or signed Blender file";
+ case BRE_INCOMPLETE:
+ return "File incomplete";
+ case BRE_CORRUPT:
+ return "File corrupt";
+
+ case BRE_TOO_NEW:
+ return "File needs newer Blender version, please upgrade";
+ case BRE_NOT_ALLOWED:
+ return "File is locked";
+
+ case BRE_NO_SCREEN:
+ return "File has no screen";
+ case BRE_NO_SCENE:
+ return "File has no scene";
+
+ default:
+ case BRE_INVALID:
+ return "<invalid read error>";
+ }
+}
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
new file mode 100644
index 00000000000..7addde6e529
--- /dev/null
+++ b/source/blender/blenloader/intern/readfile.c
@@ -0,0 +1,4810 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * .blend file reading
+ */
+
+#ifdef WIN32
+#include "winsock2.h"
+#include "BLI_winstuff.h"
+#endif
+
+#include <stdio.h> // for printf fopen fwrite fclose sprintf FILE
+#include <stdlib.h> // for getenv atoi
+#include <fcntl.h> // for open
+#include <string.h> // for strcasecmp strrchr strncmp strstr
+#include <math.h> // for pow
+
+#ifndef WIN32
+ #include <unistd.h> // for read close
+ #include <sys/param.h> // for MAXPATHLEN
+#else
+ #include <io.h> // for open close read
+#endif
+
+#include "nla.h"
+
+#include "DNA_ID.h"
+#include "DNA_packedFile_types.h"
+#include "DNA_property_types.h"
+#include "DNA_actuator_types.h"
+#include "DNA_controller_types.h"
+#include "DNA_sensor_types.h"
+#include "DNA_sdna_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_sequence_types.h"
+#include "DNA_ika_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_lattice_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_key_types.h"
+#include "DNA_meta_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_object_types.h"
+#include "DNA_world_types.h"
+#include "DNA_ipo_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_image_types.h"
+#include "DNA_material_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_vfont_types.h"
+#include "DNA_effect_types.h"
+#include "DNA_text_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_sound_types.h"
+#include "DNA_space_types.h"
+#include "DNA_oops_types.h"
+#include "DNA_group_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_fileglobal_types.h"
+#include "DNA_constraint_types.h"
+#include "DNA_action_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_nla_types.h"
+
+#include "GEN_messaging.h"
+
+#include "MEM_guardedalloc.h"
+#include "BLI_blenlib.h"
+#include "BLI_storage_types.h" // for relname flags
+
+#include "BKE_bad_level_calls.h" // for reopen_text build_seqar (from WHILE_SEQ) open_plugin_seq set_rects_butspace check_imasel_copy
+
+#include "BKE_utildefines.h" // SWITCH_INT WHILE_SEQ END_SEQ DATA ENDB DNA1 O_BINARY GLOB USER TEST REND
+#include "BKE_constraint.h"
+#include "BKE_main.h" // for Main
+#include "BKE_global.h" // for G
+#include "BKE_property.h" // for get_property
+#include "BKE_library.h" // for wich_libbase
+#include "BKE_texture.h" // for open_plugin_tex
+#include "BKE_effect.h" // for give_parteff
+#include "BKE_sca.h" // for init_actuator
+#include "BKE_mesh.h" // for ME_ defines (patching)
+#include "BKE_armature.h" // for precalc_bonelist_irestmats
+#include "BKE_action.h"
+
+#include "BPY_extern.h" // for BPY_do_pyscript
+
+#include "BLO_readfile.h"
+#include "readfile.h"
+
+#include "genfile.h"
+
+#include "BLO_readblenfile.h" // streaming read pipe, for BLO_readblenfile BLO_readblenfilememory
+
+#include "mydevice.h"
+
+/*
+ZWAK PUNT: newadres berekening en meerdere files: oplossen
+bijvoorbeeld door per file aparte newadresarrays te maken?
+
+LEZEN
+- Bestaande Library (Main) pushen of vrijgeven
+- Nieuwe Main alloceren
+- load file
+- read SDNA
+- for each LibBlock
+ - read LibBlock
+ - als Library
+ - make a new Main
+ - ID's eraan hangen
+ - else
+ - lees bijhorende direkte data
+ - link direkte data (intern en aan LibBlock)
+- lees FileGlobal
+- lees USER data, als aangegeven (~/.B.blend)
+- file vrijgeven
+- per Library met Scene (per Main)
+ - file inlezen
+ - lees SDNA
+ - alle LibBlocks uit Scene opzoeken en ID's aan Main hagen
+ - als extern LibBlock
+ - zoek Main's af
+ - is al ingelezen:
+ - nog niet ingelezen
+ - of nieuwe Main maken
+ - per LibBlock
+ - recursief dieper lezen
+ - lees bijhorende direkte data
+ - link direkte data (intern en aan LibBlock)
+ - file vrijgeven
+- per Library met nog niet gelezen LibBlocks
+ - file inlezen
+ - lees SDNA
+ - per LibBlock
+ - recursief dieper lezen
+ - lees bijhorende direkte data
+ - link direkte data (intern en aan LibBlock)
+ - file vrijgeven
+- alle Main's samenvoegen
+- alle LibBlocks linken en indirekte pointers naar libblocks
+- FileGlobal goedzetten en pointers naar Global kopieeren
+*/
+
+/* also occurs in library.c */
+/* GS reads the memory pointed at in a specific ordering. There are,
+ * however two definitions for it. I have jotted them down here, both,
+ * but I think the first one is actually used. The thing is that
+ * big-endian systems might read this the wrong way round. OTOH, we
+ * constructed the IDs that are read out with this macro explicitly as
+ * well. I expect we'll sort it out soon... */
+
+/* from blendef: */
+#define GS(a) (*((short *)(a)))
+
+/* from misc_util: flip the bytes from x */
+/* #define GS(x) (((unsigned char *)(x))[0] << 8 | ((unsigned char *)(x))[1]) */
+
+// only used here in readfile.c
+#define SWITCH_LONGINT(a) { \
+ char s_i, *p_i; \
+ p_i= (char *)&(a); \
+ s_i=p_i[0]; p_i[0]=p_i[7]; p_i[7]=s_i; \
+ s_i=p_i[1]; p_i[1]=p_i[6]; p_i[6]=s_i; \
+ s_i=p_i[2]; p_i[2]=p_i[5]; p_i[5]=s_i; \
+ s_i=p_i[3]; p_i[3]=p_i[4]; p_i[4]=s_i; }
+// only used here in readfile.c
+#define SWITCH_SHORT(a) { \
+ char s_i, *p_i; \
+ p_i= (char *)&(a); \
+ s_i=p_i[0]; p_i[0]=p_i[1]; p_i[1]=s_i; }
+
+/***/
+
+static char *functionality_check= "\0FUNCTIONALITY_CHECK += blo_readfile\n";
+
+/***/
+
+typedef struct OldNew {
+ void *old, *newp;
+ int nr;
+} OldNew;
+
+typedef struct OldNewMap {
+ OldNew *entries;
+ int nentries, entriessize;
+
+ int lasthit;
+} OldNewMap;
+
+static OldNewMap *oldnewmap_new(void) {
+ OldNewMap *onm= MEM_mallocN(sizeof(*onm), "OldNewMap");
+ onm->lasthit= 0;
+ onm->nentries= 0;
+ onm->entriessize= 1024;
+ onm->entries= MEM_mallocN(sizeof(*onm->entries)*onm->entriessize, "OldNewMap.entries");
+
+ return onm;
+}
+
+static void oldnewmap_insert(OldNewMap *onm, void *oldaddr, void *newaddr, int nr) {
+ OldNew *entry;
+
+ if (onm->nentries==onm->entriessize) {
+ int osize= onm->entriessize;
+ OldNew *oentries= onm->entries;
+
+ onm->entriessize*= 2;
+ onm->entries= MEM_mallocN(sizeof(*onm->entries)*onm->entriessize, "OldNewMap.entries");
+
+ memcpy(onm->entries, oentries, sizeof(*oentries)*osize);
+ MEM_freeN(oentries);
+ }
+
+ entry= &onm->entries[onm->nentries++];
+ entry->old= oldaddr;
+ entry->newp= newaddr;
+ entry->nr= nr;
+}
+
+static void *oldnewmap_lookup_and_inc(OldNewMap *onm, void *addr) {
+ int i;
+
+ if (onm->lasthit<onm->nentries-1) {
+ OldNew *entry= &onm->entries[++onm->lasthit];
+
+ if (entry->old==addr) {
+ entry->nr++;
+
+ return entry->newp;
+ }
+ }
+
+ for (i=0; i<onm->nentries; i++) {
+ OldNew *entry= &onm->entries[i];
+
+ if (entry->old==addr) {
+ onm->lasthit= i;
+
+ entry->nr++;
+ return entry->newp;
+ }
+ }
+
+ return NULL;
+}
+
+static void *oldnewmap_liblookup_and_inc(OldNewMap *onm, void *addr, void *lib) {
+ int i;
+
+ if (onm->lasthit<onm->nentries-1) {
+ OldNew *entry= &onm->entries[++onm->lasthit];
+
+ if (entry->old==addr) {
+ ID *id= entry->newp;
+
+ if (id && (!lib || id->lib)) {
+ entry->nr++;
+
+ return entry->newp;
+ }
+ }
+ }
+
+ for (i=0; i<onm->nentries; i++) {
+ OldNew *entry= &onm->entries[i];
+
+ if (entry->old==addr) {
+ ID *id= entry->newp;
+
+ if (id && (!lib || id->lib)) {
+ entry->nr++;
+
+ return entry->newp;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+static void *oldnewmap_typelookup_and_inc(OldNewMap *onm, void *addr, short type) {
+ int i;
+
+ if (onm->lasthit<onm->nentries-1) {
+ OldNew *entry= &onm->entries[++onm->lasthit];
+
+ if (entry->old==addr) {
+ ID *id= entry->newp;
+
+ if (id && (GS(id->name) == type)) {
+ entry->nr++;
+
+ return entry->newp;
+ }
+ }
+ }
+
+ for (i=0; i<onm->nentries; i++) {
+ OldNew *entry= &onm->entries[i];
+
+ if (entry->old==addr) {
+ ID *id= entry->newp;
+
+ if (id && (GS(id->name) == type)) {
+ entry->nr++;
+
+ return entry->newp;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+static void oldnewmap_free_unused(OldNewMap *onm) {
+ int i;
+
+ for (i=0; i<onm->nentries; i++) {
+ OldNew *entry= &onm->entries[i];
+ if (entry->nr==0) {
+ MEM_freeN(entry->newp);
+ entry->newp= NULL;
+ }
+ }
+}
+
+static void oldnewmap_clear(OldNewMap *onm) {
+ onm->nentries= 0;
+ onm->lasthit= 0;
+}
+
+static void oldnewmap_free(OldNewMap *onm) {
+ MEM_freeN(onm->entries);
+ MEM_freeN(onm);
+}
+
+/***/
+
+static void read_libraries(FileData *basefd, ListBase *mainlist);
+
+/* ************ OTHER CRAP ***************** */
+
+static void add_main_to_main(Main *mainvar, Main *from)
+{
+ ListBase *lbarray[30], *fromarray[30];
+ int a;
+
+ a= set_listbasepointers(mainvar, lbarray);
+ a= set_listbasepointers(from, fromarray);
+ while(a--) {
+ addlisttolist(lbarray[a], fromarray[a]);
+ }
+}
+
+void blo_join_main(ListBase *mainlist)
+{
+ Main *tojoin, *main= mainlist->first;
+
+ while (tojoin= main->next) {
+ add_main_to_main(main, tojoin);
+ BLI_remlink(mainlist, tojoin);
+ MEM_freeN(tojoin);
+ }
+}
+
+static void split_libdata(ListBase *lb, Main *first)
+{
+ ListBase *lbn;
+ ID *id, *idnext;
+ Main *mainvar;
+
+ id= lb->first;
+ while(id) {
+ idnext= id->next;
+ if(id->lib) {
+ mainvar= first;
+ while(mainvar) {
+ if(mainvar->curlib==id->lib) {
+ lbn= wich_libbase(mainvar, GS(id->name));
+ BLI_remlink(lb, id);
+ BLI_addtail(lbn, id);
+ break;
+ }
+ mainvar= mainvar->next;
+ }
+ if(mainvar==0) printf("error split_libdata\n");
+ }
+ id= idnext;
+ }
+}
+
+void blo_split_main(ListBase *mainlist)
+{
+ Main *main= mainlist->first;
+ ListBase *lbarray[30];
+ Library *lib;
+ int i;
+
+ for (lib= main->library.first; lib; lib= lib->id.next) {
+ Main *libmain= MEM_callocN(sizeof(*libmain), "libmain");
+ libmain->curlib= lib;
+
+ BLI_addtail(mainlist, libmain);
+ }
+
+ i= set_listbasepointers(main, lbarray);
+ while(i--)
+ split_libdata(lbarray[i], main->next);
+}
+
+static Main *blo_find_main(ListBase *mainlist, char *name)
+{
+ Main *m;
+ Library *lib;
+
+ for (m= mainlist->first; m; m= m->next) {
+ char *libname= (m->curlib)?m->curlib->name:m->name;
+
+ if (BLI_streq(name, libname))
+ return m;
+ }
+
+ m= MEM_callocN(sizeof(*m), "find_main");
+ BLI_addtail(mainlist, m);
+
+ lib= alloc_libblock(&m->library, ID_LI, "lib");
+ strcpy(lib->name, name);
+ m->curlib= lib;
+
+ return m;
+}
+
+
+/* ************ FILE PARSING ****************** */
+
+static void switch_endian_bh4(BHead4 *bhead)
+{
+ /* de ID_.. codes */
+ if((bhead->code & 0xFFFF)==0) bhead->code >>=16;
+
+ if (bhead->code != ENDB) {
+ SWITCH_INT(bhead->len);
+ SWITCH_INT(bhead->SDNAnr);
+ SWITCH_INT(bhead->nr);
+ }
+}
+
+static void switch_endian_bh8(BHead8 *bhead)
+{
+ /* de ID_.. codes */
+ if((bhead->code & 0xFFFF)==0) bhead->code >>=16;
+
+ if (bhead->code != ENDB) {
+ SWITCH_INT(bhead->len);
+ SWITCH_INT(bhead->SDNAnr);
+ SWITCH_INT(bhead->nr);
+ }
+}
+
+static void bh4_from_bh8(BHead *bhead, BHead8 *bhead8, int do_endian_swap)
+{
+ BHead4 *bhead4 = (BHead4 *) bhead;
+#ifdef WIN32
+ __int64 old;
+#else
+ long long old;
+#endif
+
+ bhead4->code= bhead8->code;
+ bhead4->len= bhead8->len;
+
+ if (bhead4->code != ENDB) {
+
+ // why is this here ??
+ if (do_endian_swap) {
+ SWITCH_LONGINT(bhead8->old);
+ }
+
+ /* this patch is to avoid a long long being read from not-eight aligned positions
+ is necessary on SGI with -n32 compiling (no, is necessary on
+ any modern 64bit architecture) */
+ memcpy(&old, &bhead8->old, 8);
+ bhead4->old = (int) (old >> 3);
+
+ bhead4->SDNAnr= bhead8->SDNAnr;
+ bhead4->nr= bhead8->nr;
+ }
+}
+
+static void bh8_from_bh4(BHead *bhead, BHead4 *bhead4)
+{
+ BHead8 *bhead8 = (BHead8 *) bhead;
+
+ bhead8->code= bhead4->code;
+ bhead8->len= bhead4->len;
+
+ if (bhead8->code != ENDB) {
+ bhead8->old= bhead4->old;
+ bhead8->SDNAnr= bhead4->SDNAnr;
+ bhead8->nr= bhead4->nr;
+ }
+}
+
+static BHeadN *get_bhead(FileData *fd)
+{
+ BHead8 bhead8;
+ BHead4 bhead4;
+ BHead bhead;
+ BHeadN *new_bhead = 0;
+ int readsize;
+
+ if (fd) {
+ if ( ! fd->eof) {
+
+ // First read the bhead structure.
+ // Depending on the platform the file was written on this can
+ // be a big or little endian BHead4 or BHead8 structure.
+
+ // As usual 'ENDB' (the last *partial* bhead of the file)
+ // needs some special handling. We don't want to EOF just yet.
+
+ if (fd->flags & FD_FLAGS_FILE_POINTSIZE_IS_4) {
+ bhead4.code = DATA;
+ readsize = fd->read(fd, &bhead4, sizeof(bhead4));
+
+ if (readsize == sizeof(bhead4) || bhead4.code == ENDB) {
+ if (fd->flags & FD_FLAGS_SWITCH_ENDIAN) {
+ switch_endian_bh4(&bhead4);
+ }
+
+ if (fd->flags & FD_FLAGS_POINTSIZE_DIFFERS) {
+ bh8_from_bh4(&bhead, &bhead4);
+ } else {
+ memcpy(&bhead, &bhead4, sizeof(bhead));
+ }
+ } else {
+ fd->eof = 1;
+ }
+ } else {
+ bhead8.code = DATA;
+ readsize = fd->read(fd, &bhead8, sizeof(bhead8));
+
+ if (readsize == sizeof(bhead8) || bhead8.code == ENDB) {
+ if (fd->flags & FD_FLAGS_SWITCH_ENDIAN) {
+ switch_endian_bh8(&bhead8);
+ }
+
+ if (fd->flags & FD_FLAGS_POINTSIZE_DIFFERS) {
+ bh4_from_bh8(&bhead, &bhead8, (fd->flags & FD_FLAGS_SWITCH_ENDIAN));
+ } else {
+ memcpy(&bhead, &bhead8, sizeof(bhead));
+ }
+ } else {
+ fd->eof = 1;
+ }
+ }
+
+ // bhead now contains the (converted) bhead structure. Now read
+ // the associated data and put everything in a BHeadN (creative naming !)
+
+ if ( ! fd->eof) {
+ new_bhead = MEM_mallocN(sizeof(BHeadN) + bhead.len, "new_bhead");
+ if (new_bhead) {
+ new_bhead->next = new_bhead->prev = 0;
+ new_bhead->bhead = bhead;
+
+ readsize = fd->read(fd, new_bhead + 1, bhead.len);
+
+ if (readsize != bhead.len) {
+ fd->eof = 1;
+ MEM_freeN(new_bhead);
+ }
+ } else {
+ fd->eof = 1;
+ }
+ }
+ }
+ }
+
+ // We've read a new block. Now add it to the list
+ // of blocks.
+
+ if (new_bhead) {
+ BLI_addtail(&fd->listbase, new_bhead);
+ }
+
+ return(new_bhead);
+}
+
+BHead *blo_firstbhead(FileData *fd)
+{
+ BHeadN *new_bhead;
+ BHead *bhead = 0;
+
+ // Rewind the file
+ // Read in a new block if necessary
+
+ new_bhead = fd->listbase.first;
+ if (new_bhead == 0) {
+ new_bhead = get_bhead(fd);
+ }
+
+ if (new_bhead) {
+ bhead = &new_bhead->bhead;
+ }
+
+ return(bhead);
+}
+
+BHead *blo_prevbhead(FileData *fd, BHead *thisblock)
+{
+ BHeadN *bheadn= (BHeadN *) (((char *) thisblock) - (int) (&((BHeadN*)0)->bhead));
+ BHeadN *prev= bheadn->prev;
+
+ return prev?&prev->bhead:NULL;
+}
+
+BHead *blo_nextbhead(FileData *fd, BHead *thisblock)
+{
+ BHeadN *new_bhead = 0;
+ BHead *bhead = 0;
+
+ if (thisblock) {
+ // bhead is actually a sub part of BHeadN
+ // We calculate the BHeadN pointer from the BHead pointer below
+ new_bhead = (BHeadN *) (((char *) thisblock) - (int) (&((BHeadN*)0)->bhead));
+
+ // get the next BHeadN. If it doesn't exist we read in the next one
+ new_bhead = new_bhead->next;
+ if (new_bhead == 0) {
+ new_bhead = get_bhead(fd);
+ }
+ }
+
+ if (new_bhead) {
+ // here we do the reverse:
+ // go from the BHeadN pointer to the BHead pointer
+ bhead = &new_bhead->bhead;
+ }
+
+ return(bhead);
+}
+
+static void decode_blender_header(FileData *fd)
+{
+ char header[SIZEOFBLENDERHEADER], num[4];
+ int readsize;
+
+ // read in the header data
+ readsize = fd->read(fd, header, sizeof(header));
+
+ if (readsize == sizeof(header)) {
+ if(strncmp(header, "BLENDER", 7) == 0) {
+ int remove_this_endian_test= 1;
+
+ fd->flags |= FD_FLAGS_FILE_OK;
+
+ // what size are pointers in the file ?
+ if(header[7]=='_') {
+ fd->flags |= FD_FLAGS_FILE_POINTSIZE_IS_4;
+ if (sizeof(void *) != 4) {
+ fd->flags |= FD_FLAGS_POINTSIZE_DIFFERS;
+ }
+ } else {
+ if (sizeof(void *) != 8) {
+ fd->flags |= FD_FLAGS_POINTSIZE_DIFFERS;
+ }
+ }
+
+ // is the file saved in a different endian
+ // than we need ?
+ if (((((char*)&remove_this_endian_test)[0]==1)?L_ENDIAN:B_ENDIAN) != ((header[8]=='v')?L_ENDIAN:B_ENDIAN)) {
+ fd->flags |= FD_FLAGS_SWITCH_ENDIAN;
+ }
+
+ // get the version number
+
+ memcpy(num, header+9, 3);
+ num[3] = 0;
+ fd->fileversion = atoi(num);
+ }
+ }
+}
+
+static int read_file_dna(FileData *fd)
+{
+ BHead *bhead;
+
+ for (bhead= blo_firstbhead(fd); bhead; bhead= blo_nextbhead(fd, bhead)) {
+ if (bhead->code==DNA1) {
+ int do_endian_swap= (fd->flags&FD_FLAGS_SWITCH_ENDIAN)?1:0;
+
+ fd->filesdna= dna_sdna_from_data(&bhead[1], bhead->len, do_endian_swap);
+ if (fd->filesdna)
+ fd->compflags= dna_get_structDNA_compareflags(fd->filesdna, fd->memsdna);
+
+ return 1;
+ } else if (bhead->code==ENDB)
+ break;
+ }
+
+ return 0;
+}
+static int fd_read_from_file(FileData *filedata, void *buffer, int size)
+{
+ int readsize = read(filedata->filedes, buffer, size);
+
+ if (readsize < 0) {
+ readsize = EOF;
+ } else {
+ filedata->seek += readsize;
+ }
+
+ return (readsize);
+}
+
+static int fd_read_from_memory(FileData *filedata, void *buffer, int size)
+{
+ // don't read more bytes then there are available in the buffer
+ int readsize = MIN2(size, filedata->buffersize - filedata->seek);
+
+ memcpy(buffer, filedata->buffer + filedata->seek, readsize);
+ filedata->seek += readsize;
+
+ return (readsize);
+}
+
+static FileData *filedata_new(void)
+{
+ extern char DNAstr[]; /* DNA.c */
+ extern int DNAlen;
+ FileData *fd = MEM_callocN(sizeof(*fd), "FileData");
+
+ fd->filedes = -1;
+
+ /* XXX, this doesn't need to be done all the time,
+ * but it keeps us reentrant, remove once we have
+ * a lib that provides a nice lock. - zr
+ */
+ fd->memsdna = dna_sdna_from_data(DNAstr, DNAlen, 0);
+
+ fd->datamap = oldnewmap_new();
+ fd->globmap = oldnewmap_new();
+ fd->libmap = oldnewmap_new();
+
+ return fd;
+}
+
+FileData *blo_openblenderfile(char *name)
+{
+ int file= open(name, O_BINARY|O_RDONLY);
+
+ if (file == -1) {
+ return NULL;
+ } else {
+ FileData *fd = filedata_new();
+ fd->filedes = file;
+ fd->buffersize = BLI_filesize(file);
+ fd->read = fd_read_from_file;
+
+ decode_blender_header(fd);
+
+ if (fd->flags & FD_FLAGS_FILE_OK) {
+ if (!read_file_dna(fd)) {
+ blo_freefiledata(fd);
+ fd= NULL;
+ }
+ } else {
+ blo_freefiledata(fd);
+ fd= NULL;
+ }
+
+ return fd;
+ }
+}
+
+FileData *blo_openblendermemory(void *mem, int memsize)
+{
+ if (!mem || memsize<SIZEOFBLENDERHEADER) {
+ return NULL;
+ } else {
+ FileData *fd= filedata_new();
+ fd->buffer= mem;
+ fd->buffersize= memsize;
+ fd->read= fd_read_from_memory;
+ fd->flags|= FD_FLAGS_NOT_MY_BUFFER;
+
+ decode_blender_header(fd);
+
+ if (fd->flags & FD_FLAGS_FILE_OK) {
+ if (!read_file_dna(fd)) {
+ blo_freefiledata(fd);
+ fd= NULL;
+ }
+ } else {
+ blo_freefiledata(fd);
+ fd= NULL;
+ }
+
+ return fd;
+ }
+}
+
+void blo_freefiledata(FileData *fd)
+{
+ if (fd) {
+ if (fd->filedes != -1) {
+ close(fd->filedes);
+ }
+
+ if (fd->buffer && !(fd->flags & FD_FLAGS_NOT_MY_BUFFER)) {
+ MEM_freeN(fd->buffer);
+ fd->buffer = 0;
+ }
+
+ // Free all BHeadN data blocks
+ BLI_freelistN(&fd->listbase);
+
+ if (fd->memsdna)
+ dna_freestructDNA(fd->memsdna);
+ if (fd->filesdna)
+ dna_freestructDNA(fd->filesdna);
+ if (fd->compflags)
+ MEM_freeN(fd->compflags);
+
+ if (fd->datamap)
+ oldnewmap_free(fd->datamap);
+ if (fd->globmap)
+ oldnewmap_free(fd->globmap);
+ if (fd->libmap && !(fd->flags & FD_FLAGS_NOT_MY_LIBMAP))
+ oldnewmap_free(fd->libmap);
+
+ MEM_freeN(fd);
+ }
+}
+
+/* ************ DIV ****************** */
+
+int BLO_has_bfile_extension(char *str)
+{
+ return (BLI_testextensie(str, ".ble") || BLI_testextensie(str, ".blend"));
+}
+
+/* ************** OLD POINTERS ******************* */
+
+static void *newdataadr(FileData *fd, void *adr) /* only direct databocks */
+{
+ return oldnewmap_lookup_and_inc(fd->datamap, adr);
+}
+
+static void *newglobadr(FileData *fd, void *adr) /* direct datablocks with global linking */
+{
+ return oldnewmap_lookup_and_inc(fd->globmap, adr);
+}
+
+static void *newlibadr(FileData *fd, void *lib, void *adr) /* only lib data */
+{
+ return oldnewmap_liblookup_and_inc(fd->libmap, adr, lib);
+}
+
+static void *newlibadr_us_type(FileData *fd, short type, void *adr) /* alleen Lib datablokken */
+{
+ ID *id= oldnewmap_typelookup_and_inc(fd->libmap, adr, type);
+
+ if (id) {
+ id->us++;
+ }
+
+ return id;
+}
+
+static void *newlibadr_us(FileData *fd, void *lib, void *adr) /* hoogt usernummer op */
+{
+ ID *id= newlibadr(fd, lib, adr);
+
+ if(id) {
+ id->us++;
+ }
+
+ return id;
+}
+
+static void change_libadr(FileData *fd, void *old, void *new)
+{
+ int i;
+
+ /* changed one thing here, the old change_libadr
+ * only remapped addresses that had an id->lib,
+ * but that doesn't make sense to me... its an
+ * old pointer, period, it needs to be remapped. - zr
+ */
+
+ /*
+ * Ton seemed to think it was necessary to look
+ * through all entries, and not return after finding
+ * a match, leaving this cryptic comment,
+ * // geen return blijkbaar kunnen er meer zijn?
+ *
+ * That doesn't make sense to me either but I am
+ * too scared to remove it... it only would make
+ * sense if two distinct old address map to the
+ * same new address - obviously that shouldn't happen
+ * because memory addresses are unique.
+ *
+ * The only case it might happen is when two distinct
+ * libraries are mapped using the same table... this
+ * won't work to start with... At some point this
+ * all needs to be made sense of and made understandable,
+ * but I'm afraid I don't have time now. -zr
+ *
+ */
+ for (i=0; i<fd->libmap->nentries; i++) {
+ OldNew *entry= &fd->libmap->entries[i];
+
+ if (old==entry->newp) {
+ entry->newp= new;
+ break;
+ }
+ }
+}
+
+
+/* ********** END OUDE POINTERS ****************** */
+/* ********** READ FILE ****************** */
+
+static void switch_endian_structs(struct SDNA *filesdna, BHead *bhead)
+{
+ int blocksize, nblocks;
+ char *data;
+
+ data= (char *)(bhead+1); /* BHEAD+DATA dependancy */
+ blocksize= filesdna->typelens[ filesdna->structs[bhead->SDNAnr][0] ];
+
+ nblocks= bhead->nr;
+ while(nblocks--) {
+ dna_switch_endian_struct(filesdna, bhead->SDNAnr, data);
+
+ data+= blocksize;
+ }
+}
+
+static void *read_struct(FileData *fd, BHead *bh)
+{
+ void *temp= NULL;
+
+ if (bh->len) {
+ if (bh->SDNAnr && (fd->flags & FD_FLAGS_SWITCH_ENDIAN))
+ switch_endian_structs(fd->filesdna, bh);
+
+ if (fd->compflags[bh->SDNAnr]) { /* flag==0: doesn't exist anymore */
+ if(fd->compflags[bh->SDNAnr]==2) {
+ temp= dna_reconstruct(fd->memsdna, fd->filesdna, fd->compflags, bh->SDNAnr, bh->nr, (bh+1));
+ } else {
+ temp= MEM_mallocN(bh->len, "read_struct");
+ memcpy(temp, (bh+1), bh->len); /* BHEAD+DATA dependancy */
+ }
+ }
+ }
+
+ return temp;
+}
+
+static void link_list(FileData *fd, ListBase *lb) /* alleen direkte data */
+{
+ Link *ln, *prev;
+
+ if(lb->first==0) return;
+
+ lb->first= newdataadr(fd, lb->first);
+ ln= lb->first;
+ prev= 0;
+ while(ln) {
+ ln->next= newdataadr(fd, ln->next);
+ ln->prev= prev;
+ prev= ln;
+ ln= ln->next;
+ }
+ lb->last= prev;
+}
+
+static void link_glob_list(FileData *fd, ListBase *lb) /* for glob data */
+{
+ Link *ln, *prev;
+ void *poin;
+
+ if(lb->first==0) return;
+
+ poin= newdataadr(fd, lb->first);
+ if(lb->first) {
+ oldnewmap_insert(fd->globmap, lb->first, poin, 0);
+ }
+ lb->first= poin;
+
+ ln= lb->first;
+ prev= 0;
+ while(ln) {
+ poin= newdataadr(fd, ln->next);
+ if(ln->next) {
+ oldnewmap_insert(fd->globmap, ln->next, poin, 0);
+ }
+ ln->next= poin;
+ ln->prev= prev;
+ prev= ln;
+ ln= ln->next;
+ }
+ lb->last= prev;
+}
+
+static void test_pointer_array(FileData *fd, void **mat)
+{
+#ifdef WIN32
+ __int64 *lpoin, *lmat;
+#else
+ long long *lpoin, *lmat;
+#endif
+ int len, *ipoin, *imat;
+
+ /* manually convert the pointer array in
+ * the old dna format to a pointer array in
+ * the new dna format.
+ */
+ if(*mat) {
+ len= MEM_allocN_len(*mat)/fd->filesdna->pointerlen;
+
+ if(fd->filesdna->pointerlen==8 && fd->memsdna->pointerlen==4) {
+ ipoin=imat= MEM_mallocN( len*4, "newmatar");
+ lpoin= *mat;
+
+ while(len-- > 0) {
+ if((fd->flags & FD_FLAGS_SWITCH_ENDIAN))
+ SWITCH_LONGINT(*lpoin);
+ *ipoin= (int) ((*lpoin) >> 3);
+ ipoin++;
+ lpoin++;
+ }
+ MEM_freeN(*mat);
+ *mat= imat;
+ }
+
+ if(fd->filesdna->pointerlen==4 && fd->memsdna->pointerlen==8) {
+ lpoin=lmat= MEM_mallocN( len*8, "newmatar");
+ ipoin= *mat;
+
+ while(len-- > 0) {
+ *lpoin= *ipoin;
+ ipoin++;
+ lpoin++;
+ }
+ MEM_freeN(*mat);
+ *mat= lmat;
+ }
+ }
+}
+
+/* ************ READ PACKEDFILE *************** */
+
+static PackedFile *direct_link_packedfile(FileData *fd, PackedFile *oldpf)
+{
+ PackedFile *pf= newdataadr(fd, oldpf);
+
+ if (pf) {
+ pf->data= newdataadr(fd, pf->data);
+ }
+
+ return pf;
+}
+
+/* ************ READ SCRIPTLINK *************** */
+
+static void lib_link_scriptlink(FileData *fd, ID *id, ScriptLink *slink)
+{
+ int i;
+
+ for(i=0; i<slink->totscript; i++) {
+ slink->scripts[i]= newlibadr(fd, id->lib, slink->scripts[i]);
+ }
+}
+
+static void direct_link_scriptlink(FileData *fd, ScriptLink *slink)
+{
+ slink->scripts= newdataadr(fd, slink->scripts);
+ slink->flag= newdataadr(fd, slink->flag);
+
+ if(fd->flags & FD_FLAGS_SWITCH_ENDIAN) {
+ int a;
+
+ for(a=0; a<slink->totscript; a++) {
+ SWITCH_SHORT(slink->flag[a]);
+ }
+ }
+}
+
+/* ************ READ IKA ***************** */
+
+static void lib_link_ika(FileData *fd, Main *main)
+{
+ Ika *ika;
+ int a;
+ Deform *def;
+
+ ika= main->ika.first;
+ while(ika) {
+ if(ika->id.flag & LIB_NEEDLINK) {
+
+ ika->parent= newlibadr(fd, ika->id.lib, ika->parent);
+
+ a= ika->totdef;
+ def= ika->def;
+ while(a--) {
+ def->ob= newlibadr(fd, ika->id.lib, def->ob);
+ def++;
+ }
+ ika->id.flag -= LIB_NEEDLINK;
+ }
+ ika= ika->id.next;
+ }
+}
+
+static void direct_link_ika(FileData *fd, Ika *ika)
+{
+ link_list(fd, &ika->limbbase);
+
+ ika->def= newdataadr(fd, ika->def);
+
+ /* afvangen fout uit V.138 en ouder */
+ if(ika->def==0) ika->totdef= 0;
+}
+
+/* ************ READ ARMATURE ***************** */
+
+static void lib_link_nlastrips(FileData *fd, ID *id, ListBase *striplist)
+{
+ bActionStrip *strip;
+
+ for (strip=striplist->first; strip; strip=strip->next){
+ strip->act = newlibadr(fd, id->lib, strip->act);
+ strip->ipo = newlibadr(fd, id->lib, strip->ipo);
+ };
+}
+
+static void lib_link_constraint_channels(FileData *fd, ID *id, ListBase *chanbase)
+{
+ bConstraintChannel *chan;
+
+ for (chan=chanbase->first; chan; chan=chan->next){
+ chan->ipo = newlibadr_us(fd, id->lib, chan->ipo);
+ }
+}
+
+static void lib_link_constraints(FileData *fd, ID *id, ListBase *conlist)
+{
+ bConstraint *con;
+
+ for (con = conlist->first; con; con=con->next) {
+ switch (con->type) {
+ case CONSTRAINT_TYPE_ACTION:
+ {
+ bActionConstraint *data;
+ data= ((bActionConstraint*)con->data);
+ data->tar = newlibadr(fd, id->lib, data->tar);
+ data->act = newlibadr(fd, id->lib, data->act);
+ }
+ break;
+ case CONSTRAINT_TYPE_LOCLIKE:
+ {
+ bLocateLikeConstraint *data;
+ data= ((bLocateLikeConstraint*)con->data);
+ data->tar = newlibadr(fd, id->lib, data->tar);
+ };
+ break;
+ case CONSTRAINT_TYPE_ROTLIKE:
+ {
+ bRotateLikeConstraint *data;
+ data= ((bRotateLikeConstraint*)con->data);
+ data->tar = newlibadr(fd, id->lib, data->tar);
+ };
+ break;
+ case CONSTRAINT_TYPE_KINEMATIC:
+ {
+ bKinematicConstraint *data;
+ data = ((bKinematicConstraint*)con->data);
+ data->tar = newlibadr(fd, id->lib, data->tar);
+ }
+ break;
+ case CONSTRAINT_TYPE_NULL:
+ break;
+ case CONSTRAINT_TYPE_TRACKTO:
+ {
+ bTrackToConstraint *data;
+ data = ((bTrackToConstraint*)con->data);
+ data->tar = newlibadr(fd, id->lib, data->tar);
+ }
+ break;
+
+ }
+ }
+}
+
+static void direct_link_constraints(FileData *fd, ListBase *lb)
+{
+ bConstraint *cons;
+
+ link_list(fd, lb);
+ for (cons=lb->first; cons; cons=cons->next) {
+ cons->data = newdataadr(fd, cons->data);
+ switch (cons->type) {
+ default:
+ break;
+ }
+ // Link data
+ }
+}
+
+static void lib_link_bone(FileData *fd, ID *id, Bone *bone)
+{
+ Bone *curBone;
+
+// lib_link_constraints(fd, id, &bone->constraints);
+
+ for (curBone=bone->childbase.first; curBone; curBone=curBone->next) {
+ lib_link_bone(fd, id, curBone);
+ }
+}
+
+
+static void lib_link_pose(FileData *fd, ID *id, bPose *pose)
+{
+ bPoseChannel *chan;
+
+ if (!pose)
+ return;
+
+ for (chan = pose->chanbase.first; chan; chan=chan->next) {
+ lib_link_constraints(fd, id, &chan->constraints);
+ }
+}
+
+static void lib_link_armature(FileData *fd, Main *main)
+{
+ bArmature *arm;
+ Bone *bone;
+
+ arm= main->armature.first;
+
+ while(arm) {
+ if(arm->id.flag & LIB_NEEDLINK) {
+ arm->id.flag -= LIB_NEEDLINK;
+ }
+
+ for (bone=arm->bonebase.first; bone; bone=bone->next) {
+ lib_link_bone(fd, &arm->id, bone);
+ }
+
+ arm= arm->id.next;
+ }
+}
+
+static void lib_link_action(FileData *fd, Main *main)
+{
+ bAction *act;
+ bActionChannel *chan;
+
+ act= main->action.first;
+ while(act) {
+ if(act->id.flag & LIB_NEEDLINK) {
+ act->id.flag -= LIB_NEEDLINK;
+
+ for (chan=act->chanbase.first; chan; chan=chan->next) {
+ chan->ipo= newlibadr_us(fd, act->id.lib, chan->ipo);
+ lib_link_constraint_channels(fd, &act->id, &chan->constraintChannels);
+ }
+
+ }
+ act= act->id.next;
+ }
+}
+
+static void direct_link_bones(FileData *fd, Bone* bone)
+{
+ Bone *child;
+
+ bone->parent= newdataadr(fd, bone->parent);
+
+ link_list(fd, &bone->childbase);
+
+ for (child=bone->childbase.first; child; child=child->next) {
+ direct_link_bones(fd, child);
+ }
+}
+
+
+static void direct_link_action(FileData *fd, bAction *act)
+{
+ bActionChannel *achan;
+
+ link_list(fd, &act->chanbase);
+
+ for (achan = act->chanbase.first; achan; achan=achan->next)
+ link_list(fd, &achan->constraintChannels);
+
+}
+
+static void direct_link_armature(FileData *fd, bArmature *arm)
+{
+ Bone *bone;
+
+ link_list(fd, &arm->bonebase);
+
+ bone=arm->bonebase.first;
+ while (bone) {
+ direct_link_bones(fd, bone);
+ bone=bone->next;
+ }
+}
+
+/* ************ READ CAMERA ***************** */
+
+static void lib_link_camera(FileData *fd, Main *main)
+{
+ Camera *ca;
+
+ ca= main->camera.first;
+ while(ca) {
+ if(ca->id.flag & LIB_NEEDLINK) {
+
+ ca->ipo= newlibadr_us(fd, ca->id.lib, ca->ipo);
+
+ lib_link_scriptlink(fd, &ca->id, &ca->scriptlink);
+
+ ca->id.flag -= LIB_NEEDLINK;
+ }
+ ca= ca->id.next;
+ }
+}
+
+static void direct_link_camera(FileData *fd, Camera *ca)
+{
+ direct_link_scriptlink(fd, &ca->scriptlink);
+}
+
+
+/* ************ READ LATTICE ***************** */
+
+static void lib_link_latt(FileData *fd, Main *main)
+{
+ Lattice *lt;
+
+ lt= main->latt.first;
+ while(lt) {
+ if(lt->id.flag & LIB_NEEDLINK) {
+
+ lt->ipo= newlibadr_us(fd, lt->id.lib, lt->ipo);
+ lt->key= newlibadr_us(fd, lt->id.lib, lt->key);
+
+ lt->id.flag -= LIB_NEEDLINK;
+ }
+ lt= lt->id.next;
+ }
+}
+
+static void direct_link_latt(FileData *fd, Lattice *lt)
+{
+ lt->def= newdataadr(fd, lt->def);
+}
+
+/* ************ READ LAMP ***************** */
+
+static void lib_link_lamp(FileData *fd, Main *main)
+{
+ Lamp *la;
+ MTex *mtex;
+ int a;
+
+ la= main->lamp.first;
+ while(la) {
+ if(la->id.flag & LIB_NEEDLINK) {
+
+ for(a=0; a<8; a++) {
+ mtex= la->mtex[a];
+ if(mtex) {
+ mtex->tex= newlibadr_us(fd, la->id.lib, mtex->tex);
+ mtex->object= newlibadr(fd, la->id.lib, mtex->object);
+ }
+ }
+
+ la->ipo= newlibadr_us(fd, la->id.lib, la->ipo);
+
+ lib_link_scriptlink(fd, &la->id, &la->scriptlink);
+
+ la->id.flag -= LIB_NEEDLINK;
+ }
+ la= la->id.next;
+ }
+}
+
+static void direct_link_lamp(FileData *fd, Lamp *la)
+{
+ int a;
+
+ direct_link_scriptlink(fd, &la->scriptlink);
+
+ for(a=0; a<8; a++) {
+ la->mtex[a]= newdataadr(fd, la->mtex[a]);
+ }
+}
+
+/* ************ READ keys ***************** */
+
+static void lib_link_key(FileData *fd, Main *main)
+{
+ Key *key;
+
+ key= main->key.first;
+ while(key) {
+ if(key->id.flag & LIB_NEEDLINK) {
+
+ key->ipo= newlibadr_us(fd, key->id.lib, key->ipo);
+ key->from= newlibadr(fd, key->id.lib, key->from);
+
+ key->id.flag -= LIB_NEEDLINK;
+ }
+ key= key->id.next;
+ }
+}
+
+static void switch_endian_keyblock(Key *key, KeyBlock *kb)
+{
+ int elemsize, a, b;
+ char *data, *poin, *cp;
+
+ elemsize= key->elemsize;
+ data= kb->data;
+
+ for(a=0; a<kb->totelem; a++) {
+
+ cp= key->elemstr;
+ poin= data;
+
+ while( cp[0] ) { /* cp[0]==aantal */
+
+ switch(cp[1]) { /* cp[1]= type */
+ case IPO_FLOAT:
+ case IPO_BPOINT:
+ case IPO_BEZTRIPLE:
+ b= cp[0];
+ while(b--) {
+ SWITCH_INT((*poin));
+ poin+= 4;
+ }
+ break;
+ }
+
+ cp+= 2;
+
+ }
+ data+= elemsize;
+ }
+}
+
+static void direct_link_key(FileData *fd, Key *key)
+{
+ KeyBlock *kb;
+
+ link_list(fd, &(key->block));
+
+ key->refkey= newdataadr(fd, key->refkey);
+
+ kb= key->block.first;
+ while(kb) {
+
+ kb->data= newdataadr(fd, kb->data);
+
+ if(fd->flags & FD_FLAGS_SWITCH_ENDIAN)
+ switch_endian_keyblock(key, kb);
+
+ kb= kb->next;
+ }
+}
+
+/* ************ READ mball ***************** */
+
+static void lib_link_mball(FileData *fd, Main *main)
+{
+ MetaBall *mb;
+ int a;
+
+ mb= main->mball.first;
+ while(mb) {
+ if(mb->id.flag & LIB_NEEDLINK) {
+
+ for(a=0; a<mb->totcol; a++) mb->mat[a]= newlibadr_us(fd, mb->id.lib, mb->mat[a]);
+
+ mb->ipo= newlibadr_us(fd, mb->id.lib, mb->ipo);
+
+ mb->id.flag -= LIB_NEEDLINK;
+ }
+ mb= mb->id.next;
+ }
+}
+
+static void direct_link_mball(FileData *fd, MetaBall *mb)
+{
+ mb->mat= newdataadr(fd, mb->mat);
+ test_pointer_array(fd, (void **)&mb->mat);
+
+ link_list(fd, &(mb->elems));
+
+ mb->disp.first= mb->disp.last= 0;
+
+ mb->bb= 0;
+}
+
+/* ************ READ WORLD ***************** */
+
+static void lib_link_world(FileData *fd, Main *main)
+{
+ World *wrld;
+ MTex *mtex;
+ int a;
+
+ wrld= main->world.first;
+ while(wrld) {
+ if(wrld->id.flag & LIB_NEEDLINK) {
+
+ wrld->ipo= newlibadr_us(fd, wrld->id.lib, wrld->ipo);
+
+ for(a=0; a<8; a++) {
+ mtex= wrld->mtex[a];
+ if(mtex) {
+ mtex->tex= newlibadr_us(fd, wrld->id.lib, mtex->tex);
+ mtex->object= newlibadr(fd, wrld->id.lib, mtex->object);
+ }
+ }
+
+ lib_link_scriptlink(fd, &wrld->id, &wrld->scriptlink);
+
+ wrld->id.flag -= LIB_NEEDLINK;
+ }
+ wrld= wrld->id.next;
+ }
+}
+
+static void direct_link_world(FileData *fd, World *wrld)
+{
+ int a;
+
+ direct_link_scriptlink(fd, &wrld->scriptlink);
+
+ for(a=0; a<8; a++) {
+ wrld->mtex[a]= newdataadr(fd, wrld->mtex[a]);
+ }
+}
+
+
+/* ************ READ IPO ***************** */
+
+static void lib_link_ipo(FileData *fd, Main *main)
+{
+ Ipo *ipo;
+
+ ipo= main->ipo.first;
+ while(ipo) {
+ if(ipo->id.flag & LIB_NEEDLINK) {
+
+ ipo->id.flag -= LIB_NEEDLINK;
+ }
+ ipo= ipo->id.next;
+ }
+}
+
+static void direct_link_ipo(FileData *fd, Ipo *ipo)
+{
+ IpoCurve *icu;
+
+ link_list(fd, &(ipo->curve));
+ icu= ipo->curve.first;
+ while(icu) {
+ icu->bezt= newdataadr(fd, icu->bezt);
+ icu->bp= newdataadr(fd, icu->bp);
+ icu= icu->next;
+ }
+}
+
+/* ************ READ VFONT ***************** */
+
+static void lib_link_vfont(FileData *fd, Main *main)
+{
+ VFont *vf;
+
+ vf= main->vfont.first;
+ while(vf) {
+ if(vf->id.flag & LIB_NEEDLINK) {
+ vf->id.flag -= LIB_NEEDLINK;
+ }
+ vf= vf->id.next;
+ }
+}
+
+static void direct_link_vfont(FileData *fd, VFont *vf)
+{
+ vf->data= NULL;
+ vf->packedfile= direct_link_packedfile(fd, vf->packedfile);
+}
+
+/* ************ READ TEXT ****************** */
+
+static void lib_link_text(FileData *fd, Main *main)
+{
+ Text *text;
+
+ text= main->text.first;
+ while(text) {
+ if(text->id.flag & LIB_NEEDLINK) {
+ text->id.flag -= LIB_NEEDLINK;
+ }
+ text= text->id.next;
+ }
+}
+
+static void direct_link_text(FileData *fd, Text *text)
+{
+ TextLine *ln;
+
+ text->name= newdataadr(fd, text->name);
+
+ text->undo_pos= -1;
+ text->undo_len= TXT_INIT_UNDO;
+ text->undo_buf= MEM_mallocN(text->undo_len, "undo buf");
+
+ text->compiled= NULL;
+
+ if(text->flags & TXT_ISEXT) {
+ /* not implemented yet... */
+ /* reopen_text(text); */
+ } else {
+
+ if(text->lines.first==0) return;
+
+ link_list(fd, &text->lines);
+
+ text->curl= newdataadr(fd, text->curl);
+ text->sell= newdataadr(fd, text->sell);
+
+ ln= text->lines.first;
+ while(ln) {
+ ln->line= newdataadr(fd, ln->line);
+
+ if (ln->len != (int) strlen(ln->line)) {
+ printf("Error loading text, line lengths differ\n");
+ ln->len = strlen(ln->line);
+ }
+
+ ln= ln->next;
+ }
+
+ text->flags |= TXT_ISTMP;
+ }
+
+ text->id.us= 1;
+}
+
+/* ************ READ IMAGE ***************** */
+
+static void lib_link_image(FileData *fd, Main *main)
+{
+ Image *ima;
+
+ ima= main->image.first;
+ while (ima) {
+ if(ima->id.flag & LIB_NEEDLINK) {
+
+ ima->id.flag -= LIB_NEEDLINK;
+ }
+ ima= ima->id.next;
+ }
+}
+
+static void direct_link_image(FileData *fd, Image *ima)
+{
+ ima->ibuf= 0;
+ ima->anim= 0;
+ memset(ima->mipmap, 0, sizeof(ima->mipmap));
+ ima->repbind= 0;
+ ima->bindcode= 0;
+
+ ima->packedfile = direct_link_packedfile(fd, ima->packedfile);
+
+ ima->ok= 1;
+}
+
+
+/* ************ READ CURVE ***************** */
+
+static void lib_link_curve(FileData *fd, Main *main)
+{
+ Curve *cu;
+ int a;
+
+ cu= main->curve.first;
+ while(cu) {
+ if(cu->id.flag & LIB_NEEDLINK) {
+
+ for(a=0; a<cu->totcol; a++) cu->mat[a]= newlibadr_us(fd, cu->id.lib, cu->mat[a]);
+
+ cu->bevobj= newlibadr(fd, cu->id.lib, cu->bevobj);
+ cu->textoncurve= newlibadr(fd, cu->id.lib, cu->textoncurve);
+ cu->vfont= newlibadr_us(fd, cu->id.lib, cu->vfont);
+
+ cu->ipo= newlibadr_us(fd, cu->id.lib, cu->ipo);
+ cu->key= newlibadr_us(fd, cu->id.lib, cu->key);
+
+ cu->id.flag -= LIB_NEEDLINK;
+ }
+ cu= cu->id.next;
+ }
+}
+
+
+static void switch_endian_knots(Nurb *nu)
+{
+ int len;
+
+ if(nu->knotsu) {
+ len= KNOTSU(nu);
+ while(len--) {
+ SWITCH_INT(nu->knotsu[len]);
+ }
+ }
+ if(nu->knotsv) {
+ len= KNOTSV(nu);
+ while(len--) {
+ SWITCH_INT(nu->knotsv[len]);
+ }
+ }
+}
+
+static void direct_link_curve(FileData *fd, Curve *cu)
+{
+ Nurb *nu;
+
+ cu->mat= newdataadr(fd, cu->mat);
+ test_pointer_array(fd, (void **)&cu->mat);
+ cu->str= newdataadr(fd, cu->str);
+
+ if(cu->vfont==0) link_list(fd, &(cu->nurb));
+ else {
+ cu->nurb.first=cu->nurb.last= 0;
+ }
+
+ cu->bev.first=cu->bev.last= 0;
+ cu->disp.first=cu->disp.last= 0;
+ cu->path= 0;
+
+ nu= cu->nurb.first;
+ while(nu) {
+ nu->bezt= newdataadr(fd, nu->bezt);
+ nu->bp= newdataadr(fd, nu->bp);
+ nu->knotsu= newdataadr(fd, nu->knotsu);
+ nu->knotsv= newdataadr(fd, nu->knotsv);
+
+ if(fd->flags & FD_FLAGS_SWITCH_ENDIAN) {
+ switch_endian_knots(nu);
+ }
+
+ nu= nu->next;
+ }
+ cu->bb= 0;
+}
+
+/* ************ READ TEX ***************** */
+
+static void lib_link_texture(FileData *fd, Main *main)
+{
+ Tex *tex;
+
+ tex= main->tex.first;
+ while(tex) {
+ if(tex->id.flag & LIB_NEEDLINK) {
+
+ tex->ima= newlibadr_us(fd, tex->id.lib, tex->ima);
+ tex->ipo= newlibadr_us(fd, tex->id.lib, tex->ipo);
+ if(tex->env) tex->env->object= newlibadr(fd, tex->id.lib, tex->env->object);
+
+ tex->id.flag -= LIB_NEEDLINK;
+ }
+ tex= tex->id.next;
+ }
+}
+
+static void direct_link_texture(FileData *fd, Tex *tex)
+{
+ tex->plugin= newdataadr(fd, tex->plugin);
+ if(tex->plugin) {
+ tex->plugin->handle= 0;
+ open_plugin_tex(tex->plugin);
+ }
+ tex->coba= newdataadr(fd, tex->coba);
+ tex->env= newdataadr(fd, tex->env);
+ if(tex->env) {
+ tex->env->ima= 0;
+ memset(tex->env->cube, 0, 6*sizeof(void *));
+ tex->env->ok= 0;
+ }
+}
+
+
+
+/* ************ READ MATERIAL ***************** */
+
+static void lib_link_material(FileData *fd, Main *main)
+{
+ Material *ma;
+ MTex *mtex;
+ int a;
+
+ ma= main->mat.first;
+ while(ma) {
+ if(ma->id.flag & LIB_NEEDLINK) {
+
+ ma->ipo= newlibadr_us(fd, ma->id.lib, ma->ipo);
+
+ for(a=0; a<8; a++) {
+ mtex= ma->mtex[a];
+ if(mtex) {
+ mtex->tex= newlibadr_us(fd, ma->id.lib, mtex->tex);
+ mtex->object= newlibadr(fd, ma->id.lib, mtex->object);
+ }
+ }
+ lib_link_scriptlink(fd, &ma->id, &ma->scriptlink);
+ ma->id.flag -= LIB_NEEDLINK;
+ }
+ ma= ma->id.next;
+ }
+}
+
+static void direct_link_material(FileData *fd, Material *ma)
+{
+ int a;
+
+ direct_link_scriptlink(fd, &ma->scriptlink);
+
+ for(a=0; a<8; a++) {
+ ma->mtex[a]= newdataadr(fd, ma->mtex[a]);
+ }
+ ma->ren= 0; /* mag niet blijven hangen, maarja */
+}
+
+/* ************ READ MESH ***************** */
+
+static void lib_link_mesh(FileData *fd, Main *main)
+{
+ Mesh *me;
+
+ me= main->mesh.first;
+ while(me) {
+ if(me->id.flag & LIB_NEEDLINK) {
+ int i;
+
+ for(i=0; i<me->totcol; i++)
+ me->mat[i]= newlibadr_us(fd, me->id.lib, me->mat[i]);
+
+ me->ipo= newlibadr_us(fd, me->id.lib, me->ipo);
+ me->key= newlibadr_us(fd, me->id.lib, me->key);
+ me->texcomesh= newlibadr_us(fd, me->id.lib, me->texcomesh);
+
+ if(me->tface) {
+ TFace *tfaces= me->tface;
+
+ for (i=0; i<me->totface; i++) {
+ TFace *tf= &tfaces[i];
+
+ tf->tpage= newlibadr(fd, me->id.lib, tf->tpage);
+ if(tf->tpage) {
+ Image *ima= tf->tpage;
+ if(ima->id.us==0)
+ ima->id.us= 1;
+ }
+ }
+ }
+ me->id.flag -= LIB_NEEDLINK;
+ }
+ me= me->id.next;
+ }
+}
+
+static void direct_link_dverts(FileData *fd, int count, MDeformVert *mdverts)
+{
+ int i, j;
+
+ if (!mdverts)
+ return;
+
+ for (i=0; i<count; i++) {
+ mdverts[i].dw=newdataadr(fd, mdverts[i].dw);
+ if (!mdverts[i].dw)
+ mdverts[i].totweight=0;
+
+ for (j=0; j< mdverts[i].totweight; j++) {
+ mdverts[i].dw[j].data = newdataadr(fd, mdverts[i].dw[j].data);
+ }
+ }
+
+}
+
+static void direct_link_mesh(FileData *fd, Mesh *mesh)
+{
+ mesh->mat= newdataadr(fd, mesh->mat);
+ test_pointer_array(fd, (void **)&mesh->mat);
+ mesh->mvert= newdataadr(fd, mesh->mvert);
+
+ mesh->dvert= newdataadr(fd, mesh->dvert);
+ direct_link_dverts(fd, mesh->totvert, mesh->dvert);
+
+ mesh->mface= newdataadr(fd, mesh->mface);
+ mesh->tface= newdataadr(fd, mesh->tface);
+ mesh->mcol= newdataadr(fd, mesh->mcol);
+ mesh->msticky= newdataadr(fd, mesh->msticky);
+
+ mesh->disp.first= mesh->disp.last= 0;
+ mesh->bb= 0;
+ mesh->oc= 0;
+ mesh->dface= 0;
+ mesh->orco= 0;
+
+ if (mesh->tface) {
+ TFace *tfaces= mesh->tface;
+ int i;
+
+ for (i=0; i<mesh->totface; i++) {
+ TFace *tf= &tfaces[i];
+
+ if(fd->flags & FD_FLAGS_SWITCH_ENDIAN) {
+ SWITCH_INT(tf->col[0]);
+ SWITCH_INT(tf->col[1]);
+ SWITCH_INT(tf->col[2]);
+ SWITCH_INT(tf->col[3]);
+ }
+ }
+ }
+}
+
+/* ************ READ OBJECT ***************** */
+
+static void lib_link_object(FileData *fd, Main *main)
+{
+ Object *ob;
+ bSensor *sens;
+ bController *cont;
+ bActuator *act;
+
+ void *poin;
+ int warn=0, a;
+
+ ob= main->object.first;
+ while(ob) {
+ if(ob->id.flag & LIB_NEEDLINK) {
+
+ ob->parent= newlibadr(fd, ob->id.lib, ob->parent);
+ ob->track= newlibadr(fd, ob->id.lib, ob->track);
+ ob->ipo= newlibadr_us(fd, ob->id.lib, ob->ipo);
+ ob->action = newlibadr_us(fd, ob->id.lib, ob->action);
+
+// ob->activecon = newglobadr(fd, ob->activecon);
+
+ poin= ob->data;
+ ob->data= newlibadr_us(fd, ob->id.lib, ob->data);
+
+ if(ob->data==NULL && poin!=NULL) {
+ ob->type= OB_EMPTY;
+ warn= 1;
+ if(ob->id.lib) printf("Can't find obdata of %s lib %s\n", ob->id.name+2, ob->id.lib->name);
+ else printf("Object %s lost data. Lib:%x\n", ob->id.name+2, (unsigned int) ob->id.lib);
+ }
+ for(a=0; a<ob->totcol; a++) ob->mat[a]= newlibadr_us(fd, ob->id.lib, ob->mat[a]);
+
+ ob->id.flag -= LIB_NEEDLINK;
+ /* dit stond er eerst: weggehaald omdat de fie give_base_to... er niet meer is */
+ /* if(ob->id.us) ob->id.flag -= LIB_NEEDLINK; */
+ /* als us==0 wordt verderop nog een base gemaakt */
+
+ /* WARNING! Also check expand_object(), should reflect the stuff below. */
+ lib_link_pose(fd, &ob->id, ob->pose);
+ lib_link_constraints(fd, &ob->id, &ob->constraints);
+ lib_link_nlastrips(fd, &ob->id, &ob->nlastrips);
+ lib_link_constraint_channels(fd, &ob->id, &ob->constraintChannels);
+
+
+ sens= ob->sensors.first;
+ while(sens) {
+ for(a=0; a<sens->totlinks; a++) {
+ sens->links[a]= newglobadr(fd, sens->links[a]);
+ }
+ if(sens->type==SENS_TOUCH) {
+ bTouchSensor *ts= sens->data;
+ ts->ma= newlibadr(fd, ob->id.lib, ts->ma);
+ }
+ else if(sens->type==SENS_MESSAGE) {
+ bMessageSensor *ms= sens->data;
+ ms->fromObject=
+ newlibadr(fd, ob->id.lib, ms->fromObject);
+ }
+ sens= sens->next;
+ }
+
+ cont= ob->controllers.first;
+ while(cont) {
+ for(a=0; a<cont->totlinks; a++) {
+ cont->links[a]= newglobadr(fd, cont->links[a]);
+ }
+ if(cont->type==CONT_PYTHON) {
+ bPythonCont *pc= cont->data;
+ pc->text= newlibadr(fd, ob->id.lib, pc->text);
+ }
+ cont->slinks= NULL;
+ cont->totslinks= 0;
+
+ cont= cont->next;
+ }
+
+ act= ob->actuators.first;
+ while(act) {
+ if(act->type==ACT_SOUND) {
+ bSoundActuator *sa= act->data;
+ sa->sound= newlibadr_us(fd, ob->id.lib, sa->sound);
+ }
+ else if(act->type==ACT_CD) {
+ /* bCDActuator *cda= act->data; */
+ }
+ else if(act->type==ACT_GAME) {
+ /* bGameActuator *ga= act->data; */
+ }
+ else if(act->type==ACT_CAMERA) {
+ bCameraActuator *ca= act->data;
+ ca->ob= newlibadr(fd, ob->id.lib, ca->ob);
+ }
+ /* leave this one, it's obsolete but necessary to read for conversion */
+ else if(act->type==ACT_ADD_OBJECT) {
+ bAddObjectActuator *eoa= act->data;
+ if(eoa) eoa->ob= newlibadr(fd, ob->id.lib, eoa->ob);
+ }
+ else if(act->type==ACT_EDIT_OBJECT) {
+ bEditObjectActuator *eoa= act->data;
+ if(eoa==NULL) {
+ init_actuator(act);
+ }
+ eoa->ob= newlibadr(fd, ob->id.lib, eoa->ob);
+ eoa->me= newlibadr(fd, ob->id.lib, eoa->me);
+ }
+ else if(act->type==ACT_SCENE) {
+ bSceneActuator *sa= act->data;
+ sa->camera= newlibadr(fd, ob->id.lib, sa->camera);
+ sa->scene= newlibadr(fd, ob->id.lib, sa->scene);
+ }
+ else if(act->type==ACT_ACTION) {
+ bActionActuator *aa= act->data;
+ aa->act= newlibadr(fd, ob->id.lib, aa->act);
+ }
+ else if(act->type==ACT_PROPERTY) {
+ bPropertyActuator *pa= act->data;
+ pa->ob= newlibadr(fd, ob->id.lib, pa->ob);
+ }
+ else if(act->type==ACT_MESSAGE) {
+ bMessageActuator *ma= act->data;
+ ma->toObject= newlibadr(fd, ob->id.lib, ma->toObject);
+ }
+ act= act->next;
+ }
+
+ lib_link_scriptlink(fd, &ob->id, &ob->scriptlink);
+ }
+ ob= ob->id.next;
+ }
+
+ if(warn) error("WARNING IN CONSOLE");
+}
+
+
+static void direct_link_pose(FileData *fd, bPose *pose) {
+
+ bPoseChannel *chan;
+
+ if (!pose)
+ return;
+
+ link_list(fd, &pose->chanbase);
+
+ for (chan = pose->chanbase.first; chan; chan=chan->next) {
+ direct_link_constraints(fd, &chan->constraints);
+ }
+
+}
+
+static void direct_link_object(FileData *fd, Object *ob)
+{
+ PartEff *paf;
+ bProperty *prop;
+ bSensor *sens;
+ bController *cont;
+ bActuator *act;
+
+ ob->disp.first=ob->disp.last= 0;
+
+ ob->pose= newdataadr(fd, ob->pose);
+ direct_link_pose(fd, ob->pose);
+
+ link_list(fd, &ob->defbase);
+ link_list(fd, &ob->nlastrips);
+ link_list(fd, &ob->constraintChannels);
+
+ ob->activecon = newdataadr(fd, ob->activecon);
+
+ direct_link_scriptlink(fd, &ob->scriptlink);
+
+ ob->mat= newdataadr(fd, ob->mat);
+ test_pointer_array(fd, (void **)&ob->mat);
+ link_list(fd, &ob->effect);
+ paf= ob->effect.first;
+ while(paf) {
+ if(paf->type==EFF_PARTICLE) {
+ paf->keys= 0;
+ }
+ if(paf->type==EFF_WAVE) {
+
+ }
+ paf= paf->next;
+ }
+
+ link_list(fd, &ob->network);
+
+ link_list(fd, &ob->prop);
+ prop= ob->prop.first;
+ while(prop) {
+ prop->poin= newdataadr(fd, prop->poin);
+ if(prop->poin==0) prop->poin= &prop->data;
+ prop= prop->next;
+ }
+
+ link_list(fd, &ob->sensors);
+ sens= ob->sensors.first;
+ while(sens) {
+ sens->data= newdataadr(fd, sens->data);
+ sens->links= newdataadr(fd, sens->links);
+ test_pointer_array(fd, (void **)&sens->links);
+ sens= sens->next;
+ }
+
+ direct_link_constraints(fd, &ob->constraints);
+
+ link_glob_list(fd, &ob->controllers);
+ cont= ob->controllers.first;
+ while(cont) {
+ cont->data= newdataadr(fd, cont->data);
+ cont->links= newdataadr(fd, cont->links);
+ test_pointer_array(fd, (void **)&cont->links);
+ cont= cont->next;
+ }
+
+ link_glob_list(fd, &ob->actuators);
+ act= ob->actuators.first;
+ while(act) {
+ act->data= newdataadr(fd, act->data);
+ act= act->next;
+ }
+
+ ob->bb= 0;
+}
+
+/* ************ READ SCENE ***************** */
+
+static void lib_link_scene(FileData *fd, Main *main)
+{
+ Scene *sce;
+ Base *base, *next;
+ Editing *ed;
+ Sequence *seq;
+
+ sce= main->scene.first;
+ while(sce) {
+ if(sce->id.flag & LIB_NEEDLINK) {
+ sce->id.us= 1;
+ sce->camera= newlibadr(fd, sce->id.lib, sce->camera);
+ sce->world= newlibadr_us(fd, sce->id.lib, sce->world);
+ sce->set= newlibadr(fd, sce->id.lib, sce->set);
+ sce->ima= newlibadr_us(fd, sce->id.lib, sce->ima);
+ sce->group= newlibadr_us(fd, sce->id.lib, sce->group);
+
+ base= sce->base.first;
+ while(base) {
+ next= base->next;
+
+ /* base->object= newlibadr_us(fd, sce->id.lib, base->object); */
+
+ base->object= newlibadr_us_type(fd, ID_OB, base->object);
+
+ if(base->object==0) {
+ printf("LIB ERROR: base removed\n");
+ BLI_remlink(&sce->base, base);
+ if(base==sce->basact) sce->basact= 0;
+ MEM_freeN(base);
+ }
+ base= next;
+ }
+
+ ed= sce->ed;
+ if(ed) {
+ WHILE_SEQ(ed->seqbasep) {
+ if(seq->ipo) seq->ipo= newlibadr_us(fd, sce->id.lib, seq->ipo);
+ if(seq->scene) seq->scene= newlibadr(fd, sce->id.lib, seq->scene);
+ seq->anim= 0;
+ }
+ END_SEQ
+ }
+ sce->id.flag -= LIB_NEEDLINK;
+ }
+
+ lib_link_scriptlink(fd, &sce->id, &sce->scriptlink);
+
+ sce= sce->id.next;
+ }
+}
+
+static void link_recurs_seq(FileData *fd, ListBase *lb)
+{
+ Sequence *seq;
+
+ link_list(fd, lb);
+ seq= lb->first;
+ while(seq) {
+ if(seq->seqbase.first) link_recurs_seq(fd, &seq->seqbase);
+ seq= seq->next;
+ }
+}
+
+static void direct_link_scene(FileData *fd, Scene *sce)
+{
+ Editing *ed;
+ Sequence *seq;
+ StripElem *se;
+ int a;
+
+ link_list(fd, &(sce->base));
+
+ sce->basact= newdataadr(fd, sce->basact);
+
+ sce->radio= newdataadr(fd, sce->radio);
+ sce->fcam= newdataadr(fd, sce->fcam);
+
+ sce->r.avicodecdata = newdataadr(fd, sce->r.avicodecdata);
+ if (sce->r.avicodecdata) {
+ sce->r.avicodecdata->lpFormat = newdataadr(fd, sce->r.avicodecdata->lpFormat);
+ sce->r.avicodecdata->lpParms = newdataadr(fd, sce->r.avicodecdata->lpParms);
+ }
+
+ if(sce->ed) {
+ ed= sce->ed= newdataadr(fd, sce->ed);
+
+ ed->metastack.first= ed->metastack.last= 0;
+
+ /* recursief sequenties linken, ook lb wordt goedgezet */
+ link_recurs_seq(fd, &ed->seqbase);
+
+ ed->seqbasep= &ed->seqbase;
+
+ WHILE_SEQ(ed->seqbasep) {
+ seq->seq1= newdataadr(fd, seq->seq1);
+ seq->seq2= newdataadr(fd, seq->seq2);
+ seq->seq3= newdataadr(fd, seq->seq3);
+ /* eigenlijk een patch: na invoering drie-seq effects */
+ if(seq->seq3==0) seq->seq3= seq->seq2;
+
+ seq->curelem= 0;
+
+ seq->plugin= newdataadr(fd, seq->plugin);
+ if(seq->plugin) open_plugin_seq(seq->plugin, seq->name+2);
+
+ seq->strip= newdataadr(fd, seq->strip);
+ if(seq->strip && seq->strip->done==0) {
+ seq->strip->done= 1;
+
+ /* standaard: strips van effecten/meta's worden niet weggeschreven, wel malloccen */
+
+ if(seq->type==SEQ_IMAGE) {
+ seq->strip->stripdata= newdataadr(fd, seq->strip->stripdata);
+ se= seq->strip->stripdata;
+ if(se) {
+ for(a=0; a<seq->strip->len; a++, se++) {
+ se->ok= 1;
+ se->ibuf= 0;
+ }
+ }
+ }
+ else if(seq->type==SEQ_MOVIE) {
+ /* alleen eerste stripelem zit in file */
+ se= newdataadr(fd, seq->strip->stripdata);
+
+ if(se) {
+ seq->strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelem");
+ *seq->strip->stripdata= *se;
+ MEM_freeN(se);
+
+ se= seq->strip->stripdata;
+
+ for(a=0; a<seq->strip->len; a++, se++) {
+ se->ok= 1;
+ se->ibuf= 0;
+ se->nr= a + 1;
+ }
+ }
+ }
+ else if(seq->len>0)
+ seq->strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelem");
+
+ }
+ }
+ END_SEQ
+ }
+
+ direct_link_scriptlink(fd, &sce->scriptlink);
+}
+
+/* ************ READ SCREEN ***************** */
+
+static void lib_link_screen(FileData *fd, Main *main)
+{
+ bScreen *sc;
+ ScrArea *sa;
+
+ sc= main->screen.first;
+ while(sc) {
+ if(sc->id.flag & LIB_NEEDLINK) {
+ sc->id.us= 1;
+ sc->scene= newlibadr(fd, sc->id.lib, sc->scene);
+
+ sa= sc->areabase.first;
+ while(sa) {
+ SpaceLink *sl;
+
+ sa->full= newlibadr(fd, sc->id.lib, sa->full);
+
+ for (sl= sa->spacedata.first; sl; sl= sl->next) {
+ if(sl->spacetype==SPACE_VIEW3D) {
+ View3D *v3d= (View3D*) sl;
+
+ v3d->camera= newlibadr(fd, sc->id.lib, v3d->camera);
+
+ if(v3d->bgpic) {
+ v3d->bgpic->ima= newlibadr_us(fd, sc->id.lib, v3d->bgpic->ima);
+ v3d->bgpic->tex= newlibadr_us(fd, sc->id.lib, v3d->bgpic->tex);
+ v3d->bgpic->rect= 0;
+ }
+ if(v3d->localvd) {
+ v3d->localvd->camera= newlibadr(fd, sc->id.lib, v3d->localvd->camera);
+ }
+ }
+ else if(sl->spacetype==SPACE_IPO) {
+ SpaceIpo *sipo= (SpaceIpo *)sl;
+ sipo->editipo= 0;
+ sipo->from= newlibadr(fd, sc->id.lib, sipo->from);
+ sipo->ipokey.first= sipo->ipokey.last= 0;
+ sipo->ipo= newlibadr(fd, sc->id.lib, sipo->ipo);
+ }
+ else if(sl->spacetype==SPACE_BUTS) {
+ SpaceButs *sbuts= (SpaceButs *)sl;
+ sbuts->rect= 0;
+ sbuts->lockpoin= 0;
+ if(main->versionfile<132) set_rects_butspace(sbuts);
+ }
+ else if(sl->spacetype==SPACE_FILE) {
+ SpaceFile *sfile= (SpaceFile *)sl;
+
+ sfile->filelist= 0;
+ sfile->libfiledata= 0;
+ sfile->returnfunc= 0;
+ }
+ else if(sl->spacetype==SPACE_IMASEL) {
+ check_imasel_copy((SpaceImaSel *)sl);
+ }
+ else if(sl->spacetype==SPACE_ACTION) {
+ SpaceAction *saction= (SpaceAction *)sl;
+ saction->action = newlibadr(fd, sc->id.lib, saction->action);
+ }
+ else if(sl->spacetype==SPACE_IMAGE) {
+ SpaceImage *sima= (SpaceImage *)sl;
+
+ sima->image= newlibadr_us(fd, sc->id.lib, sima->image);
+ }
+ else if(sl->spacetype==SPACE_NLA){
+ SpaceNla *snla= (SpaceNla *)sl;
+ }
+ else if(sl->spacetype==SPACE_TEXT) {
+ SpaceText *st= (SpaceText *)sl;
+
+ st->text= newlibadr(fd, sc->id.lib, st->text);
+
+ st->py_draw= NULL;
+ st->py_event= NULL;
+ st->py_button= NULL;
+ st->py_globaldict= NULL;
+ }
+ else if(sl->spacetype==SPACE_OOPS) {
+ SpaceOops *so= (SpaceOops *)sl;
+ Oops *oops;
+
+ oops= so->oops.first;
+ while(oops) {
+ oops->id= newlibadr(fd, 0, oops->id);
+ oops= oops->next;
+ }
+ so->lockpoin= 0;
+ }
+ else if(sl->spacetype==SPACE_SOUND) {
+ SpaceSound *ssound= (SpaceSound *)sl;
+
+ ssound->sound= newlibadr_us(fd, sc->id.lib, ssound->sound);
+ }
+ }
+ sa= sa->next;
+ }
+ sc->id.flag -= LIB_NEEDLINK;
+ }
+ sc= sc->id.next;
+ }
+}
+
+static void direct_link_screen(FileData *fd, bScreen *sc)
+{
+ ScrArea *sa;
+ ScrVert *sv;
+ ScrEdge *se;
+ Oops *oops;
+
+ link_list(fd, &(sc->vertbase));
+ link_list(fd, &(sc->edgebase));
+ link_list(fd, &(sc->areabase));
+ sc->winakt= 0;
+
+ /* edges */
+ se= sc->edgebase.first;
+ while(se) {
+ se->v1= newdataadr(fd, se->v1);
+ se->v2= newdataadr(fd, se->v2);
+ if( (long)se->v1 > (long)se->v2) {
+ sv= se->v1;
+ se->v1= se->v2;
+ se->v2= sv;
+ }
+
+ if(se->v1==NULL) {
+ printf("error reading screen... file corrupt\n");
+ se->v1= se->v2;
+ }
+ se= se->next;
+ }
+
+ /* areas */
+ sa= sc->areabase.first;
+ while(sa) {
+ SpaceLink *sl;
+
+ link_list(fd, &(sa->spacedata));
+
+ for (sl= sa->spacedata.first; sl; sl= sl->next) {
+ if (sl->spacetype==SPACE_VIEW3D) {
+ View3D *v3d= (View3D*) sl;
+ v3d->bgpic= newdataadr(fd, v3d->bgpic);
+ v3d->localvd= newdataadr(fd, v3d->localvd);
+ }
+ else if (sl->spacetype==SPACE_OOPS) {
+ SpaceOops *soops= (SpaceOops*) sl;
+ link_list(fd, &(soops->oops));
+ oops= soops->oops.first;
+ while(oops) {
+ oops->link.first= oops->link.last= 0;
+ oops= oops->next;
+ }
+ }
+ }
+
+ sa->v1= newdataadr(fd, sa->v1);
+ sa->v2= newdataadr(fd, sa->v2);
+ sa->v3= newdataadr(fd, sa->v3);
+ sa->v4= newdataadr(fd, sa->v4);
+
+ sa->win= sa->headwin= 0;
+
+ sa->uiblocks.first= sa->uiblocks.last= NULL;
+
+ sa= sa->next;
+ }
+}
+
+/* ********** READ LIBRARY *************** */
+
+
+static void direct_link_library(FileData *fd, Library *lib)
+{
+ Main *newmain;
+
+ /* nieuwe main */
+ newmain= MEM_callocN(sizeof(Main), "directlink");
+ BLI_addtail(&fd->mainlist, newmain);
+ newmain->curlib= lib;
+}
+
+static void lib_link_library(FileData *fd, Main *main)
+{
+ Library *lib;
+
+ lib= main->library.first;
+ while(lib) {
+ lib->id.us= 1;
+ lib= lib->id.next;
+ }
+}
+
+/* ************** READ SOUND ******************* */
+
+static void direct_link_sound(FileData *fd, bSound *sound)
+{
+ sound->sample = NULL;
+ sound->snd_sound = NULL;
+
+ sound->packedfile = direct_link_packedfile(fd, sound->packedfile);
+ sound->newpackedfile = direct_link_packedfile(fd, sound->newpackedfile);
+}
+
+static void lib_link_sound(FileData *fd, Main *main)
+{
+ bSound *sound;
+
+ sound= main->sound.first;
+ while(sound) {
+ if(sound->id.flag & LIB_NEEDLINK) {
+ sound->id.flag -= LIB_NEEDLINK;
+ sound->ipo= newlibadr_us(fd, sound->id.lib, sound->ipo);
+ }
+ sound= sound->id.next;
+ }
+}
+
+/* ***************** READ GROUP *************** */
+
+static void direct_link_group(FileData *fd, Group *group)
+{
+ GroupObject *go;
+ ObjectKey *ok;
+
+ link_list(fd, &group->gobject);
+ link_list(fd, &group->gkey);
+ group->active= newdataadr(fd, group->active);
+
+ go= group->gobject.first;
+ while(go) {
+ link_list(fd, &go->okey);
+ ok= go->okey.first;
+ while(ok) {
+ ok->gkey= newdataadr(fd, ok->gkey);
+ ok= ok->next;
+ }
+ go= go->next;
+ }
+}
+
+static void lib_link_group(FileData *fd, Main *main)
+{
+ Group *group= main->group.first;
+ GroupObject *go;
+ ObjectKey *ok;
+
+ while(group) {
+ if(group->id.flag & LIB_NEEDLINK) {
+ group->id.flag -= LIB_NEEDLINK;
+
+ go= group->gobject.first;
+ while(go) {
+ go->ob= newlibadr(fd, group->id.lib, go->ob);
+ ok= go->okey.first;
+ while(ok) {
+ ok->parent= newlibadr(fd, group->id.lib, ok->parent);
+ ok->track= newlibadr(fd, group->id.lib, ok->track);
+ ok->ipo= newlibadr_us(fd, group->id.lib, ok->ipo);
+ ok= ok->next;
+ }
+ go= go->next;
+ }
+ }
+ group= group->id.next;
+ }
+}
+
+/* ************** ALG & MAIN ******************** */
+
+static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, int flag, ID **id_r)
+{
+ /* deze routine leest libblock en direkte data. Met linkfunkties
+ * alles aan elkaar hangen.
+ */
+
+ ID *id;
+ ListBase *lb;
+
+ if(bhead->code==ID_ID) {
+ ID *linkedid= (ID *)(bhead + 1); /* BHEAD+DATA dependancy */
+
+ lb= wich_libbase(main, GS(linkedid->name));
+ }
+ else {
+ lb= wich_libbase(main, bhead->code);
+ }
+
+ /* libblock inlezen */
+ id = read_struct(fd, bhead);
+ if (id_r)
+ *id_r= id;
+ if (!id)
+ return blo_nextbhead(fd, bhead);
+
+ oldnewmap_insert(fd->libmap, bhead->old, id, 1);
+ BLI_addtail(lb, id);
+
+ /* eerste acht bits wissen */
+ id->flag= (id->flag & 0xFF00) | flag | LIB_NEEDLINK;
+ id->lib= main->curlib;
+ if(id->flag & LIB_FAKEUSER) id->us= 1;
+ else id->us= 0;
+
+ /* deze mag niet door de direct_link molen: is alleen het ID deel */
+
+ if(bhead->code==ID_ID) {
+ return blo_nextbhead(fd, bhead);
+ }
+
+ bhead = blo_nextbhead(fd, bhead);
+
+ /* alle data inlezen */
+ while(bhead && bhead->code==DATA) {
+ void *data= read_struct(fd, bhead);
+
+ if (data) {
+ oldnewmap_insert(fd->datamap, bhead->old, data, 0);
+ }
+
+ bhead = blo_nextbhead(fd, bhead);
+ }
+
+ /* pointers directe data goedzetten */
+ switch( GS(id->name) ) {
+ case ID_SCR:
+ direct_link_screen(fd, (bScreen *)id);
+ break;
+ case ID_SCE:
+ direct_link_scene(fd, (Scene *)id);
+ break;
+ case ID_OB:
+ direct_link_object(fd, (Object *)id);
+ break;
+ case ID_ME:
+ direct_link_mesh(fd, (Mesh *)id);
+ break;
+ case ID_CU:
+ direct_link_curve(fd, (Curve *)id);
+ break;
+ case ID_MB:
+ direct_link_mball(fd, (MetaBall *)id);
+ break;
+ case ID_MA:
+ direct_link_material(fd, (Material *)id);
+ break;
+ case ID_TE:
+ direct_link_texture(fd, (Tex *)id);
+ break;
+ case ID_IM:
+ direct_link_image(fd, (Image *)id);
+ break;
+ case ID_LA:
+ direct_link_lamp(fd, (Lamp *)id);
+ break;
+ case ID_VF:
+ direct_link_vfont(fd, (VFont *)id);
+ break;
+ case ID_TXT:
+ direct_link_text(fd, (Text *)id);
+ break;
+ case ID_IP:
+ direct_link_ipo(fd, (Ipo *)id);
+ break;
+ case ID_KE:
+ direct_link_key(fd, (Key *)id);
+ break;
+ case ID_LT:
+ direct_link_latt(fd, (Lattice *)id);
+ break;
+ case ID_IK:
+ direct_link_ika(fd, (Ika *)id);
+ break;
+ case ID_WO:
+ direct_link_world(fd, (World *)id);
+ break;
+ case ID_LI:
+ direct_link_library(fd, (Library *)id);
+ break;
+ case ID_CA:
+ direct_link_camera(fd, (Camera *)id);
+ break;
+ case ID_SO:
+ direct_link_sound(fd, (bSound *)id);
+ break;
+ case ID_GR:
+ direct_link_group(fd, (Group *)id);
+ break;
+ case ID_AR:
+ direct_link_armature(fd, (bArmature*)id);
+ break;
+ case ID_AC:
+ direct_link_action(fd, (bAction*)id);
+ break;
+ }
+
+ oldnewmap_free_unused(fd->datamap);
+ oldnewmap_clear(fd->datamap);
+
+ return (bhead);
+}
+
+static void link_global(FileData *fd, BlendFileData *bfd, FileGlobal *fg)
+{
+ bfd->winpos= fg->winpos;
+ bfd->fileflags= fg->fileflags;
+ bfd->displaymode= fg->displaymode;
+
+ bfd->curscreen= newlibadr(fd, 0, fg->curscreen);
+}
+
+static void vcol_to_fcol(Mesh *me)
+{
+ MFace *mface;
+ unsigned int *mcol, *mcoln, *mcolmain;
+ int a;
+
+ if(me->totface==0 || me->mcol==0) return;
+
+ mcoln= mcolmain= MEM_mallocN(4*sizeof(int)*me->totface, "mcoln");
+ mcol = (unsigned int *)me->mcol;
+ mface= me->mface;
+ for(a=me->totface; a>0; a--, mface++) {
+ mcoln[0]= mcol[mface->v1];
+ mcoln[1]= mcol[mface->v2];
+ mcoln[2]= mcol[mface->v3];
+ mcoln[3]= mcol[mface->v4];
+ mcoln+= 4;
+ }
+
+ MEM_freeN(me->mcol);
+ me->mcol= (MCol *)mcolmain;
+}
+
+static int map_223_keybd_code_to_224_keybd_code(int code)
+{
+ switch (code) {
+ case 312: return F12KEY;
+ case 159: return PADSLASHKEY;
+ case 161: return PAD0;
+ case 154: return PAD1;
+ case 150: return PAD2;
+ case 155: return PAD3;
+ case 151: return PAD4;
+ case 156: return PAD5;
+ case 152: return PAD6;
+ case 157: return PAD7;
+ case 153: return PAD8;
+ case 158: return PAD9;
+ default: return code;
+ }
+}
+
+static void do_versions(Main *main)
+{
+ /* PAS OP: pointers van libdata zijn nog niet omgezet */
+
+ if(main->versionfile == 100) {
+ /* tex->extend en tex->imageflag veranderd: */
+ Tex *tex = main->tex.first;
+ while(tex) {
+ if(tex->id.flag & LIB_NEEDLINK) {
+
+ if(tex->extend==0) {
+ if(tex->xrepeat || tex->yrepeat) tex->extend= TEX_REPEAT;
+ else {
+ tex->extend= TEX_EXTEND;
+ tex->xrepeat= tex->yrepeat= 1;
+ }
+ }
+
+ if(tex->imaflag & TEX_ANIM5) {
+ tex->imaflag |= TEX_MORKPATCH;
+ tex->imaflag |= TEX_ANTIALI;
+ }
+ }
+ tex= tex->id.next;
+ }
+ }
+ if(main->versionfile <= 101) {
+ /* frame mapping */
+ Scene *sce = main->scene.first;
+ while(sce) {
+ sce->r.framapto= 100;
+ sce->r.images= 100;
+ sce->r.framelen= 1.0;
+ sce= sce->id.next;
+ }
+ }
+ if(main->versionfile <= 102) {
+ /* init halo's op 1.0 */
+ Material *ma = main->mat.first;
+ while(ma) {
+ ma->add= 1.0;
+ ma= ma->id.next;
+ }
+ }
+ if(main->versionfile <= 103) {
+ /* nieuwe variabele in object: colbits */
+ Object *ob = main->object.first;
+ int a;
+ while(ob) {
+ ob->colbits= 0;
+ if(ob->totcol) {
+ for(a=0; a<ob->totcol; a++) {
+ if(ob->mat[a]) ob->colbits |= (1<<a);
+ }
+ }
+ ob= ob->id.next;
+ }
+ }
+ if(main->versionfile <= 104) {
+ /* de timeoffs zit op betere plek */
+ Object *ob = main->object.first;
+ while(ob) {
+ if(ob->transflag & 1) {
+ ob->transflag -= 1;
+ ob->ipoflag |= OB_OFFS_OB;
+ }
+ ob= ob->id.next;
+ }
+ }
+ if(main->versionfile <= 105) {
+ Object *ob = main->object.first;
+ while(ob) {
+ ob->dupon= 1; ob->dupoff= 0;
+ ob->dupsta= 1; ob->dupend= 100;
+ ob= ob->id.next;
+ }
+ }
+ if(main->versionfile <= 106) {
+ /* mcol is veranderd */
+ Mesh *me = main->mesh.first;
+ while(me) {
+ if(me->mcol) vcol_to_fcol(me);
+ me= me->id.next;
+ }
+
+ }
+ if(main->versionfile <= 107) {
+ Object *ob;
+ Scene *sce = main->scene.first;
+ while(sce) {
+ sce->r.mode |= R_GAMMA;
+ sce= sce->id.next;
+ }
+ ob= main->object.first;
+ while(ob) {
+ ob->ipoflag |= OB_OFFS_PARENT;
+ if(ob->dt==0) ob->dt= 3;
+ ob= ob->id.next;
+ }
+
+ }
+ if(main->versionfile <= 109) {
+ /* nieuwe variabele: gridlines */
+ bScreen *sc = main->screen.first;
+ while(sc) {
+ ScrArea *sa= sc->areabase.first;
+ while(sa) {
+ SpaceLink *sl= sa->spacedata.first;
+ while (sl) {
+ if (sl->spacetype==SPACE_VIEW3D) {
+ View3D *v3d= (View3D*) sl;
+
+ if (v3d->gridlines==0) v3d->gridlines= 20;
+ }
+ sl= sl->next;
+ }
+ sa= sa->next;
+ }
+ sc= sc->id.next;
+ }
+ }
+ if(main->versionfile <= 112) {
+ Mesh *me = main->mesh.first;
+ while(me) {
+ me->cubemapsize= 1.0;
+ me= me->id.next;
+ }
+ }
+ if(main->versionfile <= 113) {
+ Material *ma = main->mat.first;
+ while(ma) {
+ if(ma->flaresize==0.0) ma->flaresize= 1.0;
+ ma->subsize= 1.0;
+ ma->flareboost= 1.0;
+ ma= ma->id.next;
+ }
+ }
+ if(main->versionfile <= 114) {
+ Mesh *me= main->mesh.first;
+ MFace *mface;
+ int a_int;
+
+ /* edge drawflags veranderd */
+ while(me) {
+ a_int= me->totface;
+ mface= me->mface;
+ while(a_int--) {
+ if(mface->edcode & 16) {
+ mface->edcode -= 16;
+ mface->edcode |= ME_V3V1;
+ }
+ mface++;
+ }
+ me= me->id.next;
+ }
+ }
+
+ /* eentje overgeslagen voor bug in freeware versie */
+
+ if(main->versionfile <= 121) {
+ /* O2 versie gemaakt. */
+ }
+ if(main->versionfile <= 122) {
+ /* dithering gaat soms af (backbuf, pas sinds 121) */
+ /* relatieve paden hersteld */
+ /* sequences: endframe van seq wordt op betere plek geprint */
+ }
+ if(main->versionfile <= 123) {
+ /* nog een paar O2 foutjes: keylines in ipo window */
+ /* vertices halo object (O2) nu ook goed */
+ /* zoomwin: ook op O2 */
+ /* bug eruit: schaduw render in ortho */
+ }
+ if(main->versionfile <= 124) {
+ /* inventor lezer */
+ /* key kleur 24 bits beveiligd */
+ /* schrijf plaatje: je kun niet naderhand 24bits naar 32
+ * omzetten */
+ }
+ if(main->versionfile <= 125) {
+ /* bug vanwege compileer fout (makefile/.h dependency)*/
+ }
+ if(main->versionfile <= 126) {
+ /* overdraw text beter (clever numbuts) */
+ /* bug uit inventor lezer: node ambientColor werd niet
+ * herkend */
+ /* bugje uit toolbox: clear loc= alt-g */
+ }
+
+ if(main->versionfile <= 131) {
+ /* jpeq quality button */
+ /* anim5 and blacksmith demo */
+ /* foutje uit transp zbuf: te vroege afbreek */
+ /* geen paarse code meer als imap onvindbaar is meer */
+ /* locx werd niet geprint: string overflow! */
+ /* unieke namen: werkte niet */
+ /* toolbox menu: ook alt en ctrl keys */
+ }
+ if(main->versionfile <= 132) {
+ /* strings in Userdef: eroverheen! */
+ /* betere overdraw implementatie (numbuts) */
+ /* snapmenu redraw */
+ /* warp met 1 vertex */
+ }
+ if(main->versionfile <= 133) {
+ /* bug uit 'make edge face' (array overflow */
+ /* volledig X getekende menu's */
+ /* storage.c terug */
+ }
+ if(main->versionfile <= 134) {
+ /* Play (flipbook) restored */
+ /* Timecursor restored */
+ /* Debug option -d; prints a lot of info in console */
+ /* Text Object. Accentcodes fixed: ALT+BACKSPACE */
+ /* Cursor was sometimes wrong after reading files */
+ /* Texspace draw error: dashed lines */
+ /* Draw Schematic View now with icons in Objects */
+ /* Ortho camera: zbuffer improved. Near/far still not OK */
+ /* Text Object. Character pound= alt-l */
+ /* In editmode and 'set', draw error fixed. */
+ /* Scanline display during rendering had dropouts */
+ /* Sometimes-after render- frontbuffer drawing wasnt disabled */
+ /* Sometimes the render window got black and Blender 'hung' */
+ /* Better 'active window' implementation. */
+ /* Automatic name was too critical, more intuitive now */
+ Tex *tex = main->tex.first;
+ while (tex) {
+ if ((tex->rfac == 0.0) &&
+ (tex->gfac == 0.0) &&
+ (tex->bfac == 0.0)) {
+ tex->rfac = 1.0;
+ tex->gfac = 1.0;
+ tex->bfac = 1.0;
+ tex->filtersize = 1.0;
+ }
+ tex = tex->id.next;
+ }
+ }
+ if(main->versionfile <= 135) {
+ /* 'Windows' key resistant */
+ /* Preview-render: RGB flip (material, lamp, world) */
+ /* Fileselect draw error: 2nd time no redraw! */
+ /* Names error: names were not unique automatically */
+ /* Metaball display error: because of previous */
+ /* CTRL and ALT and SHIFT keys sometimes were locked */
+ }
+ if(main->versionfile <= 136) {
+ /* Files incompatibility Colorband PC-SGI solved */
+ /* RightMouse selecting was blocked after border-select */
+ /* Border select: print size */
+ /* Inventor: reads some 2.0 syntaxes too. Under development */
+ /* Shift/Ctrl/Alt release events got lost while moving view */
+ /* Particles draw (size) error fixed */
+ /* Display type 'DispView' works */
+ /* Metaballs convert to Mesh, normals error fixed. */
+ }
+ if(main->versionfile <= 137) {
+ /* who know */
+ }
+ if(main->versionfile <= 138) {
+ /* fixed: z buffer draw and Mesh with no materials: coredump! */
+ /* bug removed from calculation 3D Bevel Objects */
+ /* view translation in perspective fixed */
+ /* Drawing with ortho camera fixed */
+ /* timing error FreeBSD version fixed */
+ /* Mesa 3.0 included in static version */
+ /* New: LeftMouse+RightMouse allowed at numerber-button
+ * to type in values */
+ /* Vertex paint bug fixed */
+ /* New: ALT+(1, 2, 3...) for layers 11, 12, 13... */
+ }
+ if(main->versionfile <= 140) {
+ /* r-g-b-fac in texure */
+ Tex *tex = main->tex.first;
+ while (tex) {
+ if ((tex->rfac == 0.0) &&
+ (tex->gfac == 0.0) &&
+ (tex->bfac == 0.0)) {
+ tex->rfac = 1.0;
+ tex->gfac = 1.0;
+ tex->bfac = 1.0;
+ tex->filtersize = 1.0;
+ }
+ tex = tex->id.next;
+ }
+ }
+ if(main->versionfile <= 153) {
+ Scene *sce = main->scene.first;
+ while(sce) {
+ if(sce->r.blurfac==0.0) sce->r.blurfac= 1.0;
+ sce= sce->id.next;
+ }
+ }
+ if(main->versionfile <= 163) {
+ Scene *sce = main->scene.first;
+ while(sce) {
+ if(sce->r.frs_sec==0) sce->r.frs_sec= 25;
+ sce= sce->id.next;
+ }
+ }
+ if(main->versionfile <= 164) {
+ Mesh *me= main->mesh.first;
+ while(me) {
+ me->smoothresh= 30;
+ me= me->id.next;
+ }
+ }
+ if(main->versionfile <= 165) {
+ Mesh *me= main->mesh.first;
+ TFace *tface;
+ Ika *ika= main->ika.first;
+ Deform *def;
+ int nr;
+ char *cp;
+
+ while(ika) {
+ ika->xyconstraint= .5;
+
+ def= ika->def;
+ nr= ika->totdef;
+ while(nr--) {
+ if(def->fac==0.0) def->fac= 1.0;
+ def++;
+ }
+ ika= ika->id.next;
+ }
+
+ while(me) {
+ if(me->tface) {
+ nr= me->totface;
+ tface= me->tface;
+ while(nr--) {
+ cp= (char *)&tface->col[0];
+ if(cp[1]>126) cp[1]= 255; else cp[1]*=2;
+ if(cp[2]>126) cp[2]= 255; else cp[2]*=2;
+ if(cp[3]>126) cp[3]= 255; else cp[3]*=2;
+ cp= (char *)&tface->col[1];
+ if(cp[1]>126) cp[1]= 255; else cp[1]*=2;
+ if(cp[2]>126) cp[2]= 255; else cp[2]*=2;
+ if(cp[3]>126) cp[3]= 255; else cp[3]*=2;
+ cp= (char *)&tface->col[2];
+ if(cp[1]>126) cp[1]= 255; else cp[1]*=2;
+ if(cp[2]>126) cp[2]= 255; else cp[2]*=2;
+ if(cp[3]>126) cp[3]= 255; else cp[3]*=2;
+ cp= (char *)&tface->col[3];
+ if(cp[1]>126) cp[1]= 255; else cp[1]*=2;
+ if(cp[2]>126) cp[2]= 255; else cp[2]*=2;
+ if(cp[3]>126) cp[3]= 255; else cp[3]*=2;
+
+ tface++;
+ }
+ }
+ me= me->id.next;
+ }
+ }
+
+ if(main->versionfile <= 169) {
+ Mesh *me= main->mesh.first;
+ while(me) {
+ if(me->subdiv==0) me->subdiv= 3;
+ me= me->id.next;
+ }
+ }
+
+ if(main->versionfile <= 169) {
+ bScreen *sc= main->screen.first;
+ while(sc) {
+ ScrArea *sa= sc->areabase.first;
+ while(sa) {
+ SpaceLink *sl= sa->spacedata.first;
+ while(sl) {
+ if(sl->spacetype==SPACE_IPO) {
+ SpaceIpo *sipo= (SpaceIpo*) sl;
+ sipo->v2d.max[0]= 15000.0;
+ }
+ sl= sl->next;
+ }
+ sa= sa->next;
+ }
+ sc= sc->id.next;
+ }
+ }
+
+ if(main->versionfile <= 170) {
+ Object *ob = main->object.first;
+ PartEff *paf;
+ while (ob) {
+ paf = give_parteff(ob);
+ if (paf) {
+ if (paf->staticstep == 0) {
+ paf->staticstep= 5;
+ }
+ }
+ ob = ob->id.next;
+ }
+ }
+
+ if(main->versionfile <= 171) {
+ bScreen *sc= main->screen.first;
+ while(sc) {
+ ScrArea *sa= sc->areabase.first;
+ while(sa) {
+ SpaceLink *sl= sa->spacedata.first;
+ while(sl) {
+ if(sl->spacetype==SPACE_TEXT) {
+ SpaceText *st= (SpaceText*) sl;
+ if(st->font_id>1) {
+ st->font_id= 0;
+ st->lheight= 13;
+ }
+ }
+ sl= sl->next;
+ }
+ sa= sa->next;
+ }
+ sc= sc->id.next;
+ }
+ }
+
+ if(main->versionfile <= 173) {
+ int a, b;
+ Mesh *me= main->mesh.first;
+ while(me) {
+ if(me->tface) {
+ TFace *tface= me->tface;
+ for(a=0; a<me->totface; a++, tface++) {
+ for(b=0; b<4; b++) {
+ tface->uv[b][0]/= 32767.0;
+ tface->uv[b][1]/= 32767.0;
+ }
+ }
+ }
+ me= me->id.next;
+ }
+ }
+
+ if(main->versionfile <= 191) {
+ bScreen *sc= main->screen.first;
+ Object *ob= main->object.first;
+ Material *ma = main->mat.first;
+
+ /* let faces have default add factor of 0.0 */
+ while(ma) {
+ if (!(ma->mode & MA_HALO)) ma->add = 0.0;
+ ma = ma->id.next;
+ }
+
+ while(ob) {
+ ob->mass= 1.0f;
+ ob->damping= 0.1f;
+ ob->quat[1]= 1.0f;
+ ob= ob->id.next;
+ }
+
+ while(sc) {
+ ScrArea *sa= sc->areabase.first;
+ while(sa) {
+ SpaceLink *sl= sa->spacedata.first;
+ while(sl) {
+ if(sl->spacetype==SPACE_BUTS) {
+ SpaceButs *sbuts= (SpaceButs*) sl;
+ sbuts->scaflag= BUTS_SENS_LINK|BUTS_SENS_ACT|BUTS_CONT_ACT|BUTS_ACT_ACT|BUTS_ACT_LINK;
+ }
+ sl= sl->next;
+ }
+ sa= sa->next;
+ }
+ sc= sc->id.next;
+ }
+ }
+
+ if(main->versionfile <= 193) {
+ Object *ob= main->object.first;
+ while(ob) {
+ ob->inertia= 1.0f;
+ ob->rdamping= 0.1f;
+ ob= ob->id.next;
+ }
+ }
+
+ if(main->versionfile <= 196) {
+ Mesh *me= main->mesh.first;
+ int a, b;
+ while(me) {
+ if(me->tface) {
+ TFace *tface= me->tface;
+ for(a=0; a<me->totface; a++, tface++) {
+ for(b=0; b<4; b++) {
+ tface->mode |= TF_DYNAMIC;
+ tface->mode &= ~TF_INVISIBLE;
+ }
+ }
+ }
+ me= me->id.next;
+ }
+ }
+
+ if(main->versionfile <= 200) {
+ Object *ob= main->object.first;
+ while(ob) {
+ ob->scaflag = ob->gameflag & (64+128+256+512+1024+2048);
+ /* 64 is do_fh */
+ ob->gameflag &= ~(128+256+512+1024+2048);
+ ob = ob->id.next;
+ }
+ }
+
+ if(main->versionfile <= 201) {
+ /* add-object + end-object are joined to edit-object actuator */
+ Object *ob = main->object.first;
+ bProperty *prop;
+ bActuator *act;
+ bIpoActuator *ia;
+ bEditObjectActuator *eoa;
+ bAddObjectActuator *aoa;
+ while (ob) {
+ act = ob->actuators.first;
+ while (act) {
+ if(act->type==ACT_IPO) {
+ ia= act->data;
+ prop= get_property(ob, ia->name);
+ if(prop) {
+ ia->type= ACT_IPO_FROM_PROP;
+ }
+ }
+ else if(act->type==ACT_ADD_OBJECT) {
+ aoa= act->data;
+ eoa= MEM_callocN(sizeof(bEditObjectActuator), "edit ob act");
+ eoa->type= ACT_EDOB_ADD_OBJECT;
+ eoa->ob= aoa->ob;
+ eoa->time= aoa->time;
+ MEM_freeN(aoa);
+ act->data= eoa;
+ act->type= act->otype= ACT_EDIT_OBJECT;
+ }
+ else if(act->type==ACT_END_OBJECT) {
+ eoa= MEM_callocN(sizeof(bEditObjectActuator), "edit ob act");
+ eoa->type= ACT_EDOB_END_OBJECT;
+ act->data= eoa;
+ act->type= act->otype= ACT_EDIT_OBJECT;
+ }
+ act= act->next;
+ }
+ ob = ob->id.next;
+ }
+ }
+
+ if(main->versionfile <= 202) {
+ /* add-object and end-object are joined to edit-object
+ * actuator */
+ Object *ob= main->object.first;
+ bActuator *act;
+ bObjectActuator *oa;
+ while(ob) {
+ act= ob->actuators.first;
+ while(act) {
+ if(act->type==ACT_OBJECT) {
+ oa= act->data;
+ oa->flag &= ~(ACT_TORQUE_LOCAL|ACT_DROT_LOCAL); /* this actuator didn't do local/glob rot before */
+ }
+ act= act->next;
+ }
+ ob= ob->id.next;
+ }
+ }
+
+ if(main->versionfile <= 204) {
+ /* patches for new physics */
+ Object *ob= main->object.first;
+ Material *ma= main->mat.first;
+ bActuator *act;
+ bObjectActuator *oa;
+ bSound *sound;
+ while(ob) {
+ /* rotdamping */
+ ob->damping= (float) pow(ob->damping, 0.05);
+ ob->rdamping= (float) pow(ob->rdamping, 0.05);
+
+ /* please check this for demo20 files like
+ * original Egypt levels etc. converted
+ * rotation factor of 50 is not workable */
+ act= ob->actuators.first;
+ while(act) {
+ if(act->type==ACT_OBJECT) {
+ oa= act->data;
+
+ oa->forceloc[0]*= 25.0;
+ oa->forceloc[1]*= 25.0;
+ oa->forceloc[2]*= 25.0;
+
+ oa->forcerot[0]*= 10.0;
+ oa->forcerot[1]*= 10.0;
+ oa->forcerot[2]*= 10.0;
+ }
+ act= act->next;
+ }
+ ob= ob->id.next;
+ }
+
+ while(ma) {
+ ma->friction= (float) pow(ma->friction, 0.2);
+ ma->xyfrict= (float) pow(ma->xyfrict, 0.2);
+ ma= ma->id.next;
+ }
+
+ sound = main->sound.first;
+ while (sound) {
+ if (sound->volume < 0.01) {
+ sound->volume = 1.0;
+ }
+ sound = sound->id.next;
+ }
+ }
+
+ if(main->versionfile <= 205) {
+ /* patches for new physics */
+ Object *ob= main->object.first;
+ bActuator *act;
+ bSensor *sens;
+ bEditObjectActuator *oa;
+ bRaySensor *rs;
+ bCollisionSensor *cs;
+ while(ob) {
+ /* Set anisotropic friction off for old objects,
+ * values to 1.0. */
+ ob->gameflag &= ~OB_ANISOTROPIC_FRICTION;
+ ob->anisotropicFriction[0] = 1.0;
+ ob->anisotropicFriction[1] = 1.0;
+ ob->anisotropicFriction[2] = 1.0;
+
+ act= ob->actuators.first;
+ while(act) {
+ if(act->type==ACT_EDIT_OBJECT) {
+ /* Zero initial velocity for newly
+ * added objects */
+ oa= act->data;
+ oa->linVelocity[0] = 0.0;
+ oa->linVelocity[1] = 0.0;
+ oa->linVelocity[2] = 0.0;
+ oa->localflag = 0;
+ }
+ act= act->next;
+ }
+
+ sens= ob->sensors.first;
+ while (sens) {
+ /* Extra fields for radar sensors. */
+ if(sens->type == SENS_RADAR) {
+ bRadarSensor *s = sens->data;
+ s->range = 10000.0;
+ }
+
+ /* Pulsing: defaults for new sensors. */
+ if(sens->type != SENS_ALWAYS) {
+ sens->pulse = 0;
+ sens->freq = 0;
+ } else {
+ sens->pulse = 1;
+ }
+
+ /* Invert: off. */
+ sens->invert = 0;
+
+ /* Collision and ray: default = trigger
+ * on property. The material field can
+ * remain empty. */
+ if(sens->type == SENS_COLLISION) {
+ cs = (bCollisionSensor*) sens->data;
+ cs->mode = 0;
+ }
+ if(sens->type == SENS_RAY) {
+ rs = (bRaySensor*) sens->data;
+ rs->mode = 0;
+ }
+ sens = sens->next;
+ }
+ ob= ob->id.next;
+ }
+ /* have to check the exact multiplier */
+ }
+
+ if(main->versionfile <= 210) {
+ Scene *sce= main->scene.first;
+
+ while(sce) {
+ if(sce->r.postmul== 0.0) sce->r.postmul= 1.0;
+ if(sce->r.postgamma== 0.0) sce->r.postgamma= 1.0;
+ sce= sce->id.next;
+ }
+ }
+
+ if(main->versionfile <= 211) {
+ /* Render setting: per scene, the applicable gamma value
+ * can be set. Default is 1.0, which means no
+ * correction. */
+ bActuator *act;
+ bObjectActuator *oa;
+ Object *ob;
+ Scene *sce= main->scene.first;
+ while(sce) {
+ sce->r.gamma = 2.0;
+ sce= sce->id.next;
+ }
+
+ /* added alpha in obcolor */
+ ob= main->object.first;
+ while(ob) {
+ ob->col[3]= 1.0;
+ ob= ob->id.next;
+ }
+
+ /* added alpha in obcolor */
+ ob= main->object.first;
+ while(ob) {
+ act= ob->actuators.first;
+ while(act) {
+ if (act->type==ACT_OBJECT) {
+ /* multiply velocity with 50 in old files */
+ oa= act->data;
+ if (fabs(oa->linearvelocity[0]) >= 0.01f)
+ oa->linearvelocity[0] *= 50.0;
+ if (fabs(oa->linearvelocity[1]) >= 0.01f)
+ oa->linearvelocity[1] *= 50.0;
+ if (fabs(oa->linearvelocity[2]) >= 0.01f)
+ oa->linearvelocity[2] *= 50.0;
+ if (fabs(oa->angularvelocity[0])>=0.01f)
+ oa->angularvelocity[0] *= 50.0;
+ if (fabs(oa->angularvelocity[1])>=0.01f)
+ oa->angularvelocity[1] *= 50.0;
+ if (fabs(oa->angularvelocity[2])>=0.01f)
+ oa->angularvelocity[2] *= 50.0;
+ }
+ act= act->next;
+ }
+ ob= ob->id.next;
+ }
+ }
+
+ if(main->versionfile <= 212) {
+
+ bSound* sound;
+ bProperty *prop;
+ Object *ob;
+ Mesh *me;
+
+ sound = main->sound.first;
+ while (sound)
+ {
+ sound->max_gain = 1.0;
+ sound->min_gain = 0.0;
+ sound->distance = 1.0;
+
+ if (sound->attenuation > 0.0)
+ sound->flags |= SOUND_FLAGS_3D;
+ else
+ sound->flags &= ~SOUND_FLAGS_3D;
+
+ sound = sound->id.next;
+ }
+
+ ob = main->object.first;
+
+ while (ob) {
+ prop= ob->prop.first;
+ while(prop) {
+ if (prop->type == PROP_TIME) {
+ // convert old PROP_TIME values from int to float
+ *((float *)&prop->data) = (float) prop->data;
+ }
+
+ prop= prop->next;
+ }
+ ob = ob->id.next;
+ }
+
+ /* me->subdiv changed to reflect the actual reparametization
+ * better, and smeshes were removed - if it was a smesh make
+ * it a subsurf, and reset the subdiv level because subsurf
+ * takes a lot more work to calculate.
+ */
+ for (me= main->mesh.first; me; me= me->id.next) {
+ if (me->flag&ME_SMESH) {
+ me->flag&= ~ME_SMESH;
+ me->flag|= ME_SUBSURF;
+
+ me->subdiv= 1;
+ } else {
+ if (me->subdiv<2)
+ me->subdiv= 1;
+ else
+ me->subdiv--;
+ }
+ }
+ }
+
+ if(main->versionfile <= 220) {
+ Object *ob;
+ Mesh *me;
+ bArmature *arm;
+
+ ob = main->object.first;
+
+ /* adapt form factor in order to get the 'old' physics
+ * behaviour back...*/
+
+ while (ob) {
+ /* in future, distinguish between different
+ * object bounding shapes */
+ ob->formfactor = 0.4f;
+ /* patch form factor , note that inertia equiv radius
+ * of a rotation symmetrical obj */
+ if (ob->inertia != 1.0) {
+ ob->formfactor /= ob->inertia * ob->inertia;
+ }
+ ob = ob->id.next;
+ }
+
+ /* Precalculate rest position matrices for old armatures. -rvo
+ */
+ for (arm= main->armature.first; arm; arm= arm->id.next) {
+ precalc_bonelist_irestmats (&arm->bonebase);
+ }
+
+ /* Began using alpha component of vertex colors, but
+ * old file vertex colors are undefined, reset them
+ * to be fully opaque. -zr
+ */
+ for (me= main->mesh.first; me; me= me->id.next) {
+ if (me->mcol) {
+ int i;
+
+ for (i=0; i<me->totface*4; i++) {
+ MCol *mcol= &me->mcol[i];
+ mcol->a= 255;
+ }
+ }
+ if (me->tface) {
+ int i, j;
+
+ for (i=0; i<me->totface; i++) {
+ TFace *tf= &((TFace*) me->tface)[i];
+
+ for (j=0; j<4; j++) {
+ char *col= (char*) &tf->col[j];
+
+ col[0]= 255;
+ }
+ }
+ }
+ }
+ }
+ if(main->versionfile <= 221) {
+ Scene *sce= main->scene.first;
+
+ // new variables for std-alone player and runtime
+ while(sce) {
+
+ sce->r.xplay= 640;
+ sce->r.yplay= 480;
+ sce->r.freqplay= 60;
+
+ sce= sce->id.next;
+ }
+
+ }
+ if(main->versionfile <= 222) {
+ Scene *sce= main->scene.first;
+
+ // new variables for std-alone player and runtime
+ while(sce) {
+
+ sce->r.depth= 32;
+
+ sce= sce->id.next;
+ }
+ }
+
+
+ if(main->versionfile <= 223) {
+ VFont *vf;
+ Image *ima;
+ Object *ob;
+
+ for (vf= main->vfont.first; vf; vf= vf->id.next) {
+ if (BLI_streq(vf->name+strlen(vf->name)-6, ".Bfont")) {
+ strcpy(vf->name, "<builtin>");
+ }
+ }
+
+ /* Old textures animate at 25 FPS */
+ for (ima = main->image.first; ima; ima=ima->id.next){
+ ima->animspeed = 25;
+ }
+
+ /* Zr remapped some keyboard codes to be linear (stupid zr) */
+ for (ob= main->object.first; ob; ob= ob->id.next) {
+ bSensor *sens;
+
+ for (sens= ob->sensors.first; sens; sens= sens->next) {
+ if (sens->type==SENS_KEYBOARD) {
+ bKeyboardSensor *ks= sens->data;
+
+ ks->key= map_223_keybd_code_to_224_keybd_code(ks->key);
+ ks->qual= map_223_keybd_code_to_224_keybd_code(ks->qual);
+ ks->qual2= map_223_keybd_code_to_224_keybd_code(ks->qual2);
+ }
+ }
+ }
+ }
+ if(main->versionfile <= 224) {
+ bSound* sound;
+ Scene *sce;
+ Mesh *me;
+ bScreen *sc;
+ Object *ob;
+
+ for (sound=main->sound.first; sound; sound=sound->id.next)
+ {
+ if (sound->packedfile) {
+ if (sound->newpackedfile == NULL) {
+ sound->newpackedfile = sound->packedfile;
+ }
+ sound->packedfile = NULL;
+ }
+ }
+
+ /* Clear some (now) unused pose flags */
+ for (ob=main->object.first; ob; ob=ob->id.next){
+ if (ob->pose){
+ bPoseChannel *pchan;
+ for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next){
+ pchan->flag &= ~(POSE_UNUSED1|POSE_UNUSED2|POSE_UNUSED3|POSE_UNUSED4|POSE_UNUSED5);
+ }
+ }
+ }
+
+ /* Make sure that old subsurf meshes don't have zero subdivision level for rendering */
+ for (me=main->mesh.first; me; me=me->id.next){
+ if ((me->flag & ME_SUBSURF) && (me->subdivr==0))
+ me->subdivr=me->subdiv;
+ }
+
+ for (sce= main->scene.first; sce; sce= sce->id.next) {
+ sce->r.stereomode = 1; // no stereo
+ }
+
+ /* some oldfile patch, moved from set_func_space */
+ for (sc= main->screen.first; sc; sc= sc->id.next) {
+ ScrArea *sa;
+
+ for (sa= sc->areabase.first; sa; sa= sa->next) {
+ SpaceLink *sl;
+
+ for (sl= sa->spacedata.first; sl; sl= sl->next) {
+ if (sl->spacetype==SPACE_IPO) {
+ SpaceSeq *sseq= (SpaceSeq*) sl;
+ sseq->v2d.keeptot= 0;
+ }
+ }
+ }
+ }
+ }
+
+ /* onder in blender.c de nummers wijzigen! */
+}
+
+static void lib_link_all(FileData *fd, Main *main)
+{
+ lib_link_screen(fd, main);
+ lib_link_scene(fd, main);
+ lib_link_object(fd, main);
+ lib_link_curve(fd, main);
+ lib_link_mball(fd, main);
+ lib_link_material(fd, main);
+ lib_link_texture(fd, main);
+ lib_link_image(fd, main);
+ lib_link_ipo(fd, main);
+ lib_link_key(fd, main);
+ lib_link_world(fd, main);
+ lib_link_lamp(fd, main);
+ lib_link_latt(fd, main);
+ lib_link_ika(fd, main);
+ lib_link_text(fd, main);
+ lib_link_camera(fd, main);
+ lib_link_sound(fd, main);
+ lib_link_group(fd, main);
+ lib_link_armature(fd, main);
+ lib_link_action(fd, main);
+ lib_link_vfont(fd, main);
+
+ lib_link_mesh(fd, main); /* als laatste: tpage images met users op nul */
+
+ lib_link_library(fd, main); /* alleen users goedzetten */
+}
+
+BlendFileData *blo_read_file_internal(FileData *fd, BlendReadError *error_r)
+{
+ BHead *bhead= blo_firstbhead(fd);
+ BlendFileData *bfd;
+ FileGlobal *fg;
+
+ bfd= MEM_callocN(sizeof(*bfd), "blendfiledata");
+ bfd->main= MEM_callocN(sizeof(*bfd->main), "main");
+ BLI_addtail(&fd->mainlist, bfd->main);
+
+ bfd->main->versionfile= fd->fileversion;
+
+ while(bhead) {
+ switch(bhead->code) {
+ case GLOB:
+ case DATA:
+ case DNA1:
+ case TEST:
+ case REND:
+ case USER:
+ if (bhead->code==USER) {
+ bfd->user= read_struct(fd, bhead);
+ } else if (bhead->code==GLOB) {
+ fg= read_struct(fd, bhead);
+ }
+ bhead = blo_nextbhead(fd, bhead);
+ break;
+ case ENDB:
+ bhead = NULL;
+ break;
+
+ case ID_LI:
+ bhead = read_libblock(fd, bfd->main, bhead, LIB_LOCAL, NULL);
+ break;
+ case ID_ID:
+ /* always adds to the most recently loaded
+ * ID_LI block, see direct_link_library.
+ * this is part of the file format definition.
+ */
+ bhead = read_libblock(fd, fd->mainlist.last, bhead, LIB_READ+LIB_EXTERN, NULL);
+ break;
+
+ default:
+ bhead = read_libblock(fd, bfd->main, bhead, LIB_LOCAL, NULL);
+ }
+ }
+
+ /* before read_libraries */
+ do_versions(bfd->main);
+ read_libraries(fd, &fd->mainlist);
+ blo_join_main(&fd->mainlist);
+
+ lib_link_all(fd, bfd->main);
+ link_global(fd, bfd, fg); /* als laatste */
+
+ if (!bfd->curscreen)
+ bfd->curscreen= bfd->main->screen.first;
+
+ if (bfd->curscreen) {
+ bfd->curscene= bfd->curscreen->scene;
+ if (!bfd->curscene) {
+ bfd->curscene= bfd->main->scene.first;
+ bfd->curscreen->scene= bfd->curscene;
+ }
+ }
+
+ MEM_freeN(fg);
+
+ /* require all files to have an active scene
+ * and screen. (implicitly: require all files
+ * to have at least one scene and one screen).
+ */
+ if (!bfd->curscreen || !bfd->curscene) {
+ *error_r= (!bfd->curscreen)?BRE_NO_SCREEN:BRE_NO_SCENE;
+
+ BLO_blendfiledata_free(bfd);
+ return NULL;
+ }
+
+ return bfd;
+}
+
+/* ************* APPEND LIBRARY ************** */
+
+static BHead *find_previous_lib(FileData *fd, BHead *bhead)
+{
+ for (; bhead; bhead= blo_prevbhead(fd, bhead))
+ if (bhead->code==ID_LI)
+ break;
+
+ return bhead;
+}
+
+static BHead *find_bhead(FileData *fd, void *old)
+{
+ BHead *bhead;
+
+ if (!old)
+ return NULL;
+
+ for (bhead= blo_firstbhead(fd); bhead; bhead= blo_nextbhead(fd, bhead))
+ if (bhead->old==old)
+ return bhead;
+
+ return NULL;
+}
+
+static ID *is_yet_read(Main *mainvar, BHead *bhead)
+{
+ ListBase *lb;
+ ID *idtest, *id;
+
+ // BHEAD+DATA dependancy
+ idtest= (ID *)(bhead +1);
+ lb= wich_libbase(mainvar, GS(idtest->name));
+ if(lb) {
+ id= lb->first;
+ while(id) {
+ if( strcmp(id->name, idtest->name)==0 ) return id;
+ id= id->next;
+ }
+ }
+ return 0;
+}
+
+static void expand_doit(FileData *fd, Main *mainvar, void *old)
+{
+ BHead *bhead;
+ ID *id;
+
+ bhead= find_bhead(fd, old);
+ if(bhead) {
+ /* from another library? */
+ if(bhead->code==ID_ID) {
+ BHead *bheadlib= find_previous_lib(fd, bhead);
+
+ if(bheadlib) {
+ // BHEAD+DATA dependancy
+ Library *lib= (Library *)(bheadlib+1);
+ mainvar= blo_find_main(&fd->mainlist, lib->name);
+
+ id= is_yet_read(mainvar, bhead);
+
+ if(id==0) {
+ read_libblock(fd, mainvar, bhead, LIB_READ+LIB_INDIRECT, NULL);
+ printf("expand: other lib %s\n", lib->name);
+ }
+ else {
+ oldnewmap_insert(fd->libmap, bhead->old, id, 1);
+ printf("expand: already linked: %s lib: %s\n", id->name, lib->name);
+ }
+ }
+ }
+ else {
+ id= is_yet_read(mainvar, bhead);
+ if(id==0) {
+ // BHEAD+DATA dependancy
+ id= (ID *)(bhead+1);
+ read_libblock(fd, mainvar, bhead, LIB_TESTIND, NULL);
+ }
+ else {
+ oldnewmap_insert(fd->libmap, bhead->old, id, 1);
+ /* printf("expand: al ingelezen %s\n", id->name); */
+ }
+ }
+ }
+}
+
+static void expand_key(FileData *fd, Main *mainvar, Key *key)
+{
+ expand_doit(fd, mainvar, key->ipo);
+}
+
+
+static void expand_texture(FileData *fd, Main *mainvar, Tex *tex)
+{
+ expand_doit(fd, mainvar, tex->ima);
+}
+
+static void expand_material(FileData *fd, Main *mainvar, Material *ma)
+{
+ int a;
+
+ for(a=0; a<8; a++) {
+ if(ma->mtex[a]) {
+ expand_doit(fd, mainvar, ma->mtex[a]->tex);
+ expand_doit(fd, mainvar, ma->mtex[a]->object);
+ }
+ }
+ expand_doit(fd, mainvar, ma->ipo);
+}
+
+static void expand_lamp(FileData *fd, Main *mainvar, Lamp *la)
+{
+ int a;
+
+ for(a=0; a<8; a++) {
+ if(la->mtex[a]) {
+ expand_doit(fd, mainvar, la->mtex[a]->tex);
+ expand_doit(fd, mainvar, la->mtex[a]->object);
+ }
+ }
+ expand_doit(fd, mainvar, la->ipo);
+}
+
+static void expand_lattice(FileData *fd, Main *mainvar, Lattice *lt)
+{
+ expand_doit(fd, mainvar, lt->ipo);
+ expand_doit(fd, mainvar, lt->key);
+}
+
+
+static void expand_world(FileData *fd, Main *mainvar, World *wrld)
+{
+ int a;
+
+ for(a=0; a<8; a++) {
+ if(wrld->mtex[a]) {
+ expand_doit(fd, mainvar, wrld->mtex[a]->tex);
+ expand_doit(fd, mainvar, wrld->mtex[a]->object);
+ }
+ }
+ expand_doit(fd, mainvar, wrld->ipo);
+}
+
+
+static void expand_mball(FileData *fd, Main *mainvar, MetaBall *mb)
+{
+ int a;
+
+ for(a=0; a<mb->totcol; a++) {
+ expand_doit(fd, mainvar, mb->mat[a]);
+ }
+}
+
+static void expand_curve(FileData *fd, Main *mainvar, Curve *cu)
+{
+ int a;
+
+ for(a=0; a<cu->totcol; a++) {
+ expand_doit(fd, mainvar, cu->mat[a]);
+ }
+ expand_doit(fd, mainvar, cu->vfont);
+ expand_doit(fd, mainvar, cu->key);
+ expand_doit(fd, mainvar, cu->ipo);
+ expand_doit(fd, mainvar, cu->bevobj);
+ expand_doit(fd, mainvar, cu->textoncurve);
+}
+
+static void expand_mesh(FileData *fd, Main *mainvar, Mesh *me)
+{
+ int a;
+ TFace *tface;
+
+ for(a=0; a<me->totcol; a++) {
+ expand_doit(fd, mainvar, me->mat[a]);
+ }
+
+ expand_doit(fd, mainvar, me->key);
+ expand_doit(fd, mainvar, me->texcomesh);
+
+ if(me->tface) {
+ tface= me->tface;
+ a= me->totface;
+ while(a--) {
+ if(tface->tpage) expand_doit(fd, mainvar, tface->tpage);
+ tface++;
+ }
+ }
+}
+
+static void expand_constraints(FileData *fd, Main *mainvar, ListBase *lb)
+{
+ bConstraint *curcon;
+
+ for (curcon=lb->first; curcon; curcon=curcon->next) {
+ switch (curcon->type) {
+ case CONSTRAINT_TYPE_ACTION:
+ {
+ bActionConstraint *data = (bActionConstraint*)curcon->data;
+ expand_doit(fd, mainvar, data->tar);
+ expand_doit(fd, mainvar, data->act);
+ }
+ break;
+ case CONSTRAINT_TYPE_LOCLIKE:
+ {
+ bLocateLikeConstraint *data = (bLocateLikeConstraint*)curcon->data;
+ expand_doit(fd, mainvar, data->tar);
+ break;
+ }
+ case CONSTRAINT_TYPE_ROTLIKE:
+ {
+ bRotateLikeConstraint *data = (bRotateLikeConstraint*)curcon->data;
+ expand_doit(fd, mainvar, data->tar);
+ break;
+ }
+ case CONSTRAINT_TYPE_KINEMATIC:
+ {
+ bKinematicConstraint *data = (bKinematicConstraint*)curcon->data;
+ expand_doit(fd, mainvar, data->tar);
+ break;
+ }
+ case CONSTRAINT_TYPE_TRACKTO:
+ {
+ bTrackToConstraint *data = (bTrackToConstraint*)curcon->data;
+ expand_doit(fd, mainvar, data->tar);
+ break;
+ }
+ case CONSTRAINT_TYPE_NULL:
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+static void expand_bones(FileData *fd, Main *mainvar, Bone *bone)
+{
+ Bone *curBone;
+
+// expand_constraints(fd, main, &bone->constraints);
+
+ for (curBone = bone->childbase.first; curBone; curBone=curBone->next) {
+ expand_bones(fd, mainvar, curBone);
+ }
+
+}
+
+static void expand_pose(FileData *fd, Main *mainvar, bPose *pose)
+{
+ bPoseChannel *chan;
+
+ if (!pose)
+ return;
+
+ for (chan = pose->chanbase.first; chan; chan=chan->next) {
+ expand_constraints(fd, mainvar, &chan->constraints);
+ }
+}
+
+static void expand_armature(FileData *fd, Main *mainvar, bArmature *arm)
+{
+ Bone *curBone;
+
+ for (curBone = arm->bonebase.first; curBone; curBone=curBone->next) {
+ expand_bones(fd, mainvar, curBone);
+ }
+}
+
+static void expand_constraint_channels(FileData *fd, Main *mainvar, ListBase *chanbase)
+{
+ bConstraintChannel *chan;
+ for (chan=chanbase->first; chan; chan=chan->next){
+ expand_doit(fd, mainvar, chan->ipo);
+ }
+}
+
+static void expand_action(FileData *fd, Main *mainvar, bAction *act)
+{
+ bActionChannel *chan;
+ for (chan=act->chanbase.first; chan; chan=chan->next) {
+ expand_doit(fd, mainvar, chan->ipo);
+ expand_constraint_channels(fd, mainvar, &chan->constraintChannels);
+ }
+}
+
+static void expand_object(FileData *fd, Main *mainvar, Object *ob)
+{
+ bSensor *sens;
+ bController *cont;
+ bActuator *act;
+ bActionStrip *strip;
+ int a;
+
+
+ expand_doit(fd, mainvar, ob->data);
+ expand_doit(fd, mainvar, ob->ipo);
+ expand_doit(fd, mainvar, ob->action);
+
+ expand_pose(fd, mainvar, ob->pose);
+ expand_constraints(fd, mainvar, &ob->constraints);
+ expand_constraint_channels(fd, mainvar, &ob->constraintChannels);
+
+ for (strip=ob->nlastrips.first; strip; strip=strip->next){
+ expand_doit(fd, mainvar, strip->act);
+ expand_doit(fd, mainvar, strip->ipo);
+ }
+
+ for(a=0; a<ob->totcol; a++) {
+ expand_doit(fd, mainvar, ob->mat[a]);
+ }
+ sens= ob->sensors.first;
+ while(sens) {
+ if(sens->type==SENS_TOUCH) {
+ bTouchSensor *ts= sens->data;
+ expand_doit(fd, mainvar, ts->ma);
+ }
+ else if(sens->type==SENS_MESSAGE) {
+ bMessageSensor *ms= sens->data;
+ expand_doit(fd, mainvar, ms->fromObject);
+ }
+ sens= sens->next;
+ }
+
+ cont= ob->controllers.first;
+ while(cont) {
+ if(cont->type==CONT_PYTHON) {
+ bPythonCont *pc= cont->data;
+ expand_doit(fd, mainvar, pc->text);
+ }
+ cont= cont->next;
+ }
+
+ act= ob->actuators.first;
+ while(act) {
+ if(act->type==ACT_SOUND) {
+ bSoundActuator *sa= act->data;
+ expand_doit(fd, mainvar, sa->sound);
+ }
+ else if(act->type==ACT_CAMERA) {
+ bCameraActuator *ca= act->data;
+ expand_doit(fd, mainvar, ca->ob);
+ }
+ else if(act->type==ACT_EDIT_OBJECT) {
+ bEditObjectActuator *eoa= act->data;
+ if(eoa) {
+ expand_doit(fd, mainvar, eoa->ob);
+ expand_doit(fd, mainvar, eoa->me);
+ }
+ }
+ else if(act->type==ACT_SCENE) {
+ bSceneActuator *sa= act->data;
+ expand_doit(fd, mainvar, sa->camera);
+ expand_doit(fd, mainvar, sa->scene);
+ }
+ else if(act->type==ACT_ACTION) {
+ bActionActuator *aa= act->data;
+ expand_doit(fd, mainvar, aa->act);
+ }
+ else if(act->type==ACT_PROPERTY) {
+ bPropertyActuator *pa= act->data;
+ expand_doit(fd, mainvar, pa->ob);
+ }
+ else if(act->type==ACT_MESSAGE) {
+ bMessageActuator *ma= act->data;
+ expand_doit(fd, mainvar, ma->toObject);
+ }
+ act= act->next;
+ }
+}
+
+static void expand_scene(FileData *fd, Main *mainvar, Scene *sce)
+{
+ Base *base;
+
+ base= sce->base.first;
+ while(base) {
+ expand_doit(fd, mainvar, base->object);
+ base= base->next;
+ }
+ expand_doit(fd, mainvar, sce->camera);
+ expand_doit(fd, mainvar, sce->world);
+}
+
+static void expand_camera(FileData *fd, Main *mainvar, Camera *ca)
+{
+ expand_doit(fd, mainvar, ca->ipo);
+}
+
+static void expand_sound(FileData *fd, Main *mainvar, bSound *snd)
+{
+ expand_doit(fd, mainvar, snd->ipo);
+}
+
+
+static void expand_main(FileData *fd, Main *mainvar)
+{
+ ListBase *lbarray[30];
+ ID *id;
+ int a, doit= 1;
+
+ if(fd==0) return;
+
+ while(doit) {
+ doit= 0;
+
+ a= set_listbasepointers(mainvar, lbarray);
+ while(a--) {
+ id= lbarray[a]->first;
+
+ while(id) {
+ if(id->flag & LIB_TEST) {
+
+ switch(GS(id->name)) {
+
+ case ID_OB:
+ expand_object(fd, mainvar, (Object *)id);
+ break;
+ case ID_ME:
+ expand_mesh(fd, mainvar, (Mesh *)id);
+ break;
+ case ID_CU:
+ expand_curve(fd, mainvar, (Curve *)id);
+ break;
+ case ID_MB:
+ expand_mball(fd, mainvar, (MetaBall *)id);
+ break;
+ case ID_SCE:
+ expand_scene(fd, mainvar, (Scene *)id);
+ break;
+ case ID_MA:
+ expand_material(fd, mainvar, (Material *)id);
+ break;
+ case ID_TE:
+ expand_texture(fd, mainvar, (Tex *)id);
+ break;
+ case ID_WO:
+ expand_world(fd, mainvar, (World *)id);
+ break;
+ case ID_LT:
+ expand_lattice(fd, mainvar, (Lattice *)id);
+ break;
+ case ID_LA:
+ expand_lamp(fd, mainvar,(Lamp *)id);
+ break;
+ case ID_KE:
+ expand_key(fd, mainvar, (Key *)id);
+ break;
+ case ID_CA:
+ expand_camera(fd, mainvar, (Camera *)id);
+ break;
+ case ID_SO:
+ expand_sound(fd, mainvar, (bSound *)id);
+ break;
+ case ID_AR:
+ expand_armature(fd, mainvar, (bArmature *)id);
+ break;
+ case ID_AC:
+ expand_action(fd, mainvar, (bAction *)id);
+ break;
+ }
+
+ doit= 1;
+ id->flag -= LIB_TEST;
+
+ }
+ id= id->next;
+ }
+ }
+ }
+}
+
+#if 0
+static void give_base_to_objects(Scene *sce, ListBase *lb)
+{
+ Object *ob;
+ Base *base;
+
+ /* alle objects die LIB_EXTERN en LIB_NEEDLINK zijn, een base geven */
+ ob= lb->first;
+ while(ob) {
+
+ if(ob->id.us==0) {
+
+ if(ob->id.flag & LIB_NEEDLINK) {
+
+ ob->id.flag -= LIB_NEEDLINK;
+
+ if( ob->id.flag & LIB_INDIRECT ) {
+
+ base= MEM_callocN( sizeof(Base), "add_ext_base");
+ BLI_addtail(&(sce->base), base);
+ base->lay= ob->lay;
+ base->object= ob;
+ ob->id.us= 1;
+
+ ob->id.flag -= LIB_INDIRECT;
+ ob->id.flag |= LIB_EXTERN;
+
+ }
+ }
+ }
+ ob= ob->id.next;
+ }
+}
+#endif
+
+static void append_named_part(SpaceFile *sfile, Main *mainvar, Scene *scene, char *name, int idcode)
+{
+ Object *ob;
+ Base *base;
+ BHead *bhead;
+ ID *id;
+ FileData *fd= (FileData*) sfile->libfiledata;
+ int afbreek=0;
+
+ bhead = blo_firstbhead(fd);
+ while(bhead && afbreek==0) {
+
+ if(bhead->code==ENDB) afbreek= 1;
+ else if(bhead->code==idcode) {
+ // BHEAD+DATA dependancy
+ id= (ID *)(bhead+1);
+ if(strcmp(id->name+2, name)==0) {
+
+ id= is_yet_read(mainvar, bhead);
+ if(id==0) {
+ read_libblock(fd, mainvar, bhead, LIB_TESTEXT, NULL);
+ }
+ else {
+ printf("append: already linked\n");
+ oldnewmap_insert(fd->libmap, bhead->old, id, 1);
+ if(id->flag & LIB_INDIRECT) {
+ id->flag -= LIB_INDIRECT;
+ id->flag |= LIB_EXTERN;
+ }
+ }
+
+ if(idcode==ID_OB) { /* los object: base geven */
+ base= MEM_callocN( sizeof(Base), "app_nam_part");
+ BLI_addtail(&scene->base, base);
+
+ if(id==0) ob= mainvar->object.last;
+ else ob= (Object *)id;
+
+ base->lay= ob->lay;
+ base->object= ob;
+ ob->id.us++;
+ }
+ afbreek= 1;
+ }
+ }
+
+ bhead = blo_nextbhead(fd, bhead);
+ }
+}
+
+static void append_id_part(FileData *fd, Main *mainvar, ID *id, ID **id_r)
+{
+ BHead *bhead;
+
+ for (bhead= blo_firstbhead(fd); bhead; bhead= blo_nextbhead(fd, bhead)) {
+ if (bhead->code == GS(id->name)) {
+ ID *idread= (ID *)(bhead+1); /* BHEAD+DATA dependancy */
+
+ if (BLI_streq(id->name, idread->name)) {
+ id->flag -= LIB_READ;
+ id->flag |= LIB_TEST;
+
+ read_libblock(fd, mainvar, bhead, id->flag, id_r);
+
+ break;
+ }
+ } else if (bhead->code==ENDB)
+ break;
+ }
+}
+
+
+ /* append aan G.scene */
+void BLO_library_append(SpaceFile *sfile, char *dir, int idcode)
+{
+ FileData *fd= (FileData*) sfile->libfiledata;
+ ListBase mainlist;
+ Main *main;
+ int a, totsel=0;
+
+ /* zijn er geselecteerde files? */
+ for(a=0; a<sfile->totfile; a++) {
+ if(sfile->filelist[a].flags & ACTIVE) {
+ totsel++;
+ }
+ }
+
+ if(totsel==0) {
+ /* is de aangegeven file in de filelist? */
+ if(sfile->file[0]) {
+ for(a=0; a<sfile->totfile; a++) {
+ if( strcmp(sfile->filelist[a].relname, sfile->file)==0) break;
+ }
+ if(a==sfile->totfile) {
+ error("Wrong indicated name");
+ return;
+ }
+ }
+ else {
+ error("Nothing indicated");
+ return;
+ }
+ }
+ /* nu hebben OF geselecteerde, OF 1 aangegeven file */
+
+ mainlist.first= mainlist.last= G.main;
+ G.main->next= NULL;
+
+ /* mains maken */
+ blo_split_main(&mainlist);
+
+ /* welke moeten wij hebben? */
+ main= blo_find_main(&mainlist, dir);
+
+ if(totsel==0) {
+ append_named_part(sfile, main, G.scene, sfile->file, idcode);
+ }
+ else {
+ for(a=0; a<sfile->totfile; a++) {
+ if(sfile->filelist[a].flags & ACTIVE) {
+ append_named_part(sfile, main, G.scene, sfile->filelist[a].relname, idcode);
+ }
+ }
+ }
+
+ /* de main consistent maken */
+ expand_main(fd, main);
+
+ /* als expand nog andere libs gevonden heeft: */
+ read_libraries(fd, &mainlist);
+
+ blo_join_main(&mainlist);
+ G.main= mainlist.first;
+
+ lib_link_all(fd, G.main);
+
+ /* losse objects aan G.scene hangen deze hebben nog een linkflag
+ moet na lib_link ivm gelinkte scenes (ob->us==0) */
+
+ /* indirecte objects kunnen geen kwaad */
+ /* als je deze terugzet, denk aan de 'need_link' flag: doe een find naar 'give_base_to' */
+ /* give_base_to_objects(G.scene, &(G.main->object)); */
+
+ /* voorlopige patch om te voorkomen dat de switch_endian 2x gebeurt */
+ if(fd->flags & FD_FLAGS_SWITCH_ENDIAN) {
+ blo_freefiledata((FileData*) sfile->libfiledata);
+ sfile->libfiledata= 0;
+ }
+}
+
+/* ************* READ LIBRARY ************** */
+
+static int mainvar_count_libread_blocks(Main *mainvar)
+{
+ ListBase *lbarray[30];
+ int a, tot= 0;
+
+ a= set_listbasepointers(mainvar, lbarray);
+ while(a--) {
+ ID *id= lbarray[a]->first;
+
+ for (id= lbarray[a]->first; id; id= id->next)
+ if (id->flag & LIB_READ)
+ tot++;
+ }
+ return tot;
+}
+
+static void read_libraries(FileData *basefd, ListBase *mainlist)
+{
+ Main *main= mainlist->first;
+ Main *mainptr;
+ ListBase *lbarray[30];
+ int a, doit= 1;
+
+ while(doit) {
+ doit= 0;
+
+ /* test 1: inlezen libdata */
+ mainptr= main->next;
+
+ while(mainptr) {
+ int tot= mainvar_count_libread_blocks(mainptr);
+
+ if(tot) {
+ FileData *fd= mainptr->curlib->filedata;
+
+ if(fd==0) {
+ printf("read lib %s\n", mainptr->curlib->name);
+ fd= blo_openblenderfile(mainptr->curlib->name);
+ if (fd) {
+ if (fd->libmap)
+ oldnewmap_free(fd->libmap);
+
+ fd->libmap= basefd->libmap;
+ fd->flags|= FD_FLAGS_NOT_MY_LIBMAP;
+ }
+
+ mainptr->curlib->filedata= fd;
+
+ if (!fd)
+ printf("ERROR: can't find lib %s \n", mainptr->curlib->name);
+ }
+ if(fd) {
+ doit= 1;
+ a= set_listbasepointers(mainptr, lbarray);
+ while(a--) {
+ ID *id= lbarray[a]->first;
+
+ while(id) {
+ ID *idn= id->next;
+ if(id->flag & LIB_READ) {
+ ID *realid= NULL;
+ BLI_remlink(lbarray[a], id);
+
+ append_id_part(fd, mainptr, id, &realid);
+ if (!realid)
+ printf("LIB ERROR: can't find %s\n", id->name);
+ change_libadr(fd, id, realid);
+
+ MEM_freeN(id);
+ }
+ id= idn;
+ }
+ }
+
+ expand_main(fd, mainptr);
+ }
+ }
+
+ mainptr= mainptr->next;
+ }
+ }
+ mainptr= main->next;
+ while(mainptr) {
+ /* test of er libblocken niet zijn gelezen */
+ a= set_listbasepointers(mainptr, lbarray);
+ while(a--) {
+ ID *id= lbarray[a]->first;
+ while(id) {
+ ID *idn= id->next;
+ if(id->flag & LIB_READ) {
+ BLI_remlink(lbarray[a], id);
+
+ printf("LIB ERROR: can't find %s\n", id->name);
+ change_libadr(basefd, id, 0);
+
+ MEM_freeN(id);
+ }
+ id= idn;
+ }
+ }
+
+ /* sommige mains moeten nog worden ingelezen, dan is
+ * versionfile nog nul! */
+ if(mainptr->versionfile) do_versions(mainptr);
+
+ if(mainptr->curlib->filedata) blo_freefiledata(mainptr->curlib->filedata);
+ mainptr->curlib->filedata= 0;
+
+ mainptr= mainptr->next;
+ }
+}
+
+// ****************** STREAM GLUE READER **********************
+
+static int fd_read_from_streambuffer(FileData *filedata, void *buffer, int size)
+{
+ int readsize = EOF;
+ int type;
+
+ if (size <= (filedata->inbuffer - filedata->seek)) {
+ memmove(buffer, filedata->buffer + filedata->seek, size);
+ filedata->seek += size;
+ readsize = size;
+ } else {
+ // special ENDB handling
+ if (((filedata->inbuffer - filedata->seek) == 8) && (size > 8)) {
+ memmove(&type, filedata->buffer + filedata->seek, sizeof(type));
+
+ if (type == ENDB) {
+ memmove(buffer, filedata->buffer + filedata->seek, 8);
+ readsize = 8;
+ } else {
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "Error in fd_read_from_streambuffer\n");
+#endif
+ }
+ } else {
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "Error in fd_read_from_streambuffer: not enough data available\n");
+#endif
+ }
+ }
+
+ return (readsize);
+}
+
+void *blo_readstreamfile_begin(void *endControl)
+{
+ void **params = endControl;
+
+ FileData *fd = filedata_new();
+ fd->read = fd_read_from_streambuffer;
+ fd->buffersize = 100000;
+ fd->buffer = MEM_mallocN(fd->buffersize, "Buffer readstreamfile");
+ fd->bfd_r = params[0];
+ fd->error_r = params[1];
+
+ return fd;
+}
+
+int blo_readstreamfile_process(void *filedataVoidPtr, unsigned char *data, unsigned int dataIn)
+{
+ struct FileData *filedata = filedataVoidPtr;
+ int err = 0;
+ int size, datasize;
+ char *newbuffer;
+ BHead8 bhead8;
+ BHead4 bhead4;
+
+ // copy everything in the buffer
+
+ if (((int) dataIn + filedata->inbuffer) > filedata->buffersize) {
+ // do we need a bigger buffer ?
+ if (((int) dataIn + filedata->inbuffer - filedata->seek) > filedata->buffersize) {
+ // copy data and ajust settings
+ filedata->buffersize = dataIn + filedata->inbuffer - filedata->seek;
+ newbuffer = MEM_mallocN(filedata->buffersize, "readstreamfile newbuffer");
+ memmove(newbuffer, filedata->buffer + filedata->seek, filedata->inbuffer - filedata->seek);
+ MEM_freeN(filedata->buffer);
+ filedata->buffer = newbuffer;
+ } else {
+ // we just move the existing data to the start
+ // of the block
+ memmove(filedata->buffer, filedata->buffer + filedata->seek, filedata->inbuffer - filedata->seek);
+ }
+ // adjust seek and inbuffer accordingly
+ filedata->inbuffer -= filedata->seek;
+ filedata->seek = 0;
+ }
+
+ memmove(filedata->buffer + filedata->inbuffer, data, dataIn);
+ filedata->inbuffer += dataIn;
+
+ // OK, so now we have everything in one buffer. What are we
+ // going to do with it...
+
+ while (1) {
+ datasize = filedata->inbuffer - filedata->seek;
+
+ if (filedata->headerdone) {
+ if (filedata->flags & FD_FLAGS_FILE_POINTSIZE_IS_4) {
+ if (datasize > sizeof(bhead4)) {
+ datasize -= sizeof(bhead4);
+ memmove(&bhead4, filedata->buffer + filedata->seek, sizeof(bhead4));
+ size = bhead4.len;
+ } else {
+ break;
+ }
+ } else {
+ if (datasize > sizeof(bhead8)) {
+ datasize -= sizeof(bhead8);
+ memmove(&bhead8, filedata->buffer + filedata->seek, sizeof(bhead8));
+ size = bhead8.len;
+ } else {
+ break;
+ }
+ }
+
+ if (filedata->flags & FD_FLAGS_SWITCH_ENDIAN) {
+ SWITCH_INT(size);
+ }
+
+ // do we have enough left in the buffer to read
+ // in a full bhead + data ?
+ if (size <= datasize) {
+ get_bhead(filedata);
+ } else {
+ break;
+ }
+
+ } else {
+ if (datasize < SIZEOFBLENDERHEADER) {
+ // still need more data to continue..
+ break;
+ } else {
+ decode_blender_header(filedata);
+ filedata->headerdone = 1;
+ if (! (filedata->flags & FD_FLAGS_FILE_OK)) {
+ // not a blender file ... ?
+ err = 1;
+ break;
+ }
+ }
+ }
+ }
+
+ return err;
+}
+
+int blo_readstreamfile_end(void *filedataVoidPtr)
+{
+ struct FileData *fd = filedataVoidPtr;
+ int err = 1;
+
+ *fd->bfd_r= NULL;
+ if (!(fd->flags & FD_FLAGS_FILE_OK)) {
+ *fd->error_r= BRE_NOT_A_BLEND;
+ } else if ((fd->inbuffer - fd->seek) != 8) {
+ *fd->error_r= BRE_INCOMPLETE;
+ } else if (!get_bhead(fd) || !read_file_dna(fd)) {
+ // ENDB block !
+ *fd->error_r= BRE_INCOMPLETE;
+ } else {
+ *fd->bfd_r= blo_read_file_internal(fd, fd->error_r);
+ err = 0;
+ }
+
+ blo_freefiledata(fd);
+
+ return err;
+}
diff --git a/source/blender/blenloader/intern/readfile.h b/source/blender/blenloader/intern/readfile.h
new file mode 100644
index 00000000000..af0d2f8ff12
--- /dev/null
+++ b/source/blender/blenloader/intern/readfile.h
@@ -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 *****
+ * blenloader readfile private function prototypes
+ */
+#ifndef READFILE_H
+#define READFILE_H
+
+struct OldNewMap;
+
+typedef struct FileData {
+ // linked list of BHeadN's
+ ListBase listbase;
+ int flags;
+ int eof;
+ int buffersize;
+ int seek;
+ int (*read)(struct FileData *filedata, void *buffer, int size);
+
+ // variables needed for reading from memory / stream
+ char * buffer;
+
+ // variables needed for reading from file
+ int filedes;
+
+ // variables needed for reading from stream
+ char headerdone;
+ int inbuffer;
+
+ // general reading variables
+ struct SDNA *filesdna;
+ struct SDNA *memsdna;
+ char *compflags;
+
+ int fileversion;
+
+ struct OldNewMap *datamap;
+ struct OldNewMap *globmap;
+ struct OldNewMap *libmap;
+
+ ListBase mainlist;
+
+ /* ick ick, used to return
+ * data through streamglue.
+ */
+ BlendFileData **bfd_r;
+ BlendReadError *error_r;
+} FileData;
+
+typedef struct BHeadN {
+ struct BHeadN *next, *prev;
+ struct BHead bhead;
+} BHeadN;
+
+#define FD_FLAGS_SWITCH_ENDIAN (1<<0)
+#define FD_FLAGS_FILE_POINTSIZE_IS_4 (1<<1)
+#define FD_FLAGS_POINTSIZE_DIFFERS (1<<2)
+#define FD_FLAGS_FILE_OK (1<<3)
+#define FD_FLAGS_NOT_MY_BUFFER (1<<4)
+#define FD_FLAGS_NOT_MY_LIBMAP (1<<5)
+
+#define SIZEOFBLENDERHEADER 12
+
+ /***/
+
+void blo_join_main(ListBase *mainlist);
+void blo_split_main(ListBase *mainlist);
+
+ BlendFileData*
+blo_read_file_internal(
+ FileData *fd,
+ BlendReadError *error_r);
+
+
+ FileData*
+blo_openblenderfile(
+ char *name);
+
+ FileData*
+blo_openblendermemory(
+ void *buffer,
+ int buffersize);
+
+ void
+blo_freefiledata(
+ FileData *fd);
+
+
+ BHead*
+blo_firstbhead(
+ FileData *fd);
+
+ BHead*
+blo_nextbhead(
+ FileData *fd,
+ BHead *thisblock);
+
+ BHead*
+blo_prevbhead(
+ FileData *fd,
+ BHead *thisblock);
+
+#endif
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
new file mode 100644
index 00000000000..61c933cb005
--- /dev/null
+++ b/source/blender/blenloader/intern/writefile.c
@@ -0,0 +1,1788 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * .blend file writing
+ */
+
+/*
+MIXED MODEL
+FILEFORMAAT: IFF-achtige structuur (niet meer IFF compatible!)
+
+start file:
+ BLENDER_V100 12 bytes (versie 1.00)
+ V = big endian, v = little endian
+ _ = 4 byte pointer, - = 8 byte pointer
+
+datablokken: zie ook struct BHead
+ <bh.code> 4 chars
+ <bh.len> int, len data achter BHead
+ <bh.old> void, oude pointer
+ <bh.SDNAnr> int
+ <bh.nr> int, bij array: aantal structs
+ data
+ ...
+ ...
+
+Vrijwel alle data in blender zijn structs. Elke struct krijgt
+een BHead header mee. Met BHead kan de struktuur weer worden
+gelinkt en wordt met StructDNA vergeleken.
+
+SCHRIJVEN
+
+Voorkeur volgorde schrijven: (waarschijnlijk mag ook door
+elkaar, maar waarom zou je? ) In ieder geval MOET indirekte data
+ACHTER LibBlock
+
+(Locale data)
+- voor elk LibBlock
+ - schrijf LibBlock
+ - schrijf bijhorende direkte data
+(Externe data)
+- per library
+ - schrijf library block
+ - per LibBlock
+ - schrijf ID LibBlock
+- schrijf FileGlobal (een selectie uit globale data )
+- schrijf SDNA
+- schrijf USER als aangegeven (~/.B.blend)
+*/
+
+#ifndef WIN32
+#include <unistd.h>
+#else
+#include "winsock2.h"
+#include "BLI_winstuff.h"
+#include <io.h>
+#include <process.h> // for getpid
+#endif
+
+#include <math.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "nla.h" // __NLA is defined
+
+#include "DNA_packedFile_types.h"
+#include "DNA_sdna_types.h"
+#include "DNA_property_types.h"
+#include "DNA_sensor_types.h"
+#include "DNA_controller_types.h"
+#include "DNA_actuator_types.h"
+#include "DNA_effect_types.h"
+#include "DNA_object_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_vfont_types.h"
+#include "DNA_ipo_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_meta_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_material_types.h"
+#include "DNA_lattice_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_sequence_types.h"
+#include "DNA_ika_types.h"
+#include "DNA_group_types.h"
+#include "DNA_oops_types.h"
+#include "DNA_space_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_fileglobal_types.h"
+#include "DNA_sound_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_text_types.h"
+#include "DNA_image_types.h"
+#include "DNA_key_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_constraint_types.h"
+#include "DNA_listBase.h" /* for Listbase, the type of samples, ...*/
+#include "DNA_action_types.h"
+#include "DNA_nla_types.h"
+
+#include "MEM_guardedalloc.h" // MEM_freeN
+#include "BLI_blenlib.h"
+#include "BLI_linklist.h"
+
+#include "BKE_action.h"
+#include "BKE_utildefines.h" // for KNOTSU KNOTSV WHILE_SEQ END_SEQ defines
+#include "BKE_bad_level_calls.h" // build_seqar (from WHILE_SEQ) free_oops error
+#include "BKE_constraint.h"
+#include "BKE_main.h" // G.main
+#include "BKE_global.h" // for G
+#include "BKE_screen.h" // for waitcursor
+#include "BKE_packedFile.h" // for packAll
+#include "BKE_library.h" // for set_listbasepointers
+#include "BKE_sound.h" /* ... and for samples */
+
+#include "GEN_messaging.h"
+
+#include "BLO_writefile.h"
+#include "BLO_readfile.h"
+
+#include "readfile.h"
+#include "genfile.h"
+
+/* ******* MYWRITE ********* */
+
+#include "BLO_writeStreamGlue.h"
+
+/***/
+
+typedef struct {
+ struct SDNA *sdna;
+
+ int file;
+ unsigned char *buf;
+
+ int tot, count, error;
+
+ int is_publisher;
+ struct writeStreamGlueStruct *streamGlue;
+} WriteData;
+
+static WriteData *writedata_new(int file, int is_publisher)
+{
+ extern char DNAstr[]; /* DNA.c */
+ extern int DNAlen;
+
+ WriteData *wd= MEM_callocN(sizeof(*wd), "writedata");
+
+ /* XXX, see note about this in readfile.c, remove
+ * once we have an xp lock - zr
+ */
+ wd->sdna= dna_sdna_from_data(DNAstr, DNAlen, 0);
+
+ wd->file= file;
+ wd->is_publisher= is_publisher;
+
+ wd->buf= MEM_mallocN(100000, "wd->buf");
+
+ return wd;
+}
+
+static void writedata_do_write(WriteData *wd, void *mem, int memlen)
+{
+ if (wd->error) return;
+
+ if (wd->is_publisher) {
+ wd->error = writeStreamGlue(Global_streamGlueControl, &wd->streamGlue, mem, memlen, 0);
+ } else {
+ if (write(wd->file, mem, memlen) != memlen)
+ wd->error= 1;
+ }
+}
+
+static void writedata_free(WriteData *wd)
+{
+ dna_freestructDNA(wd->sdna);
+
+ MEM_freeN(wd->buf);
+ MEM_freeN(wd);
+}
+
+/***/
+
+struct streamGlueControlStruct *Global_streamGlueControl;
+int mywfile;
+
+#include "license_key.h"
+
+/**
+ * Low level WRITE(2) wrapper that buffers data
+ * @param adr Pointer to new chunk of data
+ * @param len Length of new chunk of data
+ * @warning Talks to other functions with global parameters
+ */
+ static void
+mywrite(
+ WriteData *wd,
+ void *adr,
+ int len)
+{
+ if (wd->error) return;
+
+ wd->tot+= len;
+
+ if(len>50000) {
+ if(wd->count) {
+ writedata_do_write(wd, wd->buf, wd->count);
+ wd->count= 0;
+ }
+ writedata_do_write(wd, adr, len);
+ return;
+ }
+ if(len+wd->count>99999) {
+ writedata_do_write(wd, wd->buf, wd->count);
+ wd->count= 0;
+ }
+ memcpy(&wd->buf[wd->count], adr, len);
+ wd->count+= len;
+}
+
+/**
+ * BeGiN initializer for mywrite
+ * @param file File descriptor
+ * @param write_flags Write parameters
+ * @warning Talks to other functions with global parameters
+ */
+ static WriteData *
+bgnwrite(
+ int file,
+ int write_flags)
+{
+ int is_publisher= ((write_flags & (G_FILE_COMPRESS | G_FILE_LOCK | G_FILE_SIGN | G_FILE_PUBLISH)) && LICENSE_KEY_VALID);
+ WriteData *wd= writedata_new(file, is_publisher);
+
+ if (is_publisher) {
+ mywfile= file;
+ wd->streamGlue = NULL;
+ Global_streamGlueControl = streamGlueControlConstructor();
+ streamGlueControlAppendAction(Global_streamGlueControl, DUMPFROMMEMORY);
+ if (write_flags & G_FILE_COMPRESS) {
+ streamGlueControlAppendAction(Global_streamGlueControl, DEFLATE);
+ }
+ if (write_flags & G_FILE_LOCK) {
+ streamGlueControlAppendAction(Global_streamGlueControl, ENCRYPT);
+ }
+ if (write_flags & G_FILE_SIGN) {
+ streamGlueControlAppendAction(Global_streamGlueControl, SIGN);
+ }
+ streamGlueControlAppendAction(Global_streamGlueControl, WRITEBLENFILE);
+ }
+
+ return wd;
+}
+
+/**
+ * END the mywrite wrapper
+ * @return 1 if write failed
+ * @return unknown global variable otherwise
+ * @warning Talks to other functions with global parameters
+ */
+ static int
+endwrite(
+ WriteData *wd)
+{
+ int err;
+
+ if (wd->count) {
+ writedata_do_write(wd, wd->buf, wd->count);
+ wd->count= 0;
+ }
+ if (wd->is_publisher) {
+ writeStreamGlue(Global_streamGlueControl, &wd->streamGlue, NULL, 0, 1);
+ streamGlueControlDestructor(Global_streamGlueControl);
+ // final writestream error handling goes here
+ if (wd->error) {
+ int err = wd->error;
+ int errFunction = BWS_GETFUNCTION(err);
+ int errGeneric = BWS_GETGENERR(err);
+ int errSpecific = BWS_GETSPECERR(err);
+ char *errFunctionStrings[] = {
+ "",
+ "The write stream",
+ "The deflation",
+ "The encryption",
+ "The signing",
+ "Writing the blendfile"
+ };
+ char *errGenericStrings[] = {
+ "",
+ "generated an out of memory error",
+ "is not allowed in this version",
+ "has problems with your key"
+ };
+ char *errWriteStreamGlueStrings[] = {
+ "",
+ "does not know how to proceed"
+ };
+ char *errDeflateStrings[] = {
+ "",
+ "bumped on a compress error"
+ };
+ char *errEncryptStrings[] = {
+ "",
+ "could not write the key",
+ "bumped on an encrypt error"
+ };
+ char *errSignStrings[] = {
+ "",
+ "could not write the key",
+ "failed"
+ };
+ char *errWriteBlenFileStrings[] = {
+ "",
+ "encountered problems writing the filedescription",
+ "encountered problems writing the blendfile",
+ "encountered problems writing one (or more) parameters"
+ };
+ char *errFunctionString= errFunctionStrings[errFunction];
+ char *errExtraString= "";
+
+ if (errGeneric)
+ {
+ errExtraString= errGenericStrings[errGeneric];
+ }
+ else if (errSpecific)
+ {
+ switch (errFunction)
+ {
+ case BWS_WRITESTREAMGLUE:
+ errExtraString= errWriteStreamGlueStrings[errSpecific];
+ break;
+ case BWS_DEFLATE:
+ errExtraString= errDeflateStrings[errSpecific];
+ break;
+ case BWS_ENCRYPT:
+ errExtraString= errEncryptStrings[errSpecific];
+ break;
+ case BWS_SIGN:
+ errExtraString= errSignStrings[errSpecific];
+ break;
+ case BWS_WRITEBLENFILE:
+ errExtraString= errWriteBlenFileStrings[errSpecific];
+ break;
+ default:
+ break;
+ }
+ }
+
+ // call Blender error popup window
+ error("%s %s", errFunctionString, errExtraString);
+ }
+ }
+
+ err= wd->error;
+ writedata_free(wd);
+
+ return err;
+}
+
+/* ********** WRITE FILE ****************** */
+
+static void writestruct(WriteData *wd, int filecode, char *structname, int nr, void *adr)
+{
+ BHead bh;
+ short *sp;
+
+ if(adr==0 || nr==0) return;
+
+ /* BHead vullen met data */
+ bh.code= filecode;
+ bh.old= adr;
+ bh.nr= nr;
+
+ bh.SDNAnr= dna_findstruct_nr(wd->sdna, structname);
+ if(bh.SDNAnr== -1) {
+ printf("error: can't find SDNA code %s\n", structname);
+ return;
+ }
+ sp= wd->sdna->structs[bh.SDNAnr];
+
+ bh.len= nr*wd->sdna->typelens[sp[0]];
+
+ if(bh.len==0) return;
+
+ mywrite(wd, &bh, sizeof(BHead));
+ mywrite(wd, adr, bh.len);
+}
+
+static void writedata(WriteData *wd, int filecode, int len, void *adr) /* geen struct */
+{
+ BHead bh;
+
+ if(adr==0) return;
+ if(len==0) return;
+
+ len+= 3;
+ len-= ( len % 4);
+
+ /* BHead vullen met data */
+ bh.code= filecode;
+ bh.old= adr;
+ bh.nr= 1;
+ bh.SDNAnr= 0;
+ bh.len= len;
+
+ mywrite(wd, &bh, sizeof(BHead));
+ if(len) mywrite(wd, adr, len);
+}
+
+static void write_scriptlink(WriteData *wd, ScriptLink *slink)
+{
+ writedata(wd, DATA, sizeof(void *)*slink->totscript, slink->scripts);
+ writedata(wd, DATA, sizeof(short)*slink->totscript, slink->flag);
+}
+
+static void write_renderinfo(WriteData *wd) /* alleen voor renderdaemon */
+{
+ Scene *sce;
+ int data[8];
+
+ sce= G.main->scene.first;
+ while(sce) {
+ if(sce->id.lib==0 && ( sce==G.scene || (sce->r.scemode & R_BG_RENDER)) ) {
+ data[0]= sce->r.sfra;
+ data[1]= sce->r.efra;
+
+ strncpy((char *)(data+2), sce->id.name+2, 23);
+
+ writedata(wd, REND, 32, data);
+ }
+ sce= sce->id.next;
+ }
+}
+
+static void write_userdef(WriteData *wd)
+{
+ writestruct(wd, USER, "UserDef", 1, &U);
+}
+
+static void write_effects(WriteData *wd, ListBase *lb)
+{
+ Effect *eff;
+
+ eff= lb->first;
+ while(eff) {
+
+ switch(eff->type) {
+ case EFF_BUILD:
+ writestruct(wd, DATA, "BuildEff", 1, eff);
+ break;
+ case EFF_PARTICLE:
+ writestruct(wd, DATA, "PartEff", 1, eff);
+ break;
+ case EFF_WAVE:
+ writestruct(wd, DATA, "WaveEff", 1, eff);
+ break;
+ default:
+ writedata(wd, DATA, MEM_allocN_len(eff), eff);
+ }
+
+ eff= eff->next;
+ }
+}
+
+static void write_properties(WriteData *wd, ListBase *lb)
+{
+ bProperty *prop;
+
+ prop= lb->first;
+ while(prop) {
+ writestruct(wd, DATA, "bProperty", 1, prop);
+
+ if(prop->poin && prop->poin != &prop->data)
+ writedata(wd, DATA, MEM_allocN_len(prop->poin), prop->poin);
+
+ prop= prop->next;
+ }
+}
+
+static void write_sensors(WriteData *wd, ListBase *lb)
+{
+ bSensor *sens;
+
+ sens= lb->first;
+ while(sens) {
+ writestruct(wd, DATA, "bSensor", 1, sens);
+
+ writedata(wd, DATA, sizeof(void *)*sens->totlinks, sens->links);
+
+ switch(sens->type) {
+ case SENS_NEAR:
+ writestruct(wd, DATA, "bNearSensor", 1, sens->data);
+ break;
+ case SENS_MOUSE:
+ writestruct(wd, DATA, "bMouseSensor", 1, sens->data);
+ break;
+ case SENS_TOUCH:
+ writestruct(wd, DATA, "bTouchSensor", 1, sens->data);
+ break;
+ case SENS_KEYBOARD:
+ writestruct(wd, DATA, "bKeyboardSensor", 1, sens->data);
+ break;
+ case SENS_PROPERTY:
+ writestruct(wd, DATA, "bPropertySensor", 1, sens->data);
+ break;
+ case SENS_COLLISION:
+ writestruct(wd, DATA, "bCollisionSensor", 1, sens->data);
+ break;
+ case SENS_RADAR:
+ writestruct(wd, DATA, "bRadarSensor", 1, sens->data);
+ break;
+ case SENS_RANDOM:
+ writestruct(wd, DATA, "bRandomSensor", 1, sens->data);
+ break;
+ case SENS_RAY:
+ writestruct(wd, DATA, "bRaySensor", 1, sens->data);
+ break;
+ case SENS_MESSAGE:
+ writestruct(wd, DATA, "bMessageSensor", 1, sens->data);
+ break;
+ default:
+ ; /* error: don't know how to write this file */
+ }
+
+ sens= sens->next;
+ }
+}
+
+static void write_controllers(WriteData *wd, ListBase *lb)
+{
+ bController *cont;
+
+ cont= lb->first;
+ while(cont) {
+ writestruct(wd, DATA, "bController", 1, cont);
+
+ writedata(wd, DATA, sizeof(void *)*cont->totlinks, cont->links);
+
+ switch(cont->type) {
+ case CONT_EXPRESSION:
+ writestruct(wd, DATA, "bExpressionCont", 1, cont->data);
+ break;
+ case CONT_PYTHON:
+ writestruct(wd, DATA, "bPythonCont", 1, cont->data);
+ break;
+ default:
+ ; /* error: don't know how to write this file */
+ }
+
+ cont= cont->next;
+ }
+}
+
+static void write_actuators(WriteData *wd, ListBase *lb)
+{
+ bActuator *act;
+
+ act= lb->first;
+ while(act) {
+ writestruct(wd, DATA, "bActuator", 1, act);
+
+ switch(act->type) {
+ case ACT_ACTION:
+ writestruct(wd, DATA, "bActionActuator", 1, act->data);
+ break;
+ case ACT_SOUND:
+ writestruct(wd, DATA, "bSoundActuator", 1, act->data);
+ break;
+ case ACT_CD:
+ writestruct(wd, DATA, "bCDActuator", 1, act->data);
+ break;
+ case ACT_OBJECT:
+ writestruct(wd, DATA, "bObjectActuator", 1, act->data);
+ break;
+ case ACT_IPO:
+ writestruct(wd, DATA, "bIpoActuator", 1, act->data);
+ break;
+ case ACT_PROPERTY:
+ writestruct(wd, DATA, "bPropertyActuator", 1, act->data);
+ break;
+ case ACT_CAMERA:
+ writestruct(wd, DATA, "bCameraActuator", 1, act->data);
+ break;
+ case ACT_CONSTRAINT:
+ writestruct(wd, DATA, "bConstraintActuator", 1, act->data);
+ break;
+ case ACT_EDIT_OBJECT:
+ writestruct(wd, DATA, "bEditObjectActuator", 1, act->data);
+ break;
+ case ACT_SCENE:
+ writestruct(wd, DATA, "bSceneActuator", 1, act->data);
+ break;
+ case ACT_GROUP:
+ writestruct(wd, DATA, "bGroupActuator", 1, act->data);
+ break;
+ case ACT_RANDOM:
+ writestruct(wd, DATA, "bRandomActuator", 1, act->data);
+ break;
+ case ACT_MESSAGE:
+ writestruct(wd, DATA, "bMessageActuator", 1, act->data);
+ break;
+ case ACT_GAME:
+ writestruct(wd, DATA, "bGameActuator", 1, act->data);
+ break;
+ case ACT_VISIBILITY:
+ writestruct(wd, DATA, "bVisibilityActuator", 1, act->data);
+ break;
+ default:
+ ; /* error: don't know how to write this file */
+ }
+
+ act= act->next;
+ }
+}
+
+static void write_nlastrips(WriteData *wd, ListBase *nlabase)
+{
+ bActionStrip *strip;
+
+ for (strip=nlabase->first; strip; strip=strip->next)
+ writestruct(wd, DATA, "bActionStrip", 1, strip);
+}
+
+static void write_constraints(WriteData *wd, ListBase *conlist)
+{
+ bConstraint *con;
+
+ for (con=conlist->first; con; con=con->next) {
+ /* Write the specific data */
+ switch (con->type) {
+ case CONSTRAINT_TYPE_NULL:
+ break;
+ case CONSTRAINT_TYPE_TRACKTO:
+ writestruct(wd, DATA, "bTrackToConstraint", 1, con->data);
+ break;
+ case CONSTRAINT_TYPE_KINEMATIC:
+ writestruct(wd, DATA, "bKinematicConstraint", 1, con->data);
+ break;
+ case CONSTRAINT_TYPE_ROTLIKE:
+ writestruct(wd, DATA, "bRotateLikeConstraint", 1, con->data);
+ break;
+ case CONSTRAINT_TYPE_LOCLIKE:
+ writestruct(wd, DATA, "bLocateLikeConstraint", 1, con->data);
+ break;
+ case CONSTRAINT_TYPE_ACTION:
+ writestruct(wd, DATA, "bActionConstraint", 1, con->data);
+ break;
+ default:
+ break;
+ }
+ /* Write the constraint */
+ writestruct(wd, DATA, "bConstraint", 1, con);
+ }
+}
+
+static void write_pose(WriteData *wd, bPose *pose)
+{
+ bPoseChannel *chan;
+
+ /* Write each channel */
+
+ if (!pose)
+ return;
+
+ // Write channels
+ for (chan=pose->chanbase.first; chan; chan=chan->next) {
+ write_constraints(wd, &chan->constraints);
+ writestruct(wd, DATA, "bPoseChannel", 1, chan);
+ }
+
+ // Write this pose
+ writestruct(wd, DATA, "bPose", 1, pose);
+}
+
+static void write_defgroups(WriteData *wd, ListBase *defbase)
+{
+ bDeformGroup *defgroup;
+
+ for (defgroup=defbase->first; defgroup; defgroup=defgroup->next)
+ writestruct(wd, DATA, "bDeformGroup", 1, defgroup);
+}
+
+static void write_constraint_channels(WriteData *wd, ListBase *chanbase)
+{
+ bConstraintChannel *chan;
+
+ for (chan = chanbase->first; chan; chan=chan->next)
+ writestruct(wd, DATA, "bConstraintChannel", 1, chan);
+
+}
+
+static void write_objects(WriteData *wd, ListBase *idbase)
+{
+ Object *ob;
+
+ ob= idbase->first;
+ while(ob) {
+ if(ob->id.us>0) {
+ /* schrijf LibData */
+ writestruct(wd, ID_OB, "Object", 1, ob);
+
+ /* alle direkte data */
+ writedata(wd, DATA, sizeof(void *)*ob->totcol, ob->mat);
+ write_effects(wd, &ob->effect);
+ write_properties(wd, &ob->prop);
+ write_sensors(wd, &ob->sensors);
+ write_controllers(wd, &ob->controllers);
+ write_actuators(wd, &ob->actuators);
+ write_scriptlink(wd, &ob->scriptlink);
+ write_pose(wd, ob->pose);
+ write_defgroups(wd, &ob->defbase);
+ write_constraints(wd, &ob->constraints);
+ write_constraint_channels(wd, &ob->constraintChannels);
+ write_nlastrips(wd, &ob->nlastrips);
+ }
+ ob= ob->id.next;
+ }
+}
+
+
+static void write_vfonts(WriteData *wd, ListBase *idbase)
+{
+ VFont *vf;
+ PackedFile * pf;
+
+ vf= idbase->first;
+ while(vf) {
+ if(vf->id.us>0) {
+ /* schrijf LibData */
+ writestruct(wd, ID_VF, "VFont", 1, vf);
+
+ /* alle direkte data */
+
+ if (vf->packedfile) {
+ pf = vf->packedfile;
+ writestruct(wd, DATA, "PackedFile", 1, pf);
+ writedata(wd, DATA, pf->size, pf->data);
+ }
+ }
+
+ vf= vf->id.next;
+ }
+}
+
+static void write_ipos(WriteData *wd, ListBase *idbase)
+{
+ Ipo *ipo;
+ IpoCurve *icu;
+
+ ipo= idbase->first;
+ while(ipo) {
+ if(ipo->id.us>0) {
+ /* schrijf LibData */
+ writestruct(wd, ID_IP, "Ipo", 1, ipo);
+
+ /* alle direkte data */
+ icu= ipo->curve.first;
+ while(icu) {
+ writestruct(wd, DATA, "IpoCurve", 1, icu);
+ icu= icu->next;
+ }
+
+ icu= ipo->curve.first;
+ while(icu) {
+ if(icu->bezt) writestruct(wd, DATA, "BezTriple", icu->totvert, icu->bezt);
+ if(icu->bp) writestruct(wd, DATA, "BPoint", icu->totvert, icu->bp);
+ icu= icu->next;
+ }
+ }
+
+ ipo= ipo->id.next;
+ }
+}
+
+static void write_keys(WriteData *wd, ListBase *idbase)
+{
+ Key *key;
+ KeyBlock *kb;
+
+ key= idbase->first;
+ while(key) {
+ if(key->id.us>0) {
+ /* schrijf LibData */
+ writestruct(wd, ID_KE, "Key", 1, key);
+
+ /* alle direkte data */
+ kb= key->block.first;
+ while(kb) {
+ writestruct(wd, DATA, "KeyBlock", 1, kb);
+ if(kb->data) writedata(wd, DATA, kb->totelem*key->elemsize, kb->data);
+ kb= kb->next;
+ }
+ }
+
+ key= key->id.next;
+ }
+}
+
+static void write_cameras(WriteData *wd, ListBase *idbase)
+{
+ Camera *cam;
+
+ cam= idbase->first;
+ while(cam) {
+ if(cam->id.us>0) {
+ /* schrijf LibData */
+ writestruct(wd, ID_CA, "Camera", 1, cam);
+
+ /* alle direkte data */
+ write_scriptlink(wd, &cam->scriptlink);
+ }
+
+ cam= cam->id.next;
+ }
+}
+
+static void write_mballs(WriteData *wd, ListBase *idbase)
+{
+ MetaBall *mb;
+ MetaElem *ml;
+
+ mb= idbase->first;
+ while(mb) {
+ if(mb->id.us>0) {
+ /* schrijf LibData */
+ writestruct(wd, ID_MB, "MetaBall", 1, mb);
+
+ /* alle direkte data */
+ writedata(wd, DATA, sizeof(void *)*mb->totcol, mb->mat);
+
+ ml= mb->elems.first;
+ while(ml) {
+ writestruct(wd, DATA, "MetaElem", 1, ml);
+ ml= ml->next;
+ }
+ }
+ mb= mb->id.next;
+ }
+}
+
+static void write_curves(WriteData *wd, ListBase *idbase)
+{
+ Curve *cu;
+ Nurb *nu;
+
+ cu= idbase->first;
+ while(cu) {
+ if(cu->id.us>0) {
+ /* schrijf LibData */
+ writestruct(wd, ID_CU, "Curve", 1, cu);
+
+ /* alle direkte data */
+ writedata(wd, DATA, sizeof(void *)*cu->totcol, cu->mat);
+
+ if(cu->vfont) {
+ writedata(wd, DATA, cu->len+1, cu->str);
+ }
+ else {
+ /* is ook volgorde van inlezen */
+ nu= cu->nurb.first;
+ while(nu) {
+ writestruct(wd, DATA, "Nurb", 1, nu);
+ nu= nu->next;
+ }
+ nu= cu->nurb.first;
+ while(nu) {
+ if( (nu->type & 7)==CU_BEZIER)
+ writestruct(wd, DATA, "BezTriple", nu->pntsu, nu->bezt);
+ else {
+ writestruct(wd, DATA, "BPoint", nu->pntsu*nu->pntsv, nu->bp);
+ if(nu->knotsu) writedata(wd, DATA, KNOTSU(nu)*sizeof(float), nu->knotsu);
+ if(nu->knotsv) writedata(wd, DATA, KNOTSV(nu)*sizeof(float), nu->knotsv);
+ }
+ nu= nu->next;
+ }
+ }
+ }
+ cu= cu->id.next;
+ }
+}
+
+static void write_dverts(WriteData *wd, int count, MDeformVert *dvlist)
+{
+ int i;
+
+ /* Write the dvert list */
+ writestruct(wd, DATA, "MDeformVert", count, dvlist);
+
+ /* Write deformation data for each dvert */
+ if (dvlist) {
+ for (i=0; i<count; i++) {
+ if (dvlist[i].dw)
+ writestruct(wd, DATA, "MDeformWeight", dvlist[i].totweight, dvlist[i].dw);
+ }
+ }
+}
+
+static void write_meshs(WriteData *wd, ListBase *idbase)
+{
+ Mesh *mesh;
+
+ mesh= idbase->first;
+ while(mesh) {
+ if(mesh->id.us>0) {
+ /* schrijf LibData */
+ writestruct(wd, ID_ME, "Mesh", 1, mesh);
+
+ /* alle direkte data */
+ writedata(wd, DATA, sizeof(void *)*mesh->totcol, mesh->mat);
+ writestruct(wd, DATA, "MVert", mesh->totvert, mesh->mvert);
+ write_dverts(wd, mesh->totvert, mesh->dvert);
+ writestruct(wd, DATA, "MFace", mesh->totface, mesh->mface);
+ writestruct(wd, DATA, "TFace", mesh->totface, mesh->tface);
+ writestruct(wd, DATA, "MCol", 4*mesh->totface, mesh->mcol);
+ writestruct(wd, DATA, "MSticky", mesh->totvert, mesh->msticky);
+
+ }
+ mesh= mesh->id.next;
+ }
+}
+
+static void write_images(WriteData *wd, ListBase *idbase)
+{
+ Image *ima;
+ PackedFile * pf;
+
+ ima= idbase->first;
+ while(ima) {
+ if(ima->id.us>0) {
+ /* schrijf LibData */
+ writestruct(wd, ID_IM, "Image", 1, ima);
+
+ if (ima->packedfile) {
+ pf = ima->packedfile;
+ writestruct(wd, DATA, "PackedFile", 1, pf);
+ writedata(wd, DATA, pf->size, pf->data);
+ }
+ }
+ ima= ima->id.next;
+ }
+}
+
+static void write_textures(WriteData *wd, ListBase *idbase)
+{
+ Tex *tex;
+
+ tex= idbase->first;
+ while(tex) {
+ if(tex->id.us>0) {
+ /* schrijf LibData */
+ writestruct(wd, ID_TE, "Tex", 1, tex);
+
+ /* alle direkte data */
+ if(tex->plugin) writestruct(wd, DATA, "PluginTex", 1, tex->plugin);
+ if(tex->coba) writestruct(wd, DATA, "ColorBand", 1, tex->coba);
+ if(tex->env) writestruct(wd, DATA, "EnvMap", 1, tex->env);
+ }
+ tex= tex->id.next;
+ }
+}
+
+static void write_materials(WriteData *wd, ListBase *idbase)
+{
+ Material *ma;
+ int a;
+
+ ma= idbase->first;
+ while(ma) {
+ if(ma->id.us>0) {
+ /* schrijf LibData */
+ writestruct(wd, ID_MA, "Material", 1, ma);
+
+ for(a=0; a<8; a++) {
+ if(ma->mtex[a]) writestruct(wd, DATA, "MTex", 1, ma->mtex[a]);
+ }
+
+ write_scriptlink(wd, &ma->scriptlink);
+ }
+ ma= ma->id.next;
+ }
+}
+
+static void write_worlds(WriteData *wd, ListBase *idbase)
+{
+ World *wrld;
+ int a;
+
+ wrld= idbase->first;
+ while(wrld) {
+ if(wrld->id.us>0) {
+ /* schrijf LibData */
+ writestruct(wd, ID_WO, "World", 1, wrld);
+
+ for(a=0; a<8; a++) {
+ if(wrld->mtex[a]) writestruct(wd, DATA, "MTex", 1, wrld->mtex[a]);
+ }
+
+ write_scriptlink(wd, &wrld->scriptlink);
+ }
+ wrld= wrld->id.next;
+ }
+}
+
+static void write_lamps(WriteData *wd, ListBase *idbase)
+{
+ Lamp *la;
+ int a;
+
+ la= idbase->first;
+ while(la) {
+ if(la->id.us>0) {
+ /* schrijf LibData */
+ writestruct(wd, ID_LA, "Lamp", 1, la);
+
+ /* alle direkte data */
+ for(a=0; a<8; a++) {
+ if(la->mtex[a]) writestruct(wd, DATA, "MTex", 1, la->mtex[a]);
+ }
+
+ write_scriptlink(wd, &la->scriptlink);
+ }
+ la= la->id.next;
+ }
+}
+
+static void write_lattices(WriteData *wd, ListBase *idbase)
+{
+ Lattice *lt;
+
+ lt= idbase->first;
+ while(lt) {
+ if(lt->id.us>0) {
+ /* schrijf LibData */
+ writestruct(wd, ID_LT, "Lattice", 1, lt);
+
+ /* alle direkte data */
+ writestruct(wd, DATA, "BPoint", lt->pntsu*lt->pntsv*lt->pntsw, lt->def);
+ }
+ lt= lt->id.next;
+ }
+}
+
+static void write_ikas(WriteData *wd, ListBase *idbase)
+{
+ Ika *ika;
+ Limb *li;
+
+ ika= idbase->first;
+ while(ika) {
+ if(ika->id.us>0) {
+ /* schrijf LibData */
+ writestruct(wd, ID_IK, "Ika", 1, ika);
+
+ /* alle direkte data */
+ li= ika->limbbase.first;
+ while(li) {
+ writestruct(wd, DATA, "Limb", 1, li);
+ li= li->next;
+ }
+
+ writestruct(wd, DATA, "Deform", ika->totdef, ika->def);
+ }
+ ika= ika->id.next;
+ }
+}
+
+static void write_scenes(WriteData *wd, ListBase *scebase)
+{
+ Scene *sce;
+ Base *base;
+ Editing *ed;
+ Sequence *seq;
+ Strip *strip;
+
+ sce= scebase->first;
+ while(sce) {
+ /* schrijf LibData */
+ writestruct(wd, ID_SCE, "Scene", 1, sce);
+
+ /* alle direkte data */
+ base= sce->base.first;
+ while(base) {
+ writestruct(wd, DATA, "Base", 1, base);
+ base= base->next;
+ }
+
+ writestruct(wd, DATA, "Radio", 1, sce->radio);
+ writestruct(wd, DATA, "FreeCamera", 1, sce->fcam);
+
+ ed= sce->ed;
+ if(ed) {
+ writestruct(wd, DATA, "Editing", 1, ed);
+
+ /* ook schrijfflags op nul */
+ WHILE_SEQ(&ed->seqbase) {
+ if(seq->strip) seq->strip->done= 0;
+ writestruct(wd, DATA, "Sequence", 1, seq);
+ }
+ END_SEQ
+
+ WHILE_SEQ(&ed->seqbase) {
+ if(seq->strip && seq->strip->done==0) {
+ /* strip wegschrijven met done op 0 ivm readfile */
+
+ if(seq->plugin) writestruct(wd, DATA, "PluginSeq", 1, seq->plugin);
+
+ strip= seq->strip;
+ writestruct(wd, DATA, "Strip", 1, strip);
+
+ if(seq->type==SEQ_IMAGE)
+ writestruct(wd, DATA, "StripElem", strip->len, strip->stripdata);
+ else if(seq->type==SEQ_MOVIE)
+ writestruct(wd, DATA, "StripElem", 1, strip->stripdata);
+
+ strip->done= 1;
+ }
+ }
+ END_SEQ
+ }
+
+ write_scriptlink(wd, &sce->scriptlink);
+
+ if (sce->r.avicodecdata) {
+ writestruct(wd, DATA, "AviCodecData", 1, sce->r.avicodecdata);
+ if (sce->r.avicodecdata->lpFormat) writedata(wd, DATA, sce->r.avicodecdata->cbFormat, sce->r.avicodecdata->lpFormat);
+ if (sce->r.avicodecdata->lpParms) writedata(wd, DATA, sce->r.avicodecdata->cbParms, sce->r.avicodecdata->lpParms);
+ }
+
+ sce= sce->id.next;
+ }
+}
+
+static void write_screens(WriteData *wd, ListBase *scrbase)
+{
+ bScreen *sc;
+ ScrArea *sa;
+ ScrVert *sv;
+ ScrEdge *se;
+
+ sc= scrbase->first;
+ while(sc) {
+ /* schrijf LibData */
+ writestruct(wd, ID_SCR, "Screen", 1, sc);
+
+ /* alle direkte data */
+ sv= sc->vertbase.first;
+ while(sv) {
+ writestruct(wd, DATA, "ScrVert", 1, sv);
+ sv= sv->next;
+ }
+
+ se= sc->edgebase.first;
+ while(se) {
+ writestruct(wd, DATA, "ScrEdge", 1, se);
+ se= se->next;
+ }
+
+ sa= sc->areabase.first;
+ while(sa) {
+ SpaceLink *sl;
+
+ writestruct(wd, DATA, "ScrArea", 1, sa);
+
+ sl= sa->spacedata.first;
+ while(sl) {
+ if(sl->spacetype==SPACE_VIEW3D) {
+ View3D *v3d= (View3D*) sl;
+ writestruct(wd, DATA, "View3D", 1, v3d);
+ if(v3d->bgpic) writestruct(wd, DATA, "BGpic", 1, v3d->bgpic);
+ if(v3d->localvd) writestruct(wd, DATA, "View3D", 1, v3d->localvd);
+ }
+ else if(sl->spacetype==SPACE_IPO) {
+ writestruct(wd, DATA, "SpaceIpo", 1, sl);
+ }
+ else if(sl->spacetype==SPACE_BUTS) {
+ writestruct(wd, DATA, "SpaceButs", 1, sl);
+ }
+ else if(sl->spacetype==SPACE_FILE) {
+ writestruct(wd, DATA, "SpaceFile", 1, sl);
+ }
+ else if(sl->spacetype==SPACE_SEQ) {
+ writestruct(wd, DATA, "SpaceSeq", 1, sl);
+ }
+ else if(sl->spacetype==SPACE_OOPS) {
+ SpaceOops *so= (SpaceOops *)sl;
+ Oops *oops;
+
+ /* cleanup */
+ oops= so->oops.first;
+ while(oops) {
+ Oops *oopsn= oops->next;
+ if(oops->id==0) {
+ BLI_remlink(&so->oops, oops);
+ free_oops(oops);
+ }
+ oops= oopsn;
+ }
+
+ /* NA de cleanup, ivm listbase! */
+ writestruct(wd, DATA, "SpaceOops", 1, so);
+
+ oops= so->oops.first;
+ while(oops) {
+ writestruct(wd, DATA, "Oops", 1, oops);
+ oops= oops->next;
+ }
+ }
+ else if(sl->spacetype==SPACE_IMAGE) {
+ writestruct(wd, DATA, "SpaceImage", 1, sl);
+ }
+ else if(sl->spacetype==SPACE_IMASEL) {
+ writestruct(wd, DATA, "SpaceImaSel", 1, sl);
+ }
+ else if(sl->spacetype==SPACE_TEXT) {
+ writestruct(wd, DATA, "SpaceText", 1, sl);
+ }
+ else if(sl->spacetype==SPACE_ACTION) {
+ writestruct(wd, DATA, "SpaceAction", 1, sl);
+ }
+ else if(sl->spacetype==SPACE_SOUND) {
+ writestruct(wd, DATA, "SpaceSound", 1, sl);
+ }
+ else if(sl->spacetype==SPACE_NLA){
+ writestruct(wd, DATA, "SpaceNla", 1, sl);
+ }
+ sl= sl->next;
+ }
+
+ sa= sa->next;
+ }
+
+ sc= sc->id.next;
+ }
+}
+
+static void write_libraries(WriteData *wd, Main *main)
+{
+ ListBase *lbarray[30];
+ ID *id;
+ int a, tot, foundone;
+
+ while(main) {
+
+ a=tot= set_listbasepointers(main, lbarray);
+
+ /* test: wordt lib nog gebruikt */
+ foundone= 0;
+ while(tot--) {
+ id= lbarray[tot]->first;
+ while(id) {
+ if(id->us>0 && (id->flag & LIB_EXTERN)) {
+ foundone= 1;
+ break;
+ }
+ id= id->next;
+ }
+ if(foundone) break;
+ }
+
+ if(foundone) {
+ writestruct(wd, ID_LI, "Library", 1, main->curlib);
+
+ while(a--) {
+ id= lbarray[a]->first;
+ while(id) {
+ if(id->us>0 && (id->flag & LIB_EXTERN)) {
+
+ writestruct(wd, ID_ID, "ID", 1, id);
+ }
+ id= id->next;
+ }
+ }
+ }
+
+ main= main->next;
+ }
+}
+
+static void write_bone(WriteData *wd, Bone* bone)
+{
+ Bone* cbone;
+
+// write_constraints(wd, &bone->constraints);
+
+ // Write this bone
+ writestruct(wd, DATA, "Bone", 1, bone);
+
+ // Write Children
+ cbone= bone->childbase.first;
+ while(cbone) {
+ write_bone(wd, cbone);
+ cbone= cbone->next;
+ }
+}
+
+static void write_armatures(WriteData *wd, ListBase *idbase)
+{
+ bArmature *arm;
+ Bone *bone;
+
+ arm=idbase->first;
+ while (arm) {
+ if (arm->id.us>0) {
+ writestruct(wd, ID_AR, "bArmature", 1, arm);
+
+ /* Direct data */
+ bone= arm->bonebase.first;
+ while(bone) {
+ write_bone(wd, bone);
+ bone=bone->next;
+ }
+ }
+ arm=arm->id.next;
+ }
+}
+
+static void write_actions(WriteData *wd, ListBase *idbase)
+{
+ bAction *act;
+ bActionChannel *chan;
+ act=idbase->first;
+ while (act) {
+ if (act->id.us>0) {
+ writestruct(wd, ID_AC, "bAction", 1, act);
+
+ for (chan=act->chanbase.first; chan; chan=chan->next) {
+ writestruct(wd, DATA, "bActionChannel", 1, chan);
+ write_constraint_channels(wd, &chan->constraintChannels);
+ }
+ }
+ act=act->id.next;
+ }
+}
+
+static void write_texts(WriteData *wd, ListBase *idbase)
+{
+ Text *text;
+ TextLine *tmp;
+
+ text= idbase->first;
+ while(text) {
+ if ( (text->flags & TXT_ISMEM) && (text->flags & TXT_ISEXT)) text->flags &= ~TXT_ISEXT;
+
+ /* write LibData */
+ writestruct(wd, ID_TXT, "Text", 1, text);
+ if(text->name) writedata(wd, DATA, strlen(text->name)+1, text->name);
+
+ if(!(text->flags & TXT_ISEXT)) {
+ /* now write the text data, in two steps for optimization in the readfunction */
+ tmp= text->lines.first;
+ while (tmp) {
+ writestruct(wd, DATA, "TextLine", 1, tmp);
+ tmp= tmp->next;
+ }
+
+ tmp= text->lines.first;
+ while (tmp) {
+ writedata(wd, DATA, tmp->len+1, tmp->line);
+ tmp= tmp->next;
+ }
+ }
+ text= text->id.next;
+ }
+}
+
+static void write_sounds(WriteData *wd, ListBase *idbase)
+{
+ bSound *sound;
+ bSample *sample;
+
+ PackedFile * pf;
+
+ // set all samples to unsaved status
+
+ sample = samples->first;
+ while (sample) {
+ sample->flags |= SAMPLE_NEEDS_SAVE;
+ sample = sample->id.next;
+ }
+
+ sound= idbase->first;
+ while(sound) {
+ if(sound->id.us>0) {
+ // do we need to save the packedfile as well ?
+ sample = sound->sample;
+ if (sample) {
+ if (sample->flags & SAMPLE_NEEDS_SAVE) {
+ sound->newpackedfile = sample->packedfile;
+ sample->flags &= ~SAMPLE_NEEDS_SAVE;
+ } else {
+ sound->newpackedfile = NULL;
+ }
+ }
+
+ /* write LibData */
+ writestruct(wd, ID_SO, "bSound", 1, sound);
+
+ if (sound->newpackedfile) {
+ pf = sound->newpackedfile;
+ writestruct(wd, DATA, "PackedFile", 1, pf);
+ writedata(wd, DATA, pf->size, pf->data);
+ }
+
+ if (sample) {
+ sound->newpackedfile = sample->packedfile;
+ }
+ }
+ sound= sound->id.next;
+ }
+}
+
+static void write_groups(WriteData *wd, ListBase *idbase)
+{
+ Group *group;
+ GroupKey *gk;
+ GroupObject *go;
+ ObjectKey *ok;
+
+ group= idbase->first;
+ while(group) {
+ if(group->id.us>0) {
+ /* write LibData */
+ writestruct(wd, ID_GR, "Group", 1, group);
+
+ gk= group->gkey.first;
+ while(gk) {
+ writestruct(wd, DATA, "GroupKey", 1, gk);
+ gk= gk->next;
+ }
+
+ go= group->gobject.first;
+ while(go) {
+ writestruct(wd, DATA, "GroupObject", 1, go);
+ go= go->next;
+ }
+ go= group->gobject.first;
+ while(go) {
+ ok= go->okey.first;
+ while(ok) {
+ writestruct(wd, DATA, "ObjectKey", 1, ok);
+ ok= ok->next;
+ }
+ go= go->next;
+ }
+
+ }
+ group= group->id.next;
+ }
+}
+
+static void write_global(WriteData *wd)
+{
+ FileGlobal fg;
+
+ fg.curscreen= G.curscreen;
+ fg.displaymode= R.displaymode;
+ fg.winpos= R.winpos;
+ fg.fileflags= G.fileflags;
+
+ writestruct(wd, GLOB, "FileGlobal", 1, &fg);
+}
+
+static int write_file_handle(int handle, int write_user_block, int write_flags)
+{
+ ListBase mainlist;
+ char buf[13];
+ WriteData *wd;
+ int data;
+
+ mainlist.first= mainlist.last= G.main;
+ G.main->next= NULL;
+
+ blo_split_main(&mainlist);
+
+ wd= bgnwrite(handle, write_flags);
+
+ sprintf(buf, "BLENDER%c%c%.3d", (sizeof(void*)==8)?'-':'_', (G.order==B_ENDIAN)?'V':'v', G.version);
+ mywrite(wd, buf, 12);
+
+ write_renderinfo(wd);
+
+ write_screens (wd, &G.main->screen);
+ write_scenes (wd, &G.main->scene);
+ write_objects (wd, &G.main->object);
+ write_meshs (wd, &G.main->mesh);
+ write_curves (wd, &G.main->curve);
+ write_mballs (wd, &G.main->mball);
+ write_materials(wd, &G.main->mat);
+ write_textures (wd, &G.main->tex);
+ write_images (wd, &G.main->image);
+ write_cameras (wd, &G.main->camera);
+ write_lamps (wd, &G.main->lamp);
+ write_lattices (wd, &G.main->latt);
+ write_ikas (wd, &G.main->ika);
+ write_vfonts (wd, &G.main->vfont);
+ write_ipos (wd, &G.main->ipo);
+ write_keys (wd, &G.main->key);
+ write_worlds (wd, &G.main->world);
+ write_texts (wd, &G.main->text);
+ write_sounds (wd, &G.main->sound);
+ write_groups (wd, &G.main->group);
+ write_armatures(wd, &G.main->armature);
+ write_actions (wd, &G.main->action);
+ write_libraries(wd, G.main->next);
+
+ write_global(wd);
+ if (write_user_block) {
+ write_userdef(wd);
+ }
+
+ /* dna als laatste i.v.m. (nog te schrijven) test op welke gebruikt zijn */
+ writedata(wd, DNA1, wd->sdna->datalen, wd->sdna->data);
+
+ data= ENDB;
+ mywrite(wd, &data, 4);
+
+ data= 0;
+ mywrite(wd, &data, 4);
+
+ blo_join_main(&mainlist);
+ G.main= mainlist.first;
+
+ return endwrite(wd);
+}
+
+int BLO_write_file(char *dir, int write_flags, char **error_r)
+{
+ char userfilename[FILE_MAXDIR+FILE_MAXFILE];
+ char tempname[FILE_MAXDIR+FILE_MAXFILE];
+ int file, fout, write_user_block;
+
+ sprintf(tempname, "%s@", dir);
+
+ file = open(tempname,O_BINARY+O_WRONLY+O_CREAT+O_TRUNC, 0666);
+ if(file == -1) {
+ *error_r= "Unable to open";
+ return 0;
+ }
+
+ BLI_make_file_string(G.sce, userfilename, BLI_gethome(), ".B.blend");
+ write_user_block= BLI_streq(dir, userfilename);
+
+ fout= write_file_handle(file, write_user_block, write_flags);
+ close(file);
+
+ if(!fout) {
+ if(BLI_rename(tempname, dir) < 0) {
+ *error_r= "Can't change old file. File saved with @";
+ return 0;
+ }
+ } else {
+ remove(tempname);
+
+ *error_r= "Not enough diskspace";
+ return 0;
+ }
+
+ return 1;
+}
+
+ /* Runtime writing */
+
+#ifdef WIN32
+#define PATHSEPERATOR "\\"
+#else
+#define PATHSEPERATOR "/"
+#endif
+
+static char *get_install_dir(void) {
+ extern char bprogname[];
+ char *tmpname = BLI_strdup(bprogname);
+ char *cut;
+
+#ifdef __APPLE__
+ cut = strstr(tmpname, ".app");
+ if (cut) cut[0] = 0;
+#endif
+
+ cut = BLI_last_slash(tmpname);
+
+ if (cut) {
+ cut[0] = 0;
+ return tmpname;
+ } else {
+ MEM_freeN(tmpname);
+ return NULL;
+ }
+}
+
+static char *get_runtime_path(char *exename) {
+ char *installpath= get_install_dir();
+
+ if (!installpath) {
+ return NULL;
+ } else {
+ char *path= MEM_mallocN(strlen(installpath)+strlen(PATHSEPERATOR)+strlen(exename)+1, "runtimepath");
+ strcpy(path, installpath);
+ strcat(path, PATHSEPERATOR);
+ strcat(path, exename);
+
+ MEM_freeN(installpath);
+
+ return path;
+ }
+}
+
+#ifdef __APPLE__
+
+static int recursive_copy_runtime(char *outname, char *exename, char **cause_r) {
+ char *cause = NULL, *runtime = get_runtime_path(exename);
+ char command[2 * (FILE_MAXDIR+FILE_MAXFILE) + 32];
+ int progfd = -1;
+
+ if (!runtime) {
+ cause= "Unable to find runtime";
+ goto cleanup;
+ }
+
+ progfd= open(runtime, O_BINARY|O_RDONLY, 0);
+ if (progfd==-1) {
+ cause= "Unable to find runtime";
+ goto cleanup;
+ }
+
+ sprintf(command, "/bin/cp -R %s %s", runtime, outname);
+ if (system(command) == -1) {
+ cause = "Couldn't copy runtime";
+ }
+
+cleanup:
+ if (progfd!=-1)
+ close(progfd);
+ if (runtime)
+ MEM_freeN(runtime);
+
+ if (cause) {
+ *cause_r= cause;
+ return 0;
+ } else
+ return 1;
+}
+
+void BLO_write_runtime(char *file, char *exename) {
+ char gamename[FILE_MAXDIR+FILE_MAXFILE];
+ int outfd = -1;
+ char *cause= NULL;
+
+ // remove existing file / bundle
+ BLI_delete(file, NULL, TRUE);
+
+ if (!recursive_copy_runtime(file, exename, &cause))
+ goto cleanup;
+
+ strcpy(gamename, file);
+ strcat(gamename, "/Contents/Resources/game.blend");
+
+ outfd= open(gamename, O_BINARY|O_WRONLY|O_CREAT|O_TRUNC, 0777);
+ if (outfd != -1) {
+
+ /* Ensure runtime's are built with Publisher files */
+ write_file_handle(outfd, 0, G.fileflags|G_FILE_PUBLISH);
+
+ if (write(outfd, " ", 1) != 1) {
+ cause= "Unable to write to output file";
+ goto cleanup;
+ }
+ } else {
+ cause = "Unable to open blenderfile";
+ }
+
+cleanup:
+ if (outfd!=-1)
+ close(outfd);
+
+ if (cause)
+ error("Unable to make runtime: %s", cause);
+}
+
+#else !__APPLE__
+
+static int handle_append_runtime(int handle, char *exename, char **cause_r) {
+ char *cause= NULL, *runtime= get_runtime_path(exename);
+ unsigned char buf[1024];
+ int count, progfd= -1;
+
+ if (!runtime) {
+ cause= "Unable to find runtime";
+ goto cleanup;
+ }
+
+ progfd= open(runtime, O_BINARY|O_RDONLY, 0);
+ if (progfd==-1) {
+ cause= "Unable to find runtime";
+ goto cleanup;
+ }
+
+ while ((count= read(progfd, buf, sizeof(buf)))>0) {
+ if (write(handle, buf, count)!=count) {
+ cause= "Unable to write to output file";
+ goto cleanup;
+ }
+ }
+
+cleanup:
+ if (progfd!=-1)
+ close(progfd);
+ if (runtime)
+ MEM_freeN(runtime);
+
+ if (cause) {
+ *cause_r= cause;
+ return 0;
+ } else
+ return 1;
+}
+
+static int handle_write_msb_int(int handle, int i) {
+ unsigned char buf[4];
+ buf[0]= (i>>24)&0xFF;
+ buf[1]= (i>>16)&0xFF;
+ buf[2]= (i>>8)&0xFF;
+ buf[3]= (i>>0)&0xFF;
+
+ return (write(handle, buf, 4)==4);
+}
+
+void BLO_write_runtime(char *file, char *exename) {
+ int outfd= open(file, O_BINARY|O_WRONLY|O_CREAT|O_TRUNC, 0777);
+ char *cause= NULL;
+ int datastart;
+
+ if (!outfd) {
+ cause= "Unable to open output file";
+ goto cleanup;
+ }
+ if (!handle_append_runtime(outfd, exename, &cause))
+ goto cleanup;
+
+ datastart= lseek(outfd, 0, SEEK_CUR);
+
+ /* Ensure runtime's are built with Publisher files */
+ write_file_handle(outfd, 0, G.fileflags|G_FILE_PUBLISH);
+
+ if (!handle_write_msb_int(outfd, datastart) || (write(outfd, "BRUNTIME", 8)!=8)) {
+ cause= "Unable to write to output file";
+ goto cleanup;
+ }
+
+cleanup:
+ if (outfd!=-1)
+ close(outfd);
+
+ if (cause)
+ error("Unable to make runtime: %s", cause);
+}
+
+#endif // !__APPLE__
diff --git a/source/blender/blenpluginapi/Makefile b/source/blender/blenpluginapi/Makefile
new file mode 100644
index 00000000000..17c23c419a8
--- /dev/null
+++ b/source/blender/blenpluginapi/Makefile
@@ -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 *****
+#
+# Bounces make to subdirectories.
+
+SOURCEDIR = source/blender/blenpluginapi
+DIRS = intern
+
+include nan_subdirs.mk
diff --git a/source/blender/blenpluginapi/documentation.h b/source/blender/blenpluginapi/documentation.h
new file mode 100644
index 00000000000..3a3a199b8c6
--- /dev/null
+++ b/source/blender/blenpluginapi/documentation.h
@@ -0,0 +1,71 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * @mainpage plugin API - the access point for texture and sequence
+ * plugins
+ *
+ * @section about About the plugin API
+ *
+ * This API wraps functions that are used by texture and sequence
+ * plugins. They are explicitly wrapped in order to make the
+ * dependencies to the rest of the system clear.
+ *
+ * @section issues Known issues with the plugin API
+ *
+ * - It can be difficult at times to get access to the API functions
+ * linked into the final executable. On gcc, the -fpic and -shared
+ * flags take care of this. On Irix, -shared is needed, but you also
+ * need a reference to the function to get the handle. This has
+ * momentarily been taken care of by pluginapi_force_ref().
+ *
+ * - Plugins need to define three functions that are needed for
+ * version bookkeeping and information. The plugin loading code
+ * explicitly checks for these functions. The nanes depend on whether
+ * it is a texture or sequence plugin.
+ *
+ * - The plugin loading occurs in sequence.c and texture.c. The
+ * following functions are involved:
+ * - open_plugin_seq() (used in readfile.c, editseq.c, sequence.c)
+ * - add_plugin_seq() (used in editseq.c, sequence.c)
+ * - free_plugin_seq() (used in editseq.c, sequence.c)
+ * - open_plugin_tex() (used in texture.c, readfile.c)
+ * - add_plugin_tex() (used in texture.c, buttons.c)
+ * - free_plugin_tex() (used in texture.c, buttons.c)
+ * - test_dlerr() (used in texture.c, sequence.c)
+ * Since the plugins are about to phase out, we will not sanitize this
+ * code. It will be removed as soon as the replacing system is in
+ * place.
+ *
+ * @section dependencies Dependencies
+ *
+ * The plugins wraps functions from IMB and BLI. In addition, they
+ * define some useful variables.
+ * */
diff --git a/source/blender/blenpluginapi/floatpatch.h b/source/blender/blenpluginapi/floatpatch.h
new file mode 100644
index 00000000000..d33ab7629e1
--- /dev/null
+++ b/source/blender/blenpluginapi/floatpatch.h
@@ -0,0 +1,90 @@
+/* Copyright (c) 1999, Not a Number / NeoGeo b.v.
+ * $Id$
+ *
+ * All rights reserved.
+ *
+ * Contact: blender@blender.nl
+ * Information: http://www.blender.nl
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef FLOATPATCH_H
+#define FLOATPATCH_H
+
+/* floating point libs differ at systems... with these defines it comilies at all! */
+
+#ifdef MIPS1
+#else
+
+#define fabsf(a) fabs((double)(a))
+
+#define facos acosf
+#define acosf(a) acos((double)(a))
+
+#define fasin asinf
+#define asinf(a) asin((double)(a))
+
+#define fatan atanf
+#define atanf(a) atan((double)(a))
+
+#define fatan2 atan2f
+#define atan2f(a, b) atan2((double)(a), (double)(b))
+
+#define fmodf(a, b) fmod((double)(a), (double)(b))
+
+#define fcos cosf
+#define cosf(a) cos((double)(a))
+
+#define fsin sinf
+#define sinf(a) sin((double)(a))
+
+#define ftan tanf
+#define tanf(a) tan((double)(a))
+
+#define fexp expf
+#define expf(a) exp((double)(a))
+
+#define flog logf
+#define logf(a) log((double)(a))
+
+#define flog10 log10f
+#define log10f(a) log10((double)(a))
+
+#define fsqrt sqrtf
+#define sqrtf(a) sqrt((double)(a))
+
+#define fceil ceilf
+#define ceilf(a) ceil((double)(a))
+
+#define ffloor floorf
+#define floorf(a) floor((double)(a))
+
+#define fpow powf
+#define powf(a, b) pow((double)(a), (double)(b))
+
+/* #endif */
+
+#endif
+
+#endif /* FLOATPATCH_H */
+
diff --git a/source/blender/blenpluginapi/iff.h b/source/blender/blenpluginapi/iff.h
new file mode 100644
index 00000000000..8e9d79c62b1
--- /dev/null
+++ b/source/blender/blenpluginapi/iff.h
@@ -0,0 +1,185 @@
+/* Copyright (c) 1999, Not a Number / NeoGeo b.v.
+ * $Id$
+ *
+ * All rights reserved.
+ *
+ * Contact: blender@blender.nl
+ * Information: http://www.blender.nl
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef IFF_H
+#define IFF_H
+
+#include <sys/types.h>
+#include "util.h"
+
+#define IB_rect (1 << 0)
+#define IB_planes (1 << 1)
+#define IB_cmap (1 << 2)
+#define IB_test (1 << 7)
+
+#define IB_fields (1 << 11)
+#define IB_yuv (1 << 12)
+#define IB_zbuf (1 << 13)
+#define IB_rgba (1 << 14)
+
+#define AMI (1 << 31)
+#define Anim (1 << 29)
+#define TGA (1 << 28)
+#define JPG (1 << 27)
+
+#define RAWTGA (TGA | 1)
+
+#define JPG_STD (JPG | (0 << 8))
+#define JPG_VID (JPG | (1 << 8))
+#define JPG_JST (JPG | (2 << 8))
+#define JPG_MAX (JPG | (3 << 8))
+#define JPG_MSK (0xffffff00)
+
+#define AM_ham (0x0800 | AMI)
+#define AM_hbrite (0x0080 | AMI)
+#define AM_lace (0x0004 | AMI)
+#define AM_hires (0x8000 | AMI)
+#define AM_hblace (AM_hbrite | AM_lace)
+#define AM_hilace (AM_hires | AM_lace)
+#define AM_hamlace (AM_ham | AM_lace)
+
+#define RGB888 1
+#define RGB555 2
+#define DYUV 3
+#define CLUT8 4
+#define CLUT7 5
+#define CLUT4 6
+#define CLUT3 7
+#define RL7 8
+#define RL3 9
+#define MPLTE 10
+
+#define DYUV1 0
+#define C233 1
+#define YUVX 2
+#define HAMX 3
+#define TANX 4
+
+#define AN_c233 (Anim | C233)
+#define AN_yuvx (Anim | YUVX)
+#define AN_hamx (Anim | HAMX)
+#define AN_tanx (Anim | TANX)
+
+#define IS_amiga(x) (x->ftype & AMI)
+#define IS_ham(x) ((x->ftype & AM_ham) == AM_ham)
+#define IS_hbrite(x) ((x->ftype & AM_hbrite) == AM_hbrite)
+#define IS_lace(x) ((x->ftype & AM_lace) == AM_lace)
+#define IS_hires(x) ((x->ftype & AM_hires) == AM_hires)
+#define IS_hblace(x) ((x->ftype & AM_hblace) == AM_hblace)
+#define IS_hilace(x) ((x->ftype & AM_hilace) == AM_hilace)
+#define IS_hamlace(x) ((x->ftype & AM_hamlace) == AM_hamlace)
+
+#define IS_anim(x) (x->ftype & Anim)
+#define IS_hamx(x) (x->ftype == AN_hamx)
+
+#define IS_tga(x) (x->ftype & TGA)
+#define IS_tim(x) (x->ftype & TIM)
+
+#define IMAGIC 0732
+#define IS_iris(x) (x->ftype == IMAGIC)
+
+#define IS_jpg(x) (x->ftype & JPG)
+#define IS_stdjpg(x) ((x->ftype & JPG_MSK) == JPG_STD)
+#define IS_vidjpg(x) ((x->ftype & JPG_MSK) == JPG_VID)
+#define IS_jstjpg(x) ((x->ftype & JPG_MSK) == JPG_JST)
+#define IS_maxjpg(x) ((x->ftype & JPG_MSK) == JPG_MAX)
+
+#define AN_INIT an_stringdec = stringdec; an_stringenc = stringenc;
+
+typedef struct ImBuf{
+ short x,y; /* breedte in pixels, hoogte in scanlines */
+ short skipx; /* breedte in ints om bij volgende scanline te komen */
+ uchar depth; /* actieve aantal bits/bitplanes */
+ uchar cbits; /* aantal active bits in cmap */
+ ushort mincol;
+ ushort maxcol;
+ int type; /* 0=abgr, 1=bitplanes */
+ int ftype;
+ uint *cmap; /* int array van kleuren */
+ uint *rect; /* databuffer */
+ uint **planes; /* bitplanes */
+ uchar *chardata; /* voor cdi-compressie */
+ int flags;
+ int mall; /* wat is er intern gemalloced en mag weer vrijgegeven worden */
+ short xorig, yorig;
+ char name[127];
+ char namenull;
+ int userflags;
+ int *zbuf;
+ void *userdata;
+} ImBuf;
+
+extern struct ImBuf *allocImBuf(short,short,uchar,uint,uchar);
+extern struct ImBuf *dupImBuf(struct ImBuf *);
+extern void freeImBuf(struct ImBuf*);
+
+extern short converttocmap(struct ImBuf* ibuf);
+
+extern short saveiff(struct ImBuf *,char *,int);
+
+extern struct ImBuf *loadiffmem(int *,int);
+extern struct ImBuf *loadifffile(int,int);
+extern struct ImBuf *loadiffname(char *,int);
+extern struct ImBuf *testiffname(char *,int);
+
+extern struct ImBuf *onehalf(struct ImBuf *);
+extern struct ImBuf *onethird(struct ImBuf *);
+extern struct ImBuf *halflace(struct ImBuf *);
+extern struct ImBuf *half_x(struct ImBuf *);
+extern struct ImBuf *half_y(struct ImBuf *);
+extern struct ImBuf *double_x(struct ImBuf *);
+extern struct ImBuf *double_y(struct ImBuf *);
+extern struct ImBuf *double_fast_x(struct ImBuf *);
+extern struct ImBuf *double_fast_y(struct ImBuf *);
+
+extern int ispic(char *);
+
+extern void dit2(struct ImBuf *, short, short);
+extern void dit0(struct ImBuf *, short, short);
+
+extern struct ImBuf *scaleImBuf(struct ImBuf *, short, short);
+extern struct ImBuf *scalefastImBuf(struct ImBuf *, short, short);
+extern struct ImBuf *scalefieldImBuf(struct ImBuf *, short, short);
+extern struct ImBuf *scalefastfieldImBuf(struct ImBuf *, short, short);
+
+extern void de_interlace(struct ImBuf *ib);
+
+extern void rectop(struct ImBuf *dbuf,
+ struct ImBuf *sbuf,
+ int destx,
+ int desty,
+ int srcx,
+ int srcy,
+ int width,
+ int height,
+ void (*operation)(unsigned int *, unsigned int*, int, int),
+ int value);
+
+#endif /* IFF_H */
diff --git a/source/blender/blenpluginapi/intern/Makefile b/source/blender/blenpluginapi/intern/Makefile
new file mode 100644
index 00000000000..e5cbf4d1cfc
--- /dev/null
+++ b/source/blender/blenpluginapi/intern/Makefile
@@ -0,0 +1,62 @@
+#
+# $Id$
+#
+# ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version. The Blender
+# Foundation also sells licenses for use in proprietary software under
+# the Blender License. See http://www.blender.org/BL/ for information
+# about this.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2001-2002 by 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 = blenpluginapi
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+ifeq ($(OS),$(findstring $(OS), "beos darwin freebsd linux openbsd solaris windows"))
+ CFLAGS += -funsigned-char
+endif
+
+ifeq ($(OS),$(findstring $(OS), "beos darwin freebsd linux openbsd solaris"))
+ CFLAGS += -shared
+endif
+
+CPPFLAGS += $(LEVEL_2_C_WARNINGS)
+
+# path to our own external headerfiles. On win2k this needs to be
+# longer, to avoid the util.h include problem
+CPPFLAGS += -I..
+ifeq ($(OS),windows)
+ CPPFLAGS += -I../..
+endif
+# also do dna
+CPPFLAGS += -I../../makesdna
+# path to blenlib
+CPPFLAGS += -I../../blenlib
+# path to imbuf
+CPPFLAGS += -I../../imbuf
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+
diff --git a/source/blender/blenpluginapi/intern/pluginapi.c b/source/blender/blenpluginapi/intern/pluginapi.c
new file mode 100644
index 00000000000..e4e4058707f
--- /dev/null
+++ b/source/blender/blenpluginapi/intern/pluginapi.c
@@ -0,0 +1,341 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * Wrappers for the plugin api. This api is up for removal.
+ */
+
+/* There are four headers making up the plugin api:
+ * - floatpatch.h : Wraps math functions for mips platforms, no code
+ * required.
+ * - iff.h : Defines, macros and functions for dealing
+ * with image buffer things.
+ * - plugin.h : Wraps some plugin handling types, accesses noise
+ * functions.
+ * - util.h : Useful defines, memory management.
+ */
+
+#ifdef WIN32
+#include "blenpluginapi\util.h"
+#else
+#include "util.h"
+#endif
+#include "iff.h"
+#include "plugin.h"
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h" /* util and noise functions */
+#include "IMB_imbuf.h" /* image buffer stuff */
+
+/* -------------------------------------------------------------------------- */
+/* stuff from util.h */
+/* -------------------------------------------------------------------------- */
+
+void *mallocN(int len, char *str)
+{
+ return MEM_mallocN(len, str);
+}
+
+void *callocN(int len, char *str)
+{
+ return MEM_callocN(len, str);
+}
+
+short freeN(void *vmemh)
+{
+ return MEM_freeN(vmemh);
+}
+
+/* -------------------------------------------------------------------------- */
+/* stuff from iff.h */
+/* -------------------------------------------------------------------------- */
+
+struct ImBuf *allocImBuf(short x,
+ short y,
+ uchar d,
+ uint flags,
+ uchar bitmap)
+{
+ return IMB_allocImBuf(x, y, d, flags, bitmap);
+}
+
+
+struct ImBuf *dupImBuf(struct ImBuf *ib)
+{
+ return IMB_dupImBuf(ib);
+}
+
+void freeImBuf(struct ImBuf* ib)
+{
+ IMB_freeImBuf(ib);
+}
+
+short converttocmap(struct ImBuf* ibuf)
+{
+ return IMB_converttocmap(ibuf);
+}
+
+short saveiff(struct ImBuf *ib,
+ char *c,
+ int i)
+{
+ return IMB_saveiff(ib, c, i);
+}
+
+struct ImBuf *loadiffmem(int *mem,int flags)
+{
+ return IMB_loadiffmem(mem, flags);
+}
+
+struct ImBuf *loadifffile(int a,
+ int b)
+{
+ return IMB_loadifffile(a, b);
+}
+
+struct ImBuf *loadiffname(char *n,
+ int flags)
+{
+ return IMB_loadiffname(n, flags);
+}
+
+struct ImBuf *testiffname(char *n,
+ int flags)
+{
+ return IMB_testiffname(n, flags);
+}
+
+struct ImBuf *onehalf(struct ImBuf *ib)
+{
+ return IMB_onehalf(ib);
+}
+
+struct ImBuf *onethird(struct ImBuf *ib)
+{
+ return IMB_onethird(ib);
+}
+
+struct ImBuf *halflace(struct ImBuf *ib)
+{
+ return IMB_halflace(ib);
+}
+
+struct ImBuf *half_x(struct ImBuf *ib)
+{
+ return IMB_half_x(ib);
+}
+
+struct ImBuf *half_y(struct ImBuf *ib)
+{
+ return IMB_half_y(ib);
+}
+
+struct ImBuf *double_x(struct ImBuf *ib)
+{
+ return IMB_double_x(ib);
+}
+
+struct ImBuf *double_y(struct ImBuf *ib)
+{
+ return IMB_double_y(ib);
+}
+
+struct ImBuf *double_fast_x(struct ImBuf *ib)
+{
+ return IMB_double_fast_x(ib);
+}
+
+struct ImBuf *double_fast_y(struct ImBuf *ib)
+{
+ return IMB_double_fast_y(ib);
+}
+
+int ispic(char * name)
+{
+ return IMB_ispic(name);
+}
+
+void dit2(struct ImBuf *ib,
+ short a,
+ short b)
+{
+ IMB_dit2(ib, a, b);
+}
+
+void dit0(struct ImBuf *ib,
+ short a,
+ short b)
+{
+ IMB_dit0(ib, a, b);
+}
+
+/* still the same name */
+/* void (*ditherfunc)(struct ImBuf *, short, short){} */
+
+struct ImBuf *scaleImBuf(struct ImBuf *ib,
+ short nx,
+ short ny)
+{
+ return IMB_scaleImBuf(ib, nx, ny);
+}
+
+struct ImBuf *scalefastImBuf(struct ImBuf *ib,
+ short x,
+ short y)
+{
+ return IMB_scalefastImBuf(ib, x, y);
+}
+
+
+struct ImBuf *scalefieldImBuf(struct ImBuf *ib,
+ short x,
+ short y)
+{
+ return IMB_scalefieldImBuf(ib, x, y);
+}
+
+struct ImBuf *scalefastfieldImBuf(struct ImBuf *ib,
+ short x,
+ short y)
+{
+ return IMB_scalefastfieldImBuf(ib, x, y);
+}
+
+ /* Extra ones that some NaN (read Ton) plugins use,
+ * even though they aren't in the header
+ */
+
+void de_interlace(struct ImBuf *ib)
+{
+ IMB_de_interlace(ib);
+}
+
+void rectop(struct ImBuf *dbuf,
+ struct ImBuf *sbuf,
+ int destx,
+ int desty,
+ int srcx,
+ int srcy,
+ int width,
+ int height,
+ void (*operation)(unsigned int *, unsigned int*, int, int),
+ int value)
+{
+ IMB_rectop(dbuf, sbuf, destx, desty, srcx, srcy, width, height, operation, value);
+}
+
+/* -------------------------------------------------------------------------- */
+/* stuff from plugin.h */
+/* -------------------------------------------------------------------------- */
+
+/* These three need to be defined in the plugion itself. The plugin
+ * loader looks for these functions to check whether it can use the
+ * plugin. For sequences, something similar exists. */
+/* int plugin_tex_getversion(void); */
+/* int plugin_seq_getversion(void); */
+/* void plugin_getinfo(PluginInfo *); */
+
+float hnoise(float noisesize,
+ float x,
+ float y,
+ float z)
+{
+ return BLI_hnoise(noisesize, x, y, z);
+}
+
+float hnoisep(float noisesize,
+ float x,
+ float y,
+ float z)
+{
+ return BLI_hnoisep(noisesize, x, y, z);
+}
+
+float turbulence(float noisesize,
+ float x,
+ float y,
+ float z,
+ int depth)
+{
+ return BLI_turbulence(noisesize, x, y, z, depth);
+}
+
+float turbulence1(float noisesize,
+ float x,
+ float y,
+ float z,
+ int depth)
+{
+ return BLI_turbulence1(noisesize, x, y, z, depth);
+}
+
+/* -------------------------------------------------------------------------- */
+
+ /* Stupid hack - force the inclusion of all of the
+ * above functions in the binary by 'using' each one...
+ * Otherwise they will not be imported from the archive
+ * library on Unix. -zr
+ */
+int pluginapi_force_ref(void)
+{
+ return (int) mallocN +
+ (int) callocN +
+ (int) freeN +
+ (int) allocImBuf +
+ (int) dupImBuf +
+ (int) freeImBuf +
+ (int) converttocmap +
+ (int) saveiff +
+ (int) loadiffmem +
+ (int) loadifffile +
+ (int) loadiffname +
+ (int) testiffname +
+ (int) onehalf +
+ (int) onethird +
+ (int) halflace +
+ (int) half_x +
+ (int) half_y +
+ (int) double_x +
+ (int) double_y +
+ (int) double_fast_x +
+ (int) double_fast_y +
+ (int) ispic +
+ (int) dit2 +
+ (int) dit0 +
+ (int) scaleImBuf +
+ (int) scalefastImBuf +
+ (int) scalefieldImBuf +
+ (int) scalefastfieldImBuf +
+ (int) hnoise +
+ (int) hnoisep +
+ (int) turbulence +
+ (int) turbulence1 +
+ (int) de_interlace +
+ (int) rectop;
+}
diff --git a/source/blender/blenpluginapi/plugin.h b/source/blender/blenpluginapi/plugin.h
new file mode 100644
index 00000000000..f62f60a0c6a
--- /dev/null
+++ b/source/blender/blenpluginapi/plugin.h
@@ -0,0 +1,93 @@
+/* Copyright (c) 1999, Not a Number / NeoGeo b.v.
+ * $Id$
+ *
+ * All rights reserved.
+ *
+ * Contact: blender@blender.nl
+ * Information: http://www.blender.nl
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef PLUGIN_H
+#define PLUGIN_H
+
+#include "iff.h"
+#include "util.h"
+#include "floatpatch.h"
+
+#define B_PLUGIN_VERSION 3
+
+typedef int (*TexDoit)(int, void*, float*, float*, float*);
+typedef void (*SeqDoit)(void*, float, float, int, int, ImBuf*, ImBuf*, ImBuf*, ImBuf*);
+
+typedef struct VarStruct {
+ int type;
+ char name[16];
+ float def, min, max;
+ char tip[80];
+} VarStruct;
+
+typedef struct _PluginInfo {
+ char *name;
+ char *snames;
+
+ int stypes;
+ int nvars;
+ VarStruct *varstr;
+ float *result;
+ float *cfra;
+
+ void (*init)(void);
+ void (*callback)(int);
+ TexDoit tex_doit;
+ SeqDoit seq_doit;
+} PluginInfo;
+
+int plugin_tex_getversion(void);
+int plugin_seq_getversion(void);
+void plugin_getinfo(PluginInfo *);
+
+/* *************** defines for button types ************** */
+
+#define INT 96
+#define FLO 128
+
+#define TOG (3<<9)
+#define NUM (5<<9)
+#define LABEL (10<<9)
+#define NUMSLI (14<<9)
+
+
+/* *************** API functions ******************** */
+
+ /* derived from the famous Perlin noise */
+extern float hnoise(float noisesize, float x, float y, float z);
+ /* the original Perlin noise */
+extern float hnoisep(float noisesize, float x, float y, float z);
+
+ /* soft turbulence */
+extern float turbulence(float noisesize, float x, float y, float z, int depth);
+ /* hard turbulence */
+extern float turbulence1(float noisesize, float x, float y, float z, int depth);
+
+#endif /* PLUGIN_H */
diff --git a/source/blender/blenpluginapi/util.h b/source/blender/blenpluginapi/util.h
new file mode 100644
index 00000000000..719614be4ae
--- /dev/null
+++ b/source/blender/blenpluginapi/util.h
@@ -0,0 +1,94 @@
+/* Copyright (c) 1999, Not a Number / NeoGeo b.v.
+ * $Id$
+ *
+ * All rights reserved.
+ *
+ * Contact: blender@blender.nl
+ * Information: http://www.blender.nl
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef UTIL_H
+#define UTIL_H
+
+#include <sys/types.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef ulong
+#define ulong unsigned long
+#endif
+
+#ifndef ushort
+#define ushort unsigned short
+#endif
+
+#ifndef uchar
+#define uchar unsigned char
+#endif
+
+#ifndef uint
+#define uint unsigned int
+#endif
+
+#define MIN2(x,y) ( (x)<(y) ? (x) : (y) )
+#define MIN3(x,y,z) MIN2( MIN2((x),(y)) , (z) )
+#define MIN4(x,y,z,a) MIN2( MIN2((x),(y)) , MIN2((z),(a)) )
+
+#define MAX2(x,y) ( (x)>(y) ? (x) : (y) )
+#define MAX3(x,y,z) MAX2( MAX2((x),(y)) , (z) )
+#define MAX4(x,y,z,a) MAX2( MAX2((x),(y)) , MAX2((z),(a)) )
+
+#define SWAP(type, a, b) { type sw_ap; sw_ap=(a); (a)=(b); (b)=sw_ap; }
+
+#define ABS(x) ((x) < 0 ? -(x) : (x))
+#define FLOOR(x) ((int)(x) - ((x) < 0 && (x) != (int)(x)))
+#define CEIL(x) ((int)(x) + ((x) > 0 && (x) != (int)(x)))
+#define STEP(a,b) ((a)>(b)) (1) : (0))
+#define CLAMP(val, low, high) ((val>high)?high:((val<low)?low:val))
+#define LERP(t,x0,x1) ((x0) + (t)*((x1)-(x0)))
+#define PULSE(a,b,x) (STEP((a),(x)) - STEP((b),(x)))
+#define BOXSTEP(a,b,x) CLAMP(((x)-(a))/((b)-(a)),0,1)
+
+#define PRINT(d, var1) printf(# var1 ":%" # d "\n", var1)
+#define PRINT2(d, e, var1, var2) printf(# var1 ":%" # d " " # var2 ":%" # e "\n", var1, var2)
+#define PRINT3(d, e, f, var1, var2, var3) printf(# var1 ":%" # d " " # var2 ":%" # e " " # var3 ":%" # f "\n", var1, var2, var3)
+#define PRINT4(d, e, f, g, var1, var2, var3, var4) printf(# var1 ":%" # d " " # var2 ":%" # e " " # var3 ":%" # f " " # var4 ":%" # g "\n", var1, var2, var3, var4)
+
+extern void *mallocN(int len, char *str);
+extern void *callocN(int len, char *str);
+extern short freeN(void *vmemh);
+
+#endif /* UTIL_H */
diff --git a/source/blender/bpython/Makefile b/source/blender/bpython/Makefile
new file mode 100644
index 00000000000..ef58948bd88
--- /dev/null
+++ b/source/blender/bpython/Makefile
@@ -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 *****
+#
+# Bounces make to subdirectories.
+
+SOURCEDIR = source/blender/bpython
+DIRS = intern
+
+include nan_subdirs.mk
diff --git a/source/blender/bpython/include/BPY_extern.h b/source/blender/bpython/include/BPY_extern.h
new file mode 100644
index 00000000000..8aa9a2502fc
--- /dev/null
+++ b/source/blender/bpython/include/BPY_extern.h
@@ -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 *****
+ */
+struct Text;
+struct ID;
+struct ScriptLink;
+struct ListBase;
+struct SpaceText;
+struct _object; // forward declaration for PyObject !
+
+
+void BPY_start_python(void);
+void BPY_end_python(void);
+int BPY_Err_getLinenumber(void);
+const char *BPY_Err_getFilename(void);
+void BPY_Err_Handle(struct Text *text);
+struct _object *BPY_txt_do_python(struct SpaceText* st);
+void BPY_free_compiled_text(struct Text* text);
+void BPY_clear_bad_scriptlink(struct ID *id, struct Text *byebye);
+void BPY_clear_bad_scriptlinks(struct Text *byebye);
+void BPY_clear_bad_scriptlist(struct ListBase *, struct Text *byebye);
+void BPY_do_all_scripts(short event);
+void BPY_do_pyscript(struct ID *id, short event);
+void BPY_free_scriptlink(struct ScriptLink *slink);
+void BPY_copy_scriptlink(struct ScriptLink *scriptlink);
+
+/* format importer hook */
+int BPY_call_importloader(char *name);
+
+int BPY_spacetext_is_pywin(struct SpaceText *st);
+void BPY_spacetext_do_pywin_draw(struct SpaceText *st);
+void BPY_spacetext_do_pywin_event(struct SpaceText *st, unsigned short event, short val);
diff --git a/source/blender/bpython/include/BPY_objtypes.h b/source/blender/bpython/include/BPY_objtypes.h
new file mode 100644
index 00000000000..91cdc5ceb96
--- /dev/null
+++ b/source/blender/bpython/include/BPY_objtypes.h
@@ -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 *****
+ */
+#include "DNA_ID.h"
+#include "DNA_listBase.h"
+#include "DNA_mesh_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_material_types.h"
+#include "DNA_object_types.h"
+
diff --git a/source/blender/bpython/intern/BPY_constobject.c b/source/blender/bpython/intern/BPY_constobject.c
new file mode 100644
index 00000000000..9f1a6b4cc3b
--- /dev/null
+++ b/source/blender/bpython/intern/BPY_constobject.c
@@ -0,0 +1,183 @@
+/*
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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$
+
+This is code to emulate a readonly Dictionary/Class object
+for storage of Constants
+
+Inserting readonly values:
+
+PyObject *constants = ConstObject_New();
+insertConst(constants, "item", PyInt_FromInt(CONSTANT));
+...
+
+
+Constant values are accessed in python by either:
+
+c = module.Const.CONSTANT
+
+ or
+
+c = module.Const['CONSTANT']
+
+*/
+
+#include "Python.h"
+#include "BPY_macros.h"
+
+#include "BPY_constobject.h"
+
+#define Const_Check(v) ((v)->ob_type == &Const_Type)
+
+
+/* ----------------------------------------------------- */
+/* Declarations for objects of type const */
+
+
+PyTypeObject Const_Type;
+
+/* PROTOS */
+
+
+
+static constobject *
+newconstobject()
+{
+ constobject *self;
+ Const_Type.ob_type = &PyType_Type;
+ self = PyObject_NEW(constobject, &Const_Type);
+ if (self == NULL)
+ return NULL;
+ self->dict = PyDict_New();
+ return self;
+}
+
+char ConstObject_doc[] = "Readonly dictionary type\n\n\
+This is used as a container for constants, which can be accessed by two ways:\n\
+\n\
+ c = <ConstObject>.<attribute>\n\
+\n\
+or\n\
+ c = <ConstObject>['<attribute>']";
+
+PyObject *ConstObject_New(void)
+{
+ return (PyObject *) newconstobject();
+}
+
+PyObject *const_repr(constobject *self)
+{
+ PyObject *repr;
+ repr = PyObject_Repr(self->dict);
+ return repr;
+}
+
+static void const_dealloc(PyObject *self) {
+ Py_DECREF(((constobject *)self)->dict);
+ PyMem_DEL(self);
+}
+static PyObject *
+const_getattr(constobject *self, char *name)
+{
+ PyObject *item;
+ if (STREQ(name, "__doc__")) {
+ return PyString_FromString(ConstObject_doc);
+ }
+ if (STREQ(name, "__members__")) {
+ return PyDict_Keys(self->dict);
+ }
+ item = PyDict_GetItemString(self->dict, name); /* borrowed ref ! */
+ if (item)
+ Py_INCREF(item);
+ if (!item) {
+ PyErr_SetString(PyExc_AttributeError, name);
+ }
+ return item;
+}
+
+/* inserts a constant with name into the dictionary self */
+void insertConst(PyObject *self, char *name, PyObject *cnst)
+{
+ PyDict_SetItemString(((constobject *)self)->dict, name, cnst);
+}
+
+
+/* Code to access const objects as mappings */
+
+static int
+const_length(constobject *self)
+{
+ return 0;
+}
+
+static PyObject *
+const_subscript(constobject *self, PyObject *key)
+{
+ PyObject *item;
+ item = PyDict_GetItem(self->dict, key);
+ if (item)
+ Py_INCREF(item);
+ return item;
+}
+
+static int
+const_ass_sub(constobject *self, PyObject *v, PyObject *w)
+{
+ /* no write access */
+ return 0;
+}
+
+static PyMappingMethods const_as_mapping = {
+ (inquiry)const_length, /*mp_length*/
+ (binaryfunc)const_subscript, /*mp_subscript*/
+ (objobjargproc)const_ass_sub, /*mp_ass_subscript*/
+};
+
+/* -------------------------------------------------------- */
+
+PyTypeObject Const_Type = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "const", /*tp_name*/
+ sizeof(constobject), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ (destructor) const_dealloc, /*tp_dealloc*/
+ (printfunc) 0, /*tp_print*/
+ (getattrfunc) const_getattr, /*tp_getattr*/
+ (setattrfunc) 0, /*tp_setattr*/
+ (cmpfunc) 0, /*tp_compare*/
+ (reprfunc) const_repr, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ &const_as_mapping, /*tp_as_mapping*/
+ 0, /*tp_hash*/
+};
+
diff --git a/source/blender/bpython/intern/BPY_constobject.h b/source/blender/bpython/intern/BPY_constobject.h
new file mode 100644
index 00000000000..b75ba202765
--- /dev/null
+++ b/source/blender/bpython/intern/BPY_constobject.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 struct {
+ PyObject_HEAD
+ PyObject *dict;
+
+} constobject;
+
+PyObject *ConstObject_New(void);
+void insertConst(PyObject *self, char *name, PyObject *cnst);
+
diff --git a/source/blender/bpython/intern/BPY_csg.c b/source/blender/bpython/intern/BPY_csg.c
new file mode 100644
index 00000000000..7237a843428
--- /dev/null
+++ b/source/blender/bpython/intern/BPY_csg.c
@@ -0,0 +1,239 @@
+
+/** CSG wrapper module
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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$
+ */
+
+// TODO
+
+
+#include "Python.h"
+
+#include "BPY_csg.h"
+
+#include "BKE_booleanops_mesh.h"
+#include "BKE_booleanops.h"
+#include "MEM_guardedalloc.h"
+
+#include "b_interface.h"
+
+#ifdef DEBUG
+ #define CSG_DEBUG(str) \
+ { printf str; }
+#else
+ #define CSG_DEBUG(str) \
+ {}
+#endif
+
+
+///////////////////////////////////////////////////////////////
+// CSG python object struct
+
+
+typedef struct _CSGMesh {
+ PyObject_VAR_HEAD
+ CSG_MeshDescriptor *imesh;
+} PyCSGMesh;
+
+// PROTOS
+
+static PyObject *newPyCSGMesh(CSG_MeshDescriptor *imesh);
+
+static void CSGMesh_dealloc(PyObject *self);
+static PyObject *CSGMesh_getattr(PyObject *self, char *attr);
+
+
+static char CSGMesh_Type_doc[] = "CSG mesh type";
+
+static PyTypeObject PyCSGMesh_Type = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "CSGMesh", /*tp_name*/
+ sizeof(PyCSGMesh), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ (destructor) CSGMesh_dealloc, /*tp_dealloc*/
+ (printfunc)0, /*tp_print*/
+ (getattrfunc)CSGMesh_getattr, /*tp_getattr*/
+ (setattrfunc)0, /*tp_setattr*/
+ (cmpfunc)0, /*tp_compare*/
+ (reprfunc)0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ (hashfunc)0, /*tp_hash*/
+ (ternaryfunc)0, /*tp_call*/
+ (reprfunc)0, /*tp_str*/
+
+ /* Space for future expansion */
+ 0L,0L,0L,0L,
+ CSGMesh_Type_doc /* Documentation string */
+};
+
+///////////////////////////////////////////////////////////////
+// CSG object methods
+
+
+static PyObject *CSGMesh_add(PyObject *self, PyObject *args)
+{
+ CSG_MeshDescriptor *new_imesh =
+ (CSG_MeshDescriptor *) MEM_mallocN(sizeof(CSG_MeshDescriptor),
+ "CSG_IMesh");
+
+ PyCSGMesh *c2;
+ int success = 0;
+
+ PyCSGMesh *c1 = (PyCSGMesh *) self;
+ if (!PyArg_ParseTuple(args, "O!", &PyCSGMesh_Type, &c2)) return NULL;
+
+ success = CSG_PerformOp(c1->imesh, c2->imesh, 2, new_imesh);
+
+ if (!success) {
+ PyErr_SetString(PyExc_RuntimeError, "Sorry. Didn't work");
+ return NULL; // exception
+ }
+ return newPyCSGMesh(new_imesh);
+}
+
+
+static PyMethodDef CSGMesh_methods[] = {
+ {"union", CSGMesh_add, METH_VARARGS, 0 },
+ // add more methods here
+ {NULL, NULL, 0, NULL}
+};
+
+
+static void CSGMesh_dealloc(PyObject *self)
+{
+ CSG_MeshDescriptor *imesh = ((PyCSGMesh *) self)->imesh;
+ CSG_DEBUG(("object was destroyed\n"));
+ // TODO: delete (free) struct ptr
+ CSG_DestroyMeshDescriptor(imesh);
+ MEM_freeN(imesh);
+ PyMem_DEL(self);
+}
+
+static PyObject *CSGMesh_getattr(PyObject *self, char *attr)
+{
+ return Py_FindMethod(CSGMesh_methods, (PyObject *) self, attr);
+}
+///////////////////////////////////////////////////////////////
+// CSG module methods
+
+static PyObject *newPyCSGMesh(CSG_MeshDescriptor *imesh)
+{
+ PyCSGMesh *c = PyObject_NEW(PyCSGMesh, &PyCSGMesh_Type);
+ CSG_DEBUG(("object was created\n"));
+ c->imesh = imesh;
+ // add init bla here
+ return (PyObject *) c;
+}
+
+static PyObject *CSGmodule_CSGMesh(PyObject *self, PyObject *args)
+{
+ char *name;
+
+ Object *obj;
+ CSG_MeshDescriptor *new_imesh;
+
+ if (!PyArg_ParseTuple(args, "s", &name)) return NULL;
+ new_imesh = (CSG_MeshDescriptor *) MEM_mallocN(
+ sizeof(CSG_MeshDescriptor),
+ "CSG_IMesh");
+
+ // get object by name, return its mesh data
+ // and do the conversion
+ // CSG_LoadBlenderMesh(name, new_imesh);
+
+ obj = (Object *) getFromList(getObjectList(), name);
+
+ if (!obj) {
+ PyErr_SetString(PyExc_AttributeError,
+ "requested Object does not exist");
+ return NULL;
+ }
+
+ if (obj->type != OB_MESH) {
+ PyErr_SetString(PyExc_TypeError, "Mesh object expected");
+ return NULL;
+ }
+
+ if (!CSG_LoadBlenderMesh(obj, new_imesh)) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "FATAL: Could not acquire mesh data");
+ return NULL;
+ }
+ return newPyCSGMesh(new_imesh);
+}
+
+static PyObject *CSGmodule_toBlenderMeshObject(PyObject *self,
+ PyObject *args)
+{
+ Object *new_object;
+ PyCSGMesh *pmesh;
+ CSG_MeshDescriptor *c;
+
+ float identity[4][4] = { {1.0, 0.0, 0.0, 0.0},
+ {0.0, 1.0, 0.0, 0.0},
+ {0.0, 0.0, 1.0, 0.0},
+ {0.0, 0.0, 0.0, 1.0}};
+
+
+ if (!PyArg_ParseTuple(args, "O!", &PyCSGMesh_Type, &pmesh)) return NULL;
+ c = pmesh->imesh;
+ new_object = object_new(OB_MESH);
+
+ if (!PyArg_ParseTuple(self, "")) return NULL;
+ // TODO: blender mesh conversion
+ ConvertCSGDescriptorsToMeshObject(new_object, &c->m_descriptor,
+ &c->m_face_iterator,
+ &c->m_vertex_iterator,
+ identity);
+
+ // return resulting object
+ return DataBlock_fromData(new_object);
+}
+
+static PyMethodDef CSGmodule_methods[] = {
+ {"CSGMesh", CSGmodule_CSGMesh , METH_VARARGS, 0 },
+ {"toObject", CSGmodule_toBlenderMeshObject, METH_VARARGS, 0 },
+ {NULL, NULL, 0, NULL}
+};
+
+// MODULE INITIALIZATION
+
+void initcsg()
+{
+ PyObject *mod;
+ PyCSGMesh_Type.ob_type = &PyType_Type;
+ mod = Py_InitModule("csg", CSGmodule_methods);
+
+}
+
diff --git a/source/blender/bpython/intern/BPY_csg.h b/source/blender/bpython/intern/BPY_csg.h
new file mode 100644
index 00000000000..8b4a829a057
--- /dev/null
+++ b/source/blender/bpython/intern/BPY_csg.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 *****
+ */
+#include "BPY_macros.h"
+
+#include "opy_datablock.h"
+#include "b_interface.h"
diff --git a/source/blender/bpython/intern/BPY_image.c b/source/blender/bpython/intern/BPY_image.c
new file mode 100644
index 00000000000..a94abb594a7
--- /dev/null
+++ b/source/blender/bpython/intern/BPY_image.c
@@ -0,0 +1,103 @@
+/**
+ * Image Datablocks
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "Python.h"
+#include "opy_datablock.h"
+
+#include "DNA_image_types.h"
+#include "BKE_image.h"
+
+#include "BPY_macros.h"
+#include "b_interface.h"
+
+PyObject *INITMODULE(Image)(void);
+
+/* Image_Get */
+DATABLOCK_GET(Imagemodule, image, getImageList())
+
+char Imagemodule_load_doc[] = "(filename) - return image from file 'filename' as Image object";
+
+PyObject *Imagemodule_load(PyObject *self, PyObject *args)
+{
+ char *name;
+ Image *im;
+
+ if (!PyArg_ParseTuple(args, "s", &name)) {
+ PyErr_SetString(PyExc_TypeError, "filename expected");
+ return 0;
+ }
+
+ im = add_image(name);
+ if (im) {
+ return DataBlock_fromData(im);
+ } else {
+ PyErr_SetString(PyExc_IOError, "couldn't load image");
+ return 0;
+ }
+}
+
+DataBlockProperty Image_Properties[]= {
+ {"xrep", "xrep", DBP_TYPE_SHO, 0, 1.0, 16.0},
+ {"yrep", "yrep", DBP_TYPE_SHO, 0, 1.0, 16.0},
+// {"PackedFile", "*packedfile", DBP_TYPE_FUN, 0, 0.0, 0.0, {0}, {0}, 0, 0, get_DataBlock_func},
+ {NULL}
+};
+
+#undef MethodDef
+#define MethodDef(func) _MethodDef(func, Imagemodule)
+
+struct PyMethodDef Imagemodule_methods[] = {
+ MethodDef(get),
+ MethodDef(load),
+ // for compatibility:
+ {"Load", Imagemodule_load, METH_VARARGS, Imagemodule_load_doc},
+ {NULL, NULL}
+};
+
+
+/*
+void Image_getattr(void *vdata, char *name)
+{
+}
+*/
+
+
+PyObject *INITMODULE(Image)(void)
+{
+ PyObject *mod= Py_InitModule(SUBMODULE(Image), Imagemodule_methods);
+ return mod;
+}
+
+
+
+
diff --git a/source/blender/bpython/intern/BPY_ipo.c b/source/blender/bpython/intern/BPY_ipo.c
new file mode 100644
index 00000000000..237692ca38d
--- /dev/null
+++ b/source/blender/bpython/intern/BPY_ipo.c
@@ -0,0 +1,717 @@
+/** Ipo module; access to Ipo datablocks in Blender
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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_guardedalloc.h"
+
+#include "Python.h"
+#include "BPY_macros.h"
+#include "BPY_tools.h"
+
+#include "b_interface.h" // most datatypes
+
+#include "opy_datablock.h"
+
+#include "DNA_curve_types.h"
+
+#include "BSE_editipo.h"
+
+/* GLOBALS */
+
+/* These should be put into a proper dictionary for quicker retrieval..*/
+
+NamedEnum g_OB_ipocodes[] = {
+
+ { "LocX", OB_LOC_X },
+ { "LocY", OB_LOC_Y },
+ { "LocZ", OB_LOC_Z },
+ { "dLocX", OB_DLOC_X },
+ { "dLocY", OB_DLOC_Y },
+ { "dLocZ", OB_DLOC_Z },
+ { "RotX", OB_ROT_X },
+ { "RotY", OB_ROT_Y },
+ { "RotZ", OB_ROT_Z },
+ { "dRotX", OB_DROT_X },
+ { "dRotY", OB_DROT_Y },
+ { "dRotZ", OB_DROT_Z },
+ { "SizeX", OB_SIZE_X },
+ { "SizeY", OB_SIZE_Y },
+ { "SizeY", OB_SIZE_Z },
+ { "dSizeX", OB_DSIZE_X },
+ { "dSizeY", OB_DSIZE_Y },
+ { "dSizeY", OB_DSIZE_Z },
+ { "Layer", OB_LAY },
+ { "Time", OB_TIME },
+ { 0, 0 }
+};
+
+NamedEnum g_MA_ipocodes[] = {
+
+ { "R", MA_COL_R },
+ { "G", MA_COL_G },
+ { "B", MA_COL_B },
+ { "Alpha", MA_ALPHA},
+ { "SpecR", MA_SPEC_R },
+ { "SpecG", MA_SPEC_G },
+ { "SpecB", MA_SPEC_B },
+ { "MirR", MA_MIR_R },
+ { "MirG", MA_MIR_G },
+ { "MirB", MA_MIR_B },
+ { "Emit", MA_EMIT },
+ { "Amb", MA_AMB },
+ { "Spec", MA_SPEC },
+ { "Hard", MA_HARD },
+ { "SpTra", MA_SPTR },
+ { "Ang", MA_ANG },
+ { "HaSize", MA_HASIZE },
+ { 0, 0 }
+};
+
+NamedEnum g_WO_ipocodes[] = {
+ { "HorR", WO_HOR_R },
+ { "HorG", WO_HOR_G },
+ { "HorB", WO_HOR_B },
+ { "ZenR", WO_ZEN_R },
+ { "ZenG", WO_ZEN_G },
+ { "ZenB", WO_ZEN_B },
+ { "Expos", WO_EXPOS },
+ { "Misi", WO_MISI },
+ { "MisDi", WO_MISTDI },
+ { "MisSta", WO_MISTSTA },
+ { "MisHi", WO_MISTHI },
+ { "StarR", WO_STAR_R },
+ { "StarG", WO_STAR_G },
+ { "StarB", WO_STAR_B },
+ { "StarDi", WO_STARDIST },
+ { "StarSi", WO_STARSIZE },
+ { 0, 0 }
+};
+
+NamedEnum g_CA_ipocodes[] = {
+ { "Lens", CAM_LENS },
+ { "ClSta", CAM_STA },
+ { "ClEnd", CAM_END },
+ { 0, 0 }
+};
+
+PyObject *g_ipoBlockTypes; // global for ipo type container
+PyObject *g_interpolationTypes; // global for interpolation type container
+PyObject *g_extrapolationTypes; // global for extrapolation type container
+
+typedef struct _PyBezTriple {
+ PyObject_VAR_HEAD
+
+ BezTriple bzt;
+} PyBezTriple;
+
+
+void pybzt_dealloc(PyObject *self) {
+ PyMem_DEL(self);
+}
+
+PyObject *pybzt_repr(PyObject *self) {
+ return PyString_FromString("[BezTriple]");
+}
+
+/* XXX */
+
+NamedEnum bez_triple_flags[]= {
+ {"Free", HD_FREE},
+ {"Auto", HD_AUTO},
+ {"Vect", HD_VECT},
+ {"Align", HD_ALIGN},
+ {NULL}
+};
+
+DataBlockProperty BezTriple_Properties[]= {
+ {"h1", "vec[3][3]", DBP_TYPE_VEC, 0, 2.0, 0.0, {0,0}, {3,3,-sizeof(float)}},
+ {"pt", "vec[3][3]", DBP_TYPE_VEC, 0, 2.0, 0.0, {1,0}, {3,3,-sizeof(float)}},
+ {"h2", "vec[3][3]", DBP_TYPE_VEC, 0, 2.0, 0.0, {2,0}, {3,3,-sizeof(float)}},
+
+ {"f1", "f1", DBP_TYPE_CHA, 0, 0.0, 1.0},
+ {"f2", "f2", DBP_TYPE_CHA, 0, 0.0, 1.0},
+ {"f3", "f3", DBP_TYPE_CHA, 0, 0.0, 1.0},
+
+ {"h1Type", "h1", DBP_TYPE_SHO, 0, 0.0, 0.0, {0}, {0}, DBP_HANDLING_NENM, bez_triple_flags},
+ {"h2Type", "h2", DBP_TYPE_SHO, 0, 0.0, 0.0, {0}, {0}, DBP_HANDLING_NENM, bez_triple_flags},
+
+ {"h1t", "h1", DBP_TYPE_SHO, 0, 0.0, 0.0, {0}, {0}, DBP_HANDLING_NENM, bez_triple_flags},
+ {"h2t", "h2", DBP_TYPE_SHO, 0, 0.0, 0.0, {0}, {0}, DBP_HANDLING_NENM, bez_triple_flags},
+
+ {NULL}
+};
+
+PyObject *pybzt_getattr(PyObject *self, char *name) {
+ PyBezTriple *pybzt= (PyBezTriple *) self;
+
+ return datablock_getattr(BezTriple_Properties, "BezTriple", name, &pybzt->bzt);
+}
+
+int pybzt_setattr(PyObject *self, char *name, PyObject *ob) {
+ PyBezTriple *pybzt= (PyBezTriple *) self;
+
+ return datablock_setattr(BezTriple_Properties, "BezTriple", name, &pybzt->bzt, ob);
+}
+
+PyTypeObject PyBezTriple_Type = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "BezTriple", /*tp_name*/
+ sizeof(PyBezTriple), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ (destructor) pybzt_dealloc, /*tp_dealloc*/
+ (printfunc) 0, /*tp_print*/
+ (getattrfunc) pybzt_getattr, /*tp_getattr*/
+ (setattrfunc) pybzt_setattr, /*tp_setattr*/
+ 0, /*tp_compare*/
+ (reprfunc) pybzt_repr, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash*/
+};
+
+static char pybzt_create_doc[]= "() - Create a new BezTriple object";
+PyObject *pybzt_create(PyObject *self, PyObject *args) {
+ PyBezTriple *py_bzt= PyObject_NEW(PyBezTriple, &PyBezTriple_Type);
+ // BezTriple *bzt= &py_bzt->bzt;
+
+ BPY_TRY(PyArg_ParseTuple(args, ""));
+
+ memset(&py_bzt->bzt,0,sizeof(py_bzt->bzt));
+
+ return (PyObject *) py_bzt;
+}
+
+PyObject *pybzt_from_bzt(BezTriple *bzt) {
+ PyBezTriple *py_bzt= PyObject_NEW(PyBezTriple, &PyBezTriple_Type);
+
+ memcpy(&py_bzt->bzt, bzt, sizeof(*bzt));
+
+ return (PyObject *) py_bzt;
+}
+
+
+typedef struct _PyIpoCurve {
+ PyObject_VAR_HEAD
+
+ IpoCurve *icu;
+} PyIpoCurve;
+
+
+/********************/
+/* IpoCurve methods */
+
+#undef MethodDef
+#define MethodDef(func) _MethodDef(func, IpoCurve)
+
+#define DICT_FROM_CONSTDICT(x) \
+ ((constobject *) x)->dict
+
+/** sets an enum int value 'by name' from the dictionary dict */
+
+static PyObject *setEnum_fromDict(short *i, PyObject *dict, char *key, char *errmsg)
+{
+ PyObject *p;
+ p = PyDict_GetItemString(dict, key);
+ if (!p) {
+ PyErr_SetString(PyExc_TypeError, errmsg);
+ return NULL;
+ }
+
+ *i = (short) PyInt_AsLong(p);
+ return BPY_incr_ret(Py_None);
+}
+
+static char IpoCurve_setInterpolation_doc[] =
+"(type) - Set interpolation to one of: ['Constant', 'Linear', 'Bezier']";
+
+static PyObject *IpoCurve_setInterpolation(PyObject *self, PyObject *args)
+{
+ char *typename;
+ IpoCurve *ipocurve = (IpoCurve *) ((PyIpoCurve *) self)->icu;
+
+ BPY_TRY(PyArg_ParseTuple(args, "s", &typename));
+
+ return setEnum_fromDict(&ipocurve->ipo, DICT_FROM_CONSTDICT(g_interpolationTypes),
+ typename, "Improper interpolation type, see Ipo.InterpolationTypes");
+
+}
+
+static char IpoCurve_setExtrapolation_doc[] =
+"(type) - Set interpolation to one of: ['Constant', 'Linear', 'Cyclic', 'CyclicLinear']";
+
+static PyObject *IpoCurve_setExtrapolation(PyObject *self, PyObject *args)
+{
+ char *typename;
+ IpoCurve *ipocurve = (IpoCurve *) ((PyIpoCurve *) self)->icu;
+
+ BPY_TRY(PyArg_ParseTuple(args, "s", &typename));
+
+
+ return setEnum_fromDict(&ipocurve->extrap, DICT_FROM_CONSTDICT(g_extrapolationTypes),
+ typename, "Improper extrapolation type, see Ipo.ExtrapolationTypes");
+}
+
+static char IpoCurve_getInterpolation_doc[] =
+"() - Returns interpolation type";
+
+static PyObject *IpoCurve_getInterpolation(PyObject *self, PyObject *args)
+{
+ IpoCurve *ipocurve = (IpoCurve *) ((PyIpoCurve *) self)->icu;
+
+ switch (ipocurve->ipo) {
+ case IPO_CONST: return PyString_FromString("Constant");
+ case IPO_LIN: return PyString_FromString("Linear");
+ case IPO_BEZ: return PyString_FromString("Bezier");
+ default: return PyString_FromString("<not defined>");
+ }
+}
+
+static char IpoCurve_getExtrapolation_doc[] =
+"() - Returns extrapolation type";
+
+static PyObject *IpoCurve_getExtrapolation(PyObject *self, PyObject *args)
+{
+ IpoCurve *ipocurve = (IpoCurve *) ((PyIpoCurve *) self)->icu;
+
+ switch (ipocurve->extrap) {
+ case IPO_HORIZ: return PyString_FromString("Constant");
+ case IPO_DIR: return PyString_FromString("Linear");
+ case IPO_CYCL: return PyString_FromString("Cyclic");
+ case IPO_CYCLX: return PyString_FromString("CyclicLinear");
+ default: return PyString_FromString("<not defined>");
+ }
+
+}
+
+static char IpoCurve_eval_doc[] =
+"(time = <current frame>) - evaluates ipo at time 'time' and returns result\n\
+(float). If 'time' is not specified, the current frame value is taken";
+
+static PyObject *IpoCurve_eval(PyObject *self, PyObject *args)
+{
+ PyIpoCurve *pIpocurve = (PyIpoCurve *) self;
+ float time = CurrentFrame;
+
+ BPY_TRY(PyArg_ParseTuple(args, "|f", &time));
+
+ return PyFloat_FromDouble(eval_icu(pIpocurve->icu, time));
+}
+
+static char IpoCurve_update_doc[] =
+"() - update and recalculate IpoCurve";
+
+static PyObject *IpoCurve_update(PyObject *self, PyObject *args)
+{
+
+ BPY_TRY(PyArg_ParseTuple(args, ""));
+
+ testhandles_ipocurve(((PyIpoCurve *) self)->icu); // recalculate IPO
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static struct PyMethodDef IpoCurve_methods[] = {
+ MethodDef(setInterpolation),
+ MethodDef(getInterpolation),
+ MethodDef(setExtrapolation),
+ MethodDef(getExtrapolation),
+ MethodDef(eval),
+ MethodDef(update),
+ {NULL, NULL}
+};
+
+
+PyObject *IpoCurve_getattr(PyObject *self, char *name) {
+ PyIpoCurve *py_icu= (PyIpoCurve *) self;
+ IpoCurve *icu= py_icu->icu;
+
+ if (STREQ(name, "type")) {
+ return IpoCurve_getInterpolation(self, Py_BuildValue(""));
+ } else if (STREQ(name, "extend")) {
+ return IpoCurve_getExtrapolation(self, Py_BuildValue(""));
+ } else if (STREQ(name, "name")) {
+ char icu_name[32]= "";
+
+ switch (icu->blocktype) {
+ case ID_OB:
+ getname_ob_ei(icu->adrcode, icu_name, 0);
+ break;
+ case ID_MA:
+ getname_mat_ei(icu->adrcode, icu_name);
+ break;
+ case ID_WO:
+ getname_world_ei(icu->adrcode, icu_name);
+ break;
+ case ID_SEQ:
+ getname_seq_ei(icu->adrcode, icu_name);
+ break;
+ case ID_CU:
+ getname_cu_ei(icu->adrcode, icu_name);
+ break;
+ case ID_KE:
+ getname_key_ei(icu->adrcode, icu_name);
+ break;
+ case ID_LA:
+ getname_la_ei(icu->adrcode, icu_name);
+ break;
+ case ID_CA:
+ getname_cam_ei(icu->adrcode, icu_name);
+ break;
+ default:
+ return PyString_FromString("<unknown>");
+ }
+
+ return PyString_FromString(icu_name);
+ } else if (STREQ(name, "points")) {
+ PyObject *list= PyList_New(icu->totvert);
+ BezTriple *bzt= icu->bezt;
+ int i;
+
+ for (i=0; i<icu->totvert; i++) {
+ PyList_SetItem(list, i, pybzt_from_bzt(bzt));
+ bzt++;
+ }
+
+ return list;
+ }
+ return Py_FindMethod(IpoCurve_methods, (PyObject*)self, name);
+}
+
+int IpoCurve_setattr(PyObject *self, char *name, PyObject *ob) {
+ PyIpoCurve *py_icu= (PyIpoCurve *) self;
+ IpoCurve *icu= py_icu->icu;
+
+ if (STREQ(name, "points")) {
+ int i, len;
+ BezTriple *bzt;
+
+ if (!PySequence_Check(ob) || !BPY_check_sequence_consistency(ob, &PyBezTriple_Type))
+ return py_err_ret_int(PyExc_AttributeError, "Expected list of BezTriples");
+
+ len= PySequence_Length(ob);
+
+ if (icu->bezt) // free existing (IF)
+ MEM_freeN(icu->bezt);
+
+ icu->totvert= len;
+ if (len) icu->bezt= MEM_mallocN(len*sizeof(BezTriple), "beztriples");
+
+ bzt= icu->bezt;
+ for (i=0; i<len; i++) {
+ PyBezTriple *pybzt= (PyBezTriple*) PySequence_GetItem(ob, i);
+
+ memcpy(bzt, &pybzt->bzt, sizeof(BezTriple));
+ bzt++;
+
+ Py_DECREF(pybzt);
+ }
+
+ /* Twice for auto handles */
+ calchandles_ipocurve(icu);
+ calchandles_ipocurve(icu);
+
+ boundbox_ipocurve(icu);
+ sort_time_ipocurve(icu);
+
+ return 0;
+ }
+
+ PyErr_SetString(PyExc_AttributeError, name);
+ return -1;
+}
+
+void IpoCurve_dealloc(PyObject *self) {
+ PyMem_DEL(self);
+}
+
+PyObject *IpoCurve_repr(PyObject *self) {
+ char s[256];
+ sprintf (s, "[IpoCurve %.32s]",
+ PyString_AsString(IpoCurve_getattr(self, "name")));
+ return Py_BuildValue("s", s);
+}
+
+PyTypeObject PyIpoCurve_Type = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "IpoCurve", /*tp_name*/
+ sizeof(PyIpoCurve), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ (destructor) IpoCurve_dealloc, /*tp_dealloc*/
+ (printfunc) 0, /*tp_print*/
+ (getattrfunc) IpoCurve_getattr, /*tp_getattr*/
+ (setattrfunc) IpoCurve_setattr, /*tp_setattr*/
+ 0, /*tp_compare*/
+ (reprfunc) IpoCurve_repr, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash*/
+};
+
+PyObject *IpoCurve_from_icu(IpoCurve *icu) {
+ PyIpoCurve *ob= PyObject_NEW(PyIpoCurve, &PyIpoCurve_Type);
+
+ ob->icu= icu;
+
+ return (PyObject *) ob;
+}
+
+PyObject *make_icu_list (ListBase *curves) {
+ ListBase lb= *curves;
+ IpoCurve *icu= (IpoCurve *) lb.first;
+ PyObject *list= PyList_New(0);
+ PyObject *pyipo;
+
+ while (icu) {
+ pyipo = IpoCurve_from_icu(icu);
+ PyList_Append(list, pyipo);
+ Py_DECREF(pyipo);
+ icu= icu->next;
+ }
+
+ return list;
+}
+
+DataBlockProperty Ipo_Properties[]= {
+ {"curves", "curve", DBP_TYPE_FUN, 0, 0.0, 0.0, {0}, {0}, 0, 0, make_icu_list},
+ {NULL}
+};
+
+
+/**********************/
+/* Ipo module methods */
+
+DATABLOCK_GET(Ipomodule, ipo, getIpoList())
+
+static char Ipomodule_New_doc[] =
+"(type, name = <default>) - Creates a new Ipo block of the specified type,\n\
+which must be of the appropriate datablock ID type (e.g. ID_OB, ID_MA, ...)";
+
+
+static PyObject *Ipomodule_New(PyObject *self, PyObject *args)
+{
+ Ipo *ipo;
+ int type;
+ PyObject *p;
+ char *name = NULL, *typename;
+
+ BPY_TRY(PyArg_ParseTuple(args, "s|s", &typename, &name));
+ p = PyDict_GetItemString(((constobject *)g_ipoBlockTypes)->dict, typename);
+ if (!p) {
+ PyErr_SetString(PyExc_TypeError, "Improper Ipo type, see Ipo.Types");
+ return NULL;
+ }
+
+ type = PyInt_AsLong(p);
+
+ if (!name) {
+ switch(type) {
+ case ID_OB: name = "Objpo"; break;
+ case ID_MA: name = "MatIpo"; break;
+ case ID_SEQ: name = "SeqIpo"; break;
+ case ID_CU: name = "CurveIpo"; break;
+ case ID_KE: name = "KeyIpo"; break;
+ case ID_WO: name = "WorldIpo"; break;
+ case ID_LA: name = "LampIpo"; break;
+ case ID_CA: name = "CamIpo"; break;
+ case ID_SO: name = "SndIpo"; break;
+ case ID_AC: name = "ActionIpo"; break;
+ default:
+ PyErr_SetString(PyExc_TypeError, "Internal error, illegal type");
+ return NULL;
+ }
+ }
+
+ ipo = ipo_new(type, name);
+ return DataBlock_fromData(ipo);
+}
+
+#undef MethodDef
+#define MethodDef(func) _MethodDef(func, Ipomodule)
+struct PyMethodDef Ipomodule_methods[] = {
+
+ MethodDef(New),
+ MethodDef(get),
+ {"BezTriple", pybzt_create, METH_VARARGS, pybzt_create_doc},
+
+ {NULL, NULL}
+};
+
+/********************/
+/* Ipoblock methods */
+
+/* slow and inefficient lookup function , use proper dictionaries in future */
+short code_lookup(NamedEnum *codetab, char *name)
+{
+ int i = 0;
+
+ while(codetab[i].name)
+ {
+ if (!strcmp(codetab[i].name, name))
+ return codetab[i].num;
+ i++;
+ }
+ return -1;
+}
+
+static char Ipo_addCurve_doc[]=
+"(type, curve = None) - adds IpoCurve 'curve' to the IpoBlock under type id 'type'";
+PyObject *Ipo_addCurve(PyObject *self, PyObject *args)
+{
+
+ Ipo *ipo = (Ipo *) ((DataBlock *) self)->data;
+ NamedEnum *lookup;
+
+ short code;
+
+ char *type;
+ PyIpoCurve *curve = NULL;
+ IpoCurve *ipocurve, *existingIpoCurve;
+
+ BPY_TRY(PyArg_ParseTuple(args, "s|O!", &type, &PyIpoCurve_Type, &curve));
+
+ switch (ipo->blocktype) {
+ case ID_OB:
+ lookup = g_OB_ipocodes;
+ break;
+ case ID_CA:
+ lookup = g_CA_ipocodes;
+ break;
+ case ID_MA:
+ lookup = g_MA_ipocodes;
+ break;
+ case ID_WO:
+ lookup = g_WO_ipocodes;
+ break;
+ default:
+ PyErr_SetString(PyExc_TypeError, "Ipo type not (YET) supported");
+ return NULL;
+ }
+ code = code_lookup(lookup, type);
+ if (code == -1) {
+ PyErr_SetString(PyExc_TypeError, "Unknown IpoCurve type");
+ return NULL;
+ }
+
+ if (!curve) {
+ ipocurve = ipocurve_new(); // malloc new ipocurve
+ } else { // add existing curve:
+ ipocurve = ipocurve_copy(curve->icu); // copy ipocurve
+ }
+
+ ipocurve->adrcode = code; // re-code ipo
+ ipocurve->blocktype = ipo->blocktype;
+
+ existingIpoCurve = ipo_findcurve(ipo, code);
+ if (existingIpoCurve) {
+ BLI_remlink(&(ipo->curve), existingIpoCurve); // remove existing
+ MEM_freeN(existingIpoCurve);
+ }
+ BLI_addtail(&(ipo->curve), ipocurve); // add curve to list
+ return IpoCurve_from_icu(ipocurve);
+}
+
+static char Ipo_update_doc[]=
+"() - Recalculate the ipo and update linked objects";
+
+PyObject *Ipo_update(PyObject *self, PyObject *args) {
+ DataBlock *ipoblock = (DataBlock *) self;
+ Key *key;
+
+ do_ipo((Ipo *) ipoblock->data);
+
+ /* here we should signal all objects with keys that the ipo changed */
+
+ key= getKeyList()->first;
+ while(key) {
+ if(key->ipo == (Ipo *)ipoblock->data) do_spec_key(key);
+ key= key->id.next;
+ }
+
+ return BPY_incr_ret(Py_None);
+}
+
+#undef MethodDef
+#define MethodDef(func) _MethodDef(func, Ipo)
+struct PyMethodDef Ipo_methods[] = {
+ MethodDef(addCurve),
+ MethodDef(update),
+ {NULL, NULL}
+};
+
+
+PyObject *initIpo(void)
+{
+ PyObject *mod, *dict, *d;
+
+ mod= Py_InitModule(MODNAME(BLENDERMODULE) ".Ipo", Ipomodule_methods);
+ dict = PyModule_GetDict(mod);
+
+ // ipo block types
+ d = ConstObject_New();
+ PyDict_SetItemString(dict, "Types", d);
+ g_ipoBlockTypes = d;
+
+ insertConst(d, "Object", PyInt_FromLong(ID_OB));
+ insertConst(d, "Material", PyInt_FromLong(ID_MA));
+ insertConst(d, "Sequence", PyInt_FromLong(ID_SEQ));
+ insertConst(d, "Curve", PyInt_FromLong(ID_CU));
+ insertConst(d, "Key", PyInt_FromLong(ID_KE));
+ insertConst(d, "World", PyInt_FromLong(ID_WO));
+ insertConst(d, "Lamp", PyInt_FromLong(ID_LA));
+ insertConst(d, "Camera", PyInt_FromLong(ID_CA));
+ insertConst(d, "Sound", PyInt_FromLong(ID_SO));
+ insertConst(d, "Action", PyInt_FromLong(ID_AC));
+
+ // interpolation types:
+ d = ConstObject_New();
+ g_interpolationTypes = d;
+ PyDict_SetItemString(dict, "InterpolationTypes", d);
+ insertConst(d, "Constant", PyInt_FromLong(IPO_CONST));
+ insertConst(d, "Linear", PyInt_FromLong(IPO_LIN));
+ insertConst(d, "Bezier", PyInt_FromLong(IPO_BEZ));
+
+ d = ConstObject_New();
+ g_extrapolationTypes = d;
+ PyDict_SetItemString(dict, "ExtrapolationTypes", d);
+ insertConst(d, "Constant", PyInt_FromLong(IPO_HORIZ));
+ insertConst(d, "Linear", PyInt_FromLong(IPO_DIR));
+ insertConst(d, "Cyclic", PyInt_FromLong(IPO_CYCL));
+ insertConst(d, "CyclicLinear", PyInt_FromLong(IPO_CYCLX));
+
+ return mod;
+}
diff --git a/source/blender/bpython/intern/BPY_links.c b/source/blender/bpython/intern/BPY_links.c
new file mode 100644
index 00000000000..e3c6458ef82
--- /dev/null
+++ b/source/blender/bpython/intern/BPY_links.c
@@ -0,0 +1,96 @@
+/** Helper functions to handle links between Object types,
+ * Script links */
+
+/*
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "Python.h"
+#include "BPY_macros.h"
+#include "b_interface.h"
+
+/* GLOBALS */
+
+PyObject *g_blenderdict;
+
+/* PROTOS */
+char *event_to_name(short event);
+void set_scriptlinks(ID *id, short event);
+
+#ifndef SHAREDMODULE
+PyObject *DataBlock_fromData (void *data);
+
+
+void set_scriptlinks(ID *id, short event)
+{
+ PyObject *link;
+
+ if (!g_blenderdict) // not initialized yet; this can happen at first file load
+ {
+ return;
+ }
+ if (GET_ID_TYPE(id) == ID_SCE) {
+ Py_INCREF(Py_None);
+ link = Py_None;
+ } else {
+ link = DataBlock_fromData(id);
+ }
+
+ if (!link)
+ {
+ printf ("Internal error, unable to create PyBlock for script link\n");
+ printf ("This is a bug; please report to bugs@blender.nl");
+ Py_INCREF(Py_False);
+ PyDict_SetItemString(g_blenderdict, "bylink", Py_False);
+ return;
+ } else {
+ Py_INCREF(Py_True);
+ PyDict_SetItemString(g_blenderdict, "bylink", Py_True);
+ }
+
+ PyDict_SetItemString(g_blenderdict, "link", link);
+ PyDict_SetItemString(g_blenderdict, "event", Py_BuildValue("s", event_to_name(event)));
+}
+
+/* this is just a hack-added function to release a script link reference.
+ * The scriptlink concept will be redone later */
+
+void release_scriptlinks(ID *id)
+{
+ PyObject *link;
+ if (!g_blenderdict) return; // return if Blender module was not initialized
+ link = PyDict_GetItemString(g_blenderdict, "link");
+ Py_DECREF(link);
+ Py_INCREF(Py_None);
+ PyDict_SetItemString(g_blenderdict, "link", Py_None);
+}
+
+#endif
diff --git a/source/blender/bpython/intern/BPY_listbase_macro.h b/source/blender/bpython/intern/BPY_listbase_macro.h
new file mode 100644
index 00000000000..5c5047d22d8
--- /dev/null
+++ b/source/blender/bpython/intern/BPY_listbase_macro.h
@@ -0,0 +1,62 @@
+/**
+ $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ These are macros to create python lists from base lists.
+*/
+
+
+
+/** example: DEFFUNC_GETLIST(text) defines a method for getting a list
+ * of text blocks */
+
+// Example: _GETLIST(name) -> get_namelist
+#define _GETLIST(x) get_##x##list
+
+// Function definition:
+// DEFFUNC_GETLIST_MAIN(name) -> get_namelist(PyObject *self, PyObject *args)
+#define DEFFUNC_GETLIST_MAIN(x) \
+ PyObject *_GETLIST(x)(PyObject *self, PyObject *args) \
+ { \
+ ID *id; \
+ PyObject *list; \
+ list = PyList_New(0); \
+ id = G.main->##x##.first; \
+ while (id) \
+ { \
+ PyList_Append(list, PyString_FromString(id->name+2)); \
+ id = id->next; \
+ } \
+ return list; \
+ } \
+
+// call the above function
+#define GETLISTFUNC(x) _GETLIST(x)
+// Prototype for the above function
+#define GETLISTPROTO(x) PyObject *_GETLIST(x)(PyObject *, PyObject *)
diff --git a/source/blender/bpython/intern/BPY_macros.h b/source/blender/bpython/intern/BPY_macros.h
new file mode 100644
index 00000000000..9f9bea4864a
--- /dev/null
+++ b/source/blender/bpython/intern/BPY_macros.h
@@ -0,0 +1,268 @@
+
+/* bpython library macros
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ *
+ */
+
+
+/* Hint: use gcc -E file.c to see what these macros are expanded in */
+
+#include "api.h" // temporary defines for API version
+
+#include "BPY_listbase_macro.h"
+#include "BKE_utildefines.h"
+
+/* CONSTANTS */
+
+#define IDNAME 24
+#define PATH_MAXCHAR 128
+
+/* ALIASES */
+
+#define BPY_TRY(x) {if((!(x))) return NULL;}
+#define BPY_TRY_TYPEERROR(x, str) \
+ { if(!(x)) { \
+ PyErr_SetString(PyExc_TypeError, str); \
+ return NULL; }\
+ }
+
+#define BPY_ADDCONST(dict, name) PyDict_SetItemString(dict, #name, PyInt_FromLong(name))
+#define CurrentFrame (getGlobal()->scene->r.cfra)
+#define RETURN_INC(ob) {Py_INCREF(ob); return ob; }
+
+/* Blender object internal 'reference' (user) counting */
+/* 'x' must be of type (ID *) */
+
+#ifdef DEBUG
+
+ #define BOB_USERCOUNT(x) \
+ (x)->us
+ #define BOB_DECUSER(x) \
+ printf("BOB_DECUSER: %s\n", (x)->name); \
+ (x)->us ? (x)->us--:printf("FATAL: 0--\n")
+ #define BOB_INCUSER(x) \
+ printf("BOB_INCUSER: %s\n", (x)->name); \
+ id_us_plus(x)
+ /* safe ref-inc/dec */
+ #define BOB_XDECUSER(x) \
+ if (x) { \
+ printf("BOB_XDECUSER: %s\n", (x)->name); \
+ ((x)->us ? (x)->us--:printf("FATAL: 0--\n")); \
+ }
+ #define BOB_XINCUSER(x) \
+ if (x) { \
+ printf("BOB_XINCUSER: %s\n", (x)->name); \
+ if (x) id_us_plus(x); \
+ }
+#else
+
+ #define BOB_USERCOUNT(x) \
+ (x)->us
+ #define BOB_DECUSER(x) \
+ (x)->us ? (x)->us--:printf("FATAL: 0--\n")
+ #define BOB_INCUSER(x) \
+ id_us_plus(x)
+ /* safe ref-inc/dec */
+ #define BOB_XDECUSER(x) \
+ if (x) ((x)->us ? (x)->us--:printf("FATAL: 0--\n"))
+ #define BOB_XINCUSER(x) \
+ if (x) id_us_plus(x)
+
+#endif
+
+/* WARNINGS, Verbose */
+
+#define BPY_CHECKFLAG(x) (getGlobal()->f & x)
+#define BPY_DEBUGFLAG BPY_CHECKFLAG(G_DEBUG)
+#define BPY_debug(a) if BPY_DEBUGFLAG {printf a; }
+#define BPY_warn(a) {printf a; }
+
+/* BLENDER DATABLOCK ACCESS */
+
+/* these are relicts... */
+#define GS(a) (*((short *)(a)))
+#define STREQ(str, a) ( strcmp((str), (a))==0 )
+
+/** This macro should be used to get the (short) id type of a ID datablock
+ * structure (Object, Mesh, etc.)
+ * Usage is dangerous, so use it only if you know what you're doing :-)
+ * Otherwise, use DataBlock_type() or associated functions (datablock.c)
+ */
+
+#define GET_ID_TYPE(x) (GS((x)->name))
+
+/* gets the datablock's ID pointer. be careful with its usage,
+ * - no typechecking done! */
+#define DATABLOCK_ID(x) ( (ID *) ((DataBlock *) x)->data)
+
+/** This defines the Get method plus documentation for use in a
+ * Method definition list.
+ * Example:
+ *
+ * DATABLOCK_GET(modulename, objectname, listbase.first)
+ *
+ * This function, called in Python by:
+ *
+ * modulename.Get(name)
+ *
+ * returns a Python DataBlock object for the Blender object with name
+ * 'name'. If 'name' omitted, a list of all the objects in the
+ * given list (a linked list of ID pointers) is returned
+ */
+
+
+#define DATABLOCK_GET(uname, docname, list) \
+static char uname##_get_doc[]= \
+"([name]) - Get " #docname "s from Blender\n" \
+"\n" \
+"[name] The name of the " #docname " to return\n" \
+"\n" \
+"Returns a list of all " #docname "s if name is not specified"; \
+ \
+static PyObject* uname##_get (PyObject *self, PyObject *args) { \
+ return py_find_from_list(list, args); \
+}
+
+/** This macro defines the creation of new Objects */
+
+#define DATABLOCK_NEW( modprefix, type, callfunc) \
+static char modprefix##_New_doc[] = \
+"() - returns new " #type " object"; \
+ \
+PyObject *modprefix##_New (PyObject *self, PyObject *args) \
+{ \
+ type *obj; \
+ char *name = #type; \
+ BPY_TRY(PyArg_ParseTuple(args, "|s", &name)); \
+ obj = callfunc; \
+ return DataBlock_fromData(obj); \
+} \
+
+#define DATABLOCK_ASSIGN_IPO(type, prefix) \
+static char type##_assignIpo_doc[]= \
+"(ipo) - assigns Ipo to object of type " #type ; \
+ \
+static PyObject *type##_assignIpo(PyObject *self, PyObject *args) \
+{ \
+ DataBlock *ipoblock; \
+ Ipo *ipo; \
+ type *object = PYBLOCK_AS(type, self); \
+ \
+ BPY_TRY(PyArg_ParseTuple(args, "O!", &DataBlock_Type, &ipoblock));\
+ if (!DataBlock_isType(ipoblock, ID_IP)) { \
+ PyErr_SetString(PyExc_TypeError, "expects Ipo object"); \
+ return 0; \
+ } \
+ ipo = PYBLOCK_AS_IPO(ipoblock); \
+ \
+ if (ipo->blocktype != GET_ID_TYPE((ID *) object)) { \
+ PyErr_SetString(PyExc_TypeError, \
+ "Ipo type does not match object type"); \
+ return 0; \
+ } \
+ prefix##_assignIpo(object, ipo); \
+ \
+ Py_INCREF(Py_None); \
+ return Py_None; \
+} \
+ \
+static char type##_clrIpo_doc[]= \
+"(ipo) - clears Ipo" ; \
+ \
+static PyObject *type##_clrIpo(PyObject *self, PyObject *args) \
+{ \
+ type *object = PYBLOCK_AS(type, self); \
+ BPY_TRY(PyArg_ParseTuple(args, "")); \
+ prefix##_assignIpo(object, 0); \
+ Py_INCREF(Py_None); \
+ return Py_None; \
+}
+
+/** Macro used to define the MethodDef macro which is used again for defining
+ * module or object methods in the Method table, see e.g. BPY_scene.c
+ *
+ * Usage:
+
+ * _MethodDef(delete, Scene) expands to:
+ *
+ * {"delete", Scene_delete, METH_VARARGS, Scene_delete_doc}
+ */
+#define _MethodDef(func, prefix) \
+ {#func, prefix##_##func, METH_VARARGS, prefix##_##func##_doc}
+
+/** Mark the datablock wrapper as invalid. See BPY_text.c for details */
+#define MARK_INVALID(datablock) \
+ ((DataBlock *) datablock)->data = NULL
+
+/** Check whether datablock wrapper is valid */
+#define CHECK_VALIDDATA(x, msg) \
+ if (!x) { \
+ PyErr_SetString(PyExc_RuntimeError, msg); \
+ return 0; \
+ } \
+
+
+/* OBJECT ACCESS */
+
+/** retrieves name from BPYobject */
+#define getName(x) ((x)->id.name+2)
+#define getUsers(x) ((x)->id.us)
+#define getIDName(x) ((x)->name+2)
+#define getIDUsers(x) ((x)->us)
+
+#define object_getMaterials(object) (object)->mat
+
+/** rename object with name */
+
+/* ListBase of active object in scene */
+#define FirstBase (getGlobal()->scene->base.first)
+#define ActiveBase (getGlobal()->scene->basact)
+#define ObjectfromBase(base) (base->object)
+#define SelectedAndLayer(base) (((base)->flag & SELECT) && ((base)->lay & getGlobal()->vd->lay))
+/* Active object (bright pink) */
+
+#define ActiveObject (ActiveBase ? ObjectfromBase(ActiveBase) : NULL)
+
+/* returns 1 if textureface tf is selected/active, else 0 */
+#define isSelectedFace(tf) (((tf).flag & TF_SELECT) ? 1 : 0 )
+#define isActiveFace(tf) (((tf).flag & TF_ACTIVE) ? 1 : 0 )
+
+/* some conversion macros */
+
+#define PYBLOCK_AS(x, y) (x *) ((DataBlock *) y)->data
+#define PYBLOCK_AS_TEXT(x) PYBLOCK_AS(Text, x)
+#define PYBLOCK_AS_MATERIAL(x) PYBLOCK_AS(Material, x)
+#define PYBLOCK_AS_OBJECT(x) PYBLOCK_AS(Object, x)
+#define PYBLOCK_AS_MESH(x) PYBLOCK_AS(Mesh, x)
+#define PYBLOCK_AS_LAMP(x) PYBLOCK_AS(Lamp, x)
+#define PYBLOCK_AS_IPO(x) PYBLOCK_AS(Ipo, x)
+#define PYBLOCK_AS_DATA(x) PYBLOCK_AS(void, x)
diff --git a/source/blender/bpython/intern/BPY_main.c b/source/blender/bpython/intern/BPY_main.c
new file mode 100644
index 00000000000..17995476749
--- /dev/null
+++ b/source/blender/bpython/intern/BPY_main.c
@@ -0,0 +1,672 @@
+/**
+ * blenkernel/py_main.c
+ * (cleaned up somewhat nzc apr-2001)
+
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ *
+ */
+
+/* NOTE: all externally callable routines have the prefix BPY_
+ -- see also ../include/BPY_extern.h */
+
+#include "BPY_main.h"
+#include "BPY_modules.h"
+#include "BPY_macros.h"
+#include "DNA_space_types.h"
+
+#include "b_interface.h"
+#include "mydevice.h"
+#include "import.h"
+
+/* PROTOS */
+
+extern void init_frozenmodules(void); // frozen module library
+extern void initmxTextTools(void);
+extern void inittess(void); // tesselator module
+
+void init_ourImport(void);
+
+
+/* GLOBALS */
+
+PyObject* ErrorObject = NULL;
+PyObject* callback = NULL;
+PyObject* callbackArgs = NULL;
+PyObject* blenderprogname = NULL;
+ID* script_link_id = NULL;
+
+/*------------------------------------------------------------------------*/
+/* START PYTHON (from creator.c) */
+
+void INITMODULE(BLENDERMODULE)(void);
+
+struct _inittab blendermodules[] = {
+#ifndef SHAREDMODULE // Blender module can alternatively be compiled shared
+ #ifdef STATIC_TEXTTOOLS // see api.h
+ { "mxTextTools" , initmxTextTools },
+ #endif
+ { MODNAME(BLENDERMODULE) , INITMODULE(BLENDERMODULE) },
+#endif
+#ifdef NO_RELEASE
+ { "tess" , inittess }, // GLU tesselator wrapper module
+#endif
+ { 0, 0}
+};
+
+/* hack to make sure, inittab is extended only first time */
+
+static short g_is_extended = 0;
+
+/** (Re)initializes the Python Interpreter.
+ * This function should be only called if the Python interpreter
+ * was not yet initialized (check Py_IsInitialized() )
+ */
+
+static void initBPythonInterpreter(void)
+{
+ Py_Initialize();
+
+ init_ourImport(); /* our own import, later: security */
+ if (!BPY_CHECKFLAG(G_NOFROZEN)) {
+ init_frozenmodules(); /* initialize frozen modules unless disabled */
+ }
+ init_syspath();
+}
+
+/** This function initializes Blender Python. It should be called only
+ * once at start, which is currently not the case (GameEngine Python).
+ * Therefore, it contains some dirty workarounds. They will be thrown
+ * into the grachten once the different APIs are merged into something
+ * more consistent.
+ *
+ */
+
+void BPY_start_python(void)
+{
+ Py_SetProgramName("blender");
+ if (BPY_DEBUGFLAG) {
+
+ Py_VerboseFlag = 1;
+ Py_DebugFlag = 1;
+ } else {
+#ifndef EXPERIMENTAL
+ Py_FrozenFlag = 1; /* no warnings about non set PYTHONHOME */
+ Py_NoSiteFlag = 1; /* disable auto site module import */
+#endif
+ }
+
+ if (!g_is_extended) {
+ g_is_extended = 1;
+ PyImport_ExtendInittab(blendermodules); /* extend builtin module table */
+ }
+
+ initBPythonInterpreter();
+#ifdef NO_RELEASE
+ if (PyRun_SimpleString("import startup"))
+ {
+ BPY_warn(("init script not found, continuing anyway\n"));
+ PyErr_Clear();
+ return;
+ }
+#endif
+}
+
+/** Ends the Python interpreter. This cleans up all global variables
+ * Blender-Python descriptor objects will (MUST!) decref on their
+ * raw blender objects, so this function should be called more or less
+ * immediately before garbage collection actions.
+ */
+
+void BPY_end_python(void)
+{
+ Py_Finalize();
+}
+
+void BPY_free_compiled_text(Text* text)
+{
+ if (!text->compiled) return;
+ Py_DECREF((PyObject*) text->compiled);
+ text->compiled = NULL;
+}
+
+void syspath_append(PyObject *dir)
+{
+ PyObject *m, *d;
+ PyObject *o;
+
+ PyErr_Clear();
+ m = PyImport_ImportModule("sys");
+ d = PyModule_GetDict(m);
+ o = PyDict_GetItemString(d, "path");
+ if (!PyList_Check(o)) {
+ return;
+ }
+ PyList_Append(o, dir);
+ if (PyErr_Occurred()) {
+ Py_FatalError("could not build sys.path");
+ }
+ Py_DECREF(m);
+}
+
+/* build blender specific system path for external modules */
+
+void init_syspath(void)
+{
+ PyObject *path;
+ PyObject *m, *d;
+ PyObject *p;
+ char *c;
+
+
+ char execdir[PATH_MAXCHAR], *progname;
+
+ int n;
+
+ path = Py_BuildValue("s", bprogname);
+
+ m = PyImport_ImportModule(MODNAME(BLENDERMODULE) ".sys");
+ if (m) {
+ d = PyModule_GetDict(m);
+ PyDict_SetItemString(d, "progname", path);
+ Py_DECREF(m);
+ } else {
+ BPY_debug(("Warning: could not set Blender.sys.progname\n"));
+ }
+
+ progname = BLI_last_slash(bprogname); /* looks for the last dir separator */
+
+ c = Py_GetPath(); /* get python system path */
+ PySys_SetPath(c); /* initialize */
+
+ n = progname - bprogname;
+ if (n > 0) {
+ strncpy(execdir, bprogname, n);
+ execdir[n] = '\0';
+
+ p = Py_BuildValue("s", execdir);
+ syspath_append(p); /* append to module search path */
+
+ /* set Blender.sys.progname */
+ } else {
+ BPY_debug(("Warning: could not determine argv[0] path\n"));
+ }
+ /* TODO look for the blender executable in the search path */
+ BPY_debug(("append to syspath: %s\n", U.pythondir));
+ if (U.pythondir) {
+ p = Py_BuildValue("s", U.pythondir);
+ syspath_append(p); /* append to module search path */
+ }
+ BPY_debug(("append done\n"));
+}
+
+
+#define FILENAME_LENGTH 24
+typedef struct _ScriptError {
+ char filename[FILENAME_LENGTH];
+ int lineno;
+} ScriptError;
+
+ScriptError g_script_error;
+
+int BPY_Err_getLinenumber()
+{
+ return g_script_error.lineno;
+}
+
+const char *BPY_Err_getFilename()
+{
+ return g_script_error.filename;
+}
+
+/** Returns (PyString) filename from a traceback object */
+
+PyObject *traceback_getFilename(PyObject *tb)
+{
+ PyObject *v;
+
+ v = PyObject_GetAttrString(tb, "tb_frame"); Py_DECREF(v);
+ v = PyObject_GetAttrString(v, "f_code"); Py_DECREF(v);
+ v = PyObject_GetAttrString(v, "co_filename");
+ return v;
+}
+
+/** Blender Python error handler. This catches the error and stores
+ * filename and line number in a global
+ */
+
+void BPY_Err_Handle(Text *text)
+{
+ PyObject *exception, *err, *tb, *v;
+
+ PyErr_Fetch(&exception, &err, &tb);
+
+ if (!exception && !tb) {
+ printf("FATAL: spurious exception\n");
+ return;
+ }
+
+ strcpy(g_script_error.filename, getName(text));
+
+ if (exception && PyErr_GivenExceptionMatches(exception, PyExc_SyntaxError)) {
+ // no traceback available when SyntaxError
+ PyErr_Restore(exception, err, tb); // takes away reference!
+ PyErr_Print();
+ v = PyObject_GetAttrString(err, "lineno");
+ g_script_error.lineno = PyInt_AsLong(v);
+ Py_XDECREF(v);
+ return;
+ } else {
+ PyErr_NormalizeException(&exception, &err, &tb);
+ PyErr_Restore(exception, err, tb); // takes away reference!
+ PyErr_Print();
+ tb = PySys_GetObject("last_traceback");
+ Py_INCREF(tb);
+
+// check traceback objects and look for last traceback in the
+// same text file. This is used to jump to the line of where the
+// error occured. If the error occured in another text file or module,
+// the last frame in the current file is adressed
+
+ while (1) {
+ v = PyObject_GetAttrString(tb, "tb_next");
+ if (v == Py_None ||
+ strcmp(PyString_AsString(traceback_getFilename(v)), getName(text)))
+ break;
+ Py_DECREF(tb);
+ tb = v;
+ }
+
+ v = PyObject_GetAttrString(tb, "tb_lineno");
+ g_script_error.lineno = PyInt_AsLong(v);
+ Py_XDECREF(v);
+ v = traceback_getFilename(tb);
+ strncpy(g_script_error.filename, PyString_AsString(v), FILENAME_LENGTH);
+ Py_XDECREF(v);
+ Py_DECREF(tb);
+ }
+}
+
+/** Runs a Python string in the global name space of the given dictionary
+ 'globaldict' */
+
+static PyObject *newGlobalDictionary(void)
+{
+ PyObject *d = PyDict_New();
+ PyDict_SetItemString(d, "__builtins__", PyEval_GetBuiltins());
+ PyDict_SetItemString(d, "__name__", PyString_FromString("__main__"));
+ return d;
+}
+
+static void releaseGlobalDictionary(PyObject *d)
+{
+ BPY_debug(("--- CLEAR namespace\n"));
+ PyDict_Clear(d);
+ Py_DECREF(d); // release dictionary
+}
+
+PyObject *BPY_runPython(Text *text, PyObject *globaldict)
+{
+ PyObject *ret;
+ char* buf = NULL;
+
+ if (!text->compiled)
+ {
+ buf = txt_to_buf(text);
+ /* bah, what a filthy hack -- removed */
+ /* strcat(buf, "\n"); */
+ text->compiled = Py_CompileString(buf, getName(text), Py_file_input);
+ MEM_freeN(buf);
+ if (PyErr_Occurred())
+ {
+ BPY_free_compiled_text(text);
+ return 0;
+ }
+ }
+ BPY_debug(("Run Python script \"%s\" ...\n", getName(text)));
+ ret = PyEval_EvalCode(text->compiled, globaldict, globaldict);
+ return ret;
+}
+
+/** This function is executed whenever ALT+PKEY is pressed -> drawtext.c
+ It returns the global namespace dictionary of the script context
+ (which is created newly when CLEAR_NAMESPACE is defined).
+ This may be stored in the SpaceText instance to give control over
+ namespace persistence. Remember that the same script may be executed
+ in several windows..
+ Namespace persistence is desired for scripts that use the GUI and
+ store callbacks to the current script.
+*/
+
+PyObject *BPY_txt_do_python(SpaceText *st)
+{
+ PyObject* d = NULL;
+ PyObject *ret;
+ Text *text = st->text;
+
+ if (!text)
+ {
+ return NULL;
+ }
+
+ /* TODO: make this an option: */
+#ifdef CLEAR_NAMESPACE
+ BPY_debug(("--- enable clear namespace\n"));
+ st->flags |= ST_CLEAR_NAMESPACE;
+#endif
+
+#ifdef CLEAR_NAMESPACE
+ d = newGlobalDictionary();
+#else
+ d = PyModule_GetDict(PyImport_AddModule("__main__"));
+#endif
+
+ ret = BPY_runPython(text, d);
+
+ if (!ret) {
+#ifdef CLEAR_NAMESPACE
+ releaseGlobalDictionary(d);
+#endif
+ BPY_Err_Handle(text);
+ Py_Finalize();
+ initBPythonInterpreter();
+ return NULL;
+ }
+ else
+ Py_DECREF(ret);
+
+
+ /* The following lines clear the global name space of the python
+ * interpreter. This is desired to release objects after execution
+ * of a script (remember that each wrapper object increments the refcount
+ * of the Blender Object.
+
+ * Exception: scripts that use the GUI rely on the
+ * persistent global namespace, so they need a workaround: The namespace
+ * is released when the GUI is exit.
+ * See opy_draw.c:Method_Register()
+ *
+ */
+
+#ifdef CLEAR_NAMESPACE
+ if (st->flags & ST_CLEAR_NAMESPACE) {
+ releaseGlobalDictionary(d);
+ garbage_collect(getGlobal()->main);
+ }
+#endif
+
+ return d;
+}
+
+/****************************************/
+/* SCRIPTLINKS */
+
+static void do_all_scriptlist(ListBase* list, short event)
+{
+ ID *id;
+
+ id = list->first;
+ while (id)
+ {
+ BPY_do_pyscript (id, event);
+ id = id->next;
+ }
+}
+
+void BPY_do_all_scripts(short event)
+{
+ do_all_scriptlist(getObjectList(), event);
+ do_all_scriptlist(getLampList(), event);
+ do_all_scriptlist(getCameraList(), event);
+ do_all_scriptlist(getMaterialList(), event);
+ do_all_scriptlist(getWorldList(), event);
+
+ BPY_do_pyscript(&scene_getCurrent()->id, event);
+}
+
+
+char *event_to_name(short event)
+{
+ switch (event) {
+ case SCRIPT_FRAMECHANGED:
+ return "FrameChanged";
+ case SCRIPT_ONLOAD:
+ return "OnLoad";
+ case SCRIPT_REDRAW:
+ return "Redraw";
+ default:
+ return "Unknown";
+ }
+}
+
+
+void BPY_do_pyscript(ID *id, short event)
+{
+ int i, offset;
+ char evName[24] = "";
+ char* structname = NULL;
+ ScriptLink* scriptlink;
+ PyObject *globaldict;
+
+ switch(GET_ID_TYPE(id)) {
+ case ID_OB: structname= "Object"; break;
+ case ID_LA: structname= "Lamp"; break;
+ case ID_CA: structname= "Camera"; break;
+ case ID_MA: structname= "Material"; break;
+ case ID_WO: structname= "World"; break;
+ case ID_SCE: structname= "Scene"; break;
+ default: return;
+ }
+
+ offset = BLO_findstruct_offset(structname, "scriptlink");
+ if (offset < 0)
+ {
+ BPY_warn(("Internal error, unable to find script link\n"));
+ return;
+ }
+ scriptlink = (ScriptLink*) (((char*)id) + offset);
+
+ /* no script provided */
+ if (!scriptlink->totscript) return;
+
+/* Debugging output */
+ switch (event)
+ {
+ case SCRIPT_FRAMECHANGED:
+ strcpy(evName, "SCRIPT_FRAMECHANGED");
+ BPY_debug(("do_pyscript(%s, %s)\n", getIDName(id), evName));
+ break;
+ case SCRIPT_ONLOAD:
+ strcpy(evName, "SCRIPT_ONLOAD");
+ BPY_debug(("do_pyscript(%s, %s)\n", getIDName(id), evName));
+ break;
+ case SCRIPT_REDRAW:
+ strcpy(evName, "SCRIPT_REDRAW");
+ BPY_debug(("do_pyscript(%s, %s)\n", getIDName(id), evName));
+ break;
+ default:
+ BPY_debug(("do_pyscript(): This should not happen !!!"));
+ break;
+ }
+
+/* END DEBUGGING */
+#ifndef SHAREDMODULE
+ set_scriptlinks(id, event);
+#endif
+ disable_where_script(1);
+ for (i = 0; i < scriptlink->totscript; i++)
+ {
+ if (scriptlink->flag[i] == event && scriptlink->scripts[i])
+ {
+ BPY_debug(("Evaluate script \"%s\" ...\n",
+ getIDName(scriptlink->scripts[i])));
+ script_link_id = id;
+#ifdef CLEAR_NAMESPACE
+ globaldict = newGlobalDictionary();
+#else
+ globaldict = PyModule_GetDict(PyImport_AddModule("__main__"));
+#endif
+ BPY_runPython((Text*) scriptlink->scripts[i], globaldict);
+#ifdef CLEAR_NAMESPACE
+ releaseGlobalDictionary(globaldict);
+#endif
+
+ script_link_id = NULL;
+ BPY_debug(("... done\n"));
+ }
+ }
+#ifndef SHAREDMODULE
+ release_scriptlinks(id);
+#endif
+ disable_where_script(0);
+}
+
+void BPY_clear_bad_scriptlink(ID *id, Text *byebye)
+{
+ ScriptLink* scriptlink;
+ int offset = -1;
+ char* structname = NULL;
+ int i;
+
+ switch (GET_ID_TYPE(id)) {
+ case ID_OB: structname = "Object"; break;
+ case ID_LA: structname = "Lamp"; break;
+ case ID_CA: structname = "Camera"; break;
+ case ID_MA: structname = "Material"; break;
+ case ID_WO: structname = "World"; break;
+ case ID_SCE: structname = "Scene"; break;
+ }
+
+ if (!structname) return;
+
+ offset= BLO_findstruct_offset(structname, "scriptlink");
+
+ if (offset<0) return;
+
+ scriptlink= (ScriptLink *) (((char *)id) + offset);
+
+ for(i=0; i<scriptlink->totscript; i++)
+ if ((Text*)scriptlink->scripts[i] == byebye)
+ scriptlink->scripts[i] = NULL;
+}
+
+void BPY_clear_bad_scriptlist(ListBase *list, Text *byebye)
+{
+ ID *id;
+
+ id= list->first;
+ while (id)
+ {
+ BPY_clear_bad_scriptlink(id, byebye);
+ id= id->next;
+ }
+}
+
+void BPY_clear_bad_scriptlinks(Text *byebye)
+{
+ BPY_clear_bad_scriptlist(getObjectList(), byebye);
+ BPY_clear_bad_scriptlist(getLampList(), byebye);
+ BPY_clear_bad_scriptlist(getCameraList(), byebye);
+ BPY_clear_bad_scriptlist(getMaterialList(), byebye);
+ BPY_clear_bad_scriptlist(getWorldList(), byebye);
+ BPY_clear_bad_scriptlink(&scene_getCurrent()->id, byebye);
+ allqueue(REDRAWBUTSSCRIPT, 0);
+}
+
+void BPY_free_scriptlink(ScriptLink *slink)
+{
+ if (slink->totscript)
+ {
+ if(slink->flag) MEM_freeN(slink->flag);
+ if(slink->scripts) MEM_freeN(slink->scripts);
+ }
+}
+
+void BPY_copy_scriptlink(ScriptLink *scriptlink)
+{
+ void *tmp;
+
+ if (scriptlink->totscript)
+ {
+ tmp = scriptlink->scripts;
+ scriptlink->scripts = MEM_mallocN(sizeof(ID*)*scriptlink->totscript, "scriptlistL");
+ memcpy(scriptlink->scripts, tmp, sizeof(ID*)*scriptlink->totscript);
+
+ tmp = scriptlink->flag;
+ scriptlink->flag = MEM_mallocN(sizeof(short)*scriptlink->totscript, "scriptlistF");
+ memcpy(scriptlink->flag, tmp, sizeof(short)*scriptlink->totscript);
+ }
+}
+
+/*
+ * Python alien graphics format conversion framework
+ *
+ * $Id$
+ *
+ *
+ *
+ */
+
+/* import importloader module with registered importers */
+#include "BPY_extern.h"
+#include "Python.h"
+
+
+int BPY_call_importloader(char *name)
+{
+ PyObject *mod, *tmp, *meth, *args;
+ int i, success = 0;
+
+ init_syspath();
+ mod = PyImport_ImportModule("Converter.importloader");
+ if (mod) {
+ meth = PyObject_GetAttrString(mod, "process"); // new ref
+ args = Py_BuildValue("(s)", name);
+ tmp = PyEval_CallObject(meth, args);
+ Py_DECREF(meth);
+ if (PyErr_Occurred()) {
+ PyErr_Print();
+ }
+
+ if (tmp) {
+ i = PyInt_AsLong(tmp);
+ if (i)
+ success = 1;
+ Py_DECREF(tmp);
+ }
+ Py_DECREF(mod);
+ } else {
+ PyErr_Print();
+ BPY_warn(("couldn't import 'importloader' \n"));
+ }
+ return success;
+}
+
+// more to come...
diff --git a/source/blender/bpython/intern/BPY_main.h b/source/blender/bpython/intern/BPY_main.h
new file mode 100644
index 00000000000..526aa21df8f
--- /dev/null
+++ b/source/blender/bpython/intern/BPY_main.h
@@ -0,0 +1,86 @@
+/* BlenderPython Main routine header *
+ $Id$
+
+ ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version. The Blender
+ Foundation also sells licenses for use in proprietary software under
+ the Blender License. See http://www.blender.org/BL/ for information
+ about this.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ All rights reserved.
+
+ The Original Code is: all of this file.
+
+ Contributor(s): none yet.
+
+ ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+// Note: Functions prefixed with BPY_ are called from blenkernel routines */
+
+
+#include "Python.h" /* The python includes themselves. */
+#include "compile.h" /* to give us PyCodeObject */
+#include "eval.h" /* for PyEval_EvalCode.h */
+
+/* blender stuff */
+#include "MEM_guardedalloc.h"
+#include "BLI_blenlib.h"
+#include "BLI_editVert.h"
+#include "BLI_fileops.h" /* string handling of filenames */
+
+#include "BKE_bad_level_calls.h"
+// #include "BKE_editmesh.h"
+
+#include "BKE_global.h"
+#include "BKE_main.h"
+
+#include "BLO_genfile.h" // for BLO_findstruct_offset only
+#include "BKE_text.h"
+#include "BKE_displist.h"
+#include "BKE_mesh.h"
+#include "BKE_material.h"
+#include "BKE_object.h"
+#include "BKE_screen.h"
+#include "BKE_scene.h"
+#include "BKE_library.h"
+#include "BKE_text.h"
+
+#include "b_interface.h"
+
+/* prototypes of externally used functions are HERE */
+#include "BPY_extern.h"
+
+ /* I just chucked some prototypes
+ * here... not sure where they should
+ * really be. -zr
+ */
+extern struct ID * script_link_id;
+
+extern PyObject *g_blenderdict;
+extern int g_window_redrawn;
+extern int disable_force_draw;
+
+void window_update_curCamera(Object *);
+PyObject *ConstObject_New(void);
+void insertConst(PyObject *dict, char *name, PyObject *item);
+PyObject *Windowmodule_Redraw(PyObject *self, PyObject *args);
+
+char *event_to_name(short event);
+void syspath_append(PyObject *dir);
+void init_syspath(void);
+void set_scriptlinks(ID *id, short event);
+void release_scriptlinks(ID *id);
diff --git a/source/blender/bpython/intern/BPY_modules.h b/source/blender/bpython/intern/BPY_modules.h
new file mode 100644
index 00000000000..98f9170fe9b
--- /dev/null
+++ b/source/blender/bpython/intern/BPY_modules.h
@@ -0,0 +1,47 @@
+/* Prototypes for all fixed module init routines
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * these prototypes and init functions should be homogenized
+ */
+
+extern PyObject *init_blender(void);
+extern PyObject *init_py_nmesh(void);
+extern PyObject *init_py_draw(void);
+extern PyObject *init_py_bgl(void);
+extern PyObject *initWindow(void);
+extern PyObject *initImage(void);
+extern PyObject *init_types(PyObject *dict);
+void init_py_vector(void);
+void init_py_matrix(void);
+void init_Datablockmodules(PyObject *dict);
+void initGUI(void);
+
+
+
diff --git a/source/blender/bpython/intern/BPY_object.c b/source/blender/bpython/intern/BPY_object.c
new file mode 100644
index 00000000000..d0184f9b729
--- /dev/null
+++ b/source/blender/bpython/intern/BPY_object.c
@@ -0,0 +1,499 @@
+/** Object module; access to Object objects in Blender
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "Python.h"
+#include "BPY_macros.h"
+#include "MEM_guardedalloc.h"
+#include "opy_vector.h" /* matrix datatypes */
+
+#include "b_interface.h" // most datatypes
+
+#include "opy_datablock.h"
+
+#include "BLI_arithb.h" /* Mat4Invert */
+
+/* PROTOS */
+
+
+/* ------------------------------------------------------------------------ */
+
+/**************************************************/
+/* Object properties for access by datablock code */
+
+#define NULLFUNC 0
+#define NULLHANDLING 0
+
+/* structure: see opy_datablock.h */
+/* attrname, DNA_membername, type stype, min, max, index,dlist,
+ handlingflag, extra1Ptr, extra2Ptr, extra3Ptr */
+
+DataBlockProperty Object_Properties[]= {
+ {"LocX", "loc[3]", DBP_TYPE_FLO, 0, 0.0, 0.0, {0}, {3, -sizeof(float)}},
+ {"LocY", "loc[3]", DBP_TYPE_FLO, 0, 0.0, 0.0, {1}, {3, -sizeof(float)}},
+ {"LocZ", "loc[3]", DBP_TYPE_FLO, 0, 0.0, 0.0, {2}, {3, -sizeof(float)}},
+ {"loc", "loc[3]", DBP_TYPE_VEC, 0, 3.0},
+
+ {"dLocX", "dloc[3]", DBP_TYPE_FLO, 0, 0.0, 0.0, {0}, {3, -sizeof(float)}},
+ {"dLocY", "dloc[3]", DBP_TYPE_FLO, 0, 0.0, 0.0, {1}, {3, -sizeof(float)}},
+ {"dLocZ", "dloc[3]", DBP_TYPE_FLO, 0, 0.0, 0.0, {2}, {3, -sizeof(float)}},
+ {"dloc", "dloc[3]", DBP_TYPE_VEC, 0, 3.0},
+
+ {"RotX", "rot[3]", DBP_TYPE_FLO, 0, 0.0, 0.0, {0}, {3, -sizeof(float)}},
+ {"RotY", "rot[3]", DBP_TYPE_FLO, 0, 0.0, 0.0, {1}, {3, -sizeof(float)}},
+ {"RotZ", "rot[3]", DBP_TYPE_FLO, 0, 0.0, 0.0, {2}, {3, -sizeof(float)}},
+ {"rot", "rot[3]", DBP_TYPE_VEC, 0, 3.0},
+
+ {"dRotX", "drot[3]", DBP_TYPE_FLO, 0, 0.0, 0.0, {0}, {3, -sizeof(float)}},
+ {"dRotY", "drot[3]", DBP_TYPE_FLO, 0, 0.0, 0.0, {1}, {3, -sizeof(float)}},
+ {"dRotZ", "drot[3]", DBP_TYPE_FLO, 0, 0.0, 0.0, {2}, {3, -sizeof(float)}},
+ {"drot", "drot[3]", DBP_TYPE_VEC, 0, 3.0},
+
+ {"SizeX", "size[3]", DBP_TYPE_FLO, 0, 0.0, 0.0, {0}, {3, -sizeof(float)}},
+ {"SizeY", "size[3]", DBP_TYPE_FLO, 0, 0.0, 0.0, {1}, {3, -sizeof(float)}},
+ {"SizeZ", "size[3]", DBP_TYPE_FLO, 0, 0.0, 0.0, {2}, {3, -sizeof(float)}},
+ {"size", "size[3]", DBP_TYPE_VEC, 0, 3.0},
+
+ {"dSizeX", "dsize[3]", DBP_TYPE_FLO, 0, 0.0, 0.0, {0}, {3, -sizeof(float)}},
+ {"dSizeY", "dsize[3]", DBP_TYPE_FLO, 0, 0.0, 0.0, {1}, {3, -sizeof(float)}},
+ {"dSizeZ", "dsize[3]", DBP_TYPE_FLO, 0, 0.0, 0.0, {2}, {3, -sizeof(float)}},
+ {"dsize", "dsize[3]", DBP_TYPE_VEC, 0, 3.0},
+
+ {"EffX", "effx", DBP_TYPE_FLO, DBP_TYPE_FUN, 0.0, 0.0, {0}, {0}, DBP_HANDLING_FUNC, Object_special_getattr, 0, Object_special_setattr},
+ {"EffY", "effy", DBP_TYPE_FLO, DBP_TYPE_FUN, 0.0, 0.0, {0}, {0}, DBP_HANDLING_FUNC, Object_special_getattr, 0, Object_special_setattr},
+ {"EffZ", "effz", DBP_TYPE_FLO, DBP_TYPE_FUN, 0.0, 0.0, {0}, {0}, DBP_HANDLING_FUNC, Object_special_getattr, 0, Object_special_setattr},
+
+ {"Layer", "layer", DBP_TYPE_INT, DBP_TYPE_FUN, 0.0, 0.0, {0}, {0}, DBP_HANDLING_FUNC, Object_special_getattr, 0, Object_special_setattr},
+ {"layer", "layer", DBP_TYPE_INT, DBP_TYPE_FUN, 0.0, 0.0, {0}, {0}, DBP_HANDLING_FUNC, Object_special_getattr, 0, Object_special_setattr},
+
+ {"parent", "*parent", DBP_TYPE_FUN, 0, 0.0, 0.0, {0}, {0}, 0, 0, get_DataBlock_func},
+ {"track", "*track", DBP_TYPE_FUN, 0, 0.0, 0.0, {0}, {0}, 0, 0, get_DataBlock_func},
+ {"data", "*data", DBP_TYPE_FUN, 0, 0.0, 0.0, {0}, {0}, 0, 0, get_DataBlock_func},
+ {"ipo", "*ipo", DBP_TYPE_FUN, 0, 0.0, 0.0, {0}, {0}, 0, 0, get_DataBlock_func},
+
+ {"mat", "matrix", DBP_TYPE_FUN, 0, 0.0, 0.0, {0}, {0}, DBP_HANDLING_FUNC, Object_special_getattr, newMatrixObject},
+ {"matrix", "matrix", DBP_TYPE_FUN, 0, 0.0, 0.0, {0}, {0}, DBP_HANDLING_FUNC, Object_special_getattr, newMatrixObject},
+
+ {"colbits", "colbits", DBP_TYPE_SHO, 0, 0.0, 0.0},
+ {"drawType", "dt", DBP_TYPE_CHA, 0, 0.0, 0.0},
+ {"drawMode", "dtx", DBP_TYPE_CHA, 0, 0.0, 0.0},
+
+ {NULL}
+};
+
+/*************************/
+/* Object module methods */
+
+DATABLOCK_GET(Objectmodule, object, getObjectList())
+
+char Objectmodule_New_doc[] = "(type) - Add a new object of type 'type' in the current scene";
+static PyObject *Objectmodule_New(PyObject *self, PyObject *args)
+{
+ Object *ob;
+ int type;
+
+ if (!PyArg_ParseTuple(args, "i", &type)) {
+ PyErr_SetString(PyExc_TypeError, "type expected");
+ return 0;
+ }
+ /* add object */
+ ob = object_new(type);
+ return DataBlock_fromData(ob);
+}
+
+static char Objectmodule_getSelected_doc[]=
+"() - Returns a list of selected Objects in the active layer(s)\n\
+The active object is the first in the list, if visible";
+
+static PyObject *Objectmodule_getSelected (PyObject *self, PyObject *args)
+{
+ PyObject *ob, *list;
+ Base *base;
+ Object *tmp;
+
+ list= PyList_New(0);
+
+ if (ActiveBase && SelectedAndLayer(ActiveBase)) {
+ tmp = ActiveObject; /* active object is first in list */
+ if (!tmp) goto no_selection;
+ ob = DataBlock_fromData(tmp);
+ PyList_Append(list, ob); Py_DECREF(ob); // because previous call increfs
+ }
+
+ base = FirstBase;
+ while (base) {
+ if (SelectedAndLayer(base) && base != ActiveBase) {
+ PyObject *ob = DataBlock_fromData(ObjectfromBase(base));
+ if (!ob) goto no_selection;
+ PyList_Append(list, ob); Py_DECREF(ob);
+ }
+ base= base->next;
+ }
+ return list;
+no_selection:
+ Py_DECREF(list);
+ Py_INCREF(Py_None);
+ return Py_None;
+
+}
+
+
+struct PyMethodDef Objectmodule_methods[] = {
+ {"New", Objectmodule_New, METH_VARARGS, Objectmodule_New_doc},
+ // emulation :
+ {"Get", Objectmodule_get, METH_VARARGS, Objectmodule_get_doc}, // XXX
+ {"get", Objectmodule_get, METH_VARARGS, Objectmodule_get_doc},
+ {"getSelected", Objectmodule_getSelected, METH_VARARGS, Objectmodule_getSelected_doc},
+ {NULL, NULL}
+};
+
+/*************************/
+/* Object object methods */
+
+/* Object_get is defined as macro; see opy_datablock.h */
+
+
+static char Object_getType_doc[] = "() - returns Object type";
+
+static PyObject *Object_getType(PyObject *self, PyObject *args)
+{
+ Object *ob= PYBLOCK_AS_OBJECT(self);
+ return Py_BuildValue("i", (short) ob->type);
+}
+
+static char Object_getMatrix_doc[] = "() - returns 4D matrix of object";
+
+static PyObject *Object_getMatrix(PyObject *self, PyObject *args)
+{
+ Object *ob= PYBLOCK_AS_OBJECT(self);
+ return newMatrixObject(ob->obmat);
+}
+
+static char Object_getInverseMatrix_doc[] = "() - returns inverse 4D matrix of object";
+
+static PyObject *Object_getInverseMatrix(PyObject *self, PyObject *args)
+{
+ Object *ob= PYBLOCK_AS_OBJECT(self);
+ float inverse[4][4];
+ Mat4Invert(inverse, ob->obmat);
+ return newMatrixObject(inverse);
+}
+
+static char Object_clrParent_doc[]=
+"(mode = 0, fast = 0) - clears parent object.\n\
+If specified:\n\
+ mode 2: keep object transform\n\
+ fast > 0: don't update scene hierarchy (faster)\n\
+";
+
+static PyObject *Object_clrParent(PyObject *self, PyObject *args)
+{
+ int mode = 0, ret;
+ int fast = 0;
+ Object *ob= PYBLOCK_AS_OBJECT(self);
+
+ BPY_TRY(PyArg_ParseTuple(args, "|ii", &mode, &fast));
+ ret = object_clrParent(ob, mode, fast);
+ return Py_BuildValue("i", ret);
+}
+
+DATABLOCK_ASSIGN_IPO(Object, object) // defines Object_assignIpo
+
+static char Object_makeParent_doc[]=
+"([obj1, obj2, ...], mode = 0, fast = 0) - makes 'self' a parent of the\n\
+objects in the list.\n\
+If specified:\n\
+ mode <> 0: do not clear parent inverse\n\
+ fast <> 0 : do not update scene hierarchy (faster)\n\
+\n\
+If fast is set, you will have to call Scene.getCurrent.update() before\n\
+redraw.";
+
+static PyObject *Object_makeParent(PyObject *self, PyObject *args)
+{
+ int i, ret;
+ PyObject *list;
+ int noninverse = 0;
+ int fast = 0;
+
+ DataBlock *parblk = (DataBlock*) self;
+
+ BPY_TRY(PyArg_ParseTuple(args, "O|ii", &list, &noninverse, &fast));
+ if (!PySequence_Check(list)){
+ PyErr_SetString(PyExc_TypeError, "expects a list of objects");
+ return 0;
+ }
+
+ for (i = 0; i < PySequence_Length(list); i ++) {
+ DataBlock *childblk = (DataBlock *) PySequence_GetItem(list, i);
+
+ if (!DataBlock_Check(childblk)) {
+ PyErr_SetString(PyExc_TypeError, "Object Type expected");
+ return 0;
+ }
+ ret = object_makeParent((Object *) parblk->data, (Object *) childblk->data, noninverse, fast);
+
+ Py_DECREF((PyObject *) childblk); // don't need it anymore
+ if (ret == 0) { // could not parent
+ PyErr_SetString(PyExc_RuntimeError, "parenting failed!");
+ return 0;
+ }
+ }
+
+ if (PyErr_Occurred()) {
+ PyErr_Print();
+ }
+ return Py_BuildValue("i", 1);
+}
+
+static char Object_getMaterials_doc[] = "() - returns a list of object materials";
+
+static PyObject *Object_getMaterials(PyObject *self, PyObject *args)
+{
+ DataBlock *objectblk = (DataBlock*) self;
+ Object *object = PYBLOCK_AS_OBJECT(objectblk);
+ return PyList_fromMaterialList(object->mat, object->totcol);
+}
+
+static char Object_setMaterials_doc[] = "(materialList) - sets object materials";
+
+static PyObject *Object_setMaterials(PyObject *self, PyObject *args)
+{
+ int len;
+ int ret;
+ DataBlock *objectblk = (DataBlock*) self;
+ Object *object = PYBLOCK_AS_OBJECT(objectblk);
+ PyObject *list;
+ Material **matlist;
+
+ BPY_TRY(PyArg_ParseTuple(args, "O!", &PyList_Type, &list));
+ len = PySequence_Length(list);
+ if (len) {
+ matlist = newMaterialList_fromPyList(list);
+ if (!matlist) {
+ PyErr_SetString(PyExc_TypeError,
+ "materialList must be a list of valid materials!");
+ return 0;
+ }
+ ret = object_setMaterials(object, matlist, len);
+ } else {
+ ret = 0;
+ }
+ return Py_BuildValue("i", ret);
+}
+
+static char Object_copy_doc[] = "() - returns a copy of the object, sharing the same data";
+
+static PyObject *Object_copy(PyObject *self, PyObject *args)
+{
+ Object *new;
+
+ DataBlock *objectblk = (DataBlock*) self;
+ Object *object = PYBLOCK_AS_OBJECT(objectblk);
+
+ new = object_copy(object);
+ return DataBlock_fromData(new);
+}
+
+static char Object_shareFrom_doc[] = "(obj) - link data of 'self' with data of 'obj' -- \n\
+only if of same type!";
+
+static PyObject *Object_shareFrom(PyObject *self, PyObject *args)
+{
+ DataBlock *blockA = (DataBlock*) self;
+ DataBlock *blockB;
+ Object *object, *other;
+ int t;
+
+ BPY_TRY(PyArg_ParseTuple(args, "O!", &DataBlock_Type, &blockB));
+
+ if (!DataBlock_isType(blockB, ID_OB)) {
+ PyErr_SetString(PyExc_TypeError, "Argument 1 is not of type 'Object'");
+ return NULL;
+ }
+
+ object = PYBLOCK_AS_OBJECT(blockA);
+ other = PYBLOCK_AS_OBJECT(blockB);
+
+ if (other->type != object->type) {
+ PyErr_SetString(PyExc_TypeError, "Objects are not of same data type");
+ return NULL;
+ }
+ t = object->type;
+ switch (t) {
+ case OB_MESH:
+ return Py_BuildValue("i", object_linkdata(object, other->data));
+ default:
+ PyErr_SetString(PyExc_TypeError, "Type not supported");
+ return NULL;
+ }
+}
+
+/******************/
+/* get & set attr */
+
+static float g_zero_float= 0.0;
+
+/* Object attributes functions which require getter/setter C functions
+ different from the access provided by DataBlock support */
+
+/* get special attributes through datablock property structure */
+
+void *Object_special_getattr(void *vdata, char *name)
+{
+ Object *ob= (Object *) vdata;
+ int scriptflag;
+
+ if (STREQ(name, "layer")) {
+ return &ob->lay;
+
+ } else if (strncmp(name, "eff", 3)==0) {
+ Ika *ika= ob->data;
+
+ if (ob->type==OB_IKA && ika) {
+ if (name[3]=='x') return &ika->effg[0];
+ else if (name[3]=='y') return &ika->effg[1];
+ else if (name[3]=='z') return &ika->effg[2];
+ }
+
+ return &g_zero_float;
+ /* these only for compatibiliy... XXX */
+ } else if (STREQ(name, "matrix")) {
+ scriptflag = during_script();
+ disable_where_script(1);
+ where_is_object(ob);
+ disable_where_script(scriptflag);
+
+ return &ob->obmat;
+ } else if (STREQ(name, "inverse") || STREQ(name, "inverseMatrix")) {
+ return Object_getInverseMatrix(vdata, 0);
+ }
+ /* end compatibility */
+
+ PyErr_SetString(PyExc_AttributeError, name);
+ return NULL;
+}
+
+int Object_special_setattr(void *vdata, char *name, PyObject *py_ob)
+{
+ Object *ob= (Object *) vdata;
+
+ if (STREQ(name, "layer")) {
+ Base *base;
+ int ival;
+
+ if (!PyArg_Parse(py_ob, "i", &ival)) return -1;
+
+ ob->lay= ival;
+ // TODO this is old stuff, maybe move to update routine at end of
+ // script execution ?
+ base= (G.scene->base.first);
+ while (base) {
+ if (base->object == ob) base->lay= ob->lay;
+ base= base->next;
+ }
+ // end TODO
+
+ return 0;
+ } else if (strncmp(name, "eff", 3)==0) {
+ Ika *ika= ob->data;
+ float fval;
+
+ if (!PyArg_Parse(py_ob, "f", &fval)) return -1;
+
+ if (ob->type==OB_IKA && ika) {
+ if (name[3]=='x') ika->effg[0]= fval;
+ else if (name[3]=='y') ika->effg[1]= fval;
+ else if (name[3]=='z') ika->effg[2]= fval;
+
+ itterate_ika(ob);
+ }
+ return 0;
+ }
+
+ PyErr_SetString(PyExc_AttributeError, name);
+ return -1;
+}
+
+
+
+#undef MethodDef
+#define MethodDef(func) _MethodDef(func, Object)
+
+struct PyMethodDef Object_methods[] = {
+ MethodDef(makeParent),
+ MethodDef(copy),
+ MethodDef(shareFrom),
+ MethodDef(getMatrix),
+ MethodDef(getType),
+ MethodDef(getInverseMatrix),
+ MethodDef(clrParent),
+ MethodDef(assignIpo),
+ MethodDef(clrIpo),
+ MethodDef(getMaterials),
+ MethodDef(setMaterials),
+ {NULL, NULL}
+};
+
+#undef BPY_ADDCONST
+#define BPY_ADDCONST(dict, name) insertConst(dict, #name, PyInt_FromLong(OB_##name))
+
+PyObject *initObject(void)
+{
+ PyObject *mod, *dict, *d;
+
+ mod= Py_InitModule(MODNAME(BLENDERMODULE) ".Object", Objectmodule_methods);
+ dict= PyModule_GetDict(mod);
+ d = ConstObject_New();
+ PyDict_SetItemString(dict, "Types", d);
+ BPY_ADDCONST(d, EMPTY);
+ BPY_ADDCONST(d, MESH);
+ BPY_ADDCONST(d, LAMP);
+ BPY_ADDCONST(d, CAMERA);
+
+ d = ConstObject_New();
+ PyDict_SetItemString(dict, "DrawTypes", d);
+ /* dt flags */
+ BPY_ADDCONST(d, BOUNDBOX);
+ BPY_ADDCONST(d, WIRE);
+ BPY_ADDCONST(d, SOLID);
+ BPY_ADDCONST(d, SHADED);
+ BPY_ADDCONST(d, TEXTURE);
+ d = ConstObject_New();
+ PyDict_SetItemString(dict, "DrawModes", d);
+ /* dtx flags */
+ BPY_ADDCONST(d, BOUNDBOX);
+ BPY_ADDCONST(d, AXIS);
+ BPY_ADDCONST(d, TEXSPACE);
+ insertConst(d, "NAME", PyInt_FromLong(OB_DRAWNAME));
+ return mod;
+}
+
diff --git a/source/blender/bpython/intern/BPY_scene.c b/source/blender/bpython/intern/BPY_scene.c
new file mode 100644
index 00000000000..19e992e6bb1
--- /dev/null
+++ b/source/blender/bpython/intern/BPY_scene.c
@@ -0,0 +1,506 @@
+/** Scene module; access to Scene objects in Blender
+ *
+ * Scene objects are no longer DataBlock objects, but referred
+ * by name. This makes it a little slower, but safer - Scene properties
+ * can no longer be accessed after a Scene was deleted.
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "Python.h"
+
+#include "BKE_scene.h"
+#include "BIF_drawscene.h"
+
+#include "BSE_headerbuttons.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_scene_types.h"
+#include "opy_datablock.h"
+#include "b_interface.h"
+
+#include "BPY_macros.h"
+#include "BPY_window.h"
+
+/* DEFINES */
+
+#define CHECK_VALIDSCENE(x) CHECK_VALIDDATA(x, \
+ "Scene was deleted!")
+
+#define PyScene_AsScene(x) \
+ getSceneByName(((PyScene *) x)->name)
+
+/* PROTOS */
+
+PyObject *PyScene_FromScene(Scene *scene);
+
+/************************/
+/* Helper routines */
+
+/* returns a python list of the objects of the Base 'base' */
+
+static PyObject *objectlist_from_base(Base *base)
+{
+ PyObject *pylist= PyList_New(0);
+ PyObject *b;
+
+ while (base) {
+ b = (PyObject *) DataBlock_fromData(base->object);
+ PyList_Append(pylist, b);
+ Py_XDECREF(b); // because PyList_Append increfs!
+ base = base->next;
+ }
+ return pylist;
+}
+
+/* Scene object */
+
+typedef struct {
+ PyObject_VAR_HEAD
+ char name[32];
+} PyScene;
+
+static PyObject *newPyScene(char *name);
+
+/** Returns scene by name. Can be NULL if not found */
+Scene *getSceneByName(char *name)
+{
+ return (Scene *) getFromList(getSceneList(), name);
+}
+
+/************************/
+/* Scene object methods */
+
+static char Scene_getChildren_doc[] =
+"() - returns list of scene children objects";
+
+static PyObject *Scene_getChildren(PyObject *self, PyObject *args)
+{
+ Scene *scene = PyScene_AsScene(self);
+
+ CHECK_VALIDSCENE(scene)
+
+ BPY_TRY(PyArg_ParseTuple(args, ""));
+ return objectlist_from_base(scene->base.first);
+}
+
+static char Scene_getCurrentCamera_doc[] =
+"() - returns current active camera";
+
+static PyObject *Scene_getCurrentCamera(PyObject *self, PyObject *args)
+{
+ Scene *scene = PyScene_AsScene(self);
+ Object *object;
+
+ CHECK_VALIDSCENE(scene)
+
+ object = scene->camera;
+ if (!object) {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+ return DataBlock_fromData(object);
+}
+
+static char Scene_setCurrentCamera_doc[] =
+"(camera) - sets current active camera. 'camera' must be a valid camera\n\
+Object";
+
+static PyObject *Scene_setCurrentCamera(PyObject *self, PyObject *args)
+{
+ Scene *scene = PyScene_AsScene(self);
+ Object *object;
+ DataBlock *block;
+
+ CHECK_VALIDSCENE(scene)
+
+ BPY_TRY(PyArg_ParseTuple(args, "O!", &DataBlock_Type, &block));
+ if (!DataBlock_isType(block, ID_OB)) {
+ PyErr_SetString(PyExc_TypeError, "Object type expected!");
+ return NULL;
+ }
+
+ object = PYBLOCK_AS_OBJECT(block);
+
+ scene->camera = object;
+ if (scene_getCurrent() == scene) // update current scene display
+ window_update_curCamera(object);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+#define SCENE_GETDIR(name, elem) \
+static PyObject *Scene_get##name(PyObject *self, PyObject *args) \
+{ \
+ Scene *scene = PyScene_AsScene(self); \
+ CHECK_VALIDSCENE(scene) \
+ return PyString_FromString(scene->elem); \
+} \
+
+static char Scene_getRenderdir_doc[] =
+"() - returns directory where rendered images are saved to";
+
+SCENE_GETDIR(Renderdir, r.pic)
+
+static char Scene_getBackbufdir_doc[] =
+"() - returns the Backbuffer images location";
+
+SCENE_GETDIR(Backbufdir, r.backbuf)
+
+#define INVALID_FRAME -99999
+
+static char Scene_frameSettings_doc[] =
+"(start, end, current) - sets the scene's frame settings:\n\
+ start : start frame\n\
+ end : end frame\n\
+ current: current frame\n\
+If a frame value is negative, it is not set.\n\
+\n\
+Return value: the current frame settings (start, end, current)";
+
+static PyObject *Scene_frameSettings(PyObject *self, PyObject *args)
+{
+ RenderData *rd = 0;
+ int current = INVALID_FRAME;
+ int start = INVALID_FRAME;
+ int end = INVALID_FRAME;
+ Scene *scene = PyScene_AsScene(self);
+
+ CHECK_VALIDSCENE(scene)
+
+ rd = &scene->r;
+
+ BPY_TRY(PyArg_ParseTuple(args, "|iii", &start, &end, &current));
+ if (start > 0) {
+ rd->sfra = start;
+ }
+ if (end > 0) {
+ rd->efra = end;
+ }
+ if (current > 0) {
+ rd->cfra = current;
+ }
+ return Py_BuildValue("(iii)", rd->sfra, rd->efra, rd->cfra);
+}
+
+
+static char Scene_makeCurrent_doc[] =
+"() - makes Scene the current Scene";
+
+static PyObject *Scene_makeCurrent(PyObject *self, PyObject *args)
+{
+ Scene *scene = PyScene_AsScene(self);
+
+ CHECK_VALIDSCENE(scene)
+
+ set_scene(scene);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static char Scene_copy_doc[] =
+"(duplicate_objects = 1) - make a copy of a scene\n\
+'The optional argument defines, how the scene's children objects are\n\
+duplicated:\n\
+\n\
+0: Link Objects\n\
+1: Link Object data\n\
+2: Full Copy";
+
+static PyObject *Scene_copy(PyObject *self, PyObject *args)
+{
+ Scene *scene = PyScene_AsScene(self);
+
+ int dup_objects = 0;
+
+ CHECK_VALIDSCENE(scene)
+
+ BPY_TRY(PyArg_ParseTuple(args, "|i", &dup_objects));
+
+ return PyScene_FromScene(copy_scene(scene, dup_objects));
+}
+
+static char Scene_update_doc[]= "() - Update scene\n\
+This function explicitely resorts the base list of a newly created object\n\
+hierarchy.";
+
+static PyObject *Scene_update(PyObject *self, PyObject *args)
+{
+ Scene *scene = PyScene_AsScene(self);
+
+ CHECK_VALIDSCENE(scene)
+
+ BPY_TRY(PyArg_ParseTuple(args, ""));
+ sort_baselist(scene);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static char Scene_link_doc[]= "(object) - Links object to scene";
+
+/** Links an object with a scene */
+static PyObject *Scene_link(PyObject *self, PyObject *args)
+{
+ DataBlock *block;
+ Object *object;
+ Scene *scene = PyScene_AsScene(self);
+ CHECK_VALIDSCENE(scene)
+
+ BPY_TRY(PyArg_ParseTuple(args, "O!", &DataBlock_Type, &block));
+ if (DataBlock_type(block) != ID_OB) {
+ PyErr_SetString(PyExc_TypeError, "link: invalid Object type");
+ return NULL;
+ }
+ object = PYBLOCK_AS_OBJECT(block);
+ if (!scene_linkObject(scene, object))
+ {
+ PyErr_SetString(PyExc_RuntimeError, "Object already in scene!");
+ return NULL;
+ }
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+/** unlinks (removes) an object from a scene */
+
+static char Scene_unlink_doc[]= "(object) - Unlinks object from scene";
+
+static PyObject *Scene_unlink(PyObject *self, PyObject *args)
+{
+ PyObject *retval;
+ DataBlock *block;
+ Object *object;
+ Scene *scene = PyScene_AsScene(self);
+ CHECK_VALIDSCENE(scene)
+
+ BPY_TRY(PyArg_ParseTuple(args, "O!", &DataBlock_Type, &block));
+ if (DataBlock_type(block) != ID_OB) {
+ PyErr_SetString(PyExc_TypeError, "unlink: invalid Object type");
+ return NULL;
+ }
+ object = PYBLOCK_AS_OBJECT(block);
+
+ if (!scene_unlinkObject(scene, object))
+ retval = Py_BuildValue("i", 0);
+ else
+ retval = Py_BuildValue("i", 1);
+ Py_INCREF(retval);
+ return retval;
+}
+
+#undef MethodDef
+#define MethodDef(func) _MethodDef(func, Scene)
+
+/* these are the scene object methods */
+static struct PyMethodDef Scene_methods[] = {
+ MethodDef(copy),
+ MethodDef(link),
+ MethodDef(unlink),
+ MethodDef(getChildren),
+ MethodDef(getCurrentCamera),
+ MethodDef(setCurrentCamera),
+ MethodDef(getRenderdir),
+ MethodDef(getBackbufdir),
+ MethodDef(frameSettings),
+ MethodDef(makeCurrent),
+ MethodDef(update),
+ {NULL, NULL}
+};
+
+static void PyScene_dealloc(PyObject *self)
+{
+ PyMem_DEL(self);
+}
+
+static PyObject *PyScene_getattr(PyObject *self, char *attr)
+{
+ Scene *scene;
+ if (!strcmp(attr, "name")) {
+ return PyString_FromString(((PyScene *) self)->name);
+ } else if (!strcmp(attr, "users")) {
+ scene = PyScene_AsScene(self);
+ return PyInt_FromLong(getUsers(scene));
+ } else if (!strcmp(attr, "block_type")) {
+ return Py_BuildValue("s", "Scene");
+ }
+ return Py_FindMethod(Scene_methods, (PyObject *) self, attr);
+}
+
+PyObject *PyScene_repr(PyScene *self)
+{
+ char s[256];
+ Scene *scene = PyScene_AsScene(self);
+ if (scene)
+ sprintf (s, "[Scene %.32s]", getName(scene));
+ else
+ sprintf (s, "[deleted Scene]");
+ return Py_BuildValue("s", s);
+}
+
+static PyTypeObject PyScene_Type = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "Scene", /*tp_name*/
+ sizeof(PyScene), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ (destructor) PyScene_dealloc, /*tp_dealloc*/
+ (printfunc)0, /*tp_print*/
+ (getattrfunc)PyScene_getattr, /*tp_getattr*/
+ (setattrfunc)0, /*tp_setattr*/
+ (cmpfunc)0, /*tp_compare*/
+ (reprfunc)PyScene_repr, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ (hashfunc)0, /*tp_hash*/
+ (ternaryfunc)0, /*tp_call*/
+ (reprfunc)0, /*tp_str*/
+
+ /* Space for future expansion */
+ 0L,0L,0L,0L,
+ 0 /* Documentation string */
+};
+
+static PyObject *newPyScene(char *name)
+{
+ PyScene *scene = PyObject_NEW(PyScene, &PyScene_Type);
+ strncpy(scene->name, name, 31);
+ return (PyObject *) scene;
+}
+
+PyObject *PyScene_FromScene(Scene *scene)
+{
+ if (scene)
+ return newPyScene(getName(scene));
+ else {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+}
+
+PyObject *PyScene_FromVoid(void *scene)
+{
+ return PyScene_FromScene((Scene *) scene);
+}
+
+
+/************************/
+/* Scene module methods */
+
+static char Scenemodule_get_doc[] =
+"(name = None) - get Scene 'name' from Blender, if 'name' specified.\n\
+Otherwise, a list of all Scenes is returned";
+
+static PyObject *Scenemodule_get(PyObject *self, PyObject *args)
+{
+ char *name= NULL;
+ BPY_TRY(PyArg_ParseTuple(args, "|s", &name));
+
+ if (name) {
+ return PyScene_FromScene(getSceneByName(name));
+ } else {
+ return BPY_PyList_FromIDList(getSceneList(), PyScene_FromVoid);
+ }
+}
+
+static char Scenemodule_New_doc[] =
+"(name = None) - Create new scene with (optionally given)\n\
+name.";
+
+static PyObject *Scenemodule_New(PyObject *self, PyObject *args)
+{
+ Scene *scene;
+ char *name = "Scene";
+
+ BPY_TRY(PyArg_ParseTuple(args, "|s", &name));
+ scene = add_scene(name);
+ return newPyScene(name);
+}
+
+static char Scenemodule_getCurrent_doc[] =
+"() - returns currently active Scene";
+
+static PyObject *Scenemodule_getCurrent(PyObject *self, PyObject *args)
+{
+ return newPyScene(getName(scene_getCurrent()));
+}
+
+static char Scenemodule_unlink_doc[] =
+"(scene) - deletes the Scene 'scene' from Blender\n\
+The Scene must be empty before removing it";
+
+static PyObject *Scenemodule_unlink(PyObject *self, PyObject *args)
+{
+ PyObject *sceneobj;
+ Scene *scene;
+
+ if(!PyArg_ParseTuple(args, "O!", &PyScene_Type, &sceneobj)) {
+ PyErr_SetString(PyExc_TypeError, "Scene object expected!");
+ return NULL;
+ }
+
+ scene = PyScene_AsScene(sceneobj);
+ free_libblock(getSceneList(), scene);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+
+/*****************/
+/* METHOD TABLES */
+
+/* these are the module methods */
+
+#undef MethodDef
+#define MethodDef(func) _MethodDef(func, Scenemodule)
+
+struct PyMethodDef Scenemodule_methods[] = {
+ MethodDef(get),
+ MethodDef(getCurrent),
+ MethodDef(New),
+ MethodDef(unlink),
+ {NULL, NULL}
+};
+
+PyObject *initScene()
+{
+ PyObject *mod;
+ PyScene_Type.ob_type = &PyType_Type;
+ mod= Py_InitModule(MODNAME(BLENDERMODULE) ".Scene",
+ Scenemodule_methods);
+ return mod;
+}
+
+
diff --git a/source/blender/bpython/intern/BPY_text.c b/source/blender/bpython/intern/BPY_text.c
new file mode 100644
index 00000000000..855e12a6b9f
--- /dev/null
+++ b/source/blender/bpython/intern/BPY_text.c
@@ -0,0 +1,295 @@
+/** Text buffer module; access to Text buffers in Blender
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 ownership relations of a Text buffer are in Blender pretty clear:
+ * The Text editor is ALWAYS the container for all text objects.
+ * Currently, the Text object is implemented as a free object though, as
+ * the ownership of a Text might change in future. The reference counting of
+ * a Text object IN BLENDER is not really maintained though (for the above ownership
+ * reason).
+ * This introduces a problem if a Text object is accessed after it was actually
+ * deleted. Currently, a 'guard' is implemented for access after deletion INSIDE
+ * A SCRIPT. The Blender GUI is not aware of the wrapper though, so if a Text buffer
+ * is cleared while the script is accessing the wrapper, bad results are expected.
+ * BUT: This currently can not happen, unless a Python script is running in the
+ * background as a separate thread...
+ *
+ * TODO:
+ *
+ * either a):
+ * figure out ownership and implement each access to the text buffer by
+ * name and not by reference (pointer). This will require quite some additions
+ * in the generic DataBlock access (opy_datablock.c)
+ *
+ * or b):
+ * implement reference counting for text buffers properly, so that a deletion
+ * of a text buffer by the GUI does not result in a release of the actual
+ * Text object, but by a DECREF. The garbage collector (or wrapper deletion method)
+ * will then free the Text object.
+ *
+ * To be discussed and evaluated.
+ *
+ * $Id$
+ *
+ */
+
+
+#include "Python.h"
+#include "stringobject.h"
+
+#include "BPY_macros.h"
+#include "BKE_text.h"
+#include "BIF_drawtext.h"
+#include "DNA_text_types.h"
+#include "BPY_extern.h"
+#include "BKE_sca.h"
+
+#include "b_interface.h"
+#include "opy_datablock.h"
+
+DATABLOCK_GET(Textmodule, text object, getTextList())
+
+#define CHECK_VALIDTEXT(x) CHECK_VALIDDATA(x, \
+ "Text was deleted; illegal access!")
+
+#define OFF 1
+
+static char Textmodule_New_doc[] =
+"(name = None, follow = 0) - Create new text buffer with (optionally given)\n\
+name.\n\
+If 'follow' == 1, the text display always follows the cursor";
+
+static PyObject *Textmodule_New(PyObject *self, PyObject *args)
+{
+ Text *text;
+ PyObject *textobj;
+ PyObject *name = NULL;
+ int follow = 0;
+
+ text = add_empty_text();
+ BPY_TRY(PyArg_ParseTuple(args, "|O!i", &PyString_Type, &name, &follow));
+ textobj = DataBlock_fromData(text);
+ if (follow) {
+ text->flags |= TXT_FOLLOW;
+ }
+ if (name) {
+ DataBlock_setattr(textobj, "name", name);
+ }
+ return textobj;
+}
+
+static char Textmodule_unlink_doc[] =
+"(text) - remove text object 'text' from the text window";
+
+/** This function removes the text entry from the text editor.
+ * The text is not freed here, but inside the garbage collector
+ */
+
+static PyObject *Textmodule_unlink(PyObject *self, PyObject *args)
+{
+ PyObject *textobj;
+ Text *text;
+
+ BPY_TRY(PyArg_ParseTuple(args, "O!", &DataBlock_Type, &textobj));
+ if (!DataBlock_isType((DataBlock *) textobj, ID_TXT)) {
+ PyErr_SetString(PyExc_TypeError, "Text object expected!");
+ return NULL;
+ }
+
+ text = PYBLOCK_AS_TEXT(textobj);
+ BPY_clear_bad_scriptlinks(text);
+ free_text_controllers(text);
+ unlink_text(text);
+ /* We actually should not free the text object here, but let the
+ * __del__ method of the wrapper do the job. This would require some
+ * changes in the GUI code though..
+ * So we mark the wrapper as invalid by setting wrapper->data = 0 */
+ free_libblock(getTextList(), text);
+ MARK_INVALID(textobj);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+
+/* these are the module methods */
+struct PyMethodDef Textmodule_methods[] = {
+ {"get", Textmodule_get, METH_VARARGS, Textmodule_get_doc},
+ {"New", Textmodule_New, METH_VARARGS, Textmodule_New_doc},
+ {"unlink", Textmodule_unlink, METH_VARARGS, Textmodule_unlink_doc},
+ {NULL, NULL}
+};
+
+// Text object properties
+
+DataBlockProperty Text_Properties[]= {
+ {NULL}
+};
+
+/* This is uncommented only for an example on how (probably) not to
+ * do it :-)
+ * It's a bad idea in this case to have a wrapper object destroy its wrapped object
+ * because checks have to be done whether the wrapper is still accessed after
+ * the wrapped objects deletion.
+ * Better: unlink the object from it's owner: Blender.Text.unlink(text)
+ * That way the object is not yet freed, but its refcount set to 0.
+ * The garbage collector takes care of the rest..
+ * But it has to be made sure that the wrapper object is no longer kept around
+ * after the script ends.
+ *
+
+static char Text_delete_doc[] =
+"() - delete text from Text window";
+
+static PyObject *Text_delete(PyObject *self, PyObject *args)
+{
+ Text *text = PYBLOCK_AS_TEXT(self);
+ // we have to check for validity, as the Text object is only a
+ // descriptor...
+ CHECK_VALIDTEXT(text)
+ BPY_TRY(PyArg_ParseTuple(args, ""));
+ BPY_clear_bad_scriptlinks(text);
+ free_text_controllers(text);
+ unlink_text(text);
+ free_libblock(&getGlobal()->main->text, text);
+ ((DataBlock *) self)->data = NULL;
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+*/
+
+/** This method gets called on the wrapper objects deletion.
+ * Here we release the Text object if its refcount is == 0
+
+ -- CURRENTLY UNCOMMENTED -- needs change in Blender kernel..
+
+static PyObject *Text_del(PyObject *self, PyObject *args)
+{
+ Text *text = PYBLOCK_AS_TEXT(self);
+ if (BOB_REFCNT((ID *) text) == 0) {
+ free_libblock(&getGlobal()->main->text, text);
+ }
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+*/
+
+static char Text_clear_doc[] =
+"() - clear the text buffer";
+
+static PyObject *Text_clear(PyObject *self, PyObject *args)
+{
+ Text *text = PYBLOCK_AS_TEXT(self);
+ int oldstate;
+ CHECK_VALIDTEXT(text)
+
+ oldstate = txt_get_undostate();
+ txt_set_undostate(OFF);
+ txt_sel_all(text);
+ txt_cut_sel(text);
+ txt_set_undostate(oldstate);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static char Text_set_doc[] =
+"(name, val) - set attribute name to val";
+
+static PyObject *Text_set(PyObject *self, PyObject *args)
+{
+ int ival;
+ char *attr;
+ Text *text = PYBLOCK_AS_TEXT(self);
+
+ BPY_TRY(PyArg_ParseTuple(args, "si", &attr, &ival));
+ if (STREQ("follow_cursor", attr)) {
+ if (ival) {
+ text->flags |= TXT_FOLLOW;
+ } else {
+ text->flags &= TXT_FOLLOW;
+ }
+ }
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static char Text_write_doc[] =
+"(line) - append string 'line' to the text buffer";
+
+static PyObject *Text_write(PyObject *self, PyObject *args)
+{
+ char *str;
+ Text *text = PYBLOCK_AS_TEXT(self);
+ int oldstate;
+
+ CHECK_VALIDTEXT(text)
+
+ BPY_TRY(PyArg_ParseTuple(args, "s", &str));
+ oldstate = txt_get_undostate();
+ txt_insert_buf(text, str);
+ txt_move_eof(text, 0);
+ txt_set_undostate(oldstate);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static char Text_asLines_doc[] =
+"() - returns the lines of the text buffer as list of strings";
+
+static PyObject *Text_asLines(PyObject *self, PyObject *args)
+{
+ TextLine *line;
+ PyObject *list, *ob;
+ Text *text = (Text *) ((DataBlock *) self)->data;
+
+ CHECK_VALIDTEXT(text)
+
+ line = text->lines.first;
+ list= PyList_New(0);
+ while (line) {
+ ob = Py_BuildValue("s", line->line);
+ PyList_Append(list, ob);
+ line = line->next;
+ }
+ return list;
+}
+
+/* these are the text object methods */
+struct PyMethodDef Text_methods[] = {
+ {"clear", Text_clear, METH_VARARGS, Text_clear_doc},
+ {"write", Text_write, METH_VARARGS, Text_write_doc},
+ {"set", Text_set, METH_VARARGS, Text_set_doc},
+ {"asLines", Text_asLines, METH_VARARGS, Text_asLines_doc},
+ {NULL, NULL}
+};
+
diff --git a/source/blender/bpython/intern/BPY_tools.c b/source/blender/bpython/intern/BPY_tools.c
new file mode 100644
index 00000000000..5a2c483607c
--- /dev/null
+++ b/source/blender/bpython/intern/BPY_tools.c
@@ -0,0 +1,106 @@
+/* python API tool subroutines
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "Python.h"
+#include "BKE_global.h"
+#include "BPY_tools.h"
+
+/* These should all have BPY prefixes later on */
+
+PyObject *BPY_incr_ret(PyObject *ob) {
+ Py_INCREF(ob);
+ return ob;
+}
+
+PyObject *BPY_err_ret_ob(PyObject *type, char *err) {
+ PyErr_SetString(type, err);
+ return NULL;
+}
+
+int py_err_ret_int(PyObject *type, char *err) {
+ PyErr_SetString(type, err);
+ return -1;
+}
+
+int BPY_check_sequence_consistency(PyObject *seq, PyTypeObject *against)
+{
+ PyObject *ob;
+ int len= PySequence_Length(seq);
+ int i;
+
+ for (i=0; i<len; i++) {
+ ob= PySequence_GetItem(seq, i);
+ if (ob->ob_type != against) {
+ Py_DECREF(ob);
+ return 0;
+ }
+ Py_DECREF(ob);
+ }
+ return 1;
+}
+
+int BPY_parsefloatvector(PyObject *vec, float *ptr, int n)
+{
+ int i;
+ PyObject *o, *p;
+ char errstring[80];
+
+ if (PyArg_ParseTuple(vec, "ff|f", &ptr[0], &ptr[1], &ptr[2]))
+ return 0;
+ if (PyArg_Parse(vec, "O", &p)) {
+ if (PySequence_Check(p) && PySequence_Length(p) == n ) {
+ for (i = 0; i < n; i++) {
+ o = PySequence_GetItem(vec, i);
+ if (PyFloat_Check(o)) {
+ ptr[i] = PyFloat_AsDouble(o);
+ Py_DECREF(o);
+ } else {
+ Py_DECREF(o);
+ return py_err_ret_int(PyExc_AttributeError, "vector assignment wants floats");
+ }
+ }
+ return 0;
+ }
+ }
+
+ if (!PySequence_Check(p)) {
+ printf("invalid sequence");
+ }
+
+ /* errors: */
+ sprintf(errstring, "Float vector tuple of length %d expected", n);
+ return py_err_ret_int(PyExc_AttributeError, errstring);
+}
+
+
+
+
diff --git a/source/blender/bpython/intern/BPY_tools.h b/source/blender/bpython/intern/BPY_tools.h
new file mode 100644
index 00000000000..902c15686f0
--- /dev/null
+++ b/source/blender/bpython/intern/BPY_tools.h
@@ -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 *****
+ */
+/* tools.c */
+extern PyObject *BPY_incr_ret (PyObject *ob);
+extern PyObject *BPY_err_ret_ob (PyObject *type, char *err);
+extern int py_err_ret_int (PyObject *type, char *err);
+extern int BPY_check_sequence_consistency (PyObject *seq, PyTypeObject *against);
+extern int BPY_parsefloatvector(PyObject *vec, float *ptr, int n);
diff --git a/source/blender/bpython/intern/BPY_types.h b/source/blender/bpython/intern/BPY_types.h
new file mode 100644
index 00000000000..217275f6e10
--- /dev/null
+++ b/source/blender/bpython/intern/BPY_types.h
@@ -0,0 +1,39 @@
+/* $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * API defined Object types
+ */
+
+extern PyTypeObject PyIpoCurve_Type, PyBezTriple_Type;
+extern PyTypeObject Button_Type, Buffer_Type;
+extern PyTypeObject NMesh_Type, NMFace_Type, NMVert_Type, NMCol_Type;
+extern PyTypeObject Vector_Type, Matrix_Type;
+
+extern PyTypeObject DataBlock_Type;
+extern struct PyMethodDef Null_methods[];
diff --git a/source/blender/bpython/intern/BPY_window.h b/source/blender/bpython/intern/BPY_window.h
new file mode 100644
index 00000000000..7a76dbd2e57
--- /dev/null
+++ b/source/blender/bpython/intern/BPY_window.h
@@ -0,0 +1,33 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 window_update_curCamera(Object *camera);
+
diff --git a/source/blender/bpython/intern/Makefile b/source/blender/bpython/intern/Makefile
new file mode 100644
index 00000000000..cb67e195aa8
--- /dev/null
+++ b/source/blender/bpython/intern/Makefile
@@ -0,0 +1,75 @@
+#
+# $Id$
+#
+# ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version. The Blender
+# Foundation also sells licenses for use in proprietary software under
+# the Blender License. See http://www.blender.org/BL/ for information
+# about this.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2001-2002 by 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 = bpython
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+ifeq ($(OS),$(findstring $(OS), "beos darwin freebsd linux openbsd solaris windows"))
+ CFLAGS += -funsigned-char
+endif
+
+CFLAGS += $(LEVEL_1_C_WARNINGS)
+
+CPPFLAGS += -DFUTURE_PYTHON_API # see api.h for configuration
+#CPPFLAGS += -DNO_RELEASE # see api.h for configuration
+
+# OpenGL and Python
+CPPFLAGS += -I$(OPENGL_HEADERS)
+CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION)
+CPPFLAGS += -I$(NAN_BMFONT)/include/
+
+# Reference to the types in makesdna and imbuf
+CPPFLAGS += -I../../makesdna
+CPPFLAGS += -I../../imbuf
+# This mod uses the BLI and BLO module
+CPPFLAGS += -I../../blenlib
+CPPFLAGS += -I../../blenlib/intern
+CPPFLAGS += -I$(NAN_BSP)/include # BSP includes
+CPPFLAGS += -I../../blenkernel
+CPPFLAGS += -I../../blenloader
+CPPFLAGS += -I../../bpython/include/
+# also avi is used
+CPPFLAGS += -I../../avi
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+
+# we still refer to /include a bit...
+CPPFLAGS += -I../../include
+
+# to include the render stuff:
+CPPFLAGS += -I../../render/extern/include
+
+# path to our own external headerfiles
+CPPFLAGS += -I..
+
diff --git a/source/blender/bpython/intern/README b/source/blender/bpython/intern/README
new file mode 100644
index 00000000000..c91e284cd27
--- /dev/null
+++ b/source/blender/bpython/intern/README
@@ -0,0 +1,22 @@
+Python API library // strubi@blender.nl
+------------------
+
+
+NEW:
+ Several frozen Python byte code modules are now included in the
+ API under libfrozen.a. libbpython must be linked with libfrozen.a
+ from now on.
+
+source files:
+
+py_*.c: library files of Jan Walters API. Might undergo major replacements / surgery
+ later.
+opy_*: the 'old' python API code. In fact quite nice and functional... -- needs
+ splitting up in API/ interfacing part.
+BPY_*: these are the future API prefixes (newly written stuff that should be
+ Blender 3.0 compliant... -- no interface calls inside)
+ This is not YET quite true, for convenience, it still contains some direct
+ Blender access.
+b_* : Blender interfacing / tools -- may contain dirty access hacks for blender
+ datastructures..
+
diff --git a/source/blender/bpython/intern/api.h b/source/blender/bpython/intern/api.h
new file mode 100644
index 00000000000..369e6175918
--- /dev/null
+++ b/source/blender/bpython/intern/api.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 *****
+ *
+ *
+ * This headerfile defines the API status.
+ * Parts of the API can be compiled as dynamic module for testing --
+ * see Makefile
+ */
+
+#undef EXPERIMENTAL /* undefine this for release, please :-) */
+
+/* Uncomment this if you want to have the new blender module
+compiled static into Blender :*/
+/* #define SHAREDMODULE -- put into Makefile */
+
+/* API configuration -- define in Makefile */
+
+#ifdef SHAREDMODULE
+ #define BLENDERMODULE _Blender
+#elif defined(CURRENT_PYTHON_API)
+ #define BLENDERMODULE Blender
+#elif defined(FUTURE_PYTHON_API)
+ #define BLENDERMODULE _Blender
+#else // FALLBACK
+ #define BLENDERMODULE Blender
+#endif
+
+#define SUBMODULE(mod) (MODNAME(BLENDERMODULE) "." #mod)
+
+/* this macro defines the init routine for dynamically loaded modules;
+example:
+
+void INITMODULE(BLENDERMODULE) -> void initBlender(void)
+*/
+
+#define _INITMODULE(x) init##x
+#define INITMODULE(x) _INITMODULE(x)
+
+/* MODNAME(MODULE) stringifies the module definition, example:
+MODNAME(BLENDERMODULE) -> "_Blender"
+*/
+
+#define _MODNAME(x) #x
+#define MODNAME(x) _MODNAME(x)
+
+// module configuration -- TODO: this should be set later from the Makefile...
+#if defined(__FreeBSD__) || defined(__linux__) || defined (__sgi) || defined(__sparc)
+#define STATIC_TEXTTOOLS 1
+#endif
+
+
+#define USE_NMESH 1 // still use NMesh structure for <mesh object>.data
+#define CLEAR_NAMESPACE // undefine this if you still want the old dirty global
+ // namespace shared by ALL scripts.
+
+
+// experimental sh*t:
+#ifdef EXPERIMENTAL
+ #undef USE_NMESH
+#endif
diff --git a/source/blender/bpython/intern/b_import.c b/source/blender/bpython/intern/b_import.c
new file mode 100644
index 00000000000..e490ee82338
--- /dev/null
+++ b/source/blender/bpython/intern/b_import.c
@@ -0,0 +1,191 @@
+/* $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+
+ Customized Blender import module, Sandbox model (TODO)
+
+ TODO for Sandbox:
+ - only allow builtin modules to be imported
+ - only allow file read/write from certain directories
+ - alternative: override file read/write with popup requester
+
+ main routine:
+ init_ourImport();
+
+*/
+
+
+
+#include "DNA_text_types.h"
+#include "Python.h"
+#include "import.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_library.h"
+#include "BKE_text.h"
+
+#include "BLI_blenlib.h" // mallocs
+
+#include "BPY_macros.h"
+#include "BPY_main.h"
+
+#include "b_import.h"
+
+
+/* ---------------------------------------------------------------------------- */
+
+PyObject *importText(char *name)
+{
+ Text *text;
+ char txtname[IDNAME];
+ char *buf = NULL;
+
+
+ // TODO debug for too long names !
+
+ strncpy(txtname, name, IDNAME-4);
+ strcat(txtname, ".py");
+
+ text = (Text*) getGlobal()->main->text.first;
+ while(text)
+ {
+ if (STREQ(getName(text), txtname))
+ break;
+ text = text->id.next;
+ }
+ if (!text) {
+ return NULL;
+ }
+
+ if (!text->compiled) {
+ buf = txt_to_buf(text);
+ text->compiled = Py_CompileString(buf, getName(text), Py_file_input);
+ MEM_freeN(buf);
+ if (PyErr_Occurred())
+ {
+ PyErr_Print();
+ BPY_free_compiled_text(text);
+ return NULL;
+ }
+ }
+ BPY_debug(("import from TextBuffer: %s\n", txtname));
+ return PyImport_ExecCodeModule(name, text->compiled);
+}
+
+PyObject *blender_import(PyObject *self, PyObject *args)
+{
+ PyObject *exception, *err, *tb;
+ char *name;
+ PyObject *globals = NULL, *locals = NULL, *fromlist = NULL;
+ PyObject *m;
+#ifdef PY_SANDBOXTEST
+ PyObject *l, *n;
+#endif
+
+ if (!PyArg_ParseTuple(args, "s|OOO:bimport",
+ &name, &globals, &locals, &fromlist))
+ return NULL;
+
+#ifdef PY_SANDBOXTEST
+ /* check for builtin modules */
+ m = PyImport_AddModule("sys");
+ l = PyObject_GetAttrString(m, "builtin_module_names");
+ n = PyString_FromString(name);
+
+ if (PySequence_Contains(l, n)) {
+ Py_DECREF(l);
+ m = PyImport_ImportModuleEx(name, globals, locals, fromlist);
+ return m;
+ } else {
+ /* TODO check for external python toolbox modules */
+
+ PyErr_Format(PyExc_ImportError,
+ "Import of external Module %.40s not allowed.\n\
+Please disable security in the UserButtons", name);
+ Py_DECREF(l);
+ return NULL;
+ }
+
+#else
+ m = PyImport_ImportModuleEx(name, globals, locals, fromlist);
+ if (m)
+ return m;
+ else
+ PyErr_Fetch(&exception, &err, &tb); // restore exception for probable later use
+
+ m = importText(name);
+ if (m) { // found module, ignore above exception
+ PyErr_Clear();
+ Py_XDECREF(exception); Py_XDECREF(err); Py_XDECREF(tb);
+ printf("imported from text buffer..\n");
+ } else {
+ PyErr_Restore(exception, err, tb);
+ }
+ return m;
+#endif
+}
+static PyMethodDef bimport[] = {
+ { "blimport", blender_import, METH_VARARGS,
+ "our own import"}
+};
+
+
+/*
+PyObject *override_method(PyObject *module, char *methname, PyMethodDef *newcfunc)
+{
+ PyObject *d;
+ PyObject *old;
+ PyObject *pycfunc;
+
+
+ d = PyModule_GetDict(module);
+ old = PyDict_GetItemString(module, methname);
+ if (!old)
+ return NULL;
+
+ pycfunc = PyCFunction_New(newcfunc, NULL);
+ PyDict_SetItemString(d, methname, pycfunc);
+
+ return old;
+}
+*/
+
+
+/* this overrides the built in __import__ function
+with our customized importer */
+void init_ourImport(void)
+{
+ PyObject *m, *d;
+ PyObject *import = PyCFunction_New(bimport, NULL);
+
+ m = PyImport_AddModule("__builtin__");
+ d = PyModule_GetDict(m);
+ PyDict_SetItemString(d, "__import__", import);
+}
+
diff --git a/source/blender/bpython/intern/b_import.h b/source/blender/bpython/intern/b_import.h
new file mode 100644
index 00000000000..2bc191942ca
--- /dev/null
+++ b/source/blender/bpython/intern/b_import.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 *****
+ */
+/* b_import.c */
+PyObject *importText (char *name);
+PyObject *blender_import (PyObject *self, PyObject *args);
+void init_ourImport (void);
diff --git a/source/blender/bpython/intern/b_interface.c b/source/blender/bpython/intern/b_interface.c
new file mode 100644
index 00000000000..ec89680ad91
--- /dev/null
+++ b/source/blender/bpython/intern/b_interface.c
@@ -0,0 +1,753 @@
+/** Interfacing with Blender
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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$
+ *
+ * This code is currently messy and an attempt to restructure
+ * some Blender kernel level code.
+ * Hopefully a template for a future C-API...
+ *
+ *
+ */
+
+
+#include "BLI_blenlib.h" // mallocs
+#include "BLI_arithb.h"
+
+#include "BKE_library.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_object.h"
+#include "BKE_mesh.h"
+#include "BKE_ipo.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "Python.h"
+#include "BPY_macros.h"
+#include "structmember.h"
+
+#include "BDR_editobject.h"
+
+#include "b_interface.h"
+
+/************************************************************************
+ * Generic low level routines
+ *
+ */
+
+/** This just returns a pointer to the global struct.
+ *
+ * Mainly introduced for debugging purposes..
+ *
+ */
+
+Global *getGlobal(void)
+{
+ return &G;
+}
+
+/** define list getters:
+ These functions return a linked list pointer (ListBase *) from the global
+ Blender-object list.
+
+ Example:
+ oblist = getObjectList();
+ firstobject = oblist->first;
+
+ */
+
+/*
+DEF_GETLIST(Scene, scene)
+DEF_GETLIST(Object, object)
+DEF_GETLIST(Mesh, mesh)
+DEF_GETLIST(Camera, camera)
+DEF_GETLIST(Material, mat)
+DEF_GETLIST(Lamp, lamp)
+DEF_GETLIST(World, world)
+DEF_GETLIST(Ipo, ipo)
+DEF_GETLIST(Image, image)
+DEF_GETLIST(Texture, tex)
+DEF_GETLIST(Text, text)
+DEF_GETLIST(Key, key)
+*/
+
+/* gets a datablock object from the ID list by name */
+ID *getFromList(ListBase *list, char *name)
+{
+ ID *id = list->first;
+
+ while (id) {
+ if(STREQ(name, getIDName(id))) break;
+ id= id->next;
+ }
+ return id;
+}
+
+void printList(ListBase *list)
+{
+ ID *walk = list->first;
+ ID *lastwalk = 0;
+ printf("List: %s\n", walk->name);
+ while (walk) {
+ printf(" %s\n", walk->name);
+ lastwalk = walk;
+ walk= walk->next;
+ }
+ if (list->last != lastwalk)
+ {
+ printf("****: listbase->last pointing to wrong end!\n");
+ // list->last = lastwalk;
+ }
+}
+
+
+/** (future) garbage collector subroutine */
+
+
+int gc_mainlist(ListBase *lb)
+{
+ ID *id = (ID *) lb->first;
+
+ while (id) {
+ if (getIDUsers(id) == 0) {
+ switch(GET_ID_TYPE(id)) {
+ case ID_OB:
+ BPY_debug(("free [Object %s]\n", getIDName(id)));
+ unlink_object((Object *) id);
+ free_libblock(lb, id);
+ break;
+ default: break;
+ }
+ }
+ id = id->next;
+ }
+ return 1;
+}
+
+ /** Garbage collection function. EXPERIMENTAL!
+ * This should free Blender from all unreferenced Objects (i.e.
+ * user count == 0).
+ * Don't expect too much yet -- User counting isn't done
+ * consequently in Blender. Neither parenting or bevelcurves
+ * etc. respect user counts...therefore, no circular references
+ * show up -- which are in fact possible; example:
+ *
+ * A BevelCurve is parenting its BevelObject: so there is a
+ * reference from the BevelObject to the BevelCurve, and a
+ * reference back from the Bevelcurve to the BevelObject.
+ *
+ * There are a lot of cleanup functions in Blender taking care
+ * of updating (invalidating) references to deleted objects.
+ * See unlink_object() for more details.
+ *
+ * This function must not be called inside a script, so don't go
+ * and create a wrapper for it :-)
+ * In a hopefully later implementation, the Python garbage collection
+ * might be used. For the moment, this is better than 'Save and Reload'
+ */
+
+ int garbage_collect(Main *m)
+ {
+ /* Remember, all descriptor objects must BOB_DECUSER on their raw
+ Blender Datablock in their __del__ method (C-API: dealloc function) */
+
+ gc_mainlist(&m->object);
+
+ /* TODO proper kernel level functions for safely freeing these objects
+ * must first be implemented...
+ gc_mainlist(&m->mesh);
+ gc_mainlist(&m->mat);
+ gc_mainlist(&m->lamp);
+ gc_mainlist(&m->camera);
+
+ .. and this list is far from being complete.
+ */
+
+ return 1;
+}
+
+/** expands pointer array of length 'oldsize' to length 'newsize'.
+ * A pointer to the (void *) array must be passed as first argument
+ * The array pointer content can be NULL, in this case a new array of length
+ * 'newsize' is created.
+ */
+
+static int expandPtrArray(void **p, int oldsize, int newsize)
+{
+ void *newarray;
+
+ if (newsize < oldsize) {
+ return 0;
+ }
+ newarray = MEM_callocN(newsize * sizeof(void *), "PtrArray");
+ if (*p) {
+ memcpy(newarray, *p, oldsize);
+ MEM_freeN(*p);
+ }
+ *p = newarray;
+ return 1;
+}
+
+/************************************************************************
+ * Material object low level routines
+ *
+ */
+
+/* MAXMAT = maximum number of materials per object/ object data */
+
+#define MATINDEX_CHECK(x) \
+ if ((x) < 0 || (x) >= MAXMAT) { printf("illegal matindex!\n"); return 0; }
+
+/** Returns a new material list (material pointer array) of length 'len'
+ *
+ */
+
+Material **newMaterialList(int len)
+{
+ Material **matlist =
+ (Material **) MEM_mallocN(len * sizeof(Material *), "MaterialList");
+ return matlist;
+}
+
+/** releases material list and decrements user count on materials */
+
+int releaseMaterialList(Material **matlist, int len)
+{
+ int i;
+ Material *m;
+
+ MATINDEX_CHECK(len);
+
+ for (i= 0; i < len; i++) {
+
+ m = matlist[i];
+ BOB_XDECUSER((ID *) m);
+ }
+ MEM_freeN(matlist);
+ return 1;
+}
+
+/** Synchronizes Object <-> data material lists. Blender just wants it. */
+
+int synchronizeMaterialLists(Object *object, void *data)
+{
+ // get pointer to data's material array:
+ // and number of data materials
+ // ... because they will need modification.
+
+ Material ***p_dataMaterials = give_matarar(object);
+ short *nmaterials = give_totcolp(object);
+
+ if (object->totcol > *nmaterials){ // more object mats than data mats
+ *nmaterials = object->totcol;
+ return expandPtrArray((void *) p_dataMaterials, *nmaterials, object->totcol);
+ } else if (object->totcol < *nmaterials) {
+ object->totcol = *nmaterials;
+ return expandPtrArray((void *) &object->mat, object->totcol, *nmaterials);
+ }
+ return 1; // in this case, no synchronization needed; they're of equal
+ // length
+}
+
+/************************************************************************
+ * Object low level routines
+ *
+ */
+
+/** creates a new empty object of type OB_ (TODO: should be enum)
+ *
+ */
+
+
+Object *object_new(int type)
+{
+ Object *object;
+ char name[32];
+
+ Global *g = getGlobal();
+
+ switch(type) {
+ case OB_MESH: strcpy(name, "Mesh"); break;
+ case OB_CURVE: strcpy(name, "Curve"); break;
+ case OB_SURF: strcpy(name, "Surf"); break;
+ case OB_FONT: strcpy(name, "Text"); break;
+ case OB_MBALL: strcpy(name, "Mball"); break;
+ case OB_CAMERA: strcpy(name, "Camera"); break;
+ case OB_LAMP: strcpy(name, "Lamp"); break;
+ case OB_IKA: strcpy(name, "Ika"); break;
+ case OB_LATTICE: strcpy(name, "Lattice"); break;
+ case OB_WAVE: strcpy(name, "Wave"); break;
+ case OB_ARMATURE: strcpy(name,"Armature");break;
+ default: strcpy(name, "Empty");
+ }
+
+ object = alloc_libblock(getObjectList(), ID_OB, name);
+
+ /* user count is set to 1 by alloc_libblock, we just reset it to 0... */
+ BOB_USERCOUNT((ID*) object) = 0; // it's a new object, so no user yet
+ object->flag = 0;
+ object->type = type;
+
+ /* transforms */
+ QuatOne(object->quat);
+ QuatOne(object->dquat);
+
+ object->col[3]= 1.0; // alpha
+
+ object->size[0] = object->size[1] = object->size[2] = 1.0;
+ object->loc[0] = object->loc[1] = object->loc[2] = 0.0;
+ Mat4One(object->parentinv);
+ Mat4One(object->obmat);
+ object->dt = OB_SHADED; // drawtype
+
+ object_setdefaults(object);
+
+ object->lay = 1; // Layer, by default visible
+
+ switch(type) {
+ case OB_MESH: object->data= add_mesh(); g->totmesh++; break;
+ case OB_CAMERA: object->data= add_camera(); break;
+ case OB_LAMP: object->data= add_lamp(); g->totlamp++; break;
+
+ // TODO the following types will be supported later
+ // case OB_CURVE: object->data= add_curve(OB_CURVE); g->totcurve++; break;
+ // case OB_SURF: object->data= add_curve(OB_SURF); g->totcurve++; break;
+ // case OB_FONT: object->data= add_curve(OB_FONT); break;
+ // case OB_MBALL: object->data= add_mball(); break;
+ // case OB_IKA: object->data= add_ika(); object->dt= OB_WIRE; break;
+ // case OB_LATTICE: object->data= (void *)add_lattice(); object->dt= OB_WIRE; break;
+ // case OB_WAVE: object->data= add_wave(); break;
+ // case OB_ARMATURE: object->data=add_armature();break;
+ }
+
+ g->totobj++; // gee, I *hate* G
+ return object;
+}
+
+/* returns new Base */
+Base *object_newBase(Object *object)
+{
+ Base *base;
+ base = MEM_callocN(sizeof(Base), "newbase");
+ if (!base)
+ return 0;
+ base->object = object;
+ base->lay = object->lay;
+ base->flag = object->flag;
+ return base;
+}
+
+Object *object_copy(Object *object)
+{
+ Object *new;
+
+ new = copy_object(object);
+ BOB_USERCOUNT((ID*) new) = 0; // it's a new object, so no user yet
+ return new;
+}
+
+/* Set draw mode of object */
+void object_setDrawMode(Object *object, int modebits)
+{
+ object->dt = (modebits & 0xff);
+ object->dtx = (modebits >> 8);
+}
+
+int object_getDrawMode(Object *object)
+{
+ return (((int) object->dtx) << 8 ) + object->dt;
+}
+
+/* link data to Object object */
+int object_linkdata(Object *object, void *data)
+{
+ ID *oldid, *id;
+ int valid;
+
+ if (!data) return 0;
+
+ oldid = (ID*) object->data;
+ id = (ID*) data;
+
+ valid = 0;
+
+#define _CASE(objtype, idtype) \
+ case objtype:\
+ if (GET_ID_TYPE(id) == idtype) \
+ valid = 1; \
+ break;
+
+ switch (object->type) {
+ _CASE(OB_MESH, ID_ME)
+ _CASE(OB_CAMERA, ID_CA)
+ _CASE(OB_LAMP, ID_LA)
+ default: // not supported
+ return 0;
+ }
+ if (valid) {
+ object->data = data;
+ BOB_INCUSER(id);
+ if (oldid)
+ BOB_DECUSER(oldid); // dec users
+
+ // extra check for multi materials on meshes:
+ // This is a hack to check whether object material lists are of same
+ // length as their data material lists..
+ //if (GET_ID_TYPE(id) == ID_ME) {
+ //test_object_materials(id);
+ //}
+ return 1;
+ }
+ return 0;
+}
+
+/* release data from object object */
+
+int object_unlinkdata(Object *object)
+{
+ ID *id = object->data;
+
+ BOB_XDECUSER(id);
+ return 1;
+}
+
+/** set Object materials:
+ * takes a list of Material pointers of maximum length MAXMAT
+ */
+
+int object_setMaterials(Object *object, Material **matlist, int len)
+{
+ int i;
+
+ MATINDEX_CHECK(len)
+ if (object->mat) {
+ releaseMaterialList(object->mat, len);
+ }
+ // inc user count on all materials
+ for (i = 0; i < len; i++) {
+ BOB_XINCUSER( (ID *) matlist[i]);
+ }
+
+ object->mat = matlist;
+ object->totcol = len;
+ object->actcol = len - 1; // XXX
+ // workaround: blender wants the object's data material list
+ // to be of the same length, otherwise colourful fun happens.
+ // so, we synchronize this here:
+
+ switch (object->type)
+ {
+ case OB_MESH:
+ case OB_CURVE:
+ case OB_FONT:
+ case OB_SURF:
+ case OB_MBALL:
+ synchronizeMaterialLists(object, object->data);
+ break;
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+/** make 'object' the parent of the object 'child'
+ *
+ * mode = 1: set parent inverse matrix to _1_ ('clear inverse')
+ * fast = 1: Don't update scene base (hierarchy). In this case,
+ * sort_baselist() needs to be called explicitely before redraw.
+ */
+
+int object_makeParent(Object *parent, Object *child, int mode, int fast)
+{
+ if (test_parent_loop(parent, child)) {
+ PyErr_SetString(PyExc_RuntimeError, "parenting loop detected!");
+ return 0;
+ }
+ child->partype = PAROBJECT;
+ child->parent = parent;
+ if (mode == 1) {
+ Mat4One(child->parentinv); // parent inverse = unity
+ child->loc[0] = 0.0; child->loc[1] = 0.0; child->loc[2] = 0.0;
+ } else {
+ what_does_parent(child);
+ Mat4Invert(child->parentinv, parent->obmat); // save inverse
+ }
+
+ /* This is some bad global thing again -- we should determine
+ the current scene
+ another way. Later. */
+ if (!fast)
+ sort_baselist(getGlobal()->scene);
+
+ return 1;
+}
+
+/** Unlink parenting hierarchy:
+ *
+ * mode = 2: keep transform
+ * fast = 1: don't update scene bases. see makeParent()
+ */
+
+int object_clrParent(Object *child, int mode, int fast)
+{
+ Object *par;
+
+ par = child->parent;
+ child->parent = 0;
+ if (mode == 2) { // keep transform
+ apply_obmat(child);
+ }
+ if (!fast)
+ sort_baselist(getGlobal()->scene);
+ return 1;
+}
+
+/** Set object's defaults */
+
+int object_setdefaults(Object *ob)
+{
+ if(U.flag & MAT_ON_OB) ob->colbits= -1;
+ switch(ob->type) {
+ case OB_CAMERA:
+ case OB_LAMP:
+ ob->trackflag = OB_NEGZ;
+ ob->upflag = OB_POSY;
+ break;
+ default:
+ ob->trackflag = OB_POSY;
+ ob->upflag = OB_POSZ;
+ }
+ ob->ipoflag = OB_OFFS_OB + OB_OFFS_PARENT;
+
+ /* duplivert settings */
+
+ ob->dupon = 1; ob->dupoff = 0;
+ ob->dupsta = 1; ob->dupend = 100;
+
+ /* Gameengine defaults*/
+ ob->mass= ob->inertia= 1.0;
+ ob->formfactor= 0.4;
+ ob->damping= 0.04;
+ ob->rdamping= 0.1;
+ ob->anisotropicFriction[0] = 1.0;
+ ob->anisotropicFriction[1] = 1.0;
+ ob->anisotropicFriction[2] = 1.0;
+
+ /* default to not use fh in new system */
+ ob->gameflag= OB_PROP; /*|OB_DO_FH; */
+
+ return 1;
+}
+
+/************************************************************************
+ * Creation of new data blocks
+ *
+ * We [ab|re]use the blender kernel functions, but set the user count to 0,
+ * because the object does not have users yet.
+ * Currently, the user count is abused as reference count which should be
+ * separate in future
+ */
+
+Material *material_new(void)
+{
+ Material *m = add_material("Material");
+ BOB_USERCOUNT((ID*) m) = 0; // set 'refcount' to 0, because
+ // it's a free material
+ return m;
+}
+
+Lamp *lamp_new()
+{
+ Lamp *la;
+
+ la = add_lamp();
+ BOB_USERCOUNT((ID*) la) = 0;
+
+ return la;
+}
+
+Camera *camera_new()
+{
+ Camera *cam;
+
+ cam = add_camera();
+ BOB_USERCOUNT((ID*) cam) = 0;
+ return cam;
+}
+
+Ipo *ipo_new(int type, char *name)
+{
+ Ipo *ipo;
+
+ ipo = add_ipo(name, type);
+ BOB_USERCOUNT((ID*) ipo) = 0;
+ return ipo;
+}
+
+
+/* Finds the ipo curve with channel code 'code' in the datablock 'ipo'
+ and returns it, if found (NULL otherwise) */
+
+IpoCurve *ipo_findcurve(Ipo *ipo, int code)
+{
+ IpoCurve *ipocurve;
+
+ ipocurve = ipo->curve.first;
+ while(ipocurve) {
+ if (ipocurve->adrcode == code) break;
+ ipocurve = ipocurve->next;
+ }
+ return ipocurve;
+}
+
+
+/** Returns a new Ipo curve */
+IpoCurve *ipocurve_new()
+{
+ IpoCurve *curve;
+
+ curve = MEM_callocN(sizeof(IpoCurve), "new_ipocurve");
+ curve->flag = IPO_VISIBLE;
+ return curve;
+}
+
+IpoCurve *ipocurve_copy(IpoCurve *curve)
+{
+ IpoCurve *newcurve;
+
+ newcurve = MEM_callocN(sizeof(IpoCurve), "new_ipocurve");
+ memcpy(newcurve, curve, sizeof(IpoCurve));
+ // copy bez triples:
+ newcurve->bezt= MEM_mallocN(curve->totvert*sizeof(BezTriple), "ipocurve_copy");
+ memcpy(newcurve->bezt, curve->bezt, curve->totvert*sizeof(BezTriple));
+ return newcurve;
+}
+
+/** Assign ipo to object object */
+
+/* macros, see b_interface.h */
+
+DEF_ASSIGN_IPO(object, Object) // defines object_assignIpo()
+
+DEF_ASSIGN_IPO(camera, Camera)
+
+DEF_ASSIGN_IPO(lamp, Lamp)
+
+DEF_ASSIGN_IPO(material, Material)
+
+/************************************************************************
+ * Mesh object low level routines
+ *
+ */
+
+/** Returns a new, free (non owned) mesh.
+ * add_mesh() automatically returns a mesh object with users = 1,
+ * so we set it to 0. Hack, hack.
+ */
+
+Mesh *mesh_new(void)
+{
+ Mesh *me = add_mesh();
+ ((ID *) me)->us = 0;
+ return me;
+}
+
+/** updates drawing properties etc. of mesh */
+
+void mesh_update(Mesh *mesh)
+{
+ edge_drawflags_mesh(mesh);
+ tex_space_mesh(mesh);
+}
+
+/************************************************************************
+ * Scene object low level routines
+ *
+ */
+
+/** Returns current Scene */
+
+Scene *scene_getCurrent(void)
+{
+ return getGlobal()->scene;
+}
+
+/* returns base of object 'object' in Scene 'scene', 0 if nonexistant
+ * A base is basically an visual instantiation of an 3D object (Object)
+ * in a Scene. See scene_linkObject()
+ *
+ */
+
+Base *scene_getObjectBase(Scene *scene, Object *object)
+{
+ Base *base;
+ base = scene->base.first;
+ while (base)
+ {
+ if (object == base->object) // it exists
+ return base;
+ base = base->next;
+ }
+ return NULL;
+}
+
+/* links an object into a scene */
+int scene_linkObject(Scene *scene, Object *object)
+{
+ Base *base, *b;
+ b = scene_getObjectBase(scene, object);
+ if (b)
+ return 0;
+ base = object_newBase(object);
+ if (!base) {
+ return 0;
+ }
+ BOB_INCUSER((ID *) object); // incref the object
+ BLI_addhead(&scene->base, base);
+ return 1;
+}
+
+/* unlinks an object from a scene */
+int scene_unlinkObject(Scene *scene, Object *object)
+{
+ Base *base;
+ base = scene_getObjectBase(scene, object);
+ if (base) {
+ BLI_remlink(&scene->base, base);
+ BOB_DECUSER((ID *) object);
+ MEM_freeN(base);
+ scene->basact = 0; // make sure the just deleted object has no longer an
+ // active base (which happens if it was selected
+ return 1;
+ }
+ else return 0;
+}
+
diff --git a/source/blender/bpython/intern/b_interface.h b/source/blender/bpython/intern/b_interface.h
new file mode 100644
index 00000000000..b2af2280f1f
--- /dev/null
+++ b/source/blender/bpython/intern/b_interface.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 *****
+ */
+#include "DNA_ID.h"
+#include "DNA_mesh_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_object_types.h"
+#include "DNA_text_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_ipo_types.h"
+#include "DNA_image_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_material_types.h"
+#include "DNA_scriptlink_types.h"
+#include "DNA_userdef_types.h" /* for userdata struct; U.pythondir */
+
+#include "BKE_main.h"
+#include "BKE_material.h"
+#include "BKE_mesh.h"
+#include "BKE_object.h"
+#include "BKE_scene.h"
+#include "BKE_global.h"
+
+/* DEFINES */
+
+#define ASSIGN_IPO(prefix, type) \
+ prefix##_assignIpo(type *obj, Ipo *ipo)
+
+// example DEF_ASSIGN_IPO(Object, obj) ->
+// int object_assignIpo(Object *obj, Ipo *ipo)
+
+#define DEF_ASSIGN_IPO(prefix, type) \
+ int prefix##_assignIpo(type *obj, Ipo *ipo) \
+ { \
+ BOB_XDECUSER((ID*) obj->ipo); \
+ BOB_XINCUSER((ID*) ipo); \
+ obj->ipo = ipo; \
+ return 1; \
+ } \
+
+// defined prototypes:
+
+#define FUNC_ASSIGN_IPO(prefix, arg1, arg2) \
+ prefix##_assignIpo(arg1, arg2)
+
+#define object_assignIpo(arg1, arg2) FUNC_ASSIGN_IPO(object, arg1, arg2)
+#define material_assignIpo(arg1, arg2) FUNC_ASSIGN_IPO(material, arg1, arg2)
+#define camera_assignIpo(arg1, arg2) FUNC_ASSIGN_IPO(camera, arg1, arg2)
+#define lamp_assignIpo(arg1, arg2) FUNC_ASSIGN_IPO(lamp, arg1, arg2)
+
+/** Defines for List getters */
+
+/*
+#define PROTO_GETLIST(name, member) \
+ ListBase *get##name##List(void)
+
+#define DEF_GETLIST(name, member) \
+ PROTO_GETLIST(name, member) \
+ { \
+ return &(G.main->member); \
+ }
+*/
+
+/* PROTOS */
+
+#define _GETMAINLIST(x) \
+ (&(G.main->x))
+
+#define getSceneList() _GETMAINLIST(scene)
+#define getObjectList() _GETMAINLIST(object)
+#define getMeshList() _GETMAINLIST(mesh)
+#define getMaterialList() _GETMAINLIST(mat)
+#define getCameraList() _GETMAINLIST(camera)
+#define getLampList() _GETMAINLIST(lamp)
+#define getWorldList() _GETMAINLIST(world)
+#define getIpoList() _GETMAINLIST(ipo)
+#define getImageList() _GETMAINLIST(image)
+#define getTextureList() _GETMAINLIST(tex)
+#define getTextList() _GETMAINLIST(text)
+#define getKeyList() _GETMAINLIST(key)
+#define getLatticeList() _GETMAINLIST(latt)
+
+/*
+PROTO_GETLIST(Scene, scene);
+PROTO_GETLIST(Object, object);
+PROTO_GETLIST(Mesh, mesh);
+PROTO_GETLIST(Camera, camera);
+PROTO_GETLIST(Material, mat);
+PROTO_GETLIST(Lamp, lamp);
+PROTO_GETLIST(World, world);
+PROTO_GETLIST(Ipo, ipo);
+PROTO_GETLIST(Image, image);
+PROTO_GETLIST(Texture, tex);
+PROTO_GETLIST(Text, text);
+PROTO_GETLIST(Key, key); */
+
+
+Global *getGlobal(void); // get Global struct
+
+ID *getFromList(ListBase *list, char *name);
+
+int garbage_collect(Main *m);
+
+
+Material **newMaterialList(int len);
+int releaseMaterialList(struct Material **matlist, int len);
+int synchronizeMaterialLists(Object *object, void *data);
+
+// Datablock management
+
+Material *material_new(void);
+int material_assignIpo(Material *, Ipo *);
+
+Lamp *lamp_new(void);
+int lamp_assignIpo(Lamp *, Ipo *);
+
+Camera *camera_new(void);
+int camera_assignIpo(Camera *, Ipo *);
+
+Ipo *ipo_new(int type, char *name);
+IpoCurve *ipo_findcurve(Ipo *ipo, int code);
+IpoCurve *ipocurve_new(void);
+IpoCurve *ipocurve_copy(IpoCurve *curve);
+
+// Object management
+Base *object_newBase(Object *obj);
+int object_linkdata(Object *obj, void *data);
+int object_unlinkdata(Object *obj);
+int object_setMaterials(Object *object, Material **matlist, int len);
+int object_setdefaults(Object *ob);
+int object_copyMaterialsTo(Object *object, Material **matlist, int len);
+int object_makeParent(Object *parent, Object *child, int noninverse, int fast);
+int object_clrParent(Object *child, int mode, int fast);
+Object *object_new(int type);
+Object *object_copy(Object *obj);
+void object_setDrawMode(Object *object, int val);
+int object_getDrawMode(Object *object);
+
+int object_assignIpo(Object *, Ipo *);
+
+Scene *scene_getCurrent(void);
+int scene_linkObject(Scene *scene, Object *obj);
+int scene_unlinkObject(Scene *scene, Object *object);
+Base *scene_getObjectBase(Scene *scene, Object *object);
+
+Mesh *mesh_new(void);
+void mesh_update(Mesh *me);
+
+/* blender's program name */
+extern char bprogname[]; /* init in creator.c */
+
+
+
diff --git a/source/blender/bpython/intern/opy_blender.c b/source/blender/bpython/intern/opy_blender.c
new file mode 100644
index 00000000000..6bbac3d958e
--- /dev/null
+++ b/source/blender/bpython/intern/opy_blender.c
@@ -0,0 +1,342 @@
+/* python code for Blender, written by Daniel Dunbar */
+/*
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "Python.h"
+
+#include "BPY_macros.h"
+#include "b_interface.h"
+#include "BPY_tools.h"
+#include "BPY_modules.h"
+#include "BPY_main.h"
+
+#include "BKE_main.h"
+#include "BKE_object.h" // during_script() (what is this ?)
+#include "BKE_global.h"
+#include "BKE_ipo.h" // frame_to_float()
+#include "BKE_blender.h"
+
+#include "BIF_space.h" // allqueue()
+#include "BSE_headerbuttons.h"
+
+#include "BPY_types.h" // userdefined Python Objects
+#include <string.h>
+
+#include "DNA_userdef_types.h"
+
+#include "mydevice.h"
+
+//#include "py_blender.h"
+//#include "screen.h"
+//#include "ipo.h"
+
+void INITMODULE(BLENDERMODULE)(void);
+
+PyObject *g_sysmodule;
+
+
+/*
+NamedEnum TextureTypes[]= {
+ {"Clouds", TEX_CLOUDS},
+ {"Wood", TEX_WOOD},
+ {"Marble", TEX_MARBLE},
+ {"Magic", TEX_MAGIC},
+ {"Blend", TEX_BLEND},
+ {"Stucci", TEX_STUCCI},
+ {"Noise", TEX_NOISE},
+ {"Image", TEX_IMAGE},
+ {"Plugin", TEX_PLUGIN},
+ {"Envmap", TEX_ENVMAP},
+ {NULL}
+};
+
+DataBlockProperty Texture_Properties[]= {
+ DBP_NamedEnum("type", "type", TextureTypes),
+ DBP_Short("stype", "stype", 0.0, 0.0, 0),
+
+ DBP_Float("noisesize", "noisesize", 0.0, 0.0, 0),
+ DBP_Float("turbulence", "turbul", 0.0, 0.0, 0),
+ DBP_Float("brightness", "bright", 0.0, 0.0, 0),
+ DBP_Float("contrast", "contrast", 0.0, 0.0, 0),
+ DBP_Float("rfac", "rfac", 0.0, 0.0, 0),
+ DBP_Float("gfac", "gfac", 0.0, 0.0, 0),
+ DBP_Float("bfac", "bfac", 0.0, 0.0, 0),
+ DBP_Float("filtersize", "filtersize", 0.0, 0.0, 0),
+
+ DBP_Short("noisedepth", "noisedepth", 0.0, 0.0, 0),
+ DBP_Short("noisetype", "noisetype", 0.0, 0.0, 0),
+
+ {NULL}
+};
+*/
+
+
+/*****************************/
+/* Main interface routines */
+/*****************************/
+
+
+#define BP_CURFRAME 1
+#define BP_CURTIME 2
+#define BP_FILENAME 3
+
+static char Blender_Set_doc[]=
+"(request, data) - Update settings in Blender\n\
+\n\
+(request) A string indentifying the setting to change\n\
+ 'curframe' - Sets the current frame using the number in data";
+
+static PyObject *Blender_Set (PyObject *self, PyObject *args)
+{
+ char *name;
+ PyObject *arg;
+
+ BPY_TRY(PyArg_ParseTuple(args, "sO", &name, &arg));
+
+ if (STREQ(name, "curframe")) {
+ int framenum;
+
+ BPY_TRY(PyArg_Parse(arg, "i", &framenum));
+
+ (G.scene->r.cfra)= framenum;
+
+ update_for_newframe();
+
+ } else {
+ return BPY_err_ret_ob(PyExc_AttributeError, "bad request identifier");
+ }
+
+ return BPY_incr_ret(Py_None);
+}
+
+static char Blender_Get_doc[]=
+"(request) - Retrieve settings from Blender\n\
+\n\
+(request) A string indentifying the data to be returned\n\
+ 'curframe' - Returns the current animation frame\n\
+ 'curtime' - Returns the current animation time\n\
+ 'staframe' - Returns the start frame of the animation\n\
+ 'endframe' - Returns the end frame of the animation\n\
+ 'filename' - Returns the name of the last file read or written\n\
+ 'version' - Returns the Blender version number";
+
+static PyObject *Blender_Get (PyObject *self, PyObject *args)
+{
+ PyObject *ob;
+ PyObject *dict;
+
+ BPY_TRY(PyArg_ParseTuple(args, "O", &ob));
+
+ if (PyString_Check(ob)) {
+ char *str= PyString_AsString(ob);
+
+ if (STREQ(str, "curframe"))
+ return PyInt_FromLong((G.scene->r.cfra));
+
+ else if (STREQ(str, "curtime"))
+ return PyFloat_FromDouble(frame_to_float((G.scene->r.cfra)));
+
+ else if (STREQ(str, "staframe"))
+ return PyInt_FromLong((G.scene->r.sfra));
+
+ else if (STREQ(str, "endframe"))
+ return PyInt_FromLong((G.scene->r.efra));
+
+ else if (STREQ(str, "filename"))
+ return PyString_FromString(getGlobal()->sce);
+
+ else if (STREQ(str, "vrmloptions")) // TODO: quick hack, clean up!
+ {
+ dict= PyDict_New();
+ PyDict_SetItemString(dict, "twoside",
+ PyInt_FromLong(U.vrmlflag & USERDEF_VRML_TWOSIDED));
+ PyDict_SetItemString(dict, "layers",
+ PyInt_FromLong(U.vrmlflag & USERDEF_VRML_LAYERS));
+ PyDict_SetItemString(dict, "autoscale",
+ PyInt_FromLong(U.vrmlflag & USERDEF_VRML_AUTOSCALE));
+ return dict;
+ }
+ else if (STREQ(str, "version"))
+ return PyInt_FromLong(G.version);
+ } else {
+ return BPY_err_ret_ob(PyExc_AttributeError, "expected string argument");
+ }
+
+ return BPY_err_ret_ob(PyExc_AttributeError, "bad request identifier");
+}
+
+/* for compatibility: <<EOT */
+
+static char Blender_Redraw_doc[]= "() - Redraw all 3D windows";
+
+static PyObject *Blender_Redraw(PyObject *self, PyObject *args)
+{
+ int wintype = SPACE_VIEW3D;
+
+ BPY_TRY(PyArg_ParseTuple(args, "|i", &wintype));
+
+ return Windowmodule_Redraw(self, Py_BuildValue("(i)", wintype));
+}
+/* EOT */
+
+#undef MethodDef
+#define MethodDef(func) {#func, Blender_##func, METH_VARARGS, Blender_##func##_doc}
+
+static struct PyMethodDef Blender_methods[] = {
+ MethodDef(Redraw),
+ MethodDef(Get),
+ MethodDef(Set),
+ {NULL, NULL}
+};
+
+struct PyMethodDef Null_methods[] = {
+ {NULL, NULL}
+};
+
+
+static char Blender_Const_doc[] =
+"This module is only there for compatibility reasons.\n\
+It will disappear in future, please use the Blender.Get() syntax instead\n";
+
+
+/* Blender system module
+ Sorry, this is a mess, but had to be hacked in in order to meet deadlines..
+ TODO: Cleanup
+*/
+
+static char sys_dirname_doc[] =
+ "(path) - returns the directory name of 'path'";
+
+static PyObject *sys_dirname(PyObject *self, PyObject *args)
+{
+ PyObject *c;
+
+ char *name, dirname[256];
+ char sep;
+ int n;
+
+ BPY_TRY(PyArg_ParseTuple(args, "s", &name));
+
+ c = PyObject_GetAttrString(g_sysmodule, "dirsep");
+ sep = PyString_AsString(c)[0];
+ Py_DECREF(c);
+
+ n = strrchr(name, sep) - name;
+ if (n > 255) {
+ PyErr_SetString(PyExc_RuntimeError, "path too long");
+ return 0;
+ }
+ strncpy(dirname, name, n);
+ dirname[n] = 0;
+
+ return Py_BuildValue("s", dirname);
+}
+
+#define METHODDEF(func) {#func, sys_##func, METH_VARARGS, sys_##func##_doc}
+
+static struct PyMethodDef sys_methods[] = {
+ METHODDEF(dirname),
+ {NULL, NULL}
+};
+
+
+PyObject *init_sys(void)
+{
+
+ PyObject *m, *dict, *p;
+
+ m = Py_InitModule(SUBMODULE(sys), sys_methods);
+ g_sysmodule = m;
+
+ dict= PyModule_GetDict(m);
+
+#ifdef WIN32
+ p = Py_BuildValue("s", "\\");
+#else
+ p = Py_BuildValue("s", "/");
+#endif
+
+ PyDict_SetItemString(dict, "dirsep" , p);
+ return m;
+}
+
+/* ----------------------------------------------------------------- */
+
+void INITMODULE(BLENDERMODULE)(void)
+{
+ PyObject *m, *dict, *d;
+
+ m = Py_InitModule4(MODNAME(BLENDERMODULE), Blender_methods, (char*) 0, (PyObject*)NULL, PYTHON_API_VERSION);
+
+ DataBlock_Type.ob_type = &PyType_Type;
+
+
+ init_py_vector();
+ init_py_matrix();
+
+ dict = PyModule_GetDict(m);
+ g_blenderdict = dict;
+
+ /* pyblender data type initialization */
+ init_types(dict);
+ init_Datablockmodules(dict);
+
+ /* kept for compatibility...will be removed XXX */
+ PyDict_SetItemString(dict, "bylink", PyInt_FromLong(0));
+ PyDict_SetItemString(dict, "link", Py_None);
+
+ /* initialize submodules */
+ PyDict_SetItemString(dict, "sys", init_sys());
+ Py_INCREF(Py_None);
+ PyDict_SetItemString(dict, "Image", INITMODULE(Image)());
+ PyDict_SetItemString(dict, "Window",INITMODULE(Window)());
+ PyDict_SetItemString(dict, "NMesh", init_py_nmesh());
+ PyDict_SetItemString(dict, "Draw", init_py_draw());
+ PyDict_SetItemString(dict, "BGL", init_py_bgl());
+#ifdef EXPERIMENTAL
+ PyDict_SetItemString(dict, "Nurbs", init_py_nurbs());
+#endif
+ /* CONSTANTS */
+
+ /* emulate old python XXX -> should go to Blender/ python externals */
+
+ m = Py_InitModule4(MODNAME(BLENDERMODULE) ".Const" , Null_methods, Blender_Const_doc, (PyObject*)NULL, PYTHON_API_VERSION);
+ d = PyModule_GetDict(m);
+ PyDict_SetItemString(dict, "Const", m);
+ PyDict_SetItemString(d, "BP_CURFRAME", PyInt_FromLong(BP_CURFRAME));
+ PyDict_SetItemString(d, "BP_CURTIME", PyInt_FromLong(BP_CURTIME));
+
+ PyDict_SetItemString(d, "CURFRAME", PyInt_FromLong(BP_CURFRAME));
+ PyDict_SetItemString(d, "CURTIME", PyInt_FromLong(BP_CURTIME));
+ PyDict_SetItemString(d, "FILENAME", PyInt_FromLong(BP_FILENAME));
+}
+
diff --git a/source/blender/bpython/intern/opy_datablock.c b/source/blender/bpython/intern/opy_datablock.c
new file mode 100644
index 00000000000..6804c834897
--- /dev/null
+++ b/source/blender/bpython/intern/opy_datablock.c
@@ -0,0 +1,1299 @@
+/* Datablock handling code. This handles the generic low level access to Blender
+ Datablocks. */
+
+/*
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/**************************************************************************
+ * This code provides low level, generalized access to the Blender Datablock
+ * objects. It basically creates a descriptor Python Object of type 'DataBlock'
+ * for each requested Blender datablock.
+ * This introduces the question of synchronization, for example:
+ * What happens if an Object is deleted?
+ *
+ * Blender Objects have their own 'reference counting', e.g. a Mesh datablock
+ * used by two Objects has a user count of 2. Datablocks with user count of 0
+ * are not saved to Disk -- this is the current way Blender does
+ * 'garbage collection'
+ * Therefore, an object should normally not be deleted by Python, but rather
+ * unlinked from its parent object.
+ * Still, for other objects like Scene or Text objects, deletion from 'Main'
+ * is desired.
+ * The current workaround:
+
+ * Some objects can be explicitely deleted (not recommended, but possible) --
+ * they have a user count of 1, even if they are used by objects in some way,
+ * for example Text objects which are used by any other Blender object
+ * through a ScriptLink.
+ *
+ * Objects that are deleted through Python end up with a 'dead' descriptor;
+ * accessing the descriptor after deletion causes a Python exception.
+ *
+ * NASTY UGLY DIRTY, VUILE, DRECKIGES AND STILL REMAINING PROBLEM:
+ *
+ * It is (in the current API) possible to construct the case, that an
+ * Object is deleted in Blender, but the Python descriptor does not know
+ * about this. Accessing the descriptor (which simply contains a pointer to
+ * the raw datablock struct) will most probably end in colourful joy.
+ *
+ * TODO:
+ * possible solutions:
+ * - rewrite datablock handling that way, that the descriptor uses an id
+ * tag to retrieve that pointer through a getPointerbyID() function
+ * (if the object exists!) on each access. Slow.
+ * - make sure that deletion always happends by the descriptor and never
+ * delete the raw datastructure. This solution would imply a major
+ * redesign of user action handling (GUI actions calling python).
+ * Not likely to happen...better fusion raw and python object in this case.
+ * After all, still somewhat dirty.
+ * - make sure that no deletion can happen in Blender while a script
+ * still accesses the raw data - i.e. implement user counting of raw
+ * objects with descriptors. This would need an implementation of
+ * garbage collection in Blender. This might sound like the most feasible
+ * solution...
+ */
+
+
+#include "Python.h"
+#include "BPY_macros.h"
+
+#include "opy_datablock.h"
+#include "opy_nmesh.h"
+
+#include "opy_vector.h" /* matrix datatypes */
+
+#include "BPY_tools.h"
+#include "BPY_types.h"
+#include "BPY_main.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "b_interface.h" /* needed for most of the DNA datatypes */
+
+
+/* ---------------------------------------------------------------------- */
+
+/*********************/
+/* Camera Datablocks */
+
+DATABLOCK_GET(Cameramodule, camera, getCameraList())
+
+static char Cameramodule_New_doc[] =
+"() - returns new Camera object";
+
+PyObject *Cameramodule_New (PyObject *self, PyObject *args)
+{
+ Camera *obj;
+ obj = camera_new();
+ return DataBlock_fromData(obj);
+}
+
+#ifdef FUTURE_PYTHON_API
+
+DataBlockProperty Camera_Properties[]= {
+ {"lens", "lens", DBP_TYPE_FLO, 0, 1.0, 250.0},
+ {"clipStart","clipsta", DBP_TYPE_FLO, 0, 0.0, 100.0},
+ {"clipEnd", "clipend", DBP_TYPE_FLO, 0, 1.0, 5000.0},
+ {"type", "type", DBP_TYPE_SHO, 0, 0.0, 0.0},
+ {"mode", "flag", DBP_TYPE_SHO, 0, 0.0, 0.0},
+
+ {"ipo", "*ipo", DBP_TYPE_FUN, 0, 0.0, 0.0, {0}, {0}, 0, 0, get_DataBlock_func},
+
+ {NULL}
+};
+
+#else
+
+DataBlockProperty Camera_Properties[]= {
+ {"Lens", "lens", DBP_TYPE_FLO, 0, 1.0, 250.0},
+ {"ClSta", "clipsta", DBP_TYPE_FLO, 0, 0.0, 100.0},
+ {"ClEnd", "clipend", DBP_TYPE_FLO, 0, 1.0, 5000.0},
+
+ {"ipo", "*ipo", DBP_TYPE_FUN, 0, 0.0, 0.0, {0}, {0}, 0, 0, get_DataBlock_func},
+
+ {NULL}
+};
+
+#endif
+
+static struct PyMethodDef Cameramodule_methods[] = {
+ {"New", Cameramodule_New, METH_VARARGS, Cameramodule_New_doc},
+ {"get", Cameramodule_get, METH_VARARGS, Cameramodule_get_doc},
+ {NULL, NULL}
+};
+
+DATABLOCK_ASSIGN_IPO(Camera, camera) // defines Camera_assignIpo
+
+static struct PyMethodDef Camera_methods[] = {
+ {"clrIpo", Camera_clrIpo, METH_VARARGS, Camera_clrIpo_doc},
+ {"assignIpo", Camera_assignIpo, METH_VARARGS, Camera_assignIpo_doc},
+ {NULL, NULL}
+};
+
+/***********************/
+/* Material Datablocks */
+
+
+/** returns a pointer to a new (malloced) material list created from
+ * a Python material list
+ */
+
+Material **newMaterialList_fromPyList(PyObject *list)
+{
+ int i, len;
+ DataBlock *block = 0;
+ Material *mat;
+ Material **matlist;
+
+ len = PySequence_Length(list);
+ if (len > 16) len = 16;
+
+ matlist = newMaterialList(len);
+
+ for (i= 0; i < len; i++) {
+
+ block= (DataBlock *) PySequence_GetItem(list, i);
+
+ if (DataBlock_isType(block, ID_MA)) {
+ mat = (Material *) block->data;
+ matlist[i] = mat;
+ } else {
+ // error; illegal type in material list
+ Py_DECREF(block);
+ MEM_freeN(matlist);
+ return NULL;
+ }
+ Py_DECREF(block);
+ }
+ return matlist;
+}
+
+/** Return Python List from material pointer list 'matlist' with length
+ * 'len'
+ *
+ */
+
+PyObject *PyList_fromMaterialList(Material **matlist, int len)
+{
+ PyObject *list;
+ int i;
+
+ list = PyList_New(0);
+ if (!matlist) return list;
+
+ for (i = 0; i < len; i++) {
+ Material *mat= matlist[i];
+ PyObject *ob;
+
+ if (mat) {
+ ob = DataBlock_fromData(mat);
+ PyList_Append(list, ob);
+ Py_DECREF(ob); // because Append increfs!
+ }
+ }
+ return list;
+}
+
+DATABLOCK_GET(Materialmodule, material, getMaterialList())
+
+DATABLOCK_NEW(Materialmodule, Material, material_new())
+
+static struct PyMethodDef Materialmodule_methods[] = {
+ {"get", Materialmodule_get, METH_VARARGS, Materialmodule_get_doc},
+ {"New", Materialmodule_New, METH_VARARGS, Materialmodule_New_doc},
+ {NULL, NULL}
+};
+
+DATABLOCK_ASSIGN_IPO(Material, material)
+
+static struct PyMethodDef Material_methods[] = {
+ {"clrIpo", Material_clrIpo, METH_VARARGS, Material_clrIpo_doc},
+ {"assignIpo", Material_assignIpo, METH_VARARGS, Material_assignIpo_doc},
+ {NULL, NULL}
+};
+
+#ifdef FUTURE_PYTHON_API
+
+DataBlockProperty Material_Properties[]= {
+ {"R", "r", DBP_TYPE_FLO, 0, 0.0, 1.0},
+ {"G", "g", DBP_TYPE_FLO, 0, 0.0, 1.0},
+ {"B", "b", DBP_TYPE_FLO, 0, 0.0, 1.0},
+ {"specR", "specr", DBP_TYPE_FLO, 0, 0.0, 1.0},
+ {"specG", "specg", DBP_TYPE_FLO, 0, 0.0, 1.0},
+ {"specB", "specb", DBP_TYPE_FLO, 0, 0.0, 1.0},
+ {"mirR", "mirr", DBP_TYPE_FLO, 0, 0.0, 1.0},
+ {"mirG", "mirg", DBP_TYPE_FLO, 0, 0.0, 1.0},
+ {"mirB", "mirb", DBP_TYPE_FLO, 0, 0.0, 1.0},
+ {"ref", "ref", DBP_TYPE_FLO, 0, 0.0, 1.0},
+ {"alpha", "alpha", DBP_TYPE_FLO, 0, 0.0, 1.0},
+ {"emit", "emit", DBP_TYPE_FLO, 0, 0.0, 1.0},
+ {"amb", "amb", DBP_TYPE_FLO, 0, 0.0, 1.0},
+ {"spec", "spec", DBP_TYPE_FLO, 0, 0.0, 1.0},
+ {"specTransp", "spectra", DBP_TYPE_FLO, 0, 0.0, 1.0},
+ {"haloSize", "hasize", DBP_TYPE_FLO, 0, 0.0, 10000.0},
+
+ {"mode", "mode", DBP_TYPE_INT, 0, 0.0, 0.0},
+ {"hard", "har", DBP_TYPE_SHO, 0, 1.0, 128.0},
+
+ {"ipo", "*ipo", DBP_TYPE_FUN, 0, 0.0, 0.0, {0}, {0}, 0, 0, get_DataBlock_func},
+
+ {NULL}
+};
+
+#else
+
+DataBlockProperty Material_Properties[]= {
+ {"R", "r", DBP_TYPE_FLO, 0, 0.0, 1.0},
+ {"G", "g", DBP_TYPE_FLO, 0, 0.0, 1.0},
+ {"B", "b", DBP_TYPE_FLO, 0, 0.0, 1.0},
+ {"SpecR", "specr", DBP_TYPE_FLO, 0, 0.0, 1.0},
+ {"SpecG", "specg", DBP_TYPE_FLO, 0, 0.0, 1.0},
+ {"SpecB", "specb", DBP_TYPE_FLO, 0, 0.0, 1.0},
+ {"MirR", "mirr", DBP_TYPE_FLO, 0, 0.0, 1.0},
+ {"MirG", "mirg", DBP_TYPE_FLO, 0, 0.0, 1.0},
+ {"MirB", "mirb", DBP_TYPE_FLO, 0, 0.0, 1.0},
+ {"Ref", "ref", DBP_TYPE_FLO, 0, 0.0, 1.0},
+ {"Alpha", "alpha", DBP_TYPE_FLO, 0, 0.0, 1.0},
+ {"Emit", "emit", DBP_TYPE_FLO, 0, 0.0, 1.0},
+ {"Amb", "amb", DBP_TYPE_FLO, 0, 0.0, 1.0},
+ {"Spec", "spec", DBP_TYPE_FLO, 0, 0.0, 1.0},
+ {"SpTra", "spectra", DBP_TYPE_FLO, 0, 0.0, 1.0},
+ {"HaSize", "hasize", DBP_TYPE_FLO, 0, 0.0, 10000.0},
+
+ {"Mode", "mode", DBP_TYPE_INT, 0, 0.0, 0.0},
+ {"Hard", "har", DBP_TYPE_SHO, 0, 1.0, 128.0},
+
+ {"ipo", "*ipo", DBP_TYPE_FUN, 0, 0.0, 0.0, {0}, {0}, 0, 0, get_DataBlock_func},
+
+ {NULL}
+};
+
+#endif
+
+/*******************/
+/* Lamp Datablocks */
+
+DATABLOCK_GET(Lampmodule, lamp, getLampList())
+
+// DATABLOCK_NEW(Lampmodule, Lamp, lamp_new())
+
+static char Lampmodule_New_doc[] =
+"() - returns new Lamp object";
+
+PyObject *Lampmodule_New (PyObject *self, PyObject *args)
+{
+ Lamp *obj;
+ obj = lamp_new();
+ return DataBlock_fromData(obj);
+}
+
+#ifdef FUTURE_PYTHON_API
+
+DataBlockProperty Lamp_Properties[]= {
+ {"mode", "mode", DBP_TYPE_SHO, 0, 0.0, 0.0},
+ {"type", "type", DBP_TYPE_SHO, 0, 0.0, 0.0},
+ {"R", "r", DBP_TYPE_FLO, 0, 0.0, 1.0},
+ {"G", "g", DBP_TYPE_FLO, 0, 0.0, 1.0},
+ {"B", "b", DBP_TYPE_FLO, 0, 0.0, 1.0},
+ {"energy", "energy", DBP_TYPE_FLO, 0, 0.0, 10.0},
+ {"dist", "dist", DBP_TYPE_FLO, 0, 0.01, 5000.0},
+ {"spotSize", "spotsize", DBP_TYPE_FLO, 0, 1.0, 180.0},
+ {"spotBlend", "spotblend", DBP_TYPE_FLO, 0, 0.0, 1.0},
+ {"haloInt", "haint", DBP_TYPE_FLO, 0, 0.0, 5.0},
+ {"quad1", "att1", DBP_TYPE_FLO, 0, 0.0, 1.0},
+ {"quad2", "att2", DBP_TYPE_FLO, 0, 0.0, 1.0},
+ {"bufferSize", "bufsize", DBP_TYPE_SHO, 0, 0.0, 0.0},
+ {"samples", "samp", DBP_TYPE_SHO, 0, 1.0, 16.0},
+ {"haloStep", "shadhalostep", DBP_TYPE_SHO, 0, 0.0, 12.0},
+ {"clipStart", "clipsta", DBP_TYPE_FLO, 0, 0.1, 5000.0},
+ {"clipEnd", "clipend", DBP_TYPE_FLO, 0, 0.1, 5000.0},
+ {"bias", "bias", DBP_TYPE_FLO, 0, 0.01, 5.0},
+ {"softness", "soft", DBP_TYPE_FLO, 0, 1.00, 100.0},
+
+ {"ipo", "*ipo", DBP_TYPE_FUN, 0, 0.0, 0.0, {0}, {0}, 0, 0, get_DataBlock_func},
+
+ {NULL}
+};
+#else
+
+DataBlockProperty Lamp_Properties[]= {
+ {"mode", "mode", DBP_TYPE_SHO, 0, 0.0, 0.0},
+ {"type", "type", DBP_TYPE_SHO, 0, 0.0, 0.0},
+ {"R", "r", DBP_TYPE_FLO, 0, 0.0, 1.0},
+ {"G", "g", DBP_TYPE_FLO, 0, 0.0, 1.0},
+ {"B", "b", DBP_TYPE_FLO, 0, 0.0, 1.0},
+ {"Energ", "energy", DBP_TYPE_FLO, 0, 0.0, 10.0},
+ {"Dist", "dist", DBP_TYPE_FLO, 0, 0.01, 5000.0},
+ {"SpotSi", "spotsize", DBP_TYPE_FLO, 0, 1.0, 180.0},
+ {"SpotBl", "spotblend", DBP_TYPE_FLO, 0, 0.0, 1.0},
+ {"HaloInt", "haint", DBP_TYPE_FLO, 0, 1.0, 5.0},
+ {"Quad1", "att1", DBP_TYPE_FLO, 0, 0.0, 1.0},
+ {"Quad2", "att2", DBP_TYPE_FLO, 0, 0.0, 1.0},
+
+ {"ipo", "*ipo", DBP_TYPE_FUN, 0, 0.0, 0.0, {0}, {0}, 0, 0, get_DataBlock_func},
+
+ {NULL}
+};
+
+#endif
+
+
+static struct PyMethodDef Lampmodule_methods[] = {
+ {"New", Lampmodule_New, METH_VARARGS, Lampmodule_New_doc},
+ {"get", Lampmodule_get, METH_VARARGS, Lampmodule_get_doc},
+#ifdef CURRENT_PYTHON_API
+ {"Get", Lampmodule_get, METH_VARARGS, Lampmodule_get_doc},
+#endif
+ {NULL, NULL}
+};
+
+DATABLOCK_ASSIGN_IPO(Lamp, lamp) // defines Lamp_assignIpo
+
+static struct PyMethodDef Lamp_methods[] = {
+ {"clrIpo", Lamp_clrIpo, METH_VARARGS, Lamp_clrIpo_doc},
+ {"assignIpo", Lamp_assignIpo, METH_VARARGS, Lamp_assignIpo_doc},
+ {NULL, NULL}
+};
+
+/********************/
+/* World Datablocks */
+
+DATABLOCK_GET(Worldmodule, world, getWorldList() )
+
+#ifdef FUTURE_PYTHON_API
+
+DataBlockProperty World_Properties[]= {
+
+ {"mode", "mode", DBP_TYPE_SHO, 0, 0.0, 0.0},
+ {"skyType", "skytype", DBP_TYPE_SHO, 0, 0.0, 0.0},
+ {"mistType", "mistype", DBP_TYPE_SHO, 0, 0.0, 0.0},
+ {"horR", "horr", DBP_TYPE_FLO, 0, 0.0, 1.0},
+ {"horG", "horg", DBP_TYPE_FLO, 0, 0.0, 1.0},
+ {"horB", "horb", DBP_TYPE_FLO, 0, 0.0, 1.0},
+ {"ambR", "ambr", DBP_TYPE_FLO, 0, 0.0, 1.0},
+ {"ambG", "ambg", DBP_TYPE_FLO, 0, 0.0, 1.0},
+ {"ambB", "ambb", DBP_TYPE_FLO, 0, 0.0, 1.0},
+ {"zenR", "zenr", DBP_TYPE_FLO, 0, 0.0, 1.0},
+ {"zenG", "zeng", DBP_TYPE_FLO, 0, 0.0, 1.0},
+ {"zenB", "zenb", DBP_TYPE_FLO, 0, 0.0, 1.0},
+ {"exposure", "exposure", DBP_TYPE_FLO, 0, 0.0, 5.0},
+ {"mistStart", "miststa", DBP_TYPE_FLO, 0, 0.0, 1000.0},
+ {"mistDepth", "mistdist", DBP_TYPE_FLO, 0, 0.0, 1000.0},
+ {"mistHeight", "misthi", DBP_TYPE_FLO, 0, 0.0, 100.0},
+ {"starDensity", "stardist", DBP_TYPE_FLO, 0, 2.0, 1000.0},
+ {"starMinDist", "starmindist", DBP_TYPE_FLO, 0, 0.0, 1000.0},
+ {"starSize", "starsize", DBP_TYPE_FLO, 0, 0.0, 10.0},
+ {"starColNoise", "starcolsize", DBP_TYPE_FLO, 0, 0.0, 1.0},
+ {"gravity", "gravity", DBP_TYPE_FLO, 0, 0.0, 25.0},
+
+ {"ipo", "*ipo", DBP_TYPE_FUN, 0, 0.0, 0.0, {0}, {0}, 0, 0, get_DataBlock_func},
+
+ {NULL}
+};
+
+#else
+
+DataBlockProperty World_Properties[]= {
+ {"HorR", "horr", DBP_TYPE_FLO, 0, 0.0, 1.0},
+ {"HorG", "horg", DBP_TYPE_FLO, 0, 0.0, 1.0},
+ {"HorB", "horb", DBP_TYPE_FLO, 0, 0.0, 1.0},
+ {"ZenR", "zenr", DBP_TYPE_FLO, 0, 0.0, 1.0},
+ {"ZenG", "zeng", DBP_TYPE_FLO, 0, 0.0, 1.0},
+ {"ZenB", "zenb", DBP_TYPE_FLO, 0, 0.0, 1.0},
+ {"Expos", "exposure", DBP_TYPE_FLO, 0, 0.0, 5.0},
+ {"MisSta", "miststa", DBP_TYPE_FLO, 0, 0.0, 1000.0},
+ {"MisDi", "mistdist", DBP_TYPE_FLO, 0, 0.0, 1000.0},
+ {"MisHi", "misthi", DBP_TYPE_FLO, 0, 0.0, 100.0},
+ {"StarDi", "stardist", DBP_TYPE_FLO, 0, 2.0, 1000.0},
+ {"StarSi", "starsize", DBP_TYPE_FLO, 0, 0.0, 10.0},
+
+ {"ipo", "*ipo", DBP_TYPE_FUN, 0, 0.0, 0.0, {0}, {0}, 0, 0, get_DataBlock_func},
+
+ {NULL}
+};
+
+#endif
+
+static char Worldmodule_getActive_doc[]="() - Returns the active world";
+static PyObject *Worldmodule_getActive (PyObject *self, PyObject *args)
+{
+ if (scene_getCurrent()->world)
+ return DataBlock_fromData(scene_getCurrent()->world);
+ else
+ return BPY_incr_ret(Py_None);
+}
+
+static struct PyMethodDef Worldmodule_methods[] = {
+ // these for compatibility...
+ {"get", Worldmodule_get, METH_VARARGS, Worldmodule_get_doc},
+#ifdef CURRENT_PYTHON_API
+ {"Get", Worldmodule_get, METH_VARARGS, Worldmodule_get_doc},
+#endif
+ {"getCurrent", Worldmodule_getActive, METH_VARARGS, Worldmodule_getActive_doc},
+ {NULL, NULL}
+};
+
+
+
+/* XXX these should go elsewhere */
+
+PyObject *BPY_PyList_FromIDList(ListBase *list, DBConvertfunc convertfunc)
+{
+ PyObject *pylist= PyList_New(BLI_countlist(list));
+ ID *id = list->first;
+
+ int i=0;
+
+ while (id) {
+ PyObject *ob= convertfunc(id);
+
+ if (!ob) {
+ Py_DECREF(pylist);
+ return NULL;
+ }
+ PyList_SetItem(pylist, i, ob);
+ id = id->next; i++;
+ }
+ return pylist;
+}
+
+
+PyObject *py_find_from_list(ListBase *list, PyObject *args) {
+ char *name= NULL;
+ ID *id = list->first;
+ BPY_TRY(PyArg_ParseTuple(args, "|s", &name));
+
+ if (name) {
+ while (id) {
+ if (strcmp(name, getIDName(id))==0)
+ return DataBlock_fromData(id);
+
+ id= id->next;
+ }
+ return BPY_incr_ret(Py_None);
+
+ } else
+ return BPY_PyList_FromIDList(list, DataBlock_fromData);
+}
+
+PyObject *named_enum_get(int val, NamedEnum *enums) {
+ while (enums->name) {
+ if (enums->num == val) return PyString_FromString(enums->name);
+ enums++;
+ }
+ PyErr_SetString(PyExc_AttributeError, "Internal error, Unknown enumerated type");
+ return NULL;
+}
+
+int named_enum_set(char *name, NamedEnum *enums) {
+ while (enums->name) {
+ if (STREQ(enums->name, name))
+ return enums->num;
+ enums++;
+ }
+
+ return -1;
+}
+
+static int calc_offset_subsize(int *dlist, int *idx, int *subsize) {
+ int n= *dlist;
+
+ if (n<=0) {
+ *subsize= -n;
+ return 0;
+ } else {
+ int ss;
+ int off= calc_offset_subsize(dlist+1, idx+1, &ss);
+
+ *subsize= n*ss;
+ return off + (*idx)*ss;
+ }
+}
+
+static int calc_offset(int *dlist, int *idx) {
+ int subsize;
+ return calc_offset_subsize(dlist, idx, &subsize);
+}
+
+static void *get_db_ptr(DataBlockProperty *prop, char *structname, void *struct_ptr) {
+ int offset= BLO_findstruct_offset(structname, prop->struct_name);
+ void *ptr= struct_ptr;
+
+ if (offset==-1) {
+ BPY_warn(("Internal error, Invalid prop entry\n"));
+ return NULL;
+ }
+
+ ptr= (void *) (((char *)ptr) + offset);
+
+ offset= calc_offset(prop->dlist, prop->idx);
+ ptr= (void *) (((char *)ptr) + offset);
+
+ return ptr;
+}
+
+PyObject *datablock_getattr(DataBlockProperty *props, char *structname, char *name, void *struct_ptr) {
+ if (STREQ(name, "properties") || STREQ(name, "__members__")) {
+ PyObject *l= PyList_New(0);
+ DataBlockProperty *p= props;
+
+ while (p->public_name) {
+ PyList_Append(l, PyString_FromString(p->public_name));
+ p++;
+ }
+
+ return l;
+ }
+
+ while (props->public_name) {
+ if (STREQ(name, props->public_name)) {
+ void *ptr = struct_ptr;
+ int val;
+ DBPtrToObFP conv_fp;
+
+ if (props->handling==DBP_HANDLING_NONE ||
+ props->handling==DBP_HANDLING_NENM) {
+ ptr= get_db_ptr(props, structname, struct_ptr);
+ if (!ptr) return NULL;
+
+ } else if (props->handling==DBP_HANDLING_FUNC) {
+ DBGetPtrFP fp= (DBGetPtrFP) props->extra1;
+ ptr= fp(struct_ptr, props->struct_name, 0);
+ if (!ptr) return NULL;
+ }
+
+ switch(props->type) {
+ case DBP_TYPE_CHA:
+ val= *((char *)ptr);
+ if (props->handling==DBP_HANDLING_NENM)
+ return named_enum_get(val, props->extra1);
+ else
+ return PyInt_FromLong(val);
+ case DBP_TYPE_SHO:
+ val= *((short *)ptr);
+ if (props->handling==DBP_HANDLING_NENM)
+ return named_enum_get(val, props->extra1);
+ else
+ return PyInt_FromLong(val);
+ case DBP_TYPE_INT:
+ val= *((int *)ptr);
+ if (props->handling==DBP_HANDLING_NENM)
+ return named_enum_get(val, props->extra1);
+ else
+ return PyInt_FromLong(val);
+ case DBP_TYPE_FLO:
+ return PyFloat_FromDouble ( *((float *)ptr) );
+ case DBP_TYPE_VEC:
+ return newVectorObject ( ((float *)ptr), (int) props->min );
+ case DBP_TYPE_FUN:
+ conv_fp= (DBPtrToObFP) props->extra2;
+ return conv_fp( ptr );
+ default:
+ PyErr_SetString(PyExc_AttributeError, "Internal error, Unknown prop type");
+ return NULL;
+ }
+ }
+
+ props++;
+ }
+
+ PyErr_SetString(PyExc_AttributeError, name);
+ return NULL;
+}
+
+int datablock_setattr(DataBlockProperty *props, char *structname, char *name, void *struct_ptr, PyObject *setto) {
+
+ while (props->public_name) {
+ if (STREQ(props->public_name, name)) {
+ void *ptr = NULL;
+ int type;
+ DBSetPtrFP conv_fp;
+ int clamp= props->min!=props->max;
+
+ int enum_val= -1;
+ char cha_data;
+ short sho_data;
+ int int_data;
+ float flo_data;
+
+ type= props->stype;
+ if (type==DBP_TYPE_NON) type= props->type;
+
+ if (props->handling==DBP_HANDLING_NONE) {
+ ptr= get_db_ptr(props, structname, struct_ptr);
+ if (!ptr) return 0;
+
+ } else if (props->handling==DBP_HANDLING_FUNC) {
+ if (type!=DBP_TYPE_FUN) {
+ DBGetPtrFP fp= (DBGetPtrFP) props->extra1;
+ ptr= fp(struct_ptr, props->struct_name, 1);
+ if (!ptr) return 0;
+ }
+ } else if (props->handling==DBP_HANDLING_NENM) {
+ char *str;
+ if (!PyArg_Parse(setto, "s", &str)) return -1;
+
+ ptr= get_db_ptr(props, structname, struct_ptr);
+ if (!ptr) return 0;
+
+ enum_val= named_enum_set(str, props->extra1);
+ if (enum_val==-1)
+ return py_err_ret_int(PyExc_AttributeError, "invalid setting for field");
+ }
+
+ switch(type) {
+ case DBP_TYPE_CHA:
+ if (enum_val==-1) {
+ if (!PyArg_Parse(setto, "b", &cha_data)) return -1;
+ } else cha_data= (char) enum_val;
+
+ if (clamp) {
+ CLAMP(cha_data, (char) props->min, (char) props->max);
+ }
+ *((char *)ptr)= cha_data;
+ return 0;
+ case DBP_TYPE_SHO:
+ if (enum_val==-1) {
+ if (!PyArg_Parse(setto, "h", &sho_data)) return -1;
+ } else sho_data= (short) enum_val;
+
+ if (clamp) {
+ CLAMP(sho_data, (short) props->min, (short) props->max);
+ }
+ *((short *)ptr)= sho_data;
+ return 0;
+ case DBP_TYPE_INT:
+ if (enum_val==-1) {
+ if (!PyArg_Parse(setto, "i", &int_data)) return -1;
+ } else int_data= (int) enum_val;
+
+ if (clamp) {
+ CLAMP(int_data, (int) props->min, (int) props->max);
+ }
+ *((int *)ptr)= int_data;
+ return 0;
+ case DBP_TYPE_FLO:
+ if (!PyArg_Parse(setto, "f", &flo_data)) return -1;
+ if (clamp) {
+ CLAMP(flo_data, (float) props->min, (float) props->max);
+ }
+ *((float *)ptr)= flo_data;
+ return 0;
+ case DBP_TYPE_VEC:
+ /* this is very dangerous!! TYPE_VEC also can contain non floats; see
+ * ipo curve attribute h1t, etc. */
+ if (props->min == 3.0 ) { // vector triple
+ return BPY_parsefloatvector(setto, (float *) ptr, 3);
+ } else {
+ return py_err_ret_int(PyExc_AttributeError, "cannot directly assign, use slice assignment instead");
+ }
+ return 0;
+
+ case DBP_TYPE_FUN:
+ conv_fp= (DBSetPtrFP) props->extra3;
+ if (conv_fp)
+ return conv_fp( struct_ptr, props->struct_name, setto );
+ else
+ return py_err_ret_int(PyExc_AttributeError, "cannot directly assign to item");
+ default:
+ PyErr_SetString(PyExc_AttributeError, "Internal error, Unknown prop type");
+ return -1;
+ }
+ }
+
+ props++;
+ }
+
+ PyErr_SetString(PyExc_AttributeError, name);
+ return -1;
+}
+
+PyObject *datablock_assignIpo(DataBlock *block, DataBlock *ipoblock)
+{
+ Ipo **ipoptr;
+ Ipo *ipo;
+
+ if (!DataBlock_isType(ipoblock, ID_IP)) {
+ PyErr_SetString(PyExc_TypeError, "expects Ipo object");
+ return 0;
+ }
+
+ ipo = PYBLOCK_AS_IPO(ipoblock);
+
+ if (DataBlock_type(block) != ipo->blocktype) {
+ PyErr_SetString(PyExc_TypeError, "Ipo type does not match object type!");
+ return 0;
+ }
+
+ ipoptr = get_db_ptr(block->properties, "ipo", block->data);
+ if (!ipoptr) {
+ PyErr_SetString(PyExc_RuntimeError, "Object does not have an ipo!");
+ return 0;
+ }
+
+ *ipoptr = ipo;
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+/* deallocates a Python Datablock object */
+void DataBlock_dealloc(DataBlock *self)
+{
+#ifdef REF_USERCOUNT
+ BOB_XDECUSER(DATABLOCK_ID(self)); // XXX abuse for ref count
+#endif
+ PyMem_DEL(self);
+}
+
+PyObject *DataBlock_repr(DataBlock *self)
+{
+ static char s[256];
+ if (self->data)
+ sprintf (s, "[%.32s %.32s]", self->type, getIDName((ID*)self->data));
+ else
+ sprintf (s, "[%.32s %.32s]", self->type, "<deleted>");
+ return Py_BuildValue("s", s);
+}
+
+/* ************************************************************************* */
+/* datablock linking */
+
+/** Link data to Object */
+
+static PyObject *link_Data_toObject(DataBlock *objectblk, DataBlock *datablk)
+{
+ Object *object = PYBLOCK_AS_OBJECT(objectblk);
+
+ void *data = datablk->data;
+ if (!object_linkdata(object, data))
+ {
+ PyErr_SetString(PyExc_TypeError,
+ "Object type different from Data type or linking for this type\
+ not supported");
+ return NULL;
+ }
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+
+#ifdef USE_NMESH
+/** Special function to link NMesh data to an Object */
+static PyObject *link_NMesh_toObject(DataBlock *objectblk, NMesh *nmesh)
+{
+ int retval;
+ Mesh *mesh = nmesh->mesh;
+ Object *obj = PYBLOCK_AS_OBJECT(objectblk);
+
+ // if mesh was not created yet (mesh == 0), then do so:
+ if (!mesh) {
+ mesh = Mesh_fromNMesh(nmesh); // create and convert data
+ nmesh->mesh = mesh;
+ nmesh_updateMaterials(nmesh);
+ }
+
+ retval = object_linkdata(obj, mesh);
+ if (!retval) {
+ PyErr_SetString(PyExc_RuntimeError, "failed to link NMesh data");
+ if (!mesh)
+ printf("mesh data was null\n"); // XXX
+ return NULL;
+ }
+ synchronizeMaterialLists(obj, obj->data);
+ return Py_BuildValue("i", retval);
+}
+
+#endif
+
+/** This is the generic function for linking objects with each other.
+ * It can be called on any DataBlock, as long as this makes sense.
+ * Example:
+ *
+ * from Blender import Object, Scene, NMesh
+ * ob = Object.get("Plane")
+ * scene = Scene.get("2")
+ * ob.link(scene)
+ *
+ * or
+ *
+ * nmesh = NMesh.GetRaw('Mesh')
+ * ob.link(nmesh) # instanciate mesh
+ *
+ */
+
+static char DataBlock_link_doc[]=
+"(object) - Links 'self' with the specified object.\n\
+Only the following object types can be linked to each other:\n\
+ Scene -> Object\n\
+ Object -> Data (Mesh, Curve, etc.)\n\
+ Object -> Materials: [Material1, Material2, ...]\n\
+\n\
+The order of linking does not matter, i.e. the following both expressions\n\
+are valid:\n\
+\n\
+ scene.link(object)\n\
+\n\
+ object.link(scene)\n\
+";
+
+PyObject *DataBlock_link(PyObject *self, PyObject *args)
+{
+ DataBlock *blockA= (DataBlock*) self;
+ PyObject *with;
+ DataBlock *blockB;
+
+#ifdef USE_NMESH
+ BPY_TRY(PyArg_ParseTuple(args, "O", &with));
+
+ blockB = (DataBlock *) with;
+#else
+ BPY_TRY(PyArg_ParseTuple(args, "O!", &DataBlock_Type, &blockB));
+#endif
+
+ switch (DataBlock_type(blockA)) {
+ case ID_OB:
+ // NMesh is no datablock object, so needs special treatment:
+#ifdef USE_NMESH
+ if (NMesh_Check(with)) {
+ return link_NMesh_toObject(blockA, (NMesh *) with);
+ }
+#endif
+ if (!DataBlock_Check(blockB)) {
+ PyErr_SetString(PyExc_TypeError, "Argument must be a DataBlock object!");
+ return NULL;
+ }
+ return link_Data_toObject(blockA, blockB);
+
+ default:
+ PyErr_SetString(PyExc_TypeError, "FATAL: implementation error, illegal link method");
+ return NULL;
+ }
+}
+
+/* unlinking currently disabled, but might me needed later
+ for other object types...
+
+static char DataBlock_unlink_doc[]=
+"(object) - unlinks 'self' from the specified object.\n\
+See documentation for link() for valid object types.";
+
+static PyObject *DataBlock_unlink(PyObject *self, PyObject *args)
+{
+ DataBlock *blockA= (DataBlock*) self;
+ DataBlock *blockB;
+
+ BPY_TRY(PyArg_ParseTuple(args, "O!", &DataBlock_Type, &blockB));
+ switch (DataBlock_type(blockA)) {
+ case ID_SCE:
+ switch(DataBlock_type(blockB)) {
+ case ID_OB:
+ return unlink_Object_fromScene(blockA, blockB);
+ default:
+ PyErr_SetString(PyExc_TypeError, "Scene unlink: invalid Object type");
+ return NULL;
+ }
+ default:
+ PyErr_SetString(PyExc_TypeError, "cannot unlink: invalid object type");
+ return NULL;
+
+ }
+
+}
+*/
+
+/** These are the methods common to each datablock */
+
+static struct PyMethodDef commonDataBlock_methods[] = {
+ {"link", DataBlock_link, METH_VARARGS, DataBlock_link_doc},
+// {"unlink", DataBlock_unlink, METH_VARARGS, DataBlock_unlink_doc},
+ {NULL}
+};
+
+PyObject *DataBlock_getattr(PyObject *self, char *name) {
+ DataBlock *block= (DataBlock*) self;
+ PyObject *ret = NULL;
+ CHECK_VALIDDATA(block, "block was deleted!")
+
+ // Check for common attributes:
+ if (STREQ(name, "name"))
+ return PyString_FromString((((ID*)block->data)->name)+2);
+ else if (STREQ(name, "block_type"))
+ return PyString_FromString(block->type);
+ else if (STREQ(name, "users"))
+ return PyInt_FromLong(((ID*)block->data)->us);
+
+ //
+ // the following datablock types have methods:
+ switch (DataBlock_type(block)) {
+ case ID_OB:
+ ret = Py_FindMethod(Object_methods, self, name);
+ break;
+ case ID_IP:
+ ret = Py_FindMethod(Ipo_methods, self, name);
+ break;
+ case ID_CA:
+ ret = Py_FindMethod(Camera_methods, self, name);
+ break;
+ case ID_MA:
+ ret = Py_FindMethod(Material_methods, self, name);
+ break;
+ case ID_LA:
+ ret = Py_FindMethod(Lamp_methods, self, name);
+ break;
+ case ID_TXT:
+ ret = Py_FindMethod(Text_methods, self, name);
+ break;
+ }
+ if (ret) return ret;
+ PyErr_Clear(); // no method found, clear error
+
+ // try common datablock methods
+ ret = Py_FindMethod(commonDataBlock_methods, (PyObject*)self, name);
+ if (ret) return ret;
+
+ PyErr_Clear();
+
+ // try attributes from property list
+ ret = datablock_getattr(block->properties, block->type, name, block->data);
+ return ret;
+}
+
+int DataBlock_setattr(PyObject *self, char *name, PyObject *ob) {
+ DataBlock *block= (DataBlock*) self;
+
+ CHECK_VALIDDATA(block, "block was deleted!")
+
+ if (STREQ(name, "name")) {
+ if (!PyArg_Parse(ob, "s", &name)) return -1;
+
+ new_id(block->type_list, (ID*)block->data, name);
+
+ return 0;
+ }
+ return datablock_setattr(block->properties, block->type, name, block->data, ob);
+}
+
+
+PyTypeObject DataBlock_Type = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "Block", /*tp_name*/
+ sizeof(DataBlock), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ (destructor) DataBlock_dealloc, /*tp_dealloc*/
+ (printfunc) 0, /*tp_print*/
+ (getattrfunc) DataBlock_getattr, /*tp_getattr*/
+ (setattrfunc) DataBlock_setattr, /*tp_setattr*/
+ (cmpfunc) 0, /*tp_compare*/
+ (reprfunc) DataBlock_repr, /*tp_repr*/
+};
+
+/**************************************************************************/
+
+/**********************/
+/* Texture Datablocks */
+/*
+DATABLOCK_GET(Texturemodule, texture, getTextureList())
+
+static struct PyMethodDef Texture_methods[] = {
+ {"Get", Texture_Get, 1, Texture_Get_doc},
+ {NULL, NULL}
+};
+*/
+
+
+
+/* ---------------------------------------------------------------------- */
+
+int DataBlock_type(DataBlock *block)
+{
+ return (GET_ID_TYPE((ID *) block->data));
+}
+
+int ObjectDataIDType(DataBlock *block)
+{
+ Object *ob;
+ if (!DataBlock_isType(block, ID_OB))
+ return -1;
+
+ ob = (Object *) block->data;
+ return GET_ID_TYPE((ID *) ob->data);
+}
+
+int DataBlock_isType(DataBlock *block, int type)
+{
+ ID *id;
+
+ if (!DataBlock_Check(block)) return 0;
+ id= (ID *) block->data;
+ return (GET_ID_TYPE(id))==type;
+}
+
+/** This function creates a Python datablock descriptor object from
+ * the specified data pointer. This pointer must point to a structure
+ * with a valid ID header.
+ */
+
+PyObject *DataBlock_fromData(void *data) {
+ DataBlock *newb;
+ ID *id= (ID *) data;
+ int idn;
+
+ if (!data) return BPY_incr_ret(Py_None);
+
+ idn = GET_ID_TYPE(id);
+
+ if (idn==ID_OB) {
+ newb= PyObject_NEW(DataBlock, &DataBlock_Type);
+ newb->type= "Object";
+ newb->type_list= getObjectList();
+ newb->properties= Object_Properties;
+
+ } else if (idn==ID_ME) {
+#ifdef USE_NMESH
+ return newNMesh(data);
+#else
+ newb= PyObject_NEW(DataBlock, &DataBlock_Type);
+ newb->type= "Mesh";
+ newb->type_list= getMeshList();
+ newb->properties= Mesh_Properties;
+#endif
+
+// } else if (idn==ID_CU) {
+ /* Special case, should be fixed
+ * by proper high-level NURBS access.
+ *
+ * Later.
+ */
+
+// return newNCurveObject(data);
+
+ } else if (idn==ID_LA) {
+ newb= PyObject_NEW(DataBlock, &DataBlock_Type);
+ newb->type= "Lamp";
+ newb->type_list= getLampList();
+ newb->properties= Lamp_Properties;
+
+ } else if (idn==ID_CA) {
+ newb= PyObject_NEW(DataBlock, &DataBlock_Type);
+ newb->type= "Camera";
+ newb->type_list= getCameraList();
+ newb->properties= Camera_Properties;
+
+ } else if (idn==ID_MA) {
+ newb= PyObject_NEW(DataBlock, &DataBlock_Type);
+ newb->type= "Material";
+ newb->type_list= getMaterialList();
+ newb->properties= Material_Properties;
+
+ } else if (idn==ID_WO) {
+ newb= PyObject_NEW(DataBlock, &DataBlock_Type);
+ newb->type= "World";
+ newb->type_list= getWorldList();
+ newb->properties= World_Properties;
+
+ } else if (idn==ID_IP) {
+ newb= PyObject_NEW(DataBlock, &DataBlock_Type);
+ newb->type= "Ipo";
+ newb->type_list= getIpoList();
+ newb->properties= Ipo_Properties;
+
+#ifdef EXPERIMENTAL
+ } else if (idn==ID_TE) {
+ newb= PyObject_NEW(DataBlock, &DataBlock_Type);
+ newb->type= "Tex";
+ newb->type_list= getTextureList();
+ newb->properties= Texture_Properties;
+#endif
+
+ } else if (idn==ID_IM) {
+ newb= PyObject_NEW(DataBlock, &DataBlock_Type);
+ newb->type= "Image";
+ newb->type_list= getImageList();
+ newb->properties= Image_Properties;
+
+ } else if (idn==ID_TXT) {
+ newb= PyObject_NEW(DataBlock, &DataBlock_Type);
+ newb->type= "Text";
+ newb->type_list= getTextList();
+ newb->properties= Text_Properties;
+ } else return BPY_err_ret_ob(PyExc_SystemError, "unable to create Block for data");
+
+ newb->data= data;
+#ifdef REF_USERCOUNT
+ BOB_INCUSER(id); // XXX abuse for refcount
+#endif
+
+ return (PyObject *) newb;
+}
+
+PyObject *get_DataBlock_func(void **ptr) {
+ ID *id= (ID*) *ptr;
+ return DataBlock_fromData(id);
+}
+
+/* ---------------------------------------------------------------------- */
+/* INIT ROUTINE */
+
+
+void init_types(PyObject *dict)
+{
+ PyObject *tmod, *tdict;
+
+ tmod= Py_InitModule("Blender.Types", Null_methods);
+ PyDict_SetItemString(dict, "Types", tmod);
+
+ tdict= PyModule_GetDict(tmod);
+
+ PyDict_SetItemString(tdict, "IpoCurve", (PyObject *)&PyIpoCurve_Type);
+ PyDict_SetItemString(tdict, "BezTriple", (PyObject *)&PyBezTriple_Type);
+
+ PyDict_SetItemString(tdict, "ButtonType", (PyObject *)&Button_Type);
+ PyDict_SetItemString(tdict, "BufferType", (PyObject *)&Buffer_Type);
+ PyDict_SetItemString(tdict, "NMeshType", (PyObject *)&NMesh_Type);
+ PyDict_SetItemString(tdict, "NMFaceType", (PyObject *)&NMFace_Type);
+ PyDict_SetItemString(tdict, "NMVertType", (PyObject *)&NMVert_Type);
+ PyDict_SetItemString(tdict, "NMColType", (PyObject *)&NMCol_Type);
+
+ PyDict_SetItemString(tdict, "BlockType", (PyObject *)&DataBlock_Type);
+
+ /* Setup external types */
+ PyDict_SetItemString(tdict, "VectorType", (PyObject *)&Vector_Type);
+ PyDict_SetItemString(tdict, "MatrixType", (PyObject *)&Matrix_Type);
+}
+
+#undef BPY_ADDCONST
+#define BPY_ADDCONST(dict, name) insertConst(dict, #name, PyInt_FromLong(LA_##name))
+
+PyObject *initLamp(void)
+{
+ PyObject *mod, *dict, *d;
+
+ mod= Py_InitModule(MODNAME(BLENDERMODULE) ".Lamp", Lampmodule_methods);
+ dict= PyModule_GetDict(mod);
+ d = ConstObject_New();
+ PyDict_SetItemString(dict, "Types", d);
+
+ /* type */
+ BPY_ADDCONST(d, LOCAL);
+ BPY_ADDCONST(d, SUN);
+ BPY_ADDCONST(d, SPOT);
+ BPY_ADDCONST(d, HEMI);
+
+ d = ConstObject_New();
+ PyDict_SetItemString(dict, "Modes", d);
+
+ /* mode */
+ BPY_ADDCONST(d, SHAD);
+ BPY_ADDCONST(d, HALO);
+ BPY_ADDCONST(d, LAYER);
+ BPY_ADDCONST(d, QUAD);
+ BPY_ADDCONST(d, NEG);
+ BPY_ADDCONST(d, ONLYSHADOW);
+ BPY_ADDCONST(d, SPHERE);
+ BPY_ADDCONST(d, SQUARE);
+ BPY_ADDCONST(d, TEXTURE);
+ BPY_ADDCONST(d, OSATEX);
+ BPY_ADDCONST(d, DEEP_SHADOW);
+
+ return mod;
+}
+
+PyObject *initMaterial(void)
+{
+ PyObject *mod, *dict, *d;
+
+ mod= Py_InitModule(MODNAME(BLENDERMODULE) ".Material",
+ Materialmodule_methods);
+ dict= PyModule_GetDict(mod);
+ d = ConstObject_New();
+ PyDict_SetItemString(dict, "Modes", d);
+
+ /* MATERIAL MODES
+ * ...some of these have really cryptic defines :-)
+ * We try to match them to the GUI descriptions... */
+
+#undef BPY_ADDCONST
+#define BPY_ADDCONST(dict, name) \
+ insertConst(dict, #name, PyInt_FromLong(MA_##name))
+
+ insertConst(d, "TRACEABLE", PyInt_FromLong(MA_TRACEBLE));
+ BPY_ADDCONST(d, SHADOW);
+ insertConst(d, "SHADELESS", PyInt_FromLong(MA_SHLESS));
+ BPY_ADDCONST(d, WIRE);
+ insertConst(d, "VCOL_LIGHT", PyInt_FromLong(MA_VERTEXCOL));
+ BPY_ADDCONST(d, HALO);
+ insertConst(d, "ZTRANSP", PyInt_FromLong(MA_ZTRA));
+ insertConst(d, "VCOL_PAINT", PyInt_FromLong(MA_VERTEXCOLP));
+ insertConst(d, "ZINVERT", PyInt_FromLong(MA_ZINV));
+ BPY_ADDCONST(d, ONLYSHADOW);
+ BPY_ADDCONST(d, STAR);
+ insertConst(d, "TEXFACE", PyInt_FromLong(MA_FACETEXTURE));
+ BPY_ADDCONST(d, NOMIST);
+
+ /* HALO MODES */
+ d = ConstObject_New();
+ PyDict_SetItemString(dict, "HaloModes", d);
+
+#undef BPY_ADDCONST
+#define BPY_ADDCONST(dict, name) \
+ insertConst(dict, #name, PyInt_FromLong(MA_HALO_##name))
+
+ BPY_ADDCONST(d, RINGS);
+ BPY_ADDCONST(d, LINES);
+ insertConst(d, "TEX", PyInt_FromLong(MA_HALOTEX));
+ insertConst(d, "PUNO", PyInt_FromLong(MA_HALOPUNO));
+ BPY_ADDCONST(d, SHADE);
+ BPY_ADDCONST(d, FLARE);
+
+ return mod;
+}
+
+void init_Datablockmodules(PyObject *dict) {
+#define MODLOAD(name) PyDict_SetItemString(dict, #name, Py_InitModule(MODNAME(BLENDERMODULE) "." #name, name##module_methods))
+
+ DataBlock_Type.ob_type = &PyType_Type;
+ PyIpoCurve_Type.ob_type= &PyType_Type;
+ PyBezTriple_Type.ob_type= &PyType_Type;
+
+ PyDict_SetItemString(dict, "Object", initObject());
+ PyDict_SetItemString(dict, "Lamp", initLamp());
+ PyDict_SetItemString(dict, "Material", initMaterial());
+ PyDict_SetItemString(dict, "Ipo", initIpo());
+ PyDict_SetItemString(dict, "Scene", initScene());
+ MODLOAD(Text);
+// MODLOAD(Mesh);
+ MODLOAD(Camera);
+ MODLOAD(World);
+ MODLOAD(Image);
+/* MODLOAD(Texture); */
+}
diff --git a/source/blender/bpython/intern/opy_datablock.h b/source/blender/bpython/intern/opy_datablock.h
new file mode 100644
index 00000000000..437b551a754
--- /dev/null
+++ b/source/blender/bpython/intern/opy_datablock.h
@@ -0,0 +1,193 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "BSE_edit.h" // for getname_< >_ei()
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_scene.h"
+
+/* for a few protos: only*/
+#include "BKE_library.h"
+#include "BKE_object.h"
+#include "BKE_ika.h"
+#include "BKE_ipo.h"
+#include "BKE_key.h"
+
+#include "BLI_blenlib.h"
+#include "BLO_genfile.h" // BLO_findstruct_offset()
+#include "DNA_ID.h"
+#include "DNA_curve_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_key_types.h"
+#include "DNA_material_types.h"
+#include "DNA_object_types.h"
+#include "DNA_ipo_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_ika_types.h"
+
+#include "BPY_constobject.h"
+
+typedef struct _NamedEnum {
+ char *name;
+ int num;
+} NamedEnum;
+
+extern PyTypeObject DataBlock_Type;
+
+#define DataBlock_Check(v) ((v)->ob_type == &DataBlock_Type)
+
+typedef struct _DataBlockProperty {
+ char *public_name;
+ char *struct_name;
+
+ int type;
+#define DBP_TYPE_CHA 1 /* Char item */
+#define DBP_TYPE_SHO 2 /* Short item */
+#define DBP_TYPE_INT 3 /* Int item */
+#define DBP_TYPE_FLO 4 /* Float item */
+#define DBP_TYPE_VEC 5 /* Float vector object */
+#define DBP_TYPE_FUN 6 /* Extra2 hold function to convert ptr->ob
+ extra3 holds function to convert ob->ptr */
+
+ int stype;
+#define DBP_TYPE_NON 0
+
+ float min; /* Minimum allowed value */
+ float max; /* Maximum allowed value */
+
+ int idx[4];
+ int dlist[4];
+
+ int handling;
+#define DBP_HANDLING_NONE 0 /* No special handling required */
+#define DBP_HANDLING_FUNC 1 /* Extra1 is used to retrieve ptr */
+#define DBP_HANDLING_NENM 2 /* Extra1 holds named enum to resolve
+ values from/to. */
+
+ void *extra1;
+ void *extra2;
+ void *extra3;
+} DataBlockProperty;
+
+
+/* function pointers needed for callbacks */
+
+typedef void *(*DBGetPtrFP) (void *struct_ptr, char *name, int forsetting);
+typedef PyObject * (*DBPtrToObFP) (void **ptr);
+typedef int (*DBSetPtrFP) (void *struct_ptr, char *name, PyObject *ob);
+typedef PyObject *(*DBConvertfunc) (void *data);
+
+
+typedef struct {
+ PyObject_HEAD
+ void *data;
+ char *type;
+ ListBase *type_list;
+ DataBlockProperty *properties;
+} DataBlock;
+
+/* PROTOS */
+
+/* opy_datablock.c */
+PyObject *BPY_PyList_FromIDList(ListBase *list, DBConvertfunc convertfunc);
+PyObject *get_DataBlock_func(void **p);
+
+PyObject *py_find_from_list (ListBase *list, PyObject *args);
+PyObject *named_enum_get (int val, NamedEnum *enums);
+int named_enum_set (char *name, NamedEnum *enums);
+PyObject *datablock_getattr (DataBlockProperty *props, char *structname,
+ char *name, void *struct_ptr);
+int datablock_setattr (DataBlockProperty *props, char *structname,
+ char *name, void *struct_ptr, PyObject *setto);
+PyObject *datablock_assignIpo(DataBlock *block, DataBlock *ipoblock);
+
+
+/* DataBlock Methods */
+
+void DataBlock_dealloc (DataBlock *self);
+int DataBlock_print (PyObject *self, FILE *fp, int flags);
+PyObject *DataBlock_getattr (PyObject *self, char *name);
+int DataBlock_setattr (PyObject *self, char *name, PyObject *ob);
+int DataBlock_type(DataBlock *block);
+int DataBlock_isType (DataBlock *block, int type);
+PyObject *DataBlock_fromData (void *data);
+PyObject *DataBlock_link(PyObject *self, PyObject *args);
+
+PyObject *make_icu_list (ListBase *curves);
+void pybzt_dealloc (PyObject *self);
+int pybzt_print (PyObject *self, FILE *fp, int flags);
+PyObject *pybzt_getattr (PyObject *self, char *name);
+int pybzt_setattr (PyObject *self, char *name, PyObject *ob);
+PyObject *pybzt_create (PyObject *self, PyObject *args);
+PyObject *pybzt_from_bzt (BezTriple *bzt);
+void pyicu_dealloc (PyObject *self);
+int pyicu_print (PyObject *self, FILE *fp, int flags);
+PyObject *pyicu_getattr (PyObject *self, char *name);
+int pyicu_setattr (PyObject *self, char *name, PyObject *ob);
+PyObject *pyicu_from_icu (IpoCurve *icu);
+PyObject *Ipo_Recalc (PyObject *self, PyObject *args);
+PyObject *Ipo_Eval (PyObject *self, PyObject *args);
+void init_types (PyObject *dict);
+void init_Datablockmodules (PyObject *dict);
+PyObject *getInverseMatrix(void *vdata);
+
+
+/* Object module */
+void *Object_special_getattr(void *vdata, char *name);
+int Object_special_setattr(void *vdata, char *name, PyObject *py_ob);
+
+extern PyObject *initObject(void);
+extern struct PyMethodDef Objectmodule_methods[];
+extern struct PyMethodDef Object_methods[];
+extern DataBlockProperty Object_Properties[];
+
+extern struct PyMethodDef Imagemodule_methods[];
+extern DataBlockProperty Image_Properties[];
+extern PyObject *initScene(void);
+extern struct PyMethodDef Scenemodule_methods[];
+
+extern PyObject *initIpo(void);
+extern struct PyMethodDef Ipo_methods[];
+extern struct PyMethodDef Ipomodule_methods[];
+extern DataBlockProperty Ipo_Properties[];
+
+
+extern struct PyMethodDef Textmodule_methods[];
+extern struct PyMethodDef Text_methods[];
+extern DataBlockProperty Text_Properties[];
+
+
+
+struct Material;
+
+struct
+Material **newMaterialList_fromPyList(PyObject *list);
+PyObject *PyList_fromMaterialList(struct Material **matlist, int len);
diff --git a/source/blender/bpython/intern/opy_draw.c b/source/blender/bpython/intern/opy_draw.c
new file mode 100644
index 00000000000..23929b1392f
--- /dev/null
+++ b/source/blender/bpython/intern/opy_draw.c
@@ -0,0 +1,2679 @@
+/* python.c MIXED MODEL
+ *
+ * june 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 *****
+ */
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "BMF_Api.h"
+
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_text_types.h"
+
+#include "BKE_global.h"
+
+#include "BIF_gl.h"
+#include "BIF_screen.h"
+#include "BIF_space.h"
+#include "BIF_interface.h"
+#include "BIF_mywindow.h"
+
+#include "interface.h"
+#include "mydevice.h" /* for all the event constants */
+
+#include "Python.h"
+#include "BPY_macros.h"
+#include "BPY_main.h"
+#include "BPY_tools.h"
+
+int disable_force_draw= 0;
+
+/* hack to flag that window redraw has happened inside slider callback: */
+
+static void exit_pydraw (SpaceText *st);
+static uiBlock *Get_uiBlock (void);
+void initDraw (void);
+
+/* Button Object */
+
+typedef struct _Button {
+ PyObject_VAR_HEAD
+
+ int type; /* 1 == int, 2 == float, 3 == string */
+ int slen; /* length of string (if type == 3) */
+ union {
+ int asint;
+ float asfloat;
+ char *asstr;
+ } val;
+} Button;
+
+
+static void Button_dealloc(PyObject *self) {
+ Button *but= (Button*) self;
+
+ if(but->type==3) MEM_freeN(but->val.asstr);
+
+ PyMem_DEL(self);
+}
+
+static PyObject *Button_getattr(PyObject *self, char *name) {
+ Button *but= (Button*) self;
+
+ if(STREQ(name, "val")) {
+ if (but->type==1)
+ return Py_BuildValue("i", but->val.asint);
+ else if (but->type==2)
+ return Py_BuildValue("f", but->val.asfloat);
+ else if (but->type==3)
+ return Py_BuildValue("s", but->val.asstr);
+ }
+ PyErr_SetString(PyExc_AttributeError, name);
+ return NULL;
+}
+
+static int Button_setattr(PyObject *self, char *name, PyObject *v) {
+ Button *but= (Button*) self;
+
+ if(STREQ(name, "val")) {
+ if (but->type==1)
+ PyArg_Parse(v, "i", &but->val.asint);
+ else if (but->type==2)
+ PyArg_Parse(v, "f", &but->val.asfloat);
+ else if (but->type==3) {
+ char *newstr;
+
+ PyArg_Parse(v, "s", &newstr);
+ strncpy(but->val.asstr, newstr, but->slen);
+ }
+ } else {
+ PyErr_SetString(PyExc_AttributeError, name);
+ return -1;
+ }
+
+ return 0;
+}
+
+static PyObject *Button_repr(PyObject *self) {
+ return PyObject_Repr(Button_getattr(self, "val"));
+}
+
+PyTypeObject Button_Type = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "Button", /*tp_name*/
+ sizeof(Button), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ (destructor) Button_dealloc, /*tp_dealloc*/
+ (printfunc) 0, /*tp_print*/
+ (getattrfunc) Button_getattr, /*tp_getattr*/
+ (setattrfunc) Button_setattr, /*tp_setattr*/
+ (cmpfunc) 0, /*tp_cmp*/
+ (reprfunc) Button_repr, /*tp_repr*/
+};
+
+
+static Button *newbutton (void) {
+ Button *but= (Button *) PyObject_NEW(Button, &Button_Type);
+
+ return but;
+}
+
+
+/* GUI interface routines */
+
+static void exit_pydraw(SpaceText *st)
+{
+ scrarea_queue_redraw(st->area);
+
+ if (st) {
+ Py_XDECREF((PyObject *) st->py_draw);
+ Py_XDECREF((PyObject *) st->py_event);
+ Py_XDECREF((PyObject *) st->py_button);
+
+ st->py_draw= st->py_event= st->py_button= NULL;
+ }
+}
+
+static void exec_callback(SpaceText *st, PyObject *callback, PyObject *args)
+{
+ PyObject *result= PyEval_CallObject(callback, args);
+
+ if (result==NULL) {
+ st->text->compiled= NULL;
+ PyErr_Print();
+ exit_pydraw(st);
+ }
+ Py_XDECREF(result);
+ Py_DECREF(args);
+}
+
+/* the handler for drawing routines (see Register method) */
+
+void BPY_spacetext_do_pywin_draw(SpaceText *st)
+{
+ uiBlock *block;
+ char butblock[20];
+
+ sprintf(butblock, "win %d", curarea->win);
+ block= uiNewBlock(&curarea->uiblocks, butblock, UI_EMBOSSX, UI_HELV, curarea->win);
+
+ if (st->py_draw) {
+ glPushAttrib(GL_ALL_ATTRIB_BITS);
+ exec_callback(st, st->py_draw, Py_BuildValue("()"));
+ glPopAttrib();
+ } else {
+ glClearColor(0.4375, 0.4375, 0.4375, 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+ }
+
+ uiDrawBlock(block);
+
+ curarea->win_swap= WIN_BACK_OK;
+}
+
+/* the handler for button event routines (see Register method) */
+
+static void spacetext_do_pywin_buttons(SpaceText *st, unsigned short event) {
+ if (st->py_button) {
+ exec_callback(st, st->py_button, Py_BuildValue("(i)", event));
+ }
+}
+
+/* calls the generic event handling methods registered with Register */
+
+void BPY_spacetext_do_pywin_event(SpaceText *st, unsigned short event, short val) {
+ if (event==QKEY && G.qual & (LR_ALTKEY|LR_CTRLKEY|LR_SHIFTKEY)) {
+ exit_pydraw(st);
+ return;
+ }
+
+ if (val) {
+ if (uiDoBlocks(&curarea->uiblocks, event)!=UI_NOTHING ) event= 0;
+
+ if (event==UI_BUT_EVENT) {
+ spacetext_do_pywin_buttons(st, val);
+ }
+ }
+
+ if (st->py_event) {
+ exec_callback(st, st->py_event, Py_BuildValue("(ii)", event, val));
+ }
+}
+
+int BPY_spacetext_is_pywin(SpaceText *st) {
+ return (st->py_draw || st->py_event || st->py_button);
+}
+
+static char Method_Exit_doc[]=
+"() - Exit the windowing interface";
+static PyObject *Method_Exit (PyObject *self, PyObject *args)
+{
+ SpaceText *st= curarea->spacedata.first;
+#ifdef CLEAR_NAMESPACE
+ PyObject *d;
+#endif
+ BPY_TRY(PyArg_ParseTuple(args, ""));
+
+ exit_pydraw(st);
+#ifdef CLEAR_NAMESPACE
+ d = st->py_globaldict; // The current window's global namespace dictionary
+ if (d) {
+ PyDict_Clear(d);
+ Py_DECREF(d); // release dictionary
+ }
+#endif
+
+ return BPY_incr_ret(Py_None);
+}
+
+static char Method_Register_doc[]=
+"(draw, event, button) - Register callbacks for windowing\n\
+\n\
+(draw) A function to draw the screen, taking no arguments\n\
+(event) A function to handle events, taking 2 arguments (evt, val)\n\
+ (evt) The event number\n\
+ (val) The value modifier (for key and mouse press/release)\n\
+(button) A function to handle button events, taking 1 argument (evt)\n\
+ (evt) The button number\n\
+\n\
+A None object can be passed if a callback is unused.";
+
+static PyObject *Method_Register (PyObject *self, PyObject *args)
+{
+ PyObject *newdrawc= NULL, *neweventc= NULL, *newbuttonc= NULL;
+ SpaceText *st= curarea->spacedata.first;
+
+ BPY_TRY(PyArg_ParseTuple(args, "O|OO", &newdrawc, &neweventc, &newbuttonc));
+
+ /* This is a hack again:
+ * Every python script should actually do a global variable cleanup at
+ * the end of execution.
+ * For scripts registering GUI callbacks, this does not work, because
+ * the global namespace of the interpreter still needs to be accessed
+ * from the callback.
+ * Workaround: a text object has a flag which allows the global name
+ * space to be cleared at the end of the script. This flag should be
+ * normally set when executed with Alt-P. For a script registering with
+ * the GUI though, clear the flag and set it when the GUI mode is left
+ * (Method_Exit).
+ */
+
+ BPY_debug(("--- disable clear namespace"));
+
+ st->flags &= ~ST_CLEAR_NAMESPACE;
+
+
+ if (!PyCallable_Check(newdrawc)) newdrawc= NULL;
+ if (!PyCallable_Check(neweventc)) neweventc= NULL;
+ if (!PyCallable_Check(newbuttonc)) newbuttonc= NULL;
+
+ if (!(newdrawc || neweventc || newbuttonc))
+ return BPY_incr_ret(Py_None);
+
+ exit_pydraw(st);
+
+ Py_XINCREF(newdrawc);
+ Py_XINCREF(neweventc);
+ Py_XINCREF(newbuttonc);
+
+ st->py_draw= newdrawc;
+ st->py_event= neweventc;
+ st->py_button= newbuttonc;
+
+ scrarea_queue_redraw(st->area);
+
+ return BPY_incr_ret(Py_None);
+}
+
+
+static char Method_Redraw_doc[]=
+"([after]) - Queue a redraw event\n\
+\n\
+[after=0] Determines whether the redraw is processed before or after other input events.\n\
+\n\
+Redraw events are buffered so that regardless of how many events are queued\n\
+the window only receives one redraw event.";
+
+static PyObject *Method_Redraw (PyObject *self, PyObject *args)
+{
+ int after= 0;
+
+ BPY_TRY(PyArg_ParseTuple(args, "|i", &after));
+
+ if (after) addafterqueue(curarea->win, REDRAW, 1);
+ else scrarea_queue_winredraw(curarea);
+
+ return BPY_incr_ret(Py_None);
+}
+
+
+static char Method_Draw_doc[]=
+"() - Force an immediate redraw\n\
+\n\
+Forced redraws are not buffered, in other words the window is redrawn\n\
+exactly once for everytime this function is called.";
+static PyObject *Method_Draw (PyObject *self, PyObject *args)
+{
+ /* If forced drawing is disable queue a redraw event instead */
+ if (disable_force_draw) {
+ scrarea_queue_winredraw(curarea);
+ return BPY_incr_ret(Py_None);
+ }
+
+ BPY_TRY(PyArg_ParseTuple(args, ""));
+
+ scrarea_do_windraw(curarea);
+
+ screen_swapbuffers();
+
+ return BPY_incr_ret(Py_None);
+}
+
+
+
+static char Method_Create_doc[]=
+"(value) - Create a default Button object\n\
+\n\
+(value) - The value to store in the button\n\
+\n\
+Valid values are ints, floats, and strings";
+
+static PyObject *Method_Create (PyObject *self, PyObject *args)
+{
+ Button *but;
+ PyObject *in;
+
+ BPY_TRY(PyArg_ParseTuple(args, "O", &in));
+
+ but= newbutton();
+ if(PyFloat_Check(in)) {
+ but->type= 2;
+ but->val.asfloat= PyFloat_AsDouble(in);
+ } else if (PyInt_Check(in)) {
+ but->type= 1;
+ but->val.asint= PyInt_AsLong(in);
+ } else if (PyString_Check(in)) {
+ char *newstr= PyString_AsString(in);
+
+ but->type= 3;
+ but->slen= strlen(newstr);
+ but->val.asstr= MEM_mallocN(but->slen+1, "button string");
+
+ strcpy(but->val.asstr, newstr);
+ }
+
+ return (PyObject *) but;
+}
+
+static uiBlock *Get_uiBlock(void)
+{
+ char butblock[32];
+
+ sprintf(butblock, "win %d", curarea->win);
+
+ return uiGetBlock(butblock, curarea);
+}
+
+static char Method_Button_doc[]=
+"(name, event, x, y, width, height, [tooltip]) - Create a new Button (push) button\n\
+\n\
+(name) A string to display on the button\n\
+(event) The event number to pass to the button event function when activated\n\
+(x, y) The lower left coordinate of the button\n\
+(width, height) The button width and height\n\
+[tooltip=""] The button's tooltip";
+
+static PyObject *Method_Button (PyObject *self, PyObject *args)
+{
+ uiBlock *block;
+ char *name, *tip= NULL;
+ int event;
+ int x, y, w, h;
+
+ BPY_TRY(PyArg_ParseTuple(args, "siiiii|s", &name, &event, &x, &y, &w, &h, &tip));
+
+ block= Get_uiBlock();
+
+ if(block) uiDefBut(block, BUT, event, name, x, y, w, h, 0, 0, 0, 0, 0, tip);
+
+ return BPY_incr_ret(Py_None);
+}
+
+static char Method_Menu_doc[]=
+"(name, event, x, y, width, height, default, [tooltip]) - Create a new Menu button\n\
+\n\
+(name) A string to display on the button\n\
+(event) The event number to pass to the button event function when activated\n\
+(x, y) The lower left coordinate of the button\n\
+(width, height) The button width and height\n\
+(default) The number of the option to be selected by default\n\
+[tooltip=""] The button's tooltip\n\
+\n\
+The menu options are specified through the name of the\n\
+button. Options are followed by a format code and seperated\n\
+by the '|' (pipe) character.\n\
+Valid format codes are\n\
+ %t - The option should be used as the title\n\
+ %xN - The option should set the integer N in the button value.";
+
+static PyObject *Method_Menu (PyObject *self, PyObject *args)
+{
+ uiBlock *block;
+ char *name, *tip= NULL;
+ int event, def;
+ int x, y, w, h;
+ Button *but;
+
+ BPY_TRY(PyArg_ParseTuple(args, "siiiiii|s", &name, &event, &x, &y, &w, &h, &def, &tip));
+
+ but= newbutton();
+ but->type= 1;
+ but->val.asint= def;
+
+ block= Get_uiBlock();
+ if(block) uiDefButI(block, MENU, event, name, x, y, w, h, &but->val.asint, 0, 0, 0, 0, tip);
+
+ return (PyObject *) but;
+}
+
+static char Method_Toggle_doc[]=
+"(name, event, x, y, width, height, default, [tooltip]) - Create a new Toggle button\n\
+\n\
+(name) A string to display on the button\n\
+(event) The event number to pass to the button event function when activated\n\
+(x, y) The lower left coordinate of the button\n\
+(width, height) The button width and height\n\
+(default) An integer (0 or 1) specifying the default state\n\
+[tooltip=""] The button's tooltip";
+
+static PyObject *Method_Toggle (PyObject *self, PyObject *args)
+{
+ uiBlock *block;
+ char *name, *tip= NULL;
+ int event;
+ int x, y, w, h, def;
+ Button *but;
+
+ BPY_TRY(PyArg_ParseTuple(args, "siiiiii|s", &name, &event, &x, &y, &w, &h, &def, &tip));
+
+ but= newbutton();
+ but->type= 1;
+ but->val.asint= def;
+
+ block= Get_uiBlock();
+ if(block) uiDefButI(block, TOG, event, name, x, y, w, h, &but->val.asint, 0, 0, 0, 0, tip);
+
+ return (PyObject *) but;
+}
+
+
+/* DO NOT TOUCH THIS FUNCTION !
+ Redrawing a slider inside its own callback routine is actually forbidden
+ with the current toolkit architecture (button routines are not reentrant).
+ But it works anyway.
+ XXX This is condemned to be dinosource in future - it's a hack.
+ */
+
+static void py_slider_update(void *butv, void *data2_unused)
+{
+ uiBut *but= butv;
+
+ disable_force_draw= 1;
+ /*
+ Disable forced drawing, otherwise the button object which
+ is still being used might be deleted
+ */
+
+// UIfrontbuf = 0;
+// spacetext_do_pywin_buttons(curarea->spacedata.first, but->retval);
+
+ g_window_redrawn = 0;
+ curarea->win_swap= WIN_BACK_OK;
+ UIfrontbuf = 1;
+ spacetext_do_pywin_buttons(curarea->spacedata.first, uiButGetRetVal(but));
+ UIfrontbuf = 0;
+
+ if (!g_window_redrawn) /* if Redraw already called */
+ Windowmodule_Redraw(0, Py_BuildValue("(i)", SPACE_VIEW3D));
+
+ disable_force_draw= 0;
+}
+
+static char Method_Slider_doc[]=
+"(name, event, x, y, width, height, initial, min, max, [update, tooltip]) - Create a new Slider button\n\
+\n\
+(name) A string to display on the button\n\
+(event) The event number to pass to the button event function when activated\n\
+(x, y) The lower left coordinate of the button\n\
+(width, height) The button width and height\n\
+(initial, min, max) Three values (int or float) specifying the initial and limit values.\n\
+[update=1] A value controlling whether the slider will emit events as it is edited.\n\
+ A non-zero value (default) enables the events. A zero value supresses them.\n\
+[tooltip=""] The button's tooltip";
+
+static PyObject *Method_Slider (PyObject *self, PyObject *args)
+{
+ uiBlock *block;
+ char *name, *tip= NULL;
+ int event;
+ int x, y, w, h, realtime=1;
+ Button *but;
+ PyObject *mino, *maxo, *inio;
+
+ BPY_TRY(PyArg_ParseTuple(args, "siiiiiOOO|is", &name, &event, &x, &y, &w, &h, &inio, &mino, &maxo, &realtime, &tip));
+
+
+ but= newbutton();
+ if (PyFloat_Check(inio)) {
+ float ini, min, max;
+
+ ini= PyFloat_AsDouble(inio);
+ min= PyFloat_AsDouble(mino);
+ max= PyFloat_AsDouble(maxo);
+
+ but->type= 2;
+ but->val.asfloat= ini;
+
+ block= Get_uiBlock();
+ if(block) {
+ uiBut *ubut;
+ ubut= uiDefButF(block, NUMSLI, event, name, x, y, w, h, &but->val.asfloat, min, max, 0, 0, tip);
+ if (realtime) uiButSetFunc(ubut, py_slider_update, ubut, NULL);
+ }
+ }
+ else {
+ int ini, min, max;
+
+ ini= PyInt_AsLong(inio);
+ min= PyInt_AsLong(mino);
+ max= PyInt_AsLong(maxo);
+
+ but->type= 1;
+ but->val.asint= ini;
+
+ block= Get_uiBlock();
+ if(block) {
+ uiBut *ubut;
+ ubut= uiDefButI(block, NUMSLI, event, name, x, y, w, h, &but->val.asint, min, max, 0, 0, tip);
+ if (realtime) uiButSetFunc(ubut, py_slider_update, ubut, NULL);
+ }
+ }
+ return (PyObject *) but;
+}
+
+static char Method_Scrollbar_doc[]=
+"(event, x, y, width, height, initial, min, max, [update, tooltip]) - Create a new Scrollbar\n\
+\n\
+(event) The event number to pass to the button event function when activated\n\
+(x, y) The lower left coordinate of the button\n\
+(width, height) The button width and height\n\
+(initial, min, max) Three values (int or float) specifying the initial and limit values.\n\
+[update=1] A value controlling whether the slider will emit events as it is edited.\n\
+ A non-zero value (default) enables the events. A zero value supresses them.\n\
+[tooltip=""] The button's tooltip";
+
+static PyObject *Method_Scrollbar (PyObject *self, PyObject *args)
+{
+ char *tip= NULL;
+ uiBlock *block;
+ int event;
+ int x, y, w, h, realtime=1;
+ Button *but;
+ PyObject *mino, *maxo, *inio;
+ float ini, min, max;
+
+ BPY_TRY(PyArg_ParseTuple(args, "iiiiiOOO|is", &event, &x, &y, &w, &h, &inio, &mino, &maxo, &realtime, &tip));
+
+ if (!PyNumber_Check(inio) || !PyNumber_Check(inio) || !PyNumber_Check(inio))
+ return BPY_err_ret_ob(PyExc_AttributeError, "expected numbers for initial, min, and max");
+
+ but= newbutton();
+
+ if (PyFloat_Check(inio)) but->type= 2;
+ else but->type= 1;
+
+ ini= PyFloat_AsDouble(inio);
+ min= PyFloat_AsDouble(mino);
+ max= PyFloat_AsDouble(maxo);
+
+ if (but->type==2) {
+ but->val.asfloat= ini;
+ block= Get_uiBlock();
+ if(block) {
+ uiBut *ubut;
+ ubut= uiDefButF(block, SCROLL, event, "", x, y, w, h, &but->val.asfloat, min, max, 0, 0, tip);
+ if (realtime) uiButSetFunc(ubut, py_slider_update, ubut, NULL);
+ }
+ } else {
+ but->val.asint= ini;
+ block= Get_uiBlock();
+ if(block) {
+ uiBut *ubut;
+ ubut= uiDefButI(block, SCROLL, event, "", x, y, w, h, &but->val.asint, min, max, 0, 0, tip);
+ if (realtime) uiButSetFunc(ubut, py_slider_update, ubut, NULL);
+ }
+ }
+
+ return (PyObject *) but;
+}
+
+static char Method_Number_doc[]=
+"(name, event, x, y, width, height, initial, min, max, [tooltip]) - Create a new Number button\n\
+\n\
+(name) A string to display on the button\n\
+(event) The event number to pass to the button event function when activated\n\
+(x, y) The lower left coordinate of the button\n\
+(width, height) The button width and height\n\
+(initial, min, max) Three values (int or float) specifying the initial and limit values.\n\
+[tooltip=""] The button's tooltip";
+
+static PyObject *Method_Number (PyObject *self, PyObject *args)
+{
+ uiBlock *block;
+ char *name, *tip= NULL;
+ int event;
+ int x, y, w, h;
+ Button *but;
+ PyObject *mino, *maxo, *inio;
+
+ BPY_TRY(PyArg_ParseTuple(args, "siiiiiOOO|s", &name, &event, &x, &y, &w, &h, &inio, &mino, &maxo, &tip));
+
+ but= newbutton();
+
+ if (PyFloat_Check(inio)) {
+ float ini, min, max;
+
+ ini= PyFloat_AsDouble(inio);
+ min= PyFloat_AsDouble(mino);
+ max= PyFloat_AsDouble(maxo);
+
+ but->type= 2;
+ but->val.asfloat= ini;
+
+ block= Get_uiBlock();
+ if(block) uiDefButF(block, NUM, event, name, x, y, w, h, &but->val.asfloat, min, max, 0, 0, tip);
+ } else {
+ int ini, min, max;
+
+ ini= PyInt_AsLong(inio);
+ min= PyInt_AsLong(mino);
+ max= PyInt_AsLong(maxo);
+
+ but->type= 1;
+ but->val.asint= ini;
+
+ block= Get_uiBlock();
+ if(block) uiDefButI(block, NUM, event, name, x, y, w, h, &but->val.asint, min, max, 0, 0, tip);
+ }
+
+ return (PyObject *) but;
+}
+
+static char Method_String_doc[]=
+"(name, event, x, y, width, height, initial, length, [tooltip]) - Create a new String button\n\
+\n\
+(name) A string to display on the button\n\
+(event) The event number to pass to the button event function when activated\n\
+(x, y) The lower left coordinate of the button\n\
+(width, height) The button width and height\n\
+(initial) The string to display initially\n\
+(length) The maximum input length\n\
+[tooltip=""] The button's tooltip";
+
+static PyObject *Method_String (PyObject *self, PyObject *args)
+{
+ uiBlock *block;
+ char *name, *tip= NULL, *newstr;
+ int event;
+ int x, y, w, h, len;
+ Button *but;
+
+ BPY_TRY(PyArg_ParseTuple(args, "siiiiisi|s", &name, &event, &x, &y, &w, &h, &newstr, &len, &tip));
+
+ but= newbutton();
+ but->type= 3;
+ but->slen= len;
+ but->val.asstr= MEM_mallocN(len+1, "button string");
+
+ strncpy(but->val.asstr, newstr, len);
+ but->val.asstr[len]= 0;
+
+ block= Get_uiBlock();
+ if(block) uiDefBut(block, TEX, event, name, x, y, w, h, but->val.asstr, 0, len, 0, 0, tip);
+
+ return (PyObject *) but;
+}
+
+static char Method_Text_doc[]=
+"(text) - Draw text onscreen\n\
+\n\
+(text) The text to draw\n";
+static PyObject *Method_Text (PyObject *self, PyObject *args)
+{
+ char *text;
+
+ BPY_TRY(PyArg_ParseTuple(args, "s", &text));
+
+ BMF_DrawString(G.font, text);
+
+ return BPY_incr_ret(Py_None);
+}
+
+#undef MethodDef
+#define MethodDef(func) _MethodDef(func, Method)
+
+static struct PyMethodDef Draw_methods[] = {
+ MethodDef(Create),
+ MethodDef(Button),
+ MethodDef(Toggle),
+ MethodDef(Menu),
+ MethodDef(Slider),
+ MethodDef(Scrollbar),
+ MethodDef(Number),
+ MethodDef(String),
+
+ MethodDef(Text),
+
+ MethodDef(Exit),
+ MethodDef(Redraw),
+ MethodDef(Draw),
+ MethodDef(Register),
+
+ {NULL, NULL}
+};
+
+PyObject *init_py_draw(void)
+{
+ PyObject *mod= Py_InitModule(SUBMODULE(Draw), Draw_methods);
+ PyObject *dict= PyModule_GetDict(mod);
+
+ Button_Type.ob_type= &PyType_Type;
+
+ BPY_ADDCONST(dict, LEFTMOUSE);
+ BPY_ADDCONST(dict, MIDDLEMOUSE);
+ BPY_ADDCONST(dict, RIGHTMOUSE);
+ BPY_ADDCONST(dict, MOUSEX);
+ BPY_ADDCONST(dict, MOUSEY);
+ BPY_ADDCONST(dict, TIMER0);
+ BPY_ADDCONST(dict, TIMER1);
+ BPY_ADDCONST(dict, TIMER2);
+ BPY_ADDCONST(dict, TIMER3);
+ BPY_ADDCONST(dict, KEYBD);
+ BPY_ADDCONST(dict, RAWKEYBD);
+ BPY_ADDCONST(dict, REDRAW);
+ BPY_ADDCONST(dict, INPUTCHANGE);
+ BPY_ADDCONST(dict, QFULL);
+ BPY_ADDCONST(dict, WINFREEZE);
+ BPY_ADDCONST(dict, WINTHAW);
+ BPY_ADDCONST(dict, WINCLOSE);
+ BPY_ADDCONST(dict, WINQUIT);
+#ifndef IRISGL
+ BPY_ADDCONST(dict, Q_FIRSTTIME);
+#endif
+ BPY_ADDCONST(dict, AKEY);
+ BPY_ADDCONST(dict, BKEY);
+ BPY_ADDCONST(dict, CKEY);
+ BPY_ADDCONST(dict, DKEY);
+ BPY_ADDCONST(dict, EKEY);
+ BPY_ADDCONST(dict, FKEY);
+ BPY_ADDCONST(dict, GKEY);
+ BPY_ADDCONST(dict, HKEY);
+ BPY_ADDCONST(dict, IKEY);
+ BPY_ADDCONST(dict, JKEY);
+ BPY_ADDCONST(dict, KKEY);
+ BPY_ADDCONST(dict, LKEY);
+ BPY_ADDCONST(dict, MKEY);
+ BPY_ADDCONST(dict, NKEY);
+ BPY_ADDCONST(dict, OKEY);
+ BPY_ADDCONST(dict, PKEY);
+ BPY_ADDCONST(dict, QKEY);
+ BPY_ADDCONST(dict, RKEY);
+ BPY_ADDCONST(dict, SKEY);
+ BPY_ADDCONST(dict, TKEY);
+ BPY_ADDCONST(dict, UKEY);
+ BPY_ADDCONST(dict, VKEY);
+ BPY_ADDCONST(dict, WKEY);
+ BPY_ADDCONST(dict, XKEY);
+ BPY_ADDCONST(dict, YKEY);
+ BPY_ADDCONST(dict, ZKEY);
+ BPY_ADDCONST(dict, ZEROKEY);
+ BPY_ADDCONST(dict, ONEKEY);
+ BPY_ADDCONST(dict, TWOKEY);
+ BPY_ADDCONST(dict, THREEKEY);
+ BPY_ADDCONST(dict, FOURKEY);
+ BPY_ADDCONST(dict, FIVEKEY);
+ BPY_ADDCONST(dict, SIXKEY);
+ BPY_ADDCONST(dict, SEVENKEY);
+ BPY_ADDCONST(dict, EIGHTKEY);
+ BPY_ADDCONST(dict, NINEKEY);
+ BPY_ADDCONST(dict, CAPSLOCKKEY);
+ BPY_ADDCONST(dict, LEFTCTRLKEY);
+ BPY_ADDCONST(dict, LEFTALTKEY);
+ BPY_ADDCONST(dict, RIGHTALTKEY);
+ BPY_ADDCONST(dict, RIGHTCTRLKEY);
+ BPY_ADDCONST(dict, RIGHTSHIFTKEY);
+ BPY_ADDCONST(dict, LEFTSHIFTKEY);
+ BPY_ADDCONST(dict, ESCKEY);
+ BPY_ADDCONST(dict, TABKEY);
+ BPY_ADDCONST(dict, RETKEY);
+ BPY_ADDCONST(dict, SPACEKEY);
+ BPY_ADDCONST(dict, LINEFEEDKEY);
+ BPY_ADDCONST(dict, BACKSPACEKEY);
+ BPY_ADDCONST(dict, DELKEY);
+ BPY_ADDCONST(dict, SEMICOLONKEY);
+ BPY_ADDCONST(dict, PERIODKEY);
+ BPY_ADDCONST(dict, COMMAKEY);
+ BPY_ADDCONST(dict, QUOTEKEY);
+ BPY_ADDCONST(dict, ACCENTGRAVEKEY);
+ BPY_ADDCONST(dict, MINUSKEY);
+ BPY_ADDCONST(dict, SLASHKEY);
+ BPY_ADDCONST(dict, BACKSLASHKEY);
+ BPY_ADDCONST(dict, EQUALKEY);
+ BPY_ADDCONST(dict, LEFTBRACKETKEY);
+ BPY_ADDCONST(dict, RIGHTBRACKETKEY);
+ BPY_ADDCONST(dict, LEFTARROWKEY);
+ BPY_ADDCONST(dict, DOWNARROWKEY);
+ BPY_ADDCONST(dict, RIGHTARROWKEY);
+ BPY_ADDCONST(dict, UPARROWKEY);
+ BPY_ADDCONST(dict, PAD2);
+ BPY_ADDCONST(dict, PAD4);
+ BPY_ADDCONST(dict, PAD6);
+ BPY_ADDCONST(dict, PAD8);
+ BPY_ADDCONST(dict, PAD1);
+ BPY_ADDCONST(dict, PAD3);
+ BPY_ADDCONST(dict, PAD5);
+ BPY_ADDCONST(dict, PAD7);
+ BPY_ADDCONST(dict, PAD9);
+ BPY_ADDCONST(dict, PADPERIOD);
+ BPY_ADDCONST(dict, PADSLASHKEY);
+ BPY_ADDCONST(dict, PADASTERKEY);
+ BPY_ADDCONST(dict, PAD0);
+ BPY_ADDCONST(dict, PADMINUS);
+ BPY_ADDCONST(dict, PADENTER);
+ BPY_ADDCONST(dict, PADPLUSKEY);
+ BPY_ADDCONST(dict, F1KEY);
+ BPY_ADDCONST(dict, F2KEY);
+ BPY_ADDCONST(dict, F3KEY);
+ BPY_ADDCONST(dict, F4KEY);
+ BPY_ADDCONST(dict, F5KEY);
+ BPY_ADDCONST(dict, F6KEY);
+ BPY_ADDCONST(dict, F7KEY);
+ BPY_ADDCONST(dict, F8KEY);
+ BPY_ADDCONST(dict, F9KEY);
+ BPY_ADDCONST(dict, F10KEY);
+ BPY_ADDCONST(dict, F11KEY);
+ BPY_ADDCONST(dict, F12KEY);
+ BPY_ADDCONST(dict, PAUSEKEY);
+ BPY_ADDCONST(dict, INSERTKEY);
+ BPY_ADDCONST(dict, HOMEKEY);
+ BPY_ADDCONST(dict, PAGEUPKEY);
+ BPY_ADDCONST(dict, PAGEDOWNKEY);
+ BPY_ADDCONST(dict, ENDKEY);
+
+ return mod;
+}
+
+
+/* Buffer Object */
+
+/* For Python access to OpenGL functions requiring
+ * a pointer.
+ */
+
+PyTypeObject Buffer_Type;
+
+typedef struct _Buffer {
+ PyObject_VAR_HEAD
+
+ PyObject *parent;
+
+ int type; /* GL_BYTE, GL_SHORT, GL_INT, GL_FLOAT */
+ int ndimensions;
+ int *dimensions;
+
+ union {
+ char *asbyte;
+ short *asshort;
+ int *asint;
+ float *asfloat;
+
+ void *asvoid;
+ } buf;
+} Buffer;
+
+static int type_size(int type) {
+ switch (type) {
+ case GL_BYTE:
+ return sizeof(char);
+ case GL_SHORT:
+ return sizeof(short);
+ case GL_INT:
+ return sizeof(int);
+ case GL_FLOAT:
+ return sizeof(float);
+ }
+ return -1;
+}
+
+static Buffer *make_buffer(int type, int ndimensions, int *dimensions) {
+ Buffer *buffer;
+ void *buf= NULL;
+ int i, size, length;
+
+ length= 1;
+ for (i=0; i<ndimensions; i++) length*= dimensions[i];
+
+ size= type_size(type);
+
+ buf= MEM_mallocN(length*size, "Buffer buffer");
+
+ buffer= (Buffer *) PyObject_NEW(Buffer, &Buffer_Type);
+ buffer->parent= NULL;
+ buffer->ndimensions= ndimensions;
+ buffer->dimensions= dimensions;
+ buffer->type= type;
+ buffer->buf.asvoid= buf;
+
+ for (i= 0; i<length; i++) {
+ if (type==GL_BYTE)
+ buffer->buf.asbyte[i]= 0;
+
+ else if (type==GL_SHORT)
+ buffer->buf.asshort[i]= 0;
+
+ else if (type==GL_INT)
+ buffer->buf.asint[i]= 0;
+
+ else if (type==GL_FLOAT)
+ buffer->buf.asfloat[i]= 0.0;
+ }
+
+ return buffer;
+}
+
+static int Buffer_ass_slice(PyObject *self, int begin, int end, PyObject *seq);
+
+static char Method_Buffer_doc[]=
+"(type, dimensions, [template]) - Create a new Buffer object\n\
+\n\
+(type) - The format to store data in\n\
+(dimensions) - An int or sequence specifying the dimensions of the buffer\n\
+[template] - A sequence of matching dimensions to the buffer to be created\n\
+ which will be used to initialize the Buffer.\n\
+\n\
+If a template is not passed in all fields will be initialized to 0.\n\
+\n\
+The type should be one of GL_BYTE, GL_SHORT, GL_INT, or GL_FLOAT.\n\
+If the dimensions are specified as an int a linear buffer will be\n\
+created. If a sequence is passed for the dimensions the buffer\n\
+will have len(sequence) dimensions, where the size for each dimension\n\
+is determined by the value in the sequence at that index.\n\
+\n\
+For example, passing [100, 100] will create a 2 dimensional\n\
+square buffer. Passing [16, 16, 32] will create a 3 dimensional\n\
+buffer which is twice as deep as it is wide or high.";
+
+static PyObject *Method_Buffer (PyObject *self, PyObject *args)
+{
+ PyObject *length_ob= NULL, *template= NULL;
+ Buffer *buffer;
+
+ int i, type;
+ int *dimensions = 0, ndimensions = 0;
+
+ BPY_TRY(PyArg_ParseTuple(args, "iO|O", &type, &length_ob, &template));
+
+ if (type!=GL_BYTE && type!=GL_SHORT && type!=GL_INT && type!=GL_FLOAT) {
+ PyErr_SetString(PyExc_AttributeError, "type");
+ return NULL;
+ }
+
+ if (PyNumber_Check(length_ob)) {
+ ndimensions= 1;
+ dimensions= MEM_mallocN(ndimensions*sizeof(int), "Buffer dimensions");
+ dimensions[0]= PyInt_AsLong(length_ob);
+
+ } else if (PySequence_Check(length_ob)) {
+ ndimensions= PySequence_Length(length_ob);
+ dimensions= MEM_mallocN(ndimensions*sizeof(int), "Buffer dimensions");
+
+ for (i=0; i<ndimensions; i++) {
+ PyObject *ob= PySequence_GetItem(length_ob, i);
+
+ if (!PyNumber_Check(ob)) dimensions[i]= 1;
+ else dimensions[i]= PyInt_AsLong(ob);
+
+ Py_DECREF(ob);
+ }
+ }
+
+ buffer= make_buffer(type, ndimensions, dimensions);
+ if (template && ndimensions) {
+ if (Buffer_ass_slice((PyObject *) buffer, 0, dimensions[0], template)) {
+ Py_DECREF(buffer);
+ return NULL;
+ }
+ }
+
+ return (PyObject *) buffer;
+}
+
+/**********/
+
+
+/* Buffer sequence methods */
+
+static int Buffer_len(PyObject *self) {
+ Buffer *buf= (Buffer *) self;
+
+ return buf->dimensions[0];
+}
+
+static PyObject *Buffer_item(PyObject *self, int i) {
+ Buffer *buf= (Buffer *) self;
+
+ if (i >= buf->dimensions[0]) {
+ PyErr_SetString(PyExc_IndexError, "array index out of range");
+ return NULL;
+ }
+
+ if (buf->ndimensions==1) {
+ switch (buf->type) {
+ case GL_BYTE: return Py_BuildValue("b", buf->buf.asbyte[i]);
+ case GL_SHORT: return Py_BuildValue("h", buf->buf.asshort[i]);
+ case GL_INT: return Py_BuildValue("i", buf->buf.asint[i]);
+ case GL_FLOAT: return Py_BuildValue("f", buf->buf.asfloat[i]);
+ }
+ } else {
+ Buffer *newbuf;
+ int j, length, size;
+
+ length= 1;
+ for (j=1; j<buf->ndimensions; j++) {
+ length*= buf->dimensions[j];
+ }
+ size= type_size(buf->type);
+
+ newbuf= (Buffer *) PyObject_NEW(Buffer, &Buffer_Type);
+
+ Py_INCREF(self);
+ newbuf->parent= self;
+
+ newbuf->ndimensions= buf->ndimensions-1;
+ newbuf->type= buf->type;
+ newbuf->buf.asvoid= buf->buf.asbyte + i*length*size;
+
+ newbuf->dimensions= MEM_mallocN(newbuf->ndimensions*sizeof(int), "Buffer dimensions");
+ memcpy(newbuf->dimensions, buf->dimensions+1, newbuf->ndimensions*sizeof(int));
+
+ return (PyObject *) newbuf;
+ }
+
+ return NULL;
+}
+
+static PyObject *Buffer_slice(PyObject *self, int begin, int end)
+{
+ Buffer *buf= (Buffer *) self;
+ PyObject *list;
+ int count;
+
+ if (begin<0) begin= 0;
+ if (end>buf->dimensions[0]) end= buf->dimensions[0];
+ if (begin>end) begin= end;
+
+ list= PyList_New(end-begin);
+
+ for (count= begin; count<end; count++)
+ PyList_SetItem(list, count-begin, Buffer_item(self, count));
+
+ return list;
+}
+
+static int Buffer_ass_item(PyObject *self, int i, PyObject *v) {
+ Buffer *buf= (Buffer *) self;
+
+ if (i >= buf->dimensions[0]) {
+ PyErr_SetString(PyExc_IndexError, "array assignment index out of range");
+ return -1;
+ }
+
+ if (buf->ndimensions!=1) {
+ PyObject *row= Buffer_item(self, i);
+ int ret;
+
+ if (!row) return -1;
+
+ ret= Buffer_ass_slice(row, 0, buf->dimensions[1], v);
+ Py_DECREF(row);
+
+ return ret;
+ }
+
+ if (buf->type==GL_BYTE) {
+ if (!PyArg_Parse(v, "b;Coordinates must be ints", &buf->buf.asbyte[i]))
+ return -1;
+
+ } else if (buf->type==GL_SHORT) {
+ if (!PyArg_Parse(v, "h;Coordinates must be ints", &buf->buf.asshort[i]))
+ return -1;
+
+ } else if (buf->type==GL_INT) {
+ if (!PyArg_Parse(v, "i;Coordinates must be ints", &buf->buf.asint[i]))
+ return -1;
+
+ } else if (buf->type==GL_FLOAT) {
+ if (!PyArg_Parse(v, "f;Coordinates must be floats", &buf->buf.asfloat[i]))
+ return -1;
+ }
+
+ return 0;
+}
+
+static int Buffer_ass_slice(PyObject *self, int begin, int end, PyObject *seq)
+{
+ Buffer *buf= (Buffer *) self;
+ PyObject *item;
+ int count, err=0;
+
+ if (begin<0) begin= 0;
+ if (end>buf->dimensions[0]) end= buf->dimensions[0];
+ if (begin>end) begin= end;
+
+ if (!PySequence_Check(seq)) {
+ PyErr_SetString(PyExc_TypeError, "illegal argument type for built-in operation");
+ return -1;
+ }
+
+ if (PySequence_Length(seq)!=(end-begin)) {
+ PyErr_SetString(PyExc_TypeError, "size mismatch in assignment");
+ return -1;
+ }
+
+ for (count= begin; count<end; count++) {
+ item= PySequence_GetItem(seq, count-begin);
+ err= Buffer_ass_item(self, count, item);
+ Py_DECREF(item);
+
+ if (err) break;
+ }
+
+ return err;
+}
+static PySequenceMethods Buffer_SeqMethods = {
+ (inquiry) Buffer_len, /*sq_length*/
+ (binaryfunc) 0, /*sq_concat*/
+ (intargfunc) 0, /*sq_repeat*/
+ (intargfunc) Buffer_item, /*sq_item*/
+ (intintargfunc) Buffer_slice, /*sq_slice*/
+ (intobjargproc) Buffer_ass_item, /*sq_ass_item*/
+ (intintobjargproc) Buffer_ass_slice, /*sq_ass_slice*/
+};
+
+
+
+/**********/
+
+static void Buffer_dealloc(PyObject *self) {
+ Buffer *buf= (Buffer *) self;
+
+ if (buf->parent) Py_DECREF(buf->parent);
+ else MEM_freeN(buf->buf.asvoid);
+
+ MEM_freeN(buf->dimensions);
+
+ PyMem_DEL(self);
+}
+
+static PyObject *Buffer_tolist(PyObject *self) {
+ int i, len= ((Buffer *)self)->dimensions[0];
+ PyObject *list= PyList_New(len);
+
+ for (i=0; i<len; i++) {
+ PyList_SetItem(list, i, Buffer_item(self, i));
+ }
+
+ return list;
+}
+
+static PyObject *Buffer_dimensions(PyObject *self) {
+ Buffer *buffer= (Buffer *) self;
+ PyObject *list= PyList_New(buffer->ndimensions);
+ int i;
+
+ for (i= 0; i<buffer->ndimensions; i++) {
+ PyList_SetItem(list, i, PyInt_FromLong(buffer->dimensions[i]));
+ }
+
+ return list;
+}
+
+static PyObject *Buffer_getattr(PyObject *self, char *name) {
+ if (strcmp(name, "list")==0) return Buffer_tolist(self);
+ else if (strcmp(name, "dimensions")==0) return Buffer_dimensions(self);
+
+ PyErr_SetString(PyExc_AttributeError, name);
+ return NULL;
+}
+
+static PyObject *Buffer_repr(PyObject *self) {
+ PyObject *list= Buffer_tolist(self);
+ PyObject *repr= PyObject_Repr(list);
+ Py_DECREF(list);
+
+ return repr;
+}
+
+PyTypeObject Buffer_Type = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "Buffer", /*tp_name*/
+ sizeof(Buffer), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ (destructor) Buffer_dealloc, /*tp_dealloc*/
+ (printfunc) 0, /*tp_print*/
+ (getattrfunc) Buffer_getattr, /*tp_getattr*/
+ (setattrfunc) 0, /*tp_setattr*/
+ (cmpfunc) 0, /*tp_compare*/
+ (reprfunc) Buffer_repr, /*tp_repr*/
+ 0, /*tp_as_number*/
+ &Buffer_SeqMethods, /*tp_as_sequence*/
+};
+
+#ifndef __APPLE__
+/* By golly George! It looks like fancy pants macro time!!! */
+
+/*
+#define int_str "i"
+#define int_var(number) bgl_int##number
+#define int_ref(number) &bgl_int##number
+#define int_def(number) int int_var(number)
+
+#define float_str "f"
+#define float_var(number) bgl_float##number
+#define float_ref(number) &bgl_float##number
+#define float_def(number) float float_var(number)
+*/
+
+/* TYPE_str is the string to pass to Py_ArgParse (for the format) */
+/* TYPE_var is the name to pass to the GL function */
+/* TYPE_ref is the pointer to pass to Py_ArgParse (to store in) */
+/* TYPE_def is the C initialization of the variable */
+
+#define void_str ""
+#define void_var(num)
+#define void_ref(num) &bgl_var##num
+#define void_def(num) char bgl_var##num
+
+#define buffer_str "O!"
+#define buffer_var(number) (bgl_buffer##number)->buf.asvoid
+#define buffer_ref(number) &Buffer_Type, &bgl_buffer##number
+#define buffer_def(number) Buffer *bgl_buffer##number
+
+/* GL Pointer fields, handled by buffer type */
+/* GLdoubleP, GLfloatP, GLintP, GLuintP, GLshortP */
+
+#define GLbooleanP_str "O!"
+#define GLbooleanP_var(number) (bgl_buffer##number)->buf.asvoid
+#define GLbooleanP_ref(number) &Buffer_Type, &bgl_buffer##number
+#define GLbooleanP_def(number) Buffer *bgl_buffer##number
+
+#define GLbyteP_str "O!"
+#define GLbyteP_var(number) (bgl_buffer##number)->buf.asvoid
+#define GLbyteP_ref(number) &Buffer_Type, &bgl_buffer##number
+#define GLbyteP_def(number) Buffer *bgl_buffer##number
+
+#define GLubyteP_str "O!"
+#define GLubyteP_var(number) (bgl_buffer##number)->buf.asvoid
+#define GLubyteP_ref(number) &Buffer_Type, &bgl_buffer##number
+#define GLubyteP_def(number) Buffer *bgl_buffer##number
+
+#define GLintP_str "O!"
+#define GLintP_var(number) (bgl_buffer##number)->buf.asvoid
+#define GLintP_ref(number) &Buffer_Type, &bgl_buffer##number
+#define GLintP_def(number) Buffer *bgl_buffer##number
+
+#define GLuintP_str "O!"
+#define GLuintP_var(number) (bgl_buffer##number)->buf.asvoid
+#define GLuintP_ref(number) &Buffer_Type, &bgl_buffer##number
+#define GLuintP_def(number) Buffer *bgl_buffer##number
+
+#define GLshortP_str "O!"
+#define GLshortP_var(number) (bgl_buffer##number)->buf.asvoid
+#define GLshortP_ref(number) &Buffer_Type, &bgl_buffer##number
+#define GLshortP_def(number) Buffer *bgl_buffer##number
+
+#define GLushortP_str "O!"
+#define GLushortP_var(number) (bgl_buffer##number)->buf.asvoid
+#define GLushortP_ref(number) &Buffer_Type, &bgl_buffer##number
+#define GLushortP_def(number) Buffer *bgl_buffer##number
+
+#define GLfloatP_str "O!"
+#define GLfloatP_var(number) (bgl_buffer##number)->buf.asvoid
+#define GLfloatP_ref(number) &Buffer_Type, &bgl_buffer##number
+#define GLfloatP_def(number) Buffer *bgl_buffer##number
+
+#define GLdoubleP_str "O!"
+#define GLdoubleP_var(number) (bgl_buffer##number)->buf.asvoid
+#define GLdoubleP_ref(number) &Buffer_Type, &bgl_buffer##number
+#define GLdoubleP_def(number) Buffer *bgl_buffer##number
+
+#define GLclampfP_str "O!"
+#define GLclampfP_var(number) (bgl_buffer##number)->buf.asvoid
+#define GLclampfP_ref(number) &Buffer_Type, &bgl_buffer##number
+#define GLclampfP_def(number) Buffer *bgl_buffer##number
+
+#define GLvoidP_str "O!"
+#define GLvoidP_var(number) (bgl_buffer##number)->buf.asvoid
+#define GLvoidP_ref(number) &Buffer_Type, &bgl_buffer##number
+#define GLvoidP_def(number) Buffer *bgl_buffer##number
+
+#define buffer_str "O!"
+#define buffer_var(number) (bgl_buffer##number)->buf.asvoid
+#define buffer_ref(number) &Buffer_Type, &bgl_buffer##number
+#define buffer_def(number) Buffer *bgl_buffer##number
+
+/* The standard GL typedefs are used as prototypes, we can't
+ * use the GL type directly because Py_ArgParse expects normal
+ * C types.
+ *
+ * Py_ArgParse doesn't grok writing into unsigned variables,
+ * so we use signed everything (even stuff that should be unsigned.
+ */
+
+/* typedef unsigned int GLenum; */
+#define GLenum_str "i"
+#define GLenum_var(num) bgl_var##num
+#define GLenum_ref(num) &bgl_var##num
+#define GLenum_def(num) /* unsigned */ int GLenum_var(num)
+
+/* typedef unsigned int GLboolean; */
+#define GLboolean_str "b"
+#define GLboolean_var(num) bgl_var##num
+#define GLboolean_ref(num) &bgl_var##num
+#define GLboolean_def(num) /* unsigned */ char GLboolean_var(num)
+
+/* typedef unsigned int GLbitfield; */
+#define GLbitfield_str "i"
+#define GLbitfield_var(num) bgl_var##num
+#define GLbitfield_ref(num) &bgl_var##num
+#define GLbitfield_def(num) /* unsigned */ int GLbitfield_var(num)
+
+/* typedef signed char GLbyte; */
+#define GLbyte_str "b"
+#define GLbyte_var(num) bgl_var##num
+#define GLbyte_ref(num) &bgl_var##num
+#define GLbyte_def(num) signed char GLbyte_var(num)
+
+/* typedef short GLshort; */
+#define GLshort_str "h"
+#define GLshort_var(num) bgl_var##num
+#define GLshort_ref(num) &bgl_var##num
+#define GLshort_def(num) short GLshort_var(num)
+
+/* typedef int GLint; */
+#define GLint_str "i"
+#define GLint_var(num) bgl_var##num
+#define GLint_ref(num) &bgl_var##num
+#define GLint_def(num) int GLint_var(num)
+
+/* typedef int GLsizei; */
+#define GLsizei_str "i"
+#define GLsizei_var(num) bgl_var##num
+#define GLsizei_ref(num) &bgl_var##num
+#define GLsizei_def(num) int GLsizei_var(num)
+
+/* typedef unsigned char GLubyte; */
+#define GLubyte_str "b"
+#define GLubyte_var(num) bgl_var##num
+#define GLubyte_ref(num) &bgl_var##num
+#define GLubyte_def(num) /* unsigned */ char GLubyte_var(num)
+
+/* typedef unsigned short GLushort; */
+#define GLushort_str "h"
+#define GLushort_var(num) bgl_var##num
+#define GLushort_ref(num) &bgl_var##num
+#define GLushort_def(num) /* unsigned */ short GLushort_var(num)
+
+/* typedef unsigned int GLuint; */
+#define GLuint_str "i"
+#define GLuint_var(num) bgl_var##num
+#define GLuint_ref(num) &bgl_var##num
+#define GLuint_def(num) /* unsigned */ int GLuint_var(num)
+
+/* typedef float GLfloat; */
+#define GLfloat_str "f"
+#define GLfloat_var(num) bgl_var##num
+#define GLfloat_ref(num) &bgl_var##num
+#define GLfloat_def(num) float GLfloat_var(num)
+
+/* typedef float GLclampf; */
+#define GLclampf_str "f"
+#define GLclampf_var(num) bgl_var##num
+#define GLclampf_ref(num) &bgl_var##num
+#define GLclampf_def(num) float GLclampf_var(num)
+
+/* typedef double GLdouble; */
+#define GLdouble_str "d"
+#define GLdouble_var(num) bgl_var##num
+#define GLdouble_ref(num) &bgl_var##num
+#define GLdouble_def(num) double GLdouble_var(num)
+
+/* typedef double GLclampd; */
+#define GLclampd_str "d"
+#define GLclampd_var(num) bgl_var##num
+#define GLclampd_ref(num) &bgl_var##num
+#define GLclampd_def(num) double GLclampd_var(num)
+
+/* typedef void GLvoid; */
+/* #define GLvoid_str "" */
+/* #define GLvoid_var(num) bgl_var##num */
+/* #define GLvoid_ref(num) &bgl_var##num */
+/* #define GLvoid_def(num) char bgl_var##num */
+
+#define arg_def1(a1) a1##_def(1)
+#define arg_def2(a1, a2) arg_def1(a1); a2##_def(2)
+#define arg_def3(a1, a2, a3) arg_def2(a1, a2); a3##_def(3)
+#define arg_def4(a1, a2, a3, a4) arg_def3(a1, a2, a3); a4##_def(4)
+#define arg_def5(a1, a2, a3, a4, a5) arg_def4(a1, a2, a3, a4); a5##_def(5)
+#define arg_def6(a1, a2, a3, a4, a5, a6)arg_def5(a1, a2, a3, a4, a5); a6##_def(6)
+#define arg_def7(a1, a2, a3, a4, a5, a6, a7)arg_def6(a1, a2, a3, a4, a5, a6); a7##_def(7)
+#define arg_def8(a1, a2, a3, a4, a5, a6, a7, a8)arg_def7(a1, a2, a3, a4, a5, a6, a7); a8##_def(8)
+#define arg_def9(a1, a2, a3, a4, a5, a6, a7, a8, a9)arg_def8(a1, a2, a3, a4, a5, a6, a7, a8); a9##_def(9)
+#define arg_def10(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)arg_def9(a1, a2, a3, a4, a5, a6, a7, a8, a9); a10##_def(10)
+
+#define arg_var1(a1) a1##_var(1)
+#define arg_var2(a1, a2) arg_var1(a1), a2##_var(2)
+#define arg_var3(a1, a2, a3) arg_var2(a1, a2), a3##_var(3)
+#define arg_var4(a1, a2, a3, a4) arg_var3(a1, a2, a3), a4##_var(4)
+#define arg_var5(a1, a2, a3, a4, a5) arg_var4(a1, a2, a3, a4), a5##_var(5)
+#define arg_var6(a1, a2, a3, a4, a5, a6)arg_var5(a1, a2, a3, a4, a5), a6##_var(6)
+#define arg_var7(a1, a2, a3, a4, a5, a6, a7)arg_var6(a1, a2, a3, a4, a5, a6), a7##_var(7)
+#define arg_var8(a1, a2, a3, a4, a5, a6, a7, a8)arg_var7(a1, a2, a3, a4, a5, a6, a7), a8##_var(8)
+#define arg_var9(a1, a2, a3, a4, a5, a6, a7, a8, a9)arg_var8(a1, a2, a3, a4, a5, a6, a7, a8), a9##_var(9)
+#define arg_var10(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)arg_var9(a1, a2, a3, a4, a5, a6, a7, a8, a9), a10##_var(10)
+
+#define arg_ref1(a1) a1##_ref(1)
+#define arg_ref2(a1, a2) arg_ref1(a1), a2##_ref(2)
+#define arg_ref3(a1, a2, a3) arg_ref2(a1, a2), a3##_ref(3)
+#define arg_ref4(a1, a2, a3, a4) arg_ref3(a1, a2, a3), a4##_ref(4)
+#define arg_ref5(a1, a2, a3, a4, a5) arg_ref4(a1, a2, a3, a4), a5##_ref(5)
+#define arg_ref6(a1, a2, a3, a4, a5, a6)arg_ref5(a1, a2, a3, a4, a5), a6##_ref(6)
+#define arg_ref7(a1, a2, a3, a4, a5, a6, a7)arg_ref6(a1, a2, a3, a4, a5, a6), a7##_ref(7)
+#define arg_ref8(a1, a2, a3, a4, a5, a6, a7, a8)arg_ref7(a1, a2, a3, a4, a5, a6, a7), a8##_ref(8)
+#define arg_ref9(a1, a2, a3, a4, a5, a6, a7, a8, a9)arg_ref8(a1, a2, a3, a4, a5, a6, a7, a8), a9##_ref(9)
+#define arg_ref10(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)arg_ref9(a1, a2, a3, a4, a5, a6, a7, a8, a9), a10##_ref(10)
+
+#define arg_str1(a1) a1##_str
+#define arg_str2(a1, a2) arg_str1(a1) a2##_str
+#define arg_str3(a1, a2, a3) arg_str2(a1, a2) a3##_str
+#define arg_str4(a1, a2, a3, a4) arg_str3(a1, a2, a3) a4##_str
+#define arg_str5(a1, a2, a3, a4, a5) arg_str4(a1, a2, a3, a4) a5##_str
+#define arg_str6(a1, a2, a3, a4, a5, a6)arg_str5(a1, a2, a3, a4, a5) a6##_str
+#define arg_str7(a1, a2, a3, a4, a5, a6, a7)arg_str6(a1, a2, a3, a4, a5, a6) a7##_str
+#define arg_str8(a1, a2, a3, a4, a5, a6, a7, a8)arg_str7(a1, a2, a3, a4, a5, a6, a7) a8##_str
+#define arg_str9(a1, a2, a3, a4, a5, a6, a7, a8, a9)arg_str8(a1, a2, a3, a4, a5, a6, a7, a8) a9##_str
+#define arg_str10(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)arg_str9(a1, a2, a3, a4, a5, a6, a7, a8, a9) a10##_str
+
+#define ret_def_void
+#define ret_set_void
+#define ret_ret_void return BPY_incr_ret(Py_None)
+
+#define ret_def_GLint int ret_int
+#define ret_set_GLint ret_int=
+#define ret_ret_GLint return PyInt_FromLong(ret_int);
+
+#define ret_def_GLuint unsigned int ret_uint
+#define ret_set_GLuint ret_uint=
+#define ret_ret_GLuint return PyInt_FromLong((long) ret_uint);
+
+#define ret_def_GLenum unsigned int ret_uint
+#define ret_set_GLenum ret_uint=
+#define ret_ret_GLenum return PyInt_FromLong((long) ret_uint);
+
+#define ret_def_GLboolean unsigned char ret_bool
+#define ret_set_GLboolean ret_bool=
+#define ret_ret_GLboolean return PyInt_FromLong((long) ret_bool);
+
+#define ret_def_GLstring const unsigned char *ret_str;
+#define ret_set_GLstring ret_str=
+#define ret_ret_GLstring return PyString_FromString(ret_str);
+
+#define BGL_Wrap(nargs, funcname, ret, arg_list) \
+static PyObject *Method_##funcname (PyObject *self, PyObject *args) {\
+ arg_def##nargs arg_list; \
+ ret_def_##ret; \
+ if(!PyArg_ParseTuple(args, arg_str##nargs arg_list, arg_ref##nargs arg_list)) return NULL;\
+ ret_set_##ret gl##funcname (arg_var##nargs arg_list);\
+ ret_ret_##ret; \
+}
+
+BGL_Wrap(2, Accum, void, (GLenum, GLfloat))
+BGL_Wrap(2, AlphaFunc, void, (GLenum, GLclampf))
+BGL_Wrap(3, AreTexturesResident, GLboolean, (GLsizei, GLuintP, GLbooleanP))
+BGL_Wrap(1, Begin, void, (GLenum))
+BGL_Wrap(2, BindTexture, void, (GLenum, GLuint))
+BGL_Wrap(7, Bitmap, void, (GLsizei, GLsizei, GLfloat, GLfloat, GLfloat, GLfloat, GLubyteP))
+BGL_Wrap(2, BlendFunc, void, (GLenum, GLenum))
+BGL_Wrap(1, CallList, void, (GLuint))
+BGL_Wrap(3, CallLists, void, (GLsizei, GLenum, GLvoidP))
+BGL_Wrap(1, Clear, void, (GLbitfield))
+BGL_Wrap(4, ClearAccum, void, (GLfloat, GLfloat, GLfloat, GLfloat))
+BGL_Wrap(4, ClearColor, void, (GLclampf, GLclampf, GLclampf, GLclampf))
+BGL_Wrap(1, ClearDepth, void, (GLclampd))
+BGL_Wrap(1, ClearIndex, void, (GLfloat))
+BGL_Wrap(1, ClearStencil, void, (GLint))
+BGL_Wrap(2, ClipPlane, void, (GLenum, GLdoubleP))
+BGL_Wrap(3, Color3b, void, (GLbyte, GLbyte, GLbyte))
+BGL_Wrap(1, Color3bv, void, (GLbyteP))
+BGL_Wrap(3, Color3d, void, (GLdouble, GLdouble, GLdouble))
+BGL_Wrap(1, Color3dv, void, (GLdoubleP))
+BGL_Wrap(3, Color3f, void, (GLfloat, GLfloat, GLfloat))
+BGL_Wrap(1, Color3fv, void, (GLfloatP))
+BGL_Wrap(3, Color3i, void, (GLint, GLint, GLint))
+BGL_Wrap(1, Color3iv, void, (GLintP))
+BGL_Wrap(3, Color3s, void, (GLshort, GLshort, GLshort))
+BGL_Wrap(1, Color3sv, void, (GLshortP))
+BGL_Wrap(3, Color3ub, void, (GLubyte, GLubyte, GLubyte))
+BGL_Wrap(1, Color3ubv, void, (GLubyteP))
+BGL_Wrap(3, Color3ui, void, (GLuint, GLuint, GLuint))
+BGL_Wrap(1, Color3uiv, void, (GLuintP))
+BGL_Wrap(3, Color3us, void, (GLushort, GLushort, GLushort))
+BGL_Wrap(1, Color3usv, void, (GLushortP))
+BGL_Wrap(4, Color4b, void, (GLbyte, GLbyte, GLbyte, GLbyte))
+BGL_Wrap(1, Color4bv, void, (GLbyteP))
+BGL_Wrap(4, Color4d, void, (GLdouble, GLdouble, GLdouble, GLdouble))
+BGL_Wrap(1, Color4dv, void, (GLdoubleP))
+BGL_Wrap(4, Color4f, void, (GLfloat, GLfloat, GLfloat, GLfloat))
+BGL_Wrap(1, Color4fv, void, (GLfloatP))
+BGL_Wrap(4, Color4i, void, (GLint, GLint, GLint, GLint))
+BGL_Wrap(1, Color4iv, void, (GLintP))
+BGL_Wrap(4, Color4s, void, (GLshort, GLshort, GLshort, GLshort))
+BGL_Wrap(1, Color4sv, void, (GLshortP))
+BGL_Wrap(4, Color4ub, void, (GLubyte, GLubyte, GLubyte, GLubyte))
+BGL_Wrap(1, Color4ubv, void, (GLubyteP))
+BGL_Wrap(4, Color4ui, void, (GLuint, GLuint, GLuint, GLuint))
+BGL_Wrap(1, Color4uiv, void, (GLuintP))
+BGL_Wrap(4, Color4us, void, (GLushort, GLushort, GLushort, GLushort))
+BGL_Wrap(1, Color4usv, void, (GLushortP))
+BGL_Wrap(4, ColorMask, void, (GLboolean, GLboolean, GLboolean, GLboolean))
+BGL_Wrap(2, ColorMaterial, void, (GLenum, GLenum))
+BGL_Wrap(5, CopyPixels, void, (GLint, GLint, GLsizei, GLsizei, GLenum))
+BGL_Wrap(1, CullFace, void, (GLenum))
+BGL_Wrap(2, DeleteLists, void, (GLuint, GLsizei))
+BGL_Wrap(2, DeleteTextures, void, (GLsizei, GLuintP))
+BGL_Wrap(1, DepthFunc, void, (GLenum))
+BGL_Wrap(1, DepthMask, void, (GLboolean))
+BGL_Wrap(2, DepthRange, void, (GLclampd, GLclampd))
+BGL_Wrap(1, Disable, void, (GLenum))
+BGL_Wrap(1, DrawBuffer, void, (GLenum))
+BGL_Wrap(5, DrawPixels, void, (GLsizei, GLsizei, GLenum, GLenum, GLvoidP))
+BGL_Wrap(1, EdgeFlag, void, (GLboolean))
+BGL_Wrap(1, EdgeFlagv, void, (GLbooleanP))
+BGL_Wrap(1, Enable, void, (GLenum))
+BGL_Wrap(1, End, void, (void))
+BGL_Wrap(1, EndList, void, (void))
+BGL_Wrap(1, EvalCoord1d, void, (GLdouble))
+BGL_Wrap(1, EvalCoord1dv, void, (GLdoubleP))
+BGL_Wrap(1, EvalCoord1f, void, (GLfloat))
+BGL_Wrap(1, EvalCoord1fv, void, (GLfloatP))
+BGL_Wrap(2, EvalCoord2d, void, (GLdouble, GLdouble))
+BGL_Wrap(1, EvalCoord2dv, void, (GLdoubleP))
+BGL_Wrap(2, EvalCoord2f, void, (GLfloat, GLfloat))
+BGL_Wrap(1, EvalCoord2fv, void, (GLfloatP))
+BGL_Wrap(3, EvalMesh1, void, (GLenum, GLint, GLint))
+BGL_Wrap(5, EvalMesh2, void, (GLenum, GLint, GLint, GLint, GLint))
+BGL_Wrap(1, EvalPoint1, void, (GLint))
+BGL_Wrap(2, EvalPoint2, void, (GLint, GLint))
+BGL_Wrap(3, FeedbackBuffer, void, (GLsizei, GLenum, GLfloatP))
+BGL_Wrap(1, Finish, void, (void))
+BGL_Wrap(1, Flush, void, (void))
+BGL_Wrap(2, Fogf, void, (GLenum, GLfloat))
+BGL_Wrap(2, Fogfv, void, (GLenum, GLfloatP))
+BGL_Wrap(2, Fogi, void, (GLenum, GLint))
+BGL_Wrap(2, Fogiv, void, (GLenum, GLintP))
+BGL_Wrap(1, FrontFace, void, (GLenum))
+BGL_Wrap(6, Frustum, void, (GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble))
+BGL_Wrap(1, GenLists, GLuint, (GLsizei))
+BGL_Wrap(2, GenTextures, void, (GLsizei, GLuintP))
+BGL_Wrap(2, GetBooleanv, void, (GLenum, GLbooleanP))
+BGL_Wrap(2, GetClipPlane, void, (GLenum, GLdoubleP))
+BGL_Wrap(2, GetDoublev, void, (GLenum, GLdoubleP))
+BGL_Wrap(1, GetError, GLenum, (void))
+BGL_Wrap(2, GetFloatv, void, (GLenum, GLfloatP))
+BGL_Wrap(2, GetIntegerv, void, (GLenum, GLintP))
+BGL_Wrap(3, GetLightfv, void, (GLenum, GLenum, GLfloatP))
+BGL_Wrap(3, GetLightiv, void, (GLenum, GLenum, GLintP))
+BGL_Wrap(3, GetMapdv, void, (GLenum, GLenum, GLdoubleP))
+BGL_Wrap(3, GetMapfv, void, (GLenum, GLenum, GLfloatP))
+BGL_Wrap(3, GetMapiv, void, (GLenum, GLenum, GLintP))
+BGL_Wrap(3, GetMaterialfv, void, (GLenum, GLenum, GLfloatP))
+BGL_Wrap(3, GetMaterialiv, void, (GLenum, GLenum, GLintP))
+BGL_Wrap(2, GetPixelMapfv, void, (GLenum, GLfloatP))
+BGL_Wrap(2, GetPixelMapuiv, void, (GLenum, GLuintP))
+BGL_Wrap(2, GetPixelMapusv, void, (GLenum, GLushortP))
+BGL_Wrap(1, GetPolygonStipple, void, (GLubyteP))
+BGL_Wrap(1, GetString, GLstring, (GLenum))
+BGL_Wrap(3, GetTexEnvfv, void, (GLenum, GLenum, GLfloatP))
+BGL_Wrap(3, GetTexEnviv, void, (GLenum, GLenum, GLintP))
+BGL_Wrap(3, GetTexGendv, void, (GLenum, GLenum, GLdoubleP))
+BGL_Wrap(3, GetTexGenfv, void, (GLenum, GLenum, GLfloatP))
+BGL_Wrap(3, GetTexGeniv, void, (GLenum, GLenum, GLintP))
+BGL_Wrap(5, GetTexImage, void, (GLenum, GLint, GLenum, GLenum, GLvoidP))
+BGL_Wrap(4, GetTexLevelParameterfv, void, (GLenum, GLint, GLenum, GLfloatP))
+BGL_Wrap(4, GetTexLevelParameteriv, void, (GLenum, GLint, GLenum, GLintP))
+BGL_Wrap(3, GetTexParameterfv, void, (GLenum, GLenum, GLfloatP))
+BGL_Wrap(3, GetTexParameteriv, void, (GLenum, GLenum, GLintP))
+BGL_Wrap(2, Hint, void, (GLenum, GLenum))
+BGL_Wrap(1, IndexMask, void, (GLuint))
+BGL_Wrap(1, Indexd, void, (GLdouble))
+BGL_Wrap(1, Indexdv, void, (GLdoubleP))
+BGL_Wrap(1, Indexf, void, (GLfloat))
+BGL_Wrap(1, Indexfv, void, (GLfloatP))
+BGL_Wrap(1, Indexi, void, (GLint))
+BGL_Wrap(1, Indexiv, void, (GLintP))
+BGL_Wrap(1, Indexs, void, (GLshort))
+BGL_Wrap(1, Indexsv, void, (GLshortP))
+BGL_Wrap(1, InitNames, void, (void))
+BGL_Wrap(1, IsEnabled, GLboolean, (GLenum))
+BGL_Wrap(1, IsList, GLboolean, (GLuint))
+BGL_Wrap(1, IsTexture, GLboolean, (GLuint))
+BGL_Wrap(2, LightModelf, void, (GLenum, GLfloat))
+BGL_Wrap(2, LightModelfv, void, (GLenum, GLfloatP))
+BGL_Wrap(2, LightModeli, void, (GLenum, GLint))
+BGL_Wrap(2, LightModeliv, void, (GLenum, GLintP))
+BGL_Wrap(3, Lightf, void, (GLenum, GLenum, GLfloat))
+BGL_Wrap(3, Lightfv, void, (GLenum, GLenum, GLfloatP))
+BGL_Wrap(3, Lighti, void, (GLenum, GLenum, GLint))
+BGL_Wrap(3, Lightiv, void, (GLenum, GLenum, GLintP))
+BGL_Wrap(2, LineStipple, void, (GLint, GLushort))
+BGL_Wrap(1, LineWidth, void, (GLfloat))
+BGL_Wrap(1, ListBase, void, (GLuint))
+BGL_Wrap(1, LoadIdentity, void, (void))
+BGL_Wrap(1, LoadMatrixd, void, (GLdoubleP))
+BGL_Wrap(1, LoadMatrixf, void, (GLfloatP))
+BGL_Wrap(1, LoadName, void, (GLuint))
+BGL_Wrap(1, LogicOp, void, (GLenum))
+BGL_Wrap(6, Map1d, void, (GLenum, GLdouble, GLdouble, GLint, GLint, GLdoubleP))
+BGL_Wrap(6, Map1f, void, (GLenum, GLfloat, GLfloat, GLint, GLint, GLfloatP))
+BGL_Wrap(10, Map2d, void, (GLenum, GLdouble, GLdouble, GLint, GLint, GLdouble, GLdouble, GLint, GLint, GLdoubleP))
+BGL_Wrap(10, Map2f, void, (GLenum, GLfloat, GLfloat, GLint, GLint, GLfloat, GLfloat, GLint, GLint, GLfloatP))
+BGL_Wrap(3, MapGrid1d, void, (GLint, GLdouble, GLdouble))
+BGL_Wrap(3, MapGrid1f, void, (GLint, GLfloat, GLfloat))
+BGL_Wrap(6, MapGrid2d, void, (GLint, GLdouble, GLdouble, GLint, GLdouble, GLdouble))
+BGL_Wrap(6, MapGrid2f, void, (GLint, GLfloat, GLfloat, GLint, GLfloat, GLfloat))
+BGL_Wrap(3, Materialf, void, (GLenum, GLenum, GLfloat))
+BGL_Wrap(3, Materialfv, void, (GLenum, GLenum, GLfloatP))
+BGL_Wrap(3, Materiali, void, (GLenum, GLenum, GLint))
+BGL_Wrap(3, Materialiv, void, (GLenum, GLenum, GLintP))
+BGL_Wrap(1, MatrixMode, void, (GLenum))
+BGL_Wrap(1, MultMatrixd, void, (GLdoubleP))
+BGL_Wrap(1, MultMatrixf, void, (GLfloatP))
+BGL_Wrap(2, NewList, void, (GLuint, GLenum))
+BGL_Wrap(3, Normal3b, void, (GLbyte, GLbyte, GLbyte))
+BGL_Wrap(1, Normal3bv, void, (GLbyteP))
+BGL_Wrap(3, Normal3d, void, (GLdouble, GLdouble, GLdouble))
+BGL_Wrap(1, Normal3dv, void, (GLdoubleP))
+BGL_Wrap(3, Normal3f, void, (GLfloat, GLfloat, GLfloat))
+BGL_Wrap(1, Normal3fv, void, (GLfloatP))
+BGL_Wrap(3, Normal3i, void, (GLint, GLint, GLint))
+BGL_Wrap(1, Normal3iv, void, (GLintP))
+BGL_Wrap(3, Normal3s, void, (GLshort, GLshort, GLshort))
+BGL_Wrap(1, Normal3sv, void, (GLshortP))
+BGL_Wrap(6, Ortho, void, (GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble))
+BGL_Wrap(1, PassThrough, void, (GLfloat))
+BGL_Wrap(3, PixelMapfv, void, (GLenum, GLint, GLfloatP))
+BGL_Wrap(3, PixelMapuiv, void, (GLenum, GLint, GLuintP))
+BGL_Wrap(3, PixelMapusv, void, (GLenum, GLint, GLushortP))
+BGL_Wrap(2, PixelStoref, void, (GLenum, GLfloat))
+BGL_Wrap(2, PixelStorei, void, (GLenum, GLint))
+BGL_Wrap(2, PixelTransferf, void, (GLenum, GLfloat))
+BGL_Wrap(2, PixelTransferi, void, (GLenum, GLint))
+BGL_Wrap(2, PixelZoom, void, (GLfloat, GLfloat))
+BGL_Wrap(1, PointSize, void, (GLfloat))
+BGL_Wrap(2, PolygonMode, void, (GLenum, GLenum))
+BGL_Wrap(2, PolygonOffset, void, (GLfloat, GLfloat))
+BGL_Wrap(1, PolygonStipple, void, (GLubyteP))
+BGL_Wrap(1, PopAttrib, void, (void))
+BGL_Wrap(1, PopMatrix, void, (void))
+BGL_Wrap(1, PopName, void, (void))
+BGL_Wrap(3, PrioritizeTextures, void, (GLsizei, GLuintP, GLclampfP))
+BGL_Wrap(1, PushAttrib, void, (GLbitfield))
+BGL_Wrap(1, PushMatrix, void, (void))
+BGL_Wrap(1, PushName, void, (GLuint))
+BGL_Wrap(2, RasterPos2d, void, (GLdouble, GLdouble))
+BGL_Wrap(1, RasterPos2dv, void, (GLdoubleP))
+BGL_Wrap(2, RasterPos2f, void, (GLfloat, GLfloat))
+BGL_Wrap(1, RasterPos2fv, void, (GLfloatP))
+BGL_Wrap(2, RasterPos2i, void, (GLint, GLint))
+BGL_Wrap(1, RasterPos2iv, void, (GLintP))
+BGL_Wrap(2, RasterPos2s, void, (GLshort, GLshort))
+BGL_Wrap(1, RasterPos2sv, void, (GLshortP))
+BGL_Wrap(3, RasterPos3d, void, (GLdouble, GLdouble, GLdouble))
+BGL_Wrap(1, RasterPos3dv, void, (GLdoubleP))
+BGL_Wrap(3, RasterPos3f, void, (GLfloat, GLfloat, GLfloat))
+BGL_Wrap(1, RasterPos3fv, void, (GLfloatP))
+BGL_Wrap(3, RasterPos3i, void, (GLint, GLint, GLint))
+BGL_Wrap(1, RasterPos3iv, void, (GLintP))
+BGL_Wrap(3, RasterPos3s, void, (GLshort, GLshort, GLshort))
+BGL_Wrap(1, RasterPos3sv, void, (GLshortP))
+BGL_Wrap(4, RasterPos4d, void, (GLdouble, GLdouble, GLdouble, GLdouble))
+BGL_Wrap(1, RasterPos4dv, void, (GLdoubleP))
+BGL_Wrap(4, RasterPos4f, void, (GLfloat, GLfloat, GLfloat, GLfloat))
+BGL_Wrap(1, RasterPos4fv, void, (GLfloatP))
+BGL_Wrap(4, RasterPos4i, void, (GLint, GLint, GLint, GLint))
+BGL_Wrap(1, RasterPos4iv, void, (GLintP))
+BGL_Wrap(4, RasterPos4s, void, (GLshort, GLshort, GLshort, GLshort))
+BGL_Wrap(1, RasterPos4sv, void, (GLshortP))
+BGL_Wrap(1, ReadBuffer, void, (GLenum))
+BGL_Wrap(7, ReadPixels, void, (GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, GLvoidP))
+BGL_Wrap(4, Rectd, void, (GLdouble, GLdouble, GLdouble, GLdouble))
+BGL_Wrap(2, Rectdv, void, (GLdoubleP, GLdoubleP))
+BGL_Wrap(4, Rectf, void, (GLfloat, GLfloat, GLfloat, GLfloat))
+BGL_Wrap(2, Rectfv, void, (GLfloatP, GLfloatP))
+BGL_Wrap(4, Recti, void, (GLint, GLint, GLint, GLint))
+BGL_Wrap(2, Rectiv, void, (GLintP, GLintP))
+BGL_Wrap(4, Rects, void, (GLshort, GLshort, GLshort, GLshort))
+BGL_Wrap(2, Rectsv, void, (GLshortP, GLshortP))
+BGL_Wrap(1, RenderMode, GLint, (GLenum))
+BGL_Wrap(4, Rotated, void, (GLdouble, GLdouble, GLdouble, GLdouble))
+BGL_Wrap(4, Rotatef, void, (GLfloat, GLfloat, GLfloat, GLfloat))
+BGL_Wrap(3, Scaled, void, (GLdouble, GLdouble, GLdouble))
+BGL_Wrap(3, Scalef, void, (GLfloat, GLfloat, GLfloat))
+BGL_Wrap(4, Scissor, void, (GLint, GLint, GLsizei, GLsizei))
+BGL_Wrap(2, SelectBuffer, void, (GLsizei, GLuintP))
+BGL_Wrap(1, ShadeModel, void, (GLenum))
+BGL_Wrap(3, StencilFunc, void, (GLenum, GLint, GLuint))
+BGL_Wrap(1, StencilMask, void, (GLuint))
+BGL_Wrap(3, StencilOp, void, (GLenum, GLenum, GLenum))
+BGL_Wrap(1, TexCoord1d, void, (GLdouble))
+BGL_Wrap(1, TexCoord1dv, void, (GLdoubleP))
+BGL_Wrap(1, TexCoord1f, void, (GLfloat))
+BGL_Wrap(1, TexCoord1fv, void, (GLfloatP))
+BGL_Wrap(1, TexCoord1i, void, (GLint))
+BGL_Wrap(1, TexCoord1iv, void, (GLintP))
+BGL_Wrap(1, TexCoord1s, void, (GLshort))
+BGL_Wrap(1, TexCoord1sv, void, (GLshortP))
+BGL_Wrap(2, TexCoord2d, void, (GLdouble, GLdouble))
+BGL_Wrap(1, TexCoord2dv, void, (GLdoubleP))
+BGL_Wrap(2, TexCoord2f, void, (GLfloat, GLfloat))
+BGL_Wrap(1, TexCoord2fv, void, (GLfloatP))
+BGL_Wrap(2, TexCoord2i, void, (GLint, GLint))
+BGL_Wrap(1, TexCoord2iv, void, (GLintP))
+BGL_Wrap(2, TexCoord2s, void, (GLshort, GLshort))
+BGL_Wrap(1, TexCoord2sv, void, (GLshortP))
+BGL_Wrap(3, TexCoord3d, void, (GLdouble, GLdouble, GLdouble))
+BGL_Wrap(1, TexCoord3dv, void, (GLdoubleP))
+BGL_Wrap(3, TexCoord3f, void, (GLfloat, GLfloat, GLfloat))
+BGL_Wrap(1, TexCoord3fv, void, (GLfloatP))
+BGL_Wrap(3, TexCoord3i, void, (GLint, GLint, GLint))
+BGL_Wrap(1, TexCoord3iv, void, (GLintP))
+BGL_Wrap(3, TexCoord3s, void, (GLshort, GLshort, GLshort))
+BGL_Wrap(1, TexCoord3sv, void, (GLshortP))
+BGL_Wrap(4, TexCoord4d, void, (GLdouble, GLdouble, GLdouble, GLdouble))
+BGL_Wrap(1, TexCoord4dv, void, (GLdoubleP))
+BGL_Wrap(4, TexCoord4f, void, (GLfloat, GLfloat, GLfloat, GLfloat))
+BGL_Wrap(1, TexCoord4fv, void, (GLfloatP))
+BGL_Wrap(4, TexCoord4i, void, (GLint, GLint, GLint, GLint))
+BGL_Wrap(1, TexCoord4iv, void, (GLintP))
+BGL_Wrap(4, TexCoord4s, void, (GLshort, GLshort, GLshort, GLshort))
+BGL_Wrap(1, TexCoord4sv, void, (GLshortP))
+BGL_Wrap(3, TexEnvf, void, (GLenum, GLenum, GLfloat))
+BGL_Wrap(3, TexEnvfv, void, (GLenum, GLenum, GLfloatP))
+BGL_Wrap(3, TexEnvi, void, (GLenum, GLenum, GLint))
+BGL_Wrap(3, TexEnviv, void, (GLenum, GLenum, GLintP))
+BGL_Wrap(3, TexGend, void, (GLenum, GLenum, GLdouble))
+BGL_Wrap(3, TexGendv, void, (GLenum, GLenum, GLdoubleP))
+BGL_Wrap(3, TexGenf, void, (GLenum, GLenum, GLfloat))
+BGL_Wrap(3, TexGenfv, void, (GLenum, GLenum, GLfloatP))
+BGL_Wrap(3, TexGeni, void, (GLenum, GLenum, GLint))
+BGL_Wrap(3, TexGeniv, void, (GLenum, GLenum, GLintP))
+BGL_Wrap(8, TexImage1D, void, (GLenum, GLint, GLint, GLsizei, GLint, GLenum, GLenum, GLvoidP))
+BGL_Wrap(9, TexImage2D, void, (GLenum, GLint, GLint, GLsizei, GLsizei, GLint, GLenum, GLenum, GLvoidP))
+BGL_Wrap(3, TexParameterf, void, (GLenum, GLenum, GLfloat))
+BGL_Wrap(3, TexParameterfv, void, (GLenum, GLenum, GLfloatP))
+BGL_Wrap(3, TexParameteri, void, (GLenum, GLenum, GLint))
+BGL_Wrap(3, TexParameteriv, void, (GLenum, GLenum, GLintP))
+BGL_Wrap(3, Translated, void, (GLdouble, GLdouble, GLdouble))
+BGL_Wrap(3, Translatef, void, (GLfloat, GLfloat, GLfloat))
+BGL_Wrap(2, Vertex2d, void, (GLdouble, GLdouble))
+BGL_Wrap(1, Vertex2dv, void, (GLdoubleP))
+BGL_Wrap(2, Vertex2f, void, (GLfloat, GLfloat))
+BGL_Wrap(1, Vertex2fv, void, (GLfloatP))
+BGL_Wrap(2, Vertex2i, void, (GLint, GLint))
+BGL_Wrap(1, Vertex2iv, void, (GLintP))
+BGL_Wrap(2, Vertex2s, void, (GLshort, GLshort))
+BGL_Wrap(1, Vertex2sv, void, (GLshortP))
+BGL_Wrap(3, Vertex3d, void, (GLdouble, GLdouble, GLdouble))
+BGL_Wrap(1, Vertex3dv, void, (GLdoubleP))
+BGL_Wrap(3, Vertex3f, void, (GLfloat, GLfloat, GLfloat))
+BGL_Wrap(1, Vertex3fv, void, (GLfloatP))
+BGL_Wrap(3, Vertex3i, void, (GLint, GLint, GLint))
+BGL_Wrap(1, Vertex3iv, void, (GLintP))
+BGL_Wrap(3, Vertex3s, void, (GLshort, GLshort, GLshort))
+BGL_Wrap(1, Vertex3sv, void, (GLshortP))
+BGL_Wrap(4, Vertex4d, void, (GLdouble, GLdouble, GLdouble, GLdouble))
+BGL_Wrap(1, Vertex4dv, void, (GLdoubleP))
+BGL_Wrap(4, Vertex4f, void, (GLfloat, GLfloat, GLfloat, GLfloat))
+BGL_Wrap(1, Vertex4fv, void, (GLfloatP))
+BGL_Wrap(4, Vertex4i, void, (GLint, GLint, GLint, GLint))
+BGL_Wrap(1, Vertex4iv, void, (GLintP))
+BGL_Wrap(4, Vertex4s, void, (GLshort, GLshort, GLshort, GLshort))
+BGL_Wrap(1, Vertex4sv, void, (GLshortP))
+BGL_Wrap(4, Viewport, void, (GLint, GLint, GLsizei, GLsizei))
+#endif
+
+/* XXX */
+#undef MethodDef
+#define MethodDef(func) {"gl"#func, Method_##func, METH_VARARGS}
+
+static struct PyMethodDef BGL_methods[] = {
+ {"Buffer", Method_Buffer, METH_VARARGS, Method_Buffer_doc},
+#ifndef __APPLE__
+ MethodDef( Accum),
+ MethodDef( AlphaFunc),
+ MethodDef( AreTexturesResident),
+ MethodDef( Begin),
+ MethodDef( BindTexture),
+ MethodDef( Bitmap),
+ MethodDef( BlendFunc),
+ MethodDef( CallList),
+ MethodDef( CallLists),
+ MethodDef( Clear),
+ MethodDef( ClearAccum),
+ MethodDef( ClearColor),
+ MethodDef( ClearDepth),
+ MethodDef( ClearIndex),
+ MethodDef( ClearStencil),
+ MethodDef( ClipPlane),
+ MethodDef( Color3b),
+ MethodDef( Color3bv),
+ MethodDef( Color3d),
+ MethodDef( Color3dv),
+ MethodDef( Color3f),
+ MethodDef( Color3fv),
+ MethodDef( Color3i),
+ MethodDef( Color3iv),
+ MethodDef( Color3s),
+ MethodDef( Color3sv),
+ MethodDef( Color3ub),
+ MethodDef( Color3ubv),
+ MethodDef( Color3ui),
+ MethodDef( Color3uiv),
+ MethodDef( Color3us),
+ MethodDef( Color3usv),
+ MethodDef( Color4b),
+ MethodDef( Color4bv),
+ MethodDef( Color4d),
+ MethodDef( Color4dv),
+ MethodDef( Color4f),
+ MethodDef( Color4fv),
+ MethodDef( Color4i),
+ MethodDef( Color4iv),
+ MethodDef( Color4s),
+ MethodDef( Color4sv),
+ MethodDef( Color4ub),
+ MethodDef( Color4ubv),
+ MethodDef( Color4ui),
+ MethodDef( Color4uiv),
+ MethodDef( Color4us),
+ MethodDef( Color4usv),
+ MethodDef( ColorMask),
+ MethodDef( ColorMaterial),
+ MethodDef( CopyPixels),
+ MethodDef( CullFace),
+ MethodDef( DeleteLists),
+ MethodDef( DeleteTextures),
+ MethodDef( DepthFunc),
+ MethodDef( DepthMask),
+ MethodDef( DepthRange),
+ MethodDef( Disable),
+ MethodDef( DrawBuffer),
+ MethodDef( DrawPixels),
+ MethodDef( EdgeFlag),
+ MethodDef( EdgeFlagv),
+ MethodDef( Enable),
+ MethodDef( End),
+ MethodDef( EndList),
+ MethodDef( EvalCoord1d),
+ MethodDef( EvalCoord1dv),
+ MethodDef( EvalCoord1f),
+ MethodDef( EvalCoord1fv),
+ MethodDef( EvalCoord2d),
+ MethodDef( EvalCoord2dv),
+ MethodDef( EvalCoord2f),
+ MethodDef( EvalCoord2fv),
+ MethodDef( EvalMesh1),
+ MethodDef( EvalMesh2),
+ MethodDef( EvalPoint1),
+ MethodDef( EvalPoint2),
+ MethodDef( FeedbackBuffer),
+ MethodDef( Finish),
+ MethodDef( Flush),
+ MethodDef( Fogf),
+ MethodDef( Fogfv),
+ MethodDef( Fogi),
+ MethodDef( Fogiv),
+ MethodDef( FrontFace),
+ MethodDef( Frustum),
+ MethodDef( GenLists),
+ MethodDef( GenTextures),
+ MethodDef( GetBooleanv),
+ MethodDef( GetClipPlane),
+ MethodDef( GetDoublev),
+ MethodDef( GetError),
+ MethodDef( GetFloatv),
+ MethodDef( GetIntegerv),
+ MethodDef( GetLightfv),
+ MethodDef( GetLightiv),
+ MethodDef( GetMapdv),
+ MethodDef( GetMapfv),
+ MethodDef( GetMapiv),
+ MethodDef( GetMaterialfv),
+ MethodDef( GetMaterialiv),
+ MethodDef( GetPixelMapfv),
+ MethodDef( GetPixelMapuiv),
+ MethodDef( GetPixelMapusv),
+ MethodDef( GetPolygonStipple),
+ MethodDef( GetString),
+ MethodDef( GetTexEnvfv),
+ MethodDef( GetTexEnviv),
+ MethodDef( GetTexGendv),
+ MethodDef( GetTexGenfv),
+ MethodDef( GetTexGeniv),
+ MethodDef( GetTexImage),
+ MethodDef( GetTexLevelParameterfv),
+ MethodDef( GetTexLevelParameteriv),
+ MethodDef( GetTexParameterfv),
+ MethodDef( GetTexParameteriv),
+ MethodDef( Hint),
+ MethodDef( IndexMask),
+ MethodDef( Indexd),
+ MethodDef( Indexdv),
+ MethodDef( Indexf),
+ MethodDef( Indexfv),
+ MethodDef( Indexi),
+ MethodDef( Indexiv),
+ MethodDef( Indexs),
+ MethodDef( Indexsv),
+ MethodDef( InitNames),
+ MethodDef( IsEnabled),
+ MethodDef( IsList),
+ MethodDef( IsTexture),
+ MethodDef( LightModelf),
+ MethodDef( LightModelfv),
+ MethodDef( LightModeli),
+ MethodDef( LightModeliv),
+ MethodDef( Lightf),
+ MethodDef( Lightfv),
+ MethodDef( Lighti),
+ MethodDef( Lightiv),
+ MethodDef( LineStipple),
+ MethodDef( LineWidth),
+ MethodDef( ListBase),
+ MethodDef( LoadIdentity),
+ MethodDef( LoadMatrixd),
+ MethodDef( LoadMatrixf),
+ MethodDef( LoadName),
+ MethodDef( LogicOp),
+ MethodDef( Map1d),
+ MethodDef( Map1f),
+ MethodDef( Map2d),
+ MethodDef( Map2f),
+ MethodDef( MapGrid1d),
+ MethodDef( MapGrid1f),
+ MethodDef( MapGrid2d),
+ MethodDef( MapGrid2f),
+ MethodDef( Materialf),
+ MethodDef( Materialfv),
+ MethodDef( Materiali),
+ MethodDef( Materialiv),
+ MethodDef( MatrixMode),
+ MethodDef( MultMatrixd),
+ MethodDef( MultMatrixf),
+ MethodDef( NewList),
+ MethodDef( Normal3b),
+ MethodDef( Normal3bv),
+ MethodDef( Normal3d),
+ MethodDef( Normal3dv),
+ MethodDef( Normal3f),
+ MethodDef( Normal3fv),
+ MethodDef( Normal3i),
+ MethodDef( Normal3iv),
+ MethodDef( Normal3s),
+ MethodDef( Normal3sv),
+ MethodDef( Ortho),
+ MethodDef( PassThrough),
+ MethodDef( PixelMapfv),
+ MethodDef( PixelMapuiv),
+ MethodDef( PixelMapusv),
+ MethodDef( PixelStoref),
+ MethodDef( PixelStorei),
+ MethodDef( PixelTransferf),
+ MethodDef( PixelTransferi),
+ MethodDef( PixelZoom),
+ MethodDef( PointSize),
+ MethodDef( PolygonMode),
+ MethodDef( PolygonOffset),
+ MethodDef( PolygonStipple),
+ MethodDef( PopAttrib),
+ MethodDef( PopMatrix),
+ MethodDef( PopName),
+ MethodDef( PrioritizeTextures),
+ MethodDef( PushAttrib),
+ MethodDef( PushMatrix),
+ MethodDef( PushName),
+ MethodDef( RasterPos2d),
+ MethodDef( RasterPos2dv),
+ MethodDef( RasterPos2f),
+ MethodDef( RasterPos2fv),
+ MethodDef( RasterPos2i),
+ MethodDef( RasterPos2iv),
+ MethodDef( RasterPos2s),
+ MethodDef( RasterPos2sv),
+ MethodDef( RasterPos3d),
+ MethodDef( RasterPos3dv),
+ MethodDef( RasterPos3f),
+ MethodDef( RasterPos3fv),
+ MethodDef( RasterPos3i),
+ MethodDef( RasterPos3iv),
+ MethodDef( RasterPos3s),
+ MethodDef( RasterPos3sv),
+ MethodDef( RasterPos4d),
+ MethodDef( RasterPos4dv),
+ MethodDef( RasterPos4f),
+ MethodDef( RasterPos4fv),
+ MethodDef( RasterPos4i),
+ MethodDef( RasterPos4iv),
+ MethodDef( RasterPos4s),
+ MethodDef( RasterPos4sv),
+ MethodDef( ReadBuffer),
+ MethodDef( ReadPixels),
+ MethodDef( Rectd),
+ MethodDef( Rectdv),
+ MethodDef( Rectf),
+ MethodDef( Rectfv),
+ MethodDef( Recti),
+ MethodDef( Rectiv),
+ MethodDef( Rects),
+ MethodDef( Rectsv),
+ MethodDef( RenderMode),
+ MethodDef( Rotated),
+ MethodDef( Rotatef),
+ MethodDef( Scaled),
+ MethodDef( Scalef),
+ MethodDef( Scissor),
+ MethodDef( SelectBuffer),
+ MethodDef( ShadeModel),
+ MethodDef( StencilFunc),
+ MethodDef( StencilMask),
+ MethodDef( StencilOp),
+ MethodDef( TexCoord1d),
+ MethodDef( TexCoord1dv),
+ MethodDef( TexCoord1f),
+ MethodDef( TexCoord1fv),
+ MethodDef( TexCoord1i),
+ MethodDef( TexCoord1iv),
+ MethodDef( TexCoord1s),
+ MethodDef( TexCoord1sv),
+ MethodDef( TexCoord2d),
+ MethodDef( TexCoord2dv),
+ MethodDef( TexCoord2f),
+ MethodDef( TexCoord2fv),
+ MethodDef( TexCoord2i),
+ MethodDef( TexCoord2iv),
+ MethodDef( TexCoord2s),
+ MethodDef( TexCoord2sv),
+ MethodDef( TexCoord3d),
+ MethodDef( TexCoord3dv),
+ MethodDef( TexCoord3f),
+ MethodDef( TexCoord3fv),
+ MethodDef( TexCoord3i),
+ MethodDef( TexCoord3iv),
+ MethodDef( TexCoord3s),
+ MethodDef( TexCoord3sv),
+ MethodDef( TexCoord4d),
+ MethodDef( TexCoord4dv),
+ MethodDef( TexCoord4f),
+ MethodDef( TexCoord4fv),
+ MethodDef( TexCoord4i),
+ MethodDef( TexCoord4iv),
+ MethodDef( TexCoord4s),
+ MethodDef( TexCoord4sv),
+ MethodDef( TexEnvf),
+ MethodDef( TexEnvfv),
+ MethodDef( TexEnvi),
+ MethodDef( TexEnviv),
+ MethodDef( TexGend),
+ MethodDef( TexGendv),
+ MethodDef( TexGenf),
+ MethodDef( TexGenfv),
+ MethodDef( TexGeni),
+ MethodDef( TexGeniv),
+ MethodDef( TexImage1D),
+ MethodDef( TexImage2D),
+ MethodDef( TexParameterf),
+ MethodDef( TexParameterfv),
+ MethodDef( TexParameteri),
+ MethodDef( TexParameteriv),
+ MethodDef( Translated),
+ MethodDef( Translatef),
+ MethodDef( Vertex2d),
+ MethodDef( Vertex2dv),
+ MethodDef( Vertex2f),
+ MethodDef( Vertex2fv),
+ MethodDef( Vertex2i),
+ MethodDef( Vertex2iv),
+ MethodDef( Vertex2s),
+ MethodDef( Vertex2sv),
+ MethodDef( Vertex3d),
+ MethodDef( Vertex3dv),
+ MethodDef( Vertex3f),
+ MethodDef( Vertex3fv),
+ MethodDef( Vertex3i),
+ MethodDef( Vertex3iv),
+ MethodDef( Vertex3s),
+ MethodDef( Vertex3sv),
+ MethodDef( Vertex4d),
+ MethodDef( Vertex4dv),
+ MethodDef( Vertex4f),
+ MethodDef( Vertex4fv),
+ MethodDef( Vertex4i),
+ MethodDef( Vertex4iv),
+ MethodDef( Vertex4s),
+ MethodDef( Vertex4sv),
+ MethodDef( Viewport),
+#endif
+
+ {NULL, NULL}
+};
+
+PyObject *init_py_bgl(void)
+{
+ PyObject *mod= Py_InitModule(SUBMODULE(BGL), BGL_methods);
+ PyObject *dict= PyModule_GetDict(mod);
+
+ Buffer_Type.ob_type= &PyType_Type;
+
+ BPY_ADDCONST(dict, GL_CURRENT_BIT);
+ BPY_ADDCONST(dict, GL_POINT_BIT);
+ BPY_ADDCONST(dict, GL_LINE_BIT);
+ BPY_ADDCONST(dict, GL_POLYGON_BIT);
+ BPY_ADDCONST(dict, GL_POLYGON_STIPPLE_BIT);
+ BPY_ADDCONST(dict, GL_PIXEL_MODE_BIT);
+ BPY_ADDCONST(dict, GL_LIGHTING_BIT);
+ BPY_ADDCONST(dict, GL_FOG_BIT);
+ BPY_ADDCONST(dict, GL_DEPTH_BUFFER_BIT);
+ BPY_ADDCONST(dict, GL_ACCUM_BUFFER_BIT);
+ BPY_ADDCONST(dict, GL_STENCIL_BUFFER_BIT);
+ BPY_ADDCONST(dict, GL_VIEWPORT_BIT);
+ BPY_ADDCONST(dict, GL_TRANSFORM_BIT);
+ BPY_ADDCONST(dict, GL_ENABLE_BIT);
+ BPY_ADDCONST(dict, GL_COLOR_BUFFER_BIT);
+ BPY_ADDCONST(dict, GL_HINT_BIT);
+ BPY_ADDCONST(dict, GL_EVAL_BIT);
+ BPY_ADDCONST(dict, GL_LIST_BIT);
+ BPY_ADDCONST(dict, GL_TEXTURE_BIT);
+ BPY_ADDCONST(dict, GL_SCISSOR_BIT);
+ BPY_ADDCONST(dict, GL_ALL_ATTRIB_BITS);
+
+ BPY_ADDCONST(dict, GL_FALSE);
+ BPY_ADDCONST(dict, GL_TRUE);
+
+ BPY_ADDCONST(dict, GL_POINTS);
+ BPY_ADDCONST(dict, GL_LINES);
+ BPY_ADDCONST(dict, GL_LINE_LOOP);
+ BPY_ADDCONST(dict, GL_LINE_STRIP);
+ BPY_ADDCONST(dict, GL_TRIANGLES);
+ BPY_ADDCONST(dict, GL_TRIANGLE_STRIP);
+ BPY_ADDCONST(dict, GL_TRIANGLE_FAN);
+ BPY_ADDCONST(dict, GL_QUADS);
+ BPY_ADDCONST(dict, GL_QUAD_STRIP);
+ BPY_ADDCONST(dict, GL_POLYGON);
+
+ BPY_ADDCONST(dict, GL_ACCUM);
+ BPY_ADDCONST(dict, GL_LOAD);
+ BPY_ADDCONST(dict, GL_RETURN);
+ BPY_ADDCONST(dict, GL_MULT);
+ BPY_ADDCONST(dict, GL_ADD);
+
+ BPY_ADDCONST(dict, GL_NEVER);
+ BPY_ADDCONST(dict, GL_LESS);
+ BPY_ADDCONST(dict, GL_EQUAL);
+ BPY_ADDCONST(dict, GL_LEQUAL);
+ BPY_ADDCONST(dict, GL_GREATER);
+ BPY_ADDCONST(dict, GL_NOTEQUAL);
+ BPY_ADDCONST(dict, GL_GEQUAL);
+ BPY_ADDCONST(dict, GL_ALWAYS);
+
+ BPY_ADDCONST(dict, GL_ZERO);
+ BPY_ADDCONST(dict, GL_ONE);
+ BPY_ADDCONST(dict, GL_SRC_COLOR);
+ BPY_ADDCONST(dict, GL_ONE_MINUS_SRC_COLOR);
+ BPY_ADDCONST(dict, GL_SRC_ALPHA);
+ BPY_ADDCONST(dict, GL_ONE_MINUS_SRC_ALPHA);
+ BPY_ADDCONST(dict, GL_DST_ALPHA);
+ BPY_ADDCONST(dict, GL_ONE_MINUS_DST_ALPHA);
+
+ BPY_ADDCONST(dict, GL_DST_COLOR);
+ BPY_ADDCONST(dict, GL_ONE_MINUS_DST_COLOR);
+ BPY_ADDCONST(dict, GL_SRC_ALPHA_SATURATE);
+
+ BPY_ADDCONST(dict, GL_NONE);
+ BPY_ADDCONST(dict, GL_FRONT_LEFT);
+ BPY_ADDCONST(dict, GL_FRONT_RIGHT);
+ BPY_ADDCONST(dict, GL_BACK_LEFT);
+ BPY_ADDCONST(dict, GL_BACK_RIGHT);
+ BPY_ADDCONST(dict, GL_FRONT);
+ BPY_ADDCONST(dict, GL_BACK);
+ BPY_ADDCONST(dict, GL_LEFT);
+ BPY_ADDCONST(dict, GL_RIGHT);
+ BPY_ADDCONST(dict, GL_FRONT_AND_BACK);
+ BPY_ADDCONST(dict, GL_AUX0);
+ BPY_ADDCONST(dict, GL_AUX1);
+ BPY_ADDCONST(dict, GL_AUX2);
+ BPY_ADDCONST(dict, GL_AUX3);
+
+ BPY_ADDCONST(dict, GL_NO_ERROR);
+ BPY_ADDCONST(dict, GL_INVALID_ENUM);
+ BPY_ADDCONST(dict, GL_INVALID_VALUE);
+ BPY_ADDCONST(dict, GL_INVALID_OPERATION);
+ BPY_ADDCONST(dict, GL_STACK_OVERFLOW);
+ BPY_ADDCONST(dict, GL_STACK_UNDERFLOW);
+ BPY_ADDCONST(dict, GL_OUT_OF_MEMORY);
+
+ BPY_ADDCONST(dict, GL_2D);
+ BPY_ADDCONST(dict, GL_3D);
+ BPY_ADDCONST(dict, GL_3D_COLOR);
+ BPY_ADDCONST(dict, GL_3D_COLOR_TEXTURE);
+ BPY_ADDCONST(dict, GL_4D_COLOR_TEXTURE);
+
+ BPY_ADDCONST(dict, GL_PASS_THROUGH_TOKEN);
+ BPY_ADDCONST(dict, GL_POINT_TOKEN);
+ BPY_ADDCONST(dict, GL_LINE_TOKEN);
+ BPY_ADDCONST(dict, GL_POLYGON_TOKEN);
+ BPY_ADDCONST(dict, GL_BITMAP_TOKEN);
+ BPY_ADDCONST(dict, GL_DRAW_PIXEL_TOKEN);
+ BPY_ADDCONST(dict, GL_COPY_PIXEL_TOKEN);
+ BPY_ADDCONST(dict, GL_LINE_RESET_TOKEN);
+
+ BPY_ADDCONST(dict, GL_EXP);
+ BPY_ADDCONST(dict, GL_EXP2);
+
+ BPY_ADDCONST(dict, GL_CW);
+ BPY_ADDCONST(dict, GL_CCW);
+
+ BPY_ADDCONST(dict, GL_COEFF);
+ BPY_ADDCONST(dict, GL_ORDER);
+ BPY_ADDCONST(dict, GL_DOMAIN);
+
+ BPY_ADDCONST(dict, GL_PIXEL_MAP_I_TO_I);
+ BPY_ADDCONST(dict, GL_PIXEL_MAP_S_TO_S);
+ BPY_ADDCONST(dict, GL_PIXEL_MAP_I_TO_R);
+ BPY_ADDCONST(dict, GL_PIXEL_MAP_I_TO_G);
+ BPY_ADDCONST(dict, GL_PIXEL_MAP_I_TO_B);
+ BPY_ADDCONST(dict, GL_PIXEL_MAP_I_TO_A);
+ BPY_ADDCONST(dict, GL_PIXEL_MAP_R_TO_R);
+ BPY_ADDCONST(dict, GL_PIXEL_MAP_G_TO_G);
+ BPY_ADDCONST(dict, GL_PIXEL_MAP_B_TO_B);
+ BPY_ADDCONST(dict, GL_PIXEL_MAP_A_TO_A);
+
+ BPY_ADDCONST(dict, GL_CURRENT_COLOR);
+ BPY_ADDCONST(dict, GL_CURRENT_INDEX);
+ BPY_ADDCONST(dict, GL_CURRENT_NORMAL);
+ BPY_ADDCONST(dict, GL_CURRENT_TEXTURE_COORDS);
+ BPY_ADDCONST(dict, GL_CURRENT_RASTER_COLOR);
+ BPY_ADDCONST(dict, GL_CURRENT_RASTER_INDEX);
+ BPY_ADDCONST(dict, GL_CURRENT_RASTER_TEXTURE_COORDS);
+ BPY_ADDCONST(dict, GL_CURRENT_RASTER_POSITION);
+ BPY_ADDCONST(dict, GL_CURRENT_RASTER_POSITION_VALID);
+ BPY_ADDCONST(dict, GL_CURRENT_RASTER_DISTANCE);
+ BPY_ADDCONST(dict, GL_POINT_SMOOTH);
+ BPY_ADDCONST(dict, GL_POINT_SIZE);
+ BPY_ADDCONST(dict, GL_POINT_SIZE_RANGE);
+ BPY_ADDCONST(dict, GL_POINT_SIZE_GRANULARITY);
+ BPY_ADDCONST(dict, GL_LINE_SMOOTH);
+ BPY_ADDCONST(dict, GL_LINE_WIDTH);
+ BPY_ADDCONST(dict, GL_LINE_WIDTH_RANGE);
+ BPY_ADDCONST(dict, GL_LINE_WIDTH_GRANULARITY);
+ BPY_ADDCONST(dict, GL_LINE_STIPPLE);
+ BPY_ADDCONST(dict, GL_LINE_STIPPLE_PATTERN);
+ BPY_ADDCONST(dict, GL_LINE_STIPPLE_REPEAT);
+ BPY_ADDCONST(dict, GL_LIST_MODE);
+ BPY_ADDCONST(dict, GL_MAX_LIST_NESTING);
+ BPY_ADDCONST(dict, GL_LIST_BASE);
+ BPY_ADDCONST(dict, GL_LIST_INDEX);
+ BPY_ADDCONST(dict, GL_POLYGON_MODE);
+ BPY_ADDCONST(dict, GL_POLYGON_SMOOTH);
+ BPY_ADDCONST(dict, GL_POLYGON_STIPPLE);
+ BPY_ADDCONST(dict, GL_EDGE_FLAG);
+ BPY_ADDCONST(dict, GL_CULL_FACE);
+ BPY_ADDCONST(dict, GL_CULL_FACE_MODE);
+ BPY_ADDCONST(dict, GL_FRONT_FACE);
+ BPY_ADDCONST(dict, GL_LIGHTING);
+ BPY_ADDCONST(dict, GL_LIGHT_MODEL_LOCAL_VIEWER);
+ BPY_ADDCONST(dict, GL_LIGHT_MODEL_TWO_SIDE);
+ BPY_ADDCONST(dict, GL_LIGHT_MODEL_AMBIENT);
+ BPY_ADDCONST(dict, GL_SHADE_MODEL);
+ BPY_ADDCONST(dict, GL_COLOR_MATERIAL_FACE);
+ BPY_ADDCONST(dict, GL_COLOR_MATERIAL_PARAMETER);
+ BPY_ADDCONST(dict, GL_COLOR_MATERIAL);
+ BPY_ADDCONST(dict, GL_FOG);
+ BPY_ADDCONST(dict, GL_FOG_INDEX);
+ BPY_ADDCONST(dict, GL_FOG_DENSITY);
+ BPY_ADDCONST(dict, GL_FOG_START);
+ BPY_ADDCONST(dict, GL_FOG_END);
+ BPY_ADDCONST(dict, GL_FOG_MODE);
+ BPY_ADDCONST(dict, GL_FOG_COLOR);
+ BPY_ADDCONST(dict, GL_DEPTH_RANGE);
+ BPY_ADDCONST(dict, GL_DEPTH_TEST);
+ BPY_ADDCONST(dict, GL_DEPTH_WRITEMASK);
+ BPY_ADDCONST(dict, GL_DEPTH_CLEAR_VALUE);
+ BPY_ADDCONST(dict, GL_DEPTH_FUNC);
+ BPY_ADDCONST(dict, GL_ACCUM_CLEAR_VALUE);
+ BPY_ADDCONST(dict, GL_STENCIL_TEST);
+ BPY_ADDCONST(dict, GL_STENCIL_CLEAR_VALUE);
+ BPY_ADDCONST(dict, GL_STENCIL_FUNC);
+ BPY_ADDCONST(dict, GL_STENCIL_VALUE_MASK);
+ BPY_ADDCONST(dict, GL_STENCIL_FAIL);
+ BPY_ADDCONST(dict, GL_STENCIL_PASS_DEPTH_FAIL);
+ BPY_ADDCONST(dict, GL_STENCIL_PASS_DEPTH_PASS);
+ BPY_ADDCONST(dict, GL_STENCIL_REF);
+ BPY_ADDCONST(dict, GL_STENCIL_WRITEMASK);
+ BPY_ADDCONST(dict, GL_MATRIX_MODE);
+ BPY_ADDCONST(dict, GL_NORMALIZE);
+ BPY_ADDCONST(dict, GL_VIEWPORT);
+ BPY_ADDCONST(dict, GL_MODELVIEW_STACK_DEPTH);
+ BPY_ADDCONST(dict, GL_PROJECTION_STACK_DEPTH);
+ BPY_ADDCONST(dict, GL_TEXTURE_STACK_DEPTH);
+ BPY_ADDCONST(dict, GL_MODELVIEW_MATRIX);
+ BPY_ADDCONST(dict, GL_PROJECTION_MATRIX);
+ BPY_ADDCONST(dict, GL_TEXTURE_MATRIX);
+ BPY_ADDCONST(dict, GL_ATTRIB_STACK_DEPTH);
+ BPY_ADDCONST(dict, GL_ALPHA_TEST);
+ BPY_ADDCONST(dict, GL_ALPHA_TEST_FUNC);
+ BPY_ADDCONST(dict, GL_ALPHA_TEST_REF);
+ BPY_ADDCONST(dict, GL_DITHER);
+ BPY_ADDCONST(dict, GL_BLEND_DST);
+ BPY_ADDCONST(dict, GL_BLEND_SRC);
+ BPY_ADDCONST(dict, GL_BLEND);
+ BPY_ADDCONST(dict, GL_LOGIC_OP_MODE);
+ BPY_ADDCONST(dict, GL_LOGIC_OP);
+ BPY_ADDCONST(dict, GL_AUX_BUFFERS);
+ BPY_ADDCONST(dict, GL_DRAW_BUFFER);
+ BPY_ADDCONST(dict, GL_READ_BUFFER);
+ BPY_ADDCONST(dict, GL_SCISSOR_BOX);
+ BPY_ADDCONST(dict, GL_SCISSOR_TEST);
+ BPY_ADDCONST(dict, GL_INDEX_CLEAR_VALUE);
+ BPY_ADDCONST(dict, GL_INDEX_WRITEMASK);
+ BPY_ADDCONST(dict, GL_COLOR_CLEAR_VALUE);
+ BPY_ADDCONST(dict, GL_COLOR_WRITEMASK);
+ BPY_ADDCONST(dict, GL_INDEX_MODE);
+ BPY_ADDCONST(dict, GL_RGBA_MODE);
+ BPY_ADDCONST(dict, GL_DOUBLEBUFFER);
+ BPY_ADDCONST(dict, GL_STEREO);
+ BPY_ADDCONST(dict, GL_RENDER_MODE);
+ BPY_ADDCONST(dict, GL_PERSPECTIVE_CORRECTION_HINT);
+ BPY_ADDCONST(dict, GL_POINT_SMOOTH_HINT);
+ BPY_ADDCONST(dict, GL_LINE_SMOOTH_HINT);
+ BPY_ADDCONST(dict, GL_POLYGON_SMOOTH_HINT);
+ BPY_ADDCONST(dict, GL_FOG_HINT);
+ BPY_ADDCONST(dict, GL_TEXTURE_GEN_S);
+ BPY_ADDCONST(dict, GL_TEXTURE_GEN_T);
+ BPY_ADDCONST(dict, GL_TEXTURE_GEN_R);
+ BPY_ADDCONST(dict, GL_TEXTURE_GEN_Q);
+ BPY_ADDCONST(dict, GL_PIXEL_MAP_I_TO_I_SIZE);
+ BPY_ADDCONST(dict, GL_PIXEL_MAP_S_TO_S_SIZE);
+ BPY_ADDCONST(dict, GL_PIXEL_MAP_I_TO_R_SIZE);
+ BPY_ADDCONST(dict, GL_PIXEL_MAP_I_TO_G_SIZE);
+ BPY_ADDCONST(dict, GL_PIXEL_MAP_I_TO_B_SIZE);
+ BPY_ADDCONST(dict, GL_PIXEL_MAP_I_TO_A_SIZE);
+ BPY_ADDCONST(dict, GL_PIXEL_MAP_R_TO_R_SIZE);
+ BPY_ADDCONST(dict, GL_PIXEL_MAP_G_TO_G_SIZE);
+ BPY_ADDCONST(dict, GL_PIXEL_MAP_B_TO_B_SIZE);
+ BPY_ADDCONST(dict, GL_PIXEL_MAP_A_TO_A_SIZE);
+ BPY_ADDCONST(dict, GL_UNPACK_SWAP_BYTES);
+ BPY_ADDCONST(dict, GL_UNPACK_LSB_FIRST);
+ BPY_ADDCONST(dict, GL_UNPACK_ROW_LENGTH);
+ BPY_ADDCONST(dict, GL_UNPACK_SKIP_ROWS);
+ BPY_ADDCONST(dict, GL_UNPACK_SKIP_PIXELS);
+ BPY_ADDCONST(dict, GL_UNPACK_ALIGNMENT);
+ BPY_ADDCONST(dict, GL_PACK_SWAP_BYTES);
+ BPY_ADDCONST(dict, GL_PACK_LSB_FIRST);
+ BPY_ADDCONST(dict, GL_PACK_ROW_LENGTH);
+ BPY_ADDCONST(dict, GL_PACK_SKIP_ROWS);
+ BPY_ADDCONST(dict, GL_PACK_SKIP_PIXELS);
+ BPY_ADDCONST(dict, GL_PACK_ALIGNMENT);
+ BPY_ADDCONST(dict, GL_MAP_COLOR);
+ BPY_ADDCONST(dict, GL_MAP_STENCIL);
+ BPY_ADDCONST(dict, GL_INDEX_SHIFT);
+ BPY_ADDCONST(dict, GL_INDEX_OFFSET);
+ BPY_ADDCONST(dict, GL_RED_SCALE);
+ BPY_ADDCONST(dict, GL_RED_BIAS);
+ BPY_ADDCONST(dict, GL_ZOOM_X);
+ BPY_ADDCONST(dict, GL_ZOOM_Y);
+ BPY_ADDCONST(dict, GL_GREEN_SCALE);
+ BPY_ADDCONST(dict, GL_GREEN_BIAS);
+ BPY_ADDCONST(dict, GL_BLUE_SCALE);
+ BPY_ADDCONST(dict, GL_BLUE_BIAS);
+ BPY_ADDCONST(dict, GL_ALPHA_SCALE);
+ BPY_ADDCONST(dict, GL_ALPHA_BIAS);
+ BPY_ADDCONST(dict, GL_DEPTH_SCALE);
+ BPY_ADDCONST(dict, GL_DEPTH_BIAS);
+ BPY_ADDCONST(dict, GL_MAX_EVAL_ORDER);
+ BPY_ADDCONST(dict, GL_MAX_LIGHTS);
+ BPY_ADDCONST(dict, GL_MAX_CLIP_PLANES);
+ BPY_ADDCONST(dict, GL_MAX_TEXTURE_SIZE);
+ BPY_ADDCONST(dict, GL_MAX_PIXEL_MAP_TABLE);
+ BPY_ADDCONST(dict, GL_MAX_ATTRIB_STACK_DEPTH);
+ BPY_ADDCONST(dict, GL_MAX_MODELVIEW_STACK_DEPTH);
+ BPY_ADDCONST(dict, GL_MAX_NAME_STACK_DEPTH);
+ BPY_ADDCONST(dict, GL_MAX_PROJECTION_STACK_DEPTH);
+ BPY_ADDCONST(dict, GL_MAX_TEXTURE_STACK_DEPTH);
+ BPY_ADDCONST(dict, GL_MAX_VIEWPORT_DIMS);
+ BPY_ADDCONST(dict, GL_SUBPIXEL_BITS);
+ BPY_ADDCONST(dict, GL_INDEX_BITS);
+ BPY_ADDCONST(dict, GL_RED_BITS);
+ BPY_ADDCONST(dict, GL_GREEN_BITS);
+ BPY_ADDCONST(dict, GL_BLUE_BITS);
+ BPY_ADDCONST(dict, GL_ALPHA_BITS);
+ BPY_ADDCONST(dict, GL_DEPTH_BITS);
+ BPY_ADDCONST(dict, GL_STENCIL_BITS);
+ BPY_ADDCONST(dict, GL_ACCUM_RED_BITS);
+ BPY_ADDCONST(dict, GL_ACCUM_GREEN_BITS);
+ BPY_ADDCONST(dict, GL_ACCUM_BLUE_BITS);
+ BPY_ADDCONST(dict, GL_ACCUM_ALPHA_BITS);
+ BPY_ADDCONST(dict, GL_NAME_STACK_DEPTH);
+ BPY_ADDCONST(dict, GL_AUTO_NORMAL);
+ BPY_ADDCONST(dict, GL_MAP1_COLOR_4);
+ BPY_ADDCONST(dict, GL_MAP1_INDEX);
+ BPY_ADDCONST(dict, GL_MAP1_NORMAL);
+ BPY_ADDCONST(dict, GL_MAP1_TEXTURE_COORD_1);
+ BPY_ADDCONST(dict, GL_MAP1_TEXTURE_COORD_2);
+ BPY_ADDCONST(dict, GL_MAP1_TEXTURE_COORD_3);
+ BPY_ADDCONST(dict, GL_MAP1_TEXTURE_COORD_4);
+ BPY_ADDCONST(dict, GL_MAP1_VERTEX_3);
+ BPY_ADDCONST(dict, GL_MAP1_VERTEX_4);
+ BPY_ADDCONST(dict, GL_MAP2_COLOR_4);
+ BPY_ADDCONST(dict, GL_MAP2_INDEX);
+ BPY_ADDCONST(dict, GL_MAP2_NORMAL);
+ BPY_ADDCONST(dict, GL_MAP2_TEXTURE_COORD_1);
+ BPY_ADDCONST(dict, GL_MAP2_TEXTURE_COORD_2);
+ BPY_ADDCONST(dict, GL_MAP2_TEXTURE_COORD_3);
+ BPY_ADDCONST(dict, GL_MAP2_TEXTURE_COORD_4);
+ BPY_ADDCONST(dict, GL_MAP2_VERTEX_3);
+ BPY_ADDCONST(dict, GL_MAP2_VERTEX_4);
+ BPY_ADDCONST(dict, GL_MAP1_GRID_DOMAIN);
+ BPY_ADDCONST(dict, GL_MAP1_GRID_SEGMENTS);
+ BPY_ADDCONST(dict, GL_MAP2_GRID_DOMAIN);
+ BPY_ADDCONST(dict, GL_MAP2_GRID_SEGMENTS);
+ BPY_ADDCONST(dict, GL_TEXTURE_1D);
+ BPY_ADDCONST(dict, GL_TEXTURE_2D);
+
+ BPY_ADDCONST(dict, GL_TEXTURE_WIDTH);
+ BPY_ADDCONST(dict, GL_TEXTURE_HEIGHT);
+ BPY_ADDCONST(dict, GL_TEXTURE_COMPONENTS);
+ BPY_ADDCONST(dict, GL_TEXTURE_BORDER_COLOR);
+ BPY_ADDCONST(dict, GL_TEXTURE_BORDER);
+
+ BPY_ADDCONST(dict, GL_DONT_CARE);
+ BPY_ADDCONST(dict, GL_FASTEST);
+ BPY_ADDCONST(dict, GL_NICEST);
+
+ BPY_ADDCONST(dict, GL_AMBIENT);
+ BPY_ADDCONST(dict, GL_DIFFUSE);
+ BPY_ADDCONST(dict, GL_SPECULAR);
+ BPY_ADDCONST(dict, GL_POSITION);
+ BPY_ADDCONST(dict, GL_SPOT_DIRECTION);
+ BPY_ADDCONST(dict, GL_SPOT_EXPONENT);
+ BPY_ADDCONST(dict, GL_SPOT_CUTOFF);
+ BPY_ADDCONST(dict, GL_CONSTANT_ATTENUATION);
+ BPY_ADDCONST(dict, GL_LINEAR_ATTENUATION);
+ BPY_ADDCONST(dict, GL_QUADRATIC_ATTENUATION);
+
+ BPY_ADDCONST(dict, GL_COMPILE);
+ BPY_ADDCONST(dict, GL_COMPILE_AND_EXECUTE);
+
+ BPY_ADDCONST(dict, GL_BYTE);
+ BPY_ADDCONST(dict, GL_UNSIGNED_BYTE);
+ BPY_ADDCONST(dict, GL_SHORT);
+ BPY_ADDCONST(dict, GL_UNSIGNED_SHORT);
+ BPY_ADDCONST(dict, GL_INT);
+ BPY_ADDCONST(dict, GL_UNSIGNED_INT);
+ BPY_ADDCONST(dict, GL_FLOAT);
+ BPY_ADDCONST(dict, GL_2_BYTES);
+ BPY_ADDCONST(dict, GL_3_BYTES);
+ BPY_ADDCONST(dict, GL_4_BYTES);
+
+ BPY_ADDCONST(dict, GL_CLEAR);
+ BPY_ADDCONST(dict, GL_AND);
+ BPY_ADDCONST(dict, GL_AND_REVERSE);
+ BPY_ADDCONST(dict, GL_COPY);
+ BPY_ADDCONST(dict, GL_AND_INVERTED);
+ BPY_ADDCONST(dict, GL_NOOP);
+ BPY_ADDCONST(dict, GL_XOR);
+ BPY_ADDCONST(dict, GL_OR);
+ BPY_ADDCONST(dict, GL_NOR);
+ BPY_ADDCONST(dict, GL_EQUIV);
+ BPY_ADDCONST(dict, GL_INVERT);
+ BPY_ADDCONST(dict, GL_OR_REVERSE);
+ BPY_ADDCONST(dict, GL_COPY_INVERTED);
+ BPY_ADDCONST(dict, GL_OR_INVERTED);
+ BPY_ADDCONST(dict, GL_NAND);
+ BPY_ADDCONST(dict, GL_SET);
+
+ BPY_ADDCONST(dict, GL_EMISSION);
+ BPY_ADDCONST(dict, GL_SHININESS);
+ BPY_ADDCONST(dict, GL_AMBIENT_AND_DIFFUSE);
+ BPY_ADDCONST(dict, GL_COLOR_INDEXES);
+
+ BPY_ADDCONST(dict, GL_MODELVIEW);
+ BPY_ADDCONST(dict, GL_PROJECTION);
+ BPY_ADDCONST(dict, GL_TEXTURE);
+
+ BPY_ADDCONST(dict, GL_COLOR);
+ BPY_ADDCONST(dict, GL_DEPTH);
+ BPY_ADDCONST(dict, GL_STENCIL);
+
+ BPY_ADDCONST(dict, GL_COLOR_INDEX);
+ BPY_ADDCONST(dict, GL_STENCIL_INDEX);
+ BPY_ADDCONST(dict, GL_DEPTH_COMPONENT);
+ BPY_ADDCONST(dict, GL_RED);
+ BPY_ADDCONST(dict, GL_GREEN);
+ BPY_ADDCONST(dict, GL_BLUE);
+ BPY_ADDCONST(dict, GL_ALPHA);
+ BPY_ADDCONST(dict, GL_RGB);
+ BPY_ADDCONST(dict, GL_RGBA);
+ BPY_ADDCONST(dict, GL_LUMINANCE);
+ BPY_ADDCONST(dict, GL_LUMINANCE_ALPHA);
+
+ BPY_ADDCONST(dict, GL_BITMAP);
+
+ BPY_ADDCONST(dict, GL_POINT);
+ BPY_ADDCONST(dict, GL_LINE);
+ BPY_ADDCONST(dict, GL_FILL);
+
+ BPY_ADDCONST(dict, GL_RENDER);
+ BPY_ADDCONST(dict, GL_FEEDBACK);
+ BPY_ADDCONST(dict, GL_SELECT);
+
+ BPY_ADDCONST(dict, GL_FLAT);
+ BPY_ADDCONST(dict, GL_SMOOTH);
+
+ BPY_ADDCONST(dict, GL_KEEP);
+ BPY_ADDCONST(dict, GL_REPLACE);
+ BPY_ADDCONST(dict, GL_INCR);
+ BPY_ADDCONST(dict, GL_DECR);
+
+ BPY_ADDCONST(dict, GL_VENDOR);
+ BPY_ADDCONST(dict, GL_RENDERER);
+ BPY_ADDCONST(dict, GL_VERSION);
+ BPY_ADDCONST(dict, GL_EXTENSIONS);
+
+ BPY_ADDCONST(dict, GL_S);
+ BPY_ADDCONST(dict, GL_T);
+ BPY_ADDCONST(dict, GL_R);
+ BPY_ADDCONST(dict, GL_Q);
+
+ BPY_ADDCONST(dict, GL_MODULATE);
+ BPY_ADDCONST(dict, GL_DECAL);
+
+ BPY_ADDCONST(dict, GL_TEXTURE_ENV_MODE);
+ BPY_ADDCONST(dict, GL_TEXTURE_ENV_COLOR);
+
+ BPY_ADDCONST(dict, GL_TEXTURE_ENV);
+
+ BPY_ADDCONST(dict, GL_EYE_LINEAR);
+ BPY_ADDCONST(dict, GL_OBJECT_LINEAR);
+ BPY_ADDCONST(dict, GL_SPHERE_MAP);
+
+ BPY_ADDCONST(dict, GL_TEXTURE_GEN_MODE);
+ BPY_ADDCONST(dict, GL_OBJECT_PLANE);
+ BPY_ADDCONST(dict, GL_EYE_PLANE);
+
+ BPY_ADDCONST(dict, GL_NEAREST);
+ BPY_ADDCONST(dict, GL_LINEAR);
+
+ BPY_ADDCONST(dict, GL_NEAREST_MIPMAP_NEAREST);
+ BPY_ADDCONST(dict, GL_LINEAR_MIPMAP_NEAREST);
+ BPY_ADDCONST(dict, GL_NEAREST_MIPMAP_LINEAR);
+ BPY_ADDCONST(dict, GL_LINEAR_MIPMAP_LINEAR);
+
+ BPY_ADDCONST(dict, GL_TEXTURE_MAG_FILTER);
+ BPY_ADDCONST(dict, GL_TEXTURE_MIN_FILTER);
+ BPY_ADDCONST(dict, GL_TEXTURE_WRAP_S);
+ BPY_ADDCONST(dict, GL_TEXTURE_WRAP_T);
+
+ BPY_ADDCONST(dict, GL_CLAMP);
+ BPY_ADDCONST(dict, GL_REPEAT);
+
+ BPY_ADDCONST(dict, GL_CLIP_PLANE0);
+ BPY_ADDCONST(dict, GL_CLIP_PLANE1);
+ BPY_ADDCONST(dict, GL_CLIP_PLANE2);
+ BPY_ADDCONST(dict, GL_CLIP_PLANE3);
+ BPY_ADDCONST(dict, GL_CLIP_PLANE4);
+ BPY_ADDCONST(dict, GL_CLIP_PLANE5);
+
+ BPY_ADDCONST(dict, GL_LIGHT0);
+ BPY_ADDCONST(dict, GL_LIGHT1);
+ BPY_ADDCONST(dict, GL_LIGHT2);
+ BPY_ADDCONST(dict, GL_LIGHT3);
+ BPY_ADDCONST(dict, GL_LIGHT4);
+ BPY_ADDCONST(dict, GL_LIGHT5);
+ BPY_ADDCONST(dict, GL_LIGHT6);
+ BPY_ADDCONST(dict, GL_LIGHT7);
+
+ BPY_ADDCONST(dict, GL_POLYGON_OFFSET_UNITS);
+ BPY_ADDCONST(dict, GL_POLYGON_OFFSET_POINT);
+ BPY_ADDCONST(dict, GL_POLYGON_OFFSET_LINE);
+ BPY_ADDCONST(dict, GL_POLYGON_OFFSET_FILL);
+ BPY_ADDCONST(dict, GL_POLYGON_OFFSET_FACTOR);
+
+ BPY_ADDCONST(dict, GL_TEXTURE_PRIORITY);
+ BPY_ADDCONST(dict, GL_TEXTURE_RESIDENT);
+ BPY_ADDCONST(dict, GL_TEXTURE_BINDING_1D);
+ BPY_ADDCONST(dict, GL_TEXTURE_BINDING_2D);
+
+ return mod;
+}
+
+void initDraw(void)
+{
+ init_py_draw();
+ init_py_bgl();
+}
diff --git a/source/blender/bpython/intern/opy_matrix.c b/source/blender/bpython/intern/opy_matrix.c
new file mode 100644
index 00000000000..cd93bd5f311
--- /dev/null
+++ b/source/blender/bpython/intern/opy_matrix.c
@@ -0,0 +1,173 @@
+/* python.c MIXED MODEL
+ *
+ * june 99
+ * $Id$
+ *
+ * this code might die...
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "Python.h"
+#include "BPY_tools.h"
+#include "BPY_macros.h"
+
+#include "BLI_arithb.h"
+#include "opy_vector.h"
+
+PyObject *BPY_tuple_repr(PyObject *self, int size);
+
+/* PROTOS */
+// PyObject *newVectorObject(float *vec, int size);
+
+/*****************************/
+/* Matrix Python Object */
+/*****************************/
+
+
+#define GETROWVECTOR(mat, i) ( (float *) mat[i])
+
+static void Matrix_dealloc(MatrixObject *self) {
+ Py_DECREF(self->rows[0]);
+ Py_DECREF(self->rows[1]);
+ Py_DECREF(self->rows[2]);
+ Py_DECREF(self->rows[3]);
+
+ PyMem_DEL(self);
+}
+
+#undef MethodDef
+#define MethodDef(func) _MethodDef(func, Matrix)
+
+static char Matrix_inverse_doc[] = "() - returns inverse of matrix";
+
+static PyObject *Matrix_inverse(PyObject *self, PyObject *args)
+{
+ float inverse[4][4];
+ MatrixObject *mat = (MatrixObject *) self;
+ Mat4Invert(inverse, mat->mat);
+ return newMatrixObject(inverse);
+}
+
+struct PyMethodDef Matrix_methods[] = {
+ MethodDef(inverse),
+ {NULL, NULL}
+};
+
+static PyObject *Matrix_getattr(MatrixObject *self, char *name)
+{
+ PyObject *list;
+ float val[3];
+
+ if (strcmp(name, "rot")==0) {
+ float mat3[3][3];
+
+ Mat3CpyMat4(mat3, self->mat);
+ Mat3ToEul(mat3, val);
+
+ } else if (strcmp(name, "size")==0) {
+ Mat4ToSize(self->mat, val);
+ /* Oh man, this is BAD. */
+ } else if (strcmp(name, "loc")==0) {
+ VECCOPY(val, (float *) (self->mat)[3]);
+
+ } else {
+ PyErr_SetString(PyExc_AttributeError, name);
+ return NULL;
+ }
+
+ list= PyList_New(3);
+ PyList_SetItem(list, 0, PyFloat_FromDouble(val[0]));
+ PyList_SetItem(list, 1, PyFloat_FromDouble(val[1]));
+ PyList_SetItem(list, 2, PyFloat_FromDouble(val[2]));
+
+ return list;
+}
+
+static int Matrix_setattr(MatrixObject *self, char *name, PyObject *v) {
+ return -1;
+}
+
+static PyObject *Matrix_repr (MatrixObject *self) {
+ return BPY_tuple_repr((PyObject *) self, 4);
+}
+
+static PyObject *Matrix_item(MatrixObject *self, int i)
+{
+ if (i < 0 || i >= 4) {
+ PyErr_SetString(PyExc_IndexError, "array index out of range");
+ return NULL;
+ }
+ return BPY_incr_ret(self->rows[i]);
+}
+
+static PySequenceMethods Matrix_SeqMethods = {
+ (inquiry) 0, /*sq_length*/
+ (binaryfunc) 0, /*sq_concat*/
+ (intargfunc) 0, /*sq_repeat*/
+ (intargfunc) Matrix_item, /*sq_item*/
+ (intintargfunc) 0, /*sq_slice*/
+ (intobjargproc) 0, /*sq_ass_item*/
+ (intintobjargproc) 0, /*sq_ass_slice*/
+};
+
+PyTypeObject Matrix_Type = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "Matrix", /*tp_name*/
+ sizeof(MatrixObject), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ (destructor) Matrix_dealloc, /*tp_dealloc*/
+ (printfunc) 0, /*tp_print*/
+ (getattrfunc) Matrix_getattr, /*tp_getattr*/
+ (setattrfunc) Matrix_setattr, /*tp_setattr*/
+ 0, /*tp_compare*/
+ (reprfunc) Matrix_repr, /*tp_repr*/
+ 0, /*tp_as_number*/
+ &Matrix_SeqMethods, /*tp_as_sequence*/
+};
+
+PyObject *newMatrixObject(Matrix4Ptr mat) {
+ MatrixObject *self;
+
+ self= PyObject_NEW(MatrixObject, &Matrix_Type);
+ self->mat= mat;
+
+ BPY_TRY(self->rows[0]= newVectorObject(GETROWVECTOR(self->mat, 0), 4));
+ BPY_TRY(self->rows[1]= newVectorObject(GETROWVECTOR(self->mat, 1), 4));
+ BPY_TRY(self->rows[2]= newVectorObject(GETROWVECTOR(self->mat, 2), 4));
+ BPY_TRY(self->rows[3]= newVectorObject(GETROWVECTOR(self->mat, 3), 4));
+
+ return (PyObject*) self;
+}
+
+void init_py_matrix(void) {
+ Matrix_Type.ob_type = &PyType_Type;
+}
diff --git a/source/blender/bpython/intern/opy_nmesh.c b/source/blender/bpython/intern/opy_nmesh.c
new file mode 100644
index 00000000000..48de7726dd8
--- /dev/null
+++ b/source/blender/bpython/intern/opy_nmesh.c
@@ -0,0 +1,1716 @@
+/* python.c MIXED MODEL
+ *
+ * june 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 *****
+ */
+
+#include "Python.h"
+#include "BPY_macros.h"
+#include "b_interface.h"
+#include "BPY_tools.h"
+#include "BPY_main.h"
+
+#include "opy_datablock.h"
+#include "opy_nmesh.h"
+
+#include "MEM_guardedalloc.h"
+#include "BIF_editmesh.h" /* vertexnormals_mesh() */
+#include "BDR_editface.h" /* make_tfaces */
+
+#include "BKE_mesh.h"
+#include "BKE_main.h"
+#include "BKE_global.h"
+#include "BKE_library.h"
+#include "BKE_displist.h"
+#include "BKE_screen.h"
+#include "BKE_object.h"
+#include "BPY_objtypes.h"
+#include "BLI_blenlib.h"
+#include "BIF_space.h"
+
+#include "opy_vector.h"
+
+#include "b_interface.h"
+/* PROTOS */
+
+static int convert_NMeshToMesh(Mesh *mesh, NMesh *nmesh);
+static int unlink_existingMeshdata(Mesh *mesh);
+void initNMesh(void);
+PyObject *init_py_nmesh(void);
+int BPY_check_sequence_consistency(PyObject *seq, PyTypeObject *against);
+
+/* TYPE OBJECTS */
+
+PyTypeObject NMesh_Type;
+PyTypeObject NMFace_Type;
+PyTypeObject NMVert_Type;
+PyTypeObject NMCol_Type;
+
+/* DEFINES */
+
+
+#define COL_R (b)
+#define COL_G (g)
+#define COL_B (r)
+#define COL_A (a)
+
+#define COLOR_CONVERT(col,comp) (col##->COL_##)
+
+/* GLOBALS */
+
+static PyObject *g_nmeshmodule = NULL;
+
+/*****************************/
+/* Mesh Color Object */
+/*****************************/
+
+static void NMCol_dealloc(PyObject *self) {
+ PyMem_DEL(self);
+}
+
+static NMCol *newcol (char r, char g, char b, char a) {
+ NMCol *mc= (NMCol *) PyObject_NEW(NMCol, &NMCol_Type);
+
+ mc->r= r;
+ mc->g= g;
+ mc->b= b;
+ mc->a= a;
+
+ return mc;
+}
+
+static char NMeshmodule_Col_doc[]=
+"([r, g, b, a]) - Get a new mesh color\n\
+\n\
+[r=255, g=255, b=255, a=255] Specify the color components";
+
+static PyObject *NMeshmodule_Col(PyObject *self, PyObject *args) {
+ int r=255, g=255, b=255, a=255;
+
+/*
+if(PyArg_ParseTuple(args, "fff|f", &fr, &fg, &fb, &fa))
+ return (PyObject *) newcol(255.0 * fr, 255.0 * fg, 255.0 * fb, 255.0 * fa);
+ */
+ if(PyArg_ParseTuple(args, "|iiii", &r, &g, &b, &a))
+ return (PyObject *) newcol(r, g, b, a);
+ return NULL;
+}
+
+static PyObject *NMCol_getattr(PyObject *self, char *name) {
+ NMCol *mc= (NMCol *) self;
+
+ if (strcmp(name, "r")==0) return Py_BuildValue("i", mc->r);
+ else if (strcmp(name, "g")==0) return Py_BuildValue("i", mc->g);
+ else if (strcmp(name, "b")==0) return Py_BuildValue("i", mc->b);
+ else if (strcmp(name, "a")==0) return Py_BuildValue("i", mc->a);
+
+ PyErr_SetString(PyExc_AttributeError, name);
+ return NULL;
+}
+
+static int NMCol_setattr(PyObject *self, char *name, PyObject *v) {
+ NMCol *mc= (NMCol *) self;
+ int ival;
+
+ if(!PyArg_Parse(v, "i", &ival)) return -1;
+
+ CLAMP(ival, 0, 255);
+
+ if (strcmp(name, "r")==0) mc->r= ival;
+ else if (strcmp(name, "g")==0) mc->g= ival;
+ else if (strcmp(name, "b")==0) mc->b= ival;
+ else if (strcmp(name, "a")==0) mc->a= ival;
+ else return -1;
+
+ return 0;
+}
+
+PyObject *NMCol_repr(NMCol *self)
+{
+ static char s[256];
+ sprintf (s, "[NMCol - <%d, %d, %d, %d>]", self->r, self->g, self->b, self->a);
+ return Py_BuildValue("s", s);
+}
+
+PyTypeObject NMCol_Type = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "NMCol", /*tp_name*/
+ sizeof(NMCol), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ (destructor) NMCol_dealloc, /*tp_dealloc*/
+ (printfunc) 0, /*tp_print*/
+ (getattrfunc) NMCol_getattr, /*tp_getattr*/
+ (setattrfunc) NMCol_setattr, /*tp_setattr*/
+ 0, /*tp_compare*/
+ (reprfunc) NMCol_repr, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash*/
+};
+
+
+/*****************************/
+/* NMesh Python Object */
+/*****************************/
+
+
+static void NMFace_dealloc(PyObject *self) {
+ NMFace *mf= (NMFace *) self;
+
+ Py_DECREF(mf->v);
+ Py_DECREF(mf->uv);
+ Py_DECREF(mf->col);
+
+ PyMem_DEL(self);
+
+}
+
+static NMFace *newNMFace(PyObject *vertexlist) {
+ NMFace *mf= PyObject_NEW(NMFace, &NMFace_Type);
+
+ mf->v= vertexlist;
+ mf->uv= PyList_New(0);
+ mf->tpage= NULL;
+ mf->mode = TF_DYNAMIC + TF_TEX;
+ mf->flag= TF_SELECT;
+ mf->transp= TF_SOLID;
+ mf->col= PyList_New(0);
+
+ mf->smooth= 0;
+ mf->mat_nr= 0;
+
+ return mf;
+}
+
+static char NMeshmodule_Face_doc[]=
+"(vertexlist = None) - Get a new face, and pass optional vertex list";
+static PyObject *NMeshmodule_Face(PyObject *self, PyObject *args) {
+ PyObject *vertlist = NULL;
+ BPY_TRY(PyArg_ParseTuple(args, "|O!", &PyList_Type, &vertlist));
+
+ if (!vertlist) {
+ vertlist = PyList_New(0);
+ }
+ return (PyObject *) newNMFace(vertlist);
+}
+
+/* XXX this code will be used later...
+static PyObject *Method_getmode(PyObject *self, PyObject *args) {
+ PyObject *dict, *list;
+ PyObject *constants, *values, *c;
+ int flag;
+ int i, n;
+
+ list = PyList_New(0);
+ dict = PyObject_GetAttrString(g_nmeshmodule, "Const");
+
+ if (!dict) return 0;
+
+ constants = PyDict_Keys(dict);
+ values = PyDict_Values(dict);
+
+ n = PySequence_Length(constants);
+ for (i = 0; i < n; i++)
+ {
+ flag = PyInt_AsLong(PySequence_GetItem(values, i));
+ if (flag & ((NMFace*) self)->mode)
+ {
+ c = PySequence_GetItem(constants, i);
+ PyList_Append(list, c)
+ }
+ }
+ return list;
+}
+*/
+
+static char NMFace_append_doc[]= "(vert) - appends Vertex 'vert' to face vertex list";
+
+static PyObject *NMFace_append(PyObject *self, PyObject *args)
+{
+ PyObject *vert;
+ NMFace *f= (NMFace *) self;
+
+ BPY_TRY(PyArg_ParseTuple(args, "O!", &NMVert_Type, &vert));
+ PyList_Append(f->v, vert);
+ RETURN_INC(Py_None);
+}
+
+
+#undef MethodDef
+#define MethodDef(func) {#func, NMFace_##func, METH_VARARGS, NMFace_##func##_doc}
+
+static struct PyMethodDef NMFace_methods[] = {
+ MethodDef(append),
+ {NULL, NULL}
+};
+
+static PyObject *NMFace_getattr(PyObject *self, char *name) {
+ NMFace *mf= (NMFace *) self;
+
+ if(strcmp(name, "v")==0)
+ return Py_BuildValue("O", mf->v);
+ else if (strcmp(name, "col")==0)
+ return Py_BuildValue("O", mf->col);
+ else if (strcmp(name, "mat")==0) // emulation XXX
+ return Py_BuildValue("i", mf->mat_nr);
+ else if (strcmp(name, "materialIndex")==0)
+ return Py_BuildValue("i", mf->mat_nr);
+ else if (strcmp(name, "smooth")==0)
+ return Py_BuildValue("i", mf->smooth);
+ else if (strcmp(name, "image")==0) {
+ if (mf->tpage)
+ return Py_BuildValue("O", (PyObject *) mf->tpage);
+ else
+ RETURN_INC(Py_None);
+ }
+ else if (strcmp(name, "mode")==0)
+ return Py_BuildValue("i", mf->mode);
+ else if (strcmp(name, "flag")==0)
+ return Py_BuildValue("i", mf->flag);
+ else if (strcmp(name, "transp")==0)
+ return Py_BuildValue("i", mf->transp);
+ else if (strcmp(name, "uv")==0)
+ return Py_BuildValue("O", mf->uv);
+
+ return Py_FindMethod(NMFace_methods, (PyObject*)self, name);
+/*
+ PyErr_SetString(PyExc_AttributeError, name);
+ return NULL;
+*/
+}
+
+static int NMFace_setattr(PyObject *self, char *name, PyObject *v) {
+ NMFace *mf= (NMFace *) self;
+ int ival;
+ PyObject *tmp;
+
+ if (STREQ(name, "v")) {
+ if(PySequence_Check(v)) {
+ Py_DECREF(mf->v);
+ mf->v= BPY_incr_ret(v);
+
+ return 0;
+ }
+ } else if (STREQ(name, "col")) {
+ if(PySequence_Check(v)) {
+ Py_DECREF(mf->col);
+ mf->col= BPY_incr_ret(v);
+
+ return 0;
+ }
+ } else if (STREQ(name, "mat") || STREQ(name, "materialIndex")) {
+ PyArg_Parse(v, "i", &ival);
+
+ mf->mat_nr= ival;
+
+ return 0;
+ } else if (STREQ(name, "smooth")) {
+ PyArg_Parse(v, "i", &ival);
+
+ mf->smooth= ival?1:0;
+
+ return 0;
+ } else if (STREQ(name, "uv")) {
+ if(PySequence_Check(v)) {
+ Py_DECREF(mf->uv);
+ mf->uv= BPY_incr_ret(v);
+ return 0;
+ }
+ } else if (STREQ(name, "flag")) {
+ PyArg_Parse(v, "i", &ival);
+ mf->flag = ival;
+ return 0;
+ } else if (STREQ(name, "mode")) {
+ PyArg_Parse(v, "i", &ival);
+ mf->mode = ival;
+ return 0;
+ } else if (STREQ(name, "transp")) {
+ PyArg_Parse(v, "i", &ival);
+ mf->transp = ival;
+ return 0;
+ } else if (STREQ(name, "image")) {
+ PyArg_Parse(v, "O", &tmp);
+ if (tmp == Py_None) {
+ mf->tpage = 0;
+ return 0;
+ }
+ if (!DataBlock_isType((DataBlock *) tmp, ID_IM))
+ {
+ PyErr_SetString(PyExc_TypeError, "expects Image Datablock type");
+ return -1;
+ }
+ mf->tpage = (DataBlock *) tmp;
+ return 0;
+ }
+
+ PyErr_SetString(PyExc_AttributeError, name);
+ return -1;
+}
+
+static PyObject *NMFace_repr (PyObject *self)
+{
+ return PyString_FromString("[NMFace]");
+}
+
+static int NMFace_len(NMFace *self)
+{
+ return PySequence_Length(self->v);
+}
+
+static PyObject *NMFace_item(NMFace *self, int i)
+{
+ return PySequence_GetItem(self->v, i); // new ref
+}
+
+static PyObject *NMFace_slice(NMFace *self, int begin, int end)
+{
+ return PyList_GetSlice(self->v, begin, end); // new ref
+}
+
+static PySequenceMethods NMFace_SeqMethods = {
+ (inquiry) NMFace_len, /* sq_length */
+ (binaryfunc) 0, /* sq_concat */
+ (intargfunc) 0, /* sq_repeat */
+ (intargfunc) NMFace_item, /* sq_item */
+ (intintargfunc) NMFace_slice, /* sq_slice */
+ (intobjargproc) 0, /* sq_ass_item */
+ (intintobjargproc) 0, /* sq_ass_slice */
+};
+
+
+PyTypeObject NMFace_Type = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "NMFace", /*tp_name*/
+ sizeof(NMFace), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ (destructor) NMFace_dealloc, /*tp_dealloc*/
+ (printfunc) 0, /*tp_print*/
+ (getattrfunc) NMFace_getattr, /*tp_getattr*/
+ (setattrfunc) NMFace_setattr,/*tp_setattr*/
+ 0, /*tp_compare*/
+ (reprfunc) NMFace_repr, /*tp_repr*/
+ 0, /*tp_as_number*/
+ &NMFace_SeqMethods, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash*/
+};
+
+
+static NMVert *newvert(float *co) {
+ NMVert *mv= PyObject_NEW(NMVert, &NMVert_Type);
+
+ VECCOPY(mv->co, co);
+ mv->no[0]= mv->no[1]= mv->no[2]= 0.0;
+ mv->uvco[0]= mv->uvco[1]= mv->uvco[2]= 0.0;
+
+ return mv;
+}
+
+static char NMeshmodule_Vert_doc[]=
+"([x, y, z]) - Get a new vertice\n\
+\n\
+[x, y, z] Specify new coordinates";
+
+static PyObject *NMeshmodule_Vert(PyObject *self, PyObject *args) {
+ float co[3]= {0.0, 0.0, 0.0};
+
+ BPY_TRY(PyArg_ParseTuple(args, "|fff", &co[0], &co[1], &co[2]));
+
+ return (PyObject *) newvert(co);
+}
+
+static void NMVert_dealloc(PyObject *self) {
+ PyMem_DEL(self);
+}
+
+static PyObject *NMVert_getattr(PyObject *self, char *name) {
+ NMVert *mv= (NMVert *) self;
+
+ if (STREQ(name, "co") || STREQ(name, "loc")) return newVectorObject(mv->co, 3);
+ else if (STREQ(name, "no")) return newVectorObject(mv->no, 3);
+ else if (STREQ(name, "uvco")) return newVectorObject(mv->uvco, 3);
+ else if (STREQ(name, "index")) return PyInt_FromLong(mv->index);
+
+ PyErr_SetString(PyExc_AttributeError, name);
+ return NULL;
+}
+
+static int NMVert_setattr(PyObject *self, char *name, PyObject *v) {
+ NMVert *mv= (NMVert *) self;
+ int i;
+
+ if (STREQ(name,"index")) {
+ PyArg_Parse(v, "i", &i);
+ mv->index= i;
+ return 0;
+ } else if (STREQ(name, "uvco")) {
+ if (!PyArg_ParseTuple(v, "ff|f", &(mv->uvco[0]), &(mv->uvco[1]), &(mv->uvco[2]))) {
+ PyErr_SetString(PyExc_AttributeError, "Vector tuple or triple expected");
+ return -1;
+ }
+ return 0;
+/*
+PyErr_SetString(PyExc_AttributeError, "Use slice assignment: uvco[i]");
+ return -1;
+ */
+ }
+
+ PyErr_SetString(PyExc_AttributeError, name);
+ return -1;
+}
+
+
+static int NMVert_len(NMVert *self) {
+ return 3;
+}
+
+static PyObject *NMVert_item(NMVert *self, int i)
+{
+ if (i < 0 || i >= 3) {
+ PyErr_SetString(PyExc_IndexError, "array index out of range");
+ return NULL;
+ }
+ return Py_BuildValue("f", self->co[i]);
+}
+
+static PyObject *NMVert_slice(NMVert *self, int begin, int end)
+{
+ PyObject *list;
+ int count;
+
+ if (begin<0) begin= 0;
+ if (end>3) end= 3;
+ if (begin>end) begin= end;
+
+ list= PyList_New(end-begin);
+
+ for (count= begin; count<end; count++)
+ PyList_SetItem(list, count-begin, PyFloat_FromDouble(self->co[count]));
+
+ return list;
+}
+
+static int NMVert_ass_item(NMVert *self, int i, PyObject *ob)
+{
+ if (i < 0 || i >= 3) {
+ PyErr_SetString(PyExc_IndexError, "array assignment index out of range");
+ return -1;
+ }
+
+ if (!PyNumber_Check(ob)) {
+ PyErr_SetString(PyExc_IndexError, "NMVert member must be a number");
+ return -1;
+ }
+
+ self->co[i]= PyFloat_AsDouble(ob);
+/* if(!PyArg_Parse(ob, "f", &)) return -1; */
+
+ return 0;
+}
+
+/** I guess this hurts...
+ * sorry, couldn't resist (strubi) */
+
+static int NMVert_ass_slice(NMVert *self, int begin, int end, PyObject *seq)
+{
+ int count;
+
+ if (begin<0) begin= 0;
+ if (end>3) end= 3;
+ if (begin>end) begin= end;
+
+ if (!PySequence_Check(seq)) {
+ PyErr_SetString(PyExc_TypeError, "illegal argument type for built-in operation");
+ return -1;
+ }
+
+ if (PySequence_Length(seq)!=(end-begin)) {
+ PyErr_SetString(PyExc_TypeError, "size mismatch in slice assignment");
+ return -1;
+ }
+
+ for (count= begin; count<end; count++) {
+ PyObject *ob= PySequence_GetItem(seq, count);
+ if (!PyArg_Parse(ob, "f", &self->co[count])) {
+ Py_DECREF(ob);
+ return -1;
+ }
+ Py_DECREF(ob);
+ }
+
+ return 0;
+}
+
+static PySequenceMethods NMVert_SeqMethods = {
+ (inquiry) NMVert_len, /* sq_length */
+ (binaryfunc) 0, /* sq_concat */
+ (intargfunc) 0, /* sq_repeat */
+ (intargfunc) NMVert_item, /* sq_item */
+ (intintargfunc) NMVert_slice, /* sq_slice */
+ (intobjargproc) NMVert_ass_item, /* sq_ass_item */
+ (intintobjargproc) NMVert_ass_slice, /* sq_ass_slice */
+};
+
+PyTypeObject NMVert_Type = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "NMVert", /*tp_name*/
+ sizeof(NMVert), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ (destructor) NMVert_dealloc, /*tp_dealloc*/
+ (printfunc) 0, /*tp_print*/
+ (getattrfunc) NMVert_getattr, /*tp_getattr*/
+ (setattrfunc) NMVert_setattr, /*tp_setattr*/
+ 0, /*tp_compare*/
+ (reprfunc) 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ &NMVert_SeqMethods, /*tp_as_sequence*/
+};
+
+
+static void NMesh_dealloc(PyObject *self) {
+ NMesh *me= (NMesh *) self;
+
+ Py_DECREF(me->name);
+ Py_DECREF(me->verts);
+ Py_DECREF(me->faces);
+
+ PyMem_DEL(self);
+}
+
+
+static char NMesh_getSelectedFaces_doc[] = "(flag = None) - returns list of selected Faces\n\
+If flag = 1, return indices instead";
+static PyObject *NMesh_getSelectedFaces(PyObject *self, PyObject *args)
+{
+ NMesh *nm= (NMesh *) self;
+ Mesh *me = nm->mesh;
+ int flag = 0;
+
+ TFace *tf;
+ int i;
+ PyObject *l= PyList_New(0);
+
+ if (me == NULL) return NULL;
+
+ tf = me->tface;
+ if (tf == 0) {
+ return l;
+ }
+
+ if (!PyArg_ParseTuple(args, "|i", &flag))
+ return NULL;
+ if (flag) {
+ for (i =0 ; i < me->totface; i++) {
+ if (tf[i].flag & TF_SELECT ) {
+ PyList_Append(l, PyInt_FromLong(i));
+ }
+ }
+ } else {
+ for (i =0 ; i < me->totface; i++) {
+ if (tf[i].flag & TF_SELECT ) {
+ PyList_Append(l, PyList_GetItem(nm->faces, i));
+ }
+ }
+ }
+ return l;
+}
+
+
+static char NMesh_getActiveFace_doc[] = "returns the index of the active face ";
+static PyObject *NMesh_getActiveFace(PyObject *self, PyObject *args)
+{
+ if (((NMesh *)self)->sel_face < 0)
+ RETURN_INC(Py_None);
+ return Py_BuildValue("i", ((NMesh *)self)->sel_face);
+}
+
+static char NMesh_hasVertexUV_doc[] = "(flag = None) - returns 1 if Mesh has per vertex UVs ('Sticky')\n\
+The optional argument sets the Sticky flag";
+
+static PyObject *NMesh_hasVertexUV(PyObject *self, PyObject *args)
+{
+ NMesh *me= (NMesh *) self;
+ int flag;
+
+ if (args) {
+ if (PyArg_ParseTuple(args, "i", &flag)) {
+ if(flag) me->flags |= NMESH_HASVERTUV;
+ else me->flags &= ~NMESH_HASVERTUV;
+ }
+ }
+ PyErr_Clear();
+ if (me->flags & NMESH_HASVERTUV)
+ return BPY_incr_ret(Py_True);
+ else
+ return BPY_incr_ret(Py_False);
+}
+
+static char NMesh_hasFaceUV_doc[] = "(flag = None) - returns 1 if Mesh has textured faces\n\
+The optional argument sets the textured faces flag";
+
+static PyObject *NMesh_hasFaceUV(PyObject *self, PyObject *args)
+{
+ NMesh *me= (NMesh *) self;
+ int flag = -1;
+
+ BPY_TRY(PyArg_ParseTuple(args, "|i", &flag));
+
+ switch (flag) {
+ case 0:
+ me->flags |= NMESH_HASFACEUV;
+ break;
+ case 1:
+ me->flags &= ~NMESH_HASFACEUV;
+ break;
+ default:
+ break;
+ }
+
+ if (me->flags & NMESH_HASFACEUV)
+ return BPY_incr_ret(Py_True);
+ else
+ return BPY_incr_ret(Py_False);
+}
+
+
+static char NMesh_hasVertexColours_doc[] = "(flag = None) - returns 1 if Mesh has vertex colours.\n\
+The optional argument sets the vertex colour flag";
+
+static PyObject *NMesh_hasVertexColours(PyObject *self, PyObject *args)
+{
+ NMesh *me= (NMesh *) self;
+ int flag = -1;
+
+ BPY_TRY(PyArg_ParseTuple(args, "|i", &flag));
+
+ switch (flag) {
+ case 0:
+ me->flags &= ~NMESH_HASMCOL;
+ break;
+ case 1:
+ me->flags |= NMESH_HASMCOL;
+ break;
+ default:
+ break;
+ }
+
+ if (me->flags & NMESH_HASMCOL)
+ return BPY_incr_ret(Py_True);
+ else
+ return BPY_incr_ret(Py_False);
+
+}
+
+
+static char NMesh_update_doc[] = "updates the Mesh";
+static PyObject *NMesh_update(PyObject *self, PyObject *args)
+{
+ NMesh *nmesh= (NMesh *) self;
+ Mesh *mesh = nmesh->mesh;
+
+ if (mesh) {
+ unlink_existingMeshdata(mesh);
+ convert_NMeshToMesh(mesh, nmesh);
+ mesh_update(mesh);
+ } else {
+ nmesh->mesh = Mesh_fromNMesh(nmesh);
+ }
+
+ nmesh_updateMaterials(nmesh);
+/** This is another ugly fix due to the weird material handling of blender.
+ * it makes sure that object material lists get updated (by their length)
+ * according to their data material lists, otherwise blender crashes.
+ * It just stupidly runs through all objects...BAD BAD BAD.
+ */
+ test_object_materials((ID *)mesh);
+
+ if (!during_script())
+ allqueue(REDRAWVIEW3D, 0);
+ return PyInt_FromLong(1);
+
+}
+
+
+Mesh *Mesh_fromNMesh(NMesh *nmesh)
+{
+ Mesh *mesh= NULL;
+ mesh = mesh_new(); // new empty mesh Bobject
+ if (!mesh) {
+ PyErr_SetString(PyExc_RuntimeError, "FATAL: could not create mesh object");
+ return NULL;
+ }
+
+ convert_NMeshToMesh(mesh, nmesh);
+ mesh_update(mesh);
+ return mesh;
+}
+
+#ifdef EXPERIMENTAL
+
+static char NMesh_asMesh_doc[] = "returns free Mesh datablock object from NMesh";
+static PyObject *NMesh_asMesh(PyObject *self, PyObject *args)
+{
+ char *name= NULL;
+ Mesh *mesh= NULL;
+ NMesh *nmesh;
+ int recalc_normals= 1;
+
+ nmesh = (NMesh *) self;
+
+ BPY_TRY(PyArg_ParseTuple(args, "|si", &name, &recalc_normals));
+
+ if (!PySequence_Check(nmesh->verts))
+ return BPY_err_ret_ob(PyExc_AttributeError,
+ "nmesh vertices are not a sequence");
+ if (!PySequence_Check(nmesh->faces))
+ return BPY_err_ret_ob(PyExc_AttributeError,
+ "nmesh faces are not a sequence");
+ if (!PySequence_Check(nmesh->materials))
+ return BPY_err_ret_ob(PyExc_AttributeError,
+ "nmesh materials are not a sequence");
+ if (!BPY_check_sequence_consistency(nmesh->verts, &NMVert_Type))
+ return BPY_err_ret_ob(PyExc_AttributeError,
+ "nmesh vertices must be NMVerts");
+ if (!BPY_check_sequence_consistency(nmesh->faces, &NMFace_Type))
+ return BPY_err_ret_ob(PyExc_AttributeError,
+ "nmesh faces must be NMFaces");
+
+ mesh = Mesh_fromNMesh(nmesh);
+ return DataBlock_fromData(mesh);
+}
+
+#endif
+static char NMesh_link_doc[] = "(object) - Links NMesh data with Object 'object'";
+
+PyObject * NMesh_link(PyObject *self, PyObject *args)
+{
+ return DataBlock_link(self, args);
+}
+
+#undef MethodDef
+#define MethodDef(func) {#func, NMesh_##func, METH_VARARGS, NMesh_##func##_doc}
+
+static struct PyMethodDef NMesh_methods[] = {
+ MethodDef(hasVertexColours),
+ MethodDef(hasFaceUV),
+ MethodDef(hasVertexUV),
+ MethodDef(getActiveFace),
+ MethodDef(getSelectedFaces),
+ MethodDef(update),
+#ifdef EXPERIMENTAL
+ MethodDef(asMesh),
+#endif
+ {NULL, NULL}
+};
+
+static PyObject *NMesh_getattr(PyObject *self, char *name) {
+ NMesh *me= (NMesh *) self;
+
+ if (STREQ(name, "name"))
+ return BPY_incr_ret(me->name);
+
+ else if (STREQ(name, "block_type"))
+ return PyString_FromString("NMesh");
+
+ else if (STREQ(name, "materials"))
+ return BPY_incr_ret(me->materials);
+
+ else if (STREQ(name, "verts"))
+ return BPY_incr_ret(me->verts);
+
+ else if (STREQ(name, "users")) {
+ if (me->mesh) {
+ return PyInt_FromLong(me->mesh->id.us);
+ } else { // it's a free mesh:
+ return Py_BuildValue("i", 0);
+ }
+ }
+
+ else if (STREQ(name, "faces"))
+ return BPY_incr_ret(me->faces);
+
+ return Py_FindMethod(NMesh_methods, (PyObject*)self, name);
+
+ PyErr_SetString(PyExc_AttributeError, name);
+ return NULL;
+}
+
+static int NMesh_setattr(PyObject *self, char *name, PyObject *v) {
+ NMesh *me= (NMesh *) self;
+
+ if (STREQ3(name, "verts", "faces", "materials")) {
+ if(PySequence_Check(v)) {
+ if(STREQ(name, "materials")) {
+ Py_DECREF(me->materials);
+ me->materials= BPY_incr_ret(v);
+ } else if (STREQ(name, "verts")) {
+ Py_DECREF(me->verts);
+ me->verts= BPY_incr_ret(v);
+ } else {
+ Py_DECREF(me->faces);
+ me->faces= BPY_incr_ret(v);
+ }
+ } else {
+ PyErr_SetString(PyExc_AttributeError, "expected a sequence");
+ return -1;
+ }
+ } else {
+ PyErr_SetString(PyExc_AttributeError, name);
+ return -1;
+ }
+
+ return 0;
+}
+
+PyTypeObject NMesh_Type = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "NMesh", /*tp_name*/
+ sizeof(NMesh), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ (destructor) NMesh_dealloc, /*tp_dealloc*/
+ (printfunc) 0, /*tp_print*/
+ (getattrfunc) NMesh_getattr, /*tp_getattr*/
+ (setattrfunc) NMesh_setattr, /*tp_setattr*/
+};
+
+static NMFace *nmface_from_data(NMesh *mesh, int vidxs[4], char mat_nr, char flag, TFace *tface, MCol *col)
+{
+ NMFace *newf= PyObject_NEW(NMFace, &NMFace_Type);
+ int i, len;
+
+ if(vidxs[3]) len= 4;
+ else if(vidxs[2]) len= 3;
+ else len= 2;
+
+ newf->v= PyList_New(len);
+
+ for (i=0; i<len; i++)
+ PyList_SetItem(newf->v, i, BPY_incr_ret(PyList_GetItem(mesh->verts, vidxs[i])));
+
+ if (tface) {
+ newf->uv = PyList_New(len); // per-face UV coordinates
+ for (i = 0; i < len; i++)
+ {
+ PyList_SetItem(newf->uv, i, Py_BuildValue("(ff)", tface->uv[i][0], tface->uv[i][1]));
+ }
+ if (tface->tpage)
+ newf->tpage = (DataBlock *) DataBlock_fromData((void *) tface->tpage); /* pointer to image per face */
+ else
+ newf->tpage = 0;
+ newf->mode = tface->mode; /* draw mode */
+ newf->flag = tface->flag; /* select flag */
+ newf->transp = tface->transp; /* transparency flag */
+ col = (MCol *) (tface->col);
+ } else {
+ newf->tpage = 0;
+ newf->uv = PyList_New(0);
+ }
+
+ newf->mat_nr= mat_nr;
+ newf->smooth= flag&ME_SMOOTH;
+
+ if (col) {
+ newf->col= PyList_New(4);
+ for(i=0; i<4; i++, col++)
+ PyList_SetItem(newf->col, i,
+ (PyObject *) newcol(col->b, col->g, col->r, col->a));
+ } else {
+ newf->col= PyList_New(0);
+ }
+ return newf;
+}
+
+static NMFace *nmface_from_shortdata(NMesh *mesh, MFace *face, TFace *tface, MCol *col)
+{
+ int vidxs[4];
+ vidxs[0]= face->v1;
+ vidxs[1]= face->v2;
+ vidxs[2]= face->v3;
+ vidxs[3]= face->v4;
+
+ return nmface_from_data(mesh, vidxs, face->mat_nr, face->flag, tface, col);
+}
+
+static NMFace *nmface_from_intdata(NMesh *mesh, MFaceInt *face, TFace *tface, MCol *col)
+{
+ int vidxs[4];
+ vidxs[0]= face->v1;
+ vidxs[1]= face->v2;
+ vidxs[2]= face->v3;
+ vidxs[3]= face->v4;
+
+ return nmface_from_data(mesh, vidxs, face->mat_nr, face->flag, tface, col);
+}
+
+static NMVert *nmvert_from_data(NMesh *me, MVert *vert, MSticky *st, float *co, int idx)
+{
+ NMVert *mv= PyObject_NEW(NMVert, &NMVert_Type);
+
+ VECCOPY (mv->co, co);
+
+ mv->no[0]= vert->no[0]/32767.0;
+ mv->no[1]= vert->no[1]/32767.0;
+ mv->no[2]= vert->no[2]/32767.0;
+
+ if (st) {
+ mv->uvco[0]= st->co[0];
+ mv->uvco[1]= st->co[1];
+ mv->uvco[2]= 0.0;
+
+ } else mv->uvco[0]= mv->uvco[1]= mv->uvco[2]= 0.0;
+
+ mv->index= idx;
+
+ return mv;
+}
+
+static int get_active_faceindex(Mesh *me)
+{
+ TFace *tf;
+ int i;
+
+ if (me == NULL) return -1;
+
+ tf = me->tface;
+ if (tf == 0) return -1;
+
+ for (i =0 ; i < me->totface; i++) {
+ if (tf[i].flag & TF_ACTIVE ) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+static PyObject *newNMesh_internal(Mesh *oldmesh, DispListMesh *dlm, float *extverts)
+{
+ NMesh *me= PyObject_NEW(NMesh, &NMesh_Type);
+ me->flags= 0;
+
+ if (!oldmesh) {
+ me->name= BPY_incr_ret(Py_None);
+ me->materials= PyList_New(0);
+ me->verts= PyList_New(0);
+ me->faces= PyList_New(0);
+ me->mesh= 0;
+ } else {
+ MVert *mverts;
+ MSticky *msticky;
+ MFaceInt *mfaceints;
+ MFace *mfaces;
+ TFace *tfaces;
+ MCol *mcols;
+ int i, totvert, totface;
+
+ if (dlm) {
+ me->name= BPY_incr_ret(Py_None);
+ me->mesh= 0;
+
+ msticky= NULL;
+ mfaces= NULL;
+ mverts= dlm->mvert;
+ mfaceints= dlm->mface;
+ tfaces= dlm->tface;
+ mcols= dlm->mcol;
+
+ totvert= dlm->totvert;
+ totface= dlm->totface;
+ } else {
+ me->name= PyString_FromString(oldmesh->id.name+2);
+ me->mesh= oldmesh;
+
+ mfaceints= NULL;
+ msticky= oldmesh->msticky;
+ mverts= oldmesh->mvert;
+ mfaces= oldmesh->mface;
+ tfaces= oldmesh->tface;
+ mcols= oldmesh->mcol;
+
+ totvert= oldmesh->totvert;
+ totface= oldmesh->totface;
+
+ me->sel_face= get_active_faceindex(oldmesh);
+ }
+
+ if (msticky) me->flags |= NMESH_HASVERTUV;
+ if (tfaces) me->flags |= NMESH_HASFACEUV;
+ if (mcols) me->flags |= NMESH_HASMCOL;
+
+ me->verts= PyList_New(totvert);
+ for (i=0; i<totvert; i++) {
+ MVert *oldmv= &mverts[i];
+ MSticky *oldst= msticky?&msticky[i]:NULL;
+ float *vco= extverts?&extverts[i*3]:oldmv->co;
+
+ PyList_SetItem(me->verts, i, (PyObject *) nmvert_from_data(me, oldmv, oldst, vco, i));
+ }
+
+ me->faces= PyList_New(totface);
+ for (i=0; i<totface; i++) {
+ TFace *oldtf= tfaces?&tfaces[i]:NULL;
+ MCol *oldmc= mcols?&mcols[i*4]:NULL;
+
+ if (mfaceints) {
+ MFaceInt *oldmf= &mfaceints[i];
+ PyList_SetItem(me->faces, i, (PyObject *) nmface_from_intdata(me, oldmf, oldtf, oldmc));
+ } else {
+ MFace *oldmf= &mfaces[i];
+ PyList_SetItem(me->faces, i, (PyObject *) nmface_from_shortdata(me, oldmf, oldtf, oldmc));
+ }
+ }
+ me->materials = PyList_fromMaterialList(oldmesh->mat, oldmesh->totcol);
+ }
+
+ return (PyObject *) me;
+}
+
+PyObject *newNMesh(Mesh *oldmesh)
+{
+ return newNMesh_internal(oldmesh, NULL, NULL);
+}
+
+static char NMeshmodule_New_doc[]=
+"() - returns a new, empty NMesh mesh object\n";
+
+static PyObject *NMeshmodule_New(PyObject *self, PyObject *args)
+{
+ return newNMesh(NULL);
+}
+
+static char NMeshmodule_GetRaw_doc[]=
+"([name]) - Get a raw mesh from Blender\n\
+\n\
+[name] Name of the mesh to be returned\n\
+\n\
+If name is not specified a new empty mesh is\n\
+returned, otherwise Blender returns an existing\n\
+mesh.";
+
+static PyObject *NMeshmodule_GetRaw(PyObject *self, PyObject *args)
+{
+ char *name=NULL;
+ Mesh *oldmesh=NULL;
+
+ BPY_TRY(PyArg_ParseTuple(args, "|s", &name));
+
+ if(name) {
+ oldmesh = (Mesh *) getFromList(getMeshList(), name);
+
+ if (!oldmesh) return BPY_incr_ret(Py_None);
+ }
+ return newNMesh(oldmesh);
+}
+
+static char NMeshmodule_GetRawFromObject_doc[]=
+"(name) - Get the raw mesh used by a Blender object\n"
+"\n"
+"(name) Name of the object to get the mesh from\n"
+"\n"
+"This returns the mesh as used by the object, which\n"
+"means it contains all deformations and modifications.";
+
+static PyObject *NMeshmodule_GetRawFromObject(PyObject *self, PyObject *args)
+{
+ char *name;
+ Object *ob;
+ PyObject *nmesh;
+
+ BPY_TRY(PyArg_ParseTuple(args, "s", &name));
+
+ ob= (Object*) getFromList(getObjectList(), name);
+ if (!ob)
+ return BPY_err_ret_ob(PyExc_AttributeError, name);
+ else if (ob->type!=OB_MESH)
+ return BPY_err_ret_ob(PyExc_AttributeError, "Object does not have Mesh data");
+ else {
+ Mesh *me= (Mesh*) ob->data;
+ DispList *dl;
+
+ if (mesh_uses_displist(me) && (dl= find_displist(&me->disp, DL_MESH)))
+ nmesh = newNMesh_internal(me, dl->mesh, NULL);
+ else if ((dl= find_displist(&ob->disp, DL_VERTS)))
+ nmesh = newNMesh_internal(me, NULL, dl->verts);
+ else
+ nmesh = newNMesh(me);
+ }
+ ((NMesh *) nmesh)->mesh = 0; // hack: to mark that (deformed) mesh is readonly,
+ // so the update function will not try to write it.
+ return nmesh;
+}
+
+static void mvert_from_data(MVert *mv, MSticky *st, NMVert *from)
+{
+ VECCOPY (mv->co, from->co);
+ mv->no[0]= from->no[0]*32767.0;
+ mv->no[1]= from->no[1]*32767.0;
+ mv->no[2]= from->no[2]*32767.0;
+
+ mv->flag= 0;
+ mv->mat_nr= 0;
+
+ if (st) {
+ st->co[0]= from->uvco[0];
+ st->co[1]= from->uvco[1];
+ }
+}
+
+/* TODO: this function is just a added hack. Don't look at the
+ * RGBA/BRGA confusion, it just works, but will never work with
+ * a restructured Blender */
+
+static void assign_perFaceColors(TFace *tf, NMFace *from)
+{
+ MCol *col;
+ int i;
+
+ col = (MCol *) (tf->col);
+
+ if (col) {
+ int len= PySequence_Length(from->col);
+
+ if(len>4) len= 4;
+
+ for (i=0; i<len; i++, col++) {
+ NMCol *mc= (NMCol *) PySequence_GetItem(from->col, i);
+ if(!NMCol_Check(mc)) {
+ Py_DECREF(mc);
+ continue;
+ }
+
+ col->r= mc->b;
+ col->b= mc->r;
+ col->g= mc->g;
+ col->a= mc->a;
+
+ Py_DECREF(mc);
+ }
+ }
+}
+
+static int assignFaceUV(TFace *tf, NMFace *nmface)
+{
+ PyObject *fuv, *tmp;
+ int i;
+
+ fuv = nmface->uv;
+ if (PySequence_Length(fuv) == 0)
+ return 0;
+ /* fuv = [(u_1, v_1), ... (u_n, v_n)] */
+ for (i = 0; i < PySequence_Length(fuv); i++) {
+ tmp = PyList_GetItem(fuv, i); /* stolen reference ! */
+ if (!PyArg_ParseTuple(tmp, "ff", &(tf->uv[i][0]), &(tf->uv[i][1])))
+ return 0;
+ }
+ if (nmface->tpage) /* image assigned ? */
+ {
+ tf->tpage = nmface->tpage->data;
+ }
+ else
+ tf->tpage = 0;
+
+ tf->mode = nmface->mode; /* copy mode */
+ tf->flag = nmface->flag; /* copy flag */
+ tf->transp = nmface->transp; /* copy transp flag */
+
+ /* assign vertex colours */
+ assign_perFaceColors(tf, nmface);
+ return 1;
+}
+
+static void mface_from_data(MFace *mf, TFace *tf, MCol *col, NMFace *from)
+{
+ NMVert *nmv;
+
+ int i= PyList_Size(from->v);
+ if(i>=1) {
+ nmv= (NMVert *) PyList_GetItem(from->v, 0);
+ if (NMVert_Check(nmv) && nmv->index!=-1) mf->v1= nmv->index;
+ else mf->v1= 0;
+ }
+ if(i>=2) {
+ nmv= (NMVert *) PyList_GetItem(from->v, 1);
+ if (NMVert_Check(nmv) && nmv->index!=-1) mf->v2= nmv->index;
+ else mf->v2= 0;
+ }
+ if(i>=3) {
+ nmv= (NMVert *) PyList_GetItem(from->v, 2);
+ if (NMVert_Check(nmv) && nmv->index!=-1) mf->v3= nmv->index;
+ else mf->v3= 0;
+ }
+ if(i>=4) {
+ nmv= (NMVert *) PyList_GetItem(from->v, 3);
+ if (NMVert_Check(nmv) && nmv->index!=-1) mf->v4= nmv->index;
+ else mf->v4= 0;
+ }
+
+ /* this function is evil:
+
+ test_index_mface(mf, i);
+
+ It rotates vertex indices, if there are illegal '0's (end marker)
+ in the vertex index list.
+ But it doesn't do that with vertex colours or texture coordinates...
+ */
+
+ if (tf) {
+ assignFaceUV(tf, from);
+ if (PyErr_Occurred())
+ {
+ PyErr_Print();
+ return;
+ }
+
+ test_index_face(mf, tf, i);
+ } else {
+ test_index_mface(mf, i);
+ }
+
+ mf->puno= 0;
+ mf->mat_nr= from->mat_nr;
+ mf->edcode= 0;
+ if (from->smooth)
+ mf->flag= ME_SMOOTH;
+ else
+ mf->flag= 0;
+
+ if (col) {
+ int len= PySequence_Length(from->col);
+
+ if(len>4) len= 4;
+
+ for (i=0; i<len; i++, col++) {
+ NMCol *mc= (NMCol *) PySequence_GetItem(from->col, i);
+ if(!NMCol_Check(mc)) {
+ Py_DECREF(mc);
+ continue;
+ }
+
+ col->b= mc->r;
+ col->g= mc->g;
+ col->r= mc->b;
+ col->a= mc->a;
+
+ Py_DECREF(mc);
+ }
+ }
+}
+
+
+/* check for a valid UV sequence */
+static int check_validFaceUV(NMesh *nmesh)
+{
+ PyObject *faces;
+ NMFace *nmface;
+ int i, n;
+
+ faces = nmesh->faces;
+ for (i = 0; i < PySequence_Length(faces); i++) {
+ nmface = (NMFace *) PyList_GetItem(faces, i);
+ n =
+ n = PySequence_Length(nmface->uv);
+ if (n != PySequence_Length(nmface->v))
+ {
+ if (n > 0)
+ printf("Warning: different length of vertex and UV coordinate "
+ "list in face!\n");
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static int unlink_existingMeshdata(Mesh *mesh)
+{
+ freedisplist(&mesh->disp);
+ unlink_mesh(mesh);
+ if(mesh->mvert) MEM_freeN(mesh->mvert);
+ if(mesh->mface) MEM_freeN(mesh->mface);
+ if(mesh->mcol) MEM_freeN(mesh->mcol);
+ if(mesh->msticky) MEM_freeN(mesh->msticky);
+ if(mesh->mat) MEM_freeN(mesh->mat);
+ if(mesh->tface) MEM_freeN(mesh->tface);
+ return 1;
+}
+
+Material **nmesh_updateMaterials(NMesh *nmesh)
+{
+ Material **matlist;
+ Mesh *mesh = nmesh->mesh;
+ int len = PySequence_Length(nmesh->materials);
+
+ if (!mesh) {
+ printf("FATAL INTERNAL ERROR: illegal call to updateMaterials()\n");
+ return 0;
+ }
+
+ if (len > 0) {
+ matlist = newMaterialList_fromPyList(nmesh->materials);
+ if (mesh->mat)
+ MEM_freeN(mesh->mat);
+ mesh->mat = matlist;
+ } else {
+ matlist = 0;
+ }
+ mesh->totcol = len;
+ return matlist;
+}
+
+PyObject *NMesh_assignMaterials_toObject(NMesh *nmesh, Object *ob)
+{
+ DataBlock *block;
+ Material *ma;
+ int i;
+ short old_matmask;
+
+ old_matmask = ob->colbits; // HACK: save previous colbits
+ ob->colbits = 0; // make assign_material work on mesh linked material
+
+ for (i= 0; i < PySequence_Length(nmesh->materials); i++) {
+ block= (DataBlock *) PySequence_GetItem(nmesh->materials, i);
+
+ if (DataBlock_isType(block, ID_MA)) {
+ ma = (Material *) block->data;
+ assign_material(ob, ma, i+1); // XXX don't use this function anymore
+ } else {
+ PyErr_SetString(PyExc_TypeError,
+ "Material type in attribute list 'materials' expected!");
+ Py_DECREF(block);
+ return NULL;
+ }
+
+ Py_DECREF(block);
+ }
+ ob->colbits = old_matmask; // HACK
+
+ ob->actcol = 1;
+ RETURN_INC(Py_None);
+}
+
+static int convert_NMeshToMesh(Mesh *mesh, NMesh *nmesh)
+{
+ MFace *newmf;
+ TFace *newtf;
+ MVert *newmv;
+ MSticky *newst;
+ MCol *newmc;
+
+ int i, j;
+
+ mesh->mvert= NULL;
+ mesh->mface= NULL;
+ mesh->mcol= NULL;
+ mesh->msticky= NULL;
+ mesh->tface = NULL;
+ mesh->mat= NULL;
+
+ // material assignment moved to PutRaw
+ mesh->totvert= PySequence_Length(nmesh->verts);
+ if (mesh->totvert) {
+ if (nmesh->flags&NMESH_HASVERTUV)
+ mesh->msticky= MEM_callocN(sizeof(MSticky)*mesh->totvert, "msticky");
+
+ mesh->mvert= MEM_callocN(sizeof(MVert)*mesh->totvert, "mverts");
+ }
+
+ if (mesh->totvert)
+ mesh->totface= PySequence_Length(nmesh->faces);
+ else
+ mesh->totface= 0;
+
+
+ if (mesh->totface) {
+
+/* only create vertcol array if mesh has no texture faces */
+
+/* TODO: get rid of double storage of vertex colours. In a mesh,
+ * vertex colors can be stored the following ways:
+ * - per (TFace*)->col
+ * - per (Mesh*)->mcol
+ * This is stupid, but will reside for the time being -- at least until
+ * a redesign of the internal Mesh structure */
+
+ if (!(nmesh->flags & NMESH_HASFACEUV) && (nmesh->flags&NMESH_HASMCOL))
+ mesh->mcol= MEM_callocN(4*sizeof(MCol)*mesh->totface, "mcol");
+
+ mesh->mface= MEM_callocN(sizeof(MFace)*mesh->totface, "mfaces");
+ }
+
+ /* This stuff here is to tag all the vertices referenced
+ * by faces, then untag the vertices which are actually
+ * in the vert list. Any vertices untagged will be ignored
+ * by the mface_from_data function. It comes from my
+ * screwed up decision to not make faces only store the
+ * index. - Zr
+ */
+ for (i=0; i<mesh->totface; i++) {
+ NMFace *mf= (NMFace *) PySequence_GetItem(nmesh->faces, i);
+
+ j= PySequence_Length(mf->v);
+ while (j--) {
+ NMVert *mv= (NMVert *) PySequence_GetItem(mf->v, j);
+ if (NMVert_Check(mv)) mv->index= -1;
+ Py_DECREF(mv);
+ }
+
+ Py_DECREF(mf);
+ }
+
+ for (i=0; i<mesh->totvert; i++) {
+ NMVert *mv= (NMVert *) PySequence_GetItem(nmesh->verts, i);
+ mv->index= i;
+ Py_DECREF(mv);
+ }
+
+ newmv= mesh->mvert;
+ newst= mesh->msticky;
+ for (i=0; i<mesh->totvert; i++) {
+ PyObject *mv= PySequence_GetItem(nmesh->verts, i);
+ mvert_from_data(newmv, newst, (NMVert *)mv);
+ Py_DECREF(mv);
+
+ newmv++;
+ if (newst) newst++;
+ }
+
+/* assign per face texture UVs */
+
+ /* check face UV flag, then check whether there was one
+ * UV coordinate assigned, if yes, make tfaces */
+ if ((nmesh->flags & NMESH_HASFACEUV) || (check_validFaceUV(nmesh))) {
+ make_tfaces(mesh); /* initialize TFaces */
+
+ newmc= mesh->mcol;
+ newmf= mesh->mface;
+ newtf= mesh->tface;
+ for (i=0; i<mesh->totface; i++) {
+ PyObject *mf= PySequence_GetItem(nmesh->faces, i);
+ mface_from_data(newmf, newtf, newmc, (NMFace *) mf);
+ Py_DECREF(mf);
+
+ newtf++;
+ newmf++;
+ if (newmc) newmc++;
+ }
+
+ nmesh->flags |= NMESH_HASFACEUV;
+ } else {
+
+ newmc= mesh->mcol;
+ newmf= mesh->mface;
+ for (i=0; i<mesh->totface; i++) {
+ PyObject *mf= PySequence_GetItem(nmesh->faces, i);
+ mface_from_data(newmf, 0, newmc, (NMFace *) mf);
+ Py_DECREF(mf);
+
+ newmf++;
+ if (newmc) newmc++;
+ }
+ }
+ return 1;
+}
+
+
+
+static char NMeshmodule_PutRaw_doc[]=
+"(mesh, [name, renormal]) - Return a raw mesh to Blender\n\
+\n\
+(mesh) The NMesh object to store\n\
+[name] The mesh to replace\n\
+[renormal=1] Flag to control vertex normal recalculation\n\
+\n\
+If the name of a mesh to replace is not given a new\n\
+object is created and returned.";
+
+static PyObject *NMeshmodule_PutRaw(PyObject *self, PyObject *args)
+{
+ char *name= NULL;
+ Mesh *mesh= NULL;
+ Object *ob= NULL;
+ NMesh *nmesh;
+ int recalc_normals= 1;
+
+ BPY_TRY(PyArg_ParseTuple(args, "O!|si", &NMesh_Type, &nmesh, &name, &recalc_normals));
+
+ if (!PySequence_Check(nmesh->verts))
+ return BPY_err_ret_ob(PyExc_AttributeError, "nmesh vertices are not a sequence");
+ if (!PySequence_Check(nmesh->faces))
+ return BPY_err_ret_ob(PyExc_AttributeError, "nmesh faces are not a sequence");
+ if (!PySequence_Check(nmesh->materials))
+ return BPY_err_ret_ob(PyExc_AttributeError, "nmesh materials are not a sequence");
+
+ if (!BPY_check_sequence_consistency(nmesh->verts, &NMVert_Type))
+ return BPY_err_ret_ob(PyExc_AttributeError, "nmesh vertices must be NMVerts");
+ if (!BPY_check_sequence_consistency(nmesh->faces, &NMFace_Type))
+ return BPY_err_ret_ob(PyExc_AttributeError, "nmesh faces must be NMFaces");
+
+ if (name)
+ mesh= (Mesh *) getFromList(getMeshList(), name);
+ /* returns new mesh if not found */
+
+ if(!mesh || mesh->id.us==0) {
+ ob= add_object(OB_MESH);
+ if (!ob) {
+ PyErr_SetString(PyExc_RuntimeError, "Fatal: could not create mesh object");
+ return 0;
+ }
+ if (mesh)
+ set_mesh(ob, mesh);
+ else
+ mesh= (Mesh *) ob->data;
+ }
+ if(name) new_id(getMeshList(), &mesh->id, name);
+
+ unlink_existingMeshdata(mesh);
+ convert_NMeshToMesh(mesh, nmesh);
+ nmesh->mesh = mesh;
+
+ if(recalc_normals)
+ vertexnormals_mesh(mesh, 0);
+
+ mesh_update(mesh);
+
+ if (!during_script())
+ allqueue(REDRAWVIEW3D, 0);
+
+ // OK...this requires some explanation:
+ // Materials can be assigned two ways:
+ // a) to the object data (in this case, the mesh)
+ // b) to the Object
+ //
+ // Case a) is wanted, if Mesh data should be shared among objects,
+ // as well as its materials (up to 16)
+ // Case b) is wanted, when Mesh data should be shared, but not the
+ // materials. For example, you want several checker boards sharing their
+ // mesh data, but having different colors. So you would assign material
+ // index 0 to all even, index 1 to all odd faces and bind the materials
+ // to the Object instead (MaterialButtons: [OB] button "link materials to object")
+ //
+ // This feature implies that pointers to materials can be stored in
+ // an object or a mesh. The number of total materials MUST be
+ // synchronized (ob->totcol <-> mesh->totcol). We avoid the dangerous
+ // direct access by calling blenderkernel/material.c:assign_material().
+
+ // The flags setting the material binding is found in ob->colbits, where
+ // each bit indicates the binding PER MATERIAL
+
+ if (ob) { // we created a new object
+ NMesh_assignMaterials_toObject(nmesh, ob);
+ return DataBlock_fromData(ob);
+ } else {
+ RETURN_INC(Py_None);
+ }
+}
+
+#undef MethodDef
+#define MethodDef(func) {#func, NMeshmodule_##func, METH_VARARGS, NMeshmodule_##func##_doc}
+
+static struct PyMethodDef NMeshmodule_methods[] = {
+// These should be: Mesh.Col, Mesh.Vert, Mesh.Face in fure
+// -- for ownership reasons
+ MethodDef(Col),
+ MethodDef(Vert),
+ MethodDef(Face),
+ MethodDef(New),
+ MethodDef(GetRaw),
+ MethodDef(GetRawFromObject),
+ MethodDef(PutRaw),
+ {NULL, NULL}
+};
+#undef BPY_ADDCONST
+#define BPY_ADDCONST(dict, name) insertConst(dict, #name, PyInt_FromLong(TF_##name))
+
+/* set constants for face drawing mode -- see drawmesh.c */
+
+static void init_NMeshConst(PyObject *d)
+{
+ insertConst(d, "BILLBOARD", PyInt_FromLong(TF_BILLBOARD2));
+ //BPY_ADDCONST(d, BILLBOARD);
+ insertConst(d, "ALL", PyInt_FromLong(0xffff));
+ BPY_ADDCONST(d, DYNAMIC);
+ BPY_ADDCONST(d, INVISIBLE);
+ insertConst(d, "HALO", PyInt_FromLong(TF_BILLBOARD));
+ BPY_ADDCONST(d, LIGHT);
+ BPY_ADDCONST(d, OBCOL);
+ BPY_ADDCONST(d, SHADOW);
+ BPY_ADDCONST(d, SHAREDVERT);
+ BPY_ADDCONST(d, SHAREDCOL);
+ BPY_ADDCONST(d, TEX);
+ BPY_ADDCONST(d, TILES);
+ BPY_ADDCONST(d, TWOSIDE);
+/* transparent modes */
+ BPY_ADDCONST(d, SOLID);
+ BPY_ADDCONST(d, ADD);
+ BPY_ADDCONST(d, ALPHA);
+ BPY_ADDCONST(d, SUB);
+/* TFACE flags */
+ BPY_ADDCONST(d, SELECT);
+ BPY_ADDCONST(d, HIDE);
+ BPY_ADDCONST(d, ACTIVE);
+}
+
+PyObject *init_py_nmesh(void)
+{
+ PyObject *d;
+ PyObject *mod= Py_InitModule(SUBMODULE(NMesh), NMeshmodule_methods);
+ PyObject *dict= PyModule_GetDict(mod);
+
+ NMesh_Type.ob_type= &PyType_Type;
+ NMVert_Type.ob_type= &PyType_Type;
+ NMFace_Type.ob_type= &PyType_Type;
+ NMCol_Type.ob_type= &PyType_Type;
+
+ d = ConstObject_New();
+ PyDict_SetItemString(dict, "Const" , d);
+ init_NMeshConst(d);
+
+ g_nmeshmodule = mod;
+ return mod;
+}
+
+#ifdef SHAREDMODULE
+void initNMesh(void)
+{
+ init_py_nmesh();
+}
+#endif
diff --git a/source/blender/bpython/intern/opy_nmesh.h b/source/blender/bpython/intern/opy_nmesh.h
new file mode 100644
index 00000000000..778a726b26e
--- /dev/null
+++ b/source/blender/bpython/intern/opy_nmesh.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 *****
+ */
+/* opy_nmesh.c */
+
+#include "DNA_mesh_types.h"
+
+#define NMesh_Check(v) ((v)->ob_type == &NMesh_Type)
+#define NMFace_Check(v) ((v)->ob_type == &NMFace_Type)
+#define NMVert_Check(v) ((v)->ob_type == &NMVert_Type)
+#define NMCol_Check(v) ((v)->ob_type == &NMCol_Type)
+
+typedef struct _NMCol {
+ PyObject_HEAD
+
+ unsigned char r, g, b, a;
+} NMCol;
+
+struct PyBlock;
+
+typedef struct _NMFace {
+ PyObject_HEAD
+
+ PyObject *v;
+ PyObject *uv;
+ PyObject *col;
+ short mode;
+ short flag;
+ unsigned char transp;
+ DataBlock *tpage; /* Image */
+ char mat_nr, smooth;
+} NMFace;
+
+typedef struct _NMesh {
+ PyObject_HEAD
+ Mesh *mesh;
+ PyObject *name;
+ PyObject *materials;
+ PyObject *verts;
+ PyObject *faces;
+ int sel_face; /* XXX remove */
+ char flags;
+#define NMESH_HASMCOL 1<<0
+#define NMESH_HASVERTUV 1<<1
+#define NMESH_HASFACEUV 1<<2
+
+} NMesh;
+
+typedef struct _NMVert {
+ PyObject_VAR_HEAD
+
+ float co[3];
+ float no[3];
+ float uvco[3];
+
+ int index;
+} NMVert;
+
+
+/* PROTOS */
+
+PyObject *newNMesh(Mesh *oldmesh);
+Mesh *Mesh_fromNMesh(NMesh *nmesh);
+PyObject *NMesh_assignMaterials_toObject(NMesh *nmesh, Object *ob);
+Material **nmesh_updateMaterials(NMesh *nmesh);
diff --git a/source/blender/bpython/intern/opy_vector.c b/source/blender/bpython/intern/opy_vector.c
new file mode 100644
index 00000000000..905c6aeed34
--- /dev/null
+++ b/source/blender/bpython/intern/opy_vector.c
@@ -0,0 +1,241 @@
+/* python.c MIXED MODEL
+ *
+ * june 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 *****
+ */
+
+#include "Python.h"
+#include "BPY_tools.h"
+#include "BPY_macros.h"
+#include "BPY_modules.h"
+#include "opy_vector.h"
+
+
+
+/*****************************/
+/* Vector Python Object */
+/*****************************/
+
+PyTypeObject Vector_Type;
+
+
+#define VectorObject_Check(v) ((v)->ob_type == &Vector_Type)
+
+
+static void Vector_dealloc(VectorObject *self) {
+ PyMem_DEL(self);
+}
+
+static PyObject *Vector_getattr(VectorObject *self, char *name) {
+ if (self->size==3 && ELEM3(name[0], 'x', 'y', 'z') && name[1]==0)
+ return PyFloat_FromDouble(self->vec[ name[0]-'x' ]);
+
+ PyErr_SetString(PyExc_AttributeError, name);
+ return NULL;
+}
+
+static int Vector_setattr(VectorObject *self, char *name, PyObject *v) {
+ float val;
+
+ BPY_TRY(PyArg_Parse(v, "f;Coordinates must be floats", &val));
+
+ if (self->size==3 && ELEM3(name[0], 'x', 'y', 'z') && name[1]==0)
+ self->vec[ name[0]-'x' ]= val;
+ else
+ return -1;
+
+ return 0;
+}
+
+/* Vectors utils */
+
+/* XXX
+int Vector_Parse(PyObject *vec)
+{
+
+}
+*/
+
+/* Vectors Sequence methods */
+
+static int Vector_len(VectorObject *self)
+{
+ return self->size;
+}
+
+static PyObject *Vector_item(VectorObject *self, int i)
+{
+ if (i < 0 || i >= self->size) {
+ PyErr_SetString(PyExc_IndexError, "array index out of range");
+ return NULL;
+ }
+ return Py_BuildValue("f", self->vec[i]);
+}
+
+static PyObject *Vector_slice(VectorObject *self, int begin, int end)
+{
+ PyObject *list;
+ int count;
+
+ if (begin<0) begin= 0;
+ if (end>self->size) end= self->size;
+ if (begin>end) begin= end;
+
+ list= PyList_New(end-begin);
+
+ for (count= begin; count<end; count++)
+ PyList_SetItem(list, count-begin, PyFloat_FromDouble(self->vec[count]));
+
+ return list;
+}
+
+static int Vector_ass_item(VectorObject *self, int i, PyObject *ob)
+{
+ if (i < 0 || i >= self->size) {
+ PyErr_SetString(PyExc_IndexError, "array assignment index out of range");
+ return -1;
+ }
+
+ if (!PyNumber_Check(ob)) {
+ PyErr_SetString(PyExc_IndexError, "vector member must be a number");
+ return -1;
+ }
+
+ self->vec[i]= PyFloat_AsDouble(ob);
+/* if(!PyArg_Parse(ob, "f", &)) return -1; */
+
+ return 0;
+}
+
+static int Vector_ass_slice(VectorObject *self, int begin, int end, PyObject *seq)
+{
+ int count;
+
+ if (begin<0) begin= 0;
+ if (end>self->size) end= self->size;
+ if (begin>end) begin= end;
+
+ if (!PySequence_Check(seq)) {
+ PyErr_SetString(PyExc_TypeError, "illegal argument type for built-in operation");
+ return -1;
+ }
+
+ if (PySequence_Length(seq)!=(end-begin)) {
+ PyErr_SetString(PyExc_TypeError, "size mismatch in slice assignment");
+ return -1;
+ }
+
+ for (count= begin; count<end; count++) {
+ PyObject *ob= PySequence_GetItem(seq, count);
+ if (!PyArg_Parse(ob, "f", &self->vec[count])) {
+ Py_DECREF(ob);
+ return -1;
+ }
+ Py_DECREF(ob);
+ }
+
+ return 0;
+}
+
+PyObject *BPY_tuple_repr(PyObject *self, int size)
+{
+ PyObject *repr, *comma, *item;
+ int i;
+
+ // note: a value must be built because the list is decrefed!
+ // otherwise we have nirvana pointers inside python..
+ //PyObject *repr= Py_BuildValue("s", PyString_AsString(PyObject_Repr(list)));
+ repr = PyString_FromString("(");
+ if (!repr) return 0;
+
+ item = PySequence_GetItem(self, 0);
+ PyString_ConcatAndDel(&repr, PyObject_Repr(item));
+ Py_DECREF(item);
+
+ comma = PyString_FromString(", ");
+ for (i = 1; i < size; i++) {
+ PyString_Concat(&repr, comma);
+ item = PySequence_GetItem(self, i);
+ PyString_ConcatAndDel(&repr, PyObject_Repr(item));
+ Py_DECREF(item);
+ }
+ PyString_ConcatAndDel(&repr, PyString_FromString(")"));
+ Py_DECREF(comma);
+ return repr;
+
+}
+
+
+static PyObject *Vector_repr (VectorObject *self) {
+ return BPY_tuple_repr((PyObject *) self, self->size);
+}
+
+static PySequenceMethods Vector_SeqMethods = {
+ (inquiry) Vector_len, /* sq_length */
+ (binaryfunc) 0, /* sq_concat */
+ (intargfunc) 0, /* sq_repeat */
+ (intargfunc) Vector_item, /* sq_item */
+ (intintargfunc) Vector_slice, /* sq_slice */
+ (intobjargproc) Vector_ass_item, /* sq_ass_item */
+ (intintobjargproc) Vector_ass_slice, /* sq_ass_slice */
+};
+
+PyTypeObject Vector_Type = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "Vector", /*tp_name*/
+ sizeof(VectorObject), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ (destructor) Vector_dealloc, /*tp_dealloc*/
+ (printfunc) 0, /*tp_print*/
+ (getattrfunc) Vector_getattr, /*tp_getattr*/
+ (setattrfunc) Vector_setattr, /*tp_setattr*/
+ 0, /*tp_compare*/
+ (reprfunc) Vector_repr, /*tp_repr*/
+ 0, /*tp_as_number*/
+ &Vector_SeqMethods, /*tp_as_sequence*/
+};
+
+PyObject *newVectorObject(float *vec, int size) {
+ VectorObject *self;
+
+ self= PyObject_NEW(VectorObject, &Vector_Type);
+
+ self->vec= vec;
+ self->size= size;
+
+ return (PyObject*) self;
+}
+
+void init_py_vector(void) {
+ Vector_Type.ob_type = &PyType_Type;
+}
diff --git a/source/blender/bpython/intern/opy_vector.h b/source/blender/bpython/intern/opy_vector.h
new file mode 100644
index 00000000000..cf7ca87fd6a
--- /dev/null
+++ b/source/blender/bpython/intern/opy_vector.h
@@ -0,0 +1,63 @@
+
+
+/* Matrix and vector objects in Python */
+
+/* $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ *
+ */
+
+/*****************************/
+/* Matrix Python Object */
+/*****************************/
+/* temporar hack for typecasts */
+
+typedef float (*Matrix4Ptr)[4];
+typedef struct {
+ PyObject_VAR_HEAD
+ float *vec;
+ int size;
+} VectorObject;
+
+typedef struct {
+ PyObject_VAR_HEAD
+ PyObject *rows[4];
+ Matrix4Ptr mat;
+} MatrixObject;
+
+
+/* PROTOS */
+
+PyObject *newVectorObject(float *vec, int size);
+PyObject *newMatrixObject(Matrix4Ptr mat);
+void init_py_matrix(void);
+void init_py_vector(void);
+
+
diff --git a/source/blender/bpython/intern/opy_window.c b/source/blender/bpython/intern/opy_window.c
new file mode 100644
index 00000000000..8aa976382a9
--- /dev/null
+++ b/source/blender/bpython/intern/opy_window.c
@@ -0,0 +1,194 @@
+
+/*
+ * Python Blender Window module
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "Python.h"
+#include "BPY_macros.h"
+#include "b_interface.h"
+#include "BPY_tools.h"
+#include "BPY_main.h"
+#include "BPY_window.h"
+
+#include "BSE_headerbuttons.h"
+
+#include "BIF_screen.h" // curarea
+#include "BIF_space.h" // allqueue()
+#include "BIF_drawtext.h" // pop_space_text
+#include "mydevice.h" // for all the event constants
+
+#include "opy_datablock.h"
+#include "opy_nmesh.h"
+
+#include "DNA_view3d_types.h"
+#include "DNA_space_types.h"
+
+
+/*********************************/
+/* helper routines */
+
+
+/** update current camera view */
+
+void window_update_curCamera(Object *camera)
+{
+ copy_view3d_lock(REDRAW);
+}
+
+char Windowmodule_QRedrawAll_doc[]= "() - Redraw all windows by queue event";
+
+/* hack to flag that window redraw has happened inside slider callback: */
+int g_window_redrawn = 0;
+
+static PyObject *Windowmodule_QRedrawAll(PyObject *self, PyObject *args)
+{
+ int wintype = 0;
+ BPY_TRY(PyArg_ParseTuple(args, "|i", &wintype));
+
+ allqueue(REDRAWALL, 0);
+ RETURN_INC(Py_None);
+}
+char Windowmodule_Redraw_doc[]= "() - Force a redraw of a specific Window Type; see Window.Const";
+
+PyObject *Windowmodule_Redraw(PyObject *self, PyObject *args)
+{
+ ScrArea *tempsa, *sa;
+ SpaceText *st;
+ int wintype = SPACE_VIEW3D;
+ short redraw_all = 0;
+
+ BPY_TRY(PyArg_ParseTuple(args, "|i", &wintype));
+
+ g_window_redrawn = 1;
+
+ if (wintype < 0)
+ redraw_all = 1;
+ if (!during_script()) {
+ tempsa= curarea;
+ sa= getGlobal()->curscreen->areabase.first;
+ while(sa) {
+
+ if (sa->spacetype== wintype || redraw_all) {
+ /* don't force-redraw Text window (Python GUI) when
+ redraw is called out of a slider update */
+ if (sa->spacetype == SPACE_TEXT) {
+ st = sa->spacedata.first;
+ if (st->text->flags & TXT_FOLLOW) // follow cursor display
+ pop_space_text(st);
+ if (disable_force_draw) {
+ scrarea_queue_redraw(sa);
+ }
+
+
+ } else {
+ scrarea_do_windraw(sa);
+ if (sa->headwin) scrarea_do_headdraw(sa);
+ }
+ }
+
+ sa= sa->next;
+ }
+ if(curarea!=tempsa) areawinset(tempsa->win);
+
+ if (curarea->headwin) scrarea_do_headdraw(curarea);
+ screen_swapbuffers();
+ }
+
+ RETURN_INC(Py_None);
+}
+
+char Windowmodule_RedrawAll_doc[]= "() - Redraw all windows";
+static PyObject *Windowmodule_RedrawAll(PyObject *self, PyObject *args)
+{
+ return Windowmodule_Redraw(self, Py_BuildValue("(i)", -1));
+}
+
+char Windowmodule_draw_progressbar_doc[]= "(done, text) - Draw a progressbar.\n\
+'done' is a float value <= 1.0, 'text' contains info about what is currently\n\
+being done";
+
+static PyObject *Windowmodule_draw_progressbar(PyObject *self, PyObject *args)
+{
+ float done;
+ char *info = 0;
+ int retval;
+
+ BPY_TRY(PyArg_ParseTuple(args, "fs", &done, &info));
+ retval = progress_bar(done, info);
+ return Py_BuildValue("i", retval);
+}
+
+#undef METHODDEF
+#define METHODDEF(func) {#func, Windowmodule_##func, METH_VARARGS, Windowmodule_##func##_doc}
+
+static struct PyMethodDef Windowmodule_methods[] = {
+ METHODDEF(Redraw),
+ METHODDEF(QRedrawAll),
+ METHODDEF(RedrawAll),
+ METHODDEF(draw_progressbar),
+
+ {NULL, NULL}
+};
+
+
+#undef BPY_ADDCONST
+#define BPY_ADDCONST(dict, name) insertConst(dict, #name, PyInt_FromLong(SPACE_##name))
+
+PyObject *INITMODULE(Window)(void)
+{
+ PyObject *d;
+ PyObject *mod= Py_InitModule(SUBMODULE(Window), Windowmodule_methods);
+ PyObject *dict= PyModule_GetDict(mod);
+
+/* from DNA_screen.types.h */
+ d = ConstObject_New();
+ PyDict_SetItemString(dict, "Types" , d);
+
+ BPY_ADDCONST(d, VIEW3D);
+ BPY_ADDCONST(d, IPO);
+ BPY_ADDCONST(d, OOPS);
+ BPY_ADDCONST(d, BUTS);
+ BPY_ADDCONST(d, FILE);
+ BPY_ADDCONST(d, IMAGE);
+ BPY_ADDCONST(d, INFO);
+ BPY_ADDCONST(d, SEQ);
+ BPY_ADDCONST(d, IMASEL);
+ BPY_ADDCONST(d, SOUND);
+ BPY_ADDCONST(d, ACTION);
+ BPY_ADDCONST(d, TEXT);
+ BPY_ADDCONST(d, NLA);
+/* BPY_ADDCONST(d, LOGIC); */
+
+ return mod;
+}
diff --git a/source/blender/decrypt/BLO_decrypt.h b/source/blender/decrypt/BLO_decrypt.h
new file mode 100644
index 00000000000..e552368cf0a
--- /dev/null
+++ b/source/blender/decrypt/BLO_decrypt.h
@@ -0,0 +1,78 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BLO_DECRYPT_H
+#define BLO_DECRYPT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define DECRYPT_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name
+
+DECRYPT_DECLARE_HANDLE(BLO_decryptStructHandle);
+
+/**
+ * openssl decrypt decompression initializer
+ * @retval pointer to decrypt control structure
+ */
+ BLO_decryptStructHandle
+BLO_decrypt_begin(
+ void *endControl);
+
+/**
+ * openssl decrypt dataprocessor wrapper
+ * @param BLO_decrypt Pointer to decrypt control structure
+ * @param data Pointer to new data
+ * @param dataIn New data amount
+ * @retval streamGlueRead return value
+ */
+ int
+BLO_decrypt_process(
+ BLO_decryptStructHandle BLO_decryptHandle,
+ unsigned char *data,
+ unsigned int dataIn);
+
+/**
+ * openssl decrypt final call and cleanup
+ * @param BLO_decrypt Pointer to decrypt control structure
+ * @retval streamGlueRead return value
+ */
+ int
+BLO_decrypt_end(
+ BLO_decryptStructHandle BLO_decryptHandle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BLO_DECRYPT_H */
diff --git a/source/blender/decrypt/BLO_en_de_cryptHeader.h b/source/blender/decrypt/BLO_en_de_cryptHeader.h
new file mode 100644
index 00000000000..d8bedc470ff
--- /dev/null
+++ b/source/blender/decrypt/BLO_en_de_cryptHeader.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 *****
+ *
+ */
+
+#ifndef BLO_EN_DE_CRYPT_H
+#define BLO_EN_DE_CRYPT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "BLO_sys_types.h"
+
+#define EN_DE_CRYPTHEADERSTRUCTSIZE sizeof(struct BLO_en_de_cryptHeaderStruct)
+
+// Tests showed: pubKeyLen 64, cryptedKeyLen 64 bytes
+// So we pick 2*64 bytes + 2 bytes dummy tail for now :
+#define MAXPUBKEYLEN 130
+#define MAXCRYPTKEYLEN 130
+
+struct BLO_en_de_cryptHeaderStruct {
+ uint8_t magic; // poor mans header recognize check
+ uint32_t length; // how much crypted data is there
+ uint8_t pubKey[MAXPUBKEYLEN];
+ uint32_t pubKeyLen; // the actual pubKey length
+ uint8_t cryptedKey[MAXCRYPTKEYLEN];
+ int32_t cryptedKeyLen; // the actual cryptedKey length (NOTE: signed)
+ uint32_t datacrc; // crypted data checksum
+ uint32_t headercrc; // header minus crc itself checksum
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BLO_EN_DE_CRYPT_H */
diff --git a/source/blender/decrypt/Makefile b/source/blender/decrypt/Makefile
new file mode 100644
index 00000000000..7418d4407ae
--- /dev/null
+++ b/source/blender/decrypt/Makefile
@@ -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 *****
+#
+# Bounces make to subdirectories.
+
+SOURCEDIR = source/blender/decrypt
+DIRS = intern stub
+
+include nan_subdirs.mk
diff --git a/source/blender/decrypt/intern/BLO_decrypt.c b/source/blender/decrypt/intern/BLO_decrypt.c
new file mode 100644
index 00000000000..4d2eefd9631
--- /dev/null
+++ b/source/blender/decrypt/intern/BLO_decrypt.c
@@ -0,0 +1,394 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * openssl decryption wrapper library
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "openssl/rsa.h"
+#include "openssl/rc4.h"
+#include "openssl/err.h"
+#include "zlib.h"
+
+#include "GEN_messaging.h"
+
+#include "blenkey.h"
+#include "BLO_getPubKey.h" // real and stub implemented at writestream ...
+
+#include "BLO_readStreamGlue.h"
+#include "BLO_decrypt.h"
+#include "BLO_en_de_cryptHeader.h"
+
+struct decryptStructType {
+ struct readStreamGlueStruct *streamGlue;
+ unsigned int streamDone;
+ unsigned char *deCryptKey;
+ int deCryptKeyLen; // NOTE: signed int
+ unsigned char headerbuffer[EN_DE_CRYPTHEADERSTRUCTSIZE];
+ uint32_t datacrc; // crypted data checksum
+ struct BLO_en_de_cryptHeaderStruct *streamHeader;
+ RC4_KEY rc4_key;
+ void *endControl;
+};
+
+ BLO_decryptStructHandle
+BLO_decrypt_begin(
+ void *endControl)
+{
+ struct decryptStructType *control;
+ control = malloc(sizeof(struct decryptStructType));
+ if (!control) return NULL;
+
+ control->streamGlue = NULL;
+ control->streamDone = 0;
+ control->deCryptKey = NULL;
+ control->deCryptKeyLen = 0;
+ strcpy(control->headerbuffer, "");
+ control->datacrc = 0;
+
+ control->streamHeader = malloc(EN_DE_CRYPTHEADERSTRUCTSIZE);
+ if (!control->streamHeader) {
+ free(control);
+ return NULL;
+ }
+
+ control->streamHeader->magic = 0;
+ control->streamHeader->length = 0;
+ strcpy(control->streamHeader->pubKey, "");
+ control->streamHeader->pubKeyLen = 0;
+ strcpy(control->streamHeader->cryptedKey, "");
+ control->streamHeader->cryptedKeyLen = 0;
+ control->streamHeader->datacrc = 0;
+ control->streamHeader->headercrc = 0;
+ control->endControl = endControl;
+
+ return((BLO_decryptStructHandle) control);
+}
+
+ int
+BLO_decrypt_process(
+ BLO_decryptStructHandle BLO_decryptHandle,
+ unsigned char *data,
+ unsigned int dataIn)
+{
+ int err = 0;
+ struct decryptStructType *BLO_decrypt =
+ (struct decryptStructType *) BLO_decryptHandle;
+
+ if (!BLO_decrypt) {
+ err = BRS_SETFUNCTION(BRS_DECRYPT) |
+ BRS_SETGENERR(BRS_NULL);
+ return err;
+ }
+
+ /* First check if we have our header filled in yet */
+ if (BLO_decrypt->streamHeader->cryptedKeyLen == 0) {
+ unsigned int processed;
+ if (dataIn == 0) return err; /* really need data to do anything */
+ processed = ((dataIn + BLO_decrypt->streamDone) <=
+ EN_DE_CRYPTHEADERSTRUCTSIZE)
+ ? dataIn : EN_DE_CRYPTHEADERSTRUCTSIZE;
+ memcpy(BLO_decrypt->headerbuffer + BLO_decrypt->streamDone,
+ data, processed);
+ BLO_decrypt->streamDone += processed;
+ dataIn -= processed;
+ data += processed;
+ if (BLO_decrypt->streamDone == EN_DE_CRYPTHEADERSTRUCTSIZE) {
+ /* we have the whole header, absorb it */
+ struct BLO_en_de_cryptHeaderStruct *header;
+ uint32_t crc;
+ //static unsigned char rsa_e[] = "\x11";
+ static unsigned char rsa_e[] = "\x01\x00\x01";
+ RSA *rsa = NULL;
+ byte *publisherPubKey;
+ int publisherPubKeyLen;
+
+ header = (struct BLO_en_de_cryptHeaderStruct *)
+ BLO_decrypt->headerbuffer;
+ crc = crc32(0L, (const Bytef *) header,
+ EN_DE_CRYPTHEADERSTRUCTSIZE - 4);
+
+ if (header->magic == 'A') {
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "BLO_en_de_cryptHeaderStruct Magic confirmed\n");
+#endif
+ } else {
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "ERROR BLO_en_de_cryptHeaderStruct Magic NOT confirmed\n");
+#endif
+ err = BRS_SETFUNCTION(BRS_DECRYPT) |
+ BRS_SETGENERR(BRS_MAGIC);
+ if (BLO_decrypt->streamGlue) free(BLO_decrypt->streamGlue);
+ if (BLO_decrypt->streamHeader) free(BLO_decrypt->streamHeader);
+ if (BLO_decrypt->deCryptKey) free(BLO_decrypt->deCryptKey);
+ free(BLO_decrypt);
+ return err;
+ }
+
+ if (crc == ntohl(header->headercrc)) {
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "BLO_en_de_cryptHeader CRC correct\n");
+#endif
+ } else {
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "ERROR BLO_en_de_cryptHeader CRC NOT correct\n");
+#endif
+ err = BRS_SETFUNCTION(BRS_DECRYPT) |
+ BRS_SETGENERR(BRS_CRCHEADER);
+ if (BLO_decrypt->streamGlue) free(BLO_decrypt->streamGlue);
+ if (BLO_decrypt->streamHeader) free(BLO_decrypt->streamHeader);
+ if (BLO_decrypt->deCryptKey) free(BLO_decrypt->deCryptKey);
+ free(BLO_decrypt);
+ return err;
+ }
+ BLO_decrypt->streamHeader->length = ntohl(header->length);
+ BLO_decrypt->streamHeader->pubKeyLen = ntohl(header->pubKeyLen);
+ memcpy(BLO_decrypt->streamHeader->pubKey, header->pubKey,
+ BLO_decrypt->streamHeader->pubKeyLen);
+
+ // case Publisher: get the .BPkey public key
+ // case Player/Plugin: simply use the data stream public key
+ err = getPubKey(BLO_decrypt->streamHeader->pubKey,
+ BLO_decrypt->streamHeader->pubKeyLen,
+ &publisherPubKey,
+ &publisherPubKeyLen);
+ switch (err) {
+ case 0:
+ // everything OK
+ break;
+ case 1:
+ // publisher without a key
+ case 2:
+ // publishers keylen !=
+ case 3:
+ // publishers key !=
+ default:
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "ALERT users-pubKey != datastream-pubKey, stop reading\n");
+#endif
+ err = BRS_SETFUNCTION(BRS_DECRYPT) |
+ BRS_SETSPECERR(BRS_NOTOURPUBKEY);
+ if (BLO_decrypt->streamGlue) free(BLO_decrypt->streamGlue);
+ if (BLO_decrypt->streamHeader) free(BLO_decrypt->streamHeader);
+ if (BLO_decrypt->deCryptKey) free(BLO_decrypt->deCryptKey);
+ free(BLO_decrypt);
+ return err;
+ break;
+ }
+
+ BLO_decrypt->streamHeader->cryptedKeyLen =
+ ntohl(header->cryptedKeyLen);
+ memcpy(BLO_decrypt->streamHeader->cryptedKey,
+ header->cryptedKey,
+ BLO_decrypt->streamHeader->cryptedKeyLen);
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "BLO_decrypt_process gets %u bytes\n",
+ (unsigned int) BLO_decrypt->streamHeader->length);
+#endif
+ BLO_decrypt->streamHeader->datacrc = ntohl(header->datacrc);
+
+ // finished absorbing and testing the header, create rsa key from it
+ rsa = RSA_new();
+ if (rsa == NULL) {
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "Error in RSA_new\n");
+#endif
+ err = BRS_SETFUNCTION(BRS_DECRYPT) |
+ BRS_SETSPECERR(BRS_RSANEWERROR);
+ if (BLO_decrypt->streamGlue) free(BLO_decrypt->streamGlue);
+ if (BLO_decrypt->streamHeader) free(BLO_decrypt->streamHeader);
+ if (BLO_decrypt->deCryptKey) free(BLO_decrypt->deCryptKey);
+ free(BLO_decrypt);
+ return err;
+ }
+ // static exponent
+ rsa->e = BN_bin2bn(rsa_e, sizeof(rsa_e)-1, rsa->e);
+
+ // public part into rsa->n
+ rsa->n = BN_bin2bn(publisherPubKey,
+ publisherPubKeyLen,
+ rsa->n);
+
+ //DEBUG RSA_print_fp(stdout, rsa, 0);
+
+ BLO_decrypt->deCryptKey = malloc(RSA_size(rsa) *
+ sizeof(unsigned char));
+ if (! BLO_decrypt->deCryptKey) {
+ err = BRS_SETFUNCTION(BRS_DECRYPT) |
+ BRS_SETGENERR(BRS_MALLOC);
+ if (BLO_decrypt->streamGlue) free(BLO_decrypt->streamGlue);
+ if (BLO_decrypt->streamHeader) free(BLO_decrypt->streamHeader);
+ if (BLO_decrypt->deCryptKey) free(BLO_decrypt->deCryptKey);
+ free(BLO_decrypt);
+ RSA_free(rsa);
+ return err;
+ }
+
+ // decrypt the cryptkey
+ BLO_decrypt->deCryptKeyLen = RSA_public_decrypt(
+ BLO_decrypt->streamHeader->cryptedKeyLen,
+ BLO_decrypt->streamHeader->cryptedKey,
+ BLO_decrypt->deCryptKey,
+ rsa, RSA_PKCS1_PADDING);
+ if (BLO_decrypt->deCryptKeyLen == -1) {
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "Error in RSA_public_decrypt %s\n",
+ ERR_error_string(ERR_get_error(),
+ NULL));
+#endif
+ err = BRS_SETFUNCTION(BRS_DECRYPT) |
+ BRS_SETSPECERR(BRS_DECRYPTERROR);
+ if (BLO_decrypt->streamGlue) free(BLO_decrypt->streamGlue);
+ if (BLO_decrypt->streamHeader) free(BLO_decrypt->streamHeader);
+ if (BLO_decrypt->deCryptKey) free(BLO_decrypt->deCryptKey);
+ free(BLO_decrypt);
+ RSA_free(rsa);
+ return err;
+ }
+
+ // Finally set the RC4 deCryptKey
+ RC4_set_key(&(BLO_decrypt->rc4_key),
+ BLO_decrypt->deCryptKeyLen,
+ BLO_decrypt->deCryptKey);
+
+ RSA_free(rsa);
+ }
+ }
+
+ /* Is there really (still) new data available ? */
+ if (dataIn > 0) {
+ unsigned char *deCryptBuf = malloc(dataIn);
+ if (! deCryptBuf) {
+ err = BRS_SETFUNCTION(BRS_DECRYPT) |
+ BRS_SETGENERR(BRS_MALLOC);
+ if (BLO_decrypt->streamGlue) free(BLO_decrypt->streamGlue);
+ if (BLO_decrypt->streamHeader) free(BLO_decrypt->streamHeader);
+ if (BLO_decrypt->deCryptKey) free(BLO_decrypt->deCryptKey);
+ free(BLO_decrypt);
+ return err;
+ }
+
+ BLO_decrypt->streamDone += dataIn;
+
+ // update datacrc
+ BLO_decrypt->datacrc = crc32(
+ BLO_decrypt->datacrc, (const Bytef *) data, dataIn);
+
+ // TODO FIXME we might need to keylength-align the data !
+ RC4(&(BLO_decrypt->rc4_key), dataIn, data, deCryptBuf);
+
+ // give data to streamGlueRead, it will find out what to do next
+ err = readStreamGlue(
+ BLO_decrypt->endControl,
+ &(BLO_decrypt->streamGlue),
+ (unsigned char *) deCryptBuf,
+ dataIn);
+
+ free(deCryptBuf);
+ }
+ return err;
+}
+
+/**
+ * openssl decrypt final call and cleanup
+ * @param BLO_decrypt Pointer to decrypt control structure
+ * @retval streamGlueRead return value
+ */
+ int
+BLO_decrypt_end(
+ BLO_decryptStructHandle BLO_decryptHandle)
+{
+ int err = 0;
+ struct decryptStructType *BLO_decrypt =
+ (struct decryptStructType *) BLO_decryptHandle;
+
+ if (!BLO_decrypt) {
+ err = BRS_SETFUNCTION(BRS_DECRYPT) |
+ BRS_SETGENERR(BRS_NULL);
+ if (BLO_decrypt->streamGlue) free(BLO_decrypt->streamGlue);
+ if (BLO_decrypt->streamHeader) free(BLO_decrypt->streamHeader);
+ if (BLO_decrypt->deCryptKey) free(BLO_decrypt->deCryptKey);
+ free(BLO_decrypt);
+ return err;
+ }
+
+ if (BLO_decrypt->streamDone == BLO_decrypt->streamHeader->length +
+ EN_DE_CRYPTHEADERSTRUCTSIZE) {
+#ifndef NDEBUG
+ fprintf(GEN_errorstream, "Crypted data length is correct\n");
+#endif
+ } else {
+#ifndef NDEBUG
+ fprintf(GEN_errorstream, "Crypted data length is NOT correct\n");
+#endif
+ err = BRS_SETFUNCTION(BRS_DECRYPT) |
+ BRS_SETGENERR(BRS_DATALEN);
+ if (BLO_decrypt->streamGlue) free(BLO_decrypt->streamGlue);
+ if (BLO_decrypt->streamHeader) free(BLO_decrypt->streamHeader);
+ if (BLO_decrypt->deCryptKey) free(BLO_decrypt->deCryptKey);
+ free(BLO_decrypt);
+ return err;
+ }
+
+ if (BLO_decrypt->datacrc == BLO_decrypt->streamHeader->datacrc) {
+#ifndef NDEBUG
+ fprintf(GEN_errorstream, "Crypted data CRC is correct\n");
+#endif
+ } else {
+#ifndef NDEBUG
+ fprintf(GEN_errorstream, "Crypted data CRC is NOT correct\n");
+#endif
+ err = BRS_SETFUNCTION(BRS_DECRYPT) |
+ BRS_SETGENERR(BRS_CRCDATA);
+ if (BLO_decrypt->streamGlue) free(BLO_decrypt->streamGlue);
+ if (BLO_decrypt->streamHeader) free(BLO_decrypt->streamHeader);
+ if (BLO_decrypt->deCryptKey) free(BLO_decrypt->deCryptKey);
+ free(BLO_decrypt);
+ return err;
+ }
+
+ free(BLO_decrypt->streamGlue);
+ free(BLO_decrypt->streamHeader);
+ free(BLO_decrypt->deCryptKey);
+ free(BLO_decrypt);
+
+ return err;
+}
+
diff --git a/source/blender/decrypt/intern/Makefile b/source/blender/decrypt/intern/Makefile
new file mode 100644
index 00000000000..1fcb7e5f9ee
--- /dev/null
+++ b/source/blender/decrypt/intern/Makefile
@@ -0,0 +1,61 @@
+#
+# $Id$
+#
+# ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version. The Blender
+# Foundation also sells licenses for use in proprietary software under
+# the Blender License. See http://www.blender.org/BL/ for information
+# about this.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2001-2002 by 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 = decrypt
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+ifeq ($(OS),$(findstring $(OS), "beos darwin freebsd linux openbsd solaris windows"))
+ CFLAGS += -funsigned-char
+endif
+
+CFLAGS += $(LEVEL_2_C_WARNINGS)
+
+# path to our own external headerfiles
+CPPFLAGS += -I..
+
+# external modules
+CPPFLAGS += -I../../../kernel/gen_messaging
+CPPFLAGS += -I../../readstreamglue
+
+# ugly hack for decrypt/pubkey
+CPPFLAGS += -I../../writestreamglue
+
+CPPFLAGS += -I$(NAN_OPENSSL)/include
+CPPFLAGS += -I$(NAN_BLENKEY)/include
+
+ifeq ($(OS),$(findstring $(OS), "solaris windows"))
+ CPPFLAGS += -I$(NAN_ZLIB)/include
+endif
+
diff --git a/source/blender/decrypt/stub/BLO_decryptSTUB.c b/source/blender/decrypt/stub/BLO_decryptSTUB.c
new file mode 100644
index 00000000000..62d78bfd983
--- /dev/null
+++ b/source/blender/decrypt/stub/BLO_decryptSTUB.c
@@ -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 *****
+ * decrypt STUB
+ */
+
+#include <stdio.h>
+
+#include "GEN_messaging.h"
+
+#include "BLO_readStreamErrors.h"
+#include "BLO_decrypt.h"
+
+ BLO_decryptStructHandle
+BLO_decrypt_begin(
+ void *endControl)
+{
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "Error BLO_decrypt_begin is a stub\n");
+#endif
+ return (NULL);
+}
+
+ int
+BLO_decrypt_process(
+ BLO_decryptStructHandle BLO_decryptHandle,
+ unsigned char *data,
+ unsigned int dataIn)
+{
+ int err = 0;
+ BLO_decryptHandle = NULL;
+ data = NULL;
+ dataIn = 0;
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "Error BLO_decrypt_process is a stub\n");
+#endif
+ err = BRS_SETFUNCTION(BRS_DECRYPT) |
+ BRS_SETGENERR(BRS_STUB);
+ return (err);
+}
+
+ int
+BLO_decrypt_end(
+ BLO_decryptStructHandle BLO_decryptHandle)
+{
+ int err = 0;
+ BLO_decryptHandle = NULL;
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "Error BLO_decrypt_end is a stub\n");
+#endif
+ err = BRS_SETFUNCTION(BRS_DECRYPT) |
+ BRS_SETGENERR(BRS_STUB);
+ return (err);
+}
+
diff --git a/source/blender/decrypt/stub/Makefile b/source/blender/decrypt/stub/Makefile
new file mode 100644
index 00000000000..61c601a5182
--- /dev/null
+++ b/source/blender/decrypt/stub/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 *****
+#
+#
+
+LIBNAME = decryptSTUB
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+ifeq ($(OS),$(findstring $(OS), "beos darwin freebsd linux openbsd solaris windows"))
+ CFLAGS += -funsigned-char
+endif
+
+CFLAGS += $(LEVEL_2_C_WARNINGS)
+
+# path to our own external headerfiles
+CPPFLAGS += -I..
+CPPFLAGS += -I../../readstreamglue
+
+# external modules
+CPPFLAGS += -I../../../kernel/gen_messaging
+
diff --git a/source/blender/deflate/BLO_deflate.h b/source/blender/deflate/BLO_deflate.h
new file mode 100644
index 00000000000..8ff664d88d4
--- /dev/null
+++ b/source/blender/deflate/BLO_deflate.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 *****
+ * zlib deflate compression wrapper library interface
+ */
+
+#ifndef BLO_DEFLATE_H
+#define BLO_DEFLATE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * zlib deflate dataprocessor wrapper
+ * @param data Pointer to raw input data
+ * @param dataIn Raw data input amount
+ * @param streamGlueHeader Our streamGlueHeaderStruct
+ * @retval streamGlueWrite return value
+ */
+ int
+BLO_deflate(
+ unsigned char *data,
+ unsigned int dataIn,
+ struct streamGlueHeaderStruct *streamGlueHeader);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BLO_DEFLATE_H */
diff --git a/source/blender/deflate/Makefile b/source/blender/deflate/Makefile
new file mode 100644
index 00000000000..397f72614c9
--- /dev/null
+++ b/source/blender/deflate/Makefile
@@ -0,0 +1,39 @@
+#
+# $Id$
+#
+# ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version. The Blender
+# Foundation also sells licenses for use in proprietary software under
+# the Blender License. See http://www.blender.org/BL/ for information
+# about this.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2001-2002 by 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.
+#
+
+SOURCEDIR = source/blender/deflate
+DIRS = intern
+TESTDIRS = test
+
+include nan_subdirs.mk
diff --git a/source/blender/deflate/intern/BLO_deflate.c b/source/blender/deflate/intern/BLO_deflate.c
new file mode 100644
index 00000000000..407b4f77c3a
--- /dev/null
+++ b/source/blender/deflate/intern/BLO_deflate.c
@@ -0,0 +1,210 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * zlib deflate compression wrapper library
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "zlib.h"
+
+#include "GEN_messaging.h"
+
+#include "BLO_writeStreamGlue.h"
+#include "BLO_deflate.h"
+#include "BLO_in_de_flateHeader.h"
+
+// TODO use other error function
+static int CHECK_ERR(int err, char *msg);
+
+static int CHECK_ERR(int err, char *msg) {
+ if (err != Z_OK) {
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "%s error: %d\n",
+ msg,
+ err);
+#endif
+ return 1;
+ }
+ return 0;
+}
+
+ int
+BLO_deflate(
+ unsigned char *data,
+ unsigned int dataIn,
+ struct streamGlueHeaderStruct *streamGlueHeader)
+{
+ int zlib_err; /* zlib error */
+ int err = 0; /* our own error */
+ z_stream c_stream; /* compression stream */
+ char dictionary[50];
+ Bytef *compressBuf; /* minimally sized output buffer for deflate */
+ uInt compressSize; /* minimally sized compressBuf size in bytes */
+ struct writeStreamGlueStruct *streamGlue = NULL;
+ struct BLO_in_de_flateHeaderStruct BLO_in_de_flateHeader;
+ char* errmsg1 = "deflateInit";
+ char* errmsg2 = "deflateSetDictionary";
+ char* errmsg3 = "deflateEnd";
+
+ // TODO use dictionary index, this is id = 1 :
+ strcpy(dictionary, "sure this is not a number");
+
+ compressSize = (dataIn * 1.1) + 12;
+ compressBuf = (Bytef *)malloc(compressSize);
+ if (!compressBuf) {
+ err = BWS_SETFUNCTION(BWS_DEFLATE) |
+ BWS_SETGENERR(BWS_MALLOC);
+ return err;
+ }
+
+ c_stream.next_out = compressBuf;
+ c_stream.avail_out = compressSize;
+ c_stream.next_in = data;
+ c_stream.avail_in = dataIn;
+
+ c_stream.zalloc = (alloc_func)0;
+ c_stream.zfree = (free_func)0;
+ c_stream.opaque = (voidpf)0;
+
+ zlib_err = deflateInit(&c_stream, Z_BEST_COMPRESSION);
+ if (CHECK_ERR(zlib_err, errmsg1)) {
+ err = BWS_SETFUNCTION(BWS_DEFLATE) |
+ BWS_SETSPECERR(BWS_DEFLATEERROR);
+ free(compressBuf);
+ return err;
+ }
+
+ zlib_err = deflateSetDictionary(&c_stream,
+ (const Bytef*)dictionary,
+ strlen(dictionary));
+ if (CHECK_ERR(zlib_err, errmsg2)) {
+ err = BWS_SETFUNCTION(BWS_DEFLATE) |
+ BWS_SETSPECERR(BWS_DEFLATEERROR);
+ free(compressBuf);
+ return err;
+ }
+
+ // Compress it
+ zlib_err = deflate(&c_stream, Z_FINISH);
+ if (zlib_err != Z_STREAM_END) {
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "deflate should report Z_STREAM_END\n");
+#endif
+ // (avail_out == 0) possibility ? Should not, because we
+ // malloc by the minimal needed amount rule
+ err = BWS_SETFUNCTION(BWS_DEFLATE) |
+ BWS_SETSPECERR(BWS_DEFLATEERROR);
+ free(compressBuf);
+ return err;
+ }
+
+ zlib_err = deflateEnd(&c_stream);
+ if (CHECK_ERR(zlib_err, errmsg3)) {
+ err = BWS_SETFUNCTION(BWS_DEFLATE) |
+ BWS_SETSPECERR(BWS_DEFLATEERROR);
+ free(compressBuf);
+ return err;
+ }
+
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "BLO_deflate compressed %ld bytes to %ld (%.0f%%)\n",
+ c_stream.total_in, c_stream.total_out,
+ 100. * (float)c_stream.total_out / (float)c_stream.total_in);
+
+ fprintf(GEN_errorstream,
+ "BLO_deflate writes streamGlueHeader of %u bytes\n",
+ STREAMGLUEHEADERSIZE);
+#endif
+ // Update streamGlueHeader that initiated us and write it away
+ streamGlueHeader->totalStreamLength =
+ htonl(IN_DE_FLATEHEADERSTRUCTSIZE + c_stream.total_out);
+ streamGlueHeader->crc = htonl(crc32(0L, (const Bytef *) streamGlueHeader,
+ STREAMGLUEHEADERSIZE - 4));
+ err = writeStreamGlue(
+ Global_streamGlueControl,
+ &streamGlue,
+ (unsigned char *) streamGlueHeader,
+ STREAMGLUEHEADERSIZE,
+ 0);
+ if (err) {
+ free(compressBuf);
+ return err;
+ }
+
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "BLO_deflate writes BLO_in_de_flateHeader of %u bytes\n",
+ IN_DE_FLATEHEADERSTRUCTSIZE);
+#endif
+
+ // write out our header
+ BLO_in_de_flateHeader.magic = 'B';
+ BLO_in_de_flateHeader.compressedLength = htonl(c_stream.total_out);
+ BLO_in_de_flateHeader.uncompressedLength = htonl(c_stream.total_in);
+ BLO_in_de_flateHeader.dictionary_id = htonl(1);
+ BLO_in_de_flateHeader.dictId = htonl(c_stream.adler); // adler checksum
+ BLO_in_de_flateHeader.crc = htonl(crc32(0L,
+ (const Bytef *) &BLO_in_de_flateHeader, IN_DE_FLATEHEADERSTRUCTSIZE-4));
+ err = writeStreamGlue(
+ Global_streamGlueControl,
+ &streamGlue,
+ (unsigned char *) &BLO_in_de_flateHeader,
+ IN_DE_FLATEHEADERSTRUCTSIZE,
+ 0);
+ if (err) {
+ free(compressBuf);
+ return err;
+ }
+
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "BLO_deflate writes %lu bytes raw data (total %lu)\n",
+ c_stream.total_out, STREAMGLUEHEADERSIZE +
+ IN_DE_FLATEHEADERSTRUCTSIZE + c_stream.total_out);
+#endif
+
+ // finally write all compressed data
+ err = writeStreamGlue(
+ Global_streamGlueControl,
+ &streamGlue,
+ (unsigned char *) compressBuf,
+ c_stream.total_out,
+ 1);
+
+ free(compressBuf);
+
+ return err;
+}
+
diff --git a/source/blender/deflate/intern/Makefile b/source/blender/deflate/intern/Makefile
new file mode 100644
index 00000000000..b6811f2d130
--- /dev/null
+++ b/source/blender/deflate/intern/Makefile
@@ -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 *****
+#
+#
+
+LIBNAME = deflate
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+ifeq ($(OS),$(findstring $(OS), "beos darwin freebsd linux openbsd solaris windows"))
+ CFLAGS += -funsigned-char
+endif
+
+CFLAGS += $(LEVEL_2_C_WARNINGS)
+
+# path to our own external headerfiles
+CPPFLAGS += -I..
+
+# external modules
+CPPFLAGS += -I../../../kernel/gen_messaging
+CPPFLAGS += -I../../writestreamglue
+CPPFLAGS += -I../../readstreamglue
+CPPFLAGS += -I../../inflate
+
+ifeq ($(OS),$(findstring $(OS), "solaris windows"))
+ CPPFLAGS += -I$(NAN_ZLIB)/include
+endif
+
diff --git a/source/blender/deflate/stub/BLO_deflateSTUB.c b/source/blender/deflate/stub/BLO_deflateSTUB.c
new file mode 100644
index 00000000000..cb6323dfd3e
--- /dev/null
+++ b/source/blender/deflate/stub/BLO_deflateSTUB.c
@@ -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 *****
+ * zlib deflate compression library stub
+ */
+
+#include <stdio.h>
+
+#include "GEN_messaging.h"
+#include "BLO_streamglue.h"
+#include "BLO_deflate.h"
+
+ int
+BLO_deflate(
+ unsigned char *data,
+ unsigned int dataIn,
+ struct streamGlueHeaderStruct *streamGlueHeader)
+{
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "Error BLO_deflate is a stub");
+#endif
+ return(NULL);
+}
+
diff --git a/source/blender/deflate/stub/Makefile b/source/blender/deflate/stub/Makefile
new file mode 100644
index 00000000000..55f3211e2c9
--- /dev/null
+++ b/source/blender/deflate/stub/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 *****
+#
+#
+
+LIBNAME = deflateSTUB
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+ifeq ($(OS),$(findstring $(OS), "beos darwin freebsd linux openbsd solaris windows"))
+ CFLAGS += -funsigned-char
+endif
+
+CFLAGS += $(LEVEL_2_C_WARNINGS)
+
+# path to our own external headerfiles
+CPPFLAGS += -I..
+
+# external modules
+CPPFLAGS += -I../../../kernel/gen_messaging
+CPPFLAGS += -I../../streamglue
+
+ifeq ($(OS),$(findstring $(OS), "solaris windows"))
+ CPPFLAGS += -I$(NAN_ZLIB)/include
+endif
+
diff --git a/source/blender/deflate/test/Makefile b/source/blender/deflate/test/Makefile
new file mode 100644
index 00000000000..25116d51f5c
--- /dev/null
+++ b/source/blender/deflate/test/Makefile
@@ -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 *****
+#
+# Bounces make to subdirectories.
+
+SOURCEDIR = source/blender/deflate/test
+DIRS = stubbed
+
+include nan_subdirs.mk
diff --git a/source/blender/deflate/test/stubbed/Makefile b/source/blender/deflate/test/stubbed/Makefile
new file mode 100644
index 00000000000..e8b597f068d
--- /dev/null
+++ b/source/blender/deflate/test/stubbed/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 *****
+#
+# Make a little test for the sys_types replacement.
+#
+
+DIR = $(OCGDIR)/blender/deflate/test
+ALLTARGETS = $(DIR)/stubbed_test
+
+include nan_compile.mk
+
+CFLAGS += -funsigned-char
+
+# this module's header
+CPPFLAGS += -I../..
+
+# external headers
+CPPFLAGS += -I../../../readstreamglue
+CPPFLAGS += -I../../../writestreamglue
+
+#################################################################
+# libs
+TESTLIBS = $(OCGDIR)/blender/deflate/$(DEBUG_DIR)libdeflate.a
+TESTLIBS += $(OCGDIR)/blender/writestreamglueSTUB/$(DEBUG_DIR)libwritestreamglueSTUB.a
+TESTLIBS += $(OCGDIR)/kernel/gen_messaging/$(DEBUG_DIR)libgen_messaging.a
+
+ifeq ($(OS),$(findstring $(OS), "freebsd linux"))
+ TESTLIBS += -lz
+endif
+
+ifeq ($(OS),windows)
+ TESTLIBS += ws2_32.lib
+ TESTLIBS += $(NAN_ZLIB)/lib/libz.a
+endif
+
+# There's hardly anything to debug here, so forget about it.
+$(DIR)/stubbed_test: $(OBJS)
+ $(CC) $(OBJS) $(TESTLIBS) -o $(DIR)/stubbed_test
+
+clean::
+ $(RM) $(DIR)/stubbed_test
+
+test:: $(DIR)/stubbed_test
+ $(DIR)/stubbed_test $(NAN_TEST_VERBOSITY)
diff --git a/source/blender/deflate/test/stubbed/stubbed.c b/source/blender/deflate/test/stubbed/stubbed.c
new file mode 100644
index 00000000000..9984676e9f6
--- /dev/null
+++ b/source/blender/deflate/test/stubbed/stubbed.c
@@ -0,0 +1,203 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/*
+ * Unit test for the deflater
+ *
+ * The deflater compresses data, using the zlib compression
+ * library. The BLO_deflate module wraps this. It writes the
+ * compressed data as well.
+ *
+ * Tested functions
+ *
+ * - BLO_deflate (from BLO_deflate.h)
+ *
+ * Commandline arguments: <verbosity>
+ * verbosity: 0 - print nothing
+ * 1 - print the results only
+ * 2 - print everything
+ *
+ * */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "BLO_deflate.h"
+#include "BLO_writeStreamGlue.h"
+
+struct streamGlueControlStruct *Global_streamGlueControl;
+
+void printStreamGlueHeader(struct streamGlueHeaderStruct *s)
+{
+ int i = 0;
+ char* c;
+
+ fprintf(stderr,"| |- streamGlueHeader: %p\n",
+ s);
+ fprintf(stderr,"| |- magic: %c\n",
+ s->magic);
+ fprintf(stderr,"| |- totalStreamLength: %x hex (%x reversed),"
+ " %d dec (%d reversed)\n",
+ s->totalStreamLength,
+ ntohl(s->totalStreamLength),
+ s->totalStreamLength,
+ ntohl(s->totalStreamLength));
+ fprintf(stderr,"| |- dataProcessorType: %d (%d reversed)\n",
+ s->dataProcessorType,
+ ntohl(s->dataProcessorType));
+ fprintf(stderr,"| |- crc: %x hex, (%d dec)\n",
+ s->crc,
+ s->crc);
+ fprintf(stderr,"|\n");
+ fprintf(stderr,"|-- Memory dump (starting at %p):", s);
+ c = (char*) s;
+ for(i = 0; i < STREAMGLUEHEADERSIZE; i+=4, c+=4)
+ fprintf(stderr,"%02x%02x%02x%02x-",
+ *c,
+ *(c+1) ,
+ *(c+2),
+ *(c+3) );
+ fprintf(stderr,"\n|\n");
+
+}
+
+
+
+int main (int argc, char *argv[])
+{
+ int verbose = 0;
+ int error_status = 0;
+ int retval = 0;
+ struct streamGlueHeaderStruct *streamGlueHeader;
+ int datachunksize = 12345;
+ char* datachunk = NULL;
+ int i = 0;
+ char* dataptr = NULL;
+ int sghsize = 0;
+
+ switch (argc) {
+ case 2:
+ verbose = atoi(argv[1]);
+ if (verbose < 0) verbose = 0;
+ break;
+ case 1:
+ default:
+ verbose = 0;
+ }
+
+ /* ----------------------------------------------------------------- */
+ if (verbose > 0) {
+ fprintf(stderr,"\n*** Deflate test with stubs\n|\n");
+ }
+ /* ----------------------------------------------------------------- */
+ /* We need:
+ * 1 - a data chunk
+ * 2 - the bytecount
+ * 3 - a streamglueheader
+ * The streamglueheader contains some stats about the datachunk.
+ */
+
+ /* because of stupid lib dependencies. */
+ Global_streamGlueControl = streamGlueControlConstructor();
+
+
+ /* 2: the size */
+ datachunksize = 12345;
+
+ /* 1: a data chunk. We fill it with some numbers */
+ datachunk = (char*) malloc(datachunksize);
+
+ /* an ascending-ish thingy */
+ dataptr = datachunk;
+ for (i = 0 ;
+ i < datachunksize;
+ i++, dataptr++) {
+ *dataptr = (i % 0xFF);
+ }
+
+ /* 3: the streamglue header */
+ sghsize = STREAMGLUEHEADERSIZE;
+ if (verbose > 1) {
+ fprintf(stderr,"|-- Allocating %d bytes for the header.\n",
+ sghsize);
+ }
+ streamGlueHeader = malloc(sghsize);
+ streamGlueHeader->magic = 'A';
+ streamGlueHeader->totalStreamLength = 0;
+ streamGlueHeader->dataProcessorType =
+ htonl(0x2);
+ streamGlueHeader->crc = 0;
+
+
+ if (verbose > 1) {
+ fprintf(stderr,"|\n");
+ fprintf(stderr,"|-- Will call BLO_deflate with args:\n");
+ fprintf(stderr,"| |- datachunk pointing to %p\n",
+ datachunk);
+ fprintf(stderr,"| |- datachunksize: %d\n",
+ datachunksize);
+ printStreamGlueHeader(streamGlueHeader);
+ fprintf(stderr,"| \n");
+ }
+
+ retval =
+ BLO_deflate(
+ datachunk,
+ datachunksize,
+ streamGlueHeader);
+
+ if (verbose > 1) {
+ fprintf(stderr,"|-- BLO_deflate returned %d \n", retval);
+ }
+
+ if (verbose > 1) {
+ fprintf(stderr,"|\n");
+ fprintf(stderr,"|-- Arguments are now:\n");
+ fprintf(stderr,"|-- Will call BLO_deflate with args:\n");
+ fprintf(stderr,"| |- datachunk pointing to %p\n",
+ datachunk);
+ fprintf(stderr,"| |- datachunksize: %d\n",
+ datachunksize);
+ printStreamGlueHeader(streamGlueHeader);
+ fprintf(stderr,"| \n");
+ }
+
+
+ /* ----------------------------------------------------------------- */
+ if (verbose > 0) {
+ fprintf(stderr,"|\n*** Finished test\n\n");
+ }
+ exit(error_status);
+}
+
+/* eof */
diff --git a/source/blender/encrypt/BLO_encrypt.h b/source/blender/encrypt/BLO_encrypt.h
new file mode 100644
index 00000000000..d9d2fdd396a
--- /dev/null
+++ b/source/blender/encrypt/BLO_encrypt.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 *****
+ */
+
+#ifndef BLO_ENCRYPT_H
+#define BLO_ENCRYPT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ int
+BLO_encrypt(
+ unsigned char *data,
+ unsigned int dataIn,
+ struct streamGlueHeaderStruct *streamGlueHeader);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BLO_ENCRYPT_H */
diff --git a/source/blender/encrypt/Makefile b/source/blender/encrypt/Makefile
new file mode 100644
index 00000000000..4dbd71af099
--- /dev/null
+++ b/source/blender/encrypt/Makefile
@@ -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 *****
+#
+# Bounces make to subdirectories.
+
+SOURCEDIR = source/blender/encrypt
+DIRS = intern
+
+include nan_subdirs.mk
diff --git a/source/blender/encrypt/intern/BLO_encrypt.c b/source/blender/encrypt/intern/BLO_encrypt.c
new file mode 100644
index 00000000000..ecea0d5fc14
--- /dev/null
+++ b/source/blender/encrypt/intern/BLO_encrypt.c
@@ -0,0 +1,229 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * openssl/crypt rc4 crypto wrapper library
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef _WIN32
+#include <winsock2.h>
+#include <windows.h>
+#endif
+
+#include "openssl/rc4.h"
+#include "openssl/rand.h"
+#include "openssl/rsa.h"
+#include "zlib.h"
+
+#include "GEN_messaging.h"
+
+#include "BLO_keyStore.h"
+#include "BLO_writeStreamGlue.h"
+#include "BLO_en_de_cryptHeader.h"
+#include "BLO_encrypt.h"
+
+ int
+BLO_encrypt(
+ unsigned char *data,
+ unsigned int dataIn,
+ struct streamGlueHeaderStruct *streamGlueHeader)
+{
+ int err = 0;
+ struct writeStreamGlueStruct *streamGlue = NULL;
+ struct BLO_en_de_cryptHeaderStruct BLO_en_de_cryptHeader;
+ RC4_KEY *rc4_key;
+ unsigned char *cryptBuf = NULL;
+ byte *pubKey, *privKey;
+ int pubKeyLen, privKeyLen;
+ int cryptKeyLen = 16;
+ int cryptedKeyLen;
+ byte cryptKey[16]; // FIXME cryptKeyLen];
+ RSA *rsa = NULL;
+ byte *cryptedKey;
+ static unsigned char rsa_e[] = "\x01\x00\x01";
+
+ cryptBuf = malloc(dataIn);
+ if (!cryptBuf) {
+ err = BWS_SETFUNCTION(BWS_ENCRYPT) |
+ BWS_SETGENERR(BWS_MALLOC);
+ return err;
+ }
+
+ rc4_key = malloc(sizeof(RC4_KEY));
+ if (!rc4_key) {
+ err = BWS_SETFUNCTION(BWS_ENCRYPT) |
+ BWS_SETGENERR(BWS_MALLOC);
+ free(cryptBuf);
+ return err;
+ }
+
+#ifdef _WIN32
+ RAND_screen();
+#endif
+ RAND_bytes(cryptKey, cryptKeyLen);
+
+ RC4_set_key(rc4_key, cryptKeyLen, cryptKey);
+ RC4(rc4_key, dataIn, data, cryptBuf);
+
+ free(rc4_key);
+
+ // Update streamGlueHeader that initiated us and write it away
+ streamGlueHeader->totalStreamLength =
+ htonl(EN_DE_CRYPTHEADERSTRUCTSIZE + dataIn);
+ streamGlueHeader->crc = htonl(crc32(0L,
+ (const Bytef *) streamGlueHeader, STREAMGLUEHEADERSIZE - 4));
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "BLO_encrypt writes streamGlueHeader of %u bytes\n",
+ STREAMGLUEHEADERSIZE);
+#endif
+
+ err = writeStreamGlue(
+ Global_streamGlueControl,
+ &streamGlue,
+ (unsigned char *)streamGlueHeader,
+ STREAMGLUEHEADERSIZE,
+ 0);
+ if (err) {
+ free(cryptBuf);
+ return err;
+ }
+
+ pubKeyLen = keyStoreGetPubKey(&pubKey);
+ privKeyLen = keyStoreGetPrivKey(&privKey);
+ if ((pubKeyLen == 0) || (privKeyLen == 0)) {
+ err = BWS_SETFUNCTION(BWS_ENCRYPT) |
+ BWS_SETGENERR(BWS_RSA);
+ free(cryptBuf);
+ return err;
+ }
+
+ rsa = RSA_new();
+ if (rsa == NULL) {
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "Error in RSA_new\n");
+#endif
+ err = BWS_SETFUNCTION(BWS_ENCRYPT) |
+ BWS_SETSPECERR(BWS_RSANEWERROR);
+ free(cryptBuf);
+ return err;
+ }
+ // static exponent
+ rsa->e = BN_bin2bn(rsa_e, sizeof(rsa_e)-1, rsa->e);
+
+ // public part into rsa->n
+ rsa->n = BN_bin2bn(pubKey, pubKeyLen, rsa->n);
+
+ // private part into rsa->d
+ rsa->d = BN_bin2bn(privKey, privKeyLen, rsa->d);
+
+ //DEBUG RSA_print_fp(stdout, rsa, 0);
+
+ cryptedKey = malloc(RSA_size(rsa) * sizeof(byte));
+ if (!cryptedKey) {
+ err = BWS_SETFUNCTION(BWS_ENCRYPT) |
+ BWS_SETGENERR(BWS_MALLOC);
+ free(cryptBuf);
+ RSA_free(rsa);
+ return err;
+ }
+
+ // crypt the cryptkey
+ cryptedKeyLen = RSA_private_encrypt(cryptKeyLen, cryptKey, cryptedKey,
+ rsa, RSA_PKCS1_PADDING);
+ if (cryptedKeyLen == -1) {
+ // TODO real error handling
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "Error in RSA_private_encrypt\n");
+#endif
+ err = BWS_SETFUNCTION(BWS_ENCRYPT) |
+ BWS_SETSPECERR(BWS_ENCRYPTERROR);
+ free(cryptBuf);
+ free(cryptedKey);
+ RSA_free(rsa);
+ return err;
+ }
+
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "BLO_encrypt writes BLO_en_de_cryptHeader of %u bytes\n",
+ EN_DE_CRYPTHEADERSTRUCTSIZE);
+#endif
+
+ // write out our header
+ BLO_en_de_cryptHeader.magic = 'A';
+ BLO_en_de_cryptHeader.length = htonl(dataIn);
+ memcpy(BLO_en_de_cryptHeader.pubKey, pubKey, pubKeyLen);
+ BLO_en_de_cryptHeader.pubKeyLen = htonl(pubKeyLen);
+ memcpy(BLO_en_de_cryptHeader.cryptedKey, cryptedKey, cryptedKeyLen);
+ BLO_en_de_cryptHeader.cryptedKeyLen = htonl(cryptedKeyLen);
+ BLO_en_de_cryptHeader.datacrc = htonl(crc32(0L,
+ (const Bytef *) cryptBuf, dataIn));
+ BLO_en_de_cryptHeader.headercrc = htonl(crc32(0L,
+ (const Bytef *) &BLO_en_de_cryptHeader, EN_DE_CRYPTHEADERSTRUCTSIZE-4));
+ err = writeStreamGlue(
+ Global_streamGlueControl,
+ &streamGlue,
+ (unsigned char *) &BLO_en_de_cryptHeader,
+ EN_DE_CRYPTHEADERSTRUCTSIZE,
+ 0);
+ if (err) {
+ free(cryptBuf);
+ free(cryptedKey);
+ RSA_free(rsa);
+ return err;
+ }
+
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "BLO_encrypt writes %u bytes raw data (total %u)\n",
+ dataIn,
+ STREAMGLUEHEADERSIZE + EN_DE_CRYPTHEADERSTRUCTSIZE + dataIn);
+#endif
+
+ // finally write all crypted data
+ err = writeStreamGlue(
+ Global_streamGlueControl,
+ &streamGlue,
+ (unsigned char *) cryptBuf,
+ dataIn,
+ 1);
+
+ free(cryptBuf);
+ free(cryptedKey);
+ RSA_free(rsa);
+
+ return err;
+}
+
diff --git a/source/blender/encrypt/intern/Makefile b/source/blender/encrypt/intern/Makefile
new file mode 100644
index 00000000000..0c8bab4f2ab
--- /dev/null
+++ b/source/blender/encrypt/intern/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 *****
+#
+#
+
+LIBNAME = encrypt
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+ifeq ($(OS),$(findstring $(OS), "beos darwin freebsd linux openbsd solaris windows"))
+ CFLAGS += -funsigned-char
+endif
+
+CFLAGS += $(LEVEL_2_C_WARNINGS)
+
+# path to our own external headerfiles
+CPPFLAGS += -I..
+
+# external modules
+CPPFLAGS += -I../../../kernel/gen_messaging
+CPPFLAGS += -I../../writestreamglue
+CPPFLAGS += -I../../readstreamglue
+CPPFLAGS += -I../../decrypt
+
+CPPFLAGS += -I$(NAN_OPENSSL)/include
+CPPFLAGS += -I$(NAN_BLENKEY)/include
+
+ifeq ($(OS),$(findstring $(OS), "solaris windows"))
+ CPPFLAGS += -I$(NAN_ZLIB)/include
+endif
+
diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h
new file mode 100644
index 00000000000..ec10c9b39ed
--- /dev/null
+++ b/source/blender/imbuf/IMB_imbuf.h
@@ -0,0 +1,479 @@
+/**
+ * @mainpage IMB - Imbuf module external interface
+ *
+ * @section about About the IMB module
+ *
+ * External interface of the IMage Buffer module. This module offers
+ * import/export of several graphical file formats. It offers the
+ * ImBuf type as a common structure to refer to different graphical
+ * file formats, and to enable a uniform way of handling them.
+ *
+ * @section issues Known issues with IMB
+ *
+ * - imbuf is written in C.
+ * - Endianness issues are dealt with internally.
+ * - File I/O must be done externally. The module uses FILE*'s to
+ * direct input/output.
+ * - Platform dependency is limited. Some minor patches for
+ * amiga and Irix are present. A 'posix-compliancy-patch'
+ * provides the interface to windows.
+ *
+ * @section dependencies Dependencies
+ *
+ * IMB needs:
+ * - SDNA module
+ * The listbase types are used for handling the memory
+ * management.
+ * - blenlib module
+ * blenlib handles guarded memory management in blender-style.
+ * BLI_winstuff.h makes a few windows specific behaviours
+ * posix-compliant.
+ * - avi
+ * avi defines import/export to the avi format. Only anim.c
+ * needs this. It uses the following functions:
+ * - avi_close
+ * - avi_is_avi
+ * - avi_print_error
+ * - avi_open_movie
+ * - avi_read_frame
+ * - avi_get_stream
+ * Additionally, it needs the types from the avi module.
+ * - external jpeg library
+ * The jpeg lib defines import/export to the jpeg format.
+ * only jpeg.c needs these. Used functions are:
+ * - jpeg_destroy
+ * - jpeg_resync_to_restart
+ * - jpeg_set_marker_processor
+ * - jpeg_read_header
+ * - jpeg_start_decompress
+ * - jpeg_abort_decompress
+ * - jpeg_read_scanlines
+ * - jpeg_finish_decompress
+ * - jpeg_std_error
+ * - jpeg_create_decompress
+ * - jpeg_stdio_src
+ * - jpeg_start_compress
+ * - jpeg_write_marker
+ * - jpeg_write_scanlines
+ * - jpeg_finish_compress
+ * - jpeg_create_compress
+ * - jpeg_stdio_dest
+ * - jpeg_set_defaults
+ * - jpeg_set_quality
+ * - jpeg_destroy_compress
+ * Additionally, it needs the types from the jpeg lib.
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 IMB_IMBUF_H
+#define IMB_IMBUF_H
+
+struct ImBuf;
+struct anim;
+
+/**
+ *
+ * @attention Defined in cmap.c
+ */
+void cspace(struct ImBuf *ibuf, float mat[][4]);
+
+/**
+ *
+ * @attention Defined in cmap.c
+ */
+void IMB_freeImBufdata(void);
+
+/**
+ *
+ * @attention Defined in cmap.c
+ */
+void IMB_applycmap(struct ImBuf *ibuf);
+
+/**
+ *
+ * @attention Defined in cmap.c
+ */
+short IMB_converttocmap(struct ImBuf *ibuf);
+
+/**
+ *
+ * @attention Defined in cmap.c
+ */
+int IMB_alpha_to_col0(int new);
+
+/**
+ *
+ * @attention Defined in readimage.c
+ */
+struct ImBuf *IMB_ibImageFromMemory(int *mem, int size, int flags);
+
+/**
+ *
+ * @attention Defined in readimage.c
+ */
+struct ImBuf *IMB_testiffname(char *naam,int flags);
+
+/**
+ *
+ * @attention Defined in readimage.c
+ */
+struct ImBuf *IMB_loadiffname(char *naam, int flags);
+
+/**
+ *
+ * @attention Defined in readimage.c
+ */
+void freezbufImBuf(struct ImBuf * ibuf);
+
+/**
+ *
+ * @attention Defined in allocimbuf.c
+ */
+void IMB_freeImBuf(struct ImBuf * ibuf);
+
+/**
+ *
+ * @attention Defined in allocimbuf.c
+ */
+struct ImBuf *IMB_allocImBuf(short x, short y,
+ unsigned char d, unsigned int flags,
+ unsigned char bitmap);
+
+/**
+ *
+ * @attention Defined in allocimbuf.c
+ */
+struct ImBuf *IMB_dupImBuf(struct ImBuf *ibuf1);
+
+/**
+ *
+ * @attention Defined in allocimbuf.c
+ */
+short IMB_addzbufImBuf(struct ImBuf * ibuf);
+
+/**
+ *
+ * @attention Defined in allocimbuf.c
+ */
+void IMB_freecmapImBuf(struct ImBuf * ibuf);
+
+/**
+ *
+ * @attention Defined in rectop.c
+ */
+void IMB_rectop(struct ImBuf *dbuf,
+ struct ImBuf *sbuf,
+ int destx,
+ int desty,
+ int srcx,
+ int srcy,
+ int width,
+ int height,
+ void (*operation)(unsigned int *, unsigned int*, int, int),
+ int value);
+
+/**
+ *
+ * @attention Defined in rectop.c
+ */
+void IMB_rectoptot(struct ImBuf *dbuf,
+ struct ImBuf *sbuf,
+ void (*operation)(unsigned int *, unsigned int*, int, int),
+ int value);
+
+/**
+ *
+ * @attention Defined in rectop.c
+ */
+void IMB_rectcpy(unsigned int *drect, unsigned int *srect, int x, int dummy);
+
+/**
+ * Return the length (in frames) of the given @a anim.
+ */
+int IMB_anim_get_duration(struct anim *anim);
+
+/**
+ *
+ * @attention Defined in anim.c
+ */
+struct anim * IMB_open_anim(char * name, int ib_flags);
+void IMB_close_anim(struct anim * anim);
+
+/**
+ *
+ * @attention Defined in anim.c
+ */
+struct ImBuf * IMB_anim_absolute(struct anim * anim, int position);
+
+/**
+ *
+ * @attention Defined in anim.c
+ */
+void IMB_free_anim(struct anim * anim);
+
+/**
+ *
+ * @attention Defined in anim.c
+ */
+int IMB_isanim(char * name);
+
+/**
+ *
+ * @attention Defined in anim.c
+ */
+struct ImBuf * IMB_anim_nextpic(struct anim * anim);
+
+
+/**
+ *
+ * @attention Defined in antialias.c
+ */
+void IMB_clever_double (struct ImBuf * ibuf);
+
+/**
+ *
+ * @attention Defined in antialias.c
+ */
+void IMB_antialias(struct ImBuf * ibuf);
+
+/**
+ *
+ * @attention Defined in filter.c
+ */
+void IMB_filter(struct ImBuf *ibuf);
+
+/**
+ *
+ * @attention Defined in filter.c
+ */
+void IMB_filtery(struct ImBuf *ibuf);
+
+/**
+ *
+ * @attention Defined in scaling.c
+ */
+struct ImBuf *IMB_onehalf(struct ImBuf *ibuf1);
+
+/**
+ *
+ * @attention Defined in scaling.c
+ */
+struct ImBuf *IMB_scaleImBuf(struct ImBuf * ibuf, short newx, short newy);
+
+/**
+ *
+ * @attention Defined in scaling.c
+ */
+struct ImBuf *IMB_scalefieldImBuf(struct ImBuf *ibuf, short newx, short newy);
+
+/**
+ *
+ * @attention Defined in scaling.c
+ */
+struct ImBuf *IMB_scalefastImBuf(struct ImBuf *ibuf, short newx, short newy);
+
+/**
+ *
+ * @attention Defined in writeimage.c
+ */
+short IMB_saveiff(struct ImBuf *ibuf,char *naam,int flags);
+
+/**
+ * This function pointer needs to be initialized to enable
+ * png writing from the ImBuf library.
+ *
+ * @attention Defined in writeimage.c
+ * @attention See also IMB_png_encode()
+ */
+extern short (*IMB_fp_png_encode)(struct ImBuf *ibuf, int file, int flags);
+
+/**
+ * Encodes a png image from an ImBuf
+ *
+ * @attention Defined in png_encode.c
+ * @attention See also IMB_fp_png_encode
+ */
+short IMB_png_encode(struct ImBuf *ibuf, int file, int flags);
+
+/**
+ *
+ * @attention Defined in util.c
+ */
+int IMB_ispic(char *name);
+
+/**
+ *
+ * @attention Defined in divers.c
+ */
+void IMB_de_interlace(struct ImBuf *ibuf);
+
+/**
+ * Change the ordering of the colour bytes pointed to by rect from
+ * rgba to abgr. size * 4 colour bytes are reordered.
+ *
+ * @attention Defined in imageprocess.c
+ */
+void IMB_convert_rgba_to_abgr(int size, unsigned int *rect);
+
+/**
+ *
+ * @attention defined in scaling.c
+ */
+struct ImBuf *IMB_scalefastfieldImBuf(struct ImBuf *ibuf,
+ short newx,
+ short newy);
+
+/**
+ *
+ * @attention defined in readimage.c
+ * @deprecated Only here for backwards compatibility of the
+ * @deprecated plugin system.
+ */
+struct ImBuf *IMB_loadiffmem(int *mem, int flags);
+
+/**
+ *
+ * @attention defined in readimage.c
+ * @deprecated Only here for backwards compatibility of the
+ * @deprecated plugin system.
+ */
+struct ImBuf *IMB_loadifffile(int file, int flags);
+
+/**
+ *
+ * @attention defined in scaling.c
+ */
+struct ImBuf *IMB_half_x(struct ImBuf *ibuf1);
+
+/**
+ *
+ * @attention defined in scaling.c
+ */
+struct ImBuf *IMB_double_fast_x(struct ImBuf *ibuf1);
+
+/**
+ *
+ * @attention defined in scaling.c
+ */
+struct ImBuf *IMB_double_x(struct ImBuf *ibuf1);
+
+/**
+ *
+ * @attention defined in scaling.c
+ */
+struct ImBuf *IMB_half_y(struct ImBuf *ibuf1);
+
+/**
+ *
+ * @attention defined in scaling.c
+ */
+struct ImBuf *IMB_double_fast_y(struct ImBuf *ibuf1);
+
+/**
+ *
+ * @attention defined in scaling.c
+ */
+struct ImBuf *IMB_double_y(struct ImBuf *ibuf1);
+
+/**
+ *
+ * @attention defined in scaling.c
+ */
+struct ImBuf *IMB_onethird(struct ImBuf *ibuf1);
+
+/**
+ *
+ * @attention defined in scaling.c
+ */
+struct ImBuf *IMB_halflace(struct ImBuf *ibuf1);
+
+/**
+ *
+ * @attention defined in dither.c
+ */
+void IMB_dit2(struct ImBuf * ibuf, short ofs, short bits);
+
+/**
+ *
+ * @attention defined in dither.c
+ */
+void IMB_dit0(struct ImBuf * ibuf, short ofs, short bits);
+
+/** Externally used vars: fortunately they do not use funny types */
+
+/**
+ * boolean toggle that tells whether or not to
+ * scale the colour map in the y-direction.
+ *
+ * @attention declared in hamx.c
+ */
+extern int scalecmapY;
+
+/**
+ * This 'matrix' defines the transformation from rgb to bw colour
+ * maps. You need to do a sort of dot-product for that. It is a matrix
+ * with fixed coefficients, extracted from some book.
+ *
+ * @attention Defined in matrix.h, only included in hamx.c
+ */
+extern float rgb_to_bw[4][4];
+
+/**
+ *
+ * @attention Defined in rotate.c
+ */
+void IMB_flipy(struct ImBuf * ibuf);
+
+/**
+ *
+ * @attention Defined in anim.c
+ */
+void IMB_init_movie_pointers(void);
+
+/**
+ *
+ * @attention Defined in cspace.c
+ */
+void IMB_cspace(struct ImBuf *ibuf, float mat[][4]);
+
+/**
+ *
+ * @attention Defined in allocimbuf.c
+ */
+void IMB_freezbufImBuf(struct ImBuf * ibuf);
+
+/**
+ *
+ * @attention Defined in rectop.c
+ */
+void IMB_rectfill(unsigned int *drect, unsigned int *srect, int x, int value);
+
+#endif
diff --git a/source/blender/imbuf/IMB_imbuf_types.h b/source/blender/imbuf/IMB_imbuf_types.h
new file mode 100644
index 00000000000..f674ffaab94
--- /dev/null
+++ b/source/blender/imbuf/IMB_imbuf_types.h
@@ -0,0 +1,155 @@
+/**
+ * IMB_imbuf_types.h (mar-2001 nzc)
+ *
+ * Types needed for using the image buffer.
+ *
+ * Imbuf is external code, slightly adapted to live in the Blender
+ * context. It requires an external jpeg module, and the avi-module
+ * (also external code) in order to function correctly.
+ *
+ * This file contains types and some constants that go with them. Most
+ * are self-explanatory (e.g. IS_amiga tests whether the buffer
+ * contains an Amiga-format file).
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 IMB_IMBUF_TYPES_H
+#define IMB_IMBUF_TYPES_H
+
+#include <stdio.h> /* for size_t */
+#include "DNA_listBase.h" /* for ListBase */
+struct _AviMovie;
+struct Mdec;
+
+/* the basic imbuf type */
+
+typedef struct ImBuf{
+ short x,y; /* breedte in pixels, hoogte in scanlines */
+ short skipx; /* breedte in ints om bij volgende scanline te komen */
+ unsigned char depth; /* actieve aantal bits/bitplanes */
+ unsigned char cbits; /* aantal active bits in cmap */
+ unsigned short mincol;
+ unsigned short maxcol;
+ int type; /* 0=abgr, 1=bitplanes */
+ int ftype;
+ unsigned int *cmap; /* int array van kleuren */
+ unsigned int *rect; /* databuffer */
+ unsigned int **planes; /* bitplanes */
+ int flags;
+ int mall; /* wat is er intern gemalloced en mag weer vrijgegeven worden */
+ short xorig, yorig;
+ char name[1023];
+ char namenull;
+ int userflags;
+ int *zbuf;
+ void *userdata;
+ unsigned char *encodedbuffer;
+ unsigned int encodedsize;
+ unsigned int encodedbuffersize;
+} ImBuf;
+
+/* Moved from BKE_bmfont_types.h because it is a userflag bit mask. */
+typedef enum {
+ IB_BITMAPFONT = 1 << 0,
+ IB_BITMAPDIRTY = 1 << 1
+} ImBuf_userflagsMask;
+
+
+/* From iff.h. This was once moved away by Frank, now Nzc moves it
+ * back. Such is the way it is... It is a long list of defines, and
+ * there are a few external defines in the back. Most of the stuff is
+ * probably imbuf_intern only. This will need to be merged later
+ * on. */
+
+#define IB_rect (1 << 0)
+#define IB_planes (1 << 1)
+#define IB_cmap (1 << 2)
+
+#define IB_vert (1 << 4)
+#define IB_freem (1 << 6)
+#define IB_test (1 << 7)
+
+#define IB_ttob (1 << 8)
+#define IB_subdlta (1 << 9)
+#define IB_fields (1 << 11)
+#define IB_zbuf (1 << 13)
+
+#define IB_mem (1 << 14)
+
+#define AMI (1 << 31)
+#define PNG (1 << 30)
+#define Anim (1 << 29)
+#define TGA (1 << 28)
+#define JPG (1 << 27)
+#define BMP (1 << 26)
+
+#define RAWTGA (TGA | 1)
+
+#define JPG_STD (JPG | (0 << 8))
+#define JPG_VID (JPG | (1 << 8))
+#define JPG_JST (JPG | (2 << 8))
+#define JPG_MAX (JPG | (3 << 8))
+#define JPG_MSK (0xffffff00)
+
+#define AM_ham (0x0800 | AMI)
+#define AM_hbrite (0x0080 | AMI)
+
+#define C233 1
+#define YUVX 2
+#define HAMX 3
+#define TANX 4
+
+#define AN_c233 (Anim | C233)
+#define AN_yuvx (Anim | YUVX)
+#define AN_hamx (Anim | HAMX)
+#define AN_tanx (Anim | TANX)
+
+#define IS_amiga(x) (x->ftype & AMI)
+#define IS_ham(x) ((x->ftype & AM_ham) == AM_ham)
+#define IS_hbrite(x) ((x->ftype & AM_hbrite) == AM_hbrite)
+
+#define IS_anim(x) (x->ftype & Anim)
+#define IS_hamx(x) (x->ftype == AN_hamx)
+#define IS_tga(x) (x->ftype & TGA)
+#define IS_png(x) (x->ftype & PNG)
+#define IS_bmp(x) (x->ftype & BMP)
+
+#define IMAGIC 0732
+#define IS_iris(x) (x->ftype == IMAGIC)
+
+#define IS_jpg(x) (x->ftype & JPG)
+#define IS_stdjpg(x) ((x->ftype & JPG_MSK) == JPG_STD)
+#define IS_vidjpg(x) ((x->ftype & JPG_MSK) == JPG_VID)
+#define IS_jstjpg(x) ((x->ftype & JPG_MSK) == JPG_JST)
+#define IS_maxjpg(x) ((x->ftype & JPG_MSK) == JPG_MAX)
+
+#endif
+
diff --git a/source/blender/imbuf/Makefile b/source/blender/imbuf/Makefile
new file mode 100644
index 00000000000..66c1f06c870
--- /dev/null
+++ b/source/blender/imbuf/Makefile
@@ -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 *****
+#
+# Bounces make to subdirectories.
+
+SOURCEDIR = source/blender/imbuf
+DIRS = intern
+
+include nan_subdirs.mk
diff --git a/source/blender/imbuf/intern/IMB_allocimbuf.h b/source/blender/imbuf/intern/IMB_allocimbuf.h
new file mode 100644
index 00000000000..f67ffea35c9
--- /dev/null
+++ b/source/blender/imbuf/intern/IMB_allocimbuf.h
@@ -0,0 +1,51 @@
+/**
+ * allocimbuf.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 IMB_ALLOCIMBUF_H
+#define IMB_ALLOCIMBUF_H
+
+struct ImBuf;
+
+short imb_addrectImBuf(struct ImBuf * ibuf);
+short imb_addplanesImBuf(struct ImBuf *ibuf);
+
+short imb_addencodedbufferImBuf(struct ImBuf *ibuf);
+short imb_enlargeencodedbufferImBuf(struct ImBuf *ibuf);
+
+void imb_freerectImBuf(struct ImBuf *ibuf);
+void imb_freeplanesImBuf(struct ImBuf *ibuf);
+
+short imb_addcmapImBuf(struct ImBuf *ibuf);
+
+#endif
diff --git a/source/blender/imbuf/intern/IMB_amiga.h b/source/blender/imbuf/intern/IMB_amiga.h
new file mode 100644
index 00000000000..a801746a448
--- /dev/null
+++ b/source/blender/imbuf/intern/IMB_amiga.h
@@ -0,0 +1,44 @@
+/**
+ * IMB_amiga.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 IMB_AMIGA_H
+#define IMB_AMIGA_H
+
+struct ImBuf;
+
+struct ImBuf *imb_loadamiga(int *iffmem,int flags);
+short imb_encodebodyh(struct ImBuf *ibuf, int file);
+short imb_encodebodyv(struct ImBuf *ibuf, int file);
+
+#endif
diff --git a/source/blender/imbuf/intern/IMB_bitplanes.h b/source/blender/imbuf/intern/IMB_bitplanes.h
new file mode 100644
index 00000000000..ab21a37b774
--- /dev/null
+++ b/source/blender/imbuf/intern/IMB_bitplanes.h
@@ -0,0 +1,44 @@
+/**
+ * IMB_bitplanes.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 IMB_BITPLANES_H
+#define IMB_BITPLANES_H
+
+struct ImBuf;
+
+void imb_bptolong(struct ImBuf *ibuf);
+void imb_longtobp(struct ImBuf *ibuf);
+unsigned int **imb_copyplanelist(struct ImBuf *ibuf);
+
+#endif
diff --git a/source/blender/imbuf/intern/IMB_bmp.h b/source/blender/imbuf/intern/IMB_bmp.h
new file mode 100644
index 00000000000..572ea7043ac
--- /dev/null
+++ b/source/blender/imbuf/intern/IMB_bmp.h
@@ -0,0 +1,43 @@
+/**
+ * IMB_bmp.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 IMB_BMP_H
+#define IMB_BMP_H
+
+struct ImBuf;
+
+int imb_is_a_bmp(void *buf);
+struct ImBuf *imb_bmp_decode(unsigned char *mem, int size, int flags);
+
+#endif
diff --git a/source/blender/imbuf/intern/IMB_cmap.h b/source/blender/imbuf/intern/IMB_cmap.h
new file mode 100644
index 00000000000..71f44a8ddfe
--- /dev/null
+++ b/source/blender/imbuf/intern/IMB_cmap.h
@@ -0,0 +1,44 @@
+/**
+ * IMB_cmap.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 IMB_CMAP_H
+#define IMB_CMAP_H
+
+struct ImBuf;
+
+void imb_makecolarray(struct ImBuf *ibuf, unsigned char *mem, short nocols);
+void imb_losecmapbits(struct ImBuf *ibuf, unsigned int *coltab);
+short *imb_coldeltatab(unsigned char *coltab, short mincol, short maxcol, short cbits);
+
+#endif
diff --git a/source/blender/imbuf/intern/IMB_divers.h b/source/blender/imbuf/intern/IMB_divers.h
new file mode 100644
index 00000000000..871a4486572
--- /dev/null
+++ b/source/blender/imbuf/intern/IMB_divers.h
@@ -0,0 +1,42 @@
+/**
+ * divers.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 IMB_DIVERS_H
+#define IMB_DIVERS_H
+
+struct ImBuf;
+
+void imb_checkncols(struct ImBuf *ibuf);
+
+#endif
diff --git a/source/blender/imbuf/intern/IMB_filter.h b/source/blender/imbuf/intern/IMB_filter.h
new file mode 100644
index 00000000000..5fab0ca51da
--- /dev/null
+++ b/source/blender/imbuf/intern/IMB_filter.h
@@ -0,0 +1,42 @@
+/**
+ * filter.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 IMB_FILTER_H
+#define IMB_FILTER_H
+
+struct ImBuf;
+
+void imb_filterx(struct ImBuf *ibuf);
+
+#endif
diff --git a/source/blender/imbuf/intern/IMB_ham.h b/source/blender/imbuf/intern/IMB_ham.h
new file mode 100644
index 00000000000..87c10fee902
--- /dev/null
+++ b/source/blender/imbuf/intern/IMB_ham.h
@@ -0,0 +1,42 @@
+/**
+ * IMB_ham.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 IMB_HAM_H
+#define IMB_HAM_H
+
+struct ImBuf;
+
+short imb_converttoham(struct ImBuf *ibuf);
+
+#endif
diff --git a/source/blender/imbuf/intern/IMB_hamx.h b/source/blender/imbuf/intern/IMB_hamx.h
new file mode 100644
index 00000000000..a2b3144982a
--- /dev/null
+++ b/source/blender/imbuf/intern/IMB_hamx.h
@@ -0,0 +1,44 @@
+/**
+ * IMB_hamx.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 IMB_HAMX_H
+#define IMB_HAMX_H
+
+struct ImBuf;
+
+struct ImBuf *imb_loadanim(int *iffmem, int flags);
+short imb_enc_anim(struct ImBuf *ibuf, int file);
+void imb_convhamx(struct ImBuf *ibuf, unsigned char coltab[][4], short *deltab);
+
+#endif
diff --git a/source/blender/imbuf/intern/IMB_iff.h b/source/blender/imbuf/intern/IMB_iff.h
new file mode 100644
index 00000000000..d227ce9730d
--- /dev/null
+++ b/source/blender/imbuf/intern/IMB_iff.h
@@ -0,0 +1,43 @@
+/**
+ * IMB_iff.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 IMB_IFF_H
+#define IMB_IFF_H
+
+struct ImBuf;
+
+unsigned short imb_start_iff(struct ImBuf *ibuf, int file);
+unsigned short imb_update_iff(int file, int code);
+
+#endif
diff --git a/source/blender/imbuf/intern/IMB_iris.h b/source/blender/imbuf/intern/IMB_iris.h
new file mode 100644
index 00000000000..8515b4df40a
--- /dev/null
+++ b/source/blender/imbuf/intern/IMB_iris.h
@@ -0,0 +1,43 @@
+/**
+ * IMB_iris.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 IMB_IRIS_H
+#define IMB_IRIS_H
+
+struct ImBuf;
+
+struct ImBuf *imb_loadiris(unsigned char *mem, int flags);
+short imb_saveiris(struct ImBuf * ibuf, int file, int flags);
+
+#endif
diff --git a/source/blender/imbuf/intern/IMB_jpeg.h b/source/blender/imbuf/intern/IMB_jpeg.h
new file mode 100644
index 00000000000..645513d30e3
--- /dev/null
+++ b/source/blender/imbuf/intern/IMB_jpeg.h
@@ -0,0 +1,45 @@
+/**
+ * IMB_jpeg.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 IMB_JPEG_H
+#define IMB_JPEG_H
+
+struct ImBuf;
+struct jpeg_compress_struct;
+
+int imb_save_jpeg(char * name, struct ImBuf * ibuf, int flags);
+struct ImBuf * imb_ibJpegImageFromFilename (char * filename, int flags);
+struct ImBuf * imb_ibJpegImageFromMemory (unsigned char * buffer, int size, int flags);
+
+#endif
diff --git a/source/blender/imbuf/intern/IMB_png.h b/source/blender/imbuf/intern/IMB_png.h
new file mode 100644
index 00000000000..f7f0fd187b8
--- /dev/null
+++ b/source/blender/imbuf/intern/IMB_png.h
@@ -0,0 +1,43 @@
+/**
+ * IMB_png.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 IMB_PNG_H
+#define IMB_PNG_H
+
+struct ImBuf;
+
+int imb_is_a_png(void *buf);
+struct ImBuf *imb_png_decode(unsigned char *mem, int size, int flags);
+
+#endif
diff --git a/source/blender/imbuf/intern/IMB_targa.h b/source/blender/imbuf/intern/IMB_targa.h
new file mode 100644
index 00000000000..47d54d4140d
--- /dev/null
+++ b/source/blender/imbuf/intern/IMB_targa.h
@@ -0,0 +1,45 @@
+/**
+ * IMB_targa.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 IMB_TARGA_H
+#define IMB_TARGA_H
+
+struct ImBuf;
+
+int imb_is_a_targa(void *buf);
+
+struct ImBuf *imb_loadtarga(unsigned char *mem, int flags);
+short imb_savetarga(struct ImBuf * ibuf, int file, int flags);
+
+#endif
diff --git a/source/blender/imbuf/intern/Makefile b/source/blender/imbuf/intern/Makefile
new file mode 100644
index 00000000000..e60e75b6d9a
--- /dev/null
+++ b/source/blender/imbuf/intern/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 *****
+#
+#
+
+LIBNAME = imbuf
+DIR = $(OCGDIR)/blender/imbuf
+
+include nan_compile.mk
+
+ifeq ($(OS),$(findstring $(OS), "beos darwin freebsd linux openbsd solaris windows"))
+ CFLAGS += -funsigned-char
+endif
+
+CFLAGS += $(LEVEL_1_C_WARNINGS)
+
+CPPFLAGS += -I$(NAN_JPEG)/include
+CPPFLAGS += -I$(NAN_PNG)/include
+CPPFLAGS += -I$(NAN_ZLIB)/include
+CPPFLAGS += -I../../include
+CPPFLAGS += -I../../blenkernel
+CPPFLAGS += -I../../blenlib
+CPPFLAGS += -I../../avi
+# path to the guarded memory allocator
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+# This is not really needed, but until /include is cleaned, it must be
+# there for proper compilation.
+# - No, it is also needed in antialias, for listbase (nzc)
+CPPFLAGS += -I../../makesdna
+# external interface of this module
+CPPFLAGS += -I..
+
diff --git a/source/blender/imbuf/intern/allocimbuf.c b/source/blender/imbuf/intern/allocimbuf.c
new file mode 100644
index 00000000000..8d9eb17c9c2
--- /dev/null
+++ b/source/blender/imbuf/intern/allocimbuf.c
@@ -0,0 +1,357 @@
+/**
+ * allocimbuf.c
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/* It's become a bit messy... Basically, only the IMB_ prefixed files
+ * should remain. */
+
+#include "IMB_imbuf_types.h"
+
+#include "imbuf.h"
+#include "imbuf_patch.h"
+#include "IMB_imbuf.h"
+
+#include "IMB_divers.h"
+#include "IMB_allocimbuf.h"
+
+static unsigned int dfltcmap[16] = {
+ 0x00000000, 0xffffffff, 0x777777ff, 0xccccccff,
+ 0xcc3344ff, 0xdd8844ff, 0xccdd44ff, 0x888833ff,
+ 0x338844ff, 0x44dd44ff, 0x44ddccff, 0x3388ccff,
+ 0x8888ddff, 0x4433ccff, 0xcc33ccff, 0xcc88ddff
+};
+
+void imb_freeplanesImBuf(struct ImBuf * ibuf)
+{
+ if (ibuf==0) return;
+ if (ibuf->planes){
+ if (ibuf->mall & IB_planes) free(ibuf->planes);
+ }
+ ibuf->planes = 0;
+ ibuf->mall &= ~IB_planes;
+}
+
+
+void imb_freerectImBuf(struct ImBuf * ibuf)
+{
+ if (ibuf==0) return;
+ if (ibuf->rect){
+ if (ibuf->mall & IB_rect) free(ibuf->rect);
+ }
+ ibuf->rect=0;
+ ibuf->mall &= ~IB_rect;
+}
+
+static void freeencodedbufferImBuf(struct ImBuf * ibuf)
+{
+ if (ibuf==0) return;
+ if (ibuf->encodedbuffer){
+ if (ibuf->mall & IB_mem) free(ibuf->encodedbuffer);
+ }
+ ibuf->encodedbuffer = 0;
+ ibuf->encodedbuffersize = 0;
+ ibuf->encodedsize = 0;
+ ibuf->mall &= ~IB_mem;
+}
+
+void IMB_freezbufImBuf(struct ImBuf * ibuf)
+{
+ if (ibuf==0) return;
+ if (ibuf->zbuf){
+ if (ibuf->mall & IB_zbuf) free(ibuf->zbuf);
+ }
+ ibuf->zbuf=0;
+ ibuf->mall &= ~IB_zbuf;
+}
+
+void IMB_freecmapImBuf(struct ImBuf * ibuf)
+{
+ if (ibuf == 0) return;
+ if (ibuf->cmap){
+ if (ibuf->mall & IB_cmap) free(ibuf->cmap);
+ }
+ ibuf->cmap = 0;
+ ibuf->mall &= ~IB_cmap;
+}
+
+
+void IMB_freeImBuf(struct ImBuf * ibuf)
+{
+ if (ibuf){
+ imb_freeplanesImBuf(ibuf);
+ imb_freerectImBuf(ibuf);
+ IMB_freezbufImBuf(ibuf);
+ IMB_freecmapImBuf(ibuf);
+ freeencodedbufferImBuf(ibuf);
+ free(ibuf);
+ }
+}
+
+
+static short addzbufImBuf(struct ImBuf * ibuf)
+{
+ int size;
+
+ if (ibuf==0) return(FALSE);
+ IMB_freezbufImBuf(ibuf);
+
+ size = ibuf->x * ibuf->y * sizeof(unsigned int);
+ if (ibuf->zbuf = MEM_mallocN(size, "addzbufImBuf")){
+ ibuf->mall |= IB_zbuf;
+ return (TRUE);
+ }
+
+ return (FALSE);
+}
+
+
+short imb_addencodedbufferImBuf(struct ImBuf * ibuf)
+{
+ if (ibuf==0) return(FALSE);
+
+ freeencodedbufferImBuf(ibuf);
+
+ if (ibuf->encodedbuffersize == 0)
+ ibuf->encodedbuffersize = 10000;
+
+ ibuf->encodedsize = 0;
+
+ if (ibuf->encodedbuffer = MEM_mallocN(ibuf->encodedbuffersize, "addencodedbufferImBuf")){
+ ibuf->mall |= IB_mem;
+ return (TRUE);
+ }
+
+ return (FALSE);
+}
+
+
+short imb_enlargeencodedbufferImBuf(struct ImBuf * ibuf)
+{
+ unsigned int newsize, encodedsize;
+ void *newbuffer;
+
+ if (ibuf==0) return(FALSE);
+
+ if (ibuf->encodedbuffersize < ibuf->encodedsize) {
+ printf("imb_enlargeencodedbufferImBuf: error in parameters\n");
+ return(FALSE);
+ }
+
+ newsize = 2 * ibuf->encodedbuffersize;
+ if (newsize < 10000) newsize = 10000;
+
+ newbuffer = MEM_mallocN(newsize, "enlargeencodedbufferImBuf");
+ if (newbuffer == NULL) return(FALSE);
+
+ if (ibuf->encodedbuffer) {
+ memcpy(newbuffer, ibuf->encodedbuffer, ibuf->encodedsize);
+ } else {
+ ibuf->encodedsize = 0;
+ }
+
+ encodedsize = ibuf->encodedsize;
+
+ freeencodedbufferImBuf(ibuf);
+
+ ibuf->encodedbuffersize = newsize;
+ ibuf->encodedsize = encodedsize;
+ ibuf->encodedbuffer = newbuffer;
+ ibuf->mall |= IB_mem;
+
+ return (TRUE);
+}
+
+
+short imb_addrectImBuf(struct ImBuf * ibuf)
+{
+ int size;
+
+ if (ibuf==0) return(FALSE);
+ imb_freerectImBuf(ibuf);
+
+ size = ibuf->x * ibuf->y * sizeof(unsigned int);
+ if (ibuf->rect = MEM_mallocN(size, "imb_addrectImBuf")){
+ ibuf->mall |= IB_rect;
+ if (ibuf->depth > 32) return (addzbufImBuf(ibuf));
+ else return (TRUE);
+ }
+
+ return (FALSE);
+}
+
+
+short imb_addcmapImBuf(struct ImBuf *ibuf)
+{
+ int min;
+
+ if (ibuf==0) return(FALSE);
+ IMB_freecmapImBuf(ibuf);
+
+ imb_checkncols(ibuf);
+ if (ibuf->maxcol == 0) return (TRUE);
+
+ if (ibuf->cmap = MEM_callocN(sizeof(unsigned int) * ibuf->maxcol, "imb_addcmapImBuf")){
+ min = ibuf->maxcol * sizeof(unsigned int);
+ if (min > sizeof(dfltcmap)) min = sizeof(dfltcmap);
+ memcpy(ibuf->cmap, dfltcmap, min);
+ ibuf->mall |= IB_cmap;
+ return (TRUE);
+ }
+
+ return (FALSE);
+}
+
+
+short imb_addplanesImBuf(struct ImBuf *ibuf)
+{
+ int size;
+ short skipx,d,y;
+ unsigned int **planes;
+ unsigned int *point2;
+
+ if (ibuf==0) return(FALSE);
+ imb_freeplanesImBuf(ibuf);
+
+ skipx = ((ibuf->x+31) >> 5);
+ ibuf->skipx=skipx;
+ y=ibuf->y;
+ d=ibuf->depth;
+
+ planes = MEM_mallocN( (d*skipx*y)*sizeof(int) + d*sizeof(int *), "imb_addplanesImBuf");
+
+ ibuf->planes = planes;
+ if (planes==0) return (FALSE);
+
+ point2 = (unsigned int *)(planes+d);
+ size = skipx*y;
+
+ for (;d>0;d--){
+ *(planes++) = point2;
+ point2 += size;
+ }
+ ibuf->mall |= IB_planes;
+
+ return (TRUE);
+}
+
+
+struct ImBuf *IMB_allocImBuf(short x,short y,uchar d,unsigned int flags,uchar bitmap)
+{
+ struct ImBuf *ibuf;
+
+ ibuf = MEM_callocN(sizeof(struct ImBuf), "ImBuf_struct");
+ if (bitmap) flags |= IB_planes;
+
+ if (ibuf){
+ ibuf->x=x;
+ ibuf->y=y;
+ ibuf->depth=d;
+ ibuf->ftype=TGA;
+
+ if (flags & IB_rect){
+ if (imb_addrectImBuf(ibuf)==FALSE){
+ IMB_freeImBuf(ibuf);
+ return (0);
+ }
+ }
+
+ if (flags & IB_zbuf){
+ if (addzbufImBuf(ibuf)==FALSE){
+ IMB_freeImBuf(ibuf);
+ return (0);
+ }
+ }
+
+ if (flags & IB_planes){
+ if (imb_addplanesImBuf(ibuf)==FALSE){
+ IMB_freeImBuf(ibuf);
+ return (0);
+ }
+ }
+ }
+ return (ibuf);
+}
+
+
+struct ImBuf *IMB_dupImBuf(struct ImBuf *ibuf1)
+{
+ struct ImBuf *ibuf2, tbuf;
+ int flags = 0;
+ int x, y;
+
+ if (ibuf1 == 0) return (0);
+
+ if (ibuf1->rect) flags |= IB_rect;
+ if (ibuf1->planes) flags |= IB_planes;
+
+ x = ibuf1->x;
+ y = ibuf1->y;
+ if (ibuf1->flags & IB_fields) y *= 2;
+
+ ibuf2 = IMB_allocImBuf(x, y, ibuf1->depth, flags, 0);
+ if (ibuf2 == 0) return (0);
+
+ if (flags & IB_rect) memcpy(ibuf2->rect,ibuf1->rect,x * y * sizeof(int));
+ if (flags & IB_planes) memcpy(*(ibuf2->planes),*(ibuf1->planes),ibuf1->depth * ibuf1->skipx * y * sizeof(int));
+
+ if (ibuf1->encodedbuffer) {
+ ibuf2->encodedbuffersize = ibuf1->encodedbuffersize;
+ if (imb_addencodedbufferImBuf(ibuf2) == FALSE) {
+ IMB_freeImBuf(ibuf2);
+ return(0);
+ }
+
+ memcpy(ibuf2->encodedbuffer, ibuf1->encodedbuffer, ibuf1->encodedsize);
+ }
+
+
+ tbuf = *ibuf1;
+
+ // pointers goedzetten
+ tbuf.rect = ibuf2->rect;
+ tbuf.planes = ibuf2->planes;
+ tbuf.cmap = ibuf2->cmap;
+ tbuf.encodedbuffer = ibuf2->encodedbuffer;
+
+ // malloc flag goed zetten
+ tbuf.mall = ibuf2->mall;
+
+ *ibuf2 = tbuf;
+
+ if (ibuf1->cmap){
+ imb_addcmapImBuf(ibuf2);
+ if (ibuf2->cmap) memcpy(ibuf2->cmap,ibuf1->cmap,ibuf2->maxcol * sizeof(int));
+ }
+
+ return(ibuf2);
+}
diff --git a/source/blender/imbuf/intern/amiga.c b/source/blender/imbuf/intern/amiga.c
new file mode 100644
index 00000000000..ba699f90847
--- /dev/null
+++ b/source/blender/imbuf/intern/amiga.c
@@ -0,0 +1,536 @@
+/**
+ * amiga.c
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "imbuf.h"
+#include "imbuf_patch.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "IMB_cmap.h"
+#include "IMB_allocimbuf.h"
+#include "IMB_bitplanes.h"
+#include "IMB_amiga.h"
+
+/* actually hard coded endianness */
+#define GET_BIG_LONG(x) (((uchar *) (x))[0] << 24 | ((uchar *) (x))[1] << 16 | ((uchar *) (x))[2] << 8 | ((uchar *) (x))[3])
+#define GET_LITTLE_LONG(x) (((uchar *) (x))[3] << 24 | ((uchar *) (x))[2] << 16 | ((uchar *) (x))[1] << 8 | ((uchar *) (x))[0])
+#define SWAP_L(x) (((x << 24) & 0xff000000) | ((x << 8) & 0xff0000) | ((x >> 8) & 0xff00) | ((x >> 24) & 0xff))
+#define SWAP_S(x) (((x << 8) & 0xff00) | ((x >> 8) & 0xff))
+
+/* more endianness... should move to a separate file... */
+#if defined(__sgi) || defined (__sparc) || defined (__PPC__) || defined (__ppc__) || defined (__BIG_ENDIAN__)
+#define GET_ID GET_BIG_LONG
+#define LITTLE_LONG SWAP_LONG
+#else
+#define GET_ID GET_LITTLE_LONG
+#define LITTLE_LONG ENDIAN_NOP
+#endif
+
+static uchar *decodebodyscanl(uchar *body, short bytes, uchar **list, short d)
+{
+ for (;d>0;d--){
+ uchar *point;
+ short todo;
+ uchar i,j;
+
+ point = *(list++);
+ todo=bytes;
+ while (todo>0){
+ i = *body++;
+
+ if (i & 128){ /* fill */
+ if (i==128) continue; /* nop */
+
+ i=257-i;
+ todo-=i;
+ j = *(body++);
+ do{
+ *(point++) = j;
+ i--;
+ }while (i);
+ } else{ /* copy */
+ i++;
+ todo-=i;
+
+ do{
+ *(point++) = *(body++);
+ i--;
+ }while (i);
+ }
+ }
+ if (todo) return (0);
+ }
+ return(body);
+}
+
+
+static uchar *decodebodyh(struct ImBuf *ibuf, uchar *body)
+{
+ if (ibuf->y==1) {
+ body=decodebodyscanl(body, WIDTHB(ibuf->x), (uchar **)ibuf->planes, ibuf->depth);
+ }
+ else {
+ unsigned int **list;
+ short skipx,i,bytes,y;
+
+ list = imb_copyplanelist(ibuf);
+ if (list == 0) return (0);
+
+ y=ibuf->y;
+ bytes = WIDTHB(ibuf->x);
+ skipx = ibuf->skipx;
+
+ for (;y>0;y--){
+ body=decodebodyscanl(body, bytes, (uchar **)list, ibuf->depth);
+ if (body == 0) return (0);
+
+ for (i=ibuf->depth-1;i>=0;i--){
+ list[i] += skipx;
+ }
+ }
+ free(list);
+ }
+ return(body);
+}
+
+
+static uchar *decodebodykolum(uchar *body, short bytes, uchar **list, short d, int next)
+{
+ for (;d>0;d--){
+ uchar *point;
+ short todo;
+ uchar i,j;
+
+ point = *(list++);
+ todo=bytes;
+ while (todo>0){
+ i = *body++;
+
+ if (i & 128){ /* fill */
+ if (i==128) continue; /* nop */
+
+ i=257-i;
+ todo-=i;
+ j = *body++;
+ do{
+ *point = j;
+ point += next;
+ i--;
+ }while (i);
+ }
+ else{ /* copy */
+ i++;
+ todo-=i;
+
+ do{
+ *point = *body++;
+ point += next;
+ i--;
+ }while (i);
+ }
+ }
+ if (todo) return (0);
+ }
+ return(body);
+}
+
+
+static uchar *decodebodyv(struct ImBuf *ibuf, uchar *body)
+{
+ uchar **list;
+ short skipx,i,bytes,times;
+
+ list = (uchar **)imb_copyplanelist(ibuf);
+ if (list == 0) return (0);
+
+ bytes = ibuf->y;
+ times = WIDTHB(ibuf->x);
+ skipx = ibuf->skipx << 2;
+
+ for (;times>0;times--){
+ body=decodebodykolum(body,bytes,list,ibuf->depth,skipx);
+ if (body == 0) return (0);
+
+ for (i=ibuf->depth-1;i>=0;i--){
+ list[i] += 1;
+ }
+ }
+ free(list);
+ return(body);
+}
+
+static uchar *makebody(uchar **planes, short bytes, short depth, uchar *buf)
+{
+ uchar *bitplstart,*temp;
+
+ register uchar last,this,*bitpl;
+ register short todo;
+ register int copy;
+
+ bytes--;
+ for (;depth>0;depth--){
+ bitpl = *(planes++);
+ bitplstart = bitpl;
+ todo = bytes;
+ last = *bitpl++;
+ this = *bitpl++;
+ copy = last^this;
+ while (todo>0){
+
+ if (copy){
+ do{
+ last = this;
+ this = *bitpl++;
+ if (last == this){
+ if (this == bitpl[-3]){ /* drie dezelfde? */
+ todo -= 1; /* todo goed zetten */
+ break;
+ }
+ }
+ }while (--todo != 0);
+
+ copy=bitpl-bitplstart;
+ copy -= 1;
+ if (todo) copy -= 2;
+
+ temp = bitpl;
+ bitpl = bitplstart;
+
+ while (copy){
+ last = copy;
+ if (copy>MAXDAT) last = MAXDAT;
+ copy -= last;
+ *buf++ = last-1;
+ do{
+ *buf++ = *bitpl++;
+ }while(--last != 0);
+ }
+ bitplstart = bitpl;
+ bitpl = temp;
+ last = this;
+
+ copy = FALSE;
+ }
+ else{
+ while (*bitpl++ == this){ /* zoek naar eerste afwijkende byte */
+ if (--todo == 0) break; /* of einde regel */
+ }
+ bitpl -= 1;
+ copy = bitpl-bitplstart;
+ bitplstart = bitpl;
+ todo -= 1;
+ this = *bitpl++;
+
+ while (copy){
+ if (copy>MAXRUN){
+ *buf++ = -(MAXRUN-1);
+ *buf++ = last;
+ copy -= MAXRUN;
+ }
+ else{
+ *buf++ = -(copy-1);
+ *buf++ = last;
+ break;
+ }
+ }
+ copy=TRUE;
+ }
+ }
+ }
+ return (buf);
+}
+
+
+short imb_encodebodyh(struct ImBuf *ibuf, int file)
+{
+ uchar *buf, *endbuf, *max;
+ int size, line, ok = TRUE;
+ unsigned int **list;
+ short skipx,i,y;
+
+ line = WIDTHB(ibuf->x) * ibuf->depth;
+ line += (line >> 6) + 10;
+ size = 16 * line;
+ if (size < 16384) size = 16384;
+
+ buf = (uchar *) malloc(size);
+ if (buf == 0) return (0);
+
+ max = buf + size - line;
+
+ list = imb_copyplanelist(ibuf);
+ if (list == 0){
+ free(buf);
+ return (0);
+ }
+
+ y=ibuf->y;
+ skipx = ibuf->skipx;
+ endbuf = buf;
+
+ for (y=ibuf->y;y>0;y--){
+ endbuf = makebody((uchar **)list, WIDTHB(ibuf->x), ibuf->depth, endbuf);
+ if (endbuf==0){
+ ok = -20;
+ break;
+ }
+ if (endbuf >= max || y == 1){
+ size = endbuf-buf;
+ if (write(file,buf,size)!=size) ok = -19;
+ endbuf = buf;
+ }
+ for (i=ibuf->depth-1;i>=0;i--){
+ list[i] += skipx;
+ }
+ if (ok != TRUE) break;
+ }
+ free(list);
+
+ free(buf);
+ return(ok);
+}
+
+
+short imb_encodebodyv(struct ImBuf *ibuf, int file)
+{
+ struct ImBuf *ibufv;
+ uchar *buf,*endbuf;
+ short x,offset;
+
+ buf = (uchar *) malloc((ibuf->y + (ibuf->y >> 6) + 10) * ibuf->depth);
+ if (buf == 0) return (0);
+
+ ibufv=IMB_allocImBuf((ibuf->y)<<3,1, ibuf->depth, 0, 1);
+ if (ibufv == 0){
+ free(buf);
+ return (0);
+ }
+
+ offset=0;
+
+ for(x = WIDTHB(ibuf->x);x>0;x--){
+ register short i;
+
+ for(i = ibuf->depth-1 ;i>=0;i--){
+ register uchar *p1,*p2;
+ register int skipx;
+ register short y;
+
+ skipx = (ibuf->skipx)*sizeof(int *);
+ p1=(uchar *)ibuf->planes[i];
+ p2=(uchar *)ibufv->planes[i];
+ p1 += offset;
+
+ for (y=ibuf->y;y>0;y--){
+ *(p2++) = *p1;
+ p1 += skipx;
+ }
+ }
+ offset += 1;
+
+ endbuf=makebody((uchar **)ibufv->planes, ibuf->y, ibuf->depth, buf);
+ if (endbuf==0) return (-20);
+ if (write(file,buf,endbuf-buf)!=endbuf-buf) return (-19);
+ }
+ free(buf);
+ IMB_freeImBuf(ibufv);
+ return (TRUE);
+}
+
+static uchar *readbody(struct ImBuf *ibuf, uchar *body)
+{
+ int skipbuf,skipbdy,depth,y,offset = 0;
+
+ skipbuf = ibuf->skipx;
+ skipbdy = WIDTHB(ibuf->x);
+
+ for (y = ibuf->y; y> 0; y--){
+ for( depth = 0; depth < ibuf->depth; depth ++){
+ memcpy(ibuf->planes[depth] + offset, body, skipbdy);
+ body += skipbdy;
+ }
+ offset += skipbuf;
+ }
+ return body;
+}
+
+struct ImBuf *imb_loadamiga(int *iffmem,int flags)
+{
+ int chunk,totlen,len,*cmap=0,cmaplen,*mem,ftype=0;
+ uchar *body=0;
+ struct BitMapHeader bmhd;
+ struct ImBuf *ibuf=0;
+
+ mem = iffmem;
+ bmhd.w = 0;
+
+ if (GET_ID(mem) != FORM) return (0);
+ if (GET_ID(mem+2) != ILBM) return (0);
+ totlen= (GET_BIG_LONG(mem+1) + 1) & ~1;
+ mem += 3;
+ totlen -= 4;
+
+
+ while(totlen > 0){
+ chunk = GET_ID(mem);
+ len= (GET_BIG_LONG(mem+1) + 1) & ~1;
+ mem += 2;
+
+ totlen -= len+8;
+
+ switch (chunk){
+ case BMHD:
+ memcpy(&bmhd, mem, sizeof(struct BitMapHeader));
+
+ bmhd.w = BIG_SHORT(bmhd.w);
+ bmhd.h = BIG_SHORT(bmhd.h);
+ bmhd.x = BIG_SHORT(bmhd.x);
+ bmhd.y = BIG_SHORT(bmhd.y);
+ bmhd.transparentColor = BIG_SHORT(bmhd.transparentColor);
+ bmhd.pageWidth = BIG_SHORT(bmhd.pageWidth);
+ bmhd.pageHeight = BIG_SHORT(bmhd.pageHeight);
+
+ break;
+ case BODY:
+ body = (uchar *)mem;
+ break;
+ case CMAP:
+ cmap = mem;
+ cmaplen = len/3;
+ break;
+ case CAMG:
+ ftype = GET_BIG_LONG(mem);
+ break;
+ }
+ mem = (int *)((uchar *)mem +len);
+ if (body) break;
+ }
+ if (bmhd.w == 0) return (0);
+ if (body == 0) return (0);
+
+ if (flags & IB_test) ibuf = IMB_allocImBuf(bmhd.w, bmhd.h, bmhd.nPlanes, 0, 0);
+ else ibuf = IMB_allocImBuf(bmhd.w, bmhd.h, bmhd.nPlanes + (bmhd.masking & 1),0,1);
+
+ if (ibuf == 0) return (0);
+
+ ibuf->ftype = (ftype | AMI);
+
+ if (cmap){
+ ibuf->mincol = 0;
+ ibuf->maxcol = cmaplen;
+ imb_addcmapImBuf(ibuf);
+ /* this functions needs a 3rd arg: the number of
+ * columns.... why did this work before? */
+/* imb_makecolarray(ibuf, cmap); */
+ imb_makecolarray(ibuf, cmap, 0);
+ }
+
+ if (flags & IB_test){
+ if (flags & IB_freem) free(iffmem);
+ return(ibuf);
+ }
+
+ switch (bmhd.compression){
+ case 0:
+ body= readbody(ibuf, body);
+ break;
+ case 1:
+ body= decodebodyh(ibuf,body);
+ break;
+ case 2:
+ body= decodebodyv(ibuf,body);
+ ibuf->type |= IB_subdlta;
+ break;
+ }
+
+ if (flags & IB_freem) free(iffmem);
+
+ if (body == 0){
+ free (ibuf);
+ return(0);
+ }
+
+ /* vergeet stencil */
+ ibuf->depth = bmhd.nPlanes;
+
+ if (flags & IB_rect){
+ imb_addrectImBuf(ibuf);
+ imb_bptolong(ibuf);
+ imb_freeplanesImBuf(ibuf);
+ if (ibuf->cmap){
+ if ((flags & IB_cmap) == 0) IMB_applycmap(ibuf);
+ } else if (ibuf->depth == 18){
+ int i,col;
+ unsigned int *rect;
+
+ rect = ibuf->rect;
+ for(i=ibuf->x * ibuf->y ; i>0 ; i--){
+ col = *rect;
+ col = ((col & 0x3f000) << 6) + ((col & 0xfc0) << 4) + ((col & 0x3f) << 2);
+ col += (col & 0xc0c0c0) >> 6;
+ *rect++ = col;
+ }
+ ibuf->depth = 24;
+ } else if (ibuf->depth <= 8) { /* geen colormap en geen 24 bits: zwartwit */
+ uchar *rect;
+ int size, shift;
+
+ if (ibuf->depth < 8){
+ rect = (uchar *) ibuf->rect;
+ rect += 3;
+ shift = 8 - ibuf->depth;
+ for (size = ibuf->x * ibuf->y; size > 0; size --){
+ rect[0] <<= shift;
+ rect += 4;
+ }
+ }
+ rect = (uchar *) ibuf->rect;
+ for (size = ibuf->x * ibuf->y; size > 0; size --){
+ rect[1] = rect[2] = rect[3];
+ rect += 4;
+ }
+ ibuf->depth = 8;
+ }
+ }
+
+ if ((flags & IB_ttob) == 0) IMB_flipy(ibuf);
+
+ if (ibuf) {
+ if (ibuf->rect)
+ IMB_convert_rgba_to_abgr(ibuf->x*ibuf->y, ibuf->rect);
+ }
+
+ return (ibuf);
+}
diff --git a/source/blender/imbuf/intern/anim.c b/source/blender/imbuf/intern/anim.c
new file mode 100644
index 00000000000..9525fe4ab5f
--- /dev/null
+++ b/source/blender/imbuf/intern/anim.c
@@ -0,0 +1,1157 @@
+/**
+ * anim.c
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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
+#define INC_OLE2
+#include <windows.h>
+#include <windowsx.h>
+#include <mmsystem.h>
+#include <memory.h>
+#include <commdlg.h>
+#include <vfw.h>
+
+#undef AVIIF_KEYFRAME // redefined in AVI_avi.h
+#undef AVIIF_LIST // redefined in AVI_avi.h
+
+#define FIXCC(fcc) if (fcc == 0) fcc = mmioFOURCC('N', 'o', 'n', 'e'); \
+ if (fcc == BI_RLE8) fcc = mmioFOURCC('R', 'l', 'e', '8');
+#endif
+
+#include <sys/types.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+#ifndef _WIN32
+#include <dirent.h>
+#else
+#include <io.h>
+#include "BLI_winstuff.h"
+#endif
+
+#include "BLI_blenlib.h" /* BLI_remlink BLI_filesize BLI_addtail
+ BLI_countlist BLI_stringdec */
+
+#include "imbuf.h"
+#include "imbuf_patch.h"
+
+#include "AVI_avi.h"
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "IMB_allocimbuf.h"
+#include "IMB_bitplanes.h"
+
+
+/* actually hard coded endianness */
+#define GET_BIG_LONG(x) (((uchar *) (x))[0] << 24 | ((uchar *) (x))[1] << 16 | ((uchar *) (x))[2] << 8 | ((uchar *) (x))[3])
+#define GET_LITTLE_LONG(x) (((uchar *) (x))[3] << 24 | ((uchar *) (x))[2] << 16 | ((uchar *) (x))[1] << 8 | ((uchar *) (x))[0])
+#define SWAP_L(x) (((x << 24) & 0xff000000) | ((x << 8) & 0xff0000) | ((x >> 8) & 0xff00) | ((x >> 24) & 0xff))
+#define SWAP_S(x) (((x << 8) & 0xff00) | ((x >> 8) & 0xff))
+
+/* more endianness... should move to a separate file... */
+#if defined(__sgi) || defined (__sparc) || defined (__PPC__) || defined (__ppc__) || defined (__BIG_ENDIAN__)
+#define GET_ID GET_BIG_LONG
+#define LITTLE_LONG SWAP_LONG
+#else
+#define GET_ID GET_LITTLE_LONG
+#define LITTLE_LONG ENDIAN_NOP
+#endif
+
+/****/
+
+typedef struct Anhd{
+ unsigned char type, mask;
+ unsigned short w, h;
+ unsigned short x, y;
+ unsigned short abs16, abs, reala6, real;
+ unsigned char interleave, pad0;
+ unsigned short bits16, bits;
+ unsigned char pad[16];
+}Anhd;
+
+typedef struct Anim5Delta {
+ struct Anim5Delta * next, * prev;
+ void * data;
+ int type;
+}Anim5Delta;
+
+#define ANIM_NONE (0)
+#define ANIM_SEQUENCE (1 << 0)
+#define ANIM_DIR (1 << 1)
+#define ANIM_ANIM5 (1 << 2)
+#define ANIM_TGA (1 << 3)
+#define ANIM_MOVIE (1 << 4)
+#define ANIM_MDEC (1 << 5)
+#define ANIM_AVI (1 << 6)
+
+#define ANIM5_MMAP 0
+#define ANIM5_MALLOC 1
+#define ANIM5_SNGBUF 2
+#define ANIM5_XOR 4
+
+#define MAXNUMSTREAMS 50
+
+struct anim {
+ int ib_flags;
+ int curtype;
+ int curposition; /* index 0 = 1e, 1 = 2e, enz. */
+ int duration;
+ int x, y;
+
+ /* voor op nummer */
+ char name[256];
+ /* voor sequence */
+ char first[256];
+
+ /* anim5 */
+ struct ListBase anim5base;
+ void * anim5mmap;
+ int anim5len;
+ struct Anim5Delta *anim5curdlta;
+ void (*anim5decode)(struct ImBuf *, unsigned char *);
+ int anim5flags;
+
+ /* movie */
+ void *movie;
+ void *track;
+ void *params;
+ int orientation;
+ size_t framesize;
+ int interlacing;
+
+ /* data */
+ struct ImBuf * ibuf1, * ibuf2;
+
+ /* avi */
+ struct _AviMovie *avi;
+
+#ifdef _WIN32
+ /* windows avi */
+ int avistreams;
+ int firstvideo;
+ int pfileopen;
+ PAVIFILE pfile;
+ PAVISTREAM pavi[MAXNUMSTREAMS]; // the current streams
+ PGETFRAME pgf;
+#endif
+};
+
+/****/
+
+#ifdef __sgi
+
+#include <dmedia/moviefile.h>
+
+static void movie_printerror(char * str) {
+ const char * errstr = mvGetErrorStr(mvGetErrno());
+
+ if (str) {
+ if (errstr) printf("%s: %s\n", str, errstr);
+ else printf("%s: returned error\n", str);
+ } else printf("%s\n", errstr);
+}
+
+static int startmovie(struct anim * anim) {
+ if (anim == 0) return(-1);
+
+ if ( mvOpenFile (anim->name, O_BINARY|O_RDONLY, &anim->movie ) != DM_SUCCESS ) {
+ printf("Can't open movie: %s\n", anim->name);
+ return(-1);
+ }
+ if ( mvFindTrackByMedium (anim->movie, DM_IMAGE, &anim->track) != DM_SUCCESS ) {
+ printf("No image track in movie: %s\n", anim->name);
+ mvClose(anim->movie);
+ return(-1);
+ }
+
+ anim->duration = mvGetTrackLength (anim->track);
+ anim->params = mvGetParams( anim->track );
+
+ anim->x = dmParamsGetInt( anim->params, DM_IMAGE_WIDTH);
+ anim->y = dmParamsGetInt( anim->params, DM_IMAGE_HEIGHT);
+ anim->interlacing = dmParamsGetEnum (anim->params, DM_IMAGE_INTERLACING);
+ anim->orientation = dmParamsGetEnum (anim->params, DM_IMAGE_ORIENTATION);
+ anim->framesize = dmImageFrameSize(anim->params);
+
+ anim->curposition = 0;
+
+ /*printf("x:%d y:%d size:%d interl:%d dur:%d\n", anim->x, anim->y, anim->framesize, anim->interlacing, anim->duration);*/
+ return (0);
+}
+
+static ImBuf * movie_fetchibuf(struct anim * anim, int position) {
+ ImBuf * ibuf;
+/* extern rectcpy(); */
+ int size;
+ unsigned int *rect1, *rect2;
+
+ if (anim == 0) return (0);
+
+ ibuf = IMB_allocImBuf(anim->x, anim->y, 24, IB_rect, 0);
+
+ if ( mvReadFrames(anim->track, position, 1, ibuf->x * ibuf->y *
+ sizeof(int), ibuf->rect ) != DM_SUCCESS ) {
+ movie_printerror("mvReadFrames");
+ IMB_freeImBuf(ibuf);
+ return(0);
+ }
+
+ /*
+ if (anim->interlacing == DM_IMAGE_INTERLACED_EVEN)
+ {
+ rect1 = ibuf->rect + (ibuf->x * ibuf->y) - 1;
+ rect2 = rect1 - ibuf->x;
+
+ for (size = ibuf->x * (ibuf->y - 1); size > 0; size--){
+ *rect1-- = *rect2--;
+ }
+ }
+ */
+
+ if (anim->interlacing == DM_IMAGE_INTERLACED_EVEN)
+ {
+ rect1 = ibuf->rect;
+ rect2 = rect1 + ibuf->x;
+
+ for (size = ibuf->x * (ibuf->y - 1); size > 0; size--){
+ *rect1++ = *rect2++;
+ }
+ }
+ /*if (anim->orientation == DM_TOP_TO_BOTTOM) IMB_flipy(ibuf);*/
+
+
+ return(ibuf);
+}
+
+static void free_anim_movie(struct anim * anim) {
+ if (anim == NULL) return;
+
+ if (anim->movie) {
+ mvClose(anim->movie);
+ anim->movie = NULL;
+ }
+ anim->duration = 0;
+}
+
+static int ismovie(char *name) {
+ return (mvIsMovieFile(name) == DM_TRUE);
+}
+
+#else
+
+static int ismovie(char *name) {
+ return 0;
+}
+
+ /* never called, just keep the linker happy */
+static int startmovie(struct anim * anim) { return 1; }
+static ImBuf * movie_fetchibuf(struct anim * anim, int position) { return NULL; }
+static void free_anim_movie(struct anim * anim) { ; }
+
+#endif
+
+static int an_stringdec(char *string, char* kop, char *staart,unsigned short *numlen) {
+ unsigned short len,nums,nume;
+ short i,found=FALSE;
+
+ len=strlen(string);
+
+ for(i=len-1;i>=0;i--){
+ if (string[i]=='/') break;
+ if (isdigit(string[i])) {
+ if (found){
+ nums=i;
+ } else{
+ nume=i;
+ nums=i;
+ found=TRUE;
+ }
+ } else{
+ if (found) break;
+ }
+ }
+ if (found){
+ strcpy(staart,&string[nume+1]);
+ strcpy(kop,string);
+ kop[nums]=0;
+ *numlen=nume-nums+1;
+ return ((int)atoi(&(string[nums])));
+ }
+ staart[0]=0;
+ strcpy(kop,string);
+ *numlen=0;
+ return (1);
+}
+
+
+static void an_stringenc(char *string, char *kop, char *staart,
+unsigned short numlen, int pic) {
+ char numstr[10];
+ unsigned short len,i;
+
+ len=sprintf(numstr,"%d",pic);
+
+ strcpy(string,kop);
+ for(i=len;i<numlen;i++){
+ strcat(string,"0");
+ }
+ strcat(string,numstr);
+ strcat(string,staart);
+}
+
+/* om anim5's te kunnen lezen, moet een aantal gegevens bijgehouden worden:
+ * Een lijst van pointers naar delta's, in geheugen of ge'mmap'ed
+ *
+ * Mogelijk kan er ook een 'skiptab' aangelegd worden, om sneller
+ * sprongen te kunnen maken.
+ *
+ * Er moeten niet direct al plaatjes gegenereed worden, dit maakt de
+ * routines onbruikbaar om snel naar het goede plaatje te springen.
+ * Een routine voert dus de delta's uit, een andere routine maakt van
+ * voorgrondplaatje een ibuf;
+ */
+
+
+/*
+ een aantal functie pointers moet geinporteerd worden, zodat er niet
+ nog meer library's / objects meegelinkt hoeven te worden.
+
+ Dezelfde structuur moet ook gebruikt kunnen worden voor het wegschrijven
+ van animaties. Hoe geef je dit aan ?
+
+ Hoe snel kunnen 10 .dlta's gedecomprimeerd worden
+ (zonder omzetten naar rect).
+
+ 1 - zoek naar 1e plaatje, animatie die aan de eisen voldoet
+ 2 - probeer volgende plaatje te vinden:
+ anim5 - decomprimeer
+ sequence - teller ophogen
+ directory - volgende entry
+ 3 - geen succes ? ga naar 1.
+
+
+*/
+
+/*
+ 1. Initialiseer routine met toegestane reeksen, en eerste naam
+ - series op naam (.0001)
+ - directories
+ - anim5 animaties
+ - TGA delta's
+ - iff 24bits delta's (.delta)
+
+ 2. haal volgende (vorige ?) plaatje op.
+
+ 3. vrijgeven
+*/
+
+/* selectie volgorde is:
+ 1 - anim5()
+ 2 - name
+ 3 - dir
+*/
+
+
+static void free_anim_anim5(struct anim * anim) {
+ ListBase * animbase;
+ Anim5Delta * delta, * next;
+
+ if (anim == NULL) return;
+
+ animbase = &anim->anim5base;
+ delta = animbase->first;
+
+ while (delta) {
+ next = delta->next;
+
+ if (delta->type == ANIM5_MALLOC) free(delta->data);
+ BLI_remlink(animbase, delta);
+ free(delta);
+
+ delta = next;
+ }
+
+ if (anim->anim5mmap && anim->anim5len) {
+ MEM_freeN(anim->anim5mmap);
+ }
+
+ anim->anim5mmap = NULL;
+ anim->anim5len = 0;
+ anim->anim5curdlta = 0;
+ anim->duration = 0;
+}
+
+static void free_anim_avi (struct anim *anim) {
+ int i;
+
+ if (anim == NULL) return;
+ if (anim->avi == NULL) return;
+
+ AVI_close (anim->avi);
+ MEM_freeN (anim->avi);
+ anim->avi = NULL;
+
+#ifdef _WIN32
+
+ if (anim->pgf) {
+ AVIStreamGetFrameClose(anim->pgf);
+ anim->pgf = NULL;
+ }
+
+ for (i = 0; i < anim->avistreams; i++){
+ AVIStreamRelease(anim->pavi[i]);
+ }
+ anim->avistreams = 0;
+
+ if (anim->pfileopen) {
+ AVIFileRelease(anim->pfile);
+ anim->pfileopen = 0;
+ AVIFileExit();
+ }
+#endif
+
+ anim->duration = 0;
+}
+
+static void free_anim_ibuf(struct anim * anim) {
+ if (anim == NULL) return;
+
+ if (anim->ibuf1) IMB_freeImBuf(anim->ibuf1);
+ if (anim->ibuf2) IMB_freeImBuf(anim->ibuf2);
+
+ anim->ibuf1 = anim->ibuf2 = NULL;
+}
+
+
+void IMB_free_anim(struct anim * anim) {
+ if (anim == NULL) {
+ printf("free anim, anim == NULL\n");
+ return;
+ }
+
+ free_anim_ibuf(anim);
+ free_anim_anim5(anim);
+ free_anim_movie(anim);
+ free_anim_avi(anim);
+
+ free(anim);
+}
+
+void IMB_close_anim(struct anim * anim) {
+ if (anim == 0) return;
+
+ IMB_free_anim(anim);
+}
+
+
+struct anim * IMB_open_anim(char * name, int ib_flags) {
+ struct anim * anim;
+
+ anim = (struct anim*)MEM_callocN(sizeof(struct anim), "anim struct");
+ if (anim != NULL) {
+ strcpy(anim->name, name);
+ anim->ib_flags = ib_flags;
+ }
+ return(anim);
+}
+
+
+static int isavi (char *name) {
+ return AVI_is_avi (name);
+}
+
+static int imb_get_anim_type(char * name) {
+ int type;
+ struct stat st;
+
+ if (ib_stat(name,&st) == -1) return(0);
+ if (((st.st_mode) & S_IFMT) != S_IFREG) return(0);
+
+ if (isavi(name)) return (ANIM_AVI);
+ if (ismovie(name)) return (ANIM_MOVIE);
+
+ type = IMB_ispic(name);
+ if (type == ANIM) return (ANIM_ANIM5);
+ if (type) return(ANIM_SEQUENCE);
+ return(0);
+}
+
+int IMB_isanim(char * name) {
+ int type= imb_get_anim_type(name);
+
+ return (type && type!=ANIM_SEQUENCE);
+}
+
+static void planes_to_rect(struct ImBuf * ibuf, int flags) {
+ if (ibuf == 0) return;
+
+ /* dit komt regelrecht uit de amiga.c */
+
+ if (flags & IB_rect && ibuf->rect == 0) {
+ imb_addrectImBuf(ibuf);
+ imb_bptolong(ibuf);
+ IMB_flipy(ibuf);
+ imb_freeplanesImBuf(ibuf);
+
+ if (ibuf->cmap){
+ if ((flags & IB_cmap) == 0) {
+ IMB_applycmap(ibuf);
+ IMB_convert_rgba_to_abgr(ibuf->x*ibuf->y, ibuf->rect);
+ }
+ } else if (ibuf->depth == 18){
+ int i,col;
+ unsigned int *rect;
+
+ rect = ibuf->rect;
+ for(i=ibuf->x * ibuf->y ; i>0 ; i--){
+ col = *rect;
+ col = ((col & 0x3f000) << 6) + ((col & 0xfc0) << 4)
+ + ((col & 0x3f) << 2);
+ col += (col & 0xc0c0c0) >> 6;
+ *rect++ = col;
+ }
+ ibuf->depth = 24;
+ } else if (ibuf->depth <= 8) {
+ /* geen colormap en geen 24 bits: zwartwit */
+ uchar *rect;
+ int size, shift;
+
+ if (ibuf->depth < 8){
+ rect = (uchar *) ibuf->rect;
+ rect += 3;
+ shift = 8 - ibuf->depth;
+ for (size = ibuf->x * ibuf->y; size > 0; size --){
+ rect[0] <<= shift;
+ rect += 4;
+ }
+ }
+ rect = (uchar *) ibuf->rect;
+ for (size = ibuf->x * ibuf->y; size > 0; size --){
+ rect[1] = rect[2] = rect[3];
+ rect += 4;
+ }
+ ibuf->depth = 8;
+ }
+ }
+}
+
+
+static void anim5decode(struct ImBuf * ibuf, uchar * dlta) {
+ uchar depth;
+ int skip;
+ int *ofspoint;
+ uchar **planes;
+
+ /* samenstelling delta:
+ lijst met ofsets voor delta's per bitplane (ofspoint)
+ per kolom in delta (point)
+ aantal handelingen (noops)
+ code
+ bijbehorende data
+ ...
+ ...
+ */
+
+ dlta += 8;
+
+ ofspoint = (int *)dlta;
+ skip = ibuf->skipx * sizeof(int *);
+ planes = (uchar **)ibuf->planes;
+
+ for(depth=ibuf->depth ; depth>0 ; depth--){
+ if (GET_BIG_LONG(ofspoint)){
+ uchar *planestart;
+ uchar *point;
+ uchar x;
+
+ point = dlta + GET_BIG_LONG(ofspoint);
+ planestart = planes[0];
+ x = (ibuf->x + 7) >> 3;
+
+ do{
+ uchar noop;
+
+ if (noop = *(point++)){
+ uchar *plane;
+ uchar code;
+
+ plane = planestart;
+ do{
+ if ((code = *(point++))==0){
+ uchar val;
+
+ code = *(point++);
+ val = *(point++);
+ do {
+ plane[0] = val;
+ plane += skip;
+ } while(--code);
+
+ } else if (code & 128){
+
+ code &= 0x7f;
+ do{
+ plane[0] = *(point++);
+ plane += skip;
+ } while(--code);
+
+ } else plane += code * skip;
+
+ } while(--noop);
+ }
+ planestart++;
+ } while(--x);
+ }
+ ofspoint++;
+ planes++;
+ }
+}
+
+
+static void anim5xordecode(struct ImBuf * ibuf, uchar * dlta) {
+ uchar depth;
+ int skip;
+ int *ofspoint;
+ uchar **planes;
+
+ /* samenstelling delta:
+ lijst met ofsets voor delta's per bitplane (ofspoint)
+ per kolom in delta (point)
+ aantal handelingen (noops)
+ code
+ bijbehorende data
+ ...
+ ...
+ */
+
+ dlta += 8;
+
+ ofspoint = (int *)dlta;
+ skip = ibuf->skipx * sizeof(int *);
+ planes = (uchar **)ibuf->planes;
+
+ for(depth=ibuf->depth ; depth>0 ; depth--){
+
+ if (GET_BIG_LONG(ofspoint)){
+ uchar *planestart;
+ uchar *point;
+ uchar x;
+
+ point = dlta + GET_BIG_LONG(ofspoint);
+ planestart = planes[0];
+ x = (ibuf->x + 7) >> 3;
+
+ do{
+ uchar noop;
+
+ if (noop = *(point++)){
+ uchar *plane;
+ uchar code;
+
+ plane = planestart;
+ do{
+ if ((code = *(point++))==0){
+ uchar val;
+
+ code = *(point++);
+ val = *(point++);
+ do{
+ plane[0] ^= val;
+ plane += skip;
+ }while(--code);
+
+ } else if (code & 128){
+
+ code &= 0x7f;
+ do{
+ plane[0] ^= *(point++);
+ plane += skip;
+ }while(--code);
+
+ } else plane += code * skip;
+
+ }while(--noop);
+ }
+ planestart++;
+ }while(--x);
+ }
+ ofspoint++;
+ planes++;
+ }
+}
+
+static int nextanim5(struct anim * anim) {
+ Anim5Delta * delta;
+ struct ImBuf * ibuf;
+
+ if (anim == 0) return(-1);
+
+ delta = anim->anim5curdlta;
+
+ if (delta == 0) return (-1);
+
+ if (anim->anim5flags & ANIM5_SNGBUF) {
+ ibuf = anim->ibuf1;
+ if (ibuf == 0) return (0);
+ anim->anim5decode(ibuf, delta->data);
+ } else {
+ ibuf = anim->ibuf2;
+ if (ibuf == 0) return (0);
+ anim->anim5decode(ibuf, delta->data);
+ anim->ibuf2 = anim->ibuf1;
+ anim->ibuf1 = ibuf;
+ }
+
+ anim->anim5curdlta = anim->anim5curdlta->next;
+ anim->curposition++;
+
+ return(0);
+}
+
+static int rewindanim5(struct anim * anim) {
+ Anim5Delta * delta;
+ struct ImBuf * ibuf;
+
+ if (anim == 0) return (-1);
+
+ free_anim_ibuf(anim);
+
+ delta = anim->anim5base.first;
+ if (delta == 0) return (-1);
+
+ ibuf = IMB_loadiffmem(delta->data, IB_planes);
+ if (ibuf == 0) return(-1);
+
+ anim->ibuf1 = ibuf;
+ if ((anim->anim5flags & ANIM5_SNGBUF) == 0) anim->ibuf2 = IMB_dupImBuf(ibuf);
+
+ anim->anim5curdlta = delta->next;
+ anim->curposition = 0;
+
+ return(0);
+}
+
+
+static int startanim5(struct anim * anim) {
+ int file, buf[20], totlen;
+ unsigned int len;
+ short * mem;
+ ListBase * animbase;
+ Anim5Delta * delta;
+ Anhd anhd;
+
+ /* Controles */
+
+ if (anim == 0) return(-1);
+
+ file = open(anim->name,O_BINARY|O_RDONLY);
+ if (file < 0) return (-1);
+
+ if (read(file, buf, 24) != 24) {
+ close(file);
+ return(-1);
+ }
+
+ if ((GET_ID(buf) != FORM) || (GET_ID(buf + 2) != ANIM)
+ || (GET_ID(buf + 3) != FORM) || (GET_ID(buf + 5) != ILBM)){
+ printf("No anim5 file %s\n",anim->name);
+ close(file);
+ return (-1);
+ }
+
+ /* de hele file wordt in het geheugen gemapped */
+
+ totlen = BLI_filesize(file);
+ if (totlen && file>=0) {
+ lseek(file, 0L, SEEK_SET);
+
+ mem= MEM_mallocN(totlen, "mmap");
+ if (read(file, mem, totlen) != totlen) {
+ MEM_freeN(mem);
+ mem = NULL;
+ }
+ } else {
+ mem = NULL;
+ }
+ close (file);
+
+ if (!mem) return (-1);
+
+ anhd.interleave = 0;
+ anhd.bits = 0;
+ anhd.type = 5;
+
+ anim->anim5mmap = mem;
+ anim->anim5len = totlen;
+ anim->anim5flags = 0;
+ anim->duration = 0;
+
+ animbase = & anim->anim5base;
+ animbase->first = animbase->last = 0;
+
+ /* eerste plaatje inlezen */
+
+ mem = mem + 6;
+ totlen -= 12;
+
+ len = GET_BIG_LONG(mem + 2);
+ len = (len + 8 + 1) & ~1;
+ delta = NEW(Anim5Delta);
+
+ delta->data = mem;
+ delta->type = ANIM5_MMAP;
+
+ BLI_addtail(animbase, delta);
+
+ mem += (len >> 1);
+ totlen -= len;
+
+ while (totlen > 0) {
+ len = GET_BIG_LONG(mem + 2);
+ len = (len + 8 + 1) & ~1;
+
+ switch(GET_ID(mem)){
+ case FORM:
+ len = 12;
+ break;
+ case ANHD:
+ memcpy(&anhd, mem + 4, sizeof(Anhd));
+ break;
+ case DLTA:
+ delta = NEW(Anim5Delta);
+ delta->data = mem;
+ delta->type = ANIM5_MMAP;
+ BLI_addtail(animbase, delta);
+ break;
+ }
+
+ mem += (len >> 1);
+ totlen -= len;
+ }
+
+ if (anhd.interleave == 1) anim->anim5flags |= ANIM5_SNGBUF;
+ if (BIG_SHORT(anhd.bits) & 2) anim->anim5decode = anim5xordecode;
+ else anim->anim5decode = anim5decode;
+
+ /* laatste twee delta's wissen */
+
+ delta = animbase->last;
+ if (delta) {
+ BLI_remlink(animbase, delta);
+ free(delta);
+ }
+
+ if ((anim->anim5flags & ANIM5_SNGBUF) == 0) {
+ delta = animbase->last;
+ if (delta) {
+ BLI_remlink(animbase, delta);
+ free(delta);
+ }
+ }
+
+ anim->duration = BLI_countlist(animbase);
+
+ return(rewindanim5(anim));
+}
+
+
+static struct ImBuf * anim5_fetchibuf(struct anim * anim) {
+ struct ImBuf * ibuf;
+
+ if (anim == 0) return (0);
+
+ ibuf = IMB_dupImBuf(anim->ibuf1);
+ planes_to_rect(ibuf, anim->ib_flags);
+
+ return(ibuf);
+}
+
+static int startavi (struct anim *anim) {
+
+ AviError avierror;
+#ifdef _WIN32
+ HRESULT hr;
+ int i, firstvideo = -1;
+ BYTE abFormat[1024];
+ LONG l;
+ LPBITMAPINFOHEADER lpbi;
+ AVISTREAMINFO avis;
+#endif
+
+ anim->avi = MEM_callocN (sizeof(AviMovie),"animavi");
+
+ if (anim->avi == NULL) {
+ printf("Can't open avi: %s\n", anim->name);
+ return -1;
+ }
+
+ avierror = AVI_open_movie (anim->name, anim->avi);
+
+#ifdef _WIN32
+ if (avierror == AVI_ERROR_COMPRESSION) {
+ AVIFileInit();
+ hr = AVIFileOpen(&anim->pfile, anim->name, OF_READ, 0L);
+ if (hr == 0) {
+ anim->pfileopen = 1;
+ for (i = 0; i < MAXNUMSTREAMS; i++) {
+ if (AVIFileGetStream(anim->pfile, &anim->pavi[i], 0L, i) != AVIERR_OK) {
+ break;
+ }
+
+ AVIStreamInfo(anim->pavi[i], &avis, sizeof(avis));
+ if ((avis.fccType == streamtypeVIDEO) && (firstvideo == -1)) {
+ anim->pgf = AVIStreamGetFrameOpen(anim->pavi[i], NULL);
+ if (anim->pgf) {
+ firstvideo = i;
+
+ // get stream length
+ anim->avi->header->TotalFrames = AVIStreamLength(anim->pavi[i]);
+
+ // get information about images inside the stream
+ l = sizeof(abFormat);
+ AVIStreamReadFormat(anim->pavi[i], 0, &abFormat, &l);
+ lpbi = (LPBITMAPINFOHEADER)abFormat;
+ anim->avi->header->Height = lpbi->biHeight;
+ anim->avi->header->Width = lpbi->biWidth;
+ } else {
+ FIXCC(avis.fccHandler);
+ FIXCC(avis.fccType);
+ printf("Can't find AVI decoder for type : %4.4hs/%4.4hs\n",
+ (LPSTR)&avis.fccType,
+ (LPSTR)&avis.fccHandler);
+ }
+ }
+ }
+
+ // register number of opened avistreams
+ anim->avistreams = i;
+
+ //
+ // Couldn't get any video streams out of this file
+ //
+ if ((anim->avistreams == 0) || (firstvideo == -1)) {
+ avierror = AVI_ERROR_FORMAT;
+ } else {
+ avierror = AVI_ERROR_NONE;
+ anim->firstvideo = firstvideo;
+ }
+ } else {
+ AVIFileExit();
+ }
+ }
+#endif
+
+ if (avierror != AVI_ERROR_NONE) {
+ AVI_print_error(avierror);
+ printf ("Error loading avi: %s\n", anim->name);
+ free_anim_avi(anim);
+ return -1;
+ }
+
+ anim->duration = anim->avi->header->TotalFrames;
+ anim->params = 0;
+
+ anim->x = anim->avi->header->Width;
+ anim->y = anim->avi->header->Height;
+ anim->interlacing = 0;
+ anim->orientation = 0;
+ anim->framesize = anim->x * anim->y * 4;
+
+ anim->curposition = 0;
+
+ /* printf("x:%d y:%d size:%d interl:%d dur:%d\n", anim->x, anim->y, anim->framesize, anim->interlacing, anim->duration);*/
+
+ return 0;
+}
+
+static ImBuf * avi_fetchibuf (struct anim *anim, int position) {
+ ImBuf *ibuf = NULL;
+ int *tmp;
+ int y;
+
+ if (anim == NULL) return (NULL);
+
+#ifdef _WIN32
+ if (anim->avistreams) {
+ LPBITMAPINFOHEADER lpbi;
+
+ if (anim->pgf) {
+ lpbi = AVIStreamGetFrame(anim->pgf, position + AVIStreamStart(anim->pavi[anim->firstvideo]));
+ if (lpbi) {
+ ibuf = IMB_ibImageFromMemory((int *) lpbi, 100, IB_rect);
+ }
+ }
+ } else {
+#else
+ if (1) {
+#endif
+ ibuf = IMB_allocImBuf (anim->x, anim->y, 24, IB_rect, 0);
+
+ tmp = AVI_read_frame (anim->avi, AVI_FORMAT_RGB32, position,
+ AVI_get_stream(anim->avi, AVIST_VIDEO, 0));
+
+ if (tmp == NULL) {
+ printf ("Error reading frame from AVI");
+ IMB_freeImBuf (ibuf);
+ return NULL;
+ }
+
+ for (y=0; y < anim->y; y++) {
+ memcpy (&(ibuf->rect)[((anim->y-y)-1)*anim->x], &tmp[y*anim->x],
+ anim->x * 4);
+ }
+
+ MEM_freeN (tmp);
+ }
+
+ return ibuf;
+}
+
+/* probeer volgende plaatje te lezen */
+/* Geen plaatje, probeer dan volgende animatie te openen */
+/* gelukt, haal dan eerste plaatje van animatie */
+
+static struct ImBuf * anim_getnew(struct anim * anim) {
+ struct ImBuf *ibuf = 0;
+
+ if (anim == NULL) return(0);
+
+ free_anim_anim5(anim);
+ free_anim_movie(anim);
+ free_anim_avi(anim);
+
+ if (anim->curtype != 0) return (0);
+ anim->curtype = imb_get_anim_type(anim->name);
+
+ switch (anim->curtype) {
+ case ANIM_ANIM5:
+ if (startanim5(anim)) return (0);
+ ibuf = anim5_fetchibuf(anim);
+ break;
+ case ANIM_SEQUENCE:
+ ibuf = IMB_loadiffname(anim->name, anim->ib_flags);
+ if (ibuf) {
+ strcpy(anim->first, anim->name);
+ anim->duration = 1;
+ }
+ break;
+ case ANIM_MOVIE:
+ if (startmovie(anim)) return (0);
+ ibuf = IMB_allocImBuf (anim->x, anim->y, 24, 0, 0); /* fake */
+ break;
+ case ANIM_AVI:
+ if (startavi(anim)) return (0);
+ ibuf = IMB_allocImBuf (anim->x, anim->y, 24, 0, 0);
+ break;
+ }
+
+ return(ibuf);
+}
+
+
+struct ImBuf * IMB_anim_absolute(struct anim * anim, int position) {
+ struct ImBuf * ibuf = 0;
+ char head[256], tail[256];
+ unsigned short digits;
+ int pic;
+
+ if (anim == NULL) return(0);
+
+ if (anim->curtype == 0) {
+ ibuf = anim_getnew(anim);
+ if (ibuf == NULL) return (0);
+ IMB_freeImBuf(ibuf); /* ???? */
+ }
+
+ if (position < 0) return(0);
+ if (position >= anim->duration) return(0);
+
+ switch(anim->curtype) {
+ case ANIM_ANIM5:
+ if (anim->curposition > position) rewindanim5(anim);
+ while (anim->curposition < position) {
+ if (nextanim5(anim)) return (0);
+ }
+ ibuf = anim5_fetchibuf(anim);
+ break;
+ case ANIM_SEQUENCE:
+ pic = an_stringdec(anim->first, head, tail, &digits);
+ pic += position;
+ an_stringenc(anim->name, head, tail, digits, pic);
+ ibuf = IMB_loadiffname(anim->name, LI_rect);
+ if (ibuf) {
+ anim->curposition = position;
+ /* patch... by freeing the cmap you prevent a double apply cmap... */
+ /* probably the IB_CMAP option isn't working proper
+ * after the abgr->rgba reconstruction
+ */
+ IMB_freecmapImBuf(ibuf);
+ }
+ break;
+ case ANIM_MOVIE:
+ ibuf = movie_fetchibuf(anim, position);
+ if (ibuf) {
+ anim->curposition = position;
+ IMB_convert_rgba_to_abgr(ibuf->x*ibuf->y, ibuf->rect);
+ }
+ break;
+ case ANIM_AVI:
+ ibuf = avi_fetchibuf(anim, position);
+ if (ibuf) anim->curposition = position;
+ break;
+ }
+
+ if (ibuf) {
+ if (anim->ib_flags & IB_ttob) IMB_flipy(ibuf);
+ sprintf(ibuf->name, "%s.%04d", anim->name, anim->curposition + 1);
+
+ }
+ return(ibuf);
+}
+
+struct ImBuf * IMB_anim_nextpic(struct anim * anim) {
+ struct ImBuf * ibuf = 0;
+
+ if (anim == 0) return(0);
+
+ ibuf = IMB_anim_absolute(anim, anim->curposition + 1);
+
+ return(ibuf);
+}
+
+/***/
+
+int IMB_anim_get_duration(struct anim *anim) {
+ return anim->duration;
+}
diff --git a/source/blender/imbuf/intern/antialias.c b/source/blender/imbuf/intern/antialias.c
new file mode 100644
index 00000000000..de45a47a708
--- /dev/null
+++ b/source/blender/imbuf/intern/antialias.c
@@ -0,0 +1,471 @@
+/**
+ * antialias.c
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "imbuf.h"
+
+#include "BLI_blenlib.h"
+#include "DNA_listBase.h"
+
+#include "imbuf_patch.h"
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "IMB_allocimbuf.h"
+
+/* werking:
+
+1 - zoek een overgang in een kolom
+2 - kijk wat de relatie met links en rechts is,
+
+ Is pixel boven overgang links of rechts ervan gelijk aan bovenste kleur,
+ zoek dan naar beneden.
+
+ Is pixel onder overgang links of rechts ervan gelijk aan onderste kleur,
+ zoek dan naar boven.
+
+
+*/
+
+/* er moet een functie * komen die aan kan geven of twee kleuren nu
+ * wel of niet gelijk zijn.
+ * Voor nu maar een define
+ */
+
+
+/*
+ zipfork "cc -g anti.c util.o -lgl_s -limbuf -limage -lm -o anti > /dev/console"
+ zipfork "anti /data/rt > /dev/console"
+ zipfork "anti /pics/martin/03.01.ChambFinal/0001 > /dev/console"
+*/
+
+static unsigned int anti_mask = 0xffffffff;
+static int anti_a, anti_b, anti_g, anti_r;
+
+#define compare(x, y) ((x ^ y) & anti_mask)
+
+typedef struct Edge
+{
+ struct Edge * next, * prev;
+ short position;
+ int col1, col2;
+}Edge;
+
+static void anti_free_listarray(int count, ListBase * listarray)
+{
+ int i;
+
+ if (listarray == 0) return;
+
+ for (i = 0; i < count; i++) BLI_freelistN(listarray + i);
+ MEM_freeN(listarray);
+}
+
+static ListBase * scanimage(struct ImBuf * ibuf, int dir)
+{
+ int step, pixels, lines, nextline, x, y, col1, col2;
+ unsigned int * rect;
+ ListBase * listarray, * curlist;
+ Edge * edge;
+ int count;
+
+ switch (dir) {
+ case 'h':
+ step = 1; nextline = ibuf->x;
+ pixels = ibuf->x; lines = ibuf->y;
+ break;
+ case 'v':
+ step = ibuf->x; nextline = 1;
+ pixels = ibuf->y; lines = ibuf->x;
+ }
+
+ listarray = (ListBase*)MEM_callocN((lines)* sizeof(ListBase), "listarray");
+ for (y = 0; y < lines; y++){
+ rect = ibuf->rect;
+ rect += y * nextline;
+ curlist = listarray + y;
+
+ col1 = rect[0];
+ count = 0;
+
+ for (x = 0; x < pixels; x++) {
+ col2 = rect[0];
+ if (compare(col1, col2)) {
+ edge = NEW(Edge);
+ edge->position = x;
+ edge->col1 = col1;
+ edge->col2 = col2;
+ BLI_addtail(curlist, edge);
+ col1 = col2;
+ count++;
+ if (count > 100) {
+ printf("\n\n%s: Aborting antialias !\n", ibuf->name);
+ printf("To many transitions.\nIs this a natural image ?\n\n"),
+ anti_free_listarray(lines, listarray);
+ return(0);
+ }
+ }
+ rect += step;
+ }
+ }
+
+ return(listarray);
+}
+
+
+static Edge * findmatch(Edge * first, Edge * edge)
+{
+ Edge * match = 0;
+ int in = 0, out = 65535;
+
+ if (edge->prev) in = edge->prev->position;
+ if (edge->next) out = edge->next->position;
+
+ while (first) {
+ if (first->position < edge->position) {
+ if (first->col1 == edge->col1) {
+ if (first->position >= in) match = first;
+ } else if (first->col2 == edge->col2) {
+ if (first->next == 0) match = first;
+ else if (first->next->position >= edge->position) match = first;
+ } else if (first->col2 == edge->col1) {
+ match = 0; /* bij zigzagjes kan deze al 'ns foutief gezet zijn */
+ }
+ } else if (first->position == edge->position) {
+ if (first->col1 == edge->col1 || first->col2 == edge->col2) match = first;
+ } else {
+ if (match) break; /* er is er al een */
+
+ if (first->col1 == edge->col1) {
+ if (first->prev == 0) match = first;
+ else if (first->prev->position <= edge->position) match = first;
+ } else if (first->col2 == edge->col2) {
+ if (first->position <= out) match = first;
+ }
+ }
+
+ first = first->next;
+ }
+
+ return(match);
+}
+
+
+static void filterdraw(unsigned int * ldest, unsigned int * lsrce, int zero, int half, int step)
+{
+ uchar * src, * dst;
+ int count;
+ double weight, add;
+
+ /* we filteren de pixels op ldest tussen in en out met pixels van lsrce
+ * Het gewicht loopt ondertussen van 0 naar 1
+ */
+
+
+ count = half - zero;
+ if (count < 0) count = -count;
+ if (count <= 1) return;
+
+ if (zero < half) {
+ src = (uchar *) (lsrce + (step * zero));
+ dst = (uchar *) (ldest + (step * zero));
+ } else {
+ zero--;
+ src = (uchar *) (lsrce + (step * zero));
+ dst = (uchar *) (ldest + (step * zero));
+ step = -step;
+ }
+
+ step = 4 * step;
+
+ dst += step * (count >> 1);
+ src += step * (count >> 1);
+
+ count = (count + 1) >> 1;
+ add = 0.5 / count;
+ weight = 0.5 * add;
+
+ /* dit moet natuurlijk gamma gecorrigeerd */
+
+ for(; count > 0; count --) {
+ if (anti_a) dst[0] += weight * (src[0] - dst[0]);
+ if (anti_b) dst[1] += weight * (src[1] - dst[1]);
+ if (anti_g) dst[2] += weight * (src[2] - dst[2]);
+ if (anti_r) dst[3] += weight * (src[3] - dst[3]);
+ dst += step;
+ src += step;
+ weight += add;
+ }
+}
+
+static void filterimage(struct ImBuf * ibuf, struct ImBuf * cbuf, ListBase * listarray, int dir)
+{
+ int step, pixels, lines, nextline, y, pos, drawboth;
+ unsigned int * irect, * crect;
+ Edge * left, * middle, * right, temp, * any;
+
+ switch (dir) {
+ case 'h':
+ step = 1; nextline = ibuf->x;
+ pixels = ibuf->x; lines = ibuf->y;
+ break;
+ case 'v':
+ step = ibuf->x; nextline = 1;
+ pixels = ibuf->y; lines = ibuf->x;
+ }
+
+ for (y = 1; y < lines - 1; y++){
+ irect = ibuf->rect;
+ irect += y * nextline;
+ crect = cbuf->rect;
+ crect += y * nextline;
+
+ middle = listarray[y].first;
+ while (middle) {
+ left = findmatch(listarray[y - 1].first, middle);
+ right = findmatch(listarray[y + 1].first, middle);
+ drawboth = FALSE;
+
+ if (left == 0 || right == 0) {
+ /* rand */
+ any = left;
+ if (right) any = right;
+ if (any) {
+ /* spiegelen */
+ pos = 2 * middle->position - any->position;
+
+ if (any->position < middle->position) {
+ if (pos > pixels - 1) pos = pixels - 1;
+ if (middle->next) {
+ if (pos > middle->next->position) pos = middle->next->position;
+ }
+/* if (any->next) {
+ if (pos > any->next->position) pos = any->next->position;
+ }
+*/ } else {
+ if (pos < 0) pos = 0;
+ if (middle->prev) {
+ if (pos < middle->prev->position) pos = middle->prev->position;
+ }
+/* if (any->prev) {
+ if (pos < any->prev->position) pos = any->prev->position;
+ }
+*/ }
+ temp.position = pos;
+ if (left) right = &temp;
+ else left = &temp;
+ drawboth = TRUE;
+ }
+ } else if (left->position == middle->position || right->position == middle->position) {
+ /* recht stuk */
+ /* klein hoekje, met een van de twee op afstand 2 (ander is toch op afstand 0) ? */
+
+ if (abs(left->position - right->position) == 2) drawboth = TRUE;
+ } else if (left->position < middle->position && right->position > middle->position){
+ /* trap 1 */
+ drawboth = TRUE;
+ } else if (left->position > middle->position && right->position < middle->position){
+ /* trap 2 */
+ drawboth = TRUE;
+ } else {
+ /* piek */
+ drawboth = TRUE;
+ }
+
+ if (drawboth) {
+ filterdraw(irect, crect - nextline, left->position, middle->position, step);
+ filterdraw(irect, crect + nextline, right->position, middle->position, step);
+ }
+
+ middle = middle->next;
+ }
+ }
+}
+
+
+void IMB_antialias(struct ImBuf * ibuf)
+{
+ struct ImBuf * cbuf;
+ ListBase * listarray;
+
+ if (ibuf == 0) return;
+ cbuf = IMB_dupImBuf(ibuf);
+
+ anti_a = (anti_mask >> 24) & 0xff;
+ anti_b = (anti_mask >> 16) & 0xff;
+ anti_g = (anti_mask >> 8) & 0xff;
+ anti_r = (anti_mask >> 0) & 0xff;
+
+ listarray = scanimage(cbuf, 'h');
+ if (listarray) {
+ filterimage(ibuf, cbuf, listarray, 'h');
+ anti_free_listarray(ibuf->y, listarray);
+
+ listarray = scanimage(cbuf, 'v');
+ if (listarray) {
+ filterimage(ibuf, cbuf, listarray, 'v');
+ anti_free_listarray(ibuf->x, listarray);
+ }
+ }
+
+ IMB_freeImBuf(cbuf);
+}
+
+
+/* intelligente scaling */
+
+static void _intel_scale(struct ImBuf * ibuf, ListBase * listarray, int dir)
+{
+ int step, lines, nextline, x, y, col;
+ unsigned int * irect, * trect;
+ int start, end;
+ Edge * left, * right;
+ struct ImBuf * tbuf;
+
+ switch (dir) {
+ case 'h':
+ step = 1; nextline = ibuf->x;
+ lines = ibuf->y;
+ tbuf = IMB_double_fast_y(ibuf);
+ break;
+ case 'v':
+ step = 2 * ibuf->x; nextline = 1;
+ lines = ibuf->x;
+ tbuf = IMB_double_fast_x(ibuf);
+ break;
+ default:
+ return;
+ }
+
+ imb_freerectImBuf(ibuf);
+ ibuf->rect = tbuf->rect;
+ ibuf->mall |= IB_rect;
+
+
+ ibuf->x = tbuf->x;
+ ibuf->y = tbuf->y;
+ tbuf->rect = 0;
+ IMB_freeImBuf(tbuf);
+
+ for (y = 0; y < lines - 2; y++){
+ irect = ibuf->rect;
+ irect += ((2 * y) + 1) * nextline;
+
+ left = listarray[y].first;
+ while (left) {
+ right = findmatch(listarray[y + 1].first, left);
+ if (right) {
+ if (left->col2 == right->col2) {
+ if (left->next && right->next) {
+ if (left->next->position >= right->position) {
+ start = ((left->position + right->position) >> 1);
+ end = ((left->next->position + right->next->position) >> 1);
+ col = left->col2;
+ trect = irect + (start * step);
+ for (x = start; x < end; x++) {
+ *trect = col;
+ trect += step;
+ }
+ }
+ }
+ }
+
+ if (left->col1 == right->col1) {
+ if (left->prev && right->prev) {
+ if (left->prev->position <= right->position) {
+ end = ((left->position + right->position) >> 1);
+ start = ((left->prev->position + right->prev->position) >> 1);
+ col = left->col1;
+ trect = irect + (start * step);
+ for (x = start; x < end; x++) {
+ *trect = col;
+ trect += step;
+ }
+ }
+ }
+ }
+
+ }
+ left = left->next;
+ }
+ }
+}
+
+
+void IMB_clever_double(struct ImBuf * ibuf)
+{
+ ListBase * listarray, * curlist;
+ Edge * new;
+ int size;
+ int i;
+
+ if (ibuf == 0) return;
+
+ size = ibuf->x;
+ listarray = scanimage(ibuf, 'v');
+ if (listarray) {
+ for (i = 0; i < size; i++) {
+ curlist = listarray + i;
+ new = (Edge*)MEM_callocN(sizeof(Edge),"Edge");
+ new->col2 = ibuf->rect[i]; /* bovenste pixel */
+ new->col1 = new->col2 - 1;
+ BLI_addhead(curlist, new);
+ new = (Edge*)MEM_callocN(sizeof(Edge),"Edge");
+ new->position = ibuf->y - 1;
+ new->col1 = ibuf->rect[i + ((ibuf->y -1) * ibuf->x)]; /* onderste pixel */
+ new->col2 = new->col1 - 1;
+ BLI_addtail(curlist, new);
+ }
+ _intel_scale(ibuf, listarray, 'v');
+ anti_free_listarray(size, listarray);
+
+ size = ibuf->y;
+ listarray = scanimage(ibuf, 'h');
+ if (listarray) {
+ for (i = 0; i < size; i++) {
+ curlist = listarray + i;
+ new = (Edge*)MEM_callocN(sizeof(Edge),"Edge");
+ new->col2 = ibuf->rect[i * ibuf->x]; /* linkse pixel */
+ new->col1 = new->col2 - 1;
+ BLI_addhead(curlist, new);
+ new = (Edge*)MEM_callocN(sizeof(Edge),"Edge");
+ new->position = ibuf->x - 1;
+ new->col1 = ibuf->rect[((i + 1) * ibuf->x) - 1]; /* rechtse pixel */
+ new->col2 = new->col1 - 1;
+ BLI_addtail(curlist, new);
+ }
+ _intel_scale(ibuf, listarray, 'h');
+ anti_free_listarray(size, listarray);
+ }
+ }
+}
diff --git a/source/blender/imbuf/intern/bitplanes.c b/source/blender/imbuf/intern/bitplanes.c
new file mode 100644
index 00000000000..0f1c4bf238c
--- /dev/null
+++ b/source/blender/imbuf/intern/bitplanes.c
@@ -0,0 +1,359 @@
+/**
+ * bitplanes.c
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "imbuf.h"
+#include "BLI_blenlib.h"
+
+#include "imbuf_patch.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "IMB_allocimbuf.h"
+#include "IMB_bitplanes.h"
+
+
+unsigned int **imb_copyplanelist(struct ImBuf *ibuf)
+{
+ int nobp,i;
+ unsigned int **listn,**listo;
+
+ nobp=ibuf->depth;
+ listn= malloc(nobp*sizeof(int *)); /* kopie van bitmap maken */
+ if (listn==0) return (0);
+
+ listo=ibuf->planes;
+ for (i=nobp;i>0;i--){
+ *(listn++) = *(listo++);
+ }
+ listn -= nobp;
+
+ return (listn);
+}
+
+static void bptolscanl(unsigned int *buf, int size, unsigned int **list, int nobp, int offset)
+{
+ /* zet bitplanes om in een buffer met ints
+ door 4 deelbare hoeveelheid bitplanes,
+ breedte bitplanes op ints afgrond */
+
+ list += nobp;
+
+ for (;nobp>0;)
+ {
+ int todo,i;
+ register int bp1, bp2, bp3, data;
+ register unsigned int *point;
+ int bp4, loffset;
+ /*register unsigned int bp1, bp2, bp3, bp4;*/
+
+ todo = 0;
+ point = buf;
+ loffset = offset;
+
+ if (nobp & 1){
+ list -= 1;
+ nobp -= 1;
+ for(i=size;i>0;i--)
+ {
+ if (todo==0)
+ {
+ bp1 = BIG_LONG((list[0])[loffset]);
+ loffset++;
+ todo=32;
+ }
+
+ data = *point;
+ data<<=1;
+
+ if (bp1<0) data+=1;
+ bp1<<=1;
+
+ /* data += (bp1 >> 31);
+ bp1 <<= 1;
+ */
+ *(point++)=data;
+ todo--;
+ }
+ } else if (nobp & 2){
+ list -= 2;
+ nobp -= 2;
+ for(i=size;i>0;i--)
+ {
+ if (todo==0)
+ {
+ bp1 = BIG_LONG((list[0])[loffset]);
+ bp2 = BIG_LONG((list[1])[loffset]);
+ loffset++;
+ todo=32;
+ }
+
+ data = *point;
+ data<<=2;
+
+ if (bp1<0) data+=1;
+ bp1<<=1;
+ if (bp2<0) data+=2;
+ bp2<<=1;
+
+ /* data += (bp1 >> 31) + ((bp2 & 0x80000000) >> 30);
+ bp1 <<= 1; bp2 <<= 1;
+ */
+ *(point++)=data;
+ todo--;
+ }
+ } else{
+ list -= 4;
+ nobp -= 4;
+ for(i=size;i>0;i--)
+ {
+ if (todo==0) {
+ bp1 = BIG_LONG((list[0])[loffset]);
+ bp2 = BIG_LONG((list[1])[loffset]);
+ bp3 = BIG_LONG((list[2])[loffset]);
+ bp4 = BIG_LONG((list[3])[loffset]);
+ loffset++;
+ todo=32;
+ }
+
+ data = *point;
+ data<<=4;
+
+ if (bp1<0) data+=1;
+ bp1<<=1;
+ if (bp2<0) data+=2;
+ bp2<<=1;
+ if (bp3<0) data+=4;
+ bp3<<=1;
+ if (bp4<0) data+=8;
+ bp4<<=1;
+
+ /* data += (bp1 >> 31) \
+ + ((bp2 & 0x80000000) >> 30) \
+ + ((bp3 & 0x80000000) >> 29) \
+ + ((bp4 & 0x80000000) >> 28);
+
+ bp1 <<= 1; bp2 <<= 1;
+ bp3 <<= 1; bp4 <<= 1;
+ */
+
+ *(point++)=data;
+ todo--;
+ }
+ }
+ }
+}
+
+
+void imb_bptolong(struct ImBuf *ibuf)
+{
+ int nobp,i,x;
+ unsigned int *rect,offset;
+
+ /* eerst alle ints wissen */
+
+ if (ibuf == 0) return;
+ if (ibuf->planes == 0) return;
+ if (ibuf->rect == 0) imb_addrectImBuf(ibuf);
+
+ nobp=ibuf->depth;
+ if (nobp != 32){
+ if (nobp == 24) IMB_rectoptot(ibuf, 0, IMB_rectfill, 0xff000000); /* alpha zetten */
+ else IMB_rectoptot(ibuf, 0, IMB_rectfill, 0);
+ }
+
+ rect= ibuf->rect;
+ x= ibuf->x;
+ offset=0;
+
+ for (i= ibuf->y; i>0; i--){
+ bptolscanl(rect, x, ibuf->planes, nobp, offset);
+ rect += x;
+ offset += ibuf->skipx;
+ }
+}
+
+
+static void ltobpscanl(unsigned int *rect, int x, unsigned int **list, int nobp, int offset)
+{
+ /* zet een buffer met ints, om in bitplanes. Opgepast, buffer
+ wordt vernietigd !*/
+
+ if (nobp != 32)
+ {
+ int *rect2;
+ int todo,j;
+
+ rect2 = (int*)rect;
+
+ todo = 32-nobp;
+ for (j = x;j>0;j--){
+ *(rect2++) <<= todo;
+ }
+ }
+
+ list += nobp;
+ for (;nobp>0;){
+ register int bp1=0, bp2=0, bp3=0, data;
+ register unsigned int *point;
+ int i,todo;
+ int bp4=0,loffset;
+
+ point = rect;
+ todo=32;
+ loffset=offset;
+
+ if (nobp & 1){
+ list -= 1;
+ nobp -= 1;
+
+ for(i=x;i>0;i--){
+ data = *point;
+
+ bp1 <<= 1;
+ if (data<0) bp1 += 1;
+ data <<= 1;
+
+ *(point++) = data;
+
+ todo--;
+ if (todo == 0){
+ (list[0])[loffset] = bp1;
+ loffset++;
+ todo=32;
+ }
+ }
+ if (todo != 32)
+ {
+ bp1 <<= todo;
+ (list[0])[loffset] = bp1;
+ }
+ } else if (nobp & 2){
+ list -= 2;
+ nobp -= 2;
+ for(i=x;i>0;i--){
+ data = *point;
+
+ bp2 <<= 1;
+ if (data<0) bp2 += 1;
+ data <<= 1;
+ bp1 <<= 1;
+ if (data<0) bp1 += 1;
+ data <<= 1;
+
+ *(point++) = data;
+
+ todo--;
+ if (todo == 0){
+ (list[0])[loffset] = bp1;
+ (list[1])[loffset] = bp2;
+ loffset++;
+ todo=32;
+ }
+ }
+ if (todo != 32){
+ bp1 <<= todo;
+ bp2 <<= todo;
+ (list[0])[loffset] = bp1;
+ (list[1])[loffset] = bp2;
+ }
+ } else{
+ list -= 4;
+ nobp -= 4;
+ for(i=x;i>0;i--){
+ data = *point;
+
+ bp4 <<= 1;
+ if (data<0) bp4 += 1;
+ data <<= 1;
+ bp3 <<= 1;
+ if (data<0) bp3 += 1;
+ data <<= 1;
+ bp2 <<= 1;
+ if (data<0) bp2 += 1;
+ data <<= 1;
+ bp1 <<= 1;
+ if (data<0) bp1 += 1;
+ data <<= 1;
+
+ *(point++) = data;
+
+ todo--;
+ if (todo == 0){
+ (list[0])[loffset] = bp1;
+ (list[1])[loffset] = bp2;
+ (list[2])[loffset] = bp3;
+ (list[3])[loffset] = bp4;
+ loffset++;
+ todo=32;
+ }
+ }
+ if (todo != 32){
+ bp1 <<= todo;
+ bp2 <<= todo;
+ bp3 <<= todo;
+ bp4 <<= todo;
+ (list[0])[loffset] = bp1;
+ (list[1])[loffset] = bp2;
+ (list[2])[loffset] = bp3;
+ (list[3])[loffset] = bp4;
+ }
+ }
+ }
+}
+
+
+void imb_longtobp(struct ImBuf *ibuf)
+{
+ /* zet een buffer met ints, om in bitplanes. Opgepast, buffer
+ wordt vernietigd !*/
+
+ int nobp,i,x;
+ unsigned int *rect,offset,*buf;
+ ;
+
+ nobp = ibuf->depth;
+ rect=ibuf->rect;
+ x=ibuf->x;
+ offset=0;
+ if ((buf=malloc(x*sizeof(int)))==0) return;
+
+ for (i=ibuf->y;i>0;i--){
+ memcpy(buf, rect, x*sizeof(int));
+ rect +=x ;
+ ltobpscanl(buf, x, ibuf->planes, nobp, offset);
+ offset += ibuf->skipx;
+ }
+ free(buf);
+}
diff --git a/source/blender/imbuf/intern/bmp_decode.c b/source/blender/imbuf/intern/bmp_decode.c
new file mode 100644
index 00000000000..d8b38f367e0
--- /dev/null
+++ b/source/blender/imbuf/intern/bmp_decode.c
@@ -0,0 +1,191 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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
+#include "BLI_winstuff.h"
+#endif
+#include "BLI_blenlib.h"
+
+#include "imbuf.h"
+#include "imbuf_patch.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "IMB_allocimbuf.h"
+#include "IMB_cmap.h"
+#include "IMB_bmp.h"
+
+
+// some code copied from article on microsoft.com, copied
+// here for enhanced BMP support in the future
+// http://www.microsoft.com/msj/defaultframe.asp?page=/msj/0197/mfcp1/mfcp1.htm&nav=/msj/0197/newnav.htm
+
+/*
+LPBYTE CDib::GetBits()
+ {
+ return (LPBYTE)m_pbmih + // start of bitmap +
+ m_pbmih->biSize + // size of header +
+ GetNumPaletteColors() // (num colors *
+ *sizeof(RGBQUAD); // size each entry)
+ }
+
+UINT CDib::GetNumPaletteColors()
+ {
+ UINT nColors=m_pbmih->biClrUsed;
+ if (nColors==0 && m_pbmih->biBitCount<=8)
+ nColors = 1<<m_pbmih->biBitCount;
+ return nColors;
+ }
+
+*/
+
+typedef struct BMPINFOHEADER{
+ unsigned int biSize;
+ int biWidth;
+ int biHeight;
+ unsigned short biPlanes;
+ unsigned short biBitCount;
+ unsigned int biCompression;
+ unsigned int biSizeImage;
+ int biXPelsPerMeter;
+ int biYPelsPerMeter;
+ unsigned int biClrUsed;
+ unsigned int biClrImportant;
+} BMPINFOHEADER;
+
+#define BMP_FILEHEADER_SIZE 14
+
+static int checkbmp(unsigned char *mem)
+{
+ int ret_val = 0;
+ BMPINFOHEADER bmi;
+ unsigned int u;
+
+ if (mem) {
+ if ((mem[0] == 'B') && (mem[1] == 'M')) {
+ // skip fileheader
+ mem += BMP_FILEHEADER_SIZE;
+ }
+
+ // for systems where an int needs to be 4 bytes aligned
+ memcpy(&bmi, mem, sizeof(bmi));
+
+ u = LITTLE_LONG(bmi.biSize);
+ // we only support uncompressed 24 or 32 bits images for now
+ if (u >= sizeof(BMPINFOHEADER)) {
+ if ((bmi.biCompression == 0) && (bmi.biClrUsed == 0)) {
+ u = LITTLE_SHORT(bmi.biBitCount);
+ if (u >= 16) {
+ ret_val = 1;
+ }
+ }
+ }
+ }
+
+ return(ret_val);
+}
+
+int imb_is_a_bmp(void *buf) {
+
+ return checkbmp(buf);
+}
+
+struct ImBuf *imb_bmp_decode(unsigned char *mem, int size, int flags)
+{
+ struct ImBuf *ibuf = 0;
+ BMPINFOHEADER bmi;
+ int x, y, depth, skip, i;
+ unsigned char *bmp, *rect;
+ unsigned short col;
+
+ if (checkbmp(mem) == 0) return(0);
+
+ if ((mem[0] == 'B') && (mem[1] == 'M')) {
+ // skip fileheader
+ mem += BMP_FILEHEADER_SIZE;
+ }
+
+ // for systems where an int needs to be 4 bytes aligned
+ memcpy(&bmi, mem, sizeof(bmi));
+
+ skip = LITTLE_LONG(bmi.biSize);
+ x = LITTLE_LONG(bmi.biWidth);
+ y = LITTLE_LONG(bmi.biHeight);
+ depth = LITTLE_SHORT(bmi.biBitCount);
+
+ // printf("skip: %d, x: %d y: %d, depth: %d (%x)\n", skip, x, y, depth, bmi.biBitCount);
+ if (flags & IB_test) {
+ ibuf = IMB_allocImBuf(x, y, depth, 0, 0);
+ } else {
+ ibuf = IMB_allocImBuf(x, y, depth, IB_rect, 0);
+ bmp = mem + skip;
+ rect = (unsigned char *) ibuf->rect;
+
+ if (depth == 16) {
+ for (i = x * y; i > 0; i--) {
+ col = bmp[0] + (bmp[1] << 8);
+ rect[0] = ((col >> 10) & 0x1f) << 3;
+ rect[1] = ((col >> 5) & 0x1f) << 3;
+ rect[2] = ((col >> 0) & 0x1f) << 3;
+
+ rect[3] = 255;
+ rect += 4; bmp += 2;
+ }
+
+ } else if (depth == 24) {
+ for (i = x * y; i > 0; i--) {
+ rect[0] = bmp[2];
+ rect[1] = bmp[1];
+ rect[2] = bmp[0];
+
+ rect[3] = 255;
+ rect += 4; bmp += 3;
+ }
+ } else if (depth == 32) {
+ for (i = x * y; i > 0; i--) {
+ rect[0] = bmp[0];
+ rect[1] = bmp[1];
+ rect[2] = bmp[2];
+ rect[3] = bmp[3];
+ rect += 4; bmp += 4;
+ }
+ }
+ }
+
+ if (ibuf) {
+ ibuf->ftype = BMP;
+ }
+
+ return(ibuf);
+}
+
diff --git a/source/blender/imbuf/intern/cmap.c b/source/blender/imbuf/intern/cmap.c
new file mode 100644
index 00000000000..300c3049dea
--- /dev/null
+++ b/source/blender/imbuf/intern/cmap.c
@@ -0,0 +1,589 @@
+/**
+ * cmap.c
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 <ctype.h>
+#include "BLI_blenlib.h"
+
+#include "imbuf.h"
+#include "imbuf_patch.h"
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "IMB_cmap.h"
+
+static short *lastcube = 0;
+static uchar *lastcoltab = 0;
+static short lastmaxcol;
+static short lastmincol;
+static short lastcbits;
+short alpha_col0 = FALSE;
+
+
+/*
+ * er zit nog ergens een bug/inconsequentie in het programma. Als je een plaatje om wilt zetten
+ * naar een colormap met 1 bit resolutie krijg je een zwart plaatje. Zowieso alles met minder
+ * dan 4 bits is te donker.
+ */
+
+void IMB_freeImBufdata(void)
+{
+ if (lastcube) free(lastcube);
+ lastcube= 0;
+ if (lastcoltab) free(lastcoltab);
+ lastcoltab= 0;
+}
+
+
+int IMB_alpha_to_col0(int new)
+{
+ int old;
+
+ old = alpha_col0;
+ alpha_col0 = new;
+ return (old);
+}
+
+
+void imb_losecmapbits(struct ImBuf *ibuf, unsigned int *coltab)
+{
+ int i,bits;
+ unsigned int col, and1, and2, *rect;
+
+ if (ibuf == 0) return;
+ if (ibuf->rect == 0) return;
+ if (ibuf->cbits == 0) return;
+ if (ibuf->cbits >= 8) return;
+
+ /*
+ bij cbits = 5:
+ and1 = 11100000;
+ bij cbits = 6:
+ and1 = 11000000;
+ */
+
+ bits = ibuf->cbits;
+ and1 = ((1 << (8-bits)) - 1) & 0xff;
+ and1 |= (and1 << 24) + (and1 << 16) + (and1 << 8);
+ and2 = ~and1;
+ and1 <<= bits;
+
+ rect = ibuf->rect;
+ for (i = ibuf->x * ibuf->y ; i > 0; i--) {
+ col = rect[0];
+ *rect++ = col - ((col & and1) >> bits);
+ }
+
+ if (coltab){
+ for (i = 0 ; i < ibuf->maxcol ; i++) {
+ col = coltab[i];
+ coltab[i] = (col - ((col & and1) >> bits)) & and2;
+ }
+ }
+}
+
+
+static void addcmapbits(struct ImBuf *ibuf)
+/* struct ImBuf *ibuf; */
+{
+ int i,bits;
+ int div,mul;
+ uchar * cmap;
+
+ if (ibuf == 0) return;
+ if (ibuf->cmap == 0) return;
+ if (ibuf->cbits == 0) return;
+ if (ibuf->cbits >= 8) return;
+
+ bits = ibuf->cbits;
+
+ /* bits = 4 -> div = 0xf0
+ * bits = 5 -> div = 0xf8
+ */
+
+ div = ((1 << bits) - 1) << (8 - bits);
+ mul = 0xffff / div;
+
+ if (ibuf->cmap){
+ cmap = (uchar *) ibuf->cmap;
+ for (i = 0 ; i < ibuf->maxcol ; i++){
+ cmap[1] = (mul * cmap[1]) >> 8;
+ cmap[2] = (mul * cmap[2]) >> 8;
+ cmap[3] = (mul * cmap[3]) >> 8;
+ cmap += 4;
+ }
+ }
+}
+
+
+static short addplanetocube(short *cube, short *plane, int minx, int miny, int sizep, int addcx, int addcy, int sizec, int col)
+{
+ short done = FALSE;
+ int x, numx, numy, skipc, skipp, temp;
+
+ /* eerst maar eens clippen */
+
+ numx = numy = sizep;
+
+ temp = minx + sizep - 1;
+ if (temp > sizec) numx -= temp - sizec;
+
+ temp = miny + sizep - 1;
+ if (temp > sizec) numy -= temp - sizec;
+
+ if (minx < 0){
+ plane -= minx;
+ cube -= minx * addcx;
+ numx += minx;
+ }
+
+ if (miny < 0){
+ plane -= miny * sizep;
+ cube -= miny * addcy;
+ numy += miny;
+ }
+
+ skipc = addcy - (numx * addcx);
+ skipp = sizep - numx;
+
+ for (; numy > 0 ; numy--){
+ for (x = numx ; x > 0; x--) {
+
+ if (plane[0] < cube[1]) {
+
+ cube[0] = col;
+ cube[1] = plane[0];
+ done = TRUE;
+ }
+ plane ++;
+ cube += addcx;
+ }
+ plane += skipp;
+ cube += skipc;
+ }
+
+ return (done);
+}
+
+
+
+short *imb_coldeltatab(unsigned char *coltab, short mincol, short maxcol, short cbits)
+{
+ short max, *quadr, *_quadr, *_cube, *cube, *_plane, done, nocol;
+ unsigned int addcb, addcg, addcr, sizep;
+ uchar *_colp, *colp, *col;
+ int i, j, k, addcube;
+ int r, g, b;
+
+ max = (1 << cbits) - 1;
+ nocol = maxcol - mincol;
+ coltab += 4 * mincol;
+
+ /* kleuren terugbrengen tot juiste hoeveelheid bits */
+
+ {
+ unsigned int * lctab, and;
+
+ lctab = (unsigned int *) coltab;
+ and = max << (8 - cbits);
+ and = and + (and << 8) + (and << 16) + (and << 24);
+ for (i=nocol-1 ; i >= 0 ; i--) lctab[i] = (lctab[i] & and) >> (8 - cbits);
+ }
+
+ /* zijn deze gegevens hetzelfde als de vorige ? */
+
+ if (lastcube){
+ if (mincol == lastmincol && maxcol == lastmaxcol && cbits == lastcbits){
+ if (lastcoltab){
+ if (memcmp(lastcoltab, coltab, 4 * nocol) == 0) return(lastcube);
+ }
+ }
+ }
+ if (lastcube) free(lastcube);
+ if (lastcoltab) free(lastcoltab);
+
+ lastcube = 0;
+ lastcoltab = 0;
+ _cube = malloc(2 * (1 << (3 * cbits)) * sizeof(short));
+ _plane = malloc((2 * max + 1) * (2 * max + 1) * sizeof(short));
+ _quadr = malloc((2 * max + 1) * sizeof(short));
+ _colp = malloc(6 * nocol);
+
+ if (_cube == 0 || _plane == 0 || _quadr == 0 || _colp == 0){
+ if (_cube) free(_cube);
+ if (_plane) free(_plane);
+ if (_quadr) free(_quadr);
+ if (_colp) free(_colp);
+ return(0);
+ }
+
+ lastcoltab = malloc(4 * nocol);
+ if (lastcoltab) memcpy(lastcoltab, coltab, 4 * nocol);
+ lastcube = _cube;
+ lastmincol = mincol;
+ lastmaxcol = maxcol;
+ lastcbits = cbits;
+
+ /* cube initialiseren */
+
+ cube = _cube;
+ for (i = (1 << (3 * cbits)); i > 0 ; i--){
+ cube[0] = 0;
+ cube[1] = 32767;
+ cube += 2;
+ }
+
+ /* error look up table aan maken */
+
+ {
+ unsigned int delta;
+
+ quadr = _quadr + max + 1;
+ quadr[0] = 0;
+ delta = 3;
+ for (i = 1 ; i <= max ; i++){
+ quadr[i] = quadr[-i] = delta;
+ delta += i + 3;
+ }
+ }
+
+ /* colorplane initialiseren */
+
+ for (i = 6 * nocol - 1; i >= 0; i--) _colp[i] = 1;
+
+ addcr = 2;
+ addcg = (addcr << cbits);
+ addcb = (addcg << cbits);
+
+ /* eerste ronde invullen */
+
+ {
+ unsigned int ofs;
+
+ col = coltab;
+ cube = _cube;
+
+ for (i = 0 ; i < nocol ; i++){
+ ofs = (col[3] * addcr) + (col[2] * addcg) + (col[1] * addcb);
+ /* is deze kleur al ingevuld -> dan overslaan */
+ if (cube[ofs + 1]) cube[ofs] = i + mincol;
+ cube[ofs + 1] = 0;
+ col += 4;
+ }
+ }
+
+ for (i = 1; i <= max ; i++){
+ colp = _colp;
+ col = coltab;
+ done = FALSE;
+ sizep = 2*i +1;
+
+ /* plane initialiseren */
+ {
+ unsigned int delta;
+ short *plane;
+
+ plane = _plane;
+ for (j = -i ; j <= i; j++){
+ delta = quadr[i] + quadr[j];
+ for (k = -i; k <= i; k++){
+ *plane++ = delta + quadr[k];
+ }
+ }
+ }
+
+ for (j = mincol; j < maxcol; j++){
+ b = col[1] - i;
+ g = col[2] - i;
+ r = col[3] - i;
+
+ addcube= (addcr * r) + (addcg * g) + (addcb * b);
+ /* PRINT4(d, d, d, d, addcube, r, g, b); */
+ /* if(addcube >= 2 * (1 << (3 * cbits))) { */
+ /* printf("maxerror: %d %d\n", addcube, 2 * (1 << (3 * cbits))); */
+ /* add_cube= 2 * (1 << (3 * cbits)) -1; */
+ /* } */
+ cube = _cube + addcube;
+
+ if (colp[0]){
+ if (b < 0) colp[0] = 0;
+ else done |= colp[0] = addplanetocube(cube, _plane, r, g, sizep, addcr, addcg, max, j);
+ }
+ if (colp[1]){
+ if (g < 0) colp[1] = 0;
+ else done |= colp[1] = addplanetocube(cube, _plane, r, b, sizep, addcr, addcb, max, j);
+ }
+ if (colp[2]){
+ if (r < 0) colp[2] = 0;
+ else done |= colp[2] = addplanetocube(cube, _plane, b, g, sizep, addcb, addcg, max, j);
+ }
+ if (colp[3]){
+ if ((b + sizep - 1) > max) colp[3] = 0;
+ else done |= colp[3] = addplanetocube(cube + (sizep -1) * addcb, _plane, r, g, sizep, addcr,
+ addcg, max, j);
+ }
+ if (colp[4]){
+ if ((g + sizep - 1) > max) colp[4] = 0;
+ else done |= colp[4] = addplanetocube(cube + (sizep -1) * addcg, _plane, r, b, sizep, addcr,
+ addcb, max, j);
+ }
+ if (colp[5]){
+ if ((r + sizep - 1) > max) colp[5] = 0;
+ else done |= colp[5] = addplanetocube(cube + (sizep -1) * addcr, _plane, b, g, sizep, addcb,
+ addcg, max, j);
+ }
+
+ colp += 6;
+ col += 4;
+ }
+ if (done == 0) break;
+ }
+
+ free(_quadr);
+ free(_plane);
+ free(_colp);
+ return(_cube);
+}
+
+
+static void convcmap(struct ImBuf* ibuf, short *deltab, short cbits)
+/* struct ImBuf* ibuf; */
+/* short *deltab,cbits; */
+{
+ unsigned int *rect;
+ short x,y;
+ unsigned int col;
+ unsigned int bbits,gbits,rbits;
+ unsigned int bmask,gmask,rmask;
+
+ bbits = 24 - 3 * cbits - 1;
+ gbits = 16 - 2 * cbits - 1;
+ rbits = 8 - cbits - 1;
+
+ rmask = ((1 << cbits) - 1) << (8 - cbits);
+ gmask = rmask << 8;
+ bmask = gmask << 8;
+
+ rect =(unsigned int *)ibuf->rect;
+
+ for(y=ibuf->y;y>0;y--){
+ for(x=ibuf->x;x>0;x--){
+ col = *rect;
+ col = ((col & bmask) >> bbits) + ((col & gmask) >> gbits) + ((col & rmask) >> rbits);
+ *rect++ = deltab[col];
+ }
+ }
+}
+
+short IMB_converttocmap(struct ImBuf *ibuf)
+{
+ unsigned int *coltab;
+ short *deltab=0, cbits;
+ int i;
+ int mincol, mask;
+ struct ImBuf * abuf = 0;
+ unsigned int * rect, * arect;
+
+ cbits = 5;
+ if (ibuf->cmap == 0) return(0);
+
+ if ((ibuf->cbits > 0) && (ibuf->cbits <8)) cbits = ibuf->cbits;
+
+ coltab = calloc(ibuf->maxcol, sizeof(unsigned int));
+ if (coltab == 0) return(0);
+ memcpy(coltab, ibuf->cmap, ibuf->maxcol * sizeof(unsigned int));
+
+ mincol = ibuf->mincol;
+ if (alpha_col0) {
+ if (mincol == 0) mincol = 1;
+ abuf = IMB_dupImBuf(ibuf);
+ }
+
+ imb_losecmapbits(ibuf, coltab);
+ deltab = imb_coldeltatab((uchar *) coltab, mincol ,ibuf->maxcol, cbits);
+
+ if (deltab == 0) {
+ free(coltab);
+ if (abuf) IMB_freeImBuf(abuf);
+ return(0);
+ }
+
+
+ IMB_dit0(ibuf,1,cbits);
+ IMB_dit0(ibuf,2,cbits);
+ IMB_dit0(ibuf,3,cbits);
+ convcmap(ibuf, deltab, cbits);
+
+ if (abuf) {
+ /* alpha omzetten naar kleur 0 */
+ rect = ibuf->rect;
+ arect = abuf->rect;
+
+ if (alpha_col0 == 1) mask = 0xff000000; /* alpha == 0 -> 0 */
+ if (alpha_col0 == 2) mask = 0x80000000; /* alpha < 128 -> 0 */
+
+ for (i = ibuf->x * ibuf->y; i > 0; i--) {
+ if ((*arect++ & mask) == 0) rect[0] = 0;
+ rect++;
+ }
+
+ IMB_freeImBuf(abuf);
+ }
+
+ free(coltab);
+
+ return (TRUE);
+}
+
+
+void imb_makecolarray(struct ImBuf *ibuf, unsigned char *mem, short nocols)
+/* struct ImBuf *ibuf; */
+/* uchar *mem; */
+/* short nocols; */
+{
+ short i,bits = 0;
+ uchar *cmap;
+
+ /* wat is hier de theorie achter */
+
+ nocols = ibuf->maxcol;
+
+ if (ibuf->cmap){
+ cmap = (uchar *) ibuf->cmap;
+ for (i = 0; i < nocols; i++){
+ cmap[3] = mem[0];
+ cmap[2] = mem[1];
+ cmap[1] = mem[2];
+ cmap[0] = 0;
+
+ bits |= mem[0] | mem[1] | mem[2];
+ mem += 3;
+ cmap += 4;
+ }
+
+ /* patch voor AdPro II */
+ if (IS_ham(ibuf)){
+ i = ibuf->depth - 2;
+ bits = ((1 << i) - 1) << (8 - i);
+ for (i=0 ; i<nocols ; i++) ibuf->cmap[i] &= (bits << 24) + (bits << 16) + (bits << 8) + bits;
+ }
+
+ if ((bits & 0x1f) == 0){
+ ibuf->cbits = 3;
+ } else if ((bits & 0x0f) == 0){
+ ibuf->cbits = 4;
+ } else if ((bits & 0x07) == 0){
+ ibuf->cbits = 5;
+ } else if ((bits & 0x03) == 0){
+ ibuf->cbits = 6;
+ } else ibuf->cbits = 8;
+
+ addcmapbits(ibuf);
+
+ if (IS_hbrite(ibuf)){
+ for (i=31;i>=0;i--){
+ ibuf->cmap[i+32] = (ibuf->cmap[i] & 0xfefefefe) >> 1;
+ }
+ }
+
+ if (IS_amiga(ibuf)){
+ cmap = (uchar * ) (ibuf->cmap + 1);
+ for (i = 1; i < nocols; i++){
+ cmap[0] = 0xff;
+ cmap += 4;
+ }
+ }
+ }
+}
+
+/* temporal... rects now are rgba, cmaps are abgr */
+#define SWITCH_INT(a) {char s_i, *p_i; p_i= (char *)&(a); s_i= p_i[0]; p_i[0]= p_i[3]; p_i[3]= s_i; s_i= p_i[1]; p_i[1]= p_i[2]; p_i[2]= s_i; }
+
+void IMB_applycmap(struct ImBuf *ibuf)
+/* struct ImBuf *ibuf; */
+{
+ unsigned int *rect, *cmap;
+ int x, y, i, col, code;
+ int *mask = 0;
+
+ if (ibuf == 0) return;
+ if (ibuf->rect == 0 || ibuf->cmap == 0) return;
+
+ rect = ibuf->rect;
+ cmap = ibuf->cmap;
+
+ if (IS_ham(ibuf)){
+
+ /* masker genereren maximaal (8 + 2) bits */
+ mask = malloc(1024 * 2 * sizeof(int));
+
+ x = 1 << (ibuf->depth - 2);
+ y = 65535 / (x - 1);
+
+ for (i = 0; i < x; i++){
+ mask[i] = 0;
+ mask[i + x] = 0x00ffff;
+ mask[i + x + x] = 0xffff00;
+ mask[i + x + x + x] = 0xff00ff;
+
+ col = (y * i) >> 8;
+
+ mask[i + 1024] = 0xff000000 | ibuf->cmap[i];
+ mask[i + x + 1024] = 0xff000000 | col << 16;
+ mask[i + x + x + 1024] = 0xff000000 | col;
+ mask[i + x + x + x + 1024] = 0xff000000 | col << 8;
+ }
+
+ /* alleen kleur 0 transparant */
+ mask[0+1024] =ibuf->cmap[0];
+
+ for (y = ibuf->y ; y>0 ; y--){
+ col = cmap[0];
+ for (x=ibuf->x ; x>0 ; x--){
+ code = *rect;
+ *rect++ = col = (col & mask[code]) | mask[code + 1024];
+ }
+ }
+ free(mask);
+ } else {
+
+ for(i = ibuf->x * ibuf->y; i>0; i--){
+ col = *rect;
+ if (col >= 0 && col < ibuf->maxcol) *rect = cmap[col];
+ rect++;
+
+ /* *(rect++) = cmap[*rect]; */
+ }
+ }
+}
+
diff --git a/source/blender/imbuf/intern/cspace.c b/source/blender/imbuf/intern/cspace.c
new file mode 100644
index 00000000000..5cd2da5a998
--- /dev/null
+++ b/source/blender/imbuf/intern/cspace.c
@@ -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 *****
+ */
+
+#include "BLI_blenlib.h"
+
+#include "imbuf.h"
+#include "imbuf_patch.h"
+#include "IMB_imbuf_types.h"
+
+/************************************************************************/
+/* COLORSPACE */
+/************************************************************************/
+
+static void fillmattab(double val, unsigned short *mattab)
+{
+ int tot,ival;
+ int i;
+
+ val *= (1 << 22);
+ ival = val;
+ tot = 32767; /* een half */
+
+ for(i = 256; i > 0; i--){
+ *(mattab) = (tot >> 16);
+ mattab += 3;
+ tot += ival;
+ }
+}
+
+
+static void cspfill(short *buf, short *fill, int x)
+{
+ short r,g,b;
+
+ b = fill[0];
+ g = fill[1];
+ r = fill[2];
+ for (;x>0;x--){
+ buf[0] = b;
+ buf[1] = g;
+ buf[2] = r;
+ buf += 3;
+ }
+}
+
+
+static void cspadd(short *buf, short cont[][3], unsigned char *rect, int x)
+{
+ short i;
+ for (;x>0;x--){
+ i = *(rect);
+ rect += 4;
+ buf[0] += cont[i][0];
+ buf[1] += cont[i][1];
+ buf[2] += cont[i][2];
+ buf += 3;
+ }
+}
+
+
+static void cspret(short *buf, unsigned char *rect, int x)
+{
+ int r,g,b;
+
+ for(; x > 0; x--){
+ b = buf[0];
+ g = buf[1];
+ r = buf[2];
+
+ if (b & 0x4000){
+ if (b<0) rect[2]=0;
+ else rect[2]=255;
+ } else rect[2] = b >> 6;
+
+ if (g & 0x4000){
+ if (g<0) rect[1]=0;
+ else rect[1]=255;
+ } else rect[1] = g >> 6;
+
+ if (r & 0x4000){
+ if (r<0) rect[0]=0;
+ else rect[0]=255;
+ } else rect[0] = r >> 6;
+
+ buf += 3;
+ rect += 4;
+ }
+}
+
+
+static void rotcspace(struct ImBuf *ibuf, short *cont_1, short *cont_2, short *cont_3, short *add)
+{
+ short x,y,*buf;
+ uchar *rect;
+
+ x=ibuf->x;
+ rect= (uchar *)ibuf->rect;
+
+ buf=(short *)malloc(x*3*sizeof(short));
+ if (buf){
+ for(y=ibuf->y;y>0;y--){
+ cspfill(buf,add,x);
+ cspadd(buf,cont_1,rect+0,x);
+ cspadd(buf,cont_2,rect+1,x);
+ cspadd(buf,cont_3,rect+2,x);
+ cspret(buf,rect,x);
+ rect += x<<2;
+ }
+ free(buf);
+ }
+}
+
+
+void IMB_cspace(struct ImBuf *ibuf, float mat[][4])
+{
+ short *cont_1,*cont_2,*cont_3,add[3];
+
+ cont_1=(short *)malloc(256*3*sizeof(short));
+ cont_2=(short *)malloc(256*3*sizeof(short));
+ cont_3=(short *)malloc(256*3*sizeof(short));
+
+ if (cont_1 && cont_2 && cont_3){
+
+ fillmattab(mat[0][0],cont_1);
+ fillmattab(mat[0][1],cont_1+1);
+ fillmattab(mat[0][2],cont_1+2);
+
+ fillmattab(mat[1][0],cont_2);
+ fillmattab(mat[1][1],cont_2+1);
+ fillmattab(mat[1][2],cont_2+2);
+
+ fillmattab(mat[2][0],cont_3);
+ fillmattab(mat[2][1],cont_3+1);
+ fillmattab(mat[2][2],cont_3+2);
+
+ add[0] = (mat[3][0] * 64.0) + .5;
+ add[1] = (mat[3][1] * 64.0) + .5;
+ add[2] = (mat[3][2] * 64.0) + .5;
+
+ rotcspace(ibuf, cont_1, cont_2, cont_3, add);
+ }
+
+ if (cont_1) free(cont_1);
+ if (cont_2) free(cont_2);
+ if (cont_3) free(cont_3);
+}
+
diff --git a/source/blender/imbuf/intern/data.c b/source/blender/imbuf/intern/data.c
new file mode 100644
index 00000000000..ad9194cb80e
--- /dev/null
+++ b/source/blender/imbuf/intern/data.c
@@ -0,0 +1,145 @@
+/**
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * data.c
+ *
+ * $Id$
+ */
+
+#include "imbuf.h"
+#include "matrix.h"
+
+/*
+static short quadbase[31] = {
+ 150,133,117,102,
+ 88,75,63,52,
+ 42,33,25,18,
+ 12,7,3,0,
+ 3,7,12,18,
+ 25,33,42,52,
+ 63,75,88,102,
+ 117,133,150,
+};
+
+short *quadr = quadbase+15;
+*/
+/*
+main()
+{
+ ushort _quadr[511], *quadr;
+ int i, delta;
+
+ quadr = _quadr + 255;
+
+ delta = 0;
+ for (i = 0 ; i <= 255 ; i++){
+ quadr[i] = quadr[-i] = delta;
+ delta += i + 3;
+ }
+
+ delta = 0;
+ for (i = 0; i < 511; i++){
+ printf("%6d, ", _quadr[i]);
+ delta++;
+ if (delta == 8){
+ delta = 0;
+ printf("\n");
+ }
+ }
+}
+*/
+
+static unsigned short quadbase[511] = {
+ 33150, 32893, 32637, 32382, 32128, 31875, 31623, 31372,
+ 31122, 30873, 30625, 30378, 30132, 29887, 29643, 29400,
+ 29158, 28917, 28677, 28438, 28200, 27963, 27727, 27492,
+ 27258, 27025, 26793, 26562, 26332, 26103, 25875, 25648,
+ 25422, 25197, 24973, 24750, 24528, 24307, 24087, 23868,
+ 23650, 23433, 23217, 23002, 22788, 22575, 22363, 22152,
+ 21942, 21733, 21525, 21318, 21112, 20907, 20703, 20500,
+ 20298, 20097, 19897, 19698, 19500, 19303, 19107, 18912,
+ 18718, 18525, 18333, 18142, 17952, 17763, 17575, 17388,
+ 17202, 17017, 16833, 16650, 16468, 16287, 16107, 15928,
+ 15750, 15573, 15397, 15222, 15048, 14875, 14703, 14532,
+ 14362, 14193, 14025, 13858, 13692, 13527, 13363, 13200,
+ 13038, 12877, 12717, 12558, 12400, 12243, 12087, 11932,
+ 11778, 11625, 11473, 11322, 11172, 11023, 10875, 10728,
+ 10582, 10437, 10293, 10150, 10008, 9867, 9727, 9588,
+ 9450, 9313, 9177, 9042, 8908, 8775, 8643, 8512,
+ 8382, 8253, 8125, 7998, 7872, 7747, 7623, 7500,
+ 7378, 7257, 7137, 7018, 6900, 6783, 6667, 6552,
+ 6438, 6325, 6213, 6102, 5992, 5883, 5775, 5668,
+ 5562, 5457, 5353, 5250, 5148, 5047, 4947, 4848,
+ 4750, 4653, 4557, 4462, 4368, 4275, 4183, 4092,
+ 4002, 3913, 3825, 3738, 3652, 3567, 3483, 3400,
+ 3318, 3237, 3157, 3078, 3000, 2923, 2847, 2772,
+ 2698, 2625, 2553, 2482, 2412, 2343, 2275, 2208,
+ 2142, 2077, 2013, 1950, 1888, 1827, 1767, 1708,
+ 1650, 1593, 1537, 1482, 1428, 1375, 1323, 1272,
+ 1222, 1173, 1125, 1078, 1032, 987, 943, 900,
+ 858, 817, 777, 738, 700, 663, 627, 592,
+ 558, 525, 493, 462, 432, 403, 375, 348,
+ 322, 297, 273, 250, 228, 207, 187, 168,
+ 150, 133, 117, 102, 88, 75, 63, 52,
+ 42, 33, 25, 18, 12, 7, 3, 0,
+ 3, 7, 12, 18, 25, 33, 42, 52,
+ 63, 75, 88, 102, 117, 133, 150, 168,
+ 187, 207, 228, 250, 273, 297, 322, 348,
+ 375, 403, 432, 462, 493, 525, 558, 592,
+ 627, 663, 700, 738, 777, 817, 858, 900,
+ 943, 987, 1032, 1078, 1125, 1173, 1222, 1272,
+ 1323, 1375, 1428, 1482, 1537, 1593, 1650, 1708,
+ 1767, 1827, 1888, 1950, 2013, 2077, 2142, 2208,
+ 2275, 2343, 2412, 2482, 2553, 2625, 2698, 2772,
+ 2847, 2923, 3000, 3078, 3157, 3237, 3318, 3400,
+ 3483, 3567, 3652, 3738, 3825, 3913, 4002, 4092,
+ 4183, 4275, 4368, 4462, 4557, 4653, 4750, 4848,
+ 4947, 5047, 5148, 5250, 5353, 5457, 5562, 5668,
+ 5775, 5883, 5992, 6102, 6213, 6325, 6438, 6552,
+ 6667, 6783, 6900, 7018, 7137, 7257, 7378, 7500,
+ 7623, 7747, 7872, 7998, 8125, 8253, 8382, 8512,
+ 8643, 8775, 8908, 9042, 9177, 9313, 9450, 9588,
+ 9727, 9867, 10008, 10150, 10293, 10437, 10582, 10728,
+ 10875, 11023, 11172, 11322, 11473, 11625, 11778, 11932,
+ 12087, 12243, 12400, 12558, 12717, 12877, 13038, 13200,
+ 13363, 13527, 13692, 13858, 14025, 14193, 14362, 14532,
+ 14703, 14875, 15048, 15222, 15397, 15573, 15750, 15928,
+ 16107, 16287, 16468, 16650, 16833, 17017, 17202, 17388,
+ 17575, 17763, 17952, 18142, 18333, 18525, 18718, 18912,
+ 19107, 19303, 19500, 19698, 19897, 20097, 20298, 20500,
+ 20703, 20907, 21112, 21318, 21525, 21733, 21942, 22152,
+ 22363, 22575, 22788, 23002, 23217, 23433, 23650, 23868,
+ 24087, 24307, 24528, 24750, 24973, 25197, 25422, 25648,
+ 25875, 26103, 26332, 26562, 26793, 27025, 27258, 27492,
+ 27727, 27963, 28200, 28438, 28677, 28917, 29158, 29400,
+ 29643, 29887, 30132, 30378, 30625, 30873, 31122, 31372,
+ 31623, 31875, 32128, 32382, 32637, 32893, 33150,
+};
+
+unsigned short *quadr = quadbase + 255;
diff --git a/source/blender/imbuf/intern/dither.c b/source/blender/imbuf/intern/dither.c
new file mode 100644
index 00000000000..608332af244
--- /dev/null
+++ b/source/blender/imbuf/intern/dither.c
@@ -0,0 +1,133 @@
+/**
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * dither.c
+ *
+ * $Id$
+ */
+
+#include "BLI_blenlib.h"
+
+#include "imbuf.h"
+#include "imbuf_patch.h"
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+void IMB_dit0(struct ImBuf * ibuf, short ofs, short bits)
+{
+ int x, y, and, add, pix;
+ uchar *rect;
+
+ rect= (uchar *)ibuf->rect;
+ rect +=ofs;
+
+ bits = 8 - bits;
+ and = ~((1 << bits)-1);
+ add = 1 << (bits - 1);
+
+ for (y = ibuf->y; y > 0; y--){
+ for (x = ibuf->x; x > 0; x--) {
+ pix = *rect + add;
+ if (pix > 255) pix = 255;
+ *rect = pix & and;
+ rect += 4;
+ }
+ }
+}
+
+void IMB_dit2(struct ImBuf * ibuf, short ofs, short bits)
+{
+ short x,y,pix,and,add1,add2;
+ uchar *rect;
+ uchar dit[4];
+
+ rect= (uchar *)ibuf->rect;
+ rect +=ofs;
+
+ bits = 8 - bits;
+ and = ~((1<<bits)-1);
+ bits -= 2;
+
+ ofs = 0;
+
+ switch(ofs){
+ case 3:
+ break;
+ case 2:
+ dit[0]=0;
+ dit[1]=1;
+ dit[2]=2;
+ dit[3]=3;
+ break;
+ case 1:
+ dit[0]=3;
+ dit[1]=1;
+ dit[2]=0;
+ dit[3]=2;
+ break;
+ case 0:
+ dit[0]=0;
+ dit[1]=2;
+ dit[2]=3;
+ dit[3]=1;
+ break;
+ }
+
+ if (bits < 0){
+ dit[0] >>= -bits;
+ dit[1] >>= -bits;
+ dit[2] >>= -bits;
+ dit[3] >>= -bits;
+ } else{
+ dit[0] <<= bits;
+ dit[1] <<= bits;
+ dit[2] <<= bits;
+ dit[3] <<= bits;
+ }
+
+ for(y=ibuf->y;y>0;y--){
+ if(y & 1){
+ add1=dit[0];
+ add2=dit[1];
+ }
+ else{
+ add1=dit[2];
+ add2=dit[3];
+ }
+ for(x=ibuf->x;x>0;x--){
+ pix = *rect;
+ if (x & 1) pix += add1;
+ else pix += add2;
+
+ if (pix>255) pix=255;
+ *rect = pix & and;
+ rect += 4;
+ }
+ }
+}
diff --git a/source/blender/imbuf/intern/divers.c b/source/blender/imbuf/intern/divers.c
new file mode 100644
index 00000000000..81484ef6dfc
--- /dev/null
+++ b/source/blender/imbuf/intern/divers.c
@@ -0,0 +1,119 @@
+/**
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * allocimbuf.c
+ *
+ * $Id$
+ */
+
+#include "BLI_blenlib.h"
+
+#include "imbuf.h"
+#include "imbuf_patch.h"
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "IMB_divers.h"
+
+
+void imb_checkncols(struct ImBuf *ibuf)
+/* struct ImBuf *ibuf; */
+{
+ unsigned int i;
+
+ if (ibuf==0) return;
+
+ if (IS_amiga(ibuf)){
+ if (IS_ham(ibuf)){
+ if (ibuf->depth == 0) ibuf->depth = 6;
+ ibuf->mincol = 0;
+ ibuf->maxcol = 1 << (ibuf->depth - 2);
+ /*printf("%d %d\n", ibuf->maxcol, ibuf->depth);*/
+ return;
+ } else if (IS_hbrite(ibuf)){
+ ibuf->mincol = 0;
+ ibuf->maxcol = 64;
+ ibuf->depth = 6;
+ return;
+ }
+ }
+
+ if (ibuf->maxcol == 0){
+ if (ibuf->depth <= 8){
+ ibuf->mincol = 0;
+ ibuf->maxcol = (1 << ibuf->depth);
+ return;
+ } else if (ibuf->depth == 0){
+ ibuf->depth = 5;
+ ibuf->mincol = 0;
+ ibuf->maxcol = 32;
+ }
+ return;
+ } else {
+ /* ibuf->maxcol is bepalend voor de diepte */
+ for (i=1 ; ibuf->maxcol > (1 << i); i++);
+ ibuf->depth = i;
+ return;
+ }
+}
+
+
+void IMB_de_interlace(struct ImBuf *ibuf)
+{
+ struct ImBuf * tbuf1, * tbuf2;
+/* extern rectcpy(); */
+
+ if (ibuf == 0) return;
+ if (ibuf->flags & IB_fields) return;
+ ibuf->flags |= IB_fields;
+
+ if (ibuf->rect) {
+ /* kopieen aanmaken */
+ tbuf1 = IMB_allocImBuf(ibuf->x, ibuf->y / 2, 32, IB_rect, 0);
+ tbuf2 = IMB_allocImBuf(ibuf->x, ibuf->y / 2, 32, IB_rect, 0);
+
+ ibuf->x *= 2;
+/* Functions need more args :( */
+/* rectop(tbuf1, ibuf, 0, 0, 0, 0, 32767, 32767, rectcpy); */
+/* rectop(tbuf2, ibuf, 0, 0, tbuf2->x, 0, 32767, 32767, rectcpy); */
+ IMB_rectop(tbuf1, ibuf, 0, 0, 0, 0, 32767, 32767, IMB_rectcpy, 0);
+ IMB_rectop(tbuf2, ibuf, 0, 0, tbuf2->x, 0, 32767, 32767, IMB_rectcpy, 0);
+
+ ibuf->x /= 2;
+/* rectop(ibuf, tbuf1, 0, 0, 0, 0, 32767, 32767, rectcpy); */
+/* rectop(ibuf, tbuf2, 0, tbuf2->y, 0, 0, 32767, 32767, rectcpy); */
+ IMB_rectop(ibuf, tbuf1, 0, 0, 0, 0, 32767, 32767, IMB_rectcpy, 0);
+ IMB_rectop(ibuf, tbuf2, 0, tbuf2->y, 0, 0, 32767, 32767, IMB_rectcpy, 0);
+
+ IMB_freeImBuf(tbuf1);
+ IMB_freeImBuf(tbuf2);
+ }
+ ibuf->y /= 2;
+}
+
diff --git a/source/blender/imbuf/intern/filter.c b/source/blender/imbuf/intern/filter.c
new file mode 100644
index 00000000000..dfc6e26e68a
--- /dev/null
+++ b/source/blender/imbuf/intern/filter.c
@@ -0,0 +1,144 @@
+/**
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * filter.c
+ *
+ * $Id$
+ */
+
+#include "BLI_blenlib.h"
+
+#include "imbuf.h"
+#include "imbuf_patch.h"
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "IMB_filter.h"
+
+
+/************************************************************************/
+/* FILTERS */
+/************************************************************************/
+
+static void filtrow(unsigned char *point, int x)
+{
+ unsigned int c1,c2,c3,error;
+
+ if (x>1){
+ c1 = c2 = *point;
+ error = 2;
+ for(x--;x>0;x--){
+ c3 = point[4];
+ c1 += (c2<<1) + c3 + error;
+ error = c1 & 3;
+ *point = c1 >> 2;
+ point += 4;
+ c1=c2;
+ c2=c3;
+ }
+ *point = (c1 + (c2<<1) + c2 + error) >> 2;
+ }
+}
+
+
+static void filtcolum(unsigned char *point, int y, int skip)
+{
+ unsigned int c1,c2,c3,error;
+ unsigned char *point2;
+
+ if (y>1){
+ c1 = c2 = *point;
+ point2 = point;
+ error = 2;
+ for(y--;y>0;y--){
+ point2 += skip;
+ c3 = *point2;
+ c1 += (c2<<1) + c3 +error;
+ error = c1 & 3;
+ *point = c1 >> 2;
+ point=point2;
+ c1=c2;
+ c2=c3;
+ }
+ *point = (c1 + (c2<<1) + c2 + error) >> 2;
+ }
+}
+
+
+void IMB_filtery(struct ImBuf *ibuf)
+{
+ unsigned char *point;
+ short x,y,skip;
+
+ point = (unsigned char *)ibuf->rect;
+ x = ibuf->x;
+ y = ibuf->y;
+ skip = x<<2;
+
+ for (;x>0;x--){
+ if (ibuf->depth > 24) filtcolum(point,y,skip);
+ point++;
+ filtcolum(point,y,skip);
+ point++;
+ filtcolum(point,y,skip);
+ point++;
+ filtcolum(point,y,skip);
+ point++;
+ }
+}
+
+
+void imb_filterx(struct ImBuf *ibuf)
+{
+ unsigned char *point;
+ short x,y,skip;
+
+ point = (unsigned char *)ibuf->rect;
+ x = ibuf->x;
+ y = ibuf->y;
+ skip = (x<<2) - 3;
+
+ for (;y>0;y--){
+ if (ibuf->depth > 24) filtrow(point,x);
+ point++;
+ filtrow(point,x);
+ point++;
+ filtrow(point,x);
+ point++;
+ filtrow(point,x);
+ point+=skip;
+ }
+}
+
+
+void IMB_filter(struct ImBuf *ibuf)
+{
+ IMB_filtery(ibuf);
+ imb_filterx(ibuf);
+}
diff --git a/source/blender/imbuf/intern/ham.c b/source/blender/imbuf/intern/ham.c
new file mode 100644
index 00000000000..f9c6cf996a0
--- /dev/null
+++ b/source/blender/imbuf/intern/ham.c
@@ -0,0 +1,290 @@
+/**
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * ham.c
+ *
+ * $Id$
+ */
+
+#include "BLI_blenlib.h"
+
+#include "imbuf.h"
+#include "imbuf_patch.h"
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "IMB_cmap.h"
+#include "IMB_hamx.h"
+#include "IMB_ham.h"
+
+extern short alpha_col0;
+
+#define HAMB 0x0100
+#define HAMG 0x0400
+#define HAMR 0x0200
+#define HAMC 0x1000
+#define HAMFREE 0x2000
+
+static void addhamdither(short x, unsigned char *dit,
+ short dmax, unsigned char *rgb,
+ unsigned short *ham,
+ short type, short round, short shift)
+/* short x, dmax, type, round, shift; */
+/* uchar *dit, *rgb; */
+/* unsigned short *ham; */
+{
+ short dx = 0;
+ short c1, c2;
+
+ for (;x>0;x--){
+ if (ham[0] & (HAMFREE | type)){
+ c2 = c1 = *rgb;
+
+ /* wrap dither */
+ while (dx >= dmax) dx -= dmax;
+
+ c1 += dit[dx];
+ if (c1 > 255) c1 = 255;
+ c2 += round;
+ if (c2 > 255) c2 = 255;
+
+ if (c1 != c2){
+ c1 >>= shift; c2 >>= shift;
+ if (ham[1] & HAMFREE){
+ ham[0] = type + c1;
+ ham[1] = type + c2;
+ } else if (ham[1] & type){
+ ham[0] = type + c1;
+ } else if ((ham[2] & (type | HAMFREE)) == type){
+ ham[0] = type + c1;
+ } else if ((ham[1] & HAMC) | (ham[2] & HAMC)){
+ ham[0] = type + c1;
+ }
+ }
+ }
+ rgb += 4;
+ ham ++;
+ dx ++;
+ }
+}
+
+static void convhamscanl(short x, short y,
+ unsigned char *rgbbase,
+ unsigned char coltab[][4],
+ short *deltab,
+ short bits)
+/* short x, y, bits; */
+/* uchar *rgbbase; */
+/* uchar coltab[][4]; */
+/* short *deltab; */
+{
+ int a, r, g, b, lr, lg, lb, dr, dg, db, col, fout, type, x2;
+ int round, shift;
+ uchar *rgb, dit[2];
+ unsigned short *ham, *hambase;
+
+ /* Opzet:
+ eerst wordt het gehele plaatje afgelopen, waarbij kleurovergangen gecodeerd
+ worden: FGRB XXXX XXXX
+ F - vrije kleurwaarde, mag door ieder veranderd worden
+ G/R/B - groen/rood/blauw ham overgang, alleen door die kleur te veranderen
+ XXXX XXXX - N bits waarde.
+
+ 0000 XXXX XXXX is palet kleur.
+
+ daarna wordt eerst de groen dither toegevoegd, dan de rood dither en
+ tenslotte wordt blauwdither toegevoegd
+ */
+
+ if ((hambase = (unsigned short *) malloc((x+4) * sizeof(unsigned short)))==0) return;
+
+ lb = coltab[0][1];
+ lg = coltab[0][2];
+ lr = coltab[0][3];
+ type = col = 0;
+
+ ham = hambase;
+ rgb = rgbbase;
+
+ shift = 8 - bits;
+ round = 1 << (shift - 1);
+
+ /* om te voorkomen dat er 'ruis' ontstaat aan het einde van de regel */
+ for (x2 = 3; x2 >= 0; x2 --) hambase[x + x2] = HAMFREE;
+
+ for (x2 = x ;x2 > 0; x2--){
+ r = rgb[0] + round;
+ g = rgb[1] + round;
+ b = rgb[2] + round;
+ a = rgb[3];
+
+ if (a < 128 && alpha_col0) {
+ a = 1;
+ } else a = 0;
+
+ if (b > 255) b = 255;
+ if (g > 255) {
+ g = 255;
+ }
+ if (r > 255) r = 255;
+
+ r >>= shift;
+ g >>= shift;
+ b >>= shift;
+
+ if ((b-lb) | (g-lg) | (r-lr) | a){
+ if (a) {
+ col = 0;
+ type = HAMC;
+ } else {
+ col = ((b << (2 * bits)) + (g << bits) + r) << 1;
+ fout = deltab[col + 1];
+ col = deltab[col];
+ type = HAMC;
+
+ dr = quadr[lr-r];
+ dg = quadr[lg-g];
+ db = quadr[lb-b];
+
+ if ((dr+dg) <= fout){
+ fout = dr+dg;
+ col = b;
+ type = HAMB;
+ }
+ if ((dg+db) <= fout){
+ fout = dg+db;
+ col = r;
+ type = HAMR;
+ }
+ if ((dr+db) <= fout){
+ fout = dr+db;
+ col = g;
+ type = HAMG;
+ }
+ }
+
+ switch(type){
+ case HAMG:
+ lg = g;
+ break;
+ case HAMR:
+ lr = r;
+ break;
+ case HAMB:
+ lb = b;
+ break;
+ default:
+ lb = coltab[col][1];
+ lg = coltab[col][2];
+ lr = coltab[col][3];
+ }
+ *ham = type + col;
+ } else *ham = HAMG + HAMFREE + g;
+
+ rgb += 4;
+ ham ++;
+ }
+
+
+ if (y & 1){
+ dit[0] = 0 << (shift - 2);
+ dit[1] = 3 << (shift - 2);
+ } else {
+ dit[0] = 2 << (shift - 2);
+ dit[1] = 1 << (shift - 2);
+ }
+
+ addhamdither(x,dit,2,rgbbase+2,hambase,HAMG, round, shift);
+
+ if ((y & 1)==0){
+ dit[0] = 3 << (shift - 2);
+ dit[1] = 0 << (shift - 2);
+ } else {
+ dit[0] = 1 << (shift - 2);
+ dit[1] = 2 << (shift - 2);
+ }
+
+ addhamdither(x,dit,2,rgbbase+3,hambase,HAMR, round, shift);
+ addhamdither(x,dit,2,rgbbase+1,hambase,HAMB, round, shift);
+
+
+ ham = hambase;
+ rgb = rgbbase;
+ rgb += 3;
+
+ for (x2=x;x2>0;x2--){
+ type = *(ham++);
+ if (type & HAMG) type |= HAMR | HAMB;
+
+ *rgb = (type & 0xff) | ((type & (HAMR | HAMB)) >> shift);
+ rgb += 4;
+ }
+
+ free (hambase);
+}
+
+
+short imb_converttoham(struct ImBuf *ibuf)
+/* struct ImBuf* ibuf; */
+{
+ unsigned int coltab[256],*rect;
+ short x,y,* deltab;
+ int mincol;
+
+ memcpy(coltab,ibuf->cmap,4 * ibuf->maxcol);
+
+ mincol = ibuf->mincol;
+ if (alpha_col0 && mincol == 0) mincol = 1;
+
+ if (ibuf->ftype == AN_hamx) {
+ deltab = imb_coldeltatab((uchar *) coltab, 0, ibuf->maxcol, 4);
+ } else {
+ ibuf->cbits = ibuf->depth - 2;
+ imb_losecmapbits(ibuf, coltab);
+ deltab = imb_coldeltatab((uchar *) coltab, mincol, ibuf->maxcol, ibuf->cbits);
+ }
+
+ rect = ibuf->rect;
+ x=ibuf->x;
+ y=ibuf->y;
+
+ if (ibuf->ftype == AN_hamx){
+ IMB_dit2(ibuf, 2, 4);
+ IMB_dit2(ibuf, 1, 4);
+ IMB_dit2(ibuf, 0, 4);
+ imb_convhamx(ibuf, coltab, deltab);
+ } else {
+ for(;y > 0; y--){
+ convhamscanl(x, y, rect, coltab, deltab, ibuf->cbits);
+ rect += x;
+ }
+ }
+
+ return (TRUE);
+}
diff --git a/source/blender/imbuf/intern/hamx.c b/source/blender/imbuf/intern/hamx.c
new file mode 100644
index 00000000000..b297548fde6
--- /dev/null
+++ b/source/blender/imbuf/intern/hamx.c
@@ -0,0 +1,593 @@
+/**
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * hamx.c
+ *
+ * $Id$
+ */
+
+#include "BLI_blenlib.h"
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#include <io.h>
+#endif
+
+
+#include "imbuf.h"
+#include "imbuf_patch.h"
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "IMB_allocimbuf.h"
+#include "IMB_filter.h"
+#include "IMB_ham.h"
+#include "IMB_hamx.h"
+
+/* actually hard coded endianness */
+#define GET_BIG_LONG(x) (((uchar *) (x))[0] << 24 | ((uchar *) (x))[1] << 16 | ((uchar *) (x))[2] << 8 | ((uchar *) (x))[3])
+#define GET_LITTLE_LONG(x) (((uchar *) (x))[3] << 24 | ((uchar *) (x))[2] << 16 | ((uchar *) (x))[1] << 8 | ((uchar *) (x))[0])
+#define SWAP_L(x) (((x << 24) & 0xff000000) | ((x << 8) & 0xff0000) | ((x >> 8) & 0xff00) | ((x >> 24) & 0xff))
+#define SWAP_S(x) (((x << 8) & 0xff00) | ((x >> 8) & 0xff))
+
+/* more endianness... should move to a separate file... */
+#if defined(__sgi) || defined (__sparc) || defined (__PPC__) || defined (__ppc__) || defined (__BIG_ENDIAN__)
+#define GET_ID GET_BIG_LONG
+#define LITTLE_LONG SWAP_LONG
+#else
+#define GET_ID GET_LITTLE_LONG
+#define LITTLE_LONG ENDIAN_NOP
+#endif
+
+#ifndef ABS
+#define ABS(x) ((x) < 0 ? -(x) : (x))
+#endif
+
+static uchar hamx_array_char[] = {
+ 0x00,0x00,0xFF,0xFF, 0x00,0x00,0xFF,0xFF, 0x00,0x00,0xFF,0xFF, 0x00,0x00,0xFF,0xFF, 0x00,0x00,0xFF,0xFF, 0x00,0x00,0xFF,0xFF, 0x00,0x00,0xFF,0xFF, 0x00,0x00,0xFF,0xFF,
+ 0x00,0x00,0xFF,0xFF, 0x00,0x00,0xFF,0xFF, 0x00,0x00,0xFF,0xFF, 0x00,0x00,0xFF,0xFF, 0x00,0x00,0xFF,0xFF, 0x00,0x00,0xFF,0xFF, 0x00,0x00,0xFF,0xFF, 0x00,0x00,0xFF,0xFF,
+ 0x00,0xFF,0x00,0xFF, 0x00,0xFF,0x00,0xFF, 0x00,0xFF,0x00,0xFF, 0x00,0xFF,0x00,0xFF, 0x00,0xFF,0x00,0xFF, 0x00,0xFF,0x00,0xFF, 0x00,0xFF,0x00,0xFF, 0x00,0xFF,0x00,0xFF,
+ 0x00,0xFF,0x00,0xFF, 0x00,0xFF,0x00,0xFF, 0x00,0xFF,0x00,0xFF, 0x00,0xFF,0x00,0xFF, 0x00,0xFF,0x00,0xFF, 0x00,0xFF,0x00,0xFF, 0x00,0xFF,0x00,0xFF, 0x00,0xFF,0x00,0xFF,
+ 0x00,0xFF,0xFF,0x00, 0x00,0xFF,0xFF,0x00, 0x00,0xFF,0xFF,0x00, 0x00,0xFF,0xFF,0x00, 0x00,0xFF,0xFF,0x00, 0x00,0xFF,0xFF,0x00, 0x00,0xFF,0xFF,0x00, 0x00,0xFF,0xFF,0x00,
+ 0x00,0xFF,0xFF,0x00, 0x00,0xFF,0xFF,0x00, 0x00,0xFF,0xFF,0x00, 0x00,0xFF,0xFF,0x00, 0x00,0xFF,0xFF,0x00, 0x00,0xFF,0xFF,0x00, 0x00,0xFF,0xFF,0x00, 0x00,0xFF,0xFF,0x00,
+
+ 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
+
+ 0x00,0x00,0x00,0x00, 0x00,0x10,0x00,0x00, 0x00,0x20,0x00,0x00, 0x00,0x30,0x00,0x00, 0x00,0x40,0x00,0x00, 0x00,0x50,0x00,0x00, 0x00,0x60,0x00,0x00, 0x00,0x70,0x00,0x00,
+ 0x00,0x80,0x00,0x00, 0x00,0x90,0x00,0x00, 0x00,0xA0,0x00,0x00, 0x00,0xB0,0x00,0x00, 0x00,0xC0,0x00,0x00, 0x00,0xD0,0x00,0x00, 0x00,0xE0,0x00,0x00, 0x00,0xF0,0x00,0x00,
+ 0x00,0x00,0x00,0x00, 0x00,0x00,0x10,0x00, 0x00,0x00,0x20,0x00, 0x00,0x00,0x30,0x00, 0x00,0x00,0x40,0x00, 0x00,0x00,0x50,0x00, 0x00,0x00,0x60,0x00, 0x00,0x00,0x70,0x00,
+ 0x00,0x00,0x80,0x00, 0x00,0x00,0x90,0x00, 0x00,0x00,0xA0,0x00, 0x00,0x00,0xB0,0x00, 0x00,0x00,0xC0,0x00, 0x00,0x00,0xD0,0x00, 0x00,0x00,0xE0,0x00, 0x00,0x00,0xF0,0x00,
+ 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x10, 0x00,0x00,0x00,0x20, 0x00,0x00,0x00,0x30, 0x00,0x00,0x00,0x40, 0x00,0x00,0x00,0x50, 0x00,0x00,0x00,0x60, 0x00,0x00,0x00,0x70,
+ 0x00,0x00,0x00,0x80, 0x00,0x00,0x00,0x90, 0x00,0x00,0x00,0xA0, 0x00,0x00,0x00,0xB0, 0x00,0x00,0x00,0xC0, 0x00,0x00,0x00,0xD0, 0x00,0x00,0x00,0xE0, 0x00,0x00,0x00,0xF0,
+
+ 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x30, 0x00,0x00,0x00,0x60, 0x00,0x00,0x00,0x90, 0x00,0x00,0x00,0xC0, 0x00,0x00,0x00,0xF0,
+ 0x00,0x00,0x20,0x00, 0x00,0x00,0x20,0x30, 0x00,0x00,0x20,0x60, 0x00,0x00,0x20,0x90, 0x00,0x00,0x20,0xC0, 0x00,0x00,0x20,0xF0,
+ 0x00,0x00,0x40,0x00, 0x00,0x00,0x40,0x30, 0x00,0x00,0x40,0x60, 0x00,0x00,0x40,0x90, 0x00,0x00,0x40,0xC0, 0x00,0x00,0x40,0xF0,
+ 0x00,0x00,0x60,0x00, 0x00,0x00,0x60,0x30, 0x00,0x00,0x60,0x60, 0x00,0x00,0x60,0x90, 0x00,0x00,0x60,0xC0, 0x00,0x00,0x60,0xF0,
+ 0x00,0x00,0x90,0x00, 0x00,0x00,0x90,0x30, 0x00,0x00,0x90,0x60, 0x00,0x00,0x90,0x90, 0x00,0x00,0x90,0xC0, 0x00,0x00,0x90,0xF0,
+ 0x00,0x00,0xB0,0x00, 0x00,0x00,0xB0,0x30, 0x00,0x00,0xB0,0x60, 0x00,0x00,0xB0,0x90, 0x00,0x00,0xB0,0xC0, 0x00,0x00,0xB0,0xF0,
+ 0x00,0x00,0xD0,0x00, 0x00,0x00,0xD0,0x30, 0x00,0x00,0xD0,0x60, 0x00,0x00,0xD0,0x90, 0x00,0x00,0xD0,0xC0, 0x00,0x00,0xD0,0xF0,
+ 0x00,0x00,0xF0,0x00, 0x00,0x00,0xF0,0x30, 0x00,0x00,0xF0,0x60, 0x00,0x00,0xF0,0x90, 0x00,0x00,0xF0,0xC0, 0x00,0x00,0xF0,0xF0,
+ 0x00,0x50,0x00,0x00, 0x00,0x50,0x00,0x30, 0x00,0x50,0x00,0x60, 0x00,0x50,0x00,0x90, 0x00,0x50,0x00,0xC0, 0x00,0x50,0x00,0xF0,
+ 0x00,0x50,0x20,0x00, 0x00,0x50,0x20,0x30, 0x00,0x50,0x20,0x60, 0x00,0x50,0x20,0x90, 0x00,0x50,0x20,0xC0, 0x00,0x50,0x20,0xF0,
+ 0x00,0x50,0x40,0x00, 0x00,0x50,0x40,0x30, 0x00,0x50,0x40,0x60, 0x00,0x50,0x40,0x90, 0x00,0x50,0x40,0xC0, 0x00,0x50,0x40,0xF0,
+ 0x00,0x50,0x60,0x00, 0x00,0x50,0x60,0x30, 0x00,0x50,0x60,0x60, 0x00,0x50,0x60,0x90, 0x00,0x50,0x60,0xC0, 0x00,0x50,0x60,0xF0,
+ 0x00,0x50,0x90,0x00, 0x00,0x50,0x90,0x30, 0x00,0x50,0x90,0x60, 0x00,0x50,0x90,0x90, 0x00,0x50,0x90,0xC0, 0x00,0x50,0x90,0xF0,
+ 0x00,0x50,0xB0,0x00, 0x00,0x50,0xB0,0x30, 0x00,0x50,0xB0,0x60, 0x00,0x50,0xB0,0x90, 0x00,0x50,0xB0,0xC0, 0x00,0x50,0xB0,0xF0,
+ 0x00,0x50,0xD0,0x00, 0x00,0x50,0xD0,0x30, 0x00,0x50,0xD0,0x60, 0x00,0x50,0xD0,0x90, 0x00,0x50,0xD0,0xC0, 0x00,0x50,0xD0,0xF0,
+ 0x00,0x50,0xF0,0x00, 0x00,0x50,0xF0,0x30, 0x00,0x50,0xF0,0x60, 0x00,0x50,0xF0,0x90, 0x00,0x50,0xF0,0xC0, 0x00,0x50,0xF0,0xF0,
+ 0x00,0xA0,0x00,0x00, 0x00,0xA0,0x00,0x30, 0x00,0xA0,0x00,0x60, 0x00,0xA0,0x00,0x90, 0x00,0xA0,0x00,0xC0, 0x00,0xA0,0x00,0xF0,
+ 0x00,0xA0,0x20,0x00, 0x00,0xA0,0x20,0x30, 0x00,0xA0,0x20,0x60, 0x00,0xA0,0x20,0x90, 0x00,0xA0,0x20,0xC0, 0x00,0xA0,0x20,0xF0,
+ 0x00,0xA0,0x40,0x00, 0x00,0xA0,0x40,0x30, 0x00,0xA0,0x40,0x60, 0x00,0xA0,0x40,0x90, 0x00,0xA0,0x40,0xC0, 0x00,0xA0,0x40,0xF0,
+ 0x00,0xA0,0x60,0x00, 0x00,0xA0,0x60,0x30, 0x00,0xA0,0x60,0x60, 0x00,0xA0,0x60,0x90, 0x00,0xA0,0x60,0xC0, 0x00,0xA0,0x60,0xF0,
+ 0x00,0xA0,0x90,0x00, 0x00,0xA0,0x90,0x30, 0x00,0xA0,0x90,0x60, 0x00,0xA0,0x90,0x90, 0x00,0xA0,0x90,0xC0, 0x00,0xA0,0x90,0xF0,
+ 0x00,0xA0,0xB0,0x00, 0x00,0xA0,0xB0,0x30, 0x00,0xA0,0xB0,0x60, 0x00,0xA0,0xB0,0x90, 0x00,0xA0,0xB0,0xC0, 0x00,0xA0,0xB0,0xF0,
+ 0x00,0xA0,0xD0,0x00, 0x00,0xA0,0xD0,0x30, 0x00,0xA0,0xD0,0x60, 0x00,0xA0,0xD0,0x90, 0x00,0xA0,0xD0,0xC0, 0x00,0xA0,0xD0,0xF0,
+ 0x00,0xA0,0xF0,0x00, 0x00,0xA0,0xF0,0x30, 0x00,0xA0,0xF0,0x60, 0x00,0xA0,0xF0,0x90, 0x00,0xA0,0xF0,0xC0, 0x00,0xA0,0xF0,0xF0,
+ 0x00,0xF0,0x00,0x00, 0x00,0xF0,0x00,0x30, 0x00,0xF0,0x00,0x60, 0x00,0xF0,0x00,0x90, 0x00,0xF0,0x00,0xC0, 0x00,0xF0,0x00,0xF0,
+ 0x00,0xF0,0x20,0x00, 0x00,0xF0,0x20,0x30, 0x00,0xF0,0x20,0x60, 0x00,0xF0,0x20,0x90, 0x00,0xF0,0x20,0xC0, 0x00,0xF0,0x20,0xF0,
+ 0x00,0xF0,0x40,0x00, 0x00,0xF0,0x40,0x30, 0x00,0xF0,0x40,0x60, 0x00,0xF0,0x40,0x90, 0x00,0xF0,0x40,0xC0, 0x00,0xF0,0x40,0xF0,
+ 0x00,0xF0,0x60,0x00, 0x00,0xF0,0x60,0x30, 0x00,0xF0,0x60,0x60, 0x00,0xF0,0x60,0x90, 0x00,0xF0,0x60,0xC0, 0x00,0xF0,0x60,0xF0,
+ 0x00,0xF0,0x90,0x00, 0x00,0xF0,0x90,0x30, 0x00,0xF0,0x90,0x60, 0x00,0xF0,0x90,0x90, 0x00,0xF0,0x90,0xC0, 0x00,0xF0,0x90,0xF0,
+ 0x00,0xF0,0xB0,0x00, 0x00,0xF0,0xB0,0x30, 0x00,0xF0,0xB0,0x60, 0x00,0xF0,0xB0,0x90, 0x00,0xF0,0xB0,0xC0, 0x00,0xF0,0xB0,0xF0,
+ 0x00,0xF0,0xD0,0x00, 0x00,0xF0,0xD0,0x30, 0x00,0xF0,0xD0,0x60, 0x00,0xF0,0xD0,0x90, 0x00,0xF0,0xD0,0xC0, 0x00,0xF0,0xD0,0xF0,
+ 0x00,0xF0,0xF0,0x00, 0x00,0xF0,0xF0,0x30, 0x00,0xF0,0xF0,0x60, 0x00,0xF0,0xF0,0x90, 0x00,0xF0,0xF0,0xC0, 0x00,0xF0,0xF0,0xF0,
+
+ 0x00,0x10,0x10,0x10, 0x00,0x20,0x20,0x20, 0x00,0x30,0x30,0x30, 0x00,0x40,0x40,0x40,
+ 0x00,0x50,0x50,0x50, 0x00,0x60,0x60,0x60, 0x00,0x70,0x70,0x70, 0x00,0x80,0x80,0x80,
+ 0x00,0x90,0x90,0x90, 0x00,0xA0,0xA0,0xA0, 0x00,0xB0,0xB0,0xB0, 0x00,0xC0,0xC0,0xC0,
+ 0x00,0xD0,0xD0,0xD0, 0x00,0xE0,0xE0,0xE0
+};
+
+static int * hamx_array = (int *) (hamx_array_char);
+
+static uchar cmap_hamx[] = {
+ 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x30, 0x00,0x00,0x00,0x60, 0x00,0x00,0x00,0x90, 0x00,0x00,0x00,0xC0, 0x00,0x00,0x00,0xF0,
+ 0x00,0x00,0x20,0x00, 0x00,0x00,0x20,0x30, 0x00,0x00,0x20,0x60, 0x00,0x00,0x20,0x90, 0x00,0x00,0x20,0xC0, 0x00,0x00,0x20,0xF0,
+ 0x00,0x00,0x40,0x00, 0x00,0x00,0x40,0x30, 0x00,0x00,0x40,0x60, 0x00,0x00,0x40,0x90, 0x00,0x00,0x40,0xC0, 0x00,0x00,0x40,0xF0,
+ 0x00,0x00,0x60,0x00, 0x00,0x00,0x60,0x30, 0x00,0x00,0x60,0x60, 0x00,0x00,0x60,0x90, 0x00,0x00,0x60,0xC0, 0x00,0x00,0x60,0xF0,
+ 0x00,0x00,0x90,0x00, 0x00,0x00,0x90,0x30, 0x00,0x00,0x90,0x60, 0x00,0x00,0x90,0x90, 0x00,0x00,0x90,0xC0, 0x00,0x00,0x90,0xF0,
+ 0x00,0x00,0xB0,0x00, 0x00,0x00,0xB0,0x30, 0x00,0x00,0xB0,0x60, 0x00,0x00,0xB0,0x90, 0x00,0x00,0xB0,0xC0, 0x00,0x00,0xB0,0xF0,
+ 0x00,0x00,0xD0,0x00, 0x00,0x00,0xD0,0x30, 0x00,0x00,0xD0,0x60, 0x00,0x00,0xD0,0x90, 0x00,0x00,0xD0,0xC0, 0x00,0x00,0xD0,0xF0,
+ 0x00,0x00,0xF0,0x00, 0x00,0x00,0xF0,0x30, 0x00,0x00,0xF0,0x60, 0x00,0x00,0xF0,0x90, 0x00,0x00,0xF0,0xC0, 0x00,0x00,0xF0,0xF0,
+ 0x00,0x50,0x00,0x00, 0x00,0x50,0x00,0x30, 0x00,0x50,0x00,0x60, 0x00,0x50,0x00,0x90, 0x00,0x50,0x00,0xC0, 0x00,0x50,0x00,0xF0,
+ 0x00,0x50,0x20,0x00, 0x00,0x50,0x20,0x30, 0x00,0x50,0x20,0x60, 0x00,0x50,0x20,0x90, 0x00,0x50,0x20,0xC0, 0x00,0x50,0x20,0xF0,
+ 0x00,0x50,0x40,0x00, 0x00,0x50,0x40,0x30, 0x00,0x50,0x40,0x60, 0x00,0x50,0x40,0x90, 0x00,0x50,0x40,0xC0, 0x00,0x50,0x40,0xF0,
+ 0x00,0x50,0x60,0x00, 0x00,0x50,0x60,0x30, 0x00,0x50,0x60,0x60, 0x00,0x50,0x60,0x90, 0x00,0x50,0x60,0xC0, 0x00,0x50,0x60,0xF0,
+ 0x00,0x50,0x90,0x00, 0x00,0x50,0x90,0x30, 0x00,0x50,0x90,0x60, 0x00,0x50,0x90,0x90, 0x00,0x50,0x90,0xC0, 0x00,0x50,0x90,0xF0,
+ 0x00,0x50,0xB0,0x00, 0x00,0x50,0xB0,0x30, 0x00,0x50,0xB0,0x60, 0x00,0x50,0xB0,0x90, 0x00,0x50,0xB0,0xC0, 0x00,0x50,0xB0,0xF0,
+ 0x00,0x50,0xD0,0x00, 0x00,0x50,0xD0,0x30, 0x00,0x50,0xD0,0x60, 0x00,0x50,0xD0,0x90, 0x00,0x50,0xD0,0xC0, 0x00,0x50,0xD0,0xF0,
+ 0x00,0x50,0xF0,0x00, 0x00,0x50,0xF0,0x30, 0x00,0x50,0xF0,0x60, 0x00,0x50,0xF0,0x90, 0x00,0x50,0xF0,0xC0, 0x00,0x50,0xF0,0xF0,
+ 0x00,0xA0,0x00,0x00, 0x00,0xA0,0x00,0x30, 0x00,0xA0,0x00,0x60, 0x00,0xA0,0x00,0x90, 0x00,0xA0,0x00,0xC0, 0x00,0xA0,0x00,0xF0,
+ 0x00,0xA0,0x20,0x00, 0x00,0xA0,0x20,0x30, 0x00,0xA0,0x20,0x60, 0x00,0xA0,0x20,0x90, 0x00,0xA0,0x20,0xC0, 0x00,0xA0,0x20,0xF0,
+ 0x00,0xA0,0x40,0x00, 0x00,0xA0,0x40,0x30, 0x00,0xA0,0x40,0x60, 0x00,0xA0,0x40,0x90, 0x00,0xA0,0x40,0xC0, 0x00,0xA0,0x40,0xF0,
+ 0x00,0xA0,0x60,0x00, 0x00,0xA0,0x60,0x30, 0x00,0xA0,0x60,0x60, 0x00,0xA0,0x60,0x90, 0x00,0xA0,0x60,0xC0, 0x00,0xA0,0x60,0xF0,
+ 0x00,0xA0,0x90,0x00, 0x00,0xA0,0x90,0x30, 0x00,0xA0,0x90,0x60, 0x00,0xA0,0x90,0x90, 0x00,0xA0,0x90,0xC0, 0x00,0xA0,0x90,0xF0,
+ 0x00,0xA0,0xB0,0x00, 0x00,0xA0,0xB0,0x30, 0x00,0xA0,0xB0,0x60, 0x00,0xA0,0xB0,0x90, 0x00,0xA0,0xB0,0xC0, 0x00,0xA0,0xB0,0xF0,
+ 0x00,0xA0,0xD0,0x00, 0x00,0xA0,0xD0,0x30, 0x00,0xA0,0xD0,0x60, 0x00,0xA0,0xD0,0x90, 0x00,0xA0,0xD0,0xC0, 0x00,0xA0,0xD0,0xF0,
+ 0x00,0xA0,0xF0,0x00, 0x00,0xA0,0xF0,0x30, 0x00,0xA0,0xF0,0x60, 0x00,0xA0,0xF0,0x90, 0x00,0xA0,0xF0,0xC0, 0x00,0xA0,0xF0,0xF0,
+ 0x00,0xF0,0x00,0x00, 0x00,0xF0,0x00,0x30, 0x00,0xF0,0x00,0x60, 0x00,0xF0,0x00,0x90, 0x00,0xF0,0x00,0xC0, 0x00,0xF0,0x00,0xF0,
+ 0x00,0xF0,0x20,0x00, 0x00,0xF0,0x20,0x30, 0x00,0xF0,0x20,0x60, 0x00,0xF0,0x20,0x90, 0x00,0xF0,0x20,0xC0, 0x00,0xF0,0x20,0xF0,
+ 0x00,0xF0,0x40,0x00, 0x00,0xF0,0x40,0x30, 0x00,0xF0,0x40,0x60, 0x00,0xF0,0x40,0x90, 0x00,0xF0,0x40,0xC0, 0x00,0xF0,0x40,0xF0,
+ 0x00,0xF0,0x60,0x00, 0x00,0xF0,0x60,0x30, 0x00,0xF0,0x60,0x60, 0x00,0xF0,0x60,0x90, 0x00,0xF0,0x60,0xC0, 0x00,0xF0,0x60,0xF0,
+ 0x00,0xF0,0x90,0x00, 0x00,0xF0,0x90,0x30, 0x00,0xF0,0x90,0x60, 0x00,0xF0,0x90,0x90, 0x00,0xF0,0x90,0xC0, 0x00,0xF0,0x90,0xF0,
+ 0x00,0xF0,0xB0,0x00, 0x00,0xF0,0xB0,0x30, 0x00,0xF0,0xB0,0x60, 0x00,0xF0,0xB0,0x90, 0x00,0xF0,0xB0,0xC0, 0x00,0xF0,0xB0,0xF0,
+ 0x00,0xF0,0xD0,0x00, 0x00,0xF0,0xD0,0x30, 0x00,0xF0,0xD0,0x60, 0x00,0xF0,0xD0,0x90, 0x00,0xF0,0xD0,0xC0, 0x00,0xF0,0xD0,0xF0,
+ 0x00,0xF0,0xF0,0x00, 0x00,0xF0,0xF0,0x30, 0x00,0xF0,0xF0,0x60, 0x00,0xF0,0xF0,0x90, 0x00,0xF0,0xF0,0xC0, 0x00,0xF0,0xF0,0xF0,
+ 0x00,0x10,0x10,0x10, 0x00,0x20,0x20,0x20, 0x00,0x30,0x30,0x30, 0x00,0x40,0x40,0x40, 0x00,0x50,0x50,0x50, 0x00,0x60,0x60,0x60,
+ 0x00,0x70,0x70,0x70, 0x00,0x80,0x80,0x80, 0x00,0x90,0x90,0x90, 0x00,0xA0,0xA0,0xA0, 0x00,0xB0,0xB0,0xB0, 0x00,0xC0,0xC0,0xC0,
+ 0x00,0xD0,0xD0,0xD0, 0x00,0xE0,0xE0,0xE0
+};
+
+
+float adat_gamma = 1.0;
+float adat_distort = 1.0;
+
+/*
+ *
+ * Nieuwe versie:
+ *
+ * 32 helderheden Y 15 direct te bereiken (zwart & wit zijn specials)
+ * 16 kleuren H ue
+ * 7 intensiteiten S aturation
+ *
+ * Totaal 3584 'verschillende' kleuren. Eerste 512 kleuren vrij.
+ *
+ *
+ */
+
+void imb_convhamx(struct ImBuf *ibuf, unsigned char coltab[][4], short *deltab)
+/* struct ImBuf *ibuf; */
+/* uchar coltab[][4]; */
+/* short *deltab; */
+{
+ short r,g,b,lr,lg,lb,dr,dg,db,col,fout,type,step;
+ int i;
+ uchar *rect;
+
+ /*
+ b = 0000 xxxx
+ g = 0001 xxxx
+ r = 0010 xxxx
+ cmap >= 48
+ */
+
+ for (step = 0 ; step < 2 ; step ++){
+ rect = (uchar *) ibuf->rect;
+ rect += 4*step;
+ i = ((ibuf->x * ibuf->y) + 2 - step - 1) / 2;
+
+ lb = coltab[0][1];
+ lg = coltab[0][2];
+ lr = coltab[0][3];
+ type = col = 0;
+
+ for ( ;i>0;i--){
+ b = rect[2] >> 4;
+ g = rect[1] >> 4;
+ r = rect[0] >> 4;
+
+ if ((b-lb) | (g-lg) | (r-lr)){
+ col = ((b<<8) + (g<<4) + r) << 1;
+ fout = deltab[col + 1];
+ col = deltab[col];
+ type = 0;
+ dr = quadr[lr-r] ;
+ dg = quadr[lg-g] ;
+ db = quadr[lb-b];
+
+ if ((dr+dg)<=fout) {
+ fout = dr+dg ;
+ type = 1;
+ }
+ if ((dg+db)<=fout) {
+ fout = dg+db;
+ type = 2;
+ }
+ if ((dr+db)<=fout) {
+ fout = dr+db;
+ type = 4;
+ }
+
+ switch(type){
+ case 1:
+ lb = b ;
+ col = b;
+ break;
+ case 4:
+ lg = g ;
+ col = g+16;
+ break;
+ case 2:
+ lr = r ;
+ col = r + 32;
+ break;
+ default:
+ /*printf("%04x %5d %5d ", (b<<8) + (g<<4) + r, col, fout);*/
+
+ lb = coltab[col][1];
+ lg = coltab[col][2];
+ lr = coltab[col][3];
+ /*printf("%01x%01x%01x %01x%01x%01x\n", b, g, r, lb, lg, lr);*/
+ col += 48;
+ }
+ }
+ rect[3] = col;
+ rect += 8;
+ }
+ }
+}
+
+static short dec_hamx(struct ImBuf * ibuf, unsigned char *body, int cmap[])
+/* struct ImBuf * ibuf; */
+/* uchar *body; */
+/* int cmap[]; */
+{
+ int todo,i;
+ int j,step,col;
+ unsigned int *rect;
+
+ for (step = 0 ; step < 2 ; step ++){
+ rect = ibuf->rect;
+ rect += step;
+ todo = (ibuf->x * ibuf->y + 2 - step - 1) / 2;
+ col = cmap[0];
+ while (todo>0){
+ i = *body++;
+
+ if (i & 128){ /* fill */
+
+ i = 257-i;
+ todo -= i;
+ j = *(body++);
+
+ col = ((col & hamx_array[j]) | hamx_array[j + 256]);
+
+ do{
+ *rect = col;
+ rect += 2;
+ }while (--i);
+ } else{ /* copy */
+ i++;
+ todo-=i;
+
+ do{
+ j = *(body++);
+ *rect = col = ((col & hamx_array[j]) | hamx_array[j + 256]);
+ rect += 2;
+ }while (--i);
+ }
+ }
+ if (todo) return (0);
+ }
+ return(1);
+}
+
+
+struct ImBuf *imb_loadanim(int *iffmem, int flags)
+{
+ int chunk, totlen, len, *mem, cmaplen = 0;
+ unsigned int *cmap;
+ uchar *body = 0;
+ struct Adat adat;
+ struct ImBuf *ibuf=0;
+ static int is_flipped = FALSE;
+
+ mem=iffmem;
+ if (GET_ID(mem) != FORM) return (0);
+ if (GET_ID(mem + 2) != ANIM) return (0);
+ totlen= (GET_BIG_LONG(mem + 1) + 1) & ~1;
+ mem += 3;
+ totlen -= 4;
+ adat.w = 0;
+ adat.xorig = 0;
+ adat.yorig = 0;
+ adat.gamma = adat_gamma;
+ adat.distort = adat_distort;
+
+ while(totlen > 0){
+ chunk = GET_ID(mem);
+ len = (GET_BIG_LONG(mem + 1) + 1) & ~1;
+ mem += 2;
+
+ totlen -= len+8;
+ switch (chunk){
+ case ADAT:
+ if (len > sizeof(struct Adat)){
+ memcpy(&adat,mem,sizeof(struct Adat));
+ } else{
+ memcpy(&adat,mem,len);
+ }
+ adat.w = BIG_SHORT(adat.w);
+ adat.h = BIG_SHORT(adat.h);
+ adat.type = BIG_SHORT(adat.type);
+ adat.xorig = BIG_SHORT(adat.xorig);
+ adat.yorig = BIG_SHORT(adat.yorig);
+ break;
+ case CMAP:
+ cmap = (unsigned int *) mem;
+ cmaplen = len;
+ break;
+ case BODY:
+ body = (uchar *) mem;
+ break;
+ }
+ mem = (int *)((uchar *)mem +len);
+ }
+
+ if (body == 0) return (0);
+ if (adat.w == 0) return (0);
+
+ adat_gamma = adat.gamma;
+ adat_distort = adat.distort;
+
+ if (flags & IB_test) ibuf=IMB_allocImBuf(adat.w, adat.h, 24, 0, 0);
+ else ibuf=IMB_allocImBuf(adat.w, adat.h, 24, IB_rect, 0);
+ if (ibuf==0) return (0);
+
+ ibuf->ftype = (Anim | adat.type);
+ ibuf->xorig = adat.xorig;
+ ibuf->yorig = adat.yorig;
+ ibuf->flags = flags;
+
+ if (cmaplen){
+ ibuf->cmap = malloc(cmaplen);
+ memcpy(ibuf->cmap, cmap, cmaplen);
+ ibuf->maxcol = cmaplen >> 2;
+ }
+
+ if (flags & IB_test){
+ if (flags & IB_freem) free(iffmem);
+ return(ibuf);
+ }
+
+ switch (adat.type){
+ case HAMX:
+ if (flags & IB_rect){
+ if (!is_flipped) {
+ int i;
+ unsigned int * t;
+ t = (unsigned int *) hamx_array_char;
+ for (i = 0; i < sizeof(hamx_array_char) / sizeof(int) ; i++) {
+ t[i] = SWAP_LONG(t[i]);
+ }
+
+ t = (unsigned int *) cmap_hamx;
+
+ for (i = 0; i < sizeof(cmap_hamx) / sizeof(int) ; i++) {
+ t[i] = SWAP_LONG(t[i]);
+ }
+
+ is_flipped= TRUE;
+ }
+
+ if (dec_hamx(ibuf,body,(int*) cmap_hamx) == 0){
+ IMB_freeImBuf(ibuf);
+ ibuf = 0;
+ }
+ if (flags & IB_ttob) IMB_flipy(ibuf);
+ }
+ break;
+ default:
+ IMB_freeImBuf(ibuf);
+ ibuf = 0;
+ }
+
+ if (flags & IB_freem) free(iffmem);
+
+ return (ibuf);
+}
+
+
+static unsigned char *makebody_anim(int bytes,
+ unsigned char *buf,
+ unsigned char *rect)
+/* register uchar *buf; */
+/* register uchar *rect; */
+/* int bytes; */
+{
+ register uchar last,this;
+ register int copy;
+ register uchar *rectstart,*temp;
+
+ bytes--;
+ rectstart = rect;
+ last = *rect++;
+ this = *rect++;
+ copy = last^this;
+ while (bytes>0){
+ if (copy){
+ do{
+ last = this;
+ this = *rect++;
+ if (last == this){
+ if (this == rect[-3]){ /* drie dezelfde? */
+ bytes --; /* bytes goed zetten */
+ break;
+ }
+ }
+ }while (--bytes != 0);
+
+ copy = rect-rectstart;
+ copy --;
+ if (bytes) copy -= 2;
+
+ temp = rect;
+ rect = rectstart;
+
+ while (copy){
+ last = copy;
+ if (copy>MAXDAT) last = MAXDAT;
+ copy -= last;
+ *buf++ = last-1;
+ do{
+ *buf++ = *rect++;
+ }while(--last != 0);
+ }
+ rectstart = rect;
+ rect = temp;
+ last = this;
+
+ copy = FALSE;
+ } else {
+ while (*rect++ == this){ /* zoek naar eerste afwijkende byte */
+ if (--bytes == 0) break; /* of einde regel */
+ }
+ rect --;
+ copy = rect-rectstart;
+ rectstart = rect;
+ bytes --;
+ this = *rect++;
+
+ while (copy){
+ if (copy>MAXRUN){
+ *buf++ = -(MAXRUN-1);
+ *buf++ = last;
+ copy -= MAXRUN;
+ } else {
+ *buf++ = -(copy-1);
+ *buf++ = last;
+ break;
+ }
+ }
+ copy=TRUE;
+ }
+ }
+ return (buf);
+}
+
+
+short imb_enc_anim(struct ImBuf *ibuf, int file)
+/* struct ImBuf *ibuf; */
+/* int file; */
+{
+ int step, steps, size, i, skip;
+ uchar *buf1, *crect, *_buf1, *_buf2, *bufend;
+ short ok = TRUE;
+
+ if (ibuf == 0) return (0);
+ if (file < 0 ) return (0);
+ if (ibuf->rect == 0) return(0);
+
+ /* dither toevoegen */
+
+ switch(ibuf->ftype){
+ case AN_hamx:
+ ibuf->cmap = (unsigned int *) cmap_hamx;
+ ibuf->mincol = 0;
+ ibuf->maxcol = sizeof(cmap_hamx) / 4;
+ imb_converttoham(ibuf);
+ steps = 2;
+ break;
+ }
+
+ size = ((ibuf->x + 1)* (ibuf->y + 1)) / steps + 1024;
+ if ((_buf1 = malloc(size)) == 0) return(0);
+ if ((_buf2 = malloc(size)) == 0){
+ free(_buf1);
+ return(0);
+ }
+
+ skip = 4 * steps;
+ for (step = 0 ; step < steps ; step ++){
+ crect = (uchar *) ibuf->rect;
+ crect += 4 * step;
+ size = (ibuf->x * ibuf->y + steps - step - 1) / steps;
+ buf1 = _buf1;
+ if ((ibuf->ftype == AN_hamx) || (ibuf->ftype == AN_yuvx)){
+ crect += 3;
+ for (i = size ; i>0 ; i--){
+ *(buf1 ++) = *crect;
+ crect += skip;
+ }
+ } else{
+ for (i = size ; i>0 ; i--){
+ *(buf1 ++) = crect[1] + (crect[2] >> 2) + (crect[3] >> 5);
+ crect += skip;
+ }
+ }
+ bufend = makebody_anim(size,_buf2,_buf1);
+ if (bufend == 0){
+ ok = FALSE;
+ break;
+ }
+ size = bufend - _buf2;
+ if (write(file, _buf2, size) != size){
+ ok = FALSE;
+ break;
+ }
+ }
+ free(_buf1);
+ free(_buf2);
+ return (ok);
+}
diff --git a/source/blender/imbuf/intern/iff.c b/source/blender/imbuf/intern/iff.c
new file mode 100644
index 00000000000..640eb253c26
--- /dev/null
+++ b/source/blender/imbuf/intern/iff.c
@@ -0,0 +1,225 @@
+/**
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * iff.c
+ *
+ * $Id$
+ */
+
+#include "BLI_blenlib.h"
+
+#include "imbuf.h"
+#include "imbuf_patch.h"
+#include "IMB_imbuf_types.h"
+
+#include "IMB_iff.h"
+
+unsigned short imb_start_iff(struct ImBuf *ibuf, int file)
+{
+ unsigned int *point, size, *buf;
+
+ if ((point=buf=(unsigned int *)malloc(32768))==0) return FALSE;
+
+ *point++ = FORM; /* FORMxxxxILBM in buffer */
+ *point++ = 0;
+
+ if (IS_amiga(ibuf)){
+ struct BitMapHeader *bmhd;
+
+ *point++ = ILBM;
+ *point++ = CAMG;
+ *point++ = 4;
+ *point++ = (ibuf->ftype & 0xffff);
+
+ *point++=BMHD;
+ *point++=sizeof(struct BitMapHeader);
+
+ bmhd=(struct BitMapHeader *)point; /* bmhd wijst naar plek waar bmhd moet komen */
+ point=(unsigned int *)((char *)point+sizeof(struct BitMapHeader)); /* pointer alvast verder zetten */
+
+ bmhd->w=ibuf->x;
+ bmhd->h=ibuf->y;
+ bmhd->pageWidth=ibuf->x;
+ bmhd->pageHeight=ibuf->y;
+ bmhd->x=0;
+ bmhd->y=0;
+ bmhd->nPlanes=ibuf->depth;
+ bmhd->masking=0;
+ if (ibuf->flags & IB_vert){
+ bmhd->compression=2;
+ }
+ else{
+ bmhd->compression=1;
+ }
+ bmhd->pad1=0;
+ bmhd->transparentColor=0;
+ bmhd->xAspect=1;
+ bmhd->yAspect=1;
+ } else if (IS_anim(ibuf)){
+ struct Adat *adat;
+ extern float adat_gamma;
+ extern float adat_distort;
+
+ *point++ = ANIM;
+ *point++ = ADAT;
+ *point++ = BIG_LONG(sizeof(struct Adat));
+
+ adat = (struct Adat *)point;
+ point = (unsigned int *)((char *)point+sizeof(struct Adat)); /* pointer alvast verder zetten */
+
+ adat->w = BIG_SHORT(ibuf->x);
+ adat->h = BIG_SHORT(ibuf->y);
+
+ adat->type = BIG_SHORT(ibuf->ftype);
+ adat->xorig = BIG_SHORT(ibuf->xorig);
+ adat->yorig = BIG_SHORT(ibuf->yorig);
+ adat->pad = 0;
+ adat->gamma = adat_gamma;
+ adat->distort = adat_distort;
+ }
+
+ size=((uchar *)point-(uchar *)buf);
+ if (write(file,buf,size)!=size){
+ free(buf);
+ return (FALSE);
+ }
+
+ if (ibuf->cmap){
+ if (IS_anim(ibuf)){
+ size = ibuf->maxcol * sizeof(int);
+ buf[0] = CMAP;
+ buf[1] = BIG_LONG(size);
+ if (write(file,buf,8) != 8){
+ free(buf);
+ return (FALSE);
+ }
+ if (write(file,ibuf->cmap,size) != size){
+ free(buf);
+ return (FALSE);
+ }
+ } else{
+ uchar *cpoint,*cols;
+ unsigned int i,bits;
+
+ point = buf;
+ if (IS_amiga(ibuf)){
+ *(point++) = CMAP;
+ *(point++) = BIG_LONG(3*ibuf->maxcol);
+ }
+
+ cpoint = (uchar *) point;
+ cols = (uchar *)ibuf->cmap;
+ if ((ibuf->cbits > 0) && (ibuf->cbits < 8)){
+ bits = ~((1 << (8-ibuf->cbits)) - 1);
+ } else bits = -1;
+
+ if (IS_ham(ibuf)) bits = -1;
+
+ for (i=0 ; i<ibuf->maxcol ; i++){
+ *(cpoint++) = cols[0] & bits;
+ *(cpoint++) = cols[1] & bits;
+ *(cpoint++) = cols[2] & bits;
+ cols += 4;
+ }
+ if (ibuf->maxcol & 1) *(cpoint++)=0;
+
+ size=(cpoint-(uchar *)buf);
+ if (write(file,buf,size)!=size){
+ free(buf);
+ return (FALSE);
+ }
+ }
+ }
+
+ if (IS_amiga(ibuf)) buf[0] = BODY;
+ if (IS_anim(ibuf)) buf[0] = BODY;
+ buf[1]=0;
+
+ if (write(file,buf,8)!=8){
+ free(buf);
+ return(FALSE);
+ }
+
+ free(buf);
+ return (TRUE);
+}
+
+
+unsigned short imb_update_iff(int file, int code)
+{
+ int buf[2], filelen, skip;
+ uchar nop;
+
+ if (file<=0) return (FALSE);
+
+ filelen = BLI_filesize(file)-8; /* filelengte berekenen */
+
+ lseek(file,0L,2); /* seek end */
+
+ if (filelen & 1){ /* lengte even maken */
+ switch(code){
+ case BODY:
+ nop = IFFNOP;
+ break;
+ }
+ if (write(file,&nop,1)!=1) return (FALSE);
+ filelen++;
+ }
+ lseek(file,4L,0);
+
+ buf[0] = BIG_LONG(filelen);
+
+ if (write(file, buf, 4) != 4) return (FALSE);
+ if (code == 0) return (TRUE);
+
+ filelen-=4;
+ lseek(file,4L,1);
+
+ while (filelen>0){ /* zoek BODY op */
+ read(file, buf, 8);
+ filelen -= 8;
+ if (buf[0] == code) break;
+
+ skip = BIG_LONG(buf[1]) + 1 & ~1;
+ filelen -= skip;
+ lseek(file, skip, 1);
+ }
+ if (filelen <= 0) {
+ printf("update_iff: couldn't find chunk\n");
+ return (FALSE);
+ }
+
+ lseek(file, -4L, 1);
+
+ buf[0] = BIG_LONG(filelen);
+
+ if (write(file, buf, 4)!=4) return (FALSE);
+
+ return (TRUE);
+}
diff --git a/source/blender/imbuf/intern/imageprocess.c b/source/blender/imbuf/intern/imageprocess.c
new file mode 100644
index 00000000000..dcdd0692fc4
--- /dev/null
+++ b/source/blender/imbuf/intern/imageprocess.c
@@ -0,0 +1,59 @@
+/**
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * This file was moved here from the src/ directory. It is meant to
+ * deal with endianness. It resided in a general blending lib. The
+ * other functions were only used during rendering. This single
+ * function remained. It should probably move to imbuf/intern/util.c,
+ * but we'll keep it here for the time being. (nzc)*/
+
+/* imageprocess.c MIXED MODEL
+ *
+ * april 95
+ *
+ * $Id$
+ */
+
+#include "IMB_imbuf.h"
+
+/* Only this one is used liberally here, and in imbuf */
+void IMB_convert_rgba_to_abgr(int size, unsigned int *rect)
+{
+ char *cp= (char *)rect, rt;
+
+ while(size-- > 0) {
+ rt= cp[0];
+ cp[0]= cp[3];
+ cp[3]= rt;
+ rt= cp[1];
+ cp[1]= cp[2];
+ cp[2]= rt;
+ cp+= 4;
+ }
+}
diff --git a/source/blender/imbuf/intern/imbuf.h b/source/blender/imbuf/intern/imbuf.h
new file mode 100644
index 00000000000..d22d408ddaa
--- /dev/null
+++ b/source/blender/imbuf/intern/imbuf.h
@@ -0,0 +1,190 @@
+/**
+ * imbuf.h (mar-2001 nzc)
+ *
+ * This header might have to become external...
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 IMBUF_H
+#define IMBUF_H
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <stdio.h>
+
+#ifndef WIN32
+#include <unistd.h>
+#endif
+
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <math.h>
+
+#if !defined(__FreeBSD__) && !defined(__APPLE__)
+
+/* #include <malloc.h> */ /* _should_ be in stdlib */
+
+#endif
+
+#ifndef WIN32
+#include <sys/mman.h>
+#endif
+
+#if !defined(WIN32) && !defined(__BeOS)
+#define O_BINARY 0
+#endif
+
+#define SWAP_SHORT(x) (((x & 0xff) << 8) | ((x >> 8) & 0xff))
+#define SWAP_LONG(x) (((x) << 24) | (((x) & 0xff00) << 8) | (((x) >> 8) & 0xff00) | (((x) >> 24) & 0xff))
+
+#define ENDIAN_NOP(x) (x)
+
+#if defined(__sgi) || defined(__sparc) || defined (__PPC__) || defined (__APPLE__)
+#define LITTLE_SHORT SWAP_SHORT
+#define LITTLE_LONG SWAP_LONG
+#define BIG_SHORT ENDIAN_NOP
+#define BIG_LONG ENDIAN_NOP
+#else
+#define LITTLE_SHORT ENDIAN_NOP
+#define LITTLE_LONG ENDIAN_NOP
+#define BIG_SHORT SWAP_SHORT
+#define BIG_LONG SWAP_LONG
+#endif
+
+#define malloc(x) MEM_mallocN(x, __FILE__)
+#define free(x) MEM_freeN(x)
+#define calloc(x,y) MEM_callocN((x)*(y), __FILE__)
+#define freelist(x) BLI_freelistN(x)
+
+/*
+bindkey -r f1,'cc -O -c imbuf.c\n'
+
+bindkeyo -r f1,'make paint \n'
+bindkeyo -r f2,'paint /usr/4Dgifts/iristools/images/max5.rgb \n'
+
+bindkey -r f1,'cc paint.c imbuf.c -lgl_s -lm -lfm_s -g -o paint\n'
+bindkey -r f2,'/usr/people/bin/compres /usr/people/pics/0600\n'
+
+compileren met:
+
+lc -Lm -f8 -dAMIGA imbuf
+*/
+
+#ifdef SHLIB
+void *(*ib_calloc)();
+#define calloc(x,y) ib_calloc((x),(y))
+void *(*ib_malloc)();
+#define malloc(x) ib_malloc(x)
+void (*ib_free)();
+#define free(x) ib_free(x)
+void (*ib_memcpy)();
+#define memcpy(x,y,z) ib_memcpy((x),(y),(z))
+int (*ib_abs)();
+#define abs(x) ib_abs(x)
+void (*ib_fprin_tf)();
+#define fprintf ib_fprin_tf
+int (*ib_sprin_tf)();
+#define sprintf ib_sprin_tf
+void (*ib_prin_tf)();
+#define printf ib_prin_tf
+int (*ib_lseek)();
+#define lseek(x,y,z) ib_lseek((x),(y),(z))
+void *(*ib_mmap)();
+#define mmap(u,v,w,x,y,z) ib_mmap((u),(v),(w),(x),(y),(z))
+int (*ib_munmap)();
+#define munmap(x,y) ib_munmap((x),(y))
+int (*ib_open)();
+#define open(x,y) ib_open((x),(y))
+void (*ib_close)();
+#define close(x) ib_close(x)
+int (*ib_write)();
+#define write(x,y,z) ib_write((x),(y),(z))
+int (*ib_read)();
+#define read(x,y,z) ib_read((x),(y),(z))
+int (*ib_fchmod)();
+#define fchmod(x,y) ib_fchmod((x),(y))
+int (*ib_remove)();
+#define remove(x) ib_remove(x)
+size_t (*ib_strlen)();
+#define strlen(x) ib_strlen(x)
+int (*ib_isdigit)();
+#define isdigit(x) ib_isdigit(x)
+char *(*ib_strcpy)();
+#define strcpy(x,y) ib_strcpy((x),(y))
+int (*ib_atoi)();
+#define atoi(x) ib_atoi(x)
+char *(*ib_strcat)();
+#define strcat(x,y) ib_strcat((x),(y))
+int (*ib_stat)();
+/* #define stat(x,y) ib_stat((x),(y)) */
+FILE *ib_iob;
+#define _iob ib_iob
+
+#else
+
+#define ib_stat stat
+
+#endif /* SHLIB */
+
+
+#define WIDTHB(x) (((x+15)>>4)<<1)
+
+extern unsigned short *quadr;
+extern float dyuvrgb[4][4];
+extern float rgbdyuv[4][4];
+
+
+typedef struct Adat
+{
+ unsigned short w, h;
+ unsigned short type;
+ unsigned short xorig, yorig;
+ unsigned short pad;
+ float gamma;
+ float distort;
+}Adat;
+
+struct BitMapHeader
+{
+ unsigned short w, h; /* in pixels */
+ unsigned short x, y;
+ char nPlanes;
+ char masking;
+ char compression;
+ char pad1;
+ unsigned short transparentColor;
+ char xAspect, yAspect;
+ short pageWidth, pageHeight;
+};
+
+#endif /* IMBUF_H */
diff --git a/source/blender/imbuf/intern/imbuf_patch.h b/source/blender/imbuf/intern/imbuf_patch.h
new file mode 100644
index 00000000000..9dbdc55969c
--- /dev/null
+++ b/source/blender/imbuf/intern/imbuf_patch.h
@@ -0,0 +1,114 @@
+/**
+ * imbuf_patch.h
+ *
+ * These are some definitions to make imbuf more independent from the
+ * rest of the blender code. Most of these are dirty and should not
+ * really exist.
+ *
+ * $Id$ *
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 IMBUF_PATCH_H
+#define IMBUF_PATCH_H
+
+/* most of imbuf uses this aloc, and it will disappear soon
+ * (hopefully) (25-10-2001 nzc) */
+#include "MEM_guardedalloc.h"
+
+struct ImBuf;
+
+/* originally, these were defines ... */
+typedef unsigned char uchar;
+
+/* should not be used at all */
+#define TRUE 1
+#define FALSE 0
+
+/* Endianness: flip the byte order. It's strange that this is needed..
+ * After all, there is an internal endian.{c,h}... */
+#if defined(__sgi) || defined (__sparc) || defined (__PPC__) || defined (__ppc__) || defined (__BIG_ENDIAN__)
+#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
+
+/* These defines loop back to the internal Blender memory management
+ * system, implemented in blenlib. */
+#define NEW(x) (x*)MEM_mallocN(sizeof(x),# x)
+#define mallocstruct(x,y) (x*)malloc((y)* sizeof(x))
+#define callocstruct(x,y) (x*)calloc((y), sizeof(x))
+
+/* These vars are used thoughout the image buffer for conversions. */
+extern float rgbyuv[4][4];
+extern float yuvrgb[4][4];
+extern float rgbbeta[4][4];
+
+/* This one helps debugging. */
+extern int IB_verbose;
+
+/* These ID's are used for checking memory blocks. See blenlib for
+ * more details. This set is only used in the imbuf internally. */
+
+#define CAT MAKE_ID('C','A','T',' ')
+#define FORM MAKE_ID('F','O','R','M')
+#define ILBM MAKE_ID('I','L','B','M')
+#define BMHD MAKE_ID('B','M','H','D')
+#define CMAP MAKE_ID('C','M','A','P')
+#define CAMG MAKE_ID('C','A','M','G')
+#define BODY MAKE_ID('B','O','D','Y')
+
+#define ANIM MAKE_ID('A','N','I','M')
+#define ADAT MAKE_ID('A','D','A','T')
+#define CODE MAKE_ID('C','O','D','E')
+#define ANHD MAKE_ID('A','N','H','D')
+#define DLTA MAKE_ID('D','L','T','A')
+#define BLCK MAKE_ID('B','L','C','K')
+
+#define MAXRUN 126
+#define MAXDAT 126
+#define IFFNOP 128
+
+#define camg ftype
+
+#define LI_rect IB_rect
+#define LI_planes IB_planes
+#define LI_kcmap IB_cmap
+#define LI_cmap IB_cmap
+#define LI_freem IB_freem
+#define LI_test IB_test
+
+#define SI_rect IB_rect
+#define SI_planes IB_planes
+#define SI_kcmap IB_cmap
+#define SI_cmap IB_cmap
+#define SI_vert IB_vert
+
+#endif
+
diff --git a/source/blender/imbuf/intern/iris.c b/source/blender/imbuf/intern/iris.c
new file mode 100644
index 00000000000..72a9a76d044
--- /dev/null
+++ b/source/blender/imbuf/intern/iris.c
@@ -0,0 +1,727 @@
+/**
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * iris.c
+ *
+ * $Id$
+ */
+
+#include <string.h>
+#include "BLI_blenlib.h"
+
+#include "imbuf.h"
+#include "imbuf_patch.h"
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "IMB_allocimbuf.h"
+#include "IMB_iris.h"
+
+
+typedef struct {
+ unsigned short imagic; /* stuff saved on disk . . */
+ unsigned short type;
+ unsigned short dim;
+ unsigned short xsize;
+ unsigned short ysize;
+ unsigned short zsize;
+ unsigned int min;
+ unsigned int max;
+ unsigned int wastebytes;
+ char name[80];
+ unsigned int colormap;
+
+ int file; /* stuff used in core only */
+ unsigned short flags;
+ short dorev;
+ short x;
+ short y;
+ short z;
+ short cnt;
+ unsigned short *ptr;
+ unsigned short *base;
+ unsigned short *tmpbuf;
+ unsigned int offset;
+ unsigned int rleend; /* for rle images */
+ unsigned int *rowstart; /* for rle images */
+ int *rowsize; /* for rle images */
+} IMAGE;
+
+#define RINTLUM (79)
+#define GINTLUM (156)
+#define BINTLUM (21)
+
+#define ILUM(r,g,b) ((int)(RINTLUM*(r)+GINTLUM*(g)+BINTLUM*(b))>>8)
+
+#define OFFSET_R 0 /* this is byte order dependent */
+#define OFFSET_G 1
+#define OFFSET_B 2
+#define OFFSET_A 3
+
+#define CHANOFFSET(z) (3-(z)) /* this is byte order dependent */
+
+#define TYPEMASK 0xff00
+#define BPPMASK 0x00ff
+#define ITYPE_VERBATIM 0x0000
+#define ITYPE_RLE 0x0100
+#define ISRLE(type) (((type) & 0xff00) == ITYPE_RLE)
+#define ISVERBATIM(type) (((type) & 0xff00) == ITYPE_VERBATIM)
+#define BPP(type) ((type) & BPPMASK)
+#define RLE(bpp) (ITYPE_RLE | (bpp))
+#define VERBATIM(bpp) (ITYPE_VERBATIM | (bpp))
+#define IBUFSIZE(pixels) ((pixels+(pixels>>6))<<2)
+#define RLE_NOP 0x00
+
+/* funcs */
+static void readheader(FILE *inf, IMAGE *image);
+static int writeheader(FILE *outf, IMAGE *image);
+
+static unsigned short getshort(FILE *inf);
+static unsigned int getlong(FILE *inf);
+static void putshort(FILE *outf, unsigned short val);
+static int putlong(FILE *outf, unsigned int val);
+static int writetab(FILE *outf, unsigned int *tab, int len);
+static void readtab(FILE *inf, unsigned int *tab, int len);
+
+static void expandrow(unsigned char *optr, unsigned char *iptr, int z);
+static void interleaverow(unsigned char *lptr, unsigned char *cptr, int z, int n);
+static int compressrow(unsigned char *lbuf, unsigned char *rlebuf, int z, int cnt);
+static void lumrow(unsigned char *rgbptr, unsigned char *lumptr, int n);
+
+/* not used... */
+/* static void copybw(int *lptr, int n); */
+/* static void setalpha(unsigned char *lptr, int n); */
+
+/*
+ * byte order independent read/write of shorts and ints.
+ *
+ */
+
+static uchar * file_data;
+static int file_offset;
+
+static unsigned short getshort(FILE *inf)
+/* FILE *inf; */
+{
+ unsigned char * buf;
+
+ buf = file_data + file_offset;
+ file_offset += 2;
+
+ return (buf[0]<<8)+(buf[1]<<0);
+}
+
+static unsigned int getlong(FILE *inf)
+/* FILE *inf; */
+{
+ unsigned char * buf;
+
+ buf = file_data + file_offset;
+ file_offset += 4;
+
+ return (buf[0]<<24)+(buf[1]<<16)+(buf[2]<<8)+(buf[3]<<0);
+}
+
+static void putshort(FILE *outf, unsigned short val)
+/* FILE *outf; */
+/* unsigned short val; */
+{
+ unsigned char buf[2];
+
+ buf[0] = (val>>8);
+ buf[1] = (val>>0);
+ fwrite(buf,2,1,outf);
+}
+
+static int putlong(FILE *outf, unsigned int val)
+/* FILE *outf; */
+/* unsigned int val; */
+{
+ unsigned char buf[4];
+
+ buf[0] = (val>>24);
+ buf[1] = (val>>16);
+ buf[2] = (val>>8);
+ buf[3] = (val>>0);
+ return fwrite(buf,4,1,outf);
+}
+
+static void readheader(FILE *inf, IMAGE *image)
+/* FILE *inf; */
+/* IMAGE *image; */
+{
+ memset(image, 0, sizeof(IMAGE));
+ image->imagic = getshort(inf);
+ image->type = getshort(inf);
+ image->dim = getshort(inf);
+ image->xsize = getshort(inf);
+ image->ysize = getshort(inf);
+ image->zsize = getshort(inf);
+}
+
+static int writeheader(FILE *outf, IMAGE *image)
+/* FILE *outf; */
+/* IMAGE *image; */
+{
+ IMAGE t;
+
+ memset(&t, 0, sizeof(IMAGE));
+ fwrite(&t,sizeof(IMAGE),1,outf);
+ fseek(outf,0,SEEK_SET);
+ putshort(outf,image->imagic);
+ putshort(outf,image->type);
+ putshort(outf,image->dim);
+ putshort(outf,image->xsize);
+ putshort(outf,image->ysize);
+ putshort(outf,image->zsize);
+ putlong(outf,image->min);
+ putlong(outf,image->max);
+ putlong(outf,0);
+ return fwrite("no name",8,1,outf);
+}
+
+static int writetab(FILE *outf, unsigned int *tab, int len)
+/* FILE *outf; */
+/* unsigned int *tab; */
+/* int len; */
+{
+ int r;
+
+ while(len) {
+ r = putlong(outf,*tab++);
+ len -= 4;
+ }
+ return r;
+}
+
+static void readtab(FILE *inf, unsigned int *tab, int len)
+/* FILE *inf; */
+/* unsigned int *tab; */
+/* int len; */
+{
+ while(len) {
+ *tab++ = getlong(inf);
+ len -= 4;
+ }
+}
+
+static void test_endian_zbuf(struct ImBuf *ibuf)
+{
+ int len;
+ int *zval;
+
+ if( BIG_LONG(1) == 1 ) return;
+ if(ibuf->zbuf==0) return;
+
+ len= ibuf->x*ibuf->y;
+ zval= ibuf->zbuf;
+
+ while(len--) {
+ zval[0]= BIG_LONG(zval[0]);
+ zval++;
+ }
+}
+
+
+/*
+ * longimagedata -
+ * read in a B/W RGB or RGBA iris image file and return a
+ * pointer to an array of ints.
+ *
+ */
+
+struct ImBuf *imb_loadiris(unsigned char *mem, int flags)
+{
+ unsigned int *base, *lptr;
+ unsigned int *zbase, *zptr;
+ unsigned char *rledat;
+ int *starttab, *lengthtab;
+ FILE *inf;
+ IMAGE image;
+ int x, y, z, tablen;
+ int xsize, ysize, zsize;
+ int bpp, rle, cur, badorder;
+ ImBuf * ibuf;
+ uchar * rect;
+
+ /*printf("new iris\n");*/
+
+ file_data = mem;
+ file_offset = 0;
+
+ readheader(inf, &image);
+ if(image.imagic != IMAGIC) {
+ fprintf(stderr,"longimagedata: bad magic number in image file\n");
+ return(0);
+ }
+
+ rle = ISRLE(image.type);
+ bpp = BPP(image.type);
+ if(bpp != 1 ) {
+ fprintf(stderr,"longimagedata: image must have 1 byte per pix chan\n");
+ return(0);
+ }
+
+ xsize = image.xsize;
+ ysize = image.ysize;
+ zsize = image.zsize;
+
+ if (flags & IB_test) {
+ ibuf = IMB_allocImBuf(image.xsize, image.ysize, 8 * image.zsize, 0, 0);
+ if (ibuf) ibuf->ftype = IMAGIC;
+ return(ibuf);
+ }
+
+ if (rle) {
+ tablen = ysize*zsize*sizeof(int);
+ starttab = (int *)malloc(tablen);
+ lengthtab = (int *)malloc(tablen);
+ file_offset = 512;
+
+ readtab(inf,starttab,tablen);
+ readtab(inf,lengthtab,tablen);
+
+ /* check data order */
+ cur = 0;
+ badorder = 0;
+ for (y = 0; y<ysize; y++) {
+ for (z = 0; z<zsize; z++) {
+ if (starttab[y+z*ysize]<cur) {
+ badorder = 1;
+ break;
+ }
+ cur = starttab[y+z*ysize];
+ }
+ if(badorder)
+ break;
+ }
+
+ ibuf = IMB_allocImBuf(xsize, ysize, 8 * zsize, IB_rect, 0);
+ if (ibuf->depth > 32) ibuf->depth = 32;
+ base = ibuf->rect;
+ zbase = (unsigned int *)ibuf->zbuf;
+
+ if (badorder) {
+ for(z=0; z<zsize; z++) {
+ lptr = base;
+ for(y=0; y<ysize; y++) {
+ file_offset = starttab[y+z*ysize];
+
+ rledat = file_data + file_offset;
+ file_offset += lengthtab[y+z*ysize];
+
+ expandrow(lptr, rledat, 3-z);
+ lptr += xsize;
+ }
+ }
+ }
+ else {
+ lptr = base;
+ zptr = zbase;
+ for(y=0; y<ysize; y++) {
+
+ for(z=0; z<zsize; z++) {
+
+ file_offset = starttab[y+z*ysize];
+
+ rledat = file_data + file_offset;
+ file_offset += lengthtab[y+z*ysize];
+
+ if(z<4) expandrow(lptr, rledat, 3-z);
+ else if(z<8) expandrow(zptr, rledat, 7-z);
+ }
+ lptr += xsize;
+ zptr += xsize;
+ }
+ }
+
+ free(starttab);
+ free(lengthtab);
+ }
+ else {
+
+ ibuf = IMB_allocImBuf(xsize, ysize, 8 * zsize, IB_rect, 0);
+ if (ibuf->depth > 32) ibuf->depth = 32;
+
+ base = ibuf->rect;
+ zbase = (unsigned int *)ibuf->zbuf;
+
+ file_offset = 512;
+ rledat = file_data + file_offset;
+
+ for(z = 0; z < zsize; z++) {
+
+ if(z<4) lptr = base;
+ else if(z<8) lptr= zbase;
+
+ for(y = 0; y < ysize; y++) {
+
+ interleaverow(lptr, rledat, 3-z, xsize);
+ rledat += xsize;
+
+ lptr += xsize;
+ }
+ }
+ }
+
+ if (image.zsize == 1){
+ rect = (uchar *) ibuf->rect;
+ for (x = ibuf->x * ibuf->y; x > 0; x--) {
+ rect[0] = 255;
+ rect[1] = rect[2] = rect[3];
+ rect += 4;
+ }
+ } else if (image.zsize == 3){
+ /* alpha toevoegen */
+ rect = (uchar *) ibuf->rect;
+ for (x = ibuf->x * ibuf->y; x > 0; x--) {
+ rect[0] = 255;
+ rect += 4;
+ }
+ }
+
+ ibuf->ftype = IMAGIC;
+ if (flags & IB_ttob) IMB_flipy(ibuf);
+
+ test_endian_zbuf(ibuf);
+
+ if (ibuf) {
+ if (ibuf->rect)
+ IMB_convert_rgba_to_abgr(ibuf->x*ibuf->y, ibuf->rect);
+ }
+
+ return(ibuf);
+}
+
+/* static utility functions for longimagedata */
+
+static void interleaverow(unsigned char *lptr, unsigned char *cptr, int z, int n)
+/* unsigned char *lptr, *cptr; */
+/* int z, n; */
+{
+ lptr += z;
+ while(n--) {
+ *lptr = *cptr++;
+ lptr += 4;
+ }
+}
+
+/* not used? */
+/*static void copybw(int *lptr, int n) */
+/* int *lptr; */
+/* int n; */
+/*{
+ while(n>=8) {
+ lptr[0] = 0xff000000+(0x010101*(lptr[0]&0xff));
+ lptr[1] = 0xff000000+(0x010101*(lptr[1]&0xff));
+ lptr[2] = 0xff000000+(0x010101*(lptr[2]&0xff));
+ lptr[3] = 0xff000000+(0x010101*(lptr[3]&0xff));
+ lptr[4] = 0xff000000+(0x010101*(lptr[4]&0xff));
+ lptr[5] = 0xff000000+(0x010101*(lptr[5]&0xff));
+ lptr[6] = 0xff000000+(0x010101*(lptr[6]&0xff));
+ lptr[7] = 0xff000000+(0x010101*(lptr[7]&0xff));
+ lptr += 8;
+ n-=8;
+ }
+ while(n--) {
+ *lptr = 0xff000000+(0x010101*(*lptr&0xff));
+ lptr++;
+ }
+}
+*/
+
+/* not used ? */
+/*static void setalpha(unsigned char *lptr, int n)*/
+/* unsigned char *lptr; */
+/*{
+ while(n>=8) {
+ lptr[0*4] = 0xff;
+ lptr[1*4] = 0xff;
+ lptr[2*4] = 0xff;
+ lptr[3*4] = 0xff;
+ lptr[4*4] = 0xff;
+ lptr[5*4] = 0xff;
+ lptr[6*4] = 0xff;
+ lptr[7*4] = 0xff;
+ lptr += 4*8;
+ n -= 8;
+ }
+ while(n--) {
+ *lptr = 0xff;
+ lptr += 4;
+ }
+}
+*/
+
+static void expandrow(unsigned char *optr, unsigned char *iptr, int z)
+/* unsigned char *optr, *iptr; */
+/* int z; */
+{
+ unsigned char pixel, count;
+
+ optr += z;
+ while(1) {
+ pixel = *iptr++;
+ if ( !(count = (pixel & 0x7f)) )
+ return;
+ if(pixel & 0x80) {
+ while(count>=8) {
+ optr[0*4] = iptr[0];
+ optr[1*4] = iptr[1];
+ optr[2*4] = iptr[2];
+ optr[3*4] = iptr[3];
+ optr[4*4] = iptr[4];
+ optr[5*4] = iptr[5];
+ optr[6*4] = iptr[6];
+ optr[7*4] = iptr[7];
+ optr += 8*4;
+ iptr += 8;
+ count -= 8;
+ }
+ while(count--) {
+ *optr = *iptr++;
+ optr+=4;
+ }
+ } else {
+ pixel = *iptr++;
+ while(count>=8) {
+ optr[0*4] = pixel;
+ optr[1*4] = pixel;
+ optr[2*4] = pixel;
+ optr[3*4] = pixel;
+ optr[4*4] = pixel;
+ optr[5*4] = pixel;
+ optr[6*4] = pixel;
+ optr[7*4] = pixel;
+ optr += 8*4;
+ count -= 8;
+ }
+ while(count--) {
+ *optr = pixel;
+ optr+=4;
+ }
+ }
+ }
+}
+
+/*
+ * output_iris -
+ * copy an array of ints to an iris image file. Each int
+ * represents one pixel. xsize and ysize specify the dimensions of
+ * the pixel array. zsize specifies what kind of image file to
+ * write out. if zsize is 1, the luminance of the pixels are
+ * calculated, and a sinlge channel black and white image is saved.
+ * If zsize is 3, an RGB image file is saved. If zsize is 4, an
+ * RGBA image file is saved.
+ *
+ * Added: zbuf write
+ */
+
+static int output_iris(unsigned int *lptr, int xsize, int ysize, int zsize, int file, int *zptr)
+{
+ FILE *outf;
+ IMAGE *image;
+ int tablen, y, z, pos, len;
+ int *starttab, *lengthtab;
+ unsigned char *rlebuf;
+ unsigned int *lumbuf;
+ int rlebuflen, goodwrite;
+
+ goodwrite = 1;
+ outf = fdopen(file, "wb");
+
+ if(!outf) {
+ perror("fdopen");
+ fprintf(stderr,"output_iris: can't open output file\n");
+ return 0;
+ }
+ tablen = ysize*zsize*sizeof(int);
+
+ image = (IMAGE *)malloc(sizeof(IMAGE));
+ starttab = (int *)malloc(tablen);
+ lengthtab = (int *)malloc(tablen);
+ rlebuflen = 1.05*xsize+10;
+ rlebuf = (unsigned char *)malloc(rlebuflen);
+ lumbuf = (unsigned int *)malloc(xsize*sizeof(int));
+
+ memset(image, 0, sizeof(IMAGE));
+ image->imagic = IMAGIC;
+ image->type = RLE(1);
+ if(zsize>1)
+ image->dim = 3;
+ else
+ image->dim = 2;
+ image->xsize = xsize;
+ image->ysize = ysize;
+ image->zsize = zsize;
+ image->min = 0;
+ image->max = 255;
+ goodwrite *= writeheader(outf,image);
+ fseek(outf,512+2*tablen,SEEK_SET);
+ pos = 512+2*tablen;
+
+ for (y = 0; y < ysize; y++) {
+ for (z = 0; z < zsize; z++) {
+
+ if (zsize == 1) {
+ lumrow(lptr,lumbuf,xsize);
+ len = compressrow(lumbuf,rlebuf,CHANOFFSET(z),xsize);
+ }
+ else {
+ if(z<4) {
+ len = compressrow(lptr, rlebuf,CHANOFFSET(z),xsize);
+ }
+ else if(z<8 && zptr) {
+ len = compressrow(zptr, rlebuf,CHANOFFSET(z-4),xsize);
+ }
+ }
+ if(len>rlebuflen) {
+ fprintf(stderr,"output_iris: rlebuf is too small - bad poop\n");
+ exit(1);
+ }
+ goodwrite *= fwrite(rlebuf, len, 1, outf);
+ starttab[y+z*ysize] = pos;
+ lengthtab[y+z*ysize] = len;
+ pos += len;
+ }
+ lptr += xsize;
+ if(zptr) zptr += xsize;
+ }
+
+ fseek(outf,512,SEEK_SET);
+ goodwrite *= writetab(outf,starttab,tablen);
+ goodwrite *= writetab(outf,lengthtab,tablen);
+ free(image);
+ free(starttab);
+ free(lengthtab);
+ free(rlebuf);
+ free(lumbuf);
+ fclose(outf);
+ if(goodwrite)
+ return 1;
+ else {
+ fprintf(stderr,"output_iris: not enough space for image!!\n");
+ return 0;
+ }
+}
+
+/* static utility functions for output_iris */
+
+static void lumrow(unsigned char *rgbptr, unsigned char *lumptr, int n)
+/* unsigned char *rgbptr, *lumptr; */
+/* int n; */
+{
+ lumptr += CHANOFFSET(0);
+ while(n--) {
+ *lumptr = ILUM(rgbptr[OFFSET_R],rgbptr[OFFSET_G],rgbptr[OFFSET_B]);
+ lumptr += 4;
+ rgbptr += 4;
+ }
+}
+
+static int compressrow(unsigned char *lbuf, unsigned char *rlebuf, int z, int cnt)
+/* unsigned char *lbuf, *rlebuf; */
+/* int z, cnt; */
+{
+ unsigned char *iptr, *ibufend, *sptr, *optr;
+ short todo, cc;
+ int count;
+
+ lbuf += z;
+ iptr = lbuf;
+ ibufend = iptr+cnt*4;
+ optr = rlebuf;
+
+ while(iptr<ibufend) {
+ sptr = iptr;
+ iptr += 8;
+ while((iptr<ibufend)&& ((iptr[-8]!=iptr[-4])||(iptr[-4]!=iptr[0])))
+ iptr+=4;
+ iptr -= 8;
+ count = (iptr-sptr)/4;
+ while(count) {
+ todo = count>126 ? 126:count;
+ count -= todo;
+ *optr++ = 0x80|todo;
+ while(todo>8) {
+ optr[0] = sptr[0*4];
+ optr[1] = sptr[1*4];
+ optr[2] = sptr[2*4];
+ optr[3] = sptr[3*4];
+ optr[4] = sptr[4*4];
+ optr[5] = sptr[5*4];
+ optr[6] = sptr[6*4];
+ optr[7] = sptr[7*4];
+
+ optr += 8;
+ sptr += 8*4;
+ todo -= 8;
+ }
+ while(todo--) {
+ *optr++ = *sptr;
+ sptr += 4;
+ }
+ }
+ sptr = iptr;
+ cc = *iptr;
+ iptr += 4;
+ while( (iptr<ibufend) && (*iptr == cc) )
+ iptr += 4;
+ count = (iptr-sptr)/4;
+ while(count) {
+ todo = count>126 ? 126:count;
+ count -= todo;
+ *optr++ = todo;
+ *optr++ = cc;
+ }
+ }
+ *optr++ = 0;
+ return optr - (unsigned char *)rlebuf;
+}
+
+short imb_saveiris(struct ImBuf * ibuf, int file, int flags)
+{
+ short zsize;
+ int ret;
+
+ zsize = (ibuf->depth + 7) >> 3;
+ if (flags & IB_zbuf && ibuf->zbuf != 0) zsize = 8;
+
+ IMB_convert_rgba_to_abgr(ibuf->x*ibuf->y, ibuf->rect);
+ test_endian_zbuf(ibuf);
+
+ ret = output_iris(ibuf->rect, ibuf->x, ibuf->y, zsize, file, ibuf->zbuf);
+
+ /* restore! Quite clumsy, 2 times a switch... maybe better a malloc ? */
+ IMB_convert_rgba_to_abgr(ibuf->x*ibuf->y, ibuf->rect);
+ test_endian_zbuf(ibuf);
+
+ return(ret);
+}
+
diff --git a/source/blender/imbuf/intern/jpeg.c b/source/blender/imbuf/intern/jpeg.c
new file mode 100644
index 00000000000..8132997e5cd
--- /dev/null
+++ b/source/blender/imbuf/intern/jpeg.c
@@ -0,0 +1,629 @@
+/**
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * jpeg.c
+ *
+ * $Id$
+ */
+
+
+/* This little block needed for linking to Blender... */
+#include <stdio.h>
+#include "BLI_blenlib.h"
+
+#include "imbuf.h"
+#include "imbuf_patch.h"
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "IMB_jpeg.h"
+
+#include "jpeglib.h"
+
+/* the types are from the jpeg lib */
+static void jpeg_error (j_common_ptr cinfo);
+static void init_source(j_decompress_ptr cinfo);
+static boolean fill_input_buffer(j_decompress_ptr cinfo);
+static void skip_input_data(j_decompress_ptr cinfo, long num_bytes);
+static void term_source(j_decompress_ptr cinfo);
+static void memory_source(j_decompress_ptr cinfo, unsigned char *buffer, int size);
+static boolean handle_app1 (j_decompress_ptr cinfo);
+static ImBuf * ibJpegImageFromCinfo(struct jpeg_decompress_struct * cinfo, int flags);
+
+
+/* strncasecmp hack */
+#ifdef WIN32
+#define strncasecmp(a, b, n) strncmp(a, b, n)
+#endif
+
+/*
+ * Er zijn in principe vier verschillende jpeg formaten.
+ *
+ * 1. jpeg - standaard drukwerk, u & v op kwart van resolutie
+ * 2. jvid - standaard video u & v halve resolutie, frame opengeklapt
+
+type 3 is unsupported as of jul 05 2000 Frank.
+
+ * 3. jstr - als 2, maar dan met twee losse fields weggeschreven
+ * moet baseline zijn
+ * moet rgb zijn
+ * moet samplingfactors goed hebben
+
+
+ * 4. jmax - geen scaling in de componenten
+ */
+
+static int jpeg_failed = FALSE;
+static int jpeg_default_quality;
+static int ibuf_ftype;
+
+static void jpeg_error (j_common_ptr cinfo)
+{
+ /* Always display the message */
+ (*cinfo->err->output_message) (cinfo);
+
+ /* Let the memory manager delete any temp files before we die */
+ jpeg_destroy(cinfo);
+
+ jpeg_failed = TRUE;
+}
+
+//----------------------------------------------------------
+// INPUT HANDLER FROM MEMORY
+//----------------------------------------------------------
+
+typedef struct {
+ unsigned char *buffer;
+ int filled;
+} buffer_struct;
+
+typedef struct {
+ struct jpeg_source_mgr pub; /* public fields */
+
+ unsigned char *buffer;
+ int size;
+ JOCTET terminal[2];
+} my_source_mgr;
+
+typedef my_source_mgr * my_src_ptr;
+
+static void init_source(j_decompress_ptr cinfo)
+{
+}
+
+
+static boolean fill_input_buffer(j_decompress_ptr cinfo)
+{
+ my_src_ptr src = (my_src_ptr) cinfo->src;
+
+ /* Since we have given all we have got already
+ * we simply fake an end of file
+ */
+
+ src->pub.next_input_byte = src->terminal;
+ src->pub.bytes_in_buffer = 2;
+ src->terminal[0] = (JOCTET) 0xFF;
+ src->terminal[1] = (JOCTET) JPEG_EOI;
+
+ return TRUE;
+}
+
+
+static void skip_input_data(j_decompress_ptr cinfo, long num_bytes)
+{
+ my_src_ptr src = (my_src_ptr) cinfo->src;
+
+ src->pub.next_input_byte = src->pub.next_input_byte + num_bytes;
+}
+
+
+static void term_source(j_decompress_ptr cinfo)
+{
+}
+
+static void memory_source(j_decompress_ptr cinfo, unsigned char *buffer, int size)
+{
+ my_src_ptr src;
+
+ if (cinfo->src == NULL)
+ { /* first time for this JPEG object? */
+ cinfo->src = (struct jpeg_source_mgr *)(*cinfo->mem->alloc_small)
+ ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ sizeof(my_source_mgr));
+ }
+
+ src = (my_src_ptr) cinfo->src;
+ src->pub.init_source = init_source;
+ src->pub.fill_input_buffer = fill_input_buffer;
+ src->pub.skip_input_data = skip_input_data;
+ src->pub.resync_to_restart = jpeg_resync_to_restart;
+ src->pub.term_source = term_source;
+
+ src->pub.bytes_in_buffer = size;
+ src->pub.next_input_byte = buffer;
+
+ src->buffer = buffer;
+ src->size = size;
+}
+
+
+#define MAKESTMT(stuff) do { stuff } while (0)
+
+#define INPUT_VARS(cinfo) \
+ struct jpeg_source_mgr * datasrc = (cinfo)->src; \
+ const JOCTET * next_input_byte = datasrc->next_input_byte; \
+ size_t bytes_in_buffer = datasrc->bytes_in_buffer
+
+/* Unload the local copies --- do this only at a restart boundary */
+#define INPUT_SYNC(cinfo) \
+ ( datasrc->next_input_byte = next_input_byte, \
+ datasrc->bytes_in_buffer = bytes_in_buffer )
+
+/* Reload the local copies --- seldom used except in MAKE_BYTE_AVAIL */
+#define INPUT_RELOAD(cinfo) \
+ ( next_input_byte = datasrc->next_input_byte, \
+ bytes_in_buffer = datasrc->bytes_in_buffer )
+
+/* Internal macro for INPUT_BYTE and INPUT_2BYTES: make a byte available.
+ * Note we do *not* do INPUT_SYNC before calling fill_input_buffer,
+ * but we must reload the local copies after a successful fill.
+ */
+#define MAKE_BYTE_AVAIL(cinfo,action) \
+ if (bytes_in_buffer == 0) { \
+ if (! (*datasrc->fill_input_buffer) (cinfo)) \
+ { action; } \
+ INPUT_RELOAD(cinfo); \
+ } \
+ bytes_in_buffer--
+
+/* Read a byte into variable V.
+ * If must suspend, take the specified action (typically "return FALSE").
+ */
+#define INPUT_BYTE(cinfo,V,action) \
+ MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \
+ V = GETJOCTET(*next_input_byte++); )
+
+/* As above, but read two bytes interpreted as an unsigned 16-bit integer.
+ * V should be declared unsigned int or perhaps INT32.
+ */
+#define INPUT_2BYTES(cinfo,V,action) \
+ MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \
+ V = ((unsigned int) GETJOCTET(*next_input_byte++)) << 8; \
+ MAKE_BYTE_AVAIL(cinfo,action); \
+ V += GETJOCTET(*next_input_byte++); )
+
+
+static boolean
+handle_app1 (j_decompress_ptr cinfo)
+{
+ INT32 length, i;
+ char neogeo[128];
+
+ INPUT_VARS(cinfo);
+
+ INPUT_2BYTES(cinfo, length, return FALSE);
+ length -= 2;
+
+ if (length < 16) {
+ for (i = 0; i < length; i++) INPUT_BYTE(cinfo, neogeo[i], return FALSE);
+ length = 0;
+ if (strncmp(neogeo, "NeoGeo", 6) == 0) memcpy(&ibuf_ftype, neogeo + 6, 4);
+ ibuf_ftype = BIG_LONG(ibuf_ftype);
+ }
+ INPUT_SYNC(cinfo); /* do before skip_input_data */
+ if (length > 0) (*cinfo->src->skip_input_data) (cinfo, length);
+ return TRUE;
+}
+
+
+static ImBuf * ibJpegImageFromCinfo(struct jpeg_decompress_struct * cinfo, int flags)
+{
+ JSAMPARRAY row_pointer;
+ JSAMPLE * buffer = 0;
+ int row_stride;
+ int x, y, depth, r, g, b, k;
+ struct ImBuf * ibuf = 0;
+ uchar * rect;
+
+ /* eigen app1 handler installeren */
+ ibuf_ftype = 0;
+ jpeg_set_marker_processor(cinfo, 0xe1, handle_app1);
+ cinfo->dct_method = JDCT_FLOAT;
+
+ if (jpeg_read_header(cinfo, FALSE) == JPEG_HEADER_OK) {
+ x = cinfo->image_width;
+ y = cinfo->image_height;
+ depth = cinfo->num_components;
+
+ if (cinfo->jpeg_color_space == JCS_YCCK) cinfo->out_color_space = JCS_CMYK;
+
+ jpeg_start_decompress(cinfo);
+
+ if (ibuf_ftype == 0) {
+ ibuf_ftype = JPG_STD;
+ if (cinfo->max_v_samp_factor == 1) {
+ if (cinfo->max_h_samp_factor == 1) ibuf_ftype = JPG_MAX;
+ else ibuf_ftype = JPG_VID;
+ }
+ }
+
+ if (flags & IB_test) {
+ jpeg_abort_decompress(cinfo);
+ ibuf = IMB_allocImBuf(x, y, 8 * depth, 0, 0);
+ } else {
+ ibuf = IMB_allocImBuf(x, y, 8 * depth, IB_rect, 0);
+
+ row_stride = cinfo->output_width * depth;
+
+ row_pointer = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, row_stride, 1);
+
+ for (y = ibuf->y - 1; y >= 0; y--) {
+ jpeg_read_scanlines(cinfo, row_pointer, 1);
+ if (flags & IB_ttob) {
+ rect = (uchar *) (ibuf->rect + (ibuf->y - 1 - y) * ibuf->x);
+ } else {
+ rect = (uchar *) (ibuf->rect + y * ibuf->x);
+ }
+ buffer = row_pointer[0];
+
+ switch(depth) {
+ case 1:
+ for (x = ibuf->x; x > 0; x--) {
+ rect[3] = 255;
+ rect[0] = rect[1] = rect[2] = *buffer++;
+ rect += 4;
+ }
+ break;
+ case 3:
+ for (x = ibuf->x; x > 0; x--) {
+ rect[3] = 255;
+ rect[0] = *buffer++;
+ rect[1] = *buffer++;
+ rect[2] = *buffer++;
+ rect += 4;
+ }
+ break;
+ case 4:
+ for (x = ibuf->x; x > 0; x--) {
+ r = *buffer++;
+ g = *buffer++;
+ b = *buffer++;
+ k = *buffer++;
+
+ k = 255 - k;
+ r -= k;
+ if (r & 0xffffff00) {
+ if (r < 0) r = 0;
+ else r = 255;
+ }
+ g -= k;
+ if (g & 0xffffff00) {
+ if (g < 0) g = 0;
+ else g = 255;
+ }
+ b -= k;
+ if (b & 0xffffff00) {
+ if (b < 0) b = 0;
+ else b = 255;
+ }
+
+ rect[3] = 255 - k;
+ rect[2] = b;
+ rect[1] = g;
+ rect[0] = r;
+ rect += 4;
+ }
+ }
+ }
+ jpeg_finish_decompress(cinfo);
+ }
+
+ jpeg_destroy((j_common_ptr) cinfo);
+ ibuf->ftype = ibuf_ftype;
+ }
+
+ return(ibuf);
+}
+
+ImBuf * imb_ibJpegImageFromFilename (char * filename, int flags)
+{
+ struct jpeg_decompress_struct _cinfo, *cinfo = &_cinfo;
+ struct jpeg_error_mgr jerr;
+ FILE * infile;
+ ImBuf * ibuf;
+
+ if ((infile = fopen(filename, "rb")) == NULL) {
+ /*fprintf(stderr, "can't open %s\n", filename);*/
+ return 0;
+ }
+
+ cinfo->err = jpeg_std_error(&jerr);
+ jerr.error_exit = jpeg_error;
+
+ jpeg_create_decompress(cinfo);
+ jpeg_stdio_src(cinfo, infile);
+
+ ibuf = ibJpegImageFromCinfo(cinfo, flags);
+
+ fclose(infile);
+ return(ibuf);
+}
+
+ImBuf * imb_ibJpegImageFromMemory (unsigned char * buffer, int size, int flags)
+{
+ struct jpeg_decompress_struct _cinfo, *cinfo = &_cinfo;
+ struct jpeg_error_mgr jerr;
+ ImBuf * ibuf;
+
+ cinfo->err = jpeg_std_error(&jerr);
+ jerr.error_exit = jpeg_error;
+
+ jpeg_create_decompress(cinfo);
+ memory_source(cinfo, buffer, size);
+
+ ibuf = ibJpegImageFromCinfo(cinfo, flags);
+
+ return(ibuf);
+}
+
+
+static void write_jpeg(struct jpeg_compress_struct * cinfo, struct ImBuf * ibuf)
+{
+ JSAMPLE * buffer = 0;
+ JSAMPROW row_pointer[1];
+ uchar * rect;
+ int x, y;
+ char neogeo[128];
+
+
+ jpeg_start_compress(cinfo, TRUE);
+
+ strcpy(neogeo, "NeoGeo");
+ ibuf_ftype = BIG_LONG(ibuf->ftype);
+
+ memcpy(neogeo + 6, &ibuf_ftype, 4);
+ jpeg_write_marker(cinfo, 0xe1, (JOCTET*) neogeo, 10);
+
+ row_pointer[0] =
+ mallocstruct(JSAMPLE,
+ cinfo->input_components *
+ cinfo->image_width);
+
+ for(y = ibuf->y - 1; y >= 0; y--){
+ rect = (uchar *) (ibuf->rect + y * ibuf->x);
+ buffer = row_pointer[0];
+
+ switch(cinfo->in_color_space){
+ case JCS_RGB:
+ for (x = 0; x < ibuf->x; x++) {
+ *buffer++ = rect[0];
+ *buffer++ = rect[1];
+ *buffer++ = rect[2];
+ rect += 4;
+ }
+ break;
+ case JCS_GRAYSCALE:
+ for (x = 0; x < ibuf->x; x++) {
+ *buffer++ = rect[0];
+ rect += 4;
+ }
+ break;
+ case JCS_UNKNOWN:
+ memcpy(buffer, rect, 4 * ibuf->x);
+ break;
+ /* default was missing... intentional ? */
+ default:
+ ; /* do nothing */
+ }
+
+ jpeg_write_scanlines(cinfo, row_pointer, 1);
+
+ if (jpeg_failed) break;
+ }
+
+ if (jpeg_failed == FALSE) jpeg_finish_compress(cinfo);
+ free(row_pointer[0]);
+}
+
+
+static int init_jpeg(FILE * outfile, struct jpeg_compress_struct * cinfo, struct ImBuf *ibuf)
+{
+ int quality;
+
+ quality = ibuf->ftype & 0xff;
+ if (quality <= 0) quality = jpeg_default_quality;
+ if (quality > 100) quality = 100;
+
+ jpeg_create_compress(cinfo);
+ jpeg_stdio_dest(cinfo, outfile);
+
+ cinfo->image_width = ibuf->x;
+ cinfo->image_height = ibuf->y;
+
+ cinfo->in_color_space = JCS_RGB;
+ if (ibuf->depth == 8 && ibuf->cmap == 0) cinfo->in_color_space = JCS_GRAYSCALE;
+ if (ibuf->depth == 32) cinfo->in_color_space = JCS_UNKNOWN;
+
+ switch(cinfo->in_color_space){
+ case JCS_RGB:
+ cinfo->input_components = 3;
+ break;
+ case JCS_GRAYSCALE:
+ cinfo->input_components = 1;
+ break;
+ case JCS_UNKNOWN:
+ cinfo->input_components = 4;
+ break;
+ /* default was missing... intentional ? */
+ default:
+ ; /* do nothing */
+ }
+ jpeg_set_defaults(cinfo);
+
+ /* eigen instellingen */
+
+ cinfo->dct_method = JDCT_FLOAT;
+ jpeg_set_quality(cinfo, quality, TRUE);
+
+ return(0);
+}
+
+
+static int save_stdjpeg(char * name, struct ImBuf * ibuf)
+{
+ FILE * outfile;
+ struct jpeg_compress_struct _cinfo, *cinfo = &_cinfo;
+ struct jpeg_error_mgr jerr;
+
+ if ((outfile = fopen(name, "wb")) == NULL) return(-1);
+ jpeg_default_quality = 75;
+
+ cinfo->err = jpeg_std_error(&jerr);
+ jerr.error_exit = jpeg_error;
+
+ init_jpeg(outfile, cinfo, ibuf);
+
+ write_jpeg(cinfo, ibuf);
+
+ fclose(outfile);
+ jpeg_destroy_compress(cinfo);
+
+ if (jpeg_failed) remove(name);
+ return(jpeg_failed);
+}
+
+
+static int save_vidjpeg(char * name, struct ImBuf * ibuf)
+{
+ FILE * outfile;
+ struct jpeg_compress_struct _cinfo, *cinfo = &_cinfo;
+ struct jpeg_error_mgr jerr;
+
+ if ((outfile = fopen(name, "wb")) == NULL) return(-1);
+ jpeg_default_quality = 90;
+
+ cinfo->err = jpeg_std_error(&jerr);
+ jerr.error_exit = jpeg_error;
+
+ init_jpeg(outfile, cinfo, ibuf);
+
+ /* scalings factoren goedzetten */
+ if (cinfo->in_color_space == JCS_RGB) {
+ cinfo->comp_info[0].h_samp_factor = 2;
+ cinfo->comp_info[0].v_samp_factor = 1;
+ }
+
+ write_jpeg(cinfo, ibuf);
+
+ fclose(outfile);
+ jpeg_destroy_compress(cinfo);
+
+ if (jpeg_failed) remove(name);
+ return(jpeg_failed);
+}
+
+static int save_jstjpeg(char * name, struct ImBuf * ibuf)
+{
+ char fieldname[1024];
+ struct ImBuf * tbuf;
+ int oldy;
+/* extern rectcpy(); */
+
+ tbuf = IMB_allocImBuf(ibuf->x, ibuf->y / 2, 24, IB_rect, 0);
+ tbuf->ftype = ibuf->ftype;
+ tbuf->flags = ibuf->flags;
+
+ oldy = ibuf->y;
+ ibuf->x *= 2;
+ ibuf->y /= 2;
+
+ /* extra argument assumed to be 0 (nzc) */
+/* rectop(tbuf, ibuf, 0, 0, 0, 0, 32767, 32767, rectcpy); */
+ IMB_rectop(tbuf, ibuf, 0, 0, 0, 0, 32767, 32767, IMB_rectcpy, 0);
+ sprintf(fieldname, "%s.jf0", name);
+
+ if (save_vidjpeg(fieldname, tbuf) == 0) {
+ /* extra argument assumed to be 0 (nzc) */
+/* rectop(tbuf, ibuf, 0, 0, tbuf->x, 0, 32767, 32767, rectcpy); */
+ IMB_rectop(tbuf, ibuf, 0, 0, tbuf->x, 0, 32767, 32767, IMB_rectcpy, 0);
+ sprintf(fieldname, "%s.jf1", name);
+ save_vidjpeg(fieldname, tbuf);
+ }
+
+ ibuf->y = oldy;
+ ibuf->x /= 2;
+ IMB_freeImBuf(tbuf);
+
+ /* no return value was given, assuming 0 */
+ return 0;
+}
+
+
+static int save_maxjpeg(char * name, struct ImBuf * ibuf)
+{
+ FILE * outfile;
+ struct jpeg_compress_struct _cinfo, *cinfo = &_cinfo;
+ struct jpeg_error_mgr jerr;
+
+ if ((outfile = fopen(name, "wb")) == NULL) return(-1);
+ jpeg_default_quality = 100;
+
+ cinfo->err = jpeg_std_error(&jerr);
+ jerr.error_exit = jpeg_error;
+
+ init_jpeg(outfile, cinfo, ibuf);
+
+ /* scalings factoren goedzetten */
+ if (cinfo->in_color_space == JCS_RGB) {
+ cinfo->comp_info[0].h_samp_factor = 1;
+ cinfo->comp_info[0].v_samp_factor = 1;
+ }
+
+ write_jpeg(cinfo, ibuf);
+
+ fclose(outfile);
+ jpeg_destroy_compress(cinfo);
+
+ if (jpeg_failed) remove(name);
+ return(jpeg_failed);
+}
+
+
+int imb_save_jpeg(char * name, struct ImBuf * ibuf, int flags)
+{
+ int ret;
+
+ ibuf->flags = flags;
+ if (IS_stdjpg(ibuf)) ret = save_stdjpeg(name, ibuf);
+ else if (IS_jstjpg(ibuf)) ret = save_jstjpeg(name, ibuf);
+ else if (IS_maxjpg(ibuf)) ret = save_maxjpeg(name, ibuf);
+ else ret = save_vidjpeg(name, ibuf);
+ return(ret);
+}
+
diff --git a/source/blender/imbuf/intern/matrix.h b/source/blender/imbuf/intern/matrix.h
new file mode 100644
index 00000000000..62c1c3022d0
--- /dev/null
+++ b/source/blender/imbuf/intern/matrix.h
@@ -0,0 +1,86 @@
+/**
+ * matrix.c
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/* rgbyuv is identiek aan rgbbeta */
+
+float rgbyuv[4][4]={ /* afgeleid uit videoframer = Y Cr Cb in kopieen van Francois*/
+ /* is identriek aan matrix van jpeg */
+ .50000, .11400, -.08131, 0.0, /* b */
+ -.33126, .58700, -.41869, 0.0, /* g */
+ -.16874, .29900, .50000, 0.0, /* r */
+ 128.0, 0.0, 128.0, 1.0};
+
+ /* b-y (u) y r-y (v) */
+
+
+float rgbbeta[4][4]={ /* afgeleid uit videoframer = Y Cr Cb in kopieen van Francois*/
+ /* is identriek aan matrix van jpeg */
+ .50000, .11400, -.08131, 0.0, /* b-y -> b */
+ -.33126, .58700, -.41869, 0.0, /* y -> g */
+ -.16874, .29900, .50000, 0.0, /* r-y -> r */
+ 128.0, 0.0, 128.0, 1.0};
+
+ /* b-y y r-y */
+
+
+
+float yuvrgb[4][4]={
+ 1.77200, -0.34414, 0.0, 0.0,
+ 1.0, 1.0, 1.0, 0.0,
+ 0.0, -0.71414, 1.40200, 0.0,
+ -226.816, 135.460, -179.456, 1.0};
+
+float rgb_to_bw[4][4]={
+ .114, .114, .114, 0.0,
+ .587, .587, .587, 0.0,
+ .299, .299, .299, 0.0,
+ 0.5, 0.5, 0.5, 1.0};
+
+float dyuvrgb_oud[4][4]={
+ 1.0 , 1.0 , 1.0, 0.0,
+ 1.733, -0.337, 0.0, 0.0,
+ 0.0, -.698, 1.371, 0.0,
+ -221.8, 132.47, -175.5, 1.0};
+
+float dyuvrgb[4][4]={
+ 1.164 , 1.164 , 1.164, 0.0,
+ 2.018, -0.391, 0.0, 0.0,
+ 0.0, -0.813, 1.596, 0.0,
+ -276.7, 135.6, -222.7, 1.0};
+
+float rgbdyuv[4][4]={
+ 0.439, 0.098, -0.071, 0.0,
+ -0.291, 0.504, -0.368, 0.0,
+ -0.148, 0.257, 0.439, 0.0,
+ 128.0, 16.0, 128.0, 1.0};
diff --git a/source/blender/imbuf/intern/png_decode.c b/source/blender/imbuf/intern/png_decode.c
new file mode 100644
index 00000000000..c4d795fa5af
--- /dev/null
+++ b/source/blender/imbuf/intern/png_decode.c
@@ -0,0 +1,263 @@
+/**
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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$
+ */
+
+#include "png.h"
+
+#ifdef _WIN32
+#include "BLI_winstuff.h"
+#endif
+#include "BLI_blenlib.h"
+
+#include "imbuf.h"
+#include "imbuf_patch.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "IMB_allocimbuf.h"
+#include "IMB_cmap.h"
+#include "IMB_png.h"
+
+
+
+static int checkpng(unsigned char *mem)
+{
+ int ret_val = 0;
+
+ if (mem) {
+ ret_val = !png_sig_cmp(mem, 0, 8);
+ }
+
+ return(ret_val);
+}
+
+int imb_is_a_png(void *buf) {
+
+ return checkpng(buf);
+}
+
+typedef struct PNGReadStruct {
+ unsigned char *data;
+ unsigned int size;
+ unsigned int seek;
+}PNGReadStruct;
+
+static void
+ReadData(
+ png_structp png_ptr,
+ png_bytep data,
+ png_size_t length);
+
+static void
+ReadData(
+ png_structp png_ptr,
+ png_bytep data,
+ png_size_t length)
+{
+ PNGReadStruct *rs= (PNGReadStruct *) png_get_io_ptr(png_ptr);
+
+ if (rs) {
+ if (length <= rs->size - rs->seek) {
+ memcpy(data, rs->data + rs->seek, length);
+ rs->seek += length;
+ return;
+ }
+ }
+
+ printf("Reached EOF while decoding PNG\n");
+ longjmp(png_jmpbuf(png_ptr), 1);
+}
+
+
+struct ImBuf *imb_png_decode(unsigned char *mem, int size, int flags)
+{
+ struct ImBuf *ibuf = 0;
+ png_structp png_ptr;
+ png_infop info_ptr;
+ unsigned char *pixels = 0;
+ png_bytepp row_pointers = 0;
+ png_uint_32 width, height;
+ int bit_depth, color_type;
+ PNGReadStruct ps;
+
+ unsigned char *from, *to;
+ int i, bytesperpixel;
+
+ if (checkpng(mem) == 0) return(0);
+
+ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
+ NULL, NULL, NULL);
+ if (png_ptr == NULL) {
+ printf("Cannot png_create_read_struct\n");
+ return 0;
+ }
+
+ info_ptr = png_create_info_struct(png_ptr);
+ if (info_ptr == NULL) {
+ png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
+ printf("Cannot png_create_info_struct\n");
+ return 0;
+ }
+
+ ps.size = size;
+ ps.data = mem;
+ ps.seek = 0;
+
+ png_set_read_fn(png_ptr, (void *) &ps, ReadData);
+
+ if (setjmp(png_jmpbuf(png_ptr))) {
+ png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
+ if (pixels) MEM_freeN(pixels);
+ if (row_pointers) MEM_freeN(row_pointers);
+ if (ibuf) IMB_freeImBuf(ibuf);
+ return 0;
+ }
+
+ // png_set_sig_bytes(png_ptr, 8);
+
+ png_read_info(png_ptr, info_ptr);
+ png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL);
+
+ if (bit_depth == 16) {
+ png_set_strip_16(png_ptr);
+ bit_depth = 8;
+ }
+
+ bytesperpixel = png_get_channels(png_ptr, info_ptr);
+
+ switch(color_type) {
+ case PNG_COLOR_TYPE_RGB:
+ case PNG_COLOR_TYPE_RGB_ALPHA:
+ break;
+ case PNG_COLOR_TYPE_PALETTE:
+ png_set_palette_to_rgb(png_ptr);
+ if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
+ bytesperpixel = 4;
+ } else {
+ bytesperpixel = 3;
+ }
+ break;
+ case PNG_COLOR_TYPE_GRAY:
+ case PNG_COLOR_TYPE_GRAY_ALPHA:
+ if (bit_depth < 8) {
+ png_set_expand(png_ptr);
+ bit_depth = 8;
+ }
+ break;
+ default:
+ printf("PNG format not supported\n");
+ longjmp(png_jmpbuf(png_ptr), 1);
+ }
+
+ ibuf = IMB_allocImBuf(width, height, 8 * bytesperpixel, 0, 0);
+
+ if (ibuf) {
+ ibuf->ftype = PNG;
+ } else {
+ printf("Couldn't allocate memory for PNG image\n");
+ }
+
+ if (ibuf && ((flags & IB_test) == 0)) {
+ imb_addrectImBuf(ibuf);
+
+ pixels = MEM_mallocN(ibuf->x * ibuf->y * bytesperpixel * sizeof(unsigned char), "pixels");
+ if (pixels == NULL) {
+ printf("Cannot allocate pixels array\n");
+ longjmp(png_jmpbuf(png_ptr), 1);
+ }
+
+ // allocate memory for an array of row-pointers
+ row_pointers = (png_bytepp) MEM_mallocN(ibuf->y * sizeof(png_bytep), "row_pointers");
+ if (row_pointers == NULL) {
+ printf("Cannot allocate row-pointers array\n");
+ longjmp(png_jmpbuf(png_ptr), 1);
+ }
+
+ // set the individual row-pointers to point at the correct offsets
+ for (i = 0; i < ibuf->y; i++) {
+ row_pointers[ibuf->y-1-i] = (png_bytep)
+ ((unsigned char *)pixels + (i * ibuf->x) * bytesperpixel * sizeof(unsigned char));
+ }
+
+ png_read_image(png_ptr, row_pointers);
+
+ // copy image data
+
+ to = (unsigned char *) ibuf->rect;
+ from = pixels;
+
+ switch (bytesperpixel) {
+ case 4:
+ for (i = ibuf->x * ibuf->y; i > 0; i--) {
+ to[0] = from[0];
+ to[1] = from[1];
+ to[2] = from[2];
+ to[3] = from[3];
+ to += 4; from += 4;
+ }
+ break;
+ case 3:
+ for (i = ibuf->x * ibuf->y; i > 0; i--) {
+ to[0] = from[0];
+ to[1] = from[1];
+ to[2] = from[2];
+ to[3] = 0xff;
+ to += 4; from += 3;
+ }
+ break;
+ case 2:
+ for (i = ibuf->x * ibuf->y; i > 0; i--) {
+ to[0] = to[1] = to[2] = from[0];
+ to[3] = from[1];
+ to += 4; from += 2;
+ }
+ break;
+ case 1:
+ for (i = ibuf->x * ibuf->y; i > 0; i--) {
+ to[0] = to[1] = to[2] = from[0];
+ to[3] = 0xff;
+ to += 4; from++;
+ }
+ break;
+ }
+
+ png_read_end(png_ptr, info_ptr);
+ }
+
+ // clean up
+ MEM_freeN(pixels);
+ MEM_freeN(row_pointers);
+ png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
+
+ return(ibuf);
+}
+
diff --git a/source/blender/imbuf/intern/png_encode.c b/source/blender/imbuf/intern/png_encode.c
new file mode 100644
index 00000000000..a4423f57830
--- /dev/null
+++ b/source/blender/imbuf/intern/png_encode.c
@@ -0,0 +1,236 @@
+/**
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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$
+ */
+
+
+#include "png.h"
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+#include "BLI_blenlib.h"
+
+#include "imbuf.h"
+#include "imbuf_patch.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "IMB_allocimbuf.h"
+#include "IMB_cmap.h"
+
+static void
+WriteData(
+ png_structp png_ptr,
+ png_bytep data,
+ png_size_t length);
+
+static void
+Flush(
+ png_structp png_ptr);
+
+static void
+WriteData(
+ png_structp png_ptr,
+ png_bytep data,
+ png_size_t length)
+{
+ ImBuf *ibuf = (ImBuf *) png_get_io_ptr(png_ptr);
+
+ // if buffer is to small increase it.
+ while (ibuf->encodedsize + length > ibuf->encodedbuffersize) {
+ imb_enlargeencodedbufferImBuf(ibuf);
+ }
+
+ memcpy(ibuf->encodedbuffer + ibuf->encodedsize, data, length);
+ ibuf->encodedsize += length;
+}
+
+static void
+Flush(
+ png_structp png_ptr)
+{
+}
+
+short IMB_png_encode(struct ImBuf *ibuf, int file, int flags)
+{
+ png_structp png_ptr;
+ png_infop info_ptr;
+ unsigned char *pixels = 0;
+ unsigned char *from, *to;
+ png_bytepp row_pointers = 0;
+ int i, bytesperpixel, color_type;
+ FILE *fp = 0;
+
+ bytesperpixel = (ibuf->depth + 7) >> 3;
+ if ((bytesperpixel > 4) || (bytesperpixel == 2)) {
+ printf("imb_png_encode: unsupported bytes per pixel: %d\n", bytesperpixel);
+ return (0);
+ }
+
+ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
+ NULL, NULL, NULL);
+ if (png_ptr == NULL) {
+ printf("Cannot png_create_write_struct\n");
+ return 0;
+ }
+
+ info_ptr = png_create_info_struct(png_ptr);
+ if (info_ptr == NULL) {
+ png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
+ printf("Cannot png_create_info_struct\n");
+ return 0;
+ }
+
+ if (setjmp(png_jmpbuf(png_ptr))) {
+ png_destroy_write_struct(&png_ptr, &info_ptr);
+ if (pixels) MEM_freeN(pixels);
+ if (row_pointers) MEM_freeN(row_pointers);
+ // printf("Aborting\n");
+ if (fp) {
+ fflush(fp);
+ fclose(fp);
+ }
+ return 0;
+ }
+
+ // copy image data
+
+ pixels = MEM_mallocN(ibuf->x * ibuf->y * bytesperpixel * sizeof(unsigned char), "pixels");
+ if (pixels == NULL) {
+ printf("Cannot allocate pixels array\n");
+ return 0;
+ }
+
+ from = (unsigned char *) ibuf->rect;
+ to = pixels;
+
+ switch (bytesperpixel) {
+ case 4:
+ color_type = PNG_COLOR_TYPE_RGBA;
+ for (i = ibuf->x * ibuf->y; i > 0; i--) {
+ to[0] = from[0];
+ to[1] = from[1];
+ to[2] = from[2];
+ to[3] = from[3];
+ to += 4; from += 4;
+ }
+ break;
+ case 3:
+ color_type = PNG_COLOR_TYPE_RGB;
+ for (i = ibuf->x * ibuf->y; i > 0; i--) {
+ to[0] = from[0];
+ to[1] = from[1];
+ to[2] = from[2];
+ to += 3; from += 4;
+ }
+ break;
+ case 1:
+ color_type = PNG_COLOR_TYPE_GRAY;
+ for (i = ibuf->x * ibuf->y; i > 0; i--) {
+ to[0] = from[0];
+ to++; from += 4;
+ }
+ break;
+ }
+
+ if (flags & IB_mem) {
+ // create image in memory
+ imb_addencodedbufferImBuf(ibuf);
+ ibuf->encodedsize = 0;
+
+ png_set_write_fn(png_ptr,
+ (png_voidp) ibuf,
+ WriteData,
+ Flush);
+ } else {
+ fp = fdopen(file, "wb");
+ png_init_io(png_ptr, fp);
+ }
+
+ /*
+ png_set_filter(png_ptr, 0,
+ PNG_FILTER_NONE | PNG_FILTER_VALUE_NONE |
+ PNG_FILTER_SUB | PNG_FILTER_VALUE_SUB |
+ PNG_FILTER_UP | PNG_FILTER_VALUE_UP |
+ PNG_FILTER_AVG | PNG_FILTER_VALUE_AVG |
+ PNG_FILTER_PAETH | PNG_FILTER_VALUE_PAETH|
+ PNG_ALL_FILTERS);
+
+ png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);
+ */
+
+ // png image settings
+ png_set_IHDR(png_ptr,
+ info_ptr,
+ ibuf->x,
+ ibuf->y,
+ 8,
+ color_type,
+ PNG_INTERLACE_NONE,
+ PNG_COMPRESSION_TYPE_DEFAULT,
+ PNG_FILTER_TYPE_DEFAULT);
+
+ // write the file header information
+ png_write_info(png_ptr, info_ptr);
+
+ // allocate memory for an array of row-pointers
+ row_pointers = (png_bytepp) MEM_mallocN(ibuf->y * sizeof(png_bytep), "row_pointers");
+ if (row_pointers == NULL) {
+ printf("Cannot allocate row-pointers array\n");
+ return 0;
+ }
+
+ // set the individual row-pointers to point at the correct offsets
+ for (i = 0; i < ibuf->y; i++) {
+ row_pointers[ibuf->y-1-i] = (png_bytep)
+ ((unsigned char *)pixels + (i * ibuf->x) * bytesperpixel * sizeof(unsigned char));
+ }
+
+ // write out the entire image data in one call
+ png_write_image(png_ptr, row_pointers);
+
+ // write the additional chunks to the PNG file (not really needed)
+ png_write_end(png_ptr, info_ptr);
+
+ // clean up
+ MEM_freeN(pixels);
+ MEM_freeN(row_pointers);
+ png_destroy_write_struct(&png_ptr, &info_ptr);
+
+ if (fp) {
+ fflush(fp);
+ fclose(fp);
+ }
+
+ return(1);
+}
+
diff --git a/source/blender/imbuf/intern/readimage.c b/source/blender/imbuf/intern/readimage.c
new file mode 100644
index 00000000000..ef9c7271d7b
--- /dev/null
+++ b/source/blender/imbuf/intern/readimage.c
@@ -0,0 +1,256 @@
+/**
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * allocimbuf.c
+ *
+ * $Id$
+ */
+
+#include "BLI_blenlib.h"
+
+#include "imbuf.h"
+#include "imbuf_patch.h"
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "IMB_amiga.h"
+#include "IMB_iris.h"
+#include "IMB_targa.h"
+#include "IMB_png.h"
+#include "IMB_hamx.h"
+#include "IMB_jpeg.h"
+#include "IMB_bmp.h"
+
+/* actually hard coded endianness */
+#define GET_BIG_LONG(x) (((uchar *) (x))[0] << 24 | ((uchar *) (x))[1] << 16 | ((uchar *) (x))[2] << 8 | ((uchar *) (x))[3])
+#define GET_LITTLE_LONG(x) (((uchar *) (x))[3] << 24 | ((uchar *) (x))[2] << 16 | ((uchar *) (x))[1] << 8 | ((uchar *) (x))[0])
+#define SWAP_L(x) (((x << 24) & 0xff000000) | ((x << 8) & 0xff0000) | ((x >> 8) & 0xff00) | ((x >> 24) & 0xff))
+#define SWAP_S(x) (((x << 8) & 0xff00) | ((x >> 8) & 0xff))
+
+/* more endianness... should move to a separate file... */
+#if defined(__sgi) || defined (__sparc) || defined (__PPC__) || defined (__ppc__) || defined (__BIG_ENDIAN__)
+#define GET_ID GET_BIG_LONG
+#define LITTLE_LONG SWAP_LONG
+#else
+#define GET_ID GET_LITTLE_LONG
+#define LITTLE_LONG ENDIAN_NOP
+#endif
+
+/* from misc_util: flip the bytes from x */
+#define GS(x) (((unsigned char *)(x))[0] << 8 | ((unsigned char *)(x))[1])
+
+/* this one is only def-ed once, strangely... */
+#define GSS(x) (((uchar *)(x))[1] << 8 | ((uchar *)(x))[0])
+
+int IB_verbose = TRUE;
+
+ImBuf *IMB_ibImageFromMemory(int *mem, int size, int flags) {
+ int len;
+ struct ImBuf *ibuf;
+
+ if (mem == NULL) {
+ printf("Error in ibImageFromMemory: NULL pointer\n");
+ } else {
+ if ((GS(mem) == IMAGIC) || (GSS(mem) == IMAGIC)){
+ return (imb_loadiris((uchar *) mem, flags));
+ } else if ((BIG_LONG(mem[0]) & 0xfffffff0) == 0xffd8ffe0) {
+ return (imb_ibJpegImageFromMemory((uchar *)mem, size, flags));
+ }
+
+ if (GET_ID(mem) == CAT){
+ mem += 3;
+ size -= 4;
+ while (size > 0){
+ if (GET_ID(mem) == FORM){
+ len = ((GET_BIG_LONG(mem+1) + 1) & ~1) + 8;
+ if ((GET_ID(mem+2) == ILBM) || (GET_ID(mem+2) == ANIM)) break;
+ mem = (int *)((uchar *)mem +len);
+ size -= len;
+ } else return(0);
+ }
+ }
+
+ if (size > 0){
+ if (GET_ID(mem) == FORM){
+ if (GET_ID(mem+2) == ILBM){
+ return (imb_loadamiga(mem, flags));
+ } else if (GET_ID(mem+5) == ILBM){ /* animaties */
+ return (imb_loadamiga(mem+3, flags));
+ } else if (GET_ID(mem+2) == ANIM){
+ return (imb_loadanim(mem, flags));
+ }
+ }
+ }
+
+ ibuf = imb_png_decode((uchar *)mem, size, flags);
+ if (ibuf) return(ibuf);
+
+ ibuf = imb_bmp_decode((uchar *)mem, size, flags);
+ if (ibuf) return(ibuf);
+
+ ibuf = imb_loadtarga((uchar *)mem, flags);
+ if (ibuf) return(ibuf);
+
+ if (IB_verbose) fprintf(stderr, "Unknown fileformat\n");
+ }
+
+ return (0);
+}
+
+
+struct ImBuf *IMB_loadiffmem(int *mem, int flags) {
+ int len,maxlen;
+ struct ImBuf *ibuf;
+
+ // IMB_loadiffmem shouldn't be used anymore in new development
+ // it's still here to be backwards compatible...
+
+ maxlen= (GET_BIG_LONG(mem+1) + 1) & ~1;
+
+ if (GET_ID(mem) == CAT){
+ mem += 3;
+ maxlen -= 4;
+ while(maxlen > 0){
+ if (GET_ID(mem) == FORM){
+ len = ((GET_BIG_LONG(mem+1) + 1) & ~1) + 8;
+ if ((GET_ID(mem+2) == ILBM) || (GET_ID(mem+2) == ANIM)) break;
+ mem = (int *)((uchar *)mem +len);
+ maxlen -= len;
+ } else return(0);
+ }
+ }
+
+ if (maxlen > 0){
+ if (GET_ID(mem) == FORM){
+ if (GET_ID(mem+2) == ILBM){
+ return (imb_loadamiga(mem, flags));
+ } else if (GET_ID(mem+5) == ILBM){ /* animaties */
+ return (imb_loadamiga(mem+3, flags));
+ } else if (GET_ID(mem+2) == ANIM){
+ return (imb_loadanim(mem, flags));
+ }
+ } else if ((GS(mem) == IMAGIC) || (GSS(mem) == IMAGIC)){
+ return (imb_loadiris((uchar *) mem,flags));
+ } else if ((BIG_LONG(mem[0]) & 0xfffffff0) == 0xffd8ffe0) {
+ return (0);
+ }
+ }
+
+ ibuf = imb_loadtarga((uchar *) mem,flags);
+ if (ibuf) return(ibuf);
+
+ if (IB_verbose) fprintf(stderr,"Unknown fileformat\n");
+ return (0);
+}
+
+struct ImBuf *IMB_loadifffile(int file, int flags) {
+ struct ImBuf *ibuf;
+ int size, *mem;
+
+ if (file == -1) return (0);
+
+ size = BLI_filesize(file);
+
+#if defined(AMIGA) || defined(__BeOS) || defined(WIN32)
+ mem= (int *)malloc(size);
+ if (mem==0) {
+ printf("Out of mem\n");
+ return (0);
+ }
+
+ if (read(file, mem, size)!=size){
+ printf("Read Error\n");
+ free(mem);
+ return (0);
+ }
+
+ ibuf = IMB_ibImageFromMemory(mem, size, flags);
+ free(mem);
+
+ /* for jpeg read */
+ lseek(file, 0L, SEEK_SET);
+
+#else
+ mem= (int *)mmap(0,size,PROT_READ,MAP_SHARED,file,0);
+ if (mem==(int *)-1){
+ printf("Couldn't get mapping\n");
+ return (0);
+ }
+
+ ibuf = IMB_ibImageFromMemory(mem, size, flags);
+
+ if (munmap( (void *) mem, size)){
+ printf("Couldn't unmap file.\n");
+ }
+#endif
+ return(ibuf);
+}
+
+
+struct ImBuf *IMB_loadiffname(char *naam, int flags) {
+ int file;
+ struct ImBuf *ibuf;
+ int buf[1];
+
+ file = open(naam, O_BINARY|O_RDONLY);
+
+ if (file == -1) return (0);
+
+ ibuf= IMB_loadifffile(file, flags);
+
+ if (ibuf == 0) {
+ if (read(file, buf, 4) != 4) buf[0] = 0;
+ if ((BIG_LONG(buf[0]) & 0xfffffff0) == 0xffd8ffe0)
+ ibuf = imb_ibJpegImageFromFilename(naam, flags);
+ }
+
+ if (ibuf) {
+ strncpy(ibuf->name, naam, sizeof(ibuf->name));
+ if (flags & IB_fields) IMB_de_interlace(ibuf);
+ }
+ close(file);
+ return(ibuf);
+}
+
+struct ImBuf *IMB_testiffname(char *naam,int flags) {
+ int file;
+ struct ImBuf *ibuf;
+
+ flags |= IB_test;
+ file = open(naam,O_BINARY|O_RDONLY);
+
+ if (file<=0) return (0);
+
+ ibuf=IMB_loadifffile(file,flags);
+ if (ibuf) {
+ strncpy(ibuf->name, naam, sizeof(ibuf->name));
+ }
+ close(file);
+ return(ibuf);
+}
diff --git a/source/blender/imbuf/intern/rectop.c b/source/blender/imbuf/intern/rectop.c
new file mode 100644
index 00000000000..32f01eea6c8
--- /dev/null
+++ b/source/blender/imbuf/intern/rectop.c
@@ -0,0 +1,135 @@
+/**
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * allocimbuf.c
+ *
+ * $Id$
+ */
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+#include "BLI_blenlib.h"
+
+#include "imbuf.h"
+#include "imbuf_patch.h"
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "IMB_allocimbuf.h"
+
+void IMB_rectcpy(unsigned int *drect, unsigned int *srect, int x, int dummy)
+{
+ memcpy(drect,srect, x * sizeof(int));
+}
+
+
+void IMB_rectfill(unsigned int *drect, unsigned int *srect, int x, int value)
+{
+ for (;x > 0; x--) *drect++ = value;
+}
+
+void IMB_rectop(struct ImBuf *dbuf,
+ struct ImBuf *sbuf,
+ int destx,
+ int desty,
+ int srcx,
+ int srcy,
+ int width,
+ int height,
+ void (*operation)(unsigned int *, unsigned int*, int, int),
+ int value)
+{
+ unsigned int *drect,*srect;
+
+ if (dbuf == 0) return;
+ if (operation == 0) return;
+
+ if (destx < 0){
+ srcx -= destx ;
+ width += destx ;
+ destx = 0;
+ }
+ if (srcx < 0){
+ destx -= srcx ;
+ width += destx ;
+ srcx = 0;
+ }
+ if (desty < 0){
+ srcy -= desty ;
+ height += desty ;
+ desty = 0;
+ }
+ if (srcy < 0){
+ desty -= srcy ;
+ height += desty ;
+ srcy = 0;
+ }
+
+ if (width > dbuf->x - destx) width = dbuf->x - destx;
+ if (height > dbuf->y - desty) height = dbuf->y - desty;
+ if (sbuf){
+ if (width > sbuf->x - srcx) width = sbuf->x - srcx;
+ if (height > sbuf->y - srcy) height = sbuf->y - srcy;
+ }
+
+ if (width <= 0) return;
+ if (height <= 0) return;
+
+ drect = dbuf->rect;
+ if (sbuf) srect = sbuf->rect;
+
+ drect += desty * dbuf->x;
+ drect += destx;
+ destx = dbuf->x;
+
+ if (sbuf) {
+ srect += srcy * sbuf->x;
+ srect += srcx;
+ srcx = sbuf->x;
+ } else{
+ srect = drect;
+ srcx = destx;
+ }
+
+ for (;height > 0; height--){
+ operation(drect,srect,width, value);
+ drect += destx;
+ srect += srcx;
+ }
+}
+
+
+void IMB_rectoptot(struct ImBuf *dbuf,
+ struct ImBuf *sbuf,
+ void (*operation)(unsigned int *, unsigned int*, int, int),
+ int value)
+{
+ IMB_rectop(dbuf,sbuf,0,0,0,0,32767,32767,operation, value);
+}
diff --git a/source/blender/imbuf/intern/rotate.c b/source/blender/imbuf/intern/rotate.c
new file mode 100644
index 00000000000..edd82347a8c
--- /dev/null
+++ b/source/blender/imbuf/intern/rotate.c
@@ -0,0 +1,71 @@
+/**
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * rotate.c
+ *
+ * $Id$
+ */
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+#include "BLI_blenlib.h"
+
+#include "imbuf.h"
+#include "imbuf_patch.h"
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "IMB_allocimbuf.h"
+
+void IMB_flipy(struct ImBuf * ibuf)
+{
+ short x,y,backx;
+ unsigned int *top,*bottom,temp;
+
+ if (ibuf == 0) return;
+ if (ibuf->rect == 0) return;
+
+ x = ibuf->x;
+ y = ibuf->y;
+ backx = x<<1;
+
+ top = ibuf->rect;
+ bottom = top + ((y-1) * x);
+ y >>= 1;
+
+ for(;y>0;y--){
+ for(x = ibuf->x; x > 0; x--){
+ temp = *top;
+ *(top++) = *bottom;
+ *(bottom++) = temp;
+ }
+ bottom -= backx;
+ }
+}
diff --git a/source/blender/imbuf/intern/scaling.c b/source/blender/imbuf/intern/scaling.c
new file mode 100644
index 00000000000..eb397f6bced
--- /dev/null
+++ b/source/blender/imbuf/intern/scaling.c
@@ -0,0 +1,699 @@
+/**
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * allocimbuf.c
+ *
+ * $Id$
+ */
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+#include "BLI_blenlib.h"
+
+#include "imbuf.h"
+#include "imbuf_patch.h"
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "IMB_allocimbuf.h"
+#include "IMB_filter.h"
+
+/************************************************************************/
+/* SCALING */
+/************************************************************************/
+
+
+struct ImBuf *IMB_half_x(struct ImBuf *ibuf1)
+{
+ struct ImBuf *ibuf2;
+ uchar *p1,*_p1,*dest;
+ short a,r,g,b,x,y;
+
+ if (ibuf1==0) return (0);
+ if (ibuf1->rect == 0) return (0);
+
+ if (ibuf1->x <= 1) return(IMB_dupImBuf(ibuf1));
+
+ ibuf2 = IMB_allocImBuf((ibuf1->x)/2 , ibuf1->y , ibuf1->depth,1,0);
+ if (ibuf2==0) return (0);
+
+ _p1 = (uchar *) ibuf1->rect;
+ dest=(uchar *) ibuf2->rect;
+
+ for(y=ibuf2->y;y>0;y--){
+ p1 = _p1;
+ for(x = ibuf2->x ; x>0 ; x--){
+ a = *(p1++) ;
+ b = *(p1++) ;
+ g = *(p1++) ;
+ r = *(p1++);
+ a += *(p1++) ;
+ b += *(p1++) ;
+ g += *(p1++) ;
+ r += *(p1++);
+ *(dest++) = a >> 1;
+ *(dest++) = b >> 1;
+ *(dest++) = g >> 1;
+ *(dest++) = r >> 1;
+ }
+ _p1 += (ibuf1->x << 2);
+ }
+ return (ibuf2);
+}
+
+
+struct ImBuf *IMB_double_fast_x(struct ImBuf *ibuf1)
+{
+ struct ImBuf *ibuf2;
+ int *p1,*dest, i, col;
+
+ if (ibuf1==0) return (0);
+ if (ibuf1->rect == 0) return (0);
+
+ ibuf2 = IMB_allocImBuf(2 * ibuf1->x , ibuf1->y , ibuf1->depth,1,0);
+ if (ibuf2==0) return (0);
+
+ p1 = (int *) ibuf1->rect;
+ dest=(int *) ibuf2->rect;
+
+ for(i = ibuf1->y * ibuf1->x ; i>0 ; i--) {
+ col = *p1++;
+ *dest++ = col;
+ *dest++ = col;
+ }
+
+ return (ibuf2);
+}
+
+struct ImBuf *IMB_double_x(struct ImBuf *ibuf1)
+{
+ struct ImBuf *ibuf2;
+
+ if (ibuf1==0) return (0);
+ if (ibuf1->rect == 0) return (0);
+
+ ibuf2 = IMB_double_fast_x(ibuf1);
+
+ imb_filterx(ibuf2);
+ return (ibuf2);
+}
+
+
+struct ImBuf *IMB_half_y(struct ImBuf *ibuf1)
+{
+ struct ImBuf *ibuf2;
+ uchar *p1,*p2,*_p1,*dest;
+ short a,r,g,b,x,y;
+
+ if (ibuf1==0) return (0);
+ if (ibuf1->rect == 0) return (0);
+ if (ibuf1->y <= 1) return(IMB_dupImBuf(ibuf1));
+
+ ibuf2 = IMB_allocImBuf(ibuf1->x , (ibuf1->y) / 2 , ibuf1->depth,1,0);
+ if (ibuf2==0) return (0);
+
+ _p1 = (uchar *) ibuf1->rect;
+ dest=(uchar *) ibuf2->rect;
+
+ for(y=ibuf2->y ; y>0 ; y--){
+ p1 = _p1;
+ p2 = _p1 + (ibuf1->x << 2);
+ for(x = ibuf2->x ; x>0 ; x--){
+ a = *(p1++) ;
+ b = *(p1++) ;
+ g = *(p1++) ;
+ r = *(p1++);
+ a += *(p2++) ;
+ b += *(p2++) ;
+ g += *(p2++) ;
+ r += *(p2++);
+ *(dest++) = a >> 1;
+ *(dest++) = b >> 1;
+ *(dest++) = g >> 1;
+ *(dest++) = r >> 1;
+ }
+ _p1 += (ibuf1->x << 3);
+ }
+ return (ibuf2);
+}
+
+
+struct ImBuf *IMB_double_fast_y(struct ImBuf *ibuf1)
+{
+ struct ImBuf *ibuf2;
+ int *p1, *dest1, *dest2;
+ short x,y;
+
+ if (ibuf1==0) return (0);
+ if (ibuf1->rect == 0) return (0);
+
+ ibuf2 = IMB_allocImBuf(ibuf1->x , 2 * ibuf1->y , ibuf1->depth,1,0);
+ if (ibuf2==0) return (0);
+
+ p1 = (int *) ibuf1->rect;
+ dest1=(int *) ibuf2->rect;
+
+ for(y = ibuf1->y ; y>0 ; y--){
+ dest2 = dest1 + ibuf2->x;
+ for(x = ibuf2->x ; x>0 ; x--) *dest1++ = *dest2++ = *p1++;
+ dest1 = dest2;
+ }
+
+ return (ibuf2);
+}
+
+struct ImBuf *IMB_double_y(struct ImBuf *ibuf1)
+{
+ struct ImBuf *ibuf2;
+
+ if (ibuf1==0) return (0);
+ if (ibuf1->rect == 0) return (0);
+
+ ibuf2 = IMB_double_fast_y(ibuf1);
+
+ IMB_filtery(ibuf2);
+ return (ibuf2);
+}
+
+
+struct ImBuf *IMB_onehalf(struct ImBuf *ibuf1)
+{
+ struct ImBuf *ibuf2;
+ uchar *p1,*p2,*dest;
+ int x,y;
+
+ if (ibuf1 == 0) return (0);
+ if (ibuf1->rect == 0) return (0);
+
+ if (ibuf1->x <= 1) return(IMB_half_y(ibuf1));
+ if (ibuf1->y <= 1) return(IMB_half_x(ibuf1));
+
+ ibuf2=IMB_allocImBuf((ibuf1->x)/2,(ibuf1->y)/2,ibuf1->depth,1,0);
+ if (ibuf2==0) return (0);
+
+ p1 = (uchar *) ibuf1->rect;
+ dest=(uchar *) ibuf2->rect;
+
+ for(y=ibuf2->y;y>0;y--){
+ p2 = p1 + (ibuf1->x << 2);
+ for(x=ibuf2->x;x>0;x--){
+ dest[0] = (p1[0] + p2[0] + p1[4] + p2[4]) >> 2;
+ dest[1] = (p1[1] + p2[1] + p1[5] + p2[5]) >> 2;
+ dest[2] = (p1[2] + p2[2] + p1[6] + p2[6]) >> 2;
+ dest[3] = (p1[3] + p2[3] + p1[7] + p2[7]) >> 2;
+ p1 += 8;
+ p2 += 8;
+ dest += 4;
+ }
+ p1=p2;
+ if(ibuf1->x & 1) {
+ p1+=4;
+ }
+ }
+ return (ibuf2);
+}
+
+
+
+struct ImBuf *IMB_onethird(struct ImBuf *ibuf1)
+{
+ struct ImBuf *ibuf2;
+ uchar *p1,*p2,*p3,*dest;
+ short a,r,g,b,x,y,i;
+
+ if (ibuf1 == 0) return (0);
+ if (ibuf1->rect == 0) return (0);
+
+ ibuf2=IMB_allocImBuf((ibuf1->x)/3,(ibuf1->y)/3,ibuf1->depth,1,0);
+ if (ibuf2==0) return (0);
+
+ p1 = (uchar *) ibuf1->rect;
+ dest=(uchar *) ibuf2->rect;
+
+ for(y=ibuf2->y;y>0;y--){
+ p2 = p1 + (ibuf1->x << 2);
+ p3 = p2 + (ibuf1->x << 2);
+ for(x=ibuf2->x;x>0;x--){
+ a=r=g=b=0;
+ for (i=3;i>0;i--){
+ a += *(p1++) + *(p2++) + *(p3++);
+ b += *(p1++) + *(p2++) + *(p3++);
+ g += *(p1++) + *(p2++) + *(p3++);
+ r += *(p1++) + *(p2++) + *(p3++);
+ }
+ *(dest++) = a/9;
+ *(dest++) = b/9;
+ *(dest++) = g/9;
+ *(dest++) = r/9;
+ }
+ p1=p3;
+ }
+ return (ibuf2);
+}
+
+
+struct ImBuf *IMB_halflace(struct ImBuf *ibuf1)
+{
+ struct ImBuf *ibuf2;
+ uchar *p1,*p2,*dest;
+ short a,r,g,b,x,y,i;
+
+ if (ibuf1 == 0) return (0);
+ if (ibuf1->rect == 0) return (0);
+
+ ibuf2=IMB_allocImBuf((ibuf1->x)/4,(ibuf1->y)/2,ibuf1->depth,1,0);
+ if (ibuf2==0) return (0);
+
+ p1 = (uchar *) ibuf1->rect;
+ dest=(uchar *) ibuf2->rect;
+
+ for(y= ibuf2->y / 2 ; y>0;y--){
+ p2 = p1 + (ibuf1->x << 3);
+ for(x = 2 * ibuf2->x;x>0;x--){
+ a=r=g=b=0;
+ for (i=4;i>0;i--){
+ a += *(p1++) + *(p2++);
+ b += *(p1++) + *(p2++);
+ g += *(p1++) + *(p2++);
+ r += *(p1++) + *(p2++);
+ }
+ *(dest++) = a >> 3;
+ *(dest++) = b >> 3;
+ *(dest++) = g >> 3;
+ *(dest++) = r >> 3;
+ }
+ p1 = p2;
+ }
+ return (ibuf2);
+}
+
+
+static struct ImBuf *scaledownx(struct ImBuf *ibuf, int newx)
+{
+ uchar *rect,*_newrect,*newrect;
+ float sample, add, val, nval;
+ int x, y, i;
+
+ if (ibuf == 0) return(0);
+ if (ibuf->rect == 0) return(ibuf);
+
+ _newrect = (uchar *) malloc(newx * ibuf->y * sizeof(int));
+ if (_newrect == 0) return(ibuf);
+
+ add = (ibuf->x - 0.001) / newx;
+
+ /* all four components, rgba/abgr */
+ for(i=3 ; i >= 0 ; i--){
+ rect = (uchar *) ibuf->rect;
+ rect += i;
+ newrect = _newrect + i;
+
+ for (y = ibuf->y; y>0 ; y--){
+ val = sample = 0.0;
+
+ for (x = newx ; x>0 ; x--){
+ nval = - val * sample;
+ sample += add;
+
+ while (sample >= 1.0){
+ sample -= 1.0;
+ nval += *rect;
+ rect += 4;
+ }
+ val = *rect;
+ rect += 4;
+ nval += sample * val;
+ sample -= 1.0;
+ *newrect = (nval/add) + 0.5;
+ newrect += 4;
+ }
+ }
+ }
+
+ imb_freerectImBuf(ibuf);
+ ibuf->mall |= IB_rect;
+ ibuf->rect = (unsigned int *) _newrect;
+ ibuf->x = newx;
+ return(ibuf);
+}
+
+
+static struct ImBuf *scaledowny(struct ImBuf *ibuf, int newy)
+{
+ uchar *rect,*_newrect,*newrect;
+ float sample,add,val,nval;
+ int x,y,i,skipx;
+
+ if (ibuf == 0) return(0);
+ if (ibuf->rect == 0) return(ibuf);
+
+ _newrect = (uchar *) malloc(newy * ibuf->x * sizeof(int));
+ if (_newrect == 0) return(ibuf);
+
+ add = (ibuf->y - 0.001) / newy;
+ skipx = 4 * ibuf->x;
+
+ /* all four components, rgba/abgr */
+ for(i=3 ; i>=0 ; i--){
+ for (x = skipx - 4; x>=0 ; x-= 4){
+ rect = ((uchar *) ibuf->rect) + i + x;
+ newrect = _newrect + i + x;
+ val = sample = 0.0;
+
+ for (y = newy ; y>0 ; y--){
+ nval = - val * sample;
+ sample += add;
+
+ while (sample >= 1.0){
+ sample -= 1.0;
+ nval += *rect;
+ rect += skipx;
+ }
+ val = *rect;
+ rect += skipx;
+ nval += sample * val;
+ sample -= 1.0;
+ *newrect = (nval/add) + 0.5;
+ newrect += skipx;
+ }
+ }
+ }
+
+ imb_freerectImBuf(ibuf);
+ ibuf->mall |= IB_rect;
+ ibuf->rect = (unsigned int *) _newrect;
+ ibuf->y = newy;
+ return(ibuf);
+}
+
+
+static struct ImBuf *scaleupx(struct ImBuf *ibuf, int newx)
+{
+ uchar *rect,*_newrect,*newrect;
+ float sample,add;
+ float val_a,nval_a,diff_a;
+ float val_b,nval_b,diff_b;
+ float val_g,nval_g,diff_g;
+ float val_r,nval_r,diff_r;
+ int x,y;
+
+ if (ibuf == 0) return(0);
+ if (ibuf->rect == 0) return(ibuf);
+
+ _newrect = (uchar *) malloc(newx * ibuf->y * sizeof(int));
+ if (_newrect == 0) return(ibuf);
+
+ add = (ibuf->x - 1.001) / (newx - 1.0);
+
+ rect = (uchar *) ibuf->rect;
+ newrect = _newrect;
+
+ for (y = ibuf->y; y>0 ; y--){
+
+ sample = 0;
+ val_a = rect[0] ;
+ nval_a = rect[4];
+ diff_a = nval_a - val_a ;
+ val_a += 0.5;
+
+ val_b = rect[1] ;
+ nval_b = rect[5];
+ diff_b = nval_b - val_b ;
+ val_b += 0.5;
+
+ val_g = rect[2] ;
+ nval_g = rect[6];
+ diff_g = nval_g - val_g ;
+ val_g += 0.5;
+
+ val_r = rect[3] ;
+ nval_r = rect[7];
+ diff_r = nval_r - val_r ;
+ val_r += 0.5;
+
+ rect += 8;
+ for (x = newx ; x>0 ; x--){
+ if (sample >= 1.0){
+ sample -= 1.0;
+ val_a = nval_a ;
+ nval_a = rect[0] ;
+ diff_a = nval_a - val_a ;
+ val_a += 0.5;
+
+ val_b = nval_b ;
+ nval_b = rect[1] ;
+ diff_b = nval_b - val_b ;
+ val_b += 0.5;
+
+ val_g = nval_g ;
+ nval_g = rect[2] ;
+ diff_g = nval_g - val_g ;
+ val_g += 0.5;
+
+ val_r = nval_r ;
+ nval_r = rect[3] ;
+ diff_r = nval_r - val_r ;
+ val_r += 0.5;
+ rect += 4;
+ }
+ newrect[0] = val_a + sample * diff_a;
+ newrect[1] = val_b + sample * diff_b;
+ newrect[2] = val_g + sample * diff_g;
+ newrect[3] = val_r + sample * diff_r;
+ newrect += 4;
+ sample += add;
+ }
+ }
+
+ imb_freerectImBuf(ibuf);
+ ibuf->mall |= IB_rect;
+ ibuf->rect = (unsigned int *) _newrect;
+ ibuf->x = newx;
+ return(ibuf);
+}
+
+
+static struct ImBuf *scaleupy(struct ImBuf *ibuf, int newy)
+{
+ uchar *rect,*_newrect,*newrect;
+ float sample,add,val,nval,diff;
+ int x,y,i,skipx;
+
+ if (ibuf == 0) return(0);
+ if (ibuf->rect == 0) return(ibuf);
+
+ _newrect = (uchar *)malloc(newy * ibuf->x * sizeof(int));
+ if (_newrect == 0) return(ibuf);
+
+ add = (ibuf->y - 1.001) / (newy - 1.0);
+ skipx = 4 * ibuf->x;
+
+ /* all four components, rgba/abgr */
+ for(i=3 ; i>=0 ; i--){
+ for (x = skipx - 4; x >= 0 ; x -= 4){
+ rect = (uchar *) ibuf->rect;
+ rect += i + x;
+ newrect = _newrect + i + x;
+
+ sample = 0;
+ val = *rect ;
+ rect += skipx;
+ nval = *rect;
+ rect += skipx;
+ diff = nval - val;
+ val += 0.5;
+
+ for (y = newy ; y>0 ; y--){
+ if (sample >= 1.0){
+ sample -= 1.0;
+ val = nval;
+ nval = *rect;
+ rect += skipx;
+ diff = nval - val;
+ val += 0.5;
+ }
+ *newrect = val + sample * diff;
+ newrect += skipx;
+ sample += add;
+ }
+ }
+ }
+
+ imb_freerectImBuf(ibuf);
+ ibuf->mall |= IB_rect;
+ ibuf->rect = (unsigned int *) _newrect;
+ ibuf->y = newy;
+ return(ibuf);
+}
+
+static void scalefast_Z_ImBuf(ImBuf *ibuf, short newx, short newy)
+{
+ unsigned int *rect,*_newrect,*newrect;
+ int x,y;
+ int ofsx,ofsy,stepx,stepy;
+
+ if (ibuf->zbuf) {
+ _newrect = malloc(newx * newy * sizeof(int));
+ if (_newrect == 0) return;
+
+ stepx = (65536.0 * (ibuf->x - 1.0) / (newx - 1.0)) + 0.5;
+ stepy = (65536.0 * (ibuf->y - 1.0) / (newy - 1.0)) + 0.5;
+ ofsy = 32768;
+
+ newrect = _newrect;
+
+ for (y = newy; y > 0 ; y--){
+ rect = (unsigned int*) ibuf->zbuf;
+ rect += (ofsy >> 16) * ibuf->x;
+ ofsy += stepy;
+ ofsx = 32768;
+ for (x = newx ; x > 0 ; x--){
+ *newrect++ = rect[ofsx >> 16];
+ ofsx += stepx;
+ }
+ }
+
+ IMB_freezbufImBuf(ibuf);
+ ibuf->mall |= IB_zbuf;
+ ibuf->zbuf = (int*) _newrect;
+ }
+}
+
+struct ImBuf *IMB_scaleImBuf(struct ImBuf * ibuf, short newx, short newy)
+{
+ if (ibuf == 0) return (0);
+ if (ibuf->rect == 0) return (ibuf);
+
+ // scaleup / scaledown functions below change ibuf->x and ibuf->y
+ // so we first scale the Z-buffer (if any)
+ scalefast_Z_ImBuf(ibuf, newx, newy);
+
+ if (newx < ibuf->x) if (newx) scaledownx(ibuf,newx);
+ if (newy < ibuf->y) if (newy) scaledowny(ibuf,newy);
+ if (newx > ibuf->x) if (newx) scaleupx(ibuf,newx);
+ if (newy > ibuf->y) if (newy) scaleupy(ibuf,newy);
+
+ return(ibuf);
+}
+
+
+struct ImBuf *IMB_scalefastImBuf(struct ImBuf *ibuf, short newx, short newy)
+{
+ unsigned int *rect,*_newrect,*newrect;
+ int x,y;
+ int ofsx,ofsy,stepx,stepy;
+
+ if (ibuf == 0) return(0);
+ if (ibuf->rect == 0) return(ibuf);
+
+ if (newx == ibuf->x && newy == ibuf->y) return(ibuf);
+
+ _newrect = malloc(newx * newy * sizeof(int));
+ if (_newrect == 0) return(ibuf);
+
+ newrect = _newrect;
+ stepx = (65536.0 * (ibuf->x - 1.0) / (newx - 1.0)) + 0.5;
+ stepy = (65536.0 * (ibuf->y - 1.0) / (newy - 1.0)) + 0.5;
+ ofsy = 32768;
+
+ for (y = newy; y > 0 ; y--){
+ rect = ibuf->rect;
+ rect += (ofsy >> 16) * ibuf->x;
+ ofsy += stepy;
+ ofsx = 32768;
+ for (x = newx ; x>0 ; x--){
+ *newrect++ = rect[ofsx >> 16];
+ ofsx += stepx;
+ }
+ }
+
+ imb_freerectImBuf(ibuf);
+ ibuf->mall |= IB_rect;
+ ibuf->rect = _newrect;
+
+ scalefast_Z_ImBuf(ibuf, newx, newy);
+
+ ibuf->x = newx;
+ ibuf->y = newy;
+ return(ibuf);
+}
+
+
+static struct ImBuf *generic_fieldscale(struct ImBuf *ibuf, short newx, short newy, struct ImBuf *(*scalefunc)(ImBuf *, short, short) )
+{
+ struct ImBuf *sbuf1, *sbuf2;
+/* extern void rectcpy(); */
+
+ sbuf1 = IMB_allocImBuf(ibuf->x, ibuf->y / 2, ibuf->depth, IB_rect, 0);
+ sbuf2 = IMB_allocImBuf(ibuf->x, ibuf->y / 2, ibuf->depth, IB_rect, 0);
+
+ ibuf->x *= 2;
+ /* more args needed, 0 assumed... (nzc) */
+/* rectop(sbuf1, ibuf, 0, 0, 0, 0, 32767, 32767, rectcpy); */
+/* rectop(sbuf2, ibuf, 0, 0, sbuf2->x, 0, 32767, 32767, rectcpy); */
+ IMB_rectop(sbuf1, ibuf, 0, 0, 0, 0, 32767, 32767, IMB_rectcpy, 0);
+ IMB_rectop(sbuf2, ibuf, 0, 0, sbuf2->x, 0, 32767, 32767, IMB_rectcpy, 0);
+
+ imb_freerectImBuf(ibuf);
+ ibuf->x = newx;
+ ibuf->y = newy;
+ imb_addrectImBuf(ibuf);
+
+ scalefunc(sbuf1, newx, newy / 2);
+ scalefunc(sbuf2, newx, newy / 2);
+
+ ibuf->x *= 2;
+
+ /* more args needed, 0 assumed... (nzc) */
+/* rectop(ibuf, sbuf1, 0, 0, 0, 0, 32767, 32767, rectcpy); */
+/* rectop(ibuf, sbuf2, sbuf2->x, 0, 0, 0, 32767, 32767, rectcpy); */
+ IMB_rectop(ibuf, sbuf1, 0, 0, 0, 0, 32767, 32767, IMB_rectcpy, 0);
+ IMB_rectop(ibuf, sbuf2, sbuf2->x, 0, 0, 0, 32767, 32767, IMB_rectcpy, 0);
+
+ ibuf->x /= 2;
+
+ IMB_freeImBuf(sbuf1);
+ IMB_freeImBuf(sbuf2);
+
+ return(ibuf);
+}
+
+
+struct ImBuf *IMB_scalefastfieldImBuf(struct ImBuf *ibuf,
+ short newx,
+ short newy)
+{
+ return(generic_fieldscale(ibuf, newx, newy, IMB_scalefastImBuf));
+}
+
+struct ImBuf *IMB_scalefieldImBuf(struct ImBuf *ibuf, short newx, short newy)
+{
+ return(generic_fieldscale(ibuf, newx, newy, IMB_scaleImBuf));
+}
diff --git a/source/blender/imbuf/intern/targa.c b/source/blender/imbuf/intern/targa.c
new file mode 100644
index 00000000000..dd1451a939a
--- /dev/null
+++ b/source/blender/imbuf/intern/targa.c
@@ -0,0 +1,632 @@
+/**
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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$
+ */
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#include <io.h>
+#endif
+#include "BLI_blenlib.h"
+
+#include "imbuf.h"
+#include "imbuf_patch.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "IMB_allocimbuf.h"
+#include "IMB_cmap.h"
+#include "IMB_targa.h"
+
+
+/* this one is only def-ed once, strangely... related to GS? */
+#define GSS(x) (((uchar *)(x))[1] << 8 | ((uchar *)(x))[0])
+
+/***/
+
+typedef struct TARGA
+{
+ unsigned char numid;
+ unsigned char maptyp;
+ unsigned char imgtyp;
+ short maporig;
+ short mapsize;
+ unsigned char mapbits;
+ short xorig;
+ short yorig;
+ short xsize;
+ short ysize;
+ unsigned char pixsize;
+ unsigned char imgdes;
+} TARGA;
+
+/***/
+
+static int tga_out1(unsigned int data, FILE *file)
+{
+ uchar *p;
+
+ p = (uchar *) & data;
+ if (putc(p[0],file) == EOF) return(EOF);
+ return (~EOF);
+}
+
+static int tga_out2(unsigned int data, FILE * file)
+{
+ uchar *p;
+
+ p = (uchar *) & data;
+ if (putc(p[0],file) == EOF) return(EOF);
+ if (putc(p[1],file) == EOF) return(EOF);
+ return (~EOF);
+}
+
+
+static int tga_out3(unsigned int data, FILE * file)
+{
+ uchar *p;
+
+ p = (uchar *) & data;
+ if (putc(p[2],file) == EOF) return(EOF);
+ if (putc(p[1],file) == EOF) return(EOF);
+ if (putc(p[0],file) == EOF) return(EOF);
+ return (~EOF);
+}
+
+
+static int tga_out4(unsigned int data, FILE * file)
+{
+ uchar *p;
+
+ p = (uchar *) & data;
+ /* volgorde = bgra */
+ if (putc(p[2],file) == EOF) return(EOF);
+ if (putc(p[1],file) == EOF) return(EOF);
+ if (putc(p[0],file) == EOF) return(EOF);
+ if (putc(p[3],file) == EOF) return(EOF);
+ return (~EOF);
+}
+
+static short makebody_tga(ImBuf * ibuf, FILE * file, int (*out)(unsigned int, FILE*))
+{
+ register int last,this;
+ register int copy, bytes;
+ register unsigned int *rect, *rectstart, *temp;
+ int y;
+
+ for (y = 0; y < ibuf->y; y++) {
+ bytes = ibuf->x - 1;
+ rectstart = rect = ibuf->rect + (y * ibuf->x);
+ last = *rect++;
+ this = *rect++;
+ copy = last^this;
+ while (bytes > 0){
+ if (copy){
+ do{
+ last = this;
+ this = *rect++;
+ if (last == this){
+ if (this == rect[-3]){ /* drie dezelfde? */
+ bytes --; /* bytes goed zetten */
+ break;
+ }
+ }
+ }while (--bytes != 0);
+
+ copy = rect-rectstart;
+ copy --;
+ if (bytes) copy -= 2;
+
+ temp = rect;
+ rect = rectstart;
+
+ while (copy){
+ last = copy;
+ if (copy>=128) last = 128;
+ copy -= last;
+ if (fputc(last-1,file) == EOF) return(0);
+ do{
+ if (out(*rect++,file) == EOF) return(0);
+ }while(--last != 0);
+ }
+ rectstart = rect;
+ rect = temp;
+ last = this;
+
+ copy = FALSE;
+ } else {
+ while (*rect++ == this){ /* zoek naar eerste afwijkende byte */
+ if (--bytes == 0) break; /* of einde regel */
+ }
+ rect --;
+ copy = rect-rectstart;
+ rectstart = rect;
+ bytes --;
+ this = *rect++;
+
+ while (copy){
+ if (copy>128){
+ if (fputc(255,file) == EOF) return(0);
+ copy -= 128;
+ } else {
+ if (copy == 1){
+ if (fputc(0,file) == EOF) return(0);
+ } else if (fputc(127 + copy,file) == EOF) return(0);
+ copy = 0;
+ }
+ if (out(last,file) == EOF) return(0);
+ }
+ copy=TRUE;
+ }
+ }
+ }
+ return (1);
+}
+
+static int dumptarga(struct ImBuf * ibuf, FILE * file)
+{
+ int size;
+ uchar *rect;
+
+ if (ibuf == 0) return (0);
+ if (ibuf->rect == 0) return (0);
+
+ size = ibuf->x * ibuf->y;
+ rect = (uchar *) ibuf->rect;
+
+ if (ibuf->depth <= 8) {
+ while(size > 0){
+ if (putc(*rect, file) == EOF) return (0);
+ size--;
+ rect += 4;
+ }
+ } else if (ibuf->depth <= 16) {
+ while(size > 0){
+ putc(rect[0], file);
+ if (putc(rect[1], file) == EOF) return (0);
+ size--;
+ rect += 4;
+ }
+ } else if (ibuf->depth <= 24) {
+ while(size > 0){
+ putc(rect[2], file);
+ putc(rect[1], file);
+ if (putc(rect[0], file) == EOF) return (0);
+ size--;
+ rect += 4;
+ }
+ } else if (ibuf->depth <= 32) {
+ while(size > 0){
+ putc(rect[2], file);
+ putc(rect[1], file);
+ putc(rect[0], file);
+ if (putc(rect[3], file) == EOF) return (0);
+ size--;
+ rect += 4;
+ }
+ } else return (0);
+
+ return (1);
+}
+
+
+short imb_savetarga(struct ImBuf * ibuf, int file, int flags)
+{
+ char buf[20];
+ FILE *fildes;
+ int i;
+ short ok;
+
+ if (ibuf == 0) return (0);
+ if (ibuf->rect == 0) return (0);
+
+ memset(buf,0,sizeof(buf));
+
+ /* buf[0] = 0; lengte string */
+
+ buf[16] = (ibuf->depth + 0x7 ) & ~0x7;
+ if (ibuf->cmap) {
+ buf[1] = 1;
+ buf[2] = 9;
+ buf[3] = ibuf->mincol & 0xff;
+ buf[4] = ibuf->mincol >> 8;
+ buf[5] = ibuf->maxcol & 0xff;
+ buf[6] = ibuf->maxcol >> 8;
+ buf[7] = 24;
+ if ((flags & IB_ttob) == 0) {
+ IMB_flipy(ibuf);
+ buf[17] = 0x20;
+ }
+ } else if (ibuf->depth > 8 ){
+ buf[2] = 10;
+ } else{
+ buf[2] = 11;
+ }
+
+ if (ibuf->ftype == RAWTGA) buf[2] &= ~8;
+
+ buf[8] = ibuf->xorig & 0xff;
+ buf[9] = ibuf->xorig >> 8;
+ buf[10] = ibuf->yorig & 0xff;
+ buf[11] = ibuf->yorig >> 8;
+
+ buf[12] = ibuf->x & 0xff;
+ buf[13] = ibuf->x >> 8;
+ buf[14] = ibuf->y & 0xff;
+ buf[15] = ibuf->y >> 8;
+
+ if (flags & IB_ttob) buf[17] ^= 0x20;
+
+ if (write(file, buf, 18) != 18) return (0);
+ if (ibuf->cmap){
+ for (i = 0 ; i<ibuf->maxcol ; i++){
+ if (write(file,((uchar *)(ibuf->cmap + i)) + 1,3) != 3) return (0);
+ }
+ }
+ fildes = fdopen(file,"ab");
+
+ if (ibuf->cmap && (flags & IB_cmap) == 0) IMB_converttocmap(ibuf);
+
+ if (ibuf->ftype == RAWTGA) {
+ ok = dumptarga(ibuf, fildes);
+ } else {
+ switch((ibuf->depth + 7) >> 3){
+ case 1:
+ ok = makebody_tga(ibuf, fildes, tga_out1);
+ break;
+ case 2:
+ ok = makebody_tga(ibuf, fildes, tga_out2);
+ break;
+ case 3:
+ ok = makebody_tga(ibuf, fildes, tga_out3);
+ break;
+ case 4:
+ ok = makebody_tga(ibuf, fildes, tga_out4);
+ break;
+ }
+ }
+
+ fclose(fildes);
+ return (ok);
+}
+
+
+static int checktarga(TARGA *tga, unsigned char *mem)
+{
+ tga->numid = mem[0];
+ tga->maptyp = mem[1];
+ tga->imgtyp = mem[2];
+
+ tga->maporig = GSS(mem+3);
+ tga->mapsize = GSS(mem+5);
+ tga->mapbits = mem[7];
+ tga->xorig = GSS(mem+8);
+ tga->yorig = GSS(mem+10);
+ tga->xsize = GSS(mem+12);
+ tga->ysize = GSS(mem+14);
+ tga->pixsize = mem[16];
+ tga->imgdes = mem[17];
+
+ if (tga->maptyp > 1) return(0);
+ switch (tga->imgtyp){
+ case 1: /* raw cmap */
+ case 2: /* raw rgb */
+ case 3: /* raw b&w */
+ case 9: /* cmap */
+ case 10: /* rgb */
+ case 11: /* b&w */
+ break;
+ default:
+ return(0);
+ }
+ if (tga->mapsize && tga->mapbits > 32) return(0);
+ if (tga->xsize <= 0 || tga->xsize >= 4096) return(0);
+ if (tga->ysize <= 0 || tga->ysize >= 4096) return(0);
+ if (tga->pixsize > 32) return(0);
+ if (tga->pixsize == 0) return(0);
+ return(1);
+}
+
+int imb_is_a_targa(void *buf) {
+ TARGA tga;
+
+ return checktarga(&tga, buf);
+}
+
+static void decodetarga(struct ImBuf *ibuf, unsigned char *mem, int psize)
+/* struct ImBuf *ibuf; */
+/* uchar *mem; */
+/* int psize; */
+{
+ int count, col, size;
+ unsigned int *rect;
+ uchar * cp = (uchar *) &col;
+
+ if (ibuf == 0) return;
+ if (ibuf->rect == 0) return;
+
+ size = ibuf->x * ibuf->y;
+ rect = ibuf->rect;
+
+ /* alpha zetten */
+ cp[0] = 0xff;
+ cp[1] = cp[2] = 0;
+
+ while(size > 0){
+ count = *mem++;
+ if (count >= 128) {
+ /*if (count == 128) printf("TARGA: 128 in file !\n");*/
+ count -= 127;
+
+ if (psize & 2){
+ if (psize & 1){
+ /* volgorde = bgra */
+ cp[0] = mem[3];
+ cp[1] = mem[0];
+ cp[2] = mem[1];
+ cp[3] = mem[2];
+ /*col = (mem[3] << 24) + (mem[0] << 16) + (mem[1] << 8) + mem[2];*/
+ mem += 4;
+ } else{
+ cp[1] = mem[0];
+ cp[2] = mem[1];
+ cp[3] = mem[2];
+ /*col = 0xff000000 + (mem[0] << 16) + (mem[1] << 8) + mem[2];*/
+ mem += 3;
+ }
+ } else{
+ if (psize & 1){
+ col = (mem[0] << 8) + mem[1];
+ mem += 2;
+ } else{
+ col = *mem++;
+ }
+ }
+
+ size -= count;
+ if (size >= 0) {
+ while (count > 0) {
+ *rect++ = col;
+ count--;
+ }
+ }
+ } else{
+ count ++;
+ size -= count;
+ if (size >= 0) {
+ while (count > 0){
+ if (psize & 2){
+ if (psize & 1){
+ /* volgorde = bgra */
+ cp[0] = mem[3];
+ cp[1] = mem[0];
+ cp[2] = mem[1];
+ cp[3] = mem[2];
+ /*col = (mem[3] << 24) + (mem[0] << 16) + (mem[1] << 8) + mem[2];*/
+ mem += 4;
+ } else{
+ cp[1] = mem[0];
+ cp[2] = mem[1];
+ cp[3] = mem[2];
+ /*col = 0xff000000 + (mem[0] << 16) + (mem[1] << 8) + mem[2];*/
+ mem += 3;
+ }
+ } else{
+ if (psize & 1){
+ col = (mem[0] << 8) + mem[1];
+ mem += 2;
+ } else{
+ col = *mem++;
+ }
+ }
+ *rect++ = col;
+ count --;
+ }
+ }
+ }
+ }
+ if (size) printf("decodetarga: count would overwrite %d pixels\n", -size);
+}
+
+static void ldtarga(struct ImBuf * ibuf,unsigned char * mem, int psize)
+{
+ int col,size;
+ unsigned int *rect;
+ uchar * cp = (uchar *) &col;
+
+ if (ibuf == 0) return;
+ if (ibuf->rect == 0) return;
+
+ size = ibuf->x * ibuf->y;
+ rect = ibuf->rect;
+
+ /* alpha zetten */
+ cp[0] = 0xff;
+ cp[1] = cp[2] = 0;
+
+ while(size > 0){
+ if (psize & 2){
+ if (psize & 1){
+ /* volgorde = bgra */
+ cp[0] = mem[3];
+ cp[1] = mem[0];
+ cp[2] = mem[1];
+ cp[3] = mem[2];
+ /*col = (mem[3] << 24) + (mem[0] << 16) + (mem[1] << 8) + mem[2];*/
+ mem += 4;
+ } else{
+ /* zet alpha bij 24 bits kleuren */
+ cp[1] = mem[0];
+ cp[2] = mem[1];
+ cp[3] = mem[2];
+ /*col = 0xff000000 + (mem[0] << 16) + (mem[1] << 8) + mem[2];*/
+ mem += 3;
+ }
+ } else{
+ if (psize & 1){
+ col = (mem[1] << 8) + mem[0];
+ mem += 2;
+ } else{
+ col = *mem++;
+ }
+ }
+ *rect++ = col;
+ size--;
+ }
+}
+
+
+struct ImBuf *imb_loadtarga(unsigned char *mem, int flags)
+{
+ TARGA tga;
+ struct ImBuf * ibuf;
+ int col, count, size;
+ unsigned int * rect;
+ uchar * cp = (uchar *) &col;
+
+ if (checktarga(&tga,mem) == 0) return(0);
+
+ if (flags & IB_test) ibuf = IMB_allocImBuf(tga.xsize,tga.ysize,tga.pixsize,0,0);
+ else ibuf = IMB_allocImBuf(tga.xsize,tga.ysize,(tga.pixsize + 0x7) & ~0x7,1,0);
+
+ if (ibuf == 0) return(0);
+ ibuf->ftype = TGA;
+ ibuf->xorig = tga.xorig;
+ ibuf->yorig = tga.yorig;
+ mem = mem + 18 + tga.numid;
+
+ cp[0] = 0xff;
+ cp[1] = cp[2] = 0;
+
+ if (tga.mapsize){
+ ibuf->mincol = tga.maporig;
+ ibuf->maxcol = tga.mapsize;
+ imb_addcmapImBuf(ibuf);
+ ibuf->cbits = 8;
+ for (count = 0 ; count < ibuf->maxcol ; count ++) {
+ switch (tga.mapbits >> 3) {
+ case 4:
+ cp[0] = mem[3];
+ cp[1] = mem[0];
+ cp[2] = mem[1];
+ cp[3] = mem[2];
+ mem += 4;
+ break;
+ case 3:
+ cp[1] = mem[0];
+ cp[2] = mem[1];
+ cp[3] = mem[2];
+ mem += 3;
+ break;
+ case 2:
+ col = (mem[1] << 8) + mem[0];
+ mem += 2;
+ break;
+ case 1:
+ col = *mem++;
+ break;
+ }
+ ibuf->cmap[count] = col;
+ }
+
+ size = 0;
+ for (col = ibuf->maxcol - 1; col > 0; col >>= 1) size++;
+ ibuf->depth = size;
+
+ if (tga.mapbits != 32) { /* alpha bits zetten */
+ ibuf->cmap[0] &= BIG_LONG(0x00ffffff);
+ }
+ }
+
+ if (flags & IB_test) return (ibuf);
+
+ if (tga.imgtyp != 1 && tga.imgtyp != 9) IMB_freecmapImBuf(ibuf); /* kan soms gebeuren (beuh) */
+
+ switch(tga.imgtyp){
+ case 1:
+ case 2:
+ case 3:
+ if (tga.pixsize <= 8) ldtarga(ibuf,mem,0);
+ else if (tga.pixsize <= 16) ldtarga(ibuf,mem,1);
+ else if (tga.pixsize <= 24) ldtarga(ibuf,mem,2);
+ else if (tga.pixsize <= 32) ldtarga(ibuf,mem,3);
+ break;
+ case 9:
+ case 10:
+ case 11:
+ if (tga.pixsize <= 8) decodetarga(ibuf,mem,0);
+ else if (tga.pixsize <= 16) decodetarga(ibuf,mem,1);
+ else if (tga.pixsize <= 24) decodetarga(ibuf,mem,2);
+ else if (tga.pixsize <= 32) decodetarga(ibuf,mem,3);
+ break;
+ }
+
+ if (ibuf->cmap){
+ if ((flags & IB_cmap) == 0) IMB_applycmap(ibuf);
+ }
+
+ if (tga.pixsize == 16 && ibuf->cmap == 0){
+ rect = ibuf->rect;
+ for (size = ibuf->x * ibuf->y; size > 0; size --){
+ col = *rect;
+ col = ((col & 0x1f) << 19) + ((col & 0x3e0) << 6) + ((col & 0x7c00) >> 7) ;
+ col += (col & 0xe0e0e0) >> 5;
+ *rect++ = col + 0xff000000;
+ }
+ ibuf->depth = 24;
+ }
+
+ if (tga.imgtyp == 3 || tga.imgtyp == 11){
+ uchar *crect;
+ unsigned int *lrect, col;
+
+ crect = (uchar *) ibuf->rect;
+ lrect = (unsigned int *) ibuf->rect;
+
+ for (size = ibuf->x * ibuf->y; size > 0; size --){
+ col = *lrect++;
+
+ crect[0] = 255;
+ crect[1] = crect[2] = crect[3] = col;
+ crect += 4;
+ }
+ }
+
+ if (flags & IB_ttob) tga.imgdes ^= 0x20;
+ if (tga.imgdes & 0x20) IMB_flipy(ibuf);
+
+ if (ibuf) {
+ if (ibuf->rect && (flags & IB_cmap)==0)
+ IMB_convert_rgba_to_abgr((ibuf->x+ibuf->skipx)*ibuf->y, ibuf->rect);
+ }
+
+ return(ibuf);
+}
diff --git a/source/blender/imbuf/intern/util.c b/source/blender/imbuf/intern/util.c
new file mode 100644
index 00000000000..52a29217bef
--- /dev/null
+++ b/source/blender/imbuf/intern/util.c
@@ -0,0 +1,90 @@
+/**
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * util.c
+ *
+ * $Id$
+ */
+
+#include "BLI_blenlib.h"
+
+#include "imbuf.h"
+#include "imbuf_patch.h"
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "IMB_targa.h"
+#include "IMB_png.h"
+
+/* from misc_util: flip the bytes from x */
+#define GS(x) (((unsigned char *)(x))[0] << 8 | ((unsigned char *)(x))[1])
+
+/* this one is only def-ed once, strangely... */
+#define GSS(x) (((uchar *)(x))[1] << 8 | ((uchar *)(x))[0])
+
+int IMB_ispic(char *name)
+{
+ struct stat st;
+ int fp, buf[10];
+ int ofs = 0;
+
+ if (ib_stat(name,&st) == -1) return(0);
+ if (((st.st_mode) & S_IFMT) == S_IFREG){
+ if ((fp = open(name,O_BINARY|O_RDONLY)) >= 0){
+ if (read(fp,buf,32)==32){
+ close(fp);
+ if (buf[ofs] == CAT) ofs += 3;
+ if (buf[ofs] == FORM){
+ if (buf[ofs + 2] == ILBM) return(AMI);
+ if (buf[ofs + 2] == ANIM){
+ if (buf[ofs + 3] == FORM){
+ return(ANIM);
+ }else{
+ return(Anim);
+ }
+ }
+ } else {
+ if (GS(buf) == IMAGIC) return(IMAGIC);
+ if (GSS(buf) == IMAGIC) return(IMAGIC);
+ if ((BIG_LONG(buf[0]) & 0xfffffff0) == 0xffd8ffe0) return(JPG);
+
+ /* at windows there are ".ffl" files with the same magic numnber...
+ besides that, tim images are not really important anymore! */
+ /* if ((BIG_LONG(buf[0]) == 0x10000000) && ((BIG_LONG(buf[1]) & 0xf0ffffff) == 0)) return(TIM); */
+
+ }
+ if (imb_is_a_png(buf)) return(PNG);
+ if (imb_is_a_targa(buf)) return(TGA);
+ return(FALSE);
+ }
+ close(fp);
+ }
+ }
+ return(FALSE);
+}
diff --git a/source/blender/imbuf/intern/writeimage.c b/source/blender/imbuf/intern/writeimage.c
new file mode 100644
index 00000000000..e4d24097760
--- /dev/null
+++ b/source/blender/imbuf/intern/writeimage.c
@@ -0,0 +1,145 @@
+/**
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * writeimage.c
+ *
+ * $Id$
+ */
+
+#include "BLI_blenlib.h"
+
+#include "imbuf.h"
+#include "imbuf_patch.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "IMB_allocimbuf.h"
+
+#include "IMB_targa.h"
+#include "IMB_jpeg.h"
+#include "IMB_iris.h"
+#include "IMB_ham.h"
+#include "IMB_hamx.h"
+#include "IMB_amiga.h"
+
+#include "IMB_iff.h"
+#include "IMB_bitplanes.h"
+#include "IMB_divers.h"
+
+
+short (*IMB_fp_png_encode)(struct ImBuf *ibuf, int file, int flags) = 0;
+
+short IMB_saveiff(struct ImBuf *ibuf,char *naam,int flags)
+{
+ short ok=TRUE,delpl=FALSE;
+ int file = -1;
+
+ if (ibuf==0) return (FALSE);
+ ibuf->flags = flags;
+
+ if (IS_jpg(ibuf)) {
+ if (imb_save_jpeg(naam, ibuf, flags)) return (0);
+ else return (TRUE);
+ }
+ file = open(naam, O_BINARY | O_RDWR | O_CREAT | O_TRUNC, 0666);
+ if (file < 0) return (FALSE);
+
+ if (flags & IB_rect){
+ if (ibuf->cmap){
+ imb_checkncols(ibuf);
+ }
+ }
+
+ if (IS_png(ibuf) && IMB_fp_png_encode) {
+ ok = IMB_fp_png_encode(ibuf,file,flags);
+ if (ok) {
+ close (file);
+ return (ok);
+ }
+ }
+
+ if (IS_tga(ibuf) || IS_png(ibuf)) {
+ ok = imb_savetarga(ibuf,file,flags);
+ if (ok) {
+ close (file);
+ return (ok);
+ }
+ }
+
+ if (IS_iris(ibuf)) {
+ ok = imb_saveiris(ibuf,file,flags);
+ if (ok) {
+ close (file);
+ return (ok);
+ }
+ }
+
+ if (ok) ok = imb_start_iff(ibuf,file);
+
+ if (IS_amiga(ibuf)){
+ IMB_flipy(ibuf);
+ if (flags & IB_rect){
+ if ((flags & IB_cmap) == 0) {
+ if (IS_ham(ibuf)){
+ if (ok) ok = imb_converttoham(ibuf);
+ }else if (ibuf->cmap){
+ if (ok) ok = IMB_converttocmap(ibuf);
+ }
+ }
+ if (ok){
+ if (ibuf->planes==0){
+ delpl=TRUE;
+ ok=imb_addplanesImBuf(ibuf);
+ }
+ imb_longtobp(ibuf);
+ }
+ }
+
+ if (flags & IB_vert){
+ if (ok) ok = imb_encodebodyv(ibuf,file);
+ }
+ else{
+ if (ok) ok = imb_encodebodyh(ibuf,file);
+ }
+ if (ok) ok = imb_update_iff(file,BODY);
+ }else if (IS_anim(ibuf)) {
+ if (ok) ok = imb_enc_anim(ibuf, file);
+ if (ok) ok = imb_update_iff(file, BODY);
+ }
+ close(file);
+
+ if (ok==FALSE) {
+ fprintf(stderr,"Couldn't save picture.\n");
+ }
+ if (delpl) imb_freeplanesImBuf(ibuf);
+
+ return (ok);
+}
+
diff --git a/source/blender/img/IMG_Api.h b/source/blender/img/IMG_Api.h
new file mode 100644
index 00000000000..42b0d5e3a74
--- /dev/null
+++ b/source/blender/img/IMG_Api.h
@@ -0,0 +1,63 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 7, 2001
+ */
+#ifndef _H_IMG_API
+#define _H_IMG_API
+
+#include <stddef.h>
+
+
+typedef void* IMG_BrushPtr;
+typedef void* IMG_CanvasPtr;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+extern IMG_BrushPtr IMG_BrushCreate(unsigned int width, unsigned int height, float red, float green, float blue, float alpha);
+extern void IMG_BrushDispose(IMG_BrushPtr brush);
+
+extern IMG_CanvasPtr IMG_CanvasCreate(unsigned int width, unsigned int height);
+extern IMG_CanvasPtr IMG_CanvasCreateFromPtr(void* imagePtr, unsigned int width, unsigned int height, size_t rowBytes);
+extern void IMG_CanvasDispose(IMG_CanvasPtr canvas);
+extern void IMG_CanvasDraw(IMG_CanvasPtr canvas, IMG_BrushPtr brush, unsigned int x, unsigned int y);
+extern void IMG_CanvasDrawUV(IMG_CanvasPtr canvas, IMG_BrushPtr brush, float u, float v);
+extern void IMG_CanvasDrawLine(IMG_CanvasPtr canvas, IMG_BrushPtr brush, unsigned int xStart, unsigned int yStart, unsigned int xEns, unsigned int yEnd);
+extern void IMG_CanvasDrawLineUV(IMG_CanvasPtr canvas, IMG_BrushPtr brush, float uStart, float vStart, float uEnd, float vEnd);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _H_IMG_API
diff --git a/source/blender/img/Makefile b/source/blender/img/Makefile
new file mode 100644
index 00000000000..2e1172d4635
--- /dev/null
+++ b/source/blender/img/Makefile
@@ -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 *****
+#
+# Bounces make to subdirectories.
+
+SOURCEDIR = source/blender/img
+DIRS = intern
+
+include nan_subdirs.mk
diff --git a/source/blender/img/intern/IMG_Api.cpp b/source/blender/img/intern/IMG_Api.cpp
new file mode 100644
index 00000000000..1be8b294c28
--- /dev/null
+++ b/source/blender/img/intern/IMG_Api.cpp
@@ -0,0 +1,121 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "../IMG_Api.h"
+
+#include "IMG_BrushRGBA32.h"
+#include "IMG_CanvasRGBA32.h"
+
+
+IMG_BrushPtr IMG_BrushCreate(unsigned int w, unsigned int h, float r, float g, float b, float a)
+{
+ IMG_BrushPtr brush = 0;
+ try {
+ IMG_ColorRGB c (r, g, b);
+ brush = new IMG_BrushRGBA32 (w, h, c, a);
+ }
+ catch (...) {
+ brush = 0;
+ }
+ return brush;
+}
+
+
+void IMG_BrushDispose(IMG_BrushPtr brush)
+{
+ if (brush) {
+ delete ((IMG_BrushRGBA32*)brush);
+ brush = 0;
+ }
+}
+
+
+IMG_CanvasPtr IMG_CanvasCreate(unsigned int w, unsigned int h)
+{
+ IMG_CanvasPtr canvas = 0;
+ try {
+ canvas = new IMG_CanvasRGBA32 (w, h);
+ }
+ catch (...) {
+ canvas = 0;
+ }
+ return canvas;
+}
+
+
+IMG_CanvasPtr IMG_CanvasCreateFromPtr(void* imagePtr, unsigned int w, unsigned int h, size_t rowBytes)
+{
+ IMG_CanvasPtr canvas = 0;
+ try {
+ canvas = new IMG_CanvasRGBA32 (imagePtr, w, h, rowBytes);
+ }
+ catch (...) {
+ canvas = 0;
+ }
+ return canvas;
+}
+
+void IMG_CanvasDispose(IMG_CanvasPtr canvas)
+{
+ if (canvas) {
+ delete ((IMG_CanvasRGBA32*)canvas);
+ canvas = 0;
+ }
+}
+
+#if 0
+void IMG_CanvasDraw(IMG_CanvasPtr canvas, IMG_BrushPtr brush, unsigned int x, unsigned int y)
+{
+ if (!(canvas && brush)) return;
+ ((IMG_CanvasRGBA32*)canvas)->blendPixmap((TUns32)x, (TUns32)y, *((IMG_BrushRGBA32*)brush));
+}
+
+
+void IMG_CanvasDrawUV(IMG_CanvasPtr canvas, IMG_BrushPtr brush, float u, float v)
+{
+ if (!(canvas && brush)) return;
+ ((IMG_CanvasRGBA32*)canvas)->blendPixmap(u, v, *((IMG_BrushRGBA32*)brush));
+}
+#endif
+
+
+void IMG_CanvasDrawLine(IMG_CanvasPtr canvas, IMG_BrushPtr brush, unsigned int xStart, unsigned int yStart, unsigned int xEnd, unsigned int yEnd)
+{
+ if (!(canvas && brush)) return;
+ ((IMG_CanvasRGBA32*)canvas)->blendPixmap((TUns32)xStart, (TUns32)yStart, (TUns32)xEnd, (TUns32)yEnd, *((IMG_BrushRGBA32*)brush));
+}
+
+
+void IMG_CanvasDrawLineUV(IMG_CanvasPtr canvas, IMG_BrushPtr brush, float uStart, float vStart, float uEnd, float vEnd)
+{
+ if (!(canvas && brush)) return;
+ ((IMG_CanvasRGBA32*)canvas)->blendPixmap(uStart, vStart, uEnd, vEnd, *((IMG_BrushRGBA32*)brush));
+}
diff --git a/source/blender/img/intern/IMG_BrushRGBA32.cpp b/source/blender/img/intern/IMG_BrushRGBA32.cpp
new file mode 100644
index 00000000000..7c78e98a8cf
--- /dev/null
+++ b/source/blender/img/intern/IMG_BrushRGBA32.cpp
@@ -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 *****
+ */
+
+#include "IMG_BrushRGBA32.h"
+
+
+#include <math.h>
+
+
+IMG_BrushRGBA32::IMG_BrushRGBA32(TUns32 w, TUns32 h, const IMG_ColorRGB& c, float a)
+ : IMG_PixmapRGBA32(w, h), m_color(c), m_alpha(a)
+{
+ m_ro = w < h ? w/2 : h/2;
+ m_ri = m_ro >> 1;
+ updateImage();
+}
+
+
+void IMG_BrushRGBA32::setColor(const IMG_ColorRGB& c)
+{
+ m_color = c;
+ updateImage();
+}
+
+
+void IMG_BrushRGBA32::setTransparency(float a)
+{
+ m_alpha = a;
+ if (m_alpha > 1.f) m_alpha = 1.f;
+ if (m_alpha < 0.f) m_alpha = 0.f;
+ updateImage();
+}
+
+
+void IMG_BrushRGBA32::setRadii(TUns32 rI, TUns32 rO)
+{
+ if ((rI < 2) || (rO < 2)) return;
+ m_ri = rI;
+ m_ro = rO;
+
+ TUns32 w_2 = m_width >> 1;
+ TUns32 h_2 = m_height >> 1;
+
+ /*
+ * Make the brush size smaller than half of the minimum
+ * width or height of the pixmap. Make sure that inner
+ * radius <= outer radius.
+ */
+ if (m_ro > w_2) m_ro = w_2;
+ if (m_ro > h_2) m_ro = h_2;
+ if (m_ri > m_ro) m_ri = m_ro;
+
+ updateImage();
+}
+
+
+void IMG_BrushRGBA32::updateImage()
+{
+ TUns32 cx = m_width >> 1;
+ TUns32 cy = m_height >> 1;
+
+ // Prepare pixel values for this pixmap
+ IMG_ColorRGBA c (m_color.m_r, m_color.m_g, m_color.m_b, 0.f);
+ TPixelRGBA32 pOut = getPixelValue(c);
+ c.m_a = m_alpha;
+ TPixelRGBA32 pIn = getPixelValue(c);
+ TPixelRGBA32 p = getPixelValue(c);
+ TUns8* pa = & (((TUns8*)&p)[bi_a]);
+
+ // Set the pixels in the destination rectangle
+ for (TUns32 y = 0; y < m_height; y++) {
+ // Park pixel pointer at the start pixels
+ TPixelPtr desPtr = getPixelPtr(0, y);
+ for (TUns32 x = 0; x < m_width; x++) {
+ // Calculate the distance between current pixel and center
+ float dX = (float)((TInt32)x) - ((TInt32)cx);
+ float dY = (float)((TInt32)y) - ((TInt32)cy);
+ float d = (float) ::sqrt(dX*dX + dY*dY);
+ float a;
+
+ if (d <= m_ri) {
+ *desPtr = pIn;
+ }
+ else if ((d < m_ro) && (m_ri < m_ro)) {
+ // Calculate alpha, linear
+ a = (d - m_ri) / (m_ro - m_ri);
+ // Now: 0 <= a <= 1
+ //a = m_alpha + a * (1.f - m_alpha);
+ a = (1.f - a) * m_alpha;
+ // Now: m_alpha <= a <= 1
+#if 0
+ a = (float)::pow(a, 0.2);
+#endif
+ // Store pixel
+ *pa = (TUns8)(a * ((float)0xFF));
+ *desPtr = p;
+ }
+ else {
+ *desPtr = pOut;
+ }
+ desPtr++;
+ }
+ }
+}
diff --git a/source/blender/img/intern/IMG_BrushRGBA32.h b/source/blender/img/intern/IMG_BrushRGBA32.h
new file mode 100644
index 00000000000..4cb8b3b9617
--- /dev/null
+++ b/source/blender/img/intern/IMG_BrushRGBA32.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 _H_IMG_BrushRGBA32
+#define _H_IMG_BrushRGBA32
+
+#include "IMG_PixmapRGBA32.h"
+
+
+/**
+ * A brush used for drawing in pixmaps.
+ * The brush is a pixmap as well.
+ * Drawing can be implemented by blending the brush into the pixmap.
+ *
+ * @author Maarten Gribnau
+ * @date March 7, 2001
+ * @todo Check the algorithm
+ */
+
+class IMG_BrushRGBA32 : public IMG_PixmapRGBA32 {
+public:
+ /**
+ * Constructs a brush image with the dimensions and color given.
+ * @param w width of the brush image
+ * @param h height of the brush image
+ * @param c color of the brush
+ * @param a transparency in the center of the brush
+ */
+ IMG_BrushRGBA32(TUns32 w, TUns32 h, const IMG_ColorRGB& c, float a = 0.8f);
+
+ /**
+ * Sets the color of the brush.
+ * @param c color of the brush
+ */
+ virtual void setColor(const IMG_ColorRGB& c);
+
+ /**
+ * Returns the color of the brush.
+ * @param c color of the brush
+ */
+ inline virtual void getColor(IMG_ColorRGB& c) const;
+
+ /**
+ * Sets the transparency of the brush.
+ * @param a transparency of the brush
+ */
+ virtual void setTransparency(float a);
+
+ /**
+ * Returns the transparency of the brush.
+ * @param a transparency of the brush
+ */
+ inline virtual float getTransparency() const;
+
+ /**
+ * Sets the shape of the brush from two radii (inner and outer).
+ * This creates a brush with alpha==0 inside the inner radius
+ * and gradually fades to alpha==1 at the outer radius.
+ * Inner radius should be smaller or equal to the outer radius.
+ * If not, the outer radius is made equal to the inner radius.
+ * If the either radius is larger than the bounds of the brush,
+ * they are clipped.
+ * @param rI inner radius
+ * @param rO outer radius
+ */
+ virtual void setRadii(TUns32 rI, TUns32 rO);
+
+ /**
+ * Returns the radii that determine the shape of the brush.
+ * @param rI inner radius
+ * @param rO outer radius
+ */
+ inline virtual void setRadii(TUns32& rI, TUns32& rO) const;
+
+protected:
+ /**
+ * Updates the image of this brush.
+ * The image is created using the current color, transparency and shape radii.
+ */
+ virtual void updateImage();
+
+ IMG_ColorRGB m_color; /** The color of the brush */
+ float m_alpha; /** The transparency of the brush */
+ TUns32 m_ri; /** The inner radius of the brush */
+ TUns32 m_ro; /** The outer radius of the brush */
+};
+
+
+inline void IMG_BrushRGBA32::setRadii(TUns32& rI, TUns32& rO) const
+{
+ rI = m_ri;
+ rO = m_ro;
+}
+
+inline float IMG_BrushRGBA32::getTransparency() const
+{
+ return m_alpha;
+}
+
+inline void IMG_BrushRGBA32::getColor(IMG_ColorRGB& c) const
+{
+ c = m_color;
+}
+
+
+#endif // _H_IMG_BrushRGBA32
diff --git a/source/blender/img/intern/IMG_CanvasRGBA32.cpp b/source/blender/img/intern/IMG_CanvasRGBA32.cpp
new file mode 100644
index 00000000000..5358265337d
--- /dev/null
+++ b/source/blender/img/intern/IMG_CanvasRGBA32.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 *****
+ */
+
+#include "IMG_CanvasRGBA32.h"
+
+
+
+IMG_CanvasRGBA32::IMG_CanvasRGBA32(TUns32 width, TUns32 height)
+ : IMG_PixmapRGBA32(width, height)
+{
+}
+
+IMG_CanvasRGBA32::IMG_CanvasRGBA32(void* image, TUns32 width, TUns32 height, TUns32 rowBytes)
+ : IMG_PixmapRGBA32(image, width, height, rowBytes)
+{
+}
+
+
+void IMG_CanvasRGBA32::blendPixmap(
+ TUns32 xStart, TUns32 yStart, TUns32 xEnd, TUns32 yEnd,
+ const IMG_PixmapRGBA32& pixmap)
+{
+ // Determine visibility of the line
+ IMG_Line l (xStart, yStart, xEnd, yEnd); // Line used for blending
+ IMG_Rect bnds (0, 0, m_width, m_height); // Bounds of this pixmap
+ TVisibility v = bnds.getVisibility(l);
+ if (v == kNotVisible) return;
+ if (v == kPartiallyVisible) {
+ bnds.clip(l);
+ }
+
+ float numSteps = (((float)l.getLength()) / ((float)pixmap.getWidth() / 4));
+ //numSteps *= 4;
+ numSteps = numSteps ? numSteps : 1;
+ float step = 0.f, stepSize = 1.f / ((float)numSteps);
+ TInt32 x, y;
+ for (TUns32 s = 0; s < numSteps; s++) {
+ l.getPoint(step, x, y);
+ IMG_PixmapRGBA32::blendPixmap((TUns32)x, (TUns32)y, pixmap);
+ step += stepSize;
+ }
+}
+
+
+void IMG_CanvasRGBA32::blendPixmap(
+ float uStart, float vStart, float uEnd, float vEnd,
+ const IMG_PixmapRGBA32& pixmap)
+{
+ TUns32 xStart, yStart, xEnd, yEnd;
+ getPixelAddress(uStart, vStart, xStart, yStart);
+ getPixelAddress(uEnd, vEnd, xEnd, yEnd);
+ blendPixmap(xStart, yStart, xEnd, yEnd, pixmap);
+}
+
diff --git a/source/blender/img/intern/IMG_CanvasRGBA32.h b/source/blender/img/intern/IMG_CanvasRGBA32.h
new file mode 100644
index 00000000000..4a59693cfde
--- /dev/null
+++ b/source/blender/img/intern/IMG_CanvasRGBA32.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 *****
+ * @author Maarten Gribnau
+ * @date March 6, 2001
+ */
+
+#ifndef _H_IMG_CanvasRGBA32
+#define _H_IMG_CanvasRGBA32
+
+#include "IMG_PixmapRGBA32.h"
+#include "IMG_BrushRGBA32.h"
+
+/**
+ * A IMG_PixmapRGBA32 pixmap that allows for drawing with a IMG_BrushRGBA32.
+ * @author Maarten Gribnau
+ * @date March 6, 2001
+ */
+
+class IMG_CanvasRGBA32 : public IMG_PixmapRGBA32 {
+public:
+ /**
+ * Constructor.
+ * @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_CanvasRGBA32(TUns32 width, TUns32 height);
+
+ /**
+ * Constructor.
+ * 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_CanvasRGBA32(void* image, TUns32 width, TUns32 height, TUns32 rowBytes);
+
+ /**
+ * Blends a pixmap into this pixmap over a line.
+ * Repeatedly pastes the given pixmap centered at the given line into this pixmap.
+ * The alpha information in the given image is used to blend.
+ * @todo implement wrapping modes when the pixmap does not fit within the bounds.
+ * @todo update the drawing algorithm.
+ * @param x x-coordinate of the center location of the image.
+ * @param y y-coordinate of the center location of the image.
+ * @param pixmap the pixmap to blend
+ */
+ virtual void blendPixmap(TUns32 xStart, TUns32 yStart, TUns32 xEnd, TUns32 yEnd, const IMG_PixmapRGBA32& pixmap);
+
+ /**
+ * Blends a pixmap into this pixmap over a line in (u,v) coordinates.
+ * Pastes the given pixmap centered at the given line into this pixmap.
+ * The alpha information in the given image is used to blend.
+ * @see IMG_PixmapRGBA32::blendPixmap(TUns32 xStart, TUns32 yStart, TUns32 yStart, TUns32 yEnd, const IMG_PixmapRGBA32& pixmap)
+ * @todo implement wrapping modes when the pixmap does not fit within the bounds.
+ * @param u u-coordinate of the center location of the image.
+ * @param v v-coordinate of the center location of the image.
+ * @param pixmap the pixmap to blend
+ */
+ virtual void blendPixmap(float uStart, float vStart, float uEnd, float vEnd, const IMG_PixmapRGBA32& pixmap);
+};
+
+
+#endif // _H_IMG_CanvasRGBA32
diff --git a/source/blender/img/intern/IMG_Color.h b/source/blender/img/intern/IMG_Color.h
new file mode 100644
index 00000000000..540907c66e9
--- /dev/null
+++ b/source/blender/img/intern/IMG_Color.h
@@ -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 *****
+ * @author Maarten Gribnau
+ * @date March 7, 2001
+ */
+
+#ifndef _H_IMG_Color
+#define _H_IMG_Color
+
+class IMG_ColorRGBA;
+
+/**
+ * Implements a color with red, green and blue components.
+ * Components are stored as floats.
+ * @author Maarten Gribnau
+ * @date March 7, 2001
+ */
+
+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;
+};
+
+
+/**
+ * Implements a color with red, green, blue and alpha components.
+ * Components are stored as floats.
+ * @author Maarten Gribnau
+ * @date March 6, 2001
+ */
+
+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
diff --git a/source/blender/img/intern/IMG_Line.cpp b/source/blender/img/intern/IMG_Line.cpp
new file mode 100644
index 00000000000..2b864a63705
--- /dev/null
+++ b/source/blender/img/intern/IMG_Line.cpp
@@ -0,0 +1,33 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "IMG_Line.h"
+
diff --git a/source/blender/img/intern/IMG_Line.h b/source/blender/img/intern/IMG_Line.h
new file mode 100644
index 00000000000..27243226042
--- /dev/null
+++ b/source/blender/img/intern/IMG_Line.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 *****
+ * @author Maarten Gribnau
+ * @date March 12, 2001
+ */
+
+#ifndef _H_IMG_Line
+#define _H_IMG_Line
+
+#include "IMG_Types.h"
+#include <math.h>
+
+/**
+ * A line from a start to an end point.
+ * Used for drawing lines in images.
+ * @author Maarten Gribnau
+ * @date March 6, 2001
+ */
+
+class IMG_Line {
+public:
+
+ /**
+ * Constructs a line with the given values.
+ * @param xs start point x-coordinate
+ * @param ys start point y-coordinate
+ * @param xe end point x-coordinate
+ * @param ye end point y-coordinate
+ */
+ IMG_Line(TInt32 xs=0, TInt32 ys=0, TInt32 xe=0, TInt32 ye=0)
+ : m_xs(xs), m_ys(ys), m_xe(xe), m_ye(ye) {}
+
+ /**
+ * Copy constructor.
+ * @param l line to copy
+ */
+ IMG_Line(const IMG_Line& l)
+ : m_xs(l.m_xs), m_ys(l.m_ys), m_xe(l.m_xe), m_ye(l.m_ye) {}
+
+ /**
+ * Destructor.
+ */
+ virtual ~IMG_Line() {};
+
+ /**
+ * Access to line length.
+ * @return length of the line.
+ */
+ virtual inline float getLength() const;
+
+ /**
+ * Sets all members of the line.
+ * @param xs start point x-coordinate
+ * @param ys start point y-coordinate
+ * @param xe end point x-coordinate
+ * @param ye end point y-coordinate
+ */
+ virtual inline void set(TInt32 xs, TInt32 ys, TInt32 xe, TInt32 ye);
+
+ /**
+ * Returns whether this line is empty.
+ * Empty line are lines that have length==0.
+ * @return boolean value (true==empty line)
+ */
+ virtual inline bool isEmpty() const;
+
+ /**
+ * Returns point at given value for line parameter.
+ * Calculates the coordinates of a point on the line.
+ * @param t line parameter value (0<=t<=1) of the point requested.
+ * @param x x-coordinate of the point.
+ * @param y y-coordinate of the point.
+ */
+ virtual inline void getPoint(float t, TInt32& x, TInt32& y) const;
+
+ /** Start point x-coordinate */
+ TInt32 m_xs;
+ /** Start point y-coordinate */
+ TInt32 m_ys;
+ /** End point x-coordinate */
+ TInt32 m_xe;
+ /** End point y-coordinate */
+ TInt32 m_ye;
+};
+
+
+inline float IMG_Line::getLength() const
+{
+ TInt32 dx = m_xe - m_xs;
+ TInt32 dy = m_ye - m_ys;
+ return ((float)::sqrt(((float)dx)*dx + ((float)dy)*dy));
+}
+
+
+inline void IMG_Line::set(TInt32 xs, TInt32 ys, TInt32 xe, TInt32 ye)
+{
+ m_xs = xs; m_ys = ys; m_xe = xe; m_ye = ye;
+}
+
+
+inline bool IMG_Line::isEmpty() const
+{
+ return (getLength() <= 0);
+}
+
+
+inline void IMG_Line::getPoint(float t, TInt32& x, TInt32& y) const
+{
+ x = (TInt32) (((float)m_xs) + (t * (m_xe - m_xs)));
+ y = (TInt32) (((float)m_ys) + (t * (m_ye - m_ys)));
+}
+
+
+#endif // _H_IMG_Line
diff --git a/source/blender/img/intern/IMG_MemPtr.h b/source/blender/img/intern/IMG_MemPtr.h
new file mode 100644
index 00000000000..f6c93e50c42
--- /dev/null
+++ b/source/blender/img/intern/IMG_MemPtr.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 *****
+ * @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
diff --git a/source/blender/img/intern/IMG_Pixmap.cpp b/source/blender/img/intern/IMG_Pixmap.cpp
new file mode 100644
index 00000000000..fa2176d299c
--- /dev/null
+++ b/source/blender/img/intern/IMG_Pixmap.cpp
@@ -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 *****
+ */
+
+#include "IMG_Pixmap.h"
+
+
+
+
+IMG_Pixmap::IMG_Pixmap()
+{
+ m_image = 0;
+ m_width = 0;
+ m_height = 0;
+ m_rowBytes = 0;
+ m_pixelSize = 0;
+ m_pixelType = kPixelTypeRGB32;
+/*
+#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/source/blender/img/intern/IMG_Pixmap.h b/source/blender/img/intern/IMG_Pixmap.h
new file mode 100644
index 00000000000..3491174d379
--- /dev/null
+++ b/source/blender/img/intern/IMG_Pixmap.h
@@ -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 *****
+ * @author Maarten Gribnau
+ * @date March 6, 2001
+ */
+
+#ifndef _H_IMG_Pixmap
+#define _H_IMG_Pixmap
+
+#include "IMG_Types.h"
+#include "IMG_Color.h"
+#include "IMG_Rect.h"
+
+
+/**
+ * Base class for pixmaps. Here a more elaborate description of the IMG_Pixmap class should be written.
+ * @author Maarten Gribnau
+ * @date March 6, 2001
+ */
+
+class IMG_Pixmap {
+public:
+ /**
+ * The type of pixels.
+ * The type of pixels that are stored in this pixmap.
+ */
+ typedef enum {
+ kPixelTypeRGB32 = 0, /**< R:8, G:8, B:8, Ignore:8 */
+ kPixelTypeRGBA32 = 1, /**< R:8, G:8, B:8, Alpha:8 */
+// kPixelTypeRGB16 = 2, /**< Ignore:1, R:5, G:5, B:5 */
+// kPixelTypeRGBA16 = 3, /**< Alpha:1, R:5, G:5, B:5 */
+// kPixelTypeRGB16_565 = 4, /**< R:5, G:6, B:5 */
+ kPixelTypeRGB24 = 5 /**< R:8, G:8, B:8 */
+ } PixelType;
+
+ /**
+ * Default constructor.
+ */
+ IMG_Pixmap();
+
+ /**
+ * Destructor.
+ */
+ virtual ~IMG_Pixmap();
+
+ /**
+ * Access to image data
+ * @return pointer to the image data
+ */
+ inline void* getImage() const;
+
+ /**
+ * Access to image width.
+ * @return width of the image
+ */
+ inline TUns32 getWidth() const;
+
+ /**
+ * Access to image height.
+ * @return height of the image
+ */
+ inline TUns32 getHeight() const;
+
+ /**
+ * Returns the bounds of the pixmap in a rectangle.
+ * @param bounds of the image
+ */
+ inline void getBounds(IMG_Rect& r) const;
+
+ /**
+ * Access to pixel type.
+ * @return the pixel type
+ */
+ inline PixelType getPixelType() const;
+
+ /**
+ * Clamps u, v coordinates between 0 and 1.
+ * @param u requested u-coordinate
+ * @param v requested v-coordinate
+ */
+ inline void clampUV(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, TUns32& x, TUns32& 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 IMG_Rect& r, const IMG_ColorRGBA& c) = 0;
+
+protected:
+ /** Pointer to the image data */
+ void* m_image;
+ /** Width of the image in pixels */
+ TUns32 m_width;
+ /** Height of the image in pixels */
+ TUns32 m_height;
+ /** Number of bytes for one row in the image. */
+ TUns32 m_rowBytes;
+ /** Size in bits for one pixel */
+ TUns32 m_pixelSize;
+ /** Type of pixels in this image. */
+ PixelType m_pixelType;
+// TQ3Endian m_bitOrder;
+// TQ3Endian m_byteOrder;
+};
+
+inline void* IMG_Pixmap::getImage() const
+{
+ return m_image;
+}
+
+inline TUns32 IMG_Pixmap::getWidth() const
+{
+ return m_width;
+}
+
+inline TUns32 IMG_Pixmap::getHeight() const
+{
+ return m_height;
+}
+
+inline void IMG_Pixmap::getBounds(IMG_Rect& r) const
+{
+ r.set(0, 0, m_width, m_height);
+}
+
+inline IMG_Pixmap::PixelType IMG_Pixmap::getPixelType() const
+{
+ return m_pixelType;
+}
+
+inline void IMG_Pixmap::clampUV(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, TUns32& x, TUns32& y) const
+{
+ //MAART TEMP! clampUV(u, v);
+ x = (TUns32)(((float)m_width) * u);
+ y = (TUns32)(((float)m_height) * v);
+}
+
+#endif // _H_IMG_Pixmap
diff --git a/source/blender/img/intern/IMG_PixmapRGBA32.cpp b/source/blender/img/intern/IMG_PixmapRGBA32.cpp
new file mode 100644
index 00000000000..7ef716643b7
--- /dev/null
+++ b/source/blender/img/intern/IMG_PixmapRGBA32.cpp
@@ -0,0 +1,262 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "IMG_PixmapRGBA32.h"
+
+
+
+IMG_PixmapRGBA32::IMG_PixmapRGBA32(TUns32 width, TUns32 height)
+ : IMG_Pixmap(), m_mem(width * height)
+{
+ m_image = m_mem;
+ m_width = width;
+ m_height = height;
+ m_rowBytes = width * sizeof(TPixelRGBA32);
+ m_pixelSize = 8 * sizeof(TPixelRGBA32);
+ m_pixelType = kPixelTypeRGBA32;
+}
+
+
+IMG_PixmapRGBA32::IMG_PixmapRGBA32(void* image, TUns32 width, TUns32 height, TUns32 rowBytes)
+ : IMG_Pixmap(), m_mem(image, width * rowBytes)
+{
+ m_image = m_mem;
+ m_width = width;
+ m_height = height;
+ m_rowBytes = rowBytes;
+ m_pixelSize = 8 * sizeof(TPixelRGBA32);
+ m_pixelType = kPixelTypeRGBA32;
+}
+
+
+void IMG_PixmapRGBA32::fillRect(const IMG_Rect& r, const IMG_ColorRGB& c)
+{
+ IMG_Rect t_bnds (0, 0, m_width, m_height); // Bounds of this pixmap
+ IMG_Rect r_bnds (r); // Area to set
+
+ // Determine visibility
+ TVisibility v = t_bnds.getVisibility(r_bnds);
+ if (v == kNotVisible) return;
+ if (v == 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 (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 (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;
+ TUns8* srcBytes = (TUns8*) &src;
+
+ // Set the pixels in the destination rectangle
+ for (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 (TInt32 x = r.m_l; x < r.m_r; x++) {
+ // Set the new pixel value (retain current alpha)
+ ((TUns8*)desPtr)[bi_r] = srcBytes[bi_r];
+ ((TUns8*)desPtr)[bi_g] = srcBytes[bi_g];
+ ((TUns8*)desPtr)[bi_b] = srcBytes[bi_b];
+ desPtr++;
+ }
+ }
+#endif
+}
+
+
+void IMG_PixmapRGBA32::fillRect(const IMG_Rect& r, const IMG_ColorRGBA& c)
+{
+ IMG_Rect t_bnds (0, 0, m_width, m_height); // Bounds of this pixmap
+ IMG_Rect r_bnds (r); // Area to set
+
+ // Determine visibility
+ TVisibility v = t_bnds.getVisibility(r_bnds);
+ if (v == kNotVisible) return;
+ if (v == 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 (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 (TInt32 x = r.m_l; x < r.m_r; x++) {
+ *(desPtr++) = pixel;
+ }
+ }
+}
+
+
+void IMG_PixmapRGBA32::setPixmap(TUns32 x, TUns32 y, const IMG_PixmapRGBA32& pixmap, const IMG_Rect& bnds)
+{
+ IMG_Rect i_bnds (bnds); // Bounds of input pixmap
+ IMG_Rect t_bnds (0, 0, m_width, m_height); // Bounds of this pixmap
+ IMG_Rect p_bnds (bnds); // Bounds of the paste area
+ p_bnds.setCenter(x, y);
+
+ // 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
+ TVisibility v = t_bnds.getVisibility(p_bnds);
+ if (v == kNotVisible) return;
+ if (v == 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;
+ }
+ TInt32 d = p_bnds.getWidth();
+ if (p_bnds.m_r > d) {
+ i_bnds.m_t -= d - p_bnds.m_r;
+ p_bnds.m_t = d;
+ }
+ d = p_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 (TInt32 r = 0; r < p_bnds.getHeight(); r++) {
+ // Park pixel pointers at the start pixels
+ TPixelPtr srcPtr = 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(TUns32 x, TUns32 y, const IMG_PixmapRGBA32& pixmap, const IMG_Rect& bnds)
+{
+ IMG_Rect i_bnds (bnds); // Bounds of input pixmap
+ IMG_Rect t_bnds (0, 0, m_width, m_height); // Bounds of this pixmap
+ IMG_Rect p_bnds (bnds); // Bounds of the paste area
+ p_bnds.setCenter(x, y);
+
+ // 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
+ TVisibility v = t_bnds.getVisibility(p_bnds);
+ if (v == kNotVisible) return;
+ if (v == 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;
+ }
+ 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 = pixmap.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++;
+ }
+ }
+}
+
+
+void IMG_PixmapRGBA32::blendPixmap(float u, float v, const IMG_PixmapRGBA32& pixmap)
+{
+ TUns32 x, y;
+ getPixelAddress(u, v, x, y);
+ blendPixmap(x, y, pixmap);
+}
diff --git a/source/blender/img/intern/IMG_PixmapRGBA32.h b/source/blender/img/intern/IMG_PixmapRGBA32.h
new file mode 100644
index 00000000000..407e0868f09
--- /dev/null
+++ b/source/blender/img/intern/IMG_PixmapRGBA32.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 *****
+ * @author Maarten Gribnau
+ * @date March 6, 2001
+ */
+
+#ifndef _H_IMG_PixmapRGBA32
+#define _H_IMG_PixmapRGBA32
+
+#include "IMG_Pixmap.h"
+#include "IMG_MemPtr.h"
+
+/**
+ * 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
+ */
+
+class IMG_PixmapRGBA32 : public IMG_Pixmap {
+public:
+ /**
+ * The pixel type in this pixmap.
+ */
+ typedef 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;
+
+ /** "Save" memory pointer. */
+ IMG_MemPtr<TPixelRGBA32> m_mem;
+
+ /**
+ * 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(TUns32 width, 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, TUns32 width, TUns32 height, 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 IMG_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 IMG_Rect& r, const IMG_ColorRGBA& c);
+
+ /**
+ * Pastes a pixmap into this pixmap.
+ * Pastes the given pixmap centered at the given coordinates into this pixmap.
+ * Ignores the alpha information, this is pasted too.
+ * @todo implement wrapping modes when the pixmap does not fit within the bounds.
+ * @param x x-coordinate of the center location of the image.
+ * @param y y-coordinate of the center location of the image.
+ * @param pixmap the pixmap to paste.
+ */
+ inline virtual void setPixmap(TUns32 x, TUns32 y, const IMG_PixmapRGBA32& pixmap);
+
+ /**
+ * Pastes an area in 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 too.
+ * @todo implement wrapping modes when the pixmap does not fit within the bounds.
+ * @param x x-coordinate of the center location of the image.
+ * @param y y-coordinate of the center location of the image.
+ * @param pixmap the pixmap to paste.
+ * @param bnds the bounds of the area of the pixmap to paste.
+ */
+ virtual void setPixmap(TUns32 x, TUns32 y, const IMG_PixmapRGBA32& pixmap, const IMG_Rect& bnds);
+
+ /**
+ * Blends a pixmap into this pixmap.
+ * Blends the given pixmap centered at the given coordinates into this pixmap.
+ * The alpha information in the given image is used to blend.
+ * @todo implement wrapping modes when the pixmap does not fit within the bounds.
+ * @param x x-coordinate of the center location of the image.
+ * @param y y-coordinate of the center location of the image.
+ * @param pixmap the pixmap to blend.
+ */
+ virtual void blendPixmap(TUns32 x, TUns32 y, const IMG_PixmapRGBA32& pixmap);
+
+ /**
+ * 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.
+ * @todo implement wrapping modes when the pixmap does not fit within the bounds.
+ * @param x x-coordinate of the center location of the image.
+ * @param y y-coordinate of the center location of the image.
+ * @param pixmap the pixmap to blend.
+ * @param bnds the bounds of the area of the pixmap to blend.
+ */
+ virtual void blendPixmap(TUns32 x, TUns32 y, const IMG_PixmapRGBA32& pixmap, const IMG_Rect& bnds);
+
+ /**
+ * Blends a pixmap into this pixmap at (u,v) coordinates.
+ * Pastes the given pixmap centered at the given coordinates into this pixmap.
+ * The alpha information in the given image is used to blend.
+ * @see IMG_PixmapRGBA32::blendPixmap(TUns32 x, TUns32 y, const IMG_PixmapRGBA32& pixmap)
+ * @todo implement wrapping modes when the pixmap does not fit within the bounds.
+ * @param u u-coordinate of the center location of the image.
+ * @param v v-coordinate of the center location of the image.
+ * @param pixmap the pixmap to blend
+ */
+ virtual void blendPixmap(float u, float v, const IMG_PixmapRGBA32& pixmap);
+
+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(TUns32 x, 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;
+};
+
+inline void IMG_PixmapRGBA32::setPixmap(TUns32 x, TUns32 y, const IMG_PixmapRGBA32& pixmap)
+{
+ IMG_Rect bnds;
+ pixmap.getBounds(bnds);
+ setPixmap(x, y, pixmap, bnds);
+}
+
+inline void IMG_PixmapRGBA32::blendPixmap(TUns32 x, TUns32 y, const IMG_PixmapRGBA32& pixmap)
+{
+ IMG_Rect bnds;
+ pixmap.getBounds(bnds);
+ blendPixmap(x, y, pixmap, bnds);
+}
+
+inline IMG_PixmapRGBA32::TPixelPtr IMG_PixmapRGBA32::getPixelPtr(TUns32 x, TUns32 y) const
+{
+ return (TPixelPtr) (((TUns8*)m_image) + (y*m_rowBytes) + (x*4));
+}
+
+
+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;
+ TUns8* bytes = (TUns8*)&pixel;
+ bytes[bi_r] = (TUns8)(((float) 0xFF) * c.m_r);
+ bytes[bi_g] = (TUns8)(((float) 0xFF) * c.m_g);
+ bytes[bi_b] = (TUns8)(((float) 0xFF) * c.m_b);
+ bytes[bi_a] = (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
+ TUns8* bytes = (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
diff --git a/source/blender/img/intern/IMG_Rect.cpp b/source/blender/img/intern/IMG_Rect.cpp
new file mode 100644
index 00000000000..67357712708
--- /dev/null
+++ b/source/blender/img/intern/IMG_Rect.cpp
@@ -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 *****
+ */
+
+#include "IMG_Rect.h"
+
+
+TVisibility IMG_Rect::getVisibility(IMG_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);
+ TVisibility v;
+ if (lt && rt && lb && rb) {
+ // All points inside, rectangle is inside this
+ v = 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 = kPartiallyVisible;
+ }
+ else {
+ v = kNotVisible;
+ }
+ }
+ else {
+ // Some of the points inside, rectangle is partially inside
+ v = kPartiallyVisible;
+ }
+ return v;
+}
+
+TVisibility IMG_Rect::getVisibility(IMG_Line& l) const
+{
+ bool s = isInside(l.m_xs, l.m_ys);
+ bool e = isInside(l.m_xe, l.m_ye);
+ TVisibility v;
+ if (s && e) {
+ v = kFullyVisible;
+ }
+ else if (s || e) {
+ v = kPartiallyVisible;
+ }
+ else {
+ v = kNotVisible;
+ }
+ return v;
+}
+
+
+void IMG_Rect::setCenter(TInt32 cx, TInt32 cy)
+{
+ 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 IMG_Rect::setCenter(TInt32 cx, TInt32 cy, TInt32 w, 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 IMG_Rect::clip(IMG_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;
+}
+
+bool IMG_Rect::clip(IMG_Line& l) const
+{
+ bool clipped = false;
+ return clipped;
+}
diff --git a/source/blender/img/intern/IMG_Rect.h b/source/blender/img/intern/IMG_Rect.h
new file mode 100644
index 00000000000..654cd99d89b
--- /dev/null
+++ b/source/blender/img/intern/IMG_Rect.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 *****
+ * @author Maarten Gribnau
+ * @date March 7, 2001
+ */
+
+#ifndef _H_IMG_Rect
+#define _H_IMG_Rect
+
+#include "IMG_Types.h"
+#include "IMG_Line.h"
+
+/**
+ * Implements rectangle functionality.
+ * Used for bounds in images.
+ * The four extreme coordinates are stored as left, top, right and bottom.
+ * left is assumed to be smaller than or equal to right.
+ * top is assumed to be smaller than or equal to bottom.
+ * @author Maarten Gribnau
+ * @date March 6, 2001
+ */
+
+class IMG_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
+ */
+ IMG_Rect(TInt32 l=0, TInt32 t=0, TInt32 r=0, TInt32 b=0)
+ : m_l(l), m_t(t), m_r(r), m_b(b) {}
+
+ /**
+ * Copy constructor.
+ * @param r rectangle to copy
+ */
+ IMG_Rect(const IMG_Rect& r)
+ : m_l(r.m_l), m_t(r.m_t), m_r(r.m_r), m_b(r.m_b) {}
+
+ /**
+ * Destructor.
+ */
+ virtual ~IMG_Rect() {};
+
+ /**
+ * Access to rectangle width.
+ * @return width of the rectangle
+ */
+ virtual inline TInt32 getWidth() const;
+
+ /**
+ * Access to rectangle height.
+ * @return height of the rectangle
+ */
+ virtual inline 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(TInt32 l, TInt32 t, TInt32 r, 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 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(TInt32 x, TInt32 y) const;
+
+ /**
+ * Returns whether the rectangle is inside this rectangle.
+ * @param r rectangle to test.
+ * @return visibility (not, partially or fully visible).
+ */
+ virtual TVisibility getVisibility(IMG_Rect& r) const;
+
+ /**
+ * Returns whether the line is inside this rectangle.
+ * @param l line to test.
+ * @return visibility (not, partially or fully visible).
+ */
+ virtual TVisibility getVisibility(IMG_Line& l) 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(TInt32 cx, 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(TInt32 cx, TInt32 cy, TInt32 w, 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(IMG_Rect& r) const;
+
+ /**
+ * Clips a line.
+ * Updates the line given such that it will fit within this rectangle.
+ * This can result in an empty line.
+ * @param l the line to clip
+ * @return whether clipping has occurred
+ */
+ virtual bool clip(IMG_Line& l) const;
+
+ /** Left coordinate of the rectangle */
+ TInt32 m_l;
+ /** Top coordinate of the rectangle */
+ TInt32 m_t;
+ /** Right coordinate of the rectangle */
+ TInt32 m_r;
+ /** Bottom coordinate of the rectangle */
+ TInt32 m_b;
+};
+
+
+inline TInt32 IMG_Rect::getWidth() const
+{
+ return m_r - m_l;
+}
+
+inline TInt32 IMG_Rect::getHeight() const
+{
+ return m_b - m_t;
+}
+
+inline void IMG_Rect::set(TInt32 l, TInt32 t, TInt32 r, TInt32 b)
+{
+ m_l = l; m_t = t; m_r = r; m_b = b;
+}
+
+inline bool IMG_Rect::isEmpty() const
+{
+ return (getWidth() == 0) || (getHeight() == 0);
+}
+
+inline bool IMG_Rect::isInside(TInt32 x, TInt32 y) const
+{
+ return (x >= m_l) && (x <= m_r) && (y >= m_t) && (y <= m_b);
+}
+
+#endif // _H_IMG_Rect
diff --git a/source/blender/img/intern/IMG_Types.h b/source/blender/img/intern/IMG_Types.h
new file mode 100644
index 00000000000..0c035439611
--- /dev/null
+++ b/source/blender/img/intern/IMG_Types.h
@@ -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 *****
+ * @author Maarten Gribnau
+ * @date March 7, 2001
+ */
+
+#ifndef _H_IMG_Types
+#define _H_IMG_Types
+
+typedef int TInt32;
+typedef unsigned char TUns8;
+typedef unsigned int TUns32;
+
+typedef enum {
+ kNotVisible = 0,
+ kPartiallyVisible,
+ kFullyVisible
+} TVisibility;
+
+#endif // _H_IMG_Types
diff --git a/source/blender/img/intern/Makefile b/source/blender/img/intern/Makefile
new file mode 100644
index 00000000000..b4ccd4b14e9
--- /dev/null
+++ b/source/blender/img/intern/Makefile
@@ -0,0 +1,49 @@
+#
+# $Id$
+#
+# ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version. The Blender
+# Foundation also sells licenses for use in proprietary software under
+# the Blender License. See http://www.blender.org/BL/ for information
+# about this.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2001-2002 by 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 = img
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+ifeq ($(OS),$(findstring $(OS), "beos darwin freebsd linux openbsd solaris windows"))
+ CFLAGS += -funsigned-char
+endif
+
+CFLAGS += $(LEVEL_1_C_WARNINGS)
+
+# path to SDNA types
+CPPFLAGS += -I../../makesdna
+# path to our own external headerfiles
+CPPFLAGS += -I..
+
diff --git a/source/blender/include/BDR_drawaction.h b/source/blender/include/BDR_drawaction.h
new file mode 100644
index 00000000000..7cff1089c4d
--- /dev/null
+++ b/source/blender/include/BDR_drawaction.h
@@ -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 *****
+ */
+
+#ifndef BDR_DRAWACTION_H
+#define BDR_DRAWACTION_H
+
+struct BezTriple;
+struct Ipo;
+struct gla2DDrawInfo;
+struct bAction;
+struct Object;
+
+void draw_cfra_action(void);
+void draw_bevel_but(int x, int y, int w, int h, int sel);
+void draw_ipo_channel(struct gla2DDrawInfo *di, struct Ipo *ipo, int flags, float ypos);
+void draw_action_channel(struct gla2DDrawInfo *di, struct bAction *act, int flags, float ypos);
+void draw_object_channel(struct gla2DDrawInfo *di, struct Object *ob, int flags, float ypos);
+
+#endif /* BDR_DRAWACTION_H */
diff --git a/source/blender/include/BDR_drawmesh.h b/source/blender/include/BDR_drawmesh.h
new file mode 100644
index 00000000000..2aede9b5143
--- /dev/null
+++ b/source/blender/include/BDR_drawmesh.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 *****
+ */
+
+#ifndef BDR_DRAWMESH_H
+#define BDR_DRAWMESH_H
+
+struct Image;
+struct TFace;
+struct Object;
+struct Mesh;
+
+/**
+ * Enables or disable mipmapping for realtime images (textures).
+ * Note that this will will destroy all texture bindings in OpenGL.
+ * @see free_realtime_image()
+ * @param mipmap Turn mipmapping on (mipmap!=0) or off (mipmap==0).
+ */
+void set_mipmap(int mipmap);
+
+/**
+ * Returns the current setting for mipmapping.
+ */
+int get_mipmap(void);
+
+/**
+ * Enables or disable linear mipmap setting for realtime images (textures).
+ * Note that this will will destroy all texture bindings in OpenGL.
+ * @see free_realtime_image()
+ * @param mipmap Turn linear mipmapping on (linear!=0) or off (linear==0).
+ */
+void set_linear_mipmap(int linear);
+
+/**
+ * Returns the current setting for linear mipmapping.
+ */
+int get_linear_mipmap(void);
+
+/**
+ * Resets the realtime image cache variables.
+ */
+void clear_realtime_image_cache();
+
+void free_realtime_image(struct Image *ima);
+void free_all_realtime_images(void);
+void make_repbind(struct Image *ima);
+int set_tpage(struct TFace *tface);
+void spack(unsigned int ucol);
+void draw_tfaces3D(struct Object *ob, struct Mesh *me);
+void draw_tface_mesh(struct Object *ob, struct Mesh *me, int dt);
+void init_realtime_GL(void);
+
+#endif /* BDR_DRAWMESH_H */
diff --git a/source/blender/include/BDR_drawobject.h b/source/blender/include/BDR_drawobject.h
new file mode 100644
index 00000000000..a07c17f3f59
--- /dev/null
+++ b/source/blender/include/BDR_drawobject.h
@@ -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 *****
+ */
+
+#ifndef BDR_DRAWOBJECT_H
+#define BDR_DRAWOBJECT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+struct Object;
+struct Nurb;
+struct Lamp;
+struct ListBase;
+struct BoundBox;
+struct Base;
+
+void init_draw_rects(void);
+void helpline(float *vec);
+void drawaxes(float size);
+void drawcamera(struct Object *ob);
+void calc_lattverts_ext(void);
+void calc_meshverts(void);
+void calc_meshverts_ext(void);
+void calc_nurbverts_ext(void);
+void tekenvertices(short sel);
+void tekenvertices_ext(int mode);
+void drawcircball(float *cent, float rad, float tmat[][4]);
+void get_local_bounds(struct Object *ob, float *centre, float *size);
+void draw_object(struct Base *base);
+void draw_object_ext(struct Base *base);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BDR_DRAWOBJECT_H */
diff --git a/source/blender/include/BDR_editcurve.h b/source/blender/include/BDR_editcurve.h
new file mode 100644
index 00000000000..991d176e286
--- /dev/null
+++ b/source/blender/include/BDR_editcurve.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 BDR_EDITCURVE_H
+#define BDR_EDITCURVE_H
+
+struct Curve;
+struct Nurb;
+struct BezTriple;
+struct BPoint;
+struct BezTripleNurb;
+
+short isNurbsel(struct Nurb *nu);
+int isNurbsel_count(struct Nurb *nu);
+void printknots(void);
+void load_editNurb(void);
+void make_editNurb(void);
+void remake_editNurb(void);
+void separate_nurb(void);
+short isNurbselUV(struct Nurb *nu, int *u, int *v, int flag);
+void setflagsNurb(short flag);
+void rotateflagNurb(short flag, float *cent, float rotmat[][3]);
+void translateflagNurb(short flag, float *vec);
+void weightflagNurb(short flag, float w, int mode);
+void deleteflagNurb(short flag);
+short extrudeflagNurb(int flag);
+void adduplicateflagNurb(short flag);
+void switchdirectionNurb2(void);
+void switchdirection_knots(float *base, int tot);
+void deselectall_nurb(void);
+void hideNurb(int swap);
+void revealNurb(void);
+void selectswapNurb(void);
+void subdivideNurb(void);
+short findnearestNurbvert(short sel, struct Nurb **nurb,
+ struct BezTriple **bezt, struct BPoint **bp);
+void findselectedNurbvert(struct Nurb **nu, struct BezTriple **bezt,
+ struct BPoint **bp);
+void setsplinetype(short type);
+void rotate_direction_nurb(struct Nurb *nu);
+int is_u_selected(struct Nurb *nu, int u);
+void make_selection_list_nurb(void);
+void merge_2_nurb(struct Nurb *nu1, struct Nurb *nu2);
+void merge_nurb(void);
+void addsegment_nurb(void);
+void mouse_nurb(void);
+void spinNurb(float *dvec, short mode);
+void addvert_Nurb(int mode);
+void extrude_nurb(void);
+void makecyclicNurb(void);
+void selectconnected_nurb(void);
+void selectrow_nurb(void);
+void adduplicate_nurb(void);
+void delNurb(void);
+void join_curve(int type);
+struct Nurb *addNurbprim(int type, int stype, int newname);
+void default_curve_ipo(struct Curve *cu);
+void add_primitiveCurve(int stype);
+void add_primitiveNurb(int type);
+void clear_tilt(void);
+void clever_numbuts_curve(void);
+int bezt_compare (const void *e1, const void *e2);
+
+#endif /* BDR_EDITCURVE_H */
diff --git a/source/blender/include/BDR_editface.h b/source/blender/include/BDR_editface.h
new file mode 100644
index 00000000000..4f45515cca9
--- /dev/null
+++ b/source/blender/include/BDR_editface.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 *****
+ */
+
+#ifndef BDR_EDITFACE_H
+#define BDR_EDITFACE_H
+
+struct TFace;
+struct Mesh;
+
+void set_lasttface(void);
+void default_uv(float uv[][2], float size);
+void default_tface(struct TFace *tface);
+void make_tfaces(struct Mesh *me);
+void reveal_tface(void);
+void hide_tface(void);
+void select_linked_tfaces(void);
+void deselectall_tface(void);
+void rotate_uv_tface(void);
+struct TFace* face_pick(struct Mesh *me, short x, short y);
+void face_select(void);
+void face_borderselect(void);
+float CalcNormUV(float *a, float *b, float *c);
+void uv_autocalc_tface(void);
+void set_faceselect(void);
+void face_draw(void);
+
+#endif /* BDR_EDITFACE_H */
diff --git a/source/blender/include/BDR_editmball.h b/source/blender/include/BDR_editmball.h
new file mode 100644
index 00000000000..3557266a55e
--- /dev/null
+++ b/source/blender/include/BDR_editmball.h
@@ -0,0 +1,49 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BDR_EDITMBALL_H
+#define BDR_EDITMBALL_H
+
+void make_editMball(void);
+void load_editMball(void);
+
+/**
+ * @attention The argument is discarded. It is there for
+ * compatibility.
+ */
+void add_primitiveMball(int);
+void deselectall_mball(void);
+void mouse_mball(void);
+void adduplicate_mball(void);
+void delete_mball(void);
+
+#endif /* BDR_EDITMBALL_H */
diff --git a/source/blender/include/BDR_editobject.h b/source/blender/include/BDR_editobject.h
new file mode 100644
index 00000000000..ed88334cbc8
--- /dev/null
+++ b/source/blender/include/BDR_editobject.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 BDR_EDITOBJECT_H
+#define BDR_EDITOBJECT_H
+
+struct TransVert;
+struct Object;
+struct TransOb;
+struct Tex;
+struct Material;
+struct Base;
+
+void add_object_draw(int type);
+void free_and_unlink_base(struct Base *base);
+void delete_obj(int ok);
+void make_track(void);
+void apply_obmat(struct Object *ob);
+void clear_parent(void);
+void clear_track(void);
+void clear_object(char mode);
+void reset_slowparents(void);
+void set_slowparent(void);
+void make_vertex_parent(void);
+int test_parent_loop(struct Object *par, struct Object *ob);
+void make_parent(void);
+
+void make_displists_by_parent(struct Object *ob);
+void exit_editmode(int freedata);
+void check_editmode(int type);
+void docentre(void);
+void docentre_new(void);
+void docentre_cursor(void);
+void movetolayer(void);
+void special_editmenu(void);
+void convertmenu(void);
+void copymenu_properties(struct Object *ob);
+void copymenu(void);
+void link_to_scene(unsigned short nr);
+void linkmenu(void);
+void make_duplilist_real(void);
+void apply_object(void);
+void ob_to_transob(struct Object *ob, struct TransOb *tob);
+void ob_to_tex_transob(struct Object *ob, struct TransOb *tob);
+void make_trans_objects(void);
+void enter_editmode(void);
+void copymenu_logicbricks(struct Object *ob);
+void clearbaseflags_for_editing(void);
+void make_trans_verts(float *min, float *max, int mode);
+void draw_prop_circle(void);
+void set_proportional_weight(struct TransVert *tv, float *min, float *max);
+void special_trans_update(int keyflags);
+void special_aftertrans_update(char mode, int flip, short canceled, int keyflags);
+void calc_trans_verts(void);
+void apply_keyb_grid(float *val, float fac1, float fac2, float fac3, int invert);
+void compatible_eul(float *eul, float *oldrot);
+void headerprint(char *str);
+void add_ipo_tob_poin(float *poin, float *old, float delta);
+void restore_tob(struct TransOb *tob);
+int cylinder_intersect_test(void);
+int sphere_intersect_test(void);
+int my_clock(void);
+void transform(int mode);
+void std_rmouse_transform(void (*xf_func)(int));
+void rightmouse_transform(void);
+void single_object_users(int flag);
+void new_id_matar(struct Material **matar, int totcol);
+void single_obdata_users(int flag);
+void single_mat_users(int flag);
+void do_single_tex_user(struct Tex **from);
+void single_tex_users_expand(void);
+void single_mat_users_expand(void);
+void single_user(void);
+void make_local(void);
+void adduplicate(float *dtrans);
+void selectlinks(void);
+void image_aspect(void);
+void set_ob_ipoflags(void);
+void select_select_keys(void);
+int verg_hoogste_zco(const void *a1, const void *a2);
+void sortfaces(void);
+int vergbaseco(const void *a1, const void *a2);
+void auto_timeoffs(void);
+void texspace_edit(void);
+void first_base(void);
+void make_displists_by_obdata(void *obdata);
+
+
+#endif /* BDR_EDITOBJECT_H */
+
diff --git a/source/blender/include/BDR_isect.h b/source/blender/include/BDR_isect.h
new file mode 100644
index 00000000000..3af6ea6ea17
--- /dev/null
+++ b/source/blender/include/BDR_isect.h
@@ -0,0 +1,92 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * Some geometrical operations (intersection and such).
+ */
+
+#ifndef BDR_ISECT_H
+#define BDR_ISECT_H
+
+
+struct EditVert;
+struct EditVlak;
+
+/**
+ * Intersect a face and a linesegment
+ *
+ * @param v1 Vertex 1 of the face
+ * @param v2 Vertex 2 of the face
+ * @param v3 Vertex 3 of the face
+ * @param v4 Point 1 on the line
+ * @param v5 Point 2 on the line
+ * @param vec Location of the intersection (if it exists)
+ *
+ * @retval -1 colliniar
+ * @retval 0 no intersection
+ * @retval 1 exact intersection of edge and line
+ * @retval 2 cross-intersection
+ */
+short IsectFL(float *v1, float *v2, float *v3,
+ float *v4, float *v5, float *vec);
+
+/**
+ * Intersect two lines
+ *
+ * @param v1 Point 1 of line 1
+ * @param v2 Point 2 of line 1
+ * @param v3 Point 1 of line 2
+ * @param v4 Point 2 of line 2
+ * @param cox projection (?)
+ * @param coy projection (?)
+ * @param labda answer (?)
+ * @param mu answer (?)
+ * @param vec answer (?)
+ *
+ * @retval -1 colliniar
+ * @retval 0 no intersection of segments
+ * @retval 1 exact intersection of segments
+ * @retval 2 cross-intersection of segments
+ */
+short IsectLL(float *v1, float *v2, float *v3, float *v4,
+ short cox, short coy,
+ float *labda, float *mu, float *vec);
+
+int count_comparevlak(struct EditVlak *vl1, struct EditVlak *vl2);
+void empty(void);
+void addisedge(float *vec, short* edflag,
+ struct EditVlak *vl1, struct EditVlak *vl2,
+ short tel);
+void oldedsort_andmake(struct EditVert **olded, int edcount, int proj);
+short maxco(float *v1, float *v2);
+void newfillvert(struct EditVert *v1);
+void addisfaces(struct EditVlak *evl);
+void intersect_mesh(void);
+
+#endif /* BDR_ISECT_H */
diff --git a/source/blender/include/BDR_vpaint.h b/source/blender/include/BDR_vpaint.h
new file mode 100644
index 00000000000..7f8fda21e92
--- /dev/null
+++ b/source/blender/include/BDR_vpaint.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 BDR_VPAINT_H
+#define BDR_VPAINT_H
+
+struct Mesh;
+struct MDeformVert; /* __NLA */
+unsigned int vpaint_get_current_col(void);
+unsigned int rgba_to_mcol(float r, float g, float b, float a);
+void do_shared_vertexcol(struct Mesh *me);
+void make_vertexcol(void);
+void copy_vpaint_undo(unsigned int *mcol, int tot);
+void vpaint_undo(void);
+void clear_vpaint(void);
+void clear_vpaint_selectedfaces(void);
+void vpaint_dogamma(void);
+void sample_vpaint(void);
+void init_vertexpaint(void);
+void free_vertexpaint(void);
+void vertex_paint(void);
+void set_vpaint(void);
+void set_wpaint(void);
+
+void weight_paint(void);
+void wpaint_undo (void);
+void copy_wpaint_undo (struct MDeformVert *dverts, int dcount);
+
+#endif /* BDR_VPAINT_H */
diff --git a/source/blender/include/BIF_buttons.h b/source/blender/include/BIF_buttons.h
new file mode 100644
index 00000000000..450a39929a9
--- /dev/null
+++ b/source/blender/include/BIF_buttons.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 *****
+ */
+#ifndef BIF_BUTTONS_H
+#define BIF_BUTTONS_H
+
+struct Base;
+
+extern void do_blenderbuttons(unsigned short event);
+extern void redraw_test_buttons(struct Base *new);
+
+#endif
diff --git a/source/blender/include/BIF_drawimage.h b/source/blender/include/BIF_drawimage.h
new file mode 100644
index 00000000000..a6a01ad5cb2
--- /dev/null
+++ b/source/blender/include/BIF_drawimage.h
@@ -0,0 +1,49 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BIF_DRAWIMAGE_H
+#define BIF_DRAWIMAGE_H
+
+struct SpaceImage;
+
+void calc_image_view(struct SpaceImage *sima, char mode);
+void drawimagespace(void);
+void draw_tfaces(void);
+void image_changed(struct SpaceImage *sima, int dotile);
+void image_home(void);
+void image_viewmove(void);
+void rectwrite_part(int winxmin, int winymin, int winxmax, int winymax, int x1, int y1, int xim, int yim, float zoomx, float zoomy, unsigned int *rect);
+void uvco_to_areaco(float *vec, short *mval);
+void uvco_to_areaco_noclip(float *vec, short *mval);
+void what_image(struct SpaceImage *sima);
+
+#endif
diff --git a/source/blender/include/BIF_drawoops.h b/source/blender/include/BIF_drawoops.h
new file mode 100644
index 00000000000..d580361be86
--- /dev/null
+++ b/source/blender/include/BIF_drawoops.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 *****
+ */
+
+#ifndef BIF_DRAWOOPS_H
+#define BIF_DRAWOOPS_H
+
+void give_oopslink_line(Oops *oops, OopsLink *ol, float *v1, float *v2);
+void mysbox(float x1, float y1, float x2, float y2);
+void boundbox_oops(void);
+
+#endif
diff --git a/source/blender/include/BIF_drawscene.h b/source/blender/include/BIF_drawscene.h
new file mode 100644
index 00000000000..19c22bb4a5f
--- /dev/null
+++ b/source/blender/include/BIF_drawscene.h
@@ -0,0 +1,33 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+struct Scene;
+void set_scene(struct Scene *sce);
diff --git a/source/blender/include/BIF_drawseq.h b/source/blender/include/BIF_drawseq.h
new file mode 100644
index 00000000000..0e7b113d9b4
--- /dev/null
+++ b/source/blender/include/BIF_drawseq.h
@@ -0,0 +1,41 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BIF_DRAWSEQ_H
+#define BIF_DRAWSEQ_H
+
+struct Sequence;
+void drawseqspace(void);
+void drawseq(struct Sequence *seq);
+void set_special_seq_update(int val);
+
+#endif
diff --git a/source/blender/include/BIF_drawtext.h b/source/blender/include/BIF_drawtext.h
new file mode 100644
index 00000000000..ab3c6223563
--- /dev/null
+++ b/source/blender/include/BIF_drawtext.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 BIF_DRAWTEXT_H
+#define BIF_DRAWTEXT_H
+
+struct ScrArea;
+struct SpaceText;
+struct Text;
+
+void unlink_text(struct Text *text);
+
+void init_textspace(struct ScrArea *sa);
+void free_textspace(struct SpaceText *st);
+
+void txt_write_file(struct Text *text);
+void add_text_fs(char *file);
+
+void free_txt_data(void);
+void pop_space_text(struct SpaceText *st);
+
+#endif
diff --git a/source/blender/include/BIF_editarmature.h b/source/blender/include/BIF_editarmature.h
new file mode 100644
index 00000000000..fac2eae6bf0
--- /dev/null
+++ b/source/blender/include/BIF_editarmature.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 BIF_EDITARMATURE_H
+#define BIF_EDITARMATURE_H
+
+struct Object;
+struct Bone;
+struct bArmature;
+
+typedef struct EditBone
+{
+ struct EditBone *next, *prev;
+ struct EditBone *parent;/* Editbones have a one-way link (i.e. children refer
+ to parents. This is converted to a two-way link for
+ normal bones when leaving editmode. */
+ void *temp; /* Used to store temporary data */
+
+ char name[32];
+ char oldname[32];
+ float roll; /* Roll along axis. We'll ultimately use the axis/angle method
+ for determining the transformation matrix of the bone. The axis
+ is tail-head while roll provides the angle. Refer to Graphics
+ Gems 1 p. 466 (section IX.6) if it's not already in here somewhere*/
+
+ float head[3]; /* Orientation and length is implicit during editing */
+ float tail[3];
+ /* All joints are considered to have zero rotation with respect to
+ their parents. Therefore any rotations specified during the
+ animation are automatically relative to the bones' rest positions*/
+ short sHead[2];
+ short sTail[2];
+ int flag;
+
+ int parNr; /* Used for retrieving values from the menu system */
+ /* Storage for transformation data used by the posing system.
+ Maybe a better solution would be to make bones a blenderObject
+ variant? Or perhaps to use a TOTALLY custom transformation scheme
+ for pose element, rather than trying to use the existing transObject
+ system?
+ */
+ float dist, weight;
+ float loc[3], dloc[3];
+ float size[3], dsize[3];
+ float rot[3], drot[3];
+ float quat[4], dquat[4];
+ float obmat[4][4];
+
+
+} EditBone;
+
+
+void adduplicate_armature(void);
+void addvert_armature(void);
+void add_primitiveArmature(int type);
+void apply_rot_armature (struct Object *ob, float mat[3][3]);
+void armaturebuts(void);
+void clear_armature(struct Object *ob, char mode);
+void clever_numbuts_armature (void);
+void clever_numbuts_posearmature (void);
+void delete_armature(void);
+void deselectall_armature(void);
+void deselectall_posearmature (int test);
+void draw_armature(struct Object *ob);
+void extrude_armature(void);
+void free_editArmature(void);
+void join_armature(void);
+void load_editArmature(void);
+char* make_bone_menu(struct bArmature *arm);
+void make_bone_parent(void);
+void make_editArmature(void);
+void make_trans_bones (char mode);
+void mousepose_armature(void);
+void mouse_armature(void);
+void remake_editArmature(void);
+void selectconnected_armature(void);
+void selectconnected_posearmature(void);
+void select_bone_by_name (struct bArmature *arm, char *name, int select);
+struct Bone *get_first_selected_bone (void);
+void auto_align_armature(void);
+
+#define BONESEL_TIP 0x08000000
+#define BONESEL_ROOT 0x04000000
+#define BONESEL_BONE (BONESEL_TIP|BONESEL_ROOT)
+#define BONESEL_NOSEL 0x80000000 /* Indicates a negative number */
+
+#endif
+
diff --git a/source/blender/include/BIF_editconstraint.h b/source/blender/include/BIF_editconstraint.h
new file mode 100644
index 00000000000..5d6d38fd529
--- /dev/null
+++ b/source/blender/include/BIF_editconstraint.h
@@ -0,0 +1,62 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BIF_EDITCONSTRAINT_H
+#define BIF_EDITCONSTRAINT_H
+
+struct ListBase;
+struct Object;
+struct bConstraint;
+struct bConstraintChannel;
+
+typedef struct ConstraintElement{
+ struct ConstraintElement *next, *prev;
+ struct ConstraintElement *parent;
+ Object *ob;
+ int flag;
+ const char *substring;
+ void *subdata;
+} ConstraintElement;
+
+struct bConstraintChannel *add_new_constraint_channel(const char *name);
+struct bConstraint * add_new_constraint(void);
+struct ListBase *get_constraint_client_channels (int forcevalid);
+struct ListBase *get_constraint_client(char *name, short *clienttype, void** clientdata);
+int test_constraints (struct Object *owner, const char *substring, int disable);
+void test_scene_constraints (void);
+void unique_constraint_name (struct bConstraint *con, struct ListBase *list);
+void *new_constraint_data (short type);
+
+/* void unique_constraint_name (struct bConstraint *con, struct ListBase *list); */
+
+#endif
+
diff --git a/source/blender/include/BIF_editdeform.h b/source/blender/include/BIF_editdeform.h
new file mode 100644
index 00000000000..5fcd0473ce5
--- /dev/null
+++ b/source/blender/include/BIF_editdeform.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 BIF_DEFORM_H
+#define BIF_DEFORM_H
+
+struct Object;
+struct MDeformVert;
+struct MDeformWeight;
+struct bDeformGroup;
+
+void unique_vertexgroup_name (struct bDeformGroup *dg, struct Object *ob);
+void add_defgroup (struct Object *ob);
+void del_defgroup (struct Object *ob);
+void assign_verts_defgroup (void);
+void remove_verts_defgroup (int allverts);
+void sel_verts_defgroup (int select);
+struct MDeformWeight *verify_defweight (struct MDeformVert *dv, int defgroup);
+void verify_defgroups (struct Object *ob);
+
+#endif
+
diff --git a/source/blender/include/BIF_editfont.h b/source/blender/include/BIF_editfont.h
new file mode 100644
index 00000000000..155e78d8a34
--- /dev/null
+++ b/source/blender/include/BIF_editfont.h
@@ -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 *****
+ */
+
+#ifndef BIF_EDITFONT_H
+#define BIF_EDITFONT_H
+
+void do_textedit(unsigned short event, short val, char ascii);
+void make_editText(void);
+void load_editText(void);
+void remake_editText(void);
+void free_editText(void);
+/**
+ * @attention The argument is discarded. It is there for
+ * compatibility.
+ */
+void add_primitiveFont(int);
+void to_upper(void);
+
+#endif
diff --git a/source/blender/include/BIF_editgroup.h b/source/blender/include/BIF_editgroup.h
new file mode 100644
index 00000000000..33a85839a49
--- /dev/null
+++ b/source/blender/include/BIF_editgroup.h
@@ -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 *****
+ */
+struct Group;
+void set_active_group(void);
+void add_selected_to_group(void);
+void rem_selected_from_group(void);
+void group_menu(void);
+void prev_group_key(struct Group *group);
+void next_group_key(struct Group *group);
diff --git a/source/blender/include/BIF_editika.h b/source/blender/include/BIF_editika.h
new file mode 100644
index 00000000000..ccbb91b2120
--- /dev/null
+++ b/source/blender/include/BIF_editika.h
@@ -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 *****
+ */
+struct Object;
+void draw_ika(struct Object *ob, int sel);
+void draw_ika_nrs(struct Object *ob, int type);
+int extrude_ika(struct Object *ob, int add);
+void delete_skeleton(void);
+void make_skeleton(void);
diff --git a/source/blender/include/BIF_editkey.h b/source/blender/include/BIF_editkey.h
new file mode 100644
index 00000000000..724f935cab5
--- /dev/null
+++ b/source/blender/include/BIF_editkey.h
@@ -0,0 +1,62 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BIF_EDITKEY_H
+#define BIF_EDITKEY_H
+
+struct Key;
+struct KeyBlock;
+struct Mesh;
+struct Object;
+struct Lattice;
+struct Curve;
+
+void mesh_to_key(struct Mesh *me, struct KeyBlock *kb);
+void key_to_mesh(struct KeyBlock *kb, struct Mesh *me);
+void insert_meshkey(struct Mesh *me);
+
+void latt_to_key(struct Lattice *lt, struct KeyBlock *kb);
+void key_to_latt(struct KeyBlock *kb, struct Lattice *lt);
+void insert_lattkey(struct Lattice *lt);
+
+void curve_to_key(struct Curve *cu, struct KeyBlock *kb, ListBase *nurb);
+void key_to_curve(struct KeyBlock *kb, struct Curve *cu, ListBase *nurb);
+void insert_curvekey(struct Curve *cu);
+
+struct Key *give_current_key(struct Object *ob);
+void showkeypos(struct Key *key, struct KeyBlock *kb);
+
+void deselectall_key(void);
+void delete_key(void);
+void move_keys(void);
+
+#endif
diff --git a/source/blender/include/BIF_editlattice.h b/source/blender/include/BIF_editlattice.h
new file mode 100644
index 00000000000..d7d8bcd272c
--- /dev/null
+++ b/source/blender/include/BIF_editlattice.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 BIF_EDITLATTICE_H
+#define BIF_EDITLATTICE_H
+
+void apply_lattice(void);
+void free_editLatt(void);
+void make_editLatt(void);
+void load_editLatt(void);
+void remake_editLatt(void);
+void deselectall_Latt(void);
+void mouse_lattice(void);
+
+#endif
diff --git a/source/blender/include/BIF_editmesh.h b/source/blender/include/BIF_editmesh.h
new file mode 100644
index 00000000000..9254a0db50b
--- /dev/null
+++ b/source/blender/include/BIF_editmesh.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 BIF_EDITMESH_H
+#define BIF_EDITMESH_H
+
+struct EditVlak;
+struct EditEdge;
+struct EditVert;
+struct Mesh;
+struct bDeformGroup;
+struct View3D;
+
+void free_hashedgetab(void);
+void fasterdraw(void);
+void slowerdraw(void);
+void vertexnoise(void);
+void vertexsmooth(void);
+void make_sticky(void);
+void deselectall_mesh(void);
+
+ /** Aligns the selected TFace's of @a me to the @a v3d,
+ * using the given axis (0-2). Can give a user error.
+ */
+void faceselect_align_view_to_selected(struct View3D *v3d, struct Mesh *me, int axis);
+ /** Aligns the selected faces or vertices of @a me to the @a v3d,
+ * using the given axis (0-2). Can give a user error.
+ */
+void editmesh_align_view_to_selected(struct View3D *v3d, int axis);
+
+struct EditVert *addvertlist(float *vec);
+struct EditEdge *addedgelist(struct EditVert *v1, struct EditVert *v2);
+struct EditVlak *addvlaklist(struct EditVert *v1, struct EditVert *v2, struct EditVert *v3, struct EditVert *v4, struct EditVlak *example);
+struct EditEdge *findedgelist(struct EditVert *v1, struct EditVert *v2);
+
+void remedge(struct EditEdge *eed);
+
+int vlakselectedAND(struct EditVlak *evl, int flag);
+
+void recalc_editnormals(void);
+void flip_editnormals(void);
+void vertexnormals(int testflip);
+/* this is currently only used by the python NMesh module: */
+void vertexnormals_mesh(struct Mesh *me, float *extverts);
+
+void make_editMesh(void);
+void load_editMesh(void);
+void free_editMesh(void);
+void remake_editMesh(void);
+
+void convert_to_triface(int all);
+
+void righthandfaces(int select);
+
+void mouse_mesh(void);
+
+void selectconnected_mesh(void);
+short extrudeflag(short flag,short type);
+void rotateflag(short flag, float *cent, float rotmat[][3]);
+void translateflag(short flag, float *vec);
+short removedoublesflag(short flag, float limit);
+void xsortvert_flag(int flag);
+void hashvert_flag(int flag);
+void subdivideflag(int flag, float rad, int beauty);
+void adduplicateflag(int flag);
+void extrude_mesh(void);
+void adduplicate_mesh(void);
+void split_mesh(void);
+void separate_mesh(void);
+void extrude_repeat_mesh(int steps, float offs);
+void spin_mesh(int steps,int degr,float *dvec, int mode);
+void screw_mesh(int steps,int turns);
+void selectswap_mesh(void);
+void addvert_mesh(void);
+void addedgevlak_mesh(void);
+void delete_mesh(void);
+void add_primitiveMesh(int type);
+void hide_mesh(int swap);
+void reveal_mesh(void);
+void beauty_fill(void);
+void join_triangles(void);
+void edge_flip(void);
+void join_mesh(void);
+void clever_numbuts_mesh(void);
+void sort_faces(void);
+void vertices_to_sphere(void);
+void fill_mesh(void);
+
+#endif
diff --git a/source/blender/include/BIF_editnla.h b/source/blender/include/BIF_editnla.h
new file mode 100644
index 00000000000..ebcbd1eaa49
--- /dev/null
+++ b/source/blender/include/BIF_editnla.h
@@ -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 *****
+ */
+
+#ifndef BIF_EDITNLA_H
+#define BIF_EDITNLA_H
+
+void clever_numbuts_nla(void);
+
+#endif
diff --git a/source/blender/include/BIF_editoops.h b/source/blender/include/BIF_editoops.h
new file mode 100644
index 00000000000..7e76cc65ea5
--- /dev/null
+++ b/source/blender/include/BIF_editoops.h
@@ -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 *****
+ */
+
+#ifndef BIF_EDITOOPS_H
+#define BIF_EDITOOPS_H
+
+void borderselect_oops(void);
+void deselect_all_area_oops(void);
+void mouse_select_oops(void);
+void select_backlinked_oops(void);
+void select_linked_oops(void);
+void set_select_flag_oops(void);
+void swap_select_all_oops(void);
+void transform_oops(int mode);
+
+#endif
diff --git a/source/blender/include/BIF_editsca.h b/source/blender/include/BIF_editsca.h
new file mode 100644
index 00000000000..93f43363ddf
--- /dev/null
+++ b/source/blender/include/BIF_editsca.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 *****
+ */
+
+#ifndef BIF_EDITSCA_H
+#define BIF_EDITSCA_H
+
+void make_unique_prop_names(char *str);
+void do_gamebuts(unsigned short event);
+void gamebuts(void);
+
+#endif
diff --git a/source/blender/include/BIF_editseq.h b/source/blender/include/BIF_editseq.h
new file mode 100644
index 00000000000..e10a221c018
--- /dev/null
+++ b/source/blender/include/BIF_editseq.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 BIF_EDITSEQ_H
+#define BIF_EDITSEQ_H
+
+struct Sequence;
+
+void add_duplicate_seq(void);
+void add_sequence(int type);
+void borderselect_seq(void);
+void boundbox_seq(void);
+void change_sequence(void);
+void clear_last_seq(void);
+void clever_numbuts_seq(void);
+void del_seq(void);
+void enter_meta(void);
+struct Sequence* find_nearest_seq(int *hand);
+int insert_gap(int gap, int cfra);
+void make_meta(void);
+void mouse_select_seq(void);
+void no_gaps(void);
+void seq_snapmenu(void);
+void set_filter_seq(void);
+void swap_select_seq(void);
+void touch_seq_files(void);
+void transform_seq(int mode);
+void un_meta(void);
+
+#endif
diff --git a/source/blender/include/BIF_editsima.h b/source/blender/include/BIF_editsima.h
new file mode 100644
index 00000000000..f14f856a876
--- /dev/null
+++ b/source/blender/include/BIF_editsima.h
@@ -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 *****
+ */
+void clever_numbuts_sima(void);
+void borderselect_sima(void);
+void mouseco_to_curtile(void);
+void mouse_select_sima(void);
+void select_swap_tface_uv(void);
+void tface_do_clip(void);
+void transform_tface_uv(int mode);
diff --git a/source/blender/include/BIF_editsound.h b/source/blender/include/BIF_editsound.h
new file mode 100644
index 00000000000..e4b730aedc8
--- /dev/null
+++ b/source/blender/include/BIF_editsound.h
@@ -0,0 +1,71 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BIF_EDITSOUND_H
+#define BIF_EDITSOUND_H
+
+struct bSound;
+struct bSample;
+struct ListBase;
+struct PackedFile;
+
+void sound_init_audio(void);
+void sound_initialize_sounds(void);
+void sound_exit_audio(void);
+int sound_get_mixrate(void);
+
+void* sound_get_audiodevice(void);
+void* sound_get_listener(void);
+
+int sound_set_sample(struct bSound* sound, struct bSample* sample);
+int sound_sample_is_null(struct bSound* sound);
+int sound_load_sample(struct bSound* sound);
+
+struct bSample* sound_find_sample(struct bSound* sound);
+struct bSample* sound_new_sample(struct bSound* sound);
+
+struct bSound* sound_new_sound(char *name);
+struct bSound* sound_make_copy(struct bSound* originalsound);
+void sound_end_all_sounds(void);
+
+void sound_initialize_sample(struct bSound * sound);
+void sound_load_samples(void);
+
+void sound_play_sound(struct bSound *sound);
+void sound_stop_all_sounds(void);
+
+void sound_set_position(void *object,
+ struct bSound *sound,
+ float obmatrix[4][4]);
+
+#endif
+
diff --git a/source/blender/include/BIF_editview.h b/source/blender/include/BIF_editview.h
new file mode 100644
index 00000000000..9c09103372f
--- /dev/null
+++ b/source/blender/include/BIF_editview.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 *****
+ */
+
+#ifndef BIF_EDITVIEW_H
+#define BIF_EDITVIEW_H
+
+struct Base;
+struct Object;
+
+void arrows_move_cursor(unsigned short event);
+void borderselect(void);
+void circle_select(void);
+void deselectall(void);
+void draw_sel_circle(short *mval, short *mvalo, float rad, float rado, int selecting);
+void fly(void);
+int gesture(void);
+void mouse_cursor(void);
+void mouse_select(void);
+void set_active_base(struct Base *base);
+void set_active_object(struct Object *ob);
+void set_render_border(void);
+
+#endif
diff --git a/source/blender/include/BIF_fsmenu.h b/source/blender/include/BIF_fsmenu.h
new file mode 100644
index 00000000000..c038360a874
--- /dev/null
+++ b/source/blender/include/BIF_fsmenu.h
@@ -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 *****
+ *
+ */
+
+#ifndef BSE_FSMENU_H
+#define BSE_FSMENU_H
+
+ /** Returns the number of entries in the Fileselect Menu */
+int fsmenu_get_nentries (void);
+
+ /** Returns true if the fsmenu entry at @a index exists and
+ * is a seperator.
+ */
+char* fsmenu_is_entry_a_seperator (int index);
+
+ /** Returns the fsmenu entry at @a index (or NULL if a bad index)
+ * or a seperator.
+ */
+char* fsmenu_get_entry (int index);
+
+ /** Returns a new menu description string representing the
+ * fileselect menu. Should be free'd with MEM_freeN.
+ */
+char* fsmenu_build_menu (void);
+
+ /** Append a seperator to the FSMenu, inserts always follow the
+ * last seperator.
+ */
+void fsmenu_append_seperator (void);
+
+ /** Inserts a new fsmenu entry with the given @a path.
+ * Duplicate entries are not added.
+ * @param sorted Should entry be inserted in sorted order?
+ */
+void fsmenu_insert_entry (char *path, int sorted);
+
+ /** Removes the fsmenu entry at the given @a index. */
+void fsmenu_remove_entry (int index);
+
+ /** Free's all the memory associated with the fsmenu */
+void fsmenu_free (void);
+
+#endif
diff --git a/source/blender/include/BIF_gl.h b/source/blender/include/BIF_gl.h
new file mode 100644
index 00000000000..f5507d30170
--- /dev/null
+++ b/source/blender/include/BIF_gl.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 *****
+ * os dependent include locations of gl.h
+ */
+
+#ifndef BIF_GL_H
+#define BIF_GL_H
+
+ /* XXX, fixme zr... what is the deal here,
+ * is there a reason unices don't use the
+ * <> include? (they should)
+ */
+#if !defined(__APPLE__) && !defined(WIN32)
+#include "GL/gl.h"
+#include "GL/glu.h"
+#else
+#include <GL/gl.h>
+#include <GL/glu.h>
+#endif
+
+ /*
+ * these should be phased out. cpack should be replaced in
+ * code with calls to glColor3ub, lrectwrite probably should
+ * change to a function. - zr
+ */
+
+/* Mij afspraak is cpack een getal dat als 0xFFaa66 of zo kan worden
+ * uitgedrukt. Is dus gevoelig voor endian. Met deze define wordt het
+ * altijd goed afgebeeld
+ *
+ * This define converts a numerical value to the equivalent 24-bit
+ * colour, while not being endian-sensitive. On little-endians, this
+ * is the same as doing a 'naive'indexing, on big-endian, it is not!
+ * */
+#define cpack(x) glColor3ub( ((x)&0xFF), (((x)>>8)&0xFF), (((x)>>16)&0xFF) )
+
+#define glMultMatrixf(x) glMultMatrixf( (float *)(x))
+#define glLoadMatrixf(x) glLoadMatrixf( (float *)(x))
+
+#define lrectwrite(a, b, c, d, rect) {glRasterPos2i(a, b);glDrawPixels((c)-(a)+1, (d)-(b)+1, GL_RGBA, GL_UNSIGNED_BYTE, rect);}
+
+#endif /* #ifdef BIF_GL_H */
diff --git a/source/blender/include/BIF_glutil.h b/source/blender/include/BIF_glutil.h
new file mode 100644
index 00000000000..ab8bad67760
--- /dev/null
+++ b/source/blender/include/BIF_glutil.h
@@ -0,0 +1,189 @@
+/**
+ * @file BIF_glutil.h
+ *
+ * OpenGL drawing utility functions.
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BIF_GLUTIL_H
+#define BIF_GLUTIL_H
+
+struct rcti;
+struct rctf;
+
+void sdrawXORline(int x0, int y0, int x1, int y1);
+void sdrawXORline4(int nr, int x0, int y0, int x1, int y1);
+void sdrawXORcirc(short xofs, short yofs, float rad);
+
+ /**
+ * Draw an XOR'd line in the front buffer between
+ * the given points.
+ *
+ * @attention This function also handles flushing the GL
+ * pipeline, which means it is inappropriate for drawing
+ * a large number of lines at once.
+ */
+void glutil_draw_front_xor_line(int x0, int y0, int x1, int y1);
+
+ /**
+ * Draw a lined (non-looping) arc with the given
+ * @a radius, starting at angle @a start and arcing
+ * through @a angle. The arc is centered at the origin
+ * and drawn in the XY plane.
+ *
+ * @param start The initial angle (in radians).
+ * @param angle The length of the arc (in radians).
+ * @param radius The arc radius.
+ * @param nsegments The number of segments to use in drawing the arc.
+ */
+void glutil_draw_lined_arc (float start, float angle, float radius, int nsegments);
+
+ /**
+ * Draw a filled arc with the given @a radius,
+ * starting at angle @a start and arcing through
+ * @a angle. The arc is centered at the origin
+ * and drawn in the XY plane.
+ *
+ * @param start The initial angle (in radians).
+ * @param angle The length of the arc (in radians).
+ * @param radius The arc radius.
+ * @param nsegments The number of segments to use in drawing the arc.
+ */
+void glutil_draw_filled_arc (float start, float angle, float radius, int nsegments);
+
+ /**
+ * Routines an integer value as obtained by glGetIntegerv.
+ * The param must cause only one value to be gotten from GL.
+ */
+int glaGetOneInteger (int param);
+
+ /**
+ * Routines a float value as obtained by glGetIntegerv.
+ * The param must cause only one value to be gotten from GL.
+ */
+float glaGetOneFloat (int param);
+
+ /**
+ * Functions like glRasterPos2i, except ensures that the resulting
+ * raster position is valid. @a known_good_x and @a known_good_y
+ * should be coordinates of a point known to be within the current
+ * view frustum.
+ * @attention This routine should be used when the distance of @a x
+ * and @y away from the known good point is small (ie. for small icons
+ * and for bitmap characters), when drawing large+zoomed images it is
+ * possible for overflow to occur, the glaDrawPixelsSafe routine should
+ * be used instead.
+ */
+void glaRasterPosSafe2f (float x, float y, float known_good_x, float known_good_y);
+
+ /**
+ * Functions like a limited glDrawPixels, except ensures that
+ * the image is displayed onscreen even if the @a x and @a y
+ * coordinates for would be clipped. The routine respects the
+ * glPixelZoom values, pixel unpacking parameters are _not_
+ * respected.
+
+ * @attention This routine makes many assumptions: the rect data
+ * is expected to be in RGBA unsigned byte format, the coordinate
+ * (0.375, 0.375) is assumed to be within the view frustum, and the
+ * modelview and projection matrices are assumed to define a
+ * 1-to-1 mapping to screen space.
+ * @attention Furthmore, in the case of zoomed or unpixel aligned
+ * images extending outside the view frustum, but still within the
+ * window, some portion of the image may be visible left and/or
+ * below of the given @a x and @a y coordinates. It is recommended
+ * to use the glScissor functionality if images are to be drawn
+ * with an inset view matrix.
+ */
+void glaDrawPixelsSafe (float x, float y, int img_w, int img_h, void *rect);
+
+ /**
+ * Functions like a limited glDrawPixels, but actually draws the
+ * image using textures, which can be tremendously faster on low-end
+ * cards, and also avoids problems with the raster position being
+ * clipped when offscreen. The routine respects the glPixelZoom values,
+ * pixel unpacking parameters are _not_ respected.
+
+ * @attention This routine makes many assumptions: the rect data
+ * is expected to be in RGBA unsigned byte format, and the
+ * modelview and projection matrices are assumed to define a
+ * 1-to-1 mapping to screen space.
+ */
+void glaDrawPixelsTex (float x, float y, int img_w, int img_h, void *rect);
+
+ /* 2D Drawing Assistance */
+
+ /** Define a 2D area (viewport, scissor, matrices) for OpenGL rendering.
+ * This routine sets up an OpenGL state appropriate for drawing using
+ * both vertice (glVertex, etc) and raster (glRasterPos, glRect) commands.
+ * All coordinates should be at integer positions. There is little to
+ * no reason to use glVertex2f etc. functions during 2D rendering, and
+ * thus no reason to +-0.5 the coordinates or perform other silly
+ * tricks.
+ *
+ * @param screen_rect The screen rectangle to be defined for 2D drawing.
+ */
+void glaDefine2DArea (struct rcti *screen_rect);
+
+typedef struct gla2DDrawInfo gla2DDrawInfo;
+
+ /** Save the current OpenGL state and initialize OpenGL for 2D
+ * rendering. glaEnd2DDraw should be called on the returned structure
+ * to free it and to return OpenGL to its previous state. The
+ * scissor rectangle is set to match the viewport.
+ *
+ * This routine sets up an OpenGL state appropriate for drawing using
+ * both vertice (glVertex, etc) and raster (glRasterPos, glRect) commands.
+ * All coordinates should be at integer positions. There is little to
+ * no reason to use glVertex2f etc. functions during 2D rendering, and
+ * thus no reason to +-0.5 the coordinates or perform other silly
+ * tricks.
+ *
+ * @param screen_rect The screen rectangle to be used for 2D drawing.
+ * @param world_rect The world rectangle that the 2D area represented
+ * by @a screen_rect is supposed to represent. If NULL it is assumed the
+ * world has a 1 to 1 mapping to the screen.
+ */
+gla2DDrawInfo* glaBegin2DDraw (struct rcti *screen_rect, struct rctf *world_rect);
+
+ /** Translate the (@a wo_x, @a wo_y) point from world coordinates into screen space. */
+void gla2DDrawTranslatePt (gla2DDrawInfo *di, float wo_x, float wo_y, int *sc_x_r, int *sc_y_r);
+
+ /** Translate the @a world point from world coordiantes into screen space. */
+void gla2DDrawTranslatePtv (gla2DDrawInfo *di, float world[2], int screen_r[2]);
+
+ /* Restores the previous OpenGL state and free's the auxilary
+ * gla data.
+ */
+void glaEnd2DDraw (gla2DDrawInfo *di);
+
+#endif /* BIF_GLUTIL_H */
diff --git a/source/blender/include/BIF_graphics.h b/source/blender/include/BIF_graphics.h
new file mode 100644
index 00000000000..2d97ed9d819
--- /dev/null
+++ b/source/blender/include/BIF_graphics.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 *****
+ */
+
+#ifndef BIF_GRAPHICS_H
+#define BIF_GRAPHICS_H
+
+ /* XXX, should move somewhere else, with collected windowing
+ * stuff, to be done once the proper windowing stuff has
+ * been formed.
+ */
+
+enum {
+ CURSOR_VPAINT,
+ CURSOR_FACESEL,
+ CURSOR_WAIT,
+ CURSOR_EDIT,
+ CURSOR_X_MOVE,
+ CURSOR_Y_MOVE,
+ CURSOR_HELP,
+ CURSOR_STD,
+ CURSOR_NONE
+};
+
+void set_cursor(int curs);
+int get_cursor(void);
+
+#endif /* BIF_GRAPHICS_H */
diff --git a/source/blender/include/BIF_imasel.h b/source/blender/include/BIF_imasel.h
new file mode 100644
index 00000000000..ef37ed5858d
--- /dev/null
+++ b/source/blender/include/BIF_imasel.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 BIF_IMASEL_H
+#define BIF_IMASEL_H
+
+struct SpaceImaSel;
+struct OneSelectableIma;
+struct ScrArea;
+struct ImaDir;
+
+void imadir_parent(struct SpaceImaSel *simasel);
+int bitset(int l, int bit);
+void free_sel_ima(struct OneSelectableIma *firstima);
+
+void write_new_pib(struct SpaceImaSel *simasel);
+void free_ima_dir(struct ImaDir *firstdir);
+void check_for_pib(struct SpaceImaSel *simasel);
+void clear_ima_dir(struct SpaceImaSel *simasel);
+void check_ima_dir_name(char *dir);
+int get_ima_dir(char *dirname, int dtype, int *td, struct ImaDir **first);
+void get_next_image(struct SpaceImaSel *simasel);
+void get_file_info(struct SpaceImaSel *simasel);
+void get_pib_file(struct SpaceImaSel *simasel);
+void change_imadir(struct SpaceImaSel *simasel);
+void init_imaselspace(struct ScrArea *sa);
+void check_imasel_copy(struct SpaceImaSel *simasel);
+void free_imasel(struct SpaceImaSel *simasel);
+
+#endif
diff --git a/source/blender/include/BIF_interface.h b/source/blender/include/BIF_interface.h
new file mode 100644
index 00000000000..21060330e81
--- /dev/null
+++ b/source/blender/include/BIF_interface.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 BIF_INTERFACE_H
+#define BIF_INTERFACE_H
+
+struct ID;
+struct ListBase;
+struct ScrArea;
+
+typedef struct uiBut uiBut;
+typedef struct uiBlock uiBlock;
+
+extern int UIfrontbuf;
+
+void uiEmboss(float x1, float y1, float x2, float y2, int sel);
+void uiDrawMenuBox(float minx, float miny, float maxx, float maxy);
+void uiBoundsBlock(struct uiBlock *block, int addval);
+void uiDrawBlock(struct uiBlock *block);
+void uiGetMouse(int win, short *adr);
+void uiComposeLinks(uiBlock *block);
+void uiSetButLock(int val, char *lockstr);
+void uiClearButLock(void);
+int uiDoBlocks(struct ListBase *lb, int event);
+void uiSetCurFont(uiBlock *block, int index);
+void uiDefFont(unsigned int index, void *xl, void *large, void *medium, void *small);
+void uiFreeBlock(uiBlock *block);
+void uiFreeBlocks(struct ListBase *lb);
+void uiFreeBlocksWin(struct ListBase *lb, int win);
+uiBlock *uiNewBlock(struct ListBase *lb, char *name, short dt, short font, short win);
+uiBlock *uiGetBlock(char *name, struct ScrArea *sa);
+uiBut *uiDefBut(uiBlock *block,
+ int type, int retval, char *str,
+ short x1, short y1,
+ short x2, short y2,
+ void *poin,
+ float min, float max,
+ float a1, float a2, char *tip);
+uiBut *uiDefButF(uiBlock *block, int type, int retval, char *str, short x1, short y1, short x2, short y2, float *poin, float min, float max, float a1, float a2, char *tip);
+uiBut *uiDefButI(uiBlock *block, int type, int retval, char *str, short x1, short y1, short x2, short y2, int *poin, float min, float max, float a1, float a2, char *tip);
+uiBut *uiDefButS(uiBlock *block, int type, int retval, char *str, short x1, short y1, short x2, short y2, short *poin, float min, float max, float a1, float a2, char *tip);
+uiBut *uiDefButC(uiBlock *block, int type, int retval, char *str, short x1, short y1, short x2, short y2, char *poin, float min, float max, float a1, float a2, char *tip);
+
+uiBut *uiDefIconBut(uiBlock *block,
+ int type, int retval, int icon,
+ short x1, short y1,
+ short x2, short y2,
+ void *poin,
+ float min, float max,
+ float a1, float a2, char *tip);
+uiBut *uiDefIconButF(uiBlock *block, int type, int retval, int icon, short x1, short y1, short x2, short y2, float *poin, float min, float max, float a1, float a2, char *tip);
+uiBut *uiDefIconButI(uiBlock *block, int type, int retval, int icon, short x1, short y1, short x2, short y2, int *poin, float min, float max, float a1, float a2, char *tip);
+uiBut *uiDefIconButS(uiBlock *block, int type, int retval, int icon, short x1, short y1, short x2, short y2, short *poin, float min, float max, float a1, float a2, char *tip);
+uiBut *uiDefIconButC(uiBlock *block, int type, int retval, int icon, short x1, short y1, short x2, short y2, char *poin, float min, float max, float a1, float a2, char *tip);
+
+typedef void (*uiIDPoinFuncFP) (char *str, struct ID **idpp);
+void uiDefIDPoinBut(struct uiBlock *block,
+ uiIDPoinFuncFP func, int retval, char *str,
+ short x1, short y1,
+ short x2, short y2,
+ void *idpp, char *tip);
+
+typedef uiBlock* (*uiBlockFuncFP) (void *arg1);
+void uiDefBlockBut(uiBlock *block, uiBlockFuncFP func, void *func_arg1, char *str, short x1, short y1, short x2, short y2, char *tip);
+
+void uiDefKeyevtButS(uiBlock *block, int retval, char *str, short x1, short y1, short x2, short y2, short *spoin, char *tip);
+
+void uiAutoBlock(struct uiBlock *block,
+ float minx, float miny,
+ float sizex, float sizey, int flag);
+void uiSetButLink(struct uiBut *but,
+ void **poin,
+ void ***ppoin,
+ short *tot,
+ int from, int to);
+
+int uiBlocksGetYMin (ListBase *lb);
+int uiBlockGetCol (uiBlock *block);
+void* uiBlockGetCurFont (uiBlock *block);
+
+void uiBlockSetCol (uiBlock *block, int col);
+void uiBlockSetEmboss (uiBlock *block, int emboss);
+void uiBlockSetDirection (uiBlock *block, int direction);
+void uiBlockSetFlag (uiBlock *block, int flag);
+void uiBlockSetXOfs (uiBlock *block, int xofs);
+
+int uiButGetRetVal (uiBut *but);
+
+void uiButSetFlag (uiBut *but, int flag);
+
+void uiBlockSetButmFunc (uiBlock *block, void (*butmfunc)(void *arg, int but_a2), void *arg);
+
+void uiBlockSetFunc (uiBlock *block, void (*func)(void *arg1, void *arg2), void *arg1, void *arg2);
+void uiButSetFunc (uiBut *but, void (*func)(void *arg1, void *arg2), void *arg1, void *arg2);
+
+short pupmenu(char *instr);
+short pupmenu_col(char *instr, int maxrow);
+
+#endif /* BIF_INTERFACE_H */
diff --git a/source/blender/include/BIF_keyval.h b/source/blender/include/BIF_keyval.h
new file mode 100644
index 00000000000..94fa8f09bc5
--- /dev/null
+++ b/source/blender/include/BIF_keyval.h
@@ -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 *****
+ */
+
+#ifndef BIF_KEYVAL_H
+#define BIF_KEYVAL_H
+
+char *key_event_to_string(unsigned short event);
+
+#endif
diff --git a/source/blender/include/BIF_mainqueue.h b/source/blender/include/BIF_mainqueue.h
new file mode 100644
index 00000000000..e649748cedf
--- /dev/null
+++ b/source/blender/include/BIF_mainqueue.h
@@ -0,0 +1,46 @@
+/*
+ * Central queue handling functions.
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BIF_MAINQUEUE_H
+#define BIF_MAINQUEUE_H
+
+#define MAXQUEUE 256
+
+unsigned short mainqtest (void);
+unsigned short mainqread (short *val, char *ascii);
+void mainqenter (unsigned short event, short val);
+void mainqenter_ext (unsigned short event, short val, char ascii);
+void mainqpushback (unsigned short event, short val, char ascii);
+
+#endif /* BIF_MAINQUEUE_H */
diff --git a/source/blender/include/BIF_mywindow.h b/source/blender/include/BIF_mywindow.h
new file mode 100644
index 00000000000..1e581b3dc4b
--- /dev/null
+++ b/source/blender/include/BIF_mywindow.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 *****
+ * These are the protos for mywindow.c -- an emulation of the
+ * (obsolete) IrisGL command set
+ */
+
+#ifndef BIF_MYWINDOW_H
+#define BIF_MYWINDOW_H
+
+struct rcti;
+
+/*---*/
+
+int mywinget(void);
+void mywinclose(int winid);
+void mywinposition(int winid,
+ int xmin, int xmax,
+ int ymin, int ymax);
+/*---*/
+
+int bwin_qtest(int winid);
+unsigned short bwin_qread(int winid, short *val_r, char *ascii_r);
+void bwin_qadd(int winid, unsigned short event, short val, char ascii);
+
+/*---*/
+
+void bwin_load_viewmatrix(int winid, float mat[][4]);
+void bwin_load_winmatrix(int winid, float mat[][4]);
+
+void bwin_get_viewmatrix(int winid, float mat[][4]);
+void bwin_get_winmatrix(int winid, float mat[][4]);
+
+void bwin_ortho(int winid, float x1, float x2, float y1, float y2, float n, float f);
+void bwin_ortho2(int win, float x1, float x2, float y1, float y2);
+void bwin_frustum(int winid, float x1, float x2, float y1, float y2, float n, float f);
+
+void bwin_getsize(int winid, int *x, int *y);
+void bwin_getsuborigin(int winid, int *x, int *y);
+void bwin_get_rect(int winid, struct rcti *rect_r);
+void bwin_getsinglematrix(int winid, float mat[][4]);
+void bwin_clear_viewmat(int winid);
+
+int myswinopen(int parentid, int xmin, int xmax, int ymin, int ymax);
+void myswapbuffers(void);
+
+void mygetmatrix(float mat[][4]);
+void mymultmatrix(float [][4]);
+void myloadmatrix(float mat[][4]);
+void mywinset(int wid);
+void myortho(float x1, float x2, float y1, float y2, float n, float f);
+void myortho2(float x1, float x2, float y1, float y2);
+void mywindow(float x1, float x2, float y1, float y2, float n, float f);
+void mygetsingmatrix(float (*)[4]);
+
+void setlinestyle(int nr);
+
+void BIF_wait_for_statechange(void);
+
+#define L_MOUSE 1
+#define M_MOUSE 2
+#define R_MOUSE 4
+short get_mbut(void);
+short get_qual(void);
+void getmouse(short *mval);
+
+void warp_pointer(int x, int y);
+
+int framebuffer_to_index(unsigned int col);
+unsigned int index_to_framebuffer(int index);
+
+int mywin_inmenu(void);
+void mywin_getmenu_rect(int *x, int *y, int *sx, int *sy);
+
+void my_put_frontbuffer_image(void);
+void my_get_frontbuffer_image(int x, int y, int sx, int sy);
+
+#endif
+
diff --git a/source/blender/include/BIF_oops.h b/source/blender/include/BIF_oops.h
new file mode 100644
index 00000000000..9d7aeffbfe8
--- /dev/null
+++ b/source/blender/include/BIF_oops.h
@@ -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 *****
+ */
+
+#ifndef BIF_OOPS_H
+#define BIF_OOPS_H
+
+struct Curve;
+struct Oops;
+struct OopsLink;
+struct SpaceOops;
+struct Material;
+struct Mesh;
+struct MetaBall;
+struct Object;
+void add_curve_oopslinks(struct Curve *cu, struct Oops *oops, short flag);
+void add_from_link(struct Oops *from, struct Oops *oops);
+void add_material_oopslinks(struct Material *ma, struct Oops *oops, short flag);
+void add_mball_oopslinks(struct MetaBall *mb, struct Oops *oops, short flag);
+void add_mesh_oopslinks(struct Mesh *me, struct Oops *oops, short flag);
+void add_object_oopslinks(struct Object *ob, struct Oops *oops, short flag);
+struct Oops *add_oops(void *id);
+struct OopsLink *add_oopslink(char *name, struct Oops *oops, short type, void *from, float xof, float yof);
+struct Oops *add_test_oops(void *id); /* incl links */
+void add_texture_oops(struct Material *ma);
+void build_oops(void);
+struct Oops *find_oops(ID *id);
+void free_oops(struct Oops *oops); /* ook oops zelf */
+void free_oopspace(struct SpaceOops *so);
+void new_oops_location(struct Oops *);
+int oops_test_overlap(struct Oops *test);
+int oops_test_overlaphide(struct Oops *test);
+float oopslink_totlen(struct Oops *oops);
+void shrink_oops(void);
+void shuffle_oops(void);
+int test_oops(struct Oops *oops);
+void test_oopslink(struct OopsLink *ol);
+void test_oopslinko(struct OopsLink *ol);
+
+#endif
diff --git a/source/blender/include/BIF_poseobject.h b/source/blender/include/BIF_poseobject.h
new file mode 100644
index 00000000000..872584edfe9
--- /dev/null
+++ b/source/blender/include/BIF_poseobject.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 *****
+ */
+
+#ifndef BIF_POSEOBJECT
+#define BIF_POSEOBJECT
+
+/**
+ * Activates posemode
+ */
+void enter_posemode(void);
+
+/**
+ * Provides the current object the opportunity to specify
+ * which channels to key in the current pose (if any).
+ * If an object provides its own filter, it must clear
+ * then POSE_KEY flags of unwanted channels, as well as
+ * setting the flags for desired channels.
+ *
+ * Default behaviour is to key all channels.
+ */
+void filter_pose_keys(void);
+
+/**
+ * Deactivates posemode
+ * @param freedata 0 or 1 value indicating that posedata should be deleted
+ */
+void exit_posemode(int freedata);
+
+/**
+ * Removes unreferenced pose channels from an object
+ * @param ob Object to check
+ */
+void collect_pose_garbage(struct Object *ob);
+
+#endif
+
diff --git a/source/blender/include/BIF_previewrender.h b/source/blender/include/BIF_previewrender.h
new file mode 100644
index 00000000000..0e4e1c9d71c
--- /dev/null
+++ b/source/blender/include/BIF_previewrender.h
@@ -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 *****
+ */
+struct SpaceButs;
+
+void BIF_preview_changed (struct SpaceButs *area);
+void BIF_previewrender (struct SpaceButs *area);
+void BIF_previewdraw (struct SpaceButs *area);
+
+
diff --git a/source/blender/include/BIF_renderwin.h b/source/blender/include/BIF_renderwin.h
new file mode 100644
index 00000000000..a6ac7c707ea
--- /dev/null
+++ b/source/blender/include/BIF_renderwin.h
@@ -0,0 +1,49 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+struct ScrArea;
+
+void calc_renderwin_rectangle(int posmask, int renderpos_r[2], int rendersize_r[2]);
+
+void BIF_close_render_display(void);
+
+void BIF_do_render(int anim);
+
+/**
+ * @param v3d The View3D space to render.
+ */
+void BIF_do_ogl_render(struct View3D *v3d, int anim);
+
+void BIF_renderwin_set_for_ogl_render(void);
+void BIF_renderwin_set_custom_cursor(unsigned char mask[16][2], unsigned char bitmap[16][2]);
+
+void BIF_swap_render_rects(void);
+void BIF_toggle_render_display(void);
diff --git a/source/blender/include/BIF_resources.h b/source/blender/include/BIF_resources.h
new file mode 100644
index 00000000000..c379c74c311
--- /dev/null
+++ b/source/blender/include/BIF_resources.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 *****
+ */
+
+#ifndef BIF_RESOURCES_H
+#define BIF_RESOURCES_H
+
+typedef enum {
+#define BIFICONID_FIRST (ICON_VIEW3D)
+ ICON_VIEW3D,
+ ICON_IPO,
+ ICON_OOPS,
+ ICON_BUTS,
+ ICON_FILESEL,
+ ICON_IMAGE_COL,
+ ICON_INFO,
+ ICON_SEQUENCE,
+ ICON_TEXT,
+ ICON_IMASEL,
+ ICON_SOUND,
+ ICON_ACTION,
+ ICON_NLA,
+ ICON_VIEWZOOM,
+ ICON_VIEWMOVE,
+ ICON_HOME,
+ ICON_CLIPUV_DEHLT,
+ ICON_CLIPUV_HLT,
+ ICON_SOME_WACKY_VERTS_AND_LINES,
+ ICON_A_WACKY_VERT_AND_SOME_LINES,
+ ICON_VPAINT_COL,
+
+ ICON_ORTHO,
+ ICON_PERSP,
+ ICON_CAMERA,
+ ICON_BLANK1,
+ ICON_BBOX,
+ ICON_WIRE,
+ ICON_SOLID,
+ ICON_SMOOTH,
+ ICON_POTATO,
+ ICON_BLANK2,
+ ICON_NORMALVIEW,
+ ICON_LOCALVIEW,
+ ICON_UNUSEDVIEW,
+ ICON_BLANK3,
+ ICON_SORTALPHA,
+ ICON_SORTTIME,
+ ICON_SORTSIZE,
+ ICON_LONGDISPLAY,
+ ICON_SHORTDISPLAY,
+ ICON_BLANK4,
+ ICON_BLANK5,
+
+ ICON_VIEW_AXIS_ALL,
+ ICON_VIEW_AXIS_NONE,
+ ICON_VIEW_AXIS_NONE2,
+ ICON_VIEW_AXIS_TOP,
+ ICON_VIEW_AXIS_FRONT,
+ ICON_VIEW_AXIS_SIDE,
+ ICON_POSE_DEHLT,
+ ICON_POSE_HLT,
+ ICON_BORDERMOVE,
+ ICON_MAYBE_ITS_A_LASSO,
+ ICON_BLANK6,
+ ICON_ROTATE,
+ ICON_CURSOR,
+ ICON_ROTATECOLLECTION,
+ ICON_ROTATECENTER,
+ ICON_BLANK7,
+ ICON_BLANK8,
+ ICON_BLANK9,
+ ICON_BLANK10,
+ ICON_BLANK11,
+ ICON_BLANK12,
+
+ ICON_DOTSUP,
+ ICON_DOTSDOWN,
+ ICON_BLANK13,
+ ICON_AXIS_SIDE,
+ ICON_AXIS_FRONT,
+ ICON_AXIS_TOP,
+ ICON_BLANK14,
+ ICON_BLANK15,
+ ICON_BLANK16,
+ ICON_BLANK17,
+ ICON_BLANK18,
+ ICON_ENVMAP,
+ ICON_TRANSP_HLT,
+ ICON_TRANSP_DEHLT,
+ ICON_RADIO_DEHLT,
+ ICON_RADIO_HLT,
+ ICON_TPAINT_DEHLT,
+ ICON_TPAINT_HLT,
+ ICON_WPAINT_DEHLT,
+ ICON_WPAINT_HLT,
+ ICON_BLANK21,
+
+ ICON_X,
+ ICON_GO_LEFT,
+ ICON_NO_GO_LEFT,
+ ICON_UNLOCKED,
+ ICON_LOCKED,
+ ICON_PARLIB,
+ ICON_DATALIB,
+ ICON_AUTO,
+ ICON_MATERIAL_DEHLT2,
+ ICON_RING,
+ ICON_GRID,
+ ICON_PROPEDIT,
+ ICON_KEEPRECT,
+ ICON_DESEL_CUBE_VERTS,
+ ICON_EDITMODE_DEHLT,
+ ICON_EDITMODE_HLT,
+ ICON_VPAINT_DEHLT,
+ ICON_VPAINT_HLT,
+ ICON_FACESEL_DEHLT,
+ ICON_FACESEL_HLT,
+ ICON_BLANK22,
+
+ ICON_HELP,
+ ICON_ERROR,
+ ICON_FOLDER_DEHLT,
+ ICON_FOLDER_HLT,
+ ICON_BLUEIMAGE_DEHLT,
+ ICON_BLUEIMAGE_HLT,
+ ICON_BPIBFOLDER_DEHLT,
+ ICON_BPIBFOLDER_HLT,
+ ICON_BPIBFOLDER_ERR,
+ ICON_UGLY_GREEN_RING,
+ ICON_GHOST,
+ ICON_SHARPCURVE,
+ ICON_SMOOTHCURVE,
+ ICON_BLANK23,
+ ICON_BLANK24,
+ ICON_BLANK25,
+ ICON_BLANK26,
+ ICON_BPIBFOLDER_X,
+ ICON_BPIBFOLDERGREY,
+ ICON_MAGNIFY,
+ ICON_INFO2,
+
+ ICON_RIGHTARROW,
+ ICON_DOWNARROW_HLT,
+ ICON_ROUNDBEVELTHING,
+ ICON_FULLTEXTURE,
+ ICON_REDPUBLISHERHALFTHINGY,
+ ICON_PUBLISHER,
+ ICON_CKEY,
+ ICON_CHECKBOX_DEHLT,
+ ICON_CHECKBOX_HLT,
+ ICON_LINK,
+ ICON_INLINK,
+ ICON_BEVELBUT_HLT,
+ ICON_BEVELBUT_DEHLT,
+ ICON_PASTEDOWN,
+ ICON_COPYDOWN,
+ ICON_CONSTANT,
+ ICON_LINEAR,
+ ICON_CYCLIC,
+ ICON_KEY_DEHLT,
+ ICON_KEY_HLT,
+ ICON_GRID2,
+
+ ICON_EYE,
+ ICON_LAMP,
+ ICON_MATERIAL,
+ ICON_TEXTURE,
+ ICON_ANIM,
+ ICON_WORLD,
+ ICON_SCENE,
+ ICON_EDIT,
+ ICON_GAME,
+ ICON_PAINT,
+ ICON_RADIO,
+ ICON_SCRIPT,
+ ICON_SPEAKER,
+ ICON_PASTEUP,
+ ICON_COPYUP,
+ ICON_PASTEFLIPUP,
+ ICON_PASTEFLIPDOWN,
+ ICON_CYCLICLINEAR,
+ ICON_PIN_DEHLT,
+ ICON_PIN_HLT,
+ ICON_LITTLEGRID,
+
+ ICON_FULLSCREEN,
+ ICON_SPLITSCREEN,
+ ICON_RIGHTARROW_THIN,
+ ICON_BLANK27,
+ ICON_BLANK28,
+ ICON_SCENE_SEPIA,
+ ICON_SCENE_DEHLT,
+ ICON_OBJECT,
+ ICON_MESH,
+ ICON_CURVE,
+ ICON_MBALL,
+ ICON_LATTICE,
+ ICON_LAMP_DEHLT,
+ ICON_MATERIAL_DEHLT,
+ ICON_TEXTURE_DEHLT,
+ ICON_IPO_DEHLT,
+ ICON_LIBRARY_DEHLT,
+ ICON_IMAGE_DEHLT,
+ ICON_BLANK29,
+ ICON_BLANK30,
+ ICON_BLANK31,
+
+ ICON_BLENDER,
+ ICON_PACKAGE,
+ ICON_UGLYPACKAGE,
+ ICON_MATPLANE,
+ ICON_MATSPHERE,
+ ICON_MATCUBE,
+ ICON_SCENE_HLT,
+ ICON_OBJECT_HLT,
+ ICON_MESH_HLT,
+ ICON_CURVE_HLT,
+ ICON_MBALL_HLT,
+ ICON_LATTICE_HLT,
+ ICON_LAMP_HLT,
+ ICON_MATERIAL_HLT,
+ ICON_TEXTURE_HLT,
+ ICON_IPO_HLT,
+ ICON_LIBRARY_HLT,
+ ICON_IMAGE_HLT,
+ ICON_CONSTRAINT,
+ ICON_BLANK32,
+ ICON_BLANK33,
+#define BIFICONID_LAST (ICON_BLANK33)
+#define BIFNICONIDS (BIFICONID_LAST-BIFICONID_FIRST + 1)
+} BIFIconID;
+
+typedef enum {
+#define BIFCOLORSHADE_FIRST (COLORSHADE_DARK)
+ COLORSHADE_DARK,
+ COLORSHADE_GREY,
+ COLORSHADE_MEDIUM,
+ COLORSHADE_HILITE,
+ COLORSHADE_LIGHT,
+ COLORSHADE_WHITE,
+#define BIFCOLORSHADE_LAST (COLORSHADE_WHITE)
+#define BIFNCOLORSHADES (BIFCOLORSHADE_LAST-BIFCOLORSHADE_FIRST + 1)
+} BIFColorShade;
+
+typedef enum {
+#define BIFCOLORID_FIRST (BUTGREY)
+ BUTGREY,
+ BUTGREEN,
+ BUTBLUE,
+ BUTSALMON,
+ MIDGREY,
+ BUTPURPLE,
+ BUTYELLOW,
+ REDALERT,
+ BUTRUST,
+ BUTWHITE,
+ BUTDBLUE,
+ BUTPINK,
+ BUTDPINK,
+ BUTMACTIVE,
+
+ BUTIPO,
+ BUTAUDIO,
+ BUTCAMERA,
+ BUTRANDOM,
+ BUTEDITOBJECT,
+ BUTPROPERTY,
+ BUTSCENE,
+ BUTMOTION,
+ BUTMESSAGE,
+ BUTACTION,
+ BUTCD,
+ BUTGAME,
+ BUTVISIBILITY,
+ BUTYUCK,
+ BUTSEASICK,
+ BUTCHOKE,
+ BUTIMPERIAL,
+#define BIFCOLORID_LAST (BUTIMPERIAL)
+#define BIFNCOLORIDS (BIFCOLORID_LAST-BIFCOLORID_FIRST + 1)
+} BIFColorID;
+
+void BIF_resources_init (void);
+void BIF_resources_free (void);
+
+int BIF_get_icon_width (BIFIconID icon);
+int BIF_get_icon_height (BIFIconID icon);
+void BIF_draw_icon (BIFIconID icon);
+void BIF_draw_icon_blended (BIFIconID icon, BIFColorID color, BIFColorShade shade);
+
+void BIF_set_color (BIFColorID color, BIFColorShade shade);
+
+#endif /* BIF_ICONS_H */
diff --git a/source/blender/include/BIF_scrarea.h b/source/blender/include/BIF_scrarea.h
new file mode 100644
index 00000000000..2bd10278ddd
--- /dev/null
+++ b/source/blender/include/BIF_scrarea.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 *****
+ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct ScrArea;
+
+ /**
+ * Finds the first spacedata of @a type within
+ * the scrarea.
+ */
+void *scrarea_find_space_of_type(ScrArea *sa, int type);
+
+int scrarea_get_win_x (struct ScrArea *sa);
+int scrarea_get_win_y (struct ScrArea *sa);
+int scrarea_get_win_width (struct ScrArea *sa);
+int scrarea_get_win_height (struct ScrArea *sa);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/include/BIF_screen.h b/source/blender/include/BIF_screen.h
new file mode 100644
index 00000000000..81b2874b217
--- /dev/null
+++ b/source/blender/include/BIF_screen.h
@@ -0,0 +1,124 @@
+/* replacement for screen.h */
+/*
+ *
+ * Leftovers here are actually editscreen.c thingies
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BIF_SCREEN_H
+#define BIF_SCREEN_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* externs in editscreen.c */
+extern int displaysizex, displaysizey;
+extern struct ScrArea *curarea;
+
+struct View3D;
+struct bScreen;
+struct ScrArea;
+struct ScrVert;
+struct ScrEdge;
+struct ListBase;
+
+struct View3D *find_biggest_view3d(void);
+struct ScrArea *find_biggest_area_of_type(int spacecode);
+struct ScrArea *find_biggest_area(void);
+
+void scrarea_queue_redraw(struct ScrArea *area);
+void scrarea_queue_winredraw(struct ScrArea *area);
+void scrarea_queue_headredraw(struct ScrArea *area);
+
+void duplicate_screen(void);
+void init_screen_cursors(void);
+void set_timecursor(int nr);
+void waitcursor(int val);
+void wich_cursor(struct ScrArea *sa);
+void setcursor_space(int spacetype, short cur);
+void getmouseco_sc(short *mval);
+void getmouseco_areawin(short *mval);
+void getmouseco_headwin(short *mval);
+unsigned short qtest(void);
+int anyqtest(void);
+void areawinset(short win);
+void headerbox(int selcol, int width);
+void defheaddraw(void);
+void defheadchange(void);
+unsigned short winqtest(struct ScrArea *sa);
+unsigned short headqtest(struct ScrArea *sa);
+void winqdelete(struct ScrArea *sa);
+void winqclear(struct ScrArea *sa);
+void addqueue(short win, unsigned short event, short val);
+void addafterqueue(short win, unsigned short event, short val);
+void add_readfile_event(char *filename);
+short ext_qtest(void);
+unsigned short extern_qread(short *val);
+unsigned short extern_qread_ext(short *val, char *ascii);
+void markdirty_all(void);
+void screen_swapbuffers(void);
+void set_debug_swapbuffers_ovveride(struct bScreen *sc, int mode);
+int is_allowed_to_change_screen(struct bScreen *newp);
+void splash(void * data, int datasizei, char * string);
+void screenmain(void);
+void getdisplaysize(void);
+void setprefsize(int stax, int stay, int sizx, int sizy);
+void calc_arearcts(struct ScrArea *sa);
+void resize_screen(int x, int y, int w, int h);
+struct ScrArea *closest_bigger_area(void);
+int mywinopen(int mode, short posx, short posy, short sizex, short sizey);
+void setscreen(struct bScreen *sc);
+void area_fullscreen(void);
+int select_area(int spacetype);
+void drawedge(short x1, short y1, short x2, short y2);
+void drawscreen(void);
+struct bScreen *default_twosplit(void);
+void initscreen(void);
+void unlink_screen(struct bScreen *sc);
+void reset_autosave(void);
+int area_is_active_area(struct ScrArea *area);
+
+ /***/
+
+/**
+ * Draw @a text in the header of each info window
+ * of the given screen.
+ */
+void screen_draw_info_text(struct bScreen *sc, char *text);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BIF_SCREEN_H */
diff --git a/source/blender/include/BIF_space.h b/source/blender/include/BIF_space.h
new file mode 100644
index 00000000000..68295db2ddb
--- /dev/null
+++ b/source/blender/include/BIF_space.h
@@ -0,0 +1,94 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BIF_SPACE_H
+#define BIF_SPACE_H
+
+struct ListBase;
+struct ScrArea;
+struct SpaceButs;
+struct View2D;
+
+#define REMAKEIPO 1
+#define OOPS_TEST 2
+#define REMAKEALLIPO 3 /* Reevan's ipo fixing test */
+
+void scrarea_do_windraw (struct ScrArea *sa);
+void scrarea_do_winchange (struct ScrArea *sa);
+void scrarea_do_winhandle (struct ScrArea *sa, unsigned short event, short val, char ascii);
+void scrarea_do_headdraw (struct ScrArea *sa);
+void scrarea_do_headchange (struct ScrArea *sa);
+
+/* space.c */
+extern void space_set_commmandline_options(void);
+extern void allqueue(unsigned short event, short val);
+extern void allspace(unsigned short event, short val);
+extern void changebutspace(void);
+extern void changeview2d(void);
+extern void changeview3d(void);
+extern void copy_view3d_lock(short val);
+extern void drawemptyspace(void);
+extern void drawinfospace(void);
+extern void duplicatespacelist(struct ScrArea *area, struct ListBase *lb1, struct ListBase *lb2);
+extern void extern_set_butspace(int fkey);
+extern void force_draw(void);
+extern void force_draw_all(void);
+extern void force_draw_plus(int type);
+extern void freespacelist(struct ListBase *lb);
+extern void handle_view3d_lock(void);
+extern void init_butspace(struct ScrArea *sa);
+extern void init_filespace(struct ScrArea *sa);
+extern void init_imagespace(struct ScrArea *sa);
+extern void init_oopsspace(struct ScrArea *sa);
+extern void init_nlaspace(struct ScrArea *sa);
+extern void init_seqspace(struct ScrArea *sa);
+extern void init_v2d_oops(struct View2D *v2d);
+extern void initipo(struct ScrArea *sa);
+extern void initview3d(struct ScrArea *sa);
+extern void newspace(struct ScrArea *sa, int type);
+extern void set_rects_butspace(struct SpaceButs *buts);
+extern void winqread3d(unsigned short event, short val, char ascii);
+extern void winqreadbutspace(unsigned short event, short val, char ascii);
+extern void winqreadimagespace(unsigned short event, short val, char ascii);
+extern void winqreadinfospace(unsigned short event, short val, char ascii);
+extern void winqreadipo(unsigned short event, short val, char ascii);
+extern void winqreadoopsspace(unsigned short event, short val, char ascii);
+extern void winqreadnlaspace(unsigned short event, short val, char ascii);
+extern void winqreadsequence(unsigned short event, short val, char ascii);
+extern void test_butspace(void);
+extern void start_game(void);
+
+extern void mainwindow_raise(void);
+extern void mainwindow_make_active(void);
+extern void mainwindow_close(void);
+
+#endif
diff --git a/source/blender/include/BIF_spacetypes.h b/source/blender/include/BIF_spacetypes.h
new file mode 100644
index 00000000000..03dd6de22b1
--- /dev/null
+++ b/source/blender/include/BIF_spacetypes.h
@@ -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 *****
+ */
+struct ScrArea;
+
+typedef struct _SpaceType SpaceType;
+
+typedef void (*SpaceDrawFP) (void);
+typedef void (*SpaceChangeFP) (void);
+typedef void (*SpaceHandleFP) (unsigned short evt, short val, char ascii);
+
+ /***/
+
+SpaceType* spacetype_new (char *name);
+
+void spacetype_set_winfuncs (SpaceType *st, SpaceDrawFP draw, SpaceChangeFP change, SpaceHandleFP handle);
+
+ /***/
+
+SpaceType *spaceaction_get_type (void);
+SpaceType *spacebuts_get_type (void);
+SpaceType *spacefile_get_type (void);
+SpaceType *spaceimage_get_type (void);
+SpaceType *spaceimasel_get_type (void);
+SpaceType *spaceinfo_get_type (void);
+SpaceType *spaceipo_get_type (void);
+SpaceType *spacenla_get_type (void);
+SpaceType *spaceoops_get_type (void);
+SpaceType *spaceseq_get_type (void);
+SpaceType *spacesound_get_type (void);
+SpaceType *spacetext_get_type (void);
+SpaceType *spaceview3d_get_type (void);
diff --git a/source/blender/include/BIF_tbcallback.h b/source/blender/include/BIF_tbcallback.h
new file mode 100644
index 00000000000..34f39736759
--- /dev/null
+++ b/source/blender/include/BIF_tbcallback.h
@@ -0,0 +1,41 @@
+/* $Id$
+*/
+/*
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+/* defines callback structure for toolbox menu */
+
+typedef struct _TBcallback {
+ char *desc;
+ char *key;
+ void (*cb)(int v); /* callback function takes value */
+ int val;
+} TBcallback;
+
+typedef TBcallback * (*Tbox_callbackfunc)(int l, int x);
+void tboxSetCallback(Tbox_callbackfunc f);
diff --git a/source/blender/include/BIF_toets.h b/source/blender/include/BIF_toets.h
new file mode 100644
index 00000000000..50c04a1ae0d
--- /dev/null
+++ b/source/blender/include/BIF_toets.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 *****
+ */
+
+#ifndef BIF_TOETS_H
+#define BIF_TOETS_H
+
+void BIF_save_rendered_image(void);
+
+int save_image_filesel_str(char *str);
+int blenderqread(unsigned short event, short val);
+void persptoetsen(unsigned short event); /* dutch rules man */
+int untitled(char *name);
+
+#endif
diff --git a/source/blender/include/BIF_toolbox.h b/source/blender/include/BIF_toolbox.h
new file mode 100644
index 00000000000..c8ad8f57684
--- /dev/null
+++ b/source/blender/include/BIF_toolbox.h
@@ -0,0 +1,122 @@
+/* toolbox (SPACEKEY) related
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+ /* TBOXX: breedte in pixels */
+#define TBOXXL 80
+#define TBOXXR 170
+#define TBOXX (TBOXXL+TBOXXR)
+ /* TBOXEL: aantal elementen onder elkaar */
+#define TBOXEL 14
+ /* TBOXH: hoogte van 1 element */
+#define TBOXH 20
+#define TBOXY TBOXH*TBOXEL
+
+#define TBOXBLACK 1
+#define TBOXDGREY 2
+#define TBOXWHITE 3
+#define TBOXGREY 4
+#define TBOXLGREY 5
+
+/* toolbox menu code defines
+ -> SPACE->(MAIN_ENTRY) */
+#ifdef MAART
+enum {
+ TBOX_MAIN_FILE,
+ TBOX_MAIN_ADD,
+ TBOX_MAIN_EDIT,
+ TBOX_MAIN_OBJECT1,
+ TBOX_MAIN_OBJECT2,
+ TBOX_MAIN_MESH,
+ TBOX_MAIN_CURVE,
+ TBOX_MAIN_KEY,
+ TBOX_MAIN_RENDER,
+ TBOX_MAIN_VIEW,
+ TBOX_MAIN_PYTOOL = 13
+};
+
+#else
+enum {
+ TBOX_MAIN_ADD,
+ TBOX_MAIN_FILE,
+ TBOX_MAIN_EDIT,
+ TBOX_MAIN_OBJECT1,
+ TBOX_MAIN_OBJECT2,
+ TBOX_MAIN_MESH,
+ TBOX_MAIN_CURVE,
+ TBOX_MAIN_KEY,
+ TBOX_MAIN_RENDER,
+ TBOX_MAIN_VIEW,
+ TBOX_MAIN_PYTOOL = 13
+};
+#endif
+
+/* protos */
+
+/* toolbox.c */
+void ColorFunc (int i);
+void mygetcursor (short int *index);
+void tbox_setinfo (int x, int y);
+void dummy (void);
+void bgnpupdraw (int startx, int starty, int endx, int endy);
+void endpupdraw (void);
+void asciitoraw (int ch, short unsigned int *event, short unsigned int *qual);
+void tbox_execute (void);
+void tbox_getmouse (short int *mval);
+void tbox_setmain (int val);
+void bgntoolbox (void);
+void endtoolbox (void);
+void tbox_embossbox (short int x1, short int y1, short int x2, short int y2, short int type);
+void tbox_drawelem_body (int x, int y, int type);
+void tbox_drawelem_text (int x, int y, int type);
+void tbox_drawelem (int x, int y, int type);
+void tbox_getactive (int *x, int *y);
+void drawtoolbox (void);
+void toolbox (void);
+
+void notice (char *str, ...);
+void error (char *fmt, ...);
+
+int saveover (char *filename);
+int okee (char *fmt, ...);
+
+short button (short *var, short min, short max, char *str);
+short fbutton (float *var, float min, float max, char *str);
+short sbutton (char *var, float min, float max, char *str); /* __NLA */
+int movetolayer_buts (unsigned int *lay);
+void draw_numbuts_tip (char *str, int x1, int y1, int x2, int y2);
+int do_clever_numbuts (char *name, int tot, int winevent);
+void add_numbut (int nr, int type, char *str, float min, float max, void *poin, char *tip);
+void clever_numbuts (void);
+void replace_names_but (void);
+
+void BIF_screendump(void);
+void write_screendump(char *name);
diff --git a/source/blender/include/BIF_usiblender.h b/source/blender/include/BIF_usiblender.h
new file mode 100644
index 00000000000..6cf5c1e8d9d
--- /dev/null
+++ b/source/blender/include/BIF_usiblender.h
@@ -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 *****
+ */
+
+#ifndef BIF_USIBLENDER_H
+#define BIF_USIBLENDER_H
+
+void exit_usiblender(void);
+
+void BIF_init(void);
+
+void BIF_read_file (char *name);
+int BIF_read_homefile (void);
+void BIF_read_autosavefile (void);
+
+void BIF_write_file (char *target);
+void BIF_write_homefile (void);
+void BIF_write_autosave (void);
+
+#endif
diff --git a/source/blender/include/BIF_writeavicodec.h b/source/blender/include/BIF_writeavicodec.h
new file mode 100644
index 00000000000..e096cbd27f3
--- /dev/null
+++ b/source/blender/include/BIF_writeavicodec.h
@@ -0,0 +1,44 @@
+/**
+ * Functions for writing windows avi-format files.
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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
+
+void start_avi_codec(void);
+void append_avi_codec(int frame);
+void end_avi_codec(void);
+int get_codec_settings(void);
+
+#endif
+
diff --git a/source/blender/include/BIF_writeimage.h b/source/blender/include/BIF_writeimage.h
new file mode 100644
index 00000000000..92fcbb4dc84
--- /dev/null
+++ b/source/blender/include/BIF_writeimage.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 BIF_WRITEIMAGE_H
+#define BIF_WRITEIMAGE_H
+
+struct ImBuf;
+struct EnvMap;
+
+int BIF_write_ibuf(struct ImBuf *ibuf, char *name);
+void BIF_save_envmap(struct EnvMap *env, char *str);
+
+#endif
diff --git a/source/blender/include/BIF_writemovie.h b/source/blender/include/BIF_writemovie.h
new file mode 100644
index 00000000000..e8985c68e39
--- /dev/null
+++ b/source/blender/include/BIF_writemovie.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 *****
+ */
+
+#ifndef BIF_WRITEMOVIE_H
+#define BIF_WRITEMOVIE_H
+
+void start_movie(void);
+void append_movie(int fnum);
+void end_movie(void);
+
+#endif
diff --git a/source/blender/include/BSE_buttons.h b/source/blender/include/BSE_buttons.h
new file mode 100644
index 00000000000..4c72e4309df
--- /dev/null
+++ b/source/blender/include/BSE_buttons.h
@@ -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 *****
+ */
+
+#ifndef BSE_BUTTONS_H
+#define BSE_BUTTONS_H
+
+struct ID;
+
+void test_meshpoin_but(char *name, struct ID **idpp);
+void test_obpoin_but(char *name, struct ID **idpp);
+void test_scenepoin_but(char *name, struct ID **idpp);
+void test_matpoin_but(char *name, struct ID **idpp);
+void test_scriptpoin_but(char *name, struct ID **idpp);
+void test_actionpoin_but(char *name, ID **idpp); /* __ NLA */
+void clever_numbuts_buts();
+
+#endif /* BSE_BUTTONS_H */
diff --git a/source/blender/include/BSE_drawimasel.h b/source/blender/include/BSE_drawimasel.h
new file mode 100644
index 00000000000..73abe1e9ece
--- /dev/null
+++ b/source/blender/include/BSE_drawimasel.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 *****
+ */
+
+#ifndef BSE_DRAWIMASEL_H
+#define BSE_DRAWIMASEL_H
+
+struct SpaceImaSel;
+
+void viewgate(short sx, short sy, short ex, short ey);
+void areaview (void);
+void calc_hilite(struct SpaceImaSel *simasel);
+void make_sima_area(struct SpaceImaSel *simasel);
+void draw_sima_area(struct SpaceImaSel *simasel);
+void select_ima_files(struct SpaceImaSel *simasel);
+void move_imadir_sli(struct SpaceImaSel *simasel);
+void move_imafile_sli(struct SpaceImaSel *simasel);
+void ima_select_all(struct SpaceImaSel *simasel);
+void pibplay(struct SpaceImaSel *simasel);
+void drawimasel(void);
+
+/* void calc_hilite(SpaceImaSel *simasel); */
+/* void ima_select_all(SpaceImaSel *simasel); */
+/* void move_imadir_sli(SpaceImaSel *simasel); */
+/* void move_imafile_sli(SpaceImaSel *simasel); */
+/* void pibplay(SpaceImaSel *simasel); */
+/* void select_ima_files(SpaceImaSel *simasel); */
+
+#endif /* BSE_DRAWIMASEL_H */
diff --git a/source/blender/include/BSE_drawipo.h b/source/blender/include/BSE_drawipo.h
new file mode 100644
index 00000000000..2b2d6abf1d8
--- /dev/null
+++ b/source/blender/include/BSE_drawipo.h
@@ -0,0 +1,63 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BSE_DRAWIPO_H
+#define BSE_DRAWIPO_H
+
+struct EditIpo;
+struct View2D;
+struct rctf;
+
+
+void calc_ipogrid(void);
+void draw_ipogrid(void);
+
+void areamouseco_to_ipoco (struct View2D *v2d, short *mval, float *x, float *y);
+void ipoco_to_areaco (struct View2D *v2d, float *vec, short *mval);
+void ipoco_to_areaco_noclip (struct View2D *v2d, float *vec, short *mval);
+
+void test_view2d (struct View2D *v2d, int winx, int winy);
+void calc_scrollrcts (struct View2D *v2d, int winx, int winy);
+
+int in_ipo_buttons(void);
+void drawscroll(int disptype);
+void drawipo(void);
+
+void scroll_ipobuts(void);
+void view2dzoom(void);
+int view2dmove(void);
+void view2dborder(void);
+
+struct EditIpo *select_proj_ipo(struct rctf *rectf, int event);
+
+
+#endif /* BSE_DRAWIPO_H */
diff --git a/source/blender/include/BSE_drawnla.h b/source/blender/include/BSE_drawnla.h
new file mode 100644
index 00000000000..b71c604acfe
--- /dev/null
+++ b/source/blender/include/BSE_drawnla.h
@@ -0,0 +1,39 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BSE_DRAWNLA_H
+#define BSE_DRAWNLA_H
+
+void drawnlaspace(void);
+
+#endif /* BSE_DRAWNLA */
+
diff --git a/source/blender/include/BSE_drawoops.h b/source/blender/include/BSE_drawoops.h
new file mode 100644
index 00000000000..fc354164115
--- /dev/null
+++ b/source/blender/include/BSE_drawoops.h
@@ -0,0 +1,49 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BSE_DRAWOOPS_H
+#define BSE_DRAWOOPS_H
+
+struct Oops;
+struct uiBlock;
+
+void boundbox_oops(void);
+void give_oopslink_line(struct Oops *oops, struct OopsLink *ol, float *v1, float *v2);
+void draw_oopslink(struct Oops *oops);
+void draw_icon_oops(float *co, short type);
+void mysbox(float x1, float y1, float x2, float y2);
+unsigned int give_oops_color(short type, short sel, unsigned int *border);
+void calc_oopstext(char *str, float *v1);
+void draw_oops(struct Oops *oops, struct uiBlock *block);
+void drawoopsspace(void);
+
+#endif /* BSE_DRAWOOPS */
diff --git a/source/blender/include/BSE_drawview.h b/source/blender/include/BSE_drawview.h
new file mode 100644
index 00000000000..3cd9bb07f03
--- /dev/null
+++ b/source/blender/include/BSE_drawview.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 BSE_DRAWVIEW_H
+#define BSE_DRAWVIEW_H
+
+struct Object;
+struct BGpic;
+struct rcti;
+
+void setalpha_bgpic(struct BGpic *bgpic);
+void default_gl_light(void);
+void init_gl_stuff(void);
+void two_sided(int val);
+void circf(float x, float y, float rad);
+void circ(float x, float y, float rad);
+void backdrawview3d(int test);
+void drawview3d(void);
+void drawview3d_render(struct View3D *v3d);
+int update_time(void);
+void calc_viewborder(struct View3D *v3d, struct rcti *viewborder_r);
+void view3d_set_1_to_1_viewborder(struct View3D *v3d);
+void timestr(double time, char *str);
+double speed_to_swaptime(int speed);
+double key_to_swaptime(int key);
+
+void sumo_callback(void *obp);
+void init_anim_sumo(void);
+void update_anim_sumo(void);
+void end_anim_sumo(void);
+
+void inner_play_anim_loop(int init, int mode);
+int play_anim(int mode);
+
+#endif /* BSE_DRAWVIEW_H */
diff --git a/source/blender/include/BSE_edit.h b/source/blender/include/BSE_edit.h
new file mode 100644
index 00000000000..5a631c4232a
--- /dev/null
+++ b/source/blender/include/BSE_edit.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 BSE_EDIT_H
+#define BSE_EDIT_H
+
+struct Object;
+struct rcti;
+
+int get_border(struct rcti *rect, short col);
+void count_object(struct Object *ob, int sel);
+void countall(void);
+void snapmenu(void);
+
+#endif /* BSE_EDIT_H */
diff --git a/source/blender/include/BSE_editaction.h b/source/blender/include/BSE_editaction.h
new file mode 100644
index 00000000000..007c6208b04
--- /dev/null
+++ b/source/blender/include/BSE_editaction.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 *****
+ */
+
+#ifndef BSE_EDITACTION_H
+#define BSE_EDITACTION_H
+
+struct bAction;
+struct bActionChannel;
+struct bPoseChannel;
+struct Object;
+struct Ipo;
+
+struct bActionChannel* get_hilighted_action_channel(struct bAction* action);
+void set_exprap_action(int mode);
+void free_posebuf(void);
+void copy_posebuf (void);
+void paste_posebuf (int flip);
+void set_action_key (struct bAction *act, struct bPoseChannel *chan, int adrcode, short makecurve);
+struct bAction *add_empty_action(void);
+void deselect_actionchannel_keys (struct bAction *act, int test);
+void deselect_actionchannels (struct bAction *act, int test);
+void winqreadactionspace(unsigned short event, short val, char ascii);
+void remake_action_ipos(struct bAction *act);
+void select_actionchannel_by_name (struct bAction *act, char *name, int select);
+struct bAction *bake_action_with_client (struct bAction *act, struct Object *arm, float tolerance);
+
+#endif /* BSE_EDITACTION_H */
diff --git a/source/blender/include/BSE_editaction_types.h b/source/blender/include/BSE_editaction_types.h
new file mode 100644
index 00000000000..5b2be4054a1
--- /dev/null
+++ b/source/blender/include/BSE_editaction_types.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 *****
+ */
+
+#ifndef BSE_EDITACTION_TYPES_H
+#define BSE_EDITACTION_TYPES_H
+
+#define CHANNELHEIGHT 16
+#define CHANNELSKIP 2
+#define ACTWIDTH 128
+
+#define CHANNEL_FILTER_LOC 0x00000001 /* Show location keys */
+#define CHANNEL_FILTER_ROT 0x00000002 /* Show rotation keys */
+#define CHANNEL_FILTER_SIZE 0x00000004 /* Show size keys */
+#define CHANNEL_FILTER_CON 0x00000008 /* Show constraint keys */
+#define CHANNEL_FILTER_RGB 0x00000010 /* Show object color keys */
+
+#define CHANNEL_FILTER_CU 0x00010000 /* Show curve keys */
+#define CHANNEL_FILTER_ME 0x00020000 /* Show mesh keys */
+#define CHANNEL_FILTER_LA 0x00040000 /* Show lamp keys */
+
+#endif /* BSE_EDITACTION_TYPES_H */
diff --git a/source/blender/include/BSE_editipo.h b/source/blender/include/BSE_editipo.h
new file mode 100644
index 00000000000..f05f96d8dc0
--- /dev/null
+++ b/source/blender/include/BSE_editipo.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 *****
+ */
+
+#ifndef BSE_EDITIPO_H
+#define BSE_EDITIPO_H
+
+struct TransVert;
+struct IpoCurve;
+struct BezTriple;
+struct Ipo;
+struct EditIpo;
+struct ID;
+struct ListBase;
+struct Object;
+struct IpoKey;
+struct TransOb;
+
+void remake_object_ipos(struct Object *ob);
+void getname_ac_ei(int nr, char *str);
+void getname_co_ei(int nr, char *str);
+void getname_ob_ei(int nr, char *str, int colipo);
+void getname_tex_ei(int nr, char *str);
+void getname_mat_ei(int nr, char *str);
+void getname_world_ei(int nr, char *str);
+void getname_seq_ei(int nr, char *str);
+void getname_cu_ei(int nr, char *str);
+void getname_key_ei(int nr, char *str);
+void getname_la_ei(int nr, char *str);
+void getname_cam_ei(int nr, char *str);
+void getname_snd_ei(int nr, char *str);
+struct IpoCurve *find_ipocurve(struct Ipo *ipo, int adrcode);
+void boundbox_ipocurve(struct IpoCurve *icu);
+void boundbox_ipo(struct Ipo *ipo, struct rctf *bb);
+void editipo_changed(struct SpaceIpo *si, int doredraw);
+void scale_editipo(void);
+struct Ipo *get_ipo_to_edit(struct ID **from);
+unsigned int ipo_rainbow(int cur, int tot);
+void make_ob_editipo(struct Object *ob, struct SpaceIpo *si);
+void make_seq_editipo(struct SpaceIpo *si);
+void make_cu_editipo(struct SpaceIpo *si);
+void make_key_editipo(struct SpaceIpo *si);
+int texchannel_to_adrcode(int channel);
+void make_mat_editipo(struct SpaceIpo *si);
+void make_world_editipo(struct SpaceIpo *si);
+void make_lamp_editipo(struct SpaceIpo *si);
+void make_camera_editipo(struct SpaceIpo *si);
+int make_action_editipo(struct Ipo *ipo, struct EditIpo **si);
+int make_constraint_editipo(struct Ipo *ipo, struct EditIpo **si);
+void make_sound_editipo(struct SpaceIpo *si);
+void make_editipo(void);
+void test_editipo(void);
+void get_status_editipo(void);
+void update_editipo_flags(void);
+void set_editflag_editipo(void);
+void swap_selectall_editipo(void);
+void swap_visible_editipo(void);
+void deselectall_editipo(void);
+short findnearest_ipovert(struct IpoCurve **icu, struct BezTriple **bezt);
+void move_to_frame(void);
+void do_ipowin_buts(short event);
+void do_ipo_selectbuttons(void);
+struct EditIpo *get_editipo(void);
+struct IpoCurve *get_ipocurve(struct ID *from, short type, int adrcode, struct Ipo* useipo);
+void insert_vert_ipo(struct IpoCurve *icu, float x, float y);
+void add_vert_ipo(void);
+void add_duplicate_editipo(void);
+void remove_doubles_ipo(void);
+void join_ipo(void);
+void ipo_snapmenu(void);
+void mouse_select_ipo(void);
+void sethandles_ipo(int code);
+void set_ipotype(void);
+void borderselect_ipo(void);
+void del_ipo(void);
+void free_ipocopybuf(void);
+void copy_editipo(void);
+void paste_editipo(void);
+void set_exprap_ipo(int mode);
+int find_other_handles(struct EditIpo *eicur,
+ float ctime, struct BezTriple **beztar);
+void set_speed_editipo(float speed);
+void insertkey(struct ID *id, int adrcode);
+void insertkey_editipo(void);
+void common_insertkey(void);
+void free_ipokey(struct ListBase *lb);
+void add_to_ipokey(struct ListBase *lb, struct BezTriple *bezt, int nr, int len);
+void make_ipokey(void);
+void make_ipokey_transform(struct Object *ob, struct ListBase *lb, int sel);
+void update_ipokey_val(void);
+void set_tob_old(float *old, float *poin);
+void set_ipo_pointers_transob(struct IpoKey *ik, struct TransOb *tob);
+void nextkey(struct ListBase *elems, int dir);
+void movekey_ipo(int dir);
+void movekey_obipo(int dir);
+void nextkey_ipo(int dir);
+void nextkey_obipo(int dir);
+void remake_ipo_transverts(struct TransVert *transmain, float *dvec, int tot);
+void transform_ipo(int mode);
+void clever_numbuts_ipo(void);
+void filter_sampledata(float *data, int sfra, int efra);
+void sampledata_to_ipocurve(float *data, int sfra, int efra, struct IpoCurve *icu);
+void ipo_record(void);
+
+void set_ipo_key_selection(struct Ipo *ipo, int sel);
+int is_ipo_key_selected(struct Ipo *ipo);
+void delete_ipo_keys(struct Ipo *ipo);
+int fullselect_ipo_keys(struct Ipo *ipo);
+int add_trans_ipo_keys(struct Ipo *ipo, struct TransVert *tv, int tvtot);
+void duplicate_ipo_keys(struct Ipo *ipo);
+void borderselect_ipo_key(struct Ipo *ipo, float xmin, float xmax, int val);
+void select_ipo_key(struct Ipo *ipo, float selx, int sel);
+
+#endif /* BSE_EDITIPO_H */
diff --git a/source/blender/include/BSE_editipo_types.h b/source/blender/include/BSE_editipo_types.h
new file mode 100644
index 00000000000..b14e87bf1ef
--- /dev/null
+++ b/source/blender/include/BSE_editipo_types.h
@@ -0,0 +1,262 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BSE_EDITIPO_TYPES_H
+#define BSE_EDITIPO_TYPES_H
+
+struct BezTriple;
+
+typedef struct IpoKey {
+ struct IpoKey *next, *prev;
+ short flag, rt;
+ float val;
+ struct BezTriple **data;
+} IpoKey;
+
+typedef struct EditIpo {
+ char name[12];
+ IpoCurve *icu;
+ short adrcode, flag;
+ short disptype, rt;
+ unsigned int col;
+} EditIpo;
+
+
+#define IPOBUTY 17
+
+#define TOB_IPO 1
+#define TOB_IPODROT 2
+#define TOB_IKA 4
+
+/* disptype */
+#define IPO_DISPDEGR 1
+#define IPO_DISPBITS 2
+#define IPO_DISPTIME 3
+
+/* ******************** */
+
+#define OB_TOTIPO 24
+
+#define OB_LOC_X 1
+#define OB_LOC_Y 2
+#define OB_LOC_Z 3
+#define OB_DLOC_X 4
+#define OB_DLOC_Y 5
+#define OB_DLOC_Z 6
+
+#define OB_ROT_X 7
+#define OB_ROT_Y 8
+#define OB_ROT_Z 9
+#define OB_DROT_X 10
+#define OB_DROT_Y 11
+#define OB_DROT_Z 12
+
+#define OB_SIZE_X 13
+#define OB_SIZE_Y 14
+#define OB_SIZE_Z 15
+#define OB_DSIZE_X 16
+#define OB_DSIZE_Y 17
+#define OB_DSIZE_Z 18
+
+#define OB_LAY 19
+
+#define OB_TIME 20
+
+#define OB_EFF_X 21
+#define OB_EFF_Y 22
+#define OB_EFF_Z 23
+
+#define OB_COL_R 21
+#define OB_COL_G 22
+#define OB_COL_B 23
+#define OB_COL_A 24
+
+
+
+/* ******************** */
+
+#define MA_TOTIPO 32
+
+#define MA_COL_R 1
+#define MA_COL_G 2
+#define MA_COL_B 3
+#define MA_SPEC_R 4
+#define MA_SPEC_G 5
+#define MA_SPEC_B 6
+#define MA_MIR_R 7
+#define MA_MIR_G 8
+#define MA_MIR_B 9
+#define MA_REF 10
+#define MA_ALPHA 11
+#define MA_EMIT 12
+#define MA_AMB 13
+#define MA_SPEC 14
+#define MA_HARD 15
+#define MA_SPTR 16
+#define MA_ANG 17
+#define MA_MODE 18
+#define MA_HASIZE 19
+
+#define MA_MAP1 0x20
+#define MA_MAP2 0x40
+#define MA_MAP3 0x80
+#define MA_MAP4 0x100
+#define MA_MAP5 0x200
+#define MA_MAP6 0x400
+#define MA_MAP7 0x800
+#define MA_MAP8 0x1000
+
+#define MAP_OFS_X 1
+#define MAP_OFS_Y 2
+#define MAP_OFS_Z 3
+#define MAP_SIZE_X 4
+#define MAP_SIZE_Y 5
+#define MAP_SIZE_Z 6
+#define MAP_R 7
+#define MAP_G 8
+#define MAP_B 9
+
+#define MAP_DVAR 10
+#define MAP_COLF 11
+#define MAP_NORF 12
+#define MAP_VARF 13
+
+/* ******************** */
+
+#define SEQ_TOTIPO 1
+
+#define SEQ_FAC1 1
+
+/* ******************** */
+
+#define CU_TOTIPO 1
+
+#define CU_SPEED 1
+
+/* ******************** */
+
+#define KEY_TOTIPO 32
+
+#define KEY_SPEED 0
+#define KEY_NR 1
+
+/* ******************** */
+
+#define WO_TOTIPO 29
+
+#define WO_HOR_R 1
+#define WO_HOR_G 2
+#define WO_HOR_B 3
+#define WO_ZEN_R 4
+#define WO_ZEN_G 5
+#define WO_ZEN_B 6
+
+#define WO_EXPOS 7
+
+#define WO_MISI 8
+#define WO_MISTDI 9
+#define WO_MISTSTA 10
+#define WO_MISTHI 11
+
+#define WO_STAR_R 12
+#define WO_STAR_G 13
+#define WO_STAR_B 14
+#define WO_STARDIST 15
+#define WO_STARSIZE 16
+
+/* ******************** */
+
+#define LA_TOTIPO 23
+
+#define LA_ENERGY 1
+#define LA_COL_R 2
+#define LA_COL_G 3
+#define LA_COL_B 4
+#define LA_DIST 5
+#define LA_SPOTSI 6
+#define LA_SPOTBL 7
+#define LA_QUAD1 8
+#define LA_QUAD2 9
+#define LA_HALOINT 10
+
+/* ******************** */
+
+#define CAM_TOTIPO 3
+
+#define CAM_LENS 1
+#define CAM_STA 2
+#define CAM_END 3
+
+
+/* ******************** */
+
+#define SND_TOTIPO 4
+
+#define SND_VOLUME 1
+#define SND_PITCH 2
+#define SND_PANNING 3
+#define SND_ATTEN 4
+
+/* ******************** */
+
+#define AC_TOTIPO 10 /* Action Ipos */
+
+#define AC_LOC_X 1
+#define AC_LOC_Y 2
+#define AC_LOC_Z 3
+
+#define AC_SIZE_X 13
+#define AC_SIZE_Y 14
+#define AC_SIZE_Z 15
+
+#define AC_QUAT_W 25
+#define AC_QUAT_X 26
+#define AC_QUAT_Y 27
+#define AC_QUAT_Z 28
+
+/* ******************** */
+
+#define CO_TOTIPO 1 /* Constraint Ipos */
+
+#define CO_ENFORCE 1
+/*
+#define CO_TIME 2
+#define CO_OFFSET_X 3
+#define CO_OFFSET_Y 4
+#define CO_OFFSET_Z 5
+#define CO_ORIENT_X 6
+#define CO_ORIENT_Y 7
+#define CO_ORIENT_Z 8
+#define CO_ROLL 9
+*/
+
+#endif /* BSE_EDITIPO_TYPES_H */
diff --git a/source/blender/include/BSE_editnla_types.h b/source/blender/include/BSE_editnla_types.h
new file mode 100644
index 00000000000..a6ef781514c
--- /dev/null
+++ b/source/blender/include/BSE_editnla_types.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 BSE_EDITNLA_TYPES_H
+#define BSE_EDITNLA_TYPES_H
+
+#define NLAWIDTH 196
+#define NLACHANNELHEIGHT 16
+#define NLACHANNELSKIP 1
+
+#define ACTIVE_ARMATURE(base) ((base)->object->type==OB_ARMATURE && (base)->object->action)
+
+#endif /* BSE_EDITNLA_TYPES_H */
diff --git a/source/blender/include/BSE_filesel.h b/source/blender/include/BSE_filesel.h
new file mode 100644
index 00000000000..dcc49ecc30e
--- /dev/null
+++ b/source/blender/include/BSE_filesel.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 BSE_FILESEL_H
+#define BSE_FILESEL_H
+
+struct SpaceFile;
+struct direntry;
+struct ID;
+
+void clear_global_filesel_vars(void);
+void filesel_statistics(struct SpaceFile *sfile, int *totfile, int *selfile, float *totlen, float *sellen);
+void checkdir(char *dir);
+void test_flags_file(struct SpaceFile *sfile);
+void sort_filelist(struct SpaceFile *sfile);
+void read_dir(struct SpaceFile *sfile);
+void freefilelist(struct SpaceFile *sfile);
+void parent(struct SpaceFile *sfile);
+void swapselect_file(struct SpaceFile *sfile);
+void drawfilespace(void);
+void activate_fileselect(int type, char *title, char *file, void (*func)(char *));
+void activate_imageselect(int type, char *title, char *file, void (*func)(char *));
+void activate_databrowse(struct ID *id, int idcode, int fromcode, int retval, short *menup, void (*func)(unsigned short));
+void filesel_prevspace(void);
+void free_filesel_spec(char *dir);
+void winqreadfilespace(unsigned short event, short val, char ascii);
+void main_to_filelist(struct SpaceFile *sfile);
+
+#endif
diff --git a/source/blender/include/BSE_headerbuttons.h b/source/blender/include/BSE_headerbuttons.h
new file mode 100644
index 00000000000..06693d70262
--- /dev/null
+++ b/source/blender/include/BSE_headerbuttons.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 BSE_HEADERBUTTONS_H
+#define BSE_HEADERBUTTONS_H
+
+struct uiBlock;
+struct ID;
+
+void free_matcopybuf(void);
+void clear_matcopybuf(void);
+void write_videoscape_fs(void);
+void write_vrml_fs(void);
+void write_dxf_fs(void);
+void do_global_buttons(unsigned short event);
+void do_global_buttons2(short event);
+int buttons_do_unpack(void);
+struct Scene *copy_scene(struct Scene *sce, int level);
+void do_info_buttons(unsigned short event);
+
+int start_progress_bar();
+void end_progress_bar();
+int progress_bar(float done, char *busy_info);
+
+void update_for_newframe(void);
+
+void info_buttons(void);
+void do_seq_buttons(short event);
+void seq_buttons(void);
+void do_view3d_buttons(short event);
+void sound_buttons(void);
+void do_action_buttons(unsigned short event);
+void do_ipo_buttons(short event);
+void do_buts_buttons(short event);
+void do_oops_buttons(short event);
+void do_sound_buttons(unsigned short event);
+void do_layer_buttons(short event);
+void do_nla_buttons(unsigned short event);
+
+void nla_buttons(void);
+void action_buttons(void);
+void buts_buttons(void);
+void file_buttons(void);
+void image_buttons(void);
+void imasel_buttons(void);
+void ipo_buttons(void);
+void oops_buttons(void);
+void text_buttons(void);
+void view3d_buttons(void);
+
+void buttons_active_id(struct ID **id, struct ID **idfrom);
+
+void do_headerbuttons(short event);
+
+#endif /* BSE_HEADERBUTTONS_H */
diff --git a/source/blender/include/BSE_sequence.h b/source/blender/include/BSE_sequence.h
new file mode 100644
index 00000000000..67bc244e929
--- /dev/null
+++ b/source/blender/include/BSE_sequence.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 BSE_SEQUENCE_H
+#define BSE_SEQUENCE_H
+
+struct PluginSeq;
+struct StripElem;
+struct Strip;
+struct Sequence;
+struct ListBase;
+struct Editing;
+struct ImBuf;
+struct Scene;
+
+void open_plugin_seq(struct PluginSeq *pis, char *seqname);
+struct PluginSeq *add_plugin_seq(char *str, char *seqname);
+void free_plugin_seq(struct PluginSeq *pis);
+void free_stripdata(int len, struct StripElem *se);
+void free_strip(struct Strip *strip);
+void new_stripdata(struct Sequence *seq);
+void free_sequence(struct Sequence *seq);
+void do_seq_count(struct ListBase *seqbase, int *totseq);
+void do_build_seqar(struct ListBase *seqbase, struct Sequence ***seqar, int depth);
+void build_seqar(struct ListBase *seqbase, struct Sequence ***seqar, int *totseq);
+void free_editing(struct Editing *ed);
+void calc_sequence(struct Sequence *seq);
+void sort_seq(void);
+void clear_scene_in_allseqs(struct Scene *sce);
+void do_alphaover_effect(float facf0,
+ float facf1,
+ int x, int y,
+ unsigned int *rect1,
+ unsigned int *rect2,
+ unsigned int *out);
+void do_alphaunder_effect(float facf0, float facf1,
+ int x, int y,
+ unsigned int *rect1, unsigned int *rect2,
+ unsigned int *out);
+void do_cross_effect(float facf0, float facf1,
+ int x, int y,
+ unsigned int *rect1, unsigned int *rect2,
+ unsigned int *out);
+void do_gammacross_effect(float facf0, float facf1,
+ int x, int y,
+ unsigned int *rect1, unsigned int *rect2,
+ unsigned int *out);
+void do_add_effect(float facf0, float facf1,
+ int x, int y,
+ unsigned int *rect1, unsigned int *rect2,
+ unsigned int *out);
+void do_sub_effect(float facf0, float facf1,
+ int x, int y,
+ unsigned int *rect1, unsigned int *rect2,
+ unsigned int *out);
+void do_drop_effect(float facf0, float facf1,
+ int x, int y,
+ unsigned int *rect2i, unsigned int *rect1i,
+ unsigned int *outi);
+void do_drop_effect2(float facf0, float facf1,
+ int x, int y,
+ unsigned int *rect2, unsigned int *rect1,
+ unsigned int *out);
+void do_mul_effect(float facf0, float facf1,
+ int x, int y,
+ unsigned int *rect1, unsigned int *rect2,
+ unsigned int *out);
+void make_black_ibuf(struct ImBuf *ibuf);
+void multibuf(struct ImBuf *ibuf, float fmul);
+void do_effect(int cfra, struct Sequence *seq, struct StripElem *se);
+int evaluate_seq_frame(int cfra);
+struct StripElem *give_stripelem(struct Sequence *seq, int cfra);
+void set_meta_stripdata(struct Sequence *seqm);
+void do_seq_count_cfra(struct ListBase *seqbase, int *totseq, int cfra);
+void do_build_seqar_cfra(struct ListBase *seqbase, struct Sequence ***seqar, int cfra);
+struct ImBuf *give_ibuf_seq(int cfra);
+void free_imbuf_effect_spec(int cfra);
+void free_imbuf_seq_except(int cfra);
+void free_imbuf_seq(void);
+void do_render_seq(void);
+
+
+#endif
diff --git a/source/blender/include/BSE_trans_types.h b/source/blender/include/BSE_trans_types.h
new file mode 100644
index 00000000000..44d7c44b339
--- /dev/null
+++ b/source/blender/include/BSE_trans_types.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 *****
+ */
+
+#ifndef BSE_TRANS_TYPES_H
+#define BSE_TRANS_TYPES_H
+
+struct Object;
+/* struct EditVlak; */
+/* struct EditEdge; */
+/* struct EditVert; */
+/* struct ListBase; */
+
+typedef struct TransOb {
+ float *loc;
+ float oldloc[9];
+ float *eff;
+ float oldeff[3];
+ float *rot;
+ float oldrot[12];
+ float olddrot[3];
+ float *quat;
+ float oldquat[16];
+ float olddquat[4];
+ float *size;
+ float oldsize[12];
+ float olddsize[3];
+ float obmat[3][3];
+ float obinv[3][3];
+ float parmat[3][3];
+ float parinv[3][3];
+ float obvec[3];
+ int flag; /* keys */
+ float *locx, *locy, *locz;
+ float *rotx, *roty, *rotz;
+ float *quatx, *quaty, *quatz, *quatw;
+ float *sizex, *sizey, *sizez;
+ /* __NLA */
+ float axismat[3][3]; /* Restmat of object (for localspace transforms) */
+ void *data; /* Arbitrary data */
+ /* end __NLA */
+ struct Object *ob;
+} TransOb;
+
+typedef struct TransVert {
+ float *loc;
+ float oldloc[3], fac;
+ float *val, oldval;
+ int flag;
+ float *nor;
+} TransVert;
+
+typedef struct VPaint {
+ float r, g, b, a;
+ float size; /* van brush */
+ float gamma, mul;
+ short mode, flag;
+} VPaint;
+
+#endif /* BSE_TRANS_TYPES_H */
diff --git a/source/blender/include/BSE_types.h b/source/blender/include/BSE_types.h
new file mode 100644
index 00000000000..552e44a7c70
--- /dev/null
+++ b/source/blender/include/BSE_types.h
@@ -0,0 +1,71 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+/* forward declarations for some prototype header */
+/* these may wildly occur in other header files, too */
+
+struct BGpic;
+struct SpaceText;
+struct Oops;
+struct OopsLink;
+struct uiBlock;
+struct BoundBox;
+struct Image;
+struct ImBuf;
+struct SpaceImaSel;
+struct Sequence;
+struct Scene;
+struct IpoCurve;
+struct Ipo;
+struct IpoKey;
+struct Mesh;
+struct TFace;
+struct Object;
+struct TransOb;
+struct TransVert;
+struct BPoint;
+struct BezTriple;
+
+struct Nurb;
+
+struct EditVlak;
+struct EditVert;
+struct EditEdge;
+struct EditIpo;
+
+struct bArmature;
+struct Bone;
+
+/* interface crap */
+struct uiBut;
+
+
+
diff --git a/source/blender/include/BSE_view.h b/source/blender/include/BSE_view.h
new file mode 100644
index 00000000000..a02000a6f39
--- /dev/null
+++ b/source/blender/include/BSE_view.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 *****
+ * protos for view.c -- not complete
+ */
+
+#ifndef BSE_VIEW_H
+#define BSE_VIEW_H
+
+struct Object;
+struct BoundBox;
+struct View3D;
+struct ScrArea;
+
+void persp3d(struct View3D *v3d, int a);
+void persp_general(int a);
+void persp(int a);
+void initgrabz(float x, float y, float z);
+void window_to_3d(float *vec, short mx, short my);
+void project_short(float *vec, short *adr);
+void project_short_noclip(float *vec, short *adr);
+int boundbox_clip(float obmat[][4], struct BoundBox *bb);
+void fdrawline(float x1, float y1, float x2, float y2);
+void fdrawbox(float x1, float y1, float x2, float y2);
+void sdrawline(short x1, short y1, short x2, short y2);
+void sdrawbox(short x1, short y1, short x2, short y2);
+void calctrackballvecfirst(struct rcti *area, short *mval, float *vec);
+void calctrackballvec(struct rcti *area, short *mval, float *vec);
+void viewmove(int mode);
+void setwinmatrixview3d(struct rctf *rect);
+void obmat_to_viewmat(struct Object *ob);
+void setviewmatrixview3d(void);
+float *give_cursor(void);
+unsigned int free_localbit(void);
+void initlocalview(void);
+void centreview(void);
+void restore_localviewdata(struct View3D *vd);
+void endlocalview(struct ScrArea *sa);
+void view3d_home(int centre);
+short selectprojektie(unsigned int *buffer, short x1, short y1, short x2, short y2);
+void view3d_align_axis_to_vector(struct View3D *v3d, int axisidx, float vec[3]);
+
+#endif
diff --git a/source/blender/include/LOD_DependKludge.h b/source/blender/include/LOD_DependKludge.h
new file mode 100644
index 00000000000..d8930a4fdba
--- /dev/null
+++ b/source/blender/include/LOD_DependKludge.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 *****
+ * Decimation file dependency fix (and kludge)
+ * Use together with a NAN_DECIMATIONTEST env.var. for Makefile-based linking
+ */
+#ifndef LOD_DEPENDKLUDGE_H
+#define LOD_DEPENDKLUDGE_H
+
+
+#define NAN_DECIMATION
+
+#endif //LOD_DEPENDKLUDGE_H
diff --git a/source/blender/include/TPT_DependKludge.h b/source/blender/include/TPT_DependKludge.h
new file mode 100644
index 00000000000..32ad32ad29c
--- /dev/null
+++ b/source/blender/include/TPT_DependKludge.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 *****
+ * Texture paint tool file dependency fix (and kludge)
+ */
+
+#ifndef TPT_DEPENDKLUDGE_H
+#define TPT_DEPENDKLUDGE_H
+
+
+#define NAN_TPT
+//#undef NAN_TPT
+
+#endif /* TPT_DEPENDKLUDGE_H */
+
diff --git a/source/blender/include/blendef.h b/source/blender/include/blendef.h
new file mode 100644
index 00000000000..6d6b3904645
--- /dev/null
+++ b/source/blender/include/blendef.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 *****
+ */
+#ifndef BLENDEF_H
+#define BLENDEF_H
+
+#ifdef WIN32
+#else
+#ifndef __BeOS
+#define O_BINARY 0
+#endif
+#endif
+
+#ifndef MAXFLOAT
+#define MAXFLOAT ((float)3.40282347e+38)
+#endif
+
+#include <float.h> /* deze moet een keer naar de blender.h */
+
+
+
+
+/* **************** ALGEMEEN ********************* */
+
+#define VECCOPY(v1,v2) {*(v1)= *(v2); *(v1+1)= *(v2+1); *(v1+2)= *(v2+2);}
+#define QUATCOPY(v1,v2) {*(v1)= *(v2); *(v1+1)= *(v2+1); *(v1+2)= *(v2+2); *(v1+3)= *(v2+3);}
+
+#define INPR(v1, v2) ( (v1)[0]*(v2)[0] + (v1)[1]*(v2)[1] + (v1)[2]*(v2)[2] )
+#define CLAMP(a, b, c) if((a)<(b)) (a)=(b); else if((a)>(c)) (a)=(c)
+#define CLAMPIS(a, b, c) ((a)<(b) ? (b) : (a)>(c) ? (c) : (a))
+#define CLAMPTEST(a, b, c) if((b)<(c)) {CLAMP(a, b, c);} else {CLAMP(a, c, b);}
+
+#define IS_EQ(a,b) ((fabs((double)(a)-(b)) >= (double) FLT_EPSILON) ? 0 : 1)
+
+#define INIT_MINMAX(min, max) (min)[0]= (min)[1]= (min)[2]= 1.0e30; (max)[0]= (max)[1]= (max)[2]= -1.0e30;
+#define DO_MINMAX(vec, min, max) if( (min)[0]>(vec)[0] ) (min)[0]= (vec)[0]; \
+ if( (min)[1]>(vec)[1] ) (min)[1]= (vec)[1]; \
+ if( (min)[2]>(vec)[2] ) (min)[2]= (vec)[2]; \
+ if( (max)[0]<(vec)[0] ) (max)[0]= (vec)[0]; \
+ if( (max)[1]<(vec)[1] ) (max)[1]= (vec)[1]; \
+ if( (max)[2]<(vec)[2] ) (max)[2]= (vec)[2]; \
+
+#define DO_MINMAX2(vec, min, max) if( (min)[0]>(vec)[0] ) (min)[0]= (vec)[0]; \
+ if( (min)[1]>(vec)[1] ) (min)[1]= (vec)[1]; \
+ if( (max)[0]<(vec)[0] ) (max)[0]= (vec)[0]; \
+ if( (max)[1]<(vec)[1] ) (max)[1]= (vec)[1];
+
+#define MINSIZE(val, size) ( ((val)>=0.0) ? (((val)<(size)) ? (size): (val)) : ( ((val)>(-size)) ? (-size) : (val)))
+
+#define BTST(a,b) ( ( (a) & 1<<(b) )!=0 )
+#define BCLR(a,b) ( (a) & ~(1<<(b)) )
+#define BSET(a,b) ( (a) | 1<<(b) )
+/* bit-row */
+#define BROW(min, max) (((max)>=31? 0xFFFFFFFF: (1<<(max+1))-1) - ((min)? ((1<<(min))-1):0) )
+
+// return values
+
+#define RET_OK 0
+#define RET_ERROR 1
+#define RET_CANCEL 2
+#define RET_YES (1 == 1)
+#define RET_NO (1 == 0)
+
+#define LONGCOPY(a, b, c) {int lcpc=c, *lcpa=(int *)a, *lcpb=(int *)b; while(lcpc-->0) *(lcpa++)= *(lcpb++);}
+
+#if defined(__sgi) || defined(__sparc) || defined (__PPC__) || defined (__ppc__) || defined (__BIG_ENDIAN__)
+/* big endian */
+#define MAKE_ID2(c, d) ( (c)<<8 | (d) )
+#define MOST_SIG_BYTE 0
+#define BBIG_ENDIAN
+#else
+/* little endian */
+#define MAKE_ID2(c, d) ( (d)<<8 | (c) )
+#define MOST_SIG_BYTE 1
+#define BLITTLE_ENDIAN
+#endif
+
+#define SELECT 1
+#define ACTIVE 2
+#define NOT_YET 0
+
+
+#define TESTBASE(base) ( ((base)->flag & SELECT) && ((base)->lay & G.vd->lay) )
+#define TESTBASELIB(base) ( ((base)->flag & SELECT) && ((base)->lay & G.vd->lay) && ((base)->object->id.lib==0))
+#define FIRSTBASE G.scene->base.first
+#define LASTBASE G.scene->base.last
+#define BASACT (G.scene->basact)
+#define OBACT (BASACT? BASACT->object: 0)
+#define ID_NEW(a) if( (a) && (a)->id.newid ) (a)= (void *)(a)->id.newid
+#define ID_NEW_US(a) if( (a)->id.newid) {(a)= (void *)(a)->id.newid; (a)->id.us++;}
+#define ID_NEW_US2(a) if( ((ID *)a)->newid) {(a)= ((ID *)a)->newid; ((ID *)a)->us++;}
+#define CFRA (G.scene->r.cfra)
+#define F_CFRA ((float)(G.scene->r.cfra))
+#define SFRA (G.scene->r.sfra)
+#define EFRA (G.scene->r.efra)
+
+#define ISPOIN(a, b, c) ( (a->b) && (a->c) )
+#define ISPOIN3(a, b, c, d) ( (a->b) && (a->c) && (a->d) )
+#define ISPOIN4(a, b, c, d, e) ( (a->b) && (a->c) && (a->d) && (a->e) )
+
+
+#define KNOTSU(nu) ( (nu)->orderu+ (nu)->pntsu+ (nu->orderu-1)*((nu)->flagu & 1) )
+#define KNOTSV(nu) ( (nu)->orderv+ (nu)->pntsv+ (nu->orderv-1)*((nu)->flagv & 1) )
+
+/* psfont */
+#define FNT_PDRAW 1
+#define FNT_HAEBERLI 2
+
+
+/* isect en scanfill */
+#define COMPLIMIT 0.0003
+
+
+/* **************** MAX ********************* */
+
+
+#define MAXLAMP 256
+/* max lengte material array, 16 vanwege bitjes in matfrom */
+#define MAXPICKBUF 2000
+#define MAXSEQ 32
+/* in Image struct */
+#define MAXMIPMAP 10
+/* in buttons.c */
+#define MAX_EFFECT 20
+
+/* getbutton */
+
+/* do_global_buttons(event) */
+
+#define B_ACTLOCAL 24 /* __NLA */
+#define B_ACTALONE 25 /* __NLA */
+#define B_ARMLOCAL 26 /* __NLA */
+#define B_ARMALONE 27 /* __NLA */
+
+#define B_WORLDLOCAL 28
+#define B_WORLDALONE 29
+#define B_LATTLOCAL 30
+#define B_MBALLLOCAL 31
+#define B_CAMERALOCAL 32
+#define B_OBLOCAL 33
+#define B_IPOLOCAL 34
+#define B_LAMPLOCAL 35
+#define B_MATLOCAL 36
+#define B_TEXLOCAL 37
+#define B_MESHLOCAL 38
+#define B_CURVELOCAL 39
+
+#define B_LATTALONE 40
+#define B_MBALLALONE 41
+#define B_CAMERAALONE 42
+#define B_OBALONE 43
+#define B_IPOALONE 44
+#define B_LAMPALONE 45
+#define B_MATALONE 46
+#define B_TEXALONE 47
+#define B_MESHALONE 48
+#define B_CURVEALONE 49
+/* EVENT < 50: alone's en locals */
+
+#define B_SHOWSPLASH 70
+#define B_RESETAUTOSAVE 71
+#define B_SOUNDTOGGLE 72
+#define B_MIPMAPCHANGED 73
+#define B_CONSTRAINTBROWSE 74 /* __NLA */
+#define B_ACTIONDELETE 75 /* __NLA */
+#define B_ACTIONBROWSE 76 /* __NLA */
+#define B_IMAGEDELETE 77
+#define B_LTEXBROWSE 78
+#define B_MESHBROWSE 79
+#define B_EXTEXBROWSE 80
+#define B_LOADTEMP 81
+#define B_MATDELETE 82
+#define B_TEXDELETE 83
+#define B_IPODELETE 84
+#define B_WORLDDELETE 85
+#define B_WTEXBROWSE 86
+#define B_WORLDBROWSE 87
+#define B_IPOBROWSE 88
+#define B_NEWFRAME 89
+#define B_LAMPBROWSE 90
+#define B_MATBROWSE 91
+#define B_TEXBROWSE 92
+#define B_EDITBROWSE 93
+#define B_AUTOTEXNAME 94
+#define B_AUTOMATNAME 95
+#define B_MATLOCK 96
+#define B_IDNAME 97
+#define B_NEWSPACE 98
+#define B_FULL 99
+#define B_REDR 100
+
+
+/* VIEW3D: 100 */
+#define B_HOME 101
+#define B_LAY 102
+/* pasop: codes 102-132 in gebuik voor layers */
+#define B_AUTOKEY 139
+#define B_SCENELOCK 140
+#define B_LOCALVIEW 141
+#define B_U_CAPSLOCK 142
+#define B_EDITMODE 143
+#define B_VPAINT 144
+#define B_FACESEL 145
+#define B_VIEWBUT 146
+#define B_PERSP 147
+#define B_PROPTOOL 148
+#define B_VIEWRENDER 149
+#define B_VIEWTRANS 150
+#define B_VIEWZOOM 151
+#define B_STARTGAME 152
+#define B_POSEMODE 153
+#define B_TEXTUREPAINT 154
+#define B_WPAINT 155
+
+/* IPO: 200 */
+#define B_IPOHOME 201
+#define B_IPOBORDER 202
+#define B_IPOCOPY 203
+#define B_IPOPASTE 204
+#define B_IPOCONT 205
+#define B_IPOEXTRAP 206
+#define B_IPOCYCLIC 207
+#define B_IPOMAIN 208
+#define B_IPOSHOWKEY 209
+#define B_IPOCYCLICX 210
+ /* warn: also used for oops and seq */
+#define B_VIEW2DZOOM 211
+#define B_IPOPIN 212
+
+/* OOPS: 250 */
+#define B_OOPSHOME 251
+#define B_OOPSBORDER 252
+#define B_NEWOOPS 253
+
+/* INFO: 300 */
+/* pas op: ook in filesel.c en editobject.c */
+#define B_INFOSCR 301
+#define B_INFODELSCR 302
+#define B_INFOSCE 304
+#define B_INFODELSCE 305
+#define B_FILEMENU 306
+#define B_PACKFILE 307
+
+/* IMAGE: 350 */
+#define B_SIMAGEHOME 351
+#define B_SIMABROWSE 352
+#define B_SIMAGELOAD 353
+#define B_SIMAGEDRAW 354
+#define B_BE_SQUARE 355
+#define B_SIMAGEDRAW1 356
+#define B_TWINANIM 357
+#define B_SIMAGEREPLACE 358
+#define B_CLIP_UV 359
+#define B_SIMAGELOAD1 360
+#define B_SIMAGEREPLACE1 361
+#define B_SIMAGEPAINTTOOL 362
+#define B_SIMAPACKIMA 363
+#define B_SIMAGESAVE 364
+
+/* BUTS: 400 */
+#define B_BUTSHOME 401
+#define B_BUTSPREVIEW 402
+#define B_MATCOPY 403
+#define B_MATPASTE 404
+#define B_MESHTYPE 405
+
+/* IMASEL: 450 */
+/* in de imasel.h */
+
+/* TEXT: 500 */
+#define B_TEXTBROWSE 501
+#define B_TEXTALONE 502
+#define B_TEXTLOCAL 503
+#define B_TEXTDELETE 504
+#define B_TEXTFONT 505
+#define B_TEXTSTORE 506
+
+/* FILE: 550 */
+#define B_SORTFILELIST 551
+#define B_RELOADDIR 552
+
+/* SEQUENCE: 600 */
+#define B_SEQHOME 601
+#define B_SEQCLEAR 602
+
+/* SOUND: 650 */
+#define B_SOUNDBROWSE 651
+#define B_SOUNDBROWSE2 652
+#define B_SOUNDHOME 653
+#define B_PACKSOUND 654
+
+/* ACTION: 701 - 800 */
+#define B_ACTHOME 701
+#define B_ACTCOPY 702
+#define B_ACTPASTE 703
+#define B_ACTPASTEFLIP 704
+#define B_ACTCYCLIC 705
+#define B_ACTCONT 706
+#define B_ACTMAIN 707
+#define B_ACTPIN 708
+#define B_ACTBAKE 709
+
+#define B_NOTHING -1
+#define B_NOP -1
+
+/* NLA: 801-900 */
+#define B_NLAHOME 801
+
+/* editbutflag */
+#define B_CLOCKWISE 1
+#define B_KEEPORIG 2
+#define B_BEAUTY 4
+#define B_SMOOTH 8
+
+
+/* ***************** DISPLIST ***************** */
+
+#define DL_POLY 0
+#define DL_SEGM 1
+#define DL_SURF 2
+#define DL_TRIA 3
+#define DL_INDEX3 4
+#define DL_INDEX4 5
+#define DL_VERTCOL 6
+#define DL_VERTS 7
+#define DL_NORS 8
+
+#define DL_SURFINDEX(cyclu, cyclv, sizeu, sizev) \
+ \
+ if( (cyclv)==0 && a==(sizev)-1) break; \
+ if(cyclu) { \
+ p1= sizeu*a; \
+ p2= p1+ sizeu-1; \
+ p3= p1+ sizeu; \
+ p4= p2+ sizeu; \
+ b= 0; \
+ } \
+ else { \
+ p2= sizeu*a; \
+ p1= p2+1; \
+ p4= p2+ sizeu; \
+ p3= p1+ sizeu; \
+ b= 1; \
+ } \
+ if( (cyclv) && a==sizev-1) { \
+ p3-= sizeu*sizev; \
+ p4-= sizeu*sizev; \
+ }
+
+/* DISPLAYMODE */
+#define R_DISPLAYVIEW 0
+#define R_DISPLAYWIN 1
+#define R_DISPLAYAUTO 2
+
+
+
+#if defined(__sgi) || defined(__sparc) || defined (__PPC__) || defined (__ppc__) || defined (__BIG_ENDIAN__)
+#define RCOMP 3
+#define GCOMP 2
+#define BCOMP 1
+#define ACOMP 0
+
+#else
+
+#define RCOMP 0
+#define GCOMP 1
+#define BCOMP 2
+#define ACOMP 3
+#endif
+
+#ifdef GS
+#undef GS
+#endif
+#define GS(a) (*((short *)(a)))
+
+#endif
diff --git a/source/blender/include/datatoc.h b/source/blender/include/datatoc.h
new file mode 100644
index 00000000000..0d74ae891c5
--- /dev/null
+++ b/source/blender/include/datatoc.h
@@ -0,0 +1,56 @@
+/*
+ * datatoc.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 DATATOC_H
+#define DATATOC_H
+
+extern int datatoc_B_blend_size;
+extern char datatoc_B_blend[];
+
+extern int datatoc_Bfs_size;
+extern char datatoc_Bfs[];
+
+extern int datatoc_blenderbuttons_size;
+extern char datatoc_blenderbuttons[];
+
+extern int datatoc_Bfont_size;
+extern char datatoc_Bfont[];
+
+extern int datatoc_cmap_tga_size;
+extern char datatoc_cmap_tga[];
+
+extern int datatoc_cmovie_tga_size;
+extern char datatoc_cmovie_tga[];
+
+#endif /* DATATOC_H */
diff --git a/source/blender/include/editlattice_ext.h b/source/blender/include/editlattice_ext.h
new file mode 100644
index 00000000000..bbea1e6eb93
--- /dev/null
+++ b/source/blender/include/editlattice_ext.h
@@ -0,0 +1,41 @@
+/*
+ * editlattice_ext.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 EDITLATTICE_EXT_H
+#define EDITLATTICE_EXT_H "$Id$"
+#define EDITLATTICE_EXT_H "Copyright (C) 2001 NaN Technologies B.V.
+
+void end_latt_deform(void);
+
+#endif /* EDITLATTICE_EXT_H */
diff --git a/source/blender/include/interface.h b/source/blender/include/interface.h
new file mode 100644
index 00000000000..d4155a81de4
--- /dev/null
+++ b/source/blender/include/interface.h
@@ -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 *****
+ */
+
+#ifndef INTERFACE_H
+#define INTERFACE_H
+
+/* general defines */
+
+#define UI_MAX_DRAW_STR 180
+#define UI_MAX_NAME_STR 64
+#define UI_ARRAY 29
+
+/* block->font, for now: bold = medium+1 */
+#define UI_HELV 0
+#define UI_HELVB 1
+
+
+/* MAART: moved from Button.h */
+/* Button types */
+#define CHA 32
+#define SHO 64
+#define INT 96
+#define FLO 128
+#define FUN 192
+#define BIT 256
+
+#define BUTPOIN (128+64+32)
+
+#define BUT (1<<9)
+#define ROW (2<<9)
+#define TOG (3<<9)
+#define SLI (4<<9)
+#define NUM (5<<9)
+#define TEX (6<<9)
+#define TOG3 (7<<9)
+#define TOGR (8<<9)
+#define TOGN (9<<9)
+#define LABEL (10<<9)
+#define MENU (11<<9)
+#define ICONROW (12<<9)
+#define ICONTOG (13<<9)
+#define NUMSLI (14<<9)
+#define COL (15<<9)
+#define IDPOIN (16<<9)
+#define HSVSLI (17<<9)
+#define SCROLL (18<<9)
+#define BLOCK (19<<9)
+#define BUTM (20<<9)
+#define SEPR (21<<9)
+#define LINK (22<<9)
+#define INLINK (23<<9)
+#define KEYEVT (24<<9)
+
+#define BUTTYPE (31<<9)
+
+#define MAXBUTSTR 20
+
+
+/* return from uiDoBlock */
+#define UI_CONT 0
+#define UI_NOTHING 1
+#define UI_RETURN_CANCEL 2
+#define UI_RETURN_OK 4
+#define UI_RETURN_OUT 8
+#define UI_RETURN 14
+
+/* uiBut->flag */
+#define UI_SELECT 1
+#define UI_MOUSE_OVER 2
+#define UI_ACTIVE 4
+#define UI_HAS_ICON 8
+#define UI_TEXT_LEFT 16
+
+/* uiBlock->flag */
+#define UI_BLOCK_LOOP 1
+#define UI_BLOCK_REDRAW 2
+#define UI_BLOCK_RET_1 4
+#define UI_BLOCK_BUSY 8
+#define UI_BLOCK_NUMSELECT 16
+#define UI_BLOCK_ENTER_OK 32
+#define UI_BLOCK_MENUMODE 128
+
+/* uiBlock->dt */
+#define UI_EMBOSSX 0 /* Rounded embossed button */
+#define UI_EMBOSSW 1 /* Flat bordered button */
+#define UI_EMBOSSN 2 /* No border */
+#define UI_EMBOSSF 3 /* Square embossed button */
+#define UI_EMBOSSM 4 /* Colored Border */
+#define UI_EMBOSSP 5 /* Borderless coloured button */
+
+/* uiBlock->direction */
+#define UI_TOP 0
+#define UI_DOWN 1
+#define UI_LEFT 2
+#define UI_RIGHT 3
+
+/* uiBlock->autofill */
+#define UI_BLOCK_COLLUMNS 1
+#define UI_BLOCK_ROWS 2
+
+#endif
diff --git a/source/blender/include/ipo.h b/source/blender/include/ipo.h
new file mode 100644
index 00000000000..a93c043d939
--- /dev/null
+++ b/source/blender/include/ipo.h
@@ -0,0 +1,262 @@
+
+/* ipo.h
+ *
+ * april 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 IPO_H
+#define IPO_H
+
+struct BezTriple;
+
+typedef struct IpoKey {
+ struct IpoKey *next, *prev;
+ short flag, rt;
+ float val;
+ struct BezTriple **data;
+} IpoKey;
+
+typedef struct EditIpo {
+ char name[12];
+ IpoCurve *icu;
+ short adrcode, flag;
+ short disptype, rt;
+ unsigned int col;
+} EditIpo;
+
+
+#define IPOBUTY 17
+
+
+/* disptype */
+#define IPO_DISPDEGR 1
+#define IPO_DISPBITS 2
+#define IPO_DISPTIME 3
+
+/* ******************** */
+
+#define OB_TOTIPO 24
+
+#define OB_LOC_X 1
+#define OB_LOC_Y 2
+#define OB_LOC_Z 3
+#define OB_DLOC_X 4
+#define OB_DLOC_Y 5
+#define OB_DLOC_Z 6
+
+#define OB_ROT_X 7
+#define OB_ROT_Y 8
+#define OB_ROT_Z 9
+#define OB_DROT_X 10
+#define OB_DROT_Y 11
+#define OB_DROT_Z 12
+
+#define OB_SIZE_X 13
+#define OB_SIZE_Y 14
+#define OB_SIZE_Z 15
+#define OB_DSIZE_X 16
+#define OB_DSIZE_Y 17
+#define OB_DSIZE_Z 18
+
+#define OB_LAY 19
+
+#define OB_TIME 20
+
+#define OB_EFF_X 21
+#define OB_EFF_Y 22
+#define OB_EFF_Z 23
+
+#define OB_COL_R 21
+#define OB_COL_G 22
+#define OB_COL_B 23
+#define OB_COL_A 24
+
+
+
+/* ******************** */
+
+#define MA_TOTIPO 32
+
+#define MA_COL_R 1
+#define MA_COL_G 2
+#define MA_COL_B 3
+#define MA_SPEC_R 4
+#define MA_SPEC_G 5
+#define MA_SPEC_B 6
+#define MA_MIR_R 7
+#define MA_MIR_G 8
+#define MA_MIR_B 9
+#define MA_REF 10
+#define MA_ALPHA 11
+#define MA_EMIT 12
+#define MA_AMB 13
+#define MA_SPEC 14
+#define MA_HARD 15
+#define MA_SPTR 16
+#define MA_ANG 17
+#define MA_MODE 18
+#define MA_HASIZE 19
+
+#define MA_MAP1 0x20
+#define MA_MAP2 0x40
+#define MA_MAP3 0x80
+#define MA_MAP4 0x100
+#define MA_MAP5 0x200
+#define MA_MAP6 0x400
+#define MA_MAP7 0x800
+#define MA_MAP8 0x1000
+
+#define MAP_OFS_X 1
+#define MAP_OFS_Y 2
+#define MAP_OFS_Z 3
+#define MAP_SIZE_X 4
+#define MAP_SIZE_Y 5
+#define MAP_SIZE_Z 6
+#define MAP_R 7
+#define MAP_G 8
+#define MAP_B 9
+
+#define MAP_DVAR 10
+#define MAP_COLF 11
+#define MAP_NORF 12
+#define MAP_VARF 13
+
+/* ******************** */
+
+#define SEQ_TOTIPO 1
+
+#define SEQ_FAC1 1
+
+/* ******************** */
+
+#define CU_TOTIPO 1
+
+#define CU_SPEED 1
+
+/* ******************** */
+
+#define KEY_TOTIPO 32
+
+#define KEY_SPEED 0
+#define KEY_NR 1
+
+/* ******************** */
+
+#define WO_TOTIPO 29
+
+#define WO_HOR_R 1
+#define WO_HOR_G 2
+#define WO_HOR_B 3
+#define WO_ZEN_R 4
+#define WO_ZEN_G 5
+#define WO_ZEN_B 6
+
+#define WO_EXPOS 7
+
+#define WO_MISI 8
+#define WO_MISTDI 9
+#define WO_MISTSTA 10
+#define WO_MISTHI 11
+
+#define WO_STAR_R 12
+#define WO_STAR_G 13
+#define WO_STAR_B 14
+#define WO_STARDIST 15
+#define WO_STARSIZE 16
+
+/* ******************** */
+
+#define LA_TOTIPO 23
+
+#define LA_ENERGY 1
+#define LA_COL_R 2
+#define LA_COL_G 3
+#define LA_COL_B 4
+#define LA_DIST 5
+#define LA_SPOTSI 6
+#define LA_SPOTBL 7
+#define LA_QUAD1 8
+#define LA_QUAD2 9
+#define LA_HALOINT 10
+
+/* ******************** */
+
+#define CAM_TOTIPO 3
+
+#define CAM_LENS 1
+#define CAM_STA 2
+#define CAM_END 3
+
+
+/* ******************** */
+
+#define SND_TOTIPO 4
+
+#define SND_VOLUME 1
+#define SND_PITCH 2
+#define SND_PANNING 3
+#define SND_ATTEN 4
+
+/* ******************** */
+
+#define AC_TOTIPO 10 /* Action Ipos */
+
+#define AC_LOC_X 1
+#define AC_LOC_Y 2
+#define AC_LOC_Z 3
+
+#define AC_SIZE_X 13
+#define AC_SIZE_Y 14
+#define AC_SIZE_Z 15
+
+#define AC_QUAT_W 25
+#define AC_QUAT_X 26
+#define AC_QUAT_Y 27
+#define AC_QUAT_Z 28
+
+/* ******************** */
+
+#define CO_TOTIPO 1 /* Constraint Ipos */
+
+#define CO_ENFORCE 1
+/*
+#define CO_TIME 2
+#define CO_OFFSET_X 3
+#define CO_OFFSET_Y 4
+#define CO_OFFSET_Z 5
+#define CO_ORIENT_X 6
+#define CO_ORIENT_Y 7
+#define CO_ORIENT_Z 8
+#define CO_ROLL 9
+*/
+#endif /* IPO_H */
diff --git a/source/blender/include/keyed_functions.h b/source/blender/include/keyed_functions.h
new file mode 100644
index 00000000000..d3bfd8e7710
--- /dev/null
+++ b/source/blender/include/keyed_functions.h
@@ -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 *****
+ */
+
+
+#define KEY_GETPTR(x) (g_ptrtab ? g_ptrtab[x] : 0)
+
+/* these are the defines for the keyed functions:
+
+ #define key_func<n> <function name to be behind key>
+
+ This function must be of type "int func(void*)"
+
+ To prevent symbol table dumpers from retrieving certain key
+ functions too easily, some of those functions have nonsense names.
+*/
+
+#define key_func1 make_beautiful_animation
+#define key_func2 key_return_true
+#define key_func3 calc_memleak
+/* add the corresponding function pointer defines here.
+ Example:
+
+ #define key_func4 my_protected_function_name
+ #define MY_PROTECTED_FUNCTION_PTR KEY_GETPTR(KEY_FUNC3)
+
+ KEY_GETPTR(KEY_FUNC3) corresponds to the function pointer to function
+ key_func3 after the python key code unscrambled the function pointer tables.
+ Also add pointer initializations to these functions in
+ license_key.c:init_ftable() if necessary.
+*/
+
+#define KEY_WRITE_RUNTIME KEY_GETPTR(KEY_FUNC1)
+#define KEY_RETURN_TRUE KEY_GETPTR(KEY_FUNC2)
+#define KEY_NLA_EVENT KEY_GETPTR(KEY_FUNC3)
+
+/* PROTOS */
+int make_beautiful_animation(void *vp);
+int calc_memleak (void* ptr);
+
+
diff --git a/source/blender/include/license_key.h b/source/blender/include/license_key.h
new file mode 100644
index 00000000000..b2abf2c0f6f
--- /dev/null
+++ b/source/blender/include/license_key.h
@@ -0,0 +1,94 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 LICENCEKEY_H
+#define LICENCEKEY_H
+
+#define I_AM_PUBLISHER temp_val2
+#define LICENSE_KEY_VALID temp_val
+#define SHOW_LICENSE_KEY rotop
+
+extern int LICENSE_KEY_VALID;
+extern int I_AM_PUBLISHER;
+
+extern char * license_key_name;
+extern void loadKeyboard(char * name);
+extern void checkhome(void);
+extern void SHOW_LICENSE_KEY(void);
+
+#define LICENSE_CHECK_0 (0==0)
+
+// Stuff from the Python files from Strubi
+
+typedef int (*Fptr)(void *);
+
+extern Fptr g_functab[];
+extern Fptr g_ptrtab[];
+
+// TODO: From here on, this should be a generated header file...
+
+// change all KEY_FUNC values
+// if you change PYKEY_TABLEN or PYKEY_SEED
+// see below
+
+#define PYKEY_TABLEN 21 // don't change this unless needed. Other values
+ // may yield bad random orders
+
+#define PYKEY_SEED {26,8,1972}
+
+// these values are generated by $HOME/develop/intern/keymaker/makeseed.py
+// from the above seed value.
+
+// DO NOT EDIT THESE VALUES BY HAND!
+
+#define KEY_FUNC1 12
+#define KEY_FUNC2 8
+#define KEY_FUNC3 1
+#define KEY_FUNC4 16
+#define KEY_FUNC5 20
+#define KEY_FUNC6 18
+#define KEY_FUNC7 13
+#define KEY_FUNC8 6
+#define KEY_FUNC9 9
+#define KEY_FUNC10 7
+#define KEY_FUNC11 14
+#define KEY_FUNC12 0
+#define KEY_FUNC13 5
+#define KEY_FUNC14 10
+#define KEY_FUNC15 19
+#define KEY_FUNC16 2
+#define KEY_FUNC17 11
+#define KEY_FUNC18 3
+#define KEY_FUNC19 17
+#define KEY_FUNC20 15
+#define KEY_FUNC21 4
+
+#endif
diff --git a/source/blender/include/mydevice.h b/source/blender/include/mydevice.h
new file mode 100644
index 00000000000..d87463cd7d9
--- /dev/null
+++ b/source/blender/include/mydevice.h
@@ -0,0 +1,242 @@
+
+#ifndef __MYDEVICE_H__
+#define __MYDEVICE_H__
+
+/*
+ *
+ * mouse / timer / window: tot 0x020
+ * eigen codes: 0x4...
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+
+
+/* MOUSE : 0x00x */
+
+#define LEFTMOUSE 0x001
+#define MIDDLEMOUSE 0x002
+#define RIGHTMOUSE 0x003
+#define MOUSEX 0x004
+#define MOUSEY 0x005
+
+/* timers */
+
+#define TIMER0 0x006
+#define TIMER1 0x007
+#define TIMER2 0x008
+#define TIMER3 0x009
+
+/* SYSTEM : 0x01x */
+
+#define KEYBD 0x010 /* keyboard */
+#define RAWKEYBD 0x011 /* raw keyboard for keyboard manager */
+#define REDRAW 0x012 /* used by port manager to signal redraws */
+#define INPUTCHANGE 0x013 /* input connected or disconnected */
+#define QFULL 0x014 /* queue was filled */
+#define WINFREEZE 0x015 /* user wants process in this win to shut up */
+#define WINTHAW 0x016 /* user wants process in this win to go again */
+#define WINCLOSE 0x017 /* window close */
+#define WINQUIT 0x018 /* signal from user that app is to go away */
+#define Q_FIRSTTIME 0x019 /* on startup */
+
+/* standard keyboard */
+
+#define AKEY 'a'
+#define BKEY 'b'
+#define CKEY 'c'
+#define DKEY 'd'
+#define EKEY 'e'
+#define FKEY 'f'
+#define GKEY 'g'
+#define HKEY 'h'
+#define IKEY 'i'
+#define JKEY 'j'
+#define KKEY 'k'
+#define LKEY 'l'
+#define MKEY 'm'
+#define NKEY 'n'
+#define OKEY 'o'
+#define PKEY 'p'
+#define QKEY 'q'
+#define RKEY 'r'
+#define SKEY 's'
+#define TKEY 't'
+#define UKEY 'u'
+#define VKEY 'v'
+#define WKEY 'w'
+#define XKEY 'x'
+#define YKEY 'y'
+#define ZKEY 'z'
+
+#define ZEROKEY '0'
+#define ONEKEY '1'
+#define TWOKEY '2'
+#define THREEKEY '3'
+#define FOURKEY '4'
+#define FIVEKEY '5'
+#define SIXKEY '6'
+#define SEVENKEY '7'
+#define EIGHTKEY '8'
+#define NINEKEY '9'
+
+#define CAPSLOCKKEY 211
+
+#define LEFTCTRLKEY 212
+#define LEFTALTKEY 213
+#define RIGHTALTKEY 214
+#define RIGHTCTRLKEY 215
+#define RIGHTSHIFTKEY 216
+#define LEFTSHIFTKEY 217
+
+#define ESCKEY 218
+#define TABKEY 219
+#define RETKEY 220
+#define SPACEKEY 221
+#define LINEFEEDKEY 222
+#define BACKSPACEKEY 223
+#define DELKEY 224
+#define SEMICOLONKEY 225
+#define PERIODKEY 226
+#define COMMAKEY 227
+#define QUOTEKEY 228
+#define ACCENTGRAVEKEY 229
+#define MINUSKEY 230
+#define SLASHKEY 232
+#define BACKSLASHKEY 233
+#define EQUALKEY 234
+#define LEFTBRACKETKEY 235
+#define RIGHTBRACKETKEY 236
+
+#define LEFTARROWKEY 137
+#define DOWNARROWKEY 138
+#define RIGHTARROWKEY 139
+#define UPARROWKEY 140
+
+#define PAD0 150
+#define PAD1 151
+#define PAD2 152
+#define PAD3 153
+#define PAD4 154
+#define PAD5 155
+#define PAD6 156
+#define PAD7 157
+#define PAD8 158
+#define PAD9 159
+
+
+#define PADPERIOD 199
+#define PADSLASHKEY 161
+#define PADASTERKEY 160
+
+
+#define PADMINUS 162
+#define PADENTER 163
+#define PADPLUSKEY 164
+
+
+#define F1KEY 300
+#define F2KEY 301
+#define F3KEY 302
+#define F4KEY 303
+#define F5KEY 304
+#define F6KEY 305
+#define F7KEY 306
+#define F8KEY 307
+#define F9KEY 308
+#define F10KEY 309
+#define F11KEY 310
+#define F12KEY 311
+
+#define PAUSEKEY 165
+#define INSERTKEY 166
+#define HOMEKEY 167
+#define PAGEUPKEY 168
+#define PAGEDOWNKEY 169
+#define ENDKEY 170
+
+#define UNKNOWNKEY 171
+
+/* **************** BLENDER QUEUE EVENTS ********************* */
+
+#define CHANGED 0x4000
+#define DRAWEDGES 0x4001
+#define AFTERQUEUE 0x4002
+#define BACKBUFDRAW 0x4003
+#define EXECUTE 0x4004
+#define IGNORE_REDRAW 0x4005
+#define LOAD_FILE 0x4006
+#define RESHAPE 0x4007
+#define UI_BUT_EVENT 0x4008
+#define AUTOSAVE_FILE 0x4009
+
+/* REDRAWVIEW3D moet de eerste zijn (laagste nummer) voor buttons! */
+#define REDRAWVIEW3D 0x4010
+
+#define REDRAWBUTSHEAD 0x4011
+#define REDRAWBUTSALL 0x4012
+#define REDRAWBUTSVIEW 0x4013
+#define REDRAWBUTSLAMP 0x4014
+#define REDRAWBUTSMAT 0x4015
+#define REDRAWBUTSTEX 0x4016
+#define REDRAWBUTSANIM 0x4017
+#define REDRAWBUTSWORLD 0x4018
+#define REDRAWBUTSRENDER 0x4019
+#define REDRAWBUTSEDIT 0x401A
+#define REDRAWVIEWCAM 0x401B
+#define REDRAWHEADERS 0x401C
+#define REDRAWBUTSGAME 0x401D
+#define REDRAWBUTSRADIO 0x401E
+#define REDRAWVIEW3D_Z 0x401F
+
+#define REDRAWALL 0x4020
+#define REDRAWINFO 0x4021
+#define RENDERPREVIEW 0x4022
+#define REDRAWIPO 0x4023
+#define REDRAWDATASELECT 0x4024
+#define REDRAWSEQ 0x4025
+#define REDRAWIMAGE 0x4026
+#define REDRAWOOPS 0x4027
+#define REDRAWIMASEL 0x4028
+#define AFTERIMASELIMA 0x4029
+#define AFTERIMASELGET 0x402A
+#define AFTERIMAWRITE 0x402B
+#define IMALEFTMOUSE 0x402C
+#define AFTERPIBREAD 0x402D
+#define REDRAWTEXT 0x402F
+#define REDRAWBUTSSCRIPT 0x4030
+#define REDRAWSOUND 0x4031
+#define REDRAWBUTSSOUND 0x4032
+#define REDRAWACTION 0x4033
+#define REDRAWBUTSCONSTRAINT 0x4034
+#define REDRAWNLA 0x4035
+
+#endif /* !__MYDEVICE_H__ */
diff --git a/source/blender/include/nla.h b/source/blender/include/nla.h
new file mode 100644
index 00000000000..d5685f9550e
--- /dev/null
+++ b/source/blender/include/nla.h
@@ -0,0 +1,63 @@
+/* nla.h May 2001
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * Use this to turn experimental options on
+ * or off with the #define flags. Please do not
+ * put other includes, typdefs etc in this file.
+ * ===========================================
+ *
+ * __NLA
+ * This encompasses the new armature object, the
+ * action datablock and the action window-type.
+ *
+ * __CON_IPO
+ * Support for constraint ipo keys
+ *
+ * __NLA_BAKE
+ * Allow users to bake constraints into keyframes
+ *
+ * __NLA_ACTION_BY_MOTION_ACTUATOR
+ * New action actuator playback type
+ *
+ * $Id$
+ */
+
+#ifndef NLA_H
+#define NLA_H
+
+#define __NLA
+
+#define __NLA_BAKE // Not for release: Not yet fully implemented
+#define __CON_IPO // Not for Release: Not yet fully implemented
+//#define __NLA_ACTION_BY_MOTION_ACTUATOR // Not for release: Not yet fully implemented
+
+#endif
+
diff --git a/source/blender/include/objfnt.h b/source/blender/include/objfnt.h
new file mode 100644
index 00000000000..b442a59e87d
--- /dev/null
+++ b/source/blender/include/objfnt.h
@@ -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 *****
+#ifndef OBJFNTDEF
+#define OBJFNTDEF
+
+typedef struct chardesc {
+ short movex, movey; /* advance */
+ short llx, lly; /* bounding box */
+ short urx, ury;
+ short *data; /* char data */
+ long datalen;
+} chardesc;
+
+typedef struct objfnt {
+ struct objfnt *freeaddr; /* if freeaddr != 0, objfnt is one chunck */
+ short type;
+ short charmin, charmax;
+ short my_nchars;
+ short scale;
+ chardesc *my_chars;
+} objfnt;
+
+#define OFMAGIC 0x93339333
+
+#define TM_TYPE 1
+#define PO_TYPE 2
+#define SP_TYPE 3
+
+/* ops for tmesh characters */
+
+#define TM_BGNTMESH (1)
+#define TM_SWAPTMESH (2)
+#define TM_ENDBGNTMESH (3)
+#define TM_RETENDTMESH (4)
+#define TM_RET (5)
+
+/* ops for poly characters */
+
+#define PO_BGNLOOP (1)
+#define PO_ENDBGNLOOP (2)
+#define PO_RETENDLOOP (3)
+#define PO_RET (4)
+
+/* ops for spline characters */
+
+#define SP_MOVETO (1)
+#define SP_LINETO (2)
+#define SP_CURVETO (3)
+#define SP_CLOSEPATH (4)
+#define SP_RETCLOSEPATH (5)
+#define SP_RET (6)
+
+
+#define MIN_ASCII ' '
+#define MAX_ASCII '~'
+#define NASCII (256 - 32)
+
+#define NOBBOX (30000)
+
+typedef struct pschar {
+ char *name;
+ int code;
+ int prog;
+} pschar;
+
+extern pschar charlist[NASCII];
+
+/* objfnt *fontname(void); */
+/* objfnt *readobjfnt(void); */
+/* objfnt *newobjfnt(void); */
+/* float fontstringwidth(void); */
+/* short *getcharprog(void); */
+/* chardesc *BLI_getchardesc(void); */
+/* char *asciiname(void); */
+
+#endif
diff --git a/source/blender/include/particle_effect.h b/source/blender/include/particle_effect.h
new file mode 100644
index 00000000000..588da7ee3d4
--- /dev/null
+++ b/source/blender/include/particle_effect.h
@@ -0,0 +1,48 @@
+/* dec 95
+ * jan feb 96
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 PARTICLE_EFFECT_H
+#define PARTICLE_EFFECT_H
+
+/* effect.c */
+extern Effect *add_effect(int type);
+extern PartEff *give_parteff(Object *ob);
+extern void where_is_particle(PartEff *paf, Particle *pa, float ctime, float *vec);
+extern void free_effect(Effect *eff);
+extern void free_effects(ListBase *lb);
+extern void copy_effects(ListBase *lbn, ListBase *lb);
+extern void build_particle_system(Object *ob);
+/* used externally */
+void set_buildvars(Object *ob, int *start, int *end);
+
+#endif
diff --git a/source/blender/include/playanim_ext.h b/source/blender/include/playanim_ext.h
new file mode 100644
index 00000000000..ffc8c6bce5d
--- /dev/null
+++ b/source/blender/include/playanim_ext.h
@@ -0,0 +1,40 @@
+/*
+ * external interface
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 PLAYANIM_EXT_H
+#define PLAYANIM_EXT_H
+
+/* used in apps */
+extern void playanim(int argc, char **argv);
+
+#endif
diff --git a/source/blender/inflate/BLO_in_de_flateHeader.h b/source/blender/inflate/BLO_in_de_flateHeader.h
new file mode 100644
index 00000000000..60196d0a2ee
--- /dev/null
+++ b/source/blender/inflate/BLO_in_de_flateHeader.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 *****
+ * zlib inflate and deflate stream header
+ */
+
+#ifndef BLO_IN_DE_FLATE_H
+#define BLO_IN_DE_FLATE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "BLO_sys_types.h"
+
+#define IN_DE_FLATEHEADERSTRUCTSIZE sizeof(struct BLO_in_de_flateHeaderStruct)
+
+/* POSIX datatypes, use BYTEORDER(3) */
+struct BLO_in_de_flateHeaderStruct {
+ uint8_t magic; /* poor mans header recognize check */
+ uint32_t compressedLength; /* how much compressed data is there */
+ uint32_t uncompressedLength; /* how much uncompressed data there is */
+ uint32_t dictionary_id; /* which dictionary are we using */
+ uint32_t dictId; /* Adler32 value of the dictionary */
+ uint32_t crc; /* header minus crc itself checksum */
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BLO_IN_DE_FLATE_H */
diff --git a/source/blender/inflate/BLO_inflate.h b/source/blender/inflate/BLO_inflate.h
new file mode 100644
index 00000000000..df27c62dece
--- /dev/null
+++ b/source/blender/inflate/BLO_inflate.h
@@ -0,0 +1,80 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * zlib inflate decompression wrapper library interface
+ */
+
+#ifndef BLO_INFLATE_H
+#define BLO_INFLATE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define INFLATE_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name
+
+INFLATE_DECLARE_HANDLE(BLO_inflateStructHandle);
+
+/**
+ * zlib inflate decompression initializer
+ * @retval pointer to inflate control structure
+ */
+
+ BLO_inflateStructHandle
+BLO_inflate_begin(
+ void *endControl);
+
+/**
+ * zlib inflate dataprocessor wrapper
+ * @param BLO_inflate Pointer to inflate control structure
+ * @param data Pointer to new data
+ * @param dataIn New data amount
+ * @retval streamGlueRead return value
+ */
+ int
+BLO_inflate_process(
+ BLO_inflateStructHandle BLO_inflate_handle,
+ unsigned char *data,
+ unsigned int dataIn);
+
+/**
+ * zlib inflate final call and cleanup
+ * @param BLO_inflate Pointer to inflate control structure
+ * @retval streamGlueRead return value
+ */
+ int
+BLO_inflate_end(
+ BLO_inflateStructHandle BLO_inflate_handle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BLO_INFLATE_H */
diff --git a/source/blender/inflate/Makefile b/source/blender/inflate/Makefile
new file mode 100644
index 00000000000..b19cfacf78a
--- /dev/null
+++ b/source/blender/inflate/Makefile
@@ -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 *****
+#
+# Bounces make to subdirectories.
+
+SOURCEDIR = source/blender/inflate
+DIRS = intern
+
+include nan_subdirs.mk
diff --git a/source/blender/inflate/intern/BLO_inflate.c b/source/blender/inflate/intern/BLO_inflate.c
new file mode 100644
index 00000000000..62c90fcb06a
--- /dev/null
+++ b/source/blender/inflate/intern/BLO_inflate.c
@@ -0,0 +1,431 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * zlib inflate decompression wrapper library
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "zlib.h"
+
+#include "GEN_messaging.h"
+
+#include "BLO_readStreamGlue.h"
+#include "BLO_in_de_flateHeader.h" /* used by deflate and inflate */
+
+#include "BLO_inflate.h"
+
+// TODO use other error function
+static int CHECK_ERR(int err, char *msg);
+
+static int CHECK_ERR(int err, char *msg)
+{
+ if (err != Z_OK) {
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "%s error: %d\n",
+ msg,
+ err);
+#endif
+ return 1;
+ }
+ return 0;
+}
+
+struct inflateStructType {
+ uInt compresSize; /* fixed compresBuf size in bytes */
+ Bytef *compresBuf; /* reusable fixed size output buffer for inflate */
+ struct readStreamGlueStruct *streamGlue;
+ struct BLO_in_de_flateHeaderStruct *streamHeader;
+ unsigned int streamDone;
+ unsigned char headerbuffer[IN_DE_FLATEHEADERSTRUCTSIZE];
+ z_stream d_stream; /* decompression stream */
+ char dictionary[50];
+ uLong dictId; /* Adler32 value of the dictionary */
+ void *endControl;
+};
+
+/**
+ * zlib inflate decompression initializer
+ * @retval pointer to inflate control structure
+ */
+ BLO_inflateStructHandle
+BLO_inflate_begin(
+ void *endControl)
+{
+ int err = 0; /* our own error */
+ char *errmessage = "inflateInit";
+
+ struct inflateStructType *control;
+ control = malloc(sizeof(struct inflateStructType));
+ if (!control) return NULL;
+
+ control->compresSize = (100000 * 1.1) + 12;
+ control->compresBuf = (Bytef *)malloc(control->compresSize);
+ if (!control->compresBuf) {
+ free(control);
+ return NULL;
+ }
+
+ control->streamGlue = NULL;
+ control->streamHeader = malloc(IN_DE_FLATEHEADERSTRUCTSIZE);
+ if (!control->streamHeader) {
+ free(control->compresBuf);
+ free(control);
+ return NULL;
+ }
+
+ control->streamHeader->magic = 0;
+ control->streamHeader->compressedLength = 0;
+ control->streamHeader->uncompressedLength = 0;
+ control->streamHeader->dictionary_id = 0;
+ control->streamHeader->dictId = 0;
+ control->streamHeader->crc = 0;
+ control->streamDone = 0;
+ memset(control->headerbuffer, 0, IN_DE_FLATEHEADERSTRUCTSIZE);
+ control->d_stream.zalloc = (alloc_func)0;
+ control->d_stream.zfree = (free_func)0;
+ control->d_stream.opaque = (voidpf)0;
+ // TODO use dictionary index, this is id = 1 :
+ strcpy(control->dictionary, "sure this is not a number");
+
+ /* we need to rewire this to also return err */
+ err = inflateInit(&(control->d_stream));
+ err = CHECK_ERR(err, errmessage);
+ if (err) {
+ free(control->compresBuf);
+ free(control->streamHeader);
+ free(control);
+ return NULL;
+ }
+
+ control->dictId = control->d_stream.adler;
+
+ control->d_stream.next_out = control->compresBuf;
+ control->d_stream.avail_out = control->compresSize;
+
+ control->d_stream.next_in = NULL;
+ control->d_stream.avail_in = 0;
+
+ control->endControl = endControl;
+ return((BLO_inflateStructHandle) control);
+}
+
+/**
+ * zlib inflate dataprocessor wrapper
+ * @param BLO_inflate Pointer to inflate control structure
+ * @param data Pointer to new data
+ * @param dataIn New data amount
+ * @retval streamGlueRead return value
+ */
+ int
+BLO_inflate_process(
+ BLO_inflateStructHandle BLO_inflate_handle,
+ unsigned char *data,
+ unsigned int dataIn)
+{
+ int zlib_err = 0;
+ int err = 0;
+ char *errmsg1 = "inflateSetDictionary";
+
+ struct inflateStructType *BLO_inflate =
+ (struct inflateStructType *) BLO_inflate_handle;
+
+ if (!BLO_inflate) {
+ err = BRS_SETFUNCTION(BRS_INFLATE) |
+ BRS_SETGENERR(BRS_NULL);
+ return err;
+ }
+
+ /* First check if we have our header filled in yet */
+ if (BLO_inflate->streamHeader->compressedLength == 0) {
+ unsigned int processed;
+ if (dataIn == 0) return err; /* really need data to do anything */
+ processed = ((dataIn + BLO_inflate->streamDone) <=
+ IN_DE_FLATEHEADERSTRUCTSIZE)
+ ? dataIn : IN_DE_FLATEHEADERSTRUCTSIZE;
+ memcpy(BLO_inflate->headerbuffer + BLO_inflate->streamDone,
+ data, processed);
+ BLO_inflate->streamDone += processed;
+ dataIn -= processed;
+ data += processed;
+ if (BLO_inflate->streamDone == IN_DE_FLATEHEADERSTRUCTSIZE) {
+ /* we have the whole header, absorb it */
+ struct BLO_in_de_flateHeaderStruct *header;
+ uint32_t crc;
+ header = (struct BLO_in_de_flateHeaderStruct *)
+ BLO_inflate->headerbuffer;
+ BLO_inflate->streamHeader->compressedLength =
+ ntohl(header->compressedLength);
+ BLO_inflate->streamHeader->uncompressedLength =
+ ntohl(header->uncompressedLength);
+ BLO_inflate->streamHeader->dictId =
+ ntohl(header->dictId);
+ BLO_inflate->streamHeader->dictionary_id =
+ ntohl(header->dictionary_id);
+ crc = crc32(0L, (const Bytef *) header,
+ IN_DE_FLATEHEADERSTRUCTSIZE - 4);
+
+ if (header->magic == 'B') {
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "BLO_in_de_flateHeaderStruct Magic confirmed\n");
+#endif
+ } else {
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "ERROR BLO_in_de_flateHeaderStruct Magic NOT confirmed\n");
+#endif
+ err = BRS_SETFUNCTION(BRS_INFLATE) |
+ BRS_SETGENERR(BRS_MAGIC);
+ if (BLO_inflate->streamGlue) free(BLO_inflate->streamGlue);
+ if (BLO_inflate->streamHeader) free(BLO_inflate->streamHeader);
+ if (BLO_inflate->compresBuf) free(BLO_inflate->compresBuf);
+ free(BLO_inflate);
+ return err;
+ }
+
+ if (crc == ntohl(header->crc)) {
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "BLO_in_de_flateHeader CRC correct\n");
+#endif
+ } else {
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "ERROR BLO_in_de_flateHeader CRC NOT correct\n");
+#endif
+ err = BRS_SETFUNCTION(BRS_INFLATE) |
+ BRS_SETGENERR(BRS_CRCHEADER);
+ if (BLO_inflate->streamGlue) free(BLO_inflate->streamGlue);
+ if (BLO_inflate->streamHeader) free(BLO_inflate->streamHeader);
+ if (BLO_inflate->compresBuf) free(BLO_inflate->compresBuf);
+ free(BLO_inflate);
+ return err;
+ }
+
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "BLO_inflate_process gets %u compressed bytes, will be %u uncompressed\n",
+ (unsigned int) BLO_inflate->streamHeader->compressedLength,
+ (unsigned int) BLO_inflate->streamHeader->uncompressedLength);
+#endif
+
+ }
+ }
+
+ /* Is there really (still) new data available ? */
+ if (dataIn > 0) {
+ int inflateWantsToLoopAgain = 0;
+ BLO_inflate->d_stream.next_in = data;
+ BLO_inflate->d_stream.avail_in = dataIn;
+ do {
+ zlib_err = inflate(&(BLO_inflate->d_stream), Z_SYNC_FLUSH);
+ if (zlib_err == Z_NEED_DICT) {
+ // TODO we can use BLO_inflate->d_stream.adler (it has
+ // multiple uses) to select the dictionary to use. This is id=1
+ zlib_err = inflateSetDictionary(&(BLO_inflate->d_stream),
+ (const Bytef*)BLO_inflate->dictionary,
+ strlen(BLO_inflate->dictionary));
+ err = CHECK_ERR(zlib_err, errmsg1);
+ if (err) {
+ err = BRS_SETFUNCTION(BRS_INFLATE) |
+ BRS_SETSPECERR(BRS_INFLATEERROR);
+ if (BLO_inflate->streamGlue) free(BLO_inflate->streamGlue);
+ if (BLO_inflate->streamHeader) free(BLO_inflate->streamHeader);
+ if (BLO_inflate->compresBuf) free(BLO_inflate->compresBuf);
+ free(BLO_inflate);
+ return err;
+ }
+
+ // go again
+ zlib_err = inflate(&(BLO_inflate->d_stream), Z_SYNC_FLUSH);
+ }
+ if (zlib_err == Z_STREAM_END) {
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "Note: inflate returned Z_STREAM_END\n");
+#endif
+ } else if (zlib_err != Z_OK) {
+#ifndef NDEBUG
+ fprintf(GEN_errorstream, "Error: inflate should return Z_OK, not %d\n", zlib_err);
+#endif
+ err = BRS_SETFUNCTION(BRS_INFLATE) |
+ BRS_SETSPECERR(BRS_INFLATEERROR);
+ if (BLO_inflate->streamGlue) free(BLO_inflate->streamGlue);
+ if (BLO_inflate->streamHeader) free(BLO_inflate->streamHeader);
+ if (BLO_inflate->compresBuf) free(BLO_inflate->compresBuf);
+ free(BLO_inflate);
+ return err;
+ }
+ if (BLO_inflate->d_stream.avail_out == 0) {
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "Note: inflate needs more output space, loop again %u\n",
+ (unsigned int) BLO_inflate->d_stream.avail_in);
+#endif
+ inflateWantsToLoopAgain = 1;
+ } else {
+#ifndef NDEBUG
+ if (inflateWantsToLoopAgain == 1)
+ fprintf(GEN_errorstream,
+ "Note: this is inflates last loop\n");
+#endif
+ inflateWantsToLoopAgain = 0;
+
+#ifndef NDEBUG
+ fprintf(GEN_errorstream, "inflated %u to %u (flushes) err=%d\n",
+ dataIn,
+ (unsigned int) (BLO_inflate->compresSize - BLO_inflate->d_stream.avail_out),
+ err);
+#endif
+ }
+
+ // give data to streamGlueRead, it will find out what to do next
+ err = readStreamGlue(
+ BLO_inflate->endControl,
+ &(BLO_inflate->streamGlue),
+ BLO_inflate->compresBuf,
+ BLO_inflate->compresSize - BLO_inflate->d_stream.avail_out);
+ BLO_inflate->d_stream.next_out = BLO_inflate->compresBuf;
+ BLO_inflate->d_stream.avail_out = BLO_inflate->compresSize;
+ } while (inflateWantsToLoopAgain == 1);
+ }
+ return err;
+}
+
+/**
+ * zlib inflate final call and cleanup
+ * @param BLO_inflate Pointer to inflate control structure
+ * @retval streamGlueRead return value
+ */
+ int
+BLO_inflate_end(
+ BLO_inflateStructHandle BLO_inflate_handle)
+{
+ char *errmsg2 = "inflateEnd";
+ int err = 0;
+ int zlib_err = 0;
+ struct inflateStructType *BLO_inflate =
+ (struct inflateStructType *) BLO_inflate_handle;
+ // TODO perhaps check streamHeader->totalStreamLength
+
+ if (!BLO_inflate) {
+ err = BRS_SETFUNCTION(BRS_INFLATE) |
+ BRS_SETGENERR(BRS_NULL);
+ return err;
+ }
+
+ BLO_inflate->d_stream.avail_in = 0;
+ // Note: do not also set BLO_inflate->d_stream.next_in to NULL, it
+ // is illegal (zlib.h:374) and causes a Z_STREAM_ERROR
+
+ zlib_err = inflate(&(BLO_inflate->d_stream), Z_FINISH);
+ if (zlib_err != Z_STREAM_END) {
+#ifdef NDEBUG
+ fprintf(GEN_errorstream,
+ "inflate should report Z_STREAM_END, not %d\n",
+ err);
+
+ if (BLO_inflate->d_stream.avail_out == 0) {
+ fprintf(GEN_errorstream,
+ "Error: inflate wanted more output buffer space\n");
+ // Note that we CANNOT inflate-loop again !
+ // But this should never happen because we Z_SYNC_FLUSH
+ }
+#endif
+ err = BRS_SETFUNCTION(BRS_INFLATE) |
+ BRS_SETSPECERR(BRS_INFLATEERROR);
+ if (BLO_inflate->streamGlue) free(BLO_inflate->streamGlue);
+ if (BLO_inflate->streamHeader) free(BLO_inflate->streamHeader);
+ if (BLO_inflate->compresBuf) free(BLO_inflate->compresBuf);
+ free(BLO_inflate);
+ return err;
+ }
+
+ zlib_err = inflateEnd(&(BLO_inflate->d_stream));
+ err = CHECK_ERR(zlib_err, errmsg2);
+ if (err) {
+ err = BRS_SETFUNCTION(BRS_INFLATE) |
+ BRS_SETSPECERR(BRS_INFLATEERROR);
+ if (BLO_inflate->streamGlue) free(BLO_inflate->streamGlue);
+ if (BLO_inflate->streamHeader) free(BLO_inflate->streamHeader);
+ if (BLO_inflate->compresBuf) free(BLO_inflate->compresBuf);
+ free(BLO_inflate);
+ return err;
+ }
+
+ if (BLO_inflate->d_stream.adler != BLO_inflate->dictId) {
+ // data was corrupted
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "Failed adler checksum\n");
+#endif
+ err = BRS_SETFUNCTION(BRS_INFLATE) |
+ BRS_SETGENERR(BRS_CRCDATA);
+ if (BLO_inflate->streamGlue) free(BLO_inflate->streamGlue);
+ if (BLO_inflate->streamHeader) free(BLO_inflate->streamHeader);
+ if (BLO_inflate->compresBuf) free(BLO_inflate->compresBuf);
+ free(BLO_inflate);
+ return err;
+ } else {
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "Passed adler checksum\n");
+#endif
+ }
+
+ /* ready decompressing */
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "DeCompressed %ld bytes to %ld (%.0f%%)\n",
+ BLO_inflate->d_stream.total_in, BLO_inflate->d_stream.total_out,
+ 100. * (float)BLO_inflate->d_stream.total_out /
+ (float)BLO_inflate->d_stream.total_in);
+#endif
+
+ err = readStreamGlue(
+ BLO_inflate->endControl,
+ &(BLO_inflate->streamGlue),
+ BLO_inflate->compresBuf,
+ BLO_inflate->compresSize - BLO_inflate->d_stream.avail_out);
+
+ BLO_inflate->d_stream.next_out = BLO_inflate->compresBuf;
+ BLO_inflate->d_stream.avail_out = BLO_inflate->compresSize;
+
+ if (BLO_inflate->streamGlue) free(BLO_inflate->streamGlue);
+ if (BLO_inflate->streamHeader) free(BLO_inflate->streamHeader);
+ if (BLO_inflate->compresBuf) free(BLO_inflate->compresBuf);
+ free(BLO_inflate);
+
+ return err;
+}
+
diff --git a/source/blender/inflate/intern/Makefile b/source/blender/inflate/intern/Makefile
new file mode 100644
index 00000000000..9582b6c81c6
--- /dev/null
+++ b/source/blender/inflate/intern/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 *****
+#
+#
+
+LIBNAME = inflate
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+ifeq ($(OS),$(findstring $(OS), "beos darwin freebsd linux openbsd solaris windows"))
+ CFLAGS += -funsigned-char
+endif
+
+CFLAGS += $(LEVEL_1_C_WARNINGS)
+
+# path to our own external headerfiles
+CPPFLAGS += -I..
+
+# external modules
+CPPFLAGS += -I../../../kernel/gen_messaging
+CPPFLAGS += -I../../readstreamglue
+
+ifeq ($(OS),$(findstring $(OS), "solaris windows"))
+ CPPFLAGS += -I$(NAN_ZLIB)/include
+endif
+
diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h
new file mode 100644
index 00000000000..9800f4a5f31
--- /dev/null
+++ b/source/blender/makesdna/DNA_ID.h
@@ -0,0 +1,152 @@
+/**
+ * blenlib/DNA_ID.h (mar-2001 nzc)
+ *
+ * ID and Library types, which are fundamental for sdna,
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 DNA_ID_H
+#define DNA_ID_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* There's a nasty circular dependency here.... void* to the rescue! I
+ * really wonder why this is needed. */
+
+struct Library;
+struct FileData;
+
+/* let op: Sequence heeft identiek begin. */
+/**
+ * ID is the first thing included in all serializable types. It
+ * provides a common handle to place all data in double-linked lists.
+ * */
+typedef struct ID {
+ void *next, *prev;
+ struct ID *newid;
+ struct Library *lib;
+ char name[24];
+ short us;
+ /**
+ * LIB_... flags report on status of the datablock this ID belongs
+ * to.
+ */
+ short flag;
+ int pad;
+} ID;
+
+/**
+ * ??
+ */
+typedef struct Library {
+ ID id;
+ ID *idblock;
+ struct FileData *filedata;
+ char name[160];
+ int tot, pad; /* tot, idblock en filedata zijn voor lezen en schrijven */
+} Library;
+
+/**
+ * Defines for working with IDs.
+ *
+ * The tags represent types! This is a dirty way of enabling RTTI. The
+ * sig_byte end endian defines aren't really used much.
+ *
+ **/
+
+#if defined(__sgi) || defined(__sparc) || defined (__PPC__) || defined (__ppc__) || defined (__BIG_ENDIAN__)
+/* big endian */
+#define MAKE_ID2(c, d) ( (c)<<8 | (d) )
+#define MOST_SIG_BYTE 0
+#define BBIG_ENDIAN
+#else
+/* little endian */
+#define MAKE_ID2(c, d) ( (d)<<8 | (c) )
+#define MOST_SIG_BYTE 1
+#define BLITTLE_ENDIAN
+#endif
+
+/* ID */
+#define ID_SCE MAKE_ID2('S', 'C')
+#define ID_LI MAKE_ID2('L', 'I')
+#define ID_OB MAKE_ID2('O', 'B')
+#define ID_ME MAKE_ID2('M', 'E')
+#define ID_CU MAKE_ID2('C', 'U')
+#define ID_MB MAKE_ID2('M', 'B')
+#define ID_MA MAKE_ID2('M', 'A')
+#define ID_TE MAKE_ID2('T', 'E')
+#define ID_IM MAKE_ID2('I', 'M')
+#define ID_IK MAKE_ID2('I', 'K')
+#define ID_WV MAKE_ID2('W', 'V')
+#define ID_LT MAKE_ID2('L', 'T')
+#define ID_SE MAKE_ID2('S', 'E')
+#define ID_LF MAKE_ID2('L', 'F')
+#define ID_LA MAKE_ID2('L', 'A')
+#define ID_CA MAKE_ID2('C', 'A')
+#define ID_IP MAKE_ID2('I', 'P')
+#define ID_KE MAKE_ID2('K', 'E')
+#define ID_WO MAKE_ID2('W', 'O')
+#define ID_SCR MAKE_ID2('S', 'R')
+#define ID_VF MAKE_ID2('V', 'F')
+#define ID_TXT MAKE_ID2('T', 'X')
+#define ID_SO MAKE_ID2('S', 'O')
+#define ID_SAMPLE MAKE_ID2('S', 'A')
+#define ID_GR MAKE_ID2('G', 'R')
+#define ID_ID MAKE_ID2('I', 'D')
+#define ID_SEQ MAKE_ID2('S', 'Q')
+#define ID_AR MAKE_ID2('A', 'R')
+#define ID_AC MAKE_ID2('A', 'C')
+
+#define IPO_CO MAKE_ID2('C', 'O') /* NOTE! This is not an ID, but is needed for g.sipo->blocktype */
+
+/* id->flag: eerste 8 bits altijd op nul zetten bij inlezen */
+/* (always zero the first 8 bits when reading a file) */
+#define LIB_LOCAL 0
+#define LIB_EXTERN 1
+#define LIB_INDIRECT 2
+#define LIB_TEST 8
+#define LIB_TESTEXT 9
+#define LIB_TESTIND 10
+#define LIB_READ 16
+#define LIB_NEEDLINK 32
+
+#define LIB_NEW 256
+#define LIB_FAKEUSER 512
+/* vrije testflag */
+#define LIB_DOIT 1024
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h
new file mode 100644
index 00000000000..abcd7f3d9c6
--- /dev/null
+++ b/source/blender/makesdna/DNA_action_types.h
@@ -0,0 +1,102 @@
+/* DNA_action_types.h May 2001
+ *
+ * support for the "action" datatype
+ *
+ * Reevan McKay
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 DNA_ACTION_TYPES_H
+#define DNA_ACTION_TYPES_H
+
+#include "DNA_listBase.h"
+#include "DNA_ID.h"
+#include "DNA_view2d_types.h"
+
+struct SpaceLink;
+
+typedef struct bPoseChannel{
+ struct bPoseChannel *next, *prev;
+ ListBase constraints;
+ int flag;
+ float loc[3];
+ float size[3];
+ float quat[4];
+ float obmat[4][4];
+ char name[32]; /* Channels need longer names than normal blender objects */
+ int reserved1;
+} bPoseChannel;
+
+
+typedef struct bPose{
+ ListBase chanbase;
+} bPose;
+
+typedef struct bActionChannel {
+ struct bActionChannel *next, *prev;
+ struct Ipo *ipo;
+ ListBase constraintChannels;
+ int flag;
+ char name[32]; /* Channel name */
+ int reserved1;
+
+} bActionChannel;
+
+typedef struct bAction {
+ ID id;
+ ListBase chanbase; /* Channels in this action */
+ bActionChannel *achan; /* Current action channel */
+ bPoseChannel *pchan; /* Current pose channel */
+} bAction;
+
+typedef struct SpaceAction {
+ struct SpaceLink *next, *prev;
+ int spacetype, pad;
+ struct ScrArea *area;
+
+ View2D v2d;
+ bAction *action;
+ int flag;
+ short pin, reserved1;
+ short actnr;
+ short lock;
+ int pad2;
+} SpaceAction;
+
+/* Action Channel flags */
+#define ACHAN_SELECTED 0x00000001
+#define ACHAN_HILIGHTED 0x00000002
+
+
+#endif
+
diff --git a/source/blender/makesdna/DNA_actuator_types.h b/source/blender/makesdna/DNA_actuator_types.h
new file mode 100644
index 00000000000..1a97fa88846
--- /dev/null
+++ b/source/blender/makesdna/DNA_actuator_types.h
@@ -0,0 +1,405 @@
+/**
+ * blenlib/DNA_actuator_types.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 DNA_ACTUATOR_TYPES_H
+#define DNA_ACTUATOR_TYPES_H
+
+struct Object;
+struct Mesh;
+struct Scene;
+struct Group;
+
+/* ****************** ACTUATORS ********************* */
+
+/* unused now, moved to editobjectactuator in 2.02. Still needed for dna */
+typedef struct bAddObjectActuator {
+ int time, pad;
+ struct Object *ob;
+} bAddObjectActuator;
+
+typedef struct bActionActuator {
+ struct bAction *act; /* Pointer to action */
+ short type, flag; /* Playback type */
+ short sta, end; /* Start & End frames */
+ char name[32]; /* For property-driven playback */
+ short blendin; /* Number of frames of blending */
+ short priority; /* Execution priority */
+ float stridelength; /* Displacement incurred by cycle */
+ short strideaxis; /* Displacement axis */
+ short reserved1; /* Padding */
+ short reserved2; /* Padding */
+ short reserved3; /* Padding */
+} bActionActuator;
+
+typedef struct bSoundActuator {
+ short flag, sndnr;
+ short sta, end;
+ struct bSound *sound;
+ short type, makecopy;
+ short copymade, pad[1];
+} bSoundActuator;
+
+typedef struct bCDActuator {
+ short flag, sndnr;
+ short sta, end;
+ short type, track;
+ float volume;
+} bCDActuator;
+
+typedef struct bEditObjectActuator {
+ int time;
+ short type, flag;
+ struct Object *ob;
+ struct Mesh *me;
+ char name[32];
+ float linVelocity[3]; /* initial lin. velocity on creation */
+ short localflag; /* flag for the lin. vel: apply locally */
+ short pad;
+} bEditObjectActuator;
+
+typedef struct bSceneActuator {
+ short type, flag;
+ int pad;
+ struct Scene *scene;
+ struct Object *camera;
+} bSceneActuator;
+
+typedef struct bPropertyActuator {
+ int flag, type;
+ char name[32], value[32];
+ struct Object *ob;
+} bPropertyActuator;
+
+typedef struct bObjectActuator {
+ int flag, type;
+ float forceloc[3], forcerot[3];
+ float loc[3], rot[3];
+ float dloc[3], drot[3];
+ float linearvelocity[3], angularvelocity[3];
+// float addedlinearvelocity[3];
+// char anotherpad[4];
+} bObjectActuator;
+
+typedef struct bIpoActuator {
+ short flag, type;
+ short sta, end;
+ char name[32];
+
+ short pad1, cur, butsta, butend;
+
+} bIpoActuator;
+
+typedef struct bCameraActuator {
+ struct Object *ob;
+ float height, min, max;
+ float fac;
+ short flag, axis;
+ float visifac;
+} bCameraActuator ;
+
+typedef struct bConstraintActuator {
+ short flag, damp;
+ float slow;
+ float minloc[3], maxloc[3];
+ float minrot[3], maxrot[3];
+} bConstraintActuator;
+
+typedef struct bGroupActuator {
+ short flag, type;
+ short sta, end;
+ char name[32]; /* property or groupkey */
+
+ short pad1, cur, butsta, butend;
+ struct Group *group; /* only during game */
+
+} bGroupActuator;
+
+/* I added a few extra fields here, to facilitate conversions */
+typedef struct bRandomActuator {
+ int seed;
+ int distribution;
+ int int_arg_1;
+ int int_arg_2;
+ float float_arg_1;
+ float float_arg_2;
+ char propname[32];
+} bRandomActuator;
+
+typedef struct bMessageActuator {
+ /**
+ * Send to all objects with this propertyname. Empty to broadcast.
+ */
+ char toPropName[32];
+
+ /**
+ * (Possible future use) pointer to a single destination object.
+ */
+ struct Object *toObject;
+
+ /**
+ * Message Subject to send.
+ */
+ char subject[32];
+
+ /**
+ * bodyType is either 'User defined text' or PropName
+ */
+ short bodyType, pad1;
+ int pad2;
+
+ /**
+ * Either User Defined Text or our PropName to send value of
+ */
+ char body[32];
+} bMessageActuator;
+
+typedef struct bGameActuator {
+ short flag, type;
+ short sta, end;
+ char filename[64];
+ char loadaniname[64];
+} bGameActuator;
+
+typedef struct bVisibilityActuator {
+ /** bit 0: Is this object visible? */
+ int flag;
+} bVisibilityActuator;
+
+typedef struct bActuator {
+ struct bActuator *next, *prev, *mynew;
+ short type;
+ /**
+ * Tells what type of actuator data <data> holds.
+ */
+ short flag;
+ short otype, go;
+ char name[32];
+
+ /**
+ * Data must point to an object actuator type struct.
+ */
+ void *data;
+
+ /**
+ * For ipo's and props: to find out which object the actuator
+ * belongs to */
+ struct Object *ob;
+
+} bActuator;
+
+typedef struct FreeCamera {
+ float mass, accelleration;
+ float maxspeed, maxrotspeed, maxtiltspeed;
+ int flag;
+ float rotdamp, tiltdamp, speeddamp, pad;
+} FreeCamera;
+
+/* objectactuator->flag */
+#define ACT_FORCE_LOCAL 1
+#define ACT_TORQUE_LOCAL 2
+#define ACT_DLOC_LOCAL 4
+#define ACT_DROT_LOCAL 8
+#define ACT_LIN_VEL_LOCAL 16
+#define ACT_ANG_VEL_LOCAL 32
+//#define ACT_ADD_LIN_VEL_LOCAL 64
+#define ACT_ADD_LIN_VEL 64
+
+#define ACT_OBJECT_FORCE 0
+#define ACT_OBJECT_TORQUE 1
+#define ACT_OBJECT_DLOC 2
+#define ACT_OBJECT_DROT 3
+#define ACT_OBJECT_LINV 4
+#define ACT_OBJECT_ANGV 5
+
+/* actuator->type */
+#define ACT_OBJECT 0
+#define ACT_IPO 1
+#define ACT_LAMP 2
+#define ACT_CAMERA 3
+#define ACT_MATERIAL 4
+#define ACT_SOUND 5
+#define ACT_PROPERTY 6
+ /* these two obsolete since 2.02 */
+#define ACT_ADD_OBJECT 7
+#define ACT_END_OBJECT 8
+
+#define ACT_CONSTRAINT 9
+#define ACT_EDIT_OBJECT 10
+#define ACT_SCENE 11
+#define ACT_GROUP 12
+#define ACT_RANDOM 13
+#define ACT_MESSAGE 14
+#define ACT_ACTION 15 /* __ NLA */
+#define ACT_CD 16
+#define ACT_GAME 17
+#define ACT_VISIBILITY 18
+
+/* actuator flag */
+#define ACT_SHOW 1
+#define ACT_DEL 2
+#define ACT_NEW 4
+
+/* link codes */
+#define LINK_SENSOR 0
+#define LINK_CONTROLLER 1
+#define LINK_ACTUATOR 2
+
+/* keyboardsensor->type */
+#define SENS_ALL_KEYS 1
+
+/* actionactuator->type */
+#define ACT_ACTION_PLAY 0
+#define ACT_ACTION_PINGPONG 1
+#define ACT_ACTION_FLIPPER 2
+#define ACT_ACTION_LOOP_STOP 3
+#define ACT_ACTION_LOOP_END 4
+#define ACT_ACTION_KEY2KEY 5
+#define ACT_ACTION_FROM_PROP 6
+#define ACT_ACTION_MOTION 7
+
+/* ipoactuator->type */
+#define ACT_IPO_PLAY 0
+#define ACT_IPO_PINGPONG 1
+#define ACT_IPO_FLIPPER 2
+#define ACT_IPO_LOOP_STOP 3
+#define ACT_IPO_LOOP_END 4
+#define ACT_IPO_KEY2KEY 5
+#define ACT_IPO_FROM_PROP 6
+
+/* groupactuator->type */
+#define ACT_GROUP_PLAY 0
+#define ACT_GROUP_PINGPONG 1
+#define ACT_GROUP_FLIPPER 2
+#define ACT_GROUP_LOOP_STOP 3
+#define ACT_GROUP_LOOP_END 4
+#define ACT_GROUP_FROM_PROP 5
+#define ACT_GROUP_SET 6
+
+/* ipoactuator->flag */
+#define ACT_IPOFORCE_BIT 0
+#define ACT_IPOEND_BIT 1
+#define ACT_IPOFORCE_LOCAL_BIT 2
+// unused: 3
+#define ACT_IPOCHILD_BIT 4
+
+#define ACT_IPOFORCE (1 << ACT_IPOFORCE_BIT)
+#define ACT_IPOEND (1 << ACT_IPOEND_BIT)
+#define ACT_IPOFORCE_LOCAL (1 << ACT_IPOFORCE_LOCAL_BIT)
+#define ACT_IPOCHILD (1 << ACT_IPOCHILD_BIT)
+
+/* ipoactuator->flag for k2k */
+#define ACT_K2K_PREV 1
+#define ACT_K2K_CYCLIC 2
+#define ACT_K2K_PINGPONG 4
+#define ACT_K2K_HOLD 8
+
+/* property actuator->type */
+#define ACT_PROP_ASSIGN 0
+#define ACT_PROP_ADD 1
+#define ACT_PROP_COPY 2
+
+/* constraint flag */
+#define ACT_CONST_LOCX 1
+#define ACT_CONST_LOCY 2
+#define ACT_CONST_LOCZ 4
+#define ACT_CONST_ROTX 8
+#define ACT_CONST_ROTY 16
+#define ACT_CONST_ROTZ 32
+
+/* editObjectActuator->type */
+#define ACT_EDOB_ADD_OBJECT 0
+#define ACT_EDOB_END_OBJECT 1
+#define ACT_EDOB_REPLACE_MESH 2
+#define ACT_EDOB_TRACK_TO 3
+#define ACT_EDOB_MAKE_CHILD 4
+#define ACT_EDOB_END_CHILD 5
+
+/* editObjectActuator->flag */
+#define ACT_TRACK_3D 1
+
+/* SceneActuator->type */
+#define ACT_SCENE_RESTART 0
+#define ACT_SCENE_SET 1
+#define ACT_SCENE_CAMERA 2
+#define ACT_SCENE_ADD_FRONT 3
+#define ACT_SCENE_ADD_BACK 4
+#define ACT_SCENE_REMOVE 5
+#define ACT_SCENE_SUSPEND 6
+#define ACT_SCENE_RESUME 7
+
+
+/* randomAct->distribution */
+#define ACT_RANDOM_BOOL_CONST 0
+#define ACT_RANDOM_BOOL_UNIFORM 1
+#define ACT_RANDOM_BOOL_BERNOUILLI 2
+#define ACT_RANDOM_INT_CONST 3
+#define ACT_RANDOM_INT_UNIFORM 4
+#define ACT_RANDOM_INT_POISSON 5
+#define ACT_RANDOM_FLOAT_CONST 6
+#define ACT_RANDOM_FLOAT_UNIFORM 7
+#define ACT_RANDOM_FLOAT_NORMAL 8
+#define ACT_RANDOM_FLOAT_NEGATIVE_EXPONENTIAL 9
+
+/* SoundActuator->type */
+#define ACT_SND_PLAY_STOP_SOUND 0
+#define ACT_SND_PLAY_END_SOUND 1
+#define ACT_SND_LOOP_STOP_SOUND 2
+#define ACT_SND_LOOP_END_SOUND 3
+#define ACT_SND_LOOP_BIDIRECTIONAL_SOUND 4
+#define ACT_SND_LOOP_BIDIRECTIONAL_STOP_SOUND 5
+
+/* messageactuator->type */
+#define ACT_MESG_MESG 0
+#define ACT_MESG_PROP 1
+
+/* cdactuator->type */
+#define ACT_CD_PLAY_ALL 0
+#define ACT_CD_PLAY_TRACK 1
+#define ACT_CD_LOOP_TRACK 2
+#define ACT_CD_VOLUME 3
+#define ACT_CD_STOP 4
+#define ACT_CD_PAUSE 5
+#define ACT_CD_RESUME 6
+
+/* gameactuator->type */
+#define ACT_GAME_LOAD 0
+#define ACT_GAME_START 1
+#define ACT_GAME_RESTART 2
+#define ACT_GAME_QUIT 3
+
+/* visibilityact->flag */
+/* Set means the object will become invisible */
+#define ACT_VISIBILITY_INVISIBLE_BIT 0
+#define ACT_VISIBILITY_INVISIBLE (1 << ACT_VISIBILITY_INVISIBLE_BIT)
+
+#endif
diff --git a/source/blender/makesdna/DNA_armature_types.h b/source/blender/makesdna/DNA_armature_types.h
new file mode 100644
index 00000000000..af2476b5e0c
--- /dev/null
+++ b/source/blender/makesdna/DNA_armature_types.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 *****
+ */
+
+
+#ifndef DNA_ARMATURE_TYPES_H
+#define DNA_ARMATURE_TYPES_H
+
+#include "DNA_listBase.h"
+#include "DNA_ID.h"
+
+typedef struct Bone {
+ struct Bone *next, *prev; /* Next/prev elements within this list */
+ struct Bone *parent; /* Parent (ik parent if appropriate flag is set */
+ ListBase childbase; /* Children */
+ char name[32]; /* Name of the bone - must be unique within the armature */
+
+ float roll;
+ float head[3]; /* Orientation & length are implicit now */
+ float tail[3]; /* head/tail represents rest state */
+ int flag;
+
+ /* Transformation data used for posing:
+ The same information stored by other
+ blenderObjects
+ */
+
+ float dist, weight;
+ float loc[3], dloc[3];
+ float size[3], dsize[3];
+ float quat[4], dquat[4];
+ float obmat[4][4];
+ float parmat[4][4];
+ float defmat[4][4];
+ float irestmat[4][4]; /* Cached inverse of rest matrix (objectspace)*/
+ float posemat[4][4]; /* Cached pose matrix (objectspace)*/
+}Bone;
+
+typedef struct bArmature {
+ ID id;
+ ListBase bonebase;
+ ListBase chainbase;
+ int flag;
+ int res1;
+ int res2;
+ int res3;
+}bArmature;
+
+enum {
+ ARM_RESTPOSBIT = 0,
+ ARM_UNUSED1BIT, /* Free for use */
+ ARM_DRAWAXESBIT,
+ ARM_DRAWNAMESBIT,
+ ARM_POSEBIT,
+ ARM_EDITBIT
+};
+
+enum {
+ ARM_RESTPOS = 0x00000001,
+ ARM_UNUSED1 = 0x00000002, /* Free for use */
+ ARM_DRAWAXES = 0x00000004,
+ ARM_DRAWNAMES = 0x00000008,
+ ARM_POSEMODE = 0x00000010,
+ ARM_EDITMODE = 0x00000020
+};
+
+enum {
+ BONE_SELECTED = 0x00000001,
+ BONE_ROOTSEL = 0x00000002,
+ BONE_TIPSEL = 0x00000004,
+
+ BONE_HILIGHTED = 0x00000008,
+ BONE_IK_TOPARENT= 0x00000010,
+ BONE_QUATROT = 0x00000020,
+ BONE_HIDDEN = 0x00000040,
+
+ BONE_DONE = 0x00000080, /* For detecting cyclic dependancies */
+
+ BONE_ISEMPTY = 0x00000100,
+ BONE_ISMUSCLE = 0x00000200
+};
+
+enum {
+ BONE_SELECTEDBIT = 0,
+ BONE_HEADSELBIT,
+ BONE_TAILSELBIT,
+ BONE_HILIGHTEDBIT,
+ BONE_IK_TOPARENTBIT,
+ BONE_QUATROTBIT,
+ BONE_HIDDENBIT,
+ BONE_ISEMPTYBIT,
+ BONE_ISMUSCLEBIT
+};
+
+
+#endif
diff --git a/source/blender/makesdna/DNA_camera_types.h b/source/blender/makesdna/DNA_camera_types.h
new file mode 100644
index 00000000000..71a429ba59e
--- /dev/null
+++ b/source/blender/makesdna/DNA_camera_types.h
@@ -0,0 +1,77 @@
+/**
+ * blenlib/DNA_camera_types.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 DNA_CAMERA_TYPES_H
+#define DNA_CAMERA_TYPES_H
+
+#include "DNA_ID.h"
+#include "DNA_scriptlink_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct Ipo;
+
+typedef struct Camera {
+ ID id;
+
+ short type, flag, drawzoom, hold;
+ float clipsta, clipend;
+ float netsta, netend; /* network camera */
+ float lens, drawsize;
+ float hololen, hololen1;
+
+ struct Ipo *ipo;
+
+ ScriptLink scriptlink;
+} Camera;
+
+/* **************** CAMERA ********************* */
+
+/* type */
+#define CAM_PERSP 0
+#define CAM_ORTHO 1
+
+/* flag */
+#define CAM_SHOWLIMITS 1
+#define CAM_SHOWMIST 2
+
+#define CAM_HOLO1 16
+#define CAM_HOLO2 32
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h
new file mode 100644
index 00000000000..02199b9aa01
--- /dev/null
+++ b/source/blender/makesdna/DNA_constraint_types.h
@@ -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 *****
+ * Constraint DNA data
+ */
+
+#ifndef DNA_CONSTRAINT_TYPES_H
+#define DNA_CONSTRAINT_TYPES_H
+
+#include "DNA_ID.h"
+#include "DNA_ipo_types.h"
+#include "DNA_object_types.h"
+
+struct Action;
+
+typedef struct bConstraintChannel{
+ struct bConstraintChannel *next, *prev;
+ Ipo *ipo;
+ short flag;
+ char name[30];
+} bConstraintChannel;
+
+typedef struct bConstraint{
+ struct bConstraint *next, *prev;
+ void *data; /* Constraint data (a valid constraint type) */
+ Ipo *ipo; /* Constraint ipo */
+ char type; /* Constraint type */
+ char otype; /* Old type - for menu callbacks */
+ short flag; /* Flag */
+ short reserved1;
+ char name[30]; /* Constraint name */
+
+ float enforce;
+ float time;
+ float offset[3]; /* Target location offset */
+ float orient[3]; /* Target orientation offset */
+ float roll[3]; /* Target roll offset (needed?) */
+} bConstraint;
+
+/* Single-target subobject constraints */
+typedef struct bKinematicConstraint{
+ Object *tar;
+ float tolerance; /* Acceptable distance from target */
+ int iterations; /* Maximum number of iterations to try */
+ char subtarget[32]; /* String to specify sub-object target */
+
+ float cacheeff[3]; /* Target location cache */
+ int reserved1;
+
+ float cachemat[4][4]; /* Result cache */
+} bKinematicConstraint;
+
+typedef struct bTrackToConstraint{
+ Object *tar;
+ int reserved1;
+ int reserved2;
+ char subtarget[32];
+} bTrackToConstraint;
+
+typedef struct bRotateLikeConstraint{
+ Object *tar;
+ int flag;
+ int reserved1;
+ char subtarget[32];
+} bRotateLikeConstraint;
+
+typedef struct bLocateLikeConstraint{
+ Object *tar;
+ int flag;
+ int reserved1;
+ char subtarget[32];
+} bLocateLikeConstraint;
+
+typedef struct bActionConstraint{
+ Object *tar;
+ int type;
+ short start;
+ short end;
+ float min;
+ float max;
+ struct bAction *act;
+ char subtarget[32];
+} bActionConstraint;
+
+/* Single-target object constraints */
+typedef struct bFollowPathConstraint{
+ Object *tar; /* Must be path object */
+} bFollowPathConstraint;
+
+/* Zero-target constraints */
+typedef struct bRotationConstraint{
+ float xmin, xmax;
+ float ymin, ymax;
+ float zmin, zmax;
+} bRotationConstraint;
+
+/* bConstraint.type */
+#define CONSTRAINT_TYPE_NULL 0
+#define CONSTRAINT_TYPE_CHILDOF 1 /* Unimplemented */
+#define CONSTRAINT_TYPE_TRACKTO 2
+#define CONSTRAINT_TYPE_KINEMATIC 3
+#define CONSTRAINT_TYPE_FOLLOWPATH 4 /* Unimplemented */
+#define CONSTRAINT_TYPE_ROTLIMIT 5 /* Unimplemented */
+#define CONSTRAINT_TYPE_LOCLIMIT 6 /* Unimplemented */
+#define CONSTRAINT_TYPE_SIZELIMIT 7 /* Unimplemented */
+#define CONSTRAINT_TYPE_ROTLIKE 8
+#define CONSTRAINT_TYPE_LOCLIKE 9
+#define CONSTRAINT_TYPE_SIZELIKE 10 /* Unimplemented */
+#define CONSTRAINT_TYPE_PYTHON 11 /* Unimplemented */
+#define CONSTRAINT_TYPE_ACTION 12
+
+/* bConstraint.flag */
+#define CONSTRAINT_EXPAND 0x00000001
+#define CONSTRAINT_DONE 0x00000002
+#define CONSTRAINT_DISABLE 0x00000004
+#define CONSTRAINT_LOOPTESTED 0x00000008
+
+#define CONSTRAINT_EXPAND_BIT 0
+#define CONSTRAINT_DONE_BIT 1
+#define CONSTRAINT_DISABLE_BIT 2
+
+/* bConstraintChannel.flag */
+#define CONSTRAINT_CHANNEL_SELECT 0x00000001
+
+/* bLocateLikeConstraint.flag */
+#define LOCLIKE_X 0x00000001
+#define LOCLIKE_Y 0x00000002
+#define LOCLIKE_Z 0x00000004
+
+#endif
+
diff --git a/source/blender/makesdna/DNA_controller_types.h b/source/blender/makesdna/DNA_controller_types.h
new file mode 100644
index 00000000000..1d73d27a045
--- /dev/null
+++ b/source/blender/makesdna/DNA_controller_types.h
@@ -0,0 +1,78 @@
+/**
+ * blenlib/DNA_controller_types.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 DNA_CONTROLLER_TYPES_H
+#define DNA_CONTROLLER_TYPES_H
+
+struct bActuator;
+struct Text;
+struct bSensor;
+
+/* ****************** CONTROLLERS ********************* */
+
+typedef struct bExpressionCont {
+ char str[128];
+} bExpressionCont;
+
+typedef struct bPythonCont {
+ struct Text *text;
+} bPythonCont;
+
+typedef struct bController {
+ struct bController *next, *prev, *mynew;
+ short type, flag, inputs, totlinks;
+ short otype, totslinks, pad2, pad3;
+
+ char name[32];
+ void *data;
+
+ struct bActuator **links;
+
+ struct bSensor **slinks;
+ short val, valo;
+ int pad5;
+
+} bController;
+
+/* controller->type */
+#define CONT_LOGIC_AND 0
+#define CONT_LOGIC_OR 1
+#define CONT_EXPRESSION 2
+#define CONT_PYTHON 3
+
+/* controller->flag */
+#define CONT_SHOW 1
+#define CONT_DEL 2
+#define CONT_NEW 4
+
+#endif
diff --git a/source/blender/makesdna/DNA_curve_types.h b/source/blender/makesdna/DNA_curve_types.h
new file mode 100644
index 00000000000..6fb7c01ca27
--- /dev/null
+++ b/source/blender/makesdna/DNA_curve_types.h
@@ -0,0 +1,202 @@
+/**
+ * blenlib/DNA_curve_types.h (mar-2001 nzc)
+ *
+ * Curve stuff.
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 DNA_CURVE_TYPES_H
+#define DNA_CURVE_TYPES_H
+
+#include "DNA_listBase.h"
+#include "DNA_vec_types.h"
+#include "DNA_ID.h"
+
+struct BoundBox;
+struct Object;
+struct Ipo;
+struct Key;
+struct Material;
+struct VFont;
+
+#
+#
+typedef struct Path {
+ int len;
+ float *data;
+ float totdist;
+} Path;
+
+#
+#
+typedef struct BevList {
+ struct BevList *next, *prev;
+ short nr, flag;
+ short poly, gat;
+} BevList;
+
+#
+#
+typedef struct BevPoint {
+ float x, y, z, alfa, sina, cosa, mat[3][3];
+ short f1, f2;
+} BevPoint;
+
+
+typedef struct BezTriple {
+ float vec[3][3];
+ float alfa;
+ short s[3][2];
+ short h1, h2;
+ char f1, f2, f3, hide;
+} BezTriple;
+
+typedef struct BPoint {
+ float vec[4];
+ float alfa;
+ short s[2];
+ short f1, hide;
+} BPoint;
+
+typedef struct Nurb {
+ struct Nurb *next, *prev;
+ short type, mat_nr;
+ short hide, flag;
+ short pntsu, pntsv;
+ short resolu, resolv;
+ short orderu, orderv;
+ short flagu, flagv;
+
+ float *knotsu, *knotsv;
+ BPoint *bp;
+ BezTriple *bezt;
+
+} Nurb;
+
+
+typedef struct Curve {
+ ID id;
+
+ struct BoundBox *bb;
+
+ ListBase nurb;
+ ListBase disp;
+ struct Object *bevobj, *textoncurve;
+ struct Ipo *ipo;
+ Path *path;
+ struct Key *key;
+ struct Material **mat;
+
+ ListBase bev;
+ float *orco;
+
+ float loc[3];
+ float size[3];
+ float rot[3];
+
+ int texflag;
+
+ short pathlen, totcol;
+ short flag, bevresol;
+ float width, ext1, ext2;
+
+ /* default */
+ short resolu, resolv;
+
+ /* font stuk */
+ short len, lines, pos, spacemode;
+ float spacing, linedist, shear, fsize;
+ float xof, yof;
+
+ char *str, family[24];
+ struct VFont *vfont;
+
+} Curve;
+
+typedef struct IpoCurve {
+ struct IpoCurve *next, *prev;
+
+ struct BPoint *bp;
+ struct BezTriple *bezt;
+
+ rctf maxrct, totrct;
+
+ short blocktype, adrcode, vartype;
+ short totvert;
+ short ipo, extrap;
+ short flag, rt;
+ float ymin, ymax;
+ unsigned int bitmask;
+
+ float curval;
+
+} IpoCurve;
+
+/* **************** CURVE ********************* */
+
+/* flag */
+#define CU_3D 1
+#define CU_FRONT 2
+#define CU_BACK 4
+#define CU_PATH 8
+#define CU_FOLLOW 16
+#define CU_UV_ORCO 32
+#define CU_NOPUNOFLIP 64
+
+/* spacemode */
+#define CU_LEFT 0
+#define CU_MIDDLE 1
+#define CU_RIGHT 2
+#define CU_FLUSH 3
+
+/* flag (nurb) */
+#define CU_SMOOTH ME_SMOOTH
+
+/* type (nurb) */
+#define CU_POLY 0
+#define CU_BEZIER 1
+#define CU_BSPLINE 2
+#define CU_CARDINAL 3
+#define CU_NURBS 4
+#define CU_2D 8
+
+/* flagu flagv (nurb) */
+#define CU_CYCLIC 1
+
+/* h1 h2 (beztriple) */
+#define HD_FREE 0
+#define HD_AUTO 1
+#define HD_VECT 2
+#define HD_ALIGN 3
+
+
+
+#endif
diff --git a/source/blender/makesdna/DNA_documentation.h b/source/blender/makesdna/DNA_documentation.h
new file mode 100644
index 00000000000..dd8e2d06fb8
--- /dev/null
+++ b/source/blender/makesdna/DNA_documentation.h
@@ -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 *****
+ *
+ * @mainpage DNA- Makesdna modules
+ *
+ * @section about About the DNA module
+ *
+ * The DNA module holds all type definitions that are serialized in a
+ * blender file. There is an executable that scans all files, looking
+ * for struct-s to serialize (hence sdna: Struct DNA). From this
+ * information, it builds a file with numbers that encode the format,
+ * the names of variables, and the plce to look for them.
+ *
+ * @section issues Known issues with DNA
+ *
+ * - Function pointers:
+ *
+ * Because of historical reasons, some function pointers were
+ * untyped. The parser/dna generator has been modified to explicitly
+ * handle these special cases. Most pointers have been given proper
+ * proto's by now. DNA_space_types.h::Spacefile::returnfuncmay still
+ * be badly defined. The reason for this is that is is called with
+ * different types of arguments. It takes a char* at this moment...
+ *
+ * - Path to the header files
+ *
+ * Also because of historical reasons, there is a path prefix to the
+ * headers that need to be scanned. This is the BASE_HEADER
+ * define. If you change the file-layout for DNA, you will probably
+ * have to change this (Not very flexible, but it is hardly ever
+ * changed. Sorry.).
+ *
+ * @section dependencies Dependencies
+ *
+ * DNA has no external dependencies (except for a few system
+ * includes).
+ *
+ **/
+
+/* This file has intentionally no definitions or implementation. */
diff --git a/source/blender/makesdna/DNA_effect_types.h b/source/blender/makesdna/DNA_effect_types.h
new file mode 100644
index 00000000000..3962e1ef5eb
--- /dev/null
+++ b/source/blender/makesdna/DNA_effect_types.h
@@ -0,0 +1,127 @@
+/**
+ * blenlib/DNA_effect_types.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 DNA_EFFECT_TYPES_H
+#define DNA_EFFECT_TYPES_H
+
+/* DENK ERAAN: NIEUWE EFFECTEN OOK IN DE WRITEFILE.C IVM DNA!!! */
+
+#define PAF_MAXMULT 4
+
+ /* paf->flag (bitje 0 vrij houden ivm compatibility) */
+#define PAF_BSPLINE 2
+#define PAF_STATIC 4
+#define PAF_FACE 8
+
+ /* eff->type */
+#define EFF_BUILD 0
+#define EFF_PARTICLE 1
+#define EFF_WAVE 2
+
+ /* eff->flag */
+#define EFF_SELECT 1
+#define EFF_CYCLIC 2
+
+ /* paf->stype */
+#define PAF_NORMAL 0
+#define PAF_VECT 1
+
+ /* paf->texmap */
+#define PAF_TEXINT 0
+#define PAF_TEXRGB 1
+#define PAF_TEXGRAD 2
+
+ /* wav->flag */
+#define WAV_X 2
+#define WAV_Y 4
+#define WAV_CYCL 8
+
+
+typedef struct Effect {
+ struct Effect *next, *prev;
+ short type, flag, buttype, rt;
+
+} Effect;
+
+typedef struct BuildEff {
+ struct BuildEff *next, *prev;
+ short type, flag, buttype, rt;
+
+ float len, sfra;
+
+} BuildEff;
+
+#
+#
+typedef struct Particle {
+ float co[3], no[3];
+ float time, lifetime;
+ short mat_nr, rt;
+} Particle;
+
+
+typedef struct PartEff {
+ struct PartEff *next, *prev;
+ short type, flag, buttype, stype;
+
+ float sta, end, lifetime;
+ int totpart, totkey, seed;
+
+ float normfac, obfac, randfac, texfac, randlife;
+ float force[3];
+ float damp;
+
+ float nabla, vectsize, defvec[3];
+
+ float mult[4], life[4];
+ short child[4], mat[4];
+ short texmap, curmult;
+ short staticstep, pad;
+
+ Particle *keys;
+
+} PartEff;
+
+
+typedef struct WaveEff {
+ struct WaveEff *next, *prev;
+ short type, flag, buttype, stype;
+
+ float startx, starty, height, width;
+ float narrow, speed, minfac, damp;
+
+ float timeoffs, lifetime;
+
+} WaveEff;
+
+#endif
diff --git a/source/blender/makesdna/DNA_fileglobal_types.h b/source/blender/makesdna/DNA_fileglobal_types.h
new file mode 100644
index 00000000000..73403f6ff01
--- /dev/null
+++ b/source/blender/makesdna/DNA_fileglobal_types.h
@@ -0,0 +1,47 @@
+/**
+ * blenlib/DNA_fileglobal_types.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 DNA_FILEGLOBAL_TYPES_H
+#define DNA_FILEGLOBAL_TYPES_H
+
+/**
+ * FileGlobal stores a part of the current user-unterface settings at
+ * the moment of saving, and the file-specific settings.
+ */
+typedef struct FileGlobal {
+ void *curscreen;
+ short displaymode, winpos;
+ int fileflags;
+} FileGlobal;
+
+#endif
diff --git a/source/blender/makesdna/DNA_group_types.h b/source/blender/makesdna/DNA_group_types.h
new file mode 100644
index 00000000000..c8521c1505e
--- /dev/null
+++ b/source/blender/makesdna/DNA_group_types.h
@@ -0,0 +1,100 @@
+/**
+ * blenlib/DNA_group_types.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 DNA_GROUP_TYPES_H
+#define DNA_GROUP_TYPES_H
+
+#include "DNA_listBase.h"
+#include "DNA_ID.h"
+
+struct Object;
+struct Ipo;
+
+typedef struct GroupKey {
+ struct GroupKey *next, *prev;
+ short sfra, efra;
+ float cfra;
+ char name[32];
+} GroupKey;
+
+typedef struct ObjectKey {
+ struct ObjectKey *next, *prev;
+ GroupKey *gkey; /* for reference */
+
+ /* copy of relevant data */
+ short partype, pad;
+ int par1, par2, par3;
+
+ struct Object *parent, *track;
+ struct Ipo *ipo;
+
+ /* this block identical to object */
+ float loc[3], dloc[3], orig[3];
+ float size[3], dsize[3];
+ float rot[3], drot[3];
+ float quat[4], dquat[4];
+ float obmat[4][4];
+ float parentinv[4][4];
+ float imat[4][4]; /* voor bij render, tijdens simulate, tijdelijk: ipokeys van transform */
+
+ unsigned int lay; /* kopie van Base */
+
+ char transflag, ipoflag;
+ char trackflag, upflag;
+
+ float sf, ctime, padf;
+
+
+} ObjectKey;
+
+typedef struct GroupObject {
+ struct GroupObject *next, *prev;
+ struct Object *ob;
+ ListBase okey; /* ObjectKey */
+
+} GroupObject;
+
+
+typedef struct Group {
+ ID id;
+
+ ListBase gobject; /* GroupObject */
+ ListBase gkey; /* GroupKey */
+
+ GroupKey *active;
+
+} Group;
+
+
+
+#endif
diff --git a/source/blender/makesdna/DNA_ika_types.h b/source/blender/makesdna/DNA_ika_types.h
new file mode 100644
index 00000000000..9afab711f98
--- /dev/null
+++ b/source/blender/makesdna/DNA_ika_types.h
@@ -0,0 +1,91 @@
+/**
+ * blenlib/DNA_ika_types.h (mar-2001 nzc)
+ *
+ * Old ika types. These will be superceded by Reevan's stuff, soon (I
+ * hope).
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 DNA_IKA_TYPES_H
+#define DNA_IKA_TYPES_H
+
+#include "DNA_listBase.h"
+#include "DNA_ID.h"
+
+struct Object;
+struct Ipo;
+
+typedef struct Deform {
+ struct Object *ob;
+ short flag, partype;
+ int par1, par2, par3; /* kunnen vertexnrs zijn */
+ float imat[4][4], premat[4][4], postmat[4][4];
+ float vec[3]; /* als partype==LIMB, voor distfunc */
+ float fac, dist, pad;
+
+} Deform;
+
+typedef struct Limb {
+ struct Limb *next, *prev;
+
+ float len, leno, fac, alpha, alphao, pad;
+ float eff[2];
+
+} Limb;
+
+typedef struct Ika {
+ ID id;
+
+ short partype, flag, iter, lastfra;
+
+ ListBase limbbase;
+ float eff[3], effg[3], effn[3]; /* current, global en (local)wanted */
+ float mem, slow, toty, totx, xyconstraint;
+
+ struct Ipo *ipo;
+ struct Object *parent;
+ int par1, par2, par3; /* kunnen vertexnrs zijn */
+
+ int totdef;
+ Deform *def;
+
+ int def_scroll;
+ int limb_scroll;
+} Ika;
+
+/* these defines are used for working with ikas*/
+
+/* ika.flag: */
+#define IK_GRABEFF 1
+#define IK_XYCONSTRAINT 2
+
+
+#endif
diff --git a/source/blender/makesdna/DNA_image_types.h b/source/blender/makesdna/DNA_image_types.h
new file mode 100644
index 00000000000..11dcde8de2b
--- /dev/null
+++ b/source/blender/makesdna/DNA_image_types.h
@@ -0,0 +1,86 @@
+/**
+ * blenlib/DNA_image_types.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 DNA_IMAGE_TYPES_H
+#define DNA_IMAGE_TYPES_H
+
+#include "DNA_ID.h"
+
+struct PackedFile;
+struct anim;
+struct ImBuf;
+
+typedef struct Image {
+ ID id;
+
+ char name[160];
+
+ struct anim *anim;
+ struct ImBuf *ibuf;
+ struct ImBuf *mipmap[10];
+
+ short ok, flag;
+ short lastframe, lastquality;
+
+ /* texture pagina */
+ short tpageflag, totbind;
+ short xrep, yrep;
+ short twsta, twend;
+ unsigned int bindcode;
+ unsigned int *repbind; /* om subregio's te kunnen repeaten */
+
+ struct PackedFile * packedfile;
+
+ float lastupdate;
+ short animspeed;
+ short reserved1;
+} Image;
+
+/* in Image struct */
+#define MAXMIPMAP 10
+
+/* **************** IMAGE ********************* */
+
+/* flag */
+#define IMA_HALVE 1
+#define IMA_BW 2
+#define IMA_FROMANIM 4
+#define IMA_USED 8
+#define IMA_REFLECT 16
+
+/* tpageflag */
+#define IMA_TILES 1
+#define IMA_TWINANIM 2
+#define IMA_COLCYCLE 4 /* Depreciated */
+
+#endif
diff --git a/source/blender/makesdna/DNA_ipo_types.h b/source/blender/makesdna/DNA_ipo_types.h
new file mode 100644
index 00000000000..2f332b680c0
--- /dev/null
+++ b/source/blender/makesdna/DNA_ipo_types.h
@@ -0,0 +1,302 @@
+/**
+ * blenlib/DNA_ipo_types.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 DNA_IPO_TYPES_H
+#define DNA_IPO_TYPES_H
+
+#include "DNA_listBase.h"
+#include "DNA_vec_types.h"
+
+#include "DNA_ID.h"
+
+typedef struct Ipo {
+ ID id;
+
+ ListBase curve;
+ rctf cur;
+ short blocktype, showkey;
+ int pad;
+
+} Ipo;
+
+/* sometimes used */
+
+typedef short IPO_Channel;
+
+/* defines: are these duped or new? */
+
+#define IPOBUTY 17
+
+
+/* disptype */
+#define IPO_DISPDEGR 1
+#define IPO_DISPBITS 2
+#define IPO_DISPTIME 3
+
+/* ******************** */
+
+#define OB_TOTIPO 24
+
+#define OB_LOC_X 1
+#define OB_LOC_Y 2
+#define OB_LOC_Z 3
+#define OB_DLOC_X 4
+#define OB_DLOC_Y 5
+#define OB_DLOC_Z 6
+
+#define OB_ROT_X 7
+#define OB_ROT_Y 8
+#define OB_ROT_Z 9
+#define OB_DROT_X 10
+#define OB_DROT_Y 11
+#define OB_DROT_Z 12
+
+#define OB_SIZE_X 13
+#define OB_SIZE_Y 14
+#define OB_SIZE_Z 15
+#define OB_DSIZE_X 16
+#define OB_DSIZE_Y 17
+#define OB_DSIZE_Z 18
+
+#define OB_LAY 19
+
+#define OB_TIME 20
+
+#define OB_EFF_X 21
+#define OB_EFF_Y 22
+#define OB_EFF_Z 23
+
+#define OB_COL_R 21
+#define OB_COL_G 22
+#define OB_COL_B 23
+#define OB_COL_A 24
+
+
+
+/* ******************** */
+
+#define MA_TOTIPO 32
+
+#define MA_COL_R 1
+#define MA_COL_G 2
+#define MA_COL_B 3
+#define MA_SPEC_R 4
+#define MA_SPEC_G 5
+#define MA_SPEC_B 6
+#define MA_MIR_R 7
+#define MA_MIR_G 8
+#define MA_MIR_B 9
+#define MA_REF 10
+#define MA_ALPHA 11
+#define MA_EMIT 12
+#define MA_AMB 13
+#define MA_SPEC 14
+#define MA_HARD 15
+#define MA_SPTR 16
+#define MA_ANG 17
+#define MA_MODE 18
+#define MA_HASIZE 19
+
+#define MA_MAP1 0x20
+#define MA_MAP2 0x40
+#define MA_MAP3 0x80
+#define MA_MAP4 0x100
+#define MA_MAP5 0x200
+#define MA_MAP6 0x400
+#define MA_MAP7 0x800
+#define MA_MAP8 0x1000
+
+#define MAP_OFS_X 1
+#define MAP_OFS_Y 2
+#define MAP_OFS_Z 3
+#define MAP_SIZE_X 4
+#define MAP_SIZE_Y 5
+#define MAP_SIZE_Z 6
+#define MAP_R 7
+#define MAP_G 8
+#define MAP_B 9
+
+#define MAP_DVAR 10
+#define MAP_COLF 11
+#define MAP_NORF 12
+#define MAP_VARF 13
+
+/* ******************** */
+
+#define SEQ_TOTIPO 1
+
+#define SEQ_FAC1 1
+
+/* ******************** */
+
+#define CU_TOTIPO 1
+
+#define CU_SPEED 1
+
+/* ******************** */
+
+#define KEY_TOTIPO 32
+
+#define KEY_SPEED 0
+#define KEY_NR 1
+
+/* ******************** */
+
+#define WO_TOTIPO 29
+
+#define WO_HOR_R 1
+#define WO_HOR_G 2
+#define WO_HOR_B 3
+#define WO_ZEN_R 4
+#define WO_ZEN_G 5
+#define WO_ZEN_B 6
+
+#define WO_EXPOS 7
+
+#define WO_MISI 8
+#define WO_MISTDI 9
+#define WO_MISTSTA 10
+#define WO_MISTHI 11
+
+#define WO_STAR_R 12
+#define WO_STAR_G 13
+#define WO_STAR_B 14
+#define WO_STARDIST 15
+#define WO_STARSIZE 16
+
+/* ******************** */
+
+#define LA_TOTIPO 23
+
+#define LA_ENERGY 1
+#define LA_COL_R 2
+#define LA_COL_G 3
+#define LA_COL_B 4
+#define LA_DIST 5
+#define LA_SPOTSI 6
+#define LA_SPOTBL 7
+#define LA_QUAD1 8
+#define LA_QUAD2 9
+#define LA_HALOINT 10
+
+/* ******************** */
+
+#define CAM_TOTIPO 3
+
+#define CAM_LENS 1
+#define CAM_STA 2
+#define CAM_END 3
+
+
+/* ******************** */
+
+#define SND_TOTIPO 4
+
+#define SND_VOLUME 1
+#define SND_PITCH 2
+#define SND_PANNING 3
+#define SND_ATTEN 4
+
+/* ******************** */
+
+#define AC_TOTIPO 10 /* __NLA */
+
+#define AC_LOC_X 1
+#define AC_LOC_Y 2
+#define AC_LOC_Z 3
+
+#define AC_SIZE_X 13
+#define AC_SIZE_Y 14
+#define AC_SIZE_Z 15
+
+#define AC_QUAT_W 25
+#define AC_QUAT_X 26
+#define AC_QUAT_Y 27
+#define AC_QUAT_Z 28
+
+/* ******************** */
+#define CO_TOTIPO 1 /* Constraint Ipos */
+
+#define CO_ENFORCE 1
+/*
+#define CO_TIME 2
+#define CO_OFFSET_X 3
+#define CO_OFFSET_Y 4
+#define CO_OFFSET_Z 5
+#define CO_ORIENT_X 6
+#define CO_ORIENT_Y 7
+#define CO_ORIENT_Z 8
+#define CO_ROLL 9
+*/
+
+/* these are ipo-specific */
+/* **************** IPO ********************* */
+
+/* vartype */
+#define IPO_CHAR 0
+#define IPO_SHORT 1
+#define IPO_INT 2
+#define IPO_LONG 3
+#define IPO_FLOAT 4
+#define IPO_DOUBLE 5
+#define IPO_FLOAT_DEGR 6
+/* zeer speciaal geval in keys */
+#define IPO_BEZTRIPLE 100
+#define IPO_BPOINT 101
+
+
+#define IPO_BITS 16
+#define IPO_CHAR_BIT 16
+#define IPO_SHORT_BIT 17
+#define IPO_INT_BIT 18
+
+/* ipo */
+#define IPO_CONST 0
+#define IPO_LIN 1
+#define IPO_BEZ 2
+#define IPO_MIXED 3
+
+/* extrap */
+#define IPO_HORIZ 0
+#define IPO_DIR 1
+#define IPO_CYCL 2
+#define IPO_CYCLX 3
+
+/* flag */
+#define IPO_VISIBLE 1
+#define IPO_SELECT 2
+#define IPO_EDIT 4
+#define IPO_LOCK 8
+
+
+#endif
diff --git a/source/blender/makesdna/DNA_key_types.h b/source/blender/makesdna/DNA_key_types.h
new file mode 100644
index 00000000000..ed2c3308d5f
--- /dev/null
+++ b/source/blender/makesdna/DNA_key_types.h
@@ -0,0 +1,84 @@
+/**
+ * blenlib/DNA_key_types.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 DNA_KEY_TYPES_H
+#define DNA_KEY_TYPES_H
+
+#include "DNA_listBase.h"
+#include "DNA_ID.h"
+
+struct Ipo;
+
+typedef struct KeyBlock {
+ struct KeyBlock *next, *prev;
+
+ float pos;
+ short flag, totelem;
+ short type, rt;
+ int pad;
+
+ void *data;
+
+} KeyBlock;
+
+
+typedef struct Key {
+ ID id;
+
+ KeyBlock *refkey;
+ char elemstr[32];
+ int elemsize;
+ float curval;
+
+ ListBase block;
+ struct Ipo *ipo;
+
+ ID *from;
+
+ short type, totkey;
+ short slurph, actkey;
+
+} Key;
+
+/* **************** KEY ********************* */
+
+/* type */
+#define KEY_NORMAL 0
+#define KEY_RELATIVE 1
+
+/* keyblock->type */
+#define KEY_LINEAR 0
+#define KEY_CARDINAL 1
+#define KEY_BSPLINE 2
+
+#endif
diff --git a/source/blender/makesdna/DNA_lamp_types.h b/source/blender/makesdna/DNA_lamp_types.h
new file mode 100644
index 00000000000..90ac306edc8
--- /dev/null
+++ b/source/blender/makesdna/DNA_lamp_types.h
@@ -0,0 +1,96 @@
+/**
+ * blenlib/DNA_lamp_types.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 DNA_LAMP_TYPES_H
+#define DNA_LAMP_TYPES_H
+
+#include "DNA_ID.h"
+#include "DNA_scriptlink_types.h"
+
+struct MTex;
+struct Ipo;
+
+typedef struct Lamp {
+ ID id;
+
+ short type, mode;
+
+ short colormodel, totex;
+ float r, g, b, k;
+
+ float energy, dist, spotsize, spotblend;
+ float haint;
+ float att1, att2;
+
+ short bufsize, samp;
+ float clipsta, clipend, shadspotsize;
+ float bias, soft;
+
+ /* texact is voor buttons */
+ short texact, shadhalostep;
+
+ struct MTex *mtex[8];
+ struct Ipo *ipo;
+
+ ScriptLink scriptlink;
+} Lamp;
+
+/* **************** LAMP ********************* */
+
+/* type */
+#define LA_LOCAL 0
+#define LA_SUN 1
+#define LA_SPOT 2
+#define LA_HEMI 3
+
+/* mode */
+#define LA_SHAD 1
+#define LA_HALO 2
+#define LA_LAYER 4
+#define LA_QUAD 8
+#define LA_NEG 16
+#define LA_ONLYSHADOW 32
+#define LA_SPHERE 64
+#define LA_SQUARE 128
+#define LA_TEXTURE 256
+#define LA_OSATEX 512
+/* use bit 11 for shadow tests... temp only -nzc- */
+#define LA_DEEP_SHADOW 1024
+
+/* mapto */
+#define LAMAP_COL 1
+
+/* bit isolated... */
+#define MAXLAMP 256
+
+#endif
diff --git a/source/blender/makesdna/DNA_lattice_types.h b/source/blender/makesdna/DNA_lattice_types.h
new file mode 100644
index 00000000000..adda253d434
--- /dev/null
+++ b/source/blender/makesdna/DNA_lattice_types.h
@@ -0,0 +1,65 @@
+/**
+ * blenlib/DNA_mesh_types.h (mar-2001 nzc)
+ *
+ * Mesh stuff.
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 DNA_LATTICE_TYPES_H
+#define DNA_LATTICE_TYPES_H
+
+#include "DNA_ID.h"
+
+struct BPoint;
+struct Ipo;
+struct Key;
+
+typedef struct Lattice {
+ ID id;
+
+ short pntsu, pntsv, pntsw, flag;
+ char typeu, typev, typew, type;
+ int pad;
+
+ struct BPoint *def;
+
+ struct Ipo *ipo;
+ struct Key *key;
+
+} Lattice;
+
+/* ***************** LATTICE ********************* */
+
+/* flag */
+#define LT_GRID 1
+#define LT_OUTSIDE 2
+
+#endif
diff --git a/source/blender/makesdna/DNA_listBase.h b/source/blender/makesdna/DNA_listBase.h
new file mode 100644
index 00000000000..817edd4ef9d
--- /dev/null
+++ b/source/blender/makesdna/DNA_listBase.h
@@ -0,0 +1,63 @@
+/**
+ * blenlib/BLI_listBase.h mar 2001 Nzc
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * These structs are the foundation for all linked lists in the
+ * library system.
+ *
+ */
+
+#ifndef DNA_LISTBASE_H
+#define DNA_LISTBASE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct Link
+{
+ struct Link *next,*prev;
+} Link;
+
+/* never change the size of this! genfile.c detects pointerlen with it */
+typedef struct ListBase
+{
+ void *first, *last;
+} ListBase;
+
+/* 8 byte alignment! */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/source/blender/makesdna/DNA_material_types.h b/source/blender/makesdna/DNA_material_types.h
new file mode 100644
index 00000000000..dad4a427baa
--- /dev/null
+++ b/source/blender/makesdna/DNA_material_types.h
@@ -0,0 +1,162 @@
+/**
+ * blenlib/DNA_material_types.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 DNA_MATERIAL_TYPES_H
+#define DNA_MATERIAL_TYPES_H
+
+/* #include "BLI_listBase.h" */
+
+#include "DNA_ID.h"
+#include "DNA_scriptlink_types.h"
+
+struct MTex;
+struct Ipo;
+struct Material;
+
+/* LET OP: type veranderen? ook in ipo.h doen */
+
+typedef struct Material {
+ ID id;
+
+ short colormodel, lay; /* lay: voor dynamics */
+ float r, g, b;
+ float specr, specg, specb;
+ float mirr, mirg, mirb;
+ float ambr, ambb, ambg;
+
+ float amb, emit, ang, spectra;
+ float alpha, ref, spec, zoffs, add;
+ float kfac; /* for transparent solids */
+ short har;
+ char seed1, seed2;
+
+ int mode;
+ int mode2; /* even more material settings :) */
+ short flarec, starc, linec, ringc;
+ float hasize, flaresize, subsize, flareboost;
+
+ /* onderstaand is voor buttons en render*/
+ char rgbsel, texact, pr_type, septex;
+ short pr_back, pr_lamp;
+
+ int pad1;
+ short texco, mapto;
+
+ struct MTex *mtex[8];
+ struct Ipo *ipo;
+ struct Material *ren;
+
+ /* dynamic properties */
+ float friction, fh, reflect;
+ float fhdist, xyfrict;
+ short dynamode, pad;
+
+ ScriptLink scriptlink;
+} Material;
+
+/* **************** MATERIAL ********************* */
+
+ /* maximum number of materials per material array
+ * (on object, mesh, lamp, etc.)
+ */
+#define MAXMAT 16
+
+/* colormodel */
+#define MA_RGB 0
+#define MA_CMYK 1
+#define MA_YUV 2
+#define MA_HSV 3
+
+/* mode (is int) */
+#define MA_TRACEBLE 1
+#define MA_SHADOW 2
+#define MA_SHLESS 4
+#define MA_WIRE 8
+#define MA_VERTEXCOL 16
+#define MA_HALO 32
+#define MA_ZTRA 64
+#define MA_VERTEXCOLP 128
+#define MA_ZINV 256
+#define MA_HALO_RINGS 256
+#define MA_ENV 512
+#define MA_HALO_LINES 512
+#define MA_ONLYSHADOW 1024
+#define MA_HALO_XALPHA 1024
+#define MA_STAR 0x800
+#define MA_FACETEXTURE 0x800
+#define MA_HALOTEX 0x1000
+#define MA_HALOPUNO 0x2000
+#define MA_NOMIST 0x4000
+#define MA_HALO_SHADE 0x4000
+#define MA_HALO_FLARE 0x8000
+
+/* dynamode */
+#define MA_DRAW_DYNABUTS 1
+#define MA_FH_NOR 2
+
+/* texco */
+#define TEXCO_ORCO 1
+#define TEXCO_REFL 2
+#define TEXCO_NORM 4
+#define TEXCO_GLOB 8
+#define TEXCO_UV 16
+#define TEXCO_OBJECT 32
+#define TEXCO_LAVECTOR 64
+#define TEXCO_VIEW 128
+#define TEXCO_STICKY 256
+#define TEXCO_OSA 512
+#define TEXCO_WINDOW 1024
+#define NEED_UV 2048
+
+/* mapto */
+#define MAP_COL 1
+#define MAP_NORM 2
+#define MAP_COLSPEC 4
+#define MAP_COLMIR 8
+#define MAP_VARS (0xFFF0)
+#define MAP_REF 16
+#define MAP_SPEC 32
+#define MAP_EMIT 64
+#define MAP_ALPHA 128
+#define MAP_HAR 256
+#define MAP_XTRA 512
+
+/* pr_type */
+#define MA_FLAT 0
+#define MA_SPHERE 1
+#define MA_CUBE 2
+
+/* pr_back */
+#define MA_DARK 1
+
+#endif
diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h
new file mode 100644
index 00000000000..20e79a5b632
--- /dev/null
+++ b/source/blender/makesdna/DNA_mesh_types.h
@@ -0,0 +1,229 @@
+/**
+ * blenlib/DNA_mesh_types.h (mar-2001 nzc)
+ *
+ * Mesh stuff.
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 DNA_MESH_TYPES_H
+#define DNA_MESH_TYPES_H
+
+#include "DNA_listBase.h"
+#include "DNA_ID.h"
+
+struct Ipo;
+struct Key;
+struct Material;
+struct MVert;
+struct MCol;
+struct MSticky;
+struct Mesh;
+struct OcInfo;
+struct bDeformGroup;
+
+/* This little gem is needed to satisfy the curious realms of sdna. On
+ * the other hand, it also interferes with sys/types.h, so we get rid
+ * of it asap. */
+
+#define ushort unsigned short
+
+typedef struct MFace {
+/* unsigned short v1, v2, v3, v4; */
+ ushort v1, v2, v3, v4;
+ char puno, mat_nr;
+ char edcode, flag;
+} MFace;
+
+#undef ushort
+
+typedef struct MFaceInt {
+ int v1, v2, v3, v4;
+ char puno, mat_nr;
+ char edcode, flag;
+} MFaceInt;
+
+
+typedef struct TFace {
+
+ /* this one gets interpreted as a image in texture.c */
+ void *tpage;
+
+ float uv[4][2]; /* als je dit wijzigt: ook fie set_correct_uv editmesh.c, ook andere plekken maken gebruik van de lengte van dit blok */
+ unsigned int col[4];
+ char flag, transp;
+ short mode, tile, pad;
+} TFace;
+
+typedef struct MDeformWeight { /* __NLA */
+ int def_nr; /* __NLA */
+ float weight; /* __NLA */
+ struct Bone *data; /* __NLA */ /* Runtime: Does not need to be valid in file */
+} MDeformWeight; /* __NLA */
+
+typedef struct MDeformVert { /* __NLA */
+ struct MDeformWeight *dw; /* __NLA */
+ int totweight; /* __NLA */
+ int reserved1; /* __NLA */
+} MDeformVert; /* __NLA */
+
+
+typedef struct MVert {
+ float co[3];
+ short no[3];
+ char flag, mat_nr;
+} MVert;
+
+
+typedef struct MCol {
+ char a, r, g, b;
+} MCol;
+
+
+typedef struct MSticky {
+ float co[2];
+} MSticky;
+
+
+typedef struct Mesh {
+ ID id;
+
+ struct BoundBox *bb;
+
+ ListBase effect;
+ ListBase disp;
+
+ struct Ipo *ipo;
+ struct Key *key;
+ struct Material **mat;
+
+ void *mface, *dface, *tface;
+ struct MVert *mvert;
+ struct MDeformVert *dvert; /* __NLA */
+ struct MCol *mcol;
+ struct MSticky *msticky;
+ struct Mesh *texcomesh;
+ float *orco;
+
+ struct OcInfo *oc; /* niet in file */
+ void *sumohandle;
+
+ int totvert, totface;
+
+ int texflag;
+ float loc[3];
+ float size[3];
+ float rot[3];
+
+ short smoothresh, flag;
+ short subdiv, subdivr;
+ short totcol;
+ short reserved1, reserved2, reserved3; /* Padding */
+
+ float cubemapsize, rtf;
+
+} Mesh;
+
+
+
+/* **************** MESH ********************* */
+
+/* texflag */
+#define AUTOSPACE 1
+
+/* me->flag */
+#define ME_ISDONE 1
+#define ME_NOPUNOFLIP 2
+#define ME_TWOSIDED 4
+#define ME_UVEFFECT 8
+#define ME_VCOLEFFECT 16
+#define ME_AUTOSMOOTH 32
+#define ME_SMESH 64
+#define ME_SUBSURF 128
+
+/* puno (mface) */
+#define ME_FLIPV1 1
+#define ME_FLIPV2 2
+#define ME_FLIPV3 4
+#define ME_FLIPV4 8
+#define ME_PROJXY 16
+#define ME_PROJXZ 32
+#define ME_PROJYZ 64
+
+/* edcode (mface) */
+#define ME_V1V2 1
+#define ME_V2V3 2
+#define ME_V3V1 4
+#define ME_V3V4 4
+#define ME_V4V1 8
+
+/* flag (mface) */
+#define ME_SMOOTH 1
+
+/* tface->mode (beetje compatible met PMD formaat) */
+/* sharedvert bepaalt hoe de PSX versie wordt, sharedcol is vertexkleur en puno */
+
+#define TF_DYNAMIC 1
+/* #define TF_INVISIBLE 2 */
+#define TF_TEX 4
+#define TF_SHAREDVERT 8
+#define TF_LIGHT 16
+
+#define TF_SHAREDCOL 64
+#define TF_TILES 128
+#define TF_BILLBOARD 256
+#define TF_TWOSIDE 512
+#define TF_INVISIBLE 1024
+
+#define TF_OBCOL 2048
+#define TF_BILLBOARD2 4096 /* with Z axis constraint */
+#define TF_SHADOW 8192
+#define TF_BMFONT 16384
+
+/* tface->flag: 1=select 2=active*/
+#define TF_SELECT 1
+#define TF_ACTIVE 2
+#define TF_SEL1 4
+#define TF_SEL2 8
+#define TF_SEL3 16
+#define TF_SEL4 32
+#define TF_HIDE 64
+
+/* tface->transp */
+#define TF_SOLID 0
+#define TF_ADD 1
+#define TF_ALPHA 2
+#define TF_SUB 3
+
+/* mvert->flag (1=select) */
+#define ME_SPHERETEST 2
+#define ME_SPHERETEMP 4
+
+#endif
diff --git a/source/blender/makesdna/DNA_meta_types.h b/source/blender/makesdna/DNA_meta_types.h
new file mode 100644
index 00000000000..745fe1a823a
--- /dev/null
+++ b/source/blender/makesdna/DNA_meta_types.h
@@ -0,0 +1,100 @@
+/**
+ * blenlib/DNA_meta_types.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 DNA_META_TYPES_H
+#define DNA_META_TYPES_H
+
+#include "DNA_listBase.h"
+#include "DNA_ID.h"
+
+struct BoundBox;
+struct Ipo;
+struct Material;
+
+
+typedef struct MetaElem {
+ struct MetaElem *next, *prev;
+
+ short type, lay, flag, selcol;
+ float x, y, z;
+ float expx, expy, expz;
+ float rad, rad2, s, len, maxrad2;
+ int pad;
+
+ float *mat, *imat;
+
+} MetaElem;
+
+typedef struct MetaBall {
+ ID id;
+
+ struct BoundBox *bb;
+
+ ListBase elems;
+ ListBase disp;
+ struct Ipo *ipo;
+
+ struct Material **mat;
+
+ short flag, totcol;
+ int texflag;
+ float loc[3];
+ float size[3];
+ float rot[3];
+ float wiresize, rendersize, thresh;
+
+} MetaBall;
+
+/* **************** METABALL ********************* */
+
+#define MB_MAXELEM 1024
+
+/* mb->flag */
+#define MB_UPDATE_ALWAYS 0
+#define MB_UPDATE_HALFRES 1
+#define MB_UPDATE_FAST 2
+
+/* ml->type */
+#define MB_BALL 0
+#define MB_TUBEX 1
+#define MB_TUBEY 2
+#define MB_TUBEZ 3
+#define MB_CIRCLE 4
+
+/* ml->flag */
+#define MB_NEGATIVE 2
+
+
+
+
+#endif
diff --git a/source/blender/makesdna/DNA_nla_types.h b/source/blender/makesdna/DNA_nla_types.h
new file mode 100644
index 00000000000..9d7befd67ee
--- /dev/null
+++ b/source/blender/makesdna/DNA_nla_types.h
@@ -0,0 +1,71 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 DNA_NLA_TYPES_H
+#define DNA_NLA_TYPES_H
+
+struct bAction;
+struct Ipo;
+
+typedef struct bActionStrip {
+ struct bActionStrip *next, *prev;
+ short flag;
+ short mode;
+ int reserved1;
+
+ struct Ipo *ipo; /* Blending ipo */
+ struct bAction *act; /* The action referenced by this strip */
+
+ float start, end; /* The range of frames covered by this strip */
+ float actstart, actend; /* The range of frames taken from the action */
+ float stridelen; /* The stridelength (considered when flag & ACT_USESTRIDE) */
+ float repeat; /* The number of times to repeat the action range */
+
+ float blendin, blendout;
+} bActionStrip;
+
+#define ACTSTRIPMODE_BLEND 0
+#define ACTSTRIPMODE_ADD 1
+
+#define ACTSTRIP_SELECT 0x00000001
+
+#define ACTSTRIP_USESTRIDE 0x00000002
+#define ACTSTRIP_BLENDTONEXT 0x00000004
+#define ACTSTRIP_HOLDLASTFRAME 0x00000008
+
+#define ACTSTRIP_SELECTBIT 0
+#define ACTSTRIP_USESTRIDEBIT 1
+#define ACTSTRIP_BLENDTONEXTBIT 2
+#define ACTSTRIP_HOLDLASTFRAMEBIT 3
+#endif
+
diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h
new file mode 100644
index 00000000000..df6ccacb71b
--- /dev/null
+++ b/source/blender/makesdna/DNA_object_types.h
@@ -0,0 +1,316 @@
+/**
+ * blenlib/DNA_object_types.h (mar-2001 nzc)
+ *
+ * Object is a sort of wrapper for general info.
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 DNA_OBJECT_TYPES_H
+#define DNA_OBJECT_TYPES_H
+
+#include "DNA_listBase.h"
+#include "DNA_ID.h"
+#include "DNA_scriptlink_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct bPose;
+struct Object;
+struct Ipo;
+struct BoundBox;
+struct Path;
+struct Material;
+struct bConstraintChannel;
+
+typedef struct bDeformGroup {
+ struct bDeformGroup *next, *prev;
+ char name[32];
+ void *data; /* Temporary data, most likely a pointer to the bone - no need to delete */
+} bDeformGroup;
+
+#
+#
+typedef struct BoundBox {
+ float vec[8][3];
+} BoundBox;
+
+
+typedef struct Object {
+ ID id;
+
+ short type, partype;
+ int par1, par2, par3; /* kunnen vertexnrs zijn */
+ char parsubstr[32]; /* String describing subobject info */
+ void *pardata;
+ struct Object *parent, *track;
+ struct Ipo *ipo;
+ struct Path *path;
+ struct BoundBox *bb;
+ struct bAction *action;
+ struct bPose *pose;
+ void *data;
+
+ struct bConstraintChannel *activecon;
+ ListBase constraintChannels;
+
+ ListBase effect;
+ ListBase network;
+ ListBase disp;
+ ListBase defbase;
+ struct Material **mat;
+
+ /* rot en drot moeten achterelkaar! (transform('r' en 's')) */
+ float loc[3], dloc[3], orig[3];
+ float size[3], dsize[3];
+ float rot[3], drot[3];
+ float quat[4], dquat[4];
+ float obmat[4][4];
+ float parentinv[4][4];
+ float imat[4][4]; /* voor bij render, tijdens simulate, tijdelijk: ipokeys van transform */
+
+ unsigned int lay; /* kopie van Base */
+ short flag; /* kopie van Base */
+ short colbits; /* nul==van obdata */
+ char transflag, ipoflag;
+ char trackflag, upflag;
+ short ipowin, scaflag; /* ipowin: blocktype laatste ipowindow */
+ short scavisflag, boundtype;
+
+ short dupon, dupoff, dupsta, dupend;
+
+ float sf, ctime;
+
+ /* tijdens realtime */
+
+ /* note that inertia is only called inertia for historical reasons
+ * and is not changed to avoid DNA surgery. It actually reflects the
+ * Size value in the GameButtons (= radius) */
+
+ float mass, damping, inertia;
+ /* The form factor k is introduced to give the user more control
+ * and to fix incompatibility problems.
+ * For rotational symmetric objects, the inertia value can be
+ * expressed as: Theta = k * m * r^2
+ * where m = Mass, r = Radius
+ * For a Sphere, the form factor is by default = 0.4
+ */
+
+ float formfactor, dummy_1;
+ float rdamping, sizefac;
+
+ char dt, dtx;
+ char totcol; /* kopie van mesh of curve of meta */
+ char actcol;
+
+ ScriptLink scriptlink;
+ ListBase prop;
+ ListBase sensors;
+ ListBase controllers;
+ ListBase actuators;
+
+ void *sumohandle;
+
+ float bbsize[3];
+ short dfras;
+ unsigned short actdef; /* current deformation group */
+ float col[4];
+ /**
+ * Settings for game objects
+ * bit 0: Object has dynamic behaviour
+ * bit 2: Object is evaluated by the gameengine
+ * bit 6: Use Fh settings in Materials
+ * bit 7: Use face normal to rotate Object
+ * bit 8: Friction is anisotropic
+ * bit 9: Object is a ghost
+ * bit 10: Do rigid body dynamics.
+ */
+ int gameflag;
+ /**
+ * More settings
+ * bit 15: Always ignore activity culling
+ */
+ int gameflag2;
+ int pad;
+ float anisotropicFriction[3];
+
+ ListBase constraints;
+ ListBase nlastrips;
+} Object;
+
+/* this work object is defined in object.c */
+extern Object workob;
+
+
+/* **************** OBJECT ********************* */
+
+/* used many places... should be specialized */
+#define SELECT 1
+#define ACTIVE 2
+
+/* type */
+#define OB_EMPTY 0
+#define OB_MESH 1
+#define OB_CURVE 2
+#define OB_SURF 3
+#define OB_FONT 4
+#define OB_MBALL 5
+
+#define OB_LAMP 10
+#define OB_CAMERA 11
+
+#define OB_IKA 20
+#define OB_WAVE 21
+#define OB_LATTICE 22
+
+/* 23 and 24 are for life and sector (old file compat.) */
+#define OB_ARMATURE 25
+
+/* partype: eerste 5 bits: type */
+#define PARTYPE 15
+#define PAROBJECT 0
+#define PARCURVE 1
+#define PARKEY 2
+#define PARLIMB 3
+#define PARSKEL 4
+#define PARVERT1 5
+#define PARVERT3 6
+#define PARBONE 7
+#define PARSLOW 16
+
+/* char! transflag */
+#define OB_OFFS_LOCAL 1
+#define OB_QUAT 2
+#define OB_DUPLI (8+16)
+#define OB_DUPLIFRAMES 8
+#define OB_DUPLIVERTS 16
+#define OB_DUPLIROT 32
+#define OB_DUPLINOSPEED 64
+
+#define OB_POWERTRACK 128
+
+/* char! ipoflag */
+#define OB_DRAWKEY 1
+#define OB_DRAWKEYSEL 2
+#define OB_OFFS_OB 4
+#define OB_OFFS_MAT 8
+#define OB_OFFS_VKEY 16
+#define OB_OFFS_PATH 32
+#define OB_OFFS_PARENT 64
+#define OB_OFFS_PARTICLE 128
+
+
+/* trackflag / upflag */
+#define OB_POSX 0
+#define OB_POSY 1
+#define OB_POSZ 2
+#define OB_NEGX 3
+#define OB_NEGY 4
+#define OB_NEGZ 5
+
+/* gameflag in game.h */
+
+/* dt: nummers */
+#define OB_BOUNDBOX 1
+#define OB_WIRE 2
+#define OB_SOLID 3
+#define OB_SHADED 4
+#define OB_TEXTURE 5
+
+/* dtx: flags */
+#define OB_AXIS 2
+#define OB_TEXSPACE 4
+#define OB_DRAWNAME 8
+#define OB_DRAWIMAGE 16
+
+/* boundtype */
+#define OB_BOUND_BOX 0
+#define OB_BOUND_SPHERE 1
+#define OB_BOUND_CYLINDER 2
+#define OB_BOUND_CONE 3
+#define OB_BOUND_POLYH 4
+
+/* also needed for base!!!!! or rather, thy interfere....*/
+/* base->flag en ob->flag */
+#define BA_WASSEL 2
+#define BA_PARSEL 4
+#define BA_WHERE_UPDATE 8
+#define BA_DISP_UPDATE 16
+#define BA_DO_IPO 32
+#define BA_FROMSET 128
+#define OB_DO_IMAT 256
+#define OB_FROMDUPLI 512
+#define OB_DONE 1024
+#define OB_RADIO 2048
+#define OB_FROMGROUP 4096
+
+/* ob->gameflag */
+#define OB_DYNAMIC 1
+#define OB_CHILD 2
+#define OB_ACTOR 4
+#define OB_INERTIA_LOCK_X 8
+#define OB_INERTIA_LOCK_Y 16
+#define OB_INERTIA_LOCK_Z 32
+#define OB_DO_FH 64
+#define OB_ROT_FH 128
+#define OB_ANISOTROPIC_FRICTION 256
+#define OB_GHOST 512
+#define OB_RIGID_BODY 1024
+
+#define OB_COLLISION_RESPONSE 4096
+#define OB_SECTOR 8192
+#define OB_PROP 16384
+#define OB_MAINACTOR 32768
+
+/* ob->gameflag2 */
+#define OB_NEVER_DO_ACTIVITY_CULLING 1
+
+#define OB_LIFE (OB_PROP|OB_DYNAMIC|OB_ACTOR|OB_MAINACTOR|OB_CHILD)
+
+/* ob->scavisflag */
+#define OB_VIS_SENS 1
+#define OB_VIS_CONT 2
+#define OB_VIS_ACT 4
+
+/* ob->scaflag */
+#define OB_SHOWSENS 64
+#define OB_SHOWACT 128
+#define OB_ADDSENS 256
+#define OB_ADDCONT 512
+#define OB_ADDACT 1024
+#define OB_SHOWCONT 2048
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/source/blender/makesdna/DNA_oops_types.h b/source/blender/makesdna/DNA_oops_types.h
new file mode 100644
index 00000000000..e4b7c840859
--- /dev/null
+++ b/source/blender/makesdna/DNA_oops_types.h
@@ -0,0 +1,68 @@
+/**
+ * blenlib/DNA_oops_types.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 DNA_OOPS_TYPES_H
+#define DNA_OOPS_TYPES_H
+
+#define OOPSX 5.0
+#define OOPSY 1.8
+
+#include "DNA_listBase.h"
+
+struct ID;
+
+typedef struct Oops {
+ struct Oops *next, *prev;
+ short type, flag, dt, hide;
+ float x, y; /* linksonder */
+ float dx, dy; /* shuffle */
+ struct ID *id;
+ ListBase link;
+} Oops;
+
+#
+#
+typedef struct OopsLink {
+ struct OopsLink *next, *prev;
+ short type, flag;
+ ID **idfrom;
+ Oops *to, *from; /* from is voor temp */
+ float xof, yof;
+ char name[12];
+} OopsLink;
+
+/* oops->flag (1==SELECT) */
+#define OOPS_DOSELECT 2
+#define OOPS_REFER 4
+
+#endif
diff --git a/source/blender/makesdna/DNA_packedFile_types.h b/source/blender/makesdna/DNA_packedFile_types.h
new file mode 100644
index 00000000000..40ada86cda2
--- /dev/null
+++ b/source/blender/makesdna/DNA_packedFile_types.h
@@ -0,0 +1,63 @@
+/* DNA_packedFile_types.h
+ *
+ * 12-oct-2000 nzc
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 DNA_PACKEDFILE_TYPES_H
+#define DNA_PACKEDFILE_TYPES_H
+
+typedef struct PackedFile {
+ int size;
+ int seek;
+ int flags;
+ int pad;
+ void * data;
+} PackedFile;
+
+enum PF_FileStatus
+{
+ PF_EQUAL = 0,
+ PF_DIFFERS,
+ PF_NOFILE,
+
+ PF_WRITE_ORIGINAL,
+ PF_WRITE_LOCAL,
+ PF_USE_LOCAL,
+ PF_USE_ORIGINAL,
+ PF_KEEP,
+ PF_NOOP,
+
+ PF_ASK
+};
+
+#endif /* PACKEDFILE_TYPES_H */
diff --git a/source/blender/makesdna/DNA_property_types.h b/source/blender/makesdna/DNA_property_types.h
new file mode 100644
index 00000000000..1be6ecefa6c
--- /dev/null
+++ b/source/blender/makesdna/DNA_property_types.h
@@ -0,0 +1,67 @@
+/**
+ * blenlib/DNA_property_types.h (mar-2001 nzc)
+ *
+ * Renderrecipe and scene decription. The fact that there is a
+ * hierarchy here is a bit strange, and not desirable.
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 DNA_PROPERTY_TYPES_H
+#define DNA_PROPERTY_TYPES_H
+
+/* ********************* PROPERTY ************************ */
+
+typedef struct bProperty {
+ struct bProperty *next, *prev;
+ char name[32];
+ short type, otype; /* otype is for buttons, when a property type changes */
+ int data; /* data should be 4 bytes to store int,float stuff */
+ int old; /* old is for simul */
+ short flag, pad;
+ void *poin;
+ void *oldpoin; /* oldpoin is for simul */
+
+} bProperty;
+
+/* property->type */
+#define PROP_BOOL 0
+#define PROP_INT 1
+#define PROP_FLOAT 2
+#define PROP_STRING 3
+#define PROP_VECTOR 4
+#define PROP_TIME 5
+
+/* property->flag */
+#define PROP_DEBUG 1
+
+#define MAX_PROPSTRING 128
+
+#endif
diff --git a/source/blender/makesdna/DNA_radio_types.h b/source/blender/makesdna/DNA_radio_types.h
new file mode 100644
index 00000000000..2fe9048f612
--- /dev/null
+++ b/source/blender/makesdna/DNA_radio_types.h
@@ -0,0 +1,52 @@
+/**
+ * radio_types.h dec 2000 Nzc
+ *
+ * All type defs for the Blender core.
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 DNA_RADIO_TYPES_H
+#define DNA_RADIO_TYPES_H
+
+typedef struct Radio {
+ short hemires, maxiter;
+ short drawtype, flag; /* bit 0 en 1: limits laten zien */
+ short subshootp, subshoote, nodelim, maxsublamp;
+ short pama, pami, elma, elmi; /* patch en elem limits */
+ int maxnode;
+ float convergence;
+ float radfac, gamma; /* voor afbeelden */
+
+} Radio;
+
+#endif
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
new file mode 100644
index 00000000000..147f4e22ed6
--- /dev/null
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -0,0 +1,346 @@
+/**
+ * blenlib/DNA_scene_types.h (mar-2001 nzc)
+ *
+ * Renderrecipe and scene decription. The fact that there is a
+ * hierarchy here is a bit strange, and not desirable.
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 DNA_SCENE_TYPES_H
+#define DNA_SCENE_TYPES_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "DNA_vec_types.h"
+#include "DNA_listBase.h"
+#include "DNA_scriptlink_types.h"
+#include "DNA_ID.h"
+#include "DNA_scriptlink_types.h"
+
+struct FreeCamera;
+struct Radio;
+struct Object;
+struct World;
+struct Scene;
+struct Image;
+struct Group;
+
+typedef struct Base {
+ struct Base *next, *prev;
+ unsigned int lay, selcol;
+ int flag;
+ short sx, sy;
+ struct Object *object;
+} Base;
+
+typedef struct AviCodecData {
+ void *lpFormat; /* save format */
+ void *lpParms; /* compressor options */
+ unsigned int cbFormat; /* size of lpFormat buffer */
+ unsigned int cbParms; /* size of lpParms buffer */
+
+ unsigned int fccType; /* stream type, for consistency */
+ unsigned int fccHandler; /* compressor */
+ unsigned int dwKeyFrameEvery; /* keyframe rate */
+ unsigned int dwQuality; /* compress quality 0-10,000 */
+ unsigned int dwBytesPerSecond; /* bytes per second */
+ unsigned int dwFlags; /* flags... see below */
+ unsigned int dwInterleaveEvery; /* for non-video streams only */
+ unsigned int pad;
+} AviCodecData;
+
+typedef struct RenderData {
+ struct AviCodecData *avicodecdata;
+
+ /* hoe gaat tijd gedefinieerd worden? */
+ short cfra, sfra, efra; /* plaatjes */
+ short images, framapto, flag;
+ float ctime; /* hiermee rekenen? */
+ float framelen, blurfac;
+
+ /** For UR edge rendering: give the edges this colour */
+ float edgeR, edgeG, edgeB;
+
+ short fullscreen, xplay, yplay, freqplay; /* standalone player */
+ short depth, attrib, rt1, rt2; /* standalone player */
+
+ short stereomode; /* standalone player stereo settings */
+ short pad[3];
+
+ short size, maximsize; /* size in %, max in Kb */
+ /* uit buttons: */
+ /**
+ * The desired number of pixels in the x direction
+ */
+ short xsch;
+ /**
+ * The desired number of pixels in the y direction
+ */
+ short ysch;
+ /**
+ * Adjustment factors for the aspect ratio in the x direction
+ */
+ short xasp;
+ /**
+ * Adjustment factors for the aspect ratio in the x direction
+ */
+ short yasp;
+ /**
+ * The number of part to use in the x direction
+ */
+ short xparts;
+ /**
+ * The number of part to use in the y direction
+ */
+ short yparts;
+ /* should rewrite this I think... */
+ rctf safety, border;
+
+ short winpos, planes, imtype;
+ /** Mode bits: */
+ /* 0: Enable backbuffering for images */
+ short bufflag;
+ short quality;
+ /**
+ * Flags for render settings. Use bit-masking to access the settings.
+ * 0: enable sequence output rendering
+ * 1: render daemon
+ * 4: add extensions to filenames
+ */
+ short scemode;
+
+ /**
+ * Flags for render settings. Use bit-masking to access the settings.
+ * The bits have these meanings:
+ * 0: do oversampling
+ * 1: do shadows
+ * 2: do gamma correction
+ * 3: ortho (not used?)
+ * 4: trace (not used?)
+ * 5: edge shading
+ * 6: field rendering
+ * 7: Disables time difference in field calculations
+ * 8: Gauss ? is this for sampling?
+ * 9: borders
+ * 10: panorama
+ * 11: crop
+ * 12: save SGI movies with Cosmo hardware (????)
+ * 13: odd field first rendering
+ * 14: motion blur
+ * 15: use unified renderer for this pic!
+ */
+ short mode;
+
+ /**
+ * What to do with the sky/background. Picks sky/premul/key
+ * blending for the background
+ */
+ short alphamode;
+ /**
+ * Toggles whether to apply a gamma correction for subpixel to
+ * pixel blending
+ */
+ short dogamma;
+ /**
+ * The number of samples to use per pixel.
+ */
+ short osa;
+ short frs_sec, edgeint;
+
+ /** For unified renderer: reduce intensity on boundaries with
+ * identical materials with this number.*/
+ short same_mat_redux, pad_3[3];
+
+ /**
+ * The gamma for the normal rendering. Used when doing
+ * oversampling, to correctly blend subpixels to pixels. */
+ float gamma;
+ /** post-production settings. Don't really belong here */
+ float postmul, postgamma, postadd, postigamma;
+
+ char backbuf[160], pic[160], ftype[160];
+
+} RenderData;
+
+
+typedef struct GameFraming {
+ float col[3];
+ char type, pad1, pad2, pad3;
+} GameFraming;
+
+#define SCE_GAMEFRAMING_BARS 0
+#define SCE_GAMEFRAMING_EXTEND 1
+#define SCE_GAMEFRAMING_SCALE 2
+
+typedef struct Scene {
+ ID id;
+ struct Object *camera;
+ struct World *world;
+
+ struct Scene *set;
+ struct Image *ima;
+
+ ListBase base;
+ struct Base *basact;
+ struct Group *group;
+
+ float cursor[3];
+ unsigned int lay;
+
+ /* enkele realtime vars */
+ struct FreeCamera *fcam;
+
+ void *ed;
+ struct Radio *radio;
+ void *sumohandle;
+
+ struct GameFraming framing;
+
+ /* migrate or replace? depends on some internal things... */
+ /* no, is on the right place (ton) */
+ struct RenderData r;
+
+ ScriptLink scriptlink;
+} Scene;
+
+
+/* **************** RENDERDATA ********************* */
+
+/* bufflag */
+#define R_BACKBUF 1
+#define R_BACKBUFANIM 2
+#define R_FRONTBUF 4
+#define R_FRONTBUFANIM 8
+
+/* mode */
+#define R_OSA 0x0001
+#define R_SHADOW 0x0002
+#define R_GAMMA 0x0004
+#define R_ORTHO 0x0008
+#define R_TRACE 0x0010
+#define R_EDGE 0x0020
+#define R_FIELDS 0x0040
+#define R_FIELDSTILL 0x0080
+#define R_GAUSS 0x0100
+#define R_BORDER 0x0200
+#define R_PANORAMA 0x0400
+#define R_MOVIECROP 0x0800
+#define R_COSMO 0x1000
+/* deze verschillen tussen IrisGL en OpenGL!!! */
+#define R_ODDFIELD 0x2000
+#define R_MBLUR 0x4000
+#define R_UNIFIED 0x8000
+
+/* scemode */
+#define R_DOSEQ 0x0001
+#define R_BG_RENDER 0x0002
+
+#define R_EXTENSION 0x0010
+#define R_OGL 0x0020
+
+/* alphamode */
+#define R_ADDSKY 0
+#define R_ALPHAPREMUL 1
+#define R_ALPHAKEY 2
+
+/* planes */
+#define R_PLANES24 24
+#define R_PLANES32 32
+#define R_PLANESBW 8
+
+/* imtype */
+#define R_TARGA 0
+#define R_IRIS 1
+#define R_HAMX 2
+#define R_FTYPE 3
+#define R_JPEG90 4
+#define R_MOVIE 5
+#define R_IRIZ 7
+#define R_RAWTGA 14
+#define R_AVIRAW 15
+#define R_AVIJPEG 16
+#define R_PNG 17
+#define R_AVICODEC 18
+
+
+/* **************** RENDER ********************* */
+/* mode flag is same as for renderdata */
+/* flag */
+#define R_ZTRA 1
+#define R_HALO 2
+#define R_SEC_FIELD 4
+#define R_LAMPHALO 8
+#define R_RENDERING 16
+#define R_ANIMRENDER 32
+
+/* vlakren->flag */
+#define R_SMOOTH 1
+#define R_VISIBLE 2
+#define R_NOPUNOFLIP 8
+#define R_CMAPCODE 16
+#define R_FACE_SPLIT 32
+
+/* vertren->texofs (texcoordinaten offset vanaf vertren->orco */
+#define R_UVOFS3 1
+
+/* **************** SCENE ********************* */
+#define RAD_PHASE_PATCHES 1
+#define RAD_PHASE_FACES 2
+
+/* base->flag en ob->flag */
+#define BA_WASSEL 2
+#define BA_PARSEL 4
+#define BA_WHERE_UPDATE 8
+#define BA_DISP_UPDATE 16
+#define BA_DO_IPO 32
+#define BA_FROMSET 128
+#define OB_DO_IMAT 256
+#define OB_FROMDUPLI 512
+#define OB_DONE 1024
+#define OB_RADIO 2048
+#define OB_FROMGROUP 4096
+
+/* sce->flag */
+#define SCE_ADDSCENAME 1
+
+/* return flag next_object function */
+#define F_START 0
+#define F_SCENE 1
+#define F_SET 2
+#define F_DUPLI 3
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h
new file mode 100644
index 00000000000..8ccd2eef7d1
--- /dev/null
+++ b/source/blender/makesdna/DNA_screen_types.h
@@ -0,0 +1,152 @@
+/**
+ * blenlib/DNA_screen_types.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 DNA_SCREEN_TYPES_H
+#define DNA_SCREEN_TYPES_H
+
+#include "DNA_listBase.h"
+#include "DNA_vec_types.h"
+
+#include "DNA_ID.h"
+#include "DNA_scriptlink_types.h"
+
+struct Scene;
+
+typedef struct bScreen {
+ ID id;
+ ListBase vertbase, edgebase, areabase;
+ struct Scene *scene;
+ short startx, endx, starty, endy; /* framebuffer coords */
+ short sizex, sizey;
+ short scenenr, screennr; /* alleen voor pupmenu */
+ short full, rt;
+ short mainwin, winakt;
+} bScreen;
+
+
+typedef struct ScrVert {
+ struct ScrVert *next, *prev, *newv;
+ vec2s vec;
+ int flag;
+} ScrVert;
+
+typedef struct ScrEdge {
+ struct ScrEdge *next, *prev;
+ ScrVert *v1, *v2;
+ short border; /* 1 als op rand screen */
+ short flag;
+ int pad;
+} ScrEdge;
+
+#ifndef DNA_USHORT_FIX
+#define DNA_USHORT_FIX
+/**
+ * @deprecated This typedef serves to avoid badly typed functions when
+ * @deprecated compiling while delivering a proper dna.c. Do not use
+ * @deprecated it in any case.
+ */
+typedef unsigned short dna_ushort_fix;
+#endif
+
+typedef struct ScrArea {
+ struct ScrArea *next, *prev;
+ ScrVert *v1, *v2, *v3, *v4;
+ bScreen *full; /* als area==full, dit is de parent */
+ float winmat[4][4];
+ rcti totrct, headrct, winrct;
+
+ short headwin, win;
+ short headertype; /* 0=niets, 1= down, 2= up */
+ char spacetype, butspacetype; /* SPACE_... */
+ short winx, winy; /* size */
+ char head_swap, head_equal;
+ char win_swap, win_equal;
+
+ short headbutlen, headbutofs;
+ short cursor, rt;
+
+ ListBase spacedata;
+ ListBase uiblocks;
+} ScrArea;
+
+#define MAXWIN 128
+
+/* Als je EDGEWIDTH verandert, ook globale array edcol[] goedzetten */
+#define EDGEWIDTH 5
+#define EDGEWIDTH2 (2)
+#define AREAGRID 4
+#define AREAMINX 32
+#define HEADERY 21
+#define AREAMINY (HEADERY+EDGEWIDTH)
+
+#define HEADERDOWN 1
+#define HEADERTOP 2
+
+#define SCREENNORMAL 0
+#define SCREENFULL 1
+#define SCREENAUTOPLAY 2
+
+/* sa->win_swap */
+#define WIN_FRONT_OK 1
+#define WIN_BACK_OK 2
+#define WIN_EQUAL 3
+
+#define L_SCROLL 1 /* left scrollbar */
+#define R_SCROLL 2
+#define VERT_SCROLL 3
+#define T_SCROLL 4
+#define B_SCROLL 8
+#define HOR_SCROLL 12
+
+enum {
+ SPACE_EMPTY,
+ SPACE_VIEW3D,
+ SPACE_IPO,
+ SPACE_OOPS,
+ SPACE_BUTS,
+ SPACE_FILE,
+ SPACE_IMAGE,
+ SPACE_INFO,
+ SPACE_SEQ,
+ SPACE_TEXT,
+ SPACE_IMASEL,
+ SPACE_SOUND,
+ SPACE_ACTION,
+ SPACE_NLA
+/* SPACE_LOGIC */
+};
+
+/* Adding a new space type? Change SPACEICONMAX in headerbuttons.c */
+/* -- should rather handle this with the above enum... */
+
+#endif
diff --git a/source/blender/makesdna/DNA_scriptlink_types.h b/source/blender/makesdna/DNA_scriptlink_types.h
new file mode 100644
index 00000000000..6ac581b1233
--- /dev/null
+++ b/source/blender/makesdna/DNA_scriptlink_types.h
@@ -0,0 +1,63 @@
+/**
+ * blenlib/DNA_object_types.h (mar-2001 nzc)
+ *
+ * Scriptlink is hard-coded in object for some reason.
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 DNA_SCRIPTLINK_TYPES_H
+#define DNA_SCRIPTLINK_TYPES_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct ID;
+
+typedef struct ScriptLink {
+ struct ID **scripts;
+ short *flag;
+
+ short actscript, totscript;
+ int pad;
+} ScriptLink;
+
+/* **************** SCRIPTLINKS ********************* */
+
+#define SCRIPT_FRAMECHANGED 1
+#define SCRIPT_ONLOAD 2
+#define SCRIPT_REDRAW 4
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/source/blender/makesdna/DNA_sdna_types.h b/source/blender/makesdna/DNA_sdna_types.h
new file mode 100644
index 00000000000..9541516453b
--- /dev/null
+++ b/source/blender/makesdna/DNA_sdna_types.h
@@ -0,0 +1,82 @@
+/**
+ * blenlib/DNA_sdna.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 DNA_SDNA_H
+#define DNA_SDNA_H
+
+#
+#
+struct SDNA {
+ char *data;
+ int datalen, nr_names;
+ char **names;
+ int nr_types, pointerlen;
+ char **types;
+ short *typelens;
+ int nr_structs;
+ short **structs;
+
+ /* wrong place for this really, its a simple
+ * cache for findstruct_nr.
+ */
+ int lastfind;
+};
+
+#
+#
+typedef struct BHead {
+ int code, len;
+ void *old;
+ int SDNAnr, nr;
+} BHead;
+#
+#
+typedef struct BHead4 {
+ int code, len;
+ int old;
+ int SDNAnr, nr;
+} BHead4;
+#
+#
+typedef struct BHead8 {
+ int code, len;
+#ifdef WIN32
+ /* This is a compiler type! */
+ __int64 old;
+#else
+ long long old;
+#endif
+ int SDNAnr, nr;
+} BHead8;
+
+#endif
diff --git a/source/blender/makesdna/DNA_sensor_types.h b/source/blender/makesdna/DNA_sensor_types.h
new file mode 100644
index 00000000000..ad3e83ea6c0
--- /dev/null
+++ b/source/blender/makesdna/DNA_sensor_types.h
@@ -0,0 +1,225 @@
+/**
+ * blenlib/DNA_sensor_types.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 DNA_SENSOR_TYPES_H
+#define DNA_SENSOR_TYPES_H
+
+struct Object;
+struct Material;
+
+/* ****************** SENSORS ********************* */
+
+typedef struct bNearSensor {
+ char name[32];
+ float dist, resetdist;
+ int lastval, pad;
+} bNearSensor;
+
+/**
+ * Defines the settings of a mouse sensor.
+ */
+typedef struct bMouseSensor {
+ /**
+ * The type of key this sensor listens to.
+ */
+ short type;
+ short flag;
+ short pad1;
+ short pad2;
+} bMouseSensor;
+
+typedef struct bTouchSensor {
+ char name[32];
+ struct Material *ma;
+ float dist, pad;
+} bTouchSensor;
+
+typedef struct bKeyboardSensor {
+ short key, qual;
+ short type, qual2;
+ /**
+ * Name of the target property
+ */
+ char targetName[32];
+ /**
+ * Name of the toggle property
+ */
+ char toggleName[32];
+} bKeyboardSensor;
+
+typedef struct bPropertySensor {
+ int type;
+ int pad;
+ char name[32];
+ char value[32];
+ char maxvalue[32];
+} bPropertySensor;
+
+typedef struct bCollisionSensor {
+ char name[32]; /* property name */
+ char materialName[32]; /* material */
+ short damptimer, damp;
+ short mode; /* flag to choose material or property */
+ short pad2;
+} bCollisionSensor;
+
+typedef struct bRadarSensor {
+ char name[32];
+ float angle;
+ float range;
+ short flag, axis;
+} bRadarSensor;
+
+typedef struct bRandomSensor {
+ char name[32];
+ int seed;
+ int delay;
+} bRandomSensor;
+
+typedef struct bRaySensor {
+ char name[32];
+ float range;
+ char propname[32];
+ char matname[32];
+ short mode;
+ short pad1;
+ int axisflag;
+} bRaySensor;
+
+typedef struct bMessageSensor {
+ /**
+ * (Possible future use) pointer to a single sender object
+ */
+ struct Object *fromObject;
+
+ /**
+ * Can be used to filter on subjects like this
+ */
+ char subject[32];
+
+ /**
+ * (Possible future use) body to filter on
+ */
+ char body[32];
+} bMessageSensor;
+
+typedef struct bSensor {
+ struct bSensor *next, *prev;
+ /* pulse and freq are the bool toggle and frame count for pulse mode */
+ short type, otype, flag, pulse;
+ short freq, totlinks, pad1, pad2;
+ char name[32];
+ void *data;
+
+ struct bController **links;
+
+ struct Object *ob;
+
+ /* just add here, to avoid align errors... */
+ short invert; /* Whether or not to invert the output. */
+ short freq2; /* The negative pulsing frequency? Not used anymore... */
+ int pad;
+} bSensor;
+
+/* bMouseSensor->type: uses blender event defines */
+
+/* propertysensor->type */
+#define SENS_PROP_EQUAL 0
+#define SENS_PROP_NEQUAL 1
+#define SENS_PROP_INTERVAL 2
+#define SENS_PROP_CHANGED 3
+#define SENS_PROP_EXPRESSION 4
+
+/* raysensor->axisflag */
+/* flip x and y to make y default!!! */
+#define SENS_RAY_X_AXIS 1
+#define SENS_RAY_Y_AXIS 0
+#define SENS_RAY_Z_AXIS 2
+#define SENS_RAY_NEG_X_AXIS 3
+#define SENS_RAY_NEG_Y_AXIS 4
+#define SENS_RAY_NEG_Z_AXIS 5
+//#define SENS_RAY_NEGATIVE_AXIS 1
+
+/* bMessageSensor->type */
+#define SENS_MESG_MESG 0
+#define SENS_MESG_PROP 1
+
+/* sensor->type */
+#define SENS_ALWAYS 0
+#define SENS_TOUCH 1
+#define SENS_NEAR 2
+#define SENS_KEYBOARD 3
+#define SENS_PROPERTY 4
+#define SENS_MOUSE 5
+#define SENS_COLLISION 6
+#define SENS_RADAR 7
+#define SENS_RANDOM 8
+#define SENS_RAY 9
+#define SENS_MESSAGE 10
+
+/* sensor->flag */
+#define SENS_SHOW 1
+#define SENS_DEL 2
+#define SENS_NEW 4
+#define SENS_NOT 8
+
+/* sensor->pulse */
+#define SENS_PULSE_CONT 0
+#define SENS_PULSE_REPEAT 1
+#define SENS_PULSE_ONCE 2
+#define SENS_NEG_PULSE_MODE 4
+
+/* sensor->suppress */
+#define SENS_SUPPRESS_POSITIVE_BIT 0
+#define SENS_SUPPRESS_NEGATIVE_BIT 1
+
+#define SENS_SUPPRESS_POSITIVE (1 << SENS_SUPPRESS_POSITIVE_BIT)
+#define SENS_SUPPRESS_NEGATIVE (1 << SENS_SUPPRESS_NEGATIVE_BIT)
+
+/* collision, ray sensor modes: */
+/* A little bit fake: when property is active, the first bit is
+ * reset. Bite me :) So we don't actually use it, so we comment it out
+ * ... The reason for this is that we need to be backward compatible,
+ * and have a proper default value for this thing.
+ * */
+/* #define SENS_COLLISION_PROPERTY 0 */
+#define SENS_COLLISION_MATERIAL 1
+
+/* Some stuff for the mouse sensor Type: */
+#define BL_SENS_MOUSE_LEFT_BUTTON 1
+#define BL_SENS_MOUSE_MIDDLE_BUTTON 2
+#define BL_SENS_MOUSE_RIGHT_BUTTON 4
+#define BL_SENS_MOUSE_MOVEMENT 8
+#define BL_SENS_MOUSE_MOUSEOVER 16
+
+#endif
diff --git a/source/blender/makesdna/DNA_sequence_types.h b/source/blender/makesdna/DNA_sequence_types.h
new file mode 100644
index 00000000000..217d852b9ec
--- /dev/null
+++ b/source/blender/makesdna/DNA_sequence_types.h
@@ -0,0 +1,158 @@
+/**
+ * blenlib/DNA_sequence_types.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 DNA_SEQUENCE_TYPES_H
+#define DNA_SEQUENCE_TYPES_H
+
+#include "DNA_listBase.h"
+
+struct Ipo;
+struct Scene;
+
+typedef struct StripElem {
+ char name[40];
+ struct ImBuf *ibuf;
+ struct StripElem *se1, *se2, *se3;
+ short ok, nr;
+ int pad;
+
+} StripElem;
+
+typedef struct Strip {
+ struct Strip *next, *prev;
+ short rt, len, us, done;
+ StripElem *stripdata;
+ char dir[80];
+ short orx, ory;
+ int pad;
+
+} Strip;
+
+
+typedef struct PluginSeq {
+ char name[80];
+ void *handle;
+
+ char *pname;
+
+ int vars, version;
+
+ void *varstr;
+ float *cfra;
+
+ float data[32];
+
+ void (*doit)(void);
+
+ void (*callback)(void);
+} PluginSeq;
+
+
+/* LET OP: eerste stuk identiek aan ID (ivm ipo's) */
+
+typedef struct Sequence {
+
+ struct Sequence *next, *prev, *newseq;
+ void *lib;
+ char name[24];
+
+ short flag, type;
+ int len;
+ int start, startofs, endofs;
+ int startstill, endstill;
+ int machine, depth;
+ int startdisp, enddisp;
+ float mul, handsize;
+ int sfra;
+
+ Strip *strip;
+ StripElem *curelem;
+
+ struct Ipo *ipo;
+ struct Scene *scene;
+ struct anim *anim;
+ float facf0, facf1;
+
+ PluginSeq *plugin;
+
+ /* pointers voor effecten: */
+ struct Sequence *seq1, *seq2, *seq3;
+
+ /* meta */
+ ListBase seqbase;
+
+} Sequence;
+
+
+#
+#
+typedef struct MetaStack {
+ struct MetaStack *next, *prev;
+ ListBase *oldbasep;
+ Sequence *parseq;
+} MetaStack;
+
+typedef struct Editing {
+ ListBase *seqbasep;
+ ListBase seqbase;
+ ListBase metastack;
+ short flag, rt;
+ int pad;
+} Editing;
+
+/* ***************** SEQUENCE ****************** */
+
+/* seq->flag */
+#define SEQ_LEFTSEL 2
+#define SEQ_RIGHTSEL 4
+#define SEQ_OVERLAP 8
+#define SEQ_FILTERY 16
+
+/* seq->type LET OP BITJE 3!!! */
+#define SEQ_IMAGE 0
+#define SEQ_META 1
+#define SEQ_SCENE 2
+#define SEQ_MOVIE 3
+
+#define SEQ_EFFECT 8
+#define SEQ_CROSS 8
+#define SEQ_ADD 9
+#define SEQ_SUB 10
+#define SEQ_ALPHAOVER 11
+#define SEQ_ALPHAUNDER 12
+#define SEQ_GAMCROSS 13
+#define SEQ_MUL 14
+#define SEQ_OVERDROP 15
+#define SEQ_PLUGIN 24
+
+#endif
diff --git a/source/blender/makesdna/DNA_sound_types.h b/source/blender/makesdna/DNA_sound_types.h
new file mode 100644
index 00000000000..814192cca5e
--- /dev/null
+++ b/source/blender/makesdna/DNA_sound_types.h
@@ -0,0 +1,190 @@
+/**
+ * blenlib/DNA_sound_types.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 DNA_SOUND_TYPES_H
+#define DNA_SOUND_TYPES_H
+
+#include "DNA_listBase.h"
+#include "DNA_ID.h"
+
+/* stupid... could easily be solved */
+#include "DNA_view2d_types.h"
+
+/* extern int noaudio; * defined in sound.c . also not very nice */
+/* extern ListBase *samples; don't do this in DNA, but in BKE_... instead */
+
+struct bSample;
+struct Ipo;
+struct PackedFile;
+struct SpaceLink;
+
+/* should not be here! */
+#
+#
+typedef struct bSample {
+ ID id;
+ void *data;
+ void *snd_sample;
+ short type, bits;
+ short channels;
+ int len, rate;
+// int buffer;
+ int alindex;
+ char fakedata[16];
+ int flags;
+ char name[160];
+ struct PackedFile * packedfile;
+ short us;
+} bSample;
+
+
+
+typedef struct bSound {
+ ID id;
+ char name[160];
+ struct bSample *sample;
+ struct PackedFile *packedfile;
+ struct PackedFile *newpackedfile;
+ void *snd_sound;
+ struct Ipo *ipo;
+ float volume, panning;
+ /**
+ * 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.
+ */
+ float attenuation;
+ float pitch;
+ /**
+ * min_gain indicates the minimal gain which is always guaranteed for this sound
+ */
+ float min_gain;
+ /**
+ * max_gain indicates the maximal gain which is always guaranteed for this sound
+ */
+ float max_gain;
+ /**
+ * Sets the referencedistance at which the listener will experience gain.
+ */
+ float distance;
+ int flags;
+// unsigned int loopstart;
+// unsigned int loopend;
+ char channels;
+ char highprio;
+ char pad[6];
+
+} bSound;
+
+typedef struct bSoundListener {
+ ID id;
+ /**
+ * Overall gain
+ */
+ float gain;
+ /**
+ * Sets a scaling to exaggerate or deemphasize the Doppler (pitch) shift
+ * resulting from the calculation.
+ */
+ float dopplerfactor;
+ /**
+ * Sets the value of the propagation speed relative to which the source
+ * velocities are interpreted.
+ */
+ float dopplervelocity;
+ short numsoundsblender;
+ short numsoundsgameengine;
+
+} bSoundListener;
+
+typedef struct SpaceSound {
+ struct SpaceLink *next, *prev;
+ int spacetype, pad;
+ struct ScrArea *area;
+
+ View2D v2d;
+
+ bSound *sound;
+ short mode, sndnr;
+ short xof, yof;
+ short flag, lock;
+ int pad2;
+} SpaceSound;
+
+
+enum SAMPLE_FileTypes {
+ SAMPLE_INVALID = -1, // must be negative
+ SAMPLE_UNKNOWN = 0,
+ SAMPLE_RAW,
+ SAMPLE_WAV,
+ SAMPLE_MP2,
+ SAMPLE_MP3,
+ SAMPLE_OGG_VORBIS,
+ SAMPLE_WMA,
+ SAMPLE_ASF,
+ SAMPLE_AIFF
+};
+
+
+#define SOUND_CHANNELS_STEREO 0
+#define SOUND_CHANNELS_LEFT 1
+#define SOUND_CHANNELS_RIGHT 2
+
+enum SOUND_FLAGS_BITS {
+ SOUND_FLAGS_LOOP_BIT = 0,
+ SOUND_FLAGS_FIXED_VOLUME_BIT,
+ SOUND_FLAGS_FIXED_PANNING_BIT,
+ SOUND_FLAGS_3D_BIT,
+ SOUND_FLAGS_BIDIRECTIONAL_LOOP_BIT,
+ SOUND_FLAGS_PRIORITY_BIT
+};
+
+#define SOUND_FLAGS_LOOP (1 << SOUND_FLAGS_LOOP_BIT)
+#define SOUND_FLAGS_FIXED_VOLUME (1 << SOUND_FLAGS_FIXED_VOLUME_BIT)
+#define SOUND_FLAGS_FIXED_PANNING (1 << SOUND_FLAGS_FIXED_PANNING_BIT)
+#define SOUND_FLAGS_3D (1 << SOUND_FLAGS_3D_BIT)
+#define SOUND_FLAGS_BIDIRECTIONAL_LOOP (1 << SOUND_FLAGS_BIDIRECTIONAL_LOOP_BIT)
+#define SOUND_FLAGS_PRIORITY (1 << SOUND_FLAGS_PRIORITY_BIT)
+
+enum SAMPLE_FLAGS_BITS {
+ SAMPLE_NEEDS_SAVE_BIT = 0
+};
+
+#define SAMPLE_NEEDS_SAVE (1 << SAMPLE_NEEDS_SAVE_BIT)
+
+/* to DNA_sound_types.h*/
+
+#endif
diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h
new file mode 100644
index 00000000000..092dc6eb1d3
--- /dev/null
+++ b/source/blender/makesdna/DNA_space_types.h
@@ -0,0 +1,471 @@
+/**
+ * blenlib/DNA_space_types.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 DNA_SPACE_TYPES_H
+#define DNA_SPACE_TYPES_H
+
+#include "DNA_listBase.h"
+#include "DNA_vec_types.h"
+/* Hum ... Not really nice... but needed for spacebuts. */
+#include "DNA_view2d_types.h"
+
+struct Ipo;
+struct ID;
+struct Text;
+struct ImBuf;
+struct Image;
+struct SpaceIpo;
+struct BlendHandle;
+
+ /**
+ * The base structure all the other spaces
+ * are derived (implicitly) from. Would be
+ * good to make this explicit.
+ */
+typedef struct SpaceLink SpaceLink;
+struct SpaceLink {
+ SpaceLink *next, *prev;
+ int spacetype, pad;
+ struct ScrArea *area;
+};
+
+typedef struct SpaceInfo {
+ SpaceLink *next, *prev;
+ int spacetype, pad1;
+ struct ScrArea *area;
+} SpaceInfo;
+
+typedef struct SpaceIpo {
+ SpaceLink *next, *prev;
+ int spacetype, pad1;
+ struct ScrArea *area;
+
+ unsigned int rowbut, pad2;
+ View2D v2d;
+
+ void *editipo;
+ ListBase ipokey;
+ struct Ipo *ipo;
+ struct ID *from;
+
+ short totipo, pin;
+ short butofs, channel;
+ short showkey, blocktype;
+ short menunr, lock;
+ int flag;
+ int reserved1;
+ rctf tot;
+} SpaceIpo;
+
+typedef struct SpaceButs {
+ SpaceLink *next, *prev;
+ int spacetype, pad1;
+ struct ScrArea *area;
+
+ short cursens, curact;
+ int pad2;
+ View2D v2d;
+
+ short mainb, menunr; /* texnr en menunr moeten shorts blijven */
+ short pin, mainbo;
+ void *lockpoin;
+
+ short texnr;
+ char texfrom, showgroup;
+
+ short rectx, recty; /* preview render */
+ unsigned int *rect;
+ short cury, modeltype;
+
+ short scriptblock;
+ short scaflag;
+
+ char texact, pad3[7];
+
+ /* a hackish link the anim buts keep
+ * to a SpaceIpo.
+ */
+ struct SpaceIpo *anim_linked_sipo;
+} SpaceButs;
+
+typedef struct SpaceSeq {
+ SpaceLink *next, *prev;
+ int spacetype, pad;
+ struct ScrArea *area;
+
+ View2D v2d;
+
+ short mainb, zoom;
+ int pad2;
+
+} SpaceSeq;
+
+typedef struct SpaceFile {
+ SpaceLink *next, *prev;
+ int spacetype, pad;
+ struct ScrArea *area;
+
+ struct direntry *filelist;
+ int totfile;
+ char title[24];
+ char dir[160];
+ char file[80];
+ short type, ofs, flag, sort;
+ short maxnamelen, collums;
+
+ struct BlendHandle *libfiledata;
+
+ short retval, ipotype;
+ short menu, act;
+
+ /* changed type for compiling */
+ /* void (*returnfunc)(short); ? used with char* ....*/
+ /**
+ * @attention Called in filesel.c:
+ * @attention returnfunc(this->retval) : short
+ * @attention returnfunc(name) : char*
+ * @attention Other uses are limited to testing against
+ * @attention the value. How do we resolve this? Two args?
+ * @attention For now, keep the char*, as it seems stable.
+ * @attention Be warned that strange behaviour _has_ been spotted!
+ */
+ void (*returnfunc)(char*);
+
+ short *menup;
+} SpaceFile;
+
+typedef struct SpaceOops {
+ SpaceLink *next, *prev;
+ int spacetype, pad;
+ struct ScrArea *area;
+
+ View2D v2d;
+
+ ListBase oops;
+ short pin, visiflag, flag, rt;
+ void *lockpoin;
+
+} SpaceOops;
+
+typedef struct SpaceImage {
+ SpaceLink *next, *prev;
+ int spacetype, pad;
+ struct ScrArea *area;
+
+ View2D v2d;
+
+ struct Image *image;
+ float zoom;
+ float pad2; /* MAART: is this needed? Ton: yes, padding with 8 bytes aligned */
+ short mode, pin;
+ short imanr, curtile;
+ short xof, yof;
+ short flag, lock;
+
+} SpaceImage;
+
+typedef struct SpaceNla{
+ struct SpaceLink *next, *prev;
+ int spacetype;
+ int lock;
+ struct ScrArea *area;
+
+ View2D v2d;
+} SpaceNla;
+
+typedef struct SpaceText {
+ SpaceLink *next, *prev;
+ int spacetype, pad;
+ struct ScrArea *area;
+
+ struct Text *text;
+
+ int top, viewlines;
+ short flags, menunr;
+
+ int font_id;
+ int lheight;
+ int left, pad2;
+
+ float pix_per_line;
+
+ struct rcti txtscroll, txtbar;
+
+ void *py_draw;
+ void *py_event;
+ void *py_button;
+ void *py_globaldict;
+} SpaceText;
+
+#
+#
+typedef struct OneSelectableIma {
+ int header;
+ int ibuf_type;
+ struct ImBuf *pict;
+ struct OneSelectableIma *next;
+ struct OneSelectableIma *prev;
+
+ short cmap, image, draw_me, rt;
+ short sx, sy, ex, ey, dw, dh;
+ short selectable, selected;
+ int mtime, disksize;
+ char file_name[64];
+
+ short orgx, orgy, orgd, anim; /* same as ibuf->x...*/
+ char dummy[4]; /* 128 */
+
+ char pict_rect[3968]; /* 4096 (RECT = 64 * 62) */
+
+} OneSelectableIma;
+
+#
+#
+typedef struct ImaDir {
+ struct ImaDir *next, *prev;
+ int selected, hilite;
+ int type, size;
+ int mtime;
+ char name[100];
+} ImaDir;
+
+typedef struct SpaceImaSel {
+ SpaceLink *next, *prev;
+ int spacetype, pad1;
+ struct ScrArea *area;
+
+ char title[28];
+
+ int fase;
+ short mode, subfase;
+ short mouse_move_redraw, imafase;
+ short mx, my;
+
+ short dirsli, dirsli_lines;
+ short dirsli_sx, dirsli_ey , dirsli_ex, dirsli_h;
+ short imasli, fileselmenuitem;
+ short imasli_sx, imasli_ey , imasli_ex, imasli_h;
+
+ short dssx, dssy, dsex, dsey;
+ short desx, desy, deex, deey;
+ short fssx, fssy, fsex, fsey;
+ short dsdh, fsdh;
+ short fesx, fesy, feex, feey;
+ short infsx, infsy, infex, infey;
+ short dnsx, dnsy, dnw, dnh;
+ short fnsx, fnsy, fnw, fnh;
+
+
+ char fole[128], dor[128];
+ char file[128], dir[128];
+ ImaDir *firstdir, *firstfile;
+ int topdir, totaldirs, hilite;
+ int topfile, totalfiles;
+
+ float image_slider;
+ float slider_height;
+ float slider_space;
+ short topima, totalima;
+ short curimax, curimay;
+ OneSelectableIma *first_sel_ima;
+ OneSelectableIma *hilite_ima;
+ short total_selected, ima_redraw;
+ int pad2;
+
+ struct ImBuf *cmap;
+
+ /* Also fucked. Needs to change so things compile, but breaks sdna
+ * ... */
+/* void (*returnfunc)(void); */
+ void (*returnfunc)(char*);
+ void *arg1;
+} SpaceImaSel;
+
+
+/* **************** SPACE ********************* */
+
+
+/* view3d->flag */ /* Now in DNA_view3d_types.h */
+/*
+#define V3D_DISPIMAGE 1
+#define V3D_DISPBGPIC 2
+#define V3D_SETUPBUTS 4
+#define V3D_NEEDBACKBUFDRAW 8
+#define V3D_MODE (16+32+64+128)
+#define V3D_EDITMODE 16
+#define V3D_VERTEXPAINT 32
+#define V3D_FACESELECT 64
+#define V3D_POSEMODE 128
+*/
+
+/* view3d->around */ /* Now in DNA_view3d_types.h */
+/*
+#define V3D_CENTRE 0
+#define V3D_CENTROID 3
+#define V3D_CURSOR 1
+#define V3D_LOCAL 2
+*/
+
+/* buts->mainb */
+#define BUTS_VIEW 0
+#define BUTS_LAMP 1
+#define BUTS_MAT 2
+#define BUTS_TEX 3
+#define BUTS_ANIM 4
+#define BUTS_WORLD 5
+#define BUTS_RENDER 6
+#define BUTS_EDIT 7
+#define BUTS_GAME 8
+#define BUTS_FPAINT 9
+#define BUTS_RADIO 10
+#define BUTS_SCRIPT 11
+#define BUTS_SOUND 12
+#define BUTS_CONSTRAINT 13
+
+/* buts->scaflag */
+#define BUTS_SENS_SEL 1
+#define BUTS_SENS_ACT 2
+#define BUTS_SENS_LINK 4
+#define BUTS_CONT_SEL 8
+#define BUTS_CONT_ACT 16
+#define BUTS_CONT_LINK 32
+#define BUTS_ACT_SEL 64
+#define BUTS_ACT_ACT 128
+#define BUTS_ACT_LINK 256
+
+/* deze getallen ook invullen in blender.h SpaceFile: struct dna herkent geen defines */
+#define FILE_MAXDIR 160
+#define FILE_MAXFILE 80
+
+/* filesel types */
+#define FILE_UNIX 8
+#define FILE_BLENDER 8
+#define FILE_SPECIAL 9
+
+#define FILE_LOADLIB 1
+#define FILE_MAIN 2
+
+/* sfile->flag */
+#define FILE_SHOWSHORT 1
+#define FILE_STRINGCODE 2
+#define FILE_LINK 4
+#define FILE_HIDE_DOT 8
+
+/* sfile->sort */
+#define FILE_SORTALPHA 0
+#define FILE_SORTDATE 1
+#define FILE_SORTSIZE 2
+#define FILE_SORTEXTENS 3
+
+/* files in filesel list: 2=ACTIVE */
+#define HILITE 1
+#define BLENDERFILE 4
+#define PSXFILE 8
+#define IMAGEFILE 16
+#define MOVIEFILE 32
+
+#define SCROLLH 16 /* hoogte scrollbar */
+#define SCROLLB 16 /* breedte scrollbar */
+
+/* SpaceImage->mode */
+#define SI_TEXTURE 0
+#define SI_SHOW 1
+
+/* SpaceImage->flag */
+#define SI_BE_SQUARE 1
+#define SI_EDITTILE 2
+#define SI_CLIP_UV 4
+#define SI_DRAWTOOL 8
+
+/* SpaceText flags (moved from DNA_text_types.h) */
+
+#define ST_SCROLL_SELECT 0x0001 // scrollable
+#define ST_CLEAR_NAMESPACE 0x0010 // clear namespace after script
+ // execution (see BPY_main.c)
+
+/* SpaceOops->flag */
+#define SO_TESTBLOCKS 1
+#define SO_NEWSELECTED 2
+
+/* SpaceOops->visiflag */
+#define OOPS_SCE 1
+#define OOPS_OB 2
+#define OOPS_ME 4
+#define OOPS_CU 8
+#define OOPS_MB 16
+#define OOPS_LT 32
+#define OOPS_LA 64
+#define OOPS_MA 128
+#define OOPS_TE 256
+#define OOPS_IP 512
+#define OOPS_LAY 1024
+#define OOPS_LI 2048
+#define OOPS_IM 4096
+
+/* headerbuttons: 450-499 */
+
+#define B_IMASELHOME 451
+#define B_IMASELREMOVEBIP 452
+
+#define C_BACK 0xBAAAAA
+#define C_DARK 0x665656
+#define C_DERK 0x766666
+#define C_HI 0xCBBBBB
+#define C_LO 0x544444
+
+/* queue settings */
+#define IMS_KNOW_WIN 1
+#define IMS_KNOW_BIP 2
+#define IMS_KNOW_DIR 4
+#define IMS_DOTHE_INF 8
+#define IMS_KNOW_INF 16
+#define IMS_DOTHE_IMA 32
+#define IMS_KNOW_IMA 64
+#define IMS_FOUND_BIP 128
+#define IMS_DOTHE_BIP 256
+#define IMS_WRITE_NO_BIP 512
+
+/* imasel->mode */
+#define IMS_NOIMA 0
+#define IMS_IMA 1
+#define IMS_ANIM 2
+#define IMS_DIR 4
+#define IMS_FILE 8
+#define IMS_STRINGCODE 16
+
+#define IMS_INDIR 1
+#define IMS_INDIRSLI 2
+#define IMS_INFILE 3
+#define IMS_INFILESLI 4
+
+#endif
diff --git a/source/blender/makesdna/DNA_text_types.h b/source/blender/makesdna/DNA_text_types.h
new file mode 100644
index 00000000000..e5ac46b2e00
--- /dev/null
+++ b/source/blender/makesdna/DNA_text_types.h
@@ -0,0 +1,80 @@
+/**
+ * blenlib/DNA_text_types.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 DNA_TEXT_TYPES_H
+#define DNA_TEXT_TYPES_H
+
+#include "DNA_listBase.h"
+#include "DNA_ID.h"
+
+typedef struct TextLine {
+ struct TextLine *next, *prev;
+
+ char *line;
+ int len, blen;
+} TextLine;
+
+typedef struct Text {
+ ID id;
+
+ char *name;
+
+ int flags, nlines;
+
+ ListBase lines;
+ TextLine *curl, *sell;
+ int curc, selc;
+
+ char *undo_buf;
+ int undo_pos, undo_len;
+
+ void *compiled;
+} Text;
+
+
+#define TXT_OFFSET 35
+#define TXT_TABSIZE 4
+#define TXT_INIT_UNDO 1024
+#define TXT_MAX_UNDO (TXT_INIT_UNDO*TXT_INIT_UNDO)
+
+/* text flags */
+#define TXT_ISDIRTY 0x0001
+#define TXT_ISTMP 0x0002
+#define TXT_ISMEM 0x0004
+#define TXT_ISEXT 0x0008
+#define TXT_ISSCRIPT 0x0010
+#define TXT_READONLY 0x0100
+#define TXT_FOLLOW 0x0200 // always follow cursor (console)
+
+
+#endif
diff --git a/source/blender/makesdna/DNA_texture_types.h b/source/blender/makesdna/DNA_texture_types.h
new file mode 100644
index 00000000000..53f2fd71fcf
--- /dev/null
+++ b/source/blender/makesdna/DNA_texture_types.h
@@ -0,0 +1,276 @@
+/**
+ * blenlib/DNA_texture_types.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 DNA_TEXTURE_TYPES_H
+#define DNA_TEXTURE_TYPES_H
+
+#include "DNA_ID.h"
+
+struct Ipo;
+struct PluginTex;
+struct ColorBand;
+struct EnvMap;
+struct Object;
+struct Tex;
+struct Image;
+
+typedef struct MTex {
+
+ short texco, mapto, maptoneg, blendtype;
+ struct Object *object;
+ struct Tex *tex;
+
+ char projx, projy, projz, mapping;
+ float ofs[3], size[3];
+
+ short texflag, colormodel;
+ float r, g, b, k;
+ float def_var;
+
+ float colfac, norfac, varfac;
+
+} MTex;
+
+#ifndef DNA_USHORT_FIX
+#define DNA_USHORT_FIX
+/**
+ * @deprecated This typedef serves to avoid badly typed functions when
+ * @deprecated compiling while delivering a proper dna.c. Do not use
+ * @deprecated it in any case.
+ */
+typedef unsigned short dna_ushort_fix;
+#endif
+
+typedef struct PluginTex {
+ char name[160];
+ void *handle;
+
+ char *pname;
+ char *stnames;
+
+ int stypes;
+ int vars;
+ void *varstr;
+ float *result;
+ float *cfra;
+
+ float data[32];
+
+ int (*doit)(void);
+
+ /* should be void (*)(unsigned short)... patched */
+ void (*callback)(dna_ushort_fix);
+
+ int version, pad;
+} PluginTex;
+
+typedef struct CBData {
+ float r, g, b, a, pos;
+ int cur;
+} CBData;
+
+typedef struct ColorBand {
+ short flag, tot, cur, ipotype;
+ CBData data[16];
+
+} ColorBand;
+
+typedef struct EnvMap {
+ struct Object *object;
+ struct Image *ima; /* type ENV_LOAD */
+ struct Image *cube[6]; /* these images are dynamic, not part of the main struct */
+ float imat[4][4];
+ short type, stype;
+ float clipsta, clipend;
+ unsigned int notlay;
+ int cuberes;
+ short ok, lastframe;
+} EnvMap;
+
+typedef struct Tex {
+ ID id;
+
+ float noisesize, turbul;
+ float bright, contrast, rfac, gfac, bfac;
+ float filtersize;
+ short noisedepth, noisetype;
+
+ short imaflag, flag;
+ short type, stype;
+
+ float cropxmin, cropymin, cropxmax, cropymax;
+ short xrepeat, yrepeat;
+ short extend, len;
+ short frames, offset, sfra, fie_ima;
+ float norfac, *nor;
+
+ struct Ipo *ipo;
+ struct Image *ima;
+ struct PluginTex *plugin;
+ struct ColorBand *coba;
+ struct EnvMap *env;
+
+ short fradur[4][2];
+
+} Tex;
+
+/* **************** TEX ********************* */
+
+/* type */
+#define TEX_CLOUDS 1
+#define TEX_WOOD 2
+#define TEX_MARBLE 3
+#define TEX_MAGIC 4
+#define TEX_BLEND 5
+#define TEX_STUCCI 6
+#define TEX_NOISE 7
+#define TEX_IMAGE 8
+#define TEX_PLUGIN 9
+#define TEX_ENVMAP 10
+
+/* imaflag */
+#define TEX_INTERPOL 1
+#define TEX_USEALPHA 2
+#define TEX_MIPMAP 4
+#define TEX_FIELDS 8
+#define TEX_IMAROT 16
+#define TEX_CALCALPHA 32
+#define TEX_ANIMCYCLIC 64
+#define TEX_ANIM5 128
+#define TEX_ANTIALI 256
+#define TEX_ANTISCALE 512
+#define TEX_STD_FIELD 1024
+
+#define TEX_LASOPPATCH 8192
+#define TEX_MORKPATCH 16384
+
+/* flag */
+#define TEX_COLORBAND 1
+#define TEX_FLIPBLEND 2
+#define TEX_NEGALPHA 4
+
+/* extend (begint bij 1 ivm backward comp.) */
+#define TEX_EXTEND 1
+#define TEX_CLIP 2
+#define TEX_REPEAT 3
+#define TEX_CLIPCUBE 4
+
+/* noisetype */
+#define TEX_NOISESOFT 0
+#define TEX_NOISEPERL 1
+
+/* wrap */
+#define MTEX_FLAT 0
+#define MTEX_CUBE 1
+#define MTEX_TUBE 2
+#define MTEX_SPHERE 3
+
+/* return value */
+#define TEX_INT 0
+#define TEX_RGB 1
+#define TEX_NOR 2
+
+/* texco */
+#define TEXCO_ORCO 1
+#define TEXCO_REFL 2
+#define TEXCO_NORM 4
+#define TEXCO_GLOB 8
+#define TEXCO_UV 16
+#define TEXCO_OBJECT 32
+#define TEXCO_LAVECTOR 64
+#define TEXCO_VIEW 128
+#define TEXCO_STICKY 256
+#define TEXCO_OSA 512
+#define TEXCO_WINDOW 1024
+#define NEED_UV 2048
+
+/* mapto */
+#define MAP_COL 1
+#define MAP_NORM 2
+#define MAP_COLSPEC 4
+#define MAP_COLMIR 8
+#define MAP_VARS (0xFFF0)
+#define MAP_REF 16
+#define MAP_SPEC 32
+#define MAP_EMIT 64
+#define MAP_ALPHA 128
+#define MAP_HAR 256
+#define MAP_XTRA 512
+
+/* pr_type */
+#define MA_FLAT 0
+#define MA_SPHERE 1
+#define MA_CUBE 2
+
+/* pr_back */
+#define MA_DARK 1
+
+/* pr_lamp */
+
+/* **************** MTEX ********************* */
+
+/* proj */
+#define PROJ_N 0
+#define PROJ_X 1
+#define PROJ_Y 2
+#define PROJ_Z 3
+
+/* texflag */
+#define MTEX_RGBTOINT 1
+#define MTEX_STENCIL 2
+#define MTEX_NEGATIVE 4
+#define MTEX_ALPHAMIX 8
+
+/* blendtype */
+#define MTEX_BLEND 0
+#define MTEX_MUL 1
+#define MTEX_ADD 2
+#define MTEX_SUB 3
+
+/* **************** EnvMap ********************* */
+
+/* type */
+#define ENV_CUBE 0
+#define ENV_PLANE 1
+#define ENV_SPHERE 2
+
+/* stype */
+#define ENV_STATIC 0
+#define ENV_ANIM 1
+#define ENV_LOAD 2
+
+/* ok */
+#define ENV_NORMAL 1
+#define ENV_OSA 2
+
+#endif
diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h
new file mode 100644
index 00000000000..a55fa5a1d8d
--- /dev/null
+++ b/source/blender/makesdna/DNA_userdef_types.h
@@ -0,0 +1,105 @@
+/**
+ * blenkernel/DNA_userdef_types.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 DNA_USERDEF_TYPES_H
+#define DNA_USERDEF_TYPES_H
+
+typedef struct UserDef {
+ short flag, dupflag;
+ int savetime;
+ char tempdir[64];
+ char fontdir[64];
+ char renderdir[64];
+ char textudir[64];
+ char plugtexdir[64];
+ char plugseqdir[64];
+ char pythondir[64];
+ char sounddir[64];
+ short versions, vrmlflag; // tmp for export, will be replaced by strubi
+ int gameflags;
+ int dummy_1;
+} UserDef;
+
+extern UserDef U; /* from usiblender.c !!!! */
+
+/* ***************** USERDEF ****************** */
+
+/* flag */
+#define AUTOSAVE 1
+#define AUTOGRABGRID 2
+#define AUTOROTGRID 4
+#define AUTOSIZEGRID 8
+#define SCENEGLOBAL 16
+#define TRACKBALL 32
+#define DUPLILINK 64
+#define FSCOLLUM 128
+#define MAT_ON_OB 256
+#define NO_CAPSLOCK 512
+#define VIEWMOVE 1024
+#define TOOLTIPS 2048
+#define TWOBUTTONMOUSE 4096
+#define NONUMPAD 8192
+
+/* dupflag */
+#define DUPMESH 1
+#define DUPCURVE 2
+#define DUPSURF 4
+#define DUPFONT 8
+#define DUPMBALL 16
+#define DUPLAMP 32
+#define DUPIPO 64
+#define DUPMAT 128
+#define DUPTEX 256
+#define DUPARM 512
+#define DUPACT 1024
+
+/* gameflags */
+#define USERDEF_VERTEX_ARRAYS_BIT 0
+#define USERDEF_DISABLE_SOUND_BIT 1
+#define USERDEF_DISABLE_MIPMAP_BIT 2
+
+
+#define USERDEF_VERTEX_ARRAYS (1 << USERDEF_VERTEX_ARRAYS_BIT)
+#define USERDEF_DISABLE_SOUND (1 << USERDEF_DISABLE_SOUND_BIT)
+#define USERDEF_DISABLE_MIPMAP (1 << USERDEF_DISABLE_MIPMAP_BIT)
+
+
+/* vrml flag */
+
+#define USERDEF_VRML_LAYERS 1
+#define USERDEF_VRML_AUTOSCALE 2
+#define USERDEF_VRML_TWOSIDED 4
+
+
+#endif
diff --git a/source/blender/makesdna/DNA_vec_types.h b/source/blender/makesdna/DNA_vec_types.h
new file mode 100644
index 00000000000..3df1691944b
--- /dev/null
+++ b/source/blender/makesdna/DNA_vec_types.h
@@ -0,0 +1,91 @@
+/**
+ * vec_types.h dec 2000 Nzc
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 DNA_VEC_TYPES_H
+#define DNA_VEC_TYPES_H
+
+/* types */
+
+typedef struct vec2s {
+ short x, y;
+} vec2s;
+
+typedef struct vec2i {
+ int x, y;
+} vec2i;
+
+typedef struct vec2f {
+ float x, y;
+} vec2f;
+
+typedef struct vec2d {
+ double x, y;
+} vec2d;
+
+typedef struct vec3i {
+ int x, y, z;
+} vec3i;
+
+typedef struct vec3f {
+ float x, y, z;
+} vec3f;
+
+typedef struct vec3d {
+ double x, y, z;
+} vec3d;
+
+typedef struct vec4i {
+ int x, y, z, w;
+} vec4i;
+
+typedef struct vec4f {
+ float x, y, z, w;
+} vec4f;
+
+typedef struct vec4d {
+ double x, y, z, w;
+} vec4d;
+
+typedef struct rcti {
+ int xmin, xmax;
+ int ymin, ymax;
+} rcti;
+
+typedef struct rctf {
+ float xmin, xmax;
+ float ymin, ymax;
+} rctf;
+
+#endif
diff --git a/source/blender/makesdna/DNA_vfont_types.h b/source/blender/makesdna/DNA_vfont_types.h
new file mode 100644
index 00000000000..bd50a7bd8c8
--- /dev/null
+++ b/source/blender/makesdna/DNA_vfont_types.h
@@ -0,0 +1,59 @@
+/**
+ * blenlib/DNA_vfont_types.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 DNA_VFONT_TYPES_H
+#define DNA_VFONT_TYPES_H
+
+#include "DNA_ID.h"
+
+struct PackedFile;
+struct VFontData;
+
+typedef struct VFont {
+ ID id;
+
+ char name[256];
+ float scale, pad;
+
+ struct VFontData *data;
+ struct PackedFile * packedfile;
+} VFont;
+
+/* *************** FONT ****************** */
+
+#define FO_CURS 1
+#define FO_CURSUP 2
+#define FO_CURSDOWN 3
+#define FO_DUPLI 4
+
+#endif
diff --git a/source/blender/makesdna/DNA_view2d_types.h b/source/blender/makesdna/DNA_view2d_types.h
new file mode 100644
index 00000000000..5d97584a0a7
--- /dev/null
+++ b/source/blender/makesdna/DNA_view2d_types.h
@@ -0,0 +1,52 @@
+/**
+ * blenlib/DNA_view2d_types.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 DNA_VIEW2D_TYPES_H
+#define DNA_VIEW2D_TYPES_H
+
+#include "DNA_vec_types.h"
+
+typedef struct View2D {
+ rctf tot, cur;
+ rcti vert, hor, mask;
+ float min[2], max[2];
+ float minzoom, maxzoom;
+ short scroll, keeptot;
+ short keepaspect, keepzoom;
+} View2D;
+
+#define V2D_KEEPZOOM 0x0001
+#define V2D_LOCKZOOM_X 0x0100
+#define V2D_LOCKZOOM_Y 0x0200
+
+#endif
diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h
new file mode 100644
index 00000000000..3dbe3978b15
--- /dev/null
+++ b/source/blender/makesdna/DNA_view3d_types.h
@@ -0,0 +1,127 @@
+/**
+ * blenlib/DNA_view3d_types.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 DNA_VIEW3D_TYPES_H
+#define DNA_VIEW3D_TYPES_H
+
+struct Object;
+struct Image;
+struct Tex;
+struct SpaceLink;
+
+/* This is needed to not let VC choke on near and far... old
+ * proprietary MS extensions... */
+#ifdef WIN32
+#undef near
+#undef far
+#define near clipsta
+#define far clipend
+#endif
+
+/* The near/far thing is a Win EXCEPTION. Thus, leave near/far in the
+ * code, and patch for windows. */
+
+typedef struct BGpic {
+ struct Image *ima;
+ struct Tex *tex;
+ float xof, yof, size, zoom, blend;
+ short xim, yim;
+ unsigned int *rect;
+} BGpic;
+
+typedef struct View3D {
+ struct SpaceLink *next, *prev;
+ int spacetype, pad;
+ struct ScrArea *area;
+
+ float viewmat[4][4];
+ float viewinv[4][4];
+ float persmat[4][4];
+ float persinv[4][4];
+ float viewquat[4], dist;
+
+ /**
+ * 0 - ortho
+ * 1 - do 3d perspective
+ * 2 - use the camera
+ */
+ short persp;
+ short view;
+
+ struct Object *camera;
+ struct BGpic *bgpic;
+ struct View3D *localvd;
+
+ /**
+ * The drawing mode for the 3d display. Set to OB_WIRE, OB_SOLID,
+ * OB_SHADED or OB_TEXTURED */
+ short drawtype;
+ short localview;
+ int lay, layact;
+ short scenelock, around, camzoom, flag;
+
+ float lens, grid, near, far;
+ float ofs[3], cursor[3];
+
+ short mx, my; /* moeten achter elkaar blijven staan ivm als pointer doorgeven */
+ short mxo, myo;
+
+ short gridlines, viewbut;
+ int pad2, pad3;
+} View3D;
+
+/* View3D->flag */
+#define V3D_MODE (16+32+64+128+256+512)
+#define V3D_DISPIMAGE 1
+#define V3D_DISPBGPIC 2
+#define V3D_SETUPBUTS 4
+#define V3D_NEEDBACKBUFDRAW 8
+#define V3D_EDITMODE 16
+#define V3D_VERTEXPAINT 32
+#define V3D_FACESELECT 64
+#define V3D_POSEMODE 128
+#define V3D_TEXTUREPAINT 256
+#define V3D_WEIGHTPAINT 512
+
+/* View3D->around */
+#define V3D_CENTRE 0
+#define V3D_CENTROID 3
+#define V3D_CURSOR 1
+#define V3D_LOCAL 2
+
+/* View3d->persp */
+#define V3D_PERSP_ORTHO 0
+#define V3D_PERSP_DO_3D_PERSP 1
+#define V3D_PERSP_USE_THE_CAMERA 2
+
+#endif
diff --git a/source/blender/makesdna/DNA_wave_types.h b/source/blender/makesdna/DNA_wave_types.h
new file mode 100644
index 00000000000..8da044627bd
--- /dev/null
+++ b/source/blender/makesdna/DNA_wave_types.h
@@ -0,0 +1,48 @@
+/**
+ * blenlib/DNA_wave_types.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 DNA_WAVE_TYPES_H
+#define DNA_WAVE_TYPES_H
+
+#include "DNA_ID.h"
+
+struct Ipo;
+
+typedef struct Wave {
+ ID id;
+
+ struct Ipo *ipo;
+
+} Wave;
+
+#endif
diff --git a/source/blender/makesdna/DNA_world_types.h b/source/blender/makesdna/DNA_world_types.h
new file mode 100644
index 00000000000..576c480bf24
--- /dev/null
+++ b/source/blender/makesdna/DNA_world_types.h
@@ -0,0 +1,119 @@
+/**
+ * blenlib/DNA_world_types.h (mar-2001 nzc)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 DNA_WORLD_TYPES_H
+#define DNA_WORLD_TYPES_H
+
+#include "DNA_ID.h"
+#include "DNA_scriptlink_types.h"
+
+struct Ipo;
+struct MTex;
+
+
+/**
+ * World defines general modelling data such as a background fill,
+ * gravity, colour model, stars, etc. It mixes game-data, rendering
+ * data and modelling data. */
+typedef struct World {
+ ID id;
+
+ short colormodel, totex;
+ short texact, mistype;
+
+ float horr, horg, horb, hork;
+ float zenr, zeng, zenb, zenk;
+ float ambr, ambg, ambb, ambk;
+
+ unsigned int fastcol;
+
+ float exposure;
+
+ /**
+ * Gravitation constant for the game world
+ */
+ float gravity;
+
+ /**
+ * Radius of the activity bubble, in Manhattan length. Objects
+ * outside the box are activity-culled. */
+ float activityBoxRadius;
+
+ short skytype;
+ /**
+ * Some world modes
+ * bit 0: Do mist
+ * bit 1: Do stars
+ * bit 2: (reserved) depth of field
+ * bit 3: (gameengine): Activity culling is enabled.
+ */
+ short mode;
+
+ float misi, miststa, mistdist, misthi;
+
+ float starr, starg, starb, stark;
+ float starsize, starmindist;
+ float stardist, starcolnoise;
+
+ short dofsta, dofend, dofmin, dofmax;
+
+ int pad1;
+ struct Ipo *ipo;
+ struct MTex *mtex[8];
+
+ ScriptLink scriptlink;
+} World;
+
+/* **************** WORLD ********************* */
+
+/* skytype */
+#define WO_SKYBLEND 1
+#define WO_SKYREAL 2
+#define WO_SKYPAPER 4
+/* tijdens render: */
+#define WO_SKYTEX 8
+#define WO_ZENUP 16
+
+/* mode */
+#define WO_MIST 1
+#define WO_STARS 2
+#define WO_DOF 4
+#define WO_ACTIVITY_CULLING 8
+
+/* mapto */
+#define WOMAP_BLEND 1
+#define WOMAP_HORIZ 2
+#define WOMAP_ZENUP 4
+#define WOMAP_ZENDOWN 8
+
+#endif
diff --git a/source/blender/makesdna/Makefile b/source/blender/makesdna/Makefile
new file mode 100644
index 00000000000..f8274102b8c
--- /dev/null
+++ b/source/blender/makesdna/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 *****
+#
+#
+# This module does not build normal .o's, but a DNA.c file, to be
+# compiled with the rest of the sources. To speed things up a little,
+# the compilation is done here.
+#
+# Bounces make to subdirectories.
+
+SOURCEDIR = source/blender/makesdna
+DIRS = intern
+
+include nan_subdirs.mk
diff --git a/source/blender/makesdna/intern/Makefile b/source/blender/makesdna/intern/Makefile
new file mode 100644
index 00000000000..d6a762156ca
--- /dev/null
+++ b/source/blender/makesdna/intern/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 *****
+#
+#
+
+DIR = $(OCGDIR)/blender/makesdna
+CSRCS = $(wildcard *.c)
+
+ALLTARGETS = $(OBJS) $(DIR)/$(DEBUG_DIR)makesdna $(DIR)/$(SHARED_DIR)$(DEBUG_DIR)DNA.o
+
+include nan_compile.mk
+
+ifneq ($(OS),irix)
+ CFLAGS += -funsigned-char
+endif
+
+CFLAGS += $(LEVEL_1_C_WARNINGS)
+
+CPPFLAGS += -I$(OPENGL_HEADERS)
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+CPPFLAGS += -I../../blenlib
+CPPFLAGS += -I..
+
+ifeq ($(OS),windows)
+ # Windows needs these extra libs because of winstuff... It is not
+ # _really_ needed, but it is the easiest fix for now. If you have
+ # some spare time, try to trace down the exact dep. Then again, you
+ # could also spend that time making the sdna system more robust.
+ WINLIBS = kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib
+ WINLIBS += advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib
+ WINLIBS += winmm.lib opengl32.lib glu32.lib largeint.lib
+ WINLIBS += /link /nodefaultlib:libc
+endif
+
+clean::
+ @$(RM) $(DIR)/makesdna* $(DIR)/DNA.c
+ @$(RM) $(DIR)/debug/makesdna* $(DIR)/debug/DNA.c
+
+# TODO include right .mk for ldflags
+
+# A small note: we do not use the debug version of the alloc lib. That
+# is done quite intentionally. If there is a bug in that lib, it needs
+# to be fixed by the module maintainer.
+$(DIR)/$(DEBUG_DIR)makesdna: $(OBJS) $(OCGDIR)/blender/blenlib/$(DEBUG_DIR)libblenlib.a
+ $(CC) $(LDFLAGS) -o $@ $(OBJS) \
+ $(NAN_GUARDEDALLOC)/lib/libguardedalloc.a $(WINLIBS)
+
+$(DIR)/$(DEBUG_DIR)DNA.c: $(DIR)/$(DEBUG_DIR)makesdna
+ ifeq ($(OS),windows)
+ $(SRCHOME)/tools/cygwin/cl_wrapper.pl - $(DIR)/$(DEBUG_DIR)makesdna \
+ $(DIR)/$(DEBUG_DIR)DNA.c
+ else
+ $(DIR)/$(DEBUG_DIR)makesdna $(DIR)/$(DEBUG_DIR)DNA.c
+ endif
+
+$(DIR)/$(SHARED_DIR)$(DEBUG_DIR)DNA.o: $(DIR)/$(DEBUG_DIR)DNA.c
+ $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@
+
diff --git a/source/blender/makesdna/intern/dna.c b/source/blender/makesdna/intern/dna.c
new file mode 100644
index 00000000000..e4de70fbc34
--- /dev/null
+++ b/source/blender/makesdna/intern/dna.c
@@ -0,0 +1,874 @@
+unsigned char DNAstr[]= {
+83,68,78,65,78,65,77,69,219,3,0,0,42,110,101,120,116,0,42,112,
+114,101,118,0,42,102,105,114,115,116,0,42,108,97,115,116,0,120,0,121,
+0,122,0,119,0,120,109,105,110,0,120,109,97,120,0,121,109,105,110,0,
+121,109,97,120,0,42,110,101,119,105,100,0,42,108,105,98,0,110,97,109,
+101,91,50,52,93,0,117,115,0,102,108,97,103,0,112,97,100,0,105,100,
+0,42,105,100,98,108,111,99,107,0,42,102,105,108,101,100,97,116,97,0,
+110,97,109,101,91,49,54,48,93,0,116,111,116,0,99,117,114,118,101,0,
+99,117,114,0,98,108,111,99,107,116,121,112,101,0,115,104,111,119,107,101,
+121,0,112,111,115,0,116,111,116,101,108,101,109,0,116,121,112,101,0,114,
+116,0,42,100,97,116,97,0,42,114,101,102,107,101,121,0,101,108,101,109,
+115,116,114,91,51,50,93,0,101,108,101,109,115,105,122,101,0,99,117,114,
+118,97,108,0,98,108,111,99,107,0,42,105,112,111,0,42,102,114,111,109,
+0,116,111,116,107,101,121,0,115,108,117,114,112,104,0,97,99,116,107,101,
+121,0,42,42,115,99,114,105,112,116,115,0,42,102,108,97,103,0,97,99,
+116,115,99,114,105,112,116,0,116,111,116,115,99,114,105,112,116,0,42,108,
+105,110,101,0,108,101,110,0,98,108,101,110,0,42,110,97,109,101,0,102,
+108,97,103,115,0,110,108,105,110,101,115,0,108,105,110,101,115,0,42,99,
+117,114,108,0,42,115,101,108,108,0,99,117,114,99,0,115,101,108,99,0,
+42,117,110,100,111,95,98,117,102,0,117,110,100,111,95,112,111,115,0,117,
+110,100,111,95,108,101,110,0,42,99,111,109,112,105,108,101,100,0,115,105,
+122,101,0,115,101,101,107,0,100,114,97,119,122,111,111,109,0,104,111,108,
+100,0,99,108,105,112,115,116,97,0,99,108,105,112,101,110,100,0,110,101,
+116,115,116,97,0,110,101,116,101,110,100,0,108,101,110,115,0,100,114,97,
+119,115,105,122,101,0,104,111,108,111,108,101,110,0,104,111,108,111,108,101,
+110,49,0,115,99,114,105,112,116,108,105,110,107,0,42,97,110,105,109,0,
+42,105,98,117,102,0,42,109,105,112,109,97,112,91,49,48,93,0,111,107,
+0,108,97,115,116,102,114,97,109,101,0,108,97,115,116,113,117,97,108,105,
+116,121,0,116,112,97,103,101,102,108,97,103,0,116,111,116,98,105,110,100,
+0,120,114,101,112,0,121,114,101,112,0,116,119,115,116,97,0,116,119,101,
+110,100,0,98,105,110,100,99,111,100,101,0,42,114,101,112,98,105,110,100,
+0,42,112,97,99,107,101,100,102,105,108,101,0,108,97,115,116,117,112,100,
+97,116,101,0,97,110,105,109,115,112,101,101,100,0,114,101,115,101,114,118,
+101,100,49,0,116,101,120,99,111,0,109,97,112,116,111,0,109,97,112,116,
+111,110,101,103,0,98,108,101,110,100,116,121,112,101,0,42,111,98,106,101,
+99,116,0,42,116,101,120,0,112,114,111,106,120,0,112,114,111,106,121,0,
+112,114,111,106,122,0,109,97,112,112,105,110,103,0,111,102,115,91,51,93,
+0,115,105,122,101,91,51,93,0,116,101,120,102,108,97,103,0,99,111,108,
+111,114,109,111,100,101,108,0,114,0,103,0,98,0,107,0,100,101,102,95,
+118,97,114,0,99,111,108,102,97,99,0,110,111,114,102,97,99,0,118,97,
+114,102,97,99,0,42,104,97,110,100,108,101,0,42,112,110,97,109,101,0,
+42,115,116,110,97,109,101,115,0,115,116,121,112,101,115,0,118,97,114,115,
+0,42,118,97,114,115,116,114,0,42,114,101,115,117,108,116,0,42,99,102,
+114,97,0,100,97,116,97,91,51,50,93,0,40,42,100,111,105,116,41,40,
+41,0,40,42,99,97,108,108,98,97,99,107,41,40,41,0,118,101,114,115,
+105,111,110,0,97,0,105,112,111,116,121,112,101,0,100,97,116,97,91,49,
+54,93,0,42,105,109,97,0,42,99,117,98,101,91,54,93,0,105,109,97,
+116,91,52,93,91,52,93,0,115,116,121,112,101,0,110,111,116,108,97,121,
+0,99,117,98,101,114,101,115,0,110,111,105,115,101,115,105,122,101,0,116,
+117,114,98,117,108,0,98,114,105,103,104,116,0,99,111,110,116,114,97,115,
+116,0,114,102,97,99,0,103,102,97,99,0,98,102,97,99,0,102,105,108,
+116,101,114,115,105,122,101,0,110,111,105,115,101,100,101,112,116,104,0,110,
+111,105,115,101,116,121,112,101,0,105,109,97,102,108,97,103,0,99,114,111,
+112,120,109,105,110,0,99,114,111,112,121,109,105,110,0,99,114,111,112,120,
+109,97,120,0,99,114,111,112,121,109,97,120,0,120,114,101,112,101,97,116,
+0,121,114,101,112,101,97,116,0,101,120,116,101,110,100,0,102,114,97,109,
+101,115,0,111,102,102,115,101,116,0,115,102,114,97,0,102,105,101,95,105,
+109,97,0,42,110,111,114,0,42,112,108,117,103,105,110,0,42,99,111,98,
+97,0,42,101,110,118,0,102,114,97,100,117,114,91,52,93,91,50,93,0,
+109,111,100,101,0,116,111,116,101,120,0,101,110,101,114,103,121,0,100,105,
+115,116,0,115,112,111,116,115,105,122,101,0,115,112,111,116,98,108,101,110,
+100,0,104,97,105,110,116,0,97,116,116,49,0,97,116,116,50,0,98,117,
+102,115,105,122,101,0,115,97,109,112,0,115,104,97,100,115,112,111,116,115,
+105,122,101,0,98,105,97,115,0,115,111,102,116,0,116,101,120,97,99,116,
+0,115,104,97,100,104,97,108,111,115,116,101,112,0,42,109,116,101,120,91,
+56,93,0,108,97,121,0,115,112,101,99,114,0,115,112,101,99,103,0,115,
+112,101,99,98,0,109,105,114,114,0,109,105,114,103,0,109,105,114,98,0,
+97,109,98,114,0,97,109,98,98,0,97,109,98,103,0,97,109,98,0,101,
+109,105,116,0,97,110,103,0,115,112,101,99,116,114,97,0,97,108,112,104,
+97,0,114,101,102,0,115,112,101,99,0,122,111,102,102,115,0,97,100,100,
+0,107,102,97,99,0,104,97,114,0,115,101,101,100,49,0,115,101,101,100,
+50,0,109,111,100,101,50,0,102,108,97,114,101,99,0,115,116,97,114,99,
+0,108,105,110,101,99,0,114,105,110,103,99,0,104,97,115,105,122,101,0,
+102,108,97,114,101,115,105,122,101,0,115,117,98,115,105,122,101,0,102,108,
+97,114,101,98,111,111,115,116,0,114,103,98,115,101,108,0,112,114,95,116,
+121,112,101,0,115,101,112,116,101,120,0,112,114,95,98,97,99,107,0,112,
+114,95,108,97,109,112,0,112,97,100,49,0,42,114,101,110,0,102,114,105,
+99,116,105,111,110,0,102,104,0,114,101,102,108,101,99,116,0,102,104,100,
+105,115,116,0,120,121,102,114,105,99,116,0,100,121,110,97,109,111,100,101,
+0,110,97,109,101,91,50,53,54,93,0,115,99,97,108,101,0,115,101,108,
+99,111,108,0,101,120,112,120,0,101,120,112,121,0,101,120,112,122,0,114,
+97,100,0,114,97,100,50,0,115,0,109,97,120,114,97,100,50,0,42,109,
+97,116,0,42,105,109,97,116,0,42,98,98,0,101,108,101,109,115,0,100,
+105,115,112,0,42,42,109,97,116,0,116,111,116,99,111,108,0,108,111,99,
+91,51,93,0,114,111,116,91,51,93,0,119,105,114,101,115,105,122,101,0,
+114,101,110,100,101,114,115,105,122,101,0,116,104,114,101,115,104,0,118,101,
+99,91,51,93,91,51,93,0,97,108,102,97,0,115,91,51,93,91,50,93,
+0,104,49,0,104,50,0,102,49,0,102,50,0,102,51,0,104,105,100,101,
+0,118,101,99,91,52,93,0,115,91,50,93,0,109,97,116,95,110,114,0,
+112,110,116,115,117,0,112,110,116,115,118,0,114,101,115,111,108,117,0,114,
+101,115,111,108,118,0,111,114,100,101,114,117,0,111,114,100,101,114,118,0,
+102,108,97,103,117,0,102,108,97,103,118,0,42,107,110,111,116,115,117,0,
+42,107,110,111,116,115,118,0,42,98,112,0,42,98,101,122,116,0,110,117,
+114,98,0,42,98,101,118,111,98,106,0,42,116,101,120,116,111,110,99,117,
+114,118,101,0,42,112,97,116,104,0,42,107,101,121,0,98,101,118,0,42,
+111,114,99,111,0,112,97,116,104,108,101,110,0,98,101,118,114,101,115,111,
+108,0,119,105,100,116,104,0,101,120,116,49,0,101,120,116,50,0,115,112,
+97,99,101,109,111,100,101,0,115,112,97,99,105,110,103,0,108,105,110,101,
+100,105,115,116,0,115,104,101,97,114,0,102,115,105,122,101,0,120,111,102,
+0,121,111,102,0,42,115,116,114,0,102,97,109,105,108,121,91,50,52,93,
+0,42,118,102,111,110,116,0,109,97,120,114,99,116,0,116,111,116,114,99,
+116,0,97,100,114,99,111,100,101,0,118,97,114,116,121,112,101,0,116,111,
+116,118,101,114,116,0,105,112,111,0,101,120,116,114,97,112,0,98,105,116,
+109,97,115,107,0,118,49,0,118,50,0,118,51,0,118,52,0,112,117,110,
+111,0,101,100,99,111,100,101,0,42,116,112,97,103,101,0,117,118,91,52,
+93,91,50,93,0,99,111,108,91,52,93,0,116,114,97,110,115,112,0,116,
+105,108,101,0,100,101,102,95,110,114,0,119,101,105,103,104,116,0,42,100,
+119,0,116,111,116,119,101,105,103,104,116,0,99,111,91,51,93,0,110,111,
+91,51,93,0,99,111,91,50,93,0,101,102,102,101,99,116,0,42,109,102,
+97,99,101,0,42,100,102,97,99,101,0,42,116,102,97,99,101,0,42,109,
+118,101,114,116,0,42,100,118,101,114,116,0,42,109,99,111,108,0,42,109,
+115,116,105,99,107,121,0,42,116,101,120,99,111,109,101,115,104,0,42,111,
+99,0,42,115,117,109,111,104,97,110,100,108,101,0,116,111,116,102,97,99,
+101,0,115,109,111,111,116,104,114,101,115,104,0,115,117,98,100,105,118,0,
+115,117,98,100,105,118,114,0,114,101,115,101,114,118,101,100,50,0,114,101,
+115,101,114,118,101,100,51,0,99,117,98,101,109,97,112,115,105,122,101,0,
+114,116,102,0,112,110,116,115,119,0,116,121,112,101,117,0,116,121,112,101,
+118,0,116,121,112,101,119,0,42,100,101,102,0,110,97,109,101,91,51,50,
+93,0,112,97,114,116,121,112,101,0,112,97,114,49,0,112,97,114,50,0,
+112,97,114,51,0,112,97,114,115,117,98,115,116,114,91,51,50,93,0,42,
+112,97,114,100,97,116,97,0,42,112,97,114,101,110,116,0,42,116,114,97,
+99,107,0,42,97,99,116,105,111,110,0,42,112,111,115,101,0,42,97,99,
+116,105,118,101,99,111,110,0,99,111,110,115,116,114,97,105,110,116,67,104,
+97,110,110,101,108,115,0,110,101,116,119,111,114,107,0,100,101,102,98,97,
+115,101,0,100,108,111,99,91,51,93,0,111,114,105,103,91,51,93,0,100,
+115,105,122,101,91,51,93,0,100,114,111,116,91,51,93,0,113,117,97,116,
+91,52,93,0,100,113,117,97,116,91,52,93,0,111,98,109,97,116,91,52,
+93,91,52,93,0,112,97,114,101,110,116,105,110,118,91,52,93,91,52,93,
+0,99,111,108,98,105,116,115,0,116,114,97,110,115,102,108,97,103,0,105,
+112,111,102,108,97,103,0,116,114,97,99,107,102,108,97,103,0,117,112,102,
+108,97,103,0,105,112,111,119,105,110,0,115,99,97,102,108,97,103,0,115,
+99,97,118,105,115,102,108,97,103,0,98,111,117,110,100,116,121,112,101,0,
+100,117,112,111,110,0,100,117,112,111,102,102,0,100,117,112,115,116,97,0,
+100,117,112,101,110,100,0,115,102,0,99,116,105,109,101,0,109,97,115,115,
+0,100,97,109,112,105,110,103,0,105,110,101,114,116,105,97,0,102,111,114,
+109,102,97,99,116,111,114,0,100,117,109,109,121,95,49,0,114,100,97,109,
+112,105,110,103,0,115,105,122,101,102,97,99,0,100,116,0,100,116,120,0,
+97,99,116,99,111,108,0,112,114,111,112,0,115,101,110,115,111,114,115,0,
+99,111,110,116,114,111,108,108,101,114,115,0,97,99,116,117,97,116,111,114,
+115,0,98,98,115,105,122,101,91,51,93,0,100,102,114,97,115,0,97,99,
+116,100,101,102,0,103,97,109,101,102,108,97,103,0,103,97,109,101,102,108,
+97,103,50,0,97,110,105,115,111,116,114,111,112,105,99,70,114,105,99,116,
+105,111,110,91,51,93,0,99,111,110,115,116,114,97,105,110,116,115,0,110,
+108,97,115,116,114,105,112,115,0,109,105,115,116,121,112,101,0,104,111,114,
+114,0,104,111,114,103,0,104,111,114,98,0,104,111,114,107,0,122,101,110,
+114,0,122,101,110,103,0,122,101,110,98,0,122,101,110,107,0,97,109,98,
+107,0,102,97,115,116,99,111,108,0,101,120,112,111,115,117,114,101,0,103,
+114,97,118,105,116,121,0,97,99,116,105,118,105,116,121,66,111,120,82,97,
+100,105,117,115,0,115,107,121,116,121,112,101,0,109,105,115,105,0,109,105,
+115,116,115,116,97,0,109,105,115,116,100,105,115,116,0,109,105,115,116,104,
+105,0,115,116,97,114,114,0,115,116,97,114,103,0,115,116,97,114,98,0,
+115,116,97,114,107,0,115,116,97,114,115,105,122,101,0,115,116,97,114,109,
+105,110,100,105,115,116,0,115,116,97,114,100,105,115,116,0,115,116,97,114,
+99,111,108,110,111,105,115,101,0,100,111,102,115,116,97,0,100,111,102,101,
+110,100,0,100,111,102,109,105,110,0,100,111,102,109,97,120,0,104,101,109,
+105,114,101,115,0,109,97,120,105,116,101,114,0,100,114,97,119,116,121,112,
+101,0,115,117,98,115,104,111,111,116,112,0,115,117,98,115,104,111,111,116,
+101,0,110,111,100,101,108,105,109,0,109,97,120,115,117,98,108,97,109,112,
+0,112,97,109,97,0,112,97,109,105,0,101,108,109,97,0,101,108,109,105,
+0,109,97,120,110,111,100,101,0,99,111,110,118,101,114,103,101,110,99,101,
+0,114,97,100,102,97,99,0,103,97,109,109,97,0,115,120,0,115,121,0,
+42,108,112,70,111,114,109,97,116,0,42,108,112,80,97,114,109,115,0,99,
+98,70,111,114,109,97,116,0,99,98,80,97,114,109,115,0,102,99,99,84,
+121,112,101,0,102,99,99,72,97,110,100,108,101,114,0,100,119,75,101,121,
+70,114,97,109,101,69,118,101,114,121,0,100,119,81,117,97,108,105,116,121,
+0,100,119,66,121,116,101,115,80,101,114,83,101,99,111,110,100,0,100,119,
+70,108,97,103,115,0,100,119,73,110,116,101,114,108,101,97,118,101,69,118,
+101,114,121,0,42,97,118,105,99,111,100,101,99,100,97,116,97,0,99,102,
+114,97,0,101,102,114,97,0,105,109,97,103,101,115,0,102,114,97,109,97,
+112,116,111,0,102,114,97,109,101,108,101,110,0,98,108,117,114,102,97,99,
+0,101,100,103,101,82,0,101,100,103,101,71,0,101,100,103,101,66,0,102,
+117,108,108,115,99,114,101,101,110,0,120,112,108,97,121,0,121,112,108,97,
+121,0,102,114,101,113,112,108,97,121,0,100,101,112,116,104,0,97,116,116,
+114,105,98,0,114,116,49,0,114,116,50,0,115,116,101,114,101,111,109,111,
+100,101,0,112,97,100,91,51,93,0,109,97,120,105,109,115,105,122,101,0,
+120,115,99,104,0,121,115,99,104,0,120,97,115,112,0,121,97,115,112,0,
+120,112,97,114,116,115,0,121,112,97,114,116,115,0,115,97,102,101,116,121,
+0,98,111,114,100,101,114,0,119,105,110,112,111,115,0,112,108,97,110,101,
+115,0,105,109,116,121,112,101,0,98,117,102,102,108,97,103,0,113,117,97,
+108,105,116,121,0,115,99,101,109,111,100,101,0,97,108,112,104,97,109,111,
+100,101,0,100,111,103,97,109,109,97,0,111,115,97,0,102,114,115,95,115,
+101,99,0,101,100,103,101,105,110,116,0,115,97,109,101,95,109,97,116,95,
+114,101,100,117,120,0,112,97,100,95,51,91,51,93,0,112,111,115,116,109,
+117,108,0,112,111,115,116,103,97,109,109,97,0,112,111,115,116,97,100,100,
+0,112,111,115,116,105,103,97,109,109,97,0,98,97,99,107,98,117,102,91,
+49,54,48,93,0,112,105,99,91,49,54,48,93,0,102,116,121,112,101,91,
+49,54,48,93,0,99,111,108,91,51,93,0,112,97,100,50,0,112,97,100,
+51,0,42,99,97,109,101,114,97,0,42,119,111,114,108,100,0,42,115,101,
+116,0,98,97,115,101,0,42,98,97,115,97,99,116,0,42,103,114,111,117,
+112,0,99,117,114,115,111,114,91,51,93,0,42,102,99,97,109,0,42,101,
+100,0,42,114,97,100,105,111,0,102,114,97,109,105,110,103,0,122,111,111,
+109,0,98,108,101,110,100,0,120,105,109,0,121,105,109,0,42,114,101,99,
+116,0,115,112,97,99,101,116,121,112,101,0,42,97,114,101,97,0,118,105,
+101,119,109,97,116,91,52,93,91,52,93,0,118,105,101,119,105,110,118,91,
+52,93,91,52,93,0,112,101,114,115,109,97,116,91,52,93,91,52,93,0,
+112,101,114,115,105,110,118,91,52,93,91,52,93,0,118,105,101,119,113,117,
+97,116,91,52,93,0,112,101,114,115,112,0,118,105,101,119,0,42,98,103,
+112,105,99,0,42,108,111,99,97,108,118,100,0,108,111,99,97,108,118,105,
+101,119,0,108,97,121,97,99,116,0,115,99,101,110,101,108,111,99,107,0,
+97,114,111,117,110,100,0,99,97,109,122,111,111,109,0,103,114,105,100,0,
+110,101,97,114,0,102,97,114,0,109,120,0,109,121,0,109,120,111,0,109,
+121,111,0,103,114,105,100,108,105,110,101,115,0,118,105,101,119,98,117,116,
+0,118,101,114,116,0,104,111,114,0,109,97,115,107,0,109,105,110,91,50,
+93,0,109,97,120,91,50,93,0,109,105,110,122,111,111,109,0,109,97,120,
+122,111,111,109,0,115,99,114,111,108,108,0,107,101,101,112,116,111,116,0,
+107,101,101,112,97,115,112,101,99,116,0,107,101,101,112,122,111,111,109,0,
+114,111,119,98,117,116,0,118,50,100,0,42,101,100,105,116,105,112,111,0,
+105,112,111,107,101,121,0,116,111,116,105,112,111,0,112,105,110,0,98,117,
+116,111,102,115,0,99,104,97,110,110,101,108,0,109,101,110,117,110,114,0,
+108,111,99,107,0,99,117,114,115,101,110,115,0,99,117,114,97,99,116,0,
+109,97,105,110,98,0,109,97,105,110,98,111,0,42,108,111,99,107,112,111,
+105,110,0,116,101,120,110,114,0,116,101,120,102,114,111,109,0,115,104,111,
+119,103,114,111,117,112,0,114,101,99,116,120,0,114,101,99,116,121,0,99,
+117,114,121,0,109,111,100,101,108,116,121,112,101,0,115,99,114,105,112,116,
+98,108,111,99,107,0,112,97,100,51,91,55,93,0,42,97,110,105,109,95,
+108,105,110,107,101,100,95,115,105,112,111,0,42,102,105,108,101,108,105,115,
+116,0,116,111,116,102,105,108,101,0,116,105,116,108,101,91,50,52,93,0,
+100,105,114,91,49,54,48,93,0,102,105,108,101,91,56,48,93,0,111,102,
+115,0,115,111,114,116,0,109,97,120,110,97,109,101,108,101,110,0,99,111,
+108,108,117,109,115,0,42,108,105,98,102,105,108,101,100,97,116,97,0,114,
+101,116,118,97,108,0,109,101,110,117,0,97,99,116,0,40,42,114,101,116,
+117,114,110,102,117,110,99,41,40,41,0,42,109,101,110,117,112,0,111,111,
+112,115,0,118,105,115,105,102,108,97,103,0,42,105,109,97,103,101,0,105,
+109,97,110,114,0,99,117,114,116,105,108,101,0,42,116,101,120,116,0,116,
+111,112,0,118,105,101,119,108,105,110,101,115,0,102,111,110,116,95,105,100,
+0,108,104,101,105,103,104,116,0,108,101,102,116,0,112,105,120,95,112,101,
+114,95,108,105,110,101,0,116,120,116,115,99,114,111,108,108,0,116,120,116,
+98,97,114,0,42,112,121,95,100,114,97,119,0,42,112,121,95,101,118,101,
+110,116,0,42,112,121,95,98,117,116,116,111,110,0,42,112,121,95,103,108,
+111,98,97,108,100,105,99,116,0,116,105,116,108,101,91,50,56,93,0,102,
+97,115,101,0,115,117,98,102,97,115,101,0,109,111,117,115,101,95,109,111,
+118,101,95,114,101,100,114,97,119,0,105,109,97,102,97,115,101,0,100,105,
+114,115,108,105,0,100,105,114,115,108,105,95,108,105,110,101,115,0,100,105,
+114,115,108,105,95,115,120,0,100,105,114,115,108,105,95,101,121,0,100,105,
+114,115,108,105,95,101,120,0,100,105,114,115,108,105,95,104,0,105,109,97,
+115,108,105,0,102,105,108,101,115,101,108,109,101,110,117,105,116,101,109,0,
+105,109,97,115,108,105,95,115,120,0,105,109,97,115,108,105,95,101,121,0,
+105,109,97,115,108,105,95,101,120,0,105,109,97,115,108,105,95,104,0,100,
+115,115,120,0,100,115,115,121,0,100,115,101,120,0,100,115,101,121,0,100,
+101,115,120,0,100,101,115,121,0,100,101,101,120,0,100,101,101,121,0,102,
+115,115,120,0,102,115,115,121,0,102,115,101,120,0,102,115,101,121,0,100,
+115,100,104,0,102,115,100,104,0,102,101,115,120,0,102,101,115,121,0,102,
+101,101,120,0,102,101,101,121,0,105,110,102,115,120,0,105,110,102,115,121,
+0,105,110,102,101,120,0,105,110,102,101,121,0,100,110,115,120,0,100,110,
+115,121,0,100,110,119,0,100,110,104,0,102,110,115,120,0,102,110,115,121,
+0,102,110,119,0,102,110,104,0,102,111,108,101,91,49,50,56,93,0,100,
+111,114,91,49,50,56,93,0,102,105,108,101,91,49,50,56,93,0,100,105,
+114,91,49,50,56,93,0,42,102,105,114,115,116,100,105,114,0,42,102,105,
+114,115,116,102,105,108,101,0,116,111,112,100,105,114,0,116,111,116,97,108,
+100,105,114,115,0,104,105,108,105,116,101,0,116,111,112,102,105,108,101,0,
+116,111,116,97,108,102,105,108,101,115,0,105,109,97,103,101,95,115,108,105,
+100,101,114,0,115,108,105,100,101,114,95,104,101,105,103,104,116,0,115,108,
+105,100,101,114,95,115,112,97,99,101,0,116,111,112,105,109,97,0,116,111,
+116,97,108,105,109,97,0,99,117,114,105,109,97,120,0,99,117,114,105,109,
+97,121,0,42,102,105,114,115,116,95,115,101,108,95,105,109,97,0,42,104,
+105,108,105,116,101,95,105,109,97,0,116,111,116,97,108,95,115,101,108,101,
+99,116,101,100,0,105,109,97,95,114,101,100,114,97,119,0,42,99,109,97,
+112,0,42,97,114,103,49,0,100,117,112,102,108,97,103,0,115,97,118,101,
+116,105,109,101,0,116,101,109,112,100,105,114,91,54,52,93,0,102,111,110,
+116,100,105,114,91,54,52,93,0,114,101,110,100,101,114,100,105,114,91,54,
+52,93,0,116,101,120,116,117,100,105,114,91,54,52,93,0,112,108,117,103,
+116,101,120,100,105,114,91,54,52,93,0,112,108,117,103,115,101,113,100,105,
+114,91,54,52,93,0,112,121,116,104,111,110,100,105,114,91,54,52,93,0,
+115,111,117,110,100,100,105,114,91,54,52,93,0,118,101,114,115,105,111,110,
+115,0,118,114,109,108,102,108,97,103,0,103,97,109,101,102,108,97,103,115,
+0,118,101,114,116,98,97,115,101,0,101,100,103,101,98,97,115,101,0,97,
+114,101,97,98,97,115,101,0,42,115,99,101,110,101,0,115,116,97,114,116,
+120,0,101,110,100,120,0,115,116,97,114,116,121,0,101,110,100,121,0,115,
+105,122,101,120,0,115,105,122,101,121,0,115,99,101,110,101,110,114,0,115,
+99,114,101,101,110,110,114,0,102,117,108,108,0,109,97,105,110,119,105,110,
+0,119,105,110,97,107,116,0,42,110,101,119,118,0,118,101,99,0,42,118,
+49,0,42,118,50,0,42,118,51,0,42,118,52,0,42,102,117,108,108,0,
+119,105,110,109,97,116,91,52,93,91,52,93,0,104,101,97,100,114,99,116,
+0,119,105,110,114,99,116,0,104,101,97,100,119,105,110,0,119,105,110,0,
+104,101,97,100,101,114,116,121,112,101,0,98,117,116,115,112,97,99,101,116,
+121,112,101,0,119,105,110,120,0,119,105,110,121,0,104,101,97,100,95,115,
+119,97,112,0,104,101,97,100,95,101,113,117,97,108,0,119,105,110,95,115,
+119,97,112,0,119,105,110,95,101,113,117,97,108,0,104,101,97,100,98,117,
+116,108,101,110,0,104,101,97,100,98,117,116,111,102,115,0,99,117,114,115,
+111,114,0,115,112,97,99,101,100,97,116,97,0,117,105,98,108,111,99,107,
+115,0,42,99,117,114,115,99,114,101,101,110,0,100,105,115,112,108,97,121,
+109,111,100,101,0,102,105,108,101,102,108,97,103,115,0,110,97,109,101,91,
+52,48,93,0,42,115,101,49,0,42,115,101,50,0,42,115,101,51,0,110,
+114,0,100,111,110,101,0,42,115,116,114,105,112,100,97,116,97,0,100,105,
+114,91,56,48,93,0,111,114,120,0,111,114,121,0,110,97,109,101,91,56,
+48,93,0,42,110,101,119,115,101,113,0,115,116,97,114,116,0,115,116,97,
+114,116,111,102,115,0,101,110,100,111,102,115,0,115,116,97,114,116,115,116,
+105,108,108,0,101,110,100,115,116,105,108,108,0,109,97,99,104,105,110,101,
+0,115,116,97,114,116,100,105,115,112,0,101,110,100,100,105,115,112,0,109,
+117,108,0,104,97,110,100,115,105,122,101,0,42,115,116,114,105,112,0,42,
+99,117,114,101,108,101,109,0,102,97,99,102,48,0,102,97,99,102,49,0,
+42,115,101,113,49,0,42,115,101,113,50,0,42,115,101,113,51,0,115,101,
+113,98,97,115,101,0,42,115,101,113,98,97,115,101,112,0,109,101,116,97,
+115,116,97,99,107,0,98,117,116,116,121,112,101,0,115,116,97,0,101,110,
+100,0,108,105,102,101,116,105,109,101,0,116,111,116,112,97,114,116,0,115,
+101,101,100,0,110,111,114,109,102,97,99,0,111,98,102,97,99,0,114,97,
+110,100,102,97,99,0,116,101,120,102,97,99,0,114,97,110,100,108,105,102,
+101,0,102,111,114,99,101,91,51,93,0,100,97,109,112,0,110,97,98,108,
+97,0,118,101,99,116,115,105,122,101,0,100,101,102,118,101,99,91,51,93,
+0,109,117,108,116,91,52,93,0,108,105,102,101,91,52,93,0,99,104,105,
+108,100,91,52,93,0,109,97,116,91,52,93,0,116,101,120,109,97,112,0,
+99,117,114,109,117,108,116,0,115,116,97,116,105,99,115,116,101,112,0,42,
+107,101,121,115,0,104,101,105,103,104,116,0,110,97,114,114,111,119,0,115,
+112,101,101,100,0,109,105,110,102,97,99,0,116,105,109,101,111,102,102,115,
+0,42,111,98,0,112,114,101,109,97,116,91,52,93,91,52,93,0,112,111,
+115,116,109,97,116,91,52,93,91,52,93,0,118,101,99,91,51,93,0,102,
+97,99,0,108,101,110,111,0,97,108,112,104,97,111,0,101,102,102,91,50,
+93,0,105,116,101,114,0,108,97,115,116,102,114,97,0,108,105,109,98,98,
+97,115,101,0,101,102,102,91,51,93,0,101,102,102,103,91,51,93,0,101,
+102,102,110,91,51,93,0,109,101,109,0,115,108,111,119,0,116,111,116,121,
+0,116,111,116,120,0,120,121,99,111,110,115,116,114,97,105,110,116,0,116,
+111,116,100,101,102,0,100,101,102,95,115,99,114,111,108,108,0,108,105,109,
+98,95,115,99,114,111,108,108,0,100,120,0,100,121,0,42,105,100,0,108,
+105,110,107,0,111,116,121,112,101,0,100,97,116,97,0,111,108,100,0,42,
+112,111,105,110,0,42,111,108,100,112,111,105,110,0,114,101,115,101,116,100,
+105,115,116,0,108,97,115,116,118,97,108,0,42,109,97,0,107,101,121,0,
+113,117,97,108,0,113,117,97,108,50,0,116,97,114,103,101,116,78,97,109,
+101,91,51,50,93,0,116,111,103,103,108,101,78,97,109,101,91,51,50,93,
+0,118,97,108,117,101,91,51,50,93,0,109,97,120,118,97,108,117,101,91,
+51,50,93,0,109,97,116,101,114,105,97,108,78,97,109,101,91,51,50,93,
+0,100,97,109,112,116,105,109,101,114,0,97,110,103,108,101,0,114,97,110,
+103,101,0,97,120,105,115,0,100,101,108,97,121,0,112,114,111,112,110,97,
+109,101,91,51,50,93,0,109,97,116,110,97,109,101,91,51,50,93,0,97,
+120,105,115,102,108,97,103,0,42,102,114,111,109,79,98,106,101,99,116,0,
+115,117,98,106,101,99,116,91,51,50,93,0,98,111,100,121,91,51,50,93,
+0,112,117,108,115,101,0,102,114,101,113,0,116,111,116,108,105,110,107,115,
+0,42,42,108,105,110,107,115,0,105,110,118,101,114,116,0,102,114,101,113,
+50,0,115,116,114,91,49,50,56,93,0,42,109,121,110,101,119,0,105,110,
+112,117,116,115,0,116,111,116,115,108,105,110,107,115,0,42,42,115,108,105,
+110,107,115,0,118,97,108,0,118,97,108,111,0,112,97,100,53,0,116,105,
+109,101,0,42,97,99,116,0,98,108,101,110,100,105,110,0,112,114,105,111,
+114,105,116,121,0,115,116,114,105,100,101,108,101,110,103,116,104,0,115,116,
+114,105,100,101,97,120,105,115,0,115,110,100,110,114,0,42,115,111,117,110,
+100,0,109,97,107,101,99,111,112,121,0,99,111,112,121,109,97,100,101,0,
+112,97,100,91,49,93,0,116,114,97,99,107,0,118,111,108,117,109,101,0,
+42,109,101,0,108,105,110,86,101,108,111,99,105,116,121,91,51,93,0,108,
+111,99,97,108,102,108,97,103,0,102,111,114,99,101,108,111,99,91,51,93,
+0,102,111,114,99,101,114,111,116,91,51,93,0,108,105,110,101,97,114,118,
+101,108,111,99,105,116,121,91,51,93,0,97,110,103,117,108,97,114,118,101,
+108,111,99,105,116,121,91,51,93,0,97,100,100,101,100,108,105,110,101,97,
+114,118,101,108,111,99,105,116,121,91,51,93,0,97,110,111,116,104,101,114,
+112,97,100,91,52,93,0,98,117,116,115,116,97,0,98,117,116,101,110,100,
+0,109,105,110,0,109,97,120,0,118,105,115,105,102,97,99,0,109,105,110,
+108,111,99,91,51,93,0,109,97,120,108,111,99,91,51,93,0,109,105,110,
+114,111,116,91,51,93,0,109,97,120,114,111,116,91,51,93,0,100,105,115,
+116,114,105,98,117,116,105,111,110,0,105,110,116,95,97,114,103,95,49,0,
+105,110,116,95,97,114,103,95,50,0,102,108,111,97,116,95,97,114,103,95,
+49,0,102,108,111,97,116,95,97,114,103,95,50,0,116,111,80,114,111,112,
+78,97,109,101,91,51,50,93,0,42,116,111,79,98,106,101,99,116,0,98,
+111,100,121,84,121,112,101,0,102,105,108,101,110,97,109,101,91,54,52,93,
+0,108,111,97,100,97,110,105,110,97,109,101,91,54,52,93,0,103,111,0,
+97,99,99,101,108,108,101,114,97,116,105,111,110,0,109,97,120,115,112,101,
+101,100,0,109,97,120,114,111,116,115,112,101,101,100,0,109,97,120,116,105,
+108,116,115,112,101,101,100,0,114,111,116,100,97,109,112,0,116,105,108,116,
+100,97,109,112,0,115,112,101,101,100,100,97,109,112,0,42,115,97,109,112,
+108,101,0,42,110,101,119,112,97,99,107,101,100,102,105,108,101,0,42,115,
+110,100,95,115,111,117,110,100,0,112,97,110,110,105,110,103,0,97,116,116,
+101,110,117,97,116,105,111,110,0,112,105,116,99,104,0,109,105,110,95,103,
+97,105,110,0,109,97,120,95,103,97,105,110,0,100,105,115,116,97,110,99,
+101,0,108,111,111,112,115,116,97,114,116,0,108,111,111,112,101,110,100,0,
+99,104,97,110,110,101,108,115,0,104,105,103,104,112,114,105,111,0,112,97,
+100,91,54,93,0,103,97,105,110,0,100,111,112,112,108,101,114,102,97,99,
+116,111,114,0,100,111,112,112,108,101,114,118,101,108,111,99,105,116,121,0,
+110,117,109,115,111,117,110,100,115,98,108,101,110,100,101,114,0,110,117,109,
+115,111,117,110,100,115,103,97,109,101,101,110,103,105,110,101,0,42,103,107,
+101,121,0,112,97,100,102,0,111,107,101,121,0,103,111,98,106,101,99,116,
+0,103,107,101,121,0,42,97,99,116,105,118,101,0,99,104,105,108,100,98,
+97,115,101,0,114,111,108,108,0,104,101,97,100,91,51,93,0,116,97,105,
+108,91,51,93,0,112,97,114,109,97,116,91,52,93,91,52,93,0,100,101,
+102,109,97,116,91,52,93,91,52,93,0,105,114,101,115,116,109,97,116,91,
+52,93,91,52,93,0,112,111,115,101,109,97,116,91,52,93,91,52,93,0,
+98,111,110,101,98,97,115,101,0,99,104,97,105,110,98,97,115,101,0,114,
+101,115,49,0,114,101,115,50,0,114,101,115,51,0,99,104,97,110,98,97,
+115,101,0,42,97,99,104,97,110,0,42,112,99,104,97,110,0,97,99,116,
+110,114,0,110,97,109,101,91,51,48,93,0,101,110,102,111,114,99,101,0,
+111,102,102,115,101,116,91,51,93,0,111,114,105,101,110,116,91,51,93,0,
+114,111,108,108,91,51,93,0,42,116,97,114,0,116,111,108,101,114,97,110,
+99,101,0,105,116,101,114,97,116,105,111,110,115,0,115,117,98,116,97,114,
+103,101,116,91,51,50,93,0,99,97,99,104,101,101,102,102,91,51,93,0,
+99,97,99,104,101,109,97,116,91,52,93,91,52,93,0,122,109,105,110,0,
+122,109,97,120,0,97,99,116,115,116,97,114,116,0,97,99,116,101,110,100,
+0,115,116,114,105,100,101,108,101,110,0,114,101,112,101,97,116,0,98,108,
+101,110,100,111,117,116,0,0,84,89,80,69,174,0,0,0,99,104,97,114,
+0,117,99,104,97,114,0,115,104,111,114,116,0,117,115,104,111,114,116,0,
+105,110,116,0,108,111,110,103,0,117,108,111,110,103,0,102,108,111,97,116,
+0,100,111,117,98,108,101,0,118,111,105,100,0,76,105,110,107,0,76,105,
+115,116,66,97,115,101,0,118,101,99,50,115,0,118,101,99,50,105,0,118,
+101,99,50,102,0,118,101,99,50,100,0,118,101,99,51,105,0,118,101,99,
+51,102,0,118,101,99,51,100,0,118,101,99,52,105,0,118,101,99,52,102,
+0,118,101,99,52,100,0,114,99,116,105,0,114,99,116,102,0,73,68,0,
+76,105,98,114,97,114,121,0,70,105,108,101,68,97,116,97,0,73,112,111,
+0,75,101,121,66,108,111,99,107,0,75,101,121,0,83,99,114,105,112,116,
+76,105,110,107,0,84,101,120,116,76,105,110,101,0,84,101,120,116,0,80,
+97,99,107,101,100,70,105,108,101,0,67,97,109,101,114,97,0,73,109,97,
+103,101,0,97,110,105,109,0,73,109,66,117,102,0,77,84,101,120,0,79,
+98,106,101,99,116,0,84,101,120,0,80,108,117,103,105,110,84,101,120,0,
+67,66,68,97,116,97,0,67,111,108,111,114,66,97,110,100,0,69,110,118,
+77,97,112,0,76,97,109,112,0,87,97,118,101,0,77,97,116,101,114,105,
+97,108,0,86,70,111,110,116,0,86,70,111,110,116,68,97,116,97,0,77,
+101,116,97,69,108,101,109,0,77,101,116,97,66,97,108,108,0,66,111,117,
+110,100,66,111,120,0,66,101,122,84,114,105,112,108,101,0,66,80,111,105,
+110,116,0,78,117,114,98,0,67,117,114,118,101,0,80,97,116,104,0,73,
+112,111,67,117,114,118,101,0,77,70,97,99,101,0,77,70,97,99,101,73,
+110,116,0,84,70,97,99,101,0,77,68,101,102,111,114,109,87,101,105,103,
+104,116,0,66,111,110,101,0,77,68,101,102,111,114,109,86,101,114,116,0,
+77,86,101,114,116,0,77,67,111,108,0,77,83,116,105,99,107,121,0,77,
+101,115,104,0,79,99,73,110,102,111,0,76,97,116,116,105,99,101,0,98,
+68,101,102,111,114,109,71,114,111,117,112,0,98,65,99,116,105,111,110,0,
+98,80,111,115,101,0,98,67,111,110,115,116,114,97,105,110,116,67,104,97,
+110,110,101,108,0,87,111,114,108,100,0,82,97,100,105,111,0,66,97,115,
+101,0,65,118,105,67,111,100,101,99,68,97,116,97,0,82,101,110,100,101,
+114,68,97,116,97,0,71,97,109,101,70,114,97,109,105,110,103,0,83,99,
+101,110,101,0,71,114,111,117,112,0,70,114,101,101,67,97,109,101,114,97,
+0,66,71,112,105,99,0,86,105,101,119,51,68,0,83,112,97,99,101,76,
+105,110,107,0,83,99,114,65,114,101,97,0,86,105,101,119,50,68,0,83,
+112,97,99,101,73,110,102,111,0,83,112,97,99,101,73,112,111,0,83,112,
+97,99,101,66,117,116,115,0,83,112,97,99,101,83,101,113,0,83,112,97,
+99,101,70,105,108,101,0,100,105,114,101,110,116,114,121,0,66,108,101,110,
+100,72,97,110,100,108,101,0,83,112,97,99,101,79,111,112,115,0,83,112,
+97,99,101,73,109,97,103,101,0,83,112,97,99,101,78,108,97,0,83,112,
+97,99,101,84,101,120,116,0,83,112,97,99,101,73,109,97,83,101,108,0,
+73,109,97,68,105,114,0,79,110,101,83,101,108,101,99,116,97,98,108,101,
+73,109,97,0,85,115,101,114,68,101,102,0,98,83,99,114,101,101,110,0,
+83,99,114,86,101,114,116,0,83,99,114,69,100,103,101,0,70,105,108,101,
+71,108,111,98,97,108,0,83,116,114,105,112,69,108,101,109,0,83,116,114,
+105,112,0,80,108,117,103,105,110,83,101,113,0,83,101,113,117,101,110,99,
+101,0,69,100,105,116,105,110,103,0,69,102,102,101,99,116,0,66,117,105,
+108,100,69,102,102,0,80,97,114,116,69,102,102,0,80,97,114,116,105,99,
+108,101,0,87,97,118,101,69,102,102,0,68,101,102,111,114,109,0,76,105,
+109,98,0,73,107,97,0,79,111,112,115,0,98,80,114,111,112,101,114,116,
+121,0,98,78,101,97,114,83,101,110,115,111,114,0,98,77,111,117,115,101,
+83,101,110,115,111,114,0,98,84,111,117,99,104,83,101,110,115,111,114,0,
+98,75,101,121,98,111,97,114,100,83,101,110,115,111,114,0,98,80,114,111,
+112,101,114,116,121,83,101,110,115,111,114,0,98,67,111,108,108,105,115,105,
+111,110,83,101,110,115,111,114,0,98,82,97,100,97,114,83,101,110,115,111,
+114,0,98,82,97,110,100,111,109,83,101,110,115,111,114,0,98,82,97,121,
+83,101,110,115,111,114,0,98,77,101,115,115,97,103,101,83,101,110,115,111,
+114,0,98,83,101,110,115,111,114,0,98,67,111,110,116,114,111,108,108,101,
+114,0,98,69,120,112,114,101,115,115,105,111,110,67,111,110,116,0,98,80,
+121,116,104,111,110,67,111,110,116,0,98,65,99,116,117,97,116,111,114,0,
+98,65,100,100,79,98,106,101,99,116,65,99,116,117,97,116,111,114,0,98,
+65,99,116,105,111,110,65,99,116,117,97,116,111,114,0,98,83,111,117,110,
+100,65,99,116,117,97,116,111,114,0,98,83,111,117,110,100,0,98,67,68,
+65,99,116,117,97,116,111,114,0,98,69,100,105,116,79,98,106,101,99,116,
+65,99,116,117,97,116,111,114,0,98,83,99,101,110,101,65,99,116,117,97,
+116,111,114,0,98,80,114,111,112,101,114,116,121,65,99,116,117,97,116,111,
+114,0,98,79,98,106,101,99,116,65,99,116,117,97,116,111,114,0,98,73,
+112,111,65,99,116,117,97,116,111,114,0,98,67,97,109,101,114,97,65,99,
+116,117,97,116,111,114,0,98,67,111,110,115,116,114,97,105,110,116,65,99,
+116,117,97,116,111,114,0,98,71,114,111,117,112,65,99,116,117,97,116,111,
+114,0,98,82,97,110,100,111,109,65,99,116,117,97,116,111,114,0,98,77,
+101,115,115,97,103,101,65,99,116,117,97,116,111,114,0,98,71,97,109,101,
+65,99,116,117,97,116,111,114,0,98,86,105,115,105,98,105,108,105,116,121,
+65,99,116,117,97,116,111,114,0,98,83,97,109,112,108,101,0,98,83,111,
+117,110,100,76,105,115,116,101,110,101,114,0,83,112,97,99,101,83,111,117,
+110,100,0,71,114,111,117,112,75,101,121,0,79,98,106,101,99,116,75,101,
+121,0,71,114,111,117,112,79,98,106,101,99,116,0,98,65,114,109,97,116,
+117,114,101,0,98,80,111,115,101,67,104,97,110,110,101,108,0,98,65,99,
+116,105,111,110,67,104,97,110,110,101,108,0,83,112,97,99,101,65,99,116,
+105,111,110,0,98,67,111,110,115,116,114,97,105,110,116,0,98,75,105,110,
+101,109,97,116,105,99,67,111,110,115,116,114,97,105,110,116,0,98,84,114,
+97,99,107,84,111,67,111,110,115,116,114,97,105,110,116,0,98,82,111,116,
+97,116,101,76,105,107,101,67,111,110,115,116,114,97,105,110,116,0,98,76,
+111,99,97,116,101,76,105,107,101,67,111,110,115,116,114,97,105,110,116,0,
+98,65,99,116,105,111,110,67,111,110,115,116,114,97,105,110,116,0,98,70,
+111,108,108,111,119,80,97,116,104,67,111,110,115,116,114,97,105,110,116,0,
+98,82,111,116,97,116,105,111,110,67,111,110,115,116,114,97,105,110,116,0,
+98,65,99,116,105,111,110,83,116,114,105,112,0,0,0,0,84,76,69,78,
+1,0,1,0,2,0,2,0,4,0,4,0,4,0,4,0,8,0,0,0,
+8,0,8,0,4,0,8,0,8,0,16,0,12,0,12,0,24,0,16,0,
+16,0,32,0,16,0,16,0,48,0,224,0,0,0,80,0,28,0,116,0,
+16,0,20,0,100,0,20,0,108,0,40,1,0,0,0,0,80,0,168,2,
+168,0,80,1,24,0,136,1,120,0,180,0,52,0,16,1,64,1,0,0,
+72,0,132,0,0,0,60,0,28,0,48,0,232,0,0,0,80,0,12,0,
+20,0,60,0,12,0,236,1,12,0,20,0,4,0,8,0,196,0,0,0,
+76,0,44,0,64,0,8,0,44,0,236,0,40,0,28,0,48,0,132,2,
+16,0,20,3,68,0,40,0,36,0,136,1,20,0,180,0,112,0,20,0,
+200,0,184,0,140,0,68,1,0,0,0,0,152,0,160,0,132,0,104,0,
+224,2,0,0,0,0,20,2,100,0,20,0,24,0,12,0,64,0,108,0,
+240,0,148,0,28,0,16,0,24,0,156,0,0,0,56,0,236,0,40,0,
+156,0,44,0,64,0,48,0,8,0,44,0,72,0,104,0,72,0,44,0,
+40,0,108,0,68,0,76,0,80,0,128,0,4,0,60,0,12,0,60,0,
+20,0,20,1,16,0,64,0,16,0,76,0,120,0,48,0,28,0,56,0,
+52,0,56,0,108,0,136,0,4,0,0,0,64,0,152,0,48,0,112,1,
+20,0,80,0,160,0,60,0,152,0,96,0,124,0,44,0,44,0,44,0,
+56,0,4,0,24,0,56,0,83,84,82,67,151,0,0,0,10,0,2,0,
+10,0,0,0,10,0,1,0,11,0,2,0,9,0,2,0,9,0,3,0,
+12,0,2,0,2,0,4,0,2,0,5,0,13,0,2,0,4,0,4,0,
+4,0,5,0,14,0,2,0,7,0,4,0,7,0,5,0,15,0,2,0,
+8,0,4,0,8,0,5,0,16,0,3,0,4,0,4,0,4,0,5,0,
+4,0,6,0,17,0,3,0,7,0,4,0,7,0,5,0,7,0,6,0,
+18,0,3,0,8,0,4,0,8,0,5,0,8,0,6,0,19,0,4,0,
+4,0,4,0,4,0,5,0,4,0,6,0,4,0,7,0,20,0,4,0,
+7,0,4,0,7,0,5,0,7,0,6,0,7,0,7,0,21,0,4,0,
+8,0,4,0,8,0,5,0,8,0,6,0,8,0,7,0,22,0,4,0,
+4,0,8,0,4,0,9,0,4,0,10,0,4,0,11,0,23,0,4,0,
+7,0,8,0,7,0,9,0,7,0,10,0,7,0,11,0,24,0,8,0,
+9,0,0,0,9,0,1,0,24,0,12,0,25,0,13,0,0,0,14,0,
+2,0,15,0,2,0,16,0,4,0,17,0,25,0,6,0,24,0,18,0,
+24,0,19,0,26,0,20,0,0,0,21,0,4,0,22,0,4,0,17,0,
+27,0,6,0,24,0,18,0,11,0,23,0,23,0,24,0,2,0,25,0,
+2,0,26,0,4,0,17,0,28,0,9,0,28,0,0,0,28,0,1,0,
+7,0,27,0,2,0,16,0,2,0,28,0,2,0,29,0,2,0,30,0,
+4,0,17,0,9,0,31,0,29,0,12,0,24,0,18,0,28,0,32,0,
+0,0,33,0,4,0,34,0,7,0,35,0,11,0,36,0,27,0,37,0,
+24,0,38,0,2,0,29,0,2,0,39,0,2,0,40,0,2,0,41,0,
+30,0,5,0,24,0,42,0,2,0,43,0,2,0,44,0,2,0,45,0,
+4,0,17,0,31,0,5,0,31,0,0,0,31,0,1,0,0,0,46,0,
+4,0,47,0,4,0,48,0,32,0,13,0,24,0,18,0,0,0,49,0,
+4,0,50,0,4,0,51,0,11,0,52,0,31,0,53,0,31,0,54,0,
+4,0,55,0,4,0,56,0,0,0,57,0,4,0,58,0,4,0,59,0,
+9,0,60,0,33,0,5,0,4,0,61,0,4,0,62,0,4,0,50,0,
+4,0,17,0,9,0,31,0,34,0,15,0,24,0,18,0,2,0,29,0,
+2,0,16,0,2,0,63,0,2,0,64,0,7,0,65,0,7,0,66,0,
+7,0,67,0,7,0,68,0,7,0,69,0,7,0,70,0,7,0,71,0,
+7,0,72,0,27,0,37,0,30,0,73,0,35,0,21,0,24,0,18,0,
+0,0,21,0,36,0,74,0,37,0,75,0,37,0,76,0,2,0,77,0,
+2,0,16,0,2,0,78,0,2,0,79,0,2,0,80,0,2,0,81,0,
+2,0,82,0,2,0,83,0,2,0,84,0,2,0,85,0,4,0,86,0,
+4,0,87,0,33,0,88,0,7,0,89,0,2,0,90,0,2,0,91,0,
+38,0,22,0,2,0,92,0,2,0,93,0,2,0,94,0,2,0,95,0,
+39,0,96,0,40,0,97,0,0,0,98,0,0,0,99,0,0,0,100,0,
+0,0,101,0,7,0,102,0,7,0,103,0,2,0,104,0,2,0,105,0,
+7,0,106,0,7,0,107,0,7,0,108,0,7,0,109,0,7,0,110,0,
+7,0,111,0,7,0,112,0,7,0,113,0,41,0,14,0,0,0,21,0,
+9,0,114,0,0,0,115,0,0,0,116,0,4,0,117,0,4,0,118,0,
+9,0,119,0,7,0,120,0,7,0,121,0,7,0,122,0,4,0,123,0,
+9,0,124,0,4,0,125,0,4,0,17,0,42,0,6,0,7,0,106,0,
+7,0,107,0,7,0,108,0,7,0,126,0,7,0,27,0,4,0,24,0,
+43,0,5,0,2,0,16,0,2,0,22,0,2,0,24,0,2,0,127,0,
+42,0,128,0,44,0,12,0,39,0,96,0,35,0,129,0,35,0,130,0,
+7,0,131,0,2,0,29,0,2,0,132,0,7,0,65,0,7,0,66,0,
+4,0,133,0,4,0,134,0,2,0,77,0,2,0,78,0,40,0,35,0,
+24,0,18,0,7,0,135,0,7,0,136,0,7,0,137,0,7,0,138,0,
+7,0,139,0,7,0,140,0,7,0,141,0,7,0,142,0,2,0,143,0,
+2,0,144,0,2,0,145,0,2,0,16,0,2,0,29,0,2,0,132,0,
+7,0,146,0,7,0,147,0,7,0,148,0,7,0,149,0,2,0,150,0,
+2,0,151,0,2,0,152,0,2,0,47,0,2,0,153,0,2,0,154,0,
+2,0,155,0,2,0,156,0,7,0,112,0,7,0,157,0,27,0,37,0,
+35,0,129,0,41,0,158,0,43,0,159,0,44,0,160,0,2,0,161,0,
+45,0,28,0,24,0,18,0,2,0,29,0,2,0,162,0,2,0,105,0,
+2,0,163,0,7,0,106,0,7,0,107,0,7,0,108,0,7,0,109,0,
+7,0,164,0,7,0,165,0,7,0,166,0,7,0,167,0,7,0,168,0,
+7,0,169,0,7,0,170,0,2,0,171,0,2,0,172,0,7,0,65,0,
+7,0,66,0,7,0,173,0,7,0,174,0,7,0,175,0,2,0,176,0,
+2,0,177,0,38,0,178,0,27,0,37,0,30,0,73,0,46,0,2,0,
+24,0,18,0,27,0,37,0,47,0,58,0,24,0,18,0,2,0,105,0,
+2,0,179,0,7,0,106,0,7,0,107,0,7,0,108,0,7,0,180,0,
+7,0,181,0,7,0,182,0,7,0,183,0,7,0,184,0,7,0,185,0,
+7,0,186,0,7,0,187,0,7,0,188,0,7,0,189,0,7,0,190,0,
+7,0,191,0,7,0,192,0,7,0,193,0,7,0,194,0,7,0,195,0,
+7,0,196,0,7,0,197,0,7,0,198,0,2,0,199,0,0,0,200,0,
+0,0,201,0,4,0,162,0,4,0,202,0,2,0,203,0,2,0,204,0,
+2,0,205,0,2,0,206,0,7,0,207,0,7,0,208,0,7,0,209,0,
+7,0,210,0,0,0,211,0,0,0,176,0,0,0,212,0,0,0,213,0,
+2,0,214,0,2,0,215,0,4,0,216,0,2,0,92,0,2,0,93,0,
+38,0,178,0,27,0,37,0,47,0,217,0,7,0,218,0,7,0,219,0,
+7,0,220,0,7,0,221,0,7,0,222,0,2,0,223,0,2,0,17,0,
+30,0,73,0,48,0,6,0,24,0,18,0,0,0,224,0,7,0,225,0,
+7,0,17,0,49,0,31,0,33,0,88,0,50,0,20,0,50,0,0,0,
+50,0,1,0,2,0,29,0,2,0,179,0,2,0,16,0,2,0,226,0,
+7,0,4,0,7,0,5,0,7,0,6,0,7,0,227,0,7,0,228,0,
+7,0,229,0,7,0,230,0,7,0,231,0,7,0,232,0,7,0,47,0,
+7,0,233,0,4,0,17,0,7,0,234,0,7,0,235,0,51,0,15,0,
+24,0,18,0,52,0,236,0,11,0,237,0,11,0,238,0,27,0,37,0,
+47,0,239,0,2,0,16,0,2,0,240,0,4,0,104,0,7,0,241,0,
+7,0,103,0,7,0,242,0,7,0,243,0,7,0,244,0,7,0,245,0,
+53,0,9,0,7,0,246,0,7,0,247,0,2,0,248,0,2,0,249,0,
+2,0,250,0,0,0,251,0,0,0,252,0,0,0,253,0,0,0,254,0,
+54,0,5,0,7,0,255,0,7,0,247,0,2,0,0,1,2,0,251,0,
+2,0,254,0,55,0,18,0,55,0,0,0,55,0,1,0,2,0,29,0,
+2,0,1,1,2,0,254,0,2,0,16,0,2,0,2,1,2,0,3,1,
+2,0,4,1,2,0,5,1,2,0,6,1,2,0,7,1,2,0,8,1,
+2,0,9,1,7,0,10,1,7,0,11,1,54,0,12,1,53,0,13,1,
+56,0,38,0,24,0,18,0,52,0,236,0,11,0,14,1,11,0,238,0,
+39,0,15,1,39,0,16,1,27,0,37,0,57,0,17,1,29,0,18,1,
+47,0,239,0,11,0,19,1,7,0,20,1,7,0,241,0,7,0,103,0,
+7,0,242,0,4,0,104,0,2,0,21,1,2,0,240,0,2,0,16,0,
+2,0,22,1,7,0,23,1,7,0,24,1,7,0,25,1,2,0,4,1,
+2,0,5,1,2,0,47,0,2,0,52,0,2,0,27,0,2,0,26,1,
+7,0,27,1,7,0,28,1,7,0,29,1,7,0,30,1,7,0,31,1,
+7,0,32,1,0,0,33,1,0,0,34,1,48,0,35,1,58,0,18,0,
+58,0,0,0,58,0,1,0,54,0,12,1,53,0,13,1,23,0,36,1,
+23,0,37,1,2,0,25,0,2,0,38,1,2,0,39,1,2,0,40,1,
+2,0,41,1,2,0,42,1,2,0,16,0,2,0,30,0,7,0,10,0,
+7,0,11,0,4,0,43,1,7,0,35,0,59,0,8,0,3,0,44,1,
+3,0,45,1,3,0,46,1,3,0,47,1,0,0,48,1,0,0,1,1,
+0,0,49,1,0,0,16,0,60,0,8,0,4,0,44,1,4,0,45,1,
+4,0,46,1,4,0,47,1,0,0,48,1,0,0,1,1,0,0,49,1,
+0,0,16,0,61,0,8,0,9,0,50,1,7,0,51,1,4,0,52,1,
+0,0,16,0,0,0,53,1,2,0,162,0,2,0,54,1,2,0,17,0,
+62,0,3,0,4,0,55,1,7,0,56,1,63,0,31,0,64,0,3,0,
+62,0,57,1,4,0,58,1,4,0,91,0,65,0,4,0,7,0,59,1,
+2,0,60,1,0,0,16,0,0,0,1,1,66,0,4,0,0,0,126,0,
+0,0,106,0,0,0,107,0,0,0,108,0,67,0,1,0,7,0,61,1,
+68,0,34,0,24,0,18,0,52,0,236,0,11,0,62,1,11,0,238,0,
+27,0,37,0,29,0,18,1,47,0,239,0,9,0,63,1,9,0,64,1,
+9,0,65,1,65,0,66,1,64,0,67,1,66,0,68,1,67,0,69,1,
+68,0,70,1,7,0,20,1,69,0,71,1,9,0,72,1,4,0,40,1,
+4,0,73,1,4,0,104,0,7,0,241,0,7,0,103,0,7,0,242,0,
+2,0,74,1,2,0,16,0,2,0,75,1,2,0,76,1,2,0,240,0,
+2,0,91,0,2,0,77,1,2,0,78,1,7,0,79,1,7,0,80,1,
+70,0,13,0,24,0,18,0,2,0,2,1,2,0,3,1,2,0,81,1,
+2,0,16,0,0,0,82,1,0,0,83,1,0,0,84,1,0,0,29,0,
+4,0,17,0,54,0,85,1,27,0,37,0,29,0,18,1,71,0,4,0,
+71,0,0,0,71,0,1,0,0,0,86,1,9,0,31,0,39,0,79,0,
+24,0,18,0,2,0,29,0,2,0,87,1,4,0,88,1,4,0,89,1,
+4,0,90,1,0,0,91,1,9,0,92,1,39,0,93,1,39,0,94,1,
+27,0,37,0,57,0,17,1,52,0,236,0,72,0,95,1,73,0,96,1,
+9,0,31,0,74,0,97,1,11,0,98,1,11,0,62,1,11,0,99,1,
+11,0,238,0,11,0,100,1,47,0,239,0,7,0,241,0,7,0,101,1,
+7,0,102,1,7,0,103,0,7,0,103,1,7,0,242,0,7,0,104,1,
+7,0,105,1,7,0,106,1,7,0,107,1,7,0,108,1,7,0,131,0,
+4,0,179,0,2,0,16,0,2,0,109,1,0,0,110,1,0,0,111,1,
+0,0,112,1,0,0,113,1,2,0,114,1,2,0,115,1,2,0,116,1,
+2,0,117,1,2,0,118,1,2,0,119,1,2,0,120,1,2,0,121,1,
+7,0,122,1,7,0,123,1,7,0,124,1,7,0,125,1,7,0,126,1,
+7,0,127,1,7,0,128,1,7,0,129,1,7,0,130,1,0,0,131,1,
+0,0,132,1,0,0,240,0,0,0,133,1,30,0,73,0,11,0,134,1,
+11,0,135,1,11,0,136,1,11,0,137,1,9,0,72,1,7,0,138,1,
+2,0,139,1,2,0,140,1,7,0,52,1,4,0,141,1,4,0,142,1,
+4,0,17,0,7,0,143,1,11,0,144,1,11,0,145,1,75,0,43,0,
+24,0,18,0,2,0,105,0,2,0,163,0,2,0,176,0,2,0,146,1,
+7,0,147,1,7,0,148,1,7,0,149,1,7,0,150,1,7,0,151,1,
+7,0,152,1,7,0,153,1,7,0,154,1,7,0,186,0,7,0,188,0,
+7,0,187,0,7,0,155,1,4,0,156,1,7,0,157,1,7,0,158,1,
+7,0,159,1,2,0,160,1,2,0,162,0,7,0,161,1,7,0,162,1,
+7,0,163,1,7,0,164,1,7,0,165,1,7,0,166,1,7,0,167,1,
+7,0,168,1,7,0,169,1,7,0,170,1,7,0,171,1,7,0,172,1,
+2,0,173,1,2,0,174,1,2,0,175,1,2,0,176,1,4,0,216,0,
+27,0,37,0,38,0,178,0,30,0,73,0,76,0,16,0,2,0,177,1,
+2,0,178,1,2,0,179,1,2,0,16,0,2,0,180,1,2,0,181,1,
+2,0,182,1,2,0,183,1,2,0,184,1,2,0,185,1,2,0,186,1,
+2,0,187,1,4,0,188,1,7,0,189,1,7,0,190,1,7,0,191,1,
+77,0,8,0,77,0,0,0,77,0,1,0,4,0,179,0,4,0,226,0,
+4,0,16,0,2,0,192,1,2,0,193,1,39,0,96,0,78,0,12,0,
+9,0,194,1,9,0,195,1,4,0,196,1,4,0,197,1,4,0,198,1,
+4,0,199,1,4,0,200,1,4,0,201,1,4,0,202,1,4,0,203,1,
+4,0,204,1,4,0,17,0,79,0,55,0,78,0,205,1,2,0,206,1,
+2,0,155,0,2,0,207,1,2,0,208,1,2,0,209,1,2,0,16,0,
+7,0,123,1,7,0,210,1,7,0,211,1,7,0,212,1,7,0,213,1,
+7,0,214,1,2,0,215,1,2,0,216,1,2,0,217,1,2,0,218,1,
+2,0,219,1,2,0,220,1,2,0,221,1,2,0,222,1,2,0,223,1,
+2,0,224,1,2,0,61,0,2,0,225,1,2,0,226,1,2,0,227,1,
+2,0,228,1,2,0,229,1,2,0,230,1,2,0,231,1,23,0,232,1,
+23,0,233,1,2,0,234,1,2,0,235,1,2,0,236,1,2,0,237,1,
+2,0,238,1,2,0,239,1,2,0,162,0,2,0,240,1,2,0,241,1,
+2,0,242,1,2,0,243,1,2,0,244,1,2,0,245,1,2,0,246,1,
+7,0,191,1,7,0,247,1,7,0,248,1,7,0,249,1,7,0,250,1,
+0,0,251,1,0,0,252,1,0,0,253,1,80,0,5,0,7,0,254,1,
+0,0,29,0,0,0,216,0,0,0,255,1,0,0,0,2,81,0,17,0,
+24,0,18,0,39,0,1,2,75,0,2,2,81,0,3,2,35,0,129,0,
+11,0,4,2,77,0,5,2,82,0,6,2,7,0,7,2,4,0,179,0,
+83,0,8,2,9,0,9,2,76,0,10,2,9,0,72,1,80,0,11,2,
+79,0,106,0,30,0,73,0,84,0,10,0,35,0,129,0,40,0,97,0,
+7,0,31,1,7,0,32,1,7,0,61,0,7,0,12,2,7,0,13,2,
+2,0,14,2,2,0,15,2,4,0,16,2,85,0,38,0,86,0,0,0,
+86,0,1,0,4,0,17,2,4,0,17,0,87,0,18,2,7,0,19,2,
+7,0,20,2,7,0,21,2,7,0,22,2,7,0,23,2,7,0,165,0,
+2,0,24,2,2,0,25,2,39,0,1,2,84,0,26,2,85,0,27,2,
+2,0,179,1,2,0,28,2,4,0,179,0,4,0,29,2,2,0,30,2,
+2,0,31,2,2,0,32,2,2,0,16,0,7,0,69,0,7,0,33,2,
+7,0,34,2,7,0,35,2,7,0,102,0,7,0,7,2,2,0,36,2,
+2,0,37,2,2,0,38,2,2,0,39,2,2,0,40,2,2,0,41,2,
+4,0,255,1,4,0,0,2,88,0,13,0,23,0,22,0,23,0,24,0,
+22,0,42,2,22,0,43,2,22,0,44,2,7,0,45,2,7,0,46,2,
+7,0,47,2,7,0,48,2,2,0,49,2,2,0,50,2,2,0,51,2,
+2,0,52,2,86,0,5,0,86,0,0,0,86,0,1,0,4,0,17,2,
+4,0,17,0,87,0,18,2,89,0,5,0,86,0,0,0,86,0,1,0,
+4,0,17,2,4,0,216,0,87,0,18,2,90,0,23,0,86,0,0,0,
+86,0,1,0,4,0,17,2,4,0,216,0,87,0,18,2,4,0,53,2,
+4,0,255,1,88,0,54,2,9,0,55,2,11,0,56,2,27,0,37,0,
+24,0,38,0,2,0,57,2,2,0,58,2,2,0,59,2,2,0,60,2,
+2,0,26,0,2,0,25,0,2,0,61,2,2,0,62,2,4,0,16,0,
+4,0,91,0,23,0,22,0,91,0,27,0,86,0,0,0,86,0,1,0,
+4,0,17,2,4,0,216,0,87,0,18,2,2,0,63,2,2,0,64,2,
+4,0,255,1,88,0,54,2,2,0,65,2,2,0,61,2,2,0,58,2,
+2,0,66,2,9,0,67,2,2,0,68,2,0,0,69,2,0,0,70,2,
+2,0,71,2,2,0,72,2,4,0,16,2,2,0,73,2,2,0,74,2,
+2,0,75,2,2,0,115,1,0,0,176,0,0,0,76,2,90,0,77,2,
+92,0,9,0,86,0,0,0,86,0,1,0,4,0,17,2,4,0,17,0,
+87,0,18,2,88,0,54,2,2,0,65,2,2,0,12,2,4,0,255,1,
+93,0,23,0,86,0,0,0,86,0,1,0,4,0,17,2,4,0,17,0,
+87,0,18,2,94,0,78,2,4,0,79,2,0,0,80,2,0,0,81,2,
+0,0,82,2,2,0,29,0,2,0,83,2,2,0,16,0,2,0,84,2,
+2,0,85,2,2,0,86,2,95,0,87,2,2,0,88,2,2,0,127,0,
+2,0,89,2,2,0,90,2,9,0,91,2,2,0,92,2,96,0,12,0,
+86,0,0,0,86,0,1,0,4,0,17,2,4,0,17,0,87,0,18,2,
+88,0,54,2,11,0,93,2,2,0,58,2,2,0,94,2,2,0,16,0,
+2,0,30,0,9,0,67,2,97,0,17,0,86,0,0,0,86,0,1,0,
+4,0,17,2,4,0,17,0,87,0,18,2,88,0,54,2,35,0,95,2,
+7,0,12,2,7,0,255,1,2,0,162,0,2,0,58,2,2,0,96,2,
+2,0,97,2,2,0,31,1,2,0,32,1,2,0,16,0,2,0,62,2,
+98,0,6,0,86,0,0,0,86,0,1,0,4,0,17,2,4,0,62,2,
+87,0,18,2,88,0,54,2,99,0,21,0,86,0,0,0,86,0,1,0,
+4,0,17,2,4,0,17,0,87,0,18,2,32,0,98,2,4,0,99,2,
+4,0,100,2,2,0,50,0,2,0,61,2,4,0,101,2,4,0,102,2,
+4,0,103,2,4,0,255,1,7,0,104,2,22,0,105,2,22,0,106,2,
+9,0,107,2,9,0,108,2,9,0,109,2,9,0,110,2,100,0,81,0,
+86,0,0,0,86,0,1,0,4,0,17,2,4,0,216,0,87,0,18,2,
+0,0,111,2,4,0,112,2,2,0,162,0,2,0,113,2,2,0,114,2,
+2,0,115,2,2,0,36,2,2,0,37,2,2,0,116,2,2,0,117,2,
+2,0,118,2,2,0,119,2,2,0,120,2,2,0,121,2,2,0,122,2,
+2,0,123,2,2,0,124,2,2,0,125,2,2,0,126,2,2,0,127,2,
+2,0,128,2,2,0,129,2,2,0,130,2,2,0,131,2,2,0,132,2,
+2,0,133,2,2,0,134,2,2,0,135,2,2,0,136,2,2,0,137,2,
+2,0,138,2,2,0,139,2,2,0,140,2,2,0,141,2,2,0,142,2,
+2,0,143,2,2,0,144,2,2,0,145,2,2,0,146,2,2,0,147,2,
+2,0,148,2,2,0,149,2,2,0,150,2,2,0,151,2,2,0,152,2,
+2,0,153,2,2,0,154,2,2,0,155,2,2,0,156,2,2,0,157,2,
+0,0,158,2,0,0,159,2,0,0,160,2,0,0,161,2,101,0,162,2,
+101,0,163,2,4,0,164,2,4,0,165,2,4,0,166,2,4,0,167,2,
+4,0,168,2,7,0,169,2,7,0,170,2,7,0,171,2,2,0,172,2,
+2,0,173,2,2,0,174,2,2,0,175,2,102,0,176,2,102,0,177,2,
+2,0,178,2,2,0,179,2,4,0,255,1,37,0,180,2,9,0,91,2,
+9,0,181,2,103,0,15,0,2,0,16,0,2,0,182,2,4,0,183,2,
+0,0,184,2,0,0,185,2,0,0,186,2,0,0,187,2,0,0,188,2,
+0,0,189,2,0,0,190,2,0,0,191,2,2,0,192,2,2,0,193,2,
+4,0,194,2,4,0,128,1,104,0,17,0,24,0,18,0,11,0,195,2,
+11,0,196,2,11,0,197,2,81,0,198,2,2,0,199,2,2,0,200,2,
+2,0,201,2,2,0,202,2,2,0,203,2,2,0,204,2,2,0,205,2,
+2,0,206,2,2,0,207,2,2,0,30,0,2,0,208,2,2,0,209,2,
+105,0,5,0,105,0,0,0,105,0,1,0,105,0,210,2,12,0,211,2,
+4,0,16,0,106,0,7,0,106,0,0,0,106,0,1,0,105,0,212,2,
+105,0,213,2,2,0,233,1,2,0,16,0,4,0,17,0,87,0,28,0,
+87,0,0,0,87,0,1,0,105,0,212,2,105,0,213,2,105,0,214,2,
+105,0,215,2,104,0,216,2,7,0,217,2,22,0,37,1,22,0,218,2,
+22,0,219,2,2,0,220,2,2,0,221,2,2,0,222,2,0,0,17,2,
+0,0,223,2,2,0,224,2,2,0,225,2,0,0,226,2,0,0,227,2,
+0,0,228,2,0,0,229,2,2,0,230,2,2,0,231,2,2,0,232,2,
+2,0,30,0,11,0,233,2,11,0,234,2,107,0,4,0,9,0,235,2,
+2,0,236,2,2,0,234,1,4,0,237,2,108,0,8,0,0,0,238,2,
+37,0,75,0,108,0,239,2,108,0,240,2,108,0,241,2,2,0,77,0,
+2,0,242,2,4,0,17,0,109,0,11,0,109,0,0,0,109,0,1,0,
+2,0,30,0,2,0,47,0,2,0,15,0,2,0,243,2,108,0,244,2,
+0,0,245,2,2,0,246,2,2,0,247,2,4,0,17,0,110,0,10,0,
+0,0,248,2,9,0,114,0,0,0,115,0,4,0,118,0,4,0,125,0,
+9,0,119,0,7,0,121,0,7,0,122,0,9,0,123,0,9,0,124,0,
+111,0,32,0,111,0,0,0,111,0,1,0,111,0,249,2,9,0,13,0,
+0,0,14,0,2,0,16,0,2,0,29,0,4,0,47,0,4,0,250,2,
+4,0,251,2,4,0,252,2,4,0,253,2,4,0,254,2,4,0,255,2,
+4,0,219,1,4,0,0,3,4,0,1,3,7,0,2,3,7,0,3,3,
+4,0,155,0,109,0,4,3,108,0,5,3,27,0,37,0,81,0,198,2,
+36,0,74,0,7,0,6,3,7,0,7,3,110,0,158,0,111,0,8,3,
+111,0,9,3,111,0,10,3,11,0,11,3,112,0,6,0,11,0,12,3,
+11,0,11,3,11,0,13,3,2,0,16,0,2,0,30,0,4,0,17,0,
+113,0,6,0,113,0,0,0,113,0,1,0,2,0,29,0,2,0,16,0,
+2,0,14,3,2,0,30,0,114,0,8,0,114,0,0,0,114,0,1,0,
+2,0,29,0,2,0,16,0,2,0,14,3,2,0,30,0,7,0,47,0,
+7,0,155,0,115,0,31,0,115,0,0,0,115,0,1,0,2,0,29,0,
+2,0,16,0,2,0,14,3,2,0,132,0,7,0,15,3,7,0,16,3,
+7,0,17,3,4,0,18,3,4,0,39,0,4,0,19,3,7,0,20,3,
+7,0,21,3,7,0,22,3,7,0,23,3,7,0,24,3,7,0,25,3,
+7,0,26,3,7,0,27,3,7,0,28,3,7,0,29,3,7,0,30,3,
+7,0,31,3,2,0,32,3,2,0,33,3,2,0,34,3,2,0,35,3,
+2,0,36,3,2,0,17,0,116,0,37,3,117,0,16,0,117,0,0,0,
+117,0,1,0,2,0,29,0,2,0,16,0,2,0,14,3,2,0,132,0,
+7,0,199,2,7,0,201,2,7,0,38,3,7,0,23,1,7,0,39,3,
+7,0,40,3,7,0,41,3,7,0,26,3,7,0,42,3,7,0,17,3,
+118,0,13,0,39,0,43,3,2,0,16,0,2,0,87,1,4,0,88,1,
+4,0,89,1,4,0,90,1,7,0,131,0,7,0,44,3,7,0,45,3,
+7,0,46,3,7,0,47,3,7,0,165,0,7,0,17,0,119,0,9,0,
+119,0,0,0,119,0,1,0,7,0,47,0,7,0,48,3,7,0,47,3,
+7,0,193,0,7,0,49,3,7,0,17,0,7,0,50,3,120,0,23,0,
+24,0,18,0,2,0,87,1,2,0,16,0,2,0,51,3,2,0,52,3,
+11,0,53,3,7,0,54,3,7,0,55,3,7,0,56,3,7,0,57,3,
+7,0,58,3,7,0,59,3,7,0,60,3,7,0,61,3,27,0,37,0,
+39,0,93,1,4,0,88,1,4,0,89,1,4,0,90,1,4,0,62,3,
+118,0,85,1,4,0,63,3,4,0,64,3,121,0,12,0,121,0,0,0,
+121,0,1,0,2,0,29,0,2,0,16,0,2,0,131,1,2,0,254,0,
+7,0,4,0,7,0,5,0,7,0,65,3,7,0,66,3,24,0,67,3,
+11,0,68,3,122,0,11,0,122,0,0,0,122,0,1,0,0,0,86,1,
+2,0,29,0,2,0,69,3,4,0,70,3,4,0,71,3,2,0,16,0,
+2,0,17,0,9,0,72,3,9,0,73,3,123,0,5,0,0,0,86,1,
+7,0,165,0,7,0,74,3,4,0,75,3,4,0,17,0,124,0,4,0,
+2,0,29,0,2,0,16,0,2,0,216,0,2,0,255,1,125,0,4,0,
+0,0,86,1,47,0,76,3,7,0,165,0,7,0,17,0,126,0,6,0,
+2,0,77,3,2,0,78,3,2,0,29,0,2,0,79,3,0,0,80,3,
+0,0,81,3,127,0,5,0,4,0,29,0,4,0,17,0,0,0,86,1,
+0,0,82,3,0,0,83,3,128,0,6,0,0,0,86,1,0,0,84,3,
+2,0,85,3,2,0,26,3,2,0,162,0,2,0,255,1,129,0,5,0,
+0,0,86,1,7,0,86,3,7,0,87,3,2,0,16,0,2,0,88,3,
+130,0,3,0,0,0,86,1,4,0,19,3,4,0,89,3,131,0,7,0,
+0,0,86,1,7,0,87,3,0,0,90,3,0,0,91,3,2,0,162,0,
+2,0,216,0,4,0,92,3,132,0,3,0,39,0,93,3,0,0,94,3,
+0,0,95,3,133,0,17,0,133,0,0,0,133,0,1,0,2,0,29,0,
+2,0,69,3,2,0,16,0,2,0,96,3,2,0,97,3,2,0,98,3,
+2,0,216,0,2,0,255,1,0,0,86,1,9,0,31,0,134,0,99,3,
+39,0,43,3,2,0,100,3,2,0,101,3,4,0,17,0,135,0,1,0,
+0,0,102,3,136,0,1,0,32,0,98,2,134,0,18,0,134,0,0,0,
+134,0,1,0,134,0,103,3,2,0,29,0,2,0,16,0,2,0,104,3,
+2,0,98,3,2,0,69,3,2,0,105,3,2,0,255,1,2,0,0,2,
+0,0,86,1,9,0,31,0,137,0,99,3,133,0,106,3,2,0,107,3,
+2,0,108,3,4,0,109,3,138,0,3,0,4,0,110,3,4,0,17,0,
+39,0,43,3,139,0,13,0,72,0,111,3,2,0,29,0,2,0,16,0,
+2,0,15,3,2,0,16,3,0,0,86,1,2,0,112,3,2,0,113,3,
+7,0,114,3,2,0,115,3,2,0,91,0,2,0,77,1,2,0,78,1,
+140,0,9,0,2,0,16,0,2,0,116,3,2,0,15,3,2,0,16,3,
+141,0,117,3,2,0,29,0,2,0,118,3,2,0,119,3,2,0,120,3,
+142,0,7,0,2,0,16,0,2,0,116,3,2,0,15,3,2,0,16,3,
+2,0,29,0,2,0,121,3,7,0,122,3,143,0,9,0,4,0,110,3,
+2,0,29,0,2,0,16,0,39,0,43,3,68,0,123,3,0,0,86,1,
+7,0,124,3,2,0,125,3,2,0,17,0,144,0,5,0,2,0,29,0,
+2,0,16,0,4,0,17,0,81,0,198,2,39,0,1,2,145,0,5,0,
+4,0,16,0,4,0,29,0,0,0,86,1,0,0,82,3,39,0,43,3,
+146,0,12,0,4,0,16,0,4,0,29,0,7,0,126,3,7,0,127,3,
+7,0,241,0,7,0,242,0,7,0,101,1,7,0,104,1,7,0,128,3,
+7,0,129,3,7,0,130,3,0,0,131,3,147,0,9,0,2,0,16,0,
+2,0,29,0,2,0,15,3,2,0,16,3,0,0,86,1,2,0,216,0,
+2,0,24,0,2,0,132,3,2,0,133,3,148,0,8,0,39,0,43,3,
+7,0,38,3,7,0,134,3,7,0,135,3,7,0,47,3,2,0,16,0,
+2,0,88,3,7,0,136,3,149,0,7,0,2,0,16,0,2,0,26,3,
+7,0,58,3,7,0,137,3,7,0,138,3,7,0,139,3,7,0,140,3,
+150,0,10,0,2,0,16,0,2,0,29,0,2,0,15,3,2,0,16,3,
+0,0,86,1,2,0,216,0,2,0,24,0,2,0,132,3,2,0,133,3,
+82,0,6,2,151,0,7,0,4,0,19,3,4,0,141,3,4,0,142,3,
+4,0,143,3,7,0,144,3,7,0,145,3,0,0,90,3,152,0,7,0,
+0,0,146,3,39,0,147,3,0,0,94,3,2,0,148,3,2,0,216,0,
+4,0,255,1,0,0,95,3,153,0,6,0,2,0,16,0,2,0,29,0,
+2,0,15,3,2,0,16,3,0,0,149,3,0,0,150,3,154,0,1,0,
+4,0,16,0,137,0,10,0,137,0,0,0,137,0,1,0,137,0,103,3,
+2,0,29,0,2,0,16,0,2,0,69,3,2,0,151,3,0,0,86,1,
+9,0,31,0,39,0,43,3,83,0,10,0,7,0,124,1,7,0,152,3,
+7,0,153,3,7,0,154,3,7,0,155,3,4,0,16,0,7,0,156,3,
+7,0,157,3,7,0,158,3,7,0,17,0,141,0,20,0,24,0,18,0,
+0,0,21,0,155,0,159,3,33,0,88,0,33,0,160,3,9,0,161,3,
+27,0,37,0,7,0,122,3,7,0,162,3,7,0,163,3,7,0,164,3,
+7,0,165,3,7,0,166,3,7,0,167,3,4,0,50,0,4,0,168,3,
+4,0,169,3,0,0,170,3,0,0,171,3,0,0,172,3,156,0,6,0,
+24,0,18,0,7,0,173,3,7,0,174,3,7,0,175,3,2,0,176,3,
+2,0,177,3,157,0,14,0,86,0,0,0,86,0,1,0,4,0,17,2,
+4,0,17,0,87,0,18,2,88,0,54,2,141,0,117,3,2,0,162,0,
+2,0,116,3,2,0,31,1,2,0,32,1,2,0,16,0,2,0,62,2,
+4,0,255,1,158,0,6,0,158,0,0,0,158,0,1,0,2,0,155,0,
+2,0,207,1,7,0,206,1,0,0,86,1,159,0,31,0,159,0,0,0,
+159,0,1,0,158,0,178,3,2,0,87,1,2,0,17,0,4,0,88,1,
+4,0,89,1,4,0,90,1,39,0,93,1,39,0,94,1,27,0,37,0,
+7,0,241,0,7,0,101,1,7,0,102,1,7,0,103,0,7,0,103,1,
+7,0,242,0,7,0,104,1,7,0,105,1,7,0,106,1,7,0,107,1,
+7,0,108,1,7,0,131,0,4,0,179,0,0,0,110,1,0,0,111,1,
+0,0,112,1,0,0,113,1,7,0,122,1,7,0,123,1,7,0,179,3,
+160,0,4,0,160,0,0,0,160,0,1,0,39,0,43,3,11,0,180,3,
+82,0,4,0,24,0,18,0,11,0,181,3,11,0,182,3,158,0,183,3,
+63,0,22,0,63,0,0,0,63,0,1,0,63,0,93,1,11,0,184,3,
+0,0,86,1,7,0,185,3,7,0,186,3,7,0,187,3,4,0,16,0,
+7,0,165,0,7,0,56,1,7,0,241,0,7,0,101,1,7,0,103,0,
+7,0,103,1,7,0,105,1,7,0,106,1,7,0,107,1,7,0,188,3,
+7,0,189,3,7,0,190,3,7,0,191,3,161,0,7,0,24,0,18,0,
+11,0,192,3,11,0,193,3,4,0,16,0,4,0,194,3,4,0,195,3,
+4,0,196,3,162,0,10,0,162,0,0,0,162,0,1,0,11,0,144,1,
+4,0,16,0,7,0,241,0,7,0,103,0,7,0,105,1,7,0,107,1,
+0,0,86,1,4,0,91,0,73,0,1,0,11,0,197,3,163,0,7,0,
+163,0,0,0,163,0,1,0,27,0,37,0,11,0,98,1,4,0,16,0,
+0,0,86,1,4,0,91,0,72,0,4,0,24,0,18,0,11,0,197,3,
+163,0,198,3,162,0,199,3,164,0,13,0,86,0,0,0,86,0,1,0,
+4,0,17,2,4,0,17,0,87,0,18,2,88,0,54,2,72,0,95,1,
+4,0,16,0,2,0,58,2,2,0,91,0,2,0,200,3,2,0,62,2,
+4,0,255,1,74,0,5,0,74,0,0,0,74,0,1,0,27,0,37,0,
+2,0,16,0,0,0,201,3,165,0,14,0,165,0,0,0,165,0,1,0,
+9,0,31,0,27,0,37,0,0,0,29,0,0,0,69,3,2,0,16,0,
+2,0,91,0,0,0,201,3,7,0,202,3,7,0,110,3,7,0,203,3,
+7,0,204,3,7,0,205,3,166,0,7,0,39,0,206,3,7,0,207,3,
+4,0,208,3,0,0,209,3,7,0,210,3,4,0,91,0,7,0,211,3,
+167,0,4,0,39,0,206,3,4,0,91,0,4,0,77,1,0,0,209,3,
+168,0,4,0,39,0,206,3,4,0,16,0,4,0,91,0,0,0,209,3,
+169,0,4,0,39,0,206,3,4,0,16,0,4,0,91,0,0,0,209,3,
+170,0,8,0,39,0,206,3,4,0,29,0,2,0,250,2,2,0,16,3,
+7,0,134,3,7,0,135,3,72,0,111,3,0,0,209,3,171,0,1,0,
+39,0,206,3,172,0,6,0,7,0,8,0,7,0,9,0,7,0,10,0,
+7,0,11,0,7,0,212,3,7,0,213,3,173,0,15,0,173,0,0,0,
+173,0,1,0,2,0,16,0,2,0,162,0,4,0,91,0,27,0,37,0,
+72,0,111,3,7,0,250,2,7,0,16,3,7,0,214,3,7,0,215,3,
+7,0,216,3,7,0,217,3,7,0,112,3,7,0,218,3,};
+int DNAlen= sizeof(DNAstr);
diff --git a/source/blender/makesdna/intern/makesdna.c b/source/blender/makesdna/intern/makesdna.c
new file mode 100644
index 00000000000..98a23472a9c
--- /dev/null
+++ b/source/blender/makesdna/intern/makesdna.c
@@ -0,0 +1,1121 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * Struct muncher for making SDNA
+ *
+ * Originally by Ton, some mods by Frank, and some cleaning and
+ * extension by Nzc.
+ *
+ * Makesdna creates a .c file with a long string of numbers that
+ * encode the Blender file format. It is fast, because it is basically
+ * a binary dump. There are some details to mind when reconstructing
+ * the file (endianness and byte-alignment).
+ *
+ * This little program scans all structs that need to be serialized,
+ * and determined the names and types of all members. It calculates
+ * how much memory (on disk or in ram) is needed to store that struct,
+ * and the offsets for reaching a particular one.
+ *
+ * There is a facility to get verbose output from sdna. Search for
+ * debugSDNA. This int can be set to 0 (no output) to some int. Higher
+ * numbers give more output.
+ * */
+
+#define DNA_VERSION_DATE "$Id$"
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_sdna_types.h"
+
+#define SDNA_MAX_FILENAME_LENGTH 255
+
+
+/* Included the path relative from /source/blender/ here, so we can move */
+/* headers around with more freedom. */
+char *includefiles[] = {
+
+ // if you add files here, please add them at the end
+ // of makesdna.c (this file) as well
+
+ "DNA_listBase.h",
+ "DNA_vec_types.h",
+ "DNA_ID.h",
+ "DNA_ipo_types.h",
+ "DNA_key_types.h",
+ "DNA_scriptlink_types.h",
+ "DNA_text_types.h",
+ "DNA_packedFile_types.h",
+ "DNA_camera_types.h",
+ "DNA_image_types.h",
+ "DNA_texture_types.h",
+ "DNA_lamp_types.h",
+ "DNA_wave_types.h",
+ "DNA_material_types.h",
+ "DNA_vfont_types.h",
+ // if you add files here, please add them at the end
+ // of makesdna.c (this file) as well
+ "DNA_meta_types.h",
+ "DNA_curve_types.h",
+ "DNA_mesh_types.h",
+ "DNA_lattice_types.h",
+ "DNA_object_types.h",
+ "DNA_world_types.h",
+ "DNA_radio_types.h",
+ "DNA_scene_types.h",
+ "DNA_view3d_types.h",
+ "DNA_view2d_types.h",
+ "DNA_space_types.h",
+ "DNA_userdef_types.h",
+ "DNA_screen_types.h",
+ "DNA_sdna_types.h",
+ // if you add files here, please add them at the end
+ // of makesdna.c (this file) as well
+ "DNA_fileglobal_types.h",
+ "DNA_sequence_types.h",
+ "DNA_effect_types.h",
+ "DNA_ika_types.h",
+ "DNA_oops_types.h",
+ "DNA_property_types.h",
+ "DNA_sensor_types.h",
+ "DNA_controller_types.h",
+ "DNA_actuator_types.h",
+ "DNA_sound_types.h",
+ "DNA_group_types.h",
+ "DNA_armature_types.h",
+ "DNA_action_types.h",
+ "DNA_constraint_types.h",
+ "DNA_nla_types.h",
+ // if you add files here, please add them at the end
+ // of makesdna.c (this file) as well
+
+ // empty string to indicate end of includefiles
+ ""
+};
+
+int maxdata= 500000, maxnr= 50000;
+int nr_names=0;
+int nr_types=0;
+int nr_structs=0;
+char **names, *namedata; /* op adres names[a] staat string a */
+char **types, *typedata; /* op adres types[a] staat string a */
+short *typelens; /* op typelens[a] staat de lengte van type a */
+short *alphalens; /* contains sizes as they are calculated on the alpha */
+short **structs, *structdata; /* op sp= structs[a] staat eerste adres structdefinitie
+ sp[0] is typenummer
+ sp[1] is aantal elementen
+ sp[2] sp[3] is typenr, namenr (enz) */
+/*
+ * debugSDNA:
+ * - 0 = no output, except errors
+ * - 1 = detail actions
+ * - 2 = full trace, tell which names and types were found
+ * - 4 = full trace, plus all gritty details
+ */
+int debugSDNA = 0;
+int additional_slen_offset;
+
+/* ************************************************************************** */
+/* Functions */
+/* ************************************************************************** */
+
+/**
+ * Add type <str> to struct indexed by <len>, if it was not yet found.
+ */
+int add_type(char *str, int len);
+
+/**
+ * Add variable <str> to
+ */
+int add_name(char *str);
+
+/**
+ * Search whether this structure type was already found, and if not,
+ * add it.
+ */
+short *add_struct(int namecode);
+
+/**
+ * Remove comments from this buffer. Assumes that the buffer refers to
+ * ascii-code text.
+ */
+int preprocess_include(char *maindata, int len);
+
+/**
+ * Scan this file for serializable types.
+ */
+int convert_include(char *filename);
+
+/**
+ * Determine how many bytes are needed for an array.
+ */
+int arraysize(char *astr, int len);
+
+/**
+ * Determine how many bytes are needed for each struct.
+ */
+int calculate_structlens(void);
+
+/**
+ * Construct the DNA.c file
+ */
+void dna_write(FILE *file, void *pntr, int size);
+
+/**
+ * Report all structures found so far, and print their lenghts.
+ */
+void printStructLenghts(void);
+
+/**
+ *
+ */
+int make_structDNA(FILE *file);
+
+/**
+ *
+ */
+int main(int argc, char ** argv);
+
+
+
+/* ************************************************************************** */
+/* Implementation */
+/* ************************************************************************** */
+
+/* ************************* MAKEN DNA ********************** */
+
+int add_type(char *str, int len)
+{
+ int nr;
+ char *cp;
+
+ if(str[0]==0) return -1;
+
+ /* zoek typearray door */
+ for(nr=0; nr<nr_types; nr++) {
+ if(strcmp(str, types[nr])==0) {
+ if (len) {
+ typelens[nr]= len;
+ alphalens[nr] = len;
+ }
+ return nr;
+ }
+ }
+
+ /* nieuw type appenden */
+ if(nr_types==0) cp= typedata;
+ else {
+ cp= types[nr_types-1]+strlen(types[nr_types-1])+1;
+ }
+ strcpy(cp, str);
+ types[nr_types]= cp;
+ typelens[nr_types]= len;
+ alphalens[nr_types]= len;
+
+ if(nr_types>=maxnr) {
+ printf("too many types\n");
+ return nr_types-1;;
+ }
+ nr_types++;
+
+ return nr_types-1;
+}
+
+
+/**
+ *
+ * Because of the weird way of tokenizing, we have to 'cast' function
+ * pointers to ... (*f)(), whatever the original signature. In fact,
+ * we add name and type at the same time... There are two special
+ * cases, unfortunately. These are explicitly checked.
+ *
+ * */
+int add_name(char *str)
+{
+ int nr, i, j, k;
+ char *cp;
+ char buf[255]; /* stupid limit, change it :) */
+ char *name;
+
+ additional_slen_offset = 0;
+
+ if((str[0]==0) /* || (str[1]==0) */) return -1;
+
+ if (str[0] == '(' && str[1] == '*') {
+ if (debugSDNA > 3) printf("\t\t\t\t*** Function pointer found\n");
+ /* functionpointer: transform the type (sometimes) */
+ i = 0;
+ j = 0;
+
+ while (str[i] != ')') {
+ buf[i] = str[i];
+ i++;
+ }
+
+ /* Another number we need is the extra slen offset. This extra
+ * offset is the overshoot after a space. If there is no
+ * space, no overshoot should be calculated. */
+ j = i; /* j at first closing brace */
+
+ if (debugSDNA > 3) printf("first brace after offset %d\n", i);
+
+ j++; /* j beyond closing brace ? */
+ while ((str[j] != 0) && (str[j] != ')' )) {
+ if (debugSDNA > 3) printf("seen %c ( %d) \n", str[j], str[j]);
+ j++;
+ }
+ if (debugSDNA > 3) printf("seen %c ( %d) \n", str[j], str[j]);
+ if (debugSDNA > 3) printf("special after offset %d\n", j);
+
+ if (str[j] == 0 ) {
+ if (debugSDNA > 3) printf("offsetting for space\n");
+ /* get additional offset */
+ k = 0;
+ while (str[j] != ')') {
+ j++;
+ k++;
+ }
+ if (debugSDNA > 3) printf("extra offset %d\n", k);
+ additional_slen_offset = k;
+ } else if (str[j] == ')' ) {
+ if (debugSDNA > 3) printf("offsetting for brace\n");
+ ; /* don't get extra offset */
+ } else {
+ printf("Error during tokening function pointer argument list\n");
+ }
+
+ /*
+ * Put )(void) at the end? Maybe )(). Should check this with
+ * old sdna. Actually, sometimes )(), sometimes )(void...)
+ * Alas.. such is the nature of braindamage :(
+ *
+ * Sorted it out: always do )(), except for headdraw and
+ * windraw, part of ScrArea. This is important, because some
+ * linkers will treat different fp's differently when called
+ * !!! This has to do with interference in byte-alignment and
+ * the way args are pushed on the stack.
+ *
+ * */
+ buf[i] = 0;
+ if (debugSDNA > 3) printf("Name before chomping: %s\n", buf);
+ if ( (strncmp(buf,"(*headdraw", 10) == 0)
+ || (strncmp(buf,"(*windraw", 9) == 0) ) {
+ buf[i] = ')';
+ buf[i+1] = '(';
+ buf[i+2] = 'v';
+ buf[i+3] = 'o';
+ buf[i+4] = 'i';
+ buf[i+5] = 'd';
+ buf[i+6] = ')';
+ buf[i+7] = 0;
+ } else {
+ buf[i] = ')';
+ buf[i+1] = '(';
+ buf[i+2] = ')';
+ buf[i+3] = 0;
+ }
+ /* now precede with buf*/
+ if (debugSDNA > 3) printf("\t\t\t\t\tProposing fp name %s\n", buf);
+ name = buf;
+ } else {
+ /* normal field: old code */
+ name = str;
+ }
+
+ /* zoek name array door */
+ for(nr=0; nr<nr_names; nr++) {
+ if(strcmp(name, names[nr])==0) {
+ return nr;
+ }
+ }
+
+ /* nieuw type appenden */
+ if(nr_names==0) cp= namedata;
+ else {
+ cp= names[nr_names-1]+strlen(names[nr_names-1])+1;
+ }
+ strcpy(cp, name);
+ names[nr_names]= cp;
+
+ if(nr_names>=maxnr) {
+ printf("too many names\n");
+ return nr_names-1;
+ }
+ nr_names++;
+
+ return nr_names-1;
+}
+
+short *add_struct(int namecode)
+{
+ int len;
+ short *sp;
+
+ if(nr_structs==0) {
+ structs[0]= structdata;
+ }
+ else {
+ sp= structs[nr_structs-1];
+ len= sp[1];
+ structs[nr_structs]= sp+ 2*len+2;
+ }
+
+ sp= structs[nr_structs];
+ sp[0]= namecode;
+
+ if(nr_structs>=maxnr) {
+ printf("too many structs\n");
+ return sp;
+ }
+ nr_structs++;
+
+ return sp;
+}
+
+int preprocess_include(char *maindata, int len)
+{
+ int a, newlen, comment = 0;
+ char *cp, *temp, *md;
+
+ temp= MEM_mallocN(len, "preprocess_include");
+ memcpy(temp, maindata, len);
+
+ // remove all c++ comments
+ /* alle enters/tabs/etc vervangen door spaties */
+ cp= temp;
+ a= len;
+ comment = 0;
+ while(a--) {
+ if(cp[0]=='/' && cp[1]=='/') {
+ comment = 1;
+ } else if (*cp<32) {
+ comment = 0;
+ }
+ if (comment || *cp<32 || *cp>128 ) *cp= 32;
+ cp++;
+ }
+
+
+ /* data uit temp naar maindata kopieeren, verwijder commentaar en dubbele spaties */
+ cp= temp;
+ md= maindata;
+ newlen= 0;
+ comment= 0;
+ a= len;
+ while(a--) {
+
+ if(cp[0]=='/' && cp[1]=='*') {
+ comment= 1;
+ cp[0]=cp[1]= 32;
+ }
+ if(cp[0]=='*' && cp[1]=='/') {
+ comment= 0;
+ cp[0]=cp[1]= 32;
+ }
+
+ /* niet kopieeren als: */
+ if(comment);
+ else if( cp[0]==' ' && cp[1]==' ' );
+ else if( cp[-1]=='*' && cp[0]==' ' ); /* pointers met spatie */
+ else {
+ md[0]= cp[0];
+ md++;
+ newlen++;
+ }
+ cp++;
+ }
+
+ MEM_freeN(temp);
+ return newlen;
+}
+
+void *read_file_data(char *filename, int *len_r)
+{
+#ifdef WIN32
+ FILE *fp= fopen(filename, "rb");
+#else
+ FILE *fp= fopen(filename, "r");
+#endif
+ void *data;
+
+ if (!fp) {
+ *len_r= -1;
+ return NULL;
+ }
+
+ fseek(fp, 0L, SEEK_END);
+ *len_r= ftell(fp);
+ fseek(fp, 0L, SEEK_SET);
+
+ data= MEM_mallocN(*len_r, "read_file_data");
+ if (!data) {
+ *len_r= -1;
+ return NULL;
+ }
+
+ if (fread(data, *len_r, 1, fp)!=1) {
+ *len_r= -1;
+ MEM_freeN(data);
+ return NULL;
+ }
+
+ return data;
+}
+
+int convert_include(char *filename)
+{
+ /* lees includefile, sla structen over die op regel ervoor '#' hebben.
+ sla alle data op in tijdelijke arrays.
+ */
+ int filelen, count, overslaan, slen, type, name, strct;
+ short *structpoin, *sp;
+ char *maindata, *mainend, *md, *md1;
+
+ md= maindata= read_file_data(filename, &filelen);
+ if (filelen==-1) {
+ printf("Can't read file %s\n", filename);
+ return 1;
+ }
+
+ filelen= preprocess_include(maindata, filelen);
+ mainend= maindata+filelen-1;
+
+ /* we zoeken naar '{' en dan terug naar 'struct' */
+ count= 0;
+ overslaan= 0;
+ while(count<filelen) {
+
+ /* code voor struct overslaan: twee hekjes. (voor spatie zorgt preprocess) */
+ if(md[0]=='#' && md[1]==' ' && md[2]=='#') {
+ overslaan= 1;
+ }
+
+ if(md[0]=='{') {
+ md[0]= 0;
+ if(overslaan) {
+ overslaan= 0;
+ }
+ else {
+ if(md[-1]==' ') md[-1]= 0;
+ md1= md-2;
+ while( *md1!=32) md1--; /* naar begin woord */
+ md1++;
+
+ /* structnaam te pakken, als... */
+ if( strncmp(md1-7, "struct", 6)==0 ) {
+
+
+ strct= add_type(md1, 0);
+ structpoin= add_struct(strct);
+ sp= structpoin+2;
+
+ if (debugSDNA > 1) printf("\t|\t|-- detected struct %s\n", types[strct]);
+
+ /* eerst overal keurige strings van maken */
+ md1= md+1;
+ while(*md1 != '}') {
+ if( ((long)md1) > ((long)mainend) ) break;
+
+ if(*md1==',' || *md1==' ') *md1= 0;
+ md1++;
+ }
+
+ /* types en namen lezen tot eerste karakter niet '}' */
+ md1= md+1;
+ while( *md1 != '}' ) {
+ if( ((long)md1) > ((long)mainend) ) break;
+
+ /* als er 'struct' of 'unsigned' staat, overslaan */
+ if(*md1) {
+ if( strncmp(md1, "struct", 6)==0 ) md1+= 7;
+ if( strncmp(md1, "unsigned", 6)==0 ) md1+= 9;
+
+ /* type te pakken! */
+ type= add_type(md1, 0);
+
+ if (debugSDNA > 1) printf("\t|\t|\tfound type %s (", md1);
+
+ md1+= strlen(md1);
+
+
+ /* doorlezen tot ';' */
+ while( *md1 != ';' ) {
+ if( ((long)md1) > ((long)mainend) ) break;
+
+ if(*md1) {
+ /* Name te pakken. slen needs
+ * correction for function
+ * pointers! */
+ slen= strlen(md1);
+ if( md1[slen-1]==';' ) {
+ md1[slen-1]= 0;
+
+
+ name= add_name(md1);
+ slen += additional_slen_offset;
+ sp[0]= type;
+ sp[1]= name;
+
+ if ((debugSDNA>1) && (names[name] != 0 )) printf("%s |", names[name]);
+
+ structpoin[1]++;
+ sp+= 2;
+
+ md1+= slen;
+ break;
+ }
+
+
+ name= add_name(md1);
+ slen += additional_slen_offset;
+
+ sp[0]= type;
+ sp[1]= name;
+ if ((debugSDNA > 1) && (names[name] != 0 )) printf("%s ||", names[name]);
+
+ structpoin[1]++;
+ sp+= 2;
+
+ md1+= slen;
+ }
+ md1++;
+ }
+
+ if (debugSDNA > 1) printf(")\n");
+
+ }
+ md1++;
+ }
+ }
+ }
+ }
+ count++;
+ md++;
+ }
+
+ MEM_freeN(maindata);
+
+ return 0;
+}
+
+int arraysize(char *astr, int len)
+{
+ int a, mul=1;
+ char str[100], *cp=0;
+
+ memcpy(str, astr, len+1);
+
+ for(a=0; a<len; a++) {
+ if( str[a]== '[' ) {
+ cp= &(str[a+1]);
+ }
+ else if( str[a]==']' && cp) {
+ str[a]= 0;
+ mul*= atoi(cp);
+ }
+ }
+
+ return mul;
+}
+
+int calculate_structlens(void)
+{
+ int a, b, len, alphalen, unknown= nr_structs, lastunknown, structtype, type, mul, namelen;
+ short *sp, *structpoin;
+ char *cp;
+ int has_pointer, dna_error = 0;
+
+ while(unknown) {
+ lastunknown= unknown;
+ unknown= 0;
+
+ /* loop alle structen af... */
+ for(a=0; a<nr_structs; a++) {
+ structpoin= structs[a];
+ structtype= structpoin[0];
+
+ /* als lengte nog niet bekend */
+ if(typelens[structtype]==0) {
+
+ sp= structpoin+2;
+ len= 0;
+ alphalen = 0;
+ has_pointer = 0;
+
+ /* loop alle elementen in struct af */
+ for(b=0; b<structpoin[1]; b++, sp+=2) {
+ type= sp[0];
+ cp= names[sp[1]];
+
+ namelen= strlen(cp);
+ /* is het een pointer of functiepointer? */
+ if(cp[0]=='*' || cp[1]=='*') {
+ has_pointer = 1;
+ /* heeft de naam een extra lengte? (array) */
+ mul= 1;
+ if( cp[namelen-1]==']') mul= arraysize(cp, namelen);
+
+ /* 4-8 aligned/ */
+ if(sizeof(void *) == 4) {
+ if (len % 4) {
+ printf("Align pointer error in struct: %s %s\n", types[structtype], cp);
+ dna_error = 1;
+ }
+ } else {
+ if (len % 8) {
+ printf("Align pointer error in struct: %s %s\n", types[structtype], cp);
+ dna_error = 1;
+ }
+ }
+
+ if (alphalen % 8) {
+ printf("Align pointer error in struct: %s %s\n", types[structtype],cp);
+ dna_error = 1;
+ }
+
+ len += sizeof(void *) * mul;
+ alphalen += 8 * mul;
+
+ } else if( typelens[type] ) {
+ /* heeft de naam een extra lengte? (array) */
+ mul= 1;
+ if( cp[namelen-1]==']') mul= arraysize(cp, namelen);
+
+ /* 2-4 aligned/ */
+ if(typelens[type]>3 && (len % 4) ) {
+ printf("Align 4 error in struct: %s %s\n", types[structtype], cp);
+ }
+ else if(typelens[type]==2 && (len % 2) ) {
+ printf("Align 2 error in struct: %s %s\n", types[structtype], cp);
+ }
+
+ len += mul*typelens[type];
+ alphalen += mul * alphalens[type];
+
+ } else {
+ len= 0;
+ alphalen = 0;
+ break;
+ }
+ }
+
+ if (len==0) {
+ unknown++;
+ } else {
+ typelens[structtype]= len;
+ alphalens[structtype]= alphalen;
+ // two ways to detect if a struct contains a pointer:
+ // has_pointer is set or alphalen != len
+ if (has_pointer || alphalen != len) {
+ if (alphalen % 8) {
+ printf("Sizeerror in struct: %s\n", types[structtype]);
+ dna_error = 1;
+ }
+ }
+ }
+ }
+ }
+
+ if(unknown==lastunknown) break;
+ }
+
+ if(unknown) {
+ printf("ERROR: still %d structs unknown\n", unknown);
+
+ if (debugSDNA) {
+ printf("*** Known structs : \n");
+
+ for(a=0; a<nr_structs; a++) {
+ structpoin= structs[a];
+ structtype= structpoin[0];
+
+ /* lengte nog niet bekend */
+ if(typelens[structtype]!=0) {
+ printf(" %s\n", types[structtype]);
+ }
+ }
+ }
+
+
+ printf("*** Unknown structs : \n");
+
+ for(a=0; a<nr_structs; a++) {
+ structpoin= structs[a];
+ structtype= structpoin[0];
+
+ /* lengte nog niet bekend */
+ if(typelens[structtype]==0) {
+ printf(" %s\n", types[structtype]);
+ }
+ }
+ }
+
+ return(dna_error);
+}
+
+#define MAX_DNA_LINE_LENGTH 20
+
+void dna_write(FILE *file, void *pntr, int size)
+{
+ static int linelength = 0;
+ int i;
+ char *data;
+
+ data = (char *) pntr;
+
+ for (i = 0 ; i < size ; i++)
+ {
+ fprintf(file, "%d,", data[i]);
+ linelength++;
+ if (linelength >= MAX_DNA_LINE_LENGTH) {
+ fprintf(file, "\n");
+ linelength = 0;
+ }
+ }
+}
+
+void printStructLenghts(void)
+{
+ int a, unknown= nr_structs, lastunknown, structtype;
+ short *structpoin;
+ printf("\n\n*** All detected structs:\n");
+
+ while(unknown) {
+ lastunknown= unknown;
+ unknown= 0;
+
+ /* loop alle structen af... */
+ for(a=0; a<nr_structs; a++) {
+ structpoin= structs[a];
+ structtype= structpoin[0];
+ printf("\t%s\t:%d\n", types[structtype], typelens[structtype]);
+ }
+ }
+
+ printf("*** End of list\n");
+
+}
+
+
+int make_structDNA(FILE *file)
+{
+ int len, i;
+ short *sp;
+ /* str contains filenames. Since we now include paths, I stretched */
+ /* it a bit. Hope this is enough :) -nzc- */
+ char str[SDNA_MAX_FILENAME_LENGTH], *cp;
+ int firststruct;
+
+ if (debugSDNA > -1) {
+ fflush(stdout);
+ printf("Running makesdna at debug level %d\n", debugSDNA);
+ printf("\tProgram version: %s\n", DNA_VERSION_DATE);
+ }
+
+ /* de allerlangst bekende struct is 50k, 100k is ruimte genoeg! */
+ namedata= MEM_callocN(maxdata, "namedata");
+ typedata= MEM_callocN(maxdata, "typedata");
+ structdata= MEM_callocN(maxdata, "structdata");
+
+ /* maximaal 5000 variablen, vast voldoende? */
+ names= MEM_callocN(sizeof(char *)*maxnr, "names");
+ types= MEM_callocN(sizeof(char *)*maxnr, "types");
+ typelens= MEM_callocN(sizeof(short)*maxnr, "typelens");
+ alphalens= MEM_callocN(sizeof(short)*maxnr, "alphalens");
+ structs= MEM_callocN(sizeof(short)*maxnr, "structs");
+
+ /* inserten alle bekende types */
+ /* let op: uint komt niet voor! gebruik in structen unsigned int */
+ add_type("char", 1); /* 0 */
+ add_type("uchar", 1); /* 1 */
+ add_type("short", 2); /* 2 */
+ add_type("ushort", 2); /* 3 */
+ add_type("int", 4); /* 4 */
+ add_type("long", 4); /* 5 */
+ add_type("ulong", 4); /* 6 */
+ add_type("float", 4); /* 7 */
+ add_type("double", 8); /* 8 */
+ add_type("void", 0); /* 9 */
+
+ // the defines above shouldn't be output in the padding file...
+ firststruct = nr_types;
+
+#define BASE_HEADER "../"
+
+ /* add all include files defined in the global array */
+ /* Since the internal file+path name buffer has limited length, I do a */
+ /* little test first... */
+ /* Mind the breaking condition here! */
+ if (debugSDNA) printf("\tStart of header scan:\n");
+ for (i = 0; strlen(includefiles[i]); i++) {
+ if (debugSDNA) printf("\t|-- Converting %s%s\n", BASE_HEADER, includefiles[i]);
+ if (strlen(includefiles[i]) > SDNA_MAX_FILENAME_LENGTH) {
+ /* this would cause coredumps*/
+ printf("*** \tError in makesdna: the specified filenames is too long "
+ "for parsing.\n\tFile: %s%s\n", BASE_HEADER, includefiles[i]);
+ } else {
+ sprintf(str, "%s%s", BASE_HEADER, includefiles[i]);
+ if (convert_include(str)) {
+ return (1);
+ }
+ }
+ }
+ if (debugSDNA) printf("\tFinished scanning %d headers.\n", i);
+
+ if (calculate_structlens()) {
+ // error
+ return(1);
+ }
+
+ /* DIT DEEL VOOR DEBUG */
+ if (debugSDNA > 1)
+ {
+ int a,b;
+/* short *elem; */
+ short num_types;
+
+ printf("nr_names %d nr_types %d nr_structs %d\n", nr_names, nr_types, nr_structs);
+ for(a=0; a<nr_names; a++) {
+ printf(" %s \n", names[a]);
+ }
+ printf("\n");
+
+ sp= typelens;
+ for(a=0; a<nr_types; a++, sp++) {
+ printf(" %s %d\n", types[a], *sp);
+ }
+ printf("\n");
+
+ for(a=0; a<nr_structs; a++) {
+ sp= structs[a];
+ printf(" struct %s elems: %d size: %d\n", types[sp[0]], sp[1],typelens[sp[0]]);
+ num_types = sp[1];
+ sp+= 2;
+ /* ? num_types was elem? */
+ for(b=0; b< num_types; b++, sp+= 2) {
+ printf(" %s %s\n", types[sp[0]], names[sp[1]]);
+ }
+ }
+ }
+
+ /* file schrijven */
+
+ if (debugSDNA > -1) printf("Writing file ... ");
+
+ if(nr_names==0 || nr_structs==0);
+ else {
+ strcpy(str, "SDNA");
+ dna_write(file, str, 4);
+
+ /* SCHRIJF NAMEN */
+ strcpy(str, "NAME");
+ dna_write(file, str, 4);
+ len= nr_names;
+ dna_write(file, &len, 4);
+
+ /* lengte berekenen datablok met strings */
+ cp= names[nr_names-1];
+ cp+= strlen(names[nr_names-1]) + 1; /* +1: nul-terminator */
+ len= (long)cp - (long)(names[0]);
+ len= (len+3) & ~3;
+ dna_write(file, names[0], len);
+
+ /* SCHRIJF TYPES */
+ strcpy(str, "TYPE");
+ dna_write(file, str, 4);
+ len= nr_types;
+ dna_write(file, &len, 4);
+
+ /* lengte berekenen datablok */
+ cp= types[nr_types-1];
+ cp+= strlen(types[nr_types-1]) + 1; /* +1: nul-terminator */
+ len= (long)cp - (long)(types[0]);
+ len= (len+3) & ~3;
+
+ dna_write(file, types[0], len);
+
+ /* SCHRIJF TYPELENGTES */
+ strcpy(str, "TLEN");
+ dna_write(file, str, 4);
+
+ len= 2*nr_types;
+ if(nr_types & 1) len+= 2;
+ dna_write(file, typelens, len);
+
+ /* SCHRIJF STRUCTEN */
+ strcpy(str, "STRC");
+ dna_write(file, str, 4);
+ len= nr_structs;
+ dna_write(file, &len, 4);
+
+ /* lengte berekenen datablok */
+ sp= structs[nr_structs-1];
+ sp+= 2+ 2*( sp[1] );
+ len= (long)sp - (long)(structs[0]);
+ len= (len+3) & ~3;
+
+ dna_write(file, structs[0], len);
+
+ /* dna padding test */
+
+ if (0) {
+ FILE *fp;
+ int a;
+
+ fp= fopen("padding.c", "w");
+ if(fp==NULL);
+ else {
+
+ // add all include files defined in the global array
+ for (i = 0; strlen(includefiles[i]); i++) {
+ fprintf(fp, "#include \"%s\"\n", includefiles[i]);
+ }
+
+ fprintf(fp, "main(){\n");
+ sp = typelens;
+ sp += firststruct;
+ for(a=firststruct; a<nr_types; a++, sp++) {
+ fprintf(fp, "\tprintf(\" ");
+ fprintf(fp, "%%d %s %d ", types[a], *sp);
+ fprintf(fp, "\\n\", sizeof(struct %s) - %d);\n", types[a], *sp);
+ }
+ fprintf(fp, "}\n");
+ fclose(fp);
+ }
+ }
+ /* end end padding test */
+ }
+
+
+ MEM_freeN(namedata);
+ MEM_freeN(typedata);
+ MEM_freeN(structdata);
+ MEM_freeN(names);
+ MEM_freeN(types);
+ MEM_freeN(typelens);
+ MEM_freeN(structs);
+
+ if (debugSDNA > -1) printf("done.\n");
+
+ return(0);
+}
+
+/* ************************* END MAKEN DNA ********************** */
+
+void make_bad_file(char *file)
+{
+ FILE *fp= fopen(file, "w");
+ fprintf(fp, "NO NO NO! YOUR STUPID STUPID STUPID!\n");
+ fclose(fp);
+}
+
+int main(int argc, char ** argv)
+{
+ FILE *file;
+ int return_status = 0;
+
+ if (argc != 2) {
+ printf("Usage: %s outfile.c\n", argv[0]);
+ return_status = 1;
+ } else {
+ file = fopen(argv[1], "w");
+ if (!file) {
+ printf ("Unable to open file: %s\n", argv[1]);
+ return_status = 1;
+ } else {
+ fprintf (file, "unsigned char DNAstr[]= {\n");
+ if (make_structDNA(file)) {
+ // error
+ fclose(file);
+ make_bad_file(argv[1]);
+ return_status = 1;
+ } else {
+ fprintf(file, "};\n");
+ fprintf(file, "int DNAlen= sizeof(DNAstr);\n");
+
+ fclose(file);
+ }
+ }
+ }
+
+
+ return(return_status);
+}
+
+// include files for automatic dependancies
+#include "DNA_listBase.h"
+#include "DNA_vec_types.h"
+#include "DNA_ID.h"
+#include "DNA_ipo_types.h"
+#include "DNA_key_types.h"
+#include "DNA_scriptlink_types.h"
+#include "DNA_text_types.h"
+#include "DNA_packedFile_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_image_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_wave_types.h"
+#include "DNA_material_types.h"
+#include "DNA_vfont_types.h"
+#include "DNA_meta_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_lattice_types.h"
+#include "DNA_object_types.h"
+#include "DNA_world_types.h"
+#include "DNA_radio_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_view2d_types.h"
+#include "DNA_space_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_sdna_types.h"
+#include "DNA_fileglobal_types.h"
+#include "DNA_sequence_types.h"
+#include "DNA_effect_types.h"
+#include "DNA_ika_types.h"
+#include "DNA_oops_types.h"
+#include "DNA_property_types.h"
+#include "DNA_sensor_types.h"
+#include "DNA_controller_types.h"
+#include "DNA_actuator_types.h"
+#include "DNA_sound_types.h"
+#include "DNA_group_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_action_types.h"
+#include "DNA_constraint_types.h"
+#include "DNA_nla_types.h"
+/* end of list */
diff --git a/source/blender/misc/Makefile b/source/blender/misc/Makefile
new file mode 100644
index 00000000000..73b2c8f73b0
--- /dev/null
+++ b/source/blender/misc/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 *****
+#
+#
+
+LIBNAME = misc
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+CFLAGS += $(LEVEL_1_C_WARNINGS)
+
+ifeq ($(OS),$(findstring $(OS), "beos darwin freebsd linux openbsd solaris windows"))
+ CFLAGS += -funsigned-char
+endif
+
+CPPFLAGS += -I../include
+# very silly: this is needed just because blender.h is in the includes...
+CPPFLAGS += -I../render/extern/include
+CPPFLAGS += -I../blenkernel
+CPPFLAGS += -I../blenlib
+# not really needed...
+CPPFLAGS += -I../imbuf
+CPPFLAGS += -I../makesdna
+CPPFLAGS += -I..
+
diff --git a/source/blender/misc/blendertimer.c b/source/blender/misc/blendertimer.c
new file mode 100644
index 00000000000..02b42a866b0
--- /dev/null
+++ b/source/blender/misc/blendertimer.c
@@ -0,0 +1,77 @@
+/*
+ * blendertimer.c
+ *
+ * A system-independent timer
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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
+#include "BLI_winstuff.h"
+#else
+#include <unistd.h>
+#include <sys/times.h>
+#include <sys/time.h> /* struct timeval */
+#include <sys/resource.h> /* struct rusage */
+#endif
+
+#include "BLI_blenlib.h"
+#include "BKE_global.h"
+#include "BIF_screen.h" /* qtest(), extern_qread() */
+#include "mydevice.h"
+
+#include "blendertimer.h"
+
+#include "PIL_time.h"
+
+int MISC_test_break(void)
+{
+ if (!G.background) {
+ static double ltime= 0;
+ double curtime= PIL_check_seconds_timer();
+
+ /* only check for breaks every 10 milliseconds
+ * if we get called more often.
+ */
+ if ((curtime-ltime)>.001) {
+ ltime= curtime;
+
+ while(qtest()) {
+ short val;
+ if (extern_qread(&val) == ESCKEY) {
+ G.afbreek= 1;
+ }
+ }
+ }
+ }
+
+ return (G.afbreek==1);
+}
diff --git a/source/blender/misc/blendertimer.h b/source/blender/misc/blendertimer.h
new file mode 100644
index 00000000000..77205e365e3
--- /dev/null
+++ b/source/blender/misc/blendertimer.h
@@ -0,0 +1,51 @@
+/*
+ * blendertimer.h
+ *
+ * A system-independent timer
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BLENDERTIMER_H
+#define BLENDERTIMER_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int MISC_test_break(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/source/blender/radiosity/Makefile b/source/blender/radiosity/Makefile
new file mode 100644
index 00000000000..9bbb20c3db4
--- /dev/null
+++ b/source/blender/radiosity/Makefile
@@ -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 *****
+#
+# Makes module object directory and bounces make to subdirectories.
+
+SOURCEDIR = source/blender/radiosity
+DIRS = intern
+
+include nan_subdirs.mk
diff --git a/source/blender/radiosity/extern/include/radio.h b/source/blender/radiosity/extern/include/radio.h
new file mode 100644
index 00000000000..de8fc82195b
--- /dev/null
+++ b/source/blender/radiosity/extern/include/radio.h
@@ -0,0 +1,170 @@
+/* ***************************************
+
+
+
+ radio.h nov/dec 1992
+ revised for Blender may 1999
+
+ $Id$
+
+ ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version. The Blender
+ Foundation also sells licenses for use in proprietary software under
+ the Blender License. See http://www.blender.org/BL/ for information
+ about this.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ The Original Code is Copyright (C) 2001-2002 by 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 RADIO_H
+#define RADIO_H
+#define RADIO_H
+
+/* type include */
+#include "radio_types.h"
+
+extern RadGlobal RG;
+
+/* radfactors.c */
+extern float calcStokefactor(RPatch *shoot, RPatch *rp, RNode *rn, float *area);
+extern void calcTopfactors(void);
+void calcSidefactors(void);
+extern void initradiosity(void);
+extern void rad_make_hocos(RadView *vw);
+extern void hemizbuf(RadView *vw);
+extern int makeformfactors(RPatch *shoot);
+extern void applyformfactors(RPatch *shoot);
+extern RPatch *findshootpatch(void);
+extern void setnodeflags(RNode *rn, int flag, int set);
+extern void backface_test(RPatch *shoot);
+extern void clear_backface_test(void);
+extern void progressiverad(void);
+extern void minmaxradelem(RNode *rn, float *min, float *max);
+extern void minmaxradelemfilt(RNode *rn, float *min, float *max, float *errmin, float *errmax);
+extern void subdivideshootElements(int it);
+extern void subdivideshootPatches(int it);
+extern void inithemiwindows(void);
+extern void closehemiwindows(void);
+void rad_init_energy(void);
+
+/* radio.c */
+void freeAllRad(void);
+int rad_phase(void);
+void rad_status_str(char *str);
+void rad_printstatus(void);
+void rad_setlimits(void);
+void set_radglobal(void);
+void add_radio(void);
+void delete_radio(void);
+int rad_go(void);
+void rad_subdivshootpatch(void);
+void rad_subdivshootelem(void);
+void rad_limit_subdivide(void);
+
+/* radnode.c */
+extern void setnodelimit(float limit);
+extern float *mallocVert(void);
+extern float *callocVert(void);
+extern void freeVert(float *vert);
+extern RNode *mallocNode(void);
+extern RNode *callocNode(void);
+extern void freeNode(RNode *node);
+extern void freeNode_recurs(RNode *node);
+extern RPatch *mallocPatch(void);
+extern RPatch *callocPatch(void);
+extern void freePatch(RPatch *patch);
+extern void replaceAllNode(RNode *, RNode *);
+extern void replaceAllNodeInv(RNode *neighb, RNode *old);
+extern void replaceAllNodeUp(RNode *neighb, RNode *old);
+extern void replaceTestNode(RNode *, RNode **, RNode *, int , float *);
+extern void free_fastAll(void);
+
+/* radnode.c */
+extern void start_fastmalloc(char *str);
+extern int setvertexpointersNode(RNode *neighb, RNode *node, int level, float **v1, float **v2);
+extern float edlen(float *v1, float *v2);
+extern void deleteNodes(RNode *node);
+extern void subdivideTriNode(RNode *node, RNode *edge);
+extern void subdivideNode(RNode *node, RNode *edge);
+extern int comparelevel(RNode *node, RNode *nb, int level);
+
+/* radpreprocess.c */
+extern void splitconnected(void);
+extern int vergedge(const void *v1,const void *v2);
+extern void addedge(float *v1, float *v2, EdSort *es);
+extern void setedgepointers(void);
+extern void rad_collect_meshes(void);
+extern void countelem(RNode *rn);
+extern void countglobaldata(void);
+extern void addelem(RNode ***el, RNode *rn, RPatch *rp);
+extern void makeGlobalElemArray(void);
+extern void remakeGlobaldata(void);
+extern void splitpatch(RPatch *old);
+extern void addpatch(RPatch *old, RNode *rn);
+extern void converttopatches(void);
+extern void make_elements(void);
+extern void subdividelamps(void);
+extern void maxsizePatches(void);
+extern void subdiv_elements(void);
+
+/* radpostprocess.c */
+void addaccu(register char *z, register char *t);
+void addaccuweight(register char *z, register char *t, int w);
+void triaweight(Face *face, int *w1, int *w2, int *w3);
+void init_face_tab(void);
+Face *addface(void);
+void makeface(float *v1, float *v2, float *v3, float *v4, RNode *rn);
+void anchorQuadface(RNode *rn, float *v1, float *v2, float *v3, float *v4, int flag);
+void anchorTriface(RNode *rn, float *v1, float *v2, float *v3, int flag);
+float *findmiddlevertex(RNode *node, RNode *nb, float *v1, float *v2);
+void make_face_tab(void);
+void filterFaces(void);
+void calcfiltrad(RNode *rn, float *cd);
+void filterNodes(void);
+void removeEqualNodes(short limit);
+void rad_addmesh(void);
+void rad_replacemesh(void);
+
+/* raddisplay.c */
+extern char calculatecolor(float col);
+extern void make_node_display(void);
+extern void drawnodeWire(RNode *rn);
+extern void drawsingnodeWire(RNode *rn);
+extern void drawnodeSolid(RNode *rn);
+extern void drawnodeGour(RNode *rn);
+extern void drawpatch(RPatch *patch, unsigned int col);
+extern void drawnode_ext(RNode *rn, unsigned int col);
+extern void drawOverflowElem(void);
+extern void drawfaceGour(Face *face);
+extern void drawfaceSolid(Face *face);
+extern void drawfaceWire(Face *face);
+extern void drawsquare(float *cent, float size, short cox, short coy);
+extern void drawlimits(void);
+extern void setcolNode(RNode *rn, unsigned int *col);
+extern void pseudoAmb(void);
+extern void rad_forcedraw(void);
+extern void drawpatch_ext(RPatch *patch, unsigned int col);
+
+extern void RAD_drawall(int depth_is_on);
+
+#endif /* RADIO_H */
diff --git a/source/blender/radiosity/extern/include/radio_types.h b/source/blender/radiosity/extern/include/radio_types.h
new file mode 100644
index 00000000000..c687188c889
--- /dev/null
+++ b/source/blender/radiosity/extern/include/radio_types.h
@@ -0,0 +1,174 @@
+/*
+ * radio_types.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "misc_util.h" */ /* for listbase...*/
+
+
+#ifndef RADIO_TYPES_H
+#define RADIO_TYPES_H
+
+#include "DNA_listBase.h"
+#include "DNA_material_types.h"
+
+#define DTWIRE 0
+#define DTGOUR 2
+#define DTSOLID 1
+
+#define PI M_PI
+#define RAD_MAXFACETAB 1024
+#define RAD_NEXTFACE(a) if( ((a) & 1023)==0 ) face= RG.facebase[(a)>>10]; else face++;
+
+/* RG.phase */
+#define RAD_SHOOTE 1
+#define RAD_SHOOTP 2
+#define RAD_SOLVE 3
+
+typedef struct RadView {
+ float cam[3], tar[3], up[3];
+ float wx1, wx2, wy1, wy2;
+ float mynear, myfar;
+ float viewmat[4][4], winmat[4][4];
+ unsigned int *rect, *rectz;
+ short rectx, recty;
+ int wid;
+
+} RadView;
+
+/* rn->f */
+#define RAD_PATCH 1
+#define RAD_SHOOT 2
+#define RAD_SUBDIV 4
+#define RAD_BACKFACE 8
+
+
+typedef struct RNode { /* lengte: 76 */
+ struct RNode *down1, *down2, *up;
+ struct RNode *ed1, *ed2, *ed3, *ed4;
+ struct RPatch *par;
+
+ char lev1, lev2, lev3, lev4; /* edgelevels */
+ short type; /* type: 4==QUAD, 3==TRIA */
+ short f;
+ float *v1, *v2, *v3, *v4;
+ float totrad[3], area;
+
+ unsigned int col;
+} RNode;
+
+
+typedef struct Elem { /* lengte: 44 */
+ struct RPatch *par;
+
+ short type; /* type: 4==QUAD, 3==TRIA */
+ short f; /* bit 0: patch, bit 1: shootelement */
+ float *v1, *v2, *v3, *v4;
+ float totrad[3], area;
+
+ unsigned int col;
+} Elem;
+
+
+typedef struct Face { /* lengte: 24 */
+ float *v1, *v2, *v3, *v4;
+ unsigned int col, matindex;
+} Face;
+
+/* rp->f1 */
+#define RAD_NO_SPLIT 1
+
+typedef struct RPatch {
+ struct RPatch *next, *prev;
+ RNode *first; /* first node==patch */
+
+ struct Object *from;
+
+ int type; /* 3: TRIA, 4: QUAD */
+ short f, f1; /* flags f: als node, alleen subdiv */
+
+ float ref[3], emit[3], unshot[3];
+ float cent[3], norm[3];
+ float area;
+ int matindex;
+
+} RPatch;
+
+
+typedef struct VeNoCo { /* nodig voor splitconnected */
+ struct VeNoCo *next;
+ float *v;
+ float *n;
+ float *col;
+ int flag;
+} VeNoCo;
+
+
+typedef struct EdSort { /* sorteren edges */
+ float *v1, *v2;
+ RNode *node;
+ int nr;
+} EdSort;
+
+typedef struct {
+ struct Radio *radio;
+ unsigned int *hemibuf;
+ struct ListBase patchbase;
+ int totpatch, totelem, totvert, totlamp;
+ RNode **elem; /* globaal array van alle pointers */
+ VeNoCo *verts; /* tijdelijk vertices van patches */
+ float *formfactors; /* een factor per element */
+ float *topfactors, *sidefactors; /* LUT voor delta's */
+ int *index; /* LUT voor bovenstaande LUT */
+ Face **facebase;
+ int totface;
+ float min[3], max[3], size[3], cent[3]; /* world */
+ float maxsize, totenergy;
+ float patchmin, patchmax;
+ float elemmin, elemmax;
+ float radfactor, lostenergy, igamma; /* radfac zit in button, radfactor wordt berekend */
+ int phase;
+ /* to preserve materials as used before, max 16 */
+ Material *matar[MAXMAT];
+ int totmat;
+
+ /* this part is a copy of struct Radio */
+ short hemires, maxiter;
+ short drawtype, flag; /* bit 0 en 1: limits laten zien */
+ short subshootp, subshoote, nodelim, maxsublamp;
+ int maxnode;
+ float convergence;
+ float radfac, gamma; /* voor afbeelden */
+
+} RadGlobal;
+
+#endif /* radio_types.h */
diff --git a/source/blender/radiosity/intern/Makefile b/source/blender/radiosity/intern/Makefile
new file mode 100644
index 00000000000..fde495bed85
--- /dev/null
+++ b/source/blender/radiosity/intern/Makefile
@@ -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 *****
+#
+# Makes module object directory and bounces make to subdirectories.
+
+SOURCEDIR = source/blender/radiosity/intern
+DIRS = source
+
+include nan_subdirs.mk
diff --git a/source/blender/radiosity/intern/source/Makefile b/source/blender/radiosity/intern/source/Makefile
new file mode 100644
index 00000000000..e0bb43772c2
--- /dev/null
+++ b/source/blender/radiosity/intern/source/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 *****
+#
+# radiosity uses the render lib
+#
+
+LIBNAME = radiosity
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+ifeq ($(OS),$(findstring $(OS), "beos darwin freebsd linux openbsd solaris windows"))
+ CFLAGS += -funsigned-char
+endif
+
+CFLAGS += $(LEVEL_1_C_WARNINGS)
+
+CPPFLAGS += -I$(OPENGL_HEADERS)
+
+# not very neat....
+CPPFLAGS += -I../../../blenkernel
+CPPFLAGS += -I../../../blenlib
+CPPFLAGS += -I../../../makesdna
+CPPFLAGS += -I../../../imbuf
+CPPFLAGS += -I../../../
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+
+# first /include is my own includes, second are the external includes
+# third is the external interface. there should be a nicer way to say this
+CPPFLAGS += -I../include -I../../../include -I../../extern/include
+CPPFLAGS += -I../../../render/extern/include -I../../../misc
+
diff --git a/source/blender/radiosity/intern/source/raddisplay.c b/source/blender/radiosity/intern/source/raddisplay.c
new file mode 100644
index 00000000000..b2689cf2ad6
--- /dev/null
+++ b/source/blender/radiosity/intern/source/raddisplay.c
@@ -0,0 +1,527 @@
+/* ***************************************
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+
+
+
+ raddisplay.c nov/dec 1992
+ may 1999
+
+ - drawing
+ - color calculation for display during solving
+
+ $Id$
+
+ *************************************** */
+
+#include <stdlib.h>
+#include <math.h>
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+#include "BLI_blenlib.h"
+
+#include "DNA_screen_types.h"
+#include "DNA_view3d_types.h"
+
+#include "BKE_global.h"
+#include "BKE_main.h"
+
+#include "BIF_gl.h"
+#include "BIF_screen.h"
+#include "BIF_space.h"
+#include "BIF_mywindow.h"
+
+#include "radio.h"
+
+/* Mij afspraak is cpack een getal dat als 0xFFaa66 of zo kan worden
+ * uitgedrukt. Is dus gevoelig voor endian. Met deze define wordt het
+ * altijd goed afgebeeld */
+#define cpack(x) glColor3ub( ((x)&0xFF), (((x)>>8)&0xFF), (((x)>>16)&0xFF) )
+
+char calculatecolor(float col)
+{
+ int b;
+
+ if(RG.gamma==1.0) {
+ b= RG.radfactor*col;
+ }
+ else if(RG.gamma==2.0) {
+ b= RG.radfactor*sqrt(col);
+ }
+ else {
+ b= RG.radfactor*pow(col, RG.igamma);
+ }
+
+ if(b>255) b=255;
+ return b;
+}
+
+void make_node_display()
+{
+ RNode *rn, **el;
+ int a;
+ char *charcol;
+
+ RG.igamma= 1.0/RG.gamma;
+ RG.radfactor= RG.radfac*pow(64*64, RG.igamma);
+
+ el= RG.elem;
+ for(a=RG.totelem; a>0; a--, el++) {
+ rn= *el;
+ charcol= (char *)&( rn->col );
+
+ charcol[3]= calculatecolor(rn->totrad[0]);
+ charcol[2]= calculatecolor(rn->totrad[1]);
+ charcol[1]= calculatecolor(rn->totrad[2]);
+
+ /* gouraudcolor */
+ *(rn->v1+3)= 0;
+ *(rn->v2+3)= 0;
+ *(rn->v3+3)= 0;
+ if(rn->v4) *(rn->v4+3)= 0;
+ }
+
+ el= RG.elem;
+ for(a=RG.totelem; a>0; a--, el++) {
+ rn= *el;
+ addaccuweight( (char *)&(rn->col), (char *)(rn->v1+3), 16 );
+ addaccuweight( (char *)&(rn->col), (char *)(rn->v2+3), 16 );
+ addaccuweight( (char *)&(rn->col), (char *)(rn->v3+3), 16 );
+ if(rn->v4) addaccuweight( (char *)&(rn->col), (char *)(rn->v4+3), 16 );
+ }
+}
+
+void drawnodeWire(RNode *rn)
+{
+
+ if(rn->down1) {
+ drawnodeWire(rn->down1);
+ drawnodeWire(rn->down2);
+ }
+ else {
+ glBegin(GL_LINE_LOOP);
+ glVertex3fv(rn->v1);
+ glVertex3fv(rn->v2);
+ glVertex3fv(rn->v3);
+ if(rn->type==4) glVertex3fv(rn->v4);
+ glEnd();
+ }
+}
+
+void drawsingnodeWire(RNode *rn)
+{
+
+ glBegin(GL_LINE_LOOP);
+ glVertex3fv(rn->v1);
+ glVertex3fv(rn->v2);
+ glVertex3fv(rn->v3);
+ if(rn->type==4) glVertex3fv(rn->v4);
+ glEnd();
+}
+
+void drawnodeSolid(RNode *rn)
+{
+ char *cp;
+
+ if(rn->down1) {
+ drawnodeSolid(rn->down1);
+ drawnodeSolid(rn->down2);
+ }
+ else {
+ cp= (char *)&rn->col;
+ glColor3ub(cp[3], cp[2], cp[1]);
+ glBegin(GL_POLYGON);
+ glVertex3fv(rn->v1);
+ glVertex3fv(rn->v2);
+ glVertex3fv(rn->v3);
+ if(rn->type==4) glVertex3fv(rn->v4);
+ glEnd();
+ }
+}
+
+void drawnodeGour(RNode *rn)
+{
+ char *cp;
+
+ if(rn->down1) {
+ drawnodeGour(rn->down1);
+ drawnodeGour(rn->down2);
+ }
+ else {
+ glBegin(GL_POLYGON);
+ cp= (char *)(rn->v1+3);
+ glColor3ub(cp[3], cp[2], cp[1]);
+ glVertex3fv(rn->v1);
+
+ cp= (char *)(rn->v2+3);
+ glColor3ub(cp[3], cp[2], cp[1]);
+ glVertex3fv(rn->v2);
+
+ cp= (char *)(rn->v3+3);
+ glColor3ub(cp[3], cp[2], cp[1]);
+ glVertex3fv(rn->v3);
+
+ if(rn->type==4) {
+ cp= (char *)(rn->v4+3);
+ glColor3ub(cp[3], cp[2], cp[1]);
+ glVertex3fv(rn->v4);
+ }
+ glEnd();
+ }
+}
+
+void drawpatch_ext(RPatch *patch, unsigned int col)
+{
+ ScrArea *sa, *oldsa;
+
+ glDrawBuffer(GL_FRONT);
+ if(G.zbuf) glDisable(GL_DEPTH_TEST);
+
+ cpack(col);
+
+ oldsa= curarea;
+
+ sa= G.curscreen->areabase.first;
+ while(sa) {
+ if (sa->spacetype==SPACE_VIEW3D) {
+ /* hier mywinget() gebruiken: anders wordt in header getekend */
+ if(sa->win != mywinget()) areawinset(sa->win);
+ drawnodeWire(patch->first);
+ }
+ sa= sa->next;
+ }
+
+ if(oldsa && oldsa!=curarea) areawinset(oldsa->win);
+
+ glDrawBuffer(GL_BACK);
+ if(G.zbuf) glEnable(GL_DEPTH_TEST);
+}
+
+void drawnode_ext(RNode *rn, unsigned int col)
+{
+
+ glDrawBuffer(GL_FRONT);
+ if(G.zbuf) glDisable(GL_DEPTH_TEST);
+
+ cpack(col);
+
+ drawnodeWire(rn);
+
+ glDrawBuffer(GL_BACK);
+ if(G.zbuf) glEnable(GL_DEPTH_TEST);
+}
+
+void drawOverflowElem()
+{
+ RNode **el, *rn;
+ float *fp;
+ int a;
+
+ glDrawBuffer(GL_FRONT);
+ if(G.zbuf) glDisable(GL_DEPTH_TEST);
+
+ cpack(0xFF9900);
+
+ el= RG.elem;
+ fp= RG.formfactors;
+ for(a=0; a<RG.totelem; a++, el++, fp++) {
+ if(*fp>1.0) {
+ rn= *el;
+ glBegin(GL_LINE_LOOP);
+ glVertex3fv( rn->v1);
+ glVertex3fv( rn->v2);
+ glVertex3fv( rn->v3);
+ if(rn->type==4) glVertex3fv( rn->v4);
+ glEnd();
+ }
+ }
+
+ glDrawBuffer(GL_BACK);
+ if(G.zbuf) glEnable(GL_DEPTH_TEST);
+}
+
+void drawfaceGour(Face *face)
+{
+ char *cp;
+
+ glBegin(GL_POLYGON);
+ cp= (char *)(face->v1+3);
+ glColor3ub(cp[3], cp[2], cp[1]);
+ glVertex3fv(face->v1);
+
+ cp= (char *)(face->v2+3);
+ glColor3ub(cp[3], cp[2], cp[1]);
+ glVertex3fv(face->v2);
+
+ cp= (char *)(face->v3+3);
+ glColor3ub(cp[3], cp[2], cp[1]);
+ glVertex3fv(face->v3);
+
+ if(face->v4) {
+ cp= (char *)(face->v4+3);
+ glColor3ub(cp[3], cp[2], cp[1]);
+ glVertex3fv(face->v4);
+ }
+ glEnd();
+
+}
+
+void drawfaceSolid(Face *face)
+{
+ char *cp;
+
+ cp= (char *)&face->col;
+ glColor3ub(cp[3], cp[2], cp[1]);
+
+ glBegin(GL_POLYGON);
+ glVertex3fv(face->v1);
+ glVertex3fv(face->v2);
+ glVertex3fv(face->v3);
+ if(face->v4) {
+ glVertex3fv(face->v4);
+ }
+ glEnd();
+
+}
+
+void drawfaceWire(Face *face)
+{
+ char *cp;
+
+ cp= (char *)&face->col;
+ glColor3ub(cp[3], cp[2], cp[1]);
+
+ glBegin(GL_LINE_LOOP);
+ glVertex3fv(face->v1);
+ glVertex3fv(face->v2);
+ glVertex3fv(face->v3);
+ if(face->v4) {
+ glVertex3fv(face->v4);
+ }
+ glEnd();
+
+}
+
+void drawsquare(float *cent, float size, short cox, short coy)
+{
+ float vec[3];
+
+ vec[0]= cent[0];
+ vec[1]= cent[1];
+ vec[2]= cent[2];
+
+ glBegin(GL_LINE_LOOP);
+ vec[cox]+= .5*size;
+ vec[coy]+= .5*size;
+ glVertex3fv(vec);
+ vec[coy]-= size;
+ glVertex3fv(vec);
+ vec[cox]-= size;
+ glVertex3fv(vec);
+ vec[coy]+= size;
+ glVertex3fv(vec);
+ glEnd();
+}
+
+void drawlimits()
+{
+ /* centreer rond cent */
+ short cox=0, coy=1;
+
+ if((RG.flag & 3)==2) coy= 2;
+ if((RG.flag & 3)==3) {
+ cox= 1;
+ coy= 2;
+ }
+
+ cpack(0);
+ drawsquare(RG.cent, sqrt(RG.patchmax), cox, coy);
+ drawsquare(RG.cent, sqrt(RG.patchmin), cox, coy);
+
+ drawsquare(RG.cent, sqrt(RG.elemmax), cox, coy);
+ drawsquare(RG.cent, sqrt(RG.elemmin), cox, coy);
+
+ cpack(0xFFFFFF);
+ drawsquare(RG.cent, sqrt(RG.patchmax), cox, coy);
+ drawsquare(RG.cent, sqrt(RG.patchmin), cox, coy);
+ cpack(0xFFFF00);
+ drawsquare(RG.cent, sqrt(RG.elemmax), cox, coy);
+ drawsquare(RG.cent, sqrt(RG.elemmin), cox, coy);
+
+}
+
+void setcolNode(RNode *rn, unsigned int *col)
+{
+
+ if(rn->down1) {
+ setcolNode(rn->down1, col);
+ setcolNode(rn->down2, col);
+ }
+ rn->col= *col;
+
+ *((unsigned int *)rn->v1+3)= *col;
+ *((unsigned int *)rn->v2+3)= *col;
+ *((unsigned int *)rn->v3+3)= *col;
+ if(rn->v4) *((unsigned int *)rn->v4+3)= *col;
+}
+
+void pseudoAmb()
+{
+ RPatch *rp;
+ float fac;
+ char col[4];
+
+ /* zet pseudo ambient kleuren in de nodes */
+
+ rp= RG.patchbase.first;
+ while(rp) {
+
+ if(rp->emit[0]!=0.0 || rp->emit[1]!=0.0 || rp->emit[2]!=0.0) {
+ col[1]= col[2]= col[3]= 255;
+ }
+ else {
+ fac= rp->norm[0]+ rp->norm[1]+ rp->norm[2];
+ fac= 225.0*(3+fac)/6.0;
+
+ col[3]= fac*rp->ref[0];
+ col[2]= fac*rp->ref[1];
+ col[1]= fac*rp->ref[2];
+ }
+
+ setcolNode(rp->first, (unsigned int *)col);
+
+ rp= rp->next;
+ }
+}
+
+void RAD_drawall(int depth_is_on)
+{
+ /* maakt afbeelding van elements of van faces */
+ Face *face = NULL;
+ RNode **el;
+ RPatch *rp;
+ int a;
+
+ if(!depth_is_on) {
+ glEnable(GL_DEPTH_TEST);
+ glClearDepth(1.0); glClear(GL_DEPTH_BUFFER_BIT);
+ }
+
+ if(RG.totface) {
+ if(RG.drawtype==DTGOUR) {
+ glShadeModel(GL_SMOOTH);
+ for(a=0; a<RG.totface; a++) {
+ RAD_NEXTFACE(a);
+
+ drawfaceGour(face);
+ }
+ }
+ else if(RG.drawtype==DTSOLID) {
+ for(a=0; a<RG.totface; a++) {
+ RAD_NEXTFACE(a);
+
+ drawfaceSolid(face);
+ }
+ }
+ else {
+ if(!(get_qual()&LR_SHIFTKEY)) {
+
+ for(a=0; a<RG.totface; a++) {
+ RAD_NEXTFACE(a);
+
+ drawfaceWire(face);
+ }
+ }
+ else {
+ cpack(0);
+ rp= RG.patchbase.first;
+ while(rp) {
+ drawsingnodeWire(rp->first);
+ rp= rp->next;
+ }
+ }
+ }
+ }
+ else {
+ el= RG.elem;
+ if(RG.drawtype==DTGOUR) {
+ glShadeModel(GL_SMOOTH);
+ for(a=RG.totelem; a>0; a--, el++) {
+ drawnodeGour(*el);
+ }
+ }
+ else if(RG.drawtype==DTSOLID) {
+ for(a=RG.totelem; a>0; a--, el++) {
+ drawnodeSolid(*el);
+ }
+ }
+ else {
+ cpack(0);
+ for(a=RG.totelem; a>0; a--, el++) {
+ drawnodeWire(*el);
+ }
+ }
+ }
+ glShadeModel(GL_FLAT);
+
+ if(RG.totpatch) {
+ if(RG.flag & 3) {
+ if(depth_is_on) glDisable(GL_DEPTH_TEST);
+ drawlimits();
+ if(depth_is_on) glEnable(GL_DEPTH_TEST);
+ }
+ }
+ if(!depth_is_on) {
+ glDisable(GL_DEPTH_TEST);
+ }
+}
+
+void rad_forcedraw()
+{
+ ScrArea *sa, *oldsa;
+
+ oldsa= curarea;
+
+ sa= G.curscreen->areabase.first;
+ while(sa) {
+ if (sa->spacetype==SPACE_VIEW3D) {
+ /* hier mywinget() gebruiken: anders wordt in header getekend */
+ if(sa->win != mywinget()) areawinset(sa->win);
+ scrarea_do_windraw(sa);
+ }
+ sa= sa->next;
+ }
+ screen_swapbuffers();
+
+ if(oldsa && oldsa!=curarea) areawinset(oldsa->win);
+}
+
diff --git a/source/blender/radiosity/intern/source/radfactors.c b/source/blender/radiosity/intern/source/radfactors.c
new file mode 100644
index 00000000000..2f6ac2043c2
--- /dev/null
+++ b/source/blender/radiosity/intern/source/radfactors.c
@@ -0,0 +1,956 @@
+/* ***************************************
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+
+
+
+ formfactors.c nov/dec 1992
+
+ $Id$
+
+ *************************************** */
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_rand.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+
+#include "BIF_screen.h"
+
+#include "radio.h"
+#include "render.h" /* for `RE_zbufferall_radio and RE_zbufferall_radio */
+#include "blendertimer.h" /* timer functions */
+
+/* locals */
+void rad_setmatrices(RadView *vw);
+void clearsubflagelem(RNode *rn);
+void setsubflagelem(RNode *rn);
+
+RadView hemitop, hemiside;
+
+float calcStokefactor(RPatch *shoot, RPatch *rp, RNode *rn, float *area)
+{
+ float tvec[3], fac;
+ float vec[4][3]; /* vectoren van shootcent naar vertices rp */
+ float cross[4][3]; /* uitprodukten hiervan */
+ float rad[4]; /* hoeken tussen vecs */
+
+ /* test op richting */
+ VecSubf(tvec, shoot->cent, rp->cent);
+ if( tvec[0]*shoot->norm[0]+ tvec[1]*shoot->norm[1]+ tvec[2]*shoot->norm[2]>0.0)
+ return 0.0;
+
+ if(rp->type==4) {
+
+ /* hoekvectors */
+ VecSubf(vec[0], shoot->cent, rn->v1);
+ VecSubf(vec[1], shoot->cent, rn->v2);
+ VecSubf(vec[2], shoot->cent, rn->v3);
+ VecSubf(vec[3], shoot->cent, rn->v4);
+
+ Normalise(vec[0]);
+ Normalise(vec[1]);
+ Normalise(vec[2]);
+ Normalise(vec[3]);
+
+ /* uitprod */
+ Crossf(cross[0], vec[0], vec[1]);
+ Crossf(cross[1], vec[1], vec[2]);
+ Crossf(cross[2], vec[2], vec[3]);
+ Crossf(cross[3], vec[3], vec[0]);
+ Normalise(cross[0]);
+ Normalise(cross[1]);
+ Normalise(cross[2]);
+ Normalise(cross[3]);
+
+ /* hoeken */
+ rad[0]= vec[0][0]*vec[1][0]+ vec[0][1]*vec[1][1]+ vec[0][2]*vec[1][2];
+ rad[1]= vec[1][0]*vec[2][0]+ vec[1][1]*vec[2][1]+ vec[1][2]*vec[2][2];
+ rad[2]= vec[2][0]*vec[3][0]+ vec[2][1]*vec[3][1]+ vec[2][2]*vec[3][2];
+ rad[3]= vec[3][0]*vec[0][0]+ vec[3][1]*vec[0][1]+ vec[3][2]*vec[0][2];
+
+ rad[0]= acos(rad[0]);
+ rad[1]= acos(rad[1]);
+ rad[2]= acos(rad[2]);
+ rad[3]= acos(rad[3]);
+
+ /* Stoke formule */
+ VecMulf(cross[0], rad[0]);
+ VecMulf(cross[1], rad[1]);
+ VecMulf(cross[2], rad[2]);
+ VecMulf(cross[3], rad[3]);
+
+ VECCOPY(tvec, shoot->norm);
+ fac= tvec[0]*cross[0][0]+ tvec[1]*cross[0][1]+ tvec[2]*cross[0][2];
+ fac+= tvec[0]*cross[1][0]+ tvec[1]*cross[1][1]+ tvec[2]*cross[1][2];
+ fac+= tvec[0]*cross[2][0]+ tvec[1]*cross[2][1]+ tvec[2]*cross[2][2];
+ fac+= tvec[0]*cross[3][0]+ tvec[1]*cross[3][1]+ tvec[2]*cross[3][2];
+ }
+ else {
+ /* hoekvectors */
+ VecSubf(vec[0], shoot->cent, rn->v1);
+ VecSubf(vec[1], shoot->cent, rn->v2);
+ VecSubf(vec[2], shoot->cent, rn->v3);
+
+ Normalise(vec[0]);
+ Normalise(vec[1]);
+ Normalise(vec[2]);
+
+ /* uitprod */
+ Crossf(cross[0], vec[0], vec[1]);
+ Crossf(cross[1], vec[1], vec[2]);
+ Crossf(cross[2], vec[2], vec[0]);
+ Normalise(cross[0]);
+ Normalise(cross[1]);
+ Normalise(cross[2]);
+
+ /* hoeken */
+ rad[0]= vec[0][0]*vec[1][0]+ vec[0][1]*vec[1][1]+ vec[0][2]*vec[1][2];
+ rad[1]= vec[1][0]*vec[2][0]+ vec[1][1]*vec[2][1]+ vec[1][2]*vec[2][2];
+ rad[2]= vec[2][0]*vec[0][0]+ vec[2][1]*vec[0][1]+ vec[2][2]*vec[0][2];
+
+ rad[0]= acos(rad[0]);
+ rad[1]= acos(rad[1]);
+ rad[2]= acos(rad[2]);
+
+ /* Stoke formule */
+ VecMulf(cross[0], rad[0]);
+ VecMulf(cross[1], rad[1]);
+ VecMulf(cross[2], rad[2]);
+
+ VECCOPY(tvec, shoot->norm);
+ fac= tvec[0]*cross[0][0]+ tvec[1]*cross[0][1]+ tvec[2]*cross[0][2];
+ fac+= tvec[0]*cross[1][0]+ tvec[1]*cross[1][1]+ tvec[2]*cross[1][2];
+ fac+= tvec[0]*cross[2][0]+ tvec[1]*cross[2][1]+ tvec[2]*cross[2][2];
+ }
+
+ *area= -fac/(2.0*PI);
+ return (*area * (shoot->area/rn->area));
+}
+
+
+void calcTopfactors()
+{
+ float xsq , ysq, xysq;
+ float n;
+ float *fp;
+ int a, b, hres;
+
+ fp = RG.topfactors;
+ hres= RG.hemires/2;
+ n= hres;
+
+ for (a=0; a<hres; a++) {
+
+ ysq= (n- ((float)a+0.5))/n;
+ ysq*= ysq;
+
+ for ( b=0 ; b<hres ; b++ ) {
+
+ xsq= ( n-((float)b+ 0.5) )/n;
+ xsq*= xsq;
+ xysq= xsq+ ysq+ 1.0 ;
+ xysq*= xysq;
+
+ *fp++ = 1.0/(xysq* PI* n*n);
+ }
+ }
+
+}
+
+void calcSidefactors()
+{
+ float xsq , ysq, xysq;
+ float n, y;
+ float *fp;
+ int a, b, hres;
+
+ fp = RG.sidefactors;
+ hres= RG.hemires/2;
+ n= hres;
+
+ for (a=0; a<hres; a++) {
+
+ y= (n- ((float)a+0.5))/n;
+ ysq= y*y;
+
+ for ( b=0 ; b<hres ; b++ ) {
+
+ xsq= ( n-((float)b+ 0.5) )/n;
+ xsq*= xsq;
+ xysq= xsq+ ysq+ 1.0 ;
+ xysq*= xysq;
+
+ *fp++ = y/(xysq* PI* n*n);
+ }
+ }
+
+}
+
+
+void initradiosity()
+{
+ /* alloceert en maakt LUTs voor top/side factors */
+ /* alloceert en maakt index array */
+ int a, hres2;
+
+ if(RG.topfactors) MEM_freeN(RG.topfactors);
+ if(RG.sidefactors) MEM_freeN(RG.sidefactors);
+ if(RG.index) MEM_freeN(RG.index);
+
+ RG.topfactors= MEM_callocN(RG.hemires*RG.hemires, "initradiosity");
+ calcTopfactors();
+ RG.sidefactors= MEM_callocN(RG.hemires*RG.hemires, "initradiosity1");
+ calcSidefactors();
+
+ RG.index= MEM_callocN(4*RG.hemires, "initradiosity3");
+ hres2= RG.hemires/2;
+ for(a=0; a<RG.hemires; a++) {
+ RG.index[a]= a<hres2 ? a: (hres2-1-( a % hres2 ));
+ }
+
+}
+
+void rad_make_hocos(RadView *vw)
+{
+ /* float hoco[4]; */
+ /* int a; */
+
+ /* for(a=0; a< R.totvert;a++) { */
+ /* projectvert(vec, ver->ho); */
+ /* ver->clip = testclip(ver->ho); */
+/* */
+ /* } */
+}
+
+void rad_setmatrices(RadView *vw) /* voor hemi's */
+{
+ float up1[3], len, twist;
+
+ i_lookat(vw->cam[0], vw->cam[1], vw->cam[2], vw->tar[0], vw->tar[1], vw->tar[2], 0, vw->viewmat);
+ up1[0] = vw->viewmat[0][0]*vw->up[0] + vw->viewmat[1][0]*vw->up[1] + vw->viewmat[2][0]*vw->up[2];
+ up1[1] = vw->viewmat[0][1]*vw->up[0] + vw->viewmat[1][1]*vw->up[1] + vw->viewmat[2][1]*vw->up[2];
+ up1[2] = vw->viewmat[0][2]*vw->up[0] + vw->viewmat[1][2]*vw->up[1] + vw->viewmat[2][2]*vw->up[2];
+
+ len= up1[0]*up1[0]+up1[1]*up1[1];
+ if(len>0.0) {
+ twist= -atan2(up1[0], up1[1]);
+ }
+ else twist= 0.0;
+
+ i_lookat(vw->cam[0], vw->cam[1], vw->cam[2], vw->tar[0], vw->tar[1], vw->tar[2], (180.0*twist/M_PI), vw->viewmat);
+
+ /* window matrix was set in inithemiwindows */
+
+}
+
+
+void hemizbuf(RadView *vw)
+{
+ float *factors;
+ unsigned int *rz;
+ int a, b, inda, hres;
+
+ rad_setmatrices(vw);
+ RE_zbufferall_radio(vw, RG.elem, RG.totelem);
+
+ /* factors tellen */
+ if(vw->recty==vw->rectx) factors= RG.topfactors;
+ else factors= RG.sidefactors;
+ hres= RG.hemires/2;
+
+ rz= vw->rect;
+ for(a=0; a<vw->recty; a++) {
+ inda= hres*RG.index[a];
+ for(b=0; b<vw->rectx; b++, rz++) {
+ if(*rz<RG.totelem) {
+ RG.formfactors[*rz]+= factors[inda+RG.index[b]];
+ }
+ }
+ }
+}
+
+int makeformfactors(RPatch *shoot)
+{
+ RNode **re;
+ float len, vec[3], up[3], side[3], tar[5][3], *fp;
+ int a, overfl;
+
+ if(RG.totelem==0) return 0;
+
+ memset(RG.formfactors, 0, 4*RG.totelem);
+
+ /* set up hemiview */
+ /* first: random upvector */
+ do {
+ vec[0]= (float)BLI_drand();
+ vec[1]= (float)BLI_drand();
+ vec[2]= (float)BLI_drand();
+ Crossf(up, shoot->norm, vec);
+ len= Normalise(up);
+ } while(len==0.0 || len>1.0);
+
+ VECCOPY(hemitop.up, up);
+ VECCOPY(hemiside.up, shoot->norm);
+
+ Crossf(side, shoot->norm, up);
+
+ /* five targets */
+ VecAddf(tar[0], shoot->cent, shoot->norm);
+ VecAddf(tar[1], shoot->cent, up);
+ VecSubf(tar[2], shoot->cent, up);
+ VecAddf(tar[3], shoot->cent, side);
+ VecSubf(tar[4], shoot->cent, side);
+
+ /* camera */
+ VECCOPY(hemiside.cam, shoot->cent);
+ VECCOPY(hemitop.cam, shoot->cent);
+
+ /* do it! */
+ VECCOPY(hemitop.tar, tar[0]);
+ hemizbuf(&hemitop);
+
+ for(a=1; a<5; a++) {
+ VECCOPY(hemiside.tar, tar[a]);
+ hemizbuf(&hemiside);
+ }
+
+ /* convert factors to real radiosity */
+ re= RG.elem;
+ fp= RG.formfactors;
+
+ overfl= 0;
+ for(a= RG.totelem; a>0; a--, re++, fp++) {
+
+ if(*fp!=0.0) {
+
+ *fp *= shoot->area/(*re)->area;
+
+ if(*fp>1.0) {
+ overfl= 1;
+ *fp= 1.0001;
+ }
+ }
+ }
+
+ if(overfl) {
+ /*
+ drawOverflowElem();
+ while(get_mbut()&L_MOUSE==0) {
+ if(get_mbut()&M_MOUSE) {
+ viewmove();
+ drawpatch_ext(shoot,0xFF77FF);
+ drawOverflowElem();
+ }
+ }
+ */
+ if(shoot->first->down1) {
+ splitpatch(shoot);
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+void applyformfactors(RPatch *shoot)
+{
+ RPatch *rp;
+ RNode **el, *rn;
+ float *fp, *ref, unr, ung, unb, r, g, b, w;
+ int a;
+
+ unr= shoot->unshot[0];
+ ung= shoot->unshot[1];
+ unb= shoot->unshot[2];
+
+ fp= RG.formfactors;
+ el= RG.elem;
+ for(a=0; a<RG.totelem; a++, el++, fp++) {
+ rn= *el;
+ if(*fp!= 0.0) {
+ rp= rn->par;
+ ref= rp->ref;
+
+ r= (*fp)*unr*ref[0];
+ g= (*fp)*ung*ref[1];
+ b= (*fp)*unb*ref[2];
+
+ w= rn->area/rp->area;
+ rn->totrad[0]+= r;
+ rn->totrad[1]+= g;
+ rn->totrad[2]+= b;
+
+ rp->unshot[0]+= w*r;
+ rp->unshot[1]+= w*g;
+ rp->unshot[2]+= w*b;
+ }
+ }
+
+ shoot->unshot[0]= shoot->unshot[1]= shoot->unshot[2]= 0.0;
+}
+
+RPatch *findshootpatch()
+{
+ RPatch *rp, *shoot;
+ float energy, maxenergy;
+
+ shoot= 0;
+ maxenergy= 0.0;
+ rp= RG.patchbase.first;
+ while(rp) {
+ energy= rp->unshot[0]*rp->area;
+ energy+= rp->unshot[1]*rp->area;
+ energy+= rp->unshot[2]*rp->area;
+
+ if(energy>maxenergy) {
+ shoot= rp;
+ maxenergy= energy;
+ }
+ rp= rp->next;
+ }
+
+ if(shoot) {
+ maxenergy/= RG.totenergy;
+ if(maxenergy<RG.convergence) return 0;
+ }
+
+ return shoot;
+}
+
+void setnodeflags(RNode *rn, int flag, int set)
+{
+
+ if(rn->down1) {
+ setnodeflags(rn->down1, flag, set);
+ setnodeflags(rn->down2, flag, set);
+ }
+ else {
+ if(set) rn->f |= flag;
+ else rn->f &= ~flag;
+ }
+}
+
+void backface_test(RPatch *shoot)
+{
+ RPatch *rp;
+ float tvec[3];
+
+ rp= RG.patchbase.first;
+ while(rp) {
+ if(rp!=shoot) {
+
+ VecSubf(tvec, shoot->cent, rp->cent);
+ if( tvec[0]*shoot->norm[0]+ tvec[1]*shoot->norm[1]+ tvec[2]*shoot->norm[2]>0.0) {
+ setnodeflags(rp->first, RAD_BACKFACE, 1);
+ }
+ }
+ rp= rp->next;
+ }
+}
+
+void clear_backface_test()
+{
+ RNode **re;
+ int a;
+
+ re= RG.elem;
+ for(a= RG.totelem-1; a>=0; a--, re++) {
+ (*re)->f &= ~RAD_BACKFACE;
+ }
+
+}
+
+void rad_init_energy()
+{
+ /* call before shooting */
+ /* keep patches and elements, clear all data */
+ RNode **el, *rn;
+ RPatch *rp;
+ int a;
+
+ el= RG.elem;
+ for(a=RG.totelem; a>0; a--, el++) {
+ rn= *el;
+ VECCOPY(rn->totrad, rn->par->emit);
+ }
+
+ RG.totenergy= 0.0;
+ rp= RG.patchbase.first;
+ while(rp) {
+ VECCOPY(rp->unshot, rp->emit);
+
+ RG.totenergy+= rp->unshot[0]*rp->area;
+ RG.totenergy+= rp->unshot[1]*rp->area;
+ RG.totenergy+= rp->unshot[2]*rp->area;
+
+ rp->f= 0;
+
+ rp= rp->next;
+ }
+}
+
+void progressiverad()
+{
+ RPatch *shoot;
+ int it= 0;
+
+ rad_printstatus();
+ rad_init_energy();
+
+ shoot=findshootpatch();
+
+ while( shoot ) {
+
+ setnodeflags(shoot->first, RAD_SHOOT, 1);
+
+ backface_test(shoot);
+
+ drawpatch_ext(shoot, 0x88FF00);
+
+ if( makeformfactors(shoot) ) {
+
+ applyformfactors(shoot);
+
+ it++;
+ set_timecursor(it);
+ if( (it & 3)==1 ) {
+ make_node_display();
+ rad_forcedraw();
+ }
+ setnodeflags(shoot->first, RAD_SHOOT, 0);
+ }
+
+ clear_backface_test();
+
+ if(MISC_test_break()) break;
+ if(RG.maxiter && RG.maxiter<=it) break;
+
+ shoot=findshootpatch();
+
+ }
+
+}
+
+
+/* ************* subdivideshoot *********** */
+
+void minmaxradelem(RNode *rn, float *min, float *max)
+{
+ int c;
+
+ if(rn->down1) {
+ minmaxradelem(rn->down1, min, max);
+ minmaxradelem(rn->down2, min, max);
+ }
+ else {
+ for(c=0; c<3; c++) {
+ min[c]= MIN2(min[c], rn->totrad[c]);
+ max[c]= MAX2(max[c], rn->totrad[c]);
+ }
+ }
+}
+
+void minmaxradelemfilt(RNode *rn, float *min, float *max, float *errmin, float *errmax)
+{
+ float col[3], area;
+ int c;
+
+ if(rn->down1) {
+ minmaxradelemfilt(rn->down1, min, max, errmin, errmax);
+ minmaxradelemfilt(rn->down2, min, max, errmin, errmax);
+ }
+ else {
+ VECCOPY(col, rn->totrad);
+
+ for(c=0; c<3; c++) {
+ min[c]= MIN2(min[c], col[c]);
+ max[c]= MAX2(max[c], col[c]);
+ }
+
+ VecMulf(col, 2.0);
+ area= 2.0;
+ if(rn->ed1) {
+ VecAddf(col, rn->ed1->totrad, col);
+ area+= 1.0;
+ }
+ if(rn->ed2) {
+ VecAddf(col, rn->ed2->totrad, col);
+ area+= 1.0;
+ }
+ if(rn->ed3) {
+ VecAddf(col, rn->ed3->totrad, col);
+ area+= 1.0;
+ }
+ if(rn->ed4) {
+ VecAddf(col, rn->ed4->totrad, col);
+ area+= 1.0;
+ }
+ VecMulf(col, 1.0/area);
+
+ for(c=0; c<3; c++) {
+ errmin[c]= MIN2(errmin[c], col[c]);
+ errmax[c]= MAX2(errmax[c], col[c]);
+ }
+ }
+}
+
+void setsubflagelem(RNode *rn)
+{
+
+ if(rn->down1) {
+ setsubflagelem(rn->down1);
+ setsubflagelem(rn->down2);
+ }
+ else {
+ rn->f |= RAD_SUBDIV;
+ }
+}
+
+void clearsubflagelem(RNode *rn)
+{
+
+ if(rn->down1) {
+ setsubflagelem(rn->down1);
+ setsubflagelem(rn->down2);
+ }
+ else {
+ rn->f &= ~RAD_SUBDIV;
+ }
+}
+
+void subdivideshootElements(int it)
+{
+ RPatch *rp, *shoot;
+ RNode **el, *rn;
+ float *fp, err, stoke, area, min[3], max[3], errmin[3], errmax[3];
+ int a, b, c, d, e, f, contin;
+ int maxlamp;
+
+ if(RG.maxsublamp==0) maxlamp= RG.totlamp;
+ else maxlamp= RG.maxsublamp;
+
+ while(it) {
+ rad_printstatus();
+ rad_init_energy();
+ it--;
+
+ for(a=0; a<maxlamp; a++) {
+ shoot= findshootpatch();
+ if(shoot==0) break;
+
+ set_timecursor(a);
+ drawpatch_ext(shoot, 0x88FF00);
+
+ setnodeflags(shoot->first, RAD_SHOOT, 1);
+ if( makeformfactors(shoot) ) {
+
+ fp= RG.formfactors;
+ el= RG.elem;
+ for(b=RG.totelem; b>0; b--, el++) {
+ rn= *el;
+
+ if( (rn->f & RAD_SUBDIV)==0 && *fp!=0.0) {
+ if(rn->par->emit[0]+rn->par->emit[1]+rn->par->emit[2]==0.0) {
+
+ stoke= calcStokefactor(shoot, rn->par, rn, &area);
+ if(stoke!= 0.0) {
+
+ err= *fp/stoke;
+
+ /* area error */
+ area*=(0.5*RG.hemires*RG.hemires);
+
+ if(area>35.0) {
+ if(err<0.95 || err>1.05) {
+ if(err>0.05) {
+ rn->f |= RAD_SUBDIV;
+ rn->par->f |= RAD_SUBDIV;
+ }
+ }
+ }
+ }
+
+ }
+ }
+
+ fp++;
+
+ }
+
+ applyformfactors(shoot);
+
+ if( (a & 3)==1 ) {
+ make_node_display();
+ rad_forcedraw();
+ }
+
+ setnodeflags(shoot->first, RAD_SHOOT, 0);
+ }
+ else a--;
+
+ if(MISC_test_break()) break;
+ }
+
+ /* test op extreem weinig kleurverloop binnen patch met subdivflag */
+
+ rp= RG.patchbase.first;
+
+ while(rp) {
+ if(rp->f & RAD_SUBDIV) { /* rp heeft elems die moet gesubd */
+ /* minstens 4 levels diep */
+ rn= rp->first->down1;
+ if(rn) {
+ rn= rn->down1;
+ if(rn) {
+ rn= rn->down1;
+ if(rn) rn= rn->down1;
+ }
+ }
+ if(rn) {
+ min[0]= min[1]= min[2]= 1.0e10;
+ max[0]= max[1]= max[2]= -1.0e10;
+ /* errmin en max zijn de gefilterde kleuren */
+ errmin[0]= errmin[1]= errmin[2]= 1.0e10;
+ errmax[0]= errmax[1]= errmax[2]= -1.0e10;
+ minmaxradelemfilt(rp->first, min, max, errmin, errmax);
+
+ /* verschil tussen kleuren klein: toch maar niet subd */
+ /* test ook voor de gefilterde: maar kritischer */
+
+ contin= 0;
+ a= abs( calculatecolor(min[0])-calculatecolor(max[0]));
+ b= abs( calculatecolor(errmin[0])-calculatecolor(errmax[0]));
+ if(a<15 || b<7) {
+ c= abs( calculatecolor(min[1])-calculatecolor(max[1]));
+ d= abs( calculatecolor(errmin[1])-calculatecolor(errmax[1]));
+ if(c<15 || d<7) {
+ e= abs( calculatecolor(min[2])-calculatecolor(max[2]));
+ f= abs( calculatecolor(errmin[2])-calculatecolor(errmax[2]));
+ if(e<15 || f<7) {
+ contin= 1;
+ clearsubflagelem(rp->first);
+ /* printf("%d %d %d %d %d %d\n", a, b, c, d, e, f); */
+ }
+ }
+ }
+ if(contin) {
+ drawpatch_ext(rp, 0xFFFF);
+ }
+ }
+ }
+ rp->f &= ~RAD_SUBDIV;
+ rp= rp->next;
+ }
+
+ contin= 0;
+
+ el= RG.elem;
+ for(b=RG.totelem; b>0; b--, el++) {
+ rn= *el;
+ if(rn->f & RAD_SUBDIV) {
+ rn->f-= RAD_SUBDIV;
+ subdivideNode(rn, 0);
+ if(rn->down1) {
+ subdivideNode(rn->down1, 0);
+ subdivideNode(rn->down2, 0);
+ contin= 1;
+ }
+ }
+ }
+ makeGlobalElemArray();
+
+ if(contin==0 || MISC_test_break()) break;
+ }
+
+ make_node_display();
+}
+
+void subdivideshootPatches(int it)
+{
+ RPatch *rp, *shoot, *next;
+ float *fp, err, stoke, area;
+ int a, contin;
+ int maxlamp;
+
+ if(RG.maxsublamp==0) maxlamp= RG.totlamp;
+ else maxlamp= RG.maxsublamp;
+
+ while(it) {
+ rad_printstatus();
+ rad_init_energy();
+ it--;
+
+ for(a=0; a<maxlamp; a++) {
+ shoot= findshootpatch();
+ if(shoot==0) break;
+
+ set_timecursor(a);
+ drawpatch_ext(shoot, 0x88FF00);
+
+ setnodeflags(shoot->first, RAD_SHOOT, 1);
+
+ if( makeformfactors(shoot) ) {
+
+ fp= RG.formfactors;
+ rp= RG.patchbase.first;
+ while(rp) {
+ if(*fp!=0.0 && rp!=shoot) {
+
+ stoke= calcStokefactor(shoot, rp, rp->first, &area);
+ if(stoke!= 0.0) {
+ if(area>.1) { /* ontvangt patch meer dan (ong)10% van energie? */
+ rp->f= RAD_SUBDIV;
+ }
+ else {
+
+ err= *fp/stoke;
+
+ /* area error */
+ area*=(0.5*RG.hemires*RG.hemires);
+
+ if(area>45.0) {
+ if(err<0.95 || err>1.05) {
+ if(err>0.05) {
+
+ rp->f= RAD_SUBDIV;
+
+ /* if(get_qual()&LR_SHIFTKEY);
+ else {
+ drawpatch_ext(rp, 0xFF77FF);
+
+ printf("Pa hemi %f stoke %f err %f area %f\n", *fp, stoke, err, area);
+
+ while(get_mbut()&L_MOUSE==0);
+ while(get_mbut()&L_MOUSE);
+ }
+ */
+ }
+ }
+ }
+ }
+ }
+ }
+ fp++;
+
+ rp= rp->next;
+ }
+
+ applyformfactors(shoot);
+
+ if( (a & 3)==1 ) {
+ make_node_display();
+ rad_forcedraw();
+ }
+
+ setnodeflags(shoot->first, RAD_SHOOT, 0);
+
+ if(MISC_test_break()) break;
+ }
+ else a--;
+
+ }
+
+ contin= 0;
+
+ rp= RG.patchbase.first;
+ while(rp) {
+ next= rp->next;
+ if(rp->f & RAD_SUBDIV) {
+ if(rp->emit[0]+rp->emit[1]+rp->emit[2]==0.0) {
+ contin= 1;
+ subdivideNode(rp->first, 0);
+ if(rp->first->down1) {
+ subdivideNode(rp->first->down1, 0);
+ subdivideNode(rp->first->down2, 0);
+ }
+ }
+ }
+ rp= next;
+ }
+
+ converttopatches();
+ makeGlobalElemArray();
+
+ if(contin==0 || MISC_test_break()) break;
+ }
+ make_node_display();
+}
+
+void inithemiwindows()
+{
+ RadView *vw;
+
+ /* de hemiwindows */
+ vw= &(hemitop);
+ memset(vw, 0, sizeof(RadView));
+ vw->rectx= RG.hemires;
+ vw->recty= RG.hemires;
+ vw->rectz= MEM_mallocN(4*vw->rectx*vw->recty, "initwindows");
+ vw->rect= MEM_mallocN(4*vw->rectx*vw->recty, "initwindows");
+ vw->mynear= RG.maxsize/2000.0;
+ vw->myfar= 2.0*RG.maxsize;
+ vw->wx1= -vw->mynear;
+ vw->wx2= vw->mynear;
+ vw->wy1= -vw->mynear;
+ vw->wy2= vw->mynear;
+
+ i_window(vw->wx1, vw->wx2, vw->wy1, vw->wy2, vw->mynear, vw->myfar, vw->winmat);
+
+ hemiside= hemitop;
+
+ vw= &(hemiside);
+ vw->recty/= 2;
+ vw->wy1= vw->wy2;
+ vw->wy2= 0.0;
+
+ i_window(vw->wx1, vw->wx2, vw->wy1, vw->wy2, vw->mynear, vw->myfar, vw->winmat);
+
+}
+
+void closehemiwindows()
+{
+
+ if(hemiside.rect) MEM_freeN(hemiside.rect);
+ if(hemiside.rectz) MEM_freeN(hemiside.rectz);
+ hemiside.rectz= 0;
+ hemiside.rect= 0;
+ hemitop.rectz= 0;
+ hemitop.rect= 0;
+}
diff --git a/source/blender/radiosity/intern/source/radio.c b/source/blender/radiosity/intern/source/radio.c
new file mode 100644
index 00000000000..af3797d6c2b
--- /dev/null
+++ b/source/blender/radiosity/intern/source/radio.c
@@ -0,0 +1,379 @@
+/* ***************************************
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+
+
+
+ radio.c nov/dec 1992
+ may 1999
+
+ $Id$
+
+ - mainlus
+ - toetsafhandeling
+
+
+ - PREPROCES
+ - collect meshes
+ - spitconnected (alle vlakken met verschillende kleur en normaal)
+ - setedgepointers (nodes wijzen naar buren)
+
+ - EDITING
+ - min-max patch en min-max elementsize
+ - ahv bovenstaande evt patches subdividen
+ - lampsubdivide
+
+ - als er teveel lampen zijn voor de subdivide shooting:
+ - tijdelijk patches samenvoegen
+ - met de hand aangeven?
+
+ - SUBDIVIDE SHOOTING
+ - behalve laatste shooting bepaalt dit patch-subdivide
+ - als gesubdivide patches nog > 2*minsize : doorgaan
+ - op eind zoveel mogelijk elements maken
+ - ook onthouden of lamp (nog) subdivide veroorzaakt.
+
+ - REFINEMENT SHOOTING
+ - testen op overflows (shootpatch subdividen)
+ - testen op extreme kleur verlopen:
+ - als nog kan: shootpatch subdividen
+ - elements subdividen = overnieuw beginnen ?
+ - ittereren stoppen nadat ?
+
+ - DEFINITIVE SHOOTING
+ - user geeft aan hoeveel vlakken maximaal en itteratie lengte.
+ - nodes omzetten naar minder geheugen-intensief formaat
+ - element- nodes weer samenvoegen waarin niets gebeurt (faces)
+ - elements subdividen waarin veel gebeurt
+
+ *************************************** */
+
+#include <math.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+#include "PIL_time.h"
+
+#include "BLI_blenlib.h"
+
+#include "DNA_object_types.h"
+#include "DNA_radio_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+
+#include "BKE_global.h"
+#include "BKE_main.h"
+
+#include "BIF_screen.h" /* curarea */
+#include "BIF_space.h" /* allqueue */
+
+#include "radio.h"
+#include "mydevice.h"
+
+/* locals? This one was already done in radio.h... */
+/* void rad_status_str(char *str); */
+
+RadGlobal RG= {0, 0};
+
+void freeAllRad()
+{
+ Base *base;
+ extern int Ntotvert, Ntotnode, Ntotpatch;
+
+ /* clear flag that disables drawing the meshes */
+ if(G.scene) {
+ base= (G.scene->base.first);
+ while(base) {
+ if(base->object->type==OB_MESH) {
+ base->flag &= ~OB_RADIO;
+ }
+ base= base->next;
+ }
+ }
+
+ free_fastAll(); /* verts, nodes, patches */
+ RG.patchbase.first= RG.patchbase.last= 0;
+ Ntotvert= Ntotnode= Ntotpatch= 0;
+
+ closehemiwindows(); /* not real windows anymore... */
+ if(RG.elem) MEM_freeN(RG.elem);
+ RG.elem= 0;
+ if(RG.verts) MEM_freeN(RG.verts);
+ RG.verts= 0;
+ if(RG.topfactors) MEM_freeN(RG.topfactors);
+ RG.topfactors= 0;
+ if(RG.sidefactors) MEM_freeN(RG.sidefactors);
+ RG.sidefactors= 0;
+ if(RG.formfactors) MEM_freeN(RG.formfactors);
+ RG.formfactors= 0;
+ if(RG.index) MEM_freeN(RG.index);
+ RG.index= 0;
+ if(RG.facebase) {
+ init_face_tab(); /* frees all tables */
+ MEM_freeN(RG.facebase);
+ RG.facebase= 0;
+ }
+ RG.totelem= RG.totpatch= RG.totvert= RG.totface= RG.totlamp= RG.totmat= 0;
+}
+
+int rad_phase()
+{
+ int flag= 0;
+
+ if(RG.totpatch) flag |= RAD_PHASE_PATCHES;
+ if(RG.totface) flag |= RAD_PHASE_FACES;
+
+ return flag;
+}
+
+void rad_status_str(char *str)
+{
+ extern int totfastmem;
+ int tot;
+ char *phase;
+
+ tot= (RG.totface*sizeof(Face))/1024;
+ tot+= totfastmem/1024;
+
+ if(RG.phase==RAD_SHOOTE) phase= "Phase: ELEMENT SUBD, ";
+ else if(RG.phase==RAD_SHOOTP) phase= "Phase: PATCH SUBD, ";
+ else if(RG.phase==RAD_SOLVE) phase= "Phase: SOLVE, ";
+ else if(RG.totpatch==0) phase= "Phase: COLLECT MESHES ";
+ else if(RG.totface) phase= "Phase: FINISHED, ";
+ else phase= "Phase: INIT, ";
+
+ if(RG.totpatch==0) strcpy(str, phase);
+ else sprintf(str, "%s TotPatch: %d TotElem: %d Emit: %d Faces %d Mem: %d k ", phase, RG.totpatch, RG.totelem, RG.totlamp, RG.totface, tot);
+
+ if(RG.phase==RAD_SOLVE) strcat(str, "(press ESC to stop)");
+}
+
+void rad_printstatus()
+{
+ /* actions always are started from a buttonswindow */
+ scrarea_do_windraw(curarea);
+ screen_swapbuffers();
+}
+
+void rad_setlimits()
+{
+ Radio *rad= G.scene->radio;
+ float fac;
+
+ fac= 0.0005*rad->pama;
+ RG.patchmax= RG.maxsize*fac;
+ RG.patchmax*= RG.patchmax;
+ fac= 0.0005*rad->pami;
+ RG.patchmin= RG.maxsize*fac;
+ RG.patchmin*= RG.patchmin;
+
+ fac= 0.0005*rad->elma;
+ RG.elemmax= RG.maxsize*fac;
+ RG.elemmax*= RG.elemmax;
+ fac= 0.0005*rad->elmi;
+ RG.elemmin= RG.maxsize*fac;
+ RG.elemmin*= RG.elemmin;
+}
+
+void set_radglobal()
+{
+ /* always call before any action is performed */
+ Radio *rad= G.scene->radio;
+
+ if(RG.radio==0) {
+ /* firsttime and to be sure */
+ memset(&RG, 0, sizeof(RadGlobal));
+ }
+
+ if(rad==0) return;
+
+ if(rad != RG.radio) {
+ if(RG.radio) freeAllRad();
+ memset(&RG, 0, sizeof(RadGlobal));
+ RG.radio= rad;
+ }
+
+ RG.hemires= rad->hemires & 0xFFF0;
+ RG.drawtype= rad->drawtype;
+ RG.flag= rad->flag;
+ RG.subshootp= rad->subshootp;
+ RG.subshoote= rad->subshoote;
+ RG.nodelim= rad->nodelim;
+ RG.maxsublamp= rad->maxsublamp;
+ RG.maxnode= 2*rad->maxnode; /* in button:max elem, subdividing! */
+ RG.convergence= rad->convergence/1000.0;
+ RG.radfac= rad->radfac;
+ RG.gamma= rad->gamma;
+ RG.maxiter= rad->maxiter;
+
+ rad_setlimits();
+}
+
+/* called from buttons.c */
+void add_radio()
+{
+ Radio *rad;
+
+ if(G.scene->radio) MEM_freeN(G.scene->radio);
+ rad= G.scene->radio= MEM_callocN(sizeof(Radio), "radio");
+
+ rad->hemires= 300;
+ rad->convergence= 0.1;
+ rad->radfac= 30.0;
+ rad->gamma= 2.0;
+ rad->drawtype= DTSOLID;
+ rad->subshootp= 1;
+ rad->subshoote= 2;
+ rad->maxsublamp= 0;
+
+ rad->pama= 500;
+ rad->pami= 200;
+ rad->elma= 100;
+ rad->elmi= 20;
+ rad->nodelim= 0;
+ rad->maxnode= 10000;
+ rad->flag= 2;
+ set_radglobal();
+}
+
+void delete_radio()
+{
+ freeAllRad();
+ if(G.scene->radio) MEM_freeN(G.scene->radio);
+ G.scene->radio= 0;
+
+ RG.radio= 0;
+}
+
+int rad_go(void) /* return 0 when user escapes */
+{
+ double stime= PIL_check_seconds_timer();
+ int retval;
+ /* firsttime moet vervangen worden door radphase? */
+
+ if(RG.totface) return 0;
+
+ G.afbreek= 0;
+
+ set_radglobal();
+ initradiosity(); /* LUT's */
+ inithemiwindows(); /* views */
+
+ maxsizePatches();
+
+ setnodelimit(RG.patchmin);
+ RG.phase= RAD_SHOOTP;
+ subdivideshootPatches(RG.subshootp);
+
+ setnodelimit(RG.elemmin);
+ RG.phase= RAD_SHOOTE;
+ subdivideshootElements(RG.subshoote);
+
+ setnodelimit(RG.patchmin);
+ subdividelamps();
+
+ setnodelimit(RG.elemmin);
+
+ RG.phase= RAD_SOLVE;
+ subdiv_elements();
+
+ progressiverad();
+
+ removeEqualNodes(RG.nodelim);
+
+ make_face_tab(); /* nu geankerd */
+
+ closehemiwindows();
+ RG.phase= 0;
+
+ stime= PIL_check_seconds_timer()-stime;
+ printf("Radiosity solving time: %dms\n", (int) (stime*1000));
+
+ if(G.afbreek==1) retval= 1;
+ else retval= 0;
+
+ G.afbreek= 0;
+
+ return retval;
+}
+
+void rad_subdivshootpatch()
+{
+
+ if(RG.totface) return;
+
+ G.afbreek= 0;
+
+ set_radglobal();
+ initradiosity(); /* LUT's */
+ inithemiwindows(); /* views */
+
+ subdivideshootPatches(1);
+
+ removeEqualNodes(RG.nodelim);
+ closehemiwindows();
+
+ allqueue(REDRAWVIEW3D, 1);
+}
+
+void rad_subdivshootelem(void)
+{
+
+ if(RG.totface) return;
+
+ G.afbreek= 0;
+
+ set_radglobal();
+ initradiosity(); /* LUT's */
+ inithemiwindows(); /* views */
+
+ subdivideshootElements(1);
+
+ removeEqualNodes(RG.nodelim);
+ closehemiwindows();
+
+ allqueue(REDRAWVIEW3D, 1);
+}
+
+void rad_limit_subdivide()
+{
+
+ if(G.scene->radio==0) return;
+
+ set_radglobal();
+
+ if(RG.totpatch==0) {
+ /* printf("exit: no relevant data\n"); */
+ return;
+ }
+
+ maxsizePatches();
+
+ init_face_tab(); /* free faces */
+}
diff --git a/source/blender/radiosity/intern/source/radnode.c b/source/blender/radiosity/intern/source/radnode.c
new file mode 100644
index 00000000000..b75edc0c2cf
--- /dev/null
+++ b/source/blender/radiosity/intern/source/radnode.c
@@ -0,0 +1,1095 @@
+/* ***************************************
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+
+
+
+ node.c nov/dec 1992
+ may 1999
+
+ $Id$
+
+ *************************************** */
+
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "BKE_global.h"
+#include "BKE_main.h"
+
+#include "BIF_toolbox.h"
+
+#include "radio.h"
+
+/* locals */
+void *malloc_fast(int size);
+void *calloc_fast(int size);
+void free_fast(void *poin, int siz);
+void deleteTriNodes(RNode *node);
+/* lower because of local type define */
+/* void check_mallocgroup(MallocGroup *mg); */
+
+
+/* ********** fastmalloc ************** */
+
+#define MAL_GROUPSIZE 256
+#define MAL_AVAILABLE 1
+#define MAL_FULL 2
+
+
+
+
+ListBase MallocBase= {0, 0};
+int totfastmem= 0;
+
+typedef struct MallocGroup {
+ struct MallocGroup *next, *prev;
+ short size, flag;
+ short curfree, tot;
+ char flags[MAL_GROUPSIZE];
+ char *data;
+} MallocGroup;
+
+/* one more local */
+void check_mallocgroup(MallocGroup *mg);
+
+void check_mallocgroup(MallocGroup *mg)
+{
+ int a;
+ char *cp;
+
+ if(mg->tot==MAL_GROUPSIZE) {
+ mg->flag= MAL_FULL;
+ return;
+ }
+
+ cp= mg->flags;
+
+ if(mg->curfree<MAL_GROUPSIZE-1) {
+ if(cp[mg->curfree+1]==0) {
+ mg->curfree++;
+ return;
+ }
+ }
+ if(mg->curfree>0) {
+ if(cp[mg->curfree-1]==0) {
+ mg->curfree--;
+ return;
+ }
+ }
+
+ for(a=0; a<MAL_GROUPSIZE; a++) {
+ if(cp[a]==0) {
+ mg->curfree= a;
+ return;
+ }
+ }
+ printf("fastmalloc: shouldnt be here\n");
+}
+
+void *malloc_fast(int size)
+{
+ MallocGroup *mg;
+ void *retval;
+
+ mg= MallocBase.last;
+ while(mg) {
+ if(mg->size==size) {
+ if(mg->flag & MAL_AVAILABLE) {
+ mg->flags[mg->curfree]= 1;
+ mg->tot++;
+ retval= mg->data+mg->curfree*mg->size;
+ check_mallocgroup(mg);
+ return retval;
+ }
+ }
+ mg= mg->prev;
+ }
+
+ /* no free block found */
+ mg= MEM_callocN(sizeof(MallocGroup), "mallocgroup");
+ BLI_addtail(&MallocBase, mg);
+ mg->data= MEM_mallocN(MAL_GROUPSIZE*size, "mallocgroupdata");
+ mg->flag= MAL_AVAILABLE;
+ mg->flags[0]= 1;
+ mg->curfree= 1;
+ mg->size= size;
+ mg->tot= 1;
+
+ totfastmem+= sizeof(MallocGroup)+MAL_GROUPSIZE*size;
+
+ return mg->data;
+}
+
+void *calloc_fast(int size)
+{
+ void *poin;
+
+ poin= malloc_fast(size);
+ memset(poin, 0, size);
+
+ return poin;
+}
+
+void free_fast(void *poin, int size)
+{
+ MallocGroup *mg;
+ long val;
+
+ mg= MallocBase.last;
+ while(mg) {
+ if(mg->size==size) {
+ if( ((long)poin) >= ((long)mg->data) ) {
+ if( ((long)poin) < ((long)(mg->data+MAL_GROUPSIZE*size)) ) {
+ val= ((long)poin) - ((long)mg->data);
+ val/= size;
+ mg->curfree= val;
+ mg->flags[val]= 0;
+ mg->flag= MAL_AVAILABLE;
+
+ mg->tot--;
+ if(mg->tot==0) {
+ BLI_remlink(&MallocBase, mg);
+ MEM_freeN(mg->data);
+ MEM_freeN(mg);
+ totfastmem-= sizeof(MallocGroup)+MAL_GROUPSIZE*size;
+ }
+ return;
+ }
+ }
+ }
+ mg= mg->prev;
+ }
+ printf("fast free: pointer not in memlist %p size %d\n",
+ poin, size);
+}
+
+/* security: only one function in a time can use it */
+static char *fastmallocstr= 0;
+
+void free_fastAll()
+{
+ MallocGroup *mg;
+
+ mg= MallocBase.first;
+ while(mg) {
+ BLI_remlink(&MallocBase, mg);
+ MEM_freeN(mg->data);
+ MEM_freeN(mg);
+ mg= MallocBase.first;
+ }
+ totfastmem= 0;
+ fastmallocstr= 0;
+}
+
+void start_fastmalloc(char *str)
+{
+ if(fastmallocstr) {
+ error("Fastmalloc in use: %s", fastmallocstr);
+ return;
+ }
+ fastmallocstr= str;
+}
+
+/* **************************************** */
+
+float nodelimit;
+
+void setnodelimit(float limit)
+{
+ nodelimit= limit;
+
+}
+
+/* ************ GEHEUGENBEHEER *********** */
+
+int Ntotvert=0, Ntotnode=0, Ntotpatch=0;
+
+float *mallocVert()
+{
+ Ntotvert++;
+ return (float *)malloc_fast(16);
+}
+
+float *callocVert()
+{
+ Ntotvert++;
+ return (float *)calloc_fast(16);
+}
+
+void freeVert(float *vert)
+{
+ free_fast(vert, 16);
+ Ntotvert--;
+}
+
+RNode *mallocNode()
+{
+ Ntotnode++;
+ return (RNode *)malloc_fast(sizeof(RNode));
+}
+
+RNode *callocNode()
+{
+ Ntotnode++;
+ return (RNode *)calloc_fast(sizeof(RNode));
+}
+
+void freeNode(RNode *node)
+{
+ free_fast(node, sizeof(RNode));
+ Ntotnode--;
+}
+
+void freeNode_recurs(RNode *node)
+{
+
+ if(node->down1) {
+ freeNode_recurs(node->down1);
+ freeNode_recurs(node->down2);
+ }
+
+ node->down1= node->down2= 0;
+ freeNode(node);
+
+}
+
+RPatch *mallocPatch()
+{
+ Ntotpatch++;
+ return (RPatch *)malloc_fast(sizeof(RPatch));
+}
+
+RPatch *callocPatch()
+{
+ Ntotpatch++;
+ return (RPatch *)calloc_fast(sizeof(RPatch));
+}
+
+void freePatch(RPatch *patch)
+{
+ free_fast(patch, sizeof(RPatch));
+ Ntotpatch--;
+}
+
+/* ************ SUBDIVIDE *********** */
+
+
+void replaceAllNode(RNode *neighb, RNode *newn)
+{
+ /* verandert van alle buren de edgepointers die naar newn->up wijzen in new */
+ int ok= 0;
+
+
+ if(neighb==0) return;
+ if(newn->up==0) return;
+
+ if(neighb->ed1==newn->up) {
+ neighb->ed1= newn;
+ ok= 1;
+ }
+ else if(neighb->ed2==newn->up) {
+ neighb->ed2= newn;
+ ok= 1;
+ }
+ else if(neighb->ed3==newn->up) {
+ neighb->ed3= newn;
+ ok= 1;
+ }
+ else if(neighb->ed4==newn->up) {
+ neighb->ed4= newn;
+ ok= 1;
+ }
+
+ if(ok && neighb->down1) {
+ replaceAllNode(neighb->down1, newn);
+ replaceAllNode(neighb->down2, newn);
+ }
+}
+
+void replaceAllNodeInv(RNode *neighb, RNode *old)
+{
+ /* verandert van alle buren de edgepointers die naar old wijzen in old->up */
+ if(neighb==0) return;
+ if(old->up==0) return;
+
+ if(neighb->ed1==old) {
+ neighb->ed1= old->up;
+ }
+ else if(neighb->ed2==old) {
+ neighb->ed2= old->up;
+ }
+ else if(neighb->ed3==old) {
+ neighb->ed3= old->up;
+ }
+ else if(neighb->ed4==old) {
+ neighb->ed4= old->up;
+ }
+
+ if(neighb->down1) {
+ replaceAllNodeInv(neighb->down1, old);
+ replaceAllNodeInv(neighb->down2, old);
+ }
+}
+
+void replaceAllNodeUp(RNode *neighb, RNode *old)
+{
+ /* verandert van alle buren de edgepointers die naar old wijzen in old->up */
+ if(neighb==0) return;
+ if(old->up==0) return;
+ neighb= neighb->up;
+ if(neighb==0) return;
+
+ if(neighb->ed1==old) {
+ neighb->ed1= old->up;
+ }
+ else if(neighb->ed2==old) {
+ neighb->ed2= old->up;
+ }
+ else if(neighb->ed3==old) {
+ neighb->ed3= old->up;
+ }
+ else if(neighb->ed4==old) {
+ neighb->ed4= old->up;
+ }
+
+ if(neighb->up) {
+ replaceAllNodeUp(neighb, old);
+ }
+}
+
+
+void replaceTestNode(RNode *neighb, RNode **edpp, RNode *newn, int level, float *vert)
+{
+ /* IF neighb->ed wijst naar newn->up
+ * IF edgelevels gelijk
+ IF testvert zit in neighb->ed
+ pointers beide kanten op veranderen
+ ELSE
+ RETURN
+ ELSE
+ IF neighb edgelevel is dieper
+ verander neighb pointer
+
+ */
+ int ok= 0;
+
+ if(neighb==0) return;
+ if(newn->up==0) return;
+
+ if(neighb->ed1==newn->up) {
+ if(neighb->lev1==level) {
+ if(vert==neighb->v1 || vert==neighb->v2) {
+ *edpp= neighb;
+ neighb->ed1= newn;
+ }
+ else return;
+ }
+ else if(neighb->lev1>level) {
+ neighb->ed1= newn;
+ }
+ ok= 1;
+ }
+ else if(neighb->ed2==newn->up) {
+ if(neighb->lev2==level) {
+ if(vert==neighb->v2 || vert==neighb->v3) {
+ *edpp= neighb;
+ neighb->ed2= newn;
+ }
+ else return;
+ }
+ else if(neighb->lev2>level) {
+ neighb->ed2= newn;
+ }
+ ok= 1;
+ }
+ else if(neighb->ed3==newn->up) {
+ if(neighb->lev3==level) {
+ if(neighb->type==3) {
+ if(vert==neighb->v3 || vert==neighb->v1) {
+ *edpp= neighb;
+ neighb->ed3= newn;
+ }
+ else return;
+ }
+ else {
+ if(vert==neighb->v3 || vert==neighb->v4) {
+ *edpp= neighb;
+ neighb->ed3= newn;
+ }
+ else return;
+ }
+ }
+ else if(neighb->lev3>level) {
+ neighb->ed3= newn;
+ }
+ ok= 1;
+ }
+ else if(neighb->ed4==newn->up) {
+ if(neighb->lev4==level) {
+ if(vert==neighb->v4 || vert==neighb->v1) {
+ *edpp= neighb;
+ neighb->ed4= newn;
+ }
+ else return;
+ }
+ else if(neighb->lev4>level) {
+ neighb->ed4= newn;
+ }
+ ok= 1;
+ }
+
+ if(ok && neighb->down1) {
+ replaceTestNode(neighb->down1, edpp, newn, level, vert);
+ replaceTestNode(neighb->down2, edpp, newn, level, vert);
+ }
+
+}
+
+int setvertexpointersNode(RNode *neighb, RNode *node, int level, float **v1, float **v2)
+{
+ /* vergelijkt edgelevels , als gelijk zet het de vertexpointers */
+
+ if(neighb==0) return 0;
+
+ if(neighb->ed1==node) {
+ if(neighb->lev1==level) {
+ *v1= neighb->v1;
+ *v2= neighb->v2;
+ return 1;
+ }
+ }
+ else if(neighb->ed2==node) {
+ if(neighb->lev2==level) {
+ *v1= neighb->v2;
+ *v2= neighb->v3;
+ return 1;
+ }
+ }
+ else if(neighb->ed3==node) {
+ if(neighb->lev3==level) {
+ if(neighb->type==3) {
+ *v1= neighb->v3;
+ *v2= neighb->v1;
+ }
+ else {
+ *v1= neighb->v3;
+ *v2= neighb->v4;
+ }
+ return 1;
+ }
+ }
+ else if(neighb->ed4==node) {
+ if(neighb->lev4==level) {
+ *v1= neighb->v4;
+ *v2= neighb->v1;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+float edlen(float *v1, float *v2)
+{
+ return (v1[0]-v2[0])*(v1[0]-v2[0])+ (v1[1]-v2[1])*(v1[1]-v2[1])+ (v1[2]-v2[2])*(v1[2]-v2[2]);
+}
+
+
+void subdivideTriNode(RNode *node, RNode *edge)
+{
+ RNode *n1, *n2, *up;
+ float fu, fv, fl, *v1, *v2; /* , AreaT3Dfl(); ... from arithb... */
+ int uvl;
+
+ if(node->down1 || node->down2) {
+ /* printf("trinode: subd already done\n"); */
+ return;
+ }
+
+ /* bepaal subdivide richting */
+
+ if(edge==0) {
+ /* areathreshold */
+ if(node->area<nodelimit) return;
+
+ fu= edlen(node->v1, node->v2);
+ fv= edlen(node->v2, node->v3);
+ fl= edlen(node->v3, node->v1);
+
+ if(fu>fv && fu>fl) uvl= 1;
+ else if(fv>fu && fv>fl) uvl= 2;
+ else uvl= 3;
+ }
+ else {
+
+ if(edge==node->ed1) uvl= 1;
+ else if(edge==node->ed2) uvl= 2;
+ else uvl= 3;
+ }
+
+ /* moeten naastliggende nodes dieper? Recursief! */
+ n1= 0;
+ if(uvl==1) {
+ if(node->ed1 && node->ed1->down1==0) n1= node->ed1;
+ }
+ else if(uvl==2) {
+ if(node->ed2 && node->ed2->down1==0) n1= node->ed2;
+ }
+ else {
+ if(node->ed3 && node->ed3->down1==0) n1= node->ed3;
+ }
+ if(n1) {
+ up= node->up;
+ while(up) { /* ook testen op ed4 !!! */
+ if(n1->ed1==up || n1->ed2==up || n1->ed3==up || n1->ed4==up) {
+ subdivideNode(n1, up);
+ break;
+ }
+ up= up->up;
+ }
+ }
+
+ /* Het subdividen */
+ n1= mallocNode();
+ memcpy(n1, node, sizeof(RNode));
+ n2= mallocNode();
+ memcpy(n2, node, sizeof(RNode));
+
+ n1->up= node;
+ n2->up= node;
+
+ node->down1= n1;
+ node->down2= n2;
+
+ /* subdivide edge 1 */
+ if(uvl==1) {
+
+ /* EERSTE NODE krijgt edge 2 */
+ n1->ed3= n2;
+ n1->lev3= 0;
+ replaceAllNode(n1->ed2, n1);
+ n1->lev1++;
+ replaceTestNode(n1->ed1, &(n1->ed1), n1, n1->lev1, n1->v2);
+
+ /* TWEEDE NODE krijgt edge 3 */
+ n2->ed2= n1;
+ n2->lev2= 0;
+ replaceAllNode(n2->ed3, n2);
+ n2->lev1++;
+ replaceTestNode(n2->ed1, &(n2->ed1), n2, n2->lev1, n2->v1);
+
+ /* NIEUWE VERTEX uit edge 1 */
+ if( setvertexpointersNode(n1->ed1, n1, n1->lev1, &v1, &v2) ) { /* nodes hebben gelijke levels */
+ if(v1== n1->v2) {
+ n1->v1= v2;
+ n2->v2= v2;
+ }
+ else {
+ n1->v1= v1;
+ n2->v2= v1;
+ }
+ }
+ else {
+ n1->v1= n2->v2= mallocVert();
+ n1->v1[0]= 0.5*(node->v1[0]+ node->v2[0]);
+ n1->v1[1]= 0.5*(node->v1[1]+ node->v2[1]);
+ n1->v1[2]= 0.5*(node->v1[2]+ node->v2[2]);
+ n1->v1[3]= node->v1[3]; /* color */
+ }
+ }
+ else if(uvl==2) {
+
+ /* EERSTE NODE krijgt edge 1 */
+ n1->ed3= n2;
+ n1->lev3= 0;
+ replaceAllNode(n1->ed1, n1);
+ n1->lev2++;
+ replaceTestNode(n1->ed2, &(n1->ed2), n1, n1->lev2, n1->v2);
+
+ /* TWEEDE NODE krijgt edge 3 */
+ n2->ed1= n1;
+ n2->lev1= 0;
+ replaceAllNode(n2->ed3, n2);
+ n2->lev2++;
+ replaceTestNode(n2->ed2, &(n2->ed2), n2, n2->lev2, n2->v3);
+
+ /* NIEUWE VERTEX uit edge 2 */
+ if( setvertexpointersNode(n1->ed2, n1, n1->lev2, &v1, &v2) ) { /* nodes hebben gelijke levels */
+ if(v1== n1->v2) {
+ n1->v3= v2;
+ n2->v2= v2;
+ }
+ else {
+ n1->v3= v1;
+ n2->v2= v1;
+ }
+ }
+ else {
+ n1->v3= n2->v2= mallocVert();
+ n1->v3[0]= 0.5*(node->v2[0]+ node->v3[0]);
+ n1->v3[1]= 0.5*(node->v2[1]+ node->v3[1]);
+ n1->v3[2]= 0.5*(node->v2[2]+ node->v3[2]);
+ n1->v3[3]= node->v1[3]; /* color */
+ }
+ }
+ else if(uvl==3) {
+
+ /* EERSTE NODE krijgt edge 1 */
+ n1->ed2= n2;
+ n1->lev2= 0;
+ replaceAllNode(n1->ed1, n1);
+ n1->lev3++;
+ replaceTestNode(n1->ed3, &(n1->ed3), n1, n1->lev3, n1->v1);
+
+ /* TWEEDE NODE krijgt edge 2 */
+ n2->ed1= n1;
+ n2->lev1= 0;
+ replaceAllNode(n2->ed2, n2);
+ n2->lev3++;
+ replaceTestNode(n2->ed3, &(n2->ed3), n2, n2->lev3, n2->v3);
+
+ /* NIEUWE VERTEX uit edge 3 */
+ if( setvertexpointersNode(n1->ed3, n1, n1->lev3, &v1, &v2) ) { /* nodes hebben gelijke levels */
+ if(v1== n1->v1) {
+ n1->v3= v2;
+ n2->v1= v2;
+ }
+ else {
+ n1->v3= v1;
+ n2->v1= v1;
+ }
+ }
+ else {
+ n1->v3= n2->v1= mallocVert();
+ n1->v3[0]= 0.5*(node->v1[0]+ node->v3[0]);
+ n1->v3[1]= 0.5*(node->v1[1]+ node->v3[1]);
+ n1->v3[2]= 0.5*(node->v1[2]+ node->v3[2]);
+ n1->v3[3]= node->v3[3]; /* color */
+ }
+ }
+ n1->area= AreaT3Dfl(n1->v1, n1->v2, n1->v3);
+ n2->area= AreaT3Dfl(n2->v1, n2->v2, n2->v3);
+
+}
+
+
+void subdivideNode(RNode *node, RNode *edge)
+{
+ RNode *n1, *n2, *up;
+ float fu, fv, *v1, *v2;/*, AreaQ3Dfl(); ... from arithb... */
+ int uvl;
+
+ if(Ntotnode>RG.maxnode) return;
+
+ if(node->type==3) {
+ subdivideTriNode(node, edge);
+ return;
+ }
+
+ if(node->down1 || node->down2) {
+ /* printf("subdivide Node: already done \n"); */
+ return;
+ }
+
+ /* bepaal subdivide richting */
+
+ if(edge==0) {
+ /* areathreshold */
+ if(node->area<nodelimit) {
+ return;
+ }
+ fu= fabs(node->v1[0]- node->v2[0])+ fabs(node->v1[1]- node->v2[1]) +fabs(node->v1[2]- node->v2[2]);
+ fv= fabs(node->v1[0]- node->v4[0])+ fabs(node->v1[1]- node->v4[1]) +fabs(node->v1[2]- node->v4[2]);
+ if(fu>fv) uvl= 1;
+ else uvl= 2;
+ }
+ else {
+ if(edge==node->ed1 || edge==node->ed3) uvl= 1;
+ else uvl= 2;
+ }
+
+ /* moeten naastliggende nodes dieper? Recursief! */
+ n1= n2= 0;
+ if(uvl==1) {
+ if(node->ed1 && node->ed1->down1==0) n1= node->ed1;
+ if(node->ed3 && node->ed3->down1==0) n2= node->ed3;
+ }
+ else {
+ if(node->ed2 && node->ed2->down1==0) n1= node->ed2;
+ if(node->ed4 && node->ed4->down1==0) n2= node->ed4;
+ }
+ if(n1) {
+ up= node->up;
+ while(up) {
+ if(n1->ed1==up || n1->ed2==up || n1->ed3==up || n1->ed4==up) {
+ /* printf("recurs subd\n"); */
+ subdivideNode(n1, up);
+ break;
+ }
+ up= up->up;
+ }
+ }
+ if(n2) {
+ up= node->up;
+ while(up) {
+ if(n2->ed1==up || n2->ed2==up || n2->ed3==up || n2->ed4==up) {
+ /* printf("recurs subd\n"); */
+ subdivideNode(n2, up);
+ break;
+ }
+ up= up->up;
+ }
+ }
+
+ /* Het subdividen */
+ n1= mallocNode();
+ memcpy(n1, node, sizeof(RNode));
+ n2= mallocNode();
+ memcpy(n2, node, sizeof(RNode));
+
+ n1->up= node;
+ n2->up= node;
+
+ node->down1= n1;
+ node->down2= n2;
+
+ /* subdivide edge 1 en 3 */
+ if(uvl==1) {
+
+ /* EERSTE NODE krijgt edge 2 */
+ n1->ed4= n2;
+ n1->lev4= 0;
+ replaceAllNode(n1->ed2, n1);
+ n1->lev1++;
+ n1->lev3++;
+ replaceTestNode(n1->ed1, &(n1->ed1), n1, n1->lev1, n1->v2);
+ replaceTestNode(n1->ed3, &(n1->ed3), n1, n1->lev3, n1->v3);
+
+ /* TWEEDE NODE krijgt edge 4 */
+ n2->ed2= n1;
+ n2->lev2= 0;
+ replaceAllNode(n2->ed4, n2);
+ n2->lev1++;
+ n2->lev3++;
+ replaceTestNode(n2->ed1, &(n2->ed1), n2, n2->lev1, n2->v1);
+ replaceTestNode(n2->ed3, &(n2->ed3), n2, n2->lev3, n2->v4);
+
+ /* NIEUWE VERTEX uit edge 1 */
+ if( setvertexpointersNode(n1->ed1, n1, n1->lev1, &v1, &v2) ) { /* nodes hebben gelijke levels */
+ if(v1== n1->v2) {
+ n1->v1= v2;
+ n2->v2= v2;
+ }
+ else {
+ n1->v1= v1;
+ n2->v2= v1;
+ }
+ }
+ else {
+ n1->v1= n2->v2= mallocVert();
+ n1->v1[0]= 0.5*(node->v1[0]+ node->v2[0]);
+ n1->v1[1]= 0.5*(node->v1[1]+ node->v2[1]);
+ n1->v1[2]= 0.5*(node->v1[2]+ node->v2[2]);
+ n1->v1[3]= node->v1[3]; /* color */
+ }
+
+ /* NIEUWE VERTEX uit edge 3 */
+ if( setvertexpointersNode(n1->ed3, n1, n1->lev3, &v1, &v2) ) { /* nodes hebben gelijke levels */
+ if(v1== n1->v3) {
+ n1->v4= v2;
+ n2->v3= v2;
+ }
+ else {
+ n1->v4= v1;
+ n2->v3= v1;
+ }
+ }
+ else {
+ n1->v4= n2->v3= mallocVert();
+ n1->v4[0]= 0.5*(node->v3[0]+ node->v4[0]);
+ n1->v4[1]= 0.5*(node->v3[1]+ node->v4[1]);
+ n1->v4[2]= 0.5*(node->v3[2]+ node->v4[2]);
+ n1->v4[3]= node->v4[3]; /* color */
+ }
+ }
+ /* subdivide edge 2 en 4 */
+ else if(uvl==2) {
+
+ /* EERSTE NODE krijgt edge 1 */
+ n1->ed3= n2;
+ n1->lev3= 0;
+ replaceAllNode(n1->ed1, n1);
+ n1->lev2++;
+ n1->lev4++;
+ replaceTestNode(n1->ed2, &(n1->ed2), n1, n1->lev2, n1->v2);
+ replaceTestNode(n1->ed4, &(n1->ed4), n1, n1->lev4, n1->v1);
+
+ /* TWEEDE NODE krijgt edge 3 */
+ n2->ed1= n1;
+ n2->lev1= 0;
+ replaceAllNode(n2->ed3, n2);
+ n2->lev2++;
+ n2->lev4++;
+ replaceTestNode(n2->ed2, &(n2->ed2), n2, n2->lev2, n2->v3);
+ replaceTestNode(n2->ed4, &(n2->ed4), n2, n2->lev4, n2->v4);
+
+ /* NIEUWE VERTEX uit edge 2 */
+ if( setvertexpointersNode(n1->ed2, n1, n1->lev2, &v1, &v2) ) { /* nodes hebben gelijke levels */
+ if(v1== n1->v2) {
+ n1->v3= v2;
+ n2->v2= v2;
+ }
+ else {
+ n1->v3= v1;
+ n2->v2= v1;
+ }
+ }
+ else {
+ n1->v3= n2->v2= mallocVert();
+ n1->v3[0]= 0.5*(node->v2[0]+ node->v3[0]);
+ n1->v3[1]= 0.5*(node->v2[1]+ node->v3[1]);
+ n1->v3[2]= 0.5*(node->v2[2]+ node->v3[2]);
+ n1->v3[3]= node->v3[3]; /* color */
+ }
+
+ /* NIEUWE VERTEX uit edge 4 */
+ if( setvertexpointersNode(n1->ed4, n1, n1->lev4, &v1, &v2) ) { /* nodes hebben gelijke levels */
+ if(v1== n1->v1) {
+ n1->v4= v2;
+ n2->v1= v2;
+ }
+ else {
+ n1->v4= v1;
+ n2->v1= v1;
+ }
+ }
+ else {
+ n1->v4= n2->v1= mallocVert();
+ n1->v4[0]= 0.5*(node->v1[0]+ node->v4[0]);
+ n1->v4[1]= 0.5*(node->v1[1]+ node->v4[1]);
+ n1->v4[2]= 0.5*(node->v1[2]+ node->v4[2]);
+ n1->v4[3]= node->v4[3]; /* color */
+ }
+
+ }
+
+ n1->area= AreaQ3Dfl(n1->v1, n1->v2, n1->v3, n1->v4);
+ n2->area= AreaQ3Dfl(n2->v1, n2->v2, n2->v3, n2->v4);
+
+}
+
+int comparelevel(RNode *node, RNode *nb, int level)
+{
+ /* recursief afdalen: bij diepste node testen */
+ /* return 1 is gelijk of hoger */
+
+ if(nb==0) return 1;
+
+ if(nb->down1) {
+ return 0;
+
+ /* HIER ZIT EEN FOUT, MAAR WELKE? (zonder dit werkt 't ook, maar langzamer)
+ n1= nb->down1;
+ if(n1->ed1==node) return comparelevel(node, n1, level);
+ if(n1->ed2==node) return comparelevel(node, n1, level);
+ if(n1->ed3==node) return comparelevel(node, n1, level);
+ if(n1->ed4==node) return comparelevel(node, n1, level);
+ n1= nb->down2;
+ if(n1->ed1==node) return comparelevel(node, n1, level);
+ if(n1->ed2==node) return comparelevel(node, n1, level);
+ if(n1->ed3==node) return comparelevel(node, n1, level);
+ if(n1->ed4==node) return comparelevel(node, n1, level);
+ printf(" dit kan niet ");
+ return 0;
+ */
+
+ }
+
+ if(nb->down1==0) {
+ /* if(nb->ed1==node) return (nb->lev1<=level); */
+ /* if(nb->ed2==node) return (nb->lev2<=level); */
+ /* if(nb->ed3==node) return (nb->lev3<=level); */
+ /* if(nb->ed4==node) return (nb->lev4<=level); */
+
+ return 1; /* is hogere node */
+ }
+ return 1;
+}
+
+void deleteTriNodes(RNode *node) /* beide kinderen van node */
+{
+ RNode *n1, *n2;
+
+ /* als naastliggende nodes dieper zijn: geen delete */
+ /* enkel twee nodes testen, van andere verandert level niet */
+
+ n1= node->down1;
+ n2= node->down2;
+
+ if(n1==0 || n2==0) return;
+
+ if(n1->down1 || n2->down1) return;
+
+ /* aan edges mag geen gesubdivide node zitten */
+
+ if(n1->ed1 && n1->ed1->down1) return;
+ if(n1->ed2 && n1->ed2->down1) return;
+ if(n1->ed3 && n1->ed3->down1) return;
+
+ if(n2->ed1 && n2->ed1->down1) return;
+ if(n2->ed2 && n2->ed2->down1) return;
+ if(n2->ed3 && n2->ed3->down1) return;
+
+ replaceAllNodeInv(n1->ed1, n1);
+ replaceAllNodeInv(n1->ed2, n1);
+ replaceAllNodeInv(n1->ed3, n1);
+
+ replaceAllNodeUp(n1->ed1, n1);
+ replaceAllNodeUp(n1->ed2, n1);
+ replaceAllNodeUp(n1->ed3, n1);
+
+ replaceAllNodeInv(n2->ed1, n2);
+ replaceAllNodeInv(n2->ed2, n2);
+ replaceAllNodeInv(n2->ed3, n2);
+
+ replaceAllNodeUp(n2->ed1, n2);
+ replaceAllNodeUp(n2->ed2, n2);
+ replaceAllNodeUp(n2->ed3, n2);
+
+ n1->down1= (RNode *)12; /* voor debug */
+ n2->down1= (RNode *)12;
+
+ freeNode(n1);
+ freeNode(n2);
+ node->down1= node->down2= 0;
+
+}
+
+ /* beide kinderen van node */
+void deleteNodes(RNode *node)
+{
+ RNode *n1, *n2;
+
+ /* als naastliggende nodes dieper zijn: geen delete */
+ /* enkel twee nodes testen, van andere verandert level niet */
+
+ if(node->type==3) {
+ deleteTriNodes(node);
+ return;
+ }
+
+ n1= node->down1;
+ n2= node->down2;
+
+ if(n1==0 || n2==0) return;
+
+ if(n1->down1 || n2->down1) return;
+
+ if(n1->ed3==n2) {
+
+ /* aan edges mag geen gesubdivide node zitten */
+
+ if(n1->ed1 && n1->ed1->down1) return;
+ if(n1->ed2 && n1->ed2->down1) return;
+ if(n1->ed4 && n1->ed4->down1) return;
+
+ if(n2->ed2 && n2->ed2->down1) return;
+ if(n2->ed3 && n2->ed3->down1) return;
+ if(n2->ed4 && n2->ed4->down1) return;
+
+ replaceAllNodeInv(n1->ed1, n1);
+ replaceAllNodeInv(n1->ed2, n1);
+ replaceAllNodeInv(n1->ed4, n1);
+
+ replaceAllNodeUp(n1->ed1, n1);
+ replaceAllNodeUp(n1->ed2, n1);
+ replaceAllNodeUp(n1->ed4, n1);
+
+ replaceAllNodeInv(n2->ed2, n2);
+ replaceAllNodeInv(n2->ed3, n2);
+ replaceAllNodeInv(n2->ed4, n2);
+
+ replaceAllNodeUp(n2->ed2, n2);
+ replaceAllNodeUp(n2->ed3, n2);
+ replaceAllNodeUp(n2->ed4, n2);
+
+ n1->down1= (RNode *)12; /* voor debug */
+ n2->down1= (RNode *)12;
+
+ freeNode(n1);
+ freeNode(n2);
+ node->down1= node->down2= 0;
+
+ return;
+ }
+ else if(n1->ed4==n2) {
+
+ if(n1->ed1 && n1->ed1->down1) return;
+ if(n1->ed2 && n1->ed2->down1) return;
+ if(n1->ed3 && n1->ed3->down1) return;
+
+ if(n2->ed1 && n2->ed1->down1) return;
+ if(n2->ed3 && n2->ed3->down1) return;
+ if(n2->ed4 && n2->ed4->down1) return;
+
+ replaceAllNodeInv(n1->ed1, n1);
+ replaceAllNodeInv(n1->ed2, n1);
+ replaceAllNodeInv(n1->ed3, n1);
+
+ replaceAllNodeUp(n1->ed1, n1);
+ replaceAllNodeUp(n1->ed2, n1);
+ replaceAllNodeUp(n1->ed3, n1);
+
+ replaceAllNodeInv(n2->ed1, n2);
+ replaceAllNodeInv(n2->ed3, n2);
+ replaceAllNodeInv(n2->ed4, n2);
+
+ replaceAllNodeUp(n2->ed1, n2);
+ replaceAllNodeUp(n2->ed3, n2);
+ replaceAllNodeUp(n2->ed4, n2);
+
+ n1->down1= (RNode *)12; /* voor debug */
+ n2->down1= (RNode *)12;
+
+ freeNode(n1);
+ freeNode(n2);
+ node->down1= node->down2= 0;
+
+ return;
+ }
+
+}
+
+
diff --git a/source/blender/radiosity/intern/source/radpostprocess.c b/source/blender/radiosity/intern/source/radpostprocess.c
new file mode 100644
index 00000000000..8cbbfb1f4de
--- /dev/null
+++ b/source/blender/radiosity/intern/source/radpostprocess.c
@@ -0,0 +1,871 @@
+/* ***************************************
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+
+
+
+ radpostprocess.c nov/dec 1992
+ may 1999
+
+ - faces
+ - filtering and node-limit
+ - apply to meshes
+ $Id$
+
+ *************************************** */
+
+#include <stdlib.h>
+#include <math.h>
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "DNA_material_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+#include "DNA_radio_types.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_mesh.h"
+#include "BKE_object.h"
+#include "BKE_material.h"
+
+#include "BIF_screen.h" /* waitcursor */
+#include "BIF_editview.h" /* deselectall */
+
+#include "BDR_editobject.h" /* delete_obj */
+
+#include "radio.h"
+
+/* locals? not. done in radio.h... */
+/* void rad_addmesh(void); */
+/* void rad_replacemesh(void); */
+
+void addaccu(register char *z, register char *t)
+{
+ register int div, mul;
+
+ mul= *t;
+ div= mul+1;
+ (*t)++;
+
+ t[1]= (mul*t[1]+z[1])/div;
+ t[2]= (mul*t[2]+z[2])/div;
+ t[3]= (mul*t[3]+z[3])/div;
+
+}
+
+void addaccuweight(register char *z, register char *t, int w)
+{
+ register int div, mul;
+
+ if(w==0) w= 1;
+
+ mul= *t;
+ div= mul+w;
+ if(div>255) return;
+ (*t)= div;
+
+ t[1]= (mul*t[1]+w*z[1])/div;
+ t[2]= (mul*t[2]+w*z[2])/div;
+ t[3]= (mul*t[3]+w*z[3])/div;
+
+}
+
+void triaweight(Face *face, int *w1, int *w2, int *w3)
+{
+ float n1[3], n2[3], n3[3], temp;
+
+ n1[0]= face->v2[0]-face->v1[0];
+ n1[1]= face->v2[1]-face->v1[1];
+ n1[2]= face->v2[2]-face->v1[2];
+ n2[0]= face->v3[0]-face->v2[0];
+ n2[1]= face->v3[1]-face->v2[1];
+ n2[2]= face->v3[2]-face->v2[2];
+ n3[0]= face->v1[0]-face->v3[0];
+ n3[1]= face->v1[1]-face->v3[1];
+ n3[2]= face->v1[2]-face->v3[2];
+ Normalise(n1);
+ Normalise(n2);
+ Normalise(n3);
+ temp= 32.0/(PI);
+ *w1= 0.5+temp*acos(-n1[0]*n3[0]-n1[1]*n3[1]-n1[2]*n3[2]);
+ *w2= 0.5+temp*acos(-n1[0]*n2[0]-n1[1]*n2[1]-n1[2]*n2[2]);
+ *w3= 0.5+temp*acos(-n2[0]*n3[0]-n2[1]*n3[1]-n2[2]*n3[2]);
+
+}
+
+
+
+void init_face_tab()
+{
+ int a= 0;
+
+ if(RG.facebase==0) {
+ RG.facebase= MEM_callocN(sizeof(void *)*RAD_MAXFACETAB, "init_face_tab");
+ }
+ for(a=0; a<RAD_MAXFACETAB; a++) {
+ if(RG.facebase[a]==0) break;
+ MEM_freeN(RG.facebase[a]);
+ RG.facebase[a]= 0;
+ }
+ RG.totface= 0;
+}
+
+Face *addface()
+{
+ Face *face;
+ int a;
+
+ if(RG.totface<0 || RG.totface>RAD_MAXFACETAB*1024 ) {
+ printf("error in addface: %d\n", RG.totface);
+ return 0;
+ }
+ a= RG.totface>>10;
+ face= RG.facebase[a];
+ if(face==0) {
+ face= MEM_callocN(1024*sizeof(Face),"addface");
+ RG.facebase[a]= face;
+ }
+ face+= (RG.totface & 1023);
+
+ RG.totface++;
+
+ return face;
+
+}
+
+void makeface(float *v1, float *v2, float *v3, float *v4, RNode *rn)
+{
+ Face *face;
+
+ face= addface();
+ face->v1= v1;
+ face->v2= v2;
+ face->v3= v3;
+ face->v4= v4;
+ face->col= rn->col;
+ face->matindex= rn->par->matindex;
+}
+
+
+void anchorQuadface(RNode *rn, float *v1, float *v2, float *v3, float *v4, int flag)
+{
+
+ switch(flag) {
+ case 1:
+ makeface(rn->v1, v1, rn->v4, 0, rn);
+ makeface(v1, rn->v3, rn->v4, 0, rn);
+ makeface(v1, rn->v2, rn->v3, 0, rn);
+ break;
+ case 2:
+ makeface(rn->v2, v2, rn->v1, 0, rn);
+ makeface(v2, rn->v4, rn->v1, 0, rn);
+ makeface(v2, rn->v3, rn->v4, 0, rn);
+ break;
+ case 4:
+ makeface(rn->v3, v3, rn->v2, 0, rn);
+ makeface(v3, rn->v1, rn->v2, 0, rn);
+ makeface(v3, rn->v4, rn->v1, 0, rn);
+ break;
+ case 8:
+ makeface(rn->v4, v4, rn->v3, 0, rn);
+ makeface(v4, rn->v2, rn->v3, 0, rn);
+ makeface(v4, rn->v1, rn->v2, 0, rn);
+ break;
+
+ case 3:
+ makeface(rn->v1, v1, rn->v4, 0, rn);
+ makeface(v1, v2, rn->v4, 0, rn);
+ makeface(v1, rn->v2, v2, 0, rn);
+ makeface(v2, rn->v3, rn->v4, 0, rn);
+ break;
+ case 6:
+ makeface(rn->v2, v2, rn->v1, 0, rn);
+ makeface(v2, v3, rn->v1, 0, rn);
+ makeface(v2, rn->v3, v3, 0, rn);
+ makeface(v3, rn->v4, rn->v1, 0, rn);
+ break;
+ case 12:
+ makeface(rn->v3, v3, rn->v2, 0, rn);
+ makeface(v3, v4, rn->v2, 0, rn);
+ makeface(v3, rn->v4, v4, 0, rn);
+ makeface(v4, rn->v1, rn->v2, 0, rn);
+ break;
+ case 9:
+ makeface(rn->v4, v4, rn->v3, 0, rn);
+ makeface(v4, v1, rn->v3, 0, rn);
+ makeface(v4, rn->v1, v1, 0, rn);
+ makeface(v1, rn->v2, rn->v3, 0, rn);
+ break;
+
+ case 5:
+ makeface(rn->v1, v1, v3, rn->v4, rn);
+ makeface(v1, rn->v2, rn->v3, v3, rn);
+ break;
+ case 10:
+ makeface(rn->v2, v2, v4, rn->v1, rn);
+ makeface(v2, rn->v3, rn->v4, v4, rn);
+ break;
+
+ case 7:
+ makeface(rn->v1, v1, v3, rn->v4, rn);
+ makeface(v1, v2, v3, 0, rn);
+ makeface(v1, rn->v2, v2, 0, rn);
+ makeface(v2, rn->v3, v3, 0, rn);
+ break;
+ case 14:
+ makeface(rn->v2, v2, v4, rn->v1, rn);
+ makeface(v2, v3, v4, 0, rn);
+ makeface(v2, rn->v3, v3, 0, rn);
+ makeface(v3, rn->v4, v4, 0, rn);
+ break;
+ case 13:
+ makeface(rn->v3, v3, v1, rn->v2, rn);
+ makeface(v3, v4, v1, 0, rn);
+ makeface(v3, rn->v4, v4, 0, rn);
+ makeface(v4, rn->v1, v1, 0, rn);
+ break;
+ case 11:
+ makeface(rn->v4, v4, v2, rn->v3, rn);
+ makeface(v4, v1, v2, 0, rn);
+ makeface(v4, rn->v1, v1, 0, rn);
+ makeface(v1, rn->v2, v2, 0, rn);
+ break;
+
+ case 15:
+ makeface(v1, v2, v3, v4, rn);
+ makeface(v1, rn->v2, v2, 0, rn);
+ makeface(v2, rn->v3, v3, 0, rn);
+ makeface(v3, rn->v4, v4, 0, rn);
+ makeface(v4, rn->v1, v1, 0, rn);
+ break;
+ }
+}
+
+void anchorTriface(RNode *rn, float *v1, float *v2, float *v3, int flag)
+{
+ switch(flag) {
+ case 1:
+ makeface(rn->v1, v1, rn->v3, 0, rn);
+ makeface(v1, rn->v2, rn->v3, 0, rn);
+ break;
+ case 2:
+ makeface(rn->v2, v2, rn->v1, 0, rn);
+ makeface(v2, rn->v3, rn->v1, 0, rn);
+ break;
+ case 4:
+ makeface(rn->v3, v3, rn->v2, 0, rn);
+ makeface(v3, rn->v1, rn->v2, 0, rn);
+ break;
+
+ case 3:
+ makeface(rn->v1, v2, rn->v3, 0, rn);
+ makeface(rn->v1, v1, v2, 0, rn);
+ makeface(v1, rn->v2, v2, 0, rn);
+ break;
+ case 6:
+ makeface(rn->v2, v3, rn->v1, 0, rn);
+ makeface(rn->v2, v2, v3, 0, rn);
+ makeface(v2, rn->v3, v3, 0, rn);
+ break;
+ case 5:
+ makeface(rn->v3, v1, rn->v2, 0, rn);
+ makeface(rn->v3, v3, v1, 0, rn);
+ makeface(v3, rn->v1, v1, 0, rn);
+ break;
+
+ case 7:
+ makeface(v1, v2, v3, 0, rn);
+ makeface(rn->v1, v1, v3, 0, rn);
+ makeface(rn->v2, v2, v1, 0, rn);
+ makeface(rn->v3, v3, v2, 0, rn);
+ break;
+ }
+}
+
+
+float *findmiddlevertex(RNode *node, RNode *nb, float *v1, float *v2)
+{
+ int test= 0;
+
+ if(nb==0) return 0;
+
+ if(nb->ed1==node) {
+ if(nb->v1==v1 || nb->v1==v2) test++;
+ if(nb->v2==v1 || nb->v2==v2) test+=2;
+ if(test==1) return nb->v2;
+ else if(test==2) return nb->v1;
+ }
+ else if(nb->ed2==node) {
+ if(nb->v2==v1 || nb->v2==v2) test++;
+ if(nb->v3==v1 || nb->v3==v2) test+=2;
+ if(test==1) return nb->v3;
+ else if(test==2) return nb->v2;
+ }
+ else if(nb->ed3==node) {
+ if(nb->type==4) {
+ if(nb->v3==v1 || nb->v3==v2) test++;
+ if(nb->v4==v1 || nb->v4==v2) test+=2;
+ if(test==1) return nb->v4;
+ else if(test==2) return nb->v3;
+
+ }
+ else {
+ if(nb->v3==v1 || nb->v3==v2) test++;
+ if(nb->v1==v1 || nb->v1==v2) test+=2;
+ if(test==1) return nb->v1;
+ else if(test==2) return nb->v3;
+ }
+ }
+ else if(nb->ed4==node) {
+ if(nb->v4==v1 || nb->v4==v2) test++;
+ if(nb->v1==v1 || nb->v1==v2) test+=2;
+ if(test==1) return nb->v1;
+ else if(test==2) return nb->v4;
+ }
+ return 0;
+}
+
+void make_face_tab() /* zorgt voor ankers */
+{
+ RNode *rn, **el;
+ Face *face = NULL;
+ float *v1, *v2, *v3, *v4;
+ int a, flag, w1, w2, w3;
+ char *charcol;
+
+ if(RG.totelem==0) return;
+
+ init_face_tab();
+
+ RG.igamma= 1.0/RG.gamma;
+ RG.radfactor= RG.radfac*pow(64*64, RG.igamma);
+
+ /* vlakkleuren omzetten */
+ el= RG.elem;
+ for(a=RG.totelem; a>0; a--, el++) {
+ rn= *el;
+ charcol= (char *)&( rn->col );
+
+ charcol[3]= calculatecolor(rn->totrad[0]);
+ charcol[2]= calculatecolor(rn->totrad[1]);
+ charcol[1]= calculatecolor(rn->totrad[2]);
+ }
+
+ /* nodes aflopen en Face's maken */
+ el= RG.elem;
+ for(a=RG.totelem; a>0; a--, el++) {
+
+ rn= *el;
+
+ rn->v1[3]= 0.0;
+ rn->v2[3]= 0.0;
+ rn->v3[3]= 0.0;
+ if(rn->v4) rn->v4[3]= 0.0;
+
+ /* test edges op subdivide */
+ flag= 0;
+ v1= v2= v3= v4= 0;
+ if(rn->ed1) {
+ v1= findmiddlevertex(rn, rn->ed1->down1, rn->v1, rn->v2);
+ if(v1) flag |= 1;
+ }
+ if(rn->ed2) {
+ v2= findmiddlevertex(rn, rn->ed2->down1, rn->v2, rn->v3);
+ if(v2) flag |= 2;
+ }
+ if(rn->ed3) {
+ if(rn->type==4)
+ v3= findmiddlevertex(rn, rn->ed3->down1, rn->v3, rn->v4);
+ else
+ v3= findmiddlevertex(rn, rn->ed3->down1, rn->v3, rn->v1);
+ if(v3) flag |= 4;
+ }
+ if(rn->ed4) {
+ v4= findmiddlevertex(rn, rn->ed4->down1, rn->v4, rn->v1);
+ if(v4) flag |= 8;
+ }
+
+ /* met flag en vertexpointers kunnen nu Face's gemaakt*/
+
+ if(flag==0) {
+ makeface(rn->v1, rn->v2, rn->v3, rn->v4, rn);
+ }
+ else if(rn->type==4) anchorQuadface(rn, v1, v2, v3, v4, flag);
+ else anchorTriface(rn, v1, v2, v3, flag);
+ }
+
+ /* optellen */
+ for(a=0; a<RG.totface; a++) {
+
+ RAD_NEXTFACE(a);
+
+ if(face->v4) {
+ addaccuweight( (char *)&(face->col), (char *)(face->v1+3), 16 );
+ addaccuweight( (char *)&(face->col), (char *)(face->v2+3), 16 );
+ addaccuweight( (char *)&(face->col), (char *)(face->v3+3), 16 );
+ addaccuweight( (char *)&(face->col), (char *)(face->v4+3), 16 );
+ }
+ else {
+ triaweight(face, &w1, &w2, &w3);
+ addaccuweight( (char *)&(face->col), (char *)(face->v1+3), w1 );
+ addaccuweight( (char *)&(face->col), (char *)(face->v2+3), w2 );
+ addaccuweight( (char *)&(face->col), (char *)(face->v3+3), w3 );
+ }
+ }
+
+}
+
+void filterFaces()
+{
+ /* alle kleuren van vertices in faces en weer terug */
+
+ Face *face = NULL;
+ int a, w1, w2, w3;
+
+ if(RG.totface==0) return;
+
+ /* wissen */
+ for(a=0; a<RG.totface; a++) {
+ RAD_NEXTFACE(a);
+ face->col= 0;
+ }
+
+ /* optellen: punten bij vlakken */
+ for(a=0; a<RG.totface; a++) {
+ RAD_NEXTFACE(a);
+
+ if(face->v4) {
+ addaccuweight( (char *)(face->v1+3), (char *)&(face->col), 16 );
+ addaccuweight( (char *)(face->v2+3), (char *)&(face->col), 16 );
+ addaccuweight( (char *)(face->v3+3), (char *)&(face->col), 16 );
+ addaccuweight( (char *)(face->v4+3), (char *)&(face->col), 16 );
+ }
+ else {
+ triaweight(face, &w1, &w2, &w3);
+ addaccuweight( (char *)(face->v1+3), (char *)&(face->col), w1 );
+ addaccuweight( (char *)(face->v2+3), (char *)&(face->col), w2 );
+ addaccuweight( (char *)(face->v3+3), (char *)&(face->col), w3 );
+ }
+ }
+
+ /* wissen */
+ for(a=0; a<RG.totface; a++) {
+ RAD_NEXTFACE(a);
+ face->v1[3]= 0.0;
+ face->v2[3]= 0.0;
+ face->v3[3]= 0.0;
+ if(face->v4) face->v4[3]= 0.0;
+ }
+
+
+ /* optellen: vlakken bij punten */
+ for(a=0; a<RG.totface; a++) {
+
+ RAD_NEXTFACE(a);
+
+ if(face->v4) {
+ addaccuweight( (char *)&(face->col), (char *)(face->v1+3), 16 );
+ addaccuweight( (char *)&(face->col), (char *)(face->v2+3), 16 );
+ addaccuweight( (char *)&(face->col), (char *)(face->v3+3), 16 );
+ addaccuweight( (char *)&(face->col), (char *)(face->v4+3), 16 );
+ }
+ else {
+ triaweight(face, &w1, &w2, &w3);
+ addaccuweight( (char *)&(face->col), (char *)(face->v1+3), w1 );
+ addaccuweight( (char *)&(face->col), (char *)(face->v2+3), w2 );
+ addaccuweight( (char *)&(face->col), (char *)(face->v3+3), w3 );
+ }
+ }
+}
+
+void calcfiltrad(RNode *rn, float *cd)
+{
+ float area;
+
+ cd[0]= 2.0*rn->totrad[0];
+ cd[1]= 2.0*rn->totrad[1];
+ cd[2]= 2.0*rn->totrad[2];
+ area= 2.0;
+
+ if(rn->ed1) {
+ cd[0]+= rn->ed1->totrad[0];
+ cd[1]+= rn->ed1->totrad[1];
+ cd[2]+= rn->ed1->totrad[2];
+ area+= 1.0;
+ }
+ if(rn->ed2) {
+ cd[0]+= rn->ed2->totrad[0];
+ cd[1]+= rn->ed2->totrad[1];
+ cd[2]+= rn->ed2->totrad[2];
+ area+= 1.0;
+ }
+ if(rn->ed3) {
+ cd[0]+= rn->ed3->totrad[0];
+ cd[1]+= rn->ed3->totrad[1];
+ cd[2]+= rn->ed3->totrad[2];
+ area+= 1.0;
+ }
+ if(rn->ed4) {
+ cd[0]+= rn->ed4->totrad[0];
+ cd[1]+= rn->ed4->totrad[1];
+ cd[2]+= rn->ed4->totrad[2];
+ area+= 1.0;
+ }
+ cd[0]/= area;
+ cd[1]/= area;
+ cd[2]/= area;
+
+}
+
+void filterNodes()
+{
+ /* alle kleuren van nodes in tempblok en weer terug */
+
+ RNode *rn, **el;
+ float *coldata, *cd;
+ int a;
+
+ if(RG.totelem==0) return;
+ /* de upnodes moeten kleur hebben */
+ el= RG.elem;
+ for(a=0; a<RG.totelem; a++, el++) {
+ rn= *el;
+ if(rn->up) {
+ rn->up->totrad[0]= 0.0;
+ rn->up->totrad[1]= 0.0;
+ rn->up->totrad[2]= 0.0;
+ if(rn->up->up) {
+ rn->up->up->totrad[0]= 0.0;
+ rn->up->up->totrad[1]= 0.0;
+ rn->up->up->totrad[2]= 0.0;
+ }
+ }
+ }
+ el= RG.elem;
+ for(a=0; a<RG.totelem; a++, el++) {
+ rn= *el;
+ if(rn->up) {
+ rn->up->totrad[0]+= 0.5*rn->totrad[0];
+ rn->up->totrad[1]+= 0.5*rn->totrad[1];
+ rn->up->totrad[2]+= 0.5*rn->totrad[2];
+ if(rn->up->up) {
+ rn->up->up->totrad[0]+= 0.25*rn->totrad[0];
+ rn->up->up->totrad[1]+= 0.25*rn->totrad[1];
+ rn->up->up->totrad[2]+= 0.25*rn->totrad[2];
+ }
+ }
+ }
+
+ /* met area optellen */
+ cd= coldata= MEM_mallocN(3*4*RG.totelem, "filterNodes");
+ el= RG.elem;
+ for(a=0; a<RG.totelem; a++, el++) {
+ calcfiltrad(*el, cd);
+ cd+= 3;
+ }
+
+ cd= coldata;
+ el= RG.elem;
+ for(a=0; a<RG.totelem; a++, el++) {
+ rn= *el;
+ VECCOPY(rn->totrad, cd);
+ cd+= 3;
+ }
+ MEM_freeN(coldata);
+}
+
+void removeEqualNodes(short limit)
+{
+ /* nodes met kleur gelijk aan elkaar: verwijderen */
+ RNode **el, *rn, *rn1;
+ float thresh, f1, f2;
+ int a, foundone=1, ok;
+ int c1, c2;
+
+ if(limit==0) return;
+
+ thresh= 1.0/(256.0*RG.radfactor);
+ thresh= 3.0*pow(thresh, RG.gamma);
+
+ waitcursor(1);
+
+ while(foundone) {
+ foundone= 0;
+
+ el= RG.elem;
+ for(a=RG.totelem; a>1; a--, el++) {
+ rn= *el;
+ rn1= *(el+1);
+
+ if(rn!=rn->par->first && rn1!=rn1->par->first) {
+ if(rn->up && rn->up==rn1->up) {
+ f1= rn->totrad[0]+ rn->totrad[1]+ rn->totrad[2];
+ f2= rn1->totrad[0]+ rn1->totrad[1]+ rn1->totrad[2];
+
+ ok= 0;
+ if(f1<thresh && f2<thresh) ok= 1;
+ else {
+ c1= calculatecolor(rn->totrad[0]);
+ c2= calculatecolor(rn1->totrad[0]);
+
+ if( abs(c1-c2)<=limit ) {
+ c1= calculatecolor(rn->totrad[1]);
+ c2= calculatecolor(rn1->totrad[1]);
+
+ if( abs(c1-c2)<=limit ) {
+ c1= calculatecolor(rn->totrad[2]);
+ c2= calculatecolor(rn1->totrad[2]);
+
+ if( abs(c1-c2)<=limit ) {
+ ok= 1;
+ }
+ }
+ }
+ }
+
+ if(ok) {
+ rn->up->totrad[0]= 0.5*(rn->totrad[0]+rn1->totrad[0]);
+ rn->up->totrad[1]= 0.5*(rn->totrad[1]+rn1->totrad[1]);
+ rn->up->totrad[2]= 0.5*(rn->totrad[2]+rn1->totrad[2]);
+ rn1= rn->up;
+ deleteNodes(rn1);
+ if(rn1->down1) ;
+ else {
+ foundone++;
+ a--; el++;
+ }
+ }
+ }
+ }
+ }
+ if(foundone) {
+ makeGlobalElemArray();
+ }
+ }
+ waitcursor(0);
+}
+
+#define BLSIZE 32000
+
+void rad_addmesh(void)
+{
+ Face *face = NULL;
+ Object *ob;
+ Mesh *me;
+ MVert *mvert;
+ MFace *mface;
+ Material *ma=0;
+ unsigned int *md, *coldata, *cd;
+ float **fpp, **poindata;
+ float cent[3], min[3], max[3];
+ int a, vcount, vlnr, startf, endf;
+
+ if(RG.totface==0) return;
+
+ /* make sure there's alpha in the color, to distinguish */
+ for(a=0; a<RG.totface; a++) {
+ RAD_NEXTFACE(a);
+ *((unsigned int *)face->v1+3) |= 0x1000000;
+ *((unsigned int *)face->v2+3) |= 0x1000000;
+ *((unsigned int *)face->v3+3) |= 0x1000000;
+ if(face->v4) {
+ *((unsigned int *)face->v4+3) |= 0x1000000;
+ }
+ }
+
+ /* we write in blocks of BLSIZE vertices max */
+ coldata= MEM_mallocN(4*BLSIZE, "writefaces");
+ poindata= MEM_mallocN(sizeof(void *)*BLSIZE, "writefaces1");
+
+ vlnr= 0;
+ endf= 0;
+ while(endf<RG.totface) {
+
+ cd= coldata;
+ fpp= poindata;
+ startf= endf;
+ vcount= 0;
+
+ face= RG.facebase[(startf-1)>>10]+((startf-1) & 1023);
+ for(vlnr=startf; vlnr<RG.totface; vlnr++) {
+ RAD_NEXTFACE(vlnr);
+
+ if( *((unsigned int *)face->v1+3) & 0x1000000 ) { /* is a color */
+ *cd= *((unsigned int *)face->v1+3);
+ *((unsigned int *)face->v1+3) = vcount;
+ *fpp= face->v1;
+ fpp++; vcount++; cd++;
+ }
+ if( *((unsigned int *)face->v2+3) & 0x1000000 ) {
+ *cd= *((unsigned int *)face->v2+3);
+ *((unsigned int *)face->v2+3) = vcount;
+ *fpp= face->v2;
+ fpp++; vcount++; cd++;
+ }
+ if( *((unsigned int *)face->v3+3) & 0x1000000 ) {
+ *cd= *((unsigned int *)face->v3+3);
+ *((unsigned int *)face->v3+3) = vcount;
+ *fpp= face->v3;
+ fpp++; vcount++; cd++;
+ }
+ if(face->v4 && ( *((unsigned int *)face->v4+3) & 0x1000000 ) ) {
+ *cd= *((unsigned int *)face->v4+3);
+ *((unsigned int *)face->v4+3) = vcount;
+ *fpp= face->v4;
+ fpp++; vcount++; cd++;
+ }
+
+ if(vcount>=BLSIZE-4) {
+ vlnr++;
+ break;
+ }
+ }
+
+ /* we now make the Mesh */
+ endf= vlnr;
+
+ ob= add_object(OB_MESH);
+
+ me= ob->data;
+ me->totvert= vcount;
+ me->totface= endf-startf;
+ me->flag= 0;
+ me->mvert= MEM_callocN(me->totvert*sizeof(MVert), "mverts");
+ me->mcol= MEM_callocN(4*me->totface*sizeof(MCol), "mverts");
+ me->mface= MEM_callocN(me->totface*sizeof(MFace), "mface");
+
+
+ /* materials, and set VCOL flag */
+ for(a=0; a<RG.totmat; a++) {
+ assign_material(ob, RG.matar[a], a+1);
+ ma= RG.matar[a];
+ if(ma) ma->mode |= MA_VERTEXCOL;
+ }
+
+ /* verts */
+ mvert= me->mvert;
+ fpp= poindata;
+ for(a=0; a<me->totvert; a++, mvert++, fpp++) {
+ VECCOPY(mvert->co, *fpp);
+ }
+
+ /* faces and mcol */
+ mface= me->mface;
+ md= (unsigned int *)me->mcol;
+
+ face= RG.facebase[(startf-1)>>10]+((startf-1) & 1023);
+ for(a=startf; a<endf; a++, md+=4, mface++) {
+ RAD_NEXTFACE(a);
+ mface->v1= *((unsigned int *)face->v1+3);
+ mface->v2= *((unsigned int *)face->v2+3);
+ mface->v3= *((unsigned int *)face->v3+3);
+ if(face->v4) mface->v4= *((unsigned int *)face->v4+3);
+
+ mface->edcode= 3;
+ test_index_mface(mface, face->v4 ? 4 : 3);
+ mface->mat_nr= face->matindex;
+
+ md[0]= coldata[mface->v1];
+ md[1]= coldata[mface->v2];
+ md[2]= coldata[mface->v3];
+ md[3]= coldata[mface->v4];
+ }
+
+ /* boundbox en centrenew */
+
+ INIT_MINMAX(min, max);
+
+ mvert= me->mvert;
+ for(a=0; a<me->totvert; a++, mvert++) {
+ DO_MINMAX(mvert->co, min, max);
+ }
+
+ cent[0]= (min[0]+max[0])/2.0;
+ cent[1]= (min[1]+max[1])/2.0;
+ cent[2]= (min[2]+max[2])/2.0;
+
+ mvert= me->mvert;
+ for(a=0; a<me->totvert; a++, mvert++) {
+ VecSubf(mvert->co, mvert->co, cent);
+ }
+
+ VECCOPY(ob->loc, cent);
+ tex_space_mesh(me);
+
+ /* restore colors */
+ face= RG.facebase[(startf-1)>>10]+((startf-1) & 1023);
+ for(a=startf; a<endf; a++) {
+ RAD_NEXTFACE(a);
+
+ cd= ((unsigned int *)face->v1+3);
+ if( *cd < 0x1000000 ) *cd= coldata[*cd];
+ cd= ((unsigned int *)face->v2+3);
+ if( *cd < 0x1000000 ) *cd= coldata[*cd];
+ cd= ((unsigned int *)face->v3+3);
+ if( *cd < 0x1000000 ) *cd= coldata[*cd];
+ if(face->v4) {
+ cd= ((unsigned int *)face->v4+3);
+ if( *cd < 0x1000000 ) *cd= coldata[*cd];
+ }
+ }
+ }
+
+ MEM_freeN(coldata);
+ MEM_freeN(poindata);
+
+}
+
+void rad_replacemesh(void)
+{
+ RPatch *rp;
+
+ deselectall();
+
+ rp= RG.patchbase.first;
+ while(rp) {
+ if( exist_object(rp->from)) rp->from->flag |= SELECT;
+ rp= rp->next;
+ }
+
+ copy_objectflags();
+ delete_obj(1);
+
+ rad_addmesh();
+}
+
diff --git a/source/blender/radiosity/intern/source/radpreprocess.c b/source/blender/radiosity/intern/source/radpreprocess.c
new file mode 100644
index 00000000000..c04886ca2fc
--- /dev/null
+++ b/source/blender/radiosity/intern/source/radpreprocess.c
@@ -0,0 +1,787 @@
+ /* ***************************************
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+
+
+
+ preproces.c nov/dec 1992
+ may 1999
+
+ - collect from meshes
+ - countglobaldata()
+ - makeGlobalElemArray()
+
+ $Id$
+
+ *************************************** */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_view3d_types.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_material.h"
+
+#include "BIF_toolbox.h"
+
+#include "radio.h"
+
+void setparelem(RNode *rn, RPatch *par);
+
+
+
+void splitconnected()
+{
+ /* voor zover de videoscapefile nog gedeelde vertices leverde, worden de vlakken getest
+ * op normaal en kleur. Doe dit door voor elke vertex een normaal en een kleur te onthouden.
+ */
+ RPatch *rp;
+ RNode *rn;
+ VeNoCo *vnc, *next, *vnc1;
+ int a;
+
+ /* test of gesplit moet worden */
+
+ rp= RG.patchbase.first;
+ while(rp) {
+ rn= rp->first;
+ if((rp->f1 & RAD_NO_SPLIT)==0) {
+ for(a=0; a<rp->type; a++) {
+
+ if(a==0) vnc= (VeNoCo *)rn->v1;
+ else if(a==1) vnc= (VeNoCo *)rn->v2;
+ else if(a==2) vnc= (VeNoCo *)rn->v3;
+ else vnc= (VeNoCo *)rn->v4;
+
+ if(vnc->flag==0) {
+ vnc->n= (float *)rp->norm;
+ vnc->col= (float *)rp->ref;
+ vnc->flag= 1;
+ }
+ else { /* mag vlak deze vertex gebruiken voor gouraud? */
+ vnc1= vnc;
+ while(vnc1) {
+ if(VecCompare(vnc1->n, rp->norm, 0.01)) {
+ if(VecCompare(vnc1->col, rp->ref, 0.01)) {
+ break;
+ }
+ }
+ vnc= vnc1;
+ vnc1= vnc1->next;
+ }
+ if(vnc1==0) {
+ vnc1= MEM_mallocN(sizeof(VeNoCo), "splitconn");
+ vnc1->next= 0;
+ vnc1->v= mallocVert();
+ vnc->next= vnc1;
+ VECCOPY(vnc1->v, vnc->v);
+ vnc1->n= (float *)rp->norm;
+ vnc1->col= (float *)rp->ref;
+ }
+ if(a==0) rn->v1= (float *)vnc1;
+ else if(a==1) rn->v2= (float *)vnc1;
+ else if(a==2) rn->v3= (float *)vnc1;
+ else rn->v4= (float *)vnc1;
+ }
+ }
+ }
+ rp= rp->next;
+ }
+ /* de vertexpointers van nodes aanpassen */
+
+ rp= RG.patchbase.first;
+ while(rp) {
+ rn= rp->first;
+ rn->v1= ((VeNoCo *)(rn->v1))->v;
+ rn->v2= ((VeNoCo *)(rn->v2))->v;
+ rn->v3= ((VeNoCo *)(rn->v3))->v;
+ if(rp->type==4) rn->v4= ((VeNoCo *)(rn->v4))->v;
+
+ rp= rp->next;
+ }
+
+
+ /* het hele zaakje vrijgeven */
+ vnc= RG.verts;
+ for(a=0; a<RG.totvert; a++) {
+ vnc1= vnc->next;
+ while(vnc1) {
+ next= vnc1->next;
+ MEM_freeN(vnc1);
+ vnc1= next;
+ }
+ vnc++;
+ }
+ MEM_freeN(RG.verts);
+ RG.verts= 0;
+}
+
+int vergedge(const void *v1,const void *v2)
+{
+ int *e1, *e2;
+
+ e1= (int *)v1;
+ e2= (int *)v2;
+
+ if( e1[0] > e2[0] ) return 1;
+ else if( e1[0] < e2[0] ) return -1;
+ else if( e1[1] > e2[1] ) return 1;
+ else if( e1[1] < e2[1] ) return -1;
+
+ return 0;
+}
+
+
+void addedge(float *v1, float *v2, EdSort *es)
+{
+ if( ((long)v1)<((long)v2) ) {
+ es->v1= v1;
+ es->v2= v2;
+ }
+ else {
+ es->v2= v1;
+ es->v1= v2;
+ }
+}
+
+static void setedge(RNode *node, RNode *nb, int nr, int nrb)
+{
+ switch(nr) {
+ case 1:
+ node->ed1= nb;
+ break;
+ case 2:
+ node->ed2= nb;
+ break;
+ case 3:
+ node->ed3= nb;
+ break;
+ case 4:
+ node->ed4= nb;
+ break;
+ }
+ switch(nrb) {
+ case 1:
+ nb->ed1= node;
+ break;
+ case 2:
+ nb->ed2= node;
+ break;
+ case 3:
+ nb->ed3= node;
+ break;
+ case 4:
+ nb->ed4= node;
+ break;
+ }
+}
+
+void setedgepointers()
+{
+ /* edge-array maken en sorteren */
+ /* paren edges staan bij elkaar: pointers invullen in nodes */
+ EdSort *es, *esblock;
+ RPatch *rp;
+ RNode *rn;
+ int tot= 0;
+
+ rp= RG.patchbase.first;
+ while(rp) {
+ tot+= rp->type;
+ rp= rp->next;
+ }
+
+ if(tot==0) return;
+
+ es=esblock= MEM_mallocN(tot*sizeof(EdSort), "setedgepointers");
+ rp= RG.patchbase.first;
+ while(rp) {
+ rn= rp->first;
+ addedge(rn->v1, rn->v2, es);
+ es->nr= 1;
+ es->node= rn;
+ es++;
+ addedge(rn->v2, rn->v3, es);
+ es->nr= 2;
+ es->node= rn;
+ es++;
+ if(rp->type==3) {
+ addedge(rn->v3, rn->v1, es);
+ es->nr= 3;
+ es->node= rn;
+ es++;
+ }
+ else {
+ addedge(rn->v3, rn->v4, es);
+ es->nr= 3;
+ es->node= rn;
+ es++;
+ addedge(rn->v4, rn->v1, es);
+ es->nr= 4;
+ es->node= rn;
+ es++;
+ }
+ rp= rp->next;
+ }
+
+ qsort(esblock,tot,sizeof(EdSort),vergedge);
+
+ es= esblock;
+ while(tot>0) {
+ if( es->v1== (es+1)->v1 ) {
+ if( es->v2== (es+1)->v2 ) {
+ setedge(es->node, (es+1)->node, es->nr, (es+1)->nr);
+ tot--;
+ es++;
+ }
+ }
+ es++;
+ tot--;
+ }
+
+ MEM_freeN(esblock);
+}
+
+void rad_collect_meshes()
+{
+ extern Material defmaterial;
+ Base *base;
+ Object *ob;
+ Mesh *me;
+ MVert *mvert;
+ MFace *mface;
+ Material *ma = NULL, *noma= NULL;
+ RPatch *rp;
+ RNode *rn;
+ VeNoCo *vnc, **nodevert;
+ float *vd, *v1, *v2, *v3, *v4 = NULL;
+ int a, b, offs, index, matindex;
+
+ if(G.obedit) {
+ error("Unable to perform function in EditMode");
+ return;
+ }
+
+ set_radglobal();
+
+ freeAllRad();
+
+ start_fastmalloc("Radiosity");
+
+ /* count the number of verts */
+ RG.totvert= 0;
+ RG.totface= 0;
+ base= (G.scene->base.first);
+ while(base) {
+ if(((base)->flag & SELECT) && ((base)->lay & G.vd->lay) ) {
+ if(base->object->type==OB_MESH) {
+ base->flag |= OB_RADIO;
+ me= base->object->data;
+ RG.totvert+= me->totvert;
+ }
+ }
+ base= base->next;
+ }
+ if(RG.totvert==0) {
+ error("No vertices");
+ return;
+ }
+ vnc= RG.verts= MEM_callocN(RG.totvert*sizeof(VeNoCo), "readvideoscape1");
+
+ RG.min[0]= RG.min[1]= RG.min[2]= 1.0e20;
+ RG.max[0]= RG.max[1]= RG.max[2]= -1.0e20;
+
+ /* min-max and material array */
+ base= (G.scene->base.first);
+ while(base) {
+ if( ((base)->flag & SELECT) && ((base)->lay & G.vd->lay) ) {
+ if(base->object->type==OB_MESH) {
+ me= base->object->data;
+ mvert= me->mvert;
+ for(a=0; a<me->totvert; a++, mvert++) {
+ vd= mallocVert();
+ VECCOPY(vd, mvert->co);
+ /* Should make MTC its own module... */
+ Mat4MulVecfl(base->object->obmat, vd);
+
+ vnc->v= vd;
+ for(b=0; b<3; b++) {
+ RG.min[b]= MIN2(RG.min[b], vd[b]);
+ RG.max[b]= MAX2(RG.max[b], vd[b]);
+ }
+ vnc++;
+ }
+
+ if(base->object->totcol==0) {
+ if(RG.totmat<MAXMAT) {
+ if(noma==NULL) {
+ noma= add_material("RadioMat");
+ }
+ RG.matar[RG.totmat]= noma;
+ RG.totmat++;
+ }
+ }
+ else {
+ for(a=0; a<base->object->totcol; a++) {
+ if(a+RG.totmat>MAXMAT-1) break;
+ RG.matar[a+RG.totmat]= give_current_material(base->object, a+1);
+ }
+
+ RG.totmat+= base->object->totcol;
+ if (RG.totmat >= MAXMAT) {
+ RG.totmat = MAXMAT - 1;
+ }
+ }
+ }
+ }
+ base= base->next;
+ }
+
+ RG.cent[0]= (RG.min[0]+ RG.max[0])/2;
+ RG.cent[1]= (RG.min[1]+ RG.max[1])/2;
+ RG.cent[2]= (RG.min[2]+ RG.max[2])/2;
+ RG.size[0]= (RG.max[0]- RG.min[0]);
+ RG.size[1]= (RG.max[1]- RG.min[1]);
+ RG.size[2]= (RG.max[2]- RG.min[2]);
+ RG.maxsize= MAX3(RG.size[0],RG.size[1],RG.size[2]);
+
+ /* make patches */
+
+ RG.totelem= 0;
+ RG.totpatch= 0;
+ RG.totlamp= 0;
+ offs= 0;
+ matindex= 0;
+
+ base= (G.scene->base.first);
+ while(base) {
+ if( ((base)->flag & SELECT) && ((base)->lay & G.vd->lay) ) {
+ if(base->object->type==OB_MESH) {
+ ob= base->object;
+ me= ob->data;
+ mface= me->mface;
+
+ index= -1;
+
+ for(a=0; a<me->totface; a++, mface++) {
+ if(mface->v3) {
+
+ rp= callocPatch();
+ BLI_addtail(&(RG.patchbase), rp);
+ rp->from= ob;
+
+ if(mface->v4) rp->type= 4;
+ else rp->type= 3;
+
+ rp->first= rn= callocNode();
+
+ if(mface->flag & ME_SMOOTH) rp->f1= RAD_NO_SPLIT;
+
+ /* temporal: we store the venoco in the node */
+ rn->v1= (float *)(RG.verts+mface->v1+offs);
+ v1= (RG.verts+mface->v1+offs)->v;
+ rn->v2= (float *)(RG.verts+mface->v2+offs);
+ v2= (RG.verts+mface->v2+offs)->v;
+ rn->v3= (float *)(RG.verts+mface->v3+offs);
+ v3= (RG.verts+mface->v3+offs)->v;
+
+ if(mface->v4) {
+ rn->v4= (float *)(RG.verts+mface->v4+offs);
+ v4= (RG.verts+mface->v4+offs)->v;
+ }
+ rn->par= rp;
+ rn->f= RAD_PATCH; /* deze node is Patch */
+ rn->type= rp->type;
+
+ CalcNormFloat(v1, v2, v3, rp->norm);
+ if(rn->type==4) rp->area= AreaQ3Dfl(v1, v2, v3, v4);
+ else rp->area= AreaT3Dfl(v1, v2, v3);
+
+ rn->area= rp->area;
+
+ /* kleur en emit */
+ if(mface->mat_nr != index) {
+ index= mface->mat_nr;
+ ma= give_current_material(ob, index+1);
+ if(ma==0) ma= &defmaterial;
+ }
+ rp->ref[0]= ma->r;
+ rp->ref[1]= ma->g;
+ rp->ref[2]= ma->b;
+
+ if(ma->emit) RG.totlamp++;
+
+ rp->emit[0]= rp->emit[1]= rp->emit[2]= ma->emit;
+ rp->emit[0]*= rp->ref[0];
+ rp->emit[1]*= rp->ref[1];
+ rp->emit[2]*= rp->ref[2];
+
+ nodevert= (VeNoCo **)&(rn->v1);
+ for(b=0; b<rp->type; b++) {
+ rp->cent[0]+= (*nodevert)->v[0];
+ rp->cent[1]+= (*nodevert)->v[1];
+ rp->cent[2]+= (*nodevert)->v[2];
+ nodevert++;
+ }
+ rp->cent[0]/= (float)rp->type;
+ rp->cent[1]/= (float)rp->type;
+ rp->cent[2]/= (float)rp->type;
+
+ /* for reconstruction materials */
+ rp->matindex= matindex+mface->mat_nr;
+ if(rp->matindex>MAXMAT-1) rp->matindex= MAXMAT-1;
+
+ RG.totelem++;
+ RG.totpatch++;
+ }
+ }
+ offs+= me->totvert;
+
+ matindex+= base->object->totcol;
+ if(base->object->totcol==0) matindex++;
+ }
+ }
+ base= base->next;
+ }
+
+ splitconnected();
+ setedgepointers();
+
+ makeGlobalElemArray();
+ pseudoAmb();
+ rad_setlimits();
+}
+
+void setparelem(RNode *rn, RPatch *par)
+{
+
+ if(rn->down1) {
+ setparelem(rn->down1, par);
+ setparelem(rn->down2, par);
+ }
+ else {
+ rn->par= par;
+ }
+}
+
+void countelem(RNode *rn)
+{
+
+ if(rn->down1) {
+ countelem(rn->down1);
+ countelem(rn->down2);
+ }
+ else RG.totelem++;
+}
+
+void countglobaldata()
+{
+ /* telt aantal elements en patches*/
+ RPatch *rp;
+
+ RG.totelem= RG.totpatch= 0;
+
+ rp= RG.patchbase.first;
+ while(rp) {
+ RG.totpatch++;
+ countelem(rp->first);
+ rp= rp->next;
+ }
+}
+
+void addelem(RNode ***el, RNode *rn, RPatch *rp)
+{
+ if(rn->down1) {
+ addelem(el, rn->down1, rp);
+ addelem(el, rn->down2, rp);
+ }
+ else {
+ rn->par= rp;
+ **el= rn;
+ (*el)++;
+ }
+}
+
+void makeGlobalElemArray()
+{
+ /* always called when # of elements change */
+ RPatch *rp;
+ RNode **el;
+
+ countglobaldata();
+
+ if(RG.elem) MEM_freeN(RG.elem);
+ if(RG.totelem) {
+ el= RG.elem= MEM_mallocN(sizeof(void *)*RG.totelem, "makeGlobalElemArray");
+ }
+ else {
+ RG.elem= 0;
+ return;
+ }
+
+ /* recursief elements toevoegen */
+ rp= RG.patchbase.first;
+ while(rp) {
+ addelem(&el, rp->first, rp);
+ rp= rp->next;
+ }
+
+ /* formfactor array */
+ if(RG.formfactors) MEM_freeN(RG.formfactors);
+ if(RG.totelem)
+ RG.formfactors= MEM_mallocN(sizeof(float)*RG.totelem, "formfactors");
+ else
+ RG.formfactors= 0;
+}
+
+void splitpatch(RPatch *old) /* bij overflow gedurende shoot */
+{
+ RNode *rn;
+ float **fpp;
+ RPatch *rp;
+ int a;
+
+ rn= old->first;
+ if(rn->down1==0) return;
+ rn= rn->down1;
+
+ old->unshot[0]/=2.0;
+ old->unshot[1]/=2.0;
+ old->unshot[2]/=2.0;
+ setnodeflags(old->first, 2, 0);
+
+ rp= mallocPatch();
+ *rp= *old;
+ BLI_addhead(&RG.patchbase, rp);
+ rp->first= rn;
+ rp->area= rn->area;
+ rp->cent[0]= rp->cent[1]= rp->cent[2]= 0.0;
+ fpp= &(rn->v1);
+ for(a=0; a<rp->type; a++) {
+ rp->cent[0]+= (*fpp)[0];
+ rp->cent[1]+= (*fpp)[1];
+ rp->cent[2]+= (*fpp)[2];
+ fpp++;
+ }
+ rp->cent[0]/=(float)rp->type;
+ rp->cent[1]/=(float)rp->type;
+ rp->cent[2]/=(float)rp->type;
+
+ setparelem(rn, rp);
+
+ rn= old->first->down2;
+
+ rp= mallocPatch();
+ *rp= *old;
+ BLI_addhead(&RG.patchbase, rp);
+ rp->first= rn;
+ rp->area= rn->area;
+ rp->cent[0]= rp->cent[1]= rp->cent[2]= 0.0;
+ fpp= &(rn->v1);
+ for(a=0; a<rp->type; a++) {
+ rp->cent[0]+= (*fpp)[0];
+ rp->cent[1]+= (*fpp)[1];
+ rp->cent[2]+= (*fpp)[2];
+ fpp++;
+ }
+ rp->cent[0]/=(float)rp->type;
+ rp->cent[1]/=(float)rp->type;
+ rp->cent[2]/=(float)rp->type;
+
+ setparelem(rn, rp);
+
+ BLI_remlink(&RG.patchbase, old);
+ freePatch(old);
+}
+
+
+void addpatch(RPatch *old, RNode *rn)
+{
+ float **fpp;
+ RPatch *rp;
+ int a;
+
+ if(rn->down1) {
+ addpatch(old, rn->down1);
+ addpatch(old, rn->down2);
+ }
+ else {
+ rp= mallocPatch();
+ *rp= *old;
+ BLI_addhead(&RG.patchbase, rp);
+ rp->first= rn;
+
+ rp->area= rn->area;
+ rp->cent[0]= rp->cent[1]= rp->cent[2]= 0.0;
+ fpp= &(rn->v1);
+ for(a=0; a<rp->type; a++) {
+ rp->cent[0]+= (*fpp)[0];
+ rp->cent[1]+= (*fpp)[1];
+ rp->cent[2]+= (*fpp)[2];
+ fpp++;
+ }
+ rp->cent[0]/=(float)rp->type;
+ rp->cent[1]/=(float)rp->type;
+ rp->cent[2]/=(float)rp->type;
+
+ rn->par= rp;
+ }
+}
+
+void converttopatches()
+{
+ /* loopt patcheslijst af, als node gesubdivided: nieuwe patch */
+ RPatch *rp, *next;
+
+ rp= RG.patchbase.first;
+ while(rp) {
+ next= rp->next;
+ if(rp->first->down1) {
+ addpatch(rp, rp->first);
+ BLI_remlink(&RG.patchbase, rp);
+ freePatch(rp);
+ }
+ rp= next;
+ }
+
+}
+
+void subdiv_elements()
+{
+ RNode **el, *rn;
+ int a, toobig= 1;
+
+ rad_init_energy();
+
+ /* eerst maxsize elements */
+
+ while(toobig) {
+ toobig= 0;
+
+ el= RG.elem;
+ for(a=RG.totelem; a>0; a--, el++) {
+ rn= *el;
+ if( rn->totrad[0]==0.0 && rn->totrad[1]==0.0 && rn->totrad[2]==0.0) {
+ if(rn->area>RG.elemmin) {
+ subdivideNode(rn, 0);
+ if(rn->down1 ) {
+ toobig= 1;
+ if(rn->down1->area>RG.elemmin)
+ subdivideNode( rn->down1, 0);
+ if(rn->down2->area>RG.elemmin)
+ subdivideNode( rn->down2, 0);
+ }
+ }
+ }
+ }
+ if(toobig) makeGlobalElemArray();
+ }
+
+ el= RG.elem;
+ for(a=RG.totelem; a>0; a--, el++) {
+ rn= *el;
+ if( rn->totrad[0]==0.0 && rn->totrad[1]==0.0 && rn->totrad[2]==0.0) {
+ subdivideNode(rn, 0);
+ if( rn->down1 ) {
+ subdivideNode( rn->down1, 0);
+ subdivideNode( rn->down2, 0);
+ }
+ }
+ }
+ makeGlobalElemArray();
+}
+
+void subdividelamps()
+{
+ RPatch *rp, *next;
+
+ rp= RG.patchbase.first;
+ while(rp) {
+ next= rp->next;
+ if(rp->emit[0]!=0.0 || rp->emit[1]!=0.0 || rp->emit[2]!=0.0) {
+ subdivideNode( rp->first, 0);
+ if(rp->first->down1) {
+ subdivideNode(rp->first->down1, 0);
+ subdivideNode(rp->first->down2, 0);
+ }
+
+ addpatch(rp, rp->first);
+ BLI_remlink(&RG.patchbase, rp);
+ freePatch(rp);
+ }
+ rp= next;
+ }
+
+}
+
+void maxsizePatches()
+{
+ RPatch *rp;
+ int toobig= 1;
+
+ while(toobig) {
+ toobig= 0;
+ rp= RG.patchbase.first;
+ while(rp) {
+ if(rp->area>RG.patchmax) {
+ subdivideNode( rp->first, 0);
+ if(rp->first->down1) toobig= 1;
+ }
+ rp= rp->next;
+ }
+
+ if(toobig) converttopatches();
+ }
+
+ /* aantal lampen tellen */
+ rp= RG.patchbase.first;
+ RG.totlamp= 0;
+ while(rp) {
+ if(rp->emit[0]!=0.0 || rp->emit[1]!=0.0 || rp->emit[2]!=0.0) {
+ RG.totlamp++;
+ }
+ rp= rp->next;
+ }
+ makeGlobalElemArray();
+}
+
+
+
diff --git a/source/blender/readblenfile/BLO_readblenfile.h b/source/blender/readblenfile/BLO_readblenfile.h
new file mode 100644
index 00000000000..318224a27f2
--- /dev/null
+++ b/source/blender/readblenfile/BLO_readblenfile.h
@@ -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 *****
+ *
+ */
+
+#ifndef BLO_READBLENFILE_H
+#define BLO_READBLENFILE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ BlendFileData *
+BLO_readblenfilename(
+ char *fileName,
+ BlendReadError *error_r);
+
+ BlendFileData *
+BLO_readblenfilehandle(
+ int fileHandle,
+ BlendReadError *error_r);
+
+ BlendFileData *
+BLO_readblenfilememory(
+ char *fromBuffer,
+ int fromBufferSize,
+ BlendReadError *error_r);
+
+
+ void
+BLO_setcurrentversionnumber(
+ char array[4]);
+
+ void
+BLO_setversionnumber(
+ char array[4],
+ int version);
+
+ int
+blo_is_a_runtime(
+ char *file);
+
+ BlendFileData *
+blo_read_runtime(
+ char *file,
+ BlendReadError *error_r);
+
+#define BLO_RESERVEDSIZE 12
+extern char *headerMagic;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BLO_READBLENFILE_H */
diff --git a/source/blender/readblenfile/Makefile b/source/blender/readblenfile/Makefile
new file mode 100644
index 00000000000..0db2f2aa3b5
--- /dev/null
+++ b/source/blender/readblenfile/Makefile
@@ -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 *****
+#
+# Bounces make to subdirectories.
+
+SOURCEDIR = source/blender/readblenfile
+DIRS = intern stub
+
+include nan_subdirs.mk
diff --git a/source/blender/readblenfile/intern/BLO_readblenfile.c b/source/blender/readblenfile/intern/BLO_readblenfile.c
new file mode 100644
index 00000000000..9b9bf7d27a3
--- /dev/null
+++ b/source/blender/readblenfile/intern/BLO_readblenfile.c
@@ -0,0 +1,647 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 <string.h>
+#include <fcntl.h>
+
+#ifdef WIN32
+#include <io.h> // read, open
+#else // ! WIN32
+#include <unistd.h> // read
+#endif
+
+#include "BLO_readStreamGlue.h"
+
+#include "BLO_readfile.h"
+#include "BLO_readblenfile.h"
+
+#include "BKE_blender.h"
+
+#define CACHESIZE 100000
+
+char *headerMagic = "BLENDFI";
+
+void BLO_setversionnumber(char array[4], int version)
+{
+ memset(array, 0, sizeof(array));
+
+ array[1] = version / 100;
+ array[2] = version % 100;
+}
+
+void BLO_setcurrentversionnumber(char array[4])
+{
+ BLO_setversionnumber(array, BLENDER_VERSION);
+}
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+struct BLO_readblenfileStruct {
+ struct readStreamGlueStruct *streamGlue;
+ int fileDes;
+ unsigned int cacheSize;
+ unsigned int inCache;
+ unsigned int leftToRead;
+ unsigned int Seek;
+
+ int (*read)(struct BLO_readblenfileStruct *readblenfileStruct, void *buffer, int size);
+
+ char *readCache;
+ char *fromBuffer;
+ int fromBufferSize;
+ char crInBuffer;
+ char removeCR;
+};
+
+// declare static functions
+
+static int readfromfilehandle(
+ struct BLO_readblenfileStruct *readblenfileStruct,
+ void *buffer,
+ int size);
+
+static int readfrommemory(
+ struct BLO_readblenfileStruct *readblenfileStruct,
+ void *buffer,
+ int size);
+
+static int fillcache(
+ struct BLO_readblenfileStruct *readblenfileStruct);
+
+static unsigned int readfromcache(
+ struct BLO_readblenfileStruct *readblenfileStruct,
+ void * buffer,
+ unsigned int size);
+
+static BlendFileData *readblenfilegeneric(
+ struct BLO_readblenfileStruct *readblenfileStruct,
+ BlendReadError *error_r);
+
+// implementation of static functions
+
+static int readfromfilehandle(
+ struct BLO_readblenfileStruct *readblenfileStruct,
+ void *buffer,
+ int size)
+{
+ int readsize = -1;
+
+ if (readblenfileStruct->fileDes != -1) {
+ readsize = read(readblenfileStruct->fileDes, buffer, size);
+ }
+
+ return(readsize);
+}
+
+static int readfrommemory(
+ struct BLO_readblenfileStruct *readblenfileStruct,
+ void *buffer,
+ int size)
+{
+ int readsize = -1;
+
+ if (readblenfileStruct->fromBuffer) {
+ if (size > readblenfileStruct->fromBufferSize) {
+ size = readblenfileStruct->fromBufferSize;
+ }
+
+ memcpy(buffer, readblenfileStruct->fromBuffer, size);
+ readblenfileStruct->fromBufferSize -= size;
+ readblenfileStruct->fromBuffer += size;
+
+ readsize = size;
+ }
+
+ return(readsize);
+}
+
+static int fillcache(
+ struct BLO_readblenfileStruct *readblenfileStruct)
+{
+ int readsize;
+ int toread;
+
+ // how many bytes can we read ?
+
+ toread = readblenfileStruct->leftToRead;
+
+ if (toread > readblenfileStruct->cacheSize) {
+ toread = readblenfileStruct->cacheSize;
+ }
+
+ readsize = readblenfileStruct->read(readblenfileStruct, readblenfileStruct->readCache, toread);
+ if (readsize > 0) {
+ if (readblenfileStruct->removeCR) {
+ // do some stuff here
+ }
+ readblenfileStruct->inCache = readsize;
+ readblenfileStruct->leftToRead -= readsize;
+ }
+
+ return (readsize);
+}
+
+
+static unsigned int readfromcache(
+ struct BLO_readblenfileStruct *readblenfileStruct,
+ void * buffer,
+ unsigned int size)
+{
+ unsigned int readsize = 0;
+
+ if (readblenfileStruct->inCache - readblenfileStruct->Seek > size) {
+ memcpy(buffer, readblenfileStruct->readCache + readblenfileStruct->Seek, size);
+ readblenfileStruct->Seek += size;
+ readsize = size;
+ } else {
+ // handle me
+ }
+
+ return(readsize);
+}
+
+static BlendReadError brs_to_bre(int err)
+{
+ int errFunction = BRS_GETFUNCTION(err);
+ int errGeneric = BRS_GETGENERR(err);
+ int errSpecific = BRS_GETSPECERR(err);
+
+ if (errGeneric) {
+ switch (errGeneric) {
+ case BRS_MALLOC:
+ return BRE_OUT_OF_MEMORY;
+ case BRS_NULL:
+ return BRE_INTERNAL_ERROR;
+ case BRS_MAGIC:
+ return BRE_NOT_A_BLEND;
+ case BRS_CRCHEADER:
+ case BRS_CRCDATA:
+ return BRE_CORRUPT;
+ case BRS_DATALEN:
+ return BRE_INCOMPLETE;
+ case BRS_STUB:
+ return BRE_NOT_A_BLEND;
+ }
+ } else if (errSpecific) {
+ switch (errFunction) {
+ case BRS_READSTREAMGLUE:
+ switch (errSpecific) {
+ case BRS_UNKNOWN:
+ return BRE_INTERNAL_ERROR;
+ }
+ break;
+ case BRS_READSTREAMFILE:
+ switch (errSpecific) {
+ case BRS_NOTABLEND:
+ return BRE_NOT_A_BLEND;
+ case BRS_READERROR:
+ return BRE_UNABLE_TO_READ;
+ }
+ break;
+ case BRS_INFLATE:
+ switch (errSpecific) {
+ case BRS_INFLATEERROR:
+ return BRE_CORRUPT;
+ }
+ break;
+ case BRS_DECRYPT:
+ switch (errSpecific) {
+ case BRS_RSANEWERROR:
+ return BRE_INTERNAL_ERROR;
+ case BRS_DECRYPTERROR:
+ return BRE_INTERNAL_ERROR;
+ case BRS_NOTOURPUBKEY:
+ return BRE_NOT_ALLOWED;
+ }
+ break;
+ case BRS_VERIFY:
+ switch (errSpecific) {
+ case BRS_RSANEWERROR:
+ return BRE_INTERNAL_ERROR;
+ case BRS_SIGFAILED:
+ return BRE_INTERNAL_ERROR;
+ }
+ break;
+ }
+ }
+
+ return BRE_INVALID;
+}
+
+static BlendFileData *readblenfilegeneric(
+ struct BLO_readblenfileStruct *readblenfileStruct,
+ BlendReadError *error_r)
+{
+ BlendFileData *bfd= NULL;
+ unsigned char reserved[BLO_RESERVEDSIZE];
+ uint8_t minversion[4];
+ uint8_t myversion[4];
+ uint8_t version[4];
+ uint8_t flags[4];
+ void *parms[2];
+ int filesize;
+
+ parms[0]= &bfd;
+ parms[1]= error_r;
+
+ BLO_setcurrentversionnumber(myversion);
+
+ readblenfileStruct->cacheSize = CACHESIZE;
+ readblenfileStruct->readCache = malloc(readblenfileStruct->cacheSize);
+
+ if (fillcache(readblenfileStruct) <= 0) {
+ *error_r = BRE_UNABLE_TO_READ;
+ } else if (readfromcache(readblenfileStruct, minversion, sizeof(minversion)) != sizeof(minversion)) {
+ *error_r = BRE_UNABLE_TO_READ;
+ } else if (memcmp(minversion, myversion, sizeof(minversion)) > 0) {
+ *error_r = BRE_TOO_NEW;
+ } else if (readfromcache(readblenfileStruct, version, sizeof(version)) != sizeof(version)) {
+ *error_r = BRE_UNABLE_TO_READ;
+ } else if (readfromcache(readblenfileStruct, flags, sizeof(flags)) != sizeof(flags)) {
+ *error_r = BRE_UNABLE_TO_READ;
+ } else if (readfromcache(readblenfileStruct, &filesize, sizeof(filesize)) != sizeof(filesize)) {
+ *error_r = BRE_UNABLE_TO_READ;
+ } else if (readfromcache(readblenfileStruct, reserved, sizeof(reserved)) != sizeof(reserved)) {
+ *error_r = BRE_UNABLE_TO_READ;
+ } else {
+ filesize = ntohl(filesize);
+
+ // substract number of bytes we've
+ // been handling outside readfromcache()
+ filesize -= strlen(headerMagic);
+ filesize--;
+
+ if (filesize < readblenfileStruct->inCache) {
+ // we've allready read more than we're supposed to
+ readblenfileStruct->inCache = filesize;
+ readblenfileStruct->leftToRead = 0;
+ } else {
+ //
+ readblenfileStruct->leftToRead = filesize - readblenfileStruct->inCache;
+ }
+
+ do {
+ int err;
+
+ *error_r = BRE_NONE;
+ err = readStreamGlue(
+ parms,
+ &(readblenfileStruct->streamGlue),
+ readblenfileStruct->readCache + readblenfileStruct->Seek,
+ readblenfileStruct->inCache - readblenfileStruct->Seek);
+
+ readblenfileStruct->inCache = 0;
+ readblenfileStruct->Seek = 0;
+
+ if (err) {
+ bfd = NULL;
+
+ /* If *error_r != BRE_NONE then it is
+ * blo_readstreamfile_end signaling an error
+ * in the loading code. Otherwise it is some
+ * other part of the streamglue system signalling
+ * and error so we convert the BRS error into
+ * a BRE error.
+ *
+ * Does this have to be so convoluted? No.
+ */
+ if (*error_r == BRE_NONE) {
+ *error_r = brs_to_bre(err);
+ }
+
+ break;
+ }
+ } while (fillcache(readblenfileStruct) > 0);
+ }
+
+ free(readblenfileStruct->readCache);
+ readblenfileStruct->readCache = 0;
+
+ return bfd;
+}
+
+// implementation of exported functions
+
+BlendFileData *
+BLO_readblenfilememory(
+ char *fromBuffer,
+ int fromBufferSize,
+ BlendReadError *error_r)
+{
+ static char *functionality_check= "\0FUNCTIONALITY_CHECK += BLO_readblenfilememory\n";
+ int magiclen = strlen(headerMagic);
+ BlendFileData *bfd = NULL;
+
+ if (!fromBuffer) {
+ *error_r = BRE_UNABLE_TO_OPEN;
+ } else if (fromBufferSize < magiclen) {
+ *error_r = BRE_UNABLE_TO_READ;
+ } else if (strncmp(fromBuffer, headerMagic, magiclen) != 0) {
+ *error_r = BRE_NOT_A_BLEND;
+ } else if (fromBufferSize < magiclen+1) {
+ *error_r = BRE_UNABLE_TO_READ;
+ } else if (fromBuffer[magiclen] != '\r' && fromBuffer[magiclen] != '\n') {
+ *error_r = BRE_NOT_A_BLEND;
+ } else {
+ int crnl;
+
+ fromBuffer+= magiclen;
+ fromBufferSize-= magiclen;
+ crnl = (fromBuffer[0] == '\r');
+ fromBuffer++;
+ fromBufferSize--;
+
+ if (crnl && fromBufferSize<1) {
+ *error_r = BRE_UNABLE_TO_READ;
+ } else {
+ struct BLO_readblenfileStruct *readblenfileStruct = NULL;
+
+ /* skip carriage return if necessary */
+ if (crnl) {
+ fromBuffer++;
+ fromBufferSize--;
+ }
+
+ // Allocate all the stuff we need
+ readblenfileStruct = calloc(sizeof(struct BLO_readblenfileStruct), 1);
+ readblenfileStruct->fileDes = -1;
+ readblenfileStruct->fromBuffer = fromBuffer;
+ readblenfileStruct->fromBufferSize = fromBufferSize;
+ readblenfileStruct->read = readfrommemory;
+
+ readblenfileStruct->removeCR = crnl;
+ // fake filesize for now until we've
+ // actually read in the filesize from the header
+ // make sure we don't read more bytes than there
+ // are left to handle accoding to fromBufferSize
+ readblenfileStruct->leftToRead = readblenfileStruct->fromBufferSize;
+
+ bfd = readblenfilegeneric(readblenfileStruct, error_r);
+
+ free(readblenfileStruct);
+ readblenfileStruct = 0;
+ }
+ }
+
+ return bfd;
+}
+
+
+BlendFileData *
+BLO_readblenfilehandle(
+ int fd,
+ BlendReadError *error_r)
+{
+ static char *functionality_check= "\0FUNCTIONALITY_CHECK += BLO_readblenfilehandle\n";
+ int magiclen = strlen(headerMagic);
+ BlendFileData *bfd = NULL;
+ char tempbuffer[256];
+
+ if (fd==-1) {
+ *error_r = BRE_UNABLE_TO_OPEN;
+ } else if (read(fd, tempbuffer, magiclen) != magiclen) {
+ *error_r = BRE_UNABLE_TO_READ;
+ } else if (strncmp(tempbuffer, headerMagic, magiclen) != 0 ) {
+ *error_r = BRE_NOT_A_BLEND;
+ } else if (read(fd, tempbuffer, 1) != 1) {
+ *error_r = BRE_UNABLE_TO_READ;
+ } else if (tempbuffer[0] != '\r' && tempbuffer[0] != '\n') {
+ *error_r = BRE_NOT_A_BLEND;
+ } else {
+ int crnl = (tempbuffer[0] == '\r');
+
+ if (crnl && read(fd, tempbuffer, 1)!=1) {
+ *error_r = BRE_UNABLE_TO_READ;
+ } else {
+ struct BLO_readblenfileStruct *readblenfileStruct;
+
+ // Allocate all the stuff we need
+ readblenfileStruct = calloc(sizeof(struct BLO_readblenfileStruct), 1);
+ readblenfileStruct->fileDes = fd;
+ readblenfileStruct->read = readfromfilehandle;
+
+ readblenfileStruct->removeCR = crnl;
+ // fake filesize for now until we've
+ // actually read in the filesize from the header
+ readblenfileStruct->leftToRead = CACHESIZE;
+
+ bfd = readblenfilegeneric(readblenfileStruct, error_r);
+
+ free(readblenfileStruct);
+ readblenfileStruct = 0;
+ }
+ }
+
+ return bfd;
+}
+
+BlendFileData *
+BLO_readblenfilename(
+ char *fileName,
+ BlendReadError *error_r)
+{
+ static char *functionality_check= "\0FUNCTIONALITY_CHECK += BLO_readblenfilename\n";
+ BlendFileData *bfd = NULL;
+ int fd;
+
+ fd = open(fileName, O_RDONLY | O_BINARY);
+ if (fd==-1) {
+ *error_r= BRE_UNABLE_TO_OPEN;
+ } else {
+ bfd = BLO_readblenfilehandle(fd, error_r);
+ }
+
+ if (fd!=-1)
+ close(fd);
+
+ return bfd;
+}
+
+ /* Runtime reading */
+
+static int handle_read_msb_int(int handle) {
+ unsigned char buf[4];
+
+ if (read(handle, buf, 4)!=4)
+ return -1;
+ else
+ return (buf[0]<<24) + (buf[1]<<16) + (buf[2]<<8) + (buf[3]<<0);
+}
+
+int blo_is_a_runtime(char *path) {
+ int res= 0, fd= open(path, O_BINARY|O_RDONLY, 0);
+ int datastart;
+ char buf[8];
+
+ if (fd==-1)
+ goto cleanup;
+
+ lseek(fd, -12, SEEK_END);
+
+ datastart= handle_read_msb_int(fd);
+ if (datastart==-1)
+ goto cleanup;
+ else if (read(fd, buf, 8)!=8)
+ goto cleanup;
+ else if (memcmp(buf, "BRUNTIME", 8)!=0)
+ goto cleanup;
+ else
+ res= 1;
+
+cleanup:
+ if (fd!=-1)
+ close(fd);
+
+ return res;
+}
+
+BlendFileData *
+blo_read_runtime(
+ char *path,
+ BlendReadError *error_r)
+{
+ static char *functionality_check= "\0FUNCTIONALITY_CHECK += BLO_read_runtime\n";
+ BlendFileData *bfd= NULL;
+ int fd, datastart;
+ char buf[8];
+
+ fd= open(path, O_BINARY|O_RDONLY, 0);
+ if (fd==-1) {
+ *error_r= BRE_UNABLE_TO_OPEN;
+ goto cleanup;
+ }
+
+ lseek(fd, -12, SEEK_END);
+
+ datastart= handle_read_msb_int(fd);
+ if (datastart==-1) {
+ *error_r= BRE_UNABLE_TO_READ;
+ goto cleanup;
+ } else if (read(fd, buf, 8)!=8) {
+ *error_r= BRE_UNABLE_TO_READ;
+ goto cleanup;
+ } else if (memcmp(buf, "BRUNTIME", 8)!=0) {
+ *error_r= BRE_NOT_A_BLEND;
+ goto cleanup;
+ } else {
+ lseek(fd, datastart, SEEK_SET);
+ bfd= BLO_readblenfilehandle(fd, error_r);
+ }
+
+cleanup:
+ if (fd!=-1)
+ close(fd);
+
+ return bfd;
+}
+
+#if 0
+static char *brs_error_to_string(int err) {
+ int errFunction = BRS_GETFUNCTION(err);
+ int errGeneric = BRS_GETGENERR(err);
+ int errSpecific = BRS_GETSPECERR(err);
+ char *errFunctionStrings[] = {
+ "",
+ "The read stream",
+ "The read stream loopback",
+ "The key store",
+ "The file reading",
+ "Decompressing the file",
+ "Decrypting the file",
+ "Verifying the signature"};
+ char *errGenericStrings[] = {
+ "",
+ "generated an out of memory error",
+ "bumped on an internal programming error",
+ "did not recognize this as a blend file",
+ "failed a blend file check",
+ "bumped on corrupted data",
+ "needed the rest of the blend file",
+ "is not allowed in this version"};
+ char *errReadStreamGlueStrings[] = {
+ "",
+ "does not know how to proceed"};
+ char *errReadStreamFileStrings[] = {
+ "",
+ "did not recognize this as a blend file",
+ "was busted on a read error"};
+ char *errInflateStrings[] = {
+ "",
+ "bumped on a decompress error"};
+ char *errDecryptStrings[] = {
+ "",
+ "could not make a new key",
+ "bumped on a decrypt error",
+ "was not allowed. This blend file is not made by you."};
+ char *errVerifyStrings[] = {
+ "",
+ "could not make a new key",
+ "failed"};
+ char *errFunctionString= errFunctionStrings[errFunction];
+ char *errExtraString= "";
+ char *errString;
+
+ if (errGeneric) {
+ errExtraString= errGenericStrings[errGeneric];
+ } else if (errSpecific) {
+ switch (errFunction) {
+ case BRS_READSTREAMGLUE:
+ errExtraString= errReadStreamGlueStrings[errSpecific];
+ break;
+ case BRS_READSTREAMFILE:
+ errExtraString= errReadStreamFileStrings[errSpecific];
+ break;
+ case BRS_INFLATE:
+ errExtraString= errInflateStrings[errSpecific];
+ break;
+ case BRS_DECRYPT:
+ errExtraString= errDecryptStrings[errSpecific];
+ break;
+ case BRS_VERIFY:
+ errExtraString= errVerifyStrings[errSpecific];
+ break;
+ default:
+ break;
+ }
+ }
+
+ errString= MEM_mallocN(strlen(errFunctionString) + 1 + strlen(errExtraString) + 1);
+ sprintf(errString, "%s %s", errFunctionString, errExtraString);
+
+ return errString;
+}
+#endif
diff --git a/source/blender/readblenfile/intern/Makefile b/source/blender/readblenfile/intern/Makefile
new file mode 100644
index 00000000000..6c6683eb07d
--- /dev/null
+++ b/source/blender/readblenfile/intern/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 *****
+#
+#
+
+LIBNAME = readblenfile
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+ifeq ($(OS),$(findstring $(OS), "beos darwin freebsd linux openbsd solaris windows"))
+ CFLAGS += -funsigned-char
+endif
+
+CFLAGS += $(LEVEL_2_C_WARNINGS)
+
+# path to our own external headerfiles
+CPPFLAGS += -I..
+
+# external modules
+CPPFLAGS += -I../../../kernel/gen_messaging
+CPPFLAGS += -I../../readstreamglue
+CPPFLAGS += -I../../blenlib
+CPPFLAGS += -I../../makesdna
+CPPFLAGS += -I../../blenkernel
+CPPFLAGS += -I../../blenloader
diff --git a/source/blender/readblenfile/stub/BLO_readblenfileSTUB.c b/source/blender/readblenfile/stub/BLO_readblenfileSTUB.c
new file mode 100644
index 00000000000..19ebd4491bb
--- /dev/null
+++ b/source/blender/readblenfile/stub/BLO_readblenfileSTUB.c
@@ -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 *****
+ *
+ */
+
+#include <stdio.h>
+#include "GEN_messaging.h"
+
+ int
+BLO_readblenfilememory(
+ char *fromBuffer, int fromBufferSize)
+{
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "Error BLO_readblenfilename is a stub\n");
+#endif
+ return(1);
+}
+
+ int
+BLO_readblenfilename(
+ char *fileName)
+{
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "Error BLO_readblenfilename is a stub\n");
+#endif
+ return(1);
+}
+
+ int
+BLO_readblenfilehandle(
+ int fileHandle)
+{
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "Error BLO_readblenfilehandle is a stub\n");
+#endif
+ return(1);
+}
+
+ int
+BLO_is_a_runtime(
+ char *file)
+{
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "Error BLO_is_a_runtime is a stub\n");
+#endif
+ return 0;
+}
+
+ int
+BLO_read_runtime(
+ char *file)
+{
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "Error BLO_read_runtime is a stub\n");
+#endif
+ return 0;
+}
diff --git a/source/blender/readblenfile/stub/Makefile b/source/blender/readblenfile/stub/Makefile
new file mode 100644
index 00000000000..04c6b0e5f8d
--- /dev/null
+++ b/source/blender/readblenfile/stub/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 = readblenfileSTUB
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+ifeq ($(OS),$(findstring $(OS), "beos darwin freebsd linux openbsd solaris windows"))
+ CFLAGS += -funsigned-char
+endif
+
+CFLAGS += $(LEVEL_2_C_WARNINGS)
+
+# path to our own external headerfiles
+CPPFLAGS += -I..
+
+# external modules
+CPPFLAGS += -I../../../kernel/gen_messaging
+
diff --git a/source/blender/readblenfile/test/Makefile b/source/blender/readblenfile/test/Makefile
new file mode 100644
index 00000000000..2d7b7c7fff8
--- /dev/null
+++ b/source/blender/readblenfile/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 = readblenfile
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+ALLTARGETS = $(OBJS) $(DIR)/$(DEBUG_DIR)test$(EXT)
+
+include nan_compile.mk
+
+ifeq ($(OS),$(findstring $(OS), "beos darwin freebsd linux openbsd solaris windows"))
+ CFLAGS += -funsigned-char
+endif
+
+CFLAGS += $(LEVEL_2_C_WARNINGS)
+
+# path to our own external headerfiles
+CPPFLAGS += -I..
+CPPFLAGS += -I../../readstreamglue
+
+$(DIR)/$(DEBUG_DIR)test$(EXT): $(OBJS) ../intern/BLO_readblenfile.c
+ $(CC) $(LDFLAGS) -o $@ $(OBJS) $(OCGDIR)/blender/readblenfile/$(DEBUG_DIR)libreadblenfile.a
+ $(DIR)/$(DEBUG_DIR)test$(EXT)
+
diff --git a/source/blender/readblenfile/test/test.c b/source/blender/readblenfile/test/test.c
new file mode 100644
index 00000000000..6210cb6f219
--- /dev/null
+++ b/source/blender/readblenfile/test/test.c
@@ -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 <string.h> // strlen
+#include "BLO_readblenfile.h"
+
+struct streamGlueControlStruct *Global_streamGlueControl;
+
+ int
+streamGlueWrite(
+ struct streamGlueControlStruct *streamGlueControl,
+ struct streamGlueStruct **streamGlue,
+ unsigned char *data,
+ unsigned int dataIn,
+ int finishUp)
+{
+ printf("called with %d bytes in buffer [%s]\n", dataIn, data);
+ return (0);
+}
+
+main()
+{
+ int err;
+
+ err = BLO_readblenfile();
+}
diff --git a/source/blender/readstreamglue/BLO_keyStore.h b/source/blender/readstreamglue/BLO_keyStore.h
new file mode 100644
index 00000000000..805cffbee8b
--- /dev/null
+++ b/source/blender/readstreamglue/BLO_keyStore.h
@@ -0,0 +1,75 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * make all key elements available through functions
+ */
+
+#ifndef BLO_KEYSTORE_H
+#define BLO_KEYSTORE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "blenkey.h"
+
+ void
+keyStoreConstructor(
+ UserStruct *keyUserStruct,
+ char *privHexKey,
+ char *pubHexKey,
+ byte *ByteChecks,
+ char *HexPython);
+
+ void
+keyStoreDestructor(
+ void);
+
+ int
+keyStoreGetPubKey(
+ byte **PubKey);
+
+ int
+keyStoreGetPrivKey(
+ byte **PrivKey);
+
+ char *
+keyStoreGetUserName(
+ void);
+
+ char *
+keyStoreGetEmail(
+ void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BLO_KEYSTORE_H */
diff --git a/source/blender/readstreamglue/BLO_readStreamErrors.h b/source/blender/readstreamglue/BLO_readStreamErrors.h
new file mode 100644
index 00000000000..22b25bdd256
--- /dev/null
+++ b/source/blender/readstreamglue/BLO_readStreamErrors.h
@@ -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 *****
+ * all Blender Read Stream errors
+ */
+
+#ifndef BLO_READSTREAMERRORS_H
+#define BLO_READSTREAMERRORS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define BRS_SETFUNCTION(x) ( (int)(x) << 1)
+#define BRS_GETFUNCTION(x) (( (int)(x) >> 1) & 7)
+#define BRS_SETGENERR(x) ( (int)(x) << 4)
+#define BRS_GETGENERR(x) (( (int)(x) >> 4) & 7)
+#define BRS_SETSPECERR(x) ( (int)(x) << 7)
+#define BRS_GETSPECERR(x) (( (int)(x) >> 7) & 7)
+
+// FUNCTION
+#define BRS_READSTREAMGLUE 1
+#define BRS_READSTREAMLOOP 2
+#define BRS_KEYSTORE 3
+#define BRS_READSTREAMFILE 4
+#define BRS_INFLATE 5
+#define BRS_DECRYPT 6
+#define BRS_VERIFY 7
+
+// GENeric errors
+#define BRS_MALLOC 1
+#define BRS_NULL 2
+#define BRS_MAGIC 3
+#define BRS_CRCHEADER 4
+#define BRS_CRCDATA 5
+#define BRS_DATALEN 6
+#define BRS_STUB 7
+
+// READSTREAMGLUE specific
+#define BRS_UNKNOWN 1
+
+// READSTREAMFILE specific
+#define BRS_NOTABLEND 1
+#define BRS_READERROR 2
+
+// INFLATE specific
+#define BRS_INFLATEERROR 1
+
+// DECRYPT specific
+#define BRS_RSANEWERROR 1
+#define BRS_DECRYPTERROR 2
+#define BRS_NOTOURPUBKEY 3
+
+// VERIFY specific
+#define BRS_RSANEWERROR 1
+#define BRS_SIGFAILED 2
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BLO_READSTREAMERRORS_H */
diff --git a/source/blender/readstreamglue/BLO_readStreamGlue.h b/source/blender/readstreamglue/BLO_readStreamGlue.h
new file mode 100644
index 00000000000..a89674ee249
--- /dev/null
+++ b/source/blender/readstreamglue/BLO_readStreamGlue.h
@@ -0,0 +1,96 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * connect the read stream data processors
+ */
+
+#ifndef BLO_READSTREAMGLUE_H
+#define BLO_READSTREAMGLUE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "BLO_sys_types.h"
+#include "BLO_readStreamErrors.h"
+
+#define UNKNOWN 0
+#define DUMPTOMEMORY 1
+#define DUMPFROMMEMORY 2
+#define READBLENFILE 3
+#define WRITEBLENFILE 4
+#define INFLATE 5
+#define DEFLATE 6
+#define DECRYPT 7
+#define ENCRYPT 8
+#define VERIFY 9
+#define SIGN 10
+
+#define MAXSTREAMLENGTH 10
+
+#define STREAMGLUEHEADERSIZE sizeof(struct streamGlueHeaderStruct)
+
+struct streamGlueHeaderStruct {
+ uint8_t magic; /* poor mans header recognize check */
+ uint32_t totalStreamLength; /* how much data is there */
+ uint32_t dataProcessorType; /* next data processing action */
+ uint32_t crc; /* header minus crc itself checksum */
+};
+
+struct readStreamGlueStruct {
+ /* my control structure elements */
+ unsigned int totalStreamLength;
+ unsigned int streamDone;
+ int dataProcessorType;
+ void *ProcessorTypeControlStruct;
+
+ unsigned char headerbuffer[STREAMGLUEHEADERSIZE];
+
+ void *(*begin)(void *);
+ int (*process)(void *, unsigned char *, unsigned int);
+ int (*end)(void *);
+};
+
+ unsigned int
+correctByteOrder(
+ unsigned int x);
+
+ int
+readStreamGlue(
+ void *endControl,
+ struct readStreamGlueStruct **control,
+ unsigned char *data,
+ unsigned int dataIn);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BLO_READSTREAMGLUE_H */
diff --git a/source/blender/readstreamglue/BLO_sys_types.h b/source/blender/readstreamglue/BLO_sys_types.h
new file mode 100644
index 00000000000..2e300c8428e
--- /dev/null
+++ b/source/blender/readstreamglue/BLO_sys_types.h
@@ -0,0 +1,97 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 platform-independent definition of [u]intXX_t
+ * Plus the accompanying header include for htonl/ntohl
+ *
+ * This file includes <sys/types.h> to define [u]intXX_t types, where
+ * XX can be 8, 16, 32 or 64. Unfortunately, not all systems have this
+ * file.
+ * - Windows uses __intXX compiler-builtin types. These are signed,
+ * so we have to flip the signs.
+ * For these rogue platforms, we make the typedefs ourselves.
+ *
+ */
+
+#ifndef BLO_SYS_TYPES_H
+#define BLO_SYS_TYPES_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef _WIN32
+
+/* The __intXX are built-in types of the visual complier! So we don't
+ * need to include anything else here. */
+
+typedef signed __int8 int8_t;
+typedef signed __int16 int16_t;
+typedef signed __int32 int32_t;
+typedef signed __int64 int64_t;
+
+typedef unsigned __int8 uint8_t;
+typedef unsigned __int16 uint16_t;
+typedef unsigned __int32 uint32_t;
+typedef unsigned __int64 uint64_t;
+
+#elif defined(__linux__)
+
+ /* Linux-i386, Linux-Alpha, Linux-ppc */
+#include <stdint.h>
+
+#elif defined (__APPLE__)
+
+#include <inttypes.h>
+
+#else
+
+ /* FreeBSD, Irix, Solaris */
+#include <sys/types.h>
+
+#endif /* ifdef platform for types */
+
+#ifdef _WIN32
+#define htonl(x) correctByteOrder(x)
+#define ntohl(x) correctByteOrder(x)
+#elif defined __FreeBSD__
+#include <sys/param.h>
+#elif defined (__APPLE__)
+#include <sys/types.h>
+#else /* irix sun linux */
+#include <netinet/in.h>
+#endif /* ifdef platform for htonl/ntohl */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* eof */
diff --git a/source/blender/readstreamglue/Makefile b/source/blender/readstreamglue/Makefile
new file mode 100644
index 00000000000..d3a5d89131c
--- /dev/null
+++ b/source/blender/readstreamglue/Makefile
@@ -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 *****
+#
+# Bounces make to subdirectories.
+
+SOURCEDIR = source/blender/readstreamglue
+DIRS = intern
+
+include nan_subdirs.mk
diff --git a/source/blender/readstreamglue/intern/BLO_keyStore.c b/source/blender/readstreamglue/intern/BLO_keyStore.c
new file mode 100644
index 00000000000..3936e73326c
--- /dev/null
+++ b/source/blender/readstreamglue/intern/BLO_keyStore.c
@@ -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 *****
+ * make all key elements available through functions
+ */
+
+#include <stdlib.h>
+#include <assert.h>
+
+#include "BLO_keyStore.h"
+#include "BLO_keyStorePrivate.h"
+
+// our ugly but private global pointer
+static struct keyStoreStruct *keyStore = NULL;
+
+ void
+keyStoreConstructor(
+ UserStruct *keyUserStruct,
+ char *privHexKey,
+ char *pubHexKey,
+ byte *ByteChecks,
+ char *HexPython)
+{
+ assert(keyStore == NULL);
+ keyStore = malloc(sizeof(struct keyStoreStruct));
+ assert(keyStore);
+ // TODO check for malloc errors
+
+ keyStore->keyUserStruct = *keyUserStruct;
+
+ keyStore->privKey = DeHexify(privHexKey);
+ keyStore->privKeyLen = strlen(privHexKey) / 2;
+
+ keyStore->pubKey = DeHexify(pubHexKey);
+ keyStore->pubKeyLen = strlen(pubHexKey) / 2;
+
+ memcpy(keyStore->ByteChecks, ByteChecks, 1000);
+
+ keyStore->PythonCode = DeHexify(HexPython);
+ keyStore->PythonCodeLen = strlen(HexPython) / 2;
+}
+
+ void
+keyStoreDestructor(
+ void)
+{
+ assert(keyStore);
+ if (!keyStore) {
+ return;
+ }
+ free(keyStore->privKey);
+ free(keyStore->pubKey);
+ free(keyStore->PythonCode);
+ free(keyStore);
+ keyStore = NULL;
+}
+
+ int
+keyStoreGetPubKey(
+ byte **PubKey)
+{
+ if (!keyStore) {
+ *PubKey = NULL;
+ return 0;
+ }
+ *PubKey = keyStore->pubKey;
+ return(keyStore->pubKeyLen);
+}
+
+ int
+keyStoreGetPrivKey(
+ byte **PrivKey)
+{
+ if (!keyStore) {
+ *PrivKey = NULL;
+ return 0;
+ }
+ *PrivKey = keyStore->privKey;
+ return(keyStore->privKeyLen);
+}
+
+ char *
+keyStoreGetUserName(
+ void)
+{
+ if (!keyStore) {
+ return NULL;
+ }
+ return(keyStore->keyUserStruct.name);
+}
+
+ char *
+keyStoreGetEmail(
+ void)
+{
+ if (!keyStore) {
+ return NULL;
+ }
+ return(keyStore->keyUserStruct.email);
+}
+
diff --git a/source/blender/readstreamglue/intern/BLO_keyStorePrivate.h b/source/blender/readstreamglue/intern/BLO_keyStorePrivate.h
new file mode 100644
index 00000000000..af5dee37860
--- /dev/null
+++ b/source/blender/readstreamglue/intern/BLO_keyStorePrivate.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 BLO_KEYSTOREPRIVATE_H
+#define BLO_KEYSTOREPRIVATE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "blenkey.h"
+
+// TODO this must be made external in key.h
+#define MAXBYTEDATABLOCK 1000
+
+struct keyStoreStruct {
+ UserStruct keyUserStruct;
+
+ byte *privKey;
+ int privKeyLen;
+
+ byte *pubKey;
+ int pubKeyLen;
+
+ byte ByteChecks[MAXBYTEDATABLOCK];
+
+ byte *PythonCode;
+ int PythonCodeLen;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BLO_KEYSTOREPRIVATE_H */
diff --git a/source/blender/readstreamglue/intern/BLO_readStreamGlue.c b/source/blender/readstreamglue/intern/BLO_readStreamGlue.c
new file mode 100644
index 00000000000..5f2754d8628
--- /dev/null
+++ b/source/blender/readstreamglue/intern/BLO_readStreamGlue.c
@@ -0,0 +1,228 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * connect the read stream data processors
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "zlib.h"
+
+#include "GEN_messaging.h"
+
+#include "BLO_readStreamGlue.h"
+
+#include "BLO_readStreamGlueLoopBack.h"
+#include "BLO_readfile.h"
+#include "BLO_inflate.h"
+#include "BLO_decrypt.h"
+#include "BLO_verify.h"
+
+ unsigned int
+correctByteOrder(
+ unsigned int x)
+{
+ unsigned char *s = (unsigned char *)&x;
+ return (unsigned int)(s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3]);
+}
+
+ int
+readStreamGlue(
+ void * endControl,
+ struct readStreamGlueStruct **control,
+ unsigned char *data,
+ unsigned int dataIn)
+{
+ int err = 0;
+
+ if (NULL == *control) {
+ /* we are called for the first time; play constructor */
+ *control = malloc(sizeof (struct readStreamGlueStruct));
+ if (*control == NULL) {
+ err = BRS_SETFUNCTION(BRS_READSTREAMGLUE) |
+ BRS_SETGENERR(BRS_MALLOC);
+ return err;
+ }
+ (*control)->totalStreamLength = 0;
+ (*control)->streamDone = 0;
+ (*control)->dataProcessorType = UNKNOWN;
+ memset((*control)->headerbuffer, 0, STREAMGLUEHEADERSIZE);
+ (*control)->begin = NULL;
+ (*control)->process = NULL;
+ (*control)->end = NULL;
+ }
+
+ /* First check if we have our header filled in yet */
+ if ((dataIn > 0) && ((*control)->dataProcessorType == 0)) {
+ unsigned int processed;
+ processed = ((dataIn + (*control)->streamDone) <= STREAMGLUEHEADERSIZE)
+ ? dataIn : STREAMGLUEHEADERSIZE;
+ memcpy((*control)->headerbuffer + (*control)->streamDone,
+ data, processed);
+ (*control)->streamDone += processed;
+ dataIn -= processed;
+ data += processed;
+
+ if ((*control)->streamDone == STREAMGLUEHEADERSIZE) {
+ /* we have the whole header, absorb it */
+ struct streamGlueHeaderStruct *header;
+ uint32_t crc;
+ header = (struct streamGlueHeaderStruct *)
+ (*control)->headerbuffer;
+ (*control)->totalStreamLength =
+ ntohl(header->totalStreamLength);
+ (*control)->dataProcessorType =
+ ntohl(header->dataProcessorType);
+ crc = crc32(0L, (const Bytef *) header, STREAMGLUEHEADERSIZE - 4);
+
+ if (header->magic == 'A') {
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "streamGlue header read. Magic confirmed\n");
+#endif
+ } else {
+ err = BRS_SETFUNCTION(BRS_READSTREAMGLUE) |
+ BRS_SETGENERR(BRS_MAGIC);
+ free(*control);
+ (*control) = NULL;
+ return err;
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "ERROR streamGlue header read. Magic NOT confirmed (%c)\n",
+ header->magic);
+#endif
+ }
+
+ if (crc == ntohl(header->crc)) {
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "streamGlue header CRC correct\n");
+#endif
+ } else {
+ err = BRS_SETFUNCTION(BRS_READSTREAMGLUE) |
+ BRS_SETGENERR(BRS_CRCHEADER);
+ free(*control);
+ (*control) = NULL;
+ return err;
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "ERROR streamGlue header CRC NOT correct\n");
+#endif
+ }
+
+ // No more header-> usage from this point !
+
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "read action %d will get %u raw bytes\n",
+ (*control)->dataProcessorType,
+ (unsigned int) (*control)->totalStreamLength);
+#endif
+
+ /* Set pointers to the correct dataprocessor functions */
+ switch ((*control)->dataProcessorType) {
+ case DUMPTOMEMORY:
+ case DUMPFROMMEMORY:
+ (*control)->begin = blo_readstreamfile_begin;
+ (*control)->process = blo_readstreamfile_process;
+ (*control)->end = blo_readstreamfile_end;
+ break;
+ case READBLENFILE:
+ case WRITEBLENFILE:
+ (*control)->begin = readStreamGlueLoopBack_begin;
+ (*control)->process = readStreamGlueLoopBack_process;
+ (*control)->end = readStreamGlueLoopBack_end;
+ break;
+ case INFLATE:
+ case DEFLATE:
+ (*control)->begin = BLO_inflate_begin;
+ (*control)->process = BLO_inflate_process;
+ (*control)->end = BLO_inflate_end;
+ break;
+ case DECRYPT:
+ case ENCRYPT:
+ (*control)->begin = BLO_decrypt_begin;
+ (*control)->process = BLO_decrypt_process;
+ (*control)->end = BLO_decrypt_end;
+ break;
+ case VERIFY:
+ case SIGN:
+ (*control)->begin = BLO_verify_begin;
+ (*control)->process = BLO_verify_process;
+ (*control)->end = BLO_verify_end;
+ break;
+ default:
+ err = BRS_SETFUNCTION(BRS_READSTREAMGLUE) |
+ BRS_SETSPECERR(BRS_UNKNOWN);
+ (*control) = NULL;
+ free(*control);
+ return err;
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "unknown dataProcessorType %d\n",
+ (*control)->dataProcessorType);
+#endif
+ break;
+ }
+ /* Call the dataprocessors begin() and
+ * store its (*control) struct pointer */
+ (*control)->ProcessorTypeControlStruct =
+ (*(*control)->begin)(endControl);
+ if ((*control)->ProcessorTypeControlStruct == NULL) {
+ free(*control);
+ (*control) = NULL;
+ return err;
+ }
+ }
+
+ }
+
+ /* Is there really (still) new data available ? */
+ if (dataIn > 0) {
+ err = (*(*control)->process)((*control)->ProcessorTypeControlStruct,
+ data, dataIn);
+ if (err) {
+ free(*control);
+ (*control) = NULL;
+ return err;
+ }
+ (*control)->streamDone += dataIn;
+ }
+ if ((*control)->streamDone == (*control)->totalStreamLength +
+ STREAMGLUEHEADERSIZE) {
+ err = (*(*control)->end)((*control)->ProcessorTypeControlStruct);
+ free(*control);
+ (*control) = NULL;
+ }
+ return err;
+}
+
diff --git a/source/blender/readstreamglue/intern/BLO_readStreamGlueLoopBack.c b/source/blender/readstreamglue/intern/BLO_readStreamGlueLoopBack.c
new file mode 100644
index 00000000000..e63ae974d5c
--- /dev/null
+++ b/source/blender/readstreamglue/intern/BLO_readStreamGlueLoopBack.c
@@ -0,0 +1,80 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * streamglue loopback. Needed at start of Read stream.
+ */
+
+#include <stdlib.h> // TODO use blender's
+
+#include "BLO_readStreamGlue.h"
+#include "BLO_readStreamGlueLoopBack.h"
+
+ struct readStreamGlueLoopBackStruct *
+readStreamGlueLoopBack_begin(
+ void *endControl)
+{
+ struct readStreamGlueLoopBackStruct *control;
+ control = malloc(sizeof(struct readStreamGlueLoopBackStruct));
+ if (control == NULL) {
+ return NULL;
+ }
+
+ control->streamGlue = NULL;
+ control->endControl = endControl;
+
+ return(control);
+}
+
+ int
+readStreamGlueLoopBack_process(
+ struct readStreamGlueLoopBackStruct *control,
+ unsigned char *data,
+ unsigned int dataIn)
+{
+ int err = 0;
+ /* Is there really new data available ? */
+ if (dataIn > 0) {
+ err = readStreamGlue(
+ control->endControl,
+ &(control->streamGlue),
+ data,
+ dataIn);
+ }
+ return err;
+}
+
+ int
+readStreamGlueLoopBack_end(
+ struct readStreamGlueLoopBackStruct *control)
+{
+ free(control);
+ return 0;
+}
+
diff --git a/source/blender/readstreamglue/intern/BLO_readStreamGlueLoopBack.h b/source/blender/readstreamglue/intern/BLO_readStreamGlueLoopBack.h
new file mode 100644
index 00000000000..148b5016eb4
--- /dev/null
+++ b/source/blender/readstreamglue/intern/BLO_readStreamGlueLoopBack.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 *****
+ * streamglue loopback. Needed at start of Read stream.
+ */
+
+struct readStreamGlueLoopBackStruct {
+ struct readStreamGlueStruct *streamGlue;
+ void *endControl;
+};
+
+ struct readStreamGlueLoopBackStruct *
+readStreamGlueLoopBack_begin(
+ void *endControl);
+
+ int
+readStreamGlueLoopBack_process(
+ struct readStreamGlueLoopBackStruct *control,
+ unsigned char *data,
+ unsigned int dataIn);
+
+ int
+readStreamGlueLoopBack_end(
+ struct readStreamGlueLoopBackStruct *control);
+
diff --git a/source/blender/readstreamglue/intern/Makefile b/source/blender/readstreamglue/intern/Makefile
new file mode 100644
index 00000000000..c42a1f4d0bb
--- /dev/null
+++ b/source/blender/readstreamglue/intern/Makefile
@@ -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 *****
+#
+#
+
+LIBNAME = readstreamglue
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+ifeq ($(OS),$(findstring $(OS), "beos darwin freebsd linux openbsd solaris windows"))
+ CFLAGS += -funsigned-char
+endif
+
+CFLAGS += $(LEVEL_2_C_WARNINGS)
+
+# path to our own private header files
+CPPFLAGS += -I.
+
+# path to our own external header files
+CPPFLAGS += -I..
+
+# external modules
+CPPFLAGS += -I../../../kernel/gen_messaging
+CPPFLAGS += -I../../blenloader
+CPPFLAGS += -I../../inflate
+CPPFLAGS += -I../../decrypt
+CPPFLAGS += -I../../verify
+
+CPPFLAGS += -I$(NAN_OPENSSL)/include
+
+#TODO make keystore a seperate lib
+CPPFLAGS += -I$(NAN_BLENKEY)/include
+
+ifeq ($(OS),$(findstring $(OS), "solaris windows"))
+ CPPFLAGS += -I$(NAN_ZLIB)/include
+endif
+
diff --git a/source/blender/render/Makefile b/source/blender/render/Makefile
new file mode 100644
index 00000000000..5d8fbdd743f
--- /dev/null
+++ b/source/blender/render/Makefile
@@ -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 *****
+#
+# Bounces make to subdirectories.
+
+SOURCEDIR = source/blender/render
+DIRS = intern
+
+include nan_subdirs.mk
diff --git a/source/blender/render/extern/include/render.h b/source/blender/render/extern/include/render.h
new file mode 100644
index 00000000000..0ac9d7e61c8
--- /dev/null
+++ b/source/blender/render/extern/include/render.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 *****
+ * Interface to transform the Blender scene into renderable data.
+ */
+
+#ifndef RENDER_H
+#define RENDER_H "$Id$"
+
+/* ------------------------------------------------------------------------- */
+/* This little preamble might be moved to a separate include. It contains */
+/* some defines that should become functions, and some platform dependency */
+/* fixes. I think it is risky to always include it... */
+/* ------------------------------------------------------------------------- */
+
+/* fix for OSA and defmaterial extern */
+#include "BKE_osa_types.h"
+#include "DNA_material_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* For #undefs of stupid windows defines */
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+/* ------------------------------------------------------------------------- */
+/* Types */
+/* Both external and internal types can be placed here. Make sure there are */
+/* no dirty extras in the type files so they can be included without */
+/* problems. If possible, make a note why the include is needed. */
+/* ------------------------------------------------------------------------- */
+
+#include "render_types.h"
+
+/* ------------------------------------------------------------------------- */
+/* Global variables */
+/* These variable are global to the render module, and also externally */
+/* visible. The file where they are defined must be added. */
+/* ------------------------------------------------------------------------- */
+
+extern RE_Render R; /* rendercore.c */
+extern Osa O; /* rendercore.c */
+extern Material defmaterial; /* initrender.c */
+extern unsigned short *igamtab1; /* initrender.c */
+extern unsigned short *gamtab; /* initrender.c */
+
+struct View3D;
+
+/* ------------------------------------------------------------------------- */
+/* Function definitions */
+/* */
+/* All functions that need to be externally visible must be declared here. */
+/* Currently, this interface contains 29 functions and 11 callbacks. */
+/* ------------------------------------------------------------------------- */
+
+
+/* ------------------------------------------------------------------------- */
+/* Needed for the outside world referring to shadowbuffers */
+/* ------------------------------------------------------------------------- */
+
+#ifndef RE_SHADOWBUFFERHANDLE
+#define RE_SHADOWBUFFERHANDLE
+#define RE_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name
+ RE_DECLARE_HANDLE(RE_ShadowBufferHandle);
+#endif
+
+ /**
+ * Create a new, empty shadow buffer with certain settings.
+ *
+ * @param mode 0 is a dummy buffer, 1 is the old buffer for
+ * c-based shadowing, 2 is the old buffer with c++ refit , 2 is a
+ * deep buffer
+ */
+ extern RE_ShadowBufferHandle RE_createShadowBuffer(struct LampRen *lar,
+ float mat[][4],
+ int mode);
+
+ /**
+ * Delete a shadow buffer.
+ * @param shb handle to the buffer to be released
+ */
+ extern void RE_deleteShadowBuffer(RE_ShadowBufferHandle shb);
+
+
+
+/* ------------------------------------------------------------------------- */
+/* initrender (14) */
+/* ------------------------------------------------------------------------- */
+
+struct View3D;
+
+/**
+ * Guarded call to frame renderer? Tests several limits and boundary
+ * conditions.
+ *
+ * @param ogl_render_area The View3D area to use for OpenGL rendering
+ * (can be NULL unless render R_OGL flag is set)
+ */
+void RE_initrender(struct View3D *ogl_render_view3d);
+
+/**
+ *
+ */
+void RE_setwindowclip(int mode, int jmode);
+
+/*
+ * @param ogl_render_area The View3D area to use for OpenGL rendering
+ * (can be NULL unless render R_OGL flag is set)
+ */
+void RE_animrender(struct View3D *ogl_render_view3d);
+void RE_free_render_data(void);
+void RE_free_filt_mask(void);
+void RE_holoview(void);
+void RE_init_filt_mask(void);
+void RE_init_render_data(void);
+void RE_jitterate1(float *jit1, float *jit2, int num, float rad1);
+void RE_jitterate2(float *jit1, float *jit2, int num, float rad2);
+void RE_make_existing_file(char *name);
+
+/* ------------------------------------------------------------------------- */
+/* zbuf (2) */
+/* ------------------------------------------------------------------------- */
+
+/**
+ * Converts a world coordinate into a homogenous coordinate in view
+ * coordinates. (WCS -> HCS)
+ * Also called in: shadbuf.c render.c radfactors.c
+ * initrender.c envmap.c editmesh.c
+ * @param v1 [3 floats] the world coordinate
+ * @param adr [4 floats] the homogenous view coordinate
+ */
+void RE_projectverto(float *v1,float *adr);
+
+/**
+ * Something about doing radiosity z buffering?
+ * (called in radfactors.c), hope the RadView is defined already...
+ * Also called in: radfactors.c
+ * Note: Uses globals.
+ * @param radview radiosity view definition
+ */
+ struct RadView;
+ struct RNode;
+void RE_zbufferall_radio(struct RadView *vw, struct RNode **rg_elem, int rg_totelem);
+
+
+/* ------------------------------------------------------------------------- */
+/* envmap (5) */
+/* ------------------------------------------------------------------------- */
+ struct EnvMap;
+ struct Tex;
+void RE_free_envmapdata(struct EnvMap *env);
+void RE_free_envmap(struct EnvMap *env);
+struct EnvMap *RE_add_envmap(void);
+/* these two maybe not external? yes, they are, for texture.c */
+struct EnvMap *RE_copy_envmap(struct EnvMap *env);
+/* (used in texture.c) */
+int RE_envmaptex(struct Tex *tex, float *texvec, float *dxt, float *dyt);
+
+ /* --------------------------------------------------------------------- */
+ /* rendercore (2) */
+ /* --------------------------------------------------------------------- */
+ float RE_Spec(float inp, int hard);
+
+ /* maybe not external */
+ void RE_calc_R_ref(void);
+
+ /* --------------------------------------------------------------------- */
+ /* renderdatabase (3) */
+ /* --------------------------------------------------------------------- */
+ struct VlakRen *RE_findOrAddVlak(int nr);
+ struct VertRen *RE_findOrAddVert(int nr);
+ struct HaloRen *RE_findOrAddHalo(int nr);
+ HaloRen *RE_inithalo(Material *ma,
+ float *vec,
+ float *vec1,
+ float *orco,
+ float hasize,
+ float vectsize);
+
+
+ /**
+ * callbacks (11):
+ *
+ * If the callbacks aren't set, rendering will still proceed as
+ * desired, but the concerning functionality will not be enabled.
+ *
+ * There need to be better uncoupling between the renderer and
+ * these functions still!
+ * */
+
+ void RE_set_test_break_callback(int (*f)(void));
+
+ void RE_set_timecursor_callback(void (*f)(int));
+
+ void RE_set_renderdisplay_callback(void (*f)(int, int, int, int, unsigned int *));
+ void RE_set_initrenderdisplay_callback(void (*f)(void));
+ void RE_set_clearrenderdisplay_callback(void (*f)(short));
+
+ void RE_set_printrenderinfo_callback(void (*f)(double,int));
+
+ void RE_set_getrenderdata_callback(void (*f)(void));
+ void RE_set_freerenderdata_callback(void (*f)(void));
+
+
+ /*from renderhelp, should disappear!!! */
+ /** Recalculate all normals on renderdata. */
+ void set_normalflags(void);
+ /**
+ * On loan from zbuf.h:
+ * Tests whether the first three coordinates should be clipped
+ * wrt. the fourth component. Bits 1 and 2 test on x, 3 and 4 test on
+ * y, 5 and 6 test on z:
+ * xyz > test => set first bit (01),
+ * xyz < -test => set second bit (10),
+ * xyz == test => reset both bits (00).
+ * Note: functionality is duplicated from an internal function
+ * Also called in: initrender.c, radfactors.c
+ * @param v [4 floats] a coordinate
+ * @return a vector of bitfields
+ */
+ int RE_testclip(float *v);
+
+ /* patch for the external if, to support the split for the ui */
+ void RE_addalphaAddfac(char *doel, char *bron, char addfac);
+ void RE_sky(char *col);
+ void RE_renderflare(struct HaloRen *har);
+ /**
+ * Shade the pixel at xn, yn for halo har, and write the result to col.
+ * Also called in: previewrender.c
+ * @param har The halo to be rendered on this location
+ * @param col [unsigned int 3] The destination colour vector
+ * @param zz Some kind of distance
+ * @param dist Square of the distance of this coordinate to the halo's center
+ * @param x [f] Pixel x relative to center
+ * @param y [f] Pixel y relative to center
+ * @param flarec Flare counter? Always har->flarec...
+ */
+ void RE_shadehalo(struct HaloRen *har,
+ char *col,
+ unsigned int zz,
+ float dist,
+ float x,
+ float y,
+ short flarec);
+
+/***/
+
+/* haloren->type: flags */
+
+#define HA_ONLYSKY 1
+#define HA_VECT 2
+#define HA_XALPHA 4
+#define HA_FLARECIRC 8
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* RENDER_H */
diff --git a/source/blender/render/extern/include/render_types.h b/source/blender/render/extern/include/render_types.h
new file mode 100644
index 00000000000..6ed2eafba21
--- /dev/null
+++ b/source/blender/render/extern/include/render_types.h
@@ -0,0 +1,256 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 RENDER_TYPES_H
+#define RENDER_TYPES_H "$Id$"
+
+#include "DNA_scene_types.h"
+#include "DNA_world_types.h"
+/* ------------------------------------------------------------------------- */
+
+/* Definitely weird: this equals 1<<21... so wtf?*/
+#define MAXVERT (2<<20)
+#define MAXVLAK (2<<20)
+
+
+/* This is needed to not let VC choke on near and far... old
+ * proprietary MS extensions... */
+#ifdef WIN32
+#undef near
+#undef far
+#define near clipsta
+#define far clipend
+#endif
+
+/* ------------------------------------------------------------------------- */
+
+typedef struct RE_Render
+{
+ float co[3];
+ float lo[3], gl[3], uv[3], ref[3], orn[3], winco[3], sticky[3], vcol[3];
+ float itot, i, ic, rgb, norm;
+ float vn[3], view[3], *vno, refcol[4];
+
+ float grvec[3], inprz, inprh;
+ float imat[3][3];
+
+ float viewmat[4][4], viewinv[4][4];
+ float persmat[4][4], persinv[4][4];
+ float winmat[4][4];
+
+ short flag, osatex, osa, rt;
+ /**
+ * Screen sizes and positions, in pixels
+ */
+ short xstart, xend, ystart, yend, afmx, afmy;
+ short rectx; /* Picture width - 1, normally xend - xstart. */
+ short recty; /* picture height - 1, normally yend - ystart. */
+
+ /**
+ * Distances and sizes in world coordinates nearvar, farvar were
+ * near and far, but VC in cpp mode chokes on it :( */
+ float near; /* near clip distance */
+ float far; /* far clip distance */
+ float ycor, zcor, pixsize, viewfac;
+
+
+ /* These three need to be 'handlerized'. Not an easy task... */
+/* RE_RenderDataHandle r; */
+ RenderData r;
+ World wrld;
+ ListBase parts;
+
+ int totvlak, totvert, tothalo, totlamp;
+
+ /* internal: these two are a sort of cache for the render pipe */
+ struct VlakRen *vlr;
+ int vlaknr;
+
+ /* external */
+ struct Material *mat, *matren;
+ /* internal, fortunately */
+ struct LampRen **la;
+ struct VlakRen **blovl;
+ struct VertRen **blove;
+ struct HaloRen **bloha;
+
+ unsigned int *rectaccu;
+ unsigned int *rectz; /* z buffer: distance buffer */
+ unsigned int *rectf1, *rectf2;
+ unsigned int *rectot; /* z buffer: face index buffer, recycled as colour buffer! */
+ unsigned int *rectspare; /* */
+ /* for 8 byte systems! */
+ long *rectdaps;
+
+ short win, winpos, winx, winy, winxof, winyof;
+ short winpop, displaymode, sparex, sparey;
+
+ /* Not sure what these do... But they're pointers, so good for handlerization */
+ struct Image *backbuf, *frontbuf;
+ /* backbuf is an image that drawn as background */
+
+} RE_Render;
+
+/* ------------------------------------------------------------------------- */
+
+/**
+ * Part as in part-rendering. An image rendered in parts is rendered
+ * to a list of parts, with x,y size, and a pointer to the render
+ * output stored per part. Internal!
+ */
+typedef struct Part
+{
+ struct Part *next, *prev;
+ unsigned int *rect;
+ short x, y;
+} Part;
+
+typedef struct ShadBuf {
+ short samp, shadhalostep;
+ float persmat[4][4];
+ float viewmat[4][4];
+ float winmat[4][4];
+ float *jit;
+ float d,far,pixsize,soft;
+ int co[3];
+ int size,bias;
+ unsigned long *zbuf;
+ char *cbuf;
+} ShadBuf;
+
+/* ------------------------------------------------------------------------- */
+
+typedef struct VertRen
+{
+ float co[3];
+ float n[3];
+ float ho[4];
+ float *orco;
+ float *sticky;
+ void *svert; /* smooth vert, only used during initrender */
+ short clip, texofs; /* texofs= flag */
+} VertRen;
+
+/* ------------------------------------------------------------------------- */
+
+struct halosort {
+ struct HaloRen *har;
+ unsigned int z;
+};
+
+/* ------------------------------------------------------------------------- */
+struct Material;
+struct MFace;
+struct TFace;
+
+typedef struct VlakRen
+{
+ struct VertRen *v1, *v2, *v3, *v4;
+ float n[3], len;
+ struct Material *mat;
+ struct MFace *mface;
+ struct TFace *tface;
+ unsigned int *vcol;
+ char snproj, puno;
+ char flag, ec;
+ unsigned int lay;
+} VlakRen;
+
+
+typedef struct HaloRen
+{
+ float alfa, xs, ys, rad, radsq, sin, cos, co[3], no[3];
+ unsigned int zs, zd;
+ unsigned int zBufDist;/* depth in the z-buffer coordinate system */
+ short miny, maxy;
+ short hard, b, g, r;
+ char starpoints, add, type, tex;
+ char linec, ringc, seed;
+ short flarec; /* used to be a char. why ?*/
+ float hasize;
+ int pixels;
+ unsigned int lay;
+ struct Material *mat;
+} HaloRen;
+
+struct LampRen;
+struct MTex;
+
+/**
+ * For each lamp in a scene, a LampRen is created. It determines the
+ * properties of a lightsource.
+ */
+typedef struct LampRen
+{
+ float xs, ys, dist;
+ float co[3];
+ short type, mode;
+ float r, g, b;
+ float energy, haint;
+ int lay;
+ float spotsi,spotbl;
+ float vec[3];
+ float xsp, ysp, distkw, inpr;
+ float halokw, halo;
+ float ld1,ld2;
+
+ /* copied from Lamp, to decouple more rendering stuff */
+ /** Size of the shadowbuffer */
+ short bufsize;
+ /** Number of samples for the shadows */
+ short samp;
+ /** Softness factor for shadow */
+ float soft;
+ /** shadow plus halo: detail level */
+ short shadhalostep;
+ /** Near clip of the lamp */
+ float clipsta;
+ /** Far clip of the lamp */
+ float clipend;
+ /** A small depth offset to prevent self-shadowing. */
+ float bias;
+
+ /** If the lamp casts shadows, one of these is filled. For the old
+ * renderer, shb is used, for the new pipeline the shadowBufOb,
+ * which should be a shadowbuffer handle. */
+ struct ShadBuf *shb;
+ void* shadowBufOb;
+
+ float imat[3][3];
+ float spottexfac;
+ float sh_invcampos[3], sh_zfac; /* sh_= spothalo */
+
+ struct LampRen *org;
+ struct MTex *mtex[8];
+} LampRen;
+
+#endif /* RENDER_TYPES_H */
diff --git a/source/blender/render/intern/Makefile b/source/blender/render/intern/Makefile
new file mode 100644
index 00000000000..ee9969a76c8
--- /dev/null
+++ b/source/blender/render/intern/Makefile
@@ -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 *****
+#
+# Bounces make to subdirectories.
+
+SOURCEDIR = source/blender/render/intern
+DIRS = source
+
+include nan_subdirs.mk
diff --git a/source/blender/render/intern/include/RE_DummyShadowBuffer.h b/source/blender/render/intern/include/RE_DummyShadowBuffer.h
new file mode 100644
index 00000000000..d5308277f6c
--- /dev/null
+++ b/source/blender/render/intern/include/RE_DummyShadowBuffer.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 *****
+ */
+
+#ifndef RE_DUMMYSHADOWBUFFER_H
+#define RE_DUMMYSHADOWBUFFER_H
+
+#include "RE_ShadowBuffer.h"
+
+struct LampRen;
+
+class RE_DummyShadowBuffer : public RE_ShadowBuffer {
+
+ public:
+ /**
+ * Make an empty shadow buffer
+ */
+ RE_DummyShadowBuffer(void);
+
+ /**
+ * Delete and clear this buffer
+ */
+ virtual ~RE_DummyShadowBuffer(void);
+
+ /**
+ * Place this scene in the buffer
+ */
+ virtual void importScene(struct LampRen* lar);
+
+ /**
+ * Always return a fixed shadow factor.
+ * @param inp ignored
+ * @param shb ignored
+ * @param shadowResult a vector of 3 floats with rgb shadow values
+ */
+ virtual void readShadowValue(struct ShadBuf *shb,
+ float inp,
+ float* shadowResult);
+
+};
+
+#endif /* RE_SHADOWBUFFER_H */
diff --git a/source/blender/render/intern/include/RE_ShadowBuffer.h b/source/blender/render/intern/include/RE_ShadowBuffer.h
new file mode 100644
index 00000000000..3b015597bb9
--- /dev/null
+++ b/source/blender/render/intern/include/RE_ShadowBuffer.h
@@ -0,0 +1,61 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 RE_SHADOWBUFFER_H
+#define RE_SHADOWBUFFER_H
+
+#include <iostream.h>
+
+struct ShadBuf;
+struct LampRen;
+
+class RE_ShadowBuffer {
+
+ public:
+
+ virtual ~RE_ShadowBuffer(void){};
+ /**
+ * Place this scene in the buffer
+ */
+ virtual void importScene(struct LampRen* lar) = 0;
+
+ /**
+ * Test the shadow factor at a location in the buffer
+ * @param shadowResult a vector of 3 floats with rgb shadow values
+ */
+ virtual void readShadowValue(struct ShadBuf *shb,
+ float inp,
+ float* shadowResult) = 0;
+
+};
+
+#endif /* RE_SHADOWBUFFER_H */
diff --git a/source/blender/render/intern/include/RE_basicShadowBuffer.h b/source/blender/render/intern/include/RE_basicShadowBuffer.h
new file mode 100644
index 00000000000..8d5e9237205
--- /dev/null
+++ b/source/blender/render/intern/include/RE_basicShadowBuffer.h
@@ -0,0 +1,94 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 RE_BASICSHADOWBUFFER_H
+#define RE_BASICSHADOWBUFFER_H
+
+#include "RE_ShadowBuffer.h"
+
+struct LampRen;
+struct Lamp;
+
+class RE_BasicShadowBuffer : public RE_ShadowBuffer {
+
+ private:
+
+ void lrectreadRectz(int x1, int y1, int x2, int y2, char *r1);
+ int sizeoflampbuf(struct ShadBuf *shb);
+ int firstreadshadbuf(struct ShadBuf *shb, int xs, int ys, int nr);
+ float readshadowbuf(struct ShadBuf *shb, int xs, int ys, int zs);
+ float readshadowbuf_halo(struct ShadBuf *shb, int xs, int ys, int zs);
+ float *give_jitter_tab(int samp);
+
+ int bias;
+
+ public:
+ /**
+ * Make a shadow buffer from these settings
+ */
+ RE_BasicShadowBuffer(struct LampRen *lar, float mat[][4]);
+
+ /**
+ * Delete and clear this buffer
+ */
+ virtual ~RE_BasicShadowBuffer(void);
+
+ /**
+ * Calculates shadowbuffers for a vector of shadow-giving lamps
+ * @param lar The vector of lamps
+ */
+ void importScene(LampRen *lar);
+
+ /**
+ * Determines the shadow factor for a face and lamp. There is some
+ * communication with global variables here.
+ * @param shadres The RGB shadow factors: 1.0 for no shadow, 0.0 for complete
+ * shadow. There must be a float[3] to write the result to.
+ * @param shb The shadowbuffer to find the shadow factor in.
+ * @param inp The inproduct between viewvector and ?
+ *
+ */
+ virtual void readShadowValue(struct ShadBuf *shb,
+ float inp,
+ float* shadowResult);
+
+ /**
+ * Determines the shadow factor for lamp <lar>, between <p1>
+ * and <p2>. (Which CS?)
+ */
+ float shadow_halo(LampRen *lar, float *p1, float *p2);
+
+};
+
+#endif /* RE_BASICSHADOWBUFFER_H */
+
+
diff --git a/source/blender/render/intern/include/RE_callbacks.h b/source/blender/render/intern/include/RE_callbacks.h
new file mode 100644
index 00000000000..30734728b4b
--- /dev/null
+++ b/source/blender/render/intern/include/RE_callbacks.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 *****
+ * Callbacks to make the renderer interact with calling modules.
+ */
+
+#ifndef RE_CALLBACKS_H
+#define RE_CALLBACKS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ /**
+ * Test whether operation should be prematurely terminated.
+ *
+ * @returns 0 to continue, any other value to break.
+ */
+ int RE_local_test_break(void);
+
+ /**
+ * Set a red square with the argument as text as cursor.
+ */
+ void RE_local_timecursor(int i);
+
+ /**
+ * Render these lines from the renderbuffer on screen (needs better spec)
+ */
+ void RE_local_render_display(int i, int j, int k, int l, unsigned int *m);
+
+ /**
+ * Initialise a render display (needs better spec)
+ */
+ void RE_local_init_render_display(void);
+
+ /**
+ * Clear/close a render display (needs better spec)
+ */
+ void RE_local_clear_render_display(short);
+
+ /**
+ * Print render statistics.
+ */
+ void RE_local_printrenderinfo(double time, int i);
+
+ /** Get the data for the scene to render. */
+ void RE_local_get_renderdata(void);
+
+ /** Release the data for the scene that was rendered. */
+ void RE_local_free_renderdata(void);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/source/blender/render/intern/include/edgeRender.h b/source/blender/render/intern/include/edgeRender.h
new file mode 100644
index 00000000000..d6e2fcb989e
--- /dev/null
+++ b/source/blender/render/intern/include/edgeRender.h
@@ -0,0 +1,63 @@
+/*
+ * edgeRender.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 EDGERENDER_H
+#define EDGERENDER_H
+/* ------------------------------------------------------------------------- */
+
+/**
+ * Add edges to <targetbuf>, which is of size <iw> by <ih>. Use <osanr>
+ * samples, and intensity <i>. <compat> indicates an extra shift in the
+ * image, for backwards compatibility with the old renderpipe. <mode>
+ * indicates which edges should be considered. The edges will be shaded
+ * to <rgb>
+ */
+void
+addEdges(
+ char * targetbuf,
+ int iw,
+ int ih,
+ int osanr,
+ short int i,
+ short int i_red,
+ int compat,
+ int mode,
+ float r,
+ float g,
+ float b
+ );
+
+/* ------------------------------------------------------------------------- */
+
+#endif /* EDGERENDER_H */
diff --git a/source/blender/render/intern/include/envmap.h b/source/blender/render/intern/include/envmap.h
new file mode 100644
index 00000000000..62640454151
--- /dev/null
+++ b/source/blender/render/intern/include/envmap.h
@@ -0,0 +1,49 @@
+/*
+ * envmap_ext.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 ENVMAP_EXT_H
+#define ENVMAP_EXT_H
+
+/* no types!!! */
+/* #include "envmap_types.h" */
+
+/**
+ * Make environment maps for all objects in the scene that have an
+ * environment map as texture.
+ * (initrender.c)
+ */
+void make_envmaps(void);
+
+#endif /* ENVMAP_EXT_H */
+
diff --git a/source/blender/render/intern/include/errorHandler.h b/source/blender/render/intern/include/errorHandler.h
new file mode 100644
index 00000000000..190cd0c9a35
--- /dev/null
+++ b/source/blender/render/intern/include/errorHandler.h
@@ -0,0 +1,69 @@
+/*
+ * errorHandler.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 ERRORHANDLER_H
+#define ERRORHANDLER_H
+
+/* ------------------------------------------------------------------------- */
+/* error codes */
+enum RE_RENDER_ERROR {
+ RE_NO_ERROR,
+ RE_DEPTH_MISMATCH, /* 1. conflict resolution detects a bad z value */
+ RE_BAD_FACE_TYPE, /* 2. a face type switch fails */
+ RE_BAD_FACE_INDEX, /* 3. tried to do an operation with a bad index */
+ RE_BAD_DATA_POINTER,
+ RE_TRACE_COUNTER,
+ RE_TOO_MANY_FACES, /* 6. overflow on z-buffer depth */
+ RE_EDGERENDER_WRITE_OUTSIDE_BUFFER, /* 7. write value outside buffer */
+ RE_CANNOT_ALLOCATE_MEMORY, /* 8. no memory for malloc */
+ RE_WRITE_OUTSIDE_COLOUR_BUFFER, /* 9. write outside colour target buffer */
+ RE_MAX_ERROR
+};
+
+/**
+ * Reset all counters for the error trace
+ */
+void RE_errortrace_reset(void);
+
+/**
+ * Signals an error to screen. Counts repetitive errors
+ */
+void RE_error(int errType, char* fname);
+
+/**
+ * Signals an error, and prints an integer argument
+ */
+void RE_error_int(int errType, char* fname, int valye);
+
+#endif /* ERRORHANDLER_H */
diff --git a/source/blender/render/intern/include/gammaCorrectionTables.h b/source/blender/render/intern/include/gammaCorrectionTables.h
new file mode 100644
index 00000000000..14c2d2d4a68
--- /dev/null
+++ b/source/blender/render/intern/include/gammaCorrectionTables.h
@@ -0,0 +1,79 @@
+/*
+ * gammacorrectiontables.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 GAMMACORRECTIONTABLES_H
+#define GAMMACORRECTIONTABLES_H
+
+
+
+/* Default gamma. For most CRTs, gamma ranges from 2.2 to 2.5 (Foley), so */
+/* 2.35 seems appropriate enough. Experience teaches a different number */
+/* though. Old blender: 2.0. It might be nice to make this a slider */
+#define RE_DEFAULT_GAMMA 2.0
+/* This 400 is sort of based on the number of intensity levels needed for */
+/* the typical dynamic range of a medium, in this case CRTs. (Foley) */
+/* (Actually, it says the number should be between 400 and 535.) */
+#define RE_GAMMA_TABLE_SIZE 400
+
+/**
+ * Initialise the gamma lookup tables
+ */
+void makeGammaTables(float gamma);
+
+/**
+ * Returns true if the table is initialised, false otherwise
+ */
+int gammaTableIsInitialised(void);
+
+/**
+ * Apply gamma correction on col
+ */
+float gammaCorrect(float col);
+
+/**
+ * Apply inverse gamma correction on col
+ */
+float invGammaCorrect(float col);
+
+/**
+ * Tell whether or not to do gamma.
+ */
+int doGamma(void);
+
+/**
+ * Set/unset performing gamma corrections.
+ */
+void setDoGamma(int);
+
+#endif
diff --git a/source/blender/render/intern/include/initrender.h b/source/blender/render/intern/include/initrender.h
new file mode 100644
index 00000000000..06c5f032c7d
--- /dev/null
+++ b/source/blender/render/intern/include/initrender.h
@@ -0,0 +1,59 @@
+/*
+ * initrender_ext.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 INITRENDER_EXT_H
+#define INITRENDER_EXT_H
+
+/* type includes */
+
+#include "DNA_effect_types.h" /* for PartEff type */
+#include "render_types.h"
+
+/* Functions */
+
+void init_def_material(void);
+void init_render_jit(int nr);
+float calc_weight(float *weight, int i, int j);
+void defaultlamp(void);
+void schrijfplaatje(char *name);
+void initparts(void);
+short setpart(short nr); /* return 0 als geen goede part */
+void addparttorect(short nr, Part *part);
+void add_to_blurbuf(int blur);
+void oldRenderLoop(void); /* Calls the old renderer. Contains the PART and FIELD loops. */
+void render(void); /* Switch between the old and the unified renderer. */
+/* void write_screendump(char *name); not here !*/
+
+#endif /* INITRENDER_EXT_H */
+
diff --git a/source/blender/render/intern/include/jitter.h b/source/blender/render/intern/include/jitter.h
new file mode 100644
index 00000000000..eff8c7bf805
--- /dev/null
+++ b/source/blender/render/intern/include/jitter.h
@@ -0,0 +1,50 @@
+/*
+ * jitter.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 JITTER_H
+#define JITTER_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern float jit[64][2];
+
+void initjit(float *jit, int num);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/source/blender/render/intern/include/old_zbuffer_types.h b/source/blender/render/intern/include/old_zbuffer_types.h
new file mode 100644
index 00000000000..7eb3159f438
--- /dev/null
+++ b/source/blender/render/intern/include/old_zbuffer_types.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 *****
+ * Datatypes for old zbuffering algorithms.
+ */
+
+#ifndef OLD_ZBUFFER_TYPES_H
+#define OLD_ZBUFFER_TYPES_H "$Id$"
+
+/* ------------------------------------------------------------------------- */
+
+typedef struct PixStr
+{
+ struct PixStr *next;
+ int vlak0, vlak;
+ unsigned int z;
+ unsigned int mask;
+ short aantal, ronde;
+} PixStr;
+
+/* ------------------------------------------------------------------------- */
+
+typedef struct PixStrMain
+{
+ struct PixStr *ps;
+ struct PixStrMain *next;
+} PixStrMain;
+
+/* ------------------------------------------------------------------------- */
+
+#endif
diff --git a/source/blender/render/intern/include/outerRenderLoop.h b/source/blender/render/intern/include/outerRenderLoop.h
new file mode 100644
index 00000000000..965516c9525
--- /dev/null
+++ b/source/blender/render/intern/include/outerRenderLoop.h
@@ -0,0 +1,43 @@
+/*
+ * outerRenderLoop.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 OUTERRENDERLOOP_H
+#define OUTERRENDERLOOP_H
+
+/**
+ * Outer loop for rendering a single picture.
+ */
+void unifiedRenderingLoop(void);
+
+#endif
diff --git a/source/blender/render/intern/include/pixelblending.h b/source/blender/render/intern/include/pixelblending.h
new file mode 100644
index 00000000000..39c439505e0
--- /dev/null
+++ b/source/blender/render/intern/include/pixelblending.h
@@ -0,0 +1,209 @@
+/*
+ * pixelblending_ext.h
+ * external interface for pixelblending
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 PIXELBLENDING_EXT_H
+#define PIXELBLENDING_EXT_H
+
+/* local includes */
+#include "vanillaRenderPipe_types.h"
+
+/* own include */
+#include "pixelblending_types.h"
+
+/**
+ * Samples pixel, depending on R.osa setting
+ */
+int addtosampcol(unsigned short *sampcol, unsigned short *shortcol, int mask);
+
+/**
+ * Samples pixel, bring your own R.osa setting
+ */
+int addToSampCol(unsigned short *sampcol, unsigned short *shortcol, int mask, int osaNr);
+
+/**
+ * Halo-add pixel, bring your own R.osa setting, and add factor
+ */
+void addAddSampColF(float *s, float *d, int m, int osa, char add);
+
+/**
+ * Alpha undersamples pixel, bring your own R.osa setting
+ */
+int addUnderSampColF(float *sampcol, float *dest, int mask, int osaNr);
+
+/**
+ * Alpha oversample pixel, bring your own R.osa setting
+ */
+void addOverSampColF(float *sampcol, float *dest, int mask, int osaNr);
+
+/**
+ * Convert a series of oversampled pixels into a single pixel.
+ * (float vecs to float vec)
+ */
+void sampleFloatColV2FloatColV(float *sample, float *dest, int osaNr);
+
+/**
+ * Convert a series of oversampled pixels into a single pixel. Uses R.osa to
+ * count the length! (short vecs to short vec)
+ */
+void sampleShortColV2ShortColV(unsigned short *sample, unsigned short *dest, int osaNr);
+
+/**
+ * Take colour <bron>, and apply it to <doel> using the alpha value of
+ * <bron>.
+ * @param doel
+ * @param bron
+ */
+void addAlphaOverShort(unsigned short *doel, unsigned short *bron);
+
+/**
+ * Take colour <bron>, and apply it to <doel> using the alpha value of
+ * <doel>.
+ * @param doel
+ * @param bron
+ */
+void addAlphaUnderShort(unsigned short *doel, unsigned short *bron);
+
+/**
+ * Alpha-over blending for floats.
+ */
+void addAlphaOverFloat(float *dest, float *source);
+
+/**
+ * Alpha-under blending for floats.
+ */
+void addAlphaUnderFloat(float *dest, float *source);
+
+/**
+ * Write a 16-bit-colour colour vector to a 8-bit-colour colour vector.
+ */
+void cpShortColV2CharColV(unsigned short *source, char *dest);
+
+/**
+ * Write a 8-bit-colour colour vector to a 16-bit-colour colour vector.
+ */
+void cpCharColV2ShortColV(char *source, unsigned short *dest);
+
+/**
+ * Write a 32-bit-colour colour vector to a 8-bit-colour colour vector.
+ */
+void cpIntColV2CharColV(unsigned int *source, char *dest);
+
+/**
+ * Write a floating-point-colour colour vector to a 8-bit-colour colour
+ * vector. Clip colours to [0, 1].
+ */
+void cpFloatColV2CharColV(float *source, char *dest);
+
+/**
+ * Cpoy a 8-bit-colour vector to floating point colour vector.
+ */
+void cpCharColV2FloatColV(char *source, float *dest);
+/**
+ * Cpoy a 16-bit-colour vector to floating point colour vector.
+ */
+void cpShortColV2FloatColV(unsigned short *source, float *dest);
+
+/**
+ * Copy a float-colour colour vector.
+ */
+void cpFloatColV(float *source, float *dest);
+
+/**
+ * Copy a 16-bit-colour colour vector.
+ */
+void cpShortColV(unsigned short *source, unsigned short *dest);
+
+/**
+ * Copy an 8-bit-colour colour vector.
+ */
+void cpCharColV(char *source, char *dest);
+
+/**
+ * Add a fraction of <source> to <dest>. Result ends up in <dest>.
+ * The internal calculation is done with floats.
+ *
+ * col(dest) = (1 - alpha(source)*(1 - addfac)) * dest + source
+ * alpha(dest) = alpha(source) + alpha (dest)
+ */
+void addalphaAddfacShort(unsigned short *dest, unsigned short *source, char addfac);
+
+/**
+ * Same for floats
+ */
+void addalphaAddfacFloat(float *dest, float *source, char addfac);
+
+/**
+ * Add two halos. Result ends up in <dest>. This should be the
+ * addition of two light sources. So far, I use normal alpha-under blending here.
+ * The internal calculation is done with floats. The add-factors have to be
+ * compensated outside this routine.
+ * col(dest) = s + (1 - alpha(s))d
+ * alpha(dest) = alpha(s) + (1 - alpha(s))alpha (d)
+ */
+void addHaloToHaloShort(unsigned short *dest, unsigned short *source);
+
+/**
+ * dest = dest + source
+ */
+void addalphaAddFloat(float *dest, float *source);
+
+/** ols functions: side effects?
+void addalphaUnderFloat(char *doel, char *bron); think this already exists...
+void addalphaUnderGammaFloat(char *doel, char *bron);
+*/
+/**
+ * Blend bron under doel, while doing gamma correction
+ */
+void addalphaUnderGammaFloat(float *doel, float *bron);
+
+/**
+ * Transform an premul-alpha 32-bit colour into a key-alpha 32-bit colour.
+ */
+void applyKeyAlphaCharCol(char* target);
+
+/* Old blending functions */
+void keyalpha(char *doel); /* maakt premul 255 */
+void addalphaUnder(char *doel, char *bron);
+void addalphaUnderGamma(char *doel, char *bron);
+void addalphaOver(char *doel, char *bron);
+void addalphaAdd(char *doel, char *bron);
+void addalphaAddshort(unsigned short *doel, unsigned short *bron);
+/* void addalphaAddfac(char *doel, char *bron, char addfac); to ext, temporarily */
+void addalphaAddfacshort(unsigned short *doel,
+ unsigned short *bron,
+ short addfac);
+
+
+#endif /* PIXELBLENDING_EXT_H */
diff --git a/source/blender/render/intern/include/pixelblending_types.h b/source/blender/render/intern/include/pixelblending_types.h
new file mode 100644
index 00000000000..71e2baa994c
--- /dev/null
+++ b/source/blender/render/intern/include/pixelblending_types.h
@@ -0,0 +1,61 @@
+/*
+ * pixelblending_types.h
+ * types pixelblending
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 PIXELBLENDING_TYPES_H
+#define PIXELBLENDING_TYPES_H
+
+/* #include "blender.h" */
+
+/* Threshold for a 'full' pixel: pixels with alpha above this level are */
+/* considered opaque This is the decimal value for 0xFFF0 / 0xFFFF */
+#define RE_FULL_COLOUR_FLOAT 0.9998
+/* Threshold for an 'empty' pixel: pixels with alpha above this level are */
+/* considered completely transparent. This is the decimal value */
+/* for 0x000F / 0xFFFF */
+#define RE_EMPTY_COLOUR_FLOAT 0.0002
+/* A 100% pixel. Sometimes, seems to be too little.... Hm....... */
+#define RE_UNITY_COLOUR_FLOAT 1.0
+/* A 0% pixel. I wonder how 0 the 0.0 is... */
+#define RE_ZERO_COLOUR_FLOAT 0.0
+
+/* threshold for alpha */
+#define RE_FULL_ALPHA_FLOAT 0.9998
+
+/* Same set of defines for shorts */
+#define RE_FULL_COLOUR_SHORT 0xFFF0
+#define RE_EMPTY_COLOUR_SHORT 0x0000
+
+#endif /* PIXELBLENDING_EXT_H */
+
diff --git a/source/blender/render/intern/include/pixelshading.h b/source/blender/render/intern/include/pixelshading.h
new file mode 100644
index 00000000000..de75e96a225
--- /dev/null
+++ b/source/blender/render/intern/include/pixelshading.h
@@ -0,0 +1,122 @@
+/*
+ * pixelshading.h
+ *
+ * These functions determine what actual colour a pixel will have.
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 PIXELSHADING_H
+#define PIXELSHADING_H
+
+/* ------------------------------------------------------------------------- */
+
+#include "render.h"
+#include "vanillaRenderPipe_types.h"
+/* ------------------------------------------------------------------------- */
+
+/**
+ * Render the pixel at (x,y) for object ap. Apply the jitter mask.
+ * Output is given in float collector[4]. The type vector:
+ * t[0] - min. distance
+ * t[1] - face/halo index
+ * t[2] - jitter mask
+ * t[3] - type ZB_POLY or ZB_HALO
+ * t[4] - max. distance
+ * @return pointer to the object
+ */
+void *renderPixel(float x, float y, int *t);
+
+/**
+ * Spothalos on otherwise empty pixels.
+ */
+void renderSpotHaloPixel(float x, float y, float* colbuf);
+
+/**
+ * Set the sky blending to the indicated type.
+ */
+void setSkyBlendingMode(enum RE_SkyAlphaBlendingType mode);
+
+/**
+ * Get the sky blending mode.
+ */
+enum RE_SkyAlphaBlendingType getSkyBlendingMode(void);
+/**
+ * Render the sky at pixel (x, y).
+ */
+void renderSkyPixelFloat(float x, float y);
+
+/* ------------------------------------------------------------------------- */
+/* All these are supposed to be internal. I should move these to a separate */
+/* header. */
+
+/**
+ * Determine colour for pixel at SCS x,y for face <vlaknr>. Result end up in
+ * <collector>
+ * @return pointer to this object's VlakRen
+ */
+void *renderFacePixel(float x, float y, int vlaknr);
+
+/**
+ * Render this pixel for halo haloNr. Leave result in <collector>.
+ * @return pointer to this object's HaloRen
+ */
+void *renderHaloPixel(float x, float y, int haloNr);
+
+/**
+ * Shade the halo at the given location
+ */
+void shadeHaloFloat(HaloRen *har, float *col, unsigned int zz,
+ float dist, float xn, float yn, short flarec);
+
+/**
+ * Shade a sky pixel on a certain line, into collector[4]
+ * The x-coordinate (y as well, actually) are communicated through
+ * R.view[3]
+ */
+void shadeSkyPixel(float x, float y);
+
+void shadeSpotHaloPixelFloat(float *col);
+void spotHaloFloat(struct LampRen *lar, float *view, float *intens);
+void shadeLampLusFloat(void);
+
+/* this should be replaced by shadeSpotHaloPixelFloat(), but there's */
+/* something completely fucked up here with the arith. */
+/* void renderspothaloFix(unsigned short *col); */
+void renderspothaloFix(float *col);
+
+/* used by shadeSkyPixel: */
+void shadeSkyPixelFloat(float y);
+void fillBackgroundImage(float x, float y);
+
+/* ------------------------------------------------------------------------- */
+
+#endif
diff --git a/source/blender/render/intern/include/renderHelp.h b/source/blender/render/intern/include/renderHelp.h
new file mode 100644
index 00000000000..7e192a5460e
--- /dev/null
+++ b/source/blender/render/intern/include/renderHelp.h
@@ -0,0 +1,63 @@
+/*
+ * renderhelp_ext.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 RENDERHELP_EXT_H
+#define RENDERHELP_EXT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ /* Push-pop, because this sometimes is necessary... */
+ void pushTempPanoPhi(float p);
+ void popTempPanoPhi(void);
+
+ float getPanoPhi(void);
+ float getPanovCo(void);
+ float getPanovSi(void);
+ void setPanoRot(int part);
+
+ /** Set clip flags on all data entries, using the given projection
+ * function */
+ void setzbufvlaggen( void (*projectfunc)(float *, float *) );
+
+/* external for the time being, since the converter calls it. */
+/** Recalculate all normals on renderdata. */
+/* void set_normalflags(void); */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/source/blender/render/intern/include/renderPreAndPost.h b/source/blender/render/intern/include/renderPreAndPost.h
new file mode 100644
index 00000000000..74438f10df7
--- /dev/null
+++ b/source/blender/render/intern/include/renderPreAndPost.h
@@ -0,0 +1,43 @@
+/*
+ * renderpreandpost.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 RENDERPREANDPOST_H
+#define RENDERPREANDPOST_H
+
+void prepareScene(void);
+void finalizeScene(void);
+void doClipping( void (*projectfunc)(float *, float *) );
+
+
+#endif
diff --git a/source/blender/render/intern/include/render_intern.h b/source/blender/render/intern/include/render_intern.h
new file mode 100644
index 00000000000..1f058821b2b
--- /dev/null
+++ b/source/blender/render/intern/include/render_intern.h
@@ -0,0 +1,60 @@
+/*
+ * render_int.h
+ * misc internal defines for renderer
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+ /* XXX, should die, no good reason to write
+ * regular (non-file related) endian dependant
+ * code.
+ */
+#if defined(__sgi) || defined(__sparc) || defined (__PPC__) || defined (__ppc__) || defined (__BIG_ENDIAN__)
+#define RCOMP 3
+#define GCOMP 2
+#define BCOMP 1
+#define ACOMP 0
+#else
+#define RCOMP 0
+#define GCOMP 1
+#define BCOMP 2
+#define ACOMP 3
+#endif
+
+#define VECCOPY(v1,v2) {*(v1)= *(v2); *(v1+1)= *(v2+1); *(v1+2)= *(v2+2);}
+#define QUATCOPY(v1,v2) {*(v1)= *(v2); *(v1+1)= *(v2+1); *(v1+2)= *(v2+2); *(v1+3)= *(v2+3);}
+
+#define CLAMPIS(a, b, c) ((a)<(b) ? (b) : (a)>(c) ? (c) : (a))
+
+typedef struct {
+ int a, b, c, d;
+} byte16;
+#define COPY_16(a,b) (*((byte16 *)(a))= *((byte16 *)(b)))
diff --git a/source/blender/render/intern/include/rendercore.h b/source/blender/render/intern/include/rendercore.h
new file mode 100644
index 00000000000..6138fbc3e3a
--- /dev/null
+++ b/source/blender/render/intern/include/rendercore.h
@@ -0,0 +1,117 @@
+/*
+ * rendercore_ext.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 RENDERCORE_H
+#define RENDERCORE_H
+#include "render_types.h"
+
+struct HaloRen;
+
+float mistfactor(float *co); /* dist en hoogte, return alpha */
+/* void sky(char *col); */
+void renderspothalo(unsigned short *col);
+void render_lighting_halo(struct HaloRen *har, float *colf);
+unsigned int calchalo_z(struct HaloRen *har, unsigned int zz);
+float CookTorr(float *n, float *l, float *v, int hard);
+void shadelamplus(void);
+/* void renderflare(struct HaloRen *har); */
+void add_halo_flare(void);
+
+/**
+ * Apply the background (sky). Depending on the active alphamode and
+ * worldmode, different filling strategies are applied.
+ * Active alphamode = R.r.alphamode
+ * Active worldmode = R.wrld.mode
+ * <LI>
+ * <IT> R_ALPHAPREMUL - do not fill sky, but apply alpha to colours
+ * <IT> R_ALPHAKEY - do not fill sky, do not apply alpha to colours
+ * <IT> R_ADDSKY - fill skycolour in the background, blend
+ * transparent colours with the background
+ * (there's also a world dependency here?
+ * <LI>
+ * <IT> R.wrld.mode == WO_MIST
+ * <IT> R.r.bufflag == 1, R.flag == R_SEC_FIELD
+ * <IT> R.wrld.skytype == ( WO_SKYBLEND ^ WO_SKYTEX)
+ * <IT> R.wrld.skytype == WO_SKYPAPER
+ * <IT> R.r.mode == R_PANORAMA )
+ * </LI>
+ * </LI>
+ * @param rect
+ * @param y
+ */
+void scanlinesky(char *rect, int y);
+
+/**
+ * Do z buffer stuff.
+ */
+void zbufshade(void);
+
+/**
+ * Insert transparent faces into the z buffer?
+ */
+void zbufshadeDA(void); /* Delta Accum Pixel Struct */
+
+/**
+ * Also called in: zbuf.c
+ */
+void shadepixel(float x, float y, int vlaknr);
+
+/**
+ * Shade the pixel at xn, yn for halo har, and write the result to col.
+ * Also called in: previewrender.c
+ * @param har The halo to be rendered on this location
+ * @param col [unsigned int 3] The destination colour vector
+ * @param zz Some kind of distance
+ * @param dist Square of the distance of this coordinate to the halo's center
+ * @param x [f] Pixel x relative to center
+ * @param y [f] Pixel y relative to center
+ * @param flarec Flare counter? Always har->flarec...
+ */
+/* void shadehalo(struct HaloRen *har, char *col, unsigned int zz, float dist, float x, float y, short flarec); */
+
+/**
+ * A cryptic but very efficient way of counting the number of bits that
+ * is set in the unsigned short.
+ */
+int count_mask(unsigned short mask);
+
+/* These defines are only used internally :) */
+/* dirty hack: pointers are negative, indices positive */
+/* pointers should be converted to positive numbers */
+
+#define IS_A_POINTER_CODE(a) ((a)<0)
+#define POINTER_FROM_CODE(a) ((void *)(-(a)))
+#define POINTER_TO_CODE(a) (-(long)(a))
+
+#endif /* RENDER_EXT_H */
diff --git a/source/blender/render/intern/include/rendercore_int.h b/source/blender/render/intern/include/rendercore_int.h
new file mode 100644
index 00000000000..8b1fd0ed759
--- /dev/null
+++ b/source/blender/render/intern/include/rendercore_int.h
@@ -0,0 +1,55 @@
+/*
+ * render_int.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 RENDER_INT_H
+#define RENDER_INT_H
+
+#include "zbuf_types.h"
+#include "render_types.h"
+
+/* float CookTorr(float *n, float *l, float *v, int hard); */
+void do_lamphalo_tex(LampRen *lar, float *p1, float *p2, float *intens);
+void spothalo(struct LampRen *lar, float *view, float *intens);
+void add_filt_mask(unsigned int mask, unsigned short *col, unsigned int *rb1, unsigned int *rb2, unsigned int *rb3);
+void addps(long *rd, int vlak, unsigned int z, short ronde);
+PixStr *addpsmain(void);
+float count_maskf(unsigned short mask);
+void freeps(void);
+void halovert(void);
+void renderhalo(HaloRen *har); /* postprocess versie */
+void scanlinehaloPS(unsigned int *rectz, long *rectdelta, unsigned int *rectt, short ys);
+
+
+#endif /* RENDER_INT_H */
+
diff --git a/source/blender/render/intern/include/shadbuf.h b/source/blender/render/intern/include/shadbuf.h
new file mode 100644
index 00000000000..6060edfed95
--- /dev/null
+++ b/source/blender/render/intern/include/shadbuf.h
@@ -0,0 +1,75 @@
+/*
+ * shadbuf_ext.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 SHADBUF_EXT_H
+#define SHADBUF_EXT_H
+
+#include "render_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Init memory for old-style shodow buffers. */
+void initshadowbuf(struct LampRen *lar, float mat[][4]);
+
+
+/**
+ * Calculates shadowbuffers for a vector of shadow-giving lamps
+ * @param lar The vector of lamps
+ */
+void makeshadowbuf(LampRen *lar);
+
+/**
+ * Determines the shadow factor for a face and lamp. There is some
+ * communication with global variables here.
+ * @returns The shadow factors: 1.0 for no shadow, 0.0 for complete
+ * shadow.
+ * @param shb The shadowbuffer to find the shadow factor in.
+ * @param inp The inproduct between viewvector and ?
+ *
+ */
+float testshadowbuf(struct ShadBuf *shb, float inp);
+
+/**
+ * Determines the shadow factor for lamp <lar>, between <p1>
+ * and <p2>. (Which CS?)
+ */
+float shadow_halo(LampRen *lar, float *p1, float *p2);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SHADBUF_EXT_H */
diff --git a/source/blender/render/intern/include/shadowBuffer.h b/source/blender/render/intern/include/shadowBuffer.h
new file mode 100644
index 00000000000..4df95c20674
--- /dev/null
+++ b/source/blender/render/intern/include/shadowBuffer.h
@@ -0,0 +1,79 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 SHADOWBUFFER_H
+#define SHADOWBUFFER_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef RE_SHADOWBUFFERHANDLE
+#define RE_SHADOWBUFFERHANDLE
+#define RE_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name
+RE_DECLARE_HANDLE(RE_ShadowBufferHandle);
+#endif
+
+ struct ShadBuf;
+ struct LampRen;
+
+/**
+ * Calculates shadowbuffers for a vector of shadow-giving lamps
+ * @param lar The vector of lamps
+ * @returns a handle to the buffer
+ */
+ extern void RE_buildShadowBuffer(RE_ShadowBufferHandle dsbh,
+ struct LampRen *lar);
+
+/**
+ * Determines the shadow factor for a face and lamp. There is some
+ * communication with global variables here? Should be made explicit...
+ * @param shadres The RGB shadow factors: 1.0 for no shadow, 0.0 for complete
+ * shadow. There must be a float[3] to write the result to.
+ * @param shb The shadowbuffer to find the shadow factor in.
+ * @param inp The inproduct between viewvector and ?
+ *
+ */
+ void RE_testshadowbuf(RE_ShadowBufferHandle dsbh,
+ struct ShadBuf* shbp,
+ float inp,
+ float* shadres);
+
+/**
+ * Determines a shadow factor for halo-shadows.
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SHADOWBUFFER_H */
diff --git a/source/blender/render/intern/include/texture.h b/source/blender/render/intern/include/texture.h
new file mode 100644
index 00000000000..9d033ac26dd
--- /dev/null
+++ b/source/blender/render/intern/include/texture.h
@@ -0,0 +1,86 @@
+/*
+ * texture_ext.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 TEXTURE_EXT_H
+#define TEXTURE_EXT_H "$Id$"
+#define TEXTURE_EXT_H "Copyright (C) 2001 NaN Technologies B.V.
+
+/* no types!!! */
+/* #include "texture_types.h" */
+
+struct Tex;
+struct MTex;
+struct HaloRen;
+struct LampRen;
+/**
+ * Takes uv coordinates (R.uv[], O.dxuv, O.dyuv), find texture colour
+ * at that spot (using imagewrap()).
+ * Result is kept in R.vcol (float vector 3)
+ */
+void render_realtime_texture(void);
+
+/**
+ * Do texture mapping for materials. Communicates with R.... variables.
+ */
+void do_material_tex(void);
+
+/* unsorted */
+int blend(struct Tex *tex, float *texvec);
+int clouds(struct Tex *tex, float *texvec);
+int cubemap(struct MTex *mtex, float x, float y, float z, float *adr1, float *adr2);
+int cubemap_glob(struct MTex *mtex, float x, float y, float z, float *adr1, float *adr2);
+int cubemap_ob(struct MTex *mtex, float x, float y, float z, float *adr1, float *adr2);
+void do_2d_mapping(struct MTex *mtex, float *t, float *dxt, float *dyt);
+void do_halo_tex(struct HaloRen *har, float xn, float yn, float *colf);
+void do_lamp_tex(struct LampRen *la, float *lavec);
+void do_sky_tex(void);
+int magic(struct Tex *tex, float *texvec);
+int marble(struct Tex *tex, float *texvec);
+int multitex(struct Tex *tex, float *texvec, float *dxt, float *dyt);
+int plugintex(struct Tex *tex, float *texvec, float *dxt, float *dyt);
+int stucci(struct Tex *tex, float *texvec);
+int texnoise(struct Tex *tex);
+int wood(struct Tex *tex, float *texvec);
+
+#endif /* TEXTURE_EXT_H */
+
+
+
+
+
+
+
+
+
+
diff --git a/source/blender/render/intern/include/vanillaRenderPipe.h b/source/blender/render/intern/include/vanillaRenderPipe.h
new file mode 100644
index 00000000000..4dfaa41e91d
--- /dev/null
+++ b/source/blender/render/intern/include/vanillaRenderPipe.h
@@ -0,0 +1,49 @@
+/*
+ * vanillaRenderPipe_ext.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 VANILLARENDERPIPE_EXT_H
+#define VANILLARENDERPIPE_EXT_H
+
+#include "vanillaRenderPipe_types.h"
+
+/**
+ * Render pipeline with all kinds of extras.
+ * status-------------------------\/
+ * - integrated z buffering ok
+ * - integrated halo rendering ok
+ */
+void zBufShadeAdvanced(void);
+
+
+#endif /* VANILLARENDERPIPE_EXT_H */
diff --git a/source/blender/render/intern/include/vanillaRenderPipe_int.h b/source/blender/render/intern/include/vanillaRenderPipe_int.h
new file mode 100644
index 00000000000..024b82cc812
--- /dev/null
+++ b/source/blender/render/intern/include/vanillaRenderPipe_int.h
@@ -0,0 +1,191 @@
+/*
+ * vanillaRenderPipe_int.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 VANILLARENDERPIPE_INT_H
+#define VANILLARENDERPIPE_INT_H
+
+#include "vanillaRenderPipe_types.h"
+#include "zbufferdatastruct_types.h"
+
+/**
+ * Z buffer initializer, for new pipeline.
+ * <LI>
+ * <IT> AColourBuffer : colour buffer for one line
+ * <IT> APixbufExt : pixel data buffer for one line, depth RE_ZBUFLEN
+ * </LI>
+ */
+void initRenderBuffers(int width);
+/* void initRenderBuffers(void); */
+
+/**
+ * Z buffer destructor, frees stuff from initZBuffers().
+ */
+void freeRenderBuffers(void);
+
+/**
+ * Fill the accumulation buffer APixbufExt with face and halo indices.
+ * Note: Uses globals.
+ * @param y the line number to set
+ */
+void calcZBufLine(int y);
+
+/**
+ * Shade and render the pixels in this line, into AColourBuffer
+ * Note: Uses globals.
+ * @param y the line number to set
+ */
+void renderZBufLine(int y);
+
+/**
+ * Count and sort the list behind ap into buf. Sorts on min. distance.
+ * Low index <=> high z
+ */
+int countAndSortPixelFaces(int buf[RE_MAX_FACES_PER_PIXEL][5],
+ RE_APixstrExt *ap);
+
+/**
+ * Compose the conflict and colour stacks
+ * Note: Uses globals.
+ */
+int composeStack(int zrow[RE_MAX_FACES_PER_PIXEL][RE_PIXELFIELDSIZE],
+ struct RE_faceField* stack, int ptr,
+ int totvlak, float x, float y, int osaNr);
+/**
+ * Integrate conflicting layers.
+ * Note: Uses globals.
+ */
+int resolveConflict(struct RE_faceField* stack, int ptr, float x, float y);
+
+/**
+ * Integrate the colour stack, defer conflicts.
+ * Note: Uses globals.
+ */
+void integrateStack(struct RE_faceField* stack, int ptr,
+ float x, float y, int osaNr);
+
+/**
+ * Calculate the view depth to this object on this location, with
+ * the current view parameters in R.
+ */
+int calcDepth(float x, float y, void *data, int type);
+
+
+
+/**
+ * Fills in distances of all faces in a z buffer, for given jitter settings.
+ */
+int fillZBufDistances(void);
+
+/**
+ * Fills in distances of faces in the z buffer.
+ *
+ * Halo z buffering ----------------------------------------------
+ *
+ * A halo is treated here as a billboard: no z-extension, always
+ * oriented perpendicular to the viewer. The rest of the z-buffer
+ * stores face-numbers first, then calculates colours as the
+ * final image is rendered. We'll use the same approach here,
+ * which differs from the original method (which was add halos per
+ * scan line). This means that the z-buffer now also needs to
+ * store info about what sort of 'thing' the index refers to.
+ *
+ * Halo extension:
+ * h.maxy ---------
+ * | h.xs + h.rad
+ * | h.xs
+ * | h.xs - h.rad
+ * h.miny ---------
+ *
+ * These coordinates must be clipped to picture size.
+ * I'm not quite certain about halo numbering.
+ *
+ * Halos and jittering -------------------------------------------
+ *
+ * Halos were not jittered previously. Now they are. I wonder
+ * whether this may have some adverse effects here.
+
+ * @return 1 for succes, 0 if the operation was interrupted.
+ */
+int zBufferAllFaces(void);
+
+/**
+ * Fills in distances of halos in the z buffer.
+ * @return 1 for succes, 0 if the operation was interrupted.
+ */
+int zBufferAllHalos(void);
+
+/**
+ * New fill function for z buffer, for edge-only rendering.
+ */
+void zBufferFillEdge(float *vec1, float *vec2);
+
+/**
+ * New fill function for z buffer.
+ */
+void zBufferFillFace(float *v1, float *v2, float *v3);
+
+/**
+ * One more filler: fill in halo data in z buffer.
+ * Empty so far, but may receive content of halo loop.
+ */
+void zBufferFillHalo(void);
+
+/**
+ * Copy the colour buffer output to R.rectot, to line y.
+ */
+void transferColourBufferToOutput(int y);
+
+/**
+ * Set the colour buffer fields to zero.
+ */
+void eraseColBuf(RE_COLBUFTYPE *buf);
+
+/**
+ * Blend source over dest, and leave result in dest. 1 pixel.
+ */
+void blendOverFloat(int type, float* dest, float* source, void* data);
+
+/**
+ * Blend source over dest, and leave result in dest. 1 pixel into
+ * multiple bins.
+ */
+void blendOverFloatRow(int type, float* dest, float* source,
+ void* data, int mask, int osaNr) ;
+
+/**
+ * Do a post-process step on a finalized render image.
+ */
+void std_transFloatColV2CharColV( RE_COLBUFTYPE *buf, char *target);
+
+#endif /* VANILLARENDERPIPE_INT_H */
diff --git a/source/blender/render/intern/include/vanillaRenderPipe_types.h b/source/blender/render/intern/include/vanillaRenderPipe_types.h
new file mode 100644
index 00000000000..90828ff62c3
--- /dev/null
+++ b/source/blender/render/intern/include/vanillaRenderPipe_types.h
@@ -0,0 +1,90 @@
+/*
+ * vanillaRenderPipe_types.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 VANILLARENDERPIPE_TYPES_H
+#define VANILLARENDERPIPE_TYPES_H
+
+/* Render defines */
+#define RE_MAX_OSA_COUNT 16 /* The max. number of possible oversamples */
+#define RE_MAX_FACES_PER_PIXEL 500 /* max. nr of faces rendered behind one */
+ /* pixel */
+
+enum RE_SkyAlphaBlendingType {
+ RE_ALPHA_NODEF = 0,
+ RE_ALPHA_PREMUL,
+ RE_ALPHA_KEY,
+ RE_ALPHA_SKY,
+ RE_ALPHA_MAX
+};
+
+
+/* Render typedefs */
+typedef float RE_COLBUFTYPE; /* datatype for the colour buffer */
+
+
+/**
+ * Threshold for add-blending for faces
+ */
+#define RE_FACE_ADD_THRESHOLD 0.001
+
+/**
+ For oversampling
+
+ New stack: the old stack limits our freedom to do all kinds of
+ manipulation, so we rewrite it.
+
+ A stacked face needs:
+ - a face type
+ - a colour
+ - a conflict count
+ - a data pointer (void*)
+ - a mask
+
+ The stack starts at index 0, with the closest face, and stacks up.
+
+*/
+
+struct RE_faceField {
+ int faceType;
+ float colour[4];
+ int conflictCount;
+ void *data;
+ int mask;
+};
+
+
+
+#endif /* VANILLARENDERPIPE_TYPES_H */
+
+
diff --git a/source/blender/render/intern/include/zbuf.h b/source/blender/render/intern/include/zbuf.h
new file mode 100644
index 00000000000..fdfa5b19abe
--- /dev/null
+++ b/source/blender/render/intern/include/zbuf.h
@@ -0,0 +1,180 @@
+/*
+ * zbuf_ext.h
+ * external interface for zbuf.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 ZBUF_H
+#define ZBUF_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct LampRen;
+struct VlakRen;
+
+/*-----------------------------------------------------------*/
+/* Includes */
+/*-----------------------------------------------------------*/
+
+#include "zbuf_types.h"
+#include "render_types.h"
+#include "radio_types.h" /* for RadView */
+
+/*-----------------------------------------------------------*/
+/* Function */
+/* (11 so far ) */
+/*-----------------------------------------------------------*/
+
+/**
+ * Fill a 'rectangle' with a fixed value. The rectangle contains x by
+ * y points. The rows are assumed to be contiguous in memory, and to
+ * consist of uints. This function is used for initializing the z
+ * buffer.
+ * (why is x int and y uint? called in envmap, render, zbuf)
+ * @param rect Pointer to the data representing the rectangle.
+ * @param x The width of the rectangle
+ * @param y The height of the rectangle
+ * @param val The value used to fill the rectangle.
+ */
+void fillrect(unsigned int *rect, int x, unsigned int y, unsigned int val);
+
+/**
+ * Converts a world coordinate into a homogenous coordinate in view
+ * coordinates. The transformation matrix is only allowed to have a
+ * scaling and translation component.
+ * Also called in: shadbuf.c render.c radfactors.c
+ * initrender.c envmap.c editmesh.c
+ * @param v1 [3 floats] the world coordinate
+ * @param adr [4 floats] the homogenous view coordinate
+ */
+void projectvert(float *v1,float *adr);
+
+
+/**
+ * Do a z buffer calculation pass for shadow calculations.
+ * Also called in: shadbuf.c
+ * Note: Uses globals.
+ * @param lar lamp definition data
+ */
+void zbuffershad(struct LampRen *lar);
+
+ /* to the external interface, temp, I hope... */
+/**
+ * Tests whether the first three coordinates should be clipped
+ * wrt. the fourth component. Bits 1 and 2 test on x, 3 and 4 test on
+ * y, 5 and 6 test on z:
+ * xyz > test => set first bit (01),
+ * xyz < -test => set second bit (10),
+ * xyz == test => reset both bits (00).
+ * Note: functionality is duplicated from an internal function
+ * Also called in: initrender.c, radfactors.c
+ * @param v [4 floats] a coordinate
+ * @return a vector of bitfields
+ */
+/* int testclip(float *v); */
+
+
+/* The following are only used in zbuf.c and render.c ---------------*/
+/**
+ * Fills the entire in the alpha DA buffer. (All of it!)
+ * Note: Uses globals.
+ * Also called in: render.c
+ * @param y the line number to set
+ */
+void abufsetrow(int y);
+
+
+/**
+ * Calculate the z buffer for all faces (or edges when in wireframe
+ * mode) presently visible.
+ * Note: Uses globals.
+ * Also called in: render.c
+ */
+void zbufferall(void);
+
+
+/**
+ * Initialize accumulation buffers for alpha z buffering.
+ * The buffers are global variables. Also resets Accu buffer
+ * y bounds.
+ * <LI>
+ * <IT> Acolrow : colour buffer for one line
+ * <IT> Arectz : distance buffer for one line, depth ABUFPART
+ * <IT> APixbuf : pixel data buffer for one line, depth ABUFPART
+ * </LI>
+ * Also called in: render.c (should migrate)
+ * Note: Uses globals.
+ */
+void bgnaccumbuf(void);
+
+/**
+ * Discard accumulation buffers for alpha z buffering.
+ * The buffers are global variables. The released buffers are Acolrow,
+ * Arectz, APixBuf.
+ * Also called in: render.c (should migrate)
+ * Note: Uses globals.
+ */
+void endaccumbuf(void);
+
+/**
+ * Z face intersect?
+ */
+int vergzvlak(const void *x1, const void *x2);
+
+/**
+ * Clip and fill vertex into the z buffer. zbuffunc needs to be set
+ * before entering, to assure that there is a buffer fill function
+ * that can be called. Zvlnr must be set to the current valid face
+ * index .
+ * Note: uses globals
+ * @param f1 [4 floats] vertex 1
+ * @param f2 [4 floats] vertex 2
+ * @param f3 [4 floats] vertex 3
+ * @param c1 clip conditions?
+ * @param c2
+ * @param c3
+ */
+void zbufclip(float *f1, float *f2, float *f3, int c1, int c2, int c3);
+
+/**
+ * same, for edges
+ */
+void zbufclipwire(struct VlakRen *vlr);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/source/blender/render/intern/include/zbuf_int.h b/source/blender/render/intern/include/zbuf_int.h
new file mode 100644
index 00000000000..1ea416a581f
--- /dev/null
+++ b/source/blender/render/intern/include/zbuf_int.h
@@ -0,0 +1,203 @@
+/*
+ * zbuf_int.h
+ * internal interface for zbuf.h (ie. functions that are not used
+ * anywhere else)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 ZBUF_INT_H
+#define ZBUF_INT_H
+
+#include "render_types.h"
+#include "zbuf_types.h"
+
+
+
+/**
+ * Convert a homogenous coordinate to a z buffer coordinate. The
+ * function makes use of Zmulx, Zmuly, the x and y scale factors for
+ * the screen, and Zjitx, Zjity, the pixel offset. (These are declared
+ * in render.c) The normalised z coordinate must fall on [0, 1].
+ * @param zco [3, 4 floats] pointer to the resulting z buffer coordinate
+ * @param hoco [4 floats] pointer to the homogenous coordinate of the
+ * vertex in world space.
+ */
+void hoco_to_zco(float *zco, float *hoco);
+
+/**
+ * Fill the z buffer for alpha?
+ *
+ * This is one of the z buffer fill functions called in zbufclip() and
+ * zbufwireclip().
+ *
+ * @param v1 [4 floats, world coordinates] first vertex
+ * @param v2 [4 floats, world coordinates] second vertex
+ * @param v3 [4 floats, world coordinates] third vertex
+ */
+void zbufinvulAc(float *v1, float *v2, float *v3);
+
+/**
+ * Fill the z buffer, but invert z order, and add the face index to
+ * the corresponing face buffer.
+ *
+ * This is one of the z buffer fill functions called in zbufclip() and
+ * zbufwireclip().
+ *
+ * @param v1 [4 floats, world coordinates] first vertex
+ * @param v2 [4 floats, world coordinates] second vertex
+ * @param v3 [4 floats, world coordinates] third vertex
+ */
+void zbufinvulGLinv(float *v1, float *v2, float *v3);
+
+/**
+ * Fill the z buffer, and add the face index to
+ * the corresponing face buffer. Writes into R.rectz and R.rectot. It
+ * assumes that Zvlnr is set to the face index of the face under
+ * consideration. Zvlnr is written into R.rectot. R.rectz
+ *
+ * This is one of the z buffer fill functions called in zbufclip() and
+ * zbufwireclip().
+ *
+ * @param v1 [4 floats, world coordinates] first vertex
+ * @param v2 [4 floats, world coordinates] second vertex
+ * @param v3 [4 floats, world coordinates] third vertex
+ */
+void zbufinvulGL(float *v1, float *v2, float *v3);
+
+/**
+ * Fill the z buffer. The face buffer is not operated on!
+ *
+ * This is one of the z buffer fill functions called in zbufclip() and
+ * zbufwireclip().
+ *
+ * @param v1 [4 floats, world coordinates] first vertex
+ * @param v2 [4 floats, world coordinates] second vertex
+ * @param v3 [4 floats, world coordinates] third vertex
+ */
+void zbufinvulGL_onlyZ(float *v1, float *v2, float *v3);
+
+/**
+ * Prints 3 unlabelled floating point values to stdout. Used for diagnostics.
+ * @param v1 any float
+ * @param v2 any float
+ * @param v3 any float
+ */
+void print3floats(float *v1, float *v2, float *v3);
+
+/**
+ * Checks labda and uses this to make decision about clipping the line
+ * segment from v1 to v2. labda is the factor by which the vector is
+ * cut. ( calculate s + l * ( t - s )). The result is appended to the
+ * vertex list of this face.
+ * Note: uses globals.
+ * (arguments: one int, one pointer to int... why?)
+ * @param v1 start coordinate s
+ * @param v2 target coordinate t
+ * @param b1
+ * @param b2
+ * @param clve vertex vector.
+ */
+static void maakvertpira(float *v1, float *v2, int *b1, int b2, int *clve);
+
+/**
+ * Sets labda: flag, and parametrize the clipping of vertices in
+ * viewspace coordinates. labda = -1 means no clipping, labda in [0,
+ * 1] means a clipping.
+ * Note: uses globals.
+ * @param v1 start coordinate s
+ * @param v2 target coordinate t
+ * @param b1
+ * @param b2
+ * @param b3
+ * @param a index for coordinate (x, y, or z)
+ */
+static void clipp(float *v1, float *v2, int b1, int *b2, int *b3, int a);
+
+/**
+ * Tests whether this coordinate is 'inside' or 'outside' of the view
+ * volume? By definition, this is in [0, 1].
+ * @param p vertex z difference plus coordinate difference?
+ * @param q origin z plus r minus some coordinate?
+ * @param u1 [in/out] clip fraction for ?
+ * @param u2 [in/out]
+ * @return 0 if point is outside, or 1 if the point lies on the clip
+ * boundary
+ */
+static short cliptestf(float p, float q, float *u1, float *u2);
+
+
+/* not documented yet */
+/* not sure if these should stay static... */
+
+static int clipline(float *v1, float *v2);
+
+/**
+ * Provide book-keeping for the z buffer data lists.
+ */
+APixstr *addpsmainA(void);
+void freepsA(void);
+APixstr *addpsA(void);
+
+/**
+ * Fill function for the z buffer (fills lines)
+ */
+void zbuflineAc(float *vec1, float *vec2);
+void zbufline(float *vec1, float *vec2);
+
+
+/**
+ * Copy results from the solid face z buffering to the transparent
+ * buffer.
+ */
+void copyto_abufz(int sample);
+
+/**
+ * Do accumulation z buffering.
+ */
+void zbuffer_abuf(void);
+
+/**
+ * Shade this face at this location in SCS.
+ */
+void shadetrapixel(float x, float y, int vlak);
+
+/**
+ * Determine the distance to the camera of this halo, in ZCS.
+ */
+unsigned int calcHaloDist(HaloRen *har);
+
+#endif /* ZBUF_INT_H */
+
+
+
+
+
diff --git a/source/blender/render/intern/include/zbuf_types.h b/source/blender/render/intern/include/zbuf_types.h
new file mode 100644
index 00000000000..49960541fa0
--- /dev/null
+++ b/source/blender/render/intern/include/zbuf_types.h
@@ -0,0 +1,78 @@
+/*
+ * zbuf_types.h
+ * type definitions used (and maybe exported) by zbuf.c.
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 ZBUF_TYPES_H
+#define ZBUF_TYPES_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ABUFPART 64
+
+/**
+ * Primitive data structure for zbuffering. One struct
+ * stores data for 4 entries.
+ */
+typedef struct APixstr {
+ unsigned short mask[4]; /* jitter mask */
+ int z[4]; /* distance */
+ int p[4]; /* index */
+ struct APixstr *next;
+} APixstr;
+
+
+typedef struct APixstrMain
+{
+ struct APixstr *ps;
+ struct APixstrMain *next;
+} APixstrMain;
+
+
+typedef struct {
+ float *vert;
+ float hoco[4];
+ int clip;
+} VertBucket;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZBUF_TYPES_H */
+
+
+
+
diff --git a/source/blender/render/intern/include/zbufferdatastruct.h b/source/blender/render/intern/include/zbufferdatastruct.h
new file mode 100644
index 00000000000..3e36066100c
--- /dev/null
+++ b/source/blender/render/intern/include/zbufferdatastruct.h
@@ -0,0 +1,99 @@
+/*
+ * zbufferdatastruct_ext.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 ZBUFFERDATASTRUCT_EXT_H
+#define ZBUFFERDATASTRUCT_EXT_H
+
+#include "zbufferdatastruct_types.h"
+
+/**
+ * Set memory and counters for a fresh z buffer
+ */
+void initZbuffer(int linewidth);
+
+/**
+ * Release memory for the current z buffer
+ */
+void freeZbuffer(void);
+
+/**
+ * Release previous buffer and initialise new buffer.
+ */
+void resetZbuffer(void);
+
+/**
+ * Make a root for a memory block (internal)
+ */
+RE_APixstrExt *addpsemainA(void);
+
+/**
+ * Release a memory chunk
+ */
+void freepseA(void);
+
+/**
+ * Add a structure
+ */
+RE_APixstrExt *addpseA(void);
+
+/**
+ * Add an object to a zbuffer entry.
+ */
+void insertObject(int teller,
+/* int opaque, */
+ int obindex,
+ int obtype,
+ int dist,
+ int mask);
+
+/**
+ * Add a flat object to a zbuffer entry.
+ */
+void insertFlatObject(RE_APixstrExt* ap,
+ int obindex,
+ int obtype,
+ int dist,
+ int mask);
+
+/**
+ * Add a flat object to a zbuffer entry, but don't do OSA entry testing.
+ */
+void insertFlatObjectNoOsa(RE_APixstrExt* ap,
+ int obindex,
+ int obtype,
+ int dist,
+ int mask);
+
+
+#endif
diff --git a/source/blender/render/intern/include/zbufferdatastruct_types.h b/source/blender/render/intern/include/zbufferdatastruct_types.h
new file mode 100644
index 00000000000..10e0db8a540
--- /dev/null
+++ b/source/blender/render/intern/include/zbufferdatastruct_types.h
@@ -0,0 +1,77 @@
+/*
+ * zbufferdatastruct_types.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 ZBUFFERDATASTRUCT_TYPES_H
+#define ZBUFFERDATASTRUCT_TYPES_H
+
+#define RE_ZBUFLEN 64 /* number of lines in the accumulation buffer */
+
+/**
+ * Primitive data structure for zbuffering. One struct
+ * stores data for 4 entries. This struct has been extended
+ * for the render pipeline overhaul.
+ */
+typedef struct RE_APixstrExt {
+ unsigned short mask[4]; /* jitter masks */
+ int zmin[4]; /* min. distance of all samples */
+ int zmax[4]; /* max. distance of all samples */
+ int p[4]; /* index */
+ int t[4]; /* entry type: ZB_POLY or ZB_HALO */
+ struct RE_APixstrExt *next;
+} RE_APixstrExt;
+
+/* For now I'll stick to the Blender convention of hand made defines */
+/* but this should definitely be done in a better way. An enum may */
+/* be some help, but masking is still a nice feature... */
+/* object types to buffer in the z buffer */
+#define RE_NONE 0
+#define RE_POLY 1
+#define RE_HALO 2
+#define RE_SKY 4
+
+/* unique indices for each field */
+#define RE_ZMIN 0
+#define RE_INDEX 1
+#define RE_MASK 2
+#define RE_TYPE 3
+#define RE_ZMAX 4
+#define RE_PIXELFIELDSIZE 5
+
+typedef struct RE_APixstrExtMain
+{
+ struct RE_APixstrExt *ps;
+ struct RE_APixstrExtMain *next;
+} RE_APixstrExtMain;
+
+#endif
diff --git a/source/blender/render/intern/source/Makefile b/source/blender/render/intern/source/Makefile
new file mode 100644
index 00000000000..5e3d1b095ad
--- /dev/null
+++ b/source/blender/render/intern/source/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 *****
+#
+#
+
+LIBNAME = render
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+ifeq ($(OS),$(findstring $(OS), "beos darwin freebsd linux openbsd solaris windows"))
+ CFLAGS += -funsigned-char
+ CCFLAGS += -funsigned-char
+endif
+
+CFLAGS += $(LEVEL_2_C_WARNINGS)
+
+# first /include is my own includes, second is the external interface.
+# The external modules follow after. There should be a nicer way to say this.
+CPPFLAGS += -I../include
+CPPFLAGS += -I../../extern/include
+CPPFLAGS += -I../../../radiosity/extern/include
+CPPFLAGS += -I../../../misc
+CPPFLAGS += -I../../../blenlib
+CPPFLAGS += -I../../../imbuf
+CPPFLAGS += -I../../../makesdna
+CPPFLAGS += -I../../../blenkernel
+CPPFLAGS += -I../../../../kernel/gen_messaging
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+# not very neat: the rest of blender..
+CPPFLAGS += -I../../../include
+
diff --git a/source/blender/render/intern/source/RE_DummyShadowBuffer.cpp b/source/blender/render/intern/source/RE_DummyShadowBuffer.cpp
new file mode 100644
index 00000000000..e2adefc05f2
--- /dev/null
+++ b/source/blender/render/intern/source/RE_DummyShadowBuffer.cpp
@@ -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 *****
+ */
+
+// #include <iostream.h>
+
+#include "render_intern.h"
+
+#include "RE_DummyShadowBuffer.h"
+struct LampRen;
+
+RE_DummyShadowBuffer::RE_DummyShadowBuffer(void)
+{
+ /* empty for now */
+// cout << "Constructing dummy SB\n";
+}
+
+RE_DummyShadowBuffer::~RE_DummyShadowBuffer(void)
+{
+ /* empty for now */
+// cout << "Deconstructing dummy SB\n";
+}
+
+void RE_DummyShadowBuffer::importScene(struct LampRen* lar)
+{
+ /* empty for now */
+// cout << "Importing scene in dummy SB\n";
+}
+
+void RE_DummyShadowBuffer::readShadowValue(struct ShadBuf *shb,
+ float inp,
+ float* shadowResult)
+{
+ /* a sort of puple-ish colour */
+ shadowResult[0] = 1.0;
+ shadowResult[1] = 0.0;
+ shadowResult[2] = 0.5;
+}
diff --git a/source/blender/render/intern/source/RE_basicShadowBuffer.cpp b/source/blender/render/intern/source/RE_basicShadowBuffer.cpp
new file mode 100644
index 00000000000..e126a755c35
--- /dev/null
+++ b/source/blender/render/intern/source/RE_basicShadowBuffer.cpp
@@ -0,0 +1,734 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 <string.h>
+
+//#include <iostream.h>
+#include "MEM_guardedalloc.h"
+#include "BLI_arithb.h"
+
+#include "DNA_lamp_types.h"
+/* c stuff */
+#include "MTC_matrixops.h"
+#include "render.h"
+#include "render_intern.h"
+#include "renderHelp.h"
+#include "jitter.h"
+#include "zbuf.h"
+#include "shadbuf.h"
+
+/* own include */
+#include "RE_basicShadowBuffer.h"
+/* crud */
+#define MIN2(x,y) ( (x)<(y) ? (x) : (y) )
+/* ------------------------------------------------------------------------- */
+/* The implementation of this one is a bit of a fraud still, as it
+ * still relies on everything internally to be done in C. Memory is
+ * allocated on the fly, and deallocated elsewhere... There's not much
+ * more than a handle for the implementation here. This is an exact
+ * copy of the old code, retrofitted for integration in the unified
+ * renderer.
+ *
+ * - the shadow values are tripled to make a shadow vector out of a
+ * single shadow value
+ */
+
+RE_BasicShadowBuffer::RE_BasicShadowBuffer(struct LampRen *lar, float mat[][4])
+{
+// cout << "Constructing basic SB\n";
+ bias = 0x00500000;
+ initshadowbuf(lar, mat); /* a ref to the shb is stored in the lar */
+}
+
+RE_BasicShadowBuffer::~RE_BasicShadowBuffer(void)
+{
+ /* clean-up is done when the lar's are deleted */
+// cout << "Destroying basic SB\n";
+}
+
+void RE_BasicShadowBuffer::lrectreadRectz(int x1, int y1,
+ int x2, int y2,
+ char *r1) /* leest deel uit rectz in r1 */
+{
+ unsigned int len4, *rz;
+
+ if(x1>=R.rectx || x2>=R.rectx || y1>=R.recty || y2>=R.recty) return;
+ if(x1>x2 || y1>y2) return;
+
+ len4= 4*(x2- x1+1);
+ rz= R.rectz+R.rectx*y1+x1;
+ for(;y1<=y2;y1++) {
+ memcpy(r1,rz,len4);
+ rz+= R.rectx;
+ r1+= len4;
+ }
+}
+
+
+int RE_BasicShadowBuffer::sizeoflampbuf(struct ShadBuf *shb)
+{
+ int num,count=0;
+ char *cp;
+
+ cp= shb->cbuf;
+ num= (shb->size*shb->size)/256;
+
+ while(num--) count+= *(cp++);
+
+ return 256*count;
+}
+
+float* RE_BasicShadowBuffer::give_jitter_tab(int samp)
+{
+ /* these are all possible jitter tables, takes up some
+ * 12k, not really bad!
+ * For soft shadows, it saves memory and render time
+ */
+ static int tab[17]={1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256};
+ static float jit[1496][2];
+ static char ctab[17]= {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ int a, offset=0;
+
+ if(samp<2) samp= 2;
+ else if(samp>16) samp= 16;
+
+ for(a=0; a<samp-1; a++) offset+= tab[a];
+
+ if(ctab[samp]==0) {
+ initjit(jit[offset], samp*samp);
+ ctab[samp]= 1;
+ }
+
+ return jit[offset];
+
+}
+
+void RE_BasicShadowBuffer::importScene(LampRen *lar)
+{
+ struct ShadBuf *shb= lar->shb;
+ float panophi;
+ float temp, wsize, dist;
+ int *rz, *rz1, verg, verg1;
+ unsigned long *ztile;
+ int a, x, y, minx, miny, byt1, byt2;
+ short temprx,tempry, square;
+ char *rc, *rcline, *ctile, *zt;
+
+ panophi = getPanoPhi();
+
+ /* viewvars onthouden */
+ temprx= R.rectx; tempry= R.recty;
+ R.rectx= R.recty= shb->size;
+
+ shb->jit= give_jitter_tab(shb->samp);
+
+ /* matrices en window: in R.winmat komt transformatie
+ van obsview naar lampview, inclusief lampwinmat */
+
+ wsize= shb->pixsize*(shb->size/2.0);
+
+ i_window(-wsize, wsize, -wsize, wsize, shb->d, shb->far, shb->winmat);
+
+ MTC_Mat4MulMat4(shb->persmat, shb->viewmat, shb->winmat);
+
+ /* temp, will be restored */
+ MTC_Mat4SwapMat4(shb->persmat, R.winmat);
+
+ /* zbufferen */
+ if(R.rectz) MEM_freeN(R.rectz);
+ R.rectz= (unsigned int *)MEM_mallocN(sizeof(int)*shb->size*shb->size,"makeshadbuf");
+ rcline= (char*) MEM_mallocN(256*4+sizeof(int),"makeshadbuf2");
+
+ /* onthouden: panorama rot */
+ temp= panophi;
+ panophi= 0.0;
+ pushTempPanoPhi(0.0);
+
+ /* pano interference here? */
+ setzbufvlaggen(projectvert);
+
+ popTempPanoPhi();
+ panophi= temp;
+
+ zbuffershad(lar);
+
+ /* alle pixels 1 x ingevuld verwijderen (oneven) */
+ /* probleem hierbij kan geven dat er abrupte overgangen van zacht gebied
+ * naar geen zacht gebied is: bijv als eronder een klein vlakje zit
+ * DAAROM ER WEER UIT
+ * ook vanwege shadowhalo!
+ *
+ a= shb->size*shb->size;
+ rz= R.rectz;
+ while(a--) {
+ if(*rz & 1) *rz= 0x7FFFFFFF;
+ rz++;
+ }
+ */
+
+ square= lar->mode & LA_SQUARE;
+
+ /* Z tiles aanmaken: dit systeem is 24 bits!!! */
+
+ ztile= shb->zbuf;
+ ctile= shb->cbuf;
+ for(y=0; y<shb->size; y+=16) {
+ if(y< shb->size/2) miny= y+15-shb->size/2;
+ else miny= y-shb->size/2;
+
+ for(x=0; x<shb->size; x+=16) {
+
+ /* ligt rechthoek binnen spotbundel? */
+ a= shb->size/2;
+ if(x< a) minx= x+15-a;
+ else minx= x-a;
+
+ dist= sqrt( (float)(minx*minx+miny*miny) );
+
+ if(square==0 && dist>(float)(a+12)) { /* 12, tested with a onlyshadow lamp */
+ a= 256; verg= 0; /* 0x80000000; */ /* 0x7FFFFFFF; */
+ rz1= (&verg)+1;
+ }
+ else {
+ lrectreadRectz(x, y, MIN2(shb->size-1,x+15), MIN2(shb->size-1,y+15), rcline);
+ rz1= (int *)rcline;
+
+ verg= (*rz1 & 0xFFFFFF00);
+
+ for(a=0;a<256;a++,rz1++) {
+ if( (*rz1 & 0xFFFFFF00) != verg) break;
+ }
+ }
+ if(a==256) { /* compleet leeg vakje */
+ *ctile= 0;
+ *ztile= *(rz1-1);
+ }
+ else {
+
+ /* ACOMP enz. zijn defined L/B endian */
+
+ rc= rcline;
+ rz1= (int *)rcline;
+ verg= rc[ACOMP];
+ verg1= rc[BCOMP];
+ rc+= 4;
+ byt1= 1; byt2= 1;
+ for(a=1;a<256;a++,rc+=4) {
+ byt1 &= (verg==rc[ACOMP]);
+ byt2 &= (verg1==rc[BCOMP]);
+
+ if(byt1==0) break;
+ }
+ if(byt1 && byt2) { /* alleen byte opslaan */
+ *ctile= 1;
+ *ztile= (unsigned long)MEM_mallocN(256+4, "tile1");
+ rz= (int *)*ztile;
+ *rz= *rz1;
+
+ zt= (char *)(rz+1);
+ rc= rcline;
+ for(a=0; a<256; a++, zt++, rc+=4) *zt= rc[GCOMP];
+ }
+ else if(byt1) { /* short opslaan */
+ *ctile= 2;
+ *ztile= (unsigned long)MEM_mallocN(2*256+4,"Tile2");
+ rz= (int *)*ztile;
+ *rz= *rz1;
+
+ zt= (char *)(rz+1);
+ rc= rcline;
+ for(a=0; a<256; a++, zt+=2, rc+=4) {
+ zt[0]= rc[BCOMP];
+ zt[1]= rc[GCOMP];
+ }
+ }
+ else { /* triple opslaan */
+ *ctile= 3;
+ *ztile= (unsigned long)MEM_mallocN(3*256,"Tile3");
+
+ zt= (char *)*ztile;
+ rc= rcline;
+ for(a=0; a<256; a++, zt+=3, rc+=4) {
+ zt[0]= rc[ACOMP];
+ zt[1]= rc[BCOMP];
+ zt[2]= rc[GCOMP];
+ }
+ }
+ }
+ ztile++;
+ ctile++;
+ }
+ }
+
+ MEM_freeN(rcline);
+ MEM_freeN(R.rectz); R.rectz= 0;
+
+ R.rectx= temprx; R.recty= tempry;
+ MTC_Mat4SwapMat4(shb->persmat, R.winmat);
+
+ /* printf("lampbuf %d\n", sizeoflampbuf(shb)); */
+}
+
+int RE_BasicShadowBuffer::firstreadshadbuf(struct ShadBuf *shb, int xs, int ys, int nr)
+{
+ /* return 1 als volledig gecomprimeerde shadbuftile && z==const */
+ static int *rz;
+ int ofs;
+ char *ct;
+
+ /* always test borders of shadowbuffer */
+ if(xs<0) xs= 0; else if(xs>=shb->size) xs= shb->size-1;
+ if(ys<0) ys= 0; else if(ys>=shb->size) ys= shb->size-1;
+
+ /* z berekenen */
+ ofs= (ys>>4)*(shb->size>>4) + (xs>>4);
+ ct= shb->cbuf+ofs;
+ if(*ct==0) {
+ if(nr==0) {
+ rz= *( (int **)(shb->zbuf+ofs) );
+ return 1;
+ }
+ else if(rz!= *( (int **)(shb->zbuf+ofs) )) return 0;
+
+ return 1;
+ }
+
+ return 0;
+}
+
+float RE_BasicShadowBuffer::readshadowbuf(struct ShadBuf *shb,
+ int xs, int ys, int zs) /* return 1.0 : volledig licht */
+{
+ float temp;
+ int *rz, ofs;
+ int zsamp;
+ char *ct, *cz;
+
+ /* simpleclip */
+ /* if(xs<0 || ys<0) return 1.0; */
+ /* if(xs>=shb->size || ys>=shb->size) return 1.0; */
+
+ /* always test borders of shadowbuffer */
+ if(xs<0) xs= 0; else if(xs>=shb->size) xs= shb->size-1;
+ if(ys<0) ys= 0; else if(ys>=shb->size) ys= shb->size-1;
+
+ /* z berekenen */
+ ofs= (ys>>4)*(shb->size>>4) + (xs>>4);
+ ct= shb->cbuf+ofs;
+ rz= *( (int **)(shb->zbuf+ofs) );
+
+ if(*ct==3) {
+ ct= ((char *)rz)+3*16*(ys & 15)+3*(xs & 15);
+ cz= (char *)&zsamp;
+ cz[ACOMP]= ct[0];
+ cz[BCOMP]= ct[1];
+ cz[GCOMP]= ct[2];
+ }
+ else if(*ct==2) {
+ ct= ((char *)rz);
+ ct+= 4+2*16*(ys & 15)+2*(xs & 15);
+ zsamp= *rz;
+
+ cz= (char *)&zsamp;
+ cz[BCOMP]= ct[0];
+ cz[GCOMP]= ct[1];
+ }
+ else if(*ct==1) {
+ ct= ((char *)rz);
+ ct+= 4+16*(ys & 15)+(xs & 15);
+ zsamp= *rz;
+
+ cz= (char *)&zsamp;
+ cz[GCOMP]= ct[0];
+
+ }
+ else {
+ /* got warning on this from alpha .... */
+ /* but it's working code! (ton) */
+ zsamp= (int) rz;
+ }
+
+ /* if(zsamp >= 0x7FFFFE00) return 1.0; */ /* geen schaduw als op oneindig wordt gesampeld*/
+
+ if(zsamp > zs) return 1.0; /* absoluut geen schaduw */
+ else if( zsamp < zs-bias) return 0.0 ; /* absoluut wel schaduw */
+ else { /* zacht gebied */
+
+ temp= ( (float)(zs- zsamp) )/(float)bias;
+ return 1.0 - temp*temp;
+
+ }
+}
+
+
+void RE_BasicShadowBuffer::readShadowValue(struct ShadBuf *shb,
+ float inp,
+ float * shadres) /* return 1.0: geen schaduw */
+{
+ float fac, co[4], dx[3], dy[3], aantal=0;
+ float xs1,ys1, siz, *j, xres, yres;
+ int xs,ys, zs;
+ short a,num;
+ float shadowfactor = 1.0;
+
+#ifdef RE_NO_SHADOWS
+ shadres[0] = shadowfactor;
+ shadres[1] = shadowfactor;
+ shadres[2] = shadowfactor;
+ return;
+#endif
+
+ /* if(inp <= 0.0) return 1.0; */
+
+ /* renderco en osaco roteren */
+ siz= 0.5*(float)shb->size;
+ VECCOPY(co, R.co);
+ co[3]= 1.0;
+
+ MTC_Mat4MulVec4fl(shb->persmat, co); /* rationele hom co */
+
+ xs1= siz*(1.0+co[0]/co[3]);
+ ys1= siz*(1.0+co[1]/co[3]);
+
+ /* Clip for z: near and far clip values of the shadow buffer. We
+ * can test for -1.0/1.0 because of the properties of the
+ * coordinate transformations. */
+ fac= (co[2]/co[3]);
+
+ if(fac>=1.0) {
+ shadres[0] = 0.0;
+ shadres[1] = 0.0;
+ shadres[2] = 0.0;
+ return;
+ } else if(fac<= -1.0) {
+ shadres[0] = 1.0;
+ shadres[1] = 1.0;
+ shadres[2] = 1.0;
+ return;
+ }
+
+ zs = (int) (((float)0x7FFFFFFF)*fac);
+
+ /* num*num samples nemen, gebied met fac vergroten */
+ num= shb->samp*shb->samp;
+ fac= shb->soft;
+
+
+ bias = (int) ((1.1-inp*inp)*shb->bias);
+
+ if(num==1) {
+ shadowfactor = readshadowbuf(shb,(int)xs1, (int)ys1, zs);
+ shadres[0] = shadowfactor;
+ shadres[1] = shadowfactor;
+ shadres[2] = shadowfactor;
+ return;
+ }
+
+ co[0]= R.co[0]+O.dxco[0];
+ co[1]= R.co[1]+O.dxco[1];
+ co[2]= R.co[2]+O.dxco[2];
+ co[3]= 1.0;
+ MTC_Mat4MulVec4fl(shb->persmat,co); /* rationele hom co */
+ dx[0]= xs1- siz*(1.0+co[0]/co[3]);
+ dx[1]= ys1- siz*(1.0+co[1]/co[3]);
+
+ co[0]= R.co[0]+O.dyco[0];
+ co[1]= R.co[1]+O.dyco[1];
+ co[2]= R.co[2]+O.dyco[2];
+ co[3]= 1.0;
+ MTC_Mat4MulVec4fl(shb->persmat,co); /* rationele hom co */
+ dy[0]= xs1- siz*(1.0+co[0]/co[3]);
+ dy[1]= ys1- siz*(1.0+co[1]/co[3]);
+
+ xres= fac*( fabs(dx[0])+fabs(dy[0]) );
+ yres= fac*( fabs(dx[1])+fabs(dy[1]) );
+
+ if(xres<fac) xres= fac;
+ if(yres<fac) yres= fac;
+
+ xs1-= (xres)/2;
+ ys1-= (yres)/2;
+
+ j= shb->jit;
+
+ if(xres<16.0 && yres<16.0) {
+ if(firstreadshadbuf(shb, (int)xs1, (int)ys1, 0)) {
+ if(firstreadshadbuf(shb, (int)(xs1+xres), (int)ys1, 1)) {
+ if(firstreadshadbuf(shb, (int)xs1, (int)(ys1+yres), 1)) {
+ if(firstreadshadbuf(shb, (int)(xs1+xres), (int)(ys1+yres), 1)) {
+ /* this return should do some renormalization, methinks */
+ shadowfactor = readshadowbuf(shb,(int)xs1, (int)ys1, zs);
+ shadres[0] = shadowfactor;
+ shadres[1] = shadowfactor;
+ shadres[2] = shadowfactor;
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ for(a=num;a>0;a--) {
+ /* i.p.v. jit ook met random geprobeerd: lelijk! */
+ xs= (int) (xs1 + xres*j[0]);
+ ys= (int) (ys1 + yres*j[1]);
+ j+=2;
+
+ aantal+= readshadowbuf(shb, xs, ys, zs);
+ }
+
+ /* Renormalizes for the sample number: */
+ shadowfactor = aantal/( (float)(num) );
+ shadres[0] = shadowfactor;
+ shadres[1] = shadowfactor;
+ shadres[2] = shadowfactor;
+ return;
+}
+
+/* different function... sampling behind clipend can be LIGHT, bias is negative! */
+/* return: light */
+float RE_BasicShadowBuffer::readshadowbuf_halo(struct ShadBuf *shb, int xs, int ys, int zs)
+{
+ float temp;
+ int *rz, ofs;
+ int zbias, zsamp;
+ char *ct, *cz;
+
+ /* simpleclip */
+ if(xs<0 || ys<0) return 0.0;
+ if(xs>=shb->size || ys>=shb->size) return 0.0;
+
+ /* z berekenen */
+ ofs= (ys>>4)*(shb->size>>4) + (xs>>4);
+ ct= shb->cbuf+ofs;
+ rz= *( (int **)(shb->zbuf+ofs) );
+
+ if(*ct==3) {
+ ct= ((char *)rz)+3*16*(ys & 15)+3*(xs & 15);
+ cz= (char *)&zsamp;
+ zsamp= 0;
+ cz[ACOMP]= ct[0];
+ cz[BCOMP]= ct[1];
+ cz[GCOMP]= ct[2];
+ }
+ else if(*ct==2) {
+ ct= ((char *)rz);
+ ct+= 4+2*16*(ys & 15)+2*(xs & 15);
+ zsamp= *rz;
+
+ cz= (char *)&zsamp;
+ cz[BCOMP]= ct[0];
+ cz[GCOMP]= ct[1];
+ }
+ else if(*ct==1) {
+ ct= ((char *)rz);
+ ct+= 4+16*(ys & 15)+(xs & 15);
+ zsamp= *rz;
+
+ cz= (char *)&zsamp;
+ cz[GCOMP]= ct[0];
+
+ }
+ else {
+ /* same as before */
+ /* still working code! (ton) */
+ zsamp= (int) rz;
+ }
+
+ /* geen schaduw als op oneindig wordt gesampeld*/
+
+ if(zsamp >= 0x7FFFFE00) return 1.0;
+
+ if(zsamp > zs) return 1.0; /* absoluut geen schaduw */
+ else {
+ /* bias is negative, so the (zs-bias) can be beyond 0x7fffffff */
+ zbias= 0x7fffffff - zs;
+ if(zbias > -bias) {
+ if( zsamp < zs-bias) return 0.0 ; /* absoluut wel schaduw */
+ }
+ else return 0.0 ; /* absoluut wel schaduw */
+ }
+
+ /* zacht gebied */
+
+ temp= ( (float)(zs- zsamp) )/(float)bias;
+ return 1.0 - temp*temp;
+}
+
+
+float RE_BasicShadowBuffer::shadow_halo(LampRen *lar, float *p1, float *p2)
+{
+ /* p1 p2 already are rotated in spot-space */
+ ShadBuf *shb= lar->shb;
+ float co[4], siz;
+ float labda, labdao, labdax, labday, ldx, ldy;
+ float zf, xf1, yf1, zf1, xf2, yf2, zf2;
+ float count, lightcount;
+ int x, y, z, xs1, ys1;
+ int dx = 0, dy = 0;
+
+ siz= 0.5*(float)shb->size;
+ /* negative! The other side is more important */
+ bias= -shb->bias;
+
+ co[0]= p1[0];
+ co[1]= p1[1];
+ co[2]= p1[2]/lar->sh_zfac;
+ co[3]= 1.0;
+ MTC_Mat4MulVec4fl(shb->winmat, co); /* rationele hom co */
+ xf1= siz*(1.0+co[0]/co[3]);
+ yf1= siz*(1.0+co[1]/co[3]);
+ zf1= (co[2]/co[3]);
+
+
+ co[0]= p2[0];
+ co[1]= p2[1];
+ co[2]= p2[2]/lar->sh_zfac;
+ co[3]= 1.0;
+ MTC_Mat4MulVec4fl(shb->winmat, co); /* rationele hom co */
+ xf2= siz*(1.0+co[0]/co[3]);
+ yf2= siz*(1.0+co[1]/co[3]);
+ zf2= (co[2]/co[3]);
+
+ /* de 2dda */
+
+ xs1= (int)xf1;
+ ys1= (int)yf1;
+
+ if(xf1 != xf2) {
+ if(xf2-xf1 > 0.0) {
+ labdax= (xf1-xs1-1.0)/(xf1-xf2);
+ ldx= -shb->shadhalostep/(xf1-xf2);
+ dx= shb->shadhalostep;
+ }
+ else {
+ labdax= (xf1-xs1)/(xf1-xf2);
+ ldx= shb->shadhalostep/(xf1-xf2);
+ dx= -shb->shadhalostep;
+ }
+ }
+ else {
+ labdax= 1.0;
+ ldx= 0.0;
+ }
+
+ if(yf1 != yf2) {
+ if(yf2-yf1 > 0.0) {
+ labday= (yf1-ys1-1.0)/(yf1-yf2);
+ ldy= -shb->shadhalostep/(yf1-yf2);
+ dy= shb->shadhalostep;
+ }
+ else {
+ labday= (yf1-ys1)/(yf1-yf2);
+ ldy= shb->shadhalostep/(yf1-yf2);
+ dy= -shb->shadhalostep;
+ }
+ }
+ else {
+ labday= 1.0;
+ ldy= 0.0;
+ }
+
+ x= xs1;
+ y= ys1;
+ labda= count= lightcount= 0.0;
+
+/* printf("start %x %x \n", (int)(0x7FFFFFFF*zf1), (int)(0x7FFFFFFF*zf2)); */
+
+ while(1) {
+ labdao= labda;
+
+ if(labdax==labday) {
+ labdax+= ldx;
+ x+= dx;
+ labday+= ldy;
+ y+= dy;
+ }
+ else {
+ if(labdax<labday) {
+ labdax+= ldx;
+ x+= dx;
+ } else {
+ labday+= ldy;
+ y+= dy;
+ }
+ }
+
+ labda= MIN2(labdax, labday);
+ if(labda==labdao || labda>=1.0) break;
+
+ zf= zf1 + labda*(zf2-zf1);
+ count+= 1.0;
+
+ if(zf<= 0.0) lightcount += 1.0; /* close to the spot */
+ else {
+
+ /* make sure, behind the clipend we extend halolines. */
+ if(zf>=1.0) z= 0x7FFFF000;
+ else z= (int)(0x7FFFF000*zf);
+
+ lightcount+= readshadowbuf_halo(shb, x, y, z);
+
+ }
+ }
+
+ if(count!=0.0) return (lightcount/count);
+ return 0.0;
+
+}
+
+
+
+
+/* sampelen met filter
+ xstart= xs-1;
+ ystart= ys-1;
+ if(xstart<0) xstart= 0;
+ if(ystart<0) ystart= 0;
+ xend= xstart+2;
+ yend= ystart+2;
+ if(xend>=shb->size) { xstart= shb->size-3; xend= shb->size-1;}
+ if(yend>=shb->size) { ystart= shb->size-3; yend= shb->size-1;}
+
+ fid= filt3;
+ for(ys=ystart;ys<=yend;ys++) {
+ rz= shb->buf+ ys*shb->size+ xstart;
+ for(xs= xstart;xs<=xend;xs++,rz++) {
+ if( *rz+0x100000<zs) aantal+= *fid;
+ fid++;
+ }
+ }
+
+
+ return 1.0-((float)aantal)/16.0;
+*/
diff --git a/source/blender/render/intern/source/RE_callbacks.c b/source/blender/render/intern/source/RE_callbacks.c
new file mode 100644
index 00000000000..6228edf1731
--- /dev/null
+++ b/source/blender/render/intern/source/RE_callbacks.c
@@ -0,0 +1,159 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * Callbacks to make the renderer interact with calling modules.
+ */
+
+#include <stdlib.h> /* for NULL??? */
+#include "render.h"
+#include "render_intern.h"
+#include "RE_callbacks.h"
+
+/*
+ * The callbacks are done in three parts:
+ *
+ * - a local static pointer to the eventual function. NULL if not
+ * defined, or if the behaviour is not required.
+ *
+ * - a hook that can be called locally
+ *
+ * - a hook that can be called externally, to set an external function
+ * to provide said functionality.
+ *
+ * These might be generated from a spec such as:
+ *
+ * callback {
+ * local = <local name>
+ * external = <external name>
+ * type = <ret_type> (<args>,...)
+ * }
+ *
+ * Should generate:
+ * - a static var
+ * - an internal loop, plus decl.
+ * - an external setter, plus decl.
+ *
+ */
+
+/* Part 1: ------------------------------------------------------------- */
+
+static int (*RE_local_test_break_function)(void) = NULL;
+
+static void (*RE_local_timecursor_function)(int) = NULL;
+
+static void (*RE_local_renderdisplay_function)(int i,
+ int j,
+ int k,
+ int l,
+ unsigned int *m)
+ = NULL;
+
+static void (*RE_local_initrenderdisplay_function)(void) = NULL;
+static void (*RE_local_clearrenderdisplay_function)(short) = NULL;
+
+static void (*RE_local_printrenderinfo_function)(double,int) = NULL;
+
+static void (*RE_local_getrenderdata_function)(void) = NULL;
+static void (*RE_local_freerenderdata_function)(void) = NULL;
+
+/* Part 2: ------------------------------------------------------------- */
+
+int RE_local_test_break(void) {
+ if (RE_local_test_break_function) {
+ return RE_local_test_break_function();
+ } else {
+ /* transparant behaviour: proceed */
+ return 0;
+ }
+}
+
+void RE_local_timecursor(int i) {
+ if (RE_local_timecursor_function) RE_local_timecursor_function(i);
+}
+
+void RE_local_render_display(int i, int j, int k, int l, unsigned int* m) {
+ if (RE_local_renderdisplay_function) RE_local_renderdisplay_function(i, j, k, l, m);
+}
+void RE_local_init_render_display(void) {
+ if (RE_local_initrenderdisplay_function) RE_local_initrenderdisplay_function();
+}
+void RE_local_clear_render_display(short i) {
+ if (RE_local_clearrenderdisplay_function) RE_local_clearrenderdisplay_function(i);
+}
+
+void RE_local_printrenderinfo(double time, int i) {
+ if (RE_local_printrenderinfo_function) RE_local_printrenderinfo_function(time, i);
+}
+
+void RE_local_get_renderdata(void) {
+ if (RE_local_getrenderdata_function) RE_local_getrenderdata_function();
+}
+void RE_local_free_renderdata(void) {
+ if (RE_local_freerenderdata_function) RE_local_freerenderdata_function();
+}
+
+/* Part 3: ------------------------------------------------------------- */
+
+void RE_set_test_break_callback(int (*f)(void)) {
+ RE_local_test_break_function = f;
+}
+
+void RE_set_timecursor_callback(void (*f)(int)) {
+ RE_local_timecursor_function = f;
+}
+
+void RE_set_renderdisplay_callback(void (*f)(int i,
+ int j,
+ int k,
+ int l,
+ unsigned int *))
+{
+ RE_local_renderdisplay_function = f;
+}
+
+void RE_set_initrenderdisplay_callback(void (*f)(void)) {
+ RE_local_initrenderdisplay_function = f;
+}
+
+void RE_set_clearrenderdisplay_callback(void (*f)(short)) {
+ RE_local_clearrenderdisplay_function = f;
+}
+
+void RE_set_printrenderinfo_callback(void (*f)(double,int)) {
+ RE_local_printrenderinfo_function = f;
+}
+
+void RE_set_getrenderdata_callback(void (*f)(void)) {
+ RE_local_getrenderdata_function = f;
+}
+
+void RE_set_freerenderdata_callback(void (*f)(void)) {
+ RE_local_freerenderdata_function = f;
+}
diff --git a/source/blender/render/intern/source/edgeRender.c b/source/blender/render/intern/source/edgeRender.c
new file mode 100644
index 00000000000..d3c944efac7
--- /dev/null
+++ b/source/blender/render/intern/source/edgeRender.c
@@ -0,0 +1,952 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * Add enhanced edges on a rendered image (toon shading, edge shading).
+ */
+
+/*
+ * Edge rendering: use a mask to weigh the depth of neighbouring
+ * pixels, and do a colour correction.
+ *
+ * We need:
+ * - a buffer to store the depths (ints)
+ * - a function that alters the colours in R.rectot (copy edge_enhance?)
+ * The max. z buffer depth is 0x7FFF.FFFF (7 F's)
+ *
+ * - We 'ignore' the pixels falling outside the regular buffer (we fill)
+ * these with the max depth. This causes artefacts when rendering in
+ * parts.
+ */
+
+/* ------------------------------------------------------------------------- */
+
+/* enable extra bounds checking and tracing */
+/* #define RE_EDGERENDERSAFE */
+/* disable the actual edge correction */
+/* #define RE_EDGERENDER_NO_CORRECTION */
+
+#include <stdlib.h>
+#include <math.h>
+#include <limits.h> /* INT_MIN,MAX are used here */
+#include <stdio.h>
+
+#include "MEM_guardedalloc.h"
+#include "MTC_vectorops.h"
+
+#include "RE_callbacks.h"
+#include "edgeRender.h"
+#include "render.h"
+#include "render_intern.h"
+#include "zbuf.h" /* for zbufclipwire and zbufclip */
+#include "jitter.h"
+
+#ifdef RE_EDGERENDERSAFE
+char edgeRender_h[] = EDGERENDER_H;
+char edgeRender_c[] = "$Id$";
+#include "errorHandler.h"
+#endif
+
+/* ------------------------------------------------------------------------- */
+/* the lazy way: */
+#define MIN2(x,y) ( (x)<(y) ? (x) : (y) )
+
+/* ------------------------------------------------------------------------- */
+
+ /* These function pointers are used for z buffer filling. */
+extern void (*zbuffunc)(float *, float *, float *);
+extern void (*zbuflinefunc)(float *v1, float *v2);
+extern float Zmulx, Zmuly; /* Some kind of scale? */
+extern float Zjitx,Zjity; /* The x,y values for jitter offset */
+extern unsigned int Zvlnr; /* Face rendering pointer and counter: these */
+extern VlakRen *Zvlr; /* are used for 'caching' render results. */
+
+/* ------------------------------------------------------------------------- */
+
+/* exp: */
+static Material** matBuffer; /* buffer with material indices */
+static Material* mat_cache; /* material of the face being buffered */
+
+static char* colBuffer; /* buffer with colour correction */
+static int *edgeBuffer; /* buffer with distances */
+static int bufWidth; /* x-dimension of the buffer */
+static int bufHeight; /* y-dimension of the buffer */
+static int imWidth; /* x-dimension of the image */
+static int imHeight; /* y-dimension of the image */
+static int osaCount; /* oversample count */
+static int maskBorder; /* size of the mask border */
+static short int intensity; /* edge intensity */
+static short int same_mat_redux; /* intensity reduction for boundaries with the same material */
+static int compatible_mode; /* edge positioning compatible with old rederer */
+static int selectmode; /* 0: only solid faces, 1: also transparent f's */
+
+static int Aminy; /* y value of first line in the accu buffer */
+static int Amaxy; /* y value of last line in the accu buffer */
+ /* -also used to clip when zbuffering */
+static char edgeR; /* Colour for the edges. The edges will receive */
+static char edgeG; /* this tint. The colour is fully used! */
+static char edgeB;
+/* static float edgeBlend; */ /* Indicate opaqueness of the edge colour. */
+
+/* Local functions --------------------------------------------------------- */
+/**
+ * Initialise the edge render buffer memory.
+ */
+void initEdgeRenderBuffer(void);
+/**
+ * Release buffer memory.
+ */
+void freeEdgeRenderBuffer(void);
+
+/**
+ * Set all distances in the distance buffer to the maximum distance.
+ */
+void resetDistanceBuffer(void);
+
+/**
+ * Insert this distance at these pixel coordinates.
+ */
+void insertInEdgeBuffer(int x, int y, int dist);
+
+/**
+ * Renders enhanced edges. Distances from distRect are used to
+ * determine a correction on colourRect
+ */
+void renderEdges(char * colourRect);
+
+/**
+ * Buffer an edge between these two vertices in the e.r. distance buffer.
+ */
+void fillEdgeRenderEdge(float *vec1, float *vec2);
+
+/**
+ * Buffer a face between these two vertices in the e.r. distance buffer.
+ */
+void fillEdgeRenderFace(float *v1, float *v2, float *v3);
+
+/**
+ * Compose the edge render colour buffer.
+ */
+void calcEdgeRenderColBuf(char * tarbuf);
+
+/**
+ * Loop over all objects that need to be edge rendered. This loop determines
+ * which objects get to be elected for edge rendering.
+ */
+int zBufferEdgeRenderObjects(void);
+
+/**
+ * Add edge pixels to the original image. It blends <bron> over <doel>.
+ */
+void addEdgeOver(char *doel, char *bron);
+
+/* ------------------------------------------------------------------------- */
+
+void addEdges(
+ char * targetbuf,
+ int iw, int ih,
+ int osanr,
+ short int intens, short int intens_redux,
+ int compat, int mode,
+ float r, float g, float b
+ )
+{
+ float rf, gf ,bf;
+ /* render parameters */
+ selectmode = mode;
+ imWidth = iw;
+ imHeight = ih;
+ compatible_mode = compat;
+ osaCount = osanr;
+ intensity = intens;
+ /* Reduction doesn't exceed intensity. */
+ same_mat_redux = ((intens_redux < intensity)? intens_redux : intensity);
+
+ rf = r * 255.0;
+ if (rf > 255) edgeR = 255; else edgeR = rf;
+ gf = g * 255.0;
+ if (gf > 255) edgeG = 255; else edgeG = gf;
+ bf = b * 255.0;
+ if (bf > 255) edgeB = 255; else edgeB = bf;
+
+ /* Go! */
+ initEdgeRenderBuffer();
+ calcEdgeRenderColBuf(targetbuf);
+ freeEdgeRenderBuffer();
+
+} /* end of void addEdges(char *, int, int, int, short int , int) */
+
+/* ------------------------------------------------------------------------- */
+
+void initEdgeRenderBuffer()
+{
+ char *ptr;
+ int i;
+
+ maskBorder = 1; /* for 3 by 3 mask*/
+
+ bufWidth = imWidth + (2 * maskBorder);
+ bufHeight = imHeight + (2 * maskBorder);
+
+ /* Experimental: store the material indices. */
+ if (same_mat_redux) {
+ matBuffer = MEM_callocN(sizeof(Material*)
+ * bufWidth * bufHeight, "matBuffer");
+ }
+
+ edgeBuffer = MEM_callocN(sizeof(int) * bufWidth * bufHeight, "edgeBuffer");
+ colBuffer = MEM_callocN(sizeof(char) * 4 * imWidth * imHeight, "colBuffer");
+
+
+ if ((edgeR != 0) || (edgeG != 0) || (edgeB != 0)) {
+ /* Set all colbuf pixels to the edge colour. Leave alpha channel */
+ /* cleared. Actually, we could blend in any image here... */
+ ptr = colBuffer;
+ for (i = 0; i < imWidth * imHeight; i++, ptr+=4)
+ {
+ ptr[0] = edgeR;
+ ptr[1] = edgeG;
+ ptr[2] = edgeB;
+ ptr[3] = 0;
+ }
+ }
+
+#ifdef RE_EDGERENDERSAFE
+ if (!edgeBuffer || !colBuffer) {
+ char *fname = "initEdgeRenderBuffer";
+ RE_error(RE_CANNOT_ALLOCATE_MEMORY, fname);
+ }
+#endif
+} /* end of void initEdgeRenderBuffer(void) */
+
+/* ------------------------------------------------------------------------- */
+void freeEdgeRenderBuffer(void)
+{
+ if(edgeBuffer) MEM_freeN(edgeBuffer);
+ if(colBuffer) MEM_freeN(colBuffer);
+ if(matBuffer) MEM_freeN(matBuffer);
+} /* end of void freeEdgeRenderBuffer(void) */
+
+/* ------------------------------------------------------------------------- */
+
+void resetDistanceBuffer(void)
+{
+ int i;
+ for(i = 0; i < bufWidth * bufHeight; i++) edgeBuffer[i] = 0x7FFFFFFF;
+} /* end of void resetDistanceBuffer(void) */
+
+/* ------------------------------------------------------------------------- */
+
+void insertInEdgeBuffer(int x, int y, int dist)
+{
+ int index;
+#ifdef RE_EDGERENDERSAFE
+ char *fname = "insertInEdgeBuffer";
+ if ((x < 0) || (x > imWidth ) ||
+ (y < 0) || (y > (imHeight-1) ) ) {
+ RE_error(RE_EDGERENDER_WRITE_OUTSIDE_BUFFER, fname);
+ return;
+ }
+#endif
+
+ /* +1? */
+ index = (y * bufWidth) + x + maskBorder;
+
+ /*exp: just dump a single index here. Maybe we can do more
+ * sophisticated things later on. */
+ if (same_mat_redux) {
+ matBuffer[index] = mat_cache;
+ }
+
+ if (edgeBuffer[index] >dist ) edgeBuffer[index] = dist;
+
+} /* end of void insertInEdgeBuffer(int x, int y, int dist) */
+
+/* ------------------------------------------------------------------------- */
+/* Modelled after rendercore.c/edge_enhance() */
+void renderEdges(char *colourRect)
+{
+ /* use zbuffer to define edges, add it to the image */
+ int val, y, x, col, *rz, *rz1, *rz2, *rz3;
+ char *cp;
+ int targetoffset, heightoffset;
+ int i;
+ int matdif; /* For now: just a bogus int, 0 when all materials
+ * under the mask are the same, non-0 otherwise*/
+ int *matptr_low = 0, *matptr_cent = 0, *matptr_high = 0;
+ int matdiffac = 0;
+
+#ifdef RE_EDGERENDER_NO_CORRECTION
+ return; /* no edge correction */
+#endif
+
+#ifdef RE_EDGERENDERSAFE
+ fprintf(stderr, "\n*** Activated full error trace on "
+ "edge rendering using:\n\t%s\n\t%s"
+ "\n*** Rendering edges at %d intensity",
+ edgeRender_c, edgeRender_h, intensity);
+#endif
+
+
+ /* Old renderer uses wrong positions! With the compat switch on, the po- */
+ /* sitions will be corrected to be offset in the same way. */
+ if (compatible_mode) {
+ targetoffset = 4 * (imWidth - 1);
+ heightoffset = -1;
+ } else {
+ targetoffset = 0;
+ heightoffset = 0;
+ }
+
+ /* Fill edges with some default values. We just copy what is in the edge */
+ /* This looks messy, but it appears to be ok. */
+ edgeBuffer[0] = edgeBuffer[bufWidth + 1];
+ edgeBuffer[bufWidth - 1] = edgeBuffer[(2 * bufWidth) - 2];
+ edgeBuffer[bufWidth * (bufHeight - 1)] =
+ edgeBuffer[bufWidth * (bufHeight - 2) + 1];
+ edgeBuffer[(bufWidth * bufHeight) - 1] =
+ edgeBuffer[(bufWidth * (bufHeight - 1)) - 2];
+ for (i = 1; i < bufWidth - 1; i++) { /* lieing edges */
+ edgeBuffer[i] = edgeBuffer[bufWidth + i]; /* bottom*/
+ edgeBuffer[((bufHeight - 1)*bufWidth) + i]
+ = edgeBuffer[((bufHeight - 2)*bufWidth) + i]; /* top */
+ }
+ for (i = 1; i < bufHeight - 2; i++) { /* standing edges */
+ edgeBuffer[i * bufWidth] = edgeBuffer[(i * bufWidth) + 1]; /* left */
+ edgeBuffer[((i + 1) * bufWidth) - 1] =
+ edgeBuffer[((i + 1) * bufWidth) - 2]; /* right */
+ }
+
+ /* same hack for the materials: */
+ if (same_mat_redux) {
+ matBuffer[0] = matBuffer[bufWidth + 1];
+ matBuffer[bufWidth - 1] = matBuffer[(2 * bufWidth) - 2];
+ matBuffer[bufWidth * (bufHeight - 1)] =
+ matBuffer[bufWidth * (bufHeight - 2) + 1];
+ matBuffer[(bufWidth * bufHeight) - 1] =
+ matBuffer[(bufWidth * (bufHeight - 1)) - 2];
+ for (i = 1; i < bufWidth - 1; i++) { /* lieing mats */
+ matBuffer[i] = matBuffer[bufWidth + i]; /* bottom*/
+ matBuffer[((bufHeight - 1)*bufWidth) + i]
+ = matBuffer[((bufHeight - 2)*bufWidth) + i]; /* top */
+ }
+ for (i = 1; i < bufHeight - 2; i++) { /* standing mats */
+ matBuffer[i * bufWidth] = matBuffer[(i * bufWidth) + 1]; /* left */
+ matBuffer[((i + 1) * bufWidth) - 1] =
+ matBuffer[((i + 1) * bufWidth) - 2]; /* right */
+ }
+ }
+
+ /* alle getallen in zbuffer 3 naar rechts shiften */
+ rz = edgeBuffer;
+ if(rz==0) return;
+
+ for(y=0; y < bufHeight * bufWidth; y++, rz++) {
+ (*rz)>>= 3;
+ }
+
+ /* Distance pointers */
+ rz1= edgeBuffer;
+ rz2= rz1 + bufWidth;
+ rz3= rz2 + bufWidth;
+
+ if (same_mat_redux) {
+ matptr_low = matBuffer;
+ matptr_cent = matptr_low + bufWidth;
+ matptr_high = matptr_cent + bufWidth;
+ }
+
+ if (osaCount == 1) {
+ cp = colourRect + targetoffset;
+ } else {
+ cp = colBuffer + targetoffset;
+ }
+
+ i = 0;
+
+ for(y = 0; y < (imHeight + heightoffset) ; y++) {
+
+
+ /* All these indices are a bit silly. I need to
+ * rewrite this, so all buffers use the same
+ * indexing. */
+ for(x = 0;
+ x < imWidth;
+ x++, rz1++, rz2++, rz3++, cp+=4,
+ matptr_low++,
+ matptr_cent++,
+ matptr_high++) {
+
+ col= abs( - rz1[0] - 2*rz1[1] - rz1[2]
+ - 2*rz2[0] + 12*rz2[1] - 2*rz2[2]
+ - rz3[0] - 2*rz3[1] - rz3[2]) / 3;
+
+ /* Several options for matdif:
+ *
+ * - suppress all boundaries with 0 dif
+ *
+ * - weaken col dif? Or decrease intensity by
+ * a factor when non 0 dif??
+ */
+
+ /* exp: matdif is non-0 if the mask-center
+ * material differs from any of the
+ * corners. */
+
+ if (same_mat_redux) {
+ matdif = abs (matptr_cent[1] - matptr_low[0])
+ + abs (matptr_cent[1] - matptr_low[1])
+ + abs (matptr_cent[1] - matptr_low[2])
+ + abs (matptr_cent[1] - matptr_cent[0])
+ + abs (matptr_cent[1] - matptr_low[2])
+ + abs (matptr_cent[1] - matptr_high[0])
+ + abs (matptr_cent[1] - matptr_high[1])
+ + abs (matptr_cent[1] - matptr_high[2]);
+
+ matdiffac = (matdif ? 0 : same_mat_redux);
+ }
+
+ col= ((intensity - matdiffac) * col)>>14;
+ if(col>255) col= 255;
+
+ /* Colour edge if
+ *
+ * 1. there is an appreciable, non-uniform
+ * gradient,
+ *
+ * 2. there are different materials bordering
+ * on the center pixel
+ */
+ if( (col>0)
+ /* && (matdif != 0) */) {
+
+ if(osaCount > 1) {
+ /* Currently done by tweaking alpha. The colBuffer is */
+ /* filled with pixels of the colour appropriate for the */
+ /* edges. This colour is alpha-blended over the image. */
+ /* This calculation determines how much colour each pixel */
+ /* gets. */
+ col/= osaCount;
+ val= cp[3]+col;
+ if(val>255) cp[3]= 255; else cp[3]= val;
+ }
+ else {
+ /* the pixel is blackened when col is too big */
+ val = cp[0] - col;
+ if(val<=0) {
+ cp[0]= edgeR;
+ } else {
+ cp[0]= val;
+ }
+ val = cp[1] - col;
+ if(val<=0) {
+ cp[1]= edgeG;
+ }else {
+ cp[1]= val;
+ }
+ val = cp[2] - col;
+ if(val<=0) {
+ cp[2]= edgeB;
+ } else {
+ cp[2]= val;
+ }
+ }
+ }
+ }
+ rz1+= 2;
+ rz2+= 2;
+ rz3+= 2;
+ if (same_mat_redux) {
+ matptr_low += 2;
+ matptr_cent += 2;
+ matptr_high += 2;
+ }
+
+ }
+
+} /* end of void renderEdges() */
+
+/* ------------------------------------------------------------------------- */
+
+void addEdgeOver(char *doel, char *bron) /* telt bron bij doel */
+{
+ float c;
+ int mul;
+
+ if( bron[3] == 0) return;
+ if( bron[3] == 255) { /* is getest, scheelt */
+ *((unsigned int *)doel)= *((unsigned int *)bron);
+ return;
+ }
+
+ /* This must be a special blend-mode, because we get a 'weird' data */
+ /* input format now. With edge = (c_e, a_e), picture = (c_p, a_p), we */
+ /* get: result = ( c_e*a_e + c_p(1 - a_e), a_p ). */
+
+ mul = 255 - bron[3];
+
+ /* Not sure if the conversion to float is really necessary here... I will*/
+ /* think about it another day. */
+ c = ((mul * doel[0] + bron[0] * bron[3])/255.0);
+ if(c>255) {doel[0]=255;} else { doel[0]= c;}
+ c = ((mul * doel[1] + bron[1] * bron[3])/255.0);
+ if(c>255) {doel[1]=255;} else { doel[1]= c;}
+ c = ((mul * doel[2] + bron[2] * bron[3])/255.0);
+ if(c>255) {doel[2]=255;} else { doel[2]= c;}
+}
+
+void calcEdgeRenderColBuf(char* colTargetBuffer)
+{
+
+/* int part; */
+ int keepLooping = 1;
+ int sample;
+
+ /* zbuffer fix: here? */
+ Zmulx= ((float) imWidth)/2.0;
+ Zmuly= ((float) imHeight)/2.0;
+
+ /* use these buffer fill functions */
+ zbuffunc = fillEdgeRenderFace;
+ zbuflinefunc = fillEdgeRenderEdge;
+
+ /* always buffer the max. extent */
+ Aminy = 0;
+ Amaxy = imHeight;
+
+ sample = 0; /* Zsample is used internally ! */
+ while ( (sample < osaCount) && keepLooping ) {
+ /* jitter */
+ Zjitx= -jit[sample][0];
+ Zjity= -jit[sample][1];
+
+ /* should reset dis buffer here */
+ resetDistanceBuffer();
+
+ /* kick all into a z buffer */
+ keepLooping = zBufferEdgeRenderObjects();
+
+ /* do filtering */
+ renderEdges(colTargetBuffer);
+
+ if(RE_local_test_break()) keepLooping = 0;
+ sample++;
+ }
+
+ /* correction for osa-sampling...*/
+ if( osaCount != 1) {
+ char *rp, *rt;
+ int a;
+
+ rt= colTargetBuffer;
+ rp= colBuffer;
+ for(a = imWidth * imHeight; a>0; a--, rt+=4, rp+=4) {
+ /* there seem to be rounding errors here... */
+ addEdgeOver(rt, rp);
+ }
+ }
+
+} /*End of void calcEdgeRenderZBuf(void) */
+
+/* ------------------------------------------------------------------------- */
+/* Clip flags etc. should still be set. When called in the span of 'normal' */
+/* rendering, this should be ok. */
+int zBufferEdgeRenderObjects(void)
+{
+ int keepLooping;
+ int faceCounter; /* counter for face number */
+ Material *ma;
+
+ keepLooping = 1;
+ ma = NULL;
+ faceCounter = 0;
+
+ while ( (faceCounter < R.totvlak) && keepLooping) {
+ if((faceCounter & 255)==0) { Zvlr= R.blovl[faceCounter>>8]; }
+ else Zvlr++;
+
+ ma= Zvlr->mat;
+
+ /*exp*/
+ mat_cache = ma;
+
+ /* face number is used in the fill functions */
+ Zvlnr = faceCounter + 1;
+
+ if(Zvlr->flag & R_VISIBLE) {
+
+ /* here we cull all transparent faces if mode == 0 */
+ if (selectmode || !(ma->mode & MA_ZTRA)) {
+ /* here we can add all kinds of extra selection criteria */
+ if(ma->mode & (MA_WIRE)) zbufclipwire(Zvlr);
+ else {
+ zbufclip(Zvlr->v1->ho, Zvlr->v2->ho, Zvlr->v3->ho,
+ Zvlr->v1->clip, Zvlr->v2->clip, Zvlr->v3->clip);
+ if(Zvlr->v4) {
+ Zvlnr+= 0x800000; /* in a sense, the 'adjoint' face */
+ zbufclip(Zvlr->v1->ho, Zvlr->v3->ho, Zvlr->v4->ho,
+ Zvlr->v1->clip, Zvlr->v3->clip, Zvlr->v4->clip);
+ }
+ }
+ }
+ };
+ if(RE_local_test_break()) keepLooping = 0;
+ faceCounter++;
+ }
+ return keepLooping;
+} /* End of int zBufferEdgeRenderObjects(void) */
+
+/* ------------------------------------------------------------------------- */
+
+void fillEdgeRenderFace(float *v1, float *v2, float *v3)
+{
+ /* Coordinates of the vertices are specified in ZCS */
+ double z0; /* used as temp var*/
+ double xx1;
+ double zxd,zyd,zy0, tmp;
+ float *minv,*maxv,*midv;
+ int zverg,x;
+ int my0,my2,sn1,sn2,rectx,zd;
+ int y,omsl,xs0,xs1,xs2,xs3, dx0,dx1,dx2/* , mask */;
+ int linex, liney, xoffset, yoffset; /* pointers to the pixel number */
+
+ /* These used to be doubles. We may want to change them back if the */
+ /* loss of accuracy proves to be a problem? There does not seem to be */
+ /* any performance issues here, so I'll just keep the doubles. */
+ /* float vec0[3], vec1[3], vec2[3]; */
+ double vec0[3], vec1[3], vec2[3];
+
+ /* MIN MAX */
+ /* sort vertices for min mid max y value */
+ if(v1[1]<v2[1]) {
+ if(v2[1]<v3[1]) { minv=v1; midv=v2; maxv=v3;}
+ else if(v1[1]<v3[1]) { minv=v1; midv=v3; maxv=v2;}
+ else { minv=v3; midv=v1; maxv=v2;}
+ }
+ else {
+ if(v1[1]<v3[1]) { minv=v2; midv=v1; maxv=v3;}
+ else if(v2[1]<v3[1]) { minv=v2; midv=v3; maxv=v1;}
+ else { minv=v3; midv=v2; maxv=v1;}
+ }
+
+ if(minv[1] == maxv[1]) return; /* beveiliging 'nul' grote vlakken */
+
+ my0 = ceil(minv[1]);
+ my2 = floor(maxv[1]);
+ omsl = floor(midv[1]);
+
+ /* outside the current z buffer slice: clip whole face */
+ if( (my2 < Aminy) || (my0 > Amaxy)) return;
+
+ if(my0<Aminy) my0= Aminy;
+
+ /* EDGES : DE LANGSTE */
+ xx1= maxv[1]-minv[1];
+ if(xx1>2.0/65536.0) {
+ z0= (maxv[0]-minv[0])/xx1;
+
+ tmp= (-65536.0*z0);
+ dx0= CLAMPIS(tmp, INT_MIN, INT_MAX);
+
+ tmp= 65536.0*(z0*(my2-minv[1])+minv[0]);
+ xs0= CLAMPIS(tmp, INT_MIN, INT_MAX);
+ }
+ else {
+ dx0= 0;
+ xs0= 65536.0*(MIN2(minv[0],maxv[0]));
+ }
+ /* EDGES : DE BOVENSTE */
+ xx1= maxv[1]-midv[1];
+ if(xx1>2.0/65536.0) {
+ z0= (maxv[0]-midv[0])/xx1;
+
+ tmp= (-65536.0*z0);
+ dx1= CLAMPIS(tmp, INT_MIN, INT_MAX);
+
+ tmp= 65536.0*(z0*(my2-midv[1])+midv[0]);
+ xs1= CLAMPIS(tmp, INT_MIN, INT_MAX);
+ }
+ else {
+ dx1= 0;
+ xs1= 65536.0*(MIN2(midv[0],maxv[0]));
+ }
+ /* EDGES : DE ONDERSTE */
+ xx1= midv[1]-minv[1];
+ if(xx1>2.0/65536.0) {
+ z0= (midv[0]-minv[0])/xx1;
+
+ tmp= (-65536.0*z0);
+ dx2= CLAMPIS(tmp, INT_MIN, INT_MAX);
+
+ tmp= 65536.0*(z0*(omsl-minv[1])+minv[0]);
+ xs2= CLAMPIS(tmp, INT_MIN, INT_MAX);
+ }
+ else {
+ dx2= 0;
+ xs2= 65536.0*(MIN2(minv[0],midv[0]));
+ }
+
+ /* ZBUF DX DY */
+ MTC_diff3DFF(vec1, v1, v2);
+ MTC_diff3DFF(vec2, v2, v3);
+ MTC_cross3Double(vec0, vec1, vec2);
+
+ /* cross product of two of the sides is 0 => this face is too small */
+ if(vec0[2]==0.0) return;
+
+ if(midv[1] == maxv[1]) omsl= my2;
+ if(omsl < Aminy) omsl= Aminy-1; /* dan neemt ie de eerste lus helemaal */
+
+ while (my2 > Amaxy) { /* my2 kan groter zijn */
+ xs0+=dx0;
+ if (my2<=omsl) {
+ xs2+= dx2;
+ }
+ else{
+ xs1+= dx1;
+ }
+ my2--;
+ }
+
+ xx1= (vec0[0]*v1[0]+vec0[1]*v1[1])/vec0[2]+v1[2];
+
+ zxd= -vec0[0]/vec0[2];
+ zyd= -vec0[1]/vec0[2];
+ zy0= my2*zyd+xx1;
+ zd= (int)CLAMPIS(zxd, INT_MIN, INT_MAX);
+
+ /* start-ofset in rect */
+ /* rectx= R.rectx; */
+ /* I suspect this var needs very careful setting... When edge rendering */
+ /* is on, this is strange */
+ rectx = imWidth;
+ yoffset = my2;
+ xoffset = 0;
+
+ xs3= 0; /* flag */
+ if(dx0>dx1) {
+ MTC_swapInt(&xs0, &xs1);
+ MTC_swapInt(&dx0, &dx1);
+ xs3= 1; /* flag */
+
+ }
+
+ liney = yoffset;
+ for(y=my2;y>omsl;y--) {
+
+ sn1= xs0>>16;
+ xs0+= dx0;
+
+ sn2= xs1>>16;
+ xs1+= dx1;
+
+ sn1++;
+
+ if(sn2>=rectx) sn2= rectx-1;
+ if(sn1<0) sn1= 0;
+ zverg= (int) CLAMPIS((sn1*zxd+zy0), INT_MIN, INT_MAX);
+
+ if ((sn1 < 0) || (sn1>imWidth) ) printf("\n sn1 exceeds line");
+ linex = xoffset + sn1;
+ liney = yoffset;
+
+ x= sn2-sn1;
+
+ while(x>=0) {
+ insertInEdgeBuffer(linex , liney, zverg); /* line y not needed here */
+ zverg+= zd;
+ linex++;
+ x--;
+ }
+ zy0-= zyd;
+ yoffset--;
+ }
+
+ if(xs3) {
+ xs0= xs1;
+ dx0= dx1;
+ }
+ if(xs0>xs2) {
+ xs3= xs0;
+ xs0= xs2;
+ xs2= xs3;
+ xs3= dx0;
+ dx0= dx2;
+ dx2= xs3;
+ }
+
+ for(; y>=my0; y--) {
+
+ sn1= xs0>>16;
+ xs0+= dx0;
+
+ sn2= xs2>>16;
+ xs2+= dx2;
+
+ sn1++;
+
+ if(sn2>=rectx) sn2= rectx-1;
+ if(sn1<0) sn1= 0;
+ zverg= (int) CLAMPIS((sn1*zxd+zy0), INT_MIN, INT_MAX);
+
+ linex = sn1;
+ liney = yoffset;
+
+ x= sn2-sn1;
+
+ while(x>=0) {
+ insertInEdgeBuffer(linex, liney, zverg); /* line y not needed here */
+ zverg+= zd;
+ linex++;
+ x--;
+ }
+ zy0-=zyd;
+ yoffset--;
+ }
+} /* end of void fillEdgeRenderFace(float *v1, float *v2, float *v3) */
+
+/* ------------------------------------------------------------------------- */
+
+void fillEdgeRenderEdge(float *vec1, float *vec2)
+{
+ int start, end, x, y, oldx, oldy, ofs;
+ int dz, vergz/* , mask */;
+ float dx, dy;
+ float v1[3], v2[3];
+ int linex, liney;
+ int xoffset, yoffset;
+
+
+ dx= vec2[0]-vec1[0];
+ dy= vec2[1]-vec1[1];
+
+ if(fabs(dx) > fabs(dy)) {
+
+ /* alle lijnen van links naar rechts */
+ if(vec1[0]<vec2[0]) {
+ VECCOPY(v1, vec1);
+ VECCOPY(v2, vec2);
+ }
+ else {
+ VECCOPY(v2, vec1);
+ VECCOPY(v1, vec2);
+ dx= -dx; dy= -dy;
+ }
+
+ start= floor(v1[0]);
+ end= start+floor(dx);
+ if(end >= imWidth) end = imWidth - 1;
+
+ oldy= floor(v1[1]);
+ dy/= dx;
+
+ vergz= v1[2];
+ dz= (v2[2]-v1[2])/dx;
+
+ yoffset = oldy;
+ xoffset = start;
+
+ if(dy<0) ofs= -imWidth;
+ else ofs= imWidth;
+
+ liney = yoffset;
+ linex = xoffset;
+
+ for(x= start; x<=end; x++, xoffset++) {
+
+ y= floor(v1[1]);
+ if(y!=oldy) {
+ oldy= y;
+ liney++;
+ }
+
+ if(x>=0 && y>=Aminy && y<=Amaxy) {
+ insertInEdgeBuffer(linex , liney, vergz);
+ }
+
+ v1[1]+= dy;
+ vergz+= dz;
+ }
+ }
+ else {
+
+ /* alle lijnen van onder naar boven */
+ if(vec1[1]<vec2[1]) {
+ VECCOPY(v1, vec1);
+ VECCOPY(v2, vec2);
+ }
+ else {
+ VECCOPY(v2, vec1);
+ VECCOPY(v1, vec2);
+ dx= -dx; dy= -dy;
+ }
+
+ start= floor(v1[1]);
+ end= start+floor(dy);
+
+ if(start>Amaxy || end<Aminy) return;
+
+ if(end>Amaxy) end= Amaxy;
+
+ oldx= floor(v1[0]);
+ dx/= dy;
+
+ vergz= v1[2];
+ dz= (v2[2]-v1[2])/dy;
+
+ yoffset = start;
+ xoffset = oldx;
+
+ if(dx<0) ofs= -1;
+ else ofs= 1;
+
+ linex = xoffset;
+ liney = yoffset;
+
+ for(y= start; y<=end; y++, liney++) {
+
+ x= floor(v1[0]);
+ if(x!=oldx) {
+ oldx= x;
+ linex += ofs;
+ }
+
+ if(x>=0 && y>=Aminy && (x < imWidth)) {
+ insertInEdgeBuffer(linex, liney, vergz);
+ }
+
+ v1[0]+= dx;
+ vergz+= dz;
+ }
+ }
+} /* End of void fillEdgeRenderEdge(float *vec1, float *vec2) */
+
+/* ------------------------------------------------------------------------- */
+
+/* eof edgeRender.c */
diff --git a/source/blender/render/intern/source/envmap.c b/source/blender/render/intern/source/envmap.c
new file mode 100644
index 00000000000..8aebe3670d0
--- /dev/null
+++ b/source/blender/render/intern/source/envmap.c
@@ -0,0 +1,689 @@
+
+/* envmap.c RENDER
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * may 1999
+ *
+ * $Id$
+ */
+
+#include <math.h>
+#include <string.h>
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+/* external modules: */
+#include "MEM_guardedalloc.h"
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h" /* for rectcpy */
+
+#include "DNA_texture_types.h"
+#include "DNA_image_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_texture_types.h"
+
+#include "BIF_space.h"
+#include "BIF_toolbox.h"
+
+#include "BKE_library.h"
+#include "BKE_main.h"
+#include "BKE_global.h"
+#include "BKE_world.h" // init_render_world
+#include "BKE_image.h" // BKE_write_ibuf
+
+
+/* this module */
+#include "RE_callbacks.h"
+#include "render.h"
+#include "render_intern.h"
+#include "envmap.h"
+#include "mydevice.h"
+#include "rendercore.h" /* calls zbufShade(DA).... I want to replace this with my own :)*/
+#include "renderHelp.h"
+#include "MTC_matrixops.h"
+#include "zbuf.h"
+
+/* ------------------------------------------------------------------------- */
+
+void envmap_split_ima(EnvMap *env);
+void envmap_renderdata(EnvMap *env);
+void envmap_transmatrix(float mat[][4], int part);
+void env_rotate_scene(float mat[][4], int mode);
+void env_layerflags(unsigned int notlay);
+void env_set_imats(void);
+void render_envmap(EnvMap *env);
+int envcube_isect(float *vec, float *answ);
+static void set_dxtdyt(float *dxts, float *dyts, float *dxt, float *dyt, int face);
+
+/* ------------------------------------------------------------------------- */
+
+EnvMap *RE_add_envmap(void)
+{
+ EnvMap *env;
+
+ env= MEM_callocN(sizeof(EnvMap), "envmap");
+ env->type= ENV_CUBE;
+ env->stype= ENV_STATIC;
+ env->clipsta= 0.1;
+ env->clipend= 100.0;
+ env->cuberes= 100;
+
+ return env;
+} /* end of EnvMap *RE_add_envmap() */
+
+/* ------------------------------------------------------------------------- */
+
+EnvMap *RE_copy_envmap(EnvMap *env)
+{
+ EnvMap *envn;
+ int a;
+
+ envn= MEM_dupallocN(env);
+ envn->ok= 0;
+ for(a=0; a<6; a++) envn->cube[a]= 0;
+ if(envn->ima) id_us_plus((ID *)envn->ima);
+
+ return envn;
+}
+
+/* ------------------------------------------------------------------------- */
+
+void RE_free_envmapdata(EnvMap *env)
+{
+ Image *ima;
+ int a, part;
+
+ for(part=0; part<6; part++) {
+ ima= env->cube[part];
+ if(ima) {
+ if(ima->ibuf) IMB_freeImBuf(ima->ibuf);
+
+ for(a=0; a<BLI_ARRAY_NELEMS(ima->mipmap); a++) {
+ if(ima->mipmap[a]) IMB_freeImBuf(ima->mipmap[a]);
+ }
+ MEM_freeN(ima);
+ env->cube[part]= 0;
+ }
+ }
+ env->ok= 0;
+}
+
+/* ------------------------------------------------------------------------- */
+
+void RE_free_envmap(EnvMap *env)
+{
+
+ RE_free_envmapdata(env);
+ MEM_freeN(env);
+
+}
+
+/* ------------------------------------------------------------------------- */
+
+void envmap_split_ima(EnvMap *env)
+{
+ ImBuf *ibuf;
+ Image *ima;
+/* extern rectcpy(); */
+ int dx, part;
+
+ RE_free_envmapdata(env);
+
+ dx= env->ima->ibuf->y;
+ dx/= 2;
+ if(3*dx != env->ima->ibuf->x) {
+ error("Incorrect envmap size");
+ env->ok= 0;
+ env->ima->ok= 0;
+ }
+ else {
+ for(part=0; part<6; part++) {
+ ibuf= IMB_allocImBuf(dx, dx, 24, IB_rect, 0);
+ ima= MEM_callocN(sizeof(Image), "image");
+ ima->ibuf= ibuf;
+ ima->ok= 1;
+ env->cube[part]= ima;
+ }
+ IMB_rectop(env->cube[0]->ibuf, env->ima->ibuf,
+ 0, 0, 0, 0, dx, dx, IMB_rectcpy, 0);
+ IMB_rectop(env->cube[1]->ibuf, env->ima->ibuf,
+ 0, 0, dx, 0, dx, dx, IMB_rectcpy, 0);
+ IMB_rectop(env->cube[2]->ibuf, env->ima->ibuf,
+ 0, 0, 2*dx, 0, dx, dx, IMB_rectcpy, 0);
+ IMB_rectop(env->cube[3]->ibuf, env->ima->ibuf,
+ 0, 0, 0, dx, dx, dx, IMB_rectcpy, 0);
+ IMB_rectop(env->cube[4]->ibuf, env->ima->ibuf,
+ 0, 0, dx, dx, dx, dx, IMB_rectcpy, 0);
+ IMB_rectop(env->cube[5]->ibuf, env->ima->ibuf,
+ 0, 0, 2*dx, dx, dx, dx, IMB_rectcpy, 0);
+ env->ok= 2;
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+/* ****************** RENDER ********************** */
+
+void envmap_renderdata(EnvMap *env)
+{
+ static RE_Render envR;
+ static Object *camera;
+
+ if(env) {
+ envR= R;
+ camera= G.scene->camera;
+
+ env->cuberes &= 0xFFFC;
+ R.rectx= R.r.xsch= R.recty= R.r.ysch= env->cuberes;
+ R.afmx= R.afmy= R.r.xsch/2;
+ R.xstart= R.ystart= -R.afmx;
+ R.xend= R.yend= R.xstart+R.rectx-1;
+
+ R.r.mode &= ~(R_BORDER | R_PANORAMA | R_ORTHO | R_MBLUR);
+ R.r.xparts= R.r.yparts= 1;
+ R.r.bufflag= 0;
+ R.r.size= 100;
+ R.ycor= 1.0;
+ R.r.yasp= R.r.xasp= 1;
+
+ R.near= env->clipsta;
+ R.far= env->clipend;
+
+ G.scene->camera= env->object;
+
+ }
+ else {
+ /* this to make sure init_renderdisplay works */
+ envR.winx= R.winx;
+ envR.winy= R.winy;
+ envR.winxof= R.winxof;
+ envR.winyof= R.winyof;
+
+ R= envR;
+ G.scene->camera= camera;
+ }
+
+}
+
+/* ------------------------------------------------------------------------- */
+
+void envmap_transmatrix(float mat[][4], int part)
+{
+ float tmat[4][4], eul[3], rotmat[4][4];
+
+ eul[0]= eul[1]= eul[2]= 0.0;
+
+ if(part==0) { /* neg z */
+ ;
+ } else if(part==1) { /* pos z */
+ eul[0]= M_PI;
+ } else if(part==2) { /* pos y */
+ eul[0]= M_PI/2.0;
+ } else if(part==3) { /* neg x */
+ eul[0]= M_PI/2.0;
+ eul[2]= M_PI/2.0;
+ } else if(part==4) { /* neg y */
+ eul[0]= M_PI/2.0;
+ eul[2]= M_PI;
+ } else { /* pos x */
+ eul[0]= M_PI/2.0;
+ eul[2]= -M_PI/2.0;
+ }
+
+ MTC_Mat4CpyMat4(tmat, mat);
+ EulToMat4(eul, rotmat);
+ MTC_Mat4MulSerie(mat, tmat, rotmat,
+ 0, 0, 0,
+ 0, 0, 0);
+}
+
+/* ------------------------------------------------------------------------- */
+
+void env_rotate_scene(float mat[][4], int mode)
+{
+ VlakRen *vlr = NULL;
+ VertRen *ver = NULL;
+ LampRen *lar = NULL;
+ HaloRen *har = NULL;
+ float xn, yn, zn, imat[3][3], pmat[4][4], smat[4][4], tmat[4][4];
+ int a;
+
+ if(mode==0) {
+ MTC_Mat4Invert(tmat, mat);
+ MTC_Mat3CpyMat4(imat, tmat);
+ }
+ else {
+ MTC_Mat4CpyMat4(tmat, mat);
+ MTC_Mat3CpyMat4(imat, mat);
+ }
+
+ for(a=0; a<R.totvert; a++) {
+ if((a & 255)==0) ver= R.blove[a>>8];
+ else ver++;
+
+ MTC_Mat4MulVecfl(tmat, ver->co);
+
+ xn= ver->n[0];
+ yn= ver->n[1];
+ zn= ver->n[2];
+ /* geen transpose ! */
+ ver->n[0]= imat[0][0]*xn+imat[1][0]*yn+imat[2][0]*zn;
+ ver->n[1]= imat[0][1]*xn+imat[1][1]*yn+imat[2][1]*zn;
+ ver->n[2]= imat[0][2]*xn+imat[1][2]*yn+imat[2][2]*zn;
+ Normalise(ver->n);
+ }
+
+ for(a=0; a<R.tothalo; a++) {
+ if((a & 255)==0) har= R.bloha[a>>8];
+ else har++;
+
+ MTC_Mat4MulVecfl(tmat, har->co);
+ }
+
+ for(a=0; a<R.totvlak; a++) {
+ if((a & 255)==0) vlr= R.blovl[a>>8];
+ else vlr++;
+
+ xn= vlr->n[0];
+ yn= vlr->n[1];
+ zn= vlr->n[2];
+ /* geen transpose ! */
+ vlr->n[0]= imat[0][0]*xn+imat[1][0]*yn+imat[2][0]*zn;
+ vlr->n[1]= imat[0][1]*xn+imat[1][1]*yn+imat[2][1]*zn;
+ vlr->n[2]= imat[0][2]*xn+imat[1][2]*yn+imat[2][2]*zn;
+ Normalise(vlr->n);
+ }
+
+ set_normalflags();
+
+ for(a=0; a<R.totlamp; a++) {
+ lar= R.la[a];
+
+ /* smat should actually be a 3x3 matrix, the 4x4 declaration is */
+ /* just for confusion. */
+
+ /* Only the left-top 3x3 is copied...? smat is 4by4! imat is 3x3 */
+ /* Actually, it is not: Mat3CpyMat3 copies the first 9 floats! */
+ /* What should happen is mat4cpymat3 */
+/* Mat3CpyMat3(smat, lar->imat); */
+ MTC_Mat4CpyMat3nc(smat, lar->imat);
+ /* This would be lar->imat = smat * imat, so 3d = 4d * 3d? */
+ /* the mat3mulmat3 does a multiply on the wrong elements.... */
+/* Mat3MulMat3(lar->imat, smat, imat); */
+ MTC_Mat4MulMat33(lar->imat, smat, imat);
+ MTC_Mat3MulVecfl(imat, lar->vec);
+ MTC_Mat4MulVecfl(tmat, lar->co);
+
+ lar->sh_invcampos[0]= -lar->co[0];
+ lar->sh_invcampos[1]= -lar->co[1];
+ lar->sh_invcampos[2]= -lar->co[2];
+ MTC_Mat3MulVecfl(lar->imat, lar->sh_invcampos);
+ lar->sh_invcampos[2]*= lar->sh_zfac;
+
+ if(lar->shb) {
+ if(mode==1) {
+ MTC_Mat4Invert(pmat, mat);
+ MTC_Mat4MulMat4(smat, pmat, lar->shb->viewmat);
+ MTC_Mat4MulMat4(lar->shb->persmat, smat, lar->shb->winmat);
+ }
+ else MTC_Mat4MulMat4(lar->shb->persmat, lar->shb->viewmat, lar->shb->winmat);
+ }
+ }
+
+}
+
+/* ------------------------------------------------------------------------- */
+
+void env_layerflags(unsigned int notlay)
+{
+ VlakRen *vlr = NULL;
+ int a;
+
+ for(a=0; a<R.totvlak; a++) {
+ if((a & 255)==0) vlr= R.blovl[a>>8];
+ else vlr++;
+ if(vlr->lay & notlay) vlr->flag &= ~R_VISIBLE;
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
+void env_set_imats()
+{
+ Base *base;
+ float mat[4][4];
+
+ base= G.scene->base.first;
+ while(base) {
+ MTC_Mat4MulMat4(mat, base->object->obmat, R.viewmat);
+ MTC_Mat4Invert(base->object->imat, mat);
+
+ base= base->next;
+ }
+
+}
+
+/* ------------------------------------------------------------------------- */
+
+void render_envmap(EnvMap *env)
+{
+ /* only the cubemap is implemented */
+ ImBuf *ibuf;
+ Image *ima;
+ float oldviewinv[4][4], mat[4][4], tmat[4][4];
+ short part;
+
+ /* need a recalc: ortho-render has no correct viewinv */
+ MTC_Mat4Invert(oldviewinv, R.viewmat);
+
+ /* setup necessary globals */
+ envmap_renderdata(env);
+
+ RE_local_init_render_display();
+
+ R.rectot= MEM_mallocN(sizeof(int)*R.rectx*R.recty, "rectot");
+ R.rectz= MEM_mallocN(sizeof(int)*R.rectx*R.recty, "rectz");
+
+ for(part=0; part<6; part++) {
+
+ RE_local_clear_render_display(R.win);
+ fillrect(R.rectot, R.rectx, R.recty, 0);
+
+ RE_setwindowclip(1,-1); /* geen jit:(-1) */
+
+ MTC_Mat4CpyMat4(tmat, G.scene->camera->obmat);
+ MTC_Mat4Ortho(tmat);
+ envmap_transmatrix(tmat, part);
+ MTC_Mat4Invert(mat, tmat);
+ /* mat now is the camera 'viewmat' */
+
+ MTC_Mat4CpyMat4(R.viewmat, mat);
+ MTC_Mat4CpyMat4(R.viewinv, tmat);
+
+ /* we have to correct for the already rotated vertexcoords */
+ MTC_Mat4MulMat4(tmat, oldviewinv, R.viewmat);
+ MTC_Mat4Invert(env->imat, tmat);
+
+ env_rotate_scene(tmat, 1);
+ init_render_world();
+ setzbufvlaggen(RE_projectverto);
+ env_layerflags(env->notlay);
+ env_set_imats();
+
+ if(RE_local_test_break()==0) {
+
+ RE_local_printrenderinfo(0.0, part);
+
+ if(R.r.mode & R_OSA) zbufshadeDA();
+ else zbufshade();
+
+ }
+
+ /* rotate back */
+ env_rotate_scene(tmat, 0);
+
+ if(RE_local_test_break()==0) {
+ ibuf= IMB_allocImBuf(R.rectx, R.recty, 24, IB_rect, 0);
+ ima= MEM_callocN(sizeof(Image), "image");
+ memcpy(ibuf->rect, R.rectot, 4*ibuf->x*ibuf->y);
+ ima->ibuf= ibuf;
+ ima->ok= 1;
+ env->cube[part]= ima;
+ }
+
+ if(RE_local_test_break()) break;
+
+ }
+
+ if(R.rectz) MEM_freeN(R.rectz); R.rectz= 0;
+ if(R.rectot) MEM_freeN(R.rectot); R.rectot= 0;
+
+ if(RE_local_test_break()) RE_free_envmapdata(env);
+ else {
+ if(R.r.mode & R_OSA) env->ok= ENV_OSA;
+ else env->ok= ENV_NORMAL;
+ env->lastframe= G.scene->r.cfra;
+ }
+
+ /* restore */
+ envmap_renderdata(0);
+ env_set_imats();
+ init_render_world();
+
+}
+
+/* ------------------------------------------------------------------------- */
+
+void make_envmaps()
+{
+ Tex *tex;
+ int do_init= 0;
+
+ tex= G.main->tex.first;
+ while(tex) {
+ if(tex->id.us && tex->type==TEX_ENVMAP) {
+ if(tex->env && tex->env->object) {
+ if(tex->env->object->lay & G.scene->lay) {
+ if(tex->env->stype!=ENV_LOAD) {
+
+ if(tex->env->ok==0) {
+ do_init= 1;
+ render_envmap(tex->env);
+ }
+ else if((R.r.mode & R_OSA) && tex->env->ok==ENV_NORMAL) {
+ do_init= 1;
+ RE_free_envmapdata(tex->env);
+ render_envmap(tex->env);
+ }
+ }
+ }
+ }
+ }
+ tex= tex->id.next;
+ }
+
+ if(do_init) {
+ RE_local_init_render_display();
+ RE_local_clear_render_display(R.win);
+ allqueue(REDRAWBUTSTEX, 0);
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
+int envcube_isect(float *vec, float *answ)
+{
+ float labda;
+ int face;
+
+ /* which face */
+ if( vec[2]<=-fabs(vec[0]) && vec[2]<=-fabs(vec[1]) ) {
+ face= 0;
+ labda= -1.0/vec[2];
+ answ[0]= labda*vec[0];
+ answ[1]= labda*vec[1];
+ }
+ else if( vec[2]>=fabs(vec[0]) && vec[2]>=fabs(vec[1]) ) {
+ face= 1;
+ labda= 1.0/vec[2];
+ answ[0]= labda*vec[0];
+ answ[1]= -labda*vec[1];
+ }
+ else if( vec[1]>=fabs(vec[0]) ) {
+ face= 2;
+ labda= 1.0/vec[1];
+ answ[0]= labda*vec[0];
+ answ[1]= labda*vec[2];
+ }
+ else if( vec[0]<=-fabs(vec[1]) ) {
+ face= 3;
+ labda= -1.0/vec[0];
+ answ[0]= labda*vec[1];
+ answ[1]= labda*vec[2];
+ }
+ else if( vec[1]<=-fabs(vec[0]) ) {
+ face= 4;
+ labda= -1.0/vec[1];
+ answ[0]= -labda*vec[0];
+ answ[1]= labda*vec[2];
+ }
+ else {
+ face= 5;
+ labda= 1.0/vec[0];
+ answ[0]= -labda*vec[1];
+ answ[1]= labda*vec[2];
+ }
+ answ[0]= 0.5+0.5*answ[0];
+ answ[1]= 0.5+0.5*answ[1];
+ return face;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static void set_dxtdyt(float *dxts, float *dyts, float *dxt, float *dyt, int face)
+{
+ if(face==2 || face==4) {
+ dxts[0]= dxt[0];
+ dyts[0]= dyt[0];
+ dxts[1]= dxt[2];
+ dyts[1]= dyt[2];
+ }
+ else if(face==3 || face==5) {
+ dxts[0]= dxt[1];
+ dxts[1]= dxt[2];
+ dyts[0]= dyt[1];
+ dyts[1]= dyt[2];
+ }
+ else {
+ dxts[0]= dxt[0];
+ dyts[0]= dyt[0];
+ dxts[1]= dxt[1];
+ dyts[1]= dyt[1];
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
+extern float Tin, Ta, Tr, Tg, Tb; /* texture.c */
+int RE_envmaptex(Tex *tex, float *texvec, float *dxt, float *dyt)
+{
+ /* texvec should be the already reflected normal */
+ EnvMap *env;
+ float fac, vec[3], sco[3], col[20], dxts[3], dyts[3];
+ int face, face1;
+
+ env= tex->env;
+ if(env==0 || env->object==0) return 0;
+
+ if(env->stype==ENV_LOAD) {
+ env->ima= tex->ima;
+ if(env->ima && env->ima->ok) {
+ if(env->ima->ibuf==0) ima_ibuf_is_nul(tex);
+ if(env->ima->ok && env->ok==0) envmap_split_ima(env);
+ }
+ }
+
+ if(env->ok==0) {
+
+ Tin= 0.0;
+ return 0;
+ }
+
+ /* rotate to envmap space */
+ VECCOPY(vec, texvec);
+ MTC_Mat4Mul3Vecfl(env->object->imat, vec);
+
+ face= envcube_isect(vec, sco);
+ tex->ima= env->cube[face];
+
+ if(R.osatex) {
+ MTC_Mat4Mul3Vecfl(env->object->imat, dxt);
+ MTC_Mat4Mul3Vecfl(env->object->imat, dyt);
+
+ set_dxtdyt(dxts, dyts, dxt, dyt, face);
+ imagewraposa(tex, sco, dxts, dyts);
+
+ /* edges? */
+
+ if(Ta<1.0) {
+ col[0]= Ta; col[1]= Tr; col[2]= Tg; col[3]= Tb;
+
+ VecAddf(vec, vec, dxt);
+ face1= envcube_isect(vec, sco);
+ VecSubf(vec, vec, dxt);
+
+ if(face!=face1) {
+ tex->ima= env->cube[face1];
+ set_dxtdyt(dxts, dyts, dxt, dyt, face1);
+ imagewraposa(tex, sco, dxts, dyts);
+ col[4]= Ta; col[5]= Tr; col[6]= Tg; col[7]= Tb;
+ }
+ else col[4]= col[5]= col[6]= col[7]= 0.0;
+
+ /* here was the nasty bug! col[5,6,7] were not zero-ed. FPE! */
+
+ VecAddf(vec, vec, dyt);
+ face1= envcube_isect(vec, sco);
+ VecSubf(vec, vec, dyt);
+
+ if(face!=face1) {
+ tex->ima= env->cube[face1];
+ set_dxtdyt(dxts, dyts, dxt, dyt, face1);
+ imagewraposa(tex, sco, dxts, dyts);
+ col[8]= Ta; col[9]= Tr; col[10]= Tg; col[11]= Tb;
+ }
+ else col[8]= col[9]= col[10]= col[11]= 0.0;
+
+ fac= (col[0]+col[4]+col[8]);
+ fac= 1.0/fac;
+
+ Tr= fac*(col[0]*col[1] + col[4]*col[5] + col[8]*col[9] );
+ Tg= fac*(col[0]*col[2] + col[4]*col[6] + col[8]*col[10] );
+ Tb= fac*(col[0]*col[3] + col[4]*col[7] + col[8]*col[11] );
+ Ta= 1.0;
+
+ }
+ }
+ else {
+ imagewrap(tex, sco);
+ }
+
+ tex->ima= env->ima;
+
+ return 1;
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* eof */
diff --git a/source/blender/render/intern/source/errorHandler.c b/source/blender/render/intern/source/errorHandler.c
new file mode 100644
index 00000000000..fc21ee272c4
--- /dev/null
+++ b/source/blender/render/intern/source/errorHandler.c
@@ -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 *****
+ * Error handler for the rendering code. Maybe also useful elsewhere?
+ */
+
+#include "GEN_messaging.h"
+#include "stdio.h"
+#include "errorHandler.h"
+
+#include "render_intern.h"
+
+/* ------------------------------------------------------------------------- */
+
+/* counters for error handling */
+static int lastError; /* code of last encountered error */
+static int errorCount; /* count how many time it occured */
+/* ------------------------------------------------------------------------- */
+
+char errorStrings[RE_MAX_ERROR][100] = {
+ "0: No error",
+ "1: recalculated depth falls outside original range",
+ "2: invalid face/halo type",
+ "3: invalid face index",
+ "4: invalid data pointer",
+ "5: generic trace counter",
+ "6: overflow on z buffer depth",
+ "7: write outside edgerender buffer",
+ "8: cannot allocate memory",
+ "9: write outside colour target buffer",
+};
+
+/* ------------------------------------------------------------------------- */
+
+void RE_errortrace_reset(void)
+{
+ lastError = RE_NO_ERROR;
+ errorCount = 0;
+}
+
+void RE_error(int errType, char* fname)
+{
+ /*
+ * This memory behaviour should move to the generic stream...
+ */
+
+ if (lastError == errType) {
+ int teller;
+ errorCount++;
+ for (teller = 0; teller < 12; teller++)
+ fprintf(GEN_errorstream, "%c", 0x08); /* backspaces */
+ fprintf(GEN_errorstream, "( %8u )", errorCount);
+ } else {
+ fprintf(GEN_errorstream, "\n*** %s: %s ",
+ fname, errorStrings[errType]);
+ lastError = errType;
+ errorCount = 1;
+ }
+} /* end of void RE_error(int errType, char* errText) */
+
+/* ------------------------------------------------------------------------- */
+/* note: non-repeating */
+void RE_error_int(int errType, char* fname, int value)
+{
+ fprintf(GEN_errorstream, "\n*** %s: %s : %d",
+ fname, errorStrings[errType], value);
+ lastError = RE_NO_ERROR;
+} /* end of void RE_error_int(int errType, char* errText, int value) */
+
+/* ------------------------------------------------------------------------- */
+
+/* eof */
diff --git a/source/blender/render/intern/source/gammaCorrectionTables.c b/source/blender/render/intern/source/gammaCorrectionTables.c
new file mode 100644
index 00000000000..b25e7f0cdca
--- /dev/null
+++ b/source/blender/render/intern/source/gammaCorrectionTables.c
@@ -0,0 +1,168 @@
+/**
+ * Jitter offset table
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "gammaCorrectionTables.h"
+#include <stdlib.h>
+#include <math.h>
+
+#include "render_intern.h"
+
+/* There are two parts here: one for the old renderer, one for the unified */
+/* renderer. we start with the latter. */
+
+/* Default gamma. For most CRTs, gamma ranges from 2.2 to 2.5 (Foley), so */
+/* 2.35 seems appropriate enough. Experience teaches a different number */
+/* though. Old blender: 2.0. It might be nice to make this a slider */
+#define RE_DEFAULT_GAMMA 2.0
+/* This 400 is sort of based on the number of intensity levels needed for */
+/* the typical dynamic range of a medium, in this case CRTs. (Foley) */
+/* (Actually, it says the number should be between 400 and 535.) */
+#define RE_GAMMA_TABLE_SIZE 400
+
+/* These indicate the status of the gamma lookup table --------------------- */
+
+static float gamma_range_table[RE_GAMMA_TABLE_SIZE + 1];
+static float gamfactor_table[RE_GAMMA_TABLE_SIZE];
+static float inv_gamma_range_table[RE_GAMMA_TABLE_SIZE + 1];
+static float inv_gamfactor_table[RE_GAMMA_TABLE_SIZE];
+static float colour_domain_table[RE_GAMMA_TABLE_SIZE + 1];
+static float colour_step;
+static float inv_colour_step;
+static float valid_gamma;
+static float valid_inv_gamma;
+static int gamma_table_initialised = 0;
+static int do_gamma;
+/* ------------------------------------------------------------------------- */
+
+float gammaCorrect(float c)
+{
+ int i;
+ float res = 0.0;
+
+ i = floor(c * inv_colour_step);
+ /* Clip to range [0,1]: outside, just do the complete calculation. */
+ /* We may have some performance problems here. Stretching up the LUT */
+ /* may help solve that, by exchanging LUT size for the interpolation. */
+ /* Negative colours are explicitly handled. */
+ if (i < 0) res = -pow(abs(c), valid_gamma);
+ else if (i >= RE_GAMMA_TABLE_SIZE ) res = pow(c, valid_gamma);
+ else res = gamma_range_table[i] +
+ ( (c - colour_domain_table[i]) * gamfactor_table[i]);
+
+ return res;
+} /* end of float gammaCorrect(float col) */
+
+/* ------------------------------------------------------------------------- */
+
+float invGammaCorrect(float col)
+{
+ int i;
+ float res = 0.0;
+
+ i = floor(col*inv_colour_step);
+ /* Negative colours are explicitly handled. */
+ if (i < 0) res = -pow(abs(col), valid_inv_gamma);
+ else if (i >= RE_GAMMA_TABLE_SIZE) res = pow(col, valid_inv_gamma);
+ else res = inv_gamma_range_table[i] +
+ ( (col - colour_domain_table[i]) * inv_gamfactor_table[i]);
+
+ return res;
+} /* end of float invGammaCorrect(float col) */
+
+
+/* ------------------------------------------------------------------------- */
+
+void makeGammaTables(float gamma)
+{
+ /* we need two tables: one forward, one backward */
+ int i;
+
+ valid_gamma = gamma;
+ valid_inv_gamma = 1.0 / gamma;
+ colour_step = 1.0 / RE_GAMMA_TABLE_SIZE;
+ inv_colour_step = (float) RE_GAMMA_TABLE_SIZE;
+
+ /* We could squeeze out the two range tables to gain some memory. */
+ for (i = 0; i < RE_GAMMA_TABLE_SIZE; i++) {
+ colour_domain_table[i] = i * colour_step;
+ gamma_range_table[i] = pow(colour_domain_table[i],
+ valid_gamma);
+ inv_gamma_range_table[i] = pow(colour_domain_table[i],
+ valid_inv_gamma);
+ }
+
+ /* The end of the table should match 1.0 carefully. In order to avoid */
+ /* rounding errors, we just set this explicitly. The last segment may */
+ /* have a different lenght than the other segments, but our */
+ /* interpolation is insensitive to that. */
+ colour_domain_table[RE_GAMMA_TABLE_SIZE] = 1.0;
+ gamma_range_table[RE_GAMMA_TABLE_SIZE] = 1.0;
+ inv_gamma_range_table[RE_GAMMA_TABLE_SIZE] = 1.0;
+
+ /* To speed up calculations, we make these calc factor tables. They are */
+ /* multiplication factors used in scaling the interpolation. */
+ for (i = 0; i < RE_GAMMA_TABLE_SIZE; i++ ) {
+ gamfactor_table[i] = inv_colour_step
+ * (gamma_range_table[i + 1] - gamma_range_table[i]) ;
+ inv_gamfactor_table[i] = inv_colour_step
+ * (inv_gamma_range_table[i + 1] - inv_gamma_range_table[i]) ;
+ }
+
+ gamma_table_initialised = 1;
+} /* end of void makeGammaTables(float gamma) */
+
+/* ------------------------------------------------------------------------- */
+
+int gammaTableIsInitialised(void)
+{
+ return gamma_table_initialised;
+}
+
+/* ------------------------------------------------------------------------- */
+int doGamma()
+{
+ return do_gamma;
+}
+
+/* ------------------------------------------------------------------------- */
+
+/**
+ * Set/unset performing gamma corrections.
+ */
+void setDoGamma(int i)
+{
+ do_gamma = i;
+}
+
+/* eof */
diff --git a/source/blender/render/intern/source/initrender.c b/source/blender/render/intern/source/initrender.c
new file mode 100644
index 00000000000..67fddc271e6
--- /dev/null
+++ b/source/blender/render/intern/source/initrender.c
@@ -0,0 +1,1329 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+
+/* Global includes */
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "PIL_time.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+#include "BLI_rand.h"
+
+#include "MTC_matrixops.h"
+
+#include "DNA_image_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_object_types.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_global.h"
+#include "BKE_material.h"
+#include "BKE_object.h"
+#include "BKE_image.h"
+#include "BKE_ipo.h"
+#include "BKE_key.h"
+#include "BKE_ika.h"
+#include "BKE_action.h"
+#include "BKE_writeavi.h"
+#include "BKE_scene.h"
+
+#include "BIF_toolbox.h"
+#include "BIF_writeavicodec.h"
+#include "BIF_writemovie.h" /* start_movie(), append_movie(), end_movie() */
+
+#include "BSE_drawview.h"
+#include "BSE_sequence.h"
+
+/* this module */
+#include "render.h"
+#include "render_intern.h"
+
+#include "RE_callbacks.h"
+#include "zbuf.h"
+#include "rendercore.h" /* part handler for the old renderer, shading functions */
+#include "renderPreAndPost.h"
+#include "outerRenderLoop.h"
+#include "renderHelp.h"
+#include "jitter.h"
+
+/* Own includes */
+#include "initrender.h"
+
+/* Some crud :/ */
+#define ELEM3(a, b, c, d) ( ELEM(a, b, c) || (a)==(d) )
+
+
+/* uit render.c */
+extern float fmask[256], centLut[16];
+extern unsigned short *mask1[9], *mask2[9], /* *igamtab1, */ *igamtab2/*, *gamtab */;
+extern char cmask[256], *centmask;
+
+Material defmaterial;
+short pa; /* pa is globaal part ivm print */
+short allparts[65][4];
+int qscount;
+
+/* ********************* *********************** */
+
+
+void init_def_material(void)
+{
+ Material *ma;
+
+ ma= &defmaterial;
+
+ init_material(&defmaterial);
+
+ init_render_material(ma);
+}
+
+void RE_init_render_data(void)
+{
+ memset(&R, 0, sizeof(RE_Render));
+ memset(&O, 0, sizeof(Osa));
+ O.dxwin[0]= 1.0;
+ O.dywin[1]= 1.0;
+
+ R.blove= (VertRen **)MEM_callocN(sizeof(void *)*(MAXVERT>>8),"Blove");
+ R.blovl= (VlakRen **)MEM_callocN(sizeof(void *)*(MAXVLAK>>8),"Blovl");
+ R.bloha= (HaloRen **)MEM_callocN(sizeof(void *)*(MAXVERT>>8),"Bloha");
+ R.la= (LampRen **)MEM_mallocN(MAXLAMP*sizeof(void *),"renderlamparray");
+
+ init_def_material();
+}
+
+void RE_free_render_data()
+{
+ MEM_freeN(R.blove);
+ R.blove= 0;
+ MEM_freeN(R.blovl);
+ R.blovl= 0;
+ MEM_freeN(R.bloha);
+ R.bloha= 0;
+ MEM_freeN(R.la);
+ R.la= 0;
+ if(R.rectot) MEM_freeN(R.rectot);
+ if(R.rectz) MEM_freeN(R.rectz);
+ if(R.rectspare) MEM_freeN(R.rectspare);
+ R.rectot= 0;
+ R.rectz= 0;
+ R.rectspare= 0;
+
+ end_render_material(&defmaterial);
+}
+
+/* ****************** GAMMA, MASKERS en LUTS **************** */
+
+float calc_weight(float *weight, int i, int j)
+{
+ float x, y, dist, totw= 0.0;
+ int a;
+
+ for(a=0; a<R.osa; a++) {
+ x= jit[a][0]-0.5+ i;
+ y= jit[a][1]-0.5+ j;
+ dist= sqrt(x*x+y*y);
+
+ weight[a]= 0.0;
+
+ if(R.r.mode & R_GAUSS) {
+ if(dist<1.5) {
+ x = dist*1.5;
+ weight[a]= (1.0/exp(x*x) - 1.0/exp(1.5*1.5*1.5*1.5));
+ }
+ }
+ else {
+ if(i==0 && j==0) weight[a]= 1.0;
+ }
+
+ totw+= weight[a];
+
+ }
+ return totw;
+}
+
+void RE_init_filt_mask(void)
+{
+ static int firsttime=1;
+ static float lastgamma= 0.0;
+ float gamma, igamma;
+ float weight[32], totw, val, *fpx1, *fpx2, *fpy1, *fpy2;
+ int i, j, a;
+ unsigned short *m1, *m2, shweight[32];
+
+ if(firsttime) {
+ for(a=0; a<9;a++) {
+ mask1[a]= MEM_mallocN(256*sizeof(short), "initfilt");
+ mask2[a]= MEM_mallocN(256*sizeof(short), "initfilt");
+ }
+ for(a=0; a<256; a++) {
+ cmask[a]= 0;
+ if(a & 1) cmask[a]++;
+ if(a & 2) cmask[a]++;
+ if(a & 4) cmask[a]++;
+ if(a & 8) cmask[a]++;
+ if(a & 16) cmask[a]++;
+ if(a & 32) cmask[a]++;
+ if(a & 64) cmask[a]++;
+ if(a & 128) cmask[a]++;
+ }
+ centmask= MEM_mallocN(65536, "Initfilt3");
+ for(a=0; a<16; a++) {
+ centLut[a]= -0.45+((float)a)/16.0;
+ }
+
+ gamtab= MEM_mallocN(65536*sizeof(short), "initGaus2");
+ igamtab1= MEM_mallocN(256*sizeof(short), "initGaus2");
+ igamtab2= MEM_mallocN(65536*sizeof(short), "initGaus2");
+
+ }
+
+ if(R.r.alphamode==R_ALPHAKEY) gamma= 1.0; /* ??? */
+
+ if(R.r.mode & R_GAMMA) gamma= 2.0;
+ else gamma= 1.0;
+ igamma= 1.0/gamma;
+
+ if(gamma!= lastgamma) {
+ lastgamma= gamma;
+
+ /* gamtab: in short, uit short */
+ for(a=0; a<65536; a++) {
+ val= a;
+ val/= 65535.0;
+
+ if(gamma==2.0) val= sqrt(val);
+ else if(gamma!=1.0) val= pow(val, igamma);
+
+ gamtab[a]= (65535.99*val);
+ }
+ /* inv gamtab1 : in byte, uit short */
+ for(a=1; a<=256; a++) {
+ if(gamma==2.0) igamtab1[a-1]= a*a-1;
+ else if(gamma==1.0) igamtab1[a-1]= 256*a-1;
+ else {
+ val= a/256.0;
+ igamtab1[a-1]= (65535.0*pow(val, gamma)) -1 ;
+ }
+ }
+
+ /* inv gamtab2 : in short, uit short */
+ for(a=0; a<65536; a++) {
+ val= a;
+ val/= 65535.0;
+ if(gamma==2.0) val= val*val;
+ else val= pow(val, gamma);
+
+ igamtab2[a]= 65535.0*val;
+ }
+ }
+
+ if(firsttime) {
+ firsttime= 0;
+ return;
+ }
+
+ val= 1.0/((float)R.osa);
+ for(a=0; a<256; a++) {
+ fmask[a]= ((float)cmask[a])*val;
+ }
+
+ for(a=0; a<9;a++) {
+ memset(mask1[a], 0, 256*2);
+ memset(mask2[a], 0, 256*2);
+ }
+
+ /* bereken totw */
+ totw= 0.0;
+ for(j= -1; j<2; j++) {
+ for(i= -1; i<2; i++) {
+ totw+= calc_weight(weight, i, j);
+ }
+ }
+
+ for(j= -1; j<2; j++) {
+ for(i= -1; i<2; i++) {
+ /* bereken ahv jit met ofset de gewichten */
+
+ memset(weight, 0, 32*2);
+ calc_weight(weight, i, j);
+
+ for(a=0; a<16; a++) shweight[a]= weight[a]*(65535.0/totw);
+
+ m1= mask1[ 3*(j+1)+i+1 ];
+ m2= mask2[ 3*(j+1)+i+1 ];
+
+ for(a=0; a<256; a++) {
+ if(a & 1) {
+ m1[a]+= shweight[0];
+ m2[a]+= shweight[8];
+ }
+ if(a & 2) {
+ m1[a]+= shweight[1];
+ m2[a]+= shweight[9];
+ }
+ if(a & 4) {
+ m1[a]+= shweight[2];
+ m2[a]+= shweight[10];
+ }
+ if(a & 8) {
+ m1[a]+= shweight[3];
+ m2[a]+= shweight[11];
+ }
+ if(a & 16) {
+ m1[a]+= shweight[4];
+ m2[a]+= shweight[12];
+ }
+ if(a & 32) {
+ m1[a]+= shweight[5];
+ m2[a]+= shweight[13];
+ }
+ if(a & 64) {
+ m1[a]+= shweight[6];
+ m2[a]+= shweight[14];
+ }
+ if(a & 128) {
+ m1[a]+= shweight[7];
+ m2[a]+= shweight[15];
+ }
+ }
+ }
+ }
+
+ /* centmask: de juiste subpixel ofset per masker */
+
+ fpx1= MEM_mallocN(256*sizeof(float), "initgauss4");
+ fpx2= MEM_mallocN(256*sizeof(float), "initgauss4");
+ fpy1= MEM_mallocN(256*sizeof(float), "initgauss4");
+ fpy2= MEM_mallocN(256*sizeof(float), "initgauss4");
+ for(a=0; a<256; a++) {
+ fpx1[a]= fpx2[a]= 0.0;
+ fpy1[a]= fpy2[a]= 0.0;
+ if(a & 1) {
+ fpx1[a]+= jit[0][0];
+ fpy1[a]+= jit[0][1];
+ fpx2[a]+= jit[8][0];
+ fpy2[a]+= jit[8][1];
+ }
+ if(a & 2) {
+ fpx1[a]+= jit[1][0];
+ fpy1[a]+= jit[1][1];
+ fpx2[a]+= jit[9][0];
+ fpy2[a]+= jit[9][1];
+ }
+ if(a & 4) {
+ fpx1[a]+= jit[2][0];
+ fpy1[a]+= jit[2][1];
+ fpx2[a]+= jit[10][0];
+ fpy2[a]+= jit[10][1];
+ }
+ if(a & 8) {
+ fpx1[a]+= jit[3][0];
+ fpy1[a]+= jit[3][1];
+ fpx2[a]+= jit[11][0];
+ fpy2[a]+= jit[11][1];
+ }
+ if(a & 16) {
+ fpx1[a]+= jit[4][0];
+ fpy1[a]+= jit[4][1];
+ fpx2[a]+= jit[12][0];
+ fpy2[a]+= jit[12][1];
+ }
+ if(a & 32) {
+ fpx1[a]+= jit[5][0];
+ fpy1[a]+= jit[5][1];
+ fpx2[a]+= jit[13][0];
+ fpy2[a]+= jit[13][1];
+ }
+ if(a & 64) {
+ fpx1[a]+= jit[6][0];
+ fpy1[a]+= jit[6][1];
+ fpx2[a]+= jit[14][0];
+ fpy2[a]+= jit[14][1];
+ }
+ if(a & 128) {
+ fpx1[a]+= jit[7][0];
+ fpy1[a]+= jit[7][1];
+ fpx2[a]+= jit[15][0];
+ fpy2[a]+= jit[15][1];
+ }
+ }
+
+ for(a= (1<<R.osa)-1; a>0; a--) {
+ val= count_mask(a);
+ i= (15.9*(fpy1[a & 255]+fpy2[a>>8])/val);
+ i<<=4;
+ i+= (15.9*(fpx1[a & 255]+fpx2[a>>8])/val);
+ centmask[a]= i;
+ }
+
+ MEM_freeN(fpx1);
+ MEM_freeN(fpx2);
+ MEM_freeN(fpy1);
+ MEM_freeN(fpy2);
+
+}
+
+void RE_free_filt_mask()
+{
+ int a;
+
+ for(a=0; a<9; a++) {
+ MEM_freeN(mask1[a]);
+ MEM_freeN(mask2[a]);
+ }
+ MEM_freeN(gamtab);
+ MEM_freeN(igamtab1);
+ MEM_freeN(igamtab2);
+
+ MEM_freeN(centmask);
+}
+
+/* add stuff */
+
+
+void defaultlamp()
+{
+ LampRen *lar;
+
+ lar= (LampRen *)MEM_callocN(sizeof(LampRen),"lampren");
+ R.la[R.totlamp++]=lar;
+
+ lar->type= LA_SUN;
+ lar->vec[0]= -R.viewmat[2][0];
+ lar->vec[1]= -R.viewmat[2][1];
+ lar->vec[2]= -R.viewmat[2][2];
+ Normalise(lar->vec);
+ lar->r= 1.0;
+ lar->g= 1.0;
+ lar->b= 1.0;
+ lar->lay= 65535;
+}
+
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+void RE_make_existing_file(char *name)
+{
+ char di[FILE_MAXDIR], fi[FILE_MAXFILE];
+
+ strcpy(di, name);
+ BLI_splitdirstring(di, fi);
+
+ /* exist testen */
+ if (BLI_exists(di) == 0) {
+ BLI_recurdir_fileops(di);
+ }
+}
+
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+extern float holoofs; /* render.c */
+void RE_setwindowclip(int mode, int jmode)
+{
+ /* jmode>=0: alleen jitter doen, anders berekenen */
+ /* mode==1 zet persmat en grvec */
+ Camera *cam=0;
+ float lens, fac, minx, miny, maxx, maxy;
+ float xd, yd, afmx, afmy;
+
+ if(G.scene->camera==0) return;
+
+ afmx= R.afmx;
+ afmy= R.afmy;
+
+ if(mode) {
+
+ if(G.scene->camera->type==OB_LAMP) {
+ /* fac= cos( PI*((float)(256- la->spsi))/512.0 ); */
+
+ /* phi= acos(fac); */
+ /* lens= 16.0*fac/sin(phi); */
+ lens= 35.0;
+ R.near= 0.1;
+ R.far= 1000.0;
+ }
+ else if(G.scene->camera->type==OB_CAMERA) {
+ cam= G.scene->camera->data;
+
+ lens= cam->lens;
+ R.near= cam->clipsta;
+ R.far= cam->clipend;
+ }
+ else {
+ lens= 16.0;
+ }
+
+ if( (R.r.xasp*afmx) >= (R.r.yasp*afmy) ) {
+ R.viewfac= (afmx*lens)/16.0;
+ }
+ else {
+ R.viewfac= R.ycor*(afmy*lens)/16.0;
+ }
+ if(R.r.mode & R_ORTHO) {
+ R.near*= 100.0; /* R.far niet doen */
+ R.viewfac*= 100.0;
+ }
+
+ R.pixsize= R.near/R.viewfac;
+
+ }
+
+ /* I think these offsets are wrong. They do not coincide with shadow */
+ /* calculations, btw. */
+ minx= R.xstart+.5;
+ miny= R.ycor*(R.ystart+.5);
+ maxx= R.xend+.4999;
+ maxy= R.ycor*(R.yend+.4999);
+ /* My guess: (or rather, what should be) */
+/* minx= R.xstart - 0.5; */
+/* miny= R.ycor * (R.ystart - 0.5); */
+ /* Since the SCS-s map directly to the pixel center coordinates, we need */
+ /* to stretch the clip area a bit, not just shift it. However, this gives*/
+ /* nasty problems for parts... */
+
+ if(R.flag & R_SEC_FIELD) {
+ if(R.r.mode & R_ODDFIELD) {
+ miny-= .5*R.ycor;
+ maxy-= .5*R.ycor;
+ }
+ else {
+ miny+= .5*R.ycor;
+ maxy+= .5*R.ycor;
+ }
+ }
+
+ xd= yd= 0.0;
+ if(jmode!= -1) {
+ xd= jit[jmode % R.osa][0];
+ yd= R.ycor*jit[jmode % R.osa][1];
+
+ }
+
+ if(G.special1 & G_HOLO) {
+ if(G.scene->camera->type==OB_CAMERA) {
+ cam= G.scene->camera->data;
+ if(cam->flag & CAM_HOLO2) {
+
+ if(cam->netend==0.0) cam->netend= (G.scene->r.efra);
+
+ fac= ((G.scene->r.cfra)-1.0)/(cam->netend)-0.5;
+ fac*= (R.rectx);
+ fac*= cam->hololen1;
+
+ holoofs= -fac;
+ minx-= fac;
+ maxx-= fac;
+ }
+ }
+ }
+
+ minx= R.pixsize*(minx+xd);
+ maxx= R.pixsize*(maxx+xd);
+ miny= R.pixsize*(miny+yd);
+ maxy= R.pixsize*(maxy+yd);
+
+ if(R.r.mode & R_ORTHO) {
+ /* hier de near & far vermenigvuldigen is voldoende! */
+
+ i_window(minx, maxx, miny, maxy, R.near, 100.0*R.far, R.winmat);
+ }
+ else i_window(minx, maxx, miny, maxy, R.near, R.far, R.winmat);
+
+}
+
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+void initparts()
+{
+ short nr, xd, yd, xpart, ypart, xparts, yparts;
+ short a, xminb, xmaxb, yminb, ymaxb;
+
+ if(R.r.mode & R_BORDER) {
+ xminb= R.r.border.xmin*R.rectx;
+ xmaxb= R.r.border.xmax*R.rectx;
+
+ yminb= R.r.border.ymin*R.recty;
+ ymaxb= R.r.border.ymax*R.recty;
+
+ if(xminb<0) xminb= 0;
+ if(xmaxb>R.rectx) xmaxb= R.rectx;
+ if(yminb<0) yminb= 0;
+ if(ymaxb>R.recty) ymaxb= R.recty;
+ }
+ else {
+ xminb=yminb= 0;
+ xmaxb= R.rectx;
+ ymaxb= R.recty;
+ }
+
+ xparts= R.r.xparts; /* voor border */
+ yparts= R.r.yparts;
+
+ for(nr=0;nr<xparts*yparts;nr++)
+ allparts[nr][0]= -1; /* array leegmaken */
+
+ xpart= R.rectx/xparts;
+ ypart= R.recty/yparts;
+
+ /* als border: testen of aantal parts minder kan */
+ if(R.r.mode & R_BORDER) {
+ a= (xmaxb-xminb-1)/xpart+1; /* zoveel parts in border */
+ if(a<xparts) xparts= a;
+ a= (ymaxb-yminb-1)/ypart+1; /* zoveel parts in border */
+ if(a<yparts) yparts= a;
+
+ xpart= (xmaxb-xminb)/xparts;
+ ypart= (ymaxb-yminb)/yparts;
+ }
+
+ for(nr=0; nr<xparts*yparts; nr++) {
+
+ if(R.r.mode & R_PANORAMA) {
+ allparts[nr][0]= 0;
+ allparts[nr][1]= 0;
+ allparts[nr][2]= R.rectx;
+ allparts[nr][3]= R.recty;
+ }
+ else {
+ xd= (nr % xparts);
+ yd= (nr-xd)/xparts;
+
+ allparts[nr][0]= xminb+ xd*xpart;
+ allparts[nr][1]= yminb+ yd*ypart;
+ if(xd<R.r.xparts-1) allparts[nr][2]= allparts[nr][0]+xpart;
+ else allparts[nr][2]= xmaxb;
+ if(yd<R.r.yparts-1) allparts[nr][3]= allparts[nr][1]+ypart;
+ else allparts[nr][3]= ymaxb;
+
+ if(allparts[nr][2]-allparts[nr][0]<=0) allparts[nr][0]= -1;
+ if(allparts[nr][3]-allparts[nr][1]<=0) allparts[nr][0]= -1;
+ }
+ }
+}
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+short setpart(short nr) /* return 0 als geen goede part */
+{
+
+ if(allparts[nr][0]== -1) return 0;
+
+ R.xstart= allparts[nr][0]-R.afmx;
+ R.ystart= allparts[nr][1]-R.afmy;
+ R.xend= allparts[nr][2]-R.afmx;
+ R.yend= allparts[nr][3]-R.afmy;
+ R.rectx= R.xend-R.xstart;
+ R.recty= R.yend-R.ystart;
+
+ return 1;
+}
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+void addparttorect(short nr, Part *part)
+{
+ unsigned int *rt, *rp;
+ short y, heigth, len;
+
+ /* de juiste offset in rectot */
+
+ rt= R.rectot+ (allparts[nr][1]*R.rectx+ allparts[nr][0]);
+ rp= part->rect;
+ len= (allparts[nr][2]-allparts[nr][0]);
+ heigth= (allparts[nr][3]-allparts[nr][1]);
+
+ for(y=0;y<heigth;y++) {
+ memcpy(rt, rp, 4*len);
+ rt+=R.rectx;
+ rp+= len;
+ }
+}
+
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+
+void RE_holoview()
+{
+ Camera *cam;
+ float dist, fac, fy, fz;
+
+ if(G.scene==0 || G.scene->camera==0) return;
+
+ if(G.scene->camera->type==OB_CAMERA) {
+ cam= G.scene->camera->data;
+ if(cam->flag & (CAM_HOLO1|CAM_HOLO2)) {
+ fy= G.scene->camera->loc[1];
+ fz= G.scene->camera->loc[2];
+ dist= cam->hololen*sqrt( fy*fy+ fz*fz );
+
+ fac= ((G.scene->r.cfra)-(G.scene->r.sfra))/((float)((G.scene->r.efra)-(G.scene->r.sfra)));
+
+ G.scene->camera->loc[0]= -dist+ 2*fac*dist;
+ }
+ }
+}
+
+void add_to_blurbuf(int blur)
+{
+ static unsigned int *blurrect= 0;
+ int tot, gamval;
+ short facr, facb;
+ char *rtr, *rtb;
+
+ if(blur<0) {
+ if(blurrect) {
+ if(R.rectot) MEM_freeN(R.rectot);
+ R.rectot= blurrect;
+ blurrect= 0;
+ }
+ }
+ else if(blur==R.osa-1) {
+ /* eerste keer */
+ blurrect= MEM_mallocN(R.rectx*R.recty*sizeof(int), "rectblur");
+ if(R.rectot) memcpy(blurrect, R.rectot, R.rectx*R.recty*4);
+ }
+ else if(blurrect) {
+ /* accumuleren */
+
+ facr= 256/(R.osa-blur);
+ facb= 256-facr;
+
+ if(R.rectot) {
+ rtr= (char *)R.rectot;
+ rtb= (char *)blurrect;
+ tot= R.rectx*R.recty;
+ while(tot--) {
+ if( *((unsigned int *)rtb) != *((unsigned int *)rtr) ) {
+
+ if(R.r.mode & R_GAMMA) {
+ gamval= (facr* igamtab2[ rtr[0]<<8 ] + facb* igamtab2[ rtb[0]<<8 ])>>8;
+ rtb[0]= gamtab[ gamval ]>>8;
+ gamval= (facr* igamtab2[ rtr[1]<<8 ] + facb* igamtab2[ rtb[1]<<8 ])>>8;
+ rtb[1]= gamtab[ gamval ]>>8;
+ gamval= (facr* igamtab2[ rtr[2]<<8 ] + facb* igamtab2[ rtb[2]<<8 ])>>8;
+ rtb[2]= gamtab[ gamval ]>>8;
+ gamval= (facr* igamtab2[ rtr[3]<<8 ] + facb* igamtab2[ rtb[3]<<8 ])>>8;
+ rtb[3]= gamtab[ gamval ]>>8;
+ }
+ else {
+ rtb[0]= (facr*rtr[0] + facb*rtb[0])>>8;
+ rtb[1]= (facr*rtr[1] + facb*rtb[1])>>8;
+ rtb[2]= (facr*rtr[2] + facb*rtb[2])>>8;
+ rtb[3]= (facr*rtr[3] + facb*rtb[3])>>8;
+ }
+ }
+ rtr+= 4;
+ rtb+= 4;
+ }
+ }
+ if(blur==0) {
+ /* laatste keer */
+ if(R.rectot) MEM_freeN(R.rectot);
+ R.rectot= blurrect;
+ blurrect= 0;
+ }
+ }
+}
+
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+void render() {
+ /* not too neat... should improve... */
+ if(R.r.mode & R_UNIFIED) {
+ unifiedRenderingLoop();
+ } else {
+ oldRenderLoop();
+ }
+}
+
+
+void oldRenderLoop(void) /* hierbinnen de PART en FIELD lussen */
+{
+ Part *part;
+ unsigned int *rt, *rt1, *rt2;
+ int len, y;
+ short blur, a,fields,fi,parts; /* pa is globaal ivm print */
+ unsigned int *border_buf= NULL;
+ unsigned int border_x= 0;
+ unsigned int border_y= 0;
+
+ if((R.r.mode & R_BORDER) && !(R.r.mode & R_MOVIECROP)) {
+ border_buf= R.rectot;
+ border_x= R.rectx;
+ border_y= R.recty;
+ R.rectot= 0;
+ }
+
+
+ if (R.rectz) MEM_freeN(R.rectz);
+ R.rectz = 0;
+
+ /* FIELDLUS */
+ fields= 1;
+ parts= R.r.xparts*R.r.yparts;
+
+ if(R.r.mode & R_FIELDS) {
+ fields= 2;
+ R.rectf1= R.rectf2= 0; /* fieldrecten */
+ R.r.ysch/= 2;
+ R.afmy/= 2;
+ R.r.yasp*= 2;
+ R.ycor= ( (float)R.r.yasp)/( (float)R.r.xasp);
+
+ }
+
+
+ for(fi=0; fi<fields; fi++) {
+
+ /* INIT */
+ BLI_srand( 2*(G.scene->r.cfra)+fi);
+
+
+ R.vlaknr= -1;
+ R.flag|= R_RENDERING;
+ if(fi==1) R.flag |= R_SEC_FIELD;
+
+
+ /* MOTIONBLUR lus */
+ if(R.r.mode & R_MBLUR) blur= R.osa;
+ else blur= 1;
+
+
+ while(blur--) {
+
+ /* WINDOW */
+ R.rectx= R.r.xsch;
+ R.recty= R.r.ysch;
+ R.xstart= -R.afmx;
+ R.ystart= -R.afmy;
+ R.xend= R.xstart+R.rectx-1;
+ R.yend= R.ystart+R.recty-1;
+
+
+ if(R.r.mode & R_MBLUR) set_mblur_offs(R.osa-blur);
+
+ initparts(); /* altijd doen ivm border */
+ setpart(0);
+
+ RE_local_init_render_display();
+ RE_local_clear_render_display(R.win);
+ RE_local_timecursor((G.scene->r.cfra));
+
+ prepareScene();
+
+ /* PARTS */
+ R.parts.first= R.parts.last= 0;
+ for(pa=0; pa<parts; pa++) {
+
+ if(RE_local_test_break()) break;
+
+ if(pa) { /* want pa==0 is al gedaan */
+ if(setpart(pa)==0) break;
+ }
+
+ if(R.r.mode & R_MBLUR) RE_setwindowclip(0, blur);
+ else RE_setwindowclip(0,-1);
+
+ if(R.r.mode & R_PANORAMA) setPanoRot(pa);
+
+ /* HOMOGENE COORDINATEN EN ZBUF EN CLIP OPT (per part) */
+ /* There may be some interference with z-coordinate */
+ /* calculation here? */
+
+ doClipping(RE_projectverto);
+ if(RE_local_test_break()) break;
+
+
+ /* ZBUFFER & SHADE: zbuffer stores int distances, int face indices */
+ R.rectot= (unsigned int *)MEM_callocN(sizeof(int)*R.rectx*R.recty, "rectot");
+ R.rectz = (unsigned int *)MEM_mallocN(sizeof(int)*R.rectx*R.recty, "rectz");
+
+ if(R.r.mode & R_MBLUR) RE_local_printrenderinfo(0.0, R.osa - blur);
+ else RE_local_printrenderinfo(0.0, -1);
+
+ /* choose render pipeline type, and whether or not to use the */
+ /* delta accumulation buffer. 3 choices. */
+ if(R.r.mode & R_OSA) zbufshadeDA();
+ else zbufshade();
+
+ if(RE_local_test_break()) break;
+
+ /* uitzondering */
+ if( (R.r.mode & R_BORDER) && (R.r.mode & R_MOVIECROP));
+ else {
+ /* PART OF BORDER AFHANDELEN */
+ if(parts>1 || (R.r.mode & R_BORDER)) {
+
+ part= MEM_callocN(sizeof(Part), "part");
+ BLI_addtail(&R.parts, part);
+ part->rect= R.rectot;
+ R.rectot= 0;
+
+ if (R.rectz) {
+ MEM_freeN(R.rectz);
+ R.rectz= 0;
+ }
+ }
+ }
+ }
+
+ /* PARTS SAMENVOEGEN OF BORDER INVOEGEN */
+
+ /* uitzondering: crop */
+ if( (R.r.mode & R_BORDER) && (R.r.mode & R_MOVIECROP)) ;
+ else {
+ R.rectx= R.r.xsch;
+ R.recty= R.r.ysch;
+
+ if(R.r.mode & R_PANORAMA) R.rectx*= R.r.xparts;
+
+ if(parts>1 || (R.r.mode & R_BORDER)) {
+ if(R.rectot) MEM_freeN(R.rectot);
+ if(R.r.mode & R_BORDER) {
+ if(border_x<R.rectx || border_y<R.recty || border_buf==NULL)
+ R.rectot= (unsigned int *)MEM_callocN(sizeof(int)*R.rectx*R.recty, "rectot");
+ else
+ R.rectot= border_buf;
+ }
+ else R.rectot=(unsigned int *)MEM_mallocN(sizeof(int)*R.rectx*R.recty, "rectot");
+
+ part= R.parts.first;
+ for(pa=0; pa<parts; pa++) {
+ if(allparts[pa][0]== -1) break;
+ if(part==0) break;
+
+ if(R.r.mode & R_PANORAMA) {
+ if(pa) {
+ allparts[pa][0] += pa*R.r.xsch;
+ allparts[pa][2] += pa*R.r.xsch;
+ }
+ }
+ addparttorect(pa, part);
+
+ part= part->next;
+ }
+
+ part= R.parts.first;
+ while(part) {
+ MEM_freeN(part->rect);
+ part= part->next;
+ }
+ BLI_freelistN(&R.parts);
+ }
+ }
+
+ if( (R.flag & R_HALO)) {
+ add_halo_flare();
+ }
+
+ if(R.r.mode & R_MBLUR) {
+ add_to_blurbuf(blur);
+ }
+
+ /* EINDE (blurlus) */
+ finalizeScene();
+
+ if(RE_local_test_break()) break;
+ }
+
+ /* definitief vrijgeven */
+ add_to_blurbuf(-1);
+
+ /* FIELD AFHANDELEN */
+ if(R.r.mode & R_FIELDS) {
+ if(R.flag & R_SEC_FIELD) R.rectf2= R.rectot;
+ else R.rectf1= R.rectot;
+ R.rectot= 0;
+ }
+
+ if(RE_local_test_break()) break;
+ }
+
+ /* FIELDS SAMENVOEGEN */
+ if(R.r.mode & R_FIELDS) {
+ R.r.ysch*= 2;
+ R.afmy*= 2;
+ R.recty*= 2;
+ R.r.yasp/=2;
+
+ if(R.rectot) MEM_freeN(R.rectot); /* komt voor bij afbreek */
+ R.rectot=(unsigned int *)MEM_mallocN(sizeof(int)*R.rectx*R.recty, "rectot");
+
+ if(RE_local_test_break()==0) {
+ rt= R.rectot;
+
+ if(R.r.mode & R_ODDFIELD) {
+ rt2= R.rectf1;
+ rt1= R.rectf2;
+ }
+ else {
+ rt1= R.rectf1;
+ rt2= R.rectf2;
+ }
+
+ len= 4*R.rectx;
+
+ for(a=0; a<R.recty; a+=2) {
+ memcpy(rt, rt1, len);
+ rt+= R.rectx;
+ rt1+= R.rectx;
+ memcpy(rt, rt2, len);
+ rt+= R.rectx;
+ rt2+= R.rectx;
+ }
+ }
+ }
+
+ /* R.rectx= R.r.xsch; */
+ /* if(R.r.mode & R_PANORAMA) R.rectx*= R.r.xparts; */
+ /* R.recty= R.r.ysch; */
+
+ /* als border: wel de skybuf doen */
+ if(R.r.mode & R_BORDER) {
+ if( (R.r.mode & R_MOVIECROP)==0) {
+ if(R.r.bufflag & 1) {
+ R.xstart= -R.afmx;
+ R.ystart= -R.afmy;
+ rt= R.rectot;
+ for(y=0; y<R.recty; y++, rt+= R.rectx) scanlinesky((char *)rt, y);
+ }
+ }
+ }
+
+ set_mblur_offs(0);
+
+ /* VRIJGEVEN */
+
+ /* zbuf test */
+
+ /* don't free R.rectz, only when its size is not the same as R.rectot */
+
+ if (R.rectz && parts == 1 && (R.r.mode & R_FIELDS) == 0);
+ else {
+ if(R.rectz) MEM_freeN(R.rectz);
+ R.rectz= 0;
+ }
+
+ if(R.rectf1) MEM_freeN(R.rectf1);
+ R.rectf1= 0;
+ if(R.rectf2) MEM_freeN(R.rectf2);
+ R.rectf2= 0;
+}
+
+
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+extern unsigned short usegamtab;
+void RE_initrender(struct View3D *ogl_render_view3d)
+{
+ double start_time;
+ Image *bima;
+ char name[256];
+
+ /* scenedata naar R */
+ R.r= G.scene->r;
+ R.r.postigamma= 1.0/R.r.postgamma;
+
+ /* voor zekerheid: bij voortijdige return */
+ R.rectx= R.r.xsch;
+ R.recty= R.r.ysch;
+
+ /* MAG ER WEL WORDEN GERENDERD */
+
+ /* verboden combinatie */
+ if((R.r.mode & R_BORDER) && (R.r.mode & R_PANORAMA)) {
+ error("No border allowed for Panorama");
+ G.afbreek= 1;
+ return;
+ }
+
+
+ if(R.r.xparts*R.r.yparts>64) {
+ error("No more than 64 parts");
+ G.afbreek= 1;
+ return;
+ }
+
+ if(R.r.yparts>1 && (R.r.mode & R_PANORAMA)) {
+ error("No Y-Parts allowed for Panorama");
+ G.afbreek= 1;
+ return;
+ }
+
+
+ /* BACKBUF TESTEN */
+ /* If an image is specified for use as backdrop, that image is loaded */
+ /* here. */
+ if((R.r.bufflag & 1) && (G.scene->r.scemode & R_OGL)==0) {
+ if(R.r.alphamode == R_ADDSKY) {
+ strcpy(name, R.r.backbuf);
+ BLI_convertstringcode(name, G.sce, G.scene->r.cfra);
+
+ if(R.backbuf) {
+ R.backbuf->id.us--;
+ bima= R.backbuf;
+ }
+ else bima= 0;
+
+ R.backbuf= add_image(name);
+
+ if(bima && bima->id.us<1) {
+ free_image_buffers(bima);
+ }
+ if(R.backbuf==0) {
+ error("No backbuf there!");
+ G.afbreek= 1;
+ return;
+ }
+ }
+ }
+
+
+ usegamtab= 0; /* zie hieronder */
+
+ if(R.r.mode & (R_OSA|R_MBLUR)) {
+ R.osa= R.r.osa;
+ if(R.osa>16) R.osa= 16;
+
+ init_render_jit(R.osa);
+ RE_init_filt_mask();
+
+ /* wordt af en toe tijdelijk op nul gezet, o.a. in transp zbuf */
+ if(R.r.mode & R_GAMMA) {
+ if((R.r.mode & R_OSA)) usegamtab= 1;
+ }
+ }
+ else R.osa= 0;
+
+ /* WINDOW */
+ R.r.xsch= (R.r.size*R.r.xsch)/100;
+ R.r.ysch= (R.r.size*R.r.ysch)/100;
+
+ R.afmx= R.r.xsch/2;
+ R.afmy= R.r.ysch/2;
+
+ /* when rendered without camera object */
+ /* it has to done here because of envmaps */
+ R.near= 0.1;
+ R.far= 1000.0;
+
+
+ if(R.afmx<1 || R.afmy<1) {
+ error("Image too small");
+ return;
+ }
+ R.ycor= ( (float)R.r.yasp)/( (float)R.r.xasp);
+
+ start_time= PIL_check_seconds_timer();
+
+ if(R.r.scemode & R_DOSEQ) {
+ R.rectx= R.r.xsch;
+ R.recty= R.r.ysch;
+
+ if(R.rectot) MEM_freeN(R.rectot);
+ R.rectot= (unsigned int *)MEM_callocN(sizeof(int)*R.rectx*R.recty, "rectot");
+
+ RE_local_timecursor((G.scene->r.cfra));
+
+ if(RE_local_test_break()==0) do_render_seq();
+
+ /* displayen */
+ if(R.rectot) RE_local_render_display(0, R.recty-1,
+ R.rectx, R.recty,
+ R.rectot);
+ }
+ else if(R.r.scemode & R_OGL) {
+ R.rectx= R.r.xsch;
+ R.recty= R.r.ysch;
+
+ if(R.rectot) MEM_freeN(R.rectot);
+ R.rectot= (unsigned int *)MEM_callocN(sizeof(int)*R.rectx*R.recty, "rectot");
+
+ RE_local_init_render_display();
+ drawview3d_render(ogl_render_view3d);
+ }
+ else {
+ if(G.scene->camera==0) {
+ G.scene->camera= scene_find_camera(G.scene);
+ }
+
+ if(G.scene->camera==0) {
+ error("No camera");
+ G.afbreek=1;
+ return;
+ }
+ else {
+
+ if(G.scene->camera->type==OB_CAMERA) {
+ Camera *cam= G.scene->camera->data;
+ if(cam->type==CAM_ORTHO) R.r.mode |= R_ORTHO;
+ }
+
+ render(); /* keert terug met complete rect xsch-ysch */
+ }
+ }
+
+ /* nog eens displayen: fields/seq/parts/pano etc */
+ if(R.rectot) {
+ RE_local_init_render_display();
+ RE_local_render_display(0, R.recty-1,
+ R.rectx, R.recty,
+ R.rectot);
+ }
+ else RE_local_clear_render_display(R.win);
+
+ RE_local_printrenderinfo((PIL_check_seconds_timer() - start_time), -1);
+
+ /* variabelen weer goed */
+ R.osatex= 0;
+ R.vlr= 0; /* bij cubemap */
+ R.flag= 0;
+}
+
+void RE_animrender(struct View3D *ogl_render_view3d)
+{
+ int cfrao;
+ char name[256];
+
+ if(G.scene==0) return;
+
+ /* scenedata naar R: (voor backbuf, R.rectx enz) */
+ R.r= G.scene->r;
+
+ /* START ANIMLUS overal wordt NIET de cfra uit R.r gebruikt: ivm rest blender */
+ cfrao= (G.scene->r.cfra);
+
+ if(G.scene->r.scemode & R_OGL) R.r.mode &= ~R_PANORAMA;
+
+ // these calculations apply for
+ // all movie formats
+ R.rectx= (R.r.size*R.r.xsch)/100;
+ R.recty= (R.r.size*R.r.ysch)/100;
+ if(R.r.mode & R_PANORAMA) {
+ R.rectx*= R.r.xparts;
+ R.recty*= R.r.yparts;
+ }
+
+ if (0) {
+#ifdef __sgi
+ } else if (R.r.imtype==R_MOVIE) {
+ start_movie();
+#endif
+#ifdef _WIN32
+ } else if (R.r.imtype == R_AVICODEC) {
+ start_avi_codec();
+#endif
+ } else if ELEM4(R.r.imtype, R_AVIRAW, R_AVIJPEG, R_MOVIE, R_AVICODEC) {
+ if ELEM(R.r.imtype, R_MOVIE, R_AVICODEC) {
+ printf("Selected movie format not supported on this platform,\nusing RAW AVI instead\n");
+ }
+ start_avi();
+ }
+
+ for((G.scene->r.cfra)=(G.scene->r.sfra); (G.scene->r.cfra)<=(G.scene->r.efra); (G.scene->r.cfra)++) {
+ double starttime= PIL_check_seconds_timer();
+
+ R.flag= R_ANIMRENDER;
+
+ RE_initrender(ogl_render_view3d);
+
+ /* SCHRIJF PLAATJE */
+ if(RE_local_test_break()==0) {
+
+ if (0) {
+#ifdef __sgi
+ } else if (R.r.imtype == R_MOVIE) {
+ append_movie((G.scene->r.cfra));
+#endif
+#ifdef _WIN32
+ } else if (R.r.imtype == R_AVICODEC) {
+ append_avi_codec((G.scene->r.cfra));
+#endif
+ } else if ELEM4(R.r.imtype, R_AVIRAW, R_AVIJPEG, R_MOVIE, R_AVICODEC) {
+ append_avi((G.scene->r.cfra));
+ } else {
+ makepicstring(name, (G.scene->r.cfra));
+ schrijfplaatje(name);
+ if(RE_local_test_break()==0) printf("Saved: %s", name);
+ }
+
+ timestr(PIL_check_seconds_timer()-starttime, name);
+ printf(" Time: %s\n", name);
+ fflush(stdout); /* nodig voor renderd !! */
+ }
+
+ if(G.afbreek==1) break;
+
+ }
+
+ (G.scene->r.cfra)= cfrao;
+
+ /* restoren tijd */
+ if(R.r.mode & (R_FIELDS|R_MBLUR)) {
+ do_all_ipos();
+ do_all_keys();
+ do_all_actions();
+ do_all_ikas();
+ }
+
+ if (0) {
+#ifdef __sgi
+ } else if (R.r.imtype==R_MOVIE) {
+ end_movie();
+#endif
+#ifdef _WIN32
+ } else if (R.r.imtype == R_AVICODEC) {
+ end_avi_codec();
+#endif
+ } else if ELEM4(R.r.imtype, R_AVIRAW, R_AVIJPEG, R_MOVIE, R_AVICODEC) {
+ end_avi();
+ }
+}
+
+/* *************************************************** */
+/* ******************* Screendumps ******************** */
+/* moved to the windowControl thing */
diff --git a/source/blender/render/intern/source/jitter.c b/source/blender/render/intern/source/jitter.c
new file mode 100644
index 00000000000..19311132a7e
--- /dev/null
+++ b/source/blender/render/intern/source/jitter.c
@@ -0,0 +1,192 @@
+/**
+ * Jitter offset table
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 <stdlib.h>
+#include <string.h>
+#include "MEM_guardedalloc.h"
+
+#include "BLI_arithb.h"
+#include "BLI_rand.h"
+#include "render.h"
+#include "render_intern.h"
+#include "jitter.h"
+
+float jit[64][2];
+
+void init_render_jit(int nr);
+
+
+void RE_jitterate1(float *jit1, float *jit2, int num, float rad1)
+{
+ int i , j , k;
+ float vecx, vecy, dvecx, dvecy, x, y, len;
+
+ for (i = 2*num-2; i>=0 ; i-=2) {
+ dvecx = dvecy = 0.0;
+ x = jit1[i];
+ y = jit1[i+1];
+ for (j = 2*num-2; j>=0 ; j-=2) {
+ if (i != j){
+ vecx = jit1[j] - x - 1.0;
+ vecy = jit1[j+1] - y - 1.0;
+ for (k = 3; k>0 ; k--){
+ if( fabs(vecx)<rad1 && fabs(vecy)<rad1) {
+ len= sqrt(vecx*vecx + vecy*vecy);
+ if(len>0 && len<rad1) {
+ len= len/rad1;
+ dvecx += vecx/len;
+ dvecy += vecy/len;
+ }
+ }
+ vecx += 1.0;
+
+ if( fabs(vecx)<rad1 && fabs(vecy)<rad1) {
+ len= sqrt(vecx*vecx + vecy*vecy);
+ if(len>0 && len<rad1) {
+ len= len/rad1;
+ dvecx += vecx/len;
+ dvecy += vecy/len;
+ }
+ }
+ vecx += 1.0;
+
+ if( fabs(vecx)<rad1 && fabs(vecy)<rad1) {
+ len= sqrt(vecx*vecx + vecy*vecy);
+ if(len>0 && len<rad1) {
+ len= len/rad1;
+ dvecx += vecx/len;
+ dvecy += vecy/len;
+ }
+ }
+ vecx -= 2.0;
+ vecy += 1.0;
+ }
+ }
+ }
+
+ x -= dvecx/18.0 ;
+ y -= dvecy/18.0;
+ x -= floor(x) ;
+ y -= floor(y);
+ jit2[i] = x;
+ jit2[i+1] = y;
+ }
+ memcpy(jit1,jit2,2 * num * sizeof(float));
+}
+
+void RE_jitterate2(float *jit1, float *jit2, int num, float rad2)
+{
+ int i, j;
+ float vecx, vecy, dvecx, dvecy, x, y;
+
+ for (i=2*num -2; i>= 0 ; i-=2){
+ dvecx = dvecy = 0.0;
+ x = jit1[i];
+ y = jit1[i+1];
+ for (j =2*num -2; j>= 0 ; j-=2){
+ if (i != j){
+ vecx = jit1[j] - x - 1.0;
+ vecy = jit1[j+1] - y - 1.0;
+
+ if( fabs(vecx)<rad2) dvecx+= vecx*rad2;
+ vecx += 1.0;
+ if( fabs(vecx)<rad2) dvecx+= vecx*rad2;
+ vecx += 1.0;
+ if( fabs(vecx)<rad2) dvecx+= vecx*rad2;
+
+ if( fabs(vecy)<rad2) dvecy+= vecy*rad2;
+ vecy += 1.0;
+ if( fabs(vecy)<rad2) dvecy+= vecy*rad2;
+ vecy += 1.0;
+ if( fabs(vecy)<rad2) dvecy+= vecy*rad2;
+
+ }
+ }
+
+ x -= dvecx/2 ;
+ y -= dvecy/2;
+ x -= floor(x) ;
+ y -= floor(y);
+ jit2[i] = x;
+ jit2[i+1] = y;
+ }
+ memcpy(jit1,jit2,2 * num * sizeof(float));
+}
+
+
+void initjit(float *jit, int num)
+{
+ float *jit2, x, rad1, rad2, rad3;
+ int i;
+
+ if(num==0) return;
+
+ jit2= MEM_mallocN(12 + 2*sizeof(float)*num, "initjit");
+ rad1= 1.0/sqrt((float)num);
+ rad2= 1.0/((float)num);
+ rad3= sqrt((float)num)/((float)num);
+
+ BLI_srand(31415926 + num);
+ x= 0;
+ for(i=0; i<2*num; i+=2) {
+ jit[i]= x+ rad1*(0.5-BLI_drand());
+ jit[i+1]= ((float)i/2)/num +rad1*(0.5-BLI_drand());
+ x+= rad3;
+ x -= floor(x);
+ }
+
+ for (i=0 ; i<24 ; i++) {
+ RE_jitterate1(jit, jit2, num, rad1);
+ RE_jitterate1(jit, jit2, num, rad1);
+ RE_jitterate2(jit, jit2, num, rad2);
+ }
+
+ MEM_freeN(jit2);
+}
+
+void init_render_jit(int nr)
+{
+ static int lastjit= 0;
+
+ if(lastjit==nr) return;
+
+ memset(jit, 0, 64*2*4);
+ initjit(jit[0], nr);
+
+ lastjit= nr;
+
+}
+
+/* eof */
diff --git a/source/blender/render/intern/source/outerRenderLoop.c b/source/blender/render/intern/source/outerRenderLoop.c
new file mode 100644
index 00000000000..1e16fd251db
--- /dev/null
+++ b/source/blender/render/intern/source/outerRenderLoop.c
@@ -0,0 +1,515 @@
+/**
+ * The outer loop for rendering, but only for calling the
+ * unified renderer :)
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "MEM_guardedalloc.h"
+#include "BLI_blenlib.h"
+#include "BLI_rand.h"
+
+#include "BKE_global.h"
+#include "BKE_object.h"
+
+#include "render.h"
+#include "render_intern.h"
+#include "outerRenderLoop.h"
+#include "renderPreAndPost.h"
+#include "vanillaRenderPipe.h"
+#include "renderHelp.h"
+#include "RE_callbacks.h"
+
+extern short pa; /* can move to inside the outer loop */
+/* should make a gamtab module, just like the jitter... */
+extern unsigned short *mask1[9], *mask2[9], *igamtab2;
+
+
+/* Parts bookkeeping: done on this level, because it seems appropriate to me.*/
+static short partsCoordinates[65][4];
+short setPart(short nr);/* return 0 if this is a bad part. Sets data in R....*/
+void initParts(void);
+void addPartToRect(short nr, Part *part);
+void addToBlurBuffer(int blur);
+
+/* ------------------------------------------------------------------------- */
+void addToBlurBuffer(int blur)
+{
+ static unsigned int *blurrect= 0;
+ int tot, gamval;
+ short facr, facb;
+ char *rtr, *rtb;
+
+ if(blur<0) {
+ if(blurrect) {
+ if(R.rectot) MEM_freeN(R.rectot);
+ R.rectot= blurrect;
+ blurrect= 0;
+ }
+ }
+ else if(blur==R.osa-1) {
+ /* eerste keer */
+ blurrect= MEM_mallocN(R.rectx*R.recty*sizeof(int), "rectblur");
+ if(R.rectot) memcpy(blurrect, R.rectot, R.rectx*R.recty*4);
+ }
+ else if(blurrect) {
+ /* accumuleren */
+
+ facr= 256/(R.osa-blur);
+ facb= 256-facr;
+
+ if(R.rectot) {
+ rtr= (char *)R.rectot;
+ rtb= (char *)blurrect;
+ tot= R.rectx*R.recty;
+ while(tot--) {
+ if( *((unsigned int *)rtb) != *((unsigned int *)rtr) ) {
+
+ if(R.r.mode & R_GAMMA) {
+ gamval= (facr* igamtab2[ rtr[0]<<8 ] + facb* igamtab2[ rtb[0]<<8 ])>>8;
+ rtb[0]= gamtab[ gamval ]>>8;
+ gamval= (facr* igamtab2[ rtr[1]<<8 ] + facb* igamtab2[ rtb[1]<<8 ])>>8;
+ rtb[1]= gamtab[ gamval ]>>8;
+ gamval= (facr* igamtab2[ rtr[2]<<8 ] + facb* igamtab2[ rtb[2]<<8 ])>>8;
+ rtb[2]= gamtab[ gamval ]>>8;
+ gamval= (facr* igamtab2[ rtr[3]<<8 ] + facb* igamtab2[ rtb[3]<<8 ])>>8;
+ rtb[3]= gamtab[ gamval ]>>8;
+ }
+ else {
+ rtb[0]= (facr*rtr[0] + facb*rtb[0])>>8;
+ rtb[1]= (facr*rtr[1] + facb*rtb[1])>>8;
+ rtb[2]= (facr*rtr[2] + facb*rtb[2])>>8;
+ rtb[3]= (facr*rtr[3] + facb*rtb[3])>>8;
+ }
+ }
+ rtr+= 4;
+ rtb+= 4;
+ }
+ }
+ if(blur==0) {
+ /* laatste keer */
+ if(R.rectot) MEM_freeN(R.rectot);
+ R.rectot= blurrect;
+ blurrect= 0;
+ }
+ }
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+void addPartToRect(short nr, Part *part)
+{
+ unsigned int *rt, *rp;
+ short y, heigth, len;
+
+ /* de juiste offset in rectot */
+
+ rt= R.rectot+ (partsCoordinates[nr][1]*R.rectx+ partsCoordinates[nr][0]);
+ rp= part->rect;
+ len= (partsCoordinates[nr][2]-partsCoordinates[nr][0]);
+ heigth= (partsCoordinates[nr][3]-partsCoordinates[nr][1]);
+
+ for(y=0;y<heigth;y++) {
+ memcpy(rt, rp, 4*len);
+ rt+=R.rectx;
+ rp+= len;
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
+void initParts()
+{
+ short nr, xd, yd, xpart, ypart, xparts, yparts;
+ short a, xminb, xmaxb, yminb, ymaxb;
+
+ if(R.r.mode & R_BORDER) {
+ xminb= R.r.border.xmin*R.rectx;
+ xmaxb= R.r.border.xmax*R.rectx;
+
+ yminb= R.r.border.ymin*R.recty;
+ ymaxb= R.r.border.ymax*R.recty;
+
+ if(xminb<0) xminb= 0;
+ if(xmaxb>R.rectx) xmaxb= R.rectx;
+ if(yminb<0) yminb= 0;
+ if(ymaxb>R.recty) ymaxb= R.recty;
+ }
+ else {
+ xminb=yminb= 0;
+ xmaxb= R.rectx;
+ ymaxb= R.recty;
+ }
+
+ xparts= R.r.xparts; /* voor border */
+ yparts= R.r.yparts;
+
+ for(nr=0;nr<xparts*yparts;nr++)
+ partsCoordinates[nr][0]= -1; /* array leegmaken */
+
+ xpart= R.rectx/xparts;
+ ypart= R.recty/yparts;
+
+ /* als border: testen of aantal parts minder kan */
+ if(R.r.mode & R_BORDER) {
+ a= (xmaxb-xminb-1)/xpart+1; /* zoveel parts in border */
+ if(a<xparts) xparts= a;
+ a= (ymaxb-yminb-1)/ypart+1; /* zoveel parts in border */
+ if(a<yparts) yparts= a;
+
+ xpart= (xmaxb-xminb)/xparts;
+ ypart= (ymaxb-yminb)/yparts;
+ }
+
+ for(nr=0; nr<xparts*yparts; nr++) {
+
+ if(R.r.mode & R_PANORAMA) {
+ partsCoordinates[nr][0]= 0;
+ partsCoordinates[nr][1]= 0;
+ partsCoordinates[nr][2]= R.rectx;
+ partsCoordinates[nr][3]= R.recty;
+ }
+ else {
+ xd= (nr % xparts);
+ yd= (nr-xd)/xparts;
+
+ partsCoordinates[nr][0]= xminb+ xd*xpart;
+ partsCoordinates[nr][1]= yminb+ yd*ypart;
+ if(xd<R.r.xparts-1) partsCoordinates[nr][2]= partsCoordinates[nr][0]+xpart;
+ else partsCoordinates[nr][2]= xmaxb;
+ if(yd<R.r.yparts-1) partsCoordinates[nr][3]= partsCoordinates[nr][1]+ypart;
+ else partsCoordinates[nr][3]= ymaxb;
+
+ if(partsCoordinates[nr][2]-partsCoordinates[nr][0]<=0) partsCoordinates[nr][0]= -1;
+ if(partsCoordinates[nr][3]-partsCoordinates[nr][1]<=0) partsCoordinates[nr][0]= -1;
+ }
+ }
+}
+
+short setPart(short nr) /* return 0 als geen goede part */
+{
+
+ if(partsCoordinates[nr][0]== -1) return 0;
+
+ R.xstart= partsCoordinates[nr][0]-R.afmx;
+ R.ystart= partsCoordinates[nr][1]-R.afmy;
+ R.xend= partsCoordinates[nr][2]-R.afmx;
+ R.yend= partsCoordinates[nr][3]-R.afmy;
+ R.rectx= R.xend-R.xstart;
+ R.recty= R.yend-R.ystart;
+
+ return 1;
+}
+
+/* ------------------------------------------------------------------------- */
+
+void unifiedRenderingLoop(void) /* hierbinnen de PART en FIELD lussen */
+{
+ Part *part;
+ unsigned int *rt, *rt1, *rt2;
+ int len;
+ short blur, a,fields,fi,parts; /* pa is globaal ivm print */
+ unsigned int *border_buf= NULL;
+ unsigned int border_x= 0;
+ unsigned int border_y= 0;
+
+ if((R.r.mode & R_BORDER) && !(R.r.mode & R_MOVIECROP)) {
+ border_buf= R.rectot;
+ border_x= R.rectx;
+ border_y= R.recty;
+ R.rectot= 0;
+ }
+
+
+ if (R.rectz) MEM_freeN(R.rectz);
+ R.rectz = 0;
+
+ /* FIELDLUS */
+ fields= 1;
+ parts= R.r.xparts*R.r.yparts;
+
+ if(R.r.mode & R_FIELDS) {
+ fields= 2;
+ R.rectf1= R.rectf2= 0; /* fieldrecten */
+ R.r.ysch/= 2;
+ R.afmy/= 2;
+ R.r.yasp*= 2;
+ R.ycor= ( (float)R.r.yasp)/( (float)R.r.xasp);
+
+ }
+
+
+ for(fi=0; fi<fields; fi++) {
+
+ /* INIT */
+ BLI_srand( 2*(G.scene->r.cfra)+fi);
+
+
+ R.vlaknr= -1;
+ R.flag|= R_RENDERING;
+ if(fi==1) R.flag |= R_SEC_FIELD;
+
+
+ /* MOTIONBLUR lus */
+ if(R.r.mode & R_MBLUR) blur= R.osa;
+ else blur= 1;
+
+
+ while(blur--) {
+
+ /* WINDOW */
+ R.rectx= R.r.xsch;
+ R.recty= R.r.ysch;
+ R.xstart= -R.afmx;
+ R.ystart= -R.afmy;
+ R.xend= R.xstart+R.rectx-1;
+ R.yend= R.ystart+R.recty-1;
+
+
+ if(R.r.mode & R_MBLUR) set_mblur_offs(R.osa-blur);
+
+ initParts(); /* altijd doen ivm border */
+ setPart(0);
+
+ RE_local_init_render_display();
+ RE_local_clear_render_display(R.win);
+ RE_local_timecursor((G.scene->r.cfra));
+
+ prepareScene();
+
+ /* PARTS */
+ R.parts.first= R.parts.last= 0;
+ for(pa=0; pa<parts; pa++) {
+
+ if(RE_local_test_break()) break;
+
+ if(pa) { /* want pa==0 is al gedaan */
+ if(setPart(pa)==0) break;
+ }
+
+ if(R.r.mode & R_MBLUR) RE_setwindowclip(0, blur);
+ else RE_setwindowclip(0,-1);
+
+ if(R.r.mode & R_PANORAMA) setPanoRot(pa);
+
+ /* HOMOGENE COORDINATEN EN ZBUF EN CLIP OPT (per part) */
+ /* There may be some interference with z-coordinate */
+ /* calculation here? */
+
+ doClipping(RE_projectverto);
+ if(RE_local_test_break()) break;
+
+
+ /* ZBUFFER & SHADE: zbuffer stores int distances, int face indices */
+ R.rectot= (unsigned int *)MEM_callocN(sizeof(int)*R.rectx*R.recty, "rectot");
+
+ if(R.r.mode & R_MBLUR) RE_local_printrenderinfo(0.0, R.osa - blur);
+ else RE_local_printrenderinfo(0.0, -1);
+
+ /* The inner loop */
+ zBufShadeAdvanced();
+
+ if(RE_local_test_break()) break;
+
+ /* uitzondering */
+ if( (R.r.mode & R_BORDER) && (R.r.mode & R_MOVIECROP));
+ else {
+ /* PART OF BORDER AFHANDELEN */
+ if(parts>1 || (R.r.mode & R_BORDER)) {
+
+ part= MEM_callocN(sizeof(Part), "part");
+ BLI_addtail(&R.parts, part);
+ part->rect= R.rectot;
+ R.rectot= 0;
+
+ if (R.rectz) {
+ MEM_freeN(R.rectz);
+ R.rectz= 0;
+ }
+ }
+ }
+ }
+
+ /* PARTS SAMENVOEGEN OF BORDER INVOEGEN */
+
+ /* uitzondering: crop */
+ if( (R.r.mode & R_BORDER) && (R.r.mode & R_MOVIECROP)) ;
+ else {
+ R.rectx= R.r.xsch;
+ R.recty= R.r.ysch;
+
+ if(R.r.mode & R_PANORAMA) R.rectx*= R.r.xparts;
+
+ if(parts>1 || (R.r.mode & R_BORDER)) {
+ if(R.rectot) MEM_freeN(R.rectot);
+ if(R.r.mode & R_BORDER) {
+ if(border_x<R.rectx || border_y<R.recty || border_buf==NULL)
+ R.rectot= (unsigned int *)MEM_callocN(sizeof(int)*R.rectx*R.recty, "rectot");
+ else
+ R.rectot= border_buf;
+ }
+ else R.rectot=(unsigned int *)MEM_mallocN(sizeof(int)*R.rectx*R.recty, "rectot");
+
+ part= R.parts.first;
+ for(pa=0; pa<parts; pa++) {
+ if(partsCoordinates[pa][0]== -1) break;
+ if(part==0) break;
+
+ if(R.r.mode & R_PANORAMA) {
+ if(pa) {
+ partsCoordinates[pa][0] += pa*R.r.xsch;
+ partsCoordinates[pa][2] += pa*R.r.xsch;
+ }
+ }
+ addPartToRect(pa, part);
+
+ part= part->next;
+ }
+
+ part= R.parts.first;
+ while(part) {
+ MEM_freeN(part->rect);
+ part= part->next;
+ }
+ BLI_freelistN(&R.parts);
+ }
+ }
+
+ /* don't do this for unified renderer? */
+/* if( (R.flag & R_HALO) && !G.magic) { */
+/* add_halo_flare(); */
+/* } */
+
+ if(R.r.mode & R_MBLUR) {
+ addToBlurBuffer(blur);
+ }
+
+ /* EINDE (blurlus) */
+ finalizeScene();
+
+ if(RE_local_test_break()) break;
+ }
+
+ /* definitief vrijgeven */
+ addToBlurBuffer(-1);
+
+ /* FIELD AFHANDELEN */
+ if(R.r.mode & R_FIELDS) {
+ if(R.flag & R_SEC_FIELD) R.rectf2= R.rectot;
+ else R.rectf1= R.rectot;
+ R.rectot= 0;
+ }
+
+ if(RE_local_test_break()) break;
+ }
+
+ /* FIELDS SAMENVOEGEN */
+ if(R.r.mode & R_FIELDS) {
+ R.r.ysch*= 2;
+ R.afmy*= 2;
+ R.recty*= 2;
+ R.r.yasp/=2;
+
+ if(R.rectot) MEM_freeN(R.rectot); /* komt voor bij afbreek */
+ R.rectot=(unsigned int *)MEM_mallocN(sizeof(int)*R.rectx*R.recty, "rectot");
+
+ if(RE_local_test_break()==0) {
+ rt= R.rectot;
+
+ if(R.r.mode & R_ODDFIELD) {
+ rt2= R.rectf1;
+ rt1= R.rectf2;
+ }
+ else {
+ rt1= R.rectf1;
+ rt2= R.rectf2;
+ }
+
+ len= 4*R.rectx;
+
+ for(a=0; a<R.recty; a+=2) {
+ memcpy(rt, rt1, len);
+ rt+= R.rectx;
+ rt1+= R.rectx;
+ memcpy(rt, rt2, len);
+ rt+= R.rectx;
+ rt2+= R.rectx;
+ }
+ }
+ }
+
+ /* R.rectx= R.r.xsch; */
+ /* if(R.r.mode & R_PANORAMA) R.rectx*= R.r.xparts; */
+ /* R.recty= R.r.ysch; */
+
+ /* als border: wel de skybuf doen */
+ /*
+ This may be tricky
+ */
+/* if(R.r.mode & R_BORDER) { */
+/* if( (R.r.mode & R_MOVIECROP)==0) { */
+/* if(R.r.bufflag & 1) { */
+/* R.xstart= -R.afmx; */
+/* R.ystart= -R.afmy; */
+/* rt= R.rectot; */
+/* for(y=0; y<R.recty; y++, rt+= R.rectx) scanLineSkyFloat((char *)rt, y); */
+/* } */
+/* } */
+/* } */
+
+ set_mblur_offs(0);
+
+ /* VRIJGEVEN */
+
+ /* zbuf test */
+
+ /* don't free R.rectz, only when its size is not the same as R.rectot */
+
+ if (R.rectz && parts == 1 && (R.r.mode & R_FIELDS) == 0);
+ else {
+ if(R.rectz) MEM_freeN(R.rectz);
+ R.rectz= 0;
+ }
+
+ if(R.rectf1) MEM_freeN(R.rectf1);
+ R.rectf1= 0;
+ if(R.rectf2) MEM_freeN(R.rectf2);
+ R.rectf2= 0;
+} /* End of void unifiedRenderingLoop()*/
+
+/* ------------------------------------------------------------------------- */
+
+/* eof */
+
diff --git a/source/blender/render/intern/source/pixelblending.c b/source/blender/render/intern/source/pixelblending.c
new file mode 100644
index 00000000000..4fa3703d865
--- /dev/null
+++ b/source/blender/render/intern/source/pixelblending.c
@@ -0,0 +1,919 @@
+/*
+ * pixelblending.c
+ *
+ * Functions to blend pixels with or without alpha, in various formats
+ * nzc - June 2000
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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>
+
+/* global includes */
+#include "render.h"
+#include "render_intern.h"
+
+/* local includes */
+#include "vanillaRenderPipe_types.h"
+
+/* own includes */
+#include "pixelblending_types.h"
+#include "pixelblending.h"
+#include "gammaCorrectionTables.h"
+
+/* externals */
+
+/* ------------------------------------------------------------------------- */
+/* Debug/behaviour defines */
+/* if defined: alpha blending with floats clips colour, as with shorts */
+/* #define RE_FLOAT_COLOUR_CLIPPING */
+/* if defined: alpha values are clipped */
+/* For now, we just keep alpha clipping. We run into thresholding and */
+/* blending difficulties otherwise. Be careful here. */
+#define RE_ALPHA_CLIPPING
+
+/* functions --------------------------------------------------------------- */
+
+/*
+ One things about key-alpha is that simply dividing by the alpha will
+ sometimes cause 'overflows' in that the pixel colours will be shot
+ way over full colour. This should be caught, and subsequently, the
+ operation will end up modifying the alpha as well.
+
+ Actually, when the starting colour is premul, it shouldn't overflow
+ ever. Strange thing is that colours keep overflowing...
+
+*/
+void applyKeyAlphaCharCol(char* target) {
+
+ if ((!(target[3] == 0))
+ || (target[3] == 255)) {
+ /* else: nothing to do */
+ /* check whether div-ing is enough */
+ float cf[4];
+ cf[0] = target[0]/target[3];
+ cf[1] = target[1]/target[3];
+ cf[2] = target[2]/target[3];
+ if ((cf[0] <= 1.0) && (cf[1] <= 1.0) && (cf[2] <= 1.0)) {
+ /* all colours remain properly scaled? */
+ /* scale to alpha */
+ cf[0] = (float) target[0] * (255.0/ (float)target[3]);
+ cf[1] = (float) target[1] * (255.0/ (float)target[3]);
+ cf[2] = (float) target[2] * (255.0/ (float)target[3]);
+
+ /* Clipping is important. */
+ target[0] = (cf[0] > 255.0 ? 255 : (char) cf[0]);
+ target[1] = (cf[1] > 255.0 ? 255 : (char) cf[1]);
+ target[2] = (cf[2] > 255.0 ? 255 : (char) cf[2]);
+
+ } else {
+ /* shouldn't happen! we were premul, remember? */
+/* should go to error handler: printf("Non-premul colour detected\n"); */
+ }
+ }
+
+} /* end of void applyKeyAlphaCharCol(char* target) */
+
+/* ------------------------------------------------------------------------- */
+
+void addAddSampColF(float *sampvec, float *source, int mask, int osaNr,
+ char addfac)
+{
+ int a;
+
+ for(a=0; a < osaNr; a++) {
+ if(mask & (1<<a)) addalphaAddfacFloat(sampvec, source, addfac);
+ sampvec+= 4;
+ }
+} /* end of void addAddSampColF(float, float, int, int) */
+
+/* ------------------------------------------------------------------------- */
+
+void addOverSampColF(float *sampvec, float *source, int mask, int osaNr)
+{
+ int a;
+
+ for(a=0; a < osaNr; a++) {
+ if(mask & (1<<a)) addAlphaOverFloat(sampvec, source);
+ sampvec+= 4;
+ }
+} /* end of void addOverSampColF(float, float, int, int) */
+
+/* ------------------------------------------------------------------------- */
+
+int addUnderSampColF(float *sampvec, float *source, int mask, int osaNr)
+{
+ int a, retval = osaNr;
+
+ for(a=0; a < osaNr; a++) {
+ if(mask & (1<<a)) addAlphaUnderFloat(sampvec, source);
+ if(sampvec[3] > RE_FULL_COLOUR_FLOAT) retval--;
+ sampvec+= 4;
+ }
+ return retval;
+} /* end of int addToSampColF(float, float, int, int) */
+
+/* ------------------------------------------------------------------------- */
+
+int addToSampCol(unsigned short *sampcol, unsigned short *shortcol, int mask, int osaNr)
+{
+ int a, retval = osaNr;
+
+ for(a=0; a < osaNr; a++) {
+ if(mask & (1<<a)) addAlphaUnderShort(sampcol, shortcol);
+ if(sampcol[3]>0xFFF0) retval--;
+ sampcol+= 4;
+ }
+ return retval;
+} /* end of int addToSampCol(unsigned short, uhost, int, int) */
+
+/* ------------------------------------------------------------------------- */
+
+int addtosampcol(unsigned short *sampcol, unsigned short *shortcol, int mask)
+{
+ int a, retval = R.osa;
+
+ for(a=0; a < R.osa; a++) {
+ if(mask & (1<<a)) addAlphaUnderShort(sampcol, shortcol);
+ if(sampcol[3]>0xFFF0) retval--;
+ sampcol+= 4;
+ }
+ return retval;
+} /* end of int addtosampcol(unsigned short *sampcol, unsigned short *shortcol, int mask) */
+
+/* ------------------------------------------------------------------------- */
+
+void addAlphaOverShort(unsigned short *doel, unsigned short *bron) /* vult bron over doel in met alpha van bron */
+{
+ unsigned int c;
+ unsigned int mul;
+
+ if( doel[3]==0 || bron[3]>=0xFFF0) { /* is getest, scheelt veel */
+ *((unsigned int *)doel)= *((unsigned int *)bron);
+ *((unsigned int *)(doel+2))= *((unsigned int *)(bron+2));
+ return;
+ }
+
+ mul= 0xFFFF-bron[3];
+
+ c= ((mul*doel[0])>>16)+bron[0];
+ if(c>=0xFFF0) doel[0]=0xFFF0;
+ else doel[0]= c;
+ c= ((mul*doel[1])>>16)+bron[1];
+ if(c>=0xFFF0) doel[1]=0xFFF0;
+ else doel[1]= c;
+ c= ((mul*doel[2])>>16)+bron[2];
+ if(c>=0xFFF0) doel[2]=0xFFF0;
+ else doel[2]= c;
+ c= ((mul*doel[3])>>16)+bron[3];
+ if(c>=0xFFF0) doel[3]=0xFFF0;
+ else doel[3]= c;
+
+} /* end of void addAlphaOverShort(unsigned short *doel, unsigned short *bron) */
+
+/* ------------------------------------------------------------------------- */
+
+void addAlphaUnderShort(unsigned short *doel, unsigned short *bron) /* vult bron onder doel in met alpha van doel */
+{
+ unsigned int c;
+ unsigned int mul;
+
+ if(doel[3]>=0xFFF0) return;
+ if( doel[3]==0 ) { /* is getest, scheelt veel */
+ *((unsigned int *)doel)= *((unsigned int *)bron);
+ *((unsigned int *)(doel+2))= *((unsigned int *)(bron+2));
+ return;
+ }
+
+ mul= 0xFFFF-doel[3];
+
+ c= ((mul*bron[0])>>16)+doel[0];
+ if(c>=0xFFF0) doel[0]=0xFFF0;
+ else doel[0]= c;
+ c= ((mul*bron[1])>>16)+doel[1];
+ if(c>=0xFFF0) doel[1]=0xFFF0;
+ else doel[1]= c;
+ c= ((mul*bron[2])>>16)+doel[2];
+ if(c>=0xFFF0) doel[2]=0xFFF0;
+ else doel[2]= c;
+ c= ((mul*bron[3])>>16)+doel[3];
+ if(c>=0xFFF0) doel[3]=0xFFF0;
+ else doel[3]= c;
+
+} /* end of void addAlphaUnderShort(unsigned short *doel, unsigned short *bron) */
+
+/* ------------------------------------------------------------------------- */
+
+void addAlphaOverFloat(float *dest, float *source)
+{
+ /* d = s + (1-alpha_s)d*/
+ float c;
+ float mul;
+
+ /* I may want to disable this clipping */
+#ifdef RE_FLOAT_COLOUR_CLIPPING
+ if( /* (-RE_FULL_COLOUR_FLOAT < source[3]) */
+/* && */ (source[3] > RE_FULL_COLOUR_FLOAT) ) { /* is getest, scheelt veel */
+ dest[0] = source[0];
+ dest[1] = source[1];
+ dest[2] = source[2];
+ dest[3] = source[3];
+ return;
+ }
+#endif
+
+ mul= 1.0 - source[3];
+
+ c= (mul*dest[0]) + source[0];
+#ifdef RE_FLOAT_COLOUR_CLIPPING
+ if(c >= RE_FULL_COLOUR_FLOAT) dest[0] = RE_UNITY_COLOUR_FLOAT;
+ else
+#endif
+ dest[0]= c;
+
+ c= (mul*dest[1]) + source[1];
+#ifdef RE_FLOAT_COLOUR_CLIPPING
+ if(c >= RE_FULL_COLOUR_FLOAT) dest[1] = RE_UNITY_COLOUR_FLOAT;
+ else
+#endif
+ dest[1]= c;
+
+ c= (mul*dest[2]) + source[2];
+#ifdef RE_FLOAT_COLOUR_CLIPPING
+ if(c >= RE_FULL_COLOUR_FLOAT) dest[2] = RE_UNITY_COLOUR_FLOAT;
+ else
+#endif
+ dest[2]= c;
+
+ c= (mul*dest[3]) + source[3];
+#ifdef RE_ALPHA_CLIPPING
+ if(c >= RE_FULL_COLOUR_FLOAT) dest[3] = RE_UNITY_COLOUR_FLOAT;
+ else
+#endif
+ dest[3]= c;
+
+} /* end of void addAlphaOverFloat(float *doel, float *bron) */
+
+
+
+/* ------------------------------------------------------------------------- */
+
+void addAlphaUnderFloat(float *dest, float *source)
+{
+ float c;
+ float mul;
+
+ /* I may want to disable this clipping */
+#ifdef RE_FLOAT_COLOUR_CLIPPING
+ if( dest[3] >= RE_FULL_COLOUR_FLOAT) return;
+#endif
+ if( (-RE_EMPTY_COLOUR_FLOAT < dest[3])
+ && (dest[3] < RE_EMPTY_COLOUR_FLOAT) ) { /* is getest, scheelt veel */
+ dest[0] = source[0];
+ dest[1] = source[1];
+ dest[2] = source[2];
+ dest[3] = source[3];
+ return;
+ }
+
+ mul= 1.0 - dest[3];
+
+ c= (mul*source[0]) + dest[0];
+#ifdef RE_FLOAT_COLOUR_CLIPPING
+ if(c >= RE_FULL_COLOUR_FLOAT) dest[0] = RE_UNITY_COLOUR_FLOAT;
+ else
+#endif
+ dest[0]= c;
+
+ c= (mul*source[1]) + dest[1];
+#ifdef RE_FLOAT_COLOUR_CLIPPING
+ if(c >= RE_FULL_COLOUR_FLOAT) dest[1] = RE_UNITY_COLOUR_FLOAT;
+ else
+#endif
+ dest[1]= c;
+
+ c= (mul*source[2]) + dest[2];
+#ifdef RE_FLOAT_COLOUR_CLIPPING
+ if(c >= RE_FULL_COLOUR_FLOAT) dest[2] = RE_UNITY_COLOUR_FLOAT;
+ else
+#endif
+ dest[2]= c;
+
+ c= (mul*source[3]) + dest[3];
+#ifdef RE_ALPHA_CLIPPING
+ if(c >= RE_FULL_COLOUR_FLOAT) dest[3] = RE_UNITY_COLOUR_FLOAT;
+ else
+#endif
+ dest[3]= c;
+
+} /* end of void addAlphaUnderFloat(float *doel, float *bron) */
+
+/* ------------------------------------------------------------------------- */
+
+void cpShortColV2CharColV(unsigned short *source, char *dest)
+{
+ dest[0] = source[0]>>8;
+ dest[1] = source[1]>>8;
+ dest[2] = source[2]>>8;
+ dest[3] = source[3]>>8;
+} /* end of void cpShortColV2CharColV(unsigned short *source, char *dest) */
+/* ------------------------------------------------------------------------- */
+
+void cpCharColV2ShortColV(char *source, unsigned short *dest)
+{
+ dest[0] = source[0]<<8;
+ dest[1] = source[1]<<8;
+ dest[2] = source[2]<<8;
+ dest[3] = source[3]<<8;
+} /* end of void cpShortColV2CharColV(char *source, unsigned short *dest) */
+
+/* ------------------------------------------------------------------------- */
+
+void cpIntColV2CharColV(unsigned int *source, char *dest)
+{
+ dest[0] = source[0]>>24;
+ dest[1] = source[1]>>24;
+ dest[2] = source[2]>>24;
+ dest[3] = source[3]>>24;
+} /* end of void cpIntColV2CharColV(unsigned int *source, char *dest) */
+
+/* ------------------------------------------------------------------------- */
+
+void cpCharColV2FloatColV(char *source, float *dest)
+{
+ /* What about endianness? Might be caught at this level :) */
+ dest[0] = source[0]/255.0;
+ dest[1] = source[1]/255.0;
+ dest[2] = source[2]/255.0;
+ dest[3] = source[3]/255.0;
+} /* end of void cpCharColV2FloatColV(char *source, float *dest) */
+/* ------------------------------------------------------------------------- */
+
+void cpShortColV2FloatColV(unsigned short *source, float *dest)
+{
+ dest[0] = source[0]/65535.0;
+ dest[1] = source[1]/65535.0;
+ dest[2] = source[2]/65535.0;
+ dest[3] = source[3]/65535.0;
+} /* end of void cpShortColV2FloatColV(char *source, float *dest) */
+
+/* ------------------------------------------------------------------------- */
+
+void cpFloatColV2CharColV(float* source, char *dest)
+{
+ /* can't this be done more efficient? hope the conversions are correct... */
+ if (source[0] < 0.0) dest[0] = 0;
+ else if (source[0] > 1.0) dest[0] = 255;
+ else dest[0] = (char) (source[0] * 255.0);
+
+ if (source[1] < 0.0) dest[1] = 0;
+ else if (source[1] > 1.0) dest[1] = 255;
+ else dest[1] = (char) (source[1] * 255.0);
+
+ if (source[2] < 0.0) dest[2] = 0;
+ else if (source[2] > 1.0) dest[2] = 255;
+ else dest[2] = (char) (source[2] * 255.0);
+
+ if (source[3] < 0.0) dest[3] = 0;
+ else if (source[3] > 1.0) dest[3] = 255;
+ else dest[3] = (char) (source[3] * 255.0);
+
+} /* end of void cpFloatColV2CharColV(float* source, char *dest) */
+
+/* ------------------------------------------------------------------------- */
+
+void cpShortColV(unsigned short *source, unsigned short *dest)
+{
+ dest[0] = source[0];
+ dest[1] = source[1];
+ dest[2] = source[2];
+ dest[3] = source[3];
+} /* end of void cpShortColV(unsigned short *source, unsigned short *dest) */
+
+/* ------------------------------------------------------------------------- */
+void cpFloatColV(float *source, float *dest)
+{
+ dest[0] = source[0];
+ dest[1] = source[1];
+ dest[2] = source[2];
+ dest[3] = source[3];
+} /* end of void cpFloatColV(float *source, float *dest) */
+
+/* ------------------------------------------------------------------------- */
+
+void cpCharColV(char *source, char *dest)
+{
+ dest[0] = source[0];
+ dest[1] = source[1];
+ dest[2] = source[2];
+ dest[3] = source[3];
+} /* end of void cpCharColV(char *source, char *dest) */
+
+/* ------------------------------------------------------------------------- */
+void addalphaAddfacFloat(float *dest, float *source, char addfac)
+ /* doel= bron over doel */
+{
+ float m; /* weiging factor of destination */
+ float c; /* intermediate colour */
+
+ /* 1. copy source straight away if dest has zero alpha */
+ /* 2. copy dest straight away if dest has full alpha */
+ /* I am not sure whether (2) is correct. It seems to */
+ /* me that this should not happen if float colours */
+ /* aren't clipped at 1.0 . */
+ /* I'll keep the code, but disabled.... */
+ if ( (dest[3] < RE_EMPTY_COLOUR_FLOAT)
+ /* || source[3] > RE_FULL_COLOUR_FLOAT */ ) {
+ dest[0] = source[0];
+ dest[1] = source[1];
+ dest[2] = source[2];
+ dest[3] = source[3];
+ return;
+ }
+
+ /* Addfac is a number between 0 and 1: rescale */
+ /* final target is to diminish the influence of dest when addfac rises */
+ m = 1.0 - ( source[3] * ((255.0 - addfac) / 255.0));
+
+ /* blend colours*/
+ c= (m * dest[0]) + source[0];
+#ifdef RE_FLOAT_COLOUR_CLIPPING
+ if(c >= RE_FULL_COLOUR_FLOAT) dest[0] = RE_FULL_COLOUR_FLOAT;
+ else
+#endif
+ dest[0]= c;
+
+ c= (m * dest[1]) + source[1];
+#ifdef RE_FLOAT_COLOUR_CLIPPING
+ if(c >= RE_FULL_COLOUR_FLOAT) dest[1] = RE_FULL_COLOUR_FLOAT;
+ else
+#endif
+ dest[1]= c;
+
+ c= (m * dest[2]) + source[2];
+#ifdef RE_FLOAT_COLOUR_CLIPPING
+ if(c >= RE_FULL_COLOUR_FLOAT) dest[2] = RE_FULL_COLOUR_FLOAT;
+ else
+#endif
+ dest[2]= c;
+
+ c= dest[3] + source[3];
+#ifdef RE_ALPHA_CLIPPING
+ if(c >= RE_FULL_COLOUR_FLOAT) dest[3] = RE_FULL_COLOUR_FLOAT;
+ else
+#endif
+ dest[3]= c;
+
+} /* end of void addalphaAddfacFloat(unsigned short *doel, unsigned short *bron, char addfac_help) */
+
+/* ------------------------------------------------------------------------- */
+
+void addalphaAddfacShort(unsigned short *doel, unsigned short *bron, char addfac)
+ /* doel= bron over doel */
+{
+ float m; /* weiging factor of destination */
+ float c; /* intermediate colour */
+
+ /* 1. copy bron straight away if doel has zero alpha */
+ if( doel[3] == 0) {
+ *((unsigned int *)doel) = *((unsigned int *)bron);
+ *((unsigned int *)(doel+2)) = *((unsigned int *)(bron+2));
+ return;
+ }
+
+ /* Addfac is a number between 0 and 1: rescale */
+ /* final target is to diminish the influence of dest when addfac rises */
+ m = 1.0 - ( bron[3] * ((255.0 - addfac) / 255.0));
+
+ /* blend colours*/
+ c = (m * doel[0]) + bron[0];
+ if( c > 65535.0 ) doel[0]=65535;
+ else doel[0] = floor(c);
+ c = (m * doel[1]) + bron[1];
+ if( c > 65535.0 ) doel[1]=65535;
+ else doel[1] = floor(c);
+ c = (m * doel[2]) + bron[2];
+ if( c > 65535.0 ) doel[2]=65535;
+ else doel[2] = floor(c);
+
+ c = doel[3] + bron[3];
+ if(c > 65535.0) doel[3] = 65535;
+ else doel[3]= floor(c);
+
+} /* end of void addalphaAddfacShort(unsigned short *doel, unsigned short *bron, char addfac_help) */
+
+/* ------------------------------------------------------------------------- */
+
+void addHaloToHaloShort(unsigned short *d, unsigned short *s)
+{
+ /* float m; */ /* weiging factor of destination */
+ float c[4]; /* intermediate colour */
+ float rescale = 1.0;
+
+ /* 1. copy <s> straight away if <d> has zero alpha */
+ if( d[3] == 0) {
+ *((unsigned int *) d) = *((unsigned int *) s);
+ *((unsigned int *)(d + 2)) = *((unsigned int *)(s + 2));
+ return;
+ }
+
+ /* 2. halo blending */
+ /* no blending, just add */
+ c[0] = s[0] + d[0];
+ c[1] = s[1] + d[1];
+ c[2] = s[2] + d[2];
+ c[3] = s[3] + d[3];
+ /* One thing that may happen is that this pixel is over-saturated with light - */
+ /* i.e. too much light comes out, and the pixel is clipped. Currently, this */
+ /* leads to artifacts such as overproportional undersampling of background */
+ /* colours. */
+ /* Compensating for over-saturation: */
+ /* - increase alpha */
+ /* - increase alpha and rescale colours */
+
+ /* let's try alpha increase and clipping */
+
+ /* calculate how much rescaling we need */
+ if( c[0] > 65535.0 ) {
+ rescale *= c[0] /65535.0;
+ d[0] = 65535;
+ } else d[0] = floor(c[0]);
+ if( c[1] > 65535.0 ) {
+ rescale *= c[1] /65535.0;
+ d[1] = 65535;
+ } else d[1] = floor(c[1]);
+ if( c[2] > 65535.0 ) {
+ rescale *= c[2] /65535.0;
+ d[2] = 65535;
+ } else d[2] = floor(c[2]);
+
+ /* a bit too hefty I think */
+ c[3] *= rescale;
+
+ if( c[3] > 65535.0 ) d[3] = 65535; else d[3]= floor(c[3]);
+
+} /* end of void addHaloToHaloShort(unsigned short *dest, unsigned short *source, char addfac) */
+
+/* ------------------------------------------------------------------------- */
+
+void sampleShortColV2ShortColV(unsigned short *sample, unsigned short *dest, int osaNr)
+{
+ unsigned int intcol[4] = {0};
+ unsigned short *scol = sample;
+ int a = 0;
+
+ for(a=0; a < osaNr; a++, scol+=4) {
+ intcol[0]+= scol[0]; intcol[1]+= scol[1];
+ intcol[2]+= scol[2]; intcol[3]+= scol[3];
+ }
+
+ /* Now normalise the integrated colour. It is guaranteed */
+ /* to be correctly bounded. */
+ dest[0]= intcol[0]/osaNr;
+ dest[1]= intcol[1]/osaNr;
+ dest[2]= intcol[2]/osaNr;
+ dest[3]= intcol[3]/osaNr;
+
+} /* end of void sampleShortColVToShortColV(unsigned short *sample, unsigned short *dest) */
+
+
+/* ------------------------------------------------------------------------- */
+
+void sampleFloatColV2FloatColV(float *sample, float *dest, int osaNr)
+{
+ float intcol[4] = {0};
+ float *scol = sample;
+ int a = 0;
+
+ if (doGamma()) {
+ /* use a LUT and interpolation to do the gamma correction */
+ for(a=0; a < osaNr; a++, scol+=4) {
+ intcol[0] += gammaCorrect(scol[0]);
+ intcol[1] += gammaCorrect(scol[1]);
+ intcol[2] += gammaCorrect(scol[2]);
+ intcol[3] += scol[3];
+ }
+
+ /* renormalise */
+ intcol[0] /= osaNr;
+ intcol[1] /= osaNr;
+ intcol[2] /= osaNr;
+ intcol[3] /= osaNr;
+
+ /* back to pixel values */
+ dest[0] = invGammaCorrect(intcol[0]);
+ dest[1] = invGammaCorrect(intcol[1]);
+ dest[2] = invGammaCorrect(intcol[2]);
+ dest[3] = intcol[3];
+ } else {
+ /* no gamma */
+ for(a=0; a < osaNr; a++, scol+=4) {
+ intcol[0] += scol[0]; intcol[1] += scol[1];
+ intcol[2] += scol[2]; intcol[3] += scol[3];
+ }
+
+ dest[0]= intcol[0]/osaNr;
+ dest[1]= intcol[1]/osaNr;
+ dest[2]= intcol[2]/osaNr;
+ dest[3]= intcol[3]/osaNr;
+ }
+
+} /* end void sampleFloatColVToFloatColV(unsigned short *, unsigned short *) */
+
+/* ------------------------------------------------------------------------- */
+/* The following functions are 'old' blending functions: */
+
+/* ------------------------------------------------------------------------- */
+void keyalpha(char *doel) /* maakt premul 255 */
+{
+ int c;
+ short div;
+ div= doel[3];
+ if (!div)
+ {
+ doel[0] = (doel[0] ? 255 : 0);
+ doel[1] = (doel[1] ? 255 : 0);
+ doel[2] = (doel[2] ? 255 : 0);
+ } else
+ {
+ c= (doel[0]<<8)/div;
+ if(c>255) doel[0]=255;
+ else doel[0]= c;
+ c= (doel[1]<<8)/div;
+ if(c>255) doel[1]=255;
+ else doel[1]= c;
+ c= (doel[2]<<8)/div;
+ if(c>255) doel[2]=255;
+ else doel[2]= c;
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+/* vult bron onder doel in met alpha van doel*/
+void addalphaUnder(char *doel, char *bron)
+{
+ int c;
+ int mul;
+
+ if(doel[3]==255) return;
+ if( doel[3]==0) { /* is getest, scheelt */
+ *((unsigned int *)doel)= *((unsigned int *)bron);
+ return;
+ }
+
+ mul= 255-doel[3];
+
+ c= doel[0]+ ((mul*bron[0])/255);
+ if(c>255) doel[0]=255;
+ else doel[0]= c;
+ c= doel[1]+ ((mul*bron[1])/255);
+ if(c>255) doel[1]=255;
+ else doel[1]= c;
+ c= doel[2]+ ((mul*bron[2])/255);
+ if(c>255) doel[2]=255;
+ else doel[2]= c;
+
+ c= doel[3]+ ((mul*bron[3])/255);
+ if(c>255) doel[3]=255;
+ else doel[3]= c;
+
+ /* doel[0]= MAX2(doel[0], bron[0]); */
+}
+
+/* ------------------------------------------------------------------------- */
+/* gamma-gecorr: vult bron onder doel in met alpha van doel */
+void addalphaUnderGamma(char *doel, char *bron)
+{
+ unsigned int tot;
+ int c, doe, bro;
+ int mul;
+
+ /* hier doel[3]==0 of doel==255 afvangen gebeurt al in skylus */
+ mul= 256-doel[3];
+
+ doe= igamtab1[(int)doel[0]];
+ bro= igamtab1[(int)bron[0]];
+ tot= (doe+ ((mul*bro)>>8));
+ if(tot>65535) tot=65535;
+ doel[0]= *((gamtab+tot)) >>8;
+
+ doe= igamtab1[(int)doel[1]];
+ bro= igamtab1[(int)bron[1]];
+ tot= (doe+ ((mul*bro)>>8));
+ if(tot>65535) tot=65535;
+ doel[1]= *((gamtab+tot)) >>8;
+
+ doe= igamtab1[(int)doel[2]];
+ bro= igamtab1[(int)bron[2]];
+ tot= (doe+ ((mul*bro)>>8));
+ if(tot>65535) tot=65535;
+ doel[2]= *((gamtab+tot)) >>8;
+
+ c= doel[3]+ ((mul*bron[3])/255);
+ if(c>255) doel[3]=255;
+ else doel[3]= c;
+ /* doel[0]= MAX2(doel[0], bron[0]); */
+}
+
+/* ------------------------------------------------------------------------- */
+/* doel= bron over doel */
+void addalphaOver(char *doel, char *bron)
+{
+ int c;
+ int mul;
+
+ if(bron[3]==0) return;
+ if( bron[3]==255) { /* is getest, scheelt */
+ *((unsigned int *)doel)= *((unsigned int *)bron);
+ return;
+ }
+
+ mul= 255-bron[3];
+
+ c= ((mul*doel[0])/255)+bron[0];
+ if(c>255) doel[0]=255;
+ else doel[0]= c;
+ c= ((mul*doel[1])/255)+bron[1];
+ if(c>255) doel[1]=255;
+ else doel[1]= c;
+ c= ((mul*doel[2])/255)+bron[2];
+ if(c>255) doel[2]=255;
+ else doel[2]= c;
+ c= ((mul*doel[3])/255)+bron[3];
+ if(c>255) doel[3]=255;
+ else doel[3]= c;
+}
+
+/* ------------------------------------------------------------------------- */
+void addalphaAdd(char *doel, char *bron) /* telt bron bij doel */
+{
+ int c;
+
+ if( doel[3]==0 || bron[3]==255) { /* is getest, scheelt veel */
+ *((unsigned int *)doel)= *((unsigned int *)bron);
+ return;
+ }
+ c= doel[0]+bron[0];
+ if(c>255) doel[0]=255;
+ else doel[0]= c;
+ c= doel[1]+bron[1];
+ if(c>255) doel[1]=255;
+ else doel[1]= c;
+ c= doel[2]+bron[2];
+ if(c>255) doel[2]=255;
+ else doel[2]= c;
+ c= doel[3]+bron[3];
+ if(c>255) doel[3]=255;
+ else doel[3]= c;
+}
+/* ------------------------------------------------------------------------- */
+void addalphaAddshort(unsigned short *doel, unsigned short *bron) /* telt bron bij doel */
+{
+ int c;
+
+ if( doel[3]==0) {
+ *((unsigned int *)doel)= *((unsigned int *)bron);
+ *((unsigned int *)(doel+2))= *((unsigned int *)(bron+2));
+ return;
+ }
+ c= doel[0]+bron[0];
+ if(c>65535) doel[0]=65535;
+ else doel[0]= c;
+ c= doel[1]+bron[1];
+ if(c>65535) doel[1]=65535;
+ else doel[1]= c;
+ c= doel[2]+bron[2];
+ if(c>65535) doel[2]=65535;
+ else doel[2]= c;
+ c= doel[3]+bron[3];
+ if(c>65535) doel[3]=65535;
+ else doel[3]= c;
+}
+
+/* ------------------------------------------------------------------------- */
+void addalphaAddFloat(float *dest, float *source)
+{
+
+ /* Makes me wonder whether this is required... */
+ if( dest[3] < RE_EMPTY_COLOUR_FLOAT) {
+ dest[0] = source[0];
+ dest[1] = source[1];
+ dest[2] = source[2];
+ dest[3] = source[3];
+ return;
+ }
+
+ /* no clipping! */
+ dest[0] = dest[0]+source[0];
+ dest[1] = dest[1]+source[1];
+ dest[2] = dest[2]+source[2];
+ dest[3] = dest[3]+source[3];
+
+}
+
+/* ALPHADDFAC:
+ *
+ * Z= X alphaover Y:
+ * Zrgb= (1-Xa)*Yrgb + Xrgb
+ *
+ * Om ook de add te doen moet (1-Xa) moduleren met 1 via fac
+ * (1-fac)*(1-Xa) + fac <=>
+ * 1-Xa-fac+fac*Xa+fac <=>
+ * Xa*(fac-1)+1
+ */
+
+
+/* ------------------------------------------------------------------------- */
+/* doel= bron over doel */
+void RE_addalphaAddfac(char *doel, char *bron, char addfac)
+{
+
+ int c, mul;
+
+ if( doel[3]==0) {
+ *((unsigned int *)doel)= *((unsigned int *)bron);
+ return;
+ }
+
+ mul= 255 - (bron[3]*(255-addfac))/255;
+
+ c= ((mul*doel[0])/255)+bron[0];
+ if(c>255) doel[0]=255;
+ else doel[0]= c;
+ c= ((mul*doel[1])/255)+bron[1];
+ if(c>255) doel[1]=255;
+ else doel[1]= c;
+ c= ((mul*doel[2])/255)+bron[2];
+ if(c>255) doel[2]=255;
+ else doel[2]= c;
+
+ /* c= ((mul*doel[3])/255)+bron[3]; */
+ c= doel[3]+bron[3];
+ if(c>255) doel[3]=255;
+ else doel[3]= c;
+}
+
+/* ------------------------------------------------------------------------- */
+/* doel= bron over doel */
+void addalphaAddfacshort(unsigned short *doel,
+ unsigned short *bron,
+ short addfac)
+{
+ int c, mul;
+
+ if( doel[3]==0) {
+ *((unsigned int *)doel)= *((unsigned int *)bron);
+ *((unsigned int *)(doel+2))= *((unsigned int *)(bron+2));
+ return;
+ }
+
+ mul= 0xFFFF - (bron[0]*(255-addfac))/255;
+
+ c= ((mul*doel[0])>>16)+bron[0];
+ if(c>=0xFFF0) doel[0]=0xFFF0;
+ else doel[0]= c;
+ c= ((mul*doel[1])>>16)+bron[1];
+ if(c>=0xFFF0) doel[1]=0xFFF0;
+ else doel[1]= c;
+ c= ((mul*doel[2])>>16)+bron[2];
+ if(c>=0xFFF0) doel[2]=0xFFF0;
+ else doel[2]= c;
+ c= ((mul*doel[3])>>16)+bron[3];
+ if(c>=0xFFF0) doel[3]=0xFFF0;
+ else doel[3]= c;
+
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* eof pixelblending.c */
+
+
diff --git a/source/blender/render/intern/source/pixelshading.c b/source/blender/render/intern/source/pixelshading.c
new file mode 100644
index 00000000000..ff69b4226bf
--- /dev/null
+++ b/source/blender/render/intern/source/pixelshading.c
@@ -0,0 +1,1917 @@
+/**
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * Shading of pixels
+ *
+ * 11-09-2000 nzc
+ *
+ * $Id$
+ *
+ * Shading hierarchy:
+ *
+ * (externally visible)
+ *
+ * renderPixel----------
+ * | renderHaloPixel-- shadeHaloFloat
+ * |
+ * | renderFacePixel-- shadeLampLusFloat
+ * | shadeSpotHaloPixelFloat-- spotHaloFloat
+ *
+ *
+ * renderSpotHaloPixel--(should call shadeSpotHaloPixelFloat, but there's numerical)
+ * ( issues there... need to iron that out still )
+ */
+
+#include <math.h>
+#include "BLI_arithb.h"
+
+/* External modules: */
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+#include "MTC_matrixops.h"
+#include "MTC_vectorops.h"
+
+#include "DNA_camera_types.h"
+#include "DNA_object_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_image_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_lamp_types.h"
+
+#include "BKE_global.h"
+#include "BKE_texture.h"
+#include "BKE_utildefines.h"
+
+#include "render.h"
+#include "render_intern.h"
+
+#include "vanillaRenderPipe_types.h"
+#include "pixelblending.h"
+#include "zbuf.h"
+#include "rendercore.h" /* for some shading functions... */
+#include "zbufferdatastruct.h"
+
+#include "shadbuf.h"
+#include "shadowBuffer.h"
+
+#include "renderHelp.h"
+
+#include "gammaCorrectionTables.h"
+#include "errorHandler.h"
+#include "pixelshading.h"
+
+/* ------------------------------------------------------------------------- */
+/* maybe declare local functions here? */
+/* ------------------------------------------------------------------------- */
+
+/* The collector is the communication channel with the render pipe. */
+extern RE_COLBUFTYPE collector[4]; /* used throughout as pixel colour accu */
+/* shortcol was the old collector */
+extern float holoofs, fmask[256];
+extern float Zmulx, Zmuly; /* Some kind of scale? */
+
+unsigned int calcHaloZ(HaloRen *har, unsigned int zz);
+
+/* ------------------------------------------------------------------------- */
+/* if defined: do full error tracing and reporting here */
+/* #define RE_PIXSHADE_FULL_SAFETY */
+/* if defined: use fake (dummy) colours for filling pixels (all is purple) */
+/* #define RE_FAKE_PIXELS */
+/* if defined: use fake (dummy) colours for filling faces (all blue) */
+/* #define RE_FAKE_FACE_PIXELS */
+/* if defined: use fake (dummy) colours for filling halos (all red) */
+/* #define RE_FAKE_HALO_PIXELS */
+/* #define RE_FAKE_HALO_PIXELS_2 */
+/* if defined: use fake (dummy) colours for filling spothalos (green) */
+/* #define RE_FAKE_SPOTHALO_PIXELS */
+/* if defined: use fake (dummy) colours for shading lighting */
+/* #define RE_FAKE_LAMP_SHADE */
+/* if defined: fake colours for sky pixels */
+/* #define RE_FAKE_SKY_PIXELS */
+
+/* ------------------------------------------------------------------------- */
+
+unsigned int calcHaloZ(HaloRen *har, unsigned int zz)
+{
+
+ if(har->type & HA_ONLYSKY) {
+ if(zz!=0x7FFFFFFF) zz= 0;
+ }
+ else {
+ zz= (zz>>8);
+ if(zz<0x800000) zz= (zz+0x7FFFFF);
+ else zz= (zz-0x800000);
+ }
+ return zz;
+}
+
+/* ------------------------------------------------------------------------- */
+
+void *renderPixel(float x, float y, int *obdata)
+{
+ void* data = NULL;
+#ifdef RE_PIXSHADE_FULL_SAFETY
+ char fname[] = "renderPixel";
+#endif
+#ifdef RE_FAKE_PIXELS
+ collector[0] = RE_UNITY_COLOUR_FLOAT;
+ collector[1] = 0;
+ collector[2] = RE_UNITY_COLOUR_FLOAT;
+ collector[3] = RE_UNITY_COLOUR_FLOAT;
+ return NULL;
+#endif
+
+ if (obdata[3] & RE_POLY) {
+ /* face pixels aren't rendered in floats yet, so we wrap it here */
+ data = renderFacePixel(x, y, obdata[1]);
+ }
+ else if (obdata[3] & RE_HALO) {
+ data = renderHaloPixel(x, y, obdata[1]);
+ }
+ else if( obdata[1] == 0 ) {
+ /* for lamphalo, but doesn't seem to be called? Actually it is, and */
+ /* it returns NULL pointers. */
+ data = renderFacePixel(x, y, obdata[1]);
+ }
+#ifdef RE_PIXSHADE_FULL_SAFETY
+ else RE_error(RE_BAD_FACE_TYPE, fname);
+#endif /* RE_PIXSHADE_FULL_SAFETY */
+ return data;
+
+} /* end of void renderPixel(float x, float y, int *obdata) */
+
+/* ------------------------------------------------------------------------- */
+
+void *renderFacePixel(float x, float y, int vlaknr)
+/* Result goes into <collector> */
+{
+#ifdef RE_PIXSHADE_FULL_SAFETY
+ char fname[]= "renderFacePixelFloat";
+#endif
+ static VlakRen *vlr; /* static, because we don't want to recalculate vlr */
+ /* when we already know it */
+ static VertRen *v1, *v2, *v3;
+ static float t00, t01, t10, t11, dvlak, n1[3], n2[3], n3[3];
+ static float s00, s01, s10, s11;
+ float *o1, *o2, *o3;
+ float u, v, l, dl, hox, hoy, detsh, fac, deler, alpha;
+ char *cp1, *cp2, *cp3;
+
+/* RE_error(RE_TRACE_COUNTER, fname); */
+
+#ifdef RE_FAKE_FACE_PIXELS
+ collector[0] = 0;
+ collector[1] = 0;
+ collector[2] = RE_UNITY_COLOUR_FLOAT;
+ collector[3] = RE_UNITY_COLOUR_FLOAT;
+ /* try to keep the rest as clean as possible... */
+ if( ((vlaknr & 0x7FFFFF) <= R.totvlak)
+ && ! ((R.vlaknr== -1)||(vlaknr<=0)) ) {
+ /* a bit superfluous to do this always, but */
+ /* when this is switched on, it doesn't matter */
+ vlr= RE_findOrAddVlak( (vlaknr-1) & 0x7FFFFF);
+ } else vlr = NULL;
+ return vlr;
+#endif
+
+ if(R.vlaknr== -1) { /* doet initrender */
+ /* also set in the pixelrender loop */
+ vlr= R.vlr= 0;
+ }
+
+ if(vlaknr<=0) { /* sky */
+ R.vlaknr= 0;
+ collector[3] = 0.0;
+ }
+ else if( (vlaknr & 0x7FFFFF) <= R.totvlak) {
+
+ /* What follows now is a large bunch of texture coordinate mappings. */
+ /* When this face is the same as the previous one, that means all */
+ /* the coordinate remapping does not need to be recomputed. */
+ if(vlaknr!=R.vlaknr) {
+
+ vlr= RE_findOrAddVlak( (vlaknr-1) & 0x7FFFFF);
+
+ R.mat= vlr->mat;
+ R.matren= R.mat->ren;
+
+ if(R.matren==0) { /* tijdelijk voor debug */
+ collector[3] = RE_UNITY_COLOUR_FLOAT;
+ collector[2] = 0.0;
+ collector[1] = RE_UNITY_COLOUR_FLOAT;
+ collector[0] = RE_UNITY_COLOUR_FLOAT;
+ return NULL;
+ }
+
+ R.vlr= vlr;
+
+ R.vno= vlr->n;
+ R.osatex= (R.matren->texco & TEXCO_OSA);
+ R.vlaknr= vlaknr;
+
+ v1= vlr->v1;
+ dvlak= MTC_dot3Float(v1->co, vlr->n);
+
+ if( (vlr->flag & R_SMOOTH) || (R.matren->texco & NEED_UV)) { /* uv nodig */
+ if(vlaknr & 0x800000) {
+ v2= vlr->v3;
+ v3= vlr->v4;
+ }
+ else {
+ v2= vlr->v2;
+ v3= vlr->v3;
+ }
+
+ if(vlr->snproj==0) {
+ t00= v3->co[0]-v1->co[0]; t01= v3->co[1]-v1->co[1];
+ t10= v3->co[0]-v2->co[0]; t11= v3->co[1]-v2->co[1];
+ }
+ else if(vlr->snproj==1) {
+ t00= v3->co[0]-v1->co[0]; t01= v3->co[2]-v1->co[2];
+ t10= v3->co[0]-v2->co[0]; t11= v3->co[2]-v2->co[2];
+ }
+ else {
+ t00= v3->co[1]-v1->co[1]; t01= v3->co[2]-v1->co[2];
+ t10= v3->co[1]-v2->co[1]; t11= v3->co[2]-v2->co[2];
+ }
+
+ detsh= t00*t11-t10*t01;
+ t00/= detsh; t01/=detsh;
+ t10/=detsh; t11/=detsh;
+
+ if(vlr->flag & R_SMOOTH) { /* puno's goedzetten */
+ if(vlr->puno & ME_FLIPV1) MTC_cp3FloatInv(v1->n, n1);
+ else MTC_cp3Float(v1->n, n1);
+
+ if(vlaknr & 0x800000) {
+ if(vlr->puno & ME_FLIPV3) MTC_cp3FloatInv(v2->n, n2);
+ else MTC_cp3Float(v2->n, n2);
+
+ if(vlr->puno & ME_FLIPV4) MTC_cp3FloatInv(v3->n, n3);
+ else MTC_cp3Float(v3->n, n3);
+ }
+ else {
+ if(vlr->puno & ME_FLIPV2) MTC_cp3FloatInv(v2->n, n2);
+ else MTC_cp3Float(v2->n, n2);
+
+ if(vlr->puno & ME_FLIPV3) MTC_cp3FloatInv(v3->n, n3);
+ else MTC_cp3Float(v3->n, n3);
+ }
+ }
+ if(R.matren->texco & TEXCO_STICKY) {
+ s00= v3->ho[0]/v3->ho[3] - v1->ho[0]/v1->ho[3];
+ s01= v3->ho[1]/v3->ho[3] - v1->ho[1]/v1->ho[3];
+ s10= v3->ho[0]/v3->ho[3] - v2->ho[0]/v2->ho[3];
+ s11= v3->ho[1]/v3->ho[3] - v2->ho[1]/v2->ho[3];
+
+ detsh= s00*s11-s10*s01;
+ s00/= detsh; s01/=detsh;
+ s10/=detsh; s11/=detsh;
+ }
+ }
+ } /* end of if vlaknr*/
+
+ /* This trafo might be migrated to a separate function. It is used */
+ /* quite often. */
+ /* COXYZ nieuwe methode */
+ if( (G.special1 & G_HOLO)
+ && (((Camera *)G.scene->camera->data)->flag & CAM_HOLO2) ) {
+ R.view[0]= (x+(R.xstart)+1.0+holoofs);
+ }
+ else {
+ R.view[0]= (x+(R.xstart)+1.0);
+ }
+
+ if(R.flag & R_SEC_FIELD) {
+ if(R.r.mode & R_ODDFIELD) R.view[1]= (y+R.ystart+0.5)*R.ycor;
+ else R.view[1]= (y+R.ystart+1.5)*R.ycor;
+ }
+ else R.view[1]= (y+R.ystart+1.0)*R.ycor;
+
+ R.view[2]= -R.viewfac;
+
+ if(R.r.mode & R_PANORAMA) {
+ float panoco, panosi;
+ panoco = getPanovCo();
+ panosi = getPanovSi();
+ u= R.view[0]; v= R.view[2];
+
+ R.view[0]= panoco*u + panosi*v;
+ R.view[2]= -panosi*u + panoco*v;
+ }
+
+ deler= vlr->n[0]*R.view[0] + vlr->n[1]*R.view[1] + vlr->n[2]*R.view[2];
+ if (deler!=0.0) fac= R.zcor= dvlak/deler;
+ else fac= R.zcor= 0.0;
+
+ R.co[0]= fac*R.view[0];
+ R.co[1]= fac*R.view[1];
+ R.co[2]= fac*R.view[2];
+
+ if(R.osatex || (R.r.mode & R_SHADOW) ) {
+ u= dvlak/(deler-vlr->n[0]);
+ v= dvlak/(deler- R.ycor*vlr->n[1]);
+
+ O.dxco[0]= R.co[0]- (R.view[0]-1.0)*u;
+ O.dxco[1]= R.co[1]- (R.view[1])*u;
+ O.dxco[2]= R.co[2]- (R.view[2])*u;
+
+ O.dyco[0]= R.co[0]- (R.view[0])*v;
+ O.dyco[1]= R.co[1]- (R.view[1]-1.0*R.ycor)*v;
+ O.dyco[2]= R.co[2]- (R.view[2])*v;
+
+ }
+
+ fac= Normalise(R.view);
+ R.zcor*= fac; /* voor mist */
+
+ if(R.osatex) {
+ if( (R.matren->texco & TEXCO_REFL) ) {
+ O.dxview= 1.0/fac;
+ O.dyview= R.ycor/fac;
+ }
+ }
+
+ /* UV en TEX*/
+ if( (vlr->flag & R_SMOOTH) || (R.matren->texco & NEED_UV)) {
+ if(vlr->snproj==0) {
+ u= (R.co[0]-v3->co[0])*t11-(R.co[1]-v3->co[1])*t10;
+ v= (R.co[1]-v3->co[1])*t00-(R.co[0]-v3->co[0])*t01;
+ if(R.osatex) {
+ O.dxuv[0]= O.dxco[0]*t11- O.dxco[1]*t10;
+ O.dxuv[1]= O.dxco[1]*t00- O.dxco[0]*t01;
+ O.dyuv[0]= O.dyco[0]*t11- O.dyco[1]*t10;
+ O.dyuv[1]= O.dyco[1]*t00- O.dyco[0]*t01;
+ }
+ }
+ else if(vlr->snproj==1) {
+ u= (R.co[0]-v3->co[0])*t11-(R.co[2]-v3->co[2])*t10;
+ v= (R.co[2]-v3->co[2])*t00-(R.co[0]-v3->co[0])*t01;
+ if(R.osatex) {
+ O.dxuv[0]= O.dxco[0]*t11- O.dxco[2]*t10;
+ O.dxuv[1]= O.dxco[2]*t00- O.dxco[0]*t01;
+ O.dyuv[0]= O.dyco[0]*t11- O.dyco[2]*t10;
+ O.dyuv[1]= O.dyco[2]*t00- O.dyco[0]*t01;
+ }
+ }
+ else {
+ u= (R.co[1]-v3->co[1])*t11-(R.co[2]-v3->co[2])*t10;
+ v= (R.co[2]-v3->co[2])*t00-(R.co[1]-v3->co[1])*t01;
+ if(R.osatex) {
+ O.dxuv[0]= O.dxco[1]*t11- O.dxco[2]*t10;
+ O.dxuv[1]= O.dxco[2]*t00- O.dxco[1]*t01;
+ O.dyuv[0]= O.dyco[1]*t11- O.dyco[2]*t10;
+ O.dyuv[1]= O.dyco[2]*t00- O.dyco[1]*t01;
+ }
+ }
+ l= 1.0+u+v;
+
+ if(vlr->flag & R_SMOOTH) {
+ R.vn[0]= l*n3[0]-u*n1[0]-v*n2[0];
+ R.vn[1]= l*n3[1]-u*n1[1]-v*n2[1];
+ R.vn[2]= l*n3[2]-u*n1[2]-v*n2[2];
+
+ Normalise(R.vn);
+ if(R.osatex && (R.matren->texco & (TEXCO_NORM+TEXCO_REFL)) ) {
+ dl= O.dxuv[0]+O.dxuv[1];
+ O.dxno[0]= dl*n3[0]-O.dxuv[0]*n1[0]-O.dxuv[1]*n2[0];
+ O.dxno[1]= dl*n3[1]-O.dxuv[0]*n1[1]-O.dxuv[1]*n2[1];
+ O.dxno[2]= dl*n3[2]-O.dxuv[0]*n1[2]-O.dxuv[1]*n2[2];
+ dl= O.dyuv[0]+O.dyuv[1];
+ O.dyno[0]= dl*n3[0]-O.dyuv[0]*n1[0]-O.dyuv[1]*n2[0];
+ O.dyno[1]= dl*n3[1]-O.dyuv[0]*n1[1]-O.dyuv[1]*n2[1];
+ O.dyno[2]= dl*n3[2]-O.dyuv[0]*n1[2]-O.dyuv[1]*n2[2];
+
+ }
+ }
+ else {
+ VECCOPY(R.vn, vlr->n);
+ }
+
+ if(R.matren->mode & MA_ZINV) { /* z invert */
+ /* R.vn[0]= -R.vn[0]; */
+ /* R.vn[1]= -R.vn[1]; */
+ }
+
+ if(R.matren->texco & TEXCO_ORCO) {
+ if(v2->orco) {
+ o1= v1->orco;
+ o2= v2->orco;
+ o3= v3->orco;
+
+ R.lo[0]= l*o3[0]-u*o1[0]-v*o2[0];
+ R.lo[1]= l*o3[1]-u*o1[1]-v*o2[1];
+ R.lo[2]= l*o3[2]-u*o1[2]-v*o2[2];
+
+ if(R.osatex) {
+ dl= O.dxuv[0]+O.dxuv[1];
+ O.dxlo[0]= dl*o3[0]-O.dxuv[0]*o1[0]-O.dxuv[1]*o2[0];
+ O.dxlo[1]= dl*o3[1]-O.dxuv[0]*o1[1]-O.dxuv[1]*o2[1];
+ O.dxlo[2]= dl*o3[2]-O.dxuv[0]*o1[2]-O.dxuv[1]*o2[2];
+ dl= O.dyuv[0]+O.dyuv[1];
+ O.dylo[0]= dl*o3[0]-O.dyuv[0]*o1[0]-O.dyuv[1]*o2[0];
+ O.dylo[1]= dl*o3[1]-O.dyuv[0]*o1[1]-O.dyuv[1]*o2[1];
+ O.dylo[2]= dl*o3[2]-O.dyuv[0]*o1[2]-O.dyuv[1]*o2[2];
+ }
+ }
+ }
+
+ if(R.matren->texco & TEXCO_GLOB) {
+ VECCOPY(R.gl, R.co);
+ MTC_Mat4MulVecfl(R.viewinv, R.gl);
+ if(R.osatex) {
+ VECCOPY(O.dxgl, O.dxco);
+ MTC_Mat3MulVecfl(R.imat, O.dxco);
+ VECCOPY(O.dygl, O.dyco);
+ MTC_Mat3MulVecfl(R.imat, O.dyco);
+ }
+ }
+ if((R.matren->texco & TEXCO_UV) || (R.matren->mode & (MA_VERTEXCOL|MA_FACETEXTURE))) {
+ if(R.vlr->tface) {
+ float *uv1, *uv2, *uv3;
+
+ uv1= R.vlr->tface->uv[0];
+ if( (vlaknr & 0x800000) || (R.vlr->flag & R_FACE_SPLIT) ) {
+ uv2= R.vlr->tface->uv[2];
+ uv3= R.vlr->tface->uv[3];
+ }
+ else {
+ uv2= R.vlr->tface->uv[1];
+ uv3= R.vlr->tface->uv[2];
+ }
+
+ R.uv[0]= -1.0 + 2.0*(l*uv3[0]-u*uv1[0]-v*uv2[0]);
+ R.uv[1]= -1.0 + 2.0*(l*uv3[1]-u*uv1[1]-v*uv2[1]);
+
+ if(R.osatex) {
+ float duv[2];
+
+ dl= O.dxuv[0]+O.dxuv[1];
+ duv[0]= O.dxuv[0];
+ duv[1]= O.dxuv[1];
+
+ O.dxuv[0]= 2.0*(dl*uv3[0]-duv[0]*uv1[0]-duv[1]*uv2[0]);
+ O.dxuv[1]= 2.0*(dl*uv3[1]-duv[0]*uv1[1]-duv[1]*uv2[1]);
+
+ dl= O.dyuv[0]+O.dyuv[1];
+ duv[0]= O.dyuv[0];
+ duv[1]= O.dyuv[1];
+
+ O.dyuv[0]= 2.0*(dl*uv3[0]-duv[0]*uv1[0]-duv[1]*uv2[0]);
+ O.dyuv[1]= 2.0*(dl*uv3[1]-duv[0]*uv1[1]-duv[1]*uv2[1]);
+ }
+ }
+ else {
+ R.uv[0]= 2.0*(u+.5);
+ R.uv[1]= 2.0*(v+.5);
+ }
+ }
+ if(R.matren->texco & TEXCO_NORM) {
+ R.orn[0]= R.vn[0];
+ R.orn[1]= -R.vn[1];
+ R.orn[2]= R.vn[2];
+ }
+ if(R.matren->mode & MA_VERTEXCOL) {
+
+ /* some colour calculations here */
+ cp1= (char *)vlr->vcol;
+ if(cp1) {
+ if( (vlaknr & 0x800000) || (R.vlr->flag & R_FACE_SPLIT) ) {
+ cp2= (char *)(vlr->vcol+2);
+ cp3= (char *)(vlr->vcol+3);
+ }
+ else {
+ cp2= (char *)(vlr->vcol+1);
+ cp3= (char *)(vlr->vcol+2);
+ }
+ R.vcol[0]= (l*cp3[3]-u*cp1[3]-v*cp2[3])/255.0;
+ R.vcol[1]= (l*cp3[2]-u*cp1[2]-v*cp2[2])/255.0;
+ R.vcol[2]= (l*cp3[1]-u*cp1[1]-v*cp2[1])/255.0;
+
+ }
+ else {
+ R.vcol[0]= 0.0;
+ R.vcol[1]= 0.0;
+ R.vcol[2]= 0.0;
+ }
+ }
+ if(R.matren->mode & MA_FACETEXTURE) {
+ if((R.matren->mode & MA_VERTEXCOL)==0) {
+ R.vcol[0]= 1.0;
+ R.vcol[1]= 1.0;
+ R.vcol[2]= 1.0;
+ }
+ /* shading here */
+ if(vlr->tface) render_realtime_texture();
+ }
+
+ /* hierna klopt de u en v EN O.dxuv en O.dyuv niet meer */
+ if(R.matren->texco & TEXCO_STICKY) {
+ if(v2->sticky) {
+
+ /* opnieuw u en v berekenen */
+ hox= x/Zmulx -1.0;
+ hoy= y/Zmuly -1.0;
+ u= (hox - v3->ho[0]/v3->ho[3])*s11
+ - (hoy - v3->ho[1]/v3->ho[3])*s10;
+ v= (hoy - v3->ho[1]/v3->ho[3])*s00
+ - (hox - v3->ho[0]/v3->ho[3])*s01;
+ l= 1.0+u+v;
+
+ o1= v1->sticky;
+ o2= v2->sticky;
+ o3= v3->sticky;
+
+ R.sticky[0]= l*o3[0]-u*o1[0]-v*o2[0];
+ R.sticky[1]= l*o3[1]-u*o1[1]-v*o2[1];
+
+ if(R.osatex) {
+ O.dxuv[0]= s11/Zmulx;
+ O.dxuv[1]= - s01/Zmulx;
+ O.dyuv[0]= - s10/Zmuly;
+ O.dyuv[1]= s00/Zmuly;
+
+ dl= O.dxuv[0]+O.dxuv[1];
+ O.dxsticky[0]= dl*o3[0]-O.dxuv[0]*o1[0]-O.dxuv[1]*o2[0];
+ O.dxsticky[1]= dl*o3[1]-O.dxuv[0]*o1[1]-O.dxuv[1]*o2[1];
+ dl= O.dyuv[0]+O.dyuv[1];
+ O.dysticky[0]= dl*o3[0]-O.dyuv[0]*o1[0]-O.dyuv[1]*o2[0];
+ O.dysticky[1]= dl*o3[1]-O.dyuv[0]*o1[1]-O.dyuv[1]*o2[1];
+ }
+ }
+ }
+ }
+ else {
+ VECCOPY(R.vn, vlr->n);
+ }
+ if(R.matren->texco & TEXCO_WINDOW) {
+ R.winco[0]= (x+(R.xstart))/(float)R.afmx;
+ R.winco[1]= (y+(R.ystart))/(float)R.afmy;
+ }
+
+ /* After all texture coordinates are set and converted and */
+ /* transformed, we need to put some colour on it: */
+ shadeLampLusFloat();
+
+ /* MIST */
+ if( (R.wrld.mode & WO_MIST) && (R.matren->mode & MA_NOMIST)==0 ){
+ /* alpha returned in float? */
+ alpha= mistfactor(R.co);
+ }
+ else alpha= 1.0;
+
+ /* RAYTRACE (tijdelijk?) UITGESCHAKELD */
+
+ if(R.matren->alpha!=1.0 || alpha!=1.0) {
+ fac= alpha*(R.matren->alpha);
+
+ collector[0] *= fac; /* This applies to transparent faces! Even */
+ collector[1] *= fac; /* though it may seem to be a premul op, it */
+ collector[2] *= fac; /* isn't. */
+ collector[3] = fac; /* doesn't need scaling? */
+ }
+ else {
+ collector[3] = 1.0;
+ }
+ }
+ else {
+ collector[0] = 1.0;
+ collector[1] = 1.0;
+ collector[2] = 0.0;
+ collector[3] = 1.0;
+ }
+
+ /* Spothalos: do this here for covered pixels. It seems messy to place */
+ /* it here, structure-wise, but it's more efficient. Also, not having it */
+ /* here makes it difficult to do proper overlaying later on. */
+ /* It starts off with a coordinate transform again. */
+ if(R.flag & R_LAMPHALO) {
+ if(vlaknr<=0) { /* bereken viewvec en zet R.co op far */
+
+ /* this view vector stuff should get its own function */
+ if( (G.special1 & G_HOLO) &&
+ ((Camera *)G.scene->camera->data)->flag & CAM_HOLO2) {
+ R.view[0]= (x+(R.xstart)+1.0+holoofs);
+ } else {
+ R.view[0]= (x+(R.xstart)+1.0);
+ }
+
+ if(R.flag & R_SEC_FIELD) {
+ if(R.r.mode & R_ODDFIELD) R.view[1]= (y+R.ystart+0.5)*R.ycor;
+ else R.view[1]= (y+R.ystart+1.5)*R.ycor;
+ } else {
+ R.view[1]= (y+R.ystart+1.0)*R.ycor;
+ }
+
+ R.view[2]= -R.viewfac;
+
+ if(R.r.mode & R_PANORAMA) {
+ float panoco, panosi;
+ panoco = getPanovCo();
+ panosi = getPanovSi();
+ u= R.view[0]; v= R.view[2];
+
+ R.view[0]= panoco*u + panosi*v;
+ R.view[2]= -panosi*u + panoco*v;
+ }
+
+ R.co[2]= 0.0;
+
+ }
+
+ shadeSpotHaloPixelFloat(collector);
+/* renderspothaloFix(collector); */
+
+ }
+
+#ifdef RE_PIXSHADE_FULL_SAFETY
+ if (!vlr) RE_error(RE_BAD_DATA_POINTER, fname);
+#endif
+
+ return vlr;
+
+} /* end of void renderFacePixelFloat(float x, float y, int vlaknr) */
+
+/* ------------------------------------------------------------------------- */
+/*
+ - uses R.view to determine which pixel, I think?
+ - the spothalo is dumped quite unceremoniously on top of the col vector
+ This function is also (sort of) implemented in shadespothalofix, but without
+ all the clipping stuff. Somehow, the clipping here is _quite_ critical.
+ */
+void shadeSpotHaloPixelFloat(float *col)
+{
+ LampRen *lar;
+ float factor = 0.0;
+ int a;
+ float rescol[4];
+
+
+ for(a=0; a<R.totlamp; a++) {
+ lar= R.la[a];
+ if(lar->type==LA_SPOT && (lar->mode & LA_HALO) && lar->haint>0) {
+
+ if(lar->org) {
+ lar->r= lar->org->r;
+ lar->g= lar->org->g;
+ lar->b= lar->org->b;
+ }
+
+ /* determines how much spothalo we see */
+ spotHaloFloat(lar, R.view, &factor);
+
+ if(factor>0.0) {
+
+ /* Why is alpha clipped? */
+ if(factor > RE_FULL_COLOUR_FLOAT) rescol[3]= 1.0;
+ else rescol[3]= factor;
+
+ /* erg vervelend: gammagecorrigeerd renderen EN addalphaADD */
+ /* gaat niet goed samen */
+ /* eigenlijk moet er een aparte 'optel' gamma komen */
+ /*
+ There is a strange thing here: the spothalo seems to be
+ calculated in the space you would get when you go from
+ value space through inverse gamma! So we gamma-transform
+ to value-space, then integrate, blend, and gamma correct
+ _again_.
+ */
+
+ rescol[0] = factor * lar->r; /* Lampren rgb's are floats */
+ rescol[1] = factor * lar->g;
+ rescol[2] = factor * lar->b;
+
+ /* ---->add values, disregard alpha */
+ /* - check for dest. alpha = 0. If so , just copy */
+ /* this is a slightly different approach: I do the gamma */
+ /* correction BEFORE the addition. What does the other */
+ /* approach do? */
+ if (col[3]< RE_EMPTY_COLOUR_FLOAT) {
+ col[0] = gammaCorrect(rescol[0]);
+ col[1] = gammaCorrect(rescol[1]);
+ col[2] = gammaCorrect(rescol[2]);
+ col[3] = rescol[3];
+ } else {
+ col[0] += gammaCorrect(rescol[0]);
+ col[1] += gammaCorrect(rescol[1]);
+ col[2] += gammaCorrect(rescol[2]);
+ col[3] += rescol[3];
+ }
+
+ /* this clipping may have to go? Actually, if it's */
+ /* done sooner, it may be more efficient */
+ if(col[0] > RE_FULL_COLOUR_FLOAT) col[0] = 1.0;
+ if(col[1] > RE_FULL_COLOUR_FLOAT) col[1] = 1.0;
+ if(col[2] > RE_FULL_COLOUR_FLOAT) col[2] = 1.0;
+ if(col[3] > RE_FULL_COLOUR_FLOAT) col[3] = 1.0;
+ if(col[0] < RE_EMPTY_COLOUR_FLOAT) col[0] = 0.0;
+ if(col[1] < RE_EMPTY_COLOUR_FLOAT) col[1] = 0.0;
+ if(col[2] < RE_EMPTY_COLOUR_FLOAT) col[2] = 0.0;
+ if(col[3] < RE_EMPTY_COLOUR_FLOAT) col[3] = 0.0;
+ }
+ }
+ }
+
+ if(col[0] < RE_EMPTY_COLOUR_FLOAT) col[0] = 0.0;
+ if(col[1] < RE_EMPTY_COLOUR_FLOAT) col[1] = 0.0;
+ if(col[2] < RE_EMPTY_COLOUR_FLOAT) col[2] = 0.0;
+ if(col[3] < RE_EMPTY_COLOUR_FLOAT) col[3] = 0.0;
+
+}
+
+/* ------------------------------------------------------------------------- */
+
+void spotHaloFloat(struct LampRen *lar, float *view, float *intens)
+{
+ double a, b, c, disc, nray[3], npos[3];
+ float t0, t1 = 0.0, t2= 0.0, t3, haint;
+ float p1[3], p2[3], ladist, maxz = 0.0, maxy = 0.0;
+ int snijp, doclip=1, use_yco=0;
+ int ok1=0, ok2=0;
+
+ *intens= 0.0;
+ haint= lar->haint;
+
+ VECCOPY(npos, lar->sh_invcampos); /* in initlamp berekend */
+
+ /* view roteren */
+ VECCOPY(nray, view);
+ MTC_Mat3MulVecd(lar->imat, nray);
+
+ if(R.wrld.mode & WO_MIST) {
+ /* een beetje patch... */
+ R.zcor= -lar->co[2];
+ haint *= mistfactor(lar->co);
+ if(haint==0.0) {
+ return;
+ }
+ }
+
+
+ /* maxz roteren */
+ if(R.co[2]==0) doclip= 0; /* is als halo op sky */
+ else {
+ p1[0]= R.co[0]-lar->co[0];
+ p1[1]= R.co[1]-lar->co[1];
+ p1[2]= R.co[2]-lar->co[2];
+
+ maxz= lar->imat[0][2]*p1[0]+lar->imat[1][2]*p1[1]+lar->imat[2][2]*p1[2];
+ maxz*= lar->sh_zfac;
+ maxy= lar->imat[0][1]*p1[0]+lar->imat[1][1]*p1[1]+lar->imat[2][1]*p1[2];
+
+ if( fabs(nray[2]) <0.000001 ) use_yco= 1;
+ }
+
+ /* z scalen zodat het volume genormaliseerd is */
+ nray[2]*= lar->sh_zfac;
+ /* nray hoeft niet genormaliseerd */
+
+ ladist= lar->sh_zfac*lar->dist;
+
+ /* oplossen */
+ a = nray[0] * nray[0] + nray[1] * nray[1] - nray[2]*nray[2];
+ b = nray[0] * npos[0] + nray[1] * npos[1] - nray[2]*npos[2];
+ c = npos[0] * npos[0] + npos[1] * npos[1] - npos[2]*npos[2];
+
+ snijp= 0;
+ if (fabs(a) < 0.00000001) {
+ /*
+ * Only one intersection point...
+ */
+ return;
+ }
+ else {
+ disc = b*b - a*c;
+
+ if(disc==0.0) {
+ t1=t2= (-b)/ a;
+ snijp= 2;
+ }
+ else if (disc > 0.0) {
+ disc = sqrt(disc);
+ t1 = (-b + disc) / a;
+ t2 = (-b - disc) / a;
+ snijp= 2;
+ }
+ }
+ if(snijp==2) {
+ /* sorteren */
+ if(t1>t2) {
+ a= t1; t1= t2; t2= a;
+ }
+
+ /* z van snijpunten met diabolo */
+ p1[2]= npos[2] + t1*nray[2];
+ p2[2]= npos[2] + t2*nray[2];
+
+ /* beide punten evalueren */
+ if(p1[2]<=0.0) ok1= 1;
+ if(p2[2]<=0.0 && t1!=t2) ok2= 1;
+
+ /* minstens 1 punt met negatieve z */
+ if(ok1==0 && ok2==0) return;
+
+ /* snijpunt met -ladist, de bodem van de kegel */
+ if(use_yco==0) {
+ t3= (-ladist-npos[2])/nray[2];
+
+ /* moet 1 van de snijpunten worden vervangen? */
+ if(ok1) {
+ if(p1[2]<-ladist) t1= t3;
+ }
+ else {
+ ok1= 1;
+ t1= t3;
+ }
+ if(ok2) {
+ if(p2[2]<-ladist) t2= t3;
+ }
+ else {
+ ok2= 1;
+ t2= t3;
+ }
+ }
+ else if(ok1==0 || ok2==0) return;
+
+ /* minstens 1 zichtbaar snijpunt */
+ if(t1<0.0 && t2<0.0) return;
+
+ if(t1<0.0) t1= 0.0;
+ if(t2<0.0) t2= 0.0;
+
+ if(t1==t2) return;
+
+ /* voor zekerheid nog eens sorteren */
+ if(t1>t2) {
+ a= t1; t1= t2; t2= a;
+ }
+
+ /* t0 berekenen: is de maximale zichtbare z (als halo door vlak */
+ /* doorsneden wordt) */
+ if(doclip) {
+ if(use_yco==0) t0= (maxz-npos[2])/nray[2];
+ else t0= (maxy-npos[1])/nray[1];
+
+ if(t0<t1) return;
+ if(t0<t2) t2= t0;
+ }
+
+ /* bereken punten */
+ p1[0]= npos[0] + t1*nray[0];
+ p1[1]= npos[1] + t1*nray[1];
+ p1[2]= npos[2] + t1*nray[2];
+ p2[0]= npos[0] + t2*nray[0];
+ p2[1]= npos[1] + t2*nray[1];
+ p2[2]= npos[2] + t2*nray[2];
+
+
+ /* nu hebben we twee punten, hiermee maken we drie lengtes */
+
+ a= sqrt(p1[0]*p1[0]+p1[1]*p1[1]+p1[2]*p1[2]);
+ b= sqrt(p2[0]*p2[0]+p2[1]*p2[1]+p2[2]*p2[2]);
+ c= VecLenf(p1, p2);
+
+ a/= ladist;
+ a= sqrt(a);
+ b/= ladist;
+ b= sqrt(b);
+ c/= ladist;
+
+ *intens= c*( (1.0-a)+(1.0-b) );
+
+ /* LET OP: a,b en c NIET op 1.0 clippen, dit geeft kleine
+ overflowtjes op de rand (vooral bij smalle halo's) */
+ if(*intens<=0.0) return;
+
+ /* zachte gebied */
+ /* vervalt omdat t0 nu ook voor p1/p2 wordt gebruikt */
+ /* if(doclip && t0<t2) { */
+ /* *intens *= (t0-t1)/(t2-t1); */
+ /* } */
+
+ *intens *= haint;
+
+ if(lar->shb && lar->shb->shadhalostep) {
+ /* from shadbuf.c, returns float */
+ *intens *= shadow_halo(lar, p1, p2);
+ }
+ /* if(lar->mode & LA_TEXTURE) do_lamphalo_tex(lar, p1, p2, intens); */
+
+ }
+} /* end of void spotHaloFloat(struct LampRen *, float *view, float *intens) */
+
+/* ------------------------------------------------------------------------- */
+
+void shadeLampLusFloat()
+{
+ LampRen *lar;
+ register Material *ma;
+ float i, inp, inpr, t, lv[3], lampdist, ld = 0;
+ float ir, ig, ib;
+ float isr=0,isg=0,isb=0;
+ float lvrot[3], *vn, *view, shadfac, soft;
+ int a;
+ float shadfacvec[3] = {1.0, 1.0, 1.0};
+
+ vn= R.vn;
+ view= R.view;
+ ma= R.matren;
+
+ /* aparte lus */
+ if(ma->mode & MA_ONLYSHADOW) {
+ shadfac= ir= 0.0;
+ for(a=0; a<R.totlamp; a++) {
+ lar= R.la[a];
+
+ if(lar->mode & LA_LAYER) if((lar->lay & R.vlr->lay)==0) continue;
+
+ if(lar->shb) {
+ /* alleen testen binnen spotbundel */
+ lv[0]= R.co[0]-lar->co[0];
+ lv[1]= R.co[1]-lar->co[1];
+ lv[2]= R.co[2]-lar->co[2];
+ Normalise(lv);
+ inpr= lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2];
+ if(inpr>lar->spotsi) {
+
+ inp= vn[0]*lv[0] + vn[1]*lv[1] + vn[2]*lv[2];
+
+ RE_testshadowbuf(lar->shadowBufOb, lar->shb, inp, shadfacvec);
+/* testshadowbuf(lar->shb, inp, shadfacvec); */
+
+ i= shadfacvec[0];
+
+ t= inpr - lar->spotsi;
+ if(t<lar->spotbl && lar->spotbl!=0.0) {
+ t/= lar->spotbl;
+ t*= t;
+ i= t*i+(1.0-t);
+ }
+
+ shadfac+= i;
+ ir+= 1.0;
+ }
+ else {
+ shadfac+= 1.0;
+ ir+= 1.0;
+ }
+ }
+ }
+ if(ir>0.0) shadfac/= ir;
+ ma->alpha= (R.mat->alpha)*(1.0-shadfac);
+
+ collector[0] = 0.0;
+ collector[1] = 0.0;
+ collector[2] = 0.0;
+ /* alpha is not set.... why?*/
+ return;
+ }
+
+ if(ma->mode & (MA_VERTEXCOLP|MA_FACETEXTURE)) {
+ ma->r= R.vcol[0];
+ ma->g= R.vcol[1];
+ ma->b= R.vcol[2];
+ }
+
+ /* mirror reflection colour */
+ R.refcol[0]= R.refcol[1]= R.refcol[2]= R.refcol[3]= 0.0;
+
+ if(ma->texco) {
+
+ if(ma->texco & TEXCO_REFL) {
+ RE_calc_R_ref();
+ }
+
+ if(ma->mode & (MA_VERTEXCOLP|MA_FACETEXTURE)) {
+ R.mat->r= R.vcol[0];
+ R.mat->g= R.vcol[1];
+ R.mat->b= R.vcol[2];
+ }
+
+ do_material_tex();
+ }
+
+ if(ma->mode & MA_SHLESS) {
+ if( (ma->mode & (MA_VERTEXCOL+MA_VERTEXCOLP+MA_FACETEXTURE) )) {
+ ir= R.vcol[0]*ma->r;
+ ig= R.vcol[1]*ma->g;
+ ib= R.vcol[2]*ma->b;
+ }
+ else {
+ ir= ma->r; /* apparently stored as [0,1]? */
+ ig= ma->g;
+ ib= ma->b;
+ }
+
+ collector[0] = ir; /* no clipping, no alpha */
+ collector[1] = ig;
+ collector[2] = ib;
+ return;
+ }
+
+ if( (ma->mode & (MA_VERTEXCOL+MA_VERTEXCOLP))== MA_VERTEXCOL ) {
+ ir= ma->emit+R.vcol[0];
+ ig= ma->emit+R.vcol[1];
+ ib= ma->emit+R.vcol[2];
+ }
+ else ir= ig= ib= ma->emit;
+
+ for(a=0; a<R.totlamp; a++) {
+ lar= R.la[a];
+
+ /* test op lamplayer */
+ if(lar->mode & LA_LAYER) if((lar->lay & R.vlr->lay)==0) continue;
+
+ /* lampdist berekening */
+ if(lar->type==LA_SUN || lar->type==LA_HEMI) {
+ VECCOPY(lv, lar->vec);
+ lampdist= 1.0;
+ }
+ else {
+ lv[0]= R.co[0]-lar->co[0];
+ lv[1]= R.co[1]-lar->co[1];
+ lv[2]= R.co[2]-lar->co[2];
+ ld= sqrt(lv[0]*lv[0]+lv[1]*lv[1]+lv[2]*lv[2]);
+ lv[0]/= ld;
+ lv[1]/= ld;
+ lv[2]/= ld;
+
+ /* ld wordt verderop nog gebruikt (texco's) */
+
+ if(lar->mode & LA_QUAD) {
+ t= 1.0;
+ if(lar->ld1>0.0)
+ t= lar->dist/(lar->dist+lar->ld1*ld);
+ if(lar->ld2>0.0)
+ t*= lar->distkw/(lar->distkw+lar->ld2*ld*ld);
+
+ lampdist= t;
+ }
+ else {
+ lampdist= (lar->dist/(lar->dist+ld));
+ }
+
+ if(lar->mode & LA_SPHERE) {
+ t= lar->dist - ld;
+ if(t<0.0) continue;
+
+ t/= lar->dist;
+ lampdist*= (t);
+ }
+
+ }
+
+ if(lar->mode & LA_TEXTURE) do_lamp_tex(lar, lv);
+
+ if(lar->type==LA_SPOT) {
+
+ /* hier de fie Inp() vertaagt! */
+
+ if(lar->mode & LA_SQUARE) {
+ if(lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2]>0.0) {
+ float x;
+
+ /* rotate view to lampspace */
+ VECCOPY(lvrot, lv);
+ MTC_Mat3MulVecfl(lar->imat, lvrot);
+
+ x= MAX2(fabs(lvrot[0]/lvrot[2]) , fabs(lvrot[1]/lvrot[2]));
+ /* 1.0/(sqrt(1+x*x)) is equivalent to cos(atan(x)) */
+
+ inpr= 1.0/(sqrt(1+x*x));
+ }
+ else inpr= 0.0;
+ }
+ else {
+ inpr= lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2];
+ }
+
+ t= lar->spotsi;
+ if(inpr<t) continue;
+ else {
+ t= inpr-t;
+ i= 1.0;
+ soft= 1.0;
+ if(t<lar->spotbl && lar->spotbl!=0.0) {
+ /* zachte gebied */
+ i= t/lar->spotbl;
+ t= i*i;
+ soft= (3.0*t-2.0*t*i);
+ inpr*= soft;
+ }
+ if(lar->mode & LA_ONLYSHADOW && lar->shb) {
+ if(ma->mode & MA_SHADOW) {
+ /* inprodukt positief: voorzijde vlak! */
+ inp= vn[0]*lv[0] + vn[1]*lv[1] + vn[2]*lv[2];
+ if(inp>0.0) {
+
+ /* testshadowbuf==0.0 : 100% schaduw */
+ RE_testshadowbuf(lar->shadowBufOb, lar->shb, inp, shadfacvec);
+/* testshadowbuf(lar->shb, inp, shadfacvec); */
+ shadfac = 1.0 - shadfacvec[0];
+
+ if(shadfac>0.0) {
+ shadfac*= inp*soft*lar->energy;
+ ir -= shadfac;
+ ig -= shadfac;
+ ib -= shadfac;
+
+ continue;
+ }
+ }
+ }
+ }
+ lampdist*=inpr;
+ }
+ if(lar->mode & LA_ONLYSHADOW) continue;
+
+ if(lar->mode & LA_OSATEX) {
+ R.osatex= 1; /* signaal voor multitex() */
+
+ O.dxlv[0]= lv[0] - (R.co[0]-lar->co[0]+O.dxco[0])/ld;
+ O.dxlv[1]= lv[1] - (R.co[1]-lar->co[1]+O.dxco[1])/ld;
+ O.dxlv[2]= lv[2] - (R.co[2]-lar->co[2]+O.dxco[2])/ld;
+
+ O.dylv[0]= lv[0] - (R.co[0]-lar->co[0]+O.dyco[0])/ld;
+ O.dylv[1]= lv[1] - (R.co[1]-lar->co[1]+O.dyco[1])/ld;
+ O.dylv[2]= lv[2] - (R.co[2]-lar->co[2]+O.dyco[2])/ld;
+ }
+
+ }
+
+ /* inprodukt en reflectivity*/
+ inp=i= vn[0]*lv[0] + vn[1]*lv[1] + vn[2]*lv[2];
+ if(lar->type==LA_HEMI) {
+ i= 0.5*i+0.5;
+ }
+ if(i>0.0) {
+ i*= lampdist*ma->ref;
+ }
+
+ /* schaduw en spec */
+ if(i> -0.41) { /* beetje willekeurig, beetje getest */
+ shadfac= 1.0;
+ if(lar->shb) {
+ if(ma->mode & MA_SHADOW) {
+ float shadfacvec[3] = {1.0, 1.0, 1.0};
+ RE_testshadowbuf(lar->shadowBufOb, lar->shb, inp, shadfacvec);
+/* testshadowbuf(lar->shb, inp, shadfacvec); */
+ shadfac = shadfacvec[0];
+
+/* shadfac = 1.0; : no shadow */
+ if(shadfac==0.0) continue;
+ i*= shadfac;
+ }
+ }
+ /* specularity */
+
+ if(ma->spec!=0.0) {
+
+ if(lar->type==LA_SUN || lar->type==LA_HEMI) {
+ if(lar->type==LA_SUN) {
+ lv[2]-= 1.0;
+ }
+ else {
+ lv[0]+= view[0];
+ lv[1]+= view[1];
+ lv[2]+= view[2];
+ }
+
+ Normalise(lv);
+
+ t= vn[0]*lv[0]+vn[1]*lv[1]+vn[2]*lv[2];
+
+ if(lar->type==LA_HEMI) {
+ t= 0.5*t+0.5;
+ }
+ /* let op: shadfac en lampdist uit onderstaande */
+
+ /* no more speclim */
+
+ t= ma->spec*RE_Spec(t, ma->har);
+ isr+= t*(lar->r * ma->specr);
+ isg+= t*(lar->g * ma->specg);
+ isb+= t*(lar->b * ma->specb);
+ }
+ else {
+ /* Does specular reflection? This would be the place */
+ /* to put BRDFs. */
+ t= shadfac*ma->spec*lampdist*CookTorr(vn, lv, view, ma->har);
+ isr+= t*(lar->r * ma->specr);
+ isg+= t*(lar->g * ma->specg);
+ isb+= t*(lar->b * ma->specb);
+ }
+ }
+ }
+ if(i>0.0) {
+ ir+= i*lar->r;
+ ig+= i*lar->g;
+ ib+= i*lar->b;
+ }
+ }
+
+ /* clipping: maybe don't clip? (nzc) */
+ /* yes, it shouldn't be done... unfortunately the current
+ * gammaCorrect implementation doesn't handle negative values
+ * correctly ( (-1)^2 = 1!!) (ton)
+ */
+/* if(ir<0.0) ir= 0.0; */
+/* if(ig<0.0) ig= 0.0; */
+/* if(ib<0.0) ib= 0.0; */
+/* if(isr<0.0) isr= 0.0; */
+/* if(isg<0.0) isg= 0.0; */
+/* if(isb<0.0) isb= 0.0; */
+ /* Well, it does now. -(1^2) = -1 :) (nzc) */
+
+ if(ma->mode & MA_ZTRA) { /* ztra shade */
+ if(ma->spectra!=0.0) {
+
+ t = MAX3(isr, isb, isg);
+ t *= ma->spectra;
+ if(t>1.0) t= 1.0;
+ if(ma->mapto & MAP_ALPHA) ma->alpha= (1.0-t)*ma->alpha+t;
+ else ma->alpha= (1.0-t)*R.mat->alpha+t;
+ }
+ }
+
+ if(R.refcol[0]==0.0) {
+ collector[0] = (ma->r * ir) + ma->ambr + isr;
+ collector[1] = (ma->g * ig) + ma->ambg + isg;
+ collector[2] = (ma->b * ib) + ma->ambb + isb;
+ /* clip for >0 ? */
+ }
+ else {
+ collector[0] = (ma->mirr * R.refcol[1])
+ + ((1.0 - (ma->mirr * R.refcol[0])) * ((ma->r * ir) + ma->ambr))
+ + isr;
+ collector[1] = (ma->mirg*R.refcol[2])
+ + ((1.0 - (ma->mirg * R.refcol[0])) * ((ma->g * ig) +ma->ambg))
+ +isg;
+ collector[2] = (ma->mirb*R.refcol[3])
+ + ((1.0 - (ma->mirb * R.refcol[0])) * ((ma->b * ib) +ma->ambb))
+ +isb;
+ }
+
+#ifdef RE_FAKE_LAMP_SHADE
+ collector[0] = 0.5;
+ collector[1] = 0.5;
+ collector[2] = 1.0;
+#endif
+
+}
+
+/* ------------------------------------------------------------------------- */
+
+void* renderHaloPixel(float x, float y, int haloNr) {
+ HaloRen *har = NULL;
+ float dist = 0.0;
+ unsigned int zz = 0;
+
+#ifdef RE_FAKE_HALO_PIXELS
+ collector[0] = RE_UNITY_COLOUR_FLOAT;
+ collector[1] = 0;
+ collector[2] = 0;
+ collector[3] = RE_UNITY_COLOUR_FLOAT;
+ har = RE_findOrAddHalo(haloNr); /* crash prevention */
+ return (void*) har;
+#endif
+
+ /* Find har to go with haloNr */
+ har = RE_findOrAddHalo(haloNr);
+
+ /* zz is a strange number... This call should effect that halo's are */
+ /* never cut? Seems a bit strange to me now... */
+ /* This might be the zbuffer depth */
+ zz = calcHaloZ(har, 0x7FFFFFFF);
+
+ /* distance of this point wrt. the halo center. Maybe xcor is also needed? */
+ dist = ((x - har->xs) * (x - har->xs))
+ + ((y - har->ys) * (y - har->ys) * R.ycor * R.ycor) ;
+
+ collector[0] = RE_ZERO_COLOUR_FLOAT; collector[1] = RE_ZERO_COLOUR_FLOAT;
+ collector[2] = RE_ZERO_COLOUR_FLOAT; collector[3] = RE_ZERO_COLOUR_FLOAT;
+
+ if (dist < har->radsq) {
+ shadeHaloFloat(har, collector, zz, dist,
+ (x - har->xs), (y - har->ys) * R.ycor, har->flarec);
+ /* make a second fake pixel? */
+#ifdef RE_FAKE_HALO_PIXELS_2
+ collector[0] = RE_UNITY_COLOUR_FLOAT;
+ collector[1] = 0;
+ collector[2] = 0;
+ collector[3] = RE_UNITY_COLOUR_FLOAT;
+#endif
+ }; /* else: this pixel is not rendered for this halo: no colour */
+
+ return (void*) har;
+
+} /* end of void* renderHaloPixel(float x, float y, int haloNr) */
+
+/* ------------------------------------------------------------------------- */
+
+extern float hashvectf[];
+void shadeHaloFloat(HaloRen *har,
+ float *col, unsigned int zz,
+ float dist, float xn,
+ float yn, short flarec)
+{
+ /* in col invullen */
+ /* migrate: fill collector */
+ float t, zn, radist, ringf=0.0, linef=0.0, alpha, si, co, colf[4];
+ int a;
+
+ if(R.wrld.mode & WO_MIST) {
+ if(har->type & HA_ONLYSKY) {
+ /* sterren geen mist */
+ alpha= har->alfa;
+ }
+ else {
+ /* een beetje patch... */
+ R.zcor= -har->co[2];
+ alpha= mistfactor(har->co)*har->alfa;
+ }
+ }
+ else alpha= har->alfa;
+
+ if(alpha==0.0) {
+ col[0] = 0.0;
+ col[1] = 0.0;
+ col[2] = 0.0;
+ col[3] = 0.0;
+ return;
+ }
+
+ radist= sqrt(dist);
+
+ /* let op: hiermee wordt gesjoemeld: flarec wordt op nul gezet in de pixstruct */
+ if(flarec) har->pixels+= (int)(har->rad-radist);
+
+ if(har->ringc) {
+ float *rc, fac;
+ int ofs;
+
+ /* per ring een alicirc */
+ ofs= har->seed;
+
+ for(a= har->ringc; a>0; a--, ofs+=2) {
+
+ rc= hashvectf + (ofs % 768);
+
+ fac= fabs( rc[1]*(har->rad*fabs(rc[0]) - radist) );
+
+ if(fac< 1.0) {
+ ringf+= (1.0-fac);
+ }
+ }
+ }
+
+ if(har->type & HA_VECT) {
+ dist= fabs( har->cos*(yn) - har->sin*(xn) )/har->rad;
+ if(dist>1.0) dist= 1.0;
+ if(har->tex) {
+ zn= har->sin*xn - har->cos*yn;
+ yn= har->cos*xn + har->sin*yn;
+ xn= zn;
+ }
+ }
+ else dist= dist/har->radsq;
+
+ if(har->type & HA_FLARECIRC) {
+
+ dist= 0.5+fabs(dist-0.5);
+
+ }
+
+ if(har->hard>=30) {
+ dist= sqrt(dist);
+ if(har->hard>=40) {
+ dist= sin(dist*M_PI_2);
+ if(har->hard>=50) {
+ dist= sqrt(dist);
+ }
+ }
+ }
+ else if(har->hard<20) dist*=dist;
+
+ dist=(1.0-dist);
+
+ if(har->linec) {
+ float *rc, fac;
+ int ofs;
+
+ /* per starpoint een aliline */
+ ofs= har->seed;
+
+ for(a= har->linec; a>0; a--, ofs+=3) {
+
+ rc= hashvectf + (ofs % 768);
+
+ fac= fabs( (xn)*rc[0]+(yn)*rc[1]);
+
+ if(fac< 1.0 ) {
+ linef+= (1.0-fac);
+ }
+ }
+
+ linef*= dist;
+
+ }
+
+ if(har->starpoints) {
+ float ster, hoek;
+ /* rotatie */
+ hoek= atan2(yn, xn);
+ hoek*= (1.0+0.25*har->starpoints);
+
+ co= cos(hoek);
+ si= sin(hoek);
+
+ hoek= (co*xn+si*yn)*(co*yn-si*xn);
+
+ ster= fabs(hoek);
+ if(ster>1.0) {
+ ster= (har->rad)/(ster);
+
+ if(ster<1.0) dist*= sqrt(ster);
+ }
+ }
+
+ /* halo wordt doorsneden? */
+ if(har->zs> zz-har->zd) {
+ t= ((float)(zz-har->zs))/(float)har->zd;
+ alpha*= sqrt(sqrt(t));
+ }
+
+ dist*= alpha;
+ ringf*= dist;
+ linef*= alpha;
+
+ if(dist<0.003) {
+ col[0] = 0.0;
+ col[1] = 0.0;
+ col[2] = 0.0;
+ col[3] = 0.0;
+ return;
+ }
+
+ /* The colour is either the rgb spec-ed by the user, or extracted from */
+ /* the texture */
+ if(har->tex) {
+ colf[3]= dist;
+ do_halo_tex(har, xn, yn, colf);
+ colf[0]*= colf[3];
+ colf[1]*= colf[3];
+ colf[2]*= colf[3];
+
+ }
+ else {
+ colf[0]= dist*har->r;
+ colf[1]= dist*har->g;
+ colf[2]= dist*har->b;
+ if(har->type & HA_XALPHA) colf[3]= dist*dist;
+ else colf[3]= dist;
+ }
+
+ if(har->mat && har->mat->mode & MA_HALO_SHADE) {
+ /* we test for lights because of preview... */
+ if(R.totlamp) render_lighting_halo(har, colf);
+ }
+
+ /* Next, we do the line and ring factor modifications. It seems we do */
+ /* uchar calculations, but it's basically doing float arith with a 255 */
+ /* scale factor. */
+ if(linef!=0.0) {
+ Material *ma= har->mat;
+ linef *= 255.0;
+
+ colf[0]+= linef * ma->specr;
+ colf[1]+= linef * ma->specg;
+ colf[2]+= linef * ma->specb;
+
+ if(har->type & HA_XALPHA) colf[3]+= linef*linef;
+ else colf[3]+= linef;
+ }
+ if(ringf!=0.0) {
+ Material *ma= har->mat;
+ ringf *= 255.0;
+
+ colf[0]+= ringf * ma->mirr;
+ colf[1]+= ringf * ma->mirg;
+ colf[2]+= ringf * ma->mirb;
+
+ if(har->type & HA_XALPHA) colf[3]+= ringf*ringf;
+ else colf[3]+= ringf;
+ }
+
+ /* convert to [0.0; 1.0] range */
+ col[0] = colf[0] / 255.0;
+ col[1] = colf[1] / 255.0;
+ col[2] = colf[2] / 255.0;
+ col[3] = colf[3];
+
+} /* end of shadeHaloFloat() */
+
+/* ------------------------------------------------------------------------- */
+
+void renderSpotHaloPixel(float x, float y, float* target)
+{
+ float u = 0.0, v = 0.0;
+
+#ifdef RE_FAKE_SPOTHALO_PIXELS
+ target[0] = 0.0;
+ target[1] = 1.0;
+ target[2] = 0.0;
+ target[3] = 1.0;
+ return;
+#endif
+
+ /* Strange fix? otherwise done inside shadepixel. It's sort */
+ /* of like telling this is a 'sky' pixel. */
+ R.vlaknr = 0;
+ target[3] = 0.0;
+
+ /*
+ Here's the viewvector setting again.
+ */
+ if( (G.special1 & G_HOLO) && ((Camera *)G.scene->camera->data)->flag & CAM_HOLO2) {
+ R.view[0]= (x+(R.xstart)+1.0+holoofs);
+ }
+ else {
+ R.view[0]= (x+(R.xstart)+1.0);
+ }
+
+ if(R.flag & R_SEC_FIELD) {
+ if(R.r.mode & R_ODDFIELD) R.view[1]= (y+R.ystart+0.5)*R.ycor;
+ else R.view[1]= (y+R.ystart+1.5)*R.ycor;
+ }
+ else R.view[1]= (y+R.ystart+1.0)*R.ycor;
+
+ R.view[2]= -R.viewfac;
+
+ if(R.r.mode & R_PANORAMA) {
+ float panoco, panosi;
+ panoco = getPanovCo();
+ panosi = getPanovSi();
+ u= R.view[0]; v= R.view[2];
+
+ R.view[0]= panoco*u + panosi*v;
+ R.view[2]= -panosi*u + panoco*v;
+ }
+
+ R.co[2]= 0.0;
+
+ /* This little function is a patch for spothalos on non-covered pixels. */
+ renderspothaloFix(target);
+
+} /* end of void renderSpotHaloPixel(float x, float y, float colbuf[4]) */
+
+/* ------------------------------------------------------------------------- */
+/*
+ This routine is only for sky-pixels. Therefore, no gamma needs to be done.
+ One strange side-effect is when you have a negative halo lamp. This suddenly
+ gives loads of colour. That particular case has been explicitly guarded: no
+ halo for negative halo spots!
+
+ This routine uses the viewvector in R... to determine what to shade. Just
+ deposit the colour to be blended in col.
+
+ I would like to add colours 'normally', so this routine would be the same
+ for spothalo on covered pixels, but that doesn't work. Some strange clipping
+ occurs...
+ */
+void renderspothaloFix(float *col)
+{
+ LampRen *lar;
+ float i;
+ int a;
+
+ for(a=0; a<R.totlamp; a++) {
+ lar= R.la[a];
+ if((lar->type==LA_SPOT)
+ && (lar->mode & LA_HALO)
+ && !(lar->mode & LA_NEG)
+ && (lar->haint>0)) {
+
+ if(lar->org) {
+ lar->r= lar->org->r;
+ lar->g= lar->org->g;
+ lar->b= lar->org->b;
+ }
+
+ /* returns the intensity in i */
+ spotHaloFloat(lar, R.view, &i);
+
+ if(i>0.0) {
+ /* Premul colours here! */
+ col[0] = i * lar->r;
+ col[1] = i * lar->g;
+ col[2] = i * lar->b;
+ col[3] = i;
+ }
+ }
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+/*
+
+ There are three different modes for blending sky behind a picture:
+ 1. sky = blend in sky directly
+ 2. premul = don't do sky, but apply alpha (so pretend the picture ends
+ exactly at it's boundaries)
+ 3. key = don't do anything
+ Now the stupid thing is that premul means do nothing for us, and key
+ we have to adjust a bit...
+
+*/
+
+/* Sky vars. */
+enum RE_SkyAlphaBlendingType keyingType = RE_ALPHA_SKY; /* The blending type */
+
+void setSkyBlendingMode(enum RE_SkyAlphaBlendingType mode) {
+ if ((RE_ALPHA_NODEF < mode) && (mode < RE_ALPHA_MAX) ) {
+ keyingType = mode;
+ } else {
+ /* error: false mode received */
+ keyingType = RE_ALPHA_SKY;
+ }
+}
+
+enum RE_SkyAlphaBlendingType getSkyBlendingMode() {
+ return keyingType;
+}
+
+/* This one renders into collector, as always. */
+void renderSkyPixelFloat(float x, float y)
+{
+#ifdef RE_FAKE_SKY_PIXELS
+ collector[0] = 1.0;
+ collector[1] = 1.0;
+ collector[2] = 0.0;
+ collector[3] = 1.0;
+ return;
+#endif
+
+ switch (keyingType) {
+ case RE_ALPHA_PREMUL:
+ /* Premul: don't fill, and don't change the values! */
+ case RE_ALPHA_KEY:
+ /*
+ Key: Leave pixels fully coloured, but retain alpha data, so you
+ can composit the picture later on.
+ - Should operate on the stack outcome!
+ */
+/* collector[0] = 0.0; */
+/* collector[1] = 0.0; */
+/* collector[2] = 0.0; */
+/* collector[3] = 0.0; */
+ collector[3]= 0.0;
+ collector[0]= R.wrld.horr;
+ collector[1]= R.wrld.horg;
+ collector[2]= R.wrld.horb;
+ break;
+ case RE_ALPHA_SKY:
+ /* Fill in the sky as if it were a normal face. */
+ shadeSkyPixel(x, y);
+ break;
+ default:
+ ; /* Error: illegal alpha blending state */
+ }
+}
+
+/*
+ Stuff the sky colour into the collector.
+ */
+void shadeSkyPixel(float fx, float fy) {
+
+ /*
+ The rules for sky:
+ 1. Draw an image, if a background image was provided. Stop
+ 2. get texture and colour blend, and combine these.
+ */
+
+ float fac;
+
+ /* 1. Do a backbuffer image: */
+ if(R.r.bufflag & 1) {
+ fillBackgroundImage(fx, fy);
+ return;
+ } else if((R.wrld.skytype & (WO_SKYBLEND+WO_SKYTEX))==0) {
+ /*
+ 2. Test for these types of sky. The old renderer always had to check for
+ coverage, but we don't need that anymore
+ - SKYBLEND or SKYTEX disabled: fill in a flat colour
+ - otherwise, do the appropriate mapping (tex or colour blend)
+ There used to be cached chars here, but they are not useful anymore
+ */
+ collector[0] = R.wrld.horr;
+ collector[1] = R.wrld.horg;
+ collector[2] = R.wrld.horb;
+ collector[3] = RE_UNITY_COLOUR_FLOAT;
+ } else {
+ /*
+ 3. Which type(s) is(are) this (these)? This has to be done when no simple
+ way of determining the colour exists.
+ */
+
+ /* This one true because of the context of this routine */
+/* if(rect[3] < 254) { */
+ if(R.wrld.skytype & WO_SKYPAPER) {
+ R.view[0]= (fx+(R.xstart))/(float)R.afmx;
+ R.view[1]= (fy+(R.ystart))/(float)R.afmy;
+ R.view[2]= 0.0;
+ }
+ else {
+ /* Wasn't this some pano stuff? */
+ R.view[0]= (fx+(R.xstart)+1.0);
+
+ if(R.flag & R_SEC_FIELD) {
+ if(R.r.mode & R_ODDFIELD) R.view[1]= (fy+R.ystart+0.5)*R.ycor;
+ else R.view[1]= (fy+R.ystart+1.5)*R.ycor;
+ }
+ else R.view[1]= (fy+R.ystart+1.0)*R.ycor;
+
+ R.view[2]= -R.viewfac;
+
+ fac= Normalise(R.view);
+ if(R.wrld.skytype & WO_SKYTEX) {
+ O.dxview= 1.0/fac;
+ O.dyview= R.ycor/fac;
+ }
+ }
+
+ if(R.r.mode & R_PANORAMA) {
+ float panoco, panosi;
+ float u, v;
+
+ panoco = getPanovCo();
+ panosi = getPanovSi();
+ u= R.view[0]; v= R.view[2];
+
+ R.view[0]= panoco*u + panosi*v;
+ R.view[2]= -panosi*u + panoco*v;
+ }
+
+ /* get sky colour in the collector */
+ shadeSkyPixelFloat(fy);
+ }
+
+
+}
+
+/* Only line number is important here. Result goes to collector[4] */
+void shadeSkyPixelFloat(float y)
+{
+
+ /* Why is this setting forced? Seems silly to me. It is tested in the texture unit. */
+ R.wrld.skytype |= WO_ZENUP;
+
+ /* Some view vector stuff. */
+ if(R.wrld.skytype & WO_SKYREAL) {
+
+ R.inprz= R.view[0]*R.grvec[0]+ R.view[1]*R.grvec[1]+ R.view[2]*R.grvec[2];
+
+ if(R.inprz<0.0) R.wrld.skytype-= WO_ZENUP;
+ R.inprz= fabs(R.inprz);
+ }
+ else if(R.wrld.skytype & WO_SKYPAPER) {
+ R.inprz= 0.5+ 0.5*R.view[1];
+ }
+ else {
+ /* the fraction of how far we are above the bottom of the screen */
+ R.inprz= fabs(0.5+ R.view[1]);
+ }
+
+ /* Careful: SKYTEX and SKYBLEND are NOT mutually exclusive! If */
+ /* SKYBLEND is active, the texture and colour blend are added. */
+ if(R.wrld.skytype & WO_SKYTEX) {
+ VECCOPY(R.lo, R.view);
+ if(R.wrld.skytype & WO_SKYREAL) {
+
+ MTC_Mat3MulVecfl(R.imat, R.lo);
+
+ SWAP(float, R.lo[1], R.lo[2]);
+
+ }
+
+ R.osatex= 0;
+
+ /* sky texture? I wonder how this manages to work... */
+ /* Does this communicate with R.wrld.hor{rgb}? Yes. */
+ do_sky_tex();
+ /* internally, T{rgb} are used for communicating colours in the */
+ /* texture pipe, externally, this particular routine uses the */
+ /* R.wrld.hor{rgb} thingies. */
+
+ }
+
+ /* Why are this R. members? */
+ if(R.inprz>1.0) R.inprz= 1.0;
+ R.inprh= 1.0-R.inprz;
+
+ /* No clipping, no conversion! */
+ if(R.wrld.skytype & WO_SKYBLEND) {
+ collector[0] = (R.inprh*R.wrld.horr + R.inprz*R.wrld.zenr);
+ collector[1] = (R.inprh*R.wrld.horg + R.inprz*R.wrld.zeng);
+ collector[2] = (R.inprh*R.wrld.horb + R.inprz*R.wrld.zenb);
+ } else {
+ /* Done when a texture was grabbed. */
+ collector[0]= R.wrld.horr;
+ collector[1]= R.wrld.horg;
+ collector[2]= R.wrld.horb;
+ }
+
+ collector[3]= RE_UNITY_COLOUR_FLOAT;
+ /* om verkeerde optimalisatie alphaover van flares te voorkomen */
+ /* ??? seems strange to me... This used to be a 1 when the colours */
+ /* were chars. might need a separate flag for this... */
+}
+
+
+/*
+ Render pixel (x,y) from the backbuffer into the collector
+
+ backbuf is type Image, backbuf->ibuf is an ImBuf. ibuf->rect is the
+ rgba data (32 bit total), in ibuf->x by ibuf->y pixels. Copying
+ should be really easy. I hope I understand the way ImBuf works
+ correctly. (nzc)
+*/
+void fillBackgroundImage(float x, float y)
+{
+
+ int iy, ix;
+ unsigned int* imBufPtr;
+ char *colSource;
+
+ /* This double check is bad... */
+ if (!(R.backbuf->ok)) {
+ /* Something went sour here... bail... */
+ collector[0] = 0.0;
+ collector[1] = 0.0;
+ collector[2] = 0.0;
+ collector[3] = 1.0;
+ return;
+ }
+ /* load image if not already done?*/
+ if(R.backbuf->ibuf==0) {
+ R.backbuf->ibuf= IMB_loadiffname(R.backbuf->name, IB_rect);
+ if(R.backbuf->ibuf==0) {
+ /* load failed .... keep skipping */
+ R.backbuf->ok= 0;
+ return;
+ }
+ }
+
+ /* Now for the real extraction: */
+ /* Get the y-coordinate of the scanline? */
+ iy= (int) ((y+R.afmy+R.ystart)*R.backbuf->ibuf->y)/(2*R.afmy);
+ ix= (int) ((x+R.afmx+R.xstart)*R.backbuf->ibuf->x)/(2*R.afmx);
+
+ /* correct in case of fields rendering: */
+ if(R.flag & R_SEC_FIELD) {
+ if((R.r.mode & R_ODDFIELD)==0) {
+ if( iy<R.backbuf->ibuf->y) iy++;
+ }
+ else {
+ if( iy>0) iy--;
+ }
+ }
+
+ /* Offset into the buffer: start of scanline y: */
+ imBufPtr = R.backbuf->ibuf->rect
+ + (iy * R.backbuf->ibuf->x)
+ + ix;
+
+ colSource = (char*) imBufPtr;
+
+ cpCharColV2FloatColV(colSource, collector);
+
+}
+
+/* eof */
diff --git a/source/blender/render/intern/source/renderHelp.c b/source/blender/render/intern/source/renderHelp.c
new file mode 100644
index 00000000000..c7294d0feeb
--- /dev/null
+++ b/source/blender/render/intern/source/renderHelp.c
@@ -0,0 +1,294 @@
+/**
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * Some helpful conversions/functions.
+ *
+ * $Id$
+ */
+
+#include <math.h>
+#include <limits.h>
+#include <stdlib.h>
+
+#include "render.h"
+#include "render_intern.h"
+#include "renderHelp.h"
+#include "zbuf.h"
+
+
+
+static float panovco, panovsi;
+static float panophi=0.0;
+static float tempPanoPhi;
+
+static int panotestclip(float *v);
+
+void pushTempPanoPhi(float p) {
+ tempPanoPhi = panophi;
+ panophi = p;
+}
+
+void popTempPanoPhi() {
+ panophi = tempPanoPhi;
+}
+
+float getPanoPhi(){
+ return panophi;
+}
+float getPanovCo(){
+ return panovco;
+}
+float getPanovSi(){
+ return panovsi;
+}
+
+void setPanoRot(int part)
+{
+/* extern float panovco, panovsi; */
+ static float alpha= 1.0;
+
+ /* part==0 alles initialiseren */
+
+ if(part==0) {
+
+ alpha= ((float)R.r.xsch)/R.viewfac;
+ alpha= 2.0*atan(alpha/2.0);
+ }
+
+
+ /* we roteren alles om de y-as met phi graden */
+
+ panophi= -0.5*(R.r.xparts-1)*alpha + part*alpha;
+
+ panovsi= sin(-panophi);
+ panovco= cos(-panophi);
+
+}
+
+
+
+
+static int panotestclip(float *v)
+{
+ /* gebruiken voor halo's en info's */
+ float abs4;
+ short c=0;
+
+ if((R.r.mode & R_PANORAMA)==0) return RE_testclip(v);
+
+ abs4= fabs(v[3]);
+
+ if(v[2]< -abs4) c=16; /* hier stond vroeger " if(v[2]<0) ", zie clippz() */
+ else if(v[2]> abs4) c+= 32;
+
+ if( v[1]>abs4) c+=4;
+ else if( v[1]< -abs4) c+=8;
+
+ abs4*= R.r.xparts;
+ if( v[0]>abs4) c+=2;
+ else if( v[0]< -abs4) c+=1;
+
+ return c;
+}
+
+/*
+
+ This adds the hcs coordinates to vertices. It iterates over all
+ vertices, halos and faces. After the conversion, we clip in hcs.
+
+ Elsewhere, all primites are converted to vertices.
+ Called in
+ - envmapping (envmap.c)
+ - shadow buffering (shadbuf.c)
+ - preparation for rendering (renderPreAndPost.c)
+
+*/
+
+/* move to renderer */
+void setzbufvlaggen( void (*projectfunc)(float *, float *) )
+/* ook homoco's */
+{
+ VlakRen *vlr = NULL;
+ VertRen *ver = NULL;
+ HaloRen *har = NULL;
+ float zn, vec[3], si, co, hoco[4];
+ int a;
+ float panophi = 0.0;
+
+ panophi = getPanoPhi();
+ si= sin(panophi);
+ co= cos(panophi);
+
+ /* calculate view coordinates (and zbuffer value) */
+ for(a=0; a< R.totvert;a++) {
+ if((a & 255)==0) ver= R.blove[a>>8];
+ else ver++;
+
+ if(R.r.mode & R_PANORAMA) {
+ vec[0]= co*ver->co[0] + si*ver->co[2];
+ vec[1]= ver->co[1];
+ vec[2]= -si*ver->co[0] + co*ver->co[2];
+ }
+ else {
+ VECCOPY(vec, ver->co);
+ }
+ /* Go from wcs to hcs ... */
+ projectfunc(vec, ver->ho);
+ /* ... and clip in that system. */
+ ver->clip = RE_testclip(ver->ho);
+ /*
+ Because all other ops are performed in other systems, this is
+ the only thing that has to be done.
+ */
+ }
+
+ /* calculate view coordinates (and zbuffer value) */
+ for(a=0; a<R.tothalo; a++) {
+ if((a & 255)==0) har= R.bloha[a>>8];
+ else har++;
+
+ if(R.r.mode & R_PANORAMA) {
+ vec[0]= co*har->co[0] + si*har->co[2];
+ vec[1]= har->co[1];
+ vec[2]= -si*har->co[0] + co*har->co[2];
+ }
+ else {
+ VECCOPY(vec, har->co);
+ }
+
+ projectfunc(vec, hoco);
+
+ hoco[3]*= 2.0;
+
+ if( panotestclip(hoco) ) {
+ har->miny= har->maxy= -10000; /* de render clipt 'm weg */
+ }
+ else if(hoco[3]<0.0) {
+ har->miny= har->maxy= -10000; /* de render clipt 'm weg */
+ }
+ else /* this seems to be strange code here...*/
+ {
+ zn= hoco[3]/2.0;
+ har->xs= 0.5*R.rectx*(1.0+hoco[0]/zn); /* the 0.5 negates the previous 2...*/
+ har->ys= 0.5*R.recty*(1.0+hoco[1]/zn);
+
+ /* this should be the zbuffer coordinate */
+ har->zs= 0x7FFFFF*(1.0+hoco[2]/zn);
+ /* taking this from the face clip functions? seems ok... */
+ har->zBufDist = 0x7FFFFFFF*(hoco[2]/zn);
+ vec[0]+= har->hasize;
+ projectfunc(vec, hoco);
+ vec[0]-= har->hasize;
+ zn= hoco[3];
+ har->rad= fabs(har->xs- 0.5*R.rectx*(1.0+hoco[0]/zn));
+
+ /* deze clip is eigenlijk niet OK */
+ if(har->type & HA_ONLYSKY) {
+ if(har->rad>3.0) har->rad= 3.0;
+ }
+
+ har->radsq= har->rad*har->rad;
+
+ har->miny= har->ys - har->rad/R.ycor;
+ har->maxy= har->ys + har->rad/R.ycor;
+
+ /* de Zd is bij pano nog steeds verkeerd: zie testfile in blenderbugs/halo+pano.blend */
+
+ vec[2]-= har->hasize; /* z is negatief, wordt anders geclipt */
+ projectfunc(vec, hoco);
+ zn= hoco[3];
+ zn= fabs(har->zs - 0x7FFFFF*(1.0+hoco[2]/zn));
+ har->zd= CLAMPIS(zn, 0, INT_MAX);
+
+ /* if( har->zs < 2*har->zd) { */
+ /* PRINT2(d, d, har->zs, har->zd); */
+ /* har->alfa= har->mat->alpha * ((float)(har->zs))/(float)(2*har->zd); */
+ /* } */
+
+ }
+
+ }
+
+ /* vlaggen op 0 zetten als eruit geclipt */
+ for(a=0; a<R.totvlak; a++) {
+ if((a & 255)==0) vlr= R.blovl[a>>8];
+ else vlr++;
+
+ vlr->flag |= R_VISIBLE;
+ if(vlr->v4) {
+ if(vlr->v1->clip & vlr->v2->clip & vlr->v3->clip & vlr->v4->clip) vlr->flag &= ~R_VISIBLE;
+ }
+ else if(vlr->v1->clip & vlr->v2->clip & vlr->v3->clip) vlr->flag &= ~R_VISIBLE;
+
+ }
+
+}
+
+/* ------------------------------------------------------------------------- */
+/* move to renderer */
+
+void set_normalflags(void)
+{
+ VlakRen *vlr = NULL;
+ float vec[3], xn, yn, zn;
+ int a1;
+
+ /* KLAP NORMAAL EN SNIJ PROJECTIE */
+ for(a1=0; a1<R.totvlak; a1++) {
+ if((a1 & 255)==0) vlr= R.blovl[a1>>8];
+ else vlr++;
+
+ if(vlr->flag & R_NOPUNOFLIP) {
+ /* render normaal flippen, wel niet zo netjes, maar anders dan moet de render() ook over... */
+ vlr->n[0]= -vlr->n[0];
+ vlr->n[1]= -vlr->n[1];
+ vlr->n[2]= -vlr->n[2];
+ }
+ else {
+
+ vec[0]= vlr->v1->co[0];
+ vec[1]= vlr->v1->co[1];
+ vec[2]= vlr->v1->co[2];
+
+ if( (vec[0]*vlr->n[0] +vec[1]*vlr->n[1] +vec[2]*vlr->n[2])<0.0 ) {
+ vlr->puno= ~(vlr->puno);
+ vlr->n[0]= -vlr->n[0];
+ vlr->n[1]= -vlr->n[1];
+ vlr->n[2]= -vlr->n[2];
+ }
+ }
+ xn= fabs(vlr->n[0]);
+ yn= fabs(vlr->n[1]);
+ zn= fabs(vlr->n[2]);
+ if(zn>=xn && zn>=yn) vlr->snproj= 0;
+ else if(yn>=xn && yn>=zn) vlr->snproj= 1;
+ else vlr->snproj= 2;
+
+ }
+}
diff --git a/source/blender/render/intern/source/renderPreAndPost.c b/source/blender/render/intern/source/renderPreAndPost.c
new file mode 100644
index 00000000000..761ac75d430
--- /dev/null
+++ b/source/blender/render/intern/source/renderPreAndPost.c
@@ -0,0 +1,94 @@
+/**
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * Prepare the scene data for rendering.
+ *
+ * $Id$
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "render.h"
+#include "render_intern.h"
+#include "renderPreAndPost.h"
+#include "RE_callbacks.h"
+
+#include "shadbuf.h"
+#include "envmap.h"
+#include "renderHelp.h"
+#include "shadowBuffer.h"
+
+/**
+ * Rotate all objects, make shadowbuffers and environment maps.
+ */
+void prepareScene()
+{
+ int a;
+
+
+ if(R.rectot) MEM_freeN(R.rectot);
+ R.rectot= 0;
+ if(R.rectz) MEM_freeN(R.rectz);
+ R.rectz= 0;
+
+ RE_local_get_renderdata();
+
+ /* SCHADUWBUFFER */
+ for(a=0; a<R.totlamp; a++) {
+ if(RE_local_test_break()) break;
+ /* Again, switch between old and new shadowing system. The
+ * buffer objects were initially created in
+ * blenderWorldManipulation.c */
+ if (R.r.mode & R_UNIFIED) {
+ if (R.la[a]->shadowBufOb) {
+ RE_buildShadowBuffer(R.la[a]->shadowBufOb,
+ R.la[a]);
+ }
+ } else {
+ if(R.la[a]->shb) makeshadowbuf(R.la[a]);
+ }
+ }
+
+ /* ENVIRONMENT MAPS */
+ make_envmaps();
+}
+
+void finalizeScene(void)
+{
+ /* Among other things, it releases the shadow buffers. */
+ RE_local_free_renderdata();
+}
+
+
+void doClipping( void (*projectfunc)(float *, float *) )
+{
+ setzbufvlaggen(projectfunc);
+}
+
+/* eof */
diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c
new file mode 100644
index 00000000000..32db34d7ac6
--- /dev/null
+++ b/source/blender/render/intern/source/rendercore.c
@@ -0,0 +1,2902 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/* system includes */
+#include <math.h>
+#include <string.h>
+#include <stdlib.h>
+
+/* External modules: */
+#include "MEM_guardedalloc.h"
+#include "BLI_arithb.h"
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+#include "MTC_matrixops.h"
+#include "BKE_utildefines.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_image_types.h"
+#include "DNA_object_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_lamp_types.h"
+
+#include "BKE_global.h"
+#include "BKE_texture.h"
+
+/* local include */
+#include "RE_callbacks.h"
+#include "old_zbuffer_types.h"
+#include "render.h"
+#include "render_intern.h"
+#include "zbuf.h" /* stuff like bgnaccumbuf, fillrect, ...*/
+#include "pixelblending.h"
+#include "shadbuf.h"
+#include "renderHelp.h"
+
+#include "jitter.h"
+
+/* own include */
+#include "rendercore.h"
+#include "rendercore_int.h"
+
+/* globals for this file */
+/* moved to renderData.c? Not yet... */
+RE_Render R;
+Osa O;
+
+extern float Zjitx,Zjity, Zmulx, Zmuly;
+PixStrMain psmfirst;
+int psmteller;
+
+float holoofs= 0.0, fmask[256], centLut[16];
+unsigned short usegamtab=0, shortcol[4], *mask1[9], *mask2[9], *igamtab1, *igamtab2, *gamtab;
+char cmask[256], *centmask;
+
+/* functions */
+/* comes from texture.c (only used here !) */
+/* extern void do_halo_tex(HaloRen *har, float xn, float yn, float *colf); */
+
+void gamtabdit(unsigned short *in, char *out);
+/* int count_mask(unsigned short ); */
+void scanlinehalo(unsigned int *rectz, unsigned int *rectt, short ys);
+/* void add_halo_flare(void); */
+void edge_enhance(void);
+
+/* Dither with gamma table? */
+void gamtabdit(unsigned short *in, char *out)
+/* unsigned short *in; */
+/* char *out; */
+{
+ static short rerr=0, gerr=0, berr=0;
+ unsigned int col;
+ char *cp;
+
+ cp= (char *)&col;
+ out[0]= in[0]>>8;
+
+ col= gamtab[in[2]]+berr;
+ if(col>65535) col= 65535;
+ out[1]= cp[2];
+ berr= cp[3];
+
+ col= gamtab[in[4]]+gerr;
+ if(col>65535) col= 65535;
+ out[2]= cp[2];
+ gerr= cp[3];
+
+ col= gamtab[in[6]]+rerr;
+ if(col>65535) col= 65535;
+ out[3]= cp[2];
+ rerr= cp[3];
+
+}
+
+float mistfactor(float *co) /* dist en hoogte, return alpha */
+{
+ float fac, hi;
+
+ fac= R.zcor - R.wrld.miststa; /* R.zcor wordt per pixel berekend */
+
+ /* fac= -co[2]-R.wrld.miststa; */
+
+ if(fac>0.0) {
+ if(fac< R.wrld.mistdist) {
+
+ fac= (fac/(R.wrld.mistdist));
+
+ if(R.wrld.mistype==0) fac*= fac;
+ else if(R.wrld.mistype==1);
+ else fac= sqrt(fac);
+ }
+ else fac= 1.0;
+ }
+ else fac= 0.0;
+
+ /* de hoogte schakelt de mist af */
+ if(R.wrld.misthi!=0.0 && fac!=0.0) {
+ /* op hoogte misthi is mist volledig weg */
+
+ hi= R.viewinv[0][2]*co[0]+R.viewinv[1][2]*co[1]+R.viewinv[2][2]*co[2]+R.viewinv[3][2];
+
+ if(hi>R.wrld.misthi) fac= 0.0;
+ else if(hi>0.0) {
+ hi= (R.wrld.misthi-hi)/R.wrld.misthi;
+ fac*= hi*hi;
+ }
+ }
+
+ return 1.0-fac;
+}
+
+void RE_sky(char *col)
+{
+ float rf, gf, bf;
+
+ if((R.wrld.skytype & (WO_SKYBLEND+WO_SKYTEX))==0) {
+ *( (unsigned int *)col)= R.wrld.fastcol;
+ return;
+ }
+
+ R.wrld.skytype |= WO_ZENUP;
+
+ if(R.wrld.skytype & WO_SKYREAL) {
+
+ R.inprz= R.view[0]*R.grvec[0]+ R.view[1]*R.grvec[1]+ R.view[2]*R.grvec[2];
+
+ if(R.inprz<0.0) R.wrld.skytype-= WO_ZENUP;
+ R.inprz= fabs(R.inprz);
+ }
+ else if(R.wrld.skytype & WO_SKYPAPER) {
+ R.inprz= 0.5+ 0.5*R.view[1];
+ }
+ else {
+ R.inprz= fabs(0.5+ R.view[1]);
+ }
+
+ if(R.wrld.skytype & WO_SKYTEX) {
+ VECCOPY(R.lo, R.view);
+ if(R.wrld.skytype & WO_SKYREAL) {
+
+ MTC_Mat3MulVecfl(R.imat, R.lo);
+
+ SWAP(float, R.lo[1], R.lo[2]);
+
+ }
+
+ R.osatex= 0;
+
+ do_sky_tex();
+
+ }
+
+ if(R.inprz>1.0) R.inprz= 1.0;
+ R.inprh= 1.0-R.inprz;
+
+ if(R.wrld.skytype & WO_SKYBLEND) {
+ rf= 255.0*(R.inprh*R.wrld.horr + R.inprz*R.wrld.zenr);
+ gf= 255.0*(R.inprh*R.wrld.horg + R.inprz*R.wrld.zeng);
+ bf= 255.0*(R.inprh*R.wrld.horb + R.inprz*R.wrld.zenb);
+
+ if (rf>255.0) col[0]= 255;
+ else col[0]= (char)rf;
+ if (gf>255.0) col[1]= 255;
+ else col[1]= (char)gf;
+ if (bf>255.0) col[2]= 255;
+ else col[2]= (char)bf;
+ }
+ else {
+ col[0]= 255.0*R.wrld.horr;
+ col[1]= 255.0*R.wrld.horg;
+ col[2]= 255.0*R.wrld.horb;
+ }
+ col[3]= 1; /* om verkeerde optimalisatie alphaover van flares te voorkomen */
+}
+
+/* ------------------------------------------------------------------------- */
+
+void scanlinesky(char *rect, int y)
+{
+ /* have to type this! set to : addalphaUnder: char*, char*
+ * addalphaUnderGamma: ditto called with char *, uint* !!!
+ * unmangle this shit... */
+ void (*alphafunc)();
+ float fac;
+ int dx, x, ofs;
+ unsigned int col=0, *rt;
+ short *sp;
+ char *cp, *cp1;
+ float u, v;
+
+ if(R.r.alphamode & R_ALPHAPREMUL) return;
+
+ if(R.r.alphamode & R_ALPHAKEY) {
+
+ cp= (char *)&col;
+ cp[3]= 1;
+ cp[0]= 255.0*R.wrld.horr;
+ cp[1]= 255.0*R.wrld.horg;
+ cp[2]= 255.0*R.wrld.horb;
+
+ for(x=0; x<R.rectx; x++, rect+= 4) {
+ if(rect[3]==0) {
+ *( ( unsigned int *)rect)= col;
+ }
+ else {
+ /* voorkomen dat 'col' in afbeelding voorkomt */
+ cp1= (char *)rect;
+ if( cp[0]==cp1[0] && cp[1]==cp1[1] && cp[2]==cp1[2] ) {
+
+ if(cp1[3]==255) cp1[3]= 254;
+ else cp1[3]++;
+ }
+
+ if(rect[3]!=255) {
+ keyalpha(rect);
+ }
+ }
+ }
+ return;
+ }
+
+ if(R.wrld.mode & WO_MIST) alphafunc= addalphaUnder;
+ else alphafunc= addalphaUnderGamma;
+
+
+ if(R.r.bufflag & 1) {
+ if(R.backbuf->ok) {
+ if(R.backbuf->ibuf==0) {
+ R.backbuf->ibuf= IMB_loadiffname(R.backbuf->name, IB_rect);
+ if(R.backbuf->ibuf==0) {
+ R.backbuf->ok= 0;
+ return;
+ }
+ }
+ /* welke scanline/ */
+ y= ((y+R.afmy+R.ystart)*R.backbuf->ibuf->y)/(2*R.afmy);
+
+ if(R.flag & R_SEC_FIELD) {
+ if((R.r.mode & R_ODDFIELD)==0) {
+ if( y<R.backbuf->ibuf->y) y++;
+ }
+ else {
+ if( y>0) y--;
+ }
+ }
+
+ rt= (R.backbuf->ibuf->rect + y*R.backbuf->ibuf->x);
+
+ /* op welke plek */
+ fac= ((float)R.backbuf->ibuf->x)/(float)(2*R.afmx);
+ ofs= (R.afmx+R.xstart)*fac;
+ rt+= ofs;
+
+ dx= (int) (65536.0*fac);
+ sp= (short *)&ofs;
+
+ #ifdef BBIG_ENDIAN
+ #else
+ sp++;
+ #endif
+
+ ofs= 0;
+ x= R.rectx;
+ while( x-- ) {
+ if( rect[3] != 255) {
+ if(rect[3]==0) *((unsigned int *)rect)= *rt;
+ else {
+ alphafunc(rect, rt);
+ }
+ }
+ rect+= 4;
+
+ ofs+= dx;
+ while( *sp>0 ) {
+ ofs-= 65536;
+ rt++;
+ }
+ }
+
+ }
+ return;
+ }
+
+ if((R.wrld.skytype & (WO_SKYBLEND+WO_SKYTEX))==0) {
+ for(x=0; x<R.rectx; x++, rect+= 4) {
+ if(rect[3] != 255) {
+ if(rect[3]==0) *((unsigned int *)rect)= R.wrld.fastcol;
+ else {
+ alphafunc(rect, &R.wrld.fastcol);
+ }
+ }
+ }
+ }
+ else {
+
+ for(x=0; x<R.rectx; x++, rect+= 4) {
+ if(rect[3] < 254) {
+ if(R.wrld.skytype & WO_SKYPAPER) {
+ R.view[0]= (x+(R.xstart))/(float)R.afmx;
+ R.view[1]= (y+(R.ystart))/(float)R.afmy;
+ R.view[2]= 0.0;
+ }
+ else {
+ R.view[0]= (x+(R.xstart)+1.0);
+
+ if(R.flag & R_SEC_FIELD) {
+ if(R.r.mode & R_ODDFIELD) R.view[1]= (y+R.ystart+0.5)*R.ycor;
+ else R.view[1]= (y+R.ystart+1.5)*R.ycor;
+ }
+ else R.view[1]= (y+R.ystart+1.0)*R.ycor;
+
+ R.view[2]= -R.viewfac;
+
+ fac= Normalise(R.view);
+ if(R.wrld.skytype & WO_SKYTEX) {
+ O.dxview= 1.0/fac;
+ O.dyview= R.ycor/fac;
+ }
+ }
+
+ if(R.r.mode & R_PANORAMA) {
+ float panoco, panosi;
+ panoco = getPanovCo();
+ panosi = getPanovSi();
+ u= R.view[0]; v= R.view[2];
+
+ R.view[0]= panoco*u + panosi*v;
+ R.view[2]= -panosi*u + panoco*v;
+ }
+
+ RE_sky((char *)&col);
+
+ if(rect[3]==0) *((unsigned int *)rect)= col;
+ else alphafunc(rect, &col);
+ }
+ }
+ }
+}
+
+/* ************************************** */
+
+
+
+extern float Tin; /* texture.c */
+void do_lamphalo_tex(LampRen *lar, float *p1, float *p2, float *intens)
+{
+ /* p1 p2 already are rotated in spot-space */
+ float v1[3], vec[3];
+ float dist, totin=0.0;
+ int a, steps= 32;
+
+ v1[0]= p1[0];
+ v1[1]= p1[1];
+ v1[2]= p1[2]/lar->sh_zfac;
+
+ VecSubf(vec, p2, p1);
+ dist= Normalise(vec);
+
+ /* fixed number of steps */
+ dist/= (float)steps;
+
+ for(a=0; a<steps; a++) {
+
+ VecAddf(v1, v1, vec);
+ VECCOPY(R.co, v1);
+ do_lamp_tex(lar, v1);
+ totin+= Tin;
+
+ }
+
+ totin/= (float)steps;
+
+ *intens *= totin;
+ /* why isn't there a return value here? */
+}
+
+
+
+void spothalo(struct LampRen *lar, float *view, float *intens)
+{
+ double a, b, c, disc, nray[3], npos[3];
+ float t0, t1 = 0.0, t2= 0.0, t3, haint;
+ float p1[3], p2[3], ladist, maxz = 0.0, maxy = 0.0;
+ int snijp, doclip=1, use_yco=0;
+ int ok1=0, ok2=0;
+
+ *intens= 0.0;
+ haint= lar->haint;
+
+ VECCOPY(npos, lar->sh_invcampos); /* in initlamp berekend */
+
+ /* view roteren */
+ VECCOPY(nray, view);
+ MTC_Mat3MulVecd(lar->imat, nray);
+
+ if(R.wrld.mode & WO_MIST) {
+ /* een beetje patch... */
+ R.zcor= -lar->co[2];
+ haint *= mistfactor(lar->co);
+ if(haint==0.0) {
+ return;
+ }
+ }
+
+
+ /* maxz roteren */
+ if(R.co[2]==0) doclip= 0; /* is als halo op sky */
+ else {
+ p1[0]= R.co[0]-lar->co[0];
+ p1[1]= R.co[1]-lar->co[1];
+ p1[2]= R.co[2]-lar->co[2];
+
+ maxz= lar->imat[0][2]*p1[0]+lar->imat[1][2]*p1[1]+lar->imat[2][2]*p1[2];
+ maxz*= lar->sh_zfac;
+ maxy= lar->imat[0][1]*p1[0]+lar->imat[1][1]*p1[1]+lar->imat[2][1]*p1[2];
+
+ if( fabs(nray[2]) <0.000001 ) use_yco= 1;
+ }
+
+ /* z scalen zodat het volume genormaliseerd is */
+ nray[2]*= lar->sh_zfac;
+ /* nray hoeft niet genormaliseerd */
+
+ ladist= lar->sh_zfac*lar->dist;
+
+ /* oplossen */
+ a = nray[0] * nray[0] + nray[1] * nray[1] - nray[2]*nray[2];
+ b = nray[0] * npos[0] + nray[1] * npos[1] - nray[2]*npos[2];
+ c = npos[0] * npos[0] + npos[1] * npos[1] - npos[2]*npos[2];
+
+ snijp= 0;
+ if (fabs(a) < 0.00000001) {
+ /*
+ * Only one intersection point...
+ */
+ return;
+ }
+ else {
+ disc = b*b - a*c;
+
+ if(disc==0.0) {
+ t1=t2= (-b)/ a;
+ snijp= 2;
+ }
+ else if (disc > 0.0) {
+ disc = sqrt(disc);
+ t1 = (-b + disc) / a;
+ t2 = (-b - disc) / a;
+ snijp= 2;
+ }
+ }
+ if(snijp==2) {
+ /* sorteren */
+ if(t1>t2) {
+ a= t1; t1= t2; t2= a;
+ }
+
+ /* z van snijpunten met diabolo */
+ p1[2]= npos[2] + t1*nray[2];
+ p2[2]= npos[2] + t2*nray[2];
+
+ /* beide punten evalueren */
+ if(p1[2]<=0.0) ok1= 1;
+ if(p2[2]<=0.0 && t1!=t2) ok2= 1;
+
+ /* minstens 1 punt met negatieve z */
+ if(ok1==0 && ok2==0) return;
+
+ /* snijpunt met -ladist, de bodem van de kegel */
+ if(use_yco==0) {
+ t3= (-ladist-npos[2])/nray[2];
+
+ /* moet 1 van de snijpunten worden vervangen? */
+ if(ok1) {
+ if(p1[2]<-ladist) t1= t3;
+ }
+ else {
+ ok1= 1;
+ t1= t3;
+ }
+ if(ok2) {
+ if(p2[2]<-ladist) t2= t3;
+ }
+ else {
+ ok2= 1;
+ t2= t3;
+ }
+ }
+ else if(ok1==0 || ok2==0) return;
+
+ /* minstens 1 zichtbaar snijpunt */
+ if(t1<0.0 && t2<0.0) return;
+
+ if(t1<0.0) t1= 0.0;
+ if(t2<0.0) t2= 0.0;
+
+ if(t1==t2) return;
+
+ /* voor zekerheid nog eens sorteren */
+ if(t1>t2) {
+ a= t1; t1= t2; t2= a;
+ }
+
+ /* t0 berekenen: is de maximale zichtbare z (als halo door vlak doorsneden wordt) */
+ if(doclip) {
+ if(use_yco==0) t0= (maxz-npos[2])/nray[2];
+ else t0= (maxy-npos[1])/nray[1];
+
+ if(t0<t1) return;
+ if(t0<t2) t2= t0;
+ }
+
+ /* bereken punten */
+ p1[0]= npos[0] + t1*nray[0];
+ p1[1]= npos[1] + t1*nray[1];
+ p1[2]= npos[2] + t1*nray[2];
+ p2[0]= npos[0] + t2*nray[0];
+ p2[1]= npos[1] + t2*nray[1];
+ p2[2]= npos[2] + t2*nray[2];
+
+
+ /* nu hebben we twee punten, hiermee maken we drie lengtes */
+
+ a= sqrt(p1[0]*p1[0]+p1[1]*p1[1]+p1[2]*p1[2]);
+ b= sqrt(p2[0]*p2[0]+p2[1]*p2[1]+p2[2]*p2[2]);
+ c= VecLenf(p1, p2);
+
+ a/= ladist;
+ a= sqrt(a);
+ b/= ladist;
+ b= sqrt(b);
+ c/= ladist;
+
+ *intens= c*( (1.0-a)+(1.0-b) );
+
+ /* LET OP: a,b en c NIET op 1.0 clippen, dit geeft kleine
+ overflowtjes op de rand (vooral bij smalle halo's) */
+ if(*intens<=0.0) return;
+
+ /* zachte gebied */
+ /* vervalt omdat t0 nu ook voor p1/p2 wordt gebruikt */
+ /* if(doclip && t0<t2) { */
+ /* *intens *= (t0-t1)/(t2-t1); */
+ /* } */
+
+ *intens *= haint;
+
+ if(lar->shb && lar->shb->shadhalostep) {
+ *intens *= shadow_halo(lar, p1, p2);
+ }
+ /* if(lar->mode & LA_TEXTURE) do_lamphalo_tex(lar, p1, p2, intens); */
+
+ }
+}
+
+void renderspothalo(unsigned short *col)
+{
+ LampRen *lar;
+ float i;
+ int colt, a;
+ unsigned short scol[4];
+
+
+ for(a=0; a<R.totlamp; a++) {
+ lar= R.la[a];
+ if(lar->type==LA_SPOT && (lar->mode & LA_HALO) && lar->haint>0) {
+
+ if(lar->org) {
+ lar->r= lar->org->r;
+ lar->g= lar->org->g;
+ lar->b= lar->org->b;
+ }
+
+ spothalo(lar, R.view, &i);
+
+ if(i>0.0) {
+
+ i*= 65536.0;
+
+ colt= i;
+ if(colt>65535) scol[3]= 65535; else scol[3]= colt;
+
+ /* erg vervelend: gammagecorrigeerd renderen EN addalphaADD gaat niet goed samen */
+ /* eigenlijk moet er een aparte 'optel' gamma komen */
+
+ colt= i*lar->r;
+ if(colt>65535) scol[0]= 65535; else scol[0]= colt;
+ if(usegamtab) scol[0]= igamtab2[scol[0]];
+ colt= i*lar->g;
+ if(colt>65535) scol[1]= 65535; else scol[1]= colt;
+ if(usegamtab) scol[1]= igamtab2[scol[1]];
+ colt= i*lar->b;
+ if(colt>65535) scol[2]= 65535; else scol[2]= colt;
+ if(usegamtab) scol[2]= igamtab2[scol[2]];
+
+ addalphaAddshort(col, scol);
+ }
+ }
+ }
+}
+
+void render_lighting_halo(HaloRen *har, float *colf)
+{
+ LampRen *lar;
+ float i, inp, inpr, lv[3], lampdist, ld, t, *vn;
+ float ir, ig, ib, shadfac, soft;
+ int a;
+
+ ir= ig= ib= 0.0;
+ VECCOPY(R.co, har->co);
+ vn= har->no;
+
+ O.dxco[0]= har->hasize;
+ O.dxco[1]= 0.0;
+ O.dxco[2]= 0.0;
+
+ O.dyco[0]= 0.0;
+ O.dyco[1]= har->hasize;
+ O.dyco[2]= 0.0;
+
+ for(a=0; a<R.totlamp; a++) {
+ lar= R.la[a];
+
+ /* test op lamplayer */
+ if(lar->mode & LA_LAYER) if((lar->lay & har->lay)==0) continue;
+
+ /* lampdist berekening */
+ if(lar->type==LA_SUN || lar->type==LA_HEMI) {
+ VECCOPY(lv, lar->vec);
+ lampdist= 1.0;
+ }
+ else {
+ lv[0]= R.co[0]-lar->co[0];
+ lv[1]= R.co[1]-lar->co[1];
+ lv[2]= R.co[2]-lar->co[2];
+ ld= sqrt(lv[0]*lv[0]+lv[1]*lv[1]+lv[2]*lv[2]);
+ lv[0]/= ld;
+ lv[1]/= ld;
+ lv[2]/= ld;
+
+ /* ld wordt verderop nog gebruikt (texco's) */
+
+ if(lar->mode & LA_QUAD) {
+ t= 1.0;
+ if(lar->ld1>0.0)
+ t= lar->dist/(lar->dist+lar->ld1*ld);
+ if(lar->ld2>0.0)
+ t*= lar->distkw/(lar->distkw+lar->ld2*ld*ld);
+
+ lampdist= t;
+ }
+ else {
+ lampdist= (lar->dist/(lar->dist+ld));
+ }
+
+ if(lar->mode & LA_SPHERE) {
+ t= lar->dist - ld;
+ if(t<0.0) continue;
+
+ t/= lar->dist;
+ lampdist*= (t);
+ }
+
+ }
+
+ if(lar->mode & LA_TEXTURE) do_lamp_tex(lar, lv);
+
+ if(lar->type==LA_SPOT) {
+
+ /* hier de fie Inp() vertaagt! */
+
+ if(lar->mode & LA_SQUARE) {
+ if(lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2]>0.0) {
+ float x, lvrot[3];
+
+ /* rotate view to lampspace */
+ VECCOPY(lvrot, lv);
+ MTC_Mat3MulVecfl(lar->imat, lvrot);
+
+ x= MAX2(fabs(lvrot[0]/lvrot[2]) , fabs(lvrot[1]/lvrot[2]));
+ /* 1.0/(sqrt(1+x*x)) is equivalent to cos(atan(x)) */
+
+ inpr= 1.0/(sqrt(1.0+x*x));
+ }
+ else inpr= 0.0;
+ }
+ else {
+ inpr= lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2];
+ }
+
+ t= lar->spotsi;
+ if(inpr<t) continue;
+ else {
+ t= inpr-t;
+ i= 1.0;
+ soft= 1.0;
+ if(t<lar->spotbl && lar->spotbl!=0.0) {
+ /* zachte gebied */
+ i= t/lar->spotbl;
+ t= i*i;
+ soft= (3.0*t-2.0*t*i);
+ inpr*= soft;
+ }
+ if(lar->mode & LA_ONLYSHADOW) {
+ /* if(ma->mode & MA_SHADOW) { */
+ /* inprodukt positief: voorzijde vlak! */
+ inp= vn[0]*lv[0] + vn[1]*lv[1] + vn[2]*lv[2];
+ if(inp>0.0) {
+ /* testshadowbuf==0.0 : 100% schaduw */
+ shadfac = testshadowbuf(lar->shb, inp);
+ if( shadfac>0.0 ) {
+ shadfac*= inp*soft*lar->energy;
+ ir -= shadfac;
+ ig -= shadfac;
+ ib -= shadfac;
+
+ continue;
+ }
+ }
+ /* } */
+ }
+ lampdist*=inpr;
+ }
+ if(lar->mode & LA_ONLYSHADOW) continue;
+
+ }
+
+ /* inprodukt en reflectivity*/
+
+ inp= 1.0-fabs(vn[0]*lv[0] + vn[1]*lv[1] + vn[2]*lv[2]);
+
+ /* inp= cos(0.5*M_PI-acos(inp)); */
+
+ i= inp;
+
+ if(lar->type==LA_HEMI) {
+ i= 0.5*i+0.5;
+ }
+ if(i>0.0) {
+ i*= lampdist;
+ /* i*= lampdist*ma->ref; */
+ }
+
+ /* schaduw */
+ if(i> -0.41) { /* beetje willekeurig, beetje getest */
+ shadfac= 1.0;
+ if(lar->shb) {
+ /* if(ma->mode & MA_SHADOW) { */
+ shadfac = testshadowbuf(lar->shb, inp);
+ if(shadfac==0.0) continue;
+ i*= shadfac;
+ /* } */
+ }
+ }
+
+ if(i>0.0) {
+ ir+= i*lar->r;
+ ig+= i*lar->g;
+ ib+= i*lar->b;
+ }
+ }
+
+ if(ir<0.0) ir= 0.0;
+ if(ig<0.0) ig= 0.0;
+ if(ib<0.0) ib= 0.0;
+
+ colf[0]*= ir;
+ colf[1]*= ig;
+ colf[2]*= ib;
+
+}
+
+
+extern float hashvectf[];
+void RE_shadehalo(HaloRen *har, char *col, unsigned int zz, float dist, float xn, float yn, short flarec)
+{
+ /* in col invullen */
+ float t, zn, radist, ringf=0.0, linef=0.0, alpha, si, co, colf[4];
+ int colt, a;
+
+ if(R.wrld.mode & WO_MIST) {
+ if(har->type & HA_ONLYSKY) {
+ /* sterren geen mist */
+ alpha= har->alfa;
+ }
+ else {
+ /* een beetje patch... */
+ R.zcor= -har->co[2];
+ alpha= mistfactor(har->co)*har->alfa;
+ }
+ }
+ else alpha= har->alfa;
+
+ if(alpha==0.0) {
+ col[0] = 0;
+ col[1] = 0;
+ col[2] = 0;
+ col[3] = 0;
+
+/* *( (int *)col )=0; */
+
+ return;
+ }
+
+ radist= sqrt(dist);
+
+ /* let op: hiermee wordt gesjoemeld: flarec wordt op nul gezet in de pixstruct */
+ if(flarec) har->pixels+= (int)(har->rad-radist);
+
+ if(har->ringc) {
+ float *rc, fac;
+ int ofs;
+
+ /* per ring een alicirc */
+ ofs= har->seed;
+
+ for(a= har->ringc; a>0; a--, ofs+=2) {
+
+ rc= hashvectf + (ofs % 768);
+
+ fac= fabs( rc[1]*(har->rad*fabs(rc[0]) - radist) );
+
+ if(fac< 1.0) {
+ ringf+= (1.0-fac);
+ }
+ }
+ }
+
+ if(har->type & HA_VECT) {
+ dist= fabs( har->cos*(yn) - har->sin*(xn) )/har->rad;
+ if(dist>1.0) dist= 1.0;
+ if(har->tex) {
+ zn= har->sin*xn - har->cos*yn;
+ yn= har->cos*xn + har->sin*yn;
+ xn= zn;
+ }
+ }
+ else dist= dist/har->radsq;
+
+ if(har->type & HA_FLARECIRC) {
+
+ dist= 0.5+fabs(dist-0.5);
+
+ }
+
+ if(har->hard>=30) {
+ dist= sqrt(dist);
+ if(har->hard>=40) {
+ dist= sin(dist*M_PI_2);
+ if(har->hard>=50) {
+ dist= sqrt(dist);
+ }
+ }
+ }
+ else if(har->hard<20) dist*=dist;
+
+ dist=(1.0-dist);
+
+ if(har->linec) {
+ float *rc, fac;
+ int ofs;
+
+ /* per starpoint een aliline */
+ ofs= har->seed;
+
+ for(a= har->linec; a>0; a--, ofs+=3) {
+
+ rc= hashvectf + (ofs % 768);
+
+ fac= fabs( (xn)*rc[0]+(yn)*rc[1]);
+
+ if(fac< 1.0 ) {
+ linef+= (1.0-fac);
+ }
+ }
+
+ linef*= dist;
+
+ }
+
+ if(har->starpoints) {
+ float ster, hoek;
+ /* rotatie */
+ hoek= atan2(yn, xn);
+ hoek*= (1.0+0.25*har->starpoints);
+
+ co= cos(hoek);
+ si= sin(hoek);
+
+ hoek= (co*xn+si*yn)*(co*yn-si*xn);
+
+ ster= fabs(hoek);
+ if(ster>1.0) {
+ ster= (har->rad)/(ster);
+
+ if(ster<1.0) dist*= sqrt(ster);
+ }
+ }
+
+ /* halo wordt doorsneden? */
+ if(har->zs> zz-har->zd) {
+ t= ((float)(zz-har->zs))/(float)har->zd;
+ alpha*= sqrt(sqrt(t));
+ }
+
+ dist*= alpha;
+ ringf*= dist;
+ linef*= alpha;
+
+ if(dist<0.003) {
+ *( (int *)col )=0;
+ return;
+ }
+
+ /* texture? */
+ if(har->tex) {
+ colf[3]= dist;
+ do_halo_tex(har, xn, yn, colf);
+
+ /* dist== colf[3]; */
+
+ colf[0]*= colf[3];
+ colf[1]*= colf[3];
+ colf[2]*= colf[3];
+
+ }
+ else {
+ colf[0]= dist*har->r;
+ colf[1]= dist*har->g;
+ colf[2]= dist*har->b;
+
+ if(har->type & HA_XALPHA) colf[3]= dist*dist;
+ else colf[3]= dist;
+ }
+
+ if(har->mat && har->mat->mode & MA_HALO_SHADE) {
+ /* we test for lights because of preview... */
+ if(R.totlamp) render_lighting_halo(har, colf);
+ }
+
+ if(linef!=0.0) {
+ Material *ma= har->mat;
+
+ colf[0]+= 255.0*linef*ma->specr;
+ colf[1]+= 255.0*linef*ma->specg;
+ colf[2]+= 255.0*linef*ma->specb;
+
+ if(har->type & HA_XALPHA) colf[3]+= linef*linef;
+ else colf[3]+= linef;
+ }
+ if(ringf!=0.0) {
+ Material *ma= har->mat;
+
+ colf[0]+= 255.0*ringf*ma->mirr;
+ colf[1]+= 255.0*ringf*ma->mirg;
+ colf[2]+= 255.0*ringf*ma->mirb;
+
+ if(har->type & HA_XALPHA) colf[3]+= ringf*ringf;
+ else colf[3]+= ringf;
+ }
+
+ colt= 255.0*colf[3];
+ if(colt>254) col[3]= 255; else col[3]= colt;
+
+ colt= colf[2];
+ if(colt>254) col[2]= 255; else col[2]= colt;
+
+ colt= colf[1];
+ if(colt>254) col[1]= 255; else col[1]= colt;
+
+ colt= colf[0];
+ if(colt>254) col[0]= 255; else col[0]= colt;
+
+}
+
+
+unsigned int calchalo_z(HaloRen *har, unsigned int zz)
+{
+
+ if(har->type & HA_ONLYSKY) {
+ if(zz!=0x7FFFFFFF) zz= 0;
+ }
+ else {
+ zz= (zz>>8);
+ if(zz<0x800000) zz= (zz+0x7FFFFF);
+ else zz= (zz-0x800000);
+ }
+ return zz;
+}
+
+void scanlinehaloPS(unsigned int *rectz, long *rectdelta, unsigned int *rectt, short ys)
+{
+ HaloRen *har = NULL;
+ PixStr *ps;
+ float dist,xsq,ysq,xn,yn;
+ unsigned int a, *rz, *rt, zz;
+ long *rd;
+ int accol[4];
+ short minx,maxx,x,aantal, aantalm, behind, flarec;
+ char col[4];
+
+ for(a=0;a<R.tothalo;a++) {
+ if((a & 255)==0) har= R.bloha[a>>8];
+ else har++;
+
+ if(RE_local_test_break()) break;
+
+ if(ys>har->maxy);
+ else if(ys<har->miny);
+ else {
+ minx= floor(har->xs-har->rad);
+ maxx= ceil(har->xs+har->rad);
+
+ if(maxx<0);
+ else if(R.rectx<minx);
+ else {
+ if(minx<0) minx= 0;
+ if(maxx>=R.rectx) maxx= R.rectx-1;
+
+ rt= rectt+minx;
+ rd= rectdelta+minx;
+ rz= rectz+minx;
+
+ yn= (ys-har->ys)*R.ycor;
+ ysq= yn*yn;
+ for(x=minx; x<=maxx; x++) {
+
+ flarec= har->flarec; /* har->pixels mag maar 1 x geteld worden */
+
+ if( IS_A_POINTER_CODE(*rd)) {
+ xn= x-har->xs;
+ xsq= xn*xn;
+ dist= xsq+ysq;
+ if(dist<har->radsq) {
+ ps= (PixStr *) POINTER_FROM_CODE(*rd);
+ aantal= behind= 0;
+ accol[0]=accol[1]=accol[2]=accol[3]= 0;
+ while(ps) {
+ aantalm= count_mask(ps->mask);
+ aantal+= aantalm;
+
+ zz= calchalo_z(har, ps->z);
+ if(zz> har->zs) {
+ *( (int *)col )= 0;
+ RE_shadehalo(har, col, zz, dist, xn, yn, flarec);
+ accol[0]+= aantalm*col[0];
+ accol[1]+= aantalm*col[1];
+ accol[2]+= aantalm*col[2];
+ accol[3]+= aantalm*col[3];
+ flarec= 0;
+ }
+
+ ps= ps->next;
+ }
+ ps= (PixStr *) POINTER_FROM_CODE(*rd);
+ aantal= R.osa-aantal;
+
+ zz= calchalo_z(har, *rz);
+ if(zz> har->zs) {
+ *( (int *)col )= 0;
+ RE_shadehalo(har, col, zz, dist, xn, yn, flarec);
+ accol[0]+= aantal*col[0];
+ accol[1]+= aantal*col[1];
+ accol[2]+= aantal*col[2];
+ accol[3]+= aantal*col[3];
+ }
+
+
+ col[0]= accol[0]/R.osa;
+ col[1]= accol[1]/R.osa;
+ col[2]= accol[2]/R.osa;
+ col[3]= accol[3]/R.osa;
+
+ /* if(behind > (R.osa>>1)) addalphaUnder(rt,col); */
+ RE_addalphaAddfac((char *)rt, (char *)col, har->add);
+ }
+ }
+ else {
+ zz= calchalo_z(har, *rz);
+ if(zz> har->zs) {
+ xn= x- har->xs;
+ xsq= xn*xn;
+ dist= xsq+ysq;
+ if(dist<har->radsq) {
+ RE_shadehalo(har, col, zz, dist, xn, yn, flarec);
+ RE_addalphaAddfac((char *)rt, (char *)col, har->add);
+ }
+ }
+ }
+ rt++;
+ rz++;
+ rd++;
+ }
+
+ }
+ }
+ }
+
+}
+
+void scanlinehalo(unsigned int *rectz, unsigned int *rectt, short ys)
+{
+ HaloRen *har = NULL;
+ float dist,xsq,ysq,xn,yn;
+ unsigned int a, *rz, *rt, zz;
+ short minx,maxx, x;
+ char col[4];
+
+ for(a=0; a<R.tothalo; a++) {
+ if((a & 255)==0) har= R.bloha[a>>8];
+ else har++;
+
+ if(RE_local_test_break()) break;
+
+ if(ys>har->maxy);
+ else if(ys<har->miny);
+ else {
+ minx= floor(har->xs-har->rad);
+ maxx= ceil(har->xs+har->rad);
+
+ if(maxx<0);
+ else if(R.rectx<minx);
+ else {
+ if(minx<0) minx= 0;
+ if(maxx>=R.rectx) maxx= R.rectx-1;
+
+ rt= rectt+minx;
+ rz= rectz+minx;
+
+ yn= (ys-har->ys)*R.ycor;
+ ysq= yn*yn;
+ for(x=minx; x<=maxx; x++) {
+
+ zz= calchalo_z(har, *rz);
+ if(zz> har->zs) {
+ xn= x- har->xs;
+ xsq= xn*xn;
+ dist= xsq+ysq;
+ if(dist<har->radsq) {
+ RE_shadehalo(har, col, zz, dist, xn, yn, har->flarec);
+ RE_addalphaAddfac((char *)rt, (char *)col, har->add);
+ }
+ }
+
+ rt++;
+ rz++;
+ }
+ }
+ }
+ }
+
+}
+
+void halovert()
+{
+ HaloRen *har = NULL;
+ float dist, xsq, ysq, xn, yn;
+ unsigned int a, *rectz, *rz, *rectt, *rt, zz;
+ int minx, maxx, miny, maxy, x, y;
+ char col[4];
+
+
+ for(a=0;a<R.tothalo;a++) {
+ if((a & 255)==0) har= R.bloha[a>>8];
+ else har++;
+
+ if(RE_local_test_break()) break;
+
+ if(har->maxy<0);
+ else if(R.recty<har->miny);
+ else {
+ minx= floor(har->xs-har->rad);
+ maxx= ceil(har->xs+har->rad);
+
+ if(maxx<0);
+ else if(R.rectx<minx);
+ else {
+
+ miny= floor(har->ys-har->rad);
+ maxy= ceil(har->ys+har->rad);
+
+ if(minx<0) minx= 0;
+ if(maxx>=R.rectx) maxx= R.rectx-1;
+ if(miny<0) miny= 0;
+ if(maxy>R.recty) maxy= R.recty;
+
+ rectt= R.rectot+ R.rectx*miny;
+ rectz= R.rectz+ R.rectx*miny;
+
+ for(y=miny;y<maxy;y++) {
+
+ rz= rectz+minx;
+
+ rt= (rectt+minx);
+
+ yn= (y - har->ys)*R.ycor;
+ ysq= yn*yn;
+ for(x=minx;x<=maxx;x++) {
+
+ zz= calchalo_z(har, *rz);
+
+ if(zz> har->zs) {
+
+ xn= x - har->xs;
+ xsq= xn*xn;
+ dist= xsq+ysq;
+ if(dist<har->radsq) {
+ RE_shadehalo(har, col, zz, dist, xn, yn, har->flarec);
+
+ RE_addalphaAddfac((char *)rt, (char *)col, har->add);
+
+ }
+ }
+ rt++;
+ rz++;
+ }
+
+ rectt+= R.rectx;
+ rectz+= R.rectx;
+
+ if(RE_local_test_break()) break;
+ }
+
+ }
+ }
+ }
+}
+
+float RE_Spec(float inp, int hard)
+{
+ float b1;
+
+ if(inp>=1.0) return 1.0;
+ else if (inp<=0.0) return 0.0;
+
+ b1= inp*inp;
+ /* avoid FPE */
+ if(b1<0.01) b1= 0.01;
+
+ if((hard & 1)==0) inp= 1.0;
+ if(hard & 2) inp*= b1;
+ b1*= b1;
+ if(hard & 4) inp*= b1;
+ b1*= b1;
+ if(hard & 8) inp*= b1;
+ b1*= b1;
+ if(hard & 16) inp*= b1;
+ b1*= b1;
+
+ /* avoid FPE */
+ if(b1<0.001) b1= 0.0;
+
+ if(hard & 32) inp*= b1;
+ b1*= b1;
+ if(hard & 64) inp*=b1;
+
+ if(hard & 128) {
+ b1*= b1;
+ inp*=b1;
+ }
+
+ return inp;
+}
+
+
+float CookTorr(float *n, float *l, float *v, int hard)
+{
+ float i, nh, nv, h[3];
+
+ h[0]= v[0]+l[0];
+ h[1]= v[1]+l[1];
+ h[2]= v[2]+l[2];
+ Normalise(h);
+
+ nh= n[0]*h[0]+n[1]*h[1]+n[2]*h[2];
+ if(nh<0.0) return 0.0;
+ nv= n[0]*v[0]+n[1]*v[1]+n[2]*v[2];
+ if(nv<0.0) nv= 0.0;
+ i= RE_Spec(nh, hard);
+
+ i= i/(0.1+nv);
+ return i;
+}
+
+void RE_calc_R_ref()
+{
+ float i;
+
+ /* R.vn dot R.view */
+ i= -2*(R.vn[0]*R.view[0]+R.vn[1]*R.view[1]+R.vn[2]*R.view[2]);
+
+ R.ref[0]= (R.view[0]+i*R.vn[0]);
+ R.ref[1]= (R.view[1]+i*R.vn[1]);
+ R.ref[2]= (R.view[2]+i*R.vn[2]);
+ if(R.osatex) {
+ if(R.vlr->flag & R_SMOOTH) {
+ i= -2*( (R.vn[0]+O.dxno[0])*(R.view[0]+O.dxview) +
+ (R.vn[1]+O.dxno[1])*R.view[1]+ (R.vn[2]+O.dxno[2])*R.view[2] );
+
+ O.dxref[0]= R.ref[0]- ( R.view[0]+O.dxview+i*(R.vn[0]+O.dxno[0]));
+ O.dxref[1]= R.ref[1]- (R.view[1]+ i*(R.vn[1]+O.dxno[1]));
+ O.dxref[2]= R.ref[2]- (R.view[2]+ i*(R.vn[2]+O.dxno[2]));
+
+ i= -2*( (R.vn[0]+O.dyno[0])*R.view[0]+
+ (R.vn[1]+O.dyno[1])*(R.view[1]+O.dyview)+ (R.vn[2]+O.dyno[2])*R.view[2] );
+
+ O.dyref[0]= R.ref[0]- (R.view[0]+ i*(R.vn[0]+O.dyno[0]));
+ O.dyref[1]= R.ref[1]- (R.view[1]+O.dyview+i*(R.vn[1]+O.dyno[1]));
+ O.dyref[2]= R.ref[2]- (R.view[2]+ i*(R.vn[2]+O.dyno[2]));
+
+ }
+ else {
+
+ i= -2*( R.vn[0]*(R.view[0]+O.dxview) +
+ R.vn[1]*R.view[1]+ R.vn[2]*R.view[2] );
+
+ O.dxref[0]= R.ref[0]- (R.view[0]+O.dxview+i*R.vn[0]);
+ O.dxref[1]= R.ref[1]- (R.view[1]+ i*R.vn[1]);
+ O.dxref[2]= R.ref[2]- (R.view[2]+ i*R.vn[2]);
+
+ i= -2*( R.vn[0]*R.view[0]+
+ R.vn[1]*(R.view[1]+O.dyview)+ R.vn[2]*R.view[2] );
+
+ O.dyref[0]= R.ref[0]- (R.view[0]+ i*R.vn[0]);
+ O.dyref[1]= R.ref[1]- (R.view[1]+O.dyview+i*R.vn[1]);
+ O.dyref[2]= R.ref[2]- (R.view[2]+ i*R.vn[2]);
+ }
+ }
+
+}
+
+void shadelamplus()
+{
+ LampRen *lar;
+ Material *ma;
+ float i, inp, inpr, t, lv[3], lampdist, ld = 0, ir, ig, ib, isr=0,isg=0,isb=0;
+ float lvrot[3], *vn, *view, shadfac, soft;
+ int a;
+
+ vn= R.vn;
+ view= R.view;
+ ma= R.matren;
+
+ /* aparte lus */
+ if(ma->mode & MA_ONLYSHADOW) {
+ shadfac= ir= 0.0;
+ for(a=0; a<R.totlamp; a++) {
+ lar= R.la[a];
+
+ if(lar->mode & LA_LAYER) if((lar->lay & R.vlr->lay)==0) continue;
+
+ if(lar->shb) {
+ /* alleen testen binnen spotbundel */
+ lv[0]= R.co[0]-lar->co[0];
+ lv[1]= R.co[1]-lar->co[1];
+ lv[2]= R.co[2]-lar->co[2];
+ Normalise(lv);
+ inpr= lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2];
+ if(inpr>lar->spotsi) {
+
+ inp= vn[0]*lv[0] + vn[1]*lv[1] + vn[2]*lv[2];
+
+ i = testshadowbuf(lar->shb, inp);
+
+ t= inpr - lar->spotsi;
+ if(t<lar->spotbl && lar->spotbl!=0.0) {
+ t/= lar->spotbl;
+ t*= t;
+ i= t*i+(1.0-t);
+ }
+
+ shadfac+= i;
+ ir+= 1.0;
+ }
+ else {
+ shadfac+= 1.0;
+ ir+= 1.0;
+ }
+ }
+ }
+ if(ir>0.0) shadfac/= ir;
+ ma->alpha= (R.mat->alpha)*(1.0-shadfac);
+
+ shortcol[0]=shortcol[1]=shortcol[2]= 0;
+
+ return;
+ }
+
+ if(ma->mode & (MA_VERTEXCOLP|MA_FACETEXTURE)) {
+ ma->r= R.vcol[0];
+ ma->g= R.vcol[1];
+ ma->b= R.vcol[2];
+ }
+
+ /* mirror reflection colour */
+ R.refcol[0]= R.refcol[1]= R.refcol[2]= R.refcol[3]= 0.0;
+
+ if(ma->texco) {
+
+ if(ma->texco & TEXCO_REFL) {
+ RE_calc_R_ref();
+ }
+
+ if(ma->mode & (MA_VERTEXCOLP|MA_FACETEXTURE)) {
+ R.mat->r= R.vcol[0];
+ R.mat->g= R.vcol[1];
+ R.mat->b= R.vcol[2];
+ }
+
+ do_material_tex();
+ }
+
+ if(ma->mode & MA_SHLESS) {
+ if( (ma->mode & (MA_VERTEXCOL+MA_VERTEXCOLP+MA_FACETEXTURE) )) {
+ ir= R.vcol[0]*ma->r;
+ ig= R.vcol[1]*ma->g;
+ ib= R.vcol[2]*ma->b;
+ }
+ else {
+ ir= ma->r;
+ ig= ma->g;
+ ib= ma->b;
+ }
+
+ if(usegamtab) {
+ a= 65535*ir;
+ if(a<0) a=0; else if(a>65535) a= 65535;
+ shortcol[0]= igamtab2[a];
+ a= 65535*ig;
+ if(a<0) a=0; else if(a>65535) a= 65535;
+ shortcol[1]= igamtab2[a];
+ a= 65535*ib;
+ if(a<0) a=0; else if(a>65535) a= 65535;
+ shortcol[2]= igamtab2[a];
+ }
+ else {
+ a= 65535*ir;
+ if(a<0) shortcol[0]= 0; else if(a>65535) shortcol[0]= 65535; else shortcol[0]= a;
+ a= 65535*ig;
+ if(a<0) shortcol[1]= 0; else if(a>65535) shortcol[1]= 65535; else shortcol[1]= a;
+ a= 65535*ib;
+ if(a<0) shortcol[2]= 0; else if(a>65535) shortcol[2]= 65535; else shortcol[2]= a;
+ }
+ return;
+ }
+
+ if( (ma->mode & (MA_VERTEXCOL+MA_VERTEXCOLP))== MA_VERTEXCOL ) {
+ ir= ma->emit+R.vcol[0];
+ ig= ma->emit+R.vcol[1];
+ ib= ma->emit+R.vcol[2];
+ }
+ else ir= ig= ib= ma->emit;
+
+ for(a=0; a<R.totlamp; a++) {
+ lar= R.la[a];
+
+ /* test op lamplayer */
+ if(lar->mode & LA_LAYER) if((lar->lay & R.vlr->lay)==0) continue;
+
+ /* lampdist berekening */
+ if(lar->type==LA_SUN || lar->type==LA_HEMI) {
+ VECCOPY(lv, lar->vec);
+ lampdist= 1.0;
+ }
+ else {
+ lv[0]= R.co[0]-lar->co[0];
+ lv[1]= R.co[1]-lar->co[1];
+ lv[2]= R.co[2]-lar->co[2];
+ ld= sqrt(lv[0]*lv[0]+lv[1]*lv[1]+lv[2]*lv[2]);
+ lv[0]/= ld;
+ lv[1]/= ld;
+ lv[2]/= ld;
+
+ /* ld wordt verderop nog gebruikt (texco's) */
+
+ if(lar->mode & LA_QUAD) {
+ t= 1.0;
+ if(lar->ld1>0.0)
+ t= lar->dist/(lar->dist+lar->ld1*ld);
+ if(lar->ld2>0.0)
+ t*= lar->distkw/(lar->distkw+lar->ld2*ld*ld);
+
+ lampdist= t;
+ }
+ else {
+ lampdist= (lar->dist/(lar->dist+ld));
+ }
+
+ if(lar->mode & LA_SPHERE) {
+ t= lar->dist - ld;
+ if(t<0.0) continue;
+
+ t/= lar->dist;
+ lampdist*= (t);
+ }
+
+ }
+
+ if(lar->mode & LA_TEXTURE) do_lamp_tex(lar, lv);
+
+ if(lar->type==LA_SPOT) {
+
+ /* hier de fie Inp() vertaagt! */
+
+ if(lar->mode & LA_SQUARE) {
+ if(lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2]>0.0) {
+ float x;
+
+ /* rotate view to lampspace */
+ VECCOPY(lvrot, lv);
+ MTC_Mat3MulVecfl(lar->imat, lvrot);
+
+ x= MAX2(fabs(lvrot[0]/lvrot[2]) , fabs(lvrot[1]/lvrot[2]));
+ /* 1.0/(sqrt(1+x*x)) is equivalent to cos(atan(x)) */
+
+ inpr= 1.0/(sqrt(1+x*x));
+ }
+ else inpr= 0.0;
+ }
+ else {
+ inpr= lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2];
+ }
+
+ t= lar->spotsi;
+ if(inpr<t) continue;
+ else {
+ t= inpr-t;
+ i= 1.0;
+ soft= 1.0;
+ if(t<lar->spotbl && lar->spotbl!=0.0) {
+ /* zachte gebied */
+ i= t/lar->spotbl;
+ t= i*i;
+ soft= (3.0*t-2.0*t*i);
+ inpr*= soft;
+ }
+ if(lar->mode & LA_ONLYSHADOW && lar->shb) {
+ if(ma->mode & MA_SHADOW) {
+ /* inprodukt positief: voorzijde vlak! */
+ inp= vn[0]*lv[0] + vn[1]*lv[1] + vn[2]*lv[2];
+ if(inp>0.0) {
+ /* testshadowbuf==0.0 : 100% schaduw */
+ shadfac = 1.0 - testshadowbuf(lar->shb, inp);
+ if(shadfac>0.0) {
+ shadfac*= inp*soft*lar->energy;
+ ir -= shadfac;
+ ig -= shadfac;
+ ib -= shadfac;
+
+ continue;
+ }
+ }
+ }
+ }
+ lampdist*=inpr;
+ }
+ if(lar->mode & LA_ONLYSHADOW) continue;
+
+ if(lar->mode & LA_OSATEX) {
+ R.osatex= 1; /* signaal voor multitex() */
+
+ O.dxlv[0]= lv[0] - (R.co[0]-lar->co[0]+O.dxco[0])/ld;
+ O.dxlv[1]= lv[1] - (R.co[1]-lar->co[1]+O.dxco[1])/ld;
+ O.dxlv[2]= lv[2] - (R.co[2]-lar->co[2]+O.dxco[2])/ld;
+
+ O.dylv[0]= lv[0] - (R.co[0]-lar->co[0]+O.dyco[0])/ld;
+ O.dylv[1]= lv[1] - (R.co[1]-lar->co[1]+O.dyco[1])/ld;
+ O.dylv[2]= lv[2] - (R.co[2]-lar->co[2]+O.dyco[2])/ld;
+ }
+
+ }
+
+ /* inprodukt en reflectivity*/
+ inp=i= vn[0]*lv[0] + vn[1]*lv[1] + vn[2]*lv[2];
+ if(lar->type==LA_HEMI) {
+ i= 0.5*i+0.5;
+ }
+ if(i>0.0) {
+ i*= lampdist*ma->ref;
+ }
+
+ /* schaduw en spec */
+ if(i> -0.41) { /* beetje willekeurig, beetje getest */
+ shadfac= 1.0;
+ if(lar->shb) {
+ if(ma->mode & MA_SHADOW) {
+ shadfac = testshadowbuf(lar->shb, inp);
+ if(shadfac==0.0) continue;
+ i*= shadfac;
+ }
+ }
+ /* specularity */
+
+ if(ma->spec!=0.0) {
+
+ if(lar->type==LA_SUN || lar->type==LA_HEMI) {
+ if(lar->type==LA_SUN) {
+ lv[2]-= 1.0;
+ }
+ else {
+ lv[0]+= view[0];
+ lv[1]+= view[1];
+ lv[2]+= view[2];
+ }
+
+ Normalise(lv);
+
+ t= vn[0]*lv[0]+vn[1]*lv[1]+vn[2]*lv[2];
+
+ if(lar->type==LA_HEMI) {
+ t= 0.5*t+0.5;
+ }
+ /* let op: shadfac en lampdist uit onderstaande */
+
+ /* no more speclim */
+
+ t= ma->spec*RE_Spec(t, ma->har);
+ isr+= t*(lar->r * ma->specr);
+ isg+= t*(lar->g * ma->specg);
+ isb+= t*(lar->b * ma->specb);
+ }
+ else {
+ t= shadfac*ma->spec*lampdist*CookTorr(vn, lv, view, ma->har);
+ isr+= t*(lar->r * ma->specr);
+ isg+= t*(lar->g * ma->specg);
+ isb+= t*(lar->b * ma->specb);
+ }
+ }
+ }
+ if(i>0.0) {
+ ir+= i*lar->r;
+ ig+= i*lar->g;
+ ib+= i*lar->b;
+ }
+ }
+
+ if(ir<0.0) ir= 0.0;
+ if(ig<0.0) ig= 0.0;
+ if(ib<0.0) ib= 0.0;
+ if(isr<0.0) isr= 0.0;
+ if(isg<0.0) isg= 0.0;
+ if(isb<0.0) isb= 0.0;
+
+ if(ma->mode & MA_ZTRA) { /* ztra shade */
+ if(ma->spectra!=0.0) {
+
+ t = MAX3(isr, isb, isg);
+ t *= ma->spectra;
+ if(t>1.0) t= 1.0;
+ if(ma->mapto & MAP_ALPHA) ma->alpha= (1.0-t)*ma->alpha+t;
+ else ma->alpha= (1.0-t)*R.mat->alpha+t;
+ }
+ }
+
+ if(R.refcol[0]==0.0) {
+ a= 65535.0*( ma->r*ir +ma->ambr +isr);
+ if(a>65535) a=65535; else if(a<0) a= 0;
+ shortcol[0]= a;
+ a= 65535.0*(ma->g*ig +ma->ambg +isg);
+ if(a>65535) a=65535; else if(a<0) a= 0;
+ shortcol[1]= a;
+ a= 65535*(ma->b*ib +ma->ambb +isb);
+ if(a>65535) a=65535; else if(a<0) a= 0;
+ shortcol[2]= a;
+ }
+ else {
+ a= 65535.0*( ma->mirr*R.refcol[1] + (1.0 - ma->mirr*R.refcol[0])*(ma->r*ir +ma->ambr) +isr);
+ if(a>65535) a=65535; else if(a<0) a= 0;
+ shortcol[0]= a;
+ a= 65535.0*( ma->mirg*R.refcol[2] + (1.0 - ma->mirg*R.refcol[0])*(ma->g*ig +ma->ambg) +isg);
+ if(a>65535) a=65535; else if(a<0) a= 0;
+ shortcol[1]= a;
+ a= 65535.0*( ma->mirb*R.refcol[3] + (1.0 - ma->mirb*R.refcol[0])*(ma->b*ib +ma->ambb) +isb);
+ if(a>65535) a=65535; else if(a<0) a= 0;
+ shortcol[2]= a;
+ }
+
+ if(usegamtab) {
+ shortcol[0]= igamtab2[ shortcol[0] ];
+ shortcol[1]= igamtab2[ shortcol[1] ];
+ shortcol[2]= igamtab2[ shortcol[2] ];
+ }
+}
+
+
+void shadepixel(float x, float y, int vlaknr)
+ /* x,y: windowcoordinaat van 0 tot rectx,y */
+{
+ static VlakRen *vlr;
+ static VertRen *v1, *v2, *v3;
+ static float t00, t01, t10, t11, dvlak, n1[3], n2[3], n3[3];
+ static float s00, s01, s10, s11;
+ float *o1, *o2, *o3;
+ float u, v, l, dl, hox, hoy, detsh, fac, deler, alpha;
+ char *cp1, *cp2, *cp3;
+
+ if(R.vlaknr== -1) { /* doet initrender */
+ vlr= R.vlr= 0;
+ }
+
+ if(vlaknr<=0) { /* sky */
+ R.vlaknr= 0;
+ shortcol[3]= 0;
+ }
+ else if( (vlaknr & 0x7FFFFF) <= R.totvlak) {
+
+ if(vlaknr!=R.vlaknr) {
+ vlr= RE_findOrAddVlak( (vlaknr-1) & 0x7FFFFF);
+
+ R.mat= vlr->mat;
+ R.matren= R.mat->ren;
+
+ if(R.matren==0) { /* tijdelijk voor debug */
+ shortcol[3]= 65535;
+ shortcol[2]= 0;
+ shortcol[1]= 65535;
+ shortcol[0]= 65535;
+ return;
+ }
+
+ R.vlr= vlr;
+
+ R.vno= vlr->n;
+ R.osatex= (R.matren->texco & TEXCO_OSA);
+ R.vlaknr= vlaknr;
+
+ v1= vlr->v1;
+ dvlak= v1->co[0]*vlr->n[0]+v1->co[1]*vlr->n[1]+v1->co[2]*vlr->n[2];
+
+ if( (vlr->flag & R_SMOOTH) || (R.matren->texco & NEED_UV)) { /* uv nodig */
+ if(vlaknr & 0x800000) {
+ v2= vlr->v3;
+ v3= vlr->v4;
+ }
+ else {
+ v2= vlr->v2;
+ v3= vlr->v3;
+ }
+
+ if(vlr->snproj==0) {
+ t00= v3->co[0]-v1->co[0]; t01= v3->co[1]-v1->co[1];
+ t10= v3->co[0]-v2->co[0]; t11= v3->co[1]-v2->co[1];
+ }
+ else if(vlr->snproj==1) {
+ t00= v3->co[0]-v1->co[0]; t01= v3->co[2]-v1->co[2];
+ t10= v3->co[0]-v2->co[0]; t11= v3->co[2]-v2->co[2];
+ }
+ else {
+ t00= v3->co[1]-v1->co[1]; t01= v3->co[2]-v1->co[2];
+ t10= v3->co[1]-v2->co[1]; t11= v3->co[2]-v2->co[2];
+ }
+
+ detsh= t00*t11-t10*t01;
+ t00/= detsh; t01/=detsh;
+ t10/=detsh; t11/=detsh;
+
+ if(vlr->flag & R_SMOOTH) { /* puno's goedzetten */
+ if(vlr->puno & ME_FLIPV1) {
+ n1[0]= -v1->n[0]; n1[1]= -v1->n[1]; n1[2]= -v1->n[2];
+ } else {
+ n1[0]= v1->n[0]; n1[1]= v1->n[1]; n1[2]= v1->n[2];
+ }
+ if(vlaknr & 0x800000) {
+ if(vlr->puno & ME_FLIPV3) {
+ n2[0]= -v2->n[0]; n2[1]= -v2->n[1]; n2[2]= -v2->n[2];
+ } else {
+ n2[0]= v2->n[0]; n2[1]= v2->n[1]; n2[2]= v2->n[2];
+ }
+
+ if(vlr->puno & ME_FLIPV4) {
+ n3[0]= -v3->n[0]; n3[1]= -v3->n[1]; n3[2]= -v3->n[2];
+ } else {
+ n3[0]= v3->n[0]; n3[1]= v3->n[1]; n3[2]= v3->n[2];
+ }
+
+ }
+ else {
+ if(vlr->puno & ME_FLIPV2) {
+ n2[0]= -v2->n[0]; n2[1]= -v2->n[1]; n2[2]= -v2->n[2];
+ } else {
+ n2[0]= v2->n[0]; n2[1]= v2->n[1]; n2[2]= v2->n[2];
+ }
+
+ if(vlr->puno & ME_FLIPV3) {
+ n3[0]= -v3->n[0]; n3[1]= -v3->n[1]; n3[2]= -v3->n[2];
+ } else {
+ n3[0]= v3->n[0]; n3[1]= v3->n[1]; n3[2]= v3->n[2];
+ }
+ }
+ }
+ if(R.matren->texco & TEXCO_STICKY) {
+ s00= v3->ho[0]/v3->ho[3] - v1->ho[0]/v1->ho[3];
+ s01= v3->ho[1]/v3->ho[3] - v1->ho[1]/v1->ho[3];
+ s10= v3->ho[0]/v3->ho[3] - v2->ho[0]/v2->ho[3];
+ s11= v3->ho[1]/v3->ho[3] - v2->ho[1]/v2->ho[3];
+
+ detsh= s00*s11-s10*s01;
+ s00/= detsh; s01/=detsh;
+ s10/=detsh; s11/=detsh;
+ }
+ }
+ }
+
+ /* COXYZ nieuwe methode */
+ if( (G.special1 & G_HOLO) && ((Camera *)G.scene->camera->data)->flag & CAM_HOLO2) {
+ R.view[0]= (x+(R.xstart)+1.0+holoofs);
+ }
+ else {
+ R.view[0]= (x+(R.xstart)+1.0);
+ }
+
+ if(R.flag & R_SEC_FIELD) {
+ if(R.r.mode & R_ODDFIELD) R.view[1]= (y+R.ystart+0.5)*R.ycor;
+ else R.view[1]= (y+R.ystart+1.5)*R.ycor;
+ }
+ else R.view[1]= (y+R.ystart+1.0)*R.ycor;
+
+ R.view[2]= -R.viewfac;
+
+ if(R.r.mode & R_PANORAMA) {
+ float panoco, panosi;
+ panoco = getPanovCo();
+ panosi = getPanovSi();
+
+ u= R.view[0]; v= R.view[2];
+ R.view[0]= panoco*u + panosi*v;
+ R.view[2]= -panosi*u + panoco*v;
+ }
+
+ deler= vlr->n[0]*R.view[0] + vlr->n[1]*R.view[1] + vlr->n[2]*R.view[2];
+ if (deler!=0.0) fac= R.zcor= dvlak/deler;
+ else fac= R.zcor= 0.0;
+
+ R.co[0]= fac*R.view[0];
+ R.co[1]= fac*R.view[1];
+ R.co[2]= fac*R.view[2];
+
+ if(R.osatex || (R.r.mode & R_SHADOW) ) {
+ u= dvlak/(deler-vlr->n[0]);
+ v= dvlak/(deler- R.ycor*vlr->n[1]);
+
+ O.dxco[0]= R.co[0]- (R.view[0]-1.0)*u;
+ O.dxco[1]= R.co[1]- (R.view[1])*u;
+ O.dxco[2]= R.co[2]- (R.view[2])*u;
+
+ O.dyco[0]= R.co[0]- (R.view[0])*v;
+ O.dyco[1]= R.co[1]- (R.view[1]-1.0*R.ycor)*v;
+ O.dyco[2]= R.co[2]- (R.view[2])*v;
+
+ }
+
+ fac= Normalise(R.view);
+ R.zcor*= fac; /* voor mist */
+
+ if(R.osatex) {
+ if( (R.matren->texco & TEXCO_REFL) ) {
+ O.dxview= 1.0/fac;
+ O.dyview= R.ycor/fac;
+ }
+ }
+
+ /* UV en TEX*/
+ if( (vlr->flag & R_SMOOTH) || (R.matren->texco & NEED_UV)) {
+ if(vlr->snproj==0) {
+ u= (R.co[0]-v3->co[0])*t11-(R.co[1]-v3->co[1])*t10;
+ v= (R.co[1]-v3->co[1])*t00-(R.co[0]-v3->co[0])*t01;
+ if(R.osatex) {
+ O.dxuv[0]= O.dxco[0]*t11- O.dxco[1]*t10;
+ O.dxuv[1]= O.dxco[1]*t00- O.dxco[0]*t01;
+ O.dyuv[0]= O.dyco[0]*t11- O.dyco[1]*t10;
+ O.dyuv[1]= O.dyco[1]*t00- O.dyco[0]*t01;
+ }
+ }
+ else if(vlr->snproj==1) {
+ u= (R.co[0]-v3->co[0])*t11-(R.co[2]-v3->co[2])*t10;
+ v= (R.co[2]-v3->co[2])*t00-(R.co[0]-v3->co[0])*t01;
+ if(R.osatex) {
+ O.dxuv[0]= O.dxco[0]*t11- O.dxco[2]*t10;
+ O.dxuv[1]= O.dxco[2]*t00- O.dxco[0]*t01;
+ O.dyuv[0]= O.dyco[0]*t11- O.dyco[2]*t10;
+ O.dyuv[1]= O.dyco[2]*t00- O.dyco[0]*t01;
+ }
+ }
+ else {
+ u= (R.co[1]-v3->co[1])*t11-(R.co[2]-v3->co[2])*t10;
+ v= (R.co[2]-v3->co[2])*t00-(R.co[1]-v3->co[1])*t01;
+ if(R.osatex) {
+ O.dxuv[0]= O.dxco[1]*t11- O.dxco[2]*t10;
+ O.dxuv[1]= O.dxco[2]*t00- O.dxco[1]*t01;
+ O.dyuv[0]= O.dyco[1]*t11- O.dyco[2]*t10;
+ O.dyuv[1]= O.dyco[2]*t00- O.dyco[1]*t01;
+ }
+ }
+ l= 1.0+u+v;
+
+ if(vlr->flag & R_SMOOTH) {
+ R.vn[0]= l*n3[0]-u*n1[0]-v*n2[0];
+ R.vn[1]= l*n3[1]-u*n1[1]-v*n2[1];
+ R.vn[2]= l*n3[2]-u*n1[2]-v*n2[2];
+
+ Normalise(R.vn);
+ if(R.osatex && (R.matren->texco & (TEXCO_NORM+TEXCO_REFL)) ) {
+ dl= O.dxuv[0]+O.dxuv[1];
+ O.dxno[0]= dl*n3[0]-O.dxuv[0]*n1[0]-O.dxuv[1]*n2[0];
+ O.dxno[1]= dl*n3[1]-O.dxuv[0]*n1[1]-O.dxuv[1]*n2[1];
+ O.dxno[2]= dl*n3[2]-O.dxuv[0]*n1[2]-O.dxuv[1]*n2[2];
+ dl= O.dyuv[0]+O.dyuv[1];
+ O.dyno[0]= dl*n3[0]-O.dyuv[0]*n1[0]-O.dyuv[1]*n2[0];
+ O.dyno[1]= dl*n3[1]-O.dyuv[0]*n1[1]-O.dyuv[1]*n2[1];
+ O.dyno[2]= dl*n3[2]-O.dyuv[0]*n1[2]-O.dyuv[1]*n2[2];
+
+ }
+ }
+ else {
+ VECCOPY(R.vn, vlr->n);
+ }
+
+ if(R.matren->mode & MA_ZINV) { /* z invert */
+ /* R.vn[0]= -R.vn[0]; */
+ /* R.vn[1]= -R.vn[1]; */
+ }
+
+ if(R.matren->texco & TEXCO_ORCO) {
+ if(v2->orco) {
+ o1= v1->orco;
+ o2= v2->orco;
+ o3= v3->orco;
+
+ R.lo[0]= l*o3[0]-u*o1[0]-v*o2[0];
+ R.lo[1]= l*o3[1]-u*o1[1]-v*o2[1];
+ R.lo[2]= l*o3[2]-u*o1[2]-v*o2[2];
+
+ if(R.osatex) {
+ dl= O.dxuv[0]+O.dxuv[1];
+ O.dxlo[0]= dl*o3[0]-O.dxuv[0]*o1[0]-O.dxuv[1]*o2[0];
+ O.dxlo[1]= dl*o3[1]-O.dxuv[0]*o1[1]-O.dxuv[1]*o2[1];
+ O.dxlo[2]= dl*o3[2]-O.dxuv[0]*o1[2]-O.dxuv[1]*o2[2];
+ dl= O.dyuv[0]+O.dyuv[1];
+ O.dylo[0]= dl*o3[0]-O.dyuv[0]*o1[0]-O.dyuv[1]*o2[0];
+ O.dylo[1]= dl*o3[1]-O.dyuv[0]*o1[1]-O.dyuv[1]*o2[1];
+ O.dylo[2]= dl*o3[2]-O.dyuv[0]*o1[2]-O.dyuv[1]*o2[2];
+ }
+ }
+ }
+
+ if(R.matren->texco & TEXCO_GLOB) {
+ VECCOPY(R.gl, R.co);
+ MTC_Mat4MulVecfl(R.viewinv, R.gl);
+ if(R.osatex) {
+ VECCOPY(O.dxgl, O.dxco);
+ MTC_Mat3MulVecfl(R.imat, O.dxco);
+ VECCOPY(O.dygl, O.dyco);
+ MTC_Mat3MulVecfl(R.imat, O.dyco);
+ }
+ }
+ if((R.matren->texco & TEXCO_UV) || (R.matren->mode & (MA_VERTEXCOL|MA_FACETEXTURE))) {
+ if(R.vlr->tface) {
+ float *uv1, *uv2, *uv3;
+
+ uv1= R.vlr->tface->uv[0];
+ if( (vlaknr & 0x800000) || (R.vlr->flag & R_FACE_SPLIT) ) {
+ uv2= R.vlr->tface->uv[2];
+ uv3= R.vlr->tface->uv[3];
+ }
+ else {
+ uv2= R.vlr->tface->uv[1];
+ uv3= R.vlr->tface->uv[2];
+ }
+
+ R.uv[0]= -1.0 + 2.0*(l*uv3[0]-u*uv1[0]-v*uv2[0]);
+ R.uv[1]= -1.0 + 2.0*(l*uv3[1]-u*uv1[1]-v*uv2[1]);
+
+ if(R.osatex) {
+ float duv[2];
+
+ dl= O.dxuv[0]+O.dxuv[1];
+ duv[0]= O.dxuv[0];
+ duv[1]= O.dxuv[1];
+
+ O.dxuv[0]= 2.0*(dl*uv3[0]-duv[0]*uv1[0]-duv[1]*uv2[0]);
+ O.dxuv[1]= 2.0*(dl*uv3[1]-duv[0]*uv1[1]-duv[1]*uv2[1]);
+
+ dl= O.dyuv[0]+O.dyuv[1];
+ duv[0]= O.dyuv[0];
+ duv[1]= O.dyuv[1];
+
+ O.dyuv[0]= 2.0*(dl*uv3[0]-duv[0]*uv1[0]-duv[1]*uv2[0]);
+ O.dyuv[1]= 2.0*(dl*uv3[1]-duv[0]*uv1[1]-duv[1]*uv2[1]);
+ }
+
+ }
+ else {
+ R.uv[0]= 2.0*(u+.5);
+ R.uv[1]= 2.0*(v+.5);
+ }
+ }
+ if(R.matren->texco & TEXCO_NORM) {
+ R.orn[0]= R.vn[0];
+ R.orn[1]= -R.vn[1];
+ R.orn[2]= R.vn[2];
+ }
+ if(R.matren->mode & MA_VERTEXCOL) {
+ cp1= (char *)vlr->vcol;
+ if(cp1) {
+ if( (vlaknr & 0x800000) || (R.vlr->flag & R_FACE_SPLIT) ) {
+ cp2= (char *)(vlr->vcol+2);
+ cp3= (char *)(vlr->vcol+3);
+ }
+ else {
+ cp2= (char *)(vlr->vcol+1);
+ cp3= (char *)(vlr->vcol+2);
+ }
+ R.vcol[0]= (l*cp3[3]-u*cp1[3]-v*cp2[3])/255.0;
+ R.vcol[1]= (l*cp3[2]-u*cp1[2]-v*cp2[2])/255.0;
+ R.vcol[2]= (l*cp3[1]-u*cp1[1]-v*cp2[1])/255.0;
+
+ }
+ else {
+ R.vcol[0]= 0.0;
+ R.vcol[1]= 0.0;
+ R.vcol[2]= 0.0;
+ }
+ }
+ if(R.matren->mode & MA_FACETEXTURE) {
+ if((R.matren->mode & MA_VERTEXCOL)==0) {
+ R.vcol[0]= 1.0;
+ R.vcol[1]= 1.0;
+ R.vcol[2]= 1.0;
+ }
+ if(vlr->tface) render_realtime_texture();
+ }
+
+
+ /* hierna klopt de u en v EN O.dxuv en O.dyuv niet meer */
+ if(R.matren->texco & TEXCO_STICKY) {
+ if(v2->sticky) {
+
+ /* opnieuw u en v berekenen */
+ hox= x/Zmulx -1.0;
+ hoy= y/Zmuly -1.0;
+ u= (hox - v3->ho[0]/v3->ho[3])*s11 - (hoy - v3->ho[1]/v3->ho[3])*s10;
+ v= (hoy - v3->ho[1]/v3->ho[3])*s00 - (hox - v3->ho[0]/v3->ho[3])*s01;
+ l= 1.0+u+v;
+
+ o1= v1->sticky;
+ o2= v2->sticky;
+ o3= v3->sticky;
+
+ R.sticky[0]= l*o3[0]-u*o1[0]-v*o2[0];
+ R.sticky[1]= l*o3[1]-u*o1[1]-v*o2[1];
+
+ if(R.osatex) {
+ O.dxuv[0]= s11/Zmulx;
+ O.dxuv[1]= - s01/Zmulx;
+ O.dyuv[0]= - s10/Zmuly;
+ O.dyuv[1]= s00/Zmuly;
+
+ dl= O.dxuv[0]+O.dxuv[1];
+ O.dxsticky[0]= dl*o3[0]-O.dxuv[0]*o1[0]-O.dxuv[1]*o2[0];
+ O.dxsticky[1]= dl*o3[1]-O.dxuv[0]*o1[1]-O.dxuv[1]*o2[1];
+ dl= O.dyuv[0]+O.dyuv[1];
+ O.dysticky[0]= dl*o3[0]-O.dyuv[0]*o1[0]-O.dyuv[1]*o2[0];
+ O.dysticky[1]= dl*o3[1]-O.dyuv[0]*o1[1]-O.dyuv[1]*o2[1];
+ }
+ }
+ }
+ }
+ else {
+ VECCOPY(R.vn, vlr->n);
+ }
+ if(R.matren->texco & TEXCO_WINDOW) {
+ R.winco[0]= (x+(R.xstart))/(float)R.afmx;
+ R.winco[1]= (y+(R.ystart))/(float)R.afmy;
+ }
+
+
+ shadelamplus();
+
+ /* MIST */
+ if( (R.wrld.mode & WO_MIST) && (R.matren->mode & MA_NOMIST)==0 ){
+ alpha= mistfactor(R.co);
+ }
+ else alpha= 1.0;
+
+ /* RAYTRACE (tijdelijk?) UITGESCHAKELD */
+
+ if(R.matren->alpha!=1.0 || alpha!=1.0) {
+ fac= alpha*(R.matren->alpha);
+
+ /* gamma */
+ if(R.osa && usegamtab) fac*= fac;
+
+ shortcol[3]= 65535.0*fac;
+ shortcol[0]*= fac;
+ shortcol[1]*= fac;
+ shortcol[2]*= fac;
+ }
+ else {
+ shortcol[3]= 65535;
+ }
+ }
+ else {
+ shortcol[0]= 65535;
+ shortcol[1]= 65535;
+ shortcol[2]= 0;
+ shortcol[3]= 65535;
+ }
+
+ if(R.flag & R_LAMPHALO) {
+ if(vlaknr<=0) { /* bereken viewvec en zet R.co op far */
+
+ if( (G.special1 & G_HOLO) && ((Camera *)G.scene->camera->data)->flag & CAM_HOLO2) {
+ R.view[0]= (x+(R.xstart)+1.0+holoofs);
+ }
+ else {
+ R.view[0]= (x+(R.xstart)+1.0);
+ }
+
+ if(R.flag & R_SEC_FIELD) {
+ if(R.r.mode & R_ODDFIELD) R.view[1]= (y+R.ystart+0.5)*R.ycor;
+ else R.view[1]= (y+R.ystart+1.5)*R.ycor;
+ }
+ else R.view[1]= (y+R.ystart+1.0)*R.ycor;
+
+ R.view[2]= -R.viewfac;
+
+ if(R.r.mode & R_PANORAMA) {
+ float panoco, panosi;
+ panoco = getPanovCo();
+ panosi = getPanovSi();
+
+ u= R.view[0]; v= R.view[2];
+ R.view[0]= panoco*u + panosi*v;
+ R.view[2]= -panosi*u + panoco*v;
+ }
+
+ R.co[2]= 0.0;
+
+ }
+ renderspothalo(shortcol);
+ }
+}
+
+PixStr *addpsmain()
+{
+ PixStrMain *psm;
+
+ psm= &psmfirst;
+
+ while(psm->next) {
+ psm= psm->next;
+ }
+
+ psm->next= (PixStrMain *)MEM_mallocN(sizeof(PixStrMain),"pixstrMain");
+
+ psm= psm->next;
+ psm->next=0;
+ psm->ps= (PixStr *)MEM_mallocN(4096*sizeof(PixStr),"pixstr");
+ psmteller= 0;
+
+ return psm->ps;
+}
+
+void freeps()
+{
+ PixStrMain *psm,*next;
+
+ psm= &psmfirst;
+
+ while(psm) {
+ next= psm->next;
+ if(psm->ps) {
+ MEM_freeN(psm->ps);
+ psm->ps= 0;
+ }
+ if(psm!= &psmfirst) MEM_freeN(psm);
+ psm= next;
+ }
+
+ psmfirst.next= 0;
+ psmfirst.ps= 0;
+}
+
+void addps(long *rd, int vlak, unsigned int z, short ronde)
+{
+ static PixStr *prev;
+ PixStr *ps, *last = NULL;
+ int vlakand;
+
+ if( IS_A_POINTER_CODE(*rd)) {
+ ps= (PixStr *) POINTER_FROM_CODE(*rd);
+ vlakand= (vlak & 0x7FFFFF);
+
+ if( (ps->vlak0 & 0x7FFFFF) == vlakand ) return;
+
+ while(ps) {
+ if( (ps->vlak & 0x7FFFFF) == vlakand ) {
+ ps->mask |= (1<<ronde);
+ return;
+ }
+ last= ps;
+ ps= ps->next;
+ }
+
+ if((psmteller & 4095)==0) prev= addpsmain();
+ else prev++;
+ psmteller++;
+
+ last->next= prev;
+ prev->next= 0;
+ prev->vlak= vlak;
+ prev->z= z;
+ prev->mask = (1<<ronde);
+ prev->ronde= ronde;
+
+ return;
+ }
+
+ /* eerste PS maken */
+ if((psmteller & 4095)==0) prev= addpsmain();
+ else prev++;
+ psmteller++;
+
+ prev->next= 0;
+ prev->vlak0= (int) *rd;
+ prev->vlak= vlak;
+ prev->z= z;
+ prev->mask = (1<<ronde);
+ prev->ronde= ronde;
+ *rd= POINTER_TO_CODE(prev);
+}
+
+
+int count_mask(unsigned short mask)
+{
+ return (cmask[mask & 255]+cmask[mask>>8]);
+}
+
+float count_maskf(unsigned short mask)
+{
+ return (fmask[mask & 255]+fmask[mask>>8]);
+}
+
+
+void add_filt_mask(unsigned int mask, unsigned short *col, unsigned int *rb1, unsigned int *rb2, unsigned int *rb3)
+{
+ /* bereken de waarde van mask */
+ unsigned int a, maskand, maskshift;
+ int j;
+ unsigned short val, r, g, b, al;
+
+ al= col[3];
+ r= col[0];
+ g= col[1];
+ b= col[2];
+
+ maskand= (mask & 255);
+ maskshift= (mask >>8);
+
+ for(j=2; j>=0; j--) {
+
+ a= j;
+
+ val= *(mask1[a] +maskand) + *(mask2[a] +maskshift);
+ if(val) {
+ rb1[3]+= val*al;
+ rb1[0]+= val*r;
+ rb1[1]+= val*g;
+ rb1[2]+= val*b;
+ }
+ a+=3;
+
+ val= *(mask1[a] +maskand) + *(mask2[a] +maskshift);
+ if(val) {
+ rb2[3]+= val*al;
+ rb2[0]+= val*r;
+ rb2[1]+= val*g;
+ rb2[2]+= val*b;
+ }
+ a+=3;
+
+ val= *(mask1[a] +maskand) + *(mask2[a] +maskshift);
+ if(val) {
+ rb3[3]+= val*al;
+ rb3[0]+= val*r;
+ rb3[1]+= val*g;
+ rb3[2]+= val*b;
+ }
+
+ rb1+= 4;
+ rb2+= 4;
+ rb3+= 4;
+ }
+}
+
+void edge_enhance(void)
+{
+ /* use zbuffer to define edges, add it to the image */
+ int val, y, x, col, *rz, *rz1, *rz2, *rz3;
+ char *cp;
+
+ /* alle getallen in zbuffer 3 naar rechts shiften */
+ rz= (int *)R.rectz;
+ if(rz==0) return;
+
+ for(y=0; y<R.recty; y++) {
+ for(x=0; x<R.rectx; x++, rz++) {
+ (*rz)>>= 3;
+ }
+ }
+
+ /* eerste order, werkt toch niet goed!:
+ val= abs(rz1[0]-rz2[1])+ 2*abs(rz1[1]-rz2[1])+ abs(rz1[2]-rz2[1]);
+ val+= 2*abs(rz2[0]-rz2[1])+ 2*abs(rz1[2]-rz2[1]);
+ val+= abs(rz3[0]-rz2[1])+ 2*abs(rz3[1]-rz2[1])+ abs(rz3[2]-rz2[1]);
+ *rz= val;
+ */
+
+ rz1= (int *)R.rectz;
+ rz2= rz1+R.rectx;
+ rz3= rz2+R.rectx;
+ rz= (int *)R.rectot+R.rectx;
+
+ if(R.r.mode & R_OSA) {
+ cp= (char *)(R.rectaccu+R.rectx);
+ }
+ else {
+ cp= (char *)(R.rectot+R.rectx);
+ }
+
+ /* rz itself does not seem to be used. */
+
+ for(y=0; y<R.recty-2; y++) {
+
+ rz++;
+ for(x=0; x<R.rectx-2; x++, rz++, rz1++, rz2++, rz3++, cp+=4) {
+
+ col= abs(12*rz2[1]-rz1[0]-2*rz1[1]-rz1[2]-2*rz2[0]-2*rz2[2]-rz3[0]-2*rz3[1]-rz3[2])/3;
+ /* removed the abs... now, only front/back? pixels are */
+ /* accentuated? No, the lines seem shifted strangely. the does */
+ /* not seem to be any overlap? strange... */
+/* col= -( 12*rz2[1] */
+/* - rz1[0] - 2*rz1[1] - rz1[2] */
+/* - 2*rz2[0] - 2*rz2[2] */
+/* - rz3[0] - 2*rz3[1] - rz3[2]) /3; */
+
+ col= (R.r.edgeint*col)>>14;
+ if(col>255) col= 255;
+
+ if(col>0) {
+ if(R.r.mode & R_OSA) {
+ col/= R.osa;
+
+ val= cp[3]+col;
+ if(val>255) cp[3]= 255; else cp[3]= val;
+ }
+ else {
+ val= cp[0]- col;
+ if(val<0) cp[0]= 0; else cp[0]= val;
+ val= cp[1]- col;
+ if(val<0) cp[1]= 0; else cp[1]= val;
+ val= cp[2]- col;
+ if(val<0) cp[2]= 0; else cp[2]= val;
+ }
+ }
+ }
+ rz++;
+ rz1+= 2;
+ rz2+= 2;
+ rz3+= 2;
+ cp+= 8;
+ }
+
+}
+
+/* ********************* HOOFDLUSSEN ******************** */
+
+extern unsigned short *Acolrow;
+/* short zbuffermetdehand(); */
+void zbufshadeDA(void) /* Delta Accum Pixel Struct */
+{
+ PixStr *ps;
+ float xd, yd, xs, ys;
+ unsigned int *rz, *rp, *rt, mask, fullmask;
+ unsigned int *rowbuf1, *rowbuf2, *rowbuf3, *rb1, *rb2, *rb3;
+ int a, b;
+ long *rd;
+ unsigned short *colrb, *acol;
+ short v, x, y;
+ char *colrt, tempcol[4];
+
+ R.rectdaps= MEM_callocN(sizeof(long)*R.rectx*R.recty+4,"zbufDArectd");
+ if(R.flag & R_ZTRA) bgnaccumbuf();
+
+ psmteller= 0;
+
+ if(R.r.mode & R_EDGE) {
+ R.rectaccu= (unsigned int *)MEM_callocN(sizeof(int)*R.rectx*R.recty,"zbufshadeDA");
+ }
+
+ for(v=0; v<R.osa; v++) {
+
+ xd= jit[v][0];
+ yd= jit[v][1];
+ Zjitx= -xd;
+ Zjity= -yd;
+
+ RE_local_printrenderinfo(0.0, v);
+
+ /* RECTDELTA */
+ fillrect(R.rectot,R.rectx,R.recty,0);
+
+ zbufferall();
+
+ if(v==0) {
+ a= R.rectx*R.recty;
+ rt= R.rectot;
+ rd= R.rectdaps;
+ while(a--) {
+ *rd= (long)*rt;
+ rd++; rt++;
+ }
+ }
+ else {
+ rd= R.rectdaps;
+ rp= R.rectot;
+ rz= R.rectz;
+ for(y=0; y<R.recty; y++) {
+ for(x=0; x<R.rectx; x++, rp++, rd++) {
+ if(*rd!= (long) *rp) {
+ addps(rd, *rp, *(rz+x), v);
+ }
+ }
+ rz+= R.rectx;
+ }
+ }
+ /* 1 is voor osa */
+ if(R.r.mode & R_EDGE) edge_enhance();
+
+ if(RE_local_test_break()) break;
+ }
+ if(R.flag & (R_ZTRA+R_HALO) ) { /* om de juiste zbuffer Z voor transp en halo's terug te halen */
+ xd= jit[0][0];
+ yd= jit[0][1];
+ Zjitx= -xd;
+ Zjity= -yd;
+ RE_setwindowclip(0, 0);
+ RE_local_printrenderinfo(0.0, v);
+ zbufferall();
+ }
+
+ R.vlaknr= -1;
+ rd= R.rectdaps;
+ rz= R.rectz;
+ colrt= (char *)R.rectot;
+
+
+ fullmask= (1<<R.osa)-1;
+ /* de rowbuf is 4 pixels breder dan het plaatje! */
+ rowbuf1= MEM_callocN(3*(R.rectx+4)*4*sizeof(float), "ZbufshadeDA3");
+ rowbuf2= MEM_callocN(3*(R.rectx+4)*4*sizeof(float), "ZbufshadeDA3");
+ rowbuf3= MEM_callocN(3*(R.rectx+4)*4*sizeof(float), "ZbufshadeDA3");
+
+ for(y=0;y<=R.recty;y++) {
+
+ rb1= rowbuf1;
+ rb2= rowbuf2;
+ rb3= rowbuf3;
+
+ if(y<R.recty) {
+ for(x=0; x<R.rectx; x++, rd++) {
+
+ if( IS_A_POINTER_CODE(*rd)) {
+ ps= (PixStr *) POINTER_FROM_CODE(*rd);
+ mask= 0;
+
+ while(ps) {
+ b= centmask[ps->mask];
+ xs= (float)x+centLut[b & 15];
+ ys= (float)y+centLut[b>>4];
+
+ shadepixel(xs, ys, ps->vlak);
+
+ if(shortcol[3]) {
+ add_filt_mask(ps->mask, shortcol, rb1, rb2, rb3);
+ }
+ mask |= ps->mask;
+
+ ps= ps->next;
+ }
+ ps= (PixStr *) POINTER_FROM_CODE(*rd);
+ mask= (~mask) & fullmask;
+
+ b= centmask[mask];
+ xs= (float)x+centLut[b & 15];
+ ys= (float)y+centLut[b>>4];
+
+ shadepixel(xs, ys, ps->vlak0);
+
+ if(shortcol[3]) {
+ add_filt_mask(mask, shortcol, rb1, rb2, rb3);
+ }
+ }
+ else {
+ shadepixel((float)x, (float)y, (int)*rd);
+ if(shortcol[3]) {
+ add_filt_mask(fullmask, shortcol, rb1, rb2, rb3);
+ }
+ }
+
+ rb1+=4;
+ rb2+=4;
+ rb3+=4;
+ }
+ }
+ if(y>0) {
+
+ colrb= (unsigned short *)(rowbuf3+4);
+
+ /* LET OP: ENDIAN */
+
+ for(x=0; x<R.rectx; x++,colrt+=4) {
+ colrt[0]= ( (char *) (gamtab+colrb[0+MOST_SIG_BYTE]) )[MOST_SIG_BYTE];
+ colrt[1]= ( (char *) (gamtab+colrb[2+MOST_SIG_BYTE]) )[MOST_SIG_BYTE];
+ colrt[2]= ( (char *) (gamtab+colrb[4+MOST_SIG_BYTE]) )[MOST_SIG_BYTE];
+ colrt[3]= ( (char *) (gamtab+colrb[6+MOST_SIG_BYTE]) )[MOST_SIG_BYTE];
+ colrb+= 8;
+ }
+ if(R.flag & R_ZTRA) {
+ abufsetrow(y-1);
+ acol= Acolrow;
+ colrt-= 4*R.rectx;
+
+ for(x=0; x<R.rectx; x++, colrt+=4, acol+=4) {
+ if(acol[3]) {
+ tempcol[0]= (acol[0]>>8);
+ tempcol[1]= (acol[1]>>8);
+ tempcol[2]= (acol[2]>>8);
+ tempcol[3]= (acol[3]>>8);
+ addalphaOver(colrt, tempcol);
+ }
+ }
+ }
+
+ if(R.flag & R_HALO) {
+ /* van deze pixels zijn de pixstr al 1 scanline oud */
+ scanlinehaloPS(rz-R.rectx, rd-2*R.rectx, ((unsigned int *)colrt)-R.rectx, y-1);
+
+ }
+ scanlinesky(colrt-4*R.rectx, y-1);
+
+ /* scanline begint netjes: halo's gebruiken ook textures! */
+ R.vlaknr= -1;
+
+ }
+ if(y<R.recty) {
+ memset(rowbuf3, 0, (R.rectx+4)*4*4);
+ rb3= rowbuf3;
+ rowbuf3= rowbuf2;
+ rowbuf2= rowbuf1;
+ rowbuf1= rb3;
+
+ if( y>0 && G.background==0) {
+ if((y & 1)==0) {
+ RE_local_render_display(y-2, y-1,
+ R.rectx, R.recty,
+ R.rectot);
+ }
+ }
+ rz+= R.rectx;
+ }
+ if(RE_local_test_break()) break;
+ }
+
+ if( (R.r.mode & R_EDGE) && RE_local_test_break()==0) {
+ rt= R.rectot;
+ rp= R.rectaccu;
+ for(a= R.rectx*R.recty; a>0; a--, rt++, rp++) {
+ addalphaOver((char *)rt, (char *)rp);
+ }
+ }
+
+ /* hier stond dof */
+
+ MEM_freeN(R.rectdaps);
+ freeps();
+ MEM_freeN(rowbuf1);
+ MEM_freeN(rowbuf2);
+ MEM_freeN(rowbuf3);
+ R.rectdaps= 0;
+
+ if(R.r.mode & R_EDGE) if(R.rectaccu) MEM_freeN(R.rectaccu);
+ R.rectaccu= 0;
+ if(R.flag & R_ZTRA) endaccumbuf();
+} /* end of void zbufshadeDA() */
+
+/* ------------------------------------------------------------------------ */
+
+void zbufshade(void)
+{
+ unsigned int *rz,*rp;
+ float fy;
+ int x,y;
+ unsigned short *acol;
+ char *charcol, *rt;
+
+ Zjitx=Zjity= -.5;
+
+ zbufferall();
+
+ /* SHADE */
+ rp= R.rectot;
+ rz= R.rectz;
+ charcol= (char *)shortcol;
+
+ #ifdef BBIG_ENDIAN
+ #else
+ charcol++; /* short anders uitlezen */
+ #endif
+
+ if(R.flag & R_ZTRA) bgnaccumbuf();
+
+ for(y=0; y<R.recty; y++) {
+ R.vlaknr= -1;
+ fy= y;
+
+ if(R.flag & R_ZTRA) { /* zbuf tra */
+ abufsetrow(y);
+ acol= Acolrow;
+
+ for(x=0; x<R.rectx; x++, rp++, acol+= 4) {
+ /* spothalo's added here... *rp is the target colour? */
+ shadepixel((float)x, fy, *rp);
+
+ if(acol[3]) addAlphaOverShort(shortcol, acol);
+
+ if(shortcol[3]) {
+ rt= (char *)rp;
+ rt[0]= charcol[0];
+ rt[1]= charcol[2];
+ rt[2]= charcol[4];
+ rt[3]= charcol[6];
+ }
+ else *rp= 0;
+ }
+ }
+ else {
+ for(x=0; x<R.rectx; x++, rp++) {
+ shadepixel((float)x, fy, *rp);
+ if(shortcol[3]) {
+ rt= (char *)rp;
+ rt[0]= charcol[0];
+ rt[1]= charcol[2];
+ rt[2]= charcol[4];
+ rt[3]= charcol[6];
+ }
+ else *rp= 0;
+ }
+ }
+
+ if(R.flag & R_HALO) {
+ scanlinehalo(rz, (rp-R.rectx), y);
+ rz+= R.rectx;
+ }
+ scanlinesky( (char *)(rp-R.rectx), y);
+
+ if((y & 1) && G.background!=1) {
+ RE_local_render_display(y-1, y,
+ R.rectx, R.recty,
+ R.rectot);
+ }
+
+ if(RE_local_test_break()) break;
+ }
+
+ if(R.flag & R_ZTRA) endaccumbuf();
+
+ if(R.r.mode & R_EDGE) edge_enhance();
+
+ /* if((R.flag & R_HALO) && MISC_test_break()==0) halovert(); */
+
+} /* end of void zbufshade() */
+
+/* ------------------------------------------------------------------------ */
+
+void renderhalo(HaloRen *har) /* postprocess versie */
+{
+
+ float dist, xsq, ysq, xn, yn;
+ unsigned int *rectt, *rt;
+ int minx, maxx, miny, maxy, x, y;
+ char col[4];
+
+
+ har->miny= miny= har->ys - har->rad/R.ycor;
+ har->maxy= maxy= har->ys + har->rad/R.ycor;
+
+ if(maxy<0);
+ else if(R.recty<miny);
+ else {
+ minx= floor(har->xs-har->rad);
+ maxx= ceil(har->xs+har->rad);
+
+ if(maxx<0);
+ else if(R.rectx<minx);
+ else {
+
+ if(minx<0) minx= 0;
+ if(maxx>=R.rectx) maxx= R.rectx-1;
+ if(miny<0) miny= 0;
+ if(maxy>R.recty) maxy= R.recty;
+
+ rectt= R.rectot+ R.rectx*miny;
+
+ for(y=miny;y<maxy;y++) {
+
+ rt= (rectt+minx);
+
+ yn= (y - har->ys)*R.ycor;
+ ysq= yn*yn;
+
+ for(x=minx; x<=maxx; x++) {
+ xn= x - har->xs;
+ xsq= xn*xn;
+ dist= xsq+ysq;
+ if(dist<har->radsq) {
+ RE_shadehalo(har, col, 0, dist, xn, yn, har->flarec);
+
+ RE_addalphaAddfac((char *)rt, col, har->add);
+ }
+ rt++;
+ }
+
+ rectt+= R.rectx;
+
+ if(RE_local_test_break()) break;
+ }
+
+ }
+ }
+} /* end of void renderhalo(HaloRen *har), postprocess versie */
+
+/* ------------------------------------------------------------------------ */
+
+/* extern float hashvectf[]; */
+void RE_renderflare(HaloRen *har)
+{
+ HaloRen fla;
+ Material *ma;
+ float *rc, rad, alfa, visifac, vec[3];
+ int b, type;
+
+ fla= *har;
+ fla.linec= fla.ringc= fla.flarec= 0;
+
+ rad= har->rad;
+ alfa= har->alfa;
+
+ visifac= R.ycor*(har->pixels);
+ /* alle stralen opgeteld / r^3 == 1.0! */
+ visifac /= (har->rad*har->rad*har->rad);
+ visifac*= visifac;
+
+ ma= har->mat;
+
+ /* eerste halo: gewoon doen */
+
+ har->rad= rad*ma->flaresize*visifac;
+ har->radsq= har->rad*har->rad;
+ har->zs= 0.0;
+
+ har->alfa= alfa*visifac;
+
+ renderhalo(har);
+
+ /* volgende halo's: de flares */
+ rc= hashvectf + ma->seed2;
+
+ for(b=1; b<har->flarec; b++) {
+
+ fla.r= fabs(255.0*rc[0]);
+ fla.g= fabs(255.0*rc[1]);
+ fla.b= fabs(255.0*rc[2]);
+ fla.alfa= ma->flareboost*fabs(alfa*visifac*rc[3]);
+ fla.hard= 20.0 + fabs(70*rc[7]);
+ fla.tex= 0;
+
+ type= (int)(fabs(3.9*rc[6]));
+
+ fla.rad= ma->subsize*sqrt(fabs(2.0*har->rad*rc[4]));
+
+ if(type==3) {
+ fla.rad*= 3.0;
+ fla.rad+= R.rectx/10;
+ }
+
+ fla.radsq= fla.rad*fla.rad;
+
+ vec[0]= 1.4*rc[5]*(har->xs-R.afmx);
+ vec[1]= 1.4*rc[5]*(har->ys-R.afmy);
+ vec[2]= 32.0*sqrt(vec[0]*vec[0] + vec[1]*vec[1] + 1.0);
+
+ fla.xs= R.afmx + vec[0] + (1.2+rc[8])*R.rectx*vec[0]/vec[2];
+ fla.ys= R.afmy + vec[1] + (1.2+rc[8])*R.rectx*vec[1]/vec[2];
+
+ if(R.flag & R_SEC_FIELD) {
+ if(R.r.mode & R_ODDFIELD) fla.ys += 0.5;
+ else fla.ys -= 0.5;
+ }
+ if(type & 1) fla.type= HA_FLARECIRC;
+ else fla.type= 0;
+ renderhalo(&fla);
+
+ fla.alfa*= 0.5;
+ if(type & 2) fla.type= HA_FLARECIRC;
+ else fla.type= 0;
+ renderhalo(&fla);
+
+ rc+= 7;
+ }
+} /* end of void renderflare(HaloRen *har) */
+
+void add_halo_flare(void)
+{
+/* extern void RE_projectverto(); */ /* uit zbuf.c */
+ HaloRen *har = NULL;
+ int a, mode;
+
+ mode= R.r.mode;
+ R.r.mode &= ~R_PANORAMA;
+ R.xstart= -R.afmx;
+ R.ystart= -R.afmy;
+ R.xend= R.xstart+R.rectx-1;
+ R.yend= R.ystart+R.recty-1;
+
+ RE_setwindowclip(1,-1); /* geen jit:(-1) */
+ setzbufvlaggen(RE_projectverto);
+
+ for(a=0; a<R.tothalo; a++) {
+ if((a & 255)==0) har= R.bloha[a>>8];
+ else har++;
+
+ if(har->flarec) {
+ RE_renderflare(har);
+ }
+ }
+
+ R.r.mode= mode;
+} /* end of void add_halo_flare() */
+
+
+/* end of render.c */
+
+
diff --git a/source/blender/render/intern/source/renderdatabase.c b/source/blender/render/intern/source/renderdatabase.c
new file mode 100644
index 00000000000..03b9d117e23
--- /dev/null
+++ b/source/blender/render/intern/source/renderdatabase.c
@@ -0,0 +1,248 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * Storage, retrieval and query of render specific data.
+ */
+
+/*
+ * All data from a Blender scene is converter by the renderconverter/
+ * into a special format that is used by the render module to make
+ * images out of. These functions interface to the render-specific
+ * database.
+ *
+ * The blo{ha/ve/vl} arrays store pointers to blocks of 256 data
+ * entries each.
+ *
+ * The index of an entry is >>8 (the highest 24 * bits), to find an
+ * offset in a 256-entry block.
+ *
+ * - If the 256-entry block entry has an entry in the
+ * blove/bloha/blovl array of the current block, the i-th entry in
+ * that block is allocated to this entry.
+ *
+ * - If the entry has no block allocated for it yet, memory is
+ * allocated.
+ *
+ * The pointer to the correct entry is returned. Memory is guarateed
+ * to exist (as long as the malloc does not break). Since guarded
+ * allocation is used, memory _must_ be available. Otherwise, an
+ * exit(0) would occur.
+ *
+ */
+
+#include <math.h>
+#include "MEM_guardedalloc.h"
+#include "BLI_arithb.h"
+
+#include "DNA_texture_types.h"
+#include "BKE_texture.h"
+
+#include "render.h"
+#include "render_intern.h"
+
+/* ------------------------------------------------------------------------- */
+
+VertRen *RE_findOrAddVert(int nr)
+{
+ VertRen *v;
+ int a;
+
+ if(nr<0 || nr>MAXVERT ) {
+ printf("error in findOrAddVert: %d\n",nr);
+ return R.blove[0];
+ }
+ a= nr>>8;
+ v= R.blove[a];
+ if(v==0) {
+ v= (VertRen *)MEM_callocN(256*sizeof(VertRen),"findOrAddVert");
+ R.blove[a]= v;
+ }
+ v+= (nr & 255);
+ return v;
+}
+
+/* ------------------------------------------------------------------------ */
+
+HaloRen *RE_findOrAddHalo(int nr)
+{
+ HaloRen *h;
+ int a;
+
+ if(nr<0 || nr>MAXVERT ) {
+ printf("error in findOrAddHalo: %d\n",nr);
+ return R.bloha[0];
+ }
+ a= nr>>8;
+ h= R.bloha[a];
+ if(h==0) {
+ h= (HaloRen *)MEM_callocN(256*sizeof(HaloRen),"findOrAdHalo");
+ R.bloha[a]= h;
+ }
+ h+= (nr & 255);
+ return h;
+}
+
+/* ------------------------------------------------------------------------ */
+
+VlakRen *RE_findOrAddVlak(int nr)
+{
+ VlakRen *v;
+ int a;
+
+ if(nr<0 || nr>MAXVLAK ) {
+ printf("error in findOrAddVlak: %d\n",nr);
+ return R.blovl[0];
+ }
+ a= nr>>8;
+ v= R.blovl[a];
+ if(v==0) {
+ v= (VlakRen *)MEM_callocN(256*sizeof(VlakRen),"findOrAddVlak");
+ R.blovl[a]= v;
+ }
+ v+= (nr & 255);
+ return v;
+}
+
+/* ------------------------------------------------------------------------- */
+
+extern float Tin, Tr, Tg, Tb;
+HaloRen *RE_inithalo(Material *ma,
+ float *vec,
+ float *vec1,
+ float *orco,
+ float hasize,
+ float vectsize)
+{
+ HaloRen *har;
+ MTex *mtex;
+ float xn, yn, zn, texvec[3], hoco[4], hoco1[4];
+
+ if(hasize==0) return 0;
+
+ RE_projectverto(vec, hoco);
+ if(hoco[3]==0.0) return 0;
+ if(vec1) {
+ RE_projectverto(vec1, hoco1);
+ if(hoco1[3]==0.0) return 0;
+ }
+
+ har= RE_findOrAddHalo(R.tothalo++);
+ VECCOPY(har->co, vec);
+ har->hasize= hasize;
+
+ /* projectvert wordt in zbufvlaggen gedaan ivm parts/border/pano */
+
+ /* halovect */
+ if(vec1) {
+
+ har->type |= HA_VECT;
+
+ zn= hoco[3];
+ har->xs= 0.5*R.rectx*(hoco[0]/zn);
+ har->ys= 0.5*R.recty*(hoco[1]/zn);
+ har->zs= 0x7FFFFF*(1.0+hoco[2]/zn);
+
+ har->zBufDist = 0x7FFFFFFF*(hoco[2]/zn);
+
+ xn= har->xs - 0.5*R.rectx*(hoco1[0]/hoco1[3]);
+ yn= har->ys - 0.5*R.recty*(hoco1[1]/hoco1[3]);
+ if(xn==0.0 || (xn==0.0 && yn==0.0)) zn= 0.0;
+ else zn= atan2(yn, xn);
+
+ har->sin= sin(zn);
+ har->cos= cos(zn);
+ zn= VecLenf(vec1, vec);
+
+ har->hasize= vectsize*zn + (1.0-vectsize)*hasize;
+
+ VecSubf(har->no, vec, vec1);
+ Normalise(har->no);
+ }
+
+ if(ma->mode & MA_HALO_XALPHA) har->type |= HA_XALPHA;
+
+ har->alfa= ma->alpha;
+ har->r= 255.0*ma->r;
+ har->g= 255.0*ma->g;
+ har->b= 255.0*ma->b;
+ har->add= 255.0*ma->add;
+ har->mat= ma->ren;
+ har->hard= ma->har;
+ har->seed= ma->ren->seed1 % 256;
+
+ if(ma->mode & MA_STAR) har->starpoints= ma->starc;
+ if(ma->mode & MA_HALO_LINES) har->linec= ma->linec;
+ if(ma->mode & MA_HALO_RINGS) har->ringc= ma->ringc;
+ if(ma->mode & MA_HALO_FLARE) har->flarec= ma->flarec;
+
+
+ if(ma->mtex[0]) {
+
+ if( (ma->mode & MA_HALOTEX) ) har->tex= 1;
+ else {
+
+ mtex= ma->mtex[0];
+ VECCOPY(texvec, vec);
+
+ if(mtex->texco & TEXCO_NORM) {
+ ;
+ }
+ else if(mtex->texco & TEXCO_OBJECT) {
+ /* texvec[0]+= imatbase->ivec[0]; */
+ /* texvec[1]+= imatbase->ivec[1]; */
+ /* texvec[2]+= imatbase->ivec[2]; */
+ /* Mat3MulVecfl(imatbase->imat, texvec); */
+ }
+ else {
+ if(orco) {
+ VECCOPY(texvec, orco);
+ }
+ }
+
+ externtex(mtex, texvec);
+
+ yn= Tin*mtex->colfac;
+ zn= Tin*mtex->varfac;
+
+ if(mtex->mapto & MAP_COL) {
+ zn= 1.0-yn;
+ har->r= 255.0*(yn*Tr+ zn*ma->r);
+ har->g= 255.0*(yn*Tg+ zn*ma->g);
+ har->b= 255.0*(yn*Tb+ zn*ma->b);
+ }
+ if(mtex->texco & 16) {
+ har->alfa= 255.0*Tin;
+ }
+ }
+ }
+
+ return har;
+}
+/* ------------------------------------------------------------------------- */
diff --git a/source/blender/render/intern/source/shadbuf.c b/source/blender/render/intern/source/shadbuf.c
new file mode 100644
index 00000000000..bd0a844a354
--- /dev/null
+++ b/source/blender/render/intern/source/shadbuf.c
@@ -0,0 +1,771 @@
+/* shadbuf.c RENDER
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * april 95
+ *
+ * $Id$
+ *
+ * 27-Jun-2001 switched the shadow buffer for UR to the object-shadow
+ * buffers, and removed all references and fixes for UR rendering from
+ * this one.
+ * */
+
+#include <math.h>
+#include <string.h>
+
+#include "MTC_matrixops.h"
+#include "MEM_guardedalloc.h"
+#include "BLI_arithb.h"
+
+#include "DNA_lamp_types.h"
+
+#include "render.h"
+#include "render_intern.h"
+
+#include "shadbuf.h"
+#include "renderHelp.h"
+#include "jitter.h"
+#include "zbuf.h"
+
+/* if defined: objects don't cast shadows anymore */
+/* #define RE_NO_SHADOWS */
+
+/* unused? */
+static int bias= 0x00500000;
+/* crud */
+#define MIN2(x,y) ( (x)<(y) ? (x) : (y) )
+
+/* ------------------------------------------------------------------------- */
+
+void lrectreadRectz(int x1, int y1, int x2, int y2, char *r1);
+int sizeoflampbuf(struct ShadBuf *shb);
+int firstreadshadbuf(struct ShadBuf *shb, int xs, int ys, int nr);
+float readshadowbuf(struct ShadBuf *shb, int xs, int ys, int zs);
+float readshadowbuf_halo(struct ShadBuf *shb, int xs, int ys, int zs);
+float *give_jitter_tab(int samp);
+/* ------------------------------------------------------------------------- */
+
+
+void initshadowbuf(LampRen *lar, float mat[][4])
+{
+ struct ShadBuf *shb;
+ float hoek, temp, viewinv[4][4];
+
+ /* if(la->spsi<16) return; */
+
+ /* geheugen reserveren */
+ shb= (struct ShadBuf *)MEM_callocN( sizeof(struct ShadBuf),"initshadbuf");
+ lar->shb= shb;
+
+ if(shb==0) return;
+
+ VECCOPY(shb->co, lar->co);
+
+ /* percentage: min en max in de gaten houden */
+ shb->size= (lar->bufsize*R.r.size)/100;
+ if(shb->size<512) shb->size= 512;
+ else if(shb->size > lar->bufsize) shb->size= lar->bufsize;
+
+ shb->samp= lar->samp;
+ shb->soft= lar->soft;
+ shb->shadhalostep= lar->shadhalostep;
+
+ shb->zbuf= (unsigned long *)MEM_mallocN( sizeof(unsigned long)*(shb->size*shb->size)/256, "initshadbuf2");
+ shb->cbuf= (char *)MEM_callocN( (shb->size*shb->size)/256, "initshadbuf3");
+
+ if(shb->zbuf==0 || shb->cbuf==0) {
+ if(shb->zbuf) MEM_freeN(shb->zbuf);
+ MEM_freeN(lar->shb);
+ lar->shb= 0;
+ return;
+ }
+
+ MTC_Mat4Ortho(mat);
+ MTC_Mat4Invert(shb->winmat, mat); /* winmat is hier temp */
+
+ /* matrix: combinatie van inverse view en lampmat */
+ /* opnieuw berekenen: de ortho-render heeft geen correcte viewinv */
+ MTC_Mat4Invert(viewinv, R.viewmat);
+ MTC_Mat4MulMat4(shb->viewmat, viewinv, shb->winmat);
+
+ /* projektie */
+ hoek= saacos(lar->spotsi);
+ temp= 0.5*shb->size*cos(hoek)/sin(hoek);
+ shb->d= lar->clipsta;
+
+ shb->pixsize= (shb->d)/temp;
+
+ shb->far= lar->clipend;
+ /* bias is percentage, 2x groter gemaakt ivm invalshoek correctie */
+ shb->bias= (0.02*lar->bias)*0x7FFFFFFF;
+ shb->bias= shb->bias*(100/R.r.size);
+
+}
+/* ------------------------------------------------------------------------- */
+
+
+void lrectreadRectz(int x1, int y1, int x2, int y2, char *r1) /* leest deel uit rectz in r1 */
+{
+ unsigned int len4, *rz;
+
+ if(x1>=R.rectx || x2>=R.rectx || y1>=R.recty || y2>=R.recty) return;
+ if(x1>x2 || y1>y2) return;
+
+ len4= 4*(x2- x1+1);
+ rz= R.rectz+R.rectx*y1+x1;
+ for(;y1<=y2;y1++) {
+ memcpy(r1,rz,len4);
+ rz+= R.rectx;
+ r1+= len4;
+ }
+}
+
+
+int sizeoflampbuf(struct ShadBuf *shb)
+{
+ int num,count=0;
+ char *cp;
+
+ cp= shb->cbuf;
+ num= (shb->size*shb->size)/256;
+
+ while(num--) count+= *(cp++);
+
+ return 256*count;
+}
+
+float *give_jitter_tab(int samp)
+{
+ /* these are all possible jitter tables, takes up some
+ * 12k, not really bad!
+ * For soft shadows, it saves memory and render time
+ */
+ static int tab[17]={1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256};
+ static float jit[1496][2];
+ static char ctab[17]= {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ int a, offset=0;
+
+ if(samp<2) samp= 2;
+ else if(samp>16) samp= 16;
+
+ for(a=0; a<samp-1; a++) offset+= tab[a];
+
+ if(ctab[samp]==0) {
+ initjit(jit[offset], samp*samp);
+ ctab[samp]= 1;
+ }
+
+ return jit[offset];
+
+}
+
+void makeshadowbuf(LampRen *lar)
+{
+ struct ShadBuf *shb= lar->shb;
+ float panophi;
+ float temp, wsize, dist;
+ int *rz, *rz1, verg, verg1;
+ unsigned long *ztile;
+ int a, x, y, minx, miny, byt1, byt2;
+ short temprx,tempry, square;
+ char *rc, *rcline, *ctile, *zt;
+
+ panophi = getPanoPhi();
+
+ /* viewvars onthouden */
+ temprx= R.rectx; tempry= R.recty;
+ R.rectx= R.recty= shb->size;
+
+ shb->jit= give_jitter_tab(shb->samp);
+
+ /* matrices en window: in R.winmat komt transformatie
+ van obsview naar lampview, inclusief lampwinmat */
+
+ wsize= shb->pixsize*(shb->size/2.0);
+
+ i_window(-wsize, wsize, -wsize, wsize, shb->d, shb->far, shb->winmat);
+
+ MTC_Mat4MulMat4(shb->persmat, shb->viewmat, shb->winmat);
+
+ /* temp, will be restored */
+ MTC_Mat4SwapMat4(shb->persmat, R.winmat);
+
+ /* zbufferen */
+ if(R.rectz) MEM_freeN(R.rectz);
+ R.rectz= (unsigned int *)MEM_mallocN(sizeof(int)*shb->size*shb->size,"makeshadbuf");
+ rcline= MEM_mallocN(256*4+sizeof(int),"makeshadbuf2");
+
+ /* onthouden: panorama rot */
+ temp= panophi;
+ panophi= 0.0;
+ pushTempPanoPhi(0.0);
+
+ /* pano interference here? */
+ setzbufvlaggen(projectvert);
+
+ popTempPanoPhi();
+ panophi= temp;
+
+ zbuffershad(lar);
+
+ /* alle pixels 1 x ingevuld verwijderen (oneven) */
+ /* probleem hierbij kan geven dat er abrupte overgangen van zacht gebied
+ * naar geen zacht gebied is: bijv als eronder een klein vlakje zit
+ * DAAROM ER WEER UIT
+ * ook vanwege shadowhalo!
+ *
+ a= shb->size*shb->size;
+ rz= R.rectz;
+ while(a--) {
+ if(*rz & 1) *rz= 0x7FFFFFFF;
+ rz++;
+ }
+ */
+
+ square= lar->mode & LA_SQUARE;
+
+ /* Z tiles aanmaken: dit systeem is 24 bits!!! */
+
+ ztile= shb->zbuf;
+ ctile= shb->cbuf;
+ for(y=0; y<shb->size; y+=16) {
+ if(y< shb->size/2) miny= y+15-shb->size/2;
+ else miny= y-shb->size/2;
+
+ for(x=0; x<shb->size; x+=16) {
+
+ /* ligt rechthoek binnen spotbundel? */
+ a= shb->size/2;
+ if(x< a) minx= x+15-a;
+ else minx= x-a;
+
+ dist= sqrt( (float)(minx*minx+miny*miny) );
+
+ if(square==0 && dist>(float)(a+12)) { /* 12, tested with a onlyshadow lamp */
+ a= 256; verg= 0; /* 0x80000000; */ /* 0x7FFFFFFF; */
+ rz1= (&verg)+1;
+ }
+ else {
+ lrectreadRectz(x, y, MIN2(shb->size-1,x+15), MIN2(shb->size-1,y+15), rcline);
+ rz1= (int *)rcline;
+
+ verg= (*rz1 & 0xFFFFFF00);
+
+ for(a=0;a<256;a++,rz1++) {
+ if( (*rz1 & 0xFFFFFF00) !=verg) break;
+ }
+ }
+ if(a==256) { /* compleet leeg vakje */
+ *ctile= 0;
+ *ztile= *(rz1-1);
+ }
+ else {
+
+ /* ACOMP enz. zijn defined L/B endian */
+
+ rc= rcline;
+ rz1= (int *)rcline;
+ verg= rc[ACOMP];
+ verg1= rc[BCOMP];
+ rc+= 4;
+ byt1= 1; byt2= 1;
+ for(a=1;a<256;a++,rc+=4) {
+ byt1 &= (verg==rc[ACOMP]);
+ byt2 &= (verg1==rc[BCOMP]);
+
+ if(byt1==0) break;
+ }
+ if(byt1 && byt2) { /* alleen byte opslaan */
+ *ctile= 1;
+ *ztile= (unsigned long)MEM_mallocN(256+4, "tile1");
+ rz= (int *)*ztile;
+ *rz= *rz1;
+
+ zt= (char *)(rz+1);
+ rc= rcline;
+ for(a=0; a<256; a++, zt++, rc+=4) *zt= rc[GCOMP];
+ }
+ else if(byt1) { /* short opslaan */
+ *ctile= 2;
+ *ztile= (unsigned long)MEM_mallocN(2*256+4,"Tile2");
+ rz= (int *)*ztile;
+ *rz= *rz1;
+
+ zt= (char *)(rz+1);
+ rc= rcline;
+ for(a=0; a<256; a++, zt+=2, rc+=4) {
+ zt[0]= rc[BCOMP];
+ zt[1]= rc[GCOMP];
+ }
+ }
+ else { /* triple opslaan */
+ *ctile= 3;
+ *ztile= (unsigned long)MEM_mallocN(3*256,"Tile3");
+
+ zt= (char *)*ztile;
+ rc= rcline;
+ for(a=0; a<256; a++, zt+=3, rc+=4) {
+ zt[0]= rc[ACOMP];
+ zt[1]= rc[BCOMP];
+ zt[2]= rc[GCOMP];
+ }
+ }
+ }
+ ztile++;
+ ctile++;
+ }
+ }
+
+ MEM_freeN(rcline);
+ MEM_freeN(R.rectz); R.rectz= 0;
+
+ R.rectx= temprx; R.recty= tempry;
+ MTC_Mat4SwapMat4(shb->persmat, R.winmat);
+
+ /* printf("lampbuf %d\n", sizeoflampbuf(shb)); */
+}
+
+int firstreadshadbuf(struct ShadBuf *shb, int xs, int ys, int nr)
+{
+ /* return 1 als volledig gecomprimeerde shadbuftile && z==const */
+ static int *rz;
+ int ofs;
+ char *ct;
+
+ /* always test borders of shadowbuffer */
+ if(xs<0) xs= 0; else if(xs>=shb->size) xs= shb->size-1;
+ if(ys<0) ys= 0; else if(ys>=shb->size) ys= shb->size-1;
+
+ /* z berekenen */
+ ofs= (ys>>4)*(shb->size>>4) + (xs>>4);
+ ct= shb->cbuf+ofs;
+ if(*ct==0) {
+ if(nr==0) {
+ rz= *( (int **)(shb->zbuf+ofs) );
+ return 1;
+ }
+ else if(rz!= *( (int **)(shb->zbuf+ofs) )) return 0;
+
+ return 1;
+ }
+
+ return 0;
+}
+
+float readshadowbuf(struct ShadBuf *shb, int xs, int ys, int zs) /* return 1.0 : volledig licht */
+{
+ float temp;
+ int *rz, ofs;
+ int zsamp;
+ char *ct, *cz;
+
+ /* simpleclip */
+ /* if(xs<0 || ys<0) return 1.0; */
+ /* if(xs>=shb->size || ys>=shb->size) return 1.0; */
+
+ /* always test borders of shadowbuffer */
+ if(xs<0) xs= 0; else if(xs>=shb->size) xs= shb->size-1;
+ if(ys<0) ys= 0; else if(ys>=shb->size) ys= shb->size-1;
+
+ /* z berekenen */
+ ofs= (ys>>4)*(shb->size>>4) + (xs>>4);
+ ct= shb->cbuf+ofs;
+ rz= *( (int **)(shb->zbuf+ofs) );
+
+ if(*ct==3) {
+ ct= ((char *)rz)+3*16*(ys & 15)+3*(xs & 15);
+ cz= (char *)&zsamp;
+ cz[ACOMP]= ct[0];
+ cz[BCOMP]= ct[1];
+ cz[GCOMP]= ct[2];
+ }
+ else if(*ct==2) {
+ ct= ((char *)rz);
+ ct+= 4+2*16*(ys & 15)+2*(xs & 15);
+ zsamp= *rz;
+
+ cz= (char *)&zsamp;
+ cz[BCOMP]= ct[0];
+ cz[GCOMP]= ct[1];
+ }
+ else if(*ct==1) {
+ ct= ((char *)rz);
+ ct+= 4+16*(ys & 15)+(xs & 15);
+ zsamp= *rz;
+
+ cz= (char *)&zsamp;
+ cz[GCOMP]= ct[0];
+
+ }
+ else {
+ /* got warning on this from alpha .... */
+ /* but it's working code! (ton) */
+ zsamp= (int) rz;
+ }
+
+ /* if(zsamp >= 0x7FFFFE00) return 1.0; */ /* geen schaduw als op oneindig wordt gesampeld*/
+
+ if(zsamp > zs) return 1.0; /* absoluut geen schaduw */
+ else if( zsamp < zs-bias) return 0.0 ; /* absoluut wel schaduw */
+ else { /* zacht gebied */
+
+ temp= ( (float)(zs- zsamp) )/(float)bias;
+ return 1.0 - temp*temp;
+
+ }
+}
+
+
+float testshadowbuf(struct ShadBuf *shb, float inp) /* return 1.0: geen schaduw */
+{
+ float fac, co[4], dx[3], dy[3], aantal=0;
+ float xs1,ys1, siz, *j, xres, yres;
+ int xs,ys, zs;
+ short a,num;
+
+#ifdef RE_NO_SHADOWS
+ return 1.0;
+#endif
+
+ /* if(inp <= 0.0) return 1.0; */
+
+ /* renderco en osaco roteren */
+ siz= 0.5*(float)shb->size;
+ VECCOPY(co, R.co);
+ co[3]= 1.0;
+
+ MTC_Mat4MulVec4fl(shb->persmat, co); /* rationele hom co */
+
+ xs1= siz*(1.0+co[0]/co[3]);
+ ys1= siz*(1.0+co[1]/co[3]);
+
+ /* Clip for z: near and far clip values of the shadow buffer. We
+ * can test for -1.0/1.0 because of the properties of the
+ * coordinate transformations. */
+ fac= (co[2]/co[3]);
+
+ if(fac>=1.0) {
+ return 0.0;
+ } else if(fac<= -1.0) {
+ return 1.0;
+ }
+
+ zs= ((float)0x7FFFFFFF)*fac;
+
+ /* num*num samples nemen, gebied met fac vergroten */
+ num= shb->samp*shb->samp;
+ fac= shb->soft;
+
+
+ bias= (1.1-inp*inp)*shb->bias;
+
+ if(num==1) {
+ return readshadowbuf(shb,(int)xs1, (int)ys1, zs);
+ }
+
+ co[0]= R.co[0]+O.dxco[0];
+ co[1]= R.co[1]+O.dxco[1];
+ co[2]= R.co[2]+O.dxco[2];
+ co[3]= 1.0;
+ MTC_Mat4MulVec4fl(shb->persmat,co); /* rationele hom co */
+ dx[0]= xs1- siz*(1.0+co[0]/co[3]);
+ dx[1]= ys1- siz*(1.0+co[1]/co[3]);
+
+ co[0]= R.co[0]+O.dyco[0];
+ co[1]= R.co[1]+O.dyco[1];
+ co[2]= R.co[2]+O.dyco[2];
+ co[3]= 1.0;
+ MTC_Mat4MulVec4fl(shb->persmat,co); /* rationele hom co */
+ dy[0]= xs1- siz*(1.0+co[0]/co[3]);
+ dy[1]= ys1- siz*(1.0+co[1]/co[3]);
+
+ xres= fac*( fabs(dx[0])+fabs(dy[0]) );
+ yres= fac*( fabs(dx[1])+fabs(dy[1]) );
+
+ if(xres<fac) xres= fac;
+ if(yres<fac) yres= fac;
+
+ xs1-= (xres)/2;
+ ys1-= (yres)/2;
+
+ j= shb->jit;
+
+ if(xres<16.0 && yres<16.0) {
+ if(firstreadshadbuf(shb, (int)xs1, (int)ys1, 0)) {
+ if(firstreadshadbuf(shb, (int)(xs1+xres), (int)ys1, 1)) {
+ if(firstreadshadbuf(shb, (int)xs1, (int)(ys1+yres), 1)) {
+ if(firstreadshadbuf(shb, (int)(xs1+xres), (int)(ys1+yres), 1)) {
+ return readshadowbuf(shb,(int)xs1, (int)ys1, zs);
+ }
+ }
+ }
+ }
+ }
+
+ for(a=num;a>0;a--) {
+ /* i.p.v. jit ook met random geprobeerd: lelijk! */
+ xs= xs1 + xres*j[0];
+ ys= ys1 + yres*j[1];
+ j+=2;
+
+ aantal+= readshadowbuf(shb, xs, ys, zs);
+ }
+
+ /* Renormalizes for the sample number: */
+ return aantal/( (float)(num) );
+}
+
+/* different function... sampling behind clipend can be LIGHT, bias is negative! */
+/* return: light */
+float readshadowbuf_halo(struct ShadBuf *shb, int xs, int ys, int zs)
+{
+ float temp;
+ int *rz, ofs;
+ int zbias, zsamp;
+ char *ct, *cz;
+
+ /* simpleclip */
+ if(xs<0 || ys<0) return 0.0;
+ if(xs>=shb->size || ys>=shb->size) return 0.0;
+
+ /* z berekenen */
+ ofs= (ys>>4)*(shb->size>>4) + (xs>>4);
+ ct= shb->cbuf+ofs;
+ rz= *( (int **)(shb->zbuf+ofs) );
+
+ if(*ct==3) {
+ ct= ((char *)rz)+3*16*(ys & 15)+3*(xs & 15);
+ cz= (char *)&zsamp;
+ zsamp= 0;
+ cz[ACOMP]= ct[0];
+ cz[BCOMP]= ct[1];
+ cz[GCOMP]= ct[2];
+ }
+ else if(*ct==2) {
+ ct= ((char *)rz);
+ ct+= 4+2*16*(ys & 15)+2*(xs & 15);
+ zsamp= *rz;
+
+ cz= (char *)&zsamp;
+ cz[BCOMP]= ct[0];
+ cz[GCOMP]= ct[1];
+ }
+ else if(*ct==1) {
+ ct= ((char *)rz);
+ ct+= 4+16*(ys & 15)+(xs & 15);
+ zsamp= *rz;
+
+ cz= (char *)&zsamp;
+ cz[GCOMP]= ct[0];
+
+ }
+ else {
+ /* same as before */
+ /* still working code! (ton) */
+ zsamp= (int) rz;
+ }
+
+ /* geen schaduw als op oneindig wordt gesampeld*/
+
+ if(zsamp >= 0x7FFFFE00) return 1.0;
+
+ if(zsamp > zs) return 1.0; /* absoluut geen schaduw */
+ else {
+ /* bias is negative, so the (zs-bias) can be beyond 0x7fffffff */
+ zbias= 0x7fffffff - zs;
+ if(zbias > -bias) {
+ if( zsamp < zs-bias) return 0.0 ; /* absoluut wel schaduw */
+ }
+ else return 0.0 ; /* absoluut wel schaduw */
+ }
+
+ /* zacht gebied */
+
+ temp= ( (float)(zs- zsamp) )/(float)bias;
+ return 1.0 - temp*temp;
+}
+
+
+float shadow_halo(LampRen *lar, float *p1, float *p2)
+{
+ /* p1 p2 already are rotated in spot-space */
+ ShadBuf *shb= lar->shb;
+ float co[4], siz;
+ float labda, labdao, labdax, labday, ldx, ldy;
+ float zf, xf1, yf1, zf1, xf2, yf2, zf2;
+ float count, lightcount;
+ int x, y, z, xs1, ys1;
+ int dx = 0, dy = 0;
+
+ siz= 0.5*(float)shb->size;
+ /* negative! The other side is more important */
+ bias= -shb->bias;
+
+ co[0]= p1[0];
+ co[1]= p1[1];
+ co[2]= p1[2]/lar->sh_zfac;
+ co[3]= 1.0;
+ MTC_Mat4MulVec4fl(shb->winmat, co); /* rationele hom co */
+ xf1= siz*(1.0+co[0]/co[3]);
+ yf1= siz*(1.0+co[1]/co[3]);
+ zf1= (co[2]/co[3]);
+
+
+ co[0]= p2[0];
+ co[1]= p2[1];
+ co[2]= p2[2]/lar->sh_zfac;
+ co[3]= 1.0;
+ MTC_Mat4MulVec4fl(shb->winmat, co); /* rationele hom co */
+ xf2= siz*(1.0+co[0]/co[3]);
+ yf2= siz*(1.0+co[1]/co[3]);
+ zf2= (co[2]/co[3]);
+
+ /* de 2dda */
+
+ xs1= (int)xf1;
+ ys1= (int)yf1;
+
+ if(xf1 != xf2) {
+ if(xf2-xf1 > 0.0) {
+ labdax= (xf1-xs1-1.0)/(xf1-xf2);
+ ldx= -shb->shadhalostep/(xf1-xf2);
+ dx= shb->shadhalostep;
+ }
+ else {
+ labdax= (xf1-xs1)/(xf1-xf2);
+ ldx= shb->shadhalostep/(xf1-xf2);
+ dx= -shb->shadhalostep;
+ }
+ }
+ else {
+ labdax= 1.0;
+ ldx= 0.0;
+ }
+
+ if(yf1 != yf2) {
+ if(yf2-yf1 > 0.0) {
+ labday= (yf1-ys1-1.0)/(yf1-yf2);
+ ldy= -shb->shadhalostep/(yf1-yf2);
+ dy= shb->shadhalostep;
+ }
+ else {
+ labday= (yf1-ys1)/(yf1-yf2);
+ ldy= shb->shadhalostep/(yf1-yf2);
+ dy= -shb->shadhalostep;
+ }
+ }
+ else {
+ labday= 1.0;
+ ldy= 0.0;
+ }
+
+ x= xs1;
+ y= ys1;
+ labda= count= lightcount= 0.0;
+
+/* printf("start %x %x \n", (int)(0x7FFFFFFF*zf1), (int)(0x7FFFFFFF*zf2)); */
+
+ while(1) {
+ labdao= labda;
+
+ if(labdax==labday) {
+ labdax+= ldx;
+ x+= dx;
+ labday+= ldy;
+ y+= dy;
+ }
+ else {
+ if(labdax<labday) {
+ labdax+= ldx;
+ x+= dx;
+ } else {
+ labday+= ldy;
+ y+= dy;
+ }
+ }
+
+ labda= MIN2(labdax, labday);
+ if(labda==labdao || labda>=1.0) break;
+
+ zf= zf1 + labda*(zf2-zf1);
+ count+= 1.0;
+
+ if(zf<= 0.0) lightcount += 1.0; /* close to the spot */
+ else {
+
+ /* make sure, behind the clipend we extend halolines. */
+ if(zf>=1.0) z= 0x7FFFF000;
+ else z= (int)(0x7FFFF000*zf);
+
+ lightcount+= readshadowbuf_halo(shb, x, y, z);
+
+ }
+ }
+
+ if(count!=0.0) return (lightcount/count);
+ return 0.0;
+
+}
+
+
+
+
+/* sampelen met filter
+ xstart= xs-1;
+ ystart= ys-1;
+ if(xstart<0) xstart= 0;
+ if(ystart<0) ystart= 0;
+ xend= xstart+2;
+ yend= ystart+2;
+ if(xend>=shb->size) { xstart= shb->size-3; xend= shb->size-1;}
+ if(yend>=shb->size) { ystart= shb->size-3; yend= shb->size-1;}
+
+ fid= filt3;
+ for(ys=ystart;ys<=yend;ys++) {
+ rz= shb->buf+ ys*shb->size+ xstart;
+ for(xs= xstart;xs<=xend;xs++,rz++) {
+ if( *rz+0x100000<zs) aantal+= *fid;
+ fid++;
+ }
+ }
+
+
+ return 1.0-((float)aantal)/16.0;
+*/
+
+
+
+
+
+
+
+
+
+
diff --git a/source/blender/render/intern/source/shadowBuffer.cpp b/source/blender/render/intern/source/shadowBuffer.cpp
new file mode 100644
index 00000000000..76668f4e9ac
--- /dev/null
+++ b/source/blender/render/intern/source/shadowBuffer.cpp
@@ -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 *****
+ */
+
+#include <assert.h>
+//#include <iostream.h>
+
+#include "render.h"
+#include "render_intern.h"
+#include "shadbuf.h"
+#include "shadowBuffer.h" /* the C header */
+#include "RE_ShadowBuffer.h" /* the base buffer */
+#include "RE_DummyShadowBuffer.h" /* A dummy shadow buffer */
+#include "RE_basicShadowBuffer.h" /* the 'old' shadow buffer */
+
+struct ShadBuf;
+struct LampRen;
+struct Lamp;
+/*
+ * Creates a shadow buffer of a certain type
+ */
+RE_ShadowBufferHandle RE_createShadowBuffer(struct LampRen *lar,
+ float mat[][4],
+ int mode)
+{
+ /* make a dummy: this always returns a fixed value */
+ RE_ShadowBuffer* buf = NULL;
+ switch (mode) {
+ case 0:
+ buf = new RE_DummyShadowBuffer();
+ break;
+ case 1:
+ /* loop to the old c-based buffer */
+ /* memory release is done implicitly! */
+ initshadowbuf(lar, mat);
+ break;
+ case 2:
+ buf = new RE_BasicShadowBuffer(lar, mat);
+ break;
+ case 3:
+// cout << "Deep shadow buffer requested\n";
+ break;
+ default:
+// cerr << "Bad shadow buffer type specified\n";
+ ; /* nada */
+ }
+ return (RE_ShadowBufferHandle) buf;
+}
+
+void RE_deleteShadowBuffer(RE_ShadowBufferHandle buf)
+{
+// cout << "requesting buffer delete\n";
+ assert(buf);
+ delete (RE_ShadowBuffer*) buf;
+}
+
+void RE_buildShadowBuffer(RE_ShadowBufferHandle buf,
+ struct LampRen *lar)
+{
+ assert(buf);
+ ((RE_ShadowBuffer*) buf)->importScene(lar);
+}
+
+
+void RE_testshadowbuf(RE_ShadowBufferHandle buf,
+ struct ShadBuf* shbp,
+ float inp,
+ float* shadres)
+{
+ assert(buf);
+ ((RE_ShadowBuffer*) buf)->readShadowValue(shbp, inp, shadres);
+}
diff --git a/source/blender/render/intern/source/vanillaRenderPipe.c b/source/blender/render/intern/source/vanillaRenderPipe.c
new file mode 100644
index 00000000000..5f78e1b25c9
--- /dev/null
+++ b/source/blender/render/intern/source/vanillaRenderPipe.c
@@ -0,0 +1,1654 @@
+/**
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * vanillaRenderPipe.c
+ *
+ * 28-06-2000 nzc
+ *
+ * $Id$
+ *
+ */
+
+/*
+ The render pipe
+ ---------------
+
+ The overall results of the render pass should end up in R.rectot. This
+ buffer already exists, and although its contents may change, its location
+ may not. A lot of other routines depend on it!
+
+*/
+
+/* global includes */
+#include <math.h>
+#include <limits.h> /* INT_MIN,MAX are used here */
+#include <stdlib.h>
+#include "MTC_vectorops.h"
+#include "MTC_matrixops.h"
+#include "MEM_guardedalloc.h"
+
+#include "DNA_camera_types.h"
+#include "DNA_object_types.h"
+#include "BKE_global.h"
+
+/* local includes (from the render module) */
+#include "RE_callbacks.h"
+#include "render.h" /* all kinds of stuff */
+#include "render_intern.h"
+#include "zbuf.h" /* for vergzvlak, zbufclip, zbufclipwire */
+#include "edgeRender.h" /* all edge rendering stuff */
+#include "pixelshading.h" /* painting the pixels */
+#include "rendercore.h"
+
+/* general calculus and data manipulation, also local */
+#include "gammaCorrectionTables.h"
+#include "jitter.h"
+#include "pixelblending.h"
+#include "zbufferdatastruct.h"
+
+/* own includes */
+#include "vanillaRenderPipe.h"
+#include "vanillaRenderPipe_int.h"
+
+/* crud */
+#define MIN2(x,y) ( (x)<(y) ? (x) : (y) )
+
+/* ------------------------------------------------------------------------- */
+/* Debug defines: disable all for production level code. */
+/* These variables control faking of rendered colours, extra tracing, */
+/* extra error checking and such. */
+/* ------------------------------------------------------------------------- */
+
+/* if defined: _very_ explicit tracing and checking enabled */
+/* #define RE_FULL_SAFETY */
+/* if defined: use 'simple' alpha thresholding on oversampling */
+/* #define RE_SIMPLE_ALPHA_THRESHOLD */
+
+/* ------------------------------------------------------------------------- */
+
+#ifdef RE_FULL_SAFETY
+/* Full safety does the following: */
+/* - add extra bounds checking */
+/* - add extra type checking */
+/* - do a little performance analysis */
+/* - trace the original sources */
+
+/* trace the version of the source */
+char vanillaRenderPipe_ext_h[] = VANILLARENDERPIPE_EXT_H;
+char vanillaRenderPipe_int_h[] = VANILLARENDERPIPE_INT_H;
+char vanillaRenderPipe_types_h[] = VANILLARENDERPIPE_TYPES_H;
+char vanillaRenderPipe_c[] =
+"$Id$";
+/* counters for error handling */
+static int conflictsresolved; /* number of conflicts in one frame */
+
+#include "errorHandler.h"
+#endif /* RE_FULL_SAFETY stuff */
+
+/* ------------------------------------------------------------------------- */
+
+/* External : -------------------------------------------------------------- */
+
+extern float centLut[16]; /* Lookup for jitter offsets. */
+extern unsigned int Zsample; /* Nr. of the currently active oversample. This */
+ /* counter must be set explicitly by the */
+ /* function that builds the z-buffer. */
+ /* The buffer-filling functions use it. */
+extern float Zjitx,Zjity; /* The x,y values for jitter offset */
+
+extern float Zmulx, Zmuly; /* Some kind of scale? */
+
+extern unsigned int Zvlnr; /* Face rendering pointer and counter: these */
+extern VlakRen *Zvlr; /* are used for 'caching' render results. */
+
+ /* These function pointers are used for z buffer filling. */
+extern void (*zbuffunc)(float *, float *, float *);
+extern void (*zbuflinefunc)(float *, float *);
+
+extern char cmask[256]; /* When a pixel is supersampled, we must */
+extern char *centmask; /* compute its colour on a point _on_ the face. */
+ /* These two are used to compute an offset to */
+ /* guarantee we use valid coordinates. */
+
+/* unsorted */
+extern float holoofs, fmask[256];
+extern unsigned short usegamtab, shortcol[4],
+ *mask1[9], *mask2[9],/* *igamtab1, */ *igamtab2/*, *gamtab */;
+
+extern RE_APixstrExt *APixbufExt;/*Zbuffer: linked list of face, halo indices*/
+
+/* Globals : --------------------------------------------------------------- */
+
+RE_COLBUFTYPE *AColourBuffer; /* Buffer for colours of 1 line of pixels */
+static int Aminy; /* y value of first line in the accu buffer */
+static int Amaxy; /* y value of last line in the accu buffer */
+ /* -also used to clip when zbuffering */
+
+/* Buffer width refers to the size of the buffers we build. Image size is */
+/* the same as R.rectx, R.recty. */
+static int imageHeight; /* image size in pixels in y direction */
+static int imageWidth; /* image size in pixels in x direction */
+static int bufferHeight; /* image size in pixels in y direction */
+static int bufferWidth; /* image size in pixels in x direction */
+static int zBufferWidth; /* special width because zbuffer needs to be */
+ /* wider */
+
+static int Azvoordeel; /* A small offset for transparent rendering. */
+int alphaLUT[32]; /* alpha lookuptable, for oversampling */
+ /* Its function has been superceded because */
+ /* pixels are always integrated. This */
+ /* performs the same normalization. */
+int osaNr; /* The oversample number. I keep it */
+ /* separately here, because I treat no OSA */
+ /* as if it were osa=1. */
+RE_COLBUFTYPE collector[4]; /* used throughout as pixel colour accu */
+RE_COLBUFTYPE sampcol[RE_MAX_OSA_COUNT * 4]; /* subpixel accu buffer */
+
+/* ------------------------------------------------------------------------- */
+/* Local (for now) */
+/* void integrateStack(struct RE_faceField* stack, */
+/* int ptr, */
+/* float x, */
+/* float y, */
+/* int osaNr); */
+void integratePerSubStack(struct RE_faceField* stack,
+ int ptr,
+ float x,
+ float y,
+ int osaNr);
+
+/* ------------------------------------------------------------------------- */
+
+void zBufShadeAdvanced()
+{
+ int y, keepLooping = 1;
+ float xjit = 0.0, yjit = 0.0;
+
+#ifdef RE_FULL_SAFETY
+ /* reset trace */
+ RE_errortrace_reset();
+ conflictsresolved = 0;
+ fprintf(stderr, "\n*** Activated full error trace on "
+ "unified renderer using:\n\t%s\n\t%s\n\t%s\n\t%s",
+ vanillaRenderPipe_c, vanillaRenderPipe_ext_h,
+ vanillaRenderPipe_int_h, vanillaRenderPipe_types_h);
+#endif
+
+ Zjitx=Zjity= -0.5; /* jitter preset: 0.5 pixel */
+
+ /* EDGE: for edge rendering we should compute a larger buffer, but this */
+ /* may require modifications at a deeper level. For now, we just */
+ /* 'ignore' edge pixels. */
+ imageHeight = R.recty;
+ imageWidth = R.rectx;
+ bufferHeight = R.recty;
+ bufferWidth = R.rectx;
+
+ /* Set osaNr. Treat 'no osa' as 'osa = 1' */
+ if(R.r.mode & R_OSA) {
+ osaNr = R.osa;
+ if(osaNr > 16) { /* check was moved from calcZBufLine */
+ printf("zBufShadeAdvanced> osa too large (internal error)\n");
+ G.afbreek= 1;
+ return;
+ }
+ } else {
+ /* little hack */
+ osaNr = 1;
+ xjit = jit[0][0];
+ yjit = jit[0][1];
+ jit[0][0] = 0.45;
+ jit[0][1] = 0.45;
+ }
+
+ RE_setwindowclip(0, -1); /* just to be sure, reset the view matrix */
+
+ initRenderBuffers(bufferWidth);
+
+ /* ugh! should be converted sooner!! */
+ switch (R.r.alphamode) {
+ case R_ALPHAKEY:
+ setSkyBlendingMode(RE_ALPHA_KEY);
+ break;
+ case R_ALPHAPREMUL:
+ setSkyBlendingMode(RE_ALPHA_PREMUL);
+ break;
+/* not there... this is the default case */
+/* case R_ALPHASKY: */
+/* setSkyBlendingMode(RE_ALPHA_SKY); */
+/* break; */
+ default:
+ setSkyBlendingMode(RE_ALPHA_SKY);
+ }
+
+ y = 0;
+ while ( (y < bufferHeight) && keepLooping) {
+ calcZBufLine(y);
+ R.vlaknr= -1; /* huh? why reset this counter? for shadePixel! */
+ renderZBufLine(y);
+ transferColourBufferToOutput(y);
+
+ if((y & 1) && G.background!=1) RE_local_render_display(y-1, y,
+ imageWidth,
+ imageHeight,
+ R.rectot);
+
+ if(RE_local_test_break()) keepLooping = 0;
+ y++;
+ }
+ freeRenderBuffers();
+
+ /* Edge rendering is done purely as a post-effect */
+ if(R.r.mode & R_EDGE) {
+ addEdges((char*)R.rectot, imageWidth, imageHeight,
+ osaNr,
+ R.r.edgeint, R.r.same_mat_redux,
+ G.compat, G.notonlysolid,
+ R.r.edgeR, R.r.edgeG, R.r.edgeB);
+ }
+
+ add_halo_flare(); /* from rendercore */
+
+#ifdef RE_FULL_SAFETY
+ fprintf(stderr, "\n--- resolved %d conflicts", conflictsresolved);
+ fflush(stderr);
+#endif
+
+ if (!(R.r.mode & R_OSA)) {
+ jit[0][0] = xjit;
+ jit[0][1] = yjit;
+ }
+
+} /* end of void zbufshadeAdvanced() */
+
+/* ------------------------------------------------------------------------- */
+
+void initRenderBuffers(int bwidth)
+{
+
+ /* The +1 is needed because the fill-functions use a +1 offset when */
+ /* filling in pixels. Mind that also the buffer-clearing function needs */
+ /* this offset (done in calcZBufLine). */
+ /* The offset is wrong: it shouldn't be there. I need to fix this still. */
+ AColourBuffer = MEM_callocN(4 * sizeof(RE_COLBUFTYPE) * bwidth,
+ "Acolrow");
+ zBufferWidth = bwidth + 1;
+ initZbuffer(bwidth + 1);
+
+ Aminy= -1000; /* indices of lines in the z buffer: no lines buffered */
+ Amaxy= -1000;
+
+ /* Use slider when the gamma button is pressed. */
+ if (R.r.mode & R_GAMMA) {
+ makeGammaTables(R.r.gamma);
+ setDoGamma(1);
+ } else {
+ /*
+ Needed for spotlights! Maybe a separate gammatable would be
+ required here
+ */
+ makeGammaTables(1.0);
+ setDoGamma(0);
+ }
+
+} /* End of void initZBuffers(void) */
+
+/* ------------------------------------------------------------------------- */
+
+void freeRenderBuffers(void) {
+ if (AColourBuffer) MEM_freeN(AColourBuffer);
+ freeZbuffer();
+} /* End of void freeZBuffers(void) */
+
+/* ------------------------------------------------------------------------- */
+
+void calcZBufLine(int y)
+{
+
+ int part;
+ int keepLooping = 1;
+
+ if(y<0) return;
+
+ /* zbuffer fix: here? */
+ Zmulx= ((float) bufferWidth)/2.0;
+ Zmuly= ((float) bufferHeight)/2.0;
+
+
+ /* use these buffer fill functions */
+ zbuffunc = zBufferFillFace;
+ zbuflinefunc = zBufferFillEdge;
+
+ /* (FORALL y: Aminy =< y =< Amaxy: y is buffered) */
+ if( (y < Aminy) || (y > Amaxy)) {
+ /* prepare buffer */
+ part = (y/RE_ZBUFLEN); /* These two lines are mystifying me... */
+ Aminy = part * RE_ZBUFLEN; /* Possibly for rounding things? */
+ Amaxy = Aminy + RE_ZBUFLEN - 1;
+/* if(Amaxy >= R.recty) Amaxy = R.recty-1; */
+ if(Amaxy >= bufferHeight) Amaxy = bufferHeight - 1;
+ resetZbuffer();
+
+ Zsample = 0; /* Zsample is used internally ! */
+ while ( (Zsample < osaNr) && keepLooping ) {
+ /* Apply jitter to this pixel. The jitter offsets are globals. */
+ /* They are added in zbufclip() */
+ /* Negative: these offsets are added to the vertex coordinates */
+ /* so it equals translating viewpoint over the positive vector. */
+ Zjitx= -jit[Zsample][0];
+ Zjity= -jit[Zsample][1];
+
+ keepLooping = fillZBufDistances();
+
+ if(RE_local_test_break()) keepLooping = 0;
+ Zsample++;
+ }
+ };
+
+} /*End of void calcZBufLine(int y) */
+
+/* ------------------------------------------------------------------------- */
+
+int countAndSortPixelFaces(int zrow[RE_MAX_FACES_PER_PIXEL][RE_PIXELFIELDSIZE],
+ RE_APixstrExt *ap)
+{
+#ifdef RE_FULL_SAFETY
+ char fname[] = "countAndSortPixelFaces";
+#endif
+ int totvlak; /* face counter */
+ int i; /* generic counter */
+
+ totvlak= 0;
+ while(ap) {
+ for(i=0; i<4; i++) {
+ if(ap->t[i]) {
+ zrow[totvlak][0] = ap->zmin[i];
+ zrow[totvlak][1] = ap->p[i];
+ zrow[totvlak][2] = ap->mask[i];
+ zrow[totvlak][3] = ap->t[i];
+ zrow[totvlak][4] = ap->zmax[i];
+ totvlak++;
+ if(totvlak > (RE_MAX_FACES_PER_PIXEL - 1))
+ {
+ totvlak = (RE_MAX_FACES_PER_PIXEL - 1);
+#ifdef RE_FULL_SAFETY
+ RE_error(RE_TOO_MANY_FACES, fname);
+#endif
+ }
+ } else break;
+ };
+ ap= ap->next;
+ }
+
+ if(totvlak==2) { /* Sort faces ----------------------------- */
+ if(zrow[0][0] < zrow[1][0]) {
+ i= zrow[0][0]; zrow[0][0]= zrow[1][0]; zrow[1][0]= i;
+ i= zrow[0][1]; zrow[0][1]= zrow[1][1]; zrow[1][1]= i;
+ i= zrow[0][2]; zrow[0][2]= zrow[1][2]; zrow[1][2]= i;
+ i= zrow[0][3]; zrow[0][3]= zrow[1][3]; zrow[1][3]= i;
+ i= zrow[0][4]; zrow[0][4]= zrow[1][4]; zrow[1][4]= i;
+ } /* else: two faces, and ordering is ok */
+ } else if (totvlak != 1) qsort(zrow, totvlak,
+ sizeof(int)*RE_PIXELFIELDSIZE, vergzvlak);
+ return totvlak;
+} /* end of int countAndSortPixelFaces(int* zrow,RE_APixstrExt *ap ) */
+
+/* ------------------------------------------------------------------------- */
+/* Oversampler v3 - check CVS for older versions */
+/* */
+/* In this version, I have split up the rendering into several parts, so I */
+/* can generate better profiles. */
+/* */
+/* - multiple blend functions ? */
+/* - x-rays? */
+/* - volumetric stuff ? */
+/* - maybe the oversampling should move to the shading part */
+/* */
+/* ------------------------------------------------------------------------- */
+
+/* These variables describe the buffers needed for the oversampling. */
+/* 1. A bit vector with flags to indicate which pixels have received colour. */
+static int VR_covered = 0;
+/* 2. The local vector collector, for resolving conflicts only. */
+static int VR_cbuf[RE_MAX_FACES_PER_PIXEL][2];
+
+/**
+ * Analyze the z-buffer, and pre-sample the colours.
+ */
+int composeStack(int zrow[RE_MAX_FACES_PER_PIXEL][RE_PIXELFIELDSIZE],
+ struct RE_faceField* stack, int ptr,
+ int totvlak, float x, float y, int osaNr) {
+
+#ifdef RE_FULL_SAFETY
+ char* fname = "composeStack";
+#endif
+ float xs = 0.0;
+ float ys = 0.0; /* coordinates for the render-spot */
+
+ float alphathreshold[RE_MAX_OSA_COUNT];
+ int inconflict = 0;
+ int saturationthreshold = 0;
+ int saturated = 0;
+ int i = 0;
+ int Ccount = 0;
+ int Cthresh = 0;
+ int save_totvlak = totvlak;
+ int fullsubpixelflags = 0;
+
+ VR_covered = 0;
+ for(i = 0; i < osaNr; i++) alphathreshold[i] = 0.0;
+ saturationthreshold = ( (1<<osaNr) - 1);
+
+ while ( (!saturated || (saturated && inconflict) ) && (totvlak > 0) ) {
+ totvlak--;
+
+ i= centmask[ zrow[totvlak][RE_MASK] ]; /* recenter sample position - */
+ xs= (float)x+centLut[i & 15];
+ ys= (float)y+centLut[i >> 4];
+
+ /* stack face ----------- */
+ stack[ptr].data = renderPixel(xs, ys, zrow[totvlak]);
+ stack[ptr].faceType = zrow[totvlak][RE_TYPE];
+ cpFloatColV(collector, stack[ptr].colour);
+ stack[ptr].mask = zrow[totvlak][RE_MASK];
+
+ /* This is done so that spothalos are properly overlayed on halos */
+ /* maybe we need to check the colour here... */
+ if(zrow[totvlak][RE_TYPE] & RE_POLY) VR_covered |= zrow[totvlak][RE_MASK];
+
+ /* calculate conflict parameters: ---------------------------------- */
+ if( zrow[totvlak][RE_ZMIN] < Cthresh ) {
+ inconflict = 1;
+ /* Prevent from switching on bad data. This may be done more */
+ /* efficiently later on. It is _quite_ important. */
+ if (totvlak == save_totvlak - 1) Ccount = 0;
+ else if(Ccount == 0) Ccount = 2;
+ else Ccount++;
+ stack[ptr].conflictCount = Ccount;
+ if (zrow[totvlak][RE_ZMAX] > Cthresh)
+ Cthresh = zrow[totvlak][RE_ZMAX];
+#ifdef RE_FULL_SAFETY
+ if (Ccount == 2) conflictsresolved++;
+#endif
+ } else {
+ Cthresh = zrow[totvlak][RE_ZMAX];
+ Ccount = 0;
+ stack[ptr].conflictCount = 0;
+ if (totvlak > 0 )
+ inconflict = (zrow[totvlak-1][RE_ZMIN] < Cthresh);
+ else inconflict = 0;
+ }
+
+ ptr++;
+
+ /* alpha threshold ------------------------------------------------- */
+ /* There are currently two ways of blending: alpha-over, and add. */
+ /* Add-blending does strange things, in the sense that alpha is */
+ /* simply added, and colour is sort of alpha-over blended. Using the */
+ /* same thresholding relation seems to work ok. For less than unity */
+ /* add factor, the alpha threshold may rise faster, but currently we */
+ /* do not check for this factor. */
+ for(i = 0; i < osaNr; i++) {
+ if ( zrow[totvlak][RE_MASK] & (1<<i)) {
+ alphathreshold[i] +=
+ ((1.0 - alphathreshold[i]) * collector[3]);
+ if (alphathreshold[i] > RE_FULL_ALPHA_FLOAT)
+ fullsubpixelflags |= (1<<i);
+ }
+ }
+ saturated = (fullsubpixelflags >= saturationthreshold);
+
+ } /* done stacking ----------------------------------------------------- */
+
+ /*
+ STACK_SKY Sometimes, a sky pixel is needed. Since there are
+ some issues with mist/ ztra/ env, I always put the sky here.
+ */
+/* if (!saturated) { */
+ totvlak--;
+
+ xs= (float)x;
+ ys= (float)y;
+
+ renderSkyPixelFloat(xs, ys);
+
+ stack[ptr].faceType = RE_SKY;
+ cpFloatColV(collector, stack[ptr].colour);
+ stack[ptr].data = NULL;
+ stack[ptr].mask = 0xFFFF;
+ stack[ptr].conflictCount = 0;
+ ptr++;
+/* } */
+
+ /* Index of the top of the stack */
+ return ptr;
+}
+
+/*
+ Start resolving the conflict: the stack is primed to the top-most valid
+ layer on the stack. Call this layer n. Layer n has a conflict count of c.
+ This means layers [ n - c, ..., n ]
+ */
+int resolveConflict(struct RE_faceField* stack, int ptr, float x, float y) {
+#ifdef RE_FULL_SAFETY
+ char* fname = "resolveConflicts";
+#endif
+ int face;
+ int layer;
+ float dx, dy;
+ float xs = 0.0;
+ float ys = 0.0; /* coordinates for the render-spot */
+ int i;
+
+ for(i = 0; i< osaNr; i++) { /* per bin, buffer all faces */
+ dx = jit[i][0];
+ dy = jit[i][1];
+ xs = (float)x + dx;
+ ys = (float)y + dy;
+
+ face = 0; /* only counts covering faces ------------------- */
+ layer = 0; /* counts all faces ----------------------------- */
+
+ while (layer < stack[ptr].conflictCount) {
+ if ( (1<<i) & stack[ptr - layer].mask) {
+ VR_cbuf[face][0] =
+ calcDepth(xs, ys,
+ stack[ptr - layer].data,
+ stack[ptr - layer].faceType);
+ VR_cbuf[face][1] = ptr - layer;
+ face++;
+ }
+ layer++;
+ }
+ qsort(VR_cbuf, face, sizeof(int)*2, vergzvlak);
+ for(layer = 0; layer < face; layer++) {
+ blendOverFloat(stack[VR_cbuf[layer][1]].faceType, /* type */
+ sampcol + (4 * i), /* dest */
+ stack[VR_cbuf[layer][1]].colour, /* src */
+ stack[VR_cbuf[layer][1]].data); /* data */
+ }
+ }
+
+ /* The number of layers that were handled. This is how many layers the */
+ /* top-level algorithm needs to skip. */
+ return stack[ptr].conflictCount;
+}
+
+/* The colour stack is blended down in a pretty straight-forward manner, or */
+/* a part of the stack is re-evaluated to resolve the conflict. */
+/* About 25-30% of rendering time is eaten here! */
+void integrateStack(struct RE_faceField* stack, int ptr,
+ float x,
+ float y,
+ int osaNr) {
+ /* sample the colour stack: back to front ---------------------------- */
+ /* is there a possible way to ignore alpha? this would save 25% work */
+ ptr--;
+ /* Little different now: let ptr point to the topmost valid face.*/
+ while (ptr >= 0) {
+ if (stack[ptr].conflictCount == 0) {
+ /*
+ No conflict: sample one colour into multiple bins
+ */
+ blendOverFloatRow(stack[ptr].faceType,
+ sampcol,
+ stack[ptr].colour,
+ stack[ptr].data,
+ stack[ptr].mask,
+ osaNr);
+ ptr--;
+ } else {
+ /*
+ Recalc all z-values, and integrate per sub-pixel.
+ */
+ ptr -= resolveConflict(stack, ptr, x, y);
+ }
+ }
+
+ /* Done sampling. Now we still need to fill in pixels that were not */
+ /* covered at all It seems strange that we have to check for empty alpha */
+ /* but somehow this is necessary. Check out the cover condition :).... */
+
+ /* It is important that we find a more efficient algorithm here, because */
+ /* this little loop eats _lots_ of cycles. */
+
+ /* Should be integrated in the rest of the rendering... */
+
+ if((R.flag & R_LAMPHALO)
+ /*&&
+ ( VR_covered < ((1 << osaNr) - 1 ) )*/
+ ) {
+ float halocol[4];
+ int i;
+ renderSpotHaloPixel(x, y, halocol);
+ /* test seems to be wrong? */
+ if (halocol[3] > RE_EMPTY_COLOUR_FLOAT) {
+ for (i = 0; i < osaNr; i++) {
+ /* here's a pinch: if the pixel was only covered by a halo, */
+ /* we still need to fill spothalo. How do we detect this? */
+ if (!(VR_covered & (1 << i)))
+ /* maybe a copy is enough here... */
+ addAlphaOverFloat(sampcol + (4 * i), halocol);
+ }
+ }
+ }
+}
+
+/**
+ * New approach: sample substacks. Each substack is first copied into
+ * a stack buffer, and then blended down.
+ * */
+void integratePerSubStack(struct RE_faceField* stack,
+ int ptr,
+ float x,
+ float y,
+ int osaNr) {
+ int i = 0;
+ int j = 0;
+ int k = 0;
+ int l = 0;
+ int filterMask = 0;
+ /* next step would be to improve on the substack, I guess */
+ int subStack[RE_MAX_FACES_PER_PIXEL + 1];
+ float colSubStack[4 * (RE_MAX_FACES_PER_PIXEL + 1)];
+ int subStackPtr = 0;
+ int subStackSize = 0;
+ float xs, ys;
+
+
+ while (i < osaNr) {
+ xs = x + jit[i][0];
+ ys = y + jit[i][1];
+
+ /*
+ * 1. Copy all relevant faces. Mind that stack is built from
+ * low index = low z to high index =high z. The sub-stack is
+ * exactly the other way around! (low index = high z)
+ */
+ filterMask = (1 << i);
+ subStackPtr = 0;
+ j = ptr - 1; /* the topmost valid face */
+ while (j >= 0) {
+ if (stack[j].conflictCount) {
+ /* Conflict: we sort the faces for distance right
+ * away. We could adapt conflict count, and adjust the
+ * stack later on, but that's really doing too much,
+ * too complicated. This is just fine.
+ * */
+ k = 0;
+ l = 0;
+ /* check whether the face intersects, and if so,
+ * stores depth */
+ while (k < stack[j].conflictCount) {
+ if (stack[j - k].mask & filterMask) {
+ VR_cbuf[l][0] = calcDepth(xs, ys,
+ stack[j - k].data,
+ stack[j - k].faceType);
+ VR_cbuf[l][1] = j - k;
+ l++;
+ }
+ k++;
+ }
+ /* VR_cbuf now contains l pairs (distance, stackindex) */
+ qsort(VR_cbuf, l, sizeof(int)*2, vergzvlak);
+ /*
+ * Now we put the sorted indices on the
+ * substack. qsort delivers low index = low z, which
+ * is the right wrong order for the substack */
+ k = 0;
+ while (k < l) {
+ subStack[subStackPtr] = VR_cbuf[k][1];
+ cpFloatColV(stack[VR_cbuf[k][1]].colour, &colSubStack[4*subStackPtr]);
+ subStackPtr++;
+ k++;
+ }
+
+ j -= stack[j].conflictCount;
+ } else {
+ /* no conflict */
+ if (stack[j].mask & filterMask) {
+ subStack[subStackPtr] = j;
+ cpFloatColV(stack[j].colour, &colSubStack[4*subStackPtr]);
+ subStackPtr++;
+ }
+ j--;
+ }
+ }
+ subStackSize = subStackPtr;
+
+ /* 2. Operations on the faces can go here for now. I might
+ * want to mix this code with the blending. Currently, I only
+ * handle env/ztra faces. It's a dirty patch now...*/
+ subStackPtr = subStackSize - 1;
+ while (subStackPtr >= 0) {
+ /* we can make a general meachanism here for operations */
+ if (stack[subStack[subStackPtr]].faceType == RE_POLY){
+ VlakRen* vlr = (VlakRen*) stack[subStack[subStackPtr]].data;
+ if (vlr->mat) {
+ /* ENV faces */
+ if (vlr->mat->mode & MA_ENV) {
+ int m;
+ colSubStack[4*subStackPtr] = 0.0;
+ colSubStack[(4*subStackPtr) + 1] = 0.0;
+ colSubStack[(4*subStackPtr) + 2] = 0.0;
+ colSubStack[(4*subStackPtr) + 3] = 0.0;
+ m = subStackPtr - 1;
+ while (m >= 0) {
+ if (stack[subStack[m]].faceType != RE_SKY) {
+ colSubStack[4*m] = 0.0;
+ colSubStack[(4*m) + 1] = 0.0;
+ colSubStack[(4*m) + 2] = 0.0;
+ colSubStack[(4*m) + 3] = 0.0;
+ }
+ m--;
+ }
+ }
+ /* ZTRA faces */
+ else if (!(vlr->mat->mode & MA_ZTRA)) {
+ int m;
+ m = subStackPtr - 1;
+ while (m >= 0) {
+ if (stack[subStack[m]].faceType != RE_SKY) {
+ colSubStack[4*m] = 0.0;
+ colSubStack[(4*m) + 1] = 0.0;
+ colSubStack[(4*m) + 2] = 0.0;
+ colSubStack[(4*m) + 3] = 0.0;
+ }
+ m--;
+ }
+ }
+ }
+ }
+ subStackPtr--;
+ }
+
+ /* 3. blend down */
+ subStackPtr = 0;
+ while( subStackPtr < subStackSize ) {
+ blendOverFloat(stack[subStack[subStackPtr]].faceType, /* type */
+ sampcol + (4 * i), /* dest */
+ &colSubStack[4 * subStackPtr],
+ stack[subStack[subStackPtr]].data); /* data */
+ subStackPtr++;
+ }
+
+ i++;
+ }
+}
+
+
+
+/* ------------------------------------------------------------------------- */
+/* Rendering: per line */
+/* */
+/* For each pixel in this line, we render as follows: */
+/* a. Count the number of objects buffered for this pixel, and sort on z */
+/* ------- Result is left in zrow */
+/* b. Shade the pixel: */
+/* 1. From front to back: calculate the colour for this object */
+/* 2. Blend this colour in with the already calculated colour */
+/* Repeat 1. and 2. until no faces remain. */
+/* For each pixel, a face is only rendered once, even if it is */
+/* jittered. All subpixels get the colour of the weighted centre */
+/* of the jitter-positions this face covers. */
+/* ------- Result is left in sampcol[] */
+/* c. Copy the result to the colour buffer */
+/* d. Do gamma-corrected blending */
+/* */
+/* zrow may need some clarification: */
+/* 0 - min. distance */
+/* 1 - face/halo index */
+/* 2 - masks */
+/* 3 - type RE_POLY or RE_HALO */
+/* 4 - max. distance */
+/* It is used to store copies of RE_APixstrExt records. These are sorted for */
+/* distance, and then used for rendering pixels. zrow might be replaced by */
+/* an RE_APixstrExt* array */
+/* - redo the numbering to something more logical */
+void renderZBufLine(int y) {
+ int zrow[RE_MAX_FACES_PER_PIXEL][RE_PIXELFIELDSIZE];
+ RE_APixstrExt *ap; /* iterator for the face-lists */
+ int apteller;
+ int x; /* pixel counter */
+ RE_COLBUFTYPE *colbuf; /* pointer into the line buffer */
+ RE_COLBUFTYPE *j = NULL; /* generic pixel pointer */
+ int i; /* yet another counter */
+ int stackDepth; /* faces-behind-this-pixel counter */
+ struct RE_faceField RE_OSAstack[RE_MAX_FACES_PER_PIXEL + 1];
+ int RE_OSAstack_ptr; /* Points to the lowest empty field. The indexed */
+ /* field is NOT readable. */
+
+ /* Prepare buffers and iterators */
+ colbuf = AColourBuffer;
+ eraseColBuf(AColourBuffer);
+ ap = APixbufExt + (zBufferWidth * (y - Aminy));
+ apteller = (zBufferWidth * (y - Aminy));
+
+ /* Rendering: give the right colour to this pixel (shade it) */
+ for( x = 0; x < bufferWidth; x++, ap++, colbuf+=4) {
+ if(ap->t[0]) {
+ /* reset sample collector */
+ j = sampcol;
+ for(i = 0; i < osaNr; i++, j+=4) {
+ j[0] = RE_ZERO_COLOUR_FLOAT; j[1] = RE_ZERO_COLOUR_FLOAT;
+ j[2] = RE_ZERO_COLOUR_FLOAT; j[3] = RE_ZERO_COLOUR_FLOAT;
+ };
+
+ /* a. count and sort number of faces */
+ stackDepth = countAndSortPixelFaces(zrow, ap);
+
+ /* b,c. oversample all subpixels, then integrate */
+ RE_OSAstack_ptr = 0;
+ RE_OSAstack_ptr = composeStack(zrow,
+ RE_OSAstack, RE_OSAstack_ptr,
+ stackDepth, x, y, osaNr);
+/* #ifdef RE_OLD_INTEGRATION */
+/* printf("Performing old integration\n"); */
+/* integrateStack(RE_OSAstack, RE_OSAstack_ptr, */
+/* x, y, osaNr); */
+/* #endif */
+/* #ifndef RE_OLD_INTEGRATION */
+/* printf("Performing new integration\n"); */
+ integratePerSubStack(RE_OSAstack, RE_OSAstack_ptr,
+ x, y, osaNr);
+/* #endif */
+
+ /* d. Gamma corrected blending */
+ sampleFloatColV2FloatColV(sampcol, colbuf, osaNr);
+ } else {
+ /* Remember to do things back-to-front! */
+
+ /* This is a bit dirty. Depending on sky-mode, the pixel is */
+ /* blended in differently. */
+ renderSkyPixelFloat(x, y);
+ cpFloatColV(collector, colbuf);
+
+ /* Spothalos are part of the normal pixelshader, so for covered */
+ /* pixels they are handled ok. They are 'normally' alpha blended */
+ /* onto the existing colour in the collector. */
+ if(R.flag & R_LAMPHALO) {
+ renderSpotHaloPixel(x, y, collector);
+ }
+ addAlphaOverFloat(colbuf, collector);
+ }
+ } /* End of pixel loop */
+
+} /* End of void renderZBufLine(int y) */
+
+
+/* ------------------------------------------------------------------------- */
+
+int fillZBufDistances()
+{
+ int keepLooping = 1;
+
+ keepLooping = zBufferAllFaces(); /* Solid and transparent faces*/
+ keepLooping = zBufferAllHalos() && keepLooping; /* ...and halos*/
+ return keepLooping;
+
+} /* End of void fillZBufDistances() */
+
+/* ------------------------------------------------------------------------- */
+/* Transparent faces and the 'Azvoordeel' */
+/* A transparent face can get a z-offset, which is a */
+/* way of pretending the face is a bit closer than it */
+/* actually is. This is used in animations, when faces */
+/* that are used to glue on animated characters, items, */
+/* et. need their shadows to be drawn on top of the */
+/* objects they stand on. The Azvoordeel is added to */
+/* the calculated z-coordinate in the buffer-fill */
+/* procedures. */
+
+/* static int RE_treat_face_as_opaque; */
+
+int zBufferAllFaces(void)
+{
+ int keepLooping = 1;
+ int faceCounter; /* counter for face number */
+ float vec[3], hoco[4], mul, zval, fval;
+ Material *ma=0;
+
+ faceCounter = 0;
+
+/* printf("Going to buffer faces:\n"); */
+/* printf("\tfirst pass:\n"); */
+
+/* RE_treat_face_as_opaque = 1; */
+
+ while ( (faceCounter < R.totvlak) && keepLooping) {
+ if((faceCounter & 255)==0) { Zvlr= R.blovl[faceCounter>>8]; }
+ else Zvlr++;
+
+ ma= Zvlr->mat;
+
+ /* VERY dangerous construction... zoffs is set by a slide in the ui */
+ /* so it should be safe... */
+ if((ma->mode & (MA_ZTRA)) && (ma->zoffs != 0.0)) {
+ mul= 0x7FFFFFFF;
+ zval= mul*(1.0+Zvlr->v1->ho[2]/Zvlr->v1->ho[3]);
+
+ VECCOPY(vec, Zvlr->v1->co);
+ /* z is negatief, wordt anders geclipt */
+ vec[2]-= ma->zoffs;
+ RE_projectverto(vec, hoco); /* vec onto hoco */
+ fval= mul*(1.0+hoco[2]/hoco[3]);
+
+ Azvoordeel= (int) fabs(zval - fval );
+ } else {
+ Azvoordeel= 0;
+ }
+ /* face number is used in the fill functions */
+ Zvlnr = faceCounter + 1;
+
+ if(Zvlr->flag & R_VISIBLE) { /* might test for this sooner... */
+
+ if(ma->mode & (MA_WIRE)) zbufclipwire(Zvlr);
+ else {
+ zbufclip(Zvlr->v1->ho, Zvlr->v2->ho, Zvlr->v3->ho,
+ Zvlr->v1->clip, Zvlr->v2->clip, Zvlr->v3->clip);
+ if(Zvlr->v4) {
+ Zvlnr+= 0x800000; /* in a sense, the 'adjoint' face */
+ zbufclip(Zvlr->v1->ho, Zvlr->v3->ho, Zvlr->v4->ho,
+ Zvlr->v1->clip, Zvlr->v3->clip, Zvlr->v4->clip);
+ }
+ }
+ }
+ if(RE_local_test_break()) keepLooping = 0;
+ faceCounter++;
+ }
+
+ return keepLooping;
+} /* End of int zBufferAllFaces(void) */
+
+/* ------------------------------------------------------------------------- */
+/* We cheat a little here: we only fill the halo on the first pass, and we */
+/* set a full complement of mask flags. This can be done because we consider */
+/* halos to be flat (billboards), so we do not have to correct the z range */
+/* every time we insert a halo. Also, halos fall off to zero at the edges, */
+/* so we can safely render them in pixels where they do not exist. */
+int zBufferAllHalos(void)
+{
+ HaloRen *har = NULL;
+ unsigned int haloCounter = 0;
+ int dist = 0;
+ int keepLooping = 1;
+ short miny = 0, maxy = 0, minx = 0, maxx = 0;
+ short ycount = 0, xcount = 0;
+ RE_APixstrExt *ap, *apoffset;
+ int mask; /* jitter mask */
+
+ if (!Zsample)
+ {
+ mask = (1 << osaNr) - 1 ; /* Fill all samples together */
+
+ while ( (haloCounter < R.tothalo) && keepLooping) {
+ if((haloCounter & 255)==0) har= R.bloha[haloCounter>>8];
+ else har++;
+
+ /* Halos are sometimes wrongly kicked out of the box they belong */
+ /* in... */
+
+ /* Only buffer the current alpha buffer contents!!! The line */
+ /* indices have already been clipped to picture size. */
+ minx = floor(har->xs - har->rad) - 1; /* assume min =< max is true*/
+ if (minx < 0 ) minx = 0;
+ maxx = ceil(har->xs + har->rad ) + 1;
+ /* Do the extra -1 because of the +1 later on. I guess halos might */
+ /* have to start one pixel sooner? Or maybe the lower clip should */
+ /* be adjusted */
+ if (maxx >= zBufferWidth - 1) maxx = zBufferWidth - 2;
+
+ miny = har->miny;
+ if (miny < Aminy) miny = Aminy;
+ maxy = har->maxy;
+ if (maxy > Amaxy) maxy = Amaxy;
+
+ if ( (minx <= maxx) && (miny <= maxy)) {
+ /* distance to this halo? */
+ dist = har->zBufDist /* * R.ycor */;
+ /* strange that the ycor influences the z coordinate ..*/
+ ycount = miny;
+ while (ycount <= maxy) {
+ apoffset = APixbufExt + (zBufferWidth * (ycount - Aminy));
+ ap = apoffset + minx;
+ xcount = minx;
+ while (xcount <= maxx) {
+ insertFlatObjectNoOsa(ap, haloCounter, RE_HALO, dist, mask);
+ xcount++;
+ ap++;
+ }
+ ycount++;
+ }
+ }
+ if(RE_local_test_break()) keepLooping = 0;
+ haloCounter++;
+ }
+ }
+
+ return keepLooping;
+} /* end of int zbufferAllHalos(void) */
+
+/* ------------------------------------------------------------------------- */
+void zBufferFillHalo(void)
+{
+ /* so far, intentionally empty */
+} /* end of void zBufferFillHalo(void) */
+
+/* ------------------------------------------------------------------------- */
+void zBufferFillFace(float *v1, float *v2, float *v3)
+{
+ /* Coordinates of the vertices are specified in ZCS */
+ int apteller, apoffsetteller;
+ double z0; /* used as temp var*/
+ double xx1;
+ double zxd,zyd,zy0, tmp;
+ float *minv,*maxv,*midv;
+ register int zverg,zvlak,x;
+ int my0,my2,sn1,sn2,rectx,zd;
+ int y,omsl,xs0,xs1,xs2,xs3, dx0,dx1,dx2, mask;
+
+ /* These used to be doubles. We may want to change them back if the */
+ /* loss of accuracy proves to be a problem? There does not seem to be */
+ /* any performance issues here, so I'll just keep the doubles. */
+ /* float vec0[3], vec1[3], vec2[3]; */
+ double vec0[3], vec1[3], vec2[3];
+
+ /* MIN MAX */
+ /* sort vertices for min mid max y value */
+ if(v1[1]<v2[1]) {
+ if(v2[1]<v3[1]) { minv=v1; midv=v2; maxv=v3;}
+ else if(v1[1]<v3[1]) { minv=v1; midv=v3; maxv=v2;}
+ else { minv=v3; midv=v1; maxv=v2;}
+ }
+ else {
+ if(v1[1]<v3[1]) { minv=v2; midv=v1; maxv=v3;}
+ else if(v2[1]<v3[1]) { minv=v2; midv=v3; maxv=v1;}
+ else { minv=v3; midv=v2; maxv=v1;}
+ }
+
+ if(minv[1] == maxv[1]) return; /* beveiliging 'nul' grote vlakken */
+
+ my0 = ceil(minv[1]);
+ my2 = floor(maxv[1]);
+ omsl = floor(midv[1]);
+
+ /* outside the current z buffer slice: clip whole face */
+ if( (my2 < Aminy) || (my0 > Amaxy)) return;
+
+ if(my0<Aminy) my0= Aminy;
+
+ /* EDGES : DE LANGSTE */
+ xx1= maxv[1]-minv[1];
+ if(xx1>2.0/65536.0) {
+ z0= (maxv[0]-minv[0])/xx1;
+
+ tmp= (-65536.0*z0);
+ dx0= CLAMPIS(tmp, INT_MIN, INT_MAX);
+
+ tmp= 65536.0*(z0*(my2-minv[1])+minv[0]);
+ xs0= CLAMPIS(tmp, INT_MIN, INT_MAX);
+ }
+ else {
+ dx0= 0;
+ xs0= 65536.0*(MIN2(minv[0],maxv[0]));
+ }
+ /* EDGES : DE BOVENSTE */
+ xx1= maxv[1]-midv[1];
+ if(xx1>2.0/65536.0) {
+ z0= (maxv[0]-midv[0])/xx1;
+
+ tmp= (-65536.0*z0);
+ dx1= CLAMPIS(tmp, INT_MIN, INT_MAX);
+
+ tmp= 65536.0*(z0*(my2-midv[1])+midv[0]);
+ xs1= CLAMPIS(tmp, INT_MIN, INT_MAX);
+ }
+ else {
+ dx1= 0;
+ xs1= 65536.0*(MIN2(midv[0],maxv[0]));
+ }
+ /* EDGES : DE ONDERSTE */
+ xx1= midv[1]-minv[1];
+ if(xx1>2.0/65536.0) {
+ z0= (midv[0]-minv[0])/xx1;
+
+ tmp= (-65536.0*z0);
+ dx2= CLAMPIS(tmp, INT_MIN, INT_MAX);
+
+ tmp= 65536.0*(z0*(omsl-minv[1])+minv[0]);
+ xs2= CLAMPIS(tmp, INT_MIN, INT_MAX);
+ }
+ else {
+ dx2= 0;
+ xs2= 65536.0*(MIN2(minv[0],midv[0]));
+ }
+
+ /* ZBUF DX DY */
+ /* xyz_1 = v_1 - v_2 */
+ MTC_diff3DFF(vec1, v1, v2);
+ /* xyz_2 = v_2 - v_3 */
+ MTC_diff3DFF(vec2, v2, v3);
+ /* xyz_0 = xyz_1 cross xyz_2 */
+ MTC_cross3Double(vec0, vec1, vec2);
+
+ /* cross product of two of the sides is 0 => this face is too small */
+ if(vec0[2]==0.0) return;
+
+ if(midv[1] == maxv[1]) omsl= my2;
+ if(omsl < Aminy) omsl= Aminy-1; /* dan neemt ie de eerste lus helemaal */
+
+ while (my2 > Amaxy) { /* my2 kan groter zijn */
+ xs0+=dx0;
+ if (my2<=omsl) {
+ xs2+= dx2;
+ }
+ else{
+ xs1+= dx1;
+ }
+ my2--;
+ }
+
+ xx1= (vec0[0]*v1[0]+vec0[1]*v1[1])/vec0[2]+v1[2];
+
+ zxd= -vec0[0]/vec0[2];
+ zyd= -vec0[1]/vec0[2];
+ zy0= my2*zyd+xx1;
+ zd= (int)CLAMPIS(zxd, INT_MIN, INT_MAX);
+
+ /* start-ofset in rect */
+ /* rectx= R.rectx; */
+ /* I suspect this var needs very careful setting... When edge rendering */
+ /* is on, this is strange */
+ rectx = zBufferWidth;
+ apoffsetteller = rectx*(my2-Aminy);
+
+ mask= 1<<Zsample;
+ zvlak= Zvlnr;
+
+ xs3= 0; /* flag */
+ if(dx0>dx1) {
+ MTC_swapInt(&xs0, &xs1);
+ MTC_swapInt(&dx0, &dx1);
+ xs3= 1; /* flag */
+
+ }
+
+ for(y=my2;y>omsl;y--) {
+
+ sn1= xs0>>16;
+ xs0+= dx0;
+
+ sn2= xs1>>16;
+ xs1+= dx1;
+
+ sn1++;
+
+ if(sn2>=rectx) sn2= rectx-1;
+ if(sn1<0) sn1= 0;
+ zverg= (int) CLAMPIS((sn1*zxd+zy0), INT_MIN, INT_MAX);
+ apteller = apoffsetteller + sn1;
+ x= sn2-sn1;
+
+ zverg-= Azvoordeel;
+
+ while(x>=0) {
+ insertObject(apteller, /* RE_treat_face_as_opaque, */ Zvlnr, RE_POLY, zverg, mask);
+ zverg+= zd;
+ apteller++;
+ x--;
+ }
+ zy0-= zyd;
+ apoffsetteller -= rectx;
+ }
+
+ if(xs3) {
+ xs0= xs1;
+ dx0= dx1;
+ }
+ if(xs0>xs2) {
+ xs3= xs0;
+ xs0= xs2;
+ xs2= xs3;
+ xs3= dx0;
+ dx0= dx2;
+ dx2= xs3;
+ }
+
+ for(; y>=my0; y--) {
+
+ sn1= xs0>>16;
+ xs0+= dx0;
+
+ sn2= xs2>>16;
+ xs2+= dx2;
+
+ sn1++;
+
+ if(sn2>=rectx) sn2= rectx-1;
+ if(sn1<0) sn1= 0;
+ zverg= (int) CLAMPIS((sn1*zxd+zy0), INT_MIN, INT_MAX);
+ apteller = apoffsetteller + sn1;
+ x= sn2-sn1;
+
+ zverg-= Azvoordeel;
+
+ while(x>=0) {
+ insertObject(apteller, /* RE_treat_face_as_opaque, */ Zvlnr, RE_POLY, zverg, mask);
+ zverg+= zd;
+ apteller++;
+ x--;
+ }
+
+ zy0-=zyd;
+ apoffsetteller -= rectx;
+ }
+} /* end of void zBufferFillFace(float *v1, float *v2, float *v3) */
+
+/* ------------------------------------------------------------------------- */
+
+void zBufferFillEdge(float *vec1, float *vec2)
+{
+ int apteller;
+ int start, end, x, y, oldx, oldy, ofs;
+ int dz, vergz, mask;
+ float dx, dy;
+ float v1[3], v2[3];
+
+ dx= vec2[0]-vec1[0];
+ dy= vec2[1]-vec1[1];
+
+ if(fabs(dx) > fabs(dy)) {
+
+ /* alle lijnen van links naar rechts */
+ if(vec1[0]<vec2[0]) {
+ VECCOPY(v1, vec1);
+ VECCOPY(v2, vec2);
+ }
+ else {
+ VECCOPY(v2, vec1);
+ VECCOPY(v1, vec2);
+ dx= -dx; dy= -dy;
+ }
+
+ start= floor(v1[0]);
+ end= start+floor(dx);
+ if(end >= zBufferWidth) end = zBufferWidth - 1;
+
+ oldy= floor(v1[1]);
+ dy/= dx;
+
+ vergz= v1[2];
+ vergz-= Azvoordeel;
+ dz= (v2[2]-v1[2])/dx;
+
+ apteller = zBufferWidth*(oldy-Aminy) +start;
+ mask = 1<<Zsample;
+
+ if(dy<0) ofs= -zBufferWidth;
+ else ofs= zBufferWidth;
+
+ for(x= start; x<=end; x++, /* ap++, */ apteller++) {
+
+ y= floor(v1[1]);
+ if(y!=oldy) {
+ oldy= y;
+ apteller += ofs;
+ }
+
+ if(x>=0 && y>=Aminy && y<=Amaxy) {
+ insertObject(apteller, /* RE_treat_face_as_opaque, */ Zvlnr, RE_POLY, vergz, mask);
+ }
+
+ v1[1]+= dy;
+ vergz+= dz;
+ }
+ }
+ else {
+
+ /* alle lijnen van onder naar boven */
+ if(vec1[1]<vec2[1]) {
+ VECCOPY(v1, vec1);
+ VECCOPY(v2, vec2);
+ }
+ else {
+ VECCOPY(v2, vec1);
+ VECCOPY(v1, vec2);
+ dx= -dx; dy= -dy;
+ }
+
+ start= floor(v1[1]);
+ end= start+floor(dy);
+
+ if(start>Amaxy || end<Aminy) return;
+
+ if(end>Amaxy) end= Amaxy;
+
+ oldx= floor(v1[0]);
+ dx/= dy;
+
+ vergz= v1[2];
+ vergz-= Azvoordeel;
+ dz= (v2[2]-v1[2])/dy;
+
+ apteller = zBufferWidth*(start-Aminy) +oldx;
+
+ mask= 1<<Zsample;
+
+ if(dx<0) ofs= -1;
+ else ofs= 1;
+
+ for(y= start; y<=end; y++, apteller += zBufferWidth) {
+
+ x= floor(v1[0]);
+ if(x!=oldx) {
+ oldx= x;
+ apteller += ofs;
+ }
+
+ if(x>=0 && y>=Aminy && (x < zBufferWidth)) {
+ insertObject(apteller, /* RE_treat_face_as_opaque, */ Zvlnr, RE_POLY, vergz, mask);
+ }
+
+ v1[0]+= dx;
+ vergz+= dz;
+ }
+ }
+} /* End of void zBufferFillEdge(float *vec1, float *vec2) */
+
+
+/* ------------------------------------------------------------------------- */
+/* Colour buffer related: */
+/* This transforms the 4 inputvalues RE_COLBUFTYPE to a new value */
+/* It expects the values R.r.postigamma, R.r.postmul and R.r.postadd. */
+/* This is the standard transformation, more elaborate tools are for later. */
+/* ------------------------------------------------------------------------- */
+void std_transFloatColV2CharColV( RE_COLBUFTYPE *buf, char *target)
+{
+ float fval;
+
+ /* alpha */
+ if(buf[3]<=0.0) target[3]= 0;
+ else if(buf[3]>1.0) target[3]= 255;
+ else target[3]= 255.0*buf[3];
+
+ if(R.r.postgamma==1.0) {
+ /* r */
+ fval= R.r.postmul*buf[0] + R.r.postadd;
+ if(fval<=0.0) target[0]= 0;
+ else if(fval>1.0) target[0]= 255;
+ else target[0]= 255.0*fval;
+
+ /* g */
+ fval= R.r.postmul*buf[1] + R.r.postadd;
+ if(fval<=0.0) target[1]= 0;
+ else if(fval>1.0) target[1]= 255;
+ else target[1]= 255.0*fval;
+
+ /* b */
+ fval= R.r.postmul*buf[2] + R.r.postadd;
+ if(fval<=0.0) target[2]= 0;
+ else if(fval>1.0) target[2]= 255;
+ else target[2]= 255.0*fval;
+
+ }
+ else {
+ /* putting the postmul within the pow() gives an
+ * easier control for the user, values from 1.0-2.0
+ * are relevant then
+ */
+
+
+ /* r */
+ fval= pow(R.r.postmul*buf[0], R.r.postigamma) + R.r.postadd;
+ if(fval<=0.0) target[0]= 0;
+ else if(fval>1.0) target[0]= 255;
+ else target[0]= 255.0*fval;
+
+ /* g */
+ fval=pow( R.r.postmul*buf[1], R.r.postigamma) + R.r.postadd;
+ if(fval<=0.0) target[1]= 0;
+ else if(fval>1.0) target[1]= 255;
+ else target[1]= 255.0*fval;
+
+ /* b */
+ fval= pow(R.r.postmul*buf[2], R.r.postigamma) + R.r.postadd;
+ if(fval<=0.0) target[2]= 0;
+ else if(fval>1.0) target[2]= 255;
+ else target[2]= 255.0*fval;
+ }
+
+} /* end of void std_transFloatColV2CharColV( RE_COLBUFTYPE *buf, uchar *target) */
+
+
+/* ----------------------------------------------------------------------------
+
+ Colour buffer related:
+
+ The colour buffer is a buffer of a single screen line. It contains
+ four fields of type RE_COLBUFTYPE per pixel.
+
+ We can do several post-process steps. I would prefer to move them outside
+ the render module later on, but it's ok to leave it here for now. For the
+ time being, we have:
+ - post-process function
+ Does some operations with the colours.
+ - Multiply with some factor
+ - Add constant offset
+ - Apply extra gamma correction (seems weird...)
+ - key-alpha correction
+ Key alpha means 'un-applying' the alpha. For fully covered pixels, this
+ operation has no effect.
+
+---------------------------------------------------------------------------- */
+void transferColourBufferToOutput(int y)
+{
+ /* Copy the contents of AColourBuffer to R.rectot + y * R.rectx */
+ int x = 0;
+ RE_COLBUFTYPE *buf = AColourBuffer;
+ char *target = (char*) (R.rectot + (y * imageWidth));
+
+#ifdef RE_FULL_SAFETY
+ /* since the R.rectot always has size imageWidth * imageHeight, this */
+ /* check is possible. I may want to check this per assignment later on. */
+ if ( (y < 0) || ((y > (imageHeight - 1) ))) {
+ char fname[] = "transferColourBufferToOutput";
+ RE_error_int(RE_WRITE_OUTSIDE_COLOUR_BUFFER, fname, y);
+ return;
+ }
+#endif
+
+ /* Copy the first <imageWidth> pixels. We can do some more clipping on */
+ /* the z buffer, I think. */
+ while (x < imageWidth) {
+
+ std_transFloatColV2CharColV(buf, target);
+
+ /* old function was: leave it for test */
+/* cpFloatColV2CharColV(buf, target); */
+
+ /*
+ Key-alpha mode:
+ Need to un-apply alpha if alpha is non-full. For full alpha,
+ the operation doesn't have effect. Do this after the post-
+ processing, so we can still use the benefits of that.
+
+ */
+
+ if (getSkyBlendingMode() == RE_ALPHA_KEY) {
+ applyKeyAlphaCharCol(target);
+ }
+
+ target+=4;
+ buf+=4;
+ x++;
+ }
+} /* end of void transferColourBufferToOutput(int y) */
+
+/* ------------------------------------------------------------------------- */
+
+void eraseColBuf(RE_COLBUFTYPE *buf) {
+ /* By definition, the buffer's length is 4 * R.rectx items */
+ int i = 0;
+/* while (i < 4 * R.rectx) { */
+ while (i < 4 * bufferWidth) {
+ *buf = RE_ZERO_COLOUR_FLOAT;
+ buf++; i++;
+ }
+} /* End of void eraseColBuf(RE_COLBUFTYPE *buf) */
+
+/* ------------------------------------------------------------------------- */
+
+int calcDepth(float x, float y, void* data, int type)
+{
+#ifdef RE_FULL_SAFETY
+ char fname[] = "calcDepth";
+ if (data == NULL) {
+ RE_error(RE_BAD_DATA_POINTER, fname);
+ return 0;
+ }
+#endif
+
+ if (type & RE_POLY) {
+ VlakRen* vlr = (VlakRen*) data;
+ VertRen* v1;
+ float dvlak, deler, fac, hoco_z, hoco_w;
+ int zbuf_co;
+
+ v1 = vlr->v1;
+
+ /* vertex dot face normal: WCS */
+ dvlak= v1->co[0]*vlr->n[0]+v1->co[1]*vlr->n[1]+v1->co[2]*vlr->n[2];
+
+ /* jitter has been added to x, y ! */
+ /* view vector R.view: screen coords */
+ if( (G.special1 & G_HOLO) &&
+ ((Camera *)G.scene->camera->data)->flag & CAM_HOLO2) {
+ R.view[0]= (x+(R.xstart) + 0.5 +holoofs);
+ } else R.view[0]= (x+(R.xstart) + 0.5 );
+
+ if(R.flag & R_SEC_FIELD) {
+ if(R.r.mode & R_ODDFIELD) R.view[1]= (y + R.ystart)*R.ycor;
+ else R.view[1]= (y+R.ystart + 1.0)*R.ycor;
+ } else R.view[1]= (y+R.ystart + 0.5 )*R.ycor;
+
+
+ /* for pano, another rotation in the xz plane is needed.... */
+
+ /* this is ok, in WCS */
+ R.view[2]= -R.viewfac; /* distance to viewplane */
+
+ /* face normal dot view vector: but how can this work? */
+ deler = MTC_dot3Float(vlr->n, R.view);
+ if (deler!=0.0) fac = dvlak/deler;
+ else fac = 0.0;
+
+ /* indices are wrong.... but gives almost the right value? */
+ hoco_z = (fac*R.view[2]) * R.winmat[2][2] + R.winmat[3][2];
+ hoco_w = (fac*R.view[2]) * R.winmat[2][3] + R.winmat[3][3];
+
+ zbuf_co = 0x7FFFFFFF*(hoco_z/hoco_w);
+
+ return zbuf_co; /* z component of R.co */
+ } else if (type & RE_HALO) {
+ HaloRen* har = (HaloRen*) data;
+ return har->zBufDist;
+ }
+#ifdef RE_FULL_SAFETY
+ else RE_error(RE_BAD_FACE_TYPE, fname);
+#endif /* RE_FULL_SAFETY */
+ return 0;
+} /* end of int calcDepth(float x, float y, void* data, int type) */
+
+/* Maybe these two should be in pixelblendeing.c---------------------------- */
+
+void blendOverFloat(int type, float* dest, float* source, void* data)
+{
+#ifdef RE_FULL_SAFETY
+ char fname[] = "blendOverFloat";
+ if (data == NULL){
+ RE_error(RE_BAD_DATA_POINTER, fname);
+ return;
+ }
+#endif
+
+ if (type & RE_POLY) {
+ VlakRen *ver = (VlakRen*) data;
+ if ((ver->mat != NULL) && (ver->mat->add > RE_FACE_ADD_THRESHOLD)) {
+ char addf = (char) (ver->mat->add * 255.0);
+ addalphaAddfacFloat(dest, source, addf);
+ }
+ else
+ addAlphaOverFloat(dest, source);
+ } else if (type & RE_HALO) {
+ HaloRen *har= (HaloRen*) data;
+ addalphaAddfacFloat(dest, source, har->add);
+ } else if (type & RE_SKY) {
+ addAlphaOverFloat(dest, source);
+ }
+#ifdef RE_FULL_SAFETY
+ else RE_error(RE_BAD_FACE_TYPE, fname);
+#endif
+
+} /* end of void blendOverFloat(int , float*, float*, void*) */
+
+/* ------------------------------------------------------------------------- */
+void blendOverFloatRow(int type, float* dest, float* source,
+ void* data, int mask, int osaNr)
+{
+#ifdef RE_FULL_SAFETY
+ char* fname = "blendOverFloatRow";
+ if ((data == NULL) && ((type & RE_POLY) || (type & RE_HALO))) {
+ RE_error(RE_BAD_DATA_POINTER, fname);
+ return;
+ }
+#endif
+
+ if (type & RE_POLY) {
+ VlakRen *ver = (VlakRen*) data;
+ if ((ver->mat != NULL)
+ && (ver->mat->add > RE_FACE_ADD_THRESHOLD)) {
+ char addf = (ver->mat->add * 255.0);
+ addAddSampColF(dest, source, mask, osaNr, addf);
+ } else {
+ addOverSampColF(dest, source, mask, osaNr);
+ }
+ } else if (type & RE_HALO) {
+ HaloRen *har = (HaloRen*) data;
+ addAddSampColF(dest, source, mask, osaNr, har->add);
+ } else if (type & RE_SKY) {
+ addOverSampColF(dest, source, mask, osaNr);
+ }
+#ifdef RE_FULL_SAFETY
+ else RE_error(RE_BAD_FACE_TYPE, fname);
+#endif
+} /* end of void blendOverFloatRow(int, float*, float*, void*) */
+
+/* ------------------------------------------------------------------------- */
+
+/* eof vanillaRenderPipe.c */
diff --git a/source/blender/render/intern/source/zbuf.c b/source/blender/render/intern/source/zbuf.c
new file mode 100644
index 00000000000..295e13b8d5f
--- /dev/null
+++ b/source/blender/render/intern/source/zbuf.c
@@ -0,0 +1,2329 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/*---------------------------------------------------------------------------*/
+/* Common includes */
+/*---------------------------------------------------------------------------*/
+
+#include <math.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#include "MTC_matrixops.h"
+#include "MEM_guardedalloc.h"
+
+#include "BKE_global.h"
+
+#include "DNA_lamp_types.h"
+#include "DNA_mesh_types.h"
+
+#include "radio_types.h"
+#include "radio.h" /* needs RG, some root data for radiosity */
+
+#include "render.h"
+#include "render_intern.h"
+#include "RE_callbacks.h"
+#include "old_zbuffer_types.h"
+/* local includes */
+/* can be removed when the old renderer disappears */
+#include "rendercore.h" /* shade_pixel and count_mask */
+#include "pixelblending.h"
+#include "jitter.h"
+
+/* own includes */
+#include "zbuf.h"
+#include "zbuf_int.h"
+
+/* crud */
+#define MIN2(x,y) ( (x)<(y) ? (x) : (y) )
+/*-----------------------------------------------------------*/
+/* Globals for this file */
+/*-----------------------------------------------------------*/
+
+extern float centLut[16];
+extern char *centmask;
+
+float *vlzp[32][3], labda[3][2], vez[400], *p[40];
+
+float Zmulx; /* Half the screenwidth, in pixels. (used in render.c, */
+ /* zbuf.c) */
+float Zmuly; /* Half the screenheight, in pixels. (used in render.c,*/
+ /* zbuf.c) */
+float Zjitx; /* Jitter offset in x. When jitter is disabled, this */
+ /* should be 0.5. (used in render.c, zbuf.c) */
+float Zjity; /* Jitter offset in y. When jitter is disabled, this */
+ /* should be 0.5. (used in render.c, zbuf.c) */
+
+unsigned int Zvlnr, Zsample;
+VlakRen *Zvlr;
+void (*zbuffunc)(float *, float *, float *);
+void (*zbuflinefunc)(float *, float *);
+
+APixstr *APixbuf; /* Zbuffer: linked list of face indices */
+unsigned short *Acolrow; /* Zbuffer: colour buffer, one line high */
+int *Arectz; /* Zbuffer: distance buffer, almost obsolete */
+int Aminy; /* y value of first line in the accu buffer */
+int Amaxy; /* y value of last line in the accu buffer */
+int Azvoordeel = 0;
+APixstrMain apsmfirst;
+short apsmteller = 0;
+
+/*-----------------------------------------------------------*/
+/* Functions */
+/*-----------------------------------------------------------*/
+
+void fillrect(unsigned int *rect, int x, unsigned int y, unsigned int val)
+{
+ unsigned int len,*drect;
+
+ len= x*y;
+ drect= rect;
+ while(len>0) {
+ len--;
+ *drect= val;
+ drect++;
+ }
+}
+
+/* ************* ACCU ZBUF ************ */
+
+/*-APixstr---------------------------------------------------*/
+
+APixstr *addpsmainA()
+{
+ APixstrMain *psm;
+
+ psm= &apsmfirst;
+
+ while(psm->next) {
+ psm= psm->next;
+ }
+
+ psm->next= MEM_mallocN(sizeof(APixstrMain), "addpsmainA");
+
+ psm= psm->next;
+ psm->next=0;
+ psm->ps= MEM_callocN(4096*sizeof(APixstr),"pixstr");
+ apsmteller= 0;
+
+ return psm->ps;
+}
+
+void freepsA()
+{
+ APixstrMain *psm, *next;
+
+ psm= &apsmfirst;
+
+ while(psm) {
+ next= psm->next;
+ if(psm->ps) {
+ MEM_freeN(psm->ps);
+ psm->ps= 0;
+ }
+ if(psm!= &apsmfirst) MEM_freeN(psm);
+ psm= next;
+ }
+
+ apsmfirst.next= 0;
+ apsmfirst.ps= 0;
+ apsmteller= 0;
+}
+
+APixstr *addpsA(void)
+{
+ static APixstr *prev;
+
+ /* eerste PS maken */
+ if((apsmteller & 4095)==0) prev= addpsmainA();
+ else prev++;
+ apsmteller++;
+
+ return prev;
+}
+
+/* vult kleur in, met windowcoordinaat, van Aminy->Amaxy */
+void zbufinvulAc(float *v1, float *v2, float *v3)
+{
+ APixstr *ap, *apofs, *apn;
+ double x0,y0,z0,x1,y1,z1,x2,y2,z2,xx1;
+ double zxd,zyd,zy0, tmp;
+ float *minv,*maxv,*midv;
+ int *rz,zverg,x;
+ int my0,my2,sn1,sn2,rectx,zd,*rectzofs;
+ int y,omsl,xs0,xs1,xs2,xs3, dx0,dx1,dx2, mask;
+
+ /* MIN MAX */
+ if(v1[1]<v2[1]) {
+ if(v2[1]<v3[1]) {
+ minv=v1; midv=v2; maxv=v3;
+ }
+ else if(v1[1]<v3[1]) {
+ minv=v1; midv=v3; maxv=v2;
+ }
+ else {
+ minv=v3; midv=v1; maxv=v2;
+ }
+ }
+ else {
+ if(v1[1]<v3[1]) {
+ minv=v2; midv=v1; maxv=v3;
+ }
+ else if(v2[1]<v3[1]) {
+ minv=v2; midv=v3; maxv=v1;
+ }
+ else {
+ minv=v3; midv=v2; maxv=v1;
+ }
+ }
+
+ if(minv[1] == maxv[1]) return; /* beveiliging 'nul' grote vlakken */
+
+ my0= ceil(minv[1]);
+ my2= floor(maxv[1]);
+ omsl= floor(midv[1]);
+
+ if(my2<Aminy || my0> Amaxy) return;
+
+ if(my0<Aminy) my0= Aminy;
+
+ /* EDGES : DE LANGSTE */
+ xx1= maxv[1]-minv[1];
+ if(xx1>2.0/65536.0) {
+ z0= (maxv[0]-minv[0])/xx1;
+
+ tmp= (-65536.0*z0);
+ dx0= CLAMPIS(tmp, INT_MIN, INT_MAX);
+
+ tmp= 65536.0*(z0*(my2-minv[1])+minv[0]);
+ xs0= CLAMPIS(tmp, INT_MIN, INT_MAX);
+ }
+ else {
+ dx0= 0;
+ xs0= 65536.0*(MIN2(minv[0],maxv[0]));
+ }
+ /* EDGES : DE BOVENSTE */
+ xx1= maxv[1]-midv[1];
+ if(xx1>2.0/65536.0) {
+ z0= (maxv[0]-midv[0])/xx1;
+
+ tmp= (-65536.0*z0);
+ dx1= CLAMPIS(tmp, INT_MIN, INT_MAX);
+
+ tmp= 65536.0*(z0*(my2-midv[1])+midv[0]);
+ xs1= CLAMPIS(tmp, INT_MIN, INT_MAX);
+ }
+ else {
+ dx1= 0;
+ xs1= 65536.0*(MIN2(midv[0],maxv[0]));
+ }
+ /* EDGES : DE ONDERSTE */
+ xx1= midv[1]-minv[1];
+ if(xx1>2.0/65536.0) {
+ z0= (midv[0]-minv[0])/xx1;
+
+ tmp= (-65536.0*z0);
+ dx2= CLAMPIS(tmp, INT_MIN, INT_MAX);
+
+ tmp= 65536.0*(z0*(omsl-minv[1])+minv[0]);
+ xs2= CLAMPIS(tmp, INT_MIN, INT_MAX);
+ }
+ else {
+ dx2= 0;
+ xs2= 65536.0*(MIN2(minv[0],midv[0]));
+ }
+
+ /* ZBUF DX DY */
+ x1= v1[0]- v2[0];
+ x2= v2[0]- v3[0];
+ y1= v1[1]- v2[1];
+ y2= v2[1]- v3[1];
+ z1= v1[2]- v2[2];
+ z2= v2[2]- v3[2];
+ x0= y1*z2-z1*y2;
+ y0= z1*x2-x1*z2;
+ z0= x1*y2-y1*x2;
+ if(z0==0.0) return;
+
+ if(midv[1]==maxv[1]) omsl= my2;
+ if(omsl<Aminy) omsl= Aminy-1; /* dan neemt ie de eerste lus helemaal */
+
+ while (my2 > Amaxy) { /* my2 kan groter zijn */
+ xs0+=dx0;
+ if (my2<=omsl) {
+ xs2+= dx2;
+ }
+ else{
+ xs1+= dx1;
+ }
+ my2--;
+ }
+
+ xx1= (x0*v1[0]+y0*v1[1])/z0+v1[2];
+
+ zxd= -x0/z0;
+ zyd= -y0/z0;
+ zy0= my2*zyd+xx1;
+ zd= (int)CLAMPIS(zxd, INT_MIN, INT_MAX);
+
+ /* start-ofset in rect */
+ rectx= R.rectx;
+ rectzofs= (int *)(Arectz+rectx*(my2-Aminy));
+ apofs= (APixbuf+ rectx*(my2-Aminy));
+ mask= 1<<Zsample;
+
+ xs3= 0; /* flag */
+ if(dx0>dx1) {
+ xs3= xs0;
+ xs0= xs1;
+ xs1= xs3;
+ xs3= dx0;
+ dx0= dx1;
+ dx1= xs3;
+ xs3= 1; /* flag */
+
+ }
+
+ for(y=my2;y>omsl;y--) {
+
+ sn1= xs0>>16;
+ xs0+= dx0;
+
+ sn2= xs1>>16;
+ xs1+= dx1;
+
+ sn1++;
+
+ if(sn2>=rectx) sn2= rectx-1;
+ if(sn1<0) sn1= 0;
+ zverg= (int) CLAMPIS((sn1*zxd+zy0), INT_MIN, INT_MAX);
+ rz= rectzofs+sn1;
+ ap= apofs+sn1;
+ x= sn2-sn1;
+
+ zverg-= Azvoordeel;
+
+ while(x>=0) {
+ if(zverg< *rz) {
+ apn= ap;
+ while(apn) { /* loopunrolled */
+ if(apn->p[0]==0) {apn->p[0]= Zvlnr; apn->z[0]= zverg; apn->mask[0]= mask; break; }
+ if(apn->p[0]==Zvlnr) {apn->mask[0]|= mask; break; }
+ if(apn->p[1]==0) {apn->p[1]= Zvlnr; apn->z[1]= zverg; apn->mask[1]= mask; break; }
+ if(apn->p[1]==Zvlnr) {apn->mask[1]|= mask; break; }
+ if(apn->p[2]==0) {apn->p[2]= Zvlnr; apn->z[2]= zverg; apn->mask[2]= mask; break; }
+ if(apn->p[2]==Zvlnr) {apn->mask[2]|= mask; break; }
+ if(apn->p[3]==0) {apn->p[3]= Zvlnr; apn->z[3]= zverg; apn->mask[3]= mask; break; }
+ if(apn->p[3]==Zvlnr) {apn->mask[3]|= mask; break; }
+ if(apn->next==0) apn->next= addpsA();
+ apn= apn->next;
+ }
+ }
+ zverg+= zd;
+ rz++;
+ ap++;
+ x--;
+ }
+ zy0-= zyd;
+ rectzofs-= rectx;
+ apofs-= rectx;
+ }
+
+ if(xs3) {
+ xs0= xs1;
+ dx0= dx1;
+ }
+ if(xs0>xs2) {
+ xs3= xs0;
+ xs0= xs2;
+ xs2= xs3;
+ xs3= dx0;
+ dx0= dx2;
+ dx2= xs3;
+ }
+
+ for(; y>=my0; y--) {
+
+ sn1= xs0>>16;
+ xs0+= dx0;
+
+ sn2= xs2>>16;
+ xs2+= dx2;
+
+ sn1++;
+
+ if(sn2>=rectx) sn2= rectx-1;
+ if(sn1<0) sn1= 0;
+ zverg= (int) CLAMPIS((sn1*zxd+zy0), INT_MIN, INT_MAX);
+ rz= rectzofs+sn1;
+ ap= apofs+sn1;
+ x= sn2-sn1;
+
+ zverg-= Azvoordeel;
+
+ while(x>=0) {
+ if(zverg< *rz) {
+ apn= ap;
+ while(apn) { /* loopunrolled */
+ if(apn->p[0]==0) {apn->p[0]= Zvlnr; apn->z[0]= zverg; apn->mask[0]= mask; break; }
+ if(apn->p[0]==Zvlnr) {apn->mask[0]|= mask; break; }
+ if(apn->p[1]==0) {apn->p[1]= Zvlnr; apn->z[1]= zverg; apn->mask[1]= mask; break; }
+ if(apn->p[1]==Zvlnr) {apn->mask[1]|= mask; break; }
+ if(apn->p[2]==0) {apn->p[2]= Zvlnr; apn->z[2]= zverg; apn->mask[2]= mask; break; }
+ if(apn->p[2]==Zvlnr) {apn->mask[2]|= mask; break; }
+ if(apn->p[3]==0) {apn->p[3]= Zvlnr; apn->z[3]= zverg; apn->mask[3]= mask; break; }
+ if(apn->p[3]==Zvlnr) {apn->mask[3]|= mask; break; }
+ if(apn->next==0) apn->next= addpsA();
+ apn= apn->next;
+ }
+ }
+ zverg+= zd;
+ rz++;
+ ap++;
+ x--;
+ }
+
+ zy0-=zyd;
+ rectzofs-= rectx;
+ apofs-= rectx;
+ }
+}
+
+void zbuflineAc(float *vec1, float *vec2)
+{
+ APixstr *ap, *apn;
+ unsigned int *rectz;
+ int start, end, x, y, oldx, oldy, ofs;
+ int dz, vergz, mask;
+ float dx, dy;
+ float v1[3], v2[3];
+
+ dx= vec2[0]-vec1[0];
+ dy= vec2[1]-vec1[1];
+
+ if(fabs(dx) > fabs(dy)) {
+
+ /* alle lijnen van links naar rechts */
+ if(vec1[0]<vec2[0]) {
+ VECCOPY(v1, vec1);
+ VECCOPY(v2, vec2);
+ }
+ else {
+ VECCOPY(v2, vec1);
+ VECCOPY(v1, vec2);
+ dx= -dx; dy= -dy;
+ }
+
+ start= floor(v1[0]);
+ end= start+floor(dx);
+ if(end>=R.rectx) end= R.rectx-1;
+
+ oldy= floor(v1[1]);
+ dy/= dx;
+
+ vergz= v1[2];
+ vergz-= Azvoordeel;
+ dz= (v2[2]-v1[2])/dx;
+
+ rectz= (unsigned int *)(Arectz+R.rectx*(oldy-Aminy) +start);
+ ap= (APixbuf+ R.rectx*(oldy-Aminy) +start);
+ mask= 1<<Zsample;
+
+ if(dy<0) ofs= -R.rectx;
+ else ofs= R.rectx;
+
+ for(x= start; x<=end; x++, rectz++, ap++) {
+
+ y= floor(v1[1]);
+ if(y!=oldy) {
+ oldy= y;
+ rectz+= ofs;
+ ap+= ofs;
+ }
+
+ if(x>=0 && y>=Aminy && y<=Amaxy) {
+ if(vergz<*rectz) {
+
+ apn= ap;
+ while(apn) { /* loopunrolled */
+ if(apn->p[0]==0) {apn->p[0]= Zvlnr; apn->z[0]= vergz; apn->mask[0]= mask; break; }
+ if(apn->p[0]==Zvlnr) {apn->mask[0]|= mask; break; }
+ if(apn->p[1]==0) {apn->p[1]= Zvlnr; apn->z[1]= vergz; apn->mask[1]= mask; break; }
+ if(apn->p[1]==Zvlnr) {apn->mask[1]|= mask; break; }
+ if(apn->p[2]==0) {apn->p[2]= Zvlnr; apn->z[2]= vergz; apn->mask[2]= mask; break; }
+ if(apn->p[2]==Zvlnr) {apn->mask[2]|= mask; break; }
+ if(apn->p[3]==0) {apn->p[3]= Zvlnr; apn->z[3]= vergz; apn->mask[3]= mask; break; }
+ if(apn->p[3]==Zvlnr) {apn->mask[3]|= mask; break; }
+ if(apn->next==0) apn->next= addpsA();
+ apn= apn->next;
+ }
+
+ }
+ }
+
+ v1[1]+= dy;
+ vergz+= dz;
+ }
+ }
+ else {
+
+ /* alle lijnen van onder naar boven */
+ if(vec1[1]<vec2[1]) {
+ VECCOPY(v1, vec1);
+ VECCOPY(v2, vec2);
+ }
+ else {
+ VECCOPY(v2, vec1);
+ VECCOPY(v1, vec2);
+ dx= -dx; dy= -dy;
+ }
+
+ start= floor(v1[1]);
+ end= start+floor(dy);
+
+ if(start>Amaxy || end<Aminy) return;
+
+ if(end>Amaxy) end= Amaxy;
+
+ oldx= floor(v1[0]);
+ dx/= dy;
+
+ vergz= v1[2];
+ vergz-= Azvoordeel;
+ dz= (v2[2]-v1[2])/dy;
+
+ rectz= (unsigned int *)( Arectz+ (start-Aminy)*R.rectx+ oldx );
+ ap= (APixbuf+ R.rectx*(start-Aminy) +oldx);
+ mask= 1<<Zsample;
+
+ if(dx<0) ofs= -1;
+ else ofs= 1;
+
+ for(y= start; y<=end; y++, rectz+=R.rectx, ap+=R.rectx) {
+
+ x= floor(v1[0]);
+ if(x!=oldx) {
+ oldx= x;
+ rectz+= ofs;
+ ap+= ofs;
+ }
+
+ if(x>=0 && y>=Aminy && x<R.rectx) {
+ if(vergz<*rectz) {
+
+ apn= ap;
+ while(apn) { /* loopunrolled */
+ if(apn->p[0]==0) {apn->p[0]= Zvlnr; apn->z[0]= vergz; apn->mask[0]= mask; break; }
+ if(apn->p[0]==Zvlnr) {apn->mask[0]|= mask; break; }
+ if(apn->p[1]==0) {apn->p[1]= Zvlnr; apn->z[1]= vergz; apn->mask[1]= mask; break; }
+ if(apn->p[1]==Zvlnr) {apn->mask[1]|= mask; break; }
+ if(apn->p[2]==0) {apn->p[2]= Zvlnr; apn->z[2]= vergz; apn->mask[2]= mask; break; }
+ if(apn->p[2]==Zvlnr) {apn->mask[2]|= mask; break; }
+ if(apn->p[3]==0) {apn->p[3]= Zvlnr; apn->z[3]= vergz; apn->mask[3]= mask; break; }
+ if(apn->p[3]==Zvlnr) {apn->mask[3]|= mask; break; }
+ if(apn->next==0) apn->next= addpsA();
+ apn= apn->next;
+ }
+
+ }
+ }
+
+ v1[0]+= dx;
+ vergz+= dz;
+ }
+ }
+}
+
+
+
+/* ************* NORMAL ZBUFFER ************ */
+
+void hoco_to_zco(float *zco, float *hoco)
+{
+ float deler;
+
+ deler= hoco[3];
+ zco[0]= Zmulx*(1.0+hoco[0]/deler)+ Zjitx;
+ zco[1]= Zmuly*(1.0+hoco[1]/deler)+ Zjity;
+ zco[2]= 0x7FFFFFFF *(hoco[2]/deler);
+}
+
+void zbufline(vec1, vec2)
+float *vec1, *vec2;
+{
+ unsigned int *rectz, *rectp;
+ int start, end, x, y, oldx, oldy, ofs;
+ int dz, vergz;
+ float dx, dy;
+ float v1[3], v2[3];
+
+ dx= vec2[0]-vec1[0];
+ dy= vec2[1]-vec1[1];
+
+ if(fabs(dx) > fabs(dy)) {
+
+ /* alle lijnen van links naar rechts */
+ if(vec1[0]<vec2[0]) {
+ VECCOPY(v1, vec1);
+ VECCOPY(v2, vec2);
+ }
+ else {
+ VECCOPY(v2, vec1);
+ VECCOPY(v1, vec2);
+ dx= -dx; dy= -dy;
+ }
+
+ start= floor(v1[0]);
+ end= start+floor(dx);
+ if(end>=R.rectx) end= R.rectx-1;
+
+ oldy= floor(v1[1]);
+ dy/= dx;
+
+ vergz= v1[2];
+ dz= (v2[2]-v1[2])/dx;
+
+ rectz= R.rectz+ oldy*R.rectx+ start;
+ rectp= R.rectot+ oldy*R.rectx+ start;
+
+ if(dy<0) ofs= -R.rectx;
+ else ofs= R.rectx;
+
+ for(x= start; x<=end; x++, rectz++, rectp++) {
+
+ y= floor(v1[1]);
+ if(y!=oldy) {
+ oldy= y;
+ rectz+= ofs;
+ rectp+= ofs;
+ }
+
+ if(x>=0 && y>=0 && y<R.recty) {
+ if(vergz<*rectz) {
+ *rectz= vergz;
+ *rectp= Zvlnr;
+ }
+ }
+
+ v1[1]+= dy;
+ vergz+= dz;
+ }
+ }
+ else {
+ /* alle lijnen van onder naar boven */
+ if(vec1[1]<vec2[1]) {
+ VECCOPY(v1, vec1);
+ VECCOPY(v2, vec2);
+ }
+ else {
+ VECCOPY(v2, vec1);
+ VECCOPY(v1, vec2);
+ dx= -dx; dy= -dy;
+ }
+
+ start= floor(v1[1]);
+ end= start+floor(dy);
+
+ if(end>=R.recty) end= R.recty-1;
+
+ oldx= floor(v1[0]);
+ dx/= dy;
+
+ vergz= v1[2];
+ dz= (v2[2]-v1[2])/dy;
+
+ rectz= R.rectz+ start*R.rectx+ oldx;
+ rectp= R.rectot+ start*R.rectx+ oldx;
+
+ if(dx<0) ofs= -1;
+ else ofs= 1;
+
+ for(y= start; y<=end; y++, rectz+=R.rectx, rectp+=R.rectx) {
+
+ x= floor(v1[0]);
+ if(x!=oldx) {
+ oldx= x;
+ rectz+= ofs;
+ rectp+= ofs;
+ }
+
+ if(x>=0 && y>=0 && x<R.rectx) {
+ if(vergz<*rectz) {
+ *rectz= vergz;
+ *rectp= Zvlnr;
+ }
+ }
+
+ v1[0]+= dx;
+ vergz+= dz;
+ }
+ }
+}
+
+
+void zbufclipwire(VlakRen *vlr)
+{
+ float *f1, *f2, *f3, *f4= 0, deler;
+ int c1, c2, c3, c4, ec, and, or;
+
+ /* edgecode: 1= tekenen */
+ ec = vlr->ec;
+ if(ec==0) return;
+
+ c1= vlr->v1->clip;
+ c2= vlr->v2->clip;
+ c3= vlr->v3->clip;
+ f1= vlr->v1->ho;
+ f2= vlr->v2->ho;
+ f3= vlr->v3->ho;
+
+ if(vlr->v4) {
+ f4= vlr->v4->ho;
+ c4= vlr->v4->clip;
+
+ and= (c1 & c2 & c3 & c4);
+ or= (c1 | c2 | c3 | c4);
+ }
+ else {
+ and= (c1 & c2 & c3);
+ or= (c1 | c2 | c3);
+ }
+
+ if(or) { /* niet in midden */
+ if(and) { /* helemaal eruit */
+ return;
+ }
+ else { /* clippen */
+
+ if(ec & ME_V1V2) {
+ QUATCOPY(vez, f1);
+ QUATCOPY(vez+4, f2);
+ if( clipline(vez, vez+4)) {
+ hoco_to_zco(vez, vez);
+ hoco_to_zco(vez+4, vez+4);
+ zbuflinefunc(vez, vez+4);
+ }
+ }
+ if(ec & ME_V2V3) {
+ QUATCOPY(vez, f2);
+ QUATCOPY(vez+4, f3);
+ if( clipline(vez, vez+4)) {
+ hoco_to_zco(vez, vez);
+ hoco_to_zco(vez+4, vez+4);
+ zbuflinefunc(vez, vez+4);
+ }
+ }
+ if(vlr->v4) {
+ if(ec & ME_V3V4) {
+ QUATCOPY(vez, f3);
+ QUATCOPY(vez+4, f4);
+ if( clipline(vez, vez+4)) {
+ hoco_to_zco(vez, vez);
+ hoco_to_zco(vez+4, vez+4);
+ zbuflinefunc(vez, vez+4);
+ }
+ }
+ if(ec & ME_V4V1) {
+ QUATCOPY(vez, f4);
+ QUATCOPY(vez+4, f1);
+ if( clipline(vez, vez+4)) {
+ hoco_to_zco(vez, vez);
+ hoco_to_zco(vez+4, vez+4);
+ zbuflinefunc(vez, vez+4);
+ }
+ }
+ }
+ else {
+ if(ec & ME_V3V1) {
+ QUATCOPY(vez, f3);
+ QUATCOPY(vez+4, f1);
+ if( clipline(vez, vez+4)) {
+ hoco_to_zco(vez, vez);
+ hoco_to_zco(vez+4, vez+4);
+ zbuflinefunc(vez, vez+4);
+ }
+ }
+ }
+
+ return;
+ }
+ }
+
+ deler= f1[3];
+ vez[0]= Zmulx*(1.0+f1[0]/deler)+ Zjitx;
+ vez[1]= Zmuly*(1.0+f1[1]/deler)+ Zjity;
+ vez[2]= 0x7FFFFFFF *(f1[2]/deler);
+
+ deler= f2[3];
+ vez[4]= Zmulx*(1.0+f2[0]/deler)+ Zjitx;
+ vez[5]= Zmuly*(1.0+f2[1]/deler)+ Zjity;
+ vez[6]= 0x7FFFFFFF *(f2[2]/deler);
+
+ deler= f3[3];
+ vez[8]= Zmulx*(1.0+f3[0]/deler)+ Zjitx;
+ vez[9]= Zmuly*(1.0+f3[1]/deler)+ Zjity;
+ vez[10]= 0x7FFFFFFF *(f3[2]/deler);
+
+ if(vlr->v4) {
+ deler= f4[3];
+ vez[12]= Zmulx*(1.0+f4[0]/deler)+ Zjitx;
+ vez[13]= Zmuly*(1.0+f4[1]/deler)+ Zjity;
+ vez[14]= 0x7FFFFFFF *(f4[2]/deler);
+
+ if(ec & ME_V3V4) zbuflinefunc(vez+8, vez+12);
+ if(ec & ME_V4V1) zbuflinefunc(vez+12, vez);
+ }
+ else {
+ if(ec & ME_V3V1) zbuflinefunc(vez+8, vez);
+ }
+
+ if(ec & ME_V1V2) zbuflinefunc(vez, vez+4);
+ if(ec & ME_V2V3) zbuflinefunc(vez+4, vez+8);
+
+
+
+}
+
+void zbufinvulGLinv(v1,v2,v3)
+float *v1,*v2,*v3;
+/* vult in R.rectot de waarde Zvlnr in met R.rectz */
+/* KEERT Z-VERGELIJKING OM: ALLES ACHTER IS ZICHTBAAR */
+{
+ double x0,y0,z0,x1,y1,z1,x2,y2,z2,xx1;
+ double zxd,zyd,zy0,tmp;
+ float *minv,*maxv,*midv;
+ unsigned int *rectpofs,*rp;
+ int *rz,zverg,zvlak,x;
+ int my0,my2,sn1,sn2,rectx,zd,*rectzofs;
+ int y,omsl,xs0,xs1,xs2,xs3, dx0,dx1,dx2;
+
+ /* MIN MAX */
+ if(v1[1]<v2[1]) {
+ if(v2[1]<v3[1]) {
+ minv=v1; midv=v2; maxv=v3;
+ }
+ else if(v1[1]<v3[1]) {
+ minv=v1; midv=v3; maxv=v2;
+ }
+ else {
+ minv=v3; midv=v1; maxv=v2;
+ }
+ }
+ else {
+ if(v1[1]<v3[1]) {
+ minv=v2; midv=v1; maxv=v3;
+ }
+ else if(v2[1]<v3[1]) {
+ minv=v2; midv=v3; maxv=v1;
+ }
+ else {
+ minv=v3; midv=v2; maxv=v1;
+ }
+ }
+
+ my0= ceil(minv[1]);
+ my2= floor(maxv[1]);
+ omsl= floor(midv[1]);
+
+ if(my2<0 || my0> R.recty) return;
+
+ if(my0<0) my0=0;
+
+ /* EDGES : DE LANGSTE */
+ xx1= maxv[1]-minv[1];
+ if(xx1>2.0/65536.0) {
+ z0= (maxv[0]-minv[0])/xx1;
+
+ tmp= (-65536.0*z0);
+ dx0= CLAMPIS(tmp, INT_MIN, INT_MAX);
+
+ tmp= 65536.0*(z0*(my2-minv[1])+minv[0]);
+ xs0= CLAMPIS(tmp, INT_MIN, INT_MAX);
+ }
+ else {
+ dx0= 0;
+ xs0= 65536.0*(MIN2(minv[0],maxv[0]));
+ }
+ /* EDGES : DE BOVENSTE */
+ xx1= maxv[1]-midv[1];
+ if(xx1>2.0/65536.0) {
+ z0= (maxv[0]-midv[0])/xx1;
+
+ tmp= (-65536.0*z0);
+ dx1= CLAMPIS(tmp, INT_MIN, INT_MAX);
+
+ tmp= 65536.0*(z0*(my2-midv[1])+midv[0]);
+ xs1= CLAMPIS(tmp, INT_MIN, INT_MAX);
+ }
+ else {
+ dx1= 0;
+ xs1= 65536.0*(MIN2(midv[0],maxv[0]));
+ }
+ /* EDGES : DE ONDERSTE */
+ xx1= midv[1]-minv[1];
+ if(xx1>2.0/65536.0) {
+ z0= (midv[0]-minv[0])/xx1;
+
+ tmp= (-65536.0*z0);
+ dx2= CLAMPIS(tmp, INT_MIN, INT_MAX);
+
+ tmp= 65536.0*(z0*(omsl-minv[1])+minv[0]);
+ xs2= CLAMPIS(tmp, INT_MIN, INT_MAX);
+ }
+ else {
+ dx2= 0;
+ xs2= 65536.0*(MIN2(minv[0],midv[0]));
+ }
+
+ /* ZBUF DX DY */
+ x1= v1[0]- v2[0];
+ x2= v2[0]- v3[0];
+ y1= v1[1]- v2[1];
+ y2= v2[1]- v3[1];
+ z1= v1[2]- v2[2];
+ z2= v2[2]- v3[2];
+ x0= y1*z2-z1*y2;
+ y0= z1*x2-x1*z2;
+ z0= x1*y2-y1*x2;
+
+ if(z0==0.0) return;
+
+ if(midv[1]==maxv[1]) omsl= my2;
+ if(omsl<0) omsl= -1; /* dan neemt ie de eerste lus helemaal */
+
+ while (my2 >= R.recty) { /* my2 kan groter zijn */
+ xs0+=dx0;
+ if (my2<=omsl) {
+ xs2+= dx2;
+ }
+ else{
+ xs1+= dx1;
+ }
+ my2--;
+ }
+
+ xx1= (x0*v1[0]+y0*v1[1])/z0+v1[2];
+
+ zxd= -x0/z0;
+ zyd= -y0/z0;
+ zy0= my2*zyd+xx1;
+ zd= (int)CLAMPIS(zxd, INT_MIN, INT_MAX);
+
+ /* start-ofset in rect */
+ rectx= R.rectx;
+ rectzofs= (int *)(R.rectz+rectx*my2);
+ rectpofs= (R.rectot+rectx*my2);
+ zvlak= Zvlnr;
+
+ xs3= 0; /* flag */
+ if(dx0>dx1) {
+ xs3= xs0;
+ xs0= xs1;
+ xs1= xs3;
+ xs3= dx0;
+ dx0= dx1;
+ dx1= xs3;
+ xs3= 1; /* flag */
+
+ }
+
+ for(y=my2;y>omsl;y--) {
+
+ sn1= xs0>>16;
+ xs0+= dx0;
+
+ sn2= xs1>>16;
+ xs1+= dx1;
+
+ sn1++;
+
+ if(sn2>=rectx) sn2= rectx-1;
+ if(sn1<0) sn1= 0;
+ zverg= (int) CLAMPIS((sn1*zxd+zy0), INT_MIN, INT_MAX);
+ rz= rectzofs+sn1;
+ rp= rectpofs+sn1;
+ x= sn2-sn1;
+ while(x>=0) {
+ if(zverg> *rz || *rz==0x7FFFFFFF) {
+ *rz= zverg;
+ *rp= zvlak;
+ }
+ zverg+= zd;
+ rz++;
+ rp++;
+ x--;
+ }
+ zy0-=zyd;
+ rectzofs-= rectx;
+ rectpofs-= rectx;
+ }
+
+ if(xs3) {
+ xs0= xs1;
+ dx0= dx1;
+ }
+ if(xs0>xs2) {
+ xs3= xs0;
+ xs0= xs2;
+ xs2= xs3;
+ xs3= dx0;
+ dx0= dx2;
+ dx2= xs3;
+ }
+
+ for(;y>=my0;y--) {
+
+ sn1= xs0>>16;
+ xs0+= dx0;
+
+ sn2= xs2>>16;
+ xs2+= dx2;
+
+ sn1++;
+
+ if(sn2>=rectx) sn2= rectx-1;
+ if(sn1<0) sn1= 0;
+ zverg= (int) CLAMPIS((sn1*zxd+zy0), INT_MIN, INT_MAX);
+ rz= rectzofs+sn1;
+ rp= rectpofs+sn1;
+ x= sn2-sn1;
+ while(x>=0) {
+ if(zverg> *rz || *rz==0x7FFFFFFF) {
+ *rz= zverg;
+ *rp= zvlak;
+ }
+ zverg+= zd;
+ rz++;
+ rp++;
+ x--;
+ }
+
+ zy0-=zyd;
+ rectzofs-= rectx;
+ rectpofs-= rectx;
+ }
+}
+
+void zbufinvulGL(float *v1, float *v2, float *v3) /* vult in R.rectot de waarde Zvlnr in met R.rectz */
+{
+ double x0,y0,z0;
+ double x1,y1,z1,x2,y2,z2,xx1;
+ double zxd,zyd,zy0,tmp;
+ float *minv,*maxv,*midv;
+ unsigned int *rectpofs,*rp;
+ int *rz,zverg,zvlak,x;
+ int my0,my2,sn1,sn2,rectx,zd,*rectzofs;
+ int y,omsl,xs0,xs1,xs2,xs3, dx0,dx1,dx2;
+
+ /* MIN MAX */
+ if(v1[1]<v2[1]) {
+ if(v2[1]<v3[1]) {
+ minv=v1; midv=v2; maxv=v3;
+ }
+ else if(v1[1]<v3[1]) {
+ minv=v1; midv=v3; maxv=v2;
+ }
+ else {
+ minv=v3; midv=v1; maxv=v2;
+ }
+ }
+ else {
+ if(v1[1]<v3[1]) {
+ minv=v2; midv=v1; maxv=v3;
+ }
+ else if(v2[1]<v3[1]) {
+ minv=v2; midv=v3; maxv=v1;
+ }
+ else {
+ minv=v3; midv=v2; maxv=v1;
+ }
+ }
+
+ if(minv[1] == maxv[1]) return; /* beveiliging 'nul' grote vlakken */
+
+ my0= ceil(minv[1]);
+ my2= floor(maxv[1]);
+ omsl= floor(midv[1]);
+
+ if(my2<0 || my0> R.recty) return;
+
+ if(my0<0) my0= 0;
+
+ /* EDGES : DE LANGSTE */
+ xx1= maxv[1]-minv[1];
+ if(xx1!=0.0) {
+ z0= (maxv[0]-minv[0])/xx1;
+
+ tmp= -65536.0*z0;
+ dx0= CLAMPIS(tmp, INT_MIN, INT_MAX);
+
+ tmp= 65536.0*(z0*(my2-minv[1]) + minv[0]);
+ xs0= CLAMPIS(tmp, INT_MIN, INT_MAX);
+ }
+ else {
+ dx0= 0;
+ xs0= 65536.0*(MIN2(minv[0],maxv[0]));
+ }
+ /* EDGES : DE BOVENSTE */
+ xx1= maxv[1]-midv[1];
+ if(xx1!=0.0) {
+ z0= (maxv[0]-midv[0])/xx1;
+
+ tmp= -65536.0*z0;
+ dx1= CLAMPIS(tmp, INT_MIN, INT_MAX);
+
+ tmp= 65536.0*(z0*(my2-midv[1])+midv[0]);
+ xs1= CLAMPIS(tmp, INT_MIN, INT_MAX);
+ }
+ else {
+ dx1= 0;
+ xs1= 65536.0*(MIN2(midv[0],maxv[0]));
+ }
+ /* EDGES : DE ONDERSTE */
+ xx1= midv[1]-minv[1];
+ if(xx1!=0.0) {
+ z0= (midv[0]-minv[0])/xx1;
+
+ tmp= -65536.0*z0;
+ dx2= CLAMPIS(tmp, INT_MIN, INT_MAX);
+
+ tmp= 65536.0*(z0*(omsl-minv[1])+minv[0]);
+ xs2= CLAMPIS(tmp, INT_MIN, INT_MAX);
+ }
+ else {
+ dx2= 0;
+ xs2= 65536.0*(MIN2(minv[0],midv[0]));
+ }
+
+ /* ZBUF DX DY */
+ x1= v1[0]- v2[0];
+ x2= v2[0]- v3[0];
+ y1= v1[1]- v2[1];
+ y2= v2[1]- v3[1];
+ z1= v1[2]- v2[2];
+ z2= v2[2]- v3[2];
+ x0= y1*z2-z1*y2;
+ y0= z1*x2-x1*z2;
+ z0= x1*y2-y1*x2;
+
+ if(z0==0.0) return;
+
+ if(midv[1]==maxv[1]) omsl= my2;
+ if(omsl<0) omsl= -1; /* dan neemt ie de eerste lus helemaal */
+
+ while (my2 >= R.recty) { /* my2 kan groter zijn */
+ xs0+=dx0;
+ if (my2<=omsl) {
+ xs2+= dx2;
+ }
+ else{
+ xs1+= dx1;
+ }
+ my2--;
+ }
+
+ xx1= (x0*v1[0]+y0*v1[1])/z0+v1[2];
+
+ zxd= -x0/z0;
+ zyd= -y0/z0;
+ zy0= my2*zyd+xx1;
+ zd= (int)CLAMPIS(zxd, INT_MIN, INT_MAX);
+
+ /* start-ofset in rect */
+ rectx= R.rectx;
+ rectzofs= (int *)(R.rectz+rectx*my2);
+ rectpofs= (R.rectot+rectx*my2);
+ zvlak= Zvlnr;
+
+ xs3= 0; /* flag */
+ if(dx0>dx1) {
+ xs3= xs0;
+ xs0= xs1;
+ xs1= xs3;
+ xs3= dx0;
+ dx0= dx1;
+ dx1= xs3;
+ xs3= 1; /* flag */
+
+ }
+
+ for(y=my2;y>omsl;y--) {
+
+ /* dit is ongevoelig voor endians */
+ sn1= xs0>>16;
+ xs0+= dx0;
+
+ sn2= xs1>>16;
+ xs1+= dx1;
+
+ sn1++;
+
+ if(sn2>=rectx) sn2= rectx-1;
+ if(sn1<0) sn1= 0;
+ zverg= (int) CLAMPIS((sn1*zxd+zy0), INT_MIN, INT_MAX);
+ rz= rectzofs+sn1;
+ rp= rectpofs+sn1;
+ x= sn2-sn1;
+
+ while(x>=0) {
+ if(zverg< *rz) {
+ *rz= zverg;
+ *rp= zvlak;
+ }
+ zverg+= zd;
+ rz++;
+ rp++;
+ x--;
+ }
+ zy0-=zyd;
+ rectzofs-= rectx;
+ rectpofs-= rectx;
+ }
+
+ if(xs3) {
+ xs0= xs1;
+ dx0= dx1;
+ }
+ if(xs0>xs2) {
+ xs3= xs0;
+ xs0= xs2;
+ xs2= xs3;
+ xs3= dx0;
+ dx0= dx2;
+ dx2= xs3;
+ }
+
+ for(;y>=my0;y--) {
+
+ sn1= xs0>>16;
+ xs0+= dx0;
+
+ sn2= xs2>>16;
+ xs2+= dx2;
+
+ sn1++;
+
+ if(sn2>=rectx) sn2= rectx-1;
+ if(sn1<0) sn1= 0;
+ zverg= (int) CLAMPIS((sn1*zxd+zy0), INT_MIN, INT_MAX);
+ rz= rectzofs+sn1;
+ rp= rectpofs+sn1;
+ x= sn2-sn1;
+ while(x>=0) {
+ if(zverg< *rz) {
+ *rz= zverg;
+ *rp= zvlak;
+ }
+ zverg+= zd;
+ rz++;
+ rp++;
+ x--;
+ }
+
+ zy0-=zyd;
+ rectzofs-= rectx;
+ rectpofs-= rectx;
+ }
+}
+
+
+void zbufinvulGL_onlyZ(float *v1, float *v2, float *v3) /* vult alleen R.rectz. oneven z= 1x ingevuld */
+{
+ double x0,y0,z0,x1,y1,z1,x2,y2,z2,xx1;
+ double zxd,zyd,zy0,tmp;
+ float *minv,*maxv,*midv;
+ int *rz,zverg,x;
+ int my0,my2,sn1,sn2,rectx,zd,*rectzofs;
+ int y,omsl,xs0,xs1,xs2,xs3, dx0,dx1,dx2;
+
+ /* MIN MAX */
+ if(v1[1]<v2[1]) {
+ if(v2[1]<v3[1]) {
+ minv=v1;
+ midv=v2;
+ maxv=v3;
+ }
+ else if(v1[1]<v3[1]) {
+ minv=v1;
+ midv=v3;
+ maxv=v2;
+ }
+ else {
+ minv=v3;
+ midv=v1;
+ maxv=v2;
+ }
+ }
+ else {
+ if(v1[1]<v3[1]) {
+ minv=v2;
+ midv=v1;
+ maxv=v3;
+ }
+ else if(v2[1]<v3[1]) {
+ minv=v2;
+ midv=v3;
+ maxv=v1;
+ }
+ else {
+ minv=v3;
+ midv=v2;
+ maxv=v1;
+ }
+ }
+
+ my0= ceil(minv[1]);
+ my2= floor(maxv[1]);
+ omsl= floor(midv[1]);
+
+ if(my2<0 || my0> R.recty) return;
+
+ if(my0<0) my0=0;
+
+ /* EDGES : DE LANGSTE */
+ xx1= maxv[1]-minv[1];
+ if(xx1!=0.0) {
+ z0= (maxv[0]-minv[0])/xx1;
+
+ tmp= (-65536.0*z0);
+ dx0= CLAMPIS(tmp, INT_MIN, INT_MAX);
+
+ tmp= 65536.0*(z0*(my2-minv[1])+minv[0]);
+ xs0= CLAMPIS(tmp, INT_MIN, INT_MAX);
+ }
+ else {
+ dx0= 0;
+ xs0= 65536.0*(MIN2(minv[0],maxv[0]));
+ }
+ /* EDGES : DE BOVENSTE */
+ xx1= maxv[1]-midv[1];
+ if(xx1!=0.0) {
+ z0= (maxv[0]-midv[0])/xx1;
+
+ tmp= (-65536.0*z0);
+ dx1= CLAMPIS(tmp, INT_MIN, INT_MAX);
+
+ tmp= 65536.0*(z0*(my2-midv[1])+midv[0]);
+ xs1= CLAMPIS(tmp, INT_MIN, INT_MAX);
+ }
+ else {
+ dx1= 0;
+ xs1= 65536.0*(MIN2(midv[0],maxv[0]));
+ }
+ /* EDGES : DE ONDERSTE */
+ xx1= midv[1]-minv[1];
+ if(xx1!=0.0) {
+ z0= (midv[0]-minv[0])/xx1;
+
+ tmp= (-65536.0*z0);
+ dx2= CLAMPIS(tmp, INT_MIN, INT_MAX);
+
+ tmp= 65536.0*(z0*(omsl-minv[1])+minv[0]);
+ xs2= CLAMPIS(tmp, INT_MIN, INT_MAX);
+ }
+ else {
+ dx2= 0;
+ xs2= 65536.0*(MIN2(minv[0],midv[0]));
+ }
+
+ /* ZBUF DX DY */
+ x1= v1[0]- v2[0];
+ x2= v2[0]- v3[0];
+ y1= v1[1]- v2[1];
+ y2= v2[1]- v3[1];
+ z1= v1[2]- v2[2];
+ z2= v2[2]- v3[2];
+ x0= y1*z2-z1*y2;
+ y0= z1*x2-x1*z2;
+ z0= x1*y2-y1*x2;
+
+ if(z0==0.0) return;
+
+ if(midv[1]==maxv[1]) omsl= my2;
+ if(omsl<0) omsl= -1; /* dan neemt ie de eerste lus helemaal */
+
+ while (my2 >= R.recty) { /* my2 kan groter zijn */
+ xs0+=dx0;
+ if (my2<=omsl) {
+ xs2+= dx2;
+ }
+ else{
+ xs1+= dx1;
+ }
+ my2--;
+ }
+
+ xx1= (x0*v1[0]+y0*v1[1])/z0+v1[2];
+
+ zxd= -x0/z0;
+ zyd= -y0/z0;
+ zy0= my2*zyd+xx1;
+ zd= (int)CLAMPIS(zxd, INT_MIN, INT_MAX);
+
+ /* start-ofset in rect */
+ rectx= R.rectx;
+ rectzofs= (int *)(R.rectz+rectx*my2);
+
+ xs3= 0; /* flag */
+ if(dx0>dx1) {
+ xs3= xs0;
+ xs0= xs1;
+ xs1= xs3;
+ xs3= dx0;
+ dx0= dx1;
+ dx1= xs3;
+ xs3= 1; /* flag */
+
+ }
+
+ for(y=my2;y>omsl;y--) {
+
+ sn1= xs0>>16;
+ xs0+= dx0;
+
+ sn2= xs1>>16;
+ xs1+= dx1;
+
+ sn1++;
+
+ if(sn2>=rectx) sn2= rectx-1;
+ if(sn1<0) sn1= 0;
+ zverg= (int) CLAMPIS((sn1*zxd+zy0), INT_MIN, INT_MAX);
+ rz= rectzofs+sn1;
+
+ x= sn2-sn1;
+ while(x>=0) {
+ if(zverg< *rz) {
+ *rz= zverg;
+ }
+ zverg+= zd;
+ rz++;
+ x--;
+ }
+ zy0-=zyd;
+ rectzofs-= rectx;
+ }
+
+ if(xs3) {
+ xs0= xs1;
+ dx0= dx1;
+ }
+ if(xs0>xs2) {
+ xs3= xs0;
+ xs0= xs2;
+ xs2= xs3;
+ xs3= dx0;
+ dx0= dx2;
+ dx2= xs3;
+ }
+
+ for(;y>=my0;y--) {
+
+ sn1= xs0>>16;
+ xs0+= dx0;
+
+ sn2= xs2>>16;
+ xs2+= dx2;
+
+ sn1++;
+
+ if(sn2>=rectx) sn2= rectx-1;
+ if(sn1<0) sn1= 0;
+ zverg= (int) CLAMPIS((sn1*zxd+zy0), INT_MIN, INT_MAX);
+ rz= rectzofs+sn1;
+
+ x= sn2-sn1;
+ while(x>=0) {
+ if(zverg< *rz) {
+ *rz= zverg;
+ }
+ zverg+= zd;
+ rz++;
+ x--;
+ }
+
+ zy0-=zyd;
+ rectzofs-= rectx;
+ }
+}
+
+void print3floats(float *v1, float *v2, float *v3)
+{
+ printf("1 %f %f %f %f\n", v1[0], v1[1], v1[2], v1[3]);
+ printf("2 %f %f %f %f\n", v2[0], v2[1], v2[2], v2[3]);
+ printf("3 %f %f %f %f\n", v3[0], v3[1], v3[2], v3[3]);
+}
+
+static short cliptestf(float p, float q, float *u1, float *u2)
+{
+ float r;
+
+ if(p<0.0) {
+ if(q<p) return 0;
+ else if(q<0.0) {
+ r= q/p;
+ if(r>*u2) return 0;
+ else if(r>*u1) *u1=r;
+ }
+ }
+ else {
+ if(p>0.0) {
+ if(q<0.0) return 0;
+ else if(q<p) {
+ r= q/p;
+ if(r<*u1) return 0;
+ else if(r<*u2) *u2=r;
+ }
+ }
+ else if(q<0.0) return 0;
+ }
+ return 1;
+}
+
+int RE_testclip(float *v)
+{
+ float abs4; /* LET OP: deze func moet zelfde doen als cliptestf, anders problemen in zbufclip()*/
+ short c=0;
+
+ abs4= fabs(v[3]);
+
+ if(v[2]< -abs4) c=16; /* hier stond vroeger " if(v[2]<0) ", zie clippz() */
+ else if(v[2]> abs4) c+= 32;
+
+ if( v[0]>abs4) c+=2;
+ else if( v[0]< -abs4) c+=1;
+
+ if( v[1]>abs4) c+=4;
+ else if( v[1]< -abs4) c+=8;
+
+ return c;
+}
+
+
+static void clipp(float *v1, float *v2, int b1, int *b2, int *b3, int a)
+{
+ float da,db,u1=0.0,u2=1.0;
+
+ labda[b1][0]= -1.0;
+ labda[b1][1]= -1.0;
+
+ da= v2[a]-v1[a];
+ db= v2[3]-v1[3];
+
+ /* volgens het oorspronkelijke artikel van Liang&Barsky, wordt bij het clippen van
+ * hoco's met het viewplane, het getal "0" gebruikt ipv "-w" .
+ * Dit wijkt af van de andere clipping (links en onder) en vond ik ook niet erg
+ * 'homogeen'. Het is dus een fout, wie had dat gedacht van L&B!
+ */
+
+ if(cliptestf(-da-db, v1[3]+v1[a], &u1,&u2)) {
+ if(cliptestf(da-db, v1[3]-v1[a], &u1,&u2)) {
+ *b3=1;
+ if(u2<1.0) {
+ labda[b1][1]= u2;
+ *b2=1;
+ }
+ else labda[b1][1]=1.0; /* u2 */
+ if(u1>0.0) {
+ labda[b1][0]= u1;
+ *b2=1;
+ } else labda[b1][0]=0.0;
+ }
+ }
+}
+
+static int clipline(float *v1, float *v2) /* return 0: niet tekenen */
+{
+ float dz,dw, u1=0.0, u2=1.0;
+ float dx, dy;
+
+ dz= v2[2]-v1[2];
+ dw= v2[3]-v1[3];
+
+ if(cliptestf(-dz-dw, v1[3]+v1[2], &u1,&u2)) {
+ if(cliptestf(dz-dw, v1[3]-v1[2], &u1,&u2)) {
+
+ dx= v2[0]-v1[0];
+ dz= v2[3]-v1[3];
+
+ if(cliptestf(-dx-dz, v1[0]+v1[3], &u1,&u2)) {
+ if(cliptestf(dx-dz, v1[3]-v1[0], &u1,&u2)) {
+
+ dy= v2[1]-v1[1];
+
+ if(cliptestf(-dy-dz,v1[1]+v1[3],&u1,&u2)) {
+ if(cliptestf(dy-dz,v1[3]-v1[1],&u1,&u2)) {
+
+ if(u2<1.0) {
+ v2[0]= v1[0]+u2*dx;
+ v2[1]= v1[1]+u2*dy;
+ v2[2]= v1[2]+u2*dz;
+ v2[3]= v1[3]+u2*dw;
+ }
+ if(u1>0.0) {
+ v1[0]= v1[0]+u1*dx;
+ v1[1]= v1[1]+u1*dy;
+ v1[2]= v1[2]+u1*dz;
+ v1[3]= v1[3]+u1*dw;
+ }
+ return 1;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+
+static void maakvertpira(float *v1, float *v2, int *b1, int b2, int *clve)
+{
+ float l1,l2,*adr;
+
+ l1= labda[b2][0];
+ l2= labda[b2][1];
+
+ if(l1!= -1.0) {
+ if(l1!= 0.0) {
+ adr= vez+4*(*clve);
+ p[*b1]=adr;
+ (*clve)++;
+ adr[0]= v1[0]+l1*(v2[0]-v1[0]);
+ adr[1]= v1[1]+l1*(v2[1]-v1[1]);
+ adr[2]= v1[2]+l1*(v2[2]-v1[2]);
+ adr[3]= v1[3]+l1*(v2[3]-v1[3]);
+ } else p[*b1]= v1;
+ (*b1)++;
+ }
+ if(l2!= -1.0) {
+ if(l2!= 1.0) {
+ adr= vez+4*(*clve);
+ p[*b1]=adr;
+ (*clve)++;
+ adr[0]= v1[0]+l2*(v2[0]-v1[0]);
+ adr[1]= v1[1]+l2*(v2[1]-v1[1]);
+ adr[2]= v1[2]+l2*(v2[2]-v1[2]);
+ adr[3]= v1[3]+l2*(v2[3]-v1[3]);
+ (*b1)++;
+ }
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
+void RE_projectverto(float *v1, float *adr)
+{
+ /* berekent homogene co van vertex v1 */
+ float x,y,z;
+
+ x= v1[0];
+ y= v1[1];
+ z= v1[2];
+ adr[0]= x*R.winmat[0][0] + z*R.winmat[2][0];
+ adr[1]= y*R.winmat[1][1]+ z*R.winmat[2][1];
+ adr[2]= z*R.winmat[2][2] + R.winmat[3][2];
+ adr[3]= z*R.winmat[2][3] + R.winmat[3][3];
+
+} /* end of void RE_projectverto(float *v1, float *adr) */
+
+/* ------------------------------------------------------------------------- */
+
+void projectvert(float *v1, float *adr)
+{
+ /* berekent homogene co van vertex v1 */
+ float x,y,z;
+
+ x= v1[0];
+ y= v1[1];
+ z= v1[2];
+ adr[0]= x*R.winmat[0][0]+ y*R.winmat[1][0]+ z*R.winmat[2][0]+ R.winmat[3][0];
+ adr[1]= x*R.winmat[0][1]+ y*R.winmat[1][1]+ z*R.winmat[2][1]+ R.winmat[3][1];
+ adr[2]= x*R.winmat[0][2]+ y*R.winmat[1][2]+ z*R.winmat[2][2]+ R.winmat[3][2];
+ adr[3]= x*R.winmat[0][3]+ y*R.winmat[1][3]+ z*R.winmat[2][3]+ R.winmat[3][3];
+}
+
+
+void zbufclip(float *f1, float *f2, float *f3, int c1, int c2, int c3)
+{
+ float deler;
+
+ if(c1 | c2 | c3) { /* niet in midden */
+ if(c1 & c2 & c3) { /* helemaal eruit */
+ return;
+ } else { /* clippen */
+ int arg, v, b, clipflag[3], b1, b2, b3, c4, clve=3, clvlo, clvl=1;
+
+ vez[0]= f1[0]; vez[1]= f1[1]; vez[2]= f1[2]; vez[3]= f1[3];
+ vez[4]= f2[0]; vez[5]= f2[1]; vez[6]= f2[2]; vez[7]= f2[3];
+ vez[8]= f3[0]; vez[9]= f3[1]; vez[10]= f3[2];vez[11]= f3[3];
+
+ vlzp[0][0]= vez;
+ vlzp[0][1]= vez+4;
+ vlzp[0][2]= vez+8;
+
+ clipflag[0]= ( (c1 & 48) | (c2 & 48) | (c3 & 48) );
+ if(clipflag[0]==0) { /* anders opnieuw berekend verderop, na de eerste (z) clip */
+ clipflag[1]= ( (c1 & 3) | (c2 & 3) | (c3 & 3) );
+ clipflag[2]= ( (c1 & 12) | (c2 & 12) | (c3 & 12) );
+ }
+
+ for(b=0;b<3;b++) {
+
+ if(clipflag[b]) {
+
+ clvlo= clvl;
+
+ for(v=0; v<clvlo; v++) {
+
+ if(vlzp[v][0]!=0) { /* vlak is er nog */
+ b2= b3 =0; /* clipvlaggen */
+
+ if(b==0) arg= 2;
+ else if (b==1) arg= 0;
+ else arg= 1;
+
+ clipp(vlzp[v][0],vlzp[v][1],0,&b2,&b3, arg);
+ clipp(vlzp[v][1],vlzp[v][2],1,&b2,&b3, arg);
+ clipp(vlzp[v][2],vlzp[v][0],2,&b2,&b3, arg);
+
+ if(b2==0 && b3==1) {
+ /* er helemaal in */;
+ } else if(b3==0) {
+ vlzp[v][0]=0;
+ /* er helemaal uit */;
+ } else {
+ b1=0;
+ maakvertpira(vlzp[v][0],vlzp[v][1],&b1,0,&clve);
+ maakvertpira(vlzp[v][1],vlzp[v][2],&b1,1,&clve);
+ maakvertpira(vlzp[v][2],vlzp[v][0],&b1,2,&clve);
+
+ /* als frontclip is gedaan: nu pas clipvlaggen zetten */
+ if(b==0) {
+ clipflag[1]= clipflag[2]= 0;
+ f1= vez;
+ for(b3=0; b3<clve; b3++) {
+ c4= RE_testclip(f1);
+ clipflag[1] |= (c4 & 3);
+ clipflag[2] |= (c4 & 12);
+ f1+= 4;
+ }
+ }
+
+ vlzp[v][0]=0;
+ if(b1>2) {
+ for(b3=3; b3<=b1; b3++) {
+ vlzp[clvl][0]= p[0];
+ vlzp[clvl][1]= p[b3-2];
+ vlzp[clvl][2]= p[b3-1];
+ clvl++;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* persp deling */
+ /* valt hier nog te optimaliseren door alleen te gebruiken vertices te doen? */
+ if(clve>38) printf("clip overflow: clve clvl %d %d\n",clve,clvl);
+ f1=vez;
+ for(c1=0;c1<clve;c1++) {
+ deler= f1[3];
+ f1[0]= Zmulx*(1.0+f1[0]/deler)+ Zjitx;
+ f1[1]= Zmuly*(1.0+f1[1]/deler)+ Zjity;
+ f1[2]= 0x7FFFFFFF *(f1[2]/deler);
+ f1+=4;
+ }
+ for(b=1;b<clvl;b++) {
+ if(vlzp[b][0]) {
+ zbuffunc(vlzp[b][0],vlzp[b][1],vlzp[b][2]);
+ }
+ }
+ return;
+ }
+ }
+
+ /* persp deling: HCS to ZCS */
+
+ deler= f1[3];
+ vez[0]= Zmulx*(1.0+f1[0]/deler)+ Zjitx;
+ vez[1]= Zmuly*(1.0+f1[1]/deler)+ Zjity;
+ vez[2]= 0x7FFFFFFF *(f1[2]/deler);
+
+ deler= f2[3];
+ vez[4]= Zmulx*(1.0+f2[0]/deler)+ Zjitx;
+ vez[5]= Zmuly*(1.0+f2[1]/deler)+ Zjity;
+ vez[6]= 0x7FFFFFFF *(f2[2]/deler);
+
+ deler= f3[3];
+ vez[8]= Zmulx*(1.0+f3[0]/deler)+ Zjitx;
+ vez[9]= Zmuly*(1.0+f3[1]/deler)+ Zjity;
+ vez[10]= 0x7FFFFFFF *(f3[2]/deler);
+
+ zbuffunc(vez,vez+4,vez+8);
+}
+
+/* ***************** ZBUFFER MAINROUTINES **************** */
+
+
+void zbufferall(void)
+{
+ VlakRen *vlr= NULL;
+ Material *ma=0;
+ int v;
+ short transp=0, env=0, wire=0;
+
+ Zmulx= ((float)R.rectx)/2.0;
+ Zmuly= ((float)R.recty)/2.0;
+
+ fillrect(R.rectz, R.rectx, R.recty, 0x7FFFFFFF);
+
+ Zvlnr= 0;
+
+ zbuffunc= zbufinvulGL;
+ zbuflinefunc= zbufline;
+
+ for(v=0;v<R.totvlak;v++) {
+
+ if((v & 255)==0) vlr= R.blovl[v>>8];
+ else vlr++;
+
+ if(vlr->flag & R_VISIBLE) {
+ if(vlr->mat!=ma) {
+ ma= vlr->mat;
+ transp= ma->mode & MA_ZTRA;
+ env= (ma->mode & MA_ENV);
+ wire= (ma->mode & MA_WIRE);
+
+ if(ma->mode & MA_ZINV) zbuffunc= zbufinvulGLinv;
+ else zbuffunc= zbufinvulGL;
+ }
+
+ if(transp==0) {
+ if(env) Zvlnr= 0;
+ else Zvlnr= v+1;
+
+ if(wire) zbufclipwire(vlr);
+ else {
+ zbufclip(vlr->v1->ho, vlr->v2->ho, vlr->v3->ho, vlr->v1->clip, vlr->v2->clip, vlr->v3->clip);
+ if(vlr->v4) {
+ if(Zvlnr) Zvlnr+= 0x800000;
+ zbufclip(vlr->v1->ho, vlr->v3->ho, vlr->v4->ho, vlr->v1->clip, vlr->v3->clip, vlr->v4->clip);
+ }
+ }
+ }
+ }
+ }
+}
+
+static int hashlist_projectvert(float *v1, float *hoco)
+{
+ static VertBucket bucket[256], *buck;
+
+ if(v1==0) {
+ memset(bucket, 0, 256*sizeof(VertBucket));
+ return 0;
+ }
+
+ buck= &bucket[ (((long)v1)/16) & 255 ];
+ if(buck->vert==v1) {
+ COPY_16(hoco, buck->hoco);
+ return buck->clip;
+ }
+
+ projectvert(v1, hoco);
+ buck->clip = RE_testclip(hoco);
+ buck->vert= v1;
+ COPY_16(buck->hoco, hoco);
+ return buck->clip;
+}
+
+
+void RE_zbufferall_radio(struct RadView *vw, RNode **rg_elem, int rg_totelem)
+{
+ RNode **re, *rn;
+ float hoco[4][4];
+ int a;
+ int c1, c2, c3, c4= 0;
+ unsigned int *rectoto, *rectzo;
+ int rectxo, rectyo;
+
+ if(rg_totelem==0) return;
+
+ hashlist_projectvert(0, 0);
+
+ rectxo= R.rectx;
+ rectyo= R.recty;
+ rectoto= R.rectot;
+ rectzo= R.rectz;
+
+ R.rectx= vw->rectx;
+ R.recty= vw->recty;
+ R.rectot= vw->rect;
+ R.rectz= vw->rectz;
+
+ Zmulx= ((float)R.rectx)/2.0;
+ Zmuly= ((float)R.recty)/2.0;
+
+ /* needed for projectvert */
+ MTC_Mat4MulMat4(R.winmat, vw->viewmat, vw->winmat);
+
+ fillrect(R.rectz, R.rectx, R.recty, 0x7FFFFFFF);
+ fillrect(R.rectot, R.rectx, R.recty, 0xFFFFFF);
+
+ zbuffunc= zbufinvulGL;
+
+ re= rg_elem;
+ re+= (rg_totelem-1);
+ for(a= rg_totelem-1; a>=0; a--, re--) {
+ rn= *re;
+ if( (rn->f & RAD_SHOOT)==0 ) { /* no shootelement */
+
+ if( rn->f & RAD_BACKFACE) Zvlnr= 0xFFFFFF;
+ else Zvlnr= a;
+
+ c1= hashlist_projectvert(rn->v1, hoco[0]);
+ c2= hashlist_projectvert(rn->v2, hoco[1]);
+ c3= hashlist_projectvert(rn->v3, hoco[2]);
+
+ if(rn->v4) {
+ c4= hashlist_projectvert(rn->v4, hoco[3]);
+ }
+
+ zbufclip(hoco[0], hoco[1], hoco[2], c1, c2, c3);
+ if(rn->v4) {
+ zbufclip(hoco[0], hoco[2], hoco[3], c1, c3, c4);
+ }
+ }
+ }
+
+ /* restore */
+ R.rectx= rectxo;
+ R.recty= rectyo;
+ R.rectot= rectoto;
+ R.rectz= rectzo;
+
+}
+
+void zbuffershad(LampRen *lar)
+{
+ VlakRen *vlr= NULL;
+ Material *ma=0;
+ int a, ok=1, lay= -1;
+
+ if(lar->mode & LA_LAYER) lay= lar->lay;
+
+ Zmulx= ((float)R.rectx)/2.0;
+ Zmuly= ((float)R.recty)/2.0;
+ Zjitx= Zjity= -.5;
+
+ fillrect(R.rectz,R.rectx,R.recty,0x7FFFFFFE);
+
+ zbuffunc= zbufinvulGL_onlyZ;
+
+ for(a=0;a<R.totvlak;a++) {
+
+ if((a & 255)==0) vlr= R.blovl[a>>8];
+ else vlr++;
+
+ if(vlr->mat!= ma) {
+ ma= vlr->mat;
+ ok= 1;
+ if((ma->mode & MA_TRACEBLE)==0) ok= 0;
+ }
+ /* traceble er weer in: automatische verwijdering niet geweldig */
+
+ if(ok && (vlr->flag & R_VISIBLE) && (vlr->lay & lay)) {
+ zbufclip(vlr->v1->ho, vlr->v2->ho, vlr->v3->ho, vlr->v1->clip, vlr->v2->clip, vlr->v3->clip);
+ if(vlr->v4) zbufclip(vlr->v1->ho, vlr->v3->ho, vlr->v4->ho, vlr->v1->clip, vlr->v3->clip, vlr->v4->clip);
+ }
+ }
+}
+
+
+
+/* ******************** ABUF ************************* */
+
+
+void bgnaccumbuf(void)
+{
+
+ Acolrow= MEM_mallocN(4*sizeof(short)*R.rectx, "Acolrow");
+ Arectz= MEM_mallocN(sizeof(int)*ABUFPART*R.rectx, "Arectz");
+ APixbuf= MEM_mallocN(ABUFPART*R.rectx*sizeof(APixstr), "APixbuf");
+
+ Aminy= -1000;
+ Amaxy= -1000;
+
+ apsmteller= 0;
+ apsmfirst.next= 0;
+ apsmfirst.ps= 0;
+} /* End of void bgnaccumbuf(void) */
+
+/* ------------------------------------------------------------------------ */
+
+void endaccumbuf(void)
+{
+
+ MEM_freeN(Acolrow);
+ MEM_freeN(Arectz);
+ MEM_freeN(APixbuf);
+ freepsA();
+} /* End of void endaccumbuf(void) */
+
+/* ------------------------------------------------------------------------ */
+
+void copyto_abufz(int sample)
+{
+ PixStr *ps;
+ int x, y, *rza;
+ long *rd;
+
+ memcpy(Arectz, R.rectz+ R.rectx*Aminy, 4*R.rectx*(Amaxy-Aminy+1));
+
+ if( (R.r.mode & R_OSA)==0 || sample==0) return;
+
+ rza= Arectz;
+ rd= (R.rectdaps+ R.rectx*Aminy);
+
+ sample= (1<<sample);
+
+ for(y=Aminy; y<=Amaxy; y++) {
+ for(x=0; x<R.rectx; x++) {
+
+ if( IS_A_POINTER_CODE(*rd)) {
+ ps= (PixStr *) POINTER_FROM_CODE(*rd);
+
+ while(ps) {
+ if(sample & ps->mask) {
+ *rza= ps->z;
+ break;
+ }
+ ps= ps->next;
+ }
+ }
+
+ rd++; rza++;
+ }
+ }
+} /* end of void copyto_abufz(int sample) */
+
+
+/* ------------------------------------------------------------------------ */
+
+void zbuffer_abuf()
+{
+ float vec[3], hoco[4], mul, zval, fval;
+ Material *ma=0;
+ int v, len;
+
+ Zjitx= Zjity= -.5;
+ Zmulx= ((float)R.rectx)/2.0;
+ Zmuly= ((float)R.recty)/2.0;
+
+ /* clear APixstructen */
+ len= sizeof(APixstr)*R.rectx*ABUFPART;
+ memset(APixbuf, 0, len);
+
+ zbuffunc= zbufinvulAc;
+ zbuflinefunc= zbuflineAc;
+
+ for(Zsample=0; Zsample<R.osa || R.osa==0; Zsample++) {
+
+ copyto_abufz(Zsample); /* init zbuffer */
+
+ if(R.r.mode & R_OSA) {
+ Zjitx= -jit[Zsample][0];
+ Zjity= -jit[Zsample][1];
+ }
+
+/* printf("Start facetrace\n"); */
+
+ for(v=0; v<R.totvlak; v++) {
+ if((v & 255)==0) {
+ Zvlr= R.blovl[v>>8];
+ }
+ else Zvlr++;
+
+ ma= Zvlr->mat;
+
+/* printf("Face %d :%x at %f\n", v, ma, Zvlr->v1->ho[3]); */
+
+
+ if(ma->mode & (MA_ZTRA)) {
+
+ /* voordeeltje voor transp renderen */
+ if( ma->zoffs != 0.0) {
+ mul= 0x7FFFFFFF;
+ zval= mul*(1.0+Zvlr->v1->ho[2]/Zvlr->v1->ho[3]);
+
+ VECCOPY(vec, Zvlr->v1->co);
+ /* z is negatief, wordt anders geclipt */
+ vec[2]-= ma->zoffs;
+ RE_projectverto(vec, hoco);
+ fval= mul*(1.0+hoco[2]/hoco[3]);
+
+ Azvoordeel= (int) fabs(zval - fval );
+
+ /* PATCH: als transp en niet transp dicht op elkaar liggen: Zbuf aliasing: eruit! */
+ /* Azvoordeel= 0xFFFF; */
+ }
+ else Azvoordeel= 0;
+ /* else Azvoordeel= 0xFFFF; */
+
+ Zvlnr= v+1;
+
+ if(Zvlr->flag & R_VISIBLE) {
+
+ if(ma->mode & (MA_WIRE)) zbufclipwire(Zvlr);
+ else {
+ zbufclip(Zvlr->v1->ho, Zvlr->v2->ho, Zvlr->v3->ho, Zvlr->v1->clip, Zvlr->v2->clip, Zvlr->v3->clip);
+ if(Zvlr->v4) {
+ Zvlnr+= 0x800000;
+ zbufclip(Zvlr->v1->ho, Zvlr->v3->ho, Zvlr->v4->ho, Zvlr->v1->clip, Zvlr->v3->clip, Zvlr->v4->clip);
+ }
+ }
+ }
+ }
+ if(RE_local_test_break()) break;
+ }
+
+ if((R.r.mode & R_OSA)==0) break;
+ if(RE_local_test_break()) break;
+ }
+
+} /* end of void zbuffer_abuf() */
+
+
+int vergzvlak(const void *a1, const void *a2)
+{
+ const int *x1=a1, *x2=a2;
+
+ if( x1[0] < x2[0] ) return 1;
+ else if( x1[0] > x2[0]) return -1;
+ return 0;
+}
+
+void shadetrapixel(float x, float y, int vlak)
+{
+ if( (vlak & 0x7FFFFF) > R.totvlak) {
+ printf("error in shadetrapixel nr: %d\n", (vlak & 0x7FFFFF));
+ return;
+ }
+
+ shadepixel(x, y, vlak);
+}
+
+extern unsigned short usegamtab;
+extern unsigned short shortcol[4];
+void abufsetrow(int y)
+{
+ APixstr *ap, *apn;
+ float xs, ys;
+ int x, part, a, b, zrow[100][3], totvlak, alpha[32], tempgam, nr, intcol[4];
+ int sval, tempRf;
+ unsigned short *col, tempcol[4], sampcol[16*4], *scol;
+
+ if(y<0) return;
+ if(R.osa>16) {
+ printf("abufsetrow: osa too large\n");
+ G.afbreek= 1;
+ return;
+ }
+
+ tempRf= R.flag;
+ R.flag &= ~R_LAMPHALO;
+
+ /* alpha LUT */
+ if(R.r.mode & R_OSA ) {
+ x= (65536/R.osa);
+ for(a=0; a<=R.osa; a++) {
+ alpha[a]= a*x;
+ }
+ }
+ /* moet pixbuf worden gemaakt? */
+ if(y<Aminy || y>Amaxy) {
+ part= (y/ABUFPART);
+ Aminy= part*ABUFPART;
+ Amaxy= Aminy+ABUFPART-1;
+ if(Amaxy>=R.recty) Amaxy= R.recty-1;
+ freepsA();
+ zbuffer_abuf();
+ }
+
+ /* render rij */
+ col= Acolrow;
+ memset(col, 0, 2*4*R.rectx);
+ ap= APixbuf+R.rectx*(y-Aminy);
+ ys= y;
+ tempgam= usegamtab;
+ usegamtab= 0;
+
+ for(x=0; x<R.rectx; x++, col+=4, ap++) {
+ if(ap->p[0]) {
+ /* sorteer op z */
+ totvlak= 0;
+ apn= ap;
+ while(apn) {
+ for(a=0; a<4; a++) {
+ if(apn->p[a]) {
+ zrow[totvlak][0]= apn->z[a];
+ zrow[totvlak][1]= apn->p[a];
+ zrow[totvlak][2]= apn->mask[a];
+ totvlak++;
+ if(totvlak>99) totvlak= 99;
+ }
+ else break;
+ }
+ apn= apn->next;
+ }
+ if(totvlak==1) {
+
+ if(R.r.mode & R_OSA ) {
+ b= centmask[ ap->mask[0] ];
+ xs= (float)x+centLut[b & 15];
+ ys= (float)y+centLut[b>>4];
+ }
+ else {
+ xs= x; ys= y;
+ }
+ shadetrapixel(xs, ys, ap->p[0]);
+
+ nr= count_mask(ap->mask[0]);
+ if( (R.r.mode & R_OSA) && nr<R.osa) {
+ a= alpha[ nr ];
+ col[0]= (shortcol[0]*a)>>16;
+ col[1]= (shortcol[1]*a)>>16;
+ col[2]= (shortcol[2]*a)>>16;
+ col[3]= (shortcol[3]*a)>>16;
+ }
+ else {
+ col[0]= shortcol[0];
+ col[1]= shortcol[1];
+ col[2]= shortcol[2];
+ col[3]= shortcol[3];
+ }
+ }
+ else {
+
+ if(totvlak==2) {
+ if(zrow[0][0] < zrow[1][0]) {
+ a= zrow[0][0]; zrow[0][0]= zrow[1][0]; zrow[1][0]= a;
+ a= zrow[0][1]; zrow[0][1]= zrow[1][1]; zrow[1][1]= a;
+ a= zrow[0][2]; zrow[0][2]= zrow[1][2]; zrow[1][2]= a;
+ }
+
+ }
+ else { /* totvlak>2 */
+ qsort(zrow, totvlak, sizeof(int)*3, vergzvlak);
+ }
+
+ /* samenvoegen als pixels aanvullen */
+
+ while(totvlak>0) {
+ totvlak--;
+
+ if(R.r.mode & R_OSA) {
+ b= centmask[ zrow[totvlak][2] ];
+ xs= (float)x+centLut[b & 15];
+ ys= (float)y+centLut[b>>4];
+ }
+ else {
+ xs= x; ys= y;
+ }
+ shadetrapixel(xs, ys, zrow[totvlak][1]);
+
+ a= count_mask(zrow[totvlak][2]);
+ if( (R.r.mode & R_OSA ) && a<R.osa) {
+ if(totvlak>0) {
+ memset(sampcol, 0, 4*2*R.osa);
+ sval= addtosampcol(sampcol, shortcol, zrow[totvlak][2]);
+
+ /* sval==0: aplha helemaal vol */
+ while( (sval != 0) && (totvlak>0) ) {
+ a= count_mask(zrow[totvlak-1][2]);
+ if(a==R.osa) break;
+ totvlak--;
+
+ b= centmask[ zrow[totvlak][2] ];
+
+ xs= (float)x+centLut[b & 15];
+ ys= (float)y+centLut[b>>4];
+
+ shadetrapixel(xs, ys, zrow[totvlak][1]);
+ sval= addtosampcol(sampcol, shortcol, zrow[totvlak][2]);
+ }
+ scol= sampcol;
+ intcol[0]= scol[0]; intcol[1]= scol[1];
+ intcol[2]= scol[2]; intcol[3]= scol[3];
+ scol+= 4;
+ for(a=1; a<R.osa; a++, scol+=4) {
+ intcol[0]+= scol[0]; intcol[1]+= scol[1];
+ intcol[2]+= scol[2]; intcol[3]+= scol[3];
+ }
+ tempcol[0]= intcol[0]/R.osa;
+ tempcol[1]= intcol[1]/R.osa;
+ tempcol[2]= intcol[2]/R.osa;
+ tempcol[3]= intcol[3]/R.osa;
+
+ addAlphaUnderShort(col, tempcol);
+
+ }
+ else {
+ a= alpha[a];
+ shortcol[0]= (shortcol[0]*a)>>16;
+ shortcol[1]= (shortcol[1]*a)>>16;
+ shortcol[2]= (shortcol[2]*a)>>16;
+ shortcol[3]= (shortcol[3]*a)>>16;
+ addAlphaUnderShort(col, shortcol);
+ }
+ }
+ else addAlphaUnderShort(col, shortcol);
+
+ if(col[3]>=0xFFF0) break;
+ }
+ }
+ }
+ }
+
+ usegamtab= tempgam;
+ R.flag= tempRf;
+}
+
+/* end of zbuf.c */
+
+
+
+
diff --git a/source/blender/render/intern/source/zbufferdatastruct.c b/source/blender/render/intern/source/zbufferdatastruct.c
new file mode 100644
index 00000000000..f8e683d46bd
--- /dev/null
+++ b/source/blender/render/intern/source/zbufferdatastruct.c
@@ -0,0 +1,342 @@
+/**
+ * zbufferdatastruct.c
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 z buffer consists of an array of lists. Each list holds the objects
+ * behind a pixel. These can be sorted for closest distance. Per object,
+ * we store:
+ * - object type
+ * - object index
+ * - minimum distance
+ * - maximum distance
+ * - oversample flags
+ *
+ * The buffer was created to fit the new unified renderpipeline. We might
+ * turn it into an object later on.
+ *
+ * The z buffer has an unlimited depth. The oversampling code chops at a
+ * certain number of faces. This number is defined in
+ * vanillaRenderPipe_types.h
+ *
+ * Version 1 of the z buffer inserted objects by means of linear
+ * search: we walk along the list until we find the right object or
+ * until we have to insert a new one. This is terribly inefficient
+ * when we are dealing with large numbers of objects. Can we find a
+ * better solution here?
+ *
+ * Because we treat halos as billboards, we optimize halo
+ * insertion. For this purpose the fillFlatObject() functions have
+ * been implemented. */
+
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+#include "zbufferdatastruct.h"
+#include "render.h"
+#include "render_intern.h"
+/* if defined: all jittersamples are stored individually. _very_ serious */
+/* performance hit ! also gives some buffer size problems in big scenes */
+/* #define RE_INDIVIDUAL_SUBPIXELS */
+
+/* ------------------------------------------------------------------------- */
+
+static RE_APixstrExtMain RE_apsemfirst; /* pixstr bookkeeping var */
+static short RE_apsemteller = 0; /* pixstr bookkeeping var */
+static int RE_zbufferwidth; /* width of the z-buffer (pixels) */
+RE_APixstrExt *APixbufExt; /* Zbuffer: linked list of face, halo indices */
+
+/*-RE_APixstrExt------------------------------------------------------------ */
+
+void initZbuffer(int width)
+{
+ APixbufExt = MEM_callocN(RE_ZBUFLEN * width * sizeof(RE_APixstrExt),
+ "APixbufExt");
+ RE_zbufferwidth = width;
+ RE_apsemteller = 0;
+ RE_apsemfirst.next = NULL;
+ RE_apsemfirst.ps = NULL;
+} /* end of RE_APixstrExt *initZbufferDataStruct() */
+
+/* ------------------------------------------------------------------------- */
+
+void freeZbuffer(void)
+{
+ if (APixbufExt) MEM_freeN(APixbufExt);
+ freepseA();
+} /* end of void freeZbuffer(void) */
+
+/* ------------------------------------------------------------------------- */
+
+void resetZbuffer(void)
+{
+ int len;
+
+ freepseA();
+ len = sizeof(RE_APixstrExt) * RE_zbufferwidth * RE_ZBUFLEN;
+ memset(APixbufExt, 0, len);
+} /* end of void resetZbuffer(void) */
+
+/* ------------------------------------------------------------------------- */
+
+RE_APixstrExt *addpsemainA()
+{
+ RE_APixstrExtMain *psm;
+
+ psm= &RE_apsemfirst;
+
+ while(psm->next) {
+ psm= psm->next;
+ }
+
+ psm->next= MEM_callocN(sizeof(RE_APixstrExtMain), "addpsemainA");
+
+ psm= psm->next;
+
+ /* Initialise the new structure to safe values. Memory that is newly */
+ /* allocated must be zero... Not sure if that happens everywhere now.*/
+ psm->next=0;
+ psm->ps= MEM_callocN(4096*sizeof(RE_APixstrExt),"pixstrext");
+ RE_apsemteller= 0;
+
+ return psm->ps;
+} /* End of RE_APixstrExt *addpsemainA() */
+
+/* ------------------------------------------------------------------------- */
+
+void freepseA()
+{
+ RE_APixstrExtMain *psm, *next;
+
+ psm= &RE_apsemfirst;
+
+ while(psm) {
+ next= psm->next;
+ if(psm->ps) {
+ MEM_freeN(psm->ps);
+ psm->ps= 0;
+ }
+ if(psm!= &RE_apsemfirst) MEM_freeN(psm);
+ psm= next;
+ }
+
+ RE_apsemfirst.next= 0;
+ RE_apsemfirst.ps= 0;
+ RE_apsemteller= 0;
+} /* End of void freepseA() */
+
+/* ------------------------------------------------------------------------- */
+
+RE_APixstrExt *addpseA(void)
+{
+ static RE_APixstrExt *prev;
+
+ /* eerste PS maken */
+ if((RE_apsemteller & 4095)==0) prev= addpsemainA();
+ else prev++;
+ RE_apsemteller++;
+
+ return prev;
+} /* End of RE_APixstrExt *addpseA(void) */
+
+/* ------------------------------------------------------------------------- */
+
+void insertObject(int apteller,
+/* int opaque, */
+ int obindex,
+ int obtype,
+ int dist,
+ int mask)
+{
+ /* Guard the insertion if needed? */
+ RE_APixstrExt* apn = &APixbufExt[apteller];
+
+ while(apn) {
+ if(apn->t[0] == RE_NONE) {
+ apn->p[0] = obindex; apn->t[0] = obtype;
+ apn->zmin[0] = dist; apn->zmax[0] = dist;
+ apn->mask[0] = mask;
+ break;
+ }
+#ifndef RE_INDIVIDUAL_SUBPIXELS
+ if((apn->p[0] == obindex) && (apn->t[0] & obtype)) {
+ if(dist < apn->zmin[0]) apn->zmin[0] = dist;
+ else if(dist > apn->zmax[0]) apn->zmax[0] = dist;
+ apn->mask[0]|= mask;
+ break;
+ }
+#endif
+ if(apn->t[1] == RE_NONE) {
+ apn->p[1] = obindex; apn->t[1] = obtype;
+ apn->zmin[1] = dist; apn->zmax[1] = dist;
+ apn->mask[1] = mask;
+ break;
+ }
+#ifndef RE_INDIVIDUAL_SUBPIXELS
+ if((apn->p[1] == obindex) && (apn->t[1] & obtype)) {
+ if(dist < apn->zmin[1]) apn->zmin[1] = dist;
+ else if(dist > apn->zmax[1]) apn->zmax[1] = dist;
+ apn->mask[1]|= mask;
+ break;
+ }
+#endif
+ if(apn->t[2] == RE_NONE) {
+ apn->p[2] = obindex; apn->t[2] = obtype;
+ apn->zmin[2] = dist; apn->zmax[2] = dist;
+ apn->mask[2] = mask;
+ break;
+ }
+#ifndef RE_INDIVIDUAL_SUBPIXELS
+ if((apn->p[2] == obindex) && (apn->t[2] & obtype)) {
+ if(dist < apn->zmin[2]) apn->zmin[2] = dist;
+ else if(dist > apn->zmax[2]) apn->zmax[2] = dist;
+ apn->mask[2]|= mask;
+ break;
+ }
+#endif
+ if(apn->t[3] == RE_NONE) {
+ apn->p[3] = obindex; apn->t[3] = obtype;
+ apn->zmin[3] = dist; apn->zmax[3] = dist;
+ apn->mask[3] = mask;
+ break;
+ }
+#ifndef RE_INDIVIDUAL_SUBPIXELS
+ if((apn->p[3] == obindex) && (apn->t[3] & obtype)) {
+ if(dist < apn->zmin[3]) apn->zmin[3] = dist;
+ else if(dist > apn->zmax[3]) apn->zmax[3] = dist;
+ apn->mask[3]|= mask;
+ break;
+ }
+#endif
+ if(apn->next==0) apn->next= addpseA();
+ apn= apn->next;
+ }
+} /* end of insertObject(RE_APixstrExt*, int, int, int, int) */
+
+/* ------------------------------------------------------------------------- */
+
+void insertFlatObject(RE_APixstrExt *apn, int obindex, int obtype, int dist, int mask)
+{
+ while(apn) {
+ if(apn->t[0] == RE_NONE) {
+ apn->p[0] = obindex; apn->zmin[0] = dist;
+ apn->zmax[0] = dist; apn->mask[0] = mask;
+ apn->t[0] = obtype;
+ break;
+ }
+#ifndef RE_INDIVIDUAL_SUBPIXELS
+ if( (apn->t[0] & obtype) && (apn->p[0] == obindex)) {
+ apn->mask[0]|= mask; break;
+ }
+#endif
+ if(apn->t[1] == RE_NONE) {
+ apn->p[1] = obindex; apn->zmin[1] = dist;
+ apn->zmax[1] = dist; apn->mask[1] = mask;
+ apn->t[1] = obtype;
+ break;
+ }
+#ifndef RE_INDIVIDUAL_SUBPIXELS
+ if( (apn->t[1] & obtype) && (apn->p[1] == obindex)) {
+ apn->mask[1]|= mask; break;
+ }
+#endif
+ if(apn->t[2] == RE_NONE) {
+ apn->p[2] = obindex; apn->zmin[2] = dist;
+ apn->zmax[2] = dist; apn->mask[2] = mask;
+ apn->t[2] = obtype;
+ break;
+ }
+#ifndef RE_INDIVIDUAL_SUBPIXELS
+ if( (apn->t[2] & obtype) && (apn->p[2] == obindex)) {
+ apn->mask[2]|= mask; break;
+ }
+#endif
+ if(apn->t[3] == RE_NONE) {
+ apn->p[3] = obindex; apn->zmin[3] = dist;
+ apn->zmax[3] = dist; apn->mask[3] = mask;
+ apn->t[3] = obtype;
+ break;
+ }
+#ifndef RE_INDIVIDUAL_SUBPIXELS
+ if( (apn->t[3] & obtype) && (apn->p[3] == obindex)) {
+ apn->mask[3]|= mask; break;
+ }
+#endif
+ if(apn->next==0) apn->next= addpseA();
+ apn= apn->next;
+ };
+} /* end of void insertFlatObject(RE_APixstrExt, int, int, int, int)*/
+
+/* ------------------------------------------------------------------------- */
+/* This function might be helped by an end-of-list marker */
+void insertFlatObjectNoOsa(RE_APixstrExt *ap,
+ int obindex,
+ int obtype,
+ int dist,
+ int mask)
+{
+ while(ap) {
+ if(ap->t[0] == RE_NONE) {
+ ap->p[0] = obindex; ap->zmin[0] = dist;
+ ap->zmax[0] = dist; ap->mask[0] = mask;
+ ap->t[0] = obtype;
+ break;
+ }
+
+ if(ap->t[1] == RE_NONE) {
+ ap->p[1] = obindex; ap->zmin[1] = dist;
+ ap->zmax[1] = dist; ap->mask[1] = mask;
+ ap->t[1] = obtype;
+ break;
+ }
+
+ if(ap->t[2] == RE_NONE) {
+ ap->p[2] = obindex; ap->zmin[2] = dist;
+ ap->zmax[2] = dist; ap->mask[2] = mask;
+ ap->t[2] = obtype;
+ break;
+ }
+
+ if(ap->t[3] == RE_NONE) {
+ ap->p[3] = obindex; ap->zmin[3] = dist;
+ ap->zmax[3] = dist; ap->mask[3] = mask;
+ ap->t[3] = obtype;
+ break;
+ }
+
+ if(ap->next==0) ap->next= addpseA();
+ ap= ap->next;
+ };
+} /* end of void insertFlatObjectNoOsa(RE_APixstrExt, int, int, int, int)*/
+
+/* ------------------------------------------------------------------------- */
+
+/* EOF */
diff --git a/source/blender/renderconverter/Makefile b/source/blender/renderconverter/Makefile
new file mode 100644
index 00000000000..0d65772b72b
--- /dev/null
+++ b/source/blender/renderconverter/Makefile
@@ -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 *****
+#
+# Bounces make to subdirectories.
+
+SOURCEDIR = source/blender/renderconverter
+DIRS = intern
+
+include nan_subdirs.mk
diff --git a/source/blender/renderconverter/RE_renderconverter.h b/source/blender/renderconverter/RE_renderconverter.h
new file mode 100644
index 00000000000..9d90e0f03fa
--- /dev/null
+++ b/source/blender/renderconverter/RE_renderconverter.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 *****
+ * Interface to transform the Blender scene into renderable data.
+ *
+ * @mainpage RE - Blender RE-converter external interface
+ *
+ * @section about About the RE-converter module
+ *
+ * The converter takes a Blender scene, and transforms the data into
+ * renderer-specific data.
+ *
+ * Conversions:
+ *
+ * halos: (world settings) stars ->
+ * some particle effects ->
+ * meshes with halo prop ->
+ * HaloRen (made by inithalo)
+ *
+ *
+ * VlakRen (face render data)
+ * Each vlakren needs several VertRens to make sense.
+ * VertRen (vertex render data)
+ *
+ * @section issues Known issues with RE-converter
+ *
+ *
+ * @section dependencies Dependencies
+ *
+ *
+ * */
+
+#ifndef RE_RENDERCONVERTER_H
+#define RE_RENDERCONVERTER_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ struct LampRen;
+ struct Object;
+ struct Lamp;
+
+ /** Transform a blender scene to render data. */
+ void RE_rotateBlenderScene(void);
+
+ /** Free all memory used for the conversion. */
+ void RE_freeRotateBlenderScene(void);
+
+ /**
+ * Used by the preview renderer.
+ */
+ void RE_add_render_lamp(struct Object *ob, int doshadbuf);
+
+ /**
+ * Strange support for star rendering for drawview.c... For
+ * rendering purposes, these function pointers should be NULL.
+ */
+ void RE_make_stars(void (*initfunc)(void),
+ void (*vertexfunc)(float*),
+ void (*termfunc)(void));
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+
diff --git a/source/blender/renderconverter/intern/Makefile b/source/blender/renderconverter/intern/Makefile
new file mode 100644
index 00000000000..b5680e0cba8
--- /dev/null
+++ b/source/blender/renderconverter/intern/Makefile
@@ -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 *****
+#
+#
+
+LIBNAME = renderconverter
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+ifeq ($(OS),$(findstring $(OS), "beos darwin freebsd linux openbsd solaris windows"))
+ CFLAGS += -funsigned-char
+endif
+
+CFLAGS += $(LEVEL_2_C_WARNINGS)
+
+CPPFLAGS += -I$(OPENGL_HEADERS)
+# path to our own external headerfiles
+CPPFLAGS += -I..
+# not very neat: the dirs for external modules
+CPPFLAGS += -I../../render/extern/include
+CPPFLAGS += -I../../bpython/include
+CPPFLAGS += -I../../blenkernel
+CPPFLAGS += -I../../blenlib
+CPPFLAGS += -I../../makesdna
+CPPFLAGS += -I../../include
+CPPFLAGS += -I../../misc
+CPPFLAGS += -I../../
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
diff --git a/source/blender/renderconverter/intern/convertBlenderScene.c b/source/blender/renderconverter/intern/convertBlenderScene.c
new file mode 100644
index 00000000000..2b08f4d131d
--- /dev/null
+++ b/source/blender/renderconverter/intern/convertBlenderScene.c
@@ -0,0 +1,2943 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * Interface to transform the Blender scene into renderable data.
+ */
+
+/* check for dl->flag, 1 or 2 should be replaced be the def's below */
+#define STRUBI hack
+#define DL_CYCLIC_U 1
+#define DL_CYCLIC_V 2
+
+#include <math.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <limits.h> /* for INT_MAX */
+
+#include "MTC_matrixops.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+#include "BLI_rand.h"
+
+#include "DNA_scene_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_material_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_lattice_types.h"
+#include "DNA_effect_types.h"
+#include "DNA_ika_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_object_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_mesh_types.h"
+
+#include "BKE_mesh.h"
+#include "BKE_key.h"
+#include "BKE_action.h"
+#include "BKE_curve.h"
+#include "BKE_armature.h"
+#include "BKE_object.h"
+#include "BKE_texture.h"
+#include "BKE_material.h"
+#include "BKE_main.h"
+#include "BKE_mball.h"
+#include "BKE_anim.h"
+#include "BKE_global.h"
+#include "BKE_effect.h"
+#include "BKE_world.h"
+#include "BKE_ipo.h"
+#include "BKE_ika.h"
+#include "BKE_displist.h"
+#include "BKE_lattice.h"
+#include "BKE_constraint.h"
+#include "BKE_utildefines.h"
+#include "BKE_subsurf.h"
+#include "BKE_world.h"
+
+#include "render.h"
+
+#include "RE_renderconverter.h"
+#include "blendertimer.h" /* MISC_test_break */
+
+#include "BIF_space.h"
+#include "BIF_editkey.h"
+
+#include "BSE_sequence.h"
+
+#include "BPY_extern.h"
+
+#include "nla.h"
+
+/* ------------------------------------------------------------------------- */
+/* Local functions */
+/* ------------------------------------------------------------------------- */
+static Material *give_render_material(Object *ob, int nr);
+
+
+
+/* blenderWorldManipulation.c */
+static void split_u_renderfaces(int startvlak, int startvert, int usize, int plek, int cyclu);
+static void split_v_renderfaces(int startvlak, int startvert, int usize, int vsize, int plek, int cyclu, int cyclv);
+static int contrpuntnormr(float *n, float *puno);
+static void normalenrender(int startvert, int startvlak);
+static void as_addvert(VertRen *v1, VlakRen *vlr);
+static void as_freevert(VertRen *ver);
+static void autosmooth(int startvert, int startvlak, int degr);
+static void make_render_halos(Object *ob, Mesh *me, Material *ma, float *extverts);
+static int mesh_test_flipnorm(Object *ob, MFace *mface, VlakRen *vlr, float imat[][3]);
+static void render_particle_system(Object *ob, PartEff *paf);
+static void render_static_particle_system(Object *ob, PartEff *paf);
+static void init_render_displist_mesh(Object *ob);
+static int verghalo(const void *a1, const void *a2);
+static void sort_halos(void);
+static void init_render_mball(Object *ob);
+static void init_render_mesh(Object *ob);
+static void init_render_surf(Object *ob);
+static void init_render_curve(Object *ob);
+static int test_flipnorm(float *v1, float *v2, float *v3, VlakRen *vlr, float imat[][3]);
+static void init_render_object(Object *ob);
+static HaloRen *initstar(float *vec, float hasize);
+
+/* more prototypes for autosmoothing below */
+
+
+/* ------------------------------------------------------------------------- */
+/* tool functions/defines for ad hoc simplification and possible future
+ cleanup */
+/* ------------------------------------------------------------------------- */
+
+#define UVTOINDEX(u,v) (startvlak + (u) * sizev + (v))
+#define GETNORMAL(face,normal) CalcNormFloat4(face->v1->co, face->v2->co, face->v3->co, face->v4->co, normal)
+/*
+
+NOTE THAT U/V COORDINATES ARE SOMETIMES SWAPPED !!
+
+^ ()----p4----p3----()
+| | | | |
+u | | F1 | F2 |
+ | | | |
+ ()----p1----p2----()
+ v ->
+*/
+
+/* ------------------------------------------------------------------------- */
+
+/* Stuff for stars. This sits here because it uses gl-things. Part of
+ this code may move down to the converter. */
+/* ------------------------------------------------------------------------- */
+/* this is a bad beast, since it is misused by the 3d view drawing as well. */
+
+extern unsigned char hash[512];
+
+/* - er moet een 'vast' aantal sterren gegenereerd worden tussen near en far.
+ * - alle sterren moeten bij voorkeur op de far liggen en uitsluitend in
+ * helderheid / kleur verschillen.
+ * -
+ */
+
+void RE_make_stars(void (*initfunc)(void),
+ void (*vertexfunc)(float*),
+ void (*termfunc)(void))
+{
+ HaloRen *har;
+ double dblrand, hlfrand;
+ float vec[4], fx, fy, fz;
+ float fac, starmindist, clipend;
+ float mat[4][4], stargrid, maxrand, force, alpha;
+/* float loc_far_var, loc_near_var; */
+ int x, y, z, sx, sy, sz, ex, ey, ez, maxjit, done = 0;
+ Camera * camera;
+
+ if(initfunc) R.wrld= *(G.scene->world);
+
+ stargrid = R.wrld.stardist; /* om de hoeveel een ster ? */
+ maxrand = 2.0; /* hoeveel mag een ster verschuiven (uitgedrukt in grid eenheden) */
+ maxjit = (256.0* R.wrld.starcolnoise); /* hoeveel mag een kleur veranderen */
+
+/* loc_far_var = R.far; */
+/* loc_near_var = R.near; */
+
+
+ /* afmeting sterren */
+ force = ( R.wrld.starsize );
+
+ /* minimale vrije ruimte */
+ starmindist= R.wrld.starmindist;
+
+ if (stargrid <= 0.10) return;
+
+ if (!initfunc) R.flag |= R_HALO;
+ else stargrid *= 1.0; /* tekent er minder */
+
+
+ MTC_Mat4Invert(mat, R.viewmat);
+
+ /* BOUNDINGBOX BEREKENING
+ * bbox loopt van z = loc_near_var | loc_far_var,
+ * x = -z | +z,
+ * y = -z | +z
+ */
+
+ camera = G.scene->camera->data;
+ clipend = camera->clipend;
+
+ /* omzetten naar grid coordinaten */
+
+ sx = ((mat[3][0] - clipend) / stargrid) - maxrand;
+ sy = ((mat[3][1] - clipend) / stargrid) - maxrand;
+ sz = ((mat[3][2] - clipend) / stargrid) - maxrand;
+
+ ex = ((mat[3][0] + clipend) / stargrid) + maxrand;
+ ey = ((mat[3][1] + clipend) / stargrid) + maxrand;
+ ez = ((mat[3][2] + clipend) / stargrid) + maxrand;
+
+ dblrand = maxrand * stargrid;
+ hlfrand = 2.0 * dblrand;
+
+ if (initfunc) {
+ initfunc();
+ }
+
+ for (x = sx, fx = sx * stargrid; x <= ex; x++, fx += stargrid) {
+ for (y = sy, fy = sy * stargrid; y <= ey ; y++, fy += stargrid) {
+ for (z = sz, fz = sz * stargrid; z <= ez; z++, fz += stargrid) {
+
+ BLI_srand((hash[z & 0xff] << 24) + (hash[y & 0xff] << 16) + (hash[x & 0xff] << 8));
+ vec[0] = fx + (hlfrand * BLI_drand()) - dblrand;
+ vec[1] = fy + (hlfrand * BLI_drand()) - dblrand;
+ vec[2] = fz + (hlfrand * BLI_drand()) - dblrand;
+ vec[3] = 1.0;
+
+ if (vertexfunc) {
+ if(done & 1) vertexfunc(vec);
+ done++;
+ }
+ else {
+ MTC_Mat4MulVecfl(R.viewmat, vec);
+
+ /* in vec staan globale coordinaten
+ * bereken afstand tot de kamera
+ * en bepaal aan de hand daarvan de alpha
+ */
+
+ {
+ float tx, ty, tz;
+
+ tx = vec[0];
+ ty = vec[1];
+ tz = vec[2];
+
+ alpha = sqrt(tx * tx + ty * ty + tz * tz);
+
+ if (alpha >= clipend) alpha = 0.0;
+ else if (alpha <= starmindist) alpha = 0.0;
+ else if (alpha <= 2.0 * starmindist) {
+ alpha = (alpha - starmindist) / starmindist;
+ } else {
+ alpha -= 2.0 * starmindist;
+ alpha /= (clipend - 2.0 * starmindist);
+ alpha = 1.0 - alpha;
+ }
+ }
+
+
+ if (alpha != 0.0) {
+ fac = force * BLI_drand();
+
+ har = initstar(vec, fac);
+
+ if (har) {
+ har->alfa = sqrt(sqrt(alpha));
+ har->add= 255;
+ har->r = har->g = har->b = 255;
+ if (maxjit) {
+ har->r += ((maxjit * BLI_drand()) ) - maxjit;
+ har->g += ((maxjit * BLI_drand()) ) - maxjit;
+ har->b += ((maxjit * BLI_drand()) ) - maxjit;
+ }
+ har->hard = 32;
+
+ har->type |= HA_ONLYSKY;
+ done++;
+ }
+ }
+ }
+ }
+ if(done > MAXVERT) {
+ printf("Too many stars\n");
+ break;
+ }
+ if(MISC_test_break()) break;
+ }
+ if(done > MAXVERT) break;
+
+ if(MISC_test_break()) break;
+ }
+ if (termfunc) termfunc();
+}
+
+/* ------------------------------------------------------------------------ */
+/* more star stuff */
+static HaloRen *initstar(float *vec, float hasize)
+{
+ HaloRen *har;
+ float hoco[4];
+
+ RE_projectverto(vec, hoco);
+
+ if( (R.r.mode & R_PANORAMA) || RE_testclip(hoco)==0 ) {
+ har= RE_findOrAddHalo(R.tothalo++);
+
+ /* projectvert wordt in zbufvlaggen overgedaan ivm parts */
+ VECCOPY(har->co, vec);
+ har->hasize= hasize;
+
+ har->zd= 0.0;
+
+ return har;
+ }
+ return NULL;
+}
+
+
+
+/* ------------------------------------------------------------------------- */
+
+static void split_u_renderfaces(int startvlak, int startvert, int usize, int plek, int cyclu)
+{
+ VlakRen *vlr;
+ VertRen *v1, *v2;
+ int a, v;
+
+ if(cyclu) cyclu= 1;
+
+ /* geef eerst alle betreffende vertices een pointer naar de nieuwe mee */
+ v= startvert+ plek*usize;
+ for(a=0; a<usize; a++) {
+ v2= RE_findOrAddVert(R.totvert++);
+ v1= RE_findOrAddVert(v++);
+ *v2= *v1;
+ v1->sticky= (float *)v2;
+ }
+
+ /* loop betreffende vlakken af en vervang pointers */
+ v= startvlak+plek*(usize-1+cyclu);
+ for(a=1-cyclu; a<usize; a++) {
+ vlr= RE_findOrAddVlak(v++);
+ vlr->v1= (VertRen *)(vlr->v1->sticky);
+ vlr->v2= (VertRen *)(vlr->v2->sticky);
+ }
+
+}
+
+/* ------------------------------------------------------------------------- */
+
+static void split_v_renderfaces(int startvlak, int startvert, int usize, int vsize, int plek, int cyclu, int cyclv)
+{
+ VlakRen *vlr;
+ VertRen *v1=0;
+ int a, vlak, ofs;
+
+ if(vsize<2) return;
+
+ /* loop betreffende vlakken af en maak dubbels */
+ /* omdat (evt) split_u al gedaan is kan niet met vertex->sticky pointers worden gewerkt */
+ /* want vlakken delen al geen punten meer */
+
+ if(plek+cyclu==usize) plek= -1;
+
+ vlak= startvlak+(plek+cyclu);
+ ofs= (usize-1+cyclu);
+
+ for(a=1; a<vsize; a++) {
+
+ vlr= RE_findOrAddVlak(vlak);
+ if (vlr->v1 == 0) return; /* OEPS, als niet cyclic */
+
+ v1= RE_findOrAddVert(R.totvert++);
+ *v1= *(vlr->v1);
+
+ vlr->v1= v1;
+
+ /* vlr= findOrAddVlak(vlak+1); */
+ /* vlr->v1= v1; */
+
+ if(a>1) {
+ vlr= RE_findOrAddVlak(vlak-ofs);
+ if(vlr->v4->sticky) {
+ v1= RE_findOrAddVert(R.totvert++);
+ *v1= *(vlr->v4);
+ vlr->v4= v1;
+ }
+ else vlr->v4= v1;
+ }
+
+ if(a== vsize-1) {
+ if(cyclv) {
+ ;
+ }
+ else {
+ vlr= RE_findOrAddVlak(vlak);
+ v1= RE_findOrAddVert(R.totvert++);
+ *v1= *(vlr->v4);
+ vlr->v4= v1;
+ }
+ }
+
+ vlak+= ofs;
+ }
+
+}
+
+/* ------------------------------------------------------------------------- */
+
+static int contrpuntnormr(float *n, float *puno)
+{
+ float inp;
+
+ inp=n[0]*puno[0]+n[1]*puno[1]+n[2]*puno[2];
+ if(inp<0.0) return 1;
+ return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static void normalenrender(int startvert, int startvlak)
+{
+ VlakRen *vlr;
+ VertRen *ver, *adrve1, *adrve2, *adrve3, *adrve4;
+ float n1[3], n2[3], n3[3], n4[3], *adrco, *tfl, fac, *temp;
+ int a;
+
+ if(R.totvlak==0 || R.totvert==0) return;
+ if(startvert==R.totvert || startvlak==R.totvlak) return;
+
+ adrco= (float *)MEM_callocN(12+4*sizeof(float)*(R.totvlak-startvlak), "normalen1");
+
+ tfl= adrco;
+ /* berekenen cos hoeken en puntmassa's */
+ for(a= startvlak; a<R.totvlak; a++) {
+ vlr= RE_findOrAddVlak(a);
+
+ adrve1= vlr->v1;
+ adrve2= vlr->v2;
+ adrve3= vlr->v3;
+ adrve4= vlr->v4;
+
+ VecSubf(n1, adrve2->co, adrve1->co);
+ Normalise(n1);
+ VecSubf(n2, adrve3->co, adrve2->co);
+ Normalise(n2);
+ if(adrve4==0) {
+ VecSubf(n3, adrve1->co, adrve3->co);
+ Normalise(n3);
+
+ *(tfl++)= saacos(-n1[0]*n3[0]-n1[1]*n3[1]-n1[2]*n3[2]);
+ *(tfl++)= saacos(-n1[0]*n2[0]-n1[1]*n2[1]-n1[2]*n2[2]);
+ *(tfl++)= saacos(-n2[0]*n3[0]-n2[1]*n3[1]-n2[2]*n3[2]);
+ }
+ else {
+ VecSubf(n3, adrve4->co, adrve3->co);
+ Normalise(n3);
+ VecSubf(n4, adrve1->co, adrve4->co);
+ Normalise(n4);
+
+ *(tfl++)= saacos(-n4[0]*n1[0]-n4[1]*n1[1]-n4[2]*n1[2]);
+ *(tfl++)= saacos(-n1[0]*n2[0]-n1[1]*n2[1]-n1[2]*n2[2]);
+ *(tfl++)= saacos(-n2[0]*n3[0]-n2[1]*n3[1]-n2[2]*n3[2]);
+ *(tfl++)= saacos(-n3[0]*n4[0]-n3[1]*n4[1]-n3[2]*n4[2]);
+ }
+ }
+
+ /* alle puntnormalen leegmaken */
+ for(a=startvert; a<R.totvert; a++) {
+ ver= RE_findOrAddVert(a);
+
+ ver->n[0]=ver->n[1]=ver->n[2]= 0.0;
+ }
+
+ /* berekenen normalen en optellen bij puno's */
+ tfl= adrco;
+ for(a=startvlak; a<R.totvlak; a++) {
+ vlr= RE_findOrAddVlak(a);
+
+ adrve1= vlr->v1;
+ adrve2= vlr->v2;
+ adrve3= vlr->v3;
+ adrve4= vlr->v4;
+
+ temp= adrve1->n;
+ fac= *(tfl++);
+ if( vlr->flag & R_NOPUNOFLIP);
+ else if( contrpuntnormr(vlr->n, temp) ) fac= -fac ;
+ *(temp++) +=fac*vlr->n[0];
+ *(temp++) +=fac*vlr->n[1];
+ *(temp) +=fac*vlr->n[2];
+
+ temp= adrve2->n;
+ fac= *(tfl++);
+ if( vlr->flag & R_NOPUNOFLIP);
+ else if( contrpuntnormr(vlr->n, temp) ) fac= -fac ;
+ *(temp++) +=fac*vlr->n[0];
+ *(temp++) +=fac*vlr->n[1];
+ *(temp) +=fac*vlr->n[2];
+
+ temp= adrve3->n;
+ fac= *(tfl++);
+ if( vlr->flag & R_NOPUNOFLIP);
+ else if( contrpuntnormr(vlr->n, temp) ) fac= -fac ;
+ *(temp++) +=fac*vlr->n[0];
+ *(temp++) +=fac*vlr->n[1];
+ *(temp) +=fac*vlr->n[2];
+
+ if(adrve4) {
+ temp= adrve4->n;
+ fac= *(tfl++);
+ if( vlr->flag & R_NOPUNOFLIP);
+ else if( contrpuntnormr(vlr->n, temp) ) fac= -fac ;
+ *(temp++) +=fac*vlr->n[0];
+ *(temp++) +=fac*vlr->n[1];
+ *(temp) +=fac*vlr->n[2];
+ }
+ }
+
+ /* normaliseren puntnormalen */
+ for(a=startvert; a<R.totvert; a++) {
+ ver= RE_findOrAddVert(a);
+
+ Normalise(ver->n);
+ }
+
+ /* puntnormaal omklap-vlaggen voor bij shade */
+ for(a=startvlak; a<R.totvlak; a++) {
+ vlr= RE_findOrAddVlak(a);
+
+ if((vlr->flag & R_NOPUNOFLIP)==0) {
+ adrve1= vlr->v1;
+ adrve2= vlr->v2;
+ adrve3= vlr->v3;
+ adrve4= vlr->v4;
+
+ vlr->puno= 0;
+ fac= vlr->n[0]*adrve1->n[0]+vlr->n[1]*adrve1->n[1]+vlr->n[2]*adrve1->n[2];
+ if(fac<0.0) vlr->puno= 1;
+ fac= vlr->n[0]*adrve2->n[0]+vlr->n[1]*adrve2->n[1]+vlr->n[2]*adrve2->n[2];
+ if(fac<0.0) vlr->puno+= 2;
+ fac= vlr->n[0]*adrve3->n[0]+vlr->n[1]*adrve3->n[1]+vlr->n[2]*adrve3->n[2];
+ if(fac<0.0) vlr->puno+= 4;
+
+ if(adrve4) {
+ fac= vlr->n[0]*adrve4->n[0]+vlr->n[1]*adrve4->n[1]+vlr->n[2]*adrve4->n[2];
+ if(fac<0.0) vlr->puno+= 8;
+ }
+ }
+ }
+
+ MEM_freeN(adrco);
+}
+
+/* ------------------------------------------------------------------------- */
+/* Autosmoothing: */
+/* ------------------------------------------------------------------------- */
+
+typedef struct ASvert {
+ int totface;
+ ListBase faces;
+} ASvert;
+
+typedef struct ASface {
+ struct ASface *next, *prev;
+ VlakRen *vlr[4];
+ VertRen *nver[4];
+} ASface;
+
+/* prototypes: */
+static int as_testvertex(VlakRen *vlr, VertRen *ver, ASvert *asv, float thresh);
+static VertRen *as_findvertex(VlakRen *vlr, VertRen *ver, ASvert *asv, float thresh);
+
+
+static void as_addvert(VertRen *v1, VlakRen *vlr)
+{
+ ASvert *asv;
+ ASface *asf;
+ int a;
+
+ if(v1 == NULL) return;
+
+ if(v1->svert==0) {
+ v1->svert= MEM_callocN(sizeof(ASvert), "asvert");
+ asv= v1->svert;
+ asf= MEM_callocN(sizeof(ASface), "asface");
+ BLI_addtail(&asv->faces, asf);
+ }
+
+ asv= v1->svert;
+ asf= asv->faces.last;
+ for(a=0; a<4; a++) {
+ if(asf->vlr[a]==0) {
+ asf->vlr[a]= vlr;
+ asv->totface++;
+ break;
+ }
+ }
+
+ /* new face struct */
+ if(a==4) {
+ asf= MEM_callocN(sizeof(ASface), "asface");
+ BLI_addtail(&asv->faces, asf);
+ asf->vlr[0]= vlr;
+ asv->totface++;
+ }
+}
+
+static void as_freevert(VertRen *ver)
+{
+ ASvert *asv;
+
+ asv= ver->svert;
+ BLI_freelistN(&asv->faces);
+ MEM_freeN(asv);
+ ver->svert= NULL;
+}
+
+static int as_testvertex(VlakRen *vlr, VertRen *ver, ASvert *asv, float thresh)
+{
+ /* return 1: vertex needs a copy */
+ ASface *asf;
+ float inp;
+ int a;
+
+ if(vlr==0) return 0;
+
+ asf= asv->faces.first;
+ while(asf) {
+ for(a=0; a<4; a++) {
+ if(asf->vlr[a] && asf->vlr[a]!=vlr) {
+ inp= fabs( vlr->n[0]*asf->vlr[a]->n[0] + vlr->n[1]*asf->vlr[a]->n[1] + vlr->n[2]*asf->vlr[a]->n[2] );
+ if(inp < thresh) return 1;
+ }
+ }
+ asf= asf->next;
+ }
+
+ return 0;
+}
+
+static VertRen *as_findvertex(VlakRen *vlr, VertRen *ver, ASvert *asv, float thresh)
+{
+ /* return when new vertex already was made */
+ ASface *asf;
+ float inp;
+ int a;
+
+ asf= asv->faces.first;
+ while(asf) {
+ for(a=0; a<4; a++) {
+ if(asf->vlr[a] && asf->vlr[a]!=vlr) {
+ /* this face already made a copy for this vertex! */
+ if(asf->nver[a]) {
+ inp= fabs( vlr->n[0]*asf->vlr[a]->n[0] + vlr->n[1]*asf->vlr[a]->n[1] + vlr->n[2]*asf->vlr[a]->n[2] );
+ if(inp >= thresh) {
+ return asf->nver[a];
+ }
+ }
+ }
+ }
+ asf= asf->next;
+ }
+
+ return NULL;
+}
+
+static void autosmooth(int startvert, int startvlak, int degr)
+{
+ ASvert *asv;
+ ASface *asf;
+ VertRen *ver, *v1;
+ VlakRen *vlr;
+ float thresh;
+ int a, b, totvert;
+
+ thresh= cos( M_PI*((float)degr)/180.0 );
+
+ /* initialize */
+ for(a=startvert; a<R.totvert; a++) {
+ ver= RE_findOrAddVert(a);
+ ver->svert= 0;
+ }
+
+ /* step one: construct listbase of all vertices and pointers to faces */
+ for(a=startvlak; a<R.totvlak; a++) {
+ vlr= RE_findOrAddVlak(a);
+
+ as_addvert(vlr->v1, vlr);
+ as_addvert(vlr->v2, vlr);
+ as_addvert(vlr->v3, vlr);
+ as_addvert(vlr->v4, vlr);
+ }
+
+ /* we now test all vertices, when faces have a normal too much different: they get a new vertex */
+ totvert= R.totvert;
+ for(a=startvert; a<totvert; a++) {
+ ver= RE_findOrAddVert(a);
+ asv= ver->svert;
+ if(asv && asv->totface>1) {
+
+ asf= asv->faces.first;
+ while(asf) {
+ for(b=0; b<4; b++) {
+
+ /* is there a reason to make a new vertex? */
+ vlr= asf->vlr[b];
+ if( as_testvertex(vlr, ver, asv, thresh) ) {
+
+ /* already made a new vertex within threshold? */
+ v1= as_findvertex(vlr, ver, asv, thresh);
+ if(v1==0) {
+ /* make a new vertex */
+ v1= RE_findOrAddVert(R.totvert++);
+ *v1= *ver;
+ v1->svert= 0;
+ }
+ asf->nver[b]= v1;
+ if(vlr->v1==ver) vlr->v1= v1;
+ if(vlr->v2==ver) vlr->v2= v1;
+ if(vlr->v3==ver) vlr->v3= v1;
+ if(vlr->v4==ver) vlr->v4= v1;
+ }
+ }
+ asf= asf->next;
+ }
+ }
+ }
+
+ /* free */
+ for(a=startvert; a<R.totvert; a++) {
+ ver= RE_findOrAddVert(a);
+ if(ver->svert) as_freevert(ver);
+ }
+
+}
+
+/* ------------------------------------------------------------------------- */
+/* End of autosmoothing: */
+/* ------------------------------------------------------------------------- */
+
+static void make_render_halos(Object *ob, Mesh *me, Material *ma, float *extverts)
+{
+ HaloRen *har;
+ MVert *mvert;
+ float xn, yn, zn, nor[3], view[3];
+ float *orco, vec[3], hasize, mat[4][4], imat[3][3];
+ int start, end, a, ok;
+
+ MTC_Mat4MulMat4(mat, ob->obmat, R.viewmat);
+ MTC_Mat3CpyMat4(imat, ob->imat);
+
+ R.flag |= R_HALO;
+ mvert= me->mvert;
+
+ orco= me->orco;
+
+ start= 0;
+ end= me->totvert;
+ set_buildvars(ob, &start, &end);
+ mvert+= start;
+ if(extverts) extverts+= 3*start;
+
+ ma->ren->seed1= ma->seed1;
+
+ for(a=start; a<end; a++, mvert++) {
+ ok= 1;
+
+ if(ok) {
+ hasize= ma->hasize;
+
+ if(extverts) {
+ VECCOPY(vec, extverts);
+ extverts+= 3;
+ }
+ else {
+ VECCOPY(vec, mvert->co);
+ }
+ MTC_Mat4MulVecfl(mat, vec);
+
+ if(ma->mode & MA_HALOPUNO) {
+ xn= mvert->no[0];
+ yn= mvert->no[1];
+ zn= mvert->no[2];
+
+ /* transpose ! */
+ nor[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn;
+ nor[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn;
+ nor[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn;
+ Normalise(nor);
+
+ VECCOPY(view, vec);
+ Normalise(view);
+
+ zn= nor[0]*view[0]+nor[1]*view[1]+nor[2]*view[2];
+ if(zn>=0.0) hasize= 0.0;
+ else hasize*= zn*zn*zn*zn;
+ }
+
+ if(orco) har= RE_inithalo(ma, vec, 0, orco, hasize, 0);
+ else har= RE_inithalo(ma, vec, 0, mvert->co, hasize, 0);
+ if(har) har->lay= ob->lay;
+ }
+ if(orco) orco+= 3;
+ ma->ren->seed1++;
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
+static int test_flipnorm(float *v1, float *v2, float *v3, VlakRen *vlr, float imat[][3])
+{
+ float nor[3], vec[3];
+ float xn;
+
+ CalcNormFloat(v1, v2, v3, nor);
+ vec[0]= imat[0][0]*nor[0]+ imat[0][1]*nor[1]+ imat[0][2]*nor[2];
+ vec[1]= imat[1][0]*nor[0]+ imat[1][1]*nor[1]+ imat[1][2]*nor[2];
+ vec[2]= imat[2][0]*nor[0]+ imat[2][1]*nor[1]+ imat[2][2]*nor[2];
+
+ xn= vec[0]*vlr->n[0]+vec[1]*vlr->n[1]+vec[2]*vlr->n[2];
+
+ return (xn<0.0);
+}
+
+static int mesh_test_flipnorm(Object *ob, MFace *mface, VlakRen *vlr, float imat[][3])
+{
+ DispList *dl;
+ Mesh *me= ob->data;
+ float *v1, *v2, *v3;
+
+ dl= find_displist(&ob->disp, DL_VERTS);
+ if(dl) {
+ v1= dl->verts + 3*mface->v1;
+ v2= dl->verts + 3*mface->v2;
+ v3= dl->verts + 3*mface->v3;
+ }
+ else {
+ v1= (me->mvert+mface->v1)->co;
+ v2= (me->mvert+mface->v2)->co;
+ v3= (me->mvert+mface->v3)->co;
+ }
+
+ return test_flipnorm(v1, v2, v3, vlr, imat);
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+
+
+/* ------------------------------------------------------------------------- */
+
+static void render_particle_system(Object *ob, PartEff *paf)
+{
+ Particle *pa=0;
+ HaloRen *har=0;
+ Material *ma=0;
+ float xn, yn, zn, imat[3][3], mat[4][4], hasize, ptime, ctime, vec[3], vec1[3], view[3], nor[3];
+ int a, mat_nr=1;
+
+ pa= paf->keys;
+ if(pa==0) {
+ build_particle_system(ob);
+ pa= paf->keys;
+ if(pa==0) return;
+ }
+
+ ma= give_render_material(ob, 1);
+ if(ma==0) ma= &defmaterial;
+
+ MTC_Mat4MulMat4(mat, ob->obmat, R.viewmat);
+ MTC_Mat4Invert(ob->imat, mat); /* hoort zo, voor imat texture */
+
+ MTC_Mat4Invert(mat, R.viewmat); /* particles hebben geen ob transform meer */
+ MTC_Mat3CpyMat4(imat, mat);
+
+ R.flag |= R_HALO;
+
+ if(ob->ipoflag & OB_OFFS_PARTICLE) ptime= ob->sf;
+ else ptime= 0.0;
+ ctime= bsystem_time(ob, 0, (float)G.scene->r.cfra, ptime);
+ ma->ren->seed1= ma->seed1;
+
+ for(a=0; a<paf->totpart; a++, pa+=paf->totkey) {
+
+ if(ctime > pa->time) {
+ if(ctime < pa->time+pa->lifetime) {
+
+ /* let op: ook nog de normaal van de particle berekenen */
+ if(paf->stype==PAF_VECT || ma->mode & MA_HALO_SHADE) {
+ where_is_particle(paf, pa, ctime, vec);
+ MTC_Mat4MulVecfl(R.viewmat, vec);
+ where_is_particle(paf, pa, ctime+1.0, vec1);
+ MTC_Mat4MulVecfl(R.viewmat, vec1);
+ }
+ else {
+ where_is_particle(paf, pa, ctime, vec);
+ MTC_Mat4MulVecfl(R.viewmat, vec);
+ }
+
+ if(pa->mat_nr != mat_nr) {
+ mat_nr= pa->mat_nr;
+ ma= give_render_material(ob, mat_nr);
+ if(ma==0) ma= &defmaterial;
+ }
+
+ if(ma->ipo) {
+ /* correctie voor lifetime */
+ ptime= 100.0*(ctime-pa->time)/pa->lifetime;
+ calc_ipo(ma->ipo, ptime);
+ execute_ipo((ID *)ma, ma->ipo);
+ }
+
+ hasize= ma->hasize;
+
+ if(ma->mode & MA_HALOPUNO) {
+ xn= pa->no[0];
+ yn= pa->no[1];
+ zn= pa->no[2];
+
+ /* transpose ! */
+ nor[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn;
+ nor[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn;
+ nor[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn;
+ Normalise(nor);
+
+ VECCOPY(view, vec);
+ Normalise(view);
+
+ zn= nor[0]*view[0]+nor[1]*view[1]+nor[2]*view[2];
+ if(zn>=0.0) hasize= 0.0;
+ else hasize*= zn*zn*zn*zn;
+ }
+
+ if(paf->stype==PAF_VECT) har= RE_inithalo(ma, vec, vec1, pa->co, hasize, paf->vectsize);
+ else {
+ har= RE_inithalo(ma, vec, 0, pa->co, hasize, 0);
+ if(har && ma->mode & MA_HALO_SHADE) {
+ VecSubf(har->no, vec, vec1);
+ Normalise(har->no);
+ }
+ }
+ if(har) har->lay= ob->lay;
+ }
+ }
+ ma->ren->seed1++;
+ }
+
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+static void render_static_particle_system(Object *ob, PartEff *paf)
+{
+ Particle *pa=0;
+ HaloRen *har=0;
+ Material *ma=0;
+ float xn, yn, zn, imat[3][3], mat[4][4], hasize;
+ float mtime, ptime, ctime, vec[3], vec1[3], view[3], nor[3];
+ int a, mat_nr=1;
+
+ pa= paf->keys;
+ if(pa==0) {
+ build_particle_system(ob);
+ pa= paf->keys;
+ if(pa==0) return;
+ }
+
+ ma= give_render_material(ob, 1);
+ if(ma==0) ma= &defmaterial;
+
+ MTC_Mat4MulMat4(mat, ob->obmat, R.viewmat);
+ MTC_Mat4Invert(ob->imat, mat); /* hoort zo, voor imat texture */
+
+ MTC_Mat3CpyMat4(imat, ob->imat);
+
+ R.flag |= R_HALO;
+
+ if(ob->ipoflag & OB_OFFS_PARTICLE) ptime= ob->sf;
+ else ptime= 0.0;
+ ctime= bsystem_time(ob, 0, (float)G.scene->r.cfra, ptime);
+ ma->ren->seed1= ma->seed1;
+
+ for(a=0; a<paf->totpart; a++, pa+=paf->totkey) {
+
+ where_is_particle(paf, pa, pa->time, vec1);
+ MTC_Mat4MulVecfl(mat, vec1);
+
+ mtime= pa->time+pa->lifetime+paf->staticstep-1;
+
+ for(ctime= pa->time; ctime<mtime; ctime+=paf->staticstep) {
+
+ /* make sure hair grows until the end.. */
+ if(ctime>pa->time+pa->lifetime) ctime= pa->time+pa->lifetime;
+
+
+ /* let op: ook nog de normaal van de particle berekenen */
+ if(paf->stype==PAF_VECT || ma->mode & MA_HALO_SHADE) {
+ where_is_particle(paf, pa, ctime+1.0, vec);
+ MTC_Mat4MulVecfl(mat, vec);
+ }
+ else {
+ where_is_particle(paf, pa, ctime, vec);
+ MTC_Mat4MulVecfl(mat, vec);
+ }
+
+ if(pa->mat_nr != mat_nr) {
+ mat_nr= pa->mat_nr;
+ ma= give_render_material(ob, mat_nr);
+ if(ma==0) ma= &defmaterial;
+ }
+
+ if(ma->ipo) {
+ /* correctie voor lifetime */
+ ptime= 100.0*(ctime-pa->time)/pa->lifetime;
+ calc_ipo(ma->ipo, ptime);
+ execute_ipo((ID *)ma, ma->ipo);
+ }
+
+ hasize= ma->hasize;
+
+ if(ma->mode & MA_HALOPUNO) {
+ xn= pa->no[0];
+ yn= pa->no[1];
+ zn= pa->no[2];
+
+ /* transpose ! */
+ nor[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn;
+ nor[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn;
+ nor[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn;
+ Normalise(nor);
+
+ VECCOPY(view, vec);
+ Normalise(view);
+
+ zn= nor[0]*view[0]+nor[1]*view[1]+nor[2]*view[2];
+ if(zn>=0.0) hasize= 0.0;
+ else hasize*= zn*zn*zn*zn;
+ }
+
+ if(paf->stype==PAF_VECT) har= RE_inithalo(ma, vec, vec1, pa->co, hasize, paf->vectsize);
+ else {
+ har= RE_inithalo(ma, vec, 0, pa->co, hasize, 0);
+ if(har && (ma->mode & MA_HALO_SHADE)) {
+ VecSubf(har->no, vec, vec1);
+ Normalise(har->no);
+ har->lay= ob->lay;
+ }
+ }
+
+ VECCOPY(vec1, vec);
+ }
+ ma->ren->seed1++;
+ }
+
+}
+
+/* ------------------------------------------------------------------------- */
+
+static void init_render_displist_mesh(Object *ob)
+{
+ Mesh *me;
+ DispList *dl;
+ VlakRen *vlr;
+ Material *matar[32];
+ VertRen *ver, *v1, *v2, *v3, *v4;
+ float xn, yn, zn;
+ float mat[4][4], imat[3][3], *data, *nors, *orco=0, n1[3], flen;
+ int a, b, flipnorm= -1, need_orco=0, startvert, p1, p2, p3, p4;
+ int old_totvert= R.totvert;
+ int old_totvlak= R.totvlak;
+
+ me= ob->data;
+
+ MTC_Mat4MulMat4(mat, ob->obmat, R.viewmat);
+ MTC_Mat4Invert(ob->imat, mat);
+ MTC_Mat3CpyMat4(imat, ob->imat);
+
+ /* material array */
+ memset(matar, 0, sizeof(matar));
+ matar[0]= &defmaterial;
+ for(a=0; a<ob->totcol; a++) {
+ matar[a]= give_render_material(ob, a+1);
+ if(matar[a]==0) matar[a]= &defmaterial;
+ if(matar[a]->ren->texco & TEXCO_ORCO) {
+ need_orco= 1;
+ }
+ }
+
+ dl= me->disp.first;
+
+ /* Force a displist rebuild if this is a subsurf and we have a different subdiv level */
+#if 1
+ if((dl==0) || ((me->subdiv != me->subdivr))){
+ object_deform(ob);
+ subsurf_make_mesh(ob, me->subdivr);
+ dl = me->disp.first;
+
+ }
+ else{
+ makeDispList(ob);
+ dl= me->disp.first;
+ }
+#else
+ tempdiv = me->subdiv;
+ me->subdiv = me->subdivr;
+ makeDispList(ob);
+ dl= me->disp.first;
+#endif
+ if(dl==0) return;
+
+ if(need_orco) {
+ make_orco_displist_mesh(ob, me->subdivr);
+ orco= me->orco;
+ }
+
+#if 0
+ me->subdiv = tempdiv;
+#endif
+
+ while(dl) {
+ if(dl->type==DL_SURF) {
+ startvert= R.totvert;
+ a= dl->nr*dl->parts;
+ data= dl->verts;
+ nors= dl->nors;
+
+ while(a--) {
+ ver= RE_findOrAddVert(R.totvert++);
+ VECCOPY(ver->co, data);
+ if(orco) {
+ ver->orco= orco;
+ orco+= 3;
+ }
+ else {
+ ver->orco= data;
+ }
+
+ MTC_Mat4MulVecfl(mat, ver->co);
+
+ xn= nors[0];
+ yn= nors[1];
+ zn= nors[2];
+
+ /* transpose ! */
+ ver->n[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn;
+ ver->n[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn;
+ ver->n[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn;
+
+ Normalise(ver->n);
+
+ data+= 3;
+ nors+= 3;
+ }
+
+ for(a=0; a<dl->parts; a++) {
+
+ DL_SURFINDEX(dl->flag & DL_CYCLIC_V, dl->flag & DL_CYCLIC_U, dl->nr, dl->parts);
+ p1+= startvert;
+ p2+= startvert;
+ p3+= startvert;
+ p4+= startvert;
+
+ for(; b<dl->nr; b++) {
+ v1= RE_findOrAddVert(p1);
+ v2= RE_findOrAddVert(p2);
+ v3= RE_findOrAddVert(p3);
+ v4= RE_findOrAddVert(p4);
+
+ flen= CalcNormFloat4(v1->co, v3->co, v4->co, v2->co, n1);
+ if(flen!=0.0) {
+ vlr= RE_findOrAddVlak(R.totvlak++);
+ vlr->v1= v1;
+ vlr->v2= v3;
+ vlr->v3= v4;
+ vlr->v4= v2;
+ VECCOPY(vlr->n, n1);
+ vlr->len= flen;
+ vlr->lay= ob->lay;
+
+ vlr->mat= matar[ dl->col];
+ vlr->ec= ME_V1V2+ME_V2V3;
+ vlr->flag= ME_SMOOTH;
+
+ if(flipnorm== -1) flipnorm= mesh_test_flipnorm(ob, me->mface, vlr, imat);
+
+ if(flipnorm) {
+ vlr->n[0]= -vlr->n[0];
+ vlr->n[1]= -vlr->n[1];
+ vlr->n[2]= -vlr->n[2];
+ }
+
+ /* vlr->flag |= R_NOPUNOFLIP; */
+ /* vlr->puno= 15; */
+ vlr->puno= 0;
+ }
+
+ p4= p3;
+ p3++;
+ p2= p1;
+ p1++;
+ }
+ }
+ } else if (dl->type==DL_MESH) {
+ DispListMesh *dlm= dl->mesh;
+ int i;
+
+ startvert= R.totvert;
+ for (i=0; i<dlm->totvert; i++) {
+ MVert *mv= &dlm->mvert[i];
+
+ ver= RE_findOrAddVert(R.totvert++);
+ VECCOPY(ver->co, mv->co);
+ MTC_Mat4MulVecfl(mat, ver->co);
+
+ xn= mv->no[0];
+ yn= mv->no[1];
+ zn= mv->no[2];
+
+ /* transpose ! */
+ ver->n[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn;
+ ver->n[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn;
+ ver->n[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn;
+
+ Normalise(ver->n);
+
+ if (orco)
+ ver->orco= &orco[i*3];
+ }
+
+ for (i=0; i<dlm->totface; i++) {
+ MFaceInt *mf= &dlm->mface[i];
+
+ if (!mf->v3)
+ continue;
+
+ v1= RE_findOrAddVert(startvert+mf->v1);
+ v2= RE_findOrAddVert(startvert+mf->v2);
+ v3= RE_findOrAddVert(startvert+mf->v3);
+
+ if (mf->v4) {
+ v4= RE_findOrAddVert(startvert+mf->v4);
+ flen= CalcNormFloat4(v1->co, v2->co, v3->co, v4->co, n1);
+ } else {
+ v4= 0;
+ flen= CalcNormFloat(v1->co, v2->co, v3->co, n1);
+ }
+
+ if(flen!=0.0) {
+ vlr= RE_findOrAddVlak(R.totvlak++);
+ vlr->v1= v1;
+ vlr->v2= v2;
+ vlr->v3= v3;
+ vlr->v4= v4;
+
+ VECCOPY(vlr->n, n1);
+ vlr->len= flen;
+ vlr->lay= ob->lay;
+
+ vlr->mat= matar[mf->mat_nr];
+ vlr->flag= mf->flag;
+ vlr->ec= mf->edcode;
+ vlr->puno= mf->puno;
+
+ if(flipnorm== -1) flipnorm= test_flipnorm(v1->co, v2->co, v3->co, vlr, imat);
+
+ if(flipnorm) {
+ vlr->n[0]= -vlr->n[0];
+ vlr->n[1]= -vlr->n[1];
+ vlr->n[2]= -vlr->n[2];
+ }
+
+ if (dlm->tface) {
+ vlr->tface= &dlm->tface[i];
+ vlr->vcol= vlr->tface->col;
+ } else if (dlm->mcol)
+ vlr->vcol= (unsigned int *) &dlm->mcol[i*4];
+ }
+ }
+ }
+
+ dl= dl->next;
+ }
+
+
+ normalenrender(old_totvert, old_totvlak);
+
+}
+
+/* ------------------------------------------------------------------------- */
+
+static int verghalo(const void *a1, const void *a2)
+{
+ const struct halosort *x1=a1, *x2=a2;
+
+ if( x1->z < x2->z ) return 1;
+ else if( x1->z > x2->z) return -1;
+ return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static void sort_halos(void)
+{
+ struct halosort *hablock, *haso;
+ HaloRen *har = NULL, **bloha;
+ int a;
+
+ if(R.tothalo==0) return;
+
+ /* datablok maken met halopointers, sorteren */
+ haso= hablock= MEM_mallocN(sizeof(struct halosort)*R.tothalo, "hablock");
+
+ for(a=0; a<R.tothalo; a++) {
+ if((a & 255)==0) har= R.bloha[a>>8];
+ else har++;
+ haso->har= har;
+ haso->z= har->zs;
+ haso++;
+ }
+
+ qsort(hablock, R.tothalo, sizeof(struct halosort), verghalo);
+
+ /* opnieuw samenstellen van R.bloha */
+
+ bloha= R.bloha;
+ R.bloha= (HaloRen **)MEM_callocN(sizeof(void *)*(MAXVERT>>8),"Bloha");
+
+ haso= hablock;
+ for(a=0; a<R.tothalo; a++) {
+ har= RE_findOrAddHalo(a);
+ *har= *(haso->har);
+
+ haso++;
+ }
+
+ /* vrijgeven */
+ a= 0;
+ while(bloha[a]) {
+ MEM_freeN(bloha[a]);
+ a++;
+ }
+ MEM_freeN(bloha);
+ MEM_freeN(hablock);
+
+}
+
+
+
+static Material *give_render_material(Object *ob, int nr)
+{
+ Object *temp;
+
+ if(ob->flag & OB_FROMDUPLI) {
+ temp= (Object *)ob->id.newid;
+ if(temp && temp->type==OB_FONT) {
+ ob= temp;
+ }
+ }
+
+ return give_current_material(ob, nr);
+}
+
+/* ------------------------------------------------------------------------- */
+static void init_render_mball(Object *ob)
+{
+ DispList *dl, *dlo;
+ VertRen *ver;
+ VlakRen *vlr, *vlr1;
+ Material *ma;
+ float *data, *nors, mat[4][4], imat[3][3], xn, yn, zn;
+ int a, need_orco, startvert, *index;
+
+ if (ob!=find_basis_mball(ob))
+ return;
+
+ MTC_Mat4MulMat4(mat, ob->obmat, R.viewmat);
+ MTC_Mat4Invert(ob->imat, mat);
+ MTC_Mat3CpyMat4(imat, ob->imat);
+
+ ma= give_render_material(ob, 1);
+ if(ma==0) ma= &defmaterial;
+
+ need_orco= 0;
+ if(ma->ren->texco & TEXCO_ORCO) {
+ need_orco= 1;
+ }
+
+ dlo= ob->disp.first;
+ if(dlo) BLI_remlink(&ob->disp, dlo);
+
+ makeDispList(ob);
+ dl= ob->disp.first;
+ if(dl==0) return;
+
+ startvert= R.totvert;
+ data= dl->verts;
+ nors= dl->nors;
+
+ for(a=0; a<dl->nr; a++, data+=3, nors+=3) {
+
+ ver= RE_findOrAddVert(R.totvert++);
+ VECCOPY(ver->co, data);
+ MTC_Mat4MulVecfl(mat, ver->co);
+
+ /* rendernormalen zijn omgekeerd */
+ xn= -nors[0];
+ yn= -nors[1];
+ zn= -nors[2];
+
+ /* transpose ! */
+ ver->n[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn;
+ ver->n[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn;
+ ver->n[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn;
+ Normalise(ver->n);
+
+ if(need_orco) ver->orco= data;
+ }
+
+ index= dl->index;
+ for(a=0; a<dl->parts; a++, index+=4) {
+
+ vlr= RE_findOrAddVlak(R.totvlak++);
+ vlr->v1= RE_findOrAddVert(startvert+index[0]);
+ vlr->v2= RE_findOrAddVert(startvert+index[1]);
+ vlr->v3= RE_findOrAddVert(startvert+index[2]);
+ vlr->v4= 0;
+
+ /* rendernormalen zijn omgekeerd */
+ vlr->len= CalcNormFloat(vlr->v3->co, vlr->v2->co, vlr->v1->co, vlr->n);
+
+ vlr->mface= 0;
+ vlr->mat= ma;
+ vlr->puno= 0;
+ vlr->flag= ME_SMOOTH+R_NOPUNOFLIP;
+ vlr->ec= 0;
+ vlr->lay= ob->lay;
+
+ /* mball -helaas- altijd driehoeken maken omdat vierhoeken erg onregelmatig zijn */
+ if(index[3]) {
+ vlr1= RE_findOrAddVlak(R.totvlak++);
+ *vlr1= *vlr;
+ vlr1->v2= vlr1->v3;
+ vlr1->v3= RE_findOrAddVert(startvert+index[3]);
+ vlr->len= CalcNormFloat(vlr1->v3->co, vlr1->v2->co, vlr1->v1->co, vlr1->n);
+ }
+ }
+
+ if(need_orco) {
+ /* displist bewaren en scalen */
+ make_orco_mball(ob);
+ if(dlo) BLI_addhead(&ob->disp, dlo);
+
+ }
+ else {
+ freedisplist(&ob->disp);
+ if(dlo) BLI_addtail(&ob->disp, dlo);
+ }
+}
+/* ------------------------------------------------------------------------- */
+/* convert */
+static void init_render_mesh(Object *ob)
+{
+ MFace *mface;
+ MVert *mvert;
+ Mesh *me;
+ VlakRen *vlr, *vlr1;
+ VertRen *ver;
+ Material *ma;
+ MSticky *ms;
+ PartEff *paf;
+ DispList *dl;
+ TFace *tface;
+ unsigned int *vertcol;
+ float xn, yn, zn, nor[3], imat[3][3], mat[4][4];
+ float *extverts=0, *orco;
+ int a, a1, ok, do_puno, need_orco=0, totvlako, totverto, vertofs;
+ int start, end, flipnorm;
+
+ me= ob->data;
+ if (rendermesh_uses_displist(me) && me->subdivr>0) {
+ init_render_displist_mesh(ob);
+ return;
+ }
+
+ paf = give_parteff(ob);
+ if(paf) {
+ if(paf->flag & PAF_STATIC) render_static_particle_system(ob, paf);
+ else render_particle_system(ob, paf);
+ return;
+ }
+
+ /* object_deform changes imat */
+ do_puno= object_deform(ob);
+
+ MTC_Mat4MulMat4(mat, ob->obmat, R.viewmat);
+ MTC_Mat4Invert(ob->imat, mat);
+ MTC_Mat3CpyMat4(imat, ob->imat);
+
+ if(me->totvert==0) return;
+ mvert= me->mvert;
+
+ dl= find_displist(&ob->disp, DL_VERTS);
+ if(dl) extverts= dl->verts;
+
+ totvlako= R.totvlak;
+ totverto= R.totvert;
+
+ if(me->key) do_puno= 1;
+
+ if(ob->effect.first) {
+ Effect *eff= ob->effect.first;
+ while(eff) {
+ if(eff->type==EFF_WAVE) do_puno= 1;
+ eff= eff->next;
+ }
+ }
+
+ if(me->orco==0) {
+ need_orco= 0;
+ for(a=1; a<=ob->totcol; a++) {
+ ma= give_render_material(ob, a);
+ if(ma) {
+ if(ma->ren->texco & TEXCO_ORCO) {
+ need_orco= 1;
+ break;
+ }
+ }
+ }
+ if(need_orco) {
+ make_orco_mesh(me);
+ }
+ }
+
+ orco= me->orco;
+ ms= me->msticky;
+ tface= me->tface;
+ if(tface) vertcol= ((TFace *)me->tface)->col;
+ else vertcol= (unsigned int *)me->mcol;
+
+ ma= give_render_material(ob, 1);
+ if(ma==0) ma= &defmaterial;
+
+
+ if(ma->mode & MA_HALO) {
+ make_render_halos(ob, me, ma, extverts);
+ }
+ else {
+
+ for(a=0; a<me->totvert; a++, mvert++) {
+
+ ver= RE_findOrAddVert(R.totvert++);
+ if(extverts) {
+ VECCOPY(ver->co, extverts);
+ extverts+= 3;
+ }
+ else {
+ VECCOPY(ver->co, mvert->co);
+ }
+ MTC_Mat4MulVecfl(mat, ver->co);
+
+ xn= mvert->no[0];
+ yn= mvert->no[1];
+ zn= mvert->no[2];
+ if(do_puno==0) {
+ /* transpose ! */
+ ver->n[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn;
+ ver->n[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn;
+ ver->n[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn;
+ Normalise(ver->n);
+ }
+ if(orco) {
+ ver->orco= orco;
+ orco+=3;
+ }
+ if(ms) {
+ ver->sticky= (float *)ms;
+ ms++;
+ }
+ }
+ /* nog doen bij keys: de juiste lokale textu coordinaat */
+
+ flipnorm= -1;
+ /* Testen of er een flip in de matrix zit: dan vlaknormaal ook flippen */
+
+ /* vlakken in volgorde colblocks */
+ vertofs= R.totvert- me->totvert;
+ for(a1=0; (a1<ob->totcol || (a1==0 && ob->totcol==0)); a1++) {
+
+ ma= give_render_material(ob, a1+1);
+ if(ma==0) ma= &defmaterial;
+
+ /* testen op 100% transparant */
+ ok= 1;
+ if(ma->alpha==0.0 && ma->spectra==0.0) {
+ ok= 0;
+ /* texture op transp? */
+ for(a=0; a<8; a++) {
+ if(ma->mtex[a] && ma->mtex[a]->tex) {
+ if(ma->mtex[a]->mapto & MAP_ALPHA) ok= 1;
+ }
+ }
+ }
+
+ if(ok) {
+
+ start= 0;
+ end= me->totface;
+ set_buildvars(ob, &start, &end);
+ mvert= me->mvert;
+ mface= me->mface;
+ mface+= start;
+ if(tface) {
+ tface= me->tface;
+ tface+= start;
+ }
+
+ for(a=start; a<end; a++, mface++) {
+
+ if( mface->mat_nr==a1 ) {
+
+ if(mface->v3) {
+
+ vlr= RE_findOrAddVlak(R.totvlak++);
+ vlr->v1= RE_findOrAddVert(vertofs+mface->v1);
+ vlr->v2= RE_findOrAddVert(vertofs+mface->v2);
+ vlr->v3= RE_findOrAddVert(vertofs+mface->v3);
+ if(mface->v4) vlr->v4= RE_findOrAddVert(vertofs+mface->v4);
+ else vlr->v4= 0;
+
+ /* rendernormalen zijn omgekeerd */
+ if(vlr->v4) vlr->len= CalcNormFloat4(vlr->v4->co, vlr->v3->co, vlr->v2->co,
+ vlr->v1->co, vlr->n);
+ else vlr->len= CalcNormFloat(vlr->v3->co, vlr->v2->co, vlr->v1->co,
+ vlr->n);
+ vlr->mface= mface;
+ vlr->mat= ma;
+ vlr->puno= mface->puno;
+ vlr->flag= mface->flag;
+ if(me->flag & ME_NOPUNOFLIP) {
+ vlr->flag |= R_NOPUNOFLIP;
+ vlr->puno= 15;
+ }
+ vlr->ec= mface->edcode;
+ vlr->lay= ob->lay;
+
+ if(vlr->len==0) R.totvlak--;
+ else {
+ if(flipnorm== -1) { /* per object 1 x testen */
+ flipnorm= mesh_test_flipnorm(ob, mface, vlr, imat);
+ }
+ if(flipnorm) {
+ vlr->n[0]= -vlr->n[0];
+ vlr->n[1]= -vlr->n[1];
+ vlr->n[2]= -vlr->n[2];
+ }
+
+ if(vertcol) {
+ if(tface) vlr->vcol= vertcol+sizeof(TFace)*a/4; /* vertcol is int */
+ else vlr->vcol= vertcol+sizeof(int)*a;
+ }
+ else vlr->vcol= 0;
+
+ vlr->tface= tface;
+
+ /* testen of een vierhoek als driehoek gerenderd moet */
+ if(vlr->v4) {
+
+ if(ma->mode & MA_WIRE);
+ else {
+ CalcNormFloat(vlr->v4->co, vlr->v3->co, vlr->v1->co, nor);
+ if(flipnorm) {
+ nor[0]= -nor[0];
+ nor[1]= -nor[1];
+ nor[2]= -nor[2];
+ }
+
+ xn= nor[0]*vlr->n[0] + nor[1]*vlr->n[1] + nor[2]*vlr->n[2];
+ if( xn < 0.9990 ) {
+ /* recalc this nor, previous calc was with calcnormfloat4 */
+ if(flipnorm) CalcNormFloat(vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->n);
+ else CalcNormFloat(vlr->v3->co, vlr->v2->co, vlr->v1->co, vlr->n);
+
+ vlr1= RE_findOrAddVlak(R.totvlak++);
+ *vlr1= *vlr;
+ vlr1->flag |= R_FACE_SPLIT;
+ VECCOPY(vlr1->n, nor);
+ vlr1->v2= vlr->v3;
+ vlr1->v3= vlr->v4;
+ vlr->v4= vlr1->v4= 0;
+
+ vlr1->puno= 0;
+ if(vlr->puno & ME_FLIPV1) vlr1->puno |= ME_FLIPV1;
+ if(vlr->puno & ME_FLIPV3) vlr1->puno |= ME_FLIPV2;
+ if(vlr->puno & ME_FLIPV4) vlr1->puno |= ME_FLIPV3;
+
+ }
+ }
+ }
+ }
+ }
+ else if(mface->v2 && (ma->mode & MA_WIRE)) {
+ vlr= RE_findOrAddVlak(R.totvlak++);
+ vlr->v1= RE_findOrAddVert(vertofs+mface->v1);
+ vlr->v2= RE_findOrAddVert(vertofs+mface->v2);
+ vlr->v3= vlr->v2;
+ vlr->v4= 0;
+
+ vlr->n[0]=vlr->n[1]=vlr->n[2]= 0.0;
+
+ vlr->mface= mface;
+ vlr->mat= ma;
+ vlr->puno= mface->puno;
+ vlr->flag= mface->flag;
+ vlr->ec= ME_V1V2;
+ vlr->lay= ob->lay;
+ }
+ }
+
+ if(tface) tface++;
+ }
+ }
+ }
+ }
+
+ if(me->flag & ME_AUTOSMOOTH) {
+ autosmooth(totverto, totvlako, me->smoothresh);
+ do_puno= 1;
+ }
+
+ if(do_puno) normalenrender(totverto, totvlako);
+
+}
+
+/* ------------------------------------------------------------------------- */
+/* If lar takes more lamp data, the decoupling will be better. */
+void RE_add_render_lamp(Object *ob, int doshadbuf)
+{
+ Lamp *la;
+ LampRen *lar;
+ float mat[4][4], hoek, xn, yn;
+ int c;
+
+ if(R.totlamp>=MAXLAMP) {
+ printf("lamp overflow\n");
+ return;
+ }
+ la= ob->data;
+ lar= (LampRen *)MEM_callocN(sizeof(LampRen),"lampren");
+ R.la[R.totlamp++]= lar;
+
+ MTC_Mat4MulMat4(mat, ob->obmat, R.viewmat);
+ MTC_Mat4Invert(ob->imat, mat);
+
+ MTC_Mat3CpyMat4(lar->imat, ob->imat);
+
+ lar->bufsize = la->bufsize;
+ lar->samp = la->samp;
+ lar->soft = la->soft;
+ lar->shadhalostep = la->shadhalostep;
+ lar->clipsta = la->clipsta;
+ lar->clipend = la->clipend;
+ lar->bias = la->bias;
+
+ lar->type= la->type;
+ lar->mode= la->mode;
+
+ lar->energy= la->energy;
+ lar->energy= la->energy*R.wrld.exposure;
+ if(la->mode & LA_NEG) lar->energy= -lar->energy;
+
+ lar->vec[0]= -mat[2][0];
+ lar->vec[1]= -mat[2][1];
+ lar->vec[2]= -mat[2][2];
+ Normalise(lar->vec);
+ lar->co[0]= mat[3][0];
+ lar->co[1]= mat[3][1];
+ lar->co[2]= mat[3][2];
+ lar->dist= la->dist;
+ lar->haint= la->haint;
+ lar->distkw= lar->dist*lar->dist;
+ lar->r= lar->energy*la->r;
+ lar->g= lar->energy*la->g;
+ lar->b= lar->energy*la->b;
+ lar->spotsi= 0.5;
+
+ lar->spotsi= cos( M_PI*la->spotsize/360.0 );
+ lar->spotbl= (1.0-lar->spotsi)*la->spotblend;
+
+ memcpy(lar->mtex, la->mtex, 8*4);
+
+
+ lar->lay= ob->lay;
+
+ lar->ld1= la->att1;
+ lar->ld2= la->att2;
+
+ if(lar->type==LA_SPOT) {
+
+ Normalise(lar->imat[0]);
+ Normalise(lar->imat[1]);
+ Normalise(lar->imat[2]);
+
+ xn= saacos(lar->spotsi);
+ xn= sin(xn)/cos(xn);
+ lar->spottexfac= 1.0/(xn);
+
+ if(lar->mode & LA_ONLYSHADOW) {
+ if((lar->mode & LA_SHAD)==0) lar->mode -= LA_ONLYSHADOW;
+ else if((R.r.mode & R_SHADOW)==0) lar->mode -= LA_ONLYSHADOW;
+ }
+
+ }
+
+ /* imat bases */
+
+
+ /* flag zetten voor spothalo en initvars */
+ if(la->type==LA_SPOT && (la->mode & LA_HALO)) {
+ if(la->haint>0.0) {
+ R.flag |= R_LAMPHALO;
+
+ /* camerapos (0,0,0) roteren rondom lamp */
+ lar->sh_invcampos[0]= -lar->co[0];
+ lar->sh_invcampos[1]= -lar->co[1];
+ lar->sh_invcampos[2]= -lar->co[2];
+ MTC_Mat3MulVecfl(lar->imat, lar->sh_invcampos);
+
+ /* z factor, zodat het volume genormaliseerd is */
+ hoek= saacos(lar->spotsi);
+ xn= lar->spotsi;
+ yn= sin(hoek);
+ lar->sh_zfac= yn/xn;
+ /* alvast goed scalen */
+ lar->sh_invcampos[2]*= lar->sh_zfac;
+
+ }
+ }
+
+ for(c=0; c<6; c++) {
+ if(la->mtex[c] && la->mtex[c]->tex) {
+ lar->mode |= LA_TEXTURE;
+
+ if(R.flag & R_RENDERING) {
+ if(R.osa) {
+ if(la->mtex[c]->tex->type==TEX_IMAGE) lar->mode |= LA_OSATEX;
+ }
+ }
+ }
+ }
+
+ if( (R.r.mode & R_SHADOW)
+ && (lar->mode & LA_SHAD)
+ && (la->type==LA_SPOT)
+ && doshadbuf
+ )
+ {
+ /* Per lamp, one shadow buffer is made. */
+ if (R.r.mode & R_UNIFIED) {
+ int mode;
+ /* For the UR, I want to stick to the cpp version. I can
+ * put a switch here for the different shadow buffers. At
+ * this point, the type of shadow buffer is
+ * determined. The actual calculations are done during the
+ * render pre operations. */
+ if (lar->mode & LA_DEEP_SHADOW) {
+ mode = 0; /* dummy, for testing */
+ } else if (2) {
+ mode = 2; /* old-style buffer */
+ }
+ lar->shadowBufOb = (void*) RE_createShadowBuffer(lar,
+ ob->obmat,
+ mode);
+ } else {
+ RE_createShadowBuffer(lar,
+ ob->obmat,
+ 1); /* mode = 1 is old buffer */
+ }
+ }
+
+ lar->org= MEM_dupallocN(lar);
+}
+
+/* ------------------------------------------------------------------------- */
+static void init_render_surf(Object *ob)
+{
+ Nurb *nu=0;
+ Curve *cu;
+ ListBase displist;
+ DispList *dl;
+ VertRen *ver, *v1, *v2, *v3, *v4;
+ VlakRen *vlr;
+ Material *matar[32];
+ float *data, *fp, *orco, n1[3], flen, mat[4][4];
+ int len, a, need_orco=0, startvlak, startvert, p1, p2, p3, p4;
+#ifdef STRUBI
+ int u, v;
+ int sizeu, sizev;
+ VlakRen *vlr1, *vlr2, *vlr3;
+ float n2[3], vn[3];
+ int index;
+#endif
+
+ cu= ob->data;
+ nu= cu->nurb.first;
+ if(nu==0) return;
+
+ MTC_Mat4MulMat4(mat, ob->obmat, R.viewmat);
+ MTC_Mat4Invert(ob->imat, mat);
+
+ /* material array */
+ memset(matar, 0, 4*32);
+ matar[0]= &defmaterial;
+ for(a=0; a<ob->totcol; a++) {
+ matar[a]= give_render_material(ob, a+1);
+ if(matar[a]==0) matar[a]= &defmaterial;
+ if(matar[a] && matar[a]->ren->texco & TEXCO_ORCO) {
+ need_orco= 1;
+ }
+ }
+
+ if(ob->parent && (ob->parent->type==OB_IKA || ob->parent->type==OB_LATTICE)) need_orco= 1;
+
+ if(cu->orco==0 && need_orco) make_orco_surf(cu);
+ orco= cu->orco;
+
+ /* een complete displist maken, de basedisplist kan compleet anders zijn */
+ displist.first= displist.last= 0;
+ nu= cu->nurb.first;
+ while(nu) {
+ if(nu->pntsv>1) {
+ // if (dl->flag & DL_CYCLIC_V) {
+ len= nu->resolu*nu->resolv;
+ /* makeNurbfaces wil nullen */
+
+ dl= MEM_callocN(sizeof(DispList)+len*3*sizeof(float), "makeDispList1");
+ dl->verts= MEM_callocN(len*3*sizeof(float), "makeDispList01");
+ BLI_addtail(&displist, dl);
+
+ dl->parts= nu->resolu; /* andersom want makeNurbfaces gaat zo */
+ dl->nr= nu->resolv;
+ dl->col= nu->mat_nr;
+ dl->rt= nu->flag;
+
+ data= dl->verts;
+ dl->type= DL_SURF;
+ /* if nurbs cyclic (u/v) set flags in displist accordingly */
+ if(nu->flagv & 1) dl->flag |= DL_CYCLIC_V;
+ if(nu->flagu & 1) dl->flag |= DL_CYCLIC_U;
+
+ makeNurbfaces(nu, data);
+ }
+ nu= nu->next;
+ }
+
+ if(ob->parent && ob->parent->type==OB_LATTICE) {
+ init_latt_deform(ob->parent, ob);
+ dl= displist.first;
+ while(dl) {
+
+ fp= dl->verts;
+ len= dl->nr*dl->parts;
+ for(a=0; a<len; a++, fp+=3) calc_latt_deform(fp);
+
+ dl= dl->next;
+ }
+ end_latt_deform();
+ }
+
+#ifdef __NLA
+ if(ob->parent && ob->parent->type==OB_ARMATURE) {
+/* bArmature *arm= ob->parent->data; */
+ init_armature_deform(ob->parent, ob);
+ dl= displist.first;
+ while(dl) {
+
+ fp= dl->verts;
+ len= dl->nr*dl->parts;
+ for(a=0; a<len; a++, fp+=3)
+ calc_armature_deform(ob->parent, fp, a);
+
+ dl= dl->next;
+ }
+ }
+#endif
+
+ if(ob->parent && ob->parent->type==OB_IKA) {
+ Ika *ika= ob->parent->data;
+
+ init_skel_deform(ob->parent, ob);
+ dl= displist.first;
+ while(dl) {
+
+ fp= dl->verts;
+ len= dl->nr*dl->parts;
+ for(a=0; a<len; a++, fp+=3) calc_skel_deform(ika, fp);
+
+ dl= dl->next;
+ }
+ }
+
+ dl= displist.first;
+ /* walk along displaylist and create rendervertices/-faces */
+ while(dl) {
+#ifdef STRUBI
+/* watch out: u ^= y, v ^= x !! */
+ if(dl->type==DL_SURF) {
+ startvert= R.totvert;
+ sizeu = dl->parts; sizev = dl->nr;
+
+ data= dl->verts;
+ for (u = 0; u < sizeu; u++) {
+ v1 = RE_findOrAddVert(R.totvert++); /* save this for possible V wrapping */
+ VECCOPY(v1->co, data); data += 3;
+ if(orco) {
+ v1->orco= orco; orco+= 3;
+ }
+ MTC_Mat4MulVecfl(mat, v1->co);
+
+ for (v = 1; v < sizev; v++) {
+ ver= RE_findOrAddVert(R.totvert++);
+ VECCOPY(ver->co, data); data += 3;
+ if(orco) {
+ ver->orco= orco; orco+= 3;
+ }
+ MTC_Mat4MulVecfl(mat, ver->co);
+ }
+ /* if V-cyclic, add extra vertices at end of the row */
+ if (dl->flag & DL_CYCLIC_V) {
+ ver= RE_findOrAddVert(R.totvert++);
+ VECCOPY(ver->co, v1->co);
+ ver->orco= orco;
+ orco+= 3;
+ }
+ }
+
+ if (dl->flag & DL_CYCLIC_V) sizev++; /* adapt U dimension */
+
+
+ /* if U cyclic, add extra row at end of column */
+ if (dl->flag & DL_CYCLIC_U) {
+ for (v = 0; v < sizev; v++) {
+ v1= RE_findOrAddVert(startvert + v);
+ ver= RE_findOrAddVert(R.totvert++);
+ VECCOPY(ver->co, v1->co);
+ ver->orco= orco;
+ orco +=3;
+
+ }
+ sizeu++;
+ }
+
+
+
+
+ startvlak= R.totvlak;
+
+ /* process generic surface */
+ for(u = 0; u < sizeu - 1; u++) {
+
+/* DL_SURFINDEX(dl->flag & DL_CYCLIC_U, dl->flag & DL_CYCLIC_V, dl->nr, dl->parts);
+ DL_SURFINDEX(0, 0, dl->nr, dl->parts);
+*/
+
+
+/*
+
+ ^ ()----p4----p3----()
+ | | | | |
+ u | | | |
+ | | | |
+ ()----p1----p2----()
+ v ->
+*/
+
+ p1 = startvert + u * sizev; /* walk through face list */
+ p2 = p1 + 1;
+ p3 = p2 + sizev;
+ p4 = p3 - 1;
+
+
+ for(v = 0; v < sizev - 1; v++) {
+ v1= RE_findOrAddVert(p1);
+ v2= RE_findOrAddVert(p2);
+ v3= RE_findOrAddVert(p3);
+ v4= RE_findOrAddVert(p4);
+
+ flen= CalcNormFloat4(v1->co, v2->co, v3->co, v4->co, n1);
+/* flen can be 0 if there are double nurbs control vertices
+ so zero area faces can be generated
+ ->> there is at the moment no proper way to fix this except
+ generating empty render faces */
+
+// if(flen!=0.0) {
+ vlr= RE_findOrAddVlak(R.totvlak++);
+ vlr->v1= v1; vlr->v2= v2; vlr->v3= v3; vlr->v4= v4;
+ VECCOPY(vlr->n, n1);
+ vlr->len= flen;
+ vlr->lay= ob->lay;
+ vlr->mat= matar[ dl->col];
+ vlr->ec= ME_V1V2+ME_V2V3;
+ vlr->flag= dl->rt;
+ if(cu->flag & CU_NOPUNOFLIP) {
+ vlr->flag |= R_NOPUNOFLIP;
+ vlr->puno= 15;
+ }
+// }
+
+ VecAddf(v1->n, v1->n, n1);
+ VecAddf(v2->n, v2->n, n1);
+ VecAddf(v3->n, v3->n, n1);
+ VecAddf(v4->n, v4->n, n1);
+
+ p1++; p2++; p3++; p4++;
+ }
+ }
+ /* fix normals for U resp. V cyclic faces */
+ sizeu--; sizev--; /* dec size for face array */
+ if (dl->flag & DL_CYCLIC_U) {
+
+ for (v = 0; v < sizev; v++)
+ {
+ /* optimize! :*/
+ index = startvlak + v;
+ // vlr= RE_findOrAddVlak(index + (sizeu-1) * sizev);
+ vlr= RE_findOrAddVlak(UVTOINDEX(sizeu - 1, v));
+ GETNORMAL(vlr, n1);
+ vlr1= RE_findOrAddVlak(UVTOINDEX(0, v));
+ GETNORMAL(vlr1, n2);
+ VecAddf(vlr1->v1->n, vlr1->v1->n, n1);
+ VecAddf(vlr1->v2->n, vlr1->v2->n, n1);
+ VecAddf(vlr->v3->n, vlr->v3->n, n2);
+ VecAddf(vlr->v4->n, vlr->v4->n, n2);
+ }
+ }
+ if (dl->flag & DL_CYCLIC_V) {
+
+ for (u = 0; u < sizeu; u++)
+ {
+ /* optimize! :*/
+ index = startvlak + u * sizev;
+ //vlr= RE_findOrAddVlak(index);
+ vlr= RE_findOrAddVlak(UVTOINDEX(u, 0));
+ GETNORMAL(vlr, n1);
+ vlr1= RE_findOrAddVlak(UVTOINDEX(u, sizev-1));
+ // vlr1= RE_findOrAddVlak(index + (sizev - 1));
+ GETNORMAL(vlr1, n2);
+ VecAddf(vlr1->v2->n, vlr1->v2->n, n1);
+ VecAddf(vlr1->v3->n, vlr1->v3->n, n1);
+ VecAddf(vlr->v1->n, vlr->v1->n, n2);
+ VecAddf(vlr->v4->n, vlr->v4->n, n2);
+ }
+ }
+ /* last vertex is an extra case:
+
+ ^ ()----()----()----()
+ | | | || |
+ u | |(0,n)||(0,0)|
+ | | || |
+ ()====()====[]====()
+ | | || |
+ | |(m,n)||(m,0)|
+ | | || |
+ ()----()----()----()
+ v ->
+
+ vertex [] is no longer shared, therefore distribute
+ normals of the surrounding faces to all of the duplicates of []
+ */
+
+ if (dl->flag & DL_CYCLIC_U && dl->flag & DL_CYCLIC_V)
+ {
+ vlr= RE_findOrAddVlak(UVTOINDEX(sizeu - 1, sizev - 1)); /* (m,n) */
+ GETNORMAL(vlr, n1);
+ vlr1= RE_findOrAddVlak(UVTOINDEX(0,0)); /* (0,0) */
+ GETNORMAL(vlr1, vn);
+ VecAddf(vn, vn, n1);
+ vlr2= RE_findOrAddVlak(UVTOINDEX(0, sizev-1)); /* (0,n) */
+ GETNORMAL(vlr2, n1);
+ VecAddf(vn, vn, n1);
+ vlr3= RE_findOrAddVlak(UVTOINDEX(sizeu-1, 0)); /* (m,0) */
+ GETNORMAL(vlr3, n1);
+ VecAddf(vn, vn, n1);
+ VECCOPY(vlr->v3->n, vn);
+ VECCOPY(vlr1->v1->n, vn);
+ VECCOPY(vlr2->v2->n, vn);
+ VECCOPY(vlr3->v4->n, vn);
+ }
+ for(a = startvert; a < R.totvert; a++) {
+ ver= RE_findOrAddVert(a);
+ Normalise(ver->n);
+ }
+
+
+ }
+#else
+
+ if(dl->type==DL_SURF) {
+ startvert= R.totvert;
+ a= dl->nr*dl->parts;
+ data= dl->verts;
+ while(a--) {
+ ver= RE_findOrAddVert(R.totvert++);
+ VECCOPY(ver->co, data);
+ if(orco) {
+ ver->orco= orco;
+ orco+= 3;
+ }
+ MTC_Mat4MulVecfl(mat, ver->co);
+ data+= 3;
+ }
+
+ startvlak= R.totvlak;
+
+ for(a=0; a<dl->parts; a++) {
+
+ DL_SURFINDEX(dl->flag & DL_CYCLIC_V, dl->flag & DL_CYCLIC_U, dl->nr, dl->parts);
+ p1+= startvert;
+ p2+= startvert;
+ p3+= startvert;
+ p4+= startvert;
+
+ for(; b<dl->nr; b++) {
+ v1= RE_findOrAddVert(p1);
+ v2= RE_findOrAddVert(p2);
+ v3= RE_findOrAddVert(p3);
+ v4= RE_findOrAddVert(p4);
+
+ flen= CalcNormFloat4(v1->co, v3->co, v4->co, v2->co, n1);
+ if(flen!=0.0) {
+ vlr= RE_findOrAddVlak(R.totvlak++);
+ vlr->v1= v1;
+ vlr->v2= v3;
+ vlr->v3= v4;
+ vlr->v4= v2;
+ VECCOPY(vlr->n, n1);
+ vlr->len= flen;
+ vlr->lay= ob->lay;
+ vlr->mat= matar[ dl->col];
+ vlr->ec= ME_V1V2+ME_V2V3;
+ vlr->flag= dl->rt;
+ if(cu->flag & CU_NOPUNOFLIP) {
+ vlr->flag |= R_NOPUNOFLIP;
+ vlr->puno= 15;
+ }
+ }
+
+ VecAddf(v1->n, v1->n, n1);
+ VecAddf(v2->n, v2->n, n1);
+ VecAddf(v3->n, v3->n, n1);
+ VecAddf(v4->n, v4->n, n1);
+
+ p4= p3;
+ p3++;
+ p2= p1;
+ p1++;
+ }
+ }
+
+ for(a=startvert; a<R.totvert; a++) {
+ ver= RE_findOrAddVert(a);
+ Normalise(ver->n);
+ }
+
+
+ }
+#endif
+ dl= dl->next;
+ }
+ freedisplist(&displist);
+}
+
+static void init_render_curve(Object *ob)
+{
+ Ika *ika=0;
+
+ Lattice *lt=0;
+ Curve *cu;
+ VertRen *ver;
+ VlakRen *vlr;
+ ListBase dlbev;
+ Nurb *nu=0;
+ DispList *dlb, *dl;
+ BevList *bl;
+ BevPoint *bevp;
+ Material *matar[32];
+ float len, *data, *fp, *fp1, fac;
+ float n[3], vec[3], widfac, size[3], mat[4][4];
+ int nr, startvert, startvlak, a, b, p1, p2, p3, p4;
+ int totvert, frontside, need_orco=0, firststartvert, *index;
+
+ cu= ob->data;
+ nu= cu->nurb.first;
+ if(nu==0) return;
+
+ /* displist testen */
+ if(cu->disp.first==0) makeDispList(ob);
+ dl= cu->disp.first;
+ if(cu->disp.first==0) return;
+
+ if(dl->type!=DL_INDEX3) {
+ curve_to_filledpoly(cu, &cu->disp);
+ }
+
+ if(cu->bev.first==0) makeBevelList(ob);
+
+ firststartvert= R.totvert;
+
+ MTC_Mat4MulMat4(mat, ob->obmat, R.viewmat);
+ MTC_Mat4Invert(ob->imat, mat);
+
+ /* material array */
+ memset(matar, 0, 4*32);
+ matar[0]= &defmaterial;
+ for(a=0; a<ob->totcol; a++) {
+ matar[a]= give_render_material(ob, a+1);
+ if(matar[a]==0) matar[a]= &defmaterial;
+ if(matar[a]->ren->texco & TEXCO_ORCO) {
+ need_orco= 1;
+ }
+ }
+
+ /* bevelcurve in displist */
+ dlbev.first= dlbev.last= 0;
+
+ if(cu->ext1!=0.0 || cu->ext2!=0.0 || cu->bevobj!=0) {
+ makebevelcurve(ob, &dlbev);
+ }
+
+ /* uv orco's? aantal punten tellen en malloccen */
+ if(need_orco && (cu->flag & CU_UV_ORCO)) {
+ if(cu->flag & CU_PATH);
+ else {
+ totvert= 0;
+ bl= cu->bev.first;
+ while(bl) {
+ dlb= dlbev.first;
+ while(dlb) {
+ totvert+= dlb->nr*bl->nr;
+ dlb= dlb->next;
+ }
+ bl= bl->next;
+ }
+
+ if(totvert) {
+ fp= cu->orco= MEM_mallocN(3*sizeof(float)*totvert, "cu->orco");
+
+ bl= cu->bev.first;
+ while(bl) {
+ dlb= dlbev.first;
+ while(dlb) {
+ for(b=0; b<dlb->nr; b++) {
+ fac= (2.0*b/(float)(dlb->nr-1)) - 1.0;
+ for(a=0; a<bl->nr; a++, fp+=3) {
+ fp[0]= (2.0*a/(float)(bl->nr-1)) - 1.0;
+ fp[1]= fac;
+ fp[2]= 0.0;
+ }
+ }
+ dlb= dlb->next;
+ }
+ bl= bl->next;
+ }
+ }
+ }
+ }
+
+ if(ob->parent && ob->parent->type==OB_LATTICE) {
+ lt= ob->parent->data;
+ init_latt_deform(ob->parent, ob);
+ need_orco= 1;
+ }
+
+ if(ob->parent && ob->parent->type==OB_IKA) {
+ ika= ob->parent->data;
+ init_skel_deform(ob->parent, ob);
+ need_orco= 1;
+ }
+
+ if(ob->parent && ob->parent->type==OB_ARMATURE) {
+ init_armature_deform(ob->parent, ob);
+ need_orco= 1;
+ }
+
+ /* keypos doen? NOTITIE: pas op : orco's */
+
+ /* effect op text? */
+
+ /* boundboxclip nog doen */
+
+ /* polyzijvlakken: met bevellist werken */
+ widfac= (cu->width-1.0);
+
+ bl= cu->bev.first;
+ nu= cu->nurb.first;
+ while(bl) {
+
+ if(dlbev.first) { /* anders alleen een poly */
+
+ dlb= dlbev.first; /* bevel lus */
+ while(dlb) {
+ data= MEM_mallocN(3*sizeof(float)*dlb->nr*bl->nr, "init_render_curve3");
+ fp= data;
+
+ /* voor ieder punt van bevelcurve de hele poly doen */
+ fp1= dlb->verts;
+ b= dlb->nr;
+ while(b--) {
+
+ bevp= (BevPoint *)(bl+1);
+ a= bl->nr;
+ while(a--) {
+
+ if(cu->flag & CU_3D) {
+ vec[0]= fp1[1]+widfac;
+ vec[1]= fp1[2];
+ vec[2]= 0.0;
+
+ MTC_Mat3MulVecfl(bevp->mat, vec);
+
+ fp[0]= bevp->x+ vec[0];
+ fp[1]= bevp->y+ vec[1];
+ fp[2]= bevp->z+ vec[2];
+ }
+ else {
+
+ fp[0]= bevp->x+ (widfac+fp1[1])*bevp->sina;
+ fp[1]= bevp->y+ (widfac+fp1[1])*bevp->cosa;
+ fp[2]= bevp->z+ fp1[2];
+ /* hier niet al MatMullen: polyfill moet uniform werken, ongeacht frame */
+ }
+ fp+= 3;
+ bevp++;
+ }
+ fp1+=3;
+ }
+
+ /* rendervertices maken */
+ fp= data;
+ startvert= R.totvert;
+ nr= dlb->nr*bl->nr;
+
+ while(nr--) {
+ ver= RE_findOrAddVert(R.totvert++);
+
+ if(lt) calc_latt_deform(fp);
+ else if(ika) calc_skel_deform(ika, fp);
+
+ VECCOPY(ver->co, fp);
+ MTC_Mat4MulVecfl(mat, ver->co);
+ fp+= 3;
+ }
+
+ startvlak= R.totvlak;
+
+ for(a=0; a<dlb->nr; a++) {
+
+ frontside= (a >= dlb->nr/2);
+
+ DL_SURFINDEX(bl->poly>0, dlb->type==DL_POLY, bl->nr, dlb->nr);
+ p1+= startvert;
+ p2+= startvert;
+ p3+= startvert;
+ p4+= startvert;
+
+ for(; b<bl->nr; b++) {
+
+ vlr= RE_findOrAddVlak(R.totvlak++);
+ vlr->v1= RE_findOrAddVert(p2);
+ vlr->v2= RE_findOrAddVert(p1);
+ vlr->v3= RE_findOrAddVert(p3);
+ vlr->v4= RE_findOrAddVert(p4);
+ vlr->ec= ME_V2V3+ME_V3V4;
+ if(a==0) vlr->ec+= ME_V1V2;
+
+ vlr->flag= nu->flag;
+ vlr->lay= ob->lay;
+
+ /* dit is niet echt wetenschappelijk: de vertices
+ * 2, 3 en 4 geven betere puno's dan 1 2 3: voor en achterkant anders!!
+ */
+
+ if(frontside)
+ vlr->len= CalcNormFloat(vlr->v2->co, vlr->v3->co, vlr->v4->co, vlr->n);
+ else
+ vlr->len= CalcNormFloat(vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->n);
+
+ vlr->mat= matar[ nu->mat_nr ];
+
+ p4= p3;
+ p3++;
+ p2= p1;
+ p1++;
+
+ }
+
+ }
+
+ /* dubbele punten maken: POLY SPLITSEN */
+ if(dlb->nr==4 && cu->bevobj==0) {
+ split_u_renderfaces(startvlak, startvert, bl->nr, 1, bl->poly>0);
+ split_u_renderfaces(startvlak, startvert, bl->nr, 2, bl->poly>0);
+ }
+ /* dubbele punten maken: BEVELS SPLITSEN */
+ bevp= (BevPoint *)(bl+1);
+ for(a=0; a<bl->nr; a++) {
+ if(bevp->f1)
+ split_v_renderfaces(startvlak, startvert, bl->nr, dlb->nr, a, bl->poly>0,
+ dlb->type==DL_POLY);
+ bevp++;
+ }
+
+ /* puntnormalen */
+ for(a= startvlak; a<R.totvlak; a++) {
+ vlr= RE_findOrAddVlak(a);
+
+ VecAddf(vlr->v1->n, vlr->v1->n, vlr->n);
+ VecAddf(vlr->v3->n, vlr->v3->n, vlr->n);
+ VecAddf(vlr->v2->n, vlr->v2->n, vlr->n);
+ VecAddf(vlr->v4->n, vlr->v4->n, vlr->n);
+ }
+ for(a=startvert; a<R.totvert; a++) {
+ ver= RE_findOrAddVert(a);
+ len= Normalise(ver->n);
+ if(len==0.0) ver->sticky= (float *)1;
+ else ver->sticky= 0;
+ }
+ for(a= startvlak; a<R.totvlak; a++) {
+ vlr= RE_findOrAddVlak(a);
+ if(vlr->v1->sticky) VECCOPY(vlr->v1->n, vlr->n);
+ if(vlr->v2->sticky) VECCOPY(vlr->v2->n, vlr->n);
+ if(vlr->v3->sticky) VECCOPY(vlr->v3->n, vlr->n);
+ if(vlr->v4->sticky) VECCOPY(vlr->v4->n, vlr->n);
+ }
+
+ dlb= dlb->next;
+
+ MEM_freeN(data);
+ }
+
+ }
+ bl= bl->next;
+ nu= nu->next;
+ }
+
+ if(dlbev.first) {
+ freedisplist(&dlbev);
+ }
+
+ if(cu->flag & CU_PATH) return;
+
+ /* uit de displist kunnen de vulvlakken worden gehaald */
+ dl= cu->disp.first;
+
+ while(dl) {
+ if(dl->type==DL_INDEX3) {
+
+ startvert= R.totvert;
+ data= dl->verts;
+
+ n[0]= ob->imat[0][2];
+ n[1]= ob->imat[1][2];
+ n[2]= ob->imat[2][2];
+ Normalise(n);
+
+ for(a=0; a<dl->nr; a++, data+=3) {
+
+ ver= RE_findOrAddVert(R.totvert++);
+ VECCOPY(ver->co, data);
+ MTC_Mat4MulVecfl(mat, ver->co);
+
+ VECCOPY(ver->n, n);
+ }
+
+ startvlak= R.totvlak;
+ index= dl->index;
+ for(a=0; a<dl->parts; a++, index+=3) {
+
+ vlr= RE_findOrAddVlak(R.totvlak++);
+ vlr->v1= RE_findOrAddVert(startvert+index[0]);
+ vlr->v2= RE_findOrAddVert(startvert+index[1]);
+ vlr->v3= RE_findOrAddVert(startvert+index[2]);
+ vlr->v4= 0;
+
+ VECCOPY(vlr->n, n);
+
+ vlr->mface= 0;
+ vlr->mat= matar[ dl->col ];
+ vlr->puno= 0;
+ vlr->flag= 0;
+ vlr->ec= 0;
+ vlr->lay= ob->lay;
+ }
+
+ }
+ dl= dl->next;
+ }
+
+ if(lt) {
+ end_latt_deform();
+ }
+
+ if(need_orco) { /* de domme methode: snel vervangen; rekening houden met keys! */
+
+ VECCOPY(size, cu->size);
+
+ nr= R.totvert-firststartvert;
+ if(nr) {
+ if(cu->orco) {
+ fp= cu->orco;
+ while(nr--) {
+ ver= RE_findOrAddVert(firststartvert++);
+ ver->orco= fp;
+ fp+= 3;
+ }
+ }
+ else {
+ fp= cu->orco= MEM_mallocN(sizeof(float)*3*nr, "cu orco");
+ while(nr--) {
+ ver= RE_findOrAddVert(firststartvert++);
+ ver->orco= fp;
+
+ VECCOPY(fp, ver->co);
+ MTC_Mat4MulVecfl(ob->imat, fp);
+
+ fp[0]= (fp[0]-cu->loc[0])/size[0];
+ fp[1]= (fp[1]-cu->loc[1])/size[1];
+ fp[2]= (fp[2]-cu->loc[2])/size[2];
+ fp+= 3;
+ }
+ }
+ }
+ }
+}
+
+static void init_render_object(Object *ob)
+{
+ float mat[4][4];
+
+ ob->flag |= OB_DONE;
+
+ if(ob->type==OB_LAMP)
+ RE_add_render_lamp(ob, 1);
+ else if ELEM(ob->type, OB_FONT, OB_CURVE)
+ init_render_curve(ob);
+ else if(ob->type==OB_SURF)
+ init_render_surf(ob);
+ else if(ob->type==OB_MESH)
+ init_render_mesh(ob);
+ else if(ob->type==OB_MBALL)
+ init_render_mball(ob);
+ else {
+ MTC_Mat4MulMat4(mat, ob->obmat, R.viewmat);
+ MTC_Mat4Invert(ob->imat, mat);
+ }
+}
+
+void RE_freeRotateBlenderScene(void)
+{
+ ShadBuf *shb;
+ Object *ob = NULL;
+ Mesh *me;
+ Curve *cu;
+ DispList *dl;
+ unsigned long *ztile;
+ int a, b, v;
+ char *ctile;
+
+ /* VRIJGEVEN */
+
+ for(a=0; a<R.totlamp; a++) {
+
+ /* for the shadow buf object integration */
+ if (R.la[a]->shadowBufOb) {
+ RE_deleteShadowBuffer((RE_ShadowBufferHandle) R.la[a]->shadowBufOb);
+ }
+
+ if(R.la[a]->shb) {
+ shb= R.la[a]->shb;
+ v= (shb->size*shb->size)/256;
+ ztile= shb->zbuf;
+ ctile= shb->cbuf;
+ for(b=0; b<v; b++, ztile++, ctile++) {
+ if(*ctile) MEM_freeN((void *) *ztile);
+ }
+
+ MEM_freeN(shb->zbuf);
+ MEM_freeN(shb->cbuf);
+ MEM_freeN(R.la[a]->shb);
+ }
+ if(R.la[a]->org) MEM_freeN(R.la[a]->org);
+ MEM_freeN(R.la[a]);
+ }
+ a=0;
+ while(R.blove[a]) {
+ MEM_freeN(R.blove[a]);
+ R.blove[a]=0;
+ a++;
+ }
+ a=0;
+ while(R.blovl[a]) {
+ MEM_freeN(R.blovl[a]);
+ R.blovl[a]=0;
+ a++;
+ }
+ a=0;
+ while(R.bloha[a]) {
+ MEM_freeN(R.bloha[a]);
+ R.bloha[a]=0;
+ a++;
+ }
+
+ /* orco vrijgeven. ALle ob's aflopen ivm dupli's en sets */
+ ob= G.main->object.first;
+ while(ob) {
+
+ if ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT) {
+ cu= ob->data;
+ if(cu->orco) {
+ MEM_freeN(cu->orco);
+ cu->orco= 0;
+ }
+ }
+ else if(ob->type==OB_MESH) {
+ me= ob->data;
+ if(me->orco) {
+ MEM_freeN(me->orco);
+ me->orco= 0;
+ }
+ if (rendermesh_uses_displist(me) && (me->subdiv!=me->subdivr)){
+ makeDispList(ob);
+ }
+ }
+ else if(ob->type==OB_MBALL) {
+ if(ob->disp.first && ob->disp.first!=ob->disp.last) {
+ dl= ob->disp.first;
+ BLI_remlink(&ob->disp, dl);
+ freedisplist(&ob->disp);
+ BLI_addtail(&ob->disp, dl);
+ }
+ }
+ ob= ob->id.next;
+ }
+
+ end_render_textures();
+ end_render_materials();
+
+ R.totvlak=R.totvert=R.totlamp=R.tothalo= 0;
+}
+
+
+extern int slurph_opt; /* key.c */
+extern ListBase duplilist;
+void RE_rotateBlenderScene(void)
+{
+ Base *base;
+ Object *ob, *obd;
+ Scene *sce;
+ unsigned int lay;
+ float mat[4][4];
+
+ if(G.scene->camera==0) return;
+
+ O.dxwin[0]= 0.5/(float)R.r.xsch;
+ O.dywin[1]= 0.5/(float)R.r.ysch;
+
+ slurph_opt= 0;
+
+ R.totvlak=R.totvert=R.totlamp=R.tothalo= 0;
+
+ do_all_ipos();
+ BPY_do_all_scripts(SCRIPT_FRAMECHANGED);
+ do_all_keys();
+#ifdef __NLA
+ do_all_actions();
+#endif
+ do_all_ikas();
+ test_all_displists();
+
+ /* niet erg nette calc_ipo en where_is forceer */
+ ob= G.main->object.first;
+ while(ob) {
+ ob->ctime= -123.456;
+ ob= ob->id.next;
+ }
+
+ if(G.special1 & G_HOLO) RE_holoview();
+
+ /* ivm met optimale berekening track / lattices / etc: extra where_is_ob */
+
+ base= G.scene->base.first;
+ while(base) {
+ clear_object_constraint_status(base->object);
+ if (base->object->type==OB_ARMATURE)
+ where_is_armature (base->object);
+ else
+
+ where_is_object(base->object);
+
+ if(base->next==0 && G.scene->set && base==G.scene->base.last) base= G.scene->set->base.first;
+ else base= base->next;
+ }
+
+ MTC_Mat4CpyMat4(R.viewinv, G.scene->camera->obmat);
+ MTC_Mat4Ortho(R.viewinv);
+ MTC_Mat4Invert(R.viewmat, R.viewinv);
+
+ /* is niet netjes: nu is de viewinv ongelijk aan de viewmat. voor Texco's enzo. Beter doen! */
+ if(R.r.mode & R_ORTHO) R.viewmat[3][2]*= 100.0;
+
+ RE_setwindowclip(1,-1); /* geen jit:(-1) */
+
+ /* imatflags wissen */
+ ob= G.main->object.first;
+ while(ob) {
+ ob->flag &= ~OB_DO_IMAT;
+ ob= ob->id.next;
+ }
+
+ init_render_world(); /* moet eerst ivm ambient */
+ init_render_textures();
+ init_render_materials();
+
+ /* MAAK RENDERDATA */
+
+ /* elk object maar 1 x renderen */
+ ob= G.main->object.first;
+ while(ob) {
+ ob->flag &= ~OB_DONE;
+ ob= ob->id.next;
+ }
+
+
+ /* layers: in foreground current 3D window renderen */
+ lay= G.scene->lay;
+ sce= G.scene;
+
+ base= G.scene->base.first;
+ while(base) {
+
+ ob= base->object;
+
+ if(ob->flag & OB_DONE);
+ else {
+ where_is_object(ob);
+
+ if( (base->lay & lay) || (ob->type==OB_LAMP && (base->lay & G.scene->lay)) ) {
+
+ if(ob->transflag & OB_DUPLI) {
+ /* exception: mballs! */
+ make_duplilist(sce, ob);
+ if(ob->type==OB_MBALL) {
+ init_render_object(ob);
+ }
+ else {
+ obd= duplilist.first;
+ if(obd) {
+ /* exception, in background render it doesnt make the displist */
+ if ELEM(obd->type, OB_CURVE, OB_SURF) {
+ Curve *cu;
+
+ cu= obd->data;
+ if(cu->disp.first==0) {
+ obd->flag &= ~OB_FROMDUPLI;
+ makeDispList(obd);
+ obd->flag |= OB_FROMDUPLI;
+ }
+ }
+ }
+
+ obd= duplilist.first;
+ while(obd) {
+ if(obd->type!=OB_MBALL) init_render_object(obd);
+ obd= obd->id.next;
+ }
+ }
+ free_duplilist();
+ }
+ else init_render_object(ob);
+
+ }
+ else {
+ MTC_Mat4MulMat4(mat, ob->obmat, R.viewmat);
+ MTC_Mat4Invert(ob->imat, mat);
+ }
+
+ ob->flag &= ~OB_DO_IMAT;
+ }
+ if(MISC_test_break()) break;
+
+ if(base->next==0 && G.scene->set && base==G.scene->base.last) {
+ base= G.scene->set->base.first;
+ sce= G.scene->set;
+ }
+ else base= base->next;
+
+ }
+
+ /* imat objecten */
+ ob= G.main->object.first;
+ while(ob) {
+ if(ob->flag & OB_DO_IMAT) {
+
+ ob->flag &= ~OB_DO_IMAT;
+
+ MTC_Mat4MulMat4(mat, ob->obmat, R.viewmat);
+ MTC_Mat4Invert(ob->imat, mat);
+ }
+ ob= ob->id.next;
+ }
+
+ sort_halos();
+
+ if(R.wrld.mode & WO_STARS) RE_make_stars(NULL, NULL, NULL);
+
+ slurph_opt= 1;
+
+ if(MISC_test_break()) return;
+
+ /* if(R.totlamp==0) defaultlamp(); */
+
+ set_normalflags();
+}
+
diff --git a/source/blender/sign/BLO_sign.h b/source/blender/sign/BLO_sign.h
new file mode 100644
index 00000000000..8bfc6db0013
--- /dev/null
+++ b/source/blender/sign/BLO_sign.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 *****
+ */
+
+#ifndef BLO_SIGN_H
+#define BLO_SIGN_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ int
+BLO_sign(
+ unsigned char *data,
+ unsigned int dataIn,
+ struct streamGlueHeaderStruct *streamGlueHeader);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BLO_SIGN_H */
diff --git a/source/blender/sign/Makefile b/source/blender/sign/Makefile
new file mode 100644
index 00000000000..aa4458ef678
--- /dev/null
+++ b/source/blender/sign/Makefile
@@ -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 *****
+#
+# Bounces make to subdirectories.
+
+SOURCEDIR = source/blender/sign
+DIRS = intern
+
+include nan_subdirs.mk
diff --git a/source/blender/sign/intern/BLO_sign.c b/source/blender/sign/intern/BLO_sign.c
new file mode 100644
index 00000000000..db050654f1b
--- /dev/null
+++ b/source/blender/sign/intern/BLO_sign.c
@@ -0,0 +1,227 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * openssl/crypt RSA signature wrapper library
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef _WIN32
+#include <winsock2.h>
+#include <windows.h>
+#endif
+
+#include "openssl/rsa.h"
+#include "openssl/ripemd.h"
+#include "openssl/objects.h"
+#include "zlib.h"
+
+#include "GEN_messaging.h"
+
+#include "BLO_keyStore.h"
+#include "BLO_writeStreamGlue.h"
+#include "BLO_sign_verify_Header.h"
+#include "BLO_sign.h"
+
+ int
+BLO_sign(
+ unsigned char *data2,
+ unsigned int dataIn,
+ struct streamGlueHeaderStruct *streamGlueHeader)
+{
+ int err = 0;
+ struct writeStreamGlueStruct *streamGlue = NULL;
+ struct BLO_sign_verify_HeaderStruct BLO_sign_verify_Header;
+ struct BLO_SignerHeaderStruct BLO_SignerHeader;
+ unsigned char *sigret = NULL;
+ unsigned int siglen = 0;
+ unsigned char *digest = NULL;
+ byte *pubKey = NULL, *privKey = NULL;
+ int pubKeyLen = 0, privKeyLen = 0;
+ RSA *rsa = NULL;
+ static unsigned char rsa_e[] = "\x01\x00\x01";
+ int signSuccess = 0;
+ unsigned char *data = NULL;
+
+ // Update streamGlueHeader that initiated us and write it away
+ streamGlueHeader->totalStreamLength =
+ htonl(SIGNVERIFYHEADERSTRUCTSIZE + SIGNERHEADERSTRUCTSIZE + dataIn);
+ streamGlueHeader->crc = htonl(crc32(0L,
+ (const Bytef *) streamGlueHeader, STREAMGLUEHEADERSIZE - 4));
+ err = writeStreamGlue(
+ Global_streamGlueControl,
+ &streamGlue,
+ (unsigned char *) streamGlueHeader,
+ STREAMGLUEHEADERSIZE,
+ 0);
+ if (err) return err;
+
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "BLO_sign writes streamGlueHeader of %u bytes\n",
+ STREAMGLUEHEADERSIZE);
+#endif
+
+ pubKeyLen = keyStoreGetPubKey(&pubKey);
+ privKeyLen = keyStoreGetPrivKey(&privKey);
+ if ((pubKeyLen == 0) || (privKeyLen == 0)) {
+ err = BWS_SETFUNCTION(BWS_SIGN) |
+ BWS_SETGENERR(BWS_RSA);
+ return err;
+ }
+
+ rsa = RSA_new();
+ if (rsa == NULL) {
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "Error in RSA_new\n");
+#endif
+ err = BWS_SETFUNCTION(BWS_SIGN) |
+ BWS_SETSPECERR(BWS_RSANEWERROR);
+ return err;
+ }
+ // static exponent
+ rsa->e = BN_bin2bn(rsa_e, sizeof(rsa_e)-1, rsa->e);
+
+ // public part into rsa->n
+ rsa->n = BN_bin2bn(pubKey, pubKeyLen, rsa->n);
+ //rsa->n = BN_bin2bn(rsa_n, sizeof(rsa_n)-1, rsa->n);
+
+ // private part into rsa->d
+ rsa->d = BN_bin2bn(privKey, privKeyLen, rsa->d);
+ //rsa->d = BN_bin2bn(rsa_d, sizeof(rsa_d)-1, rsa->d);
+
+ //DEBUG RSA_print_fp(stdout, rsa, 0);
+
+ sigret = malloc(RSA_size(rsa) * sizeof(byte));
+ if (!sigret) {
+ err = BWS_SETFUNCTION(BWS_SIGN) |
+ BWS_SETGENERR(BWS_MALLOC);
+ RSA_free(rsa);
+ return err;
+ }
+
+ digest = malloc(RIPEMD160_DIGEST_LENGTH);
+ if (!digest) {
+ err = BWS_SETFUNCTION(BWS_SIGN) |
+ BWS_SETGENERR(BWS_MALLOC);
+ free(sigret);
+ RSA_free(rsa);
+ return err;
+ }
+
+ // Fill BLO_SignerHeader
+ strcpy(BLO_SignerHeader.name, keyStoreGetUserName());
+ strcpy(BLO_SignerHeader.email, keyStoreGetEmail());
+ BLO_SignerHeader.homeUrl[0] = '\0';
+ BLO_SignerHeader.text[0] = '\0';
+ BLO_SignerHeader.pubKeyUrl1[0] = '\0';
+ BLO_SignerHeader.pubKeyUrl2[0] = '\0';
+
+ // prepend BLO_SignerStruct to data
+ data = malloc(SIGNERHEADERSTRUCTSIZE + dataIn);
+ if (!data) {
+ err = BWS_SETFUNCTION(BWS_SIGN) |
+ BWS_SETGENERR(BWS_MALLOC);
+ free(sigret);
+ free(digest);
+ RSA_free(rsa);
+ return err;
+ }
+ memcpy(data, &BLO_SignerHeader, SIGNERHEADERSTRUCTSIZE);
+ memcpy(data + SIGNERHEADERSTRUCTSIZE, data2, dataIn);
+ dataIn += SIGNERHEADERSTRUCTSIZE;
+
+ RIPEMD160(data, dataIn, digest);
+
+ signSuccess = RSA_sign(NID_ripemd160, digest,
+ RIPEMD160_DIGEST_LENGTH, sigret, &siglen, rsa);
+ if (signSuccess != 1) {
+ err = BWS_SETFUNCTION(BWS_SIGN) |
+ BWS_SETSPECERR(BWS_SIGNERROR);
+ free(data);
+ free(sigret);
+ free(digest);
+ RSA_free(rsa);
+ return err;
+ }
+
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "BLO_sign writes BLO_sign_verify_Header of %u bytes\n",
+ SIGNVERIFYHEADERSTRUCTSIZE);
+#endif
+ // write out our header
+ BLO_sign_verify_Header.magic = 'A';
+ BLO_sign_verify_Header.length = htonl(dataIn);
+ memcpy(BLO_sign_verify_Header.pubKey, pubKey, pubKeyLen);
+ BLO_sign_verify_Header.pubKeyLen = htonl(pubKeyLen);
+ memcpy(BLO_sign_verify_Header.signature, sigret, siglen);
+ BLO_sign_verify_Header.signatureLen = htonl(siglen);
+ BLO_sign_verify_Header.datacrc = htonl(crc32(0L,
+ (const Bytef *) data, dataIn));
+ BLO_sign_verify_Header.headercrc = htonl(crc32(0L,
+ (const Bytef *) &BLO_sign_verify_Header, SIGNVERIFYHEADERSTRUCTSIZE-4));
+ err = writeStreamGlue(
+ Global_streamGlueControl,
+ &streamGlue,
+ (unsigned char *) &BLO_sign_verify_Header,
+ SIGNVERIFYHEADERSTRUCTSIZE,
+ 0);
+ if (err) {
+ free(data);
+ free(sigret);
+ free(digest);
+ RSA_free(rsa);
+ return err;
+ }
+
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "BLO_sign writes %u bytes raw data (plus its 2 headers totals to %u)\n",
+ dataIn, STREAMGLUEHEADERSIZE + SIGNVERIFYHEADERSTRUCTSIZE + dataIn);
+#endif
+ // finally write all signed data
+ err = writeStreamGlue(
+ Global_streamGlueControl,
+ &streamGlue,
+ (unsigned char *) data,
+ dataIn,
+ 1);
+
+ free(data); // NOTE: we must release because we made a copy
+ free(digest);
+ free(sigret);
+ RSA_free(rsa);
+
+ return err;
+}
+
diff --git a/source/blender/sign/intern/Makefile b/source/blender/sign/intern/Makefile
new file mode 100644
index 00000000000..3ff0678ce22
--- /dev/null
+++ b/source/blender/sign/intern/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 *****
+#
+#
+
+LIBNAME = sign
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+ifeq ($(OS),$(findstring $(OS), "beos darwin freebsd linux openbsd solaris windows"))
+ CFLAGS += -funsigned-char
+endif
+
+CFLAGS += $(LEVEL_2_C_WARNINGS)
+
+# path to our own external headerfiles
+CPPFLAGS += -I..
+
+# external modules
+CPPFLAGS += -I../../../kernel/gen_messaging
+CPPFLAGS += -I../../writestreamglue
+CPPFLAGS += -I../../readstreamglue
+CPPFLAGS += -I../../verify
+
+CPPFLAGS += -I$(NAN_OPENSSL)/include
+CPPFLAGS += -I$(NAN_BLENKEY)/include
+
+ifeq ($(OS),$(findstring $(OS), "solaris windows"))
+ CPPFLAGS += -I$(NAN_ZLIB)/include
+endif
+
diff --git a/source/blender/src/.BCkey b/source/blender/src/.BCkey
new file mode 100644
index 00000000000..a0fd5e817d4
--- /dev/null
+++ b/source/blender/src/.BCkey
@@ -0,0 +1 @@
+0xffffffff 0xfffffff0 fffffffe
diff --git a/source/blender/src/B.blend.c b/source/blender/src/B.blend.c
new file mode 100644
index 00000000000..f15ebb05ae7
--- /dev/null
+++ b/source/blender/src/B.blend.c
@@ -0,0 +1,1051 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+/* DataToC output of file <B_blend> */
+
+int datatoc_B_blend_size= 32472;
+char datatoc_B_blend[]= {
+ 66, 76, 69, 78, 68, 69, 82, 95,118, 50, 49, 50, 82, 69, 78, 68, 32, 0, 0, 0,136,237,255,191,
+ 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,250, 0, 0, 0, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 8, 83, 82, 0, 0,100, 0, 0, 0, 80,237, 89, 8, 70, 0, 0, 0, 1, 0, 0, 0,192,148, 95, 8,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 82,115, 99,114,101,101,110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,168,107, 93, 8,240,152, 92, 8, 56,153, 92, 8, 96, 89, 94, 8,168, 89, 94, 8,
+104, 95, 94, 8, 24,190, 95, 8, 0, 0,255, 4, 0, 0,255, 3, 0, 5, 0, 4, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 9, 0,
+ 68, 65, 84, 65, 20, 0, 0, 0,168,107, 93, 8, 71, 0, 0, 0, 1, 0, 0, 0,168,106, 93, 8, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0,168,106, 93, 8, 71, 0, 0, 0, 1, 0, 0, 0, 80, 22, 93, 8,
+168,107, 93, 8, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0, 80, 22, 93, 8, 71, 0, 0, 0,
+ 1, 0, 0, 0, 16, 23, 93, 8,168,106, 93, 8, 0, 0, 0, 0, 0, 5, 0, 4, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0,
+ 16, 23, 93, 8, 71, 0, 0, 0, 1, 0, 0, 0,232,105, 93, 8, 80, 22, 93, 8, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 20, 0, 0, 0,232,105, 93, 8, 71, 0, 0, 0, 1, 0, 0, 0, 48,106, 93, 8, 16, 23, 93, 8, 0, 0, 0, 0,
+ 0, 0,252, 0, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0, 48,106, 93, 8, 71, 0, 0, 0, 1, 0, 0, 0,216, 98, 93, 8,
+232,105, 93, 8, 0, 0, 0, 0, 0, 5,252, 0, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0,216, 98, 93, 8, 71, 0, 0, 0,
+ 1, 0, 0, 0, 32, 99, 93, 8, 48,106, 93, 8, 0, 0, 0, 0, 0, 0,228, 3, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0,
+ 32, 99, 93, 8, 71, 0, 0, 0, 1, 0, 0, 0,104, 99, 93, 8,216, 98, 93, 8, 0, 0, 0, 0, 0, 5,228, 3, 0, 0, 0, 0,
+ 68, 65, 84, 65, 20, 0, 0, 0,104, 99, 93, 8, 71, 0, 0, 0, 1, 0, 0, 0,240,152, 92, 8, 32, 99, 93, 8, 0, 0, 0, 0,
+ 20, 3,252, 0, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0,240,152, 92, 8, 71, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+104, 99, 93, 8, 0, 0, 0, 0, 20, 3,228, 3, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0, 56,153, 92, 8, 72, 0, 0, 0,
+ 1, 0, 0, 0,128,153, 92, 8, 0, 0, 0, 0, 80, 22, 93, 8,168,106, 93, 8, 1, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+ 24, 0, 0, 0,128,153, 92, 8, 72, 0, 0, 0, 1, 0, 0, 0, 96,159, 92, 8, 56,153, 92, 8, 16, 23, 93, 8,168,107, 93, 8,
+ 1, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0, 96,159, 92, 8, 72, 0, 0, 0, 1, 0, 0, 0,168,159, 92, 8,
+128,153, 92, 8,232,105, 93, 8,168,107, 93, 8, 1, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,168,159, 92, 8,
+ 72, 0, 0, 0, 1, 0, 0, 0,240,159, 92, 8, 96,159, 92, 8, 16, 23, 93, 8, 48,106, 93, 8, 1, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 24, 0, 0, 0,240,159, 92, 8, 72, 0, 0, 0, 1, 0, 0, 0,184, 71, 93, 8,168,159, 92, 8,232,105, 93, 8,
+ 48,106, 93, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,184, 71, 93, 8, 72, 0, 0, 0, 1, 0, 0, 0,
+ 0, 72, 93, 8,240,159, 92, 8,216, 98, 93, 8,168,106, 93, 8, 1, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,
+ 0, 72, 93, 8, 72, 0, 0, 0, 1, 0, 0, 0, 72, 72, 93, 8,184, 71, 93, 8, 80, 22, 93, 8, 32, 99, 93, 8, 1, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0, 72, 72, 93, 8, 72, 0, 0, 0, 1, 0, 0, 0,144, 72, 93, 8, 0, 72, 93, 8,
+216, 98, 93, 8, 32, 99, 93, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,144, 72, 93, 8, 72, 0, 0, 0,
+ 1, 0, 0, 0,168,103, 93, 8, 72, 72, 93, 8,104, 99, 93, 8,232,105, 93, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+ 24, 0, 0, 0,168,103, 93, 8, 72, 0, 0, 0, 1, 0, 0, 0,240,103, 93, 8,144, 72, 93, 8,104, 99, 93, 8, 48,106, 93, 8,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,240,103, 93, 8, 72, 0, 0, 0, 1, 0, 0, 0, 56,104, 93, 8,
+168,103, 93, 8,240,152, 92, 8,216, 98, 93, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0, 56,104, 93, 8,
+ 72, 0, 0, 0, 1, 0, 0, 0,128,104, 93, 8,240,103, 93, 8,240,152, 92, 8, 32, 99, 93, 8, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 24, 0, 0, 0,128,104, 93, 8, 72, 0, 0, 0, 1, 0, 0, 0,200,104, 93, 8, 56,104, 93, 8,240,152, 92, 8,
+104, 99, 93, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,200,104, 93, 8, 72, 0, 0, 0, 1, 0, 0, 0,
+ 96, 89, 94, 8,128,104, 93, 8, 32, 99, 93, 8, 48,106, 93, 8, 1, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,
+ 96, 89, 94, 8, 72, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,200,104, 93, 8,216, 98, 93, 8,232,105, 93, 8, 1, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65,220, 0, 0, 0,168, 89, 94, 8, 73, 0, 0, 0, 1, 0, 0, 0,136, 91, 94, 8, 0, 0, 0, 0,
+168,107, 93, 8,232,105, 93, 8, 48,106, 93, 8, 16, 23, 93, 8, 0, 0, 0, 0,120, 81,101, 8,120, 81,101, 8,240, 67, 95, 8,
+240, 67, 95, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0,249, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0,229, 0, 0, 0,
+249, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0,228, 0, 0, 0, 0, 0, 0, 0, 2, 0, 4, 4, 1, 5,229, 0,
+ 1, 0, 3, 0,253, 2, 0, 0,100, 0, 0, 0, 0, 0, 0, 0,208,226, 20, 8, 16, 56, 20, 8,108,217, 23, 8, 36,197, 20, 8,
+ 36,197, 20, 8,184, 90, 94, 8, 40,151,101, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,160, 0, 0, 0,184, 90, 94, 8,
+ 63, 0, 0, 0, 1, 0, 0, 0, 40,151,101, 8, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,224,159, 68,
+ 0, 0, 0, 0, 0, 0,100, 67, 73,194,122,193,133,213,161, 68, 60,222, 71,192,122, 31,103, 67, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 67, 0, 0, 40, 66, 0, 0,200, 68, 0, 0,225, 67, 0, 0, 0, 63,225,122,180, 63,
+ 0, 0, 1, 0, 1, 0, 1, 0, 4, 0,255,255, 0, 0, 4, 0, 0,197, 95, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,150, 1, 68, 65, 84, 65, 60, 1, 0, 0, 40,151,101, 8, 65, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+184, 90, 94, 8, 5, 0, 0, 0, 0, 0, 0, 0, 72,215,100, 8, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0,
+ 0, 0, 0, 0, 57, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255, 0, 0, 0, 0, 68, 65, 84, 65,220, 0, 0, 0,
+136, 91, 94, 8, 73, 0, 0, 0, 1, 0, 0, 0,152, 92, 94, 8,168, 89, 94, 8,216, 98, 93, 8,168,106, 93, 8, 80, 22, 93, 8,
+ 32, 99, 93, 8, 0, 0, 0, 0, 32, 70, 95, 8, 32, 70, 95, 8,152,244, 95, 8,152,244, 95, 8, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0,
+231, 3, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0,231, 3, 0, 0,251, 3, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0,
+252, 3, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 1, 0, 7, 7, 1, 5, 5, 0, 3, 0, 3, 1,145, 2, 0, 0,100, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 16, 56, 20, 8,196,189, 20, 8, 0, 0, 0, 0,188,234, 20, 8, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,220, 0, 0, 0,152, 92, 94, 8, 73, 0, 0, 0, 1, 0, 0, 0,104, 95, 94, 8,
+136, 91, 94, 8,232,105, 93, 8,216, 98, 93, 8,240,152, 92, 8,104, 99, 93, 8, 0, 0, 0, 0,200,246, 95, 8,200,246, 95, 8,
+200,249, 95, 8,200,249, 95, 8,124, 9,109, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61,190,129, 61,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,111, 18, 3,187, 0, 0, 0, 0, 0, 0, 0,128, 0, 0, 0,128,
+ 0, 0, 0,128, 0, 0,128, 63, 0, 0, 0, 0, 17, 3, 0, 0,255, 0, 0, 0,225, 3, 0, 0, 0, 0, 0, 0, 17, 3, 0, 0,
+255, 0, 0, 0, 19, 1, 0, 0, 0, 0, 0, 0, 17, 3, 0, 0, 20, 1, 0, 0,225, 3, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1,
+ 18, 3,206, 2, 1, 0, 1, 0,151, 2, 0, 0,100, 0, 0, 0, 0, 0, 0, 0, 32,227, 20, 8, 16, 56, 20, 8, 88,146, 11, 8,
+132,166, 20, 8,132,166, 20, 8,168, 93, 94, 8,160,140,101, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,140, 1, 0, 0,
+168, 93, 94, 8, 60, 0, 0, 0, 1, 0, 0, 0,160,140,101, 8, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63,124, 9,109, 61, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61,190,129, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+111, 18, 3,187, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63,112, 61,138, 65, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,132,143,124, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+255,255,249,195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,112, 61,138, 65, 0, 0, 7, 0, 2, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 12, 66, 0, 0,128, 63, 10,215, 35, 60, 0, 0,250, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,104,194, 95, 8,137, 1,103, 1,137, 1,103, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 20, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 60, 1, 0, 0,
+160,140,101, 8, 65, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,168, 93, 94, 8, 5, 0, 0, 0, 0, 0, 0, 0,168,130, 94, 8,
+ 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 57, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,255,255, 0, 0, 0, 0, 68, 65, 84, 65,220, 0, 0, 0,104, 95, 94, 8, 73, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+152, 92, 94, 8,104, 99, 93, 8,240,152, 92, 8, 32, 99, 93, 8, 48,106, 93, 8, 0, 0, 0, 0,200,252, 95, 8,200,252, 95, 8,
+200,255, 95, 8,200,255, 95, 8, 1,184,157, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,140, 63,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 1,128,191, 0, 0,128,191, 0, 0, 0, 0, 0, 0, 0, 0,
+225,215,163,188, 0, 0, 0, 0, 23, 3, 0, 0, 0, 5, 0, 0,255, 0, 0, 0,225, 3, 0, 0, 23, 3, 0, 0, 0, 5, 0, 0,
+255, 0, 0, 0, 19, 1, 0, 0, 23, 3, 0, 0, 0, 5, 0, 0, 20, 1, 0, 0,225, 3, 0, 0, 0, 0, 0, 0, 1, 0, 2, 2,
+234, 1,206, 2, 3, 0, 3, 0,189, 1, 0, 0,100, 0, 0, 0, 0, 0, 0, 0,252,226, 20, 8, 16, 56, 20, 8,152,252, 24, 8,
+104,184, 20, 8,104,184, 20, 8,120, 96, 94, 8,200, 95, 95, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,180, 0, 0, 0,
+120, 96, 94, 8, 62, 0, 0, 0, 1, 0, 0, 0, 96, 97, 94, 8, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,122, 67,205,204,204,189,205,204,140, 63, 0, 0, 0, 0, 0, 0,122, 67, 0, 0,160,192, 0, 0,160, 64, 0, 0, 0, 0,
+ 16, 0, 0, 0, 0, 0, 0, 0,206, 2, 0, 0, 17, 0, 0, 0,169, 1, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 17, 0, 0, 0,
+169, 1, 0, 0, 17, 0, 0, 0,206, 2, 0, 0, 10,215, 35, 60, 10,215, 35, 60, 0, 96,106, 70, 0, 0,122, 68, 0, 0, 0, 0,
+ 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 64,107,101, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,197, 95, 8,
+ 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,122, 67,205,204,204,189,205,204,140, 63,
+ 68, 65, 84, 65,140, 1, 0, 0, 96, 97, 94, 8, 60, 0, 0, 0, 1, 0, 0, 0,200, 95, 95, 8,120, 96, 94, 8, 1, 0, 0, 0,
+ 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32,193, 0, 0,128, 63,
+ 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 65, 0, 0,128, 63,
+ 1,184,157, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,140, 63, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 80, 1,128,191, 0, 0,128,191, 0, 0, 0, 0, 0, 0, 0, 0,184,175, 31, 65, 0, 0, 32, 65,
+ 33,195, 79, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,161, 14,106, 63, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 29,254,249,195,125,254, 71,194, 0, 0, 0, 0, 0, 0, 0, 0,173,128,249, 67,138, 0, 72, 66,
+ 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 65, 1, 0, 7, 0, 2, 0, 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 66, 0, 0,128, 63, 10,215, 35, 60, 0, 0,250, 67, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,104,194, 95, 8, 64, 1,104, 1, 64, 1,104, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 60, 1, 0, 0,200, 95, 95, 8, 65, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 96, 97, 94, 8, 5, 0, 0, 0,
+ 0, 0, 0, 0,240,109,101, 8, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 57, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255, 0, 0, 0, 0, 83, 82, 0, 0,100, 0, 0, 0,192,148, 95, 8, 70, 0, 0, 0,
+ 1, 0, 0, 0, 8,163, 95, 8, 80,237, 89, 8, 0, 0, 0, 0, 0, 0, 0, 0, 83, 82,115, 99,114,101,101,110, 46, 48, 48, 49,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 32, 99, 94, 8, 8,151, 95, 8, 80,151, 95, 8,
+216,153, 95, 8, 32,154, 95, 8, 16,157, 95, 8, 24,190, 95, 8, 0, 0,255, 4, 0, 0,255, 3, 0, 5, 0, 4, 1, 0, 2, 0,
+ 0, 0, 0, 0, 1, 0, 8, 0, 68, 65, 84, 65, 20, 0, 0, 0, 32, 99, 94, 8, 71, 0, 0, 0, 1, 0, 0, 0, 88,149, 95, 8,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0, 88,149, 95, 8, 71, 0, 0, 0,
+ 1, 0, 0, 0,160,149, 95, 8, 32, 99, 94, 8, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0,
+160,149, 95, 8, 71, 0, 0, 0, 1, 0, 0, 0,232,149, 95, 8, 88,149, 95, 8, 0, 0, 0, 0, 0, 5, 0, 4, 0, 0, 0, 0,
+ 68, 65, 84, 65, 20, 0, 0, 0,232,149, 95, 8, 71, 0, 0, 0, 1, 0, 0, 0, 48,150, 95, 8,160,149, 95, 8, 0, 0, 0, 0,
+ 0, 5, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0, 48,150, 95, 8, 71, 0, 0, 0, 1, 0, 0, 0,120,150, 95, 8,
+232,149, 95, 8, 0, 0, 0, 0, 0, 0,252, 0, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0,120,150, 95, 8, 71, 0, 0, 0,
+ 1, 0, 0, 0,192,150, 95, 8, 48,150, 95, 8, 0, 0, 0, 0, 0, 5,252, 0, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0,
+192,150, 95, 8, 71, 0, 0, 0, 1, 0, 0, 0, 8,151, 95, 8,120,150, 95, 8, 0, 0, 0, 0, 0, 0,232, 3, 0, 0, 0, 0,
+ 68, 65, 84, 65, 20, 0, 0, 0, 8,151, 95, 8, 71, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,192,150, 95, 8, 0, 0, 0, 0,
+ 0, 5,232, 3, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0, 80,151, 95, 8, 72, 0, 0, 0, 1, 0, 0, 0,152,151, 95, 8,
+ 0, 0, 0, 0, 88,149, 95, 8,160,149, 95, 8, 1, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,152,151, 95, 8,
+ 72, 0, 0, 0, 1, 0, 0, 0,224,151, 95, 8, 80,151, 95, 8, 32, 99, 94, 8,232,149, 95, 8, 1, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 24, 0, 0, 0,224,151, 95, 8, 72, 0, 0, 0, 1, 0, 0, 0, 40,152, 95, 8,152,151, 95, 8, 32, 99, 94, 8,
+ 48,150, 95, 8, 1, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0, 40,152, 95, 8, 72, 0, 0, 0, 1, 0, 0, 0,
+112,152, 95, 8,224,151, 95, 8,232,149, 95, 8,120,150, 95, 8, 1, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,
+112,152, 95, 8, 72, 0, 0, 0, 1, 0, 0, 0,184,152, 95, 8, 40,152, 95, 8, 48,150, 95, 8,120,150, 95, 8, 0, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,184,152, 95, 8, 72, 0, 0, 0, 1, 0, 0, 0, 0,153, 95, 8,112,152, 95, 8,
+ 88,149, 95, 8,192,150, 95, 8, 1, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0, 0,153, 95, 8, 72, 0, 0, 0,
+ 1, 0, 0, 0, 72,153, 95, 8,184,152, 95, 8,160,149, 95, 8, 8,151, 95, 8, 1, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+ 24, 0, 0, 0, 72,153, 95, 8, 72, 0, 0, 0, 1, 0, 0, 0,144,153, 95, 8, 0,153, 95, 8,192,150, 95, 8, 8,151, 95, 8,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,144,153, 95, 8, 72, 0, 0, 0, 1, 0, 0, 0,216,153, 95, 8,
+ 72,153, 95, 8, 48,150, 95, 8,192,150, 95, 8, 1, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,216,153, 95, 8,
+ 72, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,144,153, 95, 8,120,150, 95, 8, 8,151, 95, 8, 1, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65,220, 0, 0, 0, 32,154, 95, 8, 73, 0, 0, 0, 1, 0, 0, 0, 0,156, 95, 8, 0, 0, 0, 0, 32, 99, 94, 8,
+ 48,150, 95, 8,120,150, 95, 8,232,149, 95, 8, 0, 0, 0, 0,192, 53, 95, 8,192, 53, 95, 8,192, 56, 95, 8,192, 56, 95, 8,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0,249, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0,229, 0, 0, 0,249, 0, 0, 0,
+ 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0,228, 0, 0, 0, 4, 0, 5, 0, 2, 0, 4, 4, 1, 5,229, 0, 3, 1, 3, 0,
+ 37, 3, 0, 0,100, 0, 0, 0, 0, 0, 0, 0,208,226, 20, 8, 16, 56, 20, 8,108,217, 23, 8, 36,197, 20, 8, 36,197, 20, 8,
+ 48,155, 95, 8,176,142,101, 8,232,124, 94, 8, 8,211,100, 8, 68, 65, 84, 65,160, 0, 0, 0, 48,155, 95, 8, 63, 0, 0, 0,
+ 1, 0, 0, 0,176,142,101, 8, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,224,159, 68, 0, 0, 0, 0,
+ 0, 0,100, 67,165,194,122,193,133,213,161, 68,112,222, 71,192,122, 31,103, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,128, 67, 0, 0, 40, 66, 0, 0,200, 68, 0, 0,225, 67, 0, 0, 0, 63,225,122,180, 63, 0, 0, 1, 0,
+ 1, 0, 1, 0, 6, 0,255,255, 0, 0, 6, 0, 24,190, 95, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,100, 0, 0, 0,
+ 0, 0,150, 1, 68, 65, 84, 65, 60, 1, 0, 0,176,142,101, 8, 65, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 48,155, 95, 8,
+ 5, 0, 0, 0, 0, 0, 0, 0, 96, 97, 95, 8, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0,
+ 57, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255, 0, 0, 0, 0, 68, 65, 84, 65,220, 0, 0, 0, 0,156, 95, 8,
+ 73, 0, 0, 0, 1, 0, 0, 0, 16,157, 95, 8, 32,154, 95, 8,192,150, 95, 8, 88,149, 95, 8,160,149, 95, 8, 8,151, 95, 8,
+ 0, 0, 0, 0,192, 59, 95, 8,192, 59, 95, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0,235, 3, 0, 0,
+ 0, 4, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0,235, 3, 0, 0,255, 3, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 4, 0, 0,
+ 0, 4, 0, 0, 6, 0, 0, 0, 1, 0, 7, 7, 1, 5, 1, 0, 1, 1, 3, 1,145, 2, 0, 0,100, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 16, 56, 20, 8, 0, 0, 0, 0, 0, 0, 0, 0,188,234, 20, 8, 0, 0, 0, 0, 0, 0, 0, 0,184,236,101, 8,
+184,236,101, 8, 68, 65, 84, 65,220, 0, 0, 0, 16,157, 95, 8, 73, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,156, 95, 8,
+ 48,150, 95, 8,192,150, 95, 8, 8,151, 95, 8,120,150, 95, 8, 0, 0, 0, 0,192, 62, 95, 8,192, 62, 95, 8,192, 65, 95, 8,
+204, 65, 95, 8,232,135, 69, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,193, 59,175, 61, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,111, 18, 3,187, 0, 0, 0, 0, 0, 0, 0,128, 0, 0, 0,128, 0, 0, 0,128,
+ 0, 0,128, 63, 0, 0, 0, 0, 0, 5, 0, 0,255, 0, 0, 0,229, 3, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0,255, 0, 0, 0,
+ 19, 1, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 20, 1, 0, 0,229, 3, 0, 0, 7, 0, 8, 0, 1, 0, 1, 1, 1, 5,210, 2,
+ 1, 1, 1, 0,151, 2, 0, 0,100, 0, 0, 0, 0, 0, 0, 0, 32,227, 20, 8, 16, 56, 20, 8, 88,146, 11, 8,132,166, 20, 8,
+132,166, 20, 8, 32,158, 95, 8, 56,162, 95, 8,184, 15, 96, 8,184, 15, 96, 8, 68, 65, 84, 65,140, 1, 0, 0, 32,158, 95, 8,
+ 60, 0, 0, 0, 1, 0, 0, 0,224,159, 95, 8, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63,
+ 0, 0, 0, 0,120,208,132,190,180,208, 4, 61, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63,
+ 0, 0, 0, 0,120,208,132, 62,180,208, 4,189, 0, 0, 0, 0, 0, 0,128, 63,232,135, 69, 61, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,193, 59,175, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,111, 18, 3,187,
+ 0, 0, 0, 0,221,245, 76,188, 87,211, 53, 59, 0, 0, 0, 0, 0, 0,128, 63, 83,227,165, 65, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 14,255, 58, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,255,255,249,195,
+ 0, 0, 0, 0,120,208,132, 62,181,208, 4,189, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 83,227,165, 65, 0, 0, 7, 0, 2, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 12, 66, 0, 0,128, 63,205,204,204, 61, 0, 0,250, 67,120,208,132,190,180,208, 4, 61, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,104,194, 95, 8,120, 2,106, 1,120, 2,106, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 32, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 60, 1, 0, 0,224,159, 95, 8,
+ 65, 0, 0, 0, 1, 0, 0, 0, 80,161, 95, 8, 32,158, 95, 8, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0,
+ 0, 79, 65, 68, 32, 70, 73, 76, 69, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 1, 0, 0, 0, 57, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255,
+ 0, 0, 0, 0, 68, 65, 84, 65,180, 0, 0, 0, 80,161, 95, 8, 62, 0, 0, 0, 1, 0, 0, 0, 56,162, 95, 8,224,159, 95, 8,
+ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,122, 67, 0, 0, 32,193, 0, 0, 32, 65, 0, 0, 0, 0, 0, 0,122, 67,
+ 0, 0, 32,193, 0, 0, 32, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10,215, 35, 60, 10,215, 35, 60,
+ 0, 96,106, 70, 0, 0,122, 68, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 66, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,160, 0, 0, 0, 56,162, 95, 8, 63, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 80,161, 95, 8, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,224,159, 68, 0, 0, 0, 0, 0, 0,100, 67,
+ 0, 0, 0, 0, 0,224,159, 68, 0,128,118,195, 0, 64,237, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,128, 67, 0, 0, 40, 66, 0, 0,200, 68, 0, 0,225, 67, 0, 0, 0, 63,225,122,180, 63, 0, 0, 1, 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,150, 1,
+ 83, 82, 0, 0,100, 0, 0, 0, 8,163, 95, 8, 70, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,192,148, 95, 8, 0, 0, 0, 0,
+ 0, 0, 0, 0, 83, 82,115, 99,114,101,101,110, 46, 48, 48, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0,160,163, 95, 8,184,166, 95, 8, 0,167, 95, 8,200,171, 95, 8, 16,172, 95, 8,240,184, 95, 8, 24,190, 95, 8,
+ 0, 0,255, 4, 0, 0,255, 3, 0, 5, 0, 4, 1, 0, 3, 0, 0, 0, 0, 0, 1, 0, 9, 0, 68, 65, 84, 65, 20, 0, 0, 0,
+160,163, 95, 8, 71, 0, 0, 0, 1, 0, 0, 0,232,163, 95, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 20, 0, 0, 0,232,163, 95, 8, 71, 0, 0, 0, 1, 0, 0, 0, 48,164, 95, 8,160,163, 95, 8, 0, 0, 0, 0,
+ 0, 0, 0, 4, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0, 48,164, 95, 8, 71, 0, 0, 0, 1, 0, 0, 0,120,164, 95, 8,
+232,163, 95, 8, 0, 0, 0, 0, 0, 5, 0, 4, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0,120,164, 95, 8, 71, 0, 0, 0,
+ 1, 0, 0, 0,192,164, 95, 8, 48,164, 95, 8, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0,
+192,164, 95, 8, 71, 0, 0, 0, 1, 0, 0, 0, 8,165, 95, 8,120,164, 95, 8, 0, 0, 0, 0, 0, 0,252, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 20, 0, 0, 0, 8,165, 95, 8, 71, 0, 0, 0, 1, 0, 0, 0, 80,165, 95, 8,192,164, 95, 8, 0, 0, 0, 0,
+ 0, 5,252, 0, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0, 80,165, 95, 8, 71, 0, 0, 0, 1, 0, 0, 0,152,165, 95, 8,
+ 8,165, 95, 8, 0, 0, 0, 0, 0, 0,228, 3, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0,152,165, 95, 8, 71, 0, 0, 0,
+ 1, 0, 0, 0,224,165, 95, 8, 80,165, 95, 8, 0, 0, 0, 0, 0, 5,228, 3, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0,
+224,165, 95, 8, 71, 0, 0, 0, 1, 0, 0, 0, 40,166, 95, 8,152,165, 95, 8, 0, 0, 0, 0, 0, 0,120, 2, 0, 0, 0, 0,
+ 68, 65, 84, 65, 20, 0, 0, 0, 40,166, 95, 8, 71, 0, 0, 0, 1, 0, 0, 0,112,166, 95, 8,224,165, 95, 8, 0, 0, 0, 0,
+ 0, 5,120, 2, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0,112,166, 95, 8, 71, 0, 0, 0, 1, 0, 0, 0,184,166, 95, 8,
+ 40,166, 95, 8, 0, 0, 0, 0,248, 2,120, 2, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0,184,166, 95, 8, 71, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0,112,166, 95, 8, 0, 0, 0, 0,248, 2,228, 3, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,
+ 0,167, 95, 8, 72, 0, 0, 0, 1, 0, 0, 0, 72,167, 95, 8, 0, 0, 0, 0,232,163, 95, 8, 48,164, 95, 8, 1, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0, 72,167, 95, 8, 72, 0, 0, 0, 1, 0, 0, 0,144,167, 95, 8, 0,167, 95, 8,
+160,163, 95, 8,120,164, 95, 8, 1, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,144,167, 95, 8, 72, 0, 0, 0,
+ 1, 0, 0, 0,216,167, 95, 8, 72,167, 95, 8,160,163, 95, 8,192,164, 95, 8, 1, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+ 24, 0, 0, 0,216,167, 95, 8, 72, 0, 0, 0, 1, 0, 0, 0, 32,168, 95, 8,144,167, 95, 8,120,164, 95, 8, 8,165, 95, 8,
+ 1, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0, 32,168, 95, 8, 72, 0, 0, 0, 1, 0, 0, 0,104,168, 95, 8,
+216,167, 95, 8,192,164, 95, 8, 8,165, 95, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,104,168, 95, 8,
+ 72, 0, 0, 0, 1, 0, 0, 0,176,168, 95, 8, 32,168, 95, 8,232,163, 95, 8, 80,165, 95, 8, 1, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 24, 0, 0, 0,176,168, 95, 8, 72, 0, 0, 0, 1, 0, 0, 0,248,168, 95, 8,104,168, 95, 8, 48,164, 95, 8,
+152,165, 95, 8, 1, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,248,168, 95, 8, 72, 0, 0, 0, 1, 0, 0, 0,
+ 64,169, 95, 8,176,168, 95, 8, 80,165, 95, 8,152,165, 95, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,
+ 64,169, 95, 8, 72, 0, 0, 0, 1, 0, 0, 0,136,169, 95, 8,248,168, 95, 8,192,164, 95, 8,224,165, 95, 8, 1, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,136,169, 95, 8, 72, 0, 0, 0, 1, 0, 0, 0,208,169, 95, 8, 64,169, 95, 8,
+ 80,165, 95, 8,224,165, 95, 8, 1, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,208,169, 95, 8, 72, 0, 0, 0,
+ 1, 0, 0, 0, 24,170, 95, 8,136,169, 95, 8,152,165, 95, 8, 40,166, 95, 8, 1, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+ 24, 0, 0, 0, 24,170, 95, 8, 72, 0, 0, 0, 1, 0, 0, 0, 96,170, 95, 8,208,169, 95, 8, 8,165, 95, 8, 40,166, 95, 8,
+ 1, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0, 96,170, 95, 8, 72, 0, 0, 0, 1, 0, 0, 0,168,170, 95, 8,
+ 24,170, 95, 8,224,165, 95, 8, 40,166, 95, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,168,170, 95, 8,
+ 72, 0, 0, 0, 1, 0, 0, 0,240,170, 95, 8, 96,170, 95, 8,224,165, 95, 8,112,166, 95, 8, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 24, 0, 0, 0,240,170, 95, 8, 72, 0, 0, 0, 1, 0, 0, 0, 56,171, 95, 8,168,170, 95, 8, 40,166, 95, 8,
+112,166, 95, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0, 56,171, 95, 8, 72, 0, 0, 0, 1, 0, 0, 0,
+128,171, 95, 8,240,170, 95, 8, 80,165, 95, 8,184,166, 95, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,
+128,171, 95, 8, 72, 0, 0, 0, 1, 0, 0, 0,200,171, 95, 8, 56,171, 95, 8,152,165, 95, 8,184,166, 95, 8, 0, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,200,171, 95, 8, 72, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,128,171, 95, 8,
+112,166, 95, 8,184,166, 95, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,220, 0, 0, 0, 16,172, 95, 8, 73, 0, 0, 0,
+ 1, 0, 0, 0,240,173, 95, 8, 0, 0, 0, 0,160,163, 95, 8,192,164, 95, 8, 8,165, 95, 8,120,164, 95, 8, 0, 0, 0, 0,
+ 64,195, 94, 8, 64,195, 94, 8,112,197, 94, 8,112,197, 94, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0,249, 0, 0, 0,
+ 0, 0, 0, 0, 0, 5, 0, 0,229, 0, 0, 0,249, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0,228, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0, 4, 4, 1, 5,229, 0, 3, 0, 3, 1, 37, 3, 0, 0,100, 0, 0, 0, 0, 0, 0, 0,208,226, 20, 8,
+ 16, 56, 20, 8,108,217, 23, 8, 36,197, 20, 8, 36,197, 20, 8, 32,173, 95, 8, 48, 79, 95, 8, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65,160, 0, 0, 0, 32,173, 95, 8, 63, 0, 0, 0, 1, 0, 0, 0, 48, 79, 95, 8, 0, 0, 0, 0, 4, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,224,159, 68, 0, 0, 0, 0, 0, 0,100, 67, 73,194,122,193,133,213,161, 68, 60,222, 71,192,
+122, 31,103, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 67, 0, 0, 40, 66, 0, 0,200, 68,
+ 0, 0,225, 67, 0, 0, 0, 63,225,122,180, 63, 0, 0, 1, 0, 1, 0, 1, 0, 6, 0,255,255, 0, 0, 6, 0, 24,190, 95, 8,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,150, 1, 68, 65, 84, 65, 60, 1, 0, 0, 48, 79, 95, 8,
+ 65, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 32,173, 95, 8, 5, 0, 0, 0, 0, 0, 0, 0,160,230,100, 8, 20, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 57, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255,
+ 0, 0, 0, 0, 68, 65, 84, 65,220, 0, 0, 0,240,173, 95, 8, 73, 0, 0, 0, 1, 0, 0, 0, 0,175, 95, 8, 16,172, 95, 8,
+ 80,165, 95, 8,232,163, 95, 8, 48,164, 95, 8,152,165, 95, 8, 0, 0, 0, 0,152, 81, 95, 8,152, 81, 95, 8,200, 83, 95, 8,
+200, 83, 95, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0,231, 3, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0,231, 3, 0, 0,
+251, 3, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0,252, 3, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 1, 0, 7, 7, 1, 5, 5, 0,
+ 3, 0, 3, 1,145, 2, 0, 0,100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 56, 20, 8,196,189, 20, 8, 0, 0, 0, 0,
+188,234, 20, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,220, 0, 0, 0, 0,175, 95, 8,
+ 73, 0, 0, 0, 1, 0, 0, 0,248,179, 95, 8,240,173, 95, 8,192,164, 95, 8,224,165, 95, 8, 40,166, 95, 8, 8,165, 95, 8,
+ 0, 0, 0, 0,208, 74, 95, 8,208, 74, 95, 8, 0, 77, 95, 8, 0, 77, 95, 8,228, 56,142, 61, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,185,206,105, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,111, 18, 3,187,
+ 0, 0, 0, 0, 0, 0, 0,128, 0, 0, 0,128, 0, 0, 0,128, 0, 0,128, 63, 0, 0, 0, 0, 0, 5, 0, 0,255, 0, 0, 0,
+117, 2, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0,255, 0, 0, 0, 19, 1, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 20, 1, 0, 0,
+117, 2, 0, 0, 0, 0, 0, 0, 1, 0, 8, 8, 1, 5, 98, 1, 1, 0, 3, 1, 9, 1, 0, 0,100, 0, 0, 0, 0, 0, 0, 0,
+252,226, 20, 8, 16, 56, 20, 8,156, 57, 25, 8, 0, 0, 0, 0, 44,199, 20, 8, 16,176, 95, 8,136,178, 95, 8, 0, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65,136, 0, 0, 0, 16,176, 95, 8, 64, 0, 0, 0, 1, 0, 0, 0,200,176, 95, 8, 0, 0, 0, 0,
+ 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,122, 67, 0, 0, 0, 0, 0, 0, 0, 65, 0, 0, 0, 0, 0, 0,122, 67,
+ 0, 0, 0, 0, 0, 0, 0, 65, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 98, 1, 0, 0, 17, 0, 0, 0, 1, 5, 0, 0,
+ 0, 0, 0, 0, 16, 0, 0, 0, 17, 0, 0, 0, 1, 5, 0, 0, 17, 0, 0, 0, 98, 1, 0, 0, 0, 0, 32, 65, 0, 0,128, 64,
+ 0, 0,250, 70, 0, 0, 0, 66,205,204,204, 61, 0, 0, 32, 65, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65,140, 1, 0, 0,200,176, 95, 8, 60, 0, 0, 0, 1, 0, 0, 0,136,178, 95, 8, 16,176, 95, 8, 1, 0, 0, 0,
+ 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63,
+ 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63,
+228, 56,142, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,185,206,105, 62, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,111, 18, 3,187, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63,
+102,102,102, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 38,140, 64, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,255,255,249,195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63,
+ 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,102,102,102, 65, 0, 0, 7, 0, 2, 0, 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 66, 0, 0,128, 63, 10,215, 35, 60, 0, 0,250, 67, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,104,194, 95, 8,127, 2,194, 0,127, 2,194, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65, 60, 1, 0, 0,136,178, 95, 8, 65, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,200,176, 95, 8, 5, 0, 0, 0,
+ 0, 0, 0, 0,168, 67,105, 8, 20, 0, 0, 0, 0, 65, 86, 69, 32, 84, 65, 82, 71, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,116, 49, 46, 98,108,101,110,100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 2, 0, 0, 0, 57, 0, 2, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255, 0, 0, 0, 0, 68, 65, 84, 65,220, 0, 0, 0,248,179, 95, 8, 73, 0, 0, 0,
+ 1, 0, 0, 0,240,184, 95, 8, 0,175, 95, 8,112,166, 95, 8,184,166, 95, 8,152,165, 95, 8, 40,166, 95, 8, 0, 0, 0, 0,
+ 48, 87, 95, 8, 48, 87, 95, 8, 48, 90, 95, 8, 48, 90, 95, 8,228, 56,142, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,191, 72, 20, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,111, 18, 3,187, 0, 0, 0, 0,
+ 0, 0, 0,128, 0, 0, 0,128, 0, 0, 0,128, 0, 0,128, 63,251, 2, 0, 0, 0, 5, 0, 0,123, 2, 0, 0,225, 3, 0, 0,
+251, 2, 0, 0, 0, 5, 0, 0,123, 2, 0, 0,143, 2, 0, 0,251, 2, 0, 0, 0, 5, 0, 0,144, 2, 0, 0,225, 3, 0, 0,
+ 0, 0, 0, 0, 1, 0, 8, 8, 6, 2, 82, 1, 3, 0, 3, 1, 9, 1, 0, 0,100, 0, 0, 0, 0, 0, 0, 0,252,226, 20, 8,
+ 16, 56, 20, 8,156, 57, 25, 8, 0, 0, 0, 0, 44,199, 20, 8, 8,181, 95, 8,128,183, 95, 8, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 65, 84, 65,136, 0, 0, 0, 8,181, 95, 8, 64, 0, 0, 0, 1, 0, 0, 0,192,181, 95, 8, 0, 0, 0, 0, 8, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,122, 67, 0, 0, 0, 0, 0, 0, 0, 65, 0, 0, 0, 0, 0, 0,122, 67, 0, 0, 0, 0,
+ 0, 0, 0, 65, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 49, 1, 0, 0, 17, 0, 0, 0,124, 2, 0, 0, 0, 0, 0, 0,
+ 16, 0, 0, 0, 17, 0, 0, 0,124, 2, 0, 0, 17, 0, 0, 0, 49, 1, 0, 0, 0, 0, 32, 65, 0, 0,128, 64, 0, 0,250, 70,
+ 0, 0, 0, 66,205,204,204, 61, 0, 0, 32, 65, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+140, 1, 0, 0,192,181, 95, 8, 60, 0, 0, 0, 1, 0, 0, 0,128,183, 95, 8, 8,181, 95, 8, 1, 0, 0, 0, 0, 0,128, 63,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63,228, 56,142, 61,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,191, 72, 20, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,111, 18, 3,187, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63,102,102,102, 65,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42,251,220, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,255,255,249,195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,102,102,102, 65, 0, 0, 7, 0, 2, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 66, 0, 0,128, 63, 10,215, 35, 60, 0, 0,250, 67, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,104,194, 95, 8, 62, 1,152, 0, 62, 1,152, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+ 60, 1, 0, 0,128,183, 95, 8, 65, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,192,181, 95, 8, 5, 0, 0, 0, 0, 0, 0, 0,
+ 80, 52,105, 8, 20, 0, 0, 0, 0, 65, 86, 69, 32, 84, 65, 82, 71, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,116, 49, 46, 98,108,101,110,100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 2, 0, 0, 0, 57, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,255,255, 0, 0, 0, 0, 68, 65, 84, 65,220, 0, 0, 0,240,184, 95, 8, 73, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0,248,179, 95, 8,224,165, 95, 8, 80,165, 95, 8,184,166, 95, 8,112,166, 95, 8, 0, 0, 0, 0, 48, 93, 95, 8,
+ 48, 93, 95, 8,152,154, 94, 8,152,154, 94, 8,228, 56,142, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+205,220, 29, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,111, 18, 3,187, 0, 0, 0, 0, 0, 0, 0,128,
+ 0, 0, 0,128, 0, 0, 0,128, 0, 0,128, 63, 0, 0, 0, 0,245, 2, 0, 0,123, 2, 0, 0,225, 3, 0, 0, 0, 0, 0, 0,
+245, 2, 0, 0,123, 2, 0, 0,143, 2, 0, 0, 0, 0, 0, 0,245, 2, 0, 0,144, 2, 0, 0,225, 3, 0, 0, 0, 0, 0, 0,
+ 1, 0, 2, 2,246, 2, 82, 1, 1, 0, 3, 0,189, 1, 0, 0,100, 0, 0, 0, 0, 0, 0, 0,252,226, 20, 8, 16, 56, 20, 8,
+152,252, 24, 8,104,184, 20, 8,104,184, 20, 8, 0,186, 95, 8,168,188, 95, 8, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,
+180, 0, 0, 0, 0,186, 95, 8, 62, 0, 0, 0, 1, 0, 0, 0,232,186, 95, 8, 0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0,160,192, 0, 0,210, 66,205,204,204,189,205,204,140, 63, 0, 0,160,192, 0, 0,210, 66,205,204,204,189,205,204,140, 63,
+ 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 82, 1, 0, 0, 17, 0, 0, 0,181, 2, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0,
+ 17, 0, 0, 0,181, 2, 0, 0, 17, 0, 0, 0, 82, 1, 0, 0, 10,215, 35, 60, 10,215, 35, 60, 0, 96,106, 70, 0, 0,122, 68,
+ 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 24,194, 94, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 81, 0, 0, 0, 0, 0, 0,160,192, 0, 0,210, 66,205,204,204,189,
+205,204,140, 63, 68, 65, 84, 65,140, 1, 0, 0,232,186, 95, 8, 60, 0, 0, 0, 1, 0, 0, 0,168,188, 95, 8, 0,186, 95, 8,
+ 1, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,128, 63,228, 56,142, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,205,220, 29, 62, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,111, 18, 3,187, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,128, 63,102,102,102, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,179,146,207, 64, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255,249,195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,102,102,102, 65, 0, 0, 7, 0, 2, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 66, 0, 0,128, 63, 10,215, 35, 60, 0, 0,250, 67,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,104,194, 95, 8,122, 1,170, 0,
+122, 1,170, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65, 60, 1, 0, 0,168,188, 95, 8, 65, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,232,186, 95, 8,
+ 5, 0, 0, 0, 0, 0, 0, 0, 72, 68,102, 8, 20, 0, 0, 0, 0, 79, 65, 68, 32, 70, 73, 76, 69, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0,
+ 57, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255, 0, 0, 0, 0, 83, 67, 0, 0,128, 3, 0, 0, 24,190, 95, 8,
+ 58, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 67, 49, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,104,194, 95, 8, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,200,193, 95, 8, 24,194, 95, 8,200,193, 95, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,250, 0,100, 0,
+100, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,100, 0,141, 0,
+ 64, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0,255,255,255,127,153,153,185, 63,154,153,153,153,204,204,236, 63, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 95, 0, 0, 0, 4, 0, 0, 0, 0, 0, 8, 0,
+ 25, 0, 0, 0, 0, 0, 0, 64, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 47, 47, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 47,114,101,110,100,101,114,
+ 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 47, 0, 35, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 28, 0, 0, 0,200,193, 95, 8, 56, 0, 0, 0, 1, 0, 0, 0, 24,194, 95, 8,
+ 0, 0, 0, 0, 1, 0, 0, 0, 23, 7, 7, 0, 1, 0, 0, 0,120, 2,106, 1, 0,197, 95, 8, 68, 65, 84, 65, 28, 0, 0, 0,
+ 24,194, 95, 8, 56, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,200,193, 95, 8, 1, 0, 0, 0, 39, 7, 7, 0, 0, 0, 0, 0,
+120, 2,111, 0,104,194, 95, 8, 79, 66, 0, 0,100, 2, 0, 0,104,194, 95, 8, 53, 0, 0, 0, 1, 0, 0, 0, 0,197, 95, 8,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 66, 67, 97,109,101,114, 97, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64,201, 95, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,198, 15, 2,193, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63,
+ 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,221, 15,201, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,166,119,151,180,
+ 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,191,166,119,151,180, 0, 0, 0, 0, 0, 0, 0, 0,198, 15, 2,193,
+ 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0,192,185,171, 40,
+ 0, 0, 0, 0, 0, 0,128, 63, 1, 0, 0, 0, 0, 4, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 1, 0,100, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 6, 41,100, 63, 0, 0,128, 63, 6, 41,100, 63, 0, 0, 0, 0,
+ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,
+ 79, 66, 0, 0,100, 2, 0, 0, 0,197, 95, 8, 53, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,104,194, 95, 8, 0, 0, 0, 0,
+ 0, 0, 0, 0, 79, 66, 80,108, 97,110,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,152,199, 95, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63,
+ 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63,
+ 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,166,119,151,180, 0, 0,128, 63, 0, 0, 0, 0,
+ 0, 0, 0,128, 0, 0,128,191,166,119,151,180, 0, 0, 0, 0, 0, 0, 0,128,198, 15, 2,193, 0, 0, 0,128, 0, 0,128, 63,
+ 1, 0, 0, 0, 0, 4, 0, 0, 0, 68, 1, 2, 79, 66, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0,100, 0, 0, 0, 0, 0,
+ 0, 0,128, 63, 0, 0,128, 63, 10,215, 35, 61, 0, 0,128, 63,205,204,204, 61, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,128, 63, 0, 64, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 77, 69, 0, 0,184, 0, 0, 0,
+152,199, 95, 8, 50, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 69, 80,108,
+ 97,110,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 96, 52, 95, 8,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,201, 95, 8,
+ 0, 0, 0, 0, 0, 0, 0, 0,128,200, 95, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0,128,179, 0, 0, 64, 52, 0, 0, 0, 0, 0, 0,128, 63,
+ 2, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 4, 0, 4, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 68, 65, 84, 65, 80, 0, 0, 0,128,200, 95, 8, 47, 0, 0, 0, 4, 0, 0, 0, 0, 0,128, 63,255,255,127, 63,
+ 0, 0, 0, 0, 0, 0, 0, 0,255,127, 2,255, 0, 0,128, 63, 0, 0,128,191, 0, 0, 0, 0, 0, 0, 0, 0,255,127, 2,255,
+ 1, 0,128,191,253,255,127,191, 0, 0, 0, 0, 0, 0, 0, 0,255,127, 2,255,250,255,127,191, 3, 0,128, 63, 0, 0, 0, 0,
+ 0, 0, 0, 0,255,127, 2,255, 68, 65, 84, 65, 12, 0, 0, 0, 0,201, 95, 8, 44, 0, 0, 0, 1, 0, 0, 0, 0, 0, 3, 0,
+ 2, 0, 1, 0, 16, 0, 15, 0, 67, 65, 0, 0,108, 0, 0, 0, 64,201, 95, 8, 25, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 65, 67, 97,109,101,114, 97, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,205,204,204, 61, 0, 0,200, 66, 0, 0,128, 63,
+ 0, 0,160, 65, 0, 0, 12, 66, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 71, 76, 79, 66, 12, 0, 0, 0,188,239,255,191, 74, 0, 0, 0, 1, 0, 0, 0,192,148, 95, 8,
+ 1, 0,128, 0, 0, 0, 0, 0, 85, 83, 69, 82,204, 1, 0, 0, 64,229, 85, 8, 69, 0, 0, 0, 1, 0, 0, 0,225, 24, 63, 0,
+ 4, 0, 0, 0, 47, 0, 0, 0, 0, 0,109,112, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 47, 0,115,114, 47,112,101,111,112,108,101, 47,116,114, 97, 99,101, 47,102,111,110,116, 47, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 47, 0,101,110,100,101,114, 47, 0,108,101, 47, 98,108,101,110,100, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 47, 0,105, 99,115, 47,116,101,120,116,117,114,101,115, 47, 0,100, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 47, 0,115,114, 47,112,101,111,112,108,101, 47,116,111,110, 47,112,108,117,103,105,110,115, 47, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 0, 68, 78, 65, 49, 28, 61, 0, 0, 44, 3, 64, 8, 0, 0, 0, 0, 1, 0, 0, 0, 83, 68, 78, 65,
+ 78, 65, 77, 69,169, 3, 0, 0, 42,110,101,120,116, 0, 42,112,114,101,118, 0, 42,102,105,114,115,116, 0, 42,108, 97,115,116,
+ 0,116, 97,103, 49, 0,108,101,110, 0, 42,110, 97,109,101, 0, 42,110,101,120,116,110, 97,109,101, 0,108,101,118,101,108, 0,
+116, 97,103, 50, 0,116, 97,103, 51, 0,112, 97,100, 0,120, 0,121, 0,122, 0,119, 0,120,109,105,110, 0,120,109, 97,120, 0,
+121,109,105,110, 0,121,109, 97,120, 0, 42,110,101,119,105,100, 0, 42,108,105, 98, 0,110, 97,109,101, 91, 50, 52, 93, 0,117,
+115, 0,102,108, 97,103, 0,105,100, 0, 42,105,100, 98,108,111, 99,107, 0, 42,102,105,108,101,100, 97,116, 97, 0,110, 97,109,
+101, 91, 49, 54, 48, 93, 0,116,111,116, 0, 99,117,114,118,101, 0, 99,117,114, 0, 98,108,111, 99,107,116,121,112,101, 0,115,
+104,111,119,107,101,121, 0,112,111,115, 0,116,111,116,101,108,101,109, 0,116,121,112,101, 0,114,116, 0, 42,100, 97,116, 97,
+ 0, 42,114,101,102,107,101,121, 0,101,108,101,109,115,116,114, 91, 51, 50, 93, 0,101,108,101,109,115,105,122,101, 0, 99,117,
+114,118, 97,108, 0, 98,108,111, 99,107, 0, 42,105,112,111, 0, 42,102,114,111,109, 0,116,111,116,107,101,121, 0,115,108,117,
+114,112,104, 0, 97, 99,116,107,101,121, 0, 42, 42,115, 99,114,105,112,116,115, 0, 42,102,108, 97,103, 0, 97, 99,116,115, 99,
+114,105,112,116, 0,116,111,116,115, 99,114,105,112,116, 0, 42,108,105,110,101, 0, 98,108,101,110, 0,102,108, 97,103,115, 0,
+110,108,105,110,101,115, 0,108,105,110,101,115, 0, 42, 99,117,114,108, 0, 42,115,101,108,108, 0, 99,117,114, 99, 0,115,101,
+108, 99, 0, 42,117,110,100,111, 95, 98,117,102, 0,117,110,100,111, 95,112,111,115, 0,117,110,100,111, 95,108,101,110, 0, 42,
+ 99,111,109,112,105,108,101,100, 0,115,105,122,101, 0,115,101,101,107, 0,100,114, 97,119,122,111,111,109, 0,104,111,108,100,
+ 0, 99,108,105,112,115,116, 97, 0, 99,108,105,112,101,110,100, 0,110,101,116,115,116, 97, 0,110,101,116,101,110,100, 0,108,
+101,110,115, 0,100,114, 97,119,115,105,122,101, 0,104,111,108,111,108,101,110, 0,104,111,108,111,108,101,110, 49, 0,115, 99,
+114,105,112,116,108,105,110,107, 0, 42, 97,110,105,109, 0, 42,105, 98,117,102, 0, 42,109,105,112,109, 97,112, 91, 49, 48, 93,
+ 0,111,107, 0,108, 97,115,116,102,114, 97,109,101, 0,108, 97,115,116,113,117, 97,108,105,116,121, 0,116,112, 97,103,101,102,
+108, 97,103, 0,116,111,116, 98,105,110,100, 0,120,114,101,112, 0,121,114,101,112, 0,116,119,115,116, 97, 0,116,119,101,110,
+100, 0, 98,105,110,100, 99,111,100,101, 0, 42,114,101,112, 98,105,110,100, 0, 42,112, 97, 99,107,101,100,102,105,108,101, 0,
+116,101,120, 99,111, 0,109, 97,112,116,111, 0,109, 97,112,116,111,110,101,103, 0, 98,108,101,110,100,116,121,112,101, 0, 42,
+111, 98,106,101, 99,116, 0, 42,116,101,120, 0,112,114,111,106,120, 0,112,114,111,106,121, 0,112,114,111,106,122, 0,109, 97,
+112,112,105,110,103, 0,111,102,115, 91, 51, 93, 0,115,105,122,101, 91, 51, 93, 0,116,101,120,102,108, 97,103, 0, 99,111,108,
+111,114,109,111,100,101,108, 0,114, 0,103, 0, 98, 0,107, 0,100,101,102, 95,118, 97,114, 0, 99,111,108,102, 97, 99, 0,110,
+111,114,102, 97, 99, 0,118, 97,114,102, 97, 99, 0, 42,104, 97,110,100,108,101, 0, 42,112,110, 97,109,101, 0, 42,115,116,110,
+ 97,109,101,115, 0,115,116,121,112,101,115, 0,118, 97,114,115, 0, 42,118, 97,114,115,116,114, 0, 42,114,101,115,117,108,116,
+ 0, 42, 99,102,114, 97, 0,100, 97,116, 97, 91, 51, 50, 93, 0, 40, 42,100,111,105,116, 41, 40, 41, 0, 40, 42, 99, 97,108,108,
+ 98, 97, 99,107, 41, 40, 41, 0,118,101,114,115,105,111,110, 0, 97, 0,105,112,111,116,121,112,101, 0,100, 97,116, 97, 91, 49,
+ 54, 93, 0, 42,105,109, 97, 0, 42, 99,117, 98,101, 91, 54, 93, 0,105,109, 97,116, 91, 52, 93, 91, 52, 93, 0,115,116,121,112,
+101, 0,110,111,116,108, 97,121, 0, 99,117, 98,101,114,101,115, 0,110,111,105,115,101,115,105,122,101, 0,116,117,114, 98,117,
+108, 0, 98,114,105,103,104,116, 0, 99,111,110,116,114, 97,115,116, 0,114,102, 97, 99, 0,103,102, 97, 99, 0, 98,102, 97, 99,
+ 0,102,105,108,116,101,114,115,105,122,101, 0,110,111,105,115,101,100,101,112,116,104, 0,110,111,105,115,101,116,121,112,101,
+ 0,105,109, 97,102,108, 97,103, 0, 99,114,111,112,120,109,105,110, 0, 99,114,111,112,121,109,105,110, 0, 99,114,111,112,120,
+109, 97,120, 0, 99,114,111,112,121,109, 97,120, 0,120,114,101,112,101, 97,116, 0,121,114,101,112,101, 97,116, 0,101,120,116,
+101,110,100, 0,102,114, 97,109,101,115, 0,111,102,102,115,101,116, 0,115,102,114, 97, 0,102,105,101, 95,105,109, 97, 0, 42,
+110,111,114, 0, 42,112,108,117,103,105,110, 0, 42, 99,111, 98, 97, 0, 42,101,110,118, 0,102,114, 97,100,117,114, 91, 52, 93,
+ 91, 50, 93, 0,109,111,100,101, 0,116,111,116,101,120, 0,101,110,101,114,103,121, 0,100,105,115,116, 0,115,112,111,116,115,
+105,122,101, 0,115,112,111,116, 98,108,101,110,100, 0,104, 97,105,110,116, 0, 97,116,116, 49, 0, 97,116,116, 50, 0, 98,117,
+102,115,105,122,101, 0,115, 97,109,112, 0,115,104, 97,100,115,112,111,116,115,105,122,101, 0, 98,105, 97,115, 0,115,111,102,
+116, 0,116,101,120, 97, 99,116, 0,115,104, 97,100,104, 97,108,111,115,116,101,112, 0, 42,109,116,101,120, 91, 56, 93, 0,108,
+ 97,121, 0,115,112,101, 99,114, 0,115,112,101, 99,103, 0,115,112,101, 99, 98, 0,109,105,114,114, 0,109,105,114,103, 0,109,
+105,114, 98, 0, 97,109, 98,114, 0, 97,109, 98, 98, 0, 97,109, 98,103, 0, 97,109, 98, 0,101,109,105,116, 0, 97,110,103, 0,
+115,112,101, 99,116,114, 97, 0, 97,108,112,104, 97, 0,114,101,102, 0,115,112,101, 99, 0,122,111,102,102,115, 0, 97,100,100,
+ 0,107,102, 97, 99, 0,104, 97,114, 0,115,101,101,100, 49, 0,115,101,101,100, 50, 0,109,111,100,101, 50, 0,102,108, 97,114,
+101, 99, 0,115,116, 97,114, 99, 0,108,105,110,101, 99, 0,114,105,110,103, 99, 0,104, 97,115,105,122,101, 0,102,108, 97,114,
+101,115,105,122,101, 0,115,117, 98,115,105,122,101, 0,102,108, 97,114,101, 98,111,111,115,116, 0,114,103, 98,115,101,108, 0,
+112,114, 95,116,121,112,101, 0,115,101,112,116,101,120, 0,112,114, 95, 98, 97, 99,107, 0,112,114, 95,108, 97,109,112, 0,112,
+ 97,100, 49, 0, 42,114,101,110, 0,102,114,105, 99,116,105,111,110, 0,102,104, 0,114,101,102,108,101, 99,116, 0,102,104,100,
+105,115,116, 0,120,121,102,114,105, 99,116, 0,100,121,110, 97,109,111,100,101, 0,110, 97,109,101, 91, 50, 53, 53, 93, 0,110,
+ 97,109,101,110,117,108,108, 0,115, 99, 97,108,101, 0,115,101,108, 99,111,108, 0,101,120,112,120, 0,101,120,112,121, 0,101,
+120,112,122, 0,114, 97,100, 0,114, 97,100, 50, 0,115, 0,109, 97,120,114, 97,100, 50, 0, 42,109, 97,116, 0, 42,105,109, 97,
+116, 0, 42, 98, 98, 0,101,108,101,109,115, 0,100,105,115,112, 0, 42, 42,109, 97,116, 0,116,111,116, 99,111,108, 0,108,111,
+ 99, 91, 51, 93, 0,114,111,116, 91, 51, 93, 0,119,105,114,101,115,105,122,101, 0,114,101,110,100,101,114,115,105,122,101, 0,
+116,104,114,101,115,104, 0,118,101, 99, 91, 51, 93, 91, 51, 93, 0, 97,108,102, 97, 0,115, 91, 51, 93, 91, 50, 93, 0,104, 49,
+ 0,104, 50, 0,102, 49, 0,102, 50, 0,102, 51, 0,104,105,100,101, 0,118,101, 99, 91, 52, 93, 0,115, 91, 50, 93, 0,109, 97,
+116, 95,110,114, 0,112,110,116,115,117, 0,112,110,116,115,118, 0,114,101,115,111,108,117, 0,114,101,115,111,108,118, 0,111,
+114,100,101,114,117, 0,111,114,100,101,114,118, 0,102,108, 97,103,117, 0,102,108, 97,103,118, 0, 42,107,110,111,116,115,117,
+ 0, 42,107,110,111,116,115,118, 0, 42, 98,112, 0, 42, 98,101,122,116, 0,110,117,114, 98, 0, 42, 98,101,118,111, 98,106, 0,
+ 42,116,101,120,116,111,110, 99,117,114,118,101, 0, 42,112, 97,116,104, 0, 42,107,101,121, 0, 98,101,118, 0, 42,111,114, 99,
+111, 0,112, 97,116,104,108,101,110, 0, 98,101,118,114,101,115,111,108, 0,119,105,100,116,104, 0,101,120,116, 49, 0,101,120,
+116, 50, 0,115,112, 97, 99,101,109,111,100,101, 0,115,112, 97, 99,105,110,103, 0,108,105,110,101,100,105,115,116, 0,115,104,
+101, 97,114, 0,102,115,105,122,101, 0,120,111,102, 0,121,111,102, 0, 42,115,116,114, 0,102, 97,109,105,108,121, 91, 50, 52,
+ 93, 0, 42,118,102,111,110,116, 0,109, 97,120,114, 99,116, 0,116,111,116,114, 99,116, 0, 97,100,114, 99,111,100,101, 0,118,
+ 97,114,116,121,112,101, 0,116,111,116,118,101,114,116, 0,105,112,111, 0,101,120,116,114, 97,112, 0, 98,105,116,109, 97,115,
+107, 0,118, 49, 0,118, 50, 0,118, 51, 0,118, 52, 0,112,117,110,111, 0,101,100, 99,111,100,101, 0,117,118, 91, 52, 93, 91,
+ 50, 93, 0, 99,111,108, 91, 52, 93, 0,110,111, 91, 51, 93, 0,116,114, 97,110,115,112, 0,116,105,108,101, 0, 42,116,112, 97,
+103,101, 0, 42, 99,108,117,116, 0, 99,111, 91, 51, 93, 0, 99,111, 91, 50, 93, 0,101,102,102,101, 99,116, 0, 42,109,102, 97,
+ 99,101, 0, 42,100,102, 97, 99,101, 0, 42,116,102, 97, 99,101, 0, 42,109,118,101,114,116, 0, 42,109, 99,111,108, 0, 42,109,
+115,116,105, 99,107,121, 0, 42,116,101,120, 99,111,109,101,115,104, 0, 42,111, 99, 0, 42,115,117,109,111,104, 97,110,100,108,
+101, 0,116,111,116,102, 97, 99,101, 0,115,109,111,111,116,104,114,101,115,104, 0,115,117, 98,100,105,118, 0, 99,117, 98,101,
+109, 97,112,115,105,122,101, 0,114,116,102, 0,112,110,116,115,119, 0,116,121,112,101,117, 0,116,121,112,101,118, 0,116,121,
+112,101,119, 0, 42,100,101,102, 0,109, 97,120, 0, 42, 42,111, 98, 0,112, 97,114,116,121,112,101, 0,112, 97,114, 49, 0,112,
+ 97,114, 50, 0,112, 97,114, 51, 0, 42,112, 97,114,101,110,116, 0, 42,116,114, 97, 99,107, 0,110,101,116,119,111,114,107, 0,
+ 42,108,105,102,101, 0,100,108,111, 99, 91, 51, 93, 0,111,114,105,103, 91, 51, 93, 0,100,115,105,122,101, 91, 51, 93, 0,100,
+114,111,116, 91, 51, 93, 0,113,117, 97,116, 91, 52, 93, 0,100,113,117, 97,116, 91, 52, 93, 0,111, 98,109, 97,116, 91, 52, 93,
+ 91, 52, 93, 0,112, 97,114,101,110,116,105,110,118, 91, 52, 93, 91, 52, 93, 0, 99,111,108, 98,105,116,115, 0,116,114, 97,110,
+115,102,108, 97,103, 0,105,112,111,102,108, 97,103, 0,116,114, 97, 99,107,102,108, 97,103, 0,117,112,102,108, 97,103, 0,105,
+112,111,119,105,110, 0,115, 99, 97,102,108, 97,103, 0,115, 99, 97,118,105,115,102,108, 97,103, 0, 98,111,117,110,100,116,121,
+112,101, 0,100,117,112,111,110, 0,100,117,112,111,102,102, 0,100,117,112,115,116, 97, 0,100,117,112,101,110,100, 0,115,102,
+ 0, 99,116,105,109,101, 0,109, 97,115,115, 0,100, 97,109,112,105,110,103, 0,105,110,101,114,116,105, 97, 0,114,100, 97,109,
+112,105,110,103, 0,115,105,122,101,102, 97, 99, 0,100,116, 0,100,116,120, 0, 97, 99,116, 99,111,108, 0,112,114,111,112, 0,
+115,101,110,115,111,114,115, 0, 99,111,110,116,114,111,108,108,101,114,115, 0, 97, 99,116,117, 97,116,111,114,115, 0,108, 98,
+117,102, 0,112,111,114,116, 0, 98, 98,115,105,122,101, 91, 51, 93, 0,100,102,114, 97,115, 0,103, 97,109,101,102,108, 97,103,
+ 0, 97,110,105,115,111,116,114,111,112,105, 99, 70,114,105, 99,116,105,111,110, 91, 51, 93, 0,109,105,115,116,121,112,101, 0,
+104,111,114,114, 0,104,111,114,103, 0,104,111,114, 98, 0,104,111,114,107, 0,122,101,110,114, 0,122,101,110,103, 0,122,101,
+110, 98, 0,122,101,110,107, 0, 97,109, 98,107, 0,102, 97,115,116, 99,111,108, 0,101,120,112,111,115,117,114,101, 0,103,114,
+ 97,118,105,116,121, 0,115,107,121,116,121,112,101, 0,109,105,115,105, 0,109,105,115,116,115,116, 97, 0,109,105,115,116,100,
+105,115,116, 0,109,105,115,116,104,105, 0,115,116, 97,114,114, 0,115,116, 97,114,103, 0,115,116, 97,114, 98, 0,115,116, 97,
+114,107, 0,115,116, 97,114,115,105,122,101, 0,115,116, 97,114,109,105,110,100,105,115,116, 0,115,116, 97,114,100,105,115,116,
+ 0,115,116, 97,114, 99,111,108,110,111,105,115,101, 0,100,111,102,115,116, 97, 0,100,111,102,101,110,100, 0,100,111,102,109,
+105,110, 0,100,111,102,109, 97,120, 0,104,101,109,105,114,101,115, 0,109, 97,120,105,116,101,114, 0,100,114, 97,119,116,121,
+112,101, 0,115,117, 98,115,104,111,111,116,112, 0,115,117, 98,115,104,111,111,116,101, 0,110,111,100,101,108,105,109, 0,109,
+ 97,120,115,117, 98,108, 97,109,112, 0,112, 97,109, 97, 0,112, 97,109,105, 0,101,108,109, 97, 0,101,108,109,105, 0,109, 97,
+120,110,111,100,101, 0, 99,111,110,118,101,114,103,101,110, 99,101, 0,114, 97,100,102, 97, 99, 0,103, 97,109,109, 97, 0,115,
+120, 0,115,121, 0, 99,102,114, 97, 0,101,102,114, 97, 0,105,109, 97,103,101,115, 0,102,114, 97,109, 97,112,116,111, 0,102,
+114, 97,109,101,108,101,110, 0, 98,108,117,114,102, 97, 99, 0,101,100,103,101, 82, 0,101,100,103,101, 71, 0,101,100,103,101,
+ 66, 0,109, 97,120,105,109,115,105,122,101, 0,120,115, 99,104, 0,121,115, 99,104, 0,120, 97,115,112, 0,121, 97,115,112, 0,
+120,112, 97,114,116,115, 0,121,112, 97,114,116,115, 0,115, 97,102,101,116,121, 0, 98,111,114,100,101,114, 0,119,105,110,112,
+111,115, 0,112,108, 97,110,101,115, 0,105,109,116,121,112,101, 0, 98,117,102,102,108, 97,103, 0,113,117, 97,108,105,116,121,
+ 0,115, 99,101,109,111,100,101, 0, 97,108,112,104, 97,109,111,100,101, 0,100,111,103, 97,109,109, 97, 0,111,115, 97, 0,102,
+114,115, 95,115,101, 99, 0,101,100,103,101,105,110,116, 0,112,111,115,116,109,117,108, 0,112,111,115,116,103, 97,109,109, 97,
+ 0,112,111,115,116, 97,100,100, 0,112,111,115,116,105,103, 97,109,109, 97, 0, 98, 97, 99,107, 98,117,102, 91, 49, 54, 48, 93,
+ 0,112,105, 99, 91, 49, 54, 48, 93, 0,102,116,121,112,101, 91, 49, 54, 48, 93, 0,109,111,118,105,101, 91, 49, 54, 48, 93, 0,
+ 42, 99, 97,109,101,114, 97, 0, 42,119,111,114,108,100, 0, 42,115,101,116, 0, 98, 97,115,101, 0, 42, 98, 97,115, 97, 99,116,
+ 0, 42,103,114,111,117,112, 0, 99,117,114,115,111,114, 91, 51, 93, 0, 42,102, 99, 97,109, 0, 42,101,100, 0, 42,114, 97,100,
+105,111, 0,122,111,111,109, 0, 98,108,101,110,100, 0,120,105,109, 0,121,105,109, 0, 42,114,101, 99,116, 0,115,112, 97, 99,
+101,116,121,112,101, 0,118,105,101,119,109, 97,116, 91, 52, 93, 91, 52, 93, 0,118,105,101,119,105,110,118, 91, 52, 93, 91, 52,
+ 93, 0,112,101,114,115,109, 97,116, 91, 52, 93, 91, 52, 93, 0,112,101,114,115,105,110,118, 91, 52, 93, 91, 52, 93, 0,118,105,
+101,119,113,117, 97,116, 91, 52, 93, 0,112,101,114,115,112, 0,118,105,101,119, 0,108,111, 99, 97,108,118,105,101,119, 0,108,
+ 97,121, 97, 99,116, 0,115, 99,101,110,101,108,111, 99,107, 0, 97,114,111,117,110,100, 0, 99, 97,109,122,111,111,109, 0,103,
+114,105,100, 0,110,101, 97,114, 0,102, 97,114, 0,109,120, 0,109,121, 0,109,120,111, 0,109,121,111, 0,112,114, 95,120,109,
+105,110, 0,112,114, 95,120,109, 97,120, 0,112,114, 95,121,109,105,110, 0,112,114, 95,121,109, 97,120, 0,112,114, 95,115,105,
+122,101,120, 0,112,114, 95,115,105,122,101,121, 0,103,114,105,100,108,105,110,101,115, 0,118,105,101,119, 98,117,116, 0,112,
+114, 95,102, 97, 99,120, 0,112,114, 95,102, 97, 99,121, 0, 42, 98,103,112,105, 99, 0, 42,108,111, 99, 97,108,118,100, 0,118,
+101,114,116, 0,104,111,114, 0,109, 97,115,107, 0,109,105,110, 91, 50, 93, 0,109, 97,120, 91, 50, 93, 0,109,105,110,122,111,
+111,109, 0,109, 97,120,122,111,111,109, 0,115, 99,114,111,108,108, 0,107,101,101,112,116,111,116, 0,107,101,101,112, 97,115,
+112,101, 99,116, 0,107,101,101,112,122,111,111,109, 0,114,111,119, 98,117,116, 0,118, 50,100, 0, 42,101,100,105,116,105,112,
+111, 0,105,112,111,107,101,121, 0,116,111,116,105,112,111, 0,108,111, 99,107, 0, 98,117,116,111,102,115, 0, 99,104, 97,110,
+110,101,108, 0,109,101,110,117,110,114, 0, 99,117,114,115,101,110,115, 0, 99,117,114, 97, 99,116, 0,109, 97,105,110, 98, 0,
+109, 97,105,110, 98,111, 0, 42,108,111, 99,107,112,111,105,110, 0,116,101,120,110,114, 0,116,101,120,102,114,111,109, 0,115,
+104,111,119,103,114,111,117,112, 0,114,101, 99,116,120, 0,114,101, 99,116,121, 0, 99,117,114,121, 0,109,111,100,101,108,116,
+121,112,101, 0,115, 99,114,105,112,116, 98,108,111, 99,107, 0,112, 97,100, 50, 0, 42,102,105,108,101,108,105,115,116, 0,116,
+111,116,102,105,108,101, 0,116,105,116,108,101, 91, 50, 52, 93, 0,100,105,114, 91, 49, 54, 48, 93, 0,102,105,108,101, 91, 56,
+ 48, 93, 0,111,102,115, 0,115,111,114,116, 0,109, 97,120,110, 97,109,101,108,101,110, 0, 99,111,108,108,117,109,115, 0, 42,
+108,105, 98,102,105,108,101,100, 97,116, 97, 0,114,101,116,118, 97,108, 0,109,101,110,117, 0, 97, 99,116, 0, 40, 42,114,101,
+116,117,114,110,102,117,110, 99, 41, 40, 41, 0,111,111,112,115, 0,118,105,115,105,102,108, 97,103, 0, 42,105,109, 97,103,101,
+ 0,112, 97,100, 51, 0,105,109, 97,110,114, 0, 99,117,114,116,105,108,101, 0,108,101,102,116, 0, 42,116,101,120,116, 0,116,
+111,112, 0,118,105,101,119,108,105,110,101,115, 0,102,111,110,116, 95,105,100, 0,108,104,101,105,103,104,116, 0,112,105,120,
+ 95,112,101,114, 95,108,105,110,101, 0,116,120,116,115, 99,114,111,108,108, 0,116,120,116, 98, 97,114, 0, 42,112,121, 95,100,
+114, 97,119, 0, 42,112,121, 95,101,118,101,110,116, 0, 42,112,121, 95, 98,117,116,116,111,110, 0,100,117,112,102,108, 97,103,
+ 0,115, 97,118,101,116,105,109,101, 0,116,101,109,112,100,105,114, 91, 54, 52, 93, 0,102,111,110,116,100,105,114, 91, 54, 52,
+ 93, 0,114,101,110,100,101,114,100,105,114, 91, 54, 52, 93, 0,116,101,120,116,117,100,105,114, 91, 54, 52, 93, 0,112,108,117,
+103,116,101,120,100,105,114, 91, 54, 52, 93, 0,112,108,117,103,115,101,113,100,105,114, 91, 54, 52, 93, 0,115,111,117,110,100,
+100,105,114, 91, 54, 52, 93, 0,118,101,114,115,105,111,110,115, 0,118,101,114,116, 98, 97,115,101, 0,101,100,103,101, 98, 97,
+115,101, 0, 97,114,101, 97, 98, 97,115,101, 0, 42,115, 99,101,110,101, 0,115,116, 97,114,116,120, 0,101,110,100,120, 0,115,
+116, 97,114,116,121, 0,101,110,100,121, 0,115,105,122,101,120, 0,115,105,122,101,121, 0,115, 99,101,110,101,110,114, 0,115,
+ 99,114,101,101,110,110,114, 0,102,117,108,108, 0,109, 97,105,110,119,105,110, 0,119,105,110, 97,107,116, 0, 42,110,101,119,
+118, 0,118,101, 99, 0, 42,118, 49, 0, 42,118, 50, 0, 42,118, 51, 0, 42,118, 52, 0, 42,102,117,108,108, 0, 42,104,101, 97,
+100,113,117,101,117,101, 0, 42,104,113, 0, 42,119,105,110,113,117,101,117,101, 0, 42,119,113, 0,119,105,110,109, 97,116, 91,
+ 52, 93, 91, 52, 93, 0,104,101, 97,100,114, 99,116, 0,119,105,110,114, 99,116, 0,104,101, 97,100,119,105,110, 0,119,105,110,
+ 0,104,101, 97,100,101,114,116,121,112,101, 0, 98,117,116,115,112, 97, 99,101,116,121,112,101, 0,119,105,110,120, 0,119,105,
+110,121, 0,104,101, 97,100, 95,115,119, 97,112, 0,104,101, 97,100, 95,101,113,117, 97,108, 0,119,105,110, 95,115,119, 97,112,
+ 0,119,105,110, 95,101,113,117, 97,108, 0,104,101, 97,100, 98,117,116,108,101,110, 0,104,101, 97,100, 98,117,116,111,102,115,
+ 0, 99,117,114,115,111,114, 0, 40, 42,104,101, 97,100, 99,104, 97,110,103,101, 41, 40, 41, 0, 40, 42,119,105,110, 99,104, 97,
+110,103,101, 41, 40, 41, 0, 40, 42,104,101, 97,100,100,114, 97,119, 41, 40,118,111,105,100, 41, 0, 40, 42,119,105,110,100,114,
+ 97,119, 41, 40,118,111,105,100, 41, 0, 40, 42,104,101, 97,100,113,114,101, 97,100, 41, 40, 41, 0, 40, 42,119,105,110,113,114,
+101, 97,100, 41, 40, 41, 0,115,112, 97, 99,101,100, 97,116, 97, 0,117,105, 98,108,111, 99,107,115, 0, 42, 99,117,114,115, 99,
+114,101,101,110, 0,100,105,115,112,108, 97,121,109,111,100,101, 0,102,105,108,101,102,108, 97,103,115, 0,110, 97,109,101, 91,
+ 52, 48, 93, 0, 42,115,101, 49, 0, 42,115,101, 50, 0, 42,115,101, 51, 0,110,114, 0,100,111,110,101, 0, 42,115,116,114,105,
+112,100, 97,116, 97, 0,100,105,114, 91, 56, 48, 93, 0,111,114,120, 0,111,114,121, 0,110, 97,109,101, 91, 56, 48, 93, 0, 42,
+110,101,119,115,101,113, 0,115,116, 97,114,116, 0,115,116, 97,114,116,111,102,115, 0,101,110,100,111,102,115, 0,115,116, 97,
+114,116,115,116,105,108,108, 0,101,110,100,115,116,105,108,108, 0,109, 97, 99,104,105,110,101, 0,100,101,112,116,104, 0,115,
+116, 97,114,116,100,105,115,112, 0,101,110,100,100,105,115,112, 0,109,117,108, 0,104, 97,110,100,115,105,122,101, 0, 42,115,
+116,114,105,112, 0, 42, 99,117,114,101,108,101,109, 0,102, 97, 99,102, 48, 0,102, 97, 99,102, 49, 0, 42,115,101,113, 49, 0,
+ 42,115,101,113, 50, 0, 42,115,101,113, 51, 0,115,101,113, 98, 97,115,101, 0, 42,115,101,113, 98, 97,115,101,112, 0,109,101,
+116, 97,115,116, 97, 99,107, 0, 98,117,116,116,121,112,101, 0,115,116, 97, 0,101,110,100, 0,108,105,102,101,116,105,109,101,
+ 0,116,111,116,112, 97,114,116, 0,115,101,101,100, 0,110,111,114,109,102, 97, 99, 0,111, 98,102, 97, 99, 0,114, 97,110,100,
+102, 97, 99, 0,116,101,120,102, 97, 99, 0,114, 97,110,100,108,105,102,101, 0,102,111,114, 99,101, 91, 51, 93, 0,100, 97,109,
+112, 0,110, 97, 98,108, 97, 0,118,101, 99,116,115,105,122,101, 0,100,101,102,118,101, 99, 91, 51, 93, 0,109,117,108,116, 91,
+ 52, 93, 0,108,105,102,101, 91, 52, 93, 0, 99,104,105,108,100, 91, 52, 93, 0,109, 97,116, 91, 52, 93, 0,116,101,120,109, 97,
+112, 0, 99,117,114,109,117,108,116, 0,115,116, 97,116,105, 99,115,116,101,112, 0, 42,107,101,121,115, 0,104,101,105,103,104,
+116, 0,110, 97,114,114,111,119, 0,115,112,101,101,100, 0,109,105,110,102, 97, 99, 0,116,105,109,101,111,102,102,115, 0, 42,
+111, 98, 0,112,114,101,109, 97,116, 91, 52, 93, 91, 52, 93, 0,112,111,115,116,109, 97,116, 91, 52, 93, 91, 52, 93, 0,118,101,
+ 99, 91, 51, 93, 0,102, 97, 99, 0,108,101,110,111, 0, 97,108,112,104, 97,111, 0,101,102,102, 91, 50, 93, 0,105,116,101,114,
+ 0,108, 97,115,116,102,114, 97, 0,108,105,109, 98, 98, 97,115,101, 0,101,102,102, 91, 51, 93, 0,101,102,102,103, 91, 51, 93,
+ 0,101,102,102,110, 91, 51, 93, 0,109,101,109, 0,115,108,111,119, 0,116,111,116,121, 0,116,111,116,120, 0,120,121, 99,111,
+110,115,116,114, 97,105,110,116, 0,116,111,116,100,101,102, 0,100,101,102, 95,115, 99,114,111,108,108, 0,108,105,109, 98, 95,
+115, 99,114,111,108,108, 0,100,120, 0,100,121, 0, 42,105,100, 0,108,105,110,107, 0,102, 97,115,101, 0,115,117, 98,102, 97,
+115,101, 0,109,111,117,115,101, 95,109,111,118,101, 95,114,101,100,114, 97,119, 0,105,109, 97,102, 97,115,101, 0,100,105,114,
+115,108,105, 0,100,105,114,115,108,105, 95,108,105,110,101,115, 0,100,105,114,115,108,105, 95,115,120, 0,100,105,114,115,108,
+105, 95,101,121, 0,100,105,114,115,108,105, 95,101,120, 0,100,105,114,115,108,105, 95,104, 0,105,109, 97,115,108,105, 0,102,
+105,108,101,115,101,108,109,101,110,117,105,116,101,109, 0,105,109, 97,115,108,105, 95,115,120, 0,105,109, 97,115,108,105, 95,
+101,121, 0,105,109, 97,115,108,105, 95,101,120, 0,105,109, 97,115,108,105, 95,104, 0,100,115,115,120, 0,100,115,115,121, 0,
+100,115,101,120, 0,100,115,101,121, 0,100,101,115,120, 0,100,101,115,121, 0,100,101,101,120, 0,100,101,101,121, 0,102,115,
+115,120, 0,102,115,115,121, 0,102,115,101,120, 0,102,115,101,121, 0,100,115,100,104, 0,102,115,100,104, 0,102,101,115,120,
+ 0,102,101,115,121, 0,102,101,101,120, 0,102,101,101,121, 0,105,110,102,115,120, 0,105,110,102,115,121, 0,105,110,102,101,
+120, 0,105,110,102,101,121, 0,100,110,115,120, 0,100,110,115,121, 0,100,110,119, 0,100,110,104, 0,102,110,115,120, 0,102,
+110,115,121, 0,102,110,119, 0,102,110,104, 0,102,111,108,101, 91, 49, 50, 56, 93, 0,100,111,114, 91, 49, 50, 56, 93, 0,102,
+105,108,101, 91, 49, 50, 56, 93, 0,100,105,114, 91, 49, 50, 56, 93, 0, 42,102,105,114,115,116,100,105,114, 0, 42,102,105,114,
+115,116,102,105,108,101, 0,116,111,112,100,105,114, 0,116,111,116, 97,108,100,105,114,115, 0,104,105,108,105,116,101, 0,116,
+111,112,102,105,108,101, 0,116,111,116, 97,108,102,105,108,101,115, 0,105,109, 97,103,101, 95,115,108,105,100,101,114, 0,115,
+108,105,100,101,114, 95,104,101,105,103,104,116, 0,115,108,105,100,101,114, 95,115,112, 97, 99,101, 0,116,111,112,105,109, 97,
+ 0,116,111,116, 97,108,105,109, 97, 0, 99,117,114,105,109, 97,120, 0, 99,117,114,105,109, 97,121, 0, 42,102,105,114,115,116,
+ 95,115,101,108, 95,105,109, 97, 0, 42,104,105,108,105,116,101, 95,105,109, 97, 0,116,111,116, 97,108, 95,115,101,108,101, 99,
+116,101,100, 0,105,109, 97, 95,114,101,100,114, 97,119, 0, 42, 99,109, 97,112, 0,110, 97,109,101, 91, 51, 50, 93, 0,111,116,
+121,112,101, 0,100, 97,116, 97, 0,111,108,100, 0, 42,112,111,105,110, 0, 42,111,108,100,112,111,105,110, 0,114,101,115,101,
+116,100,105,115,116, 0,108, 97,115,116,118, 97,108, 0, 42,109, 97, 0,107,101,121, 0,113,117, 97,108, 0,113,117, 97,108, 50,
+ 0,118, 97,108,117,101, 91, 51, 50, 93, 0,109, 97,120,118, 97,108,117,101, 91, 51, 50, 93, 0,109, 97,116,101,114,105, 97,108,
+ 78, 97,109,101, 91, 51, 50, 93, 0,100, 97,109,112,116,105,109,101,114, 0, 97,110,103,108,101, 0,114, 97,110,103,101, 0, 97,
+120,105,115, 0,100,101,108, 97,121, 0,112,114,111,112,110, 97,109,101, 91, 51, 50, 93, 0,109, 97,116,110, 97,109,101, 91, 51,
+ 50, 93, 0, 97,120,105,115,102,108, 97,103, 0, 42,115,101,110,100,111, 98, 0,112,114,111,112,116,121,112,101, 0,109,101,115,
+115, 97,103,101, 91, 51, 50, 93, 0,112,117,108,115,101, 0,102,114,101,113, 0,116,111,116,108,105,110,107,115, 0, 42, 42,108,
+105,110,107,115, 0,105,110,118,101,114,116, 0,102,114,101,113, 50, 0,115,116,114, 91, 49, 50, 56, 93, 0, 42,109,121,110,101,
+119, 0,105,110,112,117,116,115, 0,116,111,116,115,108,105,110,107,115, 0, 42, 42,115,108,105,110,107,115, 0,118, 97,108, 0,
+118, 97,108,111, 0,112, 97,100, 53, 0,116,105,109,101, 0,115,110,100,110,114, 0, 42,115,111,117,110,100, 0,112, 97,100, 91,
+ 51, 93, 0, 42,109,101, 0,108,105,110, 86,101,108,111, 99,105,116,121, 91, 51, 93, 0,108,111, 99, 97,108,102,108, 97,103, 0,
+102,111,114, 99,101,108,111, 99, 91, 51, 93, 0,102,111,114, 99,101,114,111,116, 91, 51, 93, 0,108,105,110,101, 97,114,118,101,
+108,111, 99,105,116,121, 91, 51, 93, 0, 97,110,103,117,108, 97,114,118,101,108,111, 99,105,116,121, 91, 51, 93, 0, 98,117,116,
+115,116, 97, 0, 98,117,116,101,110,100, 0,109,105,110, 0,118,105,115,105,102, 97, 99, 0,109,105,110,108,111, 99, 91, 51, 93,
+ 0,109, 97,120,108,111, 99, 91, 51, 93, 0,109,105,110,114,111,116, 91, 51, 93, 0,109, 97,120,114,111,116, 91, 51, 93, 0,100,
+105,115,116,114,105, 98,117,116,105,111,110, 0,105,110,116, 95, 97,114,103, 95, 49, 0,105,110,116, 95, 97,114,103, 95, 50, 0,
+102,108,111, 97,116, 95, 97,114,103, 95, 49, 0,102,108,111, 97,116, 95, 97,114,103, 95, 50, 0, 42,100,101,115,116,111, 98, 0,
+103,111, 0, 97, 99, 99,101,108,108,101,114, 97,116,105,111,110, 0,109, 97,120,115,112,101,101,100, 0,109, 97,120,114,111,116,
+115,112,101,101,100, 0,109, 97,120,116,105,108,116,115,112,101,101,100, 0,114,111,116,100, 97,109,112, 0,116,105,108,116,100,
+ 97,109,112, 0,115,112,101,101,100,100, 97,109,112, 0,116,111,116,112,111,114,116, 0, 97, 99,116,112,111,114,116, 0, 42,112,
+111,114,116, 97,108,115, 0, 42, 99, 97,109,112,111,115, 0, 42, 99, 97,109,102,114, 97,109,101, 0, 42,100,121,110, 97,109,101,
+115,104, 0, 42,116,101,120,109,101,115,104, 0,116,111,116, 99, 97,109, 0,116,111,116,102,114, 97, 0, 42,115,101, 99,116,111,
+114, 0,111,108,100,108,111, 99, 91, 51, 93, 0,115,112,101,101,100, 91, 51, 93, 0,111,108,100,108,111, 99, 49, 91, 51, 93, 0,
+108,111, 99, 49, 91, 51, 93, 0,115,112,101,101,100, 49, 91, 51, 93, 0,115,116, 97,114,116,108,111, 99, 91, 51, 93, 0,115,116,
+ 97,114,116,114,111,116, 91, 51, 93, 0,114,111,116,115,112,101,101,100, 91, 51, 93, 0,111,108,100,105,109, 97,116, 91, 52, 93,
+ 91, 52, 93, 0,102,114,105, 99,116, 0,114,111,116,102,114,105, 99,116, 0, 97,120,115,105,122,101, 0,102,114,105, 99,116,102,
+ 97, 99, 0, 97,101,114,111, 0,112, 97,100,102, 0, 42,115,101,110,115,111,114,115, 0, 42, 99,111,110,116, 97, 99,116, 0, 42,
+ 99,111,108,108,105,115,105,111,110, 0, 42,102,108,111,111,114, 0, 42,111,108,100,109,101,115,104, 0,116,111,116,115,101,110,
+115, 0, 97, 99,116,115,101,110,115, 0,116,105,109,101,114, 0,100,102,108, 97,103, 0,115,116, 97,116,101, 91, 52, 93, 0, 99,
+111,108,108,111, 99, 91, 51, 93, 0,102,108,111,111,114,108,111, 99, 91, 51, 93, 0,108,105,110,107,115, 0, 42,115, 97,109,112,
+108,101, 0, 42,115,110,100, 95,115,111,117,110,100, 0,118,111,108,117,109,101, 0,112, 97,110,110,105,110,103, 0, 97,116,116,
+101,110,117, 97,116,105,111,110, 0,112,105,116, 99,104, 0, 99,104, 97,110,110,101,108,115, 0, 42,103,107,101,121, 0,111,107,
+101,121, 0,103,111, 98,106,101, 99,116, 0,103,107,101,121, 0, 42, 97, 99,116,105,118,101, 0,114,101,115,116,109, 97,116, 91,
+ 52, 93, 91, 52, 93, 0,111,102,102,115,101,116, 91, 51, 93, 0,108,101,110,103,116,104, 0,100,117,109,109,121, 0, 98,111,110,
+101, 98, 97,115,101, 0,114,101,115, 49, 0,114,101,115, 50, 0,114,101,115, 51, 0, 0, 0, 0, 84, 89, 80, 69,149, 0, 0, 0,
+ 99,104, 97,114, 0,117, 99,104, 97,114, 0,115,104,111,114,116, 0,117,115,104,111,114,116, 0,105,110,116, 0,108,111,110,103,
+ 0,117,108,111,110,103, 0,102,108,111, 97,116, 0,100,111,117, 98,108,101, 0,118,111,105,100, 0, 76,105,110,107, 0, 76,105,
+115,116, 66, 97,115,101, 0, 77,101,109, 72,101, 97,100, 0, 77,101,109, 84, 97,105,108, 0,118,101, 99, 50,115, 0,118,101, 99,
+ 50,105, 0,118,101, 99, 50,102, 0,118,101, 99, 50,100, 0,118,101, 99, 51,105, 0,118,101, 99, 51,102, 0,118,101, 99, 51,100,
+ 0,118,101, 99, 52,105, 0,118,101, 99, 52,102, 0,118,101, 99, 52,100, 0,114, 99,116,105, 0,114, 99,116,102, 0, 73, 68, 0,
+ 76,105, 98,114, 97,114,121, 0, 73,112,111, 0, 75,101,121, 66,108,111, 99,107, 0, 75,101,121, 0, 83, 99,114,105,112,116, 76,
+105,110,107, 0, 84,101,120,116, 76,105,110,101, 0, 84,101,120,116, 0, 80, 97, 99,107,101,100, 70,105,108,101, 0, 67, 97,109,
+101,114, 97, 0, 73,109, 97,103,101, 0, 97,110,105,109, 0, 73,109, 66,117,102, 0, 77, 84,101,120, 0, 79, 98,106,101, 99,116,
+ 0, 84,101,120, 0, 80,108,117,103,105,110, 84,101,120, 0, 67, 66, 68, 97,116, 97, 0, 67,111,108,111,114, 66, 97,110,100, 0,
+ 69,110,118, 77, 97,112, 0, 76, 97,109,112, 0, 87, 97,118,101, 0, 77, 97,116,101,114,105, 97,108, 0, 86, 70,111,110,116, 0,
+ 86, 70,111,110,116, 68, 97,116, 97, 0, 77,101,116, 97, 69,108,101,109, 0, 77,101,116, 97, 66, 97,108,108, 0, 66,111,117,110,
+100, 66,111,120, 0, 66,101,122, 84,114,105,112,108,101, 0, 66, 80,111,105,110,116, 0, 78,117,114, 98, 0, 67,117,114,118,101,
+ 0, 80, 97,116,104, 0, 73,112,111, 67,117,114,118,101, 0, 77, 70, 97, 99,101, 0, 77, 70, 97, 99,101, 73,110,116, 0, 84, 70,
+ 97, 99,101, 0, 77, 86,101,114,116, 0, 77, 67,111,108, 0, 77, 83,116,105, 99,107,121, 0, 77,101,115,104, 0, 79, 99, 73,110,
+102,111, 0, 76, 97,116,116,105, 99,101, 0, 76, 66,117,102, 0, 76,105,102,101, 0, 87,111,114,108,100, 0, 82, 97,100,105,111,
+ 0, 66, 97,115,101, 0, 82,101,110,100,101,114, 68, 97,116, 97, 0, 83, 99,101,110,101, 0, 71,114,111,117,112, 0, 70,114,101,
+101, 67, 97,109,101,114, 97, 0, 66, 71,112,105, 99, 0, 86,105,101,119, 51, 68, 0, 86,105,101,119, 50, 68, 0, 83,112, 97, 99,
+101, 73,112,111, 0, 83,112, 97, 99,101, 66,117,116,115, 0, 83,112, 97, 99,101, 83,101,113, 0, 83,112, 97, 99,101, 70,105,108,
+101, 0,100,105,114,101,110,116,114,121, 0, 83,112, 97, 99,101, 79,111,112,115, 0, 83,112, 97, 99,101, 73,109, 97,103,101, 0,
+ 83,112, 97, 99,101, 84,101,120,116, 0, 85,115,101,114, 68,101,102, 0, 98, 83, 99,114,101,101,110, 0, 83, 99,114, 86,101,114,
+116, 0, 83, 99,114, 69,100,103,101, 0, 83, 99,114, 65,114,101, 97, 0, 70,105,108,101, 71,108,111, 98, 97,108, 0, 83,116,114,
+105,112, 69,108,101,109, 0, 83,116,114,105,112, 0, 80,108,117,103,105,110, 83,101,113, 0, 83,101,113,117,101,110, 99,101, 0,
+ 69,100,105,116,105,110,103, 0, 69,102,102,101, 99,116, 0, 66,117,105,108,100, 69,102,102, 0, 80, 97,114,116, 69,102,102, 0,
+ 80, 97,114,116,105, 99,108,101, 0, 87, 97,118,101, 69,102,102, 0, 68,101,102,111,114,109, 0, 76,105,109, 98, 0, 73,107, 97,
+ 0, 79,111,112,115, 0, 83,112, 97, 99,101, 73,109, 97, 83,101,108, 0, 73,109, 97, 68,105,114, 0, 79,110,101, 83,101,108,101,
+ 99,116, 97, 98,108,101, 73,109, 97, 0, 98, 80,114,111,112,101,114,116,121, 0, 98, 78,101, 97,114, 83,101,110,115,111,114, 0,
+ 98, 77,111,117,115,101, 83,101,110,115,111,114, 0, 98, 84,111,117, 99,104, 83,101,110,115,111,114, 0, 98, 75,101,121, 98,111,
+ 97,114,100, 83,101,110,115,111,114, 0, 98, 80,114,111,112,101,114,116,121, 83,101,110,115,111,114, 0, 98, 67,111,108,108,105,
+115,105,111,110, 83,101,110,115,111,114, 0, 98, 82, 97,100, 97,114, 83,101,110,115,111,114, 0, 98, 82, 97,110,100,111,109, 83,
+101,110,115,111,114, 0, 98, 82, 97,121, 83,101,110,115,111,114, 0, 98, 77,101,115,115, 97,103,101, 83,101,110,115,111,114, 0,
+ 98, 83,101,110,115,111,114, 0, 98, 67,111,110,116,114,111,108,108,101,114, 0, 98, 69,120,112,114,101,115,115,105,111,110, 67,
+111,110,116, 0, 98, 80,121,116,104,111,110, 67,111,110,116, 0, 98, 65, 99,116,117, 97,116,111,114, 0, 98, 65,100,100, 79, 98,
+106,101, 99,116, 65, 99,116,117, 97,116,111,114, 0, 98, 83,111,117,110,100, 65, 99,116,117, 97,116,111,114, 0, 98, 83,111,117,
+110,100, 0, 98, 69,100,105,116, 79, 98,106,101, 99,116, 65, 99,116,117, 97,116,111,114, 0, 98, 83, 99,101,110,101, 65, 99,116,
+117, 97,116,111,114, 0, 98, 80,114,111,112,101,114,116,121, 65, 99,116,117, 97,116,111,114, 0, 98, 79, 98,106,101, 99,116, 65,
+ 99,116,117, 97,116,111,114, 0, 98, 73,112,111, 65, 99,116,117, 97,116,111,114, 0, 98, 67, 97,109,101,114, 97, 65, 99,116,117,
+ 97,116,111,114, 0, 98, 67,111,110,115,116,114, 97,105,110,116, 65, 99,116,117, 97,116,111,114, 0, 98, 71,114,111,117,112, 65,
+ 99,116,117, 97,116,111,114, 0, 98, 82, 97,110,100,111,109, 65, 99,116,117, 97,116,111,114, 0, 98, 77,101,115,115, 97,103,101,
+ 65, 99,116,117, 97,116,111,114, 0, 83,101, 99,116,111,114, 0, 98, 83, 97,109,112,108,101, 0, 83,112, 97, 99,101, 83,111,117,
+110,100, 0, 71,114,111,117,112, 75,101,121, 0, 79, 98,106,101, 99,116, 75,101,121, 0, 71,114,111,117,112, 79, 98,106,101, 99,
+116, 0, 66,111,110,101, 0, 98, 65,114,109, 97,116,117,114,101, 0, 0, 0, 0, 84, 76, 69, 78, 1, 0, 1, 0, 2, 0, 2, 0,
+ 4, 0, 4, 0, 4, 0, 4, 0, 8, 0, 0, 0, 8, 0, 8, 0, 32, 0, 8, 0, 4, 0, 8, 0, 8, 0, 16, 0, 12, 0, 12, 0,
+ 24, 0, 16, 0, 16, 0, 32, 0, 16, 0, 16, 0, 48, 0,224, 0, 80, 0, 28, 0,116, 0, 16, 0, 20, 0,100, 0, 20, 0,108, 0,
+ 32, 1, 0, 0, 0, 0, 80, 0,100, 2,168, 0, 80, 1, 24, 0,136, 1,120, 0,180, 0, 52, 0, 16, 1, 64, 1, 0, 0, 72, 0,
+132, 0, 0, 0, 60, 0, 28, 0, 48, 0,232, 0, 0, 0, 80, 0, 12, 0, 20, 0, 72, 0, 20, 0, 4, 0, 8, 0,184, 0, 0, 0,
+ 76, 0, 12, 0,120, 1,228, 0, 40, 0, 28, 0, 0, 3,128, 3, 68, 0, 40, 0, 36, 0,140, 1,112, 0,180, 0,160, 0,136, 0,
+ 60, 1, 0, 0,148, 0,156, 0, 88, 0,204, 1,100, 0, 20, 0, 24, 0,220, 0, 12, 0, 64, 0,108, 0,240, 0,148, 0, 28, 0,
+ 16, 0, 24, 0,156, 0, 0, 0, 56, 0,236, 0, 40, 0,156, 0, 44, 0,208, 2, 0, 0, 0, 0, 64, 0, 48, 0, 8, 0, 44, 0,
+ 8, 0,104, 0, 72, 0, 44, 0, 40, 0,108, 0,140, 0, 76, 0, 80, 0,128, 0, 4, 0, 60, 0, 12, 0, 20, 0,248, 0, 64, 0,
+ 16, 0, 76, 0,104, 0, 48, 0, 28, 0, 56, 0, 52, 0, 56, 0, 76, 0,148, 0, 0, 0,148, 0, 48, 0,112, 1, 20, 0, 96, 0,
+ 72, 0, 0, 0, 83, 84, 82, 67,128, 0, 0, 0, 10, 0, 2, 0, 10, 0, 0, 0, 10, 0, 1, 0, 11, 0, 2, 0, 9, 0, 2, 0,
+ 9, 0, 3, 0, 12, 0, 8, 0, 4, 0, 4, 0, 4, 0, 5, 0, 12, 0, 0, 0, 12, 0, 1, 0, 0, 0, 6, 0, 0, 0, 7, 0,
+ 4, 0, 8, 0, 4, 0, 9, 0, 13, 0, 2, 0, 4, 0, 10, 0, 4, 0, 11, 0, 14, 0, 2, 0, 2, 0, 12, 0, 2, 0, 13, 0,
+ 15, 0, 2, 0, 4, 0, 12, 0, 4, 0, 13, 0, 16, 0, 2, 0, 7, 0, 12, 0, 7, 0, 13, 0, 17, 0, 2, 0, 8, 0, 12, 0,
+ 8, 0, 13, 0, 18, 0, 3, 0, 4, 0, 12, 0, 4, 0, 13, 0, 4, 0, 14, 0, 19, 0, 3, 0, 7, 0, 12, 0, 7, 0, 13, 0,
+ 7, 0, 14, 0, 20, 0, 3, 0, 8, 0, 12, 0, 8, 0, 13, 0, 8, 0, 14, 0, 21, 0, 4, 0, 4, 0, 12, 0, 4, 0, 13, 0,
+ 4, 0, 14, 0, 4, 0, 15, 0, 22, 0, 4, 0, 7, 0, 12, 0, 7, 0, 13, 0, 7, 0, 14, 0, 7, 0, 15, 0, 23, 0, 4, 0,
+ 8, 0, 12, 0, 8, 0, 13, 0, 8, 0, 14, 0, 8, 0, 15, 0, 24, 0, 4, 0, 4, 0, 16, 0, 4, 0, 17, 0, 4, 0, 18, 0,
+ 4, 0, 19, 0, 25, 0, 4, 0, 7, 0, 16, 0, 7, 0, 17, 0, 7, 0, 18, 0, 7, 0, 19, 0, 26, 0, 8, 0, 9, 0, 0, 0,
+ 9, 0, 1, 0, 26, 0, 20, 0, 27, 0, 21, 0, 0, 0, 22, 0, 2, 0, 23, 0, 2, 0, 24, 0, 4, 0, 11, 0, 27, 0, 6, 0,
+ 26, 0, 25, 0, 26, 0, 26, 0, 0, 0, 27, 0, 0, 0, 28, 0, 4, 0, 29, 0, 4, 0, 11, 0, 28, 0, 6, 0, 26, 0, 25, 0,
+ 11, 0, 30, 0, 25, 0, 31, 0, 2, 0, 32, 0, 2, 0, 33, 0, 4, 0, 11, 0, 29, 0, 9, 0, 29, 0, 0, 0, 29, 0, 1, 0,
+ 7, 0, 34, 0, 2, 0, 24, 0, 2, 0, 35, 0, 2, 0, 36, 0, 2, 0, 37, 0, 4, 0, 11, 0, 9, 0, 38, 0, 30, 0, 12, 0,
+ 26, 0, 25, 0, 29, 0, 39, 0, 0, 0, 40, 0, 4, 0, 41, 0, 7, 0, 42, 0, 11, 0, 43, 0, 28, 0, 44, 0, 26, 0, 45, 0,
+ 2, 0, 36, 0, 2, 0, 46, 0, 2, 0, 47, 0, 2, 0, 48, 0, 31, 0, 5, 0, 26, 0, 49, 0, 2, 0, 50, 0, 2, 0, 51, 0,
+ 2, 0, 52, 0, 4, 0, 11, 0, 32, 0, 5, 0, 32, 0, 0, 0, 32, 0, 1, 0, 0, 0, 53, 0, 4, 0, 5, 0, 4, 0, 54, 0,
+ 33, 0, 13, 0, 26, 0, 25, 0, 0, 0, 6, 0, 4, 0, 55, 0, 4, 0, 56, 0, 11, 0, 57, 0, 32, 0, 58, 0, 32, 0, 59, 0,
+ 4, 0, 60, 0, 4, 0, 61, 0, 0, 0, 62, 0, 4, 0, 63, 0, 4, 0, 64, 0, 9, 0, 65, 0, 34, 0, 5, 0, 4, 0, 66, 0,
+ 4, 0, 67, 0, 4, 0, 55, 0, 4, 0, 11, 0, 9, 0, 38, 0, 35, 0, 15, 0, 26, 0, 25, 0, 2, 0, 36, 0, 2, 0, 24, 0,
+ 2, 0, 68, 0, 2, 0, 69, 0, 7, 0, 70, 0, 7, 0, 71, 0, 7, 0, 72, 0, 7, 0, 73, 0, 7, 0, 74, 0, 7, 0, 75, 0,
+ 7, 0, 76, 0, 7, 0, 77, 0, 28, 0, 44, 0, 31, 0, 78, 0, 36, 0, 18, 0, 26, 0, 25, 0, 0, 0, 28, 0, 37, 0, 79, 0,
+ 38, 0, 80, 0, 38, 0, 81, 0, 2, 0, 82, 0, 2, 0, 24, 0, 2, 0, 83, 0, 2, 0, 84, 0, 2, 0, 85, 0, 2, 0, 86, 0,
+ 2, 0, 87, 0, 2, 0, 88, 0, 2, 0, 89, 0, 2, 0, 90, 0, 4, 0, 91, 0, 4, 0, 92, 0, 34, 0, 93, 0, 39, 0, 22, 0,
+ 2, 0, 94, 0, 2, 0, 95, 0, 2, 0, 96, 0, 2, 0, 97, 0, 40, 0, 98, 0, 41, 0, 99, 0, 0, 0,100, 0, 0, 0,101, 0,
+ 0, 0,102, 0, 0, 0,103, 0, 7, 0,104, 0, 7, 0,105, 0, 2, 0,106, 0, 2, 0,107, 0, 7, 0,108, 0, 7, 0,109, 0,
+ 7, 0,110, 0, 7, 0,111, 0, 7, 0,112, 0, 7, 0,113, 0, 7, 0,114, 0, 7, 0,115, 0, 42, 0, 14, 0, 0, 0, 28, 0,
+ 9, 0,116, 0, 0, 0,117, 0, 0, 0,118, 0, 4, 0,119, 0, 4, 0,120, 0, 9, 0,121, 0, 7, 0,122, 0, 7, 0,123, 0,
+ 7, 0,124, 0, 4, 0,125, 0, 9, 0,126, 0, 4, 0,127, 0, 4, 0, 11, 0, 43, 0, 6, 0, 7, 0,108, 0, 7, 0,109, 0,
+ 7, 0,110, 0, 7, 0,128, 0, 7, 0, 34, 0, 4, 0, 31, 0, 44, 0, 5, 0, 2, 0, 24, 0, 2, 0, 29, 0, 2, 0, 31, 0,
+ 2, 0,129, 0, 43, 0,130, 0, 45, 0, 12, 0, 40, 0, 98, 0, 36, 0,131, 0, 36, 0,132, 0, 7, 0,133, 0, 2, 0, 36, 0,
+ 2, 0,134, 0, 7, 0, 70, 0, 7, 0, 71, 0, 4, 0,135, 0, 4, 0,136, 0, 2, 0, 82, 0, 2, 0, 83, 0, 41, 0, 35, 0,
+ 26, 0, 25, 0, 7, 0,137, 0, 7, 0,138, 0, 7, 0,139, 0, 7, 0,140, 0, 7, 0,141, 0, 7, 0,142, 0, 7, 0,143, 0,
+ 7, 0,144, 0, 2, 0,145, 0, 2, 0,146, 0, 2, 0,147, 0, 2, 0, 24, 0, 2, 0, 36, 0, 2, 0,134, 0, 7, 0,148, 0,
+ 7, 0,149, 0, 7, 0,150, 0, 7, 0,151, 0, 2, 0,152, 0, 2, 0,153, 0, 2, 0,154, 0, 2, 0, 5, 0, 2, 0,155, 0,
+ 2, 0,156, 0, 2, 0,157, 0, 2, 0,158, 0, 7, 0,114, 0, 7, 0,159, 0, 28, 0, 44, 0, 36, 0,131, 0, 42, 0,160, 0,
+ 44, 0,161, 0, 45, 0,162, 0, 2, 0,163, 0, 46, 0, 28, 0, 26, 0, 25, 0, 2, 0, 36, 0, 2, 0,164, 0, 2, 0,107, 0,
+ 2, 0,165, 0, 7, 0,108, 0, 7, 0,109, 0, 7, 0,110, 0, 7, 0,111, 0, 7, 0,166, 0, 7, 0,167, 0, 7, 0,168, 0,
+ 7, 0,169, 0, 7, 0,170, 0, 7, 0,171, 0, 7, 0,172, 0, 2, 0,173, 0, 2, 0,174, 0, 7, 0, 70, 0, 7, 0, 71, 0,
+ 7, 0,175, 0, 7, 0,176, 0, 7, 0,177, 0, 2, 0,178, 0, 2, 0,179, 0, 39, 0,180, 0, 28, 0, 44, 0, 31, 0, 78, 0,
+ 47, 0, 2, 0, 26, 0, 25, 0, 28, 0, 44, 0, 48, 0, 58, 0, 26, 0, 25, 0, 2, 0,107, 0, 2, 0,181, 0, 7, 0,108, 0,
+ 7, 0,109, 0, 7, 0,110, 0, 7, 0,182, 0, 7, 0,183, 0, 7, 0,184, 0, 7, 0,185, 0, 7, 0,186, 0, 7, 0,187, 0,
+ 7, 0,188, 0, 7, 0,189, 0, 7, 0,190, 0, 7, 0,191, 0, 7, 0,192, 0, 7, 0,193, 0, 7, 0,194, 0, 7, 0,195, 0,
+ 7, 0,196, 0, 7, 0,197, 0, 7, 0,198, 0, 7, 0,199, 0, 7, 0,200, 0, 2, 0,201, 0, 0, 0,202, 0, 0, 0,203, 0,
+ 4, 0,164, 0, 4, 0,204, 0, 2, 0,205, 0, 2, 0,206, 0, 2, 0,207, 0, 2, 0,208, 0, 7, 0,209, 0, 7, 0,210, 0,
+ 7, 0,211, 0, 7, 0,212, 0, 0, 0,213, 0, 0, 0,178, 0, 0, 0,214, 0, 0, 0,215, 0, 2, 0,216, 0, 2, 0,217, 0,
+ 4, 0,218, 0, 2, 0, 94, 0, 2, 0, 95, 0, 39, 0,180, 0, 28, 0, 44, 0, 48, 0,219, 0, 7, 0,220, 0, 7, 0,221, 0,
+ 7, 0,222, 0, 7, 0,223, 0, 7, 0,224, 0, 2, 0,225, 0, 2, 0, 11, 0, 31, 0, 78, 0, 49, 0, 8, 0, 26, 0, 25, 0,
+ 0, 0,226, 0, 0, 0,227, 0, 7, 0,228, 0, 2, 0, 24, 0, 2, 0, 37, 0, 50, 0, 38, 0, 34, 0, 93, 0, 51, 0, 20, 0,
+ 51, 0, 0, 0, 51, 0, 1, 0, 2, 0, 36, 0, 2, 0,181, 0, 2, 0, 24, 0, 2, 0,229, 0, 7, 0, 12, 0, 7, 0, 13, 0,
+ 7, 0, 14, 0, 7, 0,230, 0, 7, 0,231, 0, 7, 0,232, 0, 7, 0,233, 0, 7, 0,234, 0, 7, 0,235, 0, 7, 0, 5, 0,
+ 7, 0,236, 0, 4, 0, 11, 0, 7, 0,237, 0, 7, 0,238, 0, 52, 0, 15, 0, 26, 0, 25, 0, 53, 0,239, 0, 11, 0,240, 0,
+ 11, 0,241, 0, 28, 0, 44, 0, 48, 0,242, 0, 2, 0, 24, 0, 2, 0,243, 0, 4, 0,106, 0, 7, 0,244, 0, 7, 0,105, 0,
+ 7, 0,245, 0, 7, 0,246, 0, 7, 0,247, 0, 7, 0,248, 0, 54, 0, 9, 0, 7, 0,249, 0, 7, 0,250, 0, 2, 0,251, 0,
+ 2, 0,252, 0, 2, 0,253, 0, 0, 0,254, 0, 0, 0,255, 0, 0, 0, 0, 1, 0, 0, 1, 1, 55, 0, 5, 0, 7, 0, 2, 1,
+ 7, 0,250, 0, 2, 0, 3, 1, 2, 0,254, 0, 2, 0, 1, 1, 56, 0, 18, 0, 56, 0, 0, 0, 56, 0, 1, 0, 2, 0, 36, 0,
+ 2, 0, 4, 1, 2, 0, 1, 1, 2, 0, 24, 0, 2, 0, 5, 1, 2, 0, 6, 1, 2, 0, 7, 1, 2, 0, 8, 1, 2, 0, 9, 1,
+ 2, 0, 10, 1, 2, 0, 11, 1, 2, 0, 12, 1, 7, 0, 13, 1, 7, 0, 14, 1, 55, 0, 15, 1, 54, 0, 16, 1, 57, 0, 38, 0,
+ 26, 0, 25, 0, 53, 0,239, 0, 11, 0, 17, 1, 11, 0,241, 0, 40, 0, 18, 1, 40, 0, 19, 1, 28, 0, 44, 0, 58, 0, 20, 1,
+ 30, 0, 21, 1, 48, 0,242, 0, 11, 0, 22, 1, 7, 0, 23, 1, 7, 0,244, 0, 7, 0,105, 0, 7, 0,245, 0, 4, 0,106, 0,
+ 2, 0, 24, 1, 2, 0,243, 0, 2, 0, 24, 0, 2, 0, 25, 1, 7, 0, 26, 1, 7, 0, 27, 1, 7, 0, 28, 1, 2, 0, 7, 1,
+ 2, 0, 8, 1, 2, 0, 5, 0, 2, 0, 57, 0, 2, 0, 34, 0, 2, 0, 29, 1, 7, 0, 30, 1, 7, 0, 31, 1, 7, 0, 32, 1,
+ 7, 0, 33, 1, 7, 0, 34, 1, 7, 0, 35, 1, 0, 0, 36, 1, 0, 0, 37, 1, 49, 0, 38, 1, 59, 0, 18, 0, 59, 0, 0, 0,
+ 59, 0, 1, 0, 55, 0, 15, 1, 54, 0, 16, 1, 25, 0, 39, 1, 25, 0, 40, 1, 2, 0, 32, 0, 2, 0, 41, 1, 2, 0, 42, 1,
+ 2, 0, 43, 1, 2, 0, 44, 1, 2, 0, 45, 1, 2, 0, 24, 0, 2, 0, 37, 0, 7, 0, 18, 0, 7, 0, 19, 0, 4, 0, 46, 1,
+ 7, 0, 42, 0, 60, 0, 8, 0, 3, 0, 47, 1, 3, 0, 48, 1, 3, 0, 49, 1, 3, 0, 50, 1, 0, 0, 51, 1, 0, 0, 4, 1,
+ 0, 0, 52, 1, 0, 0, 24, 0, 61, 0, 8, 0, 4, 0, 47, 1, 4, 0, 48, 1, 4, 0, 49, 1, 4, 0, 50, 1, 0, 0, 51, 1,
+ 0, 0, 4, 1, 0, 0, 52, 1, 0, 0, 24, 0, 62, 0, 10, 0, 7, 0, 53, 1, 4, 0, 54, 1, 2, 0, 55, 1, 0, 0, 24, 0,
+ 0, 0, 56, 1, 2, 0,164, 0, 2, 0, 57, 1, 4, 0, 11, 0, 9, 0, 58, 1, 9, 0, 59, 1, 63, 0, 4, 0, 7, 0, 60, 1,
+ 2, 0, 55, 1, 0, 0, 24, 0, 0, 0, 4, 1, 64, 0, 4, 0, 0, 0,128, 0, 0, 0,108, 0, 0, 0,109, 0, 0, 0,110, 0,
+ 65, 0, 1, 0, 7, 0, 61, 1, 66, 0, 29, 0, 26, 0, 25, 0, 53, 0,239, 0, 11, 0, 62, 1, 11, 0,241, 0, 28, 0, 44, 0,
+ 30, 0, 21, 1, 48, 0,242, 0, 9, 0, 63, 1, 9, 0, 64, 1, 9, 0, 65, 1, 63, 0, 66, 1, 64, 0, 67, 1, 65, 0, 68, 1,
+ 66, 0, 69, 1, 7, 0, 23, 1, 67, 0, 70, 1, 9, 0, 71, 1, 4, 0, 43, 1, 4, 0, 72, 1, 4, 0,106, 0, 7, 0,244, 0,
+ 7, 0,105, 0, 7, 0,245, 0, 2, 0, 73, 1, 2, 0, 24, 0, 2, 0, 74, 1, 2, 0,243, 0, 7, 0, 75, 1, 7, 0, 76, 1,
+ 68, 0, 13, 0, 26, 0, 25, 0, 2, 0, 5, 1, 2, 0, 6, 1, 2, 0, 77, 1, 2, 0, 24, 0, 0, 0, 78, 1, 0, 0, 79, 1,
+ 0, 0, 80, 1, 0, 0, 36, 0, 4, 0, 11, 0, 55, 0, 81, 1, 28, 0, 44, 0, 30, 0, 21, 1, 69, 0, 4, 0, 2, 0, 29, 0,
+ 2, 0, 82, 1, 4, 0, 11, 0, 40, 0, 83, 1, 40, 0, 69, 0, 26, 0, 25, 0, 2, 0, 36, 0, 2, 0, 84, 1, 4, 0, 85, 1,
+ 4, 0, 86, 1, 4, 0, 87, 1, 40, 0, 88, 1, 40, 0, 89, 1, 28, 0, 44, 0, 58, 0, 20, 1, 53, 0,239, 0, 9, 0, 38, 0,
+ 11, 0, 62, 1, 11, 0, 90, 1, 11, 0,241, 0, 48, 0,242, 0, 70, 0, 91, 1, 7, 0,244, 0, 7, 0, 92, 1, 7, 0, 93, 1,
+ 7, 0,105, 0, 7, 0, 94, 1, 7, 0,245, 0, 7, 0, 95, 1, 7, 0, 96, 1, 7, 0, 97, 1, 7, 0, 98, 1, 7, 0, 99, 1,
+ 7, 0,133, 0, 4, 0,181, 0, 2, 0, 24, 0, 2, 0,100, 1, 0, 0,101, 1, 0, 0,102, 1, 0, 0,103, 1, 0, 0,104, 1,
+ 2, 0,105, 1, 2, 0,106, 1, 2, 0,107, 1, 2, 0,108, 1, 2, 0,109, 1, 2, 0,110, 1, 2, 0,111, 1, 2, 0,112, 1,
+ 7, 0,113, 1, 7, 0,114, 1, 7, 0,115, 1, 7, 0,116, 1, 7, 0,117, 1, 7, 0,118, 1, 7, 0,119, 1, 0, 0,120, 1,
+ 0, 0,121, 1, 0, 0,243, 0, 0, 0,122, 1, 31, 0, 78, 0, 11, 0,123, 1, 11, 0,124, 1, 11, 0,125, 1, 11, 0,126, 1,
+ 9, 0, 71, 1, 69, 0,127, 1, 69, 0,128, 1, 7, 0,129, 1, 2, 0,130, 1, 2, 0,218, 0, 7, 0, 54, 1, 4, 0,131, 1,
+ 7, 0,132, 1, 71, 0, 41, 0, 26, 0, 25, 0, 2, 0,107, 0, 2, 0,165, 0, 2, 0,178, 0, 2, 0,133, 1, 7, 0,134, 1,
+ 7, 0,135, 1, 7, 0,136, 1, 7, 0,137, 1, 7, 0,138, 1, 7, 0,139, 1, 7, 0,140, 1, 7, 0,141, 1, 7, 0,188, 0,
+ 7, 0,190, 0, 7, 0,189, 0, 7, 0,142, 1, 4, 0,143, 1, 7, 0,144, 1, 7, 0,145, 1, 2, 0,146, 1, 2, 0,164, 0,
+ 7, 0,147, 1, 7, 0,148, 1, 7, 0,149, 1, 7, 0,150, 1, 7, 0,151, 1, 7, 0,152, 1, 7, 0,153, 1, 7, 0,154, 1,
+ 7, 0,155, 1, 7, 0,156, 1, 7, 0,157, 1, 7, 0,158, 1, 2, 0,159, 1, 2, 0,160, 1, 2, 0,161, 1, 2, 0,162, 1,
+ 28, 0, 44, 0, 39, 0,180, 0, 31, 0, 78, 0, 72, 0, 16, 0, 2, 0,163, 1, 2, 0,164, 1, 2, 0,165, 1, 2, 0, 24, 0,
+ 2, 0,166, 1, 2, 0,167, 1, 2, 0,168, 1, 2, 0,169, 1, 2, 0,170, 1, 2, 0,171, 1, 2, 0,172, 1, 2, 0,173, 1,
+ 4, 0,174, 1, 7, 0,175, 1, 7, 0,176, 1, 7, 0,177, 1, 73, 0, 8, 0, 73, 0, 0, 0, 73, 0, 1, 0, 4, 0,181, 0,
+ 4, 0,229, 0, 4, 0, 24, 0, 2, 0,178, 1, 2, 0,179, 1, 40, 0, 98, 0, 74, 0, 43, 0, 2, 0,180, 1, 2, 0,157, 0,
+ 2, 0,181, 1, 2, 0,182, 1, 2, 0,183, 1, 2, 0, 24, 0, 7, 0,114, 1, 7, 0,184, 1, 7, 0,185, 1, 7, 0,186, 1,
+ 7, 0,187, 1, 7, 0,188, 1, 2, 0, 66, 0, 2, 0,189, 1, 2, 0,190, 1, 2, 0,191, 1, 2, 0,192, 1, 2, 0,193, 1,
+ 2, 0,194, 1, 2, 0,195, 1, 25, 0,196, 1, 25, 0,197, 1, 2, 0,198, 1, 2, 0,199, 1, 2, 0,200, 1, 2, 0,201, 1,
+ 2, 0,202, 1, 2, 0,203, 1, 2, 0,164, 0, 2, 0,204, 1, 2, 0,205, 1, 2, 0,206, 1, 2, 0,207, 1, 2, 0,208, 1,
+ 7, 0,177, 1, 7, 0,209, 1, 7, 0,210, 1, 7, 0,211, 1, 7, 0,212, 1, 0, 0,213, 1, 0, 0,214, 1, 0, 0,215, 1,
+ 0, 0,216, 1, 75, 0, 16, 0, 26, 0, 25, 0, 40, 0,217, 1, 71, 0,218, 1, 75, 0,219, 1, 36, 0,131, 0, 11, 0,220, 1,
+ 73, 0,221, 1, 76, 0,222, 1, 7, 0,223, 1, 4, 0,181, 0, 77, 0,224, 1, 9, 0,225, 1, 72, 0,226, 1, 9, 0, 71, 1,
+ 74, 0,108, 0, 31, 0, 78, 0, 78, 0, 10, 0, 36, 0,131, 0, 41, 0, 99, 0, 7, 0, 34, 1, 7, 0, 35, 1, 7, 0, 66, 0,
+ 7, 0,227, 1, 7, 0,228, 1, 2, 0,229, 1, 2, 0,230, 1, 4, 0,231, 1, 79, 0, 42, 0, 79, 0, 0, 0, 79, 0, 1, 0,
+ 4, 0,232, 1, 7, 0,233, 1, 7, 0,234, 1, 7, 0,235, 1, 7, 0,236, 1, 7, 0,237, 1, 7, 0,167, 0, 2, 0,238, 1,
+ 2, 0,239, 1, 2, 0,165, 1, 2, 0,240, 1, 4, 0,181, 0, 4, 0,241, 1, 2, 0,242, 1, 2, 0,243, 1, 2, 0,244, 1,
+ 2, 0, 24, 0, 7, 0, 74, 0, 7, 0,245, 1, 7, 0,246, 1, 7, 0,247, 1, 7, 0,104, 0, 7, 0,223, 1, 40, 0,217, 1,
+ 2, 0,248, 1, 2, 0,249, 1, 2, 0,250, 1, 2, 0,251, 1, 2, 0,252, 1, 2, 0,253, 1, 2, 0,254, 1, 2, 0,255, 1,
+ 2, 0, 0, 2, 2, 0, 1, 2, 2, 0, 2, 2, 2, 0, 3, 2, 7, 0, 4, 2, 7, 0, 5, 2, 78, 0, 6, 2, 79, 0, 7, 2,
+ 80, 0, 13, 0, 25, 0, 29, 0, 25, 0, 31, 0, 24, 0, 8, 2, 24, 0, 9, 2, 24, 0, 10, 2, 7, 0, 11, 2, 7, 0, 12, 2,
+ 7, 0, 13, 2, 7, 0, 14, 2, 2, 0, 15, 2, 2, 0, 16, 2, 2, 0, 17, 2, 2, 0, 18, 2, 81, 0, 18, 0, 81, 0, 0, 0,
+ 81, 0, 1, 0, 4, 0,232, 1, 4, 0, 19, 2, 80, 0, 20, 2, 9, 0, 21, 2, 11, 0, 22, 2, 28, 0, 44, 0, 26, 0, 45, 0,
+ 2, 0, 23, 2, 2, 0, 24, 2, 2, 0, 25, 2, 2, 0, 26, 2, 2, 0, 33, 0, 2, 0, 32, 0, 2, 0, 27, 2, 2, 0, 37, 0,
+ 25, 0, 29, 0, 82, 0, 21, 0, 82, 0, 0, 0, 82, 0, 1, 0, 4, 0,232, 1, 2, 0, 28, 2, 2, 0, 29, 2, 80, 0, 20, 2,
+ 2, 0, 30, 2, 2, 0, 27, 2, 2, 0, 24, 2, 2, 0, 31, 2, 9, 0, 32, 2, 2, 0, 33, 2, 0, 0, 34, 2, 0, 0, 35, 2,
+ 2, 0, 36, 2, 2, 0, 37, 2, 4, 0,231, 1, 2, 0, 38, 2, 2, 0, 39, 2, 2, 0, 40, 2, 2, 0,106, 1, 83, 0, 8, 0,
+ 83, 0, 0, 0, 83, 0, 1, 0, 4, 0,232, 1, 4, 0,218, 0, 80, 0, 20, 2, 2, 0, 30, 2, 2, 0,227, 1, 4, 0, 41, 2,
+ 84, 0, 21, 0, 84, 0, 0, 0, 84, 0, 1, 0, 4, 0,232, 1, 4, 0, 11, 0, 85, 0, 42, 2, 4, 0, 43, 2, 0, 0, 44, 2,
+ 0, 0, 45, 2, 0, 0, 46, 2, 2, 0, 36, 0, 2, 0, 47, 2, 2, 0, 24, 0, 2, 0, 48, 2, 2, 0, 49, 2, 2, 0, 50, 2,
+ 0, 0, 51, 2, 2, 0, 52, 2, 2, 0,129, 0, 2, 0, 53, 2, 2, 0, 54, 2, 9, 0, 55, 2, 86, 0, 11, 0, 86, 0, 0, 0,
+ 86, 0, 1, 0, 4, 0,232, 1, 4, 0, 11, 0, 80, 0, 20, 2, 11, 0, 56, 2, 2, 0, 24, 2, 2, 0, 57, 2, 2, 0, 24, 0,
+ 2, 0, 37, 0, 9, 0, 32, 2, 87, 0, 16, 0, 87, 0, 0, 0, 87, 0, 1, 0, 4, 0,232, 1, 4, 0, 11, 0, 80, 0, 20, 2,
+ 36, 0, 58, 2, 7, 0,227, 1, 7, 0, 41, 2, 2, 0,164, 0, 2, 0, 59, 2, 2, 0, 60, 2, 2, 0, 61, 2, 2, 0, 34, 1,
+ 2, 0, 35, 1, 2, 0, 24, 0, 2, 0, 24, 2, 88, 0, 17, 0, 88, 0, 0, 0, 88, 0, 1, 0, 4, 0,232, 1, 4, 0, 62, 2,
+ 33, 0, 63, 2, 4, 0, 64, 2, 4, 0, 65, 2, 2, 0, 55, 0, 2, 0, 27, 2, 4, 0, 66, 2, 4, 0, 67, 2, 7, 0, 68, 2,
+ 24, 0, 69, 2, 24, 0, 70, 2, 9, 0, 71, 2, 9, 0, 72, 2, 9, 0, 73, 2, 89, 0, 12, 0, 2, 0, 24, 0, 2, 0, 74, 2,
+ 4, 0, 75, 2, 0, 0, 76, 2, 0, 0, 77, 2, 0, 0, 78, 2, 0, 0, 79, 2, 0, 0, 80, 2, 0, 0, 81, 2, 0, 0, 82, 2,
+ 2, 0, 83, 2, 2, 0, 37, 0, 90, 0, 17, 0, 26, 0, 25, 0, 11, 0, 84, 2, 11, 0, 85, 2, 11, 0, 86, 2, 75, 0, 87, 2,
+ 2, 0, 88, 2, 2, 0, 89, 2, 2, 0, 90, 2, 2, 0, 91, 2, 2, 0, 92, 2, 2, 0, 93, 2, 2, 0, 94, 2, 2, 0, 95, 2,
+ 2, 0, 96, 2, 2, 0, 37, 0, 2, 0, 97, 2, 2, 0, 98, 2, 91, 0, 5, 0, 91, 0, 0, 0, 91, 0, 1, 0, 91, 0, 99, 2,
+ 14, 0,100, 2, 4, 0, 24, 0, 92, 0, 7, 0, 92, 0, 0, 0, 92, 0, 1, 0, 91, 0,101, 2, 91, 0,102, 2, 2, 0,197, 1,
+ 2, 0, 24, 0, 4, 0, 11, 0, 93, 0, 38, 0, 93, 0, 0, 0, 93, 0, 1, 0, 91, 0,101, 2, 91, 0,102, 2, 91, 0,103, 2,
+ 91, 0,104, 2, 90, 0,105, 2, 2, 0,106, 2, 2, 0,107, 2, 2, 0,108, 2, 2, 0,109, 2, 7, 0,110, 2, 24, 0, 40, 1,
+ 24, 0,111, 2, 24, 0,112, 2, 2, 0,113, 2, 2, 0,114, 2, 2, 0,115, 2, 0, 0,232, 1, 0, 0,116, 2, 2, 0,117, 2,
+ 2, 0,118, 2, 0, 0,119, 2, 0, 0,120, 2, 0, 0,121, 2, 0, 0,122, 2, 2, 0,123, 2, 2, 0,124, 2, 2, 0,125, 2,
+ 2, 0, 37, 0, 9, 0,126, 2, 9, 0,127, 2, 9, 0,128, 2, 9, 0,129, 2, 9, 0,130, 2, 9, 0,131, 2, 11, 0,132, 2,
+ 11, 0,133, 2, 94, 0, 4, 0, 9, 0,134, 2, 2, 0,135, 2, 2, 0,198, 1, 4, 0,136, 2, 95, 0, 8, 0, 0, 0,137, 2,
+ 38, 0, 80, 0, 95, 0,138, 2, 95, 0,139, 2, 95, 0,140, 2, 2, 0, 82, 0, 2, 0,141, 2, 4, 0, 11, 0, 96, 0, 11, 0,
+ 96, 0, 0, 0, 96, 0, 1, 0, 2, 0, 37, 0, 2, 0, 5, 0, 2, 0, 23, 0, 2, 0,142, 2, 95, 0,143, 2, 0, 0,144, 2,
+ 2, 0,145, 2, 2, 0,146, 2, 4, 0, 11, 0, 97, 0, 10, 0, 0, 0,147, 2, 9, 0,116, 0, 0, 0,117, 0, 4, 0,120, 0,
+ 4, 0,127, 0, 9, 0,121, 0, 7, 0,123, 0, 7, 0,124, 0, 9, 0,125, 0, 9, 0,126, 0, 98, 0, 32, 0, 98, 0, 0, 0,
+ 98, 0, 1, 0, 98, 0,148, 2, 9, 0, 21, 0, 0, 0, 22, 0, 2, 0, 24, 0, 2, 0, 36, 0, 4, 0, 5, 0, 4, 0,149, 2,
+ 4, 0,150, 2, 4, 0,151, 2, 4, 0,152, 2, 4, 0,153, 2, 4, 0,154, 2, 4, 0,155, 2, 4, 0,156, 2, 4, 0,157, 2,
+ 7, 0,158, 2, 7, 0,159, 2, 4, 0,157, 0, 96, 0,160, 2, 95, 0,161, 2, 28, 0, 44, 0, 75, 0, 87, 2, 37, 0, 79, 0,
+ 7, 0,162, 2, 7, 0,163, 2, 97, 0,160, 0, 98, 0,164, 2, 98, 0,165, 2, 98, 0,166, 2, 11, 0,167, 2, 99, 0, 6, 0,
+ 11, 0,168, 2, 11, 0,167, 2, 11, 0,169, 2, 2, 0, 24, 0, 2, 0, 37, 0, 4, 0, 11, 0,100, 0, 6, 0,100, 0, 0, 0,
+100, 0, 1, 0, 2, 0, 36, 0, 2, 0, 24, 0, 2, 0,170, 2, 2, 0, 37, 0,101, 0, 8, 0,101, 0, 0, 0,101, 0, 1, 0,
+ 2, 0, 36, 0, 2, 0, 24, 0, 2, 0,170, 2, 2, 0, 37, 0, 7, 0, 5, 0, 7, 0,157, 0,102, 0, 31, 0,102, 0, 0, 0,
+102, 0, 1, 0, 2, 0, 36, 0, 2, 0, 24, 0, 2, 0,170, 2, 2, 0,134, 0, 7, 0,171, 2, 7, 0,172, 2, 7, 0,173, 2,
+ 4, 0,174, 2, 4, 0, 46, 0, 4, 0,175, 2, 7, 0,176, 2, 7, 0,177, 2, 7, 0,178, 2, 7, 0,179, 2, 7, 0,180, 2,
+ 7, 0,181, 2, 7, 0,182, 2, 7, 0,183, 2, 7, 0,184, 2, 7, 0,185, 2, 7, 0,186, 2, 7, 0,187, 2, 2, 0,188, 2,
+ 2, 0,189, 2, 2, 0,190, 2, 2, 0,191, 2, 2, 0,192, 2, 2, 0, 11, 0,103, 0,193, 2,104, 0, 16, 0,104, 0, 0, 0,
+104, 0, 1, 0, 2, 0, 36, 0, 2, 0, 24, 0, 2, 0,170, 2, 2, 0,134, 0, 7, 0, 88, 2, 7, 0, 90, 2, 7, 0,194, 2,
+ 7, 0, 26, 1, 7, 0,195, 2, 7, 0,196, 2, 7, 0,197, 2, 7, 0,182, 2, 7, 0,198, 2, 7, 0,173, 2,105, 0, 13, 0,
+ 40, 0,199, 2, 2, 0, 24, 0, 2, 0, 84, 1, 4, 0, 85, 1, 4, 0, 86, 1, 4, 0, 87, 1, 7, 0,133, 0, 7, 0,200, 2,
+ 7, 0,201, 2, 7, 0,202, 2, 7, 0,203, 2, 7, 0,167, 0, 7, 0, 11, 0,106, 0, 9, 0,106, 0, 0, 0,106, 0, 1, 0,
+ 7, 0, 5, 0, 7, 0,204, 2, 7, 0,203, 2, 7, 0,195, 0, 7, 0,205, 2, 7, 0, 11, 0, 7, 0,206, 2,107, 0, 23, 0,
+ 26, 0, 25, 0, 2, 0, 84, 1, 2, 0, 24, 0, 2, 0,207, 2, 2, 0,208, 2, 11, 0,209, 2, 7, 0,210, 2, 7, 0,211, 2,
+ 7, 0,212, 2, 7, 0,213, 2, 7, 0,214, 2, 7, 0,215, 2, 7, 0,216, 2, 7, 0,217, 2, 28, 0, 44, 0, 40, 0, 88, 1,
+ 4, 0, 85, 1, 4, 0, 86, 1, 4, 0, 87, 1, 4, 0,218, 2,105, 0, 81, 1, 4, 0,219, 2, 4, 0,220, 2,108, 0, 12, 0,
+108, 0, 0, 0,108, 0, 1, 0, 2, 0, 36, 0, 2, 0, 24, 0, 2, 0,120, 1, 2, 0, 1, 1, 7, 0, 12, 0, 7, 0, 13, 0,
+ 7, 0,221, 2, 7, 0,222, 2, 26, 0,223, 2, 11, 0,224, 2,109, 0, 78, 0,109, 0, 0, 0,109, 0, 1, 0, 4, 0,232, 1,
+ 0, 0, 44, 2, 4, 0,225, 2, 2, 0,164, 0, 2, 0,226, 2, 2, 0,227, 2, 2, 0,228, 2, 2, 0,248, 1, 2, 0,249, 1,
+ 2, 0,229, 2, 2, 0,230, 2, 2, 0,231, 2, 2, 0,232, 2, 2, 0,233, 2, 2, 0,234, 2, 2, 0,235, 2, 2, 0,236, 2,
+ 2, 0,237, 2, 2, 0,238, 2, 2, 0,239, 2, 2, 0,240, 2, 2, 0,241, 2, 2, 0,242, 2, 2, 0,243, 2, 2, 0,244, 2,
+ 2, 0,245, 2, 2, 0,246, 2, 2, 0,247, 2, 2, 0,248, 2, 2, 0,249, 2, 2, 0,250, 2, 2, 0,251, 2, 2, 0,252, 2,
+ 2, 0,253, 2, 2, 0,254, 2, 2, 0,255, 2, 2, 0, 0, 3, 2, 0, 1, 3, 2, 0, 2, 3, 2, 0, 3, 3, 2, 0, 4, 3,
+ 2, 0, 5, 3, 2, 0, 6, 3, 2, 0, 7, 3, 2, 0, 8, 3, 2, 0, 9, 3, 2, 0, 10, 3, 2, 0, 11, 3, 2, 0, 12, 3,
+ 2, 0, 13, 3, 2, 0, 14, 3, 0, 0, 15, 3, 0, 0, 16, 3, 0, 0, 17, 3, 0, 0, 18, 3,110, 0, 19, 3,110, 0, 20, 3,
+ 4, 0, 21, 3, 4, 0, 22, 3, 4, 0, 23, 3, 4, 0, 24, 3, 4, 0, 25, 3, 7, 0, 26, 3, 7, 0, 27, 3, 7, 0, 28, 3,
+ 2, 0, 29, 3, 2, 0, 30, 3, 2, 0, 31, 3, 2, 0, 32, 3,111, 0, 33, 3,111, 0, 34, 3, 2, 0, 35, 3, 2, 0, 36, 3,
+ 4, 0, 11, 0, 38, 0, 37, 3, 9, 0, 55, 2,112, 0, 11, 0,112, 0, 0, 0,112, 0, 1, 0, 0, 0, 38, 3, 2, 0, 36, 0,
+ 2, 0, 39, 3, 4, 0, 40, 3, 4, 0, 41, 3, 2, 0, 24, 0, 2, 0, 11, 0, 9, 0, 42, 3, 9, 0, 43, 3,113, 0, 5, 0,
+ 0, 0, 38, 3, 7, 0,167, 0, 7, 0, 44, 3, 4, 0, 45, 3, 4, 0, 11, 0,114, 0, 3, 0, 2, 0, 36, 0, 2, 0, 24, 0,
+ 4, 0, 11, 0,115, 0, 4, 0, 0, 0, 38, 3, 48, 0, 46, 3, 7, 0,167, 0, 7, 0, 11, 0,116, 0, 4, 0, 2, 0, 47, 3,
+ 2, 0, 48, 3, 2, 0, 36, 0, 2, 0, 49, 3,117, 0, 5, 0, 4, 0, 36, 0, 4, 0, 11, 0, 0, 0, 38, 3, 0, 0, 50, 3,
+ 0, 0, 51, 3,118, 0, 6, 0, 0, 0, 38, 3, 0, 0, 52, 3, 2, 0, 53, 3, 2, 0,182, 2, 2, 0,164, 0, 2, 0, 41, 2,
+119, 0, 5, 0, 0, 0, 38, 3, 7, 0, 54, 3, 7, 0, 55, 3, 2, 0, 24, 0, 2, 0, 56, 3,120, 0, 3, 0, 0, 0, 38, 3,
+ 4, 0,175, 2, 4, 0, 57, 3,121, 0, 7, 0, 0, 0, 38, 3, 7, 0, 55, 3, 0, 0, 58, 3, 0, 0, 59, 3, 2, 0,164, 0,
+ 2, 0,218, 0, 4, 0, 60, 3,122, 0, 8, 0, 40, 0, 61, 3, 2, 0, 36, 0, 2, 0, 62, 3, 4, 0, 11, 0, 0, 0, 63, 3,
+ 0, 0, 58, 3, 0, 0, 50, 3, 0, 0, 51, 3,123, 0, 17, 0,123, 0, 0, 0,123, 0, 1, 0, 2, 0, 36, 0, 2, 0, 39, 3,
+ 2, 0, 24, 0, 2, 0, 64, 3, 2, 0, 65, 3, 2, 0, 66, 3, 2, 0,218, 0, 2, 0, 41, 2, 0, 0, 38, 3, 9, 0, 38, 0,
+124, 0, 67, 3, 40, 0,199, 2, 2, 0, 68, 3, 2, 0, 69, 3, 4, 0, 11, 0,125, 0, 1, 0, 0, 0, 70, 3,126, 0, 1, 0,
+ 33, 0, 63, 2,124, 0, 18, 0,124, 0, 0, 0,124, 0, 1, 0,124, 0, 71, 3, 2, 0, 36, 0, 2, 0, 24, 0, 2, 0, 72, 3,
+ 2, 0, 66, 3, 2, 0, 39, 3, 2, 0, 73, 3, 2, 0, 41, 2, 2, 0, 59, 2, 0, 0, 38, 3, 9, 0, 38, 0,127, 0, 67, 3,
+123, 0, 74, 3, 2, 0, 75, 3, 2, 0, 76, 3, 4, 0, 77, 3,128, 0, 3, 0, 4, 0, 78, 3, 4, 0, 11, 0, 40, 0,199, 2,
+129, 0, 7, 0, 2, 0, 24, 0, 2, 0, 79, 3, 2, 0,171, 2, 2, 0,172, 2,130, 0, 80, 3, 2, 0, 36, 0, 2, 0, 81, 3,
+131, 0, 9, 0, 4, 0, 78, 3, 2, 0, 36, 0, 2, 0, 24, 0, 40, 0,199, 2, 66, 0, 82, 3, 0, 0, 38, 3, 7, 0, 83, 3,
+ 2, 0, 84, 3, 2, 0, 11, 0,132, 0, 5, 0, 2, 0, 36, 0, 2, 0, 24, 0, 4, 0, 11, 0, 75, 0, 87, 2, 40, 0,217, 1,
+133, 0, 5, 0, 4, 0, 24, 0, 4, 0, 36, 0, 0, 0, 38, 3, 0, 0, 50, 3, 40, 0,199, 2,134, 0, 10, 0, 4, 0, 24, 0,
+ 4, 0, 11, 0, 7, 0, 85, 3, 7, 0, 86, 3, 7, 0,244, 0, 7, 0,245, 0, 7, 0, 92, 1, 7, 0, 95, 1, 7, 0, 87, 3,
+ 7, 0, 88, 3,135, 0, 9, 0, 2, 0, 24, 0, 2, 0, 36, 0, 2, 0,171, 2, 2, 0,172, 2, 0, 0, 38, 3, 2, 0,218, 0,
+ 2, 0, 31, 0, 2, 0, 89, 3, 2, 0, 90, 3,136, 0, 8, 0, 40, 0,199, 2, 7, 0,194, 2, 7, 0, 91, 3, 7, 0, 82, 1,
+ 7, 0,203, 2, 2, 0, 24, 0, 2, 0, 56, 3, 7, 0, 92, 3,137, 0, 7, 0, 2, 0, 24, 0, 2, 0,182, 2, 7, 0,214, 2,
+ 7, 0, 93, 3, 7, 0, 94, 3, 7, 0, 95, 3, 7, 0, 96, 3,138, 0, 10, 0, 2, 0, 24, 0, 2, 0, 36, 0, 2, 0,171, 2,
+ 2, 0,172, 2, 0, 0, 38, 3, 2, 0,218, 0, 2, 0, 31, 0, 2, 0, 89, 3, 2, 0, 90, 3, 76, 0,222, 1,139, 0, 7, 0,
+ 4, 0,175, 2, 4, 0, 97, 3, 4, 0, 98, 3, 4, 0, 99, 3, 7, 0,100, 3, 7, 0,101, 3, 0, 0, 58, 3,140, 0, 5, 0,
+ 40, 0,102, 3, 4, 0, 36, 0, 4, 0, 11, 0, 0, 0, 63, 3, 0, 0, 58, 3,127, 0, 10, 0,127, 0, 0, 0,127, 0, 1, 0,
+127, 0, 71, 3, 2, 0, 36, 0, 2, 0, 24, 0, 2, 0, 39, 3, 2, 0,103, 3, 0, 0, 38, 3, 9, 0, 38, 0, 40, 0,199, 2,
+ 77, 0, 10, 0, 7, 0,115, 1, 7, 0,104, 3, 7, 0,105, 3, 7, 0,106, 3, 7, 0,107, 3, 4, 0, 24, 0, 7, 0,108, 3,
+ 7, 0,109, 3, 7, 0,110, 3, 7, 0, 11, 0,141, 0, 24, 0, 26, 0, 25, 0, 40, 0,199, 2, 2, 0, 36, 0, 2, 0, 24, 0,
+ 2, 0,111, 3, 2, 0,112, 3, 9, 0,113, 3, 69, 0,127, 1, 9, 0,114, 3, 9, 0,115, 3, 11, 0, 44, 1, 66, 0,116, 3,
+ 66, 0,117, 3, 2, 0,118, 3, 2, 0,180, 1, 2, 0,119, 3, 2, 0,157, 0, 2, 0,155, 2, 2, 0, 37, 0, 7, 0,105, 0,
+ 7, 0,129, 1, 7, 0,108, 0, 7, 0,109, 0, 7, 0,110, 0, 70, 0, 45, 0, 26, 0, 25, 0, 9, 0,120, 3, 7, 0,121, 3,
+ 7, 0,244, 0, 7, 0,122, 3, 7, 0,123, 3, 7, 0,124, 3, 7, 0,125, 3, 7, 0,126, 3, 7, 0,127, 3, 7, 0,245, 0,
+ 7, 0,128, 3, 7, 0,129, 3, 7, 0,115, 1, 7, 0,130, 3, 7, 0,131, 3, 7, 0,132, 3, 7, 0,133, 3, 7, 0,108, 0,
+ 7, 0,109, 0, 7, 0,110, 0, 7, 0,134, 3, 7, 0,135, 3, 9, 0,136, 3, 48, 0,137, 3, 40, 0,138, 3, 40, 0, 45, 0,
+ 9, 0,139, 3, 66, 0,116, 3, 66, 0,117, 3, 66, 0,140, 3, 2, 0,141, 3, 2, 0,142, 3, 0, 0, 36, 0, 0, 0,181, 0,
+ 2, 0, 24, 0, 2, 0,143, 3, 2, 0,157, 0, 2, 0,180, 1, 2, 0,144, 3, 2, 0,145, 3, 7, 0,146, 3, 7, 0,147, 3,
+ 69, 0,148, 3, 11, 0, 44, 1,130, 0, 13, 0, 26, 0, 25, 0, 0, 0, 28, 0,142, 0,149, 3, 34, 0, 93, 0, 9, 0,150, 3,
+ 28, 0, 44, 0, 7, 0,151, 3, 7, 0,152, 3, 7, 0,153, 3, 7, 0,154, 3, 4, 0, 55, 0, 0, 0,155, 3, 0, 0, 81, 3,
+143, 0, 13, 0,143, 0, 0, 0,143, 0, 1, 0, 4, 0,232, 1, 4, 0, 11, 0, 80, 0, 20, 2,130, 0, 80, 3, 2, 0,164, 0,
+ 2, 0, 79, 3, 2, 0, 34, 1, 2, 0, 35, 1, 2, 0, 24, 0, 2, 0, 24, 2, 4, 0, 41, 2,144, 0, 6, 0,144, 0, 0, 0,
+144, 0, 1, 0, 2, 0,157, 0, 2, 0,181, 1, 7, 0,180, 1, 0, 0, 38, 3,145, 0, 31, 0,145, 0, 0, 0,145, 0, 1, 0,
+144, 0,156, 3, 2, 0, 84, 1, 2, 0, 11, 0, 4, 0, 85, 1, 4, 0, 86, 1, 4, 0, 87, 1, 40, 0, 88, 1, 40, 0, 89, 1,
+ 28, 0, 44, 0, 7, 0,244, 0, 7, 0, 92, 1, 7, 0, 93, 1, 7, 0,105, 0, 7, 0, 94, 1, 7, 0,245, 0, 7, 0, 95, 1,
+ 7, 0, 96, 1, 7, 0, 97, 1, 7, 0, 98, 1, 7, 0, 99, 1, 7, 0,133, 0, 4, 0,181, 0, 0, 0,101, 1, 0, 0,102, 1,
+ 0, 0,103, 1, 0, 0,104, 1, 7, 0,113, 1, 7, 0,114, 1, 7, 0,135, 3,146, 0, 4, 0,146, 0, 0, 0,146, 0, 1, 0,
+ 40, 0,199, 2, 11, 0,157, 3, 76, 0, 4, 0, 26, 0, 25, 0, 11, 0,158, 3, 11, 0,159, 3,144, 0,160, 3,147, 0, 7, 0,
+147, 0, 0, 0,147, 0, 1, 0, 7, 0,161, 3, 7, 0,162, 3, 7, 0,163, 3, 4, 0, 24, 0, 4, 0,164, 3,148, 0, 6, 0,
+ 26, 0, 25, 0, 11, 0,165, 3, 4, 0, 24, 0, 4, 0,166, 3, 4, 0,167, 3, 4, 0,168, 3, 69, 78, 68, 66, 0, 0, 0, 0,
+};
diff --git a/source/blender/src/Bfont.c b/source/blender/src/Bfont.c
new file mode 100644
index 00000000000..adeb73f4ca3
--- /dev/null
+++ b/source/blender/src/Bfont.c
@@ -0,0 +1,134 @@
+/* DataToC output of file <Bfont> */
+/*
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 datatoc_Bfont_size= 25181;
+char datatoc_Bfont[]= {"\x80\x01\xe4\x01\x00\x00\x25\x21\x50\x53\x2d\x41\x64\x6f\x62\x65\x46\x6f\x6e\x74\x2d\x31\x2e\x30\x3a\x20\x42\x66\x6f\x6e\x74\x20\x30\x30\x31\x2e\x30\x30\x31\x0a\x31\x31\x20\x64\x69\x63\x74\x20\x62\x65\x67\x69\x6e\x0a\x2f\x46\x6f\x6e\x74\x49\x6e\x66\x6f\x20\x31\x30\x20\x64\x69\x63\x74\x20\x64\x75\x70\x20\x62\x65\x67\x69\x6e\x0a\x2f\x76\x65\x72\x73\x69\x6f\x6e\x20\x28" \
+"\x30\x30\x31\x2e\x30\x30\x31\x29\x20\x72\x65\x61\x64\x6f\x6e\x6c\x79\x20\x64\x65\x66\x0a\x2f\x46\x75\x6c\x6c\x4e\x61\x6d\x65\x20\x28\x42\x66\x6f\x6e\x74\x29\x20\x72\x65\x61\x64\x6f\x6e\x6c\x79\x20\x64\x65\x66\x0a\x2f\x46\x61\x6d\x69\x6c\x79\x4e\x61\x6d\x65\x20\x28\x42\x66\x6f\x6e\x74\x29\x20\x72\x65\x61\x64\x6f\x6e\x6c\x79\x20\x64\x65\x66\x0a\x2f\x57\x65\x69\x67\x68\x74\x20\x28\x52\x65\x67\x75\x6c\x61\x72\x29\x20\x72\x65\x61\x64\x6f\x6e\x6c\x79\x20\x64\x65\x66\x0a\x2f\x49\x74\x61\x6c\x69\x63\x41\x6e\x67\x6c\x65\x20\x30\x20\x64\x65\x66\x0a\x2f\x69\x73\x46\x69\x78\x65\x64\x50\x69\x74\x63\x68\x20\x66\x61\x6c\x73\x65\x20\x64\x65\x66\x0a\x2f\x55\x6e\x64\x65\x72\x6c\x69\x6e\x65\x50\x6f\x73\x69\x74\x69\x6f\x6e\x20\x2d\x31\x30\x30\x20\x64\x65\x66\x0a\x2f\x55\x6e\x64\x65\x72\x6c\x69\x6e\x65\x54\x68\x69\x63\x6b\x6e\x65\x73\x73\x20\x35\x30\x20\x64\x65\x66\x0a\x65\x6e\x64\x20\x72\x65\x61\x64\x6f\x6e\x6c\x79\x20\x64\x65\x66\x0a\x2f\x46\x6f\x6e\x74\x4e\x61\x6d\x65\x20\x2f\x42\x66\x6f\x6e\x74\x20\x64\x65\x66\x0a\x2f\x45\x6e" \
+"\x63\x6f\x64\x69\x6e\x67\x20\x53\x74\x61\x6e\x64\x61\x72\x64\x45\x6e\x63\x6f\x64\x69\x6e\x67\x20\x64\x65\x66\x0a\x2f\x50\x61\x69\x6e\x74\x54\x79\x70\x65\x20\x30\x20\x64\x65\x66\x0a\x2f\x46\x6f\x6e\x74\x54\x79\x70\x65\x20\x31\x20\x64\x65\x66\x0a\x2f\x46\x6f\x6e\x74\x4d\x61\x74\x72\x69\x78\x20\x5b\x30\x2e\x30\x30\x31\x20\x30\x20\x30\x20\x30\x2e\x30\x30\x31\x20\x30\x20\x30\x5d\x20\x72\x65\x61\x64\x6f\x6e\x6c\x79\x20\x64\x65\x66\x0a\x63\x75\x72\x72\x65\x6e\x74\x64\x69\x63\x74\x20\x65\x6e\x64\x0a\x63\x75\x72\x72\x65\x6e\x74\x66\x69\x6c\x65\x20\x65\x65\x78\x65\x63\x0a\x80\x02\x92\x5e\x00\x00\xd9\xd6\x6f\x63\x3b\x84\x6a\x98\x9b\x99\x74\xb0\x17\x9f\xc6\xcc\x44\x5b\xc2\xc0\x31\x03\xc6\x85\x70\xa7\xb3\x54\xa4\xa2\x80\xae\x6f\xbf\x7f\x98\xf7\x5a\x84\xba\xce\x2d\x03\x6a\x6b\x51\xb8\x48\x49\x31\x59\x1d\x92\xe5\x06\x9e\x62\x26\xd5\xad\xcc\x5d\xe4\xf8\x10\x7a\xa6\x9a\x35\xb5\x5f\x6a\x9b\x4b\x4f\x93\xc5\x6c\x23\xbc\xc6\x1d\xd7\xbf\x8f\x32\xf2\x1d\x58\xe4\x1a\x5f\x79\x0c\xee\x2f\x02\xaf\x49\x86\x95\xe9\x0c\x1d\x0b\xd2\x59\xe7" \
+"\x5b\x02\x19\x30\x0b\x0f\x69\x2c\x33\x77\x9c\x2a\xa6\x7a\xe8\x51\x7a\xbe\x12\x30\x08\x45\x22\x4a\xf6\xad\x5d\xa9\xdb\x9a\x1a\x3a\x40\xfb\x06\xb3\x6a\x9c\xcd\x69\x12\x55\x07\xfc\x2d\xe9\xd0\x41\x84\xc7\x60\x42\xf0\x3f\xcf\xd1\x53\x84\x00\x23\x97\x2a\x81\x2a\xb9\xb3\xcb\x56\x70\xc1\xce\x27\x59\x71\x1c\x75\x29\x42\x62\xd6\xf2\x91\xaf\x9b\x7c\x76\x07\x1e\xda\x7e\x7a\xd0\x26\x21\x62\x32\x22\xb9\x36\x08\x7a\xb2\x7f\xfe\x5f\x07\x86\x47\x06\x65\x92\x18\x3d\xc3\x47\xae\x92\xe6\xbf\x56\xb1\x7b\xed\xce\x13\x68\x46\xf6\xa2\xa3\x76\xab\x8c\x0b\xc0\xff\x4e\x34\x7d\x20\xfd\x0e\xc7\x7e\xfa\xb1\xf0\x63\x31\x00\x14\x8d\x2a\x7d\x2f\xd2\x1f\x12\x5a\xaa\xcd\x8f\xdb\x99\x79\x83\x2b\x67\x0d\x8a\xaa\x76\xd2\x12\xba\xb5\x61\x46\x19\x90\x96\x0c\x35\x6e\xb8\xd8\xe9\xf3\xc6\x5d\x9d\xfe\x7f\x8c\x2c\x8a\x7b\x2b\xe9\x9e\x63\xff\x6c\x86\x88\x3c\x1d\xe5\x07\x8d\xa3\xb9\x1e\x03\xe4\x84\x0d\xdd\x6d\x30\xe3\x3c\xe3\x87\x75\xdc\x80\x43\xc3\x93\x20\x76\x47\xbe\x83\x0b\xf5\xc8\x5d\x1e\xe2\x20\x72\x1a\x27\xe8\x8a\x21\x6d\xe8\x01\x0b\xe9\xd4\x4e\xdd" \
+"\x58\x9e\x87\x5f\x9f\x0e\x26\x1f\x0c\x6a\xff\x33\x93\x2a\x8b\xfe\xd2\x77\x06\x60\xdd\xe2\x8c\xb7\xd5\xde\x05\xcd\x0d\x8c\xfd\xd6\x7d\x67\xe3\x34\x3c\x66\x1f\xfa\xa3\x93\xe4\xa7\x3a\xcf\x9c\x44\xa6\x96\xa7\xa9\x74\x53\xc2\x96\x68\x98\x1f\x07\x9d\x26\x4c\x1d\x0a\xf7\x3f\x39\xc2\x6a\xe6\xb7\x78\x87\xbb\xc9\xd3\x52\xea\xa8\xb6\xa7\x5a\x38\x25\x6d\xa0\x90\x0d\x30\xcc\xbe\x0e\xa9\x67\x7f\x88\x66\x18\x51\x3d\x20\xe9\xe4\x9e\x12\xeb\xbd\x1c\x00\xde\x43\x11\x6e\x8f\x47\xdf\xb5\x21\x11\x42\x51\xd2\x07\x17\xba\xf5\xe5\xc6\x8f\x3e\x71\x21\x50\xec\x57\x94\x41\x2a\x1b\x6f\x80\xdf\xc4\x8c\x2d\x20\x5b\x7b\x9e\x88\x99\xa6\x90\x7e\x73\x85\xdc\xfe\xea\xc0\x7b\x0e\xef\x4b\xc7\x74\x1c\xf1\x19\x1e\x42\xe2\xf8\x9f\x8e\x2e\x29\x0a\xed\x6f\xcd\x1f\xe6\x48\xc4\x31\xc8\x32\x1d\x73\x99\x8d\xc6\xe1\xda\x9d\x56\x38\x43\xf9\x63\x32\x19\x97\x0e\xc8\x23\xba\xfa\xcc\x97\xbb\xd1\x33\x81\xa1\x44\x76\x82\x1f\x19\x86\xff\x4b\xaa\xf0\xe1\x71\x90\x05\xb2\x85\x2d\x55\xf2\x42\x0a\x0a\x41\x8a\x5d\x93\x48\xd2\xfa\xd1\x7b\x94\x87\x0c\x9c\x5e\x0d\xfa\x1f" \
+"\xd3\x9d\x52\x80\x84\x8f\x0b\x9b\x2f\xd3\x97\xe8\x8e\xfd\x52\x68\xea\xe7\xbe\xa9\x4e\x20\x5a\x02\x29\xc9\x7a\x8e\xcd\x90\xea\xcc\xc6\xe3\x38\x39\x06\x3f\x08\xed\x59\xc7\x1e\xe2\xa9\x30\xc6\xbf\x26\x72\x57\x87\xbd\x62\xfb\xe0\xd2\x9a\x3a\x57\x1a\x38\x29\xdb\x77\x7c\x6d\x53\xb6\xa9\xa6\x7b\xff\xbe\x23\x79\xb1\x25\x5c\x80\xf2\xf7\x84\xda\x95\x8c\x74\xb8\xa3\x0d\xf8\x8a\x44\x7c\xe5\xd3\x59\xd2\x65\xac\x95\xdd\xb6\x71\x24\xb6\x2e\x05\x8d\x7f\x93\x36\x76\x43\x6b\x69\xbb\x28\x35\xd0\xaa\x19\x2d\x71\xd8\x6e\x87\x38\x07\x1a\x0e\xe1\x3d\x4f\xe4\x48\x1e\x27\xdc\xc3\xe3\xe5\x99\xc4\x1c\x06\x6b\xf0\x36\x43\x06\x5e\x8f\x00\x22\xb4\x31\x0e\x29\x6f\x09\x29\x5e\xcb\xb8\x8b\x8e\x22\x8c\x8a\x5a\x19\xd8\x59\xfc\x2d\x2e\x84\xa9\x9a\xe6\x83\x0f\x14\x64\x63\xeb\x6a\x49\xb9\x59\x06\x42\xe6\xab\xca\x16\xd5\xe3\xb7\x20\x8a\x74\xfd\xd0\xe6\x79\x10\x3f\xee\x84\x45\x1c\x87\x58\x73\x12\x15\x0b\x66\xac\xc8\x25\xde\xff\x64\xdd\x50\xad\xda\x35\xd2\xfa\x94\xd3\xf1\x61\x96\xb9\x2b\xfa\x8a\x0e\x7a\x85\x1e\xbf\x36\x9e\x76\x16\x0c\xe8\x19\xe4\x3c" \
+"\x65\xce\x77\x1d\x39\x0c\x63\x24\xa7\xb6\x99\x56\xc3\x15\x46\x9a\x66\x6a\x2d\xec\x46\x97\x8f\xb9\xcf\xfc\x6a\x2e\xa8\x50\xd8\xce\x9d\xab\x76\x4d\x52\x99\x18\x36\xa5\x80\xa0\x1b\xc3\x75\xf1\x8d\x5d\x97\xe9\xef\xf4\x49\x7b\x85\x2a\x8a\x7b\x44\x9f\xe1\xd1\xab\xf2\x46\xd4\x06\xa8\x13\x74\xe4\x00\x0e\x94\xbf\x84\x0a\xfe\x53\x7d\x14\x11\x47\x7e\x8e\x38\x50\x37\x30\x7d\xb8\xac\x9c\xa3\xa1\x48\xf9\x69\xcc\xcf\xb3\xd9\x73\xb1\x02\x52\xdc\x8e\x0e\xb4\x8a\xfe\x53\x8b\x24\x46\xcb\x5b\x51\x52\xe5\x14\xfd\x4e\x84\xd5\x40\x9a\xa3\x3b\x5d\xf5\xa8\x26\x94\x30\xe4\x0d\xba\xcc\x5f\x8c\xb8\x76\x16\x82\x6f\x1b\x26\x8b\x7f\x6a\xac\xa1\xfe\x88\xbb\xa6\x30\xa2\x98\x7c\x45\x1b\xba\x32\x7e\x07\x90\x2b\x4b\xb0\x91\x9f\xca\xf4\x07\x4e\xcb\xfa\x20\x2a\xc3\x47\xba\x5a\x5c\xa2\x7e\x62\x2c\xc3\xa3\x2f\x58\x7c\x2b\xb1\x7a\xfb\xfe\x1d\xa1\x46\x62\xeb\x85\x34\x0c\x1c\xb8\x43\x91\x49\x58\x63\x45\x3c\xe3\x8e\x0f\xda\x52\xa7\x39\xe1\xe6\xda\x83\xfb\xab\x0b\x3f\xbf\x41\xec\xb2\x3f\x9f\xd5\xd3\x72\x40\xc8\x55\x49\x28\x5e\x7b\x6c\xab\x59\xa9\xce\x63" \
+"\xc4\x1f\x0f\x98\x8a\x4d\x89\xd2\xc5\xe4\xff\x49\x7e\x78\xf9\xd6\xaa\xd4\xa8\x49\x36\x7d\x71\x4e\xe2\x25\x89\xf9\xbc\xef\x21\xe7\xf4\x7d\x74\x89\x7e\xbb\x1f\xc1\xc2\x76\x79\x13\x50\xfa\x57\x30\x50\x3e\xf6\x1d\x79\xf7\x87\xc6\xc1\xfd\x94\xd3\x11\xd2\x11\xf7\x2c\xcd\x5b\x01\xbe\xc3\xec\x42\x5f\x90\x3a\xeb\x02\x2a\x4f\x19\x52\xa4\xa7\xf4\x72\xbc\xc0\x65\x17\x37\x45\x8d\xa8\x1c\x59\x3c\x74\x5b\xa2\x79\x1c\x7b\x60\xfc\xa5\xb4\x45\x38\xe8\x36\x7a\x8a\xdf\x9e\x83\x5e\xab\x52\x04\x70\x0d\xa0\x75\xaa\x92\x1c\xf1\x9a\xd3\x77\x10\xe9\x8d\x60\x5e\xa7\x0d\x25\x76\x69\x49\xd3\x61\x6d\x94\x83\xbe\x77\x2d\x7c\xd0\xe1\x27\x5e\x30\x3e\x21\xbc\xf8\x9a\xe9\x2e\x9e\x07\x90\x01\x79\x00\xeb\x47\x19\x34\x0d\x2e\x01\x19\xab\x1b\xb3\xaa\xa4\xe7\x02\x19\xb6\xe2\xfa\x60\xc0\x17\xb9\xda\xda\x10\x8c\x24\xb4\xd8\x3b\x5f\x31\xa5\xa2\x86\xfc\x2f\xa8\x41\xf2\xb2\xd3\x3e\x0a\xef\x99\x41\xdb\xf7\x48\x11\x69\x31\xfe\x55\x88\xd3\x75\xf0\xda\x4d\xdd\xa6\x29\x91\xc6\x04\x68\x88\xf1\x30\x00\x9e\xd2\xec\xcf\x1a\x91\x8c\x5f\xa4\x75\xc6\x00\xb7\x68\xa1" \
+"\x3b\x09\xbd\x08\x20\x2c\x1a\xff\x9d\x77\xf5\xfa\x31\xb0\x9c\xe3\x66\xe4\x69\x53\x18\x99\x55\xc4\x81\x85\x80\xd0\x81\xca\x3e\xcc\xad\x89\x5b\xdf\x70\xd0\xf3\x57\xb4\x6d\x52\x8d\x38\xef\xd2\x28\x56\xc8\xad\x1f\x20\xe6\x8c\xca\x3d\xdc\xb0\x5c\x6c\xcf\xb1\xd5\xa9\xee\xac\x9e\xfe\x26\xf2\x8d\x06\x73\xd9\xc1\x86\xa6\xe3\x24\xd0\x77\x56\x2c\x22\xc3\x47\x77\x5e\xea\xf1\x7a\x4f\xa9\xad\x24\xdd\x78\x44\x17\x03\x2c\x7d\x26\x4e\x48\xe6\x19\x3e\x12\xcd\xce\x42\x8c\x4f\x7d\xe5\xdf\x00\x5c\x19\x76\xfd\xa1\xdb\x33\xe4\xe5\xd4\x0d\x9b\x1a\x32\x36\x69\x36\x26\x55\x98\x31\x96\xe9\x58\xbf\x6f\x00\x7a\x93\x5f\xd7\x32\x21\xb0\xd1\x4d\x88\xc6\x06\x47\x61\x64\x98\x00\x9f\x5e\x5b\xca\x07\x94\x7d\xfe\x3a\x26\x6b\x31\x65\x0e\xc2\xa3\x0c\x4f\xfd\x99\x96\x36\x1e\x25\x8c\xbd\xf1\x8d\x2f\x39\x8b\x91\x4a\x58\x0f\xb2\xb3\x3f\xf1\x5b\x81\x1e\x4f\x13\x68\x48\x38\xd7\x25\x7c\xf2\x4d\x51\x6d\x9b\x00\xe9\x7a\xba\x6b\x5b\x91\x5c\xa2\x5a\x04\x71\xaa\x54\xd3\x84\x8e\x40\x1b\x5d\x98\xf8\x6b\x5e\x5d\xa0\x6d\xf9\xf1\xfb\x66\x82\x42\x60\x33\x70\x8c\xf5" \
+"\x97\x41\x2d\xbd\x9d\x75\xbc\x5b\x61\x31\x8a\x6b\x6a\x87\xcc\xcb\x26\x77\x21\x95\x57\x7a\x9e\xc6\x08\x8e\xda\x03\x38\xf9\x50\x56\xfd\x52\xf6\xcb\xe7\x39\xa0\x32\x34\xbb\x18\x6c\x82\xfd\xc1\x18\x33\xc9\x32\x03\x43\xb0\xbb\x7c\xa5\xac\x8e\xfc\x9c\x9b\xdc\xfc\x33\xed\x69\x5e\x30\x2c\xe9\xbb\xbc\x7b\x64\xda\xdf\x24\x72\x36\xdb\xdf\x27\x9c\x70\xce\x2e\x13\x0a\xd5\x8b\x45\x0c\x8a\x86\x2c\x82\x5e\x88\x04\x6f\x4d\x15\x73\xe1\xa2\x0f\x26\x9f\xda\x8a\x66\xab\x02\x8e\x30\x9e\x39\x5e\x3b\xb6\x11\x7f\xbe\xdf\xc4\x42\xee\x6b\x32\x9a\x02\x8e\xa7\x98\x12\x19\xe2\x01\xfd\xfb\x11\x66\x14\x6f\x1c\x61\x88\x0f\x3c\x41\xe6\x27\x31\x19\xa6\x1f\x12\x36\x04\x18\x59\xd3\xe2\xfa\x4a\xe2\xb9\x43\x8a\x1d\x12\x55\x9c\x7c\x91\x54\x11\xaf\xa7\x33\x0d\x36\x52\x61\x40\xce\xc9\x6f\xc7\xd6\xd2\xeb\x94\x37\xb5\xf1\x88\x56\xfe\xdb\x7a\x40\x67\xb3\x4f\x71\xa3\x7e\x4b\x6b\x4f\x66\xf4\x15\x93\xc6\xd2\xfb\x23\x88\x49\x0f\x20\x2d\x96\x86\xfd\x71\x53\x6f\xa1\x6e\xd4\xf2\x21\x0c\x0c\x10\x8f\xc2\xc7\x25\xe4\xfb\x6e\x07\xd5\xc6\x37\x50\x20\xd1\x8c\x22\x2f" \
+"\x66\xf9\xd9\xa6\x76\x1f\x6a\x02\x12\x6a\x2e\x92\x94\x7d\x00\xd0\x59\xd1\xf7\x37\x8f\xb1\x13\xb7\x7f\x47\x76\x14\x88\x03\xe9\x6d\x77\xb5\x73\xdf\x6e\x8b\xb6\xab\x6d\x68\x48\x3e\x98\x8f\x0e\x9d\x52\x9a\xfd\x8e\xd7\x3b\x01\x0b\x62\x6b\x8c\x0c\xf0\x90\x38\x26\x0e\xdc\xed\x9a\xae\x97\xb3\xcf\x68\xea\xde\x54\x7e\x9d\x5a\x34\x76\x7e\x60\x17\xcb\x87\x86\x29\x10\xc4\xd2\x2c\x7d\x44\x91\xe8\xec\x34\xde\x66\x83\x50\x65\xed\xda\xf4\xd7\xcd\x5f\x3a\x60\x12\x42\xd5\x5b\xf7\x3a\x2c\x39\x96\xc1\x8b\x87\x24\x8f\xec\x5e\xd1\xec\xd5\xe3\x2a\xb0\xad\xce\x57\x97\xf0\x91\xb9\x2d\xd1\xb1\xc9\x7b\x20\xc4\x2c\x9e\x53\xcb\xca\x06\x6a\x36\x5d\x2b\xd1\x0c\x72\x4c\x64\xf2\x68\xa5\x8a\x0f\x8f\x05\x21\xe4\xc3\xf3\x6f\x51\xf9\xae\x0f\xa7\x28\xa5\x33\x61\xb9\xd7\x96\x76\xfd\x16\x67\x09\x15\xb9\xee\xbd\x5e\x31\x68\x64\x62\xa5\xc4\x1f\x94\x70\x7d\xc7\x2e\x67\xfc\x4f\x64\xa5\x70\x68\x52\xf9\xdb\xcd\x22\xc6\x1f\xc6\xbf\xb5\x48\xd4\xb6\x3e\x57\x0d\x35\xab\x54\xde\x9c\x83\xc9\xa2\xad\x2f\x2c\xbb\x69\x77\x84\x2f\xe4\xb8\x24\x55\xda\x0b\xfb\xf2\x7c" \
+"\xcd\xa8\xfc\x18\xf5\x31\x54\xa1\x6b\xd3\x15\x3f\xdb\x59\x0f\x74\xc0\x12\xd0\x56\x5f\x4b\x47\xef\xf7\x69\x7c\x55\xae\x90\xdc\x18\xbc\x5e\x28\xd1\x84\xea\xe1\x35\x45\xf0\x2a\x2f\x5c\x12\xf0\x78\xd2\x8c\xa8\xda\x69\x3c\xf6\xf7\xee\xbc\xf7\x0a\xa2\x18\x88\xe2\x5b\x6b\x9d\xa8\x33\xba\x0f\x4f\x44\x9a\xe1\x34\x29\xe4\x7f\x23\x29\xe0\x61\xe1\x2c\x55\x10\xe1\x63\xc6\x30\xb6\x62\xeb\xff\xb2\x18\xd2\x3a\x0e\xc8\x54\x12\x84\x89\x23\xab\x3f\xc3\xee\xc3\xa7\xa7\x08\xcf\xe8\xd6\x64\x5b\xc3\x5a\xe9\x56\x62\xcf\xb9\xe5\xc4\x8c\xfd\xec\xdb\x96\x3e\x3e\x02\x0f\x33\xe8\x9d\x2c\xea\x6b\xbc\xdc\xd6\xd1\x2a\xa5\x12\x5e\x8f\xeb\xf1\xc0\xfe\x6a\x9b\x30\xf6\xef\x7b\x11\x8c\x0c\x65\xfb\x66\x9c\x7e\x82\x02\x26\x3e\xff\x1b\x86\xb6\x78\x17\x9e\x67\x04\x30\x9a\x4e\xec\x0e\xfe\xde\xef\x2a\xe4\xe0\x8a\x57\xd3\xec\x4e\xd4\x01\x6b\x8b\x51\x05\xee\xb9\x54\xcd\x33\x53\x43\x34\x2a\x87\xff\xf4\x7b\x9d\xb9\x74\x72\xa0\x74\xf6\x1e\x93\x7f\x81\x9c\x33\xe5\x27\x7a\x02\x7a\x91\xe5\x19\x7a\x02\x97\x07\x7d\xf6\x4c\x81\xd1\x6e\x8a\xf6\xd3\x21\xb7\x3c\xc0" \
+"\x6c\xa7\xa1\x9d\xad\xbc\x86\xc0\xb3\xcb\xc3\x88\x54\x29\x6e\xc1\x7a\x83\x0b\x4b\x7c\x53\x8b\x50\x0c\x47\x5d\xd6\xb3\x2b\x46\x8b\x5b\x35\xe4\x61\x69\x43\xe6\x76\x5c\xb7\x83\x72\xe7\x4a\x8c\x30\x87\xb4\x0a\xb8\x94\x2e\x4b\xb6\xcd\x53\x2f\x97\xce\x54\xf3\xe8\xe9\x7e\x8e\x1e\x0b\x71\xdb\xfc\x99\x12\x10\xd7\xee\x79\x9b\xff\x15\xd6\x59\x06\xc4\x03\xc9\x83\x30\xbb\x9f\xeb\x0e\x1b\x9b\xf5\x4d\xe5\x82\x70\xa8\xa4\xfd\x45\x17\xfd\xf2\xaf\x13\xe8\x9b\xa1\x1b\x9e\x5f\xa0\x5a\x4f\x6d\x85\xcb\x2a\x46\xb5\x78\xf7\xf4\x55\xbf\xa7\xff\x24\xfb\x73\x36\xbf\x4e\xd3\xb6\xfc\x05\x0c\x64\x20\x30\xc8\x1a\xea\x7b\x19\xa1\xfd\x86\xa8\x3c\x0f\xbb\x3e\x18\xef\xb1\x62\x5c\x6d\xc3\x70\x4e\xf2\xa1\xfa\xe0\xd2\x5e\x6f\x22\x64\xc4\x47\x67\x4a\x7b\xd8\xd9\xb4\xa0\x21\x40\x69\x7b\xb7\x7d\x54\x4d\x50\x63\x6d\xf7\xad\xa8\xef\x7a\x58\xe9\x75\xed\x94\x2b\x90\xc3\xff\xde\x7c\xd6\x85\x9c\x75\xf4\x07\x49\x0d\x64\xa4\x44\xaf\xbf\x5d\xe1\xfc\x80\x60\x4d\xe7\xc4\x96\xdf\x78\x38\x17\x65\x5e\x17\x32\x4c\x26\x1b\x59\xb8\x5d\x8c\x25\x4f\xf9\x42\xc7\x1b\xdc" \
+"\xe6\x72\xb0\xb3\xe4\xc9\x0c\x38\x71\x01\x19\xcf\x68\xb1\xbf\x4f\xed\x8f\xe2\x68\x5c\x15\xf9\x62\xcd\x16\x69\xd7\xb8\x8e\xb2\x6b\x08\xc2\x0d\x20\x9c\x54\x6d\x92\x98\x39\xf1\x48\x3e\x4a\x7a\xd4\x58\xb3\x39\x17\xba\x4a\x49\x52\x25\x50\xb6\xa5\x28\x59\x1e\xf4\xd1\x6e\xa3\x18\xb6\xc9\x8b\x91\xe1\x94\xdb\xb8\x01\x6d\x63\x9c\x25\xf7\xb1\x6f\x32\xd1\xdd\xd0\x4e\x00\x48\x06\xec\x4c\x4f\x3f\x84\x1a\xe3\x48\x8e\xe5\xf8\x78\xa0\x94\x9b\x5b\x33\x3d\x28\x16\xc0\x60\x8b\xc1\xc0\x29\x74\x4f\x8c\x74\x9e\xf8\x40\xa8\xe3\xae\x38\x72\x5c\xa0\x1f\xc8\x5e\x52\x63\x8b\x43\x5f\x2f\x4c\xb4\x98\x2b\x83\x95\xb1\x04\xd4\x38\xd1\xbe\xd1\x66\x7a\xe0\x48\xea\xf4\x6f\xaf\x8a\x78\x17\xcb\x09\x92\xea\xef\x5e\xf1\x1c\x15\xaa\x33\x02\xb0\x7d\xb3\xd9\x63\x53\x11\x10\x71\x7b\x6f\x44\x5e\x9c\xc8\x5a\x75\x1e\xae\x83\x2a\xa1\x5b\x4c\x55\xc7\x2c\x4b\xc7\x00\x9f\x6f\x9e\xec\x3f\xfc\x49\x43\xdc\x71\xa9\x9e\x4a\x07\x51\xd6\x95\x9b\xde\x81\x5b\x3f\xa9\xc4\xa8\xd0\xe6\x53\xa8\x04\x13\x1b\xb0\x9d\x92\x38\x2a\xfe\x8f\xab\x77\x3c\x7f\x39\x25\x6b\x54\xff\xf6" \
+"\x4c\x9f\x26\xb0\xe9\x0d\x61\x6b\x40\x37\xce\xc9\xcc\xda\x03\x8b\x7b\x96\x97\x6e\x1c\xc6\x63\xf7\xa7\x9b\x25\xb8\xfd\xd6\x15\xfd\xfa\xb3\x1a\xe9\x62\xcd\x75\x6d\x5e\xde\x0f\x97\xb8\x77\xdb\x9f\x1a\x34\xea\x37\x42\x64\x6c\xaf\xae\x11\x6f\x87\xbd\xf4\xee\xad\x17\x11\xf1\x88\x4e\x7c\x4b\xcb\x72\x87\xe4\xdd\x4f\xf4\xb4\x54\xd7\x78\x3a\xc1\xea\x11\x15\x84\x6e\x0a\x5d\x5d\x00\xb7\xf5\x86\x3d\x5f\x44\xbf\x8d\xed\x5f\x7e\x57\x3a\x95\x86\xd5\x6e\x74\xd8\xc0\x0a\x70\x26\xe8\x32\x23\x78\x39\x2d\xac\xe8\x25\x4d\xe2\x99\x6e\x83\xfd\xd2\xa8\xb4\x53\x38\x33\x38\xbd\xde\x61\xc1\x88\x8a\x2a\x94\x32\x6f\x18\x13\xfe\xb1\x6d\x2a\x04\x41\xac\x60\xfb\xa0\x36\x3a\xa5\xca\x40\x4b\x26\x3a\x4b\xb0\xd8\x62\x92\x7d\x76\xf8\x0e\x6a\xe4\xe2\x51\xf1\xfb\x7f\x1b\x17\x5c\x9d\x8c\x0c\x3b\x56\xfc\x7a\x0d\x80\x0e\xb8\x37\x9b\x2c\xfd\x1d\x2f\x7b\xbf\xb9\x9a\xa3\x72\xfa\xd8\x30\xda\x18\x29\x89\xba\xc8\xd1\x93\x56\xea\x0b\xfb\x2a\x38\xb5\xf3\xee\xa6\x87\x5c\x97\x56\xae\x59\x4f\x47\x0e\x18\x05\xb3\x57\x83\x87\x66\x3b\xba\x42\x01\x06\x48\x05\x1c\x4f" \
+"\x31\xba\xc2\x3e\xb3\x35\xba\x1f\x8f\x0f\x69\x20\xfb\xbc\x8a\x0b\xf4\x24\x64\x65\x50\xbb\xfd\x35\x5a\x9a\xd4\xb5\x7e\xd1\x3a\x0a\x37\xa8\x1b\xec\x73\x65\xe0\xc1\x67\xe7\xe7\x4c\x82\xa9\x40\xf7\x8f\xa0\x06\x0c\xbb\x3e\x73\x55\x85\x61\x83\x9d\xa4\x05\x12\x33\x45\x35\xe2\xaa\x20\xf8\x85\xc2\x3a\x72\xf3\x9c\x35\xdb\xe4\x25\x33\x96\xf0\xe3\x4a\x64\x42\x8c\x73\x64\x67\x2f\xa0\x91\x27\xa0\x4b\xde\xda\x1c\x6c\xe8\x6b\x5b\x00\x39\xfa\x88\x06\x21\x76\x73\x67\xb3\xdd\x6c\x28\x8e\xaf\xb9\x02\x0c\xc0\x42\xd5\x98\x29\xe9\xdf\x29\xd4\x55\x11\x34\x3a\xd3\xb5\x2e\xd3\xce\xbd\x1a\x08\x5a\x73\xe0\x97\xc3\xe0\xd5\x22\xa2\xbd\xde\xda\x9b\x4e\xc9\x65\xf2\x09\x38\xd7\x98\xef\xf7\x79\x03\x10\xdd\x38\x2d\x23\xf3\x92\x80\x2c\x72\xd7\x84\x65\xdc\xe9\xb4\x02\x1d\x57\xcb\xb9\x90\x10\x25\x71\x3c\xf4\xd6\x8c\xbf\x18\xc0\x25\xff\xa1\x93\xd8\x1e\x28\x9b\x58\x3c\xba\x87\x0b\x17\xe4\x2b\x9d\xcb\x66\xc4\xc5\x01\x01\x57\xda\x7e\x50\x4c\x1e\xb6\xcf\x99\x87\xf8\x06\xb5\xd7\x4d\x80\xc8\x0a\x13\x6b\x8a\xca\x54\x78\xbf\x8c\x75\x32\x20\x1b\x69\xae\xe0" \
+"\xaa\x7b\x35\x4c\x30\xd2\x06\xe3\xc3\x72\xeb\x57\x91\x96\x1a\x15\x11\xd6\xc6\xf5\x7d\x6d\x9c\xaa\xcc\x8f\xe4\x3e\xc4\x80\x15\xf3\x99\x5b\x47\xa4\x71\xa4\xff\x30\x24\xee\x69\xdc\xa3\x5d\x03\x21\x2f\x96\xf1\xd3\xbe\x6f\x9d\xea\xbd\x19\x3a\xf7\x4b\x76\xf7\xa7\xab\x76\xdf\x01\xb4\x62\x53\x00\x02\x6d\x11\xff\x74\xf4\x6b\x65\xdc\x64\x46\x15\x85\xb3\x5a\xd2\x74\x20\xc5\x18\x52\x72\x78\xda\x0e\x93\x50\xc2\x50\x45\x4e\xdf\x9d\xb7\x82\x31\x8b\xa2\x22\x0c\xb0\x2d\xf2\x67\xe8\x80\x44\x58\xe1\xb5\x95\x03\xd2\x14\x26\x9b\x06\xce\x88\x16\xaa\x5c\x9c\xa5\x74\x8e\xfa\x48\xcb\xeb\xc1\x74\xf4\x04\xd1\x37\xba\x1d\x08\x21\xc1\xdd\x49\x1b\xd4\xcc\x16\xc5\xb3\x08\x7a\x86\x08\xff\x60\x33\x02\xa9\xc1\x60\x80\xb2\x6d\x8f\x83\x32\xdb\xd0\x3a\x9f\x67\xe9\x64\x1a\x02\xb1\x81\x7a\xa8\x78\x47\x27\x73\xe4\x6c\x72\xa1\xf3\x18\x0a\xdd\x69\x00\x20\xe6\x4b\xd0\xe9\x04\x46\xf9\x62\x25\x2e\x57\x9e\x91\x3c\x55\xe5\xc7\xec\x7e\x50\xb7\xb5\x0c\x44\x03\x0f\x17\x24\x5c\x92\x6d\x3d\x18\x80\x4e\xef\x58\xe6\xd7\xcc\x5a\x93\x76\xab\x33\xa8\x5f\x5d\x17\x5a" \
+"\xf4\xa4\xac\xc9\xde\x70\x8f\xc1\xd1\x82\xc9\xcf\x76\xaf\x33\x03\x53\x90\x35\x07\x02\xdf\x92\x32\x65\xa8\x9f\x85\x1c\x42\x1d\x40\xe9\x4c\xb6\x85\xac\x44\xdf\x72\xfe\xec\x6f\x1e\x49\x89\x82\xa4\x83\xc4\xbd\x6f\x9b\x93\xd9\x40\xc2\x73\x8f\xc9\x4d\x16\x99\xe4\x53\xbf\x35\xd2\x57\xea\x15\x22\xbb\xb8\x1c\x3f\xb3\xd6\x53\x0e\x70\x20\xa9\x9f\x85\xcf\x13\xa9\xbc\x93\x6f\xba\x72\x2b\x76\x98\x19\x47\xb8\xf7\xef\x3e\x27\x7d\x08\xb0\x5b\x2e\x7f\x25\xa9\xf7\xba\xaa\xe7\x6a\x7c\x5d\x52\xcb\x87\x32\xb1\x55\x4a\x73\xdb\x4c\x60\xad\x2c\xf2\x26\xa3\xab\x0e\x00\x5f\x4c\x63\x4b\x0e\x27\xd5\x74\xb6\x48\x02\xea\xb0\x41\x62\x96\x24\x46\x56\x89\x97\xda\xf5\x8d\x11\x18\xe9\x29\xb9\x3a\xb2\x38\x36\x7a\x94\xe7\x97\x29\xd6\x60\x04\xf3\x2e\x3f\xc8\xe9\x80\xa1\x5f\x8a\xf4\xb7\x8d\x91\x0e\x19\x5b\xc5\x46\x03\xe3\xbb\xcb\xdf\x30\x78\x71\x07\x00\x82\xc1\xa0\x43\x6c\xb9\x47\xed\xab\x65\x9f\x60\x62\x22\x04\x8e\x72\x9b\xa0\x93\xc1\xaa\x30\x73\xfd\xac\xf5\x3b\x91\xb0\x37\xcb\xf5\x3c\x18\xf7\xeb\x4f\x0c\x75\x4a\x12\x97\x0e\xd0\x07\xe3\xe6\x8a\xb6" \
+"\x6b\x21\xac\xd3\xe8\xf4\x5b\x56\x50\xed\x37\x9a\xaf\x20\xdd\x11\x97\x4f\x68\xee\x19\xe2\x4c\x9b\x48\x27\x5a\xd1\x5d\x77\x36\x11\x09\xde\x3e\x12\x88\x19\x0f\x3b\xc2\xcb\x39\x96\x00\x34\x7a\x68\x54\xc7\x68\xb4\x9a\xb4\xb1\x8d\xad\xa9\x9a\x71\x23\x4b\xc6\x9d\x96\x50\x2c\xd4\xf8\xae\xe8\xfb\x8c\x4a\xd6\xbd\x29\x78\x71\x9c\x41\x10\x0f\xc9\x12\x2d\x10\xd2\x68\xf7\x26\x21\x28\xf9\x3d\x77\x99\xb3\x48\x58\x7a\x6d\xd0\x5b\xba\xe7\xf6\xc9\x9a\x1a\x24\x73\x7e\xd9\x2c\xc2\x8c\x67\xe5\x0f\xfa\xe3\x8c\x6a\xcc\x76\xa9\x9d\x54\x96\x1f\x80\xc2\xfe\x90\xdd\x54\x4f\xd3\x94\x21\x3c\x6b\xd3\xaa\x9f\xf8\x69\x3f\x72\x00\x17\xea\x5c\xe6\xf0\x76\x06\xfa\xb5\xb8\xe3\x40\xba\x28\x5e\x43\xe1\x85\x59\x0f\x10\xae\x90\xa5\x3b\x06\x49\x0d\x12\x1d\x0a\x2e\xed\x17\x33\x21\x1b\xc1\xd4\x3f\xc2\x05\x4f\x42\xb1\x51\xc8\x54\xfe\xe1\x24\x6e\xd0\xe1\xca\xd5\x59\xd6\x8c\x8e\xe3\xdf\x3c\xd6\x13\x91\x5c\x5c\xa4\xcf\xde\x9e\xfa\x0c\x92\x96\x43\xcc\x78\xd3\x6d\x5f\xba\x28\xa7\xb2\x5a\x22\x2e\xea\x1c\x6d\xab\xb6\x53\xc5\x24\x33\x45\x98\xa8\x79\x30\x47\xb3" \
+"\x16\xda\xa8\xb6\xa0\x93\xc3\xb1\xb0\xc9\xea\xd5\xd1\x87\xde\x09\x01\x9d\xaa\xf0\xaf\xf6\xda\xff\x5c\x35\x66\xab\x16\xeb\xb4\xf8\x76\x0a\x55\x0e\x18\xda\xb8\x84\xbf\xe1\x70\x42\x03\xe7\x24\xeb\x22\xd6\xb5\x39\x68\x97\x4c\x45\x65\x53\x14\x27\xaa\x6c\xa1\xef\xec\x7e\x09\x90\x1b\x75\xd1\xae\xad\x5c\x10\xb9\x19\x08\x41\x1d\x86\x43\x01\xf8\x3e\xdd\xef\x86\x0c\x0f\xfc\xcb\x8c\xb3\x34\xf7\x03\xe6\x22\xb8\x66\x52\x76\x4c\xda\xfe\xf2\x18\x73\x16\x77\x5a\x04\x95\xec\xb0\x74\x44\x4d\x7b\xc9\xc0\xff\xbc\x6b\xc3\x03\xd9\xb8\x6a\xdb\x74\x51\xcf\xc1\xe3\x65\x29\x1d\xe8\x48\x55\xec\x97\x4a\x5d\x96\xa6\xab\x9b\x51\x83\x51\x6d\xab\xb8\x25\xbe\x72\x6a\x71\x90\xea\x4c\x8f\x5c\x62\xbe\x70\x97\xc6\x97\xb5\x63\x07\xb6\x32\xbe\x9d\x8d\x11\xc7\x94\xe6\x0e\xf0\x5f\xee\x8b\xa1\x60\x55\x89\x9a\x4f\x43\xa8\x65\xfd\x7e\x17\xa5\x8f\x2f\x21\x9d\x64\x06\x82\xfd\xbc\x42\x15\xcd\xf3\x74\x3e\xf1\xa1\xb1\xc7\xea\x3d\x87\x37\x71\x19\x99\x1b\x81\x95\xbd\x8c\x70\xd3\x31\xb0\x26\x2c\x6e\x1d\x87\xb2\x7a\xe9\x03\xa6\x61\xaf\x3d\x9f\x62\x3d\x36\x2e\x3e" \
+"\xf6\x89\x11\x96\xf9\xa5\x63\xd3\xac\x4c\x07\x68\x27\x6a\x77\xdd\x9f\xd2\x60\x21\xec\x57\xa4\x70\x2f\xe2\xf7\xec\x8c\xb9\xb6\x14\xc9\x33\x58\x61\x34\xc6\x46\x31\xf8\x60\x33\x52\x73\xa9\x4e\x49\x70\x7b\x6a\x78\x71\xb8\x5d\xc2\xe0\x44\xd3\xc8\xed\xd1\x29\xa0\x7f\x59\xa3\x37\x09\x1b\xfc\x4e\x5d\x93\x8d\x0c\x9c\x2c\xe2\x6a\x7e\x9f\xb5\x6a\x54\x19\x27\xdc\x29\x86\xb8\xad\x45\x8d\x80\xdd\x39\xc2\x38\x29\x94\x6b\xf2\xf1\xae\x81\x98\x7b\x51\x65\x01\xcc\x09\x6d\x9a\x61\xa9\x3f\xa7\x34\x60\xef\x3f\x74\xa3\x7a\x9e\x5e\xdd\x23\x5a\xb8\x45\xba\xdc\x9b\xcd\x41\xbf\x1f\xd1\x3e\x78\x9c\x4d\x9a\xd4\x3a\xa5\xd0\xfe\x41\xcc\x94\xc8\x79\x4e\x81\x4f\x79\x27\x22\x03\xa9\x76\x78\x34\x23\x77\x8e\x1d\x0f\x90\x9c\x5a\x86\x65\x69\x0b\x70\x20\x4a\x00\xdb\x9f\x84\x64\x07\x6a\x58\x8e\x2a\x9f\x9f\x85\x0b\xaf\x5c\x58\x90\x0c\x37\xb9\x2f\x8e\x1f\x2b\x27\x10\x53\x7a\x36\x07\x96\x9e\xd7\x0e\x8f\x88\x93\x8d\xe7\x9d\x43\x98\x77\xa4\x72\x9f\x47\xd2\x90\x62\x7f\x2c\x84\xda\xaa\xb7\x06\xb9\xd2\x5e\x5f\x63\xf0\x74\x1e\x7e\x4c\x73\xd4\xf6\x66\x5c\x60" \
+"\x9f\xfc\xb1\xad\xee\x57\x91\x78\xef\x53\x67\x94\x6f\xc1\xc8\x9d\xc7\x54\xf5\xa7\x44\x2b\x09\x45\x37\x53\xa4\x6d\x5a\x2e\x65\xd7\x24\x17\x4a\xaa\x49\x1f\x97\x3f\x0d\xe9\x97\x6b\xf8\x1c\x5c\x23\x46\x05\xeb\x55\xdb\x14\xd5\x99\x9d\xf9\xb0\x25\xff\xbf\x31\xdd\xc3\xf3\xcd\x96\xee\xea\xa8\x89\x99\xc9\xde\xcd\xc7\xa2\x77\x92\x29\x59\x69\x72\x90\x1b\xc2\xa7\x0f\x11\x66\x9b\x51\x14\x40\x19\xeb\xd9\x3f\x9a\xf2\xe1\x0d\x21\xb6\x26\x74\x2f\x6b\x32\xcf\x6e\x1d\x88\x37\x21\x8b\x88\xd6\x3f\x5c\x7d\x5a\x76\xca\x07\x0d\x2d\x2b\xa2\x6a\x35\x8f\x0d\xbe\xab\xe2\xc4\x90\x11\x31\x88\x78\xf6\x63\x1c\xdb\xb8\xab\x91\xe8\xf2\xe1\x56\xd8\x1d\xfb\xf9\x29\xf4\x90\x6f\x02\x0d\x43\x45\x61\x3b\xca\x5c\xfe\x47\xbd\x06\x77\xb4\xba\xcb\x22\x12\x55\x73\x67\xb2\x0f\x8b\x2a\x9a\x27\x18\x00\x13\x16\xf0\xff\xfc\x5d\xd9\x97\x76\x59\x4c\xe4\x75\xc8\x89\x0d\xbe\xf7\xff\x18\xfd\xa2\x18\xb8\x14\x46\xad\xf2\x41\xff\x0e\x55\xeb\x63\x67\x83\xb5\x54\x50\x3f\x9c\xb8\xcc\xbf\x3d\x9c\xfc\x3b\x25\x6d\xe5\x66\x8b\x5e\xb2\xb2\xa4\xe7\x31\x9b\x23\x38\xc4\x0f\xa9" \
+"\x90\xfb\xd7\x59\x81\xe6\x48\xdb\x8b\xc5\x4e\x6d\x66\x19\x30\x2c\x7b\xd3\xd8\x6a\xb9\xed\x7c\x85\x27\x25\xa2\x14\xd3\x86\x9b\xa8\x0b\xde\x98\x8f\xd3\x70\x85\x88\x15\xa9\x59\xbb\x5c\x3d\x90\x7e\x8e\xa5\x5b\x40\x2d\x29\x38\xa4\x6c\x31\xf1\x89\x63\x2c\xbf\x64\x0b\xe1\xa6\xf4\xb7\x0e\x45\x8d\xb8\xc1\xdc\x48\xd3\x43\xdf\x10\x2b\xe3\x22\x57\x5b\x20\xe5\x54\xa2\x71\xfb\x7d\xda\x76\x1f\xfe\x10\x21\xaa\xc9\xd1\x31\x1e\x71\x68\xc1\xd4\x52\x40\x50\xd6\x20\x95\xd9\xf4\xed\xc1\xdf\x68\x4d\x80\xe4\x8c\x37\xfc\xcc\xe5\xbb\x24\x63\x99\xf1\x8a\x87\xab\xa9\x3e\xfa\xb8\x3f\xa7\x8b\xb7\x39\xaa\x24\xd9\xc9\x81\xa9\xde\x4e\x99\x41\x99\xc3\xd3\xe5\x9f\xbf\x00\x91\x0c\xd1\x19\xf7\x7a\x13\x6c\xad\xa3\xbb\xeb\xfe\x57\x50\x19\x6e\xb3\x9e\x30\xe8\x14\x8a\x51\xc6\x4e\x12\x2c\x4b\xb5\x12\xee\x60\x3d\xf7\xe5\xfe\x02\x37\xa9\x20\xb4\x88\xb1\xa1\xd5\x84\x80\x6c\x5d\x9f\xc9\xd4\xee\xdf\xe9\xba\xf3\x04\xf8\x05\x21\xd6\xc1\xd6\x5f\x33\x8d\x3c\x48\x3f\x8e\xb8\x25\x7a\x76\x88\x61\x5d\x8e\xf5\x08\x93\xe0\x7e\x43\x5d\xaa\x69\x79\xe7\xab\x55\x69\xbf" \
+"\x7e\x58\x39\x2a\xfd\xb3\x55\xfb\xc1\xa3\x70\x47\x1c\x89\x68\xc7\x79\x0d\x7a\x3a\xe7\xa0\xb0\x32\xc8\x50\x41\x63\x19\x43\x81\x5b\x61\xb2\x83\xc3\x6f\x94\x86\x47\x39\x91\x71\xd1\xb1\x33\x9a\x1d\x1c\xb4\x4a\x0d\x45\x93\x60\xd2\x6c\xb0\x59\xf8\xee\x40\x8c\x55\xc4\xa9\x14\xfb\xee\xc2\x29\x38\x27\x3b\xe2\xbd\x82\xb2\x5a\xb0\xe2\x2e\x6c\x9c\xcc\xae\x55\x76\xa5\x89\xb8\xa0\x85\x59\xaa\xb8\x25\x30\x41\xf1\xe0\x75\xa4\xf8\xd5\x70\x8f\x80\x17\x82\x85\xd8\x42\xbe\x3f\xee\xb3\x54\x47\x1b\x32\x53\xc7\x5b\x7e\xa4\xc0\x4c\x6b\x64\xe5\x06\x19\xa4\x59\xeb\x75\xf7\x3d\x6d\xcd\x4c\x80\xe6\x29\xf3\x55\x3a\xbd\x80\xd8\x15\x35\x44\x50\x01\x19\xab\xcb\x47\xb0\x2e\x06\x54\x23\x96\x5f\x90\x90\xfd\xd2\x4e\x0a\x1f\xda\xb3\xf8\x5f\x51\xf4\x4f\xd7\x3f\xc4\x64\xa5\x78\x36\x0e\xb4\x7d\x98\x6a\xad\x7d\x0e\x6c\xd3\xa1\x83\xe5\x72\x38\xfc\x10\xdd\x10\xf2\x4a\x57\xa8\x79\x7f\xf7\xd4\xc8\x47\xcc\x74\xf6\xff\x9a\x18\x89\x7f\x2d\xb1\xd4\x11\xd4\x66\xec\x1d\x58\xb1\xa6\x87\x6b\xd2\xe6\xdb\x7c\x47\x62\x32\xe6\x6b\xde\x4f\xde\xbe\x25\xf1\xf2\xa7\x1b" \
+"\x75\xfd\xc9\x4c\xfb\xba\x12\x87\x60\xbf\xcf\x0f\x6b\x43\x92\xfb\x69\x66\x19\xc8\x47\xd1\xa5\x7d\xc0\x12\xe4\xa2\xee\xd6\xdd\x8a\x31\x28\x64\x7a\xf9\x14\x79\x39\xc7\x0b\x00\xf3\x4c\x39\x17\xd3\x6e\xd4\xfa\xda\x5f\x9a\x91\xb3\xad\x2d\xe9\x9b\xf6\x43\x23\xcb\x5d\x05\x02\x5b\x79\x74\x5d\x40\x45\x1f\xb6\xb3\x4a\x3b\xc6\x29\x13\x66\x33\x4c\x7e\xe0\x99\x41\xfe\xba\x5a\x10\x5b\xdc\x9a\x82\x14\xbb\x67\x8d\xf8\xbc\xf5\xfa\x8b\xbf\x30\x8a\x28\xc7\xc9\x9b\x93\x53\x3e\xfe\x50\x03\x6b\x68\x24\x67\xba\x5e\xba\xe1\x6b\xa7\x76\xe6\xc7\x55\xf1\xdb\x8b\x14\x1c\xe9\x05\x83\x90\x65\x15\xe4\xec\xf9\x73\x52\x3e\x93\xaf\xfb\xae\x80\xb0\xff\xf8\x8e\xef\x71\xa5\xfe\xee\x16\x63\xa2\xca\x6c\x4f\xeb\xf6\x20\xdc\x0b\x33\xef\x6d\x04\xcc\xb3\xd4\x56\x26\x05\xe8\xaa\x4c\x97\x83\xa5\xce\x7a\x69\x7c\x6b\x1c\x89\xc4\x63\xc2\x06\x7a\x1d\x4b\xb2\x1a\xe8\x46\x21\xe7\x18\x49\x21\xbb\xb5\xf0\x4b\x16\x72\xa3\x62\x72\x06\x5d\x02\x20\x10\x4f\x5d\x77\xdb\x99\x0f\xb6\x81\x7b\xf2\xa2\xb6\x98\xc8\x18\x0e\x5f\x30\x23\x3c\xed\x47\xb7\x98\x5c\x86\x1f\x52\xae" \
+"\x35\x9b\xaa\x60\xdd\x5d\x89\x5a\x1f\x80\x14\x83\x0f\x56\x9a\x5d\xbe\xb2\x7c\xd6\x82\x2b\x40\x86\xf9\x00\x30\xd7\x5c\xec\xca\x18\x2f\x3c\xe8\xbe\x7c\x03\x47\x91\xb7\xd7\xf0\x01\x64\xeb\xcb\xb9\xcd\x7a\xde\x29\xc7\x7f\x04\x4a\x39\x5c\x50\xe3\x6d\x51\xc5\x20\x26\x23\x35\x5e\xf5\x09\x8d\xf5\xdf\xdf\x5f\x2a\xaf\x9d\xd1\xd7\x5a\x40\x00\xf8\xf4\xf6\x19\x3c\x07\xa9\x8a\xf6\xb8\x60\x9b\x44\x5e\x9b\x16\x0f\xf1\xa9\x14\x31\xd7\xd1\x6f\xef\xc8\x90\x05\x21\x99\x8e\xef\x94\x6e\x75\x6d\xf8\x43\x62\x6d\x9d\xbb\xac\xa0\xa9\x55\x36\x00\x99\x81\xd9\x96\x43\x7c\x97\x65\x6a\x83\xcf\x86\x05\xff\x8b\x92\xc0\x00\x73\x5b\x06\x81\x3a\x3c\x67\x6a\xdf\x34\xd3\x66\xfc\x99\x07\x24\x22\x20\x88\x6f\x18\xe7\xda\x65\x72\x31\x80\xb9\x3a\xeb\x1a\x6c\x94\xd8\x02\x6d\x7f\x4c\xaa\xe6\xa7\x4d\xe6\x90\x78\xea\xb7\x4e\xf6\xcc\xe4\x86\xf9\x58\x64\xc4\xc6\xa8\x71\xd8\x2a\x23\xc1\xea\x22\xc3\x98\x7d\x4f\x4f\x18\xa1\xad\x10\xae\x2e\x43\xaa\x83\x9c\xe8\x56\x59\xad\x1e\x27\xd1\xb1\x32\x89\x54\x6d\xcb\x19\xb3\x69\x2a\x97\x8d\x38\x2f\x92\x6d\xaf\xe1\xf3\xd2" \
+"\xce\x51\xc4\xed\x9f\xc9\xa5\x37\xb5\x99\x45\x99\x75\x76\xd9\x82\x41\x8b\x44\x76\x3b\xc9\xca\x52\x81\xa2\x17\x66\x3d\x9b\x6d\xce\x7d\x29\x6f\x8b\x53\xae\x85\xf2\x2c\x02\xeb\xba\x3a\xf7\x63\x88\xad\x6a\xfa\xf8\x22\x98\x85\x03\xd0\xaa\x81\x17\x3c\x49\xd4\x2e\xbf\xbe\x58\xcf\xdd\xa4\xb2\x2d\xd7\x83\xcc\xe1\x75\xad\x8a\xb4\x03\x00\x0f\x0e\xdd\x49\xb8\x16\xa7\x53\xd8\x1f\x89\xfe\x6c\x5a\x15\xeb\x05\x44\x8f\xec\xda\xb1\xaa\xef\xb4\x08\xa8\x8c\xe2\xbd\x10\x91\x3e\xa3\xe1\x5d\xcd\x25\x78\x62\x81\xf9\x81\xfd\xd5\xae\xc8\x13\x8f\x8c\x09\xb1\x32\x69\x86\x45\x71\xf4\x85\x06\x78\x19\x9b\x84\xfe\xe2\xcf\x2b\x38\xa8\x45\xa9\x5f\x53\xa6\x22\x45\xd5\xbb\x62\xf3\x77\x8f\x79\xf9\x77\x81\xa5\x67\x92\x8c\x0d\x88\xee\xa0\xaa\xfd\xab\xd4\x62\xef\xac\xc3\xf9\x44\xcf\x3c\x18\x82\x80\xa7\xa3\xb2\x82\xdc\x06\x8b\xc6\xc9\x6e\x1a\x5b\x9b\x90\x8f\xd4\x55\x6a\x32\xc6\x4a\xd2\xa8\x92\xe8\xac\x1e\x98\xce\x45\x2c\x2f\x58\xa5\xb4\xdd\x2d\xfc\xf8\x2f\x1a\x21\x8e\xbd\x4d\x4d\x14\xb9\xf7\xf9\x58\x43\x75\xf9\x97\x76\x39\x12\x89\x80\xbd\x86\x94\x55" \
+"\x07\x2f\x3c\x8e\x6e\x69\xfc\x2d\xa5\xbb\x86\x32\xff\xb4\x38\x82\x89\x4c\xbd\xda\x98\x2e\x94\x2c\x01\xef\x2f\x48\xc0\x46\x0e\x4a\x5a\x88\xf5\x23\x28\xab\x1d\x11\x61\x4d\xb8\x20\x26\x26\xfc\x0c\x00\xe2\x0b\xde\x84\xb7\x79\xd1\x53\x03\xa4\xf3\x20\x6f\x6d\x91\xcb\x39\xf1\xc0\x05\x6b\xa4\x80\x03\xda\x45\xb2\xc8\xde\x2d\x41\x69\x6e\x73\xb8\x4b\xf3\xdd\x31\xe2\xaa\xbd\x31\xf6\x81\x21\x96\x26\xcb\x03\xd6\x6f\xce\x96\xa8\x89\xa2\xe4\x03\x60\x69\xb8\x1b\x6a\x51\x20\x93\xe6\x3c\xdb\xc7\xb0\x4a\x64\x12\x50\x8c\x46\x80\x73\x77\x6f\x52\xac\x08\x06\xa8\xbc\x38\xc5\x70\x9f\xa9\xd8\xc8\x5a\xfb\x68\x70\x13\xb3\x47\x3b\xb5\x8a\xe0\x9e\xfc\x94\x32\x41\x37\x21\x78\x8e\x89\x6c\x14\x8e\xec\x90\x59\xc5\xbe\xbc\x13\x66\xe3\xf0\x26\xaa\x81\x7b\x45\x7b\xc1\x0d\x25\x85\x2c\xa7\xd2\x8d\xac\x9a\xd0\x2a\x9c\x23\x7e\xb0\x01\x62\xc1\x87\x66\xeb\xe5\x16\x22\xbb\x12\x6f\x40\x53\x6b\x11\x9d\xf1\x75\x3b\x08\xd3\x3c\xc8\x57\xb8\x59\x84\xf9\x3c\x12\x51\xed\xe1\x35\xdd\x83\xff\xda\x40\xef\xc2\x07\xb5\x28\x03\x2e\x6c\xdc\x34\x6c\x3e\xfe\x8c\x25\x74" \
+"\x0f\x28\xa9\x5a\x2f\x88\x66\xfd\x07\xdf\x84\xcf\x3c\xea\x15\x86\x9b\x3f\x70\x25\x48\xde\x37\x3b\x14\x22\xa7\x47\xde\xdd\xa4\xa1\x5c\x83\xf4\xeb\xf3\xed\xb8\x81\x4d\xa5\xa0\x8b\xab\xea\xea\x45\x71\x80\x5d\xd7\x09\x54\x29\xd5\x23\xa4\x18\x78\xcc\xb4\xb2\x99\x2f\xf5\x39\x16\xaf\xce\x0c\xaf\xcb\x81\x27\x5d\x7f\x12\x0c\x37\x2b\x24\xfc\x01\x68\x74\x3b\x87\xc1\x91\xb7\x29\x3e\x4e\xa5\xbd\xe8\x80\xe0\x0b\x8e\xff\x02\xdf\x5f\x50\xdb\x57\xf9\x79\x1f\xb5\x32\xf1\x1f\x7f\xae\x63\xee\xb0\x74\x41\xdc\xa0\xbd\x19\xcc\x67\x14\xe7\x2a\xc3\x22\xb4\x69\x79\x6e\x63\x95\x8b\x01\xdd\x7c\x43\xac\x2f\xbd\xcf\x0e\xe5\x4f\x9e\xbb\xcb\x7e\xec\x0e\x35\x79\xf3\x84\x4e\x27\x48\x07\xa5\x16\x4e\x29\x65\x80\x14\xa8\x88\xc6\x6d\xe2\x20\x87\xa8\x68\x9b\x73\x39\x32\x42\x11\x48\xf5\x7c\x46\xbc\xc2\x90\x59\x8c\x55\x08\x0a\x81\xe3\xa7\x0f\x0f\xc9\x36\xef\xc2\x9a\xcc\x81\x1b\xbe\xf5\x66\xa6\xb2\xc9\x07\xc5\x4e\x95\x45\xf5\x04\x8f\x04\x54\x0d\xd9\x3b\xf2\xdf\xe2\xc7\xe7\x76\xbc\x37\x73\x38\x0f\xd9\x03\x00\xb5\xbe\x03\xa2\x7f\x78\xce\xb5\x08\xe1\x9b" \
+"\x94\xca\x75\x46\x60\x51\xf6\xa5\xfd\x73\x94\xd9\x8a\x2c\xcb\x24\x2c\xdd\x3b\x7a\x44\xaa\xf8\xeb\x58\xf2\xd1\x2a\x47\x1f\x75\x05\x95\xdd\xd8\x9a\x74\x29\xe7\x8a\x7b\x55\x80\x47\x6d\x6f\x11\x48\xa3\xe1\x6d\x07\x28\x85\x4a\x4c\x9b\x6b\x22\xc1\x72\xf0\x3d\x1f\x18\x2e\xd7\xc5\x60\x72\xd5\x12\xd6\x39\x77\x32\x12\x05\xaf\xfe\x15\xf6\x40\x91\xab\xd9\xf3\x9f\xfa\xe7\xe4\x40\xa4\x61\x3d\x96\x09\xe6\x0b\x8a\x84\x5f\xd1\x8a\x61\x57\x8b\xbe\xab\x87\x9e\xaa\x63\xc6\x12\x7f\x2c\x66\x01\xec\x5a\x49\xd6\x87\x74\x6b\xf7\xaf\x2e\xee\x33\x4f\xa3\xf9\x05\x89\x91\x5c\x8a\x17\xcf\x9e\x32\x6d\x83\x54\x3d\xb8\xfc\xe8\x14\x43\x6b\xbd\x3d\xc6\x1b\x06\xbd\x77\x22\xec\x5e\x69\x41\x8c\xb5\xf8\x20\x0c\x77\x7e\x00\x0e\xe2\x4e\x07\x79\x6f\x2f\x1e\x31\xce\xbb\x7d\xf7\xeb\x06\xe5\x22\xa1\xae\x48\x9a\x25\x5e\x08\x58\x7d\x36\xb6\x64\x2e\x54\x90\xd5\xfb\x3e\x47\xb1\x78\xff\xc2\x0e\x69\xce\x97\xb3\x90\x8c\xbf\xa7\xf8\x2c\x46\xe3\x9a\x8e\x20\xae\x9f\xc7\x9a\x4e\xa5\x44\x60\x49\x08\x0d\xf6\xa2\x9b\x30\x07\x79\x5a\xad\x28\xe2\xa6\xbd\x23\x57\xe1\x2d" \
+"\xd1\xdc\x46\x16\x9c\xd8\x27\x7e\x54\x8e\xcf\x64\xdb\x9b\xa6\x2b\xfd\xa1\xff\x8f\x94\x5d\x11\x07\x6d\xb0\x70\x0e\x57\x93\xba\x7b\x20\x9f\xfc\x53\x6f\xb6\xfa\x1c\xef\xcf\x5c\x40\x11\x1a\xd8\x00\x29\x18\x8e\xf6\x13\xac\x20\x89\xea\x45\x93\xfb\xea\xcf\x5f\x06\x71\xd1\x6b\x45\x7a\xc6\x94\x0d\x12\x1c\xee\xbf\xa8\xcd\x90\xea\xb5\xf7\xc0\x97\xb0\x5f\x9d\x3c\xe0\x1a\x78\x18\x10\x42\x66\x33\xb9\x6f\x27\x06\xcd\xbb\x10\x01\x8d\x2d\xea\x30\x90\x1a\x5c\x9b\xd5\xda\x58\x97\x00\x6f\x6d\x1c\x2c\xac\x18\xd7\xcd\xba\x2a\x77\x7c\x30\x29\xc7\x55\x51\xf4\x18\xaa\x47\x9c\x8d\xf9\xea\xc1\xae\x4d\xb8\x2f\x6b\x70\xeb\x7c\xfe\x07\xa3\x9c\x47\x3b\x7a\xe0\xc4\xd7\x47\x51\x91\xcf\xb2\x61\x76\x2d\x9a\x6d\xbe\x8f\x3f\x53\x87\x6e\xa6\xae\x2f\xc3\x21\x00\xea\xd4\xdf\x0b\xf8\xd2\x9e\x11\x8b\xef\x0f\x39\x85\xb9\x98\x47\x38\x02\x3e\x0a\x67\xf3\xf7\xb6\x51\x0a\x26\x31\x07\x83\x0a\xca\xb8\x4f\x95\x54\xd5\x7a\x85\xd0\x18\x8d\x84\x0c\xf4\xfb\xa0\x29\x38\xdb\x7b\x78\x17\xf0\x28\x1d\x20\xd5\xde\x24\x31\xad\xb0\x0b\xd1\x91\x68\x9a\x9a\xb6\xb7\x05\x3c" \
+"\x83\x46\xe0\x2f\x7d\x6e\x2f\xf6\xb4\xde\x7d\xf3\xfb\x37\x19\x93\x4d\xa4\x74\xda\x98\xbf\xf4\x2f\xc7\x44\xd0\xd1\x31\x5a\xc5\xb0\x02\xbf\x7f\xc6\x30\x10\xa8\xf3\x29\xc3\x32\xaf\x21\xac\x5c\xb9\xfe\x60\xdd\x41\x18\x24\xbb\x0a\x68\xf2\x65\xb9\xb0\xce\xd7\xa6\x52\xbd\xf5\xd0\x3e\x26\xcf\x61\xc0\x2d\x2e\x62\x42\xc9\x45\x5f\xce\xd3\xcc\xe1\x89\xcc\x64\x6e\x3a\x54\x1d\x70\x90\x33\x0f\x01\xaa\x4f\x29\xef\x4d\x01\xd0\xd1\x50\xd0\xd6\x1b\xa8\x99\xe5\xbc\x28\xfa\x0d\xf0\x17\x60\x36\xeb\x17\xca\xa5\xd7\x6d\x8f\xa3\xa1\x88\x65\x6d\x62\x66\x36\xe7\x8d\x9d\x16\x05\xc9\x59\x0a\xf1\x71\xe1\xb9\xea\x80\xd4\xce\xba\x3b\x72\x4f\x45\x2b\xab\xd0\xdb\x3f\xdb\x70\x36\x4d\x9c\x74\x96\x8c\x71\xba\x4f\x83\x6d\xe7\xcd\xaa\xfd\x83\x61\x8d\x6b\xf2\x05\xee\xa7\x20\x87\xc2\x8f\x97\x47\x16\x51\xfe\x54\x78\x67\x83\x3d\x56\x7e\x42\x33\xc9\x00\xaa\x46\x12\x26\x98\xe1\x03\x75\x62\x64\x8d\x72\x27\xa1\xbd\x92\x94\x2b\x37\xbd\x12\x9d\xb5\xb9\x07\x75\x4d\x38\xe5\x5b\x50\xe9\x4f\xa5\x8c\x18\x62\xc5\x82\x32\x46\x2c\x6f\xe6\xf1\x5c\xcc\xf6\x4e\x13\x12" \
+"\xe7\xdb\xc9\xcf\x54\xcd\x89\x8a\x71\x2d\x04\x48\x91\xcc\x03\x56\xe6\xc8\xd0\xa6\xda\xb7\xd9\x15\x59\x17\x28\x6b\xa1\x44\xe6\x60\xec\x5b\x6a\x0f\x26\xff\x84\x0d\xf8\x62\x6a\xb1\xdf\x36\xf7\x72\x52\x93\xa1\x2a\x2b\x0a\xc0\x0c\x5e\xc8\xf8\xc8\x55\xe7\xf7\xf6\xc9\xdd\xb4\xd9\x71\x0c\xde\x58\x35\x15\x06\x1a\xd6\xdc\x98\xfd\x5c\x38\x9e\x11\xe9\xda\x5f\xea\x5b\x61\x47\x94\x0b\x03\xe2\xc7\xfa\xc9\x84\x5c\xf4\x12\xd2\xf8\xd4\x59\xb6\x60\x49\x79\xfa\xde\x3b\x79\x76\x13\x1c\xdd\x7e\x30\x77\xbe\xd9\x48\xc2\x5b\x04\xd5\x11\x89\x22\xf6\x07\x06\x8f\xf5\x61\xc0\xfc\x37\x91\x52\x0a\x4d\x6f\x1f\x50\x4a\x9c\x0e\x44\x6f\x52\x4c\xa8\xcb\x09\xdc\x36\xe9\xaf\xba\xa9\x68\xf3\x02\x8f\x6d\xd5\xf7\xa3\xc4\xb5\x25\x10\x32\xda\x1c\x81\x76\xa2\xbb\x62\xca\xe2\xf4\x27\x1b\x5a\xff\xeb\x7d\x62\xce\x9b\xb3\xd3\x3a\x87\x50\x61\xdc\x20\x88\x12\xe2\x3c\xfb\x33\xaa\xa5\x2f\x04\x3f\xa0\x29\x69\x55\x17\x7a\x20\x91\x45\x55\x9f\x93\x49\xd1\xc9\xa9\x19\xe1\xa4\x06\x97\x5c\x09\xdf\x37\x89\xca\x43\xdd\x64\xa1\xf8\x0a\xd1\xc3\x1b\x92\x04\xdb\xe3\xbe\xcb" \
+"\x86\xe4\x0a\xa0\x22\xdd\xfa\x6e\xcb\x21\xba\x3c\x88\xb9\xeb\x48\x2d\x69\xb0\xa1\x24\xa9\xb9\xae\xa8\x92\x17\x39\x80\xc6\xa2\xc2\xc5\x3e\xfe\x66\xc8\x9a\x8c\x62\x28\xd0\x80\x5f\x97\x4d\x28\xbe\x58\x4b\x9c\x2f\xcf\xdc\x0b\x7d\x9f\x18\x59\x8e\x3c\x02\x9c\x19\x2c\xcb\x27\xde\xa6\x7a\x5d\xd7\x5b\x57\x39\xc7\x45\xd3\xf4\x8c\xf1\x6a\x2b\xc1\x0a\x96\x41\xe2\xa3\xca\xa5\x9b\x5d\xdb\xcf\x1c\xae\x9d\xc9\xc7\xa9\xae\x1c\x24\x75\x6a\x9b\x57\xd1\xdf\xab\x68\x48\x4c\xb4\x65\xc4\xf8\xa3\xfc\x96\x21\xe0\x76\x80\x82\x91\xd3\x1c\x50\x11\xae\x21\x9c\x6c\x8b\x78\xe1\x6f\x09\x2e\xe4\x4f\x70\x79\x23\xb5\xaa\x0c\x83\xad\xa9\x04\x28\x08\x65\x22\x9a\xe3\xc8\x39\x32\x76\xdc\x80\x15\xd0\x3e\x83\x44\xc1\x34\xa3\x23\x60\x2d\xe1\x1a\xdb\x32\xc2\x2c\x16\xb5\x53\x15\x52\x23\x64\x0a\xf1\xda\x0c\x68\xf0\xfe\xbe\x36\x30\xd5\x57\x41\xb7\x1b\xe8\x17\xf6\xa9\xb3\xa4\x37\x42\x46\xdb\x07\xd6\x80\x3a\xf4\x78\x34\xff\xd5\xaa\x51\xeb\x10\x2e\x12\xe5\xba\x8b\x76\x7f\x0c\x4a\xad\x6a\xab\xa1\x03\x6c\x03\x71\xd3\x02\x58\x5a\xe3\xca\xc4\xc3\x45\x58\xa8\x28" \
+"\x57\xf7\xd2\x05\x1a\x75\x9f\x2a\x03\x49\x94\xf7\xec\x6e\x10\xec\xa9\xb3\x16\xc6\x20\x4f\x8a\x60\x46\x06\xa1\x1b\x47\x9b\xf1\x70\x3c\xbc\x33\x86\x9a\x00\xcf\xcb\x2b\x66\x58\xb4\x8b\xef\x48\x1a\x2e\xae\x4c\x41\x0e\x87\xca\xd3\x7c\xc9\x04\xe3\x28\x77\x2e\x66\x17\x47\x8f\xa7\xa4\x4d\xc0\x87\x10\x1b\x94\x7f\x7b\xbf\xd1\xa0\x31\x5d\x8a\x5e\xa1\xb5\xcd\x50\x50\x21\x49\xcb\x2d\x24\xc2\xad\x56\x07\xea\xc8\x8a\x14\x3e\x14\x6e\x54\x10\xee\xcf\x7b\xaf\xe9\x28\x87\x33\x55\x88\x40\xcc\xc6\xcf\x97\xa2\x85\xcf\x3a\xf6\xbb\xc9\x5b\xb9\x4c\x2e\xd1\xad\x99\x47\x9e\xf1\x6d\x42\x81\x6d\x13\x46\x1e\xba\x4c\xf9\x7d\xc5\xf3\xdf\xdb\x10\x5d\x86\xe8\x3b\xbc\x2a\x04\x9b\x81\xec\x91\xa6\xf4\xde\x67\x03\xa6\x91\x96\x39\x81\x13\xfd\x9d\xf2\x42\x61\xa5\x6b\x57\xb4\xf5\xf7\x2f\x13\x22\x87\xdb\x5e\x4c\x76\x9c\xf7\x94\x2c\x8e\xa4\x14\xb8\x60\xb3\x8a\x36\x27\xd4\xeb\x60\xd7\x27\x2d\x33\xd7\x27\x2f\x77\x78\x16\xc5\xa6\x9e\x1a\x73\x15\x10\x6e\x17\xa6\x84\xd1\xe8\x67\xf8\xc8\x85\xee\xe0\x0d\x32\x6e\x21\xd3\x9a\x05\xef\x89\xe2\x57\x83\x98\xe1\x3b" \
+"\xd0\x31\xcc\xed\x51\x95\x22\xa7\x2e\xb5\x79\x6e\x1f\x6c\xe2\x0a\x50\x06\x2f\x54\xb4\xb0\x56\x46\xab\xdd\x55\x8f\xac\xe3\x78\xe5\x4b\x8c\x85\xc3\xb0\xad\x5c\x52\xb3\x61\x73\x74\xec\xe0\x46\x2c\xa6\xce\x17\x63\x00\xd5\x2f\xcb\x99\xdd\xb2\xf6\xc4\x1e\x4a\xd0\x64\xf5\x55\x88\x84\x06\xd5\x49\xc7\xf8\x3d\xce\x8d\x4a\x3d\x64\xb5\x9d\x33\x83\x5f\x74\xd9\xda\xa2\x20\x88\x0a\x73\xdd\x41\x10\xdf\x13\xa3\xac\x49\x8c\x61\x45\x43\xc7\x74\x89\xfb\xbc\x6a\x44\x4e\x19\xe1\xca\x28\x75\xa1\x72\x0a\xd0\x1d\x30\xd9\x52\xea\x4b\x86\x9c\x09\xfd\xf1\x90\x16\xba\x8b\x65\x6f\x25\x48\x5f\x21\xb1\x14\xf6\xd2\x84\x01\xff\x54\x99\xab\x8c\xde\x39\x56\x22\xb5\xe4\x27\x0d\x9e\x23\x39\x71\x10\x3d\x61\x6f\x27\x30\xc0\x58\x66\xc9\x53\x49\x71\xe3\x74\x14\x49\xa9\x87\x6b\x08\x60\xfa\x17\x19\xf2\x33\xa6\x1d\xa0\xa9\x2b\xef\x5a\xfe\xc6\xd1\x36\xf9\x1f\xd9\x17\x76\x39\xc0\x14\x45\x4d\x32\x18\x22\xbe\xa6\x1c\xb5\x31\x7e\xde\x85\xab\x00\x55\xd4\xe2\x5e\x23\x0b\xba\xfd\x2a\xa2\xe7\x6f\x29\x35\x15\x00\xc4\xd3\x11\x49\xb4\xd3\x2b\x0a\x0b\xa9\x2a\xd9\x64" \
+"\xdc\x6a\xd3\x08\x44\x2c\x41\x7c\xd6\x67\xc6\x1e\xbf\x19\x47\x36\xaf\x26\xb3\xc7\x46\x8a\x61\x6c\xff\x8a\x7d\x28\xe3\xa1\x4c\xed\x89\xb5\x97\x82\xc7\x93\x32\xca\x3f\xcc\xc9\xd2\xb0\x60\x22\x38\x43\x7b\xb7\x01\x4c\x9a\xeb\xb3\xd8\x0c\x75\xbc\x2e\x9c\xfc\x71\xa0\xe9\xc5\x55\x88\x1e\xf8\x8c\x0c\x5e\x86\x41\x56\xc3\xea\xf6\x5b\xa9\x16\xf6\xb3\x32\x09\x72\xdd\xb5\x75\x4b\xf8\xfa\xb2\x0d\x1b\x11\xfd\xf2\x2e\xd9\x26\xad\x29\xc7\x1d\x4a\x28\x23\x44\xd2\xd0\x3a\xb4\x85\xf4\x8a\x71\xcf\x22\xe1\x7a\x5c\x6f\xdd\xb7\x18\x96\x31\x07\x15\x42\x38\x3a\xa5\x72\x53\x1b\x1f\x30\x0e\x06\xa0\x42\x2d\x40\x57\xb8\x07\x1d\x7b\xf8\xe7\x4c\x01\x85\x52\x7a\x36\xc6\x2b\x8f\x87\x05\xad\x5a\xea\xc1\x0b\x0d\x9e\xc8\xd2\xeb\x22\x10\x93\x22\x0c\xa2\x7d\x11\x2a\x78\xb2\xfe\x46\xf7\x62\xef\xfd\x79\x06\xe4\x88\x8e\xe0\x54\xb5\xf4\x7a\x82\xa5\xf7\x1a\x28\x07\xc2\x4b\x45\x6d\x9a\x08\x45\x49\x13\xbb\x5d\x8d\x85\xa3\x8e\x66\xe6\xa7\x40\x3c\x52\x8c\x49\xcd\xdd\x2c\x8b\x6a\x43\x4b\xe8\xc0\xc9\xc7\xc6\x03\x8a\xe4\x8c\xa1\xd4\x39\x37\x33\x5e\x26\x59\xe1" \
+"\x5c\x25\xef\x38\x23\x32\xcb\x7b\x91\x8c\x3e\x25\x4e\x11\xdf\xec\xd3\x03\x98\x30\xc8\x49\x12\xca\xcb\x64\xb9\xab\x33\xfe\x8f\x27\x8d\x7d\x1c\xec\xb3\x2d\xea\x7e\x14\x41\xae\x61\xf1\xf2\x2d\x3f\x31\x0a\x89\xea\x89\xba\xe1\x84\x24\x36\xc3\xad\x15\xb9\xa3\x76\x7d\xf4\x42\xac\x91\x7c\xf2\x05\x15\xe6\x33\xa5\x18\x47\x9d\x74\xac\xb7\x93\xb0\x94\x88\x58\x54\x0a\x53\x16\xad\x43\xe4\x11\x25\x88\xf8\xea\x4d\xe9\x91\x6f\xfd\x1f\x4d\xd4\x6f\xde\xd7\x2e\x4d\x1d\x0a\xc0\x79\x11\xad\x46\xfc\x35\x88\x10\xb1\xa2\x1c\x71\x7c\xb5\x92\xeb\xf8\x50\x50\xf2\x5e\x15\xc0\xa2\xec\x15\xa3\xf4\xd9\x0f\xa7\x54\xc3\x2b\xd8\xdc\xb1\x45\x63\x23\x3a\xd9\xfc\xc3\x66\x0d\xc4\x69\x06\xd9\x30\xd1\xc7\x8f\x8b\x33\xe3\xb4\x50\x94\xce\xb7\x99\x1f\xf5\x3c\xb6\xcd\xc7\x99\xf4\xe8\xfb\xd1\xa9\x2a\xa3\x43\xd9\xb5\x1b\x39\x73\x6b\x4e\xc0\xfe\xec\xb7\xe6\x72\x2a\x9b\x13\x8e\x53\xcf\xac\x35\x14\xfa\x02\x96\x25\xd6\xba\x23\x08\xb3\xaa\x5a\xd6\xa0\xda\xfb\x82\xc5\x18\xbf\x17\xec\xe3\x9d\x03\x60\x20\xa8\xad\xf8\xd7\x29\x0e\x0e\x50\x86\x22\x41\x6c\x6a\x2e\xc3" \
+"\x96\x96\x7b\x67\x38\x79\xca\xd5\x6b\xf5\xbf\x81\xc0\x28\x5a\x05\x1e\x64\x77\x9c\xd0\x16\xce\x77\x30\x45\x36\x16\xe6\xd9\x61\xa7\x72\x69\x9b\xbc\x4e\x03\xaa\xe2\xd1\xa7\x93\x9a\x5a\x7e\xc1\x0c\xfd\xe4\xa5\x03\x1f\x66\x6a\x02\xeb\x12\x27\x98\xad\xb6\xc2\x7e\xb7\x72\xca\xd1\x20\x44\x62\x63\xb9\x37\x15\x74\x59\xe0\x4f\xa0\xa6\xab\x27\xb3\xad\x92\x4f\xa7\x24\x4b\xc3\x16\xf8\xb1\x61\x7a\x0e\x56\xea\x63\x14\x8a\xfc\x02\x1f\x2f\xbf\xbb\x88\xe0\xe9\xac\x1c\x3b\x4d\xe7\x7c\x56\x43\x19\x09\xde\x77\x9d\x1d\x1e\xa6\x6f\x6b\x8a\x99\xfe\x1a\x69\xf3\x5b\xd0\x02\xf9\xbc\x28\x22\x8a\x5b\x20\xab\xf6\x40\x39\x07\x91\xf3\x9b\x5d\xe4\xe4\x9e\x5e\xb9\x95\x3f\xec\xb0\xba\x23\x91\xab\xd1\xd5\xd6\x01\x9e\x8f\xb9\x21\xf8\x54\x01\x5b\xc9\x00\xae\x70\x34\xa5\xca\x18\x14\xea\x7d\xff\x8e\x23\x8a\x15\x57\x9d\x28\x57\x96\xde\xe2\x72\x77\x7f\xbe\x7b\x19\x0a\xaf\x14\x42\x23\x08\xfd\xcb\x11\x4f\xef\x4f\x31\x5c\x6f\x3e\x40\x5e\x96\x5f\x32\xf6\x13\x4e\x59\xf7\x04\x19\x92\x8e\xc9\x65\x89\x24\xb3\x5d\x50\x9e\x90\x22\xf8\xad\x14\xf5\xb4\x1e\x84\xf1" \
+"\x0a\x78\xcd\x0a\xc8\x77\xc3\xc1\x30\xcd\x8f\x30\x35\x9b\xf2\x32\x63\xb5\x9a\xb6\x2c\xf3\x05\x12\x79\x8c\x3c\x38\x8d\xd5\x9c\x9e\x7a\x1c\x7d\x2a\x98\x53\x2f\x84\x10\x36\xf6\xa4\x7b\x44\xed\x97\x14\xa1\x80\x18\xfb\x99\x24\x09\x64\xe3\xeb\x0f\xcc\x21\x45\x5a\xaf\x47\xc8\xd7\x18\x1c\x88\x7b\xe0\x70\xcd\xb7\xab\x82\x77\x9d\x57\x9b\x37\x59\x32\x79\x8f\x0c\x76\x33\x83\x6d\x6f\x27\xc2\xce\x77\x96\x59\x09\xc7\x56\x58\xcf\x20\xf1\x8d\x6a\x0b\x13\xf1\x8c\x4a\x13\xf1\x74\xba\xe0\xd8\x8b\x53\x23\xba\xbd\x7a\x40\xa8\x79\x3f\xb6\x65\xe8\x98\x60\x04\xa2\xbf\x98\x49\x0c\xf0\x37\x33\x70\xda\xd8\x81\x1e\x27\x31\xd1\x84\x18\x8c\x16\x11\xd8\xda\x78\xdd\xf8\x28\xa9\x18\x4e\xc6\xdb\x63\x56\xe1\xe9\xff\xef\x76\x0d\x2c\xbe\x91\x98\xcf\x65\x66\xa8\xcc\xd4\xb3\x6d\x36\x65\x30\x9b\x5b\xaa\x0a\x57\x83\x31\x5f\xa5\xc7\x3e\xa2\xbb\xef\xba\x07\xe1\x80\xb2\xc9\x27\xdf\xd5\xc2\xca\x41\xd8\xbc\xcc\xa1\x35\x67\xc8\x6c\x38\x77\xcd\x98\xe3\x69\x08\x37\x63\x64\xe2\xe3\xce\x68\xac\xf9\x7e\x27\xb9\x01\xf3\x86\xe2\x68\x24\xb0\xf2\x33\x1b\x53\xfc\xfa" \
+"\xdb\x02\xc9\xc5\x40\x9c\x66\xab\xac\x3b\x23\x3c\x9a\x70\x20\x0e\xfc\x4e\x5b\xa2\x36\x8b\xdf\x9a\x61\x9d\xec\x31\x21\xfd\x43\x3c\x64\x7f\xcc\x53\xeb\x07\xd9\xd7\x88\x55\x4c\xac\xa1\xb4\x36\x3d\x2b\xbb\xcf\x7d\x32\x9d\xf6\x60\x9f\xcb\x11\x3d\x1a\xb8\xce\xce\xe8\x49\x20\xde\xfc\x40\x9c\x4e\x8c\x29\x79\x49\xde\x85\x48\x62\x2d\xa1\xac\x2a\xe6\xa4\xf8\x8b\xff\x8c\x54\x05\xf4\x83\x9e\xb9\xb1\x05\x1b\xc9\x44\x45\x25\x20\x0b\x4f\x0f\xda\xc9\x29\x3d\xdc\x52\x66\x8f\x89\x5d\xa1\x5d\xb8\x85\x8c\x09\x76\xdc\xd9\xb8\x9d\xe3\xb8\x01\xdb\x23\xb7\xb7\x9a\xc3\x7b\x3b\x7c\xa6\xfb\x97\xf8\x53\xc7\x9e\xa3\xce\x04\x83\x20\x45\x89\x5d\x34\xd5\x54\xdb\xe1\x55\x92\x1a\x15\x7a\x8a\x6c\xbd\x5d\x1d\x24\x13\x7f\xb9\xfb\xba\x86\x01\x8b\x82\x94\x18\x93\x71\x99\x12\x9c\x71\xdc\x88\x63\xcf\x10\xe0\x76\x05\x7d\xf7\xdf\xbb\xff\xb0\x2d\xe1\x64\x41\xe6\x5e\xf7\x6a\xec\x8b\x30\xaa\x87\xbc\x6e\x48\xf5\x4d\xe5\x77\x79\xdd\x75\x50\xa1\x0b\x53\x6f\x68\x07\x10\xd7\xc8\x4c\x46\x1e\xeb\x6d\xff\x6c\x33\x16\x27\x76\xa6\xb9\x0a\xc9\x19\x87\x8b\x7b\x2f\xe7" \
+"\x5e\xed\x2c\xcd\xe0\x65\x9f\xdb\x34\x4b\xdb\x75\x7f\x5e\x25\x62\xa6\x1a\xda\xb6\x87\x4f\x61\x80\x2f\x50\x0b\x81\xe8\xc7\x49\xee\x14\x60\x49\x08\x0d\xf6\x96\x71\x10\x5d\x1d\x3f\x63\xb8\x7f\x30\xb8\x0f\xc9\x29\x08\x49\x14\xfe\xba\xbe\x55\x39\x6a\xdb\x32\xde\xf5\x13\x01\xe0\x7e\xcc\xb0\xd4\x2e\xca\xfd\xf6\x8b\x8b\x9d\xa5\xe0\x64\x10\x30\x32\x92\x92\xbd\xd7\x69\xfa\xdb\x07\x69\x1b\xc3\x3a\xb9\xdf\x18\x84\xc7\x79\xb7\x1c\x0f\xf2\xaa\xc4\x78\x74\x10\xc5\xd1\xe2\x39\xdd\x06\x14\x9a\x62\x32\x64\xd1\x44\x23\x39\x4d\xa8\x8b\x65\xb3\x49\xb6\x9e\xed\x36\x8c\x27\xb5\x6c\x9a\x8b\x70\xb9\x70\x58\x33\x7d\x5d\x1a\xca\x4d\x9d\x30\x58\x42\x4a\x40\x37\x99\x4e\x7b\x9c\xab\x3b\x2b\x0b\x8e\xf9\x89\x19\x88\xdb\xf4\xd2\x75\x2c\x9c\x88\x50\xe0\xec\xd5\xbe\x47\xfc\x87\x25\x5f\x07\x05\x1c\xac\xf1\x1b\xd9\x8c\x13\x2a\x8a\x6b\x47\x0c\x4b\xb3\x70\x1d\x81\xbf\x09\x8d\xb3\xff\x01\xa2\x07\x76\x69\x2f\x31\x69\x2c\x14\x56\xb9\x02\x7d\x92\xf1\x9f\x69\xb0\xdd\x73\xd5\x0e\x42\xca\x5f\xfa\xd5\x2b\xf8\xb0\x04\x2e\x27\x54\x13\xba\x50\xf2\x35\xb6\x9c" \
+"\x03\x2b\x08\x4f\x58\x9c\x7f\x0b\xf7\xb3\xc7\xd0\xfb\x25\xd9\x16\xcf\xbf\x80\x35\xa0\x10\x9f\xc5\x13\xd6\xf0\x1d\xc1\xd4\x49\xbf\xf4\x1b\xbd\xe5\x63\xfb\xfe\x32\x2a\xbf\xc7\x0f\x95\x8d\x51\x3c\x19\x87\x78\xe7\x28\x54\x7f\x3b\x96\x7f\x2d\x9a\x87\x7c\x6d\xfc\xba\xcc\x62\x94\xa2\x85\x0a\xea\xe8\x98\x58\xd8\x36\xf2\xce\x4e\xa0\x0c\x4e\x0a\xe4\x02\xee\x32\x09\xe6\x74\xcc\xce\xa0\x09\xc7\x0c\x0c\xe0\x0d\x99\x51\x33\xfd\x8c\xc5\x94\x2f\xc0\x0e\xbb\xff\xd8\x6e\x8d\xc6\x23\xd4\xf4\x43\x4d\x30\x57\x2e\x2e\x71\xcd\xdc\x51\x69\x6d\x09\xf8\xc2\x64\x47\xbb\xa0\x09\xdd\xb2\xb0\x77\xc4\x24\x88\x0c\x44\x22\x71\xdd\xfa\xfa\x04\xfb\x14\x89\x46\xf1\xac\xb2\xb9\xd6\x17\x37\xc4\x1f\xa0\x4c\xd6\xe6\x8b\xc0\x90\x78\xbc\xe1\xd7\x84\x21\x69\xb2\x53\x45\x5c\xc0\x70\x7b\xdd\x22\x07\x49\x91\xe9\x38\x0c\x43\x6a\x98\x4d\x8f\x4d\xd9\x66\x06\xc7\x35\x0e\xa2\x0c\x86\x5b\x3b\xa9\xb5\x12\x2f\x0b\xce\x45\x41\x42\x1b\xa0\x62\x95\x16\x18\x35\xc4\x77\xe7\x54\xd3\xf6\xe7\xda\x63\x78\xc5\x97\x1e\x99\xc0\x78\xfd\x46\xea\xfd\xef\x22\x4a\x06\xe9\x95\x9b" \
+"\xd6\x0c\x7f\x39\x5c\xe1\xc9\xe9\x74\x30\xe2\x5e\x9f\xd4\x4e\xde\x63\x74\x1d\xbb\x03\x3b\xa7\x44\x6c\xa2\x92\x7d\x06\xb2\xe6\x3c\x9e\x3c\x55\x5e\x71\x5d\x02\x4b\xc3\xea\x42\xc8\x94\x80\x32\x38\x3a\xcd\x4f\xe2\x0b\xbd\xbd\x58\x20\x43\x53\x54\xbc\x1f\xb4\x4f\xfc\x09\xb1\xc7\x35\xa3\x42\x36\x6e\xf5\xae\x71\xe1\xcc\xb4\x95\x06\x8d\x12\xfa\x96\xa8\xe5\x63\x6b\x6e\x6c\x3f\x46\x2b\x92\xd8\x40\x2a\x03\xe3\x92\xdf\xe9\x06\x8c\x6c\xee\x15\xf5\x46\x0e\x98\x5c\x6d\x8a\x68\xc8\xc3\xf8\x7d\xe6\x08\x04\x8a\x7d\xe4\xdd\xe1\x62\x92\xe6\x5b\xe1\xf7\xcf\x1d\x70\xb9\xca\x9d\xda\x12\xc1\x2d\x36\x2f\xd7\xa2\x1d\x5c\x5f\x0d\x58\x28\x81\x01\x96\x6a\xcb\x75\x4c\xb0\x9d\xa9\x3d\x2d\xc9\x43\x23\xee\x95\x15\xae\x32\xa2\x96\x78\x16\x90\xc3\xbb\xd6\xef\xb2\xe7\xa5\xc8\xa7\xaa\x6b\x62\xf2\xcd\x48\x71\xa6\xa3\x06\xc5\x39\xd2\x6a\xe7\xc0\x11\x70\x4d\x53\xab\xd8\x7f\x49\x8f\xb6\xe0\x6f\x68\x89\x7b\x77\x34\x99\x2a\xcd\xa1\x91\xae\xa7\x26\x75\x82\x52\x1f\xe4\x66\xea\x1e\xc7\xc2\xcf\x49\x6d\x40\xe7\x37\xdd\x41\xe1\xcb\x1c\x71\x02\x78\xc9\x16\x7d" \
+"\xd3\x4c\x52\x3a\x4b\xb5\x21\x79\xbd\x8a\x46\x7a\x9b\xfc\x85\x33\x23\xf1\xc1\x79\x94\x30\x2c\x9b\x7b\xf0\x09\xa9\x91\x0f\x4f\xd5\xb4\xa0\x1e\xc6\xe1\xd1\xba\x7c\xba\x35\xf0\xf6\x0d\xbc\x34\xd3\xdd\xb5\xd4\x8c\x8f\xbb\xb2\x0b\xb5\xca\x4e\x32\x37\x77\xe4\x71\x78\xe7\xb8\xa5\x7a\x79\x5e\xb5\xde\xf8\xe1\xcc\xf5\xae\xcd\x3f\xdb\xc0\xf6\x52\x65\x6d\x73\xa0\x99\x52\x83\x26\xdb\xe5\x3a\x72\xcd\x8a\x8d\x89\xed\x59\x5e\xf5\x54\xb1\xa6\x00\x26\x10\xad\x38\xf8\x43\x37\x72\xfc\x59\xfb\x92\x5d\x18\x68\x71\xb5\x25\xa4\x25\x9e\x60\x89\xbf\xd6\x15\x33\xd7\x3a\x7b\x6f\xa1\x74\x9d\x70\xd3\xbc\xd2\x34\x69\xdb\x5b\xd5\xbf\x85\xab\x2f\x66\xae\x33\xaa\xb4\x0a\x1e\xb5\x11\x2b\x4c\x0d\xf2\x88\x29\x2d\x9b\x18\x2d\x4f\x92\xda\x06\x6b\x2f\x8e\x20\x8d\x5e\xa5\x0c\x95\x54\xaa\x7a\xca\x43\x82\x7e\x27\x81\xf4\xbb\x13\xe3\x16\x6c\xea\x5e\x62\x3d\x9b\xfb\xe4\xd4\x2b\x25\xfe\x51\xde\x29\x43\x05\xe1\x7c\x35\xcb\x6f\x18\xd4\x40\x11\x55\xc2\xff\x38\xbe\x73\xc0\xcb\x37\xaa\x98\xbb\xa6\x74\x55\x42\xa7\xd5\xf7\x81\x0f\x76\x56\x68\xe0\xc3\x6c\x6d\x06" \
+"\xc8\xbf\x22\x8a\x75\x4a\xb6\xd1\x12\xcc\xb6\x8b\xb8\x1b\x6b\xaf\x0e\x91\x9b\xc5\xfb\x35\x8d\xd1\x62\x82\xe6\x02\x5b\x5b\x5a\xfe\x83\xfc\x5b\x55\x27\xd4\x49\x5a\x39\xb8\x90\x1a\xa3\x06\x20\xf3\xea\xa2\xea\xec\xa7\xea\x49\x71\x32\x4d\xa5\x81\x7a\xd3\x06\x22\xc2\xb8\x1d\x87\xe2\x5b\x72\x0e\x60\xf6\xf3\x16\xc8\xf2\xdc\xae\xe3\xf4\xa8\xc7\xc5\x37\x72\x3e\xd7\xac\x3a\x3c\x52\x29\xcd\x08\x6b\xfd\x3e\x6c\x7a\xf9\x4e\x89\x27\xa7\x0e\x23\x99\x88\x3e\xc1\xd3\x78\x31\xed\xe8\x16\xd7\xbe\x84\xa1\xfa\xf9\xae\xfd\x5a\x5d\xd2\x23\xde\x23\x3e\x3c\xcc\x6b\x3f\xc6\x79\x93\x44\xd5\x4b\x31\x32\x03\x05\x4a\x1e\x5c\x77\x0b\xdf\x85\xde\x1d\xe9\xf8\x5d\x57\xc2\x8b\x54\x34\xd6\x2c\x92\x13\xf1\x52\xcc\xa3\x9a\xfd\x82\x9f\x58\x94\x74\xcf\x1d\x72\x75\x96\x9a\x18\x51\x4e\x5f\x01\xd0\x54\xc5\xac\x8d\x03\x6b\x12\xc0\x78\xc4\x5b\x1e\x52\x5a\xe8\xa3\x0a\x8e\x60\xc6\x3e\x7e\xd4\x99\x64\xcf\x92\x7a\xe9\x5c\xbc\x93\x1b\x09\x66\xcc\x77\xd1\xf2\x47\xde\x6c\x72\xf9\xad\x3b\x0e\x43\x1a\x68\xf0\x88\xc7\x46\x83\x27\x86\x12\x01\x98\x4f\xe0\x82\x68\xc3" \
+"\xb3\xd7\x5a\xba\xf4\xee\x0c\x5a\xb5\x91\x4b\xee\x54\x9e\x6f\x3f\xbb\x79\x98\x84\xa7\x96\x8a\x3e\xcb\x28\x46\x8a\x9a\xd2\x25\x32\xe2\x45\xfd\x8f\x1a\x00\xf3\x83\x05\x8b\x4f\x30\x30\x73\x7a\x3d\x47\x29\x01\xe8\xef\x04\x60\x4a\xd1\xfd\x80\xe0\xde\x9e\x61\x96\x10\x1e\x84\xf0\xc7\xc5\x76\x0d\x47\x38\xa0\xbe\x23\xd7\x6e\xa5\xfe\x1a\x45\x2b\xc3\xa3\x1e\xf5\x8a\x30\x50\x8c\xf5\x59\x53\xa5\x41\x27\x14\x53\x73\x77\x6f\x5a\xca\x65\xac\x5b\xb2\x23\x11\x78\x2d\x76\x5b\x3c\xbd\xb4\x85\x22\x13\x89\x98\x8f\x10\xba\xd6\x04\x2e\xf2\x17\xb3\xe5\xcc\x37\xda\x16\xbc\x05\xde\x8c\x45\xc3\x2b\x1f\x22\x9f\x83\x35\x1c\x53\xd0\x9e\x70\xa3\x10\x3d\xaf\x03\x45\x71\x86\xae\x15\x7d\xa2\x5b\xb6\xfb\x78\x11\x5e\x64\xfc\xc7\x76\x23\xf8\x40\xce\xb3\x26\x79\xb0\x54\xc5\x09\x02\x2d\x6f\xf4\xa1\xfa\xc7\x82\xd0\xa7\xfa\x00\x9b\x39\x00\x5f\x27\xce\xed\x05\x17\x3a\x8e\x89\x4d\xa4\x98\xdb\x5e\x39\xed\x10\xdb\x77\x39\x3a\x65\xbd\x68\xcd\xe4\x1c\xed\x77\x8f\x63\xf1\x05\xa0\x73\x5b\xd7\xf6\xc6\x99\x3c\xba\x40\xf8\x7e\x43\x38\x9b\xb3\x37\x66\x03\x2f\x44" \
+"\x91\x29\xd1\x2d\x94\x6a\x0b\x47\xbf\xab\xf5\x21\x06\x85\xd8\x01\x6d\x80\x38\x78\xf7\x11\xa9\x96\xad\x3d\x6f\x00\x41\x02\x5f\xe5\x3f\x3b\xb9\x94\xd5\x95\x8c\xbe\x39\x97\xa3\x49\x09\xe7\xfa\x4c\x7e\xd3\x0c\xaf\x0e\x26\x92\x1e\x66\x16\x7c\x3a\x89\xef\xb5\x63\xb0\x02\xb8\x30\xc4\x84\xf8\x8c\x5a\xc2\x5f\x06\x5a\xf2\xab\xfe\xbd\xeb\x08\x44\xf4\x73\x59\xd9\x0a\x3d\xac\xfc\x4b\xba\x75\xd4\xd8\x3e\xfd\x62\x9c\xe9\x60\x8b\x37\x5b\xfb\xa8\xdd\x43\xe7\x12\x8c\xfa\x26\xe8\x8f\x41\xdc\xea\x81\x6a\xb8\x3f\xab\x77\x60\x20\x09\x2d\x97\x4a\x47\x51\xa2\x6d\x3a\xc2\x7d\xbf\xa9\xf4\x09\xbe\x25\x26\x62\x24\xee\xb0\x26\x96\x1e\xe3\x00\xbf\x3c\xbd\x00\x04\xb2\xc4\xee\xb6\xe9\x08\x7e\x0e\xec\x49\x64\x10\x96\x31\x1a\x68\x98\xc5\x84\x35\xe5\x64\xc4\xce\x07\x4a\x5b\x8f\x17\xce\x78\xfc\x34\x49\xa1\x94\x29\xa0\x89\x1d\xcf\xde\x0d\x80\x90\xbf\xa2\x3c\x18\xe2\xbb\xfa\x49\x4c\xf6\xf0\x1f\xfe\x6d\x90\x66\xf8\xcf\xd7\x2c\xb6\x1d\xca\x36\x8d\x6b\x7c\xef\xcd\xf3\x36\x9e\x00\x94\xca\x62\x41\xe9\xc9\x3c\xa9\x22\x40\x51\x3e\xcd\xe1\xe4\xe9\xfa\x17" \
+"\x92\x35\x68\x78\x44\x47\xb3\x1a\x9c\xe6\x19\xe1\xeb\x8a\x14\xc4\xdf\x48\xb0\xed\x43\x6b\xca\xd3\x20\x1f\xb8\x1a\xb2\x40\x86\xe1\x73\x08\xe3\x09\xc8\x21\x1f\x1f\x3a\x52\xfb\xf9\x36\x2e\x3c\x0c\xe9\x42\xde\x90\xf3\x6f\x6e\x19\x75\x4d\x6c\xdf\xd3\xd1\x17\x4e\xa2\x9a\x4d\x54\xfb\xa6\x59\xcf\x2d\x4e\x33\x55\x12\x33\x0e\x38\x09\x83\xba\x6f\xe5\xe6\x0b\xc5\xc4\xc9\xb8\x86\x93\x34\x0e\xb9\x91\x0e\x09\xa4\x9d\x52\x03\xfc\x2a\xf4\x8c\xcf\xbd\x4d\x0d\xe8\xf8\x8b\x0a\x89\x1e\xbd\x5b\x5c\xca\x3f\xf9\x61\xd4\x8b\x27\x9b\xfb\xfd\x0a\xf9\x0d\x73\xee\xcb\x70\x93\xba\xb9\x2e\xef\x33\x8f\x94\xfb\xa3\xd0\xfe\x79\xf0\xf3\x16\xa2\x2f\xc4\x2c\xf9\x00\x3b\x7f\x90\x52\x0b\x45\x7c\x4c\x83\xe7\xec\xa9\x61\xac\xa8\x9d\x18\x11\x3d\x6c\xe5\xb6\x99\x00\xc4\x17\x76\x28\x46\xa7\xb2\x4f\x2f\x71\x4b\x5d\x2e\x87\x94\x79\x39\x14\x96\x1c\x42\xd2\x8d\x8e\x5b\x83\x70\xef\xbc\x23\x05\xb5\x80\x02\x3b\x78\x06\xe4\xce\x82\x84\x68\x1e\xdb\x93\x52\x0c\x30\x09\x62\x33\x22\xc4\x87\xec\x73\xb2\x0a\x19\x08\xcd\x1c\xe7\x8c\xc7\xe0\xe0\xa2\x7b\x58\xc2\xca\xda" \
+"\x74\x31\xe9\x89\x70\x48\xeb\x9d\x7d\x89\x4a\x84\x31\x45\xe8\xf9\xf7\xf1\x2f\x08\x70\x05\x48\x8a\x95\x79\x02\x94\xcc\x5d\xe7\x2c\x81\x8c\x95\xce\x68\x25\xd0\xb5\x56\x43\x7a\xa7\x72\xa6\xc8\x86\xb4\xb3\x8b\x78\x10\x6a\xab\x5d\x3a\xb3\xaf\xb3\xf4\x94\x24\x53\xab\x9d\xb6\x92\x6f\x16\x00\x90\x6e\x69\x2f\x5a\xec\xb1\x2f\x2c\x23\xfa\xed\x6f\x8d\x59\x06\xba\x16\xc4\x20\xa6\x17\x8f\x11\x60\x7f\x3a\x8b\x89\x1d\xfa\xa4\x34\x8d\x01\x0d\x75\x52\x5d\xf1\xfe\x78\x8b\xa5\x01\x72\x69\x07\x87\xb4\x39\xfc\xca\xe9\x45\xfd\x26\x0b\x58\xdf\x11\xcb\x40\xa2\xaa\x7f\x3b\xa3\x5a\x08\x3a\x95\x14\xd6\x9f\x1a\xa0\x78\xf4\x7b\x5b\xcb\x1f\x56\xed\x14\xf2\x42\x0e\xb6\xce\x7f\x36\x77\x24\xb6\x29\x81\x80\xc1\x51\x13\xb6\x78\x55\x17\xd2\xdc\xb1\xca\xcc\x66\x8f\x51\xf3\xe9\x0f\x43\xb7\x9d\x60\x7a\x78\x82\x4f\x9a\x76\x24\x4e\x98\x18\x7b\x5a\x56\xa9\xc8\x14\x1d\x39\xd2\x85\x10\x34\x18\xca\x14\xad\x65\xe6\x3d\x2f\x69\x5e\xf4\x2f\xd9\xcf\x57\x57\x5d\xcc\x8a\x6e\x08\x96\xc8\xf8\x81\x8b\x86\xe1\x22\x22\x96\xf7\x46\xc2\x90\xa7\x15\x62\xa1\x07\x26\x4e" \
+"\x03\x24\x2a\x86\xa1\x9d\xcb\x57\x22\xab\x1c\xc7\x40\xba\x82\xdf\x67\x79\x58\x82\x32\xae\x0a\x32\x4f\x0d\x5c\xa2\x63\x01\x55\xa8\x7a\x3d\x84\x50\x55\x70\xee\x06\xb3\xcf\xa2\x35\x10\xc6\xfa\xda\xce\xca\xf2\xf8\x1f\x4a\x56\xc5\x85\xc1\x24\x63\x85\xa0\xdf\x37\x24\x99\x65\xa5\xbc\xb8\xb3\xbd\x24\xc6\xfe\x33\xc7\x0d\x74\x18\x0a\x87\x65\xd0\xa6\x36\x6b\x01\xa6\x61\x26\xc9\x2d\x56\xda\x2c\xa3\x3c\xad\x81\x45\x11\xcc\x37\x55\x8d\x50\x64\x58\x7f\x6c\xcd\x41\x49\x9f\xcc\xd8\xfa\xf0\x11\x79\xc4\xc4\x79\x2e\x40\x19\xd7\x58\x66\xdd\xf4\x23\xf8\x60\x72\x42\x7d\x86\x07\x53\x61\x00\x50\xa6\xe0\xd8\x16\xd5\x12\x2a\xf2\x7e\xb6\x51\xe0\x0a\x25\xc1\x2b\xae\x4a\x9f\x93\x3a\x41\xd9\x93\x6e\xd6\x5f\x7a\xae\x7d\x79\x4a\x42\x90\x4a\x63\x34\x84\x68\x69\x8b\xe1\x80\x3e\x01\xbc\x07\x2b\xb9\xde\x86\x06\xd8\x34\xd3\xd5\x53\x6d\xb0\xa6\x98\xa1\x30\xd3\x7c\xc6\xf1\x34\xed\x8b\x9b\x14\xe9\x8c\x37\x93\x44\x4d\xa6\x6a\x51\xd5\xfa\x4a\x7d\xa5\xd5\x41\x93\x5c\x1f\xd0\xf2\xa9\x5a\x1e\xef\xa5\x8f\xc4\x55\xf7\x79\x93\x26\xb5\xaa\x4b\x1e\xe0\x69\x79" \
+"\x1b\xc5\xf6\xac\x27\x6d\x06\xd1\x2a\xd0\x0d\x94\x99\x61\xf7\x26\xa8\xb9\x4c\x2a\x66\x91\xa6\x1b\xf2\x25\x88\x2d\xf5\x20\xc8\xb1\xe1\xf8\x9a\x75\xac\xb8\x25\x9c\xd0\x64\x97\x40\x10\xc1\xfe\xd5\xcd\x8c\xcf\x99\x40\x9b\x39\x2f\xed\x3b\xe7\x0a\x82\xcc\x48\x1e\x11\x3c\x4c\x73\xa1\xed\x68\x05\x26\xfe\x5a\x98\xd0\x31\xc2\xa0\xf3\x6a\x4e\x29\xfb\x8f\x68\x82\xb4\xf1\x62\xd3\xee\xc2\xe0\x24\xf2\x27\x6d\xb4\x43\x82\xd2\x2c\x08\xa2\x96\x10\x4c\x53\x28\x56\x61\x57\xbb\x2a\x32\x3f\x23\x62\xc0\x17\x8a\xec\x5a\x03\x9d\x13\x05\xfc\xe4\xd3\xef\x01\x55\xbe\x36\x90\xda\xdd\xb8\x13\x59\x4b\x8a\x35\x73\xce\x1f\x64\x63\xbb\x50\xa2\xde\x86\xa7\xee\x75\x54\x24\x3e\xb2\xe0\x93\x77\xa0\x41\xf4\xf5\x9d\xbc\xb8\xde\x2a\x35\xbc\x54\x33\x05\x16\xd6\xe5\x5c\xf9\x11\x4e\x06\x4f\x91\x5c\xc9\x35\x3a\x2d\x57\x5a\x13\xc2\xfd\x12\x44\x57\x3a\x30\xce\x55\xf1\xad\x28\x00\x26\x4b\xd2\xe3\xfe\x96\x75\xa8\x58\x29\xb4\x1f\x4d\xef\x88\x25\x6a\xde\x21\x3f\xef\xd9\xf5\x1d\x0b\xff\x5e\xb5\x84\x5b\x50\x98\x0f\xe0\xfd\xbb\x68\xbf\x5f\xb4\x37\x6c\x18\x41\x20" \
+"\x1b\x93\xc9\x66\x66\x40\xf5\x0e\xc4\x9a\xa9\x85\xbf\x75\x31\x6c\x4b\x85\x48\x5f\x30\x7e\x01\xa6\xbb\x81\xdf\x5e\x60\x27\xe1\xde\xc4\xd2\x81\x23\x18\xba\x91\x06\xad\x52\x43\x82\x61\xa7\x8a\xa7\x39\xb5\xe4\xf9\xf7\x2c\x1d\x09\x8c\xf5\x31\xa4\xd2\x77\x5b\xb0\x0f\x1f\xce\x58\xe5\x9b\x17\x48\x72\xe0\xed\xbe\xc2\x93\x85\xe9\xaa\x16\x40\xf1\xa2\xcc\x34\xd0\x8a\x9f\x1d\x5e\x19\x75\x67\x84\xe8\x41\xc6\x5a\xb7\x71\x06\x4c\x34\x8d\xc7\xa6\xaa\x80\xc7\xfb\x3c\x89\x56\x4e\x34\x10\x48\x40\x70\xae\x43\x36\x49\x3f\x37\xb7\x1e\x0b\x30\x83\x07\x5e\x97\x11\xa6\x73\x3e\x05\xdd\x47\x1e\x89\x23\xb5\xfa\xbb\x44\x1a\xbb\x33\xca\xf9\x4c\xa2\x3f\x0a\x90\x7b\x77\xd9\x9b\x0f\xd6\xd4\x34\x27\xd0\x6d\xd2\xce\xe6\xf2\xba\xfe\xaa\x8a\x34\x28\x82\x07\x66\x43\x1c\x26\x6a\x98\x7a\xac\xb8\xa6\x51\x1e\xec\x95\xd5\xec\xae\x82\x8c\x2c\x8f\xc7\x09\x76\x3a\x0b\x1e\x7e\x8b\x27\x80\x5c\x53\xf2\xcf\xc8\x9d\xf5\x93\x54\xcf\x8c\x78\x3b\x38\xe4\x91\xb1\x82\x30\x8b\x4e\x65\x7c\x2a\xe4\x81\xac\x0e\xf8\x90\x8e\xbd\x26\x9e\x3a\x55\x54\x4b\x88\xb4\xaf\x0d\xb8" \
+"\x00\x1a\x80\xea\x97\xa7\x28\x06\xa3\x08\x17\x39\x45\x2a\x59\xae\x32\x00\xd8\xba\xa6\x07\x8f\x7b\x5f\x17\x1a\x86\x7f\x7d\xc7\x75\x1a\xd7\x81\xd4\x77\x53\x02\x42\x60\xf7\x7e\xf1\x31\xab\xba\xde\x92\xea\x73\xc7\x7b\x70\x4f\x93\x35\xd2\x5f\xc0\xa6\x31\x89\xf5\x50\x78\x0e\xb8\xf2\xed\x83\x1b\x8d\x64\xb2\xb9\x36\xf5\x98\x37\xf3\x58\x2d\x7a\x30\xe5\xd6\x37\x76\x69\xde\x1a\xbd\x44\x2a\x15\x22\x39\xa5\xf6\x6d\x23\x54\x2d\x4c\xc4\x74\x7f\x58\xb4\x0a\xb3\x67\xe2\xd0\x21\x5b\x6f\x0c\xe7\xdd\xa6\x40\xc7\x5d\x57\x3a\xa4\x6c\x17\x7e\xa9\xd8\x77\x44\x68\x18\x33\x9c\x47\xaf\xb5\x5d\xb8\x7c\xab\x22\x48\x73\x5f\x94\x48\xa6\xf1\xb2\xdf\x24\x0a\x0c\xdb\x32\xac\x8b\x98\x1a\xe8\xb9\xf9\x5f\xf9\x08\xf4\x14\x4e\x88\x8d\x91\xa9\xa8\x02\xd0\x09\x1e\x25\x32\x95\x2f\x32\x11\x40\xd6\xa8\x20\x17\xe4\xe8\x1f\x4e\xdb\x4d\x08\x50\xfd\x29\x4f\x08\x7b\x41\xea\x24\x4e\x97\x17\x44\x12\x46\x0a\x09\x09\x21\x8e\x81\x73\x8f\xbf\x7f\xd1\x8d\xca\xbd\x37\x78\x10\x94\xb8\x7a\xb2\x4d\x0a\x95\x12\x1e\x06\x65\x35\x5a\x9b\xef\xfd\x52\x39\x0b\x7d\x54\x07\xaf" \
+"\x74\x3e\xd2\xe8\x70\x82\xfd\x69\x99\xcb\x1f\x78\xfb\xf1\x2d\x29\x7f\x60\x92\x0b\xbb\xb4\x73\x15\x3f\xb6\xd5\xc4\xaf\xff\xa2\x1f\xe9\x41\xc5\x6e\x2a\x88\x36\x76\xea\xb0\x03\xfc\x53\x04\x6b\x85\x13\xe2\x22\xa3\xe8\x1f\x27\xab\xb2\xf2\x24\x45\x40\x21\xa7\x8b\x51\xb8\xa0\xcf\x77\x25\x89\x28\xa5\x32\xa7\xf3\xbc\x52\x8e\x5b\x02\x00\xd1\x10\xa6\x98\x86\x71\xb9\xec\xfd\xa1\x78\x5a\x5e\xbd\x51\xc9\xe0\x3c\x42\x52\x17\x0c\xc7\xc5\x56\xc6\x10\x36\xae\xed\x79\xba\xf4\x8d\x32\x1a\x98\x78\x4e\x34\x47\x73\x28\x5e\x9c\x16\xa2\xf1\xdb\x5a\xd4\xec\x15\x99\xaa\x8e\x14\xc8\xfb\x31\x62\xc0\xad\x0e\xa7\xc7\xa7\xb0\xeb\x6f\x3d\xf3\x1e\xd7\x23\x71\x7f\x7a\xfa\x4f\xa2\x28\x82\x51\x1f\x33\xb1\xf0\x09\x1f\xc0\xd2\x97\xab\x4e\xc9\x32\x66\xe3\x4b\xc4\xef\xe8\xaf\xf0\x77\xcd\xbf\xb4\xd1\x44\x7b\x56\xf4\x72\xf4\xd1\x07\x23\x11\x10\x59\x85\x59\x2a\x09\x12\x7c\x15\xfc\x65\xf4\x58\x4f\xd6\xea\x91\x8c\x34\x76\x2f\x2c\x79\x2b\x0e\x06\x9d\x1a\x10\xac\xfc\x55\x5e\x54\x3b\x86\x13\x77\x0a\x46\x5b\x9d\xf6\x08\x4a\x20\x0f\x17\xe6\x02\xcd\xbc\x67\xed" \
+"\x5c\x13\x58\x15\x93\x87\x75\x7c\x6b\x8c\x27\x98\x33\x38\xf6\x7a\x99\xae\x6a\x91\x8c\x92\x4e\xb4\xf3\xd4\x3e\x2e\x03\x83\x89\x4e\x38\x4f\xa0\xfc\x75\x54\x7e\xc7\xc2\xf0\xe3\x17\xbc\x28\xce\x48\x44\x28\x3a\x5b\xb7\x50\x28\x1f\x41\x09\x46\x17\x22\x40\xc7\xd5\x8a\x50\x8c\x3a\xca\xd7\x73\xdf\x5c\xb5\xda\x74\xfc\xd2\xbe\xd2\x36\xa6\xf1\x42\x84\x3e\x62\x6d\x9e\x33\x34\x59\x45\x18\xab\xb0\xeb\x74\xaf\x12\x6f\x50\xa7\xd1\xaa\x96\xc2\x98\x17\x60\xa2\x29\xf4\xe8\x50\x55\x4c\xe2\x7e\xf0\xc4\xd6\x51\x28\xb7\xe1\x66\x0a\xa6\x39\xe7\xe6\xe8\x95\xa4\x74\x70\x7a\x00\xb6\x35\xc7\xfc\x37\x32\x6f\xf3\xc8\x40\xbf\x1d\xf0\x56\xbb\x7e\x85\x79\xf9\xf9\x25\x3a\xae\xd1\x27\x98\x67\x97\x83\x7f\xcf\x9a\x0e\xbc\xef\x1c\x6b\x21\x0a\x39\x52\x9e\x74\x3f\xe1\x1d\x67\x50\x86\x54\xf5\x25\x0d\x01\x46\x5f\xb4\x52\xbf\x00\x43\xf3\x43\xda\x94\x1e\xf8\xa0\x85\x5c\x53\xbe\xc5\xfb\x96\x75\x1c\xb2\x79\x11\x10\xd1\x04\xbc\x9b\x37\x52\x86\x80\x03\x68\x8e\x84\x90\x20\x65\x00\xdf\xa6\x4f\x31\x6c\x40\xe7\xa2\x06\x1b\x5e\x74\x44\xeb\xa8\x24\x73\x27\xbf\x97" \
+"\x1c\xca\xe4\x23\x5a\x35\xac\xaa\xad\x97\xec\xae\xc5\x13\x55\xd8\xc0\x9e\x80\x23\x06\x58\x15\x19\x9e\x5c\x12\xd5\x16\x88\x77\x95\x7c\xd5\x67\xc5\x06\xce\xae\x24\xc4\xc7\xd0\x44\x39\x54\x1c\xda\xfb\xd6\x4b\x9d\xfe\x2e\x3d\xe4\xbc\x57\x5d\x7d\x9b\x26\xaf\x04\x24\xa0\x1f\xb1\x46\xde\xf5\x55\xf6\x45\x6d\x2d\x4d\x97\xaf\xca\x17\x11\x8b\x42\x4d\xa6\x9b\xfb\x52\x9c\x0b\x4d\x66\xde\x14\xaa\xff\xe8\xa2\x29\x49\x1a\x59\x76\x3a\x7e\xd4\xcf\x6c\x37\x05\x88\x96\xf0\xdf\xb9\x67\xe7\x73\xb6\xbd\x27\xa4\xa2\xb6\x70\x71\x0b\x5d\xfa\x6c\xf7\xe7\x8f\xac\x43\xdf\xdd\xe0\x18\x74\x80\x77\xe8\x8f\x5a\x1b\x95\x31\xe2\xc3\xee\x42\xe9\x0f\x61\x89\xaa\x9b\xec\x7c\xb9\x5f\xc0\x79\x24\x52\x4c\xf9\x1f\x2e\x66\xb9\x0e\xf3\x1e\xf4\xd9\xb8\x9c\x9c\xcf\x23\x26\x59\x6b\xd4\x8b\x4b\xa1\x10\x4e\xe8\x4c\xd1\x07\x5c\x5e\x50\x9f\x3a\xa2\x8a\xd8\xce\xe7\x5d\x55\xc6\x8c\x5a\xc8\xaa\x4f\x76\x1a\x34\xa8\x6f\xa5\xe0\x5b\x2d\x55\x2a\xa2\x8e\x37\x00\x13\xa7\x8e\x56\x4a\xeb\x2b\xe6\x03\xa2\x5d\x21\xef\x2b\xb5\xfd\x9b\x6a\x1c\x30\x96\x2b\xea\x66\xbb\xf7\xbb" \
+"\x28\x2b\x9e\x21\x30\xf2\xd6\x5f\xb6\x7e\x03\x19\xda\x2f\xa3\x8c\xd9\x06\xdd\xc7\x39\x4c\xb6\xf4\x6e\x31\xa8\xf0\x81\x1f\xe2\xb9\x23\x12\xb9\xbd\x02\x11\xbe\x86\x89\x1d\x4c\x76\x30\xd8\x21\xbc\x67\xa0\x42\x8f\x17\xe6\xff\x18\xee\x06\x6f\x12\xd6\xa3\xf4\x1e\x24\x04\xd8\x1f\xa2\x3c\x7f\xeb\xcb\x43\x22\x45\x14\xe3\xdc\x38\x6b\x4e\x51\x0a\xa0\xa9\x13\xff\xd3\x7e\x2e\x4d\x2e\x98\x2e\x72\x87\x8b\x17\x03\xac\x34\x50\x56\x0b\x05\xbe\x33\x56\xbe\x43\x00\x4b\x11\xa0\xe5\x0c\xfe\x98\xdd\x03\xd5\xdc\xd5\xf4\x33\x9d\x49\xfb\xce\xd5\x2b\x71\xf7\xf5\xbd\x34\xe2\xfa\x6d\xd4\x04\xa8\x84\x18\x89\xa0\xaf\xdb\xcc\x9c\x20\xfd\x79\x08\xd1\xc8\x60\x58\x5d\x42\xf3\x54\x4c\x94\x8e\xe5\x56\x1f\x6a\x0a\x17\x88\xc8\x84\x98\x96\x33\x7d\xca\x0d\xca\x3f\x6e\x26\x7d\x0c\x71\x11\xa2\x5c\xd9\x18\x6c\xeb\xd1\x51\x41\xca\xb3\x3c\xb0\x0b\x5b\x3e\x2d\x7e\x60\x09\x42\x99\x86\x0b\x28\xe7\xcd\x42\x05\xf9\x5c\x63\x77\xce\x69\x6c\xcf\x4f\x2c\x3d\x0a\xb3\x12\x07\x21\x0f\x44\xcc\x28\xd6\xab\xdf\xb1\x62\x5e\xb0\xf3\xa5\x98\xe7\x9a\x01\x43\xe2\xec\x6d\x89" \
+"\xca\x48\xea\xf3\x17\x9c\x29\x69\x76\x28\x48\x70\x93\x35\x4c\x7e\x9e\xff\x91\xd5\xd6\x2b\xf1\xc2\x7d\xe3\x68\xf1\xc4\xf4\xed\x8c\xd6\x3e\xd2\xf9\xcf\x8f\x3a\x6a\xb6\x0a\x4b\xf7\x72\x13\x7f\xd2\xd9\x66\xbe\xc8\x95\x24\x3b\x89\xcc\xde\xdf\x7b\x3f\xd7\x54\xf9\x31\x95\x53\x89\xcd\xe0\xc0\x2c\xa6\x65\x6d\xb5\x62\xdb\x11\xa9\xba\x23\x0b\x6c\x83\x4b\xb9\xdc\x3a\xd6\x81\x43\x0f\x6a\xdc\x43\x4c\x07\xf7\x9a\xc9\x92\x19\xe0\x33\xa9\xb4\x3d\x49\xa9\xd8\xa3\x40\xb3\x90\x3d\xb8\xa3\xa3\x08\x71\x28\x2a\x35\x2e\x50\x32\xc7\x9c\x06\x8a\x2c\x56\x82\x0c\xc3\xfb\xbf\x63\x7a\x7f\x74\x9b\xf8\xcd\x56\xac\x31\xc5\x84\x65\x7c\x20\x17\xe1\x4e\xfc\x17\xb6\x1b\x0a\x5d\x87\xdc\x62\xf6\x3e\x9d\x86\x66\x01\x71\xf4\x41\x27\x03\x6a\xa8\x16\x8e\x10\x40\x8c\x0f\x50\x63\x23\x16\xb3\xa5\xa6\x55\x64\xe9\x5a\xe5\x12\x4e\x5c\xcc\xff\xda\xe0\x79\xda\x95\x92\x65\x5a\xed\xd1\x8d\xac\x47\xc1\x5a\xaf\xbd\xa5\xa9\x58\x1b\x0f\xc5\xe1\x84\x20\x7a\xd7\x59\x5c\x82\xaf\xa0\xba\xc9\x14\x3d\x40\xa2\x85\x03\x2b\xf2\x01\xfd\xfc\xb5\x88\xfd\xda\xa3\x82\x6f\x24\x0e" \
+"\x85\x07\xdb\xcc\x91\x22\x20\xaa\xc1\xec\x97\x4a\x4a\x93\x4c\x8a\x6b\x79\x7a\x75\x9e\x1c\xf6\x32\xff\x87\x8a\xa4\x11\x26\xa4\xd2\x4b\xae\x74\xd0\x92\x91\xa3\x36\xa1\x8e\x68\xf2\xfd\x4c\x61\xba\x5c\x83\x45\xbd\xd9\xf1\xe1\x9d\x4e\x25\x4e\x60\xdc\xc2\x03\xf6\xd6\x79\xb2\x5d\x1a\x2e\xa5\x89\x04\xdf\x61\x0e\x5e\x32\x34\xea\x32\x56\x45\x8d\xa5\x79\xca\x98\x25\x55\x16\x87\xd4\xe9\x1e\x6a\xd0\x98\x0a\xc4\x17\x90\x02\xc7\x12\x2b\x2f\xec\x53\x1e\x36\xf9\x07\x91\x74\xef\x24\xbf\x73\xab\x65\x4d\x27\x66\xa7\xf9\x98\xea\xc1\x8d\x18\x8f\xfe\x84\xf1\x31\xdd\xdf\xbd\x67\x0c\xf5\x14\xf0\xd5\x79\x98\x52\x45\xb3\xc0\xba\x06\x42\x38\x16\x16\x90\xf0\x7d\x57\x0d\xf8\x5d\x6c\xe5\xf5\x94\x0e\x3e\x83\x2d\x64\xc9\x3f\x44\x76\xf9\x42\x62\x84\x8d\x4a\x8c\x14\xdc\x51\x86\x8d\xac\xbe\xc7\x95\xcd\x5d\x39\x2d\x71\xf0\x0f\xa1\x04\x7a\xe4\x1c\x96\xdc\xb7\x58\xe2\x33\x75\x06\x6b\x7a\x27\xa5\x19\x0f\xc5\xc7\x95\x9d\x83\xd6\x2c\xfd\xf0\xf7\xf1\x8b\xe5\xe8\xd4\xda\x71\x17\xbc\x84\x93\xfa\xfc\x0e\x91\x07\xf6\x65\x1b\xbe\x9b\x1b\xe0\x14\x25\x3f\x02" \
+"\x36\x26\x05\x22\xba\x02\x6b\xdd\xa1\x42\xf8\xd9\x3f\x4f\xca\x53\x35\xfd\x7f\x57\xfc\x6c\x85\xaf\x0e\x52\x8c\x84\x96\x5e\xea\x78\x78\xd6\x20\xea\x35\x51\x3c\x6b\xff\xa6\xbc\x59\x99\x09\xad\xea\x55\xf4\x0b\x4c\xd9\xbe\x16\x10\x93\x50\x17\x71\x7e\xf1\x54\x39\x86\x54\x98\x2a\x61\x9e\xb0\xf7\x8a\xf9\x36\x6e\x67\x70\xaa\x34\xee\x6d\x1b\x83\x89\x54\x25\x35\xa2\x2d\x0c\x87\xe4\xb3\xc5\x2c\xa3\x8f\x21\x00\x7d\xc6\x2d\x7a\x5d\xfc\x94\xd0\xa3\xf2\x63\x7e\xc3\x7a\xf7\x67\x8d\x16\xd0\x94\x71\xec\xd2\xdf\x39\xf1\x80\x09\x28\x69\xcf\x6d\x45\xe5\xcc\xee\x62\x7c\x64\xe3\x11\xb9\xe2\x12\x77\xc0\x32\x18\x62\xc4\xbb\xe6\xe0\x3c\xbf\x9d\x29\xb3\x5f\x4c\x99\x06\xd9\xe8\x5d\x02\x6e\x29\x94\x8c\xcb\x09\x9c\xe1\xae\x1a\x10\x01\xb6\x14\xf2\xdd\x72\x48\x15\x8d\xe2\xd5\xc8\x11\xc6\x10\x64\xb0\xd8\x49\xf0\x4c\x06\xed\x4e\xc8\x77\x4d\x27\xf0\x9e\x1f\x94\x83\xbb\x3f\xe8\xd2\x40\xb3\xfa\xe8\x35\x4e\x28\x12\x59\x21\x27\x8c\xd1\x38\x70\xf9\x92\xde\x07\x7f\xa1\x41\x92\x21\x92\x7f\x38\x72\x20\x54\x50\x18\x70\xe5\xe6\xd5\x5e\x5b\x94\xf4\x6d\x0d" \
+"\x9d\x6f\x33\xc9\xad\xad\x42\x88\x96\x06\x6f\x6f\x9a\x0b\x11\x74\x0d\x1b\xd1\xf2\x3b\x63\x15\xa9\xde\x44\x48\xde\xa4\x3d\xd9\xc9\x35\xcd\x21\x0f\x8d\x0a\x50\x0a\xd7\x52\x7d\x2b\xa5\x36\xb8\x1a\x97\x47\xcb\xce\x32\x3a\x39\xa1\x34\xa8\x16\xf2\xb3\x7d\x6f\x2b\x5b\x57\x03\x07\x7e\xb1\x36\xa3\x94\x5d\xff\x37\x7c\x2b\x8d\x48\xa6\x22\x93\xa3\x87\x00\x32\x7e\x98\xa5\x01\xf4\x76\x5f\x60\x50\x04\xbb\xce\x6e\xef\xd6\xb7\xd1\x7d\xfc\x28\xb6\x7e\x86\x02\x2d\xb6\x8a\xb3\x02\x66\x8a\x65\x13\x5c\x86\x27\x45\x78\x39\xbe\x39\x82\xf5\x49\xdd\x17\xae\xb7\x5d\x1c\x9d\x2a\xe7\xd9\xce\x8b\x73\x26\xbc\x81\x7c\x0c\x6e\x59\x6c\x84\x33\x8e\xf4\x87\xf5\xfb\x44\x80\x38\xda\x1a\xf8\x81\x22\x9d\xa7\x54\x8a\xf5\x5f\x40\xac\x4a\x09\xfc\x11\xbc\x49\x6e\xe5\x4e\xe6\x99\xe7\x2c\xbf\x2e\x7e\x27\xf1\x7b\xdf\x2e\x2f\x27\x45\x8b\x76\x07\xb8\xb7\xa6\xab\x3d\x70\xc8\x6f\xc4\x3d\x7b\xd9\xbc\xc1\x66\xd4\x69\x5c\x00\x9f\x1b\xb0\x4a\x32\xfa\x6b\x44\x1a\xc4\xcb\xef\x00\x2a\xb8\x23\x8f\x0e\x6a\xac\x4c\x93\x70\x64\x19\xd7\x29\xaa\x7e\x5f\x6c\xda\x52\x24\x09" \
+"\x74\xb1\xb6\x7b\xfe\xbe\x38\x35\x7d\xef\x42\xf3\x91\x0a\x3d\x66\x39\x6d\xc5\x50\x9f\x61\xfd\x78\x30\xf9\x61\xb1\x02\xb9\x99\x0e\xc9\x79\xa5\x6b\x85\x76\xf8\xdc\x44\xce\x60\x89\x9a\x79\xd7\xd9\xbd\x4a\x4c\xcc\xde\x23\xde\xe3\x53\x34\x4d\xb4\x7a\x7b\xb8\xf9\xd4\xf0\x16\xc8\x88\xc2\xce\x6f\x78\xa2\xfd\xba\x9b\xd5\x95\x27\x61\xfc\x84\x5f\x46\xf1\x2f\x36\x13\x8f\xbc\x95\x94\xee\xa1\xc2\x79\x11\x5d\x6f\x85\xf2\xc9\xd4\xb7\x8a\x98\xb2\x25\xe6\x8c\x6b\x89\x7a\xa3\x4b\x05\x87\xe1\xba\x20\x32\x83\x68\xc5\x10\x57\xa3\xb4\xfb\xaa\x1b\xb5\xf1\x55\xb3\x7e\x74\xdb\xce\x4f\xf2\x05\x65\x29\xa5\x50\xdf\x42\x20\x44\x47\x58\x35\x75\xd8\xd1\xac\x70\xd4\x81\x98\x31\x6d\x3d\xec\x4f\xde\x9c\x0b\xef\x1f\xca\x3d\x7b\xcd\x3a\x80\x07\x5f\x1b\x8b\x87\x5b\x77\xc0\xbb\x0d\x63\xa5\x67\xfe\x8c\xc3\xea\x64\x4f\xe7\x9a\xb0\xe9\x52\xd6\xbf\x3c\xc1\x35\x8f\xd5\xfa\x83\x5b\x28\x91\xe1\xd4\x6a\x4d\xc9\x6a\xb9\x78\x8d\xe1\xc3\x05\x6e\x84\xeb\xbd\x5f\x2a\x5a\x37\xc2\x74\xde\x93\x5b\xac\xaf\xdc\xe8\x17\x5f\xc9\x04\x96\x66\xfa\x17\xc4\x56\x78\x1c\x2a" \
+"\xbc\x30\x2e\x90\x42\x55\x7c\x2a\xbb\x89\xd4\xc4\xe6\xf5\x6f\x93\xcc\xa1\x3f\x23\x64\x16\x90\xe8\xd0\x58\x65\x97\x0a\x1f\xd2\x5a\x01\x04\xca\x87\x78\x66\x51\x79\xbd\xc9\x2c\xde\xd1\x30\xbc\x98\x6c\xfa\x41\xad\x0d\xf0\x01\x7b\x6d\x24\xa3\x89\xac\x45\xfa\xa2\x0a\x4b\x59\x39\x66\x93\x4d\x12\x5d\x04\x68\xd8\xe1\xcf\xe5\x18\x39\xbb\xe4\x63\xda\xcc\x3a\x73\x2c\x78\xd1\x63\xc8\xd6\x9c\xdd\x8b\x11\x83\x9f\xa4\xe9\xa0\x06\x02\x1b\x0f\x3c\xcc\xdb\x12\xbe\xa4\xd2\xcb\xbc\x22\x74\x24\x86\x65\xc1\x4b\x58\xbd\xde\xf5\xae\xcb\x00\xc7\xa1\x39\x16\x04\xdb\x4d\x18\x24\x8d\x46\xd7\xdb\x1f\x5c\x69\x0a\x46\x66\xa9\xf4\xd7\xe6\xa9\x58\xf0\x9d\xbe\x05\x82\xba\xe8\x4c\x75\x2d\xe6\xb5\x73\x43\x23\xac\x0f\xa5\x1e\x7d\xb4\x39\xf5\x19\x61\xf4\xaa\xb6\xb4\x6b\x18\xe7\xc3\x8c\x61\x32\xdc\xdc\xc1\xc4\x90\x31\x20\x5a\x3e\xce\x6d\x55\x23\x87\xdc\xf9\xff\x4e\x67\xcf\x62\x9c\xe4\xd5\xfe\x16\xe7\xf7\xbf\x98\xfa\x25\x08\xac\xcc\x88\xb5\x1e\x4b\x09\xae\xe2\xaf\xac\xee\xed\x6b\x1b\xe6\x2e\xc5\xf0\x8c\xa2\xe1\x41\xa5\xf9\xd1\x31\x98\x13\x66\x60\x60" \
+"\xce\x91\x28\x27\x9b\x44\x08\xe4\xb0\x00\x70\x06\x1b\xa4\x0c\xdc\xb9\x8c\x5f\x47\xca\x7d\xea\x0f\xf6\x34\xce\x05\x67\xc6\x06\x41\x0c\xd1\x57\xdf\x79\xef\x7c\x78\x80\x9c\xc2\xfa\xef\x85\xf7\xe3\x4c\x6b\x49\x26\xe4\xf1\x21\x13\x3d\x8a\x46\x25\x2d\x3a\xef\x0d\xb0\x1b\x11\x29\xca\xe9\x3e\xdf\xaf\x9d\x24\xea\xc0\x17\xb4\x40\x3d\xe7\x67\xad\x53\xa9\xf1\x33\xc9\x51\x43\xd9\x4f\xf6\xcb\xf7\xe9\x75\xfd\x99\xfc\x32\x36\xfb\x78\xfe\xd7\x69\xa8\x2f\x80\x3d\x8b\xf3\x5b\x8e\xa6\xb3\x1a\x61\x41\xab\xa7\xf4\x72\xbc\xc0\x65\x17\x37\x73\xcd\xde\xd1\x3b\x6f\x53\x93\xbc\x1a\xa3\x7b\xf4\xfc\x62\x94\x68\x6e\x51\x1b\xa7\x43\xc8\x55\xfb\x50\xa3\x75\x24\x4e\x89\x5f\x22\x3b\xa3\xac\xa4\x59\xf7\x48\x40\xb5\x29\x56\xff\xb8\x9e\xee\xb9\xe2\x46\x70\x7b\xb3\x03\x49\x01\x6f\x6e\xa1\x31\x1d\x70\x7c\xf4\x6e\xee\xf7\x0e\x0e\x4c\xc7\x9f\xc5\xb3\xfa\xf4\xf7\x55\xac\x38\x62\x46\xe8\x63\xcc\xe2\x4b\x79\x49\xef\xcd\xbf\xd2\x4a\x5c\x04\x00\xea\xc1\xc4\xc2\xad\x44\x2c\x0f\x28\x9b\xa6\xcd\xc5\x34\xcf\xa9\x7b\x8f\x05\xb3\xea\x1f\xca\x56\x38\x18\xe9\x3e" \
+"\x79\xd3\x85\x13\xd1\x58\x20\x9e\x55\x46\x55\xf8\xf9\x30\xe1\x2f\x56\x0d\x80\x06\x8c\x24\x1f\x80\x3a\xd7\xb0\x51\x81\x7d\xac\xe0\xd1\xcf\xf6\xad\xcf\xc1\x16\x61\x3c\xad\xb7\x4d\xfd\x9b\x12\xb2\x24\x71\xba\xd8\x46\x35\x2f\xb0\xb0\x6e\x58\x86\x51\xda\xa4\xe6\x2d\xf1\x1b\x50\x64\x61\x07\xf1\x76\x48\xc8\xa5\xbb\x9b\xbe\x5e\x28\x1e\xcd\x99\x47\x68\x8d\x0f\xdc\x0f\x99\xb1\xc8\x9b\xef\x78\x65\x88\x11\x99\xff\x58\xa3\xb9\xdd\xc7\xd8\x62\x45\x5f\x3b\xaf\xa4\xe9\xfd\x85\xe1\x02\x9c\x79\x5d\xe9\x0b\xac\xa4\xfc\x42\x19\x3b\x8d\xc3\x72\x83\xe0\x32\x8b\xe3\x87\xf0\x04\xab\x0e\xce\x8c\xcf\x37\xd3\x9f\x87\x08\xc1\xef\xe9\xcf\x35\xf4\xee\x54\x13\x49\x01\x5e\x68\x2a\x94\x1a\x03\x65\xc6\x99\xef\xef\x22\xe6\xfd\x6c\x06\x36\x3b\x36\xfc\x31\x56\x43\x5a\xae\xc4\x8c\xef\xb5\x40\x55\x0b\x2c\x09\xe5\xf9\x88\x48\x7d\xc7\xbf\xf2\x9c\x91\x51\x46\xc1\x2c\xb5\x85\x24\xd3\xf2\x1e\x90\xf4\x07\x59\x61\x62\xf4\x3d\xb8\x03\xae\x65\xad\xdd\xef\x91\xa6\xe1\xb6\x52\xca\x4c\x4c\x96\xc6\x5d\x78\x64\xfe\x2f\x15\xa8\x3d\x26\xa5\x30\x1f\x4c\x3b\x25\x59" \
+"\x6a\x57\xcb\xb3\xf8\x9c\xa2\x40\x32\x4c\x05\x7b\x71\x09\xd7\xe2\x17\xcd\x2c\xf5\x75\xb3\xfb\xa0\x6a\xcd\x82\xbb\xfd\x97\xe0\x18\x20\x6b\xd2\xdd\x3e\x09\x85\xc0\x77\x8f\xe8\x45\xcc\x62\x05\x56\x79\x11\xf5\xb4\xf9\xe9\x30\xb9\x38\x3e\x14\xd7\x8c\x06\xdc\x8b\x2c\x2e\xb4\xec\xd7\xfa\x51\xc3\xfe\x65\x87\x28\x87\xeb\x8d\x16\xb7\x01\x1f\x03\x59\xfc\x57\xcf\x3a\x18\xa1\xe1\x1c\xd9\xae\x7a\x47\x2e\x64\x19\x55\xbd\xb1\x2d\xb9\x35\xd2\x6d\xde\xf0\xf4\x52\x4b\xbc\x11\xbf\x2d\xb8\xdc\x84\x69\x4b\x97\x0c\x05\xec\x94\x96\x0a\x16\xc7\x1a\x8f\x8e\x9f\x89\x57\x8e\x46\xf1\x43\x05\x0f\xeb\x57\x14\xe0\xcf\xd2\x26\x3c\xf5\x22\xee\x6c\xc1\xcc\xc2\xb3\x07\x83\x9e\x3f\xf5\xff\x5f\x22\xf7\x3f\x64\x27\x55\x33\xb6\xdc\x45\x7d\x58\xdf\x27\xa0\xb0\x73\x64\xe8\x96\x14\x28\xcd\x84\xe7\xc9\x61\x28\x42\xcf\x35\xc3\x27\x3b\x04\xbf\x8c\xd2\x42\x2e\x68\xc4\x40\x23\x16\x97\xd2\x58\xdc\x6c\x60\x5f\xaf\x61\x46\x19\x5a\x6f\x70\x7b\x6a\xcc\x16\x3b\x6a\xf8\xe8\xb2\x95\x20\x24\x10\xfe\xbf\xca\x5f\xb1\xb1\x74\x5f\xd5\xcd\xaa\xfe\x60\xb8\xe9\xa6\x0a\x9c" \
+"\x5f\xfe\x69\xcd\x37\x9e\x3d\x81\xd7\x62\xe6\x6b\x03\x3f\x9d\x9b\xcf\xf7\x9d\x4f\xfe\x8a\xbd\x5e\xf8\xf4\x98\xa7\x6f\x10\xca\xea\x51\x26\xfd\x01\xb4\xd2\x18\x59\xb8\xfc\x55\x06\x23\xdf\x09\x22\x53\xfe\xe0\x45\x8a\xc7\x25\x5a\x18\x15\x88\x0f\x33\x32\x1e\x36\xd8\xe3\x9c\x75\xf2\x64\x34\xa3\x59\x21\xa4\x62\x11\x59\xb0\x15\x9b\x0f\x92\xd8\x56\x75\xa8\x03\x79\x4b\xfc\x74\x50\xc7\xa2\xd7\x4a\x04\x1f\x76\xba\xce\xf9\x74\xdd\x63\x41\x36\x21\x0d\x4e\xd2\x23\xd2\x35\x7a\xbe\xc6\xdd\xb7\x86\xcc\x4f\x08\x19\xd2\xbc\xfd\x55\xc9\x2e\xfa\x03\xe8\xd0\x25\x0c\xdf\x48\x97\x94\xee\xa8\xcc\xfc\x1f\x01\x1c\x76\xf8\xaa\x95\x49\x3b\x20\xca\x65\x97\x0f\x08\xbd\xa3\xd9\x8d\x96\x74\x41\x81\xa6\x93\x36\x01\x42\xd6\xe4\x4d\x4c\x0c\x69\x01\x52\x81\x7b\x1c\x32\x6a\xef\x73\xbd\x51\xa5\x59\x40\xa2\x48\xad\xa2\x0c\x8f\xa1\x2a\xc3\x34\x31\x4f\x82\xe7\xcf\x7d\x71\x15\x2b\xb8\x78\x61\x4f\xa2\x24\x7d\xcc\xfd\x17\xeb\x16\x57\xfa\x81\x2e\x33\x8c\xb8\x7a\x05\xb0\x5b\x4d\x79\x63\x5e\xf6\xd9\xf7\xb5\x64\xbe\x51\x2b\x47\x61\xd8\x52\x90\x32\xd7\x48\x58" \
+"\x88\xca\xa7\x92\x14\x6c\x6f\x30\x08\x80\x4d\x3b\xb3\xe3\x74\x66\x6a\xaa\x7b\xb7\x96\x0f\x14\xe2\xb1\xf4\xc7\xd2\xe1\x60\x0b\xe8\xe6\x6b\xe6\x5c\x58\x07\xc8\xfa\xa2\x8f\xf5\xd7\xc2\xae\x7e\x1f\x91\xd3\x9e\xd2\x7d\xde\x56\x50\x69\xcf\x60\xc5\xf0\x10\x79\xe5\x10\x2b\x20\x12\x61\x74\xf9\x69\x35\x0a\x6d\xa3\xe2\x5a\x2b\xcd\x1b\xbe\x14\x4b\x05\x77\x61\x51\x64\xec\x1e\x0d\x2a\x1e\x94\xed\xe1\x95\x23\x11\x11\x05\x8e\x23\xfa\xd7\xc5\x9b\x11\x6f\x91\x81\x35\x39\x00\xc8\xf9\x59\xb0\xbd\x01\x74\x24\x0f\x8c\xb6\x5f\xd6\x8f\x74\xeb\x52\xa5\x35\xc0\xb5\xb7\x83\x6a\x05\x8e\x23\x1f\xeb\xb1\x5a\xcb\x79\xa7\xd8\xa5\x21\x2f\xe1\x15\xe3\xde\xeb\x52\x4a\xc3\xc5\xd7\x4f\xcd\x6c\x91\xb9\x58\xe0\xcf\xb9\x2b\x94\xc7\x37\xce\x37\x35\x24\x53\xe4\x0f\x9b\xf0\x34\x8b\x24\xa9\xca\x8c\x0b\x94\xc9\x64\x74\x05\x04\x5d\xd1\xff\x0e\x68\x1b\x1e\x8a\xe0\xb6\x88\x44\x1b\x12\x7f\x3d\xe7\x0d\x4f\xd3\x81\xaa\x53\x85\x79\x2a\xc9\x5b\xa1\x9d\x5d\x5c\xe4\xe6\x55\x2a\x48\xfc\x8e\x55\x31\x31\x5a\xf8\x69\x40\x65\x11\xb7\x68\x47\x42\x58\xe7\xf3\xb9\x7f\x6d" \
+"\x60\x10\x90\x43\x89\x8e\x33\x0f\xb0\xe5\xc3\xf4\x79\xe1\xeb\x01\x2f\x1a\xbb\xc7\x1d\x54\x2a\xd1\xc0\x17\x18\x42\x8b\x69\x3b\x2a\x62\x2a\x3b\x79\x2a\x13\xfc\xd8\x53\xaa\x0f\x99\xe3\xd1\xf2\xc0\x54\x7f\xe1\x07\x6a\x34\x7a\x0b\xc5\x0d\x72\xc4\xc2\x43\xd9\x6a\xc9\x09\x21\xbc\x2c\x50\x9c\x8a\x0d\xea\xbd\x1d\xf0\xbe\xf7\xe7\xc2\x71\x91\xb6\x3f\xb8\x51\xcb\x58\xad\x2b\x94\x7e\x3f\x37\x1e\xb3\xa9\x08\x04\xd3\x07\x49\x30\x98\xa9\x41\x8b\xef\x27\x2a\x42\x43\xd1\x04\x14\x66\xc1\x3a\x16\x9b\xe5\xf8\xe9\x63\xee\x3e\xad\x47\x38\x2b\x99\x81\xfd\xa1\x45\x57\x5e\x32\x35\x01\x12\xa7\xb3\xfd\xe8\x05\xf4\xb4\x49\xca\xce\xc7\xb1\x9c\xa8\x90\x9c\x70\xf7\xbb\x5d\x79\xe9\x95\x10\x50\x91\x43\xaf\x39\xfc\xb9\xda\x38\x0d\x00\xa4\xa0\x54\x13\x44\xa8\x0e\x59\x4d\xe1\x02\x0e\x53\x7c\x38\x37\xa2\xe5\x27\xc4\xf9\x1b\xf0\x5a\x85\xf1\xed\x4f\xa9\xe9\xad\x8f\xff\x24\xf9\xa6\x74\x74\xb1\xd8\x95\xe0\x1a\x40\x2c\xb1\x19\x05\xfd\x0d\x32\x41\xed\x0f\x8a\x2b\x5f\x6c\x14\x81\xb8\x8a\x79\x6e\xf0\x5b\x0c\x66\xbb\xb7\xe8\xc4\xfd\x8c\x5a\xae\xab\x09\x96" \
+"\x9f\x58\x61\x38\xe3\x9e\x5c\xe3\xd1\xe3\x89\xf8\xf8\xb6\xa7\xe5\x6e\xbc\x55\x1e\x4a\x07\x48\x63\x6a\xb2\xb5\x5a\xf8\x65\x3b\xb8\x40\x1a\xbc\x01\x4c\x91\xbf\x76\x4e\xa1\x5a\x9d\x6c\x79\xeb\x9a\x5a\x70\xec\xcc\xe2\x43\xc1\xcc\x88\x54\xe0\x2f\xa5\x00\x2c\x2e\xe2\x90\x71\x92\x85\x49\x49\x65\x3d\x31\xb7\x2d\x88\xd1\x0a\xb9\xcf\x18\xf1\xfd\x86\x71\xf8\xe9\x71\x4b\xa1\xb1\x02\x42\xd8\x3e\xb0\x3b\x04\xa3\x5a\xaf\x60\xee\xf3\xc3\x3e\x20\x3d\xe1\x4b\xb2\x7e\x60\x6d\x7a\xe7\xef\xb4\xc4\xcb\x14\xc1\x00\xcb\x31\x92\x22\x7f\xfa\xc0\xcc\x59\xff\x56\x09\x9b\x78\xa1\xed\x40\x94\x32\x36\x78\x5f\xbe\x79\x5d\x41\x7d\xbf\xca\xbe\x10\x70\xbf\x4d\x1c\x7d\x5a\x54\x80\x07\xda\xfb\xb1\x47\x90\xa2\x3c\x2b\xd9\xff\x31\x35\x65\x83\x2a\xc0\x40\x7b\xbc\x21\xd9\x93\xf8\x3f\x4b\x3d\x45\x95\xf8\x5a\x70\x94\x84\x0f\x72\x72\x42\xeb\xc6\xde\xa6\x6c\x8c\xac\xf8\x0e\xfc\x3f\x9e\x99\x91\x3d\x73\xa0\xc2\x1e\xca\x22\x12\x9e\x8b\x84\xaf\x49\x4d\x24\x0a\x55\x9c\xb4\x2c\x5c\xf5\x43\x7c\x15\x37\x03\xb5\xd0\x10\x4e\x90\x2d\x96\x99\xab\x63\xcb\x78\x66\x90" \
+"\xcd\x95\x10\xa8\xf5\x3c\x43\xab\x69\xa3\x4a\x65\xc5\xf3\x4d\xce\xbb\x4f\x7d\x36\xe8\x32\x63\x3c\xd1\x15\xe0\xcb\xf0\x36\x05\x40\xbe\x71\x34\x2b\x72\x99\x39\x18\xf6\xf9\x43\x05\x74\x6c\xa7\x18\x98\x9d\x91\x91\xb8\x87\x09\x15\x13\x28\xd0\x57\xfe\x30\xf9\xff\xa2\x27\x4b\x77\x14\xbc\xf5\xa6\x17\x86\x45\x40\x07\xf2\xb8\x59\x11\xa6\x24\x9e\x4c\x69\xeb\xd4\x4b\x0e\xb3\xa8\x33\xcc\x2a\x32\xbb\x05\x76\x4c\xad\x3a\x9b\xac\xc3\xa8\x2c\x1c\x81\x09\xbc\x08\x72\x4f\x39\xe9\x96\xaf\x24\xd5\x3b\xb0\xcf\x19\x0a\x94\x50\x03\x74\x0e\x78\xa1\xe9\xfa\x24\xd4\x74\x1a\xcb\x25\x81\x2a\x18\x41\xbe\x9d\x41\xc1\x84\xc3\xb5\x1b\x7d\xa1\xed\x11\x35\xcb\x20\x1d\x86\x78\xda\x78\x54\x8b\x27\x79\xf4\xbe\xa7\xb3\xa5\x71\xa9\xdb\x1f\x89\x56\x0f\x2b\xed\x63\x47\x2b\x97\xa7\xdd\xb6\x70\x9d\x6f\x28\x5b\x85\x11\x57\xde\x53\xdd\x27\xbc\x95\x33\x2d\x87\x68\x1b\x94\xf6\xf8\x1c\xa0\xdb\x7d\xc6\x29\x97\xce\x1a\xa7\xa7\x5e\x29\x69\xfb\x04\x23\xfb\xa6\x01\x6f\x9c\xd1\x7e\x27\x5d\x69\xea\xc5\x40\xb9\xb1\x30\xb6\x99\x63\x22\x1b\x6d\x7e\xc0\xb7\x14\x75\x83" \
+"\xd1\x5d\x25\x47\x60\x57\x04\xb7\x34\x10\x04\x7d\x0c\x35\x09\x4c\x68\x97\xaa\x09\xba\x4a\x98\x8c\xad\xe7\x34\x71\x0b\x73\x06\x4b\x3e\xd0\xc0\x66\x47\x70\xcc\x4a\xce\x14\x52\x05\x99\x10\xc2\xba\xb3\xbe\xaa\xdb\xfb\x6d\x18\x58\xdf\x89\xb9\xbe\xd9\xa8\x50\x65\xd2\x69\xdf\x73\x7c\x47\x5b\xc0\x30\x2a\xce\xdc\x0e\x30\x03\xe8\x63\x33\xf7\x27\x92\x97\x94\xe6\x5c\x71\x7b\xb8\x7c\xa9\x37\x05\xf9\xe2\x9c\x56\x51\xa7\x90\xa4\xa9\x49\xf1\x3d\x38\x14\xf7\x74\xac\x93\xaa\x03\x06\x50\xbd\x03\xdc\x0b\x3e\x38\x81\xb3\x91\xcd\x5b\x2e\x41\x1d\x72\xb8\xd0\x76\xef\x67\x21\xe0\xb1\x6d\x96\x13\x13\x64\x88\xa6\x61\x65\xa8\x09\x07\x1d\x8f\xa9\x5d\xba\x4c\x17\x03\xe3\x5d\xf0\xeb\x5e\xc3\x02\x2e\xbc\x4b\x25\xfc\x3c\x3e\xba\xfa\x8f\x85\x60\x7f\xd0\x7f\x37\xb0\xf7\xe8\x63\xc4\x63\xc5\x6b\xa2\xea\x2f\x6d\x1b\x79\x42\x49\xa0\x01\x34\x1d\x48\x59\xfc\xe7\x41\xec\xfa\xc6\xba\x81\x15\x66\x62\x39\x14\xb8\xdd\xae\x30\x25\x0b\xb9\x7b\xbb\x66\x4e\x5c\x03\x45\xa1\xde\x21\x96\xfa\x75\x55\x76\x6f\x04\x91\xf2\x3e\xff\x1b\x30\x48\x57\xfd\x20\x9d\x82\x44" \
+"\x3f\xe0\xdf\xe3\x1d\xd9\xb1\xad\x3d\xce\x22\x0e\xcd\x46\xa1\xe0\x1c\x83\xc5\xcb\x69\x21\xb2\x83\x90\xba\x93\x77\xa7\xac\x07\x74\x34\xd6\x34\xbf\x10\x14\x8a\xf1\x96\x3c\x11\x1e\x5a\x16\x90\xbb\xe3\xa3\x86\xb0\x42\x79\x0e\x01\xe8\x63\x5d\x39\x19\x71\xb1\xf3\x7e\x2e\x31\x00\x43\xcf\xc6\xff\x26\xa4\x34\xdd\x34\xdc\x5a\xc4\xbf\x49\x21\x88\x63\x4a\xc3\x1f\xe7\xc2\xc7\xb6\x8c\x52\x9d\xbc\x08\x0c\x51\x54\x6b\x02\x02\x23\x59\xa8\x3a\x82\x10\x3c\x58\xa3\xd4\x57\x84\xc2\xc2\x3f\xbb\x62\xf3\x73\x40\xf5\xaf\x09\xda\x00\x20\xd2\xc5\x28\xa6\x2c\x0f\xea\xee\x21\x99\xe0\xfa\x78\x33\x00\xe3\x78\xdb\x2c\x1e\x56\x40\x68\xea\xab\x89\x4e\x7d\xcc\xfd\x3c\x86\xd3\xda\x2f\x0f\x91\x32\xe7\x6c\x8f\x7e\x63\x50\x6d\xf2\xd3\x92\x8e\x53\x16\xea\x96\x30\x7b\xe3\x34\xd0\xd5\x89\x53\xd9\x52\x2b\x9b\xd4\xe6\xa2\x8b\x6b\xf3\xdc\x2d\xfd\xdc\xfa\x61\x67\xef\x36\x0e\x16\x83\x4a\xab\x63\xdb\x62\x28\xd8\xb0\x9e\x52\xfa\x6a\xfe\x02\x63\x31\x38\xa8\x77\xb8\x8c\xb6\x74\xba\x1d\x67\xdf\x14\x09\x5f\x06\x24\x1c\x86\x5a\x08\x39\x41\x9e\x21\xee\x9b\x3d\xd2" \
+"\xec\x7e\x6d\x90\xfc\xde\x2c\x68\x6a\xd4\x8c\xc3\x1f\xde\x8d\x83\x37\x01\xa0\xec\x34\x9b\xaa\xad\x9a\x55\xee\x06\x9a\x5d\xf4\xac\x14\xcf\x03\xf9\x8f\x34\x16\x4d\x64\x0e\xe3\xfe\x23\x42\x1b\x25\xde\x62\x07\x16\x91\xca\xd6\x74\xd6\x21\xde\x8a\x20\x9a\x33\x56\x68\x77\x1c\x6b\x44\x0d\xd9\x9b\xc4\xdf\xcd\xb4\x5e\x16\x95\x9c\xa7\xca\x2d\x7d\x25\x69\xcf\x91\x1a\xa2\x9b\xa7\x07\x9b\x33\xc9\x03\x48\xb6\x9a\xd1\x0e\xc5\xd7\x8c\x72\xba\x79\xac\x5e\x4d\x10\x8e\x00\x67\xb8\x17\x1d\x37\x65\xd3\x3c\xe5\x36\x4e\x79\xf6\x4f\xd4\x60\xef\x34\xb6\x84\x2a\xd6\xd0\x1c\x30\xfc\x4f\x71\x91\x5a\x6e\x2e\x91\xbe\x50\x3f\xa6\xd2\x4d\x22\x6f\x7d\x33\x66\x0a\x03\xc2\xd1\x09\xa0\x0f\x9b\x24\xeb\x8e\xfc\x7d\xae\x2c\xba\x4e\xab\x36\x3e\x0e\xe3\xbf\xc0\xea\x2b\x54\x63\x60\xc9\x01\x0c\x65\x62\xed\x0c\xf9\xba\x94\xdd\x11\xd1\x0b\xb5\x94\xa6\xb1\x2c\xa2\x10\x55\x23\xd6\x55\x72\x64\xf9\x4c\x52\x4a\x46\x1e\x92\x63\xe6\x0f\x9d\x75\x9a\xdb\x83\xa3\xc1\xaf\xd8\x1e\x93\xb0\xe0\x74\x52\x90\xe0\x83\xf9\x32\xf7\xc4\xed\x41\xb2\x66\x69\xfc\x14\x1f\xa6\x11" \
+"\xd9\xcf\x8c\xd8\xfe\x7b\x3b\x4d\x11\x6f\x62\xa8\xd2\xed\x4c\x6e\x6b\x10\x64\x28\x2e\xd0\x51\xc9\xa0\x34\x89\x19\xb4\x88\x25\xd6\xad\xac\x5f\x71\xd2\xc3\x5f\xde\xac\x76\x77\xbd\x62\xfd\x7b\x6b\x12\x62\x6f\xc9\xe0\xc5\x6d\x88\x96\x95\x05\x57\x7c\xbc\x25\xc9\x49\xc6\x1a\x06\x3e\x86\xbc\x88\xce\x7e\x65\x2e\xea\x11\xca\x2f\x87\xdf\x39\x3b\x35\x72\x26\x59\x1f\x01\x4c\x4c\xee\x8f\x0b\xbe\x1e\x4c\xe6\x2e\xa2\x33\x00\xba\xcf\x7e\x6b\xdb\x9c\x12\x68\xf7\x9e\xf4\x91\x14\x54\x1f\x44\x8d\x37\xbe\xdd\x69\x66\x38\x51\x9a\x7d\x47\x7b\x7e\xec\xb3\x51\xe7\xdc\xa7\x77\xce\x73\x6a\x3b\xa6\xa6\x03\x89\x2b\x38\x20\x05\x2d\xd7\x91\xa2\x2f\x94\xea\x72\x12\x03\xa6\xf8\xd1\x75\xc0\x67\x23\x53\x4f\x13\xd4\xe6\x0c\x80\xd6\x8e\x94\xad\xea\xd4\x3e\x4e\x90\x08\x8d\x3f\xfc\xff\xbc\x1b\xbf\x84\x35\xd7\xdc\x13\xbf\x4b\xfd\x91\xe6\x7a\x9c\x73\xfa\x49\xab\xd2\x16\xe9\xf4\x5b\x3a\x2f\x4b\x44\x74\xb6\x62\xb6\x4b\x42\x24\x9f\x40\xcd\xb0\x66\x32\xed\x26\x6b\x94\x3a\x3d\x40\x01\xf9\x44\x4b\xeb\x68\x19\xe4\x93\xe9\x2e\x19\xbe\x76\xc4\x22\x27\x01\x3c" \
+"\xc9\x43\x4d\x40\x09\x2b\x00\x96\x29\x49\x39\xfe\xd3\x60\x5d\x81\xe7\x3f\x0c\xb1\x6a\xee\x46\x49\x57\xfb\x07\xfe\x33\xd4\x22\x22\x89\x7f\xd1\xcf\x46\x3c\x44\x47\x4a\xd0\x77\xd3\x99\x64\xad\x15\xb2\x5f\x71\x06\x67\xf4\xcc\xc8\x8d\x3a\x9c\x0d\x15\x6d\xa9\xd7\xce\xb8\x0a\xf8\xd6\xdb\x02\x16\x6c\x25\xf7\x9d\x66\xa7\xfd\x8e\x8b\xb1\x3e\xf3\x3b\x93\x45\xe7\x96\x7b\xb1\xe7\xe0\x21\x1d\x4b\xb8\x73\x8f\xda\x04\x0a\x7d\x23\x32\xc9\x8f\x2c\xaf\x6c\xce\xf7\x98\x51\xf9\x87\xdd\x17\x84\x50\x68\x18\x06\x0a\xd0\x9b\x61\x2d\x09\x34\x1d\xe8\x98\xb0\x4b\xf2\xf1\x6f\x80\x7f\x90\x60\x9f\xab\x49\xfa\x34\xa3\x2b\x9e\xe8\x59\xe3\x41\xdb\x97\x99\xe3\x3d\x2e\xe8\xb1\xaa\xcb\xed\x09\xfd\xe1\xde\xe0\xc8\x56\x92\xb4\x68\x08\x0f\xbd\xb8\x5e\xb1\x24\x39\xaa\xce\x3e\x2f\x98\x43\x4d\x6a\x0a\x1a\xb4\x2c\x7c\xaf\x05\x51\x60\xd7\x8f\x8e\x98\x3d\x02\x51\xd8\x42\x8e\xd8\x47\x08\xaf\xf5\x33\x90\xba\xa6\x1c\xe6\x40\x9f\x96\x5a\xf9\x41\x97\x0a\x88\x5b\x26\x92\x01\xf3\x17\x8d\xe0\x7d\x6c\x04\xa6\xba\xf1\x37\x0a\xca\xfb\xe6\x60\xfc\xf8\xc5\x30\x1d\xef" \
+"\x81\xcc\xb8\x0f\x0a\x59\x82\xaf\x90\x3b\x9b\x21\xab\x79\x20\x13\xfc\x6d\xdc\xbf\x73\xed\x25\xf3\xe9\x79\x7a\x5a\xfa\x42\x8e\x2c\x23\xcb\xda\x91\xf3\x8c\x1c\xa1\xd5\x99\xe7\x4c\x8a\x4c\xfb\x97\x07\x0b\x40\xc1\x49\xe6\xbf\xc4\x99\x53\x05\x5e\x6b\x68\x01\x41\xcb\x95\x99\xd1\x4c\x52\x3c\x00\x15\x99\x3f\xac\x77\x6a\xdf\x33\xd4\xf4\x90\x19\x19\x7e\xd8\x09\x5d\x2a\x2e\xbc\x86\x9a\xc3\x54\x2e\x7e\x80\x88\x6f\x15\x5a\x67\xdb\xc6\x27\xa1\x35\xff\x97\xd5\x69\x87\x73\xe2\x5e\x1c\x30\xfc\x50\x21\x3c\xd5\xce\xf7\xbf\xaf\xc3\xe3\x76\x36\xb9\xcd\xc3\xf8\x0b\xee\xca\x0d\xec\x26\xb6\x01\x01\x33\x6f\xbe\xea\xf9\x57\xbd\xea\x23\x94\xe2\x48\x83\x4d\xf9\xd6\x30\x24\x74\x3a\xe4\x4d\xa8\xde\xbe\x73\xc1\x9d\xae\xd5\x69\x78\x17\x62\x86\x16\xcd\x96\xc0\xca\x80\x41\x80\x55\xfe\x63\x87\xe3\xaa\x50\x60\xea\xe1\xad\xac\x9c\xb3\xea\x51\xb9\x22\xe3\x9b\x29\xf2\xf4\x8a\x94\x3a\xff\xe8\x3f\x92\xb8\xe9\x9d\x69\xce\xb5\x35\x2a\xa5\x3b\x4d\x47\xce\xdb\xa9\xa8\xf6\x3d\x72\xab\x93\x16\x65\xda\x5c\x5d\x3a\x67\x50\xf0\x98\x50\x89\xb3\xb5\xaf\xcb\xf5" \
+"\x6f\xe7\x04\x29\x9e\x5e\xe0\xbd\xac\x7a\x61\x5c\x5d\x7e\x2f\xe5\xef\x34\xe1\x66\x26\x19\x3d\xc4\x79\xe3\x5e\x1b\x94\x85\x3d\x62\xf7\x07\x52\xbb\x9f\x6a\x4a\x33\xf5\xab\x2a\x45\xbc\xe3\x22\xb2\x88\xd2\x89\x3e\x56\x65\x08\xcc\x6a\x06\xea\x69\x85\x33\x45\x32\xa4\x54\xb6\x49\x5e\x6b\x0a\x86\x13\xa5\x6f\xbf\x91\xee\x00\x08\xbc\x39\x7b\xb9\x84\x09\xa9\x2b\xd7\x5c\x4a\x6c\xb0\xdb\x58\x1a\xe3\xff\xac\xc6\xaf\x28\x6a\x78\xe3\x94\x18\x97\xc3\x79\xb6\x46\xb1\xfb\x69\x1b\xa8\x10\x8e\xcf\xb0\x4a\x2f\xd9\xa1\x8b\x1c\x3c\xe4\xc4\xf6\xe9\xf9\xb8\xd4\x24\xc4\x60\x7d\x4f\xc5\x25\x11\x85\xfb\x59\xe2\xbb\xe8\x26\xee\x9e\xb7\x5c\x60\x23\x03\x1c\xf7\x44\x6f\x67\xae\x6e\x51\xa4\x92\xa5\xc3\xdb\x72\x1b\xcf\x53\xff\xfd\x7e\x58\xf2\xc6\x6f\x66\xda\xf9\x72\x09\x99\xdd\xdf\xb0\xbc\x58\x11\xd0\x2e\xb2\xee\x24\xfd\x6d\xe0\xde\x4f\x9a\x7d\x12\xc8\x65\x74\x39\x01\x81\x61\xc9\x97\x6f\xb7\xde\x8c\x87\x72\x9c\x5f\x54\xb2\xf1\x9f\xb1\x70\x3e\x19\x7d\x73\xe8\x66\xfb\x3e\xcb\x0e\x05\x96\x5c\x63\xf1\xdb\x35\xfa\x45\x30\x41\x8d\xf3\x82\x7c\xe1\x1e" \
+"\xb0\x3b\x11\xaf\x91\xfe\x31\xf1\xeb\x89\xe2\x88\x2a\x00\xfb\xa0\xcd\x9c\xc0\x0a\x09\x55\x37\x0e\x3b\x26\xac\xc0\x18\xdd\x42\x36\xed\xee\x93\x5a\xe4\xbd\x16\x09\xdc\xa4\x64\xda\x4c\xb0\x80\xb8\x88\x98\xfc\x43\xa2\xe3\x77\x85\x05\x0f\x6c\x82\xa5\xd3\x18\x13\x22\x4a\xea\xd1\xce\xcb\x05\xe8\x05\x85\x5c\xfb\x6f\xf2\x51\x39\x64\x0c\x74\x8b\xbd\x71\xa7\x8d\xb5\xae\x2f\x0a\x69\xed\x0a\xaa\xc3\x8c\xf5\xb8\xce\x2c\x07\xaf\xb6\x94\x9f\xd1\xef\x8d\xc0\xc2\x07\xbd\xe1\x5d\x25\xa1\x5a\x51\xa7\x61\x20\xa1\x0c\x93\x6e\x51\x80\x0e\x4e\x92\xfc\x13\xfc\xdd\x39\xc4\xe9\x62\xc0\xa6\x31\xc7\x96\x60\x1e\xf7\xa9\xb7\xfc\xd2\xc9\xe2\x17\x72\xc1\xe5\x7b\xfb\x5d\xbb\xbf\x2c\xc3\xd6\xde\xf3\x09\xb4\xd7\x22\x59\x43\xdc\xa2\xc3\xc8\x43\x7e\xf7\x3b\x8e\x23\x52\xee\x80\x19\x33\x87\x98\xee\x64\x34\x3b\x76\x98\x93\x6f\x85\x8a\x29\xc4\xd2\x18\xf1\x0a\x23\x49\xa3\x5e\x61\xb5\x20\x90\x18\xac\xbf\xcd\x0c\x19\xe6\x6c\x82\x8a\xf8\xa4\x62\x8d\x5c\x63\x38\xb4\xc0\x37\x3f\x46\xad\xa4\x39\x1a\x5f\x87\xf3\xff\x9f\xd3\xa3\x2f\x80\x47\x9b\x62\xbb\x51\x9f" \
+"\xbf\x01\x37\xe1\xf1\x10\xae\xf0\xa8\x7a\x25\x28\x61\xcf\x9d\x9d\xb0\x07\xfc\x51\x85\xd6\x80\x53\xf9\x21\x48\x8f\x04\x57\x08\xc5\xe7\x15\xde\x4a\x8a\x84\x95\x6c\x66\x18\xdd\x9a\x53\xbb\x50\x1f\x07\x3f\x74\xb4\xa9\x54\xca\x12\xbc\x0e\x76\x62\xa6\x4b\xf4\x0a\x01\xdb\x4f\x69\xa3\x00\xf9\xfd\x60\x56\xc9\x27\x61\x53\x53\xae\x30\xf9\x49\x27\xbf\xd0\xa8\x22\x43\x97\xfe\x10\x12\x87\x5c\x9d\xe0\xe1\x29\xfe\x2d\xcb\x29\xc5\xd8\x8d\x0f\xd2\x21\xdb\x43\xbd\xdc\x45\x32\x13\x4f\x2b\x4b\x7a\x01\x5d\x2c\x41\xc5\x0f\x1d\xea\x27\xaf\xe9\x88\x05\x41\x7b\x74\x6d\x88\x3f\x5c\x3b\x1f\x9e\x01\x28\xdb\x9e\x5e\x27\xec\xcf\xc6\x7c\xf7\xd1\x96\xa8\x92\x1b\xa4\x50\x6d\xfb\xdc\x65\x96\x1d\x8e\x2c\xc7\x47\xe8\x1b\x24\x76\x45\xe6\x54\x1a\xac\xfc\xe3\x2e\x13\x23\xa8\xef\x05\x0f\xdc\x80\x5f\xd4\x6a\xcd\xf2\x38\x80\x09\x14\x1c\x18\x21\x0b\xb1\xf4\x6e\xed\x83\xe9\xb7\xdf\x79\x73\x5a\xe1\xdf\xa0\x53\x42\x88\x46\x3a\x99\x0d\x68\x88\xcf\x27\xea\x81\x8c\xf7\xdb\xb0\x48\x78\xd3\xb9\x85\x76\x83\xd4\x3b\xba\xb2\xc7\xe4\x36\xe7\x61\xbb\xe0\x61\xed\xce" \
+"\xd7\x09\x16\x0c\x0c\x93\x15\x26\xa5\x4e\x95\xf5\x91\x76\x67\xf5\x81\x78\x05\x8e\x31\x00\xd3\xe0\xef\x4d\x72\x30\xac\x9e\xab\x13\xe0\xc9\x52\xda\x4e\xa8\x5b\x86\x0f\x28\xbb\x72\x2a\x1a\x08\x8e\xd3\x3d\xe9\x08\x9b\xb1\x93\x95\xe8\xa0\x01\xb1\x87\xf5\x90\x45\x16\x9d\x9c\xc8\x6d\x85\xc9\x9d\xd4\xfe\x86\xd5\xbf\xff\x65\xff\x14\xeb\x69\x3e\xdd\xd2\x9f\x40\xf6\x88\xb5\x3c\x29\x95\x81\xe0\x2e\x4f\xad\x88\x69\x7d\xc0\xf4\x10\xec\xac\xc2\xf7\x88\xa0\xbf\xdb\x18\x65\x97\xcc\xbd\xfe\x45\xa0\x4f\x54\x95\x2b\x6c\x5a\x41\x10\x4b\x31\xb6\x1d\xd3\xbc\x87\x91\x83\x6c\x8f\x61\x5f\x26\x26\xf4\x75\x5c\x9d\x5b\x26\x76\x76\x86\x6c\x7b\x53\xd7\xef\xe4\xba\x2d\x70\xca\xa6\x7f\xc7\x50\xb7\xfb\x70\x71\xed\x31\x94\x5c\x1f\x36\xf2\xd0\x0c\x2f\x65\x4a\x4f\x13\x4e\x7a\x3c\x7d\x55\x85\x03\x34\x7b\xec\x3c\x3e\xb2\x65\x6f\x5b\x59\xe4\x3f\x3e\x74\x35\x94\x47\x2e\x99\x85\xf4\x3b\x57\x75\xab\x43\xb6\x77\x03\xcc\xd7\xcd\x80\xf8\x0b\x3b\x22\x0f\x73\xf9\xb1\xf0\xc6\x3a\x34\x17\x65\x84\x76\x27\xb5\xc7\x31\x27\x62\xc4\x17\xb3\xc7\x3e\x41\xa5\xf6\xda" \
+"\xa1\x96\xa3\xfd\x5e\x7c\xd7\x0a\xf5\x47\x87\xa8\x3b\xfb\xe5\x9d\x27\x4b\xb3\xd3\x53\x21\xac\x51\x02\x1e\xde\xae\x42\x50\x0b\xc4\xbb\x7b\xff\x7f\xbb\xd0\xec\x6a\x58\x36\x5d\xfd\x25\x21\x9b\x52\x1a\x9c\x39\x57\x94\x82\x2c\x54\xcf\xab\xc8\x83\x52\x1c\x3d\x7a\x9b\x72\xa0\xfd\x1d\xb1\x32\xa8\x64\x49\x12\x84\x5c\x88\x43\x18\x9c\x95\xa4\x78\x6d\x82\xaa\x9c\xa4\xf8\x68\x53\x98\xe7\xd3\x64\x4e\x3b\xaa\x93\x65\x56\xfe\x7f\x8f\x7c\xb2\xe8\x23\x23\xf3\x03\xdc\xc6\xb6\x92\x47\xfa\x32\x3d\x98\xfd\x65\xdb\xdb\x9f\x3a\x22\xef\x6f\x90\x1d\x08\x63\x18\xd4\x7b\xb0\xab\x00\x84\xfd\x23\x8c\xa6\x9d\x44\xd7\xd9\x69\x4e\xe0\x12\x76\xd8\x4f\xe3\x65\x3b\x99\x1b\xd9\xf3\xfa\xc1\xd5\x64\xb8\x45\x4e\xe5\x07\x90\x6b\x05\xd6\xdf\x8b\x7b\x2c\x8c\xa5\x83\xd7\x41\x4d\xb5\x8f\x65\xda\xc6\x57\x2f\xbf\x0a\x66\xe7\x00\xef\x17\x80\x53\x0b\xda\x3e\x68\xb9\x49\xd3\xd8\x28\x46\xe7\x5c\xbb\xac\xff\x42\x9f\x5d\x9c\x23\xac\x7b\x02\xe6\x7b\xec\xf1\x9a\x58\x88\xb3\x93\xae\x59\x32\x05\x9e\xa9\x80\x7f\xd7\xe7\x52\x53\x9f\x42\xf1\xcd\x67\x8f\x14\xf8\xef\x8f" \
+"\x1f\xd2\xf9\x27\x19\x08\x08\xf2\x6f\x6f\xbc\x23\xbe\xfb\x11\x72\xa4\x31\x18\x71\x9f\x32\x73\x38\xbe\xb4\x5b\x7d\xed\x63\x74\xd3\x24\xd0\x73\x0c\x49\x3d\x63\x6e\x51\x40\x53\xa3\x83\x9a\xd3\x09\xa5\x0b\x1e\xb1\xb1\x2b\xf1\x07\x6c\xcb\xe0\x4b\x19\xf6\xa0\x21\x94\x20\x83\xb7\xbe\x00\xdb\x1c\xd0\xf2\x86\xae\x5b\x5c\x33\x24\xf0\x2b\x8b\x93\x65\xb7\x33\xd8\xf9\x2a\xa6\x34\x85\x73\xf9\x06\xf0\x17\x1b\x17\x4d\xb4\x28\xaf\xf0\xad\x68\x46\x89\x53\x52\xab\x9b\xd7\x88\x83\x04\xac\x13\x64\xff\x92\xa0\xc7\x80\xb1\x82\xa3\x38\x68\x6b\x66\x2c\xb2\xc4\xbb\x00\x26\x35\xe6\xbf\x94\xda\xcf\x69\x42\x6a\x67\x34\xf1\x77\xe9\x3f\x3f\xb6\x2d\x65\x3d\xd2\x59\xaf\x65\x62\x59\xac\xfc\xec\x24\x36\x8f\x83\x37\x23\xbd\x80\x39\x49\x22\xe5\xfa\xce\xfd\x2b\x25\x35\x88\xac\x49\xdd\x1b\xcd\xcf\x15\x78\x5c\x06\xdc\xa6\x42\x5f\x2d\xf1\xd1\x70\x48\x16\x1f\xdd\xe8\xdc\x9d\xf8\x4e\x69\xd6\xe6\x29\xc1\xd3\x2e\xf9\x1a\x0b\xf2\x2a\xe1\x74\xcf\xa6\x8d\x74\xb9\xdf\x56\xda\xbe\xff\xb9\xfa\xc7\xb5\x38\xbc\x84\x25\x1b\x55\xf8\x70\xa1\xb6\xa4\x99\x81\x28\x25" \
+"\x0d\x08\x43\xec\x24\xb6\x97\x82\x60\x83\x41\x1a\x67\xef\x41\xf3\xea\xa2\x07\x5a\xed\x18\x63\x91\x2f\xb5\x63\x41\x26\x24\x70\x9d\xef\xe1\x7f\xa1\xa8\x06\x42\xe7\xfc\x8e\x9a\xe1\x8a\xbd\xf3\x42\x8e\x47\x3d\xef\x37\xe6\x3b\x28\xe0\x86\x68\x64\xbd\xa6\xf9\x42\x5b\x92\x9a\x1c\x43\x4e\x8a\x28\x72\x47\xac\x03\xa8\xe9\x09\x6a\xe4\x8f\x38\xc1\xe3\xf3\x90\x33\xde\x5e\xe0\x2b\x4f\x95\xd4\xf5\x34\x44\xc8\x11\xeb\x2d\xa4\x93\x3e\x76\x34\xd8\xc3\x4e\x0d\x42\xbe\xbc\xf1\x8e\xea\xb6\x55\x30\x94\xd6\x7b\x39\xdf\xbc\xe5\x77\xa9\xb4\xc1\x46\xfa\xd7\xf9\x1d\x58\x7b\x58\xe2\xd2\xab\xaa\x20\x50\x55\x03\x1a\xdb\x6d\x61\x86\x0b\x60\x76\x47\x82\x56\xb6\x4d\x74\x89\xd6\x1c\x8c\xf2\xe3\xb2\xa7\xc8\xd6\xaf\x6b\x60\x84\x21\x28\x40\x5d\xce\x5a\x81\x84\xdd\xaa\xf2\x71\xeb\xfb\xac\xc1\x23\x3a\x55\x46\x09\x4b\x68\x47\xa1\x63\xd6\x06\x21\xcc\xfa\xac\xc7\x21\xb7\xf6\xfa\x6d\xfb\x32\x6a\x72\x10\x86\x96\x13\xdb\x15\x3c\x3f\xfb\xcc\x9d\x2d\x6a\xe9\x85\x9a\x91\x87\xc9\x4d\x3b\xb2\xb0\xd9\x6d\xec\x13\x13\xc8\x05\xa5\xeb\x51\x0e\x2a\x99\x28\xbd\x56" \
+"\x5c\x5a\xef\x4d\x35\x88\x41\x70\x5e\x82\x68\x47\x37\x4f\x16\xfa\x22\xb2\x0e\x5b\x18\x91\xfa\x04\xc5\x60\x48\x76\x8e\x1f\x53\x89\x0e\x39\x73\x24\xca\x90\x0a\x13\x7b\xb0\x17\x5d\x23\x5a\x91\x49\xa3\x7c\x42\x9c\x08\x52\xf3\x16\xcc\x3b\x4d\x31\xde\x01\xf6\x07\x4b\x0f\xea\x6e\x09\xe8\x1d\x9c\xef\xfa\x58\x18\xf4\x7b\x0f\xa9\x42\xb4\xfe\xd2\xe9\x86\x1b\x64\xa2\x67\x9e\xdf\x95\xe2\xa7\x8c\x35\x22\x39\x69\xdd\x70\x74\x48\xcf\xa9\x62\xc8\xbd\x21\x48\xb5\xa2\xa6\x04\x1d\x62\x9d\xb8\xf4\xbc\x7f\xba\x23\xba\xca\x18\x15\xb9\xa0\x3f\x11\x70\x4e\x60\x31\x57\x3c\x9a\xd7\x31\xc4\xb3\x7a\x3c\xfd\x9a\x56\xb1\xe3\x46\x01\x50\xcd\x3a\x42\x67\x92\xaa\x6c\x22\x86\x95\x86\xa0\xe1\x98\x3f\x12\xc7\x65\x9e\xc7\xeb\x7c\x62\x69\x08\x3e\x64\x5c\xf8\x51\x3b\x6c\xbe\x9c\xd8\x6a\x67\x5a\x45\xc7\xa0\x15\x42\xcb\x7d\x9d\xbd\x08\x73\x0f\x9e\x4d\x69\x7c\xab\xb4\xe3\x86\x32\xd0\xf5\xfe\x23\xe7\xd7\xe7\xc1\xda\xd8\x44\xcc\xe5\xe9\x5f\x78\xb1\x69\x6c\x5c\x09\xb5\x77\xc4\x13\x61\x05\x91\xfe\x70\x9c\x46\x09\x44\x27\x54\x21\x50\x02\x15\xe4\xb8\x91\xda" \
+"\x13\xca\xe7\x90\x03\x1d\x16\x0e\x92\xc1\x5a\xd8\x3f\x5f\xc5\x46\xc6\x44\xeb\x84\x10\x1f\x64\xb3\x13\x69\x13\xb2\xd2\xde\x76\x94\x25\xca\x32\xde\x54\xf6\x59\x24\x19\xb7\x50\xaf\x4f\x9a\x26\x77\x59\x7d\x85\x38\x15\x3d\xbb\x7b\x50\xe0\xbb\x0f\x54\x2e\x13\x01\x18\xf6\xfa\x20\xe2\xc1\x31\x76\xfc\x01\x2f\xac\xa1\xaf\x3c\x71\x38\xf8\xc6\x64\x75\x4e\x8a\x9a\x28\xe7\x76\x78\x17\xdf\x08\xef\x91\x33\x2b\x52\x92\x53\x81\x2b\x92\x4b\xab\x14\xba\x9d\xae\x89\xcd\xbb\xc6\x25\x0a\x6c\x41\x9a\xd4\xcf\x3f\xb2\x0b\x33\x05\x3e\xac\x7a\xdb\x93\x10\xdf\xf3\x86\x92\xa1\xad\x76\x71\xb9\xd4\xc7\x1d\x53\x05\xf1\x2a\x36\xa0\x39\x64\x74\x6f\xda\xc1\x27\x42\x43\x8d\xa1\xb3\x8d\x36\x57\x10\x2b\x0f\x5d\x29\xf0\x3e\x42\xe7\x3b\x2a\x30\x2e\xcf\x8d\x1b\xa0\x9c\xf7\x8a\x81\x82\x44\x22\x42\x45\xb1\x2d\x6c\x1a\x24\x32\x6d\x2e\xee\x52\xbb\xdb\xa6\xe1\x73\xcc\x79\xe4\x7a\x5c\x41\x43\x45\xa2\x68\x0a\x75\x11\x21\x71\x6e\x0a\x09\x02\x29\x18\xe3\xad\x31\x0a\x02\x93\x73\xc5\x5d\x85\x8b\x56\x26\x8a\x66\x5c\x11\x5e\x73\x4a\x65\x05\x0c\xde\xba\xe5\x10\x7e" \
+"\x10\xea\x69\xbf\xb8\xb6\x1b\x3b\x98\x76\xb3\x72\x4e\x41\x0f\x15\x2b\xd7\x07\xd7\x6e\xcf\x98\x80\x0e\x6a\xbc\x49\xe6\xb7\x17\x65\x5c\x5f\xfa\x73\xf5\x28\x3a\xa7\x9d\xc9\x01\xe5\xe9\x27\xf3\x67\xfd\x68\x87\xf8\xdb\x4a\x7f\x5b\x87\xe0\xf0\x2a\x06\x46\x46\x30\x17\x34\x4e\x0c\xd4\xcb\x37\x86\x6c\x6b\xb9\xed\x81\x78\xea\x36\xf3\xfc\xe7\x13\xbe\xbe\x2e\x30\x73\xc8\x91\x77\xc3\x8c\x7a\x15\x55\x78\xbd\x21\xd0\x3b\x27\xb5\x39\x37\x80\x90\x95\x78\x41\x4d\x71\x4b\xcb\xc2\xfb\xd9\x4d\x6e\x38\x36\x5d\xf0\x65\xdb\x34\xae\xa3\x99\xc1\x18\x10\x70\x67\xb2\xfc\x39\x02\x07\x37\xb8\x50\xb0\xf8\x80\xec\x49\xfa\x42\xda\x3f\x10\xe6\x95\x20\x95\xed\xc7\xa8\x51\x93\x3f\xd3\xfb\x70\xdf\x3e\x5c\x3c\x72\x9c\xcb\x0c\xe1\xe8\xfa\xa6\x7b\xc2\xe3\x38\x52\x04\x68\xa8\xaa\x26\x5d\x7a\xe8\xcf\xe4\x44\x3a\xf7\xa2\x60\x80\x14\xf9\x72\x5d\x25\xc7\xe5\x98\x86\xa8\x0e\xd4\x99\x89\x1f\xf1\xbd\xa3\xdf\xf7\xc4\x16\x43\x1b\x69\x0a\xeb\x1c\x18\xb1\xf9\xe6\x13\xf7\x91\xe4\x97\xc3\x11\xc9\x5d\xe2\xa7\x4c\xe3\x55\xcf\xc8\x8b\x25\x94\x28\xf3\xd6\x3c\x37\xf1" \
+"\xb7\x7e\xa0\x61\x06\x81\x68\xb6\xcf\xfa\x4d\x7b\xeb\xd3\x9e\xab\x34\xab\xba\x35\x79\x18\x89\x69\xa4\xf7\xac\x84\xc9\x1f\x87\x7b\x00\xa4\xa4\xeb\xa7\x67\x3f\x28\x36\x66\x2e\xc5\xb9\xc2\x0e\xc3\x9f\xb6\x78\x04\x24\x0e\xc2\xdb\x9b\x17\xe9\x94\xa9\x71\x9e\x5c\x67\x44\xf7\x85\xd6\xfc\x09\xdc\x32\xc6\xfb\x4b\x22\x0a\x73\xd1\xac\x93\xa8\xb9\x51\x46\xae\x9b\x50\x6f\xf6\x4e\xc7\x9b\xc0\x02\xf1\xa2\x7b\x7b\x4d\xe4\x65\x16\xf1\x59\xf5\x3f\x03\xeb\x4c\xa2\x14\x0c\x51\xe4\xfe\x32\x92\x4c\x95\x70\xe2\x58\xe7\xa7\xe5\x1b\xfa\x15\x62\x54\xeb\xfb\xd5\xee\xd1\x6f\x22\x90\xb5\xbe\x16\x3c\x70\xf4\x62\xf1\x13\x33\xa3\x04\xc6\x08\x32\xc2\xc8\xf1\x9b\xc0\x61\x5f\xad\x31\x5e\xa9\x70\x15\x57\x17\xe5\xe2\x4b\x3c\x86\x7e\x15\x0a\x56\x54\xee\x71\x13\x4d\xcd\x03\x9e\x69\xf1\x62\x56\xed\xe9\xbe\x61\x88\xca\xea\x93\x79\xfd\x9c\xb0\xee\xde\x47\x23\xb9\x7f\xd4\xd3\x00\x56\x81\x83\x5d\x6f\xa7\x79\x8a\x45\xfb\x04\x5a\xe5\x2b\x30\x90\x8a\x00\x30\xf9\xca\xcb\x2e\x75\xaf\x1b\x60\xe6\x77\x5d\x9c\x81\xba\x7a\x85\x72\xa0\xc4\x32\x51\x61\x3f\x0d\xbc" \
+"\x92\x3f\x04\xdc\xde\xa5\x09\xec\x7c\x75\x91\x5b\xf4\xba\xe9\x23\x4e\xf1\x2d\x26\x7f\xb3\xa5\x14\xfd\x83\xab\x29\xe6\x9e\xa2\x53\x32\x13\x17\x53\x80\x79\x43\xf8\x11\x91\x62\x70\xbe\xfa\xed\xf3\xf8\x40\x92\x29\x10\x2c\x9a\x21\x3c\xa2\xa1\x9c\xe5\xb0\xac\x31\x2a\xf0\xeb\x55\x5a\xa2\x97\xaa\xb7\x1b\x15\xb7\x28\x86\xbb\xc1\x4b\xb7\x4c\x3f\xeb\x1b\x5a\x85\x1a\x8a\x53\x96\x4d\xce\xe9\xa6\xcc\x5a\x7d\xd3\x85\xe5\x0a\xa6\x0c\x92\xb8\x98\x6b\xf2\xf5\x34\x91\x9a\x22\xf9\x0d\x66\xfd\xd1\x14\x03\xe1\x58\x9c\x89\x1e\xb6\xce\xd3\xff\x95\x27\x40\x85\x10\x7d\x05\x73\xdc\x33\x7a\xf2\x79\xde\xd4\xef\xed\xd0\x1f\x48\x62\x24\x83\xb9\x09\x7c\x0e\x37\xec\xc4\x26\x44\x52\x11\xc5\xff\xa8\xc7\x9e\x5e\x34\x3a\x7e\x64\x39\x76\xb8\xd6\x2a\x41\xf9\x9c\x80\x52\x8b\xea\x3f\x77\x37\x59\x6c\xcf\xd1\xe2\x22\xc6\x86\x36\x83\x9a\x57\x60\x1f\x0b\xf1\x01\x0b\x61\x3d\xa7\x14\xdf\xbc\xa3\x1f\xfa\xbd\x0d\x1d\xc4\xd1\xda\x77\x66\x0d\xac\x95\x95\xdb\xfb\x40\xee\xd3\xd4\x88\x52\xed\x96\x8c\xbc\xc9\x7b\xbf\x53\x85\xc1\xfd\x19\x1b\xf6\x48\x3c\xd4\xe3\xf1" \
+"\xd1\xce\x8e\x1d\x0b\x0b\x92\xb6\xcb\xd6\x19\xc0\xec\xc5\xb0\x06\xd8\x69\x91\xbf\x73\xa1\x6b\xaa\xc2\x79\x94\xcd\x41\x74\x9d\x60\xad\xd9\x1e\x60\xae\xef\xb2\x97\x79\x2e\x03\x56\x41\x20\x78\xc3\x42\x56\x90\xce\x5b\x24\x94\x2a\xd8\xd0\xa4\xcb\x95\x45\xe6\x31\x4e\xe0\xb1\x17\xaf\x67\xbf\x6f\xb5\x82\xff\xd7\xbd\xad\x86\xbd\x40\x24\xe2\x86\x59\x74\x8a\x5c\x51\xf6\xca\x0a\xf3\x15\x51\xa5\xd2\xeb\x31\x63\xd9\x13\xb8\x36\x47\x66\x84\x31\x87\xe4\x9c\x43\xaa\x26\xad\xc8\xef\xf4\xff\x41\xd3\x64\xa1\x76\x6f\xda\xdb\x57\x17\x39\x09\xf6\x66\xfc\x9d\xcd\x62\x0c\x61\xc6\xb7\x8d\xdf\x9a\x17\xb4\x7b\x50\x9c\x90\xe7\x5f\x2a\x87\x1f\xf4\xa4\x79\x8a\x74\x9a\xcf\xde\x8a\x20\x54\xb9\x38\x72\x09\xf4\x0b\xd5\xed\xa6\x5b\x1f\xd9\x14\xb3\xa8\x79\x8b\xed\xb5\xdd\x5a\xae\x02\xb0\x22\xd2\x82\xf1\x82\xf0\xb2\x59\xb0\x82\xb9\xf3\x34\x65\x74\x70\x06\x3c\x54\x06\x6e\x1d\xf6\x42\x0a\xa4\x82\x2e\x4b\xa3\xb3\x2d\xfa\x20\x39\x30\x4a\xa9\x85\x2c\xa7\xf1\x67\x1f\x77\xf3\x4a\xd0\x04\xa2\x11\x0b\x48\x7e\x0a\x51\x75\xbc\x67\xde\xa3\x4e\xce\x48\xd8\x49" \
+"\x02\xdd\xe6\x7a\x6b\x8d\x7e\x01\xec\x3f\x33\xa9\xa0\x0e\xa5\xd0\xae\x09\x5b\x4a\xfc\x92\xc6\x4f\xee\xaf\x27\x66\x4b\x96\x28\x6d\x8f\x75\x4d\x99\xea\x52\x26\xa2\x17\xf2\x6b\x7c\xd9\x0d\x33\x37\x5c\x01\x1c\x8a\x3e\xd1\x45\xde\x3f\x3e\x96\xdd\x4a\xe8\xdc\xb5\x15\x24\xcb\xb6\xc1\xb7\xad\x71\x9d\xf1\xd0\x83\xac\x00\xb0\x37\xe5\x3f\x36\x54\xc5\x69\xc4\x9a\x3c\x34\x32\xbf\xe6\xca\x81\x55\xeb\x4b\xf5\xac\x3a\xe6\x00\xfb\xfa\x68\x7b\xf7\xe0\x78\x76\x1e\x32\xdf\x90\xe9\xf3\xd5\x3a\xe4\x7c\x18\xa8\xc2\x18\xc0\x04\x3f\x6b\x27\x37\xca\xc4\xfe\x95\x8d\xbd\x88\xda\x6c\xcb\x64\xc6\x79\xf0\xfc\xd0\xc8\xe6\xb2\x75\xc7\x02\x37\xa5\xd6\xd2\xf6\x8e\xb2\x3f\x56\xf9\x9c\x64\xac\xca\xc5\x94\xde\x4c\xb9\xdd\xf8\x47\x07\xe7\xe0\x9e\xec\x1b\x2c\x35\x3a\xb5\x41\xb0\x92\xdf\xfe\x05\xf9\xcf\xda\xa0\xd4\xf5\x0e\x72\xf6\x99\x8b\x37\xe6\x59\x8f\x7d\x85\x67\xf9\x7b\x5b\xe5\xc3\xd6\x41\xfb\xdb\x0b\x30\xa7\x48\x09\x83\x6e\xcf\xf4\xc5\x9f\x17\x33\xa1\x87\xfb\xdc\x34\xf2\x7a\xc7\x15\xe7\x22\xb9\x54\x8c\x70\x03\xa4\xe7\x40\xa2\xc0\x67\xb6\xa2\x70" \
+"\x02\x8e\x16\x94\x3e\x47\x4f\xe8\x55\x26\x0f\x57\xe6\xe8\x70\xcb\x5e\xe6\xac\xe9\xdb\x9e\xf6\x57\x3d\x9b\x16\x0e\x9d\x17\x3d\x63\xc4\x61\x46\xd8\xad\xec\xd3\x78\xc5\x1c\xe7\x2f\xd7\x42\x47\x2e\x42\x1c\x1d\xdf\x4d\xad\x90\x52\xdc\xde\x63\xe5\x4a\x35\x58\x74\x7b\xa2\xf0\xa8\xd8\x8e\xcd\x90\xb7\x7f\x87\x04\xa2\x5b\xb0\x4e\x1a\xb2\xf9\x68\xc3\x4c\x69\xce\x8f\x14\x9e\xdc\x16\x43\xc9\xed\x4e\xf1\x38\x6f\x3f\xa0\xf0\xa8\x83\xfd\x3e\x08\x33\x58\x2b\xae\xd9\xeb\xf3\x47\x32\xd2\x07\xeb\x38\x3f\x80\x6f\x20\xf4\xbb\xd9\xaa\x4d\x98\x41\x07\xc8\x1e\x2f\x53\x7e\x8b\xaa\x8e\xdb\xb8\x9c\x36\x66\xf9\x5e\x20\x02\xcc\xce\x4d\xe6\x3c\xb8\x8f\xa7\x6e\xf1\xcb\x3c\x2c\xae\x80\x96\xba\xd7\xda\xbd\x57\x6b\xd8\x54\x4c\xa6\xab\x5b\x17\x10\xd0\xd3\xb5\xea\x3d\xcb\xe0\xac\x80\x81\x42\x07\xf9\x00\x4b\x9d\xeb\x31\xf4\x9a\x9d\x6b\xcd\x46\x92\x26\xbc\x06\xda\x85\xe7\xcc\xa8\xea\x85\x11\xf5\x55\xfd\xa3\xf2\xa8\x38\x09\x63\x8e\xec\xed\x43\x14\xe2\x3c\x04\x56\x53\xd0\xf3\x13\x7f\xa8\x06\x9c\x43\xb3\x42\xaa\xf2\xd3\xaa\xc7\xbc\x47\xe7\xbf\x43\x2a" \
+"\x6d\x25\x75\x9a\xe7\x74\x3f\xe8\xce\x6b\x8d\x11\x7f\x8f\x4f\xf7\xa0\x3e\x97\xea\x74\x7e\x0e\xdf\x08\x05\x34\x52\x08\x63\x11\x09\x07\x04\xd0\x6a\x0b\xd0\x9c\x9d\x55\x33\xec\x80\x29\x42\x63\xf3\xdc\x99\x83\x6f\x4e\xbd\x5f\xdb\x33\x64\x29\x96\xbc\xda\x23\x25\xb0\x1f\x7a\xfc\xcf\xde\xd6\x8e\x5f\x13\x88\x9f\xc3\xd1\x27\xb6\x13\x61\xb9\x48\x53\xa5\xd0\xf9\x53\x04\xf4\xe6\x1e\x07\x0d\xa1\x5a\xc8\x79\x8a\x43\x97\xfc\xc5\xa5\x2c\xd7\x09\x51\x76\xb3\x9f\x0f\x03\x9c\x69\x97\x68\x6d\xa1\xca\x8f\xc7\x29\xbb\xac\x9a\x40\x69\x45\x43\xad\xe2\x22\xea\x6f\x45\xf4\x2d\xe6\x31\x0b\x12\x9e\x38\xb8\x37\x7c\x2e\xfc\xd7\x6d\xec\x7c\x9c\xac\x94\x9f\x2c\x93\x81\x32\x31\xe6\x80\xd5\x89\xa1\x7d\x8c\xde\x24\x5a\x75\xdf\x92\xed\x7a\x27\x76\xbc\x5d\x0b\x28\x31\x72\xe6\x50\x1f\xdd\x3a\xc7\xae\xc0\x70\x1f\xec\x62\x38\x4c\x1b\xc7\x4e\x1c\x30\x3e\xf6\xcf\x1e\x55\x32\x1f\x04\x8f\x3a\xf1\x83\x53\xcb\x46\xf1\x7c\x96\xa0\x58\x1e\xe3\xb1\xd5\x4b\x8b\x7a\x53\x53\x29\x61\x8c\x4e\x9d\xbc\xac\x55\x34\xca\x4c\x2f\x91\x4c\x7e\x90\xe4\x31\xef\x67\xc4\x95" \
+"\xcb\x85\x9f\xc9\xd7\xf1\x47\xf5\x72\x31\x7d\xe4\x16\xc0\xeb\xe6\xf6\xf7\x64\x6e\x4c\x4a\xd6\xe2\xdd\x78\x8c\xfa\x6c\x09\xcb\x28\x5c\x13\xb8\x88\x56\x4c\xfa\xb1\x40\x4c\xd6\x4f\xbe\x56\x08\x83\xb2\x00\xc8\xab\xf5\x90\x5e\x02\xec\x0b\xbb\x77\xa5\x53\x82\xfc\x31\x7e\xfe\x83\x26\x2b\xf5\xaa\x35\x07\xb7\xcd\x54\x47\x10\x7f\x56\xf9\x1f\xa9\x41\x21\xcf\x92\x6f\x9b\x2b\x91\x55\xfa\xd8\x26\x5f\x12\x81\xba\x0e\x03\x9e\x2b\xb7\x2c\xcd\x5a\x25\x8d\x1b\x82\x73\x04\x79\x43\x71\x2b\x6d\xfb\x47\x67\x20\x81\xa3\x49\x74\xfc\x20\x95\x11\x96\x75\xa8\xda\x38\xa3\xad\x7d\x54\x67\x88\xc3\x59\x2e\x1b\x2d\x99\x06\xb8\x51\x5d\x83\x1c\x2a\xab\x57\xb1\x87\x6d\x18\x4e\x50\x67\x6e\xa8\x03\xfb\xa5\x8b\xab\x19\x4d\xa6\xfa\xc1\xa6\xa8\xc3\xa0\x0c\x19\x6e\x24\x00\x84\xf7\xc7\xc3\x1e\xb1\x0e\xb0\xc5\x3a\x8e\x5d\x2b\x97\x7e\x1c\xb8\xe7\xb3\x71\xe3\x1a\xa5\x62\xb4\xb7\xda\xb6\x96\x7d\xe7\x66\xe7\xce\x27\x39\x79\xc1\x2b\x0b\xfe\xad\x1d\xfb\x2d\xab\x6a\x57\x72\x26\x3a\x99\x48\x54\xc1\x24\x02\x8e\xd7\x79\x93\xa0\x0b\x25\xf3\xd5\xd9\xb5\x98\x70\xbf" \
+"\x9b\xd9\x88\x75\xaf\xb6\x7d\x86\xda\x3a\xd4\xef\x27\xfa\x77\xdc\x71\xd6\x8f\xcc\x7c\x0b\x99\xc8\x9e\xd7\xfd\x28\x23\x11\xe8\x2d\xd9\x2f\xbf\x9f\xc7\x52\x29\x6a\x9e\xf4\xde\xfe\x85\x6d\x97\x2b\xbb\xcb\xa5\x3d\xa3\xcd\x07\xd9\x0c\xfc\x7b\x5a\xff\xff\x58\xdd\x7a\x4c\xad\xb9\x55\xb9\x21\xe4\xe2\xa1\x48\xd9\x22\xc5\x8c\xbe\x12\x07\x8e\xb1\xcb\x31\x5d\x5b\x0c\x0c\x1d\x23\x64\x88\x3a\x16\xae\x31\x47\xd1\xda\xc7\x7d\x33\x6e\x75\x2d\xcd\x8d\x51\xc0\x94\xd3\xee\xda\x54\xe3\xbf\xa0\x31\x6e\xcf\xbe\x08\x9c\xb8\xa7\x94\xe4\x45\x13\x27\x03\xd2\xcc\xc4\xe6\x7b\x40\x7b\x85\x73\x21\x55\x0f\x2d\x90\xda\x1f\xc0\x22\x3c\xd0\xa6\x71\x97\x7a\xf9\xab\xcf\x08\xa4\xcf\x8a\xf6\xd9\xfb\x22\x1b\x91\x90\x39\x3c\xa5\xcb\x75\xc7\x50\x8d\xda\x24\x41\x18\x73\x21\x98\x8b\x98\x22\x48\x63\xc0\xdb\x31\x41\xbb\xd9\x0e\xd0\x38\x3e\x8f\x0c\x33\xe1\xbb\x26\x13\x72\x53\x76\x75\x11\xf9\xe0\xb9\xe1\xed\x47\x4f\x43\x4b\x33\x00\x5c\x7b\x9b\x7a\x9a\x69\x65\xeb\x11\xa0\x23\x98\x6c\x2d\x97\x9a\x5c\x95\x3f\xff\x4d\x99\x68\x62\xd0\xfb\x70\xbd\x26\x66\xcd\x75" \
+"\xff\xe8\x96\x6d\x33\x46\x05\x0b\xe0\x29\x8d\xc8\xe3\xaa\x01\xdc\x22\x67\x70\xb9\xa9\xcf\x8d\xb7\xac\x3d\x81\x71\x7e\xc8\x3b\xc5\x5d\xf5\xf0\x3a\xe8\x28\x5a\x7d\x25\x86\xd2\x52\x76\xea\xc8\x73\xa9\x7c\xbc\x01\xac\xec\x1f\x4f\xd3\xd5\x92\xc3\xce\x69\x39\xf1\x3b\xed\x91\x20\x06\x18\xfd\x17\x3c\xd3\x02\x5e\x2a\xbe\xb4\xd5\xb1\x17\xa7\x68\x03\xe2\xab\xd0\x5f\x60\x39\x35\x8d\x73\x58\xae\x0a\xce\xea\x96\xb6\x9d\xf2\x5d\x61\x50\x09\x9a\x98\xa6\x5e\x8d\xee\xd4\x44\xe7\xf4\x00\x24\xa7\x02\x09\xa9\x10\x97\xaa\x21\x33\x01\x69\xd2\xc2\xe0\x92\xdd\xe3\x89\x3f\x90\x0e\x05\x8c\x1e\xc1\xcb\x2f\x5a\x14\xe9\xa9\x42\xc0\x5b\xfc\xa1\x8c\x43\xca\x0c\x18\xbe\xf2\x2e\xd0\x79\x08\xc2\xa4\xa4\x7d\xd8\xc2\xf2\x7d\x83\x23\x05\x2d\x12\x98\x9d\xf0\x23\x38\xf6\x90\xaf\x02\x07\x7b\x0d\x9e\xa8\x73\xdd\xc3\x36\xec\x23\x84\xf6\x07\x64\x6c\x78\x11\x17\xd2\x3d\xee\x26\x49\x95\x1c\xf9\x1d\x05\xe8\x1c\x83\x54\x4f\x9b\x1a\x52\x60\x96\xdb\x7a\xa7\xe7\x38\xe9\xb0\x9a\xd5\x7e\x0e\x9b\x0d\x44\x9d\x19\xec\xf4\x40\x7d\x4a\xf7\xf1\x7b\xb1\x66\x2b\xf4\x7a" \
+"\xad\x4b\x84\xf4\xf8\xec\xf6\xa1\x8a\x44\x56\x02\x34\x79\xe8\x60\x64\xcf\xee\xdb\x40\xc5\xa2\x08\x61\x90\x59\x79\x42\x92\xa6\xe9\x07\x91\xd9\xdf\x33\xfe\x80\x01\xd3\x01\x00\x00\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x0a\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x0a\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x0a\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30" \
+"\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x0a\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x0a\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x0a\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x0a\x63\x6c\x65\x61\x72\x74\x6f\x6d\x61\x72\x6b\x0a\x80" \
+"\x03"};
diff --git a/source/blender/src/Makefile b/source/blender/src/Makefile
new file mode 100644
index 00000000000..4741f695a75
--- /dev/null
+++ b/source/blender/src/Makefile
@@ -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 *****
+#
+#
+
+ORGLIBNAME = src
+LIBNAME ?= $(ORGLIBNAME)
+DIR ?= $(OCGDIR)/blender/$(ORGLIBNAME)
+
+CSRCS ?= $(wildcard *.c)
+PUB_CSRCS ?= $(CSRCS) $(wildcard pub/*.c)
+CRE_CSRCS ?= $(CSRCS) $(wildcard cre/*.c)
+
+OBJS = $(OCGDIR)/blender/makesdna/$(DEBUG_DIR)DNA.o
+
+ALLTARGETS = creator publisher
+
+include nan_compile.mk
+
+# Cflags stuff ------------------------------------------
+
+CFLAGS += $(LEVEL_1_C_WARNINGS)
+#CFLAGS += $(LEVEL_1_C_WARNINGS) -diag_error 1196
+
+ifeq ($(OS),$(findstring $(OS), "beos darwin freebsd linux openbsd solaris windows"))
+ CFLAGS += -funsigned-char
+endif
+
+# PreProcessor stuff ------------------------------------------
+
+CPPFLAGS += -I$(OPENGL_HEADERS)
+CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION)
+CPPFLAGS += -I$(NAN_GHOST)/include
+CPPFLAGS += -I$(NAN_BMFONT)/include
+
+# External interfaces of modules:
+CPPFLAGS += -I../render/extern/include
+CPPFLAGS += -I../renderconverter
+CPPFLAGS += -I../blenkernel
+CPPFLAGS += -I../blenlib
+CPPFLAGS += -I../bpython/include
+CPPFLAGS += -I../makesdna
+CPPFLAGS += -I../imbuf
+CPPFLAGS += -I../blenloader
+CPPFLAGS += -I../verify
+CPPFLAGS += -I..
+CPPFLAGS += -I../misc
+CPPFLAGS += -I../../kernel/gen_system
+CPPFLAGS += -I../../gameengine/SoundSystem
+
+# Only used by py_demo.c !!!
+CPPFLAGS += -I../radiosity/extern/include
+
+CPPFLAGS += -I$(SRCHOME)/sumo/include
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+
+CPPFLAGS += -I$(NAN_DECIMATION)/include
+CPPFLAGS += -I$(NAN_BSP)/include
+
+CPPFLAGS += -I$(NAN_BLENKEY)/include
+CPPFLAGS += -I../readstreamglue
+CPPFLAGS += -I../include
+
+ifdef NAN_BUILDINFO
+ CPPFLAGS += -DNAN_BUILDINFO
+endif
+
+ifeq ($(OS),linux)
+ ifeq ($(CPU),alpha)
+ CPPFLAGS += -I$(NAN_MESA)/include
+ endif
+ ifeq ($(CPU),i386)
+ CPPFLAGS += -I$(NAN_MESA)/include
+ endif
+ ifeq ($(CPU),powerpc)
+ CPPFLAGS += -I/usr/src/MesaCVS/include
+ endif
+endif
diff --git a/source/blender/src/blenderbuttons.c b/source/blender/src/blenderbuttons.c
new file mode 100644
index 00000000000..b4aedcc9e95
--- /dev/null
+++ b/source/blender/src/blenderbuttons.c
@@ -0,0 +1,1210 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+/* DataToC output of file <blenderbuttons> */
+
+int datatoc_blenderbuttons_size= 37540;
+char datatoc_blenderbuttons[]= {
+137, 80, 78, 71,
+ 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 1,190, 0, 0, 0,242, 8, 2, 0, 0, 0,189, 2, 55, 29, 0, 0, 32,
+ 0, 73, 68, 65, 84,120,218,236, 93,121, 92, 84, 85,251,127,238,189,179,177,175,130, 10,138,128,184,164, 40, 8,238,187,130,146,
+ 75,101,130,154,246,166,239, 91, 57,152,190,165,102,106,153,111,249,102,165,253,114,169,232, 21,244,173,172,183, 69, 69, 91,204,
+ 76, 19, 76,115,201, 13,247, 13, 68, 80, 4, 4,129, 25, 6,152,253,222,123,126,127, 28,184, 14,195,204,157, 59, 3, 40,213,253,
+126,248,232,157, 59,243,220,229,220,115,191,231,123,158,115,206,243, 16,147,158, 94, 9, 34, 68,136, 16, 33,194, 25,144, 98, 17,
+136, 16, 33, 66,132, 72,157, 34, 68,136, 16, 33, 82,167, 8, 17, 34, 68,136,212, 41, 66,132, 8, 17, 34,117,138, 16, 33, 66,132,
+ 72,157, 34, 68,136, 16, 33, 66,164, 78, 17, 34, 68,136, 16,169, 83,132, 8, 17, 34, 68,234, 20, 33, 66,132, 8,145, 58, 69,136,
+ 16, 33, 66,164, 78, 17, 34, 68,136, 16, 33, 82,167, 8, 17, 34, 68,180, 16, 36,246,190,216,243,229, 91,220,182,107, 33, 66,240,
+ 17,156,181,109,206,121, 45,109, 93,190,108,167,174,220,234,140, 46,156,215,181,251,181,121, 94,151,143,240,176,158,145, 88,175,
+196,122,213,118,234, 85,203,168, 78,171, 18,180, 87,160,246,108,241,159, 11, 21,171,153,231, 21, 88, 15, 92,171, 61,173,129,166,
+247,251, 96,206,222,130,229,252, 32,109,197,122, 37,214,171, 22,183,109,121,213,201,145,247,131,124,228, 86, 45, 6,126,228,194,
+ 91,105, 43,219, 7, 86,191,155,217,202,113,230,194,207,222,244,140,194,109,185, 95,206, 93,182, 6, 0, 54,175, 93,142,119, 10,
+ 47,103,108,232,172, 45, 7,203,243,138,245, 74,172, 87,127,208,122, 69, 58,172, 46,206, 18,232,164,167, 87,226, 63, 23,158,244,
+195, 13, 30,106,245,252, 30,204,233, 44,111,217,229, 18,112,161, 15,203,221,102,115,238,215, 41, 91,171,226,197, 27, 98,189, 18,
+235,213,195,173, 87,173,162, 58,255, 64,176,122,186, 46, 60,242,230,212,239, 7,239,103,105,230,205,138, 16,235,149, 88,175, 90,
+ 94,117,182, 5,112,222, 25, 23,188,197, 15,247,145,187,236,140,123, 96,142, 17, 92, 50, 92,191, 6,111,252, 69,222, 16,177, 94,
+137,245,234,207,172, 58,185,135,221,156,114,119,202, 81,210,204, 46,149,149, 83,201,133, 83,187,112,205,205,151, 6, 46,120,133,
+ 38, 61,189,114,207,151,111, 61, 96, 55,165, 88,175,196,122, 37,170,206, 86,175,223,150,110, 29,129,237,109,115,234,183,149, 23,
+201,101, 79, 28,119,156, 7, 57, 40, 55,119,217, 26, 23,238,186,153,247, 43,214,171, 7, 83,175,240,195,229, 30,177, 88,175,254,
+228,170,179, 69,116, 1,215,136, 53,179,169,116,161,173,126, 40,197,229,154,160,176,116,171,111, 94,187,220,169,155,253,195,245,
+194,196,122, 37,214,171, 63,179,234,108, 78,253,126,144, 62,157,182,112, 94, 17, 98,189, 18,209,230,168,211,170,231,248,128,189,
+227, 45,114, 34,167,170,157,101,151,217,178,163,228,218,155,246, 0, 76, 90, 4, 86,238,124,215, 94,105,167,234,198,195, 29, 70,
+248,171,213,171,135,229, 55,252,235,212, 43, 73, 91,123,171,155,158, 84, 72, 41,224,158, 84, 75, 45,152,107,230, 53, 11,127,228,
+156,251,223,133,107,118,185, 73,227,206,107, 89,185, 93, 94,228,215,156,183, 75,172, 87,173, 90,175, 92,123,190, 98,189, 18, 8,
+ 66,156,183, 37, 66,132, 8, 17, 45,208, 97, 23, 33, 66,132, 8, 17, 34,117,138, 16, 33, 66,132, 72,157, 34, 68,136, 16, 33, 82,
+167, 8, 17, 34, 68,136,212, 41, 66,132, 8, 17, 34,117,138, 16, 33, 66,132, 8,145, 58, 69,136, 16, 33, 66,164, 78, 17, 34, 68,
+136,120, 8,184,191,154,104,242,240, 80,225,102, 63, 30, 41,182,252,104,101, 91,120,229,119, 32, 13, 29, 66, 67,106,245, 90,117,
+149,182, 91,207, 97,194,109,143,158,189, 9,172,188,188,164,196,195,205,195,207,223, 99, 96,124,184,112,219,230, 92,115, 73,105,
+166, 76, 65,203, 21, 18, 74, 66, 49, 64,120,203,166, 8,183,245,245,143,243,243,243,115,115,115, 3,130,184,122,105, 55,255,121,
+221, 66,174, 11,191,102,125, 73, 15,203,143, 29,221,203,133,219,150,234,130, 27,217, 26,157, 56,111,169,188,209,121, 67, 76,185,
+194,109, 75,100,221,219,130,109, 47, 91,229,188,118,109,230,178,101, 41, 77,247, 95,105, 92,206,110,161, 38, 39,158, 81,177,172,
+ 81,221, 8,113,226, 25,253, 88,210,232, 25, 25,140, 30,194,109, 21,114,109,163, 67, 61,150, 38,220,118,242,238, 5,150, 31, 95,
+ 46, 75, 23,110,187,174,125,106, 43,189,131, 15,204,182,133,169,211, 38,158,191,246,198,150,158,171,132, 28,168,224,242, 47, 4,
+176,158,114,183,207, 50,190,254,252,243, 15,134, 38, 12,165,181,186, 71,122,140, 96, 89,152,191,148,121,228,145,238,249,249,183,
+ 13,122,218,171,195,208,166,182,199,206,221, 67, 64,212, 25,245,202,197,171, 87,125, 56,190,244, 74, 14,128, 98,239,133, 98,146,
+132, 15,222,124, 61, 47, 47,183, 75,151, 48,185,155, 36,192, 79,222,212,246,218,143, 63,203,229,114,119,119,119, 47, 47, 47, 95,
+ 95,223, 0,255, 0,127,127, 63, 31, 31, 95, 79, 15, 15, 74, 34, 97, 89, 70,175,215,215,214,212,158,215,105,236, 93,121,126,222,
+118,185, 66,239,233,165, 80,184,203, 37, 50,138, 32, 9, 82, 66, 33,234, 23, 51, 77,200,232, 68,254,187, 46, 44, 34, 3, 3, 3,
+ 21, 30, 6,163,209, 64, 82, 36, 65, 64,199, 78,195,171,171,213,186,218,203,173,215,220,109,222,188,121,238,220,185, 98,179,239,
+ 16,246,136,210,217,223, 0, 64,123, 55,247,146,146, 18,169, 66,206,186,187, 63,200, 91,208,169,206, 31,207,222,102,185, 39, 33,
+101, 77,219, 44,237,255,125,241,133, 92, 38, 99, 89,214,195,211,115,242, 99,143,253,133, 84,103, 83,220,216,186, 2, 6, 74,158,
+215,124,179,197,231, 41,254,163,164, 60,214,213, 56,198,223, 92, 87, 45, 97,200, 1,125, 66,103,207,126,169,222, 29, 64,194,137,
+223,183, 6,118, 14, 97,235,106, 70, 14,140, 46, 45, 85,103,157,163,173,108,149,202,119, 64,230, 67,184,123, 35, 10, 93,184,250,
+247, 79,183,237,199,251, 89, 22,146, 6, 15,134,186, 50, 0,175,155,151,174, 73, 3,125,135, 14,234,237,233, 27,212,244,236, 4,
+ 16, 4, 65,144, 4, 73,145,148, 68, 66, 73,164, 82,169, 84, 42,145, 74, 37, 18, 9, 77, 19, 36, 73, 17, 4, 97,239,202, 47,156,
+219,236,227, 35,241,242,244,108, 23, 20,224,233,229,206, 32,198, 96,212,155, 25,198,221,211,189, 93, 80, 7,134,189,117,231,122,
+ 23,155,134,251, 14,228,121,121,121,250,250,250,233,116,110, 58,157,187, 66, 33, 39, 72, 0, 0,189, 94,175,211,233, 42,213,222,
+149,149,149, 85,149,229, 67, 7,119,178,105,158,185, 54,147,191, 72, 19,230, 36,248, 5,251,217,228,205, 22,100,207,215,254,239,
+255, 0,224,157, 87, 94,113,193,246,213,247,222, 3,128,119,151, 46, 21,110,114,185,164, 36, 47, 47, 15, 0,158, 28, 61, 90,160,
+ 73,198,142, 29, 0,192, 61, 65,132, 16, 65, 16,248, 95,252, 17,127, 59, 55,197, 6,253, 45, 91,150,194,207,140, 66,120, 51,220,
+207, 95,111, 50, 2,128,204, 77, 97,210, 27, 88,173,174,178,236,110,135,232,104, 30,147, 14,145,221, 28,222,151, 79, 88,207,235,
+ 7,127,112,248,179,227,217,219,134, 37,204, 80,248,197, 8, 42,172, 20,149,195,159, 76,155, 54,109, 71, 74,150,205,175, 70,103,
+ 85,112,219,143,248, 74, 0,224,158,129,213,211, 8, 0,180, 52, 2,128,140,129,190,221,188,164, 54,109,223,127,255,253,215, 22,
+ 46,121,252,201, 41, 6,131,254,131, 13,235,211,210,210, 22, 44, 88,240,215,165,206,168, 57,111, 47,221,186,226,189,129,215,159,
+ 7, 7,236,105,172, 83,181,239, 58,118,245, 43, 79,110,205, 56,132,247, 28, 62,158,174,213, 25, 39, 36,188, 52,100,232,156, 25,
+211,198,184,185,201, 77, 12, 93,171, 51,117, 27, 52,179,137,245,109, 48,193,147,179, 54, 61,191,184,190, 35,144, 52,100,148, 66,
+ 33,255,254,224,254,189,199,126,255,226,179,255, 24,244, 70, 25, 37,241,116,151,121,203,152,252,162, 50, 43, 99,132, 0, 1,106,
+248, 23, 33, 4,136, 69, 8, 33, 22,177, 12,195, 48, 12, 67,211, 52, 77,211, 54, 47,251,228,239,155,131,218, 81, 94, 94, 30,157,
+ 58,117,238,222, 51,202,211,211, 93, 85, 93, 85, 90,118,183,162,170,146,165,145,135,187, 71,247,110,143,248,248, 22, 93, 62,225,
+105,101,184,251,251, 83, 32,145,235, 37,164, 76, 46,211,233, 20, 58,157,155, 66, 33, 39, 8, 4, 64,232,116, 58,157,174, 78,167,
+211,106,235,106,170, 42, 74,191,220,122,214, 39, 50,206,230,217,255,239,139,255,179, 87,158,175, 60, 99,155,203,212,106,181,229,
+182,191,191, 63,230, 17, 63, 63,191,155, 55,111,102,102,102, 58,197,167,178,224,250,222,162, 26,192,207,101, 9,156,153, 57,127,
+254,124,243,189,123, 66,120, 51, 40, 40,232,201,113,227,204,114,249,186,117,235,166,142, 25,131,137,143, 31, 4, 65,188,255,230,
+155,245,253,202, 55,222, 88,183,106,149,205,109,123,230,150,236,185,118,109,102, 92, 92, 92, 86, 86, 65, 66, 66,132, 64,222,236,
+209,190,131,175,183, 55,230,104, 15,133,219,221,138,123, 53,234,106, 79, 95,191,219,167,207,132,245,143,231, 49,124,108,238,146,
+167,167, 78,142,234, 82,223,238,190,177,238, 35,238,171, 85, 47,255, 19, 0,138,126,206, 30,208,173,147,160,142,185, 64,222,172,
+111,147,253, 29,253, 34,193,225, 49, 60, 36,196,133, 85,207, 18,222,129, 76,193, 5, 99,193,149, 60,149, 54,254,103,190,231,155,
+158,145,177, 88, 57,255,153,231,254,145,249,213,182, 46, 93,186,172, 94,251,158,215,155,171,191,255,254,251, 39,158,120,226, 15,
+ 65,130,174,197,223,113,208, 97, 23,206,158, 0,178, 71,122,118, 39,201, 67,121,213, 85, 0,215, 52, 37, 55,164, 10,249, 15, 63,
+125,168,171,100,102,253,125, 17,203,194, 99,147, 7, 51, 18, 79,123,198,121,121,215, 88, 22, 38,244, 37, 0, 58, 2,132, 25,140,
+166,228,164,113, 10, 95,242,139,175,247,145, 36,236,220,182,149,162,107,123,134,201,243,139,160, 9,117, 34,150,101, 89,150,101,
+ 24,134,102,104,147,217,100, 52, 26,245, 6, 61, 65, 16, 36, 73,210,180, 89,167,211,233,244,122,155,227, 97, 62,222, 72, 42,149,
+250,251, 7,116,141,140,234,214,181, 7, 73, 17, 52,195,222,171, 80, 25, 13,102,134,213, 86,148, 87,134,134,232,123, 68,245, 56,
+123,238,123,128,246,150,134,114, 18, 33, 86,111,214,209, 90, 10, 20,114,153, 66, 33,151, 74, 37, 44, 75, 19, 4,161,213,233,238,
+149,151, 94,185,120,166,234, 94, 41,203, 50, 36, 33,116, 32,238,211, 77,159,226,141,127,204,251,135,221,247, 34, 51,211,114,123,
+241,226,197, 69, 69, 69, 4, 65,100,100,100,184, 80, 99, 62,254,248,227,242,242,242,157, 59,119, 78, 28, 49,194, 47, 40,200, 89,
+243,119,151, 46, 85, 3, 32,132,210,210,210, 0, 64, 57,109, 26,255,239,243,242,242,158, 28, 55, 14, 0,100, 50, 89,183,110,221,
+118, 29, 60, 40, 68,126, 10,161, 87,126, 44, 91,150,146,149, 85,144,147,147, 3, 0,220,191, 41, 41, 41, 14,121,179, 91, 80,176,
+175,183, 55, 69,146, 47, 60, 61, 75,111, 48,174,251,228, 19,119, 55, 55,131,193, 96,208,235, 73, 9,117,231,220,185, 78,177,177,
+246,108, 49, 63,222,184,117,203,242,163, 11, 24, 56,102, 70, 86,230,242,196,199,158, 69,242, 40,129, 38,196,180,250,246, 21,237,
+240,179,183,199, 30, 30,241,149,220,174, 99, 14, 39,182,147,190,148, 81, 51, 43, 92,226, 23,228,144, 55,179,179,179,187,116,232,
+248,220, 11,169,203, 23, 45, 77,251, 44,125, 64,191,126,233, 31,165, 47, 92,186,228,171,193, 3, 47, 93,186, 20,205, 43,207,219,
+ 26,111,130, 51,129,168, 37, 86,158, 77, 91, 79, 79, 82, 82,199,132,148, 58,100, 79,150,162, 40, 0, 0,240, 6, 8,245, 9,233,
+126, 59,119,231,166,140,207, 72,163,251,184,209, 67,247,101, 31,211,233,192,221,223,167,169,153,155,123,119,189, 46,151, 97,152,
+134, 29,101, 0,165, 36, 53,234,153,217,207,178,114,237,158,159, 62,125,108,242, 63,220, 61, 64, 87,165,182,226,175,250,179, 34,
+150, 97, 88,154,166,205,102,179,209, 96,212,233,244, 82,169, 20, 8, 48,153, 76, 36, 65,210, 52,173,211,233,234,234,234,192,199,
+218, 69,117,248,215,140,246,193, 4, 65,146, 18, 74,202,176, 72, 85,165, 49,209,166,242,178,170,106,117,173, 78,107, 2, 61,205,
+178,101,148,228,114,199,208, 48, 15, 55, 55, 91, 94, 2, 0,218,164, 87, 87,220,211,215,177,102, 3, 69, 17, 52,109,190, 87, 94,
+114,245, 98, 78,121,233, 29,132, 16, 73, 82, 36, 73,130,125, 95,129, 11,192,162,114,243,230,205,201,201,201, 49, 49, 49,114,185,
+124,253,250,245,174, 29, 10, 75,206, 65,189,123, 7, 7, 7,167,165,165, 77, 26, 57,178,163,243,236,233, 7,160,156, 54, 77, 26,
+ 20,148,150,150, 38, 13, 10,114,168, 61,205,114,185,212,104,220,181,107,151,165,252, 20,222,121,119, 25,152, 49,185, 6, 70,169,
+ 84,102,102, 58,150,156, 90,157,174,157,191,255,223,147,147,171, 53, 53, 21,170, 42,169, 84,130, 33,149, 74,229,110,238, 53, 85,
+149,181,119,138,189, 58,217, 29,172,184,113,235,214,151,187,126,180,164, 78,172, 61, 7,246,235, 51, 97,244, 72, 1, 87, 93, 11,
+224,229, 21, 16,147,240,152,199,129,221,159, 60, 24, 47,231,197,207, 55, 26,247,125, 22,180,229,236, 35,190, 18,202,219,159, 86,
+223,139,255,249,158,135,132,208,210,136,178,163, 1, 10,243,243,247,238,254,233,243, 45,159,127,248,201,127,210,215,111,244, 15,
+240, 95,253,206,234, 47,190,254,106,248,160,161,159,126,242,233,147, 41, 79, 14, 31, 58,188,141,243,166,107,249,223, 27,149,199,
+210,147, 52,254, 43,169, 99, 0, 64,107, 70,218,206,253, 43,122, 61, 46, 27,248,164, 86,226, 9,165,215,159,215,124, 99,243, 40,
+187, 15,170, 0,106, 30,159,253, 18,203, 2,128, 10,192, 11,192, 28,214,189,159, 66, 46, 97,104, 35, 50,209, 0,224,229,229, 85,
+165, 82, 55,181,221,184, 97, 49, 0, 92, 61,241, 9, 89,127, 45, 44, 0,176,250, 43, 6,163,153,146, 42, 8,153, 20, 0,106,107,
+106, 2, 2, 2,108, 19, 54,203,178, 44, 67,211,102,163,209,164, 55,232,235,234,234, 52,154,154,106,117,181,170, 74, 85, 85, 85,
+ 85,165,170, 82, 87,171, 53, 53, 54,198,136,228,114, 19,195,176, 38, 19,173,174,174,201,207, 47, 60,147,115,254,212,169,115,215,
+175,223, 44, 45,169,168,171, 51,214,213, 26, 42,238,169,175, 94,189,113,242,100, 78, 73,137,141, 49, 83, 78, 11,153,244,186,146,
+194, 27, 23, 79, 29,255,110,251, 39,251,118,111, 43, 46, 42, 96, 88, 6, 8, 2,136, 6,134,229,133,189,190,185,221,182, 78, 82,
+223,218,249,249,249,121,121,121, 45, 91,182,204,181, 74,243,241,199, 31, 39, 39, 39, 3, 64,120,187,118, 68,243,248, 29, 51, 38,
+214,158, 60,189,117, 0, 88,183,110,221,141,187,119,159, 28, 55,110, 88, 76, 12, 0, 92,188,120, 17, 0,190,253,245, 87,254,227,
+191,252,198, 27, 75,222,124, 19,247,202,241, 6,222,198, 27, 60,189,117,140,172,172, 2, 75,222,228,182,241,126,123,240,149, 72,
+ 12, 38, 35, 69, 81,215, 11,110, 22, 20,223, 57,121,254,130,201,100, 38,129,144, 72, 36, 4, 65,176, 12,163,215,234, 14,236,216,
+206,115, 4,142, 55,159,158, 58,185,145,155,232,236, 69, 78,141,242,194,171,161,166, 70, 97,210,204,202, 92, 46,165,111,180, 46,
+151,168,238,202, 58,119,187, 55,127,200,197,207, 55, 74, 2, 59,224,125,247,230, 15, 9, 84,144,222, 18,219,149,164,123, 84,119,
+119,119,143, 15,255,251,241,232,145, 35, 7, 14, 30, 84,152, 95,120, 61, 63, 15, 88,164,144,203,135,198, 13,253,105,247, 79,223,
+125,247,221, 31,197,125,233, 84, 74, 37,137, 85,247,220, 82,123, 18,243,119,121,244, 28,122,228,247, 43, 0,240,232,115,233,117,
+ 27,167,120,220, 62,241, 60,250,102,139,175, 13,237,217,213, 59,244,242,197,111, 27,232, 88, 11, 96, 6, 48,131,217, 40, 97, 41,
+ 18, 88, 0,248,238,251, 95, 0, 96,232,163, 54,186,117,251, 46,161,164,216,222, 22,122, 78, 2, 32, 5,169,130, 38, 24, 22, 8,
+ 0,152, 62,235, 69, 0,184,125,124,179, 77,234,164, 25,134, 52,211, 36,105, 36, 73, 18,128, 96, 24,218,104, 52, 72, 36, 82,130,
+ 0,134, 97, 76, 38,147,209, 96,148,119,234, 96,101,200, 48,172,201,204,130,222, 84, 89,169,214,233,140, 20, 37, 49,153,204, 70,
+147,201,204,152, 89,196, 34,130, 0,210, 92, 91,103,170,168,168,213,234,105,128,110,118,152,179,126,195,104,208,107,170, 85, 36,
+ 73, 17, 4, 16, 78, 74,205,220,219,185,221,195,186,243,244,211, 45, 29,127,110, 13, 18, 88, 34,145, 20, 20, 20,172, 93,187, 22,
+ 0,150, 45, 91,230,227,227,163,209,104,170,171,171,133,244,112,177,228,108,223,190, 94,197, 47, 88,176,224,163,143, 62,114, 77,
+120,114, 71,224,161, 78,206,203, 73,120,121,173, 93,187,118,233,210,165, 82,169,212,172, 86,251,248,248, 44, 95,176,192,161,246,
+180,244,105,218,243,123,218, 28, 2,114, 40, 69,177, 26,181,233,225, 82,171, 84,158, 94, 94,149,106,245,175, 39, 79, 74, 72,202,
+104, 54,235,244,122,150,101,177,115,153, 54,155, 76, 70, 35,127, 81, 55,237,164,175,122,249,159, 88,120, 70,117,233, 82, 84,144,
+239, 84, 9, 39,164,172,209, 86,156,252,249,187, 79, 92,208,158, 14,251,233, 28,206,239,216, 18, 51,123,145, 60,188, 15, 0,208,
+149,119,243, 84, 90, 0,144, 15,158, 84,196,208,238,105, 39,109,154,212,212,212,200,221, 20, 93,195,195, 11,139,239, 84, 85, 84,
+ 77,127,122,214,222,236, 3, 31,172, 89,247,221,222,221, 81,225, 81,207, 76,253,219,239,103,143,125,183,107,215,148,169, 83,255,
+228,195, 68,247,251,236,189,198,186,247, 24,210,101,202,202,210, 74, 13, 0, 44,126,106,204,187, 83,223,128,245,143,194,221,235,
+224,107,227, 64,249, 53, 53,221,124,189,105, 35,228, 31,250,178,235,168,241, 0, 20, 0,152, 77,102, 41,144,117, 6, 35, 0, 36,
+141,234,231, 22, 16, 98,243, 34,146,162,137,189, 23,144, 84, 1,178,206,227, 77, 69, 71,176,240,148,202,228,102, 48,120,186, 41,
+ 0, 96,247,222,111,244, 85,119, 6, 69,250,218,162, 78,196, 48, 12, 77,208, 36, 73, 96, 38, 53,153, 76,122,189, 30,171, 51,150,
+101,105,154, 54,153, 76,237,154, 24, 26, 12, 52, 69, 17, 52,205, 26,141, 76,109,173, 30, 33,160,105,214,108,102,128, 4, 82, 66,
+ 1, 73, 32,130, 64,136,160, 89,173,222,192,240,213, 75,142, 63,235, 41,147,211,155,248, 51,209,130,146, 19, 0,220, 27, 38,199,
+ 88,242,102, 68, 68, 68,109,109, 45, 77,211,248,197, 22, 40, 57,187, 4, 6,226,143, 93, 2, 3,137, 22,117, 44,216,243,114,162,
+218,218,149, 43, 87, 26,171,170,204,184,185,109,223, 30, 0,164, 70,227,228,201,147, 75,238,221, 11,105,209,121, 63, 92,127,156,
+115,116, 90, 33, 46, 46, 14,143, 23, 1,192,149, 18,235,111,105,163,169,218,164, 50, 24, 12,190, 62, 62, 10,153,220,204,208, 8,
+ 33,220, 18,155,205,102,150,102,248,203,249,198,173, 91,220, 24,145,101,207,221,114,236,200, 89,120,180, 27, 8,224,138,130, 19,
+238,235, 28,121,160,226, 94,151,157,178,206,221,136,240, 62, 97,159,157,171, 52,176, 30, 18,194,116,244,251,220,130, 66,123, 21,
+ 68, 79,155,114,126, 63,181,241,253, 13, 67, 70, 13,123,253,223,111,238,255,121,255, 87, 95,252,111,240,136, 97,157,186,116,150,
+184, 75,179,143,100,127,253,249,255,190,253,126,215, 79, 63,253, 52,113,226,196, 63, 19,117,146, 77,121,115,233, 73, 26, 0, 32,
+ 52,102,245,103,251, 48,111, 2,192,250,111, 14, 18,157,248, 71,250,170,243,170,139, 36,114, 72,122,108,209,215, 31,174, 1, 48,
+129,206,200,232,225,251, 95,207,103,157,190, 10, 0,161,157,195, 73, 9,101,207,120, 66, 95,194,108,128,221, 63,237,139, 31,247,
+ 79, 0, 41,128,148,114,131,105,147, 82, 38,140,120, 28, 0,138,111,223, 68,102,198,206, 48, 2,203,178, 44,205,208, 70,147,201,
+ 96, 52,232,245, 58,173,182,174,182,182, 86,163,209,212,104,106,106,106,106,235,234,234,116, 58,157, 13, 79,150,150,213,235,105,
+189,158,214,106, 77,181,181,134,154, 90,125,109,157,161,174,206, 88,163, 49,212,214, 26,107,107,140,181, 53, 70,141,198,168,169,
+214,171,213,122,187,227, 23, 8,184, 65,126, 2, 44,136,178,158, 68, 29,163,231,224,158,199,246, 30,219,127,112, 63,102,210,220,
+219,124,147,192, 41,138,146, 52,148,225,123,239,189, 7, 0,203,151, 47,143,136,136,128,134,233, 59,194, 37,103,112,112,163,201,
+216,243,231,207,255,233,183,223, 74, 5, 12,148,219, 68, 90, 90, 26, 63,249,154,229,245,115,114,183,111,223,158, 95, 86, 6, 0,
+123, 14, 29,226,118,230,230,230,182,107,215,174,149,170, 56,230, 71,165, 82,201,237,193,219, 28,111,218,110,162,188,189, 88,134,
+169, 81,169, 43, 43, 43,171,170,213, 90,157, 78,171,211,213,214,213,105, 53, 53,181,213,213, 6,189,206,100, 48,176,180,221, 54,
+213,146, 31, 57,222,196,219,150,163,237,252,168,171, 56,153,149,121, 63,105,132, 78,117,190,181,233,224,238,244, 46, 97,159,157,
+ 35,194,251, 24, 15,239,188,253,247, 88, 15, 9,113, 36,177, 29,173,169,136,223,119,207, 78,127, 29,146,147,147,159,127,105, 94,
+126,110,238,239,135,142,248,120,249, 60, 53,253, 41,223, 0,255,179,167,206,120,202, 20, 30, 30, 30, 29,186,116,252,102,219, 55,
+203, 87,188, 86, 87, 93,221, 6,233,143,203,107,196,253,185,162, 58, 57,222,252,219,152,126,160,189, 8, 85, 5, 43,255,177,100,
+213,198, 45,164, 79, 40, 0, 12,243, 87,161, 59,252, 79,206, 19,160, 14, 0, 46, 92,252,177,111,204,228,127,189,254,197, 15,223,
+174,255,229,215,107,163, 7,247,146, 72,228, 7,142,156, 69,148,196,196, 48,252, 87,147, 20,219, 99, 95,206,117, 88,183, 38,121,
+242,132, 73,147, 38,239, 63,248, 29,109, 54, 76, 28,255, 20,201,152,165, 20,101,199,215,137,176, 74,173,159,145,196,178,148,153,
+ 38, 73,146, 36, 9, 32, 8,196,214,143,192,219, 26, 4,144, 17,132, 94, 42,165, 8,146, 0,132, 88, 22, 24,150,165,105,150,166,
+ 17, 65,209, 64, 16, 8, 8,154, 5, 19,205,234, 13,140,187,159, 93,197,105,185, 69, 16,152,194,136,198,195, 73,118, 37,103,207,
+193, 61,235,149,209,214,172,172,173, 89, 0,112,108,239, 49,152,192, 87, 68, 44,139, 0, 96,231,206,157,184,214,134,135,135, 99,
+113,109, 54,155,105,154,118, 72,157,178,224, 96, 44, 57,195, 91,142,170,164, 65, 65, 0, 48,113,164,221,161,143, 33,209,209,235,
+214,173,155, 60,121,114,110,110,110, 94, 94,222, 19, 9, 9, 0,208,189,123,119,110,231,237,219,183, 3,229,242,246, 13, 42,184,
+169,175,147, 83,211, 75,222,124,147,187, 71,135, 94, 78, 14, 41, 41, 41,153,153,153, 74,165, 50, 35, 35, 3,243,102, 92, 92, 28,
+191,137,186, 82, 67, 0,109, 50, 25, 13,229, 58,153, 66, 33,145, 72,176,234,212,215,213, 25,181, 90,163,209, 88, 87, 93,157, 52,
+107,150, 61,115,204,143,184,207, 62,176, 95,159,147,103, 47,114, 95, 89,185, 62,237, 14, 18, 85,156, 60,121,232,187,177, 19,102,
+212,211,168,230, 70,238,197, 99, 46,136, 77,225,189,117, 0,200, 83,105,139,158,235,143, 10, 47, 6,109, 57,171,165, 81,205,172,
+112,159,175, 11,107,254, 30, 32, 33,128,180,223, 52,206, 95,176, 96,229,154,213, 65, 1,129,102,150,185,113,167, 96,214, 83, 51,
+191,248,242,203, 31,190,223, 61,115,214, 76,163,193,120,228,204,113,189,190,110,238,156, 57,217,191,255,110,115,164,247,161,179,
+167,101,206, 84,225,249,145, 36, 86,195, 68, 81,115,222, 62, 1, 16,125,237, 34,156,249, 14, 69, 79, 52, 95,216,181,106,213, 42,
+194, 39,228,141, 69,207,163,180, 39, 1,160, 66,207,218, 60,208,225, 67, 63,140, 28, 53, 22, 0,180,172, 57,191,186, 8,128,233,
+234, 29, 62,122,116,159,224,192,246, 85,154, 26, 0,168, 54,209,119,171,181, 61,109,217,134,118, 30, 92, 92,244, 59, 0, 0, 33,
+ 73,234, 75, 0, 72,246, 93, 50,239,223,179,179,188,178, 52,192,215, 7, 0,124,101,210, 14,190,158,118,216, 11,177, 44, 0,176,
+120, 86, 39,203,178, 12,201, 16, 36, 65, 16, 4,129, 5, 33, 66, 8,217,184,230,167,102,190,244,191, 47, 86, 41, 20, 18,138,194,
+ 61,125,196, 50,136,102,144,217,204,210, 44, 2,130, 96,129, 96, 24,100, 52,179, 47,205, 91,101,181,144,203,194,211,137,184, 15,
+ 28,105,222,255,143, 87,120,114,188,105,181,125,108,175,221, 55,132, 97, 24,163,209,152,156,156,140,169,115,231,206,157, 59,119,
+238, 76, 78, 78,142,140,140, 36, 8,226,131, 15, 62, 88,190,124,185, 74,197, 55, 47,122,201,146, 37, 75,150, 44,217,183,111,159,
+182,188,209,216, 87,120,187,118,133,133,133,192, 59, 61,190,233, 28,120,105, 80,208,199, 31,127,140, 16,154, 52,114,100,136,125,
+ 63,105,251,192,192, 33,125,250, 84,221,186, 21, 40,151,231, 53,140,179, 71,117,232,176,120,241,226, 99,199,142,117,235,214,173,
+119, 72, 8,143,123,215,210,191, 41,220,215,105,233,244, 92,182, 44,101,217,178,148,130,130,122,189,201, 77,243,228, 25,100,247,
+ 12, 9,210,223, 45, 99,105, 70,171,209,104, 42, 43, 8,130, 68,136, 53, 24, 12,184,154, 21, 94,189,102, 54, 25,121,134,215, 27,
+245,168, 70,143,156, 48,122, 36, 55, 52, 36,164,195, 94, 87,121,234,228,161,239, 0,192,211,195,227, 7, 11,225, 25, 63,124, 74,
+171,242, 72,252,207,247,206, 60, 10, 49,113, 9,247,230, 15,105,255,159,227,121, 42,173,159,140,168, 82,169, 37, 4, 33,225,237,
+ 67, 61,243,204, 51,220,246,143, 63,254, 56, 97,226,163,123,118,239,217,177, 99,199,155, 43, 86,254,114, 40,155,146, 80, 33,161,
+ 33, 26,141, 6,100,109,142, 58,193,213, 60,125, 18, 11,222, 52, 71,205,121,167,222, 79,116,138, 94, 59, 64, 2,159, 61, 7,189,
+198,190, 49, 40, 6,116,183,208,191,227, 65, 93,162, 53,163,239,251,217,102,229,220, 60,211,209, 19,239, 0, 0, 75, 41,112,231,
+ 50,191,230,238,191, 22,252, 67,167, 51,214,232,141, 0, 96, 34,229, 99,146,146,109,218,174, 92, 49,103,223, 79,241, 0, 0, 12,
+ 94, 59, 76, 39, 69, 19, 51, 94, 88,239,238, 46,247,118, 83, 0,128,148, 53,132,180,179,243,102, 34,132, 8, 96,217,250, 69, 38,
+ 44,193, 18, 44, 22,127, 4, 16, 13, 29,106, 59, 82, 76,167,115,211,235,107,165, 82,138, 36,128, 69,192,178,136,166, 89,154,102,
+117,122, 26, 1,193, 34, 48,211, 8,145,132,173,115, 2,209,192,160,184,183,110,169, 64, 27,228, 38, 1, 0, 79,255,125,138,189,
+245,179,215,126,191,230,180,191, 31, 33,189, 94, 31, 29, 29, 29, 17, 17,113,235,214,173, 29, 59,118,112, 10, 20, 99,205,154, 53,
+ 14,217, 19, 0, 82, 83, 83,155,238,156, 58,123, 54, 8,152, 30,143,151,247, 88, 98,242,168, 81, 14,199,151,218, 55, 76,144,176,
+ 84,160,183,111,223,142,239,222, 93,166,213,242,223,114,115,222, 10, 75,126,180,156, 21, 11, 2,214, 26,185,117,104,175,187,145,
+207,208,116,141,186,154,166,105,220, 0,171,203,239,213,168,213, 8, 33, 30,201,105,229,244,252,114,215,143,150, 19,146, 44,221,
+160,118,234,229,133, 19,191,226, 17, 87,248, 33,243, 19, 0,232, 55,114,134,127, 80, 76,107,178, 7,106,196,158,176, 37, 38,245,
+ 95,101, 44,219,119,235,169, 83, 73,193,189,246,148, 75, 8,240,146, 10,157,161, 60,121,242,228,131,135, 14,142, 73, 28,187,123,
+215,247,111,173, 93,179, 76,163, 65, 44,187,125,251,174,192,192,192,162,154, 63,227, 48, 17,199,155, 0,208,117,246,219, 75,183,
+174, 0,128,247, 32, 27,174,100,115,154, 20, 0,162,250,216, 61, 86, 59,255,216, 9,115,158, 97, 16, 39, 15, 81,157,182,134,146,
+248, 0,233,190,244,125, 7,115,182,147, 38,246,254,254,227,229, 64,234,160, 65, 32,122,122,250, 48,102, 53, 32,237,237,227,155,
+227,251,116,230, 29,165, 65, 0, 4, 2, 68, 32, 32, 8, 68,212,179,150,101, 7,195,246,235,167, 76, 93,154,246,209, 59,181,181,
+ 26,137,132,108, 24,113, 66,102, 51, 91, 87,103, 50,209, 44,139, 8, 74, 66,190,247,238,198,166,134,143, 62, 62, 8, 0,246,255,
+120,130,161, 25,124,244,250, 5,129,245,163, 67, 0, 64,204,126, 46,153,231,126,159,123,235,185, 91, 55,111,185,240,192,140, 70,
+163, 90,173,246,241,241,137,139,139, 27, 48, 96, 64, 69, 69,197,205,155, 55, 9,130, 96, 89,118,215,174, 93, 14,217,115,193,236,
+217,110, 65, 65,147,108,117,174, 23,204,158, 13, 0,110,246, 73,240,149, 87, 94, 1, 0, 43,219,144,198, 62, 83,135,104, 31, 24,
+ 56,180, 79,159,170, 91,183,130,220,220,122, 15, 25,210,170,149,219,138, 25,227,226,226,172,198,139, 28,178,103, 64, 84,215, 90,
+181, 90, 34,151, 25,141, 6,198, 76,179, 44,235,229,231,167, 81,169,146,102,205,226,151,156,220,148,120,236,232, 60,121,246,226,
+132,209, 35, 57, 47,167,189, 25,242,221, 58,168, 43,171, 42,119,100,222,159, 2, 56,109,214,179, 42, 83,148,115, 44,216,164,135,
+222,100, 15,225, 80,123,194,207,245,203, 40,187,254, 80,191,126, 79, 99,102,132, 95,195,152, 81, 99, 46,248, 93, 24, 55, 49,233,
+249,191, 61,219,167,111,244,238, 31,126,252,253,124,206,220,185,115,139, 90, 33, 12, 71,115, 96,149, 57,217,169, 68,202,118, 87,
+ 19,225,137, 74,152, 64, 45,247,240,163,119,239,161, 31,126,248,197,139, 47, 61, 21, 18, 22, 5, 96,148,202, 21,197,119,107, 70,
+ 78,126, 70,200,165,196,198, 70,204,153, 51,109,235,167,223, 2,123, 27, 64, 66, 27,244, 33, 29,124, 58,123,211, 14,133, 24, 1,
+ 4, 34, 16,129, 0,107, 63, 2, 16, 96, 13, 42,224,164, 11,254,249, 26, 0,188,246,234,139, 20, 69, 34, 0,134, 65, 52,205,212,
+213,209, 44,139, 72,146,216,180,137, 47,162,204,248,201,131, 0, 96,239,247,199,208,125,226, 36, 0,224, 89,229, 83, 14,207,171,
+169,211,216, 92,162,238, 16, 44,203,234,245,122,134, 97,106,106,106, 40,138, 98, 24,166,125,251,246,102,179,217,114,222,226,154,
+ 53,107,236,173,200,196,242,208,207,165, 73, 72,254,184, 49,114,146, 43,155, 34,216,206, 20, 93,123,112,217,215,105,197,137, 54,
+199,217, 29, 78,140,239, 50,160, 63, 0, 92, 63,124,216,160,211,179, 12,211, 51, 46, 46,122,200, 8,207, 16,222, 2, 68,196,237,
+194,155, 0, 32, 3,248,199,147,245,174,235,219,133, 55, 45,183,109, 78, 96,203,187,235, 7,224, 55,125,214,115,183,239,148,157,
+248,109, 15, 0,236,248,234,147,129, 35, 38,121, 5, 15, 19, 82, 80,211,166, 77, 19,178,206,146, 33,228, 54,247, 23, 77,105,255,
+115,169,161,165, 88,169,111,223,190,125,251,246, 61,115,230, 76,246,137,195, 1,129, 1,109, 57, 96,141,107,249,223, 29, 47,196,
+116,246,136,145, 61,250,255,180, 63,255,137,137,238, 65, 33,157, 84,181,244,200,137,127, 19,110, 59,184,127,143,193,253, 95, 83,
+ 42,255, 5, 80,238,231, 37,233,236,207, 58, 54,153, 53,189,249,101,247,206,187, 31, 2,192,139, 47,254,211,108, 50,177, 8,220,
+221,221, 55,108,216, 32,208,118,194, 19, 67, 1,224,167,239,142, 18, 4, 57,247,133,167, 31,192,147, 70, 8, 25,141, 70,147,201,
+132, 9, 5, 83,201,159, 53,150,146,195,245,157,194, 33, 36, 66,146, 61,244, 24, 57, 82,248,143,239, 22,228, 14,140, 10,117,249,
+ 92, 85,166,174,158,193, 93, 19, 82,134, 57,107,104, 47,174,135, 5, 72,154,144,235, 73,219, 35,132, 55,107,233,110, 94, 60,132,
+224,202,244,181,248,248,248,182, 92,187,154,142, 11, 9,247,123, 18,174,185, 72, 69, 60, 92,184, 25,175,235, 27,135,212, 20, 33,
+ 66,196,131,132, 24, 37,254, 15, 9,145, 55, 69,136, 16,169, 83,132, 8, 17, 34, 68,234, 20, 33, 66,132, 8,145, 58, 69,136, 16,
+ 33, 66,132, 21, 90, 37,173,155,104, 43,218,182, 77, 91,188, 22, 83, 44,171,191,184,109, 11, 83, 39, 52, 14,145,192, 3,155,149,
+175, 57,182, 34,156,130,189,247, 95,132, 11, 5,101,239, 55,114, 6, 25,169,251,211,113,138,138,138, 74, 74, 74,228,114,121, 96,
+ 96, 96,231,206,157, 31,216, 45,112,241,177,196, 55,168,237,170, 78, 12,135,235,222,120, 2,228, 88,217, 54, 13,128,198, 99,251,
+249, 23,159,240,159,119,246, 51,207,182,181,215,146,255, 7, 11, 23, 46,236,217,179,167,203,230, 41, 41, 41, 9, 9, 9,246, 12,
+ 91,138, 61,199,143, 31, 15, 0,251,247,239,127, 0,182, 90,173,118,215,174, 93, 56,173,219,212,169, 83, 99,237,103,167,104,122,
+191, 14,211,186,165,167,167,219,108,167,249, 11,138,231, 91,142, 55,239,221,187,103, 52, 26, 9,130, 80, 40, 20, 6,131,161,168,
+168,232,244,233,211,125,251,246,237,218,181,171,189,195, 14, 29, 58,212,225,125,221,189,123,183,160,160,192,225,207,214,174, 93,
+139,131, 10, 10, 41, 43, 33,115,123,167, 77,155,102,179, 94, 89,213,201,176,176, 48, 0,168,173,173, 53, 26,141,248,217,241,212,
+ 73,145, 58, 31, 62,142, 29, 61, 57,116,216,192,166,251, 73, 32,218, 96,217,253,144,158,100,239,171, 39,230,237,107,142, 0,183,
+ 71,172, 89, 89, 89,150,219, 92, 61, 46, 44, 44,196,105,221,156,226,211, 75,151, 46, 97,250,179, 60,148,179, 72, 77, 77,157, 63,
+127,190,144, 20, 52, 56,175,198, 51,207, 60,163, 86,171,215,173, 91,215,165, 75, 23, 63, 63,199,235,169, 8,130,248,249,231,159,
+241,118, 82, 82,210,190,125,251,108,110,243, 20, 50,199,143, 74,165, 50, 46, 46,142, 75, 38, 42,164,249,209,104, 52, 65, 65, 65,
+152,163,221,220,220,238,221,187, 87, 93, 93,237,227,227,115,234,212, 41, 0,224, 97,207,222,189,123,167,164,164,112,148,103,169,
+ 28,113, 96,255, 19, 39, 78,204,156, 57, 83, 72, 9, 11,228, 77,140,141, 27, 55, 54,191, 98,123,120,120, 92,189,122, 85, 42,149,
+154, 76,166,125,251,246,221,184,113,227,213, 87, 95,253, 19,147, 96,171,164,117,123,136,236, 73,146, 36, 23, 44,142, 5,212,246,
+ 31, 64, 72,252,106,188, 81,114,230,117, 23,204,113,150, 96,126,237, 96,149,214, 45, 33, 33,225,192,129, 3, 4, 65, 88, 5,182,
+ 16, 8, 46,173, 27,206,180,225, 44,246,239,223,159,157,157,205,165,117,115, 72, 67,121,121,121, 56,190, 14, 78,235,182,110,221,
+ 58, 33,242,179,249,105,221, 50, 50, 50, 54,111,222,108,153,214, 77,169, 84,166,164,164, 56,188, 96,181, 90,237,231,231, 71,146,
+228,156, 57,115, 12, 6, 67,122,122,186,155,155,155,193, 96,208,235,245, 20, 69,229,228,228,180,107,215,206,199,199,199,166, 45,
+230, 71, 78, 87,186,156, 7,101,217,178,101, 74,165, 82,184,240, 4,128, 69,139, 22,225, 13,110, 69, 92,211, 61,246, 16, 22, 22,
+ 86, 89, 89,249,250,235,175,123,120,120,236,220,185,115,228,200,145,127, 41,222, 4,151,211,186, 53, 19,220,203,207,179, 71, 56,
+123,218, 12,178,249, 23, 7,167,158,146,147,147, 19, 19, 19,161,113,216, 36,167,112,233,210, 37, 0, 72, 72, 72,192,105,221,130,
+131,131, 93, 72, 94, 56,118,236,216,177, 99,199, 94,186,116, 41, 45, 45, 77, 72,250, 67, 76, 70,174,201,207,230,192,102, 90, 55,
+135, 66, 91,167,211, 5, 4, 4,204,152, 49, 67,163,209, 84, 85, 85, 73, 27,242,186, 73,165, 82, 55, 55, 55,149, 74,117,250,244,
+105,158,131, 20, 20, 20,112, 77, 26,166, 78,172, 61,227,226,226,132,107,252,136,136,136,101,203,150, 97,195, 7,224,229,188,117,
+235,214,225,195,135, 39, 78,156, 24, 22, 22, 22, 24, 24,120,248,240,225, 87, 95,125,213,195,195, 67,171,213, 82, 20,245, 39,230,
+ 77,156,149,200,169,180,110, 45, 73,157, 77,187,153, 2,199,142,132,247,220,219, 32,166, 46,216,191, 43,109,124,115, 10,173, 57,
+175, 4,247, 94,185, 32, 57,177,216,140,142,142, 38, 8,162,188,188,220,229,188,175,216, 48, 45, 45,205,222,141, 96, 47, 39, 0,
+172, 91,183,110,234,212,169, 92,108, 71,156,214, 13,239,228,209,158, 73, 73, 73,156,223,252,209, 71, 31,229,116, 40, 79, 63,189,
+105,251,109,149,214, 77,169, 84,114, 61,119,155,200,207,207, 39, 73,146,162,168,252,252,124,132, 80,110,110, 46, 14, 26,128,211,
+186, 49, 12,163,211,233,190,251,238, 59, 30, 18,228,120, 51, 37,197, 58, 10,137, 83,125,240,136,136, 8,124,193,206,202, 79, 23,
+ 96, 54,155,251,245,235,119,232,208,161,248,248,120,173, 86,139, 93, 34,135, 14, 29, 26, 63,126, 60, 77,211,127, 86, 69,194,101,
+115,155,187,108,141,240, 64,241, 45, 73,157,205, 25, 38,250, 67,179,231,137,194, 71, 6,133, 95,117,173,159,142,229, 73, 68, 68,
+132, 11,241, 59,172,210, 19, 9, 25,118,176,148,156, 86,105,221, 92, 19,158,220, 17,120,210,186,113, 50, 83,171,213,174, 93,187,
+ 54, 42, 42, 74, 42,149,202,229,114, 31, 31,159,213,171, 87, 59,212,158,150, 62, 77,123,126, 79, 33, 13,121, 83, 41,202,253,166,
+169,202, 80,169, 84,124, 32,159, 8, 0, 0, 32, 0, 73, 68, 65, 84, 94, 94, 94, 42,149,234,248,241,227, 20, 69,225,132, 87, 92,
+ 90, 55,179,217,108,116,148,214,173,105, 39,157,107,231, 34, 34, 34,238, 57,153,203, 36, 35, 35, 3, 63,110, 23, 26, 90,225,177,
+108,214,173, 91,247,202, 43,175,224,102,172,160,160,224,198,141, 27, 0, 16, 27, 27,155,155,155, 27,228,106,202,191, 63, 43, 36,
+109,246,202,254, 16,188, 57,117,193,254,230,152,187,172,202,155,242, 38, 56, 51,158,128, 37,103,239,222,245, 89, 72,123,247,238,
+221, 76,225,201, 15,206,203,233,225,225,177,114,229, 74,169, 84,138,247,199,196,196, 0,128,159,159,223,228,201,147,143, 30, 61,
+ 58,121,242,228, 22, 60, 41, 71, 49,156,163,211, 10,113,113,113, 92,115,213,116,222,159,201,100, 82,169, 84, 6,131,193,199,199,
+ 71, 46,151,227,228, 37, 92, 90, 55,134,113,144,214, 13, 55,135, 77,123,238,150, 99, 71,206,194,101, 67,225,190,206,213,171, 87,
+ 79,156, 56,177, 75,151, 46,238,238,238,163, 70,141, 82,169, 84, 30, 30, 30,106,181,122,235,214,173, 36,249, 39, 92, 62,131, 35,
+ 39,109, 94,187,220,178,195, 46,208,215,217, 70,139,227,143,162, 55, 1,160, 95,108, 76,246,193, 95,191, 62,232,142,153,244, 68,
+225, 35, 78,153,199,197,197,101,101,101,225,161,115,165, 82, 41, 64, 57,214,191,177, 86,105,221,132, 3, 75,206,166,105,221,118,
+238,220,137,191,114, 1, 14,211,186,169,213,245, 73, 25,183,111,223,126,254,252,121, 0,216,182,109, 27,183,179, 85,211,186,113,
+227,233, 86, 45, 22,191,204,247,242,242, 98, 24, 70,173, 86, 87, 86, 86,170,213,106,157, 78,167,211,233,234,234,234,106,106,106,
+ 52, 26,141, 94,175, 55, 26,141,140,253, 92, 91,150, 15,197,106,112, 79,184,131,165,160,160,192,242,178,133,247, 42, 92,198,231,
+159,127, 62,106,212, 40,119,119,247,171, 87,175, 30, 58,116,200,195,195,227, 95,255,250,215,209,163, 71, 95,125,245,213, 63, 37,
+117,222,247,234, 56,153,211, 13,218,230, 48,209,240, 17,131, 5, 38,197,125,232,146,179, 95,108,125,218,131, 93,223,126,183,235,
+ 91, 0,128,236,131,191,194,152,209, 0,142, 39, 39,225,185, 50,220, 27,133, 95, 48, 1,243,132, 8,104,146,214,205, 41,222,196,
+146,211,166,192,116, 77,120, 98,194, 93,176, 96,129,221,130,154, 58,213, 50,173,219,211, 79, 63, 13, 77,210,186,253,237,111,118,
+227,186, 54,211,215, 9, 46,165,117, 11, 8, 8,168,170,170, 50,153, 76, 21, 21, 21,114,185,156, 75,235,166,213,106,117, 58,157,
+209,104,212,104, 52, 86, 78, 76, 75,112, 29, 2,104, 18,157,158,199,170,105,175,130,235,245, 55,157, 27, 47, 80,108, 10,239,173,
+ 3,192,141, 27, 55,114,115,115,117, 58,221,224,193,131,117, 58, 93,102,102,230,244,233,211,119,239,222, 77, 81,212,159,155, 58,
+ 45, 85,231, 67,160,206, 22, 25, 38,250, 99,233, 77,155,219,217, 7,127, 21,168, 55,109,110, 91, 78,222,180, 9,123,105,221,112,
+106, 13,126, 50,229,210,186, 89,237,143,142,142,198,105,221,120,166,184, 55,157, 3,143,137, 24, 33,180, 96,193, 2,174,251,223,
+ 20,177,177,177, 97, 97, 97, 56,131, 91, 94, 94, 30, 30,103,183,220,105,153, 20,204,186,161,104, 60,175, 83,184,175,211,178, 18,
+102,100,100, 36, 36, 36,100,101,101,225, 10,201, 77, 84,224,241, 27,134,134,134,230,231,231,227,104,252,102,179, 25,115, 55,151,
+214, 13,143, 26, 9,212,251, 9, 9, 9, 9, 9, 9,156,102, 20, 98,197, 17,101, 68, 68,132,229, 75,228,242, 36, 39,129,192,243,
+144, 94,126,249,229, 67,135, 14,141, 30, 61,250,198,141, 27,158,158,158, 69, 69, 69,127, 86,234,196, 35,236, 86,195, 68, 46,142,
+176, 59, 53,146, 99, 5,171,231,106,217,102, 90, 54,197,127, 14,222, 4,128, 59,197,101,246,190,114,115,115,119,104,110,211, 1,
+ 39,240, 85,228, 79,235,230, 80,138,218, 76,235,118,235,214, 45, 33,178,183,105,115,248,207,127,254,147,135, 55, 49,252,253,253,
+177, 43, 83, 46,151, 91,138,205,215, 95,127,157,191,202, 53,179,243, 97,201,143, 86,179, 95, 29,174, 53, 26, 57,114,228,222,189,
+123,105,154,174,174,174,230, 18, 53, 87, 84, 84, 84, 87, 87, 35,132, 4,122, 45,177,163,211,114, 66,146,165, 27,148,159, 55,185,
+210,126,144,139, 47, 49,123, 46, 95,190,252,240,225,195,147, 39, 79,126,247,221,119,151, 44, 89, 34,145, 72, 20, 10, 5,136,224,
+161, 78,135,205,154,107, 83, 97,254,124, 88,189,122,117,101,101,101,115,154, 25,151, 93, 87, 4, 65, 68, 70, 70, 70, 70, 70,142,
+ 29, 59,182,160,160,192,102, 90, 55,123,236,137, 83,179,165,164,164, 88,250, 58,177,164, 90,186,116, 41, 63, 79,217,180,117,182,
+131, 47, 80,108,182, 84, 55,200,146,116,154,166,117,227,103, 79,130, 32, 38, 78,156,248,213, 87, 95,201,100, 50,163,209, 72,211,
+ 52,203,178,190,190,190,106,181,218,225,146, 68,110, 74, 60,230,235,156,156,156,132,132, 4,238,221,177,247,150,225, 42, 97,181,
+244,200, 89, 95,118,211, 30,186, 83,125,118,204,158,220, 52,248, 23, 94,120, 1,111,212,212,212,252, 89,223,101,171, 97, 34, 23,
+169,179, 57,204,216,212, 86,248,209,218,218, 18,117,135,104,215,174, 93,115, 70, 54, 34, 34, 34, 90,100,130, 30,119, 28, 75, 49,
+184,102,205, 26,123,116,208,156, 53,200, 45,181,126,153, 83,160, 2,225,178,175,211,170, 16,108,202,124,135,130,110,214,172, 89,
+ 55,111,222,252,245,215, 95,113, 54,189,152,152,152,105,211,166, 57,124,118, 39, 78,156,224,164, 43,183,199,114,219,222,211,228,
+154, 85,204,185,107,215,174, 21,190,114,124, 90,243,242, 56,253, 5, 3,139,112,185,137, 44, 73,211,149,213, 68,205, 41, 59, 49,
+160,203,195,197,159,181,252, 91,240,190, 92, 62, 20,214,248,194,127,127,236,216, 49,129,235,211,121,154, 67, 23, 26, 42, 49, 54,
+ 71,115,216,211, 41,222, 4, 49,173,219, 31, 23, 98,102, 55, 17, 34, 30, 34,196, 40,241,127, 84,136,188, 41, 66,132, 72,157, 34,
+ 68,136, 16, 33, 82,167, 8, 17, 34, 68,136,212, 41, 66,132, 8, 17, 34, 44,209,138,105,221,156, 74,161, 69, 33, 36,101,192, 32,
+177, 61, 59,218,221,204, 26, 36, 36, 75,136,169,172, 90,204,150, 97, 24,131,193, 64, 81, 20,142,195,200,133,228,104,141,243, 50,
+130, 27,232,189,135,219, 68, 89,253,248, 88,154,112,219,201,187, 23,180,148,237, 15,147,157,176,125,252,199, 70,182,147,134,133,
+ 0, 0, 65, 16,102,179,185,176,176,208,100, 50, 73, 36,146,226,226,226,167,124,186,236, 63,115, 70,223,167,211,160, 65,131, 40,
+138,194, 83,187,246, 28, 45,105,169,178,194,231,229,128, 23, 56, 92,185,114,165, 99,199,142, 42,149,170, 99,199,142,110,110,110,
+208,176,180,193,234,188, 54,109,239, 92,254, 82, 57,188,232,235, 51,221, 36, 65,227, 60,189,188,237,217,182,173,180,110,252,224,
+ 95,216,208,252, 20, 90, 76,195,181,180, 63,113, 53,255,222, 93, 55,153,162,187,187, 79,254,136,222, 0,160,147, 62, 8,117,252,
+151, 74,161, 69, 81,148,135,135, 71,243,143,147,155,155,187, 97,195,134,117,175, 1, 0,124,127,100,248,172, 89,179,172,126, 96,
+201,155,119,138,238,148, 20, 23,231, 94,191,174, 86,171,195,194,194, 60,189,188, 18,199,143,227, 63,254,129, 3, 7, 28, 94,195,
+206,157, 59,133, 63, 41,188,146,202,102, 46, 35, 62,164,168, 0, 0, 0, 1, 16,144,233,239,132, 97,220, 6,136,152, 13, 0, 80,
+176, 21,114, 22, 59, 93,190,201,149,247,207,187, 51,144,231,135, 4, 65,104,181,218, 95,126,249,165,160,160, 32, 69, 26,208,190,
+ 83, 59,131, 86,239,166,163,135, 46,121,126,196,228,233,123, 62, 73,255, 49, 59,123,220,184,113, 15,160,106, 49, 12, 83, 80, 80,
+208,183,111,223,110,221,186,157, 61,123,214, 96, 48, 68, 69, 69, 9,140, 74, 65,211,244,133, 51,231, 66,159,141, 93, 58,160,215,
+137, 95,222,223,117,105, 84, 84,239, 49,109, 51,162,133, 32,234, 20,178, 20,189, 69, 82,104, 69,157,189,233, 87, 85, 71, 0, 50,
+ 49,148, 89, 85, 87, 92,169,185,149,150,227, 57,122, 96, 96, 47,190,209,228,156, 95,149, 61,234,103,221, 81,223,253,194, 30, 57,
+141,230,206,128, 30,145,176,248,109,231, 72,208,169, 20, 90,246, 56,183,181,131,209, 2, 64, 74, 74, 38, 0,248,251,219, 88,234,
+174, 82, 37, 0,128, 82,233,247, 96,166,248, 53,240, 38, 2,128,239,143,140, 56,122,244,104, 83,234,228, 16, 27,253, 75,121,241,
+174, 47, 62,171,255,152,119, 61, 23, 0,158,251,251,183,154,186, 5,213, 53,124,235, 56,183,111,223,238,176, 25,112,170,249,111,
+196,164, 74,101,186, 48,218,181, 76, 36,231, 4, 34,102,223, 15,195,225, 2,117, 54,220, 29, 79,148, 38,140,155, 55,111, 30,218,
+177,227,223, 9,211, 98,102,189, 32, 11,246, 3, 9, 9, 64, 2,139,128,149,178, 70, 52, 97,246,220,162, 15,215, 28, 63,126,124,
+200,144, 33,173, 77, 67, 36, 73,198,196,196, 28, 58,116,168,111,223,190, 3, 6, 12, 40, 43, 43,187,112,225, 66,159, 62,125,132,
+ 44,242,166, 40,106,236,152,196,119,215,239, 94, 54,231,210,160,164,121,131, 6,102, 45,249,168,184, 91,255,103,108,218,114, 41,
+255,120,238,200, 94,202,191, 86,167,206,251, 85, 45, 97, 71, 70,138, 90, 56,123,186,144, 66, 43,244,102,121, 63, 55, 63, 89, 7,
+ 31, 6,144, 91,181,123, 89, 69, 69, 89,173, 38, 92,238,121,125,255, 81, 4,208,206, 62,123,246,136,132,235, 55, 73,132, 20, 12,
+ 33,127, 34,209, 60,101,156, 30,128,109,104,171,157,172,231, 78,178, 30, 23,222,230,204,153, 51, 0, 16,191,188, 96,109, 14,192,
+218,105, 14, 9,212,229,140,152,247,213, 76, 92,156,173, 83,168, 5, 94,249,141,108,239,247,119, 60,133,183, 95, 78,249, 38,106,
+172,198,217,240, 5,185,185,185,235,215,175, 39, 73,242,229,119, 96,248,240,225, 71,142, 28,225, 57, 66,108,244, 47,131, 6,238,
+ 26, 52, 16, 86,173,186,191,115,230, 76,152, 48, 1, 0,210,190,217,193,199,158, 20, 69,225,136, 39, 12,195, 76,159, 62, 29,175,
+217,119, 72, 37, 54,245, 38, 94,177,202, 93,103,106,170, 80,222,116, 17,113,235,161, 33,213,218,134, 13, 27,160,223, 58, 56,251,
+114, 43,157,234,224,193,131,155,166,204, 13, 31,147, 8,148,145,144,146,132,132, 36, 40, 41, 66, 4,171,165, 17,195, 32, 19,243,
+252,236, 23, 94,248,215, 75, 55,131,131,157,154,222,239, 2,206,156, 57,211,161, 67, 7,150,101, 15, 31, 62,124,253,250,245,196,
+196,196,193,131, 7,159, 60,121,178, 87,175, 94, 14,109,143,102,127,243,100,140, 46,167,150,154,249, 70,221,176,216, 15, 22, 44,
+156,254,254,178,234,101,239,127, 21, 17, 59,147,135, 22, 57,122, 73, 77, 77,181,218,195,255,162, 89, 37, 38,186,239, 73,104,102,
+130, 13, 75,222, 4, 0,101,166,159, 16,246,116, 45,133, 86,151,235,165,221,101, 30, 50, 68,187,189,255, 10,173, 51, 41, 94,126,
+219, 71,166, 48, 72,245, 90,131,222, 13,136,187,135, 79,200, 66, 59,216, 75,161,117,253, 38,108,222,198, 2,232, 0,116, 0, 48,
+188, 63, 57,101, 28,209,192,158, 48,119, 6,108,222, 38,232,145, 59,155, 66, 11,243, 38, 38, 77,204,155, 92,113,173, 21,192,158,
+ 55,215,220,180,247, 85,228,114,190,202,237,239,159,101, 25,166,183,241, 87,202,184,184,184,185,115,249,194,154, 85, 94,234,240,
+122,218,227, 8,208, 96,255,215,135, 38,244, 58,122,224,202,186,204,153,144,137,222, 88,252,159,142,221,133,202,183,186,219,202,
+ 16, 5,232,170,174, 32,132,188,130,250, 96,222,220,180,105,147,205, 31,251,122, 95, 30, 52,112, 23,222, 62,121, 18, 6, 54,196,
+120,121,171,161,222, 62, 53, 45, 45,253,191, 43, 16,116,226,233,146, 55,243,125, 86, 42,149,152, 55, 45,152, 84,153,158,110,187,
+ 90,146,211,212, 92,195, 75, 0, 0, 1,108, 74,227,111, 9,220,135, 38, 0,208,196,198, 58,155,156,174,198,221,107, 0, 96,217,
+ 57, 11, 23, 46,196,251, 23, 46, 92,184,113,227, 70, 50,234,217,250, 3, 35, 0, 2,172,108, 37,211,173,207,107,153,213, 66, 50,
+157,239,188, 6,131,161,125, 88, 23, 96, 77,164, 28, 8, 9, 69,215,106, 12, 5,133, 21,197, 37,161, 67, 70, 17, 50, 95,194,108,
+ 2,138, 92, 59,111, 73,226,230, 55, 23, 47, 94,220,156, 98,228,161, 21, 44, 0,245,122,189,191,191,127,110,110, 46,203,178,133,
+133,133, 91,183,110,237,217,179,103,117,117,181, 67, 81,143, 16, 10, 35, 79,118,232,156, 84,125,248,146, 70, 45,255,223, 30,122,
+239,137, 47, 95, 76,113,147,232, 88, 0, 27,212,249,112,123,241, 18,126,210, 68, 8, 17,137, 13,241,102,178,166, 65,138,227, 38,
+ 26, 51,166, 78,247, 21, 0, 97, 48,124,234,239,159, 37, 36,133, 86,208, 93, 85, 80,176, 66,241,198, 11, 76,165,138, 46,173,148,
+200,164,238, 4,229, 65, 80, 30,148,196, 95,170, 80,215, 86,223, 61,120,220,103,202,163, 54,109,173,152,241,200,105,118,202, 56,
+ 2, 0,214,175, 32, 16, 1, 4, 18, 42, 63,157, 77,161,101,201,155,214, 72,216,177,118,237, 52,167, 92,165,126,115,235,203, 92,
+189, 57, 67,200,165,186, 38,156, 17, 66, 43,210, 30,195,164, 57,164, 87, 50, 0, 12,233,149,124,252, 74,175,163, 7,174,172, 90,
+ 63, 63, 35, 67,104,215,134, 32, 64,185,232, 50,174,241,195,134, 13, 59,114,228,136, 61,222, 4,128, 17,195, 78,115,219,253,251,
+195,150, 45,240,235,175, 16, 21, 5, 17, 17,247, 85,106, 76,244,181,115,151, 58,217,243,157, 9,239,188,243,168,123, 43,161,106,
+143, 55, 1, 32, 61, 35, 3,179,159,205,246,137,109,120, 99, 51, 54,111, 38, 8,248,241,183, 70, 67, 16,155,210, 51,240, 93,117,
+233,210, 5, 33,244,193, 7, 31,224,253, 31,124,240,193,198,141, 27,247,239,223,143,131,251, 97,118,180,178,197, 18, 24, 33,244,
+252,243,207,219,240, 3, 54, 92,255,230, 45, 91, 8, 2,246, 28, 41,177,122,178, 18, 47, 47,144, 82,140,174,250,218,222,236,175,
+118,236,252, 79,105, 33, 0,156, 90,229, 29, 53, 98,130,177,232,206,149, 11, 57,151, 10,243, 52,101,101,151, 47, 95, 6,104,239,
+ 2, 89,224, 24,213,252,220, 87, 90, 90,186,114,229,202,247,223,127,223,100, 50, 81, 20,229,229,229,165,213,106, 79,157, 58,197,
+ 95, 45,177,109,117,241,177, 85,159, 21,125,178,176,163, 74, 43,147, 73,200, 80, 63, 69, 89,165, 73,249, 30,221, 55, 62,174,179,
+253,158, 4, 38, 80,238, 65, 55,221,224, 65,211,102,192,158, 14,181,209,190,218,171,109, 56, 46,225,253,189, 89,130, 34, 11,224,
+216,198, 58,221,215,152, 55, 57,239, 27,127,204, 99,201,161, 28, 31, 85, 45, 43,147,152,114,174, 24,175, 21, 24,126, 57, 2,122,
+163, 12, 33,119,160, 36, 64, 24, 89, 90,101, 52,252,231,192, 30,123,230,235, 87,192,220, 25,247, 63,206,157,209,208,166, 3,202,
+205, 71,139,223,118,162,105,194, 41,180, 64, 64,192,246,130,130, 2,203, 32,155,247, 37,167, 5,123, 62,128,176,222, 78,187,101,
+207,107, 1, 8,142, 55, 1,224,201, 55,164,239,239,120,106, 88, 98, 47, 0,116,243, 92,157,144,131,124,253,245,215, 47,191, 67,
+120,182,139, 70, 0, 73, 83,230, 29, 61,122,148,239,173,128, 59, 33, 29, 27, 69,187,232,219, 23,162,162,224,153,103, 26,245,238,
+ 59,117, 42,225,233,176, 83, 20, 53,125,250,116,170, 49,184, 61,252, 87,203,213,100,167, 60, 18,132,197, 91,141,209,244, 35, 97,
+171, 81,230, 12,199,141, 27,103,165,239, 22, 46, 92,136,243,152, 54, 92,153,181,237,247, 25, 25,151, 47, 95,198, 7,231,110,211,
+178, 16,240, 71,155,231,149, 33, 68,186,203,205,101,183, 51, 94,127,125,171,182, 90, 61,114, 16,222,255,201,151, 91,223, 92,242,
+ 92,183,197, 79,253,251,210,193, 29,234,194,196,199, 30, 19,216,169, 58,127,254,188, 82,169, 60,119,238,156, 69, 99,147,110,179,
+ 12,113,129, 92,186,116,233,240,225,195, 79, 61,245, 84, 90, 90, 90, 93, 93, 29, 14,211,103, 48, 24, 60, 61, 61,167, 77,155, 54,
+116,232, 80,123,164, 73, 16,196,165,223,119,229,237, 95,188,248,213,117, 63,190,209,241, 90,137, 68, 83, 71,177, 4, 84,213,153,
+ 80, 64,228,162,215,222,158,244,196,211,118, 27,185,244,116,252,194,102,100,100,216,219, 16, 14,204,155,174,132,255,224, 72,211,
+ 5, 25,111,181, 7,243,166,165, 20,229, 73,161, 37,169,170, 86, 33,169,172, 74,165,248,254, 32, 33, 33,193, 96, 66,181, 90,130,
+166,165, 0, 12, 98, 13, 12, 93, 75,155,128,181,235,219,194,195, 65,235, 87,216,120, 46, 61, 34, 93,241,120, 10, 73,161,101, 37,
+ 57,207,172,137,104, 74,163, 66,146,112, 69, 46,143,228,233,185,183, 56,222, 75,127,121,144,223,235, 28,111, 98,224, 61,131,253,
+175,188,151,254,178,195, 11,254,234,171,175,126,251,237,183,170,170,177, 1, 1,217,158,129,189, 17, 66, 36, 73,242,120,226,139,
+138,192,178, 5, 65, 8, 6, 12, 0, 0,184,113, 3, 62,254,184,126,167, 74, 5, 18,137, 93, 95,144, 67,183,166,107,121,110,185,
+ 10,201,127,203, 47,189,244, 18,167, 28, 45, 73,144,255,224, 56,232, 31,246,114,114,192,194, 51, 60, 60,252,190,240,108,140,103,
+ 67,186,229, 93,185, 90,226,231, 71,146,228,139, 47,190,248,225,135, 31, 10, 63,239,112,163, 47, 98,235,158,123,103, 69,116,114,
+114,198, 59,239,112,145,137, 51,110, 92,174,239,141, 29, 57,114,224,192,129,194,194, 66,132, 16,118,109,241,243, 38,238, 70,100,
+100,100,164,166,166,198,196,196,156, 59,119, 14, 33, 52,111,222,188, 59,181, 54, 26,167,226,226,226,199, 31,127, 60, 60, 60,124,
+239,222,189, 56, 1, 9, 0,224, 36,154,227,199,143,231, 25,201, 65, 8, 21,228,158,127,115,233, 63, 2,162, 50,207,101,206,190,
+120,135, 40, 42,151, 0, 34,141, 38,179, 10, 5,204,127,246, 5,215,134,215, 93,136, 59,236, 20,111, 66, 75, 77,137,207,104, 64,
+131, 16, 67, 77,199, 52,184,223, 52, 53,191, 90, 92,116,186,178,244, 74, 97, 65,121,225,173,154, 91,197,181,119, 74,104,157,222,
+108,166,107, 25,147,142,161,141,136, 97, 0, 33, 71,101,193,141,167, 95,191, 9,139,223,134,197,111, 99,189, 73,174, 91,225, 74,
+ 36,124, 33, 45,115,252,242, 2,142, 37,241,182,229, 30, 75, 50,117, 32,213,213,155,113, 63, 29,255,181, 54,123, 14, 75,172,247,
+214, 95,191,183, 31, 0,190, 93,101, 94,186,240, 13, 0, 24,154,224,216,139,255,245,215, 95, 79, 25,241,155, 74,149,224,119, 34,
+123,195, 10, 64, 8,141, 24, 49,130,167,171, 14, 0,157, 58,119,138,140, 4,238,239,250,117,192, 65,133,162,162,208,198,141,224,
+239, 15,254,254,208,181, 43, 36,142,119,192,140,156,210,180,148, 96,248, 99, 51, 43, 45,207,111, 14, 28, 56, 96, 69,127,245, 29,
+157,245,235,249,103, 77, 37, 36, 36,112,201,212, 44,177,104,209,162, 70,194,179, 49,126,187, 90,244,143,103,231,231,124,253,245,
+171,175,190,218,148,175,241,121,179,179,179,109,242,194,136, 71, 58,127,250,201,199,113, 51,103,190,251,238,187, 54, 79,189,112,
+225,194,177, 99,199, 10,164,161, 77,155, 54, 17, 4,145,145,145,129, 16,194,237, 34,150,156, 56, 19, 95, 83,152,205,230, 61,123,
+246, 92,189,122,245,198,141, 27, 90,173,214,108, 54, 3,128,201,100,122,226,137, 39, 28,170, 49,163,209,152,179,107,166, 33,239,
+163,253,135,111, 22,222,165,106,180, 36,131,160, 68,235, 54,127,241, 10,135,182, 74,165, 18,207, 54, 75, 77, 77,197,109, 33,206,
+186,140, 16,194, 27,173,247, 30,145, 77, 43,147,101,247,196,178,251, 41,228,112,216, 55,228,238, 62,203,114, 76, 3, 28,165,208,
+146,202, 40, 6, 65,177,182,186, 72,163,170,168, 81,107, 12, 6,181, 73, 95, 97,212,223, 53,232, 74, 12,117, 42,179, 81,205,154,
+ 77, 22, 14,126,235,246,182,191,109,215,231,115,211, 61, 17,200, 16,200, 4,142,249,184,150, 66,203, 70, 87, 93, 48,111,242, 15,
+ 7,181, 18,142,101, 93,193, 27, 61,130,198, 63,249,134,148,251, 91,183, 99, 38, 1, 4,127, 53,125,124,216,225,217,139, 19,252,
+ 78,100, 19, 4,241,195,177, 81, 0,192, 51, 27,137, 67,183, 30,221, 45,200, 23,210,210, 32, 63, 31, 6, 12,128, 85,171, 16, 7,
+123,153,132, 57,213,201, 48, 12,195, 48,216,215,201, 52,192, 89,215,167,179,192,242,208, 74,235,189,244,210, 75, 4, 65,216, 83,
+142,156,234,177,201,185, 54,119,222,119,211,203,171, 9,210,243,191,175,189,237,185, 39,107,238,220,185, 92,228, 58,101, 84,239,
+151,226,134,184,187,187,143, 24, 49, 98,229,202,149, 89, 89, 89, 92, 70, 60, 14,159,148,228,221,237,245, 72, 72, 72, 8,203,178,
+ 54,105,215,230, 78,123, 15,154, 27,188,158, 55,111, 30, 52, 76,134,181,153, 92, 0,223,108,167, 78,157,138,138,138,142, 28, 57,
+210,181,107, 87,137, 68,130, 91,187, 65,131, 6, 9,145,135,145, 61, 98, 55,255,226,123,113,239, 27,195, 7,247,244, 80,144, 30,
+238,140,155,220,248,232,227,130, 60,132, 25, 25, 25, 28,179, 55,167,195,238,172,228,180,173, 58,173, 8, 20, 29, 72, 17,210,175,
+225,128,179, 86, 97,198,196,255, 58, 76,161,213,115,200, 16,218,211, 93,141,152,171, 90,245,101, 77,213,149,154,202, 43, 53,170,
+171, 90, 85,190, 78, 93,101, 52,212,209,116,169, 78,203,147, 12,107,202, 56, 98,253, 10,106,253, 10, 10, 1,133, 8,114,238, 12,
+226,249, 25,178,103,167,183,139,140, 12,102, 65, 10, 64, 8,225, 77,103, 83,104,113, 63,198, 44,217,148, 43, 51, 51, 51,133,100,
+146,193, 25, 49,151,231, 44,199, 76,138, 21,104,235, 97,201,180,111,126, 87,189,125,252, 74,253,128,245,183,171,204,131,252,234,
+211,199,191, 61,127, 79,122,250,102,158,215,105,195,235, 48,103,241, 88,223, 19, 89,163,223, 27, 73, 78,132, 67,135, 14, 9,172,
+ 18, 97, 97, 97,220,246,152, 49,224,235, 11, 17, 17,240,104,227, 49,191,248,254,253, 29,250, 58, 45,245, 38,222, 35, 68,117, 90,
+ 57, 43, 45, 70, 24, 4, 73,146, 3, 7, 14, 88, 69, 89,223,184,113,163,144,137,250, 92,171, 96,249,145,181,175, 0, 0,192, 68,
+ 16,172,206, 40,109, 31,166, 92,189,122,142,135,175,239,161,223,235, 59,242, 79,207,121,243,253,255,222, 88,255,205,191,162,199,
+ 76,243, 11, 63,176,123,119,211,166,253,137, 84,101,175,222,189,241, 16, 22,215,180,112,109,143,229, 71,155,221,243,212,212, 84,
+ 60, 10,132,157,155, 28, 75,198,196,196,224,161,152,121,243,230,217,147,156, 8, 33,169, 84,250,196, 19, 79,104, 52, 26,181, 90,
+237,230,230,214,174, 93, 59, 95, 95, 95, 33, 57, 57, 16, 66,114,185,124,106,234,135, 91, 79,199,223,186, 83, 19,236, 67, 13,238,
+ 78,244, 9, 71, 30,222,222,208,182, 33,225,161,243, 70, 46, 3, 97,170,211, 50,133,150,191,127, 38, 8, 75,161, 85,215,183,171,
+ 46, 47, 79, 71, 27,107,180,186,155,102,179,148, 5, 4,160, 49, 27, 88,132, 16,192,222,242, 66, 45,109,142,136,136,160,236,214,
+ 58, 98,241,219,247,171,197,250, 21, 0,192, 50, 96,188,150, 95,251,233,246, 26,129,188, 9, 78,166,208,138,136,136,128,181,211,
+108, 22, 11,166, 81,135,142,206,200,229,145, 54, 51, 98, 66,107, 78,102,143, 26, 83, 3, 59, 16, 22,158,216,227,185,116,225, 27,
+199,175,244,122,127,199,204,215, 62,158,152,145,206,119,193,179, 23, 39, 52,204,195, 63, 4, 0, 42, 85, 2, 66,153, 4, 65, 0,
+160,204, 76,190,233, 80, 83,146,167, 30,216,255, 11, 0,204,156, 9,163, 71,215,215, 41,132,208,158, 61, 48,105, 18, 0,192,192,
+193,131,122, 69,247, 22,226,235,116,118, 58, 39,247, 8,148, 74, 37, 73,146,150,204,149,158,158, 33,100, 62, 60,118, 14,114, 30,
+ 79,172, 64,249, 37, 39, 88,140,139, 90,142,149, 59, 76, 16, 75, 16, 4, 93, 91, 43, 13,244,167,220, 61,123, 77, 77,254,247,184,
+196,215,240, 4,163,216,126,140,222, 32, 13, 8,142, 30, 52,170, 75,104,248,135,215,126,239,221,187,247,221,211,141,242,187,164,
+ 42,149, 88, 37,188,144,154,138,231, 48,209, 22,101, 37,145, 80,128,238, 79,123,154,216, 88, 94,197,196,196,224,142, 57,214,110,
+ 86, 29,243,152,152, 24, 30,222,196,151,237,235,235, 59,104,208,160,235,215,175,159, 61,123,150, 97, 24, 15, 15, 15,157, 78, 39,
+208, 41, 25, 28, 28,252,248,227,143,159, 56,122,106, 99,230, 1,111, 66,214, 61,216,152, 95,233, 49,172,187,153,227, 86,123,142,
+ 75,130, 32,184, 23,150,103,168,189, 53, 36, 39, 56,156, 18,127,127, 90,169,128,153, 73,205, 73,161, 21,144, 60,161,234,203, 93,
+ 26,146, 45, 51,212,129,217,204, 32, 68, 0, 92,171,171, 46,209,213,112, 41,180,236, 59, 61,208,220, 25,196,230,109,136,243,117,
+246,136,164, 41,208, 58,197,155,224,124, 10,173,101,203,150,173, 93, 59, 13,224, 12,199,152,241,203, 11, 48,111,198,199,199, 59,
+148,156, 46,103,196, 84,169, 18, 0,212,137,137,155,155,250,100,241, 87, 74, 37, 95,106,182,119,230,239, 89,241,241,228,223,119,
+160,193,254, 87,240,188,206, 19,234,213, 4, 16,111,207,255, 17,136, 82,158,243,250,251,103, 17, 4, 49,101,202,148, 45, 91,106,
+112,101, 38, 26,198,122,241, 2, 39,140, 31,143, 12,110,106, 59,255,197,127,126,252,225, 71, 99,198,128,229,245, 78,152, 0,255,
+250, 23,236, 63, 48,104, 12,239,220, 53,220,251, 75, 78, 78,222,190,125,187,205,233,241, 2, 57, 20, 79,137,183,244,157,165,103,
+100,240,204,238,180,124, 34, 27, 55,110,196,212,185, 97,195, 6, 33,146,211,181,241, 10,133, 66, 81,118,251, 86,120,100, 20, 75,
+ 27, 9,154,145,120,121,123,245,139,247,140,237,207,106,105, 70,103, 68, 52, 3, 12,187,108,211,251,211,103, 78,111, 42,232,232,
+109,126, 60, 71,182,250,246,241, 31,173,127, 48,111,222,188,244,244,116,252, 10,112,249,136, 44,217,147,255, 6,187,119,239,254,
+209, 71, 31, 85, 84, 84, 36, 38, 38,158, 57,115, 70,167,211,197,196,196, 56,204, 64,131,109, 7, 13, 28,152,250,108,106, 97,113,
+225,223,158, 77, 61,121,224,243,187,181,170,248,145,137,193,161,221,172,196,169, 77,197,202, 17, 84,211,153,240, 66,166,196,183,
+138,234,180,217,116, 11,228, 77,112, 62,133, 22, 16,208,237,111, 83, 75, 50,182,130,155, 66,141,104, 19, 77,179,136, 13,240,241,
+ 41,214,106,184,117, 53, 44, 97,111,128, 8,217,242,117, 50, 78,241, 38, 56,191,134, 18,207, 3,197, 44,137,253, 9,150,188,233,
+240, 80, 46,103,196,180, 52,111, 82,200,142, 36, 43, 1,129,189,239,101,108,250, 52,247,160, 98, 93,230, 83,191,239, 0, 2,136,
+ 37,211,190,233, 62,138,101,201, 82,135,117, 32, 37, 37, 19,160, 6, 0, 16, 2, 43, 78,216,186, 46, 27, 0, 60, 58,167, 3,216,
+ 8,181,208, 43,186,247,127,182,100, 4, 6,253, 2,240, 45,247,218,212,214,118,139,141,235, 29, 28,154,200,207, 47,246, 84, 39,
+231,232, 20, 56,194,158,158,158,158,154,154,106,149, 20,215, 33,111, 90,122, 60,241, 11,236, 80,114,186,140, 49, 99,198,204,223,
+177,249,223,181,213, 49, 35,135,145,193,126, 8, 33, 48, 35, 96, 17,128,148,160, 36,132,140,218,146,190,222,123,108,124,100,100,
+100,139,207, 6,199, 29,243, 77,155, 54,165,166,166,246,237,219,215, 41,219,155, 55,111,102,103,103, 83, 20, 53,124,248,112,146,
+ 36,173, 92,156, 12,195, 16, 4, 97, 47, 23,241,217,179,103,191,216,250,185,140,146, 39, 63,149, 76,146,228,176, 9,207, 53, 98,
+124,154,198,182,205,201,212,251, 48,169,211, 5,122,117, 45,133,214,104,229,156,130,155, 5,103,127,222,175, 53,154,104,134,137,
+ 28,208, 47,169,243, 83, 14, 57,200,229, 32, 29,152,251, 92, 75,161,197, 29, 1,207,100,138,143,143,231,248, 87,200,245, 52, 39,
+ 35,166, 82,233,103,239,174,149,202, 44,199,222, 37,210, 12, 0,221, 18, 76, 25, 9,220, 17,106, 88, 97,167,222,186, 46, 27,128,
+152,189,184, 62, 34, 3,174,207, 91,215,101,123,116, 78,247,232,156,226,208,188,180,124,220,166,255,142, 35,224,142,143,183, 6,
+ 0,240,226, 75,135, 47,133,107,115,143,120,216,211, 5, 67,206,227,233,148,228,228, 81, 76,182,125, 56,145,145,237, 95,124,113,
+227, 47,191, 20,188,245,125,138, 52,192,183, 83, 59,131, 86,175,215,209, 47, 45,121,149,114,247,223,251,121,198,133, 64, 98,156,
+ 51,139,208, 25,134, 22,226,235, 23,216, 49,183,119,119,121,121,121, 8,161, 30, 61,122, 84, 85, 85, 73, 36, 18,154,166, 3, 2,
+ 2,160, 33, 34,137, 76, 38, 3, 0,155,212,137, 16, 58,117,234, 20, 75, 19, 67,134,246, 45, 46, 46,150,201,100, 38,147, 41, 52,
+ 52, 20,127,165,209,104, 20, 10, 5, 65, 16,114,185,156, 71,177, 97, 86,181,220,112,170,195,238, 90,111,189, 37,169,179,197,232,
+ 44, 50, 34, 98,193, 60,171,157,102,163,129,148, 72, 91,240, 21,178,228, 62,215, 82,104, 53, 37, 80, 23,206,235,218,233,120,174,
+182,181,163,126,120,116, 78, 7, 0,171, 94, 50, 63,105,218,242, 80,119,170,173,238, 4, 0, 66, 30,103, 98, 98, 34,207,108, 30,
+129,111,183, 37,125,184, 22, 12,162,176,176,208,161,167,146,223,233, 41,144,134,220,221,221,167, 76,153,130, 3,199, 21, 53, 4,
+142, 59,150,125, 0, 7,142, 27, 59,104,172, 61,219, 45,234,119,159,247,123,181,209, 46,222, 72, 75,246,216,211,133,123,236,223,
+191, 63,158,194,201,178,172,201,100, 2,128,138,138, 10, 0,240,244,244, 4, 0,188,199, 42,170, 33,119,191,147, 38, 77,194, 63,
+ 96, 89,214, 96, 48, 0, 64, 81, 81, 17, 0,224, 25, 23,120,143, 76, 38,179,169, 58, 31,110, 96, 51, 49,173,155, 8, 17, 34, 68,
+ 56, 13, 49, 74,188, 8, 17, 34, 68,136,212, 41, 66,132, 8, 17, 34,117,138, 16, 33, 66, 68, 27,132, 68, 44,130, 63, 10, 98, 5,
+135,195,226,112, 78,116,100,139, 16,209,218,212,249, 71, 76, 85,214, 47, 52, 87, 65, 92,147,144,165, 36,232, 8, 32, 16, 80, 44,
+200, 0,128, 64, 8, 17, 8,175,194,164,192,244,202,219,106,104, 50,255,224,143,120,191,161,206, 12, 41, 22, 55,158,156, 33,166,
+192, 19,109, 69, 91, 81,117,214,227,223,107,118, 60, 63, 67,214, 51,210,124,253, 38,194, 51,225,215,175, 32, 23,191,125,127, 58,
+204,186,215, 73, 2, 53, 90,107,100, 3, 8,153,202,110,105, 76, 44,139, 16, 34, 72,223,224,142, 66,214,222, 90,194,203,203,171,
+182,182,214, 80,153,167, 8,236, 38,182,198, 14,113, 45,247,172,201,160,235,219,119,152, 83, 86, 54,167,233, 9,156,158,210, 28,
+ 91,140,240,240,112, 60, 71, 10,199,109,115,234,202, 45, 99,223,184, 54,195, 73,196, 31,160,195,254,249, 23,159,240, 27,204,126,
+230, 89,123, 95, 53,199,214,101,108,217,102, 90,191,194, 50, 80,252,125,222,156, 59,131, 32, 16, 2, 64, 61, 34, 97,253, 10, 56,
+120,219,206, 33,104, 83,210,249,255,156,170,100, 74,244,236, 61, 19,113, 91,230, 43,141,140,123,100,200, 88,133,155,155,144, 11,
+216,115,232,250,238,255, 72,192,104, 2,160, 65,126,245,248,113,253,153, 43, 94, 10, 31,231, 56,212,112, 47, 79, 17,244,231,167,
+221,139, 23,178,186,132, 26,163, 35, 17,203, 50,154,138,109, 37,229,100,157,177, 67,124,220,112,129,230,154,138,255, 82, 84,253,
+226,218,252,141,203, 99,254,109, 18,126,106, 75,190,219,181,107,215,146, 37, 75,156,186,242,196,196,196,133, 11, 23, 18, 4,177,
+ 97,195, 6, 23,232,207,197,148,112,127, 13,240,135, 85,195,226,102,243,150, 45,246, 90, 68,110,202, 39, 94,237,206,173,121,231,
+226, 91, 63,156,180,110, 45, 8, 18, 90,126, 41,213,186, 21,114, 2,140, 0,128, 83, 96, 2, 0, 0, 53,188, 63,151, 20, 19, 89,
+ 38,197,156,100, 39,212, 52, 5,108,120,160,103,173,174,130,162, 25,130, 70, 76,173,190,236,196,143,251, 47,156, 24, 62,123,145,
+127, 64, 0,255, 5,124,249,107, 41,209,229, 49,128,189, 64,146, 32,117, 7, 74, 50,100,148,103,244, 35,101,159,125,127, 91,225,
+ 30,230,152, 49,213,121,241,221,107,135, 12,116, 3, 35, 13,112,117,200,198,254,129,149, 57,147, 70,244,120, 96, 15,133, 39,182,
+ 2, 15,206,159,203,146, 75, 84, 18,210,100, 48, 48, 26,173,219,176, 17,142,227,131, 93,189,126,214, 75, 81, 53,102,168,188, 75,
+ 88,164,183,183,143,153,166, 43, 42, 42,131,139,238,220,184, 89,112,252,152,106,200,208,199,133,156,151,162,106,152,252,183, 93,
+190, 89,151, 87,190,226,184,197,220, 26,118,158, 88,197,109, 13, 89, 89, 89,187,118,237,106,180,108,191,117,120, 4,215,166,250,
+116, 54,206,154, 21,125, 75,156,124,174,161, 66, 66, 67, 0,254,251, 71,122, 46, 93, 59, 96,250, 71, 54, 27,164,159,127,254, 25,
+111, 39, 37, 37,237,219,183,207,230,182, 99,245, 99, 49,138, 32,124,158,187,109,234, 60,118,244,228,208, 97, 3, 91,182, 92, 89,
+ 71,209,218, 5, 70,237,110,116, 76,130,188,145, 15, 61, 34,155,155, 20,243, 86,113,233,158, 50, 40,214, 1,141,192,147, 4,137,
+148,146,213, 85, 28,218,190,229,137,212,165,246,214,222, 2,192,182,239, 14, 18, 49, 74,188,206, 12,140, 38, 96, 89,144, 48, 64,
+146, 94,126,254, 83, 71,221,219,181,223,168,240,227, 19,146, 6,237,237,191, 63, 86,237, 21,220, 30, 24, 22,128, 6, 51,237, 22,
+ 28,174,241, 15,249,242,200,161,167,135,119,124, 48,175,150,179,188,121,249,234, 89,100,188, 21,214,193,224,227, 45, 39, 73,119,
+189,158,174, 82,233, 15,103,109, 84,120,247, 27, 56, 96, 4,143,161,130,170,232, 22,142,122,245,234,121,183, 76,157,115,238,108,
+ 93,157,214,199,199, 43, 34, 34,140,164,164, 12, 83,116,238,252,209,216,152, 97,109,150,128, 18, 19, 19,185,224,193, 11, 23, 46,
+220,176, 97,195, 22, 91, 34, 72, 72, 67,245,128,175, 28,175, 46,219,185,115,103,107,167, 50,231, 4, 96, 70, 70,186,179,231, 33,
+195,166, 98, 91,102,187, 47,167, 32, 31, 88,121, 90, 37, 35, 18,190, 46,211,174,234, 60,118,244, 36, 0, 56, 75,160, 71, 95,188,
+ 97,115,255,176, 15,163,132,151, 5,126,159,133, 16,232, 43,171,245, 0,176,126,133,227,164,152, 61, 34, 9,123, 29,118, 51, 41,
+ 77,239, 56,181,212,151, 5,146,242, 2, 99,183,130,131, 69, 42, 93, 53, 73,105, 74, 11,239,220,185, 21, 22,102,123,185,228,233,
+156,156, 74,223,254, 65, 82,169, 84, 38,125, 98,243, 12,227,182, 39,241,254, 57,243, 6, 79,159,220, 46,164,189, 34, 50, 80, 93,
+ 98, 63, 2,137,161, 42,111,234,104,141,151,159, 63, 24,140,192,178, 64, 51, 96,166,101,114, 25, 73,128, 41,106,228,182, 31, 50,
+102, 60, 62,166, 13,146,136, 81, 91, 18, 30,162, 15, 12,240, 8, 13,105,239,238,225,126,251,118, 9,195,176, 33, 29,189,174, 92,
+251,253,188,155, 71, 76,180,237,192,172,151, 46, 29,237,211,205,212,185,115,248,213,107,183,115,114,174, 85, 84,214, 34, 4,126,
+126,110, 58, 93, 93,108,108,175,234,106, 77, 73,206,185, 11,151,220,250, 70,199,181,193, 91,182, 74,149,225, 48, 73,134,101, 63,
+212, 74,212, 19, 4,193,117, 78, 93,232,245,191,245,214, 91,147, 39, 79,118,118,173,100, 66, 66, 2, 65, 16, 59,118,236,224, 17,
+ 1, 92, 14,222,251, 29,139,243,231,113, 40,144,216,216, 88, 43,138,108, 74, 43, 92, 88, 0,132,144, 82,153,234,148,176,181,180,
+165,166, 87,179,219,125, 31,202, 83,230,110,170, 89,105,221,172, 8, 20,115,168, 64,216,164, 72,129,188,137,113,248,240,225,146,
+146,146,146,146, 18,167,162, 69, 53, 77,138,137, 27,174,245, 43,136,117,175, 19, 61, 34, 9, 4, 82,187, 69, 64, 73,162, 6,142,
+ 27, 57, 58,105,228,200,196,216, 17, 19, 60, 31,123,105, 84, 0, 2, 96, 37, 4, 92,190,100,247,222,243,111, 22,122, 5,132, 74,
+101, 18,153,148, 2, 0,249,140,111,241,223,229,139, 5, 96, 48,128,193, 16,211, 89,195,115,193,145,126,234,144, 96, 5,232, 13,
+213,247,106,182,126,117,161,123,255,143,183,108, 62,105,214,106,164, 50,169, 84, 42,173, 12,236,127,186,121,113,149,156,194,185,
+115,231,184,252, 4,252,146, 83, 33,185,235,230, 38, 85,200,101,225,225, 93,226, 7, 12,240,243,243,147, 72, 40,153,140,242,247,
+ 83,148,220,185,101,183,125, 70, 37, 94,158,110, 58, 61,125,249,242,141,210, 50, 77, 81,113, 77, 94,129,233,110, 89,109, 69, 69,
+245,141,188,130,174,145,145, 33, 29,189,171, 42,138,218,172,228,180,138, 18,207,159, 36,163, 81,213, 34, 73,123, 41,225, 92, 19,
+173,155, 54,109,226, 79, 75,217, 20,217,217,217,153,153,153, 56,178, 23,143, 76,179, 76,223,102,153,152,200,242,116,246, 78,141,
+ 15,139,227,201,187,166,196,119, 44,242,176,253, 45, 0,127,248,146,164,164,164, 71, 31,125, 20,247,202,241, 6,222, 78,106,128,
+ 16,201,105,217, 24, 76,122,122,165, 43,105,221, 90, 86,129,186,140, 27, 55,110, 0, 64, 73, 73, 73, 72, 72,136,176,206, 59,177,
+126, 5,186,126,243, 62,129, 54, 78,138,137,247,155, 38, 61, 45,164, 3, 75, 34,239,160,238, 1, 10,162,200,192, 0,232,245,181,
+246,126, 89, 92, 84,212,161, 23, 41,161, 36, 20, 37,101, 24, 51,183,113, 87, 65, 17, 0, 0, 32, 0, 73, 68, 65, 84,255,206,205,
+ 90,208, 27, 0,144, 55,226, 27,196,136,233,160, 1, 61, 9, 64,220,204,171,120,239,211,219, 35,166,204,169,233,216, 83,118,183,
+ 76,234,227,143, 88,198,171, 93,104,254,249,253,253,227,226, 90,137, 40, 45,165,196,185,115,231, 4,202, 4,181,234, 94,160, 23,
+ 65, 51,172,201, 76, 87, 84,170,164, 50,133,209,104, 54,211, 12, 77,179, 52,131,170,213,149,246, 12,101, 82,173,194, 45,180,170,
+ 74, 83, 83,171, 83,169,245,222, 1,125,135,244,233,115,234,216,190,142, 38, 90, 83,163,233,222, 61, 82, 46,147,104,107, 85,109,
+ 83,114, 90, 38, 4,198,216,184,113,163, 64,143, 39,206,189,222,116, 39,127, 79,147, 11,126,154,154,234, 63,118,236,253,120, 31,
+ 37, 37, 37, 0,176,123,247,238,202,202, 74,129,113, 94,178,178,178, 48,111,226,223,239,218,181,203, 30,127,113, 9, 42,160, 33,
+ 49, 17, 14,223,137,227, 31,115,126, 82,123,188,143, 67, 46,205,155, 55, 15,107, 85,155, 55,104,239, 93, 78, 73, 73, 73, 30,156,
+181, 29, 96,250, 6, 45, 57,189,218,166,237, 0, 59,217, 0, 44,125,154,246,252,158,173, 84, 55, 90,126, 53,145,149,198,116, 74,
+114,106, 52, 26, 75, 2,221,184,113,163, 67, 41,244,252, 12, 10, 0, 45,126, 27, 54,111,131,245, 43,234,255,122,220, 79,249, 67,
+244,136,116,212,200, 35,228,165,175,242,214, 87,186,105,171, 60,180, 21,221,203,115,206, 85, 25,170, 89,130, 6,240,105,207, 51,
+119, 12, 49,198, 90,138, 34, 41,201,253, 50,140, 58, 52,119,194,232,112,172, 58, 11, 74,229, 60,231,244, 70, 38,208, 25, 64,111,
+ 40,190, 81, 30, 28,210,169, 71,207,158, 0,224, 43,161, 37, 18,137,132,146, 80, 20, 89, 92, 84,212, 74,188,105, 41, 37,240, 71,
+252, 62, 56, 84, 13, 12, 3, 90,157, 89,171, 53,213,212, 24,203,203,213,165,165,149,181,181,198,186, 58,115, 93,157, 73,171, 53,
+107,170,237,170,108,163,145, 54, 24, 24,179,217,228,229, 37,235, 20,226,237,238,225, 1, 0, 17,145, 93, 66, 59,122,251,120, 43,
+ 16, 98,204, 52,107, 52,106,219,166,228,180, 74, 8,204,209,159, 67,225,217, 52, 51, 7,198,134, 13, 27, 28, 70,179,182,232,255,
+222, 7,126, 76, 37, 37, 37,153,153,153, 66,250,100,217,217,217, 59,119,238,228,120, 51, 33, 33, 33, 57, 57,217, 30,241, 17, 4,
+209, 52,193, 6,174, 18,220,126,132,144,163,144,125,200,202,237,102,233,172,176,103, 19, 24, 24, 72, 52,104, 75,103,109, 91, 10,
+123,190,124, 11,255, 9, 55, 17,164, 58, 31,152,222,108,120, 69, 25,129,241,229,158,159, 46,239, 25,105,186,222,144,139,119,241,
+219,245, 41,133, 27, 20, 40,238,179, 83,235, 86, 16, 12,120,254,102,199,215,201,210,230,110,199, 51,228, 4, 91, 97, 34,129,161,
+239,220, 45,249,111, 9, 41, 5,164,161,136,129,177,118,231,205,132,134,134,252,246,197, 43, 19,150,127, 71, 42, 20,222,222, 62,
+ 95,244,122, 9,144, 17,134,117, 4,130, 0,163, 1, 88, 56,125,213, 11,186,218,189,242,130, 50,121,223, 64, 3, 0, 49,190,127,
+112, 96,213,141, 28, 67,105,164,127,213,209,208,101, 82,138,161, 40,146, 49,212,186,144, 3, 89, 8,176,222,196,210,192,114,222,
+ 6, 78, 24,203,111,235,231,223,174,180,240,178, 92, 70,153,204,172,193, 88,124,167,184, 74,165,174, 81,169,116, 85, 42,125,149,
+ 74,239,235,223,197,158, 97,121, 37, 42, 43,175,236,217, 51,178, 90,173,150, 74,200,154,218, 98,109, 53,251, 72, 87,109,112,187,
+118,238,238,238,114,185,219,221,178, 90,130,242,107,155, 29,118,155,137,216,176,199,147,223, 16,107, 82,171, 92,196, 2,243,115,
+112,152, 54,109, 26,167,194,112, 84, 89,130, 32,166, 78,157,154,152,152,200, 63,205,219, 74,111, 98, 88,106,216, 70,125, 32, 59,
+ 9, 54,240,254, 77,155, 54,225,236,105,120,255, 29, 91,231,221,180,105,211, 11, 47,204,195,113,163,231,205,155,199, 5,250, 75,
+ 79, 79,199,215,207,195,185,155, 54,109,250,120,180,223,244,141, 58,171,158,251,244,141, 58,108,251,143,209,210,214,230, 77,203,
+237,150,233,176,187, 70,154,195, 62,140,194,227, 69, 78, 73, 78, 14,150,188,153,148,148,196, 19, 91,190, 71, 87, 22, 79,219, 28,
+222, 31,142,156,182,225,250,124,110,186, 39, 2, 6, 1, 65, 34,187,250, 26,177,204, 15,151,138,170,204,200, 64,131,150, 1, 21,
+ 77, 34, 64,149,122,212, 61,105,178,183,167,151, 93, 14,234, 23, 91, 92, 92, 92,122,229,215, 46,253,146,100, 50, 57, 24, 77, 64,
+146,192,152,112,235,185,251, 55, 19,219,117, 18,207, 61,158,206,147,245,141,172, 5, 2, 20, 36, 49,244,209,136,161,230, 11, 64,
+200,183,151, 75, 77, 38,150, 49,212,157,248,239, 43, 35, 6,246,109,165,138,130,131,129,227, 60,177,184, 61, 23,194,155, 0,208,
+ 55, 58,238,218,229, 28, 84, 82,163,211,155,213,114, 3, 2,181,193, 64,215,212, 24,239, 85,234, 74,239,214, 13, 31,109,119, 50,
+150,222, 20, 88, 80, 88, 17, 17,222, 57, 60, 60,180,170,170,210,207,151,137,138,242, 9,106, 23,161,112,115,171,174,174,203, 57,
+123,189,184,164,166,125,104,175,182, 67,151, 8,128, 32, 0, 83, 22,199, 92, 54,231,102,218,104,223, 44,230,213,224, 92,196,150,
+212,185,126,253,250, 95,126,249,197,158, 45,126, 34, 56,148, 53, 78,250,100, 73,118,152, 58,147,147,147,121,122,235, 22,157,253,
+108,167,226,118,219, 75,176,129,247, 59,204,136,137, 16,250,207,127, 54, 97, 79,110, 76, 76, 95,206, 65,217,160, 34,237, 70, 2,
+197,182,228, 52, 53,182, 77, 25, 44,231, 10,102,218, 6, 45, 56,138,132,157,148,148,196, 77, 30,120,244,209, 71,185,167,227, 84,
+ 63,125,238,178, 53,247,169, 99,237,114,129,236, 41,105, 35, 74, 19, 99,198,140, 25, 78,253,158,104,112,104, 78, 25, 71, 76, 25,
+ 71,214, 87, 71, 2,205,157,129, 16, 72, 89,228, 19, 25,233,205, 66, 5, 1, 12,107,127,194, 25, 2, 66,195, 82,149,102,150,102,
+ 81,141, 25,213,154, 89, 19, 37,137, 24, 61,118,228,136, 71,121, 78,221,163, 91,247,187,241,165,103,206,124,149, 87, 83,217,117,
+240,147,208, 21,192,100, 2, 32,206, 23,212,158, 43,244, 48, 71,205,228,191,114,182,199,200,221,135,182, 61, 54, 88, 86,255, 14,
+ 33, 18, 88, 19, 0,152,245,181,165, 23,127,141, 8, 9,136,237, 23,219, 74,133,140, 83, 41, 96,189,137,187, 96,194, 7,109, 67,
+195,186,159, 57,177, 63, 40,208,221,221, 93, 2, 0, 70, 35, 83, 83,107, 82,169,245,157,194,123, 13, 27, 50,210,158,213,132, 9,
+ 83,127,249,249,179, 19,167,174, 12, 31,218, 55, 44, 44,204,108, 50,196,198,244,241,240,241,185, 93, 80, 84, 82, 90,125,236,247,
+107,234, 90,159, 41,131, 71,182, 29,234,156, 87,159, 44,147,152,167, 84, 98, 42,100, 45, 24,147, 36, 9,158, 20,105,169, 74,165,
+ 69,108,101,130,101, 89, 78,120,226, 44,196, 73, 73,227, 27,232, 25, 38,206, 90,217,180,103,106,143,239, 8,130,224,231, 77, 75,
+ 36, 39, 39,219,211,152, 60,181,162,105,130, 13,110, 63, 79, 0,121,142,115,113,226, 76,203,129, 29,135, 94, 32, 75,219, 29,139,
+ 60, 45, 27, 20,238,227,254, 11,102,123, 5, 98,233,223,124,192,190, 78,219,212, 57,100,232,128,102,250, 23, 92,211,155,220, 13,
+ 11,196,181,155,168,103,189, 91,211, 65, 82,204, 97,253,205,190,221,237, 81, 39, 50, 48, 64,179, 8, 33, 36,235, 24,213,177,125,
+ 88,239,254,131, 67, 59, 58, 94, 33, 59,122,212,104, 79, 79,207, 67,191,238,251,225,224,231,240, 83,125, 62,150,205, 23, 99, 98,
+250,245, 23,114,241,101, 97, 51, 62, 59,240,117,108, 39,109, 76, 23, 47, 64,168,186,206, 92, 91, 81,148,127,244, 91,195,245,253,
+241,241,113, 61,186,117,111, 61,106,136,141,141, 77, 77, 77,197,217,162,172,102,159, 56,120,172, 67, 70, 2, 64,222,245,171,165,
+ 5,183, 73,146, 96, 24,164,112,243,239,214,179,247,148, 39, 28,100,215, 8, 10,233,115,226,212, 62,131,129,142,238, 29, 17,210,
+ 49,176,232, 78,185,250,210,205,220,188,162,236,131, 23,111,151,160,231,158,255,167,192, 11, 40,220, 83,235,242, 93,223,186,117,
+ 75,224, 47,217,237,126,194,191,157,188,155,215,246,230,103,156,240,220,184,113, 35, 20,108,181,252,129,149,173, 77, 17,106,201,
+ 50,206, 9, 11, 39, 95, 97,123, 9, 54,132, 36,222,224, 40,210,234,103, 66, 90,101,246,246,174,157, 27,159, 1,128,148,193,141,
+ 58,230,220, 71,123,212,249,112, 87,103, 73, 90,164,208, 91, 4, 46,132,203,223,178,141,105, 32, 74, 7, 73, 49,143,158, 54, 77,
+178,203, 69, 68,173,137, 54,209, 80,110,130,105, 79, 61,239,237,237, 35,252, 2,250,199,247,239, 31,223,255,244,153,211, 0,245,
+158, 84,129,188,137, 97,238, 53,115,243,217,211,212,241, 43,213, 21,249,103,202,125,114,139, 30,143,236, 20, 60,106,244,168,254,
+241,253, 91,187,180, 99, 99, 99, 93, 91, 88, 50,108,200,200, 97, 67, 70,158,191,148, 83, 94, 86,238,225,225,193, 35, 54, 27,189,
+ 66,125,226, 98,250,196,125,245,101,198,213,220,147, 29,130, 61, 21, 10,105, 93,157,169,228,110, 13, 33,233,244,220,243,207, 8,
+ 60,181,167,255, 98,151,239, 23, 79,207,124, 8, 56,251, 50, 68,254,253,254,244,166,156,197,173,199,125, 0,144,154,234,223, 64,
+184,174,208,138, 61,166,115,200,128,174,101,230,224,110,211,178,159,254,224,177,121,237,114,203, 62,187,139,212,217,156,101,230,
+173,177, 68, 93, 8,174,223, 36,123, 68, 66,143, 72, 52,183,161,187,223, 48,194,206,206,157, 46,217,188,157,118, 80, 4, 50,185,
+193, 47, 84, 91,107, 0, 15,228,238,238,238,194, 5,244,143,239,223,243,133, 67,241,161, 26,223,128,174,209, 78,230,209,137,233,
+215, 31,160, 63, 0, 12, 7, 56,125,230,244, 3, 32,205,150,233,245, 71,199, 65,180,211, 86,179,158, 86, 30, 61,126,184,162,170,
+ 66, 95,166, 83, 40, 2, 66,195,251, 8,100, 94,104, 94, 34,154, 22, 73, 98,131, 16, 11,174, 45, 38, 46,216, 90, 63,212, 94,240,
+121,107, 63, 23,167, 58,233,109, 4,227, 38, 77,119,168, 31, 7,180,142,175,115,210,211, 43,241, 24,209,230,181,203, 45,119,186,
+174, 58,255, 88, 64,245,119, 65, 91, 46, 90, 95,191, 2, 0,168,168,174, 10,128, 58,135,141, 94,210, 11,205,141,107,185,104,201,
+ 43,205,191,145, 63, 10,111, 54,203,147, 51,100,100,219,191,200,205,234, 53,115,253,150, 55,218,149,233,239,186,109,206, 98,167,
+196,230, 95, 13,201,243,211, 30, 98,139,200,177,167, 83,188, 9, 98, 90,183, 63, 16,196, 80,199, 34, 68,180, 29,136, 81,226,255,
+ 48, 16,121, 80,132,136,182, 3, 49, 55,145, 8, 17, 34, 68,136,212, 41, 66,132, 8, 17, 34,117,138, 16, 33, 66, 68, 27,196,195,
+ 79,235, 54,114, 64,136,189, 95,106, 85,101,120,195,195,191, 61,222, 56,124,170,196,242, 7,198,118,193,246,108, 15,108, 88,128,
+ 55, 18, 23,213,143,223,201, 43,202, 5,158,183, 41,132,159,183, 41,172,206, 27, 31,107, 55,140,113,101,225, 21,188, 17, 24, 94,
+191, 42,241,204,185,210,150,186,223,164, 3,182, 3, 68,250,116,236,248,183,134,128, 99,105,193,245,199,223,151, 56,183,165,158,
+175,165,109,110,110,174,101, 68,140, 69,139, 22,117,239,222,189,149,234,149,104,219, 34,182,151, 46, 93,194, 27,209,209,209,206,
+218, 54, 13, 94,254,151, 72,235,134,195, 7,224,109,167, 22,195, 54,211, 86,171, 42,243,240,111,143, 73,179,125,167, 46, 0, 80,
+102, 63, 16,100, 83,250, 72, 92,148,134, 73,228,227,221,167, 0, 96,254, 99, 3,218,120,219, 85, 89,120, 37, 48,188, 23, 38,205,
+ 94,241, 67, 1,224,202,153, 99,173,125,191, 63,214,213,237,215,106,199,123,120,236,215,106,161,188,252,212,178,165, 0, 48, 96,
+237,123,173,122,167,135, 14, 29,218,182,109,155,193, 96,224,246, 40, 20,138, 25, 51,102,140, 26, 53, 74,148, 48,109, 10,151, 46,
+ 93,138,142,142,198,164,233,108,157,196, 17, 39, 48,105, 58, 85, 39, 45, 99, 65,185, 54,235,200,133, 52, 19,173, 66,157,153,153,
+153,158, 61, 83,184,109,167,232, 47, 51, 51, 51,197,163,157,179,182,152, 46,221,124, 2,180,170, 50, 76,154, 54, 21, 40,143,230,
+ 26, 48,107,249,129, 13, 11,240, 3,107,250,173,205,105, 88,150,135,197,169, 50, 16, 66, 44,203, 2, 0,195, 48,248,122, 72, 74,
+202, 47,244, 0,160, 67, 80, 48, 0,152,106,170,141, 52, 13, 0,117, 52,131,175,199, 39, 40,148, 95, 99,250,116,140,172, 44,188,
+130, 43,168, 45, 5,234,215,178,247, 11, 0, 11,202,203, 1, 0,243, 38, 38, 77, 0,200,253,229,128,229,183,147,120,159,148,198,
+163,178,202,179,162,186, 42, 63,200,183,103,104,101, 87, 33, 15, 55, 55, 55,119,251,246,237,150,188, 9, 0, 6,131,193,205,205,
+173, 67,135, 14, 86,218, 83,196, 67, 36, 77, 92, 39, 47, 93,186,212,180, 78, 54, 40, 80, 63, 30,230, 26, 48,107,185, 82,169,108,
+ 90, 39,241,183,246,234,164, 82,169,220,180,245,155,251, 31,231, 60,229, 44,253, 89, 50, 47, 79,192,160, 86,167, 78,165, 82,201,
+241, 38, 0,120,246, 76, 17,126, 53, 74,165,146,227, 77, 0, 72,241,104, 39,196, 86,171, 42,115,243, 9,240,241,246, 2, 0,252,
+175,213,183,237, 59,117,177, 39, 63, 15,108, 88, 48, 96,214,242,217,211,159, 4, 0,252,175,213,183, 31,239, 62,229,176,233,163,
+ 40, 42, 52, 52,148,162, 40,147,201,164,213,106, 25,134, 81,171,213, 2, 11,209, 83, 66,125,186,241, 59,185, 15,148,223,130,211,
+117, 37, 21,101,249,255,219,240,170, 67,177,233,211, 49, 50,180, 99,123, 0,192,255,218,236,185,187,118,191, 60,171,240, 22,148,
+151,143,247,240,120,107,193,124, 0,120,171,129, 52,191,204,203,187,207,155,142,150,240,221, 66, 71, 96, 64,201,140,206, 79, 27,
+217,174,114, 22, 93,171,204, 62,119, 32,183, 43,251, 2,255,253,110,216,176, 65,175,215,111,221,186,117,206,156, 57,120, 15,222,
+214,235,245, 10,133,162, 53,115,141,137,112,130, 55,125, 58, 70,230,157, 59,222, 43,126,168,101,157, 60,248,211,183,193,193,193,
+ 92,207,221,222, 91,207, 83, 39,149, 74,229,253, 80, 84,142,120, 19, 0, 54,109,253,198, 5,246,116, 1, 54, 3,116, 10,156,234,
+222, 38,134,137, 44,121,179,145,186,169,169, 45,187,115,203,205, 39,160,169, 8,181,201, 35,150,248,124,251,183,243, 31, 27, 48,
+ 96,214,242,166, 13,160, 21,100, 50, 25, 69, 81,222,222,222, 5, 5, 5,106,181,154,101, 89,225,188,217, 33, 40,216, 83, 66, 77,
+249,231,234, 71,103, 14,217,115,185,164, 76, 15,206,242,166, 37,138, 75,203,174,156, 57,214,206,207, 27, 0, 64, 66,185,112,191,
+ 73, 83,103, 3,128,159, 68,234,144, 55, 1, 96,101,218,199, 43,211, 62,198,188,185, 95,171,125,101,220, 36, 0,128,118, 50,158,
+ 43, 63,231,179,119, 92,114,199,191,135,189, 32, 37, 61, 61,192,157, 4, 42, 36,120,232,176,169, 99, 11, 58,110,224,239,170, 3,
+192,231,159,127,142, 25,211,234, 95,238, 7, 2,113,228,200, 17,145,230, 90,137, 55,223,126,109, 81,102,102,230,127, 63,122,223,
+146, 55, 51, 51, 51,211,210,210,120,234,164, 37,111, 54,173,147,143, 14,141, 5, 0,240,242, 16,200,155,247,217,211,153, 20, 59,
+ 15, 30, 18,123,146,115,221,235,207,206,157, 57, 30,239,217,252,245,254,151, 87, 11,146,193,156,228,124, 36,105,208,155, 59,119,
+ 3,192, 52,207, 32, 33,194,211,138, 55, 53, 53,181,122, 77, 21,238, 47,227,175, 52, 53,118, 67,230, 88, 61,179,207,183,127,123,
+234,171, 53,184,239,128,191,250,124,251,183, 60,167,142,140,140,172,170,170,170,170,170,146,201,100, 36, 73,234,245,122,181, 90,
+ 77, 81, 20,195, 48, 14,227, 47,236,250,254,187,189,103,245, 27, 23,142,235, 16, 20,236,238,225,127, 71, 91,242,191, 13,175,122,
+ 74,168, 58,154,161,120,109,173,120,179,184,180, 76, 83,122, 19, 0,122,132, 6,221,170,168,150,187,203,141,122,163,179,247,251,
+234,150, 61, 95,190,179,184,119,196, 35,215, 10,175,217,179,197,188,105,169, 52,247,107,181, 0, 80,160, 92, 53,229,167, 79,122,
+ 13,136,184,146, 99, 55, 10,239, 5,217,158,161,163,130,219,121,244,212,163, 90,202,164,149,209, 70, 13,201, 24, 8,196,202, 60,
+ 67,134,199,239,124,245,157,228,152,215,108, 26, 98, 23,167, 92, 46,231,252, 80,248,173,192,219, 6,131, 65,161, 80, 8,247,120,
+126,249,229,215,195,135, 15, 23,201,174,197, 17,218,177,125, 74, 74, 74,102,102,102, 78, 78, 78,196, 79,223,118,139, 29,146,119,
+238, 56, 30,180, 72, 73, 73,113,173, 78,190, 55,103,210, 71,251, 78,180,143,232, 80,118,187,188, 85, 47,158,115,176,186,224,235,
+116,109, 69,165, 93, 95, 39,230, 77,175, 71,166,213, 94,221, 49,119,230,248,151, 87,127,226,212,113, 49,111,186, 0,174, 87,110,
+165, 67,245,154, 42, 15,255,246, 0, 37, 60,182, 92,175,220,170, 13, 60,245,213,154,196, 69,105, 80, 97,251,225,209, 52,237,238,
+238, 78,146,164,159,159,159, 78,167,211,106,181, 0,208,174, 93,187,170,170, 42,135, 81, 9, 12,106, 24,224,230,246,202, 71, 71,
+ 18,251,194,237,115,128,163, 45,191,242,209,145, 15, 23,141,102, 88, 70,200,253,114, 14,248,177,113, 61, 36, 94,228,254, 67, 87,
+ 99,123,116,242,246,148, 31, 62,147, 31, 24,222,235, 86,227, 17,118,123,247,187,251, 42,130,187,240,216, 88, 98,203,158,130, 0,
+191,240, 39,135, 18, 60,247,139,121, 19, 51, 38, 0,160, 55, 55, 64,136,134,120,254, 13,180,234, 45, 32,245,196,169,119,210,130,
+131,109,198,254, 51,244,184, 29,230, 59,161,134,169, 51,170,243,255, 87,244,245,209,199,212,143, 60, 55,122,220, 63, 61,221,252,
+186, 43, 36,126,146,199, 52,167,191,229, 11, 95, 66,146, 36, 87,158,150,219, 78,225,200,145, 35, 4, 65, 28, 61,122,116,216,176,
+ 97, 46,216, 2,128, 72,187, 60, 24, 51,241,201,130,130,130,156,156,156,204,204,204,184,130, 2,156,185, 62, 46, 46, 46,105,100,
+ 60,174,147,209,209,209,183,120, 71,171,185, 58,121,247,251, 53, 94,189, 20,158, 81, 11,119,172,121,174,111,239,246,221, 39,173,
+206,200,200,104,141,145,110, 75,246,124,152,170,147,243,114,122,253,127,123, 95, 30, 23, 85,185,255,255, 57, 51,103,102, 24,246,
+ 85, 80, 17, 17, 16, 92,114, 67, 43,115, 55,135, 44, 81, 43, 21,205,180,205,202,193,186,149,230, 66, 89,253,110,247, 86, 38,150,
+ 91,246, 77,161,155, 90,138,154,104,166, 32,165, 98,138,187, 41,154,107,130, 48, 34,136,128, 44,195,192, 48,251,156,231,247,199,
+ 35,231, 30,103, 57,115,102, 96, 16,189,231, 93, 47, 95,135, 51,231,115,214,231,188,207,251,243,121, 62,207,243,233, 53,213, 50,
+162,231, 40,226,105, 17,229,100, 98,170,119, 7,235,130,165,214,192,210,210,218,121,103,145,156,204, 15,157, 53,105, 58,148,156,
+ 0, 80, 83, 83,211,161, 67, 7,172,137,140, 70, 35,238, 29,242,243,243, 19,137, 68,101,101,101,236, 83,251,111,200,205,123, 99,
+252, 72,172,151, 10, 77, 80, 93, 89, 4, 0,163, 98,193,247,243, 67,243, 22, 12,113,120,206,183,110, 87, 2, 64, 68,135, 64,165,
+ 94, 79,250, 10,117,213, 26, 16, 8, 58,118, 13,223,255,199, 25,142,215,251,202,252, 47,110, 28, 63, 72, 86, 66,125, 40,120, 10,
+ 4,131, 35,187, 61, 57,146, 45,113,138,169, 55, 55, 79,123, 99,167,190, 0, 98,116,112,154, 4,111, 18, 38, 12, 12,159,240, 10,
+155, 60,239, 28,104, 48,212,137, 76,198, 77,165, 91, 78,190,234, 55,226,249,103,123,116,232,121,121,255,225, 1, 73, 77, 34, 67,
+147,169, 7, 85, 93,197,214,149,135,185, 18,199, 58,153,203, 78, 97,243,230, 45,105,105,107,147,147,223,114,150, 58,143, 30, 61,
+154,145,177, 21, 31,151,103, 79, 22, 60, 61,121,102, 84, 84, 20,214,158, 88,111,134,118,236,232, 84,155,156, 61, 97,196,169,219,
+119,124,250,249,148,239, 43, 6, 15,201,228,119, 94, 14, 12, 31,239,214,115,182,118,237,157,162, 81,215,166,255,112, 16,235,196,
+218, 51,125,203, 62,215, 46,233,211, 41, 19,165, 62, 62, 4, 65, 0, 65,176,148,129,102, 74, 75,155, 65,207,102,201,201,134, 63,
+ 51,150,218, 12,184,220,149,156,246,209,208,208,208,216,216,168,215,235, 41,138,170,174,174,198,222,186, 70,163, 81,171,213, 14,
+ 29,246, 93,107, 62, 62,124, 25, 84, 37, 96,212,194, 55, 41,163,177,183,126,238, 60,252, 85,113,156, 75,113, 37,213,237,226, 64,
+ 63,175,160, 64,175,184,216,158,138, 27,213,133,229,181, 17, 65,126,250,170, 59, 38,163,137, 78,237,100,185,222, 33,163,158, 29,
+ 54,122,250,174,172,237,135,142,108,223,178, 98,254,228,249, 75, 46, 26,161,186,246, 14,203,245,210,145,205,215,134, 60, 62,163,
+ 87,215,237,187,254,184,120,177,100,197,165,252,109, 9, 47,195, 15, 39,202,203,171,233,212, 78, 27, 14,157, 78, 98, 54,212, 24,
+ 12, 42, 0,192,165,232, 26,164, 74, 0,208, 82, 26,129,190, 73,218, 36,172,170,176, 77,157,248, 54,234,116, 58,186,135,157,185,
+236,172,228,196,204,235, 84,196,243,232,209,163,155, 55,111, 89,183,238,187,180,180,181, 25, 25, 91,249,104, 41,123,155,180, 88,
+ 67,183, 73, 58,181,147,165, 77, 14,127, 52, 78, 54, 52,246,139,127,127,189,124, 85,206,255,219,252, 71,242,147,131, 42,119,231,
+168,148, 13,246,184, 44, 45, 45,109,206,171,211,173,215,207,113,166,155,168, 21,245,166,139,117,216, 45, 58,214,103,191, 56,118,
+249,199,175,167,111,217, 71,123,235, 88,120,114,151,156, 55,142, 95, 1, 0,129, 80, 72,138, 68,211,252, 59,218, 44, 46,104, 33,
+ 45,109,118, 22,113,149, 96,182, 2,213, 14,109, 3, 2, 2,170,171,171, 37, 18, 73, 99, 99, 99, 72, 72, 8,238, 50,210,233,116,
+245,245,245, 14,169,115,246, 23,219,190, 73, 25,237, 23, 9,135, 47,195,187,169,135,188, 73,225,164,247,190,188, 69, 85,102,172,
+ 88, 36, 20, 16, 92, 36,231,192,129,177, 33, 81,145, 29, 66,130,197, 2,194, 68,160,234, 38,173,178, 81,199,241,122,151, 47,253,
+245,185,158,221,124,125,131, 60, 67, 58, 25,235,148,231,179,183,214,215,113,173,163,185,126,233, 63, 96,158,140, 52, 25, 34,155,
+224,142,176,225,155,138, 51, 32,246,117, 16,157, 40,110,168, 17,104, 75,197,154, 65, 49,163,123,189,236,173, 8, 56, 28, 18,114,
+190,203, 96,133, 74,208,168, 71, 90,205,102,202,195, 78, 41,167,214,154,205,123,243,230, 45, 51,102, 76, 7,128,153, 51, 95,220,
+188,121, 11,119,195,140,140,173, 51,103,222, 45,121, 50, 99,198,244,140,140,173, 60, 69,218,107,147, 39, 79,158,196,241,205,129,
+ 3, 7, 2, 64,102,102,230,207,123,114,184,183,201,221,187, 62, 29,155,242,206,184,113, 99,130, 37,194, 70, 2,237, 43, 44, 59,
+121,185,220, 33,241, 89,176, 39,254,179,205,186,137,112,237,117, 90,111,114,100, 79, 54, 37,184,252,227,215, 1,192,217, 40,231,
+ 61, 47, 91, 83,147, 65,167, 19,144, 66,161,136, 20,137, 37, 30, 30, 30, 14, 37,167, 5,105, 86,150,149,112,151,156, 22, 15,242,
+237,137,143, 57,148,156, 0, 96, 54,155,195,194,194,244,122,125, 85, 85,213,237,219,183, 3, 2, 2,234,235,235,177, 86,114, 72,
+157,213,149, 69, 31,127,126, 72, 85, 2, 95,205, 31,254,207,247,134,204,254, 98, 91,198,242, 69, 66, 82, 76, 18, 4,233,200, 86,
+117,187,184, 99,176,191, 8, 68, 4, 16, 21, 55,174,220,188,163,234,228,231,163,213,232,206, 21,151,115,145,156,147,103,189, 47,
+ 10, 4,129, 16, 54,230,220,216,249,221,194,177,175,207,189,252,247,133,183,199,116,117,120,189,251,154,154,150, 79,156, 10,245,
+ 30, 64,136, 96,249,215, 83,206, 28, 93,250,216,115, 39, 78, 93, 34, 86, 46, 98,145,156, 0,112,161, 50,152,208,170,212,208,164,
+241,240,136,158,236, 27, 62, 73,164, 26,235,173, 15,143, 53,153, 53,198,154,242,227,107, 84, 49, 49,209,238,107,223,199,142, 29,
+ 35, 8, 2,251,218,248, 95,142,226,241,232,209,163, 8, 33,218, 73,199, 11,199,142, 29,227,137,210, 26,133,231, 79,208,241,205,
+183,102, 77, 77, 74, 74, 2,128,252,252,252,223, 78,156,227, 34, 57,167,201, 30,247,163, 2, 4, 32,218,185,242,157,239,178,255,
+154,250,104,239, 27, 69,165, 83,150,108,114,168, 10, 49,123,210,255,211,219,187,155, 61,153,140, 9, 78,246, 23, 9,236, 73, 78,
+ 28,238,180, 23,241,116, 40, 57,167,122,119,152,230, 27, 38, 16, 8, 68, 18, 49, 41, 18,147, 34,177, 88,234,145, 20, 20,190,100,
+201, 18, 46,146,147, 73,154, 14,121,211, 66,114, 50, 73,211, 33,143, 0,128, 82,169, 84,171,213, 34,145, 8, 75, 78,138,162,240,
+191, 92,168,115,211,202, 15,207,149,231,121,135,193,194, 53, 71,125, 72, 97,117,101,145,175, 68, 84, 95,119, 75, 40, 32, 72,214,
+ 0, 5,150,156, 93, 2,125,174, 42,110,152, 12, 6, 9, 41, 86,171,117, 23,110,220, 14,238,214,219, 33,111,226,235,125,246, 31,
+159,101,124,179, 90, 67, 65,151,232,240,203, 87, 78,189, 63,161, 31,199,235, 5,128,247,163, 7,101, 93,255, 3, 84, 38,240, 8,
+ 62,240,231, 85,226,203,119,190, 13, 13,101,231, 77, 0,232,103, 24,127,252,192,159, 96,104, 84, 19,141, 74,129, 90, 69, 26,141,
+230, 6,137, 78,227,113,251,198,182,197,215, 35,251,199,178, 79,213, 44,149, 74,241,130,135,135, 7,253, 17,165, 87, 58,164,191,
+ 77,155, 50,214,173,251,142, 94,243,210, 75, 51, 54,111,222,226,144, 61,113,136,147,150,156,180,240,220,180, 41,131,119,219,173,
+219, 36,221,159,254,241, 39,243, 36,164, 56, 52, 52, 20,179, 39, 61, 56,144,189, 77,190, 49,170,239,220,175, 87, 55, 86,221, 9,
+241,237,112,229,106,233,171, 43,182,164,165,165,113,244,166,211, 24, 96,250,224,237, 54, 69,137,109,190,206,198,171,219,193, 86,
+127, 17, 23,108, 87,223, 1,128, 25,193, 93, 0,128, 20,145,164, 88,172, 85,171, 3, 66, 67, 61,133,158,236,146,147,153,150, 36,
+ 66, 70, 48,105,238,106, 67,210,211,161,228,100,166, 37, 1,128,234,206,221,238, 60,150, 33, 61, 52,123, 2, 64, 88, 88, 24, 0,
+212,213,213,249,250,250, 98,111,157, 75,113,152, 77, 43, 63, 4,248,114, 78,210, 72,248,230,232,119, 31, 37, 78,153,191,122,203,
+210,183, 73,130, 16, 75, 60, 28, 74,206,171,165,119, 98,186, 4, 31,204, 61, 5, 0,126,157,162, 1,192,168,191,235, 25,137,236,
+155, 99,201,249,249,172, 49,239,254,115, 99,151, 40,194,169,235,197,146,243,169, 93,235,247,207,152, 78,132, 15, 6,128,177, 94,
+ 94, 0,144,165,190, 59,151,254, 4,111,111,150,211,238,171, 95,116,225,183,108, 93,220,137,200,238,143, 52, 72,225, 6,220,108,
+ 44,169,174, 94, 98, 86, 43,195,231,189, 60,159,253, 70,173, 93,187, 86, 42,149,106,181, 90,186,183, 80, 42,149,174, 93,187,150,
+ 11,111,102,100,108, 77, 75,187,103,203, 97,195,134, 33,132, 50, 50,182, 18, 4, 97,175,203, 40, 57,249, 45,132,208,204,153, 47,
+ 90,244, 11,225, 63, 51, 50,182,102,100,108,101,210, 49, 31,229,252,226,211,143,127,201,250,109,236,176,120,186, 77,250,117,138,
+ 30,168, 80, 60, 61,121,102,105,173, 38, 34,200,147, 93,114,206, 77,207, 90,252,250, 83,157,194, 70, 97,254, 5,128,220,220, 92,
+188,129, 83,195, 17,105, 50,197,188,233,190,209, 65,216, 55,111,229,228, 36,215, 72,211,195,219,139, 20,137, 1, 96, 86,151, 56,
+145,135,196, 59, 32, 0, 0,180,141,141, 70,131, 1, 0,196, 82, 15, 41,105,100, 49,199,153, 73, 94,129, 97,148,217, 40, 66,119,
+183, 52, 18, 34,123, 67, 33,153,192, 89, 17, 9,243,190,165, 25,132, 35,111,210,236, 73,167,193,215,213,213,113,186, 65, 12,246,
+220,212,156, 18,254,253,146,230,113, 53, 70, 53,123, 33,177, 46,129, 62,127,214,212,255,117,189, 60,184, 91,111,154, 49, 29,242,
+ 38,198,179,255,248,108,103,188,215, 63,158,239,225,194,245,190, 31, 61,104,254,158,237,196, 23,255,252, 45,244,241, 85,234,203,
+244,250, 1,164, 40,220, 67,226,240, 98,251, 25,198,255,182, 71,119, 75, 89, 92, 93, 91, 81, 85,232, 45, 52,251, 14,237, 59,124,
+244,203,163,221,244, 62,211,244,103,253, 19,102,192, 77,155, 50, 54,109,202,176, 32, 86, 12, 22, 90, 28, 62,124, 56,223,207,110,
+179, 77, 62,241,196, 19, 22,109,242,233,201, 51, 1,128,133, 55, 49,222, 24,213, 55, 33,247,244,140,127,254, 52, 98,196,136,208,
+123, 61, 24, 23,120,147,201,158, 92,210,201,173,215,184,192,182,217,206, 20, 98,248, 47, 51,224,108, 88, 46, 54, 73, 73, 73, 90,
+171, 53,119,109,155,170,239,238,151, 36, 69, 34,145, 68, 34,145, 72, 36, 82,169, 20,255, 91,128,180,227,198,141,251,171,196,110,
+172,211, 43, 48, 76,104,210,128, 73, 35,100,144, 38,151, 1, 79,216, 61, 87,221,185,197,228, 17, 46,164,233, 23,210,201, 96,208,
+187,246, 92,103,124,182,233,250,181, 43, 46, 55,211, 63, 11,203,112, 3,101,242,166, 67,210,196,120, 57,222,203,181,235, 5, 0,
+ 98,229, 34, 76,154, 52,111,114, 36, 77, 26,207,116,155, 2,248,179,192,173,134,221,186,117,235,240,192,161,181,107,215,210, 35,
+136, 54,110,220,136, 37,231,198,141, 27, 89,178,214,216, 85, 33,207,128,173, 11,155,109,210, 33,105, 98, 36,124,252,125, 43,146,
+ 38,147, 61, 91,101, 27,238,140,233,116, 89, 55,153, 76,198,253, 58, 45, 82, 91,157,178,253,171,196, 50, 45, 22, 71, 51, 49,105,
+130,147,164,137,163,123,174,145, 8, 0,152,204, 20, 23, 73,107, 19,119,234, 84,220, 15,196, 4,142,102,186, 70,154, 45,185, 94,
+ 28,205,204, 82,171, 93, 38, 77, 30, 15, 43,112, 47, 80,105,173,198, 5,210,196,204, 69,251,230,173, 69,154,109, 0,139,154,110,
+192,151,117,227,193,131, 7, 15,183,130,159, 37,158, 7, 15, 30, 60,120,234,228,193,131, 7, 15,158, 58,121,240,224,193,131,167,
+ 78, 30, 60,120,240,120, 24,112,255,203,186,253,175,217,234, 42,203,184,219,122,132,117,105,221,115, 22, 34, 68, 82,160, 23,218,
+ 78,245, 23,153,193, 36, 0, 68,240,207,151,183,125,152,109, 31,126,213,233,236, 24, 44,133, 66,145,219, 12,133, 66,193,127, 24,
+ 45, 32, 49, 35, 51, 65,208,188, 89, 90, 90,122,242,228,201,115,231,206,149,150,222,157, 52,196, 40, 4, 68, 56,177,195,214,154,
+215,131, 71,251, 71, 65, 65,129, 83, 27, 39, 39, 39,187,124, 32,151,109,239,143,234,108,111,112,150,251, 20, 10,197,210,165, 75,
+167, 78,157,202, 52,143,138,138,226,110,174, 80, 40, 50, 51, 51,147,146,146,162,162,162, 28, 26,206,158, 61,219,225, 62,167, 78,
+157,106, 51,187,237,192,129, 13, 92,108,149, 74,175,214,189,165, 52,105,222,185,115, 71,175,215, 19, 4,225,225,225,161,211,233,
+ 74, 75, 75,207,156, 57,211,175, 95,191,152,152, 24,167,118,200,101,160, 42, 0,200,229,115,184,108,102,115, 68, 80,203,108,229,
+118, 54, 78,227, 94,127, 81,161, 80, 44, 9,158,140,246, 22,147,135,239,153,221,199,188,236, 79,148, 83, 60, 61,228, 23,144,244,
+112,120,122, 99,199,142, 5,128,125,251, 92,153,188, 49, 41, 41, 19, 0,228,242,128,150,100, 74,226, 50,206, 14, 39,204,125,243,
+205,217, 8,129,245, 83, 93,176, 96, 62, 23,115,186, 85,172, 90,181,106,228,200,145,201,201,201, 91,182,108,105,104,104,112,120,
+208,123, 40,137, 20,190, 48, 68, 44, 79,150, 47,251,253,171, 5, 9, 11,240,202,239,191, 79,127, 48,168, 51, 55, 55,215,226, 57,
+ 89,175,105,111,212, 73,243,166, 76, 38,195,217,185, 10,133,130, 35,117, 98,218,197, 68,128,135, 69,165,164,164, 56,182,205, 12,
+116,180, 99,187,119,172,105,130,131, 58,104, 32,229, 66, 73,174,204,240,170, 82,169, 58,116,232,128, 53,163, 84, 42,189,115,231,
+ 78,125,125,189,159,159,223,159,127,254, 9, 0, 92,216,147, 46, 22, 77, 16,196,228,201,147,101, 50,153, 67, 14,221,179,231, 87,
+188, 48,113,226,115,246,150,237,217,106, 79,220,173, 60, 42, 29,242, 45,189,204,252, 83, 58,196,238,164, 39,191,255,126,207,132,
+247, 71,142, 28,193, 19,208,208, 55,106,243,230,205,236, 13, 35, 53, 53,245,139, 81,253,129, 32, 44,202, 98,163,173,197, 64, 16,
+ 78, 53,209,182,127,137,152,188,153,150,150,134, 16,202,200,200, 56,118,236,216,184, 23, 63,178,183,241, 9,171, 82, 94,187, 50,
+231,175, 92,185,146,162,168,244,244,244,140,140, 12,223,136,145, 54,233,146,118, 65,174, 93,187, 70, 16,196,244,233,211, 1,224,
+197, 23, 95,228, 66,184, 95, 31,184, 91, 13,169,114, 95, 5, 65, 16, 91,222,243, 4, 32, 82,158, 94, 4,191, 3, 0,108,253,113,
+ 75,242,200, 54,210,161,220, 71,181, 11,108,190,144,153,153,153,233,233,233, 22,175, 10, 71,247,185, 37,158, 50,211, 22, 11, 64,
+238,182,233,233,233,244,160, 38,153, 76,198, 93,111, 98,218, 37, 8, 34, 41, 41, 41, 45, 45, 13, 31,148,227, 85, 16, 83,149,248,
+127,150, 53,246,224,157,189, 22,255,207,178,198, 33,111, 34,132,112,147,229,232, 59, 43,149, 74, 63, 63, 63,129, 64, 48,107,214,
+172, 25, 51,102,136,197, 98,169, 84,234,225,225, 65, 16,132, 80, 40,204,207,207, 87,169, 84, 44,230, 87,175, 94,149,203,229, 59,
+118,236,192,183, 11, 33,180,115,231,206,228,228,228,171, 87,175,182, 49, 29, 88,208,168,155, 62,222,169,169,169,105,105,105, 47,
+118,216, 53, 61,120,167,197,205,255,232,241,191,200, 67, 47,112,217, 79,114,114,242,194,133, 11,187,117,235,230,194, 57, 36, 39,
+ 39,203,229, 1, 65, 65, 7, 91,174, 55,105,222,116,202,156,230,205,249,243,231,179,152, 51,155,223,170, 85,171, 70,140, 24, 1,
+ 0,211,167, 79, 31, 57,114,164, 67,222,176,176,157,246, 4, 9, 0, 91,222,147,190, 48, 68,188,104,236,194,182,108, 84, 78,141,
+ 97, 23,216,114, 16,238, 78,210,135,181, 27, 45, 49,184, 16, 25,110,109, 45,105,169,174,185,219, 54,217,208, 89, 19,154,118, 83,
+ 82, 82, 56, 14,231,191, 95,160,121,211,162, 9, 58,108,166, 26,141, 70, 32, 16,188,240,194, 11, 42,149,234,246,237,219, 34,145,
+136, 36, 73, 60,225, 0,158,214,232,204,153, 51, 44, 77,124,245,234,213, 4, 65, 76,153, 50,101,221,186,117, 50,153, 44, 45, 45,
+109,202,148, 41, 0,240,205, 55,223, 60,100,161, 61,154, 55, 1,160, 91,183,110,204,161,198,114,185,156,118, 74, 56,170, 72,153,
+ 76,182,110,221,186,204,204, 76,215,162,195, 31,126,248, 97,102,102,166,197, 72, 71,142,188,185, 98,197, 10,130, 32,146,147,147,
+ 51, 50,238,206,179,199,101,182, 42,154, 55,177,185, 64, 32, 56,123,246, 44,151,105,250, 10, 10, 10, 8,130,120,225,133,187, 31,
+149,233,211,167,143, 26, 53, 42, 57, 57,121,247,238,221, 14,195, 62,149,251, 42,128,128,140,119,239,142,254,220,242,158,231,244,
+161,146,148,167, 23,181, 67,222,180,237,176,203,100, 50,186,180,147,130, 81,218,201, 97, 43,105, 45,222,108, 21,234,108, 9,150,
+ 46, 93,234,242,133,180, 25, 92,120, 9,139,138,138, 4, 2,129, 80, 40, 44, 42, 42, 66, 8, 21, 20, 20, 24, 12, 6,130, 32, 72,
+146, 36, 8,194,108, 54,107, 52,154, 93,187,118,217,123,208, 7, 15, 30, 4,128, 41, 83,166, 48, 55,192,203,248,197,102,105, 33,
+ 76,127,220,222, 50,139,192,180,231,185,179,184,234, 22,126, 58,214, 65,220,177, 36,120,242, 23,163,250,147,114,139,248,230,105,
+148,163, 80,112, 9,230, 48,100, 35,254,186, 96,142, 56,120,240, 32,119,159, 29,219,118,239,222, 29, 56,135,149,153,152, 51,103,
+ 14, 29,154,152, 51,103, 14, 46, 79,194,157, 55, 71, 14, 21, 2, 0, 69, 81, 11, 22, 44, 88,181,106, 21, 54,159, 48,241, 77,246,
+106,133,180,228,164,129, 61,247,156,156,156, 30, 61,122, 0,120,177,219, 78,123,226,158, 9, 37,182,188,231, 9, 0, 91,183,156,
+ 47, 8, 43, 96,183,109, 21,222,156,157,178, 52, 61,245,131, 22,197, 58,103,207,158,141,197, 38, 93,218,201, 41,222,180,169,125,
+ 88,194,112,246,108,153,235,221, 87,238, 46, 55, 55,151,158, 22,144,121, 14,174, 69,166,208,246, 0,151,207, 68, 61,222,113,151,
+ 8,125,146, 22,239, 18,253, 39,179, 78,175, 5,234,234,234,124,124,124,234,234,234, 78,156, 56, 33, 20, 10, 13, 6,131, 86,171,
+197,147, 58, 35,132,140, 70,163, 94,175,103, 97,100,172,196,173,239,137, 76, 38,219,177, 99, 71,102,102, 38,203,237,106,121,172,
+ 83, 58,228, 91, 38, 81,226,101,142, 4, 58, 98,196, 8,103,217, 19,237, 45, 6,184, 27,223,164,131,230,104,219, 13, 0,130,123,
+ 12,157,249,117, 1,128,117,235,214,201,229,114,215,194,157, 31,126,248, 33,142,210,114, 55, 71, 8,209,113,198, 97,195,134, 29,
+ 61,122,212, 41,189,137, 16, 50,153, 76, 76,243,188,227,230,175, 83,147, 29, 74, 78,204,149,214, 88,185,114,101,226,140,143,237,
+217, 50,162,156,247,106, 82, 14,182,173,197,155, 45, 85,157, 22,218,179,141,245, 38, 51,110,208, 54, 9, 70, 76,223,156,217,247,
+202,206, 5, 44,209, 79,151, 57,148,142,114,178,115,232,158, 61,150,133,154, 55,109,218,244,210, 75, 47, 49,164,220,195,236, 55,
+ 66, 0, 0, 32, 0, 73, 68, 65, 84, 68,185, 92,110, 29,234, 54, 24, 12,117,117,117, 58,157,206,207,207, 79, 34,145,152, 76, 38,
+132,144,217,108, 54, 24, 12,184, 20,168, 67, 37,107, 47,104, 51,101,202,148, 54, 8,113,216,235, 47,226, 2,204,158, 78,188, 24,
+135,167, 91, 95,236,244,224,157, 78,133,224,153,146,147,254,194,113,252, 36, 51, 37,167,205,143, 37, 59,182,108,217,130,119,178,
+110,221, 58, 23, 66,156, 88, 51,145, 36, 57,111,222,188,179,103,207, 54,155, 59,104, 30,171, 87,175,182,152, 3,112,219,182,109,
+121,121,121, 8, 33,252, 45,103,201,175, 92,181,122,213, 11,131,239,145,156, 51,190,209,108, 59, 97, 68, 8, 13,120,113, 64,242,
+200,100,183, 22, 34,118, 1, 2, 22, 45,134,111, 31, 29,244,100, 65, 84, 84, 84, 74, 74,138,107,103, 96,207, 22, 87, 52,229,174,
+ 28, 45,128,123,219,157, 13, 15,113, 73, 57,106, 15,152, 56,113,226,196,137, 19,233, 63, 49,111,210, 43,173,185, 21,195,199,199,
+199,108, 54, 43,149,202,154,154, 26,165, 82,169,209,104,112,225,207,134,134, 6,149, 74,165,213,106,245,122, 61,174,165,108, 47,
+ 38,181, 99,199, 14,135,159,159,118,133, 35, 12,208, 43,107,106,106,232,101,150,248,157,245, 84,138,116, 52,220, 5,201, 73, 11,
+207, 29, 59,118,184, 28,241,220,177, 99, 7,151, 38,157,145,145,145,151,151,135,187,134,146,147,147,241,181,115, 76, 45, 2,128,
+143, 82, 70,230,229,229, 81, 63,251, 35,132, 86,174, 92,137,205,143,156,160,154, 37,160, 93,201, 73,187,231, 0,176,117,107,198,
+156, 57,115,242,242,242,230,206,157,235,240,208,149,251, 42, 8, 32, 50,154, 37,231,139,171, 53,194, 23, 84, 91, 79, 24,230,206,
+157,155,250,251,178, 54, 8,113, 58, 43, 57,237,170,206,244,244,116, 58,196, 73, 7, 61,217,105, 5, 51, 32,214,143,206, 58,215,
+ 22,182, 88,135, 70, 69, 69,185,230,164,211,201, 73,109, 9, 44, 54, 93,243,214,177,216,228,226,173,211,188, 73, 47,208, 44,105,
+115,165, 5,130,130,130,106,107,107, 13, 6, 3,174, 0, 74,146, 36, 86,157, 77, 77, 77, 26,141, 70,175,215,171, 84, 42, 22, 73,
+133,165,165,205,196, 53,252, 43,235, 57,183, 66,172,147,227,250,123, 66,150,182,106, 97,125,244,209, 71, 95,124,241, 69,112,112,
+176, 91,155,132,181,228,164,225, 48,226,105, 45, 57,157,210,155, 51,102,204,152, 57,115, 38, 66,104,201,146, 37,139, 23, 47, 30,
+ 49, 98,196,140, 25, 51, 56,154,127,252,193,200,195,135, 15, 19, 59,130, 0, 96,255,199, 62, 79,125,222, 56, 98,196,136, 47, 82,
+243, 16, 66,236,178, 23,231,114, 2,192,182,109, 91,242,242,142, 34, 2,205,155, 59, 47, 46, 46,142,203, 65, 87,173, 90,245,194,
+ 16,209,127,149, 38,160,121,115,231,133, 62, 21,230, 66,132,183,109,120,211, 54,117,210,122,115,224,192,129,204,160,167, 67, 71,
+131,201,128,174,105, 79,108,219, 66, 63, 29,159,179,139, 12,232,230, 71,213,114,224,144, 2, 93,108,139,169, 61,109,174,100, 34,
+ 60, 60,188,168,168,200,108, 54, 55, 52, 52, 24,141, 70, 28,226,212,233,116, 56,195, 9,247, 26,177, 68,241,100, 50, 89,102,102,
+ 38, 22,158,116, 75,200,205,205,181, 88,211,102,177, 78,166,255,110,239, 94,217,139, 23,127,244,209, 71,211,166, 77,251,249,231,
+159,185,135,149, 44,150,151, 4, 79,126,125,212,214,233,185,182, 83,226,199,142, 29,123,227,198, 13,139,172, 82,140, 27, 55,110,
+ 0,107,122,124, 82, 82,102, 82,210,152,132, 4,133,117, 80,181,182,118, 12,128, 82, 46,183,251, 38,210,133, 37,176,176,221,191,
+127, 63, 0,112,231, 77,129,128, 64,219, 3, 0,243,230, 69,211,134, 67, 6, 0,248, 34, 53,143,203,171,129,155,211,156, 57,115,
+ 16, 66,243,222,159, 23, 23, 27,199,241,160, 11, 23, 45, 32, 8, 2, 33, 16,190,160,194,182, 97, 79,117, 4,196,174,113, 91, 19,
+214, 93, 67,217,155, 63,115,152,218, 73,218,115,190,232,174, 33,186, 11,149, 75,236,175, 85, 60,119,103, 51, 58,255, 7, 65, 59,
+200,204,194,129, 22, 43,109,198,134, 70,142, 28,153,147,147, 99, 50,153,234,235,235,113,172, 19, 0,170,171,171,235,235,235, 17,
+ 66,120, 36, 21,203,113,223,123,239,189,213,171, 87, 99, 2,101,198, 55,223,123,239, 61,119,127,117,180, 39,254,193,133, 46,109,
+242,136, 53,165, 38, 39, 39,115,228, 77,107,254,106,238, 50,114,252,129,183, 57,160,176,164,164, 4, 56,116, 66,210,225,178,123,
+207, 92,198,229,122,107,107,107,247,239,223,207, 12, 50,114,129, 92, 46,167,126, 14,216,127,209, 4, 0, 27, 15, 25,182,157, 48,
+ 32,132,142,158,116, 34,182,112,228,200,145,185,115,231,114, 84,154, 52,112, 35,252,249,164,113,238,220,185, 97, 99, 59, 54, 51,
+113,123,127, 7, 73,155, 13, 11,167,151, 51,229,134, 67,135,221,162, 97,185,204,158, 45,223, 9, 61, 22,147, 35,236, 21,101,226,
+ 66,223,214, 30, 58,119,159,221,218, 67,231,232,179,211,125, 89,204,183,194,230, 74,155,210, 32, 49, 49, 49, 35, 35, 67, 44, 22,
+235,245,122,147,201, 68, 81,148,191,191,191, 82,169,228,146, 71,209,171, 87,175,180,180,180, 3, 7, 14,224, 46,117,156,227,249,
+ 64,148, 82, 96,226,143, 63,254, 72, 76, 76,204,206,206,118,129, 55,105,150, 81,164,164,176,184, 71, 11, 23, 46, 4, 59,169, 41,
+139, 22, 45, 98,143,117,202,229, 1,246,108,229,242, 92, 46, 12,232, 80,119,179, 96,236,231,141,255, 13, 4, 59,195,155,223,125,
+231, 98,109,209,175,191, 90, 30,246, 84,199,251,210, 18,172,165, 37,247,209, 68,118,147,147, 28,174,113, 43,218, 50,163,211,169,
+194, 74,247, 18,180,139,148, 49,117,234, 84,144,186,120,182, 56, 22, 97, 81,169,149,201,245,120, 37,251, 21,205,152, 49,163,184,
+184,248,208,161, 67, 90,173,214,108, 54,247,239,223,127,234,212,169,220,239,121, 66, 66, 66, 66, 66, 2,214, 11, 28,197,102,107,
+197, 58,237, 45,179,240,136, 69,159, 47,199,242,235,230,101,127,162,173,197,211, 67,238,161,206, 55, 26, 6,188, 62,122, 27, 41,
+127, 1,167,196,227,159,108,170,123,150,251, 63,102,204, 24,135, 13,210,133,159,232,235, 37, 8,226,249,231,159,199,163,230,157,
+133, 96,154,146, 32,136,137,207,206,198, 95, 89,156,138,196, 28,100,233, 14, 12,156, 25,255, 32,122,126,237,113,250, 15, 23, 62,
+149,109, 47,124, 90,114,196,150,204,235,209, 90, 87, 26, 29, 29, 29, 29, 29,109,177,210, 96, 48, 8,133, 66,161, 80,216,218, 15,
+116,237,125,178,181,209,144,102,206,156,201,201,139,204, 41, 6,130,192,113, 42,122,229,235,163,183, 1, 2,135, 97,141, 7,232,
+197,177, 50,119, 28, 98,108,245, 36,161, 54, 27,159,222,186,224,203,186,241,224,193,131,135,243, 10,157,191, 5, 60,120,240,224,
+193, 83, 39, 15, 30, 60,120,184, 29, 36,127, 11,120,240,224,193, 4, 97,189,132,232,127,120,240,212,201,131, 7, 15,155,188, 73,
+220,253,207, 10, 8, 16, 79,160, 86,212,201,151,133,226,109, 31, 38,219,151, 39,246,161,151, 5, 2, 1, 78,162,162,243,108, 80,
+ 51,240, 6, 63,237,185,196,180,173, 47, 57,228,225,225,129,183,199,211,244, 49,109,241, 60, 41, 20, 69, 1,128,209,104,244,233,
+ 50,226,127,224, 62, 19, 66, 82,130, 40, 19, 69,153,178,143,221, 98,166, 42,217,179, 69, 8, 85, 85, 85,133,133,133,185,112,220,
+150,216,114,185, 94, 94,117, 2, 0, 36, 39, 39,211, 47,128,179,201, 25, 45,183,229,152,136,206,163,229, 16, 24,154,200,218, 27,
+221,117, 23, 59,155,202, 10, 81,183, 91, 62,189, 52,190, 93,197, 94, 62,246,182, 63,118,236,216,176, 97,195, 48,105, 98,250, 35,
+ 8,130, 73,127, 84, 51,110,222,188,105, 97,123,238,220,185,129, 3, 7, 74,165, 82,146, 36,133, 66, 33,109,142, 25,211,220, 12,
+189, 94,159,159,159, 63,170,203,136,246,127,247, 16, 66,181,181,181, 39, 79,158,244,247,247,183, 72,116,117,172, 67, 9,129,196,
+ 35,208, 63, 32,174, 73, 93,174,110, 44, 35,128, 0,194,129,252,164, 40,106,199,142, 29,133,133,133, 0, 32,149, 74,231,207,159,
+207,253,112,216, 86, 81, 92, 36, 20, 10,197, 18,201,220,185,243,218,103,245,192, 7,158, 58,241,164, 44,206,214,206,108,185, 45,
+253, 56,221,157, 48,204, 3, 16,106,188,249,183,234,200,118,141, 70, 31,249,184, 64, 26, 78,116, 47,189,248, 40, 92, 80,234,189,
+255,242,124,185,134,232,108,211,232,234,213,171, 66,161,112,248,240,225,100, 51, 48,141, 98,177,105, 50,153,204,102,179,209,104,
+188,121,243,230, 31,127,252, 33, 12, 26,196,180,213,104, 52,231,207,159, 31, 60,120,176, 88, 44,166, 39,210, 23, 8, 4, 20, 69,
+153, 76, 38,147,201,100, 52, 26,181, 90,237,249,243,231,213,106,117,123,190,115,139, 23, 47,166,151,167, 76,153,210,216,216,216,
+191,127,127, 23,108, 55,109,201,151, 74, 59, 8,133, 98,117, 99, 25, 65, 0,194,217,159,246, 91,253,237,219,183,213,106,245,139,
+ 47,190, 24, 21, 21,133, 71,133, 6, 6, 6, 14, 26, 52,200,230,198,175,142,189,103,140,192,165,107,215, 14,251,120,190,191,242,
+223, 3,226, 31,169,184,117,103,127,206,225,200, 71, 6, 52, 52,168,218, 59,117, 50, 53,148,189,229,246,134,150,156,155,203,182,
+ 76,215,143, 39, 55,183,194, 80,118, 85,114, 98,147, 94, 67, 77,138, 17,198,133,152,168, 64, 36, 10, 20, 54,214,138,165,141,218,
+158, 23,190,205,143, 77,214,120,118,181,249,128,254,254,251,111,177, 88,252,228,147, 79, 98, 6, 20,137, 68, 2,129, 0, 79,234,
+108, 50,153,244,122,125, 89, 89,217,161, 67,135,204,102,179,197, 24, 0,129, 64, 96, 52, 26, 47, 92,184, 48,124,248,112,169, 84,
+ 42,145, 72,176, 45,166, 78,189, 94,175, 86,171, 47, 93,186,164,211,233, 28, 14, 31, 40, 41, 41, 41, 43, 43,107,108,108, 20,139,
+197,161,161,161,221,187,119,199,161, 0, 46,104,137, 45, 69, 81, 31,127,252, 49, 61,113,212,226,197,139,175, 94,189,218,161, 67,
+135,160,160, 32,142,188,185,126,214,172,113, 3, 6, 0, 64,216, 59,239, 72, 61, 67,213, 13,165, 13,170, 98,132,204, 2, 1,129,
+ 40, 7,205, 62, 48, 48, 48, 56, 56,248,167,159,126,122,229,149, 87,246,236,217, 19, 24, 24,120,228,200, 17,131,193, 0, 16, 97,
+115,251,218, 47,223,167,151,189, 13,198, 78, 38,221,220,133,255, 92,249,245,191,190,250,250,187,206, 2,243,119, 95,175,120,242,
+133, 23,237,217,182, 28, 22,165, 53, 56,166,186,219, 78, 78,178,158, 39,198,122,185,253,160, 37, 19, 79,184,108,139, 39,220,198,
+243, 59,240,222,186,251,160,171,175,137,185,177,215, 87,104,142,241, 67, 93, 35,144,176,175, 88,252,120, 79,159,254, 17, 30, 30,
+ 70, 19, 5, 66, 74,164,203,221, 36, 48, 53,218,104,217,205,165, 68,206,159, 63,239,233,233,233,227,227,227,235,235,235,239,239,
+239,235,235,235,235,235,235,233,233, 89, 91, 91,155,151,151, 39, 16, 8, 4, 2,129, 77, 91,179,217,124,229,202, 21,145, 72,228,
+235,235, 27, 16, 16, 16, 24, 24,136,205, 37, 18,201,223,127,255,173,215,235,177, 20,101, 57,249,139, 23, 47,254,254,251,239,217,
+217,217, 89, 89, 89, 89, 89, 89,217,217,217, 71,143, 30,109,106,106,226,114,225, 46,219, 82, 20,165,211,233, 42, 43, 43,153, 43,
+151, 44, 89,114,245,234,213, 17, 35, 70,120,122,122, 58, 38, 5,161,152,249,103,229,154, 53, 83,158, 11,175,174, 58,163,110, 44,
+ 3, 0, 28, 55, 38, 88,203,129, 30, 59,118,236,244,233,211,243,231,207, 15, 13, 13,157, 52,105,210, 75, 47,189, 52,102,204,152,
+156,156, 28, 46, 47,228,230,162,138,157,103, 47,103,102,124,215, 53,188,195,251,239,188,180,228,179, 5, 47,245,138,226,100,219,
+ 26,188, 9,156,139, 20,145,109,195, 80,110,141,117,186, 76, 94, 45,177, 37, 8,194,162,156, 55, 15,119,160,238,202,185,219,229,
+ 13,157,252, 73, 17,101, 36,131, 41,242,137,167, 61,194, 62,161, 76,165,112,249, 21, 84,220, 80,171, 17, 71, 8, 53, 23, 46,158,
+240,139, 31,107, 77,127,184, 92,221,245,235,215,131,131,131,199,140, 25,227,229,229, 69,146, 36, 69, 81, 90,173,182,160,160,224,
+200,145, 35, 66,161,144, 36, 73,235,217,157,241,122,177, 88,108, 54,155, 11, 11, 11, 71,141, 26, 21, 24, 24, 40, 18,137,140, 70,
+163, 74,165, 58,123,246,172,209,104, 20,137, 68,216,121,103,209,140, 7, 14, 28,168,172,172,140,142,142, 14, 11, 11,107,106,106,
+186,118,237,218, 31,127,252,225,229,229, 21, 31, 31,207,174, 31, 75, 74, 74, 14,228, 30,172, 82, 25,124, 99, 6,135,133,116, 49,
+ 54,169,106,174,159, 61,144,123,208,161, 45, 69, 81, 13, 13, 13,133,133,133, 37, 37, 37,125,251,246, 93,188,120, 49, 22,158,216,
+251,118, 40, 90, 5, 66,177, 84, 26, 44,245, 12,203,216,118,113,198, 11,125,215,207,154, 5, 0,179,214,175, 7, 0,163,241, 46,
+107, 11, 8, 16, 16,132,153,176, 27,236,204,201,201,201,201,201,249,232,163,143,124,124,124, 0, 32, 61, 61,125,208,160, 65, 53,
+ 53, 53,177,177,177, 14, 31,247,234,243,215, 87,159, 43,220,189, 97, 25, 41,212, 18,102,243,178, 85,235, 39,142, 27,115, 91, 64,
+ 58, 59, 27,147, 83,188,201,148,153,220,139,187,145,220, 41,178,125,122,166,248,172,240,172, 7,220,231,193,110,185,109, 59, 15,
+ 98, 60, 52,240,213,213,230,148,234, 58, 43,133, 3,124,137,144,106,136, 33,253, 4, 68, 16,210, 85, 53, 85, 17, 87, 74,169,202,
+ 38, 29, 41, 16, 0, 85, 8,246,169, 83, 34,145, 20, 23, 23,119,238,220, 57, 33, 33, 65, 40, 20, 82, 20, 85, 91, 91,123,236,216,
+ 49,145, 72, 36, 22,139,241,176,125,202,202, 22,155,139,197, 98,132,144, 66,161,136,137,137,241,243,243, 83,171,213,231,207,159,
+ 55,155,205, 18,137, 68,175,215,235,245,122, 22, 61,113,230,204,153, 91,183,110,245,235,215,111,212,168, 81,225,225,225, 77, 77,
+ 77, 33, 33, 33,185,185,185, 39, 79,158,116,232,122,159, 57,115,166,170, 78, 21, 24, 59, 56,106,248, 52,255,240, 88,125, 83,125,
+233,233,189,215, 15,254,232,208, 22, 71,105,111,223,190, 29, 26, 26, 26, 27, 27,123,241,226, 69, 76,154, 52,129,218,156,251,249,
+238, 7,131,244,240, 15,136,243, 15,140, 19, 8, 68, 70, 99,211, 15, 27, 14,205,122,109, 52,182,125,243,205, 55, 67, 66, 66,176,
+ 45, 65, 52,135, 57,109,133, 59,143, 29, 59,150,149,149,245,214, 91,111,117,236,216, 17, 0, 14, 30, 60, 88, 82, 82, 34,149, 74,
+165, 82,105, 98, 98,226,137,171, 90,150,171,222, 82, 80,182,252,204,181,255, 44, 77, 9,143,235,218,164, 86,238,254,237,204,197,
+ 75, 5,254,136, 18, 87, 86, 37,254, 99,198,241, 43,218,118, 29,235,196,147,180,179, 47,183, 43,180,132,185,120,214,107,255,168,
+174, 41, 59, 81,161, 77,244,244, 60, 90, 70,117,138,151,116,211,231, 43,175,190,181,107,217, 69,170, 68,165, 54,160,242, 70,179,
+148, 20,152, 84,149,126,182, 20, 0,205,158, 30, 30, 30, 55,111,222,188,118,237, 90,239,222,189,149, 74,229,169, 83,167,112, 4,
+211, 94,176, 18, 87,165,167,109, 17, 66,101,101,101,125,250,244,201,205,205,165, 40,202,195,195, 67, 36, 18,225,158,119, 22,135,
+189,180,180, 84,167,211, 13, 28, 56, 48, 60, 60, 92, 40, 20,250,250,250, 62,254,248,227,167, 78,157, 42, 45, 45,213,235,245,236,
+ 87, 93, 90, 90, 74, 9,196,157,251,203,252,195, 99, 5, 66,145,212, 55, 36,226,241,196,155,167,246,176,219, 34,132,234,235,235,
+203,203,203, 35, 34, 34,134, 14, 29, 42, 20, 10,241, 44,241,175,188,242, 10,222,192,207,207,143,229,160, 30, 30, 65, 65, 33,253,
+ 12,122, 85, 77,237,121,189, 94,105, 52,170, 1, 0,219, 86, 85, 86,210,182,132,125, 95,189,162,162, 34, 35, 35, 99,198,140, 25,
+125,250,244, 1,128,253,251,247,231,228,228,124,248,225,135,161,161,161,205,155,216, 77, 18, 42,108,208,164,228,253,181,116,129,
+124,248,120, 89,147,186,102,251, 47,121,105, 63,236,252,237,253, 87,163,238,220, 74,109,168, 12, 12, 12, 98,177,117, 25, 22, 97,
+ 77,238, 51,206,217, 86,157,204, 89, 97,236, 45,183,127,180, 65,242,208,186,117,235,218,255,172,242, 15, 58, 46,212,105, 85, 6,
+234, 66,181,233,118,189, 41,244, 20,217,119,123,209,205,146, 43, 5,167, 13, 38, 82,104,160, 64,103, 64, 74, 68,133, 4, 32,155,
+244, 71,167, 37,225, 46,242,170,170,170,174, 93,187,150,148,148,224,148, 35, 92, 66, 25,131,139,131,194,236, 21,108,159,207,157,
+162, 40, 28, 12,237,214,173, 27,243,147,112,246,236, 89, 0,136,139,139,195,133, 24,236, 77, 70, 78, 16, 2, 0,208,106,170,212,
+141,101,102,179,142,105,187, 7,160,168,168, 40, 38, 38, 38, 37, 37, 5, 16,216,244, 63,149, 74,229,154, 53,107, 18, 19, 19,135,
+ 13, 27, 6, 0,199,143, 31,255,245,215, 95,223,126,251,109, 6,111,218, 69,133, 70,255, 82,206,169,185, 83, 19,167,188, 52, 89,
+163,107,216,181,231,240,170,239,182,252,244,212,163, 81,119,218,168,148, 27,237,167,115,159, 14,169, 53,147,147,218, 85,239,188,
+203,201, 67, 56, 0,186,110,221, 58,154,124,185, 7,127,185,219,242,224, 8,173,217,215, 72, 84,158,173,209,147, 4, 28, 84,232,
+194, 50,169,166,142, 29,138,196,106, 82,169,212,131,192, 83, 8,128,144, 36, 40,204, 30,217,225,204, 77,179,217,108, 50,153,130,
+130,130,188,189,189,187,118,237,122,249,242,101,188,198, 34, 49,158,105,139, 51, 55, 77, 38,147, 86,171, 69, 8,117,233,210,165,
+188,188,188, 99,199,142, 87,174, 92,209,235,245, 6,131, 1,239,153,165,105, 69, 68, 68,220,186,117, 43, 63, 63,223,199,199, 7,
+ 59,236,167, 79,159, 86,171,213, 17, 17, 17, 18,137,132,253,170, 35, 34, 34,170, 46, 92, 41, 63,159, 43,241, 9,162, 29,118, 67,
+147,146,221,150, 62, 25,141, 70, 67, 81, 20, 86,196, 88,120,226,245,113,113,113, 42,149,221, 44, 31,147, 73,107, 50,170,165, 94,
+ 97, 30,210,192, 38,117, 5, 0, 98,218,126,255,253,247,216,150,186,247,134,213,214,214,238,221,187, 87,171,213, 94,187,118,109,
+218,180,105,131, 7, 15,198,242, 51, 43, 43,107,225,194,133,221,186,117, 99,185,204,218,218,218,156,156,156,223,119,239,250,227,
+ 80,222,191,223,152,250,220,171,211, 52, 6,245,141, 27,101,105,105,219,127,157, 48, 36,190, 67, 64,219,183, 55, 46,165, 53,238,
+ 70,117, 90,253,216,109,223, 59,111,179,175,134,230, 53, 71, 51,114,203,217,245,133,155,108,121,112, 68, 76,247,152,238, 94, 66,
+ 31, 2,140, 8,253,173, 52,100, 20,233,183,158,184,125,166,184,238,182, 22,106,117,230, 98, 53,170,208,163, 46,209, 49, 54,121,
+ 4,231, 18,225,114,243, 29, 59,118,124,228,145, 71, 0, 32, 48, 48,240,177,199, 30,195,244,135, 25,208,250, 97, 97, 90, 52, 26,
+141, 6,131,129, 32,136,232,232,232,250,250,250,178,178,178,186,186,186,200,200, 72,129, 64, 96, 48, 24,244,122, 61,222,204,222,
+153, 63,250,232,163,225,225,225, 87,174, 92,193, 29,229,184,139, 92, 40, 20, 62,241,196, 19,184,255,132, 5,143, 62,250,104,104,
+160, 95,173,226,175,130, 3, 27,174,236, 93,251,247,222,180,155, 39,127,149, 8, 40,118, 91,146, 36, 67, 67, 67,125,125,125, 47,
+ 92,184,112,235,214, 45, 76,160, 76,237,153,145,145,209,187,119,111,123,230, 6,189, 74, 85, 95, 36, 18,121,249, 7,246,240,242,
+238, 44, 18,121, 97, 29, 10, 0,183, 79,255,223,161,159,222, 77,232,161, 6, 0, 10, 53,143,199, 68, 0, 0,123,247,238,149, 74,
+165,189,123,247,142,140,140,196,188,137,229,231,204,153, 51,217,121, 19, 0,114,114,246,250,250,122,143, 24,249,120,255,248,190,
+207,191, 53, 75, 67,152,170,239,212, 37,191,243, 89,234,160,152, 54,230,205,241, 51, 63,161, 25,147, 99, 79, 81, 27,205,156,196,
+226,224,184,137,101, 92, 78, 30,106,137, 82,110,255, 57,176, 15, 28, 58,199,246,234,211, 49,120,104,144,228,209, 0,113, 39, 15,
+129, 4, 33, 15,189, 41,194,155, 84, 34,116, 89,109, 42,108, 50,117,238, 16,228, 21,217,203,166,247,138,147,222,117, 58, 93, 68,
+ 68, 68,191,126,253,148, 74,101,125,125,125,125,125,189,143,143,207,224,193,131,113,245,121, 92, 98,196,218, 22,231,189, 19, 4,
+ 17, 27, 27,171,213,106,171,171,171,239,220,185, 83, 93, 93,221,212,212, 20, 27, 27, 75,146, 36,182,101,169,189, 28, 25, 25,153,
+144,144, 16, 29, 29,125,227,198,141,125,251,246,253,249,231,159,158,158,158, 79, 62,249,100,191,126,253, 28,246,116, 71, 70, 70,
+ 38,200,198, 68,119,244, 87, 23,159, 46,220,247, 67,249,159,187, 3, 36,102,217, 24,199,182,190,190,190,241,241,241, 8,161, 19,
+ 39, 78,228,231,231,151,151,151,215,213,213, 45, 94,188, 24,143,152, 26, 52,104, 16, 75, 49,122,138, 50,170,148, 69,117,213,151,
+ 36, 30,129, 97,157,158, 8, 9,123,204,199, 55,242,171,175,191,193,182, 91,223,243,220,118, 92, 15, 0,248, 91, 67,247,175, 23,
+ 22, 22, 6, 7, 7, 15, 27, 54,108,210,164, 73, 26,141,166,169,169,233,219,111,191,157, 54,109, 26,254, 80,177,163,160,160,176,
+107, 68,248, 11, 47, 76,252,248,163,185,181,141,170,154,218,154,217,239,126,246,217,243, 99,198, 68,132,222,151,198,230,212,228,
+197,100,219, 80, 36, 11, 63,186, 41,108,196, 39, 15, 61, 28,232,212, 45, 90,247,216,112,211,159, 57, 37, 42,240, 38, 68, 93,189,
+ 5,229,102, 66, 40, 33,143,220, 49,235, 40, 8,145, 8,163, 7,141, 80, 7, 68,218,164, 78,163,209, 40, 20, 10,187,117,235, 22,
+ 31, 31,223,208,208,160,211,233,112,114,146,193, 96, 8, 12, 12, 28, 54,108, 88, 86, 86,150,209,104, 52,155,205, 22,175,129,217,
+108,198, 67,143,122,246,236,137, 11,136,234,116, 58,220, 80,177, 86,237,217,179,103, 93, 93,157, 90,173,102,255,240,247,237,219,
+215,215,215,215,181,180,118,215,108, 5, 2, 65,167, 78,157,112, 61,206,107,215,174,149,150,150,250,248,248,248,251,251, 39, 36,
+ 36,252,231, 63,255,177, 55,158,135,225,179,107,234,149, 5, 58, 93,157,127, 64,172,183, 79, 23, 31,223,136,166,198,242,165,169,
+ 63, 76,127, 65,182,181,185, 72, 58,133, 61,246,102,238, 28, 55,110, 92, 78, 78,206,173, 91,183,234,234,234, 38, 78,156,248,227,
+143, 63, 62,246,216, 99, 61,122,244,224,114,141,137,137,227,118,237,202,106,168,175,189,117,187,226,189,183, 95, 94,248,193,146,
+231,159, 28, 50, 76,223, 0,162, 54, 26,229,232, 84,191,144, 27,169,243, 62,246,206,211, 20,201,212,122, 28,213,159,133, 45,109,
+ 37,151,203,237,149, 84,108, 21, 91, 30, 28, 17, 57,100,244, 69,189,169,250,143,131, 34,147,246, 98, 35,202,109, 52,137, 9, 34,
+ 8,161,209, 29,253, 71, 62, 53, 38,112,224, 40, 59, 26,138, 50,155,205,145,145,145,143, 61,246,152, 86,171, 53, 26,141, 98,177,
+ 24,211, 31, 22,140, 33, 33, 33, 67,135, 14,221,183,111,159, 77,213, 73,146,100,191,126,253, 8,130,208,104, 52, 88,186,210, 1,
+ 25,163,209, 72, 81, 84,159, 62,125, 78,157, 58,101, 48, 24, 28,234,199,200,200, 72, 23, 47,220, 37, 91,129, 64,224,239,239,223,
+167, 79,159,206,157, 59, 43,149,202,234,234,106, 0, 40, 47, 47,127,230,153,103, 86,172, 88,225,208,220,108,214, 55,169,203, 13,
+ 6,149,180,161,196,215, 63,218,211,187,147,167,119,167,253, 7,171,136, 49,161,205, 50, 8,128,145,149, 52,100,200, 16,177, 88,
+ 92, 87, 87, 55,110,220,184,160,160,160,151, 95,126,249,240,225,195, 28, 79,245,137, 39,134, 72, 36, 18,223,171,249,111,191,253,
+122,120,108,247,101,115, 95,223,248,221,143,223, 10,117,247,171,165,113, 79,234,108,125,213,121, 95,122,231,239, 87,126, 18,207,
+140,109, 3,129, 64,208,127,204,216,160, 78,225,213,127, 95, 22,222, 84,196, 24, 43,124,130, 66,135,244,233,209,123,224, 35,218,
+176, 56,150, 64, 80,183,110,221,134, 13, 27,134,131,146, 66,161, 80,175,215,227,193,148,180, 47,223,165, 75,151,161, 67,135, 90,
+191,234, 82,169,180,127,255,254, 36, 73, 26, 12, 6,188, 37,221, 97, 77,207,253, 33, 16, 8, 6, 12, 24, 96, 81,236,183,253,128,
+ 36,201, 14, 29, 58,116,232,208, 33, 46, 46,142,162, 40,141, 70,163,215,235,135, 13, 27,246,209, 71, 31,113,176, 70, 70, 67,163,
+209,160,214,106,171, 37,146, 0,145,216, 71, 32, 32, 55,103,236,157, 57, 35,241,238,247,227,222,173,177,152, 93,190,124,185, 86,
+171, 5,128,216,216, 88,238,229,173,226,227, 7, 10, 31,125,116,214,167,216, 22,197,198,198,197, 62,247, 28, 73,182,145,234, 28,
+ 63,243,147,236,205,159,185, 54, 16,243, 97,158,175,211, 53,106,163,173, 92, 48,111,137, 45, 15,118,116,233,217,187, 75,207,222,
+ 0, 64,207, 83,196,158, 33,157,148,148, 20, 16, 16,128,187,209,113,119, 51,157,135,132,187,134,240,228, 73,209,209,209, 4, 65,
+ 28,187,124,207, 0,199, 85,171, 86,101,102,102,226, 13,204,102,179,189, 73,231,196, 98,177, 67, 23,184,157,124,123,188,189,189,
+189,189,189,157,108,153,152, 64, 27, 5, 2, 18, 64, 0, 64, 97, 91,123, 17, 10, 60, 61, 18,221,179,207, 29,102, 51, 53,111,222,
+ 60,215,108, 91,139, 61,157,229, 77,224,203,186,241,224,193,195, 6, 47,128, 85,101, 76,126,146,227,255, 29,213,201,131, 7, 15,
+215,128,128,175,167,225, 72,203,243,183,128, 7, 15, 30, 60,120,234,228,193,131, 7, 15,158, 58,121,240,224,193,163,253,129, 47,
+235,198,219,242,182,188,237,255,150,109, 43, 83, 39,216, 25, 12,206, 49,155,161, 93,217,114, 52,191, 95,231,220,126,224,242,152,
+ 81,139,203,127, 80, 46,156, 31,167,192,195, 45,212, 9, 0,104,251, 61,163,238,137,169, 74,238,251,178,104,148, 78, 13,130,108,
+137,173,197, 57, 59,117,218,247,235,156, 49,234,170,139,170,171, 43,170,106,212, 42,149,209,207, 79, 20, 26,236, 29, 18,210, 49,
+ 48, 36,134,139,237,185,147,223, 41,138, 11,139, 75,116,101, 21,168, 75, 71, 34, 58,210, 35, 42, 58, 54,254,137,183,218,158,112,
+219,102,232,148, 66,161, 72, 77, 77,165,255, 76, 73, 73,105,179, 89, 16, 93,190,186,251,120,206, 60,218,154, 58, 31, 80,208, 92,
+ 73, 16, 64,253, 28,208,254, 79,216,104,104, 42, 43,189,100, 48, 24, 99,186,249,143, 26, 22,225,239, 39, 81,214,235,202, 43,212,
+215, 21, 21,245,170,154, 46, 17,125, 68, 98, 47,123,182,202,154,194, 19,121,223, 11,161, 97, 90, 34, 12, 29, 8,209, 93,161,168,
+ 4, 29, 59,171,205, 57,116, 97,239,206,133, 67, 70,190, 25, 16, 28,203,241, 52, 92,214,155, 76,195, 54, 24,120,106,253, 89,194,
+148,212, 6, 18, 18, 31,218,133,171,187,143,231,204,195, 41,184,150, 18,255,144,116, 19,209,194,243,129,224, 77, 0,184, 85,122,
+ 41, 52,216, 99, 82, 98,108,191,222, 29,130, 2,164, 4, 16,190,222,146,216,232,192,132,145,145, 33,129,146, 91,165,151, 88,108,
+ 79,228,125, 63,124, 96,195,246,111, 97, 86, 18,244,136, 6, 0,240,242,132,158, 49,240,239,121, 48,184, 95,195,137,188,239,157,
+122,189, 93, 16,203,214, 47,191, 91,233,128, 57, 81, 0, 13, 23,148, 62, 77,130,174,209,159,107,134, 78,157, 51,247,241,139, 60,
+ 90,139, 52, 45, 70, 97,114, 31,198,254, 80,245,176, 63, 40, 51,182,215, 85, 23, 25,141,198,199,226, 59,254,247, 49, 8, 8,177,
+ 88, 40,245, 32, 69, 34, 65,116,183, 0,131,193, 88, 87, 93,100,207, 79, 23, 66,195,188, 89,160,211,195,141, 50, 80,170,160,190,
+ 1,182,236,129,119, 62,133,197, 95,195,144,120, 16,160,134,115, 39,191,123,104,158, 41,115, 18, 25,155,100,205,101,102, 25,166,
+ 40,166, 53,178,179, 31, 9,238,124,109,113,206, 7, 14, 28,200,205,205,229,114,206,109, 54,118,155, 7, 19,120,178, 78,122,202,
+206,214,175,136,217, 6,110, 81, 75,181,103,107, 28,215, 53,199,211,158,162,177,185,171,234,154,138,184,232, 64,204,152, 22, 63,
+121, 72,200,122,149, 62, 54, 58,176, 80, 81, 97, 51,232,169, 40, 46,156,150, 8, 0,240,251, 17,248,191, 77,240,212,112, 24, 55,
+ 10,174, 21,193,249, 43, 72,234, 65, 12,232, 13, 99, 71,194, 47,251, 10,227,159,112,151,195,110,243, 22,185,111,114, 63, 22, 39,
+ 23,147, 96,106,106, 42,151,171,176,142, 48,112,151,216,204,235,229,226,191, 51,207,249,192,129, 3, 59,118,236,192,235,101, 50,
+ 25,251, 57,147, 36,233,176,108, 17,143,214, 37, 77,151,109, 45,169,211,186,131,133, 35, 29,216,163, 33, 46,182,238,112,247, 56,
+118, 1,219,236, 98,226,104,107,177, 25,247,222,170,170,106,245,232,161, 17, 8,193,209,147,101, 26,173, 17, 0,226,251,133,133,
+ 4, 73,203,202, 27,139,110, 40, 73, 82,208, 61, 42,224,248,233,166,184,158, 54,108,139, 75,116, 67, 7,130,222, 8,191,229,193,
+161,147,168, 83, 40, 17, 21, 1, 99,134, 65,143,104,130, 20,130,136,132,193,253,225,171, 52, 29,203, 9, 51,235, 53,217, 91, 96,
+105, 82, 76,213,246, 64, 76,237,108,147,230, 44, 8,145, 35,237, 90,248,239, 92,204,105,222,204,204,204,148,201,100,236, 27,243,
+ 14,251, 3, 4,199, 61,236,220,251,220,173,149, 8, 71,109, 98,147, 97,185, 83,182,205, 51,183,158,184,211,174,155,111,213,197,
+196,209,214,230,102,120,111, 4, 0,181,221,110,212, 85,165, 50,250,249, 73, 0,160,236,118,131, 86,107, 2,128,152,168,128,144,
+ 32,233,133, 43,119, 10,174,215,121,120, 8,163,187,249, 43, 85,182, 39,130, 44,171, 64,209, 93,129, 0,120,122, 4,244,239, 69,
+ 72,196, 96, 50,193, 83,195,193,223, 7, 20,165, 48,118, 4,116, 13,135,178, 10,247, 14, 63,166, 25,211,230, 52,169,237,138, 52,
+109, 82,158,245,183,196, 41, 5,234,212, 37, 39, 37, 37,101,102,102, 2,192,148, 41, 83, 28,135,207, 4,252, 16,149,251, 6,103,
+ 43,187,181, 23,135,221, 38, 13,113,164, 48,167, 50,168,108,239,161,149,250,229,137,169, 74, 46,187,242,243, 19, 41,235,117,193,
+129,158, 73, 19,123,152,204,148, 68, 34, 20, 10, 4, 8,161,241, 79, 69, 39, 38, 68, 19, 4,212, 42,181,126,126, 34,155,182, 93,
+ 58, 18,197, 55, 81,143,104,120,242, 9, 64, 0,215,138,160,111, 15, 8,240,133,103, 70, 1, 69, 1, 41,132,194, 27,208,165, 35,
+193,126,147, 29, 46, 56,155, 66,220, 6,201, 73, 22,135,224,114, 68,154,226,153,178,209,230, 50,247,163, 59, 37, 87,233, 45, 17,
+ 66, 9, 9, 9,124, 86,233, 67,195,155,240,112,116, 19,165,221, 11, 23, 68, 16, 66, 32,152,166,108,249,153,160,237, 1, 8,129,
+192, 17,149,135, 6,123,151,149, 55, 2,192,138,181,103,254,186,124,199,104,164, 40,234,110,137, 90, 60,171,100, 89,121, 99,104,
+176,183, 77,219,232, 72,143,227,249, 0, 0,193, 3,225,252, 21,152, 61, 29, 98,186,130,136,132,207,191, 5,177, 8, 4, 2, 56,
+158, 15,209,145, 30,220, 25,193,181, 48, 37,173,215,232,123,238,166,112, 39,174,124,139,119, 78,247,174,224, 5,188,210, 94,105,
+ 92,118, 15,198, 89,222,180,247, 69,231,114,206, 50,153, 44, 33, 33,129,203, 57,179, 20,137,227,209,174,120, 19,248, 49,236,255,
+109,181,173,148,213,132,182, 7, 32,112, 64,196, 33, 33, 29,139,110, 40, 41, 10,125,240,222,224,194,162,186,191, 11,107, 9,226,
+191, 53,154, 40, 10, 21,221, 80,134,132,116,180,105, 27, 21, 29,187,247, 15, 48,155, 1, 41,224,208, 73,200, 58, 8,207,188, 6,
+163, 95,132,195,167, 0, 0,204,102,216,251, 7, 68, 69,199,186,239, 70, 89, 4, 58,221,237,176, 51,115,200, 45,168,211,122, 3,
+ 46,206, 59,184, 63, 63,201,229,115,102, 41, 18,199,163, 93,241, 38, 79,157,173, 12, 98,170,146,139,207, 30, 24, 18, 35,145,136,
+ 79,231,223,166, 40,244,140, 44,234,226,149, 59, 95,172, 56,249,249,242, 19,152, 55, 79,231,223,150, 72,196,246,198, 20,197, 63,
+241,150, 25,124, 87,174, 7,179, 25,214,125, 14, 63,253, 2,163, 7,195,128, 94,112,120, 43,152,205,176,114, 61,152,193,151,251,
+152, 34,102,190,161,179, 98,211, 30,191,180, 46,152,140,131,131,134,204, 5,224,150,156,132, 79,152,217, 57,238, 84,124,211,217,
+ 47,132,203,231,108, 50,153,248,151,232,129,224, 77,158, 58,155,117,226,246,128, 86,220, 21, 23, 1,219, 37,162, 79,117,157,126,
+103,118,193,237, 74,117,226, 83,209, 31,206, 27,156,252, 90,255,243,151,170,118,102, 23, 84,215,233,187, 68,244, 97,177, 29, 50,
+242,205,163,249,190, 73,111, 67,254,101,248,254, 75, 88,252, 54,200, 95,132, 31,182, 67,210,219,112, 52,223,119,200,200, 55, 93,
+144,144, 78,241, 38,199,245,173, 2,230, 64, 70,215, 54,176, 32, 62,151,235,166,112, 55,116,249,156,121,234,188, 47,104,157,138,
+152,214, 93, 46,220, 59, 97,184, 36, 39,113,183,229,110,222,146,227,218,188, 58,215,142,235, 84,111,149, 72,236, 21, 21, 51,184,
+174,186, 72, 81, 82,113,242,236, 45,122, 12,123,104,135, 78, 14,199,176, 7, 4,199, 38, 78,254,234,220,201,239,126,222, 91,184,
+228,255,218,116, 12,123, 27,243, 38,180, 97, 54,155, 11,167,209,234,231,204, 59,236,247, 87,123, 58, 69,166,100,107,181,200, 86,
+183,117, 54,231,174, 61,156,179,179, 8, 12,137, 9, 12,137,137,115,201, 54,254,137,183, 56,230,189,223,119, 70,104, 63,120, 32,
+206,150, 32, 8, 65, 51,112, 4, 28, 87,145,195, 96,175,252,206,163,237, 30, 19, 95,214,141, 7, 15, 30, 60,156, 5, 31,235,228,
+193,131, 7, 15,158, 58,121,240,224,193,131,167, 78, 30, 60,120,240,224,169,147, 7, 15, 30, 60, 30, 6,240,101,221, 90,199,150,
+101,148,158, 91,109, 21, 10,133, 66,161,200,204,204,116,193,246,198,141, 27,197,197,197,153,153,153,233,233,233, 0,192,236,186,
+229,159, 47,111,251, 16,219,182, 50,117,218,123,159,173,225, 48,195,163, 37,182,247, 5, 22, 53,100,156, 58,103,218,214,230, 28,
+186, 28,109, 47,175,240,125,228,253, 6,231,107,165,161,190,218,111,145,193, 12, 0,233,233,233,179,103,207,118,230,162,209,163,
+194,109, 70, 99,131, 84, 42,221,190,125,251,171,175,190,106, 54,155, 13, 6,131, 59,134, 81,187, 48,175,240,125,183,189,191,160,
+243,147,112,114,146,193, 96, 16, 10,133,124,102, 82, 59, 85,157, 22,109,206,230, 67,162,199, 89,179,191, 36,174,217,114, 81, 97,
+238,227, 77,155, 37,183,184,204, 7,142,167,173,149,203,229, 22, 51,129,115,180, 69,127,125, 66,244,255,236,167, 60, 3, 0,160,
+191,238, 38,138, 17,253, 29,207, 83,237,115,245,125,132, 96,235,113, 3, 0, 60, 51, 64,212,187,243, 21, 44, 30,185, 16,104, 68,
+224,233, 27,151,170,142, 85,116,109,242,246,122,122, 84,125,231, 16, 34,239,240,129,134, 70,221,184,113,227,244,122,189, 59,222,
+ 79,183,126,110, 89,108, 29, 94, 11,247,102,233, 66,187, 90,182,108,217,194,133, 11,163,163,163,157, 50, 20, 10,133, 36, 73,146,
+ 36, 41, 20, 10, 5, 2, 65,106,106,234,194,133, 11,205,102,179,201,100, 50,153, 76,238, 75,155,223,187,119, 47,251,205, 25, 55,
+110,156,195,157,228,228,228, 56,181,253, 67, 69,157, 44,188, 57,112,224,192,252,252,124,135,205,215,102,115,100,177,181,216, 79,
+ 74, 74, 10,118, 66,219,172,206, 98, 90, 90,154,245,176, 98,124, 38, 44,106,148,182, 5,128,164,164, 36,153, 76, 70,207,101,203,
+209, 22,115, 37,254, 55,245, 95, 64,243,230,162,103, 61,150,237,214,177,156,182, 95,193,252,222, 17,194, 38, 29,122,127,188,199,
+169,235, 38,173, 30,105,141, 48,186,243,149,203,165,102,135,242,179,236,226,202,252,106, 47, 95, 47, 34,180, 67,104,135,206, 49,
+ 55,111,233,227, 98, 77, 18,225,157,172,236,154,173, 91,183, 78,154, 52,137, 23, 20,173,130,212,212,212, 9, 19, 38, 44, 91,182,
+204,162, 13,199,199,199,255,235, 95,255,154, 48, 97,130,237, 23,146, 36,197,205, 40, 43, 43,235,222,189,187, 80, 40,244,241,241,
+ 41, 42, 42,242,246,246, 62,115,230,204,201,147, 39,223,126,251,109,123, 7,197,143,158,126,127,233, 55, 17,175, 33, 8, 2,127,
+ 95,109, 98,207,158, 61,214, 38,244, 26,132, 16, 23, 42,220,189,123,183, 83,219,183, 31,224, 49, 69,220,243,220, 73,167,120,147,
+125, 95, 44,211,127,113, 28,104,140, 25,103,233,210,165, 31,124,240, 1,189,198,125,236,201,228, 62,155,103,194, 62, 43, 15,190,
+ 40,250,155,193,156,223,129,163,173, 77,117,185,232, 89,182, 41,227, 16, 66,193,215,231,119,239, 36,148,138,137,200, 16, 65,117,
+ 3, 50,153,133, 53,141, 72,165, 65,197, 85, 20, 65, 64, 48,117, 81,161, 80,216, 60, 58, 66, 8,170,119,196, 68, 68, 85, 87, 87,
+ 69,134,135,244,233, 29, 69,122, 7, 68,133,215,107,205,170,138, 10,115,185, 82, 39,213, 43,138,139,251,185,187,224,173,179,147,
+ 88,183,220,214,250, 91,238,110,207, 87,161, 80, 16, 4,209,171, 87,175,172,172, 44,230,227, 24, 56,112, 32, 11,111, 2,128, 72,
+ 36,242,240,240,168,169,169,137,141,141, 29, 48, 96, 0, 73,146,223,124,243,141,217,108,238,211,167,207, 47,191,252,114,230,204,
+153,139, 23, 47, 10,133, 66,123,218,117, 32,192, 37, 0, 0, 18, 59, 73, 68, 65, 84,243,217,103,159,197,215,107,239, 45,102,161,
+179,221,187,119,227, 59, 99, 83,250, 32,132,170,170,170,184, 80,167, 83,219,183, 19,198,108,169,234,196,237,210,158,102,108,179,
+176,227, 7, 31,124,192,125, 78,135, 22,234, 2,123,238, 30,199,146,217,244,123,155,155,155,203,148,156, 92,108, 51,222,245,182,
+ 46,167, 52,227,155, 38,118, 43,132,144,135,152, 16, 10,192, 83, 2,245, 26,100, 48, 35, 47, 15, 66,107, 4,173, 1,117, 14, 16,
+ 80, 20, 20, 86,152,115,115,115,109, 10,207,198,202,211,126, 34, 47,145, 8,189,153,244,152,217,132, 42,149,134,210, 27, 42, 1,
+148,249,251,235,239, 84,149,136,133,170,171, 37,245,229,186, 92, 39, 99,166, 45,245,223,157,157, 51,148, 57, 87,139,117, 53, 20,
+123,168,171,251,111,113,139,192,192, 92,123,228,210,138, 77,107,252,248,241,184, 25, 92,185,114, 5, 47, 96,189, 57,126,252,120,
+ 22, 67,137, 68,210,212,212,212,179,103,207,209,163, 71,207,159, 63,255,245,215, 95, 7, 0,163,209,184,113,227,198,252,252,252,
+115,231,206,253,252,243,207, 90,173,214, 94, 72, 58, 49, 49,209,229,115,254,225,135, 31,216, 63, 63, 92, 84, 36,189, 19,142,219,
+ 63, 60, 14,187, 77,229,216, 54, 68,102,173,221,218, 0,204, 34,133, 52,223,113,228, 62, 46,250, 72, 46,151,219,119, 1,236,190,
+186,216, 91,183,182, 69, 8, 85, 31,126, 63, 44, 66,168,214, 34,132,128, 32, 64, 99, 64, 90, 3, 24, 77, 8, 0, 76, 20,162, 16,
+ 2,128, 75, 23,242, 21, 10, 5,128,216, 98,183,245, 85, 87,196, 33, 1, 33,254,254,245, 74,109,189, 74,121,234, 74, 85,185, 18,
+121,122,106,162,187,170,181,234,154,190,221,141,189, 34,245,233, 91,243,139,138,138, 0, 60,128, 71,203, 36, 39, 65, 16, 89, 89,
+ 89,227,199,143,207,206,206,238,221,187,119, 82, 82,146, 67,222,196,212, 89, 93, 93,237,233,233, 57, 98,196,136,175,191,254, 90,
+ 36, 18,201,229,242, 31,127,252, 49, 63, 63,255,212,169, 83, 7, 15, 30,188,116,233, 82,112,112, 48,203, 28, 75,179,103,207,182,
+231,176,127,255, 61, 91,161,233, 86,113,216,247,236,217,243, 96, 57,236,244, 43,230,172,252,108, 95,197, 75,173, 39,244,110,231,
+ 69,111,112,215,144,205,114, 93, 56,250,233,242,172, 78, 25,239,122, 89, 43, 80,159,171,243,111,232, 81,101, 61, 69, 16, 2, 47,
+ 29, 34, 8,194,100, 70, 58, 35,232, 12,160, 55,130,222, 8, 58, 3, 24, 77,205,170,231, 94,218,245,190,242,126,249,237,136,200,
+ 8,111,129,135,176, 86,171, 61,120,230, 86, 97, 89,121,109,157,122, 80, 95,179, 94, 99,210, 25,204, 90, 29,117,179, 12, 52, 90,
+248,234,171,175,248,153, 13, 90, 46, 57,123,245,234, 21, 21, 21,165, 80, 40,178,179,179,177,240,116,200,155,216, 97,239,223,191,
+191,135,135,199,143, 63,254, 56,107,214,172, 47,191,252, 18, 33,116,250,244,233,188,188,188,139, 23, 47,170, 84,170,238,221,187,
+ 55, 52, 52,176, 84, 49,122,238,185,231,172, 5, 53, 86,217,236,154,244,127,211, 97,111, 53,213,121,191,152,136,118,144,109, 86,
+206, 98, 9, 74,222, 95,150,151,201,100,152, 61,109,202,103,123, 10,218, 38, 45,114,241,220, 95,254,182,169, 83,160,224,197, 97,
+ 98,189, 17,124, 61, 9, 33,129, 0,192, 96, 70,122, 35, 52,233, 81,147, 14,105, 12,200, 76,129,205, 78,227,151,191,109,234, 31,
+167,232, 30, 83,247,123,222,157, 58,149,110,112,223,134,199,252,212, 34,177, 94,163,163,110, 85,160, 38, 29, 97, 54, 19,193,129,
+ 4, 16,124,141,135,214, 1,110,207, 76,247, 37, 59, 59,155, 73,106, 54, 35,158, 2,129, 96,209,162, 69, 36, 73,254,244,211, 79,
+ 27, 54,108,120,237,181,215,150, 46, 93, 74, 16, 68, 73, 73,137, 86,171, 77, 73, 73, 49,153, 76,201,201,201, 44,137, 1, 46,107,
+ 61,222, 97,127, 32, 85, 39, 51, 60,103, 77,145,246,232,233,190, 11, 79,102,136,147,121,146,185,185,185,184, 20, 98, 90, 90,154,
+117, 58,174, 67,222,196, 61,236,214,182,102, 10, 52,122,164, 55,162,250, 38,164, 51, 34, 17, 9, 0, 96, 50,131,206, 0, 26, 3,
+170,109, 68,213, 13,232,124,137, 9, 33, 72, 74, 74,210,222,187, 79, 51, 5,101, 21,134,162, 34,229,137,115, 74,132,136,107, 69,
+212,244,137, 38, 18,161,202, 59,176,255, 40, 52,106, 16, 69,193,147,131, 9,169, 4,198, 37, 62,107,110,147,187,231, 26, 92,171,
+226, 23, 24,216,118, 77,200,162, 1,167,165,165,197,199,199,159, 59,119, 46, 43, 43,139,185,222, 94,103,209,242,229,203,253,253,
+253,177,112, 91,191,126,253,172, 89,179, 54,108,216,128, 57,119,249,242,229,245,245,245, 13, 13, 13, 26,141,134,229, 4,222,124,
+243, 77,166,163,141, 37, 39,187,183,254, 63,235,176, 63,240,212,153,159,159,111,175, 95, 88,161, 80,112,201,106,106,149, 16,149,
+205,101,123,239, 6, 86,157, 22, 4, 10,140,138,219, 54, 85,103, 75,138,160,165,165,165, 93,191,126,189,244,248, 55, 8, 81,132,
+ 6,196, 36, 1, 0, 6, 19, 50, 35,104,212, 32,189, 17, 76,102, 48,153, 97,226,115, 83,100, 50,153, 5,237, 98,219,146,227,171,
+123, 71, 82, 71,206,155, 5, 2,168,172, 38,164, 30,176,239, 40,104, 52, 4,162, 32,190,151,168,244, 54, 53,242,201,196,177, 99,
+199,230,156,168,104,203,176,140,187,109,237, 57,161,109, 3,220,171, 62,126,252,120,252,232,177, 11,181,104,209, 34,155, 27, 83,
+ 20,117,254,252,249,225,195,135,211,107,214,175, 95,143, 89,204,104, 52,154,205,230,235,215,175,135,132,132,176,143, 92,120,238,
+185,231, 92,208,140,188,195,238, 70,234,204,207,207,119,135,215,140, 5, 90,106,106, 42,142, 15, 90,232, 77, 76, 64, 73, 73, 73,
+110, 37, 77, 11,214,198,127,226, 72,130, 67,189, 76, 19, 40, 48,226,158, 92,108,237, 97,217,110,157, 61,219,152,152,152,245,235,
+140, 99, 30, 17, 81, 0, 70, 19,229, 33, 34, 16,130, 70, 29,210,155,144,153,130,252, 98,179,137, 66,246,114,176, 99, 98, 98,126,
+250,222, 52,178,191,240,197,241, 66,181, 22,169, 26,161,177,137,136,233,138, 76, 38,130, 0,143,218,122,170,188,210,240,108, 82,
+ 47,161, 80,216,198,186,204,169,111,137,107,182,247,107, 28,206,192,129, 3, 63,253,244, 83,166,192, 92,182,108,217,132, 9, 19,
+236, 61, 35,131,193, 16, 23, 23,167,211,233,132, 66,161,167,167, 39, 0,236,220,185,115,242,228,201, 90,173, 86,167,211,233,245,
+122,111,111,111,179,217,204,126, 57,174,245,179,243, 14,187,187,168,179,133,188,201, 98, 46,147,201, 48, 63,226,248, 32,157, 8,
+197, 20,155, 54,187, 98,220,196,155, 76,238, 99,239,106,103,242, 38, 51,238,201,197,150,157, 55,237,217, 18, 4,241,229,242,117,
+243,222, 73,150, 74,128,162,224,145, 8, 33, 65, 0, 66,119, 73,211,140,132,147, 38, 77, 98,177,253,108,217,186,249,115,147,205,
+ 20, 24, 76,200,108, 6, 2, 96,220,104, 80, 53, 18,127, 93,209,234,140,130,137, 19, 39,185, 59,169,243,127, 10,214,217,239,114,
+185,124,252,248,241, 44,253, 69, 6,131, 65,171,213, 42, 20,138,126,253,250,153, 76, 38,145, 72,180,123,247,238,132,132, 4,157,
+ 78,167,209,104,174, 95,191, 30, 16, 16,192,146,156, 68,131, 14,127,113,113,213,121,135,221,141,212,233, 38,189,105,211, 17,179,
+118,207,221,154, 21,239, 50,111,194,189,125, 65, 52,251, 3,183,180, 80,123, 17, 79, 46,182, 43,215,172,147,203,229, 4, 1,199,
+174,153,112,150, 18, 0, 32, 4, 73, 73,147, 28,126, 99,150,126,181,230,221,119,255,129,173, 16,130, 35,103,160, 73, 67, 81, 20,
+ 76,156,152,248,212, 83, 79,241,124,215,138,176,224,205,228,228,100, 76,154, 89, 89, 89, 4, 65,216, 36, 80,131,193, 32, 16, 8,
+ 58,117,234,212,216,216,120,246,236,217, 1, 3, 6,152, 76, 38,149, 74,117,225,194,133,110,221,186, 5, 5, 5,105,181, 90,147,
+201,228, 80, 68,227,220,120,167, 68, 40,239,176,183,136, 58,237,165,112,114, 33, 47,246,244, 79,135,123,192,163, 33, 45,118,226,
+178,118,227, 8,123,231,204,229,184,204,225,234,116, 4,211,217,146, 74,114,185, 60,227, 93, 47,204,164,206, 86, 10,162,111, 23,
+238, 23,138,138,138,226,114,175, 68, 34,209,154, 53,255,119,249,242,229,181,107,215, 2, 64,163, 26, 18, 19, 19,163,163,163,227,
+226,226,220, 23, 16,108, 73,191, 80,139,250,148,238, 95,136, 19,238,237, 8, 82, 40, 20, 8,161,236,236,108,235,159, 44,168, 19,
+ 87, 34, 50, 24, 12, 17, 17, 17,245,245,245,159,124,242,137, 74,165,234,220,185,179, 90,173, 54, 24, 12, 56,226,233,240,208, 46,
+248,236,149,149,149, 45,191,228, 86,217,201,131, 71,157,247,189,204, 89, 84, 84, 84, 91,102, 32,181,226,177, 90,242,122, 59,236,
+112,103,185, 93,174, 5, 52, 72,146,236,215,175, 31,253,231,248,241,227,113, 10,119, 59,188,207,247,189, 77,186, 76,217, 22,165,
+217,122,246,236,185,126,253,122,135,165,217,176,162,164, 40,202,104, 52,226,233, 63, 0,128,162,168, 54,152,254,131,135,115,143,
+152, 79,126,230,193,131, 7, 15,103,193,207, 18,207,131, 7, 15, 30, 60,117,242,224,193,131, 7, 79,157, 60,120,240,224,193, 83,
+ 39, 15, 30, 60,120, 60, 12,176, 81,214,205, 98,250, 53,155,211,178, 61,196,101,161,152, 9, 82,244,181,243, 37,180,248,123,213,
+ 18, 91,123, 89,107,238,182,125, 88,239,179, 83,134,208,198,101,221,156,133, 51,227, 14,197,214,182,244,178,197,204, 73, 22, 63,
+185,233, 3, 66,151, 39,106, 78,147,188, 91,141,160, 13,190, 93,133,133,133,203,151, 47,199,203,239,191,255,126, 92, 92, 92, 59,
+255,216, 90,220,171,191,255,254, 27, 0,122,246,236,233,214,131,202,229,242,103,159,147,239,254, 53,205,162, 25,228,252,118,110,
+247,175,105,246, 26,134, 92, 46,191,124,249,114,223, 62,143, 80, 8,240, 2, 0, 92,188,116,207, 26, 10,113,106, 87,184, 29,186,
+214, 2,241, 24, 51,139,137, 14,184, 95, 56,184,185, 86,194,195,138,130,130, 2,183,190, 77,173, 57,253, 7,199,220,245, 43,229,
+ 54,190, 0, 22,108,197, 28,210,192, 78,100, 45,175,122,136,247,128,185,192, 58,225, 14,255,106, 51,133,139,121,232,206,221,186,
+ 0, 64,149, 78,103,210,234, 1, 0,234, 27,160,121,202, 78,246, 19,163,121, 19, 0, 86,172, 88,193,165,132,153,128, 0, 10, 1,
+254, 23,192,246,194,218,117,105,110,162, 48,250, 94, 97,210,228,126,175, 92,126,249, 49,111,142,123, 38, 30, 64,190,251,215, 52,
+167,118,133,233, 18, 0, 30,121,228, 17,122, 13,190,123,244, 26,119,127,105,232, 97,102, 28,199, 44, 88,220, 79,252, 46, 56,117,
+213,214, 27,115, 55,119,193,182, 37,223, 21, 55,125, 24, 10, 10, 10, 86,174, 92,185,110,221,186, 7,131, 58, 93,254,180,222,195,
+161, 46,152,180,160,234, 33, 93, 13, 9, 0,240,191, 22,191,114,154,116,199,223,247,162, 98,155, 20,194,205,112,252,206,127,206,
+ 93, 40,174,157,180,116,131,251,158,153,133,110, 2, 0, 11,109, 69,177,222, 15,246,250, 25, 44,101,191,240,189,122,245,213, 87,
+ 1, 0,255,107,249,254,224,161,157,182, 12,199,140,249, 77, 46,127,198,229, 55,100,220, 51,241,179,103,207, 6, 72,223,253,235,
+ 61,235,177, 14,101,193,199, 31,255,179,188,162, 70,171,169, 31, 52,104,208,197,139,151,127,250,241, 7,139, 53, 27, 55,254,224,
+ 86,234,100, 14, 87,115,106,206, 89,102,113, 89,103,217,211,122, 51,238,199,117,193, 22, 79,223,195,114,122, 14,105,193,166,173,
+203,100,130,121,147,162,168,244,244,244,140,140,140, 25, 51,102,176,111,207,156, 31,158,123,158,187,128,249,121,196,224,184,204,
+242,129,117,232,188,216,100, 55,204, 80,132, 21,217,113, 25,232,146,110, 31, 83,167, 78,101,121, 96, 73, 73, 73,214,140,249,193,
+ 7, 31, 16, 4,145,146,146,226,144,148, 59,119,235, 2,254,190,191, 36, 79, 14, 34,134, 86,252,103,141,119,109,189,187,121,211,
+ 66, 73, 81, 8, 40,116,143,146,162, 90, 54, 67,144, 61, 21,143,239,149, 53, 99,110,220,184,177,103,207,158,207, 12, 29, 0, 0,
+224,227,229,166, 75,206,249,237, 92,122,122,122,206,111,231,156, 53, 44,187, 85,113,179,164,248,239,107,127,175, 88,177,188, 71,
+143, 24, 10, 89,174,113,183,234, 76, 75,187, 27, 79,160, 23,156,229, 77,166, 62,224,232, 99,185, 92,155,192, 53, 91,153, 76,134,
+ 39, 54,195, 37,181, 45,222,113,122,242, 51, 22,230,181, 62, 10,182,114, 97,144, 30,205,155,243,231,207,207,200,200, 56,118,236,
+ 24,119,222, 4,103,202,108,144,214,238,182,197,140, 24, 54,215,219,116,186, 49,165, 90, 79,156,193, 52,204,204,204,180,230,117,
+235,169, 97,219, 32,190,137,177,125,251,118, 11,210,196, 50,129,150,162,116,109, 78,155,184,165, 40,109,218,245,255,188,103,173,
+238,220,173, 75,104,144, 84,177, 75, 49,105,233, 6,240,247,133,250, 6, 16,113,154,186,109,254,252,249,180,207, 62,127,254,124,
+ 46, 38, 20,130, 8, 47,248,118, 38,188,177, 17, 66, 60,225,239,122,203, 53, 87, 56,204, 5,236, 66,145,200,127,255,251,223, 22,
+164,137,239,213,178, 87,199,175,249,253, 84, 88, 84,199,202,155, 85,246, 36, 39, 0,176, 8, 79,135,122,106,247,175,105,216, 91,
+183,224, 83,135, 45, 68, 42, 21,201,100, 99, 16,136,126,220,184, 1, 79, 43, 99,189,198, 53, 18,113, 95,203,100,250,233,204, 71,
+227, 80,123,226,159,232,240,168,189, 95, 89, 30,129,107,182,208, 60, 14, 56, 45, 77, 9,160,148,203, 3,184,243, 38,109,139,137,
+146,158, 91, 18, 91, 57,123,147, 11, 10, 10, 86,172, 88,129,199,191, 14, 31, 62,252,232,209,163, 28,123, 44,102,167, 44, 5,128,
+244,212, 15,238,143,195,158,153,153,137,163, 96, 22,228, 75,255,201, 62,127,176,189,206, 34,135,119,144, 69, 87,114, 7,125,139,
+105,210,100, 58, 89,246,122,232,180, 80,170,126,254,113,228,179, 0,100,159,168, 97, 43,252,231, 28, 0,160,204, 5,162,151,215,
+152, 76,156, 42, 85,196,198,198, 58,219, 62,238,172,135,127,173,131, 46,225, 80,149, 45,254,241, 7,195,171,219,108,172,105,121,
+148,131, 5,116,167, 80,197,175, 75,125,122,123,120,119,159,187,125,233, 27,253, 30, 9,139, 27,255, 57,203,189, 98,121,238,236,
+238, 60,110, 12, 52,111,166,165,165,225,222, 33, 46, 59,127,235,173, 57, 22,193, 13,235, 53,110, 10,113,186, 86,167,218, 66,111,
+ 90,196,139,216,217,147,150,183, 44,241, 74,150,155, 76,219, 50,107,142, 2, 0, 49, 85,201,110,203,226, 92,114,100, 64, 38,243,
+ 66,243,148,254,206,190, 23,115,230,204, 1, 0,138,162, 22, 44, 88,176,106,213, 42,204,155,120,142, 27,118,201,137,121, 19, 47,
+164,167,126,144,189,249, 51, 46,110,123, 43,199, 58,163,162,162,112,224,131, 89,118, 2,223, 62, 46, 97, 11,235,206, 34,224,208,
+211,221,242, 34,154, 88, 90, 90,144,166, 67,201, 9, 0,191,127,248,233,132, 47, 87,152,100, 67, 73, 0,239,147, 69, 7,138,107,
+ 1,192, 36,123,199,120, 41,152, 8,121,203, 5,231,136, 75,115,169,125,110,235, 59,175,149, 21, 38, 47,106, 58,104, 8, 11,182,
+189,198, 5,213,201,145, 79, 55,110,220, 8, 0,179, 39,140, 56,117,251,142, 79, 63,159,242,125,197,224, 33,153,252,206,203,129,
+225,227,193,109,176,238, 85,231,114,187,210,210,210,142, 31, 63,142,123,204, 88, 22,184, 28,212,169,158, 16,135, 82,203,230,172,
+222, 54,219, 3, 75,239,104, 59,156,125,130,169, 55,211,210,148, 0,144,153,233,162, 60,119, 65,111, 34,132,232, 66,161,195,134,
+ 13, 59,122,244, 40, 59,111,182, 16, 36,151, 32,151,245, 74,150,199,134, 63,167, 56,196,139,163,159, 88,138,226,234,128,110,125,
+169, 92, 6,206,182,177, 14,122, 58,140,235, 79, 90,183, 19, 77,236, 86,245, 68,124, 16, 12,149, 78, 94, 99,170,168, 6,127, 95,
+178,118,107,246,170,124,224, 48,215,186,107,229, 34, 46,188, 63,125, 80,127,136,122,231,114,111,239,215, 10,186, 38,193,183,139,
+172,215,184, 79,117,166,166,166, 14,127, 52, 78, 54, 52,118, 66,159, 69,203, 87,173,189,154, 95,158,252,228,160,202,221, 57, 42,
+101,131, 11,207,194,194,157,183,215,174,108,202, 76, 46,217, 8,173,149,156,228, 90,176,216,222, 50, 52,207,244,106, 51,120, 69,
+111,105,239, 25,181,164, 66,137,251, 96,179,196,161,107,197, 29, 92,176,194,177, 23,146, 36,231,205,155,119,246,236, 89,135, 33,
+206,214,164, 78,123, 21,201,185,164,196, 51, 47,152, 41, 60, 49, 87, 70, 69, 69,209,105,128,214,229,198, 88,190,177, 92,226, 20,
+ 45, 79, 78,194,210,210,102,103,145,195,221, 22,127, 53, 91, 52,121,141,246,118, 33,121,114,141,113,231, 59,196,184,175,247,188,
+ 53,229,230,158, 27, 19,150,253, 4,164,187,234, 62, 45,202,132,125,203,118,245,190, 57, 22,106,154, 22, 38, 44,178,185,198, 29,
+177, 78, 90,114,238,222,245,169,176,115, 47,111,136, 45,205, 75,111, 36,208,159,133,101,178,203,229,172,119,190,180, 57,180,146,
+ 70,115, 37, 0, 28, 60,248,140,197,175, 54,219,149, 61,247,156, 75,143,115,219, 39, 39,165,165,165,209,170,211,122, 70, 87,186,
+197, 98,213,105, 93, 63,138,251, 81,220,145,230,221, 26,151,175,196,242,147,169, 64,185,139,214,204,204, 76, 23,120, 51, 35, 35,
+227,200,145, 35,104,123, 0, 49, 85,185,114,229, 74,132,144, 64, 32,112,107,102, 18,184, 41,175, 19, 23,204,192, 13,200,154, 79,
+237, 61,114,150,206,162, 22, 10, 40,118, 10,198,146,211,130, 52, 49,209, 59, 60,135, 11,197,181,198, 75,255,170,130,227, 97,227,
+190, 6, 85, 67,113,250,130,232, 57, 43, 43, 55, 44, 0, 17, 9, 2,119, 13,114, 45,109,130,158, 29,158,103, 95,227, 38,213,153,
+154,154, 58, 77,246,184, 31, 21,160, 1,209,206,149,239,124,151,253,215,194,167,135,189,186, 98,203,148, 37,155,220,212,109,130,
+137,166, 57,175,211,185,239, 37,220,167,228, 36,153, 76, 22, 21, 21,197, 50,243, 55,247, 9,188, 45, 2,157,240,224,192,217,188,
+ 34,102, 37, 68,167,108,183,108,201, 56,124,248, 48,177, 35, 8, 0,246,127,236,243,212,231,141, 35, 70,140,112,152,144,212, 78,
+169, 19,154, 83,189,152, 43, 57,182, 21,139,183,130,227, 11,201,146,141,200, 94,136,216, 66,114,114, 39,205,187, 14,251,210, 13,
+191, 0, 60,253,101, 34,202, 92, 64, 76, 93,126,161,184,150, 8, 12, 40,186,213, 0, 36, 9,110, 43,142,102,157,197,233, 84, 94,
+167,203,177, 78, 44, 57,223, 24,213,119,238,215,171, 63, 92,156, 18,226,219,225,202,213,210, 87,175,110,105,131,129, 46, 76,222,
+100,122,172, 14,133,103,217,173,138,178,178,210,218,186, 59, 71,142,228,253,227, 31,111,227,228, 36,230, 26, 55,197,133, 88, 38,
+237,118,250,118,201,182, 3, 0,228, 78,229,242,238,180, 74, 15,187,117,185,102,135, 61,236, 22,202,145, 46, 47,230,254,232,170,
+ 28,109, 15, 0,204,155, 23, 77, 27, 14, 25, 0,160, 13,120,243, 30,234,180, 87, 74,215,206,178,152, 11,141, 50,111, 52, 22,158,
+ 78, 9,162, 54, 24, 10, 73, 75, 78,102, 90,146, 66,161,160, 9,215,225, 7, 16,179,231,243, 95,174, 71, 59, 33,248,213,180,195,
+115,167, 12, 75,205, 0,145,200,203, 67,236,166,115,166, 61, 77,139, 5,167,156, 80, 23, 36, 12,150,156,115,211,179, 22,191,254,
+ 84,167,176, 81,116,136,134,251,189,106,102,189,103,198,140,249,173,217, 91,119,130,179,152,121,157,244,184, 76,118,180, 36, 57,
+169,117, 67,159, 45, 28,114,195,157,223, 91,222,195,238,172,173,181,114,108,155,226,128,114,185,156,250, 57, 96,255, 69, 19, 0,
+108, 60,100,216,118,194,128, 16,106,179, 17,171,173,153,215,105, 65,157,214, 68,233,166, 27,218,242,228, 36,204,209,184,218, 15,
+253,121,224, 62,108,110,210,210, 13,208,156, 6, 63,114,241,221, 8, 75,147, 59, 95,143,150, 95,172,107,120, 99, 84,223,132,220,
+211, 51,254,249, 19,142,232, 49,159,108, 27,188, 45, 76,237,201, 49, 61,190,133,201, 73,246, 34, 3,220,159, 2, 29,229,199,203,
+109, 21,112,108,211,209, 68,247, 23, 99, 63,111,116,249, 84,199,207,252, 36,123,243,103,233,169, 31, 48,243, 58, 57,166, 46,180,
+166,195,110,221,206,108,166,104, 56, 60, 51,103,223,237, 22, 38, 39,225,110,116,230, 40, 8,142, 68,128,245,105,235,222,177, 54,
+152,232,161, 37,251, 79,248,248,123,215,238,149,181,240,228,126, 26,246, 88,242,217,231,228,244,175, 22, 30, 61,125,160,150, 36,
+ 39,181, 86, 20, 11, 7,175,112,221, 61, 87, 62,111,205,174, 58,247,247,162,141,199,176,223,199,198, 41,152,166, 36, 8, 98,226,
+179,179, 45,154,138,205,246,192, 22,241,115, 38, 25,190,149,169,147,251, 53,179,247, 12, 58,123,239, 90, 94,246,203,101, 34,104,
+185,212,186, 79,223,115,212, 60,222,181,237,238, 85, 75, 46,220,217,215,160, 93,105,124,104,238, 53,229,222,245,209,242,131,222,
+ 95,213,217,182, 60,235, 74, 99,182, 22,158,220,133,221,127, 63,111,124, 89, 55, 30, 60,120,240,112, 22,252, 44,241, 60,120,240,
+224,193, 83, 39, 15, 30, 60,120,184, 31,255, 31, 19, 50, 19, 5, 1,234,172,253, 0, 0, 0, 0, 73, 69, 78, 68,174, 66, 96,130,
+};
diff --git a/source/blender/src/booleanops.c b/source/blender/src/booleanops.c
new file mode 100644
index 00000000000..5c89dee1a46
--- /dev/null
+++ b/source/blender/src/booleanops.c
@@ -0,0 +1,795 @@
+
+#include <string.h>
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * CSG operations.
+ */
+
+
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_ghash.h"
+
+#include "DNA_material_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "CSG_BooleanOps.h"
+
+#include "BKE_global.h"
+#include "BKE_mesh.h"
+#include "BKE_displist.h"
+#include "BKE_object.h"
+#include "BKE_booleanops.h"
+#include "BKE_utildefines.h"
+#include "BKE_library.h"
+#include "BKE_material.h"
+
+#include <math.h>
+
+// TODO check to see how many of these includes are necessary
+
+#include "BLI_blenlib.h"
+#include "BLI_editVert.h"
+#include "BLI_arithb.h"
+#include "BLI_linklist.h"
+#include "BLI_memarena.h"
+
+
+/**
+ * Here's the vertex iterator structure used to walk through
+ * the blender vertex structure.
+ */
+
+typedef struct {
+ Object *ob;
+ Mesh *mesh;
+ int pos;
+} VertexIt;
+
+/**
+ * Implementations of local vertex iterator functions.
+ * These describe a blender mesh to the CSG module.
+ */
+
+static
+ void
+VertexIt_Destruct(
+ CSG_VertexIteratorDescriptor * iterator
+){
+ if (iterator->it) {
+ // deallocate memory for iterator
+ MEM_freeN(iterator->it);
+ iterator->it = 0;
+ }
+ iterator->Done = NULL;
+ iterator->Fill = NULL;
+ iterator->Reset = NULL;
+ iterator->Step = NULL;
+ iterator->num_elements = 0;
+
+};
+
+static
+ int
+VertexIt_Done(
+ CSG_IteratorPtr it
+){
+ VertexIt * iterator = (VertexIt *)it;
+ return(iterator->pos >= iterator->mesh->totvert);
+}
+
+
+static
+ void
+VertexIt_Fill(
+ CSG_IteratorPtr it,
+ CSG_IVertex *vert
+){
+ VertexIt * iterator = (VertexIt *)it;
+ MVert *verts = iterator->mesh->mvert;
+
+ float global_pos[3];
+
+ VecMat4MulVecfl(
+ global_pos,
+ iterator->ob->obmat,
+ verts[iterator->pos].co
+ );
+
+ vert->position[0] = global_pos[0];
+ vert->position[1] = global_pos[1];
+ vert->position[2] = global_pos[2];
+}
+
+static
+ void
+VertexIt_Step(
+ CSG_IteratorPtr it
+){
+ VertexIt * iterator = (VertexIt *)it;
+ iterator->pos ++;
+}
+
+static
+ void
+VertexIt_Reset(
+ CSG_IteratorPtr it
+){
+ VertexIt * iterator = (VertexIt *)it;
+ iterator->pos = 0;
+}
+
+static
+ void
+VertexIt_Construct(
+ CSG_VertexIteratorDescriptor * output,
+ Object *ob
+){
+
+ VertexIt *it;
+ if (output == 0) return;
+
+ // allocate some memory for blender iterator
+ it = (VertexIt *)(MEM_mallocN(sizeof(VertexIt),"Boolean_VIt"));
+ if (it == 0) {
+ return;
+ }
+ // assign blender specific variables
+ it->ob = ob;
+ it->mesh = ob->data;
+
+ it->pos = 0;
+
+ // assign iterator function pointers.
+ output->Step = VertexIt_Step;
+ output->Fill = VertexIt_Fill;
+ output->Done = VertexIt_Done;
+ output->Reset = VertexIt_Reset;
+ output->num_elements = it->mesh->totvert;
+ output->it = it;
+}
+
+/**
+ * Blender Face iterator
+ */
+
+typedef struct {
+ Object *ob;
+ Mesh *mesh;
+ int pos;
+} FaceIt;
+
+
+static
+ void
+FaceIt_Destruct(
+ CSG_FaceIteratorDescriptor * iterator
+) {
+ MEM_freeN(iterator->it);
+ iterator->Done = NULL;
+ iterator->Fill = NULL;
+ iterator->Reset = NULL;
+ iterator->Step = NULL;
+ iterator->num_elements = 0;
+};
+
+
+static
+ int
+FaceIt_Done(
+ CSG_IteratorPtr it
+) {
+ // assume CSG_IteratorPtr is of the correct type.
+ FaceIt * iterator = (FaceIt *)it;
+ return(iterator->pos >= iterator->mesh->totface);
+};
+
+static
+ void
+FaceIt_Fill(
+ CSG_IteratorPtr it,
+ CSG_IFace *face
+){
+ // assume CSG_IteratorPtr is of the correct type.
+ FaceIt * face_it = (FaceIt *)it;
+ Object *ob = face_it->ob;
+ MFace *mfaces = face_it->mesh->mface;
+ TFace *tfaces = face_it->mesh->tface;
+ int f_index = face_it->pos;
+ MFace *mface = &mfaces[f_index];
+ FaceData *fdata = face->user_face_data;
+
+ if (mface->v3) {
+ // ignore lines (faces with mface->v3==0)
+ face->vertex_index[0] = mface->v1;
+ face->vertex_index[1] = mface->v2;
+ face->vertex_index[2] = mface->v3;
+ if (mface->v4) {
+ face->vertex_index[3] = mface->v4;
+ face->vertex_number = 4;
+ } else {
+ face->vertex_number = 3;
+ }
+ }
+
+ fdata->material = give_current_material(ob, mface->mat_nr+1);
+
+ // pack rgba colors.
+ if (tfaces) {
+ TFace *tface= &tfaces[f_index];
+ int i;
+
+ fdata->tpage = tface->tpage;
+ fdata->flag = tface->flag;
+ fdata->transp = tface->transp;
+ fdata->mode = tface->mode;
+ fdata->tile = tface->tile;
+
+ for (i=0; i<4; i++) {
+ FaceVertexData *fvdata= face->user_face_vertex_data[i];
+
+ fvdata->uv[0] = tface->uv[i][0];
+ fvdata->uv[1] = tface->uv[i][1];
+ fvdata->color[0] = (float) ((tface->col[i] >> 24) & 0xff);
+ fvdata->color[1] = (float) ((tface->col[i] >> 16) & 0xff);
+ fvdata->color[2] = (float) ((tface->col[i] >> 8) & 0xff);
+ fvdata->color[3] = (float) ((tface->col[i] >> 0) & 0xff);
+ }
+ }
+};
+
+
+static
+ void
+FaceIt_Step(
+ CSG_IteratorPtr it
+) {
+ FaceIt * face_it = (FaceIt *)it;
+ face_it->pos ++;
+};
+
+static
+ void
+FaceIt_Reset(
+ CSG_IteratorPtr it
+) {
+ FaceIt * face_it = (FaceIt *)it;
+ face_it->pos = 0;
+}
+
+static
+ void
+FaceIt_Construct(
+ CSG_FaceIteratorDescriptor * output,
+ Object * ob
+){
+
+ FaceIt *it;
+ if (output == 0) return;
+
+ // allocate some memory for blender iterator
+ it = (FaceIt *)(MEM_mallocN(sizeof(FaceIt),"Boolean_FIt"));
+ if (it == 0) {
+ return ;
+ }
+ // assign blender specific variables
+ it->ob = ob;
+ it->mesh = ob->data;
+ it->pos = 0;
+
+ // assign iterator function pointers.
+ output->Step = FaceIt_Step;
+ output->Fill = FaceIt_Fill;
+ output->Done = FaceIt_Done;
+ output->Reset = FaceIt_Reset;
+ output->num_elements = it->mesh->totface;
+ output->it = it;
+};
+
+
+/**
+ * Interpolation functions for various user data types.
+ */
+
+ int
+InterpNoUserData(
+ void *d1,
+ void *d2,
+ void *dnew,
+ float epsilon
+) {
+ // nothing to do of course.
+ return 0;
+}
+
+ int
+InterpFaceVertexData(
+ void *d1,
+ void *d2,
+ void *dnew,
+ float epsilon
+) {
+ /* XXX, passed backwards, should be fixed inside
+ * BSP lib I guess.
+ */
+ FaceVertexData *fv1 = d2;
+ FaceVertexData *fv2 = d1;
+ FaceVertexData *fvO = dnew;
+
+ fvO->uv[0] = (fv2->uv[0] - fv1->uv[0]) * epsilon + fv1->uv[0];
+ fvO->uv[1] = (fv2->uv[1] - fv1->uv[1]) * epsilon + fv1->uv[1];
+ fvO->color[0] = (fv2->color[0] - fv1->color[0]) * epsilon + fv1->color[0];
+ fvO->color[1] = (fv2->color[1] - fv1->color[1]) * epsilon + fv1->color[1];
+ fvO->color[2] = (fv2->color[2] - fv1->color[2]) * epsilon + fv1->color[2];
+ fvO->color[3] = (fv2->color[3] - fv1->color[3]) * epsilon + fv1->color[3];
+
+ return 0;
+}
+
+
+
+/**
+ * Assumes mesh is valid and forms part of a fresh
+ * blender object.
+ */
+
+
+
+ int
+NewBooleanMesh(
+ struct Base * base,
+ struct Base * base_select,
+ int int_op_type
+){
+ Mesh *me2 = get_mesh(base_select->object);
+ Mesh *me = get_mesh(base->object);
+ Mesh *me_new = NULL;
+ Object *ob;
+ int free_tface1,free_tface2;
+
+ float inv_mat[4][4];
+ int success = 0;
+ // build and fill new descriptors for these meshes
+ CSG_VertexIteratorDescriptor vd_1;
+ CSG_VertexIteratorDescriptor vd_2;
+ CSG_FaceIteratorDescriptor fd_1;
+ CSG_FaceIteratorDescriptor fd_2;
+
+ CSG_MeshPropertyDescriptor mpd1,mpd2;
+
+ // work out the operation they chose and pick the appropriate
+ // enum from the csg module.
+
+ CSG_OperationType op_type;
+
+ if (me == NULL || me2 == NULL) return 0;
+
+ switch (int_op_type) {
+ case 1 : op_type = e_csg_intersection; break;
+ case 2 : op_type = e_csg_union; break;
+ case 3 : op_type = e_csg_difference; break;
+ case 4 : op_type = e_csg_classify; break;
+ default : op_type = e_csg_intersection;
+ }
+
+ // Here is the section where we describe the properties of
+ // both meshes to the bsp module.
+
+ if (me->mcol != NULL) {
+ // Then this mesh has vertex colors only
+ // well this is awkward because there is no equivalent
+ // test_index_mface just for vertex colors!
+ // as a temporary hack we can convert these vertex colors
+ // into tfaces do the operation and turn them back again.
+
+ // create some memory for the tfaces.
+ me->tface = (TFace *)MEM_callocN(sizeof(TFace)*me->totface,"BooleanOps_TempTFace");
+ mcol_to_tface(me,1);
+ free_tface1 = 1;
+ } else {
+ free_tface1 = 0;
+ }
+
+ mpd1.user_face_vertex_data_size = 0;
+ mpd1.user_data_size = sizeof(FaceData);
+
+ if (me->tface) {
+ mpd1.user_face_vertex_data_size = sizeof(FaceVertexData);
+ }
+
+ // same for mesh2
+
+ if (me2->mcol != NULL) {
+ // create some memory for the tfaces.
+ me2->tface = (TFace *)MEM_callocN(sizeof(TFace)*me2->totface,"BooleanOps_TempTFace");
+ mcol_to_tface(me2,1);
+ free_tface2 = 1;
+ } else {
+ free_tface2 = 0;
+ }
+
+ mpd2.user_face_vertex_data_size = 0;
+ mpd2.user_data_size = sizeof(FaceData);
+
+ if (me2->tface) {
+ mpd2.user_face_vertex_data_size = sizeof(FaceVertexData);
+ }
+
+ ob = base->object;
+
+ // we map the final object back into object 1's (ob)
+ // local coordinate space. For this we need to compute
+ // the inverse transform from global to local.
+
+ Mat4Invert(inv_mat,ob->obmat);
+
+ // make a boolean operation;
+ {
+ CSG_BooleanOperation * bool_op = CSG_NewBooleanFunction();
+ CSG_MeshPropertyDescriptor output_mpd = CSG_DescibeOperands(bool_op,mpd1,mpd2);
+ // analyse the result and choose mesh descriptors accordingly
+ int output_type;
+ if (output_mpd.user_face_vertex_data_size) {
+ output_type = 1;
+ } else {
+ output_type = 0;
+ }
+
+ BuildMeshDescriptors(
+ base->object,
+ &fd_1,
+ &vd_1
+ );
+ BuildMeshDescriptors(
+ base_select->object,
+ &fd_2,
+ &vd_2
+ );
+
+ // perform the operation
+
+ if (output_type == 0) {
+
+ success =
+ CSG_PerformBooleanOperation(
+ bool_op,
+ op_type,
+ fd_1,vd_1,fd_2,vd_2,
+ InterpNoUserData
+ );
+ } else {
+ success =
+ CSG_PerformBooleanOperation(
+ bool_op,
+ op_type,
+ fd_1,vd_1,fd_2,vd_2,
+ InterpFaceVertexData
+ );
+ }
+
+ if (success) {
+ // descriptions of the output;
+ CSG_VertexIteratorDescriptor vd_o;
+ CSG_FaceIteratorDescriptor fd_o;
+
+ // Create a new blender mesh object - using 'base' as
+ // a template for the new object.
+ Object * ob_new= AddNewBlenderMesh(base);
+
+ // get the output descriptors
+
+ CSG_OutputFaceDescriptor(bool_op,&fd_o);
+ CSG_OutputVertexDescriptor(bool_op,&vd_o);
+
+ me_new = ob_new->data;
+ // iterate through results of operation and insert into new object
+ // see subsurf.c
+
+ ConvertCSGDescriptorsToMeshObject(
+ ob_new,
+ &output_mpd,
+ &fd_o,
+ &vd_o,
+ inv_mat
+ );
+
+ // initialize the object
+ tex_space_mesh(me_new);
+
+ // free up the memory
+
+ CSG_FreeVertexDescriptor(&vd_o);
+ CSG_FreeFaceDescriptor(&fd_o);
+ }
+
+ CSG_FreeBooleanOperation(bool_op);
+ bool_op = NULL;
+
+ }
+
+ // We may need to map back the tfaces to mcols here.
+ if (free_tface1) {
+ tface_to_mcol(me);
+ MEM_freeN(me->tface);
+ me->tface = NULL;
+ }
+ if (free_tface2) {
+ tface_to_mcol(me2);
+ MEM_freeN(me2->tface);
+ me2->tface = NULL;
+ }
+
+ if (free_tface1 && free_tface2) {
+ // then we need to map the output tfaces into mcols
+ if (me_new) {
+ tface_to_mcol(me_new);
+ MEM_freeN(me_new->tface);
+ me_new->tface = NULL;
+ }
+ }
+
+ FreeMeshDescriptors(&fd_1,&vd_1);
+ FreeMeshDescriptors(&fd_2,&vd_2);
+
+ return success;
+}
+
+
+ Object *
+AddNewBlenderMesh(
+ Base *base
+){
+ Mesh *old_me;
+ Base *basen;
+ Object *ob_new;
+
+ // now create a new blender object.
+ // duplicating all the settings from the previous object
+ // to the new one.
+ ob_new= copy_object(base->object);
+
+ // Ok we don't want to use the actual data from the
+ // last object, the above function incremented the
+ // number of users, so decrement it here.
+ old_me= ob_new->data;
+ old_me->id.us--;
+
+ // Now create a new base to add into the linked list of
+ // vase objects.
+
+ basen= MEM_mallocN(sizeof(Base), "duplibase");
+ *basen= *base;
+ BLI_addhead(&G.scene->base, basen); /* addhead: anders oneindige lus */
+ basen->object= ob_new;
+ basen->flag &= ~SELECT;
+
+ // Initialize the mesh data associated with this object.
+ ob_new->data= add_mesh();
+ G.totmesh++;
+
+ // Finally assign the object type.
+ ob_new->type= OB_MESH;
+
+ return ob_new;
+};
+
+
+
+/**
+ *
+ * External interface
+ *
+ * This function builds a blender mesh using the output information from
+ * the CSG module. It declares all the necessary blender cruft and
+ * fills in the vertex and face arrays.
+ */
+ int
+ConvertCSGDescriptorsToMeshObject(
+ Object *ob,
+ CSG_MeshPropertyDescriptor *props,
+ CSG_FaceIteratorDescriptor *face_it,
+ CSG_VertexIteratorDescriptor *vertex_it,
+ float parinv[][4]
+){
+ Mesh *me = ob->data;
+ FaceVertexData *user_face_vertex_data;
+ GHash *material_hash;
+ CSG_IVertex vert;
+ CSG_IFace face;
+ MVert *insert_pos;
+ MFace *mfaces;
+ TFace *tfaces;
+ int fi_insert_pos, nmaterials;
+
+ // create some memory for the Iface according to output mesh props.
+
+ if (face_it == NULL || vertex_it == NULL || props == NULL || me == NULL) {
+ return 0;
+ }
+ if (vertex_it->num_elements > 65000) return 0;
+
+ // initialize the face structure for readback
+
+ face.user_face_data = MEM_callocN(sizeof(FaceData),"BooleanOp_IFaceData");
+
+ if (props->user_face_vertex_data_size) {
+ user_face_vertex_data = MEM_callocN(sizeof(FaceVertexData)*4,"BooleanOp_IFaceData");
+ face.user_face_vertex_data[0] = &user_face_vertex_data[0];
+ face.user_face_vertex_data[1] = &user_face_vertex_data[1];
+ face.user_face_vertex_data[2] = &user_face_vertex_data[2];
+ face.user_face_vertex_data[3] = &user_face_vertex_data[3];
+ } else {
+ user_face_vertex_data = NULL;
+ }
+
+ // create memory for the vertex array.
+
+ me->mvert = MEM_callocN(sizeof(MVert) * vertex_it->num_elements,"BooleanOp_VertexArray");
+ me->mface = MEM_callocN(sizeof(MFace) * face_it->num_elements,"BooleanOp_FaceArray");
+
+ if (user_face_vertex_data) {
+ me->tface = MEM_callocN(sizeof(TFace) * face_it->num_elements,"BooleanOp_TFaceArray");
+ if (me->tface == NULL) return 0;
+ } else {
+ me->tface = NULL;
+ }
+
+ if (me->mvert == NULL || me->mface == NULL) return 0;
+
+ insert_pos = me->mvert;
+ mfaces = me->mface;
+ tfaces = me->tface;
+
+ fi_insert_pos = 0;
+
+ // step through the iterators.
+
+ while (!vertex_it->Done(vertex_it->it)) {
+ vertex_it->Fill(vertex_it->it,&vert);
+
+ // map output vertex into insert_pos
+ // and transform at by parinv at the same time.
+
+ VecMat4MulVecfl(
+ insert_pos->co,
+ parinv,
+ vert.position
+ );
+ insert_pos ++;
+ vertex_it->Step(vertex_it->it);
+ }
+
+ me->totvert = vertex_it->num_elements;
+
+ // a hash table to remap materials to indices with
+ material_hash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+ nmaterials = 0;
+
+ while (!face_it->Done(face_it->it)) {
+ MFace *mface = &mfaces[fi_insert_pos];
+ FaceData *fdata;
+
+ face_it->Fill(face_it->it,&face);
+
+ // cheat CSG never dumps out quads.
+
+ mface->v1 = face.vertex_index[0];
+ mface->v2 = face.vertex_index[1];
+ mface->v3 = face.vertex_index[2];
+ mface->v4 = 0;
+
+ mface->edcode = ME_V1V2|ME_V2V3|ME_V3V4|ME_V4V1;
+ mface->puno = 0;
+ mface->mat_nr = 0;
+ mface->flag = 0;
+
+ /* HACK, perform material to index mapping using a general
+ * hash table, just tuck the int into a void *.
+ */
+
+ fdata = face.user_face_data;
+ if (!BLI_ghash_haskey(material_hash, fdata->material)) {
+ int matnr = nmaterials++;
+ BLI_ghash_insert(material_hash, fdata->material, (void*) matnr);
+ assign_material(ob, fdata->material, matnr+1);
+ }
+ mface->mat_nr = (int) BLI_ghash_lookup(material_hash, fdata->material);
+
+ // grab the vertex colors and texture cos and dump them into the tface.
+
+ if (tfaces) {
+ TFace *tface= &tfaces[fi_insert_pos];
+ int i;
+
+ // copy all the tface settings back
+ tface->tpage = fdata->tpage;
+ tface->flag = fdata->flag;
+ tface->transp = fdata->transp;
+ tface->mode = fdata->mode;
+ tface->tile = fdata->tile;
+
+ for (i=0; i<4; i++) {
+ FaceVertexData *fvdata = face.user_face_vertex_data[i];
+ float *color = fvdata->color;
+
+ tface->uv[i][0] = fvdata->uv[0];
+ tface->uv[i][1] = fvdata->uv[1];
+ tface->col[i] =
+ ((((unsigned int)floor(color[0] + 0.5f)) & 0xff) << 24) |
+ ((((unsigned int)floor(color[1] + 0.5f)) & 0xff) << 16) |
+ ((((unsigned int)floor(color[2] + 0.5f)) & 0xff) << 8) |
+ ((((unsigned int)floor(color[3] + 0.5f)) & 0xff) << 0);
+ }
+
+ test_index_face(mface, tface, 3);
+ } else {
+ test_index_mface(mface, 3);
+ }
+
+ fi_insert_pos++;
+ face_it->Step(face_it->it);
+ }
+
+ BLI_ghash_free(material_hash, NULL, NULL);
+
+ me->totface = face_it->num_elements;
+ // thats it!
+
+ if (user_face_vertex_data) {
+ MEM_freeN(user_face_vertex_data);
+ }
+ MEM_freeN(face.user_face_data);
+
+ return 1;
+}
+
+ void
+BuildMeshDescriptors(
+ struct Object *ob,
+ struct CSG_FaceIteratorDescriptor * face_it,
+ struct CSG_VertexIteratorDescriptor * vertex_it
+){
+ VertexIt_Construct(vertex_it,ob);
+ FaceIt_Construct(face_it,ob);
+}
+
+ void
+FreeMeshDescriptors(
+ struct CSG_FaceIteratorDescriptor *face_it,
+ struct CSG_VertexIteratorDescriptor *vertex_it
+){
+ VertexIt_Destruct(vertex_it);
+ FaceIt_Destruct(face_it);
+}
+
diff --git a/source/blender/src/booleanops_mesh.c b/source/blender/src/booleanops_mesh.c
new file mode 100644
index 00000000000..8df36833a1d
--- /dev/null
+++ b/source/blender/src/booleanops_mesh.c
@@ -0,0 +1,302 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "CSG_BooleanOps.h"
+
+#include "BKE_booleanops.h"
+#include "BKE_booleanops_mesh.h"
+#include "MEM_guardedalloc.h"
+
+#include "DNA_material_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "BKE_global.h"
+#include "BKE_mesh.h"
+#include "BKE_displist.h"
+#include "BKE_object.h"
+#include "BKE_utildefines.h"
+#include "BKE_library.h"
+#include "BKE_material.h"
+
+#include "BLI_arithb.h"
+
+/**
+ * Implementation of boolean ops mesh interface.
+ */
+
+ void
+CSG_DestroyMeshDescriptor(
+ CSG_MeshDescriptor *mesh
+){
+ // Call mesh descriptors destroy function....
+ mesh->m_destroy_func(mesh);
+}
+
+// Destroy function for blender mesh internals.
+
+static
+ void
+CSG_DestroyBlenderMeshInternals(
+ CSG_MeshDescriptor *mesh
+) {
+ // Free face and vertex iterators.
+ FreeMeshDescriptors(&(mesh->m_face_iterator),&(mesh->m_vertex_iterator));
+};
+
+
+static
+ void
+CSG_DestroyCSGMeshInternals(
+ CSG_MeshDescriptor *mesh
+){
+ CSG_FreeVertexDescriptor(&(mesh->m_vertex_iterator));
+ CSG_FreeFaceDescriptor(&(mesh->m_face_iterator));
+}
+
+static
+ int
+MakeCSGMeshFromBlenderBase(
+ Base * base,
+ CSG_MeshDescriptor * output
+) {
+ Mesh *me;
+ if (output == NULL || base == NULL) return 0;
+
+ me = get_mesh(base->object);
+
+ output->m_descriptor.user_face_vertex_data_size = 0;
+ output->m_descriptor.user_data_size = sizeof(FaceData);
+
+ if (me->tface) {
+ output->m_descriptor.user_face_vertex_data_size = sizeof(FaceVertexData);
+ }
+
+ output->base = base;
+
+ BuildMeshDescriptors(
+ base->object,
+ &(output->m_face_iterator),
+ &(output->m_vertex_iterator)
+ );
+
+ output->m_destroy_func = CSG_DestroyBlenderMeshInternals;
+
+ return 1;
+}
+
+ int
+CSG_LoadBlenderMesh(
+ Object * obj,
+ CSG_MeshDescriptor *output
+){
+
+ Mesh *me;
+ if (output == NULL || obj == NULL) return 0;
+
+ me = get_mesh(obj);
+
+ output->m_descriptor.user_face_vertex_data_size = 0;
+ output->m_descriptor.user_data_size = sizeof(FaceData);
+
+ if (me->tface) {
+ output->m_descriptor.user_face_vertex_data_size = sizeof(FaceVertexData);
+ }
+
+ output->base = NULL;
+
+ BuildMeshDescriptors(
+ obj,
+ &(output->m_face_iterator),
+ &(output->m_vertex_iterator)
+ );
+
+ output->m_destroy_func = CSG_DestroyBlenderMeshInternals;
+ output->base = NULL;
+
+ return 1;
+}
+
+
+
+
+ int
+CSG_AddMeshToBlender(
+ CSG_MeshDescriptor *mesh
+){
+ Mesh *me_new = NULL;
+ Object *ob_new = NULL;
+ float inv_mat[4][4];
+
+ if (mesh == NULL) return 0;
+ if (mesh->base == NULL) return 0;
+
+ Mat4Invert(inv_mat,mesh->base->object->obmat);
+
+ // Create a new blender mesh object - using 'base' as
+ // a template for the new object.
+ ob_new= AddNewBlenderMesh(mesh->base);
+
+ me_new = ob_new->data;
+
+ // make sure the iterators are reset.
+ mesh->m_face_iterator.Reset(mesh->m_face_iterator.it);
+ mesh->m_vertex_iterator.Reset(mesh->m_vertex_iterator.it);
+
+ // iterate through results of operation and insert into new object
+ // see subsurf.c
+
+ ConvertCSGDescriptorsToMeshObject(
+ ob_new,
+ &(mesh->m_descriptor),
+ &(mesh->m_face_iterator),
+ &(mesh->m_vertex_iterator),
+ inv_mat
+ );
+
+ // initialize the object
+ tex_space_mesh(me_new);
+
+ return 1;
+}
+
+ int
+CSG_PerformOp(
+ CSG_MeshDescriptor *mesh1,
+ CSG_MeshDescriptor *mesh2,
+ int int_op_type,
+ CSG_MeshDescriptor *output
+){
+
+ CSG_OperationType op_type;
+ CSG_BooleanOperation * bool_op = CSG_NewBooleanFunction();
+ int success = 0;
+
+ if (bool_op == NULL) return 0;
+
+ if ((mesh1 == NULL) || (mesh2 == NULL) || (output == NULL)) {
+ return 0;
+ }
+ if ((int_op_type < 1) || (int_op_type > 3)) return 0;
+
+ switch (int_op_type) {
+ case 1 : op_type = e_csg_intersection; break;
+ case 2 : op_type = e_csg_union; break;
+ case 3 : op_type = e_csg_difference; break;
+ case 4 : op_type = e_csg_classify; break;
+ default : op_type = e_csg_intersection;
+ }
+
+ output->m_descriptor = CSG_DescibeOperands(bool_op,mesh1->m_descriptor,mesh2->m_descriptor);
+ output->base = mesh1->base;
+
+ if (output->m_descriptor.user_face_vertex_data_size) {
+ // Then use the only interp function supported
+ success =
+ CSG_PerformBooleanOperation(
+ bool_op,
+ op_type,
+ mesh1->m_face_iterator,
+ mesh1->m_vertex_iterator,
+ mesh2->m_face_iterator,
+ mesh2->m_vertex_iterator,
+ InterpFaceVertexData
+ );
+ } else {
+ success =
+ CSG_PerformBooleanOperation(
+ bool_op,
+ op_type,
+ mesh1->m_face_iterator,
+ mesh1->m_vertex_iterator,
+ mesh2->m_face_iterator,
+ mesh2->m_vertex_iterator,
+ InterpNoUserData
+ );
+ }
+
+ if (!success) {
+ CSG_FreeBooleanOperation(bool_op);
+ bool_op = NULL;
+ return 0;
+ }
+
+ // get the ouput mesh descriptors.
+
+ CSG_OutputFaceDescriptor(bool_op,&(output->m_face_iterator));
+ CSG_OutputVertexDescriptor(bool_op,&(output->m_vertex_iterator));
+ output->m_destroy_func = CSG_DestroyCSGMeshInternals;
+
+ return 1;
+};
+
+ int
+NewBooleanMeshTest(
+ struct Base * base,
+ struct Base * base_select,
+ int op_type
+){
+
+ CSG_MeshDescriptor m1,m2,output;
+ CSG_MeshDescriptor output2,output3;
+
+ if (!MakeCSGMeshFromBlenderBase(base,&m1)) {
+ return 0;
+ }
+
+ if (!MakeCSGMeshFromBlenderBase(base_select,&m2)) {
+ return 0;
+ }
+
+ CSG_PerformOp(&m1,&m2,1,&output);
+ CSG_PerformOp(&m1,&m2,2,&output2);
+ CSG_PerformOp(&m1,&m2,3,&output3);
+
+ if (!CSG_AddMeshToBlender(&output)) {
+ return 0;
+ }
+ if (!CSG_AddMeshToBlender(&output2)) {
+ return 0;
+ }
+ if (!CSG_AddMeshToBlender(&output3)) {
+ return 0;
+ }
+
+
+ CSG_DestroyMeshDescriptor(&m1);
+ CSG_DestroyMeshDescriptor(&m2);
+ CSG_DestroyMeshDescriptor(&output);
+ CSG_DestroyMeshDescriptor(&output2);
+ CSG_DestroyMeshDescriptor(&output3);
+
+ return 1;
+};
diff --git a/source/blender/src/buttons.c b/source/blender/src/buttons.c
new file mode 100644
index 00000000000..85aeb92d959
--- /dev/null
+++ b/source/blender/src/buttons.c
@@ -0,0 +1,7338 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * Everything for drawing buttons (and I do mean _everything_).
+ */
+
+
+/* System includes ----------------------------------------------------- */
+
+#include <time.h>
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef _WIN32
+#include "BLI_winstuff.h"
+#else
+#include <unistd.h>
+#endif
+#include "MEM_guardedalloc.h"
+
+#include "BMF_Api.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+
+#include "DNA_action_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_constraint_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_effect_types.h"
+#include "DNA_group_types.h"
+#include "DNA_ika_types.h"
+#include "DNA_image_types.h"
+#include "DNA_key_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_lattice_types.h"
+#include "DNA_material_types.h"
+#include "DNA_meta_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+#include "DNA_packedFile_types.h"
+#include "DNA_radio_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_sound_types.h"
+#include "DNA_space_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_vfont_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_world_types.h"
+
+#include "BKE_anim.h"
+#include "BKE_armature.h"
+#include "BKE_constraint.h"
+#include "BKE_curve.h"
+#include "BKE_displist.h"
+#include "BKE_effect.h"
+#include "BKE_font.h"
+#include "BKE_global.h"
+#include "BKE_ika.h"
+#include "BKE_image.h"
+#include "BKE_ipo.h"
+#include "BKE_lattice.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+#include "BKE_material.h"
+#include "BKE_mball.h"
+#include "BKE_mesh.h"
+#include "BKE_object.h"
+#include "BKE_packedFile.h"
+#include "BKE_plugin_types.h"
+#include "BKE_sound.h"
+#include "BKE_texture.h"
+#include "BKE_utildefines.h"
+#include "BKE_writeavi.h"
+
+/* Everything from source (BIF, BDR, BSE) ------------------------------ */
+
+#include "BDR_drawobject.h"
+#include "BDR_editcurve.h"
+#include "BDR_editface.h"
+#include "BDR_editobject.h"
+#include "BDR_isect.h"
+#include "BDR_vpaint.h"
+
+#include "BSE_drawview.h"
+#include "BSE_editipo.h"
+#include "BSE_edit.h"
+#include "BSE_filesel.h"
+#include "BSE_headerbuttons.h"
+#include "BSE_trans_types.h"
+#include "BSE_view.h"
+#include "BSE_buttons.h"
+
+#include "BIF_gl.h"
+#include "BIF_editarmature.h"
+#include "BIF_editconstraint.h"
+#include "BIF_editdeform.h"
+#include "BIF_editfont.h"
+#include "BIF_editmesh.h"
+#include "BIF_editsca.h"
+#include "BIF_editsound.h"
+#include "BIF_interface.h"
+#include "BIF_mywindow.h"
+#include "BIF_renderwin.h"
+#include "BIF_resources.h"
+#include "BIF_screen.h"
+#include "BIF_scrarea.h"
+#include "BIF_space.h"
+#include "BIF_toets.h"
+#include "BIF_toolbox.h"
+#include "BIF_previewrender.h"
+#include "BIF_writeimage.h"
+#include "BIF_writeavicodec.h"
+
+#include "license_key.h"
+extern int LICENSE_KEY_VALID;
+
+/* 'old' stuff": defines and types ------------------------------------- */
+#include "blendef.h"
+#include "interface.h"
+
+/* old style modules --------------------------------------------------- */
+
+#include "mydevice.h"
+
+#include "render.h"
+#include "radio.h"
+#include "nla.h" /* For __NLA: Do not remove! */
+
+/* Decimation includes. See LOD_DependKludge.h for enabling Decimation */
+#include "LOD_DependKludge.h"
+#ifdef NAN_DECIMATION
+ #include "LOD_decimation.h"
+#endif
+
+/* own include --------------------------------------------------------- */
+#include "BSE_buttons.h"
+
+/* some dirt ... let the linker deal with it :( ------------------------ */
+extern ListBase editNurb; /* from editcurve */
+extern VPaint Gvp; /* from vpaint */
+
+/* Local vars ---------------------------------------------------------- */
+short bgpicmode=0, near=1000, far=1000;
+short degr= 90, step= 9, turn= 1, editbutflag= 1;
+float hspeed=.1, prspeed=0.0, prlen=0.0, doublimit= 0.001;
+int decim_faces=0;
+
+#ifdef __NLA
+float editbutvweight=1;
+#endif
+float extr_offs= 1.0, editbutweight=1.0, editbutsize=0.1, cumapsize= 1.0;
+MTex emptytex;
+char texstr[15][8]= {"None" , "Clouds" , "Wood",
+ "Marble", "Magic" , "Blend",
+ "Stucci", "Noise" , "Image",
+ "Plugin", "EnvMap" , "",
+ "" , "" , ""};
+
+
+/* Local functions ----------------------------------------------------- */
+
+/* event for buttons (ROW) to indicate the backbuffer isn't OK (ogl) */
+#define B_DIFF 1
+
+/* *********************** */
+#define B_VIEWBUTS 1100
+
+#define B_LOADBGPIC 1001
+#define B_BLENDBGPIC 1002
+#define B_BGPICBROWSE 1003
+#define B_BGPICTEX 1004
+#define B_BGPICCLEAR 1005
+#define B_BGPICTEXCLEAR 1006
+
+/* *********************** */
+#define B_LAMPBUTS 1200
+
+#define B_LAMPREDRAW 1101
+#define B_COLLAMP 1102
+#define B_TEXCLEARLAMP 1103
+
+/* *********************** */
+#define B_MATBUTS 1300
+
+#define B_MATCOL 1201
+#define B_SPECCOL 1202
+#define B_MIRCOL 1203
+#define B_ACTCOL 1204
+#define B_MATFROM 1205
+#define B_MATPRV 1206
+#define B_MTEXCOL 1207
+#define B_TEXCLEAR 1208
+#define B_MATPRV_DRAW 1209
+#define B_MTEXPASTE 1210
+#define B_MTEXCOPY 1211
+#define B_MATLAY 1212
+
+/* *********************** */
+#define B_TEXBUTS 1400
+
+#define B_TEXTYPE 1301
+#define B_DEFTEXVAR 1302
+#define B_LOADTEXIMA 1303
+#define B_NAMEIMA 1304
+#define B_TEXCHANNEL 1305
+#define B_TEXREDR_PRV 1306
+#define B_TEXIMABROWSE 1307
+#define B_IMAPTEST 1308
+#define B_RELOADIMA 1309
+#define B_LOADPLUGIN 1310
+#define B_NAMEPLUGIN 1311
+#define B_COLORBAND 1312
+#define B_ADDCOLORBAND 1313
+#define B_DELCOLORBAND 1314
+#define B_CALCCBAND 1315
+#define B_CALCCBAND2 1316
+#define B_DOCOLORBAND 1317
+#define B_REDRAWCBAND 1318
+#define B_BANDCOL 1319
+#define B_LOADTEXIMA1 1320
+#define B_PLUGBUT 1321
+
+/* plugbut reserves 24 buttons at least! */
+
+#define B_ENV_MAKE 1350
+#define B_ENV_FREE 1351
+#define B_ENV_DELETE 1352
+#define B_ENV_SAVE 1353
+#define B_ENV_OB 1354
+
+#define B_PACKIMA 1355
+
+/* *********************** */
+#define B_ANIMBUTS 1500
+
+#define B_RECALCPATH 1401
+#define B_MUL_IPO 1402
+#define B_AUTOTIMEOFS 1403
+#define B_FRAMEMAP 1404
+#define B_NEWEFFECT 1405
+#define B_PREVEFFECT 1406
+#define B_NEXTEFFECT 1407
+#define B_CHANGEEFFECT 1408
+#define B_CALCEFFECT 1409
+#define B_DELEFFECT 1410
+#define B_RECALCAL 1411
+#define B_SETSPEED 1412
+#define B_PRINTSPEED 1413
+#define B_PRINTLEN 1414
+#define B_RELKEY 1415
+
+ /* heeft MAX_EFFECT standen! Volgende pas 1450... */
+#define B_SELEFFECT 1430
+
+
+/* *********************** */
+#define B_WORLDBUTS 1600
+
+#define B_TEXCLEARWORLD 1501
+
+/* *********************** */
+#define B_RENDERBUTS 1700
+
+#define B_FS_PIC 1601
+#define B_FS_BACKBUF 1602
+
+#define B_FS_FTYPE 1604
+#define B_DORENDER 1605
+#define B_DOANIM 1606
+#define B_PLAYANIM 1607
+#define B_PR_PAL 1608
+#define B_PR_FULL 1609
+#define B_PR_PRV 1610
+#define B_PR_CDI 1611
+#define B_PR_PAL169 1612
+#define B_PR_D2MAC 1613
+#define B_PR_MPEG 1614
+#define B_REDRAWDISP 1615
+#define B_SETBROWSE 1616
+#define B_CLEARSET 1617
+#define B_PR_PRESET 1618
+#define B_PR_PANO 1619
+
+#define B_IS_FTYPE 1622
+#define B_IS_BACKBUF 1623
+#define B_PR_PC 1624
+
+#define B_PR_PANO360 1627
+#define B_PR_HALFFIELDS 1628
+#define B_NEWRENDERPIPE 1629
+#define B_R_SCALE 1630
+#define B_G_SCALE 1631
+#define B_B_SCALE 1632
+#define B_USE_R_SCALE 1633
+#define B_USE_G_SCALE 1634
+#define B_USE_B_SCALE 1635
+#define B_EDGECOLSLI 1636
+#define B_GAMMASLI 1637
+
+#define B_FILETYPEMENU 1638
+#define B_SELECTCODEC 1639
+#define B_RTCHANGED 1640
+
+#ifdef __NLA
+/* *********************** */
+enum {
+ B_ARMATUREBUTS = 1800,
+ B_POSE = 1701
+};
+#endif
+
+/* *********************** */
+#define B_COMMONEDITBUTS 2049
+
+#define B_MATWICH 2003
+#define B_MATNEW 2004
+#define B_MATDEL 2005
+#define B_MATASS 2006
+#define B_MATSEL 2007
+#define B_MATDESEL 2008
+#define B_HIDE 2009
+#define B_REVEAL 2010
+#define B_SELSWAP 2011
+#define B_SETSMOOTH 2012
+#define B_SETSOLID 2013
+#define B_AUTOTEX 2014
+#define B_DOCENTRE 2015
+#define B_DOCENTRENEW 2016
+#define B_DOCENTRECURSOR 2017
+
+ /* 32 getallen! */
+#define B_OBLAY 2018
+
+#define B_MESHBUTS 2100
+
+#define B_FLIPNORM 2050
+#define B_SPIN 2051
+#define B_SPINDUP 2052
+#define B_EXTR 2053
+#define B_SCREW 2054
+#define B_EXTREP 2055
+#define B_SPLIT 2056
+#define B_REMDOUB 2057
+#define B_SUBDIV 2058
+#define B_FRACSUBDIV 2059
+#define B_XSORT 2060
+#define B_HASH 2061
+#define B_DELSTICKY 2062
+#define B_DELVERTCOL 2063
+#define B_MAKE_TFACES 2064
+#define B_TOSPHERE 2065
+#define B_DEL_TFACES 2066
+#define B_NEWVGROUP 2067
+#define B_DELVGROUP 2068
+#define B_ASSIGNVGROUP 2069
+#define B_REMOVEVGROUP 2070
+#define B_SELVGROUP 2071
+#define B_DESELVGROUP 2072
+#define B_DECIM_FACES 2073
+#define B_DECIM_CANCEL 2074
+#define B_DECIM_APPLY 2075
+#define B_AUTOVGROUP 2076
+#define B_SLOWERDRAW 2077
+#define B_FASTERDRAW 2078
+#define B_VERTEXNOISE 2079
+#define B_VERTEXSMOOTH 2080
+#define B_INTERSECTMESH 2081
+#define B_MAKESTICKY 2082
+#define B_MAKEVERTCOL 2083
+
+/* *********************** */
+#define B_CURVEBUTS 2200
+
+#define B_CONVERTPOLY 2101
+#define B_CONVERTBEZ 2102
+#define B_CONVERTBSPL 2103
+#define B_CONVERTCARD 2104
+#define B_CONVERTNURB 2105
+#define B_UNIFU 2106
+#define B_ENDPU 2107
+#define B_BEZU 2108
+#define B_UNIFV 2109
+#define B_ENDPV 2110
+#define B_BEZV 2111
+#define B_SETWEIGHT 2112
+#define B_SETW1 2113
+#define B_SETW2 2114
+#define B_SETW3 2115
+#define B_SETORDER 2116
+#define B_MAKEDISP 2117
+#define B_SUBDIVCURVE 2118
+#define B_SPINNURB 2119
+#define B_CU3D 2120
+#define B_SETRESOLU 2121
+#define B_SETW4 2122
+
+
+/* *********************** */
+#define B_FONTBUTS 2300
+
+#define B_MAKEFONT 2201
+#define B_TOUPPER 2202
+#define B_SETFONT 2203
+#define B_LOADFONT 2204
+#define B_TEXTONCURVE 2205
+#define B_PACKFONT 2206
+
+/* *********************** */
+#define B_IKABUTS 2400
+
+#define B_IKASETREF 2301
+#define B_IKARECALC 2302
+
+/* *********************** */
+#define B_CAMBUTS 2500
+
+/* *********************** */
+#define B_MBALLBUTS 2600
+
+#define B_RECALCMBALL 2501
+
+/* *********************** */
+#define B_LATTBUTS 2700
+
+#define B_RESIZELAT 2601
+#define B_DRAWLAT 2602
+#define B_LATTCHANGED 2603
+
+/* *********************** */
+#define B_GAMEBUTS 2800
+
+/* in editsca.c */
+
+/* *********************** */
+#define B_FPAINTBUTS 2900
+
+#define B_VPCOLSLI 2801
+#define B_VPGAMMA 2802
+
+#define B_COPY_TF_MODE 2804
+#define B_COPY_TF_UV 2805
+#define B_COPY_TF_COL 2806
+#define B_REDR_3D_IMA 2807
+#define B_SET_VCOL 2808
+
+#define B_COPY_TF_TEX 2814
+#define B_TFACE_HALO 2815
+#define B_TFACE_BILLB 2816
+
+#define B_SHOWTEX 2832
+#define B_ASSIGNMESH 2833
+
+
+/* *********************** */
+#define B_RADIOBUTS 3000
+
+#define B_RAD_GO 2901
+#define B_RAD_INIT 2902
+#define B_RAD_LIMITS 2903
+#define B_RAD_FAC 2904
+#define B_RAD_NODELIM 2905
+#define B_RAD_NODEFILT 2906
+#define B_RAD_FACEFILT 2907
+#define B_RAD_ADD 2908
+#define B_RAD_DELETE 2909
+#define B_RAD_COLLECT 2910
+#define B_RAD_SHOOTP 2911
+#define B_RAD_SHOOTE 2912
+#define B_RAD_REPLACE 2913
+#define B_RAD_DRAW 2914
+#define B_RAD_FREE 2915
+#define B_RAD_ADDMESH 2916
+
+/* *********************** */
+#define B_SCRIPTBUTS 3100
+
+#define B_SCRIPT_ADD 3001
+#define B_SCRIPT_DEL 3002
+#define B_SCRIPT_TYPE 3003
+
+/* Scene script buttons */
+#define B_SSCRIPT_ADD 3004
+#define B_SSCRIPT_DEL 3005
+#define B_SSCRIPT_TYPE 3006
+
+/* *********************** */
+#define B_SOUNDBUTS 3200
+enum B_SOUND_BUTTONS {
+ B_SOUND_CHANGED = 3101,
+ B_SOUND_REDRAW,
+ B_SOUND_VOLUME,
+ B_SOUND_PANNING,
+ B_SOUND_PITCH,
+ B_SOUND_LOAD_SAMPLE,
+ B_SOUND_MENU_SAMPLE,
+ B_SOUND_NAME_SAMPLE,
+ B_SOUND_UNLINK_SAMPLE,
+ B_SOUND_RELOAD_SAMPLE,
+ B_SOUND_UNPACK_SAMPLE,
+ B_SOUND_PLAY_SAMPLE,
+ B_SOUND_COPY_SOUND,
+ B_SOUND_LOOPSTART,
+ B_SOUND_LOOPEND,
+ B_SOUND_BIDIRECTIONAL
+};
+
+/* *********************** */
+#define B_CONSTRAINTBUTS 3300
+enum {
+ B_CONSTRAINT_REDRAW = 3201,
+ B_CONSTRAINT_ADD,
+ B_CONSTRAINT_DEL,
+ B_CONSTRAINT_TEST,
+ B_CONSTRAINT_CHANGETYPE,
+ B_CONSTRAINT_CHANGENAME,
+ B_CONSTRAINT_CHANGETARGET
+};
+
+/* *********************** */
+/* BUTTON BUT: > 4000 */
+/* BUTTON 4001-4032: layers */
+
+
+static char *physics_pup(void)
+{
+ /* the number needs to match defines in game.h */
+ return "Physics %t|Sumo %x0|"
+ "ODE %x4 |None %x7|";
+}
+
+
+static void draw_buttons_edge(int win, float x1)
+{
+ float asp, winmat[4][4];
+ int w,h;
+
+ bwin_getsinglematrix(win, winmat);
+ bwin_getsize(win, &w, &h);
+ asp= 2.0/(w*winmat[0][0]);
+
+ glColor3ub(0,0,0);
+ fdrawline(x1, -1000, x1, 2000);
+ glColor3ub(255,255,255);
+ fdrawline(x1+asp, -1000, x1+asp, 2000);
+}
+
+static int packdummy = 0;
+
+void test_scriptpoin_but(char *name, ID **idpp)
+{
+ ID *id;
+
+ id= G.main->text.first;
+ while(id) {
+ if( strcmp(name, id->name+2)==0 ) {
+ *idpp= id;
+ return;
+ }
+ id= id->next;
+ }
+ *idpp= 0;
+}
+#ifdef __NLA
+void test_actionpoin_but(char *name, ID **idpp)
+{
+ ID *id;
+
+ id= G.main->action.first;
+ while(id) {
+ if( strcmp(name, id->name+2)==0 ) {
+ *idpp= id;
+ return;
+ }
+ id= id->next;
+ }
+ *idpp= 0;
+}
+#endif
+
+void test_obpoin_but(char *name, ID **idpp)
+{
+ ID *id;
+
+ if(idpp == (ID **)&(emptytex.object)) {
+ error("Add texture first");
+ *idpp= 0;
+ return;
+ }
+
+ id= G.main->object.first;
+ while(id) {
+ if( strcmp(name, id->name+2)==0 ) {
+ *idpp= id;
+ return;
+ }
+ id= id->next;
+ }
+ *idpp= 0;
+}
+
+void test_obcurpoin_but(char *name, ID **idpp)
+{
+ ID *id;
+
+ if(idpp == (ID **)&(emptytex.object)) {
+ error("Add texture first");
+ *idpp= 0;
+ return;
+ }
+
+ id= G.main->object.first;
+ while(id) {
+ if( strcmp(name, id->name+2)==0 ) {
+ if (((Object *)id)->type != OB_CURVE) {
+ error ("Bevel object must be a Curve");
+ break;
+ }
+ *idpp= id;
+ return;
+ }
+ id= id->next;
+ }
+ *idpp= 0;
+}
+
+void test_meshpoin_but(char *name, ID **idpp)
+{
+ ID *id;
+
+ if( *idpp ) (*idpp)->us--;
+
+ id= G.main->mesh.first;
+ while(id) {
+ if( strcmp(name, id->name+2)==0 ) {
+ *idpp= id;
+ id_us_plus(id);
+ return;
+ }
+ id= id->next;
+ }
+ *idpp= 0;
+}
+
+void test_matpoin_but(char *name, ID **idpp)
+{
+ ID *id;
+
+ if( *idpp ) (*idpp)->us--;
+
+ id= G.main->mat.first;
+ while(id) {
+ if( strcmp(name, id->name+2)==0 ) {
+ *idpp= id;
+ id_us_plus(id);
+ return;
+ }
+ id= id->next;
+ }
+ *idpp= 0;
+}
+
+void test_scenepoin_but(char *name, ID **idpp)
+{
+ ID *id;
+
+ if( *idpp ) (*idpp)->us--;
+
+ id= G.main->scene.first;
+ while(id) {
+ if( strcmp(name, id->name+2)==0 ) {
+ *idpp= id;
+ id_us_plus(id);
+ return;
+ }
+ id= id->next;
+ }
+ *idpp= 0;
+}
+
+
+
+/* ************************************* */
+
+static void do_common_editbuts(unsigned short event)
+{
+ EditVlak *evl;
+ Base *base;
+ Object *ob;
+ Mesh *me;
+ Nurb *nu;
+ Curve *cu;
+ MFace *mface;
+ BezTriple *bezt;
+ BPoint *bp;
+ unsigned int local;
+ int a, bit, index= -1;
+
+ switch(event) {
+
+ case B_MATWICH:
+ if(G.obedit && G.obedit->actcol>0) {
+ if(G.obedit->type == OB_MESH) {
+ evl= G.edvl.first;
+ while(evl) {
+ if( vlakselectedAND(evl, 1) ) {
+ if(index== -1) index= evl->mat_nr;
+ else if(index!=evl->mat_nr) {
+ error("Mixed colors");
+ return;
+ }
+ }
+ evl= evl->next;
+ }
+ }
+ else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
+ nu= editNurb.first;
+ while(nu) {
+ if( isNurbsel(nu) ) {
+ if(index== -1) index= nu->mat_nr;
+ else if(index!=nu->mat_nr) {
+ error("Mixed colors");
+ return;
+ }
+ }
+ nu= nu->next;
+ }
+ }
+ if(index>=0) {
+ G.obedit->actcol= index+1;
+ scrarea_queue_winredraw(curarea);
+ }
+ }
+ break;
+ case B_MATNEW:
+ new_material_to_objectdata((G.scene->basact) ? (G.scene->basact->object) : 0);
+ scrarea_queue_winredraw(curarea);
+ allqueue(REDRAWVIEW3D_Z, 0);
+ break;
+ case B_MATDEL:
+ delete_material_index();
+ scrarea_queue_winredraw(curarea);
+ allqueue(REDRAWVIEW3D_Z, 0);
+ break;
+ case B_MATASS:
+ if(G.obedit && G.obedit->actcol>0) {
+ if(G.obedit->type == OB_MESH) {
+ evl= G.edvl.first;
+ while(evl) {
+ if( vlakselectedAND(evl, 1) )
+ evl->mat_nr= G.obedit->actcol-1;
+ evl= evl->next;
+ }
+ allqueue(REDRAWVIEW3D_Z, 0);
+ makeDispList(G.obedit);
+ }
+ else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
+ nu= editNurb.first;
+ while(nu) {
+ if( isNurbsel(nu) )
+ nu->mat_nr= G.obedit->actcol-1;
+ nu= nu->next;
+ }
+ }
+ }
+ break;
+ case B_MATSEL:
+ case B_MATDESEL:
+ if(G.obedit) {
+ if(G.obedit->type == OB_MESH) {
+ evl= G.edvl.first;
+ while(evl) {
+ if(evl->mat_nr== G.obedit->actcol-1) {
+ if(event==B_MATSEL) {
+ if(evl->v1->h==0) evl->v1->f |= 1;
+ if(evl->v2->h==0) evl->v2->f |= 1;
+ if(evl->v3->h==0) evl->v3->f |= 1;
+ if(evl->v4 && evl->v4->h==0) evl->v4->f |= 1;
+ }
+ else {
+ if(evl->v1->h==0) evl->v1->f &= ~1;
+ if(evl->v2->h==0) evl->v2->f &= ~1;
+ if(evl->v3->h==0) evl->v3->f &= ~1;
+ if(evl->v4 && evl->v4->h==0) evl->v4->f &= ~1;
+ }
+ }
+ evl= evl->next;
+ }
+ tekenvertices_ext( event==B_MATSEL );
+ }
+ else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
+ nu= editNurb.first;
+ while(nu) {
+ if(nu->mat_nr==G.obedit->actcol-1) {
+ if(nu->bezt) {
+ a= nu->pntsu;
+ bezt= nu->bezt;
+ while(a--) {
+ if(bezt->hide==0) {
+ if(event==B_MATSEL) {
+ bezt->f1 |= 1;
+ bezt->f2 |= 1;
+ bezt->f3 |= 1;
+ }
+ else {
+ bezt->f1 &= ~1;
+ bezt->f2 &= ~1;
+ bezt->f3 &= ~1;
+ }
+ }
+ bezt++;
+ }
+ }
+ else if(nu->bp) {
+ a= nu->pntsu*nu->pntsv;
+ bp= nu->bp;
+ while(a--) {
+ if(bp->hide==0) {
+ if(event==B_MATSEL) bp->f1 |= 1;
+ else bp->f1 &= ~1;
+ }
+ bp++;
+ }
+ }
+ }
+ nu= nu->next;
+ }
+ allqueue(REDRAWVIEW3D, 0);
+ }
+ }
+ break;
+ case B_HIDE:
+ if(G.obedit) {
+ if(G.obedit->type == OB_MESH) hide_mesh(0);
+ else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) hideNurb(0);
+ }
+ break;
+ case B_REVEAL:
+ if(G.obedit) {
+ if(G.obedit->type == OB_MESH) reveal_mesh();
+ else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) revealNurb();
+ }
+ else if(G.f & G_FACESELECT) reveal_tface();
+
+ break;
+ case B_SELSWAP:
+ if(G.obedit) {
+ if(G.obedit->type == OB_MESH) selectswap_mesh();
+ else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) selectswapNurb();
+ }
+ break;
+ case B_AUTOTEX:
+ ob= OBACT;
+ if(ob && G.obedit==0) {
+ if(ob->type==OB_MESH) tex_space_mesh(ob->data);
+ else if(ob->type==OB_MBALL) ;
+ else tex_space_curve(ob->data);
+ }
+ break;
+ case B_DOCENTRE:
+ docentre();
+ break;
+ case B_DOCENTRENEW:
+ docentre_new();
+ break;
+ case B_DOCENTRECURSOR:
+ docentre_cursor();
+ break;
+ case B_SETSMOOTH:
+ case B_SETSOLID:
+ if(G.obedit) {
+ if(G.obedit->type == OB_MESH) {
+ evl= G.edvl.first;
+ while(evl) {
+ if( vlakselectedAND(evl, 1) ) {
+ if(event==B_SETSMOOTH) evl->flag |= ME_SMOOTH;
+ else evl->flag &= ~ME_SMOOTH;
+ }
+ evl= evl->next;
+ }
+
+ makeDispList(G.obedit);
+ allqueue(REDRAWVIEW3D, 0);
+ }
+ else {
+ nu= editNurb.first;
+ while(nu) {
+ if(isNurbsel(nu)) {
+ if(event==B_SETSMOOTH) nu->flag |= ME_SMOOTH;
+ else nu->flag &= ~ME_SMOOTH;
+ }
+ nu= nu->next;
+ }
+
+ }
+ }
+ else {
+ base= FIRSTBASE;
+ while(base) {
+ if(TESTBASELIB(base)) {
+ if(base->object->type==OB_MESH) {
+ me= base->object->data;
+ mface= me->mface;
+ for(a=0; a<me->totface; a++, mface++) {
+ if(event==B_SETSMOOTH) mface->flag |= ME_SMOOTH;
+ else mface->flag &= ~ME_SMOOTH;
+ }
+
+ makeDispList(base->object);
+ }
+ else if ELEM(base->object->type, OB_SURF, OB_CURVE) {
+ cu= base->object->data;
+ nu= cu->nurb.first;
+ while(nu) {
+ if(event==B_SETSMOOTH) nu->flag |= ME_SMOOTH;
+ else nu->flag &= ~ME_SMOOTH;
+ nu= nu->next;
+ }
+ }
+ }
+ base= base->next;
+ }
+ allqueue(REDRAWVIEW3D, 0);
+ }
+ break;
+
+ default:
+ if(event>=B_OBLAY && event<=B_OBLAY+31) {
+ local= BASACT->lay & 0xFF000000;
+ BASACT->lay -= local;
+ if(BASACT->lay==0 || (G.qual & LR_SHIFTKEY)==0) {
+ bit= event-B_OBLAY;
+ BASACT->lay= 1<<bit;
+ scrarea_queue_winredraw(curarea);
+ }
+ BASACT->lay += local;
+ /* optimale redraw */
+ if( (OBACT->lay & G.vd->lay) && (BASACT->lay & G.vd->lay) );
+ else if( (OBACT->lay & G.vd->lay)==0 && (BASACT->lay & G.vd->lay)==0 );
+ else allqueue(REDRAWVIEW3D, 0);
+
+ OBACT->lay= BASACT->lay;
+ }
+ }
+
+}
+
+void common_editbuts(void)
+{
+ Object *ob;
+ ID *id;
+ Material *ma;
+ uiBlock *block;
+ void *poin;
+ float min;
+ int xco, a, dx, dy;
+ char str[32];
+
+ ob= OBACT;
+ if(ob==0) return;
+
+ sprintf(str, "buttonswin %d", curarea->win);
+ block= uiNewBlock(&curarea->uiblocks, str, UI_EMBOSSX, UI_HELV, curarea->win);
+
+ /* LAYERS */
+ xco= 291;
+ dx= 32;
+ dy= 30;
+ for(a=0; a<10; a++) {
+ /* the (a+10) evaluates correctly because of
+ precedence... brackets aren't a bad idea though */
+ uiDefButI(block, TOG|BIT|(a+10), B_OBLAY+a+10, "", (short)(xco+a*(dx/2)), 180, (short)(dx/2), (short)(dy/2), &(BASACT->lay), 0, 0, 0, 0, "");
+ uiDefButI(block, TOG|BIT|a, B_OBLAY+a, "",(short)(xco+a*(dx/2)), (short)(180+dy/2), (short)(dx/2), (short)(1+dy/2), &(BASACT->lay), 0, 0, 0, 0, "");
+ if(a==4) xco+= 5;
+ }
+
+ id= ob->data;
+ if(id && id->lib) uiSetButLock(1, "Can't edit library data");
+
+ uiBlockSetCol(block, BUTGREY);
+ uiDefBut(block, LABEL, 0, "Drawtype", 28,200,100,18, 0, 0, 0, 0, 0, "");
+ uiDefButC(block, MENU, REDRAWVIEW3D, "Drawtype%t|Bounds %x1|Wire %x2|Solid %x3|Shaded %x4",
+ 28,180,100,18, &ob->dt, 0, 0, 0, 0, "Drawtype menu");
+ uiDefBut(block, LABEL, 0, "Draw Extra", 28,160,100,18, 0, 0, 0, 0, 0, "");
+ uiDefButC(block, TOG|BIT|0, REDRAWVIEW3D, "Bounds", 28, 140, 100, 18, &ob->dtx, 0, 0, 0, 0, "Display bounding object");
+ uiDefButS(block, MENU, REDRAWVIEW3D, "Bounding volume%t|Box%x0|Sphere%x1|Cylinder%x2|Cone%x3|Polyheder",
+ 28, 120, 100, 18, &ob->boundtype, 0, 0, 0, 0, "Choose between bound objects");
+ uiDefButC(block, TOG|BIT|1, REDRAWVIEW3D, "Axis", 28, 80, 100, 18, &ob->dtx, 0, 0, 0, 0, "Draw axis");
+ uiDefButC(block, TOG|BIT|2, REDRAWVIEW3D, "TexSpace", 28, 60, 100, 18, &ob->dtx, 0, 0, 0, 0, "Display texture space");
+ uiDefButC(block, TOG|BIT|3, REDRAWVIEW3D, "Name", 28, 40, 100, 18, &ob->dtx, 0, 0, 0, 0, "Print object name");
+
+ uiBlockSetCol(block, BUTGREY);
+
+ /* material en select swap en hide */
+ if ELEM5(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL) {
+
+ if(ob->type==OB_MESH) poin= &( ((Mesh *)ob->data)->texflag );
+ else if(ob->type==OB_MBALL) poin= &( ((MetaBall *)ob->data)->texflag );
+ else poin= &( ((Curve *)ob->data)->texflag );
+ uiDefButI(block, TOG|BIT|0, B_AUTOTEX, "AutoTexSpace", 143,180,130,19, poin, 0, 0, 0, 0, "To switch automatic calculation of texture space");
+
+ sprintf(str,"%d Mat:", ob->totcol);
+ if(ob->totcol) min= 1.0; else min= 0.0;
+ ma= give_current_material(ob, ob->actcol);
+
+ if(ma) {
+ uiDefButF(block, COL, 0, "", 291,123,24,30, &(ma->r), 0, 0, 0, 0, "");
+ uiDefBut(block, LABEL, 0, ma->id.name+2, 318,146, 103, 30, 0, 0, 0, 0, 0, "");
+ }
+ uiDefButC(block, NUM, B_REDR, str, 318,123,103,30, &ob->actcol, min, (float)(ob->totcol), 0, 0, "Total indices, active index");
+ uiDefBut(block, BUT,B_MATWICH, "?", 423,123,31,30, 0, 0, 0, 0, 0, "In EditMode, sets the active material index from selected faces");
+
+ uiBlockSetCol(block, BUTSALMON);
+ uiDefBut(block, BUT,B_MATNEW, "New", 292,101,80,21, 0, 0, 0, 0, 0, "Add a new Material index");
+ uiDefBut(block, BUT,B_MATDEL, "Delete", 374,101,80,21, 0, 0, 0, 0, 0, "Delete this Material index");
+ uiDefBut(block, BUT,B_MATASS, "Assign", 291,47,162,26, 0, 0, 0, 0, 0, "In EditMode, assign the active index to selected faces");
+
+ uiBlockSetCol(block, BUTGREY);
+ uiDefBut(block, BUT,B_MATSEL, "Select", 292,76,79,22, 0, 0, 0, 0, 0, "In EditMode, select faces that have the active index");
+ uiDefBut(block, BUT,B_MATDESEL, "Deselect", 373,76,79,21, 0, 0, 0, 0, 0, "Deselect everything with current indexnumber");
+
+ if(ob->type!=OB_FONT) {
+ uiDefBut(block, BUT,B_HIDE, "Hide", 1091,152,77,18, 0, 0, 0, 0, 0, "Hide selected faces");
+ uiDefBut(block, BUT,B_REVEAL, "Reveal", 1171,152,86,18, 0, 0, 0, 0, 0, "Reveal selected faces");
+ uiDefBut(block, BUT,B_SELSWAP, "Select Swap", 1091,129,166,18, 0, 0, 0, 0, 0, "Select not-selected, and deselect selected faces");
+ }
+ uiDefBut(block, BUT,B_SETSMOOTH, "Set Smooth", 291,15,80,20, 0, 0, 0, 0, 0, "In EditMode: set 'smooth' rendering of selected faces");
+ uiDefBut(block, BUT,B_SETSOLID, "Set Solid", 373,15,80,20, 0, 0, 0, 0, 0, "In EditMode: set 'solid' rendering of selected faces");
+
+ }
+
+ if ELEM3(ob->type, OB_MESH, OB_SURF, OB_CURVE) {
+ uiBlockSetCol(block, BUTSALMON);
+ uiDefBut(block, BUT,B_DOCENTRE, "Centre", 961, 115, 100, 19, 0, 0, 0, 0, 0, "Shift object data to be centered about object's origin");
+ uiDefBut(block, BUT,B_DOCENTRENEW, "Centre New", 961, 95, 100, 19, 0, 0, 0, 0, 0, "Shift object's origin to center of object data");
+ uiDefBut(block, BUT,B_DOCENTRECURSOR, "Centre Cursor", 961, 75, 100, 19, 0, 0, 0, 0, 0, "Shift object's origin to cursor location");
+ }
+
+
+ uiDrawBlock(block);
+
+}
+
+
+
+/* *************************** MESH ******************************** */
+
+#ifdef NAN_DECIMATION
+
+static int decimate_count_tria(Object *ob)
+{
+ int tottria;
+ MFace *mface;
+ Mesh *me;
+ int a;
+
+ me= ob->data;
+
+ /* count number of trias, since decimator doesnt allow quads */
+ tottria= 0;
+ mface= me->mface;
+ for(a=0; a<me->totface; a++, mface++) {
+ if(mface->v4) tottria++;
+ if(mface->v3) tottria++;
+ }
+
+ return tottria;
+}
+
+static void decimate_faces(void)
+{
+ Object *ob;
+ Mesh *me;
+ MVert *mvert;
+ MFace *mface;
+ LOD_Decimation_Info lod;
+ float *vb=NULL;
+ float *vnb=NULL;
+ int *tib=NULL;
+ int a, tottria;
+
+ /* we assume the active object being decimated */
+ ob= OBACT;
+ if(ob==NULL || ob->type!=OB_MESH) return;
+ me= ob->data;
+
+ /* add warning for vertex col and tfaces */
+ if(me->tface || me->mcol) {
+ if(okee("This will remove UV coords and vertexcolors")==0) return;
+ if(me->tface) MEM_freeN(me->tface);
+ if(me->mcol) MEM_freeN(me->mcol);
+ me->tface= NULL;
+ me->mcol= NULL;
+ }
+
+ /* count number of trias, since decimator doesnt allow quads */
+ tottria= decimate_count_tria(ob);
+
+ if(tottria<3) {
+ error("Need more input faces than just 3");
+ return;
+ }
+ /* allocate and init */
+ lod.vertex_buffer= MEM_mallocN(3*sizeof(float)*me->totvert, "vertices");
+ lod.vertex_normal_buffer= MEM_mallocN(3*sizeof(float)*me->totvert, "normals");
+ lod.triangle_index_buffer= MEM_mallocN(3*sizeof(int)*tottria, "trias");
+ lod.vertex_num= me->totvert;
+ lod.face_num= tottria;
+
+ /* fill vertex buffer */
+ vb= lod.vertex_buffer;
+ vnb= lod.vertex_normal_buffer;
+ mvert= me->mvert;
+ for(a=0; a<me->totvert; a++, mvert++, vb+=3, vnb+=3) {
+ VECCOPY(vb, mvert->co);
+ VECCOPY(vnb, mvert->no);
+ Normalise(vnb);
+ }
+
+ /* fill index buffer */
+ mface= me->mface;
+ tib= lod.triangle_index_buffer;
+ for(a=0; a<me->totface; a++, mface++) {
+ if(mface->v4) {
+ tib[0]= mface->v1;
+ tib[1]= mface->v3;
+ tib[2]= mface->v4;
+ tib+= 3;
+ }
+ if(mface->v3) {
+ tib[0]= mface->v1;
+ tib[1]= mface->v2;
+ tib[2]= mface->v3;
+ tib+= 3;
+ }
+ }
+
+ if(LOD_LoadMesh(&lod) ) {
+ if( LOD_PreprocessMesh(&lod) ) {
+ DispList *dl;
+ DispListMesh *dlm;
+ MFaceInt *mfaceint;
+
+ /* we assume the decim_faces tells how much to reduce */
+
+ while(lod.face_num > decim_faces) {
+ if( LOD_CollapseEdge(&lod)==0) break;
+ }
+
+ /* ok, put back the stuff in a displist */
+ freedisplist(&(ob->disp));
+ dl= MEM_callocN(sizeof(DispList), "disp");
+ BLI_addtail(&ob->disp, dl);
+ dl->type= DL_MESH;
+ dlm=dl->mesh= MEM_callocN(sizeof(DispListMesh), "dispmesh");
+ dlm->mvert= MEM_callocN(lod.vertex_num*sizeof(MVert), "mvert");
+ dlm->mface= MEM_callocN(lod.face_num*sizeof(MFaceInt), "mface");
+ dlm->totvert= lod.vertex_num;
+ dlm->totface= lod.face_num;
+
+ mvert= dlm->mvert;
+ vb= lod.vertex_buffer;
+ for(a=0; a<lod.vertex_num; a++, vb+=3, mvert++) {
+ VECCOPY(mvert->co, vb);
+ }
+
+ mfaceint= dlm->mface;
+ tib= lod.triangle_index_buffer;
+ for(a=0; a<lod.face_num; a++, mfaceint++, tib+=3) {
+ mfaceint->v1= tib[0];
+ mfaceint->v2= tib[1];
+ mfaceint->v3= tib[2];
+ }
+ }
+ else error("No memory");
+
+ LOD_FreeDecimationData(&lod);
+ }
+ else error("No manifold Mesh");
+
+ MEM_freeN(lod.vertex_buffer);
+ MEM_freeN(lod.vertex_normal_buffer);
+ MEM_freeN(lod.triangle_index_buffer);
+
+ allqueue(REDRAWVIEW3D, 0);
+}
+
+
+
+static void decimate_cancel(void)
+{
+ Object *ob;
+
+ ob= OBACT;
+ if(ob) {
+ freedisplist(&ob->disp);
+ makeDispList(ob);
+ }
+ allqueue(REDRAWVIEW3D, 0);
+}
+
+static void decimate_apply(void)
+{
+ Object *ob;
+ DispList *dl;
+ DispListMesh *dlm;
+ Mesh *me;
+ MFace *mface;
+ MFaceInt *mfaceint;
+ int a;
+
+ if(G.obedit) return;
+
+ ob= OBACT;
+ if(ob) {
+ dl= ob->disp.first;
+ if(dl && dl->mesh) {
+ dlm= dl->mesh;
+ me= ob->data;
+
+ // vertices
+ if(me->mvert) MEM_freeN(me->mvert);
+ me->mvert= dlm->mvert;
+ dlm->mvert= NULL;
+ me->totvert= dlm->totvert;
+
+ // faces
+ if(me->mface) MEM_freeN(me->mface);
+ me->mface= MEM_callocN(dlm->totface*sizeof(MFace), "mface");
+ me->totface= dlm->totface;
+ mface= me->mface;
+ mfaceint= dlm->mface;
+ for(a=0; a<me->totface; a++, mface++, mfaceint++) {
+ mface->v1= mfaceint->v1;
+ mface->v2= mfaceint->v2;
+ mface->v3= mfaceint->v3;
+ test_index_mface(mface, 3);
+ }
+
+ freedisplist(&ob->disp);
+
+ G.obedit= ob;
+ make_editMesh();
+ load_editMesh();
+ free_editMesh();
+ G.obedit= NULL;
+ tex_space_mesh(me);
+ }
+ else error("Not a decimated Mesh");
+ }
+}
+
+#endif
+
+void do_meshbuts(unsigned short event)
+{
+ Object *ob;
+ Mesh *me;
+ float fac;
+ short randfac;
+
+ ob= OBACT;
+ if(ob && ob->type==OB_MESH) {
+
+ me= get_mesh(ob);
+ if(me==0) return;
+
+ switch(event) {
+#ifdef __NLA
+ case B_AUTOVGROUP:
+ if (!get_armature(ob->parent)){
+ error ("Mesh must be the child of an armature");
+ break;
+ }
+ /* Verify that there are vertex groups for bones in armature */
+ /* Remove selected vertices from all defgroups */
+ /* Perform assignment for selected vertices */
+
+ allqueue (REDRAWVIEW3D, 1);
+ break;
+ case B_NEWVGROUP:
+ add_defgroup (G.obedit);
+ scrarea_queue_winredraw(curarea);
+ break;
+ case B_DELVGROUP:
+ del_defgroup (G.obedit);
+ allqueue (REDRAWVIEW3D, 1);
+ break;
+ case B_ASSIGNVGROUP:
+ assign_verts_defgroup ();
+ allqueue (REDRAWVIEW3D, 1);
+ break;
+ case B_REMOVEVGROUP:
+ remove_verts_defgroup (0);
+ allqueue (REDRAWVIEW3D, 1);
+ break;
+ case B_SELVGROUP:
+ sel_verts_defgroup(1);
+ allqueue (REDRAWVIEW3D, 1);
+ break;
+ case B_DESELVGROUP:
+ sel_verts_defgroup(0);
+ allqueue (REDRAWVIEW3D, 1);
+ break;
+#endif
+ case B_DELSTICKY:
+
+ if(me->msticky) MEM_freeN(me->msticky);
+ me->msticky= 0;
+ allqueue(REDRAWBUTSEDIT, 0);
+ break;
+ case B_MAKESTICKY:
+ make_sticky();
+ break;
+ case B_MAKEVERTCOL:
+ make_vertexcol();
+ break;
+ case B_DELVERTCOL:
+ if(me->mcol) MEM_freeN(me->mcol);
+ me->mcol= 0;
+ G.f &= ~G_VERTEXPAINT;
+ freedisplist(&(ob->disp));
+ allqueue(REDRAWBUTSEDIT, 0);
+ allqueue(REDRAWVIEW3D, 0);
+ break;
+
+ case B_MAKE_TFACES:
+ make_tfaces(me);
+ allqueue(REDRAWBUTSEDIT, 0);
+ break;
+
+ case B_DEL_TFACES:
+ if(me->tface) MEM_freeN(me->tface);
+ me->tface= 0;
+ G.f &= ~G_FACESELECT;
+ allqueue(REDRAWBUTSEDIT, 0);
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWIMAGE, 0);
+ break;
+
+ case B_FLIPNORM:
+ if(G.obedit) {
+ flip_editnormals();
+ }
+ else flipnorm_mesh( get_mesh(ob) );
+
+ allqueue(REDRAWVIEW3D, 0);
+ break;
+
+ case B_DECIM_FACES:
+ decimate_faces();
+ break;
+ case B_DECIM_CANCEL:
+ decimate_cancel();
+ break;
+ case B_DECIM_APPLY:
+ decimate_apply();
+ break;
+
+ case B_SLOWERDRAW:
+ slowerdraw();
+ break;
+ case B_FASTERDRAW:
+ fasterdraw();
+ break;
+ }
+ }
+
+ if(G.obedit==0 || (G.obedit->type!=OB_MESH)) return;
+
+ switch(event) {
+ case B_SPIN:
+ if( select_area(SPACE_VIEW3D)) spin_mesh(step, degr, 0, 0);
+ break;
+ case B_SPINDUP:
+ if( select_area(SPACE_VIEW3D)) spin_mesh(step, degr, 0, 1);
+ break;
+ case B_EXTR:
+ G.f |= G_DISABLE_OK;
+ if( select_area(SPACE_VIEW3D)) extrude_mesh();
+ G.f -= G_DISABLE_OK;
+ break;
+ case B_SCREW:
+ if( select_area(SPACE_VIEW3D)) screw_mesh(step, turn);
+ break;
+ case B_EXTREP:
+ if( select_area(SPACE_VIEW3D)) extrude_repeat_mesh(step, extr_offs);
+ break;
+ case B_SPLIT:
+ G.f |= G_DISABLE_OK;
+ split_mesh();
+ G.f -= G_DISABLE_OK;
+ break;
+ case B_REMDOUB:
+ notice("Removed: %d", removedoublesflag(1, doublimit));
+ allqueue(REDRAWVIEW3D, 0);
+ break;
+ case B_SUBDIV:
+ waitcursor(1);
+ subdivideflag(1, 0.0, editbutflag & B_BEAUTY);
+ countall();
+ waitcursor(0);
+ allqueue(REDRAWVIEW3D, 0);
+ break;
+ case B_FRACSUBDIV:
+ randfac= 10;
+ if(button(&randfac, 1, 100, "Rand fac:")==0) return;
+ waitcursor(1);
+ fac= -( (float)randfac )/100;
+ subdivideflag(1, fac, editbutflag & B_BEAUTY);
+ countall();
+ waitcursor(0);
+ allqueue(REDRAWVIEW3D, 0);
+ break;
+ case B_XSORT:
+ if( select_area(SPACE_VIEW3D)) xsortvert_flag(1);
+ break;
+ case B_HASH:
+ hashvert_flag(1);
+ break;
+ case B_TOSPHERE:
+ vertices_to_sphere();
+ break;
+ case B_INTERSECTMESH:
+ intersect_mesh();
+ break;
+ case B_VERTEXNOISE:
+ vertexnoise();
+ break;
+ case B_VERTEXSMOOTH:
+ vertexsmooth();
+ break;
+ }
+ /* LETOP: bovenstaande events alleen in editmode! */
+}
+
+static void verify_vertexgroup_name_func(void *datav, void *data2_unused)
+{
+ unique_vertexgroup_name((bDeformGroup*)datav, OBACT);
+}
+
+void meshbuts(void)
+{
+ Object *ob;
+ Mesh *me;
+ uiBlock *block;
+ uiBut *but;
+ float val;
+ char str[64];
+#ifdef __NLA
+ int by;
+ float min;
+ int defCount;
+ bDeformGroup *defGroup;
+#endif
+
+ ob= OBACT;
+ if(ob==0) return;
+
+ sprintf(str, "editbuttonswin %d", curarea->win);
+ block= uiNewBlock(&curarea->uiblocks, str, UI_EMBOSSX, UI_HELV, curarea->win);
+
+ me= get_mesh(ob);
+
+ if(me) {
+ uiDefButS(block, TOG|BIT|1, REDRAWVIEW3D, "No V.Normal Flip", 143,160,130,18, &me->flag, 0, 0, 0, 0, "Disable flipping of vertexnormals during render");
+ uiBlockSetCol(block, BUTGREEN);
+ uiDefButS(block, TOG|BIT|5, REDRAWVIEW3D, "Auto Smooth", 143,140,130,18, &me->flag, 0, 0, 0, 0, "Automatic detection of smooth rendered faces during render");
+ uiBlockSetCol(block, BUTGREY);
+ uiDefButS(block, NUM, B_DIFF, "Degr:", 143, 120, 130, 18, &me->smoothresh, 1, 80, 0, 0, "Maximum angle (between face normals) that defines smooth rendering");
+ uiBlockSetCol(block, BUTGREEN);
+ uiDefButS(block, TOG|BIT|7, B_MAKEDISP, "SubSurf", 143,100,130,18, &me->flag, 0, 0, 0, 0, "Catmull-Clark Subdivision Surface");
+ uiBlockSetCol(block, BUTGREY);
+ uiDefButS(block, NUM, B_MAKEDISP, "Subdiv:", 143, 80, 100, 18, &me->subdiv, 0, 12, 0, 0, "Level of subdivision for interactive display");
+ uiDefButS(block, NUM, B_MAKEDISP, "", 243, 80, 30, 18, &me->subdivr, 0, 12, 0, 0, "Level of subdivision for rendering");
+ uiDefButS(block, TOG|BIT|2, REDRAWVIEW3D, "Double Sided", 1090,184,164,19, &me->flag, 0, 0, 0, 0, "Make faces doublesided");
+
+ uiBlockSetCol(block, BUTSALMON);
+
+ if(me->msticky) val= 1.0; else val= 0.0;
+ uiDefBut(block, LABEL, 0, "Sticky", 137,55,70,20, 0, val, 0, 0, 0, "");
+ if(me->msticky==0) {
+ uiDefBut(block, BUT, B_MAKESTICKY, "Make", 210,58,63,19, 0, 0, 0, 0, 0, "Make sticky texture coords (projected from view)");
+ }
+ else uiDefBut(block, BUT, B_DELSTICKY, "Delete", 210,58,63,19, 0, 0, 0, 0, 0, "Delete sticky texture coords");
+
+ if(me->mcol) val= 1.0; else val= 0.0;
+ uiDefBut(block, LABEL, 0, "VertCol", 140,33,70,20, 0, val, 0, 0, 0, "");
+ if(me->mcol==0) {
+ uiDefBut(block, BUT, B_MAKEVERTCOL, "Make", 209,36,64,19, 0, 0, 0, 0, 0, "Enable vertex colours");
+ }
+ else uiDefBut(block, BUT, B_DELVERTCOL, "Delete", 209,36,64,19, 0, 0, 0, 0, 0, "");
+
+ if(me->tface) val= 1.0; else val= 0.0;
+ uiDefBut(block, LABEL, 0, "TexFace", 142,13,70,20, 0, val, 0, 0, 0, "");
+ if(me->tface==0) {
+ uiDefBut(block, BUT, B_MAKE_TFACES, "Make", 209,14,64,20, 0, 0, 0, 0, 0, "Enable texture face");
+ }
+ else uiDefBut(block, BUT, B_DEL_TFACES, "Delete", 209,14,64,20, 0, 0, 0, 0, 0, "Delete texture face");
+
+ uiBlockSetCol(block, BUTGREY);
+
+ uiDefIDPoinBut(block, test_meshpoin_but, 0, "TexMesh:", 477,185,249,19, &me->texcomesh, "Enter the name of a Meshblock");
+ }
+
+
+ /* EDIT */
+
+ if(me) {
+#ifdef NAN_DECIMATION
+ int tottria= decimate_count_tria(ob);
+ DispList *dl;
+
+ // wacko, wait for new displist system (ton)
+ if( (dl=ob->disp.first) && dl->mesh);
+ else decim_faces= tottria;
+
+ uiBlockSetCol(block, BUTPURPLE);
+ uiDefButI(block, NUMSLI,B_DECIM_FACES, "Decimator", 477,155,249,20, &decim_faces, 4.0, tottria, 10, 10, "The number of triangles to reduce to");
+ uiBlockSetCol(block, BUTSALMON);
+ uiDefBut(block, BUT,B_DECIM_CANCEL, "Cancel", 477,135,124,19, 0, 0, 0, 0, 0, "restore Mesh");
+ uiDefBut(block, BUT,B_DECIM_APPLY, "Apply", 602,135,124,19, 0, 0, 0, 0, 0, "apply decimation to Mesh");
+#endif
+
+ uiBlockSetCol(block, BUTSALMON);
+ uiDefBut(block, BUT,B_EXTR,"Extrude", 477,100,249,24, 0, 0, 0, 0, 0, "Convert selected edges to faces");
+ uiDefBut(block, BUT,B_SPINDUP,"Spin Dup", 639,75,87,24, 0, 0, 0, 0, 0, "Use spin with duplication tool");
+ uiDefBut(block, BUT,B_SPIN, "Spin", 558,75,78,24, 0, 0, 0, 0, 0, "Use spin tool");
+ uiDefBut(block, BUT,B_SCREW,"Screw", 477,75,79,24, 0, 0, 0, 0, 0, "Use screw tool");
+ uiDefBut(block, BUT,B_EXTREP, "ExtrudeRepeat",477,15,128,19, 0, 0, 0, 0, 0, "Create a repetitive extrude along a straight line");
+
+ uiBlockSetCol(block, BUTGREY);
+ uiDefButS(block, NUM, B_DIFF, "Degr:", 477,55,78,19, &degr,10.0,360.0, 0, 0, "Specify the number of degrees the spin revolves");
+ uiDefButS(block, NUM, B_DIFF, "Steps:", 558,55,78,19, &step,1.0,180.0, 0, 0, "Specify the total number of spin revolutions");
+ uiDefButS(block, NUM, B_DIFF, "Turns:", 639,55,86,19, &turn,1.0,360.0, 0, 0, "Specify the number of revolutions the screw turns");
+ uiDefButS(block, TOG|BIT|0, B_DIFF, "Clockwise", 639,35,86,19, &editbutflag, 0, 0, 0, 0, "Specify the direction for screw and spin");
+ uiDefButS(block, TOG|BIT|1, B_DIFF, "Keep Original", 477,35,156,19, &editbutflag, 0, 0, 0, 0, "Seperate original and new vertices and faces");
+ uiDefButF(block, NUM, B_DIFF, "Offset:", 608,15,117,19, &extr_offs, 0.01, 10.0, 100, 0, "Set the distance between each step of the extrude repeat");
+ }
+
+ by=206;
+
+ uiBlockSetCol(block, BUTGREEN);
+ uiDefButS(block, TOG|BIT|2, 0, "Beauty", 847,by-=20,94,19, &editbutflag, 0, 0, 0, 0, "Split face in halves");
+ uiBlockSetCol(block, BUTSALMON);
+
+ uiDefBut(block, BUT, B_INTERSECTMESH, "Intersect", 847,by-=19,94,18, 0, 0, 0, 0, 0, "Intersect selected faces");
+ uiDefBut(block, BUT,B_SPLIT,"Split", 847,by-=19,94,18, 0, 0, 0, 0, 0, "Split msh without removing faces");
+ uiDefBut(block, BUT,B_TOSPHERE,"To Sphere", 847,by-=19,94,18, 0, 0, 0, 0, 0, "Blow vertices up into spherical shape");
+ uiDefBut(block, BUT,B_SUBDIV,"Subdivide", 847,by-=19,94,18, 0, 0, 0, 0, 0, "Split face in quarters");
+ uiDefBut(block, BUT,B_FRACSUBDIV, "Fract Subd",847,by-=19,94,18, 0, 0, 0, 0, 0, "Split face with random factor");
+
+ uiDefBut(block, BUT,B_VERTEXNOISE,"Noise", 847,by-=19,94,18, 0, 0, 0, 0, 0, "Use vertex coordinate as texture coordinate");
+ uiDefBut(block, BUT,B_VERTEXSMOOTH,"Smooth", 847,by-=19,94,18, 0, 0, 0, 0, 0, "Flatten angels");
+ uiDefBut(block, BUT,B_XSORT,"Xsort", 847,by-=19,94,18, 0, 0, 0, 0, 0, "Sort vertices in the X direction");
+ uiDefBut(block, BUT,B_HASH,"Hash", 847,by-=19,94,18, 0, 0, 0, 0, 0, "Randomize vertices sequence");
+
+ uiBlockSetCol(block, BUTGREY);
+ uiDefButF(block, NUM, B_DIFF, "Limit:", 959,151,100,19, &doublimit, 0.0001, 1.0, 10, 0, "Specify the limit in distance to remove doubles");
+
+ uiBlockSetCol(block, BUTSALMON);
+
+ uiDefBut(block, BUT,B_REMDOUB,"Rem Doubles", 958,173,101,32, 0, 0, 0, 0, 0, "Remove doubles");
+
+ uiDefBut(block, BUT,B_FLIPNORM,"Flip Normals", 961,55,100,19, 0, 0, 0, 0, 0, "Toggle the direction of the face normals");
+
+ uiDefBut(block, BUT, B_SLOWERDRAW,"SlowerDraw", 961,35,100,19, 0, 0, 0, 0, 0, "Draw slow but accurate");
+ uiDefBut(block, BUT, B_FASTERDRAW,"FasterDraw", 961,15,100,19, 0, 0, 0, 0, 0, "Draw fast but less accurate");
+
+#ifdef __NLA
+
+ /* Draw Vertex grouping buttons if we're in editmode*/
+ if (ob){
+ char *s, *menustr;
+ bDeformGroup *dg;
+ int index;
+
+ by = 210;
+ uiBlockSetCol(block, BUTGREY);
+ uiDefBut(block, LABEL,0,"Vertex Groups", 740,by-=19,93,18, 0, 0, 0, 0, 0, "");
+
+ defCount=BLI_countlist(&ob->defbase);
+
+ if (!defCount)
+ min=0;
+ else
+ min=1;
+
+#if 0
+ sprintf (str, "%d Group:", defCount);
+ uiDefButS(block, NUM, REDRAWBUTSEDIT, str, 740, by-=22,93,18, &ob->actdef, min, defCount, 0, 0, "");
+#else
+ s= menustr = MEM_callocN((32 * defCount)+20, "menustr");
+
+ for (index = 1, dg = ob->defbase.first; dg; index++, dg=dg->next){
+ int cnt= sprintf (s, "%s%%x%d|", dg->name, index);
+
+ if (cnt>0)
+ s+= cnt;
+ }
+
+ by-=22;
+ if (defCount)
+ uiDefButS(block, MENU, REDRAWBUTSEDIT, menustr, 740, by,18,18, &ob->actdef, min, defCount, 0, 0, "Active deformation group");
+ MEM_freeN (menustr);
+#endif
+ if (ob->actdef){
+ defGroup = BLI_findlink(&ob->defbase, ob->actdef-1);
+ but= uiDefBut(block, TEX,REDRAWBUTSEDIT,"", 758,by,93-18,18, defGroup->name, 0, 32, 0, 0, "Change the current deformations group's name (and bone affiliation)");
+ uiButSetFunc(but, verify_vertexgroup_name_func, defGroup, NULL);
+ }
+ uiDefButF(block, NUM, REDRAWVIEW3D, "Weight:", 740, by-=22, 93, 18, &editbutvweight, 0, 1, 10, 0, "Change the bone's deformation strength");
+
+ }
+
+ if (G.obedit && G.obedit==ob){
+
+ uiBlockSetCol(block, BUTSALMON);
+/* uiDefBut(block, BUT,B_AUTOVGROUP,"Auto Weight", 740,by-=22,93,18, 0, 0, 0, 0, 0, "Automatically assign deformation groups"); */
+ uiDefBut(block, BUT,B_NEWVGROUP,"New", 740,by-=22,45,18, 0, 0, 0, 0, 0, "Create a new deformation group");
+ uiDefBut(block, BUT,B_DELVGROUP,"Delete", 788,by,45,18, 0, 0, 0, 0, 0, "Remove the current deformation group");
+
+ uiBlockSetCol(block, BUTSALMON);
+ uiDefBut(block, BUT,B_ASSIGNVGROUP,"Assign", 740,by-=22,93,18, 0, 0, 0, 0, 0, "Assign selected vertices to the current deformation group");
+ uiDefBut(block, BUT,B_REMOVEVGROUP,"Remove", 740,by-=22,93,18, 0, 0, 0, 0, 0, "Remove selected vertices from the current deformation group");
+
+ uiBlockSetCol(block, BUTGREY);
+ uiDefBut(block, BUT,B_SELVGROUP,"Select", 740,by-=22,93,18, 0, 0, 0, 0, 0, "Select vertices belonging to the current deformation group");
+ uiDefBut(block, BUT,B_DESELVGROUP,"Deselect", 740,by-=22,93,18, 0, 0, 0, 0, 0, "Deselect vertices belonging to the current deformation group");
+
+}
+#endif
+
+ uiBlockSetCol(block, BUTGREY);
+ uiDefButF(block, NUM, REDRAWVIEW3D, "NSize:", 1090, 90, 164, 19, &editbutsize, 0.001, 2.0, 10, 0, "Set the length of the face normals");
+ uiDefButI(block, TOG|BIT|6, REDRAWVIEW3D, "Draw Normals", 1090,70,164,19, &G.f, 0, 0, 0, 0, "Draw face normals");
+ uiDefButI(block, TOG|BIT|7, REDRAWVIEW3D, "Draw Faces", 1090,50,164,19, &G.f, 0, 0, 0, 0, "Draw faces");
+ uiDefButI(block, TOG|BIT|11, 0, "All edges", 1090,10,164,19, &G.f, 0, 0, 0, 0, "Draw edges normally, without optimisation");
+
+ uiDrawBlock(block);
+}
+
+/* *************************** FONT ******************************** */
+
+short give_vfontnr(VFont *vfont)
+{
+ VFont *vf;
+ short nr= 1;
+
+ vf= G.main->vfont.first;
+ while(vf) {
+ if(vf==vfont) return nr;
+ nr++;
+ vf= vf->id.next;
+ }
+ return -1;
+}
+
+VFont *give_vfontpointer(int nr) /* nr= button */
+{
+ VFont *vf;
+ short tel= 1;
+
+ vf= G.main->vfont.first;
+ while(vf) {
+ if(tel==nr) return vf;
+ tel++;
+ vf= vf->id.next;
+ }
+ return G.main->vfont.first;
+}
+
+VFont *exist_vfont(char *str)
+{
+ VFont *vf;
+
+ vf= G.main->vfont.first;
+ while(vf) {
+ if(strcmp(vf->name, str)==0) return vf;
+ vf= vf->id.next;
+ }
+ return 0;
+}
+
+static char *give_vfontbutstr(void)
+{
+ VFont *vf;
+ int len= 0;
+ char *str, di[FILE_MAXDIR], fi[FILE_MAXFILE];
+
+ vf= G.main->vfont.first;
+ while(vf) {
+ strcpy(di, vf->name);
+ BLI_splitdirstring(di, fi);
+ len+= strlen(fi)+4;
+ vf= vf->id.next;
+ }
+
+ str= MEM_callocN(len+21, "vfontbutstr");
+ strcpy(str, "FONTS %t");
+ vf= G.main->vfont.first;
+ while(vf) {
+
+ if(vf->id.us==0) strcat(str, "|0 ");
+ else strcat(str, "| ");
+
+ strcpy(di, vf->name);
+ BLI_splitdirstring(di, fi);
+
+ strcat(str, fi);
+ vf= vf->id.next;
+ }
+ return str;
+}
+
+void load_buts_vfont(char *name)
+{
+ VFont *vf;
+ Curve *cu;
+
+ if(OBACT && OBACT->type==OB_FONT) cu= OBACT->data;
+ else return;
+
+ vf= exist_vfont(name);
+ if(vf==0) {
+ vf= load_vfont(name);
+ if(vf==0) return;
+ }
+ else id_us_plus((ID *)vf);
+
+ if(cu->vfont) cu->vfont->id.us--;
+ cu->vfont= vf;
+
+ text_to_curve(OBACT, 0);
+ makeDispList(OBACT);
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWBUTSEDIT, 0);
+}
+
+void do_fontbuts(unsigned short event)
+{
+ Curve *cu;
+ VFont *vf;
+ Object *ob;
+ ScrArea *sa;
+ char str[80];
+
+ ob= OBACT;
+
+ switch(event) {
+ case B_MAKEFONT:
+ text_to_curve(ob, 0);
+ makeDispList(ob);
+ allqueue(REDRAWVIEW3D, 0);
+ break;
+ case B_TOUPPER:
+ to_upper();
+ break;
+ case B_LOADFONT:
+ vf= give_vfontpointer(G.buts->texnr);
+ if(vf && vf->id.prev!=vf->id.next) strcpy(str, vf->name);
+ else strcpy(str, U.fontdir);
+
+ sa= closest_bigger_area();
+ areawinset(sa->win);
+
+ activate_fileselect(FILE_SPECIAL, "SELECT FONT", str, load_buts_vfont);
+
+ break;
+ case B_PACKFONT:
+ if (ob) {
+ cu= ob->data;
+ if(cu && cu->vfont) {
+ if (cu->vfont->packedfile) {
+ if (G.fileflags & G_AUTOPACK) {
+ if (okee("Disable AutoPack ?")) {
+ G.fileflags &= ~G_AUTOPACK;
+ }
+ }
+
+ if ((G.fileflags & G_AUTOPACK) == 0) {
+ if (unpackVFont(cu->vfont, PF_ASK) == RET_OK) {
+ text_to_curve(ob, 0);
+ makeDispList(ob);
+ allqueue(REDRAWVIEW3D, 0);
+ }
+ }
+ } else {
+ cu->vfont->packedfile = newPackedFile(cu->vfont->name);
+ }
+ }
+ }
+ allqueue(REDRAWHEADERS, 0);
+ allqueue(REDRAWBUTSEDIT, 0);
+ break;
+
+ case B_SETFONT:
+ if(ob) {
+ cu= ob->data;
+
+ vf= give_vfontpointer(G.buts->texnr);
+ if(vf) {
+ id_us_plus((ID *)vf);
+ cu->vfont->id.us--;
+ cu->vfont= vf;
+ text_to_curve(ob, 0);
+ makeDispList(ob);
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWBUTSEDIT, 0);
+ }
+ }
+ break;
+ case B_TEXTONCURVE:
+ if(ob) {
+ cu= ob->data;
+ if(cu->textoncurve && cu->textoncurve->type!=OB_CURVE) {
+ error("Only Curve Objects");
+ cu->textoncurve= 0;
+ allqueue(REDRAWBUTSEDIT, 0);
+ }
+ text_to_curve(ob, 0);
+ makeDispList(ob);
+ }
+ }
+}
+
+
+
+void fontbuts(void)
+{
+ Curve *cu;
+ uiBlock *block;
+ char *strp, str[64];
+
+ if(OBACT==0) return;
+
+ sprintf(str, "editbuttonswin1 %d", curarea->win);
+ block= uiNewBlock(&curarea->uiblocks, str, UI_EMBOSSX, UI_HELV, curarea->win);
+
+ cu= OBACT->data;
+
+ uiBlockSetCol(block, BUTGREEN);
+ uiDefButS(block, ROW,B_MAKEFONT, "Left", 484,139,53,18, &cu->spacemode, 0.0,0.0, 0, 0, "");
+ uiDefButS(block, ROW,B_MAKEFONT, "Middle", 604,139,61,18, &cu->spacemode, 0.0,1.0, 0, 0, "");
+ uiDefButS(block, ROW,B_MAKEFONT, "Right", 540,139,62,18, &cu->spacemode, 0.0,2.0, 0, 0, "");
+ uiDefButS(block, ROW,B_MAKEFONT, "Flush", 665,139,61,18, &cu->spacemode, 0.0,3.0, 0, 0, "");
+
+ uiBlockSetCol(block, BUTGREY);
+
+ uiDefIDPoinBut(block, test_obpoin_but, B_TEXTONCURVE, "TextOnCurve:", 484,115,243,19, &cu->textoncurve, "");
+
+ uiDefButF(block, NUM,B_MAKEFONT, "Size:", 482,56,121,19, &cu->fsize, 0.1,10.0, 10, 0, "");
+ uiDefButF(block, NUM,B_MAKEFONT, "Linedist:", 605,56,121,19, &cu->linedist, 0.0,10.0, 10, 0, "");
+ uiDefButF(block, NUM,B_MAKEFONT, "Spacing:", 482,34,121,19, &cu->spacing, 0.0,10.0, 10, 0, "");
+ uiDefButF(block, NUM,B_MAKEFONT, "Y offset:", 605,34,121,19, &cu->yof, -50.0,50.0, 10, 0, "");
+ uiDefButF(block, NUM,B_MAKEFONT, "Shear:", 482,12,121,19, &cu->shear, -1.0,1.0, 10, 0, "");
+ uiDefButF(block, NUM,B_MAKEFONT, "X offset:", 605,12,121,19, &cu->xof, -50.0,50.0, 10, 0, "");
+
+ uiDefBut(block, TEX,REDRAWVIEW3D, "Ob Family:", 752,192,164,19, cu->family, 0.0, 20.0, 0, 0, "");
+
+ uiBlockSetCol(block, BUTSALMON);
+ uiDefBut(block, BUT, B_TOUPPER, "ToUpper", 623,163,103,23, 0, 0, 0, 0, 0, "");
+
+ uiBlockSetCol(block, BUTGREY);
+
+ G.buts->texnr= give_vfontnr(cu->vfont);
+
+ strp= give_vfontbutstr();
+
+ uiDefButS(block, MENU, B_SETFONT, strp, 484,191,220,20, &G.buts->texnr, 0, 0, 0, 0, "");
+
+ if (cu->vfont->packedfile) {
+ packdummy = 1;
+ } else {
+ packdummy = 0;
+ }
+
+ uiBlockSetCol(block, BUTYELLOW);
+ uiDefIconButI(block, TOG|BIT|0, B_PACKFONT, ICON_PACKAGE, 706,191,20,20, &packdummy, 0, 0, 0, 0, "Pack/Unpack this Vectorfont");
+
+ MEM_freeN(strp);
+
+ uiBlockSetCol(block, BUTSALMON);
+ uiDefBut(block, BUT,B_LOADFONT, "Load Font", 484,163,103,23, 0, 0, 0, 0, 0, "");
+
+ uiDrawBlock(block);
+}
+
+/* *************************** CURVE ******************************** */
+
+
+void do_curvebuts(unsigned short event)
+{
+ extern Nurb *lastnu;
+ Object *ob;
+ Curve *cu;
+ Nurb *nu;
+
+ ob= OBACT;
+ if(ob==0) return;
+
+ switch(event) {
+
+ case B_CONVERTPOLY:
+ case B_CONVERTBEZ:
+ case B_CONVERTBSPL:
+ case B_CONVERTCARD:
+ case B_CONVERTNURB:
+ if(G.obedit) {
+ setsplinetype(event-B_CONVERTPOLY);
+ makeDispList(G.obedit);
+ allqueue(REDRAWVIEW3D, 0);
+ }
+ break;
+ case B_UNIFU:
+ case B_ENDPU:
+ case B_BEZU:
+ case B_UNIFV:
+ case B_ENDPV:
+ case B_BEZV:
+ if(G.obedit) {
+ nu= editNurb.first;
+ while(nu) {
+ if(isNurbsel(nu)) {
+ if((nu->type & 7)==CU_NURBS) {
+ if(event<B_UNIFV) {
+ nu->flagu &= 1;
+ nu->flagu += ((event-B_UNIFU)<<1);
+ makeknots(nu, 1, nu->flagu>>1);
+ }
+ else if(nu->pntsv>1) {
+ nu->flagv &= 1;
+ nu->flagv += ((event-B_UNIFV)<<1);
+ makeknots(nu, 2, nu->flagv>>1);
+ }
+ }
+ }
+ nu= nu->next;
+ }
+ makeDispList(G.obedit);
+ allqueue(REDRAWVIEW3D, 0);
+ }
+ break;
+ case B_SETWEIGHT:
+ if(G.obedit) {
+ weightflagNurb(1, editbutweight, 0);
+ makeDispList(G.obedit);
+ allqueue(REDRAWVIEW3D, 0);
+ }
+ break;
+ case B_SETW1:
+ editbutweight= 1.0;
+ scrarea_queue_winredraw(curarea);
+ break;
+ case B_SETW2:
+ editbutweight= sqrt(2.0)/4.0;
+ scrarea_queue_winredraw(curarea);
+ break;
+ case B_SETW3:
+ editbutweight= 0.25;
+ scrarea_queue_winredraw(curarea);
+ break;
+ case B_SETW4:
+ editbutweight= sqrt(0.5);
+ scrarea_queue_winredraw(curarea);
+ break;
+ case B_SETORDER:
+ if(G.obedit) {
+ nu= lastnu;
+ if(nu && (nu->type & 7)==CU_NURBS ) {
+ if(nu->orderu>nu->pntsu) {
+ nu->orderu= nu->pntsu;
+ scrarea_queue_winredraw(curarea);
+ }
+ makeknots(nu, 1, nu->flagu>>1);
+ if(nu->orderv>nu->pntsv) {
+ nu->orderv= nu->pntsv;
+ scrarea_queue_winredraw(curarea);
+ }
+ makeknots(nu, 2, nu->flagv>>1);
+ }
+ makeDispList(G.obedit);
+ allqueue(REDRAWVIEW3D, 0);
+ }
+ break;
+ case B_MAKEDISP:
+ if(ob->type==OB_FONT) text_to_curve(ob, 0);
+ makeDispList(ob);
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWINFO, 1); /* 1, want header->win==0! */
+ break;
+
+ case B_SUBDIVCURVE:
+ subdivideNurb();
+ break;
+ case B_SPINNURB:
+ /* bad bad bad!!! use brackets!!! In case you wondered:
+ {==,!=} goes before & goes before || */
+ if( (G.obedit==0) ||
+ (G.obedit->type!=OB_SURF) ||
+ ((G.obedit->lay & G.vd->lay) == 0) ) return;
+ spinNurb(0, 0);
+ countall();
+ makeDispList(G.obedit);
+ allqueue(REDRAWVIEW3D, 0);
+ break;
+ case B_CU3D: /* allow 3D curve */
+ if(G.obedit) {
+ cu= G.obedit->data;
+ nu= editNurb.first;
+ while(nu) {
+ nu->type &= ~CU_2D;
+ if((cu->flag & CU_3D)==0) nu->type |= CU_2D;
+ test2DNurb(nu);
+ nu= nu->next;
+ }
+ }
+ if(ob->type==OB_CURVE) {
+ cu= ob->data;
+ nu= cu->nurb.first;
+ while(nu) {
+ nu->type &= ~CU_2D;
+ if((cu->flag & CU_3D)==0) nu->type |= CU_2D;
+ test2DNurb(nu);
+ nu= nu->next;
+ }
+ }
+ break;
+ case B_SETRESOLU:
+ if(ob->type==OB_CURVE) {
+ cu= ob->data;
+ if(ob==G.obedit) nu= editNurb.first;
+ else nu= cu->nurb.first;
+
+ while(nu) {
+ nu->resolu= cu->resolu;
+ nu= nu->next;
+ }
+ }
+ else if(ob->type==OB_FONT) text_to_curve(ob, 0);
+
+ makeDispList(ob);
+ allqueue(REDRAWVIEW3D, 0);
+
+ break;
+ }
+}
+
+void curvebuts(void)
+{
+ Object *ob;
+ Curve *cu;
+ Nurb *nu;
+ extern Nurb *lastnu;
+ uiBlock *block;
+ short *sp;
+ char str[64];
+
+ ob= OBACT;
+ if(ob==0) return;
+
+ sprintf(str, "editbuttonswin %d", curarea->win);
+ block= uiNewBlock(&curarea->uiblocks, str, UI_EMBOSSX, UI_HELV, curarea->win);
+
+ cu= ob->data;
+
+ if(ob->type==OB_CURVE || ob->type==OB_SURF) {
+ uiBlockSetCol(block, BUTSALMON);
+ uiDefBut(block, LABEL, 0, "Convert", 463,173,72, 18, 0, 0, 0, 0, 0, "");
+ uiDefBut(block, BUT,B_CONVERTPOLY,"Poly", 467,152,72, 18, 0, 0, 0, 0, 0, "");
+ uiDefBut(block, BUT,B_CONVERTBEZ,"Bezier", 467,132,72, 18, 0, 0, 0, 0, 0, "");
+ uiDefBut(block, BUT,B_CONVERTBSPL,"Bspline", 467,112,72, 18, 0, 0, 0, 0, 0, "");
+ uiDefBut(block, BUT,B_CONVERTCARD,"Cardinal", 467,92,72, 18, 0, 0, 0, 0, 0, "");
+ uiDefBut(block, BUT,B_CONVERTNURB,"Nurb", 467,72,72, 18, 0, 0, 0, 0, 0, "");
+
+ uiDefBut(block, LABEL, 0, "Make Knots",562,173,102, 18, 0, 0, 0, 0, 0, "");
+ uiDefBut(block, BUT,B_UNIFU,"Uniform U", 565,152,102, 18, 0, 0, 0, 0, 0, "");
+ uiDefBut(block, BUT,B_ENDPU,"Endpoint U", 565,132,102, 18, 0, 0, 0, 0, 0, "");
+ uiDefBut(block, BUT,B_BEZU,"Bezier U", 565,112,102, 18, 0, 0, 0, 0, 0, "");
+ uiDefBut(block, BUT,B_UNIFV,"V", 670,152,50, 18, 0, 0, 0, 0, 0, "");
+ uiDefBut(block, BUT,B_ENDPV,"V", 670,132,50, 18, 0, 0, 0, 0, 0, "");
+ uiDefBut(block, BUT,B_BEZV,"V", 670,112,50, 18, 0, 0, 0, 0, 0, "");
+
+ uiDefBut(block, BUT,B_SETWEIGHT,"Set Weight", 465,11,95,49, 0, 0, 0, 0, 0, "");
+ uiBlockSetCol(block, BUTGREY);
+ uiDefButF(block, NUM,0,"Weight:", 564,36,102,22, &editbutweight, 0.01, 10.0, 10, 0, "");
+ uiDefBut(block, BUT,B_SETW1,"1.0", 669,36,50,22, 0, 0, 0, 0, 0, "");
+ uiDefBut(block, BUT,B_SETW2,"sqrt(2)/4", 564,11,57,20, 0, 0, 0, 0, 0, "");
+ uiDefBut(block, BUT,B_SETW3,"0.25", 621,11,43,20, 0, 0, 0, 0, 0, "");
+ uiDefBut(block, BUT,B_SETW4,"sqrt(0.5)", 664,11,57,20, 0, 0, 0, 0, 0, "");
+
+ if(ob==G.obedit) {
+ nu= lastnu;
+ if(nu==0) nu= editNurb.first;
+ if(nu) sp= &(nu->orderu);
+ else sp= 0;
+ uiDefButS(block, NUM, B_SETORDER, "Order U:", 565,91,102, 18, sp, 2.0, 6.0, 0, 0, "");
+ if(nu) sp= &(nu->orderv);
+ else sp= 0;
+ uiDefButS(block, NUM, B_SETORDER, "V:", 670,91,50, 18, sp, 2.0, 6.0, 0, 0, "");
+ if(nu) sp= &(nu->resolu);
+ else sp= 0;
+ uiDefButS(block, NUM, B_MAKEDISP, "Resol U:", 565,70,102, 18, sp, 1.0, 128.0, 0, 0, "");
+ if(nu) sp= &(nu->resolv);
+ else sp= 0;
+ uiDefButS(block, NUM, B_MAKEDISP, "V:", 670,70,50, 18, sp, 1.0, 128.0, 0, 0, "");
+ }
+
+ uiBlockSetCol(block, BUTSALMON);
+ uiDefBut(block, BUT, B_SUBDIVCURVE, "Subdivide", 1092,105,165,20, 0, 0, 0, 0, 0, "");
+ }
+
+ if(ob->type==OB_SURF) {
+ uiDefBut(block, BUT, B_SPINNURB, "Spin", 808,92,101,36, 0, 0, 0, 0, 0, "");
+
+ uiBlockSetCol(block, BUTGREY);
+ uiDefButS(block, TOG|BIT|5, 0, "UV Orco", 143,160,130,18, &cu->flag, 0, 0, 0, 0, "");
+ uiDefButS(block, TOG|BIT|6, REDRAWVIEW3D, "No Puno Flip", 143,140,130,18, &cu->flag, 0, 0, 0, 0, "");
+ }
+ else {
+
+ uiBlockSetCol(block, BUTGREY);
+ uiDefButS(block, TOG|BIT|5, 0, "UV Orco", 143,160,130,18, &cu->flag, 0, 0, 0, 0, "");
+
+ uiDefButS(block, NUM, B_MAKEDISP, "DefResolU:", 752,163,132,21, &cu->resolu, 1.0, 128.0, 0, 0, "");
+ uiBlockSetCol(block, BUTSALMON);
+ uiDefBut(block, BUT, B_SETRESOLU, "Set", 887,163,29,21, 0, 0, 0, 0, 0, "");
+
+ uiBlockSetCol(block, BUTGREY);
+ uiDefButS(block, NUM, B_MAKEDISP, "BevResol:", 753,30,163,18, &cu->bevresol, 0.0, 10.0, 0, 0, "");
+
+ uiDefIDPoinBut(block, test_obcurpoin_but, B_MAKEDISP, "BevOb:", 753,10,163,18, &cu->bevobj, "");
+ uiDefButF(block, NUM, B_MAKEDISP, "Width:", 753,90,163,18, &cu->width, 0.0, 2.0, 1, 0, "");
+ uiDefButF(block, NUM, B_MAKEDISP, "Ext1:", 753,70,163,18, &cu->ext1, 0.0, 5.0, 10, 0, "");
+ uiDefButF(block, NUM, B_MAKEDISP, "Ext2:", 753,50,163,18, &cu->ext2, 0.0, 2.0, 1, 0, "");
+ uiBlockSetCol(block, BUTBLUE);
+ if(ob->type==OB_FONT) {
+ uiDefButS(block, TOG|BIT|1, B_MAKEDISP, "Front", 833,130,79,18, &cu->flag, 0, 0, 0, 0, "");
+ uiDefButS(block, TOG|BIT|2, B_MAKEDISP, "Back", 753,130,76,18, &cu->flag, 0, 0, 0, 0, "");
+ }
+ else {
+ uiDefButS(block, TOG|BIT|0, B_CU3D, "3D", 867,130,47,18, &cu->flag, 0, 0, 0, 0, "");
+ uiDefButS(block, TOG|BIT|1, B_MAKEDISP, "Front", 810,130,55,18, &cu->flag, 0, 0, 0, 0, "");
+ uiDefButS(block, TOG|BIT|2, B_MAKEDISP, "Back", 753,130,53,18, &cu->flag, 0, 0, 0, 0, "");
+ }
+ uiBlockSetCol(block, BUTGREY);
+ }
+
+ uiDefButF(block, NUM, REDRAWVIEW3D, "NSize:", 1090, 80, 164, 19, &editbutsize, 0.001, 1.0, 10, 0, "");
+
+ uiDrawBlock(block);
+}
+
+
+/* *************************** CAMERA ******************************** */
+
+
+void camerabuts(void)
+{
+ Camera *cam;
+ Object *ob;
+ uiBlock *block;
+ float grid=0.0;
+ char str[64];
+
+ if(G.vd) grid= G.vd->grid;
+ if(grid<1.0) grid= 1.0;
+
+ ob= OBACT;
+ if(ob==0) return;
+
+ sprintf(str, "editbuttonswin %d", curarea->win);
+ block= uiNewBlock(&curarea->uiblocks, str, UI_EMBOSSX, UI_HELV, curarea->win);
+
+ cam= ob->data;
+ uiDefButF(block, NUM,REDRAWVIEW3D, "Lens:", 470,178,160,20, &cam->lens, 1.0, 250.0, 100, 0, "Specify the lens of the camera");
+ uiDefButF(block, NUM,REDRAWVIEW3D, "ClipSta:", 470,147,160,20, &cam->clipsta, 0.001*grid, 100.0*grid, 10, 0, "Specify the startvalue of the the field of view");
+ uiDefButF(block, NUM,REDRAWVIEW3D, "ClipEnd:", 470,125,160,20, &cam->clipend, 1.0, 5000.0*grid, 100, 0, "Specify the endvalue of the the field of view");
+ uiDefButF(block, NUM,REDRAWVIEW3D, "DrawSize:", 470,90,160,20, &cam->drawsize, 0.1*grid, 10.0, 10, 0, "Specify the drawsize of the camera");
+
+ uiBlockSetCol(block, BUTGREEN);
+ uiDefButS(block, TOG, REDRAWVIEW3D, "Ortho", 470,49,61,40, &cam->type, 0, 0, 0, 0, "Render orthogonally");
+
+ uiDefButS(block, TOG|BIT|0,REDRAWVIEW3D, "ShowLimits", 533,69,97,20, &cam->flag, 0, 0, 0, 0, "Draw the field of view");
+ uiDefButS(block, TOG|BIT|1,REDRAWVIEW3D, "Show Mist", 533,49,97,20, &cam->flag, 0, 0, 0, 0, "Draw a line that indicates the mist area");
+
+ if(G.special1 & G_HOLO) {
+ uiBlockSetCol(block, BUTGREY);
+ if(cam->netend==0.0) cam->netend= EFRA;
+ uiDefButF(block, NUM, REDRAWVIEW3D, "Anim len", 670,80,100,20, &cam->netend, 1.0, 2500.0, 0, 0, "");
+ uiDefButF(block, NUM, REDRAWVIEW3D, "Path len:", 670,160,100,20, &cam->hololen, 0.1, 25.0, 10, 0, "");
+ uiDefButF(block, NUM, REDRAWVIEW3D, "Shear fac:", 670,140,100,20, &cam->hololen1, 0.1, 5.0, 10, 0, "");
+ uiBlockSetCol(block, BUTGREEN);
+ uiDefButS(block, TOG|BIT|4, REDRAWVIEW3D, "Holo 1", 670,120,100,20, &cam->flag, 0.0, 0.0, 0, 0, "");
+ uiDefButS(block, TOG|BIT|5, REDRAWVIEW3D, "Holo 2", 670,100,100,20, &cam->flag, 0.0, 0.0, 0, 0, "");
+
+ }
+ uiDrawBlock(block);
+}
+
+/* *************************** FACE/PAINT *************************** */
+
+void do_fpaintbuts(unsigned short event)
+{
+ Mesh *me;
+ Object *ob;
+ extern TFace *lasttface; /* caches info on tface bookkeeping ?*/
+
+ ob= OBACT;
+ if(ob==0) return;
+
+ switch(event) {
+
+ case B_VPGAMMA:
+ vpaint_dogamma();
+ break;
+ case B_COPY_TF_MODE:
+ case B_COPY_TF_UV:
+ case B_COPY_TF_COL:
+ case B_COPY_TF_TEX:
+ me= get_mesh(ob);
+ if(me && me->tface) {
+/* extern TFace *lasttface; */
+ TFace *tface= me->tface;
+ int a= me->totface;
+
+ set_lasttface();
+ if(lasttface) {
+
+ while(a--) {
+ if(tface!=lasttface && (tface->flag & TF_SELECT)) {
+ if(event==B_COPY_TF_MODE) {
+ tface->mode= lasttface->mode;
+ tface->transp= lasttface->transp;
+ }
+ else if(event==B_COPY_TF_UV) {
+ memcpy(tface->uv, lasttface->uv, sizeof(tface->uv));
+ tface->tpage= lasttface->tpage;
+ tface->tile= lasttface->tile;
+
+ if(lasttface->mode & TF_TILES) tface->mode |= TF_TILES;
+ else tface->mode &= ~TF_TILES;
+
+ }
+ else if(event==B_COPY_TF_TEX) {
+ tface->tpage= lasttface->tpage;
+ tface->tile= lasttface->tile;
+
+ if(lasttface->mode & TF_TILES) tface->mode |= TF_TILES;
+ else tface->mode &= ~TF_TILES;
+ }
+ else if(event==B_COPY_TF_COL) memcpy(tface->col, lasttface->col, sizeof(tface->col));
+ }
+ tface++;
+ }
+ }
+ do_shared_vertexcol(me);
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWIMAGE, 0);
+ }
+ break;
+ case B_SET_VCOL:
+ clear_vpaint_selectedfaces();
+ break;
+ case B_REDR_3D_IMA:
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWIMAGE, 0);
+ break;
+ case B_ASSIGNMESH:
+
+ test_object_materials(ob->data);
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWBUTSGAME, 0);
+ break;
+
+ case B_TFACE_HALO:
+ set_lasttface();
+ if(lasttface) {
+ lasttface->mode &= ~TF_BILLBOARD2;
+ allqueue(REDRAWBUTSGAME, 0);
+ }
+ break;
+
+ case B_TFACE_BILLB:
+ set_lasttface();
+ if(lasttface) {
+ lasttface->mode &= ~TF_BILLBOARD;
+ allqueue(REDRAWBUTSGAME, 0);
+ }
+ break;
+ }
+}
+
+void fpaintbuts(void)
+{
+/* extern VPaint Gvp; already in the top of the file */
+ Object *ob;
+ uiBlock *block;
+ char str[32];
+
+ ob= OBACT;
+ if(ob==0) return;
+
+ sprintf(str, "buttonswin %d", curarea->win);
+ block= uiNewBlock(&curarea->uiblocks, str, UI_EMBOSSX, UI_HELV, curarea->win);
+
+ /* VPAINT BUTTONS */
+ uiBlockSetCol(block, BUTGREY);
+
+ if (G.f & G_VERTEXPAINT) {
+ uiDefBut(block, LABEL, 0, "Vertex Paint", 1037,180,194,18, 0, 0, 0, 0, 0, "");
+ } else if (G.f & G_TEXTUREPAINT) {
+ uiDefBut(block, LABEL, 0, "Texture Paint", 1037,180,194,18, 0, 0, 0, 0, 0, "");
+ }
+
+ uiDefButF(block, NUMSLI, 0, "R ", 979,160,194,19, &Gvp.r, 0.0, 1.0, B_VPCOLSLI, 0, "The amount of red used for painting");
+ uiDefButF(block, NUMSLI, 0, "G ", 979,140,194,19, &Gvp.g, 0.0, 1.0, B_VPCOLSLI, 0, "The amount of green used for painting");
+ uiDefButF(block, NUMSLI, 0, "B ", 979,120,194,19, &Gvp.b, 0.0, 1.0, B_VPCOLSLI, 0, "The amount of blue used for painting");
+ uiDefButF(block, NUMSLI, 0, "Opacity ", 979,100,194,19, &Gvp.a, 0.0, 1.0, 0, 0, "The amount of pressure on the brush");
+ uiDefButF(block, NUMSLI, 0, "Size ", 979,80,194,19, &Gvp.size, 2.0, 64.0, 0, 0, "The size of the brush");
+
+ uiDefButF(block, COL, B_VPCOLSLI, "", 1176,100,28,80, &(Gvp.r), 0, 0, 0, 0, "");
+
+ uiDefButS(block, ROW, B_DIFF, "Mix", 1212,160,63,19, &Gvp.mode, 1.0, 0.0, 0, 0, "Mix the vertex colours");
+ uiDefButS(block, ROW, B_DIFF, "Add", 1212,140,63,19, &Gvp.mode, 1.0, 1.0, 0, 0, "Add the vertex colour");
+ uiDefButS(block, ROW, B_DIFF, "Sub", 1212, 120,63,19, &Gvp.mode, 1.0, 2.0, 0, 0, "Subtract from the vertex colour");
+ uiDefButS(block, ROW, B_DIFF, "Mul", 1212, 100,63,19, &Gvp.mode, 1.0, 3.0, 0, 0, "Multiply the vertex colour");
+ uiDefButS(block, ROW, B_DIFF, "Filter", 1212, 80,63,19, &Gvp.mode, 1.0, 4.0, 0, 0, "Mix the colours with an alpha factor");
+
+ uiBlockSetCol(block, BUTGREEN);
+ uiDefButS(block, TOG|BIT|1, 0, "Area", 980,50,80,19, &Gvp.flag, 0, 0, 0, 0, "Set the area the brush covers");
+ uiDefButS(block, TOG|BIT|2, 0, "Soft", 1061,50,112,19, &Gvp.flag, 0, 0, 0, 0, "Use a soft brush");
+ uiDefButS(block, TOG|BIT|3, 0, "Normals", 1174,50,102,19, &Gvp.flag, 0, 0, 0, 0, "Use vertex normal for painting");
+
+ uiBlockSetCol(block, BUTSALMON);
+ uiDefBut(block, BUT, B_VPGAMMA, "Set", 980,30,80,19, 0, 0, 0, 0, 0, "Apply Mul and Gamma to vertex colours");
+ uiBlockSetCol(block, BUTGREY);
+ uiDefButF(block, NUM, B_DIFF, "Mul:", 1061,30,112,19, &Gvp.mul, 0.1, 50.0, 10, 0, "Set the number to multiply vertex colours with");
+ uiDefButF(block, NUM, B_DIFF, "Gamma:", 1174,30,102,19, &Gvp.gamma, 0.1, 5.0, 10, 0, "Change the clarity of the vertex colours");
+
+ uiDefBut(block, LABEL, 0, "Face Select", 600,180,194,18, 0, 0, 0, 0, 0, "");
+ if(G.f & G_FACESELECT) {
+ extern TFace *lasttface;
+
+ set_lasttface();
+ if(lasttface) {
+
+ uiBlockSetCol(block, BUTGREEN);
+ uiDefButS(block, TOG|BIT|2, B_REDR_3D_IMA, "Tex", 600,160,60,19, &lasttface->mode, 0, 0, 0, 0, "Render face with texture");
+ uiDefButS(block, TOG|BIT|7, B_REDR_3D_IMA, "Tiles", 660,160,60,19, &lasttface->mode, 0, 0, 0, 0, "Use tilemode for face");
+ uiDefButS(block, TOG|BIT|4, REDRAWVIEW3D, "Light", 720,160,60,19, &lasttface->mode, 0, 0, 0, 0, "Use light for face");
+ uiDefButS(block, TOG|BIT|10, REDRAWVIEW3D, "Invisible",780,160,60,19, &lasttface->mode, 0, 0, 0, 0, "Make face invisible");
+ uiDefButS(block, TOG|BIT|0, REDRAWVIEW3D, "Collision", 840,160,60,19, &lasttface->mode, 0, 0, 0, 0, "Use face for collision detection");
+
+ uiDefButS(block, TOG|BIT|6, REDRAWVIEW3D, "Shared", 600,140,60,19, &lasttface->mode, 0, 0, 0, 0, "Blend vertex colours across face when vertices are shared");
+ uiDefButS(block, TOG|BIT|9, REDRAWVIEW3D, "Twoside", 660,140,60,19, &lasttface->mode, 0, 0, 0, 0, "Render face twosided");
+ uiDefButS(block, TOG|BIT|11, REDRAWVIEW3D, "ObColor",720,140,60,19, &lasttface->mode, 0, 0, 0, 0, "Use ObColor instead of vertex colours");
+
+ uiDefButS(block, TOG|BIT|8, B_TFACE_HALO, "Halo", 600,120,60,19, &lasttface->mode, 0, 0, 0, 0, "Screen aligned billboard");
+ uiDefButS(block, TOG|BIT|12, B_TFACE_BILLB, "Billboard",660,120,60,19, &lasttface->mode, 0, 0, 0, 0, "Billboard with Z-axis constraint");
+ uiDefButS(block, TOG|BIT|13, REDRAWVIEW3D, "Shadow", 720,120,60,19, &lasttface->mode, 0, 0, 0, 0, "Face is used for shadow");
+ uiDefButS(block, TOG|BIT|14, REDRAWVIEW3D, "Text", 780,120,60,19, &lasttface->mode, 0, 0, 0, 0, "Enable bitmap text on face");
+
+ uiBlockSetCol(block, BUTPURPLE);
+ uiDefButC(block, ROW, REDRAWVIEW3D, "Opaque", 600,100,60,19, &lasttface->transp, 2.0, 0.0, 0, 0, "Render colour of textured face as colour");
+ uiDefButC(block, ROW, REDRAWVIEW3D, "Add", 660,100,60,19, &lasttface->transp, 2.0, 1.0, 0, 0, "Render face transparent and add colour of face");
+ uiDefButC(block, ROW, REDRAWVIEW3D, "Alpha", 720,100,60,19, &lasttface->transp, 2.0, 2.0, 0, 0, "Render polygon transparent, depending on alpha channel of the texture");
+ /* uiDefButC(block, ROW, REDRAWVIEW3D, "Sub", 780,100,60,19, &lasttface->transp, 2.0, 3.0, 0, 0); ,""*/
+
+ }
+ }
+ uiBlockSetCol(block, BUTSALMON);
+ if(G.f & G_FACESELECT) {
+ uiDefBut(block, BUT, B_SET_VCOL, "Set VertCol", 859,37,103,28, 0, 0, 0, 0, 0, "Set Vertex colour of selection to current (Shift+K)");
+
+ }
+ uiDefBut(block, BUT, B_COPY_TF_MODE, "Copy DrawMode", 650,7,117,28, 0, 0, 0, 0, 0, "Copy the drawmode");
+ uiDefBut(block, BUT, B_COPY_TF_UV, "Copy UV+tex", 771,7,85,28, 0, 0, 0, 0, 0, "Copy UV information and textures");
+ uiDefBut(block, BUT, B_COPY_TF_COL, "Copy VertCol", 859,7,103,28, 0, 0, 0, 0, 0, "Copy vertex colours");
+
+ uiDrawBlock(block);
+}
+
+/* *************************** RADIO ******************************** */
+
+void do_radiobuts(short event)
+{
+ Radio *rad;
+ int phase;
+
+ phase= rad_phase();
+ rad= G.scene->radio;
+
+ switch(event) {
+ case B_RAD_ADD:
+ add_radio();
+ allqueue(REDRAWBUTSRADIO, 0);
+ allqueue(REDRAWVIEW3D, 0);
+ break;
+ case B_RAD_DELETE:
+ delete_radio();
+ allqueue(REDRAWBUTSRADIO, 0);
+ allqueue(REDRAWVIEW3D, 0);
+ break;
+ case B_RAD_FREE:
+ freeAllRad();
+ allqueue(REDRAWBUTSRADIO, 0);
+ allqueue(REDRAWVIEW3D, 0);
+ break;
+ case B_RAD_COLLECT:
+ rad_collect_meshes();
+ allqueue(REDRAWBUTSRADIO, 0);
+ allqueue(REDRAWVIEW3D, 0);
+ break;
+ case B_RAD_INIT:
+ if(phase==RAD_PHASE_PATCHES) {
+ rad_limit_subdivide();
+ allqueue(REDRAWBUTSRADIO, 0);
+ allqueue(REDRAWVIEW3D, 0);
+ }
+ break;
+ case B_RAD_SHOOTP:
+ if(phase==RAD_PHASE_PATCHES) {
+ waitcursor(1);
+ rad_subdivshootpatch();
+ allqueue(REDRAWBUTSRADIO, 0);
+ allqueue(REDRAWVIEW3D, 0);
+ waitcursor(0);
+ }
+ break;
+ case B_RAD_SHOOTE:
+ if(phase==RAD_PHASE_PATCHES) {
+ waitcursor(1);
+ rad_subdivshootelem();
+ allqueue(REDRAWBUTSRADIO, 0);
+ allqueue(REDRAWVIEW3D, 0);
+ waitcursor(0);
+ }
+ break;
+ case B_RAD_GO:
+ if(phase==RAD_PHASE_PATCHES) {
+ waitcursor(1);
+ rad_go();
+ waitcursor(0);
+ allqueue(REDRAWBUTSRADIO, 0);
+ allqueue(REDRAWVIEW3D, 0);
+ }
+ break;
+ case B_RAD_LIMITS:
+ rad_setlimits();
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWBUTSRADIO, 0);
+ break;
+ case B_RAD_FAC:
+ set_radglobal();
+ if(phase & RAD_PHASE_FACES) make_face_tab();
+ else make_node_display();
+ allqueue(REDRAWVIEW3D, 0);
+ break;
+ case B_RAD_NODELIM:
+ if(phase & RAD_PHASE_FACES) {
+ set_radglobal();
+ removeEqualNodes(rad->nodelim);
+ make_face_tab();
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWBUTSRADIO, 0);
+ }
+ break;
+ case B_RAD_NODEFILT:
+ if(phase & RAD_PHASE_FACES) {
+ set_radglobal();
+ filterNodes();
+ make_face_tab();
+ allqueue(REDRAWVIEW3D, 0);
+ }
+ break;
+ case B_RAD_FACEFILT:
+ if(phase & RAD_PHASE_FACES) {
+ filterFaces();
+ allqueue(REDRAWVIEW3D, 0);
+ }
+ break;
+ case B_RAD_DRAW:
+ set_radglobal();
+ allqueue(REDRAWVIEW3D, 0);
+ break;
+ case B_RAD_ADDMESH:
+ if(phase & RAD_PHASE_FACES) rad_addmesh();
+ allqueue(REDRAWVIEW3D, 0);
+ break;
+ case B_RAD_REPLACE:
+ if(phase & RAD_PHASE_FACES) rad_replacemesh();
+ allqueue(REDRAWVIEW3D, 0);
+ break;
+ }
+
+}
+
+
+void radiobuts(void)
+{
+ Radio *rad;
+ uiBlock *block;
+ int flag;
+ char str[128];
+
+ rad= G.scene->radio;
+ if(rad==0) {
+ add_radio();
+ rad= G.scene->radio;
+ }
+
+ flag= rad_phase();
+
+ sprintf(str, "buttonswin %d", curarea->win);
+ block= uiNewBlock(&curarea->uiblocks, str, UI_EMBOSSX, UI_HELV, curarea->win);
+ uiAutoBlock(block, 10, 30, 190, 100, UI_BLOCK_ROWS);
+
+ if(flag == RAD_PHASE_PATCHES) uiBlockSetCol(block, BUTSALMON);
+ else uiBlockSetCol(block, BUTGREY);
+ uiDefBut(block, BUT, B_RAD_INIT, "Limit Subdivide", 0, 0, 10, 10, NULL, 0, 0, 0, 0, "Subdivide patches");
+ if(flag & RAD_PHASE_PATCHES) uiBlockSetCol(block, BUTPURPLE);
+ else uiBlockSetCol(block, BUTSALMON);
+ uiDefBut(block, BUT, B_RAD_COLLECT, "Collect Meshes", 1, 0, 10, 10, NULL, 0, 0, 0, 0, "Convert selected and visible meshes to patches");
+ uiDrawBlock(block);
+
+ sprintf(str, "buttonswin1 %d", curarea->win);
+ block= uiNewBlock(&curarea->uiblocks, str, UI_EMBOSSX, UI_HELV, curarea->win);
+ uiAutoBlock(block, 210, 30, 230, 150, UI_BLOCK_ROWS);
+
+ uiBlockSetCol(block, BUTGREEN);
+ uiDefButS(block, ROW, B_RAD_DRAW, "Wire", 0, 0, 10, 10, &rad->drawtype, 0.0, 0.0, 0, 0, "Enable wireframe drawmode");
+ uiDefButS(block, ROW, B_RAD_DRAW, "Solid", 0, 0, 10, 10, &rad->drawtype, 0.0, 1.0, 0, 0, "Enable solid drawmode");
+ uiDefButS(block, ROW, B_RAD_DRAW, "Gour", 0, 0, 10, 10, &rad->drawtype, 0.0, 2.0, 0, 0, "Enable Gourad drawmode");
+ uiBlockSetCol(block, BUTGREY);
+ uiDefButS(block, TOG|BIT|0, B_RAD_DRAW, "ShowLim", 1, 0, 10, 10, &rad->flag, 0, 0, 0, 0, "Visualize patch and element limits");
+ uiDefButS(block, TOG|BIT|1, B_RAD_DRAW, "Z", 1, 0, 3, 10, &rad->flag, 0, 0, 0, 0, "Draw limits different");
+ uiBlockSetCol(block, BUTGREY);
+ uiDefButS(block, NUM, B_RAD_LIMITS, "ElMax:", 2, 0, 10, 10, &rad->elma, 1.0, 500.0, 0, 0, "Set maximum size of an element");
+ uiDefButS(block, NUM, B_RAD_LIMITS, "ElMin:", 2, 0, 10, 10, &rad->elmi, 1.0, 100.0, 0, 0, "Set minimum size of an element");
+ uiDefButS(block, NUM, B_RAD_LIMITS, "PaMax:", 3, 0, 10, 10, &rad->pama, 10.0, 1000.0, 0, 0, "Set maximum size of a patch");
+ uiDefButS(block, NUM, B_RAD_LIMITS, "PaMin:", 3, 0, 10, 10, &rad->pami, 10.0, 1000.0, 0, 0, "Set minimum size of a patch");
+ uiDrawBlock(block);
+
+ sprintf(str, "buttonswin2 %d", curarea->win);
+ block= uiNewBlock(&curarea->uiblocks, str, UI_EMBOSSX, UI_HELV, curarea->win);
+ uiAutoBlock(block, 450, 30, 180, 150, UI_BLOCK_ROWS);
+
+ if(flag == RAD_PHASE_PATCHES) uiBlockSetCol(block, BUTSALMON);
+ else uiBlockSetCol(block, BUTGREY);
+ uiDefBut(block, BUT, B_RAD_SHOOTE, "Subdiv Shoot Element", 0, 0, 12, 10, NULL, 0, 0, 0, 0, "");
+ uiDefBut(block, BUT, B_RAD_SHOOTP, "Subdiv Shoot Patch", 1, 0, 12, 10, NULL, 0, 0, 0, 0, "Detect high energy changes");
+ uiBlockSetCol(block, BUTGREY);
+ uiDefButS(block, NUM, 0, "Max Subdiv Shoot:", 2, 0, 10, 10, &rad->maxsublamp, 1.0, 250.0, 0, 0, "Set the maximum number of shoot patches that are evaluated");
+ uiDefButI(block, NUM, 0, "MaxEl:", 3, 0, 10, 10, &rad->maxnode, 1.0, 250000.0, 0, 0, "Set the maximum allowed number of elements");
+ uiDefButS(block, NUM, B_RAD_LIMITS, "Hemires:", 4, 0, 10, 10, &rad->hemires, 100.0, 1000.0, 100, 0, "Set the size of a hemicube");
+ uiDrawBlock(block);
+
+ sprintf(str, "buttonswin3 %d", curarea->win);
+ block= uiNewBlock(&curarea->uiblocks, str, UI_EMBOSSX, UI_HELV, curarea->win);
+ uiAutoBlock(block, 640, 30, 200, 150, UI_BLOCK_ROWS);
+
+ uiBlockSetCol(block, BUTGREY);
+ uiDefButS(block, NUM, 0, "Max Iterations:", 0, 0, 10, 10, &rad->maxiter, 0.0, 10000.0, 0, 0, "Maximum number of radiosity rounds");
+ uiDefButF(block, NUM, 0, "Convergence:", 1, 0, 10, 10, &rad->convergence, 0.0, 1.0, 10, 0, "Set the lower threshold of unshot energy");
+ uiDefButS(block, NUM, 0, "SubSh P:", 2, 0, 10, 10, &rad->subshootp, 0.0, 10.0, 0, 0, "Set the number of times the environment is tested to detect pathes");
+ uiDefButS(block, NUM, 0, "SubSh E:", 2, 0, 10, 10, &rad->subshoote, 0.0, 10.0, 0, 0, "Set the number of times the environment is tested to detect elements");
+ if(flag == RAD_PHASE_PATCHES) uiBlockSetCol(block, BUTSALMON);
+ uiDefBut(block, BUT, B_RAD_GO, "GO", 3, 0, 10, 15, NULL, 0, 0, 0, 0, "Start the radiosity simulation");
+ uiDrawBlock(block);
+
+ sprintf(str, "buttonswin4 %d", curarea->win);
+ block= uiNewBlock(&curarea->uiblocks, str, UI_EMBOSSX, UI_HELV, curarea->win);
+ uiAutoBlock(block, 850, 30, 200, 150, UI_BLOCK_ROWS);
+
+ uiBlockSetCol(block, BUTGREY);
+ uiDefButF(block, NUM, B_RAD_FAC, "Mult:", 0, 0, 50, 17, &rad->radfac, 0.001, 250.0, 100, 0, "Mulitply the energy values");
+ uiDefButF(block, NUM, B_RAD_FAC, "Gamma:", 0, 0, 50, 17, &rad->gamma, 0.2, 10.0, 10, 0, "Change the contrast of the energy values");
+ if(flag & RAD_PHASE_FACES) uiBlockSetCol(block, BUTSALMON);
+ else uiBlockSetCol(block, BUTGREY);
+ uiDefBut(block, BUT, B_RAD_FACEFILT, "FaceFilter", 1, 0, 10, 10, NULL, 0, 0, 0, 0, "Force an extra smoothing");
+ if(flag & RAD_PHASE_FACES) uiBlockSetCol(block, BUTSALMON);
+ else uiBlockSetCol(block, BUTGREY);
+ uiDefBut(block, BUT, B_RAD_NODELIM, "RemoveDoubles", 2, 0, 30, 10, NULL, 0.0, 50.0, 0, 0, "Join elements which differ less than 'Lim'");
+ uiBlockSetCol(block, BUTGREY);
+ uiDefButS(block, NUM, 0, "Lim:", 2, 0, 10, 10, &rad->nodelim, 0.0, 50.0, 0, 0, "Set the range for removing doubles");
+ if(flag & RAD_PHASE_FACES) uiBlockSetCol(block, BUTSALMON);
+ else uiBlockSetCol(block, BUTGREY);
+ uiDefBut(block, BUT, B_RAD_NODEFILT, "Element Filter", 3, 0, 10, 10, NULL, 0, 0, 0, 0, "Filter elements to remove aliasing artefacts");
+ uiDrawBlock(block);
+
+ sprintf(str, "buttonswin5 %d", curarea->win);
+ block= uiNewBlock(&curarea->uiblocks, str, UI_EMBOSSX, UI_HELV, curarea->win);
+ uiAutoBlock(block, 1060, 30, 190, 150, UI_BLOCK_ROWS);
+
+ if(flag & RAD_PHASE_PATCHES) uiBlockSetCol(block, BUTSALMON);
+ else uiBlockSetCol(block, BUTGREY);
+ uiDefBut(block, BUT, B_RAD_FREE, "Free Radio Data", 0, 0, 10, 10, NULL, 0, 0, 0, 0, "Release all memory used by Radiosity");
+ if(flag & RAD_PHASE_FACES) uiBlockSetCol(block, BUTSALMON);
+ else uiBlockSetCol(block, BUTGREY);
+ uiDefBut(block, BUT, B_RAD_REPLACE, "Replace Meshes", 1, 0, 10, 10, NULL, 0, 0, 0, 0, "Convert meshes to Mesh objects with vertex colours, changing input-meshes");
+ uiDefBut(block, BUT, B_RAD_ADDMESH, "Add new Meshes", 2, 0, 10, 10, NULL, 0, 0, 0, 0, "Convert meshes to Mesh objects with vertex colours, unchanging input-meshes");
+ uiDrawBlock(block);
+
+ rad_status_str(str);
+ cpack(0);
+ glRasterPos2i(210, 189);
+ BMF_DrawString(uiBlockGetCurFont(block), str);
+}
+
+
+/* *************************** MBALL ******************************** */
+
+void do_mballbuts(unsigned short event)
+{
+ switch(event) {
+ case B_RECALCMBALL:
+ makeDispList(OBACT);
+ allqueue(REDRAWVIEW3D, 0);
+ break;
+ }
+}
+
+void mballbuts(void)
+{
+ extern MetaElem *lastelem;
+ MetaBall *mb;
+ Object *ob;
+ uiBlock *block;
+ char str[64];
+
+ ob= OBACT;
+ if(ob==0) return;
+
+ sprintf(str, "editbuttonswin %d", curarea->win);
+ block= uiNewBlock(&curarea->uiblocks, str, UI_EMBOSSX, UI_HELV, curarea->win);
+
+ mb= ob->data;
+ if (ob==find_basis_mball(ob)) {
+ uiDefButF(block, NUMSLI, B_RECALCMBALL, "Wiresize:", 470,178,250,19, &mb->wiresize, 0.05, 1.0, 0, 0, "");
+ uiDefButF(block, NUMSLI, 0, "Rendersize:", 470,158,250,19, &mb->rendersize, 0.05, 1.0, 0, 0, "");
+ uiDefButF(block, NUMSLI, B_RECALCMBALL, "Threshold:", 470,138,250,19, &mb->thresh, 0.0001, 5.0, 0, 0, "");
+
+ uiBlockSetCol(block, BUTBLUE);
+ uiDefBut(block, LABEL, 0, "Update:", 471,108,120,19, 0, 0, 0, 0, 0, "");
+ uiDefButS(block, ROW, B_DIFF, "Always", 471, 85, 120, 19, &mb->flag, 0.0, 0.0, 0, 0, "");
+ uiDefButS(block, ROW, B_DIFF, "Half Res", 471, 65, 120, 19, &mb->flag, 0.0, 1.0, 0, 0, "");
+ uiDefButS(block, ROW, B_DIFF, "Fast", 471, 45, 120, 19, &mb->flag, 0.0, 2.0, 0, 0, "");
+ uiBlockSetCol(block, BUTGREY);
+ }
+
+ if(ob==G.obedit && lastelem) {
+ uiDefButF(block, NUMSLI, B_RECALCMBALL, "Stiffness:", 750,178,250,19, &lastelem->s, 0.0, 10.0, 0, 0, "");
+ uiDefButF(block, NUMSLI, B_RECALCMBALL, "Len:", 750,158,250,19, &lastelem->len, 0.0, 20.0, 0, 0, "");
+
+ uiBlockSetCol(block, BUTGREEN);
+ uiDefButS(block, TOG|BIT|1, B_RECALCMBALL, "Negative",752,116,60,19, &lastelem->flag, 0, 0, 0, 0, "");
+
+ uiDefButS(block, ROW, B_RECALCMBALL, "Ball", 753,83,60,19, &lastelem->type, 1.0, 0.0, 0, 0, "");
+ uiDefButS(block, ROW, B_RECALCMBALL, "TubeX", 753,62,60,19, &lastelem->type, 1.0, 1.0, 0, 0, "");
+ uiDefButS(block, ROW, B_RECALCMBALL, "TubeY", 814,62,60,19, &lastelem->type, 1.0, 2.0, 0, 0, "");
+ uiDefButS(block, ROW, B_RECALCMBALL, "TubeZ", 876,62,60,19, &lastelem->type, 1.0, 3.0, 0, 0, "");
+
+ }
+ uiDrawBlock(block);
+}
+
+/* *************************** SCRIPT ******************************** */
+
+static void extend_scriptlink(ScriptLink *slink)
+{
+ void *stmp, *ftmp;
+
+ if (!slink) return;
+
+ stmp= slink->scripts;
+ slink->scripts= MEM_mallocN(sizeof(ID*)*(slink->totscript+1), "scriptlistL");
+
+ ftmp= slink->flag;
+ slink->flag= MEM_mallocN(sizeof(short*)*(slink->totscript+1), "scriptlistF");
+
+ if (slink->totscript) {
+ memcpy(slink->scripts, stmp, sizeof(ID*)*(slink->totscript));
+ MEM_freeN(stmp);
+
+ memcpy(slink->flag, ftmp, sizeof(short)*(slink->totscript));
+ MEM_freeN(ftmp);
+ }
+
+ slink->scripts[slink->totscript]= NULL;
+ slink->flag[slink->totscript]= SCRIPT_FRAMECHANGED;
+
+ slink->totscript++;
+
+ if(slink->actscript<1) slink->actscript=1;
+}
+
+static void delete_scriptlink(ScriptLink *slink)
+{
+ int i;
+
+ if (!slink) return;
+
+ if (slink->totscript>0) {
+ for (i=slink->actscript-1; i<slink->totscript-1; i++) {
+ slink->flag[i]= slink->flag[i+1];
+ slink->scripts[i]= slink->scripts[i+1];
+ }
+
+ slink->totscript--;
+ }
+
+ CLAMP(slink->actscript, 1, slink->totscript);
+
+ if (slink->totscript==0) {
+ if (slink->scripts) MEM_freeN(slink->scripts);
+ if (slink->flag) MEM_freeN(slink->flag);
+
+ slink->scripts= NULL;
+ slink->flag= NULL;
+ slink->totscript= slink->actscript= 0;
+ }
+}
+
+void do_scriptbuts(short event)
+{
+ Object *ob=NULL;
+ ScriptLink *script=NULL;
+ Material *ma;
+
+ switch (event) {
+ case B_SSCRIPT_ADD:
+ extend_scriptlink(&G.scene->scriptlink);
+ break;
+ case B_SSCRIPT_DEL:
+ delete_scriptlink(&G.scene->scriptlink);
+ break;
+
+ case B_SCRIPT_ADD:
+ case B_SCRIPT_DEL:
+ ob= OBACT;
+
+ if (ob && G.buts->scriptblock==ID_OB) {
+ script= &ob->scriptlink;
+
+ } else if (ob && G.buts->scriptblock==ID_MA) {
+ ma= give_current_material(ob, ob->actcol);
+ if (ma) script= &ma->scriptlink;
+
+ } else if (ob && G.buts->scriptblock==ID_CA) {
+ if (ob->type==OB_CAMERA)
+ script= &((Camera *)ob->data)->scriptlink;
+
+ } else if (ob && G.buts->scriptblock==ID_LA) {
+ if (ob->type==OB_LAMP)
+ script= &((Lamp *)ob->data)->scriptlink;
+
+ } else if (G.buts->scriptblock==ID_WO) {
+ if (G.scene->world)
+ script= &(G.scene->world->scriptlink);
+ }
+
+ if (event==B_SCRIPT_ADD) extend_scriptlink(script);
+ else delete_scriptlink(script);
+
+ break;
+ default:
+ break;
+ }
+
+ allqueue(REDRAWBUTSSCRIPT, 0);
+}
+
+void draw_scriptlink(uiBlock *block, ScriptLink *script, int sx, int sy, int scene)
+{
+ char str[256];
+
+ uiBlockSetCol(block, BUTGREY);
+
+ if (script->totscript) {
+ strcpy(str, "FrameChanged%x 1|");
+ strcat(str, "Redraw%x 4|");
+ if (scene) {
+ strcat(str, "OnLoad%x 2");
+ }
+
+ uiDefButS(block, MENU, 1, str, (short)sx, (short)sy, 148, 19, &script->flag[script->actscript-1], 0, 0, 0, 0, "Script links for the Frame changed event");
+
+ uiDefIDPoinBut(block, test_scriptpoin_but, 1, "", (short)(sx+150),(short)sy, 98, 19, &script->scripts[script->actscript-1], "Name of Script to link");
+ }
+
+ sprintf(str,"%d Scr:", script->totscript);
+ uiDefButS(block, NUM, REDRAWBUTSSCRIPT, str, (short)(sx+250), (short)sy,98,19, &script->actscript, 1, script->totscript, 0, 0, "Total / Active Script link (LeftMouse + Drag to change)");
+
+ uiBlockSetCol(block, BUTSALMON);
+
+ if (scene) {
+ if (script->totscript<32767)
+ uiDefBut(block, BUT, B_SSCRIPT_ADD, "New", (short)(sx+350), (short)sy, 38, 19, 0, 0, 0, 0, 0, "Add a new Script link");
+ if (script->totscript)
+ uiDefBut(block, BUT, B_SSCRIPT_DEL, "Del", (short)(sx+390), (short)sy, 38, 19, 0, 0, 0, 0, 0, "Delete the current Script link");
+ } else {
+ if (script->totscript<32767)
+ uiDefBut(block, BUT, B_SCRIPT_ADD, "New", (short)(sx+350), (short)sy, 38, 19, 0, 0, 0, 0, 0, "Add a new Script link");
+ if (script->totscript)
+ uiDefBut(block, BUT, B_SCRIPT_DEL, "Del", (short)(sx+390), (short)sy, 38, 19, 0, 0, 0, 0, 0, "Delete the current Script link");
+ }
+}
+
+void scriptbuts(void)
+{
+ Object *ob=NULL;
+ ScriptLink *script=NULL;
+ Material *ma;
+ uiBlock *block;
+ char str[64];
+
+ ob= OBACT;
+
+ sprintf(str, "buttonswin %d", curarea->win);
+ block= uiNewBlock(&curarea->uiblocks, str, UI_EMBOSSX, UI_HELV, curarea->win);
+
+ if (ob && G.buts->scriptblock==ID_OB) {
+ script= &ob->scriptlink;
+
+ } else if (ob && G.buts->scriptblock==ID_MA) {
+ ma= give_current_material(ob, ob->actcol);
+ if (ma) script= &ma->scriptlink;
+
+ } else if (ob && G.buts->scriptblock==ID_CA) {
+ if (ob->type==OB_CAMERA)
+ script= &((Camera *)ob->data)->scriptlink;
+
+ } else if (ob && G.buts->scriptblock==ID_LA) {
+ if (ob->type==OB_LAMP)
+ script= &((Lamp *)ob->data)->scriptlink;
+
+ } else if (G.buts->scriptblock==ID_WO) {
+ if (G.scene->world)
+ script= &(G.scene->world->scriptlink);
+ }
+
+ if (script) draw_scriptlink(block, script, 25, 180, 0);
+
+ /* EVENTS */
+ draw_buttons_edge(curarea->win, 540);
+
+ draw_scriptlink(block, &G.scene->scriptlink, 600, 180, 1);
+
+ uiDrawBlock(block);
+}
+
+/* *************************** IKA ******************************** */
+/* is this number used elsewhere? */
+/* static int ika_del_number; */
+void do_ikabuts(unsigned short event)
+{
+ Base *base;
+ Object *ob;
+
+ ob= OBACT;
+
+ switch(event) {
+ case B_IKASETREF:
+ base= FIRSTBASE;
+ while(base) {
+ if TESTBASELIB(base) {
+ if(base->object->type==OB_IKA) init_defstate_ika(base->object);
+ }
+ base= base->next;
+ }
+ break;
+ case B_IKARECALC:
+ itterate_ika(ob);
+ break;
+ }
+}
+
+void ikabuts(void)
+{
+ Ika *ika;
+ Object *ob;
+ Limb *li;
+ Deform *def;
+ uiBlock *block;
+ int nr, cury, nlimbs;
+ char str[32];
+
+ ob= OBACT;
+ if(ob==0) return;
+
+ sprintf(str, "editbuttonswin %d", curarea->win);
+ block= uiNewBlock(&curarea->uiblocks, str, UI_EMBOSSX, UI_HELV, curarea->win);
+
+ ika= ob->data;
+
+ uiBlockSetCol(block, BUTSALMON);
+ uiDefBut(block, BUT, B_IKASETREF, "Set Reference",470,180,200,20, 0, 0, 0, 0, 0, "");
+
+ uiBlockSetCol(block, BUTGREEN);
+ uiDefButS(block, TOG|BIT|1, B_DIFF, "Lock XY Plane", 470,140,200,20, &ika->flag, 0.0, 1.0, 0, 0, "New IK option: allows both X and Y axes to rotate");
+ uiBlockSetCol(block, BUTGREY);
+ uiDefButF(block, NUM, B_DIFF, "XY constraint ", 470,120,200,20, &ika->xyconstraint, 0.0, 1.0, 100, 0, "Constrain in radians");
+
+ uiDefButF(block, NUMSLI, B_DIFF, "Mem ", 470,80,200,20, &ika->mem, 0.0, 1.0, 0, 0, "");
+ uiDefButS(block, NUM, B_DIFF, "Iter: ", 470,60,200,20, &ika->iter, 2.0, 16.0, 0, 0, "");
+
+
+ uiBlockSetCol(block, BUTGREY);
+
+ uiDefBut(block, LABEL, 0, "Limb Weight", 680, 200, 150, 19, 0, 0, 0, 0, 0, "");
+ cury= 180;
+ li= ika->limbbase.first;
+
+ nlimbs= BLI_countlist(&ika->limbbase);
+
+ for (nr = 0; nr < nlimbs; nr++) {
+ sprintf(str, "Limb %d:", nr);
+ uiDefButF(block, NUM, B_DIFF, str, 680, (short)cury, 150, 19, &li->fac, 0.01, 1.0, 10, 0, "");
+ cury-= 20;
+ li= li->next;
+ }
+
+
+
+ uiDefBut(block, LABEL, 0, "Deform Max Dist", 955, 200, 140, 19, 0, 0, 0, 0, 0, "");
+ uiDefBut(block, LABEL, 0, "Deform Weight", 1095, 200, 140, 19, 0, 0, 0, 0, 0, "");
+
+
+ cury= 180;
+ def= ika->def;
+ for (nr = 0; nr < ika->totdef; nr++) {
+ def = ika->def+nr;
+ if(def->ob) {
+ if(def->ob->type!=OB_IKA) sprintf(str, "%s :", def->ob->id.name+2);
+ else sprintf(str, "%s (%d):", def->ob->id.name+2, def->par1);
+ }
+
+ uiDefBut(block, LABEL, 0, str, 855, (short)cury, 100, 19, 0, 0.01, 0.0, 0, 0, "");
+ uiDefButF(block, NUM, B_DIFF, "", 955, (short)cury, 140, 19, &def->dist, 0.0, 40.0, 100, 0, "Beyond this distance the Limb doesn't influence deformation. '0.0' is global influence.");
+ uiDefButF(block, NUM, B_DIFF, "", 1095,(short)cury, 140, 19, &def->fac, 0.01, 10.0, 10, 0, "");
+
+ cury-= 20;
+ }
+ uiDrawBlock(block);
+}
+
+/* *************************** LATTICE ******************************** */
+
+void do_latticebuts(unsigned short event)
+{
+ Object *ob;
+ Lattice *lt;
+
+ ob= OBACT;
+
+ switch(event) {
+ case B_RESIZELAT:
+ if(ob) {
+ if(ob==G.obedit) resizelattice(editLatt);
+ else resizelattice(ob->data);
+ }
+ allqueue(REDRAWVIEW3D, 0);
+ break;
+ case B_DRAWLAT:
+ if(ob==G.obedit) calc_lattverts_ext();
+ allqueue(REDRAWVIEW3D, 0);
+ break;
+ case B_LATTCHANGED:
+
+ lt= ob->data;
+ if(lt->flag & LT_OUTSIDE) outside_lattice(lt);
+
+ make_displists_by_parent(ob);
+
+ allqueue(REDRAWVIEW3D, 0);
+
+ break;
+ }
+}
+
+void latticebuts(void)
+{
+ Lattice *lt;
+ Object *ob;
+ uiBlock *block;
+ char str[64];
+
+ ob= OBACT;
+ if(ob==0) return;
+
+ sprintf(str, "editbuttonswin %d", curarea->win);
+ block= uiNewBlock(&curarea->uiblocks, str, UI_EMBOSSX, UI_HELV, curarea->win);
+
+ if(ob==G.obedit) lt= editLatt;
+ else lt= ob->data;
+
+ uiSetButLock(lt->key!=0, "Not with VertexKeys");
+ uiSetButLock(ob==G.obedit, "Unable to perform function in EditMode");
+ uiDefButS(block, NUM, B_RESIZELAT, "U:", 470,178,100,19, &lt->pntsu, 1.0, 64.0, 0, 0, "");
+ uiDefButS(block, NUM, B_RESIZELAT, "V:", 470,158,100,19, &lt->pntsv, 1.0, 64.0, 0, 0, "");
+ uiDefButS(block, NUM, B_RESIZELAT, "W:", 470,138,100,19, &lt->pntsw, 1.0, 64.0, 0, 0, "");
+ uiClearButLock();
+
+ uiBlockSetCol(block, BUTGREEN);
+ uiDefButC(block, ROW, B_LATTCHANGED, "Lin", 572, 178, 40, 19, &lt->typeu, 1.0, (float)KEY_LINEAR, 0, 0, "");
+ uiDefButC(block, ROW, B_LATTCHANGED, "Card", 612, 178, 40, 19, &lt->typeu, 1.0, (float)KEY_CARDINAL, 0, 0, "");
+ uiDefButC(block, ROW, B_LATTCHANGED, "B", 652, 178, 40, 19, &lt->typeu, 1.0, (float)KEY_BSPLINE, 0, 0, "");
+
+ uiDefButC(block, ROW, B_LATTCHANGED, "Lin", 572, 158, 40, 19, &lt->typev, 2.0, (float)KEY_LINEAR, 0, 0, "");
+ uiDefButC(block, ROW, B_LATTCHANGED, "Card", 612, 158, 40, 19, &lt->typev, 2.0, (float)KEY_CARDINAL, 0, 0, "");
+ uiDefButC(block, ROW, B_LATTCHANGED, "B", 652, 158, 40, 19, &lt->typev, 2.0, (float)KEY_BSPLINE, 0, 0, "");
+
+ uiDefButC(block, ROW, B_LATTCHANGED, "Lin", 572, 138, 40, 19, &lt->typew, 3.0, (float)KEY_LINEAR, 0, 0, "");
+ uiDefButC(block, ROW, B_LATTCHANGED, "Card", 612, 138, 40, 19, &lt->typew, 3.0, (float)KEY_CARDINAL, 0, 0, "");
+ uiDefButC(block, ROW, B_LATTCHANGED, "B", 652, 138, 40, 19, &lt->typew, 3.0, (float)KEY_BSPLINE, 0, 0, "");
+
+ uiBlockSetCol(block, BUTSALMON);
+ uiDefBut(block, BUT, B_RESIZELAT, "Make Regular", 470,101,99,32, 0, 0, 0, 0, 0, "");
+
+ uiBlockSetCol(block, BUTGREEN);
+ uiDefButS(block, TOG|BIT|1, B_LATTCHANGED, "Outside", 571,101,120,31, &lt->flag, 0, 0, 0, 0, "");
+
+ uiDrawBlock(block);
+}
+
+
+/* *************************** TEXTURE ******************************** */
+
+Tex *cur_imatex=0;
+int prv_win= 0;
+
+void load_tex_image(char *str) /* aangeroepen vanuit fileselect */
+{
+ Image *ima=0;
+ Tex *tex;
+
+ tex= cur_imatex;
+ if(tex->type==TEX_IMAGE || tex->type==TEX_ENVMAP) {
+
+ ima= add_image(str);
+ if(ima) {
+ if(tex->ima) {
+ tex->ima->id.us--;
+ }
+ tex->ima= ima;
+
+ free_image_buffers(ima); /* forceer opnieuw inlezen */
+ ima->ok= 1;
+ }
+
+ allqueue(REDRAWBUTSTEX, 0);
+
+ BIF_preview_changed(G.buts);
+ }
+}
+
+void load_plugin_tex(char *str) /* aangeroepen vanuit fileselect */
+{
+ Tex *tex;
+
+ tex= cur_imatex;
+ if(tex->type!=TEX_PLUGIN) return;
+
+ if(tex->plugin) free_plugin_tex(tex->plugin);
+
+ tex->stype= 0;
+ tex->plugin= add_plugin_tex(str);
+
+ allqueue(REDRAWBUTSTEX, 0);
+ BIF_preview_changed(G.buts);
+}
+
+int vergcband(const void *a1, const void *a2)
+{
+ const CBData *x1=a1, *x2=a2;
+
+ if( x1->pos > x2->pos ) return 1;
+ else if( x1->pos < x2->pos) return -1;
+ return 0;
+}
+
+
+
+void save_env(char *name)
+{
+ Tex *tex;
+ char str[FILE_MAXFILE];
+
+ strcpy(str, name);
+ BLI_convertstringcode(str, G.sce, G.scene->r.cfra);
+ tex= G.buts->lockpoin;
+
+ if(tex && GS(tex->id.name)==ID_TE) {
+ if(tex->env && tex->env->ok && saveover(str)) {
+ waitcursor(1);
+ BIF_save_envmap(tex->env, str);
+ strcpy(G.ima, name);
+ waitcursor(0);
+ }
+ }
+
+}
+
+void drawcolorband(ColorBand *coba, float x1, float y1, float sizex, float sizey)
+{
+ CBData *cbd;
+ float v3[2], v1[2], v2[2];
+ int a;
+
+ if(coba==0) return;
+
+ /* outline */
+ v1[0]= x1; v1[1]= y1;
+ glLineWidth((GLfloat)(3));
+ cpack(0x0);
+ glBegin(GL_LINE_LOOP);
+ glVertex2fv(v1);
+ v1[0]+= sizex;
+ glVertex2fv(v1);
+ v1[1]+= sizey;
+ glVertex2fv(v1);
+ v1[0]-= sizex;
+ glVertex2fv(v1);
+ glEnd();
+ glLineWidth((GLfloat)(1));
+
+
+ glShadeModel(GL_SMOOTH);
+ cbd= coba->data;
+
+ v1[0]= v2[0]= x1;
+ v1[1]= y1;
+ v2[1]= y1+sizey;
+
+ glBegin(GL_QUAD_STRIP);
+
+ glColor3fv( &cbd->r );
+ glVertex2fv(v1); glVertex2fv(v2);
+
+ for(a=0; a<coba->tot; a++, cbd++) {
+
+ v1[0]=v2[0]= x1+ cbd->pos*sizex;
+
+ glColor3fv( &cbd->r );
+ glVertex2fv(v1); glVertex2fv(v2);
+ }
+
+ v1[0]=v2[0]= x1+ sizex;
+ glVertex2fv(v1); glVertex2fv(v2);
+
+ glEnd();
+ glShadeModel(GL_FLAT);
+
+ /* hulplijntjes */
+
+ v1[0]= v2[0]=v3[0]= x1;
+ v1[1]= y1;
+ v2[1]= y1+0.5*sizey;
+ v3[1]= y1+sizey;
+
+ cbd= coba->data;
+ glBegin(GL_LINES);
+ for(a=0; a<coba->tot; a++, cbd++) {
+ v1[0]=v2[0]=v3[0]= x1+ cbd->pos*sizex;
+
+ glColor3ub(0, 0, 0);
+ glVertex2fv(v1);
+ glVertex2fv(v2);
+
+ if(a==coba->cur) {
+ glVertex2f(v1[0]-1, v1[1]);
+ glVertex2f(v2[0]-1, v2[1]);
+ glVertex2f(v1[0]+1, v1[1]);
+ glVertex2f(v2[0]+1, v2[1]);
+ }
+
+ glColor3ub(255, 255, 255);
+ glVertex2fv(v2);
+ glVertex2fv(v3);
+
+ if(a==coba->cur) {
+ glVertex2f(v2[0]-1, v2[1]);
+ glVertex2f(v3[0]-1, v3[1]);
+ glVertex2f(v2[0]+1, v2[1]);
+ glVertex2f(v3[0]+1, v3[1]);
+ }
+ }
+ glEnd();
+
+ glFlush();
+}
+
+
+
+void do_texbuts(unsigned short event)
+{
+ Tex *tex;
+ ImBuf *ibuf;
+ ScrArea *sa;
+ ID *id;
+ CBData *cbd;
+ float dx;
+ int a, nr;
+ short mvalo[2], mval[2];
+ char *name, str[80];
+
+ tex= G.buts->lockpoin;
+
+ switch(event) {
+ case B_TEXCHANNEL:
+ scrarea_queue_headredraw(curarea);
+ BIF_preview_changed(G.buts);
+ allqueue(REDRAWBUTSTEX, 0);
+ break;
+ case B_TEXTYPE:
+ if(tex==0) return;
+ tex->stype= 0;
+ allqueue(REDRAWBUTSTEX, 0);
+ BIF_preview_changed(G.buts);
+ break;
+ case B_DEFTEXVAR:
+ if(tex==0) return;
+ default_tex(tex);
+ allqueue(REDRAWBUTSTEX, 0);
+ BIF_preview_changed(G.buts);
+ break;
+ case B_LOADTEXIMA:
+ case B_LOADTEXIMA1:
+ if(tex==0) return;
+ /* globals: even onthouden: we maken andere area fileselect */
+ cur_imatex= tex;
+ prv_win= curarea->win;
+
+ sa= closest_bigger_area();
+ areawinset(sa->win);
+ if(tex->ima) name= tex->ima->name;
+ else name= U.textudir;
+
+ if(event==B_LOADTEXIMA)
+ activate_imageselect(FILE_SPECIAL, "SELECT IMAGE", name, load_tex_image);
+ else
+ activate_fileselect(FILE_SPECIAL, "SELECT IMAGE", name, load_tex_image);
+
+ break;
+ case B_NAMEIMA:
+ if(tex==0) return;
+ if(tex->ima) {
+ cur_imatex= tex;
+ prv_win= curarea->win;
+
+ /* naam in tex->ima is door button veranderd! */
+ strcpy(str, tex->ima->name);
+ if(tex->ima->ibuf) strcpy(tex->ima->name, tex->ima->ibuf->name);
+
+ load_tex_image(str);
+ }
+ break;
+ case B_TEXREDR_PRV:
+ allqueue(REDRAWBUTSTEX, 0);
+ BIF_preview_changed(G.buts);
+ break;
+ case B_TEXIMABROWSE:
+ if(tex) {
+ id= (ID*) tex->ima;
+
+ if(G.buts->menunr== -2) {
+ activate_databrowse(id, ID_IM, 0, B_TEXIMABROWSE, &G.buts->menunr, do_texbuts);
+ } else if (G.buts->menunr>0) {
+ Image *newima= (Image*) BLI_findlink(&G.main->image, G.buts->menunr-1);
+
+ if (newima && newima!=(Image*) id) {
+ tex->ima= newima;
+ id_us_plus((ID*) newima);
+ if(id) id->us--;
+
+ allqueue(REDRAWBUTSTEX, 0);
+ BIF_preview_changed(G.buts);
+ }
+ }
+ }
+ break;
+ case B_IMAPTEST:
+ if(tex) {
+ if( (tex->imaflag & (TEX_FIELDS+TEX_MIPMAP))== TEX_FIELDS+TEX_MIPMAP ) {
+ error("Cannot combine fields and mipmap");
+ tex->imaflag -= TEX_MIPMAP;
+ allqueue(REDRAWBUTSTEX, 0);
+ }
+
+ if(tex->ima && tex->ima->ibuf) {
+ ibuf= tex->ima->ibuf;
+ nr= 0;
+ if( !(tex->imaflag & TEX_FIELDS) && (ibuf->flags & IB_fields) ) nr= 1;
+ if( (tex->imaflag & TEX_FIELDS) && !(ibuf->flags & IB_fields) ) nr= 1;
+ if(nr) {
+ IMB_freeImBuf(ibuf);
+ tex->ima->ibuf= 0;
+ tex->ima->ok= 1;
+ BIF_preview_changed(G.buts);
+ }
+ }
+ }
+ break;
+ case B_RELOADIMA:
+ if(tex && tex->ima) {
+ // check if there is a newer packedfile
+
+ if (tex->ima->packedfile) {
+ PackedFile *pf;
+ pf = newPackedFile(tex->ima->name);
+ if (pf) {
+ freePackedFile(tex->ima->packedfile);
+ tex->ima->packedfile = pf;
+ } else {
+ error("Image not available. Keeping packed image.");
+ }
+ }
+
+ IMB_freeImBuf(tex->ima->ibuf);
+ tex->ima->ibuf= 0;
+ tex->ima->ok= 1;
+ allqueue(REDRAWBUTSTEX, 0);
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWIMAGE, 0);
+ BIF_preview_changed(G.buts);
+ }
+ break;
+
+ case B_PACKIMA:
+ if(tex && tex->ima) {
+ if (tex->ima->packedfile) {
+ if (G.fileflags & G_AUTOPACK) {
+ if (okee("Disable AutoPack ?")) {
+ G.fileflags &= ~G_AUTOPACK;
+ }
+ }
+
+ if ((G.fileflags & G_AUTOPACK) == 0) {
+ unpackImage(tex->ima, PF_ASK);
+ }
+ } else {
+ if (tex->ima->ibuf && (tex->ima->ibuf->userflags & IB_BITMAPDIRTY)) {
+ error("Can't pack painted image. Save image from Image window first.");
+ } else {
+ tex->ima->packedfile = newPackedFile(tex->ima->name);
+ }
+ }
+ allqueue(REDRAWBUTSTEX, 0);
+ allqueue(REDRAWHEADERS, 0);
+ }
+ break;
+ case B_LOADPLUGIN:
+ if(tex==0) return;
+
+ /* globals: even onthouden: we maken andere area fileselect */
+ cur_imatex= tex;
+ prv_win= curarea->win;
+
+ sa= closest_bigger_area();
+ areawinset(sa->win);
+ if(tex->plugin) strcpy(str, tex->plugin->name);
+ else {
+ strcpy(str, U.plugtexdir);
+ }
+ activate_fileselect(FILE_SPECIAL, "SELECT PLUGIN", str, load_plugin_tex);
+
+ break;
+
+ case B_NAMEPLUGIN:
+ if(tex==0 || tex->plugin==0) return;
+ strcpy(str, tex->plugin->name);
+ free_plugin_tex(tex->plugin);
+ tex->stype= 0;
+ tex->plugin= add_plugin_tex(str);
+ allqueue(REDRAWBUTSTEX, 0);
+ BIF_preview_changed(G.buts);
+ break;
+
+ case B_COLORBAND:
+ if(tex==0) return;
+ if(tex->coba==0) tex->coba= add_colorband();
+ allqueue(REDRAWBUTSTEX, 0);
+ BIF_preview_changed(G.buts);
+ break;
+
+ case B_ADDCOLORBAND:
+ if(tex==0 || tex->coba==0) return;
+
+ if(tex->coba->tot < MAXCOLORBAND-1) tex->coba->tot++;
+ tex->coba->cur= tex->coba->tot-1;
+
+ do_texbuts(B_CALCCBAND);
+
+ break;
+
+ case B_DELCOLORBAND:
+ if(tex==0 || tex->coba==0 || tex->coba->tot<2) return;
+
+ for(a=tex->coba->cur; a<tex->coba->tot; a++) {
+ tex->coba->data[a]= tex->coba->data[a+1];
+ }
+ if(tex->coba->cur) tex->coba->cur--;
+ tex->coba->tot--;
+
+ allqueue(REDRAWBUTSTEX, 0);
+ BIF_preview_changed(G.buts);
+ break;
+
+ case B_CALCCBAND:
+ case B_CALCCBAND2:
+ if(tex==0 || tex->coba==0 || tex->coba->tot<2) return;
+
+ for(a=0; a<tex->coba->tot; a++) tex->coba->data[a].cur= a;
+ qsort(tex->coba->data, tex->coba->tot, sizeof(CBData), vergcband);
+ for(a=0; a<tex->coba->tot; a++) {
+ if(tex->coba->data[a].cur==tex->coba->cur) {
+ if(tex->coba->cur!=a) addqueue(curarea->win, REDRAW, 0); /* button cur */
+ tex->coba->cur= a;
+ break;
+ }
+ }
+ if(event==B_CALCCBAND2) return;
+
+ allqueue(REDRAWBUTSTEX, 0);
+ BIF_preview_changed(G.buts);
+
+ break;
+
+ case B_DOCOLORBAND:
+ if(tex==0 || tex->coba==0) return;
+
+ cbd= tex->coba->data + tex->coba->cur;
+ uiGetMouse(mywinget(), mvalo);
+
+ while(get_mbut() & L_MOUSE) {
+ uiGetMouse(mywinget(), mval);
+ if(mval[0]!=mvalo[0]) {
+ dx= mval[0]-mvalo[0];
+ dx/= 345.0;
+ cbd->pos+= dx;
+ CLAMP(cbd->pos, 0.0, 1.0);
+
+ glDrawBuffer(GL_FRONT);
+ drawcolorband(tex->coba, 923,81,345,20);
+ /* uiSetButs(B_CALCCBAND, B_CALCCBAND); */
+ glDrawBuffer(GL_BACK);
+
+ do_texbuts(B_CALCCBAND2);
+ cbd= tex->coba->data + tex->coba->cur; /* ivm qsort */
+
+ mvalo[0]= mval[0];
+ }
+ BIF_wait_for_statechange();
+ }
+ allqueue(REDRAWBUTSTEX, 0);
+ BIF_preview_changed(G.buts);
+
+ break;
+
+ case B_REDRAWCBAND:
+ glDrawBuffer(GL_FRONT);
+ drawcolorband(tex->coba, 923,81,345,20);
+ glDrawBuffer(GL_BACK);
+ BIF_preview_changed(G.buts);
+ break;
+
+ case B_ENV_DELETE:
+ if(tex->env) {
+ RE_free_envmap(tex->env);
+ tex->env= 0;
+ allqueue(REDRAWBUTSTEX, 0);
+ BIF_preview_changed(G.buts);
+ }
+ break;
+ case B_ENV_FREE:
+ if(tex->env) {
+ RE_free_envmapdata(tex->env);
+ allqueue(REDRAWBUTSTEX, 0);
+ BIF_preview_changed(G.buts);
+ }
+ break;
+ case B_ENV_SAVE:
+ if(tex->env && tex->env->ok) {
+ sa= closest_bigger_area();
+ areawinset(sa->win);
+ save_image_filesel_str(str);
+ activate_fileselect(FILE_SPECIAL, str, G.ima, save_env);
+ }
+ break;
+ case B_ENV_OB:
+ if(tex->env && tex->env->object) {
+ BIF_preview_changed(G.buts);
+ if ELEM(tex->env->object->type, OB_CAMERA, OB_LAMP) {
+ error("Camera or Lamp not allowed");
+ tex->env->object= 0;
+ }
+ }
+ break;
+
+ default:
+ if(event>=B_PLUGBUT && event<=B_PLUGBUT+23) {
+ PluginTex *pit= tex->plugin;
+ if(pit && pit->callback) {
+ pit->callback(event - B_PLUGBUT);
+ BIF_preview_changed(G.buts);
+ }
+ }
+ }
+}
+
+static void test_idbutton_cb(void *namev, void *arg2_unused)
+{
+ char *name= namev;
+ test_idbutton(name+2);
+}
+
+void texbuts(void)
+{
+ Object *ob;
+ Material *ma=0;
+ World *wrld=0;
+ Lamp *la=0;
+ ID *id = NULL;
+ MTex *mtex = NULL;
+ Tex *tex;
+ VarStruct *varstr;
+ PluginTex *pit;
+ CBData *cbd;
+ EnvMap *env;
+ uiBlock *block;
+ uiBut *but;
+ int a, xco, yco, loos, dx, dy, ok;
+ char str[30], *strp;
+
+ sprintf(str, "buttonswin %d", curarea->win);
+ block= uiNewBlock(&curarea->uiblocks, str, UI_EMBOSSX, UI_HELV, curarea->win);
+
+ uiBlockSetCol(block, BUTSALMON);
+
+ uiDefButC(block, ROW, B_TEXREDR_PRV, "Mat", 200,172,40,20, &G.buts->texfrom, 3.0, 0.0, 0, 0, "Display the texture of the active material");
+ uiDefButC(block, ROW, B_TEXREDR_PRV, "World", 240,172,52,20, &G.buts->texfrom, 3.0, 1.0, 0, 0, "Display the texture of the world block");
+ uiDefButC(block, ROW, B_TEXREDR_PRV, "Lamp", 292,172,46,20, &G.buts->texfrom, 3.0, 2.0, 0, 0, "Display the texture of the lamp");
+ uiBlockSetCol(block, BUTGREY);
+
+ ok= 0;
+
+ if(G.buts->texfrom==0) {
+ ob= OBACT;
+ if(ob) {
+ id= ob->data;
+ if(id) {
+ ma= give_current_material(ob, ob->actcol);
+ if(ma) ok= 1;
+ }
+ }
+
+ }
+ else if(G.buts->texfrom==1) {
+ wrld= G.scene->world;
+ if(wrld) {
+ id= (ID *)wrld;
+ ok= 1;
+ }
+ }
+ else if(G.buts->texfrom==2) {
+ ob= OBACT;
+ if(ob) {
+ if(ob->type==OB_LAMP) {
+ la= ob->data;
+ id= (ID *)la;
+ ok= 1;
+ }
+ }
+ }
+
+ if(ok==0) {
+ uiDrawBlock(block);
+ return;
+ }
+
+ uiSetButLock(id->lib!=0, "Can't edit library data");
+
+ /* CHANNELS */
+ yco= 140;
+ for(a= 0; a<8; a++) {
+ if(G.buts->texfrom==0) mtex= ma->mtex[a];
+ else if(G.buts->texfrom==1) mtex= wrld->mtex[a];
+ else if(G.buts->texfrom==2) mtex= la->mtex[a];
+
+ if(mtex && mtex->tex) splitIDname(mtex->tex->id.name+2, str, &loos);
+ else strcpy(str, "");
+ str[14]= 0;
+ if(G.buts->texfrom==0) {
+ uiDefButC(block, ROW, B_TEXCHANNEL, str, 200,(short)yco,140,18, &(ma->texact), 0.0, (float)a, 0, 0, "Linked channel");
+ }
+ else if(G.buts->texfrom==1) {
+ uiDefButS(block, ROW, B_TEXCHANNEL, str, 200,(short)yco,140,18, &(wrld->texact), 0.0, (float)a, 0, 0, "");
+ if(a==5) break;
+ }
+ else if(G.buts->texfrom==2) {
+ uiDefButS(block, ROW, B_TEXCHANNEL, str, 200,(short)yco,140,18, &(la->texact), 0.0, (float)a, 0, 0, "");
+ if(a==5) break;
+ }
+ yco-= 19;
+ }
+
+ if(G.buts->texfrom==0) {
+ but= uiDefBut(block, TEX, B_IDNAME, "MA:", 200,195,140,20, ma->id.name+2, 0.0, 18.0, 0, 0, "Name of the datablock");
+ uiButSetFunc(but, test_idbutton_cb, ma->id.name, NULL);
+ mtex= ma->mtex[ ma->texact ];
+ }
+ else if(G.buts->texfrom==1) {
+ but= uiDefBut(block, TEX, B_IDNAME, "WO:", 200,195,140,20, wrld->id.name+2, 0.0, 18.0, 0, 0, "Name of the datablock");
+ uiButSetFunc(but, test_idbutton_cb, wrld->id.name, NULL);
+ mtex= wrld->mtex[ wrld->texact ];
+ }
+ else if(G.buts->texfrom==2) {
+ but= uiDefBut(block, TEX, B_IDNAME, "LA:", 200,195,140,20, la->id.name+2, 0.0, 18.0, 0, 0, "Name of the datablock");
+ uiButSetFunc(but, test_idbutton_cb, la->id.name, NULL);
+ mtex= la->mtex[ la->texact ];
+ }
+
+ if(mtex && mtex->tex) {
+ tex= mtex->tex;
+
+ uiSetButLock(tex->id.lib!=0, "Can't edit library data");
+ xco= 275;
+ uiDefButS(block, ROW, B_TEXTYPE, texstr[0], (short)(xco+=75), 195, 75, 20, &tex->type, 1.0, 0.0, 0, 0, "Default");
+ uiDefButS(block, ROW, B_TEXTYPE, texstr[TEX_IMAGE],(short)(xco+=75), 195, 75, 20, &tex->type, 1.0, (float)TEX_IMAGE, 0, 0, "Use image texture");
+ uiDefButS(block, ROW, B_TEXTYPE, texstr[TEX_ENVMAP], (short)(xco+=75), 195, 75, 20, &tex->type, 1.0, (float)TEX_ENVMAP, 0, 0, "Use environment maps");
+ if(tex->plugin && tex->plugin->doit) strp= tex->plugin->pname; else strp= texstr[TEX_PLUGIN];
+ uiDefButS(block, ROW, B_TEXTYPE, strp, (short)(xco+=75), 195, 75, 20, &tex->type, 1.0, (float)TEX_PLUGIN, 0, 0, "Use plugin");
+ uiDefButS(block, ROW, B_TEXTYPE, texstr[TEX_CLOUDS], (short)(xco+=75), 195, 75, 20, &tex->type, 1.0, (float)TEX_CLOUDS, 0, 0, "Use clouds texture");
+ uiDefButS(block, ROW, B_TEXTYPE, texstr[TEX_WOOD], (short)(xco+=75), 195, 75, 20, &tex->type, 1.0, (float)TEX_WOOD, 0, 0, "Use wood texture");
+ uiDefButS(block, ROW, B_TEXTYPE, texstr[TEX_MARBLE], (short)(xco+=75), 195, 75, 20, &tex->type, 1.0, (float)TEX_MARBLE, 0, 0, "Use marble texture");
+ uiDefButS(block, ROW, B_TEXTYPE, texstr[TEX_MAGIC], (short)(xco+=75), 195, 75, 20, &tex->type, 1.0, (float)TEX_MAGIC, 0, 0, "Use magic texture");
+ uiDefButS(block, ROW, B_TEXTYPE, texstr[TEX_BLEND], (short)(xco+=75), 195, 75, 20, &tex->type, 1.0, (float)TEX_BLEND, 0, 0, "Use blend texture");
+ uiDefButS(block, ROW, B_TEXTYPE, texstr[TEX_STUCCI], (short)(xco+=75), 195, 75, 20, &tex->type, 1.0, (float)TEX_STUCCI, 0, 0, "Use strucci texture");
+ uiDefButS(block, ROW, B_TEXTYPE, texstr[TEX_NOISE], (short)(xco+=75), 195, 75, 20, &tex->type, 1.0, (float)TEX_NOISE, 0, 0, "Use noise texture");
+
+ /* TYPES */
+ uiBlockSetCol(block, BUTGREEN);
+ switch(tex->type) {
+ case TEX_CLOUDS:
+ uiDefButS(block, ROW, B_MATPRV, "Default", 350, 170, 75, 18, &tex->stype, 2.0, 0.0, 0, 0, "Use standard noise");
+ uiDefButS(block, ROW, B_MATPRV, "Color", 425, 170, 75, 18, &tex->stype, 2.0, 1.0, 0, 0, "Let Noise give RGB value");
+ uiBlockSetCol(block, BUTGREY);
+ uiDefButF(block, NUM, B_MATPRV, "NoiseSize :", 350, 110, 150, 19, &tex->noisesize, 0.0001, 2.0, 10, 0, "Set the dimension of the noise table");
+ uiDefButS(block, NUM, B_MATPRV, "NoiseDepth:", 350, 90, 150, 19, &tex->noisedepth, 0.0, 6.0, 0, 0, "Set the depth of the cloud calculation");
+ uiBlockSetCol(block, BUTGREEN);
+ uiDefButS(block, ROW, B_MATPRV, "Soft noise", 350, 40, 100, 19, &tex->noisetype, 12.0, 0.0, 0, 0, "Use soft noise");
+ uiDefButS(block, ROW, B_MATPRV, "Hard noise", 450, 40, 100, 19, &tex->noisetype, 12.0, 1.0, 0, 0, "Use hard noise");
+ break;
+
+ case TEX_WOOD:
+ uiDefButS(block, ROW, B_MATPRV, "Bands", 350, 170, 75, 18, &tex->stype, 2.0, 0.0, 0, 0, "Use standard wood texture");
+ uiDefButS(block, ROW, B_MATPRV, "Rings", 425, 170, 75, 18, &tex->stype, 2.0, 1.0, 0, 0, "Use wood rings");
+ uiDefButS(block, ROW, B_MATPRV, "BandNoise", 500, 170, 75, 18, &tex->stype, 2.0, 2.0, 0, 0, "Add noise to standard wood");
+ uiDefButS(block, ROW, B_MATPRV, "RingNoise", 575, 170, 75, 18, &tex->stype, 2.0, 3.0, 0, 0, "Add noise to rings");
+ uiBlockSetCol(block, BUTGREY);
+ uiDefButF(block, NUM, B_MATPRV, "NoiseSize :", 350, 110, 150, 19, &tex->noisesize, 0.0001, 2.0, 10, 0, "Set the dimension of the noise table");
+ uiDefButF(block, NUM, B_MATPRV, "Turbulence:", 350, 90, 150, 19, &tex->turbul, 0.0, 200.0, 10, 0, "Set the turbulence of the bandnoise and ringnoise types");
+ uiBlockSetCol(block, BUTGREEN);
+ uiDefButS(block, ROW, B_MATPRV, "Soft noise", 350, 40, 100, 19, &tex->noisetype, 12.0, 0.0, 0, 0, "Use soft noise");
+ uiDefButS(block, ROW, B_MATPRV, "Hard noise", 450, 40, 100, 19, &tex->noisetype, 12.0, 1.0, 0, 0, "Use hard noise");
+ break;
+
+ case TEX_MARBLE:
+ uiDefButS(block, ROW, B_MATPRV, "Soft", 350, 170, 75, 18, &tex->stype, 2.0, 0.0, 0, 0, "Use soft marble");
+ uiDefButS(block, ROW, B_MATPRV, "Sharp", 425, 170, 75, 18, &tex->stype, 2.0, 1.0, 0, 0, "Use more clearly defined marble");
+ uiDefButS(block, ROW, B_MATPRV, "Sharper", 500, 170, 75, 18, &tex->stype, 2.0, 2.0, 0, 0, "Use very clear defined marble");
+ uiBlockSetCol(block, BUTGREY);
+ uiDefButF(block, NUM, B_MATPRV, "NoiseSize :", 350, 110, 150, 19, &tex->noisesize, 0.0001, 2.0, 10, 0, "Set the dimension of the noise table");
+ uiDefButS(block, NUM, B_MATPRV, "NoiseDepth:", 350, 90, 150, 19, &tex->noisedepth, 0.0, 6.0, 0, 0, "Set the depth of the marble calculation");
+ uiDefButF(block, NUM, B_MATPRV, "Turbulence:", 350, 70, 150, 19, &tex->turbul, 0.0, 200.0, 10, 0, "Set the turbulence of the sine bands");
+ uiBlockSetCol(block, BUTGREEN);
+ uiDefButS(block, ROW, B_MATPRV, "Soft noise", 350, 40, 100, 19, &tex->noisetype, 12.0, 0.0, 0, 0, "Use soft noise");
+ uiDefButS(block, ROW, B_MATPRV, "Hard noise", 450, 40, 100, 19, &tex->noisetype, 12.0, 1.0, 0, 0, "Use hard noise");
+ break;
+
+ case TEX_MAGIC:
+ uiBlockSetCol(block, BUTGREY);
+ uiDefButF(block, NUM, B_MATPRV, "Size :", 350, 110, 150, 19, &tex->noisesize, 0.0001, 2.0, 10, 0, "Set the dimension of the pattern");
+ uiDefButS(block, NUM, B_MATPRV, "Depth:", 350, 90, 150, 19, &tex->noisedepth, 0.0, 10.0, 0, 0, "Set the depth of the pattern");
+ uiDefButF(block, NUM, B_MATPRV, "Turbulence:", 350, 70, 150, 19, &tex->turbul, 0.0, 200.0, 10, 0, "Set the strength of the pattern");
+ break;
+
+ case TEX_BLEND:
+ uiDefButS(block, ROW, B_MATPRV, "Lin", 350, 170, 75, 18, &tex->stype, 2.0, 0.0, 0, 0, "Use a linear progresion");
+ uiDefButS(block, ROW, B_MATPRV, "Quad", 425, 170, 75, 18, &tex->stype, 2.0, 1.0, 0, 0, "Use a quadratic progression");
+ uiDefButS(block, ROW, B_MATPRV, "Ease", 500, 170, 75, 18, &tex->stype, 2.0, 2.0, 0, 0, "");
+ uiDefButS(block, ROW, B_MATPRV, "Diag", 575, 170, 75, 18, &tex->stype, 2.0, 3.0, 0, 0, "Use a diagonal progression");
+ uiDefButS(block, ROW, B_MATPRV, "Sphere", 650, 170, 75, 18, &tex->stype, 2.0, 4.0, 0, 0, "Use progression with the shape of a sphere");
+ uiDefButS(block, ROW, B_MATPRV, "Halo", 725, 170, 75, 18, &tex->stype, 2.0, 5.0, 0, 0, "Use a quadratic progression with the shape of a sphere");
+
+ uiDefButS(block, TOG|BIT|1, B_MATPRV, "Flip XY", 350, 130, 75, 18, &tex->flag, 0, 0, 0, 0, "Flip the direction of the progression a quarter turn");
+ break;
+
+ case TEX_STUCCI:
+ uiDefButS(block, ROW, B_MATPRV, "Plastic", 350, 170, 75, 18, &tex->stype, 2.0, 0.0, 0, 0, "Use standard stucci");
+ uiDefButS(block, ROW, B_MATPRV, "Wall In", 425, 170, 75, 18, &tex->stype, 2.0, 1.0, 0, 0, "Set start value");
+ uiDefButS(block, ROW, B_MATPRV, "Wall Out", 500, 170, 75, 18, &tex->stype, 2.0, 2.0, 0, 0, "Set end value");
+ uiBlockSetCol(block, BUTGREY);
+ uiDefButF(block, NUM, B_MATPRV, "NoiseSize :", 350, 110, 150, 19, &tex->noisesize, 0.0001, 2.0, 10, 0, "Set the dimension of the noise table");
+ uiDefButF(block, NUM, B_MATPRV, "Turbulence:", 350, 90, 150, 19, &tex->turbul, 0.0, 200.0, 10, 0, "Set the depth of the stucci");
+ uiBlockSetCol(block, BUTGREEN);
+ uiDefButS(block, ROW, B_MATPRV, "Soft noise", 350, 40, 100, 19, &tex->noisetype, 12.0, 0.0, 0, 0, "Use soft noise");
+ uiDefButS(block, ROW, B_MATPRV, "Hard noise", 450, 40, 100, 19, &tex->noisetype, 12.0, 1.0, 0, 0, "Use hard noise");
+
+ break;
+
+ case TEX_NOISE:
+ break;
+
+ case TEX_IMAGE:
+
+ break;
+ }
+
+ uiBlockSetCol(block, BUTSALMON);
+ uiDefBut(block, BUT, B_DEFTEXVAR, "Default Vars", 1180,169,93,47, 0, 0, 0, 0, 0, "Return to standard values");
+
+ uiBlockSetCol(block, BUTGREY);
+ /* SPECIFIC */
+ if(tex->type==TEX_IMAGE) {
+ uiDefButF(block, NUM, B_REDR, "MinX ", 350,30,140,19, &tex->cropxmin, -10.0, 10.0, 10, 0, "Set minimum X value for cropping");
+ uiDefButF(block, NUM, B_REDR, "MaxX ", 350,10,140,19, &tex->cropxmax, -10.0, 10.0, 10, 0, "Set maximum X value for cropping");
+ uiDefButF(block, NUM, B_REDR, "MinY ", 494,30,140,19, &tex->cropymin, -10.0, 10.0, 10, 0, "Set minimum Y value for cropping");
+ uiDefButF(block, NUM, B_REDR, "MaxY ", 494,10,140,19, &tex->cropymax, -10.0, 10.0, 10, 0, "Set maximum Y value for cropping");
+
+
+ uiDefButS(block, ROW, 0, "Extend", 350,85,69,19, &tex->extend, 4.0, 1.0, 0, 0, "Extend the colour of the edge");
+ uiDefButS(block, ROW, 0, "Clip", 421,85,59,19, &tex->extend, 4.0, 2.0, 0, 0, "Return alpha 0.0 outside image");
+ uiDefButS(block, ROW, 0, "Repeat", 565,85,68,19, &tex->extend, 4.0, 3.0, 0, 0, "Repeat image horizontally and vertically");
+ uiDefButS(block, ROW, 0, "ClipCube", 482,85,82,19, &tex->extend, 4.0, 4.0, 0, 0, "Return alpha 0.0 outside cubeshaped area around image");
+
+ uiDefButF(block, NUM, B_MATPRV, "Filter :", 352,109,135,19, &tex->filtersize, 0.1, 25.0, 0, 0, "Set the filter size used by mipmap and interpol");
+
+ uiDefButS(block, NUM, B_MATPRV, "Xrepeat:", 350,60,140,19, &tex->xrepeat, 1.0, 512.0, 0, 0, "Set the degree of repetition in the X direction");
+ uiDefButS(block, NUM, B_MATPRV, "Yrepeat:", 494,60,140,19, &tex->yrepeat, 1.0, 512.0, 0, 0, "Set the degree of repetition in the Y direction");
+
+ uiDefButS(block, NUM, B_MATPRV, "Frames :", 642,110,150,19, &tex->frames, 0.0, 18000.0, 0, 0, "Activate animation option");
+ uiDefButS(block, NUM, B_MATPRV, "Offset :", 642,90,150,19, &tex->offset, -9000.0, 9000.0, 0, 0, "Set the number of the first picture of the animation");
+ uiDefButS(block, NUM, B_MATPRV, "Fie/Ima:", 642,60,98,19, &tex->fie_ima, 1.0, 200.0, 0, 0, "Set the number of fields per rendered frame");
+ uiDefButS(block, NUM, B_MATPRV, "StartFr:", 642,30,150,19, &tex->sfra, 1.0, 9000.0, 0, 0, "Set the start frame of the animation");
+ uiDefButS(block, NUM, B_MATPRV, "Len:", 642,10,150,19, &tex->len, 0.0, 9000.0, 0, 0, "Set the length of the animation");
+
+ uiDefButS(block, NUM, B_MATPRV, "Fra:", 802,70,73,19, &(tex->fradur[0][0]), 0.0, 18000.0, 0, 0, "Montage mode: frame start");
+ uiDefButS(block, NUM, B_MATPRV, "", 879,70,37,19, &(tex->fradur[0][1]), 0.0, 250.0, 0, 0, "Montage mode: amount of displayed frames");
+ uiDefButS(block, NUM, B_MATPRV, "Fra:", 802,50,73,19, &(tex->fradur[1][0]), 0.0, 18000.0, 0, 0, "Montage mode: frame start");
+ uiDefButS(block, NUM, B_MATPRV, "", 879,50,37,19, &(tex->fradur[1][1]), 0.0, 250.0, 0, 0, "Montage mode: amount of displayed frames");
+ uiDefButS(block, NUM, B_MATPRV, "Fra:", 802,30,73,19, &(tex->fradur[2][0]), 0.0, 18000.0, 0, 0, "Montage mode: frame start");
+ uiDefButS(block, NUM, B_MATPRV, "", 879,30,37,19, &(tex->fradur[2][1]), 0.0, 250.0, 0, 0, "Montage mode: amount of displayed frames");
+ uiDefButS(block, NUM, B_MATPRV, "Fra:", 802,10,73,19, &(tex->fradur[3][0]), 0.0, 18000.0, 0, 0, "Montage mode: frame start");
+ uiDefButS(block, NUM, B_MATPRV, "", 879,10,37,19, &(tex->fradur[3][1]), 0.0, 250.0, 0, 0, "Montage mode: amount of displayed frames");
+
+ uiBlockSetCol(block, BUTGREEN);
+ uiDefButS(block, TOG|BIT|6, 0, "Cyclic", 743,60,48,19, &tex->imaflag, 0, 0, 0, 0, "Repeat animation image");
+
+ uiBlockSetCol(block, BUTSALMON);
+ uiDefBut(block, BUT, B_LOADTEXIMA, "Load Image", 350,137,132,24, 0, 0, 0, 0, 0, "Load image - thumbnail view");
+ uiBlockSetCol(block, BUTGREY);
+ uiDefBut(block, BUT, B_LOADTEXIMA1, "", 485,137,10,24, 0, 0, 0, 0, 0, "Load image - file view");
+
+ id= (ID *)tex->ima;
+ IDnames_to_pupstring(&strp, NULL, NULL, &(G.main->image), id, &(G.buts->menunr));
+ if(strp[0])
+ uiDefButS(block, MENU, B_TEXIMABROWSE, strp, 496,137,23,24, &(G.buts->menunr), 0, 0, 0, 0, "Browse");
+ MEM_freeN(strp);
+
+ if(tex->ima) {
+ uiDefBut(block, TEX, B_NAMEIMA, "", 520,137,412,24, tex->ima->name, 0.0, 79.0, 0, 0, "Texture name");
+ sprintf(str, "%d", tex->ima->id.us);
+ uiDefBut(block, BUT, 0, str, 934,137,23,24, 0, 0, 0, 0, 0, "Number of users");
+ uiDefBut(block, BUT, B_RELOADIMA, "Reload", 986,137,68,24, 0, 0, 0, 0, 0, "Reload");
+
+ if (tex->ima->packedfile) {
+ packdummy = 1;
+ } else {
+ packdummy = 0;
+ }
+ uiDefIconButI(block, TOG|BIT|0, B_PACKIMA, ICON_PACKAGE, 960,137,24,24, &packdummy, 0, 0, 0, 0, "Pack/Unpack this Image");
+ }
+
+ uiBlockSetCol(block, BUTGREEN);
+
+ uiDefButS(block, TOG|BIT|0, 0, "InterPol", 350, 170, 75, 18, &tex->imaflag, 0, 0, 0, 0, "Interpolate pixels of the image");
+ uiDefButS(block, TOG|BIT|1, B_MATPRV, "UseAlpha", 425, 170, 75, 18, &tex->imaflag, 0, 0, 0, 0, "Use the alpha layer");
+ uiDefButS(block, TOG|BIT|5, B_MATPRV, "CalcAlpha", 500, 170, 75, 18, &tex->imaflag, 0, 0, 0, 0, "Calculate an alpha based on the RGB");
+ uiDefButS(block, TOG|BIT|2, B_MATPRV, "NegAlpha", 575, 170, 75, 18, &tex->flag, 0, 0, 0, 0, "Reverse the alpha value");
+ uiDefButS(block, TOG|BIT|2, B_IMAPTEST, "MipMap", 650, 170, 75, 18, &tex->imaflag, 0, 0, 0, 0, "Generate a series of pictures used for mipmapping");
+ uiDefButS(block, TOG|BIT|3, B_IMAPTEST, "Fields", 725, 170, 75, 18, &tex->imaflag, 0, 0, 0, 0, "Work with field images");
+ uiDefButS(block, TOG|BIT|4, B_MATPRV, "Rot90", 800, 170, 50, 18, &tex->imaflag, 0, 0, 0, 0, "Rotate image 90 degrees when rendered");
+ uiDefButS(block, TOG|BIT|7, B_RELOADIMA, "Movie", 850, 170, 50, 18, &tex->imaflag, 0, 0, 0, 0, "Use a movie for an image");
+ uiDefButS(block, TOG|BIT|8, 0, "Anti", 900, 170, 50, 18, &tex->imaflag, 0, 0, 0, 0, "Use anti-aliasing");
+ uiDefButS(block, TOG|BIT|10, 0, "StField", 950, 170, 50, 18, &tex->imaflag, 0, 0, 0, 0, "");
+
+ uiBlockSetCol(block, BUTGREY);
+
+ /* printen aantal frames anim */
+ if(tex->ima && tex->ima->anim) {
+ sprintf(str, "%d frs ", IMB_anim_get_duration(tex->ima->anim));
+ uiDefBut(block, LABEL, 0, str, 834, 110, 90, 18, 0, 0, 0, 0, 0, "");
+ sprintf(str, "%d cur ", tex->ima->lastframe);
+ uiDefBut(block, LABEL, 0, str, 834, 90, 90, 18, 0, 0, 0, 0, 0, "");
+ }
+
+
+ }
+ else if(tex->type==TEX_PLUGIN) {
+ if(tex->plugin && tex->plugin->doit) {
+
+ pit= tex->plugin;
+
+ uiBlockSetCol(block, BUTGREEN);
+ for(a=0; a<pit->stypes; a++) {
+ uiDefButS(block, ROW, B_MATPRV, pit->stnames+16*a, (short)(350+75*a), 170, 75, 18, &tex->stype, 2.0, (float)a, 0, 0, "");
+ }
+
+ uiBlockSetCol(block, BUTGREY);
+ varstr= pit->varstr;
+ if(varstr) {
+ for(a=0; a<pit->vars; a++, varstr++) {
+ xco= 350 + 140*(a/6);
+ yco= 110 - 20*(a % 6);
+ uiDefBut(block, varstr->type, B_PLUGBUT+a, varstr->name, (short)xco,(short)yco,137,19, &(pit->data[a]), varstr->min, varstr->max, 100, 0, varstr->tip);
+ }
+ }
+ uiDefBut(block, TEX, B_NAMEPLUGIN, "", 520,137,412,24, pit->name, 0.0, 79.0, 0, 0, "Browse");
+ }
+
+ uiBlockSetCol(block, BUTSALMON);
+ uiDefBut(block, BUT, B_LOADPLUGIN, "Load Plugin", 350,137,137,24, 0, 0, 0, 0, 0, "");
+
+ }
+ else if(tex->type==TEX_ENVMAP) {
+
+ if(tex->env==0) tex->env= RE_add_envmap();
+
+ if(tex->env) {
+ env= tex->env;
+
+ uiBlockSetCol(block, BUTGREEN);
+ uiDefButS(block, ROW, B_REDR, "Static", 350, 170, 75, 18, &env->stype, 2.0, 0.0, 0, 0, "Calculate map only once");
+ uiDefButS(block, ROW, B_REDR, "Anim", 425, 170, 75, 18, &env->stype, 2.0, 1.0, 0, 0, "Calculate map each rendering");
+ uiDefButS(block, ROW, B_ENV_FREE, "Load", 500, 170, 75, 18, &env->stype, 2.0, 2.0, 0, 0, "Load map from disk");
+
+ if(env->stype==ENV_LOAD) {
+ uiBlockSetCol(block, BUTSALMON);
+ uiDefBut(block, BUT, B_LOADTEXIMA, "Load Image", 350,137,132,24, 0, 0, 0, 0, 0, "Load image - thumbnail view");
+ uiBlockSetCol(block, BUTGREY);
+ uiDefBut(block, BUT, B_LOADTEXIMA1, "", 485,137,10,24, 0, 0, 0, 0, 0, "Load image - file view");
+
+ id= (ID *)tex->ima;
+ IDnames_to_pupstring(&strp, NULL, NULL, &(G.main->image), id, &(G.buts->menunr));
+ if(strp[0])
+ uiDefButS(block, MENU, B_TEXIMABROWSE, strp, 496,137,23,24, &(G.buts->menunr), 0, 0, 0, 0, "");
+ MEM_freeN(strp);
+
+ if(tex->ima) {
+ uiDefBut(block, TEX, B_NAMEIMA, "", 520,137,412,24, tex->ima->name, 0.0, 79.0, 0, 0, "");
+ sprintf(str, "%d", tex->ima->id.us);
+ uiDefBut(block, BUT, 0, str, 934,137,23,24, 0, 0, 0, 0, 0, "");
+ if (tex->ima->packedfile) {
+ packdummy = 1;
+ } else {
+ packdummy = 0;
+ }
+ uiDefIconButI(block, TOG|BIT|0, B_PACKIMA, ICON_PACKAGE, 960,137,24,24, &packdummy, 0, 0, 0, 0, "Pack/Unpack this Image");
+ uiDefBut(block, BUT, B_RELOADIMA, "Reload", 986,137,68,24, 0, 0, 0, 0, 0, "");
+ }
+ }
+ else {
+ uiBlockSetCol(block, BUTSALMON);
+ uiDefBut(block, BUT, B_ENV_FREE, "Free Data", 350,137,107,24, 0, 0, 0, 0, 0, "Release all images associated with environment map");
+ uiBlockSetCol(block, BUTGREY);
+ uiDefBut(block, BUT, B_ENV_SAVE, "Save EnvMap", 461,137,115,24, 0, 0, 0, 0, 0, "Save environment map");
+ }
+ uiBlockSetCol(block, BUTGREY);
+ uiDefIDPoinBut(block, test_obpoin_but, B_ENV_OB, "Ob:", 350,95,206,24, &(env->object), "Object name");
+ uiBlockSetCol(block, BUTGREY);
+ uiDefButF(block, NUM, REDRAWVIEW3D, "ClipSta", 350,68,122,24, &env->clipsta, 0.01, 50.0, 100, 0, "Set start value for clipping");
+ uiDefButF(block, NUM, 0, "ClipEnd", 475,68,142,24, &env->clipend, 0.1, 5000.0, 1000, 0, "Set end value for clipping");
+ if(env->stype!=ENV_LOAD) uiDefButI(block, NUM, B_ENV_FREE, "CubeRes", 620,68,140,24, &env->cuberes, 50, 1000.0, 0, 0, "Set the resolution in pixels");
+
+ uiDefButF(block, NUM, B_MATPRV, "Filter :", 558,95,201,24, &tex->filtersize, 0.1, 25.0, 0, 0, "Adjust sharpness or blurriness of the reflection"),
+
+ uiDefBut(block, LABEL, 0, "Don't render layer:", 772,100,140,22, 0, 0.0, 0.0, 0, 0, "");
+ xco= 772;
+ dx= 28;
+ dy= 26;
+ for(a=0; a<10; a++) {
+ uiDefButI(block, TOG|BIT|(a+10), 0, "",(short)(xco+a*(dx/2)), 68, (short)(dx/2), (short)(dy/2), &env->notlay, 0, 0, 0, 0, "Render this layer");
+ uiDefButI(block, TOG|BIT|a, 0, "", (short)(xco+a*(dx/2)), (short)(68+dy/2), (short)(dx/2), (short)(1+dy/2), &env->notlay, 0, 0, 0, 0, "Render this layer");
+ if(a==4) xco+= 5;
+ }
+
+ }
+ }
+
+ /* COLORBAND */
+ uiBlockSetCol(block, BUTSALMON);
+ uiDefButS(block, TOG|BIT|0, B_COLORBAND, "Colorband", 923,103,102,20, &tex->flag, 0, 0, 0, 0, "Use colorband");
+ if(tex->flag & TEX_COLORBAND) {
+ uiDefBut(block, BUT, B_ADDCOLORBAND, "Add", 1029,103,50,20, 0, 0, 0, 0, 0, "Add new colour to the colorband");
+ uiDefBut(block, BUT, B_DELCOLORBAND, "Del", 1218,104,50,20, 0, 0, 0, 0, 0, "Delete the active colour");
+ uiBlockSetCol(block, BUTPURPLE);
+ uiDefButS(block, NUM, B_REDR, "Cur:", 1082,104,132,20, &tex->coba->cur, 0.0, (float)(tex->coba->tot-1), 0, 0, "The active colour from the colorband");
+
+ uiDefBut(block, LABEL, B_DOCOLORBAND, "", 923,81,345,20, 0, 0, 0, 0, 0, "Colorband"); /* alleen voor event! */
+
+ drawcolorband(tex->coba, 923,81,345,20);
+ cbd= tex->coba->data + tex->coba->cur;
+
+ uiDefButF(block, NUM, B_CALCCBAND, "Pos", 923,59,89,20, &cbd->pos, 0.0, 1.0, 10, 0, "Set the position of the active colour");
+ uiBlockSetCol(block, BUTGREEN);
+ uiDefButS(block, ROW, B_REDRAWCBAND, "E", 1013,59,20,20, &tex->coba->ipotype, 5.0, 1.0, 0, 0, "Interpolation type Ease");
+ uiDefButS(block, ROW, B_REDRAWCBAND, "L", 1033,59,20,20, &tex->coba->ipotype, 5.0, 0.0, 0, 0, "Interpolation type Linear");
+ uiDefButS(block, ROW, B_REDRAWCBAND, "S", 1053,59,20,20, &tex->coba->ipotype, 5.0, 2.0, 0, 0, "Interpolation type Spline");
+ uiBlockSetCol(block, BUTPURPLE);
+ uiDefButF(block, COL, B_BANDCOL, "", 1076,59,28,20, &(cbd->r), 0, 0, 0, 0, "");
+ uiDefButF(block, NUMSLI, B_REDRAWCBAND, "A ", 1107,58,163,20, &cbd->a, 0.0, 1.0, 0, 0, "Set the alpha value");
+
+ uiDefButF(block, NUMSLI, B_REDRAWCBAND, "R ", 923,37,116,20, &cbd->r, 0.0, 1.0, B_BANDCOL, 0, "Set the red value");
+ uiDefButF(block, NUMSLI, B_REDRAWCBAND, "G ", 1042,37,111,20, &cbd->g, 0.0, 1.0, B_BANDCOL, 0, "Set the green value");
+ uiDefButF(block, NUMSLI, B_REDRAWCBAND, "B ", 1156,36,115,20, &cbd->b, 0.0, 1.0, B_BANDCOL, 0, "Set the blue value");
+
+ }
+
+
+ /* RGB-BRICON */
+ uiBlockSetCol(block, BUTGREY);
+ uiDefButF(block, NUMSLI, B_MATPRV, "Bright", 923,11,166,20, &tex->bright, 0.0, 2.0, 0, 0, "Set the brightness of the colour or intensity of a texture");
+
+ uiDefButF(block, NUMSLI, B_MATPRV, "Contr", 1093,11,180,20, &tex->contrast, 0.01, 2.0, 0, 0, "Set the contrast of the colour or intensity of a texture");
+
+ if((tex->flag & TEX_COLORBAND)==0) {
+ uiDefButF(block, NUMSLI, B_MATPRV, "R ", 923,37,116,20, &tex->rfac, 0.0, 2.0, 0, 0, "Set the red value");
+ uiDefButF(block, NUMSLI, B_MATPRV, "G ", 1042,37,111,20, &tex->gfac, 0.0, 2.0, 0, 0, "Set the green value");
+ uiDefButF(block, NUMSLI, B_MATPRV, "B ", 1156,36,115,20, &tex->bfac, 0.0, 2.0, 0, 0, "Set the blue value");
+ }
+ }
+
+ /* PREVIEW RENDER */
+
+ BIF_previewdraw(G.buts);
+
+ uiDrawBlock(block);
+}
+
+/* ****************************** MATERIAL ************************ */
+MTex mtexcopybuf;
+
+
+void do_matbuts(unsigned short event)
+{
+ static short mtexcopied=0;
+ Material *ma;
+ MTex *mtex;
+
+ switch(event) {
+ case B_ACTCOL:
+ scrarea_queue_headredraw(curarea);
+ allqueue(REDRAWBUTSMAT, 0);
+ allqueue(REDRAWIPO, 0);
+ BIF_previewdraw(G.buts);
+ break;
+ case B_MATFROM:
+
+ scrarea_queue_headredraw(curarea);
+ allqueue(REDRAWBUTSMAT, 0);
+ BIF_previewdraw(G.buts);
+ break;
+ case B_MATPRV:
+ /* dit event wordt ook door lamp, tex en sky gebruikt */
+ BIF_preview_changed(G.buts);
+ break;
+ case B_MATPRV_DRAW:
+ BIF_preview_changed(G.buts);
+ allqueue(REDRAWBUTSMAT, 0);
+ break;
+ case B_TEXCLEAR:
+ ma= G.buts->lockpoin;
+ mtex= ma->mtex[(int) ma->texact ];
+ if(mtex) {
+ if(mtex->tex) mtex->tex->id.us--;
+ MEM_freeN(mtex);
+ ma->mtex[ (int) ma->texact ]= 0;
+ allqueue(REDRAWBUTSMAT, 0);
+ allqueue(REDRAWOOPS, 0);
+ BIF_preview_changed(G.buts);
+ }
+ break;
+ case B_MTEXCOPY:
+ ma= G.buts->lockpoin;
+ if(ma && ma->mtex[(int)ma->texact] ) {
+ mtex= ma->mtex[(int)ma->texact];
+ if(mtex->tex==0) {
+ error("No texture available");
+ }
+ else {
+ memcpy(&mtexcopybuf, ma->mtex[(int)ma->texact], sizeof(MTex));
+ notice("copied!");
+ mtexcopied= 1;
+ }
+ }
+ break;
+ case B_MTEXPASTE:
+ ma= G.buts->lockpoin;
+ if(ma && mtexcopied && mtexcopybuf.tex) {
+ if(ma->mtex[(int)ma->texact]==0 ) ma->mtex[(int)ma->texact]= MEM_mallocN(sizeof(MTex), "mtex");
+ memcpy(ma->mtex[(int)ma->texact], &mtexcopybuf, sizeof(MTex));
+
+ id_us_plus((ID *)mtexcopybuf.tex);
+ notice("pasted!");
+ BIF_preview_changed(G.buts);
+ scrarea_queue_winredraw(curarea);
+ }
+ break;
+ case B_MATLAY:
+ ma= G.buts->lockpoin;
+ if(ma && ma->lay==0) {
+ ma->lay= 1;
+ scrarea_queue_winredraw(curarea);
+ }
+ }
+}
+
+void matbuts(void)
+{
+ Object *ob;
+ Material *ma;
+ ID *id, *idn;
+ MTex *mtex;
+ uiBlock *block;
+ uiBut *but;
+ float *colpoin = NULL, min;
+ int rgbsel = 0, a, loos;
+ char str[30], *strp;
+ short xco;
+
+ ob= OBACT;
+ if(ob==0 || ob->data==0) return;
+
+ sprintf(str, "buttonswin %d", curarea->win);
+ block= uiNewBlock(&curarea->uiblocks, str, UI_EMBOSSX, UI_HELV, curarea->win);
+
+ if(ob->actcol==0) ob->actcol= 1; /* ivm TOG|BIT button */
+
+ /* aangeven waar het materiaal aan hangt */
+ uiBlockSetCol(block, BUTSALMON);
+ uiDefButS(block, TOG|BIT|(ob->actcol-1), B_MATFROM, "OB", 342, 195, 33, 20, &ob->colbits, 0, 0, 0, 0, "Link material to object");
+ idn= ob->data;
+ strncpy(str, idn->name, 2);
+ str[2]= 0;
+ uiBlockSetCol(block, BUTGREEN);
+ uiDefButS(block, TOGN|BIT|(ob->actcol-1), B_MATFROM, str, 380, 195, 33, 20, &ob->colbits, 0, 0, 0, 0, "Show the block the material is linked to");
+ uiBlockSetCol(block, BUTGREY);
+
+ /* id is het blok waarvan materiaal wordt gepakt */
+ if( BTST(ob->colbits, ob->actcol-1) ) id= (ID *)ob;
+ else id= ob->data;
+
+ sprintf(str, "%d Mat", ob->totcol);
+ if(ob->totcol) min= 1.0; else min= 0.0;
+ uiDefButC(block, NUM, B_ACTCOL, str, 415,195,140,20, &(ob->actcol), min, (float)ob->totcol, 0, 0, "Number of materials on object / Active material");
+
+ uiSetButLock(id->lib!=0, "Can't edit library data");
+
+ strncpy(str, id->name, 2);
+ str[2]= ':'; str[3]= 0;
+ but= uiDefBut(block, TEX, B_IDNAME, str, 200,195,140,20, id->name+2, 0.0, 18.0, 0, 0, "Show the block the material is linked to");
+ uiButSetFunc(but, test_idbutton_cb, id->name, NULL);
+
+ if(ob->totcol==0) {
+ uiDrawBlock(block);
+ return;
+ }
+
+ ma= give_current_material(ob, ob->actcol);
+
+ if(ma==0) {
+ uiDrawBlock(block);
+ return;
+ }
+ uiSetButLock(ma->id.lib!=0, "Can't edit library data");
+
+ uiBlockSetCol(block, BUTGREY);
+ uiDefButS(block, ROW, REDRAWBUTSMAT, "RGB", 200,166,44,22, &(ma->colormodel), 1.0, (float)MA_RGB, 0, 0, "Create colour by red, green and blue");
+ uiDefButS(block, ROW, REDRAWBUTSMAT, "HSV", 200,143,44,22, &(ma->colormodel), 1.0, (float)MA_HSV, 0, 0, "Mix colour with hue, saturation and value");
+ uiDefButS(block, TOG|BIT|0, REDRAWBUTSMAT, "DYN", 200,120,44,22, &(ma->dynamode), 0.0, 0.0, 0, 0, "Adjust parameters for dynamics options");
+
+ if((ma->mode & MA_HALO)==0)
+ uiDefButF(block, NUM, 0, "Zoffset:", 200,91,174,19, &(ma->zoffs), 0.0, 10.0, 0, 0, "Give face an artificial offset");
+
+ if(ma->dynamode & MA_DRAW_DYNABUTS) {
+ uiDefButF(block, NUMSLI, 0, "Restitut ", 380,168,175,21, &ma->reflect, 0.0, 1.0, 0, 0, "Elasticity of collisions");
+ uiDefButF(block, NUMSLI, 0, "Friction ",
+ 380,144,175,21, &ma->friction, 0.0, 100.0, 0, 0,
+ "Coulomb friction coefficient");
+/**/
+ uiDefButF(block, NUMSLI, 0, "Fh Force ", 380,120,175,21, &ma->fh, 0.0, 1.0, 0, 0, "Upward spring force within the Fh area");
+ uiDefButF(block, NUM, 0, "Fh Damp ", 260,144,120,21, &ma->xyfrict, 0.0, 1.0, 10, 0, "Damping of the Fh spring force");
+ uiDefButF(block, NUM, 0, "Fh Dist ", 260,120,120,21, &ma->fhdist, 0.0, 20.0, 10, 0, "Height of the Fh area");
+ uiBlockSetCol(block, BUTGREEN);
+ uiDefButS(block, TOG|BIT|1, 0, "Fh Norm", 260,168,120,21, &ma->dynamode, 0.0, 0.0, 0, 0, "Add a horizontal spring force on slopes");
+ uiBlockSetCol(block, BUTGREY);
+ }
+ else {
+ uiDefButF(block, COL, B_MIRCOL, "", 246,143,37,45, &(ma->mirr), 0, 0, 0, 0, "");
+ uiDefButF(block, COL, B_SPECCOL, "", 287,143,37,45, &(ma->specr), 0, 0, 0, 0, "");
+ uiDefButF(block, COL, B_MATCOL, "", 326,143,47,45, &(ma->r), 0, 0, 0, 0, "");
+
+ if(ma->mode & MA_HALO) {
+ uiDefButC(block, ROW, REDRAWBUTSMAT, "Ring", 246,120,37,22, &(ma->rgbsel), 2.0, 2.0, 0, 0, "Mix the colour of the rings with the RGB sliders");
+ uiDefButC(block, ROW, REDRAWBUTSMAT, "Line", 287,120,37,22, &(ma->rgbsel), 2.0, 1.0, 0, 0, "Mix the colour of the lines with the RGB sliders");
+ uiDefButC(block, ROW, REDRAWBUTSMAT, "Halo", 326,120,47,22, &(ma->rgbsel), 2.0, 0.0, 0, 0, "Mix the colour of the halo with the RGB sliders");
+ }
+ else {
+ uiDefButC(block, ROW, REDRAWBUTSMAT, "Mir", 246,120,37,22, &(ma->rgbsel), 2.0, 2.0, 0, 0, "Use mirror colour");
+ uiDefButC(block, ROW, REDRAWBUTSMAT, "Spec", 287,120,37,22, &(ma->rgbsel), 2.0, 1.0, 0, 0, "Set the colour of the specularity");
+ uiDefButC(block, ROW, REDRAWBUTSMAT, "Color", 326,120,47,22, &(ma->rgbsel), 2.0, 0.0, 0, 0, "Set the basic colour of the material");
+ }
+ if(ma->rgbsel==0) {colpoin= &(ma->r); rgbsel= B_MATCOL;}
+ else if(ma->rgbsel==1) {colpoin= &(ma->specr); rgbsel= B_SPECCOL;}
+ else if(ma->rgbsel==2) {colpoin= &(ma->mirr); rgbsel= B_MIRCOL;}
+
+ if(ma->rgbsel==0 && (ma->mode & (MA_VERTEXCOLP|MA_FACETEXTURE) && !(ma->mode & MA_HALO)));
+ else if(ma->colormodel==MA_HSV) {
+ uiBlockSetCol(block, BUTPURPLE);
+ uiDefButF(block, HSVSLI, B_MATPRV, "H ", 380,168,175,21, colpoin, 0.0, 0.9999, rgbsel, 0, "");
+ uiBlockSetCol(block, BUTPURPLE);
+ uiDefButF(block, HSVSLI, B_MATPRV, "S ", 380,144,175,21, colpoin, 0.0001, 1.0, rgbsel, 0, "");
+ uiBlockSetCol(block, BUTPURPLE);
+ uiDefButF(block, HSVSLI, B_MATPRV, "V ", 380,120,175,21, colpoin, 0.0001, 1.0, rgbsel, 0, "");
+ uiBlockSetCol(block, BUTGREY);
+ }
+ else {
+ uiDefButF(block, NUMSLI, B_MATPRV, "R ", 380,168,175,21, colpoin, 0.0, 1.0, rgbsel, 0, "");
+ uiDefButF(block, NUMSLI, B_MATPRV, "G ", 380,144,175,21, colpoin+1, 0.0, 1.0, rgbsel, 0, "");
+ uiDefButF(block, NUMSLI, B_MATPRV, "B ", 380,120,175,21, colpoin+2, 0.0, 1.0, rgbsel, 0, "");
+ }
+ }
+ if(ma->mode & MA_HALO) {
+ uiDefButF(block, NUM, B_MATPRV, "HaloSize: ", 200,70,175,18, &(ma->hasize), 0.0, 100.0, 10, 0, "Set the dimension of the halo");
+ uiDefButF(block, NUMSLI, B_MATPRV, "Alpha ", 200,50,175,18, &(ma->alpha), 0.0, 1.0, 0, 0, "Set the degree of coverage");
+ uiDefButS(block, NUMSLI, B_MATPRV, "Hard ", 200,30,175,18, &(ma->har), 1.0, 127.0, 0, 0, "Set the hardness of the halo");
+ uiDefButF(block, NUMSLI, B_MATPRV, "Add ", 200,10,175,18, &(ma->add), 0.0, 1.0, 0, 0, "Strength of the add effect");
+
+ uiDefButS(block, NUM, B_MATPRV, "Rings: ", 380,90,85,18, &(ma->ringc), 0.0, 24.0, 0, 0, "Set the number of rings rendered over the basic halo");
+ uiDefButS(block, NUM, B_MATPRV, "Lines: ", 465,90,90,18, &(ma->linec), 0.0, 250.0, 0, 0, "Set the number of star shaped lines rendered over the halo");
+ uiDefButS(block, NUM, B_MATPRV, "Star: ", 380,70,85,18, &(ma->starc), 3.0, 50.0, 0, 0, "Set the number of points on the star shaped halo");
+ uiDefButC(block, NUM, B_MATPRV, "Seed: ", 465,70,90,18, &(ma->seed1), 0.0, 255.0, 0, 0, "Use random values for ring dimension and line location");
+
+ uiDefButF(block, NUM, B_MATPRV, "FlareSize: ", 380,50,85,18, &(ma->flaresize), 0.1, 25.0, 10, 0, "Set the factor the flare is larger than the halo");
+ uiDefButF(block, NUM, B_MATPRV, "Sub Size: ", 465,50,90,18, &(ma->subsize), 0.1, 25.0, 10, 0, "Set the dimension of the subflares, dots and circles");
+ uiDefButF(block, NUM, B_MATPRV, "FlareBoost: ", 380,30,175,18, &(ma->flareboost), 0.1, 10.0, 10, 0, "Give the flare extra strength");
+ uiDefButC(block, NUM, B_MATPRV, "Fl.seed: ", 380,10,85,18, &(ma->seed2), 0.0, 255.0, 0, 0, "Specify an offset in the seed table");
+ uiDefButS(block, NUM, B_MATPRV, "Flares: ", 465,10,90,18, &(ma->flarec), 1.0, 32.0, 0, 0, "Set the nuber of subflares");
+
+ uiBlockSetCol(block, BUTBLUE);
+
+ uiDefButI(block, TOG|BIT|15, B_MATPRV, "Flare", 571, 181, 77, 36, &(ma->mode), 0, 0, 0, 0, "Render halo as a lensflare");
+ uiDefButI(block, TOG|BIT|8, B_MATPRV, "Rings", 571, 143, 77, 18, &(ma->mode), 0, 0, 0, 0, "Render rings over basic halo");
+ uiDefButI(block, TOG|BIT|9, B_MATPRV, "Lines", 571, 124, 77, 18, &(ma->mode), 0, 0, 0, 0, "Render star shaped lines over the basic halo");
+ uiDefButI(block, TOG|BIT|11, B_MATPRV, "Star", 571, 105, 77, 18, &(ma->mode), 0, 0, 0, 0, "Render halo as a star");
+ uiDefButI(block, TOG|BIT|5, B_MATPRV_DRAW, "Halo", 571, 86, 77, 18, &(ma->mode), 0, 0, 0, 0, "Render as a halo");
+
+ uiDefButI(block, TOG|BIT|12, B_MATPRV, "HaloTex", 571, 67, 77, 18, &(ma->mode), 0, 0, 0, 0, "Give halo a texture");
+ uiDefButI(block, TOG|BIT|13, B_MATPRV, "HaloPuno", 571, 48, 77, 18, &(ma->mode), 0, 0, 0, 0, "Use the vertex normal to specify the dimension of the halo");
+ uiDefButI(block, TOG|BIT|10, B_MATPRV, "X Alpha", 571, 28, 77, 18, &(ma->mode), 0, 0, 0, 0, "Use extreme alpha");
+ uiDefButI(block, TOG|BIT|14, B_MATPRV, "Shaded", 571, 10, 77, 18, &(ma->mode), 0, 0, 0, 0, "Let halo receive light");
+ }
+ else {
+ uiDefButF(block, NUMSLI, B_MATPRV, "Spec ", 200,70,175,18, &(ma->spec), 0.0, 2.0, 0, 0, "Set the degree of specularity");
+ uiDefButS(block, NUMSLI, B_MATPRV, "Hard ", 200,50,175,18, &(ma->har), 1.0, 255.0, 0, 0, "Set the hardness of the specularity");
+ uiDefButF(block, NUMSLI, B_MATPRV, "SpTr ", 200,30,175,18, &(ma->spectra), 0.0, 1.0, 0, 0, "Make sheen areas opaque");
+ uiDefButF(block, NUMSLI, B_MATPRV, "Add ", 200,10,175,18, &(ma->add), 0.0, 1.0, 0, 0, "Glow factor");
+
+ uiDefButF(block, NUMSLI, B_MATPRV, "Ref ", 380,70,175,18, &(ma->ref), 0.0, 1.0, 0, 0, "Set the amount of reflection");
+ uiDefButF(block, NUMSLI, B_MATPRV, "Alpha ", 380,50,175,18, &(ma->alpha), 0.0, 1.0, 0, 0, "Set the amount of coverage, to make materials transparent");
+ uiDefButF(block, NUMSLI, B_MATPRV, "Emit ", 380,30,175,18, &(ma->emit), 0.0, 1.0, 0, 0, "Set the amount of emitting light");
+ uiDefButF(block, NUMSLI, B_MATPRV, "Amb ", 380,10,175,18, &(ma->amb), 0.0, 1.0, 0, 0, "Set the amount of global ambient color");
+ /* transparent solids : exponential dropoff */
+/* uiDefButF(block, NUMSLI, B_MATPRV, "K ", 380,-10,175,18, &(ma->kfac), 0.0, 10.0, 0, 0, ""); */
+
+ uiBlockSetCol(block, BUTBLUE);
+
+ uiDefButI(block, TOG|BIT|0, 0, "Traceable", 571,200,77,18, &(ma->mode), 0, 0, 0, 0, "Make material visible for shadow lamps");
+ uiDefButI(block, TOG|BIT|1, 0, "Shadow", 571,181,77,18, &(ma->mode), 0, 0, 0, 0, "Enable material for shadows");
+ uiDefButI(block, TOG|BIT|2, B_MATPRV, "Shadeless", 571, 162, 77, 18, &(ma->mode), 0, 0, 0, 0, "Make material insensitive to light or shadow");
+ uiDefButI(block, TOG|BIT|3, 0, "Wire", 571, 143, 77, 18, &(ma->mode), 0, 0, 0, 0, "Render only the edges of faces");
+ uiDefButI(block, TOG|BIT|4, B_REDR, "VCol Light", 571, 124, 77, 18, &(ma->mode), 0, 0, 0, 0, "Add vertex colours as extra light");
+ uiDefButI(block, TOG|BIT|7, B_REDR, "VCol Paint", 571,105, 77, 18, &(ma->mode), 0, 0, 0, 0, "Replace basic colours with vertex colours");
+ uiDefButI(block, TOG|BIT|5, B_MATPRV_DRAW, "Halo",571, 86, 77, 18, &(ma->mode), 0, 0, 0, 0, "Render as a halo");
+ uiDefButI(block, TOG|BIT|6, 0, "ZTransp", 571, 67, 77, 18, &(ma->mode), 0, 0, 0, 0, "Z-Buffer transparent faces");
+ uiDefButI(block, TOG|BIT|8, 0, "ZInvert", 571, 48, 77, 18, &(ma->mode), 0, 0, 0, 0, "Render with inverted Z Buffer");
+ uiDefButI(block, TOG|BIT|9, 0, "Env", 571, 29, 77, 18, &(ma->mode), 0, 0, 0, 0, "Do not render material");
+ uiDefButI(block, TOG|BIT|10, 0, "OnlyShadow", 571, 10, 77, 18, &(ma->mode), 0, 0, 0, 0, "Let alpha be determined on the degree of shadow");
+ /* transparent solids */
+/* uiDefButI(block, TOG|BIT|0, 0, "Transp", 571,-10, 77, 18, &(ma->mode2), 0, 0, 0, 0, ""); */
+
+ uiDefButI(block, TOG|BIT|14, 0, "No Mist", 477,95,77,18, &(ma->mode), 0, 0, 0, 0, "Set the material insensitive to mist");
+ uiDefButI(block, TOG|BIT|11, B_REDR, "TexFace", 398,95,77,18, &(ma->mode), 0, 0, 0, 0, "UV-Editor assigned texture gives color and texture info for the faces");
+ }
+ /* PREVIEW RENDER */
+
+ BIF_previewdraw(G.buts);
+
+ uiDefIconButC(block, ROW, B_MATPRV, ICON_MATPLANE, 10,195,25,20, &(ma->pr_type), 10, 0, 0, 0, "");
+ uiDefIconButC(block, ROW, B_MATPRV, ICON_MATSPHERE, 35,195,25,20, &(ma->pr_type), 10, 1, 0, 0, "");
+ uiDefIconButC(block, ROW, B_MATPRV, ICON_MATCUBE, 60,195,25,20, &(ma->pr_type), 10, 2, 0, 0, "");
+
+ uiDefIconButS(block, ICONTOG|BIT|0, B_MATPRV, ICON_TRANSP_HLT, 95,195,25,20, &(ma->pr_back), 0, 0, 0, 0, "");
+
+ uiDefIconBut(block, BUT, B_MATPRV, ICON_EYE, 159,195,30,20, 0, 0, 0, 0, 0, "");
+
+ /* TEX CHANNELS */
+ uiBlockSetCol(block, BUTGREY);
+ xco= 665;
+ for(a= 0; a<8; a++) {
+ mtex= ma->mtex[a];
+ if(mtex && mtex->tex) splitIDname(mtex->tex->id.name+2, str, &loos);
+ else strcpy(str, "");
+ str[10]= 0;
+ uiDefButC(block, ROW, B_MATPRV_DRAW, str, xco, 195, 63, 20, &(ma->texact), 3.0, (float)a, 0, 0, "");
+ xco+= 65;
+ }
+
+ uiDefIconBut(block, BUT, B_MTEXCOPY, ICON_COPYUP, (short)xco,195,20,21, 0, 0, 0, 0, 0, "Copy the material settings to the buffer");
+ uiDefIconBut(block, BUT, B_MTEXPASTE, ICON_PASTEUP, (short)(xco+20),195,20,21, 0, 0, 0, 0, 0, "Paste the material settings from the buffer");
+
+
+ uiBlockSetCol(block, BUTGREEN);
+ uiDefButC(block, TOG, B_MATPRV, "SepT", (short)(xco+40), 195, 40, 20, &(ma->septex), 0, 0, 0, 0, "Render only use active texture channel");
+ uiBlockSetCol(block, BUTGREY);
+
+ mtex= ma->mtex[ ma->texact ];
+ if(mtex==0) {
+ mtex= &emptytex;
+ default_mtex(mtex);
+ }
+
+ /* TEXCO */
+ uiBlockSetCol(block, BUTGREEN);
+ uiDefButS(block, ROW, B_MATPRV, "Object", 694,166,49,18, &(mtex->texco), 4.0, (float)TEXCO_OBJECT, 0, 0, "Use linked object's coordinates for texture coordinates");
+ uiDefIDPoinBut(block, test_obpoin_but, B_MATPRV, "", 745,166,133,18, &(mtex->object), "");
+ uiDefButS(block, ROW, B_MATPRV, "UV", 664,166,29,18, &(mtex->texco), 4.0, (float)TEXCO_UV, 0, 0, "Use UV coordinates for texture coordinates");
+
+ uiDefButS(block, ROW, B_MATPRV, "Glob", 665,146,35,18, &(mtex->texco), 4.0, (float)TEXCO_GLOB, 0, 0, "Use global coordinates for the texture coordinates");
+ uiDefButS(block, ROW, B_MATPRV, "Orco", 701,146,38,18, &(mtex->texco), 4.0, (float)TEXCO_ORCO, 0, 0, "Use the original coordinates of the mesh");
+ uiDefButS(block, ROW, B_MATPRV, "Stick", 739,146,38,18, &(mtex->texco), 4.0, (float)TEXCO_STICKY, 0, 0, "Use mesh sticky coordaintes for the texture coordinates");
+ uiDefButS(block, ROW, B_MATPRV, "Win", 779,146,31,18, &(mtex->texco), 4.0, (float)TEXCO_WINDOW, 0, 0, "Use screen coordinates as texture coordinates");
+ uiDefButS(block, ROW, B_MATPRV, "Nor", 811,146,32,18, &(mtex->texco), 4.0, (float)TEXCO_NORM, 0, 0, "Use normal vector as texture coordinates");
+ uiDefButS(block, ROW, B_MATPRV, "Refl", 844,146,33,18, &(mtex->texco), 4.0, (float)TEXCO_REFL, 0, 0, "Use reflection vector as texture coordinates");
+
+ uiBlockSetCol(block, BUTGREY);
+
+ /* COORDS */
+ uiDefButC(block, ROW, B_MATPRV, "Flat", 666,114,48,18, &(mtex->mapping), 5.0, (float)MTEX_FLAT, 0, 0, "Map X and Y coordinates directly");
+ uiDefButC(block, ROW, B_MATPRV, "Cube", 717,114,50,18, &(mtex->mapping), 5.0, (float)MTEX_CUBE, 0, 0, "Map using the normal vector");
+ uiDefButC(block, ROW, B_MATPRV, "Tube", 666,94,48,18, &(mtex->mapping), 5.0, (float)MTEX_TUBE, 0, 0, "Map with Z as central axis (tube-like)");
+ uiDefButC(block, ROW, B_MATPRV, "Sphe", 716,94,50,18, &(mtex->mapping), 5.0, (float)MTEX_SPHERE, 0, 0, "Map with Z as central axis (sphere-like)");
+
+ xco= 665;
+ for(a=0; a<4; a++) {
+ if(a==0) strcpy(str, "");
+ else if(a==1) strcpy(str, "X");
+ else if(a==2) strcpy(str, "Y");
+ else strcpy(str, "Z");
+
+ uiDefButC(block, ROW, B_MATPRV, str, (short)xco, 50, 24, 18, &(mtex->projx), 6.0, (float)a, 0, 0, "");
+ uiDefButC(block, ROW, B_MATPRV, str, (short)xco, 30, 24, 18, &(mtex->projy), 7.0, (float)a, 0, 0, "");
+ uiDefButC(block, ROW, B_MATPRV, str, (short)xco, 10, 24, 18, &(mtex->projz), 8.0, (float)a, 0, 0, "");
+ xco+= 26;
+ }
+
+ uiDefButF(block, NUM, B_MATPRV, "ofsX", 778,114,100,18, mtex->ofs, -10.0, 10.0, 10, 0, "Fine tune X coordinate");
+ uiDefButF(block, NUM, B_MATPRV, "ofsY", 778,94,100,18, mtex->ofs+1, -10.0, 10.0, 10, 0, "Fine tune Y coordinate");
+ uiDefButF(block, NUM, B_MATPRV, "ofsZ", 778,74,100,18, mtex->ofs+2, -10.0, 10.0, 10, 0, "Fine tune Z coordinate");
+ uiDefButF(block, NUM, B_MATPRV, "sizeX", 778,50,100,18, mtex->size, -100.0, 100.0, 10, 0, "Set an extra scaling for the texture coordinate");
+ uiDefButF(block, NUM, B_MATPRV, "sizeY", 778,30,100,18, mtex->size+1, -100.0, 100.0, 10, 0, "Set an extra scaling for the texture coordinate");
+ uiDefButF(block, NUM, B_MATPRV, "sizeZ", 778,10,100,18, mtex->size+2, -100.0, 100.0, 10, 0, "Set an extra scaling for the texture coordinate");
+
+ /* TEXTUREBLOK SELECT */
+ if(G.main->tex.first==0)
+ id= NULL;
+ else
+ id= (ID*) mtex->tex;
+ IDnames_to_pupstring(&strp, NULL, "ADD NEW %x32767", &(G.main->tex), id, &(G.buts->texnr));
+ uiDefButS(block, MENU, B_EXTEXBROWSE, strp, 900,146,20,19, &(G.buts->texnr), 0, 0, 0, 0, "The name of the texture");
+ MEM_freeN(strp);
+
+ if(id) {
+ uiDefBut(block, TEX, B_IDNAME, "TE:", 900,166,163,19, id->name+2, 0.0, 18.0, 0, 0, "The name of the texture block");
+ sprintf(str, "%d", id->us);
+ uiDefBut(block, BUT, 0, str, 996,146,21,19, 0, 0, 0, 0, 0, "");
+ uiDefIconBut(block, BUT, B_AUTOTEXNAME, ICON_AUTO, 1041,146,21,19, 0, 0, 0, 0, 0, "Auto-assign name to texture");
+ if(id->lib) {
+ if(ma->id.lib) uiDefIconBut(block, BUT, 0, ICON_DATALIB, 1019,146,21,19, 0, 0, 0, 0, 0, "");
+ else uiDefIconBut(block, BUT, 0, ICON_PARLIB, 1019,146,21,19, 0, 0, 0, 0, 0, "");
+ }
+ uiBlockSetCol(block, BUTSALMON);
+ uiDefBut(block, BUT, B_TEXCLEAR, "Clear", 922, 146, 72, 19, 0, 0, 0, 0, 0, "Erase link to datablock");
+ uiBlockSetCol(block, BUTGREY);
+ }
+
+ /* TEXTURE OUTPUT */
+ uiDefButS(block, TOG|BIT|1, B_MATPRV, "Stencil", 900,114,52,18, &(mtex->texflag), 0, 0, 0, 0, "Set the mapping to stencil mode");
+ uiDefButS(block, TOG|BIT|2, B_MATPRV, "Neg", 954,114,38,18, &(mtex->texflag), 0, 0, 0, 0, "Reverse the effect of the texture");
+ uiDefButS(block, TOG|BIT|0, B_MATPRV, "No RGB", 994,114,69,18, &(mtex->texflag), 0, 0, 0, 0, "Use an RGB texture as an intensity texture");
+
+ uiDefButF(block, COL, B_MTEXCOL, "", 900,100,163,12, &(mtex->r), 0, 0, 0, 0, "Browse datablocks");
+
+ if(ma->colormodel==MA_HSV) {
+ uiBlockSetCol(block, BUTPURPLE);
+ uiDefButF(block, HSVSLI, B_MATPRV, "H ", 900,80,163,18, &(mtex->r), 0.0, 0.9999, B_MTEXCOL, 0, "");
+ uiBlockSetCol(block, BUTPURPLE);
+ uiDefButF(block, HSVSLI, B_MATPRV, "S ", 900,60,163,18, &(mtex->r), 0.0001, 1.0, B_MTEXCOL, 0, "");
+ uiBlockSetCol(block, BUTPURPLE);
+ uiDefButF(block, HSVSLI, B_MATPRV, "V ", 900,40,163,18, &(mtex->r), 0.0001, 1.0, B_MTEXCOL, 0, "");
+ uiBlockSetCol(block, BUTGREY);
+ }
+ else {
+ uiDefButF(block, NUMSLI, B_MATPRV, "R ", 900,80,163,18, &(mtex->r), 0.0, 1.0, B_MTEXCOL, 0, "Set the amount of red the intensity texture blends with");
+ uiDefButF(block, NUMSLI, B_MATPRV, "G ", 900,60,163,18, &(mtex->g), 0.0, 1.0, B_MTEXCOL, 0, "Set the amount of green the intensity texture blends with");
+ uiDefButF(block, NUMSLI, B_MATPRV, "B ", 900,40,163,18, &(mtex->b), 0.0, 1.0, B_MTEXCOL, 0, "Set the amount of blue the intensity texture blends with");
+ }
+
+ uiDefButF(block, NUMSLI, B_MATPRV, "DVar ", 900,10,163,18, &(mtex->def_var), 0.0, 1.0, 0, 0, "Set the value the texture blends with the current value");
+
+ /* MAP TO */
+ uiBlockSetCol(block, BUTGREEN);
+ uiDefButS(block, TOG|BIT|0, B_MATPRV, "Col", 1087,166,35,18, &(mtex->mapto), 0, 0, 0, 0, "Let the texture affect basic colour of the material");
+ uiDefButS(block, TOG3|BIT|1, B_MATPRV, "Nor", 1126,166,31,18, &(mtex->mapto), 0, 0, 0, 0, "Let the texture affect the rendered normal");
+ uiDefButS(block, TOG|BIT|2, B_MATPRV, "Csp", 1160,166,34,18, &(mtex->mapto), 0, 0, 0, 0, "Let the texture affect the specularity colour");
+ uiDefButS(block, TOG|BIT|3, B_MATPRV, "Cmir", 1196,166,35,18, &(mtex->mapto), 0, 0, 0, 0, "Let the texture affext the mirror colour");
+ uiDefButS(block, TOG3|BIT|4, B_MATPRV, "Ref", 1234,166,31,18, &(mtex->mapto), 0, 0, 0, 0, "Let the texture affect the value of the materials reflectivity");
+ uiDefButS(block, TOG3|BIT|5, B_MATPRV, "Spec", 1087,146,36,18, &(mtex->mapto), 0, 0, 0, 0, "Let the texture affect the value of specularity");
+ uiDefButS(block, TOG3|BIT|8, B_MATPRV, "Hard", 1126,146,44,18, &(mtex->mapto), 0, 0, 0, 0, "Let the texture affect the hardness value");
+ uiDefButS(block, TOG3|BIT|7, B_MATPRV, "Alpha", 1172,146,45,18, &(mtex->mapto), 0, 0, 0, 0, "Let the texture affect the alpha value");
+ uiDefButS(block, TOG3|BIT|6, B_MATPRV, "Emit", 1220,146,45,18, &(mtex->mapto), 0, 0, 0, 0, "Let the texture affect the emit value");
+
+/* uiDefButS(block, TOG|BIT|3, B_MATPRV, "Alpha Mix",1087,114,100,18, &(mtex->texflag), 0, 0, 0, 0); ,""*/
+
+ uiBlockSetCol(block, BUTGREY);
+ uiDefButS(block, ROW, B_MATPRV, "Mix", 1087,94,48,18, &(mtex->blendtype), 9.0, (float)MTEX_BLEND, 0, 0, "The texture blends the values or colour");
+ uiDefButS(block, ROW, B_MATPRV, "Mul", 1136,94,44,18, &(mtex->blendtype), 9.0, (float)MTEX_MUL, 0, 0, "The texture multiplies the values or colour");
+ uiDefButS(block, ROW, B_MATPRV, "Add", 1182,94,41,18, &(mtex->blendtype), 9.0, (float)MTEX_ADD, 0, 0, "The texture adds the values or colour");
+ uiDefButS(block, ROW, B_MATPRV, "Sub", 1226,94,40,18, &(mtex->blendtype), 9.0, (float)MTEX_SUB, 0, 0, "The texture subtracts the values or colour");
+
+ uiDefButF(block, NUMSLI, B_MATPRV, "Col ", 1087,50,179,18, &(mtex->colfac), 0.0, 1.0, 0, 0, "Set the amount the texture affects colour");
+ uiDefButF(block, NUMSLI, B_MATPRV, "Nor ", 1087,30,179,18, &(mtex->norfac), 0.0, 5.0, 0, 0, "Set the amount the texture affects the normal");
+ uiDefButF(block, NUMSLI, B_MATPRV, "Var ", 1087,10,179,18, &(mtex->varfac), 0.0, 1.0, 0, 0, "Set the amount the texture affects a value");
+
+ uiDrawBlock(block);
+}
+
+
+/* ************************ SOUND *************************** */
+static void load_new_sample(char *str) /* called from fileselect */
+{
+ char name[FILE_MAXDIR+FILE_MAXFILE];
+ bSound *sound;
+ bSample *sample, *newsample;
+
+ sound = G.buts->lockpoin;
+
+ if (sound) {
+ // save values
+ sample = sound->sample;
+ strcpy(name, sound->sample->name);
+
+ strcpy(sound->name, str);
+ sound_set_sample(sound, NULL);
+ sound_initialize_sample(sound);
+
+ if (sound->sample->type == SAMPLE_INVALID) {
+ error("Not a valid sample: %s", str);
+
+ newsample = sound->sample;
+
+ // restore values
+ strcpy(sound->name, name);
+ sound_set_sample(sound, sample);
+
+ // remove invalid sample
+
+ sound_free_sample(newsample);
+ BLI_remlink(samples, newsample);
+ MEM_freeN(newsample);
+ }
+ }
+
+ allqueue(REDRAWBUTSSOUND, 0);
+ if (curarea) BIF_preview_changed(G.buts);
+}
+
+
+void do_soundbuts(unsigned short event)
+{
+ char name[FILE_MAXDIR+FILE_MAXFILE];
+ bSound *sound;
+ bSample *sample;
+ bSound* tempsound;
+ ID *id;
+
+ sound = G.buts->lockpoin;
+
+ switch(event)
+ {
+ case B_SOUND_REDRAW:
+ {
+ allqueue(REDRAWBUTSSOUND, 0);
+ break;
+ }
+ case B_SOUND_LOAD_SAMPLE:
+ {
+ if (sound) strcpy(name, sound->name);
+ else strcpy(name, U.sounddir);
+
+ activate_fileselect(FILE_SPECIAL, "SELECT WAV FILE", name, load_new_sample);
+ break;
+ }
+ case B_SOUND_PLAY_SAMPLE:
+ {
+ if (sound)
+ {
+ if (sound->sample->type != SAMPLE_INVALID)
+ {
+ sound_play_sound(sound);
+ allqueue(REDRAWBUTSSOUND, 0);
+ }
+ }
+ break;
+ }
+ case B_SOUND_MENU_SAMPLE:
+ {
+ if (G.buts->menunr == -2) {
+ if (sound) {
+ activate_databrowse((ID *)sound->sample, ID_SAMPLE, 0, B_SOUND_MENU_SAMPLE, &G.buts->menunr, do_soundbuts);
+ }
+ } else if (G.buts->menunr > 0) {
+ sample = BLI_findlink(samples, G.buts->menunr - 1);
+ if (sample && sound) {
+ BLI_strncpy(sound->name, sample->name, sizeof(sound->name));
+ sound_set_sample(sound, sample);
+ do_soundbuts(B_SOUND_REDRAW);
+ }
+ }
+
+ break;
+ }
+ case B_SOUND_NAME_SAMPLE:
+ {
+ load_new_sample(sound->name);
+ break;
+ }
+ case B_SOUND_UNPACK_SAMPLE:
+ if(sound && sound->sample) {
+ sample = sound->sample;
+
+ if (sample->packedfile) {
+ if (G.fileflags & G_AUTOPACK) {
+ if (okee("Disable AutoPack ?")) {
+ G.fileflags &= ~G_AUTOPACK;
+ }
+ }
+
+ if ((G.fileflags & G_AUTOPACK) == 0) {
+ unpackSample(sample, PF_ASK);
+ }
+ } else {
+ sound_set_packedfile(sample, newPackedFile(sample->name));
+ }
+ allqueue(REDRAWHEADERS, 0);
+ do_soundbuts(B_SOUND_REDRAW);
+ }
+ break;
+ case B_SOUND_COPY_SOUND:
+ {
+ if (sound)
+ {
+ tempsound = sound_make_copy(sound);
+ sound = tempsound;
+ id = &sound->id;
+ G.buts->lockpoin = (bSound*)id;
+ do_soundbuts(B_SOUND_REDRAW);
+ }
+ break;
+ }
+ case B_SOUND_LOOPSTART:
+ {
+#ifdef SOUND_UNDER_DEVELOPMENT
+/* if (sound->loopstart > sound->loopend)
+ sound->loopstart = sound->loopend;*/
+#endif
+ allqueue(REDRAWBUTSSOUND, 0);
+ BIF_preview_changed(G.buts);
+ break;
+ }
+ case B_SOUND_LOOPEND:
+ {
+#ifdef SOUND_UNDER_DEVELOPMENT
+/* if (sound->loopend < sound->loopstart)
+ sound->loopend = sound->loopstart;*/
+#endif
+ allqueue(REDRAWBUTSSOUND, 0);
+ BIF_preview_changed(G.buts);
+ break;
+ }
+
+ default:
+ {
+ if (G.f & G_DEBUG)
+ {
+ printf("do_soundbuts: unhandled event %d\n", event);
+ }
+ break;
+ }
+ }
+}
+
+
+void soundbuts(void)
+{
+ short xco, yco, xcostart = 20;
+ bSound *sound;
+ bSample *sample;
+ uiBlock *block;
+ char *strp, str[32];
+ ID *id;
+ char ch[20];
+ char sampleinfo[200];
+ char mixrateinfo[50];
+ int mixrate;
+
+ sound = G.buts->lockpoin;
+ yco = 195;
+
+ if (sound)
+ {
+ sound_initialize_sample(sound);
+
+ sample = sound->sample;
+
+ xco = xcostart;
+ sprintf(str, "buttonswin %d", curarea->win);
+ block= uiNewBlock(&curarea->uiblocks, str, UI_EMBOSSX, UI_HELV, curarea->win);
+
+ uiSetButLock(sound->id.lib!=0, "Can't edit library data");
+
+ /* sound settings ------------------------------------------------------------------ */
+
+ uiDefBut(block, LABEL, 0, "Sound settings:",xco,yco,195,20, 0, 0, 0, 0, 0, "");
+
+ yco -= 30;
+ uiBlockSetCol(block, BUTGREEN);
+ uiDefBut(block, BUT, B_SOUND_PLAY_SAMPLE, "Play", xco, yco, 195, 24, 0, 0.0, 0, 0, 0,
+ "Playback sample using settings below");
+
+ uiBlockSetCol(block, BUTGREY);
+ xco += 225;
+
+ if (sound->sample && sound->sample->len)
+ {
+ if (sound->sample->channels == 1)
+ strcpy(ch, "Mono");
+ else if (sound->sample->channels == 2)
+ strcpy(ch, "Stereo");
+ else
+ strcpy(ch, "Unknown");
+
+ uiDefBut(block, LABEL, 0, "Sample: ",xco,yco,195,20, 0, 0, 0, 0, 0, "");
+ xco +=55;
+ sprintf(sampleinfo, "%s, %d bit, %d Hz, %d samples", ch, sound->sample->bits, sound->sample->rate, sound->sample->len);
+ uiDefBut(block, LABEL, 0, sampleinfo,xco,yco,295,20, 0, 0, 0, 0, 0, "");
+ }
+ else
+ {
+ uiDefBut(block, LABEL, 0, "No sample info available.",xco,yco,195,20, 0, 0, 0, 0, 0, "");
+ xco +=55;
+ }
+
+ xco += 314;
+ uiDefBut(block, BUT, B_SOUND_COPY_SOUND, "Copy sound",
+ xco,yco,95,24, 0, 0, 0, 0, 0, "Make a copy of the current sound");
+ /*
+ xco += 25;
+ if (sample->channels > 1)
+ {
+ xco += 100;
+ uiDefButC(block, ROW, B_SOUND_REDRAW, "Left", xco, yco, 95, 20, &sound->channels, 1.0, (float)SOUND_CHANNELS_LEFT, 0, 0, "");
+ xco += 100;
+ uiDefButC(block, ROW, B_SOUND_REDRAW, "Stereo", xco, yco, 95, 20, &sound->channels, 1.0, (float)SOUND_CHANNELS_STEREO, 0, 0, "");
+ xco += 100;
+ uiDefButC(block, ROW, B_SOUND_REDRAW, "Right", xco, yco, 95, 20, &sound->channels, 1.0, (float)SOUND_CHANNELS_RIGHT, 0, 0, "");
+ }
+ */
+
+ xco = xcostart;
+ yco -= 30;
+ uiDefBut(block, BUT, B_SOUND_LOAD_SAMPLE, "Load sample",
+ xco, yco,195,24, 0, 0, 0, 0, 0, "Load a different sample");
+
+ uiBlockSetCol(block, BUTGREY);
+
+ id= (ID *)sound->sample;
+ IDnames_to_pupstring(&strp, NULL, NULL, samples, id, &(G.buts->menunr));
+ if (strp[0]) {
+ xco += 200;
+ uiDefButS(block, MENU, B_SOUND_MENU_SAMPLE, strp,xco,yco,23,24, &(G.buts->menunr), 0, 0, 0, 0, "Select another loaded sample");
+ }
+ MEM_freeN(strp);
+
+ xco += 25;
+ uiDefBut(block, TEX, B_SOUND_NAME_SAMPLE, "",xco,yco,412,24, sound->name, 0.0, 79.0, 0, 0, "The sample used by this sound");
+
+ sprintf(str, "1");
+ // sprintf(str, "%d", tex->ima->id.us);
+ xco += 415;
+ uiDefBut(block, BUT, B_SOUND_UNLINK_SAMPLE, str,xco,yco,23,24, 0, 0, 0, 0, 0, "The number of users");
+
+ if (sound->sample->packedfile)
+ packdummy = 1;
+ else
+ packdummy = 0;
+
+ xco += 25;
+ uiDefIconButI(block, TOG|BIT|0, B_SOUND_UNPACK_SAMPLE, ICON_PACKAGE,
+ xco, yco,24,24, &packdummy, 0, 0, 0, 0,"Pack/Unpack this sample");
+ /*
+ xco += 25;
+ uiDefBut(block, BUT, B_SOUND_RELOAD_SAMPLE, "Reload",xco, yco,68,24, 0, 0, 0, 0, 0, "");
+ */
+ /* parameters settings ------------------------------------------------------------------ */
+
+ xco = xcostart;
+ yco -= 45;
+ uiDefBut(block, LABEL, 0, "Parameter settings:",xco,yco,195,20, 0, 0, 0, 0, 0, "");
+
+ yco -= 30;
+ uiBlockSetCol(block, BUTGREY);
+ uiDefButF(block, NUMSLI, B_SOUND_CHANGED, "Volume: ",
+ xco,yco,195,24,&sound->volume, 0.0, 1.0, 0, 0, "Set the volume of this sound");
+
+ xco += 200;
+ uiDefButF(block, NUMSLI, B_SOUND_CHANGED, "Pitch: ",
+ xco,yco,195,24,&sound->pitch, -12.0, 12.0, 0, 0, "Set the pitch of this sound");
+
+ xco = xcostart;
+ yco -= 30;
+ uiBlockSetCol(block, BUTSALMON);
+ uiDefButI(block, TOG|BIT|SOUND_FLAGS_LOOP_BIT, B_SOUND_REDRAW, "Loop",
+ xco, yco, 95, 24, &sound->flags, 0.0, 0.0, 0, 0,"Toggle between looping on/off");
+
+ if (sound->flags & SOUND_FLAGS_LOOP && LICENSE_KEY_VALID)
+ {
+ xco += 100;
+ uiDefButI(block, TOG|BIT|SOUND_FLAGS_BIDIRECTIONAL_LOOP_BIT, B_SOUND_REDRAW, "Ping Pong",
+ xco, yco, 95, 24, &sound->flags, 0.0, 0.0, 0, 0,"Toggle between A->B and A->B->A looping");
+
+#ifdef SOUND_UNDER_DEVELOPMENT
+/* uiBlockSetCol(block, REDALERT);
+ xco += 100;
+ uiDefButI(block, NUM, B_SOUND_LOOPSTART, "loopstart: ", xco,yco,195,24,
+ &sound->loopstart, 0, sound->sample->len, 0, 0, "Set the startpoint for the loop of this sound");
+
+ xco += 200;
+ uiDefButI(block, NUM, B_SOUND_LOOPEND, "loopend: ",xco,yco,195,24,
+ &sound->loopend, 0, sound->sample->len, 0, 0, "Set the endpoint for the loop of this sound");
+*/
+#endif
+ }
+
+#ifdef SOUND_UNDER_DEVELOPMENT
+ xco = xcostart;
+ yco -= 30;
+ uiDefButI(block, TOG|BIT|SOUND_FLAGS_PRIORITY_BIT, B_SOUND_REDRAW, "Priority",
+ xco, yco, 95, 24, &sound->flags, 0.0, 0.0, 0, 0,"Toggle between high and low priority");
+#endif
+
+ /* 2D & 3D settings ------------------------------------------------------------------ */
+
+ uiBlockSetCol(block, BUTGREY);
+ if (sound->sample->channels == 1)
+ {
+ xco = xcostart;
+ yco -= 30;
+ uiDefButI(block, TOG|BIT|SOUND_FLAGS_3D_BIT, B_SOUND_REDRAW, "3D Sound",
+ xco, yco, 95, 24, &sound->flags, 0, 0, 0, 0, "Turns 3D sound on");
+
+ if (sound->flags & SOUND_FLAGS_3D)
+ {
+ xco = xcostart;
+ yco -= 30;
+ uiBlockSetCol(block, BUTGREY);
+ uiDefBut(block, LABEL, 0, "3D surround settings:",xco,yco,195,20, 0, 0, 0, 0, 0, "");
+ uiDefButF(block, NUMSLI, B_SOUND_CHANGED, "Scale: ",
+ xco,(short)(yco-=30),195,24,&sound->attenuation, 0.0, 5.0, 1.0, 0, "Sets the world-scaling factor for this sound");
+
+ /*
+ xco += 200;
+ uiDefButF(block, NUMSLI, B_SOUND_CHANGED, "Distance: ",
+ xco,yco,195,20,&sound->distance, 0.0, 100.0, 1.0, 0, "Reference distance: sets the distance at which the listener will experience gain");
+ xco -= 200;
+ yco -= 30;
+ uiDefButF(block, NUMSLI, B_SOUND_CHANGED, "Minvol: ",
+ xco,yco,195,20,&sound->min_gain, 0.0, 1.0, 1.0, 0, "Minimal volume: sets the lower threshold for the gain of this sound");
+ xco += 200;
+ uiDefButF(block, NUMSLI, B_SOUND_CHANGED, "Maxvol: ",
+ xco,yco,195,20,&sound->max_gain, 0.0, 10.0, 1.0, 0, "Maximal volume: sets the upper threshold for the gain of this sound");
+ */
+ }
+ }
+
+ /* listener settings ------------------------------------------------------------------ */
+
+ draw_buttons_edge(curarea->win, 740);
+
+ xco = xcostart + 750;
+ yco = 195;
+ uiBlockSetCol(block, BUTGREY);
+ mixrate = sound_get_mixrate();
+ sprintf(mixrateinfo, "Mixrate: %d Hz", mixrate);
+ uiDefBut(block, LABEL, 0, mixrateinfo, xco,yco,295,20, 0, 0, 0, 0, 0, "");
+
+ yco -= 30;
+
+ uiDefBut(block, LABEL, 0, "Listener settings:",xco,yco,195,20, 0, 0, 0, 0, 0, "");
+
+ yco -= 30;
+ uiDefButF(block, NUMSLI, B_SOUND_CHANGED, "Volume: ",
+ xco,yco,195,24,&G.listener->gain, 0.0, 1.0, 1.0, 0, "Sets the maximum volume for the overall sound");
+
+ yco -= 30;
+ uiDefBut(block, LABEL, 0, "Doppler effect settings:",xco,yco,195,20, 0, 0, 0, 0, 0, "");
+ /*
+ yco -= 30;
+ uiDefButF(block, NUMSLI, B_SOUND_CHANGED, "Scale: ",
+ xco,yco,195,20,&G.listener->dopplerfactor, 0.0, 10.0, 1.0, 0, "Doppler scaling: sets the scaling factor for doppler effect");
+ */
+ yco -= 30;
+ uiDefButF(block, NUMSLI, B_SOUND_CHANGED, "Doppler: ",
+ xco,yco,195,24,&G.listener->dopplervelocity, 0.0, 10.0, 1.0, 0, "Use this for scaling the doppler effect");
+ /*
+ if (sound->channels != SOUND_CHANNELS_STEREO || sample->channels == 1)
+ {
+ uiBlockSetCol(block, BUTGREEN);
+ uiDefButI(block, TOGN|BIT|SOUND_FLAGS_FIXED_PANNING_BIT, B_SOUND_REDRAW, "3D pan",
+ xco, yco, 95, 20, &sound->flags, 0, 0, 0, 0, "");
+
+ uiBlockSetCol(block, BUTSALMON);
+ xco += 100;
+ uiDefButI(block, TOG|BIT|SOUND_FLAGS_FIXED_PANNING_BIT, B_SOUND_REDRAW, "Fixed",
+ xco, yco, 95, 20, &sound->flags, 0, 0, 0, 0, "");
+
+ uiBlockSetCol(block, BUTGREY);
+ if (sound->flags & SOUND_FLAGS_FIXED_PANNING)
+ {
+ xco += 100;
+ uiDefButF(block, NUMSLI, B_SOUND_CHANGED, "Pann: ",
+ xco,yco,195,20,&sound->panning, -1.0, 1.0, 0, 0, "");
+ }
+ }
+ */
+ uiDrawBlock(block);
+ }
+}
+
+/* ************************ LAMP *************************** */
+
+void do_lampbuts(unsigned short event)
+{
+ Lamp *la;
+ MTex *mtex;
+
+ switch(event) {
+ case B_LAMPREDRAW:
+ BIF_preview_changed(G.buts);
+ allqueue(REDRAWVIEW3D, 0);
+ break;
+ case B_TEXCLEARLAMP:
+ la= G.buts->lockpoin;
+ mtex= la->mtex[ la->texact ];
+ if(mtex) {
+ if(mtex->tex) mtex->tex->id.us--;
+ MEM_freeN(mtex);
+ la->mtex[ la->texact ]= 0;
+ allqueue(REDRAWBUTSLAMP, 0);
+ allqueue(REDRAWOOPS, 0);
+ BIF_preview_changed(G.buts);
+ }
+ break;
+ }
+
+ if(event) freefastshade();
+}
+
+
+void lampbuts(void)
+{
+ Object *ob;
+ Lamp *la;
+ MTex *mtex;
+ ID *id;
+ uiBlock *block;
+ float grid=0.0;
+ int loos, a;
+ char *strp, str[32];
+ short xco;
+
+ if(G.vd) grid= G.vd->grid;
+ if(grid<1.0) grid= 1.0;
+
+ ob= OBACT;
+ if(ob==0) return;
+ if(ob->type!=OB_LAMP) return;
+
+ sprintf(str, "buttonswin %d", curarea->win);
+ block= uiNewBlock(&curarea->uiblocks, str, UI_EMBOSSX, UI_HELV, curarea->win);
+
+ la= ob->data;
+ uiSetButLock(la->id.lib!=0, "Can't edit library data");
+
+ uiBlockSetCol(block, BUTGREEN);
+ uiDefButS(block, ROW,B_LAMPREDRAW,"Lamp", 317,190,61,25,&la->type,1.0,(float)LA_LOCAL, 0, 0, "Use a point light source");
+ uiDefButS(block, ROW,B_LAMPREDRAW,"Spot", 379,190,59,25,&la->type,1.0,(float)LA_SPOT, 0, 0, "Restrict lamp to conical space");
+ uiDefButS(block, ROW,B_LAMPREDRAW,"Sun", 439,190,58,25,&la->type,1.0,(float)LA_SUN, 0, 0, "Light shines from constant direction");
+ uiDefButS(block, ROW,B_LAMPREDRAW,"Hemi", 499,190,55,25,&la->type,1.0,(float)LA_HEMI, 0, 0, "Light shines as half a sphere");
+
+ uiBlockSetCol(block, BUTGREY);
+ uiDefButF(block, NUM,B_LAMPREDRAW,"Dist:",611,190,104,25,&la->dist, 0.01, 5000.0, 100, 0, "Set the distance value");
+
+ uiBlockSetCol(block, BUTBLUE);
+ uiDefButS(block, TOG|BIT|3, B_MATPRV,"Quad", 203,196,100,19,&la->mode, 0, 0, 0, 0, "Use inverse quadratic proportion");
+ uiDefButS(block, TOG|BIT|6, REDRAWVIEW3D,"Sphere",203,176,100,19,&la->mode, 0, 0, 0, 0, "Lamp only shines inside a sphere");
+ uiDefButS(block, TOG|BIT|0, REDRAWVIEW3D, "Shadows", 203,156,100,19,&la->mode, 0, 0, 0, 0, "Let lamp produce shadows");
+ uiDefButS(block, TOG|BIT|1, 0,"Halo", 203,136,100,19,&la->mode, 0, 0, 0, 0, "Render spotlights with a volumetric halo");
+ uiDefButS(block, TOG|BIT|2, 0,"Layer", 203,116,100,19,&la->mode, 0, 0, 0, 0, "Illuminate objects in the same layer only");
+ uiDefButS(block, TOG|BIT|4, B_MATPRV,"Negative", 203,96,100,19,&la->mode, 0, 0, 0, 0, "Cast negative light");
+ uiDefButS(block, TOG|BIT|5, 0,"OnlyShadow", 203,76,100,19,&la->mode, 0, 0, 0, 0, "Render shadow only");
+ uiDefButS(block, TOG|BIT|7, B_LAMPREDRAW,"Square", 203,56,100,19,&la->mode, 0, 0, 0, 0, "Use square spotbundles");
+#ifdef __SHADOW_EXP
+ /* move this elsewhere */
+ uiDefButS(block, TOG|BIT|10, 0,"DeepShadow", 203,216,100,19,&la->mode, 0, 0, 0, 0, "");
+#endif
+
+ uiBlockSetCol(block, BUTGREY);
+ uiDefButS(block, ROW,B_DIFF,"BufSi 512", 203,30,89,19, &la->bufsize,2.0,512.0, 0, 0, "Set the size of the shadow buffer");
+ uiDefButS(block, ROW,B_DIFF,"768", 293,30,48,19, &la->bufsize,2.0,768.0, 0, 0, "Set the size of the shadow buffer");
+ uiDefButS(block, ROW,B_DIFF,"1024", 203,10,43,19, &la->bufsize,2.0,1024.0, 0, 0, "Set the size of the shadow buffer");
+ uiDefButS(block, ROW,B_DIFF,"1536", 248,10,45,19, &la->bufsize,2.0,1536.0, 0, 0, "Set the size of the shadow buffer");
+ uiDefButS(block, ROW,B_DIFF,"2560", 293,10,48,19, &la->bufsize,2.0,2560.0, 0, 0, "Set the size of the shadow buffer");
+ uiDefButF(block, NUM,REDRAWVIEW3D,"ClipSta:", 346,30,146,19, &la->clipsta, 0.1*grid,1000.0*grid, 10, 0, "Set the shadow map clip start");
+ uiDefButF(block, NUM,REDRAWVIEW3D,"ClipEnd:", 346,9,146,19,&la->clipend, 1.0, 5000.0*grid, 100, 0, "Set the shadow map clip end");
+
+ uiDefButS(block, NUM,0,"Samples:", 496,30,105,19, &la->samp,1.0,16.0, 0, 0, "Number of shadow map samples");
+ uiDefButS(block, NUM,0,"Halo step:", 496,10,105,19, &la->shadhalostep, 0.0, 12.0, 0, 0, "Volumetric halo sampling frequency");
+ uiDefButF(block, NUM,0,"Bias:", 605,30,108,19, &la->bias, 0.01, 5.0, 1, 0, "Shadow map sampling bias");
+ uiDefButF(block, NUM,0,"Soft:", 605,10,108,19, &la->soft,1.0,100.0, 100, 0, "Set the size of the shadow sample area");
+
+ uiBlockSetCol(block, BUTGREY);
+ uiDefButF(block, NUMSLI,B_MATPRV,"Energy ", 520,156,195,20, &(la->energy), 0.0, 10.0, 0, 0, "Set the intensity of the light");
+
+ uiDefButF(block, NUMSLI,B_MATPRV,"R ", 520,128,194,20,&la->r, 0.0, 1.0, B_COLLAMP, 0, "Set the red component of the light");
+ uiDefButF(block, NUMSLI,B_MATPRV,"G ", 520,108,194,20,&la->g, 0.0, 1.0, B_COLLAMP, 0, "Set the green component of the light");
+ uiDefButF(block, NUMSLI,B_MATPRV,"B ", 520,88,194,20,&la->b, 0.0, 1.0, B_COLLAMP, 0, "Set the blue component of the light");
+
+ uiDefButF(block, COL, B_COLLAMP, "", 520,64,193,23, &la->r, 0, 0, 0, 0, "");
+
+ uiDefButF(block, NUMSLI,B_LAMPREDRAW,"SpotSi ",317,157,192,19,&la->spotsize, 1.0, 180.0, 0, 0, "Set the angle of the spot beam in degrees");
+ uiDefButF(block, NUMSLI,B_MATPRV,"SpotBl ", 316,136,192,19,&la->spotblend, 0.0, 1.0, 0, 0, "Set the softness of the spot edge");
+ uiDefButF(block, NUMSLI,B_MATPRV,"Quad1 ", 316,106,192,19,&la->att1, 0.0, 1.0, 0, 0, "Set the light intensity value 1 for a quad lamp");
+ uiDefButF(block, NUMSLI,B_MATPRV,"Quad2 ", 317,86,191,19,&la->att2, 0.0, 1.0, 0, 0, "Set the light intensity value 2 for a quad lamp");
+ uiDefButF(block, NUMSLI,0,"HaloInt ", 316,64,193,19,&la->haint, 0.0, 5.0, 0, 0, "Set the intensity of the spot halo");
+
+
+ /* TEX CHANNELS */
+ uiBlockSetCol(block, BUTGREY);
+ xco= 745;
+ for(a= 0; a<6; a++) {
+ mtex= la->mtex[a];
+ if(mtex && mtex->tex) splitIDname(mtex->tex->id.name+2, str, &loos);
+ else strcpy(str, "");
+ str[10]= 0;
+ uiDefButS(block, ROW, B_REDR, str, xco, 195, 83, 20, &(la->texact), 3.0, (float)a, 0, 0, "");
+ xco+= 85;
+ }
+
+ mtex= la->mtex[ la->texact ];
+ if(mtex==0) {
+ mtex= &emptytex;
+ default_mtex(mtex);
+ mtex->texco= TEXCO_VIEW;
+ }
+
+ /* TEXCO */
+ uiBlockSetCol(block, BUTGREEN);
+ uiDefButS(block, ROW, B_MATPRV, "Object", 745,146,49,18, &(mtex->texco), 4.0, (float)TEXCO_OBJECT, 0, 0, "Use linked object's coordinates for texture coordinates");
+ uiDefIDPoinBut(block, test_obpoin_but, B_MATPRV, "", 745,166,133,18, &(mtex->object), "");
+ uiDefButS(block, ROW, B_MATPRV, "Glob", 795,146,45,18, &(mtex->texco), 4.0, (float)TEXCO_GLOB, 0, 0, "Generate texture coordinates from global coordinates");
+ uiDefButS(block, ROW, B_MATPRV, "View", 839,146,39,18, &(mtex->texco), 4.0, (float)TEXCO_VIEW, 0, 0, "Generate texture coordinates from view coordinates");
+
+ uiBlockSetCol(block, BUTGREY);
+ uiDefButF(block, NUM, B_MATPRV, "dX", 745,114,133,18, mtex->ofs, -20.0, 20.0, 10, 0, "Set the extra translation of the texture coordinate");
+ uiDefButF(block, NUM, B_MATPRV, "dY", 745,94,133,18, mtex->ofs+1, -20.0, 20.0, 10, 0, "Set the extra translation of the texture coordinate");
+ uiDefButF(block, NUM, B_MATPRV, "dZ", 745,74,133,18, mtex->ofs+2, -20.0, 20.0, 10, 0, "Set the extra translation of the texture coordinate");
+ uiDefButF(block, NUM, B_MATPRV, "sizeX", 745,50,133,18, mtex->size, -10.0, 10.0, 10, 0, "Set the extra scaling of the texture coordinate");
+ uiDefButF(block, NUM, B_MATPRV, "sizeY", 745,30,133,18, mtex->size+1, -10.0, 10.0, 10, 0, "Set the extra scaling of the texture coordinate");
+ uiDefButF(block, NUM, B_MATPRV, "sizeZ", 745,10,133,18, mtex->size+2, -10.0, 10.0, 10, 0, "Set the extra scaling of the texture coordinate");
+
+ /* TEXTUREBLOK SELECT */
+ id= (ID *)mtex->tex;
+ IDnames_to_pupstring(&strp, NULL, "ADD NEW %x 32767", &(G.main->tex), id, &(G.buts->texnr));
+
+ /* werkt niet omdat lockpoin op lamp staat, niet op texture */
+ uiDefButS(block, MENU, B_LTEXBROWSE, strp, 900,146,20,19, &(G.buts->texnr), 0, 0, 0, 0, "Select an existing texture, or create new");
+ MEM_freeN(strp);
+
+ if(id) {
+ uiDefBut(block, TEX, B_IDNAME, "TE:", 900,166,163,19, id->name+2, 0.0, 18.0, 0, 0, "Name of the texture block");
+ sprintf(str, "%d", id->us);
+ uiDefBut(block, BUT, 0, str, 996,146,21,19, 0, 0, 0, 0, 0, "Select an existing texture, or create new");
+ uiDefIconBut(block, BUT, B_AUTOTEXNAME, ICON_AUTO, 1041,146,21,19, 0, 0, 0, 0, 0, "Auto assign a name to the texture");
+ if(id->lib) {
+ if(la->id.lib) uiDefIconBut(block, BUT, 0, ICON_DATALIB, 1019,146,21,19, 0, 0, 0, 0, 0, "");
+ else uiDefIconBut(block, BUT, 0, ICON_PARLIB, 1019,146,21,19, 0, 0, 0, 0, 0, "");
+ }
+ uiBlockSetCol(block, BUTSALMON);
+ uiDefBut(block, BUT, B_TEXCLEARLAMP, "Clear", 922, 146, 72, 19, 0, 0, 0, 0, 0, "Erase link to texture");
+ uiBlockSetCol(block, BUTGREY);
+ }
+
+ /* TEXTURE OUTPUT */
+ uiDefButS(block, TOG|BIT|1, B_MATPRV, "Stencil", 900,114,52,18, &(mtex->texflag), 0, 0, 0, 0, "Set the mapping to stencil mode");
+ uiDefButS(block, TOG|BIT|2, B_MATPRV, "Neg", 954,114,38,18, &(mtex->texflag), 0, 0, 0, 0, "Apply the inverse of the texture");
+ uiDefButS(block, TOG|BIT|0, B_MATPRV, "RGBtoInt", 994,114,69,18, &(mtex->texflag), 0, 0, 0, 0, "Use an RGB texture as an intensity texture");
+
+ uiDefButF(block, COL, B_MTEXCOL, "", 900,100,163,12, &(mtex->r), 0, 0, 0, 0, "");
+ uiDefButF(block, NUMSLI, B_MATPRV, "R ", 900,80,163,18, &(mtex->r), 0.0, 1.0, B_MTEXCOL, 0, "Set the red component of the intensity texture to blend with");
+ uiDefButF(block, NUMSLI, B_MATPRV, "G ", 900,60,163,18, &(mtex->g), 0.0, 1.0, B_MTEXCOL, 0, "Set the green component of the intensity texture to blend with");
+ uiDefButF(block, NUMSLI, B_MATPRV, "B ", 900,40,163,18, &(mtex->b), 0.0, 1.0, B_MTEXCOL, 0, "Set the blue component of the intensity texture to blend with");
+ uiDefButF(block, NUMSLI, B_MATPRV, "DVar ", 900,10,163,18, &(mtex->def_var), 0.0, 1.0, 0, 0, "Set the value the texture blends with");
+
+ /* MAP TO */
+ uiBlockSetCol(block, BUTGREEN);
+ uiDefButS(block, TOG|BIT|0, B_MATPRV, "Col", 1087,166,81,18, &(mtex->mapto), 0, 0, 0, 0, "Let the texture affect the colour of the lamp");
+
+ uiBlockSetCol(block, BUTGREY);
+ uiDefButS(block, ROW, B_MATPRV, "Blend", 1087,114,48,18, &(mtex->blendtype), 9.0, (float)MTEX_BLEND, 0, 0, "Mix the values");
+ uiDefButS(block, ROW, B_MATPRV, "Mul", 1136,114,44,18, &(mtex->blendtype), 9.0, (float)MTEX_MUL, 0, 0, "Multiply the values");
+ uiDefButS(block, ROW, B_MATPRV, "Add", 1182,114,41,18, &(mtex->blendtype), 9.0, (float)MTEX_ADD, 0, 0, "Add the values");
+ uiDefButS(block, ROW, B_MATPRV, "Sub", 1226,114,40,18, &(mtex->blendtype), 9.0, (float)MTEX_SUB, 0, 0, "Subtract the values");
+
+ uiDefButF(block, NUMSLI, B_MATPRV, "Col ", 1087,50,179,18, &(mtex->colfac), 0.0, 1.0, 0, 0, "Set the amount the texture affects the colour");
+ uiDefButF(block, NUMSLI, B_MATPRV, "Nor ", 1087,30,179,18, &(mtex->norfac), 0.0, 1.0, 0, 0, "Set the amount the texture affects the normal");
+ uiDefButF(block, NUMSLI, B_MATPRV, "Var ", 1087,10,179,18, &(mtex->varfac), 0.0, 1.0, 0, 0, "Set the amount the texture affects the value");
+
+
+ BIF_previewdraw(G.buts);
+
+ uiDrawBlock(block);
+}
+
+/* ***************************** ANIM ************************** */
+
+void do_animbuts(unsigned short event)
+{
+ Object *ob;
+ Base *base;
+ Effect *eff, *effn;
+ int type;
+
+ ob= OBACT;
+
+ switch(event) {
+
+ case B_RECALCPATH:
+ calc_curvepath(OBACT);
+ allqueue(REDRAWVIEW3D, 0);
+ break;
+ case B_MUL_IPO:
+ scale_editipo();
+ allqueue(REDRAWBUTSANIM, 0);
+ break;
+ case B_AUTOTIMEOFS:
+ auto_timeoffs();
+ break;
+ case B_FRAMEMAP:
+ G.scene->r.framelen= G.scene->r.framapto;
+ G.scene->r.framelen/= G.scene->r.images;
+ break;
+ case B_NEWEFFECT:
+ if(ob) {
+ if (BLI_countlist(&ob->effect)==MAX_EFFECT)
+ error("Unable to add: effect limit reached");
+ else
+ copy_act_effect(ob);
+ }
+ allqueue(REDRAWBUTSANIM, 0);
+ break;
+ case B_DELEFFECT:
+ if(ob==0 || ob->type!=OB_MESH) break;
+ eff= ob->effect.first;
+ while(eff) {
+ effn= eff->next;
+ if(eff->flag & SELECT) {
+ BLI_remlink(&ob->effect, eff);
+ free_effect(eff);
+ break;
+ }
+ eff= effn;
+ }
+ allqueue(REDRAWBUTSANIM, 0);
+ allqueue(REDRAWVIEW3D, 0);
+ break;
+ case B_NEXTEFFECT:
+ if(ob==0 || ob->type!=OB_MESH) break;
+ eff= ob->effect.first;
+ while(eff) {
+ if(eff->flag & SELECT) {
+ if(eff->next) {
+ eff->flag &= ~SELECT;
+ eff->next->flag |= SELECT;
+ }
+ break;
+ }
+ eff= eff->next;
+ }
+ allqueue(REDRAWBUTSANIM, 0);
+ break;
+ case B_PREVEFFECT:
+ if(ob==0 || ob->type!=OB_MESH) break;
+ eff= ob->effect.first;
+ while(eff) {
+ if(eff->flag & SELECT) {
+ if(eff->prev) {
+ eff->flag &= ~SELECT;
+ eff->prev->flag |= SELECT;
+ }
+ break;
+ }
+ eff= eff->next;
+ }
+ allqueue(REDRAWBUTSANIM, 0);
+ break;
+ case B_CHANGEEFFECT:
+ if(ob==0 || ob->type!=OB_MESH) break;
+ eff= ob->effect.first;
+ while(eff) {
+ if(eff->flag & SELECT) {
+ if(eff->type!=eff->buttype) {
+ BLI_remlink(&ob->effect, eff);
+ type= eff->buttype;
+ free_effect(eff);
+ eff= add_effect(type);
+ BLI_addtail(&ob->effect, eff);
+ }
+ break;
+ }
+ eff= eff->next;
+ }
+ allqueue(REDRAWBUTSANIM, 0);
+ allqueue(REDRAWVIEW3D, 0);
+ break;
+ case B_CALCEFFECT:
+ if(ob==0 || ob->type!=OB_MESH) break;
+ eff= ob->effect.first;
+ while(eff) {
+ if(eff->flag & SELECT) {
+ if(eff->type==EFF_PARTICLE) build_particle_system(ob);
+ else if(eff->type==EFF_WAVE) object_wave(ob);
+ }
+ eff= eff->next;
+ }
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWBUTSANIM, 0);
+ break;
+ case B_RECALCAL:
+ base= FIRSTBASE;
+ while(base) {
+ if(base->lay & G.vd->lay) {
+ ob= base->object;
+ eff= ob->effect.first;
+ while(eff) {
+ if(eff->flag & SELECT) {
+ if(eff->type==EFF_PARTICLE) build_particle_system(ob);
+ }
+ eff= eff->next;
+ }
+ }
+ base= base->next;
+ }
+ allqueue(REDRAWVIEW3D, 0);
+ break;
+ case B_SETSPEED:
+ set_speed_editipo(hspeed);
+ break;
+ case B_PRINTSPEED:
+ ob= OBACT;
+ if(ob) {
+ float vec[3];
+ CFRA++;
+ do_ob_ipo(ob);
+ where_is_object(ob);
+ VECCOPY(vec, ob->obmat[3]);
+ CFRA--;
+ do_ob_ipo(ob);
+ where_is_object(ob);
+ VecSubf(vec, vec, ob->obmat[3]);
+ prspeed= Normalise(vec);
+ scrarea_queue_winredraw(curarea);
+ }
+ break;
+ case B_PRINTLEN:
+ ob= OBACT;
+ if(ob && ob->type==OB_CURVE) {
+ Curve *cu=ob->data;
+
+ if(cu->path) prlen= cu->path->totdist; else prlen= -1.0;
+ scrarea_queue_winredraw(curarea);
+ }
+ break;
+ case B_RELKEY:
+ allspace(REMAKEIPO, 0);
+ allqueue(REDRAWBUTSANIM, 0);
+ allqueue(REDRAWIPO, 0);
+ break;
+
+ default:
+ if(event>=B_SELEFFECT && event<B_SELEFFECT+MAX_EFFECT) {
+ ob= OBACT;
+ if(ob) {
+ int a=B_SELEFFECT;
+
+ eff= ob->effect.first;
+ while(eff) {
+ if(event==a) eff->flag |= SELECT;
+ else eff->flag &= ~SELECT;
+
+ a++;
+ eff= eff->next;
+ }
+ allqueue(REDRAWBUTSANIM, 0);
+ }
+ }
+ }
+}
+
+void animbuts(void)
+{
+ Object *ob;
+ Mesh *me;
+ Lattice *lt;
+ Effect *eff;
+ Curve *cu;
+ ScrArea *sa;
+ uiBlock *block;
+ int a, ok;
+ char str[32];
+ short x, y;
+
+ sprintf(str, "buttonswin %d", curarea->win);
+ block= uiNewBlock(&curarea->uiblocks, str, UI_EMBOSSX, UI_HELV, curarea->win);
+
+ uiDefButS(block, NUM,REDRAWSEQ,"Sta:", 320,17,93,27,&G.scene->r.sfra,1.0,18000.0, 0, 0, "Specify the start frame of the animation");
+ uiDefButS(block, NUM,REDRAWSEQ,"End:", 416,17,95,27,&G.scene->r.efra,1.0,18000.0, 0, 0, "Specify the end frame of the animation");
+
+ uiDefButS(block, NUM,B_FRAMEMAP,"Map Old:", 320,69,93,22,&G.scene->r.framapto,1.0,900.0, 0, 0, "Specify old map value in frames");
+ uiDefButS(block, NUM,B_FRAMEMAP,"Map New:", 416,69,95,22,&G.scene->r.images,1.0,900.0, 0, 0, "Specify new map value in frames");
+
+ uiDefButS(block, NUM, 0, "AnimSpeed:", 320,47,192,19, &G.animspeed, 1.0, 9.0, 0, 0, "Set the maximum speed of the animation");
+
+ ob= OBACT;
+ if(ob) {
+
+ uiBlockSetCol(block, BUTGREEN);
+/* uiDefButC(block, TOG|BIT|1, REDRAWVIEW3D, "Quaternions", 320,190,192,19, &ob->transflag, 0.0, 0.0, 0, 0, "Use quaternions for rotation"); */
+ uiBlockSetCol(block, BUTGREY);
+
+ uiDefButF(block, NUM, REDRAWALL, "TimeOffset:", 23,18,114,30, &ob->sf, -9000.0, 9000.0, 100, 0, "Specify an offset in frames");
+
+ uiBlockSetCol(block, BUTGREEN);
+ uiDefButC(block, TOG|BIT|0, REDRAWVIEW3D, "Draw Key", 25,144,84,19, &ob->ipoflag, 0, 0, 0, 0, "Draw object as key position");
+ uiDefButC(block, TOG|BIT|1, REDRAWVIEW3D, "Draw Key Sel", 25,123,84,19, &ob->ipoflag, 0, 0, 0, 0, "Limit the drawing of object keys");
+
+ uiDefButC(block, TOG|BIT|2, REDRAWALL, "Offs Ob", 25,64,60,20, &ob->ipoflag, 0, 0, 0, 0, "Let the timeoffset work on its own objectipo");
+ uiDefButC(block, TOG|BIT|6, REDRAWALL, "Offs Par", 85,64,60,20, &ob->ipoflag, 0, 0, 0, 0, "Let the timeoffset work on the parent");
+ uiDefButC(block, TOG|BIT|7, REDRAWALL, "Offs Parti", 145,64,60,20, &ob->ipoflag, 0, 0, 0, 0, "Let the timeoffset work on the particle effect");
+
+ uiDefButS(block, TOG|BIT|4, 0, "SlowPar", 205,64,60,20, &ob->partype, 0, 0, 0, 0, "Create a delay in the parent relationship");
+
+ /* uiDefButC(block, TOG|BIT|5, REDRAWALL, "Offs Path", 85,64,60,20, &ob->ipoflag, 0, 0, 0, 0); ,""*/
+ /* uiDefButC(block, TOG|BIT|3, REDRAWALL, "Offs Mat", 145,64,60,20, &ob->ipoflag, 0, 0, 0, 0); ,""*/
+ /* uiDefButC(block, TOG|BIT|4, REDRAWALL, "Offs VertKey", 205,64,60,20, &ob->ipoflag, 0, 0, 0, 0); ,""*/
+
+
+ uiBlockSetCol(block, BUTGREY);
+ uiDefButC(block, TOG|BIT|3, REDRAWVIEW3D, "DupliFrames", 112,144,106,19, &ob->transflag, 0, 0, 0, 0, "Make copy of object for every frame");
+ uiDefButC(block, TOG|BIT|4, REDRAWVIEW3D, "DupliVerts", 112,123,80,19, &ob->transflag, 0, 0, 0, 0, "Duplicate child objects on all vertices");
+ uiBlockSetCol(block, BUTGREEN);
+ uiDefButC(block, TOG|BIT|5, REDRAWVIEW3D, "Rot", 194,123,24,19, &ob->transflag, 0, 0, 0, 0, "Rotate dupli according to facenormal");
+
+ uiBlockSetCol(block, BUTGREY);
+ uiDefButS(block, NUM, REDRAWVIEW3D, "DupSta:", 220,144,93,19, &ob->dupsta, 1.0, 1500.0, 0, 0, "Specify startframe for Dupliframes");
+ uiDefButS(block, NUM, REDRAWVIEW3D, "DupEnd", 315,144,93,19, &ob->dupend, 1.0, 2500.0, 0, 0, "Specify endframe for Dupliframes");
+ uiDefButS(block, NUM, REDRAWVIEW3D, "DupOn:", 220,123,93,19, &ob->dupon, 1.0, 1500.0, 0, 0, "");
+ uiDefButS(block, NUM, REDRAWVIEW3D, "DupOff", 315,123,93,19, &ob->dupoff, 0.0, 1500.0, 0, 0, "");
+ uiBlockSetCol(block, BUTGREEN);
+ uiDefButC(block, TOG|BIT|6, REDRAWVIEW3D, "No Speed", 410,144,93,19, &ob->transflag, 0, 0, 0, 0, "Set dupliframes to still, regardless of frame");
+ uiDefButC(block, TOG|BIT|7, REDRAWVIEW3D, "Powertrack", 410,123,93,19, &ob->transflag, 0, 0, 0, 0, "Switch objects rotation off");
+
+ uiBlockSetCol(block, BUTSALMON);
+ uiDefBut(block, BUT, B_AUTOTIMEOFS, "Automatic Time", 140,18,104,31, 0, 0, 0, 0, 0, "Generate automatic timeoffset values for all selected frames");
+ uiBlockSetCol(block, BUTGREY);
+ sprintf(str, "%.4f", prspeed);
+ uiDefBut(block, LABEL, 0, str, 247,40,63,31, 0, 1.0, 0, 0, 0, "");
+ uiDefBut(block, BUT, B_PRINTSPEED, "PrSpeed", 247,18,63,31, 0, 0, 0, 0, 0, "Print objectspeed");
+
+ if(ob->type==OB_MESH) {
+ me= ob->data;
+ if(me->key) {
+ uiDefButS(block, NUM, B_DIFF, "Slurph:", 125,101,93,19, &(me->key->slurph), -500.0, 500.0, 0, 0, "");
+ uiDefButS(block, TOG, B_RELKEY, "Relative Keys", 220,100,93,19, &me->key->type, 0, 0, 0, 0, "");
+ }
+ }
+ if(ob->type==OB_CURVE) {
+ cu= ob->data;
+ uiDefButS(block, NUM, B_RECALCPATH, "PathLen:", 34,100,90,19, &cu->pathlen, 1.0, 9000.0, 0, 0, "");
+ /* if(cu->key==0) { */
+ uiDefButS(block, TOG|BIT|3, B_RECALCPATH, "CurvePath", 125,100,90,19 , &cu->flag, 0, 0, 0, 0, "");
+ uiDefButS(block, TOG|BIT|4, REDRAWVIEW3D, "CurveFollow", 216,100,90,19, &cu->flag, 0, 0, 0, 0, "");
+ /* } */
+ sprintf(str, "%.4f", prlen);
+ uiDefBut(block, LABEL, 0, str, 396,100,90,19, 0, 1.0, 0, 0, 0, "");
+ uiDefBut(block, BUT, B_PRINTLEN, "PrintLen", 306,100,90,19, 0, 0, 0, 0, 0, "");
+ }
+ if(ob->type==OB_SURF) {
+ cu= ob->data;
+
+ if(cu->key) {
+ /* uiDefButS(block, NUM, B_DIFF, "Slurph:", 124,100,93,19, &(cu->key->slurph), -500.0, 500.0,0,0); ,""*/
+ uiDefButS(block, TOG, B_RELKEY, "Relative Keys", 220,100,93,19, &cu->key->type, 0, 0, 0, 0, "");
+ }
+ }
+ if(ob->type==OB_LATTICE) {
+ lt= ob->data;
+ if(lt->key) {
+ uiDefButS(block, NUM, B_DIFF, "Slurph:", 124,100,93,19, &(lt->key->slurph), -500.0, 500.0, 0, 0, "");
+ uiDefButS(block, TOG, B_RELKEY, "Relative Keys", 370,190,133,19, &lt->key->type, 0, 0, 0, 0, "");
+ }
+ }
+
+ uiBlockSetCol(block, BUTGREEN);
+ uiDefButC(block, ROW,REDRAWVIEW3D,"TrackX", 27,190,58,17, &ob->trackflag, 12.0, 0.0, 0, 0, "Specify the axis that points to another object");
+ uiDefButC(block, ROW,REDRAWVIEW3D,"Y", 85,190,19,17, &ob->trackflag, 12.0, 1.0, 0, 0, "Specify the axis that points to another object");
+ uiDefButC(block, ROW,REDRAWVIEW3D,"Z", 104,190,19,17, &ob->trackflag, 12.0, 2.0, 0, 0, "Specify the axis that points to another object");
+ uiDefButC(block, ROW,REDRAWVIEW3D,"-X", 123,190,24,17, &ob->trackflag, 12.0, 3.0, 0, 0, "Specify the axis that points to another object");
+ uiDefButC(block, ROW,REDRAWVIEW3D,"-Y", 147,190,24,17, &ob->trackflag, 12.0, 4.0, 0, 0, "Specify the axis that points to another object");
+ uiDefButC(block, ROW,REDRAWVIEW3D,"-Z", 171,190,24,17, &ob->trackflag, 12.0, 5.0, 0, 0, "Specify the axis that points to another object");
+ uiDefButC(block, ROW,REDRAWVIEW3D,"UpX", 205,190,40,17, &ob->upflag, 13.0, 0.0, 0, 0, "Specify the axis that points up");
+ uiDefButC(block, ROW,REDRAWVIEW3D,"Y", 245,190,20,17, &ob->upflag, 13.0, 1.0, 0, 0, "Specify the axis that points up");
+ uiDefButC(block, ROW,REDRAWVIEW3D,"Z", 265,190,19,17, &ob->upflag, 13.0, 2.0, 0, 0, "Specify the axis that points up");
+
+ uiBlockSetCol(block, BUTSALMON);
+
+ /* EFFECTS */
+
+ draw_buttons_edge(curarea->win, 540);
+ draw_buttons_edge(curarea->win, 1010);
+
+ if (ob->type == OB_MESH) {
+ uiDefBut(block, BUT, B_NEWEFFECT, "NEW Effect", 550,187,124,27, 0, 0, 0, 0, 0, "Create a new effect");
+ uiDefBut(block, BUT, B_DELEFFECT, "Delete", 676,187,62,27, 0, 0, 0, 0, 0, "Delete the effect");
+ }
+
+ uiBlockSetCol(block, BUTGREY);
+
+ /* select effs */
+ eff= ob->effect.first;
+ a= 0;
+ while(eff) {
+
+ x= 15 * a + 550;
+ y= 172; // - 12*( abs(a/10) ) ;
+ uiDefButS(block, TOG|BIT|0, B_SELEFFECT+a, "", x, y, 15, 12, &eff->flag, 0, 0, 0, 0, "");
+
+ a++;
+ if(a==MAX_EFFECT) break;
+ eff= eff->next;
+ }
+
+ eff= ob->effect.first;
+ while(eff) {
+ if(eff->flag & SELECT) break;
+ eff= eff->next;
+ }
+
+ if(eff) {
+ uiDefButS(block, MENU, B_CHANGEEFFECT, "Build %x0|Particles %x1|Wave %x2", 895,187,107,27, &eff->buttype, 0, 0, 0, 0, "Start building the effect");
+
+ if(eff->type==EFF_BUILD) {
+ BuildEff *bld;
+
+ bld= (BuildEff *)eff;
+
+ uiDefButF(block, NUM, 0, "Len:", 649,138,95,21, &bld->len, 1.0, 9000.0, 100, 0, "Specify the total time the building requires");
+ uiDefButF(block, NUM, 0, "Sfra:", 746,138,94,22, &bld->sfra, 1.0, 9000.0, 100, 0, "Specify the startframe of the effect");
+ }
+ else if(eff->type==EFF_WAVE) {
+ WaveEff *wav;
+
+ wav= (WaveEff *)eff;
+
+ uiBlockSetCol(block, BUTGREEN);
+ uiDefButS(block, TOG|BIT|1, B_CALCEFFECT, "X", 782,135,54,23, &wav->flag, 0, 0, 0, 0, "Enable X axis");
+ uiDefButS(block, TOG|BIT|2, B_CALCEFFECT, "Y", 840,135,47,23, &wav->flag, 0, 0, 0, 0, "Enable Y axis");
+ uiDefButS(block, TOG|BIT|3, B_CALCEFFECT, "Cycl", 890,135,111,23, &wav->flag, 0, 0, 0, 0, "Enable cyclic wave efefct");
+
+ uiBlockSetCol(block, BUTGREY);
+ uiDefButF(block, NUM, B_CALCEFFECT, "Sta x:", 550,135,113,24, &wav->startx, -100.0, 100.0, 100, 0, "Starting position for the X axis");
+ uiDefButF(block, NUM, B_CALCEFFECT, "Sta y:", 665,135,104,24, &wav->starty, -100.0, 100.0, 100, 0, "Starting position for the Y axis");
+
+ uiDefButF(block, NUMSLI, B_CALCEFFECT, "Speed:", 550,100,216,20, &wav->speed, -2.0, 2.0, 0, 0, "Specify the wave speed");
+ uiDefButF(block, NUMSLI, B_CALCEFFECT, "Heigth:", 550,80,216,20, &wav->height, -2.0, 2.0, 0, 0, "Specify the amplitude of the wave");
+ uiDefButF(block, NUMSLI, B_CALCEFFECT, "Width:", 550,60,216,20, &wav->width, 0.0, 5.0, 0, 0, "Specify the width of the wave");
+ uiDefButF(block, NUMSLI, B_CALCEFFECT, "Narrow:", 550,40,216,20, &wav->narrow, 0.0, 10.0, 0, 0, "Specify how narrow the wave follows");
+
+ uiDefButF(block, NUM, B_CALCEFFECT, "Time sta:", 780,100,219,20, &wav->timeoffs, -1000.0, 1000.0, 100, 0, "Specify startingframe of the wave");
+
+ uiDefButF(block, NUM, B_CALCEFFECT, "Lifetime:", 780,80,219,20, &wav->lifetime, -1000.0, 1000.0, 100, 0, "Specify the lifespan of the wave");
+ uiDefButF(block, NUM, B_CALCEFFECT, "Damptime:", 780,60,219,20, &wav->damp, -1000.0, 1000.0, 100, 0, "Specify the dampingtime of the wave");
+
+ }
+ else if(eff->type==EFF_PARTICLE) {
+ PartEff *paf;
+
+ paf= (PartEff *)eff;
+
+ uiDefBut(block, BUT, B_RECALCAL, "RecalcAll", 741,187,67,27, 0, 0, 0, 0, 0, "Update the particle system");
+ uiBlockSetCol(block, BUTGREEN);
+ uiDefButS(block, TOG|BIT|2, B_CALCEFFECT, "Static", 825,187,67,27, &paf->flag, 0, 0, 0, 0, "Make static particles");
+ uiBlockSetCol(block, BUTGREY);
+
+ uiDefButI(block, NUM, B_CALCEFFECT, "Tot:", 550,146,91,20, &paf->totpart, 1.0, 100000.0, 0, 0, "Set the total number of particles");
+ if(paf->flag & PAF_STATIC) {
+ uiDefButS(block, NUM, REDRAWVIEW3D, "Step:", 644,146,84,20, &paf->staticstep, 1.0, 100.0, 10, 0, "");
+ }
+ else {
+ uiDefButF(block, NUM, B_CALCEFFECT, "Sta:", 644,146,84,20, &paf->sta, -250.0, 9000.0, 100, 0, "Specify the startframe");
+ uiDefButF(block, NUM, B_CALCEFFECT, "End:", 731,146,97,20, &paf->end, 1.0, 9000.0, 100, 0, "Specify the endframe");
+ }
+ uiDefButF(block, NUM, B_CALCEFFECT, "Life:", 831,146,88,20, &paf->lifetime, 1.0, 9000.0, 100, 0, "Specify the life span of the particles");
+ uiDefButI(block, NUM, B_CALCEFFECT, "Keys:", 922,146,80,20, &paf->totkey, 1.0, 32.0, 0, 0, "Specify the number of key positions");
+
+ uiBlockSetCol(block, BUTGREEN);
+ uiDefButS(block, NUM, B_REDR, "CurMul:", 550,124,91,20, &paf->curmult, 0.0, 3.0, 0, 0, "Multiply the particles");
+ uiBlockSetCol(block, BUTGREY);
+ uiDefButS(block, NUM, B_CALCEFFECT, "Mat:", 644,124,84,20, paf->mat+paf->curmult, 1.0, 8.0, 0, 0, "Specify the material used for the particles");
+ uiDefButF(block, NUM, B_CALCEFFECT, "Mult:", 730,124,98,20, paf->mult+paf->curmult, 0.0, 1.0, 10, 0, "Switch particle multiplication on/off");
+ uiDefButS(block, NUM, B_CALCEFFECT, "Child:", 922,124,80,20, paf->child+paf->curmult, 1.0, 600.0, 100, 0, "Specify the number of children of a particle that multiply itself");
+ uiDefButF(block, NUM, B_CALCEFFECT, "Life:", 831,124,89,20, paf->life+paf->curmult, 1.0, 600.0, 100, 0, "Specify the lifespan of the next generation particles");
+
+ uiDefButF(block, NUM, B_CALCEFFECT, "Randlife:", 550,96,96,20, &paf->randlife, 0.0, 2.0, 10, 0, "Give the particlelife a random variation");
+ uiDefButI(block, NUM, B_CALCEFFECT, "Seed:", 652,96,80,20, &paf->seed, 0.0, 255.0, 0, 0, "Set an offset in the random table");
+
+ uiDefButF(block, NUM, B_DIFF, "VectSize", 885,96,116,20, &paf->vectsize, 0.0, 1.0, 10, 0, "Set the speed for Vect");
+ uiBlockSetCol(block, BUTGREEN);
+ uiDefButS(block, TOG|BIT|3, B_CALCEFFECT, "Face", 735,96,46,20, &paf->flag, 0, 0, 0, 0, "Emit particles also from faces");
+ uiDefButS(block, TOG|BIT|1, B_CALCEFFECT, "Bspline", 782,96,54,20, &paf->flag, 0, 0, 0, 0, "Use B spline formula for particle interpolation");
+ uiDefButS(block, TOG, REDRAWVIEW3D, "Vect", 837,96,45,20, &paf->stype, 0, 0, 0, 0, "Give the particles a rotation direction");
+
+ uiBlockSetCol(block, BUTPURPLE);
+ uiDefButF(block, NUM, B_CALCEFFECT, "Norm:", 550,67,96,20, &paf->normfac, -2.0, 2.0, 10, 0, "Let the mesh give the particle a starting speed");
+ uiDefButF(block, NUM, B_CALCEFFECT, "Ob:", 649,67,86,20, &paf->obfac, -1.0, 1.0, 10, 0, "Let the object give the particle a starting speed");
+ uiDefButF(block, NUM, B_CALCEFFECT, "Rand:", 738,67,86,20, &paf->randfac, 0.0, 2.0, 10, 0, "Give the startingspeed a random variation");
+ uiDefButF(block, NUM, B_CALCEFFECT, "Tex:", 826,67,85,20, &paf->texfac, 0.0, 2.0, 10, 0, "Let the texture give the particle a starting speed");
+ uiDefButF(block, NUM, B_CALCEFFECT, "Damp:", 913,67,89,20, &paf->damp, 0.0, 1.0, 10, 0, "Specify the damping factor");
+
+ uiBlockSetCol(block, BUTGREY);
+ uiDefButF(block, NUM, B_CALCEFFECT, "X:", 550,31,72,20, paf->force, -1.0, 1.0, 1, 0, "Specify the X axis of a continues force");
+ uiDefButF(block, NUM, B_CALCEFFECT, "Y:", 624,31,78,20, paf->force+1,-1.0, 1.0, 1, 0, "Specify the Y axis of a continues force");
+ uiDefBut(block, LABEL, 0, "Force:", 550,9,72,20, 0, 1.0, 0, 0, 0, "");
+ uiDefButF(block, NUM, B_CALCEFFECT, "Z:", 623,9,79,20, paf->force+2, -1.0, 1.0, 1, 0, "Specify the Z axis of a continues force");
+
+ uiDefBut(block, LABEL, 0, "Texture:", 722,9,74,20, 0, 1.0, 0, 0, 0, "");
+ uiBlockSetCol(block, BUTGREEN);
+ uiDefButS(block, ROW, B_CALCEFFECT, "Int", 875,9,32,43, &paf->texmap, 14.0, 0.0, 0, 0, "Use texture intensity as a factor for texture force");
+ uiDefButS(block, ROW, B_CALCEFFECT, "RGB", 911,31,45,20, &paf->texmap, 14.0, 1.0, 0, 0, "Use RGB values as a factor for particle speed");
+ uiDefButS(block, ROW, B_CALCEFFECT, "Grad", 958,31,44,20, &paf->texmap, 14.0, 2.0, 0, 0, "Use texture gradient as a factor for particle speed");
+ uiBlockSetCol(block, BUTGREY);
+ uiDefButF(block, NUM, B_CALCEFFECT, "Nabla:", 911,9,91,20, &paf->nabla, 0.0001, 1.0, 1, 0, "Specify the dimension of the area for gradient calculation");
+ uiDefButF(block, NUM, B_CALCEFFECT, "X:", 722,31,74,20, paf->defvec, -1.0, 1.0, 1, 0, "Specify the X axis of a force, determined by the texture");
+ uiDefButF(block, NUM, B_CALCEFFECT, "Y:", 798,31,74,20, paf->defvec+1,-1.0, 1.0, 1, 0, "Specify the Y axis of a force, determined by the texture");
+ uiDefButF(block, NUM, B_CALCEFFECT, "Z:", 797,9,75,20, paf->defvec+2, -1.0, 1.0, 1, 0, "Specify the Z axis of a force, determined by the texture");
+
+ }
+ }
+ }
+
+ /* IPO BUTTONS ALS LAATSTE */
+ ok= 0;
+ if(G.sipo) {
+ /* bestaat deze? */
+ sa= G.curscreen->areabase.first;
+ while(sa) {
+ if(sa->spacetype==SPACE_IPO && sa->spacedata.first==G.sipo) break;
+ sa= sa->next;
+ }
+ if(sa) {
+ if(G.sipo->ipo && G.sipo->ipo->curve.first) ok= 1;
+ }
+ }
+
+ uiBlockSetCol(block, BUTGREEN);
+ // RMGRP uiDefButC(block, ROW, B_REDR, "Ipo settings", 1020, 180, 100, 19, &G.buts->showgroup, 15.0, 0.0, 0, 0, "");
+ // RMGRP uiDefButC(block, ROW, B_REDR, "Group settings", 1120, 180, 100, 19, &G.buts->showgroup, 15.0, 1.0, 0, 0, "");
+ uiBlockSetCol(block, BUTGREY);
+
+ if(ok && G.buts->showgroup==0) {
+ sprintf(str, "%.3f", G.sipo->v2d.tot.xmin);
+ uiDefBut(block, LABEL, 0, str, 1020, 140, 100, 19, 0, 0, 0, 0, 0, "");
+ sprintf(str, "%.3f", G.sipo->v2d.tot.xmax);
+ uiDefBut(block, LABEL, 0, str, 1120, 140, 100, 19, 0, 0, 0, 0, 0, "");
+
+ uiDefButF(block, NUM, B_DIFF, "Xmin:", 1020, 120, 100, 19, &G.sipo->tot.xmin, -G.sipo->v2d.max[0], G.sipo->v2d.max[0], 100, 0, "");
+ uiDefButF(block, NUM, B_DIFF, "Xmax:", 1120, 120, 100, 19, &G.sipo->tot.xmax, -G.sipo->v2d.max[0], G.sipo->v2d.max[0], 100, 0, "");
+
+ sprintf(str, "%.3f", G.sipo->v2d.tot.ymin);
+ uiDefBut(block, LABEL, 0, str, 1020, 100, 100, 19, 0, 0, 0, 0, 0, "");
+ sprintf(str, "%.3f", G.sipo->v2d.tot.ymax);
+ uiDefBut(block, LABEL, 0, str, 1120, 100, 100, 19, 0, 0, 0, 0, 0, "");
+
+ uiDefButF(block, NUM, B_DIFF, "Ymin:", 1020, 80, 100, 19, &G.sipo->tot.ymin, -G.sipo->v2d.max[1], G.sipo->v2d.max[1], 100, 0, "");
+ uiDefButF(block, NUM, B_DIFF, "Ymax:", 1120, 80, 100, 19, &G.sipo->tot.ymax, -G.sipo->v2d.max[1], G.sipo->v2d.max[1], 100, 0, "");
+
+ uiBlockSetCol(block, BUTSALMON);
+ uiDefBut(block, BUT, B_MUL_IPO, "SET", 1220,79,50,62, 0, 0, 0, 0, 0, "");
+
+
+ /* SPEED BUTTON */
+ uiBlockSetCol(block, BUTGREY);
+ uiDefButF(block, NUM, B_DIFF, "Speed:", 1020,23,164,28, &hspeed, 0.0, 180.0, 1, 0, "");
+
+ uiBlockSetCol(block, BUTSALMON);
+ uiDefBut(block, BUT, B_SETSPEED, "SET", 1185,23,83,29, 0, 0, 0, 0, 0, "");
+ }
+
+ if(G.buts->showgroup && G.scene->group) {
+ GroupKey *gk;
+ short yco= 140;
+
+ gk= G.scene->group->gkey.first;
+ while(gk) {
+ if(gk==G.scene->group->active) uiBlockSetCol(block, BUTPURPLE);
+ else uiBlockSetCol(block, BUTGREY);
+ uiDefBut(block, TEX, B_DIFF, "Name:", 1020, yco, 140, 19, &gk->name, 0.0, 31.0, 10, 0, "");
+ uiDefButS(block, NUM, B_DIFF, "Sta:", 1160, yco, 60, 19, &gk->sfra, 0.0, 5000.0, 10, 0, "");
+ uiDefButS(block, NUM, B_DIFF, "End:", 1220, yco, 50, 19, &gk->efra, 0.0, 5000.0, 10, 0, "");
+ yco-= 20;
+ gk= gk->next;
+ }
+ }
+
+ uiDrawBlock(block);
+}
+
+
+
+
+/* ***************************** WORLD ************************** */
+
+void do_worldbuts(unsigned short event)
+{
+ World *wrld;
+ MTex *mtex;
+
+ switch(event) {
+ case B_TEXCLEARWORLD:
+ wrld= G.buts->lockpoin;
+ mtex= wrld->mtex[ wrld->texact ];
+ if(mtex) {
+ if(mtex->tex) mtex->tex->id.us--;
+ MEM_freeN(mtex);
+ wrld->mtex[ wrld->texact ]= 0;
+ allqueue(REDRAWBUTSWORLD, 0);
+ allqueue(REDRAWOOPS, 0);
+ BIF_preview_changed(G.buts);
+ }
+ break;
+ }
+}
+
+void worldbuts(void)
+{
+ World *wrld;
+ MTex *mtex;
+ ID *id;
+ uiBlock *block;
+ int a, loos;
+ char str[30], *strp;
+ short xco;
+
+ wrld= G.scene->world;
+ if(wrld==0) return;
+
+ sprintf(str, "buttonswin %d", curarea->win);
+ block= uiNewBlock(&curarea->uiblocks, str, UI_EMBOSSX, UI_HELV, curarea->win);
+
+ uiSetButLock(wrld->id.lib!=0, "Can't edit library data");
+ uiBlockSetCol(block, BUTGREEN);
+
+ uiDefButS(block, TOG|BIT|1,B_MATPRV,"Real", 286,190,71,19, &wrld->skytype, 0, 0, 0, 0, "Render background with real horizon");
+ uiDefButS(block, TOG|BIT|0,B_MATPRV,"Blend", 208,190,74,19, &wrld->skytype, 0, 0, 0, 0, "Render background with natural progression");
+ uiDefButS(block, TOG|BIT|2,B_MATPRV,"Paper", 361,190,71,19, &wrld->skytype, 0, 0, 0, 0, "Flatten blend or texture coordinates");
+ uiBlockSetCol(block, BUTGREY);
+ uiDefButF(block, NUMSLI,B_MATPRV,"HoR ", 200,55,175,18, &(wrld->horr), 0.0, 1.0, 0,0, "The amount of red of the horizon colour");
+ uiDefButF(block, NUMSLI,B_MATPRV,"HoG ", 200,34,175,18, &(wrld->horg), 0.0, 1.0, 0,0, "The amount of green of the horizon colour");
+ uiDefButF(block, NUMSLI,B_MATPRV,"HoB ", 200,13,175,18, &(wrld->horb), 0.0, 1.0, 0,0, "The amount of blue of the horizon colour");
+ uiDefButF(block, NUMSLI,B_MATPRV,"ZeR ", 200,136,175,18, &(wrld->zenr), 0.0, 1.0, 0,0, "The amount of red of the zenith colour");
+ uiDefButF(block, NUMSLI,B_MATPRV,"ZeG ", 200,116,175,18, &(wrld->zeng), 0.0, 1.0, 0,0, "The amount of green of the zenith colour");
+ uiDefButF(block, NUMSLI,B_MATPRV,"ZeB ", 200,96,175,18, &(wrld->zenb), 0.0, 1.0, 0,0, "The amount of blue of the zenith colour");
+ uiDefButF(block, NUMSLI,B_MATPRV,"AmbR ", 380,55,175,18, &(wrld->ambr), 0.0, 1.0 ,0,0, "The amount of red of the ambient colour");
+ uiDefButF(block, NUMSLI,B_MATPRV,"AmbG ", 380,34,175,18, &(wrld->ambg), 0.0, 1.0 ,0,0, "The amount of red of the ambient colour");
+ uiDefButF(block, NUMSLI,B_MATPRV,"AmbB ", 380,13,175,18, &(wrld->ambb), 0.0, 1.0 ,0,0, "The amount of red of the ambient colour");
+
+ uiDefBut(block, MENU|SHO, 1, physics_pup(),
+ 380,152,175,18, &wrld->pad1, 0, 0, 0, 0, "Physics Engine");
+
+
+ /* Activity bubble */
+ // uiDefButS(block, TOG|BIT|3,B_DIFF, "Do activity culling",
+ // 380,152,175,18, &wrld->mode, 0, 0, 0, 0,
+ // "Disable logic and physics for far away objects.");
+/* if (wrld->mode & WO_ACTIVITY_CULLING) { */
+ // uiDefButF(block, NUM,0, "Active R ",
+ // 380,132,175,18, &(wrld->activityBoxRadius), 0.5, 10000.0, 100.0, 0,
+ // "Radius for activity culling (in Manhattan length).");
+/* } */
+
+ /* Gravitation for the game worlds */
+ uiDefButF(block, NUMSLI,0, "Grav ",
+ 380,112,175,18, &(wrld->gravity), 0.0, 25.0, 0, 0,
+ "Gravitation constant of the game world.");
+
+ uiDefButF(block, NUMSLI,0, "Expos ", 380,92,175,18, &(wrld->exposure), 0.2, 5.0, 0, 0, "Set the lighting time, exposure");
+
+ uiBlockSetCol(block, BUTGREEN);
+ uiDefButS(block, TOG|BIT|0,REDRAWVIEW3D,"Mist", 571,190,100,19, &wrld->mode, 0, 0, 0, 0, "Enable mist");
+ uiBlockSetCol(block, BUTGREY);
+ uiDefButS(block, ROW, B_DIFF, "Qua", 571, 170, 33, 19, &wrld->mistype, 1.0, 0.0, 0, 0, "Use quadratic progression");
+ uiDefButS(block, ROW, B_DIFF, "Lin", 604, 170, 33, 19, &wrld->mistype, 1.0, 1.0, 0, 0, "Use linear progression");
+ uiDefButS(block, ROW, B_DIFF, "Sqr", 637, 170, 33, 19, &wrld->mistype, 1.0, 2.0, 0, 0, "Use inverse quadratic progression");
+
+ uiDefButF(block, NUM,REDRAWVIEW3D, "Sta:", 571,150,100,19, &wrld->miststa, 0.0, 1000.0, 10, 0, "Specify the starting distance of the mist");
+ uiDefButF(block, NUM,REDRAWVIEW3D, "Di:", 571,130,100,19, &wrld->mistdist, 0.0,1000.0, 10, 00, "Specify the depth of the mist");
+ uiDefButF(block, NUM,B_DIFF,"Hi:", 571,110,100,19, &wrld->misthi,0.0,100.0, 10, 0, "Specify the factor for a less dense mist with increasing height");
+ uiBlockSetCol(block, BUTGREEN);
+ uiDefButS(block, TOG|BIT|1,B_DIFF, "Stars",571,90,100,19, &wrld->mode, 0, 0, 0, 0, "Enable stars");
+ uiBlockSetCol(block, BUTGREY);
+ uiDefButF(block, NUM,B_DIFF,"StarDist:", 571,70,100,19, &(wrld->stardist), 2.0, 1000.0, 100, 0, "Specify the average distance between two stars");
+ uiDefButF(block, NUM,B_DIFF,"MinDist:", 571,50,100,19, &(wrld->starmindist), 0.0, 1000.0, 100, 0, "Specify the minimum distance to the camera");
+ uiDefButF(block, NUM,B_DIFF,"Size:", 571,30,100,19, &(wrld->starsize), 0.0, 10.0, 10, 0, "Specify the average screen dimension");
+ uiDefButF(block, NUM,B_DIFF,"Colnoise:", 571,10,100,19, &(wrld->starcolnoise), 0.0, 1.0, 100, 0, "Randomize starcolour");
+
+
+ /* TEX CHANNELS */
+ uiBlockSetCol(block, BUTGREY);
+ xco= 745;
+ for(a= 0; a<6; a++) {
+ mtex= wrld->mtex[a];
+ if(mtex && mtex->tex) splitIDname(mtex->tex->id.name+2, str, &loos);
+ else strcpy(str, "");
+ str[10]= 0;
+ uiDefButS(block, ROW, REDRAWBUTSWORLD, str, xco, 195, 83, 20, &(wrld->texact), 3.0, (float)a, 0, 0, "Texture channel");
+ xco+= 85;
+ }
+
+ mtex= wrld->mtex[ wrld->texact ];
+ if(mtex==0) {
+ mtex= &emptytex;
+ default_mtex(mtex);
+ mtex->texco= TEXCO_VIEW;
+ }
+
+ /* TEXCO */
+ uiBlockSetCol(block, BUTGREEN);
+ uiDefButS(block, ROW, B_MATPRV, "Object", 745,146,49,18, &(mtex->texco), 4.0, (float)TEXCO_OBJECT, 0, 0, "The name of the object used as a source for texture coordinates");
+ uiDefIDPoinBut(block, test_obpoin_but, B_MATPRV, "", 745,166,133,18, &(mtex->object), "");
+ uiDefButS(block, ROW, B_MATPRV, "View", 839,146,39,18, &(mtex->texco), 4.0, (float)TEXCO_VIEW, 0, 0, "Pass camera view vector on to the texture");
+
+ uiBlockSetCol(block, BUTGREY);
+ uiDefButF(block, NUM, B_MATPRV, "dX", 745,114,133,18, mtex->ofs, -20.0, 20.0, 10, 0, "Fine tune X coordinate");
+ uiDefButF(block, NUM, B_MATPRV, "dY", 745,94,133,18, mtex->ofs+1, -20.0, 20.0, 10, 0, "Fine tune Y coordinate");
+ uiDefButF(block, NUM, B_MATPRV, "dZ", 745,74,133,18, mtex->ofs+2, -20.0, 20.0, 10, 0, "Fine tune Z coordinate");
+ uiDefButF(block, NUM, B_MATPRV, "sizeX", 745,50,133,18, mtex->size, -20.0, 20.0, 10, 0, "Set an extra scaling for the texture coordinate");
+ uiDefButF(block, NUM, B_MATPRV, "sizeY", 745,30,133,18, mtex->size+1, -20.0, 20.0, 10, 0, "Set an extra scaling for the texture coordinate");
+ uiDefButF(block, NUM, B_MATPRV, "sizeZ", 745,10,133,18, mtex->size+2, -20.0, 20.0, 10, 0, "Set an extra scaling for the texture coordinate");
+
+ /* TEXTUREBLOK SELECT */
+ id= (ID *)mtex->tex;
+ IDnames_to_pupstring(&strp, NULL, "ADD NEW %x 32767", &(G.main->tex), id, &(G.buts->texnr));
+ uiDefButS(block, MENU, B_WTEXBROWSE, strp, 900,146,20,19, &(G.buts->texnr), 0, 0, 0, 0, "Browse");
+ MEM_freeN(strp);
+
+ if(id) {
+ uiDefBut(block, TEX, B_IDNAME, "TE:", 900,166,163,19, id->name+2, 0.0, 18.0, 0, 0, "Specify the texture name");
+ sprintf(str, "%d", id->us);
+ uiDefBut(block, BUT, 0, str, 996,146,21,19, 0, 0, 0, 0, 0, "Number of users");
+ uiDefIconBut(block, BUT, B_AUTOTEXNAME, ICON_AUTO, 1041,146,21,19, 0, 0, 0, 0, 0, "Auto assign name to texture");
+ if(id->lib) {
+ if(wrld->id.lib) uiDefIconBut(block, BUT, 0, ICON_DATALIB, 1019,146,21,19, 0, 0, 0, 0, 0, "");
+ else uiDefIconBut(block, BUT, 0, ICON_PARLIB, 1019,146,21,19, 0, 0, 0, 0, 0, "");
+ }
+ uiBlockSetCol(block, BUTSALMON);
+ uiDefBut(block, BUT, B_TEXCLEARWORLD, "Clear", 922, 146, 72, 19, 0, 0, 0, 0, 0, "Erase link to texture");
+ uiBlockSetCol(block, BUTGREY);
+ }
+
+ /* TEXTURE OUTPUT */
+ uiDefButS(block, TOG|BIT|1, B_MATPRV, "Stencil", 900,114,52,18, &(mtex->texflag), 0, 0, 0, 0, "Use stencil mode");
+ uiDefButS(block, TOG|BIT|2, B_MATPRV, "Neg", 954,114,38,18, &(mtex->texflag), 0, 0, 0, 0, "Inverse texture operation");
+ uiDefButS(block, TOG|BIT|0, B_MATPRV, "RGBtoInt", 994,114,69,18, &(mtex->texflag), 0, 0, 0, 0, "Use RGB values for intensity texure");
+
+ uiDefButF(block, COL, B_MTEXCOL, "", 900,100,163,12, &(mtex->r), 0, 0, 0, 0, "");
+ uiDefButF(block, NUMSLI, B_MATPRV, "R ", 900,80,163,18, &(mtex->r), 0.0, 1.0, B_MTEXCOL, 0, "The amount of red that blends with the intensity colour");
+ uiDefButF(block, NUMSLI, B_MATPRV, "G ", 900,60,163,18, &(mtex->g), 0.0, 1.0, B_MTEXCOL, 0, "The amount of green that blends with the intensity colour");
+ uiDefButF(block, NUMSLI, B_MATPRV, "B ", 900,40,163,18, &(mtex->b), 0.0, 1.0, B_MTEXCOL, 0, "The amount of blue that blends with the intensity colour");
+ uiDefButF(block, NUMSLI, B_MATPRV, "DVar ", 900,10,163,18, &(mtex->def_var), 0.0, 1.0, 0, 0, "The value that an intensity texture blends with the current value");
+
+ /* MAP TO */
+ uiBlockSetCol(block, BUTGREEN);
+ uiDefButS(block, TOG|BIT|0, B_MATPRV, "Blend", 1087,166,81,18, &(mtex->mapto), 0, 0, 0, 0, "Let the texture work on the colour progression in the sky");
+ uiDefButS(block, TOG|BIT|1, B_MATPRV, "Hori", 1172,166,81,18, &(mtex->mapto), 0, 0, 0, 0, "Let the texture work on the colour of the horizon");
+ uiDefButS(block, TOG|BIT|2, B_MATPRV, "ZenUp", 1087,147,81,18, &(mtex->mapto), 0, 0, 0, 0, "Let the texture work on the colour of the zenith above");
+ uiDefButS(block, TOG|BIT|3, B_MATPRV, "ZenDo", 1172,147,81,18, &(mtex->mapto), 0, 0, 0, 0, "Let the texture work on the colour of the zenith below");
+
+ uiBlockSetCol(block, BUTGREY);
+ uiDefButS(block, ROW, B_MATPRV, "Blend", 1087,114,48,18, &(mtex->blendtype), 9.0, (float)MTEX_BLEND, 0, 0, "The texture blends the values");
+ uiDefButS(block, ROW, B_MATPRV, "Mul", 1136,114,44,18, &(mtex->blendtype), 9.0, (float)MTEX_MUL, 0, 0, "The texture multiplies the values");
+ uiDefButS(block, ROW, B_MATPRV, "Add", 1182,114,41,18, &(mtex->blendtype), 9.0, (float)MTEX_ADD, 0, 0, "The texture adds the values");
+ uiDefButS(block, ROW, B_MATPRV, "Sub", 1226,114,40,18, &(mtex->blendtype), 9.0, (float)MTEX_SUB, 0, 0, "The texture subtracts the values");
+
+ uiDefButF(block, NUMSLI, B_MATPRV, "Col ", 1087,50,179,18, &(mtex->colfac), 0.0, 1.0, 0, 0, "Specify the extent to which the texture works on colour");
+ uiDefButF(block, NUMSLI, B_MATPRV, "Nor ", 1087,30,179,18, &(mtex->norfac), 0.0, 1.0, 0, 0, "Specify the extent to which the texture works on the normal");
+ uiDefButF(block, NUMSLI, B_MATPRV, "Var ", 1087,10,179,18, &(mtex->varfac), 0.0, 1.0, 0, 0, "Specify the extent to which the texture works on a value");
+
+
+ BIF_previewdraw(G.buts);
+
+ uiDrawBlock(block);
+}
+
+
+/* **************************** VIEW ************************ */
+
+static void view3d_change_bgpic_ima(View3D *v3d, Image *newima) {
+ if (v3d->bgpic && v3d->bgpic->ima!=newima) {
+ if (newima)
+ id_us_plus((ID*) newima);
+ if (v3d->bgpic->ima)
+ v3d->bgpic->ima->id.us--;
+ v3d->bgpic->ima= newima;
+
+ if(v3d->bgpic->rect) MEM_freeN(v3d->bgpic->rect);
+ v3d->bgpic->rect= NULL;
+
+ allqueue(REDRAWBUTSVIEW, 0);
+ }
+}
+static void view3d_change_bgpic_tex(View3D *v3d, Tex *newtex) {
+ if (v3d->bgpic && v3d->bgpic->tex!=newtex) {
+ if (newtex)
+ id_us_plus((ID*) newtex);
+ if (v3d->bgpic->tex)
+ v3d->bgpic->tex->id.us--;
+ v3d->bgpic->tex= newtex;
+
+ allqueue(REDRAWBUTSVIEW, 0);
+ }
+}
+
+static void load_bgpic_image(char *name)
+{
+ Image *ima;
+ View3D *vd;
+
+ vd= scrarea_find_space_of_type(curarea, SPACE_VIEW3D);
+ if(vd==0 || vd->bgpic==0) return;
+
+ ima= add_image(name);
+ if(ima) {
+ if(vd->bgpic->ima) {
+ vd->bgpic->ima->id.us--;
+ }
+ vd->bgpic->ima= ima;
+
+ free_image_buffers(ima); /* forceer opnieuw inlezen */
+ ima->ok= 1;
+ }
+ allqueue(REDRAWBUTSVIEW, 0);
+
+}
+
+void do_viewbuts(unsigned short event)
+{
+ View3D *vd;
+ char *name;
+
+ vd= scrarea_find_space_of_type(curarea, SPACE_VIEW3D);
+ if(vd==0) return;
+
+ switch(event) {
+ case B_LOADBGPIC:
+ if(vd->bgpic && vd->bgpic->ima) name= vd->bgpic->ima->name;
+ else name= G.ima;
+
+ activate_imageselect(FILE_SPECIAL, "SELECT IMAGE", name, load_bgpic_image);
+ break;
+ case B_BLENDBGPIC:
+ if(vd->bgpic && vd->bgpic->rect) setalpha_bgpic(vd->bgpic);
+ break;
+ case B_BGPICBROWSE:
+ if(vd->bgpic) {
+ if (G.buts->menunr==-2) {
+ activate_databrowse((ID*) vd->bgpic->ima, ID_IM, 0, B_BGPICBROWSE, &G.buts->menunr, do_viewbuts);
+ } else if (G.buts->menunr>0) {
+ Image *newima= (Image*) BLI_findlink(&G.main->image, G.buts->menunr-1);
+
+ if (newima)
+ view3d_change_bgpic_ima(vd, newima);
+ }
+ }
+ break;
+ case B_BGPICCLEAR:
+ if (vd->bgpic)
+ view3d_change_bgpic_ima(vd, NULL);
+ break;
+ case B_BGPICTEX:
+ if (vd->bgpic) {
+ if (G.buts->texnr==-2) {
+ activate_databrowse((ID*) vd->bgpic->tex, ID_TE, 0, B_BGPICTEX, &G.buts->texnr, do_viewbuts);
+ } else if (G.buts->texnr>0) {
+ Tex *newtex= (Tex*) BLI_findlink(&G.main->tex, G.buts->texnr-1);
+
+ if (newtex)
+ view3d_change_bgpic_tex(vd, newtex);
+ }
+ }
+ break;
+ case B_BGPICTEXCLEAR:
+ if (vd->bgpic)
+ view3d_change_bgpic_tex(vd, NULL);
+ break;
+ }
+}
+
+void viewbuts(void)
+{
+ View3D *vd;
+ ID *id;
+ uiBlock *block;
+ char *strp, str[64];
+
+ /* op zoek naar spacedata */
+ vd= scrarea_find_space_of_type(curarea, SPACE_VIEW3D);
+ if(vd==0) return;
+
+ sprintf(str, "buttonswin %d", curarea->win);
+ block= uiNewBlock(&curarea->uiblocks, str, UI_EMBOSSX, UI_HELV, curarea->win);
+
+ if(vd->flag & V3D_DISPBGPIC) {
+ if(vd->bgpic==0) {
+ vd->bgpic= MEM_callocN(sizeof(BGpic), "bgpic");
+ vd->bgpic->size= 5.0;
+ vd->bgpic->blend= 0.5;
+ }
+ }
+
+ uiDefButS(block, TOG|BIT|1, REDRAWBUTSVIEW, "BackGroundPic", 347,160,127,29 ,
+ &vd->flag, 0, 0, 0, 0, "Display a picture in the 3D background");
+ if(vd->bgpic) {
+ uiDefButF(block, NUM, B_DIFF, "Size:",
+ 478,160,82,29, &vd->bgpic->size, 0.1,
+ 250.0, 100, 0, "Set the size for the width of the BackGroundPic");
+
+ id= (ID *)vd->bgpic->ima;
+ IDnames_to_pupstring(&strp, NULL, NULL, &(G.main->image), id, &(G.buts->menunr));
+ if(strp[0])
+ uiDefButS(block, MENU, B_BGPICBROWSE, strp, 347,112,20,19, &(G.buts->menunr), 0, 0, 0, 0, "Browse");
+ MEM_freeN(strp);
+
+ uiDefBut(block, BUT, B_LOADBGPIC, "LOAD", 370,112,189,19, 0, 0, 0, 0, 0, "Specify the BackGroundPic");
+ uiDefButF(block, NUMSLI, B_BLENDBGPIC, "Blend:", 347,84,213,19,&vd->bgpic->blend, 0.0,1.0, 0, 0, "Set the BackGroundPic transparency");
+
+ if(vd->bgpic->ima) {
+ uiDefBut(block, TEX, 0,"BGpic: ", 347,136,211,19,&vd->bgpic->ima->name,0.0,100.0, 0, 0, "The Selected BackGroundPic");
+ uiDefIconBut(block, BUT, B_BGPICCLEAR, ICON_X, 347+211,112,20,19, 0, 0, 0, 0, 0, "Remove background image link");
+ }
+
+ /* There is a bug here ... (what bug? where? what is this? - zr) */
+ /* textureblok: */
+ id= (ID *)vd->bgpic->tex;
+ IDnames_to_pupstring(&strp, NULL, NULL, &(G.main->tex), id, &(G.buts->texnr));
+ if (strp[0])
+ uiDefButS(block, MENU, B_BGPICTEX, strp, 347, 20, 20,19, &(G.buts->texnr), 0, 0, 0, 0, "Browse");
+ MEM_freeN(strp);
+
+ uiDefBut(block, LABEL, 0, "Select texture for animated backgroundimage", 370, 20, 300,19, 0, 0, 0, 0, 0, "");
+
+ if (id) {
+ uiDefBut(block, TEX, B_IDNAME, "TE:", 347,0,211,19, id->name+2, 0.0, 18.0, 0, 0, "");
+ uiDefIconBut(block, BUT, B_BGPICTEXCLEAR, ICON_X, 347+211,0,20,19, 0, 0, 0, 0, 0, "Remove background texture link");
+ }
+ }
+
+ uiDefButF(block, NUM, B_DIFF, "Grid:", 347, 60, 105, 19, &vd->grid, 0.001, 1000.0, 100, 0, "Set the distance between gridlines");
+ uiDefButS(block, NUM, B_DIFF, "GridLines:", 452, 60, 105, 19, &vd->gridlines, 0.0, 100.0, 100, 0, "Set the number of gridlines");
+ uiDefButF(block, NUM, B_DIFF, "Lens:", 557, 60, 105, 19, &vd->lens, 10.0, 120.0, 100, 0, "Set the lens for the perspective view");
+
+ uiDefButF(block, NUM, B_DIFF, "ClipStart:", 347, 40, 105, 19, &vd->near, 0.1*vd->grid, 100.0, 100, 0, "Set startvalue in perspective view mode");
+ uiDefButF(block, NUM, B_DIFF, "ClipEnd:", 452, 40, 105, 19, &vd->far, 1.0, 1000.0*vd->grid, 100, 0, "Set endvalue in perspective view mode");
+
+ /* for(b=0; b<8; b++) { */
+ /* for(a=0; a<8; a++) { */
+ /* uiDefButC(block, TOG|BIT|(7-a), 0, "", 100+12*a, 100-12*b, 12, 12, &(arr[b]),0,0,0,0); ,""*/
+ /* } */
+ /* } */
+ /* DefBut(BUT, 1001, "print", 50,100,50,20, 0, 0, 0, 0,0); */
+
+ uiDrawBlock(block);
+}
+
+void output_pic(char *name)
+{
+ strcpy(G.scene->r.pic, name);
+ allqueue(REDRAWBUTSRENDER, 0);
+}
+
+void backbuf_pic(char *name)
+{
+ Image *ima;
+
+ strcpy(G.scene->r.backbuf, name);
+ allqueue(REDRAWBUTSRENDER, 0);
+
+ ima= add_image(name);
+ if(ima) {
+ free_image_buffers(ima); /* forceer opnieuw inlezen */
+ ima->ok= 1;
+ }
+}
+
+void ftype_pic(char *name)
+{
+ strcpy(G.scene->r.ftype, name);
+ allqueue(REDRAWBUTSRENDER, 0);
+}
+
+
+/* **************************** VIEW ************************ */
+
+
+static void scene_change_set(Scene *sc, Scene *set) {
+ if (sc->set!=set) {
+ sc->set= set;
+
+ allqueue(REDRAWBUTSRENDER, 0);
+ allqueue(REDRAWVIEW3D, 0);
+ }
+}
+
+static void run_playanim(char *file) {
+ extern char bprogname[]; /* usiblender.c */
+ char str[FILE_MAXDIR+FILE_MAXFILE];
+ int pos[2], size[2];
+
+ calc_renderwin_rectangle(R.winpos, pos, size);
+
+ sprintf(str, "%s -a -p %d %d \"%s\"", bprogname, pos[0], pos[1], file);
+ system(str);
+}
+
+void do_renderbuts(unsigned short event)
+{
+ ScrArea *sa;
+ ID *id;
+ char file[FILE_MAXDIR+FILE_MAXFILE];
+
+ switch(event) {
+
+ case B_DORENDER:
+ BIF_do_render(0);
+ break;
+ case B_RTCHANGED:
+ allqueue(REDRAWALL, 0);
+ break;
+ case B_PLAYANIM:
+ makeavistring(file);
+ if(BLI_exist(file)) {
+ run_playanim(file);
+ }
+ else {
+ makepicstring(file, G.scene->r.sfra);
+ if(BLI_exist(file)) {
+ run_playanim(file);
+ }
+ else error("Can't find image: %s", file);
+ }
+ break;
+
+ case B_DOANIM:
+ BIF_do_render(1);
+ break;
+
+ case B_FS_PIC:
+ sa= closest_bigger_area();
+ areawinset(sa->win);
+ activate_fileselect(FILE_SPECIAL, "SELECT OUTPUT PICTURES", G.scene->r.pic, output_pic);
+ break;
+ case B_FS_BACKBUF:
+ sa= closest_bigger_area();
+ areawinset(sa->win);
+ activate_fileselect(FILE_SPECIAL, "SELECT BACKBUF PICTURE", G.scene->r.backbuf, backbuf_pic);
+ break;
+ case B_IS_BACKBUF:
+ sa= closest_bigger_area();
+ areawinset(sa->win);
+ activate_imageselect(FILE_SPECIAL, "SELECT BACKBUF PICTURE", G.scene->r.backbuf, backbuf_pic);
+ break;
+ case B_FS_FTYPE:
+ sa= closest_bigger_area();
+ areawinset(sa->win);
+ activate_fileselect(FILE_SPECIAL, "SELECT FTYPE", G.scene->r.ftype, ftype_pic);
+ break;
+ case B_IS_FTYPE:
+ sa= closest_bigger_area();
+ areawinset(sa->win);
+ activate_imageselect(FILE_SPECIAL, "SELECT FTYPE", G.scene->r.ftype, ftype_pic);
+ break;
+
+ case B_PR_PAL:
+ G.scene->r.xsch= 720;
+ G.scene->r.ysch= 576;
+ G.scene->r.xasp= 54;
+ G.scene->r.yasp= 51;
+ G.scene->r.size= 100;
+ G.scene->r.mode &= ~R_PANORAMA;
+ G.scene->r.xparts= G.scene->r.yparts= 1;
+
+ BLI_init_rctf(&G.scene->r.safety, 0.1, 0.9, 0.1, 0.9);
+ allqueue(REDRAWBUTSRENDER, 0);
+ allqueue(REDRAWVIEWCAM, 0);
+ break;
+#ifdef _WIN32
+ case B_FILETYPEMENU:
+ allqueue(REDRAWBUTSRENDER, 0);
+ // fall through to codec settings if this is the first
+ // time R_AVICODEC is selected for this scene.
+ if ((G.scene->r.imtype != R_AVICODEC) || (G.scene->r.avicodecdata)) {
+ break;
+ }
+ case B_SELECTCODEC:
+ get_codec_settings();
+ break;
+#endif
+ case B_PR_FULL:
+ G.scene->r.xsch= 1280;
+ G.scene->r.ysch= 1024;
+ G.scene->r.xasp= 1;
+ G.scene->r.yasp= 1;
+ G.scene->r.size= 100;
+ G.scene->r.mode &= ~R_PANORAMA;
+ G.scene->r.xparts= G.scene->r.yparts= 1;
+
+ BLI_init_rctf(&G.scene->r.safety, 0.1, 0.9, 0.1, 0.9);
+ allqueue(REDRAWBUTSRENDER, 0);
+ allqueue(REDRAWVIEWCAM, 0);
+ break;
+ case B_PR_PRV:
+ G.scene->r.xsch= 640;
+ G.scene->r.ysch= 512;
+ G.scene->r.xasp= 1;
+ G.scene->r.yasp= 1;
+ G.scene->r.size= 50;
+ G.scene->r.mode &= ~R_PANORAMA;
+ G.scene->r.xparts= G.scene->r.yparts= 1;
+
+ BLI_init_rctf(&G.scene->r.safety, 0.1, 0.9, 0.1, 0.9);
+ allqueue(REDRAWVIEWCAM, 0);
+ allqueue(REDRAWBUTSRENDER, 0);
+ break;
+ case B_PR_CDI:
+ G.scene->r.xsch= 384;
+ G.scene->r.ysch= 280;
+ G.scene->r.xasp= 1;
+ G.scene->r.yasp= 1;
+ G.scene->r.size= 100;
+ G.scene->r.mode &= ~R_PANORAMA;
+ G.scene->r.xparts= G.scene->r.yparts= 1;
+
+ BLI_init_rctf(&G.scene->r.safety, 0.15, 0.85, 0.15, 0.85);
+ allqueue(REDRAWVIEWCAM, 0);
+ allqueue(REDRAWBUTSRENDER, 0);
+ break;
+ case B_PR_PAL169:
+ G.scene->r.xsch= 720;
+ G.scene->r.ysch= 576;
+ G.scene->r.xasp= 64;
+ G.scene->r.yasp= 45;
+ G.scene->r.size= 100;
+ G.scene->r.mode &= ~R_PANORAMA;
+ G.scene->r.xparts= G.scene->r.yparts= 1;
+
+ BLI_init_rctf(&G.scene->r.safety, 0.1, 0.9, 0.1, 0.9);
+ allqueue(REDRAWVIEWCAM, 0);
+ allqueue(REDRAWBUTSRENDER, 0);
+ break;
+ case B_PR_D2MAC:
+ G.scene->r.xsch= 1024;
+ G.scene->r.ysch= 576;
+ G.scene->r.xasp= 1;
+ G.scene->r.yasp= 1;
+ G.scene->r.size= 50;
+ G.scene->r.mode &= ~R_PANORAMA;
+ G.scene->r.xparts= G.scene->r.yparts= 1;
+
+ BLI_init_rctf(&G.scene->r.safety, 0.1, 0.9, 0.1, 0.9);
+ allqueue(REDRAWVIEWCAM, 0);
+ allqueue(REDRAWBUTSRENDER, 0);
+ break;
+ case B_PR_MPEG:
+ G.scene->r.xsch= 368;
+ G.scene->r.ysch= 272;
+ G.scene->r.xasp= 105;
+ G.scene->r.yasp= 100;
+ G.scene->r.size= 100;
+ G.scene->r.mode &= ~R_PANORAMA;
+ G.scene->r.xparts= G.scene->r.yparts= 1;
+
+ BLI_init_rctf(&G.scene->r.safety, 0.1, 0.9, 0.1, 0.9);
+ allqueue(REDRAWVIEWCAM, 0);
+ allqueue(REDRAWBUTSRENDER, 0);
+ break;
+ case B_PR_PC:
+ G.scene->r.xsch= 640;
+ G.scene->r.ysch= 480;
+ G.scene->r.xasp= 100;
+ G.scene->r.yasp= 100;
+ G.scene->r.size= 100;
+ G.scene->r.mode &= ~R_PANORAMA;
+ G.scene->r.xparts= G.scene->r.yparts= 1;
+
+ BLI_init_rctf(&G.scene->r.safety, 0.0, 1.0, 0.0, 1.0);
+ allqueue(REDRAWVIEWCAM, 0);
+ allqueue(REDRAWBUTSRENDER, 0);
+ break;
+ case B_PR_PRESET:
+ G.scene->r.xsch= 720;
+ G.scene->r.ysch= 576;
+ G.scene->r.xasp= 54;
+ G.scene->r.yasp= 51;
+ G.scene->r.size= 100;
+ G.scene->r.mode= R_OSA+R_SHADOW+R_FIELDS;
+ G.scene->r.imtype= R_TARGA;
+ G.scene->r.xparts= G.scene->r.yparts= 1;
+
+ BLI_init_rctf(&G.scene->r.safety, 0.1, 0.9, 0.1, 0.9);
+ allqueue(REDRAWVIEWCAM, 0);
+ allqueue(REDRAWBUTSRENDER, 0);
+ break;
+ case B_PR_PANO:
+ G.scene->r.xsch= 36;
+ G.scene->r.ysch= 176;
+ G.scene->r.xasp= 115;
+ G.scene->r.yasp= 100;
+ G.scene->r.size= 100;
+ G.scene->r.mode |= R_PANORAMA;
+ G.scene->r.xparts= 16;
+ G.scene->r.yparts= 1;
+
+ BLI_init_rctf(&G.scene->r.safety, 0.1, 0.9, 0.1, 0.9);
+ allqueue(REDRAWVIEWCAM, 0);
+ allqueue(REDRAWBUTSRENDER, 0);
+ break;
+
+ case B_SETBROWSE:
+ id= (ID*) G.scene->set;
+
+ if (G.buts->menunr==-2) {
+ activate_databrowse(id, ID_SCE, 0, B_SETBROWSE, &G.buts->menunr, do_renderbuts);
+ } else if (G.buts->menunr>0) {
+ Scene *newset= (Scene*) BLI_findlink(&G.main->scene, G.buts->menunr-1);
+
+ if (newset==G.scene)
+ error("Not allowed");
+ else if (newset)
+ scene_change_set(G.scene, newset);
+ }
+ break;
+ case B_CLEARSET:
+ scene_change_set(G.scene, NULL);
+ break;
+ }
+}
+
+uiBlock *edge_render_menu(void *arg_unused)
+{
+ uiBlock *block;
+
+ block= uiNewBlock(&curarea->uiblocks,
+ "edge render", UI_EMBOSSX, UI_HELV,
+ curarea->win);
+
+ /* use this for a fake extra empy space around the buttons */
+ uiDefBut(block, LABEL, 0, "",
+/* 285, -20, 230, 100, NULL, */
+ 285, -20, 230, 120, NULL,
+ 0, 0, 0, 0, "");
+
+ uiDefButS(block, NUM, 0,"Eint:",
+ 295,50,70,19,
+ &G.scene->r.edgeint, 0.0, 255.0, 0, 0,
+ "Sets edge intensity for Toon shading");
+ uiBlockSetCol(block, BUTGREEN);
+ uiDefButI(block, TOG, 0,"Shift",
+ 365,50,70,19,
+ &G.compat, 0, 0, 0, 0,
+ "For unified renderer: use old offsets for edges");
+ uiDefButI(block, TOG, 0,"All", 435,50,70,19,
+ &G.notonlysolid, 0, 0, 0, 0,
+ "For unified renderer: also consider transparent "
+ "faces for toon shading");
+
+ /* colour settings for the toon shading */
+ uiBlockSetCol(block, BUTGREY);
+ uiDefButF(block, COL, B_EDGECOLSLI, "",
+ 295,-10,30,60,
+ &(G.scene->r.edgeR), 0, 0, 0, 0,
+ "");
+
+ uiDefButF(block, NUMSLI, 0, "R ",
+ 325, 30, 180,19,
+ &G.scene->r.edgeR, 0.0, 1.0, B_EDGECOLSLI, 0,
+ "For unified renderer: Colour for edges in toon shading mode.");
+ uiDefButF(block, NUMSLI, 0, "G ",
+ 325, 10, 180,19,
+ &G.scene->r.edgeG, 0.0, 1.0, B_EDGECOLSLI, 0,
+ "For unified renderer: Colour for edges in toon shading mode.");
+ uiDefButF(block, NUMSLI, 0, "B ",
+ 325, -10, 180,19,
+ &G.scene->r.edgeB, 0.0, 1.0, B_EDGECOLSLI, 0,
+ "For unified renderer: Colour for edges in toon shading mode.");
+
+ uiDefButI(block, NUM, 0,"AntiShift",
+ 365,70,140,19,
+ &(G.scene->r.same_mat_redux), 0, 255.0, 0, 0,
+ "For unified renderer: reduce intensity on boundaries "
+ "with identical materials with this number.");
+
+ uiBlockSetDirection(block, UI_TOP);
+
+ return block;
+}
+
+static uiBlock *post_render_menu(void *arg_unused)
+{
+ uiBlock *block;
+
+ block= uiNewBlock(&curarea->uiblocks, "post render", UI_EMBOSSX, UI_HELV, curarea->win);
+
+ /* use this for a fake extra empy space around the buttons */
+ uiDefBut(block, LABEL, 0, "", -10, 10, 200, 80, NULL, 0, 0, 0, 0, "");
+
+ uiDefButF(block, NUMSLI, 0,"Add:", 0,60,180,19,
+ &G.scene->r.postadd, -1.0, 1.0, 0, 0, "");
+ uiDefButF(block, NUMSLI, 0,"Mul:", 0,40,180,19,
+ &G.scene->r.postmul, 0.01, 4.0, 0, 0, "");
+ uiDefButF(block, NUMSLI, 0,"Gamma:", 0,20,180,19,
+ &G.scene->r.postgamma, 0.2, 2.0, 0, 0, "");
+
+ uiBlockSetDirection(block, UI_TOP);
+
+ return block;
+}
+
+
+static uiBlock *framing_render_menu(void *arg_unused)
+{
+ uiBlock *block;
+ short yco = 60, xco = 0;
+ int randomcolorindex = 1234;
+
+ block= uiNewBlock(&curarea->uiblocks, "framing_options", UI_EMBOSSX, UI_HELV, curarea->win);
+
+ /* use this for a fake extra empy space around the buttons */
+ uiDefBut(block, LABEL, 0, "", -10, -10, 300, 100, NULL, 0, 0, 0, 0, "");
+
+ uiDefBut(block, LABEL, B_NOP, "Framing:", xco, yco, 68,19, 0, 0, 0, 0, 0, "");
+ uiDefButC(block, ROW, 0, "Stretch", xco += 70, yco, 68, 19, &G.scene->framing.type, 1.0, SCE_GAMEFRAMING_SCALE , 0, 0, "Stretch or squeeze the viewport to fill the display window");
+ uiDefButC(block, ROW, 0, "Expose", xco += 70, yco, 68, 19, &G.scene->framing.type, 1.0, SCE_GAMEFRAMING_EXTEND, 0, 0, "Show the entire viewport in the display window, viewing more horizontally or vertically");
+ uiDefButC(block, ROW, 0, "Bars", xco += 70, yco, 68, 19, &G.scene->framing.type, 1.0, SCE_GAMEFRAMING_BARS , 0, 0, "Show the entire viewport in the display window, using bar horizontally or vertically");
+
+ yco -= 20;
+ xco = 35;
+
+ uiDefButF(block, COL, randomcolorindex, "", 0, yco - 58 + 18, 33, 58, &G.scene->framing.col[0], 0, 0, 0, 0, "");
+
+ uiDefButF(block, NUMSLI, 0, "R ", xco,yco,243,18, &G.scene->framing.col[0], 0.0, 1.0, randomcolorindex, 0, "Set the red component of the bars");
+ yco -= 20;
+ uiDefButF(block, NUMSLI, 0, "G ", xco,yco,243,18, &G.scene->framing.col[1], 0.0, 1.0, randomcolorindex, 0, "Set the green component of the bars");
+ yco -= 20;
+ uiDefButF(block, NUMSLI, 0, "B ", xco,yco,243,18, &G.scene->framing.col[2], 0.0, 1.0, randomcolorindex, 0, "Set the blue component of the bars");
+
+ uiBlockSetDirection(block, UI_TOP);
+
+ return block;
+}
+
+
+static char *imagetype_pup(void)
+{
+ static char string[1024];
+ char formatstring[1024];
+
+ strcpy(formatstring, "Save image as: %%t|%s %%x%d|%s %%x%d|%s %%x%d|%s %%x%d|%s %%x%d|%s %%x%d|%s %%x%d|%s %%x%d|%s %%x%d");
+
+#ifdef __sgi
+ strcat(formatstring, "|%s %%x%d"); // add space for Movie
+#endif
+
+ if (LICENSE_KEY_VALID) {
+ strcat(formatstring, "|%s %%x%d"); // add space for PNG
+
+#ifdef _WIN32
+ strcat(formatstring, "|%s %%x%d"); // add space for AVI Codec
+#endif
+
+ sprintf(string, formatstring,
+ "AVI Raw", R_AVIRAW,
+ "AVI Jpeg", R_AVIJPEG,
+#ifdef _WIN32
+ "AVI Codec", R_AVICODEC,
+#endif
+ "Targa", R_TARGA,
+ "Targa Raw", R_RAWTGA,
+ "PNG", R_PNG,
+ "Jpeg", R_JPEG90,
+ "HamX", R_HAMX,
+ "Iris", R_IRIS,
+ "Iris + Zbuffer", R_IRIZ,
+ "Ftype", R_FTYPE,
+ "Movie", R_MOVIE
+ );
+ } else {
+ sprintf(string, formatstring,
+ "AVI Raw", R_AVIRAW,
+ "AVI Jpeg", R_AVIJPEG,
+ "Targa", R_TARGA,
+ "Targa Raw", R_RAWTGA,
+ "Jpeg", R_JPEG90,
+ "HamX", R_HAMX,
+ "Iris", R_IRIS,
+ "Iris + Zbuffer", R_IRIZ,
+ "Ftype", R_FTYPE,
+ "Movie", R_MOVIE
+ );
+ }
+
+ return (string);
+}
+
+
+void renderbuts(void)
+{
+ ID *id;
+ int a,b;
+ uiBlock *block;
+ char *strp;
+ char str[64];
+ int yofs;
+
+ sprintf(str, "buttonswin %d", curarea->win);
+ block= uiNewBlock(&curarea->uiblocks, str, UI_EMBOSSX, UI_HELV, curarea->win);
+
+ uiDefBut(block, TEX,0,"", 34,172,257,19,G.scene->r.pic, 0.0,79.0, 0, 0, "Directory/name to save rendered Pics to");
+ uiDefBut(block, BUT,B_FS_PIC," ", 10,172,22,19, 0, 0, 0, 0, 0, "Open Fileselect to get Pics dir/name");
+ uiDefBut(block, TEX,0,"", 34,149,257,19,G.scene->r.backbuf, 0.0,79.0, 0, 0, "Image to use as background for rendering");
+ uiDefBut(block, BUT,B_FS_BACKBUF," ", 21,149,11,19, 0, 0, 0, 0, 0, "Open Fileselect to get Backbuf image");
+ uiDefBut(block, TEX,0,"", 34,126,257,19,G.scene->r.ftype,0.0,79.0, 0, 0, "Image to use with FTYPE Image type");
+ uiDefBut(block, BUT,B_FS_FTYPE," ", 21,126,11,19, 0, 0, 0, 0, 0, "Open Fileselect to get Ftype image");
+ uiDefIconBut(block, BUT, B_CLEARSET, ICON_X, 267,102,24,21, 0, 0, 0, 0, 0, "Remove Set link");
+
+ /* SET BUTTON */
+ id= (ID *)G.scene->set;
+ IDnames_to_pupstring(&strp, NULL, NULL, &(G.main->scene), id, &(G.buts->menunr));
+ if(strp[0])
+ uiDefButS(block, MENU, B_SETBROWSE, strp, 10,103,22,19, &(G.buts->menunr), 0, 0, 0, 0, "Scene to link as a Set");
+ MEM_freeN(strp);
+
+ uiDefBut(block, LABEL, 0, "Set", 295,103,63,19, 0, 0, 0, 0, 0, "");
+
+ uiBlockSetCol(block, BUTBLUE);
+
+ if(G.scene->set) {
+ uiSetButLock(1, NULL);
+ uiDefIDPoinBut(block, test_scenepoin_but, 0, "", 34,103,231,19, &(G.scene->set), "Name of the Set");
+ uiClearButLock();
+ }
+
+ uiBlockSetCol(block, BUTSALMON);
+ uiDefBut(block, BUT,B_IS_BACKBUF," ", 10,149,11,19, 0, 0, 0, 0, 0, "Open Imageselect to get Backbuf image");
+ uiDefBut(block, BUT,B_IS_FTYPE," ", 10,126,11,19, 0, 0, 0, 0, 0, "Open Imageselect to get Ftype image");
+ uiBlockSetCol(block, BUTGREY);
+
+ uiDefBut(block, LABEL,0,"Pics", 295,172,63,19, 0, 0, 0, 0, 0, "");
+ uiDefButS(block, TOG|BIT|0, 0,"Backbuf", 295,149,63,19, &G.scene->r.bufflag, 0, 0, 0, 0, "Enable/Disable use of Backbuf image");
+ uiDefBut(block, LABEL,0,"Ftype", 295,126,63,19, 0, 0, 0, 0, 0, "");
+
+ uiBlockSetCol(block, BUTGREY);
+
+ for(b=0; b<3; b++)
+ for(a=0; a<3; a++)
+ uiDefButS(block, TOG|BIT|(3*b+a),800,"", (short)(34+18*a),(short)(11+12*b),16,10, &R.winpos, 0, 0, 0, 0, "Render window placement on screen");
+
+ uiDefButS(block, ROW, B_REDR, "DispView", 99,28,77,18, &R.displaymode, 0.0, (float)R_DISPLAYVIEW, 0, 0, "Sets render output to display in 3D view");
+ uiDefButS(block, ROW, B_REDR, "DispWin", 99,10,78,18, &R.displaymode, 0.0, (float)R_DISPLAYWIN, 0, 0, "Sets render output to display in a seperate window");
+
+ uiDefButS(block, TOG|BIT|4, 0, "Extensions", 190,10,95,18, &G.scene->r.scemode, 0.0, 0.0, 0, 0, "Adds extensions to the output when rendering animations");
+
+ uiBlockSetCol(block, BUTSALMON);
+
+ uiDefBut(block, BUT,B_DORENDER,"RENDER", 369,142,192,47, 0, 0, 0, 0, 0, "Start the rendering");
+
+ uiBlockSetCol(block, BUTGREY);
+ uiDefButS(block, TOG|BIT|1,0,"Shadows", 565,167,122,22, &G.scene->r.mode, 0, 0, 0, 0, "Enable shadow calculation");
+ uiDefButS(block, TOG|BIT|10,0,"Panorama",565,142,122,22, &G.scene->r.mode, 0, 0, 0, 0, "Enable panorama rendering (output width is multiplied by Xparts)");
+
+ uiDefButS(block, ROW,B_DIFF,"100%", 565,114,121,20,&G.scene->r.size,1.0,100.0, 0, 0, "Set render size to defined size");
+ uiDefButS(block, ROW,B_DIFF,"75%", 565,90,36,20,&G.scene->r.size,1.0,75.0, 0, 0, "Set render size to 3/4 of defined size");
+ uiDefButS(block, ROW,B_DIFF,"50%", 604,90,40,20,&G.scene->r.size,1.0,50.0, 0, 0, "Set render size to 1/2 of defined size");
+ uiDefButS(block, ROW,B_DIFF,"25%", 647,90,39,20,&G.scene->r.size,1.0,25.0, 0, 0, "Set render size to 1/4 of defined size");
+
+ uiDefButS(block, TOG|BIT|0, 0, "OSA", 369,114,124,20,&G.scene->r.mode, 0, 0, 0, 0, "Enables Oversampling (Anti-aliasing)");
+ uiDefButF(block, NUM,B_DIFF,"Bf:", 495,90,65,20,&G.scene->r.blurfac, 0.01, 5.0, 10, 0, "Sets motion blur factor");
+ uiDefButS(block, TOG|BIT|14, 0, "MBLUR", 495,114,66,20,&G.scene->r.mode, 0, 0, 0, 0, "Enables Motion Blur calculation");
+
+ uiDefButS(block, ROW,B_DIFF,"5", 369,90,29,20,&G.scene->r.osa,2.0,5.0, 0, 0, "Sets oversample level to 5");
+ uiDefButS(block, ROW,B_DIFF,"8", 400,90,29,20,&G.scene->r.osa,2.0,8.0, 0, 0, "Sets oversample level to 8 (Recommended)");
+ uiDefButS(block, ROW,B_DIFF,"11", 431,90,33,20,&G.scene->r.osa,2.0,11.0, 0, 0, "Sets oversample level to 11");
+ uiDefButS(block, ROW,B_DIFF,"16", 466,90,28,20,&G.scene->r.osa,2.0,16.0, 0, 0, "Sets oversample level to 16");
+
+ uiDefButS(block, NUM,B_DIFF,"Xparts:", 369,42,99,31,&G.scene->r.xparts,1.0, 64.0, 0, 0, "Sets the number of horizontal parts to render image in (For panorama sets number of camera slices)");
+ uiDefButS(block, NUM,B_DIFF,"Yparts:", 472,42,86,31,&G.scene->r.yparts,1.0, 64.0, 0, 0, "Sets the number of vertical parts to render image in");
+
+ uiDefButS(block, TOG|BIT|6,0,"Fields",564,42,90,31,&G.scene->r.mode, 0, 0, 0, 0, "Enables field rendering");
+
+ uiDefButS(block, TOG|BIT|13,0,"Odd", 655,57,30,16,&G.scene->r.mode, 0, 0, 0, 0, "Enables Odd field first rendering (Default: Even field)");
+ uiDefButS(block, TOG|BIT|7,0,"x", 655,42,30,15,&G.scene->r.mode, 0, 0, 0, 0, "Disables time difference in field calculations");
+
+ uiDefButS(block, ROW,800,"Sky", 369,11,38,24,&G.scene->r.alphamode,3.0,0.0, 0, 0, "Fill background with sky");
+ uiDefButS(block, ROW,800,"Premul", 410,11,54,24,&G.scene->r.alphamode,3.0,1.0, 0, 0, "Multiply alpha in advance");
+ uiDefButS(block, ROW,800,"Key", 467,11,44,24,&G.scene->r.alphamode,3.0,2.0, 0, 0, "Alpha and colour values remain unchanged");
+
+ /* Toon shading buttons */
+ uiDefButS(block, TOG|BIT|5, 0,"Edge", 295,70,70,19,
+ &G.scene->r.mode, 0, 0, 0, 0, "Enable Toon shading");
+ uiDefBlockBut(block, edge_render_menu, NULL, "Edge Settings |>> ", 155, 70, 138, 19, "Display edge settings");
+
+ /* unified render buttons */
+ if(G.scene->r.mode & R_UNIFIED) {
+ uiDefBlockBut(block, post_render_menu, NULL, "Post process |>> ", 15, 70, 138, 19, "Only for unified render");
+ if (G.scene->r.mode & R_GAMMA) {
+ uiDefButF(block, NUMSLI, 0,"Gamma:", 15, 50, 280, 19,
+ &(G.scene->r.gamma), 0.2, 5.0, B_GAMMASLI, 0,
+ "The gamma value for blending oversampled images (1.0 = no correction).");
+ }
+ }
+
+
+ uiDefButS(block, TOG|BIT|9,REDRAWVIEWCAM, "Border", 565,11,58,24, &G.scene->r.mode, 0, 0, 0, 0, "Render a small cut-out of the image");
+ uiDefButS(block, TOG|BIT|2,0, "Gamma", 626,11,58,24, &G.scene->r.mode, 0, 0, 0, 0, "Enable gamma correction");
+
+ uiBlockSetCol(block, BUTSALMON);
+ uiDefBut(block, BUT,B_DOANIM,"ANIM", 692,142,192,47, 0, 0, 0, 0, 0, "Start rendering a sequence");
+
+ uiBlockSetCol(block, BUTBLUE);
+
+ uiDefButS(block, TOG|BIT|0, 0, "Do Sequence", 692,114,192,20, &G.scene->r.scemode, 0, 0, 0, 0, "Enables sequence output rendering (Default: 3D rendering)");
+ uiDefButS(block, TOG|BIT|1, 0, "Render Daemon", 692,90,192,20, &G.scene->r.scemode, 0, 0, 0, 0, "Let external network render current scene");
+
+ uiBlockSetCol(block, BUTGREY);
+ uiDefBut(block, BUT,B_PLAYANIM, "PLAY", 692,40,94,33, 0, 0, 0, 0, 0, "Play animation of rendered images/avi (searches Pics: field)");
+
+ uiDefButS(block, NUM, B_RTCHANGED, "rt:", 790,40,95,33, &G.rt, 0.0, 256.0, 0, 0, "General testing/debug button");
+
+ uiDefButS(block, ROW,B_DIFF,"BW", 892, 10,74,20, &G.scene->r.planes, 5.0,(float)R_PLANESBW, 0, 0, "Images are saved with BW (grayscale) data");
+ uiDefButS(block, ROW,B_DIFF,"RGB", 968, 10,74,20, &G.scene->r.planes, 5.0,(float)R_PLANES24, 0, 0, "Images are saved with RGB (color) data");
+ uiDefButS(block, ROW,B_DIFF,"RGBA", 1044, 10,75,20, &G.scene->r.planes, 5.0,(float)R_PLANES32, 0, 0, "Images are saved with RGB and Alpha data (if supported)");
+
+ yofs = 54;
+
+#ifdef __sgi
+ yofs = 76;
+ uiDefButS(block, NUM,B_DIFF,"MaxSize:", 892,32,165,20, &G.scene->r.maximsize, 0.0, 500.0, 0, 0, "Maximum size per frame to save in an SGI movie");
+ uiBlockSetCol(block, BUTGREEN);
+ uiDefButS(block, TOG|BIT|12,0,"Cosmo", 1059,32,60,20, &G.scene->r.mode, 0, 0, 0, 0, "Attempt to save SGI movies using Cosmo hardware");
+ uiBlockSetCol(block, BUTGREY);
+#endif
+
+ uiDefButS(block, MENU,B_FILETYPEMENU,imagetype_pup(), 892,yofs,174,20, &G.scene->r.imtype, 0, 0, 0, 0, "Images are saved in this file format");
+ uiBlockSetCol(block, BUTGREEN);
+ uiDefButS(block, TOG|BIT|11,0, "Crop", 1068,yofs,51,20, &G.scene->r.mode, 0, 0, 0, 0, "Exclude border rendering from total image");
+ uiBlockSetCol(block, BUTGREY);
+
+ yofs -= 22;
+
+ if(G.scene->r.quality==0) G.scene->r.quality= 90;
+
+#ifdef _WIN32
+ if (G.scene->r.imtype == R_AVICODEC) {
+#else
+ if (0) {
+#endif
+ uiDefBut(block, BUT,B_SELECTCODEC, "Select Codec", 892,yofs,112,20, 0, 0, 0, 0, 0, "Set codec settings for AVI Codec");
+ } else {
+ uiDefButS(block, NUM,0, "Quality:", 892,yofs,112,20, &G.scene->r.quality, 10.0, 100.0, 0, 0, "Quality setting for JPEG images, AVI Jpeg and SGI movies");
+ }
+ uiDefButS(block, NUM,REDRAWSEQ,"Frs/sec:", 1007,yofs,112,20, &G.scene->r.frs_sec, 1.0, 120.0, 0, 0, "Frames per second, for AVI and Sequence window grid");
+
+ uiDefButS(block, NUM,REDRAWSEQ,"Sta:", 692,10,94,24, &G.scene->r.sfra,1.0,18000.0, 0, 0, "The start frame of the animation");
+ uiDefButS(block, NUM,REDRAWSEQ,"End:", 790,10,95,24, &G.scene->r.efra,1.0,18000.0, 0, 0, "The end frame of the animation");
+
+ uiDefBlockBut(block, framing_render_menu, NULL, "Game framing settings |>> ", 892, 169, 227, 20, "Display game framing settings");
+
+ uiDefButS(block, NUM,REDRAWVIEWCAM,"SizeX:", 892 ,136,112,27, &G.scene->r.xsch, 4.0, 10000.0, 0, 0, "The image width in pixels");
+ uiDefButS(block, NUM,REDRAWVIEWCAM,"SizeY:", 1007,136,112,27, &G.scene->r.ysch, 4.0,10000.0, 0, 0, "The image height in scanlines");
+ uiDefButS(block, NUM,REDRAWVIEWCAM,"AspX:", 892 ,114,112,20, &G.scene->r.xasp, 1.0,200.0, 0, 0, "The horizontal aspect ratio");
+ uiDefButS(block, NUM,REDRAWVIEWCAM,"AspY:", 1007,114,112,20, &G.scene->r.yasp, 1.0,200.0, 0, 0, "The vertical aspect ratio");
+
+ uiDefBut(block, BUT,B_PR_PAL, "PAL", 1146,170,133,18, 0, 0, 0, 0, 0, "Size preset: Image size - 720x576, Aspect ratio - 54x51");
+ uiDefBut(block, BUT,B_PR_PRESET, "Default", 1146,149,133,18, 0, 0, 0, 0, 0, "Same as PAL, with render settings (OSA, Shadows, Fields)");
+ uiDefBut(block, BUT,B_PR_PRV, "Preview", 1146,115,133,18, 0, 0, 0, 0, 0, "Size preset: Image size - 640x512, Render size 50%");
+ uiDefBut(block, BUT,B_PR_PC, "PC", 1146,94,133,18, 0, 0, 0, 0, 0, "Size preset: Image size - 640x480, Aspect ratio - 100x100");
+ uiDefBut(block, BUT,B_PR_PAL169, "PAL 16:9", 1146,73,133,18, 0, 0, 0, 0, 0, "Size preset: Image size - 720x576, Aspect ratio - 64x45");
+ uiDefBut(block, BUT,B_PR_PANO, "PANO", 1146,52,133,18, 0, 0, 0, 0, 0, "Standard panorama settings");
+ uiDefBut(block, BUT,B_PR_FULL, "FULL", 1146,31,133,18, 0, 0, 0, 0, 0, "Size preset: Image size - 1280x1024, Aspect ratio - 1x1");
+ uiDefButS(block, TOG|BIT|15, B_REDR, "Unified Renderer", 1146,10,133,18,
+ &G.scene->r.mode, 0, 0, 0, 0,
+ "Use the unified renderer.");
+
+ uiDrawBlock(block);
+}
+
+/* ********************* CONSTRAINT ***************************** */
+
+static void activate_constraint_ipo_func (void *arg1v, void *unused)
+{
+
+ bConstraint *con = arg1v;
+ bConstraintChannel *chan;
+ ListBase *conbase;
+ Ipo *ipo = NULL;
+
+ get_constraint_client(NULL, NULL, NULL);
+
+ conbase = get_constraint_client_channels(1);
+
+ if (!conbase)
+ return;
+
+ /* See if this list already has an appropriate channel */
+ chan = find_constraint_channel(conbase, con->name);
+
+ if (!chan){
+ /* Add a new constraint channel */
+ chan = add_new_constraint_channel(con->name);
+ BLI_addtail(conbase, chan);
+ }
+
+ /* Ensure there is an ipo to display */
+ if (!chan->ipo){
+ chan->ipo = add_ipo(con->name, IPO_CO);
+ }
+
+ /* Make this the active channel */
+ OBACT->activecon = chan;
+
+ allqueue(REDRAWIPO, 0);
+ allqueue(REDRAWNLA, 0);
+
+}
+
+static void del_constraint_func (void *arg1v, void *arg2v)
+{
+ bConstraint *con= arg1v;
+ Object *ob;
+
+ ListBase *lb= arg2v;
+
+ ob=OBACT;
+
+ if (ob->activecon && !strcmp(ob->activecon->name, con->name))
+ ob->activecon = NULL;
+
+ free_constraint_data (con);
+
+ BLI_freelinkN(lb, con);
+
+ allqueue(REDRAWBUTSCONSTRAINT, 0);
+ allqueue(REDRAWIPO, 0);
+
+}
+
+static void verify_constraint_name_func (void *data, void *data2_unused)
+{
+ ListBase *conlist;
+ bConstraint *con;
+ char ownerstr[64];
+ short type;
+
+ con = (bConstraint*) data;
+ if (!con)
+ return;
+
+ conlist = get_constraint_client(ownerstr, &type, NULL);
+ unique_constraint_name (con, conlist);
+}
+
+static void constraint_changed_func (void *data, void *data2_unused)
+{
+ bConstraint *con = (bConstraint*) data;
+
+ if (con->type == con->otype)
+ return;
+
+ free_constraint_data (con);
+ con->data = new_constraint_data(con->type);
+
+}
+
+static void move_constraint_func (void *datav, void *data2_unused)
+{
+ bConstraint *constraint_to_move= datav;
+ int val;
+ ListBase *conlist;
+ char ownerstr[64];
+ short type;
+ bConstraint *curCon, *con, *neighbour;
+
+ val= pupmenu("Move up%x1|Move down %x2");
+
+ con = constraint_to_move;
+
+ if(val>0) {
+ conlist = get_constraint_client(ownerstr, &type, NULL);
+ for (curCon = conlist->first; curCon; curCon = curCon->next){
+ if (curCon == con){
+ /* Move up */
+ if (val == 1 && con->prev){
+ neighbour = con->prev;
+ BLI_remlink(conlist, neighbour);
+ BLI_insertlink(conlist, con, neighbour);
+ }
+ /* Move down */
+ else if (val == 2 && con->next){
+ neighbour = con->next;
+ BLI_remlink (conlist, con);
+ BLI_insertlink(conlist, neighbour, con);
+ }
+ break;
+ }
+ }
+ }
+}
+
+static void get_constraint_typestring (char *str, bConstraint *con)
+{
+ switch (con->type){
+ case CONSTRAINT_TYPE_CHILDOF:
+ strcpy (str, "Child Of");
+ return;
+ case CONSTRAINT_TYPE_NULL:
+ strcpy (str, "Null");
+ return;
+ case CONSTRAINT_TYPE_TRACKTO:
+ strcpy (str, "Track To");
+ return;
+ case CONSTRAINT_TYPE_KINEMATIC:
+ strcpy (str, "IK Solver");
+ return;
+ case CONSTRAINT_TYPE_ROTLIKE:
+ strcpy (str, "Copy Rotation");
+ return;
+ case CONSTRAINT_TYPE_LOCLIKE:
+ strcpy (str, "Copy Location");
+ return;
+ case CONSTRAINT_TYPE_ACTION:
+ strcpy (str, "Action");
+ return;
+ default:
+ strcpy (str, "Unknown");
+ return;
+ }
+}
+
+static BIFColorID get_constraint_col(bConstraint *con)
+{
+ switch (con->type) {
+ case CONSTRAINT_TYPE_NULL:
+ return BUTWHITE;
+ case CONSTRAINT_TYPE_KINEMATIC:
+ return BUTPURPLE;
+ case CONSTRAINT_TYPE_TRACKTO:
+ return BUTGREEN;
+ case CONSTRAINT_TYPE_ROTLIKE:
+ return BUTBLUE;
+ case CONSTRAINT_TYPE_LOCLIKE:
+ return BUTYELLOW;
+ case CONSTRAINT_TYPE_ACTION:
+ return BUTPINK;
+ default:
+ return REDALERT;
+ }
+}
+
+static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, short *xco, short *yco, short type)
+{
+ uiBut *but;
+ char typestr[64];
+ short height, width = 268;
+ BIFColorID curCol;
+
+ uiBlockSetEmboss(block, UI_EMBOSSW);
+
+ get_constraint_typestring (typestr, con);
+
+ curCol = get_constraint_col(con);
+ /* Draw constraint header */
+ uiBlockSetCol(block, BUTSALMON);
+
+ but = uiDefIconBut(block, BUT, B_CONSTRAINT_REDRAW, ICON_X, *xco, *yco, 20, 20, list, 0.0, 0.0, 0.0, 0.0, "Delete constraint");
+
+ uiButSetFunc(but, del_constraint_func, con, list);
+
+ if (con->flag & CONSTRAINT_EXPAND){
+ uiBlockSetCol(block, BUTYELLOW);
+
+ if (con->flag & CONSTRAINT_DISABLE)
+ uiBlockSetCol(block, REDALERT);
+
+ if (type==TARGET_BONE)
+ but = uiDefButC(block, MENU, B_CONSTRAINT_TEST, "Bone Constraint%t|Track To%x2|IK Solver%x3|Copy Rotation%x8|Copy Location%x9|Action%x12|Null%x0", *xco+20, *yco, 100, 20, &con->type, 0.0, 0.0, 0.0, 0.0, "Constraint type");
+ else
+ but = uiDefButC(block, MENU, B_CONSTRAINT_TEST, "Object Constraint%t|Track To%x2|Copy Rotation%x8|Copy Location%x9|Null%x0", *xco+20, *yco, 100, 20, &con->type, 0.0, 0.0, 0.0, 0.0, "Constraint type");
+
+ uiButSetFunc(but, constraint_changed_func, con, NULL);
+ con->otype = con->type;
+
+ but = uiDefBut(block, TEX, B_CONSTRAINT_REDRAW, "", *xco+120, *yco, 128, 20, con->name, 0.0, 32.0, 0.0, 0.0, "Constraint name");
+ uiButSetFunc(but, verify_constraint_name_func, con, NULL);
+ }
+ else{
+ uiBlockSetEmboss(block, UI_EMBOSSP);
+ uiBlockSetCol(block, BUTGREY);
+
+ if (con->flag & CONSTRAINT_DISABLE){
+ uiBlockSetCol(block, REDALERT);
+ BIF_set_color(REDALERT, COLORSHADE_MEDIUM);
+ }
+ else
+ BIF_set_color(curCol, COLORSHADE_MEDIUM);
+
+ glRects(*xco+20, *yco, *xco+248, *yco+20);
+
+ but = uiDefBut(block, LABEL, B_CONSTRAINT_TEST, typestr, *xco+20, *yco, 100, 20, NULL, 0.0, 0.0, 0.0, 0.0, "");
+ uiButSetFunc(but, move_constraint_func, con, NULL);
+ but = uiDefBut(block, LABEL, B_CONSTRAINT_TEST, con->name, *xco+120, *yco, 128, 20, NULL, 0.0, 0.0, 0.0, 0.0, "");
+ uiButSetFunc(but, move_constraint_func, con, NULL);
+ }
+
+ uiBlockSetCol(block, BUTGREY);
+
+ uiBlockSetEmboss(block, UI_EMBOSSW);
+ uiDefIconButS(block, ICONTOG|BIT|CONSTRAINT_EXPAND_BIT, B_CONSTRAINT_REDRAW, ICON_RIGHTARROW, *xco+248, *yco, 20, 20, &con->flag, 0.0, 0.0, 0.0, 0.0, "Collapse");
+
+
+ /* Draw constraint data*/
+#ifdef __CON_IPO
+ if (con->type!=CONSTRAINT_TYPE_NULL)
+ {
+ uiDefBut(block, NUMSLI|FLO, B_CONSTRAINT_REDRAW, "Influence:", *xco+280, *yco, 196, 20, &con->enforce, 0.0, 1.0, 0.0, 0.0, "Amount of influence this constraint will have on the final solution");
+ but = uiDefBut(block, BUT, B_CONSTRAINT_REDRAW, "Edit Ipo", *xco+480, *yco, 64, 20, 0, 0.0, 1.0, 0.0, 0.0, "Show this constraint's ipo in the object's Ipo window");
+ /* If this is on an object, add the constraint to the object */
+ uiButSetFunc (but, activate_constraint_ipo_func, con, NULL);
+ /* If this is on a bone, add the constraint to the action (if any) */
+ }
+#endif
+
+ if (!(con->flag & CONSTRAINT_EXPAND)){
+ (*yco)-=21;
+ return;
+ }
+
+ switch (con->type){
+ case CONSTRAINT_TYPE_ACTION:
+ {
+ bActionConstraint *data = con->data;
+ bArmature *arm;
+
+ height = 86;
+ BIF_set_color(curCol, COLORSHADE_GREY);
+ glRects(*xco, *yco-height, *xco+width, *yco);
+ uiEmboss((float)*xco, (float)*yco-height, (float)*xco+width, (float)*yco, 1);
+
+ /* Draw target parameters */
+ uiDefIDPoinBut(block, test_obpoin_but, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+((width/2)-48), *yco-20, 96, 18, &data->tar, "Target Object");
+
+ arm = get_armature(data->tar);
+ if (arm){
+ but=uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", *xco+((width/2)-48), *yco-40,96,18, &data->subtarget, 0, 24, 0, 0, "Bone");
+ }
+ else
+ strcpy (data->subtarget, "");
+
+ /* Draw action button */
+ uiDefIDPoinBut(block, test_actionpoin_but, B_CONSTRAINT_CHANGETARGET, "AC:", *xco+((width/2)-120), *yco-60, 80, 18, &data->act, "Action containing the keyed motion for this bone");
+
+ uiDefButS(block, NUM, B_CONSTRAINT_CHANGETARGET, "Start:", *xco+((width/2)-40), *yco-60, 80, 18, &data->start, 1, 18000, 0.0, 0.0, "Starting frame of the keyed motion");
+ uiDefButS(block, NUM, B_CONSTRAINT_CHANGETARGET, "End:", *xco+((width/2)+40), *yco-60, 80, 18, &data->end, 1, 18000, 0.0, 0.0, "Ending frame of the keyed motion");
+
+ /* Draw XYZ toggles */
+ uiDefButI(block, MENU, B_CONSTRAINT_REDRAW, "Key on%t|X Rot%x0|Y Rot%x1|Z Rot%x2", *xco+((width/2)-120), *yco-80, 80, 18, &data->type, 0, 24, 0, 0, "Specify which transformation channel from the target is used to key the action");
+ uiDefButF(block, NUM, B_CONSTRAINT_REDRAW, "Min:", *xco+((width/2)-40), *yco-80, 80, 18, &data->min, -180, 180, 0, 0, "Minimum value for target channel range");
+ uiDefButF(block, NUM, B_CONSTRAINT_REDRAW, "Max:", *xco+((width/2)+40), *yco-80, 80, 18, &data->max, -180, 180, 0, 0, "Maximum value for target channel range");
+
+ }
+ break;
+ case CONSTRAINT_TYPE_LOCLIKE:
+ {
+ bLocateLikeConstraint *data = con->data;
+ bArmature *arm;
+ height = 66;
+ BIF_set_color(curCol, COLORSHADE_GREY);
+ glRects(*xco, *yco-height, *xco+width, *yco);
+ uiEmboss((float)*xco, (float)*yco-height, (float)*xco+width, (float)*yco, 1);
+
+ /* Draw target parameters */
+ uiDefIDPoinBut(block, test_obpoin_but, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+((width/2)-48), *yco-20, 96, 18, &data->tar, "Target Object");
+
+ arm = get_armature(data->tar);
+ if (arm){
+ but=uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", *xco+((width/2)-48), *yco-40,96,18, &data->subtarget, 0, 24, 0, 0, "Bone");
+ }
+ else
+ strcpy (data->subtarget, "");
+
+ /* Draw XYZ toggles */
+ but=uiDefButI(block, TOG|BIT|0, B_CONSTRAINT_TEST, "X", *xco+((width/2)-48), *yco-60, 32, 18, &data->flag, 0, 24, 0, 0, "Copy X component");
+ but=uiDefButI(block, TOG|BIT|1, B_CONSTRAINT_TEST, "Y", *xco+((width/2)-16), *yco-60, 32, 18, &data->flag, 0, 24, 0, 0, "Copy Y component");
+ but=uiDefButI(block, TOG|BIT|2, B_CONSTRAINT_TEST, "Z", *xco+((width/2)+16), *yco-60, 32, 18, &data->flag, 0, 24, 0, 0, "Copy Z component");
+ }
+ break;
+ case CONSTRAINT_TYPE_ROTLIKE:
+ {
+ bRotateLikeConstraint *data = con->data;
+ bArmature *arm;
+ height = 46;
+ BIF_set_color(curCol, COLORSHADE_GREY);
+ glRects(*xco, *yco-height, *xco+width, *yco);
+ uiEmboss((float)*xco, (float)*yco-height, (float)*xco+width, (float)*yco, 1);
+
+ uiDefIDPoinBut(block, test_obpoin_but, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+((width/2)-48), *yco-20, 96, 18, &data->tar, "Target Object");
+
+ arm = get_armature(data->tar);
+ if (arm){
+ but=uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", *xco+((width/2)-48), *yco-40,96,18, &data->subtarget, 0, 24, 0, 0, "Bone");
+ }
+ else
+ strcpy (data->subtarget, "");
+
+ }
+ break;
+ case CONSTRAINT_TYPE_KINEMATIC:
+ {
+ bKinematicConstraint *data = con->data;
+ bArmature *arm;
+
+ height = 66;
+ BIF_set_color(curCol, COLORSHADE_GREY);
+ glRects(*xco, *yco-height, *xco+width, *yco);
+ uiEmboss((float)*xco, (float)*yco-height, (float)*xco+width, (float)*yco, 1);
+
+ uiDefButF(block, NUM, B_CONSTRAINT_REDRAW, "Tolerance:", *xco+((width/2)-96), *yco-20, 96, 18, &data->tolerance, 0.0001, 1.0, 0.0, 0.0, "Maximum distance to target after solving");
+ uiDefButI(block, NUM, B_CONSTRAINT_REDRAW, "Iterations:", *xco+((width/2)), *yco-20, 96, 18, &data->iterations, 1, 10000, 0.0, 0.0, "Maximum number of solving iterations");
+
+ uiDefIDPoinBut(block, test_obpoin_but, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+((width/2)-48), *yco-40, 96, 18, &data->tar, "Target Object");
+
+ arm = get_armature(data->tar);
+ if (arm){
+ but=uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", *xco+((width/2)-48), *yco-60,96,18, &data->subtarget, 0, 24, 0, 0, "Bone");
+ }
+ else
+ strcpy (data->subtarget, "");
+
+ }
+ break;
+ case CONSTRAINT_TYPE_NULL:
+ {
+ height = 20;
+ BIF_set_color(curCol, COLORSHADE_GREY);
+ glRects(*xco, *yco-height, *xco+width, *yco);
+ uiEmboss((float)*xco, (float)*yco-height, (float)*xco+width, (float)*yco, 1);
+ }
+ break;
+ case CONSTRAINT_TYPE_TRACKTO:
+ {
+ bTrackToConstraint *data = con->data;
+ bArmature *arm;
+
+ height = 46;
+ BIF_set_color(curCol, COLORSHADE_GREY);
+ glRects(*xco, *yco-height, *xco+width, *yco);
+ uiEmboss((float)*xco, (float)*yco-height, (float)*xco+width, (float)*yco, 1);
+
+ uiDefIDPoinBut(block, test_obpoin_but, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+((width/2)-48), *yco-20, 96, 18, &data->tar, "Target Object");
+
+ arm = get_armature(data->tar);
+ if (arm){
+ but=uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", *xco+((width/2)-48), *yco-40,96,18, &data->subtarget, 0, 24, 0, 0, "Bone");
+ }
+ else
+ strcpy (data->subtarget, "");
+ }
+ break;
+ default:
+ height = 0;
+ break;
+ }
+
+ (*yco)-=(24+height);
+
+}
+
+static void constraintbuts(void)
+{
+ short xco, yco, type;
+ uiBlock *block;
+ char str[32];
+ ListBase *conlist;
+ char ownerstr[64];
+ bConstraint *curcon;
+
+ xco = 320;
+ yco = 195;
+
+ sprintf(str, "buttonswin %d", curarea->win);
+
+ block= uiNewBlock(&curarea->uiblocks, str, UI_EMBOSSX, UI_HELV, curarea->win);
+
+ conlist = get_constraint_client(ownerstr, &type, NULL);
+
+ if (conlist){
+
+ uiBlockSetCol(block, BUTSALMON);
+ uiDefBut(block, BUT, B_CONSTRAINT_ADD, "Add", xco, yco, 95, 20, 0, 0.0, 0, 0, 0,"Add new constraint");
+
+ /* Go through the list of constraints and draw them */
+ xco = 465;
+ yco = 195;
+
+ for (curcon = conlist->first; curcon; curcon=curcon->next)
+ {
+ /* Draw default constraint header */
+ draw_constraint(block, conlist, curcon, &xco, &yco, type);
+ }
+
+ }
+
+ uiDrawBlock(block);
+
+}
+
+static void do_constraintbuts(unsigned short event)
+{
+ ListBase *list;
+ short type;
+
+ switch(event) {
+ case B_CONSTRAINT_CHANGENAME:
+ break;
+ case B_CONSTRAINT_TEST:
+ test_scene_constraints();
+ allqueue (REDRAWVIEW3D, 0);
+ allqueue (REDRAWBUTSCONSTRAINT, 0);
+ break;
+ case B_CONSTRAINT_REDRAW:
+ test_scene_constraints();
+ allqueue (REDRAWVIEW3D, 0);
+ allqueue (REDRAWBUTSCONSTRAINT, 0);
+ break;
+ case B_CONSTRAINT_CHANGETARGET:
+ test_scene_constraints();
+ allqueue (REDRAWVIEW3D, 0);
+ allqueue (REDRAWBUTSCONSTRAINT, 0);
+ break;
+ case B_CONSTRAINT_CHANGETYPE:
+ test_scene_constraints();
+ allqueue (REDRAWVIEW3D, 0);
+ allqueue (REDRAWBUTSCONSTRAINT, 0);
+ break;
+ case B_CONSTRAINT_ADD:
+ {
+ bConstraint *con;
+ // ListBase *chanbase;
+ // bConstraintChannel *chan;
+
+ Object *ob = OBACT;
+ list = get_constraint_client(NULL, &type, NULL);
+ // chanbase= get_constraint_client_channels(0);
+ if (list){
+ con = add_new_constraint();
+ unique_constraint_name(con, list);
+ // chan = add_new_constraint_channel(con->name);
+ // ob->activecon = chan;
+ // BLI_addtail(chanbase, chan);
+ BLI_addtail(list, con);
+ }
+ test_scene_constraints();
+ allqueue (REDRAWVIEW3D, 0);
+ allqueue (REDRAWBUTSCONSTRAINT, 0);
+ }
+ break;
+ case B_CONSTRAINT_DEL:
+ test_scene_constraints();
+ allqueue (REDRAWVIEW3D, 0);
+ allqueue (REDRAWBUTSCONSTRAINT, 0);
+ break;
+ default:
+ break;
+ }
+}
+
+/* ********************* GAME ***************************** */
+
+/* in editsca.c */
+
+/* ***************************<>******************************** */
+
+void drawbutspace(void)
+{
+ SpaceButs *sbuts= curarea->spacedata.first;
+ View2D *v2d= &sbuts->v2d;
+ ID *id;
+ Object *ob;
+ float vec[2];
+
+ if(curarea->headertype==0) {
+ ID *id, *idfrom;
+
+ buttons_active_id(&id, &idfrom);
+ G.buts->lockpoin= id;
+ }
+
+ ob= OBACT;
+
+ myortho2(v2d->cur.xmin, v2d->cur.xmax, v2d->cur.ymin, v2d->cur.ymax);
+
+ glShadeModel(GL_SMOOTH);
+ glBegin(GL_QUADS);
+ cpack(0x909090);
+ vec[0]= v2d->cur.xmin;
+ vec[1]= v2d->cur.ymax-15;
+ glVertex2fv(vec);
+ vec[0]= v2d->cur.xmax;
+ glVertex2fv(vec);
+ cpack(0x646464);
+ vec[1]= v2d->cur.ymax;
+ glVertex2fv(vec);
+ vec[0]= v2d->cur.xmin;
+ glVertex2fv(vec);
+ glEnd();
+ glShadeModel(GL_FLAT);
+
+ cpack(0x909090);
+ glRectf(v2d->cur.xmin, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax-15);
+
+ uiSetButLock(G.scene->id.lib!=0, "Can't edit library data");
+ uiFreeBlocksWin(&curarea->uiblocks, curarea->win);
+
+ switch(G.buts->mainb) {
+ case BUTS_VIEW:
+ viewbuts();
+ break;
+ case BUTS_LAMP:
+ lampbuts();
+ break;
+ case BUTS_MAT:
+ if(ob==0) return;
+ if(ob->type>=OB_LAMP) return;
+
+ matbuts();
+ break;
+ case BUTS_TEX:
+ texbuts();
+ break;
+ case BUTS_ANIM:
+ animbuts();
+ break;
+ case BUTS_WORLD:
+ worldbuts();
+ break;
+ case BUTS_RENDER:
+ renderbuts();
+ break;
+ case BUTS_GAME:
+ gamebuts();
+ break;
+ case BUTS_FPAINT:
+ fpaintbuts();
+ break;
+ case BUTS_RADIO:
+ radiobuts();
+ break;
+ case BUTS_SOUND:
+ soundbuts();
+ break;
+ case BUTS_CONSTRAINT:
+ constraintbuts();
+ break;
+ case BUTS_SCRIPT:
+ scriptbuts();
+ break;
+ case BUTS_EDIT:
+ if(ob==0) return;
+
+ common_editbuts();
+
+ id= ob->data;
+ if(id && id->lib) uiSetButLock(1, "Can't edit library data");
+
+ if(ob->type==OB_MESH) meshbuts();
+ else if ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT) {
+ curvebuts();
+ if(ob->type==OB_FONT) fontbuts();
+ }
+ else if(ob->type==OB_CAMERA) camerabuts();
+ else if(ob->type==OB_MBALL) mballbuts();
+ else if(ob->type==OB_LATTICE) latticebuts();
+ else if(ob->type==OB_IKA) ikabuts();
+#ifdef __NLA
+ else if(ob->type==OB_ARMATURE) armaturebuts();
+#endif
+
+ break;
+ }
+
+ uiClearButLock();
+
+ test_butspace();
+
+ curarea->win_swap= WIN_BACK_OK;
+}
+
+void do_blenderbuttons(unsigned short event)
+{
+ SpaceButs *buts;
+
+ /* teken ook de soortgelijke windows? */
+ buts= curarea->spacedata.first;
+ if(buts->mainb==BUTS_VIEW) allqueue(REDRAWBUTSVIEW, curarea->win);
+ else if(buts->mainb==BUTS_LAMP) allqueue(REDRAWBUTSLAMP, curarea->win);
+ else if(buts->mainb==BUTS_MAT || buts->mainb==BUTS_TEX) {
+ allqueue(REDRAWBUTSMAT, curarea->win);
+ allqueue(REDRAWBUTSTEX, curarea->win);
+ }
+ else if(buts->mainb==BUTS_WORLD) allqueue(REDRAWBUTSWORLD, curarea->win);
+ else if(buts->mainb==BUTS_ANIM) allqueue(REDRAWBUTSANIM, curarea->win);
+ else if(buts->mainb==BUTS_RENDER) allqueue(REDRAWBUTSRENDER, curarea->win);
+ else if(buts->mainb==BUTS_EDIT) allqueue(REDRAWBUTSEDIT, curarea->win);
+ else if(buts->mainb==BUTS_FPAINT) allqueue(REDRAWBUTSGAME, curarea->win);
+ else if(buts->mainb==BUTS_RADIO) allqueue(REDRAWBUTSRADIO, curarea->win);
+ else if(buts->mainb==BUTS_SCRIPT) allqueue(REDRAWBUTSSCRIPT, curarea->win);
+ else if(buts->mainb==BUTS_SOUND) allqueue(REDRAWBUTSSOUND, curarea->win);
+ else if(buts->mainb==BUTS_CONSTRAINT) allqueue(REDRAWBUTSCONSTRAINT, curarea->win);
+
+ if(event<=100) {
+ do_global_buttons(event);
+ }
+ else if(event<=B_VIEWBUTS) {
+ do_viewbuts(event);
+ }
+ else if(event<=B_LAMPBUTS) {
+ do_lampbuts(event);
+ }
+ else if(event<=B_MATBUTS) {
+ do_matbuts(event);
+ }
+ else if(event<=B_TEXBUTS) {
+ do_texbuts(event);
+ }
+ else if(event<=B_ANIMBUTS) {
+ do_animbuts(event);
+ }
+ else if(event<=B_WORLDBUTS) {
+ do_worldbuts(event);
+ }
+ else if(event<=B_RENDERBUTS) {
+ do_renderbuts(event);
+ }
+ else if(event<=B_COMMONEDITBUTS) {
+ do_common_editbuts(event);
+ }
+ else if(event<=B_MESHBUTS) {
+ do_meshbuts(event);
+ }
+ else if(event<=B_CURVEBUTS) {
+ do_curvebuts(event);
+ }
+ else if(event<=B_FONTBUTS) {
+ do_fontbuts(event);
+ }
+ else if(event<=B_IKABUTS) {
+ do_ikabuts(event);
+ }
+ else if(event<=B_CAMBUTS) {
+ ;
+ }
+ else if(event<=B_MBALLBUTS) {
+ do_mballbuts(event);
+ }
+ else if(event<=B_LATTBUTS) {
+ do_latticebuts(event);
+ }
+ else if(event<=B_GAMEBUTS) {
+ do_gamebuts(event);
+ }
+ else if(event<=B_FPAINTBUTS) {
+ do_fpaintbuts(event);
+ }
+ else if(event<=B_RADIOBUTS) {
+ do_radiobuts(event);
+ }
+ else if(event<=B_SCRIPTBUTS) {
+ do_scriptbuts(event);
+ }
+ else if(event<=B_SOUNDBUTS) {
+ do_soundbuts(event);
+ }
+ else if(event<=B_CONSTRAINTBUTS) {
+ do_constraintbuts(event);
+ }
+ else if(event>=REDRAWVIEW3D) allqueue(event, 0);
+}
+
+
+void redraw_test_buttons(Base *new)
+{
+ ScrArea *sa;
+ SpaceButs *buts;
+
+ sa= G.curscreen->areabase.first;
+ while(sa) {
+ if(sa->spacetype==SPACE_BUTS) {
+ buts= sa->spacedata.first;
+
+ if(buts->mainb==BUTS_LAMP) {
+ allqueue(REDRAWBUTSLAMP, 0);
+ BIF_preview_changed(buts);
+ }
+ else if(buts->mainb==BUTS_MAT) {
+ allqueue(REDRAWBUTSMAT, 0);
+ BIF_preview_changed(buts);
+ }
+ else if(buts->mainb==BUTS_TEX) {
+ allqueue(REDRAWBUTSTEX, 0);
+ if(new && new->object->type==OB_LAMP) buts->texfrom= 2;
+ else buts->texfrom= 0;
+ BIF_preview_changed(buts);
+ }
+ else if(buts->mainb==BUTS_ANIM) {
+ allqueue(REDRAWBUTSANIM, 0);
+ }
+ else if(buts->mainb==BUTS_EDIT) {
+ allqueue(REDRAWBUTSEDIT, 0);
+ }
+ else if(buts->mainb==BUTS_GAME) {
+ allqueue(REDRAWBUTSGAME, 0);
+ }
+ else if(buts->mainb==BUTS_FPAINT) {
+ allqueue(REDRAWBUTSGAME, 0);
+ }
+ else if(buts->mainb==BUTS_SCRIPT) {
+ allqueue(REDRAWBUTSSCRIPT, 0);
+ }
+ else if(buts->mainb==BUTS_SOUND) {
+ allqueue(REDRAWBUTSSOUND, 0);
+ }
+ else if(buts->mainb==BUTS_CONSTRAINT) {
+ allqueue(REDRAWBUTSCONSTRAINT, 0);
+ }
+ }
+ sa= sa->next;
+ }
+}
+
+void clever_numbuts_buts()
+{
+ Material *ma;
+ Lamp *la;
+ World *wo;
+ static char hexrgb[8]; /* Uh... */
+ static char hexspec[8]; /* Uh... */
+ static char hexmir[8]; /* Uh... */
+ static char hexho[8];
+ static char hexze[8];
+ int rgb[3];
+
+ switch (G.buts->mainb){
+ case BUTS_FPAINT:
+
+ sprintf(hexrgb, "%02X%02X%02X", (int)(Gvp.r*255), (int)(Gvp.g*255), (int)(Gvp.b*255));
+
+ add_numbut(0, TEX, "RGB:", 0, 6, hexrgb, "HTML Hex value for the RGB color");
+ do_clever_numbuts("Vertex Paint RGB Hex Value", 1, REDRAW);
+
+ /* Assign the new hex value */
+ sscanf(hexrgb, "%02X%02X%02X", &rgb[0], &rgb[1], &rgb[2]);
+ Gvp.r= (rgb[0]/255.0 >= 0.0 && rgb[0]/255.0 <= 1.0 ? rgb[0]/255.0 : 0.0) ;
+ Gvp.g = (rgb[1]/255.0 >= 0.0 && rgb[1]/255.0 <= 1.0 ? rgb[1]/255.0 : 0.0) ;
+ Gvp.b = (rgb[2]/255.0 >= 0.0 && rgb[2]/255.0 <= 1.0 ? rgb[2]/255.0 : 0.0) ;
+
+ break;
+ case BUTS_LAMP:
+ la= G.buts->lockpoin;
+ if (la){
+ sprintf(hexrgb, "%02X%02X%02X", (int)(la->r*255), (int)(la->g*255), (int)(la->b*255));
+ add_numbut(0, TEX, "RGB:", 0, 6, hexrgb, "HTML Hex value for the lamp color");
+ do_clever_numbuts("Lamp RGB Hex Values", 1, REDRAW);
+ sscanf(hexrgb, "%02X%02X%02X", &rgb[0], &rgb[1], &rgb[2]);
+ la->r = (rgb[0]/255.0 >= 0.0 && rgb[0]/255.0 <= 1.0 ? rgb[0]/255.0 : 0.0) ;
+ la->g = (rgb[1]/255.0 >= 0.0 && rgb[1]/255.0 <= 1.0 ? rgb[1]/255.0 : 0.0) ;
+ la->b = (rgb[2]/255.0 >= 0.0 && rgb[2]/255.0 <= 1.0 ? rgb[2]/255.0 : 0.0) ;
+ BIF_preview_changed(G.buts);
+ }
+ break;
+ case BUTS_WORLD:
+ wo= G.buts->lockpoin;
+ if (wo){
+ sprintf(hexho, "%02X%02X%02X", (int)(wo->horr*255), (int)(wo->horg*255), (int)(wo->horb*255));
+ sprintf(hexze, "%02X%02X%02X", (int)(wo->zenr*255), (int)(wo->zeng*255), (int)(wo->zenb*255));
+ add_numbut(0, TEX, "Zen:", 0, 6, hexze, "HTML Hex value for the Zenith color");
+ add_numbut(1, TEX, "Hor:", 0, 6, hexho, "HTML Hex value for the Horizon color");
+ do_clever_numbuts("World RGB Hex Values", 2, REDRAW);
+
+ sscanf(hexho, "%02X%02X%02X", &rgb[0], &rgb[1], &rgb[2]);
+ wo->horr = (rgb[0]/255.0 >= 0.0 && rgb[0]/255.0 <= 1.0 ? rgb[0]/255.0 : 0.0) ;
+ wo->horg = (rgb[1]/255.0 >= 0.0 && rgb[1]/255.0 <= 1.0 ? rgb[1]/255.0 : 0.0) ;
+ wo->horb = (rgb[2]/255.0 >= 0.0 && rgb[2]/255.0 <= 1.0 ? rgb[2]/255.0 : 0.0) ;
+ sscanf(hexze, "%02X%02X%02X", &rgb[0], &rgb[1], &rgb[2]);
+ wo->zenr = (rgb[0]/255.0 >= 0.0 && rgb[0]/255.0 <= 1.0 ? rgb[0]/255.0 : 0.0) ;
+ wo->zeng = (rgb[1]/255.0 >= 0.0 && rgb[1]/255.0 <= 1.0 ? rgb[1]/255.0 : 0.0) ;
+ wo->zenb = (rgb[2]/255.0 >= 0.0 && rgb[2]/255.0 <= 1.0 ? rgb[2]/255.0 : 0.0) ;
+ BIF_preview_changed(G.buts);
+
+ }
+ break;
+ case BUTS_MAT:
+
+ ma= G.buts->lockpoin;
+
+ /* Build a hex value */
+ if (ma){
+ sprintf(hexrgb, "%02X%02X%02X", (int)(ma->r*255), (int)(ma->g*255), (int)(ma->b*255));
+ sprintf(hexspec, "%02X%02X%02X", (int)(ma->specr*255), (int)(ma->specg*255), (int)(ma->specb*255));
+ sprintf(hexmir, "%02X%02X%02X", (int)(ma->mirr*255), (int)(ma->mirg*255), (int)(ma->mirb*255));
+
+ add_numbut(0, TEX, "Col:", 0, 6, hexrgb, "HTML Hex value for the RGB color");
+ add_numbut(1, TEX, "Spec:", 0, 6, hexspec, "HTML Hex value for the Spec color");
+ add_numbut(2, TEX, "Mir:", 0, 6, hexmir, "HTML Hex value for the Mir color");
+ do_clever_numbuts("Material RGB Hex Values", 3, REDRAW);
+
+ /* Assign the new hex value */
+ sscanf(hexrgb, "%02X%02X%02X", &rgb[0], &rgb[1], &rgb[2]);
+ ma->r = (rgb[0]/255.0 >= 0.0 && rgb[0]/255.0 <= 1.0 ? rgb[0]/255.0 : 0.0) ;
+ ma->g = (rgb[1]/255.0 >= 0.0 && rgb[1]/255.0 <= 1.0 ? rgb[1]/255.0 : 0.0) ;
+ ma->b = (rgb[2]/255.0 >= 0.0 && rgb[2]/255.0 <= 1.0 ? rgb[2]/255.0 : 0.0) ;
+ sscanf(hexspec, "%02X%02X%02X", &rgb[0], &rgb[1], &rgb[2]);
+ ma->specr = (rgb[0]/255.0 >= 0.0 && rgb[0]/255.0 <= 1.0 ? rgb[0]/255.0 : 0.0) ;
+ ma->specg = (rgb[1]/255.0 >= 0.0 && rgb[1]/255.0 <= 1.0 ? rgb[1]/255.0 : 0.0) ;
+ ma->specb = (rgb[2]/255.0 >= 0.0 && rgb[2]/255.0 <= 1.0 ? rgb[2]/255.0 : 0.0) ;
+ sscanf(hexmir, "%02X%02X%02X", &rgb[0], &rgb[1], &rgb[2]);
+ ma->mirr = (rgb[0]/255.0 >= 0.0 && rgb[0]/255.0 <= 1.0 ? rgb[0]/255.0 : 0.0) ;
+ ma->mirg = (rgb[1]/255.0 >= 0.0 && rgb[1]/255.0 <= 1.0 ? rgb[1]/255.0 : 0.0) ;
+ ma->mirb = (rgb[2]/255.0 >= 0.0 && rgb[2]/255.0 <= 1.0 ? rgb[2]/255.0 : 0.0) ;
+
+ BIF_preview_changed(G.buts);
+ }
+ break;
+ }
+}
diff --git a/source/blender/src/cmap.tga.c b/source/blender/src/cmap.tga.c
new file mode 100644
index 00000000000..8c76d8be460
--- /dev/null
+++ b/source/blender/src/cmap.tga.c
@@ -0,0 +1,88 @@
+/* DataToC output of file <cmap_tga> */
+/*
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 datatoc_cmap_tga_size= 13400;
+char datatoc_cmap_tga[]= {"\x00\x01\x01\x00\x00\x00\x01\x18\x00\x00\x00\x00\x9a\x00\x50\x00\x08\x08\xf3\xf3\xf3\xdb\xdb\xdb\xc4\xc4\xc4\xad\xad\xad\x96\x96\x96\x7f\x7f\x7f\x67\x67\x67\x50\x50\x50\x39\x39\x39\x22\x22\x22\x0b\x0b\x0b\xf4\xf4\xf4\xe6\xc8\xec\xe6\xa4\xec\xe6\x7f\xec\xe6\x5b\xec\xe6\x36\xec\xe6\x12\xec\xb3\xec\xec\xb3\xc8\xec\xb3\xa4\xec\xb3\x7f\xec\xb3\x5b\xec" \
+"\xb3\x36\xec\xb3\x12\xec\x80\xec\xec\x80\xc8\xec\x80\xa4\xec\x80\x7f\xec\x80\x5b\xec\x80\x36\xec\x80\x12\xec\x4d\xec\xec\x4d\xc8\xec\x4d\xa4\xec\x4d\x7f\xec\x4d\x5b\xec\x4d\x36\xec\x4d\x12\xec\x1a\xec\xec\x1a\xc8\xec\x1a\xa4\xec\x1a\x7f\xec\x1a\x5b\xec\x1a\x36\xec\x1a\x12\xec\xe6\xec\xc8\xe6\xc8\xc8\xe6\xa4\xc8\xe6\x7f\xc8\xe6\x5b\xc8\xe6\x36\xc8\xe6\x12\xc8\xb3\xec\xc8\xb3\xc8\xc8\xb3\xa4\xc8\xb3\x7f\xc8\xb3\x5b\xc8\xb3\x36\xc8\xb3\x12\xc8\x80\xec\xc8\x80\xc8\xc8\x80\xa4\xc8\x80\x7f\xc8\x80\x5b\xc8\x80\x36\xc8\x80\x12\xc8\x4d\xec\xc8\x4d\xc8\xc8\x4d\xa4\xc8\x4d\x7f\xc8\x4d\x5b\xc8\x4d\x36\xc8\x4d\x12\xc8\x1a\xec\xc8\x1a\xc8\xc8\x1a\xa4\xc8\x1a\x7f\xc8\x1a\x5b\xc8\x1a\x36\xc8\x1a\x12\xc8\xe6\xec\xa4\xe6\xc8\xa4\xe6\xa4\xa4\xe6\x7f\xa4\xe6\x5b\xa4\xe6\x36\xa4\xe6\x12\xa4\xb3\xec\xa4\xb3\xc8\xa4\xb3\xa4\xa4\xb3\x7f\xa4\xb3\x5b\xa4\xb3\x36\xa4\xb3\x12\xa4\x80\xec\xa4\x80\xc8\xa4\x80\xa4\xa4\x80\x7f\xa4\x80\x5b\xa4\x80\x36\xa4\x80\x12\xa4\x4d\xec\xa4\x4d\xc8\xa4\x4d\xa4\xa4\x4d\x7f\xa4\x4d\x5b\xa4\x4d\x36\xa4\x4d" \
+"\x12\xa4\x1a\xec\xa4\x1a\xc8\xa4\x1a\xa4\xa4\x1a\x7f\xa4\x1a\x5b\xa4\x1a\x36\xa4\x1a\x12\xa4\xe6\xec\x7f\xe6\xc8\x7f\xe6\xa4\x7f\xe6\x7f\x7f\xe6\x5b\x7f\xe6\x36\x7f\xe6\x12\x7f\xb3\xec\x7f\xb3\xc8\x7f\xb3\xa4\x7f\xb3\x7f\x7f\xb3\x5b\x7f\xb3\x36\x7f\xb3\x12\x7f\x80\xec\x7f\x80\xc8\x7f\x80\xa4\x7f\x80\x7f\x7f\x80\x5b\x7f\x80\x36\x7f\x80\x12\x7f\x4d\xec\x7f\x4d\xc8\x7f\x4d\xa4\x7f\x4d\x7f\x7f\x4d\x5b\x7f\x4d\x36\x7f\x4d\x12\x7f\x1a\xec\x7f\x1a\xc8\x7f\x1a\xa4\x7f\x1a\x7f\x7f\x1a\x5b\x7f\x1a\x36\x7f\x1a\x12\x7f\xe6\xec\x5b\xe6\xc8\x5b\xe6\xa4\x5b\xe6\x7f\x5b\xe6\x5b\x5b\xe6\x36\x5b\xe6\x12\x5b\xb3\xec\x5b\xb3\xc8\x5b\xb3\xa4\x5b\xb3\x7f\x5b\xb3\x5b\x5b\xb3\x36\x5b\xb3\x12\x5b\x80\xec\x5b\x80\xc8\x5b\x80\xa4\x5b\x80\x7f\x5b\x80\x5b\x5b\x80\x36\x5b\x80\x12\x5b\x4d\xec\x5b\x4d\xc8\x5b\x4d\xa4\x5b\x4d\x7f\x5b\x4d\x5b\x5b\x4d\x36\x5b\x4d\x12\x5b\x1a\xec\x5b\x1a\xc8\x5b\x1a\xa4\x5b\x1a\x7f\x5b\x1a\x5b\x5b\x1a\x36\x5b\x1a\x12\x5b\xe6\xec\x36\xe6\xc8\x36\xe6\xa4\x36\xe6\x7f\x36\xe6\x5b\x36\xe6\x36\x36\xe6\x12\x36\xb3\xec" \
+"\x36\xb3\xc8\x36\xb3\xa4\x36\xb3\x7f\x36\xb3\x5b\x36\xb3\x36\x36\xb3\x12\x36\x80\xec\x36\x80\xc8\x36\x80\xa4\x36\x80\x7f\x36\x80\x5b\x36\x80\x36\x36\x80\x12\x36\x4d\xec\x36\x4d\xc8\x36\x4d\xa4\x36\x4d\x7f\x36\x4d\x5b\x36\x4d\x36\x36\x4d\x12\x36\x1a\xec\x36\x1a\xc8\x36\x1a\xa4\x36\x1a\x7f\x36\x1a\x5b\x36\x1a\x36\x36\x1a\x12\x36\xe6\xec\x12\xe6\xc8\x12\xe6\xa4\x12\xe6\x7f\x12\xe6\x5b\x12\xe6\x36\x12\xe6\x12\x12\xb3\xec\x12\xb3\xc8\x12\xb3\xa4\x12\xb3\x7f\x12\xb3\x5b\x12\xb3\x36\x12\xb3\x12\x12\x80\xec\x12\x80\xc8\x12\x80\xa4\x12\x80\x7f\x12\x80\x5b\x12\x80\x36\x12\x80\x12\x12\x4d\xec\x12\x4d\xc8\x12\x4d\xa4\x12\x4d\x7f\x12\x4d\x5b\x12\x4d\x36\x12\x4d\x12\x12\x1a\xec\x12\x1a\xc8\x12\x1a\xa4\x12\x1a\x7f\x12\x1a\x5b\x12\x1a\x36\x12\x1a\x12\x12\x03\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02" \
+"\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x04\x07\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x07\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x02\x04\x07\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x02\x07\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a" \
+"\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x02\x04\x07\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x02\x07\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a" \
+"\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x02\x04\x07\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x02\x07\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x02\x04\x07\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x02\x07\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a" \
+"\x0a\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x02\x04\x07\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x02\x07\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\xff\xff\xff\xff\xff\x09\x09\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x09\x09\x09\xff\xff\xff\xff\xff\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x02\x04\x07\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x02\x07\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\xdc\xdc\xdc\xdc\xdc" \
+"\xdc\xdc\xdc\xdc\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\x09\x09\x09\x09\x09\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x09\x09\x09\x09\x09\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x02\x04\x07\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x02\x07\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\x09\x09\x09\x09\xdb\xdb\xdb\xdb\xdb\xdb\x09\x09\x09\x09\x09\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\x09\x09\x09\x09\x09\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x09\x09\x09\x09\xdc\xdc\xdc\xdc" \
+"\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x02\x04\x07\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x02\x07\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\x09\x09\x09\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x09\x09\x09\x09\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\x02\x04\x07\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x02\x07\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe" \
+"\xfe\xfe\xfe\xfe\xf7\xf7\xf7\xf7\xf7\xf7\xf7\xf7\xf7\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\x02\x04\x07\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x02\x07\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xf7\xf7\xf7\xf7\xf7\xf7\xf7\xf7\xf7\xf7\xf7\xf7\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\x02\x04\x07\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x02\x07\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9" \
+"\xb9\xb8\xb8\xb8\xb8\xb8\xb8\xb8\xb8\xb8\xb7\xb7\xda\xda\xda\xda\xda\xda\xda\xda\xda\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xf6\xf6\xf6\xf6\xf6\xf7\xf7\xf7\xf7\xf7\xf7\xf7\xf7\xf7\xf7\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xb2\xb2\xb2\xb2\xb2\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\x02\x04\x07\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x02\x07\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb8\xb8\xb8\xb8\xb8\xb8\xb8\xb8\xb8\xb7\xb7\xb7\xb7\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xf6\xf6\xf6\xf6\xf6\xf6\xf6\xf6\xf7\xf7\xf7\xf7\xf7\xf7\xf7\xf7\xf7\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xb2" \
+"\xb2\xb2\xb2\xb2\xb2\xb2\xb2\xb2\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\x02\x04\x07\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x02\x07\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb8\xb8\xb8\xb8\xb8\xb8\xb8\xb8\xb8\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xda\xda\xda\xda\xda\xda\xda\xda\xda\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xf6\xf6\xf6\xf6\xf6\xf6\xf6\xf6\xf6\xf6\xf7\xf7\xf7\xf7\xf7\xf7\xf7\xf7\xf7\xf7\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xb2\xb2\xb2\xb2\xb2\xb2\xb2\xb2\xb2\xb2\xb2\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\x02\x04\x07\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x02\x07\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb8\xb8\xb8\xb8\xb8\xb8\xb8\xb8\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xda\xda\xda\xda\xda\xda\xda\xda\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xf6" \
+"\xf6\xf6\xf6\xf6\xf6\xf6\xf6\xf6\xf6\xf6\xf6\xf6\xf7\xf7\xf7\xf7\xf7\xf7\xf7\xf7\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xb2\xb2\xb2\xb2\xb2\xb2\xb2\xb2\xb2\xb2\xb2\xb2\xb2\xb2\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\x02\x04\x07\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\x02\x07\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb8\xb8\xb8\xb8\xb8\xb8\xb8\xb8\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xda\xda\xda\xda\xda\xda\xda\xda\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xf6\xf6\xf6\xf6\xf6\xf6\xf6\xf6\xf6\xf6\xf6\xf6\xf6\xf6\xf6\xf7\xf7\xf7\xf7\xf7\xf7\xf7\xf7\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xb2\xb2\xb2\xb2\xb2\xb2\xb2\xb2\xb2\xb2\xb2\xb2\xb2\xb2\xb2\xb2\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\x02\x04\x07\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\x02\x07\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb8" \
+"\xb8\xb8\xb8\xb8\xb8\xb8\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xda\xda\xda\xda\xda\xda\xda\xda\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xf6\xf6\xf6\xf6\xf6\xf6\xf6\xf6\xf6\xf6\xef\xef\xef\xef\xef\xef\xef\xf0\xf0\xf0\xf0\xf0\xf0\xf0\xf0\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xce\xce\xce\xce\xce\xce\xce\xab\xab\xab\xab\xab\xab\xab\xab\xb2\xb2\xb2\xb2\xb2\xb2\xb2\xb2\xb2\xb2\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\x02\x04\x07\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\x02\x07\x96\x96\x96\x96\x96\x96\x96\x96\x95\x95\x95\x95\x95\x95\x95\x94\x94\x94\x94\x94\x94\x94\x94\xb6\xb6\xb6\xb6\xb6\xb6\xb6\xb6\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xee\xef\xef\xef\xef\xef\xef\xef\xef\xf0\xf0\xf0\xf0\xf0\xf0\xf0\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xce\xce\xce\xce\xce\xce\xce\xab\xab\xab\xab\xab" \
+"\xab\xab\xab\x88\x88\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x96\x96\x96\x96\x96\x96\x96\x96\x96\x96\x96\x02\x04\x07\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x02\x07\x96\x96\x96\x96\x96\x96\x96\x96\x95\x95\x95\x95\x95\x95\x94\x94\x94\x94\x94\x94\x94\x94\x93\x93\xb6\xb6\xb6\xb6\xb6\xb6\xb6\xb6\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xee\xee\xee\xef\xef\xef\xef\xef\xef\xef\xef\xf0\xf0\xf0\xf0\xf0\xf0\xf0\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xce\xce\xce\xce\xce\xce\xab\xab\xab\xab\xab\xab\xab\xab\x88\x88\x88\x88\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x96\x96\x96\x96\x96\x96\x96\x96\x96\x96\x02\x04\x07\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x02\x07\x96\x96\x96\x96\x96\x96\x96\x95\x95\x95\x95\x95\x95\x95\x94\x94\x94\x94\x94\x94\x94\x93\x93\x93\x93\x93\xb6\xb6\xb6\xb6\xb6\xb6\xb6\xd9\xd9\xd9\xd9\xd9\xd9\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xf5\xf5\xf5" \
+"\xf5\xf5\xf5\xf5\xf5\xf5\xee\xee\xee\xee\xee\xef\xef\xef\xef\xef\xef\xef\xef\xf0\xf0\xf0\xf0\xf0\xf0\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xce\xce\xce\xce\xce\xce\xce\xab\xab\xab\xab\xab\xab\xab\x88\x88\x88\x88\x88\x88\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x96\x96\x96\x96\x96\x96\x96\x96\x96\x96\x02\x04\x07\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x02\x07\x96\x96\x96\x96\x96\x96\x96\x95\x95\x95\x95\x95\x95\x94\x94\x94\x94\x94\x94\x94\x93\x93\x93\x93\x93\x93\xb6\xb6\xb6\xb6\xb6\xb6\xb6\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xee\xee\xee\xee\xee\xee\xee\xef\xef\xef\xef\xef\xef\xef\xef\xf0\xf0\xf0\xf0\xf0\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xce\xce\xce\xce\xce\xce\xab\xab\xab\xab\xab\xab\xab\x88\x88\x88\x88\x88\x88\x88\x88\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x96\x96\x96\x96\x96\x96\x96\x96\x96\x02\x04\x07\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x02\x07\x96\x96\x96\x96\x96\x96\x95\x95" \
+"\x95\x95\x95\x95\x94\x94\x94\x94\x94\x94\x94\x93\x93\x93\x93\x93\x93\x93\x93\xb6\xb6\xb6\xb6\xb6\xb6\xb6\xd9\xd9\xd9\xd9\xd9\xd9\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xee\xee\xee\xee\xee\xee\xee\xee\xee\xef\xef\xef\xef\xef\xef\xef\xf0\xf0\xf0\xf0\xf0\xf0\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xce\xce\xce\xce\xce\xce\xab\xab\xab\xab\xab\xab\xab\x88\x88\x88\x88\x88\x88\x88\x88\x88\x88\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x96\x96\x96\x96\x96\x96\x96\x96\x96\x02\x04\x07\x08\x08\x08\x08\x08\x08\x08\x08\x08\x07\x07\x02\x07\x73\x73\x73\x73\x73\x73\x72\x72\x72\x72\x72\x71\x71\x71\x71\x71\x71\x71\x70\x70\x70\x70\x70\x92\x92\x92\x92\x92\xb5\xb5\xb5\xb5\xb5\xb5\xb5\xd8\xd8\xd8\xd8\xd8\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xf4\xf4\xf4\xf4\xf4\xf4\xf4\xf4\xed\xed\xed\xed\xed\xed\xed\xee\xee\xee\xee\xef\xef\xef\xef\xef\xef\xef\xf0\xf0\xf0\xf0\xf0\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xce\xce\xce\xce\xce\xce\xab\xab\xab\xab\xab\xab" \
+"\x88\x88\x88\x88\x88\x65\x65\x65\x65\x65\x65\x65\x6c\x6c\x6c\x6c\x6c\x6c\x6c\x6c\x73\x73\x73\x73\x73\x73\x73\x73\x02\x04\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x02\x07\x73\x73\x73\x73\x73\x73\x72\x72\x72\x72\x72\x71\x71\x71\x71\x71\x71\x71\x70\x70\x70\x70\x6f\x6f\x92\x92\x92\x92\x92\xb5\xb5\xb5\xb5\xb5\xb5\xb5\xd8\xd8\xd8\xd8\xd8\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xf4\xf4\xf4\xf4\xf4\xf4\xf4\xf4\xed\xed\xed\xed\xed\xed\xed\xee\xee\xee\xee\xee\xef\xef\xef\xef\xef\xef\xf0\xf0\xf0\xf0\xf0\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xce\xce\xce\xce\xce\xab\xab\xab\xab\xab\xab\xab\x88\x88\x88\x88\x65\x65\x65\x65\x65\x65\x65\x65\x6c\x6c\x6c\x6c\x6c\x6c\x6c\x6c\x73\x73\x73\x73\x73\x73\x73\x73\x02\x04\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x02\x07\x73\x73\x73\x73\x73\x73\x72\x72\x72\x72\x72\x71\x71\x71\x71\x71\x71\x70\x70\x70\x70\x6f\x6f\x6f\x6f\x92\x92\x92\x92\x92\xb5\xb5\xb5\xb5\xb5\xb5\xd8\xd8\xd8\xd8\xd8\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xf4\xf4\xf4\xf4" \
+"\xf4\xf4\xf4\xf4\xed\xed\xed\xed\xed\xed\xed\xed\xed\xee\xee\xee\xee\xef\xef\xef\xef\xef\xef\xef\xf0\xf0\xf0\xf0\xf0\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xce\xce\xce\xce\xab\xab\xab\xab\xab\xab\xab\x88\x88\x88\x88\x65\x65\x65\x65\x65\x65\x65\x65\x65\x65\x6c\x6c\x6c\x6c\x6c\x6c\x6c\x6c\x73\x73\x73\x73\x73\x73\x73\x02\x04\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x02\x07\x73\x73\x73\x73\x73\x72\x72\x72\x72\x72\x71\x71\x71\x71\x71\x71\x70\x70\x70\x70\x70\x6f\x6f\x6f\x6f\x6f\x92\x92\x92\x92\xb5\xb5\xb5\xb5\xb5\xb5\xd8\xd8\xd8\xd8\xd8\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xf4\xf4\xf4\xf4\xf4\xf4\xf4\xed\xed\xed\xed\xed\xed\xed\xed\xe6\xe6\xe6\xe7\xe7\xe7\xe7\xe8\xe8\xe8\xe8\xe8\xe8\xe9\xe9\xe9\xe9\xe9\xea\xea\xea\xea\xea\xea\xea\xea\xea\xea\xc7\xc7\xc7\xc7\xc7\xa4\xa4\xa4\xa4\xa4\xa4\x81\x81\x81\x81\x5e\x5e\x5e\x5e\x65\x65\x65\x65\x65\x65\x65\x65\x6c\x6c\x6c\x6c\x6c\x6c\x6c\x73\x73\x73\x73\x73\x73\x73\x02\x04\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x02\x07\x73\x73\x73\x73\x73\x72" \
+"\x72\x72\x72\x71\x71\x71\x71\x71\x71\x70\x70\x70\x70\x70\x6f\x6f\x6f\x6f\x6f\x6f\x6f\x92\x92\x92\x92\xb5\xb5\xb5\xb5\xb5\xb5\xd8\xd8\xd8\xd8\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xf4\xf4\xf4\xf4\xf4\xf4\xf4\xf4\xed\xed\xed\xed\xed\xed\xed\xe6\xe6\xe6\xe6\xe7\xe7\xe7\xe7\xe7\xe8\xe8\xe8\xe8\xe8\xe8\xe9\xe9\xe9\xe9\xea\xea\xea\xea\xea\xea\xea\xea\xea\xea\xc7\xc7\xc7\xc7\xc7\xa4\xa4\xa4\xa4\xa4\x81\x81\x81\x81\x81\x5e\x5e\x5e\x5e\x5e\x65\x65\x65\x65\x65\x65\x65\x6c\x6c\x6c\x6c\x6c\x6c\x6c\x73\x73\x73\x73\x73\x73\x73\x02\x04\x07\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\x02\x07\x73\x73\x73\x73\x73\x72\x72\x72\x72\x71\x71\x71\x71\x71\x71\x70\x70\x70\x70\x6f\x6f\x6f\x6f\x6f\x6f\x6f\x6f\x92\x92\x92\x92\xb5\xb5\xb5\xb5\xb5\xb5\xd8\xd8\xd8\xd8\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xf4\xf4\xf4\xf4\xf4\xf4\xf4\xed\xed\xed\xed\xed\xed\xed\xe6\xe6\xe6\xe6\xe6\xe6\xe7\xe7\xe7\xe7\xe8\xe8\xe8\xe8\xe8\xe8\xe9\xe9\xe9\xe9\xea\xea\xea\xea\xea\xea\xea\xea\xea\xea\xc7\xc7\xc7\xc7\xa4\xa4\xa4\xa4\xa4\xa4\x81" \
+"\x81\x81\x81\x5e\x5e\x5e\x5e\x5e\x5e\x65\x65\x65\x65\x65\x65\x65\x65\x6c\x6c\x6c\x6c\x6c\x6c\x6c\x73\x73\x73\x73\x73\x73\x02\x04\x07\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\x02\x07\x50\x50\x50\x50\x50\x4f\x4f\x4f\x4f\x4e\x4e\x4e\x4e\x4e\x4d\x4d\x4d\x4d\x4d\x4c\x4c\x4c\x4c\x6e\x6e\x6e\x6e\x6e\x91\x91\x91\x91\xb4\xb4\xb4\xb4\xb4\xb4\xd7\xd7\xd7\xd7\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xf3\xf3\xf3\xf3\xf3\xf3\xf3\xec\xec\xec\xec\xec\xec\xec\xe5\xe5\xe5\xe6\xe6\xe6\xe6\xe7\xe7\xe7\xe7\xe8\xe8\xe8\xe8\xe8\xe9\xe9\xe9\xe9\xe9\xea\xea\xea\xea\xea\xea\xea\xea\xea\xc7\xc7\xc7\xc7\xa4\xa4\xa4\xa4\xa4\xa4\x81\x81\x81\x81\x5e\x5e\x5e\x5e\x3b\x3b\x3b\x42\x42\x42\x42\x42\x42\x42\x49\x49\x49\x49\x49\x49\x49\x50\x50\x50\x50\x50\x50\x02\x04\x07\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\x02\x07\x50\x50\x50\x50\x4f\x4f\x4f\x4f\x4f\x4e\x4e\x4e\x4e\x4e\x4d\x4d\x4d\x4d\x4c\x4c\x4c\x4c\x4b\x4b\x6e\x6e\x6e\x6e\x6e\x91\x91\x91\x91\xb4\xb4\xb4\xb4\xb4\xd7\xd7\xd7\xd7\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xf3\xf3\xf3" \
+"\xf3\xf3\xf3\xec\xec\xec\xec\xec\xec\xec\xe5\xe5\xe5\xe5\xe6\xe6\xe6\xe6\xe6\xe7\xe7\xe7\xe8\xe8\xe8\xe8\xe8\xe8\xe9\xe9\xe9\xe9\xea\xea\xea\xea\xea\xea\xea\xea\xea\xc7\xc7\xc7\xc7\xa4\xa4\xa4\xa4\xa4\x81\x81\x81\x81\x5e\x5e\x5e\x5e\x3b\x3b\x3b\x3b\x3b\x42\x42\x42\x42\x42\x42\x42\x49\x49\x49\x49\x49\x49\x50\x50\x50\x50\x50\x50\x02\x04\x07\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x02\x07\x50\x50\x50\x50\x4f\x4f\x4f\x4f\x4e\x4e\x4e\x4e\x4e\x4d\x4d\x4d\x4d\x4c\x4c\x4c\x4c\x4c\x4b\x4b\x4b\x6e\x6e\x6e\x6e\x91\x91\x91\x91\xb4\xb4\xb4\xb4\xb4\xd7\xd7\xd7\xd7\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xf3\xf3\xf3\xf3\xf3\xec\xec\xec\xec\xec\xec\xec\xec\xe5\xe5\xe5\xe5\xe5\xe6\xe6\xe6\xe6\xe7\xe7\xe7\xe7\xe8\xe8\xe8\xe8\xe8\xe9\xe9\xe9\xe9\xea\xea\xea\xea\xea\xea\xea\xea\xea\xc7\xc7\xc7\xa4\xa4\xa4\xa4\xa4\x81\x81\x81\x81\x5e\x5e\x5e\x5e\x5e\x3b\x3b\x3b\x3b\x3b\x42\x42\x42\x42\x42\x42\x42\x42\x49\x49\x49\x49\x49\x50\x50\x50\x50\x50\x50\x02\x04\x07\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x02\x07\x50\x50\x50\x50" \
+"\x4f\x4f\x4f\x4f\x4e\x4e\x4e\x4e\x4e\x4d\x4d\x4d\x4d\x4c\x4c\x4c\x4c\x4b\x4b\x4b\x4b\x4b\x6e\x6e\x6e\x6e\x91\x91\x91\xb4\xb4\xb4\xb4\xb4\xb4\xd7\xd7\xd7\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xf3\xf3\xf3\xf3\xf3\xf3\xec\xec\xec\xec\xec\xec\xec\xe5\xe5\xe5\xe5\xe5\xe5\xe6\xe6\xe6\xe6\xe7\xe7\xe7\xe7\xe8\xe8\xe8\xe8\xe8\xe9\xe9\xe9\xe9\xea\xea\xea\xea\xea\xea\xea\xea\xc7\xc7\xc7\xc7\xa4\xa4\xa4\xa4\xa4\x81\x81\x81\x81\x5e\x5e\x5e\x5e\x3b\x3b\x3b\x3b\x3b\x3b\x3b\x42\x42\x42\x42\x42\x42\x42\x49\x49\x49\x49\x49\x50\x50\x50\x50\x50\x50\x02\x04\x07\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x02\x07\x50\x50\x50\x50\x4f\x4f\x4f\x4f\x4e\x4e\x4e\x4e\x4d\x4d\x4d\x4d\x4c\x4c\x4c\x4c\x4c\x4b\x4b\x4b\x4b\x4b\x6e\x6e\x6e\x6e\x91\x91\x91\x91\xb4\xb4\xb4\xb4\xb4\xd7\xd7\xd7\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xf3\xf3\xf3\xf3\xf3\xf3\xec\xec\xec\xec\xec\xec\xe5\xe5\xe5\xe5\xe5\xde\xde\xde\xdf\xdf\xdf\xdf\xe0\xe0\xe0\xe0\xe1\xe1\xe1\xe1\xe1\xe2\xe2\xe2\xe3\xe3\xe3\xe3\xe3\xe3\xe3\xe3\xc0\xc0\xc0\xc0\x9d\x9d\x9d\x9d\x9d\x7a" \
+"\x7a\x7a\x57\x57\x57\x57\x34\x34\x34\x34\x3b\x3b\x3b\x3b\x42\x42\x42\x42\x42\x42\x42\x49\x49\x49\x49\x49\x49\x50\x50\x50\x50\x50\x02\x04\x07\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x02\x07\x50\x50\x50\x50\x4f\x4f\x4f\x4e\x4e\x4e\x4e\x4e\x4d\x4d\x4d\x4d\x4c\x4c\x4c\x4c\x4b\x4b\x4b\x4b\x4b\x4b\x6e\x6e\x6e\x6e\x6e\x91\x91\x91\xb4\xb4\xb4\xb4\xb4\xd7\xd7\xd7\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xf3\xf3\xf3\xf3\xf3\xf3\xec\xec\xec\xec\xec\xec\xe5\xe5\xe5\xe5\xe5\xde\xde\xde\xdf\xdf\xdf\xdf\xdf\xe0\xe0\xe0\xe1\xe1\xe1\xe1\xe1\xe2\xe2\xe2\xe3\xe3\xe3\xe3\xe3\xe3\xe3\xe3\xc0\xc0\xc0\xc0\x9d\x9d\x9d\x9d\x7a\x7a\x7a\x7a\x57\x57\x57\x57\x34\x34\x34\x34\x3b\x3b\x3b\x3b\x3b\x42\x42\x42\x42\x42\x42\x49\x49\x49\x49\x49\x49\x50\x50\x50\x50\x50\x02\x04\x07\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x02\x07\x2d\x2d\x2d\x2d\x2c\x2c\x2c\x2b\x2b\x2b\x2b\x2a\x2a\x2a\x2a\x29\x29\x29\x29\x28\x28\x28\x28\x4a\x4a\x4a\x4a\x6d\x6d\x6d\x6d\x90\x90\x90\x90\xb3\xb3\xb3\xb3\xd6\xd6\xd6\xd6\xf9\xf9\xf9\xf9\xf9\xf9\xf9\xf9\xf9\xf2\xf2" \
+"\xf2\xf2\xf2\xeb\xeb\xeb\xeb\xeb\xeb\xe4\xe4\xe4\xe4\xe4\xdd\xde\xde\xde\xde\xdf\xdf\xdf\xdf\xe0\xe0\xe0\xe1\xe1\xe1\xe1\xe1\xe2\xe2\xe2\xe3\xe3\xe3\xe3\xe3\xe3\xe3\xe3\xc0\xc0\xc0\x9d\x9d\x9d\x9d\x9d\x7a\x7a\x7a\x57\x57\x57\x57\x57\x34\x34\x34\x11\x11\x18\x18\x18\x18\x18\x1f\x1f\x1f\x1f\x1f\x1f\x26\x26\x26\x26\x26\x2d\x2d\x2d\x2d\x2d\x02\x04\x07\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x02\x07\x2d\x2d\x2d\x2d\x2c\x2c\x2c\x2b\x2b\x2b\x2b\x2a\x2a\x2a\x2a\x29\x29\x29\x29\x28\x28\x28\x28\x27\x4a\x4a\x4a\x4a\x6d\x6d\x6d\x6d\x90\x90\x90\xb3\xb3\xb3\xb3\xd6\xd6\xd6\xd6\xf9\xf9\xf9\xf9\xf9\xf9\xf9\xf9\xf9\xf2\xf2\xf2\xf2\xf2\xeb\xeb\xeb\xeb\xeb\xeb\xe4\xe4\xe4\xe4\xdd\xdd\xdd\xde\xde\xde\xdf\xdf\xdf\xdf\xe0\xe0\xe0\xe0\xe1\xe1\xe1\xe1\xe2\xe2\xe2\xe3\xe3\xe3\xe3\xe3\xe3\xe3\xe3\xc0\xc0\xc0\x9d\x9d\x9d\x9d\x7a\x7a\x7a\x7a\x57\x57\x57\x57\x34\x34\x34\x34\x11\x11\x18\x18\x18\x18\x18\x1f\x1f\x1f\x1f\x1f\x1f\x26\x26\x26\x26\x26\x2d\x2d\x2d\x2d\x2d\x02\x04\x07\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x02\x07\x2d\x2d" \
+"\x2d\x2d\x2c\x2c\x2c\x2b\x2b\x2b\x2b\x2a\x2a\x2a\x29\x29\x29\x29\x28\x28\x28\x28\x27\x27\x4a\x4a\x4a\x4a\x6d\x6d\x6d\x6d\x90\x90\x90\x90\xb3\xb3\xb3\xb3\xd6\xd6\xd6\xf9\xf9\xf9\xf9\xf9\xf9\xf9\xf9\xf2\xf2\xf2\xf2\xf2\xeb\xeb\xeb\xeb\xeb\xeb\xe4\xe4\xe4\xe4\xe4\xdd\xdd\xdd\xde\xde\xde\xde\xdf\xdf\xdf\xdf\xe0\xe0\xe0\xe1\xe1\xe1\xe1\xe2\xe2\xe2\xe3\xe3\xe3\xe3\xe3\xe3\xe3\xe3\xc0\xc0\xc0\x9d\x9d\x9d\x9d\x7a\x7a\x7a\x7a\x57\x57\x57\x34\x34\x34\x34\x11\x11\x11\x11\x18\x18\x18\x18\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x26\x26\x26\x26\x2d\x2d\x2d\x2d\x2d\x02\x04\x07\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x02\x07\x2d\x2d\x2d\x2d\x2c\x2c\x2c\x2b\x2b\x2b\x2b\x2a\x2a\x2a\x29\x29\x29\x29\x28\x28\x28\x28\x27\x27\x27\x4a\x4a\x4a\x6d\x6d\x6d\x6d\x6d\x90\x90\x90\xb3\xb3\xb3\xb3\xd6\xd6\xd6\xf9\xf9\xf9\xf9\xf9\xf9\xf9\xf9\xf2\xf2\xf2\xf2\xf2\xeb\xeb\xeb\xeb\xeb\xeb\xe4\xe4\xe4\xe4\xdd\xdd\xdd\xdd\xdd\xde\xde\xde\xdf\xdf\xdf\xdf\xe0\xe0\xe0\xe0\xe1\xe1\xe1\xe2\xe2\xe2\xe2\xe3\xe3\xe3\xe3\xe3\xe3\xe3\xc0\xc0\xc0\x9d\x9d\x9d\x9d\x7a" \
+"\x7a\x7a\x57\x57\x57\x57\x34\x34\x34\x34\x11\x11\x11\x11\x11\x18\x18\x18\x18\x1f\x1f\x1f\x1f\x1f\x1f\x26\x26\x26\x26\x26\x2d\x2d\x2d\x2d\x02\x04\x07\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x02\x07\x2d\x2d\x2d\x2d\x2c\x2c\x2b\x2b\x2b\x2b\x2b\x2a\x2a\x2a\x29\x29\x29\x28\x28\x28\x28\x27\x27\x27\x27\x27\x4a\x4a\x4a\x6d\x6d\x6d\x6d\x90\x90\x90\xb3\xb3\xb3\xb3\xd6\xd6\xd6\xf9\xf9\xf9\xf9\xf9\xf9\xf9\xf9\xf2\xf2\xf2\xf2\xf2\xeb\xeb\xeb\xeb\xeb\xe4\xe4\xe4\xe4\xe4\xdd\xdd\xdd\xdd\xdd\xde\xde\xde\xde\xdf\xdf\xdf\xdf\xe0\xe0\xe0\xe1\xe1\xe1\xe1\xe2\xe2\xe2\xe3\xe3\xe3\xe3\xe3\xe3\xe3\xc0\xc0\x9d\x9d\x9d\x9d\x7a\x7a\x7a\x7a\x57\x57\x57\x57\x34\x34\x34\x11\x11\x11\x11\x11\x11\x18\x18\x18\x18\x18\x1f\x1f\x1f\x1f\x1f\x26\x26\x26\x26\x26\x2d\x2d\x2d\x2d\x02\x04\x07\x05\x05\x05\x05\x85\x85\x85\x85\x85\x85\x85\x02\x07\x2d\x2d\x2d\x2c\x2c\x2c\x2b\x2b\x2b\x2b\x2a\x2a\x2a\x29\x29\x29\x29\x28\x28\x28\x28\x27\x27\x27\x27\x27\x4a\x4a\x4a\x6d\x6d\x6d\x6d\x90\x90\x90\xb3\xb3\xb3\xb3\xd6\xd6\xd6\xf9\xf9\xf9\xf9\xf9\xf9\xf9\xf9\xf2" \
+"\xf2\xf2\xf2\xeb\xeb\xeb\xeb\xeb\xeb\xe4\xe4\xe4\xe4\xe4\xdd\xdd\xdd\xdd\xdd\xdd\xde\xde\xde\xdf\xdf\xdf\xdf\xe0\xe0\xe0\xe1\xe1\xe1\xe1\xe2\xe2\xe2\xe3\xe3\xe3\xe3\xe3\xe3\xc0\xc0\xc0\x9d\x9d\x9d\x9d\x7a\x7a\x7a\x57\x57\x57\x57\x34\x34\x34\x34\x11\x11\x11\x11\x11\x11\x18\x18\x18\x18\x18\x1f\x1f\x1f\x1f\x1f\x26\x26\x26\x26\x26\x2d\x2d\x2d\x2d\x02\x04\x07\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85\x02\x07\x2d\x2d\x2d\x2c\x2c\x2c\x2b\x2b\x2b\x2a\x2a\x2a\x2a\x29\x29\x29\x29\x28\x28\x28\x28\x27\x27\x27\x27\x27\x4a\x4a\x4a\x6d\x6d\x6d\x6d\x90\x90\x90\x90\xb3\xb3\xb3\xb3\xd6\xd6\xd6\xf9\xf9\xf9\xf9\xf9\xf9\xf2\xf2\xf2\xf2\xf2\xeb\xeb\xeb\xeb\xeb\xeb\xe4\xe4\xe4\xe4\xe4\xdd\xdd\xdd\xdd\xdd\xdd\xde\xde\xde\xdf\xdf\xdf\xdf\xe0\xe0\xe0\xe0\xe1\xe1\xe1\xe1\xe2\xe2\xe3\xe3\xe3\xe3\xe3\xe3\xc0\xc0\xc0\x9d\x9d\x9d\x9d\x7a\x7a\x7a\x57\x57\x57\x57\x34\x34\x34\x34\x11\x11\x11\x11\x11\x11\x18\x18\x18\x18\x18\x1f\x1f\x1f\x1f\x1f\x1f\x26\x26\x26\x26\x2d\x2d\x2d\x2d\x02\x04\x07\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85\x02\x07" \
+"\x2d\x2d\x2c\x2c\x2c\x2b\x2b\x2b\x2b\x2a\x2a\x2a\x2a\x29\x29\x29\x29\x28\x28\x28\x28\x27\x27\x27\x27\x27\x4a\x4a\x4a\x4a\x6d\x6d\x6d\x6d\x90\x90\x90\xb3\xb3\xb3\xb3\xd6\xd6\xd6\xf9\xf9\xf9\xf9\xf9\xf9\xf2\xf2\xf2\xf2\xf2\xeb\xeb\xeb\xeb\xeb\xeb\xe4\xe4\xe4\xe4\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xde\xde\xde\xdf\xdf\xdf\xdf\xdf\xe0\xe0\xe0\xe1\xe1\xe1\xe1\xe2\xe2\xe2\xe3\xe3\xe3\xe3\xc0\xc0\xc0\x9d\x9d\x9d\x9d\x7a\x7a\x7a\x7a\x57\x57\x57\x57\x34\x34\x34\x34\x11\x11\x11\x11\x11\x11\x18\x18\x18\x18\x18\x1f\x1f\x1f\x1f\x1f\x1f\x26\x26\x26\x26\x26\x2d\x2d\x2d\x02\x04\x07\x04\x04\x04\x04\x04\x04\x04\x04\x04\x04\x04\x02\x07\x2d\x2d\x2c\x2c\x2c\x2b\x2b\x2b\x2b\x2a\x2a\x2a\x29\x29\x29\x29\x29\x28\x28\x28\x28\x27\x27\x27\x27\x27\x4a\x4a\x4a\x4a\x6d\x6d\x6d\x6d\x90\x90\x90\x90\xb3\xb3\xb3\xb3\xd6\xd6\xd6\xf9\xf9\xf9\xf9\xf2\xf2\xf2\xf2\xf2\xeb\xeb\xeb\xeb\xeb\xeb\xe4\xe4\xe4\xe4\xe4\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xde\xde\xde\xde\xdf\xdf\xdf\xdf\xe0\xe0\xe0\xe1\xe1\xe1\xe1\xe1\xe2\xe2\xe3\xe3\xe3\xe3\xc0\xc0\xc0\x9d\x9d\x9d\x9d\x7a" \
+"\x7a\x7a\x7a\x57\x57\x57\x57\x34\x34\x34\x11\x11\x11\x11\x11\x11\x11\x11\x18\x18\x18\x18\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x26\x26\x26\x26\x2d\x2d\x2d\x02\x04\x07\x04\x04\x04\x04\x04\x04\x04\x04\x04\x04\x04\x02\x07\x2d\x2c\x2c\x2c\x2b\x2b\x2b\x2b\x2b\x2a\x2a\x2a\x29\x29\x29\x29\x28\x28\x28\x28\x27\x27\x27\x27\x27\x27\x4a\x4a\x4a\x4a\x6d\x6d\x6d\x6d\x6d\x90\x90\x90\xb3\xb3\xb3\xb3\xd6\xd6\xd6\xf9\xf9\xf9\xf9\xf2\xf2\xf2\xf2\xf2\xeb\xeb\xeb\xeb\xeb\xeb\xe4\xe4\xe4\xe4\xe4\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xde\xde\xde\xde\xdf\xdf\xdf\xdf\xe0\xe0\xe0\xe0\xe1\xe1\xe1\xe1\xe2\xe2\xe2\xe3\xe3\xc0\xc0\xc0\x9d\x9d\x9d\x9d\x7a\x7a\x7a\x7a\x57\x57\x57\x57\x34\x34\x34\x34\x11\x11\x11\x11\x11\x11\x11\x11\x18\x18\x18\x18\x18\x1f\x1f\x1f\x1f\x1f\x1f\x26\x26\x26\x26\x26\x2d\x2d\x02\x04\x07\x04\x04\x04\x04\x04\x04\x04\x04\x04\x04\x04\x02\x07\x2d\x2c\x2c\x2c\x2b\x2b\x2b\x2b\x2a\x2a\x2a\x29\x29\x29\x29\x29\x28\x28\x28\x28\x27\x27\x27\x27\x27\x27\x4a\x4a\x4a\x4a\x4a\x6d\x6d\x6d\x6d\x90\x90\x90\x90\xb3\xb3\xb3\xb3\xd6\xd6\xd6\xf9\xf9\xf2\xf2" \
+"\xf2\xf2\xf2\xeb\xeb\xeb\xeb\xeb\xeb\xeb\xe4\xe4\xe4\xe4\xe4\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xde\xde\xde\xde\xdf\xdf\xdf\xdf\xdf\xe0\xe0\xe0\xe1\xe1\xe1\xe1\xe1\xe2\xe2\xe2\xc0\xc0\xc0\xc0\x9d\x9d\x9d\x9d\x7a\x7a\x7a\x7a\x57\x57\x57\x57\x34\x34\x34\x34\x11\x11\x11\x11\x11\x11\x11\x11\x18\x18\x18\x18\x18\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x26\x26\x26\x26\x26\x2d\x02\x04\x07\x04\x04\x04\x04\x04\x04\x04\x04\x04\x04\x04\x02\x07\x2c\x2c\x2c\x2b\x2b\x2b\x2b\x2a\x2a\x2a\x2a\x29\x29\x29\x29\x29\x28\x28\x28\x28\x27\x27\x27\x27\x27\x27\x4a\x4a\x4a\x4a\x4a\x6d\x6d\x6d\x6d\x6d\x90\x90\x90\xb3\xb3\xb3\xb3\xd6\xd6\xd6\xd6\xd6\xcf\xcf\xcf\xcf\xcf\xc8\xc8\xc8\xc8\xc8\xc8\xc1\xc1\xc1\xc1\xc1\xc1\xba\xba\xba\xba\xba\xba\xba\xbb\xbb\xbb\xbb\xbc\xbc\xbc\xbc\xbc\xbd\xbd\xbd\xbd\xbe\xbe\xbe\xbe\xbf\xbf\xbf\xbf\xbf\xbf\x9c\x9c\x9c\x9c\x79\x79\x79\x79\x56\x56\x56\x56\x56\x33\x33\x33\x33\x10\x10\x10\x10\x10\x10\x10\x10\x17\x17\x17\x17\x17\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x25\x25\x25\x25\x25\x2c\x02\x04\x07\x04\x04\x04\x04\x04\x04\x04\x04\x04\x04\x04" \
+"\x02\x07\x2c\x2c\x2b\x2b\x2b\x2b\x2b\x2a\x2a\x2a\x2a\x29\x29\x29\x29\x29\x28\x28\x28\x28\x27\x27\x27\x27\x27\x27\x4a\x4a\x4a\x4a\x4a\x6d\x6d\x6d\x6d\x6d\x90\x90\x90\x90\xb3\xb3\xb3\xb3\xd6\xd6\xd6\xcf\xcf\xcf\xcf\xcf\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc1\xc1\xc1\xc1\xc1\xc1\xba\xba\xba\xba\xba\xba\xba\xbb\xbb\xbb\xbb\xbb\xbc\xbc\xbc\xbc\xbc\xbd\xbd\xbd\xbe\xbe\xbe\xbe\xbe\xbf\xbf\xbf\xbf\xbf\x9c\x9c\x9c\x9c\x79\x79\x79\x79\x56\x56\x56\x56\x56\x33\x33\x33\x33\x10\x10\x10\x10\x10\x10\x10\x10\x17\x17\x17\x17\x17\x17\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x25\x25\x25\x25\x25\x02\x04\x07\x04\x04\x04\x04\x04\x04\x04\x04\x04\x04\x04\x02\x07\x25\x25\x24\x24\x24\x24\x23\x23\x23\x23\x22\x22\x22\x22\x22\x21\x21\x21\x21\x21\x20\x20\x20\x20\x20\x20\x43\x43\x43\x43\x43\x66\x66\x66\x66\x66\x89\x89\x89\x89\xac\xac\xac\xac\xac\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xc8\xc8\xc8\xc8\xc8\xc8\xc1\xc1\xc1\xc1\xc1\xc1\xc1\xba\xba\xba\xba\xba\xba\xba\xbb\xbb\xbb\xbb\xbb\xbc\xbc\xbc\xbc\xbc\xbd\xbd\xbd\xbd\xbe\xbe\xbe\xbe\xbf\xbf\xbf\xbf\x9c\x9c\x9c\x9c\x79\x79" \
+"\x79\x79\x56\x56\x56\x56\x56\x33\x33\x33\x33\x33\x10\x10\x10\x10\x10\x10\x10\x10\x17\x17\x17\x17\x17\x17\x17\x1e\x1e\x1e\x1e\x1e\x1e\x25\x25\x25\x25\x25\x02\x04\x07\x04\x04\x04\x04\x04\x04\x04\x04\x04\x04\x04\x02\x07\x25\x24\x24\x24\x24\x24\x23\x23\x23\x23\x22\x22\x22\x22\x22\x21\x21\x21\x21\x21\x20\x20\x20\x20\x20\x20\x20\x43\x43\x43\x43\x66\x66\x66\x66\x66\x66\x89\x89\x89\x89\xac\xac\xac\xac\xcf\xcf\xcf\xcf\xcf\xcf\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc1\xc1\xc1\xc1\xc1\xc1\xba\xba\xba\xba\xba\xba\xba\xba\xbb\xbb\xbb\xbb\xbb\xbc\xbc\xbc\xbc\xbc\xbc\xbd\xbd\xbd\xbd\xbe\xbe\xbe\xbe\xbf\xbf\x9c\x9c\x9c\x9c\x9c\x79\x79\x79\x79\x56\x56\x56\x56\x56\x33\x33\x33\x33\x33\x10\x10\x10\x10\x10\x10\x10\x10\x10\x17\x17\x17\x17\x17\x17\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x25\x25\x25\x25\x02\x04\x07\x5a\x5a\x5a\x5a\x5a\x5a\x5a\x5a\x5a\x5a\x5a\x02\x07\x25\x24\x24\x24\x24\x23\x23\x23\x23\x22\x22\x22\x22\x22\x22\x21\x21\x21\x21\x21\x20\x20\x20\x20\x20\x20\x20\x43\x43\x43\x43\x43\x66\x66\x66\x66\x66\x89\x89\x89\x89\xac\xac\xac\xac\xac\xcf\xcf" \
+"\xcf\xcf\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc1\xc1\xc1\xc1\xc1\xc1\xba\xba\xba\xba\xba\xba\xba\xba\xbb\xbb\xbb\xbb\xbb\xbc\xbc\xbc\xbc\xbc\xbc\xbd\xbd\xbd\xbd\xbe\xbe\xbe\xbe\xbe\x9c\x9c\x9c\x9c\x9c\x79\x79\x79\x79\x56\x56\x56\x56\x56\x56\x33\x33\x33\x33\x33\x10\x10\x10\x10\x10\x10\x10\x10\x10\x17\x17\x17\x17\x17\x17\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x25\x25\x25\x25\x02\x04\x07\x5a\x5a\x5a\x5a\x5a\x5a\x5a\x5a\x5a\x5a\x5a\x02\x07\x24\x24\x24\x24\x23\x23\x23\x23\x23\x22\x22\x22\x22\x22\x21\x21\x21\x21\x21\x21\x20\x20\x20\x20\x20\x20\x20\x43\x43\x43\x43\x43\x66\x66\x66\x66\x66\x66\x89\x89\x89\x89\xac\xac\xac\xac\xac\xac\xac\xac\xa5\xa5\xa5\xa5\xa5\xa5\xa5\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x97\x97\x97\x97\x97\x97\x97\x97\x97\x98\x98\x98\x98\x98\x99\x99\x99\x99\x99\x9a\x9a\x9a\x9a\x9a\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x78\x78\x78\x78\x55\x55\x55\x55\x55\x55\x32\x32\x32\x32\x32\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x16\x16\x16\x16\x16\x16\x1d\x1d\x1d\x1d\x1d\x1d\x1d\x1d\x24\x24\x24\x02\x04\x07\x5a\x5a\x5a\x5a\x5a\x5a\x5a\x5a\x5a" \
+"\x5a\x5a\x02\x07\x24\x24\x24\x24\x23\x23\x23\x23\x22\x22\x22\x22\x22\x22\x21\x21\x21\x21\x21\x20\x20\x20\x20\x20\x20\x20\x20\x43\x43\x43\x43\x43\x43\x66\x66\x66\x66\x66\x89\x89\x89\x89\x89\xac\xac\xac\xac\xac\xac\xa5\xa5\xa5\xa5\xa5\xa5\xa5\xa5\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x97\x97\x97\x97\x97\x97\x97\x97\x97\x98\x98\x98\x98\x98\x99\x99\x99\x99\x99\x99\x9a\x9a\x9a\x9a\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x78\x78\x78\x78\x55\x55\x55\x55\x55\x55\x32\x32\x32\x32\x32\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x16\x16\x16\x16\x16\x16\x16\x1d\x1d\x1d\x1d\x1d\x1d\x1d\x1d\x24\x24\x02\x04\x07\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x02\x07\x24\x24\x24\x23\x23\x23\x23\x22\x22\x22\x22\x22\x22\x22\x21\x21\x21\x21\x21\x20\x20\x20\x20\x20\x20\x20\x20\x43\x43\x43\x43\x43\x43\x66\x66\x66\x66\x66\x66\x89\x89\x89\x89\xac\xac\xac\xac\xac\xa5\xa5\xa5\xa5\xa5\xa5\xa5\xa5\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x97\x97\x97\x97\x97\x97\x97\x97\x97\x97\x98\x98\x98\x98\x98\x98\x99\x99\x99\x99\x99\x99\x9a\x9a\x9a\x9a\x9b\x9b\x9b\x9b\x9b\x9b\x78\x78\x78" \
+"\x78\x55\x55\x55\x55\x55\x55\x55\x32\x32\x32\x32\x32\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x16\x16\x16\x16\x16\x16\x16\x16\x1d\x1d\x1d\x1d\x1d\x1d\x1d\x1d\x24\x02\x04\x07\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x02\x07\x24\x24\x23\x23\x23\x23\x23\x22\x22\x22\x22\x22\x22\x21\x21\x21\x21\x21\x21\x20\x20\x20\x20\x20\x20\x20\x20\x43\x43\x43\x43\x43\x43\x66\x66\x66\x66\x66\x66\x66\x89\x89\x89\x89\xac\xac\xac\xac\xa5\xa5\xa5\xa5\xa5\xa5\xa5\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x97\x97\x97\x97\x97\x97\x97\x97\x97\x97\x98\x98\x98\x98\x98\x98\x99\x99\x99\x99\x99\x99\x9a\x9a\x9a\x9a\x9a\x9b\x9b\x9b\x9b\x78\x78\x78\x78\x78\x55\x55\x55\x55\x55\x55\x32\x32\x32\x32\x32\x32\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x16\x16\x16\x16\x16\x16\x16\x1d\x1d\x1d\x1d\x1d\x1d\x1d\x1d\x24\x02\x04\x07\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x02\x07\x24\x23\x23\x23\x23\x23\x22\x22\x22\x22\x22\x22\x22\x21\x21\x21\x21\x21\x21\x20\x20\x20\x20\x20\x20\x20\x20\x20\x43\x43\x43\x43\x43\x43\x66\x66\x66\x66\x66\x66\x89\x89\x89\x89\x89\xac" \
+"\xac\xa5\xa5\xa5\xa5\xa5\xa5\xa5\xa5\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x97\x97\x97\x97\x97\x97\x97\x97\x97\x97\x98\x98\x98\x98\x98\x98\x98\x99\x99\x99\x99\x99\x99\x9a\x9a\x9a\x9a\x9a\x9b\x9b\x9b\x78\x78\x78\x78\x55\x55\x55\x55\x55\x55\x55\x32\x32\x32\x32\x32\x32\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x16\x16\x16\x16\x16\x16\x16\x16\x1d\x1d\x1d\x1d\x1d\x1d\x1d\x1d\x02\x04\x07\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x02\x07\x1d\x1c\x1c\x1c\x1c\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x19\x19\x19\x19\x19\x19\x19\x19\x19\x3c\x3c\x3c\x3c\x3c\x3c\x5f\x5f\x5f\x5f\x5f\x5f\x5f\x82\x82\x82\x82\x82\xa5\xa5\xa5\xa5\xa5\xa5\xa5\xa5\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x97\x97\x97\x97\x97\x97\x97\x97\x97\x97\x97\x98\x98\x98\x98\x98\x98\x98\x99\x99\x99\x99\x99\x99\x99\x9a\x9a\x9a\x9a\x9a\x9b\x78\x78\x78\x78\x55\x55\x55\x55\x55\x55\x55\x32\x32\x32\x32\x32\x32\x32\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x16\x16\x16\x16\x16\x16\x16\x16\x16\x1d\x1d\x1d\x1d\x1d\x1d\x1d\x02\x04\x07\x03\x03\x03\x03\x03\x03\x03" \
+"\x03\x03\x03\x03\x02\x07\x1c\x1c\x1c\x1c\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x3c\x3c\x3c\x3c\x3c\x3c\x3c\x5f\x5f\x5f\x5f\x5f\x5f\x5f\x82\x82\x82\x82\x82\x82\x82\x82\x82\x82\x82\x7b\x7b\x7b\x7b\x7b\x7b\x7b\x7b\x7b\x74\x74\x74\x74\x74\x74\x74\x74\x74\x74\x74\x74\x75\x75\x75\x75\x75\x75\x75\x76\x76\x76\x76\x76\x76\x76\x77\x77\x77\x77\x77\x77\x77\x77\x77\x54\x54\x54\x54\x54\x54\x54\x31\x31\x31\x31\x31\x31\x31\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x15\x15\x15\x15\x15\x15\x15\x15\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x02\x04\x07\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x07\x1c\x1c\x1c\x1c\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x3c\x3c\x3c\x3c\x3c\x3c\x3c\x3c\x5f\x5f\x5f\x5f\x5f\x5f\x5f\x82\x82\x82\x82\x82\x82\x82\x82\x82\x82\x7b\x7b\x7b\x7b\x7b\x7b\x7b\x7b\x7b\x74\x74\x74\x74\x74\x74\x74\x74\x74\x74\x74\x74\x75\x75\x75\x75\x75\x75\x75\x75\x76\x76\x76\x76\x76\x76\x76\x77\x77\x77\x77\x77\x77\x54" \
+"\x54\x54\x54\x54\x54\x54\x54\x31\x31\x31\x31\x31\x31\x31\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x15\x15\x15\x15\x15\x15\x15\x15\x15\x1c\x1c\x1c\x1c\x1c\x1c\x02\x04\x07\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x07\x1c\x1c\x1c\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x3c\x3c\x3c\x3c\x3c\x3c\x3c\x3c\x5f\x5f\x5f\x5f\x5f\x5f\x5f\x5f\x82\x82\x82\x82\x82\x82\x82\x82\x7b\x7b\x7b\x7b\x7b\x7b\x7b\x7b\x7b\x74\x74\x74\x74\x74\x74\x74\x74\x74\x74\x74\x74\x74\x75\x75\x75\x75\x75\x75\x75\x75\x76\x76\x76\x76\x76\x76\x76\x77\x77\x77\x77\x77\x77\x54\x54\x54\x54\x54\x54\x54\x31\x31\x31\x31\x31\x31\x31\x31\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x15\x15\x15\x15\x15\x15\x15\x15\x15\x1c\x1c\x1c\x1c\x1c\x02\x04\x07\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x07\x1c\x1c\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x3c\x3c\x3c\x3c\x3c\x3c\x3c\x3c\x5f\x5f\x5f\x5f\x5f\x5f\x5f" \
+"\x5f\x82\x82\x82\x82\x82\x82\x7b\x7b\x7b\x7b\x7b\x7b\x7b\x7b\x7b\x7b\x74\x74\x74\x74\x74\x74\x74\x74\x74\x74\x74\x74\x74\x74\x75\x75\x75\x75\x75\x75\x75\x75\x76\x76\x76\x76\x76\x76\x76\x76\x77\x77\x77\x54\x54\x54\x54\x54\x54\x54\x54\x31\x31\x31\x31\x31\x31\x31\x31\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x1c\x1c\x1c\x1c\x02\x04\x07\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x07\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x3c\x3c\x3c\x3c\x3c\x3c\x3c\x3c\x3c\x5f\x5f\x5f\x5f\x5f\x5f\x5f\x5f\x82\x82\x82\x82\x7b\x7b\x7b\x7b\x7b\x7b\x7b\x7b\x7b\x7b\x74\x74\x74\x74\x74\x74\x74\x74\x74\x74\x74\x74\x74\x74\x74\x75\x75\x75\x75\x75\x75\x75\x75\x75\x76\x76\x76\x76\x76\x76\x76\x76\x54\x54\x54\x54\x54\x54\x54\x54\x31\x31\x31\x31\x31\x31\x31\x31\x31\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x1c\x1c\x1c\x02\x04\x07\x02\x02\x02\x02\x02" \
+"\x02\x02\x02\x02\x02\x02\x02\x07\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x3c\x3c\x3c\x3c\x3c\x3c\x3c\x3c\x3c\x5f\x5f\x5f\x5f\x5f\x5f\x5f\x5f\x5f\x5f\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x52\x52\x52\x52\x52\x52\x52\x52\x52\x52\x53\x53\x53\x53\x53\x53\x53\x53\x53\x53\x53\x53\x53\x53\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x1b\x1b\x02\x04\x07\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x07\x1b\x1b\x1b\x1b\x1b\x1b\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x3c\x3c\x3c\x3c\x3c\x3c\x3c\x3c\x3c\x3c\x5f\x5f\x5f\x5f\x5f\x5f\x5f\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x52\x52\x52\x52\x52\x52\x52\x52\x52\x52\x53\x53\x53\x53\x53\x53\x53\x53" \
+"\x53\x53\x53\x53\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x02\x04\x07\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x07\x14\x14\x14\x14\x14\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x35\x35\x35\x35\x35\x35\x35\x35\x35\x35\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x52\x52\x52\x52\x52\x52\x52\x52\x52\x52\x52\x53\x53\x53\x53\x53\x53\x53\x53\x53\x53\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x02\x04\x07\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x02\x07\x14\x14\x14\x14\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x35\x35\x35\x35\x35\x35\x35\x35\x35\x35\x35" \
+"\x35\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x52\x52\x52\x52\x52\x52\x52\x52\x52\x52\x52\x52\x53\x53\x53\x53\x53\x53\x53\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x02\x04\x07\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x02\x07\x14\x14\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x35\x35\x35\x35\x35\x35\x35\x35\x35\x35\x35\x35\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x52\x52\x52\x52\x52\x52\x52\x52\x52\x52\x52\x52\x53\x53\x53\x53\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x14\x14\x14\x14\x14\x14\x14\x14\x14\x02\x04\x07\x01\x01\x01" \
+"\x01\x01\x01\x01\x01\x01\x01\x01\x02\x07\x14\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x35\x35\x35\x35\x35\x35\x35\x35\x35\x35\x35\x35\x58\x58\x58\x58\x58\x58\x58\x58\x58\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x51\x52\x52\x52\x52\x52\x52\x52\x52\x52\x52\x52\x52\x53\x53\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x14\x14\x14\x14\x14\x14\x14\x02\x04\x07\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x02\x07\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x35\x35\x35\x35\x35\x35\x35\x35\x35\x35\x35\x35\x35\x35\x35\x35\x35\x35\x35\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f" \
+"\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x13\x13\x13\x13\x13\x13\x02\x04\x07\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x02\x07\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x35\x35\x35\x35\x35\x35\x35\x35\x35\x35\x35\x35\x35\x35\x35\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x13\x13\x13\x13\x02\x04\x07\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x02\x07\x13\x13\x13\x13\x13\x13\x01\x01\x01\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x01\x01\x01" \
+"\x35\x35\x35\x35\x35\x35\x35\x35\x35\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x13\x13\x02\x04\x07\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x02\x07\x0c\x0c\x0c\x0c\x01\x01\x01\x01\x01\x01\x01\x12\x12\x12\x12\x12\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x12\x12\x12\x12\x01\x01\x01\x01\x01\x01\x01\x01\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x01\x01\x01\x01\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x01\x01\x01\x01\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x02\x04\x07\x0b" \
+"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x02\x07\x0c\x01\x01\x01\x01\x01\x01\x01\x01\x01\x12\x12\x12\x12\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x12\x12\x12\x12\x12\x01\x01\x01\x01\x01\x01\x01\x01\x01\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x02\x04\x07\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x02\x07\x01\x01\x01\x01\x01\x01\x01\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x01\x01\x01\x01\x01\x01\x01\x01\x01\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x2e\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x01\x01\x01\x01\x01" \
+"\x01\x01\x01\x01\x01\x01\x01\x01\x01\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x01\x02\x04\x07\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x02\x07\x0c\x0c\x0c\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x2e\x2e\x2e\x2e\x2e\x2e\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0c\x0c\x02\x04\x07\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x02\x07\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" \
+"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x02\x04\x07\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x02\x07\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x02\x04" \
+"\x07\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x02\x07\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x02\x04\x07\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x02\x07\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" \
+"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x02\x04\x07\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x02\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x04\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x03\x01\x00\x14\x00\x3e\x33\x00\x00\x00\x01\x00\x00\x38\x42\x49\x4d\x03\xed\x00\x00\x00\x00\x00\x10\x00\x48\x00\x00\x00\x01\x00\x01\x00\x48\x00\x00\x00" \
+"\x01\x00\x01\x38\x42\x49\x4d\x03\xf3\x00\x00\x00\x00\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x38\x42\x49\x4d\x03\xf5\x00\x00\x00\x00\x00\x48\x00\x2f\x66\x66\x00\x01\x00\x6c\x66\x66\x00\x06\x00\x00\x00\x00\x00\x00\x00\x2f\x66\x66\x00\x01\x00\xa1\x99\x9a\x00\x06\x00\x00\x00\x00\x00\x00\x00\x32\x00\x00\x00\x01\x00\x5a\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x35\x00\x00\x00\x01\x00\x2d\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x38\x42\x49\x4d\x03\xf8\x00\x00\x00\x00\x00\x70\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x03\xe8\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x03\xe8\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x03\xe8\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x03\xe8\x00\x00\x00\x00\x00\x00\x32\x33\x00\x00\x54\x52\x55\x45\x56\x49\x53\x49\x4f\x4e\x2d\x58\x46\x49\x4c\x45\x2e" \
+"\x00"};
diff --git a/source/blender/src/cmovie.tga.c b/source/blender/src/cmovie.tga.c
new file mode 100644
index 00000000000..1d468946352
--- /dev/null
+++ b/source/blender/src/cmovie.tga.c
@@ -0,0 +1,201 @@
+/* DataToC output of file <cmovie_tga> */
+/*
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 datatoc_cmovie_tga_size= 6247;
+char datatoc_cmovie_tga[]= {"\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x00\x34\x00\x20\x00\x01\x0c\x0c\x0c\xff\x0d\x0d\x0d\xff\x82\xe0\xe0\xe0\xff\x01\xdf\xdf\xdf\xff\x0d\x0d\x0d\xff\x83\x0c\x0c\x0c\xff\x17\xfe\xfe\xfe\xff\xfd\xfd\xfd\xff\xfd\xfd\xfd\xff\xfe\xfe\xfe\xff\x50\x50\x50\xff\x9c\x9c\x9c\xff\x9c\x9c\x9c\xff\x9d\x9d\x9d\xff\xac\xac\xac\xff\xb8\xb8\xb8\xff\xb6\xb6\xb6\xff\xa9\xa9\xa9\xff\x9c\x9c\x9c\xff\xa4\xa4\xa4" \
+"\xff\xb2\xb2\xb2\xff\x3b\x35\x35\xff\x58\x51\x51\xff\xa3\x9c\x9c\xff\x9a\x97\x97\xff\xb8\xb8\xb8\xff\xaf\xae\xae\xff\x47\x42\x42\xff\x86\x80\x80\xff\xb4\xb4\xb4\xff\x8c\xb7\xb7\xb7\xff\x84\xb8\xb8\xb8\xff\x83\x0c\x0c\x0c\xff\x00\x0d\x0d\x0d\xff\x82\xe0\xe0\xe0\xff\x01\xdf\xdf\xdf\xff\x0d\x0d\x0d\xff\x8b\x0c\x0c\x0c\xff\x83\xfe\xfe\xfe\xff\x13\x52\x52\x52\xff\x9f\x9f\x9f\xff\xa0\xa0\xa0\xff\xa9\xa9\xa9\xff\xb6\xb6\xb6\xff\xb7\xb7\xb7\xff\xac\xac\xac\xff\x9d\x9d\x9d\xff\x9c\x9c\x9c\xff\xa6\xa6\xa6\xff\xa6\xa6\xa6\xff\x38\x32\x32\xff\x72\x6a\x6a\xff\x86\x80\x80\xff\xaf\xaf\xaf\xff\xb7\xb7\xb7\xff\x5d\x5a\x5a\xff\x4d\x46\x46\xff\x9a\x93\x93\xff\xb4\xb4\xb4\xff\x8b\xb7\xb7\xb7\xff\x85\xb8\xb8\xb8\xff\x95\x0c\x0c\x0c\xff\x83\xfe\xfe\xfe\xff\x13\x5a\x5a\x5a\xff\xb3\xb3\xb3\xff\xb4\xb4\xb4\xff\xb7\xb7\xb7\xff\xb8\xb8\xb8\xff\xb5\xb5\xb5\xff\xa2\xa2\xa2\xff\x9c\x9c\x9c\xff\x9d\x9d\x9d\xff\xad\xad\xad\xff\xb8\xb8\xb8\xff\x91\x8f\x8f\xff\x8e\x8b\x8b\xff\xad\xac\xac\xff\xb8\xb8\xb8\xff\x9a\x99\x99\xff\x33\x2c\x2c\xff\x84" \
+"\x7d\x7d\xff\x9e\x99\x99\xff\xb6\xb6\xb6\xff\x8b\xb7\xb7\xb7\xff\x85\xb8\xb8\xb8\xff\x8b\x0c\x0c\x0c\xff\x00\x0d\x0d\x0d\xff\x82\xe0\xe0\xe0\xff\x01\xdf\xdf\xdf\xff\x0d\x0d\x0d\xff\x83\x0c\x0c\x0c\xff\x83\xc3\x73\x00\xff\x00\x5c\x5c\x5c\xff\x83\xb8\xb8\xb8\xff\x04\xb5\xb5\xb5\xff\xa3\xa3\xa3\xff\x9e\x9e\x9e\xff\xa7\xa7\xa7\xff\xb6\xb6\xb6\xff\x83\xb8\xb8\xb8\xff\x04\xb7\xb7\xb7\xff\x92\x90\x90\xff\x43\x3b\x3b\xff\x7b\x74\x74\xff\xa0\x9d\x9d\xff\x89\xb7\xb7\xb7\xff\x01\xb6\xb6\xb6\xff\xb7\xb7\xb7\xff\x86\xb8\xb8\xb8\xff\x83\x0c\x0c\x0c\xff\x00\x0d\x0d\x0d\xff\x82\xe0\xe0\xe0\xff\x03\xdf\xdf\xdf\xff\x0d\x0d\x0d\xff\x0c\x0c\x0c\xff\x0c\x0c\x0c\xff\x83\xe0\xe0\xe0\xff\x01\xdf\xdf\xdf\xff\xdf\xdf\xdf\xff\x83\x0c\x0c\x0c\xff\x83\xc3\x73\x00\xff\x00\x5c\x5c\x5c\xff\x83\xb8\xb8\xb8\xff\x03\xb7\xb7\xb7\xff\xb3\xb3\xb3\xff\xb2\xb2\xb2\xff\xb7\xb7\xb7\xff\x83\xb8\xb8\xb8\xff\x04\xb7\xb7\xb7\xff\xb7\xb7\xb7\xff\xb6\xb6\xb6\xff\x91\x8f\x8f\xff\xa2\xa0\xa0\xff\x8b\xb7\xb7\xb7\xff\x87\xb8\xb8\xb8\xff\x83\x0c\x0c\x0c\xff\x83" \
+"\xe0\xe0\xe0\xff\x03\xdf\xdf\xdf\xff\xdf\xdf\xdf\xff\x0c\x0c\x0c\xff\x0c\x0c\x0c\xff\x83\xe0\xe0\xe0\xff\x01\xdf\xdf\xdf\xff\xdf\xdf\xdf\xff\x83\x0c\x0c\x0c\xff\x83\xc3\x73\x00\xff\x00\x5c\x5c\x5c\xff\x89\xb8\xb8\xb8\xff\x01\xb7\xb7\xb7\xff\xb8\xb8\xb8\xff\x8f\xb7\xb7\xb7\xff\x88\xb8\xb8\xb8\xff\x83\x0c\x0c\x0c\xff\x83\xe0\xe0\xe0\xff\x04\xdf\xdf\xdf\xff\xdf\xdf\xdf\xff\x0c\x0c\x0c\xff\x0c\x0c\x0c\xff\x0d\x0d\x0d\xff\x82\xe0\xe0\xe0\xff\x01\xdf\xdf\xdf\xff\x0d\x0d\x0d\xff\xb1\x0c\x0c\x0c\xff\x00\x0d\x0d\x0d\xff\x82\xe0\xe0\xe0\xff\x01\xdf\xdf\xdf\xff\x0d\x0d\x0d\xff\xff\x0c\x0c\x0c\xff\x81\x0c\x0c\x0c\xff\x00\x0d\x0d\x0d\xff\x82\xe0\xe0\xe0\xff\x01\xdf\xdf\xdf\xff\x0d\x0d\x0d\xff\x83\x0c\x0c\x0c\xff\x83\xfe\xfe\xfe\xff\x00\x5c\x5c\x5c\xff\x85\xb8\xb8\xb8\xff\x00\xb7\xb7\xb7\xff\x83\xb6\xb6\xb6\xff\x8d\xb8\xb8\xb8\xff\x02\xb7\xb7\xb7\xff\xb7\xb7\xb7\xff\xb8\xb8\xb8\xff\x82\xb7\xb7\xb7\xff\x85\xb8\xb8\xb8\xff\x83\x0c\x0c\x0c\xff\x00\x0d\x0d\x0d\xff\x82\xe0\xe0\xe0\xff\x03\xdf\xdf\xdf\xff\x0d\x0d\x0d\xff\x0c\x0c" \
+"\x0c\xff\x0c\x0c\x0c\xff\x83\xe0\xe0\xe0\xff\x01\xdf\xdf\xdf\xff\xdf\xdf\xdf\xff\x83\x0c\x0c\x0c\xff\x83\xfe\xfe\xfe\xff\x00\x5c\x5c\x5c\xff\x83\xb8\xb8\xb8\xff\x09\xb6\xb6\xb6\xff\xb2\xb2\xb2\xff\xae\xae\xae\xff\xa9\xa9\xa9\xff\xa6\xa6\xa6\xff\xa6\xa6\xa6\xff\xa8\xa8\xa8\xff\xab\xab\xab\xff\xb2\xb2\xb2\xff\xb6\xb6\xb6\xff\x89\xb8\xb8\xb8\xff\x86\xb7\xb7\xb7\xff\x85\xb8\xb8\xb8\xff\x83\x0c\x0c\x0c\xff\x83\xe0\xe0\xe0\xff\x03\xdf\xdf\xdf\xff\xdf\xdf\xdf\xff\x0c\x0c\x0c\xff\x0c\x0c\x0c\xff\x83\xe0\xe0\xe0\xff\x01\xdf\xdf\xdf\xff\xdf\xdf\xdf\xff\x83\x0c\x0c\x0c\xff\x83\xe0\xb8\x7f\xff\x06\x5c\x5c\x5c\xff\xb8\xb8\xb8\xff\xb8\xb8\xb8\xff\xb7\xb7\xb7\xff\xb1\xb1\xb1\xff\xa8\xa8\xa8\xff\xa0\xa0\xa0\xff\x85\x9c\x9c\x9c\xff\x05\x9e\x9e\x9e\xff\xa4\xa4\xa4\xff\xb0\xb0\xb0\xff\xb9\xb9\xb9\xff\xba\xba\xba\xff\xb9\xb9\xb9\xff\x86\xb8\xb8\xb8\xff\x85\xb7\xb7\xb7\xff\x85\xb8\xb8\xb8\xff\x83\x0c\x0c\x0c\xff\x83\xe0\xe0\xe0\xff\x04\xdf\xdf\xdf\xff\xdf\xdf\xdf\xff\x0c\x0c\x0c\xff\x0c\x0c\x0c\xff\x0d\x0d\x0d\xff\x82\xe0\xe0\xe0" \
+"\xff\x01\xdf\xdf\xdf\xff\x0d\x0d\x0d\xff\x83\x0c\x0c\x0c\xff\x83\xc3\x73\x00\xff\x04\x5c\x5c\x5c\xff\xb8\xb8\xb8\xff\xb6\xb6\xb6\xff\xae\xae\xae\xff\xa1\xa1\xa1\xff\x87\x9c\x9c\x9c\xff\x09\x9d\x9d\x9d\xff\xa0\xa0\xa0\xff\xa3\xa3\xa3\xff\xa9\xa9\xa9\xff\x9c\x9b\x9c\xff\x8c\x8a\x8b\xff\x7f\x7e\x7e\xff\x8c\x8a\x8b\xff\xa1\xa1\xa1\xff\xb5\xb5\xb5\xff\x83\xb8\xb8\xb8\xff\x84\xb7\xb7\xb7\xff\x85\xb8\xb8\xb8\xff\x83\x0c\x0c\x0c\xff\x00\x0d\x0d\x0d\xff\x82\xe0\xe0\xe0\xff\x01\xdf\xdf\xdf\xff\x0d\x0d\x0d\xff\x8b\x0c\x0c\x0c\xff\x83\xc3\x73\x00\xff\x03\x5c\x5c\x5c\xff\xb7\xb7\xb7\xff\xac\xac\xac\xff\x9f\x9f\x9f\xff\x87\x9c\x9c\x9c\xff\x0e\x9d\x9d\x9d\xff\xa0\xa0\xa0\xff\x9f\x9f\x9f\xff\x6e\x6c\x6c\xff\x36\x31\x32\xff\x21\x1b\x1c\xff\x20\x1a\x1b\xff\x1f\x19\x1a\xff\x1e\x19\x1a\xff\x24\x1f\x20\xff\x42\x3e\x3f\xff\x84\x83\x83\xff\xb2\xb2\xb2\xff\xb8\xb8\xb8\xff\xb8\xb8\xb8\xff\x84\xb7\xb7\xb7\xff\x85\xb8\xb8\xb8\xff\x95\x0c\x0c\x0c\xff\x83\xe0\xb8\x7f\xff\x02\x5c\x5c\x5c\xff\xb1\xb1\xb1\xff\xa0\xa0\xa0\xff\x88\x9c\x9c\x9c" \
+"\xff\x0d\x9d\x9d\x9d\xff\x96\x96\x96\xff\x42\x3e\x3f\xff\x21\x1b\x1c\xff\x1e\x22\x20\xff\x16\x3e\x34\xff\x10\x4f\x41\xff\x0e\x53\x44\xff\x10\x41\x35\xff\x14\x1f\x1c\xff\x19\x14\x15\xff\x1e\x19\x1a\xff\x45\x41\x42\xff\xa2\xa1\xa1\xff\x85\xb7\xb7\xb7\xff\x85\xb8\xb8\xb8\xff\x8b\x0c\x0c\x0c\xff\x00\x0d\x0d\x0d\xff\x82\xe0\xe0\xe0\xff\x01\xdf\xdf\xdf\xff\x0d\x0d\x0d\xff\x83\x0c\x0c\x0c\xff\x83\xfe\xfe\xfe\xff\x01\x5a\x5a\x5a\xff\xa5\xa5\xa5\xff\x89\x9c\x9c\x9c\xff\x0e\x96\x96\x96\xff\x41\x3d\x3e\xff\x20\x1d\x1e\xff\x14\x4d\x3f\xff\x07\x98\x78\xff\x05\xaf\x8a\xff\x05\xbc\x94\xff\x05\xbb\x92\xff\x05\xba\x92\xff\x05\xa0\x7d\xff\x09\x62\x4d\xff\x10\x21\x1c\xff\x19\x14\x15\xff\x2f\x2a\x2b\xff\x99\x98\x99\xff\x84\xb7\xb7\xb7\xff\x85\xb8\xb8\xb8\xff\x83\x0c\x0c\x0c\xff\x00\x0d\x0d\x0d\xff\x82\xe0\xe0\xe0\xff\x03\xdf\xdf\xdf\xff\x0d\x0d\x0d\xff\x0c\x0c\x0c\xff\x0c\x0c\x0c\xff\x83\xe0\xe0\xe0\xff\x01\xdf\xdf\xdf\xff\xdf\xdf\xdf\xff\x83\x0c\x0c\x0c\xff\x05\xfe\xfe\xfe\xff\xfd\xfd\xfd\xff\xfd\xfd\xfd\xff\xfe\xfe\xfe\xff\x55" \
+"\x55\x55\xff\x9d\x9d\x9d\xff\x88\x9c\x9c\x9c\xff\x10\x9b\x9b\x9b\xff\x48\x45\x46\xff\x20\x1b\x1c\xff\x11\x6a\x55\xff\x06\x9d\x79\xff\x06\xa8\x82\xff\x06\xb2\x8a\xff\x06\xc3\x96\xff\x06\xd1\xa4\xff\x06\xd0\xa3\xff\x06\xbd\x94\xff\x04\xad\x88\xff\x05\x88\x6a\xff\x0b\x37\x2c\xff\x16\x12\x12\xff\x31\x2d\x2e\xff\xa2\xa2\xa2\xff\x84\xb7\xb7\xb7\xff\x84\xb8\xb8\xb8\xff\x83\x0c\x0c\x0c\xff\x83\xe0\xe0\xe0\xff\x03\xdf\xdf\xdf\xff\xdf\xdf\xdf\xff\x0c\x0c\x0c\xff\x0c\x0c\x0c\xff\x83\xe0\xe0\xe0\xff\x01\xdf\xdf\xdf\xff\xdf\xdf\xdf\xff\x83\x0c\x0c\x0c\xff\x83\xfe\xfe\xfe\xff\x01\x55\x55\x55\xff\x9e\x9e\x9e\xff\x88\x9c\x9c\x9c\xff\x11\x75\x74\x75\xff\x22\x1d\x1e\xff\x1a\x48\x3d\xff\x06\x9f\x7b\xff\x06\xaf\x8a\xff\x06\xb4\x8c\xff\x06\xc0\x95\xff\x08\xc9\x9c\xff\x09\xcd\xa3\xff\x08\xc5\x9b\xff\x07\xca\x9f\xff\x05\xba\x92\xff\x04\xa5\x81\xff\x04\x90\x71\xff\x0b\x33\x28\xff\x17\x12\x12\xff\x4d\x49\x4a\xff\xb3\xb3\xb3\xff\x83\xb7\xb7\xb7\xff\x84\xb8\xb8\xb8\xff\x83\x0c\x0c\x0c\xff\x83\xe0\xe0\xe0\xff\x04\xdf\xdf\xdf\xff\xdf\xdf" \
+"\xdf\xff\x0c\x0c\x0c\xff\x0c\x0c\x0c\xff\x0d\x0d\x0d\xff\x82\xe0\xe0\xe0\xff\x01\xdf\xdf\xdf\xff\x0d\x0d\x0d\xff\x83\x0c\x0c\x0c\xff\x83\xc3\x73\x00\xff\x02\x5b\x5b\x5b\xff\xb0\xb0\xb0\xff\xa2\xa2\xa2\xff\x86\x9c\x9c\x9c\xff\x12\x9b\x9b\x9b\xff\x3c\x39\x39\xff\x24\x1f\x20\xff\x0e\x92\x75\xff\x07\xab\x85\xff\x07\xaf\x88\xff\x07\xbd\x94\xff\x06\x97\x76\xff\x0b\x66\x4f\xff\x13\x3c\x33\xff\x19\x2d\x33\xff\x1d\x39\x46\xff\x17\x61\x5e\xff\x0b\x91\x77\xff\x04\x9d\x7b\xff\x05\x86\x69\xff\x0d\x20\x1b\xff\x1d\x18\x18\xff\x86\x84\x84\xff\x83\xb7\xb7\xb7\xff\x84\xb8\xb8\xb8\xff\x83\x0c\x0c\x0c\xff\x00\x0d\x0d\x0d\xff\x82\xe0\xe0\xe0\xff\x01\xdf\xdf\xdf\xff\x0d\x0d\x0d\xff\x8b\x0c\x0c\x0c\xff\x83\xc3\x73\x00\xff\x02\x5c\x5c\x5c\xff\xb7\xb7\xb7\xff\xa7\xa7\xa7\xff\x86\x9c\x9c\x9c\xff\x13\x8e\x8e\x8e\xff\x27\x23\x23\xff\x1d\x4c\x42\xff\x09\xb3\x8d\xff\x08\xaf\x87\xff\x09\xbf\x95\xff\x08\x9e\x7d\xff\x0b\x48\x39\xff\x1a\x10\x14\xff\x23\x12\x2a\xff\x2c\x19\x47\xff\x2d\x1b\x56\xff\x2b\x1a\x59\xff\x26\x24\x58\xff\x12\x76\x6e\xff" \
+"\x04\xa3\x80\xff\x07\x63\x4d\xff\x13\x0f\x0f\xff\x42\x3e\x3f\xff\xb4\xb4\xb4\xff\x82\xb7\xb7\xb7\xff\x84\xb8\xb8\xb8\xff\x95\x0c\x0c\x0c\xff\x83\xc3\x73\x00\xff\x02\x5c\x5c\x5c\xff\xb6\xb6\xb6\xff\xa3\xa3\xa3\xff\x86\x9c\x9c\x9c\xff\x13\x9b\x9b\x9b\xff\x88\x92\x8f\xff\x0f\xa5\x83\xff\x0a\xba\x93\xff\x0b\xb5\x8d\xff\x0a\xc4\x9b\xff\x08\x6c\x57\xff\x14\x0f\x0e\xff\x1d\x10\x20\xff\x28\x18\x42\xff\x30\x1d\x5d\xff\x36\x21\x72\xff\x39\x23\x82\xff\x37\x23\x85\xff\x2e\x27\x72\xff\x0b\x9a\x82\xff\x04\x97\x74\xff\x0c\x20\x1a\xff\x20\x1a\x1c\xff\x9f\x9e\x9e\xff\x82\xb7\xb7\xb7\xff\x84\xb8\xb8\xb8\xff\x8b\x0c\x0c\x0c\xff\x00\x0d\x0d\x0d\xff\x82\xe0\xe0\xe0\xff\x01\xdf\xdf\xdf\xff\x0d\x0d\x0d\xff\x83\x0c\x0c\x0c\xff\x83\xe0\xb8\x7f\xff\x02\x5b\x5b\x5b\xff\xb3\xb3\xb3\xff\xa4\xa4\xa4\xff\x86\x9c\x9c\x9c\xff\x13\x9d\x9d\x9d\xff\x8b\xa2\x9b\xff\x11\xb9\x96\xff\x0e\xc7\xa0\xff\x0e\xc8\xa0\xff\x0b\xb4\x8e\xff\x0d\x3b\x30\xff\x16\x0b\x10\xff\x21\x14\x2f\xff\x2d\x1c\x52\xff\x36\x22\x70\xff\x4a\x33\x9c\xff\x5d\x45\xc1\xff\x59\x42" \
+"\xc9\xff\x43\x2d\xaa\xff\x1e\x65\x7c\xff\x04\xb5\x8e\xff\x08\x50\x40\xff\x20\x22\x22\xff\x86\x85\x85\xff\x82\xb7\xb7\xb7\xff\x84\xb8\xb8\xb8\xff\x83\x0c\x0c\x0c\xff\x00\x0d\x0d\x0d\xff\x82\xe0\xe0\xe0\xff\x03\xdf\xdf\xdf\xff\x0d\x0d\x0d\xff\x0c\x0c\x0c\xff\x0c\x0c\x0c\xff\x83\xe0\xe0\xe0\xff\x01\xdf\xdf\xdf\xff\xdf\xdf\xdf\xff\x83\x0c\x0c\x0c\xff\x83\xfe\xfe\xfe\xff\x02\x52\x52\x52\xff\xa1\xa1\xa1\xff\x9e\x9e\x9e\xff\x87\x9c\x9c\x9c\xff\x12\x88\xa4\x9d\xff\x14\xb6\x92\xff\x12\xbb\x95\xff\x12\xca\xa1\xff\x0f\xb0\x8a\xff\x0f\x2c\x24\xff\x18\x0c\x17\xff\x26\x15\x3c\xff\x33\x20\x67\xff\x47\x30\x94\xff\x71\x57\xd5\xff\xa3\x87\xfc\xff\x92\x76\xfc\xff\x5b\x41\xda\xff\x2d\x4d\x90\xff\x06\xbc\x92\xff\x05\xaa\x84\xff\x55\xaf\x98\xff\xbc\xbc\xbc\xff\x82\xb7\xb7\xb7\xff\x84\xb8\xb8\xb8\xff\x83\x0c\x0c\x0c\xff\x83\xe0\xe0\xe0\xff\x03\xdf\xdf\xdf\xff\xdf\xdf\xdf\xff\x0c\x0c\x0c\xff\x0c\x0c\x0c\xff\x83\xe0\xe0\xe0\xff\x01\xdf\xdf\xdf\xff\xdf\xdf\xdf\xff\x83\x0c\x0c\x0c\xff\x83\xfe\xfe\xfe\xff\x00\x51\x51\x51\xff\x88\x9c\x9c" \
+"\x9c\xff\x13\x98\x97\x97\xff\x93\x9d\x9a\xff\x45\xb3\x99\xff\x17\xc9\xa1\xff\x17\xca\xa1\xff\x15\xca\xa3\xff\x11\x3c\x31\xff\x17\x0b\x19\xff\x26\x15\x44\xff\x34\x21\x6f\xff\x4f\x37\xa4\xff\x85\x6b\xf0\xff\xc1\xa3\xff\xff\xad\x8f\xff\xff\x66\x4a\xec\xff\x30\x49\x91\xff\x07\xca\x9f\xff\x06\xb7\x8e\xff\x49\xb8\x9e\xff\xbe\xbe\xbe\xff\x82\xb7\xb7\xb7\xff\x84\xb8\xb8\xb8\xff\x83\x0c\x0c\x0c\xff\x83\xe0\xe0\xe0\xff\x04\xdf\xdf\xdf\xff\xdf\xdf\xdf\xff\x0c\x0c\x0c\xff\x0c\x0c\x0c\xff\x0d\x0d\x0d\xff\x82\xe0\xe0\xe0\xff\x01\xdf\xdf\xdf\xff\x0d\x0d\x0d\xff\x83\x0c\x0c\x0c\xff\x83\xfe\xfe\xfe\xff\x00\x55\x55\x55\xff\x88\x9c\x9c\x9c\xff\x16\x7a\x79\x79\xff\x86\x7f\x7f\xff\xa6\xb6\xaf\xff\x23\xd0\xaa\xff\x1e\xdc\xb1\xff\x1d\xe3\xb8\xff\x15\x7e\x65\xff\x18\x0d\x17\xff\x24\x15\x3e\xff\x33\x1f\x6a\xff\x49\x32\x9e\xff\x6f\x54\xdf\xff\x95\x78\xfe\xff\x88\x69\xfe\xff\x5b\x3e\xdf\xff\x26\x76\x91\xff\x07\xcf\xa2\xff\x07\xb8\x90\xff\x4b\xb6\x9c\xff\xbf\xbf\xbf\xff\xb8\xb8\xb8\xff\xb7\xb7\xb7\xff\xb7\xb7\xb7\xff\x84\xb8\xb8\xb8\xff" \
+"\x83\x0c\x0c\x0c\xff\x00\x0d\x0d\x0d\xff\x82\xe0\xe0\xe0\xff\x01\xdf\xdf\xdf\xff\x0d\x0d\x0d\xff\x8b\x0c\x0c\x0c\xff\x83\xc3\x73\x00\xff\x05\x59\x59\x59\xff\xa2\xa2\xa2\xff\x9c\x9c\x9c\xff\x9c\x9c\x9c\xff\x9b\x9b\x9b\xff\x99\x99\x99\xff\x83\x9c\x9c\x9c\xff\x16\x93\x93\x93\xff\x6c\x65\x65\xff\xc1\xba\xb9\xff\x4d\xd8\xb7\xff\x25\xe2\xb8\xff\x24\xe1\xb6\xff\x1f\xd1\xa8\xff\x17\x2a\x28\xff\x21\x14\x32\xff\x2f\x1c\x5b\xff\x3e\x28\x88\xff\x50\x37\xb6\xff\x5f\x42\xdc\xff\x60\x40\xe8\xff\x46\x43\xb6\xff\x12\xd5\xb8\xff\x07\xd3\xa6\xff\x09\x85\x69\xff\x57\x5e\x5a\xff\xab\xa8\xa8\xff\xb8\xb8\xb8\xff\xb7\xb7\xb7\xff\xb7\xb7\xb7\xff\x84\xb8\xb8\xb8\xff\x95\x0c\x0c\x0c\xff\x83\xc3\x73\x00\xff\x20\x5c\x5c\x5c\xff\xac\xac\xac\xff\x9d\x9d\x9d\xff\x8f\x8f\x8f\xff\x4d\x48\x48\xff\x56\x50\x50\xff\x66\x62\x62\xff\x74\x71\x71\xff\x7f\x7c\x7c\xff\x8d\x8a\x8a\xff\x99\x99\x99\xff\x5d\x59\x59\xff\xc2\xba\xba\xff\xa2\xd7\xc9\xff\x2d\xdd\xb5\xff\x2b\xe9\xbf\xff\x29\xef\xc8\xff\x21\xb9\x99\xff\x1a\x28\x2e\xff\x24\x16\x3f\xff\x33\x20\x66" \
+"\xff\x3c\x24\x85\xff\x43\x2b\x9d\xff\x43\x40\xa8\xff\x1e\xbe\xb2\xff\x0a\xea\xba\xff\x07\xd6\xaa\xff\x0c\x53\x42\xff\x79\x72\x72\xff\xa9\xa6\xa6\xff\xb7\xb7\xb7\xff\xb8\xb8\xb8\xff\xb7\xb7\xb7\xff\x84\xb8\xb8\xb8\xff\x8b\x0c\x0c\x0c\xff\x00\x0d\x0d\x0d\xff\x82\xe0\xe0\xe0\xff\x01\xdf\xdf\xdf\xff\x0d\x0d\x0d\xff\x83\x0c\x0c\x0c\xff\x83\xc3\x73\x00\xff\x1d\x5c\x5c\x5c\xff\xb6\xb6\xb6\xff\xa5\xa5\xa5\xff\x65\x62\x62\xff\x43\x3b\x3b\xff\x77\x6f\x6f\xff\xa0\x99\x99\xff\x9f\x98\x98\xff\x91\x8a\x8a\xff\x91\x8f\x8f\xff\x9b\x9b\x9b\xff\x7e\x7d\x7d\xff\x92\x8b\x8b\xff\xd7\xd4\xd2\xff\x5f\xda\xbd\xff\x30\xe0\xb9\xff\x2e\xd7\xb0\xff\x2b\xde\xb7\xff\x25\xbe\x9c\xff\x1f\x71\x63\xff\x21\x48\x55\xff\x26\x4d\x63\xff\x26\x88\x90\xff\x19\xe4\xc7\xff\x10\xeb\xbc\xff\x0b\xdd\xae\xff\x08\xb5\x8f\xff\x25\x34\x2f\xff\x96\x8f\x8f\xff\xb2\xb1\xb1\xff\x82\xb7\xb7\xb7\xff\x84\xb8\xb8\xb8\xff\x83\x0c\x0c\x0c\xff\x00\x0d\x0d\x0d\xff\x82\xe0\xe0\xe0\xff\x03\xdf\xdf\xdf\xff\x0d\x0d\x0d\xff\x0c\x0c\x0c\xff\x0c\x0c\x0c\xff\x83\xe0\xe0\xe0\xff" \
+"\x01\xdf\xdf\xdf\xff\xdf\xdf\xdf\xff\x83\x0c\x0c\x0c\xff\x83\xe0\xb8\x7f\xff\x1d\x5c\x5c\x5c\xff\xb7\xb7\xb7\xff\xb3\xb3\xb3\xff\x98\x98\x98\xff\x4d\x49\x49\xff\x5e\x57\x57\xff\x77\x70\x70\xff\x80\x7c\x7c\xff\x93\x92\x92\xff\x9c\x9c\x9c\xff\x9c\x9c\x9c\xff\x9b\x9b\x9b\xff\x61\x5d\x5d\xff\xcb\xc4\xc4\xff\xca\xda\xd4\xff\x45\xd5\xb2\xff\x31\xd3\xae\xff\x2e\xd0\xab\xff\x2b\xdc\xb8\xff\x29\xe0\xb7\xff\x24\xd8\xae\xff\x20\xe0\xb7\xff\x1b\xea\xbe\xff\x15\xe5\xb7\xff\x10\xe3\xb5\xff\x0c\xd0\xa5\xff\x0d\x69\x55\xff\x70\x6a\x6a\xff\xa3\x9d\x9d\xff\xb8\xb7\xb7\xff\x82\xb7\xb7\xb7\xff\x84\xb8\xb8\xb8\xff\x83\x0c\x0c\x0c\xff\x83\xe0\xe0\xe0\xff\x03\xdf\xdf\xdf\xff\xdf\xdf\xdf\xff\x0c\x0c\x0c\xff\x0c\x0c\x0c\xff\x83\xe0\xe0\xe0\xff\x01\xdf\xdf\xdf\xff\xdf\xdf\xdf\xff\x83\x0c\x0c\x0c\xff\x0a\xfe\xfe\xfe\xff\xfd\xfd\xfd\xff\xfd\xfd\xfd\xff\xfe\xfe\xfe\xff\x59\x59\x59\xff\xae\xae\xae\xff\xb3\xb3\xb3\xff\xb2\xb2\xb2\xff\xa2\xa2\xa2\xff\x90\x90\x90\xff\x97\x97\x97\xff\x84\x9c\x9c\x9c\xff\x10\x92\x92\x92\xff\x77\x73\x73\xff\xe0" \
+"\xd9\xd9\xff\xc7\xdd\xd6\xff\x4e\xce\xaf\xff\x33\xd8\xb4\xff\x2f\xd4\xb0\xff\x2a\xd4\xad\xff\x25\xda\xb1\xff\x21\xd0\xa8\xff\x1b\xda\xb2\xff\x15\xd7\xaf\xff\x0f\xc3\x9c\xff\x0d\x84\x6a\xff\x4f\x55\x52\xff\x9d\x96\x96\xff\xb1\xae\xae\xff\x83\xb7\xb7\xb7\xff\x84\xb8\xb8\xb8\xff\x83\x0c\x0c\x0c\xff\x83\xe0\xe0\xe0\xff\x04\xdf\xdf\xdf\xff\xdf\xdf\xdf\xff\x0c\x0c\x0c\xff\x0c\x0c\x0c\xff\x0d\x0d\x0d\xff\x82\xe0\xe0\xe0\xff\x01\xdf\xdf\xdf\xff\x0d\x0d\x0d\xff\x83\x0c\x0c\x0c\xff\x1f\xfe\xfe\xfe\xff\xfd\xfd\xfd\xff\xfd\xfd\xfd\xff\xfe\xfe\xfe\xff\x4f\x4f\x4f\xff\xa3\xa3\xa3\xff\xb4\xb4\xb4\xff\xb8\xb8\xb8\xff\xb4\xb4\xb4\xff\xa7\xa7\xa7\xff\x9e\x9e\x9e\xff\x9c\x9c\x9c\xff\x9c\x9c\x9c\xff\x9b\x9b\x9b\xff\x96\x96\x96\xff\x85\x83\x83\xff\x95\x94\x94\xff\x89\x89\x89\xff\x85\x80\x80\xff\xe8\xe0\xe0\xff\xd8\xe4\xdf\xff\x76\xdd\xc6\xff\x37\xcd\xab\xff\x2d\xcc\xa8\xff\x27\xd3\xae\xff\x21\xc7\xa1\xff\x1a\xbe\x97\xff\x13\xa6\x84\xff\x18\x73\x5f\xff\x5d\x61\x5f\xff\x9c\x95\x95\xff\xac\xa8\xa8\xff\x84\xb7\xb7\xb7\xff\x84\xb8\xb8" \
+"\xb8\xff\x83\x0c\x0c\x0c\xff\x00\x0d\x0d\x0d\xff\x82\xe0\xe0\xe0\xff\x01\xdf\xdf\xdf\xff\x0d\x0d\x0d\xff\x8b\x0c\x0c\x0c\xff\x83\xfe\xfe\xfe\xff\x01\x51\x51\x51\xff\xb0\xb0\xb0\xff\x82\xb8\xb8\xb8\xff\x16\xb6\xb6\xb6\xff\xaf\xaf\xaf\xff\x90\x90\x90\xff\x68\x65\x65\xff\x5a\x55\x55\xff\x63\x5d\x5d\xff\x88\x81\x81\xff\x9a\x9a\x9a\xff\x9c\x9c\x9c\xff\x8e\x8d\x8d\xff\x90\x8d\x8d\xff\xdf\xd8\xd8\xff\xee\xe7\xe7\xff\xcc\xda\xd4\xff\x8a\xcb\xbc\xff\x5b\xb5\x9f\xff\x48\xa0\x8b\xff\x4b\x8e\x7e\xff\x6b\x84\x7d\xff\x98\x92\x91\xff\xa5\x9e\x9e\xff\xae\xab\xab\xff\xb6\xb6\xb6\xff\x84\xb7\xb7\xb7\xff\x84\xb8\xb8\xb8\xff\x95\x0c\x0c\x0c\xff\x83\xc3\x73\x00\xff\x19\x59\x59\x59\xff\xb7\xb7\xb7\xff\xb8\xb8\xb8\xff\xb8\xb8\xb8\xff\xb5\xb5\xb5\xff\xae\xae\xae\xff\x8f\x8e\x8e\xff\x39\x32\x32\xff\x5f\x58\x58\xff\x91\x8a\x8a\xff\x98\x92\x92\xff\x9d\x9c\x9c\xff\xa7\xa7\xa7\xff\xa7\xa7\xa7\xff\xaa\xaa\xaa\xff\xad\xac\xac\xff\x9a\x9a\x9a\xff\xbf\xbb\xbb\xff\xd9\xd3\xd3\xff\xe2\xda\xda\xff\xd7\xcf\xcf\xff\xca\xc3\xc3\xff\xbf\xb8\xb8\xff" \
+"\xb8\xb1\xb1\xff\xb4\xaf\xaf\xff\xb5\xb3\xb3\xff\x86\xb7\xb7\xb7\xff\x84\xb8\xb8\xb8\xff\x8b\x0c\x0c\x0c\xff\x00\x0d\x0d\x0d\xff\x82\xe0\xe0\xe0\xff\x01\xdf\xdf\xdf\xff\x0d\x0d\x0d\xff\x83\x0c\x0c\x0c\xff\x83\xc3\x73\x00\xff\x17\x5c\x5c\x5c\xff\xb8\xb8\xb8\xff\xb7\xb7\xb7\xff\xb1\xb1\xb1\xff\xa4\xa4\xa4\xff\xa8\xa8\xa8\xff\x71\x6e\x6e\xff\x4a\x42\x42\xff\x7f\x78\x78\xff\x91\x8a\x8a\xff\xa3\xa1\xa1\xff\xb8\xb8\xb8\xff\xb8\xb8\xb8\xff\xb7\xb7\xb7\xff\x8b\x89\x89\xff\xa1\x9e\x9e\xff\xb8\xb8\xb8\xff\xb8\xb8\xb8\xff\xab\xab\xab\xff\xb8\xb7\xb7\xff\xc1\xbe\xbe\xff\xc3\xc1\xc1\xff\xbd\xbb\xbb\xff\xb9\xb8\xb8\xff\x89\xb7\xb7\xb7\xff\x83\xb8\xb8\xb8\xff\x83\x0c\x0c\x0c\xff\x00\x0d\x0d\x0d\xff\x82\xe0\xe0\xe0\xff\x03\xdf\xdf\xdf\xff\x0d\x0d\x0d\xff\x0c\x0c\x0c\xff\x0c\x0c\x0c\xff\x83\xe0\xe0\xe0\xff\x01\xdf\xdf\xdf\xff\xdf\xdf\xdf\xff\x83\x0c\x0c\x0c\xff\x83\xc3\x73\x00\xff\x12\x5c\x5c\x5c\xff\xb4\xb4\xb4\xff\xac\xac\xac\xff\x9f\x9f\x9f\xff\x9c\x9c\x9c\xff\xae\xae\xae\xff\xb3\xb3\xb3\xff\x84\x82\x82\xff\x7d\x7a\x7a\xff" \
+"\x98\x97\x97\xff\xb6\xb6\xb6\xff\xb8\xb8\xb8\xff\xb3\xb3\xb3\xff\x73\x71\x71\xff\x6a\x63\x63\xff\xaf\xae\xae\xff\xb8\xb8\xb8\xff\xb7\xb7\xb7\xff\x97\x95\x95\xff\x8e\xb7\xb7\xb7\xff\x83\xb6\xb6\xb6\xff\x83\x0c\x0c\x0c\xff\x83\xe0\xe0\xe0\xff\x03\xdf\xdf\xdf\xff\xdf\xdf\xdf\xff\x0c\x0c\x0c\xff\x0c\x0c\x0c\xff\x83\xe0\xe0\xe0\xff\x01\xdf\xdf\xdf\xff\xdf\xdf\xdf\xff\x83\x0c\x0c\x0c\xff\x83\xe0\xb8\x7f\xff\x13\x58\x58\x58\xff\xa3\xa3\xa3\xff\x9c\x9c\x9c\xff\x9c\x9c\x9c\xff\xa2\xa2\xa2\xff\xb4\xb4\xb4\xff\xb8\xb8\xb8\xff\xb5\xb5\xb5\xff\xa4\xa4\xa4\xff\xa3\xa3\xa3\xff\xb6\xb6\xb6\xff\xa0\x9f\x9f\xff\x4f\x4a\x4a\xff\x56\x4e\x4e\xff\x95\x8f\x8f\xff\xb5\xb5\xb5\xff\xb8\xb8\xb8\xff\x8e\x8d\x8d\xff\x78\x72\x72\xff\xb6\xb5\xb5\xff\x8c\xb7\xb7\xb7\xff\x84\xb8\xb8\xb8\xff\x83\x0c\x0c\x0c\xff\x83\xe0\xe0\xe0\xff\x04\xdf\xdf\xdf\xff\xdf\xdf\xdf\xff\x0c\x0c\x0c\xff\x0c\x0c\x0c\xff\x0d\x0d\x0d\xff\x82\xe0\xe0\xe0\xff\x01\xdf\xdf\xdf\xff\x0d\x0d\x0d\xff\x83\x0c\x0c\x0c\xff\x17\xfe\xfe\xfe\xff\xfd\xfd\xfd\xff\xfd\xfd\xfd\xff\xfe" \
+"\xfe\xfe\xff\x50\x50\x50\xff\x9c\x9c\x9c\xff\x9c\x9c\x9c\xff\x9d\x9d\x9d\xff\xac\xac\xac\xff\xb8\xb8\xb8\xff\xb6\xb6\xb6\xff\xa9\xa9\xa9\xff\x9c\x9c\x9c\xff\xa4\xa4\xa4\xff\xb2\xb2\xb2\xff\x3b\x35\x35\xff\x58\x51\x51\xff\xa3\x9c\x9c\xff\x9a\x97\x97\xff\xb8\xb8\xb8\xff\xaf\xae\xae\xff\x47\x42\x42\xff\x86\x80\x80\xff\xb4\xb4\xb4\xff\x8c\xb7\xb7\xb7\xff\x84\xb8\xb8\xb8\xff\x83\x0c\x0c\x0c\xff\x00\x0d\x0d\x0d\xff\x82\xe0\xe0\xe0\xff\x01\xdf\xdf\xdf\xff\x0d\x0d\x0d\xff\x8b\x0c\x0c\x0c\xff\x83\xfe\xfe\xfe\xff\x13\x52\x52\x52\xff\x9f\x9f\x9f\xff\xa0\xa0\xa0\xff\xa9\xa9\xa9\xff\xb6\xb6\xb6\xff\xb7\xb7\xb7\xff\xac\xac\xac\xff\x9d\x9d\x9d\xff\x9c\x9c\x9c\xff\xa6\xa6\xa6\xff\xa6\xa6\xa6\xff\x38\x32\x32\xff\x72\x6a\x6a\xff\x86\x80\x80\xff\xaf\xaf\xaf\xff\xb7\xb7\xb7\xff\x5d\x5a\x5a\xff\x4d\x46\x46\xff\x9a\x93\x93\xff\xb4\xb4\xb4\xff\x8b\xb7\xb7\xb7\xff\x85\xb8\xb8\xb8\xff\x95\x0c\x0c\x0c\xff\x83\xfe\xfe\xfe\xff\x13\x5a\x5a\x5a\xff\xb3\xb3\xb3\xff\xb4\xb4\xb4\xff\xb7\xb7\xb7\xff\xb8\xb8\xb8\xff\xb5\xb5\xb5\xff\xa2\xa2\xa2" \
+"\xff\x9c\x9c\x9c\xff\x9d\x9d\x9d\xff\xad\xad\xad\xff\xb8\xb8\xb8\xff\x91\x8f\x8f\xff\x8e\x8b\x8b\xff\xad\xac\xac\xff\xb8\xb8\xb8\xff\x9a\x99\x99\xff\x33\x2c\x2c\xff\x84\x7d\x7d\xff\x9e\x99\x99\xff\xb6\xb6\xb6\xff\x8b\xb7\xb7\xb7\xff\x85\xb8\xb8\xb8\xff\x8b\x0c\x0c\x0c\xff\x00\x0d\x0d\x0d\xff\x82\xe0\xe0\xe0\xff\x01\xdf\xdf\xdf\xff\x0d\x0d\x0d\xff\x83\x0c\x0c\x0c\xff\x83\xc3\x73\x00\xff\x00\x5c\x5c\x5c\xff\x83\xb8\xb8\xb8\xff\x04\xb5\xb5\xb5\xff\xa3\xa3\xa3\xff\x9e\x9e\x9e\xff\xa7\xa7\xa7\xff\xb6\xb6\xb6\xff\x83\xb8\xb8\xb8\xff\x04\xb7\xb7\xb7\xff\x92\x90\x90\xff\x43\x3b\x3b\xff\x7b\x74\x74\xff\xa0\x9d\x9d\xff\x89\xb7\xb7\xb7\xff\x01\xb6\xb6\xb6\xff\xb7\xb7\xb7\xff\x86\xb8\xb8\xb8\xff\x83\x0c\x0c\x0c\xff\x00\x0d\x0d\x0d\xff\x82\xe0\xe0\xe0\xff\x03\xdf\xdf\xdf\xff\x0d\x0d\x0d\xff\x0c\x0c\x0c\xff\x0c\x0c\x0c\xff\x83\xe0\xe0\xe0\xff\x01\xdf\xdf\xdf\xff\xdf\xdf\xdf\xff\x83\x0c\x0c\x0c\xff\x83\xc3\x73\x00\xff\x00\x5c\x5c\x5c\xff\x83\xb8\xb8\xb8\xff\x03\xb7\xb7\xb7\xff\xb3\xb3\xb3\xff\xb2\xb2\xb2\xff\xb7\xb7\xb7\xff" \
+"\x83\xb8\xb8\xb8\xff\x04\xb7\xb7\xb7\xff\xb7\xb7\xb7\xff\xb6\xb6\xb6\xff\x91\x8f\x8f\xff\xa2\xa0\xa0\xff\x8b\xb7\xb7\xb7\xff\x87\xb8\xb8\xb8\xff\x83\x0c\x0c\x0c\xff\x83\xe0\xe0\xe0\xff\x03\xdf\xdf\xdf\xff\xdf\xdf\xdf\xff\x0c\x0c\x0c\xff\x0c\x0c\x0c\xff\x83\xe0\xe0\xe0\xff\x01\xdf\xdf\xdf\xff\xdf\xdf\xdf\xff\x83\x0c\x0c\x0c\xff\x83\xc3\x73\x00\xff\x00\x5c\x5c\x5c\xff\x89\xb8\xb8\xb8\xff\x01\xb7\xb7\xb7\xff\xb8\xb8\xb8\xff\x8f\xb7\xb7\xb7\xff\x88\xb8\xb8\xb8\xff\x83\x0c\x0c\x0c\xff\x83\xe0\xe0\xe0\xff\x04\xdf\xdf\xdf\xff\xdf\xdf\xdf\xff\x0c\x0c\x0c\xff\x0c\x0c\x0c\xff\x0d\x0d\x0d\xff\x82\xe0\xe0\xe0\xff\x01\xdf\xdf\xdf\xff\x0d\x0d\x0d\xff\xb1\x0c\x0c\x0c\xff\x00\x0d\x0d\x0d\xff\x82\xe0\xe0\xe0\xff\x01\xdf\xdf\xdf\xff\x0d\x0d\x0d\xff\xff\x0c\x0c\x0c\xff\x81\x0c\x0c\x0c\xff\x00\x0d\x0d\x0d\xff\x82\xe0\xe0\xe0\xff\x01\xdf\xdf\xdf\xff\x0d\x0d\x0d\xff\x83\x0c\x0c\x0c\xff\x83\xfe\xfe\xfe\xff\x00\x5c\x5c\x5c\xff\x85\xb8\xb8\xb8\xff\x00\xb7\xb7\xb7\xff\x83\xb6\xb6\xb6\xff\x8d\xb8\xb8\xb8\xff\x02\xb7\xb7\xb7\xff\xb7\xb7" \
+"\xb7\xff\xb8\xb8\xb8\xff\x82\xb7\xb7\xb7\xff\x85\xb8\xb8\xb8\xff\x83\x0c\x0c\x0c\xff\x00\x0d\x0d\x0d\xff\x82\xe0\xe0\xe0\xff\x03\xdf\xdf\xdf\xff\x0d\x0d\x0d\xff\x0c\x0c\x0c\xff\x0c\x0c\x0c\xff\x83\xe0\xe0\xe0\xff\x01\xdf\xdf\xdf\xff\xdf\xdf\xdf\xff\x83\x0c\x0c\x0c\xff\x83\xfe\xfe\xfe\xff\x00\x5c\x5c\x5c\xff\x83\xb8\xb8\xb8\xff\x09\xb6\xb6\xb6\xff\xb2\xb2\xb2\xff\xae\xae\xae\xff\xa9\xa9\xa9\xff\xa6\xa6\xa6\xff\xa6\xa6\xa6\xff\xa8\xa8\xa8\xff\xab\xab\xab\xff\xb2\xb2\xb2\xff\xb6\xb6\xb6\xff\x89\xb8\xb8\xb8\xff\x86\xb7\xb7\xb7\xff\x85\xb8\xb8\xb8\xff\x83\x0c\x0c\x0c\xff\x83\xe0\xe0\xe0\xff\x03\xdf\xdf\xdf\xff\xdf\xdf\xdf\xff\x0c\x0c\x0c\xff\x0c\x0c\x0c\xff\x83\xe0\xe0\xe0\xff\x01\xdf\xdf\xdf\xff\xdf\xdf\xdf\xff\x83\x0c\x0c\x0c\xff\x83\xe0\xb8\x7f\xff\x06\x5c\x5c\x5c\xff\xb8\xb8\xb8\xff\xb8\xb8\xb8\xff\xb7\xb7\xb7\xff\xb1\xb1\xb1\xff\xa8\xa8\xa8\xff\xa0\xa0\xa0\xff\x85\x9c\x9c\x9c\xff\x05\x9e\x9e\x9e\xff\xa4\xa4\xa4\xff\xb0\xb0\xb0\xff\xb9\xb9\xb9\xff\xba\xba\xba\xff\xb9\xb9\xb9\xff\x86\xb8\xb8\xb8\xff\x85\xb7\xb7" \
+"\xb7\xff\x85\xb8\xb8\xb8\xff\x83\x0c\x0c\x0c\xff\x83\xe0\xe0\xe0\xff\x04\xdf\xdf\xdf\xff\xdf\xdf\xdf\xff\x0c\x0c\x0c\xff\x0c\x0c\x0c\xff\x0d\x0d\x0d\xff\x82\xe0\xe0\xe0\xff\x01\xdf\xdf\xdf\xff\x0d\x0d\x0d\xff\x83\x0c\x0c\x0c\xff\x83\xc3\x73\x00\xff\x04\x5c\x5c\x5c\xff\xb8\xb8\xb8\xff\xb6\xb6\xb6\xff\xae\xae\xae\xff\xa1\xa1\xa1\xff\x87\x9c\x9c\x9c\xff\x09\x9d\x9d\x9d\xff\xa0\xa0\xa0\xff\xa3\xa3\xa3\xff\xa9\xa9\xa9\xff\x9c\x9b\x9c\xff\x8c\x8a\x8b\xff\x7f\x7e\x7e\xff\x8c\x8a\x8b\xff\xa1\xa1\xa1\xff\xb5\xb5\xb5\xff\x83\xb8\xb8\xb8\xff\x84\xb7\xb7\xb7\xff\x85\xb8\xb8\xb8\xff\x83\x0c\x0c\x0c\xff\x00\x0d\x0d\x0d\xff\x82\xe0\xe0\xe0\xff\x01\xdf\xdf\xdf\xff\x0d\x0d\x0d\xff\x8b\x0c\x0c\x0c\xff\x83\xc3\x73\x00\xff\x03\x5c\x5c\x5c\xff\xb7\xb7\xb7\xff\xac\xac\xac\xff\x9f\x9f\x9f\xff\x87\x9c\x9c\x9c\xff\x0e\x9d\x9d\x9d\xff\xa0\xa0\xa0\xff\x9f\x9f\x9f\xff\x6e\x6c\x6c\xff\x36\x31\x32\xff\x21\x1b\x1c\xff\x20\x1a\x1b\xff\x1f\x19\x1a\xff\x1e\x19\x1a\xff\x24\x1f\x20\xff\x42\x3e\x3f\xff\x84\x83\x83\xff\xb2\xb2\xb2\xff\xb8\xb8\xb8" \
+"\xff\xb8\xb8\xb8\xff\x84\xb7\xb7\xb7\xff\x85\xb8\xb8\xb8\xff\x95\x0c\x0c\x0c\xff\x83\xe0\xb8\x7f\xff\x02\x5c\x5c\x5c\xff\xb1\xb1\xb1\xff\xa0\xa0\xa0\xff\x88\x9c\x9c\x9c\xff\x0d\x9d\x9d\x9d\xff\x96\x96\x96\xff\x42\x3e\x3f\xff\x21\x1b\x1c\xff\x1e\x22\x20\xff\x16\x3e\x34\xff\x10\x4f\x41\xff\x0e\x53\x44\xff\x10\x41\x35\xff\x14\x1f\x1c\xff\x19\x14\x15\xff\x1e\x19\x1a\xff\x45\x41\x42\xff\xa2\xa1\xa1\xff\x85\xb7\xb7\xb7\xff\x85\xb8\xb8\xb8\xff\x8b\x0c\x0c\x0c\xff\x00\x0d\x0d\x0d\xff\x82\xe0\xe0\xe0\xff\x01\xdf\xdf\xdf\xff\x0d\x0d\x0d\xff\x83\x0c\x0c\x0c\xff\x83\xfe\xfe\xfe\xff\x01\x5a\x5a\x5a\xff\xa5\xa5\xa5\xff\x89\x9c\x9c\x9c\xff\x0e\x96\x96\x96\xff\x41\x3d\x3e\xff\x20\x1d\x1e\xff\x14\x4d\x3f\xff\x07\x98\x78\xff\x05\xaf\x8a\xff\x05\xbc\x94\xff\x05\xbb\x92\xff\x05\xba\x92\xff\x05\xa0\x7d\xff\x09\x62\x4d\xff\x10\x21\x1c\xff\x19\x14\x15\xff\x2f\x2a\x2b\xff\x99\x98\x99\xff\x84\xb7\xb7\xb7\xff\x85\xb8\xb8\xb8\xff\x83\x0c\x0c\x0c\xff\x00\x0d\x0d\x0d\xff\x82\xe0\xe0\xe0\xff\x02\xdf\xdf\xdf\xff\x0d\x0d\x0d\xff\x0c\x0c\x0c" \
+"\xff"};
+
+/* these are not the monkeys you are looking for */
+int monkeyo= 4;
+int monkeynv= 271;
+int monkeynf= 250;
+signed char monkeyv[271][3]= {
+{-71,21,98},{-63,12,88},{-57,7,74},{-82,-3,79},{-82,4,92},
+{-82,17,100},{-92,21,102},{-101,12,95},{-107,7,83},
+{-117,31,84},{-109,31,95},{-96,31,102},{-92,42,102},
+{-101,50,95},{-107,56,83},{-82,66,79},{-82,58,92},
+{-82,46,100},{-71,42,98},{-63,50,88},{-57,56,74},
+{-47,31,72},{-55,31,86},{-67,31,97},{-66,31,99},
+{-70,43,100},{-82,48,103},{-93,43,105},{-98,31,105},
+{-93,20,105},{-82,31,106},{-82,15,103},{-70,20,100},
+{-127,55,95},{-127,45,105},{-127,-87,94},{-127,-41,100},
+{-127,-24,102},{-127,-99,92},{-127,52,77},{-127,73,73},
+{-127,115,-70},{-127,72,-109},{-127,9,-106},{-127,-49,-45},
+{-101,-24,72},{-87,-56,73},{-82,-89,73},{-80,-114,68},
+{-85,-121,67},{-104,-124,71},{-127,-126,74},{-71,-18,68},
+{-46,-5,69},{-21,19,57},{-17,55,76},{-36,62,80},
+{-64,77,88},{-86,97,94},{-107,92,97},{-119,63,96},
+{-106,53,99},{-111,39,98},{-101,12,95},{-79,2,90},
+{-64,8,86},{-47,24,83},{-45,38,83},{-50,48,85},
+{-72,56,92},{-95,60,97},{-127,-98,94},{-113,-92,94},
+{-112,-107,91},{-119,-113,89},{-127,-114,88},{-127,-25,96},
+{-127,-18,95},{-114,-19,95},{-111,-29,96},{-116,-37,95},
+{-76,-6,86},{-48,7,80},{-34,26,77},{-32,48,84},
+{-39,53,93},{-71,70,102},{-87,82,107},{-101,79,109},
+{-114,55,108},{-111,-13,104},{-100,-57,91},{-95,-90,88},
+{-93,-105,85},{-97,-117,81},{-106,-119,81},{-127,-121,82},
+{-127,6,93},{-127,27,98},{-85,61,95},{-106,18,96},
+{-110,27,97},{-112,-88,94},{-117,-57,96},{-127,-57,96},
+{-127,-42,95},{-115,-35,100},{-110,-29,102},{-113,-17,100},
+{-122,-16,100},{-127,-26,106},{-121,-19,104},{-115,-20,104},
+{-113,-29,106},{-117,-32,103},{-127,-37,103},{-94,-40,71},
+{-106,-31,91},{-104,-40,91},{-97,-32,71},{-127,-112,88},
+{-121,-111,88},{-115,-105,91},{-115,-95,93},{-127,-100,84},
+{-115,-96,85},{-115,-104,82},{-121,-109,81},{-127,-110,81},
+{-105,28,100},{-103,20,99},{-84,55,97},{-92,54,99},
+{-73,51,99},{-55,45,89},{-52,37,88},{-53,25,87},
+{-66,13,92},{-79,8,95},{-98,14,100},{-104,38,100},
+{-100,48,100},{-97,46,97},{-102,38,97},{-96,16,97},
+{-79,11,93},{-68,15,90},{-57,27,86},{-56,36,86},
+{-59,43,87},{-74,50,96},{-91,51,98},{-84,52,96},
+{-101,22,96},{-102,29,96},{-113,59,78},{-102,85,79},
+{-84,88,76},{-65,71,71},{-40,58,63},{-25,52,59},
+{-28,21,48},{-50,0,53},{-71,-12,60},{-127,115,37},
+{-127,126,-10},{-127,-25,-86},{-127,-59,24},{-127,-125,59},
+{-127,-103,44},{-127,-73,41},{-127,-62,36},{-18,30,7},
+{-17,41,-6},{-28,34,-56},{-68,56,-90},{-33,-6,9},
+{-51,-16,-21},{-45,-1,-55},{-84,7,-85},{-97,-45,52},
+{-104,-53,33},{-90,-91,49},{-95,-64,50},{-85,-117,51},
+{-109,-97,47},{-111,-69,46},{-106,-121,56},{-99,-36,55},
+{-100,-29,60},{-101,-22,64},{-100,-50,21},{-89,-40,-34},
+{-83,-19,-69},{-69,111,-49},{-69,119,-9},{-69,109,30},
+{-68,67,55},{-34,52,43},{-46,58,36},{-45,90,7},
+{-25,72,16},{-25,79,-15},{-45,96,-25},{-45,87,-57},
+{-25,69,-46},{-48,42,-75},{-65,3,-70},{-22,42,-26},
+{-75,-22,19},{-72,-25,-27},{-13,52,-30},{-28,-18,-16},
+{6,-13,-42},{37,7,-55},{46,41,-54},{31,65,-54},
+{4,61,-40},{3,53,-37},{25,56,-50},{35,37,-52},
+{28,10,-52},{5,-5,-39},{-21,-9,-17},{-9,46,-28},
+{-6,39,-37},{-14,-3,-27},{6,0,-47},{25,12,-57},
+{31,32,-57},{23,46,-56},{4,44,-46},{-19,37,-27},
+{-20,22,-35},{-30,12,-35},{-22,11,-35},{-19,2,-35},
+{-23,-2,-35},{-34,0,-9},{-35,-3,-22},{-35,5,-24},
+{-25,26,-27},{-13,31,-34},{-13,30,-41},{-23,-2,-41},
+{-18,2,-41},{-21,10,-41},{-29,12,-41},{-19,22,-41},
+{6,42,-53},{25,44,-62},{34,31,-63},{28,11,-62},
+{7,0,-54},{-14,-2,-34},{-5,37,-44},{-13,14,-42},
+{-7,8,-43},{1,16,-47},{-4,22,-45},{3,30,-48},
+{8,24,-49},{15,27,-50},{12,35,-50},{4,56,-62},
+{33,60,-70},{48,38,-64},{41,7,-68},{6,-11,-63},
+{-26,-16,-42},{-17,49,-49},
+};
+
+signed char monkeyf[250][4]= {
+{27,4,5,26}, {25,4,5,24}, {3,6,5,4}, {1,6,5,2}, {5,6,7,4},
+{3,6,7,2}, {5,8,7,6}, {3,8,7,4}, {7,8,9,6},
+{5,8,9,4}, {7,10,9,8}, {5,10,9,6}, {9,10,11,8},
+{7,10,11,6}, {9,12,11,10}, {7,12,11,8}, {11,6,13,12},
+{5,4,13,12}, {3,-2,13,12}, {-3,-4,13,12}, {-5,-10,13,12},
+{-11,-12,14,12}, {-13,-18,14,13}, {-19,4,5,13}, {10,12,4,4},
+{10,11,9,9}, {8,7,9,9}, {7,5,6,6}, {6,3,4,4},
+{5,1,2,2}, {4,-1,0,0}, {3,-3,-2,-2}, {22,67,68,23},
+{20,65,66,21}, {18,63,64,19}, {16,61,62,17}, {14,59,60,15},
+{12,19,48,57}, {18,19,48,47}, {18,19,48,47}, {18,19,48,47},
+{18,19,48,47}, {18,19,48,47}, {18,19,48,47}, {18,19,48,47},
+{18,19,48,47}, {18,-9,-8,47}, {18,27,45,46}, {26,55,43,44},
+{24,41,42,54}, {22,39,40,23}, {20,37,38,21}, {18,35,36,19},
+{16,33,34,17}, {14,31,32,15}, {12,39,30,13}, {11,48,45,38},
+{8,36,-19,9}, {8,-20,44,47}, {42,45,46,43}, {18,19,40,39},
+{16,17,38,37}, {14,15,36,35}, {32,44,43,33}, {12,33,32,42},
+{19,44,43,42}, {40,41,42,-27}, {8,9,39,-28}, {15,43,42,16},
+{13,43,42,14}, {11,43,42,12}, {9,-30,42,10}, {37,12,38,-32},
+{-33,37,45,46}, {-33,40,41,39}, {38,40,41,37}, {36,40,41,35},
+{34,40,41,33}, {36,39,38,37}, {35,40,39,38}, {1,2,14,21},
+{1,2,40,13}, {1,2,40,39}, {1,24,12,39}, {-34,36,38,11},
+{35,38,36,37}, {-37,8,35,37}, {-11,-12,-45,40}, {-11,-12,39,38},
+{-11,-12,37,36}, {-11,-12,35,34}, {33,34,40,41}, {33,34,38,39},
+{33,34,36,37}, {33,-52,34,35}, {33,37,36,34}, {33,35,34,34},
+{8,7,37,36}, {-32,7,35,46}, {-34,-33,45,46}, {4,-33,43,34},
+{-34,-33,41,42}, {-34,-33,39,40}, {-34,-33,37,38}, {-34,-33,35,36},
+{-34,-33,33,34}, {-34,-33,31,32}, {-34,-4,28,30}, {-5,-34,28,27},
+{-35,-44,36,27}, {26,35,36,45}, {24,25,44,45}, {25,23,44,42},
+{25,24,41,40}, {25,24,39,38}, {25,24,37,36}, {25,24,35,34},
+{25,24,33,32}, {25,24,31,30}, {15,24,29,38}, {25,24,27,26},
+{23,12,37,26}, {11,12,35,36}, {-86,-59,36,-80}, {-60,-61,36,35},
+{-62,-63,36,35}, {-64,-65,36,35}, {-66,-67,36,35}, {-68,-69,36,35},
+{-70,-71,36,35}, {-72,-73,36,35}, {-74,-75,36,35}, {42,43,53,58},
+{40,41,57,56}, {38,39,55,57}, {-81,-80,37,56}, {-83,-82,55,52},
+{-85,-84,51,49}, {-87,-86,48,49}, {47,50,51,48}, {46,48,51,49},
+{43,46,49,44}, {-92,-91,45,42}, {-23,49,50,-20}, {-94,40,48,-24},
+{-96,-22,48,49}, {-97,48,21,-90}, {-100,36,50,23}, {22,49,48,-100},
+{-101,47,46,22}, {21,45,35,25}, {33,34,44,41}, {13,14,28,24},
+{-107,26,30,-106}, {14,46,45,15}, {14,44,43,-110}, {-111,42,23,-110},
+{6,7,45,46}, {45,44,47,46}, {45,46,47,48}, {47,46,49,48},
+{17,49,47,48}, {17,36,46,48}, {35,36,44,45}, {35,36,40,43},
+{35,36,38,39}, {-4,-3,37,35}, {-123,34,33,1}, {-9,-8,-7,-6},
+{-10,-7,32,-125}, {-127,-11,-126,-126}, {-7,-6,5,31}, {4,5,33,30},
+{4,39,33,32}, {4,35,32,38}, {20,21,39,38}, {4,37,38,5},
+{-11,-10,36,3}, {-11,15,14,35}, {13,16,34,34}, {-13,14,13,13},
+{-3,1,30,29}, {-3,28,29,1}, {-2,31,28,-1}, {12,13,27,30},
+{-2,26,12,12}, {35,29,42,36}, {34,35,36,33}, {32,35,36,31},
+{30,35,36,29}, {28,35,36,27}, {26,35,36,25}, {34,39,38,35},
+{32,39,38,33}, {30,39,38,31}, {28,39,38,29}, {26,39,38,27},
+{25,31,32,38}, {-18,-17,45,44}, {-18,17,28,44}, {-24,-20,42,-23},
+{11,35,27,14}, {25,28,39,41}, {37,41,40,38}, {34,40,36,35},
+{32,40,39,33}, {30,39,31,40}, {21,29,39,22}, {-31,37,28,4},
+{-32,33,35,36}, {32,33,34,34}, {18,35,36,48}, {34,25,40,35},
+{24,25,38,39}, {24,25,36,37}, {24,25,34,35}, {24,25,32,33},
+{24,13,41,31}, {17,11,41,35}, {15,16,34,35}, {13,14,34,35},
+{11,12,34,35}, {9,10,34,35}, {7,8,34,35}, {26,25,37,36},
+{35,36,37,38}, {37,36,39,38}, {37,38,39,40}, {25,31,36,39},
+{18,34,35,30}, {17,22,30,33}, {19,29,21,20}, {16,26,29,17},
+{24,29,28,25}, {22,31,28,23}, {20,31,30,21}, {18,31,30,19},
+{16,30,17,17}, {-21,-22,35,34}, {-21,-22,33,32}, {-21,-22,31,30},
+{-21,-22,29,28}, {-21,-22,27,26}, {-28,-22,25,31}, {24,28,29,30},
+{23,24,26,27}, {23,24,25,25}, {-69,-35,-32,27}, {-70,26,25,-66},
+{-68,-67,24,-33},
+};
diff --git a/source/blender/src/cre/license.jpeg.c b/source/blender/src/cre/license.jpeg.c
new file mode 100644
index 00000000000..ffbc87cd495
--- /dev/null
+++ b/source/blender/src/cre/license.jpeg.c
@@ -0,0 +1,34 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 datatoc_tonize= 0;
+char datatoc_ton[]= {0};
diff --git a/source/blender/src/cre/license_key.c b/source/blender/src/cre/license_key.c
new file mode 100644
index 00000000000..a74c74e64f2
--- /dev/null
+++ b/source/blender/src/cre/license_key.c
@@ -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 *****
+ */
+
+#include "license_key.h"
+#include "keyed_functions.h"
+#include "BKE_utildefines.h"
+#include "BIF_screen.h" // splash
+#include "BIF_toolbox.h"
+#include "blenkey.h"
+#include <stdio.h>
+#include <string.h>
+#include "BLO_readfile.h"
+#include "BLO_keyStore.h"
+
+int LICENSE_KEY_VALID = FALSE;
+int I_AM_PUBLISHER = FALSE;
+
+static UserStruct User;
+
+// Python stuff
+
+#include "Python.h"
+#include "marshal.h"
+#include "compile.h" /* to give us PyCodeObject */
+#include "eval.h" /* prototype for PyEval_EvalCode */
+
+
+Fptr g_functab[PYKEY_TABLEN];
+Fptr g_ptrtab[PYKEY_TABLEN];
+
+static int g_seed[3] = PYKEY_SEED;
+static PyObject *g_module_self;
+static PyObject *g_main;
+
+
+// end Python stuff
+
+// **************** PYTHON STUFF **************************
+/* ----------------------------------------------------- */
+/* this is the dummy functions to demonstrate */
+
+int sticky_shoes(void *vp)
+{
+#ifndef NDEBUG
+ printf("feature not enabled: Buy our Key NOW!\n");
+#endif
+ return 0;
+}
+
+/*
+int key_func1(void *vp) {
+ printf("function 1 called\n");
+}
+
+*/
+int key_return_true(void *vp) {
+#ifndef NDEBUG
+ printf("function 2 called (return true)\n");
+#endif
+ return 1;
+}
+
+/* ----------------------------------------------------- */
+
+/* Declarations for objects of type Fplist */
+
+
+#ifndef NDEBUG
+void feature1(void)
+{
+ Fptr f;
+
+ printf("feature 2 called\n");
+ f = g_ptrtab[KEY_FUNC2];
+ if (f) f(0);
+}
+
+void feature2(void)
+{
+ Fptr f;
+
+ printf("feature 3 called\n");
+ f = g_ptrtab[KEY_FUNC3];
+ if (f) f(0);
+}
+
+#endif
+
+
+/* Initialization function for the module (*must* be called initprot) */
+
+static void init_ftable(void) // initializes functiontable
+{
+ int i;
+
+ g_functab[0] = &key_func1;
+ g_functab[1] = &key_func2;
+ g_functab[2] = &key_func3;
+
+ for (i = 3; i < PYKEY_TABLEN; i++)
+ {
+ g_functab[i] = &sticky_shoes;
+ }
+
+ // for debugging perposes
+ /*
+ for (i = 0; i < PYKEY_TABLEN; i++)
+ {
+ g_functab[i] = (Fptr *) (i + 100);
+ }
+ */
+}
+
+
+static void init_ptable(void) // initializes functiontable
+{
+ int i;
+
+ for (i = 0; i < PYKEY_TABLEN; i++)
+ {
+ g_ptrtab[i] = &sticky_shoes;
+ }
+}
+
+
+#ifdef NDEBUG
+static void print_ptable(void)
+{
+ int i;
+
+ for (i = 0; i < PYKEY_TABLEN; i++)
+ {
+ printf ("index[%02d] = %08x\n", i, g_ptrtab[i]);
+ }
+}
+#endif
+
+static void insertname(PyObject *m,PyObject *p, char *name)
+{
+}
+
+/* initialisation */
+static void initprot()
+{
+ init_ftable(); // malloc
+ init_ptable(); // malloc
+}
+
+// ******************************* KEY STUFF *********************
+
+void create_key_name(char * keyname)
+{
+}
+
+void checkhome()
+{
+ initprot(); // initialize module and function tables
+}
+
+void SHOW_LICENSE_KEY(void)
+{
+}
+
+void loadKeyboard(char * name)
+{
+}
diff --git a/source/blender/src/drawaction.c b/source/blender/src/drawaction.c
new file mode 100644
index 00000000000..77319e5804b
--- /dev/null
+++ b/source/blender/src/drawaction.c
@@ -0,0 +1,583 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * Drawing routines for the Action window type
+ */
+
+/* System includes ----------------------------------------------------- */
+
+#include <math.h>
+#include <stdlib.h>
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "BMF_Api.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+/* Types --------------------------------------------------------------- */
+#include "DNA_action_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_ipo_types.h"
+#include "DNA_object_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_space_types.h"
+#include "DNA_constraint_types.h"
+
+#include "BKE_action.h"
+#include "BKE_global.h"
+
+/* Everything from source (BIF, BDR, BSE) ------------------------------ */
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+#include "BIF_resources.h"
+#include "BIF_screen.h"
+#include "BIF_interface.h"
+#include "BIF_mywindow.h"
+
+#include "BDR_editcurve.h"
+#include "BSE_view.h"
+#include "BSE_drawipo.h"
+#include "BSE_editaction_types.h"
+#include "BDR_drawaction.h"
+
+/* 'old' stuff": defines and types, and own include -------------------- */
+
+#include "blendef.h"
+
+/* local functions ----------------------------------------------------- */
+void drawactionspace(void);
+static void draw_channel_names(void);
+static void draw_channel_strips(SpaceAction *saction);
+int count_action_levels(bAction *act);
+static BezTriple **ipo_to_keylist(Ipo *ipo, int flags, int *totvert);
+static BezTriple **action_to_keylist(bAction *act, int flags, int *totvert);
+static BezTriple **ob_to_keylist(Object *ob, int flags, int *totvert);
+static void draw_keylist(gla2DDrawInfo *di, int totvert, BezTriple **blist, float ypos);
+
+
+/* implementation ------------------------------------------------------ */
+void draw_cfra_action(void)
+{
+ Object *ob;
+ float vec[2];
+
+ vec[0]= (G.scene->r.cfra);
+ vec[0]*= G.scene->r.framelen;
+
+ vec[1]= G.v2d->cur.ymin;
+ glColor3ub(0x60, 0xc0, 0x40);
+ glLineWidth(2.0);
+
+ glBegin(GL_LINE_STRIP);
+ glVertex2fv(vec);
+ vec[1]= G.v2d->cur.ymax;
+ glVertex2fv(vec);
+ glEnd();
+
+ ob= (G.scene->basact) ? (G.scene->basact->object) : 0;
+ if(ob && ob->sf!=0.0 && (ob->ipoflag & OB_OFFS_OB) ) {
+ vec[0]-= ob->sf;
+
+ glColor3ub(0x10, 0x60, 0);
+
+ glBegin(GL_LINE_STRIP);
+ glVertex2fv(vec);
+ vec[1]= G.v2d->cur.ymin;
+ glVertex2fv(vec);
+ glEnd();
+ }
+
+ glLineWidth(1.0);
+}
+
+static void draw_channel_names(void)
+{
+ short ofsx, ofsy = 0;
+
+ bAction *act;
+ bActionChannel *chan;
+ bConstraintChannel *conchan;
+ float x, y;
+
+ myortho2 (0, ACTWIDTH, G.v2d->cur.ymin, G.v2d->cur.ymax); // Scaling
+
+ /* Blank out the area */
+ if(curarea->winx>SCROLLB+10 && curarea->winy>SCROLLH+10) {
+ if(G.v2d->scroll) {
+ ofsx= curarea->winrct.xmin;
+ ofsy= curarea->winrct.ymin;
+ glViewport(ofsx, ofsy+G.v2d->mask.ymin-SCROLLB, ACTWIDTH, ( ofsy+G.v2d->mask.ymax)-( ofsy+G.v2d->mask.ymin-SCROLLB));
+ glScissor(ofsx, ofsy+G.v2d->mask.ymin-SCROLLB, ACTWIDTH, ( ofsy+G.v2d->mask.ymax)-( ofsy+G.v2d->mask.ymin-SCROLLB));
+ }
+ }
+
+ glClearColor(.8, .8, .8, 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ /* Clip to the scrollable area */
+
+ glColor3ub(0x00, 0x00, 0x00);
+
+ act=G.saction->action;
+ x = 0.0;
+
+ if (act) {
+ y= count_action_levels(act)*(CHANNELHEIGHT+CHANNELSKIP);
+
+ for (chan=act->chanbase.first; chan; chan=chan->next){
+ glColor3ub(0xAA, 0xAA, 0xAA);
+ glRectf(x, y-CHANNELHEIGHT/2, (float)ACTWIDTH, y+CHANNELHEIGHT/2);
+
+ if (chan->flag & ACHAN_SELECTED)
+ glColor3ub(255, 255, 255);
+ else
+ glColor3ub(0, 0, 0);
+ glRasterPos2f(x+8, y-4);
+ BMF_DrawString(G.font, chan->name);
+ y-=CHANNELHEIGHT+CHANNELSKIP;
+
+ /* Draw constraint channels */
+ for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next){
+ if (conchan->flag & CONSTRAINT_CHANNEL_SELECT)
+ glColor3ub(255, 255, 255);
+ else
+ glColor3ub(0, 0, 0);
+
+ glRasterPos2f(x+32, y-4);
+ BMF_DrawString(G.font, conchan->name);
+ y-=CHANNELHEIGHT+CHANNELSKIP;
+ }
+ }
+ }
+
+
+ myortho2 (0, ACTWIDTH, 0, ( ofsy+G.v2d->mask.ymax)-( ofsy+G.v2d->mask.ymin-SCROLLB)); // Scaling
+
+ glShadeModel(GL_SMOOTH);
+
+ y=9;
+
+ /* Draw sexy shaded block thingies */
+ glEnable (GL_BLEND);
+ glBegin(GL_QUAD_STRIP);
+ glColor4ub (0xCC,0xCC,0xCC,0x00);
+ glVertex2f (0,SCROLLB*2-y);
+ glVertex2f (ACTWIDTH,SCROLLB*2-y);
+
+ glColor4ub (0xCC,0xCC,0xCC,0xFF);
+ glVertex2f (0,SCROLLB-y);
+ glVertex2f (ACTWIDTH,SCROLLB-y);
+
+ glColor4ub (0xCC,0xCC,0xCC,0xFF);
+ glVertex2f (0,0-y);
+ glVertex2f (ACTWIDTH,0-y);
+
+ glEnd();
+
+/* y=( ofsy+G.v2d->mask.ymax)-( ofsy+G.v2d->mask.ymin-SCROLLB);
+
+ glBegin(GL_QUAD_STRIP);
+ glColor4ub (0x88,0x88,0x88,0xFF);
+ glVertex2f (0,y);
+ glVertex2f (ACTWIDTH,y);
+ glColor4ub (0x88,0x88,0x88,0x00);
+ glVertex2f (0,y-SCROLLB);
+ glVertex2f (ACTWIDTH,y-SCROLLB);
+
+ glEnd();
+*/
+ glDisable (GL_BLEND);
+
+ glShadeModel(GL_FLAT);
+
+}
+
+int count_action_levels(bAction *act)
+{
+ int y=0;
+ bActionChannel *achan;
+
+ if (!act)
+ return 0;
+
+ for (achan=act->chanbase.first; achan; achan=achan->next){
+ y+=1;
+ y+=BLI_countlist(&achan->constraintChannels);
+ }
+
+ return y;
+}
+ /** Draw a nicely beveled button (in screen space) */
+void draw_bevel_but(int x, int y, int w, int h, int sel)
+{
+ int xmin= x, ymin= y;
+ int xmax= x+w-1, ymax= y+h-1;
+ int i;
+
+ glColor3ub(0,0,0);
+ glBegin(GL_LINE_LOOP);
+ glVertex2i(xmin, ymin);
+ glVertex2i(xmax, ymin);
+ glVertex2i(xmax, ymax);
+ glVertex2i(xmin, ymax);
+ glEnd();
+
+ glBegin(GL_LINE_LOOP);
+ if (sel) glColor3ub(0xD0, 0x7E, 0x06);
+ else glColor3ub(0x8C, 0x8C, 0x8C);
+ glVertex2i(xmax-1, ymin+1);
+ glVertex2i(xmax-1, ymax-1);
+ if (sel) glColor3ub(0xF4, 0xEE, 0x8E);
+ else glColor3ub(0xDF, 0xDF, 0xDF);
+ glVertex2i(xmin+1, ymax-1);
+ glVertex2i(xmin+1, ymin+1);
+ glEnd();
+
+ if (sel) glColor3ub(0xF1, 0xCA, 0x13);
+ else glColor3ub(0xAC, 0xAC, 0xAC);
+ glBegin(GL_LINES);
+ for (i=xmin+2; i<=xmax-2; i++) {
+ glVertex2f(i, ymin+2);
+ glVertex2f(i, ymax-1);
+ }
+ glEnd();
+}
+
+static void draw_channel_strips(SpaceAction *saction)
+{
+ rcti scr_rct;
+ gla2DDrawInfo *di;
+ bAction *act;
+ bActionChannel *chan;
+ bConstraintChannel *conchan;
+ float y;
+
+ act= saction->action;
+ if (!act)
+ return;
+
+ scr_rct.xmin= saction->area->winrct.xmin + ACTWIDTH;
+ scr_rct.ymin= saction->area->winrct.ymin + saction->v2d.mask.ymin-SCROLLB;
+ scr_rct.xmax= saction->area->winrct.xmin + saction->v2d.hor.xmax;
+ scr_rct.ymax= saction->area->winrct.ymin + saction->v2d.mask.ymax;
+ di= glaBegin2DDraw(&scr_rct, &G.v2d->cur);
+
+ y= count_action_levels(act)*(CHANNELHEIGHT+CHANNELSKIP);
+
+ for (chan=act->chanbase.first; chan; chan=chan->next){
+ int frame1_x, channel_y;
+
+ gla2DDrawTranslatePt(di, 1, y, &frame1_x, &channel_y);
+
+ glEnable(GL_BLEND);
+ if (chan->flag & ACHAN_SELECTED) glColor4b(0x11, 0x22, 0x55, 0x22);
+ else glColor4b(0x55, 0x22, 0x11, 0x22);
+ glRectf(0, channel_y-CHANNELHEIGHT/2, frame1_x, channel_y+CHANNELHEIGHT/2);
+
+ if (chan->flag & ACHAN_SELECTED) glColor4b(0x11, 0x22, 0x55, 0x44);
+ else glColor4b(0x55, 0x22, 0x11, 0x44);
+ glRectf(frame1_x, channel_y-CHANNELHEIGHT/2, G.v2d->hor.xmax, channel_y+CHANNELHEIGHT/2);
+ glDisable(GL_BLEND);
+
+ draw_ipo_channel(di, chan->ipo, 0, y);
+
+ /* Increment the step */
+ y-=CHANNELHEIGHT+CHANNELSKIP;
+
+
+ /* Draw constraint channels */
+ for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next){
+ gla2DDrawTranslatePt(di, 1, y, &frame1_x, &channel_y);
+ glEnable(GL_BLEND);
+ if (conchan->flag & ACHAN_SELECTED) glColor4b(0x11, 0x22, 0x55, 0x22);
+ else glColor4b(0x55, 0x22, 0x11, 0x22);
+ glRectf(0, channel_y-CHANNELHEIGHT/2+4, frame1_x, channel_y+CHANNELHEIGHT/2-4);
+
+ if (conchan->flag & ACHAN_SELECTED) glColor4b(0x11, 0x22, 0x55, 0x44);
+ else glColor4b(0x55, 0x22, 0x11, 0x44);
+ glRectf(frame1_x, channel_y-CHANNELHEIGHT/2+4, G.v2d->hor.xmax, channel_y+CHANNELHEIGHT/2-4);
+ glDisable(GL_BLEND);
+
+ draw_ipo_channel(di, conchan->ipo, 0, y);
+ y-=CHANNELHEIGHT+CHANNELSKIP;
+ }
+ }
+
+ glaEnd2DDraw(di);
+}
+
+void drawactionspace(void)
+{
+
+ short ofsx = 0, ofsy = 0;
+
+ if (!G.saction)
+ return;
+
+
+ if (!G.saction->pin) {
+ if (OBACT)
+ G.saction->action = OBACT->action;
+ else
+ G.saction->action=NULL;
+ }
+
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) ;
+
+ calc_scrollrcts(G.v2d, curarea->winx, curarea->winy);
+
+ if(curarea->winx>SCROLLB+10 && curarea->winy>SCROLLH+10) {
+ if(G.v2d->scroll) {
+ ofsx= curarea->winrct.xmin;
+ ofsy= curarea->winrct.ymin;
+ glViewport(ofsx+G.v2d->mask.xmin, ofsy+G.v2d->mask.ymin, ( ofsx+G.v2d->mask.xmax-1)-(ofsx+G.v2d->mask.xmin)+1, ( ofsy+G.v2d->mask.ymax-1)-( ofsy+G.v2d->mask.ymin)+1);
+ glScissor(ofsx+G.v2d->mask.xmin, ofsy+G.v2d->mask.ymin, ( ofsx+G.v2d->mask.xmax-1)-(ofsx+G.v2d->mask.xmin)+1, ( ofsy+G.v2d->mask.ymax-1)-( ofsy+G.v2d->mask.ymin)+1);
+ }
+ }
+
+ glClearColor(.45, .45, .45, 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ myortho2 (G.v2d->cur.xmin, G.v2d->cur.xmax, G.v2d->cur.ymin, G.v2d->cur.ymax);
+
+ /* Draw backdrop */
+ calc_ipogrid();
+ draw_ipogrid();
+
+ /* Draw channel strips */
+ draw_channel_strips(G.saction);
+
+ /* Draw current frame */
+ glViewport(ofsx+G.v2d->mask.xmin, ofsy+G.v2d->mask.ymin, ( ofsx+G.v2d->mask.xmax-1)-(ofsx+G.v2d->mask.xmin)+1, ( ofsy+G.v2d->mask.ymax-1)-( ofsy+G.v2d->mask.ymin)+1);
+ glScissor(ofsx+G.v2d->mask.xmin, ofsy+G.v2d->mask.ymin, ( ofsx+G.v2d->mask.xmax-1)-(ofsx+G.v2d->mask.xmin)+1, ( ofsy+G.v2d->mask.ymax-1)-( ofsy+G.v2d->mask.ymin)+1);
+ myortho2 (G.v2d->cur.xmin, G.v2d->cur.xmax, G.v2d->cur.ymin, G.v2d->cur.ymax);
+ draw_cfra_action();
+
+ /* Draw scroll */
+ mywinset(curarea->win);
+ if(curarea->winx>SCROLLB+10 && curarea->winy>SCROLLH+10) {
+ myortho2(-0.5, curarea->winx+0.5, -0.5, curarea->winy+0.5);
+ if(G.v2d->scroll) drawscroll(0);
+ }
+
+ /* Draw channel names */
+ draw_channel_names();
+
+ curarea->win_swap= WIN_BACK_OK;
+}
+
+void draw_channel_name(const char* name, short type, float ypos, int selected)
+{
+}
+
+static void draw_keylist(gla2DDrawInfo *di, int totvert, BezTriple **blist, float ypos)
+{
+ int v;
+
+ if (!blist)
+ return;
+
+ for (v = 0; v<totvert; v++){
+ if (v==0 || (blist[v]->vec[1][0] != blist[v-1]->vec[1][0])){
+ int sc_x, sc_y;
+ gla2DDrawTranslatePt(di, blist[v]->vec[1][0], ypos, &sc_x, &sc_y);
+ draw_bevel_but(sc_x-2, sc_y-5, 7, 13, (blist[v]->f2 & 1));
+ }
+ }
+}
+
+void draw_object_channel(gla2DDrawInfo *di, Object *ob, int flags, float ypos)
+{
+ BezTriple **blist;
+ int totvert;
+
+ blist = ob_to_keylist(ob, flags, &totvert);
+ if (blist){
+ draw_keylist(di,totvert, blist, ypos);
+ MEM_freeN(blist);
+ }
+}
+
+void draw_ipo_channel(gla2DDrawInfo *di, Ipo *ipo, int flags, float ypos)
+{
+ BezTriple **blist;
+ int totvert;
+
+ blist = ipo_to_keylist(ipo, flags, &totvert);
+ if (blist){
+ draw_keylist(di,totvert, blist, ypos);
+ MEM_freeN(blist);
+ }
+}
+
+void draw_action_channel(gla2DDrawInfo *di, bAction *act, int flags, float ypos)
+{
+ BezTriple **blist;
+ int totvert;
+
+ blist = action_to_keylist(act, flags, &totvert);
+ if (blist){
+ draw_keylist(di,totvert, blist, ypos);
+ MEM_freeN(blist);
+ }
+}
+
+static BezTriple **ob_to_keylist(Object *ob, int flags, int *totvert)
+{
+ IpoCurve *icu;
+ int v, count=0;
+
+ BezTriple **list = NULL;
+
+ if (ob){
+
+ /* Count Object Keys */
+ if (ob->ipo){
+ for (icu=ob->ipo->curve.first; icu; icu=icu->next){
+ count+=icu->totvert;
+ }
+ }
+
+ /* Count Constraint Keys */
+ /* Count object data keys */
+
+ /* Build the list */
+ if (count){
+ list = MEM_callocN(sizeof(BezTriple*)*count, "beztlist");
+ count=0;
+
+ /* Add object keyframes */
+ for (icu=ob->ipo->curve.first; icu; icu=icu->next){
+ for (v=0; v<icu->totvert; v++){
+ list[count++]=&icu->bezt[v];
+ }
+ }
+
+ /* Add constraint keyframes */
+ /* Add object data keyframes */
+
+ /* Sort */
+ qsort(list, count, sizeof(BezTriple*), bezt_compare);
+ }
+ }
+ (*totvert)=count;
+ return list;
+}
+
+static BezTriple **ipo_to_keylist(Ipo *ipo, int flags, int *totvert)
+{
+ IpoCurve *icu;
+ int v, count=0;
+
+ BezTriple **list = NULL;
+
+ if (ipo){
+ /* Count required keys */
+ for (icu=ipo->curve.first; icu; icu=icu->next){
+ count+=icu->totvert;
+ }
+
+ /* Build the list */
+ if (count){
+ list = MEM_callocN(sizeof(BezTriple*)*count, "beztlist");
+ count=0;
+
+ for (icu=ipo->curve.first; icu; icu=icu->next){
+ for (v=0; v<icu->totvert; v++){
+ list[count++]=&icu->bezt[v];
+ }
+ }
+ qsort(list, count, sizeof(BezTriple*), bezt_compare);
+ }
+ }
+ (*totvert)=count;
+ return list;
+}
+
+static BezTriple **action_to_keylist(bAction *act, int flags, int *totvert)
+{
+ IpoCurve *icu;
+ bActionChannel *achan;
+ bConstraintChannel *conchan;
+ int v, count=0;
+
+ BezTriple **list = NULL;
+
+ if (act){
+ /* Count required keys */
+ for (achan=act->chanbase.first; achan; achan=achan->next){
+ /* Count transformation keys */
+ for (icu=achan->ipo->curve.first; icu; icu=icu->next)
+ count+=icu->totvert;
+
+ /* Count constraint keys */
+ for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next)
+ for (icu=conchan->ipo->curve.first; icu; icu=icu->next)
+ count+=icu->totvert;
+
+
+ }
+
+ /* Build the list */
+ if (count){
+ list = MEM_callocN(sizeof(BezTriple*)*count, "beztlist");
+ count=0;
+
+ for (achan=act->chanbase.first; achan; achan=achan->next){
+ /* Add transformation keys */
+ for (icu=achan->ipo->curve.first; icu; icu=icu->next){
+ for (v=0; v<icu->totvert; v++)
+ list[count++]=&icu->bezt[v];
+ }
+
+ /* Add constraint keys */
+ for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next){
+ for (icu=conchan->ipo->curve.first; icu; icu=icu->next)
+ for (v=0; v<icu->totvert; v++)
+ list[count++]=&icu->bezt[v];
+ }
+
+ }
+ qsort(list, count, sizeof(BezTriple*), bezt_compare);
+
+ }
+ }
+ (*totvert)=count;
+ return list;
+}
+
diff --git a/source/blender/src/drawimage.c b/source/blender/src/drawimage.c
new file mode 100644
index 00000000000..ede04c45d6b
--- /dev/null
+++ b/source/blender/src/drawimage.c
@@ -0,0 +1,582 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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>
+#ifdef WIN32
+#include <io.h>
+#include "BLI_winstuff.h"
+#else
+#include <unistd.h>
+#endif
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_editVert.h"
+
+#include "IMB_imbuf_types.h"
+
+#include "DNA_image_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_packedFile_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_global.h"
+#include "BKE_mesh.h"
+#include "BKE_image.h"
+
+#include "BDR_editface.h"
+
+#include "BIF_gl.h"
+#include "BIF_space.h"
+#include "BIF_screen.h"
+#include "BIF_mywindow.h"
+#include "BIF_drawimage.h"
+
+/* Modules used */
+#include "mydevice.h"
+#include "render.h"
+
+
+void rectwrite_part(int winxmin, int winymin, int winxmax, int winymax, int x1, int y1, int xim, int yim, float zoomx, float zoomy, unsigned int *rect)
+{
+ int cx, cy, oldxim, x2, y2;
+
+ oldxim= xim;
+
+ /* coordinaten hoe 't op scherm komt */
+ x2= x1+ zoomx*xim;
+ y2= y1+ zoomy*yim;
+
+ /* partiele clip */
+ if(x1<winxmin) {
+ /* recten bij OpenGL mogen niet links/onder van windowrand beginnen */
+ cx= winxmin-x1+(int)zoomx;
+ /* zorg ervoor dat de rect pixelnauwkeurig wordt neergezet */
+ cx/= zoomx;
+ cx++;
+ x1+= zoomx*cx;
+ xim-= cx;
+ rect+= cx;
+ }
+ if(y1<winymin) {
+ cy= winymin-y1+(int)zoomy;
+ cy/= zoomy;
+ cy++;
+ y1+= zoomy*cy;
+ rect+= cy*oldxim;
+ yim-= cy;
+ }
+ if(x2>=winxmax) {
+ cx= x2-winxmax;
+ cx/= zoomx;
+ xim-= cx+3;
+ }
+ if(y2>=winymax) {
+ cy= y2-winymax;
+ cy/= zoomy;
+ yim-= cy+3;
+ }
+
+ if(xim<=0) return;
+ if(yim<=0) return;
+
+ mywinset(G.curscreen->mainwin);
+ glScissor(winxmin, winymin, winxmax-winxmin+1, winymax-winymin+1);
+
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, oldxim);
+
+ glPixelZoom(zoomx, zoomy);
+
+ glRasterPos2i(x1, y1);
+ glDrawPixels(xim, yim, GL_RGBA, GL_UNSIGNED_BYTE, rect);
+
+ glPixelZoom(1.0, 1.0);
+
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+
+ mywinset(curarea->win);
+}
+
+/**
+ * Sets up the fields of the View2D member of the SpaceImage struct
+ * This routine can be called in two modes:
+ * mode == 'f': float mode ???
+ * mode == 'p': pixel mode ???
+ *
+ * @param sima the image space to update
+ * @param mode the mode to use for the update
+ * @return void
+ *
+ */
+void calc_image_view(SpaceImage *sima, char mode)
+{
+ float xim=256, yim=256;
+ float x1, y1;
+ float zoom;
+
+ if(sima->image && sima->image->ibuf) {
+ xim= sima->image->ibuf->x;
+ yim= sima->image->ibuf->y;
+ }
+
+ sima->v2d.tot.xmin= 0;
+ sima->v2d.tot.ymin= 0;
+ sima->v2d.tot.xmax= xim;
+ sima->v2d.tot.ymax= yim;
+
+ sima->v2d.mask.xmin= sima->v2d.mask.ymin= 0;
+ sima->v2d.mask.xmax= curarea->winx;
+ sima->v2d.mask.ymax= curarea->winy;
+
+
+ /* Which part of the image space do we see? */
+ /* Same calculation as in lrectwrite: area left and down*/
+ x1= curarea->winrct.xmin+(curarea->winx-sima->zoom*xim)/2;
+ y1= curarea->winrct.ymin+(curarea->winy-sima->zoom*yim)/2;
+
+ x1-= sima->zoom*sima->xof;
+ y1-= sima->zoom*sima->yof;
+
+ /* float! */
+ zoom= sima->zoom;
+
+ /* relatieve afbeeld links */
+ sima->v2d.cur.xmin= ((curarea->winrct.xmin - (float)x1)/zoom);
+ sima->v2d.cur.xmax= sima->v2d.cur.xmin + ((float)curarea->winx/zoom);
+
+ /* relatieve afbeeld links */
+ sima->v2d.cur.ymin= ((curarea->winrct.ymin-(float)y1)/zoom);
+ sima->v2d.cur.ymax= sima->v2d.cur.ymin + ((float)curarea->winy/zoom);
+
+ if(mode=='f') {
+ sima->v2d.cur.xmin/= xim;
+ sima->v2d.cur.xmax/= xim;
+ sima->v2d.cur.ymin/= yim;
+ sima->v2d.cur.ymax/= yim;
+ }
+}
+
+void what_image(SpaceImage *sima)
+{
+ extern TFace *lasttface; /* editface.c */
+ Mesh *me;
+
+ if(sima->mode==SI_TEXTURE) {
+ if(G.f & G_FACESELECT) {
+
+ sima->image= 0;
+ me= get_mesh((G.scene->basact) ? (G.scene->basact->object) : 0);
+ set_lasttface();
+
+ if(me && me->tface && lasttface) {
+ if(lasttface->mode & TF_TEX) {
+ sima->image= lasttface->tpage;
+
+ if(sima->flag & SI_EDITTILE);
+ else sima->curtile= lasttface->tile;
+
+ if(sima->image) {
+ if(lasttface->mode & TF_TILES) sima->image->tpageflag |= IMA_TILES;
+ else sima->image->tpageflag &= ~IMA_TILES;
+ }
+ }
+ }
+ }
+ }
+}
+
+void image_changed(SpaceImage *sima, int dotile)
+{
+ TFace *tface;
+ Mesh *me;
+ int a;
+
+ if(sima->mode==SI_TEXTURE) {
+
+ if(G.f & G_FACESELECT) {
+ me= get_mesh((G.scene->basact) ? (G.scene->basact->object) : 0);
+ if(me && me->tface) {
+ tface= me->tface;
+ a= me->totface;
+ while(a--) {
+ if(tface->flag & TF_SELECT) {
+
+ if(dotile==2) {
+ tface->mode &= ~TF_TILES;
+ }
+ else {
+ tface->tpage= sima->image;
+ tface->mode |= TF_TEX;
+
+ if(dotile) tface->tile= sima->curtile;
+ }
+
+ if(sima->image) {
+ if(sima->image->tpageflag & IMA_TILES) tface->mode |= TF_TILES;
+ else tface->mode &= ~TF_TILES;
+
+ if(sima->image->id.us==0) sima->image->id.us= 1;
+ }
+ }
+ tface++;
+ }
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWBUTSGAME, 0);
+ }
+ }
+ }
+}
+
+
+void uvco_to_areaco(float *vec, short *mval)
+{
+ float x, y;
+
+ mval[0]= 3200;
+
+ x= (vec[0] - G.v2d->cur.xmin)/(G.v2d->cur.xmax-G.v2d->cur.xmin);
+ y= (vec[1] - G.v2d->cur.ymin)/(G.v2d->cur.ymax-G.v2d->cur.ymin);
+
+ if(x>=0.0 && x<=1.0) {
+ if(y>=0.0 && y<=1.0) {
+ mval[0]= G.v2d->mask.xmin + x*(G.v2d->mask.xmax-G.v2d->mask.xmin);
+ mval[1]= G.v2d->mask.ymin + y*(G.v2d->mask.ymax-G.v2d->mask.ymin);
+ }
+ }
+}
+
+void uvco_to_areaco_noclip(float *vec, short *mval)
+{
+ float x, y;
+
+ mval[0]= 3200;
+
+ x= (vec[0] - G.v2d->cur.xmin)/(G.v2d->cur.xmax-G.v2d->cur.xmin);
+ y= (vec[1] - G.v2d->cur.ymin)/(G.v2d->cur.ymax-G.v2d->cur.ymin);
+
+ x= G.v2d->mask.xmin + x*(G.v2d->mask.xmax-G.v2d->mask.xmin);
+ y= G.v2d->mask.ymin + y*(G.v2d->mask.ymax-G.v2d->mask.ymin);
+
+ mval[0]= x;
+ mval[1]= y;
+}
+
+
+void draw_tfaces(void)
+{
+ TFace *tface;
+ MFace *mface;
+ Mesh *me;
+ unsigned int col;
+ int a;
+
+ glPointSize(2.0);
+
+ if(G.f & G_FACESELECT) {
+ me= get_mesh((G.scene->basact) ? (G.scene->basact->object) : 0);
+ if(me && me->tface) {
+
+ calc_image_view(G.sima, 'f'); /* float */
+ myortho2(G.v2d->cur.xmin, G.v2d->cur.xmax, G.v2d->cur.ymin, G.v2d->cur.ymax);
+
+ tface= me->tface;
+ mface= me->mface;
+ a= me->totface;
+
+ while(a--) {
+ if(mface->v3 && (tface->flag & TF_SELECT) ) {
+
+ cpack(0x0);
+ glBegin(GL_LINE_LOOP);
+ glVertex2fv( tface->uv[0] );
+ glVertex2fv( tface->uv[1] );
+ glVertex2fv( tface->uv[2] );
+ if(mface->v4) glVertex2fv( tface->uv[3] );
+ glEnd();
+
+ setlinestyle(2);
+ /* kleuren: R=x G=y */
+
+ if(tface->flag & TF_ACTIVE) cpack(0xFF00); else cpack(0xFFFFFF);
+
+ glBegin(GL_LINE_STRIP);
+ glVertex2fv( tface->uv[0] );
+ glVertex2fv( tface->uv[1] );
+ glEnd();
+
+ if(tface->flag & TF_ACTIVE) cpack(0xFF); else cpack(0xFFFFFF);
+
+ glBegin(GL_LINE_STRIP);
+ glVertex2fv( tface->uv[0] );
+ if(mface->v4) glVertex2fv( tface->uv[3] ); else glVertex2fv( tface->uv[2] );
+ glEnd();
+
+ cpack(0xFFFFFF);
+
+ glBegin(GL_LINE_STRIP);
+ glVertex2fv( tface->uv[1] );
+ glVertex2fv( tface->uv[2] );
+ if(mface->v4) glVertex2fv( tface->uv[3] );
+ glEnd();
+
+ setlinestyle(0);
+
+ glBegin(GL_POINTS);
+
+ if(tface->flag & TF_SEL1) col= 0x77FFFF; else col= 0xFF70FF;
+ cpack(col);
+ glVertex2fv(tface->uv[0]);
+
+ if(tface->flag & TF_SEL2) col= 0x77FFFF; else col= 0xFF70FF;
+ cpack(col);
+ glVertex2fv(tface->uv[1]);
+
+ if(tface->flag & TF_SEL3) col= 0x77FFFF; else col= 0xFF70FF;
+ cpack(col);
+ glVertex2fv(tface->uv[2]);
+
+ if(mface->v4) {
+ if(tface->flag & TF_SEL4) col= 0x77FFFF; else col= 0xFF70FF;
+ cpack(col);
+ glVertex2fv(tface->uv[3]);
+ }
+ glEnd();
+ }
+
+ tface++;
+ mface++;
+ }
+ }
+ }
+ glPointSize(1.0);
+}
+
+static unsigned int *get_part_from_ibuf(ImBuf *ibuf, short startx, short starty, short endx, short endy)
+{
+ unsigned int *rt, *rp, *rectmain;
+ short y, heigth, len;
+
+ /* de juiste offset in rectot */
+
+ rt= ibuf->rect+ (starty*ibuf->x+ startx);
+
+ len= (endx-startx);
+ heigth= (endy-starty);
+
+ rp=rectmain= MEM_mallocN(heigth*len*sizeof(int), "rect");
+
+ for(y=0; y<heigth; y++) {
+ memcpy(rp, rt, len*4);
+ rt+= ibuf->x;
+ rp+= len;
+ }
+ return rectmain;
+}
+
+void drawimagespace(void)
+{
+ ImBuf *ibuf= NULL;
+ unsigned int *rect;
+ int x1, y1, xmin, xmax, ymin, ymax;
+ short sx, sy, dx, dy;
+
+ glClearColor(.1875, .1875, .1875, 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ curarea->win_swap= WIN_BACK_OK;
+
+ xmin= curarea->winrct.xmin; xmax= curarea->winrct.xmax;
+ ymin= curarea->winrct.ymin; ymax= curarea->winrct.ymax;
+
+ what_image(G.sima);
+
+ if(G.sima->image) {
+
+ if(G.sima->image->ibuf==0) {
+ load_image(G.sima->image, IB_rect, G.sce, G.scene->r.cfra);
+ }
+ ibuf= G.sima->image->ibuf;
+ }
+
+ if(ibuf==0 || ibuf->rect==0) {
+ calc_image_view(G.sima, 'f');
+ myortho2(G.v2d->cur.xmin, G.v2d->cur.xmax, G.v2d->cur.ymin, G.v2d->cur.ymax);
+ cpack(0x404040);
+ glRectf(0.0, 0.0, 1.0, 1.0);
+ draw_tfaces();
+
+ return;
+ }
+
+ /* plek berekenen */
+ x1= xmin+(curarea->winx-G.sima->zoom*ibuf->x)/2;
+ y1= ymin+(curarea->winy-G.sima->zoom*ibuf->y)/2;
+
+ x1-= G.sima->zoom*G.sima->xof;
+ y1-= G.sima->zoom*G.sima->yof;
+
+
+ if(G.sima->flag & SI_EDITTILE) {
+ rectwrite_part(xmin, ymin, xmax, ymax, x1, y1, ibuf->x, ibuf->y, (float)G.sima->zoom, (float)G.sima->zoom, ibuf->rect);
+
+ dx= ibuf->x/G.sima->image->xrep;
+ dy= ibuf->y/G.sima->image->yrep;
+ sy= (G.sima->curtile / G.sima->image->xrep);
+ sx= G.sima->curtile - sy*G.sima->image->xrep;
+
+ sx*= dx;
+ sy*= dy;
+
+ calc_image_view(G.sima, 'p'); /* pixel */
+ myortho2(G.v2d->cur.xmin, G.v2d->cur.xmax, G.v2d->cur.ymin, G.v2d->cur.ymax);
+
+ cpack(0x0);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glRects(sx, sy, sx+dx-1, sy+dy-1); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ cpack(0xFFFFFF);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glRects(sx+1, sy+1, sx+dx, sy+dy); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ }
+ else if(G.sima->mode==SI_TEXTURE) {
+ if(G.sima->image->tpageflag & IMA_TILES) {
+
+
+ /* eventjes laten staan */
+ if(G.sima->image->xrep<1) return;
+ if(G.sima->image->yrep<1) return;
+
+ if(G.sima->curtile >= G.sima->image->xrep*G.sima->image->yrep)
+ G.sima->curtile = G.sima->image->xrep*G.sima->image->yrep - 1;
+
+ dx= ibuf->x/G.sima->image->xrep;
+ dy= ibuf->y/G.sima->image->yrep;
+
+ sy= (G.sima->curtile / G.sima->image->xrep);
+ sx= G.sima->curtile - sy*G.sima->image->xrep;
+
+ sx*= dx;
+ sy*= dy;
+
+ rect= get_part_from_ibuf(ibuf, sx, sy, sx+dx, sy+dy);
+
+ /* rect= ibuf->rect; */
+ for(sy= 0; sy+dy<=ibuf->y; sy+= dy) {
+ for(sx= 0; sx+dx<=ibuf->x; sx+= dx) {
+
+ rectwrite_part(xmin, ymin, xmax, ymax,
+ x1+sx*G.sima->zoom, y1+sy*G.sima->zoom, dx, dy, (float)G.sima->zoom, (float)G.sima->zoom, rect);
+ }
+ }
+
+ MEM_freeN(rect);
+ }
+ else
+ rectwrite_part(xmin, ymin, xmax, ymax, x1, y1, ibuf->x, ibuf->y, (float)G.sima->zoom,(float)G.sima->zoom, ibuf->rect);
+
+ draw_tfaces();
+ }
+
+ calc_image_view(G.sima, 'f'); /* float */
+}
+
+void image_viewmove(void)
+{
+ short mval[2], mvalo[2], xof, yof;
+
+ getmouseco_sc(mvalo);
+
+ while(get_mbut()&(L_MOUSE|M_MOUSE)) {
+
+ getmouseco_sc(mval);
+
+ xof= (mvalo[0]-mval[0])/G.sima->zoom;
+ yof= (mvalo[1]-mval[1])/G.sima->zoom;
+
+ if(xof || yof) {
+
+ G.sima->xof+= xof;
+ G.sima->yof+= yof;
+
+ mvalo[0]= mval[0];
+ mvalo[1]= mval[1];
+
+ scrarea_do_windraw(curarea);
+ screen_swapbuffers();
+ }
+ else BIF_wait_for_statechange();
+ }
+}
+
+/**
+ * Updates the fields of the View2D member of the SpaceImage struct.
+ * Default behavior is to reset the position of the image and set the zoom to 1
+ * If the image will not fit within the window rectangle, the zoom is adjusted
+ *
+ * @return void
+ *
+ */
+void image_home(void)
+{
+ int width, height;
+ float zoomX, zoomY;
+
+ if (curarea->spacetype != SPACE_IMAGE) return;
+ if ((G.sima->image == 0) || (G.sima->image->ibuf == 0)) return;
+
+ /* Check if the image will fit in the image with zoom==1 */
+ width = curarea->winx;
+ height = curarea->winy;
+ if (((G.sima->image->ibuf->x >= width) || (G.sima->image->ibuf->y >= height)) &&
+ ((width > 0) && (height > 0))) {
+ /* Find the zoom value that will fit the image in the image space */
+ zoomX = ((float)width) / ((float)G.sima->image->ibuf->x);
+ zoomY = ((float)height) / ((float)G.sima->image->ibuf->y);
+ G.sima->zoom= MIN2(zoomX, zoomY);
+
+ /* Now make it a power of 2 */
+ G.sima->zoom = 1 / G.sima->zoom;
+ G.sima->zoom = log(G.sima->zoom) / log(2);
+ G.sima->zoom = ceil(G.sima->zoom);
+ G.sima->zoom = pow(2, G.sima->zoom);
+ G.sima->zoom = 1 / G.sima->zoom;
+ }
+ else {
+ G.sima->zoom= (float)1;
+ }
+
+ G.sima->xof= G.sima->yof= 0;
+
+ calc_image_view(G.sima, 'p');
+
+ scrarea_queue_winredraw(curarea);
+}
+
diff --git a/source/blender/src/drawimasel.c b/source/blender/src/drawimasel.c
new file mode 100644
index 00000000000..62d5b9ac583
--- /dev/null
+++ b/source/blender/src/drawimasel.c
@@ -0,0 +1,843 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 <string.h>
+
+#ifdef _WIN32
+#include "BLI_winstuff.h"
+#pragma warning (once : 4761)
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "BMF_Api.h"
+
+#include "BLI_blenlib.h"
+
+#include "IMB_imbuf_types.h"
+
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+
+#include "BKE_global.h"
+
+#include "BIF_fsmenu.h"
+#include "BIF_gl.h"
+#include "BIF_resources.h"
+#include "BIF_screen.h"
+#include "BIF_interface.h"
+#include "BIF_imasel.h"
+#include "BIF_mywindow.h"
+#include "BIF_space.h"
+
+#include "BSE_drawimasel.h"
+#include "BSE_filesel.h"
+
+#include "interface.h"
+#include "blendef.h"
+#include "mydevice.h"
+
+#define IMALINESIZE 16
+/* well, who would have thought ... */
+#define lrectwrite(a, b, c, d, rect) {glRasterPos2i(a, b);glDrawPixels((c)-(a)+1, (d)-(b)+1, GL_RGBA, GL_UNSIGNED_BYTE, rect);}
+
+/* GLOBALS */
+extern char *fsmenu;
+
+void viewgate(short sx, short sy, short ex, short ey)
+{
+ short wx, wy;
+ wx = curarea->winrct.xmin; wy = curarea->winrct.ymin;
+ glViewport(wx+sx, wy+sy, (wx+ex )-(wx+sx)+1, (wy+ey )-(wy+sy)+1);
+ glScissor(wx+sx, wy+sy, (wx+ex )-(wx+sx)+1, (wy+ey )-(wy+sy)+1);
+ myortho2((float)sx+0.5 , (float)ex+0.5, (float)sy+0.5, (float)ey+0.5);
+}
+
+void areaview (void)
+{
+ short wx, wy;
+ wx = curarea->winrct.xmin; wy = curarea->winrct.ymin;
+ glViewport(wx, wy, curarea->winx, curarea->winy);
+ glScissor(wx, wy, curarea->winx, curarea->winy);
+ myortho2(-0.5, (float)(curarea->winx)-0.5, -0.5, (float)(curarea->winy)-0.5);
+
+}
+
+void calc_hilite(SpaceImaSel *simasel)
+{
+ OneSelectableIma *ima;
+ ImaDir *direntry;
+ short mx, my;
+ int i, area_event;
+
+ if (simasel->hilite > -1) {
+ direntry = simasel->firstdir;
+ while(direntry){
+ direntry->hilite = 0;
+ direntry = direntry->next;
+ }
+ simasel->hilite = -1;
+ }
+
+ if (simasel->totalima){
+ simasel->hilite_ima = 0;
+ ima = simasel->first_sel_ima;
+ while (ima){
+ ima->selectable = 0;
+ ima = ima->next;
+ }
+ }
+
+ area_event = 0;
+ mx = simasel->mx;
+ my = simasel->my;
+
+ if (simasel->desx > 0){
+ if ( (mx > simasel->desx) && (mx < simasel->deex) && (my > simasel->desy) && (my < simasel->deey) ) area_event = IMS_INDIR;
+ }
+ if (simasel->fesx > 0){
+ if ( (mx > simasel->fesx) && (mx < simasel->feex) && (my > simasel->fesy) && (my < simasel->feey) ) area_event = IMS_INFILE;
+ }
+
+ switch(area_event){
+ case IMS_INDIR:
+ simasel->hilite = simasel->topdir + ((simasel->deey - my - 4) / IMALINESIZE);
+
+ if (my >= simasel->deey) simasel->hilite = -1;
+ if (simasel->hilite >= simasel->totaldirs) simasel->hilite = -1;
+
+ if (simasel->hilite > -1){
+ direntry = simasel->firstdir;
+ for (i = simasel->hilite; i>0; i--){
+ direntry = direntry->next;
+ }
+ direntry->hilite = 1;
+
+ }
+ simasel->mouse_move_redraw = 1;
+ break;
+
+ case IMS_INFILE:
+ if (simasel->totalima){
+ ima = simasel->first_sel_ima;
+ while (ima){
+ ima->selectable = 0;
+
+ if (ima->draw_me) {
+ if ((mx > ima->sx) && (mx < ima->sx+76) && (my > ima->sy-16) && (my < ima->sy+76)) {
+ ima->selectable = 1;
+ simasel->hilite_ima = ima;
+ simasel->mouse_move_redraw = 1;
+ }
+ }
+
+ ima = ima->next;
+ }
+ }
+ break;
+ }
+}
+
+
+void make_sima_area(SpaceImaSel *simasel)
+{
+ OneSelectableIma *ima;
+ short rh, dm, sc;
+ short boxperline, boxlines, boxlinesinview, boxlinesleft;
+
+/* ima slider box */
+ simasel->fssx = 8;
+ simasel->fssy = 8;
+ simasel->fsex = 30;
+ simasel->fsey = curarea->winy-64;
+/* ima entry's box */
+ simasel->fesx = simasel->fsex + 8;
+ simasel->fesy = simasel->fssy;
+ simasel->feex = curarea->winx- 8;
+ simasel->feey = curarea->winy-64;
+/* ima names */
+ simasel->dnsx = 38;
+ simasel->dnsy = curarea->winy - 29;
+ simasel->dnw = curarea->winx - 8 - 38;
+ simasel->dnh = 21;
+ simasel->fnsx = simasel->fesx;
+ simasel->fnsy = curarea->winy - 29 - 29;
+ simasel->fnw = curarea->winx - 8 - simasel->fnsx;
+ simasel->fnh = 21;
+
+ if ((simasel->mode & 1)==1){
+ /* dir slider box */
+ simasel->dssx = 8;
+
+ simasel->dsex = 30;
+ simasel->dsey = curarea->winy-64;
+ /* dir entry's box */
+ simasel->desx = 38;
+ simasel->desy = 8;
+
+ simasel->deex = 208;
+ simasel->deey = curarea->winy-64;
+ simasel->dssy = simasel->desy;
+ if (simasel->deex > (curarea->winx -8) ) simasel->deex = curarea->winx - 8;
+ if (simasel->deex <= simasel->desx ) simasel->dssx = 0;
+ /* file slider & entry & name box ++ */
+ simasel->fssx += 216;
+ simasel->fsex += 216;
+ simasel->fesx += 216;
+ simasel->fnsx += 216;
+ simasel->fnw -= 216;
+ }else{
+ simasel->desx = 0;
+ }
+
+ if ((simasel->mode & 2) == 2){
+ simasel->fesy += 32;
+ simasel->infsx = simasel->fesx; simasel->infsy = 8;
+ simasel->infex = simasel->feex; simasel->infey = 28;
+ }else{
+ simasel->infsx = 0;
+ }
+
+ simasel->dsdh = simasel->deey - simasel->desy - 4;
+
+ if (simasel->dsdh <= 16) { simasel->desx = 0; }
+ if ((simasel->feex-16) <= simasel->fesx) { simasel->fesx = 0; }
+ if ((simasel->infex-16) <= simasel->infsx) { simasel->infsx = 0; }
+
+ if ((simasel->deey ) <= simasel->desy) { simasel->desx = 0; }
+ if ((simasel->feey ) <= simasel->fesy) { simasel->fesx = 0; }
+ if ((simasel->infey ) > simasel->feey) { simasel->infsx = 0;}
+
+ /* Dir Slider */
+ if (simasel->desx != 0){
+ simasel->dirsli = 0;
+
+ simasel->dirsli_lines = (simasel->dsdh / IMALINESIZE);
+ simasel->dirsli_h = 0;
+
+ if (simasel->topdir < 0) simasel->topdir = 0;
+ if (simasel->topdir > (simasel->totaldirs - simasel->dirsli_lines) ) simasel->topdir = (simasel->totaldirs - simasel->dirsli_lines);
+
+ if ( (simasel->totaldirs * IMALINESIZE) >= simasel->dsdh ){
+ simasel->dirsli = 1;
+ simasel->dirsli_sx = simasel->dssx+2;
+ simasel->dirsli_ex = simasel->dsex-2;
+
+ simasel->dirsli_h = (simasel->dsdh) * (float)simasel->dirsli_lines / (float)simasel->totaldirs;
+ simasel->dirsli_ey = simasel->dsey - 2;
+ if (simasel->topdir) {
+ rh = (simasel->dsdh - simasel->dirsli_h);
+ simasel->dirsli_ey -= rh * (float)((float)simasel->topdir / (float)(simasel->totaldirs - simasel->dirsli_lines ));
+ }
+
+ if (simasel->dirsli_h < 4) simasel->dirsli_h = 4;
+
+ }else{
+ simasel->topdir = 0;
+ }
+ }
+
+ if (simasel->totalima){
+ /* there are images */
+
+ ima = simasel->first_sel_ima;
+
+
+ boxperline = (simasel->feex - simasel->fesx) / 80;
+ if (boxperline) boxlines = 1 + (simasel->totalima / boxperline); else boxlines = 1;
+ boxlinesinview = (simasel->feey - simasel->fesy) / 100;
+ boxlinesleft = boxlines - boxlinesinview;
+
+ if (boxlinesleft > 0){
+ /* slider needed */
+
+ simasel->slider_height = boxlinesinview / (float)(boxlines+1);
+ simasel->slider_space = 1.0 - simasel->slider_height;
+
+ simasel->imasli_sx = simasel->fssx+1;
+ simasel->imasli_ex = simasel->fsex-1;
+ simasel->fsdh = simasel->fsey - simasel->fssy - 4;
+
+ simasel->imasli_h = simasel->fsdh * simasel->slider_height;
+ if (simasel->imasli_h < 6) simasel->imasli_h = 6;
+ simasel->imasli_ey = simasel->fsey - 2 - (simasel->fsdh * simasel->slider_space * simasel->image_slider);
+
+ simasel->imasli = 1;
+
+ }else{
+ simasel->image_slider = 0;
+ simasel->imasli = 0;
+ }
+
+ sc = simasel->image_slider * (boxlinesleft * 100);
+
+ simasel->curimax = simasel->fesx + 8;
+ simasel->curimay = simasel->feey - 90 + sc;
+
+ dm = 1;
+ if (simasel->curimay-2 < simasel->fesy) dm = 0;
+ if (simasel->curimay+80 > simasel->feey) dm = 0;
+ if (simasel->curimax+72 > simasel->feex) dm = 0;
+
+ simasel->total_selected = 0;
+ while (ima){
+ ima->draw_me = dm;
+
+ if (ima->selected) simasel->total_selected++;
+
+ ima->sx = simasel->curimax;
+ ima->sy = simasel->curimay+16;
+
+ ima->ex = ima->sx + ima->dw;
+ ima->ey = ima->sy + ima->dh;
+
+ simasel->curimax += 80;
+ if (simasel->curimax + 72 > simasel->feex){
+
+ simasel->curimax = simasel->fesx + 8;
+ simasel->curimay -= 100;
+
+ dm = 1;
+ if (simasel->curimay+80 > simasel->feey) dm = 0;
+ if (simasel->curimay-8 < simasel->fesy) dm = 0;
+
+ }
+ ima = ima->next;
+ }
+ }
+}
+
+static void str_image_type(int ftype, char *name)
+{
+ strcpy(name, "");
+
+ if((ftype & JPG_MSK) == JPG_STD) strcat(name, "std ");
+ if((ftype & JPG_MSK) == JPG_VID) strcat(name, "video ");
+ if((ftype & JPG_MSK) == JPG_JST) strcat(name, "amiga ");
+ if((ftype & JPG_MSK) == JPG_MAX) strcat(name, "max ");
+
+ if( ftype == AN_hamx) { strcat(name, "hamx "); return; }
+
+ if( ftype == IMAGIC ) { strcat(name, "sgi "); return; }
+ if( ftype & JPG ) { strcat(name, "jpeg "); }
+ if( ftype & TGA ) { strcat(name, "targa "); }
+ if( ftype & PNG ) { strcat(name, "png "); }
+ if( ftype & AMI ) { strcat(name, "iff "); }
+}
+
+void draw_sima_area(SpaceImaSel *simasel)
+{
+ uiBlock *block;
+ OneSelectableIma *ima;
+ ImaDir *direntry;
+ int i, info;
+ short sx, sy, ex, ey, sc;
+ char naam[256], infostr[256];
+
+ glClearColor(0.4375, 0.4375, 0.4375, 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ sprintf(naam, "win %d", curarea->win);
+ block= uiNewBlock(&curarea->uiblocks, naam, UI_EMBOSSF, UI_HELV, curarea->win);
+ uiBlockSetCol(block, BUTBLUE);
+
+ if (simasel->desx > 0){
+ /* DIR ENTRYS */
+ cpack(C_DERK);
+ glRecti(simasel->dssx, simasel->dssy, simasel->dsex, simasel->dsey);
+ glRecti(simasel->desx, simasel->desy, simasel->deex, simasel->deey);
+
+ uiEmboss(simasel->dssx, simasel->dssy, simasel->dsex, simasel->dsey,1);
+ uiEmboss(simasel->desx, simasel->desy, simasel->deex, simasel->deey,1);
+
+ if (simasel->dirsli == 1) {
+ sx = simasel->dirsli_sx+2;
+ sy = simasel->dirsli_ey - simasel->dirsli_h+2;
+ ex = simasel->dirsli_ex-2;
+ ey = simasel->dirsli_ey-2;
+
+ cpack(C_BACK);
+
+ glRecti(sx, sy, ex, ey);
+ uiEmboss(sx, sy, ex,ey,0);
+ }
+ if (simasel->totaldirs) {
+ sx = simasel->desx+8;
+ sy = simasel->deey-IMALINESIZE;
+
+ direntry = simasel->firstdir;
+ if (simasel->topdir){
+ for(i = simasel->topdir; i>0; i--){
+ direntry = direntry->next;
+ }
+ }
+ viewgate(simasel->desx, simasel->desy, simasel->deex-4, simasel->deey);
+
+ i = simasel->dirsli_lines;
+ if (i > simasel->totaldirs) i = simasel->totaldirs;
+ for(;i > 0; i--){
+ strcpy(naam, direntry->name);
+
+ cpack(0xFFFFFF);
+ if (direntry->selected == 1){
+ cpack(0x7777CC);
+ glRecti(simasel->desx+2, sy-4, simasel->deex-4, sy+IMALINESIZE-4);
+ cpack(0xFFFFFF);
+ }
+ if (direntry->hilite == 1){
+ cpack(0x999999);
+ glRecti(simasel->desx+2, sy-4, simasel->deex-4, sy+IMALINESIZE-4);
+ cpack(0xFFFFFF);
+ }
+
+ glRasterPos2i(sx, sy);
+ BMF_DrawString(G.font, naam);
+
+ direntry = direntry->next;
+ sy-=IMALINESIZE;
+ }
+ areaview();
+
+ }
+
+ /* status icons */
+
+ sx = simasel->desx;
+ sy = simasel->deey+6;
+
+ glRasterPos2f(sx+16*0, sy);
+ if (bitset(simasel->fase, IMS_FOUND_BIP)) {
+ BIF_draw_icon(ICON_BPIBFOLDER_HLT);
+ } else if (bitset(simasel->fase, IMS_WRITE_NO_BIP)) {
+ BIF_draw_icon(ICON_BPIBFOLDER_DEHLT);
+ } else {
+ BIF_draw_icon(ICON_BPIBFOLDER_DEHLT);
+ }
+
+ glRasterPos2f(sx+16*1, sy);
+ if (bitset(simasel->fase, IMS_KNOW_INF)) {
+ BIF_draw_icon(ICON_FOLDER_HLT);
+ } else {
+ BIF_draw_icon(ICON_FOLDER_DEHLT);
+ }
+
+ glRasterPos2f(sx+16*2, sy);
+ if (bitset(simasel->fase, IMS_KNOW_IMA)) {
+ BIF_draw_icon(ICON_BLUEIMAGE_HLT);
+ } else {
+ BIF_draw_icon(ICON_BLUEIMAGE_DEHLT);
+ }
+ }
+
+ if (simasel->fesx > 0) {
+ int extrabutsize;
+
+ cpack(C_DARK);
+
+ glRecti(simasel->fssx, simasel->fssy, simasel->fsex, simasel->fsey);
+
+ glRecti(simasel->fesx, simasel->fesy, simasel->feex, simasel->feey);
+
+ uiEmboss(simasel->fssx-1, simasel->fssy-1, simasel->fsex+1, simasel->fsey+1,1);
+ uiEmboss(simasel->fesx-1, simasel->fesy-1, simasel->feex+1, simasel->feey+1,1);
+
+ if (simasel->imasli == 1){
+ sx = simasel->imasli_sx;
+ sy = simasel->imasli_ey - simasel->imasli_h;
+ ex = simasel->imasli_ex;
+ ey = simasel->imasli_ey;
+
+ cpack(C_BACK);
+
+ glRecti(sx, sy, ex, ey);
+ uiEmboss(sx, sy, ex, ey, 1);
+ }
+
+ info = 0;
+ strcpy(infostr, "");
+ if (simasel->totalima){
+ viewgate(simasel->fesx, simasel->fesy, simasel->feex, simasel->feey);
+
+ ima = simasel->first_sel_ima;
+
+ while (ima){
+ sc = 0;
+
+ sx = ima->sx- 6; sy = ima->sy-20 + sc;
+ ex = ima->sx+71; ey = ima->sy+70 + sc;
+
+ if(ima->selected == 1){
+ cpack(0xCC6666);
+ glRecti(sx, sy, ex, ey);
+ }
+ if(ima->selectable == 1){
+ if (ima->selected ) cpack(0xEE8888); else cpack(0x999999);
+
+ if (((simasel->mode & 8) != 8) && (simasel->hilite_ima == ima)){
+ glRecti(sx, sy, ex, ey); uiEmboss(sx,sy, ex,ey, 1);
+ }
+ if (ima->disksize/1000 > 1000){ sprintf(infostr, "%s %.2fMb x%i y%i %i bits ",ima->file_name,(ima->disksize/1024)/1024.0, ima->orgx, ima->orgy, ima->orgd);
+ }else{ sprintf(infostr, "%s %dKb x%i y%i %i bits ", ima->file_name,ima->disksize/1024, ima->orgx, ima->orgy, ima->orgd);
+ }
+ if (ima->anim == 1){ strcat (infostr, "movie"); }else{
+ str_image_type(ima->ibuf_type, naam);
+ strcat (infostr, naam);
+ }
+ info = 1;
+ }
+
+ sx = ima->sx; sy = ima->sy + sc;
+ ex = ima->ex; ey = ima->ey + sc;
+
+ if (ima->anim == 0) cpack(C_DARK); else cpack(C_DERK);
+
+ glRecti(sx, sy, ex, ey);
+ uiEmboss(sx-1,sy-1, ex+1,ey+1, 1);
+
+ cpack(0);
+ strcpy(naam, ima->file_name);
+ naam[11] = 0;
+
+ glRasterPos2i(sx+32-BMF_GetStringWidth(G.fonts, naam) / 2 , sy-16);
+ BMF_DrawString(G.fonts, naam);
+
+ if ((ima) && (ima->pict) && (ima->pict->rect)){
+ if ( (ey > simasel->fesy) && (sy < simasel->feey)){
+ lrectwrite(sx, sy, ex-1, ey-1, ima->pict->rect);
+ }
+ }
+
+ ima = ima->next;
+ }
+
+ if ((simasel->mode & 8) == 8) { /* if loep */
+
+ if (bitset(simasel->fase, IMS_KNOW_IMA) && (simasel->hilite_ima)) {
+
+ ima = simasel->hilite_ima;
+ glPixelZoom(2.0, 2.0);
+
+ sx = ima->sx + (ima->ex - ima->sx)/2 - (ima->ex - ima->sx);
+ sy = ima->sy + (ima->ey - ima->sy)/2 - (ima->ey - ima->sy);
+
+ ex = sx + 2*(ima->ex - ima->sx);
+ ey = sy + 2*(ima->ey - ima->sy);
+
+ /* cpack(C_DERK); */
+ /* uiEmboss(sx-8,sy-8, ex+8,ey+8, 1); */
+ /* glRecti(sx-7, sy-7, ex+7, ey+7); */
+ uiEmboss(sx-1,sy-1, ex+1,ey+1, 0);
+
+ lrectwrite(sx, sy, sx+ (ima->ex - ima->sx)-1, sy+ (ima->ey - ima->sy)-1, ima->pict->rect);
+
+ glPixelZoom(1.0, 1.0);
+ }
+ }
+ areaview(); /* reset viewgate */
+ }
+
+
+ /* INFO */
+ if (simasel->infsx > 0){
+ cpack(C_DARK);
+
+ glRecti(simasel->infsx, simasel->infsy, simasel->infex, simasel->infey);
+ uiEmboss(simasel->infsx, simasel->infsy, simasel->infex, simasel->infey,1);
+
+ if ((info)&&(strlen(infostr) > 0)){
+
+ sx = curarea->winrct.xmin;
+ sy = curarea->winrct.ymin;
+
+ viewgate(simasel->infsx, simasel->infsy, simasel->infex, simasel->infey);
+
+ cpack(0xAAAAAA);
+ glRasterPos2i(simasel->infsx+4, simasel->infsy+6);
+ BMF_DrawString(G.font, infostr);
+
+ areaview(); /* reset viewgate */
+
+ }
+ }
+
+ extrabutsize= (simasel->returnfunc)?60:0;
+ if (simasel->dnw > extrabutsize+8) {
+ simasel->dnw-= extrabutsize;
+ uiDefBut(block, TEX, 1,"", simasel->dnsx, simasel->dnsy, simasel->dnw, simasel->dnh, simasel->dir, 0.0, (float)FILE_MAXFILE-1, 0, 0, "");
+ if (extrabutsize)
+ uiDefBut(block, BUT, 5, "Load", simasel->dnsx+simasel->dnw, simasel->dnsy, extrabutsize, 21, NULL, 0.0, 0.0, 0, 0, "Load the selected image");
+ }
+ if (simasel->fnw > extrabutsize+8) {
+ simasel->fnw-= extrabutsize;
+ uiDefBut(block, TEX, 2,"", simasel->fnsx, simasel->fnsy, simasel->fnw, simasel->fnh, simasel->file, 0.0, (float)FILE_MAXFILE-1, 0, 0, "");
+ if (extrabutsize)
+ uiDefBut(block, BUT, 6, "Cancel", simasel->fnsx+simasel->fnw, simasel->fnsy, extrabutsize, 21, NULL, 0.0, 0.0, 0, 0, "Cancel image loading");
+ }
+ }
+
+ if (curarea->winx > 16) {
+ char *menu= fsmenu_build_menu();
+
+ uiDefBut(block, BUT, 13, "P", 8, (short)(curarea->winy-29), 20, 21, 0, 0, 0, 0, 0, "");
+ uiDefButS(block, MENU, 3 , menu, 8, (short)(curarea->winy-58), 20, 21, &simasel->fileselmenuitem, 0, 0, 0, 0, "");
+
+ MEM_freeN(menu);
+ }
+
+ uiDrawBlock(block);
+}
+
+void select_ima_files(SpaceImaSel *simasel)
+{
+ short set_reset;
+ short mval[2], oval[2];
+
+ set_reset = 1 - (simasel->hilite_ima->selected);
+
+ getmouseco_areawin(mval);
+ oval[0] = mval[0] + 1;
+
+ while(get_mbut()&R_MOUSE) {
+ getmouseco_areawin(mval);
+ if ((oval[0] != mval[0]) || (oval[1] != mval[1])){
+ simasel->mx = mval[0];
+ simasel->my = mval[1];
+
+ calc_hilite(simasel);
+
+ if (simasel->hilite_ima){
+ simasel->hilite_ima->selected = set_reset;
+ scrarea_do_windraw(curarea);
+ screen_swapbuffers();
+ }
+ oval[0] = mval[0];
+ oval[1] = mval[1];
+ }
+ }
+}
+
+void move_imadir_sli(SpaceImaSel *simasel)
+{
+
+ short mval[2], lval[2], fh;
+ float rh;
+
+ getmouseco_areawin(mval);
+
+ if ((mval[0] > simasel->dirsli_sx) &&
+ (mval[0] < simasel->dirsli_ex) &&
+ (mval[1] > simasel->dirsli_ey - simasel->dirsli_h) &&
+ (mval[1] < simasel->dirsli_ey) ){
+
+ /* extactly in the slider */
+ fh = simasel->dirsli_ey - mval[1];
+ lval[1]=1;
+ while(get_mbut()&L_MOUSE) {
+ getmouseco_areawin(mval);
+ if (mval[1] != lval[1]){
+
+ rh = (float)(simasel->dsey - mval[1] - fh - simasel->dssy) / (simasel->dsdh - simasel->dirsli_h);
+
+ simasel->topdir = 1 + rh * (simasel->totaldirs - simasel->dirsli_lines);
+
+ scrarea_do_windraw(curarea);
+ uiEmboss(simasel->dirsli_sx, simasel->dirsli_ey - simasel->dirsli_h,
+ simasel->dirsli_ex, simasel->dirsli_ey,1);
+ screen_swapbuffers();
+ lval[1] = mval[1];
+ }
+ }
+ }else{
+ if (mval[1] < simasel->dirsli_ey - simasel->dirsli_h)
+ simasel->topdir += (simasel->dirsli_lines - 1);
+ else
+ simasel->topdir -= (simasel->dirsli_lines - 1);
+
+ while(get_mbut()&L_MOUSE) { }
+ }
+}
+
+void move_imafile_sli(SpaceImaSel *simasel)
+{
+ short mval[2], cmy, omy = 0;
+ short ssl, sdh, ssv;
+
+ getmouseco_areawin(mval);
+ cmy = mval[1];
+
+ if ((mval[0] > simasel->imasli_sx) &&
+ (mval[0] < simasel->imasli_ex) &&
+ (mval[1] > simasel->imasli_ey - simasel->imasli_h) &&
+ (mval[1] < simasel->imasli_ey) ){
+
+ ssv = simasel->fsey - simasel->imasli_ey - 2;
+
+ while(get_mbut() & L_MOUSE) {
+ getmouseco_areawin(mval);
+ if (mval[1] != omy){
+ sdh = simasel->fsdh - simasel->imasli_h;
+ ssl = cmy - mval[1] + ssv;
+
+ if (ssl < 0) { ssl = 0; }
+ if (ssl > sdh) { ssl = sdh; }
+
+ simasel->image_slider = ssl / (float)sdh;
+
+ scrarea_do_windraw(curarea);
+ uiEmboss(simasel->imasli_sx, simasel->imasli_ey - simasel->imasli_h,
+ simasel->imasli_ex, simasel->imasli_ey, 1);
+
+ screen_swapbuffers();
+ omy = mval[1];
+ }
+ }
+ }else{
+ while(get_mbut() & L_MOUSE) { }
+ }
+}
+
+void ima_select_all(SpaceImaSel *simasel)
+{
+ OneSelectableIma *ima;
+ int reselect = 0;
+
+ ima = simasel->first_sel_ima;
+ if (!ima) return;
+
+ while(ima){
+ if (ima->selected == 1) reselect = 1;
+ ima = ima->next;
+ }
+ ima = simasel->first_sel_ima;
+ if (reselect == 1){
+ while(ima){
+ ima->selected = 0;
+ ima = ima->next;
+ }
+ }else{
+ while(ima){
+ ima->selected = 1;
+ ima = ima->next;
+ }
+ }
+}
+
+void pibplay(SpaceImaSel *simasel)
+{
+ OneSelectableIma *ima;
+ int sx= 8, sy= 8;
+
+ ima = simasel->first_sel_ima;
+ if (!ima) return ;
+
+ sx = curarea->winrct.xmin + 8;
+ sy = curarea->winrct.ymin + 8;
+
+ while(!(get_mbut()&L_MOUSE)){
+ scrarea_do_windraw(curarea);
+
+ lrectwrite(sx, sy, sx+ima->dw-1, sy+ima->dh-1, ima->pict->rect);
+
+ ima = ima->next;
+ if (!ima) ima = simasel->first_sel_ima;
+ screen_swapbuffers();
+ }
+}
+
+
+
+/* ************** hoofdtekenfunktie ************** */
+
+void drawimasel() /* hoofdtekenfunktie */
+{
+ SpaceImaSel *simasel;
+ simasel= curarea->spacedata.first;
+
+ /* ortho: xmin xmax, ymin, ymax! */
+ myortho2(-0.5, (float)(curarea->winx)-0.5, -0.5, (float)(curarea->winy)-0.5);
+
+ if (simasel->fase == 0){
+ checkdir(simasel->dir);
+ clear_ima_dir(simasel);
+ }
+
+ if (!bitset(simasel->fase, IMS_KNOW_DIR)){
+ if(simasel->firstdir) free_ima_dir(simasel->firstdir);
+ if(simasel->firstfile) free_ima_dir(simasel->firstfile);
+ simasel->firstdir = 0;
+ simasel->firstfile = 0;
+
+ if (get_ima_dir(simasel->dir, IMS_DIR, &simasel->totaldirs, &simasel->firstdir) < 0){
+ /* error */
+ strcpy(simasel->dir, simasel->dor);
+ get_ima_dir(simasel->dir, IMS_DIR, &simasel->totaldirs, &simasel->firstdir);
+ }
+
+ if (get_ima_dir(simasel->dir, IMS_FILE, &simasel->totalfiles, &simasel->firstfile) < 0){
+ /* error */
+ strcpy(simasel->file, simasel->fole);
+ get_ima_dir(simasel->dir, IMS_FILE, &simasel->totalfiles, &simasel->firstfile);
+ }
+
+ simasel->topdir = 0;
+ simasel->topfile = 0;
+ simasel->fase |= IMS_KNOW_DIR;
+
+ check_for_pib(simasel);
+
+ strcpy(simasel->fole, simasel->file);
+ strcpy(simasel->dor, simasel->dir);
+ }
+
+ if (!bitset(simasel->fase, IMS_FOUND_BIP)){
+ /* Make the first Bip file ever in this directory */
+ if ( !bitset(simasel->fase, IMS_KNOW_INF)){
+ if (!bitset(simasel->fase, IMS_DOTHE_INF)){
+ if(simasel->first_sel_ima) free_sel_ima(simasel->first_sel_ima);
+ simasel->first_sel_ima = 0;
+ simasel->fase |= IMS_DOTHE_INF;
+ addafterqueue(curarea->win, AFTERIMASELIMA, 1);
+ }
+ }
+ }else{
+ if (!bitset(simasel->fase, IMS_KNOW_BIP)){
+ addafterqueue(curarea->win, AFTERPIBREAD, 1);
+ }
+ }
+
+ make_sima_area(simasel);
+ calc_hilite(simasel);
+ draw_sima_area(simasel);
+
+ curarea->win_swap= WIN_BACK_OK;
+}
+
diff --git a/source/blender/src/drawipo.c b/source/blender/src/drawipo.c
new file mode 100644
index 00000000000..95f391c2dab
--- /dev/null
+++ b/source/blender/src/drawipo.c
@@ -0,0 +1,1622 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 <math.h>
+
+#ifndef _WIN32
+#include <unistd.h>
+#else
+#include <io.h>
+#include "BLI_winstuff.h"
+#endif
+
+#include "BMF_Api.h"
+
+#include "BLI_blenlib.h"
+
+#include "DNA_curve_types.h"
+#include "DNA_ipo_types.h"
+#include "DNA_key_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_sequence_types.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_curve.h"
+#include "BKE_ipo.h"
+#include "BKE_global.h"
+
+#include "BIF_gl.h"
+#include "BIF_resources.h"
+#include "BIF_screen.h"
+#include "BIF_interface.h"
+#include "BIF_mywindow.h"
+#include "BIF_space.h"
+
+#include "BSE_drawipo.h"
+#include "BSE_view.h"
+#include "BSE_editipo.h"
+#include "BSE_editaction_types.h"
+#include "BSE_editnla_types.h"
+
+#include "mydevice.h"
+#include "interface.h"
+#include "ipo.h" /* retains old stuff */
+#include "blendef.h"
+
+/* local define... also used in editipo ... */
+#define ISPOIN(a, b, c) ( (a->b) && (a->c) )
+#define ISPOIN3(a, b, c, d) ( (a->b) && (a->c) && (a->d) )
+#define ISPOIN4(a, b, c, d, e) ( (a->b) && (a->c) && (a->d) && (a->e) )
+
+#define IPOBUTX 65
+#define IPOSTEP 35 /* minimum pixels per gridstep */
+
+static float ipogrid_dx, ipogrid_dy, ipogrid_startx, ipogrid_starty;
+static int ipomachtx, ipomachty;
+
+static int vertymin, vertymax, horxmin, horxmax; /* globals om LEFTMOUSE op scrollbar te testen */
+
+
+
+static void scroll_prstr(float x, float y, float val, char dir, int disptype)
+{
+ int len, macht;
+ char str[32];
+
+ if(dir=='v') {
+ macht= ipomachty;
+ if ELEM(disptype, IPO_DISPDEGR, IPO_DISPTIME) {
+ macht+=1;
+ val *= 10;
+ }
+ }
+ else macht= ipomachtx;
+
+ if (macht<=0) sprintf(str, "%.*f", 1-macht, val);
+ else sprintf(str, "%d", (int)val);
+
+ len= strlen(str);
+ if(dir=='h') x-= 4*len;
+ else y-= 4*len;
+
+ if(dir=='v' && disptype==IPO_DISPDEGR) {
+ str[len]= 186; /* Degree symbol */
+ str[len+1]= 0;
+ }
+
+ glRasterPos2f(x, y);
+ BMF_DrawString(G.fonts, str);
+}
+
+static void step_to_grid(float *step, int *macht)
+{
+ float loga, rem;
+
+ /* proberen step als 10e macht te schrijven */
+
+ loga= log10(*step);
+ *macht= (int)(loga);
+
+ rem= loga- *macht;
+ rem= pow(10.0, rem);
+
+ if(loga<0.0) {
+ if(rem < 0.2) rem= 0.2;
+ else if(rem < 0.5) rem= 0.5;
+ else rem= 1.0;
+
+ *step= rem*pow(10.0, (float)*macht);
+ }
+ else {
+ if(rem < 2.0) rem= 2.0;
+ else if(rem < 5.0) rem= 5.0;
+ else rem= 10.0;
+
+ *step= rem*pow(10.0, (float)*macht);
+
+ (*macht)++;
+ }
+
+}
+
+void calc_ipogrid()
+{
+ float space, pixels;
+
+ /* regel: gridstep is minimaal IPOSTEP pixels */
+ /* hoe groot zijn IPOSTEP pixels? */
+
+ if(G.v2d==0) return;
+
+ space= G.v2d->cur.xmax - G.v2d->cur.xmin;
+ pixels= G.v2d->mask.xmax-G.v2d->mask.xmin;
+
+ ipogrid_dx= IPOSTEP*space/pixels;
+ step_to_grid(&ipogrid_dx, &ipomachtx);
+
+ if ELEM(curarea->spacetype, SPACE_SEQ, SPACE_SOUND) {
+ if(ipogrid_dx < 0.1) ipogrid_dx= 0.1;
+ ipomachtx-= 2;
+ if(ipomachtx<-2) ipomachtx= -2;
+ }
+
+ space= (G.v2d->cur.ymax - G.v2d->cur.ymin);
+ pixels= curarea->winy;
+ ipogrid_dy= IPOSTEP*space/pixels;
+ step_to_grid(&ipogrid_dy, &ipomachty);
+
+ if ELEM(curarea->spacetype, SPACE_SEQ, SPACE_SOUND) {
+ if(ipogrid_dy < 1.0) ipogrid_dy= 1.0;
+ if(ipomachty<1) ipomachty= 1;
+ }
+
+ ipogrid_startx= G.v2d->cur.xmin-fmod(G.v2d->cur.xmin, ipogrid_dx);
+ if(G.v2d->cur.xmin<0.0) ipogrid_startx-= ipogrid_dx;
+ ipogrid_starty= (G.v2d->cur.ymin-fmod(G.v2d->cur.ymin, ipogrid_dy));
+ if(G.v2d->cur.ymin<0.0) ipogrid_starty-= ipogrid_dy;
+
+}
+
+void draw_ipogrid(void)
+{
+ float vec1[2], vec2[2];
+ int a, step;
+
+ vec1[0]= vec2[0]= ipogrid_startx;
+ vec1[1]= ipogrid_starty;
+ vec2[1]= G.v2d->cur.ymax;
+
+ step= (G.v2d->mask.xmax-G.v2d->mask.xmin+1)/IPOSTEP;
+
+ if(curarea->spacetype==SPACE_SOUND) glColor3ub(0x70, 0x70, 0x60);
+ else glColor3ub(0x40, 0x40, 0x40);
+
+ for(a=0; a<step; a++) {
+ glBegin(GL_LINE_STRIP);
+ glVertex2fv(vec1); glVertex2fv(vec2);
+ glEnd();
+ vec2[0]= vec1[0]+= ipogrid_dx;
+ }
+
+ vec2[0]= vec1[0]-= 0.5*ipogrid_dx;
+
+ if(curarea->spacetype==SPACE_SOUND) glColor3ub(0x80, 0x80, 0x70);
+ else glColor3ub(0x50, 0x50, 0x50);
+
+ step++;
+ for(a=0; a<=step; a++) {
+ glBegin(GL_LINE_STRIP);
+ glVertex2fv(vec1); glVertex2fv(vec2);
+ glEnd();
+ vec2[0]= vec1[0]-= ipogrid_dx;
+ }
+
+ if(curarea->spacetype!=SPACE_SOUND && curarea->spacetype!=SPACE_ACTION && curarea->spacetype!=SPACE_NLA) {
+ vec1[0]= ipogrid_startx;
+ vec1[1]= vec2[1]= ipogrid_starty;
+ vec2[0]= G.v2d->cur.xmax;
+
+ step= (curarea->winy+1)/IPOSTEP;
+
+ glColor3ub(0x40, 0x40, 0x40);
+ for(a=0; a<=step; a++) {
+ glBegin(GL_LINE_STRIP);
+ glVertex2fv(vec1); glVertex2fv(vec2);
+ glEnd();
+ vec2[1]= vec1[1]+= ipogrid_dy;
+ }
+ vec2[1]= vec1[1]-= 0.5*ipogrid_dy;
+ step++;
+
+ if(curarea->spacetype==SPACE_IPO) {
+ glColor3ub(0x50, 0x50, 0x50);
+ for(a=0; a<step; a++) {
+ glBegin(GL_LINE_STRIP);
+ glVertex2fv(vec1); glVertex2fv(vec2);
+ glEnd();
+ vec2[1]= vec1[1]-= ipogrid_dy;
+ }
+ }
+ }
+
+ glColor3ub(0, 0, 0);
+
+ if (curarea->spacetype!=SPACE_ACTION && curarea->spacetype!=SPACE_NLA)
+ { /* Horizontal axis */
+ vec1[0]= G.v2d->cur.xmin;
+ vec2[0]= G.v2d->cur.xmax;
+ vec1[1]= vec2[1]= 0.0;
+ glBegin(GL_LINE_STRIP);
+
+ glVertex2fv(vec1);
+ glVertex2fv(vec2);
+
+ glEnd();
+ }
+
+ /* Vertical axis */
+
+ vec1[1]= G.v2d->cur.ymin;
+ vec2[1]= G.v2d->cur.ymax;
+ vec1[0]= vec2[0]= 0.0;
+ glBegin(GL_LINE_STRIP);
+ glVertex2fv(vec1); glVertex2fv(vec2);
+ glEnd();
+
+ /* Limits box */
+ if(curarea->spacetype==SPACE_IPO) {
+ if(G.sipo->blocktype==ID_SEQ) {
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ glRectf(0.0, 0.0, 100.0, 1.0);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ }
+ else if(ELEM(G.sipo->blocktype, ID_CU, IPO_CO)) {
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ glRectf(0.0, 1.0, G.v2d->cur.xmax, 1.0);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ }
+ }
+}
+
+void areamouseco_to_ipoco(View2D *v2d, short *mval, float *x, float *y)
+{
+ float div, ofs;
+
+ div= v2d->mask.xmax-v2d->mask.xmin;
+ ofs= v2d->mask.xmin;
+
+ *x= v2d->cur.xmin+ (v2d->cur.xmax-v2d->cur.xmin)*(mval[0]-ofs)/div;
+
+ div= v2d->mask.ymax-v2d->mask.ymin;
+ ofs= v2d->mask.ymin;
+
+ *y= v2d->cur.ymin+ (v2d->cur.ymax-v2d->cur.ymin)*(mval[1]-ofs)/div;
+}
+
+void ipoco_to_areaco(View2D *v2d, float *vec, short *mval)
+{
+ float x, y;
+
+ mval[0]= 3200;
+
+ x= (vec[0] - v2d->cur.xmin)/(v2d->cur.xmax-v2d->cur.xmin);
+ y= (vec[1] - v2d->cur.ymin)/(v2d->cur.ymax-v2d->cur.ymin);
+
+ if(x>=0.0 && x<=1.0) {
+ if(y>=0.0 && y<=1.0) {
+ mval[0]= v2d->mask.xmin + x*(v2d->mask.xmax-v2d->mask.xmin);
+ mval[1]= v2d->mask.ymin + y*(v2d->mask.ymax-v2d->mask.ymin);
+ }
+ }
+}
+
+void ipoco_to_areaco_noclip(View2D *v2d, float *vec, short *mval)
+{
+ float x, y;
+
+ x= (vec[0] - v2d->cur.xmin)/(v2d->cur.xmax-v2d->cur.xmin);
+ y= (vec[1] - v2d->cur.ymin)/(v2d->cur.ymax-v2d->cur.ymin);
+
+ x= v2d->mask.xmin + x*(v2d->mask.xmax-v2d->mask.xmin);
+ y= v2d->mask.ymin + y*(v2d->mask.ymax-v2d->mask.ymin);
+
+ if(x<-32760) mval[0]= -32760;
+ else if(x>32760) mval[0]= 32760;
+ else mval[0]= x;
+
+ if(y<-32760) mval[1]= -32760;
+ else if(y>32760) mval[1]= 32760;
+ else mval[1]= y;
+}
+
+int in_ipo_buttons(void)
+{
+ short mval[2];
+
+ getmouseco_areawin(mval);
+
+ if(mval[0]< G.v2d->mask.xmax) return 0;
+ else return 1;
+}
+
+
+void test_view2d(View2D *v2d, int winx, int winy)
+{
+ /* cur mag niet groter dan max, kleiner dan min of buiten tot vallen */
+ rctf *cur, *tot;
+ float dx, dy, temp, fac, zoom;
+
+ cur= &v2d->cur;
+ tot= &v2d->tot;
+
+ dx= cur->xmax-cur->xmin;
+ dy= cur->ymax-cur->ymin;
+
+
+ /* Reevan's test */
+ if (v2d->keepzoom & V2D_LOCKZOOM_Y)
+ v2d->cur.ymax=v2d->cur.ymin+((float)winy);
+
+ if (v2d->keepzoom & V2D_LOCKZOOM_X)
+ v2d->cur.xmax=v2d->cur.xmin+((float)winx);
+
+ if(v2d->keepzoom & V2D_KEEPZOOM) {
+ /* niet op min/max testen: ahv curarea de zoom fixeren */
+ zoom= ((float)winx)/dx;
+
+ if(zoom<v2d->minzoom || zoom>v2d->maxzoom) {
+ if(zoom<v2d->minzoom) fac= zoom/v2d->minzoom;
+ else fac= zoom/v2d->maxzoom;
+
+ dx*= fac;
+ temp= 0.5*(cur->xmax+cur->xmin);
+
+ cur->xmin= temp-0.5*dx;
+ cur->xmax= temp+0.5*dx;
+ }
+
+ zoom= ((float)winy)/dy;
+
+ if(zoom<v2d->minzoom || zoom>v2d->maxzoom) {
+ if(zoom<v2d->minzoom) fac= zoom/v2d->minzoom;
+ else fac= zoom/v2d->maxzoom;
+
+ dy*= fac;
+ temp= 0.5*(cur->ymax+cur->ymin);
+ cur->ymin= temp-0.5*dy;
+ cur->ymax= temp+0.5*dy;
+ }
+
+
+ }
+
+ else{
+
+ /* end test */
+
+ if(dx<v2d->min[0]) {
+ dx= v2d->min[0];
+ temp= 0.5*(cur->xmax+cur->xmin);
+ cur->xmin= temp-0.5*dx;
+ cur->xmax= temp+0.5*dx;
+ }
+ else if(dx>v2d->max[0]) {
+ dx= v2d->max[0];
+ temp= 0.5*(cur->xmax+cur->xmin);
+ cur->xmin= temp-0.5*dx;
+ cur->xmax= temp+0.5*dx;
+ }
+
+ if(dy<v2d->min[1]) {
+ dy= v2d->min[1];
+ temp= 0.5*(cur->ymax+cur->ymin);
+ cur->ymin= temp-0.5*dy;
+ cur->ymax= temp+0.5*dy;
+ }
+ else if(dy>v2d->max[1]) {
+ dy= v2d->max[1];
+ temp= 0.5*(cur->ymax+cur->ymin);
+ cur->ymin= temp-0.5*dy;
+ cur->ymax= temp+0.5*dy;
+ }
+
+ }
+
+
+
+
+ if(v2d->keeptot) {
+ dx= cur->xmax-cur->xmin;
+ dy= cur->ymax-cur->ymin;
+
+ if(dx > tot->xmax-tot->xmin) {
+ if(v2d->keepzoom==0) {
+ if(cur->xmin<tot->xmin) cur->xmin= tot->xmin;
+ if(cur->xmax>tot->xmax) cur->xmax= tot->xmax;
+ }
+ else {
+ if(cur->xmax < tot->xmax) {
+ dx= tot->xmax-cur->xmax;
+ cur->xmin+= dx;
+ cur->xmax+= dx;
+ }
+ else if(cur->xmin > tot->xmin) {
+ dx= cur->xmin-tot->xmin;
+ cur->xmin-= dx;
+ cur->xmax-= dx;
+ }
+ }
+ }
+ else {
+ if(cur->xmin < tot->xmin) {
+ dx= tot->xmin-cur->xmin;
+ cur->xmin+= dx;
+ cur->xmax+= dx;
+ }
+ else if(cur->xmax > tot->xmax) {
+ dx= cur->xmax-tot->xmax;
+ cur->xmin-= dx;
+ cur->xmax-= dx;
+ }
+ }
+
+ if(dy > tot->ymax-tot->ymin) {
+ if(v2d->keepzoom==0) {
+ if(cur->ymin<tot->ymin) cur->ymin= tot->ymin;
+ if(cur->ymax>tot->ymax) cur->ymax= tot->ymax;
+ }
+ else {
+ if(cur->ymax < tot->ymax) {
+ dy= tot->ymax-cur->ymax;
+ cur->ymin+= dy;
+ cur->ymax+= dy;
+ }
+ else if(cur->ymin > tot->ymin) {
+ dy= cur->ymin-tot->ymin;
+ cur->ymin-= dy;
+ cur->ymax-= dy;
+ }
+ }
+ }
+ else {
+ if(cur->ymin < tot->ymin) {
+ dy= tot->ymin-cur->ymin;
+ cur->ymin+= dy;
+ cur->ymax+= dy;
+ }
+ else if(cur->ymax > tot->ymax) {
+ dy= cur->ymax-tot->ymax;
+ cur->ymin-= dy;
+ cur->ymax-= dy;
+ }
+ }
+ }
+
+ if(v2d->keepaspect) {
+ dx= (cur->ymax-cur->ymin)/(cur->xmax-cur->xmin);
+ dy= ((float)winy)/((float)winx);
+
+ /* dx/dy is de totale aspect */
+
+ /* this exception is for buttons...keepzoom doesnt work proper */
+ if(v2d->keepzoom) fac= dy;
+ else fac= dx/dy;
+
+ if(fac>1.0) {
+
+ /* portrait window: x corrigeren */
+ dx= cur->ymax-cur->ymin;
+ temp= (cur->xmax+cur->xmin);
+
+ cur->xmin= temp/2.0 - 0.5*dx/dy;
+ cur->xmax= temp/2.0 + 0.5*dx/dy;
+ }
+ else {
+ dx= cur->xmax-cur->xmin;
+ temp= (cur->ymax+cur->ymin);
+
+ cur->ymin= temp/2.0 - 0.5*dy*dx;
+ cur->ymax= temp/2.0 + 0.5*dy*dx;
+ }
+ }
+}
+
+void calc_scrollrcts(View2D *v2d, int winx, int winy)
+{
+ v2d->mask.xmin= v2d->mask.ymin= 0;
+ v2d->mask.xmax= winx;
+ v2d->mask.ymax= winy;
+
+ if(curarea->spacetype==SPACE_ACTION) {
+ v2d->mask.xmin+= ACTWIDTH;
+ v2d->hor.xmin+=ACTWIDTH;
+ }
+ else if(curarea->spacetype==SPACE_NLA){
+ v2d->mask.xmin+= NLAWIDTH;
+ v2d->hor.xmin+=NLAWIDTH;
+ }
+ else if(curarea->spacetype==SPACE_IPO) {
+ v2d->mask.xmax-= IPOBUTX;
+
+ if(v2d->mask.xmax<IPOBUTX)
+ v2d->mask.xmax= winx;
+ }
+
+ if(v2d->scroll) {
+ if(v2d->scroll & L_SCROLL) {
+ v2d->vert= v2d->mask;
+ v2d->vert.xmax= SCROLLB;
+ v2d->mask.xmin= SCROLLB+1;
+ }
+ else if(v2d->scroll & R_SCROLL) {
+ v2d->vert= v2d->mask;
+ v2d->vert.xmin= v2d->vert.xmax-SCROLLB;
+ v2d->mask.xmax= v2d->vert.xmin-1;
+ }
+
+ if(v2d->scroll & B_SCROLL) {
+ v2d->hor= v2d->mask;
+ v2d->hor.ymax= SCROLLH;
+ v2d->mask.ymin= SCROLLH+1;
+ }
+ else if(v2d->scroll & T_SCROLL) {
+ v2d->hor= v2d->mask;
+ v2d->hor.ymin= v2d->hor.ymax-SCROLLH;
+ v2d->mask.ymax= v2d->hor.ymin-1;
+ }
+ }
+}
+
+ /* draws a line in left vertical scrollbar at the given height */
+static void draw_solution_line(View2D *v2d, float h)
+{
+ float vec[2];
+ short mval[2];
+
+ vec[0]= v2d->cur.xmin;
+ vec[1]= h;
+ ipoco_to_areaco(v2d, vec, mval);
+ if(mval[0]!=3200) {
+ glBegin(GL_LINES);
+ glVertex2f(v2d->vert.xmin, mval[1]);
+ glVertex2f(v2d->vert.xmax, mval[1]);
+ glEnd();
+ }
+}
+
+static void draw_solution(SpaceIpo *sipo)
+{
+ View2D *v2d= &sipo->v2d;
+ EditIpo *ei;
+ int a;
+
+ if (!(v2d->scroll & VERT_SCROLL)) return;
+
+ ei= sipo->editipo;
+ for(a=0; a<sipo->totipo; a++, ei++) {
+ if ISPOIN(ei, flag & IPO_VISIBLE, icu) {
+ cpack(ei->col);
+
+ /* DISPBITS ipo's have 'multiple' values. */
+ if(ei->disptype==IPO_DISPBITS) {
+ int b, val= ei->icu->curval;
+
+ for (b=0; b<31; b++)
+ if (val & (1<<b))
+ draw_solution_line(v2d, b+1);
+ } else {
+ draw_solution_line(v2d, ei->icu->curval);
+ }
+ }
+ }
+}
+
+void drawscroll(int disptype)
+{
+ rcti vert, hor;
+ float fac, dfac, val, fac2, tim;
+ unsigned int dark, darker, light;
+
+ vert= (G.v2d->vert);
+ hor= (G.v2d->hor);
+
+ darker= 0x525252;
+ dark= 0x656565;
+ light= 0x989898;
+
+ cpack(dark);
+ if(G.v2d->scroll & HOR_SCROLL) {
+ glRecti(hor.xmin, hor.ymin, hor.xmax, hor.ymax);
+ glColor3ub(0, 0, 0);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glRecti(hor.xmin, hor.ymin, hor.xmax, hor.ymax); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+
+ /* slider */
+ fac= (G.v2d->cur.xmin- G.v2d->tot.xmin)/(G.v2d->tot.xmax-G.v2d->tot.xmin);
+ if(fac<0.0) fac= 0.0;
+ horxmin= hor.xmin+fac*(hor.xmax-hor.xmin) + 1;
+
+ fac= (G.v2d->cur.xmax- G.v2d->tot.xmin)/(G.v2d->tot.xmax-G.v2d->tot.xmin);
+ if(fac>1.0) fac= 1.0;
+ horxmax= hor.xmin+fac*(hor.xmax-hor.xmin) -1;
+
+ if(horxmin > horxmax-2) horxmin= horxmax-2;
+
+ glColor3ub(0x78, 0x78, 0x78);
+ glRecti(horxmin, hor.ymin+1, horxmax, hor.ymax-1);
+
+ cpack(light);
+ sdrawline(horxmin, hor.ymax-1, horxmax, hor.ymax-1); /* boven */
+ sdrawline(horxmin, hor.ymin+1, horxmin, hor.ymax-1); /* links */
+ cpack(darker);
+ sdrawline(horxmin, hor.ymin+1, horxmax, hor.ymin+1); /* onder */
+ sdrawline(horxmax, hor.ymin+1, horxmax, hor.ymax-1); /* rechts */
+
+ /* de cijfers: ipogrid_startx en -dx omzetten naar scroll coordinaten */
+ fac= (ipogrid_startx- G.v2d->cur.xmin)/(G.v2d->cur.xmax-G.v2d->cur.xmin);
+ fac= hor.xmin+fac*(hor.xmax-hor.xmin);
+
+ dfac= (ipogrid_dx)/(G.v2d->cur.xmax-G.v2d->cur.xmin);
+ dfac= dfac*(hor.xmax-hor.xmin);
+
+ glColor3ub(0, 0, 0);
+ val= ipogrid_startx;
+ while(fac < hor.xmax) {
+
+ if(curarea->spacetype==SPACE_SEQ) {
+ fac2= val/(float)G.scene->r.frs_sec;
+ tim= floor(fac2);
+ fac2= fac2-tim;
+ scroll_prstr(fac, 3.0+(float)(hor.ymin), tim+G.scene->r.frs_sec*fac2/100.0, 'h', disptype);
+ }
+ else if(curarea->spacetype==SPACE_SOUND) {
+ fac2= val/(float)G.scene->r.frs_sec;
+ scroll_prstr(fac, 3.0+(float)(hor.ymin), fac2, 'h', disptype);
+ }
+ else {
+ scroll_prstr(fac, 3.0+(float)(hor.ymin), val, 'h', disptype);
+ }
+
+ fac+= dfac;
+ val+= ipogrid_dx;
+ }
+ }
+ cpack(dark);
+ if(G.v2d->scroll & VERT_SCROLL) {
+ glRecti(vert.xmin, vert.ymin, vert.xmax, vert.ymax);
+ glColor3ub(0, 0, 0);
+
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glRecti(vert.xmin, vert.ymin, vert.xmax, vert.ymax); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+
+ /* slider */
+ fac= (G.v2d->cur.ymin- G.v2d->tot.ymin)/(G.v2d->tot.ymax-G.v2d->tot.ymin);
+ if(fac<0.0) fac= 0.0;
+ vertymin= vert.ymin+fac*(vert.ymax-vert.ymin) + 1;
+
+ fac= (G.v2d->cur.ymax- G.v2d->tot.ymin)/(G.v2d->tot.ymax-G.v2d->tot.ymin);
+ if(fac>1.0) fac= 1.0;
+ vertymax= vert.ymin+fac*(vert.ymax-vert.ymin) -1;
+
+ if(vertymin > vertymax-2) vertymin= vertymax-2;
+
+ glColor3ub(0x78, 0x78, 0x78);
+ glRecti(vert.xmin+1, vertymin, vert.xmax-1, vertymax);
+
+ cpack(light);
+
+ sdrawline(vert.xmin+1, vertymax, vert.xmax-1, vertymax); /* boven */
+ sdrawline(vert.xmin+1, vertymin, vert.xmin+1, vertymax); /* links */
+ cpack(darker);
+ sdrawline(vert.xmin+1, vertymin, vert.xmax-1, vertymin); /* onder */
+ sdrawline(vert.xmax-1, vertymin, vert.xmax-1, vertymax); /* rechts */
+
+ /* de cijfers: ipogrid_starty en -dy omzetten naar scroll coordinaten */
+ fac= (ipogrid_starty- G.v2d->cur.ymin)/(G.v2d->cur.ymax-G.v2d->cur.ymin);
+ fac= vert.ymin+SCROLLH+fac*(vert.ymax-vert.ymin-SCROLLH);
+
+ dfac= (ipogrid_dy)/(G.v2d->cur.ymax-G.v2d->cur.ymin);
+ dfac= dfac*(vert.ymax-vert.ymin-SCROLLH);
+
+ if(curarea->spacetype==SPACE_SEQ) {
+ glColor3ub(0, 0, 0);
+ val= ipogrid_starty;
+ fac+= 0.5*dfac;
+ while(fac < vert.ymax) {
+ scroll_prstr((float)(vert.xmax)-14.0, fac, val, 'v', disptype);
+ fac+= dfac;
+ val+= ipogrid_dy;
+ }
+ }
+ else if (curarea->spacetype==SPACE_NLA){
+ }
+ else if (curarea->spacetype==SPACE_ACTION){
+ /* No digits on vertical axis in action mode! */
+ }
+ else {
+ glColor3ub(0, 0, 0);
+ val= ipogrid_starty;
+ while(fac < vert.ymax) {
+ scroll_prstr((float)(vert.xmax)-3.0, fac, val, 'v', disptype);
+ fac+= dfac;
+ val+= ipogrid_dy;
+ }
+ }
+ }
+}
+
+static void draw_ipobuts(SpaceIpo *sipo)
+{
+ ScrArea *area= sipo->area;
+ View2D *v2d= &sipo->v2d;
+ uiBlock *block;
+ uiBut *but;
+ EditIpo *ei;
+ int a, y, sel, tot;
+ char naam[20];
+
+ if(area->winx<IPOBUTX) return;
+
+ if(sipo->butofs) {
+ tot= 30+IPOBUTY*sipo->totipo;
+ if(tot<area->winy) sipo->butofs= 0;
+ }
+
+ drawedge(v2d->mask.xmax+3, 0, v2d->mask.xmax+3, area->winy);
+ glColor3ub(0x7f, 0x70, 0x70);
+
+ glRects(v2d->mask.xmax+6, 0, area->winx, area->winy);
+
+ if(sipo->totipo==0) return;
+ if(sipo->editipo==0) return;
+
+ sprintf(naam, "ipowin %d", area->win);
+ block= uiNewBlock(&area->uiblocks, naam, UI_EMBOSSN, UI_HELV, area->win);
+ uiBlockSetCol(block, BUTRUST);
+
+ ei= sipo->editipo;
+ y= area->winy-30+sipo->butofs;
+ for(a=0; a<sipo->totipo; a++, ei++, y-=IPOBUTY) {
+
+ but= uiDefButI(block, TOG|BIT|a, a+1, ei->name, v2d->mask.xmax+18, y, IPOBUTX-15, IPOBUTY-1, &(sipo->rowbut), 0, 0, 0, 0, "");
+ /* XXXXX, is this, the sole caller
+ * of this function, really necessary?
+ */
+ uiButSetFlag(but, UI_TEXT_LEFT);
+
+ if(ei->icu) {
+ cpack(ei->col);
+
+ glRects(v2d->mask.xmax+8, y+2, v2d->mask.xmax+15, y+IPOBUTY-2);
+ sel= ei->flag & (IPO_SELECT + IPO_EDIT);
+
+ uiEmboss((float)(v2d->mask.xmax+8), (float)(y+2), (float)(v2d->mask.xmax+15), (float)(y+IPOBUTY-2), sel);
+ }
+
+ if(sipo->blocktype==ID_KE) {
+ Key *key= (Key *)sipo->from;
+ if(key==0 || key->type==KEY_NORMAL) break;
+ }
+ }
+ uiDrawBlock(block);
+}
+
+static void calc_ipoverts(SpaceIpo *sipo)
+{
+ View2D *v2d= &sipo->v2d;
+ EditIpo *ei;
+ BezTriple *bezt;
+ BPoint *bp;
+ int a, b;
+
+ ei= G.sipo->editipo;
+ for(a=0; a<sipo->totipo; a++, ei++) {
+ if ISPOIN(ei, flag & IPO_VISIBLE, icu) {
+ if(ei->icu->bezt) {
+ bezt= ei->icu->bezt;
+ b= ei->icu->totvert;
+ while(b--) {
+ ipoco_to_areaco(v2d, bezt->vec[0], bezt->s[0]);
+ ipoco_to_areaco(v2d, bezt->vec[1], bezt->s[1]);
+ ipoco_to_areaco(v2d, bezt->vec[2], bezt->s[2]);
+ bezt++;
+ }
+ }
+ else if(ei->icu->bp) {
+ bp= ei->icu->bp;
+ b= ei->icu->totvert;
+ while(b--) {
+ ipoco_to_areaco(v2d, bp->vec, bp->s);
+ bp++;
+ }
+ }
+ }
+ }
+}
+
+
+static void draw_ipovertices(int sel)
+{
+ EditIpo *ei;
+ BezTriple *bezt;
+ float v1[2];
+ unsigned int col;
+ int val, ok, nr, a, b;
+
+ if(G.f & G_PICKSEL) return;
+
+ glPointSize(3.0);
+ glBegin(GL_POINTS);
+
+ ei= G.sipo->editipo;
+ for(nr=0; nr<G.sipo->totipo; nr++, ei++) {
+ if ISPOIN(ei, flag & IPO_VISIBLE, icu) {
+
+ if(G.sipo->showkey) {
+ if(sel) col= 0xFFFFFF; else col= 0x0;
+ } else if(ei->flag & IPO_EDIT) {
+ if(sel) col= 0x77FFFF; else col= 0xFF70FF;
+ } else {
+ if(sel) col= 0xFFFFFF; else col= 0x0;
+ val= (ei->icu->flag & IPO_SELECT)!=0;
+ if(sel != val) continue;
+ }
+
+ cpack(col);
+
+ bezt= ei->icu->bezt;
+ a= ei->icu->totvert;
+ while(a--) {
+
+ if(ei->disptype==IPO_DISPBITS) {
+ ok= 0;
+ if(ei->flag & IPO_EDIT) {
+ if( (bezt->f2 & 1) == sel ) ok= 1;
+ }
+ else ok= 1;
+
+ if(ok) {
+ val= bezt->vec[1][1];
+ b= 0;
+ v1[0]= bezt->vec[1][0];
+
+ while(b<31) {
+ if(val & (1<<b)) {
+ v1[1]= b+1;
+ glVertex3fv(v1);
+ }
+ b++;
+ }
+ }
+ }
+ else {
+
+ if(ei->flag & IPO_EDIT) {
+ if(ei->icu->ipo==IPO_BEZ) {
+ if( (bezt->f1 & 1) == sel )
+ glVertex3fv(bezt->vec[0]);
+ if( (bezt->f3 & 1) == sel )
+ glVertex3fv(bezt->vec[2]);
+ }
+ if( (bezt->f2 & 1) == sel )
+ glVertex3fv(bezt->vec[1]);
+
+ }
+ else {
+ glVertex3fv(bezt->vec[1]);
+ }
+ }
+
+ bezt++;
+ }
+ }
+ }
+
+ glEnd();
+ glPointSize(1.0);
+}
+
+static void draw_ipohandles(int sel)
+{
+ extern unsigned int nurbcol[];
+ EditIpo *ei;
+ BezTriple *bezt;
+ float *fp;
+ unsigned int *col;
+ int a, b;
+
+ if(sel) col= nurbcol+4;
+ else col= nurbcol;
+
+ ei= G.sipo->editipo;
+ for(a=0; a<G.sipo->totipo; a++, ei++) {
+ if ISPOIN4(ei, flag & IPO_VISIBLE, flag & IPO_EDIT, icu, disptype!=IPO_DISPBITS) {
+ if(ei->icu->ipo==IPO_BEZ) {
+ bezt= ei->icu->bezt;
+ b= ei->icu->totvert;
+ while(b--) {
+
+ if( (bezt->f2 & 1)==sel) {
+ fp= bezt->vec[0];
+ cpack(col[bezt->h1]);
+
+ glBegin(GL_LINE_STRIP);
+ glVertex2fv(fp); glVertex2fv(fp+3);
+ glEnd();
+ cpack(col[bezt->h2]);
+
+ glBegin(GL_LINE_STRIP);
+ glVertex2fv(fp+3); glVertex2fv(fp+6);
+ glEnd();
+ }
+ else if( (bezt->f1 & 1)==sel) {
+ fp= bezt->vec[0];
+ cpack(col[bezt->h1]);
+
+ glBegin(GL_LINE_STRIP);
+ glVertex2fv(fp); glVertex2fv(fp+3);
+ glEnd();
+ }
+ else if( (bezt->f3 & 1)==sel) {
+ fp= bezt->vec[1];
+ cpack(col[bezt->h2]);
+
+ glBegin(GL_LINE_STRIP);
+ glVertex2fv(fp); glVertex2fv(fp+3);
+ glEnd();
+ }
+
+ bezt++;
+ }
+ }
+ }
+ }
+}
+
+int pickselcode;
+
+static void init_pickselcode(void)
+{
+ pickselcode= 1;
+}
+
+static void draw_ipocurves(int sel)
+{
+ EditIpo *ei;
+ IpoCurve *icu;
+ BezTriple *bezt, *prevbezt;
+ float *fp, fac, data[120], v1[2], v2[2], v3[2], v4[2];
+ float cycdx=0, cycdy=0, cycxofs, cycyofs;
+ int a, b, resol, cycount, val, nr;
+
+
+ ei= G.sipo->editipo;
+ for(nr=0; nr<G.sipo->totipo; nr++, ei++) {
+ if ISPOIN3(ei, flag & IPO_VISIBLE, icu, icu->bezt) {
+
+ if(G.f & G_PICKSEL) {
+ glLoadName(pickselcode++);
+ val= 1;
+ }
+ else {
+ val= (ei->flag & (IPO_SELECT+IPO_EDIT))!=0;
+ val= (val==sel);
+ }
+
+ if(val) {
+
+ cycyofs= cycxofs= 0.0;
+ cycount= 1;
+
+ icu= ei->icu;
+
+ /* curve */
+ if(G.sipo->showkey) glColor3ub(0, 0, 0); else cpack(ei->col);
+
+ /* cyclic */
+ if(icu->extrap & IPO_CYCL) {
+ cycdx= (icu->bezt+icu->totvert-1)->vec[1][0] - icu->bezt->vec[1][0];
+ cycdy= (icu->bezt+icu->totvert-1)->vec[1][1] - icu->bezt->vec[1][1];
+ if(cycdx>0.01) {
+
+ while(icu->bezt->vec[1][0]+cycxofs > G.v2d->cur.xmin) {
+ cycxofs-= cycdx;
+ if(icu->extrap & IPO_DIR) cycyofs-= cycdy;
+ cycount++;
+ }
+ bezt= icu->bezt+(icu->totvert-1);
+ fac= 0.0;
+ while(bezt->vec[1][0]+fac < G.v2d->cur.xmax) {
+ cycount++;
+ fac+= cycdx;
+ }
+ }
+ }
+
+ while(cycount--) {
+
+ if(ei->disptype==IPO_DISPBITS) {
+
+ /* lijnen */
+ cpack(ei->col);
+ bezt= icu->bezt;
+ a= icu->totvert;
+
+ while(a--) {
+ val= bezt->vec[1][1];
+ b= 0;
+
+ while(b<31) {
+ if(val & (1<<b)) {
+ v1[1]= b+1;
+
+ glBegin(GL_LINE_STRIP);
+ if(icu->extrap & IPO_CYCL) ;
+ else if(a==icu->totvert-1) {
+ v1[0]= G.v2d->cur.xmin+cycxofs;
+ glVertex2fv(v1);
+ }
+ v1[0]= bezt->vec[1][0]+cycxofs;
+ glVertex2fv(v1);
+
+ if(a) v1[0]= (bezt+1)->vec[1][0]+cycxofs;
+ else if(icu->extrap & IPO_CYCL) ;
+ else v1[0]= G.v2d->cur.xmax+cycxofs;
+
+ glVertex2fv(v1);
+ glEnd();
+ }
+ b++;
+ }
+ bezt++;
+ }
+
+ }
+ else {
+
+ b= icu->totvert-1;
+ prevbezt= icu->bezt;
+ bezt= prevbezt+1;
+
+ glBegin(GL_LINE_STRIP);
+
+ /* extrap naar links? */
+ if( (icu->extrap & IPO_CYCL)==0) {
+ if(prevbezt->vec[1][0] > G.v2d->cur.xmin) {
+ v1[0]= G.v2d->cur.xmin;
+ if(icu->extrap==IPO_HORIZ || icu->ipo==IPO_CONST) v1[1]= prevbezt->vec[1][1];
+ else {
+ fac= (prevbezt->vec[0][0]-prevbezt->vec[1][0])/(prevbezt->vec[1][0]-v1[0]);
+ if(fac!=0.0) fac= 1.0/fac;
+ v1[1]= prevbezt->vec[1][1]-fac*(prevbezt->vec[0][1]-prevbezt->vec[1][1]);
+ }
+ glVertex2fv(v1);
+ }
+ }
+
+ if(b==0) {
+ v1[0]= prevbezt->vec[1][0]+cycxofs;
+ v1[1]= prevbezt->vec[1][1]+cycyofs;
+ glVertex2fv(v1);
+ }
+
+ while(b--) {
+ if(icu->ipo==IPO_CONST) {
+ v1[0]= prevbezt->vec[1][0]+cycxofs;
+ v1[1]= prevbezt->vec[1][1]+cycyofs;
+ glVertex2fv(v1);
+ v1[0]= bezt->vec[1][0]+cycxofs;
+ v1[1]= prevbezt->vec[1][1]+cycyofs;
+ glVertex2fv(v1);
+ }
+ else if(icu->ipo==IPO_LIN) {
+ v1[0]= prevbezt->vec[1][0]+cycxofs;
+ v1[1]= prevbezt->vec[1][1]+cycyofs;
+ glVertex2fv(v1);
+ }
+ else {
+ resol= 3.0*sqrt(bezt->vec[1][0] - prevbezt->vec[1][0]);
+
+ if(resol<2) {
+ v1[0]= prevbezt->vec[1][0]+cycxofs;
+ v1[1]= prevbezt->vec[1][1]+cycyofs;
+ glVertex2fv(v1);
+ }
+ else {
+ if(resol>32) resol= 32;
+
+ v1[0]= prevbezt->vec[1][0]+cycxofs;
+ v1[1]= prevbezt->vec[1][1]+cycyofs;
+ v2[0]= prevbezt->vec[2][0]+cycxofs;
+ v2[1]= prevbezt->vec[2][1]+cycyofs;
+
+ v3[0]= bezt->vec[0][0]+cycxofs;
+ v3[1]= bezt->vec[0][1]+cycyofs;
+ v4[0]= bezt->vec[1][0]+cycxofs;
+ v4[1]= bezt->vec[1][1]+cycyofs;
+
+ correct_bezpart(v1, v2, v3, v4);
+
+ maakbez(v1[0], v2[0], v3[0], v4[0], data, resol);
+ maakbez(v1[1], v2[1], v3[1], v4[1], data+1, resol);
+
+ fp= data;
+ while(resol--) {
+ glVertex2fv(fp);
+ fp+= 3;
+ }
+ }
+ }
+ prevbezt= bezt;
+ bezt++;
+
+ /* laatste punt? */
+ if(b==0) {
+ v1[0]= prevbezt->vec[1][0]+cycxofs;
+ v1[1]= prevbezt->vec[1][1]+cycyofs;
+ glVertex2fv(v1);
+ }
+ }
+
+ /* extrap naar rechts? */
+ if( (icu->extrap & IPO_CYCL)==0) {
+ if(prevbezt->vec[1][0] < G.v2d->cur.xmax) {
+ v1[0]= G.v2d->cur.xmax;
+ if(icu->extrap==IPO_HORIZ || icu->ipo==IPO_CONST) v1[1]= prevbezt->vec[1][1];
+ else {
+ fac= (prevbezt->vec[2][0]-prevbezt->vec[1][0])/(prevbezt->vec[1][0]-v1[0]);
+ if(fac!=0.0) fac= 1.0/fac;
+ v1[1]= prevbezt->vec[1][1]-fac*(prevbezt->vec[2][1]-prevbezt->vec[1][1]);
+ }
+ glVertex2fv(v1);
+ }
+ }
+
+ glEnd();
+
+ }
+ cycxofs+= cycdx;
+ if(icu->extrap & IPO_DIR) cycyofs+= cycdy;
+ }
+
+ /* lijn die het einde van een snelheidscurve aangeeft */
+ if(G.sipo->blocktype==ID_CU && icu->adrcode==CU_SPEED) {
+ b= icu->totvert-1;
+ if(b) {
+ glColor3ub(0, 0, 0);
+ bezt= icu->bezt+b;
+ glBegin(GL_LINES);
+ glVertex2f(bezt->vec[1][0], 0.0);
+ glVertex2f(bezt->vec[1][0], bezt->vec[1][1]);
+ glEnd();
+ }
+ }
+ }
+ }
+ }
+}
+
+static void draw_cfra(SpaceIpo *sipo)
+{
+ View2D *v2d= &sipo->v2d;
+ Object *ob;
+ float vec[2];
+
+ vec[0]= (G.scene->r.cfra);
+ vec[0]*= G.scene->r.framelen;
+
+ vec[1]= v2d->cur.ymin;
+ glColor3ub(0x60, 0xc0, 0x40);
+ glLineWidth(2.0);
+
+ glBegin(GL_LINE_STRIP);
+ glVertex2fv(vec);
+ vec[1]= v2d->cur.ymax;
+ glVertex2fv(vec);
+ glEnd();
+
+ if(sipo->blocktype==ID_OB) {
+ ob= (G.scene->basact) ? (G.scene->basact->object) : 0;
+ if(ob && ob->sf!=0.0 && (ob->ipoflag & OB_OFFS_OB) ) {
+ vec[0]-= ob->sf;
+
+ glColor3ub(0x10, 0x60, 0);
+
+ glBegin(GL_LINE_STRIP);
+ glVertex2fv(vec);
+ vec[1]= G.v2d->cur.ymin;
+ glVertex2fv(vec);
+ glEnd();
+ }
+ }
+
+ glLineWidth(1.0);
+}
+
+static void draw_ipokey(SpaceIpo *sipo)
+{
+ IpoKey *ik;
+
+ glBegin(GL_LINES);
+ for (ik= sipo->ipokey.first; ik; ik= ik->next) {
+ if(ik->flag & 1) glColor3ub(0xFF, 0xFF, 0x99);
+ else glColor3ub(0xAA, 0xAA, 0x55);
+
+ glVertex2f(ik->val, G.v2d->cur.ymin);
+ glVertex2f(ik->val, G.v2d->cur.ymax);
+ }
+ glEnd();
+}
+
+static void draw_key(SpaceIpo *sipo, int visible)
+{
+ View2D *v2d= &sipo->v2d;
+ Key *key;
+ KeyBlock *kb, *act=NULL;
+ unsigned int col;
+
+ key= (Key *)sipo->from;
+ if(key==0)
+ return;
+
+ if(key->type== KEY_RELATIVE) if(visible==0) return;
+
+ kb= key->block.first;
+ while(kb) {
+ if(kb->type==KEY_LINEAR) setlinestyle(2);
+ else if(kb->type==KEY_BSPLINE) setlinestyle(4);
+ else setlinestyle(0);
+
+ if(kb==key->refkey) col= 0x22FFFF;
+ else col= 0xFFFF00;
+
+ if( (kb->flag & SELECT)==0) col-= 0x225500;
+ else act= kb;
+
+ cpack(col);
+
+ glBegin(GL_LINE_STRIP);
+ glVertex2f(v2d->cur.xmin, kb->pos);
+ glVertex2f(v2d->cur.xmax, kb->pos);
+ glEnd();
+
+ kb= kb->next;
+ }
+
+ if(act) {
+ if(act->type==KEY_LINEAR) setlinestyle(2);
+ else if(act->type==KEY_BSPLINE) setlinestyle(4);
+ else setlinestyle(0);
+
+ if(act==key->refkey) cpack(0x22FFFF);
+ else cpack(0xFFFF00);
+
+ glBegin(GL_LINE_STRIP);
+ glVertex2f(v2d->cur.xmin, act->pos);
+ glVertex2f(v2d->cur.xmax, act->pos);
+ glEnd();
+ }
+
+ setlinestyle(0);
+}
+
+void drawipo(void)
+{
+ SpaceIpo *sipo= curarea->spacedata.first;
+ View2D *v2d= &sipo->v2d;
+ EditIpo *ei;
+ int ofsx, ofsy, a, disptype;
+
+ v2d->hor.xmax+=IPOBUTX;
+ calc_scrollrcts(G.v2d, curarea->winx, curarea->winy);
+
+
+ if (sipo->pin)
+ glClearColor(.45, .40, .40, 0.0); // litepink
+ else
+ glClearColor(.45, .45, .45, 0.0);
+
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ if(curarea->winx>SCROLLB+10 && curarea->winy>SCROLLH+10) {
+ if(v2d->scroll) {
+ ofsx= curarea->winrct.xmin; // ivm mywin
+ ofsy= curarea->winrct.ymin;
+ glViewport(ofsx+v2d->mask.xmin, ofsy+v2d->mask.ymin, ( ofsx+v2d->mask.xmax-1)-(ofsx+v2d->mask.xmin)+1, ( ofsy+v2d->mask.ymax-1)-( ofsy+v2d->mask.ymin)+1);
+ glScissor(ofsx+v2d->mask.xmin, ofsy+v2d->mask.ymin, ( ofsx+v2d->mask.xmax-1)-(ofsx+v2d->mask.xmin)+1, ( ofsy+v2d->mask.ymax-1)-( ofsy+v2d->mask.ymin)+1);
+ }
+ }
+
+ test_editipo(); /* test of huidige editipo klopt, make_editipo zet de v2d->cur */
+
+ myortho2(v2d->cur.xmin, v2d->cur.xmax, v2d->cur.ymin, v2d->cur.ymax);
+
+
+ if(sipo->editipo) {
+
+ /* schaal corrigeren voor graden? */
+ disptype= -1;
+ ei= sipo->editipo;
+ for(a=0; a<sipo->totipo; a++, ei++) {
+ if(ei->flag & IPO_VISIBLE) {
+ if(disptype== -1) disptype= ei->disptype;
+ else if(disptype!=ei->disptype) disptype= 0;
+ }
+ }
+
+ calc_ipogrid();
+ draw_ipogrid();
+
+ calc_ipoverts(sipo);
+
+ draw_cfra(sipo);
+
+ /* ipokeys */
+ if(sipo->showkey) {
+ if(sipo->ipokey.first==0) make_ipokey();
+ draw_ipokey(sipo);
+ }
+
+ if(sipo->blocktype==ID_KE) {
+ ei= sipo->editipo;
+ draw_key(sipo, ei->flag & IPO_VISIBLE);
+ }
+
+ /* draw deselect */
+ draw_ipocurves(0);
+ draw_ipohandles(0);
+ draw_ipovertices(0);
+
+ /* draw select */
+ draw_ipocurves(1);
+ draw_ipohandles(1);
+ draw_ipovertices(1);
+
+ /* restore viewport */
+ mywinset(curarea->win);
+
+ if(curarea->winx>SCROLLB+10 && curarea->winy>SCROLLH+10) {
+
+ /* ortho op pixelnivo curarea */
+ myortho2(-0.5, curarea->winx+0.5, -0.5, curarea->winy+0.5);
+
+ if(v2d->scroll) {
+ drawscroll(disptype);
+ draw_solution(sipo);
+ }
+
+ draw_ipobuts(sipo);
+ }
+ }
+ else {
+ calc_ipogrid();
+ draw_ipogrid();
+ }
+
+ curarea->win_swap= WIN_BACK_OK;
+}
+
+void scroll_ipobuts()
+{
+ int tot;
+ short yo, mval[2];
+
+ tot= 30+IPOBUTY*G.sipo->totipo;
+ if(tot<curarea->winy) return;
+
+ getmouseco_areawin(mval);
+ yo= mval[1];
+
+ while(get_mbut()&M_MOUSE) {
+ getmouseco_areawin(mval);
+ if(mval[1]!=yo) {
+ G.sipo->butofs+= (mval[1]-yo);
+ if(G.sipo->butofs<0) G.sipo->butofs= 0;
+ else if(G.sipo->butofs+curarea->winy>tot) G.sipo->butofs= tot-curarea->winy;
+
+ scrarea_do_windraw(curarea);
+ screen_swapbuffers();
+
+ yo= mval[1];
+ }
+ else BIF_wait_for_statechange();
+ }
+}
+
+
+
+void view2dzoom()
+{
+ float fac, dx, dy;
+ short mval[2], mvalo[2];
+
+ areawinset(curarea->win); /* vanuit buttons */
+ curarea->head_swap= 0;
+ getmouseco_areawin(mvalo);
+
+ while(get_mbut()&(L_MOUSE|M_MOUSE)) {
+ getmouseco_areawin(mval);
+
+ if(mval[0]!=mvalo[0] || mval[1]!=mvalo[1]) {
+
+ fac= 0.001*(mval[0]-mvalo[0]);
+ dx= fac*(G.v2d->cur.xmax-G.v2d->cur.xmin);
+ fac= 0.001*(mval[1]-mvalo[1]);
+ dy= fac*(G.v2d->cur.ymax-G.v2d->cur.ymin);
+
+ G.v2d->cur.xmin+= dx;
+ G.v2d->cur.xmax-= dx;
+ if(curarea->spacetype!=SPACE_SEQ && curarea->spacetype!=SPACE_SOUND && curarea->spacetype!=SPACE_NLA && curarea->spacetype!=SPACE_ACTION) {
+ G.v2d->cur.ymin+= dy;
+ G.v2d->cur.ymax-= dy;
+ }
+
+ test_view2d(G.v2d, curarea->winx, curarea->winy); /* cur min max rects */
+ scrarea_do_windraw(curarea);
+ screen_swapbuffers();
+ }
+ else BIF_wait_for_statechange();
+ }
+}
+
+int view2dmove()
+{
+ /* return 1 als er iets gedaan is */
+ float facx=0.0, facy=0.0, dx, dy, left=1.0, right=1.0;
+ short mval[2], mvalo[2], leftret=1;
+
+ /* alles goedzetten */
+ scrarea_do_windraw(curarea);
+ curarea->head_swap= 0;
+
+
+ if(G.qual & LR_CTRLKEY) {
+ view2dzoom();
+ curarea->head_swap= 0;
+ return 0;
+ }
+
+ /* testen waar muis is */
+ getmouseco_areawin(mvalo);
+
+ if ELEM6(curarea->spacetype, SPACE_IPO, SPACE_SEQ, SPACE_OOPS, SPACE_SOUND, SPACE_ACTION, SPACE_NLA)
+ {
+ if( BLI_in_rcti(&G.v2d->mask, (int)mvalo[0], (int)mvalo[1]) ) {
+ facx= (G.v2d->cur.xmax-G.v2d->cur.xmin)/(float)(G.v2d->mask.xmax-G.v2d->mask.xmin);
+ facy= (G.v2d->cur.ymax-G.v2d->cur.ymin)/(float)(G.v2d->mask.ymax-G.v2d->mask.ymin);
+ }
+ else if(BLI_in_rcti(&G.v2d->vert, (int)mvalo[0], (int)mvalo[1])) {
+ facy= -(G.v2d->tot.ymax-G.v2d->tot.ymin)/(float)(G.v2d->mask.ymax-G.v2d->mask.ymin);
+ if(get_mbut()&L_MOUSE) {
+ /* welk deel van de scrollbar moet bewegen? */
+ if(mvalo[1]< (vertymin+vertymax)/2 ) right= 0.0;
+ else left= 0.0;
+ leftret= 0;
+ }
+ }
+ else if(BLI_in_rcti(&G.v2d->hor, (int)mvalo[0], (int)mvalo[1])) {
+ facx= -(G.v2d->tot.xmax-G.v2d->tot.xmin)/(float)(G.v2d->mask.xmax-G.v2d->mask.xmin);
+ if(get_mbut()&L_MOUSE) {
+ /* welk deel van de scrollbar moet bewegen? */
+ if(mvalo[0]< (horxmin+horxmax)/2 ) right= 0.0;
+ else left= 0.0;
+ leftret= 0;
+ }
+ }
+ }
+ else {
+ facx= (G.v2d->cur.xmax-G.v2d->cur.xmin)/(float)(curarea->winx);
+ facy= (G.v2d->cur.ymax-G.v2d->cur.ymin)/(float)(curarea->winy);
+ }
+
+
+ /* no y move in audio */
+ if(curarea->spacetype==SPACE_SOUND) facy= 0.0;
+
+ if(get_mbut()&L_MOUSE && leftret) return 0;
+ if(facx==0.0 && facy==0.0) return 1;
+
+ while(get_mbut()&(L_MOUSE|M_MOUSE)) {
+ getmouseco_areawin(mval);
+ if(mval[0]!=mvalo[0] || mval[1]!=mvalo[1]) {
+ dx= facx*(mvalo[0]-mval[0]);
+ dy= facy*(mvalo[1]-mval[1]);
+ G.v2d->cur.xmin+= left*dx;
+ G.v2d->cur.xmax+= right*dx;
+ G.v2d->cur.ymin+= left*dy;
+ G.v2d->cur.ymax+= right*dy;
+
+ test_view2d(G.v2d, curarea->winx, curarea->winy);
+
+ scrarea_do_windraw(curarea);
+ screen_swapbuffers();
+
+ mvalo[0]= mval[0];
+ mvalo[1]= mval[1];
+
+ }
+ else BIF_wait_for_statechange();
+ }
+ curarea->head_swap= 0;
+ return 1;
+}
+
+
+void view2dborder(void)
+{
+
+}
+
+EditIpo *select_proj_ipo(rctf *rectf, int event)
+{
+ EditIpo *ei;
+ float xmin, ymin, xmax, ymax;
+ /* this was IGLuint, but it's a useless typedef... */
+ GLuint buffer[MAXPICKBUF];
+ int a, b;
+ int code, hits;
+ short mval[2];
+
+ G.f |= G_PICKSEL;
+
+ if(rectf==0) {
+ getmouseco_areawin(mval);
+
+ mval[0]-= 6; mval[1]-= 6;
+ areamouseco_to_ipoco(G.v2d, mval, &xmin, &ymin);
+ mval[0]+= 12; mval[1]+= 12;
+ areamouseco_to_ipoco(G.v2d, mval, &xmax, &ymax);
+
+ myortho2(xmin, xmax, ymin, ymax);
+ }
+ else myortho2(rectf->xmin, rectf->xmax, rectf->ymin, rectf->ymax);
+
+ glSelectBuffer( MAXPICKBUF, buffer);
+ glRenderMode(GL_SELECT);
+ glInitNames(); /* deze twee fies zijn waarvoor? Anders werkt het niet */
+ glPushName(-1);
+
+ init_pickselcode(); /* drawipo.c */
+ draw_ipocurves(0);
+
+ G.f -= G_PICKSEL;
+
+ hits= glRenderMode(GL_RENDER);
+ glPopName(); /* zie boven (pushname) */
+ if(hits<1) return 0;
+
+ code= 1;
+ ei= G.sipo->editipo;
+ for(a=0; a<G.sipo->totipo; a++, ei++) {
+ if ISPOIN(ei, icu, flag & IPO_VISIBLE) {
+ if(rectf) {
+ for(b=0; b<hits; b++) {
+ /* conversion for glSelect */
+ if(code == buffer[ (4 * b) + 3] ) {
+ if(event==LEFTMOUSE) ei->flag |= IPO_SELECT;
+ else ei->flag &= ~IPO_SELECT;
+ ei->icu->flag= ei->flag;
+ }
+ }
+ }
+ else {
+ /* also conversion for glSelect */
+ if(code==buffer[ 3 ]) return ei;
+ }
+ code++;
+ }
+ }
+ return 0;
+}
+
diff --git a/source/blender/src/drawmesh.c b/source/blender/src/drawmesh.c
new file mode 100644
index 00000000000..805dbe84693
--- /dev/null
+++ b/source/blender/src/drawmesh.c
@@ -0,0 +1,999 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 <string.h>
+#include <math.h>
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+
+#include "IMB_imbuf_types.h"
+
+#include "DNA_image_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_material_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+#include "DNA_property_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_view3d_types.h"
+
+#include "BKE_bmfont.h"
+#include "BKE_main.h"
+#include "BKE_mesh.h"
+#include "BKE_image.h"
+#include "BKE_property.h"
+#include "BKE_global.h"
+#include "BKE_displist.h"
+#include "BKE_object.h"
+#include "BKE_material.h"
+
+#include "BIF_gl.h"
+#include "BIF_mywindow.h"
+
+#include "BDR_editface.h"
+#include "BDR_vpaint.h"
+#include "BDR_drawmesh.h"
+
+#include "BSE_drawview.h"
+
+#include "blendef.h"
+#include "nla.h"
+
+//#include "glext.h"
+/* some local functions */
+static void draw_hide_tfaces(Object *ob, Mesh *me);
+
+#if defined(GL_EXT_texture_object) && !defined(__sun__) && !defined(__APPLE__)
+
+ /* exception for mesa... not according th opengl specs */
+ #ifndef __linux__
+ #define glBindTexture(A,B) glBindTextureEXT(A,B)
+ #endif
+
+ #define glGenTextures(A,B) glGenTexturesEXT(A,B)
+ #define glDeleteTextures(A,B) glDeleteTexturesEXT(A,B)
+ #define glPolygonOffset(A,B) glPolygonOffsetEXT(A,B)
+
+#else
+
+/* #define GL_FUNC_ADD_EXT GL_FUNC_ADD */
+/* #define GL_FUNC_REVERSE_SUBTRACT_EXT GL_FUNC_REVERSE_SUBTRACT */
+/* #define GL_POLYGON_OFFSET_EXT GL_POLYGON_OFFSET */
+
+#endif
+
+ /* (n&(n-1)) zeros the least significant bit of n */
+static int is_pow2(int num) {
+ return ((num)&(num-1))==0;
+}
+static int smaller_pow2(int num) {
+ while (!is_pow2(num))
+ num= num&(num-1);
+ return num;
+}
+
+static int fCurtile=0, fCurmode=0,fCurtileXRep=0,fCurtileYRep=0;
+static Image *fCurpage=0;
+static short fTexwindx, fTexwindy, fTexwinsx, fTexwinsy;
+static int fDoMipMap = 1;
+static int fLinearMipMap = 0;
+
+/* static int source, dest; also not used */
+
+/**
+ * Enables or disable mipmapping for realtime images.
+ * @param mipmap Turn mipmapping on (mipmap!=0) or off (mipmap==0).
+ */
+void set_mipmap(int mipmap)
+{
+ if (fDoMipMap != (mipmap != 0)) {
+ free_all_realtime_images();
+ fDoMipMap = mipmap != 0;
+ }
+}
+
+
+/**
+ * Returns the current setting for mipmapping.
+ */
+int get_mipmap(void)
+{
+ return fDoMipMap;
+}
+
+/**
+ * Enables or disable linear mipmap setting for realtime images (textures).
+ * Note that this will will destroy all texture bindings in OpenGL.
+ * @see free_realtime_image()
+ * @param mipmap Turn linear mipmapping on (linear!=0) or off (linear==0).
+ */
+void set_linear_mipmap(int linear)
+{
+ if (fLinearMipMap != (linear != 0)) {
+ free_all_realtime_images();
+ fLinearMipMap = linear != 0;
+ }
+}
+
+/**
+ * Returns the current setting for linear mipmapping.
+ */
+int get_linear_mipmap(void)
+{
+ return fLinearMipMap;
+}
+
+
+/**
+ * Resets the realtime image cache variables.
+ */
+void clear_realtime_image_cache()
+{
+ fCurpage = NULL;
+ fCurtile = 0;
+ fCurmode = 0;
+ fCurtileXRep = 0;
+ fCurtileYRep = 0;
+}
+
+/* REMEMBER! Changes here must go into my_set_tpage() as well */
+int set_tpage(TFace *tface)
+{
+ static int alphamode= -1;
+ static TFace *lasttface= 0;
+ Image *ima;
+ unsigned int *rect, *bind;
+ int tpx, tpy, tilemode, tileXRep,tileYRep;
+
+ /* afschakelen */
+ if(tface==0) {
+ if(lasttface==0) return 0;
+
+ lasttface= 0;
+ fCurtile= 0;
+ fCurpage= 0;
+ if(fCurmode!=0) {
+ glMatrixMode(GL_TEXTURE);
+ glLoadIdentity();
+ glMatrixMode(GL_MODELVIEW);
+ }
+ fCurmode= 0;
+ fCurtileXRep=0;
+ fCurtileYRep=0;
+ alphamode= -1;
+
+ glDisable(GL_BLEND);
+ glDisable(GL_TEXTURE_2D);
+ glDisable(GL_TEXTURE_GEN_S);
+ glDisable(GL_TEXTURE_GEN_T);
+
+ return 0;
+ }
+ lasttface= tface;
+
+ if( alphamode != tface->transp) {
+ alphamode= tface->transp;
+
+ if(alphamode) {
+ glEnable(GL_BLEND);
+
+ if(alphamode==TF_ADD) {
+ glBlendFunc(GL_ONE, GL_ONE);
+ /* glBlendEquationEXT(GL_FUNC_ADD_EXT); */
+ }
+ else if(alphamode==TF_ALPHA) {
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ /* glBlendEquationEXT(GL_FUNC_ADD_EXT); */
+ }
+ /* else { */
+ /* glBlendFunc(GL_ONE, GL_ONE); */
+ /* glBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT); */
+ /* } */
+ }
+ else glDisable(GL_BLEND);
+ }
+
+ ima= tface->tpage;
+
+ /* Enable or disable reflection mapping */
+ if (ima && (ima->flag & IMA_REFLECT)){
+
+// glActiveTextureARB(GL_TEXTURE0_ARB);
+ glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
+ glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
+
+ glEnable(GL_TEXTURE_GEN_S);
+ glEnable(GL_TEXTURE_GEN_T);
+
+ /* Handle multitexturing here */
+ }
+ else{
+ glDisable(GL_TEXTURE_GEN_S);
+ glDisable(GL_TEXTURE_GEN_T);
+ }
+
+ tilemode= tface->mode & TF_TILES;
+ tileXRep = 0;
+ tileYRep = 0;
+ if (ima)
+ {
+ tileXRep = ima->xrep;
+ tileYRep = ima->yrep;
+ }
+
+
+ if(ima==fCurpage && fCurtile==tface->tile && tilemode==fCurmode && fCurtileXRep==tileXRep && fCurtileYRep == tileYRep) return ima!=0;
+
+ if(tilemode!=fCurmode || fCurtileXRep!=tileXRep || fCurtileYRep != tileYRep)
+ {
+ glMatrixMode(GL_TEXTURE);
+ glLoadIdentity();
+
+ if(tilemode && ima!=0)
+ glScalef(ima->xrep, ima->yrep, 1.0);
+
+ glMatrixMode(GL_MODELVIEW);
+ }
+
+ if(ima==0 || ima->ok==0) {
+ glDisable(GL_TEXTURE_2D);
+
+ fCurtile= tface->tile;
+ fCurpage= 0;
+ fCurmode= tilemode;
+ fCurtileXRep = tileXRep;
+ fCurtileYRep = tileYRep;
+
+ return 0;
+ }
+
+ if(ima->ibuf==0) {
+ load_image(ima, IB_rect, G.sce, G.scene->r.cfra);
+
+ if(ima->ibuf==0) {
+ ima->ok= 0;
+
+ fCurtile= tface->tile;
+ fCurpage= 0;
+ fCurmode= tilemode;
+ fCurtileXRep = tileXRep;
+ fCurtileYRep = tileYRep;
+
+ glDisable(GL_TEXTURE_2D);
+ return 0;
+ }
+
+ }
+
+ if(ima->tpageflag & IMA_TWINANIM) fCurtile= ima->lastframe;
+ else fCurtile= tface->tile;
+
+ if(tilemode) {
+
+ if(ima->repbind==0) make_repbind(ima);
+
+ if(fCurtile>=ima->totbind) fCurtile= 0;
+
+ /* this happens when you change repeat buttons */
+ if(ima->repbind) bind= ima->repbind+fCurtile;
+ else bind= &ima->bindcode;
+
+ if(*bind==0) {
+
+ fTexwindx= ima->ibuf->x/ima->xrep;
+ fTexwindy= ima->ibuf->y/ima->yrep;
+
+ if(fCurtile>=ima->xrep*ima->yrep) fCurtile= ima->xrep*ima->yrep-1;
+
+ fTexwinsy= fCurtile / ima->xrep;
+ fTexwinsx= fCurtile - fTexwinsy*ima->xrep;
+
+ fTexwinsx*= fTexwindx;
+ fTexwinsy*= fTexwindy;
+
+ tpx= fTexwindx;
+ tpy= fTexwindy;
+
+ rect= ima->ibuf->rect + fTexwinsy*ima->ibuf->x + fTexwinsx;
+ }
+ }
+ else {
+ bind= &ima->bindcode;
+
+ if(*bind==0) {
+ tpx= ima->ibuf->x;
+ tpy= ima->ibuf->y;
+ rect= ima->ibuf->rect;
+ }
+ }
+
+ if(*bind==0) {
+ int rectw= tpx, recth= tpy;
+ unsigned int *tilerect= NULL, *scalerect= NULL;
+
+ /*
+ * Maarten:
+ * According to Ton this code is not needed anymore. It was used only
+ * in really old Blenders.
+ * Reevan:
+ * Actually it is needed for backwards compatibility. Simpledemo 6 does not display correctly without it.
+ */
+#if 1
+ if (tilemode) {
+ int y;
+
+ tilerect= MEM_mallocN(rectw*recth*sizeof(*tilerect), "tilerect");
+ for (y=0; y<recth; y++) {
+ unsigned int *rectrow= &rect[y*ima->ibuf->x];
+ unsigned int *tilerectrow= &tilerect[y*rectw];
+
+ memcpy(tilerectrow, rectrow, tpx*sizeof(*rectrow));
+ }
+
+ rect= tilerect;
+ }
+#endif
+ if (!is_pow2(rectw) || !is_pow2(recth)) {
+ rectw= smaller_pow2(rectw);
+ recth= smaller_pow2(recth);
+
+ scalerect= MEM_mallocN(rectw*recth*sizeof(*scalerect), "scalerect");
+ gluScaleImage(GL_RGBA, tpx, tpy, GL_UNSIGNED_BYTE, rect, rectw, recth, GL_UNSIGNED_BYTE, scalerect);
+ rect= scalerect;
+ }
+
+ glGenTextures(1, bind);
+
+ if(G.f & G_DEBUG) {
+ printf("var1: %s\n", ima->id.name+2);
+ printf("var1: %d, var2: %d\n", *bind, tpx);
+ printf("var1: %d, var2: %d\n", fCurtile, tilemode);
+ }
+ glBindTexture( GL_TEXTURE_2D, *bind);
+
+ if (!fDoMipMap)
+ {
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, rect);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ } else
+ {
+ int minfilter= fLinearMipMap?GL_LINEAR_MIPMAP_LINEAR:GL_LINEAR_MIPMAP_NEAREST;
+
+ gluBuild2DMipmaps(GL_TEXTURE_2D, 4, rectw, recth, GL_RGBA, GL_UNSIGNED_BYTE, rect);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minfilter);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ }
+
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+
+ if (tilerect)
+ MEM_freeN(tilerect);
+ if (scalerect)
+ MEM_freeN(scalerect);
+ }
+ else glBindTexture( GL_TEXTURE_2D, *bind);
+
+
+
+ glEnable(GL_TEXTURE_2D);
+
+ fCurpage= ima;
+ fCurmode= tilemode;
+ fCurtileXRep = tileXRep;
+ fCurtileYRep = tileYRep;
+
+ return 1;
+}
+
+void free_realtime_image(Image *ima)
+{
+ if(ima->bindcode) {
+ glDeleteTextures(1, &ima->bindcode);
+ ima->bindcode= 0;
+ }
+ if(ima->repbind) {
+ glDeleteTextures(ima->totbind, ima->repbind);
+
+ MEM_freeN(ima->repbind);
+ ima->repbind= 0;
+ }
+}
+
+void free_all_realtime_images(void)
+{
+ Image* ima;
+
+ ima= G.main->image.first;
+ while(ima) {
+ free_realtime_image(ima);
+ ima= ima->id.next;
+ }
+}
+
+void make_repbind(Image *ima)
+{
+ if(ima==0 || ima->ibuf==0) return;
+
+ if(ima->repbind) {
+ glDeleteTextures(ima->totbind, ima->repbind);
+ MEM_freeN(ima->repbind);
+ ima->repbind= 0;
+ }
+ ima->totbind= ima->xrep*ima->yrep;
+ if(ima->totbind>1) {
+ ima->repbind= MEM_callocN(sizeof(int)*ima->totbind, "repbind");
+ }
+}
+
+void update_realtime_textures()
+{
+ Image *ima;
+
+ ima= G.main->image.first;
+ while(ima) {
+ if(ima->tpageflag & IMA_TWINANIM) {
+ if(ima->twend >= ima->xrep*ima->yrep) ima->twend= ima->xrep*ima->yrep-1;
+
+ /* check: zit de bindcode niet het array? Vrijgeven. (nog doen) */
+
+ ima->lastframe++;
+ if(ima->lastframe > ima->twend) ima->lastframe= ima->twsta;
+
+ }
+ ima= ima->id.next;
+ }
+}
+
+
+/* XXX, this routine should die but
+ * the great wisdom of NaN has inspired
+ * its progation.
+ */
+void spack(unsigned int ucol)
+{
+ char *cp= (char *)&ucol;
+
+ glColor3ub(cp[3], cp[2], cp[1]);
+}
+
+static void draw_hide_tfaces(Object *ob, Mesh *me)
+{
+ TFace *tface;
+ MFace *mface;
+ float *v1, *v2, *v3, *v4;
+ int a;
+
+ if(me==0 || me->tface==0) return;
+
+ mface= me->mface;
+ tface= me->tface;
+
+ cpack(0x0);
+ setlinestyle(1);
+ for(a=me->totface; a>0; a--, mface++, tface++) {
+ if(mface->v3==0) continue;
+
+ if( (tface->flag & TF_HIDE)) {
+
+ v1= (me->mvert+mface->v1)->co;
+ v2= (me->mvert+mface->v2)->co;
+ v3= (me->mvert+mface->v3)->co;
+ if(mface->v4) v4= (me->mvert+mface->v4)->co; else v4= 0;
+
+ glBegin(GL_LINE_LOOP);
+ glVertex3fv( v1 );
+ glVertex3fv( v2 );
+ glVertex3fv( v3 );
+ if(mface->v4) glVertex3fv( v4 );
+ glEnd();
+ }
+ }
+ setlinestyle(0);
+}
+
+
+void draw_tfaces3D(Object *ob, Mesh *me)
+{
+ MFace *mface;
+ TFace *tface;
+ DispList *dl;
+ float *v1, *v2, *v3, *v4, *extverts= NULL;
+ int a;
+
+ if(me==0 || me->tface==0) return;
+
+ glDisable(GL_DEPTH_TEST);
+
+ mface= me->mface;
+ tface= me->tface;
+
+ dl= find_displist(&ob->disp, DL_VERTS);
+ if (dl) extverts= dl->verts;
+
+ /* SELECT faces */
+ for(a=me->totface; a>0; a--, mface++, tface++) {
+ if(mface->v3==0) continue;
+ if(tface->flag & TF_HIDE) continue;
+
+ if( tface->flag & (TF_ACTIVE|TF_SELECT) ) {
+ if (extverts) {
+ v1= extverts+3*mface->v1;
+ v2= extverts+3*mface->v2;
+ v3= extverts+3*mface->v3;
+ v4= mface->v4?(extverts+3*mface->v4):NULL;
+ } else {
+ v1= (me->mvert+mface->v1)->co;
+ v2= (me->mvert+mface->v2)->co;
+ v3= (me->mvert+mface->v3)->co;
+ v4= mface->v4?(me->mvert+mface->v4)->co:NULL;
+ }
+
+ if(tface->flag & TF_ACTIVE) {
+ /* kleuren: R=x G=y */
+ cpack(0xFF);
+ glBegin(GL_LINE_STRIP); glVertex3fv(v1); if(v4) glVertex3fv(v4); else glVertex3fv(v3); glEnd();
+ cpack(0xFF00);
+ glBegin(GL_LINE_STRIP); glVertex3fv(v1); glVertex3fv(v2); glEnd();
+ cpack(0x0);
+ glBegin(GL_LINE_STRIP); glVertex3fv(v2); glVertex3fv(v3); if(v4) glVertex3fv(v4); glEnd();
+ }
+ else {
+ cpack(0x0);
+ glBegin(GL_LINE_LOOP);
+ glVertex3fv( v1 );
+ glVertex3fv( v2 );
+ glVertex3fv( v3 );
+ if(v4) glVertex3fv( v4 );
+ glEnd();
+ }
+
+ if(tface->flag & TF_SELECT) {
+ cpack(0xFFFFFF);
+ setlinestyle(1);
+ glBegin(GL_LINE_LOOP);
+ glVertex3fv( v1 );
+ glVertex3fv( v2 );
+ glVertex3fv( v3 );
+ if(v4) glVertex3fv( v4 );
+ glEnd();
+ setlinestyle(0);
+ }
+ }
+ }
+
+ glEnable(GL_DEPTH_TEST);
+}
+
+static int set_gl_light(Object *ob)
+{
+ Base *base;
+ Lamp *la;
+ int count;
+ /* float zero[4]= {0.0, 0.0, 0.0, 0.0}; */
+ float vec[4];
+
+ vec[3]= 1.0;
+
+ for(count=0; count<8; count++) glDisable(GL_LIGHT0+count);
+
+ count= 0;
+
+ base= FIRSTBASE;
+ while(base) {
+ if(base->object->type==OB_LAMP ) {
+ if(base->lay & G.vd->lay) {
+ if(base->lay & ob->lay)
+ {
+ la= base->object->data;
+
+ glPushMatrix();
+ glLoadMatrixf((float *)G.vd->viewmat);
+
+ where_is_object_simul(base->object);
+ VECCOPY(vec, base->object->obmat[3]);
+
+ if(la->type==LA_SUN) {
+ vec[0]= base->object->obmat[2][0];
+ vec[1]= base->object->obmat[2][1];
+ vec[2]= base->object->obmat[2][2];
+ vec[3]= 0.0;
+ glLightfv(GL_LIGHT0+count, GL_POSITION, vec);
+ }
+ else {
+ vec[3]= 1.0;
+ glLightfv(GL_LIGHT0+count, GL_POSITION, vec);
+ glLightf(GL_LIGHT0+count, GL_CONSTANT_ATTENUATION, 1.0);
+ glLightf(GL_LIGHT0+count, GL_LINEAR_ATTENUATION, la->att1/la->dist);
+ /* without this next line it looks backward compatible. attennuation still is acceptable */
+ /* glLightf(GL_LIGHT0+count, GL_QUADRATIC_ATTENUATION, la->att2/(la->dist*la->dist)); */
+
+ if(la->type==LA_SPOT) {
+ vec[0]= -base->object->obmat[2][0];
+ vec[1]= -base->object->obmat[2][1];
+ vec[2]= -base->object->obmat[2][2];
+ glLightfv(GL_LIGHT0+count, GL_SPOT_DIRECTION, vec);
+ glLightf(GL_LIGHT0+count, GL_SPOT_CUTOFF, la->spotsize/2.0);
+ glLightf(GL_LIGHT0+count, GL_SPOT_EXPONENT, 128.0*la->spotblend);
+ }
+ else glLightf(GL_LIGHT0+count, GL_SPOT_CUTOFF, 180.0);
+ }
+
+ vec[0]= la->energy*la->r;
+ vec[1]= la->energy*la->g;
+ vec[2]= la->energy*la->b;
+ vec[3]= 1.0;
+ glLightfv(GL_LIGHT0+count, GL_DIFFUSE, vec);
+ glLightfv(GL_LIGHT0+count, GL_SPECULAR, vec);//zero);
+ glEnable(GL_LIGHT0+count);
+
+ glPopMatrix();
+
+ count++;
+ if(count>7) break;
+ }
+ }
+ }
+ base= base->next;
+ }
+
+ return count;
+}
+
+static Material *give_current_material_or_def(Object *ob, int matnr)
+{
+ extern Material defmaterial;
+ Material *ma= give_current_material(ob, matnr);
+
+ return ma?ma:&defmaterial;
+}
+
+static int set_draw_settings_cached(int clearcache, int textured, TFace *texface, int lit, Object *litob, int litmatnr, int doublesided)
+{
+ static int c_textured;
+ static int c_lit;
+ static int c_doublesided;
+ static TFace *c_texface;
+ static Object *c_litob;
+ static int c_litmatnr;
+ static int c_badtex;
+
+ if (clearcache) {
+ c_textured= c_lit= c_doublesided= -1;
+ c_texface= (TFace*) -1;
+ c_litob= (Object*) -1;
+ c_litmatnr= -1;
+ c_badtex= 0;
+ }
+
+ if (doublesided!=c_doublesided) {
+ if (doublesided) glDisable(GL_CULL_FACE);
+ else glEnable(GL_CULL_FACE);
+
+ c_doublesided= doublesided;
+ }
+
+ if (textured!=c_textured || texface!=c_texface) {
+ if (textured) {
+ c_badtex= !set_tpage(texface);
+ } else {
+ set_tpage(0);
+ c_badtex= 0;
+ }
+ c_textured= textured;
+ c_texface= texface;
+ }
+
+ if (c_badtex) lit= 0;
+ if (lit!=c_lit || litob!=c_litob || litmatnr!=c_litmatnr) {
+ if (lit) {
+ Material *ma= give_current_material_or_def(litob, litmatnr);
+ float spec[4];
+
+ spec[0]= ma->spec*ma->specr;
+ spec[1]= ma->spec*ma->specg;
+ spec[2]= ma->spec*ma->specb;
+ spec[3]= 1.0;
+
+ glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, spec);
+ glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
+ glEnable(GL_LIGHTING);
+ glEnable(GL_COLOR_MATERIAL);
+ }
+ else {
+ glDisable(GL_LIGHTING);
+ glDisable(GL_COLOR_MATERIAL);
+ }
+ c_lit= lit;
+ c_litob= litob;
+ c_litmatnr= litmatnr;
+ }
+
+ return c_badtex;
+}
+
+void draw_tface_mesh(Object *ob, Mesh *me, int dt) /* maximum dt: precies volgens ingestelde waardes */
+{
+ TFace *tface;
+ MFace *mface;
+ float *extverts= NULL;
+ unsigned char obcol[4];
+ int a, mode;
+ short islight, istex;
+
+ if (!me || !me->tface) return;
+
+
+ glShadeModel(GL_SMOOTH);
+
+ islight= set_gl_light(ob);
+
+ obcol[0]= CLAMPIS(ob->col[0]*255, 0, 255);
+ obcol[1]= CLAMPIS(ob->col[1]*255, 0, 255);
+ obcol[2]= CLAMPIS(ob->col[2]*255, 0, 255);
+ obcol[3]= CLAMPIS(ob->col[3]*255, 0, 255);
+
+ /* eerst alle texture polys */
+
+ glCullFace(GL_BACK); glEnable(GL_CULL_FACE);
+ if(G.vd->drawtype==OB_TEXTURE) istex= 1;
+ else istex= 0;
+
+ set_draw_settings_cached(1, 0, 0, 0, 0, 0, 0);
+
+ if(dt > OB_SOLID) {
+ bProperty *prop = get_property(ob, "Text");
+ MFaceInt *mfaceint= NULL;
+ int editing= (G.f & (G_VERTEXPAINT+G_FACESELECT+G_TEXTUREPAINT+G_WEIGHTPAINT)) && (ob==((G.scene->basact) ? (G.scene->basact->object) : 0));
+ MVert *mvert;
+ int totface;
+
+ if (mesh_uses_displist(me) && !editing) {
+ DispList *dl= find_displist(&me->disp, DL_MESH);
+ DispListMesh *dlm= dl->mesh;
+
+ totface= dlm->totface;
+
+ if (!dl)
+ totface= 0;
+ else {
+ totface= dlm->totface;
+ mvert= dlm->mvert;
+ mfaceint= dlm->mface;
+ tface= dlm->tface;
+ }
+ } else {
+ DispList *dl= find_displist(&ob->disp, DL_VERTS);
+ if (dl) extverts= dl->verts;
+
+ totface= me->totface;
+ mvert= me->mvert;
+ mface= me->mface;
+ tface= me->tface;
+ }
+
+ for (a=0; a<totface; a++, tface++) {
+ int v1idx, v2idx, v3idx, v4idx, mf_smooth, matnr, badtex;
+ float *v1, *v2, *v3, *v4;
+
+ if (mfaceint) {
+ MFaceInt *mf= &mfaceint[a];
+
+ v1idx= mf->v1;
+ v2idx= mf->v2;
+ v3idx= mf->v3;
+ v4idx= mf->v4;
+ mf_smooth= mf->flag & ME_SMOOTH;
+ matnr= mf->mat_nr;
+ } else {
+ MFace *mf= &mface[a];
+
+ v1idx= mf->v1;
+ v2idx= mf->v2;
+ v3idx= mf->v3;
+ v4idx= mf->v4;
+ mf_smooth= mf->flag & ME_SMOOTH;
+ matnr= mf->mat_nr;
+ }
+
+ if(v3idx==0) continue;
+ if(tface->flag & TF_HIDE) continue;
+ if(tface->mode & TF_INVISIBLE) continue;
+
+ mode= tface->mode;
+
+ if (extverts) {
+ v1= extverts+3*v1idx;
+ v2= extverts+3*v2idx;
+ v3= extverts+3*v3idx;
+ v4= v4idx?(extverts+3*v4idx):NULL;
+ } else {
+ v1= (mvert+v1idx)->co;
+ v2= (mvert+v2idx)->co;
+ v3= (mvert+v3idx)->co;
+ v4= v4idx?(mvert+v4idx)->co:NULL;
+ }
+
+ badtex= set_draw_settings_cached(0, istex && (mode&TF_TEX), tface, islight && (mode&TF_LIGHT), ob, matnr, mode&TF_TWOSIDE);
+
+ if (prop && !badtex && !editing && (mode & TF_BMFONT)) {
+ char string[MAX_PROPSTRING];
+ int characters, index;
+ Image *ima;
+ float curpos;
+
+ // The BM_FONT handling code is duplicated in the gameengine
+ // Search for 'Frank van Beek' ;-)
+
+ // string = "Frank van Beek";
+
+ set_property_valstr(prop, string);
+ characters = strlen(string);
+
+ ima = tface->tpage;
+ if (ima == NULL) {
+ characters = 0;
+ }
+
+ if (1 || !mf_smooth) {
+ float nor[3];
+
+ CalcNormFloat(v1, v2, v3, nor);
+
+ glNormal3fv(nor);
+ }
+
+ curpos= 0.0;
+ glBegin(v4?GL_QUADS:GL_TRIANGLES);
+ for (index = 0; index < characters; index++) {
+ float centerx, centery, sizex, sizey, transx, transy, movex, movey, advance;
+ int character = string[index];
+ char *cp= NULL;
+
+ // lets calculate offset stuff
+ // space starts at offset 1
+ // character = character - ' ' + 1;
+
+ matrixGlyph(ima->ibuf, character, & centerx, &centery, &sizex, &sizey, &transx, &transy, &movex, &movey, &advance);
+ movex+= curpos;
+
+ if (mode & TF_OBCOL) glColor3ubv(obcol);
+ else cp= (char *)&(tface->col[0]);
+
+ glTexCoord2f((tface->uv[0][0] - centerx) * sizex + transx, (tface->uv[0][1] - centery) * sizey + transy);
+ if (cp) glColor3ub(cp[3], cp[2], cp[1]);
+ glVertex3f(sizex * v1[0] + movex, sizey * v1[1] + movey, v1[2]);
+
+ glTexCoord2f((tface->uv[1][0] - centerx) * sizex + transx, (tface->uv[1][1] - centery) * sizey + transy);
+ if (cp) glColor3ub(cp[7], cp[6], cp[5]);
+ glVertex3f(sizex * v2[0] + movex, sizey * v2[1] + movey, v2[2]);
+
+ glTexCoord2f((tface->uv[2][0] - centerx) * sizex + transx, (tface->uv[2][1] - centery) * sizey + transy);
+ if (cp) glColor3ub(cp[11], cp[10], cp[9]);
+ glVertex3f(sizex * v3[0] + movex, sizey * v3[1] + movey, v3[2]);
+
+ if(v4) {
+ glTexCoord2f((tface->uv[3][0] - centerx) * sizex + transx, (tface->uv[3][1] - centery) * sizey + transy);
+ if (cp) glColor3ub(cp[15], cp[14], cp[13]);
+ glVertex3f(sizex * v4[0] + movex, sizey * v4[1] + movey, v4[2]);
+ }
+
+ curpos+= advance;
+ }
+ glEnd();
+ }
+ else {
+ char *cp= NULL;
+
+ if (badtex) glColor3ub(0xFF, 0x00, 0xFF);
+ else if (mode & TF_OBCOL) glColor3ubv(obcol);
+ else cp= (char *)&(tface->col[0]);
+
+ if (!mf_smooth) {
+ float nor[3];
+
+ CalcNormFloat(v1, v2, v3, nor);
+
+ glNormal3fv(nor);
+ }
+
+ glBegin(v4?GL_QUADS:GL_TRIANGLES);
+
+ glTexCoord2fv(tface->uv[0]);
+ if (cp) glColor3ub(cp[3], cp[2], cp[1]);
+ if (mf_smooth) glNormal3sv(mvert[v1idx].no);
+ glVertex3fv(v1);
+
+ glTexCoord2fv(tface->uv[1]);
+ if (cp) glColor3ub(cp[7], cp[6], cp[5]);
+ if (mf_smooth) glNormal3sv(mvert[v2idx].no);
+ glVertex3fv(v2);
+
+ glTexCoord2fv(tface->uv[2]);
+ if (cp) glColor3ub(cp[11], cp[10], cp[9]);
+ if (mf_smooth) glNormal3sv(mvert[v3idx].no);
+ glVertex3fv(v3);
+
+ if(v4) {
+ glTexCoord2fv(tface->uv[3]);
+ if (cp) glColor3ub(cp[15], cp[14], cp[13]);
+ if (mf_smooth) glNormal3sv(mvert[v4idx].no);
+ glVertex3fv(v4);
+ }
+ glEnd();
+ }
+ }
+
+ /* textures uitzetten */
+ set_tpage(0);
+ }
+
+ glShadeModel(GL_FLAT);
+ glDisable(GL_CULL_FACE);
+
+ draw_hide_tfaces(ob, me);
+
+ if(ob==OBACT && (G.f & G_FACESELECT)) {
+ draw_tfaces3D(ob, me);
+ }
+
+ /* XXX, bad patch - default_gl_light() calls
+ * glLightfv(GL_LIGHT_POSITION, ...) which
+ * is transformed by the current matrix... we
+ * need to make sure that matrix is identity.
+ *
+ * It would be better if drawmesh.c kept track
+ * of and restored the light settings it changed.
+ * - zr
+ */
+ glPushMatrix();
+ glLoadIdentity();
+ default_gl_light();
+ glPopMatrix();
+}
+
+void init_realtime_GL(void)
+{
+ glMatrixMode(GL_TEXTURE);
+ glLoadIdentity();
+ glMatrixMode(GL_MODELVIEW);
+
+}
+
diff --git a/source/blender/src/drawnla.c b/source/blender/src/drawnla.c
new file mode 100644
index 00000000000..d5a729b7378
--- /dev/null
+++ b/source/blender/src/drawnla.c
@@ -0,0 +1,523 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 (once : 4761)
+#include "BLI_winstuff.h"
+#endif
+
+#include "BMF_Api.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "BSE_drawnla.h"
+#include "BSE_drawipo.h"
+#include "BSE_editnla_types.h"
+
+#include "BIF_gl.h"
+#include "BIF_resources.h"
+#include "BIF_screen.h"
+#include "BIF_mywindow.h"
+#include "BIF_glutil.h"
+
+#include "DNA_view3d_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_object_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_ipo_types.h"
+#include "DNA_action_types.h"
+#include "DNA_nla_types.h"
+#include "DNA_constraint_types.h"
+
+#include "BLI_blenlib.h"
+#include "MEM_guardedalloc.h"
+#include "BKE_global.h"
+
+#include "BDR_drawaction.h"
+#include "BDR_editcurve.h"
+
+#include "blendef.h"
+#include "interface.h"
+
+/* Local function prototypes */
+static void draw_nlastrips(SpaceNla *snla);
+static void draw_nlatree(void);
+
+int count_nla_levels(void);
+int nla_filter (Base* base, int flags);
+
+#define TESTBASE_SAFE(base) ((base)->flag & SELECT)
+
+/* Implementation */
+static void draw_nlatree(void)
+{
+
+ short ofsx, ofsy = 0;
+ Base *base;
+ float x, y;
+ bActionStrip *strip;
+ bConstraintChannel *conchan;
+
+ myortho2 (0, NLAWIDTH, G.v2d->cur.ymin, G.v2d->cur.ymax); // Scaling
+
+ /* Blank out the area */
+ if(curarea->winx>SCROLLB+10 && curarea->winy>SCROLLH+10) {
+ if(G.v2d->scroll) {
+ ofsx= curarea->winrct.xmin;
+ ofsy= curarea->winrct.ymin;
+ glViewport(ofsx, ofsy+G.v2d->mask.ymin-SCROLLB, NLAWIDTH, ( ofsy+G.v2d->mask.ymax)-( ofsy+G.v2d->mask.ymin-SCROLLB));
+ glScissor(ofsx, ofsy+G.v2d->mask.ymin-SCROLLB, NLAWIDTH, ( ofsy+G.v2d->mask.ymax)-( ofsy+G.v2d->mask.ymin-SCROLLB));
+ }
+ }
+
+ glClearColor(.6, .6, .6, 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ /* Clip to the scrollable area */
+
+ glColor3ub(0x00, 0x00, 0x00);
+
+ x = 0.0;
+
+ y = count_nla_levels();
+
+ y*= (NLACHANNELHEIGHT+NLACHANNELSKIP);
+
+ for (base=G.scene->base.first; base; base=base->next){
+ if (nla_filter(base, 0)){
+ cpack (0xAAAAAA);
+ glRectf(x, y-NLACHANNELHEIGHT/2, (float)NLAWIDTH, y+NLACHANNELHEIGHT/2);
+
+ /* Draw the name / ipo timeline*/
+ if (TESTBASE_SAFE(base))
+ cpack(0xFFFFFF);
+ else
+ cpack (0x000000);
+ glRasterPos2f(x+16, y-4);
+ BMF_DrawString(G.font, base->object->id.name+2);
+
+ /* Draw the constraint ipos */
+ for (conchan = base->object->constraintChannels.first; conchan; conchan=conchan->next){
+ y-=NLACHANNELHEIGHT+NLACHANNELSKIP;
+ cpack (0x888888);
+ glRectf(x+16, y-NLACHANNELHEIGHT/2, (float)NLAWIDTH, y+NLACHANNELHEIGHT/2);
+
+ if (conchan->flag & CONSTRAINT_CHANNEL_SELECT)
+ cpack(0xFFFFFF);
+ else
+ cpack (0x000000);
+
+ glRasterPos2f(x+32, y-4);
+ BMF_DrawString(G.font, conchan->name);
+ }
+
+ /* Draw the action timeline */
+ if (ACTIVE_ARMATURE(base)){
+ glRasterPos2f(x, y-8);
+ BIF_draw_icon(ICON_DOWNARROW_HLT);
+ y-=NLACHANNELHEIGHT+NLACHANNELSKIP;
+
+ if (base->object->action){
+ cpack (0x888888);
+ glRectf(x+16, y-NLACHANNELHEIGHT/2, (float)NLAWIDTH, y+NLACHANNELHEIGHT/2);
+
+ if (TESTBASE_SAFE(base))
+ cpack(0xFFFFFF);
+ else
+ cpack (0x000000);
+
+ glRasterPos2f(x+32, y-4);
+ BMF_DrawString(G.font, base->object->action->id.name+2);
+ }
+ }
+ y-=NLACHANNELHEIGHT+NLACHANNELSKIP;
+
+ /* Draw the nla strips */
+ if (base->object->type==OB_ARMATURE){
+ for (strip = base->object->nlastrips.first; strip; strip=strip->next){
+ cpack (0x666666);
+ glRectf(x+32, y-NLACHANNELHEIGHT/2, (float)NLAWIDTH, y+NLACHANNELHEIGHT/2);
+
+ if (TESTBASE_SAFE(base))
+ cpack(0xFFFFFF);
+ else
+ cpack (0x000000);
+
+ glRasterPos2f(x+48, y-4);
+ BMF_DrawString(G.font, strip->act->id.name+2);
+
+ y-=(NLACHANNELHEIGHT+NLACHANNELSKIP);
+
+ }
+ }
+ }
+ }
+
+ myortho2 (0, NLAWIDTH, 0, ( ofsy+G.v2d->mask.ymax)-( ofsy+G.v2d->mask.ymin-SCROLLB)); // Scaling
+
+ glShadeModel(GL_SMOOTH);
+
+ y=9;
+
+#if 1
+ /* Draw sexy shaded block thingies */
+ glEnable (GL_BLEND);
+ glBegin(GL_QUAD_STRIP);
+ glColor4ub (0x99,0x99,0x99,0x00);
+ glVertex2f (0,SCROLLB*2-y);
+ glVertex2f (NLAWIDTH,SCROLLB*2-y);
+
+ glColor4ub (0x99,0x99,0x99,0xFF);
+ glVertex2f (0,SCROLLB-y);
+ glVertex2f (NLAWIDTH,SCROLLB-y);
+
+ glColor4ub (0x99,0x99,0x99,0xFF);
+ glVertex2f (0,0-y);
+ glVertex2f (NLAWIDTH,0-y);
+
+ glEnd();
+
+ glDisable (GL_BLEND);
+#endif
+
+ glShadeModel(GL_FLAT);
+}
+
+static void draw_nlastrips(SpaceNla *snla)
+{
+ rcti scr_rct;
+ gla2DDrawInfo *di;
+ Base *base;
+ int offset = 0;
+ bConstraintChannel *conchan;
+
+ float y;
+
+ /* Draw strips */
+
+ scr_rct.xmin= snla->area->winrct.xmin + NLAWIDTH;
+ scr_rct.ymin= snla->area->winrct.ymin + snla->v2d.mask.ymin-SCROLLB;
+ scr_rct.xmax= snla->area->winrct.xmin + snla->v2d.hor.xmax;
+ scr_rct.ymax= snla->area->winrct.ymin + snla->v2d.mask.ymax;
+ di= glaBegin2DDraw(&scr_rct, &G.v2d->cur);
+
+ y=count_nla_levels();
+ y*= (NLACHANNELHEIGHT+NLACHANNELSKIP);
+
+ for (base=G.scene->base.first; base; base=base->next){
+ Object *ob;
+ bActionStrip *strip;
+ int frame1_x, channel_y;
+
+ ob=base->object;
+
+ if (nla_filter(base, 0)){
+ /* Draw the field */
+ glEnable (GL_BLEND);
+ if (TESTBASE_SAFE(base))
+ glColor4b (0x11, 0x22, 0x55, 0x22);
+ else
+ glColor4b (0x55, 0x22, 0x11, 0x22);
+
+ gla2DDrawTranslatePt(di, 1, y, &frame1_x, &channel_y);
+ glRectf(0, channel_y-NLACHANNELHEIGHT/2, frame1_x, channel_y+NLACHANNELHEIGHT/2);
+
+
+ if (TESTBASE_SAFE(base))
+ glColor4b (0x11, 0x22, 0x55, 0x44);
+ else
+ glColor4b (0x55, 0x22, 0x11, 0x44);
+ glRectf(frame1_x, channel_y-NLACHANNELHEIGHT/2, G.v2d->hor.xmax, channel_y+NLACHANNELHEIGHT/2);
+
+ glDisable (GL_BLEND);
+
+ /* Draw the ipo */
+ draw_object_channel(di, ob, 0, y);
+ y-=NLACHANNELHEIGHT+NLACHANNELSKIP;
+
+ /* Draw the constraints */
+ for (conchan=ob->constraintChannels.first; conchan; conchan=conchan->next){
+ glEnable (GL_BLEND);
+ if (conchan->flag & CONSTRAINT_CHANNEL_SELECT)
+ glColor4b (0x11, 0x22, 0x55, 0x22);
+ else
+ glColor4b (0x55, 0x22, 0x11, 0x22);
+
+ gla2DDrawTranslatePt(di, 1, y, &frame1_x, &channel_y);
+ glRectf(0, channel_y-NLACHANNELHEIGHT/2+4, frame1_x, channel_y+NLACHANNELHEIGHT/2-4);
+
+
+ if (conchan->flag & CONSTRAINT_CHANNEL_SELECT)
+ glColor4b (0x11, 0x22, 0x55, 0x44);
+ else
+ glColor4b (0x55, 0x22, 0x11, 0x44);
+ glRectf(frame1_x, channel_y-NLACHANNELHEIGHT/2+4, G.v2d->hor.xmax, channel_y+NLACHANNELHEIGHT/2-4);
+
+ glDisable (GL_BLEND);
+
+ /* Draw the ipo */
+ draw_ipo_channel(di, conchan->ipo, 0, y);
+ y-=NLACHANNELHEIGHT+NLACHANNELSKIP;
+
+ }
+ }
+
+
+
+
+ /* Draw the action strip */
+ if (ACTIVE_ARMATURE(base)){
+
+ /* Draw the field */
+ glEnable (GL_BLEND);
+ if (TESTBASE_SAFE(base))
+ glColor4ub (0x11, 0x22, 0x55, 0x22);
+ else
+ glColor4ub (0x55, 0x22, 0x11, 0x22);
+ gla2DDrawTranslatePt(di, 1, y, &frame1_x, &channel_y);
+ glRectf(0, channel_y-NLACHANNELHEIGHT/2+4, frame1_x, channel_y+NLACHANNELHEIGHT/2-4);
+
+
+ if (TESTBASE_SAFE(base))
+ glColor4ub (0x11, 0x22, 0x55, 0x44);
+ else
+ glColor4ub (0x55, 0x22, 0x11, 0x44);
+ glRectf(frame1_x, channel_y-NLACHANNELHEIGHT/2+4, G.v2d->hor.xmax, channel_y+NLACHANNELHEIGHT/2-4);
+
+ glDisable (GL_BLEND);
+
+ /* Draw the action keys */
+ draw_action_channel(di, ob->action, 0, y);
+
+ y-=NLACHANNELHEIGHT+NLACHANNELSKIP;
+
+ }
+
+ /* Draw the nla strips */
+ if (ob->type==OB_ARMATURE){
+ for (strip=ob->nlastrips.first; strip; strip=strip->next){
+ int stripstart, stripend;
+ int blendstart, blendend;
+ unsigned char r,g,b;
+
+ /* Draw rect */
+ if (strip->flag & ACTSTRIP_SELECT){
+ r = 0xFF; g=0xFF; b=0xAA;
+ }
+ else{
+ r = 0xE4; g=0x9C; b=0xC6;
+ }
+
+ glColor4ub (r, g, b, 0xFF);
+
+ gla2DDrawTranslatePt(di, strip->start+strip->blendin, y, &stripstart, &channel_y);
+ gla2DDrawTranslatePt(di, strip->end-strip->blendout, y, &stripend, &channel_y);
+ glRectf(stripstart, channel_y-NLACHANNELHEIGHT/2+3, stripend, channel_y+NLACHANNELHEIGHT/2-3);
+
+
+ /* Draw blendin */
+ if (strip->blendin>0){
+ glBegin(GL_TRIANGLES);
+
+ gla2DDrawTranslatePt(di, strip->start, y, &blendstart, &channel_y);
+
+ glColor4ub (r*0.75, g*0.75, b*0.75, 0xFF);
+ glVertex2f(blendstart, channel_y-NLACHANNELHEIGHT/2+3);
+ glVertex2f(stripstart, channel_y+NLACHANNELHEIGHT/2-3);
+ glVertex2f(stripstart, channel_y-NLACHANNELHEIGHT/2+3);
+
+
+ glEnd();
+ }
+ if (strip->blendout>0){
+ glBegin(GL_TRIANGLES);
+ gla2DDrawTranslatePt(di, strip->end, y, &blendend, &channel_y);
+ glColor4ub (r*0.75, g*0.75, b*0.75, 0xFF);
+ glVertex2f(blendend, channel_y-NLACHANNELHEIGHT/2+3);
+ glVertex2f(stripend, channel_y+NLACHANNELHEIGHT/2-3);
+ glVertex2f(stripend, channel_y-NLACHANNELHEIGHT/2+3);
+ glEnd();
+ }
+
+ /* Draw border */
+ glBegin(GL_LINE_STRIP);
+ glColor4f(1, 1, 1, 0.5);
+ gla2DDrawTranslatePt(di, strip->start, y, &stripstart, &channel_y);
+ gla2DDrawTranslatePt(di, strip->end, y, &stripend, &channel_y);
+
+ glVertex2f(stripstart, channel_y-NLACHANNELHEIGHT/2+3);
+ glVertex2f(stripstart, channel_y+NLACHANNELHEIGHT/2-3);
+ glVertex2f(stripend, channel_y+NLACHANNELHEIGHT/2-3);
+ glColor4f(0, 0, 0, 0.5);
+ glVertex2f(stripend, channel_y-NLACHANNELHEIGHT/2+3);
+ glVertex2f(stripstart, channel_y-NLACHANNELHEIGHT/2+3);
+ glEnd();
+
+ glEnable (GL_BLEND);
+
+ /* Show strip extension */
+ if (strip->flag & ACTSTRIP_HOLDLASTFRAME){
+ glColor4ub (r, g, b, 0x55);
+
+ glRectf(stripend, channel_y-NLACHANNELHEIGHT/2+4, G.v2d->hor.xmax, channel_y+NLACHANNELHEIGHT/2-2);
+ }
+
+ /* Show repeat */
+ if (strip->repeat > 1.0 && !(strip->flag & ACTSTRIP_USESTRIDE)){
+ float rep = 1;
+ glBegin(GL_LINES);
+ while (rep<strip->repeat){
+ /* Draw line */
+ glColor4f(0, 0, 0, 0.5);
+ gla2DDrawTranslatePt(di, strip->start+(rep*((strip->end-strip->start)/strip->repeat)), y, &frame1_x, &channel_y);
+ glVertex2f(frame1_x, channel_y-NLACHANNELHEIGHT/2+4);
+ glVertex2f(frame1_x, channel_y+NLACHANNELHEIGHT/2-2);
+
+ glColor4f(1.0, 1.0, 1.0, 0.5);
+ gla2DDrawTranslatePt(di, strip->start+(rep*((strip->end-strip->start)/strip->repeat)), y, &frame1_x, &channel_y);
+ glVertex2f(frame1_x+1, channel_y-NLACHANNELHEIGHT/2+4);
+ glVertex2f(frame1_x+1, channel_y+NLACHANNELHEIGHT/2-2);
+ rep+=1.0;
+ }
+ glEnd();
+
+ }
+ glDisable (GL_BLEND);
+
+ y-=(NLACHANNELHEIGHT+NLACHANNELSKIP);
+ }
+
+ }
+ }
+ glaEnd2DDraw(di);
+
+}
+
+void drawnlaspace(void)
+{
+ short ofsx = 0, ofsy = 0;
+
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) ;
+
+ calc_scrollrcts(G.v2d, curarea->winx, curarea->winy);
+
+ if(curarea->winx>SCROLLB+10 && curarea->winy>SCROLLH+10) {
+ if(G.v2d->scroll) {
+ ofsx= curarea->winrct.xmin;
+ ofsy= curarea->winrct.ymin;
+ glViewport(ofsx+G.v2d->mask.xmin, ofsy+G.v2d->mask.ymin, ( ofsx+G.v2d->mask.xmax-1)-(ofsx+G.v2d->mask.xmin)+1, ( ofsy+G.v2d->mask.ymax-1)-( ofsy+G.v2d->mask.ymin)+1);
+ glScissor(ofsx+G.v2d->mask.xmin, ofsy+G.v2d->mask.ymin, ( ofsx+G.v2d->mask.xmax-1)-(ofsx+G.v2d->mask.xmin)+1, ( ofsy+G.v2d->mask.ymax-1)-( ofsy+G.v2d->mask.ymin)+1);
+ }
+ }
+
+ glClearColor(.45, .45, .45, 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ myortho2 (G.v2d->cur.xmin, G.v2d->cur.xmax, G.v2d->cur.ymin, G.v2d->cur.ymax);
+
+ /* Draw backdrop */
+ calc_ipogrid();
+ draw_ipogrid();
+
+ /* Draw channel strips */
+ draw_nlastrips(G.snla);
+
+ /* Draw current frame */
+ glViewport(ofsx+G.v2d->mask.xmin, ofsy+G.v2d->mask.ymin, ( ofsx+G.v2d->mask.xmax-1)-(ofsx+G.v2d->mask.xmin)+1, ( ofsy+G.v2d->mask.ymax-1)-( ofsy+G.v2d->mask.ymin)+1);
+ glScissor(ofsx+G.v2d->mask.xmin, ofsy+G.v2d->mask.ymin, ( ofsx+G.v2d->mask.xmax-1)-(ofsx+G.v2d->mask.xmin)+1, ( ofsy+G.v2d->mask.ymax-1)-( ofsy+G.v2d->mask.ymin)+1);
+ myortho2 (G.v2d->cur.xmin, G.v2d->cur.xmax, G.v2d->cur.ymin, G.v2d->cur.ymax);
+ draw_cfra_action();
+
+ /* Draw scroll */
+ mywinset(curarea->win);
+ if(curarea->winx>SCROLLB+10 && curarea->winy>SCROLLH+10) {
+ myortho2(-0.5, curarea->winx+0.5, -0.5, curarea->winy+0.5);
+ if(G.v2d->scroll) drawscroll(0);
+ }
+
+ /* Draw channel names */
+ draw_nlatree();
+
+ curarea->win_swap= WIN_BACK_OK;
+}
+
+int count_nla_levels(void)
+{
+ Base *base;
+ int y=0;
+
+ for (y=0, base=G.scene->base.first; base; base=base->next)
+ {
+ if (nla_filter(base,0 )){
+ /* Ipo */
+ y++;
+ /* Constraint channels */
+ y+=BLI_countlist(&base->object->constraintChannels);
+
+ if (base->object->type==OB_ARMATURE){
+ /* Action */
+ if(base->object->action){
+ // bActionChannel *achan;
+ y++;
+
+ // for (achan=base->object->action->chanbase.first; achan; achan=achan->next){
+ // y+=BLI_countlist(&achan->constraintChannels);
+ // }
+ }
+ /* Nla strips */
+ y+= BLI_countlist(&base->object->nlastrips);
+ }
+ }
+ }
+
+ return y;
+}
+
+int nla_filter (Base* base, int flags)
+{
+ Object *ob = base->object;
+
+ /* Only objects with ipos */
+ if (ob->ipo)
+ return 1;
+
+ if (ob->constraintChannels.first)
+ return 1;
+
+ /* Only armatures */
+ if (ob->type==OB_ARMATURE)
+ return 1;
+
+ else return 0;
+} \ No newline at end of file
diff --git a/source/blender/src/drawobject.c b/source/blender/src/drawobject.c
new file mode 100644
index 00000000000..83657303628
--- /dev/null
+++ b/source/blender/src/drawobject.c
@@ -0,0 +1,3579 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 <string.h>
+#include <math.h>
+
+#ifdef _WIN32
+#include "BLI_winstuff.h"
+#endif
+#include "MEM_guardedalloc.h"
+
+#include "BMF_Api.h"
+
+#include "IMB_imbuf.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+
+#include "MTC_matrixops.h"
+
+#include "DNA_camera_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_effect_types.h"
+#include "DNA_ipo_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_lattice_types.h"
+#include "DNA_material_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meta_types.h"
+#include "DNA_object_types.h"
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_world_types.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_curve.h"
+#include "BKE_object.h"
+#include "BKE_global.h"
+#include "BKE_displist.h"
+#include "BKE_material.h"
+#include "BKE_ipo.h"
+#include "BKE_mesh.h"
+#include "BKE_effect.h"
+#include "BKE_lattice.h"
+
+#include "BIF_gl.h"
+#include "BIF_mywindow.h"
+#include "BIF_screen.h"
+#include "BIF_space.h"
+#include "BIF_editarmature.h"
+#include "BIF_editika.h"
+#include "BIF_editmesh.h"
+
+#include "BDR_drawmesh.h"
+#include "BDR_drawobject.h"
+#include "BDR_editobject.h"
+
+#include "BSE_view.h"
+#include "BSE_drawview.h"
+#include "BSE_trans_types.h"
+
+#include "blendef.h"
+#include "mydevice.h"
+#include "nla.h"
+
+#ifdef __NLA
+#include "BKE_deform.h"
+#endif
+
+/* pretty stupid */
+/* extern Lattice *editLatt; already in BKE_lattice.h */
+/* editcurve.c */
+extern ListBase editNurb;
+/* editmball.c */
+extern ListBase editelems;
+
+/* more or less needed forwards */
+static void drawmeshwire(Object *ob);
+
+ /***/
+
+// Materials start counting at # one....
+#define MAXMATBUF (MAXMAT + 1)
+static float matbuf[MAXMATBUF][2][4];
+
+static void init_gl_materials(Object *ob)
+{
+ extern Material defmaterial;
+ Material *ma;
+ int a;
+
+ if(ob->totcol==0) {
+ matbuf[0][0][0]= defmaterial.r;
+ matbuf[0][0][1]= defmaterial.g;
+ matbuf[0][0][2]= defmaterial.b;
+ matbuf[0][0][3]= 1.0;
+
+ matbuf[0][1][0]= defmaterial.specr;
+ matbuf[0][1][1]= defmaterial.specg;
+ matbuf[0][1][2]= defmaterial.specb;
+ matbuf[0][1][3]= 1.0;
+
+ /* ook matnr 1, displists! */
+ VECCOPY(matbuf[1][0], matbuf[0][0]);
+ VECCOPY(matbuf[1][1], matbuf[0][1]);
+ }
+
+ for(a=1; a<=ob->totcol; a++) {
+ ma= give_current_material(ob, a);
+ if(ma==NULL) ma= &defmaterial;
+ if(a<MAXMATBUF) {
+ matbuf[a][0][0]= (ma->ref+ma->emit)*ma->r;
+ matbuf[a][0][1]= (ma->ref+ma->emit)*ma->g;
+ matbuf[a][0][2]= (ma->ref+ma->emit)*ma->b;
+ matbuf[a][0][3]= 1.0;
+
+ matbuf[a][1][0]= ma->spec*ma->specr;
+ matbuf[a][1][1]= ma->spec*ma->specg;
+ matbuf[a][1][2]= ma->spec*ma->specb;
+ matbuf[a][1][3]= 1.0;
+ }
+ }
+}
+
+static void set_gl_material(int nr)
+{
+ if(nr<MAXMATBUF) {
+ glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, matbuf[nr][0]);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, matbuf[nr][1]);
+ }
+}
+
+ /***/
+
+unsigned int rect_desel[16]= {0x707070,0x0,0x0,0x707070,0x407070,0x70cccc,0x407070,0x0,0xaaffff,0xffffff,0x70cccc,0x0,0x70cccc,0xaaffff,0x407070,0x707070};
+unsigned int rect_sel[16]= {0x707070,0x0,0x0,0x707070,0x702070,0xcc50cc,0x702070,0x0,0xff80ff,0xffffff,0xcc50cc,0x0,0xcc50cc,0xff80ff,0x702070,0x707070};
+
+unsigned int rectu_desel[16]= {0xff4e4e4e,0xff5c2309,0xff000000,0xff4e4f4d,0xff000000,0xffff9d72,0xffff601c,0xff000000,0xff5d2409,0xffffffff,0xffff9d72,0xff5b2209,0xff4e4e4e,0xff5c2309,0xff010100,0xff4f4f4f};
+unsigned int rectu_sel[16]= {0xff4e4e4e,0xff403c00,0xff000000,0xff4e4e4d,0xff000000,0xfffff64c,0xffaaa100,0xff000000,0xff403c00,0xffffffff,0xfffff64c,0xff403c00,0xff4f4f4f,0xff403c00,0xff010100,0xff4e4e4e};
+
+unsigned int rectl_desel[81]= {0x777777,0x777777,0xa9fefe,0xaaffff,0xaaffff,0xaaffff,0xaaffff,0x777777,0x777777,0x777777,0xa9fefe,0xaafefe,0x777777,0x777777,0x777777,0xa9fefe,0xa9fefe,0x777777,0xaaffff,0xa9fefe,0x4e4e4e,0x0,0x124040,0x0,0x4e4e4e,0xaafefe,0xaaffff,0xaaffff,0x777777,0x0,0x227777,0x55cccc,0x227777,0x0,0x777777,0xaaffff,0xaaffff,0x777777,0x124040,0x88ffff,0xffffff,0x55cccc,0x124040,0x777777,0xaaffff,0xaaffff,0x777777,0x0,0x55cccc,0x88ffff,0x227777,0x0,0x777777,0xaaffff,0xaafefe,0xaafefe,0x4f4f4f,0x0,0x124040,0x0,0x4e4e4e,0xa9fefe,0xaaffff,0x777777,0xa9fefe,0xa9fefe,0x777777,0x777777,0x777777,0xa9fefe,0xa9fefe,0x777777,0x777777,0x777777,0xa9fefe,0xa9fefe,0xaaffff,0xaaffff,0xaaffff,0x777777,0x777777};
+unsigned int rectl_sel[81]= {0x777777,0x777777,0xffaaff,0xffaaff,0xffaaff,0xffaaff,0xffaaff,0x777777,0x777777,0x777777,0xffaaff,0xffaaff,0x777777,0x777777,0x777777,0xffaaff,0xffaaff,0x777777,0xffaaff,0xffaaff,0x4e4e4e,0x10101,0x402440,0x0,0x4e4e4e,0xffaaff,0xffaaff,0xffaaff,0x777777,0x0,0x774477,0xcc77cc,0x774477,0x0,0x777777,0xffaaff,0xffaaff,0x777777,0x402440,0xffaaff,0xffffff,0xcc77cc,0x412541,0x777777,0xffaaff,0xffaaff,0x777777,0x10101,0xcc77cc,0xffaaff,0x774477,0x0,0x777777,0xffaaff,0xffaaff,0xffaaff,0x4e4e4e,0x10101,0x402440,0x0,0x4e4e4e,0xffaaff,0xffaaff,0x777777,0xffaaff,0xffaaff,0x777777,0x777777,0x777777,0xffaaff,0xffaaff,0x777777,0x777777,0x777777,0xffaaff,0xffaaff,0xffaaff,0xffaaff,0xffaaff,0x777777,0x777777};
+unsigned int rectlus_desel[81]= {0x777777,0x777777,0xa9fefe,0xaaffff,0xaaffff,0xaaffff,0xaaffff,0x777777,0x777777,0x777777,0xa9fefe,0xaafefe,0x777777,0x777777,0x777777,0xa9fefe,0xa9fefe,0x777777,0xaaffff,0xa9fefe,0x4e4e4e,0x0,0x5c2309,0x0,0x4e4f4d,0xaafefe,0xaaffff,0xaaffff,0x777777,0x0,0xff601c,0xff9d72,0xff601c,0x0,0x777777,0xaaffff,0xaaffff,0x777777,0x5d2409,0xffceb8,0xff9d72,0xff9d72,0x5b2209,0x777777,0xaaffff,0xaaffff,0x777777,0x10100,0xffceb8,0xffceb8,0xff601c,0x0,0x777777,0xaaffff,0xaafefe,0xaafefe,0x4e4e4e,0x0,0x5c2309,0x10100,0x4f4f4f,0xa9fefe,0xaaffff,0x777777,0xa9fefe,0xa9fefe,0x777777,0x777777,0x777777,0xa9fefe,0xa9fefe,0x777777,0x777777,0x777777,0xa9fefe,0xa9fefe,0xaaffff,0xaaffff,0xaaffff,0x777777,0x777777};
+unsigned int rectlus_sel[81]= {0x777777,0x777777,0xffaaff,0xffaaff,0xffaaff,0xffaaff,0xffaaff,0x777777,0x777777,0x777777,0xffaaff,0xffaaff,0x777777,0x777777,0x777777,0xffaaff,0xffaaff,0x777777,0xffaaff,0xffaaff,0x4e4e4e,0x10100,0x403c00,0x0,0x4e4e4d,0xffaaff,0xffaaff,0xffaaff,0x777777,0x0,0xaaa100,0xfff64c,0xaaa100,0x0,0x777777,0xffaaff,0xffaaff,0x777777,0x403c00,0xfffde2,0xffffff,0xfff64c,0x403c00,0x777777,0xffaaff,0xffaaff,0x777777,0x10100,0xfff64c,0xfffde2,0xaaa100,0x0,0x777777,0xffaaff,0xffaaff,0xffaaff,0x4f4f4f,0x0,0x403c00,0x10100,0x4e4e4e,0xffaaff,0xffaaff,0x777777,0xffaaff,0xffaaff,0x777777,0x777777,0x777777,0xffaaff,0xffaaff,0x777777,0x777777,0x777777,0xffaaff,0xffaaff,0xffaaff,0xffaaff,0xffaaff,0x777777,0x777777};
+unsigned int rectllib_desel[81]= {0xff777777,0xff777777,0xb9b237,0xb9b237,0xb9b237,0xb9b237,0xb9b237,0xff777777,0xff777777,0xff777777,0xb9b237,0xb9b237,0xff777777,0xff777777,0xff777777,0xb9b237,0xb9b237,0xff777777,0xb9b237,0xb9b237,0x4e4e4e,0x0,0x5c2309,0x0,0x4e4f4d,0xb9b237,0xb9b237,0xb9b237,0xff777777,0x0,0xff601c,0xff9d72,0xff601c,0x0,0xff777777,0xb9b237,0xb9b237,0xff777777,0x5d2409,0xffceb8,0xff9d72,0xff9d72,0x5b2209,0xff777777,0xb9b237,0xb9b237,0xff777777,0x10100,0xffceb8,0xffceb8,0xff601c,0x0,0xff777777,0xb9b237,0xb9b237,0xb9b237,0x4e4e4e,0x0,0x5c2309,0x10100,0x4f4f4f,0xb9b237,0xb9b237,0xff777777,0xb9b237,0xb9b237,0xff777777,0xff777777,0xff777777,0xb9b237,0xb9b237,0xff777777,0xff777777,0xff777777,0xb9b237,0xb9b237,0xb9b237,0xb9b237,0xb9b237,0xff777777,0xff777777};
+unsigned int rectllib_sel[81]= {0xff777777,0xff777777,0xfff64c,0xfff64c,0xfff64c,0xfff64c,0xfff64c,0xff777777,0xff777777,0xff777777,0xfff64c,0xfff64c,0xff777777,0xff777777,0xff777777,0xfff64c,0xfff64c,0xff777777,0xfff64c,0xfff64c,0x4e4e4e,0x10100,0x403c00,0x0,0x4e4e4d,0xfff64c,0xfff64c,0xfff64c,0xff777777,0x0,0xaaa100,0xfff64c,0xaaa100,0x0,0xff777777,0xfff64c,0xfff64c,0xff777777,0x403c00,0xfffde2,0xffffff,0xfff64c,0x403c00,0xff777777,0xfff64c,0xfff64c,0xff777777,0x10100,0xfff64c,0xfffde2,0xaaa100,0x0,0xff777777,0xfff64c,0xfff64c,0xfff64c,0x4f4f4f,0x0,0x403c00,0x10100,0x4e4e4e,0xfff64c,0xfff64c,0xff777777,0xfff64c,0xfff64c,0xff777777,0xff777777,0xff777777,0xfff64c,0xfff64c,0xff777777,0xff777777,0xff777777,0xfff64c,0xfff64c,0xfff64c,0xfff64c,0xfff64c,0xff777777,0xff777777};
+
+unsigned int rectl_set[81]= {0xff777777,0xff777777,0xaaaaaa,0xaaaaaa,0xaaaaaa,0xaaaaaa,0xaaaaaa,0xff777777,0xff777777,0xff777777,0xaaaaaa,0xaaaaaa,0xff777777,0xff777777,0xff777777,0xaaaaaa,0xaaaaaa,0xff777777,0xaaaaaa,0xaaaaaa,0x4e4e4e,0x10100,0x202020,0x0,0x4e4e4d,0xaaaaaa,0xaaaaaa,0xaaaaaa,0xff777777,0x0,0xaaa100,0xaaaaaa,0xaaa100,0x0,0xff777777,0xaaaaaa,0xaaaaaa,0xff777777,0x202020,0xfffde2,0xffffff,0xaaaaaa,0x202020,0xff777777,0xaaaaaa,0xaaaaaa,0xff777777,0x10100,0xaaaaaa,0xfffde2,0xaaa100,0x0,0xff777777,0xaaaaaa,0xaaaaaa,0xaaaaaa,0x4f4f4f,0x0,0x202020,0x10100,0x4e4e4e,0xaaaaaa,0xaaaaaa,0xff777777,0xaaaaaa,0xaaaaaa,0xff777777,0xff777777,0xff777777,0xaaaaaa,0xaaaaaa,0xff777777,0xff777777,0xff777777,0xaaaaaa,0xaaaaaa,0xaaaaaa,0xaaaaaa,0xaaaaaa,0xff777777,0xff777777};
+
+#define B_YELLOW 0x77FFFF
+#define B_PURPLE 0xFF70FF
+
+
+unsigned int selcol= 0xFF88FF;
+unsigned int actselcol= 0xFFBBFF;
+
+static unsigned int colortab[24]=
+ {0x0, 0xFF88FF, 0xFFBBFF,
+ 0x403000, 0xFFFF88, 0xFFFFBB,
+ 0x104040, 0x66CCCC, 0x77CCCC,
+ 0x101040, 0x5588FF, 0x88BBFF,
+ 0xFFFFFF
+ };
+
+
+static float cube[8][3] = {
+ {-1.0, -1.0, -1.0},
+ {-1.0, -1.0, 1.0},
+ {-1.0, 1.0, 1.0},
+ {-1.0, 1.0, -1.0},
+ { 1.0, -1.0, -1.0},
+ { 1.0, -1.0, 1.0},
+ { 1.0, 1.0, 1.0},
+ { 1.0, 1.0, -1.0},
+};
+
+void init_draw_rects(void)
+{
+ if(G.order==B_ENDIAN) {
+ IMB_convert_rgba_to_abgr(16, rect_desel);
+ IMB_convert_rgba_to_abgr(16, rect_sel);
+
+ IMB_convert_rgba_to_abgr(16, rectu_desel);
+ IMB_convert_rgba_to_abgr(16, rectu_sel);
+
+ IMB_convert_rgba_to_abgr(81, rectl_desel);
+ IMB_convert_rgba_to_abgr(81, rectl_sel);
+
+ IMB_convert_rgba_to_abgr(81, rectlus_desel);
+ IMB_convert_rgba_to_abgr(81, rectlus_sel);
+
+ IMB_convert_rgba_to_abgr(81, rectllib_desel);
+ IMB_convert_rgba_to_abgr(81, rectllib_sel);
+
+ IMB_convert_rgba_to_abgr(81, rectl_set);
+ }
+}
+
+static void draw_icon_centered(float *pos, unsigned int *rect, int rectsize)
+{
+ float hsize= (float) rectsize/2.0;
+ GLubyte dummy= 0;
+
+ glRasterPos3fv(pos);
+
+ /* use bitmap to shift rasterpos in pixels */
+ glBitmap(1, 1, 0.0, 0.0, -hsize, -hsize, &dummy);
+ glFinish(); /* for sun */
+
+ glDrawPixels(rectsize, rectsize, GL_RGBA, GL_UNSIGNED_BYTE, rect);
+}
+
+void helpline(float *vec)
+{
+ float vecrot[3];
+ short mval[2], mval1[2];
+
+ VECCOPY(vecrot, vec);
+ if(G.obedit) Mat4MulVecfl(G.obedit->obmat, vecrot);
+
+ getmouseco_areawin(mval);
+ project_short_noclip(vecrot, mval1);
+
+ persp(0);
+
+ glDrawBuffer(GL_FRONT);
+
+ cpack(0);
+
+ setlinestyle(3);
+ glBegin(GL_LINE_STRIP);
+ glVertex2sv(mval);
+ glVertex2sv(mval1);
+ glEnd();
+ setlinestyle(0);
+
+ persp(1);
+
+ glDrawBuffer(GL_BACK);
+}
+
+void drawaxes(float size)
+{
+ int axis;
+
+ for (axis=0; axis<3; axis++) {
+ float v1[3]= {0.0, 0.0, 0.0};
+ float v2[3]= {0.0, 0.0, 0.0};
+ int arrow_axis= (axis==0)?1:0;
+
+ glBegin(GL_LINES);
+
+ v2[axis]= size;
+ glVertex3fv(v1);
+ glVertex3fv(v2);
+
+ v1[axis]= size*0.8;
+ v1[arrow_axis]= -size*0.125;
+ glVertex3fv(v1);
+ glVertex3fv(v2);
+
+ v1[arrow_axis]= size*0.125;
+ glVertex3fv(v1);
+ glVertex3fv(v2);
+
+ glEnd();
+
+ v2[axis]+= size*0.125;
+ glRasterPos3fv(v2);
+
+ if (axis==0)
+ BMF_DrawString(G.font, "x");
+ else if (axis==1)
+ BMF_DrawString(G.font, "y");
+ else
+ BMF_DrawString(G.font, "z");
+ }
+}
+
+#if 0
+static void drawgourcube(void)
+{
+ float n[3];
+
+ n[0]=0; n[1]=0; n[2]=0;
+ glBegin(GL_QUADS);
+ n[0]= -1.0;
+ glNormal3fv(n);
+ glVertex3fv(cube[0]); glVertex3fv(cube[1]); glVertex3fv(cube[2]); glVertex3fv(cube[3]);
+ n[0]=0;
+ glEnd();
+
+ glBegin(GL_QUADS);
+ n[1]= -1.0;
+ glNormal3fv(n);
+ glVertex3fv(cube[0]); glVertex3fv(cube[4]); glVertex3fv(cube[5]); glVertex3fv(cube[1]);
+ n[1]=0;
+ glEnd();
+
+ glBegin(GL_QUADS);
+ n[0]= 1.0;
+ glNormal3fv(n);
+ glVertex3fv(cube[4]); glVertex3fv(cube[7]); glVertex3fv(cube[6]); glVertex3fv(cube[5]);
+ n[0]=0;
+ glEnd();
+
+ glBegin(GL_QUADS);
+ n[1]= 1.0;
+ glNormal3fv(n);
+ glVertex3fv(cube[7]); glVertex3fv(cube[3]); glVertex3fv(cube[2]); glVertex3fv(cube[6]);
+ n[1]=0;
+ glEnd();
+
+ glBegin(GL_QUADS);
+ n[2]= 1.0;
+ glNormal3fv(n);
+ glVertex3fv(cube[1]); glVertex3fv(cube[5]); glVertex3fv(cube[6]); glVertex3fv(cube[2]);
+ n[2]=0;
+ glEnd();
+
+ glBegin(GL_QUADS);
+ n[2]= -1.0;
+ glNormal3fv(n);
+ glVertex3fv(cube[7]); glVertex3fv(cube[4]); glVertex3fv(cube[0]); glVertex3fv(cube[3]);
+ glEnd();
+}
+#endif
+
+static void drawcube(void)
+{
+
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(cube[0]); glVertex3fv(cube[1]);glVertex3fv(cube[2]); glVertex3fv(cube[3]);
+ glVertex3fv(cube[0]); glVertex3fv(cube[4]);glVertex3fv(cube[5]); glVertex3fv(cube[6]);
+ glVertex3fv(cube[7]); glVertex3fv(cube[4]);
+ glEnd();
+
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(cube[1]); glVertex3fv(cube[5]);
+ glEnd();
+
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(cube[2]); glVertex3fv(cube[6]);
+ glEnd();
+
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(cube[3]); glVertex3fv(cube[7]);
+ glEnd();
+}
+
+#if 0
+static void drawcube_size(float *size)
+{
+
+ glPushMatrix();
+ glScalef(size[0], size[1], size[2]);
+
+
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(cube[0]); glVertex3fv(cube[1]);glVertex3fv(cube[2]); glVertex3fv(cube[3]);
+ glVertex3fv(cube[0]); glVertex3fv(cube[4]);glVertex3fv(cube[5]); glVertex3fv(cube[6]);
+ glVertex3fv(cube[7]); glVertex3fv(cube[4]);
+ glEnd();
+
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(cube[1]); glVertex3fv(cube[5]);
+ glEnd();
+
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(cube[2]); glVertex3fv(cube[6]);
+ glEnd();
+
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(cube[3]); glVertex3fv(cube[7]);
+ glEnd();
+
+ glPopMatrix();
+}
+#endif
+
+static void tekenshadbuflimits(Lamp *la, float mat[][4])
+{
+ float sta[3], end[3], lavec[3];
+
+ lavec[0]= -mat[2][0];
+ lavec[1]= -mat[2][1];
+ lavec[2]= -mat[2][2];
+ Normalise(lavec);
+
+ sta[0]= mat[3][0]+ la->clipsta*lavec[0];
+ sta[1]= mat[3][1]+ la->clipsta*lavec[1];
+ sta[2]= mat[3][2]+ la->clipsta*lavec[2];
+
+ end[0]= mat[3][0]+ la->clipend*lavec[0];
+ end[1]= mat[3][1]+ la->clipend*lavec[1];
+ end[2]= mat[3][2]+ la->clipend*lavec[2];
+
+
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(sta);
+ glVertex3fv(end);
+ glEnd();
+
+ glPointSize(3.0);
+ glBegin(GL_POINTS);
+ cpack(0);
+ glVertex3fv(sta);
+ glVertex3fv(end);
+ glEnd();
+ glPointSize(1.0);
+}
+
+
+
+static void spotvolume(float *lvec, float *vvec, float inp)
+{
+ /* camera staat op 0,0,0 */
+ float temp[3],plane[3],mat1[3][3],mat2[3][3],mat3[3][3],mat4[3][3],q[4],co,si,hoek;
+
+ Normalise(lvec);
+ Normalise(vvec); /* is dit de goede vector ? */
+
+ Crossf(temp,vvec,lvec); /* vergelijking van vlak door vvec en lvec */
+ Crossf(plane,lvec,temp); /* en dan het vlak loodrecht daarop en evenwijdig aan lvec */
+
+ Normalise(plane);
+
+ /* nu hebben we twee vergelijkingen: die van de kegel en die van het vlak, maar we hebben
+ drie onbekenden We halen nu een onbekende weg door het vlak naar z=0 te roteren */
+ /* Ik heb geen flauw idee of dat mag, we moeten tenslotte twee oplossingen krijgen, maar we
+ proberen het gewoon: vlak vector moet (0,0,1) worden*/
+
+ /* roteer om uitproduct vector van (0,0,1) en vlakvector, inproduct graden */
+ /* volgens defenitie volgt dat uitproduct is (plane[1],-plane[0],0), en cos() = plane[2]);*/
+
+ q[1] = plane[1] ;
+ q[2] = -plane[0] ;
+ q[3] = 0 ;
+ Normalise(&q[1]);
+
+ hoek = saacos(plane[2])/2.0;
+ co = cos(hoek);
+ si = sqrt(1-co*co);
+
+ q[0] = co;
+ q[1] *= si;
+ q[2] *= si;
+ q[3] = 0;
+
+ QuatToMat3(q,mat1);
+
+ /* lampvector nu over acos(inp) graden roteren */
+
+ vvec[0] = lvec[0] ;
+ vvec[1] = lvec[1] ;
+ vvec[2] = lvec[2] ;
+
+ Mat3One(mat2);
+ co = inp;
+ si = sqrt(1-inp*inp);
+
+ mat2[0][0] = co;
+ mat2[1][0] = -si;
+ mat2[0][1] = si;
+ mat2[1][1] = co;
+ Mat3MulMat3(mat3,mat2,mat1);
+
+ mat2[1][0] = si;
+ mat2[0][1] = -si;
+ Mat3MulMat3(mat4,mat2,mat1);
+ Mat3Transp(mat1);
+
+ Mat3MulMat3(mat2,mat1,mat3);
+ Mat3MulVecfl(mat2,lvec);
+ Mat3MulMat3(mat2,mat1,mat4);
+ Mat3MulVecfl(mat2,vvec);
+
+ return;
+}
+
+
+
+static void drawlamp(Object *ob)
+{
+ Lamp *la;
+ float vec[3], lvec[3], vvec[3],x,y,z;
+
+ la= ob->data;
+ vec[0]=vec[1]=vec[2]= 0.0;
+
+ setlinestyle(4);
+
+ if(la->type==LA_SPOT) {
+
+ lvec[0]=lvec[1]= 0.0;
+ lvec[2] = 1.0;
+ x = G.vd->persmat[0][2];
+ y = G.vd->persmat[1][2];
+ z = G.vd->persmat[2][2];
+ vvec[0]= x*ob->obmat[0][0] + y*ob->obmat[0][1] + z*ob->obmat[0][2];
+ vvec[1]= x*ob->obmat[1][0] + y*ob->obmat[1][1] + z*ob->obmat[1][2];
+ vvec[2]= x*ob->obmat[2][0] + y*ob->obmat[2][1] + z*ob->obmat[2][2];
+
+ y = cos( M_PI*la->spotsize/360.0 );
+ spotvolume(lvec, vvec, y);
+ x = -la->dist;
+ lvec[0] *= x ;
+ lvec[1] *= x ;
+ lvec[2] *= x;
+ vvec[0] *= x ;
+ vvec[1] *= x ;
+ vvec[2] *= x;
+
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(vvec);
+ glVertex3fv(vec);
+ glVertex3fv(lvec);
+ glEnd();
+
+ z = x*sqrt(1.0 - y*y);
+ x *= y;
+
+ glTranslatef(0.0 , 0.0 , x);
+ if(la->mode & LA_SQUARE) {
+ vvec[0]= fabs(z);
+ vvec[1]= fabs(z);
+ vvec[2]= 0.0;
+ glBegin(GL_LINE_LOOP);
+ glVertex3fv(vvec);
+ vvec[1]= -fabs(z);
+ glVertex3fv(vvec);
+ vvec[0]= -fabs(z);
+ glVertex3fv(vvec);
+ vvec[1]= fabs(z);
+ glVertex3fv(vvec);
+ glEnd();
+ }
+ else circ(0.0, 0.0, fabs(z));
+
+ }
+ else if ELEM(la->type, LA_HEMI, LA_SUN) {
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(vec);
+ vec[2]= -la->dist;
+ glVertex3fv(vec);
+ glEnd();
+ }
+ else {
+ if(la->mode & LA_SPHERE) {
+
+ float tmat[4][4], imat[4][4];
+
+ vec[0]= vec[1]= vec[2]= 0.0;
+ mygetmatrix(tmat);
+ Mat4Invert(imat, tmat);
+
+ drawcircball(vec, la->dist, imat);
+
+ }
+ }
+ myloadmatrix(G.vd->viewmat);
+
+ VECCOPY(vec, ob->obmat[3]);
+
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(vec);
+ vec[2]= 0;
+ glVertex3fv(vec);
+ glEnd();
+ setlinestyle(0);
+
+ if(la->type==LA_SPOT && (la->mode & LA_SHAD) ) {
+ tekenshadbuflimits(la, ob->obmat);
+ }
+}
+
+static void draw_limit_line(float sta, float end, unsigned int col)
+{
+ glBegin(GL_LINES);
+ glVertex3f(0.0, 0.0, -sta);
+ glVertex3f(0.0, 0.0, -end);
+ glEnd();
+
+ glPointSize(3.0);
+ glBegin(GL_POINTS);
+ cpack(col);
+ glVertex3f(0.0, 0.0, -sta);
+ glVertex3f(0.0, 0.0, -end);
+ glEnd();
+ glPointSize(1.0);
+}
+
+
+void drawcamera(Object *ob)
+{
+ /* een staande piramide met (0,0,0) als top */
+ Camera *cam;
+ World *wrld;
+ float vec[8][4], tmat[4][4], fac, facx, facy, depth;
+
+ cam= ob->data;
+ glDisable(GL_LIGHTING);
+ glDisable(GL_CULL_FACE);
+
+ /* zo is ie altijd te zien */
+ fac= cam->drawsize;
+ if(G.vd->persp>=2) fac= cam->clipsta+0.1;
+
+ depth= - fac*cam->lens/16.0;
+ facx= fac*1.28;
+ facy= fac*1.024;
+
+ vec[0][0]= 0; vec[0][1]= 0; vec[0][2]= 0.001; /* GLBUG: z niet op nul vanwege picking op entry */
+ vec[1][0]= facx; vec[1][1]= facy; vec[1][2]= depth;
+ vec[2][0]= facx; vec[2][1]= -facy; vec[2][2]= depth;
+ vec[3][0]= -facx; vec[3][1]= -facy; vec[3][2]= depth;
+ vec[4][0]= -facx; vec[4][1]= facy; vec[4][2]= depth;
+
+ glBegin(GL_LINE_LOOP);
+ glVertex3fv(vec[0]);
+ glVertex3fv(vec[1]);
+ glVertex3fv(vec[2]);
+ glVertex3fv(vec[0]);
+ glVertex3fv(vec[3]);
+ glVertex3fv(vec[4]);
+ glEnd();
+
+ glBegin(GL_LINES);
+ glVertex3fv(vec[2]);
+ glVertex3fv(vec[3]);
+ glEnd();
+
+ glBegin(GL_LINES);
+ glVertex3fv(vec[4]);
+ glVertex3fv(vec[1]);
+ glEnd();
+
+ if(G.vd->persp>=2) return;
+ if(G.f & G_BACKBUFSEL) return;
+
+ /* pijl aan top */
+ vec[0][2]= depth;
+
+ glBegin(GL_QUADS);
+
+ vec[0][0]= -0.2*cam->drawsize;
+ vec[0][1]= cam->drawsize;
+ glVertex3fv(vec[0]);
+
+ vec[0][0]= 0.2*cam->drawsize;
+ glVertex3fv(vec[0]);
+
+ vec[0][1]= 1.6*cam->drawsize;
+ glVertex3fv(vec[0]);
+
+ vec[0][0]= -0.2*cam->drawsize;
+ glVertex3fv(vec[0]);
+ glEnd();
+
+ glBegin(GL_TRIANGLES);
+
+ vec[0][0]= -0.4*cam->drawsize;
+ vec[0][1]= 1.6*cam->drawsize;
+ glVertex3fv(vec[0]);
+
+ vec[0][0]= 0.0;
+ vec[0][1]= 2.0*cam->drawsize;
+ glVertex3fv(vec[0]);
+
+ vec[0][0]= 0.4*cam->drawsize;
+ vec[0][1]= 1.6*cam->drawsize;
+ glVertex3fv(vec[0]);
+
+ glEnd();
+
+ if(cam->flag & (CAM_SHOWLIMITS+CAM_SHOWMIST)) {
+ myloadmatrix(G.vd->viewmat);
+ Mat4CpyMat4(vec, ob->obmat);
+ Mat4Ortho(vec);
+ mymultmatrix(vec);
+
+ MTC_Mat4SwapMat4(G.vd->persmat, tmat);
+ mygetsingmatrix(G.vd->persmat);
+
+ if(cam->flag & CAM_SHOWLIMITS)
+ draw_limit_line(cam->clipsta, cam->clipend, B_YELLOW);
+
+ wrld= G.scene->world;
+ if(cam->flag & CAM_SHOWMIST)
+ if(wrld) draw_limit_line(wrld->miststa, wrld->miststa+wrld->mistdist, 0xFFFFFF);
+
+ MTC_Mat4SwapMat4(G.vd->persmat, tmat);
+ }
+}
+
+static void tekenvertslatt(short sel)
+{
+ Lattice *lt;
+ BPoint *bp;
+ int a, uxt, u, vxt, v, wxt, w;
+
+ glPointSize(3.0);
+
+ if(sel) cpack(B_YELLOW);
+ else cpack(B_PURPLE);
+
+ glBegin(GL_POINTS);
+
+ bp= editLatt->def;
+ lt= editLatt;
+
+ if(lt->flag & LT_OUTSIDE) {
+
+ for(w=0; w<lt->pntsw; w++) {
+ if(w==0 || w==lt->pntsw-1) wxt= 1; else wxt= 0;
+ for(v=0; v<lt->pntsv; v++) {
+ if(v==0 || v==lt->pntsv-1) vxt= 1; else vxt= 0;
+
+ for(u=0; u<lt->pntsu; u++, bp++) {
+ if(u==0 || u==lt->pntsu-1) uxt= 1; else uxt= 0;
+ if(uxt || vxt || wxt) {
+ if(bp->hide==0) {
+ if((bp->f1 & 1)==sel) glVertex3fv(bp->vec);
+ }
+ }
+ }
+ }
+ }
+ }
+ else {
+
+ a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
+ while(a--) {
+ if(bp->hide==0) {
+ if((bp->f1 & 1)==sel) glVertex3fv(bp->vec);
+ }
+ bp++;
+ }
+ }
+
+ glPointSize(1.0);
+ glEnd();
+}
+
+static void calc_lattverts(void)
+{
+ BPoint *bp;
+ float mat[4][4];
+ int a;
+
+ MTC_Mat4SwapMat4(G.vd->persmat, mat);
+ mygetsingmatrix(G.vd->persmat);
+
+ bp= editLatt->def;
+
+ a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
+ while(a--) {
+ project_short(bp->vec, bp->s);
+ bp++;
+ }
+
+ MTC_Mat4SwapMat4(G.vd->persmat, mat);
+}
+
+
+void calc_lattverts_ext(void)
+{
+
+ areawinset(curarea->win);
+ mymultmatrix(G.obedit->obmat);
+ calc_lattverts();
+ myloadmatrix(G.vd->viewmat);
+
+}
+
+
+static void drawlattice(Object *ob)
+{
+ Lattice *lt;
+ BPoint *bp, *bpu;
+ int u, v, w, dv, dw, uxt, vxt, wxt;
+
+ lt= ob->data;
+ if(ob==G.obedit) {
+ bp= editLatt->def;
+
+ cpack(0x004000);
+ }
+ else {
+ bp= lt->def;
+ }
+
+ dv= lt->pntsu;
+ dw= dv*lt->pntsv;
+
+ if(lt->flag & LT_OUTSIDE) {
+
+ for(w=0; w<lt->pntsw; w++) {
+
+ if(w==0 || w==lt->pntsw-1) wxt= 1; else wxt= 0;
+
+ for(v=0; v<lt->pntsv; v++) {
+
+ if(v==0 || v==lt->pntsv-1) vxt= 1; else vxt= 0;
+
+ for(u=0, bpu=0; u<lt->pntsu; u++, bp++) {
+
+ if(u==0 || u==lt->pntsu-1) uxt= 1; else uxt= 0;
+
+ if(uxt || vxt || wxt) {
+
+ if(w && (uxt || vxt)) {
+
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv( (bp-dw)->vec ); glVertex3fv(bp->vec);
+ glEnd();
+ }
+ if(v && (uxt || wxt)) {
+
+ glBegin(GL_LINES);
+ glVertex3fv( (bp-dv)->vec ); glVertex3fv(bp->vec);
+ glEnd();
+ }
+ if(u && (vxt || wxt)) {
+
+ glBegin(GL_LINES);
+ glVertex3fv(bpu->vec); glVertex3fv(bp->vec);
+ glEnd();
+ }
+ }
+
+ bpu= bp;
+ }
+ }
+ }
+ }
+ else {
+ for(w=0; w<lt->pntsw; w++) {
+
+ for(v=0; v<lt->pntsv; v++) {
+
+ for(u=0, bpu=0; u<lt->pntsu; u++, bp++) {
+
+ if(w) {
+
+ glBegin(GL_LINES);
+ glVertex3fv( (bp-dw)->vec ); glVertex3fv(bp->vec);
+ glEnd();
+ }
+ if(v) {
+
+ glBegin(GL_LINES);
+ glVertex3fv( (bp-dv)->vec ); glVertex3fv(bp->vec);
+ glEnd();
+ }
+ if(u) {
+
+ glBegin(GL_LINES);
+ glVertex3fv(bpu->vec); glVertex3fv(bp->vec);
+ glEnd();
+ }
+ bpu= bp;
+ }
+ }
+ }
+ }
+
+ if(ob==G.obedit) {
+
+ calc_lattverts();
+
+ if(G.zbuf) glDisable(GL_DEPTH_TEST);
+
+ tekenvertslatt(0);
+ tekenvertslatt(1);
+
+ if(G.zbuf) glEnable(GL_DEPTH_TEST);
+ }
+}
+
+/* ***************** ******************** */
+
+void calc_meshverts(void)
+{
+ EditVert *eve;
+ float mat[4][4];
+
+ if(G.edve.first==0) return;
+ eve= G.edve.first;
+
+ MTC_Mat4SwapMat4(G.vd->persmat, mat);
+ mygetsingmatrix(G.vd->persmat);
+
+ eve= G.edve.first;
+ while(eve) {
+ if(eve->h==0) {
+ project_short(eve->co, &(eve->xs));
+ }
+ eve= eve->next;
+ }
+ MTC_Mat4SwapMat4(G.vd->persmat, mat);
+}
+
+void calc_meshverts_ext(void)
+{
+
+ areawinset(curarea->win);
+ mymultmatrix(G.obedit->obmat);
+ calc_meshverts();
+ myloadmatrix(G.vd->viewmat);
+
+}
+
+static void calc_Nurbverts(Nurb *nurb)
+{
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ float mat[4][4];
+ int a;
+
+ MTC_Mat4SwapMat4(G.vd->persmat, mat);
+ mygetsingmatrix(G.vd->persmat);
+
+ nu= nurb;
+ while(nu) {
+ if((nu->type & 7)==1) {
+ bezt= nu->bezt;
+ a= nu->pntsu;
+ while(a--) {
+ project_short(bezt->vec[0], bezt->s[0]);
+ project_short(bezt->vec[1], bezt->s[1]);
+ project_short(bezt->vec[2], bezt->s[2]);
+ bezt++;
+ }
+ }
+ else {
+ bp= nu->bp;
+ a= nu->pntsu*nu->pntsv;
+ while(a--) {
+ project_short(bp->vec, bp->s);
+ bp++;
+ }
+ }
+ nu= nu->next;
+ }
+
+ MTC_Mat4SwapMat4(G.vd->persmat, mat);
+}
+
+void calc_nurbverts_ext(void)
+{
+
+ areawinset(curarea->win);
+ mymultmatrix(G.obedit->obmat);
+ calc_Nurbverts(editNurb.first);
+ myloadmatrix(G.vd->viewmat);
+
+}
+
+void tekenvertices(short sel)
+{
+ EditVert *eve;
+
+ glPointSize(2.0);
+
+ if(sel) cpack(B_YELLOW);
+ else cpack(B_PURPLE);
+#ifdef __NLA /* __TEKENTEST */
+// if (sel==2)
+// cpack (0x0000FF);
+#endif /* __TEKENTEST */
+ glBegin(GL_POINTS);
+
+ eve= (EditVert *)G.edve.first;
+ while(eve) {
+ if(eve->h==0 && (eve->f & 1)==sel ) {
+ glVertex3fv(eve->co);
+ }
+#ifdef __NLA /* __TEKENTEST */
+// if (eve->totweight && sel==2)
+// glVertex3fv(eve->co);
+
+#endif /* __TEKENTEST */
+ eve= eve->next;
+ }
+ glEnd();
+
+ glPointSize(1.0);
+}
+
+void tekenvertices_ext(int mode)
+{
+ ScrArea *tempsa, *sa;
+ View3D *vd;
+
+ if(G.f & (G_FACESELECT+G_DRAWFACES)) {
+ allqueue(REDRAWVIEW3D, 0);
+ return;
+ }
+
+ if(G.zbuf) glDisable(GL_DEPTH_TEST);
+
+ glDrawBuffer(GL_FRONT);
+
+ /* alle views aflopen */
+ tempsa= curarea;
+ sa= G.curscreen->areabase.first;
+ while(sa) {
+ if(sa->spacetype==SPACE_VIEW3D) {
+ vd= sa->spacedata.first;
+ if(G.obedit->lay & vd->lay) {
+ areawinset(sa->win);
+ mymultmatrix(G.obedit->obmat);
+
+ calc_meshverts();
+ if(mode==0 || mode==2) tekenvertices(0);
+ if(mode==1 || mode==2) tekenvertices(1);
+ sa->win_swap= WIN_FRONT_OK;
+
+ myloadmatrix(G.vd->viewmat);
+ }
+ }
+ sa= sa->next;
+ }
+ if(curarea!=tempsa) areawinset(tempsa->win);
+
+ glDrawBuffer(GL_BACK);
+ if(G.zbuf) glEnable(GL_DEPTH_TEST);
+}
+
+/* ************** DRAW DISPLIST ****************** */
+
+ /* DispListMesh */
+
+static void displistmesh_draw_wire(DispListMesh *dlm) {
+ int i;
+
+ for (i=0; i<dlm->totface; i++) {
+ MFaceInt *mf= &dlm->mface[i];
+
+ glBegin(GL_LINE_LOOP);
+ glVertex3fv(dlm->mvert[mf->v1].co);
+ glVertex3fv(dlm->mvert[mf->v2].co);
+ if (mf->v3) {
+ glVertex3fv(dlm->mvert[mf->v3].co);
+ if (mf->v4)
+ glVertex3fv(dlm->mvert[mf->v4].co);
+ }
+ glEnd();
+ }
+}
+
+static void displistmesh_draw_solid(DispListMesh *dlm, int drawsmooth, float *nors) {
+ int lmode, lshademodel= -1, lmat_nr= -1;
+ int i;
+
+#define PASSVERT(ind) { \
+ if (drawsmooth && lshademodel==GL_SMOOTH) \
+ glNormal3sv(dlm->mvert[(ind)].no); \
+ glVertex3fv(dlm->mvert[(ind)].co); \
+}
+
+ glBegin(lmode= GL_QUADS);
+ for (i=0; i<dlm->totface; i++) {
+ MFaceInt *mf= &dlm->mface[i];
+
+ if (mf->v3) {
+ int nmode= mf->v4?GL_QUADS:GL_TRIANGLES;
+
+ if (nmode!=lmode) {
+ glEnd();
+ glBegin(lmode= nmode);
+ }
+
+ if (drawsmooth) {
+ int nshademodel= (mf->flag&ME_SMOOTH)?GL_SMOOTH:GL_FLAT;
+
+ if (nshademodel!=lshademodel) {
+ glEnd();
+ glShadeModel(lshademodel= nshademodel);
+ glBegin(lmode);
+ }
+
+ if (mf->mat_nr!=lmat_nr)
+ set_gl_material((lmat_nr= mf->mat_nr)+1);
+ }
+
+ if (drawsmooth && lshademodel==GL_FLAT)
+ glNormal3fv(&nors[i*3]);
+
+ PASSVERT(mf->v1);
+ PASSVERT(mf->v2);
+ PASSVERT(mf->v3);
+ if (mf->v4)
+ PASSVERT(mf->v4);
+ }
+ }
+ glEnd();
+
+#undef PASSVERT
+}
+
+static void displistmesh_draw_shaded(DispListMesh *dlm, unsigned char *vcols1, unsigned char *vcols2) {
+ int i, lmode;
+
+ glShadeModel(GL_SMOOTH);
+ if (vcols2)
+ glEnable(GL_CULL_FACE);
+
+#define PASSVERT(vidx, fidx) { \
+ unsigned char *col= &colbase[fidx*4]; \
+ glColor3ub(col[3], col[2], col[1]); \
+ glVertex3fv(dlm->mvert[(vidx)].co); \
+}
+
+ glBegin(lmode= GL_QUADS);
+ for (i=0; i<dlm->totface; i++) {
+ MFaceInt *mf= &dlm->mface[i];
+
+ if (mf->v3) {
+ int nmode= mf->v4?GL_QUADS:GL_TRIANGLES;
+ unsigned char *colbase= &vcols1[i*16];
+
+ if (nmode!=lmode) {
+ glEnd();
+ glBegin(lmode= nmode);
+ }
+
+ PASSVERT(mf->v1, 0);
+ PASSVERT(mf->v2, 1);
+ PASSVERT(mf->v3, 2);
+ if (mf->v4)
+ PASSVERT(mf->v4, 3);
+
+ if (vcols2) {
+ unsigned char *colbase= &vcols2[i*16];
+
+ if (mf->v4)
+ PASSVERT(mf->v4, 3);
+ PASSVERT(mf->v3, 2);
+ PASSVERT(mf->v2, 1);
+ PASSVERT(mf->v1, 0);
+ }
+ }
+ }
+ glEnd();
+
+ if (vcols2)
+ glDisable(GL_CULL_FACE);
+
+#undef PASSVERT
+}
+
+ /***/
+
+static int draw_index_wire= 1;
+static int index3_nors_incr= 1;
+
+static void drawDispListwire(ListBase *dlbase)
+{
+ DispList *dl;
+ int parts, nr, ofs, *index;
+ float *data;
+
+ if(dlbase==0) return;
+
+ dl= dlbase->first;
+ while(dl) {
+ data= dl->verts;
+
+ switch(dl->type) {
+ case DL_SEGM:
+ parts= dl->parts;
+ while(parts--) {
+ nr= dl->nr;
+ glBegin(GL_LINE_STRIP);
+ while(nr--) {
+ glVertex3fv(data);
+ data+=3;
+ }
+ glEnd();
+ }
+ break;
+ case DL_POLY:
+ parts= dl->parts;
+ while(parts--) {
+ nr= dl->nr;
+ glBegin(GL_LINE_LOOP);
+ while(nr--) {
+ glVertex3fv(data);
+ data+=3;
+ }
+ glEnd();
+ }
+ break;
+ case DL_SURF:
+ parts= dl->parts;
+ while(parts--) {
+ nr= dl->nr;
+ if(dl->flag & 1) glBegin(GL_LINE_LOOP);
+ else glBegin(GL_LINE_STRIP);
+
+ while(nr--) {
+ glVertex3fv(data);
+ data+=3;
+ }
+ glEnd();
+ }
+ ofs= 3*dl->nr;
+ nr= dl->nr;
+ while(nr--) {
+ data= ( dl->verts )+3*nr;
+ parts= dl->parts;
+ if(dl->flag & 2) glBegin(GL_LINE_LOOP);
+ else glBegin(GL_LINE_STRIP);
+
+ while(parts--) {
+ glVertex3fv(data);
+ data+=ofs;
+ }
+ glEnd();
+ }
+ break;
+
+ case DL_INDEX3:
+ if(draw_index_wire) {
+ parts= dl->parts;
+ data= dl->verts;
+ index= dl->index;
+ while(parts--) {
+
+ glBegin(GL_LINE_LOOP);
+ glVertex3fv(data+3*index[0]);
+ glVertex3fv(data+3*index[1]);
+ glVertex3fv(data+3*index[2]);
+ glEnd();
+ index+= 3;
+ }
+ }
+ break;
+
+ case DL_INDEX4:
+ if(draw_index_wire) {
+ parts= dl->parts;
+ data= dl->verts;
+ index= dl->index;
+ while(parts--) {
+
+ glBegin(GL_LINE_LOOP);
+ glVertex3fv(data+3*index[0]);
+ glVertex3fv(data+3*index[1]);
+ glVertex3fv(data+3*index[2]);
+ if(index[3]) glVertex3fv(data+3*index[3]);
+ glEnd();
+ index+= 4;
+ }
+ }
+ break;
+
+ case DL_MESH:
+ displistmesh_draw_wire(dl->mesh);
+ break;
+ }
+ dl= dl->next;
+ }
+}
+
+static void drawDispListsolid(ListBase *lb, Object *ob)
+{
+ DispList *dl;
+ int parts, ofs, p1, p2, p3, p4, a, b, *index;
+ float *data, *v1, *v2, *v3, *v4;
+ float *ndata, *n1, *n2, *n3, *n4;
+ int drawsmooth= !(G.f & G_BACKBUFSEL);
+
+ if(lb==0) return;
+ if (drawsmooth) {
+ glShadeModel(GL_SMOOTH);
+ glEnable(GL_LIGHTING);
+ }
+
+ dl= lb->first;
+ while(dl) {
+ data= dl->verts;
+ ndata= dl->nors;
+
+ switch(dl->type) {
+ case DL_SURF:
+ if(!drawsmooth) {
+ for(a=0; a<dl->parts; a++) {
+
+ DL_SURFINDEX(dl->flag & 1, dl->flag & 2, dl->nr, dl->parts);
+
+ v1= data+ 3*p1;
+ v2= data+ 3*p2;
+ v3= data+ 3*p3;
+ v4= data+ 3*p4;
+
+ glBegin(GL_QUAD_STRIP);
+
+ glVertex3fv(v2);
+ glVertex3fv(v4);
+
+ for(; b<dl->nr; b++) {
+
+ glVertex3fv(v1);
+ glVertex3fv(v3);
+
+ v2= v1; v1+= 3;
+ v4= v3; v3+= 3;
+ }
+
+
+ glEnd();
+ }
+ }
+ else {
+
+ set_gl_material(dl->col+1);
+/*
+ glBegin(GL_LINES);
+ for(a=0; a<dl->parts*dl->nr; a++) {
+ float nor[3];
+
+ VECCOPY(nor, data+3*a);
+ glVertex3fv(nor);
+ VecAddf(nor, nor, ndata+3*a);
+ glVertex3fv(nor);
+ }
+ glEnd();
+*/
+ for(a=0; a<dl->parts; a++) {
+
+ DL_SURFINDEX(dl->flag & 1, dl->flag & 2, dl->nr, dl->parts);
+
+ v1= data+ 3*p1;
+ v2= data+ 3*p2;
+ v3= data+ 3*p3;
+ v4= data+ 3*p4;
+ n1= ndata+ 3*p1;
+ n2= ndata+ 3*p2;
+ n3= ndata+ 3*p3;
+ n4= ndata+ 3*p4;
+
+ glBegin(GL_QUAD_STRIP);
+
+ glNormal3fv(n2); glVertex3fv(v2);
+ glNormal3fv(n4); glVertex3fv(v4);
+
+ for(; b<dl->nr; b++) {
+
+ glNormal3fv(n1); glVertex3fv(v1);
+ glNormal3fv(n3); glVertex3fv(v3);
+
+ v2= v1; v1+= 3;
+ v4= v3; v3+= 3;
+ n2= n1; n1+= 3;
+ n4= n3; n3+= 3;
+ }
+
+
+ glEnd();
+ }
+ }
+ break;
+
+ case DL_INDEX3:
+
+ parts= dl->parts;
+ data= dl->verts;
+ ndata= dl->nors;
+ index= dl->index;
+
+ if(!drawsmooth) {
+ while(parts--) {
+
+ glBegin(GL_TRIANGLES);
+ glVertex3fv(data+3*index[0]);
+ glVertex3fv(data+3*index[1]);
+ glVertex3fv(data+3*index[2]);
+ glEnd();
+ index+= 3;
+ }
+ }
+ else {
+
+ set_gl_material(dl->col+1);
+
+ /* voor poly's is er maar 1 normaal nodig */
+ if(index3_nors_incr==0) {
+ while(parts--) {
+
+ glBegin(GL_TRIANGLES);
+ glNormal3fv(ndata);
+ glVertex3fv(data+3*index[0]);
+ glVertex3fv(data+3*index[1]);
+ glVertex3fv(data+3*index[2]);
+ glEnd();
+ index+= 3;
+ }
+ }
+ else {
+ while(parts--) {
+
+ glBegin(GL_TRIANGLES);
+ ofs= 3*index[0];
+ glNormal3fv(ndata+ofs); glVertex3fv(data+ofs);
+ ofs= 3*index[1];
+ glNormal3fv(ndata+ofs); glVertex3fv(data+ofs);
+ ofs= 3*index[2];
+ glNormal3fv(ndata+ofs); glVertex3fv(data+ofs);
+ glEnd();
+ index+= 3;
+ }
+ }
+ }
+ break;
+
+ case DL_INDEX4:
+
+ parts= dl->parts;
+ data= dl->verts;
+ ndata= dl->nors;
+ index= dl->index;
+
+ if(!drawsmooth) {
+ while(parts--) {
+
+ glBegin(index[3]?GL_QUADS:GL_TRIANGLES);
+ glVertex3fv(data+3*index[0]);
+ glVertex3fv(data+3*index[1]);
+ glVertex3fv(data+3*index[2]);
+ if(index[3]) glVertex3fv(data+3*index[3]);
+ glEnd();
+ index+= 4;
+ }
+ }
+ else {
+
+ set_gl_material(dl->col+1);
+
+ while(parts--) {
+
+ glBegin(index[3]?GL_QUADS:GL_TRIANGLES);
+ ofs= 3*index[0];
+ glNormal3fv(ndata+ofs); glVertex3fv(data+ofs);
+ ofs= 3*index[1];
+ glNormal3fv(ndata+ofs); glVertex3fv(data+ofs);
+ ofs= 3*index[2];
+ glNormal3fv(ndata+ofs); glVertex3fv(data+ofs);
+ if(index[3]) {
+ ofs= 3*index[3];
+ glNormal3fv(ndata+ofs); glVertex3fv(data+ofs);
+ }
+ glEnd();
+ index+= 4;
+ }
+ }
+ break;
+
+ case DL_MESH:
+ if (!dl->nors)
+ addnormalsDispList(ob, lb);
+ displistmesh_draw_solid(dl->mesh, drawsmooth, dl->nors);
+ break;
+
+ }
+ dl= dl->next;
+ }
+
+ if(drawsmooth) {
+ glShadeModel(GL_FLAT);
+ glDisable(GL_LIGHTING);
+ }
+}
+
+static void drawDispListshaded(ListBase *lb, Object *ob)
+{
+ DispList *dl, *dlob;
+ int parts, p1, p2, p3, p4, a, b, *index;
+ float *data, *v1, *v2, *v3, *v4;/* , *extverts=0 */
+ unsigned int *cdata, *c1, *c2, *c3, *c4;
+ char *cp;
+
+ if(lb==0) return;
+
+ glShadeModel(GL_SMOOTH);
+
+ dl= lb->first;
+ dlob= ob->disp.first;
+ while(dl && dlob) {
+
+ cdata= dlob->col1;
+ data= dl->verts;
+ if(cdata==0) break;
+
+ switch(dl->type) {
+ case DL_SURF:
+
+ for(a=0; a<dl->parts; a++) {
+
+ DL_SURFINDEX(dl->flag & 1, dl->flag & 2, dl->nr, dl->parts);
+
+ v1= data+ 3*p1;
+ v2= data+ 3*p2;
+ v3= data+ 3*p3;
+ v4= data+ 3*p4;
+ c1= cdata+ p1;
+ c2= cdata+ p2;
+ c3= cdata+ p3;
+ c4= cdata+ p4;
+
+ for(; b<dl->nr; b++) {
+
+ glBegin(GL_QUADS);
+ cp= (char *)c1;
+ glColor3ub(cp[3], cp[2], cp[1]);
+ glVertex3fv(v1);
+ cp= (char *)c2;
+ glColor3ub(cp[3], cp[2], cp[1]);
+ glVertex3fv(v2);
+ cp= (char *)c4;
+ glColor3ub(cp[3], cp[2], cp[1]);
+ glVertex3fv(v4);
+ cp= (char *)c3;
+ glColor3ub(cp[3], cp[2], cp[1]);
+ glVertex3fv(v3);
+ glEnd();
+
+ v2= v1; v1+= 3;
+ v4= v3; v3+= 3;
+ c2= c1; c1++;
+ c4= c3; c3++;
+ }
+ }
+ break;
+
+ case DL_INDEX3:
+
+ parts= dl->parts;
+ index= dl->index;
+
+ while(parts--) {
+
+ glBegin(GL_TRIANGLES);
+ cp= (char *)(cdata+index[0]);
+ glColor3ub(cp[3], cp[2], cp[1]);
+ glVertex3fv(data+3*index[0]);
+
+ cp= (char *)(cdata+index[1]);
+ glColor3ub(cp[3], cp[2], cp[1]);
+ glVertex3fv(data+3*index[1]);
+
+ cp= (char *)(cdata+index[2]);
+ glColor3ub(cp[3], cp[2], cp[1]);
+ glVertex3fv(data+3*index[2]);
+ glEnd();
+ index+= 3;
+ }
+ break;
+
+ case DL_INDEX4:
+
+ parts= dl->parts;
+ index= dl->index;
+ while(parts--) {
+
+ glBegin(index[3]?GL_QUADS:GL_TRIANGLES);
+ cp= (char *)(cdata+index[0]);
+ glColor3ub(cp[3], cp[2], cp[1]);
+ glVertex3fv(data+3*index[0]);
+
+ cp= (char *)(cdata+index[1]);
+ glColor3ub(cp[3], cp[2], cp[1]);
+ glVertex3fv(data+3*index[1]);
+
+ cp= (char *)(cdata+index[2]);
+ glColor3ub(cp[3], cp[2], cp[1]);
+ glVertex3fv(data+3*index[2]);
+
+ if(index[3]) {
+
+ cp= (char *)(cdata+index[3]);
+ glColor3ub(cp[3], cp[2], cp[1]);
+ glVertex3fv(data+3*index[3]);
+ }
+ glEnd();
+ index+= 4;
+ }
+ break;
+
+ case DL_MESH:
+ displistmesh_draw_shaded(dl->mesh, (unsigned char*) dlob->col1, (unsigned char*) dlob->col2);
+ break;
+
+ }
+ dl= dl->next;
+ dlob= dlob->next;
+ }
+
+ glShadeModel(GL_FLAT);
+}
+
+static void drawmeshsolid(Object *ob, float *nors)
+{
+ Mesh *me;
+ DispList *dl;
+ MVert *mvert;
+ TFace *tface;
+ MFace *mface;
+ EditVlak *evl;
+ float *extverts=0, *v1, *v2, *v3, *v4;
+ int glmode, setsmooth=0, a, start, end, matnr= -1, vertexpaint, i;
+ short no[3], *n1, *n2, *n3, *n4 = NULL;
+
+ vertexpaint= (G.f & (G_VERTEXPAINT+G_FACESELECT+G_TEXTUREPAINT+G_WEIGHTPAINT)) && (ob==((G.scene->basact) ? (G.scene->basact->object) : 0));
+
+ me= get_mesh(ob);
+ if(me==0) return;
+
+ glShadeModel(GL_FLAT);
+
+ if( (G.f & G_BACKBUFSEL)==0 ) {
+ glEnable(GL_LIGHTING);
+ init_gl_materials(ob);
+ two_sided( me->flag & ME_TWOSIDED );
+ }
+
+ mface= me->mface;
+ if( (G.f & G_FACESELECT) && ob==((G.scene->basact) ? (G.scene->basact->object) : 0)) tface= me->tface;
+ else tface= 0;
+
+ mvert= me->mvert;
+ a= me->totface;
+
+ /* SOLVE */
+ /* if ELEM(ob->type, OB_SECTOR, OB_LIFE) glEnable(GL_CULL_FACE); */
+
+ if(ob==G.obedit || (G.obedit && ob->data==G.obedit->data)) {
+
+ evl= G.edvl.first;
+ while(evl) {
+ if(evl->v1->h==0 && evl->v2->h==0 && evl->v3->h==0) {
+
+ if(evl->mat_nr!=matnr) {
+ matnr= evl->mat_nr;
+ set_gl_material(matnr+1);
+ }
+
+ if(evl->v4 && evl->v4->h==0) {
+
+ glBegin(GL_QUADS);
+ glNormal3fv(evl->n);
+ glVertex3fv(evl->v1->co);
+ glVertex3fv(evl->v2->co);
+ glVertex3fv(evl->v3->co);
+ glVertex3fv(evl->v4->co);
+ glEnd();
+ }
+ else {
+
+ glBegin(GL_TRIANGLES);
+ glNormal3fv(evl->n);
+ glVertex3fv(evl->v1->co);
+ glVertex3fv(evl->v2->co);
+ glVertex3fv(evl->v3->co);
+ glEnd();
+ }
+ }
+ evl= evl->next;
+ }
+
+ glDisable(GL_LIGHTING);
+ glShadeModel(GL_FLAT);
+
+ if(ob==G.obedit) {
+ calc_meshverts();
+
+ if(G.zbuf) glDisable(GL_DEPTH_TEST);
+ tekenvertices(0);
+ tekenvertices(1);
+ if(G.zbuf) glEnable(GL_DEPTH_TEST);
+ }
+
+ }
+ else {
+
+ start= 0; end= me->totface;
+ set_buildvars(ob, &start, &end);
+ mface+= start;
+ if(tface) tface+= start;
+
+ dl= find_displist(&ob->disp, DL_VERTS);
+ if(dl) extverts= dl->verts;
+
+ glBegin(GL_QUADS);
+ glmode= GL_QUADS;
+
+ for(a=start; a<end; a++, mface++, nors+=3) {
+ if(mface->v3) {
+ if(tface && (tface->flag & TF_HIDE)) {
+ if( (G.f & G_BACKBUFSEL)==0) {
+ glBegin(GL_LINE_LOOP);
+ glVertex3fv( (mvert+mface->v1)->co);
+ glVertex3fv( (mvert+mface->v2)->co);
+ glVertex3fv( (mvert+mface->v3)->co);
+ if(mface->v4) glVertex3fv( (mvert+mface->v1)->co);
+ glEnd();
+ tface++;
+ }
+ }
+ else {
+ if(extverts) {
+ v1= extverts+3*mface->v1;
+ v2= extverts+3*mface->v2;
+ v3= extverts+3*mface->v3;
+ if(mface->v4) v4= extverts+3*mface->v4;
+ else v4= 0;
+ }
+ else {
+ v1= (mvert+mface->v1)->co;
+ v2= (mvert+mface->v2)->co;
+ v3= (mvert+mface->v3)->co;
+ if(mface->v4) v4= (mvert+mface->v4)->co;
+ else v4= 0;
+ }
+
+
+ if(tface) {
+ if(tface->mode & TF_TWOSIDE) glEnable(GL_CULL_FACE);
+ else glDisable(GL_CULL_FACE);
+ }
+
+
+ /* dit GL_QUADS grapje is op snelheid getest: factor 2! */
+
+ if(v4) {if(glmode==GL_TRIANGLES) {glmode= GL_QUADS; glEnd(); glBegin(GL_QUADS);}}
+ else {if(glmode==GL_QUADS) {glmode= GL_TRIANGLES; glEnd(); glBegin(GL_TRIANGLES);}}
+
+ if(G.f & G_BACKBUFSEL) {
+ if(vertexpaint) {
+ i= index_to_framebuffer(a+1);
+ cpack(i);
+ }
+
+ glVertex3fv( v1 );
+ glVertex3fv( v2 );
+ glVertex3fv( v3 );
+ if(v4) glVertex3fv( v4 );
+
+ }
+ else {
+
+ if(mface->mat_nr!=matnr) {
+ matnr= mface->mat_nr;
+ set_gl_material(matnr+1);
+ }
+
+ if( (me->flag & ME_AUTOSMOOTH)==0 && (mface->flag & ME_SMOOTH)) {
+ if(setsmooth==0) {
+ glEnd();
+ glShadeModel(GL_SMOOTH);
+ if(glmode==GL_TRIANGLES) glBegin(GL_TRIANGLES);
+ else glBegin(GL_QUADS);
+ setsmooth= 1;
+ }
+ n1= (mvert+mface->v1)->no;
+ n2= (mvert+mface->v2)->no;
+ n3= (mvert+mface->v3)->no;
+ if(v4) n4= (mvert+mface->v4)->no;
+
+ if(mface->puno & ME_FLIPV1) {
+ no[0]= -n1[0]; no[1]= -n1[1]; no[2]= -n1[2];
+ glNormal3sv(no);
+ }
+ else glNormal3sv(n1);
+ glVertex3fv( v1 );
+
+ if(mface->puno & ME_FLIPV2) {
+ no[0]= -n2[0]; no[1]= -n2[1]; no[2]= -n2[2];
+ glNormal3sv(no);
+ }
+ else glNormal3sv(n2);
+ glVertex3fv( v2 );
+
+ if(mface->puno & ME_FLIPV3) {
+ no[0]= -n3[0]; no[1]= -n3[1]; no[2]= -n3[2];
+ glNormal3sv(no);
+ }
+ else glNormal3sv(n3);
+ glVertex3fv( v3 );
+
+ if(v4) {
+ if(mface->puno & ME_FLIPV4) {
+ no[0]= -n4[0]; no[1]= -n4[1]; no[2]= -n4[2];
+ glNormal3sv(no);
+ }
+ else glNormal3sv(n4);
+ glVertex3fv( v4 );
+ }
+ }
+ else {
+ if(setsmooth==1) {
+ glEnd();
+ glShadeModel(GL_FLAT);
+ if(glmode==GL_TRIANGLES) glBegin(GL_TRIANGLES);
+ else glBegin(GL_QUADS);
+ setsmooth= 0;
+ }
+ glNormal3fv(nors);
+ glVertex3fv( v1 );
+ glVertex3fv( v2 );
+ glVertex3fv( v3 );
+ if(v4) glVertex3fv( v4 );
+ }
+ }
+ }
+ if(tface) tface++;
+ }
+ }
+
+ glEnd();
+ }
+
+ /* SOLVE */
+/* if ELEM(ob->type, OB_SECTOR, OB_LIFE) glDisable(GL_CULL_FACE); */
+
+ if(G.f & G_BACKBUFSEL) {
+ glDisable(GL_CULL_FACE);
+ }
+ glDisable(GL_LIGHTING);
+
+}
+
+static void drawmeshshaded(Object *ob, unsigned int *col1, unsigned int *col2)
+{
+ Mesh *me;
+ MVert *mvert;
+ MFace *mface;
+ TFace *tface;
+ DispList *dl;
+ float *extverts=0, *v1, *v2, *v3, *v4;
+ int a, start, end, twoside;
+ char *cp1, *cp2 = NULL;
+ int lglmode;
+
+ glShadeModel(GL_SMOOTH);
+ glDisable(GL_LIGHTING);
+
+ me= ob->data;
+ mface= me->mface;
+
+ /* tekent ie geen hide */
+ if( (G.f & G_FACESELECT) && ob==((G.scene->basact) ? (G.scene->basact->object) : 0)) tface= me->tface;
+ else tface= 0;
+
+ mvert= me->mvert;
+ a= me->totface;
+
+ twoside= me->flag & ME_TWOSIDED;
+ if(col2==0) twoside= 0;
+
+ if(twoside) glEnable(GL_CULL_FACE);
+
+ start= 0; end= me->totface;
+ set_buildvars(ob, &start, &end);
+ mface+= start;
+ if(tface) tface+= start;
+ col1+= 4*start;
+ if(col2) col2+= 4*start;
+
+ dl= find_displist(&ob->disp, DL_VERTS);
+ if(dl) extverts= dl->verts;
+
+ glBegin(lglmode= GL_QUADS);
+
+ cp1= (char *)col1;
+ if(col2) cp2= (char *)col2;
+
+ for(a=start; a<end; a++, mface++, cp1+= 16) {
+ if(mface->v3) {
+ if(tface && (tface->flag & TF_HIDE)) tface++;
+ else {
+ int nglmode= mface->v4?GL_QUADS:GL_TRIANGLES;
+
+ if (nglmode!=lglmode) {
+ glEnd();
+ glBegin(lglmode= nglmode);
+ }
+
+ if(extverts) {
+ v1= extverts+3*mface->v1;
+ v2= extverts+3*mface->v2;
+ v3= extverts+3*mface->v3;
+ if(mface->v4) v4= extverts+3*mface->v4;
+ else v4= 0;
+ }
+ else {
+ v1= (mvert+mface->v1)->co;
+ v2= (mvert+mface->v2)->co;
+ v3= (mvert+mface->v3)->co;
+ if(mface->v4) v4= (mvert+mface->v4)->co;
+ else v4= 0;
+ }
+
+ if(tface) {
+ if(tface->mode & TF_TWOSIDE) glEnable(GL_CULL_FACE);
+ else glDisable(GL_CULL_FACE);
+ }
+
+ glColor3ub(cp1[3], cp1[2], cp1[1]);
+ glVertex3fv( v1 );
+ glColor3ub(cp1[7], cp1[6], cp1[5]);
+ glVertex3fv( v2 );
+ glColor3ub(cp1[11], cp1[10], cp1[9]);
+ glVertex3fv( v3 );
+ if(v4) {
+ glColor3ub(cp1[15], cp1[14], cp1[13]);
+ glVertex3fv( v4 );
+ }
+
+ if(twoside) {
+
+ glColor3ub(cp2[11], cp2[10], cp2[9]);
+ glVertex3fv( v3 );
+ glColor3ub(cp2[7], cp2[6], cp2[5]);
+ glVertex3fv( v2 );
+ glColor3ub(cp2[3], cp2[2], cp2[1]);
+ glVertex3fv( v1 );
+ if(mface->v4) {
+ glColor3ub(cp2[15], cp2[14], cp2[13]);
+ glVertex3fv( v4 );
+ }
+ }
+ }
+ }
+ if(col2) cp2+= 16;
+ }
+
+ glEnd();
+ glShadeModel(GL_FLAT);
+ if(twoside) glDisable(GL_CULL_FACE);
+
+}
+
+static void drawDispList(Object *ob, int dt)
+{
+ ListBase *lb=0;
+ DispList *dl;
+ Mesh *me;
+ int solid;
+
+
+ solid= (dt > OB_WIRE);
+
+ switch(ob->type) {
+ case OB_MESH:
+
+ me= get_mesh(ob);
+ if(me==0) return;
+
+ if(me->bb==0) tex_space_mesh(me);
+ if(me->totface>4) if(boundbox_clip(ob->obmat, me->bb)==0) return;
+
+
+
+ if(dt==OB_SOLID ) {
+
+ lb= &me->disp;
+ if(lb->first==0) addnormalsDispList(ob, lb);
+
+ dl= lb->first;
+ if(dl==0) return;
+
+ if(mesh_uses_displist(me)) {
+ int vertexpaint= (G.f & (G_VERTEXPAINT+G_FACESELECT+G_TEXTUREPAINT+G_WEIGHTPAINT)) && (ob==((G.scene->basact) ? (G.scene->basact->object) : 0));
+
+ /* vertexpaint only true when selecting */
+ if (vertexpaint)
+ drawmeshsolid(ob, NULL);
+ else {
+ init_gl_materials(ob);
+ two_sided(me->flag & ME_TWOSIDED);
+ drawDispListsolid(lb, ob);
+ }
+ }
+ else drawmeshsolid(ob, dl->nors);
+
+ }
+ else if(dt==OB_SHADED) {
+#ifdef __NLA
+ if( G.f & G_WEIGHTPAINT && me->dvert) {
+ unsigned char *wtcol, *curwt;
+ MFace *curface;
+ int i;
+ unsigned char r,g,b;
+ float val1,val2,val3,val4;
+
+ wtcol = curwt= MEM_callocN (sizeof (unsigned char) * me->totface*4*4, "weightmap");
+
+ memset (wtcol, 0x55, sizeof (unsigned char) * me->totface*4*4);
+ for (i=0, curface=(MFace*)me->mface; i<me->totface; i++, curface++){
+
+ val1 = get_mvert_weight (ob, curface->v1, ob->actdef-1);
+ val2 = get_mvert_weight (ob, curface->v2, ob->actdef-1);
+ val3 = get_mvert_weight (ob, curface->v3, ob->actdef-1);
+ if (curface->v4)
+ val4 = get_mvert_weight (ob, curface->v4, ob->actdef-1);
+
+ color_temperature (val1, &r, &g, &b);
+ *curwt++=0; *curwt++=b; *curwt++=g; *curwt++=r;
+ color_temperature (val2, &r, &g, &b);
+ *curwt++=0; *curwt++=b; *curwt++=g; *curwt++=r;
+ color_temperature (val3, &r, &g, &b);
+ *curwt++=0; *curwt++=b; *curwt++=g; *curwt++=r;
+ color_temperature (val4, &r, &g, &b);
+ *curwt++=0; *curwt++=b; *curwt++=g; *curwt++=r;
+
+ }
+
+ drawmeshshaded(ob, (unsigned int*)wtcol, 0);
+ MEM_freeN (wtcol);
+
+ }
+ else
+#endif
+ if( G.f & (G_VERTEXPAINT+G_TEXTUREPAINT)) {
+ /* in deze volgorde: vertexpaint heeft soms al mcol gemaakt */
+///*
+
+//*/
+ if(me->mcol)
+ drawmeshshaded(ob, (unsigned int *)me->mcol, 0);
+ else if(me->tface) {
+ tface_to_mcol(me);
+ drawmeshshaded(ob, (unsigned int *)me->mcol, 0);
+ MEM_freeN(me->mcol); me->mcol= 0;
+ }
+ else
+ drawmeshwire(ob);
+
+ }
+ else {
+ dl= ob->disp.first;
+
+ if(dl==0 || dl->col1==0) {
+ shadeDispList(ob);
+ dl= ob->disp.first;
+ }
+ if(dl) {
+ if(mesh_uses_displist(me))
+ drawDispListshaded(&me->disp, ob);
+ else
+ drawmeshshaded(ob, dl->col1, dl->col2);
+ }
+ }
+ }
+
+ if(ob==((G.scene->basact) ? (G.scene->basact->object) : 0) && (G.f & G_FACESELECT)) {
+ draw_tfaces3D(ob, me);
+ }
+
+ break;
+
+ case OB_FONT:
+ case OB_CURVE:
+
+ lb= &((Curve *)ob->data)->disp;
+ if(lb->first==0) makeDispList(ob);
+
+ if(solid && ob!=G.obedit) {
+ dl= lb->first;
+ if(dl==0) return;
+
+ /* regel: dl->type INDEX3 altijd vooraan in lijst */
+ if(dl->type!=DL_INDEX3) {
+ curve_to_filledpoly(ob->data, lb);
+ dl= lb->first;
+ }
+ if(dl->nors==0) addnormalsDispList(ob, lb);
+
+ index3_nors_incr= 0;
+
+ if(dt==OB_SHADED) {
+ if(ob->disp.first==0) shadeDispList(ob);
+ drawDispListshaded(lb, ob);
+ }
+ else {
+ init_gl_materials(ob);
+ two_sided(0);
+ drawDispListsolid(lb, ob);
+ }
+ index3_nors_incr= 1;
+ }
+ else {
+ draw_index_wire= 0;
+ drawDispListwire(lb);
+ draw_index_wire= 1;
+ }
+ break;
+ case OB_SURF:
+
+ lb= &((Curve *)ob->data)->disp;
+ if(lb->first==0) makeDispList(ob);
+
+ if(solid) {
+ dl= lb->first;
+ if(dl==0) return;
+
+ if(dl->nors==0) addnormalsDispList(ob, lb);
+
+ if(dt==OB_SHADED) {
+ if(ob->disp.first==0) shadeDispList(ob);
+ drawDispListshaded(lb, ob);
+ }
+ else {
+ init_gl_materials(ob);
+ two_sided(0);
+
+ drawDispListsolid(lb, ob);
+ }
+ }
+ else {
+ drawDispListwire(lb);
+ }
+ break;
+ case OB_MBALL:
+
+ lb= &ob->disp;
+ if(lb->first==0) makeDispList(ob);
+
+ if(solid) {
+
+ if(dt==OB_SHADED) {
+ dl= lb->first;
+ if(dl && dl->col1==0) shadeDispList(ob);
+ drawDispListshaded(lb, ob);
+ }
+ else {
+ init_gl_materials(ob);
+ two_sided(0);
+
+ drawDispListsolid(lb, ob);
+ }
+ }
+ else drawDispListwire(lb);
+ break;
+ }
+
+}
+
+/* ******************************** */
+
+
+static void draw_particle_system(Object *ob, PartEff *paf)
+{
+ Particle *pa;
+ float ptime, ctime, vec[3], vec1[3];
+ int a;
+
+ pa= paf->keys;
+ if(pa==0) {
+ build_particle_system(ob);
+ pa= paf->keys;
+ if(pa==0) return;
+ }
+
+ myloadmatrix(G.vd->viewmat);
+
+ if(ob->ipoflag & OB_OFFS_PARTICLE) ptime= ob->sf;
+ else ptime= 0.0;
+ ctime= bsystem_time(ob, 0, (float)(G.scene->r.cfra), ptime);
+
+ glPointSize(1.0);
+ if(paf->stype!=PAF_VECT) glBegin(GL_POINTS);
+
+ for(a=0; a<paf->totpart; a++, pa+=paf->totkey) {
+
+ if(ctime > pa->time) {
+ if(ctime < pa->time+pa->lifetime) {
+
+ if(paf->stype==PAF_VECT) {
+ where_is_particle(paf, pa, ctime, vec);
+ where_is_particle(paf, pa, ctime+1.0, vec1);
+
+
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(vec);
+ glVertex3fv(vec1);
+ glEnd();
+
+ }
+ else {
+ where_is_particle(paf, pa, ctime, vec);
+
+ glVertex3fv(vec);
+
+ }
+ }
+ }
+ }
+ if(paf->stype!=PAF_VECT) glEnd();
+
+}
+
+static void draw_static_particle_system(Object *ob, PartEff *paf)
+{
+ Particle *pa;
+ float ctime, mtime, vec[3], vec1[3];
+ int a;
+
+ pa= paf->keys;
+ if(pa==0) {
+ build_particle_system(ob);
+ pa= paf->keys;
+ if(pa==0) return;
+ }
+
+ glPointSize(1.0);
+ if(paf->stype!=PAF_VECT) glBegin(GL_POINTS);
+
+ for(a=0; a<paf->totpart; a++, pa+=paf->totkey) {
+
+ where_is_particle(paf, pa, pa->time, vec1);
+
+ mtime= pa->time+pa->lifetime+paf->staticstep-1;
+
+ for(ctime= pa->time; ctime<mtime; ctime+=paf->staticstep) {
+
+ /* make sure hair grows until the end.. */
+ if(ctime>pa->time+pa->lifetime) ctime= pa->time+pa->lifetime;
+
+ if(paf->stype==PAF_VECT) {
+ where_is_particle(paf, pa, ctime+1, vec);
+
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(vec);
+ glVertex3fv(vec1);
+ glEnd();
+
+ VECCOPY(vec1, vec);
+ }
+ else {
+ where_is_particle(paf, pa, ctime, vec);
+
+ glVertex3fv(vec);
+
+ }
+ }
+ }
+ if(paf->stype!=PAF_VECT) glEnd();
+
+}
+
+static void drawmeshwire(Object *ob)
+{
+ extern float editbutsize; /* buttons.c */
+ Mesh *me;
+ MVert *mvert;
+ MFace *mface;
+ DispList *dl;
+ Material *ma;
+ EditEdge *eed;
+ EditVlak *evl;
+ float fvec[3], cent[3], *f1, *f2, *f3, *f4, *extverts=0;
+ int a, start, end, test, /* colbcol=0, */ ok;
+
+ me= get_mesh(ob);
+
+ if(ob==G.obedit || (G.obedit && ob->data==G.obedit->data)) {
+
+ if(G.zbuf==0 && mesh_uses_displist(me)) {
+ cpack(0x505050);
+ drawDispListwire(&me->disp);
+ }
+ cpack(0x0);
+
+ eed= G.eded.first;
+
+ glBegin(GL_LINES);
+ while(eed) {
+ if(eed->h==0) {
+ glVertex3fv(eed->v1->co);
+ glVertex3fv(eed->v2->co);
+ }
+ eed= eed->next;
+ }
+ glEnd();
+
+ if(ob!=G.obedit) return;
+
+ calc_meshverts();
+
+ if(G.zbuf) glDisable(GL_DEPTH_TEST);
+ tekenvertices(0);
+ tekenvertices(1);
+#ifdef __NLA
+ tekenvertices(2); /* __TEKENTEST */
+#endif
+ if(G.zbuf) glEnable(GL_DEPTH_TEST);
+
+ if(G.f & G_DRAWNORMALS) { /* normals */
+ cpack(0xDDDD22);
+
+ glBegin(GL_LINES);
+
+ evl= G.edvl.first;
+ while(evl) {
+ if(evl->v1->h==0 && evl->v2->h==0 && evl->v3->h==0) {
+ if(evl->v4) CalcCent4f(fvec, evl->v1->co, evl->v2->co, evl->v3->co, evl->v4->co);
+ else CalcCent3f(fvec, evl->v1->co, evl->v2->co, evl->v3->co);
+
+ glVertex3fv(fvec);
+ fvec[0]+= editbutsize*evl->n[0];
+ fvec[1]+= editbutsize*evl->n[1];
+ fvec[2]+= editbutsize*evl->n[2];
+ glVertex3fv(fvec);
+
+ }
+ evl= evl->next;
+ }
+
+ glEnd();
+ }
+ if(G.f & (G_FACESELECT+G_DRAWFACES)) { /* vlakken */
+
+ evl= G.edvl.first;
+ while(evl) {
+ if(evl->v1->h==0 && evl->v2->h==0 && evl->v3->h==0) {
+
+ if(vlakselectedAND(evl, 1)) cpack(0x559999);
+ else cpack(0x664466);
+
+ if(evl->v4 && evl->v4->h==0) {
+
+ CalcCent4f(cent, evl->v1->co, evl->v2->co, evl->v3->co, evl->v4->co);
+ glBegin(GL_LINE_LOOP);
+ VecMidf(fvec, cent, evl->v1->co); glVertex3fv(fvec);
+ VecMidf(fvec, cent, evl->v2->co); glVertex3fv(fvec);
+ VecMidf(fvec, cent, evl->v3->co); glVertex3fv(fvec);
+ VecMidf(fvec, cent, evl->v4->co); glVertex3fv(fvec);
+ glEnd();
+ }
+ else {
+
+ CalcCent3f(cent, evl->v1->co, evl->v2->co, evl->v3->co);
+ glBegin(GL_LINE_LOOP);
+ VecMidf(fvec, cent, evl->v1->co); glVertex3fv(fvec);
+ VecMidf(fvec, cent, evl->v2->co); glVertex3fv(fvec);
+ VecMidf(fvec, cent, evl->v3->co); glVertex3fv(fvec);
+ glEnd();
+ }
+ }
+ evl= evl->next;
+ }
+ }
+ }
+ else {
+
+ if(me==0) return;
+
+ if(me->bb==0) tex_space_mesh(me);
+ if(me->totface>4) if(boundbox_clip(ob->obmat, me->bb)==0) return;
+
+ if(mesh_uses_displist(me)) drawDispListwire(&me->disp);
+ else {
+
+ mvert= me->mvert;
+ mface= me->mface;
+
+ ok= 0;
+ if(me->totface==0) ok= 1;
+ else {
+ ma= give_current_material(ob, 1);
+ if(ma && (ma->mode & MA_HALO)) ok= 1;
+ }
+
+ dl= find_displist(&ob->disp, DL_VERTS);
+ if(dl) extverts= dl->verts;
+
+ if(ok) {
+
+ start= 0; end= me->totvert;
+ set_buildvars(ob, &start, &end);
+
+ glPointSize(1.5);
+ glBegin(GL_POINTS);
+
+ if(extverts) {
+ extverts+= 3*start;
+ for(a= start; a<end; a++, extverts+=3) {
+ glVertex3fv(extverts);
+ }
+ }
+ else {
+ mvert+= start;
+ for(a= start; a<end; a++, mvert++) {
+ glVertex3fv(mvert->co);
+ }
+ }
+
+ glEnd();
+ glPointSize(1.0);
+ }
+ else {
+
+ start= 0; end= me->totface;
+ set_buildvars(ob, &start, &end);
+ mface+= start;
+
+ for(a=start; a<end; a++, mface++) {
+ test= mface->edcode;
+
+ if(test) {
+ if(extverts) {
+ f1= extverts+3*mface->v1;
+ f2= extverts+3*mface->v2;
+ }
+ else {
+ f1= (mvert+mface->v1)->co;
+ f2= (mvert+mface->v2)->co;
+ }
+
+ if(mface->v4) {
+ if(extverts) {
+ f3= extverts+3*mface->v3;
+ f4= extverts+3*mface->v4;
+ }
+ else {
+ f3= (mvert+mface->v3)->co;
+ f4= (mvert+mface->v4)->co;
+ }
+
+ if(test== ME_V1V2+ME_V2V3+ME_V3V4+ME_V4V1) {
+ glBegin(GL_LINE_LOOP);
+ glVertex3fv(f1); glVertex3fv(f2); glVertex3fv(f3); glVertex3fv(f4);
+ glEnd();
+ }
+ else if(test== ME_V1V2+ME_V2V3+ME_V3V4) {
+
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(f1); glVertex3fv(f2); glVertex3fv(f3); glVertex3fv(f4);
+ glEnd();
+ }
+ else if(test== ME_V2V3+ME_V3V4+ME_V4V1) {
+
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(f2); glVertex3fv(f3); glVertex3fv(f4); glVertex3fv(f1);
+ glEnd();
+ }
+ else if(test== ME_V3V4+ME_V4V1+ME_V1V2) {
+
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(f3); glVertex3fv(f4); glVertex3fv(f1); glVertex3fv(f2);
+ glEnd();
+ }
+ else if(test== ME_V4V1+ME_V1V2+ME_V2V3) {
+
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(f4); glVertex3fv(f1); glVertex3fv(f2); glVertex3fv(f3);
+ glEnd();
+ }
+ else {
+ if(test & ME_V1V2) {
+
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(f1); glVertex3fv(f2);
+ glEnd();
+ }
+ if(test & ME_V2V3) {
+
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(f2); glVertex3fv(f3);
+ glEnd();
+ }
+ if(test & ME_V3V4) {
+
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(f3); glVertex3fv(f4);
+ glEnd();
+ }
+ if(test & ME_V4V1) {
+
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(f4); glVertex3fv(f1);
+ glEnd();
+ }
+ }
+ }
+ else if(mface->v3) {
+ if(extverts) f3= extverts+3*mface->v3;
+ else f3= (mvert+mface->v3)->co;
+
+ if(test== ME_V1V2+ME_V2V3+ME_V3V1) {
+ glBegin(GL_LINE_LOOP);
+ glVertex3fv(f1); glVertex3fv(f2); glVertex3fv(f3);
+ glEnd();
+ }
+ else if(test== ME_V1V2+ME_V2V3) {
+
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(f1); glVertex3fv(f2); glVertex3fv(f3);
+ glEnd();
+ }
+ else if(test== ME_V2V3+ME_V3V1) {
+
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(f2); glVertex3fv(f3); glVertex3fv(f1);
+ glEnd();
+ }
+ else if(test== ME_V1V2+ME_V3V1) {
+
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(f3); glVertex3fv(f1); glVertex3fv(f2);
+ glEnd();
+ }
+ else {
+ if(test & ME_V1V2) {
+
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(f1); glVertex3fv(f2);
+ glEnd();
+ }
+ if(test & ME_V2V3) {
+
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(f2); glVertex3fv(f3);
+ glEnd();
+ }
+ if(test & ME_V3V1) {
+
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(f3); glVertex3fv(f1);
+ glEnd();
+ }
+ }
+ }
+ else if(test & ME_V1V2) {
+
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(f1); glVertex3fv(f2);
+ glEnd();
+ }
+ }
+ }
+ }
+
+ }
+ }
+}
+
+unsigned int nurbcol[8]= {
+ 0, 0x9090, 0x409030, 0x603080, 0, 0x40fff0, 0x40c033, 0xA090F0 };
+
+static void tekenhandlesN(Nurb *nu, short sel)
+{
+ BezTriple *bezt;
+ float *fp;
+ unsigned int *col;
+ int a;
+
+ if(nu->hide) return;
+ if( (nu->type & 7)==1) {
+ if(sel) col= nurbcol+4;
+ else col= nurbcol;
+
+ bezt= nu->bezt;
+ a= nu->pntsu;
+ while(a--) {
+ if(bezt->hide==0) {
+ if( (bezt->f2 & 1)==sel) {
+ fp= bezt->vec[0];
+ cpack(col[bezt->h1]);
+
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(fp);
+ glVertex3fv(fp+3);
+ glEnd();
+ cpack(col[bezt->h2]);
+
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(fp+3);
+ glVertex3fv(fp+6);
+ glEnd();
+ }
+ else if( (bezt->f1 & 1)==sel) {
+ fp= bezt->vec[0];
+ cpack(col[bezt->h1]);
+
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(fp);
+ glVertex3fv(fp+3);
+ glEnd();
+ }
+ else if( (bezt->f3 & 1)==sel) {
+ fp= bezt->vec[1];
+ cpack(col[bezt->h2]);
+
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(fp);
+ glVertex3fv(fp+3);
+ glEnd();
+ }
+ }
+ bezt++;
+ }
+ }
+}
+
+static void tekenvertsN(Nurb *nu, short sel)
+{
+ BezTriple *bezt;
+ BPoint *bp;
+ int a;
+
+ if(nu->hide) return;
+
+ if(sel) cpack(B_YELLOW);
+ else cpack(B_PURPLE);
+ glPointSize(3.0);
+
+ glBegin(GL_POINTS);
+
+ if((nu->type & 7)==1) {
+
+ bezt= nu->bezt;
+ a= nu->pntsu;
+ while(a--) {
+ if(bezt->hide==0) {
+ if((bezt->f1 & 1)==sel) glVertex3fv(bezt->vec[0]);
+ if((bezt->f2 & 1)==sel) glVertex3fv(bezt->vec[1]);
+ if((bezt->f3 & 1)==sel) glVertex3fv(bezt->vec[2]);
+ }
+ bezt++;
+ }
+ }
+ else {
+ bp= nu->bp;
+ a= nu->pntsu*nu->pntsv;
+ while(a--) {
+ if(bp->hide==0) {
+ if((bp->f1 & 1)==sel) glVertex3fv(bp->vec);
+ }
+ bp++;
+ }
+ }
+
+ glEnd();
+ glPointSize(1.0);
+}
+
+static void draw_editnurb(Object *ob, Nurb *nurb, int sel)
+{
+ Nurb *nu;
+ BPoint *bp, *bp1;
+ int a, b, ofs;
+
+ nu= nurb;
+ while(nu) {
+ if(nu->hide==0) {
+ switch(nu->type & 7) {
+ case CU_POLY:
+ cpack(nurbcol[3]);
+ bp= nu->bp;
+ for(b=0; b<nu->pntsv; b++) {
+ if(nu->flagu & 1) glBegin(GL_LINE_LOOP);
+
+ else glBegin(GL_LINE_STRIP);
+
+ for(a=0; a<nu->pntsu; a++, bp++) {
+ glVertex3fv(bp->vec);
+ }
+
+ if(nu->flagu & 1) glEnd();
+ else glEnd();
+ }
+ break;
+ case CU_NURBS:
+
+ bp= nu->bp;
+ for(b=0; b<nu->pntsv; b++) {
+ bp1= bp;
+ bp++;
+ for(a=nu->pntsu-1; a>0; a--, bp++) {
+ if(bp->hide==0 && bp1->hide==0) {
+ if(sel) {
+ if( (bp->f1 & 1) && ( bp1->f1 & 1) ) {
+ cpack(nurbcol[5]);
+
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(bp->vec);
+ glVertex3fv(bp1->vec);
+ glEnd();
+ }
+ }
+ else {
+ if( (bp->f1 & 1) && ( bp1->f1 & 1) );
+ else {
+ cpack(nurbcol[1]);
+
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(bp->vec);
+ glVertex3fv(bp1->vec);
+ glEnd();
+ }
+ }
+ }
+ bp1= bp;
+ }
+ }
+ if(nu->pntsv > 1) { /* surface */
+
+ ofs= nu->pntsu;
+ for(b=0; b<nu->pntsu; b++) {
+ bp1= nu->bp+b;
+ bp= bp1+ofs;
+ for(a=nu->pntsv-1; a>0; a--, bp+=ofs) {
+ if(bp->hide==0 && bp1->hide==0) {
+ if(sel) {
+ if( (bp->f1 & 1) && ( bp1->f1 & 1) ) {
+ cpack(nurbcol[7]);
+
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(bp->vec);
+ glVertex3fv(bp1->vec);
+ glEnd();
+ }
+ }
+ else {
+ if( (bp->f1 & 1) && ( bp1->f1 & 1) );
+ else {
+ cpack(nurbcol[3]);
+
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(bp->vec);
+ glVertex3fv(bp1->vec);
+ glEnd();
+ }
+ }
+ }
+ bp1= bp;
+ }
+ }
+
+ }
+ break;
+ }
+ }
+ nu= nu->next;
+ }
+}
+
+static void drawnurb(Object *ob, Nurb *nurb, int dt)
+{
+ extern float editbutsize; /* buttons.c */
+ Curve *cu;
+ Nurb *nu;
+ BevPoint *bevp;
+ BevList *bl;
+ float vec[3];
+ int a, nr, skip;
+
+ /* eerst handles niet select */
+ nu= nurb;
+ while(nu) {
+ if((nu->type & 7)==CU_BEZIER) {
+ tekenhandlesN(nu, 0);
+ }
+ nu= nu->next;
+ }
+
+ /* dan DispList */
+
+ cpack(0);
+ cu= ob->data;
+ drawDispList(ob, dt);
+
+ draw_editnurb(ob, nurb, 0);
+ draw_editnurb(ob, nurb, 1);
+
+ if(cu->flag & CU_3D) {
+
+ if(cu->bev.first==0) makeBevelList(ob);
+
+ cpack(0x0);
+ bl= cu->bev.first;
+ nu= nurb;
+ while(nu && bl) {
+ bevp= (BevPoint *)(bl+1);
+ nr= bl->nr;
+
+ skip= nu->resolu/16;
+
+ while(nr-- > 0) {
+
+ glBegin(GL_LINE_STRIP);
+ vec[0]= bevp->x-editbutsize*bevp->mat[0][0];
+ vec[1]= bevp->y-editbutsize*bevp->mat[0][1];
+ vec[2]= bevp->z-editbutsize*bevp->mat[0][2];
+ glVertex3fv(vec);
+ vec[0]= bevp->x+editbutsize*bevp->mat[0][0];
+ vec[1]= bevp->y+editbutsize*bevp->mat[0][1];
+ vec[2]= bevp->z+editbutsize*bevp->mat[0][2];
+ glVertex3fv(vec);
+
+ glEnd();
+
+ bevp++;
+
+ a= skip;
+ while(a--) {
+ bevp++;
+ nr--;
+ }
+ }
+
+ bl= bl->next;
+ nu= nu->next;
+ }
+ }
+
+ calc_Nurbverts(nurb);
+
+ if(G.zbuf) glDisable(GL_DEPTH_TEST);
+
+ nu= nurb;
+ while(nu) {
+ if((nu->type & 7)==1) tekenhandlesN(nu, 1);
+ tekenvertsN(nu, 0);
+ nu= nu->next;
+ }
+
+ nu= nurb;
+ while(nu) {
+ tekenvertsN(nu, 1);
+ nu= nu->next;
+ }
+
+ if(G.zbuf) glEnable(GL_DEPTH_TEST);
+}
+
+static void tekentextcurs(void)
+{
+ cpack(0);
+
+ glBegin(GL_QUADS);
+ glVertex2fv(G.textcurs[0]);
+ glVertex2fv(G.textcurs[1]);
+ glVertex2fv(G.textcurs[2]);
+ glVertex2fv(G.textcurs[3]);
+ glEnd();
+}
+
+void drawcircball(float *cent, float rad, float tmat[][4])
+{
+ float si, co, phi, dphi, vec[3], vx[3], vy[3];
+ int a, tot=32;
+
+ VECCOPY(vx, tmat[0]);
+ VECCOPY(vy, tmat[1]);
+ VecMulf(vx, rad);
+ VecMulf(vy, rad);
+
+ dphi= 2.0*M_PI/tot;
+ phi= 0.0;
+
+ glBegin(GL_LINE_LOOP);
+ for(a=0; a<tot; a++, phi+= dphi) {
+ si= sin(phi);
+ co= cos(phi);
+ vec[0]= cent[0]+si*vx[0]+co*vy[0];
+ vec[1]= cent[1]+si*vx[1]+co*vy[1];
+ vec[2]= cent[2]+si*vx[2]+co*vy[2];
+ glVertex3fv(vec);
+ }
+ glEnd();
+}
+
+static void drawmball(Object *ob, int dt)
+{
+ MetaBall *mb;
+ MetaElem *ml;
+ float imat[4][4], tmat[4][4];
+ int code= 1;
+
+ mb= ob->data;
+
+ if(ob==G.obedit) {
+ cpack(0x0);
+ if((G.f & G_PICKSEL)==0 ) drawDispList(ob, dt);
+ ml= editelems.first;
+ }
+ else {
+ drawDispList(ob, dt);
+ ml= mb->elems.first;
+ }
+
+ mygetmatrix(tmat);
+ Mat4Invert(imat, tmat);
+ Normalise(imat[0]);
+ Normalise(imat[1]);
+
+ while(ml) {
+
+ if(ob==G.obedit) {
+ if(ml->flag & SELECT) cpack(0xA0A0F0);
+ else cpack(0x3030A0);
+
+ if(G.f & G_PICKSEL) {
+ ml->selcol= code;
+ glLoadName(code++);
+ }
+ }
+ drawcircball(&(ml->x), ml->rad, imat);
+
+ ml= ml->next;
+ }
+
+}
+
+static void draw_bb_box(BoundBox *bb)
+{
+ float *vec;
+
+ vec= bb->vec[0];
+
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(vec); glVertex3fv(vec+3);glVertex3fv(vec+6); glVertex3fv(vec+9);
+ glVertex3fv(vec); glVertex3fv(vec+12);glVertex3fv(vec+15); glVertex3fv(vec+18);
+ glVertex3fv(vec+21); glVertex3fv(vec+12);
+ glEnd();
+
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(vec+3); glVertex3fv(vec+15);
+ glEnd();
+
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(vec+6); glVertex3fv(vec+18);
+ glEnd();
+
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(vec+9); glVertex3fv(vec+21);
+ glEnd();
+
+}
+
+void get_local_bounds(Object *ob, float *centre, float *size)
+{
+ BoundBox *bb= NULL;
+ /* uses boundbox, function used by Ketsji */
+
+ if(ob->type==OB_MESH) {
+ bb= ( (Mesh *)ob->data )->bb;
+ if(bb==0) {
+ tex_space_mesh(ob->data);
+ bb= ( (Mesh *)ob->data )->bb;
+ }
+ }
+ else if ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT) {
+ bb= ( (Curve *)ob->data )->bb;
+ }
+ else if(ob->type==OB_MBALL) {
+ bb= ob->bb;
+ }
+ if(bb==NULL) {
+ centre[0]= centre[1]= centre[2]= 0.0;
+ VECCOPY(size, ob->size);
+ }
+ else {
+ size[0]= 0.5*fabs(bb->vec[0][0] - bb->vec[4][0]);
+ size[1]= 0.5*fabs(bb->vec[0][1] - bb->vec[2][1]);
+ size[2]= 0.5*fabs(bb->vec[0][2] - bb->vec[1][2]);
+
+ centre[0]= (bb->vec[0][0] + bb->vec[4][0])/2.0;
+ centre[1]= (bb->vec[0][1] + bb->vec[2][1])/2.0;
+ centre[2]= (bb->vec[0][2] + bb->vec[1][2])/2.0;
+ }
+}
+
+
+
+static void draw_bb_quadric(BoundBox *bb, short type)
+{
+ float size[3], cent[3];
+ GLUquadricObj *qobj = gluNewQuadric();
+
+ gluQuadricDrawStyle(qobj, GLU_SILHOUETTE);
+
+ size[0]= 0.5*fabs(bb->vec[0][0] - bb->vec[4][0]);
+ size[1]= 0.5*fabs(bb->vec[0][1] - bb->vec[2][1]);
+ size[2]= 0.5*fabs(bb->vec[0][2] - bb->vec[1][2]);
+
+ cent[0]= (bb->vec[0][0] + bb->vec[4][0])/2.0;
+ cent[1]= (bb->vec[0][1] + bb->vec[2][1])/2.0;
+ cent[2]= (bb->vec[0][2] + bb->vec[1][2])/2.0;
+
+ if(type==OB_BOUND_SPHERE) {
+ glTranslatef(cent[0], cent[1], cent[2]);
+ glScalef(size[0], size[1], size[2]);
+ gluSphere(qobj, 1.0, 8, 5);
+ }
+ else if(type==OB_BOUND_CYLINDER) {
+ glTranslatef(cent[0], cent[1], cent[2]-size[2]);
+ glScalef(size[0], size[1], 2.0*size[2]);
+ gluCylinder(qobj, 1.0, 1.0, 1.0, 8, 1);
+ }
+ else if(type==OB_BOUND_CONE) {
+ glTranslatef(cent[0], cent[1], cent[2]-size[2]);
+ glScalef(size[0], size[1], 2.0*size[2]);
+ gluCylinder(qobj, 1.0, 0.0, 1.0, 8, 1);
+ }
+
+ gluDeleteQuadric(qobj);
+}
+
+static void draw_bounding_volume(Object *ob)
+{
+ BoundBox *bb=0;
+
+ if(ob->type==OB_MESH) {
+ bb= ( (Mesh *)ob->data )->bb;
+ if(bb==0) {
+ tex_space_mesh(ob->data);
+ bb= ( (Mesh *)ob->data )->bb;
+ }
+ }
+ else if ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT) {
+ bb= ( (Curve *)ob->data )->bb;
+ if(bb==0) {
+ makeDispList(ob);
+ bb= ( (Curve *)ob->data )->bb;
+ }
+ }
+ else if(ob->type==OB_MBALL) {
+ bb= ob->bb;
+ if(bb==0) {
+ makeDispList(ob);
+ bb= ob->bb;
+ }
+ }
+ else {
+ drawcube();
+ return;
+ }
+
+ if(bb==0) return;
+
+ if(ob->boundtype==OB_BOUND_BOX) draw_bb_box(bb);
+ else draw_bb_quadric(bb, ob->boundtype);
+
+}
+
+static void drawtexspace(Object *ob)
+{
+ Mesh *me;
+ MetaBall *mb;
+ Curve *cu;
+ BoundBox bb;
+ float *vec, *loc, *size;
+
+ if(ob->type==OB_MESH) {
+ me= ob->data;
+ size= me->size;
+ loc= me->loc;
+ }
+ else if ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT) {
+ cu= ob->data;
+ size= cu->size;
+ loc= cu->loc;
+ }
+ else if(ob->type==OB_MBALL) {
+ mb= ob->data;
+ size= mb->size;
+ loc= mb->loc;
+ }
+ else return;
+
+ bb.vec[0][0]=bb.vec[1][0]=bb.vec[2][0]=bb.vec[3][0]= loc[0]-size[0];
+ bb.vec[4][0]=bb.vec[5][0]=bb.vec[6][0]=bb.vec[7][0]= loc[0]+size[0];
+
+ bb.vec[0][1]=bb.vec[1][1]=bb.vec[4][1]=bb.vec[5][1]= loc[1]-size[1];
+ bb.vec[2][1]=bb.vec[3][1]=bb.vec[6][1]=bb.vec[7][1]= loc[1]+size[1];
+
+ bb.vec[0][2]=bb.vec[3][2]=bb.vec[4][2]=bb.vec[7][2]= loc[2]-size[2];
+ bb.vec[1][2]=bb.vec[2][2]=bb.vec[5][2]=bb.vec[6][2]= loc[2]+size[2];
+
+ setlinestyle(2);
+
+ vec= bb.vec[0];
+
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(vec); glVertex3fv(vec+3);glVertex3fv(vec+6); glVertex3fv(vec+9);
+ glVertex3fv(vec); glVertex3fv(vec+12);glVertex3fv(vec+15); glVertex3fv(vec+18);
+ glVertex3fv(vec+21); glVertex3fv(vec+12);
+ glEnd();
+
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(vec+3); glVertex3fv(vec+15);
+ glEnd();
+
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(vec+6); glVertex3fv(vec+18);
+ glEnd();
+
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(vec+9); glVertex3fv(vec+21);
+ glEnd();
+
+ setlinestyle(0);
+}
+
+static int ob_from_decimator(Object *ob)
+{
+ /* note: this is a temporal solution, a reconstruction of the
+ displist system should take care of it (ton)
+ */
+ DispList *dl;
+
+ dl= ob->disp.first;
+
+ if(dl && dl->mesh) return 1;
+
+ return 0;
+}
+
+void draw_object(Base *base)
+{
+ PartEff *paf;
+ Object *ob;
+ Curve *cu;
+ Mesh *me;
+ ListBase elems;
+ CfraElem *ce;
+ float cfraont, axsize=1.0;
+ unsigned int *rect, col=0;
+ static int warning_recursive= 0;
+ int sel, drawtype, colindex= 0, ipoflag;
+ short dt, dtx, zbufoff= 0;
+
+ ob= base->object;
+
+ /* keys tekenen? */
+ if(base==(G.scene->basact) || (base->flag & (SELECT+BA_WASSEL))) {
+ if(warning_recursive==0 && ob!=G.obedit) {
+ if(ob->ipo && ob->ipo->showkey && (ob->ipoflag & OB_DRAWKEY)) {
+ float temp[7][3];
+
+ warning_recursive= 1;
+
+ elems.first= elems.last= 0;
+ make_cfra_list(ob->ipo, &elems);
+
+ cfraont= (G.scene->r.cfra);
+ drawtype= G.vd->drawtype;
+ if(drawtype>OB_WIRE) G.vd->drawtype= OB_WIRE;
+ sel= base->flag;
+ memcpy(temp, &ob->loc, 7*3*sizeof(float));
+
+ ipoflag= ob->ipoflag;
+ ob->ipoflag &= ~OB_OFFS_OB;
+
+ set_no_parent_ipo(1);
+ disable_speed_curve(1);
+
+ if ((ob->ipoflag & OB_DRAWKEYSEL)==0) {
+ ce= elems.first;
+ while(ce) {
+ if(!ce->sel) {
+ (G.scene->r.cfra)= ce->cfra/G.scene->r.framelen;
+
+ base->flag= 0;
+
+ where_is_object_time(ob, (G.scene->r.cfra));
+ draw_object(base);
+ }
+ ce= ce->next;
+ }
+ }
+
+ ce= elems.first;
+ while(ce) {
+ if(ce->sel) {
+ (G.scene->r.cfra)= ce->cfra/G.scene->r.framelen;
+
+ base->flag= SELECT;
+
+ where_is_object_time(ob, (G.scene->r.cfra));
+ draw_object(base);
+ }
+ ce= ce->next;
+ }
+
+ set_no_parent_ipo(0);
+ disable_speed_curve(0);
+
+ base->flag= sel;
+ ob->ipoflag= ipoflag;
+
+ /* restore icu->curval */
+ (G.scene->r.cfra)= cfraont;
+
+ memcpy(&ob->loc, temp, 7*3*sizeof(float));
+ where_is_object(ob);
+ G.vd->drawtype= drawtype;
+
+ BLI_freelistN(&elems);
+
+ warning_recursive= 0;
+ }
+ }
+ }
+
+ /* patch? kinderen met timeoffs verprutsen ouders. Hoe los je dat op! */
+ /* if( ((int)ob->ctime) != F_(G.scene->r.cfra)) where_is_object(ob); */
+
+ mymultmatrix(ob->obmat);
+
+ /* welke wire kleur */
+ if((G.f & (G_BACKBUFSEL+G_PICKSEL)) == 0) {
+ project_short(ob->obmat[3], &base->sx);
+
+ if(G.moving==1 && (base->flag & (SELECT+BA_PARSEL))) colindex= 12;
+ else {
+ if((G.scene->basact)==base) {
+ if(base->flag & (SELECT+BA_WASSEL)) colindex= 2;
+ }
+ else {
+ if(base->flag & (SELECT+BA_WASSEL)) colindex= 1;
+ }
+ if(ob->id.lib) colindex+= 3;
+ else if(warning_recursive==1) colindex+= 6;
+ else if(ob->flag & OB_FROMGROUP) colindex+= 9;
+ }
+
+ col= colortab[colindex];
+ cpack(col);
+
+ }
+
+ /* maximum drawtype */
+ dt= MIN2(G.vd->drawtype, ob->dt);
+ if(G.zbuf==0 && dt>OB_WIRE) dt= OB_WIRE;
+ dtx= 0;
+
+ /* faceselect uitzondering: ook solid tekenen als dt==wire, behalve in editmode */
+ if(ob==((G.scene->basact) ? (G.scene->basact->object) : 0) && (G.f & (G_FACESELECT+G_VERTEXPAINT+G_TEXTUREPAINT+G_WEIGHTPAINT))) {
+ if(ob->type==OB_MESH) {
+
+ if(ob==G.obedit) dt= OB_WIRE;
+ else {
+ if(G.f & G_BACKBUFSEL) dt= OB_SOLID;
+ else dt= OB_SHADED;
+
+ glClearDepth(1.0); glClear(GL_DEPTH_BUFFER_BIT);
+ glEnable(GL_DEPTH_TEST);
+ zbufoff= 1;
+ }
+ }
+ else {
+ if(dt<OB_SOLID) {
+ dt= OB_SOLID;
+ glClearDepth(1.); glClear(GL_DEPTH_BUFFER_BIT);
+ glEnable(GL_DEPTH_TEST);
+ zbufoff= 1;
+ }
+ }
+ }
+ else if(dt>=OB_WIRE ) {
+
+ if(dt>OB_SOLID) if(G.f & G_BACKBUFSEL) dt= OB_SOLID;
+
+ dtx= ob->dtx;
+ if(G.obedit==ob) {
+ if(dtx & OB_TEXSPACE) dtx= OB_TEXSPACE;
+ else dtx= 0;
+ }
+
+ if(G.f & G_DRAW_EXT) {
+ if(ob->type==OB_EMPTY || ob->type==OB_CAMERA || ob->type==OB_LAMP) dt= OB_WIRE;
+ }
+
+ }
+
+ if( (G.f & G_DRAW_EXT) && dt>OB_WIRE) {
+
+ switch( ob->type) {
+ case OB_MBALL:
+ drawmball(ob, dt);
+ break;
+ }
+ }
+ else {
+
+ switch( ob->type) {
+
+ case OB_MESH:
+ me= ob->data;
+
+#if 1
+#ifdef __NLA
+ /* Force a refresh of the display list if the parent is an armature */
+ if (ob->parent && ob->parent->type==OB_ARMATURE && ob->partype==PARSKEL){
+#if 0 /* Turn this on if there are problems with deformation lag */
+ where_is_armature (ob->parent);
+#endif
+ if (ob != G.obedit)
+ makeDispList (ob);
+ }
+#endif
+#endif
+ if(base->flag & OB_RADIO);
+ else if(ob==G.obedit || (G.obedit && ob->data==G.obedit->data)) {
+ if(dt<=OB_WIRE) drawmeshwire(ob);
+ else {
+ if(mesh_uses_displist(me)) {
+ init_gl_materials(ob);
+ two_sided( me->flag & ME_TWOSIDED );
+ drawDispListsolid(&me->disp, ob);
+ drawmeshwire(ob);
+ }
+ else drawmeshsolid(ob, 0);
+ }
+ if(ob==G.obedit && (G.f & G_PROPORTIONAL)) draw_prop_circle();
+ }
+ else {
+ Material *ma= give_current_material(ob, 1);
+
+ if(ob_from_decimator(ob)) drawDispListwire(&ob->disp);
+ else if(dt==OB_BOUNDBOX) draw_bounding_volume(ob);
+ else if(dt==OB_WIRE) drawmeshwire(ob);
+ else if(ma && (ma->mode & MA_HALO)) drawmeshwire(ob);
+ else if(me->tface) {
+ if(G.f & G_BACKBUFSEL) drawmeshsolid(ob, 0);
+ else if(G.f & G_FACESELECT || G.vd->drawtype==OB_TEXTURE) draw_tface_mesh(ob, ob->data, dt);
+ else drawDispList(ob, dt);
+ }
+ else drawDispList(ob, dt);
+ }
+ if( (ob!=G.obedit)
+ && ((G.f & (G_BACKBUFSEL+G_PICKSEL)) == 0) ) {
+ paf = give_parteff(ob);
+ if( paf ) {
+ if(col) cpack(0xFFFFFF); /* zichtbaarheid */
+ if(paf->flag & PAF_STATIC) draw_static_particle_system(ob, paf);
+ else draw_particle_system(ob, paf);
+ cpack(col);
+ }
+ }
+
+ break;
+ case OB_FONT:
+ cu= ob->data;
+ if(ob==G.obedit) {
+ tekentextcurs();
+ cpack(0xFFFF90);
+ drawDispList(ob, OB_WIRE);
+ }
+ else if(dt==OB_BOUNDBOX) draw_bounding_volume(ob);
+ else if(boundbox_clip(ob->obmat, cu->bb)) drawDispList(ob, dt);
+
+ break;
+ case OB_CURVE:
+ case OB_SURF:
+ cu= ob->data;
+ /* een pad niet solid tekenen: wel dus!!! */
+ /* if(cu->flag & CU_PATH) if(dt>OB_WIRE) dt= OB_WIRE; */
+
+ if(ob==G.obedit) {
+ drawnurb(ob, editNurb.first, dt);
+ if((G.f & G_PROPORTIONAL)) draw_prop_circle();
+ }
+ else if(dt==OB_BOUNDBOX) draw_bounding_volume(ob);
+ else if(boundbox_clip(ob->obmat, cu->bb)) drawDispList(ob, dt);
+
+ break;
+ case OB_MBALL:
+ if(ob==G.obedit) drawmball(ob, dt);
+ else if(dt==OB_BOUNDBOX) draw_bounding_volume(ob);
+ else drawmball(ob, dt);
+ break;
+ case OB_EMPTY:
+ drawaxes(1.0);
+ break;
+ case OB_LAMP:
+ /* doet myloadmatrix */
+ drawlamp(ob);
+ break;
+ case OB_CAMERA:
+ drawcamera(ob);
+ break;
+ case OB_LATTICE:
+ drawlattice(ob);
+ if(ob==G.obedit && (G.f & G_PROPORTIONAL)) draw_prop_circle();
+ break;
+ case OB_IKA:
+ draw_ika(ob, base->flag & SELECT);
+ break;
+#ifdef __NLA
+ case OB_ARMATURE:
+ draw_armature (ob);
+ break;
+#endif
+ default:
+ drawaxes(1.0);
+ }
+ }
+
+ /* draw extra: na gewone draw ivm makeDispList */
+ if(dtx) {
+ if(G.f & G_SIMULATION);
+ else if(dtx & OB_AXIS) {
+ drawaxes(axsize);
+ }
+ if(dtx & OB_BOUNDBOX) draw_bounding_volume(ob);
+ if(dtx & OB_TEXSPACE) drawtexspace(ob);
+ if(dtx & OB_DRAWNAME) {
+ if(ob->type==OB_LAMP) glRasterPos3fv(ob->obmat[3]);
+ else glRasterPos3f(0.0, 0.0, 0.0);
+
+ BMF_DrawString(G.font, " ");
+ BMF_DrawString(G.font, ob->id.name+2);
+ }
+ if(dtx & OB_DRAWIMAGE) drawDispListwire(&ob->disp);
+ }
+
+ if(dt<OB_SHADED) {
+ if((ob->gameflag & OB_ACTOR) && (ob->gameflag & OB_DYNAMIC)) {
+ float tmat[4][4], imat[4][4], vec[3];
+
+ vec[0]= vec[1]= vec[2]= 0.0;
+ mygetmatrix(tmat);
+ Mat4Invert(imat, tmat);
+
+ setlinestyle(2);
+ drawcircball(vec, ob->inertia, imat);
+ setlinestyle(0);
+ }
+ }
+
+ myloadmatrix(G.vd->viewmat);
+
+ if(zbufoff) glDisable(GL_DEPTH_TEST);
+
+ if(warning_recursive) return;
+ if(base->flag & OB_FROMDUPLI) return;
+ if(base->flag & OB_RADIO) return;
+ if(G.f & G_SIMULATION) return;
+
+ if((G.f & (G_BACKBUFSEL+G_PICKSEL))==0) {
+ /* hulplijnen e.d. */
+ if(ob->parent && (ob->parent->lay & G.vd->lay)) {
+ setlinestyle(3);
+ glBegin(GL_LINES);
+ glVertex3fv(ob->obmat[3]);
+ glVertex3fv(ob->orig);
+ glEnd();
+ setlinestyle(0);
+ }
+
+ /* object centers */
+ if(G.zbuf) glDisable(GL_DEPTH_TEST);
+ if(ob->type == OB_LAMP) {
+ if(ob->id.lib) {
+ if(base->flag & SELECT) rect= rectllib_sel;
+ else rect= rectllib_desel;
+ }
+ else if(ob->id.us>1) {
+ if(base->flag & SELECT) rect= rectlus_sel;
+ else rect= rectlus_desel;
+ }
+ else {
+ if(base->flag & SELECT) rect= rectl_sel;
+ else rect= rectl_desel;
+ }
+ draw_icon_centered(ob->obmat[3], rect, 9);
+ }
+ else {
+ if(ob->id.lib || ob->id.us>1) {
+ if(base->flag & SELECT) rect= rectu_sel;
+ else rect= rectu_desel;
+ }
+ else {
+ if(base->flag & SELECT) rect= rect_sel;
+ else if(base==(G.scene->basact)) rect= rect_sel;
+ else rect= rect_desel;
+ }
+ draw_icon_centered(ob->obmat[3], rect, 4);
+ }
+ if(G.zbuf) glEnable(GL_DEPTH_TEST);
+
+ }
+ else if((G.f & (G_VERTEXPAINT|G_FACESELECT|G_TEXTUREPAINT|G_WEIGHTPAINT))==0) {
+
+ glBegin(GL_POINTS);
+ glVertex3fv(ob->obmat[3]);
+ glEnd();
+
+ }
+}
+
+void draw_object_ext(Base *base)
+{
+ ScrArea *tempsa, *sa;
+ View3D *vd;
+
+ if(G.vd==0) return;
+
+ if(G.vd->drawtype > OB_WIRE) {
+ G.zbuf= 1;
+ glEnable(GL_DEPTH_TEST);
+ }
+
+ G.f |= G_DRAW_EXT;
+
+ glDrawBuffer(GL_FRONT);
+
+ /* alle views aflopen */
+ tempsa= curarea;
+ sa= G.curscreen->areabase.first;
+ while(sa) {
+ if(sa->spacetype==SPACE_VIEW3D) {
+ /* er wordt beperkt in beide buffers getekend: selectbuffer! */
+
+ vd= sa->spacedata.first;
+ if(base->lay & vd->lay) {
+ areawinset(sa->win);
+
+ draw_object(base);
+
+ sa->win_swap= WIN_FRONT_OK;
+ }
+ }
+ sa= sa->next;
+ }
+ if(curarea!=tempsa) areawinset(tempsa->win);
+
+ G.f &= ~G_DRAW_EXT;
+
+ glFinish();
+ glDrawBuffer(GL_BACK);
+
+ if(G.zbuf) {
+ G.zbuf= 0;
+ glDisable(GL_DEPTH_TEST);
+ }
+}
diff --git a/source/blender/src/drawoops.c b/source/blender/src/drawoops.c
new file mode 100644
index 00000000000..c37d7747c28
--- /dev/null
+++ b/source/blender/src/drawoops.c
@@ -0,0 +1,437 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 <string.h>
+#include <math.h>
+
+#ifdef _WIN32
+#include "BLI_winstuff.h"
+#endif
+
+#include "BMF_Api.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+
+#include "DNA_ID.h"
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+#include "DNA_oops_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_view2d_types.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_global.h"
+
+#include "BIF_gl.h"
+#include "BIF_interface.h"
+#include "BIF_glutil.h"
+#include "BIF_resources.h"
+#include "BIF_screen.h"
+#include "BIF_interface.h"
+#include "BIF_mywindow.h"
+
+/* #include "BIF_drawoops.h" bad name :(*/
+#include "BIF_oops.h"
+
+#include "BSE_drawipo.h"
+#include "BSE_drawoops.h"
+#include "interface.h"
+
+float oopscalex;
+
+void boundbox_oops()
+{
+ Oops *oops;
+ float min[2], max[2];
+ int ok= 0;
+
+ if(G.soops==0) return;
+
+ min[0]= 1000.0;
+ max[0]= -10000.0;
+ min[1]= 1000.0;
+ max[1]= -1000.0;
+
+ oops= G.soops->oops.first;
+ while(oops) {
+ if(oops->hide==0) {
+ ok= 1;
+
+ min[0]= MIN2(min[0], oops->x);
+ max[0]= MAX2(max[0], oops->x+OOPSX);
+ min[1]= MIN2(min[1], oops->y);
+ max[1]= MAX2(max[1], oops->y+OOPSY);
+ }
+ oops= oops->next;
+ }
+
+ if(ok==0) return;
+
+ G.v2d->tot.xmin= min[0];
+ G.v2d->tot.xmax= max[0];
+ G.v2d->tot.ymin= min[1];
+ G.v2d->tot.ymax= max[1];
+
+}
+
+void give_oopslink_line(Oops *oops, OopsLink *ol, float *v1, float *v2)
+{
+
+ if(ol->to && ol->to->hide==0) {
+ v1[0]= oops->x+ol->xof;
+ v1[1]= oops->y+ol->yof;
+ v2[0]= ol->to->x+OOPSX/2;
+ v2[1]= ol->to->y;
+ }
+ else if(ol->from && ol->from->hide==0) {
+ v1[0]= ol->from->x + ol->xof;
+ v1[1]= ol->from->y + ol->xof;
+ v2[0]= oops->x+OOPSX/2;
+ v2[1]= oops->y;
+ }
+}
+
+void draw_oopslink(Oops *oops)
+{
+ OopsLink *ol;
+ float vec[4];
+
+ if(oops->type==ID_SCE) {
+ if(oops->flag & SELECT) {
+ if(oops->id->lib) cpack(0x4080A0);
+ else cpack(0x808080);
+ }
+ else cpack(0x606060);
+ }
+ else {
+ if(oops->flag & SELECT) {
+ if(oops->id->lib) cpack(0x11AAFF);
+ else cpack(0xFFFFFF);
+ }
+ else cpack(0x0);
+ }
+
+ ol= oops->link.first;
+ while(ol) {
+ if(ol->to && ol->to->hide==0) {
+
+ give_oopslink_line(oops, ol, vec, vec+2);
+
+ glBegin(GL_LINE_STRIP);
+ glVertex2fv(vec);
+ glVertex2fv(vec+2);
+ glEnd();
+ }
+ ol= ol->next;
+ }
+}
+
+void draw_icon_oops(float *co, short type)
+{
+ BIFIconID icon;
+
+ switch(type) {
+ default: return;
+
+ case ID_OB: icon= ICON_OBJECT_HLT; break;
+ case ID_ME: icon= ICON_MESH_HLT; break;
+ case ID_CU: icon= ICON_CURVE_HLT; break;
+ case ID_MB: icon= ICON_MBALL_HLT; break;
+ case ID_LT: icon= ICON_LATTICE_HLT; break;
+ case ID_LA: icon= ICON_LAMP_HLT; break;
+ case ID_MA: icon= ICON_MATERIAL_HLT; break;
+ case ID_TE: icon= ICON_TEXTURE_HLT; break;
+ case ID_IP: icon= ICON_IPO_HLT; break;
+ case ID_LI: icon= ICON_LIBRARY_HLT; break;
+ case ID_IM: icon= ICON_IMAGE_HLT; break;
+ }
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ glRasterPos2f(co[0], co[1]-0.2);
+ BIF_draw_icon(icon);
+
+ glBlendFunc(GL_ONE, GL_ZERO);
+ glDisable(GL_BLEND);
+}
+
+void mysbox(float x1, float y1, float x2, float y2)
+{
+ float vec[2];
+
+ glBegin(GL_LINE_LOOP);
+ vec[0]= x1; vec[1]= y1;
+ glVertex2fv(vec);
+ vec[0]= x2;
+ glVertex2fv(vec);
+ vec[1]= y2;
+ glVertex2fv(vec);
+ vec[0]= x1;
+ glVertex2fv(vec);
+ glEnd();
+}
+
+unsigned int give_oops_color(short type, short sel, unsigned int *border)
+{
+ unsigned int body;
+ /* geeft ook aan of stippellijn getekend moet */
+
+ switch(type) {
+ case ID_OB:
+ body= 0x707070; break;
+ case ID_SCE:
+ body= 0x608060; break;
+ case ID_MA:
+ body= 0x808060; break;
+ case ID_TE:
+ body= 0x7080a0; break;
+ case ID_IP:
+ body= 0x906050; break;
+ case ID_LA:
+ body= 0x608080; break;
+ case ID_LI:
+ body= 0x2198DC; break;
+ case ID_IM:
+ body= 0x35659F; break;
+ default:
+ body= 0x606070; break;
+ }
+
+ if(sel) {
+ if(G.moving) *border= 0xf0f0f0;
+ else *border= 0xc0c0c0;
+ }
+ else *border= 0x0;
+
+
+ return body;
+}
+
+void calc_oopstext(char *str, float *v1)
+{
+ float f1, f2, size;
+ short mval[2], len, flen;
+
+ ipoco_to_areaco_noclip(G.v2d, v1, mval);
+ f1= mval[0];
+ v1[0]+= OOPSX;
+ ipoco_to_areaco_noclip(G.v2d, v1, mval);
+ f2= mval[0];
+ size= f2-f1;
+
+ len= strlen(str);
+
+ while( (flen= BMF_GetStringWidth(G.fonts, str)) > size) {
+ if(flen < 10 || len<2) break;
+ len--;
+ str[len]= 0;
+ }
+
+ mval[0]= (f1+f2-flen+1)/2;
+ mval[1]= 1;
+ areamouseco_to_ipoco(G.v2d, mval, &f1, &f2);
+
+ v1[0]= f1;
+
+}
+
+void draw_oops(Oops *oops, uiBlock *block)
+{
+ OopsLink *ol;
+ float v1[2], x1, y1, x2, y2, f1, f2;
+ unsigned int body, border;
+ short line= 0;
+ char str[32];
+
+ x1= oops->x;
+ x2= oops->x+OOPSX;
+ y1= oops->y;
+ y2= oops->y+OOPSY;
+
+ if(x2 < G.v2d->cur.xmin || x1 > G.v2d->cur.xmax) return;
+ if(y2 < G.v2d->cur.ymin || y1 > G.v2d->cur.ymax) return;
+
+ body= give_oops_color(oops->type, oops->flag & SELECT, &border);
+ if(oops->id== (ID *)((G.scene->basact) ? (G.scene->basact->object) : 0)) line= 1;
+ else if(oops->id== (ID *)G.scene) line= 1;
+
+ if(oops->id->us) {
+ cpack(body);
+
+ glRectf(x1, y1, x2, y2);
+ }
+ if(oops->id->lib) {
+ if(oops->id->flag & LIB_INDIRECT) cpack(0x1144FF);
+ else cpack(0x11AAFF);
+
+ glRectf(x2-0.2*OOPSX, y2-0.2*OOPSX, x2-0.1*OOPSX, y2-0.1*OOPSX);
+ }
+
+ v1[0]= x1;
+ v1[1]= (y1+y2)/2 -0.3;
+ if(oops->type==ID_LI) {
+ sprintf(str, " %s", ((Library *)oops->id)->name);
+ }
+ else {
+ sprintf(str, " %s", oops->id->name+2);
+ }
+ calc_oopstext(str, v1);
+
+ /* ICON */
+ if(str[1] && oopscalex>1.1) {
+ draw_icon_oops(v1, oops->type);
+ }
+ if(oops->flag & SELECT) cpack(0xFFFFFF);
+ else cpack(0x0);
+ glRasterPos3f(v1[0], v1[1], 0.0);
+ BMF_DrawString(G.fonts, str);
+
+ if(line) setlinestyle(2);
+ cpack(border);
+
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ glRectf(x1, y1, x2, y2);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ if(line) setlinestyle(0);
+
+ /* connectieblokjes */
+ ol= oops->link.first;
+ while(ol) {
+
+ f1= x1+ol->xof;
+ f2= y1+ol->yof;
+
+ body= give_oops_color(ol->type, oops->flag & SELECT, &border);
+ cpack(body);
+
+ glRectf(f1-.2, f2-.2, f1+.2, f2+.2);
+ cpack(border);
+
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+
+ glRectf(f1-.2, f2-.2, f1+.2, f2+.2);
+
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+
+ ol= ol->next;
+ }
+
+ if(oops->flag & OOPS_REFER) {
+ /* Draw the little rounded connection point */
+ glColor3ub(0, 0, 0);
+ glPushMatrix();
+
+ glTranslatef(oops->x + 0.5*OOPSX, oops->y, 0.0);
+ glutil_draw_filled_arc(0.0, M_PI, 0.05*OOPSX, 7);
+
+ glPopMatrix();
+ }
+}
+
+void drawoopsspace()
+{
+ uiBlock *block;
+ Oops *oops;
+ int ofsx, ofsy;
+ char name[32];
+
+ glClearColor(0.55, 0.55, 0.55, 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+ if(G.soops==0) return;
+
+ sprintf(name, "win %d", curarea->win);
+ block= uiNewBlock(&curarea->uiblocks, name, UI_EMBOSSF, UI_HELVB, curarea->win);
+
+ boundbox_oops();
+ calc_scrollrcts(G.v2d, curarea->winx, curarea->winy);
+
+ if(curarea->winx>SCROLLB+10 && curarea->winy>SCROLLH+10) {
+ if(G.v2d->scroll) {
+ ofsx= curarea->winrct.xmin; /* ivm mywin */
+ ofsy= curarea->winrct.ymin;
+
+ glViewport(ofsx+G.v2d->mask.xmin, ofsy+G.v2d->mask.ymin, ( ofsx+G.v2d->mask.xmax-1)-(ofsx+G.v2d->mask.xmin)+1, ( ofsy+G.v2d->mask.ymax-1)-( ofsy+G.v2d->mask.ymin)+1);
+ glScissor(ofsx+G.v2d->mask.xmin, ofsy+G.v2d->mask.ymin, ( ofsx+G.v2d->mask.xmax-1)-(ofsx+G.v2d->mask.xmin)+1, ( ofsy+G.v2d->mask.ymax-1)-( ofsy+G.v2d->mask.ymin)+1);
+ }
+ }
+
+ myortho2(G.v2d->cur.xmin, G.v2d->cur.xmax, G.v2d->cur.ymin, G.v2d->cur.ymax);
+
+ oopscalex= .14*((float)curarea->winx)/(G.v2d->cur.xmax-G.v2d->cur.xmin);
+ calc_ipogrid(); /* voor scrollvariables */
+ build_oops();
+
+ oops= G.soops->oops.first;
+ while(oops) {
+ if(oops->hide==0) {
+ draw_oopslink(oops);
+ }
+ oops= oops->next;
+ }
+ oops= G.soops->oops.first;
+ while(oops) {
+ if(oops->hide==0) {
+ if(oops->flag & SELECT); else draw_oops(oops, block);
+ }
+ oops= oops->next;
+ }
+ oops= G.soops->oops.first;
+ while(oops) {
+ if(oops->hide==0) {
+ if(oops->flag & SELECT) draw_oops(oops, block);
+ }
+ oops= oops->next;
+ }
+
+ /* restore viewport */
+ mywinset(curarea->win);
+
+
+ if(G.v2d->scroll) {
+ /* ortho op pixelnivo curarea */
+ myortho2(-0.5, curarea->winx+0.5, -0.5, curarea->winy+0.5);
+ drawscroll(0);
+ }
+
+ uiDrawBlock(block);
+
+ curarea->win_swap= WIN_BACK_OK;
+}
+
+
+
diff --git a/source/blender/src/drawscene.c b/source/blender/src/drawscene.c
new file mode 100644
index 00000000000..d5b75645dff
--- /dev/null
+++ b/source/blender/src/drawscene.c
@@ -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 *****
+ * drawing graphics and editing
+ */
+
+#include <math.h>
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+
+#include "DNA_scene_types.h"
+#include "DNA_space_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_view3d_types.h"
+
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_scene.h"
+
+#include "BDR_editobject.h"
+
+#include "BIF_space.h"
+#include "BIF_drawscene.h"
+
+#include "BSE_view.h"
+
+#include "blendef.h" /* DIE ! */
+#include "mydevice.h"
+
+
+void set_scene(Scene *sce) /* zie ook scene.c: set_scene_bg() */
+{
+ bScreen *sc;
+
+ G.scene= sce;
+
+ sc= G.main->screen.first;
+ while(sc) {
+ if((U.flag & SCENEGLOBAL) || sc==G.curscreen) {
+
+ if(sce != sc->scene) {
+ /* alle area's endlocalview */
+ ScrArea *sa= sc->areabase.first;
+ while(sa) {
+ endlocalview(sa);
+ sa= sa->next;
+ }
+ sc->scene= sce;
+ }
+
+ }
+ sc= sc->id.next;
+ }
+
+ copy_view3d_lock(0); /* space.c */
+
+ /* zijn er camera's in de views die niet in de scene zitten? */
+ sc= G.main->screen.first;
+ while(sc) {
+ if( (U.flag & SCENEGLOBAL) || sc==G.curscreen) {
+ ScrArea *sa= sc->areabase.first;
+ while(sa) {
+ SpaceLink *sl= sa->spacedata.first;
+ while(sl) {
+ if(sl->spacetype==SPACE_VIEW3D) {
+ View3D *v3d= (View3D*) sl;
+ if (!v3d->camera || !object_in_scene(v3d->camera, sce)) {
+ v3d->camera= scene_find_camera(sc->scene);
+ if (sc==G.curscreen) handle_view3d_lock();
+ if (!v3d->camera && v3d->persp>1) v3d->persp= 1;
+ }
+ }
+ sl= sl->next;
+ }
+ sa= sa->next;
+ }
+ }
+ sc= sc->id.next;
+ }
+
+ set_scene_bg(G.scene);
+
+ /* volledige redraw */
+ allqueue(REDRAWALL, 0);
+ allqueue(REDRAWDATASELECT, 0); /* doet remake */
+}
+
+
diff --git a/source/blender/src/drawseq.c b/source/blender/src/drawseq.c
new file mode 100644
index 00000000000..22b397abde6
--- /dev/null
+++ b/source/blender/src/drawseq.c
@@ -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 *****
+ */
+
+#ifdef _WIN32
+#include "BLI_winstuff.h"
+#endif
+
+#include <string.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BMF_Api.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+
+#include "IMB_imbuf_types.h"
+
+#include "DNA_sequence_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_view2d_types.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_global.h"
+
+#include "BIF_gl.h"
+#include "BIF_mywindow.h"
+#include "BIF_screen.h"
+#include "BIF_drawseq.h"
+#include "BIF_editseq.h"
+#include "BIF_drawimage.h"
+
+#include "BSE_view.h"
+#include "BSE_drawipo.h"
+#include "BSE_sequence.h"
+
+/* Modules used */
+#include "blendertimer.h" /* timer functions */
+
+int no_rightbox=0, no_leftbox= 0;
+
+static void EmbossBoxf(float x1, float y1, float x2, float y2, int sel, unsigned int dark, unsigned int light)
+{
+
+ if(sel) cpack(dark);
+ else cpack(light);
+ if(sel) glLineWidth(2.0);
+ fdrawline(x1, y2, x2, y2); /* boven */
+ if(no_leftbox==0) fdrawline(x1, y1, x1, y2); /* links */
+
+ if(sel) glLineWidth(1.0);
+
+ if(sel) cpack(light);
+ else cpack(dark);
+ fdrawline(x1, y1, x2, y1); /* onder */
+ if(no_rightbox==0) fdrawline(x2, y1, x2, y2); /* rechts */
+
+}
+
+static char *give_seqname(Sequence *seq)
+{
+ if(seq->type==SEQ_META) {
+ if(seq->name[2]) return seq->name+2;
+ return "META";
+ }
+ else if(seq->type==SEQ_SCENE) return "SCENE";
+ else if(seq->type==SEQ_MOVIE) return "MOVIE";
+ else if(seq->type<SEQ_EFFECT) return seq->strip->dir;
+ else if(seq->type==SEQ_CROSS) return "CROSS";
+ else if(seq->type==SEQ_GAMCROSS) return "GAMMA CROSS";
+ else if(seq->type==SEQ_ADD) return "ADD";
+ else if(seq->type==SEQ_SUB) return "SUB";
+ else if(seq->type==SEQ_MUL) return "MUL";
+ else if(seq->type==SEQ_ALPHAOVER) return "ALPHAOVER";
+ else if(seq->type==SEQ_ALPHAUNDER) return "ALPHAUNDER";
+ else if(seq->type==SEQ_OVERDROP) return "OVER DROP";
+ else if(seq->type==SEQ_PLUGIN) {
+ if(seq->plugin && seq->plugin->doit) return seq->plugin->pname;
+ return "PLUGIN";
+ }
+ else return "EFFECT";
+
+}
+
+static void draw_cfra_seq(void)
+{
+ glColor3ub(0x30, 0x90, 0x50);
+ glLineWidth(2.0);
+ glBegin(GL_LINES);
+ glVertex2f(G.scene->r.cfra, G.v2d->cur.ymin);
+ glVertex2f(G.scene->r.cfra, G.v2d->cur.ymax);
+ glEnd();
+ glLineWidth(1.0);
+}
+
+static unsigned int seq_color(Sequence *seq)
+{
+ switch(seq->type) {
+ case SEQ_META:
+ return 0x509090;
+ case SEQ_MOVIE:
+ return 0x805040;
+ case SEQ_SCENE:
+ if(seq->scene==G.scene) return 0x709050;
+ return 0x609060;
+ case SEQ_CROSS:
+ return 0x505090;
+ case SEQ_GAMCROSS:
+ return 0x5040A0;
+ case SEQ_ADD:
+ return 0x6060A0;
+ case SEQ_SUB:
+ return 0x8060A0;
+ case SEQ_MUL:
+ return 0x8080A0;
+ case SEQ_ALPHAOVER:
+ return 0x6080A0;
+ case SEQ_ALPHAUNDER:
+ return 0x9080A0;
+ case SEQ_OVERDROP:
+ return 0x5080B0;
+ case SEQ_PLUGIN:
+ return 0x906000;
+ default:
+ return 0x906060;
+ }
+
+}
+
+static void drawmeta_contents(Sequence *seqm, float x1, float y1, float x2, float y2)
+{
+ Sequence *seq;
+ float dx;
+ int nr;
+
+ nr= 0;
+ WHILE_SEQ(&seqm->seqbase) {
+ nr++;
+ }
+ END_SEQ
+
+ dx= (x2-x1)/nr;
+
+ WHILE_SEQ(&seqm->seqbase) {
+ cpack(seq_color(seq));
+ glRectf(x1, y1, x1+0.9*dx, y2);
+ EmbossBoxf(x1, y1, x1+0.9*dx, y2, 0, 0x404040, 0xB0B0B0);
+ x1+= dx;
+ }
+ END_SEQ
+}
+
+void drawseq(Sequence *seq)
+{
+ float v1[2], v2[2], x1, x2, y1, y2;
+ unsigned int body, dark, light;
+ int len, size;
+ short mval[2];
+ char str[120], *strp;
+
+
+ if(seq->startdisp > seq->enddisp) body= 0x707070;
+
+ body= seq_color(seq);
+ dark= 0x202020;
+ light= 0xB0B0B0;
+
+ if(G.moving && (seq->flag & SELECT)) {
+ if(seq->flag & SEQ_OVERLAP) dark= light= 0x4040FF;
+ else {
+ if(seq->flag & (SEQ_LEFTSEL+SEQ_RIGHTSEL));
+ else dark= light= 0xFFFFFF;
+ }
+ }
+
+ /* body */
+ if(seq->startstill) x1= seq->start;
+ else x1= seq->startdisp;
+ y1= seq->machine+0.2;
+ if(seq->endstill) x2= seq->start+seq->len;
+ else x2= seq->enddisp;
+ y2= seq->machine+0.8;
+
+ cpack(body);
+ glRectf(x1, y1, x2, y2);
+ EmbossBoxf(x1, y1, x2, y2, seq->flag & 1, dark, light);
+
+ v1[1]= y1;
+ v2[1]= y2;
+ if(seq->type < SEQ_EFFECT) {
+
+ /* decoratie: balkjes */
+ x1= seq->startdisp;
+ x2= seq->enddisp;
+
+ if(seq->startofs) {
+ cpack(0x707070);
+ glRectf((float)(seq->start), y1-0.2, x1, y1);
+ EmbossBoxf((float)(seq->start), y1-0.2, x1, y1, seq->flag & 1, dark, light);
+ }
+ if(seq->endofs) {
+ cpack(0x707070);
+ glRectf(x2, y2, (float)(seq->start+seq->len), y2+0.2);
+ EmbossBoxf(x2, y2, (float)(seq->start+seq->len), y2+0.2, seq->flag & 1, dark, light);
+ }
+
+ if(seq->startstill) {
+ cpack(body);
+ glRectf(x1, y1+0.1, (float)(seq->start), y1+0.5);
+ no_rightbox= 1;
+ EmbossBoxf(x1, y1+0.1, (float)(seq->start), y1+0.5, seq->flag & 1, dark, light);
+ no_rightbox= 0;
+ }
+ if(seq->endstill) {
+ cpack(body);
+ glRectf((float)(seq->start+seq->len), y1+0.1, x2, y1+0.5);
+ no_leftbox= 1;
+ EmbossBoxf((float)(seq->start+seq->len), y1+0.1, x2, y1+0.5, seq->flag & 1, dark, light);
+ no_leftbox= 0;
+ }
+
+ }
+
+ /* berekenen of seq lang genoeg is om naam te printen */
+ x1= seq->startdisp+seq->handsize;
+ x2= seq->enddisp-seq->handsize;
+
+ /* maar eerst de inhoud van de meta */
+ if(seq->type==SEQ_META) drawmeta_contents(seq, x1, y1+0.15, x2, y2-0.15);
+
+ if(x1<G.v2d->cur.xmin) x1= G.v2d->cur.xmin;
+ else if(x1>G.v2d->cur.xmax) x1= G.v2d->cur.xmax;
+ if(x2<G.v2d->cur.xmin) x2= G.v2d->cur.xmin;
+ else if(x2>G.v2d->cur.xmax) x2= G.v2d->cur.xmax;
+
+ if(x1 != x2) {
+ v1[0]= x1;
+ ipoco_to_areaco_noclip(G.v2d, v1, mval);
+ x1= mval[0];
+ v2[0]= x2;
+ ipoco_to_areaco_noclip(G.v2d, v2, mval);
+ x2= mval[0];
+ size= x2-x1;
+
+ if(seq->type == SEQ_META) sprintf(str, "%d %s", seq->len, give_seqname(seq));
+ else if(seq->type == SEQ_SCENE) {
+ if(seq->scene) sprintf(str, "%d %s %s", seq->len, give_seqname(seq), seq->scene->id.name+2);
+ else sprintf(str, "%d %s", seq->len, give_seqname(seq));
+ }
+ else if(seq->type & SEQ_EFFECT) {
+ if(seq->seq3!=seq->seq2 && seq->seq1!=seq->seq3)
+ sprintf(str, "%d %s: %d-%d (use %d)", seq->len, give_seqname(seq), seq->seq1->machine, seq->seq2->machine, seq->seq3->machine);
+ else
+ sprintf(str, "%d %s: %d-%d", seq->len, give_seqname(seq), seq->seq1->machine, seq->seq2->machine);
+ }
+ else if(seq->name[2]) sprintf(str, "%s", seq->name+2);
+ else sprintf(str, "%d %s%s", seq->len, seq->strip->dir, seq->strip->stripdata->name);
+
+ strp= str;
+
+ while( (len= BMF_GetStringWidth(G.font, strp)) > size) {
+ if(len < 10) break;
+ if(strp[1]==0) break;
+ strp++;
+ }
+
+ mval[0]= (x1+x2-len+1)/2;
+ mval[1]= 1;
+ areamouseco_to_ipoco(G.v2d, mval, &x1, &x2);
+
+ if(seq->flag & SELECT) cpack(0xFFFFFF);
+ else cpack(0x0);
+ glRasterPos3f(x1, y1+0.2, 0.0);
+ BMF_DrawString(G.font, strp);
+ }
+
+ if(seq->type < SEQ_EFFECT) {
+
+ /* decoratie: driehoekjes */
+ x1= seq->startdisp;
+ x2= seq->enddisp;
+
+ body+= 0x101010;
+ dark= 0x202020;
+ light= 0xB0B0B0;
+
+ /* linker driehoek */
+
+ if(seq->flag & SEQ_LEFTSEL) {
+ cpack(body+0x20);
+ if(G.moving) {
+ if(seq->flag & SEQ_OVERLAP) dark= light= 0x4040FF;
+ else dark= light= 0xFFFFFF;
+ }
+ }
+ else {
+ cpack(body);
+ }
+
+ glBegin(GL_TRIANGLES);
+ v1[0]= x1; glVertex2fv(v1);
+ v2[0]= x1; glVertex2fv(v2);
+ v2[0]+= seq->handsize; v2[1]= (y1+y2)/2.0; glVertex2fv(v2); v2[1]= y2;
+ glEnd();
+
+ cpack(light);
+
+ glBegin(GL_LINE_STRIP);
+ v1[0]= x1; glVertex2fv(v1);
+ v2[0]= x1; glVertex2fv(v2);
+ v2[0]+= seq->handsize; v2[1]= (y1+y2)/2.0; glVertex2fv(v2); v2[1]= y2;
+ cpack(dark);
+ glVertex2fv(v1);
+ glEnd();
+
+ if(G.moving || (seq->flag & SEQ_LEFTSEL)) {
+ cpack(0xFFFFFF);
+ glRasterPos3f(x1, y1+0.2, 0.0);
+ sprintf(str, "%d", seq->startdisp);
+ BMF_DrawString(G.font, str);
+ }
+
+ /* rechter driehoek */
+
+ dark= 0x202020;
+ light= 0xB0B0B0;
+
+ if(seq->flag & SEQ_RIGHTSEL) {
+ cpack(body+0x20);
+ if(G.moving) {
+ if(seq->flag & SEQ_OVERLAP) dark= light= 0x4040FF;
+ else dark= light= 0xFFFFFF;
+ }
+ }
+ else {
+ cpack(body);
+ }
+ glBegin(GL_TRIANGLES);
+ v2[0]= x2; glVertex2fv(v2);
+ v1[0]= x2; glVertex2fv(v1);
+ v2[0]-= seq->handsize; v2[1]= (y1+y2)/2.0; glVertex2fv(v2); v2[1]= y2;
+ glEnd();
+
+ cpack(dark);
+ glBegin(GL_LINE_STRIP);
+ v2[0]= x2; glVertex2fv(v2);
+ v1[0]= x2; glVertex2fv(v1);
+ v1[0]-= seq->handsize; v1[1]= (y1+y2)/2.0; glVertex2fv(v1); v1[1]= y2;
+ cpack(light);
+ glVertex2fv(v2);
+ glEnd();
+
+ if(G.moving || (seq->flag & SEQ_RIGHTSEL)) {
+ cpack(0xFFFFFF);
+ glRasterPos3f(x2-seq->handsize/2, y1+0.2, 0.0);
+ sprintf(str, "%d", seq->enddisp-1);
+ BMF_DrawString(G.font, str);
+ }
+
+
+ }
+}
+
+static Sequence *special_seq_update= 0;
+
+void set_special_seq_update(int val)
+{
+ int x;
+
+ /* als met muis in sequence && LEFTMOUSE */
+ if(val) {
+ special_seq_update= find_nearest_seq(&x);
+ }
+ else special_seq_update= 0;
+}
+
+
+static void draw_image_seq(void)
+{
+ SpaceSeq *sseq;
+ StripElem *se;
+ struct ImBuf *ibuf;
+ int x1, y1;
+
+ glClearColor(0.0, 0.0, 0.0, 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ curarea->win_swap= WIN_BACK_OK;
+
+ ibuf= (ImBuf *)give_ibuf_seq( (G.scene->r.cfra));
+
+ if(special_seq_update) {
+ se = special_seq_update->curelem;
+ if(se) {
+ if(se->ok==2) {
+ if(se->se1)
+ ibuf= se->se1->ibuf;
+ }
+ else ibuf= se->ibuf;
+ }
+ }
+ if(ibuf==0 || ibuf->rect==0) return;
+
+ sseq= curarea->spacedata.first;
+ if(sseq==0) return;
+
+ /* plek berekenen */
+ x1= curarea->winrct.xmin+(curarea->winx-sseq->zoom*ibuf->x)/2;
+ y1= curarea->winrct.ymin+(curarea->winy-sseq->zoom*ibuf->y)/2;
+
+ /* convert_rgba_to_abgr(ibuf->x*ibuf->y, ibuf->rect); */
+
+ rectwrite_part(curarea->winrct.xmin, curarea->winrct.ymin,
+ curarea->winrct.xmax, curarea->winrct.ymax,
+ x1, y1, ibuf->x, ibuf->y, (float)sseq->zoom,(float)sseq->zoom, ibuf->rect);
+
+ /* convert_rgba_to_abgr(ibuf->x*ibuf->y, ibuf->rect); */
+}
+
+static void draw_extra_seqinfo(void)
+{
+ extern Sequence *last_seq;
+ StripElem *se, *last;
+ float xco, xfac;
+ int sta, end;
+ char str[256];
+
+ if(last_seq==0) return;
+
+ /* xfac: afm 1 pixel */
+ xfac= G.v2d->cur.xmax - G.v2d->cur.xmin;
+ xfac/= (float)(G.v2d->mask.xmax-G.v2d->mask.xmin);
+ xco= G.v2d->cur.xmin+40*xfac;
+
+ cpack(0);
+
+ /* NAAM */
+ glRasterPos3f(xco, 0.3, 0.0);
+ strcpy(str, give_seqname(last_seq));
+ BMF_DrawString(G.font, str);
+ xco += xfac*BMF_GetStringWidth(G.font, str) +30.0*xfac;
+
+ if(last_seq->type==SEQ_SCENE && last_seq->scene) {
+ glRasterPos3f(xco, 0.3, 0.0);
+ BMF_DrawString(G.font, last_seq->scene->id.name+2);
+ xco += xfac*BMF_GetStringWidth(G.font, last_seq->scene->id.name+2) +30.0*xfac;
+ }
+
+ /* LEN */
+ if(last_seq->type & SEQ_EFFECT)
+ sprintf(str, "len: %d From %d - %d", last_seq->len, last_seq->startdisp, last_seq->enddisp-1);
+ else
+ sprintf(str, "len: %d (%d)", last_seq->enddisp-last_seq->startdisp, last_seq->len);
+
+ glRasterPos3f(xco, 0.3, 0.0);
+ BMF_DrawString(G.font, str);
+ xco += xfac*BMF_GetStringWidth(G.font, str) +30.0*xfac;
+
+ if(last_seq->type==SEQ_IMAGE) {
+
+ /* CURRENT */
+ se= (StripElem *)give_stripelem(last_seq, (G.scene->r.cfra));
+ if(se) {
+ sprintf(str, "cur: %s", se->name);
+ glRasterPos3f(xco, 0.3, 0.0);
+ BMF_DrawString(G.font, str);
+ xco += xfac*BMF_GetStringWidth(G.font, str) +30.0*xfac;
+ }
+
+ /* FIRST EN LAST */
+
+ if(last_seq->strip) {
+ se= last_seq->strip->stripdata;
+ last= se+last_seq->len-1;
+ if(last_seq->startofs) se+= last_seq->startofs;
+ if(last_seq->endofs) last-= last_seq->endofs;
+
+ sprintf(str, "First: %s at %d Last: %s at %d", se->name, last_seq->startdisp, last->name, last_seq->enddisp-1);
+ glRasterPos3f(xco, 0.3, 0.0);
+ BMF_DrawString(G.font, str);
+ xco += xfac*BMF_GetStringWidth(G.font, str) +30.0*xfac;
+
+ /* orig size */
+ sprintf(str, "OrigSize: %d x %d", last_seq->strip->orx, last_seq->strip->ory);
+ glRasterPos3f(xco, 0.3, 0.0);
+ BMF_DrawString(G.font, str);
+ xco += xfac*BMF_GetStringWidth(G.font, str) +30.0*xfac;
+ }
+ }
+ else if(last_seq->type==SEQ_MOVIE) {
+
+ sta= last_seq->startofs;
+ end= last_seq->len-1-last_seq->endofs;
+
+ sprintf(str, "%s %s%s First: %d at %d Last: %d at %d Cur: %d",
+ last_seq->name+2, last_seq->strip->dir, last_seq->strip->stripdata->name,
+ sta, last_seq->startdisp, end, last_seq->enddisp-1, (G.scene->r.cfra)-last_seq->startdisp);
+
+ glRasterPos3f(xco, 0.3, 0.0);
+ BMF_DrawString(G.font, str);
+ }
+}
+
+void drawseqspace(void)
+{
+ SpaceSeq *sseq;
+ Editing *ed;
+ Sequence *seq;
+ int ofsx, ofsy;
+
+ ed= G.scene->ed;
+
+ sseq= curarea->spacedata.first;
+ if(sseq->mainb==1) {
+ draw_image_seq();
+ return;
+ }
+
+ if(ed && ed->metastack.first) glClearColor(0.5, 0.5, 0.4, 0.0);
+ else glClearColor(.40625, .40625, .40625, 0.0);
+
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ calc_scrollrcts(G.v2d, curarea->winx, curarea->winy);
+
+ if(curarea->winx>SCROLLB+10 && curarea->winy>SCROLLH+10) {
+ if(G.v2d->scroll) {
+ ofsx= curarea->winrct.xmin; /* ivm mywin */
+ ofsy= curarea->winrct.ymin;
+ glViewport(ofsx+G.v2d->mask.xmin, ofsy+G.v2d->mask.ymin, ( ofsx+G.v2d->mask.xmax-1)-(ofsx+G.v2d->mask.xmin)+1, ( ofsy+G.v2d->mask.ymax-1)-( ofsy+G.v2d->mask.ymin)+1);
+ glScissor(ofsx+G.v2d->mask.xmin, ofsy+G.v2d->mask.ymin, ( ofsx+G.v2d->mask.xmax-1)-(ofsx+G.v2d->mask.xmin)+1, ( ofsy+G.v2d->mask.ymax-1)-( ofsy+G.v2d->mask.ymin)+1);
+ }
+ }
+
+
+ myortho2(G.v2d->cur.xmin, G.v2d->cur.xmax, G.v2d->cur.ymin, G.v2d->cur.ymax);
+
+ cpack(0x585858);
+ glRectf(G.v2d->cur.xmin, 0.0, G.v2d->cur.xmax, 1.0);
+
+ boundbox_seq();
+ calc_ipogrid();
+ draw_ipogrid();
+ draw_cfra_seq();
+
+ /* sequenties: eerst de deselect */
+
+ if(ed) {
+ seq= ed->seqbasep->first;
+ while(seq) {
+ if(seq->flag & SELECT); else drawseq(seq);
+ seq= seq->next;
+ }
+ }
+ ed= G.scene->ed;
+ if(ed) {
+ seq= ed->seqbasep->first;
+ while(seq) {
+ if(seq->flag & SELECT) drawseq(seq);
+ seq= seq->next;
+ }
+ }
+
+ draw_extra_seqinfo();
+
+ /* restore viewport */
+ mywinset(curarea->win);
+
+ if(curarea->winx>SCROLLB+10 && curarea->winy>SCROLLH+10) {
+
+ /* ortho op pixelnivo curarea */
+ myortho2(-0.5, curarea->winx+0.5, -0.5, curarea->winy+0.5);
+
+ if(G.v2d->scroll) {
+ drawscroll(0);
+ }
+
+
+ }
+
+ curarea->win_swap= WIN_BACK_OK;
+}
+
+
diff --git a/source/blender/src/drawsound.c b/source/blender/src/drawsound.c
new file mode 100644
index 00000000000..c17ba472e5d
--- /dev/null
+++ b/source/blender/src/drawsound.c
@@ -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 *****
+ */
+
+#include <math.h>
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+
+#include "DNA_scene_types.h"
+#include "DNA_sound_types.h"
+#include "DNA_space_types.h"
+#include "DNA_screen_types.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_global.h"
+
+#include "BIF_gl.h"
+#include "BIF_mywindow.h"
+#include "BIF_screen.h"
+#include "BIF_editsound.h"
+
+#include "BSE_drawipo.h"
+
+/* local */
+void drawsoundspace(void);
+
+/*implementation */
+static void draw_wave(int startsamp, int endsamp, short sampdx, short offset, short *sp, float sampfac, float y)
+{
+ float min, max, v1[2], v2[3];
+ int i, j;
+ short value, deltasp;
+
+ sp+= offset*startsamp;
+
+ deltasp= offset*sampdx;
+
+ glBegin(GL_LINES);
+ for(i=startsamp; i<endsamp; i+=sampdx, sp+=deltasp) {
+
+ /* filter */
+ min= max= 0.0;
+ for(j=0; j<sampdx; j++) {
+ value= sp[offset*j];
+ if(value < min) min= value;
+ else if(value > max) max= value;
+ }
+ v1[1]= y + 0.002*min;
+ v2[1]= y + 0.002*max;
+
+ v1[0]=v2[0]= sampfac*i;
+
+ glVertex2fv(v1);
+ glVertex2fv(v2);
+ }
+ glEnd();
+}
+
+static void draw_sample(bSample *sample)
+{
+ float sampxlen, sampfac;
+ int samples, startsamp, endsamp;
+ short *sp, sampdx;
+
+ /* one sample is where in v2d space? (v2d space in frames!) */
+ sampfac= 25.0/(sample->rate);
+
+ /* how many samples? */
+ samples= sample->len/(sample->channels*(sample->bits/8));
+ /* total len in v2d space */
+ sampxlen= sampfac*samples;
+
+ /* one pixel is how many samples? */
+ sampdx= (samples*((G.v2d->cur.xmax-G.v2d->cur.xmin)/sampxlen))/curarea->winx;
+
+ if(sampdx==0) sampdx= 1;
+
+ /* start and and */
+ startsamp = G.v2d->cur.xmin/sampfac;
+ CLAMP(startsamp, 0, samples-1);
+ endsamp= G.v2d->cur.xmax/sampfac;
+ CLAMP(endsamp, 0, samples-1);
+ endsamp-= sampdx;
+
+ /* set 'tot' for sliders */
+ G.v2d->tot.xmax= sampfac*samples;
+
+ /* channels? */
+ if(sample->channels==2) {
+
+ cpack(0x905050);
+ sp= (short *)(sample->data);
+ draw_wave(startsamp, endsamp, sampdx, 2, sp, sampfac, 85.0);
+
+ cpack(0x506890);
+ sp++;
+ draw_wave(startsamp, endsamp, sampdx, 2, sp, sampfac, 190.0);
+ }
+ else {
+ cpack(0x905050);
+ sp= (short *)(sample->data);
+
+ draw_wave(startsamp, endsamp, sampdx, 1, sp, sampfac, 128.0);
+ }
+}
+
+static void draw_cfra_sound(void)
+{
+ float vec[2];
+
+ vec[0]= (G.scene->r.cfra);
+ vec[0]*= G.scene->r.framelen;
+
+ vec[1]= G.v2d->cur.ymin;
+ glColor3ub(0x20, 0x80, 0x20);
+ glLineWidth(3.0);
+
+ glBegin(GL_LINE_STRIP);
+ glVertex2fv(vec);
+ vec[1]= G.v2d->cur.ymax;
+ glVertex2fv(vec);
+ glEnd();
+
+ glLineWidth(1.0);
+}
+
+
+void drawsoundspace(void)
+{
+ short ofsx, ofsy;
+
+ glClearColor(.6275, .6275, .6275, 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ calc_scrollrcts(G.v2d, curarea->winx, curarea->winy);
+
+ if(curarea->winx>SCROLLB+10 && curarea->winy>SCROLLH+10) {
+ if(G.v2d->scroll) {
+ ofsx= curarea->winrct.xmin; /* ivm mywin */
+ ofsy= curarea->winrct.ymin;
+ glViewport(ofsx+G.v2d->mask.xmin, ofsy+G.v2d->mask.ymin, ( ofsx+G.v2d->mask.xmax-1)-(ofsx+G.v2d->mask.xmin)+1, ( ofsy+G.v2d->mask.ymax-1)-( ofsy+G.v2d->mask.ymin)+1);
+ glScissor(ofsx+G.v2d->mask.xmin, ofsy+G.v2d->mask.ymin, ( ofsx+G.v2d->mask.xmax-1)-(ofsx+G.v2d->mask.xmin)+1, ( ofsy+G.v2d->mask.ymax-1)-( ofsy+G.v2d->mask.ymin)+1);
+ }
+ }
+
+ myortho2(G.v2d->cur.xmin, G.v2d->cur.xmax, G.v2d->cur.ymin, G.v2d->cur.ymax);
+
+ /* boundbox_seq(); */
+ calc_ipogrid();
+ draw_ipogrid();
+
+ if (G.ssound->sound) {
+ sound_initialize_sample(G.ssound->sound);
+ draw_sample(G.ssound->sound->sample);
+ }
+
+ draw_cfra_sound();
+
+ /* restore viewport */
+ mywinset(curarea->win);
+
+ if(curarea->winx>SCROLLB+10 && curarea->winy>SCROLLH+10) {
+
+ /* ortho op pixelnivo curarea */
+ myortho2(-0.5, curarea->winx+0.5, -0.5, curarea->winy+0.5);
+
+ if(G.v2d->scroll) {
+ drawscroll(0);
+ }
+ }
+
+ curarea->win_swap= WIN_BACK_OK;
+}
diff --git a/source/blender/src/drawtext.c b/source/blender/src/drawtext.c
new file mode 100644
index 00000000000..0b511149996
--- /dev/null
+++ b/source/blender/src/drawtext.c
@@ -0,0 +1,1101 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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>
+#ifndef _WIN32
+#include <unistd.h>
+#else
+#include <io.h>
+#include "BLI_winstuff.h"
+#endif
+#include "MEM_guardedalloc.h"
+#include "PIL_time.h"
+
+#include "BMF_Api.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+
+#include "DNA_text_types.h"
+#include "DNA_space_types.h"
+#include "DNA_screen_types.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_text.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+
+#include "BPY_extern.h"
+
+#include "BIF_gl.h"
+#include "BIF_keyval.h"
+#include "BIF_interface.h"
+#include "BIF_drawtext.h"
+#include "BIF_spacetypes.h"
+#include "BIF_usiblender.h"
+#include "BIF_screen.h"
+#include "BIF_toolbox.h"
+#include "BIF_space.h"
+#include "BIF_mywindow.h"
+
+#include "BSE_filesel.h"
+
+#include "mydevice.h"
+#include "blendef.h"
+#include "interface.h"
+
+/* locals */
+void drawtextspace(void);
+void winqreadtextspace(unsigned short event, short val, char ascii);
+
+static void *last_txt_find_string= NULL;
+
+static BMF_Font *spacetext_get_font(SpaceText *st) {
+ static BMF_Font *scr12= NULL;
+ static BMF_Font *scr15= NULL;
+
+ switch (st->font_id) {
+ default:
+ case 0:
+ if (!scr12)
+ scr12= BMF_GetFont(BMF_kScreen12);
+ return scr12;
+ case 1:
+ if (!scr15)
+ scr15= BMF_GetFont(BMF_kScreen15);
+ return scr15;
+ }
+}
+
+static int spacetext_get_fontwidth(SpaceText *st) {
+ return BMF_GetCharacterWidth(spacetext_get_font(st), ' ');
+}
+
+static char *temp_char_buf= NULL;
+static int *temp_char_accum= NULL;
+static int temp_char_len= 0;
+static int temp_char_pos= 0;
+
+static void temp_char_write(char c, int accum) {
+ if (temp_char_len==0 || temp_char_pos>=temp_char_len) {
+ char *nbuf; int *naccum;
+ int olen= temp_char_len;
+
+ if (olen) temp_char_len*= 2;
+ else temp_char_len= 256;
+
+ nbuf= MEM_mallocN(sizeof(*temp_char_buf)*temp_char_len, "temp_char_buf");
+ naccum= MEM_mallocN(sizeof(*temp_char_accum)*temp_char_len, "temp_char_accum");
+
+ if (olen) {
+ memcpy(nbuf, temp_char_buf, olen);
+ memcpy(naccum, temp_char_accum, olen);
+
+ MEM_freeN(temp_char_buf);
+ MEM_freeN(temp_char_accum);
+ }
+
+ temp_char_buf= nbuf;
+ temp_char_accum= naccum;
+ }
+
+ temp_char_buf[temp_char_pos]= c;
+ temp_char_accum[temp_char_pos]= accum;
+
+ if (c==0) temp_char_pos= 0;
+ else temp_char_pos++;
+}
+
+void free_txt_data(void) {
+ txt_free_cut_buffer();
+
+ if (last_txt_find_string) MEM_freeN(last_txt_find_string);
+ if (temp_char_buf) MEM_freeN(temp_char_buf);
+ if (temp_char_accum) MEM_freeN(temp_char_accum);
+}
+
+static int render_string (char *in) {
+ int r= 0, i;
+
+ while(*in) {
+ if (*in=='\t') {
+ if (temp_char_pos && *(in-1)=='\t') i= TXT_TABSIZE;
+ else i= TXT_TABSIZE - (temp_char_pos%TXT_TABSIZE);
+
+ while(i--) temp_char_write(' ', r);
+ } else temp_char_write(*in, r);
+
+ r++;
+ in++;
+ }
+ r= temp_char_pos;
+ temp_char_write(0, 0);
+
+ return r;
+}
+
+static int text_draw(SpaceText *st, char *str, int cshift, int maxwidth, int draw, int x, int y) {
+ int r=0, w= 0;
+ char *in;
+ int *acc;
+
+ w= render_string(str);
+ if(w<cshift ) return 0; /* String is shorter than shift */
+
+ in= temp_char_buf+cshift;
+ acc= temp_char_accum+cshift;
+ w= w-cshift;
+
+ if (draw) {
+ glRasterPos2i(x, y);
+ BMF_DrawString(spacetext_get_font(st), in);
+ } else {
+ while (w-- && *acc++ < maxwidth) {
+ r+= spacetext_get_fontwidth(st);
+ }
+ }
+
+ if (cshift && r==0) return 0;
+ else return r+TXT_OFFSET;
+}
+
+static void set_cursor_to_pos (SpaceText *st, int x, int y, int sel)
+{
+ Text *text;
+ TextLine **linep;
+ int *charp;
+ int w;
+
+ text= st->text;
+
+ if(sel) { linep= &text->sell; charp= &text->selc; }
+ else { linep= &text->curl; charp= &text->curc; }
+
+ y= (curarea->winy - y)/st->lheight;
+
+ y-= txt_get_span(text->lines.first, *linep) - st->top;
+
+ if (y>0) {
+ while (y-- != 0) if((*linep)->next) *linep= (*linep)->next;
+ } else if (y<0) {
+ while (y++ != 0) if((*linep)->prev) *linep= (*linep)->prev;
+ }
+
+ x-= TXT_OFFSET;
+ if (x<0) x= 0;
+ x = (x/spacetext_get_fontwidth(st)) + st->left;
+
+ w= render_string((*linep)->line);
+ if(x<w) *charp= temp_char_accum[x];
+ else *charp= (*linep)->len;
+
+ if(!sel) txt_pop_sel(text);
+}
+
+static void draw_cursor(SpaceText *st) {
+ int h, x, i;
+ Text *text= st->text;
+ TextLine *linef, *linel;
+ int charf, charl;
+
+ if (text->curl==text->sell && text->curc==text->selc) {
+ x= text_draw(st, text->curl->line, st->left, text->curc, 0, 0, 0);
+
+ if (x) {
+ h= txt_get_span(text->lines.first, text->curl) - st->top;
+
+ glColor3f(1.0, 0.0, 0.0);
+
+ glRecti(x-1, curarea->winy-st->lheight*(h)-2, x+1, curarea->winy-st->lheight*(h+1)-2);
+ }
+ } else {
+ int span= txt_get_span(text->curl, text->sell);
+
+ if (span<0) {
+ linef= text->sell;
+ charf= text->selc;
+
+ linel= text->curl;
+ charl= text->curc;
+ } else if (span>0) {
+ linef= text->curl;
+ charf= text->curc;
+
+ linel= text->sell;
+ charl= text->selc;
+ } else {
+ linef= linel= text->curl;
+
+ if (text->curc<text->selc) {
+ charf= text->curc;
+ charl= text->selc;
+ } else {
+ charf= text->selc;
+ charl= text->curc;
+ }
+ }
+
+ /* Walk to the beginning of visible text */
+ h= txt_get_span(text->lines.first, linef) - st->top;
+ while (h++<-1 && linef!=linel) linef= linef->next;
+
+ x= text_draw(st, linef->line, st->left, charf, 0, 0, 0);
+
+ glColor3f(0.75, 0.44, 0.44);
+
+ if (!x) x= TXT_OFFSET-10;
+ while (linef && linef != linel) {
+ h= txt_get_span(text->lines.first, linef) - st->top;
+ if (h>st->viewlines) break;
+
+ glRecti(x, curarea->winy-st->lheight*(h)-2, curarea->winx, curarea->winy-st->lheight*(h+1)-2);
+ glRecti(TXT_OFFSET-10, curarea->winy-st->lheight*(h+1)-2, TXT_OFFSET, curarea->winy-st->lheight*(h+2)-2);
+ x= TXT_OFFSET;
+
+ linef= linef->next;
+ }
+
+ h= txt_get_span(text->lines.first, linef) - st->top;
+
+ i= text_draw(st, linel->line, st->left, charl, 0, 0, 0);
+ if(i) glRecti(x, curarea->winy-st->lheight*(h)-2, i, curarea->winy-st->lheight*(h+1)-2);
+ }
+
+ glColor3f(0.0, 0.0, 0.0);
+}
+
+static void calc_text_rcts(SpaceText *st)
+{
+ short barheight, barstart;
+ int lbarstart, lbarh, ltexth;
+
+ lbarstart= st->top;
+ lbarh= st->viewlines;
+ ltexth= txt_get_span(st->text->lines.first, st->text->lines.last)+1;
+
+ barheight= (lbarh*(curarea->winy-4))/ltexth;
+ if (barheight<20) barheight=20;
+
+ barstart= (lbarstart*(curarea->winy-4))/ltexth + 8;
+
+ st->txtbar.xmin= 5;
+ st->txtbar.xmax= 17;
+ st->txtbar.ymax= curarea->winy - barstart;
+ st->txtbar.ymin= st->txtbar.ymax - barheight;
+
+ CLAMP(st->txtbar.ymin, 2, curarea->winy-2);
+ CLAMP(st->txtbar.ymax, 2, curarea->winy-2);
+
+ st->pix_per_line= (float) ltexth/curarea->winy;
+ if (st->pix_per_line<.1) st->pix_per_line=.1;
+
+ lbarstart= MIN2(txt_get_span(st->text->lines.first, st->text->curl),
+ txt_get_span(st->text->lines.first, st->text->sell));
+ lbarh= abs(txt_get_span(st->text->lines.first, st->text->curl)-txt_get_span(st->text->lines.first, st->text->sell));
+
+ barheight= (lbarh*(curarea->winy-4))/ltexth;
+ if (barheight<2) barheight=2;
+
+ barstart= (lbarstart*(curarea->winy-4))/ltexth + 8;
+
+ st->txtscroll.xmin= 5;
+ st->txtscroll.xmax= 17;
+ st->txtscroll.ymax= curarea->winy-barstart;
+ st->txtscroll.ymin= st->txtscroll.ymax - barheight;
+
+ CLAMP(st->txtscroll.ymin, 2, curarea->winy-2);
+ CLAMP(st->txtscroll.ymax, 2, curarea->winy-2);
+}
+
+static void draw_textscroll(SpaceText *st)
+{
+ if (!st->text) return;
+
+ calc_text_rcts(st);
+
+ cpack(0x707070);
+ glRecti(2, 2, 20, curarea->winy-6);
+ uiEmboss(2, 2, 20, curarea->winy-6, 1);
+
+ cpack(0x909090);
+ glRecti(st->txtbar.xmin, st->txtbar.ymin, st->txtbar.xmax, st->txtbar.ymax);
+
+ cpack(0x7777c6);
+ glRecti(st->txtscroll.xmin, st->txtscroll.ymin, st->txtscroll.xmax, st->txtscroll.ymax);
+
+ uiEmboss(st->txtbar.xmin, st->txtbar.ymin, st->txtbar.xmax, st->txtbar.ymax, st->flags & ST_SCROLL_SELECT);
+}
+
+static void screen_skip(SpaceText *st, int lines)
+{
+ int last;
+
+ if (!st) return;
+ if (st->spacetype != SPACE_TEXT) return;
+ if (!st->text) return;
+
+ st->top += lines;
+
+ last= txt_get_span(st->text->lines.first, st->text->lines.last);
+ last= last - (st->viewlines/2);
+
+ if (st->top>last) st->top= last;
+ if (st->top<0) st->top= 0;
+}
+
+/*
+ * mode 1 == view scroll
+ * mode 2 == scrollbar
+ */
+static void do_textscroll(SpaceText *st, int mode)
+{
+ short delta[2]= {0, 0};
+ short mval[2], hold[2], old[2];
+
+ if (!st->text) return;
+
+ calc_text_rcts(st);
+
+ st->flags|= ST_SCROLL_SELECT;
+
+ glDrawBuffer(GL_FRONT);
+ uiEmboss(st->txtbar.xmin, st->txtbar.ymin, st->txtbar.xmax, st->txtbar.ymax, st->flags & ST_SCROLL_SELECT);
+ glDrawBuffer(GL_BACK);
+
+ getmouseco_areawin(mval);
+ old[0]= hold[0]= mval[0];
+ old[1]= hold[1]= mval[1];
+
+ while(get_mbut()&(L_MOUSE|M_MOUSE)) {
+ getmouseco_areawin(mval);
+
+ if(old[0]!=mval[0] || old[1]!=mval[1]) {
+ if (mode==1) {
+ delta[0]= (hold[0]-mval[0])/spacetext_get_fontwidth(st);
+ delta[1]= (mval[1]-hold[1])/st->lheight;
+ }
+ else delta[1]= (hold[1]-mval[1])*st->pix_per_line;
+
+ if (delta[0] || delta[1]) {
+ screen_skip(st, delta[1]);
+ st->left+= delta[0];
+ if (st->left<0) st->left= 0;
+
+ scrarea_do_windraw(curarea);
+ screen_swapbuffers();
+
+ hold[0]=mval[0];
+ hold[1]=mval[1];
+ }
+ old[0]=mval[0];
+ old[1]=mval[1];
+ } else {
+ BIF_wait_for_statechange();
+ }
+ }
+ st->flags^= ST_SCROLL_SELECT;
+
+ glDrawBuffer(GL_FRONT);
+ uiEmboss(st->txtbar.xmin, st->txtbar.ymin, st->txtbar.xmax, st->txtbar.ymax, st->flags & ST_SCROLL_SELECT);
+ glDrawBuffer(GL_BACK);
+}
+
+static void do_selection(SpaceText *st, int selecting)
+{
+ short mval[2], old[2];
+ int sell, selc;
+ int linep2, charp2;
+ int first= 1;
+
+ getmouseco_areawin(mval);
+ old[0]= mval[0];
+ old[1]= mval[1];
+
+ if (!selecting) {
+ int curl= txt_get_span(st->text->lines.first, st->text->curl);
+ int curc= st->text->curc;
+ int linep2, charp2;
+
+ set_cursor_to_pos(st, mval[0], mval[1], 0);
+
+ linep2= txt_get_span(st->text->lines.first, st->text->curl);
+ charp2= st->text->selc;
+
+ if (curl!=linep2 || curc!=charp2)
+ txt_undo_add_toop(st->text, UNDO_CTO, curl, curc, linep2, charp2);
+ }
+
+ sell= txt_get_span(st->text->lines.first, st->text->sell);
+ selc= st->text->selc;
+
+ while(get_mbut()&L_MOUSE) {
+ getmouseco_areawin(mval);
+
+ if (mval[1]<0 || mval[1]>curarea->winy) {
+ int d= (old[1]-mval[1])*st->pix_per_line;
+ if (d) screen_skip(st, d);
+
+ set_cursor_to_pos(st, mval[0], mval[1]<0?0:curarea->winy, 1);
+
+ scrarea_do_windraw(curarea);
+ screen_swapbuffers();
+ } else if (mval[0]<0 || mval[0]>curarea->winx) {
+ if (mval[0]>curarea->winx) st->left++;
+ else if (mval[0]<0 && st->left>0) st->left--;
+
+ set_cursor_to_pos(st, mval[0], mval[1], 1);
+
+ scrarea_do_windraw(curarea);
+ screen_swapbuffers();
+
+ PIL_sleep_ms(10);
+ } else if (first || old[0]!=mval[0] || old[1]!=mval[1]) {
+ set_cursor_to_pos(st, mval[0], mval[1], 1);
+
+ scrarea_do_windraw(curarea);
+ screen_swapbuffers();
+
+ old[0]= mval[0];
+ old[1]= mval[1];
+ first= 1;
+ } else {
+ BIF_wait_for_statechange();
+ }
+ }
+
+ linep2= txt_get_span(st->text->lines.first, st->text->sell);
+ charp2= st->text->selc;
+
+ if (sell!=linep2 || selc!=charp2)
+ txt_undo_add_toop(st->text, UNDO_STO, sell, selc, linep2, charp2);
+}
+
+void drawtextspace(void)
+{
+ SpaceText *st= curarea->spacedata.first;
+ Text *text;
+ int i;
+ TextLine *tmp;
+
+ if (BPY_spacetext_is_pywin(st)) {
+ BPY_spacetext_do_pywin_draw(st);
+ return;
+ }
+
+ glClearColor(0.6, 0.6, 0.6, 1.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+ myortho2(-0.5, curarea->winrct.xmax-curarea->winrct.xmin-0.5, -0.5, curarea->winrct.ymax-curarea->winrct.ymin-0.5);
+
+ text= st->text;
+ if(!text) return;
+
+ /* Make sure all the positional pointers exist */
+ if (!text->curl || !text->sell || !text->lines.first || !text->lines.last)
+ txt_clean_text(text);
+
+ if(st->lheight) st->viewlines= (int) curarea->winy/st->lheight;
+ else st->viewlines= 0;
+
+ glColor3f(0.0, 0.0, 0.0);
+
+ draw_cursor(st);
+
+ tmp= text->lines.first;
+ for (i= 0; i<st->top && tmp; i++)
+ tmp= tmp->next;
+ for (i=0; i<st->viewlines && tmp; i++, tmp= tmp->next)
+ text_draw(st, tmp->line, st->left, 0, 1, TXT_OFFSET, curarea->winy-st->lheight*(i+1));
+
+ draw_textscroll(st);
+
+ curarea->win_swap= WIN_BACK_OK;
+}
+
+void pop_space_text (SpaceText *st)
+{
+ int i, x;
+
+ if(!st) return;
+ if(!st->text) return;
+ if(!st->text->curl) return;
+
+ i= txt_get_span(st->text->lines.first, st->text->curl);
+ if (st->top+st->viewlines <= i || st->top > i) {
+ st->top= i - st->viewlines/2;
+ }
+
+ x= text_draw(st, st->text->curl->line, st->left, st->text->curc, 0, 0, 0);
+
+ if (x==0 || x>curarea->winx) {
+ st->left= st->text->curc-0.5*(curarea->winx)/spacetext_get_fontwidth(st);
+ }
+
+ if (st->top < 0) st->top= 0;
+ if (st->left <0) st->left= 0;
+}
+
+void add_text_fs(char *file)
+{
+ SpaceText *st= curarea->spacedata.first;
+ Text *text;
+
+ if (!st) return;
+ if (st->spacetype != SPACE_TEXT) return;
+
+ text= add_text(file);
+
+ st->text= text;
+
+ st->top= 0;
+
+ allqueue(REDRAWTEXT, 0);
+ allqueue(REDRAWHEADERS, 0);
+}
+
+void free_textspace(SpaceText *st)
+{
+ if (!st) return;
+
+ st->text= NULL;
+}
+
+static void save_mem_text(char *str)
+{
+ SpaceText *st= curarea->spacedata.first;
+ Text *text;
+
+ if (!str) return;
+
+ if (!st) return;
+ if (st->spacetype != SPACE_TEXT) return;
+
+ text= st->text;
+ if(!text) return;
+
+ if (text->name) MEM_freeN(text->name);
+ text->name= MEM_mallocN(strlen(str)+1, "textname");
+ strcpy(text->name, str);
+
+ text->flags ^= TXT_ISMEM;
+
+ txt_write_file(text);
+}
+
+void txt_write_file(Text *text)
+{
+ FILE *fp;
+ TextLine *tmp;
+
+ /* Do we need to get a filename? */
+ if (text->flags & TXT_ISMEM) {
+ activate_fileselect(FILE_SPECIAL, "SAVE TEXT FILE", G.sce, save_mem_text);
+ return;
+ }
+
+ /* Should we ask to save over? */
+ if (text->flags & TXT_ISTMP) {
+ if (BLI_exists(text->name)) {
+ if (!okee("Save over?")) return;
+ } else if (!okee("Create new file?")) return;
+
+ text->flags ^= TXT_ISTMP;
+ }
+
+ fp= fopen(text->name, "w");
+ if (fp==NULL) {
+ error("Unable to save file");
+ return;
+ }
+
+ tmp= text->lines.first;
+ while (tmp) {
+ if (tmp->next) fprintf(fp, "%s\n", tmp->line);
+ else fprintf(fp, "%s", tmp->line);
+
+ tmp= tmp->next;
+ }
+
+ fclose (fp);
+
+ if (text->flags & TXT_ISDIRTY) text->flags ^= TXT_ISDIRTY;
+}
+
+void unlink_text(Text *text)
+{
+ bScreen *scr;
+ ScrArea *area;
+ SpaceLink *sl;
+
+ for (scr= G.main->screen.first; scr; scr= scr->id.next) {
+ for (area= scr->areabase.first; area; area= area->next) {
+ for (sl= area->spacedata.first; sl; sl= sl->next) {
+ if (sl->spacetype==SPACE_TEXT) {
+ SpaceText *st= (SpaceText*) sl;
+
+ if (st->text==text) {
+ st->text= NULL;
+ st->top= 0;
+
+ if (st==area->spacedata.first) {
+ scrarea_queue_redraw(area);
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+static int jumptoline_interactive(SpaceText *st) {
+ short nlines= txt_get_span(st->text->lines.first, st->text->lines.last)+1;
+ short tmp= txt_get_span(st->text->lines.first, st->text->curl)+1;
+
+ if (button(&tmp, 1, nlines, "Jump to line:")) {
+ txt_move_toline(st->text, tmp-1, 0);
+ pop_space_text(st);
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+void winqreadtextspace(unsigned short event, short val, char ascii)
+{
+ SpaceText *st= curarea->spacedata.first;
+ Text *text= st->text;
+ char *py_filename;
+ int do_draw=0, p;
+
+ if (BPY_spacetext_is_pywin(st)) {
+ BPY_spacetext_do_pywin_event(st, event, val);
+ return;
+ }
+
+ text= st->text;
+
+ if (!text) {
+ if (val && !ELEM(G.qual, 0, LR_SHIFTKEY)) {
+ if (event==FKEY && (G.qual & LR_ALTKEY) && (G.qual & LR_SHIFTKEY)) {
+ switch (pupmenu("File %t|New %x0|Open... %x1")) {
+ case 0:
+ st->text= add_empty_text();
+ st->top= 0;
+
+ allqueue(REDRAWTEXT, 0);
+ allqueue(REDRAWHEADERS, 0);
+ break;
+ case 1:
+ activate_fileselect(FILE_SPECIAL, "LOAD TEXT FILE", G.sce, add_text_fs);
+ break;
+ }
+ } else if (event==QKEY) {
+ if(okee("QUIT BLENDER")) exit_usiblender();
+ }
+ }
+
+ return;
+ }
+
+ if (event==LEFTMOUSE) {
+ if (val) {
+ short mval[2];
+
+ getmouseco_areawin(mval);
+
+ if (mval[0]>2 && mval[0]<20 && mval[1]>2 && mval[1]<curarea->winy-2) {
+ do_textscroll(st, 2);
+ } else {
+ do_selection(st, G.qual&LR_SHIFTKEY);
+ do_draw= 1;
+ }
+ }
+ } else if (event==MIDDLEMOUSE) {
+ if (val) {
+ do_textscroll(st, 1);
+ }
+ } else if (ascii) {
+ if (txt_add_char(text, ascii)) {
+ pop_space_text(st);
+ do_draw= 1;
+ }
+ } else if (val) {
+ switch (event) {
+ case FKEY:
+ if ((G.qual & LR_ALTKEY) && (G.qual & LR_SHIFTKEY)) {
+ p= pupmenu("File %t|New %x0|Open... %x1|Save %x2|Save As...%x3");
+
+ switch(p) {
+ case 0:
+ st->text= add_empty_text();
+ st->top= 0;
+
+ allqueue(REDRAWTEXT, 0);
+ allqueue(REDRAWHEADERS, 0);
+ break;
+
+ case 1:
+ activate_fileselect(FILE_SPECIAL, "LOAD TEXT FILE", G.sce, add_text_fs);
+ break;
+
+ case 3:
+ text->flags |= TXT_ISMEM;
+
+ case 2:
+ txt_write_file(text);
+ do_draw= 1;
+ break;
+
+ default:
+ break;
+ }
+ } else if (G.qual & LR_ALTKEY) {
+ char *findstr= last_txt_find_string;
+
+ if (txt_has_sel(text) && !(G.qual & LR_CTRLKEY)) {
+ findstr= txt_sel_to_buf(text);
+ } else if (!last_txt_find_string || (G.qual & LR_CTRLKEY)) {
+ char buf[256];
+
+ if (findstr && strlen(findstr)<(sizeof(buf)-1))
+ strcpy(buf, findstr);
+ else
+ buf[0]= 0;
+
+ if (sbutton(buf, 0, sizeof(buf)-1, "Find: ") && buf[0])
+ findstr= BLI_strdup(buf);
+ else
+ findstr= NULL;
+ }
+
+ if (findstr!=last_txt_find_string) {
+ if (last_txt_find_string)
+ MEM_freeN(last_txt_find_string);
+ last_txt_find_string= findstr;
+ }
+
+ if (findstr) {
+ if (txt_find_string(text, findstr))
+ pop_space_text(st);
+ else
+ error("Not found: %s", findstr);
+ }
+
+ do_draw= 1;
+ }
+
+ break;
+
+ case EKEY:
+ if (G.qual & LR_ALTKEY && G.qual & LR_SHIFTKEY) {
+ p= pupmenu("Edit %t|"
+ "Cut %x0|"
+ "Copy %x1|"
+ "Paste %x2|"
+ "Print Cut Buffer %x3");
+ switch(p) {
+ case 0:
+ txt_cut_sel(text);
+ do_draw= 1;
+ break;
+ case 1:
+ txt_copy_sel(text);
+ do_draw= 1;
+ break;
+ case 2:
+ txt_paste(text);
+ do_draw= 1;
+ break;
+ case 3:
+ txt_print_cutbuffer();
+ break;
+ }
+ }
+ break;
+
+ case VKEY:
+ if (G.qual & LR_ALTKEY && G.qual & LR_SHIFTKEY) {
+ p= pupmenu("View %t|"
+ "Top of File %x0|"
+ "Bottom of File %x1|"
+ "Page Up %x2|"
+ "Page Down %x3");
+ switch(p) {
+ case 0:
+ txt_move_bof(text, 0);
+ do_draw= 1;
+ pop_space_text(st);
+ break;
+
+ case 1:
+ txt_move_eof(text, 0);
+ do_draw= 1;
+ pop_space_text(st);
+ break;
+
+ case 2:
+ screen_skip(st, -st->viewlines);
+ do_draw= 1;
+ break;
+
+ case 3:
+ screen_skip(st, st->viewlines);
+ do_draw= 1;
+ break;
+ }
+ }
+ break;
+
+ case SKEY:
+ if (G.qual & LR_ALTKEY && G.qual & LR_SHIFTKEY) {
+ p= pupmenu("Select %t|"
+ "Select All %x0|"
+ "Select Line %x1|"
+ "Jump to Line %x3");
+ switch(p) {
+ case 0:
+ txt_sel_all(text);
+ do_draw= 1;
+ break;
+
+ case 1:
+ txt_sel_line(text);
+ do_draw= 1;
+ break;
+
+ case 3:
+ do_draw= jumptoline_interactive(st);
+ break;
+ }
+ }
+ break;
+
+ case QKEY:
+ if(okee("QUIT BLENDER")) exit_usiblender();
+ break;
+ }
+
+ switch(event) {
+ case AKEY:
+ if (G.qual & LR_CTRLKEY) {
+ txt_move_bol(text, G.qual & LR_SHIFTKEY);
+ do_draw= 1;
+ pop_space_text(st);
+ } else if (G.qual & LR_ALTKEY) {
+ txt_sel_all(text);
+ do_draw= 1;
+ }
+ break;
+
+ case CKEY:
+ if (G.qual & LR_ALTKEY) {
+ txt_copy_sel(text);
+ do_draw= 1;
+ }
+ break;
+
+ case DKEY:
+ if (G.qual & LR_CTRLKEY) {
+ txt_delete_char(text);
+ do_draw= 1;
+ pop_space_text(st);
+ }
+ break;
+
+ case EKEY:
+ if (G.qual & LR_CTRLKEY) {
+ txt_move_eol(text, G.qual & LR_SHIFTKEY);
+ do_draw= 1;
+ pop_space_text(st);
+ }
+ break;
+
+ case JKEY:
+ if (G.qual & LR_ALTKEY) {
+ do_draw= jumptoline_interactive(st);
+ }
+ break;
+
+ case OKEY:
+ if (G.qual & LR_ALTKEY) {
+ activate_fileselect(FILE_SPECIAL, "LOAD TEXT FILE", G.sce, add_text_fs);
+ }
+ break;
+
+ case PKEY:
+ if (G.qual & LR_ALTKEY) {
+ if (!BPY_txt_do_python(st)) {
+ int lineno = BPY_Err_getLinenumber();
+ // jump to error if happened in current text:
+ py_filename = (char*) BPY_Err_getFilename();
+ if (!strcmp(py_filename, st->text->id.name+2)) {
+ error("Python script error, check console");
+ if (lineno >= 0) {
+ txt_move_toline(text, lineno-1, 0);
+ txt_sel_line(text);
+ do_draw= 1;
+ pop_space_text(st);
+ }
+ } else {
+ error("Error in other (possibly external) file, "\
+ "check console");
+ }
+ }
+ }
+ break;
+
+ case RKEY:
+ if (G.qual & LR_ALTKEY) {
+ txt_do_redo(text);
+ do_draw= 1;
+ }
+ if (G.qual & LR_CTRLKEY) {
+ if (text->compiled) BPY_free_compiled_text(text);
+ text->compiled = NULL;
+ if (okee("Reopen Text")) {
+ if (!reopen_text(text)) {
+ error("Could not reopen file");
+ }
+ }
+ do_draw= 1;
+ }
+ break;
+
+ case SKEY:
+ if (G.qual & LR_ALTKEY) {
+ if (G.qual & LR_SHIFTKEY)
+ if (text) text->flags |= TXT_ISMEM;
+
+ txt_write_file(text);
+ do_draw= 1;
+ }
+ break;
+
+ case UKEY:
+ if (G.qual & LR_ALTKEY) {
+ if (G.qual & LR_SHIFTKEY) txt_print_undo(text);
+ else {
+ txt_do_undo(text);
+ do_draw= 1;
+ }
+ }
+ break;
+
+ case VKEY:
+ if (G.qual & LR_ALTKEY) {
+ txt_paste(text);
+ do_draw= 1;
+ pop_space_text(st);
+ }
+ break;
+
+ case XKEY:
+ if (G.qual & LR_ALTKEY) {
+ txt_cut_sel(text);
+ do_draw= 1;
+ pop_space_text(st);
+ }
+ break;
+
+ case TABKEY:
+ txt_add_char(text, '\t');
+ pop_space_text(st);
+ do_draw= 1;
+ break;
+
+ case RETKEY:
+ txt_split_curline(text);
+ do_draw= 1;
+ pop_space_text(st);
+ break;
+
+ case BACKSPACEKEY:
+ txt_backspace_char(text);
+ do_draw= 1;
+ pop_space_text(st);
+ break;
+
+ case DELKEY:
+ txt_delete_char(text);
+ do_draw= 1;
+ pop_space_text(st);
+ break;
+
+ case DOWNARROWKEY:
+ txt_move_down(text, G.qual & LR_SHIFTKEY);
+ do_draw= 1;
+ pop_space_text(st);
+ break;
+
+ case LEFTARROWKEY:
+ txt_move_left(text, G.qual & LR_SHIFTKEY);
+ do_draw= 1;
+ pop_space_text(st);
+ break;
+
+ case RIGHTARROWKEY:
+ txt_move_right(text, G.qual & LR_SHIFTKEY);
+ do_draw= 1;
+ pop_space_text(st);
+ break;
+
+ case UPARROWKEY:
+ txt_move_up(text, G.qual & LR_SHIFTKEY);
+ do_draw= 1;
+ pop_space_text(st);
+ break;
+
+ case PAGEDOWNKEY:
+ screen_skip(st, st->viewlines);
+ do_draw= 1;
+ break;
+
+ case PAGEUPKEY:
+ screen_skip(st, -st->viewlines);
+ do_draw= 1;
+ break;
+ }
+ }
+
+ if (do_draw) {
+ ScrArea *sa;
+
+ for (sa= G.curscreen->areabase.first; sa; sa= sa->next) {
+ SpaceText *st= sa->spacedata.first;
+
+ if (st && st->spacetype==SPACE_TEXT) {
+ scrarea_queue_redraw(sa);
+ }
+ }
+ }
+}
diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c
new file mode 100644
index 00000000000..1db14d8cad9
--- /dev/null
+++ b/source/blender/src/drawview.c
@@ -0,0 +1,1650 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 NAN_LINEAR_PHYSICS
+
+#include <math.h>
+#ifndef WIN32
+#include <unistd.h>
+#include <sys/times.h>
+#else
+#include <io.h>
+#include "BLI_winstuff.h"
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "PIL_time.h"
+
+#include "BMF_Api.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+
+#include "IMB_imbuf_types.h"
+
+#include "DNA_object_types.h"
+#include "DNA_constraint_types.h"
+#include "DNA_group_types.h"
+#include "DNA_image_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_userdef_types.h"
+
+#include "BKE_action.h"
+#include "BKE_anim.h"
+#include "BKE_constraint.h"
+#include "BKE_displist.h"
+#include "BKE_global.h"
+#include "BKE_ika.h"
+#include "BKE_image.h"
+#include "BKE_ipo.h"
+#include "BKE_key.h"
+#include "BKE_main.h"
+#include "BKE_object.h"
+#include "BKE_texture.h"
+#include "BKE_utildefines.h"
+
+#include "BIF_gl.h"
+#include "BIF_resources.h"
+#include "BIF_screen.h"
+#include "BIF_interface.h"
+#include "BIF_space.h"
+#include "BIF_buttons.h"
+#include "BIF_drawimage.h"
+#include "BIF_editgroup.h"
+#include "BIF_mywindow.h"
+
+#include "BDR_drawmesh.h"
+#include "BDR_drawobject.h"
+
+#include "BSE_view.h"
+#include "BSE_drawview.h"
+#include "BSE_headerbuttons.h"
+
+#include "RE_renderconverter.h"
+
+#include "BPY_extern.h" // Blender Python library
+
+#include "interface.h"
+#include "blendef.h"
+#include "mydevice.h"
+
+/* Modules used */
+#include "render.h"
+#include "radio.h"
+
+/* for physics in animation playback */
+#ifdef NAN_LINEAR_PHYSICS
+#include "sumo.h"
+#endif
+
+/* locals */
+void drawname(Object *ob);
+void star_stuff_init_func(void);
+void star_stuff_vertex_func(float* i);
+void star_stuff_term_func(void);
+
+void star_stuff_init_func(void)
+{
+ cpack(-1);
+ glPointSize(1.0);
+ glBegin(GL_POINTS);
+}
+void star_stuff_vertex_func(float* i)
+{
+ glVertex3fv(i);
+}
+void star_stuff_term_func(void)
+{
+ glEnd();
+}
+
+void setalpha_bgpic(BGpic *bgpic)
+{
+ int x, y, alph;
+ char *rect;
+
+ alph= (int)(255.0*(1.0-bgpic->blend));
+
+ rect= (char *)bgpic->rect;
+ for(y=0; y< bgpic->yim; y++) {
+ for(x= bgpic->xim; x>0; x--, rect+=4) {
+ rect[3]= alph;
+ }
+ }
+}
+
+
+static float light_pos1[] = { -0.3, 0.3, 0.90, 0.0 };
+/* static float light_pos2[] = { 0.3, -0.3, -0.90, 0.0 }; never used? */
+
+void default_gl_light(void)
+{
+ float mat_specular[] = { 0.5, 0.5, 0.5, 1.0 };
+ float light_col1[] = { 0.8, 0.8, 0.8, 0.0 };
+
+ int a;
+
+ glLightfv(GL_LIGHT0, GL_POSITION, light_pos1);
+ glLightfv(GL_LIGHT0, GL_DIFFUSE, light_col1);
+ glLightfv(GL_LIGHT0, GL_SPECULAR, mat_specular);
+
+ glEnable(GL_LIGHT0);
+ for(a=1; a<8; a++) glDisable(GL_LIGHT0+a);
+ glDisable(GL_LIGHTING);
+
+ glDisable(GL_COLOR_MATERIAL);
+}
+
+void init_gl_stuff(void)
+{
+ float mat_specular[] = { 0.5, 0.5, 0.5, 1.0 };
+ float mat_shininess[] = { 35.0 };
+/* float one= 1.0; */
+ int a, x, y;
+ GLubyte pat[32*32];
+ const GLubyte *patc= pat;
+
+ glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_specular);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
+
+ default_gl_light();
+
+ /* no local viewer, looks ugly in ortho mode */
+ /* glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, &one); */
+
+ glDepthFunc(GL_LEQUAL);
+ /* scaling matrices */
+ glEnable(GL_NORMALIZE);
+
+ glShadeModel(GL_FLAT);
+
+ glDisable(GL_ALPHA_TEST);
+ glDisable(GL_BLEND);
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_FOG);
+ glDisable(GL_LIGHTING);
+ glDisable(GL_LOGIC_OP);
+ glDisable(GL_STENCIL_TEST);
+ glDisable(GL_TEXTURE_1D);
+ glDisable(GL_TEXTURE_2D);
+
+ glPixelTransferi(GL_MAP_COLOR, GL_FALSE);
+ glPixelTransferi(GL_RED_SCALE, 1);
+ glPixelTransferi(GL_RED_BIAS, 0);
+ glPixelTransferi(GL_GREEN_SCALE, 1);
+ glPixelTransferi(GL_GREEN_BIAS, 0);
+ glPixelTransferi(GL_BLUE_SCALE, 1);
+ glPixelTransferi(GL_BLUE_BIAS, 0);
+ glPixelTransferi(GL_ALPHA_SCALE, 1);
+ glPixelTransferi(GL_ALPHA_BIAS, 0);
+
+ a= 0;
+ for(x=0; x<32; x++) {
+ for(y=0; y<4; y++) {
+ if( (x) & 1) pat[a++]= 0x88;
+ else pat[a++]= 0x22;
+ }
+ }
+
+ glPolygonStipple(patc);
+
+
+ init_realtime_GL();
+}
+
+void two_sided(int val)
+{
+
+ /* twosided aan: geft errors bij x flip! */
+ glLightModeliv(GL_LIGHT_MODEL_TWO_SIDE, (GLint *)&val);
+}
+
+void circf(float x, float y, float rad)
+{
+ GLUquadricObj *qobj = gluNewQuadric();
+
+ gluQuadricDrawStyle(qobj, GLU_FILL);
+
+ glPushMatrix();
+
+ glTranslatef(x, y, 0.);
+
+ gluDisk( qobj, 0.0, rad, 32, 1);
+
+ glPopMatrix();
+
+ gluDeleteQuadric(qobj);
+}
+
+void circ(float x, float y, float rad)
+{
+ GLUquadricObj *qobj = gluNewQuadric();
+
+ gluQuadricDrawStyle(qobj, GLU_SILHOUETTE);
+
+ glPushMatrix();
+
+ glTranslatef(x, y, 0.);
+
+ gluDisk( qobj, 0.0, rad, 32, 1);
+
+ glPopMatrix();
+
+ gluDeleteQuadric(qobj);
+}
+
+/* ********** IN ONTWIKKELING ********** */
+
+static void draw_bgpic(void)
+{
+ BGpic *bgpic;
+ Image *ima;
+ float vec[3], fac, asp, zoomx, zoomy;
+ int x1, y1, x2, y2, cx, cy;
+ short mval[2];
+
+ bgpic= G.vd->bgpic;
+ if(bgpic==0) return;
+
+ if(bgpic->tex) {
+ init_render_texture(bgpic->tex);
+ free_unused_animimages();
+ ima= bgpic->tex->ima;
+ end_render_texture(bgpic->tex);
+ }
+ else {
+ ima= bgpic->ima;
+ }
+
+ if(ima==0) return;
+ if(ima->ok==0) return;
+
+ /* plaatje testen */
+ if(ima->ibuf==0) {
+
+ if(bgpic->rect) MEM_freeN(bgpic->rect);
+ bgpic->rect= 0;
+
+ if(bgpic->tex) {
+ ima_ibuf_is_nul(bgpic->tex);
+ }
+ else {
+ waitcursor(1);
+ load_image(ima, IB_rect, G.sce, G.scene->r.cfra);
+ waitcursor(0);
+ }
+ if(ima->ibuf==0) {
+ ima->ok= 0;
+ return;
+ }
+ }
+
+ if(bgpic->rect==0) {
+
+ bgpic->rect= MEM_dupallocN(ima->ibuf->rect);
+ bgpic->xim= ima->ibuf->x;
+ bgpic->yim= ima->ibuf->y;
+ setalpha_bgpic(bgpic);
+ }
+
+ if(G.vd->persp==2) {
+ rcti vb;
+
+ calc_viewborder(G.vd, &vb);
+
+ x1= vb.xmin;
+ y1= vb.ymin;
+ x2= vb.xmax;
+ y2= vb.ymax;
+ }
+ else {
+ /* windowco berekenen */
+ initgrabz(0.0, 0.0, 0.0);
+ window_to_3d(vec, 1, 0);
+ fac= MAX3( fabs(vec[0]), fabs(vec[1]), fabs(vec[1]) );
+ fac= 1.0/fac;
+
+ asp= ( (float)ima->ibuf->y)/(float)ima->ibuf->x;
+
+ vec[0]= vec[1]= vec[2]= 0.0;
+ project_short_noclip(vec, mval);
+ cx= mval[0];
+ cy= mval[1];
+
+ x1= cx+ fac*(bgpic->xof-bgpic->size);
+ y1= cy+ asp*fac*(bgpic->yof-bgpic->size);
+ x2= cx+ fac*(bgpic->xof+bgpic->size);
+ y2= cy+ asp*fac*(bgpic->yof+bgpic->size);
+ }
+
+ /* volledige clip? */
+
+ if(x2 < 0 ) return;
+ if(y2 < 0 ) return;
+ if(x1 > curarea->winx ) return;
+ if(y1 > curarea->winy ) return;
+
+ zoomx= x2-x1;
+ zoomx /= (float)ima->ibuf->x;
+ zoomy= y2-y1;
+ zoomy /= (float)ima->ibuf->y;
+
+ glEnable(GL_BLEND);
+ if(G.zbuf) glDisable(GL_DEPTH_TEST);
+
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ rectwrite_part(curarea->winrct.xmin, curarea->winrct.ymin, curarea->winrct.xmax, curarea->winrct.ymax,
+ x1+curarea->winrct.xmin, y1+curarea->winrct.ymin, ima->ibuf->x, ima->ibuf->y, zoomx, zoomy, bgpic->rect);
+
+ glBlendFunc(GL_ONE, GL_ZERO);
+ glDisable(GL_BLEND);
+ if(G.zbuf) glEnable(GL_DEPTH_TEST);
+
+}
+
+void timestr(double time, char *str)
+{
+ /* formaat 00:00:00.00 (hr:min:sec) string moet 12 lang */
+ int hr= (int) time/(60*60);
+ int min= (int) fmod(time/60, 60.0);
+ int sec= (int) fmod(time, 60.0);
+ int hun= (int) fmod(time*100.0, 100.0);
+
+ if (hr) {
+ sprintf(str, "%.2d:%.2d:%.2d.%.2d",hr,min,sec,hun);
+ } else {
+ sprintf(str, "%.2d:%.2d.%.2d",min,sec,hun);
+ }
+
+ str[11]=0;
+}
+
+
+static void drawgrid(void)
+{
+ /* extern short bgpicmode; */
+ float wx, wy, x, y, fw, fx, fy, dx;
+ float vec4[4];
+
+ vec4[0]=vec4[1]=vec4[2]=0.0;
+ vec4[3]= 1.0;
+ Mat4MulVec4fl(G.vd->persmat, vec4);
+ fx= vec4[0];
+ fy= vec4[1];
+ fw= vec4[3];
+
+ wx= (curarea->winx/2.0); /* ivm afrondfoutjes, grid op verkeerde plek */
+ wy= (curarea->winy/2.0);
+
+ x= (wx)*fx/fw;
+ y= (wy)*fy/fw;
+
+ vec4[0]=vec4[1]=G.vd->grid;
+ vec4[2]= 0.0;
+ vec4[3]= 1.0;
+ Mat4MulVec4fl(G.vd->persmat, vec4);
+ fx= vec4[0];
+ fy= vec4[1];
+ fw= vec4[3];
+
+ dx= fabs(x-(wx)*fx/fw);
+ if(dx==0) dx= fabs(y-(wy)*fy/fw);
+
+ if(dx<6.0) {
+ dx*= 10.0;
+ setlinestyle(3);
+ if(dx<6.0) {
+ dx*= 10.0;
+ if(dx<6.0) {
+ setlinestyle(0);
+ return;
+ }
+ }
+ }
+
+ persp(0);
+
+ cpack(0x484848);
+
+ x+= (wx);
+ y+= (wy);
+ fx= x/dx;
+ fx= x-dx*floor(fx);
+
+ while(fx< curarea->winx) {
+ fdrawline(fx, 0.0, fx, (float)curarea->winy);
+ fx+= dx;
+ }
+
+ fy= y/dx;
+ fy= y-dx*floor(fy);
+
+
+ while(fy< curarea->winy) {
+ fdrawline(0.0, fy, (float)curarea->winx, fy);
+ fy+= dx;
+ }
+
+ /* kruis in midden */
+ if(G.vd->view==3) cpack(0xA0D0A0); /* y-as */
+ else cpack(0xA0A0D0); /* x-as */
+
+ fdrawline(0.0, y, (float)curarea->winx, y);
+
+ if(G.vd->view==7) cpack(0xA0D0A0); /* y-as */
+ else cpack(0xE0A0A0); /* z-as */
+
+ fdrawline(x, 0.0, x, (float)curarea->winy);
+
+ persp(1);
+ setlinestyle(0);
+}
+
+
+static void drawfloor(void)
+{
+ View3D *vd;
+ float vert[3], grid;
+ int a, gridlines;
+
+ vd= curarea->spacedata.first;
+
+ vert[2]= 0.0;
+
+ if(vd->gridlines<3) return;
+
+ gridlines= vd->gridlines/2;
+ grid= gridlines*vd->grid;
+
+ cpack(0x484848);
+
+ for(a= -gridlines;a<=gridlines;a++) {
+
+ if(a==0) {
+ if(vd->persp==0) cpack(0xA0D0A0);
+ else cpack(0x402000);
+ }
+ else if(a==1) {
+ cpack(0x484848);
+ }
+
+
+ glBegin(GL_LINE_STRIP);
+ vert[0]= a*vd->grid;
+ vert[1]= grid;
+ glVertex3fv(vert);
+ vert[1]= -grid;
+ glVertex3fv(vert);
+ glEnd();
+ }
+
+ cpack(0x484848);
+
+ for(a= -gridlines;a<=gridlines;a++) {
+ if(a==0) {
+ if(vd->persp==0) cpack(0xA0A0D0);
+ else cpack(0);
+ }
+ else if(a==1) {
+ cpack(0x484848);
+ }
+
+ glBegin(GL_LINE_STRIP);
+ vert[1]= a*vd->grid;
+ vert[0]= grid;
+ glVertex3fv(vert );
+ vert[0]= -grid;
+ glVertex3fv(vert);
+ glEnd();
+ }
+
+}
+
+static void drawcursor(void)
+{
+
+ if(G.f & G_PLAYANIM) return;
+
+ project_short( give_cursor(), &G.vd->mx);
+
+ G.vd->mxo= G.vd->mx;
+ G.vd->myo= G.vd->my;
+
+ if( G.vd->mx!=3200) {
+
+ setlinestyle(0);
+ cpack(0xFF);
+ circ((float)G.vd->mx, (float)G.vd->my, 10.0);
+ setlinestyle(4);
+ cpack(0xFFFFFF);
+ circ((float)G.vd->mx, (float)G.vd->my, 10.0);
+ setlinestyle(0);
+ cpack(0x0);
+
+ sdrawline(G.vd->mx-20, G.vd->my, G.vd->mx-5, G.vd->my);
+ sdrawline(G.vd->mx+5, G.vd->my, G.vd->mx+20, G.vd->my);
+ sdrawline(G.vd->mx, G.vd->my-20, G.vd->mx, G.vd->my-5);
+ sdrawline(G.vd->mx, G.vd->my+5, G.vd->mx, G.vd->my+20);
+ }
+}
+
+static void view3d_get_viewborder_size(View3D *v3d, float size_r[2])
+{
+ float winmax= MAX2(v3d->area->winx, v3d->area->winy);
+ float aspect= (float) (G.scene->r.xsch*G.scene->r.xasp)/(G.scene->r.ysch*G.scene->r.yasp);
+
+ if(aspect>1.0) {
+ size_r[0]= winmax;
+ size_r[1]= winmax/aspect;
+ } else {
+ size_r[0]= winmax*aspect;
+ size_r[1]= winmax;
+ }
+}
+
+void calc_viewborder(struct View3D *v3d, rcti *viewborder_r)
+{
+ float zoomfac, size[2];
+
+ view3d_get_viewborder_size(v3d, size);
+
+ /* magic zoom calculation, no idea what
+ * it signifies, if you find out, tell me! -zr
+ */
+ zoomfac= (M_SQRT2 + v3d->camzoom/50.0);
+ zoomfac= (zoomfac*zoomfac)*0.25;
+
+ size[0]= size[0]*zoomfac;
+ size[1]= size[1]*zoomfac;
+
+ /* center in window */
+ viewborder_r->xmin= 0.5*v3d->area->winx - 0.5*size[0];
+ viewborder_r->ymin= 0.5*v3d->area->winy - 0.5*size[1];
+ viewborder_r->xmax= viewborder_r->xmin + size[0];
+ viewborder_r->ymax= viewborder_r->ymin + size[1];
+}
+
+void view3d_set_1_to_1_viewborder(View3D *v3d)
+{
+ float size[2];
+ int im_width= (G.scene->r.size*G.scene->r.xsch)/100;
+
+ view3d_get_viewborder_size(v3d, size);
+
+ v3d->camzoom= (sqrt(4.0*im_width/size[0]) - M_SQRT2)*50.0;
+ v3d->camzoom= CLAMPIS(v3d->camzoom, -30, 300);
+}
+
+static void drawviewborder(void)
+{
+ float fac, a;
+ float x1, x2, y1, y2;
+ float x3, y3, x4, y4;
+ rcti viewborder;
+
+ calc_viewborder(G.vd, &viewborder);
+ x1= viewborder.xmin;
+ y1= viewborder.ymin;
+ x2= viewborder.xmax;
+ y2= viewborder.ymax;
+
+ /* rand */
+ setlinestyle(3);
+ cpack(0);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ glRectf(x1+1, y1-1, x2+1, y2-1);
+
+ cpack(0xFFFFFF);
+ glRectf(x1, y1, x2, y2);
+
+ /* border */
+ if(G.scene->r.mode & R_BORDER) {
+
+ cpack(0);
+ x3= x1+ G.scene->r.border.xmin*(x2-x1);
+ y3= y1+ G.scene->r.border.ymin*(y2-y1);
+ x4= x1+ G.scene->r.border.xmax*(x2-x1);
+ y4= y1+ G.scene->r.border.ymax*(y2-y1);
+
+ glRectf(x3+1, y3-1, x4+1, y4-1);
+
+ cpack(0x4040FF);
+ glRectf(x3, y3, x4, y4);
+ }
+
+ /* safetykader */
+
+ fac= 0.1;
+
+ a= fac*(x2-x1);
+ x1+= a;
+ x2-= a;
+
+ a= fac*(y2-y1);
+ y1+= a;
+ y2-= a;
+
+ cpack(0);
+ glRectf(x1+1, y1-1, x2+1, y2-1);
+ cpack(0xFFFFFF);
+ glRectf(x1, y1, x2, y2);
+
+ setlinestyle(0);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+
+}
+
+
+void backdrawview3d(int test)
+{
+ struct Base *base;
+ int tel=1;
+
+ if(G.f & (G_VERTEXPAINT|G_FACESELECT|G_TEXTUREPAINT|G_WEIGHTPAINT));
+ else {
+ G.vd->flag &= ~V3D_NEEDBACKBUFDRAW;
+ return;
+ }
+
+ if(G.vd->flag & V3D_NEEDBACKBUFDRAW); else return;
+ if(G.obedit) {
+ G.vd->flag &= ~V3D_NEEDBACKBUFDRAW;
+ return;
+ }
+
+ if(test) {
+ if(qtest()) {
+ addafterqueue(curarea->win, BACKBUFDRAW, 1);
+ return;
+ }
+ }
+
+ if(G.vd->drawtype > OB_WIRE) G.zbuf= TRUE;
+ curarea->win_swap &= ~WIN_BACK_OK;
+
+ glDisable(GL_DITHER);
+
+ glClearColor(0.0, 0.0, 0.0, 0.0);
+ if(G.zbuf) {
+ glEnable(GL_DEPTH_TEST);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ }
+ else {
+ glClear(GL_COLOR_BUFFER_BIT);
+ glDisable(GL_DEPTH_TEST);
+ }
+
+ G.f |= G_BACKBUFSEL;
+
+ if(G.f & (G_VERTEXPAINT|G_FACESELECT|G_TEXTUREPAINT|G_WEIGHTPAINT)) {
+ base= (G.scene->basact);
+ if(base && (base->lay & G.vd->lay)) {
+ draw_object(base);
+ }
+ }
+ else {
+
+ base= (G.scene->base.first);
+ while(base) {
+
+ /* elke base ivm meerdere windows */
+ base->selcol= 0x070707 | ( ((tel & 0xF00)<<12) + ((tel & 0xF0)<<8) + ((tel & 0xF)<<4) );
+ tel++;
+
+ if(base->lay & G.vd->lay) {
+
+ if(test) {
+ if(qtest()) {
+ addafterqueue(curarea->win, BACKBUFDRAW, 1);
+ break;
+ }
+ }
+
+ cpack(base->selcol);
+ draw_object(base);
+ }
+ base= base->next;
+ }
+ }
+
+ if(base==0) G.vd->flag &= ~V3D_NEEDBACKBUFDRAW;
+
+ G.f &= ~G_BACKBUFSEL;
+ G.zbuf= FALSE;
+ glDisable(GL_DEPTH_TEST);
+ glEnable(GL_DITHER);
+}
+
+
+void drawname(Object *ob)
+{
+ cpack(0x404040);
+ glRasterPos3f(0.0, 0.0, 0.0);
+
+ BMF_DrawString(G.font, " ");
+ BMF_DrawString(G.font, ob->id.name+2);
+}
+
+static void draw_view_icon(void)
+{
+ BIFIconID icon;
+
+ if(G.vd->view==7) icon= ICON_AXIS_TOP;
+ else if(G.vd->view==1) icon= ICON_AXIS_FRONT;
+ else if(G.vd->view==3) icon= ICON_AXIS_SIDE;
+ else return ;
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ glRasterPos2f(5.0, 5.0);
+ BIF_draw_icon(icon);
+
+ glBlendFunc(GL_ONE, GL_ZERO);
+ glDisable(GL_BLEND);
+}
+
+void drawview3d(void)
+{
+ Base *base;
+ Object *ob;
+
+ setwinmatrixview3d(0); /* 0= geen pick rect */
+
+ setviewmatrixview3d();
+
+ Mat4MulMat4(G.vd->persmat, G.vd->viewmat, curarea->winmat);
+ Mat4Invert(G.vd->persinv, G.vd->persmat);
+ Mat4Invert(G.vd->viewinv, G.vd->viewmat);
+
+ if(G.vd->drawtype > OB_WIRE) {
+ G.zbuf= TRUE;
+ glEnable(GL_DEPTH_TEST);
+ if(G.f & G_SIMULATION) {
+ glClearColor(0.0, 0.0, 0.0, 0.0);
+ }
+ else {
+ glClearColor(0.45, 0.45, 0.45, 0.0);
+ }
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ glLoadIdentity();
+ }
+ else {
+ glClearColor(0.45, 0.45, 0.45, 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+ }
+
+ myloadmatrix(G.vd->viewmat);
+
+ if(G.vd->view==0 || G.vd->persp!=0) {
+ drawfloor();
+ if(G.vd->persp==2) {
+ if(G.scene->world) {
+ if(G.scene->world->mode & WO_STARS) RE_make_stars(star_stuff_init_func,
+ star_stuff_vertex_func,
+ star_stuff_term_func);
+ }
+ if(G.vd->flag & V3D_DISPBGPIC) draw_bgpic();
+ }
+ }
+ else {
+ drawgrid();
+
+ if(G.vd->flag & V3D_DISPBGPIC) {
+ draw_bgpic();
+ }
+ }
+
+ /* Clear the constraint "done" flags */
+ for (base = G.scene->base.first; base; base=base->next){
+ clear_object_constraint_status(base->object);
+ }
+
+ /* eerst set tekenen */
+ if(G.scene->set) {
+
+ /* patchje: kleur blijft constant */
+ G.f |= G_PICKSEL;
+
+ base= G.scene->set->base.first;
+ while(base) {
+ if(G.vd->lay & base->lay) {
+ where_is_object(base->object);
+
+ cpack(0x404040);
+ draw_object(base);
+
+ if(base->object->transflag & OB_DUPLI) {
+ extern ListBase duplilist;
+ Base tbase;
+
+ tbase= *base;
+
+ tbase.flag= OB_FROMDUPLI;
+ make_duplilist(G.scene->set, base->object);
+ ob= duplilist.first;
+ while(ob) {
+ tbase.object= ob;
+ draw_object(&tbase);
+ ob= ob->id.next;
+ }
+ free_duplilist();
+
+ }
+ }
+ base= base->next;
+ }
+
+ G.f &= ~G_PICKSEL;
+ }
+
+/* SILLY CODE!!!! */
+/* See next silly code... why is the same code
+ * ~ duplicated twice, and then this silly if(FALSE)
+ * in part... wacky! and bad!
+ */
+
+ /* eerst niet selected en dupli's */
+ base= G.scene->base.first;
+ while(base) {
+
+ if(G.vd->lay & base->lay) {
+
+ where_is_object(base->object);
+
+ if(FALSE && base->object->transflag & OB_DUPLI) {
+ extern ListBase duplilist;
+ Base tbase;
+
+ /* altijd eerst original tekenen vanwege make_displist */
+ draw_object(base);
+
+ /* patchje: kleur blijft constant */
+ G.f |= G_PICKSEL;
+ cpack(0x404040);
+
+ tbase.flag= OB_FROMDUPLI;
+ make_duplilist(G.scene, base->object);
+
+ ob= duplilist.first;
+ while(ob) {
+ tbase.object= ob;
+ draw_object(&tbase);
+ ob= ob->id.next;
+ }
+ free_duplilist();
+
+ G.f &= ~G_PICKSEL;
+ }
+ else if((base->flag & SELECT)==0) {
+ draw_object(base);
+ }
+
+ }
+
+ base= base->next;
+ }
+ /* selected */
+ base= G.scene->base.first;
+ while(base) {
+
+ if ( ((base)->flag & SELECT) && ((base)->lay & G.vd->lay) ) {
+ draw_object(base);
+ }
+
+ base= base->next;
+ }
+
+/* SILLY CODE!!!! */
+ /* dupli's, als laatste om zeker te zijn de displisten zijn ok */
+ base= G.scene->base.first;
+ while(base) {
+
+ if(G.vd->lay & base->lay) {
+ if(base->object->transflag & OB_DUPLI) {
+ extern ListBase duplilist;
+ Base tbase;
+
+ /* patchje: kleur blijft constant */
+ G.f |= G_PICKSEL;
+ cpack(0x404040);
+
+ tbase.flag= OB_FROMDUPLI;
+ make_duplilist(G.scene, base->object);
+
+ ob= duplilist.first;
+ while(ob) {
+ tbase.object= ob;
+ draw_object(&tbase);
+ ob= ob->id.next;
+ }
+ free_duplilist();
+
+ G.f &= ~G_PICKSEL;
+ }
+ }
+ base= base->next;
+ }
+
+
+ if(G.scene->radio) RAD_drawall(G.vd->drawtype>=OB_SOLID);
+
+ persp(0);
+
+ if(G.vd->persp>1) drawviewborder();
+ drawcursor();
+ draw_view_icon();
+
+ persp(1);
+
+ curarea->win_swap= WIN_BACK_OK;
+
+ if(G.zbuf) {
+ G.zbuf= FALSE;
+ glDisable(GL_DEPTH_TEST);
+ }
+
+ if(G.f & (G_VERTEXPAINT|G_FACESELECT|G_TEXTUREPAINT|G_WEIGHTPAINT)) {
+ G.vd->flag |= V3D_NEEDBACKBUFDRAW;
+ addafterqueue(curarea->win, BACKBUFDRAW, 1);
+ }
+}
+
+
+ /* Called back by rendering system, icky
+ */
+void drawview3d_render(struct View3D *v3d)
+{
+ extern short v3d_windowmode;
+ Base *base;
+ Object *ob;
+
+ /* XXXXXXXX live and die by the hack */
+ free_all_realtime_images();
+ mywindow_build_and_set_renderwin();
+
+ v3d_windowmode= 1;
+ setwinmatrixview3d(0);
+ v3d_windowmode= 0;
+ glMatrixMode(GL_PROJECTION);
+ glLoadMatrixf(R.winmat);
+ glMatrixMode(GL_MODELVIEW);
+
+ setviewmatrixview3d();
+ glLoadMatrixf(v3d->viewmat);
+
+ Mat4MulMat4(v3d->persmat, v3d->viewmat, R.winmat);
+ Mat4Invert(v3d->persinv, v3d->persmat);
+ Mat4Invert(v3d->viewinv, v3d->viewmat);
+
+ if(v3d->drawtype > OB_WIRE) {
+ G.zbuf= TRUE;
+ glEnable(GL_DEPTH_TEST);
+ }
+
+ if (v3d->drawtype==OB_TEXTURE && G.scene->world) {
+ glClearColor(G.scene->world->horr, G.scene->world->horg, G.scene->world->horb, 0.0);
+ } else {
+ glClearColor(0.45, 0.45, 0.45, 0.0);
+ }
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ glLoadIdentity();
+ glLoadMatrixf(v3d->viewmat);
+
+ /* abuse! to make sure it doesnt draw the helpstuff */
+ G.f |= G_SIMULATION;
+
+ do_all_ipos();
+ BPY_do_all_scripts(SCRIPT_FRAMECHANGED);
+ do_all_keys();
+ do_all_actions();
+ do_all_ikas();
+
+ test_all_displists();
+
+ /* niet erg nette calc_ipo en where_is forceer */
+ ob= G.main->object.first;
+ while(ob) {
+ ob->ctime= -123.456;
+ ob= ob->id.next;
+ }
+
+ /* eerst set tekenen */
+ if(G.scene->set) {
+
+ /* patchje: kleur blijft constant */
+ G.f |= G_PICKSEL;
+
+ base= G.scene->set->base.first;
+ while(base) {
+ if(v3d->lay & base->lay) {
+ if ELEM3(base->object->type, OB_LAMP, OB_CAMERA, OB_LATTICE);
+ else {
+ where_is_object(base->object);
+
+ cpack(0x404040);
+ draw_object(base);
+
+ if(base->object->transflag & OB_DUPLI) {
+ extern ListBase duplilist;
+ Base tbase;
+
+ tbase.flag= OB_FROMDUPLI;
+ make_duplilist(G.scene->set, base->object);
+ ob= duplilist.first;
+ while(ob) {
+ tbase.object= ob;
+ draw_object(&tbase);
+ ob= ob->id.next;
+ }
+ free_duplilist();
+ }
+ }
+ }
+ base= base->next;
+ }
+
+ G.f &= ~G_PICKSEL;
+ }
+ for (base = G.scene->base.first; base; base=base->next){
+ clear_object_constraint_status(base->object);
+ }
+ /* eerst niet selected en dupli's */
+ base= G.scene->base.first;
+ while(base) {
+
+ if(v3d->lay & base->lay) {
+ if ELEM3(base->object->type, OB_LAMP, OB_CAMERA, OB_LATTICE);
+ else {
+ where_is_object(base->object);
+
+ if(base->object->transflag & OB_DUPLI) {
+ extern ListBase duplilist;
+ Base tbase;
+
+ /* altijd eerst original tekenen vanwege make_displist */
+ draw_object(base);
+
+ /* patchje: kleur blijft constant */
+ G.f |= G_PICKSEL;
+ cpack(0x404040);
+
+ tbase.flag= OB_FROMDUPLI;
+ make_duplilist(G.scene, base->object);
+ ob= duplilist.first;
+ while(ob) {
+ tbase.object= ob;
+ draw_object(&tbase);
+ ob= ob->id.next;
+ }
+ free_duplilist();
+
+ G.f &= ~G_PICKSEL;
+ }
+ else if((base->flag & SELECT)==0) {
+ draw_object(base);
+ }
+ }
+ }
+
+ base= base->next;
+ }
+
+ /* selected */
+ base= G.scene->base.first;
+ while(base) {
+
+ if ( ((base)->flag & SELECT) && ((base)->lay & v3d->lay) ) {
+ if ELEM3(base->object->type, OB_LAMP, OB_CAMERA, OB_LATTICE);
+ else draw_object(base);
+ }
+
+ base= base->next;
+ }
+
+ if(G.scene->radio) RAD_drawall(G.vd->drawtype>=OB_SOLID);
+
+ if(G.zbuf) {
+ G.zbuf= FALSE;
+ glDisable(GL_DEPTH_TEST);
+ }
+
+ G.f &= ~G_SIMULATION;
+
+ glFinish();
+
+ glReadPixels(0, 0, R.rectx, R.recty, GL_RGBA, GL_UNSIGNED_BYTE, R.rectot);
+ glLoadIdentity();
+
+ free_all_realtime_images();
+}
+
+
+double tottime = 0.0;
+
+int update_time(void)
+{
+ static double ltime;
+ double time;
+
+ time = PIL_check_seconds_timer();
+
+ tottime += (time - ltime);
+ ltime = time;
+ return (tottime < 0.0);
+}
+
+double speed_to_swaptime(int speed)
+{
+ switch(speed) {
+ case 1:
+ return 1.0/60.0;
+ case 2:
+ return 1.0/50.0;
+ case 3:
+ return 1.0/30.0;
+ case 4:
+ return 1.0/25.0;
+ case 5:
+ return 1.0/20.0;
+ case 6:
+ return 1.0/15.0;
+ case 7:
+ return 1.0/12.5;
+ case 8:
+ return 1.0/10.0;
+ case 9:
+ return 1.0/6.0;
+ }
+ return 1.0/4.0;
+}
+
+double key_to_swaptime(int key)
+{
+ switch(key) {
+ case PAD1:
+ G.animspeed= 1;
+ tottime= 0;
+ return speed_to_swaptime(1);
+ case PAD2:
+ G.animspeed= 2;
+ tottime= 0;
+ return speed_to_swaptime(2);
+ case PAD3:
+ G.animspeed= 3;
+ tottime= 0;
+ return speed_to_swaptime(3);
+ case PAD4:
+ G.animspeed= 4;
+ tottime= 0;
+ return speed_to_swaptime(4);
+ case PAD5:
+ G.animspeed= 5;
+ tottime= 0;
+ return speed_to_swaptime(5);
+ case PAD6:
+ G.animspeed= 6;
+ tottime= 0;
+ return speed_to_swaptime(6);
+ case PAD7:
+ G.animspeed= 7;
+ tottime= 0;
+ return speed_to_swaptime(7);
+ case PAD8:
+ G.animspeed= 8;
+ tottime= 0;
+ return speed_to_swaptime(8);
+ case PAD9:
+ G.animspeed= 9;
+ tottime= 0;
+ return speed_to_swaptime(9);
+ }
+
+ return speed_to_swaptime(G.animspeed);
+}
+
+#ifdef NAN_LINEAR_PHYSICS
+
+void sumo_callback(void *obp)
+{
+ Object *ob= obp;
+ SM_Vector3 vec;
+ float matf[3][3];
+ int i, j;
+
+ SM_GetMatrixf(ob->sumohandle, ob->obmat[0]);
+
+ VECCOPY(ob->loc, ob->obmat[3]);
+
+ for (i = 0; i < 3; ++i) {
+ for (j = 0; j < 3; ++j) {
+ matf[i][j] = ob->obmat[i][j];
+ }
+ }
+ Mat3ToEul(matf, ob->rot);
+}
+
+void init_anim_sumo(void)
+{
+ extern Material defmaterial;
+ Base *base;
+ Mesh *me;
+ Object *ob;
+ Material *mat;
+ MFace *mface;
+ MVert *mvert;
+ float centre[3], size[3];
+ int a;
+ SM_ShapeHandle shape;
+ SM_SceneHandle scene;
+ SM_Material material;
+ SM_MassProps massprops;
+ SM_Vector3 vec;
+ SM_Vector3 scaling;
+
+ scene= SM_CreateScene();
+ G.scene->sumohandle = scene;
+
+ vec[0]= 0.0;
+ vec[1]= 0.0;
+ vec[2]= -9.8;
+ SM_SetForceField(scene, vec);
+
+ /* ton: cylinders & cones are still Y-axis up, will be Z-axis later */
+ /* ton: write location/rotation save and restore */
+
+ base= FIRSTBASE;
+ while (base) {
+ if (G.vd->lay & base->lay) {
+ ob= base->object;
+
+ /* define shape, for now only meshes take part in physics */
+ get_local_bounds(ob, centre, size);
+
+ if (ob->type==OB_MESH) {
+ me= ob->data;
+
+ if (ob->gameflag & OB_DYNAMIC) {
+ if (me->sumohandle)
+ shape= me->sumohandle;
+ else {
+ /* make new handle */
+ switch(ob->boundtype) {
+ case OB_BOUND_BOX:
+ shape= SM_Box(2.0*size[0], 2.0*size[1], 2.0*size[2]);
+ break;
+ case OB_BOUND_SPHERE:
+ shape= SM_Sphere(size[0]);
+ break;
+ case OB_BOUND_CYLINDER:
+ shape= SM_Cylinder(size[0], 2.0*size[2]);
+ break;
+ case OB_BOUND_CONE:
+ shape= SM_Cone(size[0], 2.0*size[2]);
+ break;
+ }
+
+ me->sumohandle= shape;
+ }
+ /* sumo material properties */
+ mat= give_current_material(ob, 0);
+ if(mat==NULL)
+ mat= &defmaterial;
+
+ material.restitution= mat->reflect;
+ material.static_friction= mat->friction;
+ material.dynamic_friction= mat->friction;
+
+ /* sumo mass properties */
+ massprops.mass= ob->mass;
+ massprops.center[0]= 0.0;
+ massprops.center[1]= 0.0;
+ massprops.center[2]= 0.0;
+
+ massprops.inertia[0]= 0.5*ob->mass;
+ massprops.inertia[1]= 0.5*ob->mass;
+ massprops.inertia[2]= 0.5*ob->mass;
+
+ massprops.orientation[0]= 0.0;
+ massprops.orientation[1]= 0.0;
+ massprops.orientation[2]= 0.0;
+ massprops.orientation[3]= 1.0;
+
+ ob->sumohandle = SM_CreateObject(ob, shape, &material,
+ &massprops, sumo_callback);
+ SM_AddObject(scene, ob->sumohandle);
+
+ scaling[0] = ob->size[0];
+ scaling[1] = ob->size[1];
+ scaling[2] = ob->size[2];
+ SM_SetMatrixf(ob->sumohandle, ob->obmat[0]);
+ SM_SetScaling(ob->sumohandle, scaling);
+
+ }
+ else {
+ if(me->sumohandle) shape= me->sumohandle;
+ else {
+ /* make new handle */
+ shape= SM_NewComplexShape();
+
+ mface= me->mface;
+ mvert= me->mvert;
+ for(a=0; a<me->totface; a++,mface++) {
+ if(mface->v3) {
+ SM_Begin();
+ SM_Vertex( (mvert+mface->v1)->co[0], (mvert+mface->v1)->co[1], (mvert+mface->v1)->co[2]);
+ SM_Vertex( (mvert+mface->v2)->co[0], (mvert+mface->v2)->co[1], (mvert+mface->v2)->co[2]);
+ SM_Vertex( (mvert+mface->v3)->co[0], (mvert+mface->v3)->co[1], (mvert+mface->v3)->co[2]);
+ if(mface->v4)
+ SM_Vertex( (mvert+mface->v4)->co[0], (mvert+mface->v4)->co[1], (mvert+mface->v4)->co[2]);
+ SM_End();
+ }
+ }
+
+ SM_EndComplexShape();
+
+ me->sumohandle= shape;
+ }
+ /* sumo material properties */
+ mat= give_current_material(ob, 0);
+ if(mat==NULL)
+ mat= &defmaterial;
+ material.restitution= mat->reflect;
+ material.static_friction= mat->friction;
+ material.dynamic_friction= mat->friction;
+
+ /* sumo mass properties */
+ massprops.mass= ob->mass;
+ massprops.center[0]= 0.0;
+ massprops.center[1]= 0.0;
+ massprops.center[2]= 0.0;
+
+ massprops.inertia[0]= 0.5*ob->mass;
+ massprops.inertia[1]= 0.5*ob->mass;
+ massprops.inertia[2]= 0.5*ob->mass;
+
+ massprops.orientation[0]= 0.0;
+ massprops.orientation[1]= 0.0;
+ massprops.orientation[2]= 0.0;
+ massprops.orientation[3]= 1.0;
+
+ ob->sumohandle= SM_CreateObject(ob, shape, &material, NULL, NULL);
+ SM_AddObject(scene, ob->sumohandle);
+
+ scaling[0] = ob->size[0];
+ scaling[1] = ob->size[1];
+ scaling[2] = ob->size[2];
+ SM_SetMatrixf(ob->sumohandle, ob->obmat[0]);
+ SM_SetScaling(ob->sumohandle, scaling);
+ }
+ }
+ }
+ base= base->next;
+ }
+}
+
+/* update animated objects */
+void update_anim_sumo(void)
+{
+ SM_Vector3 scaling;
+
+ Base *base;
+ Object *ob;
+ Mesh *me;
+
+ base= FIRSTBASE;
+ while(base) {
+ if(G.vd->lay & base->lay) {
+ ob= base->object;
+
+ if(ob->sumohandle) {
+ if((ob->gameflag & OB_DYNAMIC)==0) {
+ /* evt: optimise, check for anim */
+ scaling[0] = ob->size[0];
+ scaling[1] = ob->size[1];
+ scaling[2] = ob->size[2];
+ SM_SetMatrixf(ob->sumohandle, ob->obmat[0]);
+ SM_SetScaling(ob->sumohandle, scaling);
+ }
+ }
+ }
+ base= base->next;
+ }
+
+}
+
+void end_anim_sumo(void)
+{
+ Base *base;
+ Object *ob;
+ Mesh *me;
+
+ base= FIRSTBASE;
+ while(base) {
+ if(G.vd->lay & base->lay) {
+ ob= base->object;
+
+ if(ob->type==OB_MESH) {
+ if(ob->sumohandle) {
+ SM_RemoveObject(G.scene->sumohandle, ob->sumohandle);
+ SM_DeleteObject(ob->sumohandle);
+ ob->sumohandle= NULL;
+ }
+ me= ob->data;
+ if(me->sumohandle) {
+ SM_DeleteShape(me->sumohandle);
+ me->sumohandle= NULL;
+ }
+ }
+ }
+ base= base->next;
+ }
+ if(G.scene->sumohandle) {
+ SM_DeleteScene(G.scene->sumohandle);
+ G.scene->sumohandle= NULL;
+ }
+}
+
+#endif
+
+void inner_play_anim_loop(int init, int mode)
+{
+ ScrArea *sa;
+ static ScrArea *oldsa;
+ static double swaptime;
+ static int curmode;
+
+ /* init */
+ if(init) {
+ oldsa= curarea;
+ swaptime= speed_to_swaptime(G.animspeed);
+ tottime= 0.0;
+ curmode= mode;
+#ifdef NAN_LINEAR_PHYSICS
+ init_anim_sumo();
+#endif
+ return;
+ }
+
+ set_timecursor(CFRA);
+ do_all_ipos();
+ BPY_do_all_scripts(SCRIPT_FRAMECHANGED);
+ do_all_keys();
+ do_all_actions();
+ do_all_ikas();
+
+
+ test_all_displists();
+#ifdef NAN_LINEAR_PHYSICS
+ update_anim_sumo();
+
+ SM_Proceed(G.scene->sumohandle, swaptime, 40, NULL);
+#endif
+ sa= G.curscreen->areabase.first;
+ while(sa) {
+ if(sa==oldsa) {
+ scrarea_do_windraw(sa);
+ }
+ else if(curmode) {
+ if ELEM(sa->spacetype, SPACE_VIEW3D, SPACE_SEQ) {
+ scrarea_do_windraw(sa);
+ }
+ }
+
+ sa= sa->next;
+ }
+
+ /* minimaal swaptime laten voorbijgaan */
+ tottime -= swaptime;
+ while (update_time()) PIL_sleep_ms(1);
+
+ if(CFRA==EFRA) {
+ if (tottime > 0.0) tottime = 0.0;
+ CFRA= SFRA;
+ }
+ else CFRA++;
+
+}
+
+int play_anim(int mode)
+{
+ ScrArea *sa, *oldsa;
+ int cfraont;
+ unsigned short event=0;
+ short val;
+
+ /* patch voor zeer oude scenes */
+ if(SFRA==0) SFRA= 1;
+ if(EFRA==0) EFRA= 250;
+
+ if(SFRA>EFRA) return 0;
+
+ update_time();
+
+ /* waitcursor(1); */
+ G.f |= G_PLAYANIM; /* in sequence.c en view.c wordt dit afgevangen */
+
+ cfraont= CFRA;
+ oldsa= curarea;
+
+ inner_play_anim_loop(1, mode); /* 1==init */
+
+ while(TRUE) {
+
+ inner_play_anim_loop(0, 0);
+
+ screen_swapbuffers();
+
+ while(qtest()) {
+
+ event= extern_qread(&val);
+ if(event==ESCKEY) break;
+ else if(event==MIDDLEMOUSE) {
+ if(U.flag & VIEWMOVE) {
+ if(G.qual & LR_SHIFTKEY) viewmove(0);
+ else if(G.qual & LR_CTRLKEY) viewmove(2);
+ else viewmove(1);
+ }
+ else {
+ if(G.qual & LR_SHIFTKEY) viewmove(1);
+ else if(G.qual & LR_CTRLKEY) viewmove(2);
+ else viewmove(0);
+ }
+ }
+ else if(val) {
+ if(event==PAGEUPKEY) {
+ Group *group= G.main->group.first;
+ while(group) {
+ next_group_key(group);
+ group= group->id.next;
+ }
+ }
+ else if(event==PAGEDOWNKEY) {
+ Group *group= G.main->group.first;
+ while(group) {
+ prev_group_key(group);
+ group= group->id.next;
+ }
+ }
+ }
+ }
+ if(event==ESCKEY || event==SPACEKEY) break;
+
+ if(mode==2 && CFRA==EFRA) break;
+ }
+
+ if(event==SPACEKEY);
+ else CFRA= cfraont;
+
+ do_all_ipos();
+ do_all_keys();
+ do_all_actions();
+ do_all_ikas();
+
+
+ if(oldsa!=curarea) areawinset(oldsa->win);
+
+ /* restore all areas */
+ sa= G.curscreen->areabase.first;
+ while(sa) {
+ if( (mode && sa->spacetype==SPACE_VIEW3D) || sa==curarea) addqueue(sa->win, REDRAW, 1);
+
+ sa= sa->next;
+ }
+
+ /* speed button */
+ allqueue(REDRAWBUTSANIM, 0);
+ /* groups could have changed ipo */
+ allspace(REMAKEIPO, 0);
+ allqueue(REDRAWIPO, 0);
+ allqueue(REDRAWNLA, 0);
+ allqueue (REDRAWACTION, 0);
+ /* vooropig */
+ update_for_newframe();
+#ifdef NAN_LINEAR_PHYSICS
+ end_anim_sumo();
+#endif
+ waitcursor(0);
+ G.f &= ~G_PLAYANIM;
+
+ if (event==ESCKEY || event==SPACEKEY) return 1;
+ else return 0;
+}
diff --git a/source/blender/src/edit.c b/source/blender/src/edit.c
new file mode 100644
index 00000000000..a811f7fd7c3
--- /dev/null
+++ b/source/blender/src/edit.c
@@ -0,0 +1,830 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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>
+#ifndef WIN32
+#include <unistd.h>
+#else
+#include <io.h>
+#include "BLI_winstuff.h"
+#endif
+#include "MEM_guardedalloc.h"
+
+#include "BMF_Api.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_lattice_types.h"
+#include "DNA_meta_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_space_types.h"
+#include "DNA_view3d_types.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_anim.h"
+#include "BKE_object.h"
+#include "BKE_displist.h"
+#include "BKE_global.h"
+#include "BKE_lattice.h"
+#include "BKE_mesh.h"
+
+#include "BIF_gl.h"
+#include "BIF_mywindow.h"
+#include "BIF_screen.h"
+#include "BIF_interface.h"
+#include "BIF_space.h"
+#include "BIF_editview.h"
+#include "BIF_glutil.h"
+
+#include "BSE_view.h"
+#include "BSE_edit.h"
+#include "BSE_trans_types.h"
+#include "BSE_drawipo.h"
+
+#include "BDR_editobject.h"
+
+/* old stuff */
+#include "blendertimer.h"
+#include "blendef.h"
+#include "interface.h"
+#include "mydevice.h"
+/*#include "armature.h"*/
+/* #include "edit.h" */
+#include "nla.h"
+
+#ifdef __NLA
+#include "BIF_editarmature.h"
+#endif
+
+/* editmball.c */
+extern ListBase editelems; /* go away ! */
+
+
+/* from editobject */
+extern void make_trans_verts(float *min, float *max, int mode);
+
+/* circle selection callback */
+typedef void (*select_CBfunc)(short selecting, Object *editobj, short *mval, float rad);
+
+extern void obedit_selectionCB(short selecting, Object *editobj,
+ short *mval, float rad);
+extern void uvedit_selectionCB(short selecting, Object *editobj,
+ short *mval, float rad);
+
+void circle_selectCB(select_CBfunc func);
+
+int get_border(rcti *rect, short col)
+{
+ float dvec[4], fac1, fac2;
+ int retval=1;
+ unsigned short event;
+ short mval[2], mvalo[4], val, x1, y1;
+ char str[64];
+
+ mywinset(G.curscreen->mainwin);
+
+ /* pietsje groter, 1 pixel aan de rand */
+ glReadBuffer(GL_FRONT);
+ glDrawBuffer(GL_FRONT);
+
+ /* removed my_get_frontbuffer, this crashes when it gets a part outside the screen */
+ /* solved it with just a redraw! */
+
+ mywinset(curarea->win);
+
+ glDrawBuffer(GL_FRONT);
+ persp(0);
+ initgrabz(0.0, 0.0, 0.0);
+
+ getmouseco_areawin(mvalo);
+
+ /* draws the selection initial cross */
+ sdrawXORline4(0, 0, mvalo[1], curarea->winx, mvalo[1]);
+ sdrawXORline4(1, mvalo[0], 0, mvalo[0], curarea->winy);
+
+ while(TRUE) {
+
+ /* als een renderwindow open is en de muis gaat erin */
+ persp(1);
+ mywinset(curarea->win);
+ persp(0);
+
+ /* selection loop while mouse pressed */
+ getmouseco_areawin(mval);
+
+ if(mvalo[0]!=mval[0] || mvalo[1]!=mval[1]) {
+
+ /* aiming cross */
+ sdrawXORline4(0, 0, mval[1], curarea->winx, mval[1]);
+ sdrawXORline4(1, mval[0], 0, mval[0], curarea->winy);
+ glFlush();
+
+ mvalo[0]= mval[0];
+ mvalo[1]= mval[1];
+ }
+ event= extern_qread(&val);
+
+ if(event && val) {
+ if(event==ESCKEY) {
+ retval= 0;
+ break;
+ }
+ else if(event==BKEY) {
+ /* b has been pressed twice: proceed with circle select */
+ retval= 0;
+ break;
+ }
+ else if(event==LEFTMOUSE) break;
+ else if(event==MIDDLEMOUSE) break;
+ else if(event==RIGHTMOUSE) break;
+ }
+ } /* end while (TRUE) */
+
+ /* erase XORed lines */
+ sdrawXORline4(-1, 0, 0, 0, 0);
+
+ if(retval) {
+ /* box select */
+ x1= mval[0];
+ y1= mval[1];
+
+ getmouseco_areawin(mvalo);
+
+ sdrawXORline4(0, x1, y1, x1, mvalo[1]);
+ sdrawXORline4(1, x1, mvalo[1], mvalo[0], mvalo[1]);
+ sdrawXORline4(2, mvalo[0], mvalo[1], mvalo[0], y1);
+ sdrawXORline4(3, mvalo[0], y1, x1, y1);
+ glFlush();
+
+ while(TRUE) {
+ getmouseco_areawin(mval);
+ if(mvalo[0]!=mval[0] || mvalo[1]!=mval[1]) {
+
+ sdrawXORline4(0, x1, y1, x1, mval[1]);
+ sdrawXORline4(1, x1, mval[1], mval[0], mval[1]);
+ sdrawXORline4(2, mval[0], mval[1], mval[0], y1);
+ sdrawXORline4(3, mval[0], y1, x1, y1);
+ glFlush();
+
+ mvalo[0]= mval[0];
+ mvalo[1]= mval[1];
+ }
+
+ event= extern_qread(&val);
+
+ /* still because of the renderwindow... */
+ persp(1);
+ mywinset(curarea->win);
+ persp(0);
+
+ if(val==0) {
+ if(event==ESCKEY) {
+ retval= 0;
+ break;
+ }
+ else if(event==LEFTMOUSE) break;
+ else if(event==MIDDLEMOUSE) break;
+ else if(event==RIGHTMOUSE) break;
+ }
+
+ if(curarea->spacetype==SPACE_VIEW3D) {
+ glColor3f(0.4375, 0.4375, 0.4375);
+ glRecti(0, 10, 250, 20);
+ glColor3f(0.0, 0.0, 0.0);
+
+ if(G.vd->persp==0) {
+ window_to_3d(dvec, mvalo[0]-x1, mvalo[1]-y1);
+
+ glRasterPos2i(10, 10);
+ sprintf(str, "X %.4f Y %.4f Z %.4f Dia %.4f", dvec[0], dvec[1], dvec[2], sqrt(dvec[0]*dvec[0]+dvec[1]*dvec[1]+dvec[2]*dvec[2]));
+ BMF_DrawString(G.fonts, str);
+ }
+ else if(G.vd->persp==2) {
+ rcti vb;
+
+ calc_viewborder(G.vd, &vb);
+
+ fac1= (mvalo[0]-x1)/( (float) (vb.xmax-vb.xmin) );
+ fac1*= 0.01*G.scene->r.size*G.scene->r.xsch;
+
+ fac2= (mvalo[1]-y1)/( (float) (vb.ymax-vb.ymin) );
+ fac2*= 0.01*G.scene->r.size*G.scene->r.ysch;
+
+ glRasterPos2i(10, 10);
+ sprintf(str, "X %.1f Y %.1f Dia %.1f", fabs(fac1), fabs(fac2), sqrt(fac1*fac1 + fac2*fac2) );
+ BMF_DrawString(G.fonts, str);
+ }
+ }
+ else if(curarea->spacetype==SPACE_IPO) {
+ SpaceIpo *sipo= curarea->spacedata.first;
+
+ glColor3f(.40625, .40625, .40625);
+ glRecti(20, 30, 170, 40);
+ glColor3f(0.0, 0.0, 0.0);
+
+ mvalo[2]= x1;
+ mvalo[3]= y1;
+ areamouseco_to_ipoco(&sipo->v2d, mval, dvec, dvec+1);
+ areamouseco_to_ipoco(&sipo->v2d, mvalo+2, dvec+2, dvec+3);
+
+ glRasterPos2i(30, 30);
+ sprintf(str, "Time: %.4f Y %.4f", dvec[0]-dvec[2], dvec[1]-dvec[3]);
+ BMF_DrawString(G.fonts, str);
+ }
+ } /* end while (TRUE) */
+ sdrawXORline4(-1, 0, 0, 0, 0);
+
+ if(retval) {
+ rect->xmin= x1;
+ rect->ymin= y1;
+ rect->xmax= mval[0];
+ rect->ymax= mval[1];
+ retval= event;
+
+ /* normaliseren */
+ if(rect->xmin>rect->xmax) SWAP(int, rect->xmin, rect->xmax);
+ if(rect->ymin>rect->ymax) SWAP(int, rect->ymin, rect->ymax);
+
+ if(rect->xmin==rect->xmax) retval= 0;
+ if(rect->ymin==rect->ymax) retval= 0;
+ }
+ }
+
+
+ /* wissen */
+ if(event!=BKEY) {
+ if ELEM(curarea->spacetype, SPACE_VIEW3D, SPACE_IPO) {
+ scrarea_queue_winredraw(curarea);
+ }
+ }
+
+ glFlush();
+ glReadBuffer(GL_BACK);
+ glDrawBuffer(GL_BACK);
+
+ persp(1);
+
+ /* pressed B again ? -> brush select */
+ if(event==BKEY) {
+ switch (curarea->spacetype) {
+ case SPACE_VIEW3D:
+ if (G.obedit)
+ circle_selectCB(&obedit_selectionCB);
+ return 0;
+ case SPACE_IMAGE: // brush select in UV editor
+ circle_selectCB(&uvedit_selectionCB);
+ // this is a hack; we return 0 that the caller from get_border
+ // doesn't execute the selection code for border select..
+ return 0;
+ }
+ }
+ return retval;
+}
+
+void draw_sel_circle(short *mval, short *mvalo, float rad, float rado, int selecting)
+{
+ static short no_mvalo=0;
+
+ if(mval==0 && mvalo==0) { /* signal */
+ no_mvalo= 1;
+ return;
+ }
+
+ persp(0);
+ glDrawBuffer(GL_FRONT);
+
+ /* cirkel tekenen */
+
+ if(mvalo && no_mvalo==0) {
+ sdrawXORcirc(mvalo[0], mvalo[1], rado);
+ }
+
+ if(mval) {
+ sdrawXORcirc(mval[0], mval[1], rad);
+ }
+
+ glFlush();
+ persp(1);
+ glDrawBuffer(GL_BACK);
+
+ no_mvalo= 0;
+}
+
+/** This function does the same as editview.c:circle_select(),
+ * but the selection actions are defined by a callback, making
+ * it (hopefully) reusable for other windows than the 3D view.
+ */
+
+void circle_selectCB(select_CBfunc callback)
+{
+ static float rad= 40.0;
+ float rado;
+ int firsttime=1;
+ unsigned short event;
+ short mvalo[2], mval[2], val;
+ short selecting=0;
+ Object *obj;
+
+ if(G.obedit) obj = G.obedit;
+ else obj = OBACT;
+
+
+ getmouseco_areawin(mvalo);
+ draw_sel_circle(mvalo, 0, rad, 0.0, selecting);
+
+ rado= rad;
+
+ while(TRUE) {
+
+ /* als een renderwindow open is en de muis gaat erin */
+
+ mywinset(curarea->win);
+
+ getmouseco_areawin(mval);
+
+ if(mval[0]!=mvalo[0] || mval[1]!=mvalo[1] || rado!=rad || firsttime) {
+ firsttime= 0;
+
+ draw_sel_circle(mval, mvalo, rad, rado, selecting);
+
+ mvalo[0]= mval[0];
+ mvalo[1]= mval[1];
+ rado= rad;
+
+ if(selecting) {
+ callback(selecting, obj, mval, rad);
+ }
+ }
+ event= extern_qread(&val);
+ if (event) {
+ int afbreek= 0;
+
+ switch(event) {
+ case LEFTMOUSE:
+ case MIDDLEMOUSE:
+ if(val) selecting= event;
+ else selecting= 0;
+ firsttime= 1;
+
+ break;
+ case PADPLUSKEY:
+ if(val) if(rad<200.0) rad*= 1.2;
+ break;
+ case PADMINUS:
+ if(val) if(rad>5.0) rad/= 1.2;
+ break;
+
+ case ESCKEY: case SPACEKEY: case RIGHTMOUSE:
+ case GKEY: case SKEY: case RKEY: case XKEY: case EKEY: case TABKEY:
+ afbreek= 1;
+ break;
+
+ }
+
+ if(afbreek) break;
+ }
+ }
+
+ /* cirkel wissen */
+ draw_sel_circle(0, mvalo, 0, rad, 1);
+
+ countall();
+ allqueue(REDRAWINFO, 0);
+}
+
+void count_object(Object *ob, int sel)
+{
+ Mesh *me;
+ Curve *cu;
+ int tot=0, totf=0;
+
+ switch(ob->type) {
+ case OB_MESH:
+ G.totmesh++;
+ me= get_mesh(ob);
+ if(me) {
+ G.totvert+= me->totvert;
+ G.totface+= me->totface;
+ if(sel) {
+ G.totvertsel+= me->totvert;
+ G.totfacesel+= me->totface;
+ }
+ }
+ break;
+
+ case OB_LAMP:
+ G.totlamp++;
+ break;
+ case OB_SURF:
+ case OB_CURVE:
+ case OB_FONT:
+ G.totcurve++;
+ tot=totf= 0;
+ cu= ob->data;
+ if(cu->disp.first==0) makeDispList(ob);
+ count_displist( &cu->disp, &tot, &totf);
+ G.totvert+= tot;
+ G.totface+= totf;
+ if(sel) {
+ G.totvertsel+= tot;
+ G.totfacesel+= totf;
+ }
+ break;
+ case OB_MBALL:
+ count_displist( &ob->disp, &tot, &totf);
+ G.totvert+= tot;
+ G.totface+= totf;
+ if(sel) {
+ G.totvertsel+= tot;
+ G.totfacesel+= totf;
+ }
+
+ break;
+ }
+
+}
+
+void countall()
+{
+/* extern Lattice *editLatt; in BKE_lattice.h*/
+ extern ListBase editNurb;
+ /* extern ListBase bpbase; */
+ Base *base;
+ Object *ob;
+ Mesh *me;
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ MetaElem *ml;
+ /* struct BodyPoint *bop; */
+ struct EditVert *eve;
+ struct EditVlak *evl;
+#ifdef __NLA
+ struct EditBone *ebo;
+#endif
+ int a;
+
+ G.totvert= G.totvertsel= G.totfacesel= G.totface= G.totobj=
+ G.totmesh= G.totlamp= G.totcurve= G.totobjsel= 0;
+
+ if(G.obedit) {
+
+ if(G.obedit->type==OB_MESH) {
+ eve= G.edve.first;
+ while(eve) {
+ G.totvert++;
+ if(eve->f & 1) G.totvertsel++;
+ eve= eve->next;
+ }
+ evl= G.edvl.first;
+ while(evl) {
+ G.totface++;
+ if(evl->v1->f & 1) {
+ if(evl->v2->f & 1) {
+ if(evl->v3->f & 1) {
+ if(evl->v4) {
+ if(evl->v4->f & 1) G.totfacesel++;
+ }
+ else {
+ G.totfacesel++;
+ }
+ }
+ }
+ }
+ evl= evl->next;
+ }
+ }
+#ifdef __NLA
+ else if (G.obedit->type==OB_ARMATURE){
+ for (ebo=G.edbo.first;ebo;ebo=ebo->next){
+
+ /* Synch selection to parent for ik children */
+ if ((ebo->flag & BONE_IK_TOPARENT) && ebo->parent){
+ G.totvert--;
+ if (ebo->parent->flag & BONE_TIPSEL)
+ ebo->flag |= BONE_ROOTSEL;
+ else
+ ebo->flag &= ~BONE_ROOTSEL;
+ }
+
+ if (ebo->flag & BONE_TIPSEL)
+ G.totvertsel++;
+ if (ebo->flag & BONE_ROOTSEL)
+ G.totvertsel++;
+
+ if ((ebo->flag & BONE_TIPSEL) && (ebo->flag & BONE_ROOTSEL))
+ ebo->flag |= BONE_SELECTED;
+ else
+ ebo->flag &= ~BONE_SELECTED;
+
+ // If this is an IK child and it's parent is being moved, remove our root
+ if ((ebo->flag & BONE_IK_TOPARENT)&& (ebo->flag & BONE_ROOTSEL) && ebo->parent && (ebo->parent->flag & BONE_TIPSEL)){
+ G.totvertsel--;
+ }
+
+ G.totvert+=2;
+ G.totface++;
+
+
+ }
+ }
+#endif
+ else if ELEM3(G.obedit->type, OB_CURVE, OB_SURF, OB_FONT) {
+ nu= editNurb.first;
+ while(nu) {
+ if((nu->type & 7)==CU_BEZIER) {
+ bezt= nu->bezt;
+ a= nu->pntsu;
+ while(a--) {
+ G.totvert+=3;
+ if(bezt->f1) G.totvertsel++;
+ if(bezt->f2) G.totvertsel++;
+ if(bezt->f3) G.totvertsel++;
+ bezt++;
+ }
+ }
+ else {
+ bp= nu->bp;
+ a= nu->pntsu*nu->pntsv;
+ while(a--) {
+ G.totvert++;
+ if(bp->f1 & 1) G.totvertsel++;
+ bp++;
+ }
+ }
+ nu= nu->next;
+ }
+ }
+ else if(G.obedit->type==OB_MBALL) {
+ ml= editelems.first;
+ while(ml) {
+ G.totvert++;
+ if(ml->flag & SELECT) G.totvertsel++;
+ ml= ml->next;
+ }
+ }
+ else if(G.obedit->type==OB_LATTICE) {
+ bp= editLatt->def;
+
+ a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
+ while(a--) {
+ G.totvert++;
+ if(bp->f1 & 1) G.totvertsel++;
+ bp++;
+ }
+ }
+
+ allqueue(REDRAWINFO, 1); /* 1, want header->win==0! */
+ return;
+ }
+ else if(G.f & (G_FACESELECT + G_VERTEXPAINT + G_TEXTUREPAINT +G_WEIGHTPAINT)) {
+ me= get_mesh((G.scene->basact) ? (G.scene->basact->object) : 0);
+ if(me) {
+ G.totface= me->totface;
+ G.totvert= me->totvert;
+ }
+ allqueue(REDRAWINFO, 1); /* 1, want header->win==0! */
+ return;
+ }
+
+ if(G.vd==0) return;
+ if(G.scene==0) return;
+
+ base= (G.scene->base.first);
+ while(base) {
+ if(G.vd->lay & base->lay) {
+
+ G.totobj++;
+ if(base->flag & SELECT) G.totobjsel++;
+
+ count_object(base->object, base->flag & SELECT);
+
+ if(base->object->transflag & OB_DUPLI) {
+ extern ListBase duplilist;
+
+ make_duplilist(G.scene, base->object);
+ ob= duplilist.first;
+ while(ob) {
+ G.totobj++;
+ count_object(ob, base->flag & SELECT);
+ ob= ob->id.next;
+ }
+ free_duplilist();
+ }
+ }
+ base= base->next;
+ }
+ allqueue(REDRAWINFO, 1); /* 1, want header->win==0! */
+}
+
+void snapmenu()
+{
+ extern TransVert *transvmain;
+ extern int tottrans;
+ extern float originmat[3][3]; /* object.c */
+ TransVert *tv;
+ Base *base;
+ Object *ob;
+ float gridf, *curs, imat[3][3], bmat[3][3], vec[3], min[3], max[3], centroid[3];
+ int count, a;
+ short event;
+
+ event= pupmenu("SNAP %t|Sel -> Grid%x1|Sel -> Curs%x2|Curs-> Grid%x3|Curs-> Sel%x4");
+
+ gridf= G.vd->grid;
+ curs= give_cursor();
+
+ if(event== 1 || event==2) { /* sel->grid sel->curs */
+
+ if(G.obedit) {
+#ifdef __NLA
+ if ELEM5(G.obedit->type, OB_ARMATURE, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE) make_trans_verts(bmat[0], bmat[1], 0);
+#else
+ if ELEM4(G.obedit->type, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE) make_trans_verts(bmat[0], bmat[1], 0);
+#endif
+ if(tottrans==0) return;
+
+ Mat3CpyMat4(bmat, G.obedit->obmat);
+ Mat3Inv(imat, bmat);
+
+ tv= transvmain;
+ for(a=0; a<tottrans; a++, tv++) {
+
+ if(event==2) {
+
+ vec[0]= curs[0]-G.obedit->obmat[3][0];
+ vec[1]= curs[1]-G.obedit->obmat[3][1];
+ vec[2]= curs[2]-G.obedit->obmat[3][2];
+ }
+ else {
+ VECCOPY(vec, tv->loc);
+ Mat3MulVecfl(bmat, vec);
+ VecAddf(vec, vec, G.obedit->obmat[3]);
+ vec[0]= G.vd->grid*floor(.5+ vec[0]/gridf);
+ vec[1]= G.vd->grid*floor(.5+ vec[1]/gridf);
+ vec[2]= G.vd->grid*floor(.5+ vec[2]/gridf);
+ VecSubf(vec, vec, G.obedit->obmat[3]);
+ }
+ Mat3MulVecfl(imat, vec);
+ VECCOPY(tv->loc, vec);
+
+ }
+ MEM_freeN(transvmain);
+ transvmain= 0;
+
+ if ELEM(G.obedit->type, OB_SURF, OB_CURVE) makeDispList(G.obedit);
+
+ if (G.obedit->type == OB_ARMATURE)
+ special_trans_update(0);
+
+ allqueue(REDRAWVIEW3D, 0);
+ return;
+ }
+#ifdef __NLA
+ if (G.obpose){
+ allqueue(REDRAWVIEW3D, 0);
+ return;
+ }
+#endif
+ base= (G.scene->base.first);
+ while(base) {
+ if( ( ((base)->flag & SELECT) && ((base)->lay & G.vd->lay) && ((base)->object->id.lib==0))) {
+ ob= base->object;
+
+ if(event==2) {
+ vec[0]= -ob->obmat[3][0] + curs[0];
+ vec[1]= -ob->obmat[3][1] + curs[1];
+ vec[2]= -ob->obmat[3][2] + curs[2];
+ }
+ else {
+ vec[0]= -ob->obmat[3][0]+G.vd->grid*floor(.5+ ob->obmat[3][0]/gridf);
+ vec[1]= -ob->obmat[3][1]+G.vd->grid*floor(.5+ ob->obmat[3][1]/gridf);
+ vec[2]= -ob->obmat[3][2]+G.vd->grid*floor(.5+ ob->obmat[3][2]/gridf);
+ }
+ if(ob->parent) {
+ where_is_object(ob);
+
+ Mat3Inv(imat, originmat);
+ Mat3MulVecfl(imat, vec);
+ ob->loc[0]+= vec[0];
+ ob->loc[1]+= vec[1];
+ ob->loc[2]+= vec[2];
+ }
+ else {
+ ob->loc[0]+= vec[0];
+ ob->loc[1]+= vec[1];
+ ob->loc[2]+= vec[2];
+ }
+ }
+
+ base= base->next;
+ }
+ allqueue(REDRAWVIEW3D, 0);
+ }
+ else if(event==3) { /* curs to grid */
+ curs[0]= G.vd->grid*floor(.5+curs[0]/gridf);
+ curs[1]= G.vd->grid*floor(.5+curs[1]/gridf);
+ curs[2]= G.vd->grid*floor(.5+curs[2]/gridf);
+
+ allqueue(REDRAWVIEW3D, 0);
+ }
+ else if(event==4) { /* curs to sel */
+ count= 0;
+ INIT_MINMAX(min, max);
+ centroid[0]= centroid[1]= centroid[2]= 0.0;
+
+ if(G.obedit) {
+ tottrans=0;
+#ifdef __NLA
+ if ELEM5(G.obedit->type, OB_ARMATURE, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE) make_trans_verts(bmat[0], bmat[1], 0);
+#else
+ if ELEM4(G.obedit->type, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE) make_trans_verts(bmat[0], bmat[1], 0);
+#endif
+ if(tottrans==0) return;
+
+ Mat3CpyMat4(bmat, G.obedit->obmat);
+
+ tv= transvmain;
+ for(a=0; a<tottrans; a++, tv++) {
+ VECCOPY(vec, tv->loc);
+ Mat3MulVecfl(bmat, vec);
+ VecAddf(vec, vec, G.obedit->obmat[3]);
+ VecAddf(centroid, centroid, vec);
+ DO_MINMAX(vec, min, max);
+ }
+
+ if(G.vd->around==V3D_CENTROID) {
+ VecMulf(centroid, 1.0/(float)tottrans);
+ VECCOPY(curs, centroid);
+ }
+ else {
+ curs[0]= (min[0]+max[0])/2;
+ curs[1]= (min[1]+max[1])/2;
+ curs[2]= (min[2]+max[2])/2;
+ }
+ MEM_freeN(transvmain);
+ transvmain= 0;
+ }
+ else {
+ base= (G.scene->base.first);
+ while(base) {
+ if(((base)->flag & SELECT) && ((base)->lay & G.vd->lay) ) {
+ VECCOPY(vec, base->object->obmat[3]);
+ VecAddf(centroid, centroid, vec);
+ DO_MINMAX(vec, min, max);
+ count++;
+ }
+ base= base->next;
+ }
+ if(count) {
+ if(G.vd->around==V3D_CENTROID) {
+ VecMulf(centroid, 1.0/(float)count);
+ VECCOPY(curs, centroid);
+ }
+ else {
+ curs[0]= (min[0]+max[0])/2;
+ curs[1]= (min[1]+max[1])/2;
+ curs[2]= (min[2]+max[2])/2;
+ }
+ }
+ }
+
+ allqueue(REDRAWVIEW3D, 0);
+ }
+}
diff --git a/source/blender/src/editaction.c b/source/blender/src/editaction.c
new file mode 100644
index 00000000000..f927bcf5264
--- /dev/null
+++ b/source/blender/src/editaction.c
@@ -0,0 +1,1414 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 <string.h>
+#include <math.h>
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "PIL_time.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "DNA_action_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_ipo_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_constraint_types.h"
+
+#include "BKE_armature.h"
+#include "BKE_constraint.h"
+#include "BKE_displist.h"
+#include "BKE_curve.h"
+#include "BKE_ipo.h"
+#include "BKE_global.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+#include "BKE_action.h"
+
+#include "BIF_gl.h"
+#include "BIF_mywindow.h"
+#include "BIF_toolbox.h"
+#include "BIF_screen.h"
+#include "BIF_space.h"
+#include "BIF_buttons.h"
+#include "BIF_interface.h"
+#include "BIF_editview.h"
+#include "BIF_poseobject.h"
+#include "BIF_editarmature.h"
+
+#include "BSE_edit.h"
+#include "BSE_drawipo.h"
+#include "BSE_headerbuttons.h"
+#include "BSE_editipo.h"
+#include "BSE_editaction.h"
+#include "BSE_trans_types.h"
+#include "BSE_editaction_types.h"
+
+#include "BDR_editobject.h"
+
+#include "blendertimer.h"
+
+#include "interface.h"
+#include "mydevice.h"
+#include "blendef.h"
+#include "nla.h"
+
+static bPose *g_posebuf=NULL;
+extern int count_action_levels (bAction *act);
+
+#define BEZSELECTED(bezt) (((bezt)->f1 & 1) || ((bezt)->f2 & 1) || ((bezt)->f3 & 1))
+
+/* Local Function prototypes */
+
+static void insertactionkey(bAction *act, bActionChannel *achan, bPoseChannel *chan, int adrcode, short makecurve, float time);
+static void flip_name (char *name);
+static void mouse_actionchannels(bAction *act, short *mval);
+static void borderselect_action(void);
+static void mouse_action(void);
+static bActionChannel *get_nearest_actionchannel_key (float *index, short *sel, bConstraintChannel **conchan);
+static void delete_actionchannels(void);
+static void delete_actionchannel_keys(void);
+static void duplicate_actionchannel_keys(void);
+static void transform_actionchannel_keys(char mode);
+static void select_poseelement_by_name (char *name, int select);
+static void hilight_channel (bAction *act, bActionChannel *chan, short hilight);
+static void set_action_key_time (bAction *act, bPoseChannel *chan, int adrcode, short makecurve, float time);
+
+/* Implementation */
+
+static void select_poseelement_by_name (char *name, int select)
+{
+ /* Synchs selection of channels with selection of object elements in posemode */
+
+ Object *ob;
+
+ ob = G.obpose;
+ if (!ob)
+ return;
+
+ switch (ob->type){
+ case OB_ARMATURE:
+ select_bone_by_name ((bArmature*)ob->data, name, select);
+ break;
+ default:
+ break;
+ }
+}
+#ifdef __NLA_BAKE
+bAction* bake_action_with_client (bAction *act, Object *armob, float tolerance)
+{
+ bAction *result=NULL;
+ bActionChannel *achan;
+ float actlen;
+ int curframe;
+ char newname[64];
+ bArmature *arm;
+ Bone *bone;
+ float oldframe;
+ bAction *temp;
+ bPoseChannel *pchan;
+
+ if (!act)
+ return NULL;
+
+ arm = get_armature(armob);
+
+
+ if (G.obedit){
+ error ("Not in editmode");
+ return NULL;
+ }
+
+ if (!arm){
+ error ("Must have an armature selected");
+ return NULL;
+ }
+ /* Get a new action */
+ result = add_empty_action();
+
+ /* Assign the new action a unique name */
+ sprintf (newname, "%s.BAKED", act->id.name+2);
+ rename_id(&result->id, newname);
+
+ actlen = calc_action_end(act);
+
+ oldframe = G.scene->r.cfra;
+
+ temp = armob->action;
+ armob->action = act;
+
+ for (curframe=1; curframe<ceil(actlen+1); curframe++){
+
+ /* Apply the old action */
+
+ G.scene->r.cfra = curframe;
+
+ /* Apply the object ipo */
+ get_pose_from_action(&armob->pose, act, curframe);
+ apply_pose_armature(arm, armob->pose, 1);
+ clear_object_constraint_status(armob);
+ where_is_armature_time(armob, curframe);
+
+ /* For each channel: set avail keys with current values */
+ for (pchan=armob->pose->chanbase.first; pchan; pchan=pchan->next){
+
+ /* Copy the constraints from the armature (if any) */
+
+ bone = get_named_bone(arm, pchan->name);
+ if (bone){
+
+ Mat4ToQuat(pchan->obmat, pchan->quat);
+ Mat4ToSize(pchan->obmat, pchan->size);
+ VECCOPY(pchan->loc, pchan->obmat[3]);
+
+ /* Apply to keys */
+ set_action_key_time (result, pchan, AC_QUAT_X, 1, curframe);
+ set_action_key_time (result, pchan, AC_QUAT_Y, 1, curframe);
+ set_action_key_time (result, pchan, AC_QUAT_Z, 1, curframe);
+ set_action_key_time (result, pchan, AC_QUAT_W, 1, curframe);
+ set_action_key_time (result, pchan, AC_LOC_X, 1, curframe);
+ set_action_key_time (result, pchan, AC_LOC_Y, 1, curframe);
+ set_action_key_time (result, pchan, AC_LOC_Z, 1, curframe);
+ }
+ }
+ }
+
+ /* Make another pass to ensure all keyframes are set to linear interpolation mode */
+ for (achan = result->chanbase.first; achan; achan=achan->next){
+ IpoCurve* icu;
+ for (icu = achan->ipo->curve.first; icu; icu=icu->next){
+ icu->ipo= IPO_LIN;
+ }
+ }
+
+ notice ("Made new action \"%s\"", newname);
+ G.scene->r.cfra = oldframe;
+ armob->action = temp;
+ return result;
+}
+#endif
+
+void select_actionchannel_by_name (bAction *act, char *name, int select)
+{
+ bActionChannel *chan;
+
+ if (!act)
+ return;
+
+ for (chan = act->chanbase.first; chan; chan=chan->next){
+ if (!strcmp (chan->name, name)){
+ act->achan = chan;
+ if (select){
+ chan->flag |= ACHAN_SELECTED;
+ hilight_channel (act, chan, 1);
+ }
+ else{
+ chan->flag &= ~ACHAN_SELECTED;
+ hilight_channel (act, chan, 0);
+ }
+ return;
+ }
+ }
+}
+
+void remake_action_ipos(bAction *act)
+{
+ bActionChannel *chan;
+ bConstraintChannel *conchan;
+ IpoCurve *icu;
+
+ for (chan= act->chanbase.first; chan; chan=chan->next){
+ if (chan->ipo){
+ for (icu = chan->ipo->curve.first; icu; icu=icu->next){
+ sort_time_ipocurve(icu);
+ testhandles_ipocurve(icu);
+ }
+ }
+ for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next){
+ if (conchan->ipo){
+ for (icu = conchan->ipo->curve.first; icu; icu=icu->next){
+ sort_time_ipocurve(icu);
+ testhandles_ipocurve(icu);
+ }
+ }
+ }
+ }
+}
+
+static void duplicate_actionchannel_keys(void)
+{
+ bAction *act;
+ bActionChannel *chan;
+ bConstraintChannel *conchan;
+
+ act=G.saction->action;
+ if (!act)
+ return;
+
+ /* Find selected items */
+ for (chan = act->chanbase.first; chan; chan=chan->next){
+ duplicate_ipo_keys(chan->ipo);
+ for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next)
+ duplicate_ipo_keys(conchan->ipo);
+ }
+
+ transform_actionchannel_keys ('g');
+}
+
+static bActionChannel *get_nearest_actionchannel_key (float *index, short *sel, bConstraintChannel **rchan){
+ bAction *act;
+ bActionChannel *chan;
+ IpoCurve *icu;
+ bActionChannel *firstchan=NULL;
+ bConstraintChannel *conchan, *firstconchan=NULL;
+ int foundsel=0;
+ float firstvert=-1, foundx=-1;
+ int i;
+ short mval[2];
+ float ymin, ymax;
+ rctf rectf;
+ *index=0;
+
+ *rchan=NULL;
+ act=G.saction->action; /* We presume that we are only called during a valid action */
+
+ getmouseco_areawin (mval);
+
+ mval[0]-=7;
+ areamouseco_to_ipoco(G.v2d, mval, &rectf.xmin, &rectf.ymin);
+
+ mval[0]+=14;
+ areamouseco_to_ipoco(G.v2d, mval, &rectf.xmax, &rectf.ymax);
+
+ ymax = count_action_levels (act) * (CHANNELHEIGHT + CHANNELSKIP);
+
+ *sel=0;
+
+ for (chan=act->chanbase.first; chan; chan=chan->next){
+
+ /* Check action channel */
+ ymin=ymax-(CHANNELHEIGHT+CHANNELSKIP);
+ if (!((ymax < rectf.ymin) || (ymin > rectf.ymax))){
+ for (icu=chan->ipo->curve.first; icu; icu=icu->next){
+ for (i=0; i<icu->totvert; i++){
+ if (icu->bezt[i].vec[1][0] > rectf.xmin && icu->bezt[i].vec[1][0] <= rectf.xmax ){
+ if (!firstchan){
+ firstchan=chan;
+ firstvert=icu->bezt[i].vec[1][0];
+ *sel = icu->bezt[i].f2 & 1;
+ }
+
+ if (icu->bezt[i].f2 & 1){
+ if (!foundsel){
+ foundsel=1;
+ foundx = icu->bezt[i].vec[1][0];
+ }
+ }
+ else if (foundsel && icu->bezt[i].vec[1][0] != foundx){
+ *index=icu->bezt[i].vec[1][0];
+ *sel = 0;
+ return chan;
+ }
+ }
+ }
+ }
+ }
+ ymax=ymin;
+
+ /* Check constraint channels */
+ for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next){
+ ymin=ymax-(CHANNELHEIGHT+CHANNELSKIP);
+ if (!((ymax < rectf.ymin) || (ymin > rectf.ymax))){
+ for (icu=conchan->ipo->curve.first; icu; icu=icu->next){
+ for (i=0; i<icu->totvert; i++){
+ if (icu->bezt[i].vec[1][0] > rectf.xmin && icu->bezt[i].vec[1][0] <= rectf.xmax ){
+ if (!firstchan){
+ firstchan=chan;
+ firstconchan=conchan;
+ firstvert=icu->bezt[i].vec[1][0];
+ *sel = icu->bezt[i].f2 & 1;
+ }
+
+ if (icu->bezt[i].f2 & 1){
+ if (!foundsel){
+ foundsel=1;
+ foundx = icu->bezt[i].vec[1][0];
+ }
+ }
+ else if (foundsel && icu->bezt[i].vec[1][0] != foundx){
+ *index=icu->bezt[i].vec[1][0];
+ *sel = 0;
+ *rchan = conchan;
+ return chan;
+ }
+ }
+ }
+ }
+ }
+ ymax=ymin;
+ }
+ }
+
+ *rchan = firstconchan;
+ *index=firstvert;
+ return firstchan;
+}
+
+static void mouse_action(void)
+{
+ bAction *act;
+ short sel;
+ float selx;
+ bActionChannel *chan;
+ bConstraintChannel *conchan;
+ short mval[2];
+
+ act=G.saction->action;
+ if (!act)
+ return;
+
+ getmouseco_areawin (mval);
+
+ chan=get_nearest_actionchannel_key(&selx, &sel, &conchan);
+
+ if (chan){
+ if (!(G.qual & LR_SHIFTKEY)){
+ deselect_actionchannel_keys(act, 0);
+ deselect_actionchannels(act, 0);
+ act->achan = chan;
+ chan->flag |= ACHAN_SELECTED;
+ hilight_channel (act, chan, 1);
+ sel = 0;
+ }
+
+ if (conchan)
+ select_ipo_key(conchan->ipo, selx, sel);
+ else
+ select_ipo_key(chan->ipo, selx, sel);
+
+ allqueue(REDRAWIPO, 0);
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWACTION, 0);
+ allqueue(REDRAWNLA, 0);
+
+ }
+}
+
+static void borderselect_action(void)
+{
+ rcti rect;
+ rctf rectf;
+ int val;
+ short mval[2];
+ bActionChannel *chan;
+ bConstraintChannel *conchan;
+ bAction *act;
+ float ymin, ymax;
+
+ act=G.saction->action;
+ val= get_border (&rect, 3);
+
+ if (!act)
+ return;
+
+ if (val){
+ mval[0]= rect.xmin;
+ mval[1]= rect.ymin+2;
+ areamouseco_to_ipoco(G.v2d, mval, &rectf.xmin, &rectf.ymin);
+ mval[0]= rect.xmax;
+ mval[1]= rect.ymax-2;
+ areamouseco_to_ipoco(G.v2d, mval, &rectf.xmax, &rectf.ymax);
+
+ ymax=count_action_levels(act) * (CHANNELHEIGHT+CHANNELSKIP);
+ for (chan=act->chanbase.first; chan; chan=chan->next){
+
+ /* Check action */
+ ymin=ymax-(CHANNELHEIGHT+CHANNELSKIP);
+ if (!((ymax < rectf.ymin) || (ymin > rectf.ymax)))
+ borderselect_ipo_key(chan->ipo, rectf.xmin, rectf.xmax, val);
+
+ ymax=ymin;
+
+ /* Check constraints */
+ for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next){
+ ymin=ymax-(CHANNELHEIGHT+CHANNELSKIP);
+ if (!((ymax < rectf.ymin) || (ymin > rectf.ymax)))
+ borderselect_ipo_key(conchan->ipo, rectf.xmin, rectf.xmax, val);
+
+ ymax=ymin;
+ }
+ }
+ allqueue(REDRAWNLA, 0);
+ allqueue(REDRAWACTION, 0);
+ allqueue(REDRAWIPO, 0);
+ }
+}
+
+bActionChannel* get_hilighted_action_channel(bAction* action)
+{
+ bActionChannel *chan;
+
+ if (!action)
+ return NULL;
+
+ for (chan=action->chanbase.first; chan; chan=chan->next){
+ if (chan->flag & ACHAN_SELECTED && chan->flag & ACHAN_HILIGHTED)
+ return chan;
+ }
+
+ return NULL;
+
+}
+
+void set_exprap_action(int mode)
+{
+ if(G.saction->action && G.saction->action->id.lib) return;
+
+ error ("Not yet implemented!");
+}
+
+void free_posebuf(void)
+{
+ if (g_posebuf){
+ clear_pose(g_posebuf);
+ MEM_freeN (g_posebuf);
+ }
+ g_posebuf=NULL;
+}
+
+void copy_posebuf (void)
+{
+ Object *ob;
+
+ free_posebuf();
+
+ ob=G.obpose;
+ if (!ob){
+ error ("Copybuf is empty");
+ return;
+ }
+
+ filter_pose_keys();
+ copy_pose(&g_posebuf, ob->pose, 0);
+
+}
+
+static void flip_name (char *name)
+{
+
+ char prefix[128]={""}; /* The part before the facing */
+ char suffix[128]={""}; /* The part after the facing */
+ char replace[128]={""}; /* The replacement string */
+
+ char *index=NULL;
+ /* Find the last period */
+
+ strcpy (prefix, name);
+
+ /* Check for an instance of .Right */
+ if (!index){
+ index = strstr (prefix, "Right");
+ if (index){
+ *index=0;
+ strcpy (replace, "Left");
+ strcpy (suffix, index+6);
+ }
+ }
+
+ /* Che ck for an instance of .RIGHT */
+ if (!index){
+ index = strstr (prefix, "RIGHT");
+ if (index){
+ *index=0;
+ strcpy (replace, "LEFT");
+ strcpy (suffix, index+6);
+ }
+ }
+
+
+ /* Check for an instance of .right */
+ if (!index){
+ index = strstr (prefix, "right");
+ if (index){
+ *index=0;
+ strcpy (replace, "left");
+ strcpy (suffix, index+6);
+ }
+ }
+
+ /* Check for an instance of .left */
+ if (!index){
+ index = strstr (prefix, "left");
+ if (index){
+ *index=0;
+ strcpy (replace, "right");
+ strcpy (suffix, index+5);
+ }
+ }
+
+ /* Check for an instance of .LEFT */
+ if (!index){
+ index = strstr (prefix, "LEFT");
+ if (index){
+ *index=0;
+ strcpy (replace, "RIGHT");
+ strcpy (suffix, index+5);
+ }
+ }
+
+ /* Check for an instance of .Left */
+ if (!index){
+ index = strstr (prefix, "Left");
+ if (index){
+ *index=0;
+ strcpy (replace, "Right");
+ strcpy (suffix, index+5);
+ }
+ }
+
+ /* check for an instance of .L */
+ if (!index){
+ index = strstr (prefix, ".L");
+ if (index){
+ *index=0;
+ strcpy (replace, ".R");
+ strcpy (suffix, index+2);
+ }
+ }
+
+ /* check for an instance of .l */
+ if (!index){
+ index = strstr (prefix, ".l");
+ if (index){
+ *index=0;
+ strcpy (replace, ".r");
+ strcpy (suffix, index+2);
+ }
+ }
+
+ /* Checl for an instance of .R */
+ if (!index){
+ index = strstr (prefix, ".R");
+ if (index){
+ *index=0;
+ strcpy (replace, ".L");
+ strcpy (suffix, index+2);
+ }
+ }
+
+ /* Checl for an instance of .r */
+ if (!index){
+ index = strstr (prefix, ".r");
+ if (index){
+ *index=0;
+ strcpy (replace, ".l");
+ strcpy (suffix, index+2);
+ }
+ }
+
+ sprintf (name, "%s%s%s", prefix, replace, suffix);
+}
+
+void paste_posebuf (int flip){
+ Object *ob;
+ bPoseChannel *temp, *chan;
+ float eul[4];
+ Base *base;
+ int newchan = 0;
+
+ ob=G.obpose;
+ if (!ob)
+ return;
+
+ if (!g_posebuf){
+ error ("Copybuf is empty");
+ return;
+ };
+
+ collect_pose_garbage(ob);
+
+ /* Safely merge all of the channels in this pose into
+ any existing pose */
+ if (ob->pose){
+ if (U.flag & 0x01<<14){
+ /* Display "Avail, all" dialog */
+ }
+ for (chan=g_posebuf->chanbase.first; chan; chan=chan->next){
+ if (chan->flag & POSE_KEY){
+ temp = copy_pose_channel (chan);
+ if (flip){
+ flip_name (temp->name);
+ temp->loc[0]*=-1;
+
+ QuatToEul(temp->quat, eul);
+ eul[1]*=-1;
+ eul[2]*=-1;
+ EulToQuat(eul, temp->quat);
+ }
+
+ temp = set_pose_channel (ob->pose, temp);
+
+ if (U.flag & 0x01<<14){
+ /* Set keys on pose */
+ if (chan->flag & POSE_ROT){
+ set_action_key(ob->action, temp, AC_QUAT_X, newchan);
+ set_action_key(ob->action, temp, AC_QUAT_Y, newchan);
+ set_action_key(ob->action, temp, AC_QUAT_Z, newchan);
+ set_action_key(ob->action, temp, AC_QUAT_W, newchan);
+ };
+ if (chan->flag & POSE_SIZE){
+ set_action_key(ob->action, temp, AC_SIZE_X, newchan);
+ set_action_key(ob->action, temp, AC_SIZE_Y, newchan);
+ set_action_key(ob->action, temp, AC_SIZE_Z, newchan);
+ };
+ if (chan->flag & POSE_LOC){
+ set_action_key(ob->action, temp, AC_LOC_X, newchan);
+ set_action_key(ob->action, temp, AC_LOC_Y, newchan);
+ set_action_key(ob->action, temp, AC_LOC_Z, newchan);
+ };
+ }
+ }
+ }
+
+ if (U.flag & 0x01<<14){
+ remake_action_ipos(ob->action);
+ allqueue (REDRAWIPO, 0);
+ allqueue (REDRAWVIEW3D, 0);
+ allqueue (REDRAWACTION, 0);
+ allqueue(REDRAWNLA, 0);
+ }
+
+ /* Update deformation children */
+ if (G.obpose->type == OB_ARMATURE){
+ for (base= FIRSTBASE; base; base= base->next){
+ if (G.obpose==base->object->parent){
+ if (base->object->partype==PARSKEL)
+ makeDispList(base->object);
+ }
+ }
+ }
+ }
+}
+
+void set_action_key (struct bAction *act, struct bPoseChannel *chan, int adrcode, short makecurve)
+{
+ set_action_key_time (act, chan, adrcode, makecurve, frame_to_float(CFRA));
+}
+
+static void set_action_key_time (bAction *act, bPoseChannel *chan, int adrcode, short makecurve, float time)
+{
+ bActionChannel *achan;
+ char ipstr[256];
+
+ if (!act)
+ return;
+
+ if (!chan)
+ return;
+ /* See if this action channel exists already */
+ for (achan=act->chanbase.first; achan; achan=achan->next){
+ if (!strcmp (chan->name, achan->name))
+ break;
+ }
+
+ if (!achan){
+ if (!makecurve)
+ return;
+ achan = MEM_callocN (sizeof(bActionChannel), "actionChannel");
+ strcpy (achan->name, chan->name);
+ BLI_addtail (&act->chanbase, achan);
+ }
+
+ /* Ensure the channel appears selected in the action window */
+ achan->flag |= ACHAN_SELECTED;
+
+ /* Ensure this action channel has a valid Ipo */
+ if (!achan->ipo){
+ sprintf (ipstr, "%s.%s", act->id.name+2, chan->name);
+ ipstr[23]=0;
+ achan->ipo= add_ipo(ipstr, ID_AC);
+ }
+
+ insertactionkey(act, achan, chan, adrcode, makecurve, time);
+
+}
+
+static void insertactionkey(bAction *act, bActionChannel *achan, bPoseChannel *chan, int adrcode, short makecurve, float cfra)
+{
+ IpoCurve *icu;
+ void *poin;
+ float curval;
+ int type;
+ ID *id;
+
+ if (!act){
+ return;
+ }
+ if (act->id.lib){
+ error ("Can't pose libactions");
+ return;
+ }
+ act->achan=achan;
+ act->pchan=chan;
+
+ id=(ID*) act;
+
+ /* First see if this curve exists */
+ if (!makecurve){
+ if (!achan->ipo)
+ return;
+
+ for (icu = achan->ipo->curve.first; icu; icu=icu->next){
+ if (icu->adrcode == adrcode)
+ break;
+ }
+ if (!icu)
+ return;
+ }
+
+
+ icu = get_ipocurve (id, GS(id->name), adrcode, achan->ipo);
+
+ if(icu) {
+ poin= get_ipo_poin(id, icu, &type);
+ if(poin) {
+ curval= read_ipo_poin(poin, type);
+ // cfra= frame_to_float(CFRA);
+ insert_vert_ipo(icu, cfra, curval);
+ }
+ }
+
+}
+
+bAction *add_empty_action(void)
+{
+ bAction *act;
+
+ act= alloc_libblock(&G.main->action, ID_AC, "Action");
+ act->id.flag |= LIB_FAKEUSER;
+ act->id.us++;
+ return act;
+}
+
+static void transform_actionchannel_keys(char mode)
+{
+ bAction *act;
+ TransVert *tv;
+ int /*sel=0,*/ i;
+ bActionChannel *chan;
+ short mvals[2], mvalc[2], cent[2];
+ float sval[2], cval[2], lastcval[2];
+ short cancel=0;
+ float fac=0.0F;
+ int loop=1;
+ int tvtot=0;
+ float deltax, startx;
+ float cenf[2];
+ int invert=0, firsttime=1;
+ char str[256];
+ bConstraintChannel *conchan;
+
+ act=G.saction->action;
+
+ /* Ensure that partial selections result in beztriple selections */
+ for (chan=act->chanbase.first; chan; chan=chan->next){
+ tvtot+=fullselect_ipo_keys(chan->ipo);
+
+ for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next)
+ tvtot+=fullselect_ipo_keys(conchan->ipo);
+ }
+
+ /* If nothing is selected, bail out */
+ if (!tvtot)
+ return;
+
+
+ /* Build the transvert structure */
+ tv = MEM_callocN (sizeof(TransVert) * tvtot, "transVert");
+ tvtot=0;
+ for (chan=act->chanbase.first; chan; chan=chan->next){
+ /* Add the actionchannel */
+ tvtot = add_trans_ipo_keys(chan->ipo, tv, tvtot);
+ for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next)
+ tvtot = add_trans_ipo_keys(conchan->ipo, tv, tvtot);
+ }
+
+ /* Do the event loop */
+ cent[0] = curarea->winx + (G.saction->v2d.hor.xmax)/2;
+ cent[1] = curarea->winy + (G.saction->v2d.hor.ymax)/2;
+ areamouseco_to_ipoco(G.v2d, cent, &cenf[0], &cenf[1]);
+
+ getmouseco_areawin (mvals);
+ areamouseco_to_ipoco(G.v2d, mvals, &sval[0], &sval[1]);
+
+ startx=sval[0];
+ while (loop) {
+ /* Get the input */
+ /* If we're cancelling, reset transformations */
+ /* Else calc new transformation */
+ /* Perform the transformations */
+ while (qtest()) {
+ short val;
+ unsigned short event= extern_qread(&val);
+
+ if (val) {
+ switch (event) {
+ case LEFTMOUSE:
+ case SPACEKEY:
+ case RETKEY:
+ loop=0;
+ break;
+ case XKEY:
+ break;
+ case ESCKEY:
+ case RIGHTMOUSE:
+ cancel=1;
+ loop=0;
+ break;
+ default:
+ arrows_move_cursor(event);
+ break;
+ };
+ }
+ }
+
+ if (cancel) {
+ for (i=0; i<tvtot; i++) {
+ tv[i].loc[0]=tv[i].oldloc[0];
+ tv[i].loc[1]=tv[i].oldloc[1];
+ }
+ } else {
+ getmouseco_areawin (mvalc);
+ areamouseco_to_ipoco(G.v2d, mvalc, &cval[0], &cval[1]);
+
+ if (!firsttime && lastcval[0]==cval[0] && lastcval[1]==cval[1]) {
+ PIL_sleep_ms(1);
+ } else {
+ for (i=0; i<tvtot; i++){
+ tv[i].loc[0]=tv[i].oldloc[0];
+
+ switch (mode){
+ case 'g':
+ deltax = cval[0]-sval[0];
+ fac= deltax;
+
+ apply_keyb_grid(&fac, 0.0, 1.0, 0.1, U.flag & AUTOGRABGRID);
+
+ tv[i].loc[0]+=fac;
+ break;
+ case 's':
+ startx=mvals[0]-(ACTWIDTH/2+(curarea->winrct.xmax-curarea->winrct.xmin)/2);
+ deltax=mvalc[0]-(ACTWIDTH/2+(curarea->winrct.xmax-curarea->winrct.xmin)/2);
+ fac= fabs(deltax/startx);
+
+ apply_keyb_grid(&fac, 0.0, 0.2, 0.1, U.flag & AUTOSIZEGRID);
+
+ if (invert){
+ if (i % 03 == 0){
+ memcpy (tv[i].loc, tv[i].oldloc, sizeof(tv[i+2].oldloc));
+ }
+ if (i % 03 == 2){
+ memcpy (tv[i].loc, tv[i].oldloc, sizeof(tv[i-2].oldloc));
+ }
+
+ fac*=-1;
+ }
+ startx= (G.scene->r.cfra);
+
+ tv[i].loc[0]-= startx;
+ tv[i].loc[0]*=fac;
+ tv[i].loc[0]+= startx;
+
+ break;
+ }
+ }
+ }
+
+ if (mode=='s'){
+ sprintf(str, "sizeX: %.3f", fac);
+ headerprint(str);
+ }
+ else if (mode=='g'){
+ sprintf(str, "deltaX: %.3f", fac);
+ headerprint(str);
+ }
+
+ if (G.saction->lock){
+ do_all_actions();
+ allqueue (REDRAWVIEW3D, 0);
+ allqueue (REDRAWACTION, 0);
+ allqueue (REDRAWIPO, 0);
+ allqueue(REDRAWNLA, 0);
+ force_draw_all();
+ }
+ else {
+ addqueue (curarea->win, REDRAWALL, 0);
+ force_draw ();
+ }
+ }
+
+ lastcval[0]= cval[0];
+ lastcval[1]= cval[1];
+ firsttime= 0;
+ }
+
+ /* Update the curve */
+ /* Depending on the lock status, draw necessary views */
+
+ do_all_actions();
+ remake_action_ipos(act);
+ allqueue (REDRAWVIEW3D, 0);
+ allqueue (REDRAWACTION, 0);
+ allqueue(REDRAWNLA, 0);
+ allqueue (REDRAWIPO, 0);
+ MEM_freeN (tv);
+}
+
+void deselect_actionchannel_keys (bAction *act, int test)
+{
+ bActionChannel *chan;
+ bConstraintChannel *conchan;
+ int sel=1;;
+
+ if (!act)
+ return;
+
+ /* Determine if this is selection or deselection */
+
+ if (test){
+ for (chan=act->chanbase.first; chan; chan=chan->next){
+ /* Test the channel ipos */
+ if (is_ipo_key_selected(chan->ipo)){
+ sel = 0;
+ break;
+ }
+
+ /* Test the constraint ipos */
+ for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next){
+ if (is_ipo_key_selected(conchan->ipo)){
+ sel = 0;
+ break;
+ }
+ }
+
+ if (sel == 0)
+ break;
+ }
+ }
+ else
+ sel=0;
+
+ /* Set the flags */
+ for (chan=act->chanbase.first; chan; chan=chan->next){
+ set_ipo_key_selection(chan->ipo, sel);
+ for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next)
+ set_ipo_key_selection(conchan->ipo, sel);
+ }
+}
+
+void deselect_actionchannels (bAction *act, int test)
+{
+ bActionChannel *chan;
+ bConstraintChannel *conchan;
+ int sel=1;
+
+ if (!act)
+ return;
+
+ /* See if we should be selecting or deselecting */
+ if (test){
+ for (chan=act->chanbase.first; chan; chan=chan->next){
+ if (!sel)
+ break;
+
+ if (chan->flag & ACHAN_SELECTED){
+ sel=0;
+ break;
+ }
+ if (sel){
+ for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next){
+ if (conchan->flag & CONSTRAINT_CHANNEL_SELECT){
+ sel=0;
+ break;
+ }
+ }
+ }
+ }
+ }
+ else
+ sel=0;
+
+ /* Now set the flags */
+ for (chan=act->chanbase.first; chan; chan=chan->next){
+ select_poseelement_by_name(chan->name, sel);
+
+ if (sel)
+ chan->flag |= ACHAN_SELECTED;
+ else
+ chan->flag &= ~ACHAN_SELECTED;
+
+ for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next){
+ if (sel)
+ conchan->flag |= CONSTRAINT_CHANNEL_SELECT;
+ else
+ conchan->flag &= ~CONSTRAINT_CHANNEL_SELECT;
+ }
+ }
+
+}
+
+static void hilight_channel (bAction *act, bActionChannel *chan, short select)
+{
+ bActionChannel *curchan;
+
+ if (!act)
+ return;
+
+ for (curchan=act->chanbase.first; curchan; curchan=curchan->next){
+ if (curchan==chan && select)
+ curchan->flag |= ACHAN_HILIGHTED;
+ else
+ curchan->flag &= ~ACHAN_HILIGHTED;
+ }
+}
+
+static void mouse_actionchannels(bAction *act, short *mval)
+{
+ bActionChannel *chan;
+ bConstraintChannel *clickconchan=NULL;
+ float click;
+ int wsize;
+ int sel;
+ bConstraintChannel *conchan;
+
+ if (!act)
+ return;
+
+ wsize = (count_action_levels (act)*(CHANNELHEIGHT+CHANNELSKIP));
+
+
+ click = (wsize-(mval[1]+G.v2d->cur.ymin));
+ click += CHANNELHEIGHT/2;
+ click /= (CHANNELHEIGHT+CHANNELSKIP);
+
+ if (click<0)
+ return;
+
+ for (chan = act->chanbase.first; chan; chan=chan->next){
+ if ((int)click==0)
+ break;
+
+ click--;
+
+ /* Check for click in a constraint */
+ for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next){
+ if ((int)click==0){
+ clickconchan=conchan;
+ chan=act->chanbase.last;
+ break;
+ }
+ click--;
+ }
+ }
+
+ if (!chan){
+ if (clickconchan){
+ if (clickconchan->flag & CONSTRAINT_CHANNEL_SELECT)
+ sel = 0;
+ else
+ sel =1;
+
+ /* Channel names clicking */
+ if (G.qual & LR_SHIFTKEY){
+ // select_poseelement_by_name(chan->name, !(chan->flag & ACHAN_SELECTED));
+ if (clickconchan->flag & CONSTRAINT_CHANNEL_SELECT){
+ clickconchan->flag &= ~CONSTRAINT_CHANNEL_SELECT;
+ // hilight_channel(act, chan, 0);
+ }
+ else{
+ clickconchan->flag |= CONSTRAINT_CHANNEL_SELECT;
+ // hilight_channel(act, chan, 1);
+ }
+ }
+ else{
+ deselect_actionchannels (act, 0); // Auto clear
+ clickconchan->flag |= CONSTRAINT_CHANNEL_SELECT;
+ // hilight_channel(act, chan, 1);
+ // act->achan = chan;
+ // select_poseelement_by_name(chan->name, 1);
+ }
+
+ }
+ else
+ return;
+ }
+ else{
+ /* Choose the mode */
+ if (chan->flag & ACHAN_SELECTED)
+ sel = 0;
+ else
+ sel =1;
+
+ /* Channel names clicking */
+ if (G.qual & LR_SHIFTKEY){
+ select_poseelement_by_name(chan->name, !(chan->flag & ACHAN_SELECTED));
+ if (chan->flag & ACHAN_SELECTED){
+ chan->flag &= ~ACHAN_SELECTED;
+ hilight_channel(act, chan, 0);
+ }
+ else{
+ chan->flag |= ACHAN_SELECTED;
+ hilight_channel(act, chan, 1);
+ }
+ }
+ else{
+ deselect_actionchannels (act, 0); // Auto clear
+ chan->flag |= ACHAN_SELECTED;
+ hilight_channel(act, chan, 1);
+ act->achan = chan;
+ select_poseelement_by_name(chan->name, 1);
+ }
+
+ }
+ allqueue (REDRAWIPO, 0);
+ allqueue (REDRAWVIEW3D, 0);
+ allqueue (REDRAWACTION, 0);
+ allqueue(REDRAWNLA, 0);
+
+}
+
+static void delete_actionchannel_keys(void)
+{
+ bAction *act;
+ bActionChannel *chan;
+ bConstraintChannel *conchan;
+
+ act = G.saction->action;
+ if (!act)
+ return;
+
+ if (!okee("Erase selected keys"))
+ return;
+
+ for (chan = act->chanbase.first; chan; chan=chan->next){
+
+ /* Check action channel keys*/
+ delete_ipo_keys(chan->ipo);
+
+ /* Delete constraint channel keys */
+ for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next)
+ delete_ipo_keys(conchan->ipo);
+ }
+
+ remake_action_ipos (act);
+ allspace(REMAKEIPO, 0);
+ allqueue(REDRAWACTION, 0);
+ allqueue(REDRAWIPO, 0);
+ allqueue(REDRAWNLA, 0);
+
+}
+static void delete_actionchannels (void)
+{
+ bConstraintChannel *conchan, *nextconchan;
+ bActionChannel *chan, *next;
+ bAction *act;
+ int freechan;
+
+ act=G.saction->action;
+
+ if (!act)
+ return;
+
+ for (chan=act->chanbase.first; chan; chan=chan->next){
+ if (chan->flag & ACHAN_SELECTED)
+ break;
+ for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next)
+ {
+ if (conchan->flag & CONSTRAINT_CHANNEL_SELECT){
+ chan=act->chanbase.last;
+ break;
+ }
+ }
+ }
+
+ if (!chan && !conchan)
+ return;
+
+ if (!okee("Erase selected channels"))
+ return;
+
+ for (chan=act->chanbase.first; chan; chan=next){
+ freechan = 0;
+ next=chan->next;
+
+ /* Remove action channels */
+ if (chan->flag & ACHAN_SELECTED){
+ if (chan->ipo)
+ chan->ipo->id.us--; /* Release the ipo */
+ freechan = 1;
+ }
+
+ /* Remove constraint channels */
+ for (conchan=chan->constraintChannels.first; conchan; conchan=nextconchan){
+ nextconchan=conchan->next;
+ if (freechan || conchan->flag & CONSTRAINT_CHANNEL_SELECT){
+ if (conchan->ipo)
+ conchan->ipo->id.us--;
+ BLI_freelinkN(&chan->constraintChannels, conchan);
+ }
+ }
+
+ if (freechan)
+ BLI_freelinkN (&act->chanbase, chan);
+
+ }
+
+ allqueue (REDRAWACTION, 0);
+ allqueue(REDRAWNLA, 0);
+
+}
+void winqreadactionspace(unsigned short event, short val, char ascii)
+{
+ SpaceAction *saction;
+ bAction *act;
+ int doredraw= 0;
+ short mval[2];
+ float dx,dy;
+ int cfra;
+
+ if(curarea->win==0) return;
+
+ saction= curarea->spacedata.first;
+ if (!saction)
+ return;
+
+ act=saction->action;
+ if(val) {
+
+ if( uiDoBlocks(&curarea->uiblocks, event)!=UI_NOTHING ) event= 0;
+
+ getmouseco_areawin(mval);
+
+ switch(event) {
+ case UI_BUT_EVENT:
+ do_blenderbuttons(val);
+ break;
+ case HOMEKEY:
+ do_action_buttons(B_ACTHOME);
+ break;
+ case DKEY:
+ if (G.qual & LR_SHIFTKEY && mval[0]>ACTWIDTH){
+ duplicate_actionchannel_keys();
+ remake_action_ipos(act);
+ }
+ break;
+ case DELKEY:
+ case XKEY:
+ if (mval[0]<ACTWIDTH)
+ delete_actionchannels ();
+ else
+ delete_actionchannel_keys ();
+ break;
+ case GKEY:
+ if (mval[0]>=ACTWIDTH)
+ transform_actionchannel_keys ('g');
+ break;
+ case SKEY:
+ if (mval[0]>=ACTWIDTH)
+ transform_actionchannel_keys ('s');
+ break;
+ case AKEY:
+ if (mval[0]<ACTWIDTH){
+ deselect_actionchannels (act, 1);
+ allqueue (REDRAWVIEW3D, 0);
+ allqueue (REDRAWACTION, 0);
+ allqueue(REDRAWNLA, 0);
+ allqueue (REDRAWIPO, 0);
+ }
+ else{
+ deselect_actionchannel_keys (act, 1);
+ allqueue (REDRAWACTION, 0);
+ allqueue(REDRAWNLA, 0);
+ allqueue (REDRAWIPO, 0);
+ }
+ break;
+ case BKEY:
+ borderselect_action();
+ break;
+ case RIGHTMOUSE:
+ if (mval[0]<ACTWIDTH)
+ mouse_actionchannels(act, mval);
+ else
+ mouse_action();
+ break;
+ case LEFTMOUSE:
+ if (mval[0]>ACTWIDTH){
+ do {
+ getmouseco_areawin(mval);
+
+ areamouseco_to_ipoco(G.v2d, mval, &dx, &dy);
+
+ cfra= (int)dx;
+ if(cfra< 1) cfra= 1;
+
+ if( cfra!=CFRA ) {
+ CFRA= cfra;
+ update_for_newframe();
+ force_draw_plus(SPACE_VIEW3D);
+ force_draw_plus(SPACE_IPO);
+ force_draw_plus(SPACE_BUTS);
+ }
+
+ } while(get_mbut()&L_MOUSE);
+ }
+
+ break;
+ case MIDDLEMOUSE:
+ view2dmove(); /* in drawipo.c */
+ break;
+ }
+ }
+
+ if(doredraw) addqueue(curarea->win, REDRAW, 1);
+
+}
+
diff --git a/source/blender/src/editarmature.c b/source/blender/src/editarmature.c
new file mode 100644
index 00000000000..31c9c94fa6f
--- /dev/null
+++ b/source/blender/src/editarmature.c
@@ -0,0 +1,2574 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * editarmature.c: Interface for creating and posing armature objects
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "BMF_Api.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+
+#include "DNA_action_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_view3d_types.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_action.h"
+#include "BKE_armature.h"
+#include "BKE_constraint.h"
+#include "BKE_global.h"
+#include "BKE_object.h"
+
+#include "BIF_gl.h"
+#include "BIF_graphics.h"
+#include "BIF_interface.h"
+#include "BIF_resources.h"
+#include "BIF_screen.h"
+#include "BIF_space.h"
+#include "BIF_toolbox.h"
+#include "BIF_editarmature.h"
+#include "BIF_poseobject.h"
+#include "BIF_mywindow.h"
+
+#include "BDR_editobject.h"
+#include "BDR_drawobject.h"
+
+#include "BSE_edit.h"
+#include "BSE_view.h"
+#include "BSE_trans_types.h"
+#include "BSE_editaction.h"
+
+#include "mydevice.h"
+#include "interface.h"
+#include "blendef.h"
+#include "nla.h"
+
+/* >>>>> FIXME: ARG! Colours should be defined in a header somewhere! */
+/* Note, these came from drawobject.c They really should be in a nice header file somewhere */
+#define B_YELLOW 0x77FFFF
+#define B_PURPLE 0xFF70FF
+
+#define B_CYAN 0xFFFF00
+#define B_AQUA 0xFFBB55 /* 0xFF8833*/
+
+extern int tottrans; /* Originally defined in editobject.c */
+extern struct TransOb *transmain; /* Originally defined in editobject.c */
+extern float centre[3], centroid[3]; /* Originally defined in editobject.c */
+
+/* Macros */
+#define TEST_EDITARMATURE {if(G.obedit==0) return; if( (G.vd->lay & G.obedit->lay)==0 ) return;}
+
+/* Local Function Prototypes */
+static void editbones_to_armature (ListBase *bones, Object *ob);
+static int editbone_to_parnr (EditBone *bone);
+
+static void validate_editbonebutton(EditBone *bone);
+static void fix_bonelist_roll (ListBase *bonelist, ListBase *editbonelist);
+static int select_bonechildren_by_name (struct Bone *bone, char *name, int select);
+static void build_bonestring (char *string, struct EditBone *bone);
+static void draw_boneverti (float x, float y, float z, float size, int flag);
+static void draw_bone (int armflag, int boneflag, unsigned int id, char *name, float length);
+static void draw_bonechildren (struct Bone *bone, int flag, unsigned int *index);
+static void add_bone_input (struct Object *ob);
+static void make_boneList(struct ListBase* list, struct ListBase *bones, struct EditBone *parent);
+static void make_bone_menu_children (struct Bone *bone, char *str, int *index);
+static void delete_bone(struct EditBone* exBone);
+static void clear_armature_children (struct Bone *bone, struct bPose *pose, char mode);
+static void parnr_to_editbone(EditBone *bone);
+
+static int count_bones (struct bArmature *arm, int flagmask, int allbones);
+
+static int count_bonechildren (struct Bone *bone, int incount, int flagmask, int allbones);
+static int add_trans_bonechildren (struct Object* ob, struct Bone* bone, struct TransOb* buffer, int index, char mode);
+static void deselect_bonechildren (struct Bone *bone, int mode);
+static void selectconnected_posebonechildren (struct Bone *bone);
+
+static int editbone_name_exists (char* name);
+static void unique_editbone_name (char* name);
+static void *get_nearest_bone (int findunsel);
+static EditBone * get_nearest_editbonepoint (int findunsel, int *selmask);
+
+static void attach_bone_to_parent(EditBone *bone);
+static Bone *get_first_selected_bonechildren (Bone *bone);
+
+
+/* Functions */
+
+
+
+void apply_rot_armature (Object *ob, float mat[3][3]){
+ ListBase list;
+ EditBone *ebone;
+ bArmature *arm;
+
+ arm = get_armature(ob);
+
+ if (!arm)
+ return;
+
+ /* Put the armature into editmode */
+ list.first= list.last = NULL;
+ make_boneList(&list, &arm->bonebase, NULL);
+
+ /* Do the rotations */
+ for (ebone = list.first; ebone; ebone=ebone->next){
+
+ {
+
+ /* Fixme: This is essentially duplicated from join_armature */
+
+ float premat[4][4];
+ float postmat[4][4];
+ float difmat[4][4];
+ float imat[4][4];
+ float temp[4][4];
+ float delta[3];
+ float rmat[4][4];
+
+ Mat4CpyMat3 (rmat, mat);
+ /* Get the premat */
+ VecSubf (delta, ebone->tail, ebone->head);
+ make_boneMatrixvr(temp, delta, ebone->roll);
+ Mat4MulMat4 (premat, temp, rmat);
+
+ Mat4MulVecfl(rmat, ebone->head);
+ Mat4MulVecfl(rmat, ebone->tail);
+
+ /* Get the postmat */
+ VecSubf (delta, ebone->tail, ebone->head);
+ make_boneMatrixvr(postmat, delta, ebone->roll);
+
+ /* Find the roll */
+ Mat4Invert (imat, premat);
+ Mat4MulMat4 (difmat, postmat, imat);
+
+#if 0
+ printmatrix4 ("Difmat", difmat);
+#endif
+ ebone->roll -=atan(difmat[2][0]/difmat[2][2]);
+
+ if (difmat[0][0]<0)
+ ebone->roll +=M_PI;
+
+ }
+
+
+ }
+
+ /* Turn the list into an armature */
+ editbones_to_armature(&list, ob);
+
+ /* Free the editbones */
+ if (list.first){
+ BLI_freelistN (&list);
+ }
+
+}
+
+
+
+static Bone *get_first_selected_bonechildren (Bone *bone)
+{
+ Bone *curbone, *result;
+
+ if (bone->flag & BONE_SELECTED)
+ return bone;
+
+ for (curbone = bone->childbase.first; curbone; curbone=curbone->next){
+ result = get_first_selected_bonechildren(curbone);
+ if (result)
+ return result;
+ };
+
+ return NULL;
+}
+
+Bone *get_first_selected_bone (void)
+{
+ Bone *curbone, *result;
+ bArmature *arm;
+
+ arm = get_armature(OBACT);
+ if (!arm)
+ return NULL;
+
+ for (curbone = arm->bonebase.first; curbone; curbone=curbone->next){
+ result = get_first_selected_bonechildren(curbone);
+ if (result)
+ return result;
+ }
+
+ return NULL;
+}
+
+void clever_numbuts_posearmature (void)
+{
+ bArmature *arm;
+ Bone *bone;
+ bPoseChannel *chan;
+
+ arm = get_armature(OBACT);
+ if (!arm)
+ return;
+
+ bone = get_first_selected_bone();
+
+ if (!bone)
+ return;
+
+ add_numbut(0, NUM|FLO, "Loc X:", -G.vd->far, G.vd->far, bone->loc, 0);
+ add_numbut(1, NUM|FLO, "Loc Y:", -G.vd->far, G.vd->far, bone->loc+1, 0);
+ add_numbut(2, NUM|FLO, "Loc Z:", -G.vd->far, G.vd->far, bone->loc+2, 0);
+
+ add_numbut(3, NUM|FLO, "Quat X:", -G.vd->far, G.vd->far, bone->quat, 0);
+ add_numbut(4, NUM|FLO, "Quat Y:", -G.vd->far, G.vd->far, bone->quat+1, 0);
+ add_numbut(5, NUM|FLO, "Quat Z:", -G.vd->far, G.vd->far, bone->quat+2, 0);
+ add_numbut(6, NUM|FLO, "Quat W:", -G.vd->far, G.vd->far, bone->quat+3, 0);
+
+ add_numbut(7, NUM|FLO, "Size X:", -G.vd->far, G.vd->far, bone->size, 0);
+ add_numbut(8, NUM|FLO, "Size Y:", -G.vd->far, G.vd->far, bone->size+1, 0);
+ add_numbut(9, NUM|FLO, "Size Z:", -G.vd->far, G.vd->far, bone->size+2, 0);
+
+ do_clever_numbuts("Active Bone", 10, REDRAW);
+
+ /* This is similar to code in special_trans_update */
+
+ if (!G.obpose->pose) G.obpose->pose= MEM_callocN(sizeof(bPose), "pose");
+ chan = MEM_callocN (sizeof (bPoseChannel), "transPoseChannel");
+
+ chan->flag |= POSE_LOC|POSE_ROT|POSE_SIZE;
+ memcpy (chan->loc, bone->loc, sizeof (chan->loc));
+ memcpy (chan->quat, bone->quat, sizeof (chan->quat));
+ memcpy (chan->size, bone->size, sizeof (chan->size));
+ strcpy (chan->name, bone->name);
+
+ set_pose_channel (G.obpose->pose, chan);
+
+}
+
+void clever_numbuts_armature (void)
+{
+ EditBone *ebone, *child;
+
+ ebone= G.edbo.first;
+
+ for (ebone = G.edbo.first; ebone; ebone=ebone->next){
+ if (ebone->flag & BONE_SELECTED)
+ break;
+ }
+
+ if (!ebone)
+ return;
+
+ add_numbut(0, NUM|FLO, "Root X:", -G.vd->far, G.vd->far, ebone->head, 0);
+ add_numbut(1, NUM|FLO, "Root Y:", -G.vd->far, G.vd->far, ebone->head+1, 0);
+ add_numbut(2, NUM|FLO, "Root Z:", -G.vd->far, G.vd->far, ebone->head+2, 0);
+
+ add_numbut(3, NUM|FLO, "Tip X:", -G.vd->far, G.vd->far, ebone->tail, 0);
+ add_numbut(4, NUM|FLO, "Tip Y:", -G.vd->far, G.vd->far, ebone->tail+1, 0);
+ add_numbut(5, NUM|FLO, "Tip Z:", -G.vd->far, G.vd->far, ebone->tail+2, 0);
+
+ /* Convert roll to degrees */
+ ebone->roll *= (180.0F/M_PI);
+ add_numbut(6, NUM|FLO, "Roll:", -G.vd->far, G.vd->far, &ebone->roll, 0);
+
+ do_clever_numbuts("Active Bone", 7, REDRAW);
+
+ /* Convert roll to radians */
+ ebone->roll /= (180.0F/M_PI);
+
+ // Update our parent
+ if (ebone->parent && ebone->flag & BONE_IK_TOPARENT){
+ VECCOPY (ebone->parent->tail, ebone->head);
+ }
+
+ // Update our children if necessary
+ for (child = G.edbo.first; child; child=child->next){
+ if (child->parent == ebone && child->flag & BONE_IK_TOPARENT){
+ VECCOPY (child->head, ebone->tail);
+ }
+ }
+}
+
+void select_bone_by_name (bArmature *arm, char *name, int select)
+{
+ Bone *bone;
+
+ if (!arm)
+ return;
+
+ for (bone=arm->bonebase.first; bone; bone=bone->next)
+ if (select_bonechildren_by_name (bone, name, select))
+ break;
+}
+
+static int select_bonechildren_by_name (Bone *bone, char *name, int select)
+{
+ Bone *curBone;
+
+ if (!strcmp (bone->name, name)){
+ if (select)
+ bone->flag |= BONE_SELECTED;
+ else
+ bone->flag &= ~BONE_SELECTED;
+ return 1;
+ }
+
+ for (curBone=bone->childbase.first; curBone; curBone=curBone->next){
+ if (select_bonechildren_by_name (curBone, name, select))
+ return 1;
+ }
+
+ return 0;
+}
+void selectconnected_armature(void)
+{
+ EditBone *bone, *curBone, *next;
+
+ if (G.qual & LR_SHIFTKEY)
+ bone= get_nearest_bone(0);
+ else
+ bone= get_nearest_bone(1);
+
+ if (!bone)
+ return;
+
+ /* Select parents */
+ for (curBone=bone; curBone; curBone=next){
+ if (G.qual & LR_SHIFTKEY){
+ curBone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
+ }
+ else{
+ curBone->flag |= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
+ }
+
+ if (curBone->flag & BONE_IK_TOPARENT)
+ next=curBone->parent;
+ else
+ next=NULL;
+ }
+
+ /* Select children */
+ while (bone){
+ for (curBone=G.edbo.first; curBone; curBone=next){
+ next = curBone->next;
+ if (curBone->parent == bone){
+ if (curBone->flag & BONE_IK_TOPARENT){
+ if (G.qual & LR_SHIFTKEY)
+ curBone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
+ else
+ curBone->flag |= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
+ bone=curBone;
+ break;
+ }
+ else{
+ bone=NULL;
+ break;
+ }
+ }
+ }
+ if (!curBone)
+ bone=NULL;
+
+ }
+
+ countall();
+ allqueue (REDRAWVIEW3D, 0);
+
+}
+
+void selectconnected_posearmature(void)
+{
+ Bone *bone, *curBone, *next;
+
+ if (G.qual & LR_SHIFTKEY)
+ bone= get_nearest_bone(0);
+ else
+ bone = get_nearest_bone(1);
+
+ if (!bone)
+ return;
+
+ /* Select parents */
+ for (curBone=bone; curBone; curBone=next){
+ select_actionchannel_by_name (G.obpose->action, curBone->name, !(G.qual & LR_SHIFTKEY));
+ if (G.qual & LR_SHIFTKEY)
+ curBone->flag &= ~BONE_SELECTED;
+ else
+ curBone->flag |= BONE_SELECTED;
+
+ if (curBone->flag & BONE_IK_TOPARENT)
+ next=curBone->parent;
+ else
+ next=NULL;
+ }
+
+ /* Select children */
+ for (curBone=bone->childbase.first; curBone; curBone=next){
+ selectconnected_posebonechildren (curBone);
+ }
+
+ countall();
+ allqueue (REDRAWVIEW3D, 0);
+ allqueue (REDRAWACTION, 0);
+}
+
+static void selectconnected_posebonechildren (Bone *bone)
+{
+ Bone *curBone;
+
+ if (!(bone->flag & BONE_IK_TOPARENT))
+ return;
+
+ select_actionchannel_by_name (G.obpose->action, bone->name, !(G.qual & LR_SHIFTKEY));
+
+ if (G.qual & LR_SHIFTKEY)
+ bone->flag &= ~BONE_SELECTED;
+ else
+ bone->flag |= BONE_SELECTED;
+
+ for (curBone=bone->childbase.first; curBone; curBone=curBone->next){
+ selectconnected_posebonechildren (curBone);
+ }
+}
+
+
+char *make_bone_menu (bArmature *arm)
+{
+ char *menustr=NULL;
+ Bone *curBone;
+ int size;
+ int index=0;
+
+
+ // Count the bones
+ size = (count_bones (arm, 0xFFFFFFFF, 1)*48) + 256;
+ menustr = MEM_callocN(size, "bonemenu");
+
+ sprintf (menustr, "Select Bone%%t");
+
+ for (curBone=arm->bonebase.first; curBone; curBone=curBone->next){
+ make_bone_menu_children (curBone, menustr, &index);
+ }
+
+ return menustr;
+}
+
+static void make_bone_menu_children (Bone *bone, char *str, int *index)
+{
+ Bone *curBone;
+
+ sprintf (str, "%s|%s%%x%d", str, bone->name, *index);
+ (*index) ++;
+
+ for (curBone=bone->childbase.first; curBone; curBone=curBone->next)
+ make_bone_menu_children (curBone, str, index);
+}
+
+void free_editArmature(void)
+{
+
+ /* Clear the editbones list */
+ if (G.edbo.first){
+ BLI_freelistN (&G.edbo);
+ }
+}
+
+static EditBone * get_nearest_editbonepoint (int findunsel, int *selmask){
+ EditBone *ebone;
+ GLuint buffer[MAXPICKBUF];
+ short hits;
+ int i, takeNext=0;
+ int sel;
+ unsigned int hitresult, hitbone, firstunSel=-1;
+
+ glInitNames();
+ hits=selectprojektie(buffer, 0, 0, 0, 0);
+
+ /* See if there are any selected bones in this group */
+ if (hits){
+ for (i=0; i< hits; i++){
+ hitresult = buffer[3+(i*4)];
+ if (!(hitresult&BONESEL_NOSEL)){
+
+ /* Determine which points are selected */
+ hitbone = hitresult & ~(BONESEL_ROOT|BONESEL_TIP);
+
+ /* Determine what the current bone is */
+ ebone = BLI_findlink(&G.edbo, hitbone);
+
+ /* See if it is selected */
+ sel = 0;
+ if ((hitresult & (BONESEL_TIP|BONESEL_ROOT)) == (BONESEL_TIP|BONESEL_ROOT))
+ sel = (ebone->flag & (BONE_TIPSEL| BONE_ROOTSEL)) == (BONE_TIPSEL|BONE_ROOTSEL) ? 1 : 0;
+ else if (hitresult & BONESEL_TIP)
+ sel |= ebone->flag & BONE_TIPSEL;
+ else if (hitresult & BONESEL_ROOT)
+ sel |= ebone->flag & BONE_ROOTSEL;
+ if (!findunsel)
+ sel = !sel;
+
+ if (sel)
+ takeNext=1;
+ else{
+ if (firstunSel == -1)
+ firstunSel = hitresult;
+ if (takeNext){
+ *selmask =0;
+ if (hitresult & BONESEL_ROOT)
+ *selmask |= BONE_ROOTSEL;
+ if (hitresult & BONESEL_TIP)
+ *selmask |= BONE_TIPSEL;
+ return ebone;
+ }
+ }
+ }
+ }
+
+ if (firstunSel != -1){
+ *selmask = 0;
+ if (firstunSel & BONESEL_ROOT)
+ *selmask |= BONE_ROOTSEL;
+ if (firstunSel & BONESEL_TIP)
+ *selmask |= BONE_TIPSEL;
+ return BLI_findlink(&G.edbo, firstunSel & ~(BONESEL_ROOT|BONESEL_TIP));
+ }
+#if 1
+ else{
+ *selmask = 0;
+ if (buffer[3] & BONESEL_ROOT)
+ *selmask |= BONE_ROOTSEL;
+ if (buffer[3] & BONESEL_TIP)
+ *selmask |= BONE_TIPSEL;
+#if 1
+ return BLI_findlink(&G.edbo, buffer[3] & ~(BONESEL_ROOT|BONESEL_TIP));
+#else
+ return NULL;
+#endif
+ }
+#endif
+ }
+
+ *selmask = 0;
+ return NULL;
+}
+
+static void * get_nearest_bone (int findunsel){
+ void *firstunSel=NULL, *data;
+ GLuint buffer[MAXPICKBUF];
+ short hits;
+ int i, takeNext=0;
+ int sel;
+ unsigned int hitresult;
+ Bone *bone;
+ EditBone *ebone;
+
+ glInitNames();
+ hits=selectprojektie(buffer, 0, 0, 0, 0);
+
+
+ /* See if there are any selected bones in this group */
+ if (hits){
+ for (i=0; i< hits; i++){
+ hitresult = buffer[3+(i*4)];
+ if (!(hitresult&BONESEL_NOSEL)){
+
+ /* Determine which points are selected */
+ hitresult &= ~(BONESEL_ROOT|BONESEL_TIP);
+
+ /* Determine what the current bone is */
+ if (!G.obedit){
+ bone = get_indexed_bone(OBACT->data, hitresult);
+ if (findunsel)
+ sel = (bone->flag & BONE_SELECTED);
+ else
+ sel = !(bone->flag & BONE_SELECTED);
+ data = bone;
+ }
+ else{
+ ebone = BLI_findlink(&G.edbo, hitresult);
+ if (findunsel)
+ sel = (ebone->flag & BONE_SELECTED);
+ else
+ sel = !(ebone->flag & BONE_SELECTED);
+
+ data = ebone;
+ }
+
+ if (sel)
+ takeNext=1;
+ else{
+ if (!firstunSel)
+ firstunSel=data;
+ if (takeNext)
+ return data;
+ }
+ }
+ }
+
+ if (firstunSel)
+ return firstunSel;
+#if 1
+ else{
+#if 1
+ if (G.obedit)
+ return BLI_findlink(&G.edbo, buffer[3] & ~(BONESEL_ROOT|BONESEL_TIP));
+ else
+ return get_indexed_bone(OBACT->data, buffer[3] & ~(BONESEL_ROOT|BONESEL_TIP));
+#else
+ return NULL;
+#endif
+ }
+#endif
+ }
+
+ return NULL;
+}
+
+void delete_armature(void)
+{
+ EditBone *curBone, *next;
+
+ TEST_EDITARMATURE;
+ if(okee("Erase selected")==0) return;
+
+ for (curBone=G.edbo.first;curBone;curBone=next){
+ next=curBone->next;
+ if (curBone->flag&BONE_SELECTED)
+ delete_bone(curBone);
+ }
+
+
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWBUTSEDIT, 0);
+ allqueue(REDRAWBUTSCONSTRAINT, 0);
+ countall();
+}
+
+
+static void delete_bone(EditBone* exBone)
+{
+ EditBone *curBone;
+ bPoseChannel *chan;
+
+ /* Find any bones that refer to this bone */
+ for (curBone=G.edbo.first;curBone;curBone=curBone->next){
+ if (curBone->parent==exBone){
+ curBone->parent=exBone->parent;
+ curBone->flag &= ~BONE_IK_TOPARENT;
+ }
+ }
+
+ /* Erase any associated pose channel */
+ if (G.obedit->pose){
+ for (chan=G.obedit->pose->chanbase.first; chan; chan=chan->next){
+ if (!strcmp (chan->name, exBone->name)){
+ free_constraints(&chan->constraints);
+ BLI_freelinkN (&G.obedit->pose->chanbase, chan);
+ break;
+ }
+ }
+ }
+
+
+ allqueue(REDRAWBUTSCONSTRAINT, 0);
+ allqueue(REDRAWBUTSEDIT, 0);
+
+ BLI_freelinkN (&G.edbo,exBone);
+}
+
+void remake_editArmature(void)
+{
+ if(okee("Reload Original data")==0) return;
+
+ make_editArmature();
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWBUTSHEAD, 0);
+ allqueue(REDRAWBUTSCONSTRAINT, 0);
+ allqueue(REDRAWBUTSEDIT, 0);
+}
+
+void mouse_armature(void)
+{
+ EditBone* nearBone = NULL;
+ int selmask;
+
+ nearBone=get_nearest_editbonepoint(1, &selmask);
+
+ if (nearBone){
+ if ((G.qual & LR_SHIFTKEY) && (nearBone->flag & selmask))
+ nearBone->flag &= ~selmask;
+ else
+ nearBone->flag |= selmask;
+
+ if (!(G.qual & LR_SHIFTKEY)){
+ deselectall_armature();
+ nearBone->flag |= selmask;
+ }
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWBUTSEDIT, 0);
+ allqueue(REDRAWBUTSCONSTRAINT, 0);
+ };
+ countall();
+ rightmouse_transform();
+}
+
+void make_editArmature(void)
+{
+ bArmature *arm;
+
+ if (G.obedit==0)
+ return;
+
+ free_editArmature();
+
+ arm= get_armature(G.obedit);
+ if (!arm)
+ return;
+
+ make_boneList (&G.edbo, &arm->bonebase,NULL);
+}
+
+static void editbones_to_armature (ListBase *list, Object *ob)
+{
+ bArmature *arm;
+ EditBone *eBone;
+ Bone *newBone;
+
+ arm = get_armature(ob);
+ if (!list)
+ return;
+ if (!arm)
+ return;
+
+ free_bones(arm);
+
+
+ /* Copy the bones from the editData into the armature*/
+ for (eBone=list->first;eBone;eBone=eBone->next){
+ newBone=MEM_callocN (sizeof(Bone), "bone");
+ eBone->temp= newBone; /* Associate the real Bones with the EditBones */
+
+ strcpy (newBone->name, eBone->name);
+ memcpy (newBone->head, eBone->head, sizeof(float)*3);
+ memcpy (newBone->tail, eBone->tail, sizeof(float)*3);
+ newBone->flag=eBone->flag &~(BONE_SELECTED|BONE_HILIGHTED);
+// newBone->roll=eBone->roll;
+ newBone->roll = 0.0F;
+
+ /* >>>>> FIXME: This isn't a very good system: a lot of
+ pointless copying involved. To be investigated
+ once things are working better.
+ */
+
+ newBone->weight = eBone->weight;
+ newBone->dist = eBone->dist;
+ memcpy (newBone->loc, eBone->loc, sizeof(eBone->loc));
+ memcpy (newBone->dloc, eBone->dloc, sizeof(eBone->dloc));
+/* memcpy (newBone->orig, eBone->orig, sizeof(eBone->orig));*/
+ memcpy (newBone->size, eBone->size, sizeof(eBone->size));
+ memcpy (newBone->dsize, eBone->dsize, sizeof(eBone->dsize));
+ memcpy (newBone->quat, eBone->quat, sizeof(eBone->quat));
+ memcpy (newBone->dquat, eBone->dquat, sizeof(eBone->dquat));
+ memcpy (newBone->obmat, eBone->obmat, sizeof(eBone->obmat));
+ }
+
+ /* Fix parenting in a separate pass to ensure ebone->bone connections
+ are valid at this point */
+ for (eBone=list->first;eBone;eBone=eBone->next){
+ newBone= (Bone*) eBone->temp;
+ if (eBone->parent){
+ newBone->parent=(Bone*) eBone->parent->temp;
+ BLI_addtail (&newBone->parent->childbase,newBone);
+
+ {
+ float M_boneRest[4][4];
+ float M_parentRest[4][4];
+ float iM_parentRest[4][4];
+ float delta[3];
+
+ /* Get the parent's global matrix (rotation only)*/
+ VecSubf (delta, eBone->parent->tail, eBone->parent->head);
+ make_boneMatrixvr(M_parentRest, delta, eBone->parent->roll);
+
+ /* Get this bone's global matrix (rotation only)*/
+ VecSubf (delta, eBone->tail, eBone->head);
+ make_boneMatrixvr(M_boneRest, delta, eBone->roll);
+
+ /* Invert the parent matrix */
+ Mat4Invert (iM_parentRest, M_parentRest);
+
+ /* Get the new head and tail */
+ VecSubf (newBone->head, eBone->head, eBone->parent->tail);
+ VecSubf (newBone->tail, eBone->tail, eBone->parent->tail);
+
+ Mat4MulVecfl(iM_parentRest, newBone->head);
+ Mat4MulVecfl(iM_parentRest, newBone->tail);
+
+
+ }
+
+ }
+ /* ...otherwise add this bone to the armature's bonebase */
+ else
+ BLI_addtail (&arm->bonebase,newBone);
+ }
+
+ /* Make a pass through the new armature to fix rolling */
+ fix_bonelist_roll (&arm->bonebase, list);
+ /* Get rid of pose channels that may have belonged to deleted bones */
+ collect_pose_garbage(ob);
+ /* Ensure all bones have channels */
+ apply_pose_armature(arm, ob->pose, 0);
+
+ /* Calculate and cache the inverse restposition matrices (needed for deformation)*/
+ precalc_bonelist_irestmats(&arm->bonebase);
+}
+
+
+void load_editArmature(void)
+{
+ bArmature *arm;
+
+ arm=get_armature(G.obedit);
+ if (!arm)
+ return;
+
+#if 1
+ editbones_to_armature(&G.edbo, G.obedit);
+#else
+ free_bones(arm);
+
+
+ /* Copy the bones from the editData into the armature*/
+ for (eBone=G.edbo.first;eBone;eBone=eBone->next){
+ newBone=MEM_callocN (sizeof(Bone), "bone");
+ eBone->temp= newBone; /* Associate the real Bones with the EditBones */
+
+ strcpy (newBone->name, eBone->name);
+ memcpy (newBone->head, eBone->head, sizeof(float)*3);
+ memcpy (newBone->tail, eBone->tail, sizeof(float)*3);
+ newBone->flag=eBone->flag &~(BONE_SELECTED|BONE_HILIGHTED);
+ // newBone->roll=eBone->roll;
+ newBone->roll = 0.0F;
+
+ /* >>>>> FIXME: This isn't a very good system: a lot of
+ pointless copying involved. To be investigated
+ once things are working better.
+ */
+
+ newBone->weight = eBone->weight;
+ newBone->dist = eBone->dist;
+ memcpy (newBone->loc, eBone->loc, sizeof(eBone->loc));
+ memcpy (newBone->dloc, eBone->dloc, sizeof(eBone->dloc));
+/* memcpy (newBone->orig, eBone->orig, sizeof(eBone->orig));*/
+ memcpy (newBone->size, eBone->size, sizeof(eBone->size));
+ memcpy (newBone->dsize, eBone->dsize, sizeof(eBone->dsize));
+ memcpy (newBone->quat, eBone->quat, sizeof(eBone->quat));
+ memcpy (newBone->dquat, eBone->dquat, sizeof(eBone->dquat));
+ memcpy (newBone->obmat, eBone->obmat, sizeof(eBone->obmat));
+ }
+
+ /* Fix parenting in a separate pass to ensure ebone->bone connections
+ are valid at this point */
+ for (eBone=G.edbo.first;eBone;eBone=eBone->next){
+ newBone= (Bone*) eBone->temp;
+ if (eBone->parent){
+ newBone->parent=(Bone*) eBone->parent->temp;
+ BLI_addtail (&newBone->parent->childbase,newBone);
+
+ {
+ float M_boneRest[4][4];
+ float M_parentRest[4][4];
+ float M_relativeBone[4][4];
+ float iM_parentRest[4][4];
+ float delta[3];
+
+ /* Get the parent's global matrix (rotation only)*/
+ VecSubf (delta, eBone->parent->tail, eBone->parent->head);
+ make_boneMatrixvr(M_parentRest, delta, eBone->parent->roll);
+
+ /* Get this bone's global matrix (rotation only)*/
+ VecSubf (delta, eBone->tail, eBone->head);
+ make_boneMatrixvr(M_boneRest, delta, eBone->roll);
+
+ /* Invert the parent matrix */
+ Mat4Invert (iM_parentRest, M_parentRest);
+
+ /* Get the new head and tail */
+ VecSubf (newBone->head, eBone->head, eBone->parent->tail);
+ VecSubf (newBone->tail, eBone->tail, eBone->parent->tail);
+
+ Mat4MulVecfl(iM_parentRest, newBone->head);
+ Mat4MulVecfl(iM_parentRest, newBone->tail);
+
+
+ }
+
+ }
+ /* ...otherwise add this bone to the armature's bonebase */
+ else
+ BLI_addtail (&arm->bonebase,newBone);
+ }
+
+ /* Make a pass through the new armature to fix rolling */
+ fix_bonelist_roll (&arm->bonebase, &G.edbo);
+
+ /* Get rid of pose channels that may have belonged to deleted bones */
+ collect_pose_garbage(G.obedit);
+#endif
+}
+
+static void fix_bonelist_roll (ListBase *bonelist, ListBase *editbonelist)
+{
+ Bone *curBone;
+ EditBone *ebone;
+
+ for (curBone=bonelist->first; curBone; curBone=curBone->next){
+
+ /* Fix this bone's roll */
+#if 1
+ {
+ float premat[4][4];
+ float postmat[4][4];
+ float difmat[4][4];
+ float imat[4][4];
+ float delta[3];
+
+ /* Find the associated editbone */
+ for (ebone = editbonelist->first; ebone; ebone=ebone->next)
+ if ((Bone*)ebone->temp == curBone)
+ break;
+
+ if (ebone){
+ /* Get the premat */
+ VecSubf (delta, ebone->tail, ebone->head);
+ make_boneMatrixvr(premat, delta, ebone->roll);
+
+ /* Get the postmat */
+ get_objectspace_bone_matrix(curBone, postmat, 1, 0);
+ postmat[3][0]=postmat[3][1]=postmat[3][2]=0.0F;
+#if 1
+ Mat4Invert (imat, premat);
+ Mat4MulMat4 (difmat, postmat, imat);
+#else
+ Mat4Invert (imat, postmat);
+ Mat4MulMat4 (difmat, premat, imat);
+#endif
+#if 0
+ printf ("Bone %s\n", curBone->name);
+ printmatrix4 ("premat", premat);
+ printmatrix4 ("postmat", postmat);
+ printmatrix4 ("difmat", difmat);
+ printf ("Roll = %f\n", (-atan(difmat[2][0]/difmat[2][2]) * (180.0/M_PI)));
+#endif
+ curBone->roll = -atan(difmat[2][0]/difmat[2][2]);
+
+ if (difmat[0][0]<0)
+ curBone->roll +=M_PI;
+
+ }
+ }
+#endif
+
+ fix_bonelist_roll (&curBone->childbase, editbonelist);
+ }
+}
+
+void make_bone_parent(void)
+{
+/* error ("Bone Parenting not yet implemented"); */
+ return;
+}
+
+static void make_boneList(ListBase* list, ListBase *bones, EditBone *parent)
+{
+ EditBone *eBone;
+ Bone *curBone;
+
+ for (curBone=bones->first; curBone; curBone=curBone->next){
+ eBone=MEM_callocN(sizeof(EditBone),"make_editbone");
+
+ /* Copy relevant data from bone to eBone */
+ eBone->parent=parent;
+ strcpy (eBone->name, curBone->name);
+ eBone->flag = curBone->flag & ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
+
+ /* Print bone matrix before and after */
+
+ get_bone_root_pos(curBone, eBone->head, 0);
+ get_bone_tip_pos(curBone, eBone->tail, 0);
+// eBone->roll=curBone->roll;
+ eBone->roll=0;
+
+#if 1
+ {
+ float delta[3];
+ float premat[4][4];
+ float postmat[4][4];
+ float imat[4][4];
+ float difmat[4][4];
+
+ VecSubf (delta, eBone->tail, eBone->head);
+ make_boneMatrixvr(postmat, delta, eBone->roll);
+
+ get_objectspace_bone_matrix(curBone, premat, 1, 0);
+
+#if 0
+ Mat4Invert (imat, premat);
+ Mat4MulMat4 (difmat, postmat, imat);
+#else
+ Mat4Invert (imat, postmat);
+ Mat4MulMat4 (difmat, premat, imat);
+#endif
+#if 0
+ printf ("Bone %s\n", curBone->name);
+ printmatrix4 ("diffmat", difmat);
+ printf ("Roll : atan of %f / %f = %f\n", difmat[2][0], difmat[2][2], (float)atan(difmat[2][0]/difmat[2][2])*(180.0F/M_PI));
+#endif
+ eBone->roll = atan(difmat[2][0]/difmat[2][2]);
+
+ if (difmat[0][0]<0)
+ eBone->roll +=M_PI;
+ }
+#endif
+ eBone->dist= curBone->dist;
+ eBone->weight= curBone->weight;
+ memcpy (eBone->loc, curBone->loc, sizeof(curBone->loc));
+ memcpy (eBone->dloc, curBone->dloc, sizeof(curBone->dloc));
+ /* memcpy (eBone->orig, curBone->orig, sizeof(curBone->orig));*/
+ memcpy (eBone->size, curBone->size, sizeof(curBone->size));
+ memcpy (eBone->dsize, curBone->dsize, sizeof(curBone->dsize));
+ memcpy (eBone->quat, curBone->quat, sizeof(curBone->quat));
+ memcpy (eBone->dquat, curBone->dquat, sizeof(curBone->dquat));
+ memcpy (eBone->obmat, curBone->obmat, sizeof(curBone->obmat));
+
+
+ BLI_addtail (list, eBone);
+
+ /* Add children if necessary */
+ if (curBone->childbase.first)
+ make_boneList (list, &curBone->childbase, eBone);
+ }
+
+
+}
+
+#if 0
+static EditVert* add_armatureVert (float *loc)
+{
+ EditVert* vert=NULL;
+
+ vert = MEM_callocN (sizeof (EditVert), "armaturevert");
+ if (vert){
+ VECCOPY (vert->co, loc);
+ BLI_addtail (&G.edve,vert);
+ }
+
+ return vert;
+
+}
+
+static EditVert* get_armatureVert (float *loc)
+{
+ EditVert* vert;
+
+ for (vert=G.edve.first;vert;vert=vert->next){
+ if ((vert->co[0]==loc[0])&&(vert->co[1]==loc[1])&&(vert->co[2]==loc[2])){
+ return (vert);
+ }
+ }
+
+ return add_armatureVert (loc);
+}
+#endif
+
+void draw_armature(Object *ob)
+{
+ bArmature *arm;
+ Bone *bone;
+ EditBone *eBone;
+ unsigned int index;
+ float delta[3],offset[3];
+ float bmat[4][4];
+ float length;
+
+ if (ob==NULL) return;
+
+ arm= ob->data;
+ if (arm==NULL) return;
+
+ if (!(ob->lay & G.vd->lay))
+ return;
+
+ /* If we're in editmode, draw the Global edit data */
+ if(ob==G.obedit || (G.obedit && ob->data==G.obedit->data)) {
+ cpack (0x000000);
+
+ arm->flag |= ARM_EDITMODE;
+ for (eBone=G.edbo.first, index=0; eBone; eBone=eBone->next, index++){
+ if (ob==G.obedit){
+ // if ((eBone->flag&(BONE_TIPSEL | BONE_ROOTSEL))==(BONE_TIPSEL|BONE_ROOTSEL))
+ // cpack (B_YELLOW);
+ // else
+ cpack (B_PURPLE);
+ }
+ else cpack (0x000000);
+
+ glPushMatrix();
+
+ /* Compose the parent transforms (i.e. their translations) */
+ VECCOPY (offset,eBone->head);
+
+ glTranslatef (offset[0],offset[1],offset[2]);
+
+ delta[0]=eBone->tail[0]-eBone->head[0];
+ delta[1]=eBone->tail[1]-eBone->head[1];
+ delta[2]=eBone->tail[2]-eBone->head[2];
+
+ length = sqrt (delta[0]*delta[0] + delta[1]*delta[1] +delta[2]*delta[2]);
+
+ make_boneMatrixvr(bmat, delta, eBone->roll);
+ glMultMatrixf (bmat);
+ draw_bone (arm->flag, eBone->flag, index, eBone->name, length);
+
+ glPopMatrix();
+ if (eBone->parent){
+ glLoadName (-1);
+ setlinestyle(3);
+
+ glBegin(GL_LINES);
+ glVertex3fv(eBone->parent->tail);
+ glVertex3fv(eBone->head);
+ glEnd();
+
+ setlinestyle(0);
+ }
+ };
+ arm->flag &= ~ARM_EDITMODE;
+ cpack (B_YELLOW);
+
+ }
+ else{
+ /* Draw hierarchical bone list (non-edit data) */
+
+ /* Ensure we're using the mose recent pose */
+ if (!ob->pose)
+ ob->pose=MEM_callocN (sizeof(bPose), "pose");
+
+#if 1 /* Activate if there are problems with action lag */
+ apply_pose_armature(arm, ob->pose, 0);
+ where_is_armature (ob);
+#endif
+
+ if (G.obpose == ob){
+ arm->flag |= ARM_POSEMODE;
+#if 0 /* Depreciated interactive ik goal drawing */
+ if (arm->chainbase.first){
+ glPushMatrix();
+ glTranslatef(((PoseChain*)arm->chainbase.first)->goal[0],
+ ((PoseChain*)arm->chainbase.first)->goal[1],
+ ((PoseChain*)arm->chainbase.first)->goal[2]);
+ drawaxes(1.0);
+ glPopMatrix();
+ }
+#endif
+ }
+ index = 0;
+ for (bone=arm->bonebase.first; bone; bone=bone->next) {
+ glPushMatrix();
+ draw_bonechildren(bone, arm->flag, &index);
+ glPopMatrix();
+ if (arm->flag & ARM_POSEMODE)
+ cpack (B_CYAN);
+ }
+
+ arm->flag &= ~ARM_POSEMODE;
+ }
+}
+
+static void draw_boneverti (float x, float y, float z, float size, int flag)
+{
+ GLUquadricObj *qobj;
+
+ size*=0.05;
+
+/*
+ Ultimately dots should be drawn in screenspace
+ For now we'll just draw them any old way.
+*/
+ glPushMatrix();
+
+ glTranslatef(x, y, z);
+
+ qobj = gluNewQuadric();
+ gluQuadricDrawStyle(qobj, GLU_SILHOUETTE);
+ gluPartialDisk( qobj, 0, 1.0F*size, 32, 1, 360.0, 360.0);
+
+ glRotatef (90, 0, 1, 0);
+ gluPartialDisk( qobj, 0, 1.0F*size, 32, 1, 360.0, 360.0);
+
+ glRotatef (90, 1, 0, 0);
+ gluPartialDisk( qobj, 0, 1.0F*size, 32, 1, 360.0, 360.0);
+
+ gluDeleteQuadric(qobj);
+
+ glPopMatrix();
+}
+
+static void draw_bonechildren (Bone *bone, int flag, unsigned int *index)
+{
+ Bone *cbone;
+ float delta[3];
+ float length;
+ float M_objectspacemat[4][4];
+
+ if (bone==NULL) return;
+
+ if (flag & ARM_POSEMODE){
+ if (bone->flag & BONE_SELECTED)
+ cpack (B_CYAN);
+ else
+ cpack (B_AQUA);
+ }
+
+ // Draw a line from our root to the parent's tip
+ if (bone->parent && !(bone->flag & (BONE_IK_TOPARENT|BONE_HIDDEN)) ){
+ float childMat[4][4];
+ float boneMat[4][4];
+ float tip[3], root[3];
+ get_objectspace_bone_matrix(bone->parent, boneMat, 0, 1);
+ get_objectspace_bone_matrix(bone, childMat, 1, 1);
+
+ VECCOPY (tip, boneMat[3]);
+ VECCOPY (root, childMat[3]);
+
+ if (flag & ARM_POSEMODE)
+ glLoadName (-1);
+ setlinestyle(3);
+ glBegin(GL_LINES);
+ glVertex3fv(tip);
+ glVertex3fv(root);
+ glEnd();
+ setlinestyle(0);
+ }
+
+
+ /* Draw this bone in objectspace */
+ delta[0]=bone->tail[0]-bone->head[0];
+ delta[1]=bone->tail[1]-bone->head[1];
+ delta[2]=bone->tail[2]-bone->head[2];
+ length = sqrt (delta[0]*delta[0] + delta[1]*delta[1] + delta[2]*delta[2] );
+
+ /* Incorporates offset, rest rotation, user rotation and parent coordinates*/
+ get_objectspace_bone_matrix(bone, M_objectspacemat, 1, 1);
+
+ if (!(bone->flag & BONE_HIDDEN)){
+ glPushMatrix();
+ glMultMatrixf(M_objectspacemat);
+
+
+ if (flag & ARM_POSEMODE)
+ draw_bone(flag, (bone->parent && bone->parent->flag & BONE_HIDDEN) ? (bone->flag & ~BONE_IK_TOPARENT) : (bone->flag), *index, bone->name, length);
+ else
+ draw_bone(flag, (bone->parent && bone->parent->flag & BONE_HIDDEN) ? (bone->flag & ~BONE_IK_TOPARENT) : (bone->flag), -1, bone->name, length);
+ glPopMatrix();
+ }
+ (*index)++;
+
+ /* Draw the children */
+ for (cbone= bone->childbase.first; cbone; cbone=cbone->next){
+ draw_bonechildren (cbone, flag, index);
+ }
+}
+
+static void draw_bone (int armflag, int boneflag, unsigned int id, char *name, float length)
+{
+ float vec[2];
+ float bulge;
+ float pointsize;
+ /*
+ FIXME: This routine should probably draw the bones in screenspace using
+ the projected start & end points of the transformed bone
+ */
+
+ pointsize = length;
+ if (pointsize<0.1)
+ pointsize=0.1;
+
+ /* Draw a 3d octahedral bone */
+
+ bulge=length*0.1;
+
+ if (id!=-1)
+ glLoadName((GLuint) id );
+
+ glPushMatrix();
+
+ /* Draw root point if we have no IK parent */
+ if (!(boneflag & BONE_IK_TOPARENT)){
+ if (id != -1)
+ glLoadName (id | BONESEL_ROOT);
+ if (armflag & ARM_EDITMODE){
+ if (boneflag & BONE_ROOTSEL)
+ cpack (B_YELLOW);
+ else
+ cpack (B_PURPLE);
+ }
+ draw_boneverti (0, 0, 0, pointsize, 0);
+ }
+
+ /* Draw tip point (for selection only )*/
+
+ if (id != -1)
+ glLoadName (id | BONESEL_TIP);
+
+ if (armflag & ARM_EDITMODE){
+ if (boneflag & BONE_TIPSEL)
+ cpack (B_YELLOW);
+ else
+ cpack (B_PURPLE);
+ }
+
+ draw_boneverti (0, length, 0, pointsize, 0);
+
+ if (id != -1){
+ if (armflag & ARM_POSEMODE)
+ glLoadName((GLuint) id);
+ else{
+#if 1 /* Bones not selectable in editmode */
+ glLoadName((GLuint) -1);
+#else
+ glLoadName ((GLuint) id|BONESEL_TIP|BONESEL_ROOT);
+#endif
+ }
+ }
+
+
+ if (armflag & ARM_EDITMODE){
+ if (boneflag & BONE_SELECTED)
+ cpack (B_YELLOW);
+ else
+ cpack (B_PURPLE);
+ }
+
+ /* Draw additional axes */
+ if (armflag & ARM_DRAWAXES){
+ drawaxes(length*0.25F);
+ }
+
+ /* Section 1*/
+ glBegin(GL_LINE_STRIP);
+ vec[0]= vec[1]= 0;
+ glVertex2fv(vec);
+
+ vec[0]= -bulge; vec[1]= bulge;
+ glVertex2fv(vec);
+
+ vec[0]= 0; vec[1]= length;
+ glVertex2fv(vec);
+
+ vec[0]= bulge; vec[1]= bulge;
+ glVertex2fv(vec);
+
+ vec[0]= 0; vec[1]= 0;
+ glVertex2fv(vec);
+ glEnd();
+
+ /* Section 2*/
+ glRotatef(90,0,1,0);
+ glBegin(GL_LINE_STRIP);
+ vec[0]= vec[1]= 0;
+ glVertex2fv(vec);
+
+ vec[0]= -bulge; vec[1]= bulge;
+ glVertex2fv(vec);
+
+ vec[0]= 0; vec[1]= length;
+ glVertex2fv(vec);
+
+ vec[0]= bulge; vec[1]= bulge;
+ glVertex2fv(vec);
+
+ vec[0]= 0; vec[1]= 0;
+ glVertex2fv(vec);
+ glEnd();
+
+ /* Square*/
+ glTranslatef (0,bulge,0);
+ glRotatef(45,0,1,0);
+ glRotatef(90,1,0,0);
+ glBegin(GL_LINE_STRIP);
+
+ vec[0]= -bulge*.707;vec[1]=-bulge*.707;
+ glVertex2fv(vec);
+
+ vec[0]= bulge*.707;vec[1]= -bulge*.707;
+ glVertex2fv(vec);
+
+ vec[0]= bulge*.707;vec[1]= bulge*.707;
+ glVertex2fv(vec);
+
+ vec[0]= -bulge*.707;vec[1]= bulge*.707;
+ glVertex2fv(vec);
+
+ vec[0]= vec[1]= -bulge*.707;
+ glVertex2fv(vec);
+ glEnd();
+
+
+ glPopMatrix();
+
+ /* Draw the bone name */
+ if (armflag & ARM_DRAWNAMES){
+ glRasterPos3f(0, length/2.0, 0);
+ BMF_DrawString(G.font, " ");
+ BMF_DrawString(G.font, name);
+ }
+}
+
+
+
+void add_primitiveArmature(int type)
+{
+ if(G.scene->id.lib) return;
+
+ /* this function also comes from an info window */
+ if ELEM(curarea->spacetype, SPACE_VIEW3D, SPACE_INFO); else return;
+ if(G.vd==NULL) return;
+
+ check_editmode(OB_ARMATURE);
+
+ /* If we're not the "obedit", make a new object and enter editmode */
+ if(G.obedit==NULL) {
+ add_object(OB_ARMATURE);
+ base_init_from_view3d(BASACT, G.vd);
+ G.obedit= BASACT->object;
+
+ where_is_object(G.obedit);
+
+ make_editArmature();
+ setcursor_space(SPACE_VIEW3D, CURSOR_EDIT);
+ }
+
+ switch (type){
+ default:
+ add_bone_input (G.obedit);
+ break;
+ };
+
+ countall();
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWBUTSEDIT, 0);
+ allqueue(REDRAWBUTSHEAD, 0);
+ allqueue(REDRAWBUTSCONSTRAINT, 0);
+ allqueue(REDRAWNLA, 0);
+}
+
+static void add_bone_input (Object *ob)
+/*
+ FUNCTION:
+ Creates a bone chain under user input.
+ As the user clicks to accept each bone,
+ a new bone is started as the child and IK
+ child of the previous bone. Pressing ESC
+ cancels the current bone and leaves bone
+ adding mode.
+
+*/
+{
+ float *cursLoc, cent[3], dx, dy;
+ float mat[3][3], curs[3], cmat[3][3], imat[3][3], rmat[4][4], itmat[4][4];
+ short xo, yo, mval[2], afbreek=0;
+ short val;
+ float restmat[4][4], tempVec[4];
+ EditBone *bone;
+ EditBone *parent;
+ unsigned short event;
+ float angle, scale;
+ float length, lengths;
+ float newEnd[4];
+ int addbones=1;
+ float dvec[3], dvecp[3];
+
+ cursLoc= give_cursor();
+
+ VECCOPY (curs,cursLoc);
+
+ while (addbones>0){
+ afbreek=0;
+ /* Create an inverse matrix */
+ Mat3CpyMat4(mat, G.obedit->obmat);
+ VECCOPY(cent, curs);
+ cent[0]-= G.obedit->obmat[3][0];
+ cent[1]-= G.obedit->obmat[3][1];
+ cent[2]-= G.obedit->obmat[3][2];
+
+ Mat3CpyMat4(imat, G.vd->viewmat);
+ Mat3MulVecfl(imat, cent);
+
+ Mat3MulMat3(cmat, imat, mat);
+ Mat3Inv(imat,cmat);
+
+ /* Create a temporary bone */
+ bone= MEM_callocN(sizeof(EditBone), "eBone");
+
+ /* If we're the child of something, set that up now */
+ if (addbones>1){
+ parent=G.edbo.last;
+ bone->parent=parent;
+ bone->flag|=BONE_IK_TOPARENT;
+ }
+
+ strcpy (bone->name,"Bone");
+ unique_editbone_name (bone->name);
+
+ BLI_addtail(&G.edbo, bone);
+
+ bone->flag |= BONE_QUATROT;
+ bone->flag |= (BONE_SELECTED);
+ deselectall_armature();
+ bone->flag |= BONE_SELECTED|BONE_HILIGHTED|BONE_TIPSEL|BONE_ROOTSEL;
+
+ bone->weight= 1.0F;
+ bone->dist= 1.0F;
+
+ /* Project cursor center to screenspace. */
+ getmouseco_areawin(mval);
+ xo= mval[0];
+ yo= mval[1];
+ window_to_3d(dvecp, xo, yo);
+
+ while (1) {
+
+ getmouseco_areawin(mval);
+ window_to_3d(dvec, mval[0], mval[1]);
+
+ scale=1000;
+
+ dx= ((float)mval[0]-(float)xo)*scale;
+ dy= ((float)mval[1]-(float)yo)*scale;
+
+ /* Calc bone length*/
+ lengths= sqrt((dx*dx)+(dy*dy));
+ length = sqrt(((dvec[0]-dvecp[0])*(dvec[0]-dvecp[0]))+((dvec[1]-dvecp[1])*(dvec[1]-dvecp[1]))+((dvec[2]-dvecp[2])*(dvec[2]-dvecp[2])));
+
+ /* Find rotation around screen normal */
+ if (lengths>0.0F) {
+ angle= acos(dy/lengths);
+ if (dx<0.0F)
+ angle*= -1.0F;
+ }
+ else angle= 0.0F;
+
+ /* FIXME: Is there a blender-defined way of making rot and trans matrices? */
+ rmat[0][0]= cos (angle);
+ rmat[0][1]= -sin (angle);
+ rmat[0][2]= 0.0F;
+ rmat[0][3]= 0.0F;
+ rmat[1][0]= sin (angle);
+ rmat[1][1]= cos (angle);
+ rmat[1][2]= 0.0F;
+ rmat[1][3]= 0.0F;
+ rmat[2][0]= 0.0F;
+ rmat[2][1]= 0.0F;
+ rmat[2][2]= 1.0F;
+ rmat[2][3]= 0.0F;
+ rmat[3][0]= cent[0];
+ rmat[3][1]= cent[1];
+ rmat[3][2]= cent[2];
+ rmat[3][3]= 1.0F;
+
+ /* Rotate object's inversemat by the bone's rotation
+ to get the coordinate space of the bone */
+ Mat4CpyMat3 (itmat, imat);
+ Mat4MulMat4 (restmat, rmat, itmat);
+
+ /* Find the bone head */
+ tempVec[0]=0; tempVec[1]=0.0F; tempVec[2]=0.0F; tempVec[3]=1.0F;
+ Mat4MulVec4fl (restmat, tempVec);
+ VECCOPY (bone->head, tempVec);
+
+ /* Find the bone tail */
+ tempVec[0]=0; tempVec[1]=length; tempVec[2]=0.0F; tempVec[3]=1.0F;
+ Mat4MulVec4fl (restmat, tempVec);
+ VECCOPY (bone->tail, tempVec);
+
+ /* IF we're a child of something, add the parents' translates */
+
+ /* Offset of child is new cursor*/
+
+ VECCOPY (newEnd,bone->tail); newEnd[3]=1;
+
+ /* Set the bone's transformations */
+ Mat4One (bone->obmat);
+ bone->size[0]=bone->size[1]=bone->size[2]=1.0F;
+
+ force_draw();
+ while(qtest()) {
+ event= extern_qread(&val);
+ if(val) {
+ switch(event) {
+ case ESCKEY:
+ case RIGHTMOUSE:
+ BLI_freelinkN (&G.edbo,bone);
+ afbreek=1;
+ addbones=0;
+ break;
+ case LEFTMOUSE:
+ case MIDDLEMOUSE:
+ case SPACEKEY:
+ case RETKEY:
+ afbreek= 1;
+
+ Mat4MulVec4fl (G.obedit->obmat,newEnd);
+
+ curs[0]=newEnd[0];
+ curs[1]=newEnd[1];
+ curs[2]=newEnd[2];
+ addbones++;
+ break;
+ } /* End of case*/
+ } /* End of if (val)*/
+ if(afbreek) break;
+ } /* Endd of Qtest loop */
+
+ if(afbreek) break;
+ }/* End of positioning loop (while)*/
+ } /* End of bone adding loop*/
+
+ countall();
+
+}
+
+static void validate_editbonebutton_cb(void *bonev, void *arg2_unused)
+{
+ EditBone *curBone= bonev;
+ validate_editbonebutton(curBone);
+}
+static void parnr_to_editbone_cb(void *bonev, void *arg2_unused)
+{
+ EditBone *curBone= bonev;
+ parnr_to_editbone(curBone);
+}
+static void attach_bone_to_parent_cb(void *bonev, void *arg2_unused)
+{
+ EditBone *curBone= bonev;
+ attach_bone_to_parent(curBone);
+}
+
+void armaturebuts(void)
+{
+ bArmature *arm=NULL;
+ Object *ob=NULL;
+ uiBlock *block=NULL;
+ char str[64];
+ int bx=148, by=100;
+ EditBone *curBone;
+ uiBut *but;
+ char *boneString=NULL;
+ int index;
+
+ ob= OBACT;
+ if (ob==NULL) return;
+
+ sprintf(str, "editbuttonswin %d", curarea->win);
+ block= uiNewBlock (&curarea->uiblocks, str, UI_EMBOSSX, UI_HELV, curarea->win);
+
+ arm= ob->data;
+ if (arm==NULL) return;
+
+ uiBlockSetCol(block, BUTGREEN);
+ uiDefButI(block, TOG|BIT|ARM_RESTPOSBIT,REDRAWVIEW3D, "Rest Pos", bx,by,97,20, &arm->flag, 0, 0, 0, 0, "Disable all animation for this object");
+ uiDefButI(block, TOG|BIT|ARM_DRAWAXESBIT,REDRAWVIEW3D, "Draw Axes", bx,by-46,97,20, &arm->flag, 0, 0, 0, 0, "Draw bone axes");
+ uiDefButI(block, TOG|BIT|ARM_DRAWNAMESBIT,REDRAWVIEW3D, "Draw Names", bx,by-69,97,20, &arm->flag, 0, 0, 0, 0, "Draw bone names");
+
+ uiBlockSetCol(block, BUTGREY);
+
+ /* Draw the bone name block */
+
+ bx+=400; by=200;
+
+ if (G.obedit==ob){
+ uiDefBut(block, LABEL, 0, "Selected Bones", bx,by,128,18, 0, 0, 0, 0, 0, "");
+ by-=20;
+ for (curBone=G.edbo.first, index=0; curBone; curBone=curBone->next, index++){
+ if (curBone->flag & (BONE_SELECTED)){
+
+ /* Hide in posemode flag */
+ uiBlockSetCol(block, BUTGREEN);
+ uiDefButI(block, TOG|BIT|BONE_HIDDENBIT, REDRAWVIEW3D, "Hide", bx-50,by,48,18, &curBone->flag, 0, 0, 0, 0, "Toggles display of this bone in posemode");
+
+ /* Bone naming button */
+ uiBlockSetCol(block, BUTGREY);
+ strcpy (curBone->oldname, curBone->name);
+ but=uiDefBut(block, TEX, REDRAWVIEW3D, "BO:", bx,by,97,18, &curBone->name, 0, 24, 0, 0, "Change the bone name");
+ uiButSetFunc(but, validate_editbonebutton_cb, curBone, NULL);
+
+ uiDefBut(block, LABEL, 0, "child of", bx+106,by,100,18, NULL, 0.0, 0.0, 0.0, 0.0, "");
+
+ boneString = malloc((BLI_countlist(&G.edbo) * 64)+64);
+ build_bonestring (boneString, curBone);
+
+ curBone->parNr = editbone_to_parnr(curBone->parent);
+ but = uiDefButI(block, MENU,REDRAWVIEW3D, boneString, bx+164,by,97,18, &curBone->parNr, 0.0, 0.0, 0.0, 0.0, "Parent");
+ uiButSetFunc(but, parnr_to_editbone_cb, curBone, NULL);
+
+ free(boneString);
+
+ /* IK to parent flag */
+ if (curBone->parent){
+ uiBlockSetCol(block, BUTGREEN);
+ but=uiDefButI(block, TOG|BIT|BONE_IK_TOPARENTBIT, REDRAWVIEW3D, "IK", bx+275,by,32,18, &curBone->flag, 0.0, 0.0, 0.0, 0.0, "IK link to parent");
+ uiButSetFunc(but, attach_bone_to_parent_cb, curBone, NULL);
+ }
+
+ /* Dist and weight buttons */
+ uiBlockSetCol(block, BUTGREY);
+ uiDefButF(block, NUM,REDRAWVIEW3D, "Dist:", bx+320, by, 110, 18, &curBone->dist, 0.0, 1000.0, 10.0, 0.0, "Bone deformation distance");
+ uiDefButF(block, NUM,REDRAWVIEW3D, "Weight:", bx+438, by, 110, 18, &curBone->weight, 0.0F, 1000.0F, 10.0F, 0.0F, "Bone deformation weight");
+
+ by-=19;
+ }
+ }
+ }
+
+ uiDrawBlock (block);
+
+}
+
+static int editbone_to_parnr (EditBone *bone)
+{
+ EditBone *ebone;
+ int index;
+
+ for (ebone=G.edbo.first, index=0; ebone; ebone=ebone->next, index++){
+ if (ebone==bone)
+ return index;
+ }
+
+ return -1;
+}
+
+static void parnr_to_editbone(EditBone *bone)
+{
+ if (bone->parNr == -1){
+ bone->parent = NULL;
+ bone->flag &= ~BONE_IK_TOPARENT;
+ }
+ else{
+ bone->parent = BLI_findlink(&G.edbo, bone->parNr);
+ attach_bone_to_parent(bone);
+ }
+}
+
+static void attach_bone_to_parent(EditBone *bone)
+{
+ EditBone *curbone;
+
+ if (bone->flag & BONE_IK_TOPARENT) {
+
+ /* See if there are any other bones that refer to the same parent and disconnect them */
+ for (curbone = G.edbo.first; curbone; curbone=curbone->next){
+ if (curbone!=bone){
+ if (curbone->parent && (curbone->parent == bone->parent) && (curbone->flag & BONE_IK_TOPARENT))
+ curbone->flag &= ~BONE_IK_TOPARENT;
+ }
+ }
+
+ /* Attach this bone to its parent */
+ VECCOPY(bone->head, bone->parent->tail);
+ }
+
+}
+
+static void build_bonestring (char *string, EditBone *bone){
+ EditBone *curBone;
+ EditBone *pBone;
+ int skip=0;
+ int index;
+
+ sprintf (string, "Parent%%t| %%x%d", -1); /* That space is there for a reason */
+
+ for (curBone = G.edbo.first, index=0; curBone; curBone=curBone->next, index++){
+ /* Make sure this is a valid child */
+ if (curBone != bone){
+ skip=0;
+ for (pBone=curBone->parent; pBone; pBone=pBone->parent){
+ if (pBone==bone){
+ skip=1;
+ break;
+ }
+ }
+
+ if (skip)
+ continue;
+
+ sprintf (string, "%s|%s%%x%d", string, curBone->name, index);
+ }
+ }
+}
+
+static void validate_editbonebutton(EditBone *eBone){
+ EditBone *prev;
+ bAction *act;
+ bActionChannel *chan;
+ Base *base;
+
+ /* Separate the bone from the G.edbo */
+ prev=eBone->prev;
+ BLI_remlink (&G.edbo, eBone);
+
+ /* Validate the name */
+ unique_editbone_name (eBone->name);
+
+ /* Re-insert the bone */
+ if (prev)
+ BLI_insertlink(&G.edbo, prev, eBone);
+ else
+ BLI_addhead (&G.edbo, eBone);
+
+ /* Rename channel if necessary */
+ if (G.obedit)
+ act = G.obedit->action;
+
+ if (act && !act->id.lib){
+ // Find the appropriate channel
+ for (chan = act->chanbase.first; chan; chan=chan->next){
+ if (!strcmp (chan->name, eBone->oldname)){
+ strcpy (chan->name, eBone->name);
+ }
+ }
+ allqueue(REDRAWACTION, 0);
+ }
+
+ /* Update the parenting info of any users */
+ /* Yes, I know this is the worst thing you have ever seen. */
+
+ for (base = G.scene->base.first; base; base=base->next){
+ Object *ob = base->object;
+
+ /* See if an object is parented to this armature */
+ if (ob->parent && ob->partype==PARBONE && (ob->parent->type==OB_ARMATURE) && (ob->parent->data == G.obedit->data)){
+ if (!strcmp(ob->parsubstr, eBone->oldname))
+ strcpy(ob->parsubstr, eBone->name);
+ }
+ }
+
+ exit_editmode(0); /* To ensure new names make it to the edit armature */
+
+}
+
+void deselectall_armature(void)
+/* Actually, it toggles selection, deselecting
+ everything if anything is selected */
+{
+ EditBone *eBone;
+ int sel=1;
+
+
+ /* Determine if there are any selected bones
+ And therefore whether we are selecting or deselecting */
+ for (eBone=G.edbo.first;eBone;eBone=eBone->next){
+ if (eBone->flag & (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL)){
+ sel=0;
+ break;
+ };
+ };
+
+ /* Set the flags */
+ for (eBone=G.edbo.first;eBone;eBone=eBone->next){
+ if (sel)
+ eBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ else
+ eBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ };
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWBUTSEDIT, 0);
+ allqueue(REDRAWBUTSHEAD, 0);
+ allqueue(REDRAWBUTSCONSTRAINT, 0);
+ countall();
+}
+
+void join_armature(void)
+{
+
+ Object *ob;
+ Base *base, *nextbase;
+ ListBase eblist;
+ EditBone *curbone, *next;
+ float mat[4][4], imat[4][4];
+
+ /* Ensure we're not in editmode and that the active object is an armature*/
+ if(G.obedit) return;
+
+ ob= OBACT;
+ if(ob->type!=OB_ARMATURE) return;
+
+ /* Make sure the user wants to continue*/
+ if(okee("Join selected Armatures")==0) return;
+
+ /* Put the active armature into editmode and join the bones from the other one*/
+#if 1
+ enter_editmode();
+#else
+ baselist.first=baselist.last=0;
+ make_boneList(&baselist, &((bArmature*)ob->data)->bonebase, NULL);
+#endif
+
+ for (base=FIRSTBASE; base; base=nextbase) {
+ nextbase = base->next;
+ if (TESTBASE(base)){
+ if ((base->object->type==OB_ARMATURE) && (base->object!=ob)){
+ /* Make a list of editbones */
+ eblist.first=eblist.last=0;
+ make_boneList (&eblist, &((bArmature*)base->object->data)->bonebase,NULL);
+ /* Find the difference matrix */
+ Mat4Invert(imat, ob->obmat);
+ Mat4MulMat4(mat, base->object->obmat, imat);
+
+ /* Copy bones from the object to the edit armature */
+ for (curbone=eblist.first; curbone; curbone=next){
+ next = curbone->next;
+
+ /* Blank out tranformation data */
+ curbone->loc[0]=curbone->loc[1]=curbone->loc[2]=0.0F;
+ curbone->size[0]=curbone->size[1]=curbone->size[2]=1.0F;
+ curbone->quat[0]=curbone->quat[1]=curbone->quat[2]=curbone->quat[3]=0.0F;
+
+ unique_editbone_name (curbone->name);
+
+ /* Transform the bone */
+ {
+ float premat[4][4];
+ float postmat[4][4];
+ float difmat[4][4];
+ float imat[4][4];
+ float temp[4][4];
+ float delta[3];
+
+ /* Get the premat */
+ VecSubf (delta, curbone->tail, curbone->head);
+ make_boneMatrixvr(temp, delta, curbone->roll);
+ Mat4MulMat4 (premat, temp, mat);
+
+ Mat4MulVecfl(mat, curbone->head);
+ Mat4MulVecfl(mat, curbone->tail);
+
+ /* Get the postmat */
+ VecSubf (delta, curbone->tail, curbone->head);
+ make_boneMatrixvr(postmat, delta, curbone->roll);
+
+ /* Find the roll */
+ Mat4Invert (imat, premat);
+ Mat4MulMat4 (difmat, postmat, imat);
+
+ curbone->roll -=atan(difmat[2][0]/difmat[2][2]);
+
+ if (difmat[0][0]<0)
+ curbone->roll +=M_PI;
+
+ }
+#if 1
+ BLI_remlink(&eblist, curbone);
+ BLI_addtail(&G.edbo, curbone);
+#else
+ BLI_remlink(&eblist, curbone);
+ BLI_addtail(&baselist, curbone);
+#endif
+ }
+
+ free_and_unlink_base(base);
+ }
+ }
+ }
+
+#if 1
+ exit_editmode(1);
+#else
+ editbones_to_armature(&baselist, ob);
+ if (baselist.first){
+ BLI_freelistN (&baselist);
+ }
+#endif
+ allqueue(REDRAWVIEW3D, 0);
+
+}
+
+
+static int editbone_name_exists (char *name){
+ EditBone *eBone;
+
+ for (eBone=G.edbo.first; eBone; eBone=eBone->next){
+ if (!strcmp (name, eBone->name))
+ return 1;
+ }
+
+ return 0;
+
+}
+
+static void unique_editbone_name (char *name){
+ char tempname[64];
+ int number;
+ char *dot;
+
+
+ if (editbone_name_exists(name)){
+ /* Strip off the suffix */
+ dot=strchr(name, '.');
+ if (dot)
+ *dot=0;
+
+ for (number = 1; number <=999; number++){
+ sprintf (tempname, "%s.%03d", name, number);
+ if (!editbone_name_exists(tempname)){
+ strcpy (name, tempname);
+ return;
+ }
+ }
+ }
+}
+
+void extrude_armature(void)
+{
+ EditBone *newbone, *curbone, *first=NULL, *partest;
+
+ TEST_EDITARMATURE;
+
+
+ if(okee("Extrude Bone Segments")==0) return;
+
+ /* Duplicate the necessary bones */
+ for (curbone = G.edbo.first; ((curbone) && (curbone!=first)); curbone=curbone->next){
+ if (curbone->flag & (BONE_TIPSEL|BONE_SELECTED)){
+ newbone = MEM_callocN(sizeof(EditBone), "extrudebone");
+
+
+ VECCOPY (newbone->head, curbone->tail);
+ VECCOPY (newbone->tail, newbone->head);
+ newbone->parent = curbone;
+ newbone->flag = BONE_TIPSEL;
+ newbone->flag |= BONE_QUATROT;
+ newbone->weight= curbone->weight;
+ newbone->dist= curbone->dist;
+ Mat4One(newbone->obmat);
+
+ /* See if there are any ik children of the parent */
+ for (partest = G.edbo.first; partest; partest=partest->next){
+ if ((partest->parent == curbone) && (partest->flag & BONE_IK_TOPARENT))
+ break;
+ }
+
+ if (!partest)
+ newbone->flag |= BONE_IK_TOPARENT;
+
+ strcpy (newbone->name, curbone->name);
+ unique_editbone_name(newbone->name);
+
+ /* Add the new bone to the list */
+ BLI_addtail(&G.edbo, newbone);
+ if (!first)
+ first = newbone;
+ }
+
+ /* Deselect the old bone */
+ curbone->flag &= ~(BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL);
+
+ }
+
+ /* Transform the endpoints */
+ countall();
+ transform('g');
+ allqueue(REDRAWBUTSEDIT, 0);
+ allqueue(REDRAWBUTSCONSTRAINT, 0);
+}
+
+void addvert_armature(void)
+{
+/*
+ I haven't decided if it will be possible to add bones in this way.
+ For the moment, we'll use Extrude, or explicit parenting.
+ */
+}
+
+
+
+
+
+void adduplicate_armature(void)
+{
+ EditBone *eBone = NULL;
+ EditBone *curBone;
+ EditBone *firstDup=NULL; /* The beginning of the duplicated bones in the edbo list */
+
+ countall();
+
+ /* Find the selected bones and duplicate them as needed */
+ for (curBone=G.edbo.first; curBone && curBone!=firstDup; curBone=curBone->next){
+ if (curBone->flag & BONE_SELECTED){
+
+ eBone=MEM_callocN(sizeof(EditBone), "addup_editbone");
+ eBone->flag |= BONE_SELECTED;
+
+ /* Copy data from old bone to new bone */
+ memcpy (eBone, curBone, sizeof(EditBone));
+
+ /* Blank out tranformation data */
+ eBone->loc[0]=eBone->loc[1]=eBone->loc[2]=0.0F;
+ eBone->size[0]=eBone->size[1]=eBone->size[2]=1.0F;
+ eBone->quat[0]=eBone->quat[1]=eBone->quat[2]=eBone->quat[3]=0.0F;
+
+ curBone->temp = eBone;
+ eBone->temp = curBone;
+
+ unique_editbone_name (eBone->name);
+ BLI_addtail (&G.edbo, eBone);
+ if (!firstDup)
+ firstDup=eBone;
+ }
+ }
+
+ if (eBone){
+ /* Fix the head and tail */
+ if (eBone->parent && !eBone->parent->flag & BONE_SELECTED){
+ VecSubf (eBone->tail, eBone->tail, eBone->head);
+ VecSubf (eBone->head, eBone->head, eBone->head);
+ }
+ }
+
+ /* Run though the list and fix the pointers */
+ for (curBone=G.edbo.first; curBone && curBone!=firstDup; curBone=curBone->next){
+
+ if (curBone->flag & BONE_SELECTED){
+ eBone=(EditBone*) curBone->temp;
+
+ /* If this bone has no parent,
+ Set the duplicate->parent to NULL
+ */
+ if (!curBone->parent){
+ eBone->parent = NULL;
+ }
+ /* If this bone has a parent that IS selected,
+ Set the duplicate->parent to the curBone->parent->duplicate
+ */
+ else if (curBone->parent->flag & BONE_SELECTED){
+ eBone->parent=(EditBone*) curBone->parent->temp;
+ }
+ /* If this bone has a parent that IS not selected,
+ Set the duplicate->parent to the curBone->parent
+ */
+ else {
+ eBone->parent=(EditBone*) curBone->parent;
+ eBone->flag &= ~BONE_IK_TOPARENT;
+ }
+
+ }
+ }
+
+ /* Deselect the old bones and select the new ones */
+
+ for (curBone=G.edbo.first; curBone && curBone!=firstDup; curBone=curBone->next){
+ curBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ }
+
+
+ transform('g');
+ allqueue(REDRAWBUTSEDIT, 0);
+ allqueue(REDRAWBUTSCONSTRAINT, 0);
+}
+
+/*
+ *
+ * POSING FUNCTIONS: Maybe move these to a separate file at some point
+ *
+ *
+ */
+
+
+void clear_armature(Object *ob, char mode){
+ Bone *curBone;
+ bArmature *arm;
+
+ arm=get_armature(ob);
+
+ if (!arm)
+ return;
+
+ for (curBone=arm->bonebase.first; curBone; curBone=curBone->next){
+ clear_armature_children (curBone, ob->pose, mode);
+ }
+
+ where_is_armature (ob);
+
+}
+
+static void clear_armature_children (Bone *bone, bPose *pose, char mode){
+ Bone *curBone;
+ bPoseChannel *chan;
+ if (!bone)
+ return;
+
+ verify_pose_channel (pose, bone->name);
+ chan=get_pose_channel (pose, bone->name);
+
+ if (!chan)
+ return;
+
+ if (bone->flag & BONE_SELECTED){
+ switch (mode){
+ case 'r':
+ chan->quat[1]=chan->quat[2]=chan->quat[3]=0.0F; chan->quat[0]=1.0F;
+ break;
+ case 'g':
+ chan->loc[0]=chan->loc[1]=chan->loc[2]=0.0F;
+ break;
+ case 's':
+ chan->size[0]=chan->size[1]=chan->size[2]=1.0F;
+ break;
+
+ }
+ }
+
+ for (curBone=bone->childbase.first; curBone; curBone=curBone->next){
+ clear_armature_children (curBone, pose, mode);
+ }
+
+}
+
+void mousepose_armature(void)
+/*
+ Handles right-clicking for selection
+ of bones in armature pose modes.
+*/
+{
+ Bone *nearBone;
+
+ if (!G.obpose)
+ return;
+
+ nearBone = get_nearest_bone(1);
+
+ if (nearBone){
+ if (!(G.qual & LR_SHIFTKEY)){
+ deselectall_posearmature(0);
+ nearBone->flag|=BONE_SELECTED;
+ select_actionchannel_by_name(G.obpose->action, nearBone->name, 1);
+ }
+ else {
+ if (nearBone->flag & BONE_SELECTED){
+ nearBone->flag &= ~BONE_SELECTED;
+ select_actionchannel_by_name(G.obpose->action, nearBone->name, 0);
+ }
+ else{
+ nearBone->flag |= BONE_SELECTED;
+ select_actionchannel_by_name(G.obpose->action, nearBone->name, 1);
+ }
+ };
+ }
+
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWACTION, 0);
+ allqueue(REDRAWIPO, 0); /* To force action ipo update */
+ allqueue(REDRAWBUTSCONSTRAINT, 0);
+
+// countall();
+ rightmouse_transform();
+
+}
+
+void make_trans_bones (char mode)
+/* Used in pose mode */
+{
+ bArmature *arm;
+ Bone *curBone;
+ int count=0;
+
+ transmain=NULL;
+
+ arm=get_armature (G.obpose);
+ if (!arm)
+ return;
+
+ if (arm->flag & ARM_RESTPOS){
+ notice ("Transformation not possible while Rest Position is enabled");
+ return;
+ }
+
+
+ if (!(G.obpose->lay & G.vd->lay))
+ return;
+
+
+ centroid[0]=centroid[1]=centroid[2]=0;
+
+ apply_pose_armature(arm, G.obpose->pose, 0);
+ where_is_armature (G.obpose);
+
+ /* Allocate memory for the transformation record */
+ tottrans= count_bones (arm, BONE_SELECTED, 0);
+
+ if (!tottrans)
+ return;
+
+ transmain= MEM_callocN(tottrans*sizeof(TransOb), "bonetransmain");
+
+ for (curBone=arm->bonebase.first; curBone; curBone=curBone->next){
+ count = add_trans_bonechildren (G.obpose, curBone, transmain, count, mode);
+ }
+
+ tottrans=count;
+
+ if (tottrans){
+ centroid[0]/=tottrans;
+ centroid[1]/=tottrans;
+ centroid[2]/=tottrans;
+ Mat4MulVecfl (G.obpose->obmat, centroid);
+ }
+ else{
+ MEM_freeN (transmain);
+ }
+ return;
+
+}
+
+static int count_bones (bArmature *arm, int flagmask, int allbones)
+{
+ int count=0;
+ Bone *curBone;
+
+ if (!arm)
+ return 0;
+
+ for (curBone=arm->bonebase.first; curBone; curBone=curBone->next){
+ count = count_bonechildren (curBone, count, flagmask, allbones);
+ }
+
+ return count;
+
+}
+
+static int count_bonechildren (Bone *bone, int incount, int flagmask, int allbones){
+
+ Bone *curBone;
+
+ if (!bone)
+ return incount;
+
+ if (bone->flag & flagmask || flagmask == 0xFFFFFFFF){
+ incount++;
+ if (!allbones)
+ return incount;
+ }
+
+ for (curBone=bone->childbase.first; curBone; curBone=curBone->next){
+ incount=count_bonechildren (curBone, incount, flagmask, allbones);
+ }
+
+ return incount;
+}
+
+
+static int add_trans_bonechildren (Object* ob, Bone* bone, TransOb* buffer, int index, char mode)
+{
+ Bone *curBone;
+ TransOb *curOb;
+ float parmat[4][4], tempmat[4][4];
+ float tempobmat[4][4];
+ float vec[3];
+ if (!bone)
+ return index;
+
+
+
+ /* We don't let IK children get "grabbed" */
+ if (bone->flag & BONE_SELECTED){
+ if (!((mode=='g' || mode=='G') && (bone->flag & BONE_IK_TOPARENT))){
+
+ get_bone_root_pos (bone, vec, 1);
+
+ VecAddf (centroid, centroid, vec);
+
+ curOb=&buffer[index];
+
+ curOb->ob = ob;
+ curOb->rot=NULL;
+
+ curOb->quat= bone->quat;
+ curOb->size= bone->size;
+ curOb->loc = bone->loc;
+
+ curOb->data = bone; // FIXME: Dangerous
+
+ memcpy (curOb->oldquat, bone->quat, sizeof (bone->quat));
+ memcpy (curOb->oldsize, bone->size, sizeof (bone->size));
+ memcpy (curOb->oldloc, bone->loc, sizeof (bone->loc));
+
+#if 0
+ if (bone->parent)
+ get_objectspace_bone_matrix(bone->parent, tempmat, 1, 1);
+ else
+ Mat4One (tempmat);
+#else
+ /* Get the matrix of this bone minus the usertransform */
+ Mat4CpyMat4 (tempobmat, bone->obmat);
+ Mat4One (bone->obmat);
+ get_objectspace_bone_matrix(bone, tempmat, 1, 1);
+ Mat4CpyMat4 (bone->obmat, tempobmat);
+
+
+#endif
+
+#if 1
+ Mat4MulMat4 (parmat, tempmat, ob->obmat); /* Original */
+
+ /* Get world transform */
+ get_objectspace_bone_matrix(bone, tempmat, 1, 1);
+ if (ob->parent){
+ where_is_object(ob->parent);
+ Mat4MulSerie (tempobmat, ob->parent->obmat, ob->obmat, tempmat, NULL, NULL, NULL, NULL, NULL);
+ }
+ else
+ Mat4MulSerie (tempobmat, ob->obmat, tempmat, NULL, NULL, NULL, NULL, NULL, NULL);
+ Mat3CpyMat4 (curOb->axismat, tempobmat);
+ Mat3Ortho(curOb->axismat);
+
+#else
+ Mat4MulMat4 (parmat, ob->obmat, tempmat);
+#endif
+ Mat3CpyMat4 (curOb->parmat, parmat);
+ Mat3Inv (curOb->parinv, curOb->parmat);
+
+ Mat3CpyMat4 (curOb->obmat, bone->obmat);
+ Mat3Inv (curOb->obinv, curOb->obmat);
+
+ index++;
+ return index;
+ }
+
+ }
+
+ /* Recursively search */
+ for (curBone = bone->childbase.first; curBone; curBone=curBone->next){
+ index=add_trans_bonechildren (ob, curBone, buffer, index, mode);
+ }
+
+ return index;
+}
+
+static void deselect_bonechildren (Bone *bone, int mode)
+{
+ Bone *curBone;
+
+ if (!bone)
+ return;
+
+ if (mode==0)
+ bone->flag &= ~BONE_SELECTED;
+ else if (!(bone->flag & BONE_HIDDEN))
+ bone->flag |= BONE_SELECTED;
+
+ select_actionchannel_by_name(G.obpose->action, bone->name, mode);
+
+ for (curBone=bone->childbase.first; curBone; curBone=curBone->next){
+ deselect_bonechildren(curBone, mode);
+ }
+}
+
+
+void deselectall_posearmature (int test){
+ int selectmode = 0;
+ Bone* curBone;
+
+ /* Determine if we're selecting or deselecting */
+ if (test){
+ if (!count_bones (get_armature(G.obpose), BONE_SELECTED, 0))
+ selectmode = 1;
+ }
+
+ /* Set the flags accordingly */
+ for (curBone=get_armature(G.obpose)->bonebase.first; curBone; curBone=curBone->next)
+ deselect_bonechildren (curBone, selectmode);
+
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWACTION, 0);
+
+}
+
+void auto_align_armature(void)
+/* Sets the roll value of selected bones so that their zaxes point upwards */
+{
+ EditBone *ebone;
+ float xaxis[3]={1.0, 0.0, 0.0}, yaxis[3], zaxis[3]={0.0, 0.0, 1.0}, ytest[3]={0.0, -1.0, 0.0};
+ float targetmat[4][4], imat[4][4];
+ float curmat[4][4], diffmat[4][4];
+ float delta[3];
+
+ for (ebone = G.edbo.first; ebone; ebone=ebone->next){
+ if (ebone->flag & BONE_SELECTED){
+ /* Find the current bone matrix */
+ VecSubf(delta, ebone->tail, ebone->head);
+ make_boneMatrixvr (curmat, delta, 0.0);
+
+ /* Make new matrix based on y axis & z-up */
+ VECCOPY (yaxis, curmat[1]);
+
+ Mat4One(targetmat);
+ VECCOPY (targetmat[0], xaxis);
+ VECCOPY (targetmat[1], yaxis);
+ VECCOPY (targetmat[2], zaxis);
+ Mat4Ortho(targetmat);
+
+ /* Find the difference between the two matrices */
+
+ Mat4Invert (imat, targetmat);
+ Mat4MulMat4(diffmat, curmat, imat);
+
+ ebone->roll = atan(diffmat[2][0]/diffmat[2][2]);
+
+ }
+ }
+} \ No newline at end of file
diff --git a/source/blender/src/editconstraint.c b/source/blender/src/editconstraint.c
new file mode 100644
index 00000000000..17d59a18192
--- /dev/null
+++ b/source/blender/src/editconstraint.c
@@ -0,0 +1,753 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+
+#include "DNA_action_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_constraint_types.h"
+#include "DNA_curve_types.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_action.h"
+#include "BKE_armature.h"
+#include "BKE_object.h"
+#include "BKE_global.h"
+#include "BKE_constraint.h"
+#include "BKE_ipo.h"
+
+#include "BIF_editarmature.h"
+#include "BIF_editconstraint.h"
+#include "BIF_interface.h"
+#include "BIF_screen.h"
+#include "BIF_toolbox.h"
+
+#include "BSE_editaction.h"
+
+#include "interface.h"
+#include "blendef.h"
+#include "nla.h"
+
+static short add_constraint_element (Object *owner, const char *substring, Object *parent, const char *parentstring);
+static short detect_constraint_loop (Object *owner, const char* substring, int disable);
+static void test_bonelist_constraints (Object *owner, ListBase *list);
+static void clear_object_constraint_loop_flags(Object *ob);
+//static int is_child_of(struct Object *owner, struct Object *parent);
+//static int is_bonechild_of(struct Bone *bone, struct Bone *parent);
+static int is_child_of_ex(Object *owner, const char *ownersubstr, Object *parent, const char *parsubstr);
+
+ListBase g_conBase;
+const char *g_conString;
+Object *g_conObj;
+
+
+void unique_constraint_name (bConstraint *con, ListBase *list){
+ char tempname[64];
+ int number;
+ char *dot;
+ int exists = 0;
+ bConstraint *curcon;
+
+ /* See if we even need to do this */
+ for (curcon = list->first; curcon; curcon=curcon->next){
+ if (curcon!=con){
+ if (!strcmp(curcon->name, con->name)){
+ exists = 1;
+ break;
+ }
+ }
+ }
+
+ if (!exists)
+ return;
+
+ /* Strip off the suffix */
+ dot=strchr(con->name, '.');
+ if (dot)
+ *dot=0;
+
+ for (number = 1; number <=999; number++){
+ sprintf (tempname, "%s.%03d", con->name, number);
+
+ exists = 0;
+ for (curcon=list->first; curcon; curcon=curcon->next){
+ if (con!=curcon){
+ if (!strcmp (curcon->name, tempname)){
+ exists = 1;
+ break;
+ }
+ }
+ }
+ if (!exists){
+ strcpy (con->name, tempname);
+ return;
+ }
+ }
+}
+
+static int is_child_of_ex(Object *owner, const char *ownersubstr, Object *parent, const char *parsubstr)
+{
+ Object *curob;
+ int working = 1;
+ Bone *bone = NULL;
+ Bone *parbone= NULL;
+
+ curob=owner;
+
+ /* If this is a bone */
+ if (strlen(ownersubstr))
+ bone = get_named_bone(get_armature(owner->parent), ownersubstr);
+
+ if (strlen(parsubstr))
+ parbone = get_named_bone(get_armature(parent), parsubstr);
+
+
+ /* Traverse the scene graph */
+ while (curob && !bone){
+ switch (curob->partype){
+ case PARBONE:
+ if (strlen(parsubstr)){
+ bone = get_named_bone(get_armature(curob->parent), curob->parsubstr);
+ break;
+ }
+ /* The break is supposed to be missing */
+ default:
+ if (curob==parent){
+ if (parbone)
+ return 0;
+ else
+ return 1;
+ }
+ curob=curob->parent;
+ }
+ }
+
+
+ /* Descend into the armature scene graph */
+ while (bone){
+ if (bone==parbone)
+ return 1;
+ bone=bone->parent;
+ }
+
+ return 0;
+}
+/*
+static int is_child_of(Object *owner, Object *parent)
+{
+ Object *curpar;
+
+ for (curpar = owner->parent; curpar; curpar=curpar->parent){
+ if (curpar==parent)
+ return 1;
+ }
+
+ return 0;
+}
+
+
+static int is_bonechild_of(Bone *bone, Bone *parent)
+{
+ Bone *curpar;
+
+ if (!bone)
+ return 0;
+
+ for (curpar = bone->parent; curpar; curpar=curpar->parent){
+ if (curpar==parent)
+ return 1;
+ }
+ return 0;
+}
+*/
+static short add_constraint_element (Object *owner, const char *substring, Object *parent, const char *parentstring)
+{
+
+ if (!owner)
+ return 0;
+
+ /* See if this is the original object */
+ if (parent == owner){
+ if (!strcmp (parentstring, substring))
+ return 1;
+ }
+
+ if (owner == g_conObj){
+ if (!strcmp (g_conString, substring))
+ return 1;
+ }
+
+ /* See if this is a child of the adding object */
+ if (parent){
+// if (is_child_of (owner, parent))
+ if (is_child_of_ex (owner, substring, parent, parentstring))
+ return 1;
+ /* Parent is a bone */
+/* if ((owner==parent) && (owner->type == OB_ARMATURE)){
+ if (strlen (substring) && strlen(parentstring)){
+ if (is_bonechild_of(get_named_bone(owner->data, substring), get_named_bone(parent->data, parentstring)))
+ return 1;
+ }
+ }
+ */
+ }
+ return 0;
+}
+
+static void test_bonelist_constraints (Object *owner, ListBase *list)
+{
+ Bone *bone;
+ Base *base1;
+
+
+ for (bone = list->first; bone; bone=bone->next){
+ for (base1 = G.scene->base.first; base1; base1=base1->next){
+ clear_object_constraint_loop_flags(base1->object);
+ }
+ test_constraints(owner, bone->name, 1);
+ test_bonelist_constraints (owner, &bone->childbase);
+ }
+}
+
+
+static void clear_object_constraint_loop_flags(Object *ob)
+{
+ bConstraint *con;
+
+ if (!ob)
+ return;
+
+ /* Test object constraints */
+ for (con = ob->constraints.first; con; con=con->next){
+ con->flag &= ~CONSTRAINT_LOOPTESTED;
+ }
+
+ switch (ob->type){
+ case OB_ARMATURE:
+ if (ob->pose){
+ bPoseChannel *pchan;
+ for (pchan = ob->pose->chanbase.first; pchan; pchan=pchan->next){
+ for (con = pchan->constraints.first; con; con=con->next){
+ con->flag &= ~CONSTRAINT_LOOPTESTED;
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+}
+void test_scene_constraints (void)
+{
+ Base *base, *base1;
+
+/* Clear the "done" flags of all constraints */
+
+ for (base = G.scene->base.first; base; base=base->next){
+ clear_object_constraint_loop_flags(base->object);
+ }
+
+ /* Test all constraints */
+ for (base = G.scene->base.first; base; base=base->next){
+ /* Test the object */
+
+ for (base1 = G.scene->base.first; base1; base1=base1->next)
+ clear_object_constraint_loop_flags(base1->object);
+
+
+ test_constraints (base->object, "", 1);
+
+
+ /* Test the subobject constraints */
+ switch (base->object->type){
+ case OB_ARMATURE:
+ {
+ bArmature *arm;
+ arm = get_armature(base->object);
+ if (arm)
+ test_bonelist_constraints (base->object, &arm->bonebase);
+ }
+ break;
+ default:
+ break;
+ }
+
+
+ }
+}
+
+int test_constraints (Object *owner, const char *substring, int disable)
+{
+/* init_constraint_elements();*/
+ g_conObj = owner;
+ g_conString = substring;
+
+ if (detect_constraint_loop (owner, substring, disable))
+ return 1;
+ else
+ return 0;
+
+/* free_constraint_elements(); */
+}
+
+static short detect_constraint_loop (Object *owner, const char* substring, int disable)
+{
+
+ bConstraint *curcon;
+ ListBase *conlist;
+ int type;
+ int result = 0;
+
+ if (!owner)
+ return result;
+
+ /* Check parents */
+ /* Get the constraint list for this object */
+
+ if (strlen (substring)){
+ switch (owner->type){
+ case OB_ARMATURE:
+ type = TARGET_BONE;
+ break;
+ default:
+ type = TARGET_OBJECT;
+ break;
+ }
+ }
+ else
+ type = TARGET_OBJECT;
+
+
+ switch (type){
+ case TARGET_OBJECT:
+ conlist = &owner->constraints;
+ /* Check parents */
+#if 0
+ if (owner->parent && (ELEM (owner->partype, PAROBJECT, PARBONE))){
+ if (add_constraint_element (owner->parent, "", NULL, NULL)){
+ return 1;
+ }
+ /* if (detect_constraint_loop (owner->parent, "", disable)){
+ return 1;
+ }
+ */
+ }
+ /* Check tracking */
+ if (owner->track && (ELEM (owner->partype, PAROBJECT, PARBONE))){
+ if (add_constraint_element (owner->track, "", NULL, NULL)){
+ return 1;
+ }
+ /* if (detect_constraint_loop (owner->track, "", disable)){
+ return 1;
+ }
+ */
+ }
+#else
+ if (owner->parent && (owner->partype==PAROBJECT))
+ if (add_constraint_element (owner->parent, "", NULL, NULL))
+ return 1;
+
+ if (owner->parent && (owner->partype==PARBONE))
+ if (add_constraint_element (owner->parent, owner->parsubstr, NULL, NULL))
+ return 1;
+
+ /* Check tracking */
+ if (owner->track)
+ if (add_constraint_element (owner->track, "", NULL, NULL))
+ return 1;
+#endif
+
+ break;
+ case TARGET_BONE:
+ {
+ Bone *bone;
+ bPoseChannel *chan;
+
+ bone = get_named_bone(((bArmature*)owner->data), substring);
+ chan = get_pose_channel (owner->pose, substring);
+ if (bone){
+ conlist = &chan->constraints;
+ if (bone->parent){
+ if (add_constraint_element (owner, bone->parent->name, NULL, NULL))
+ return 1;
+ if (detect_constraint_loop (owner, bone->parent->name, disable))
+ return 1;
+ }
+ else{
+ if (add_constraint_element (owner, "", NULL, NULL))
+ return 1;
+ if (detect_constraint_loop (owner, "", disable))
+ return 1;
+ }
+ }
+ else
+ conlist = NULL;
+ }
+ break;
+ default:
+ conlist = NULL;
+ break;
+ }
+
+ /* Cycle constraints */
+ if (conlist){
+ for (curcon = conlist->first; curcon; curcon=curcon->next){
+
+ /* Clear the disable flag */
+
+ if (curcon->flag & CONSTRAINT_LOOPTESTED){
+ return 0;
+ }
+ else {
+ curcon->flag &= ~CONSTRAINT_DISABLE;
+ curcon->flag |= CONSTRAINT_LOOPTESTED;
+ switch (curcon->type){
+ case CONSTRAINT_TYPE_ACTION:
+ {
+ bActionConstraint *data = curcon->data;
+
+ if (!exist_object(data->tar)){
+ data->tar = NULL;
+ break;
+ }
+
+ if (add_constraint_element (data->tar, data->subtarget, owner, substring)){
+ curcon->flag |= CONSTRAINT_DISABLE;
+ result = 1;
+ break;
+ // return 1;
+ }
+ if (detect_constraint_loop (data->tar, data->subtarget, disable)){
+ curcon->flag |= CONSTRAINT_DISABLE;
+ result = 1;
+ break;
+ // return 1;
+ }
+ }
+ break;
+ case CONSTRAINT_TYPE_LOCLIKE:
+ {
+ bLocateLikeConstraint *data = curcon->data;
+
+ if (!exist_object(data->tar)){
+ data->tar = NULL;
+ break;
+ }
+
+ if (add_constraint_element (data->tar, data->subtarget, owner, substring)){
+ curcon->flag |= CONSTRAINT_DISABLE;
+ result = 1;
+ break;
+ // return 1;
+ }
+ if (detect_constraint_loop (data->tar, data->subtarget, disable)){
+ curcon->flag |= CONSTRAINT_DISABLE;
+ result = 1;
+ break;
+ // return 1;
+ }
+ }
+ break;
+ case CONSTRAINT_TYPE_ROTLIKE:
+ {
+ bRotateLikeConstraint *data = curcon->data;
+
+ if (!exist_object(data->tar)){
+ data->tar = NULL;
+ break;
+ }
+
+ if (add_constraint_element (data->tar, data->subtarget, owner, substring)){
+ curcon->flag |= CONSTRAINT_DISABLE;
+ result = 1;
+ break;
+ // return 1;
+ }
+ if (detect_constraint_loop (data->tar, data->subtarget, disable)){
+ curcon->flag |= CONSTRAINT_DISABLE;
+ result = 1;
+ break;
+ // return 1;
+ }
+ }
+ break;
+ case CONSTRAINT_TYPE_KINEMATIC:
+ {
+ bKinematicConstraint *data = curcon->data;
+ if (!exist_object(data->tar)){
+ data->tar = NULL;
+ break;
+ }
+
+ if (add_constraint_element (data->tar, data->subtarget, owner, substring)){
+ curcon->flag |= CONSTRAINT_DISABLE;
+ result = 1;
+ break;
+ // return 1;
+ }
+ if (detect_constraint_loop (data->tar, data->subtarget, disable)){
+ curcon->flag |= CONSTRAINT_DISABLE;
+ result = 1;
+ break;
+ // return 1;
+ }
+ }
+ break;
+ case CONSTRAINT_TYPE_TRACKTO:
+ {
+ bTrackToConstraint *data = curcon->data;
+ if (!exist_object(data->tar)) data->tar = NULL;
+
+ if (add_constraint_element (data->tar, data->subtarget, owner, substring)){
+ curcon->flag |= CONSTRAINT_DISABLE;
+ result = 1;
+ break;
+ // return 1;
+ }
+ if (detect_constraint_loop (data->tar, data->subtarget, disable)){
+ curcon->flag |= CONSTRAINT_DISABLE;
+ result = 1;
+ break;
+ // return 1;
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ return result;
+}
+
+ListBase *get_constraint_client_channels (int forcevalid)
+{
+
+ Object *ob;
+ char ipstr[64];
+
+ ob=OBACT;
+
+ if (!ob)
+ return NULL;
+
+ /* See if we are a bone constraint */
+ if (G.obpose){
+ switch (G.obpose->type){
+ case OB_ARMATURE:
+ {
+ bActionChannel *achan;
+ Bone *bone;
+
+ bone = get_first_selected_bone();
+ if (!bone) break;
+
+ /* Make sure we have an action */
+ if (!G.obpose->action){
+ if (!forcevalid)
+ return NULL;
+
+ G.obpose->action=add_empty_action();
+ }
+
+ /* Make sure we have an actionchannel */
+ achan = get_named_actionchannel(G.obpose->action, bone->name);
+ if (!achan){
+ if (!forcevalid)
+ return NULL;
+
+ achan = MEM_callocN (sizeof(bActionChannel), "actionChannel");
+
+ strcpy (achan->name, bone->name);
+ sprintf (ipstr, "%s.%s", G.obpose->action->id.name+2, achan->name);
+ ipstr[23]=0;
+ achan->ipo= add_ipo(ipstr, ID_AC);
+
+ BLI_addtail (&G.obpose->action->chanbase, achan);
+ }
+
+ return &achan->constraintChannels;
+ }
+ }
+ }
+
+ return &ob->constraintChannels;
+}
+
+ListBase *get_constraint_client(char *name, short *clientType, void **clientdata)
+{
+ Object *ob;
+ ListBase *list;
+
+ ob=OBACT;
+ if (clientType)
+ *clientType = -1;
+
+ if (!ob)
+ return NULL;
+
+ list = &ob->constraints;
+
+ /* Prep the object's constraint channels */
+ if (clientType)
+ *clientType = TARGET_OBJECT;
+
+ if (name)
+ strcpy (name, ob->id.name+2);
+
+ if (G.obpose){
+ switch (G.obpose->type){
+ case OB_ARMATURE:
+ {
+ Bone *bone;
+
+ bone = get_first_selected_bone();
+ if (!bone) break;
+
+ {
+ bPoseChannel *chan;
+
+ /* Is the bone the client? */
+ if (clientType)
+ *clientType = TARGET_BONE;
+ if (clientdata)
+ *clientdata = bone;
+ if (name)
+ sprintf (name, "%s>>%s", name, bone->name);
+ verify_pose_channel(G.obpose->pose, bone->name);
+ chan = get_pose_channel (G.obpose->pose, bone->name);
+ list = &chan->constraints;
+
+ }
+ }
+ break;
+ }
+ }
+
+ return list;
+}
+
+void *new_constraint_data (short type)
+{
+ void *result;
+
+ switch (type){
+ case CONSTRAINT_TYPE_KINEMATIC:
+ {
+ bKinematicConstraint *data;
+ data = MEM_callocN(sizeof(bKinematicConstraint), "kinematicConstraint");
+
+ data->tolerance = 0.001;
+ data->iterations = 500;
+
+ result = data;
+ }
+ break;
+ case CONSTRAINT_TYPE_NULL:
+ {
+ result = NULL;
+ }
+ break;
+ case CONSTRAINT_TYPE_TRACKTO:
+ {
+ bTrackToConstraint *data;
+ data = MEM_callocN(sizeof(bTrackToConstraint), "tracktoConstraint");
+
+ result = data;
+
+ }
+ break;
+ case CONSTRAINT_TYPE_ROTLIKE:
+ {
+ bRotateLikeConstraint *data;
+ data = MEM_callocN(sizeof(bRotateLikeConstraint), "rotlikeConstraint");
+
+ result = data;
+ }
+ break;
+ case CONSTRAINT_TYPE_LOCLIKE:
+ {
+ bLocateLikeConstraint *data;
+ data = MEM_callocN(sizeof(bLocateLikeConstraint), "loclikeConstraint");
+
+ data->flag |= LOCLIKE_X|LOCLIKE_Y|LOCLIKE_Z;
+ result = data;
+ }
+ break;
+ case CONSTRAINT_TYPE_ACTION:
+ {
+ bActionConstraint *data;
+ data = MEM_callocN(sizeof(bActionConstraint), "actionConstraint");
+
+ result = data;
+ }
+ break;
+ default:
+ result = NULL;
+ break;
+ }
+
+ return result;
+}
+
+bConstraint * add_new_constraint(void)
+{
+ bConstraint *con;
+
+ con = MEM_callocN(sizeof(bConstraint), "constraint");
+
+ /* Set up a generic constraint datablock */
+ con->type = CONSTRAINT_TYPE_TRACKTO;
+ con->flag |= CONSTRAINT_EXPAND;
+ con->enforce=1.0F;
+ /* Load the data for it */
+ con->data = new_constraint_data(con->type);
+ strcpy (con->name, "Const");
+ return con;
+}
+
+bConstraintChannel *add_new_constraint_channel(const char* name)
+{
+ bConstraintChannel *chan = NULL;
+
+ chan = MEM_callocN(sizeof(bConstraintChannel), "constraintChannel");
+ strcpy(chan->name, name);
+
+ return chan;
+} \ No newline at end of file
diff --git a/source/blender/src/editcurve.c b/source/blender/src/editcurve.c
new file mode 100644
index 00000000000..023fa1bba27
--- /dev/null
+++ b/source/blender/src/editcurve.c
@@ -0,0 +1,3979 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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>
+#ifndef WIN32
+#include <unistd.h>
+#else
+#include <io.h>
+#include "BLI_winstuff.h"
+#endif
+#include <stdlib.h>
+#include "MEM_guardedalloc.h"
+
+#include "BMF_Api.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+
+#include "DNA_curve_types.h"
+#include "DNA_ipo_types.h"
+#include "DNA_key_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_view3d_types.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_library.h"
+#include "BKE_ipo.h"
+#include "BKE_displist.h"
+#include "BKE_curve.h"
+#include "BKE_global.h"
+#include "BKE_object.h"
+#include "BKE_main.h"
+
+#include "BIF_gl.h"
+#include "BIF_graphics.h"
+#include "BIF_screen.h"
+#include "BIF_toolbox.h"
+#include "BIF_space.h"
+#include "BIF_editkey.h"
+#include "BIF_mywindow.h"
+#include "BIF_interface.h"
+
+#include "BSE_view.h" /* For persp... */
+#include "BSE_edit.h"
+
+#include "BDR_drawobject.h"
+#include "BDR_editcurve.h"
+#include "BDR_editobject.h"
+
+/* #include "graphics.h" */
+#include "interface.h" /* MAART: for NUM and FLO types, + pupmenu */
+/* #include "edit.h" */
+#include "mydevice.h"
+#include "blendef.h"
+
+
+#include "BDR_editcurve.h"
+/* still need to eradicate a few :( */
+#define callocstructN(x,y,name) (x*)MEM_callocN((y)* sizeof(x),name)
+/* only used sparingly: */
+#define BEZSELECTED(bezt) (((bezt)->f1 & 1) || ((bezt)->f2 & 1) || ((bezt)->f3 & 1))
+
+
+ListBase editNurb;
+BPoint *lastselbp;
+Nurb *lastnu; /* voor selected */
+
+
+/* void freeNurblist(ListBase *lb); already declared in the kernel */
+
+float nurbcircle[8][2]= {
+ {0.0, -1.0}, {-1.0, -1.0}, {-1.0, 0.0}, {-1.0, 1.0},
+ {0.0, 1.0}, { 1.0, 1.0}, { 1.0, 0.0}, { 1.0, -1.0}
+};
+
+short isNurbsel(Nurb *nu)
+{
+ BezTriple *bezt;
+ BPoint *bp;
+ int a;
+
+ if((nu->type & 7)==CU_BEZIER) {
+ bezt= nu->bezt;
+ a= nu->pntsu;
+ while(a--) {
+ if( (bezt->f1 & 1) || (bezt->f2 & 1) || (bezt->f3 & 1) ) return 1;
+ bezt++;
+ }
+ }
+ else {
+ bp= nu->bp;
+ a= nu->pntsu*nu->pntsv;
+ while(a--) {
+ if( (bp->f1 & 1) ) return 1;
+ bp++;
+ }
+ }
+ return 0;
+}
+
+int isNurbsel_count(Nurb *nu)
+{
+ BezTriple *bezt;
+ BPoint *bp;
+ int a, sel=0;
+
+ if((nu->type & 7)==CU_BEZIER) {
+ bezt= nu->bezt;
+ a= nu->pntsu;
+ while(a--) {
+ if( (bezt->f1 & 1) || (bezt->f2 & 1) || (bezt->f3 & 1) ) sel++;
+ bezt++;
+ }
+ }
+ else {
+ bp= nu->bp;
+ a= nu->pntsu*nu->pntsv;
+ while(a--) {
+ if( (bp->f1 & 1) ) sel++;
+ bp++;
+ }
+ }
+ return sel;
+}
+
+
+void printknots()
+{
+ Nurb *nu;
+ int a, num;
+
+ nu= editNurb.first;
+ while(nu) {
+ if(isNurbsel(nu) && (nu->type & 7)==CU_NURBS) {
+ if(nu->knotsu) {
+ num= KNOTSU(nu);
+ for(a=0;a<num;a++) printf("knotu %d: %f\n", a, nu->knotsu[a]);
+ }
+ if(nu->knotsv) {
+ num= KNOTSV(nu);
+ for(a=0;a<num;a++) printf("knotv %d: %f\n", a, nu->knotsv[a]);
+ }
+ }
+ nu= nu->next;
+ }
+}
+
+#if 0
+static void printweightsNurb(void)
+{
+ Nurb *nu;
+ BPoint *bp;
+ int a;
+ char str[30];
+
+ if(G.obedit==0) return;
+
+ persp(0);
+
+ glDrawBuffer(GL_FRONT);
+
+ nu= editNurb.first;
+ while(nu) {
+ if((nu->type & 7)==CU_NURBS) {
+ a= nu->pntsu*nu->pntsv;
+ bp= nu->bp;
+ while(a--) {
+ if(bp->f1 & 1) {
+ if(bp->s[0]!= 3200) {
+ sprintf(str,"%2.2f", bp->vec[3]);
+
+ cpack(0x737373);
+ glRasterPos2i(bp->s[0]-1, bp->s[1]-1);
+ BMF_DrawString(G.font, str);
+
+ glRasterPos2i(bp->s[0]+1, bp->s[1]+1);
+ BMF_DrawString(G.font, str);
+
+ cpack(0xFFFFFF);
+ glRasterPos2i(bp->s[0], bp->s[1]);
+ BMF_DrawString(G.font, str);
+ }
+ }
+ bp++;
+ }
+ }
+ nu= nu->next;
+ }
+
+ glDrawBuffer(GL_BACK);
+ persp(1);
+}
+#endif
+
+
+/* ********************* LOAD EN MAKE *************** */
+
+void load_editNurb()
+{
+ /* laad editNurb in object */
+ Curve *cu= 0;
+ Nurb *nu, *newnu;
+ KeyBlock *actkey=0;
+
+ if(G.obedit==0) return;
+
+ if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
+
+ G.totvert= count_curveverts(&editNurb);
+
+ cu= G.obedit->data;
+
+ /* zijn er keys? */
+ if(cu->key) {
+ actkey= cu->key->block.first;
+ while(actkey) {
+ if(actkey->flag & SELECT) break;
+ actkey= actkey->next;
+ }
+
+ if(actkey) {
+ /* aktieve key: de vertices */
+
+ if(G.totvert) {
+ if(actkey->data) MEM_freeN(actkey->data);
+
+ actkey->data= MEM_callocN(cu->key->elemsize*G.totvert, "actkey->data");
+ actkey->totelem= G.totvert;
+
+ curve_to_key(cu, actkey, &editNurb);
+ }
+ }
+ }
+
+ if(cu->key && actkey!=cu->key->refkey) {
+ /* er zijn keys, alleen veranderingen in verts schrijven */
+ /* als aantal vertices verschillen, beetje onvoorspelbaar */
+
+ /* vertex -> vertex copy! */
+ if(actkey) key_to_curve(actkey, cu, &cu->nurb);
+ }
+ else {
+ freeNurblist(&(cu->nurb));
+
+ nu= editNurb.first;
+ while(nu) {
+ newnu= duplicateNurb(nu);
+ newnu->hide= 0;
+ BLI_addtail(&(cu->nurb), newnu);
+
+ if((nu->type & 7)==CU_NURBS) {
+ if(nu->pntsu < nu->orderu) nu->orderu= nu->pntsu;
+ }
+
+ nu= nu->next;
+ }
+ }
+
+ }
+
+ lastnu= 0; /* voor selected */
+
+}
+
+void make_editNurb()
+{
+ /* maak kopie van baseNurb in editNurb */
+ Curve *cu=0;
+ Nurb *nu, *newnu;
+ BezTriple *bezt;
+ BPoint *bp;
+ KeyBlock *actkey=0;
+ int a, tot=0;
+
+ if(G.obedit==0) return;
+
+ lastselbp= 0; /* global voor select row */
+
+ if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
+ freeNurblist(&editNurb);
+
+ cu= G.obedit->data;
+ nu= cu->nurb.first;
+
+ while(nu) {
+ newnu= duplicateNurb(nu);
+ BLI_addtail(&editNurb, newnu);
+ /* flags op nul */
+ newnu->hide= 0;
+ if((nu->type & 7)==CU_BEZIER) {
+ a= nu->pntsu;
+ bezt= newnu->bezt;
+ while(a--) {
+ bezt->f1= bezt->f2= bezt->f3= bezt->hide= 0;
+ bezt++;
+ tot+= 3;
+ }
+ }
+ else {
+ a= nu->pntsu*nu->pntsv;
+ bp= newnu->bp;
+ while(a--) {
+ bp->f1= bp->hide= 0;
+ bp++;
+ tot++;
+ }
+ }
+ nu= nu->next;
+ }
+
+ if(cu->key) {
+ actkey= cu->key->block.first;
+ while(actkey) {
+ if(actkey->flag & SELECT) break;
+ actkey= actkey->next;
+ }
+
+ if(actkey) {
+ key_to_curve(actkey, cu, &editNurb);
+ }
+ }
+ makeDispList(G.obedit);
+ }
+ else G.obedit= 0;
+
+ countall();
+
+ lastnu= 0; /* voor selected */
+}
+
+void remake_editNurb()
+{
+
+ if(okee("Reload Original data")==0) return;
+
+ make_editNurb();
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWBUTSEDIT, 0);
+}
+
+
+void separate_nurb()
+{
+ Nurb *nu, *nu1;
+ Object *oldob;
+ Base *base, *oldbase;
+ Curve *cu;
+ ListBase editnurbo;
+ float trans[9];
+
+ if( (G.vd->lay & G.obedit->lay)==0 ) return;
+
+ if(okee("Separate")==0) return;
+
+ waitcursor(1);
+
+ cu= G.obedit->data;
+ if(cu->key) {
+ error("Can't separate with vertex keys");
+ return;
+ }
+
+ /* we gaan de zaak als volgt neppen:
+ * 1. duplicate base: dit wordt de nieuwe, oude pointer onthouden
+ * 2. alle NIET geselecteerde curves/nurbs apart zetten
+ * 3. load_ebaseNurb(): dit is de nieuwe base
+ * 4. freelist en oude nurbs weer terughalen
+ */
+
+ /* alleen ebase geselecteerd */
+ base= FIRSTBASE;
+ while(base) {
+ if(base->lay & G.vd->lay) {
+ if(base->object==G.obedit) base->flag |= 1;
+ else base->flag &= ~1;
+ }
+ base= base->next;
+ }
+
+ /* apart zetten: alles wat maar enigszins NIET select is */
+ editnurbo.first= editnurbo.last= 0;
+ nu= editNurb.first;
+ while(nu) {
+ nu1= nu->next;
+ if(isNurbsel(nu)==0) {
+ BLI_remlink(&editNurb, nu);
+ BLI_addtail(&editnurbo, nu);
+ }
+ nu= nu1;
+ }
+
+ oldob= G.obedit;
+ oldbase= BASACT;
+
+ trans[0]=trans[1]=trans[2]=trans[3]=trans[4]=trans[5]= 0.0;
+ trans[6]=trans[7]=trans[8]= 1.0;
+ G.qual |= LR_ALTKEY; /* patch om zeker te zijn van gelinkte dupli */
+ adduplicate(trans);
+ G.qual &= ~LR_ALTKEY;
+
+ G.obedit= BASACT->object; /* basact wordt in adduplicate() gezet */
+
+ G.obedit->data= copy_curve(cu);
+ /* omdat nieuwe curve een kopie is: aantal users verlagen */
+ cu->id.us--;
+
+ load_editNurb();
+
+ BASACT->flag &= ~SELECT;
+
+ if(editNurb.first) freeNurblist(&editNurb);
+
+ editNurb= editnurbo;
+
+ G.obedit= 0; /* displisten doen anders in editmode */
+ makeDispList(OBACT); /* de gesepareerde */
+
+ G.obedit= oldob;
+ BASACT= oldbase;
+ BASACT->flag |= SELECT;
+
+ waitcursor(0);
+
+ countall();
+ allqueue(REDRAWVIEW3D, 0);
+
+ lastnu= 0; /* voor selected */
+}
+
+/* ******************* FLAGS ********************* */
+
+
+short isNurbselUV(Nurb *nu, int *u, int *v, int flag)
+/*
+Nurb *nu;
+int *u, *v, flag;
+*/
+{
+ /* return u!=-1: 1 rij in u-richting geselecteerd. U heeft de waarde tussen 0-pntsv
+ * return v!=-1: 1 kolom in v-richting geselecteerd. V heeft de waarde tussen 0-pntsu
+ */
+ BPoint *bp;
+ int a, b, sel;
+
+ *u= *v= -1;
+
+ bp= nu->bp;
+ for(b=0; b<nu->pntsv; b++) {
+ sel= 0;
+ for(a=0; a<nu->pntsu; a++, bp++) {
+ if(bp->f1 & flag) sel++;
+ }
+ if(sel==nu->pntsu) {
+ if(*u== -1) *u= b;
+ else return 0;
+ }
+ else if(sel>1) return 0; /* want sel==1 is nog goed */
+ }
+
+ for(a=0; a<nu->pntsu; a++) {
+ sel= 0;
+ bp= nu->bp+a;
+ for(b=0; b<nu->pntsv; b++, bp+=nu->pntsu) {
+ if(bp->f1 & flag) sel++;
+ }
+ if(sel==nu->pntsv) {
+ if(*v== -1) *v= a;
+ else return 0;
+ }
+ else if(sel>1) return 0;
+ }
+
+ if(*u==-1 && *v>-1) return 1;
+ if(*v==-1 && *u>-1) return 1;
+ return 0;
+}
+
+void setflagsNurb(short flag)
+/* short flag; */
+{
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ int a;
+
+ nu= editNurb.first;
+ while(nu) {
+ if( (nu->type & 7)==CU_BEZIER) {
+ a= nu->pntsu;
+ bezt= nu->bezt;
+ while(a--) {
+ bezt->f1= bezt->f2= bezt->f3= flag;
+ bezt++;
+ }
+ }
+ else {
+ a= nu->pntsu*nu->pntsv;
+ bp= nu->bp;
+ while(a--) {
+ bp->f1= flag;
+ bp++;
+ }
+ }
+ nu= nu->next;
+ }
+}
+
+void rotateflagNurb(short flag, float *cent, float rotmat[][3])
+{
+ /* alle verts met (flag & 'flag') rotate */
+ Nurb *nu;
+ BPoint *bp;
+ int a;
+
+ nu= editNurb.first;
+ while(nu) {
+ if((nu->type & 7)==CU_NURBS) {
+ bp= nu->bp;
+ a= nu->pntsu*nu->pntsv;
+
+ while(a--) {
+ if(bp->f1 & flag) {
+ bp->vec[0]-=cent[0];
+ bp->vec[1]-=cent[1];
+ bp->vec[2]-=cent[2];
+ Mat3MulVecfl(rotmat, bp->vec);
+ bp->vec[0]+=cent[0];
+ bp->vec[1]+=cent[1];
+ bp->vec[2]+=cent[2];
+ }
+ bp++;
+ }
+ }
+ nu= nu->next;
+ }
+}
+
+
+void translateflagNurb(short flag, float *vec)
+{
+ /* alle verts met (->f & flag) translate */
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ int a;
+
+ nu= editNurb.first;
+ while(nu) {
+ if( (nu->type & 7)==CU_BEZIER) {
+ a= nu->pntsu;
+ bezt= nu->bezt;
+ while(a--) {
+ if(bezt->f1 & flag) VecAddf(bezt->vec[0], bezt->vec[0], vec);
+ if(bezt->f2 & flag) VecAddf(bezt->vec[1], bezt->vec[1], vec);
+ if(bezt->f3 & flag) VecAddf(bezt->vec[2], bezt->vec[2], vec);
+ bezt++;
+ }
+ }
+ else {
+ a= nu->pntsu*nu->pntsv;
+ bp= nu->bp;
+ while(a--) {
+ if(bp->f1 & flag) VecAddf(bp->vec, bp->vec, vec);
+ bp++;
+ }
+ }
+
+ test2DNurb(nu);
+
+ nu= nu->next;
+ }
+}
+
+void weightflagNurb(short flag, float w, int mode) /* mode==0: vervangen, mode==1: vermenigvuldigen */
+{
+ Nurb *nu;
+ BPoint *bp;
+ int a;
+
+ nu= editNurb.first;
+ while(nu) {
+ if((nu->type & 7)==CU_NURBS) {
+ a= nu->pntsu*nu->pntsv;
+ bp= nu->bp;
+ while(a--) {
+ if(bp->f1 & flag) {
+ if(mode==1) bp->vec[3]*= w;
+ else bp->vec[3]= w;
+ }
+ bp++;
+ }
+ }
+ nu= nu->next;
+ }
+}
+
+void deleteflagNurb(short flag)
+{
+ Nurb *nu, *next;
+ BPoint *bp, *bpn, *newbp;
+ int a, b, newu, newv, sel;
+
+ if(G.obedit && G.obedit->type==OB_SURF);
+ else return;
+
+ lastselbp= 0;
+
+ nu= editNurb.first;
+ while(nu) {
+ next= nu->next;
+
+ /* is de hele nurb geselecteerd */
+ bp= nu->bp;
+ a= nu->pntsu*nu->pntsv;
+ while(a) {
+ a--;
+ if(bp->f1 & flag);
+ else break;
+ bp++;
+ }
+ if(a==0) {
+ BLI_remlink(&editNurb, nu);
+ freeNurb(nu);
+ }
+ else {
+ /* is de nurb in U richting geselecteerd */
+ newv= nu->pntsv;
+ bp= nu->bp;
+ for(b=0; b<nu->pntsv; b++) {
+ sel= 0;
+ for(a=0; a<nu->pntsu; a++, bp++) {
+ if(bp->f1 & flag) sel++;
+ }
+ if(sel==nu->pntsu) {
+ newv--;
+ }
+ else if(sel>=1) {
+ /* don't delete */
+ break;
+ }
+ }
+ if(newv!=nu->pntsv && b==nu->pntsv) {
+ /* deleten */
+ bp= nu->bp;
+ bpn = newbp =
+ (BPoint*) MEM_mallocN(newv * nu->pntsu * sizeof(BPoint), "deleteNurb");
+ for(b=0; b<nu->pntsv; b++) {
+ if((bp->f1 & flag)==0) {
+ memcpy(bpn, bp, nu->pntsu*sizeof(BPoint));
+ bpn+= nu->pntsu;
+ }
+ bp+= nu->pntsu;
+ }
+ nu->pntsv= newv;
+ MEM_freeN(nu->bp);
+ nu->bp= newbp;
+ if(nu->orderv>nu->pntsv) nu->orderv= nu->pntsv;
+
+ makeknots(nu, 2, nu->flagv>>1);
+ }
+ else {
+ /* is de nurb in V richting geselecteerd */
+ newu= nu->pntsu;
+ for(a=0; a<nu->pntsu; a++) {
+ bp= nu->bp+a;
+ sel= 0;
+ for(b=0; b<nu->pntsv; b++, bp+=nu->pntsu) {
+ if(bp->f1 & flag) sel++;
+ }
+ if(sel==nu->pntsv) {
+ newu--;
+ }
+ else if(sel>=1) {
+ /* don't delete */
+ break;
+ }
+ }
+ if(newu!=nu->pntsu && a==nu->pntsu) {
+ /* deleten */
+ bp= nu->bp;
+ bpn = newbp =
+ (BPoint*) MEM_mallocN(newu * nu->pntsv * sizeof(BPoint), "deleteNurb");
+ for(b=0; b<nu->pntsv; b++) {
+ for(a=0; a<nu->pntsu; a++, bp++) {
+ if((bp->f1 & flag)==0) {
+ *bpn= *bp;
+ bpn++;
+ }
+ }
+ }
+ MEM_freeN(nu->bp);
+ nu->bp= newbp;
+ if(newu==1 && nu->pntsv>1) { /* maak een U spline */
+ nu->pntsu= nu->pntsv;
+ nu->pntsv= 1;
+ SWAP(short, nu->orderu, nu->orderv);
+ if(nu->orderu>nu->pntsu) nu->orderu= nu->pntsu;
+ if(nu->knotsv) MEM_freeN(nu->knotsv);
+ nu->knotsv= 0;
+ }
+ else {
+ nu->pntsu= newu;
+ if(nu->orderu>nu->pntsu) nu->orderu= nu->pntsu;
+ }
+ makeknots(nu, 1, nu->flagu>>1);
+ }
+ }
+ }
+ nu= next;
+ }
+}
+
+short extrudeflagNurb(int flag)
+/* int flag; */
+{
+ Nurb *nu;
+ BPoint *bp, *bpn, *newbp;
+ int ok= 0, a, u, v, len;
+
+ if(G.obedit && G.obedit->type==OB_SURF);
+ else return 0;
+
+ nu= editNurb.first;
+ while(nu) {
+
+ if(nu->pntsv==1) {
+ bp= nu->bp;
+ a= nu->pntsu;
+ while(a) {
+ if(bp->f1 & flag);
+ else break;
+ bp++;
+ a--;
+ }
+ if(a==0) {
+ ok= 1;
+ newbp =
+ (BPoint*)MEM_mallocN(2 * nu->pntsu * sizeof(BPoint), "extrudeNurb1");
+ memcpy(newbp, nu->bp, nu->pntsu*sizeof(BPoint) );
+ bp= newbp+ nu->pntsu;
+ memcpy(bp, nu->bp, nu->pntsu*sizeof(BPoint) );
+ MEM_freeN(nu->bp);
+ nu->bp= newbp;
+ a= nu->pntsu;
+ while(a--) {
+ bp->f1 |= flag;
+ newbp->f1 &= ~flag;
+ bp++;
+ newbp++;
+ }
+
+ nu->pntsv= 2;
+ nu->orderv= 2;
+ makeknots(nu, 2, nu->flagv>>1);
+ }
+ }
+ else {
+ /* welke rij of kolom is geselecteerd */
+
+ if( isNurbselUV(nu, &u, &v, flag) ) {
+
+ /* alles deselecteren */
+ bp= nu->bp;
+ a= nu->pntsu*nu->pntsv;
+ while(a--) {
+ bp->f1 &= ~flag;
+ bp++;
+ }
+
+ if(u==0 || u== nu->pntsv-1) { /* rij in u-richting geselecteerd */
+ ok= 1;
+ newbp =
+ (BPoint*) MEM_mallocN(nu->pntsu*(nu->pntsv + 1)
+ * sizeof(BPoint), "extrudeNurb1");
+ if(u==0) {
+ len= nu->pntsv*nu->pntsu;
+ memcpy(newbp+nu->pntsu, nu->bp, len*sizeof(BPoint) );
+ memcpy(newbp, nu->bp, nu->pntsu*sizeof(BPoint) );
+ bp= newbp;
+ }
+ else {
+ len= nu->pntsv*nu->pntsu;
+ memcpy(newbp, nu->bp, len*sizeof(BPoint) );
+ memcpy(newbp+len, nu->bp+len-nu->pntsu, nu->pntsu*sizeof(BPoint) );
+ bp= newbp+len;
+ }
+
+ a= nu->pntsu;
+ while(a--) {
+ bp->f1 |= flag;
+ bp++;
+ }
+
+ MEM_freeN(nu->bp);
+ nu->bp= newbp;
+ nu->pntsv++;
+ if(nu->resolv<3) nu->resolv++;
+ makeknots(nu, 2, nu->flagv>>1);
+ }
+ else if(v==0 || v== nu->pntsu-1) { /* kolom in v-richting geselecteerd */
+ ok= 1;
+ bpn = newbp =
+ (BPoint*) MEM_mallocN((nu->pntsu + 1) * nu->pntsv * sizeof(BPoint), "extrudeNurb1");
+ bp= nu->bp;
+
+ for(a=0; a<nu->pntsv; a++) {
+ if(v==0) {
+ *bpn= *bp;
+ bpn->f1 |= flag;
+ bpn++;
+ }
+ memcpy(bpn, bp, nu->pntsu*sizeof(BPoint));
+ bp+= nu->pntsu;
+ bpn+= nu->pntsu;
+ if(v== nu->pntsu-1) {
+ *bpn= *(bp-1);
+ bpn->f1 |= flag;
+ bpn++;
+ }
+ }
+
+ MEM_freeN(nu->bp);
+ nu->bp= newbp;
+ nu->pntsu++;
+ if(nu->resolu<3) nu->resolu++;
+ makeknots(nu, 1, nu->flagu>>1);
+ }
+ }
+ }
+ nu= nu->next;
+ }
+
+ return ok;
+}
+
+
+void adduplicateflagNurb(short flag)
+/* short flag; */
+{
+ Nurb *nu, *newnu;
+ BezTriple *bezt, *bezt1;
+ BPoint *bp, *bp1;
+ int a, b, starta, enda, newu, newv;
+ char *usel;
+
+ nu= editNurb.last;
+ while(nu) {
+ if( (nu->type & 7)==CU_BEZIER) {
+ bezt= nu->bezt;
+ for(a=0; a<nu->pntsu; a++) {
+ enda= -1;
+ starta= a;
+ while( (bezt->f1 & flag) || (bezt->f2 & flag) || (bezt->f3 & flag) ) {
+ bezt->f1 &= ~flag;
+ bezt->f2 &= ~flag;
+ bezt->f3 &= ~flag;
+ enda=a;
+ if(a>=nu->pntsu-1) break;
+ a++;
+ bezt++;
+ }
+ if(enda>=starta) {
+ newnu = (Nurb*)MEM_mallocN(sizeof(Nurb), "adduplicateN");
+ memcpy(newnu, nu, sizeof(Nurb));
+ BLI_addtail(&editNurb, newnu);
+ lastnu= newnu;
+ newnu->pntsu= enda-starta+1;
+ newnu->bezt=
+ (BezTriple*)MEM_mallocN((enda - starta + 1) * sizeof(BezTriple), "adduplicateN");
+ memcpy(newnu->bezt, nu->bezt+starta, newnu->pntsu*sizeof(BezTriple));
+
+ b= newnu->pntsu;
+ bezt1= newnu->bezt;
+ while(b--) {
+ bezt1->f1 |= flag;
+ bezt1->f2 |= flag;
+ bezt1->f3 |= flag;
+ bezt1++;
+ }
+
+ if(nu->flagu & 1) {
+ if(starta!=0 || enda!=nu->pntsu-1) newnu->flagu--;
+ }
+ }
+ bezt++;
+ }
+ }
+ else if(nu->pntsv==1) { /* want UV Nurb heeft andere duplimethode */
+ bp= nu->bp;
+ for(a=0; a<nu->pntsu; a++) {
+ enda= -1;
+ starta= a;
+ while(bp->f1 & flag) {
+ bp->f1 &= ~flag;
+ enda= a;
+ if(a>=nu->pntsu-1) break;
+ a++;
+ bp++;
+ }
+ if(enda>=starta) {
+ newnu = (Nurb*)MEM_mallocN(sizeof(Nurb), "adduplicateN3");
+ memcpy(newnu, nu, sizeof(Nurb));
+ lastnu= newnu;
+ BLI_addtail(&editNurb, newnu);
+ newnu->pntsu= enda-starta+1;
+ newnu->bp = (BPoint*)MEM_mallocN((enda-starta+1) * sizeof(BPoint), "adduplicateN4");
+ memcpy(newnu->bp, nu->bp+starta, newnu->pntsu*sizeof(BPoint));
+
+ b= newnu->pntsu;
+ bp1= newnu->bp;
+ while(b--) {
+ bp1->f1 |= flag;
+ bp1++;
+ }
+
+ if(nu->flagu & 1) {
+ if(starta!=0 || enda!=nu->pntsu-1) newnu->flagu--;
+ }
+
+ /* knots */
+ newnu->knotsu= 0;
+ makeknots(newnu, 1, newnu->flagu>>1);
+ }
+ bp++;
+ }
+ }
+ else {
+ /* een rechthoekig gebied in de nurb moet geselecteerd zijn */
+ if(isNurbsel(nu)) {
+ usel= MEM_callocN(nu->pntsu, "adduplicateN4");
+ bp= nu->bp;
+ for(a=0; a<nu->pntsv; a++) {
+ for(b=0; b<nu->pntsu; b++, bp++) {
+ if(bp->f1 & flag) usel[b]++;
+ }
+ }
+ newu= 0;
+ newv= 0;
+ for(a=0; a<nu->pntsu; a++) {
+ if(usel[a]) {
+ if(newv==0 || usel[a]==newv) {
+ newv= usel[a];
+ newu++;
+ }
+ else {
+ newv= 0;
+ break;
+ }
+ }
+ }
+ if(newu==0 || newv==0) {
+ printf("Can't duplicate Nurb\n");
+ }
+ else {
+
+ if(newu==1) SWAP(short, newu, newv);
+
+ newnu = (Nurb*)MEM_mallocN(sizeof(Nurb), "adduplicateN5");
+ memcpy(newnu, nu, sizeof(Nurb));
+ BLI_addtail(&editNurb, newnu);
+ lastnu= newnu;
+ newnu->pntsu= newu;
+ newnu->pntsv= newv;
+ newnu->bp =
+ (BPoint*)MEM_mallocN(newu * newv * sizeof(BPoint), "adduplicateN6");
+ newnu->orderu= MIN2(nu->orderu, newu);
+ newnu->orderv= MIN2(nu->orderv, newv);
+
+ bp= newnu->bp;
+ bp1= nu->bp;
+ for(a=0; a<nu->pntsv; a++) {
+ for(b=0; b<nu->pntsu; b++, bp1++) {
+ if(bp1->f1 & flag) {
+ memcpy(bp, bp1, sizeof(BPoint));
+ bp1->f1 &= ~flag;
+ bp++;
+ }
+ }
+ }
+ if(nu->pntsu==newnu->pntsu) {
+ newnu->knotsu= MEM_mallocN(sizeof(float)*KNOTSU(nu), "adduplicateN6");
+ memcpy(newnu->knotsu, nu->knotsu, sizeof(float)*KNOTSU(nu));
+ }
+ else {
+ newnu->knotsu= 0;
+ makeknots(newnu, 1, newnu->flagu>>1);
+ }
+ if(nu->pntsv==newnu->pntsv) {
+ newnu->knotsv= MEM_mallocN(sizeof(float)*KNOTSV(nu), "adduplicateN7");
+ memcpy(newnu->knotsv, nu->knotsv, sizeof(float)*KNOTSV(nu));
+ }
+ else {
+ newnu->knotsv= 0;
+ makeknots(newnu, 2, newnu->flagv>>1);
+ }
+
+ }
+ MEM_freeN(usel);
+ }
+ }
+
+ nu= nu->prev;
+ }
+
+ /* lastnu changed */
+ allqueue(REDRAWBUTSEDIT, 0);
+}
+
+
+void switchdirectionNurb2(void)
+{
+ Nurb *nu;
+
+ if(G.obedit->lay & G.vd->lay);
+ else return;
+
+ nu= editNurb.first;
+ while(nu) {
+ if( isNurbsel(nu) ) switchdirectionNurb(nu);
+ nu= nu->next;
+ }
+
+ makeDispList(G.obedit);
+ allqueue(REDRAWVIEW3D, 0);
+}
+
+void switchdirection_knots(float *base, int tot)
+{
+ float *fp1, *fp2, *tempf;
+ int a;
+
+ if(base==NULL || tot==0) return;
+
+ /* de knots omkeren */
+ a= tot;
+ fp1= base;
+ fp2= fp1+(a-1);
+ a/= 2;
+ while(fp1!=fp2 && a>0) {
+ SWAP(float, *fp1, *fp2);
+ a--;
+ fp1++;
+ fp2--;
+ }
+ /* en weer in stijgende lijn maken */
+ a= tot;
+ fp1= base;
+ fp2=tempf= MEM_mallocN(sizeof(float)*a, "switchdirect");
+ while(a--) {
+ fp2[0]= fabs(fp1[1]-fp1[0]);
+ fp1++;
+ fp2++;
+ }
+
+ a= tot-1;
+ fp1= base;
+ fp2= tempf;
+ fp1[0]= 0.0;
+ fp1++;
+ while(a--) {
+ fp1[0]= fp1[-1]+fp2[0];
+ fp1++;
+ fp2++;
+ }
+ MEM_freeN(tempf);
+}
+
+/* **************** EDIT ************************ */
+
+void deselectall_nurb()
+{
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ int a, b;
+
+ if(G.obedit->lay & G.vd->lay);
+ else return;
+
+ a= 0;
+ nu= editNurb.first;
+ while(nu) {
+ if((nu->type & 7)==CU_BEZIER) {
+ b= nu->pntsu;
+ bezt= nu->bezt;
+ while(b--) {
+ if(bezt->hide==0) {
+ if(bezt->f1 & 1) {
+ a=1;
+ break;
+ }
+ if(bezt->f2 & 1) {
+ a=1;
+ break;
+ }
+ if(bezt->f3 & 1) {
+ a=1;
+ break;
+ }
+ }
+ bezt++;
+ }
+ }
+ else {
+ b= nu->pntsu*nu->pntsv;
+ bp= nu->bp;
+ while(b--) {
+ if(bp->hide==0) {
+ if(bp->f1 & 1) {
+ a=1;
+ break;
+ }
+ }
+ bp++;
+ }
+ }
+ if(a) break;
+ nu= nu->next;
+ }
+
+ nu= editNurb.first;
+ while(nu) {
+ if((nu->type & 7)==1) {
+ b= nu->pntsu;
+ bezt= nu->bezt;
+ while(b--) {
+ if(bezt->hide==0) {
+ if(a) {
+ bezt->f1 &= ~1;
+ bezt->f2 &= ~1;
+ bezt->f3 &= ~1;
+ }
+ else {
+ bezt->f1 |= 1;
+ bezt->f2 |= 1;
+ bezt->f3 |= 1;
+ }
+ }
+ bezt++;
+ }
+ }
+ else {
+ b= nu->pntsu*nu->pntsv;
+ bp= nu->bp;
+ while(b--) {
+ if(bp->hide==0) {
+ if(a) bp->f1 &= ~ 1;
+ else bp->f1 |= 1;
+ }
+ bp++;
+ }
+ }
+ nu= nu->next;
+ }
+ countall();
+ allqueue(REDRAWVIEW3D, 0);
+}
+
+void hideNurb(int swap)
+{
+ Nurb *nu;
+ BPoint *bp;
+ BezTriple *bezt;
+ int a, sel;
+
+ if(G.obedit==0) return;
+
+ nu= editNurb.first;
+ while(nu) {
+ if((nu->type & 7)==CU_BEZIER) {
+ bezt= nu->bezt;
+ a= nu->pntsu;
+ sel= 0;
+ while(a--) {
+ if(BEZSELECTED(bezt)) {
+ sel++;
+ bezt->f1 &= ~1;
+ bezt->f2 &= ~1;
+ bezt->f3 &= ~1;
+ bezt->hide= 1;
+ }
+ bezt++;
+ }
+ if(sel==nu->pntsu) nu->hide= 1;
+ }
+ else {
+ bp= nu->bp;
+ a= nu->pntsu*nu->pntsv;
+ sel= 0;
+ while(a--) {
+ if(swap==0 && (bp->f1 & 1)) {
+ bp->f1 &= ~1;
+ bp->hide= 1;
+ sel++;
+ }
+ else if(swap && (bp->f1 & 1)==0) {
+ bp->f1 &= ~1;
+ bp->hide= 1;
+ sel++;
+ }
+ bp++;
+ }
+ if(sel==nu->pntsu*nu->pntsv) nu->hide= 1;
+ }
+ nu= nu->next;
+ }
+
+ makeDispList(G.obedit);
+ countall();
+ allqueue(REDRAWVIEW3D, 0);
+}
+
+void revealNurb()
+{
+ Nurb *nu;
+ BPoint *bp;
+ BezTriple *bezt;
+ int a;
+
+ if(G.obedit==0) return;
+
+ nu= editNurb.first;
+ while(nu) {
+ nu->hide= 0;
+ if((nu->type & 7)==CU_BEZIER) {
+ bezt= nu->bezt;
+ a= nu->pntsu;
+ while(a--) {
+ if(bezt->hide) {
+ bezt->f1 |= 1;
+ bezt->f2 |= 1;
+ bezt->f3 |= 1;
+ bezt->hide= 0;
+ }
+ bezt++;
+ }
+ }
+ else {
+ bp= nu->bp;
+ a= nu->pntsu*nu->pntsv;
+ while(a--) {
+ if(bp->hide) {
+ bp->f1 |= 1;
+ bp->hide= 0;
+ }
+ bp++;
+ }
+ }
+ nu= nu->next;
+ }
+
+ makeDispList(G.obedit);
+ countall();
+ allqueue(REDRAWVIEW3D, 0);
+}
+
+void selectswapNurb()
+{
+ Nurb *nu;
+ BPoint *bp;
+ BezTriple *bezt;
+ int a;
+
+ if(G.obedit==0) return;
+
+ nu= editNurb.first;
+ while(nu) {
+ if((nu->type & 7)==CU_BEZIER) {
+ bezt= nu->bezt;
+ a= nu->pntsu;
+ while(a--) {
+ if(bezt->hide==0) {
+ if(bezt->f1 & 1) bezt->f1 &= ~1;
+ else bezt->f1 |= 1;
+ if(bezt->f2 & 1) bezt->f2 &= ~1;
+ else bezt->f2 |= 1;
+ if(bezt->f3 & 1) bezt->f3 &= ~1;
+ else bezt->f3 |= 1;
+ }
+ bezt++;
+ }
+ }
+ else {
+ bp= nu->bp;
+ a= nu->pntsu*nu->pntsv;
+ while(a--) {
+ if(bp->hide==0) {
+ if(bp->f1 & 1) bp->f1 &= ~1;
+ else bp->f1 |= 1;
+ }
+ bp++;
+ }
+ }
+ nu= nu->next;
+ }
+
+ countall();
+ allqueue(REDRAWVIEW3D, 0);
+}
+
+/** Divide the line segments associated with the currently selected
+ * curve nodes (Bezier or NURB). If there are no valid segment
+ * selections within the current selection, nothing happens.
+ *
+ * @deffunc subdividenurb subdivideNurb(void)
+ * @return Nothing
+ * @param None
+*/
+void subdivideNurb()
+{
+ Nurb *nu;
+ BezTriple *prevbezt, *bezt, *beztnew, *beztn;
+ BPoint *bp, *prevbp, *bpnew, *bpn;
+ float vec[12];
+ int a, b, sel, aantal, *usel, *vsel;
+
+ // printf("*** subdivideNurb: entering subdivide\n");
+
+ nu= editNurb.first;
+ while(nu) {
+ aantal= 0;
+ if((nu->type & 7)==CU_BEZIER) {
+ /*
+ Insert a point into a 2D Bezier curve.
+ Endpoints are preserved. Otherwise, all selected and inserted points are
+ newly created. Old points are discarded.
+ */
+ /* tellen */
+ if(nu->flagu & 1) {
+ a= nu->pntsu;
+ bezt= nu->bezt;
+ prevbezt= bezt+(a-1);
+ }
+ else {
+ a= nu->pntsu-1;
+ prevbezt= nu->bezt;
+ bezt= prevbezt+1;
+ }
+ while(a--) {
+ if( BEZSELECTED(prevbezt) && BEZSELECTED(bezt) ) aantal++;
+ prevbezt= bezt;
+ bezt++;
+ }
+
+ if(aantal) {
+ /* inserten */
+ beztnew =
+ /* I have some severe doubt about the original
+ * formulation... I stick to the upper bound to be
+ * on the safe side */
+ (BezTriple*)MEM_mallocN((aantal + nu->pntsu) * sizeof(BezTriple), "subdivNurb");
+/* mallocstructN(BezTriple, aantal+nu->pntsu, "subdivNurb"); */
+ beztn= beztnew;
+ if(nu->flagu & 1) {
+ a= nu->pntsu;
+ bezt= nu->bezt;
+ prevbezt= bezt+(a-1);
+ }
+ else {
+ a= nu->pntsu-1;
+ prevbezt= nu->bezt;
+ bezt= prevbezt+1;
+ }
+ while(a--) {
+ memcpy(beztn, prevbezt, sizeof(BezTriple));
+ beztn++;
+ // printf("*** subdivideNurb: insert Bezier point\n");
+
+ if( BEZSELECTED(prevbezt) && BEZSELECTED(bezt) ) {
+ memcpy(beztn, bezt, sizeof(BezTriple));
+ maakbez(prevbezt->vec[1][0],prevbezt->vec[2][0],
+ bezt->vec[0][0],bezt->vec[1][0],vec,2);
+ maakbez(prevbezt->vec[1][1],prevbezt->vec[2][1],
+ bezt->vec[0][1],bezt->vec[1][1],vec+1,2);
+ maakbez(prevbezt->vec[1][2],prevbezt->vec[2][2],
+ bezt->vec[0][2],bezt->vec[1][2],vec+2,2);
+ VECCOPY(beztn->vec[1], vec+3);
+ beztn->h1= beztn->h2= HD_AUTO;
+ beztn++;
+ }
+
+ prevbezt= bezt;
+ bezt++;
+ }
+ /* laatste punt */
+ if((nu->flagu & 1)==0) memcpy(beztn, prevbezt, sizeof(BezTriple));
+
+ MEM_freeN(nu->bezt);
+ nu->bezt= beztnew;
+ nu->pntsu+= aantal;
+
+ calchandlesNurb(nu);
+ }
+ } /* End of 'if((nu->type & 7)==CU_BEZIER)' */
+ else if (nu->pntsv==1) {
+ /*
+ All flat lines (ie. co-planar), except flat Nurbs. Flat NURB curves
+ are handled together with the regular NURB plane division, as it
+ should be. I split it off just now, let's see if it is
+ stable... nzc 30-5-'00
+ */
+ /* tellen */
+ if(nu->flagu & 1) {
+ a= nu->pntsu*nu->pntsv;
+ bp= nu->bp;
+ prevbp= bp+(a-1);
+ }
+ else {
+ a= nu->pntsu-1;
+ prevbp= nu->bp;
+ bp= prevbp+1;
+ }
+ while(a--) {
+ if( (bp->f1 & 1) && (prevbp->f1 & 1) ) aantal++;
+ prevbp= bp;
+ bp++;
+ }
+
+ if(aantal) {
+ /* inserten */
+ bpnew =
+ (BPoint*)MEM_mallocN((aantal + nu->pntsu) * sizeof(BPoint), "subdivNurb2");
+ bpn= bpnew;
+
+ if(nu->flagu & 1) {
+ a= nu->pntsu;
+ bp= nu->bp;
+ prevbp= bp+(a-1);
+ }
+ else {
+ a= nu->pntsu-1;
+ prevbp= nu->bp;
+ bp= prevbp+1;
+ }
+ while(a--) {
+ memcpy(bpn, prevbp, sizeof(BPoint));
+ bpn++;
+
+ if( (bp->f1 & 1) && (prevbp->f1 & 1) ) {
+ // printf("*** subdivideNurb: insert 'linear' point\n");
+ memcpy(bpn, bp, sizeof(BPoint));
+ bpn->vec[0]= (prevbp->vec[0]+bp->vec[0])/2.0;
+ bpn->vec[1]= (prevbp->vec[1]+bp->vec[1])/2.0;
+ bpn->vec[2]= (prevbp->vec[2]+bp->vec[2])/2.0;
+ bpn->vec[3]= (prevbp->vec[3]+bp->vec[3])/2.0;
+ bpn++;
+
+ }
+ prevbp= bp;
+ bp++;
+ }
+ if((nu->flagu & 1)==0) memcpy(bpn, prevbp, sizeof(BPoint)); /* laatste punt */
+
+ MEM_freeN(nu->bp);
+ nu->bp= bpnew;
+ nu->pntsu+= aantal;
+
+ if(nu->type & 4) {
+ makeknots(nu, 1, nu->flagu>>1);
+ }
+ }
+ } /* End of 'else if(nu->pntsv==1)' */
+ else if((nu->type & 7)==CU_NURBS) {
+ /* This is a very strange test ... */
+ /**
+ Subdivide NURB surfaces - nzc 30-5-'00 -
+
+ Subdivision of a NURB curve can be effected by adding a
+ control point (insertion of a knot), or by raising the
+ degree of the functions used to build the NURB. The
+ expression
+
+ degree = #knots - #controlpoints + 1 (J Walter piece)
+ degree = #knots - #controlpoints (Blender
+ implementation)
+ ( this is confusing.... what is true? Another concern
+ is that the JW piece allows the curve to become
+ explicitly 1st order derivative discontinuous, while
+ this is not what we want here... )
+
+ is an invariant for a single NURB curve. Raising the degree
+ of the NURB is done elsewhere; the degree is assumed
+ constant during this opration. Degree is a property shared
+ by all controlpoints in a curve (even though it is stored
+ per control point - this can be misleading).
+ Adding a knot is done by searching for the place in the
+ knot vector where a certain knot value must be inserted, or
+ by picking an appropriate knot value between two existing
+ ones. The number of controlpoints that is influenced by the
+ insertion depends on the order of the curve. A certain
+ minimum number of knots is needed to form high-order
+ curves, as can be seen from the equation above. In Blender,
+ currently NURBs may be up to 6th order, so we modify at
+ most 6 points. One point is added. For an n-degree curve,
+ n points are discarded, and n+1 points inserted
+ (so effectively, n points are modified). (that holds for
+ the JW piece, but it seems not for our NURBs)
+ In practice, the knot spacing is copied, but the tail
+ (the points following the insertion point) need to be
+ offset to keep the knot series ascending. The knot series
+ is always a series of monotonically ascending integers in
+ Blender. When not enough control points are available to
+ fit the order, duplicates of the endpoints are added as
+ needed.
+ */
+ /* selecteer-arrays aanleggen */
+ usel= MEM_callocN(sizeof(int)*nu->pntsu, "subivideNurb3");
+ vsel= MEM_callocN(sizeof(int)*nu->pntsv, "subivideNurb3");
+ sel= 0;
+
+ /* Count the number of selected points. */
+ bp= nu->bp;
+ for(a=0; a<nu->pntsv; a++) {
+ for(b=0; b<nu->pntsu; b++) {
+ if(bp->f1 & 1) {
+ usel[b]++;
+ vsel[a]++;
+ sel++;
+ }
+ bp++;
+ }
+ }
+ if( sel == (nu->pntsu*nu->pntsv) ) { /* hele nurb subdividen */
+ /* Global subdivision is a special case of partial
+ subdivision. Strange it is considered separately... */
+ bpn=bpnew= MEM_mallocN( (2*nu->pntsu-1)*(2*nu->pntsv-1)*sizeof(BPoint), "subdivideNurb4");
+ bp= nu->bp;
+ /* eerst de rijen subdividen */
+ for(a=0; a<nu->pntsv; a++) {
+ for(b=0; b<nu->pntsu; b++) {
+ *bpn= *bp;
+ bpn++;
+ bp++;
+ if(b<nu->pntsu-1) {
+ *bpn= *bp;
+ prevbp= bp-1;
+ bpn->vec[0]= (prevbp->vec[0]+bp->vec[0])/2.0;
+ bpn->vec[1]= (prevbp->vec[1]+bp->vec[1])/2.0;
+ bpn->vec[2]= (prevbp->vec[2]+bp->vec[2])/2.0;
+ bpn->vec[3]= (prevbp->vec[3]+bp->vec[3])/2.0;
+ bpn++;
+ }
+ }
+ bpn+= (2*nu->pntsu-1);
+ }
+ /* nu nieuwe invoegen */
+ bpn= bpnew+(2*nu->pntsu-1);
+ bp= bpnew+(4*nu->pntsu-2);
+ prevbp= bpnew;
+ for(a=1; a<nu->pntsv; a++) {
+
+ for(b=0; b<2*nu->pntsu-1; b++) {
+ *bpn= *bp;
+ bpn->vec[0]= (prevbp->vec[0]+bp->vec[0])/2.0;
+ bpn->vec[1]= (prevbp->vec[1]+bp->vec[1])/2.0;
+ bpn->vec[2]= (prevbp->vec[2]+bp->vec[2])/2.0;
+ bpn->vec[3]= (prevbp->vec[3]+bp->vec[3])/2.0;
+ bpn++;
+ bp++;
+ prevbp++;
+ }
+ bp+= (2*nu->pntsu-1);
+ bpn+= (2*nu->pntsu-1);
+ prevbp+= (2*nu->pntsu-1);
+ }
+ MEM_freeN(nu->bp);
+ nu->bp= bpnew;
+ nu->pntsu= 2*nu->pntsu-1;
+ nu->pntsv= 2*nu->pntsv-1;
+ makeknots(nu, 1, nu->flagu>>1);
+ makeknots(nu, 2, nu->flagv>>1);
+ } /* End of 'if(sel== nu->pntsu*nu->pntsv)' (subdivide entire NURB) */
+ else {
+ /* in v richting subdividen? */
+ sel= 0;
+ for(a=0; a<nu->pntsv-1; a++) {
+ if(vsel[a]==nu->pntsu && vsel[a+1]==nu->pntsu) sel++;
+ }
+
+ if(sel) { /* V ! */
+ bpn=bpnew= MEM_mallocN( (sel+nu->pntsv)*nu->pntsu*sizeof(BPoint), "subdivideNurb4");
+ bp= nu->bp;
+ for(a=0; a<nu->pntsv; a++) {
+ for(b=0; b<nu->pntsu; b++) {
+ *bpn= *bp;
+ bpn++;
+ bp++;
+ }
+ if( (a<nu->pntsv-1) && vsel[a]==nu->pntsu && vsel[a+1]==nu->pntsu ) {
+ prevbp= bp- nu->pntsu;
+ for(b=0; b<nu->pntsu; b++) {
+ /*
+ This simple bisection must be replaces by a
+ subtle resampling of a number of points. Our
+ task is made slightly easier because each
+ point in our curve is a separate data
+ node. (is it?)
+ */
+ *bpn= *prevbp;
+ bpn->vec[0]= (prevbp->vec[0]+bp->vec[0])/2.0;
+ bpn->vec[1]= (prevbp->vec[1]+bp->vec[1])/2.0;
+ bpn->vec[2]= (prevbp->vec[2]+bp->vec[2])/2.0;
+ bpn->vec[3]= (prevbp->vec[3]+bp->vec[3])/2.0;
+ bpn++;
+ prevbp++;
+ bp++;
+ }
+ bp-= nu->pntsu;
+ }
+ }
+ MEM_freeN(nu->bp);
+ nu->bp= bpnew;
+ nu->pntsv+= sel;
+ makeknots(nu, 2, nu->flagv>>1);
+ }
+ else {
+ /* of in u richting? */
+ sel= 0;
+ for(a=0; a<nu->pntsu-1; a++) {
+ if(usel[a]==nu->pntsv && usel[a+1]==nu->pntsv) sel++;
+ }
+
+ if(sel) { /* U ! */
+ /* Inserting U points is sort of 'default' Flat curves only get */
+ /* U points inserted in them. */
+ bpn=bpnew= MEM_mallocN( (sel+nu->pntsu)*nu->pntsv*sizeof(BPoint), "subdivideNurb4");
+ bp= nu->bp;
+ for(a=0; a<nu->pntsv; a++) {
+ for(b=0; b<nu->pntsu; b++) {
+ *bpn= *bp;
+ bpn++;
+ bp++;
+ if( (b<nu->pntsu-1) && usel[b]==nu->pntsv && usel[b+1]==nu->pntsv ) {
+ /*
+ One thing that bugs me here is that the
+ orders of things are not the same as in
+ the JW piece. Also, this implies that we
+ handle at most 3rd order curves? I miss
+ some symmetry here...
+ */
+ prevbp= bp- 1;
+ *bpn= *prevbp;
+ bpn->vec[0]= (prevbp->vec[0]+bp->vec[0])/2.0;
+ bpn->vec[1]= (prevbp->vec[1]+bp->vec[1])/2.0;
+ bpn->vec[2]= (prevbp->vec[2]+bp->vec[2])/2.0;
+ bpn->vec[3]= (prevbp->vec[3]+bp->vec[3])/2.0;
+ bpn++;
+ }
+ }
+ }
+ MEM_freeN(nu->bp);
+ nu->bp= bpnew;
+ nu->pntsu+= sel;
+ makeknots(nu, 1, nu->flagu>>1); /* shift knots
+ forward */
+ }
+ }
+ }
+ MEM_freeN(usel);
+ MEM_freeN(vsel);
+ // printf("*** subdivideNurb: end of NURB splitting part\n");
+ } /* End of 'if((nu->type & 7)==CU_NURBS)' */
+ nu= nu->next;
+ }
+
+ /* Sync flushing */
+ // printf("*** subdivideNurb: subdivide done\n");
+
+ makeDispList(G.obedit);
+ countall();
+ allqueue(REDRAWVIEW3D, 0);
+}
+
+
+short findnearestNurbvert(short sel, Nurb **nurb, BezTriple **bezt, BPoint **bp)
+/*
+short sel;
+Nurb **nurb;
+BezTriple **bezt;
+BPoint **bp;
+*/
+{
+ /* sel==1: selected krijgen een nadeel */
+ /* in nurb en bezt of bp wordt nearest weggeschreven */
+ /* return 0 1 2: handlepunt */
+ Nurb *nu;
+ BezTriple *bezt1;
+ BPoint *bp1;
+ short dist= 100, temp, mval[2], a, hpoint=0;
+
+ *nurb= 0;
+ *bezt= 0;
+ *bp= 0;
+
+ /* projektie doen */
+ calc_nurbverts_ext(); /* drawobject.c */
+
+ getmouseco_areawin(mval);
+
+ nu= editNurb.first;
+ while(nu) {
+ if((nu->type & 7)==CU_BEZIER) {
+ bezt1= nu->bezt;
+ a= nu->pntsu;
+ while(a--) {
+ if(bezt1->hide==0) {
+ temp= abs(mval[0]- bezt1->s[0][0])+ abs(mval[1]- bezt1->s[0][1]);
+ if( (bezt1->f1 & 1)==sel) temp+=5;
+ if(temp<dist) {
+ hpoint=0;
+ *bezt=bezt1;
+ dist= temp;
+ *nurb= nu;
+ *bp= 0;
+ }
+
+ /* middelste punten een klein nadeel */
+ temp= 3+abs(mval[0]- bezt1->s[1][0])+ abs(mval[1]- bezt1->s[1][1]);
+ if( (bezt1->f2 & 1)==sel) temp+=5;
+ if(temp<dist) {
+ hpoint=1;
+ *bezt=bezt1;
+ dist= temp;
+ *nurb= nu;
+ *bp= 0;
+ }
+
+ temp= abs(mval[0]- bezt1->s[2][0])+ abs(mval[1]- bezt1->s[2][1]);
+ if( (bezt1->f3 & 1)==sel) temp+=5;
+ if(temp<dist) {
+ hpoint=2;
+ *bezt=bezt1;
+ dist= temp;
+ *nurb= nu;
+ *bp= 0;
+ }
+ }
+ bezt1++;
+ }
+ }
+ else {
+ bp1= nu->bp;
+ a= nu->pntsu*nu->pntsv;
+ while(a--) {
+ if(bp1->hide==0) {
+ temp= abs(mval[0]- bp1->s[0])+ abs(mval[1]- bp1->s[1]);
+ if( (bp1->f1 & 1)==sel) temp+=5;
+ if(temp<dist) {
+ hpoint=0;
+ *bp=bp1;
+ dist= temp;
+ *nurb= nu;
+ *bezt= 0;
+ }
+ }
+ bp1++;
+ }
+ }
+ nu= nu->next;
+ }
+
+ return hpoint;
+}
+
+
+void findselectedNurbvert(Nurb **nu, BezTriple **bezt, BPoint **bp)
+{
+ /* in nu en (bezt of bp) wordt selected weggeschreven als er 1 sel. is */
+ /* als er meer punten in 1 spline selected: alleen nu terug, bezt en bp zijn 0 */
+ Nurb *nu1;
+ BezTriple *bezt1;
+ BPoint *bp1;
+ int a;
+
+ *nu= 0;
+ *bezt= 0;
+ *bp= 0;
+ nu1= editNurb.first;
+ while(nu1) {
+ if((nu1->type & 7)==CU_BEZIER) {
+ bezt1= nu1->bezt;
+ a= nu1->pntsu;
+ while(a--) {
+ if( (bezt1->f1 & 1) || (bezt1->f2 & 1) || (bezt1->f3 & 1) ) {
+ if(*nu!=0 && *nu!= nu1) {
+ *nu= 0;
+ *bp= 0;
+ *bezt= 0;
+ return;
+ }
+ else if(*bezt || *bp) {
+ *bp= 0;
+ *bezt= 0;
+ }
+ else {
+ *bezt= bezt1;
+ *nu= nu1;
+ }
+ }
+ bezt1++;
+ }
+ }
+ else {
+ bp1= nu1->bp;
+ a= nu1->pntsu*nu1->pntsv;
+ while(a--) {
+ if( bp1->f1 & 1 ) {
+ if(*nu!=0 && *nu!= nu1) {
+ *bp= 0;
+ *bezt= 0;
+ *nu= 0;
+ return;
+ }
+ else if(*bezt || *bp) {
+ *bp= 0;
+ *bezt= 0;
+ }
+ else {
+ *bp= bp1;
+ *nu= nu1;
+ }
+ }
+ bp1++;
+ }
+ }
+ nu1= nu1->next;
+ }
+}
+
+void setsplinetype(short type)
+/*
+short type;
+*/
+{
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ int a, c, nr;
+
+ if(type==CU_CARDINAL || type==CU_BSPLINE) {
+ error("Not implemented yet");
+ return;
+ }
+
+ nu= editNurb.first;
+ while(nu) {
+ if(isNurbsel(nu)) {
+
+ if((nu->type & 7)==0) { /* Poly */
+ if(type==CU_BEZIER) { /* naar Bezier met vecthandles */
+ nr= nu->pntsu;
+ bezt =
+ (BezTriple*)MEM_callocN(nr * sizeof(BezTriple), "setsplinetype2");
+ nu->bezt= bezt;
+ a= nr;
+ bp= nu->bp;
+ while(a--) {
+ VECCOPY(bezt->vec[1], bp->vec);
+ bezt->f1=bezt->f2=bezt->f3= bp->f1;
+ bezt->h1= bezt->h2= HD_VECT;
+ bp++;
+ bezt++;
+ }
+ MEM_freeN(nu->bp);
+ nu->bp= 0;
+ nu->pntsu= nr;
+ nu->type &= ~7;
+ nu->type |= 1;
+ calchandlesNurb(nu);
+ }
+ else if(type==4) { /* naar Nurb */
+ nu->type &= ~7;
+ nu->type+= 4;
+ nu->orderu= 4;
+ nu->flagu &= 1;
+ nu->flagu += 4;
+ makeknots(nu, 1, nu->flagu>>1);
+ a= nu->pntsu*nu->pntsv;
+ bp= nu->bp;
+ while(a--) {
+ bp->vec[3]= 1.0;
+ bp++;
+ }
+ }
+ }
+ else if((nu->type & 7)==CU_BEZIER) { /* Bezier */
+ if(type==0 || type==4) { /* naar Poly of Nurb */
+ nr= 3*nu->pntsu;
+ nu->bp =
+ (BPoint*)MEM_callocN(nr * sizeof(BPoint), "setsplinetype");
+ a= nu->pntsu;
+ bezt= nu->bezt;
+ bp= nu->bp;
+ while(a--) {
+ if(type==0 && bezt->h1==HD_VECT && bezt->h2==HD_VECT) {
+ /* vectorhandle wordt 1 polyvert */
+ VECCOPY(bp->vec, bezt->vec[1]);
+ bp->vec[3]= 1.0;
+ bp->f1= bezt->f2;
+ nr-= 2;
+ bp++;
+ }
+ else {
+ for(c=0;c<3;c++) {
+ VECCOPY(bp->vec, bezt->vec[c]);
+ bp->vec[3]= 1.0;
+ if(c==0) bp->f1= bezt->f1;
+ else if(c==1) bp->f1= bezt->f2;
+ else bp->f1= bezt->f3;
+ bp++;
+ }
+ }
+ bezt++;
+ }
+ MEM_freeN(nu->bezt);
+ nu->bezt= 0;
+ nu->pntsu= nr;
+ nu->pntsv= 1;
+ nu->orderu= 4;
+ nu->orderv= 1;
+ nu->type &= ~7;
+ nu->type+= type;
+ if(nu->flagu & 1) c= nu->orderu-1;
+ else c= 0;
+ if(type== 4) {
+ nu->flagu &= 1;
+ nu->flagu += 4;
+ makeknots(nu, 1, nu->flagu>>1);
+ }
+ }
+ }
+ else if( (nu->type & 7)==CU_NURBS && G.obedit->type==OB_CURVE) {
+ if(type==0) { /* naar Poly */
+ nu->type &= ~7;
+ MEM_freeN(nu->knotsu);
+ nu->knotsu= 0;
+ if(nu->knotsv) MEM_freeN(nu->knotsv);
+ nu->knotsv= 0;
+ }
+ else if(type==CU_BEZIER) { /* naar Bezier */
+ nr= nu->pntsu/3;
+ bezt =
+ (BezTriple*)MEM_callocN(nr * sizeof(BezTriple), "setsplinetype2");
+ nu->bezt= bezt;
+ a= nr;
+ bp= nu->bp;
+ while(a--) {
+ VECCOPY(bezt->vec[0], bp->vec);
+ bezt->f1= bp->f1;
+ bp++;
+ VECCOPY(bezt->vec[1], bp->vec);
+ bezt->f2= bp->f1;
+ bp++;
+ VECCOPY(bezt->vec[2], bp->vec);
+ bezt->f3= bp->f1;
+ bp++;
+ bezt++;
+ }
+ MEM_freeN(nu->bp);
+ nu->bp= 0;
+ MEM_freeN(nu->knotsu);
+ nu->knotsu= 0;
+ nu->pntsu= nr;
+ nu->type &= ~7;
+ nu->type+= 1;
+ }
+ }
+ }
+ nu= nu->next;
+ }
+}
+
+/* ******************** SKINNING LOFTING!!! ******************** */
+
+void rotate_direction_nurb(Nurb *nu)
+{
+ BPoint *bp1, *bp2, *temp;
+ int u, v;
+
+ SWAP(short, nu->pntsu, nu->pntsv);
+ SWAP(short, nu->orderu, nu->orderv);
+ SWAP(short, nu->resolu, nu->resolv);
+ SWAP(short, nu->flagu, nu->flagv);
+
+ SWAP(float *, nu->knotsu, nu->knotsv);
+ switchdirection_knots(nu->knotsv, KNOTSV(nu) );
+
+ temp= MEM_dupallocN(nu->bp);
+ bp1= nu->bp;
+ for(v=0; v<nu->pntsv; v++) {
+ for(u=0; u<nu->pntsu; u++, bp1++) {
+ bp2= temp + (nu->pntsu-u-1)*(nu->pntsv) + v;
+ *bp1= *bp2;
+ }
+ }
+
+ MEM_freeN(temp);
+}
+
+int is_u_selected(Nurb *nu, int u)
+{
+ BPoint *bp;
+ int v;
+
+ /* what about resolu == 2? */
+ bp= nu->bp+u;
+ for(v=0; v<nu->pntsv-1; v++, bp+=nu->pntsu) {
+ if(v) if(bp->f1 & 1) return 1;
+ }
+
+ return 0;
+}
+
+/* ******************************** */
+
+typedef struct NurbSort {
+ struct NurbSort *next, *prev;
+ Nurb *nu;
+ float vec[3];
+} NurbSort;
+
+static ListBase nsortbase= {0, 0};
+/* static NurbSort *nusmain; */ /* this var seems to go unused... at least in this file */
+
+void make_selection_list_nurb()
+{
+ ListBase nbase= {0, 0};
+ NurbSort *nus, *nustest, *headdo, *taildo;
+ Nurb *nu;
+ BPoint *bp;
+ float dist, headdist, taildist;
+ int a;
+
+ nu= editNurb.first;
+ while(nu) {
+ if( isNurbsel(nu) ) {
+
+ nus = (NurbSort*)MEM_callocN(sizeof(NurbSort), "sort");
+ BLI_addhead(&nbase, nus);
+ nus->nu= nu;
+
+ bp= nu->bp;
+ a= nu->pntsu;
+ while(a--) {
+ VecAddf(nus->vec, nus->vec, bp->vec);
+ bp++;
+ }
+ VecMulf(nus->vec, 1.0/(float)nu->pntsu);
+
+
+ }
+ nu= nu->next;
+ }
+
+ /* just add the first one */
+ nus= nbase.first;
+ BLI_remlink(&nbase, nus);
+ BLI_addtail( &nsortbase, nus);
+
+ /* now add, either at head or tail, the closest one */
+ while(nbase.first) {
+
+ headdist= taildist= 1.0e30;
+ headdo= taildo= 0;
+
+ nustest= nbase.first;
+ while(nustest) {
+ dist= VecLenf(nustest->vec, ((NurbSort *)nsortbase.first)->vec);
+
+ if(dist<headdist) {
+ headdist= dist;
+ headdo= nustest;
+ }
+ dist= VecLenf(nustest->vec, ((NurbSort *)nsortbase.last)->vec);
+
+ if(dist<taildist) {
+ taildist= dist;
+ taildo= nustest;
+ }
+ nustest= nustest->next;
+ }
+
+ if(headdist<taildist) {
+ BLI_remlink(&nbase, headdo);
+ BLI_addhead(&nsortbase, headdo);
+ }
+ else {
+ BLI_remlink(&nbase, taildo);
+ BLI_addtail(&nsortbase, taildo);
+ }
+ }
+}
+
+void merge_2_nurb(Nurb *nu1, Nurb *nu2)
+{
+ BPoint *bp, *bp1, *bp2, *temp;
+ float len1, len2;
+ int origu, u, v;
+
+ /* first nurbs will be changed to make u = resolu-1 selected */
+ /* 2nd nurbs will be changed to make u = 0 selected */
+
+ /* first nurbs: u = resolu-1 selected */
+
+ if( is_u_selected(nu1, nu1->pntsu-1) );
+ else {
+ rotate_direction_nurb(nu1);
+ if( is_u_selected(nu1, nu1->pntsu-1) );
+ else {
+ rotate_direction_nurb(nu1);
+ if( is_u_selected(nu1, nu1->pntsu-1) );
+ else {
+ rotate_direction_nurb(nu1);
+ if( is_u_selected(nu1, nu1->pntsu-1) );
+ else {
+ /* rotate again, now its OK! */
+ if(nu1->pntsv!=1) rotate_direction_nurb(nu1);
+ return;
+ }
+ }
+ }
+ }
+
+ /* 2nd nurbs: u = 0 selected */
+ if( is_u_selected(nu2, 0) );
+ else {
+ rotate_direction_nurb(nu2);
+ if( is_u_selected(nu2, 0) );
+ else {
+ rotate_direction_nurb(nu2);
+ if( is_u_selected(nu2, 0) );
+ else {
+ rotate_direction_nurb(nu2);
+ if( is_u_selected(nu2, 0) );
+ else {
+ /* rotate again, now its OK! */
+ if(nu1->pntsu==1) rotate_direction_nurb(nu1);
+ if(nu2->pntsv!=1) rotate_direction_nurb(nu2);
+ return;
+ }
+ }
+ }
+ }
+
+ if( nu1->pntsv != nu2->pntsv ) {
+ error("resolution doesn't match");
+ return;
+ }
+
+ /* ok, now nu1 has the rightmost collumn and nu2 the leftmost collumn selected */
+ /* maybe we need a 'v' flip of nu2? */
+
+ bp1= nu1->bp+nu1->pntsu-1;
+ bp2= nu2->bp;
+ len1= 0.0;
+
+ for(v=0; v<nu1->pntsv; v++, bp1+=nu1->pntsu, bp2+=nu2->pntsu) {
+ len1+= VecLenf(bp1->vec, bp2->vec);
+ }
+
+ bp1= nu1->bp + nu1->pntsu-1;
+ bp2= nu2->bp + nu2->pntsu*(nu2->pntsv-1);
+ len2= 0.0;
+
+ for(v=0; v<nu1->pntsv; v++, bp1+=nu1->pntsu, bp2-=nu2->pntsu) {
+ len2+= VecLenf(bp1->vec, bp2->vec);
+ }
+
+ /* merge */
+ origu= nu1->pntsu;
+ nu1->pntsu+= nu2->pntsu;
+ nu1->resolu+= nu2->pntsu;
+ if(nu1->resolv < nu2->resolv) nu1->resolv= nu2->resolv;
+ if(nu1->orderu<3) nu1->orderu++;
+ if(nu1->orderv<3) nu1->orderv++;
+ temp= nu1->bp;
+ nu1->bp= MEM_mallocN(nu1->pntsu*nu1->pntsv*sizeof(BPoint), "mergeBP");
+
+ bp= nu1->bp;
+ bp1= temp;
+
+ for(v=0; v<nu1->pntsv; v++) {
+
+ /* switch direction? */
+ if(len1<len2) bp2= nu2->bp + v*nu2->pntsu;
+ else bp2= nu2->bp + (nu1->pntsv-v-1)*nu2->pntsu;
+
+ for(u=0; u<nu1->pntsu; u++, bp++) {
+ if(u<origu) {
+ *bp= *bp1; bp1++;
+ bp->f1 &= ~SELECT;
+ }
+ else {
+ *bp= *bp2; bp2++;
+ }
+ }
+ }
+
+ /* merge knots */
+ makeknots(nu1, 1, nu1->flagu>>1);
+
+ /* make knots, for merged curved for example */
+ makeknots(nu1, 2, nu1->flagv>>1);
+
+ MEM_freeN(temp);
+ BLI_remlink(&editNurb, nu2);
+ freeNurb(nu2);
+}
+
+void merge_nurb()
+{
+ NurbSort *nus1, *nus2;
+ int ok= 1;
+
+ make_selection_list_nurb();
+
+ if(nsortbase.first == nsortbase.last) {
+ BLI_freelistN(&nsortbase);
+ error("Too few selections");
+ return;
+ }
+
+ nus1= nsortbase.first;
+ nus2= nus1->next;
+
+ /* resolution match, to avoid uv rotations */
+ if(nus1->nu->pntsv==1) {
+ if(nus1->nu->pntsu==nus2->nu->pntsu || nus1->nu->pntsu==nus2->nu->pntsv);
+ else ok= 0;
+ }
+ else if(nus2->nu->pntsv==1) {
+ if(nus2->nu->pntsu==nus1->nu->pntsu || nus2->nu->pntsu==nus1->nu->pntsv);
+ else ok= 0;
+ }
+ else if( nus1->nu->pntsu==nus2->nu->pntsu || nus1->nu->pntsv==nus2->nu->pntsv);
+ else if( nus1->nu->pntsu==nus2->nu->pntsv || nus1->nu->pntsv==nus2->nu->pntsu);
+ else {
+ ok= 0;
+ }
+
+ if(ok==0) {
+ error("resolution doesn't match");
+ BLI_freelistN(&nsortbase);
+ return;
+ }
+
+ while(nus2) {
+ merge_2_nurb(nus1->nu, nus2->nu);
+ nus2= nus2->next;
+ }
+
+ BLI_freelistN(&nsortbase);
+
+ makeDispList(G.obedit);
+ allqueue(REDRAWVIEW3D, 0);
+
+}
+
+
+void addsegment_nurb()
+{
+ /* voegt twee curves samen */
+ Nurb *nu, *nu1=0, *nu2=0;
+ BezTriple *bezt;
+ BPoint *bp;
+ float *fp, offset;
+ int a;
+
+ /* first decide if this is a surface merge! */
+ if(G.obedit->type==OB_SURF) nu= editNurb.first;
+ else nu= 0;
+
+ while(nu) {
+ if( isNurbsel(nu) ) {
+
+ if(nu->pntsu>1 && nu->pntsv>1) break;
+ if(isNurbsel_count(nu)>1) break;
+ if(isNurbsel_count(nu)==1) {
+ /* only 1 selected, not first or last, a little complex, but intuitive */
+ if(nu->pntsv==1) {
+ if( (nu->bp->f1 & 1) || ((nu->bp+nu->pntsu-1)->f1 & 1));
+ else break;
+ }
+ }
+ }
+ nu= nu->next;
+ }
+ if(nu) {
+ merge_nurb();
+ return;
+ }
+
+ /* vind de beide nurben en punten, nu1 wordt achter nu2 gezet */
+ nu= editNurb.first;
+ while(nu) {
+ if((nu->flagu & 1)==0) { /* niet cyclic */
+ if( (nu->type & 7)==CU_BEZIER ) {
+ bezt= nu->bezt;
+ if(nu1==0) {
+ if( BEZSELECTED(bezt) ) nu1= nu;
+ else {
+ bezt= bezt+(nu->pntsu-1);
+ if( BEZSELECTED(bezt) ) {
+ nu1= nu;
+ switchdirectionNurb(nu);
+ }
+ }
+ }
+ else if(nu2==0) {
+ if( BEZSELECTED(bezt) ) {
+ nu2= nu;
+ switchdirectionNurb(nu);
+ }
+ else {
+ bezt= bezt+(nu->pntsu-1);
+ if( BEZSELECTED(bezt) ) {
+ nu2= nu;
+ }
+ }
+ }
+ else break;
+ }
+ else if(nu->pntsv==1) {
+ bp= nu->bp;
+ if(nu1==0) {
+ if( bp->f1 & 1) nu1= nu;
+ else {
+ bp= bp+(nu->pntsu-1);
+ if( bp->f1 & 1 ) {
+ nu1= nu;
+ switchdirectionNurb(nu);
+ }
+ }
+ }
+ else if(nu2==0) {
+ if( bp->f1 & 1) {
+ nu2= nu;
+ switchdirectionNurb(nu);
+ }
+ else {
+ bp= bp+(nu->pntsu-1);
+ if( bp->f1 & 1 ) {
+ nu2= nu;
+ }
+ }
+ }
+ else break;
+ }
+ }
+ nu= nu->next;
+ }
+
+ if((nu1 && nu2) && (nu1!=nu2)) {
+ if( nu1->type==nu2->type) {
+ if((nu1->type & 7)==CU_BEZIER) {
+ bezt =
+ (BezTriple*)MEM_mallocN((nu1->pntsu+nu2->pntsu) * sizeof(BezTriple), "addsegmentN");
+ memcpy(bezt, nu2->bezt, nu2->pntsu*sizeof(BezTriple));
+ memcpy(bezt+nu2->pntsu, nu1->bezt, nu1->pntsu*sizeof(BezTriple));
+ MEM_freeN(nu1->bezt);
+ nu1->bezt= bezt;
+ nu1->pntsu+= nu2->pntsu;
+ BLI_remlink(&editNurb, nu2);
+ freeNurb(nu2);
+ calchandlesNurb(nu1);
+ }
+ else {
+ bp =
+ (BPoint*)MEM_mallocN((nu1->pntsu+nu2->pntsu) * sizeof(BPoint), "addsegmentN2");
+ memcpy(bp, nu2->bp, nu2->pntsu*sizeof(BPoint) );
+ memcpy(bp+nu2->pntsu, nu1->bp, nu1->pntsu*sizeof(BPoint));
+ MEM_freeN(nu1->bp);
+ nu1->bp= bp;
+
+ a= nu1->pntsu+nu1->orderu;
+
+ nu1->pntsu+= nu2->pntsu;
+ BLI_remlink(&editNurb, nu2);
+
+ /* en de knots aaneenrijgen */
+ if((nu1->type & 7)==4) {
+ fp= MEM_mallocN(sizeof(float)*KNOTSU(nu1), "addsegment3");
+ memcpy(fp, nu1->knotsu, sizeof(float)*a);
+ MEM_freeN(nu1->knotsu);
+ nu1->knotsu= fp;
+
+
+ offset= nu1->knotsu[a-1] +1.0;
+ fp= nu1->knotsu+a;
+ for(a=0; a<nu2->pntsu; a++, fp++) {
+ if(nu2->knotsu)
+ *fp= offset+nu2->knotsu[a+1];
+ else
+ *fp = offset;
+ }
+ }
+ freeNurb(nu2);
+ }
+ }
+ makeDispList(G.obedit);
+ countall();
+ allqueue(REDRAWVIEW3D, 0);
+ }
+ else error("Can't make segment");
+}
+
+void mouse_nurb()
+{
+ Nurb *nu;
+ BezTriple *bezt=0;
+ BPoint *bp=0;
+ short hand;
+
+ hand= findnearestNurbvert(1, &nu, &bezt, &bp);
+
+ if(bezt || bp) {
+ if((G.qual & LR_SHIFTKEY)==0) {
+
+ setflagsNurb(0);
+
+ if(bezt) {
+
+ if(hand==1) {
+ bezt->f1|= 1;
+ bezt->f2|= 1;
+ bezt->f3|= 1;
+ }
+ else if(hand==0) bezt->f1|= 1;
+ else bezt->f3|= 1;
+ }
+ else {
+ lastselbp= bp;
+ bp->f1 |= 1;
+ }
+
+ allqueue(REDRAWVIEW3D, 0);
+ }
+ else {
+ if(bezt) {
+ if(hand==1) {
+ if(bezt->f2 & 1) {
+ bezt->f1 &= ~1;
+ bezt->f2 &= ~1;
+ bezt->f3 &= ~1;
+ }
+ else {
+ bezt->f1 |= 1;
+ bezt->f2 |= 1;
+ bezt->f3 |= 1;
+ }
+ }
+ else if(hand==0) {
+ if(bezt->f1 & 1) {
+ bezt->f1 &= ~1;
+ }
+ else {
+ bezt->f1 |= 1;
+ }
+ }
+ else {
+ if(bezt->f3 & 1) {
+ bezt->f3 &= ~1;
+ }
+ else {
+ bezt->f3 |= 1;
+ }
+ }
+ }
+ else {
+ if(bp->f1 & 1) bp->f1 &= ~1;
+ else {
+ bp->f1 |= 1;
+ lastselbp= bp;
+ }
+ }
+
+ allqueue(REDRAWVIEW3D, 0);
+
+ }
+
+ countall();
+ }
+
+ rightmouse_transform();
+
+ if(nu!=lastnu) {
+ lastnu= nu;
+ allqueue(REDRAWBUTSEDIT, 0);
+ }
+
+}
+
+void spinNurb(float *dvec, short mode)
+/* float *dvec; */
+/* short mode; */ /* 0 is extrude, 1 is duplicate */
+{
+ Nurb *nu;
+ float *curs, si,phi,n[3],q[4],cmat[3][3],tmat[3][3],imat[3][3];
+ float cent[3],bmat[3][3], rotmat[3][3], scalemat1[3][3], scalemat2[3][3];
+ float persmat[3][3], persinv[3][3];
+ short a,ok;
+
+ if(G.obedit==0 || G.obedit->type!=OB_SURF) return;
+ if( (G.vd->lay & G.obedit->lay)==0 ) return;
+
+ Mat3CpyMat4(persmat, G.vd->viewmat);
+ Mat3Inv(persinv, persmat);
+
+ /* imat en centrum en afmeting */
+ Mat3CpyMat4(bmat, G.obedit->obmat);
+ Mat3Inv(imat, bmat);
+
+ curs= give_cursor();
+ VECCOPY(cent, curs);
+ VecSubf(cent, cent, G.obedit->obmat[3]);
+ Mat3MulVecfl(imat,cent);
+
+ if(dvec) {
+ n[0]=n[1]= 0.0;
+ n[2]= 1.0;
+ } else {
+ n[0]= G.vd->viewinv[2][0];
+ n[1]= G.vd->viewinv[2][1];
+ n[2]= G.vd->viewinv[2][2];
+ Normalise(n);
+ }
+
+ phi= M_PI/8.0;
+ q[0]= cos(phi);
+ si= sin(phi);
+ q[1]= n[0]*si;
+ q[2]= n[1]*si;
+ q[3]= n[2]*si;
+ QuatToMat3(q, cmat);
+ Mat3MulMat3(tmat, cmat, bmat);
+ Mat3MulMat3(rotmat, imat, tmat);
+
+ Mat3One(scalemat1);
+ scalemat1[0][0]= sqrt(2.0);
+ scalemat1[1][1]= sqrt(2.0);
+
+ Mat3MulMat3(tmat,persmat,bmat);
+ Mat3MulMat3(cmat,scalemat1,tmat);
+ Mat3MulMat3(tmat,persinv,cmat);
+ Mat3MulMat3(scalemat1,imat,tmat);
+
+ Mat3One(scalemat2);
+ scalemat2[0][0]/= sqrt(2.0);
+ scalemat2[1][1]/= sqrt(2.0);
+
+ Mat3MulMat3(tmat,persmat,bmat);
+ Mat3MulMat3(cmat,scalemat2,tmat);
+ Mat3MulMat3(tmat,persinv,cmat);
+ Mat3MulMat3(scalemat2,imat,tmat);
+
+ ok= 1;
+
+ for(a=0;a<7;a++) {
+ if(mode==0) ok= extrudeflagNurb(1);
+ else adduplicateflagNurb(1);
+ if(ok==0) {
+ error("Can't spin");
+ break;
+ }
+ rotateflagNurb(1,cent,rotmat);
+
+ if(mode==0) {
+ if( (a & 1)==0 ) {
+ rotateflagNurb(1,cent,scalemat1);
+ weightflagNurb(1, 0.25*sqrt(2.0), 1);
+ }
+ else {
+ rotateflagNurb(1,cent,scalemat2);
+ weightflagNurb(1, 4.0/sqrt(2.0), 1);
+ }
+ }
+ if(dvec) {
+ Mat3MulVecfl(bmat,dvec);
+ translateflagNurb(1,dvec);
+ }
+ }
+
+ if(ok) {
+ nu= editNurb.first;
+ while(nu) {
+ if(isNurbsel(nu)) {
+ nu->orderv= 4;
+ nu->flagv |= 1;
+ makeknots(nu, 2, nu->flagv>>1);
+ }
+ nu= nu->next;
+ }
+ }
+}
+
+void addvert_Nurb(int mode)
+{
+ Nurb *nu;
+ BezTriple *bezt, *newbezt = NULL;
+ BPoint *bp, *newbp = NULL;
+ float *curs, mat[3][3],imat[3][3], temp[3];
+
+ if(G.obedit==0) return;
+ if( (G.vd->lay & G.obedit->lay)==0 ) return;
+
+ if(mode=='e' && okee("Extrude")==0) return;
+
+ Mat3CpyMat4(mat, G.obedit->obmat);
+ Mat3Inv(imat,mat);
+
+ findselectedNurbvert(&nu, &bezt, &bp);
+ if(bezt==0 && bp==0) return;
+
+ if((nu->type & 7)==CU_BEZIER) {
+ /* welk bezpoint? */
+ if(bezt== nu->bezt) { /* eerste */
+ bezt->f1= bezt->f2= bezt->f3= 0;
+ newbezt =
+ (BezTriple*)MEM_callocN((nu->pntsu+1) * sizeof(BezTriple), "addvert_Nurb");
+ memcpy(newbezt+1, bezt, nu->pntsu*sizeof(BezTriple));
+ *newbezt= *bezt;
+ newbezt->f1= newbezt->f2= newbezt->f3= 1;
+ if(bezt->h1 & 1) newbezt->h1= newbezt->h2= HD_AUTO;
+ else newbezt->h1= newbezt->h2= HD_VECT;
+ VECCOPY(temp, bezt->vec[1]);
+ MEM_freeN(nu->bezt);
+ nu->bezt= newbezt;
+ bezt= newbezt+1;
+ }
+ else if(bezt== (nu->bezt+nu->pntsu-1)) { /* laatste */
+ bezt->f1= bezt->f2= bezt->f3= 0;
+ newbezt =
+ (BezTriple*)MEM_callocN((nu->pntsu+1) * sizeof(BezTriple), "addvert_Nurb");
+ memcpy(newbezt, nu->bezt, nu->pntsu*sizeof(BezTriple));
+ *(newbezt+nu->pntsu)= *bezt;
+ VECCOPY(temp, bezt->vec[1]);
+ MEM_freeN(nu->bezt);
+ nu->bezt= newbezt;
+ newbezt+= nu->pntsu;
+ newbezt->f1= newbezt->f2= newbezt->f3= 1;
+ if(newbezt->h2 & 1) newbezt->h1= newbezt->h2= HD_AUTO;
+ else newbezt->h1= newbezt->h2= HD_VECT;
+ bezt= nu->bezt+nu->pntsu-1;
+ }
+ else bezt= 0;
+
+ if(bezt) {
+ nu->pntsu++;
+ newbezt->s[1][0]= G.vd->mx;
+ newbezt->s[1][1]= G.vd->my;
+
+ if(mode=='e') {
+ VECCOPY(newbezt->vec[0], bezt->vec[0]);
+ VECCOPY(newbezt->vec[1], bezt->vec[1]);
+ VECCOPY(newbezt->vec[2], bezt->vec[2]);
+ }
+ else {
+ curs= give_cursor();
+
+ VECCOPY(newbezt->vec[1], curs);
+ VecSubf(newbezt->vec[1],newbezt->vec[1],G.obedit->obmat[3]);
+ Mat3MulVecfl(imat,newbezt->vec[1]);
+ VecSubf(temp, newbezt->vec[1],temp);
+ VecAddf(newbezt->vec[0], bezt->vec[0],temp);
+ VecAddf(newbezt->vec[2], bezt->vec[2],temp);
+ calchandlesNurb(nu);
+ }
+ }
+ }
+ else if(nu->pntsv==1) {
+ /* welk b-point? */
+ if(bp== nu->bp) { /* eerste */
+ bp->f1= 0;
+ newbp =
+ (BPoint*)MEM_callocN((nu->pntsu+1) * sizeof(BPoint), "addvert_Nurb3");
+ memcpy(newbp+1, bp, nu->pntsu*sizeof(BPoint));
+ *newbp= *bp;
+ newbp->f1= 1;
+ MEM_freeN(nu->bp);
+ nu->bp= newbp;
+ }
+ else if(bp== (nu->bp+nu->pntsu-1)) { /* laatste */
+ bp->f1= 0;
+ newbp =
+ (BPoint*)MEM_callocN((nu->pntsu+1) * sizeof(BPoint), "addvert_Nurb4");
+ memcpy(newbp, nu->bp, nu->pntsu*sizeof(BPoint));
+ *(newbp+nu->pntsu)= *bp;
+ MEM_freeN(nu->bp);
+ nu->bp= newbp;
+ newbp+= nu->pntsu;
+ newbp->f1= 1;
+ }
+ else bp= 0;
+
+ if(bp) {
+ nu->pntsu++;
+ newbp->s[0]= G.vd->mx;
+ newbp->s[1]= G.vd->my;
+
+ if(nu->resolu<3) nu->resolu++;
+ makeknots(nu, 1, nu->flagu>>1);
+
+ if(mode=='e') {
+ VECCOPY(newbp->vec, bp->vec);
+ }
+ else {
+ curs= give_cursor();
+
+ VECCOPY(newbp->vec, curs);
+ VecSubf(newbp->vec, newbp->vec, G.obedit->obmat[3]);
+ Mat3MulVecfl(imat,newbp->vec);
+ newbp->vec[3]= 1.0;
+ }
+ }
+ }
+
+ test2DNurb(nu);
+ makeDispList(G.obedit);
+ countall();
+ allqueue(REDRAWVIEW3D, 0);
+
+ if(mode=='e') transform('d');
+ else while(get_mbut()&R_MOUSE) BIF_wait_for_statechange();
+}
+
+void extrude_nurb()
+{
+ Nurb *nu;
+ int ok= 0;
+
+ if(G.obedit && G.obedit->type==OB_SURF) {
+
+ /* first test: curve? */
+ nu= editNurb.first;
+ while(nu) {
+ if(nu->pntsv==1 && isNurbsel_count(nu)==1 ) break;
+ nu= nu->next;
+ }
+ if(nu) {
+ addvert_Nurb('e');
+ }
+ else {
+
+ if(okee("Extrude")==0) return;
+ ok= extrudeflagNurb(1); /* '1'= flag */
+
+ if(ok) {
+ makeDispList(G.obedit);
+ countall();
+ transform('d');
+ }
+ }
+ }
+}
+
+
+
+void makecyclicNurb()
+{
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ float *fp;
+ int a, b, cyclmode=0;
+
+ nu= editNurb.first;
+ while(nu) {
+ if( nu->pntsu>1 || nu->pntsv>1) {
+ if( (nu->type & 7)==0 ) {
+ a= nu->pntsu;
+ bp= nu->bp;
+ while(a--) {
+ if( bp->f1 & 1 ) {
+ if(nu->flagu & 1) nu->flagu--;
+ else nu->flagu++;
+ break;
+ }
+ bp++;
+ }
+ }
+ else if( (nu->type & 7)==CU_BEZIER ) {
+ a= nu->pntsu;
+ bezt= nu->bezt;
+ while(a--) {
+ if( BEZSELECTED(bezt) ) {
+ if(nu->flagu & 1) nu->flagu--;
+ else nu->flagu++;
+ break;
+ }
+ bezt++;
+ }
+ calchandlesNurb(nu);
+ }
+ else if(nu->pntsv==1 && (nu->type & 7)==CU_NURBS) {
+ a= nu->pntsu;
+ bp= nu->bp;
+ while(a--) {
+ if( bp->f1 & 1 ) {
+ if(nu->flagu & 1) nu->flagu--;
+ else {
+ nu->flagu++;
+ fp= MEM_mallocN(sizeof(float)*KNOTSU(nu), "makecyclicN");
+ b= (nu->orderu+nu->pntsu);
+ memcpy(fp, nu->knotsu, sizeof(float)*b);
+ MEM_freeN(nu->knotsu);
+ nu->knotsu= fp;
+
+ makeknots(nu, 1, 0); /* 1==u 0==uniform */
+
+ }
+ break;
+ }
+ bp++;
+ }
+ }
+ else if(nu->type==CU_NURBS) {
+ if(cyclmode==0) {
+ cyclmode= pupmenu("Toggle %t|cyclic U%x1|cyclic V%x2");
+ if(cyclmode < 1) return;
+ }
+ a= nu->pntsu*nu->pntsv;
+ bp= nu->bp;
+ while(a--) {
+
+ if( bp->f1 & 1) {
+ if(cyclmode==1 && nu->pntsu>1) {
+ if(nu->flagu & 1) nu->flagu--;
+ else {
+ nu->flagu++;
+ fp= MEM_mallocN(sizeof(float)*KNOTSU(nu), "makecyclicN");
+ b= (nu->orderu+nu->pntsu);
+ memcpy(fp, nu->knotsu, sizeof(float)*b);
+ MEM_freeN(nu->knotsu);
+ nu->knotsu= fp;
+
+ makeknots(nu, 1, 0); /* 1==u 0==uniform */
+ }
+ }
+ if(cyclmode==2 && nu->pntsv>1) {
+ if(nu->flagv & 1) nu->flagv--;
+ else {
+ nu->flagv++;
+ fp= MEM_mallocN(sizeof(float)*KNOTSV(nu), "makecyclicN");
+ b= (nu->orderv+nu->pntsv);
+ memcpy(fp, nu->knotsv, sizeof(float)*b);
+ MEM_freeN(nu->knotsv);
+ nu->knotsv= fp;
+
+ makeknots(nu, 2, 0); /* 2==v 0==uniform */
+ }
+ }
+ break;
+ }
+ bp++;
+ }
+
+ }
+ }
+ nu= nu->next;
+ }
+ makeDispList(G.obedit);
+}
+
+void selectconnected_nurb()
+{
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ int a;
+
+ findnearestNurbvert(1, &nu, &bezt, &bp);
+ if(bezt) {
+ a= nu->pntsu;
+ bezt= nu->bezt;
+ while(a--) {
+ if(bezt->hide==0) {
+ if(G.qual & LR_SHIFTKEY) {
+ bezt->f1 &= ~1;
+ bezt->f2 &= ~1;
+ bezt->f3 &= ~1;
+ }
+ else {
+ bezt->f1 |= 1;
+ bezt->f2 |= 1;
+ bezt->f3 |= 1;
+ }
+ }
+ bezt++;
+ }
+ }
+ else if(bp) {
+ a= nu->pntsu*nu->pntsv;
+ bp= nu->bp;
+ while(a--) {
+ if(bp->hide==0) {
+ if(G.qual & LR_SHIFTKEY) {
+ bp->f1 &= ~1;
+ }
+ else {
+ bp->f1 |= 1;
+ }
+ }
+ bp++;
+ }
+ }
+
+ countall();
+ allqueue(REDRAWVIEW3D, 0);
+}
+
+void selectrow_nurb()
+{
+ static BPoint *last=0;
+ static int direction=0;
+ Nurb *nu;
+ BPoint *bp;
+ int u = 0, v = 0, a, b, ok=0;
+
+ if(editNurb.first==0) return;
+ if(G.obedit==0 || G.obedit->type!=OB_SURF) return;
+ if(lastselbp==0) return;
+
+ /* zoek de juiste nurb en toggle met u of v */
+ nu= editNurb.first;
+ while(nu) {
+ bp= nu->bp;
+ for(v=0; v<nu->pntsv; v++) {
+ for(u=0; u<nu->pntsu; u++, bp++) {
+ if(bp==lastselbp) {
+ if(bp->f1 & 1) {
+ ok= 1;
+ break;
+ }
+ }
+ }
+ if(ok) break;
+ }
+ if(ok) {
+ if(last==lastselbp) {
+ direction= 1-direction;
+ setflagsNurb(0);
+ }
+ last= lastselbp;
+
+ bp= nu->bp;
+ for(a=0; a<nu->pntsv; a++) {
+ for(b=0; b<nu->pntsu; b++, bp++) {
+ if(direction) {
+ if(a==v) if(bp->hide==0) bp->f1 |= 1;
+ }
+ else {
+ if(b==u) if(bp->hide==0) bp->f1 |= 1;
+ }
+ }
+ }
+ countall();
+ allqueue(REDRAWVIEW3D, 0);
+ return;
+ }
+ nu= nu->next;
+ }
+}
+
+void adduplicate_nurb()
+{
+
+ if( (G.vd->lay & G.obedit->lay)==0 ) return;
+
+ adduplicateflagNurb(1);
+
+ countall();
+ transform('d');
+}
+
+void delNurb()
+{
+ Nurb *nu, *next, *nu1;
+ BezTriple *bezt, *bezt1, *bezt2;
+ BPoint *bp, *bp1, *bp2;
+ int a;
+ short event, cut = 0;
+
+ if(G.obedit==0 ) return;
+ if( (G.vd->lay & G.obedit->lay)==0 ) return;
+
+ if(G.obedit->type==OB_SURF) event= pupmenu("ERASE %t|Selected%x0|All%x2");
+ else event= pupmenu("ERASE %t|Selected%x0|Segment%x1|All%x2");
+
+ if(event== -1) return;
+
+ if(G.obedit->type==OB_SURF) {
+ if(event==0) deleteflagNurb(1);
+ else freeNurblist(&editNurb);
+
+ countall();
+ makeDispList(G.obedit);
+ allqueue(REDRAWVIEW3D, 0);
+ return;
+ }
+
+ if(event==0) {
+ /* eerste doorloop, kunnen hele stukken weg? */
+ nu= editNurb.first;
+ while(nu) {
+ next= nu->next;
+ if( (nu->type & 7)==CU_BEZIER ) {
+ bezt= nu->bezt;
+ a= nu->pntsu;
+ if(a) {
+ while(a) {
+ if( BEZSELECTED(bezt) );
+ else break;
+ a--;
+ bezt++;
+ }
+ if(a==0) {
+ BLI_remlink(&editNurb, nu);
+ freeNurb(nu);
+ }
+ }
+ }
+ else {
+ bp= nu->bp;
+ a= nu->pntsu*nu->pntsv;
+ if(a) {
+ while(a) {
+ if(bp->f1 & 1 );
+ else break;
+ a--;
+ bp++;
+ }
+ if(a==0) {
+ BLI_remlink(&editNurb, nu);
+ freeNurb(nu);
+ }
+ }
+ }
+ nu= next;
+ }
+ /* tweede doorloop, kleine stukken weg: alleen curves */
+ nu= editNurb.first;
+ while(nu) {
+ next= nu->next;
+ event= 0;
+ if( (nu->type & 7)==CU_BEZIER ) {
+ bezt= nu->bezt;
+ for(a=0;a<nu->pntsu;a++) {
+ if( BEZSELECTED(bezt) ) {
+ memcpy(bezt, bezt+1, (nu->pntsu-a-1)*sizeof(BezTriple));
+ nu->pntsu--;
+ a--;
+ event= 1;
+ }
+ else bezt++;
+ }
+ if(event) {
+ bezt1 =
+ (BezTriple*)MEM_mallocN((nu->pntsu) * sizeof(BezTriple), "delNurb");
+ memcpy(bezt1, nu->bezt, (nu->pntsu)*sizeof(BezTriple) );
+ MEM_freeN(nu->bezt);
+ nu->bezt= bezt1;
+ calchandlesNurb(nu);
+ }
+ }
+ else if(nu->pntsv==1) {
+ bp= nu->bp;
+
+ for(a=0;a<nu->pntsu;a++) {
+ if( bp->f1 & 1 ) {
+ memcpy(bp, bp+1, (nu->pntsu-a-1)*sizeof(BPoint));
+ nu->pntsu--;
+ a--;
+ event= 1;
+ }
+ else {
+ bp++;
+ }
+ }
+ if(event) {
+ bp1 = (BPoint*)MEM_mallocN(nu->pntsu * sizeof(BPoint), "delNurb2");
+ memcpy(bp1, nu->bp, (nu->pntsu)*sizeof(BPoint) );
+ MEM_freeN(nu->bp);
+ nu->bp= bp1;
+ }
+ makeknots(nu, 1, nu->flagu>>1);
+ }
+ nu= next;
+ }
+ }
+ else if(event==1) { /* erase segment */
+ /* vind de twee geselecteerde punten */
+ bezt1= bezt2= 0;
+ bp1= bp2= 0;
+ nu= editNurb.first;
+ nu1= 0;
+ while(nu) {
+ next= nu->next;
+ if( (nu->type & 7)==CU_BEZIER ) {
+ bezt= nu->bezt;
+ for(a=0; a<nu->pntsu-1; a++) {
+ if( BEZSELECTED(bezt) ) {
+ bezt1= bezt;
+ bezt2= bezt+1;
+ if( (bezt2->f1 & 1) || (bezt2->f2 & 1) || (bezt2->f3 & 1) ) ;
+ else { /* misschien niet cyclic maken */
+ if(a==0 && (nu->flagu & 1) ) {
+ bezt2= bezt+(nu->pntsu-1);
+ if( (bezt2->f1 & 1) || (bezt2->f2 & 1) || (bezt2->f3 & 1) ) {
+ nu->flagu--;
+ makeDispList(G.obedit);
+ allqueue(REDRAWVIEW3D, 0);
+ }
+ }
+ return;
+ }
+ cut= a;
+ nu1= nu;
+ break;
+ }
+ bezt++;
+ }
+ }
+ else if(nu->pntsv==1) {
+ bp= nu->bp;
+ for(a=0; a<nu->pntsu-1; a++) {
+ if( bp->f1 & 1 ) {
+ bp1= bp;
+ bp2= bp+1;
+ if( bp2->f1 & 1 ) ;
+ else { /* misschien niet cyclic maken */
+ if(a==0 && (nu->flagu & 1) ) {
+ bp2= bp+(nu->pntsu-1);
+ if( bp2->f1 & 1 ) {
+ nu->flagu--;
+ makeDispList(G.obedit);
+ allqueue(REDRAWVIEW3D, 0);
+ }
+ }
+ return;
+ }
+ cut= a;
+ nu1= nu;
+ break;
+ }
+ bp++;
+ }
+ }
+ if(nu1) break;
+
+ nu= nu->next;
+ }
+ if(nu1) {
+ if(bezt1) {
+ if(nu1->pntsu==2) { /* helemaal weg */
+ BLI_remlink(&editNurb, nu);
+ freeNurb(nu);
+ }
+ else if(nu1->flagu & 1) { /* cyclic */
+ bezt =
+ (BezTriple*)MEM_mallocN((cut+1) * sizeof(BezTriple), "delNurb1");
+ memcpy(bezt, nu1->bezt,(cut+1)*sizeof(BezTriple));
+ a= nu1->pntsu-cut-1;
+ memcpy(nu1->bezt, bezt2, a*sizeof(BezTriple));
+ memcpy(nu1->bezt+a, bezt, (cut+1)*sizeof(BezTriple));
+ nu1->flagu--;
+ MEM_freeN(bezt);
+ calchandlesNurb(nu);
+ }
+ else { /* nieuwe curve erbij */
+
+/* hier zit een fout in... maar waar? (a kan nul worden) */
+
+ nu =
+ (Nurb*)MEM_mallocN(sizeof(Nurb), "delNurb2");
+ memcpy(nu, nu1, sizeof(Nurb));
+ BLI_addtail(&editNurb, nu);
+ nu->bezt =
+ (BezTriple*)MEM_mallocN((cut+1) * sizeof(BezTriple), "delNurb3");
+ memcpy(nu->bezt, nu1->bezt,(cut+1)*sizeof(BezTriple));
+ a= nu1->pntsu-cut-1;
+
+ bezt =
+ (BezTriple*)MEM_mallocN(a * sizeof(BezTriple), "delNurb4");
+ memcpy(bezt, nu1->bezt+cut+1,a*sizeof(BezTriple));
+ MEM_freeN(nu1->bezt);
+ nu1->bezt= bezt;
+ nu1->pntsu= a;
+ nu->pntsu= cut+1;
+
+
+ calchandlesNurb(nu);
+ calchandlesNurb(nu1);
+ }
+ }
+ else if(bp1) {
+ if(nu1->pntsu==2) { /* helemaal weg */
+ BLI_remlink(&editNurb, nu);
+ freeNurb(nu);
+ }
+ else if(nu1->flagu & 1) { /* cyclic */
+ bp =
+ (BPoint*)MEM_mallocN((cut+1) * sizeof(BPoint), "delNurb5");
+ memcpy(bp, nu1->bp,(cut+1)*sizeof(BPoint));
+ a= nu1->pntsu-cut-1;
+ memcpy(nu1->bp, bp2, a*sizeof(BPoint));
+ memcpy(nu1->bp+a, bp, (cut+1)*sizeof(BPoint));
+ nu1->flagu--;
+ MEM_freeN(bp);
+ }
+ else { /* nieuwe curve erbij */
+ nu = (Nurb*)MEM_mallocN(sizeof(Nurb), "delNurb6");
+ memcpy(nu, nu1, sizeof(Nurb));
+ BLI_addtail(&editNurb, nu);
+ nu->bp =
+ (BPoint*)MEM_mallocN((cut+1) * sizeof(BPoint), "delNurb7");
+ memcpy(nu->bp, nu1->bp,(cut+1)*sizeof(BPoint));
+ a= nu1->pntsu-cut-1;
+ bp =
+ (BPoint*)MEM_mallocN(a * sizeof(BPoint), "delNurb8");
+ memcpy(bp, nu1->bp+cut+1,a*sizeof(BPoint));
+ MEM_freeN(nu1->bp);
+ nu1->bp= bp;
+ nu1->pntsu= a;
+ nu->pntsu= cut+1;
+ }
+ }
+ }
+ }
+ else if(event==2) {
+ freeNurblist(&editNurb);
+ }
+
+ countall();
+ makeDispList(G.obedit);
+ allqueue(REDRAWVIEW3D, 0);
+}
+
+
+void join_curve(int type)
+{
+ Base *base, *nextb;
+ Object *ob;
+ Curve *cu;
+ Nurb *nu, *newnu;
+ BezTriple *bezt;
+ BPoint *bp;
+ ListBase tempbase;
+ float imat[4][4], cmat[4][4];
+ int a;
+
+ if(G.obedit) return;
+
+ ob= OBACT;
+ if(ob->type!=type) return;
+ if(ob->lay & G.vd->lay); else return;
+ tempbase.first= tempbase.last= 0;
+
+ if(type==OB_SURF) {
+ if(okee("Join selected Nurbs")==0) return;
+ }
+ else if(okee("Join selected Curves")==0) return;
+
+ /* alle geselecteerde curves invers transformen in obact */
+ Mat4Invert(imat, ob->obmat);
+
+ base= FIRSTBASE;
+ while(base) {
+ nextb= base->next;
+ if TESTBASE(base) {
+ if(base->object->type==type) {
+ if(base->object != ob) {
+
+ cu= base->object->data;
+
+ if(cu->nurb.first) {
+ /* let op: matmul omkeren is ECHT fout */
+ Mat4MulMat4(cmat, base->object->obmat, imat);
+
+ nu= cu->nurb.first;
+ while(nu) {
+ newnu= duplicateNurb(nu);
+ BLI_addtail(&tempbase, newnu);
+
+ if( (bezt= newnu->bezt) ) {
+ a= newnu->pntsu;
+ while(a--) {
+ Mat4MulVecfl(cmat, bezt->vec[0]);
+ Mat4MulVecfl(cmat, bezt->vec[1]);
+ Mat4MulVecfl(cmat, bezt->vec[2]);
+ bezt++;
+ }
+ }
+ if( (bp= newnu->bp) ) {
+ a= newnu->pntsu*nu->pntsv;
+ while(a--) {
+ Mat4MulVecfl(cmat, bp->vec);
+ bp++;
+ }
+ }
+ nu= nu->next;
+ }
+ }
+
+ free_and_unlink_base(base);
+ }
+ }
+ }
+ base= nextb;
+ }
+
+ cu= ob->data;
+ addlisttolist(&cu->nurb, &tempbase);
+
+ enter_editmode();
+ exit_editmode(1);
+
+ allqueue(REDRAWVIEW3D, 0);
+}
+
+
+
+Nurb *addNurbprim(int type, int stype, int newname)
+/* type: &8= 2D; 0=poly,1 bez, 4 nurb
+ * stype: 0: 2/4 punts curve
+ * 1: 8 punts cirkel
+ * 2: 4x4 patch Nurb
+ * 3: tube 4:sphere 5:donut
+ * 6: 5 punts, 5e order rechte lijn (pad) alleen nurbspline!
+ */
+{
+ static int xzproj= 0;
+ Nurb *nu = NULL;
+ BezTriple *bezt;
+ BPoint *bp;
+ float *curs, cent[3],vec[3],imat[3][3],mat[3][3];
+ float fac,cmat[3][3];
+ int a, b;
+
+ /* imat en centrum en afmeting */
+ if(G.obedit) {
+
+ Mat3CpyMat4(mat, G.obedit->obmat);
+ curs= give_cursor();
+ VECCOPY(cent, curs);
+ cent[0]-= G.obedit->obmat[3][0];
+ cent[1]-= G.obedit->obmat[3][1];
+ cent[2]-= G.obedit->obmat[3][2];
+
+ Mat3CpyMat4(imat, G.vd->viewmat);
+ Mat3MulVecfl(imat, cent);
+ Mat3MulMat3(cmat, imat, mat);
+ Mat3Inv(imat, cmat);
+ setflagsNurb(0);
+ }
+ else {
+ Mat3One(imat);
+ cent[0]= cent[1]= cent[2]= 0.0;
+ }
+
+ if ELEM5(stype, 0, 1, 2, 4, 6) {
+ nu = (Nurb*)MEM_callocN(sizeof(Nurb), "addNurbprim");
+ nu->type= type;
+ nu->resolu= 12;
+ nu->resolv= 12;
+ /* if(G.obedit && (G.mainb==5 || G.mainb==9)) nu->col= 0; */
+ }
+
+ switch(stype) {
+ case 0: /* curve */
+ if(newname) {
+ rename_id((ID *)G.obedit, "Curve");
+ rename_id((ID *)G.obedit->data, "Curve");
+ }
+ if((type & 7)==CU_BEZIER) {
+ nu->pntsu= 2;
+ nu->bezt =
+ (BezTriple*)MEM_callocN(2 * sizeof(BezTriple), "addNurbprim1");
+ bezt= nu->bezt;
+ bezt->h1= bezt->h2= HD_ALIGN;
+ bezt->f1= bezt->f2= bezt->f3= 1;
+
+ for(a=0;a<3;a++) {
+ VECCOPY(bezt->vec[a], cent);
+ }
+ bezt->vec[1][0]+= -G.vd->grid;
+ bezt->vec[0][0]+= -1.5*G.vd->grid;
+ bezt->vec[0][1]+= -0.5*G.vd->grid;
+ bezt->vec[2][0]+= -0.5*G.vd->grid;
+ bezt->vec[2][1]+= 0.5*G.vd->grid;
+ for(a=0;a<3;a++) Mat3MulVecfl(imat, bezt->vec[a]);
+
+ bezt++;
+ bezt->h1= bezt->h2= HD_ALIGN;
+ bezt->f1= bezt->f2= bezt->f3= 1;
+
+ for(a=0;a<3;a++) {
+ VECCOPY(bezt->vec[a], cent);
+ }
+ bezt->vec[1][0]+= G.vd->grid;
+ for(a=0;a<3;a++) Mat3MulVecfl(imat, bezt->vec[a]);
+
+ calchandlesNurb(nu);
+ }
+ else {
+ nu->pntsu= 4;
+ nu->pntsv= 1;
+ nu->orderu= 4;
+ nu->bp= callocstructN(BPoint, 4, "addNurbprim3");
+
+ bp= nu->bp;
+ for(a=0;a<4;a++, bp++) {
+ VECCOPY(bp->vec, cent);
+ bp->vec[3]= 1.0;
+ bp->f1= 1;
+ }
+
+ bp= nu->bp;
+ bp->vec[0]+= -1.5*G.vd->grid;
+ bp++;
+ bp->vec[0]+= -G.vd->grid;
+ bp->vec[1]+= G.vd->grid;
+ bp++;
+ bp->vec[0]+= G.vd->grid;
+ bp->vec[1]+= G.vd->grid;
+ bp++;
+ bp->vec[0]+= 1.5*G.vd->grid;
+
+ bp= nu->bp;
+ for(a=0;a<4;a++, bp++) Mat3MulVecfl(imat,bp->vec);
+
+ if((type & 7)==4) {
+ nu->knotsu= 0; /* makeknots alloceert */
+ makeknots(nu, 1, nu->flagu>>1);
+ }
+
+ }
+ break;
+ case 6: /* 5 punts pad */
+ nu->pntsu= 5;
+ nu->pntsv= 1;
+ nu->orderu= 5;
+ nu->flagu= 2; /* endpoint */
+ nu->resolu= 32;
+ nu->bp= callocstructN(BPoint, 5, "addNurbprim3");
+
+ bp= nu->bp;
+ for(a=0;a<5;a++, bp++) {
+ VECCOPY(bp->vec, cent);
+ bp->vec[3]= 1.0;
+ bp->f1= 1;
+ }
+
+ bp= nu->bp;
+ bp->vec[0]+= -2.0*G.vd->grid;
+ bp++;
+ bp->vec[0]+= -G.vd->grid;
+ bp++; bp++;
+ bp->vec[0]+= G.vd->grid;
+ bp++;
+ bp->vec[0]+= 2.0*G.vd->grid;
+
+ bp= nu->bp;
+ for(a=0;a<5;a++, bp++) Mat3MulVecfl(imat,bp->vec);
+
+ if((type & 7)==4) {
+ nu->knotsu= 0; /* makeknots alloceert */
+ makeknots(nu, 1, nu->flagu>>1);
+ }
+
+ break;
+ case 1: /* cirkel */
+ if(newname) {
+ rename_id((ID *)G.obedit, "CurveCircle");
+ rename_id((ID *)G.obedit->data, "CurveCircle");
+ }
+ if((type & 7)==CU_BEZIER) {
+ nu->pntsu= 4;
+ nu->bezt= callocstructN(BezTriple, 4, "addNurbprim1");
+ nu->flagu= 1;
+ bezt= nu->bezt;
+
+ for(a=0;a<3;a++) {
+ VECCOPY(bezt->vec[a], cent);
+ }
+ bezt->h1= bezt->h2= HD_AUTO;
+ bezt->f1= bezt->f2= bezt->f3= 1;
+ bezt->vec[1][0]+= -G.vd->grid;
+ for(a=0;a<3;a++) Mat3MulVecfl(imat,bezt->vec[a]);
+
+ bezt++;
+ for(a=0;a<3;a++) {
+ VECCOPY(bezt->vec[a], cent);
+ }
+ bezt->h1= bezt->h2= HD_AUTO;
+ bezt->f1= bezt->f2= bezt->f3= 1;
+ bezt->vec[1][1]+= G.vd->grid;
+ for(a=0;a<3;a++) Mat3MulVecfl(imat,bezt->vec[a]);
+
+ bezt++;
+ for(a=0;a<3;a++) {
+ VECCOPY(bezt->vec[a], cent);
+ }
+ bezt->h1= bezt->h2= HD_AUTO;
+ bezt->f1= bezt->f2= bezt->f3= 1;
+ bezt->vec[1][0]+= G.vd->grid;
+ for(a=0;a<3;a++) Mat3MulVecfl(imat,bezt->vec[a]);
+
+ bezt++;
+ for(a=0;a<3;a++) {
+ VECCOPY(bezt->vec[a], cent);
+ }
+ bezt->h1= bezt->h2= HD_AUTO;
+ bezt->f1= bezt->f2= bezt->f3= 1;
+ bezt->vec[1][1]+= -G.vd->grid;
+ for(a=0;a<3;a++) Mat3MulVecfl(imat,bezt->vec[a]);
+
+ calchandlesNurb(nu);
+ }
+ else if( (type & 7)==CU_NURBS ) { /* nurb */
+ nu->pntsu= 8;
+ nu->pntsv= 1;
+ nu->orderu= 4;
+ nu->bp= callocstructN(BPoint, 8, "addNurbprim6");
+ nu->flagu= 1;
+ bp= nu->bp;
+
+ for(a=0; a<8; a++) {
+ bp->f1= 1;
+ VECCOPY(bp->vec, cent);
+
+ if(xzproj==0) {
+ bp->vec[0]+= nurbcircle[a][0]*G.vd->grid;
+ bp->vec[1]+= nurbcircle[a][1]*G.vd->grid;
+ }
+ else {
+ bp->vec[0]+= 0.25*nurbcircle[a][0]*G.vd->grid-.75*G.vd->grid;
+ bp->vec[2]+= 0.25*nurbcircle[a][1]*G.vd->grid;
+ }
+ if(a & 1) bp->vec[3]= 0.25*sqrt(2.0);
+ else bp->vec[3]= 1.0;
+ Mat3MulVecfl(imat,bp->vec);
+ bp++;
+ }
+
+ makeknots(nu, 1, nu->flagu>>1);
+ }
+ break;
+ case 2: /* 4x4 patch */
+ if( (type & 7)==CU_NURBS ) { /* nurb */
+ if(newname) {
+ rename_id((ID *)G.obedit, "Surf");
+ rename_id((ID *)G.obedit->data, "Surf");
+ }
+
+ nu->pntsu= 4;
+ nu->pntsv= 4;
+ nu->orderu= 4;
+ nu->orderv= 4;
+ nu->flag= ME_SMOOTH;
+ nu->bp= callocstructN(BPoint, 4*4, "addNurbprim6");
+ nu->flagu= 0;
+ nu->flagv= 0;
+ bp= nu->bp;
+
+ for(a=0; a<4; a++) {
+ for(b=0; b<4; b++) {
+ VECCOPY(bp->vec, cent);
+ bp->f1= 1;
+ fac= (float)a -1.5;
+ bp->vec[0]+= fac*G.vd->grid;
+ fac= (float)b -1.5;
+ bp->vec[1]+= fac*G.vd->grid;
+ if(a==1 || a==2) if(b==1 || b==2) {
+ bp->vec[2]+= G.vd->grid;
+ }
+ Mat3MulVecfl(imat,bp->vec);
+ bp->vec[3]= 1.0;
+ bp++;
+ }
+ }
+
+ makeknots(nu, 1, nu->flagu>>1);
+ makeknots(nu, 2, nu->flagv>>1);
+ }
+ break;
+ case 3: /* tube */
+ if( (type & 7)==CU_NURBS ) {
+ if(newname) {
+ rename_id((ID *)G.obedit, "SurfTube");
+ rename_id((ID *)G.obedit->data, "SurfTube");
+ }
+
+ nu= addNurbprim(4, 1, 0); /* cirkel */
+ nu->resolu= 32;
+ nu->flag= ME_SMOOTH;
+ BLI_addtail(&editNurb, nu); /* tijdelijk voor extrude en translate */
+ vec[0]=vec[1]= 0.0;
+ vec[2]= -G.vd->grid;
+ Mat3MulVecfl(imat, vec);
+ translateflagNurb(1, vec);
+ extrudeflagNurb(1);
+ vec[0]= -2*vec[0];
+ vec[1]= -2*vec[1];
+ vec[2]= -2*vec[2];
+ translateflagNurb(1, vec);
+
+ BLI_remlink(&editNurb, nu);
+
+ a= nu->pntsu*nu->pntsv;
+ bp= nu->bp;
+ while(a-- >0) {
+ bp->f1 |= 1;
+ bp++;
+ }
+ }
+ break;
+ case 4: /* sphere */
+ if( (type & 7)==CU_NURBS ) {
+ if(newname) {
+ rename_id((ID *)G.obedit, "SurfSphere");
+ rename_id((ID *)G.obedit->data, "SurfSphere");
+ }
+
+ nu->pntsu= 5;
+ nu->pntsv= 1;
+ nu->orderu= 3;
+ nu->resolu= 24;
+ nu->resolv= 32;
+ nu->flag= ME_SMOOTH;
+ nu->bp= callocstructN(BPoint, 5, "addNurbprim6");
+ nu->flagu= 0;
+ bp= nu->bp;
+
+ for(a=0; a<5; a++) {
+ bp->f1= 1;
+ VECCOPY(bp->vec, cent);
+ bp->vec[0]+= nurbcircle[a][0]*G.vd->grid;
+ bp->vec[2]+= nurbcircle[a][1]*G.vd->grid;
+ if(a & 1) bp->vec[3]= 0.5*sqrt(2.0);
+ else bp->vec[3]= 1.0;
+ Mat3MulVecfl(imat,bp->vec);
+ bp++;
+ }
+ nu->flagu= 4;
+ makeknots(nu, 1, nu->flagu>>1);
+
+ BLI_addtail(&editNurb, nu); /* tijdelijk voor spin */
+ spinNurb(0, 0);
+
+ makeknots(nu, 2, nu->flagv>>1);
+
+ a= nu->pntsu*nu->pntsv;
+ bp= nu->bp;
+ while(a-- >0) {
+ bp->f1 |= 1;
+ bp++;
+ }
+ BLI_remlink(&editNurb, nu);
+ }
+ break;
+ case 5: /* donut */
+ if( (type & 7)==CU_NURBS ) {
+ if(newname) {
+ rename_id((ID *)G.obedit, "SurfDonut");
+ rename_id((ID *)G.obedit->data, "SurfDonut");
+ }
+
+ xzproj= 1;
+ nu= addNurbprim(4, 1, 0); /* cirkel */
+ xzproj= 0;
+ nu->resolu= 24;
+ nu->resolv= 32;
+ nu->flag= ME_SMOOTH;
+ BLI_addtail(&editNurb, nu); /* tijdelijk voor extrude en translate */
+ spinNurb(0, 0);
+
+ BLI_remlink(&editNurb, nu);
+
+ a= nu->pntsu*nu->pntsv;
+ bp= nu->bp;
+ while(a-- >0) {
+ bp->f1 |= 1;
+ bp++;
+ }
+
+ }
+ break;
+ }
+
+ /* altijd doen: */
+ nu->flag= ME_SMOOTH;
+
+ test2DNurb(nu);
+
+ return nu;
+}
+
+void default_curve_ipo(Curve *cu)
+{
+ IpoCurve *icu;
+ BezTriple *bezt;
+
+ if(cu->ipo) return;
+
+ cu->ipo= add_ipo("CurveIpo", ID_CU);
+
+ icu= MEM_callocN(sizeof(IpoCurve), "ipocurve");
+
+ icu->blocktype= ID_CU;
+ icu->adrcode= CU_SPEED;
+ icu->flag= IPO_VISIBLE+IPO_SELECT;
+ set_icu_vars(icu);
+
+ BLI_addtail( &(cu->ipo->curve), icu);
+
+ icu->bezt= bezt= MEM_callocN(2*sizeof(BezTriple), "defaultipo");
+ icu->totvert= 2;
+
+ bezt->hide= IPO_BEZ;
+ bezt->f1=bezt->f2= bezt->f3= SELECT;
+ bezt->h1= bezt->h2= HD_AUTO;
+ bezt++;
+ bezt->vec[1][0]= 100.0;
+ bezt->vec[1][1]= 1.0;
+ bezt->hide= IPO_BEZ;
+ bezt->f1=bezt->f2= bezt->f3= SELECT;
+ bezt->h1= bezt->h2= HD_AUTO;
+
+ calchandles_ipocurve(icu);
+}
+
+void add_primitiveCurve(int stype)
+{
+ Nurb *nu;
+ Curve *cu;
+ int type, newname= 0;
+
+ if(G.scene->id.lib) return;
+
+ /* this function also comes from an info window */
+ if ELEM(curarea->spacetype, SPACE_VIEW3D, SPACE_INFO); else return;
+ if(G.vd==0) return;
+
+ if(stype>=10 && stype<20) type= CU_2D+1;
+ else if(stype>=20 && stype<30) type= CU_2D+2;
+ else if(stype>=30 && stype<40) type= CU_2D+3;
+ else if(stype>=40 && stype<50) {
+ if(stype==46) type= 4;
+ else type= CU_2D+4;
+ }
+ else type= CU_2D;
+
+ check_editmode(OB_CURVE);
+
+ /* als geen obedit: nieuw object en in editmode gaan */
+ if(G.obedit==0) {
+ add_object(OB_CURVE);
+ base_init_from_view3d(BASACT, G.vd);
+ G.obedit= BASACT->object;
+
+ where_is_object(G.obedit);
+
+ make_editNurb();
+ setcursor_space(SPACE_VIEW3D, CURSOR_EDIT);
+ newname= 1;
+
+ cu= G.obedit->data;
+ if(stype==46) {
+ cu->flag |= (CU_3D+CU_PATH);
+
+ default_curve_ipo(cu);
+ }
+ }
+ else cu= G.obedit->data;
+
+ if(cu->flag & CU_3D) type &= ~CU_2D;
+
+ stype= (stype % 10);
+
+ nu= addNurbprim(type, stype, newname); /* 2D */
+
+ BLI_addtail(&editNurb, nu);
+ makeDispList(G.obedit);
+
+ allqueue(REDRAWBUTSEDIT, 0);
+
+ countall();
+ allqueue(REDRAWVIEW3D, 0);
+}
+
+void add_primitiveNurb(int type)
+{
+ Nurb *nu;
+ int newname= 0;
+
+ if(G.scene->id.lib) return;
+ if ELEM(curarea->spacetype, SPACE_VIEW3D, SPACE_INFO); else return;
+
+ check_editmode(OB_SURF);
+
+ /* als geen obedit: nieuw object en in editmode gaan */
+ if(G.obedit==0) {
+ add_object(OB_SURF);
+ base_init_from_view3d(BASACT, G.vd);
+ G.obedit= BASACT->object;
+
+ where_is_object(G.obedit);
+
+ make_editNurb();
+ setcursor_space(SPACE_VIEW3D, CURSOR_EDIT);
+ newname= 1;
+ }
+
+ nu= addNurbprim(4, type, newname);
+ BLI_addtail(&editNurb,nu);
+ makeDispList(G.obedit);
+
+ allqueue(REDRAWBUTSEDIT, 0);
+
+ countall();
+ allqueue(REDRAWVIEW3D, 0);
+}
+
+
+
+void clear_tilt()
+{
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ int a;
+
+ if(okee("Clear tilt")==0) return;
+
+ nu= editNurb.first;
+ while(nu) {
+ if( nu->bezt ) {
+ bezt= nu->bezt;
+ a= nu->pntsu;
+ while(a--) {
+ if(BEZSELECTED(bezt)) bezt->alfa= 0.0;
+ bezt++;
+ }
+ }
+ else if(nu->bp) {
+ bp= nu->bp;
+ a= nu->pntsu*nu->pntsv;
+ while(a--) {
+ if(bp->f1 & 1) bp->alfa= 0.0;
+ bp++;
+ }
+ }
+ nu= nu->next;
+ }
+
+ makeBevelList(G.obedit);
+ allqueue(REDRAWVIEW3D, 0);
+}
+
+void clever_numbuts_curve()
+{
+ BPoint *bp;
+ BezTriple *bezt;
+ float old[3], delta[3];
+ int a;
+
+ if(lastnu==0) return;
+ if(lastnu->bp) {
+ bp= lastnu->bp;
+ a= lastnu->pntsu*lastnu->pntsv;
+ while(a--) {
+ if(bp->f1 & 1) break;
+ bp++;
+ }
+ if(bp==0) return;
+
+ add_numbut(0, NUM|FLO, "LocX:", -G.vd->far, G.vd->far, bp->vec, 0);
+ add_numbut(1, NUM|FLO, "LocY:", -G.vd->far, G.vd->far, bp->vec+1, 0);
+ add_numbut(2, NUM|FLO, "LocZ:", -G.vd->far, G.vd->far, bp->vec+2, 0);
+ add_numbut(3, NUM|FLO, " W:", 0.0, 100.0, bp->vec+3, 0);
+
+ do_clever_numbuts("Active BPoint", 4, REDRAW);
+ makeDispList(G.obedit);
+ }
+ else if(lastnu->bezt) {
+ bezt= lastnu->bezt;
+ a= lastnu->pntsu;
+ while(a--) {
+ if(BEZSELECTED(bezt)) break;
+ bezt++;
+ }
+ if(bezt==0) return;
+
+ if(bezt->f2 & 1) {
+ add_numbut(0, NUM|FLO, "LocX:", -G.vd->far, G.vd->far, bezt->vec[1], 0);
+ add_numbut(1, NUM|FLO, "LocY:", -G.vd->far, G.vd->far, bezt->vec[1]+1, 0);
+ add_numbut(2, NUM|FLO, "LocZ:", -G.vd->far, G.vd->far, bezt->vec[1]+2, 0);
+ VECCOPY(old, bezt->vec[1]);
+ do_clever_numbuts("Active BezierPoint", 3, REDRAW);
+
+ VecSubf(delta, bezt->vec[1], old);
+ VecAddf(bezt->vec[0], bezt->vec[0], delta);
+ VecAddf(bezt->vec[2], bezt->vec[2], delta);
+ makeDispList(G.obedit);
+ }
+ else if(bezt->f1 & 1) {
+ add_numbut(0, NUM|FLO, "LocX:", -G.vd->far, G.vd->far, bezt->vec[0], 0);
+ add_numbut(1, NUM|FLO, "LocY:", -G.vd->far, G.vd->far, bezt->vec[0]+1, 0);
+ add_numbut(2, NUM|FLO, "LocZ:", -G.vd->far, G.vd->far, bezt->vec[0]+2, 0);
+
+ do_clever_numbuts("Active HandlePoint", 3, REDRAW);
+ }
+ else if(bezt->f3 & 1) {
+ add_numbut(0, NUM|FLO, "LocX:", -G.vd->far, G.vd->far, bezt->vec[0], 0);
+ add_numbut(1, NUM|FLO, "LocY:", -G.vd->far, G.vd->far, bezt->vec[2]+1, 0);
+ add_numbut(2, NUM|FLO, "LocZ:", -G.vd->far, G.vd->far, bezt->vec[2]+2, 0);
+
+ do_clever_numbuts("Active HandlePoint", 3, REDRAW);
+ }
+ }
+
+}
+
+int bezt_compare (const void *e1, const void *e2)
+{
+ BezTriple *b1 = *((BezTriple**)e1);
+ BezTriple *b2 = *((BezTriple**)e2);
+
+ /* Check numerical values */
+ float val = b1->vec[1][0] - b2->vec[1][0];
+
+ if (val<0)
+ return -1;
+
+ if (val>0)
+ return 1;
+
+ /* Check selected flags : Ensures that selected keys will be listed first */
+
+ if ((b1->f2 & 1) && !(b2->f2 & 1))
+ return -1;
+ if (!(b1->f2 & 1) && (b2->f2 & 1))
+ return 1;
+
+ return 0;
+}
diff --git a/source/blender/src/editdeform.c b/source/blender/src/editdeform.c
new file mode 100644
index 00000000000..7bce1aaa695
--- /dev/null
+++ b/source/blender/src/editdeform.c
@@ -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 *****
+ * Creator-specific support for vertex deformation groups
+ */
+
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_editVert.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+
+#include "BKE_global.h"
+#include "BKE_deform.h"
+#include "BKE_mesh.h"
+
+#include "BIF_editdeform.h"
+#include "BIF_toolbox.h"
+
+void sel_verts_defgroup (int select)
+{
+ EditVert *eve;
+ Object *ob;
+ int i;
+
+ ob=G.obedit;
+
+ if (!ob)
+ return;
+
+ switch (ob->type){
+ case OB_MESH:
+ for (eve=G.edve.first; eve; eve=eve->next){
+ if (eve->totweight){
+ for (i=0; i<eve->totweight; i++){
+ if (eve->dw[i].def_nr == (ob->actdef-1)){
+ if (select) eve->f |= 1;
+ else eve->f &= ~1;
+ break;
+ }
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+}
+
+MDeformWeight *verify_defweight (MDeformVert *dv, int defgroup)
+/* Ensures that mv has a deform weight entry for
+the specified defweight group */
+{
+ int i;
+ MDeformWeight *newdw;
+
+ if (!dv)
+ return NULL;
+
+ for (i=0; i<dv->totweight; i++){
+ if (dv->dw[i].def_nr == defgroup)
+ return dv->dw+i;
+ }
+
+ newdw = MEM_callocN (sizeof(MDeformWeight)*(dv->totweight+1), "deformWeight");
+ if (dv->dw){
+ memcpy (newdw, dv->dw, sizeof(MDeformWeight)*dv->totweight);
+ MEM_freeN (dv->dw);
+ }
+ dv->dw=newdw;
+
+ dv->dw[dv->totweight].weight=0;
+ dv->dw[dv->totweight].def_nr=defgroup;
+ /* Group index */
+
+ dv->totweight++;
+
+ return dv->dw+(dv->totweight-1);
+}
+
+void add_defgroup (Object *ob)
+{
+ bDeformGroup *defgroup;
+
+ if (!ob)
+ return;
+
+ defgroup = MEM_callocN (sizeof(bDeformGroup), "deformGroup");
+ strcpy (defgroup->name, "Group");
+
+ BLI_addtail(&ob->defbase, defgroup);
+ unique_vertexgroup_name(defgroup, ob);
+
+ ob->actdef = BLI_countlist(&ob->defbase);
+}
+
+void del_defgroup (Object *ob)
+{
+ bDeformGroup *defgroup;
+ EditVert *eve;
+ int i;
+
+
+ if (!ob)
+ return;
+
+ if (!ob->actdef)
+ return;
+
+ defgroup = BLI_findlink(&ob->defbase, ob->actdef-1);
+ if (!defgroup)
+ return;
+
+ /* Make sure that no verts are using this group */
+ remove_verts_defgroup(1);
+
+ /* Make sure that any verts with higher indices are adjusted accordingly */
+ for (eve=G.edve.first; eve; eve=eve->next){
+ for (i=0; i<eve->totweight; i++){
+ if (eve->dw[i].def_nr > (ob->actdef-1))
+ eve->dw[i].def_nr--;
+ }
+ }
+
+ /* Update the active material index if necessary */
+ if (ob->actdef==BLI_countlist(&ob->defbase))
+ ob->actdef--;
+
+ /* Remove the group */
+ BLI_freelinkN (&ob->defbase, defgroup);
+}
+
+void assign_verts_defgroup (void)
+/* Only available in editmode */
+{
+ Object *ob;
+ EditVert *eve;
+ bDeformGroup *dg, *eg;
+ extern float editbutvweight; /* buttons.c */
+ int i, done;
+ MDeformWeight *newdw;
+
+ ob=G.obedit;
+
+ if (!ob)
+ return;
+
+ dg=BLI_findlink(&ob->defbase, ob->actdef-1);
+ if (!dg){
+ error ("No vertex group active");
+ return;
+ }
+
+ switch (ob->type){
+ case OB_MESH:
+ /* Go through the list of editverts and assign them */
+ for (eve=G.edve.first; eve; eve=eve->next){
+ if (eve->f & 1){
+ done=0;
+ /* See if this vert already has a reference to this group */
+ /* If so: Change its weight */
+ done=0;
+ for (i=0; i<eve->totweight; i++){
+ eg = BLI_findlink (&ob->defbase, eve->dw[i].def_nr);
+ /* Find the actual group */
+ if (eg==dg){
+ eve->dw[i].weight=editbutvweight;
+ done=1;
+ break;
+ }
+ }
+ /* If not: Add the group and set its weight */
+ if (!done){
+ newdw = MEM_callocN (sizeof(MDeformWeight)*(eve->totweight+1), "deformWeight");
+ if (eve->dw){
+ memcpy (newdw, eve->dw, sizeof(MDeformWeight)*eve->totweight);
+ MEM_freeN (eve->dw);
+ }
+ eve->dw=newdw;
+
+ eve->dw[eve->totweight].weight=editbutvweight;
+ eve->dw[eve->totweight].def_nr=ob->actdef-1;
+
+ eve->totweight++;
+
+ }
+ }
+ }
+ break;
+ default:
+ printf ("Assigning deformation groups to unknown object type: Warn <reevan@blender.nl>\n");
+ break;
+ }
+
+}
+
+void remove_verts_defgroup (int allverts)
+/* Only available in editmode */
+{
+ Object *ob;
+ EditVert *eve;
+ MDeformWeight *newdw;
+ bDeformGroup *dg, *eg;
+ int i;
+
+ ob=G.obedit;
+
+ if (!ob)
+ return;
+
+ dg=BLI_findlink(&ob->defbase, ob->actdef-1);
+ if (!dg){
+ error ("No vertex group active");
+ return;
+ }
+
+ switch (ob->type){
+ case OB_MESH:
+ for (eve=G.edve.first; eve; eve=eve->next){
+ if (eve->dw && ((eve->f & 1) || allverts)){
+ for (i=0; i<eve->totweight; i++){
+ /* Find group */
+ eg = BLI_findlink (&ob->defbase, eve->dw[i].def_nr);
+ if (eg == dg){
+ eve->totweight--;
+ if (eve->totweight){
+ newdw = MEM_mallocN (sizeof(MDeformWeight)*(eve->totweight), "deformWeight");
+
+ if (eve->dw){
+ memcpy (newdw, eve->dw, sizeof(MDeformWeight)*i);
+ memcpy (newdw+i, eve->dw+i+1, sizeof(MDeformWeight)*(eve->totweight-i));
+ MEM_freeN (eve->dw);
+ }
+ eve->dw=newdw;
+ }
+ else{
+ MEM_freeN (eve->dw);
+ eve->dw=NULL;
+ }
+ }
+ }
+ }
+ }
+ break;
+ default:
+ printf ("Removing deformation groups from unknown object type: Warn <reevan@blender.nl>\n");
+ break;
+ }
+}
+
+void verify_defgroups (Object *ob)
+{
+ /* Ensure the defbase & the dverts match */
+ switch (ob->type){
+ case OB_MESH:
+ if (!ob->defbase.first){
+ if (((Mesh*)ob->data)->dvert){
+ free_dverts(((Mesh*)ob->data)->dvert, ((Mesh*)ob->data)->totvert);
+ ((Mesh*)ob->data)->dvert=NULL;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+void unique_vertexgroup_name (bDeformGroup *dg, Object *ob)
+{
+ char tempname[64];
+ int number;
+ char *dot;
+ int exists = 0;
+ bDeformGroup *curdef;
+
+ if (!ob)
+ return;
+ /* See if we even need to do this */
+ for (curdef = ob->defbase.first; curdef; curdef=curdef->next){
+ if (dg!=curdef){
+ if (!strcmp(curdef->name, dg->name)){
+ exists = 1;
+ break;
+ }
+ }
+ }
+
+ if (!exists)
+ return;
+
+ /* Strip off the suffix */
+ dot=strchr(dg->name, '.');
+ if (dot)
+ *dot=0;
+
+ for (number = 1; number <=999; number++){
+ sprintf (tempname, "%s.%03d", dg->name, number);
+
+ exists = 0;
+ for (curdef=ob->defbase.first; curdef; curdef=curdef->next){
+ if (dg!=curdef){
+ if (!strcmp (curdef->name, tempname)){
+ exists = 1;
+ break;
+ }
+ }
+ }
+ if (!exists){
+ strcpy (dg->name, tempname);
+ return;
+ }
+ }
+}
diff --git a/source/blender/src/editface.c b/source/blender/src/editface.c
new file mode 100644
index 00000000000..8ae3b2a7035
--- /dev/null
+++ b/source/blender/src/editface.c
@@ -0,0 +1,1338 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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>
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "MTC_matrixops.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "DNA_image_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+#include "DNA_space_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_view3d_types.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_displist.h"
+#include "BKE_global.h"
+#include "BKE_mesh.h"
+#include "BKE_texture.h"
+
+#include "BSE_view.h"
+#include "BSE_edit.h"
+#include "BSE_drawview.h" /* for backdrawview3d */
+
+#include "BIF_interface.h"
+#include "BIF_mywindow.h"
+#include "BIF_toolbox.h"
+#include "BIF_screen.h"
+#include "BIF_gl.h"
+#include "BIF_graphics.h"
+#include "BIF_space.h" /* for allqueue */
+
+#include "BDR_drawmesh.h"
+#include "BDR_editface.h"
+#include "BDR_vpaint.h"
+
+#include "BDR_editface.h"
+#include "BDR_vpaint.h"
+
+#include "mydevice.h"
+#include "blendef.h"
+#include "render.h"
+
+/* #include "graphics.h" */
+// #include "blendef.h"
+#include "interface.h"
+#include "TPT_DependKludge.h"
+
+#ifdef NAN_TPT
+#include "../img/IMG_Api.h"
+#include "BSE_trans_types.h"
+#endif /* NAN_TPT */
+
+TFace *lasttface=0;
+
+void set_lasttface()
+{
+ Mesh *me;
+ TFace *tface;
+ int a;
+
+ lasttface= 0;
+
+ me= get_mesh(OBACT);
+ if(me==0 || me->tface==0) return;
+
+ tface= me->tface;
+ a= me->totface;
+ while(a--) {
+ if(tface->flag & TF_ACTIVE) {
+ lasttface= tface;
+ return;
+ }
+ tface++;
+ }
+
+ tface= me->tface;
+ a= me->totface;
+ while(a--) {
+ if(tface->flag & TF_SELECT) {
+ lasttface= tface;
+ return;
+ }
+ tface++;
+ }
+
+ tface= me->tface;
+ a= me->totface;
+ while(a--) {
+ if((tface->flag & TF_HIDE)==0) {
+ lasttface= tface;
+ return;
+ }
+ tface++;
+ }
+}
+
+void default_uv(float uv[][2], float size)
+{
+ int dy;
+
+ if(size>1.0) size= 1.0;
+
+ dy= 1.0-size;
+
+ uv[0][0]= 0;
+ uv[0][1]= size+dy;
+
+ uv[1][0]= 0;
+ uv[1][1]= dy;
+
+ uv[2][0]= size;
+ uv[2][1]= dy;
+
+ uv[3][0]= size;
+ uv[3][1]= size+dy;
+
+
+}
+
+void default_tface(TFace *tface)
+{
+ default_uv(tface->uv, 1.0);
+
+ tface->col[0]= tface->col[1]= tface->col[2]= tface->col[3]= vpaint_get_current_col();
+
+ tface->mode= TF_TEX;
+ tface->mode= 0;
+ tface->flag= TF_SELECT;
+ tface->tpage= 0;
+ tface->mode |= TF_DYNAMIC;
+}
+
+void make_tfaces(Mesh *me)
+{
+ TFace *tface;
+ int a;
+
+ a= me->totface;
+ if(a==0) return;
+ tface= me->tface= MEM_callocN(a*sizeof(TFace), "tface");
+ while(a--) {
+ default_tface(tface);
+ tface++;
+ }
+ if(me->mcol) {
+ mcol_to_tface(me, 1);
+ }
+}
+
+void reveal_tface()
+{
+ Mesh *me;
+ TFace *tface;
+ int a;
+
+ me= get_mesh(OBACT);
+ if(me==0 || me->tface==0 || me->totface==0) return;
+
+ tface= me->tface;
+ a= me->totface;
+ while(a--) {
+ if(tface->flag & TF_HIDE) {
+ tface->flag |= TF_SELECT;
+ tface->flag -= TF_HIDE;
+ }
+ tface++;
+ }
+
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWIMAGE, 0);
+}
+
+
+
+void hide_tface()
+{
+ Mesh *me;
+ TFace *tface;
+ int a;
+
+ me= get_mesh(OBACT);
+ if(me==0 || me->tface==0 || me->totface==0) return;
+
+ if(G.qual & LR_ALTKEY) {
+ reveal_tface();
+ return;
+ }
+
+ tface= me->tface;
+ a= me->totface;
+ while(a--) {
+ if(tface->flag & TF_HIDE);
+ else {
+ if(G.qual & LR_SHIFTKEY) {
+ if( (tface->flag & TF_SELECT)==0) tface->flag |= TF_HIDE;
+ }
+ else {
+ if( (tface->flag & TF_SELECT)) tface->flag |= TF_HIDE;
+ }
+ }
+ if(tface->flag & TF_HIDE) tface->flag &= ~TF_SELECT;
+
+ tface++;
+ }
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWIMAGE, 0);
+
+}
+
+void select_linked_tfaces()
+{
+ Mesh *me;
+ TFace *tface;
+ MFace *mface;
+ int a, doit=1;
+ char *cpmain;
+
+ me= get_mesh(OBACT);
+ if(me==0 || me->tface==0 || me->totface==0) return;
+
+ cpmain= MEM_callocN(me->totvert, "cpmain");
+
+ while(doit) {
+ doit= 0;
+
+ /* select connected: array vullen */
+ tface= me->tface;
+ mface= me->mface;
+ a= me->totface;
+ while(a--) {
+ if(tface->flag & TF_HIDE);
+ else if(tface->flag & TF_SELECT) {
+ if( mface->v3) {
+ cpmain[mface->v1]= 1;
+ cpmain[mface->v2]= 1;
+ cpmain[mface->v3]= 1;
+ if(mface->v4) cpmain[mface->v4]= 1;
+ }
+ }
+ tface++; mface++;
+ }
+
+ /* omgekeerd: vanuit array vlakken selecteren */
+
+ tface= me->tface;
+ mface= me->mface;
+ a= me->totface;
+ while(a--) {
+ if(tface->flag & TF_HIDE);
+ else if((tface->flag & TF_SELECT)==0) {
+ if( mface->v3) {
+ if(mface->v4) {
+ if(cpmain[mface->v4]) {
+ tface->flag |= TF_SELECT;
+ doit= 1;
+ }
+ }
+ if( cpmain[mface->v1] || cpmain[mface->v2] || cpmain[mface->v3] ) {
+ tface->flag |= TF_SELECT;
+ doit= 1;
+ }
+ }
+ }
+ tface++; mface++;
+ }
+
+ }
+ MEM_freeN(cpmain);
+
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWIMAGE, 0);
+
+}
+
+void deselectall_tface()
+{
+ Mesh *me;
+ TFace *tface;
+ int a, sel;
+
+ me= get_mesh(OBACT);
+ if(me==0 || me->tface==0) return;
+
+ tface= me->tface;
+ a= me->totface;
+ sel= 0;
+ while(a--) {
+ if(tface->flag & TF_HIDE);
+ else if(tface->flag & TF_SELECT) sel= 1;
+ tface++;
+ }
+
+ tface= me->tface;
+ a= me->totface;
+ while(a--) {
+ if(tface->flag & TF_HIDE);
+ else {
+ if(sel) tface->flag &= ~TF_SELECT;
+ else tface->flag |= TF_SELECT;
+ }
+ tface++;
+ }
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWIMAGE, 0);
+
+}
+
+void rotate_uv_tface()
+{
+ Mesh *me;
+ TFace *tface;
+ MFace *mface;
+ short mode;
+ int a;
+
+ me= get_mesh(OBACT);
+ if(me==0 || me->tface==0) return;
+
+ mode= pupmenu("OK? %t|Rot UV %x1|Rot VertexCol %x2");
+
+ if(mode<1) return;
+
+ tface= me->tface;
+ mface= me->mface;
+ a= me->totface;
+ while(a--) {
+ if(tface->flag & TF_SELECT) {
+ if(mode==1) {
+ float u1= tface->uv[0][0];
+ float v1= tface->uv[0][1];
+
+ tface->uv[0][0]= tface->uv[1][0];
+ tface->uv[0][1]= tface->uv[1][1];
+
+ tface->uv[1][0]= tface->uv[2][0];
+ tface->uv[1][1]= tface->uv[2][1];
+
+ if(mface->v4) {
+ tface->uv[2][0]= tface->uv[3][0];
+ tface->uv[2][1]= tface->uv[3][1];
+
+ tface->uv[3][0]= u1;
+ tface->uv[3][1]= v1;
+ }
+ else {
+ tface->uv[2][0]= u1;
+ tface->uv[2][1]= v1;
+ }
+ }
+ else if(mode==2) {
+ unsigned int tcol= tface->col[0];
+
+ tface->col[0]= tface->col[1];
+ tface->col[1]= tface->col[2];
+
+ if(mface->v4) {
+ tface->col[2]= tface->col[3];
+ tface->col[3]= tcol;
+ }
+ else {
+ tface->col[2]= tcol;
+ }
+ }
+ }
+ tface++;
+ mface++;
+ }
+
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWIMAGE, 0);
+}
+
+/**
+ * Returns the face under the give position in screen coordinates.
+ * Code extracted from face_select routine.
+ * Question: why is all of the backbuffer drawn?
+ * We're only interested in one pixel!
+ * @author Maarten Gribnau
+ * @param me the mesh with the faces to be picked
+ * @param x the x-coordinate to pick at
+ * @param y the y-coordinate to pick at
+ * @return the face under the cursor (0 if there was no face found)
+ */
+TFace* face_pick(Mesh *me, short x, short y)
+{
+ unsigned int col;
+ int index;
+ TFace *ret = 0;
+
+ if (me==0 || me->tface==0) {
+ return ret;
+ }
+
+ /* Have OpenGL draw in the back buffer with color coded face indices */
+ if (curarea->win_swap==WIN_EQUAL) {
+ G.vd->flag |= V3D_NEEDBACKBUFDRAW;
+ }
+ if (G.vd->flag & V3D_NEEDBACKBUFDRAW) {
+ backdrawview3d(0);
+ }
+ /* Read the pixel under the cursor */
+ glReadPixels(x+curarea->winrct.xmin, y+curarea->winrct.ymin, 1, 1,
+ GL_RGBA, GL_UNSIGNED_BYTE, &col);
+ /* Unbelievable! */
+ if (G.order==B_ENDIAN) {
+ SWITCH_INT(col);
+ }
+ /* Convert the color back to a face index */
+ index = framebuffer_to_index(col);
+ if (col==0 || index<=0 || index>me->totface) {
+ return ret;
+ }
+ /* Return the face */
+ ret = ((TFace*)me->tface) + (index-1);
+ return ret;
+}
+
+void face_select()
+{
+ Object *ob;
+ Mesh *me;
+ TFace *tface, *tsel;
+ short mval[2];
+ int a;
+
+ /* Get the face under the cursor */
+ ob = OBACT;
+ if (!(ob->lay & G.vd->lay)) {
+ error("Active object not in this layer!");
+ }
+ me = get_mesh(ob);
+ getmouseco_areawin(mval);
+ tsel = face_pick(me, mval[0], mval[1]);
+ if (!tsel) return;
+
+ if (tsel->flag & TF_HIDE) return;
+
+ /* clear flags */
+ tface = me->tface;
+ a = me->totface;
+ while (a--) {
+ if (G.qual & LR_SHIFTKEY) {
+ tface->flag &= ~TF_ACTIVE;
+ }
+ else {
+ tface->flag &= ~(TF_ACTIVE+TF_SELECT);
+ }
+ tface++;
+ }
+
+ tsel->flag |= TF_ACTIVE;
+
+ if (G.qual & LR_SHIFTKEY) {
+ if (tsel->flag & TF_SELECT) {
+ tsel->flag &= ~TF_SELECT;
+ }
+ else {
+ tsel->flag |= TF_SELECT;
+ }
+ }
+ else {
+ tsel->flag |= TF_SELECT;
+ }
+
+ lasttface = tsel;
+
+ /* image window redraw */
+ allqueue(REDRAWIMAGE, 0);
+ allqueue(REDRAWBUTSGAME, 0);
+ allqueue(REDRAWVIEW3D, 0);
+}
+
+
+void face_borderselect()
+{
+ Mesh *me;
+ TFace *tface;
+ rcti rect;
+ unsigned int *rectm, *rt;
+ int a, sx, sy, index, val;
+ char *selar;
+
+ me= get_mesh(OBACT);
+ if(me==0 || me->tface==0) return;
+ if(me->totface==0) return;
+
+ val= get_border(&rect, 3);
+
+ /* why readbuffer here? shouldn't be necessary */
+ glReadBuffer(GL_BACK);
+
+ if(val) {
+ selar= MEM_callocN(me->totface+1, "selar");
+
+ sx= (rect.xmax-rect.xmin+1);
+ sy= (rect.ymax-rect.ymin+1);
+ if(sx*sy<=0) return;
+
+ rt=rectm= MEM_mallocN(sizeof(int)*sx*sy, "selrect");
+ glReadPixels(rect.xmin+curarea->winrct.xmin, rect.ymin+curarea->winrct.ymin, sx, sy, GL_RGBA, GL_UNSIGNED_BYTE, rectm);
+ if(G.order==B_ENDIAN) IMB_convert_rgba_to_abgr(sx*sy, rectm);
+
+ a= sx*sy;
+ while(a--) {
+ if(*rt) {
+ index= framebuffer_to_index(*rt);
+ if(index<=me->totface) selar[index]= 1;
+ }
+ rt++;
+ }
+
+ tface= me->tface;
+ for(a=1; a<=me->totface; a++, tface++) {
+ if(selar[a]) {
+ if(tface->flag & TF_HIDE);
+ else {
+ if(val==LEFTMOUSE) tface->flag |= TF_SELECT;
+ else tface->flag &= ~TF_SELECT;
+ }
+ }
+ }
+
+ MEM_freeN(rectm);
+ MEM_freeN(selar);
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWIMAGE, 0);
+ }
+}
+
+#define TEST_STRUBI 1
+#ifdef TEST_STRUBI
+float CalcNormUV(float *a, float *b, float *c)
+{
+ float d1[3], d2[3];
+
+ d1[0] = a[0] - b[0];
+ d1[1] = a[1] - b[1];
+ d2[0] = b[0] - c[0];
+ d2[1] = b[1] - c[1];
+ return (d1[0] * d2[1] - d1[1] * d2[0]);
+}
+#endif
+
+
+/* Pupmenu codes: */
+#define UV_CUBE_MAPPING 2
+#define UV_CYL_MAPPING 3
+#define UV_SPHERE_MAPPING 4
+#define UV_BOUNDS4_MAPPING 65
+#define UV_BOUNDS2_MAPPING 66
+#define UV_BOUNDS1_MAPPING 67
+#define UV_STD4_MAPPING 130
+#define UV_STD2_MAPPING 129
+#define UV_STD1_MAPPING 128
+#define UV_WINDOW_MAPPING 5
+
+/* Some macro tricks to make pupmenu construction look nicer :-)
+ Sorry, just did it for fun. */
+
+#define _STR(x) " " #x
+#define STRING(x) _STR(x)
+
+#define MENUSTRING(string, code) string " %x" STRING(code)
+#define MENUTITLE(string) string " %t|"
+
+void uv_autocalc_tface()
+{
+ Mesh *me;
+ TFace *tface;
+ MFace *mface;
+ MVert *mv;
+ Object *ob;
+ extern float cumapsize; /* buttons.c */
+ float dx, dy, min[3], cent[3], max[3], no[3], *loc, mat[4][4];
+ float fac = 1.0;
+
+ int i, n, mi; /* strubi */
+ int a, b;
+ short cox, coy, mode, adr[2];
+
+ me= get_mesh(ob=OBACT);
+ if(me==0 || me->tface==0) return;
+ if(me->totface==0) return;
+
+ mode= pupmenu(MENUTITLE("UV Calculation")
+ MENUSTRING("Cube", UV_CUBE_MAPPING) "|"
+ MENUSTRING("Cylinder", UV_CYL_MAPPING) "|"
+ MENUSTRING("Bounds to 1/4", UV_BOUNDS4_MAPPING) "|"
+ MENUSTRING("Bounds to 1/2", UV_BOUNDS2_MAPPING) "|"
+ MENUSTRING("Bounds to 1/1", UV_BOUNDS1_MAPPING) "|"
+ MENUSTRING("Standard 1/4", UV_STD4_MAPPING) "|"
+ MENUSTRING("Standard 1/2", UV_STD2_MAPPING) "|"
+ MENUSTRING("Standard 1/1", UV_STD1_MAPPING) "|"
+ MENUSTRING("From Window", UV_WINDOW_MAPPING) );
+
+ switch(mode) {
+ case UV_CUBE_MAPPING:
+ tface= me->tface;
+ mface= me->mface;
+ mv= me->mvert;
+ loc= ob->obmat[3];
+
+ fbutton(&cumapsize, 0.0001, 100.0, "Cubemap size");
+
+ for(a=0; a<me->totface; a++, mface++, tface++) {
+ if(tface->flag & TF_SELECT) {
+ if(mface->v3==0) continue;
+
+ CalcNormFloat((mv+mface->v1)->co, (mv+mface->v2)->co, (mv+mface->v3)->co, no);
+
+ no[0]= fabs(no[0]);
+ no[1]= fabs(no[1]);
+ no[2]= fabs(no[2]);
+
+ cox=0; coy= 1;
+ if(no[2]>=no[0] && no[2]>=no[1]);
+ else if(no[1]>=no[0] && no[1]>=no[2]) coy= 2;
+ else { cox= 1; coy= 2;}
+
+ tface->uv[0][0]= 0.5+0.5*cumapsize*(loc[cox] + (mv+mface->v1)->co[cox]);
+ tface->uv[0][1]= 0.5+0.5*cumapsize*(loc[coy] + (mv+mface->v1)->co[coy]);
+ dx = floor(tface->uv[0][0]);
+ dy = floor(tface->uv[0][1]);
+ tface->uv[0][0] -= dx;
+ tface->uv[0][1] -= dy;
+ tface->uv[1][0]= 0.5+0.5*cumapsize*(loc[cox] + (mv+mface->v2)->co[cox]);
+ tface->uv[1][1]= 0.5+0.5*cumapsize*(loc[coy] + (mv+mface->v2)->co[coy]);
+ tface->uv[1][0] -= dx;
+ tface->uv[1][1] -= dy;
+ tface->uv[2][0]= 0.5+0.5*cumapsize*(loc[cox] + (mv+mface->v3)->co[cox]);
+ tface->uv[2][1]= 0.5+0.5*cumapsize*(loc[coy] + (mv+mface->v3)->co[coy]);
+ tface->uv[2][0] -= dx;
+ tface->uv[2][1] -= dy;
+ if(mface->v4) {
+ tface->uv[3][0]= 0.5+0.5*cumapsize*(loc[cox] + (mv+mface->v4)->co[cox]);
+ tface->uv[3][1]= 0.5+0.5*cumapsize*(loc[coy] + (mv+mface->v4)->co[coy]);
+ tface->uv[3][0] -= dx;
+ tface->uv[3][1] -= dy;
+ }
+
+ }
+ }
+
+ case UV_BOUNDS4_MAPPING:
+ fac = 0.25;
+ goto bounds_mapping;
+ case UV_BOUNDS2_MAPPING:
+ fac = 0.5;
+ goto bounds_mapping;
+ case UV_BOUNDS1_MAPPING:
+ // fac = 1.0; was already initialized as 1.0
+ case UV_WINDOW_MAPPING:
+ bounds_mapping:
+ mymultmatrix(ob->obmat);
+ MTC_Mat4SwapMat4(G.vd->persmat, mat);
+ mygetsingmatrix(G.vd->persmat);
+
+ tface= me->tface;
+ mface= me->mface;
+
+ dx = curarea->winx;
+ dy = curarea->winy;
+
+ if (dx > dy) dy = dx;
+ else dx = dy;
+
+ for(a=0; a<me->totface; a++, mface++, tface++) {
+ if(tface->flag & TF_SELECT) {
+
+ if(mface->v3==0) continue;
+
+ project_short( (me->mvert+mface->v1)->co, adr);
+ if(adr[0]!=3200) {
+ tface->uv[0][0]= ((float)adr[0])/dx;
+ tface->uv[0][1]= ((float)adr[1])/dy;
+ }
+ project_short( (me->mvert+mface->v2)->co, adr);
+ if(adr[0]!=3200) {
+ tface->uv[1][0]= ((float)adr[0])/dx;
+ tface->uv[1][1]= ((float)adr[1])/dy;
+ }
+ project_short( (me->mvert+mface->v3)->co, adr);
+ if(adr[0]!=3200) {
+ tface->uv[2][0]= ((float)adr[0])/dx;
+ tface->uv[2][1]= ((float)adr[1])/dy;
+ }
+ if(mface->v4) {
+ project_short( (me->mvert+mface->v4)->co, adr);
+ if(adr[0]!=3200) {
+ tface->uv[3][0]= ((float)adr[0])/dx;
+ tface->uv[3][1]= ((float)adr[1])/dy;
+ }
+ }
+ }
+ }
+
+ //stop here if WINDOW_MAPPING:
+ if (mode == UV_WINDOW_MAPPING) break;
+
+ /* minmax */
+ min[0]= min[1]= 1.0;
+ max[0]= max[1]= 0.0;
+ tface= me->tface;
+ mface= me->mface;
+ for(a=0; a<me->totface; a++, mface++, tface++) {
+ if(tface->flag & TF_SELECT) {
+ if(mface->v3==0) continue;
+
+ if(mface->v4) b= 3; else b= 2;
+ for(; b>=0; b--) {
+ min[0]= MIN2(tface->uv[b][0], min[0]);
+ min[1]= MIN2(tface->uv[b][1], min[1]);
+ max[0]= MAX2(tface->uv[b][0], max[0]);
+ max[1]= MAX2(tface->uv[b][1], max[1]);
+ }
+ }
+ }
+
+ dx= max[0]-min[0];
+ dy= max[1]-min[1];
+
+ tface= me->tface;
+ mface= me->mface;
+ for(a=0; a<me->totface; a++, mface++, tface++) {
+ if(tface->flag & TF_SELECT) {
+ if(mface->v3==0) continue;
+
+ if(mface->v4) b= 3; else b= 2;
+ for(; b>=0; b--) {
+ tface->uv[b][0]= ((tface->uv[b][0] - min[0])* fac) / dx;
+ tface->uv[b][1]= 1.0 - fac + ((tface->uv[b][1] - min[1]) * fac) /dy;
+ }
+ }
+ }
+ break;
+
+ case UV_STD4_MAPPING:
+ fac = 0.25;
+ goto standard_mapping;
+ case UV_STD2_MAPPING:
+ fac = 0.5;
+ goto standard_mapping;
+ case UV_STD1_MAPPING:
+ fac = 1.0;
+
+ standard_mapping:
+ tface= me->tface;
+ for(a=0; a<me->totface; a++, tface++) {
+ if(tface->flag & TF_SELECT) {
+ default_uv(tface->uv, fac);
+ }
+ }
+ break;
+
+ case UV_SPHERE_MAPPING:
+ case UV_CYL_MAPPING:
+
+ /* calc centre */
+
+ INIT_MINMAX(min, max);
+
+ tface= me->tface;
+ mface= me->mface;
+ for(a=0; a<me->totface; a++, mface++, tface++) {
+ if(tface->flag & TF_SELECT) {
+ if(mface->v3==0) continue;
+
+ DO_MINMAX( (me->mvert+mface->v1)->co, min, max);
+ DO_MINMAX( (me->mvert+mface->v2)->co, min, max);
+ DO_MINMAX( (me->mvert+mface->v3)->co, min, max);
+ if(mface->v4) DO_MINMAX( (me->mvert+mface->v3)->co, min, max);
+ }
+ }
+
+ VecMidf(cent, min, max);
+
+ tface= me->tface;
+ mface= me->mface;
+ for(a=0; a<me->totface; a++, mface++, tface++) {
+ if(tface->flag & TF_SELECT) {
+ if(mface->v3==0) continue;
+
+ VecSubf(no, (me->mvert+mface->v1)->co, cent);
+ if(mode==UV_CYL_MAPPING) tubemap(no[0], no[1], no[2], tface->uv[0], &tface->uv[0][1]);
+ else spheremap(no[0], no[1], no[2], tface->uv[0], &tface->uv[0][1]);
+
+ VecSubf(no, (me->mvert+mface->v2)->co, cent);
+ if(mode==UV_CYL_MAPPING) tubemap(no[0], no[1], no[2], tface->uv[1], &tface->uv[1][1]);
+ else spheremap(no[0], no[1], no[2], tface->uv[1], &tface->uv[1][1]);
+
+ VecSubf(no, (me->mvert+mface->v3)->co, cent);
+ if(mode==UV_CYL_MAPPING) tubemap(no[0], no[1], no[2], tface->uv[2], &tface->uv[2][1]);
+ else spheremap(no[0], no[1], no[2], tface->uv[2], &tface->uv[2][1]);
+ n = 3;
+
+ if(mface->v4) {
+ VecSubf(no, (me->mvert+mface->v4)->co, cent);
+ if(mode==3) tubemap(no[0], no[1], no[2], tface->uv[3], &tface->uv[3][1]);
+ else spheremap(no[0], no[1], no[2], tface->uv[3], &tface->uv[3][1]);
+ n = 4;
+ }
+ mi = 0;
+ for (i = 1; i < n; i++)
+ {
+ if (tface->uv[i][0] > tface->uv[mi][0]) mi = i;
+ }
+ for (i = 0; i < n; i++)
+ {
+ if (i != mi) {
+ dx = tface->uv[mi][0] - tface->uv[i][0];
+ if (dx > 0.5) {
+ tface->uv[i][0] += 1.0;
+ }
+ }
+ }
+ }
+ }
+ break;
+ default:
+ return;
+ } // end switch
+
+ /* clipping and wrapping */
+ if(G.sima && G.sima->flag & SI_CLIP_UV) {
+ tface= me->tface;
+ mface= me->mface;
+ for(a=0; a<me->totface; a++, mface++, tface++) {
+ if(tface->flag & TF_SELECT) {
+ if(mface->v3==0) continue;
+
+ dx= dy= 0;
+ if(mface->v4) b= 3; else b= 2;
+ for(; b>=0; b--) {
+ while(tface->uv[b][0] + dx < 0.0) dx+= 0.5;
+ while(tface->uv[b][0] + dx > 1.0) dx-= 0.5;
+ while(tface->uv[b][1] + dy < 0.0) dy+= 0.5;
+ while(tface->uv[b][1] + dy > 1.0) dy-= 0.5;
+ }
+
+ if(mface->v4) b= 3; else b= 2;
+ for(; b>=0; b--) {
+ tface->uv[b][0]+= dx;
+ CLAMP(tface->uv[b][0], 0.0, 1.0);
+
+ tface->uv[b][1]+= dy;
+ CLAMP(tface->uv[b][1], 0.0, 1.0);
+ }
+ }
+ }
+ }
+
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWIMAGE, 0);
+ myloadmatrix(G.vd->viewmat);
+ MTC_Mat4SwapMat4(G.vd->persmat, mat);
+
+}
+
+void set_faceselect() /* toggle */
+{
+ Object *ob = OBACT;
+ Mesh *me = 0;
+
+ scrarea_queue_headredraw(curarea);
+
+ if(G.f & G_FACESELECT) G.f &= ~G_FACESELECT;
+ else {
+ if (ob && ob->type == OB_MESH) G.f |= G_FACESELECT;
+ }
+
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWBUTSGAME, 0);
+ allqueue(REDRAWBUTSEDIT, 0);
+ allqueue(REDRAWIMAGE, 0);
+
+ ob= OBACT;
+ me= get_mesh(ob);
+ if(me && me->tface==NULL) make_tfaces(me);
+
+ if(G.f & G_FACESELECT) {
+ setcursor_space(SPACE_VIEW3D, CURSOR_FACESEL);
+ if(me) set_lasttface();
+ }
+ else if((G.f & (G_WEIGHTPAINT|G_VERTEXPAINT|G_TEXTUREPAINT))==0) {
+ if(me) reveal_tface();
+ setcursor_space(SPACE_VIEW3D, CURSOR_STD);
+ makeDispList(ob);
+ }
+ countall();
+}
+
+
+#ifdef NAN_TPT
+/**
+ * Get the view ray through the screen point.
+ * Uses the OpenGL settings of the active view port.
+ * The coordinates should be given in viewport coordinates.
+ * @author Maarten Gribnau
+ * @param x the x-coordinate of the screen point.
+ * @param y the y-coordinate of the screen point.
+ * @param org origin of the view ray.
+ * @param dir direction of the view ray.
+ */
+void get_pick_ray(short x, short y, float org[3], float dir[3])
+{
+ double mvmatrix[16];
+ double projmatrix[16];
+ GLint viewport[4];
+ double px, py, pz;
+ float l;
+
+ /* Get the matrices needed for gluUnProject */
+ glGetIntegerv(GL_VIEWPORT, viewport);
+ glGetDoublev(GL_MODELVIEW_MATRIX, mvmatrix);
+ glGetDoublev(GL_PROJECTION_MATRIX, projmatrix);
+
+ /* Set up viewport so that gluUnProject will give correct values */
+ viewport[0] = 0;
+ viewport[1] = 0;
+ /* printf("viewport = (%4d, %4d, %4d, %4d)\n", viewport[0], viewport[1], viewport[2], viewport[3]); */
+ /* printf("cursor = (%4d, %4d)\n", x, y); */
+
+ gluUnProject((GLdouble) x, (GLdouble) y, 0.0, mvmatrix, projmatrix, viewport, &px, &py, &pz);
+ org[0] = (float)px; org[1] = (float)py; org[2] = (float)pz;
+ /* printf("world point at z=0.0 is (%f, %f, %f)\n", org[0], org[1], org[2]); */
+ gluUnProject((GLdouble) x, (GLdouble) y, 1.0, mvmatrix, projmatrix, viewport, &px, &py, &pz);
+ /* printf("world point at z=1.0 is (%f, %f, %f)\n", px, py, pz); */
+ dir[0] = ((float)px) - org[0];
+ dir[1] = ((float)py) - org[1];
+ dir[2] = ((float)pz) - org[2];
+ l = (float)sqrt(dir[0]*dir[0] + dir[1]*dir[1] + dir[2]*dir[2]);
+ if (!l) return;
+ l = 1. / l;
+ dir[0] *= l; dir[1] *= l; dir[2] *= l;
+ /* printf("ray org. is (%f, %f, %f)\n", org[0], org[1], org[2]); */
+ /* printf("ray dir. is (%f, %f, %f)\n", dir[0], dir[1], dir[2]); */
+}
+
+
+int triangle_ray_intersect(float tv0[3], float tv1[3], float tv2[3], float org[3], float dir[3], float uv[2])
+{
+ float v1v0[3];
+ float v2v0[3];
+ float n[3], an[3];
+ float t, d, l;
+ float p[3];
+ double u0, v0, u1, v1, u2, v2, uvtemp;
+ unsigned int iu, iv;
+
+ /* Calculate normal of the plane (cross, normalize)
+ * Could really use moto here...
+ */
+ v1v0[0] = tv1[0] - tv0[0];
+ v1v0[1] = tv1[1] - tv0[1];
+ v1v0[2] = tv1[2] - tv0[2];
+ v2v0[0] = tv2[0] - tv0[0];
+ v2v0[1] = tv2[1] - tv0[1];
+ v2v0[2] = tv2[2] - tv0[2];
+ n[0] = (v1v0[1] * v2v0[2]) - (v1v0[2] * v2v0[1]);
+ n[1] = (v1v0[2] * v2v0[0]) - (v1v0[0] * v2v0[2]);
+ n[2] = (v1v0[0] * v2v0[1]) - (v1v0[1] * v2v0[0]);
+ l = sqrt(n[0]*n[0] + n[1]*n[1] + n[2]*n[2]);
+ if (!l) return 0;
+ l = 1. / l;
+ n[0] *= l; n[1] *= l; n[2] *= l;
+
+ /* Calculate intersection point */
+ t = n[0]*dir[0] + n[1]*dir[1] + n[2]*dir[2];
+ if (fabs(t) < 1.0e-6) return 0;
+ d = -(n[0]*tv0[0] + n[1]*tv0[1] + n[2]*tv0[2]);
+ t = -(((n[0]*org[0] + n[1]*org[1] + n[2]*org[2]) + d) / t);
+ if (t < 0) return 0;
+ p[0] = org[0] + dir[0]*t;
+ p[1] = org[1] + dir[1]*t;
+ p[2] = org[2] + dir[2]*t;
+ /*printf("intersection at (%f, %f, %f)\n", p[0], p[1], p[2]);*/
+
+ /* Calculate the largest component of the normal */
+ an[0] = fabs(n[0]); an[1] = fabs(n[1]); an[2] = fabs(n[2]);
+ if ((an[0] > an[1]) && (an[0] > an[2])) {
+ iu = 1; iv = 2;
+ }
+ else if ((an[1] > an[0]) && (an[1] > an[2])) {
+ iu = 2; iv = 0;
+ }
+ else {
+ iu = 0; iv = 1;
+ }
+ /* printf("iu, iv = (%d, %d)\n", iu, iv); */
+
+ /* Calculate (u,v) */
+ u0 = p[iu] - tv0[iu];
+ v0 = p[iv] - tv0[iv];
+ u1 = tv1[iu] - tv0[iu];
+ v1 = tv1[iv] - tv0[iv];
+ u2 = tv2[iu] - tv0[iu];
+ v2 = tv2[iv] - tv0[iv];
+ /* printf("u0, v0, u1, v1, u2, v2 = (%f, %f, %f, %f, %f, %f)\n", u0, v0, u1, v1, u2, v2); */
+
+ /* These calculations should be in double precision.
+ * On windows we get inpredictable results in single precision
+ */
+ if (u1 == 0) {
+ uvtemp = u0/u2;
+ uv[1] = (float)uvtemp;
+ /* if ((uv[1] >= 0.) && (uv[1] <= 1.)) { */
+ uv[0] = (float)((v0 - uvtemp*v2) / v1);
+ /* } */
+ }
+ else {
+ uvtemp = (v0*u1 - u0*v1)/(v2*u1-u2*v1);
+ uv[1] = (float)uvtemp;
+ /* if ((uv[1] >= 0) && (uv[1] <= 1)) { */
+ uv[0] = (float)((u0 - uvtemp*u2) / u1);
+ /* } */
+ }
+ /* printf("uv[0], uv[1] = (%f, %f)\n", uv[0], uv[1]); */
+ return ((uv[0] >= 0) && (uv[1] >= 0) && ((uv[0]+uv[1]) <= 1)) ? 2 : 1;
+}
+
+/**
+ * Returns the vertex (local) coordinates of a face.
+ * No bounds checking!
+ * @author Maarten Gribnau
+ * @param mesh the mesh with the face.
+ * @param face the face.
+ * @param v1 vertex 1 coordinates.
+ * @param v2 vertex 2 coordinates.
+ * @param v3 vertex 3 coordinates.
+ * @param v4 vertex 4 coordinates.
+ * @return number of vertices of this face
+ */
+int face_get_vertex_coordinates(Mesh* mesh, TFace* face, float v1[3], float v2[3], float v3[3], float v4[3])
+{
+ int num_vertices;
+ MVert *mv;
+ MFace *mf = (MFace *) (((MFace *)mesh->mface) + (face - (TFace *) mesh->tface));
+
+ num_vertices = mf->v4 == 0 ? 3 : 4;
+ mv = mesh->mvert + mf->v1;
+ v1[0] = mv->co[0]; v1[1] = mv->co[1]; v1[2] = mv->co[2];
+ mv = mesh->mvert + mf->v2;
+ v2[0] = mv->co[0]; v2[1] = mv->co[1]; v2[2] = mv->co[2];
+ mv = mesh->mvert + mf->v3;
+ v3[0] = mv->co[0]; v3[1] = mv->co[1]; v3[2] = mv->co[2];
+ if (num_vertices == 4) {
+ mv = mesh->mvert + mf->v4;
+ v4[0] = mv->co[0]; v4[1] = mv->co[1]; v4[2] = mv->co[2];
+ }
+
+ return num_vertices;
+}
+
+/**
+ * Finds texture coordinates from face edge interpolation values.
+ * @author Maarten Gribnau
+ * @param face the face.
+ * @param v1 vertex 1 index.
+ * @param v2 vertex 2 index.
+ * @param v3 vertex 3 index.
+ * @param a interpolation value of edge v2-v1.
+ * @param b interpolation value of edge v3-v1.
+ * @param u (u,v) coordinate.
+ * @param v (u,v) coordinate.
+ */
+void face_get_uv(TFace* face, int v1, int v2, int v3, float a, float b, float* u, float* v)
+{
+ float uv01[2], uv21[2];
+
+ /* Pin a,b inside [0,1] range */
+#if 0
+ a = (float)fmod(a, 1.);
+ b = (float)fmod(b, 1.);
+#else
+ if (a < 0.f) a = 0.f;
+ else if (a > 1.f) a = 1.f;
+ if (b < 0.f) b = 0.f;
+ else if (b > 1.f) b = 1.f;
+#endif
+
+ /* Convert to texture coordinates */
+ uv01[0] = face->uv[v2][0] - face->uv[v1][0];
+ uv01[1] = face->uv[v2][1] - face->uv[v1][1];
+ uv21[0] = face->uv[v3][0] - face->uv[v1][0];
+ uv21[1] = face->uv[v3][1] - face->uv[v1][1];
+ uv01[0] *= a;
+ uv01[1] *= a;
+ uv21[0] *= b;
+ uv21[1] *= b;
+ *u = face->uv[v1][0] + (uv01[0] + uv21[0]);
+ *v = face->uv[v1][1] + (uv01[1] + uv21[1]);
+}
+
+/**
+ * Get the (u,v) coordinates on a face from a point in screen coordinates.
+ * The coordinates should be given in viewport coordinates.
+ * @author Maarten Gribnau
+ * @param object the object with the mesh
+ * @param mesh the mesh with the face to be picked.
+ * @param face the face to be picked.
+ * @param x the x-coordinate to pick at.
+ * @param y the y-coordinate to pick at.
+ * @param u the u-coordinate calculated.
+ * @param v the v-coordinate calculated.
+ * @return intersection result:
+ * 0 == no intersection, (u,v) invalid
+ * 1 == intersection, (u,v) valid
+ */
+int face_pick_uv(Object* object, Mesh* mesh, TFace* face, short x, short y, float* u, float* v)
+{
+ float org[3], dir[3];
+ float ab[2];
+ float v1[3], v2[3], v3[3], v4[3];
+ int result;
+ int num_verts;
+
+ /* Get a view ray to intersect with the face */
+ get_pick_ray(x, y, org, dir);
+
+ /* Convert local vertex coordinates to world */
+ num_verts = face_get_vertex_coordinates(mesh, face, v1, v2, v3, v4);
+ /* Convert local vertex coordinates to world */
+ Mat4MulVecfl(object->obmat, v1);
+ Mat4MulVecfl(object->obmat, v2);
+ Mat4MulVecfl(object->obmat, v3);
+ if (num_verts > 3) {
+ Mat4MulVecfl(object->obmat, v4);
+ }
+
+ /* Get (u,v) values (local face coordinates) of intersection point
+ * If face is a quad, there are two triangles to check.
+ */
+ result = triangle_ray_intersect(v2, v1, v3, org, dir, ab);
+ if ((num_verts == 3) || (num_verts == 4) && (result > 1)) {
+ /* Face is a triangle or a quad with a hit on the first triangle */
+ face_get_uv(face, 1, 0, 2, ab[0], ab[1], u, v);
+ /* printf("triangle 1, texture (u,v)=(%f, %f)\n", *u, *v); */
+ }
+ else {
+ /* Face is a quad and no intersection with first triangle */
+ result = triangle_ray_intersect(v4, v3, v1, org, dir, ab);
+ face_get_uv(face, 3, 2, 0, ab[0], ab[1], u, v);
+ /* printf("triangle 2, texture (u,v)=(%f, %f)\n", *u, *v); */
+ }
+ return result > 0;
+}
+
+/**
+ * First attempt at drawing in the texture of a face.
+ * @author Maarten Gribnau
+ */
+void face_draw()
+{
+ Object *ob;
+ Mesh *me;
+ TFace *face, *face_old = 0;
+ short xy[2], xy_old[2];
+ //int a, index;
+ Image *img, *img_old;
+ IMG_BrushPtr brush;
+ IMG_CanvasPtr canvas = 0;
+ int rowBytes;
+ char *warn_packed_file = 0;
+ float uv[2], uv_old[2];
+ extern VPaint Gvp;
+
+ ob = OBACT;
+ if (!ob) {
+ error("No active object"); return;
+ }
+ if (!(ob->lay & G.vd->lay)) {
+ error("Active object not in this layer"); return;
+ }
+ me = get_mesh(ob);
+ if (!me) {
+ error("Active object does not have a mesh"); return;
+ }
+
+ brush = IMG_BrushCreate(Gvp.size, Gvp.size, Gvp.r, Gvp.g, Gvp.b, Gvp.a);
+ if (!brush) {
+ error("Can not create brush"); return;
+ }
+
+ getmouseco_areawin(xy_old);
+ while (get_mbut() & L_MOUSE) {
+ getmouseco_areawin(xy);
+ /* Check if cursor has moved */
+ if ((xy[0] != xy_old[0]) || (xy[1] != xy_old[1])) {
+
+ /* Get face to draw on */
+ face = face_pick(me, xy[0], xy[1]);
+
+ /* Check if this is another face. */
+ if (face != face_old) {
+ /* The active face changed, check the texture */
+ if (face) {
+ img = face->tpage;
+ }
+ else {
+ img = 0;
+ }
+
+ if (img != img_old) {
+ /* Faces have different textures. Finish drawing in the old face. */
+ if (face_old && canvas) {
+ face_pick_uv(ob, me, face_old, xy[0], xy[1], &uv[0], &uv[1]);
+ IMG_CanvasDrawLineUV(canvas, brush, uv_old[0], uv_old[1], uv[0], uv[1]);
+ img_old->ibuf->userflags |= IB_BITMAPDIRTY;
+ /* Delete old canvas */
+ IMG_CanvasDispose(canvas);
+ canvas = 0;
+ }
+
+ /* Create new canvas and start drawing in the new face. */
+ if (img) {
+ if (img->ibuf && img->packedfile == 0) {
+ /* MAART: skipx is not set most of the times. Make a guess. */
+ rowBytes = img->ibuf->skipx ? img->ibuf->skipx : img->ibuf->x * 4;
+ canvas = IMG_CanvasCreateFromPtr(img->ibuf->rect, img->ibuf->x, img->ibuf->y, rowBytes);
+ if (canvas) {
+ face_pick_uv(ob, me, face, xy_old[0], xy_old[1], &uv_old[0], &uv_old[1]);
+ face_pick_uv(ob, me, face, xy[0], xy[1], &uv[0], &uv[1]);
+ IMG_CanvasDrawLineUV(canvas, brush, uv_old[0], uv_old[1], uv[0], uv[1]);
+ img->ibuf->userflags |= IB_BITMAPDIRTY;
+ }
+ }
+ else {
+ /* TODO: should issue warning that no texture is assigned */
+ if (img->packedfile) {
+ warn_packed_file = img->id.name + 2;
+ img = 0;
+ }
+ }
+ }
+ }
+ else {
+ /* Face changed and faces have the same texture. */
+ if (canvas) {
+ /* Finish drawing in the old face. */
+ if (face_old) {
+ face_pick_uv(ob, me, face_old, xy[0], xy[1], &uv[0], &uv[1]);
+ IMG_CanvasDrawLineUV(canvas, brush, uv_old[0], uv_old[1], uv[0], uv[1]);
+ img_old->ibuf->userflags |= IB_BITMAPDIRTY;
+ }
+
+ /* Start drawing in the new face. */
+ if (face) {
+ face_pick_uv(ob, me, face, xy_old[0], xy_old[1], &uv_old[0], &uv_old[1]);
+ face_pick_uv(ob, me, face, xy[0], xy[1], &uv[0], &uv[1]);
+ IMG_CanvasDrawLineUV(canvas, brush, uv_old[0], uv_old[1], uv[0], uv[1]);
+ img->ibuf->userflags |= IB_BITMAPDIRTY;
+ }
+ }
+ }
+ }
+ else {
+ /* Same face, continue drawing */
+ if (face && canvas) {
+ /* Get the new (u,v) coordinates */
+ face_pick_uv(ob, me, face, xy[0], xy[1], &uv[0], &uv[1]);
+ IMG_CanvasDrawLineUV(canvas, brush, uv_old[0], uv_old[1], uv[0], uv[1]);
+ img->ibuf->userflags |= IB_BITMAPDIRTY;
+ }
+ }
+
+ if (face && img) {
+ /* Make OpenGL aware of a change in the texture */
+ free_realtime_image(img);
+ /* Redraw the view */
+ scrarea_do_windraw(curarea);
+ screen_swapbuffers();
+ }
+
+ xy_old[0] = xy[0];
+ xy_old[1] = xy[1];
+ uv_old[0] = uv[0];
+ uv_old[1] = uv[1];
+ face_old = face;
+ img_old = img;
+ }
+ }
+
+ IMG_BrushDispose(brush);
+ if (canvas) {
+ IMG_CanvasDispose(canvas);
+ canvas = 0;
+ }
+
+ if (warn_packed_file) {
+ error("Painting in packed images not supported: %s", warn_packed_file);
+ }
+
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWIMAGE, 0);
+ allqueue(REDRAWHEADERS, 0);
+}
+#endif /* NAN_TPT */
diff --git a/source/blender/src/editfont.c b/source/blender/src/editfont.c
new file mode 100644
index 00000000000..fb39c33976f
--- /dev/null
+++ b/source/blender/src/editfont.c
@@ -0,0 +1,537 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 <string.h>
+
+#include <fcntl.h>
+#ifndef WIN32
+#include <unistd.h>
+#else
+#include <io.h>
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_editVert.h"
+
+#include "DNA_curve_types.h"
+#include "DNA_object_types.h"
+#include "DNA_vfont_types.h"
+#include "DNA_scene_types.h"
+
+#include "BKE_displist.h"
+#include "BKE_font.h"
+#include "BKE_object.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+
+#include "BIF_editfont.h"
+#include "BIF_toolbox.h"
+#include "BIF_space.h"
+#include "BIF_mywindow.h"
+
+#include "BDR_editobject.h"
+
+#include "mydevice.h"
+
+#include "blendef.h"
+
+#define MAXTEXT 1000
+
+int textediting=0;
+
+static char findaccent(char char1, char code)
+{
+ char new= 0;
+
+ if(char1=='a') {
+ if(code=='`') new= 224;
+ else if(code==39) new= 225;
+ else if(code=='^') new= 226;
+ else if(code=='~') new= 227;
+ else if(code=='"') new= 228;
+ else if(code=='o') new= 229;
+ else if(code=='e') new= 230;
+ else if(code=='-') new= 170;
+ }
+ else if(char1=='c') {
+ if(code==',') new= 231;
+ if(code=='|') new= 162;
+ }
+ else if(char1=='e') {
+ if(code=='`') new= 232;
+ else if(code==39) new= 233;
+ else if(code=='^') new= 234;
+ else if(code=='"') new= 235;
+ }
+ else if(char1=='i') {
+ if(code=='`') new= 236;
+ else if(code==39) new= 237;
+ else if(code=='^') new= 238;
+ else if(code=='"') new= 239;
+ }
+ else if(char1=='n') {
+ if(code=='~') new= 241;
+ }
+ else if(char1=='o') {
+ if(code=='`') new= 242;
+ else if(code==39) new= 243;
+ else if(code=='^') new= 244;
+ else if(code=='~') new= 245;
+ else if(code=='"') new= 246;
+ else if(code=='/') new= 248;
+ else if(code=='-') new= 186;
+ else if(code=='e') new= 143;
+ }
+ else if(char1=='s') {
+ if(code=='s') new= 167;
+ }
+ else if(char1=='u') {
+ if(code=='`') new= 249;
+ else if(code==39) new= 250;
+ else if(code=='^') new= 251;
+ else if(code=='"') new= 252;
+ }
+ else if(char1=='y') {
+ if(code==39) new= 253;
+ else if(code=='"') new= 255;
+ }
+ else if(char1=='A') {
+ if(code=='`') new= 192;
+ else if(code==39) new= 193;
+ else if(code=='^') new= 194;
+ else if(code=='~') new= 195;
+ else if(code=='"') new= 196;
+ else if(code=='o') new= 197;
+ else if(code=='e') new= 198;
+ }
+ else if(char1=='C') {
+ if(code==',') new= 199;
+ }
+ else if(char1=='E') {
+ if(code=='`') new= 200;
+ else if(code==39) new= 201;
+ else if(code=='^') new= 202;
+ else if(code=='"') new= 203;
+ }
+ else if(char1=='I') {
+ if(code=='`') new= 204;
+ else if(code==39) new= 205;
+ else if(code=='^') new= 206;
+ else if(code=='"') new= 207;
+ }
+ else if(char1=='N') {
+ if(code=='~') new= 209;
+ }
+ else if(char1=='O') {
+ if(code=='`') new= 210;
+ else if(code==39) new= 211;
+ else if(code=='^') new= 212;
+ else if(code=='~') new= 213;
+ else if(code=='"') new= 214;
+ else if(code=='/') new= 216;
+ else if(code=='e') new= 141;
+ }
+ else if(char1=='U') {
+ if(code=='`') new= 217;
+ else if(code==39) new= 218;
+ else if(code=='^') new= 219;
+ else if(code=='"') new= 220;
+ }
+ else if(char1=='Y') {
+ if(code==39) new= 221;
+ }
+ else if(char1=='1') {
+ if(code=='4') new= 188;
+ if(code=='2') new= 189;
+ }
+ else if(char1=='3') {
+ if(code=='4') new= 190;
+ }
+ else if(char1==':') {
+ if(code=='-') new= 247;
+ }
+ else if(char1=='-') {
+ if(code==':') new= 247;
+ if(code=='|') new= 135;
+ if(code=='+') new= 177;
+ }
+ else if(char1=='|') {
+ if(code=='-') new= 135;
+ if(code=='=') new= 136;
+ }
+ else if(char1=='=') {
+ if(code=='|') new= 136;
+ }
+ else if(char1=='+') {
+ if(code=='-') new= 177;
+ }
+
+ if(new) return new;
+ else return char1;
+}
+
+static char *textbuf=0;
+static char *oldstr;
+
+static int insert_into_textbuf(Curve *cu, char c)
+{
+ if (cu->len<MAXTEXT-1) {
+ int x;
+
+ for(x= cu->len; x>cu->pos; x--) textbuf[x]= textbuf[x-1];
+ textbuf[cu->pos]= c;
+
+ cu->pos++;
+ cu->len++;
+ textbuf[cu->len]='\0';
+
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+void do_textedit(unsigned short event, short val, char ascii)
+{
+ Curve *cu;
+ static int accentcode= 0;
+ int x, doit=0, cursmove=0;
+
+ cu= G.obedit->data;
+
+ if(ascii) {
+
+ /* o.a. afvangen van TAB (TAB==9) */
+ if( (ascii > 31 && ascii < 200 && ascii != 127) || (ascii==13) || (ascii==10) || (ascii==8)) {
+
+ if(accentcode) {
+ if(cu->pos>0) textbuf[cu->pos-1]= findaccent(textbuf[cu->pos-1], ascii);
+ accentcode= 0;
+ }
+ else if(cu->len<MAXTEXT-1) {
+ if(G.qual & LR_ALTKEY ) {
+ if(ascii=='t') ascii= 137;
+ else if(ascii=='c') ascii= 169;
+ else if(ascii=='f') ascii= 164;
+ else if(ascii=='g') ascii= 176;
+ else if(ascii=='l') ascii= 163;
+ else if(ascii=='r') ascii= 174;
+ else if(ascii=='s') ascii= 223;
+ else if(ascii=='v') ascii= 1001;
+ else if(ascii=='y') ascii= 165;
+ else if(ascii=='.') ascii= 138;
+ else if(ascii=='1') ascii= 185;
+ else if(ascii=='2') ascii= 178;
+ else if(ascii=='3') ascii= 179;
+ else if(ascii=='%') ascii= 139;
+ else if(ascii=='?') ascii= 191;
+ else if(ascii=='!') ascii= 161;
+ else if(ascii=='x') ascii= 215;
+ else if(ascii=='>') ascii= 187;
+ else if(ascii=='<') ascii= 171;
+ }
+
+ if(ascii==1001) {
+ int file, filelen;
+ char *strp;
+
+/* this should be solved by clipboard support */
+#ifdef __WIN32_DISABLED
+ file= open("C:\\windows\\temp\\cutbuf", O_BINARY|O_RDONLY);
+#else
+ file= open("/tmp/.cutbuffer", O_BINARY|O_RDONLY);
+#endif
+ if(file>0) {
+
+ filelen = BLI_filesize(file);
+
+ strp= MEM_mallocN(filelen+1, "tempstr");
+ read(file, strp, filelen);
+ close(file);
+ strp[filelen]= 0;
+ if(cu->len+filelen<MAXTEXT) {
+ strcat( textbuf, strp);
+ cu->len= strlen(textbuf);
+ cu->pos= cu->len;
+ }
+ MEM_freeN(strp);
+ }
+ }
+ else {
+ insert_into_textbuf(cu, ascii);
+ }
+ }
+
+ doit= 1;
+ }
+ }
+ else if(val) {
+ cursmove= 0;
+
+ switch(event) {
+ case RETKEY:
+ insert_into_textbuf(cu, '\n');
+ doit= 1;
+ break;
+
+ case RIGHTARROWKEY:
+ if(G.qual & LR_SHIFTKEY) {
+ while(cu->pos<cu->len) {
+ if( textbuf[cu->pos]==0) break;
+ if( textbuf[cu->pos]=='\n') break;
+ cu->pos++;
+ }
+ }
+ else {
+ cu->pos++;
+ }
+ cursmove= FO_CURS;
+ break;
+
+ case LEFTARROWKEY:
+
+ if(G.qual & LR_SHIFTKEY) {
+ while(cu->pos>0) {
+ if( textbuf[cu->pos-1]=='\n') break;
+ cu->pos--;
+ }
+ }
+ else {
+ cu->pos--;
+ }
+ cursmove=FO_CURS;
+ break;
+
+ case UPARROWKEY:
+ if(G.qual & LR_SHIFTKEY) {
+ cu->pos= 0;
+ cursmove= FO_CURS;
+ }
+ else if(G.qual & LR_ALTKEY) {
+ if (cu->pos && textbuf[cu->pos - 1] < 255) {
+ textbuf[cu->pos - 1]++;
+ doit= 1;
+ }
+ }
+ else cursmove=FO_CURSUP;
+ break;
+
+ case DOWNARROWKEY:
+ if(G.qual & LR_SHIFTKEY) {
+ cu->pos= cu->len;
+ cursmove= FO_CURS;
+ }
+ else if(G.qual & LR_ALTKEY) {
+ if (cu->pos && textbuf[cu->pos - 1] > 1) {
+ textbuf[cu->pos - 1]--;
+ doit= 1;
+ }
+ }
+ else cursmove= FO_CURSDOWN;
+ break;
+
+ case BACKSPACEKEY:
+ if(cu->len!=0) {
+ if(G.qual & LR_ALTKEY) {
+ if(cu->pos>0) accentcode= 1;
+ }
+ else if(G.qual & LR_SHIFTKEY) {
+ cu->pos= 0;
+ textbuf[0]= 0;
+ cu->len= 0;
+ }
+ else if(cu->pos>0) {
+ for(x=cu->pos;x<=cu->len;x++) textbuf[x-1]= textbuf[x];
+ cu->pos--;
+ textbuf[--cu->len]='\0';
+ }
+ }
+ doit= 1;
+ break;
+ }
+
+ if(cursmove) {
+ if(cu->pos>cu->len) cu->pos= cu->len;
+ else if(cu->pos>=MAXTEXT) cu->pos= MAXTEXT;
+ else if(cu->pos<0) cu->pos= 0;
+ }
+ }
+ if(doit || cursmove) {
+ text_to_curve(G.obedit, cursmove);
+ if(cursmove==0) makeDispList(G.obedit);
+ allqueue(REDRAWVIEW3D, 0);
+ }
+}
+
+void make_editText(void)
+{
+ Curve *cu;
+
+ cu= G.obedit->data;
+ if(textbuf==0) textbuf= MEM_mallocN(MAXTEXT, "texteditbuf");
+ BLI_strncpy(textbuf, cu->str, MAXTEXT);
+ oldstr= cu->str;
+ cu->str= textbuf;
+
+ cu->len= strlen(textbuf);
+ if(cu->pos>cu->len) cu->pos= cu->len;
+
+ text_to_curve(G.obedit, 0);
+ makeDispList(G.obedit);
+
+ textediting= 1;
+}
+
+void load_editText(void)
+{
+ Curve *cu;
+
+ cu= G.obedit->data;
+
+ MEM_freeN(oldstr);
+ oldstr= 0;
+
+ cu->str= MEM_mallocN(cu->len+1, "tekstedit");
+ strcpy(cu->str, textbuf);
+
+ /* this memory system is weak... */
+ MEM_freeN(textbuf);
+ textbuf= 0;
+
+ cu->len= strlen(cu->str);
+ textediting= 0;
+}
+
+void remake_editText(void)
+{
+ Curve *cu;
+
+ if(okee("Reload Original text")==0) return;
+
+ BLI_strncpy(textbuf, oldstr, MAXTEXT);
+ cu= G.obedit->data;
+ cu->len= strlen(textbuf);
+ if(cu->pos>cu->len) cu->pos= cu->len;
+
+ text_to_curve(G.obedit, 0);
+ makeDispList(G.obedit);
+
+ allqueue(REDRAWVIEW3D, 0);
+}
+
+void free_editText(void)
+{
+ if(oldstr) MEM_freeN(oldstr);
+ textbuf= oldstr= 0;
+ textediting= 0;
+}
+
+static VFont *get_builtin_font(void)
+{
+ VFont *vf;
+
+ for (vf= G.main->vfont.first; vf; vf= vf->id.next)
+ if (BLI_streq(vf->name, "<builtin>"))
+ return vf;
+
+ return load_vfont("<builtin>");
+}
+
+void add_primitiveFont(int dummy_argument)
+{
+ Curve *cu;
+
+ if (G.obedit && G.obedit->type==OB_FONT) return;
+ check_editmode(OB_FONT);
+
+ add_object(OB_FONT);
+ base_init_from_view3d(BASACT, G.vd);
+ G.obedit= BASACT->object;
+ where_is_object(G.obedit);
+
+ cu= G.obedit->data;
+
+ cu->vfont= get_builtin_font();
+ cu->vfont->id.us++;
+ cu->str= MEM_mallocN(12, "str");
+ strcpy(cu->str, "Text");
+ cu->pos= 4;
+
+ make_editText();
+ allqueue(REDRAWVIEW3D, 0);
+}
+
+void to_upper(void)
+{
+ Curve *cu;
+ int len, ok;
+ char *str;
+
+ if(G.obedit==0) {
+ return;
+ }
+
+ ok= 0;
+ cu= G.obedit->data;
+
+ len= strlen(cu->str);
+ str= cu->str;
+ while(len) {
+ if( *str>=97 && *str<=122) {
+ ok= 1;
+ *str-= 32;
+ }
+ len--;
+ str++;
+ }
+
+ if(ok==0) {
+ len= strlen(cu->str);
+ str= cu->str;
+ while(len) {
+ if( *str>=65 && *str<=90) {
+ *str+= 32;
+ }
+ len--;
+ str++;
+ }
+ }
+ text_to_curve(G.obedit, 0);
+ makeDispList(G.obedit);
+
+ allqueue(REDRAWVIEW3D, 0);
+
+}
+
+
diff --git a/source/blender/src/editgroup.c b/source/blender/src/editgroup.c
new file mode 100644
index 00000000000..e72fb33e9b8
--- /dev/null
+++ b/source/blender/src/editgroup.c
@@ -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 *****
+ */
+
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+
+#include "DNA_group_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_view3d_types.h"
+
+#include "BKE_group.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+
+#include "BIF_space.h"
+#include "BIF_interface.h"
+#include "BIF_toolbox.h"
+#include "BIF_editgroup.h"
+
+#include "interface.h"
+#include "blendef.h"
+#include "mydevice.h"
+
+void set_active_group(void)
+{
+ /* with active object, find active group */
+ Group *group;
+ GroupObject *go;
+
+ G.scene->group= NULL;
+
+ if(BASACT) {
+ group= G.main->group.first;
+ while(group) {
+ go= group->gobject.first;
+ while(go) {
+ if(go->ob == OBACT) {
+ G.scene->group= group;
+ return;
+ }
+ go= go->next;
+ }
+ group= group->id.next;
+ }
+ }
+}
+
+
+void add_selected_to_group(void)
+{
+ Base *base= FIRSTBASE;
+ Group *group;
+
+ if(BASACT==NULL) {
+ error("No active object");
+ return;
+ }
+
+ if(okee("Add selected to group")==0) return;
+
+ if(G.scene->group==NULL) G.scene->group= add_group();
+
+ while(base) {
+ if TESTBASE(base) {
+
+ /* each object only in one group */
+ group= find_group(base->object);
+ if(group==G.scene->group);
+ else {
+ if(group) {
+ rem_from_group(group, base->object);
+ }
+ add_to_group(G.scene->group, base->object);
+ base->object->flag |= OB_FROMGROUP;
+ base->flag |= OB_FROMGROUP;
+ }
+ }
+ base= base->next;
+ }
+
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWBUTSANIM, 0);
+}
+
+void rem_selected_from_group(void)
+{
+ Base *base=FIRSTBASE;
+ Group *group;
+
+ if(okee("Remove selected from group")==0) return;
+
+ while(base) {
+ if TESTBASE(base) {
+
+ group= find_group(base->object);
+ if(group) {
+ rem_from_group(group, base->object);
+
+ base->object->flag &= ~OB_FROMGROUP;
+ base->flag &= ~OB_FROMGROUP;
+ }
+ }
+ base= base->next;
+ }
+
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWBUTSANIM, 0);
+}
+
+void group_menu(void)
+{
+ Base *base;
+ GroupObject *go;
+ GroupKey *gk;
+ short nr, len;
+ char *str, tstr[40];
+
+ if(G.scene->group==NULL) return;
+
+ /* make menu string */
+ len= 60;
+ gk= G.scene->group->gkey.first;
+ while(gk) {
+ len+= 36;
+ gk= gk->next;
+ }
+
+ str= MEM_mallocN(len, "groupmenu");
+ strcpy(str, "Group options%t|Select members %x1");
+
+ if(G.scene->group->active)
+ strcat(str, "|Overwrite active key %x2|%l");
+
+ nr= 3;
+ gk= G.scene->group->gkey.first;
+ while(gk) {
+ sprintf(tstr, "|Load: %s %%x%d", gk->name, nr++);
+ strcat(str, tstr);
+ gk= gk->next;
+ }
+
+ /* here we go */
+
+ nr= pupmenu(str);
+ MEM_freeN(str);
+
+ if(nr==1) {
+ go= G.scene->group->gobject.first;
+ while(go) {
+ go->ob->flag |= SELECT;
+ go= go->next;
+ }
+
+ /* nasty thing... that should be solved someday */
+ base= FIRSTBASE;
+ while(base) {
+ base->flag= base->object->flag;
+ base= base->next;
+ }
+
+ }
+ else if(nr==2) {
+ go= G.scene->group->gobject.first;
+ while(go) {
+ add_object_key(go, G.scene->group->active);
+ go= go->next;
+ }
+
+ }
+ else if(nr>2) {
+ nr-= 2;
+ gk= G.scene->group->gkey.first;
+ while(gk) {
+ nr--;
+ if(nr==0) break;
+ gk= gk->next;
+ }
+
+ G.scene->group->active= gk;
+ set_group_key(G.scene->group);
+
+ }
+
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWBUTSANIM, 0);
+ allspace(REMAKEIPO, 0);
+ allqueue(REDRAWIPO, 0);
+}
+
+
+void prev_group_key(Group *group)
+{
+ GroupKey *gk= group->active;
+
+ if(gk) gk= gk->prev;
+
+ if(gk==NULL) group->active= group->gkey.last;
+ else group->active= gk;
+
+ set_group_key(group);
+}
+
+void next_group_key(Group *group)
+{
+ GroupKey *gk= group->active;
+
+ if(gk) gk= gk->next;
+
+ if(gk==NULL) group->active= group->gkey.first;
+ else group->active= gk;
+
+ set_group_key(group);
+
+}
+
+
diff --git a/source/blender/src/editika.c b/source/blender/src/editika.c
new file mode 100644
index 00000000000..1c4cde7a247
--- /dev/null
+++ b/source/blender/src/editika.c
@@ -0,0 +1,422 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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>
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+#include "MEM_guardedalloc.h"
+
+#include "BMF_Api.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+
+#include "DNA_object_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_ika_types.h"
+#include "DNA_view3d_types.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_object.h"
+#include "BKE_ika.h"
+#include "BKE_global.h"
+#include "BKE_displist.h"
+
+#include "BIF_gl.h"
+#include "BIF_toolbox.h"
+#include "BIF_mywindow.h"
+#include "BIF_screen.h"
+#include "BIF_space.h"
+#include "BIF_editika.h"
+
+#include "BSE_view.h"
+#include "BSE_drawview.h"
+
+#include "mydevice.h"
+#include "blendef.h"
+
+static void draw_limb(Limb *li, float small)
+{
+ float vec[2];
+
+ glRotatef(( li->alpha*180.0/M_PI), 0.0, 0.0, 1.0);
+
+ { GLUquadricObj *qobj = gluNewQuadric();
+ gluQuadricDrawStyle(qobj, GLU_SILHOUETTE);
+ gluPartialDisk( qobj, small, small, 32, 1, 180.0, 180.0);
+ gluDeleteQuadric(qobj);
+ };
+
+ vec[0]= 0.0; vec[1]= small;
+ glBegin(GL_LINE_STRIP);
+ glVertex2fv(vec);
+ vec[0]= li->len; vec[1]= 0.0;
+ glVertex2fv(vec);
+ vec[0]= 0.0; vec[1]= -small;
+ glVertex2fv(vec);
+ glEnd();
+
+ small*= 0.25;
+
+ if(li->next) circf(li->len, 0.0, small);
+ else circf(li->len, 0.0, small);
+
+ glTranslatef(li->len, 0.0, 0.0);
+}
+
+void draw_ika(Object *ob, int sel)
+{
+ Ika *ika;
+ Limb *li;
+ float col[4];
+ float small= 0.15;
+
+ ika= ob->data;
+ li= ika->limbbase.first;
+ if(li==0) return;
+
+ /* we zijn al in objectspace */
+ glPushMatrix();
+
+ glGetFloatv(GL_CURRENT_COLOR, col);
+
+ if((ika->flag & IK_GRABEFF)==0) {
+ if(sel) cpack(0xFFFF);
+ circf(0.0, 0.0, 0.05*li->len);
+
+ glColor3f(col[0], col[1], col[2]);
+ }
+
+ while(li) {
+ small= 0.10*li->len;
+ draw_limb(li, small);
+ li= li->next;
+ }
+
+ if(ika->flag & IK_GRABEFF) {
+ if(sel) {
+ if(ika->def) cpack(0xFFFF00);
+ else cpack(0xFFFF);
+ }
+ circf(0.0, 0.0, 0.25*small);
+ glColor3f(col[0], col[1], col[2]);
+ }
+
+ glPopMatrix();
+}
+
+/* type 0: verts, type 1: limbs */
+void draw_ika_nrs(Object *ob, int type)
+{
+ Ika *ika;
+ Limb *li;
+ int nr=0;
+ char str[12];
+
+ if(curarea->spacetype!=SPACE_VIEW3D) return;
+ mywinset(curarea->win);
+
+ glDrawBuffer(GL_FRONT);
+ myloadmatrix(G.vd->viewmat);
+ mymultmatrix(ob->obmat);
+
+ ika= ob->data;
+ li= ika->limbbase.first;
+
+ /* we zijn al in objectspace */
+ glPushMatrix();
+ cpack(0xFFFFFF);
+
+ if(type==0) {
+ sprintf(str, " %d", nr++);
+ glRasterPos3f(0.0, 0.0, 0.0);
+ BMF_DrawString(G.font, str);
+
+ while(li) {
+
+ glRotatef(( li->alpha*180.0/M_PI), 0.0, 0.0, 1.0);
+ glTranslatef(li->len, 0.0, 0.0);
+ sprintf(str, " %d", nr++);
+ glRasterPos3f(0.0, 0.0, 0.0);
+ BMF_DrawString(G.font, str);
+
+ li= li->next;
+ }
+ }
+ else {
+ while(li) {
+
+ glRotatef(( li->alpha*180.0/M_PI), 0.0, 0.0, 1.0);
+ glTranslatef( 0.7*li->len, 0.0, 0.0);
+ sprintf(str, " %d", nr++);
+ glRasterPos3f(0.0, 0.0, 0.0);
+ BMF_DrawString(G.font, str);
+ glTranslatef( 0.3*li->len, 0.0, 0.0);
+
+ li= li->next;
+ }
+
+ }
+
+ glDrawBuffer(GL_BACK);
+ glPopMatrix();
+}
+
+
+
+int extrude_ika(Object *ob, int add)
+{
+ Ika *ika;
+ Limb *li;
+ float dvec[3], dvecp[3], oldeul[3], mat[3][3], imat[3][3];
+ int firsttime= 1;
+ unsigned short event = 0;
+ short val, afbreek=0, mval[2], xo, yo;
+
+ /* init */
+ VECCOPY(oldeul, ob->rot);
+ initgrabz(ob->obmat[3][0], ob->obmat[3][1], ob->obmat[3][2]);
+
+ Mat3CpyMat4(mat, ob->obmat);
+ Mat3Inv(imat, mat);
+
+ getmouseco_areawin(mval);
+ xo= mval[0];
+ yo= mval[1];
+
+ /* het laatste punt van de ika */
+ ika= ob->data;
+
+ if(add) {
+ /* een erbij: */
+ li= MEM_callocN(sizeof(Limb), "limb");
+ BLI_addtail(&ika->limbbase, li);
+ if(li->prev) {
+ li->eff[0]= li->prev->eff[0];
+ li->eff[1]= li->prev->eff[1];
+ }
+ li->eff[0]+= 0.5;
+ }
+ li= ika->limbbase.last;
+ if(li==0) return 0;
+
+ while(TRUE) {
+
+ getmouseco_areawin(mval);
+ if(mval[0]!=xo || mval[1]!=yo || firsttime) {
+ firsttime= 0;
+
+ window_to_3d(dvec, mval[0]-xo, mval[1]-yo);
+ VECCOPY(dvecp, dvec);
+
+ /* apply */
+ Mat3MulVecfl(imat, dvecp);
+ li->eff[0]+= dvecp[0];
+ li->eff[1]+= dvecp[1];
+
+ calc_limb(li);
+
+ if(li->prev==0) {
+ VECCOPY(ob->rot, oldeul);
+ euler_rot(ob->rot, li->alpha, 'z');
+ li->alpha= li->alphao= 0.0;
+ }
+
+ xo= mval[0];
+ yo= mval[1];
+
+ force_draw();
+ }
+
+ while(qtest()) {
+ event= extern_qread(&val);
+ if(val) {
+ switch(event) {
+ case ESCKEY:
+ case LEFTMOUSE:
+ case MIDDLEMOUSE:
+ case SPACEKEY:
+ case RETKEY:
+ afbreek= 1;
+ break;
+ }
+ }
+ if(afbreek) break;
+ }
+
+ if(afbreek) break;
+ }
+
+ if(event==ESCKEY) {
+ if(ika->limbbase.first!=ika->limbbase.last) {
+ li= ika->limbbase.last;
+ BLI_remlink(&ika->limbbase, li);
+ MEM_freeN(li);
+ }
+ }
+ else if(add) init_defstate_ika(ob);
+
+ allqueue(REDRAWVIEW3D, 0);
+
+ if(event==LEFTMOUSE) return 0;
+ return 1;
+}
+
+void delete_skeleton(void)
+{
+ Object *ob;
+ Ika *ika;
+
+ ob= OBACT;
+ if(ob==0 || ob->type!=OB_IKA || (ob->flag & SELECT)==0) return;
+
+ ika= ob->data;
+
+ if(!ika->def) return;
+ if(!okee("Delete Skeleton")) return;
+
+ if(ika->def) MEM_freeN(ika->def);
+ ika->def= 0;
+ ika->totdef= 0;
+
+ allqueue(REDRAWVIEW3D, 0);
+}
+
+static void copy_deform(int tot, Deform *defbase, Deform *def)
+{
+ /* defbase is the old one, *def is new. When they match,
+ the deform data is copied */
+
+ while(tot--) {
+ if(defbase->ob==def->ob && defbase->par1==def->par1) {
+ def->fac= defbase->fac;
+ def->dist= defbase->dist;
+ return;
+ }
+ defbase++;
+ }
+}
+
+void make_skeleton(void)
+{
+ Object *ob;
+ Base *base;
+ Ika *ika;
+ Deform *def, *defbase;
+ Limb *li;
+ int a, totdef=0;
+
+ ob= OBACT;
+ if(ob==0 || ob->type!=OB_IKA || (ob->flag & SELECT)==0) return;
+
+ if(!okee("Make Skeleton")) return;
+
+ ika= ob->data;
+
+ /* per selected ob, per limb, de obmat en imat berekenen */
+
+ base= FIRSTBASE;
+ while(base) {
+ if TESTBASE(base) {
+ if(base->object->type==OB_IKA) totdef+= count_limbs(base->object);
+ else totdef++;
+ }
+ base= base->next;
+ }
+
+ if(totdef==0) {
+ error("Nothing selected");
+ return;
+ }
+
+ def=defbase= MEM_callocN(totdef*sizeof(Deform), "deform");
+
+ base= FIRSTBASE;
+ while(base) {
+ if TESTBASE(base) {
+
+ if(base->object->type==OB_IKA) {
+
+ li= ( (Ika *)(base->object->data) )->limbbase.first;
+ a= 0;
+ while(li) {
+ what_does_parent1(base->object, PARLIMB, a, 0, 0);
+ def->ob= base->object;
+ def->partype= PARLIMB;
+ def->par1= a;
+
+ Mat4Invert(def->imat, workob.obmat);
+ def->vec[0]= li->len;
+ def->fac= 1.0;
+
+ copy_deform(ika->totdef, ika->def, def);
+
+ def++;
+ a++;
+ li= li->next;
+ }
+ }
+ else {
+ what_does_parent1(base->object, PAROBJECT, 0, 0, 0);
+ def->ob= base->object;
+ def->partype= PAROBJECT;
+
+ def->vec[0]= 0.0;
+ def->fac= 1.0;
+ def->dist= 0.0;
+
+ copy_deform(ika->totdef, ika->def, def);
+
+ Mat4Invert(def->imat, workob.obmat);
+ def++;
+ }
+ }
+ base= base->next;
+ }
+
+ if(ika->def) MEM_freeN(ika->def);
+ ika->def= defbase;
+ ika->totdef= totdef;
+
+ /* Recalculate the deformation on any object
+ * that was parented to the old skeleton.
+ */
+ for (base= FIRSTBASE; base; base= base->next)
+ if (base->object->parent==ob)
+ makeDispList(base->object);
+
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWBUTSEDIT, 0);
+}
diff --git a/source/blender/src/editimasel.c b/source/blender/src/editimasel.c
new file mode 100644
index 00000000000..f96491b1a6f
--- /dev/null
+++ b/source/blender/src/editimasel.c
@@ -0,0 +1,383 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 <stdio.h>
+#include <math.h>
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#else
+#include <sys/times.h>
+#endif
+
+#include "PIL_time.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+
+#include "BKE_global.h"
+
+#include "BIF_fsmenu.h"
+#include "BIF_screen.h"
+#include "BIF_interface.h"
+#include "BIF_imasel.h"
+
+#include "BSE_filesel.h"
+#include "BSE_drawimasel.h"
+
+#include "BDR_editcurve.h"
+
+#include "blendef.h"
+#include "mydevice.h"
+#include "interface.h"
+
+/* locals */
+void draw_icon_imasel(void);
+void winqreadimasel(unsigned short event, short val, char ascii);
+
+#define XIC 20
+#define YIC 21
+
+/* GLOBALS */
+extern char *fsmenu;
+
+
+void draw_icon_imasel(void)
+{
+ scrarea_queue_winredraw(curarea);
+}
+
+void winqreadimasel(unsigned short event, short val, char ascii)
+{
+ SpaceImaSel *simasel;
+
+ short mval[2];
+ short area_event;
+ short queredraw = 0;
+ char name[256];
+ char *selname;
+ static double prevtime=0;
+
+
+ if(val==0) return;
+ simasel= curarea->spacedata.first;
+
+ area_event = 0;
+ getmouseco_areawin(mval);
+ simasel->mx= mval[0];
+ simasel->my= mval[1];
+
+ if (simasel->desx > 0){
+ if ( (mval[0] > simasel->dssx) && (mval[0] < simasel->dsex) && (mval[1] > simasel->dssy) && (mval[1] < simasel->dsey) ) area_event = IMS_INDIRSLI;
+ if ( (mval[0] > simasel->desx) && (mval[0] < simasel->deex) && (mval[1] > simasel->desy) && (mval[1] < simasel->deey) ) area_event = IMS_INDIR;
+ }
+ if (simasel->fesx > 0){
+ if ( (mval[0] > simasel->fssx) && (mval[0] < simasel->fsex) && (mval[1] > simasel->fssy) && (mval[1] < simasel->fsey) ) area_event = IMS_INFILESLI;
+ if ( (mval[0] > simasel->fesx) && (mval[0] < simasel->feex) && (mval[1] > simasel->fesy) && (mval[1] < simasel->feey) ) area_event = IMS_INFILE;
+ }
+
+ if( event!=RETKEY && event!=PADENTER)
+ if( uiDoBlocks(&curarea->uiblocks, event)!=UI_NOTHING ) event= 0;
+
+ switch(event) {
+ case AFTERPIBREAD:
+ get_pib_file(simasel);
+ queredraw = 1;
+ break;
+
+ case AFTERIMASELIMA:
+ if (bitset(simasel->fase, IMS_DOTHE_INF)){
+ get_file_info(simasel);
+
+ if (!bitset(simasel->fase, IMS_KNOW_INF)){
+ addafterqueue(curarea->win, AFTERIMASELIMA, 1);
+
+ }else{
+ simasel->subfase = 0;
+ simasel->imafase = 0;
+ simasel->fase |= IMS_DOTHE_IMA;
+ addafterqueue(curarea->win, AFTERIMASELGET, 1);
+ }
+ }
+ break;
+ case AFTERIMASELGET:
+ if (bitset(simasel->fase, IMS_DOTHE_IMA)){
+ get_next_image(simasel);
+ if (simasel->ima_redraw > 0){
+ double newtime = PIL_check_seconds_timer();
+ if ((newtime - prevtime) > 0.03) {
+ simasel->ima_redraw = 0;
+ queredraw = 1;
+ prevtime = newtime;
+ }
+
+ }
+ if (!bitset(simasel->fase, IMS_KNOW_IMA)){
+ addafterqueue(curarea->win, AFTERIMASELGET, 1);
+ }else{
+ simasel->ima_redraw = 0;
+ simasel->subfase = 0;
+ simasel->imafase = 0;
+ addqueue(curarea->win, AFTERIMAWRITE, 1);
+ queredraw = 1;
+ }
+ }
+ break;
+ case AFTERIMAWRITE:
+ if (bitset(simasel->fase, IMS_KNOW_IMA)){
+ write_new_pib(simasel);
+ queredraw = 1;
+ }
+ break;
+
+ case RIGHTMOUSE:
+ if ((area_event == IMS_INFILE) && (simasel->hilite_ima)){
+ select_ima_files(simasel);
+ queredraw = 1;
+ }
+ break;
+ case UI_BUT_EVENT:
+
+ /* bug: blender's interface kit also returns a '4'... what is it! */
+
+ switch(val) {
+ case 13: /* 'P' */
+ imadir_parent(simasel);
+ queredraw = 1;
+
+ case 1: /* dir entry */
+ checkdir(simasel->dir);
+ clear_ima_dir(simasel);
+ queredraw = 1;
+ break;
+
+ case 3: /* fsmenu */
+ selname= fsmenu_get_entry(simasel->fileselmenuitem-1);
+ if (selname) {
+ strcpy(simasel->dir, selname);
+ checkdir(simasel->dir);
+ clear_ima_dir(simasel);
+ queredraw = 1;
+ }
+ break;
+
+ case 5:
+ if (simasel->returnfunc) {
+ char name[256];
+ strcpy(name, simasel->dir);
+ strcat(name, simasel->file);
+ simasel->returnfunc(name);
+ filesel_prevspace();
+ }
+ break;
+ case 6:
+ filesel_prevspace();
+ break;
+
+ }
+ break;
+
+ case LEFTMOUSE:
+ case MIDDLEMOUSE:
+
+ /* No button pressed */
+ switch (area_event){
+ case IMS_INDIRSLI:
+ move_imadir_sli(simasel);
+ queredraw = 1;
+ break;
+ case IMS_INFILESLI:
+ move_imafile_sli(simasel);
+ queredraw = 1;
+ break;
+ case IMS_INDIR:
+ if (simasel->hilite > -1){
+ change_imadir(simasel);
+ queredraw = 1;
+ }
+ break;
+ case IMS_INFILE:
+ if (simasel->hilite_ima){
+ strcpy(simasel->fole, simasel->hilite_ima->file_name);
+ strcpy(simasel->file, simasel->hilite_ima->file_name);
+
+ if (event == LEFTMOUSE) addqueue(curarea->win, IMALEFTMOUSE, 1);
+
+ if ((event == MIDDLEMOUSE)&&(simasel->returnfunc)){
+ strcpy(name, simasel->dir);
+ strcat(name, simasel->file);
+
+ if(simasel->mode & IMS_STRINGCODE) BLI_makestringcode(G.sce, name);
+
+ simasel->returnfunc(name);
+ filesel_prevspace();
+ }
+ queredraw = 1;
+ }
+ break;
+ }
+ break;
+
+ case MOUSEX:
+ case MOUSEY:
+ getmouseco_areawin(mval); /* lokaal screen */
+ calc_hilite(simasel);
+ if (simasel->mouse_move_redraw ){
+ simasel->mouse_move_redraw = 0;
+ queredraw = 1;
+ }
+ break;
+
+ case PAGEUPKEY:
+ case PAGEDOWNKEY:
+ switch(area_event){
+ case IMS_INDIRSLI:
+ case IMS_INDIR:
+ if (simasel->dirsli){
+ if (event == PAGEUPKEY) simasel->topdir -= (simasel->dirsli_lines - 1);
+ if (event == PAGEDOWNKEY) simasel->topdir += (simasel->dirsli_lines - 1);
+ queredraw = 1;
+ }
+ break;
+ case IMS_INFILESLI:
+ case IMS_INFILE:
+ if(simasel->imasli){
+ if (event == PAGEUPKEY) simasel->image_slider -= simasel->slider_height;
+ if (event == PAGEDOWNKEY) simasel->image_slider += simasel->slider_height;
+
+ if(simasel->image_slider < 0.0) simasel->image_slider = 0.0;
+ if(simasel->image_slider > 1.0) simasel->image_slider = 1.0;
+ queredraw = 1;
+ }
+ break;
+ }
+ break;
+
+ case HOMEKEY:
+ simasel->image_slider = 0.0;
+ queredraw = 1;
+ break;
+
+ case ENDKEY:
+ simasel->image_slider = 1.0;
+ queredraw = 1;
+ break;
+
+ case AKEY:
+ if (G.qual == 0){
+ ima_select_all(simasel);
+ queredraw = 1;
+ }
+ break;
+
+ case PKEY:
+ if(G.qual & LR_SHIFTKEY) {
+ extern char bprogname[]; /* usiblender.c */
+
+ sprintf(name, "%s -a \"%s%s\"", bprogname, simasel->dir, simasel->file);
+ system(name);
+ }
+ if(G.qual & LR_CTRLKEY) {
+ if(bitset(simasel->fase, IMS_KNOW_IMA)) pibplay(simasel);
+ }
+ if (G.qual == 0){
+ imadir_parent(simasel);
+ checkdir(simasel->dir);
+ clear_ima_dir(simasel);
+ queredraw = 1;
+ }
+ break;
+
+ case IKEY:
+ if ((G.qual == 0)&&(simasel->file)){
+ sprintf(name, "$IMAGEEDITOR %s%s", simasel->dir, simasel->file);
+ system(name);
+ queredraw = 1;
+ }
+
+ break;
+
+ case PADPLUSKEY:
+ case EQUALKEY:
+ BLI_newname(simasel->file, +1);
+ queredraw = 1;
+ break;
+
+ case PADMINUS:
+ case MINUSKEY:
+ BLI_newname(simasel->file, -1);
+ queredraw = 1;
+ break;
+
+ case BACKSLASHKEY:
+ case SLASHKEY:
+#ifdef WIN32
+ strcpy(simasel->dir, "\\");
+#else
+ strcpy(simasel->dir, "/");
+#endif
+ clear_ima_dir(simasel);
+ simasel->image_slider = 0.0;
+ queredraw = 1;
+ break;
+
+ case PERIODKEY:
+ clear_ima_dir(simasel);
+ queredraw = 1;
+ break;
+
+ case ESCKEY:
+ filesel_prevspace();
+ break;
+
+ case PADENTER:
+ case RETKEY:
+ if (simasel->returnfunc){
+ strcpy(name, simasel->dir);
+ strcat(name, simasel->file);
+ simasel->returnfunc(name);
+ filesel_prevspace();
+ }
+ break;
+ }
+
+
+ if (queredraw) scrarea_queue_winredraw(curarea);
+}
+
+
diff --git a/source/blender/src/editipo.c b/source/blender/src/editipo.c
new file mode 100644
index 00000000000..163bf0132c8
--- /dev/null
+++ b/source/blender/src/editipo.c
@@ -0,0 +1,5212 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 <math.h>
+#ifndef WIN32
+#include <unistd.h>
+#else
+#include <io.h>
+#include "BLI_winstuff.h"
+#endif
+#include "MEM_guardedalloc.h"
+#include "PIL_time.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+
+#include "DNA_constraint_types.h"
+#include "DNA_action_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_object_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_sequence_types.h"
+#include "DNA_sound_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_material_types.h"
+#include "DNA_key_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_ipo_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_space_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_group_types.h"
+#include "DNA_ika_types.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_action.h"
+#include "BKE_anim.h"
+#include "BKE_material.h"
+#include "BKE_ipo.h"
+#include "BKE_key.h"
+#include "BKE_ika.h"
+#include "BKE_displist.h"
+#include "BKE_global.h"
+#include "BKE_group.h"
+
+#include "BIF_buttons.h"
+#include "BIF_editkey.h"
+#include "BIF_editseq.h"
+#include "BIF_editview.h"
+#include "BIF_interface.h"
+#include "BIF_mywindow.h"
+#include "BIF_poseobject.h"
+#include "BIF_screen.h"
+#include "BIF_space.h"
+#include "BIF_toolbox.h"
+#include "BIF_poseobject.h"
+
+#include "BDR_drawobject.h"
+#include "BDR_editobject.h"
+
+#include "BSE_trans_types.h"
+#include "BSE_editipo_types.h"
+#include "BSE_drawipo.h"
+#include "BSE_editipo.h"
+#include "BSE_editaction.h"
+#include "BSE_edit.h"
+#include "BSE_drawview.h"
+#include "BSE_headerbuttons.h"
+
+#include "blendef.h"
+#include "mydevice.h"
+#include "interface.h"
+#include "render.h"
+
+/* forwards */
+#define BEZSELECTED(bezt) (((bezt)->f1 & 1) || ((bezt)->f2 & 1) || ((bezt)->f3 & 1))
+
+#define IPOTHRESH 0.9
+#define ISPOIN(a, b, c) ( (a->b) && (a->c) )
+#define ISPOIN3(a, b, c, d) ( (a->b) && (a->c) && (a->d) )
+#define ISPOIN4(a, b, c, d, e) ( (a->b) && (a->c) && (a->d) && (a->e) )
+
+extern int ob_ar[];
+extern int ma_ar[];
+extern int seq_ar[];
+extern int cu_ar[];
+extern int key_ar[];
+extern int wo_ar[];
+extern int la_ar[];
+extern int cam_ar[];
+extern int snd_ar[];
+extern int ac_ar[];
+extern int co_ar[];
+
+void getname_ac_ei(int nr, char *str)
+{
+ switch(nr) {
+ case AC_LOC_X:
+ strcpy(str, "LocX"); break;
+ case AC_LOC_Y:
+ strcpy(str, "LocY"); break;
+ case AC_LOC_Z:
+ strcpy(str, "LocZ"); break;
+ case AC_SIZE_X:
+ strcpy(str, "SizeX"); break;
+ case AC_SIZE_Y:
+ strcpy(str, "SizeY"); break;
+ case AC_SIZE_Z:
+ strcpy(str, "SizeZ"); break;
+ case AC_QUAT_X:
+ strcpy(str, "QuatX"); break;
+ case AC_QUAT_Y:
+ strcpy(str, "QuatY"); break;
+ case AC_QUAT_Z:
+ strcpy(str, "QuatZ"); break;
+ case AC_QUAT_W:
+ strcpy(str, "QuatW"); break;
+ default:
+ str[0]= 0;
+ }
+}
+
+void getname_co_ei(int nr, char *str)
+{
+ switch(nr){
+ case CO_ENFORCE:
+ strcpy(str, "Inf"); break;
+ }
+}
+
+void getname_ob_ei(int nr, char *str, int colipo)
+{
+ switch(nr) {
+ case OB_LOC_X:
+ strcpy(str, "LocX"); break;
+ case OB_LOC_Y:
+ strcpy(str, "LocY"); break;
+ case OB_LOC_Z:
+ strcpy(str, "LocZ"); break;
+ case OB_DLOC_X:
+ strcpy(str, "dLocX"); break;
+ case OB_DLOC_Y:
+ strcpy(str, "dLocY"); break;
+ case OB_DLOC_Z:
+ strcpy(str, "dLocZ"); break;
+
+ case OB_ROT_X:
+ strcpy(str, "RotX"); break;
+ case OB_ROT_Y:
+ strcpy(str, "RotY"); break;
+ case OB_ROT_Z:
+ strcpy(str, "RotZ"); break;
+ case OB_DROT_X:
+ strcpy(str, "dRotX"); break;
+ case OB_DROT_Y:
+ strcpy(str, "dRotY"); break;
+ case OB_DROT_Z:
+ strcpy(str, "dRotZ"); break;
+
+ case OB_SIZE_X:
+ strcpy(str, "SizeX"); break;
+ case OB_SIZE_Y:
+ strcpy(str, "SizeY"); break;
+ case OB_SIZE_Z:
+ strcpy(str, "SizeZ"); break;
+ case OB_DSIZE_X:
+ strcpy(str, "dSizeX"); break;
+ case OB_DSIZE_Y:
+ strcpy(str, "dSizeY"); break;
+ case OB_DSIZE_Z:
+ strcpy(str, "dSizeZ"); break;
+
+ case OB_LAY:
+ strcpy(str, "Layer"); break;
+
+ case OB_TIME:
+ strcpy(str, "Time"); break;
+ case OB_EFF_X:
+ if(colipo) strcpy(str, "ColR");
+ else strcpy(str, "EffX");
+ break;
+ case OB_EFF_Y:
+ if(colipo) strcpy(str, "ColG");
+ else strcpy(str, "EffY");
+ break;
+ case OB_EFF_Z:
+ if(colipo) strcpy(str, "ColB");
+ else strcpy(str, "EffZ");
+ break;
+ case OB_COL_A:
+ strcpy(str, "ColA");
+ break;
+ default:
+ str[0]= 0;
+ }
+}
+
+void getname_tex_ei(int nr, char *str)
+{
+ switch(nr) {
+ case MAP_OFS_X:
+ strcpy(str, "OfsX"); break;
+ case MAP_OFS_Y:
+ strcpy(str, "OfsY"); break;
+ case MAP_OFS_Z:
+ strcpy(str, "OfsZ"); break;
+ case MAP_SIZE_X:
+ strcpy(str, "SizeX"); break;
+ case MAP_SIZE_Y:
+ strcpy(str, "SizeY"); break;
+ case MAP_SIZE_Z:
+ strcpy(str, "SizeZ"); break;
+ case MAP_R:
+ strcpy(str, "texR"); break;
+ case MAP_G:
+ strcpy(str, "texG"); break;
+ case MAP_B:
+ strcpy(str, "texB"); break;
+ case MAP_DVAR:
+ strcpy(str, "DefVar"); break;
+ case MAP_COLF:
+ strcpy(str, "Col"); break;
+ case MAP_NORF:
+ strcpy(str, "Nor"); break;
+ case MAP_VARF:
+ strcpy(str, "Var"); break;
+ default:
+ str[0]= 0;
+ }
+}
+
+void getname_mat_ei(int nr, char *str)
+{
+ if(nr>=MA_MAP1) getname_tex_ei((nr & (MA_MAP1-1)), str);
+ else {
+ switch(nr) {
+ case MA_COL_R:
+ strcpy(str, "R"); break;
+ case MA_COL_G:
+ strcpy(str, "G"); break;
+ case MA_COL_B:
+ strcpy(str, "B"); break;
+ case MA_SPEC_R:
+ strcpy(str, "SpecR"); break;
+ case MA_SPEC_G:
+ strcpy(str, "SpecG"); break;
+ case MA_SPEC_B:
+ strcpy(str, "SpecB"); break;
+ case MA_MIR_R:
+ strcpy(str, "MirR"); break;
+ case MA_MIR_G:
+ strcpy(str, "MirG"); break;
+ case MA_MIR_B:
+ strcpy(str, "MirB"); break;
+ case MA_REF:
+ strcpy(str, "Ref"); break;
+ case MA_ALPHA:
+ strcpy(str, "Alpha"); break;
+ case MA_EMIT:
+ strcpy(str, "Emit"); break;
+ case MA_AMB:
+ strcpy(str, "Amb"); break;
+ case MA_SPEC:
+ strcpy(str, "Spec"); break;
+ case MA_HARD:
+ strcpy(str, "Hard"); break;
+ case MA_SPTR:
+ strcpy(str, "SpTra"); break;
+ case MA_ANG:
+ strcpy(str, "Ang"); break;
+ case MA_MODE:
+ strcpy(str, "Mode"); break;
+ case MA_HASIZE:
+ strcpy(str, "HaSize"); break;
+ default:
+ str[0]= 0;
+ }
+ }
+}
+
+void getname_world_ei(int nr, char *str)
+{
+ if(nr>=MA_MAP1) getname_tex_ei((nr & (MA_MAP1-1)), str);
+ else {
+ switch(nr) {
+ case WO_HOR_R:
+ strcpy(str, "HorR"); break;
+ case WO_HOR_G:
+ strcpy(str, "HorG"); break;
+ case WO_HOR_B:
+ strcpy(str, "HorB"); break;
+ case WO_ZEN_R:
+ strcpy(str, "ZenR"); break;
+ case WO_ZEN_G:
+ strcpy(str, "ZenG"); break;
+ case WO_ZEN_B:
+ strcpy(str, "ZenB"); break;
+
+ case WO_EXPOS:
+ strcpy(str, "Expos"); break;
+
+ case WO_MISI:
+ strcpy(str, "Misi"); break;
+ case WO_MISTDI:
+ strcpy(str, "MisDi"); break;
+ case WO_MISTSTA:
+ strcpy(str, "MisSta"); break;
+ case WO_MISTHI:
+ strcpy(str, "MisHi"); break;
+
+ case WO_STAR_R:
+ strcpy(str, "StarR"); break;
+ case WO_STAR_G:
+ strcpy(str, "StarB"); break;
+ case WO_STAR_B:
+ strcpy(str, "StarG"); break;
+
+ case WO_STARDIST:
+ strcpy(str, "StarDi"); break;
+ case WO_STARSIZE:
+ strcpy(str, "StarSi"); break;
+ default:
+ str[0]= 0;
+ }
+ }
+}
+
+void getname_seq_ei(int nr, char *str)
+{
+ switch(nr) {
+ case SEQ_FAC1:
+ strcpy(str, "Fac"); break;
+ default:
+ str[0]= 0;
+ }
+}
+
+void getname_cu_ei(int nr, char *str)
+{
+
+ switch(nr) {
+ case CU_SPEED:
+ strcpy(str, "Speed"); break;
+ default:
+ str[0]= 0;
+ }
+}
+
+void getname_key_ei(int nr, char *str)
+{
+ if(nr==KEY_SPEED) strcpy(str, "Speed");
+ else sprintf(str, "Key %d", nr);
+}
+
+void getname_la_ei(int nr, char *str)
+{
+ if(nr>=MA_MAP1) getname_tex_ei((nr & (MA_MAP1-1)), str);
+ else {
+ switch(nr) {
+ case LA_ENERGY:
+ strcpy(str, "Energ"); break;
+ case LA_COL_R:
+ strcpy(str, "R"); break;
+ case LA_COL_G:
+ strcpy(str, "G"); break;
+ case LA_COL_B:
+ strcpy(str, "B"); break;
+ case LA_DIST:
+ strcpy(str, "Dist"); break;
+ case LA_SPOTSI:
+ strcpy(str, "SpoSi"); break;
+ case LA_SPOTBL:
+ strcpy(str, "SpoBl"); break;
+ case LA_QUAD1:
+ strcpy(str, "Quad1"); break;
+ case LA_QUAD2:
+ strcpy(str, "Quad2"); break;
+ case LA_HALOINT:
+ strcpy(str, "HaInt"); break;
+ default:
+ str[0]= 0;
+ }
+ }
+}
+
+void getname_cam_ei(int nr, char *str)
+{
+ switch(nr) {
+ case CAM_LENS:
+ strcpy(str, "Lens"); break;
+ case CAM_STA:
+ strcpy(str, "ClSta"); break;
+ case CAM_END:
+ strcpy(str, "ClEnd"); break;
+ default:
+ str[0]= 0;
+ }
+}
+
+void getname_snd_ei(int nr, char *str)
+{
+ switch(nr) {
+ case SND_VOLUME:
+ strcpy(str, "Vol"); break;
+ case SND_PITCH:
+ strcpy(str, "Pitch"); break;
+ case SND_PANNING:
+ strcpy(str, "Pan"); break;
+ case SND_ATTEN:
+ strcpy(str, "Atten"); break;
+ default:
+ str[0]= 0;
+ }
+}
+
+
+IpoCurve *find_ipocurve(Ipo *ipo, int adrcode)
+{
+ if(ipo) {
+ IpoCurve *icu= ipo->curve.first;
+ while(icu) {
+ if(icu->adrcode==adrcode) return icu;
+ icu= icu->next;
+ }
+ }
+ return NULL;
+}
+
+void boundbox_ipocurve(IpoCurve *icu)
+{
+ BezTriple *bezt;
+ float vec[3]={0.0,0.0,0.0};
+ float min[3], max[3];
+ int a;
+
+ if(icu->totvert) {
+ INIT_MINMAX(min, max);
+
+ if(icu->bezt ) {
+ a= icu->totvert;
+ bezt= icu->bezt;
+ while(a--) {
+ if(icu->vartype & IPO_BITS) {
+ vec[0]= bezt->vec[1][0];
+ vec[1]= 0.0;
+ DO_MINMAX(vec, min, max);
+
+ vec[1]= 16.0;
+ DO_MINMAX(vec, min, max);
+ }
+ else {
+ if(icu->ipo==IPO_BEZ && a!=icu->totvert-1) {
+ DO_MINMAX(bezt->vec[0], min, max);
+ }
+ DO_MINMAX(bezt->vec[1], min, max);
+ if(icu->ipo==IPO_BEZ && a!=0) {
+ DO_MINMAX(bezt->vec[2], min, max);
+ }
+ }
+
+ bezt++;
+ }
+ }
+ if(min[0]==max[0]) max[0]= (float)(min[0]+1.0);
+ if(min[1]==max[1]) max[1]= (float)(min[1]+0.1);
+
+ icu->totrct.xmin= min[0];
+ icu->totrct.ymin= min[1];
+ icu->totrct.xmax= max[0];
+ icu->totrct.ymax= max[1];
+ }
+ else {
+ icu->totrct.xmin= icu->totrct.ymin= 0.0;
+ icu->totrct.xmax= EFRA;
+ icu->totrct.ymax= 1.0;
+ }
+}
+
+void boundbox_ipo(Ipo *ipo, rctf *bb)
+{
+ IpoCurve *icu;
+ int first= 1;
+
+ icu= ipo->curve.first;
+ while(icu) {
+
+ boundbox_ipocurve(icu);
+
+ if(first) {
+ *bb= icu->totrct;
+ first= 0;
+ }
+ else BLI_union_rctf(bb, &(icu->totrct));
+
+ icu= icu->next;
+ }
+}
+
+
+
+void editipo_changed(SpaceIpo *si, int doredraw)
+{
+ EditIpo *ei;
+ View2D *v2d;
+ Key *key;
+ KeyBlock *kb;
+ int a, first=1;
+
+
+ ei= si->editipo;
+ if(ei==0)
+ return;
+
+ for(a=0; a<si->totipo; a++, ei++) {
+
+ if(ei->icu) {
+
+ /* 2 keer i.v.m. ittereren nieuwe autohandle */
+ calchandles_ipocurve(ei->icu);
+ calchandles_ipocurve(ei->icu);
+
+ if(ei->flag & IPO_VISIBLE) {
+
+ boundbox_ipocurve(ei->icu);
+ sort_time_ipocurve(ei->icu);
+ if(first) {
+ si->v2d.tot= ei->icu->totrct;
+ first= 0;
+ }
+ else BLI_union_rctf(&(si->v2d.tot), &(ei->icu->totrct));
+ }
+ }
+ }
+
+ v2d= &(si->v2d);
+// v2d = &G.v2d;
+
+ /* keylijnen? */
+ if(si->blocktype==ID_KE) {
+ key= (Key *)si->from;
+ if(key && key->block.first) {
+ kb= key->block.first;
+ if(kb->pos < v2d->tot.ymin) v2d->tot.ymin= kb->pos;
+ kb= key->block.last;
+ if(kb->pos > v2d->tot.ymax) v2d->tot.ymax= kb->pos;
+ }
+ }
+
+
+ /* is er geen curve? */
+ if(first) {
+ v2d->tot.xmin= 0.0;
+ v2d->tot.xmax= EFRA;
+ v2d->tot.ymin= (float)-0.1;
+ v2d->tot.ymax= (float)1.1;
+
+ if(si->blocktype==ID_SEQ) {
+ v2d->tot.xmin= -5.0;
+ v2d->tot.xmax= 105.0;
+ v2d->tot.ymin= (float)-0.1;
+ v2d->tot.ymax= (float)1.1;
+ }
+ }
+
+ si->tot= v2d->tot;
+
+ if(doredraw) {
+ /* als do_ipo altijd wordt aangeroepen: problemen met insertkey, bijvoorbeeld
+ * als alleen een 'loc' wordt ge-insert wordt de 'ob->rot' veranderd.
+ */
+
+
+ if(si->blocktype==ID_OB) {
+ /* clear delta loc,rot,size (bij ipo vrijgeven/deleten) */
+ clear_delta_obipo(si->ipo);
+
+ }
+
+ do_ipo(si->ipo);
+
+ allqueue(REDRAWIPO, 0);
+ allqueue (REDRAWACTION, 0);
+ allqueue(REDRAWNLA, 0);
+ allqueue(REDRAWBUTSANIM, 0);
+
+ if(si->blocktype==ID_OB) {
+ Object *ob= (Object *)si->from;
+ if(ob && ob->type==OB_IKA) itterate_ika(ob);
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWNLA, 0);
+ }
+
+ else if(si->blocktype==ID_MA) allqueue(REDRAWBUTSMAT, 0);
+ else if(si->blocktype==ID_WO) allqueue(REDRAWBUTSWORLD, 0);
+ else if(si->blocktype==ID_LA) allqueue(REDRAWBUTSLAMP, 0);
+ else if(si->blocktype==ID_SO) allqueue(REDRAWBUTSSOUND, 0);
+ else if(si->blocktype==ID_CA) {
+ allqueue(REDRAWBUTSEDIT, 0);
+ allqueue(REDRAWVIEW3D, 0);
+ }
+ else if(si->blocktype==ID_SEQ) clear_last_seq();
+ else if(si->blocktype==ID_AC){
+ do_all_actions();
+ allqueue(REDRAWACTION, 0);
+ allqueue(REDRAWNLA, 0);
+ }
+ else if(si->blocktype==ID_KE) {
+ do_spec_key((Key *)si->from);
+ allqueue(REDRAWVIEW3D, 0);
+ }
+ else if(si->blocktype==ID_CU) {
+ calc_curvepath(OBACT);
+ allqueue(REDRAWVIEW3D, 0);
+ }
+ }
+
+ if(si->showkey) make_ipokey();
+}
+
+void scale_editipo()
+{
+ /* komt uit buttons, scale met G.sipo->tot rect */
+
+ EditIpo *ei;
+ BezTriple *bezt;
+ float facx, facy;
+ int a, b;
+
+ facx= (G.sipo->tot.xmax-G.sipo->tot.xmin)/(G.sipo->v2d.tot.xmax-G.sipo->v2d.tot.xmin);
+ facy= (G.sipo->tot.ymax-G.sipo->tot.ymin)/(G.sipo->v2d.tot.ymax-G.sipo->v2d.tot.ymin);
+
+ ei= G.sipo->editipo;
+ if(ei==0) return;
+ for(a=0; a<G.sipo->totipo; a++, ei++) {
+ if ISPOIN(ei, flag & IPO_VISIBLE, icu) {
+ bezt= ei->icu->bezt;
+ b= ei->icu->totvert;
+ while(b--) {
+
+ bezt->vec[0][0]= facx*(bezt->vec[0][0] - G.sipo->v2d.tot.xmin) + G.sipo->tot.xmin;
+ bezt->vec[1][0]= facx*(bezt->vec[1][0] - G.sipo->v2d.tot.xmin) + G.sipo->tot.xmin;
+ bezt->vec[2][0]= facx*(bezt->vec[2][0] - G.sipo->v2d.tot.xmin) + G.sipo->tot.xmin;
+
+ bezt->vec[0][1]= facy*(bezt->vec[0][1] - G.sipo->v2d.tot.ymin) + G.sipo->tot.ymin;
+ bezt->vec[1][1]= facy*(bezt->vec[1][1] - G.sipo->v2d.tot.ymin) + G.sipo->tot.ymin;
+ bezt->vec[2][1]= facy*(bezt->vec[2][1] - G.sipo->v2d.tot.ymin) + G.sipo->tot.ymin;
+
+ bezt++;
+ }
+ }
+ }
+ editipo_changed(G.sipo, 1);
+ allqueue(REDRAWNLA, 0);
+ allqueue (REDRAWACTION, 0);
+ allqueue(REDRAWIPO, 0);
+}
+
+
+Ipo *get_ipo_to_edit(ID **from)
+{
+ Object *ob= OBACT;
+
+ *from= 0;
+
+
+ if (G.sipo->pin) {
+ *from = G.sipo->from;
+ return G.sipo->ipo;
+ }
+
+ if(G.sipo->blocktype==ID_SEQ) {
+ extern Sequence *last_seq;
+
+ *from= (ID *)last_seq;
+ if(last_seq) return last_seq->ipo;
+ }
+ else if(G.sipo->blocktype==IPO_CO){
+ if (ob && ob->activecon){
+ *from= (ID*) ob;
+ return ob->activecon->ipo;
+ }
+ }
+ else if(G.sipo->blocktype==ID_AC) {
+ bActionChannel *chan;
+ if (ob && ob->action){
+ *from= (ID *) ob->action;
+ chan= get_hilighted_action_channel(ob->action);
+ if (chan)
+ return chan->ipo;
+ else{
+ *from = NULL;
+ return NULL;
+ }
+ }
+
+ }
+ else if(G.sipo->blocktype==ID_WO) {
+ World *wo= G.scene->world;
+ *from= (ID *)wo;
+ if(wo) return wo->ipo;
+ }
+ else if(G.sipo->blocktype==ID_OB) {
+ if(ob) {
+ *from= (ID *)ob;
+ return ob->ipo;
+ }
+ }
+ else if(G.sipo->blocktype==ID_MA) {
+ if(ob) {
+ Material *ma= give_current_material(ob, ob->actcol);
+ *from= (ID *)ma;
+ if(ma) return ma->ipo;
+ }
+ }
+ else if(G.sipo->blocktype==ID_KE) {
+ if(ob) {
+ Key *key= give_current_key(ob);
+ *from= (ID *)key;
+ if(key) return key->ipo;
+ }
+ }
+ else if(G.sipo->blocktype==ID_CU) {
+ if(ob && ob->type==OB_CURVE) {
+ Curve *cu= ob->data;
+ *from= (ID *)cu;
+ return cu->ipo;
+ }
+ }
+ else if(G.sipo->blocktype==ID_LA) {
+ if(ob && ob->type==OB_LAMP) {
+ Lamp *la= ob->data;
+ *from= (ID *)la;
+ return la->ipo;
+ }
+ }
+ else if(G.sipo->blocktype==ID_CA) {
+ if(ob && ob->type==OB_CAMERA) {
+ Camera *ca= ob->data;
+ *from= (ID *)ca;
+ if(ca) return ca->ipo;
+ }
+ }
+ else if(G.sipo->blocktype==ID_SO) {
+
+ if (G.buts && G.buts->mainb == BUTS_SOUND) {
+
+ bSound *sound = G.buts->lockpoin;
+
+ *from= (ID *)sound;
+
+ if(sound) return sound->ipo;
+
+ }
+ }
+
+ return NULL;
+}
+
+unsigned int ipo_rainbow(int cur, int tot)
+{
+ float dfac, fac, sat;
+
+ dfac= (float)(1.0/( (float)tot+1.0));
+
+ /* deze berekening zorgt voor twee verschillende cycles regenboogkleuren */
+ if(cur< tot/2) fac= (float)(cur*2.0*dfac);
+ else fac= (float)((cur-tot/2)*2.0*dfac +dfac);
+
+ if(fac>0.5 && fac<0.8) sat= (float)0.4;
+ else sat= 0.5;
+
+ return hsv_to_cpack(fac, sat, 1.0);
+}
+
+void make_ob_editipo(Object *ob, SpaceIpo *si)
+{
+ EditIpo *ei;
+ int a, len, colipo=0;
+
+ if(ob->type==OB_MESH) colipo= 1;
+
+ ei= si->editipo= MEM_callocN(OB_TOTIPO*sizeof(EditIpo), "editipo");
+
+ si->totipo= OB_TOTIPO;
+
+ for(a=0; a<OB_TOTIPO; a++) {
+ getname_ob_ei(ob_ar[a], ei->name, colipo);
+ ei->adrcode= ob_ar[a];
+
+ if ELEM6(ei->adrcode, OB_ROT_X, OB_ROT_Y, OB_ROT_Z, OB_DROT_X, OB_DROT_Y, OB_DROT_Z) ei->disptype= IPO_DISPDEGR;
+ else if(ei->adrcode==OB_LAY) ei->disptype= IPO_DISPBITS;
+ else if(ei->adrcode==OB_TIME) ei->disptype= IPO_DISPTIME;
+
+ ei->col= ipo_rainbow(a, OB_TOTIPO);
+
+ if(colipo) {
+ len= strlen(ei->name);
+ if(len) {
+ if( ei->name[ len-1 ]=='R') ei->col= 0x5050FF;
+ else if( ei->name[ len-1 ]=='G') ei->col= 0x50FF50;
+ else if( ei->name[ len-1 ]=='B') ei->col= 0xFF7050;
+ }
+ }
+
+ ei->icu= find_ipocurve(si->ipo, ei->adrcode);
+ if(ei->icu) {
+ ei->flag= ei->icu->flag;
+ }
+
+ ei++;
+ }
+}
+
+
+void make_seq_editipo(SpaceIpo *si)
+{
+ EditIpo *ei;
+ int a;
+
+ ei= si->editipo= MEM_callocN(SEQ_TOTIPO*sizeof(EditIpo), "editipo");
+
+ si->totipo= SEQ_TOTIPO;
+
+
+ for(a=0; a<SEQ_TOTIPO; a++) {
+ getname_seq_ei(seq_ar[a], ei->name);
+ ei->adrcode= seq_ar[a];
+
+ ei->col= ipo_rainbow(a, SEQ_TOTIPO);
+
+ ei->icu= find_ipocurve(si->ipo, ei->adrcode);
+ if(ei->icu) {
+ ei->flag= ei->icu->flag;
+ }
+ else ei->flag |= IPO_VISIBLE;
+
+ ei++;
+ }
+}
+
+void make_cu_editipo(SpaceIpo *si)
+{
+ EditIpo *ei;
+ int a;
+
+ ei= si->editipo= MEM_callocN(CU_TOTIPO*sizeof(EditIpo), "editipo");
+
+ si->totipo= CU_TOTIPO;
+
+
+ for(a=0; a<CU_TOTIPO; a++) {
+ getname_cu_ei(cu_ar[a], ei->name);
+ ei->adrcode= cu_ar[a];
+
+ ei->col= ipo_rainbow(a, CU_TOTIPO);
+
+ ei->icu= find_ipocurve(si->ipo, ei->adrcode);
+ if(ei->icu) {
+ ei->flag= ei->icu->flag;
+ }
+ else ei->flag |= IPO_VISIBLE;
+
+ ei++;
+ }
+}
+
+void make_key_editipo(SpaceIpo *si)
+{
+ Key *key;
+ EditIpo *ei;
+ int a;
+
+ ei= si->editipo= MEM_callocN(KEY_TOTIPO*sizeof(EditIpo), "editipo");
+
+ si->totipo= KEY_TOTIPO;
+
+ for(a=0; a<KEY_TOTIPO; a++) {
+ getname_key_ei(key_ar[a], ei->name);
+ ei->adrcode= key_ar[a];
+
+ ei->col= ipo_rainbow(a, KEY_TOTIPO);
+
+ ei->icu= find_ipocurve(si->ipo, ei->adrcode);
+ if(ei->icu) {
+ ei->flag= ei->icu->flag;
+ }
+ else if(a==0) ei->flag |= IPO_VISIBLE;
+
+ ei++;
+ }
+
+ ei= si->editipo;
+ key= (Key *)G.sipo->from;
+ if(key && key->type==KEY_RELATIVE) {
+ strcpy(ei->name, "----");
+ }
+ else {
+ ei->flag |= IPO_VISIBLE;
+ }
+}
+
+int texchannel_to_adrcode(int channel)
+{
+ switch(channel) {
+ case 0: return MA_MAP1;
+ case 1: return MA_MAP2;
+ case 2: return MA_MAP3;
+ case 3: return MA_MAP4;
+ case 4: return MA_MAP5;
+ case 5: return MA_MAP6;
+ case 6: return MA_MAP7;
+ case 7: return MA_MAP8;
+ default: return 0;
+ }
+}
+
+void make_mat_editipo(SpaceIpo *si)
+{
+ EditIpo *ei;
+ int a, len;
+
+ if(si->from==0) return;
+
+ ei= si->editipo= MEM_callocN(MA_TOTIPO*sizeof(EditIpo), "editipo");
+
+ si->totipo= MA_TOTIPO;
+
+ for(a=0; a<MA_TOTIPO; a++) {
+ getname_mat_ei(ma_ar[a], ei->name);
+ ei->adrcode= ma_ar[a];
+
+ if(ei->adrcode & MA_MAP1) {
+ ei->adrcode-= MA_MAP1;
+ ei->adrcode |= texchannel_to_adrcode(si->channel);
+ }
+ else {
+ /* dit was weggecommentaard. Waarom? */
+ if(ei->adrcode==MA_MODE) ei->disptype= IPO_DISPBITS;
+ }
+
+ ei->col= ipo_rainbow(a, WO_TOTIPO);
+
+ len= strlen(ei->name);
+ if(len) {
+ if( ei->name[ len-1 ]=='R') ei->col= 0x5050FF;
+ else if( ei->name[ len-1 ]=='G') ei->col= 0x50FF50;
+ else if( ei->name[ len-1 ]=='B') ei->col= 0xFF7050;
+ }
+
+ ei->icu= find_ipocurve(si->ipo, ei->adrcode);
+ if(ei->icu) {
+ ei->flag= ei->icu->flag;
+ }
+
+ ei++;
+ }
+}
+
+void make_world_editipo(SpaceIpo *si)
+{
+ EditIpo *ei;
+ int a, len;
+
+ if(si->from==0) return;
+
+ ei= si->editipo= MEM_callocN(WO_TOTIPO*sizeof(EditIpo), "editipo");
+
+ si->totipo= WO_TOTIPO;
+
+ for(a=0; a<WO_TOTIPO; a++) {
+ getname_world_ei(wo_ar[a], ei->name);
+ ei->adrcode= wo_ar[a];
+
+ if(ei->adrcode & MA_MAP1) {
+ ei->adrcode-= MA_MAP1;
+ ei->adrcode |= texchannel_to_adrcode(si->channel);
+ }
+ else {
+ if(ei->adrcode==MA_MODE) ei->disptype= IPO_DISPBITS;
+ }
+
+ ei->col= ipo_rainbow(a, MA_TOTIPO);
+
+ len= strlen(ei->name);
+ if(len) {
+ if( ei->name[ len-1 ]=='R') ei->col= 0x5050FF;
+ else if( ei->name[ len-1 ]=='G') ei->col= 0x50FF50;
+ else if( ei->name[ len-1 ]=='B') ei->col= 0xFF7050;
+ }
+
+ ei->icu= find_ipocurve(si->ipo, ei->adrcode);
+ if(ei->icu) {
+ ei->flag= ei->icu->flag;
+ }
+
+ ei++;
+ }
+}
+
+void make_lamp_editipo(SpaceIpo *si)
+{
+ EditIpo *ei;
+ int a;
+
+ ei= si->editipo= MEM_callocN(LA_TOTIPO*sizeof(EditIpo), "editipo");
+
+ si->totipo= LA_TOTIPO;
+
+
+ for(a=0; a<LA_TOTIPO; a++) {
+ getname_la_ei(la_ar[a], ei->name);
+ ei->adrcode= la_ar[a];
+
+ if(ei->adrcode & MA_MAP1) {
+ ei->adrcode-= MA_MAP1;
+ ei->adrcode |= texchannel_to_adrcode(si->channel);
+ }
+
+ ei->col= ipo_rainbow(a, LA_TOTIPO);
+
+ ei->icu= find_ipocurve(si->ipo, ei->adrcode);
+ if(ei->icu) {
+ ei->flag= ei->icu->flag;
+ }
+
+ ei++;
+ }
+}
+
+void make_camera_editipo(SpaceIpo *si)
+{
+ EditIpo *ei;
+ int a;
+
+ ei= si->editipo= MEM_callocN(CAM_TOTIPO*sizeof(EditIpo), "editipo");
+
+ si->totipo= CAM_TOTIPO;
+
+
+ for(a=0; a<CAM_TOTIPO; a++) {
+ getname_cam_ei(cam_ar[a], ei->name);
+ ei->adrcode= cam_ar[a];
+
+ ei->col= ipo_rainbow(a, CAM_TOTIPO);
+
+ ei->icu= find_ipocurve(si->ipo, ei->adrcode);
+ if(ei->icu) {
+ ei->flag= ei->icu->flag;
+ }
+
+ ei++;
+ }
+}
+
+int make_constraint_editipo(Ipo *ipo, EditIpo **si)
+{
+ EditIpo *ei;
+ int a;
+
+ ei= *si= MEM_callocN(CO_TOTIPO*sizeof(EditIpo), "editipo");
+
+ for(a=0; a<CO_TOTIPO; a++) {
+ getname_co_ei(co_ar[a], ei->name);
+ ei->adrcode= co_ar[a];
+
+ ei->col= ipo_rainbow(a, CO_TOTIPO);
+
+ ei->icu= find_ipocurve(ipo, ei->adrcode);
+ if(ei->icu) {
+ ei->flag= ei->icu->flag;
+ }
+
+ ei++;
+ }
+
+ return CO_TOTIPO;
+}
+int make_action_editipo(Ipo *ipo, EditIpo **si)
+{
+ EditIpo *ei;
+ int a;
+
+ ei= *si= MEM_callocN(AC_TOTIPO*sizeof(EditIpo), "editipo");
+
+ for(a=0; a<AC_TOTIPO; a++) {
+ getname_ac_ei(ac_ar[a], ei->name);
+ ei->adrcode= ac_ar[a];
+
+ ei->col= ipo_rainbow(a, AC_TOTIPO);
+
+ ei->icu= find_ipocurve(ipo, ei->adrcode);
+ if(ei->icu) {
+ ei->flag= ei->icu->flag;
+ }
+
+ ei++;
+ }
+
+ return AC_TOTIPO;
+}
+
+void make_sound_editipo(SpaceIpo *si)
+{
+ EditIpo *ei;
+ int a;
+
+ ei= si->editipo= MEM_callocN(SND_TOTIPO*sizeof(EditIpo), "editipo");
+
+ si->totipo= SND_TOTIPO;
+
+
+ for(a=0; a<SND_TOTIPO; a++) {
+ getname_snd_ei(snd_ar[a], ei->name);
+ ei->adrcode= snd_ar[a];
+
+ ei->col= ipo_rainbow(a, SND_TOTIPO);
+
+ ei->icu= find_ipocurve(si->ipo, ei->adrcode);
+ if(ei->icu) {
+ ei->flag= ei->icu->flag;
+ }
+
+ ei++;
+ }
+}
+
+void make_editipo()
+{
+ EditIpo *ei;
+ Object *ob;
+ ID *from;
+ rctf *rf;
+ int a;
+
+ if(G.sipo->editipo)
+ MEM_freeN(G.sipo->editipo);
+ G.sipo->editipo= 0;
+ G.sipo->totipo= 0;
+ ob= OBACT;
+
+ G.sipo->ipo= get_ipo_to_edit(&from);
+ G.sipo->from= from;
+
+ if(G.sipo->ipo) G.sipo->showkey= G.sipo->ipo->showkey;
+
+ if(G.sipo->blocktype==ID_SEQ) {
+ make_seq_editipo(G.sipo);
+ }
+ else if(G.sipo->blocktype==ID_WO) {
+ make_world_editipo(G.sipo);
+ }
+ else if(G.sipo->blocktype==ID_OB) {
+ if (ob) {
+ ob->ipowin= ID_OB;
+ make_ob_editipo(ob, G.sipo);
+ }
+ }
+ else if(G.sipo->blocktype==ID_MA) {
+ if (ob) {
+ ob->ipowin= ID_MA;
+ make_mat_editipo(G.sipo);
+ }
+ }
+ else if(G.sipo->blocktype==ID_CU) {
+ if (ob) {
+ ob->ipowin= ID_CU;
+ make_cu_editipo(G.sipo);
+ }
+ }
+ else if(G.sipo->blocktype==ID_KE) {
+ if (ob) {
+ ob->ipowin= ID_KE;
+ make_key_editipo(G.sipo);
+ }
+ }
+ else if(G.sipo->blocktype==ID_LA) {
+ if (ob) {
+ ob->ipowin= ID_LA;
+ make_lamp_editipo(G.sipo);
+ }
+ }
+ else if(G.sipo->blocktype==ID_CA) {
+ if (ob) {
+ ob->ipowin= ID_CA;
+ make_camera_editipo(G.sipo);
+ }
+ }
+ else if(G.sipo->blocktype==ID_SO) {
+ if (ob) {
+ ob->ipowin= ID_SO;
+ make_sound_editipo(G.sipo);
+ }
+ }
+ else if(G.sipo->blocktype==IPO_CO){
+ G.sipo->totipo = make_constraint_editipo(G.sipo->ipo, (EditIpo**)&G.sipo->editipo);
+ if (ob) {
+ ob->ipowin= IPO_CO;
+ }
+ }
+ else if(G.sipo->blocktype==ID_AC) {
+
+ G.sipo->totipo = make_action_editipo(G.sipo->ipo, (EditIpo**)&G.sipo->editipo);
+ if (ob) {
+ ob->ipowin= ID_AC;
+ }
+ }
+
+ if(G.sipo->editipo==0) return;
+
+ /* rowbut voor VISIBLE select */
+ G.sipo->rowbut= 0;
+ ei= G.sipo->editipo;
+ for(a=0; a<G.sipo->totipo; a++, ei++) {
+
+ if(ei->flag & IPO_VISIBLE) G.sipo->rowbut |= (1<<a);
+
+ if(ei->icu) ei->icu->flag= ei->flag;
+ }
+ editipo_changed(G.sipo, 0);
+
+ if(G.sipo->ipo) {
+
+ if (G.sipo->pin)
+ rf= &(G.sipo->v2d.cur);
+ else
+ rf= &(G.sipo->ipo->cur);
+
+ if(rf->xmin<rf->xmax && rf->ymin<rf->ymax) G.v2d->cur= *rf;
+
+ }
+ else {
+ if(G.sipo->blocktype==ID_OB) {
+ G.v2d->cur.xmin= 0.0;
+ G.v2d->cur.xmax= EFRA;
+ G.v2d->cur.ymin= -5.0;
+ G.v2d->cur.ymax= +5.0;
+ }
+ else if(G.sipo->blocktype==ID_CA) {
+ G.v2d->cur.xmin= 0.0;
+ G.v2d->cur.xmax= EFRA;
+ G.v2d->cur.ymin= 0.0;
+ G.v2d->cur.ymax= 100.0;
+ }
+ else if ELEM5(G.sipo->blocktype, ID_MA, ID_CU, ID_WO, ID_LA, IPO_CO) {
+ G.v2d->cur.xmin= (float)-0.1;
+ G.v2d->cur.xmax= EFRA;
+ G.v2d->cur.ymin= (float)-0.1;
+ G.v2d->cur.ymax= (float)+1.1;
+ }
+ else if(G.sipo->blocktype==ID_SEQ) {
+ G.v2d->cur.xmin= -5.0;
+ G.v2d->cur.xmax= 105.0;
+ G.v2d->cur.ymin= (float)-0.1;
+ G.v2d->cur.ymax= (float)+1.1;
+ }
+ else if(G.sipo->blocktype==ID_KE) {
+ G.v2d->cur.xmin= (float)-0.1;
+ G.v2d->cur.xmax= EFRA;
+ G.v2d->cur.ymin= (float)-0.1;
+ G.v2d->cur.ymax= (float)+2.1;
+ }
+
+ }
+}
+
+
+void test_editipo()
+{
+ Ipo *ipo;
+ ID *from;
+
+ if(G.sipo->editipo==0){
+ make_editipo();
+ }
+ else {
+ ipo= get_ipo_to_edit(&from);
+
+ if(G.sipo->ipo != ipo || G.sipo->from!=from)
+ make_editipo();
+
+ }
+
+ if (G.sipo->pin)
+ return;
+
+
+ if(G.sipo->ipo)
+ G.sipo->ipo->cur = G.v2d->cur;
+
+}
+
+/* ****************************************** */
+
+int totipo_edit, totipo_sel, totipo_vis, totipo_vert, totipo_vertsel, totipo_key, totipo_keysel;
+
+void get_status_editipo()
+{
+ EditIpo *ei;
+ IpoKey *ik;
+ BezTriple *bezt;
+ int a, b;
+
+ totipo_vis= 0;
+ totipo_sel= 0;
+ totipo_edit= 0;
+ totipo_vert= 0;
+ totipo_vertsel= 0;
+ totipo_key= 0;
+ totipo_keysel= 0;
+
+ if(G.sipo->ipo && G.sipo->ipo->id.lib) return;
+
+ ei= G.sipo->editipo;
+ if(ei==0) return;
+ for(a=0; a<G.sipo->totipo; a++) {
+ if( ei->flag & IPO_VISIBLE ) {
+ totipo_vis++;
+ if(ei->flag & IPO_SELECT) totipo_sel++;
+ if(G.sipo->showkey || (ei->flag & IPO_EDIT)) {
+
+ /* als showkey: wel de vertices tellen (voor grab) */
+ if(G.sipo->showkey==0) totipo_edit++;
+
+ if(ei->icu) {
+ if(ei->icu->bezt) {
+ bezt= ei->icu->bezt;
+ b= ei->icu->totvert;
+ while(b--) {
+ if(ei->icu->ipo==IPO_BEZ) {
+ if(bezt->f1 & 1) totipo_vertsel++;
+ if(bezt->f3 & 1) totipo_vertsel++;
+ totipo_vert+= 2;
+ }
+ if(bezt->f2 & 1) totipo_vertsel++;
+
+ totipo_vert++;
+ bezt++;
+ }
+ }
+ }
+ }
+ }
+ ei++;
+ }
+
+ if(G.sipo->showkey) {
+ ik= G.sipo->ipokey.first;
+ while(ik) {
+ totipo_key++;
+ if(ik->flag & 1) totipo_keysel++;
+ ik= ik->next;
+ }
+ }
+}
+
+
+
+void update_editipo_flags()
+{
+ EditIpo *ei;
+ IpoKey *ik;
+ unsigned int flag;
+ int a;
+
+ ei= G.sipo->editipo;
+ if(ei) {
+ for(a=0; a<G.sipo->totipo; a++, ei++) {
+ ei->flag &= ~IPO_VISIBLE;
+ flag= (1<<a);
+ if( G.sipo->rowbut & flag ) ei->flag |= IPO_VISIBLE;
+
+ if(ei->icu) ei->icu->flag= ei->flag;
+
+ }
+ }
+ if(G.sipo->showkey) {
+ ik= G.sipo->ipokey.first;
+ while(ik) {
+ for(a=0; a<G.sipo->totipo; a++) {
+ if(ik->data[a]) {
+ if(ik->flag & 1) {
+ ik->data[a]->f1 |= 1;
+ ik->data[a]->f2 |= 1;
+ ik->data[a]->f3 |= 1;
+ }
+ else {
+ ik->data[a]->f1 &= ~1;
+ ik->data[a]->f2 &= ~1;
+ ik->data[a]->f3 &= ~1;
+ }
+ }
+ }
+ ik= ik->next;
+ }
+ }
+}
+
+void set_editflag_editipo()
+{
+ EditIpo *ei;
+ int a; /* , tot= 0, ok= 0; */
+
+ /* van showkey direkt door naar editen geselecteerde punten */
+ if(G.sipo->showkey) {
+ G.sipo->showkey= 0;
+ if(G.sipo->ipo) G.sipo->ipo->showkey= 0;
+ ei= G.sipo->editipo;
+ for(a=0; a<G.sipo->totipo; a++, ei++) ei->flag |= IPO_SELECT;
+ scrarea_queue_headredraw(curarea);
+ allqueue(REDRAWVIEW3D, 0);
+ }
+
+ get_status_editipo();
+
+ if(G.sipo->ipo && G.sipo->ipo->id.lib) return;
+
+ ei= G.sipo->editipo;
+ for(a=0; a<G.sipo->totipo; a++, ei++) {
+ if(ei->icu) {
+ if(ei->flag & IPO_VISIBLE) {
+
+ if(totipo_edit==0 && (ei->flag & IPO_SELECT)) {
+ ei->flag |= IPO_EDIT;
+ ei->icu->flag= ei->flag;
+ }
+ else if(totipo_edit && (ei->flag & IPO_EDIT)) {
+ ei->flag -= IPO_EDIT;
+ ei->icu->flag= ei->flag;
+ }
+ else if(totipo_vis==1) {
+ if(ei->flag & IPO_EDIT) ei->flag -= IPO_EDIT;
+ else ei->flag |= IPO_EDIT;
+ ei->icu->flag= ei->flag;
+ }
+ }
+ }
+ }
+
+ scrarea_queue_winredraw(curarea);
+}
+
+void swap_selectall_editipo()
+{
+ Object *ob;
+ EditIpo *ei;
+ IpoKey *ik;
+ BezTriple *bezt;
+ int a, b; /* , sel=0; */
+
+
+ deselectall_key();
+
+ get_status_editipo();
+
+
+
+ if(G.sipo->showkey) {
+ ik= G.sipo->ipokey.first;
+ while(ik) {
+ if(totipo_vertsel) ik->flag &= ~1;
+ else ik->flag |= 1;
+ ik= ik->next;
+ }
+ update_editipo_flags();
+
+ if(G.sipo->showkey && G.sipo->blocktype==ID_OB ) {
+ ob= OBACT;
+ if(ob && (ob->ipoflag & OB_DRAWKEY)) draw_object_ext(BASACT);
+ }
+ }
+ else if(totipo_edit==0) {
+ ei= G.sipo->editipo;
+ if (ei){
+ for(a=0; a<G.sipo->totipo; a++) {
+ if( ei->flag & IPO_VISIBLE ) {
+ if(totipo_sel) ei->flag &= ~IPO_SELECT;
+ else ei->flag |= IPO_SELECT;
+ }
+ ei++;
+ }
+ update_editipo_flags();
+ }
+ }
+ else {
+ ei= G.sipo->editipo;
+ for(a=0; a<G.sipo->totipo; a++) {
+ if ISPOIN3(ei, flag & IPO_VISIBLE, flag & IPO_EDIT, icu ) {
+ bezt= ei->icu->bezt;
+ if(bezt) {
+ b= ei->icu->totvert;
+ while(b--) {
+ if(totipo_vertsel) {
+ bezt->f1= bezt->f2= bezt->f3= 0;
+ }
+ else {
+ bezt->f1= bezt->f2= bezt->f3= 1;
+ }
+ bezt++;
+ }
+ }
+ }
+ ei++;
+ }
+
+ }
+
+ scrarea_queue_winredraw(curarea);
+
+}
+
+void swap_visible_editipo()
+{
+ EditIpo *ei;
+ Object *ob;
+ int a; /* , sel=0; */
+
+ get_status_editipo();
+
+ G.sipo->rowbut= 0;
+
+ ei= G.sipo->editipo;
+ for(a=0; a<G.sipo->totipo; a++) {
+ if(totipo_vis==0) {
+ if(ei->icu) {
+ ei->flag |= IPO_VISIBLE;
+ G.sipo->rowbut |= (1<<a);
+ }
+ }
+ else ei->flag &= ~IPO_VISIBLE;
+ ei++;
+ }
+
+ update_editipo_flags();
+
+ if(G.sipo->showkey) {
+
+ make_ipokey();
+
+ ob= OBACT;
+ if(ob && (ob->ipoflag & OB_DRAWKEY)) allqueue(REDRAWVIEW3D, 0);
+ }
+
+ scrarea_queue_winredraw(curarea);
+
+}
+
+void deselectall_editipo()
+{
+ EditIpo *ei;
+ IpoKey *ik;
+ BezTriple *bezt;
+ int a, b; /* , sel=0; */
+
+ deselectall_key();
+
+ get_status_editipo();
+
+ if(G.sipo->showkey) {
+ ik= G.sipo->ipokey.first;
+ while(ik) {
+ ik->flag &= ~1;
+ ik= ik->next;
+ }
+ update_editipo_flags();
+
+ }
+ else if(totipo_edit==0) {
+
+ ei= G.sipo->editipo;
+ for(a=0; a<G.sipo->totipo; a++) {
+ if( ei->flag & IPO_VISIBLE ) {
+ ei->flag &= ~IPO_SELECT;
+ }
+ ei++;
+ }
+ update_editipo_flags();
+ }
+ else {
+ ei= G.sipo->editipo;
+ for(a=0; a<G.sipo->totipo; a++) {
+ if ISPOIN3(ei, flag & IPO_VISIBLE, flag & IPO_EDIT, icu ) {
+ if(ei->icu->bezt) {
+ bezt= ei->icu->bezt;
+ b= ei->icu->totvert;
+ while(b--) {
+ bezt->f1= bezt->f2= bezt->f3= 0;
+ bezt++;
+ }
+ }
+ }
+ ei++;
+ }
+ }
+
+ scrarea_queue_winredraw(curarea);
+}
+
+short findnearest_ipovert(IpoCurve **icu, BezTriple **bezt)
+{
+ /* selected krijgen een nadeel */
+ /* in icu en (bezt of bp) wordt nearest weggeschreven */
+ /* return 0 1 2: handlepunt */
+ EditIpo *ei;
+ BezTriple *bezt1;
+ int a, b;
+ short dist= 100, temp, mval[2], hpoint=0;
+
+ *icu= 0;
+ *bezt= 0;
+
+ getmouseco_areawin(mval);
+
+ ei= G.sipo->editipo;
+ for(a=0; a<G.sipo->totipo; a++, ei++) {
+ if ISPOIN3(ei, flag & IPO_VISIBLE, flag & IPO_EDIT, icu) {
+
+ if(ei->icu->bezt) {
+ bezt1= ei->icu->bezt;
+ b= ei->icu->totvert;
+ while(b--) {
+
+ ipoco_to_areaco_noclip(G.v2d, bezt1->vec[0], bezt1->s[0]);
+ ipoco_to_areaco_noclip(G.v2d, bezt1->vec[1], bezt1->s[1]);
+ ipoco_to_areaco_noclip(G.v2d, bezt1->vec[2], bezt1->s[2]);
+
+ if(ei->disptype==IPO_DISPBITS) {
+ temp= abs(mval[0]- bezt1->s[1][0]);
+ }
+ else temp= abs(mval[0]- bezt1->s[1][0])+ abs(mval[1]- bezt1->s[1][1]);
+
+ if( bezt1->f2 & 1) temp+=5;
+ if(temp<dist) {
+ hpoint= 1;
+ *bezt= bezt1;
+ dist= temp;
+ *icu= ei->icu;
+ }
+
+ if(ei->disptype!=IPO_DISPBITS && ei->icu->ipo==IPO_BEZ) {
+ /* middelste punten een klein voordeel */
+ temp= -3+abs(mval[0]- bezt1->s[0][0])+ abs(mval[1]- bezt1->s[0][1]);
+ if( bezt1->f1 & 1) temp+=5;
+ if(temp<dist) {
+ hpoint= 0;
+ *bezt= bezt1;
+ dist= temp;
+ *icu= ei->icu;
+ }
+
+ temp= abs(mval[0]- bezt1->s[2][0])+ abs(mval[1]- bezt1->s[2][1]);
+ if( bezt1->f3 & 1) temp+=5;
+ if(temp<dist) {
+ hpoint= 2;
+ *bezt=bezt1;
+ dist= temp;
+ *icu= ei->icu;
+ }
+ }
+ bezt1++;
+ }
+ }
+ }
+ }
+
+ return hpoint;
+}
+
+
+void move_to_frame()
+{
+ EditIpo *ei;
+ BezTriple *bezt;
+ ID *id;
+ float cfra;
+ int a, b;
+
+ if(G.sipo->editipo==0) return;
+
+ ei= G.sipo->editipo;
+
+ for(a=0; a<G.sipo->totipo; a++, ei++) {
+ if ISPOIN(ei, flag & IPO_VISIBLE, icu) {
+ if(G.sipo->showkey || (ei->flag & IPO_EDIT)) {
+
+ if(ei->icu->bezt) {
+
+ b= ei->icu->totvert;
+ bezt= ei->icu->bezt;
+ while(b--) {
+ if(BEZSELECTED(bezt)) {
+
+ cfra= bezt->vec[1][0]/G.scene->r.framelen;
+
+ id= G.sipo->from;
+ if(id && GS(id->name)==ID_OB ) {
+ Object *ob= (Object *)id;
+ if(ob->sf!=0.0 && (ob->ipoflag & OB_OFFS_OB) ) {
+ cfra+= ob->sf/G.scene->r.framelen;
+ }
+ }
+ CFRA= (short)floor(cfra+0.5);
+
+ if(CFRA < 1) CFRA= 1;
+ update_for_newframe();
+
+ break;
+ }
+ bezt++;
+ }
+ }
+ }
+ }
+ }
+}
+
+/* *********************************** */
+
+void do_ipowin_buts(short event)
+{
+ if((G.qual & LR_SHIFTKEY)==0) {
+ G.sipo->rowbut= (1<<event);
+ }
+ scrarea_queue_winredraw(curarea);
+
+ update_editipo_flags();
+
+ if(G.sipo->showkey) {
+ make_ipokey();
+ if(G.sipo->blocktype==ID_OB) allqueue(REDRAWVIEW3D, 0);
+ }
+
+}
+
+void do_ipo_selectbuttons()
+{
+ EditIpo *ei, *ei1;
+ int a, nr;
+ short mval[2];
+
+ if(G.sipo->showkey) return;
+
+ /* geen editipo toestaan: editipo's naar selected omzetten */
+ get_status_editipo();
+ if(totipo_edit) {
+ set_editflag_editipo();
+ }
+
+ /* welke */
+ getmouseco_areawin(mval);
+
+ nr= -(mval[1]-curarea->winy+30-G.sipo->butofs-IPOBUTY)/IPOBUTY;
+ if(nr>=0 && nr<G.sipo->totipo) {
+ ei= G.sipo->editipo;
+ ei+= nr;
+
+ if(ei->icu) {
+ if((ei->flag & IPO_VISIBLE)==0) {
+ ei->flag |= IPO_VISIBLE;
+ G.sipo->rowbut |= (1<<nr);
+ }
+
+ if((G.qual & LR_SHIFTKEY)==0) {
+ ei1= G.sipo->editipo;
+ for(a=0; a<G.sipo->totipo; a++) {
+ ei1->flag &= ~IPO_SELECT;
+ ei1++;
+ }
+ }
+
+ if(ei->flag & IPO_SELECT) {
+ ei->flag &= ~IPO_SELECT;
+ }
+ else {
+ ei->flag |= IPO_SELECT;
+ }
+
+ update_editipo_flags();
+ scrarea_queue_winredraw(curarea);
+ }
+ }
+}
+
+/* ******************************************* */
+
+EditIpo *get_editipo()
+{
+ EditIpo *ei;
+ int a; /* , sel=0; */
+
+ get_status_editipo();
+
+ if(totipo_edit>1) {
+ error("Too many editipo's");
+ return 0;
+ }
+ if(G.sipo->editipo==0) return 0;
+
+ ei= G.sipo->editipo;
+ for(a=0; a<G.sipo->totipo; a++) {
+ if(ei->flag & IPO_VISIBLE) {
+ if( ei->flag & IPO_EDIT ) return ei;
+ else if(totipo_vis==1) return ei;
+
+ if(ei->flag & IPO_SELECT) {
+ if(totipo_sel==1) return ei;
+ }
+ }
+ ei++;
+ }
+ return 0;
+}
+
+
+static Ipo *get_ipo(ID *from, short type, int make)
+{
+ Object *ob;
+ Material *ma;
+ Curve *cu;
+ Sequence *seq;
+ Key *key;
+ World *wo;
+ Lamp *la;
+ Camera *ca;
+ Ipo *ipo= 0;
+ bAction *act;
+
+ if( type==ID_OB) {
+ ob= (Object *)from;
+ if(ob->id.lib) return 0;
+
+ ipo= ob->ipo;
+ if(make && ipo==0) ipo= ob->ipo= add_ipo("ObIpo", ID_OB);
+ }
+ else if( type==IPO_CO){
+ ob= (Object *)from;
+ if(ob->id.lib) return 0;
+
+ if (ob->activecon){
+ ipo= ob->activecon->ipo;
+ if(make && ipo==0) ipo= ob->activecon->ipo= add_ipo("CoIpo", IPO_CO);
+ }
+ }
+ else if( type==ID_AC) {
+ act= (bAction *)from;
+ if (!act->achan) return 0;
+ if (act->id.lib) return 0;
+ ipo= act->achan->ipo;
+
+ /* This should never happen */
+ if(make && ipo==0) ipo= act->achan->ipo= add_ipo("AcIpo", ID_AC);
+ }
+ else if( type==ID_MA) {
+ ma= (Material *)from;
+ if(ma->id.lib) return 0;
+ ipo= ma->ipo;
+
+ if(make && ipo==0) ipo= ma->ipo= add_ipo("MatIpo", ID_MA);
+ }
+
+ else if( type==ID_SEQ) {
+ seq= (Sequence *)from;
+
+ if(seq->type & SEQ_EFFECT) {
+ ipo= seq->ipo;
+ if(make && ipo==0) ipo= seq->ipo= add_ipo("SeqIpo", ID_SEQ);
+ }
+ else return 0;
+ }
+ else if( type==ID_CU) {
+ cu= (Curve *)from;
+ if(cu->id.lib) return 0;
+ ipo= cu->ipo;
+
+ if(make && ipo==0) ipo= cu->ipo= add_ipo("CuIpo", ID_CU);
+ }
+ else if( type==ID_KE) {
+ key= (Key *)from;
+ if(key->id.lib) return 0;
+ ipo= key->ipo;
+
+ if(make && ipo==0) ipo= key->ipo= add_ipo("KeyIpo", ID_KE);
+ }
+ else if( type==ID_WO) {
+ wo= (World *)from;
+ if(wo->id.lib) return 0;
+ ipo= wo->ipo;
+
+ if(make && ipo==0) ipo= wo->ipo= add_ipo("WoIpo", ID_WO);
+ }
+ else if( type==ID_LA) {
+ la= (Lamp *)from;
+ if(la->id.lib) return 0;
+ ipo= la->ipo;
+
+ if(make && ipo==0) ipo= la->ipo= add_ipo("LaIpo", ID_LA);
+ }
+ else if( type==ID_CA) {
+ ca= (Camera *)from;
+ if(ca->id.lib) return 0;
+ ipo= ca->ipo;
+
+ if(make && ipo==0) ipo= ca->ipo= add_ipo("CaIpo", ID_CA);
+ }
+ else if( type==ID_SO) {
+ bSound *snd= (bSound *)from;
+ if(snd->id.lib) return 0;
+ ipo= snd->ipo;
+
+ if(make && ipo==0) ipo= snd->ipo= add_ipo("SndIpo", ID_SO);
+ }
+ else return 0;
+
+ return ipo;
+}
+
+
+// this function should not have the G.sipo in it...
+
+IpoCurve *get_ipocurve(ID *from, short type, int adrcode, Ipo *useipo)
+{
+ Ipo *ipo= 0;
+ IpoCurve *icu=0;
+
+ /* return 0 als lib */
+ /* ook testen of ipo en ipocurve bestaan */
+
+ if (useipo==NULL) {
+
+ if (G.sipo==NULL || G.sipo->pin==0){
+ ipo= get_ipo(from, type, 1); /* 1= make */
+ }
+ else
+ ipo = G.sipo->ipo;
+
+
+ if(G.sipo) {
+ if (G.sipo->pin==0) G.sipo->ipo= ipo;
+ }
+ }
+ else
+ ipo= useipo;
+
+
+ if(ipo && ipo->id.lib==0) {
+
+ icu= ipo->curve.first;
+ while(icu) {
+ if(icu->adrcode==adrcode) break;
+ icu= icu->next;
+ }
+ if(icu==0) {
+ icu= MEM_callocN(sizeof(IpoCurve), "ipocurve");
+
+ icu->flag |= IPO_VISIBLE;
+
+ if (!useipo && G.sipo && G.sipo->pin)
+ icu->blocktype = G.sipo->blocktype;
+ else
+ icu->blocktype= type;
+ icu->adrcode= adrcode;
+
+ set_icu_vars(icu);
+
+ BLI_addtail( &(ipo->curve), icu);
+ }
+ }
+ return icu;
+}
+
+void insert_vert_ipo(IpoCurve *icu, float x, float y)
+{
+ BezTriple *bezt, beztr, *newbezt;
+ int a = 0, h1, h2;
+
+ memset(&beztr, 0, sizeof(BezTriple));
+ beztr.vec[1][0]= x;
+ beztr.vec[1][1]= y;
+ beztr.hide= IPO_BEZ;
+ beztr.f1= beztr.f2= beztr.f3= SELECT;
+ beztr.h1= beztr.h2= HD_AUTO;
+
+ bezt= icu->bezt;
+
+ if(bezt==0) {
+ icu->bezt= MEM_callocN( sizeof(BezTriple), "beztriple");
+ *(icu->bezt)= beztr;
+ icu->totvert= 1;
+ }
+ else {
+ /* alle vertices deselect */
+ for(a=0; a<icu->totvert; a++, bezt++) {
+ bezt->f1= bezt->f2= bezt->f3= 0;
+ }
+
+ bezt= icu->bezt;
+ for(a=0; a<=icu->totvert; a++, bezt++) {
+
+ /* geen dubbele punten */
+ if(a<icu->totvert && (bezt->vec[1][0]>x-IPOTHRESH && bezt->vec[1][0]<x+IPOTHRESH)) {
+ *(bezt)= beztr;
+ break;
+ }
+ if(a==icu->totvert || bezt->vec[1][0] > x) {
+ newbezt= MEM_callocN( (icu->totvert+1)*sizeof(BezTriple), "beztriple");
+
+ if(a>0) memcpy(newbezt, icu->bezt, a*sizeof(BezTriple));
+
+ bezt= newbezt+a;
+ *(bezt)= beztr;
+
+ if(a<icu->totvert) memcpy(newbezt+a+1, icu->bezt+a, (icu->totvert-a)*sizeof(BezTriple));
+
+ MEM_freeN(icu->bezt);
+ icu->bezt= newbezt;
+
+ icu->totvert++;
+ break;
+ }
+ }
+ }
+
+
+ calchandles_ipocurve(icu);
+
+ /* handletype goedzetten */
+ if(icu->totvert>2) {
+ h1= h2= HD_AUTO;
+ if(a>0) h1= (bezt-1)->h2;
+ if(a<icu->totvert-1) h2= (bezt+1)->h1;
+ bezt->h1= h1;
+ bezt->h2= h2;
+
+ calchandles_ipocurve(icu);
+ }
+}
+
+void add_vert_ipo()
+{
+ EditIpo *ei;
+ float x, y;
+ int val;
+ short mval[2];
+
+ if(G.sipo->ipo && G.sipo->ipo->id.lib) return;
+ if(G.sipo->showkey) {
+ G.sipo->showkey= 0;
+ free_ipokey(&G.sipo->ipokey);
+ }
+
+ getmouseco_areawin(mval);
+
+ if(mval[0]>G.v2d->mask.xmax) return;
+
+ ei= get_editipo();
+ if(ei==0) return;
+
+ areamouseco_to_ipoco(G.v2d, mval, &x, &y);
+
+ if(ei->icu==0) {
+ if(G.sipo->from)
+ ei->icu= get_ipocurve(G.sipo->from, G.sipo->blocktype, ei->adrcode, 0);
+ }
+ if(ei->icu==0) return;
+
+ if(ei->disptype==IPO_DISPBITS) {
+ ei->icu->vartype= IPO_BITS;
+ val= (int)floor(y-0.5);
+ if(val<0) val= 0;
+ y= (float)(1 << val);
+ }
+
+ insert_vert_ipo(ei->icu, x, y);
+
+ /* voor zekerheid: als icu 0 was, of maar 1 curve visible */
+ ei->flag |= IPO_SELECT;
+ ei->icu->flag= ei->flag;
+
+ editipo_changed(G.sipo, 1);
+}
+
+void add_duplicate_editipo()
+{
+ Object *ob;
+ EditIpo *ei;
+ IpoCurve *icu;
+ BezTriple *bezt, *beztn, *newb;
+ int tot, a, b;
+
+ get_status_editipo();
+ if(totipo_vertsel==0) return;
+
+ ei= G.sipo->editipo;
+ for(a=0; a<G.sipo->totipo; a++, ei++) {
+ if ISPOIN3(ei, flag & IPO_VISIBLE, icu, icu->bezt) {
+ if(G.sipo->showkey || (ei->flag & IPO_EDIT)) {
+ icu= ei->icu;
+
+ /* hoeveel punten */
+ tot= 0;
+ b= icu->totvert;
+ bezt= icu->bezt;
+ while(b--) {
+ if(bezt->f2 & 1) tot++;
+ bezt++;
+ }
+
+ if(tot) {
+ icu->totvert+= tot;
+ newb= beztn= MEM_mallocN(icu->totvert*sizeof(BezTriple), "bezt");
+ bezt= icu->bezt;
+ b= icu->totvert-tot;
+ while(b--) {
+ *beztn= *bezt;
+ if(bezt->f2 & 1) {
+ beztn->f1= beztn->f2= beztn->f3= 0;
+ beztn++;
+ *beztn= *bezt;
+ }
+ beztn++;
+ bezt++;
+ }
+ MEM_freeN(icu->bezt);
+ icu->bezt= newb;
+
+ calchandles_ipocurve(icu);
+ }
+ }
+ }
+ }
+
+ if(G.sipo->showkey) {
+ make_ipokey();
+ if(G.sipo->blocktype==ID_OB) {
+ ob= OBACT;
+ if(ob && (ob->ipoflag & OB_DRAWKEY)) allqueue(REDRAWVIEW3D, 0);
+ }
+ }
+ transform_ipo('g');
+}
+
+void remove_doubles_ipo()
+{
+ EditIpo *ei;
+ IpoKey *ik, *ikn;
+ BezTriple *bezt, *newb, *new1;
+ float val;
+ int mode, a, b;
+
+ ei= G.sipo->editipo;
+ for(a=0; a<G.sipo->totipo; a++, ei++) {
+ if ISPOIN3(ei, flag & IPO_VISIBLE, icu, icu->bezt) {
+
+ /* OF de curve is selected OF in editmode OF in keymode */
+ mode= 0;
+ if(G.sipo->showkey || (ei->flag & IPO_EDIT)) mode= 1;
+ else if(ei->flag & IPO_SELECT) mode= 2;
+
+ if(mode) {
+ bezt= ei->icu->bezt;
+ newb= new1= MEM_mallocN(ei->icu->totvert*sizeof(BezTriple), "newbezt");
+ *newb= *bezt;
+ b= ei->icu->totvert-1;
+ bezt++;
+ while(b--) {
+
+ /* mag er verwijderd worden? */
+ if(mode==2 || (bezt->f2 & 1)) {
+
+ /* verschillen de punten? */
+ if( fabs( bezt->vec[1][0]-newb->vec[1][0] ) > 0.9 ) {
+ newb++;
+ *newb= *bezt;
+ }
+ else {
+ /* gemiddelde */
+ VecMidf(newb->vec[0], newb->vec[0], bezt->vec[0]);
+ VecMidf(newb->vec[1], newb->vec[1], bezt->vec[1]);
+ VecMidf(newb->vec[2], newb->vec[2], bezt->vec[2]);
+
+ newb->h1= newb->h2= HD_FREE;
+
+ ei->icu->totvert--;
+ }
+
+ }
+ else {
+ newb++;
+ *newb= *bezt;
+ }
+ bezt++;
+ }
+
+ MEM_freeN(ei->icu->bezt);
+ ei->icu->bezt= new1;
+
+ calchandles_ipocurve(ei->icu);
+ }
+ }
+ }
+
+ editipo_changed(G.sipo, 1); /* maakt ook ipokeys opnieuw! */
+
+ /* dubbele keys weg */
+ if(G.sipo->showkey) {
+ ik= G.sipo->ipokey.first;
+ ikn= ik->next;
+
+ while(ik && ikn) {
+ if( (ik->flag & 1) && (ikn->flag & 1) ) {
+ if( fabs(ik->val-ikn->val) < 0.9 ) {
+ val= (float)((ik->val + ikn->val)/2.0);
+
+ for(a=0; a<G.sipo->totipo; a++) {
+ if(ik->data[a]) ik->data[a]->vec[1][0]= val;
+ if(ikn->data[a]) ikn->data[a]->vec[1][0]= val;
+ }
+ }
+ }
+ ik= ikn;
+ ikn= ikn->next;
+
+ }
+
+ editipo_changed(G.sipo, 1); /* maakt ook ipokeys opnieuw! */
+
+ }
+ deselectall_editipo();
+}
+
+void join_ipo()
+{
+ EditIpo *ei;
+ IpoKey *ik;
+ IpoCurve *icu;
+ BezTriple *bezt, *beztn, *newb;
+ float val;
+ int mode, tot, a, b;
+
+ get_status_editipo();
+
+ mode= pupmenu("Join %t|All Selected %x1|Selected doubles %x2");
+ if( mode==2 ) {
+ remove_doubles_ipo();
+ return;
+ }
+ else if(mode!=1) return;
+
+ /* eerst: meerdere geselecteerde verts in 1 curve */
+ ei= G.sipo->editipo;
+ for(a=0; a<G.sipo->totipo; a++, ei++) {
+ if ISPOIN3(ei, flag & IPO_VISIBLE, icu, icu->bezt) {
+ if(G.sipo->showkey || (ei->flag & IPO_EDIT)) {
+ icu= ei->icu;
+
+ /* hoeveel punten */
+ tot= 0;
+ b= icu->totvert;
+ bezt= icu->bezt;
+ while(b--) {
+ if(bezt->f2 & 1) tot++;
+ bezt++;
+ }
+
+ if(tot>1) {
+ tot--;
+ icu->totvert-= tot;
+
+ newb= MEM_mallocN(icu->totvert*sizeof(BezTriple), "bezt");
+ /* het eerste punt wordt het nieuwe punt */
+ beztn= newb+1;
+ tot= 0;
+
+ bezt= icu->bezt;
+ b= icu->totvert+tot+1;
+ while(b--) {
+
+ if(bezt->f2 & 1) {
+ if(tot==0) *newb= *bezt;
+ else {
+ VecAddf(newb->vec[0], newb->vec[0], bezt->vec[0]);
+ VecAddf(newb->vec[1], newb->vec[1], bezt->vec[1]);
+ VecAddf(newb->vec[2], newb->vec[2], bezt->vec[2]);
+ }
+ tot++;
+ }
+ else {
+ *beztn= *bezt;
+ beztn++;
+ }
+ bezt++;
+ }
+
+ VecMulf(newb->vec[0], (float)(1.0/((float)tot)));
+ VecMulf(newb->vec[1], (float)(1.0/((float)tot)));
+ VecMulf(newb->vec[2], (float)(1.0/((float)tot)));
+
+ MEM_freeN(icu->bezt);
+ icu->bezt= newb;
+
+ sort_time_ipocurve(icu);
+ calchandles_ipocurve(icu);
+ }
+ }
+ }
+ }
+
+ /* dan: in keymode: meerdere geselecteerde keys samenvoegen */
+
+ editipo_changed(G.sipo, 1); /* maakt ook ipokeys opnieuw! */
+
+ if(G.sipo->showkey) {
+ ik= G.sipo->ipokey.first;
+ val= 0.0;
+ tot= 0;
+ while(ik) {
+ if(ik->flag & 1) {
+ for(a=0; a<G.sipo->totipo; a++) {
+ if(ik->data[a]) {
+ val+= ik->data[a]->vec[1][0];
+ break;
+ }
+ }
+ tot++;
+ }
+ ik= ik->next;
+ }
+ if(tot>1) {
+ val/= (float)tot;
+
+ ik= G.sipo->ipokey.first;
+ while(ik) {
+ if(ik->flag & 1) {
+ for(a=0; a<G.sipo->totipo; a++) {
+ if(ik->data[a]) {
+ ik->data[a]->vec[1][0]= val;
+ }
+ }
+ }
+ ik= ik->next;
+ }
+ editipo_changed(G.sipo, 0);
+ }
+ }
+ deselectall_editipo();
+}
+
+void ipo_snapmenu()
+{
+ EditIpo *ei;
+ BezTriple *bezt;
+ float dx = 0.0;
+ int a, b;
+ short event, ok, ok2;
+
+ event= pupmenu("Snap %t|Horizontal %x1|To next %x2|To frame %x3|To current frame%x4");
+ if(event < 1) return;
+
+ get_status_editipo();
+
+ ei= G.sipo->editipo;
+ for(b=0; b<G.sipo->totipo; b++, ei++) {
+ if ISPOIN3(ei, flag & IPO_VISIBLE, icu, icu->bezt) {
+
+ ok2= 0;
+ if(G.sipo->showkey) ok2= 1;
+ else if(totipo_vert && (ei->flag & IPO_EDIT)) ok2= 2;
+ else if(totipo_vert==0 && (ei->flag & IPO_SELECT)) ok2= 3;
+
+ if(ok2) {
+ bezt= ei->icu->bezt;
+ a= ei->icu->totvert;
+ while(a--) {
+ ok= 0;
+ if(totipo_vert) {
+ if(bezt->f2 & 1) ok= 1;
+ }
+ else ok= 1;
+
+ if(ok) {
+ if(event==1) {
+ bezt->vec[0][1]= bezt->vec[2][1]= bezt->vec[1][1];
+ if(bezt->h1==HD_AUTO || bezt->h1==HD_VECT) bezt->h1= HD_ALIGN;
+ if(bezt->h2==HD_AUTO || bezt->h2==HD_VECT) bezt->h2= HD_ALIGN;
+ }
+ else if(event==2) {
+ if(a) {
+ bezt->vec[0][1]= bezt->vec[1][1]= bezt->vec[2][1]= (bezt+1)->vec[1][1];
+ if(bezt->h1==HD_AUTO || bezt->h1==HD_VECT) bezt->h1= HD_ALIGN;
+ if(bezt->h2==HD_AUTO || bezt->h2==HD_VECT) bezt->h2= HD_ALIGN;
+ }
+ }
+ else if(event==3) {
+ bezt->vec[1][0]= (float)(floor(bezt->vec[1][0]+0.5));
+ }
+ else if(event==4) { /* to current frame */
+
+ if(ok2==1 || ok2==2) {
+
+ if(G.sipo->blocktype==ID_SEQ) {
+ Sequence *seq;
+
+ seq= (Sequence *)G.sipo->from;
+ if(seq) {
+ dx= (float)(CFRA-seq->startdisp);
+ dx= (float)(100.0*dx/((float)(seq->enddisp-seq->startdisp)));
+
+ dx-= bezt->vec[1][0];
+ }
+ }
+ else dx= G.scene->r.framelen*CFRA - bezt->vec[1][0];
+
+ bezt->vec[0][0]+= dx;
+ bezt->vec[1][0]+= dx;
+ bezt->vec[2][0]+= dx;
+ }
+ }
+ }
+
+ bezt++;
+ }
+ calchandles_ipocurve(ei->icu);
+ }
+ }
+ }
+ editipo_changed(G.sipo, 1);
+}
+
+
+
+void mouse_select_ipo()
+{
+ Object *ob;
+ EditIpo *ei, *actei= 0;
+ IpoCurve *icu;
+ IpoKey *ik, *actik;
+ BezTriple *bezt;
+ Key *key;
+ KeyBlock *kb, *actkb=0;
+ float x, y, dist, mindist;
+ int a, oldflag = 0, hand, ok;
+ short mval[2], xo, yo;
+
+ if(G.sipo->editipo==0) return;
+
+ get_status_editipo();
+
+ if(G.sipo->showkey) {
+ getmouseco_areawin(mval);
+
+ areamouseco_to_ipoco(G.v2d, mval, &x, &y);
+ actik= 0;
+ mindist= 1000.0;
+ ik= G.sipo->ipokey.first;
+ while(ik) {
+ dist= (float)(fabs(ik->val-x));
+ if(ik->flag & 1) dist+= 1.0;
+ if(dist < mindist) {
+ actik= ik;
+ mindist= dist;
+ }
+ ik= ik->next;
+ }
+ if(actik) {
+ oldflag= actik->flag;
+
+ if(G.qual & LR_SHIFTKEY);
+ else deselectall_editipo();
+
+ if(G.qual & LR_SHIFTKEY) {
+ if(oldflag & 1) actik->flag &= ~1;
+ else actik->flag |= 1;
+ }
+ else {
+ actik->flag |= 1;
+ }
+ }
+ }
+ else if(totipo_edit) {
+
+ hand= findnearest_ipovert(&icu, &bezt);
+
+ if(G.qual & LR_SHIFTKEY) {
+ if(bezt) {
+ if(hand==1) {
+ if(BEZSELECTED(bezt)) {
+ bezt->f1= bezt->f2= bezt->f3= 0;
+ }
+ else {
+ bezt->f1= bezt->f2= bezt->f3= 1;
+ }
+ }
+ else if(hand==0) {
+ if(bezt->f1 & 1) bezt->f1= 0;
+ else bezt->f1= 1;
+ }
+ else {
+ if(bezt->f3 & 1) bezt->f3= 0;
+ else bezt->f3= 1;
+ }
+ }
+ }
+ else {
+ deselectall_editipo();
+
+ if(bezt) {
+ if(hand==1) {
+ bezt->f1|= 1; bezt->f2|= 1; bezt->f3|= 1;
+ }
+ else if(hand==0) bezt->f1|= 1;
+ else bezt->f3|= 1;
+ }
+ }
+ }
+ else {
+
+ /* vertex keys ? */
+
+ if(G.sipo->blocktype==ID_KE && G.sipo->from) {
+ key= (Key *)G.sipo->from;
+
+ ei= G.sipo->editipo;
+ if(key->type==KEY_NORMAL || (ei->flag & IPO_VISIBLE)) {
+ getmouseco_areawin(mval);
+
+ areamouseco_to_ipoco(G.v2d, mval, &x, &y);
+ /* hoeveel is 20 pixels? */
+ mindist= (float)(20.0*(G.v2d->cur.ymax-G.v2d->cur.ymin)/(float)curarea->winy);
+
+ kb= key->block.first;
+ while(kb) {
+ dist= (float)(fabs(kb->pos-y));
+ if(kb->flag & SELECT) dist+= (float)0.01;
+ if(dist < mindist) {
+ actkb= kb;
+ mindist= dist;
+ }
+ kb= kb->next;
+ }
+ if(actkb) {
+ ok= TRUE;
+ if(G.obedit && (actkb->flag & 1)==0) {
+ ok= okee("Copy Key after leaving EditMode");
+ }
+ if(ok) {
+ /* doet ook alle keypos */
+ deselectall_editipo();
+
+ /* oldflag= actkb->flag; */
+
+ /* if(G.qual & LR_SHIFTKEY); */
+ /* else { */
+ /* deselectall_key(); */
+ /* } */
+
+ /* if(G.qual & LR_SHIFTKEY) { */
+ /* if(oldflag & 1) actkb->flag &= ~1; */
+ /* else actkb->flag |= 1; */
+ /* } */
+ /* else { */
+ actkb->flag |= 1;
+ /* } */
+
+ /* bereken keypos */
+ showkeypos((Key *)G.sipo->from, actkb);
+ }
+ }
+ }
+ }
+
+ /* select curve */
+ if(actkb==0) {
+ if(totipo_vis==1) {
+ ei= G.sipo->editipo;
+ for(a=0; a<G.sipo->totipo; a++, ei++) {
+ if(ei->icu) {
+ if(ei->flag & IPO_VISIBLE) actei= ei;
+ }
+ }
+ }
+ else if(totipo_vis>1) {
+ actei= select_proj_ipo(0, 0);
+ }
+
+ if(actei) oldflag= actei->flag;
+
+ if(G.qual & LR_SHIFTKEY);
+ else deselectall_editipo();
+
+ if(actei) {
+ if(G.qual & LR_SHIFTKEY) {
+ if(oldflag & IPO_SELECT) actei->flag &= ~IPO_SELECT;
+ else actei->flag |= IPO_SELECT;
+ }
+ else {
+ actei->flag |= IPO_SELECT;
+ }
+ }
+ }
+ }
+
+ update_editipo_flags();
+
+ force_draw();
+
+ if(G.sipo->showkey && G.sipo->blocktype==ID_OB) {
+ ob= OBACT;
+ if(ob && (ob->ipoflag & OB_DRAWKEY)) draw_object_ext(BASACT);
+ }
+
+ getmouseco_areawin(mval);
+ xo= mval[0];
+ yo= mval[1];
+
+ while(get_mbut()&R_MOUSE) {
+ getmouseco_areawin(mval);
+ if(abs(mval[0]-xo)+abs(mval[1]-yo) > 4) {
+
+ if(actkb) move_keys();
+ else transform_ipo('g');
+
+ return;
+ }
+ BIF_wait_for_statechange();
+ }
+}
+
+void sethandles_ipo(int code)
+{
+ /* code==1: set autohandle */
+ /* code==2: set vectorhandle */
+ /* als code==3 (HD_ALIGN) toggelt het, vectorhandles worden HD_FREE */
+ EditIpo *ei;
+ BezTriple *bezt;
+ int a, b, ok=0;
+
+ if(G.sipo->ipo && G.sipo->ipo->id.lib) return;
+
+ if(code==1 || code==2) {
+ ei= G.sipo->editipo;
+ for(a=0; a<G.sipo->totipo; a++, ei++) {
+ if ISPOIN4(ei, flag & IPO_VISIBLE, flag & IPO_EDIT, icu, icu->bezt) {
+ bezt= ei->icu->bezt;
+ b= ei->icu->totvert;
+ while(b--) {
+ if(bezt->f1 || bezt->f3) {
+ if(bezt->f1) bezt->h1= code;
+ if(bezt->f3) bezt->h2= code;
+
+ if(bezt->h1!=bezt->h2) {
+ if ELEM(bezt->h1, HD_ALIGN, HD_AUTO) bezt->h1= HD_FREE;
+ if ELEM(bezt->h2, HD_ALIGN, HD_AUTO) bezt->h2= HD_FREE;
+ }
+ }
+ bezt++;
+ }
+ calchandles_ipocurve(ei->icu);
+ }
+ }
+ }
+ else {
+ /* is er 1 handle NIET vrij: alles vrijmaken, else ALIGNED maken */
+
+ ei= G.sipo->editipo;
+ for(a=0; a<G.sipo->totipo; a++, ei++) {
+ if ISPOIN4(ei, flag & IPO_VISIBLE, flag & IPO_EDIT, icu, icu->bezt) {
+ bezt= ei->icu->bezt;
+ b= ei->icu->totvert;
+ while(b--) {
+ if(bezt->f1 && bezt->h1) ok= 1;
+ if(bezt->f3 && bezt->h2) ok= 1;
+ if(ok) break;
+ bezt++;
+ }
+ }
+ }
+ if(ok) ok= HD_FREE;
+ else ok= HD_ALIGN;
+
+ ei= G.sipo->editipo;
+ for(a=0; a<G.sipo->totipo; a++, ei++) {
+ if ISPOIN4(ei, flag & IPO_VISIBLE, flag & IPO_EDIT, icu, icu->bezt) {
+ bezt= ei->icu->bezt;
+ b= ei->icu->totvert;
+ while(b--) {
+ if(bezt->f1) bezt->h1= ok;
+ if(bezt->f3 ) bezt->h2= ok;
+
+ bezt++;
+ }
+ calchandles_ipocurve(ei->icu);
+ }
+ }
+ }
+ editipo_changed(G.sipo, 1);
+}
+
+void set_ipotype()
+{
+ EditIpo *ei;
+ Key *key;
+ KeyBlock *kb;
+ int a;
+ short event;
+
+ if(G.sipo->ipo && G.sipo->ipo->id.lib) return;
+ if(G.sipo->showkey) return;
+ get_status_editipo();
+
+ if(G.sipo->blocktype==ID_KE && totipo_edit==0 && totipo_sel==0) {
+ key= (Key *)G.sipo->from;
+ if(key==0) return;
+
+ event= pupmenu("Key Type %t|Linear %x1|Cardinal %x2|B spline %x3");
+ if(event < 1) return;
+
+ kb= key->block.first;
+ while(kb) {
+ if(kb->flag & SELECT) {
+ kb->type= 0;
+ if(event==1) kb->type= KEY_LINEAR;
+ if(event==2) kb->type= KEY_CARDINAL;
+ if(event==3) kb->type= KEY_BSPLINE;
+ }
+ kb= kb->next;
+ }
+ }
+ else {
+ event= pupmenu("Ipo Type %t|Constant %x1|Linear %x2|Bezier %x3");
+ if(event < 1) return;
+
+ ei= G.sipo->editipo;
+ for(a=0; a<G.sipo->totipo; a++, ei++) {
+ if ISPOIN3(ei, flag & IPO_VISIBLE, flag & IPO_SELECT, icu) {
+ if(event==1) ei->icu->ipo= IPO_CONST;
+ else if(event==2) ei->icu->ipo= IPO_LIN;
+ else ei->icu->ipo= IPO_BEZ;
+ }
+ }
+ }
+ scrarea_queue_winredraw(curarea);
+}
+
+void borderselect_ipo()
+{
+ EditIpo *ei;
+ IpoKey *ik;
+ BezTriple *bezt;
+ rcti rect;
+ rctf rectf;
+ int a, b, val;
+ short mval[2];
+
+ get_status_editipo();
+
+ val= get_border(&rect, 3);
+
+ if(val) {
+ mval[0]= rect.xmin;
+ mval[1]= rect.ymin;
+ areamouseco_to_ipoco(G.v2d, mval, &rectf.xmin, &rectf.ymin);
+ mval[0]= rect.xmax;
+ mval[1]= rect.ymax;
+ areamouseco_to_ipoco(G.v2d, mval, &rectf.xmax, &rectf.ymax);
+
+ if(G.sipo->showkey) {
+ ik= G.sipo->ipokey.first;
+ while(ik) {
+ if(rectf.xmin<ik->val && rectf.xmax>ik->val) {
+ if(val==LEFTMOUSE) ik->flag |= 1;
+ else ik->flag &= ~1;
+ }
+ ik= ik->next;
+ }
+ update_editipo_flags();
+ }
+ else if(totipo_edit==0) {
+ if(rect.xmin<rect.xmax && rect.ymin<rect.ymax)
+ select_proj_ipo(&rectf, val);
+ }
+ else {
+
+ ei= G.sipo->editipo;
+ for(a=0; a<G.sipo->totipo; a++, ei++) {
+ if ISPOIN3(ei, flag & IPO_VISIBLE, flag & IPO_EDIT, icu) {
+ if(ei->icu->bezt) {
+ b= ei->icu->totvert;
+ bezt= ei->icu->bezt;
+ while(b--) {
+ int bit= (val==LEFTMOUSE);
+
+ if(BLI_in_rctf(&rectf, bezt->vec[0][0], bezt->vec[0][1]))
+ bezt->f1 = (bezt->f1&~1) | bit;
+ if(BLI_in_rctf(&rectf, bezt->vec[1][0], bezt->vec[1][1]))
+ bezt->f2 = (bezt->f2&~1) | bit;
+ if(BLI_in_rctf(&rectf, bezt->vec[2][0], bezt->vec[2][1]))
+ bezt->f3 = (bezt->f3&~1) | bit;
+
+ bezt++;
+ }
+ }
+ }
+ }
+ }
+ scrarea_queue_winredraw(curarea);
+ }
+}
+
+
+
+
+void del_ipo()
+{
+ EditIpo *ei;
+ BezTriple *bezt, *bezt1;
+ int a, b;
+ int del, event;
+
+ get_status_editipo();
+ if(G.sipo->ipo && G.sipo->ipo->id.lib) return;
+
+ if(totipo_edit==0 && totipo_sel==0 && totipo_vertsel==0) {
+ delete_key();
+ return;
+ }
+
+ if( okee("Erase selected")==0 ) return;
+
+ // eerste doorloop, kunnen hele stukken weg?
+ ei= G.sipo->editipo;
+ for(a=0; a<G.sipo->totipo; a++, ei++) {
+
+ del= 0;
+
+ if(G.sipo->showkey==0 && totipo_edit==0) {
+ if ISPOIN3(ei, flag & IPO_VISIBLE, flag & IPO_SELECT, icu) {
+ del= 1;
+ }
+ }
+ else {
+ if ISPOIN(ei, flag & IPO_VISIBLE, icu) {
+ if(G.sipo->showkey || (ei->flag & IPO_EDIT)) {
+ if(ei->icu->bezt) {
+ bezt= ei->icu->bezt;
+ b= ei->icu->totvert;
+ if(b) {
+ while(b) {
+ if( BEZSELECTED(bezt) );
+ else break;
+ b--;
+ bezt++;
+ }
+ if(b==0) del= 1;
+ }
+ }
+ }
+ }
+ }
+
+ if(del) {
+ BLI_remlink( &(G.sipo->ipo->curve), ei->icu);
+ if(ei->icu->bezt) MEM_freeN(ei->icu->bezt);
+ MEM_freeN(ei->icu);
+ ei->flag &= ~IPO_SELECT;
+ ei->flag &= ~IPO_EDIT;
+ ei->icu= 0;
+ }
+ }
+
+ // tweede doorloop, kleine stukken weg: alleen curves
+ ei= G.sipo->editipo;
+ for(b=0; b<G.sipo->totipo; b++, ei++) {
+ if ISPOIN(ei, flag & IPO_VISIBLE, icu) {
+ if(G.sipo->showkey || (ei->flag & IPO_EDIT)) {
+
+ event= 0;
+ if(ei->icu->bezt) {
+
+ bezt= ei->icu->bezt;
+ for(a=0; a<ei->icu->totvert; a++) {
+ if( BEZSELECTED(bezt) ) {
+ memcpy(bezt, bezt+1, (ei->icu->totvert-a-1)*sizeof(BezTriple));
+ ei->icu->totvert--;
+ a--;
+ event= 1;
+ }
+ else bezt++;
+ }
+ if(event) {
+ bezt1 = (BezTriple*) MEM_mallocN(ei->icu->totvert * sizeof(BezTriple), "delNurb");
+ memcpy(bezt1, ei->icu->bezt, (ei->icu->totvert)*sizeof(BezTriple) );
+ MEM_freeN(ei->icu->bezt);
+ ei->icu->bezt= bezt1;
+ }
+ }
+ }
+ }
+ }
+
+ allqueue(REDRAWNLA, 0);
+ allqueue (REDRAWACTION, 0);
+ allqueue(REDRAWIPO, 0);
+ allspace(REMAKEIPO, 0);
+}
+
+ListBase ipocopybuf={0, 0};
+int totipocopybuf=0;
+
+void free_ipocopybuf()
+{
+ IpoCurve *icu;
+
+ while( (icu= ipocopybuf.first) ) {
+ if(icu->bezt) MEM_freeN(icu->bezt);
+ BLI_remlink(&ipocopybuf, icu);
+ MEM_freeN(icu);
+ }
+ totipocopybuf= 0;
+}
+
+void copy_editipo()
+{
+ EditIpo *ei;
+ IpoCurve *icu;
+ int a;
+
+ if(G.sipo->showkey) {
+ error("cannot copy\n");
+ return;
+ }
+
+ free_ipocopybuf();
+
+ ei= G.sipo->editipo;
+ for(a=0; a<G.sipo->totipo; a++, ei++) {
+ if ISPOIN(ei, flag & IPO_VISIBLE, icu) {
+ if( (ei->flag & IPO_EDIT) || (ei->flag & IPO_SELECT) ) {
+ icu= MEM_callocN(sizeof(IpoCurve), "ipocopybuf");
+ *icu= *(ei->icu);
+ BLI_addtail(&ipocopybuf, icu);
+ if(icu->bezt) {
+ icu->bezt= MEM_mallocN(icu->totvert*sizeof(BezTriple), "ipocopybuf");
+ memcpy(icu->bezt, ei->icu->bezt, icu->totvert*sizeof(BezTriple));
+ }
+ totipocopybuf++;
+ }
+ }
+ }
+
+ if(totipocopybuf==0) error("Copybuf is empty");
+}
+
+void paste_editipo()
+{
+ EditIpo *ei;
+ IpoCurve *icu;
+ int a, ok;
+
+ if(G.sipo->showkey) return;
+
+ if(totipocopybuf==0) return;
+ if(G.sipo->ipo==0) return;
+ if(G.sipo->ipo && G.sipo->ipo->id.lib) return;
+
+ get_status_editipo();
+
+ if(totipo_vis==0) {
+ error("No visible splines");
+ }
+ else if(totipo_vis!=totipocopybuf && totipo_sel!=totipocopybuf) {
+ error("Incompatible paste");
+ }
+ else {
+ /* problemen voorkomen: andere splines visible dan select */
+ if(totipo_vis==totipo_sel) totipo_vis= 0;
+
+ icu= ipocopybuf.first;
+ if(icu==0) return;
+
+ ei= G.sipo->editipo;
+ for(a=0; a<G.sipo->totipo; a++, ei++) {
+ if(ei->flag & IPO_VISIBLE) {
+ ok= 0;
+ if(totipo_vis==totipocopybuf) ok= 1;
+ if(totipo_sel==totipocopybuf && (ei->flag & IPO_SELECT)) ok= 1;
+
+ if(ok) {
+
+ ei->icu= get_ipocurve(G.sipo->from, G.sipo->blocktype, ei->adrcode, 0);
+ if(ei->icu==0) return;
+
+ if(ei->icu->bezt) MEM_freeN(ei->icu->bezt);
+ ei->icu->bezt= 0;
+
+ ei->icu->totvert= icu->totvert;
+ ei->icu->flag= ei->flag= icu->flag;
+ ei->icu->extrap= icu->extrap;
+ ei->icu->ipo= icu->ipo;
+
+ if(icu->bezt) {
+ ei->icu->bezt= MEM_mallocN(icu->totvert*sizeof(BezTriple), "ipocopybuf");
+ memcpy(ei->icu->bezt, icu->bezt, icu->totvert*sizeof(BezTriple));
+ }
+
+ icu= icu->next;
+
+ }
+ }
+ }
+ editipo_changed(G.sipo, 1);
+ }
+}
+
+void set_exprap_ipo(int mode)
+{
+ EditIpo *ei;
+ int a;
+
+ if(G.sipo->ipo && G.sipo->ipo->id.lib) return;
+ /* in geval van keys: altijd ok */
+
+ ei= G.sipo->editipo;
+ for(a=0; a<G.sipo->totipo; a++, ei++) {
+ if ISPOIN(ei, flag & IPO_VISIBLE, icu) {
+ if( (ei->flag & IPO_EDIT) || (ei->flag & IPO_SELECT) || (G.sipo->showkey) ) {
+ ei->icu->extrap= mode;
+ }
+ }
+ }
+ editipo_changed(G.sipo, 1);
+}
+
+int find_other_handles(EditIpo *eicur, float ctime, BezTriple **beztar)
+{
+ EditIpo *ei;
+ BezTriple *bezt;
+ int a, b, c= 1, totvert;
+
+ ei= G.sipo->editipo;
+ for(a=0; a<G.sipo->totipo; a++, ei++) {
+ if(ei!=eicur && ei->icu && (ei->flag & IPO_VISIBLE)) {
+
+ bezt= ei->icu->bezt;
+ totvert= ei->icu->totvert;
+
+ for(b=0; b<totvert; b++, bezt++) {
+ if( bezt->vec[1][0] < ctime+IPOTHRESH && bezt->vec[1][0] > ctime-IPOTHRESH) {
+ if(c>2) return 0;
+ beztar[c]= bezt;
+ c++;
+ }
+ }
+ }
+ }
+
+ if(c==3) return 1;
+ return 0;
+}
+
+void set_speed_editipo(float speed)
+{
+ EditIpo *ei;
+ BezTriple *bezt, *beztar[3];
+ float vec1[3], vec2[3];
+ int a, b, totvert, didit=0;
+
+ if(G.sipo->ipo && G.sipo->ipo->id.lib) return;
+
+ /* uitgaande van 1 visible curve, selected punt, bijhorende punten: lencorr! */
+
+ ei= G.sipo->editipo;
+ for(a=0; a<G.sipo->totipo; a++, ei++) {
+ if ISPOIN(ei, flag & IPO_VISIBLE, icu) {
+ bezt= ei->icu->bezt;
+ totvert= ei->icu->totvert;
+
+ for(b=0; b<totvert; b++, bezt++) {
+ if(BEZSELECTED(bezt)) {
+
+ beztar[0]= bezt;
+
+ if( find_other_handles(ei, bezt->vec[1][0], beztar) ) {
+ beztar[0]->h1= beztar[0]->h2= HD_ALIGN;
+ beztar[1]->h1= beztar[1]->h2= HD_ALIGN;
+ beztar[2]->h1= beztar[2]->h2= HD_ALIGN;
+
+ vec1[0]= (beztar[0]->vec[1][1] - beztar[0]->vec[0][1]) / (beztar[0]->vec[1][0] - beztar[0]->vec[0][0]) ;
+ vec2[0]= (beztar[0]->vec[1][1] - beztar[0]->vec[2][1]) / (beztar[0]->vec[2][0] - beztar[0]->vec[1][0]) ;
+
+ vec1[1]= (beztar[1]->vec[1][1] - beztar[1]->vec[0][1]) / (beztar[1]->vec[1][0] - beztar[1]->vec[0][0]) ;
+ vec2[1]= (beztar[1]->vec[1][1] - beztar[1]->vec[2][1]) / (beztar[1]->vec[2][0] - beztar[1]->vec[1][0]) ;
+
+ vec1[2]= (beztar[2]->vec[1][1] - beztar[2]->vec[0][1]) / (beztar[2]->vec[1][0] - beztar[2]->vec[0][0]) ;
+ vec2[2]= (beztar[2]->vec[1][1] - beztar[2]->vec[2][1]) / (beztar[2]->vec[2][0] - beztar[2]->vec[1][0]) ;
+
+ Normalise(vec1);
+ Normalise(vec2);
+
+ VecMulf(vec1, speed);
+ VecMulf(vec2, speed);
+
+ beztar[0]->vec[0][1]= beztar[0]->vec[1][1] - vec1[0]*(beztar[0]->vec[1][0] - beztar[0]->vec[0][0]) ;
+ beztar[0]->vec[2][1]= beztar[0]->vec[1][1] - vec2[0]*(beztar[0]->vec[2][0] - beztar[0]->vec[1][0]) ;
+
+ beztar[1]->vec[0][1]= beztar[1]->vec[1][1] - vec1[1]*(beztar[1]->vec[1][0] - beztar[1]->vec[0][0]) ;
+ beztar[1]->vec[2][1]= beztar[1]->vec[1][1] - vec2[1]*(beztar[1]->vec[2][0] - beztar[1]->vec[1][0]) ;
+
+ beztar[2]->vec[0][1]= beztar[2]->vec[1][1] - vec1[2]*(beztar[2]->vec[1][0] - beztar[2]->vec[0][0]) ;
+ beztar[2]->vec[2][1]= beztar[2]->vec[1][1] - vec2[2]*(beztar[2]->vec[2][0] - beztar[2]->vec[1][0]) ;
+
+ didit= 1;
+ }
+ else {
+ error("Cannot set speed");
+ }
+ }
+ }
+ break;
+ }
+ }
+
+ if(didit==0) error("Did not set speed");
+
+ editipo_changed(G.sipo, 1);
+ allqueue(REDRAWNLA, 0);
+ allqueue (REDRAWACTION, 0);
+ allqueue(REDRAWIPO, 0);
+
+}
+
+
+void insertkey(ID *id, int adrcode)
+{
+ IpoCurve *icu;
+ Ipo *ipo;
+ Object *ob;
+ void *poin;
+ float curval, cfra;
+ int type;
+
+ if(id) {
+
+ // this call here, otherwise get_ipo_curve gives it from the pinned ipo
+ ipo= get_ipo(id, GS(id->name), 1); // 1=make
+
+ icu= get_ipocurve(id, GS(id->name), adrcode, ipo);
+
+ if(icu) {
+ poin= get_ipo_poin(id, icu, &type);
+ if(poin) {
+ curval= read_ipo_poin(poin, type);
+
+ cfra= frame_to_float(CFRA);
+
+ if( GS(id->name)==ID_OB ) {
+ ob= (Object *)id;
+ if(ob->sf!=0.0 && (ob->ipoflag & OB_OFFS_OB) ) {
+ /* eigenlijk frametofloat overniew berekenen! daarvoor CFRA als float door kunnen geven */
+ cfra-= ob->sf*G.scene->r.framelen;
+ }
+ }
+
+ insert_vert_ipo(icu, cfra, curval);
+ }
+ }
+ }
+}
+
+void insertkey_editipo()
+{
+ EditIpo *ei;
+ IpoKey *ik;
+ ID *id;
+ float *fp, cfra, *insertvals;
+ int a, nr, ok, tot;
+ short event;
+
+ if(G.sipo->showkey)
+ event= pupmenu("Insert KeyVertices %t|Current frame %x1|Selected Keys %x2");
+ else
+ event= pupmenu("Insert KeyVertices %t|Current frame %x1");
+
+ if(event<1) return;
+
+ ei= G.sipo->editipo;
+ for(nr=0; nr<G.sipo->totipo; nr++, ei++) {
+ if ISPOIN(ei, flag & IPO_VISIBLE, icu) {
+
+ ok= 0;
+ if(G.sipo->showkey) ok= 1;
+ else if(ei->flag & IPO_SELECT) ok= 1;
+
+ if(ok) {
+ /* aantal tellen */
+ if(event==1) tot= 1;
+ else {
+ ik= G.sipo->ipokey.first;
+ tot= 0;
+ while(ik) {
+ if(ik->flag & 1) tot++;
+ ik= ik->next;
+ }
+ }
+ if(tot) {
+
+ /* correctie voor ob timeoffs */
+ cfra= frame_to_float(CFRA);
+ id= G.sipo->from;
+ if(id && GS(id->name)==ID_OB ) {
+ Object *ob= (Object *)id;
+ if(ob->sf!=0.0 && (ob->ipoflag & OB_OFFS_OB) ) {
+ cfra-= ob->sf*G.scene->r.framelen;
+ }
+ }
+ else if(id && GS(id->name)==ID_SEQ) {
+ extern Sequence *last_seq; /* editsequence.c */
+
+ if(last_seq) {
+ cfra= (float)(100.0*(cfra-last_seq->startdisp)/((float)(last_seq->enddisp-last_seq->startdisp)));
+ }
+ }
+
+ insertvals= MEM_mallocN(sizeof(float)*2*tot, "insertkey_editipo");
+ /* zeker zijn dat icu->curval klopt */
+ calc_ipo(G.sipo->ipo, cfra);
+
+ if(event==1) {
+ insertvals[0]= cfra;
+
+ insertvals[1]= ei->icu->curval;
+ }
+ else {
+ fp= insertvals;
+ ik= G.sipo->ipokey.first;
+ while(ik) {
+ if(ik->flag & 1) {
+ calc_ipo(G.sipo->ipo, ik->val);
+
+ fp[0]= ik->val;
+ fp[1]= ei->icu->curval;
+ fp+= 2;
+ }
+ ik= ik->next;
+ }
+ }
+ fp= insertvals;
+ for(a=0; a<tot; a++, fp+=2) {
+ insert_vert_ipo(ei->icu, fp[0], fp[1]);
+ }
+
+ MEM_freeN(insertvals);
+ calc_ipo(G.sipo->ipo, (float)CFRA);
+ }
+ }
+ }
+ }
+ allqueue (REDRAWACTION, 0);
+ allqueue(REDRAWNLA, 0);
+ allqueue(REDRAWIPO, 0);
+ allspace(REMAKEIPO, 0);
+}
+
+
+void common_insertkey()
+{
+ Base *base;
+ Object *ob;
+ Material *ma;
+ ID *id;
+ IpoCurve *icu;
+ World *wo;
+ Lamp *la;
+ int tlay, map, event;
+ char menustr[256];
+
+ if(curarea->spacetype==SPACE_IPO) {
+ insertkey_editipo();
+ }
+ else if(curarea->spacetype==SPACE_BUTS) {
+
+ if(G.buts->mainb==BUTS_MAT) {
+ id= G.buts->lockpoin;
+ ma= G.buts->lockpoin;
+ if(id) {
+ event= pupmenu("Insert Key %t|RGB%x0|Alpha%x1|HaSize%x2|Mode %x3|All Color%x10|Ofs%x12|Size%x13|All Mapping%x11");
+ if(event== -1) return;
+
+ map= texchannel_to_adrcode(ma->texact);
+
+ if(event==0 || event==10) {
+ insertkey(id, MA_COL_R);
+ insertkey(id, MA_COL_G);
+ insertkey(id, MA_COL_B);
+ }
+ if(event==1 || event==10) {
+ insertkey(id, MA_ALPHA);
+ }
+ if(event==2 || event==10) {
+ insertkey(id, MA_HASIZE);
+ }
+ if(event==3 || event==10) {
+ insertkey(id, MA_MODE);
+ }
+ if(event==10) {
+ insertkey(id, MA_SPEC_R);
+ insertkey(id, MA_SPEC_G);
+ insertkey(id, MA_SPEC_B);
+ insertkey(id, MA_REF);
+ insertkey(id, MA_EMIT);
+ insertkey(id, MA_AMB);
+ insertkey(id, MA_SPEC);
+ insertkey(id, MA_HARD);
+ insertkey(id, MA_MODE);
+ }
+ if(event==12 || event==11) {
+ insertkey(id, map+MAP_OFS_X);
+ insertkey(id, map+MAP_OFS_Y);
+ insertkey(id, map+MAP_OFS_Z);
+ }
+ if(event==13 || event==11) {
+ insertkey(id, map+MAP_SIZE_X);
+ insertkey(id, map+MAP_SIZE_Y);
+ insertkey(id, map+MAP_SIZE_Z);
+ }
+ if(event==11) {
+ insertkey(id, map+MAP_R);
+ insertkey(id, map+MAP_G);
+ insertkey(id, map+MAP_B);
+ insertkey(id, map+MAP_DVAR);
+ insertkey(id, map+MAP_COLF);
+ insertkey(id, map+MAP_NORF);
+ insertkey(id, map+MAP_VARF);
+ }
+ }
+ }
+ else if(G.buts->mainb==BUTS_WORLD) {
+ id= G.buts->lockpoin;
+ wo= G.buts->lockpoin;
+ if(id) {
+ event= pupmenu("Insert Key %t|ZenRGB%x0|HorRGB%x1|Mist%x2|stars %x3|Ofs%x12|Size%x13");
+ if(event== -1) return;
+
+ map= texchannel_to_adrcode(wo->texact);
+
+ if(event==0) {
+ insertkey(id, WO_ZEN_R);
+ insertkey(id, WO_ZEN_G);
+ insertkey(id, WO_ZEN_B);
+ }
+ if(event==1) {
+ insertkey(id, WO_HOR_R);
+ insertkey(id, WO_HOR_G);
+ insertkey(id, WO_HOR_B);
+ }
+ if(event==2) {
+ insertkey(id, WO_MISI);
+ insertkey(id, WO_MISTDI);
+ insertkey(id, WO_MISTSTA);
+ insertkey(id, WO_MISTHI);
+ }
+ if(event==3) {
+ insertkey(id, WO_STAR_R);
+ insertkey(id, WO_STAR_G);
+ insertkey(id, WO_STAR_B);
+ insertkey(id, WO_STARDIST);
+ insertkey(id, WO_STARSIZE);
+ }
+ if(event==12) {
+ insertkey(id, map+MAP_OFS_X);
+ insertkey(id, map+MAP_OFS_Y);
+ insertkey(id, map+MAP_OFS_Z);
+ }
+ if(event==13) {
+ insertkey(id, map+MAP_SIZE_X);
+ insertkey(id, map+MAP_SIZE_Y);
+ insertkey(id, map+MAP_SIZE_Z);
+ }
+ }
+ }
+ else if(G.buts->mainb==BUTS_LAMP) {
+ id= G.buts->lockpoin;
+ la= G.buts->lockpoin;
+ if(id) {
+ event= pupmenu("Insert Key %t|RGB%x0|Energy%x1|Spotsi%x2|Ofs%x12|Size%x13");
+ if(event== -1) return;
+
+ map= texchannel_to_adrcode(la->texact);
+
+ if(event==0) {
+ insertkey(id, LA_COL_R);
+ insertkey(id, LA_COL_G);
+ insertkey(id, LA_COL_B);
+ }
+ if(event==1) {
+ insertkey(id, LA_ENERGY);
+ }
+ if(event==2) {
+ insertkey(id, LA_SPOTSI);
+ }
+ if(event==12) {
+ insertkey(id, map+MAP_OFS_X);
+ insertkey(id, map+MAP_OFS_Y);
+ insertkey(id, map+MAP_OFS_Z);
+ }
+ if(event==13) {
+ insertkey(id, map+MAP_SIZE_X);
+ insertkey(id, map+MAP_SIZE_Y);
+ insertkey(id, map+MAP_SIZE_Z);
+ }
+
+ }
+ }
+ else if(G.buts->mainb==BUTS_EDIT) {
+ ob= OBACT;
+ if(ob && ob->type==OB_CAMERA) {
+ id= G.buts->lockpoin;
+ if(id) {
+ event= pupmenu("Insert Key %t|Lens%x0|Clipping%x1");
+ if(event== -1) return;
+
+ if(event==0) {
+ insertkey(id, CAM_LENS);
+ }
+ if(event==1) {
+ insertkey(id, CAM_STA);
+ insertkey(id, CAM_END);
+ }
+ }
+ }
+ }
+ else if(G.buts->mainb==BUTS_SOUND) {
+ if(G.ssound) {
+ id= G.buts->lockpoin;
+ if(id) {
+ event= pupmenu("Insert Key %t|Volume%x0|Pitch%x1|Panning%x2|Attennuation%x3");
+ if(event== -1) return;
+
+ if(event==0) {
+ insertkey(id, SND_VOLUME);
+ }
+ if(event==1) {
+ insertkey(id, SND_PITCH);
+ }
+ if(event==2) {
+ insertkey(id, SND_PANNING);
+ }
+ if(event==3) {
+ insertkey(id, SND_ATTEN);
+ }
+ }
+ }
+ }
+
+ allqueue(REDRAWACTION, 0);
+ allqueue(REDRAWNLA, 0);
+ allqueue(REDRAWIPO, 0);
+ allspace(REMAKEIPO, 0);
+
+ }
+ else if(curarea->spacetype==SPACE_VIEW3D) {
+
+
+ base= FIRSTBASE;
+ while(base) {
+ if TESTBASELIB(base) break;
+ base= base->next;
+ }
+ if(base==0) return;
+
+ if (G.obpose)
+ strcpy(menustr, "Insert Key%t|Loc%x0|Rot%x1|Size%x2|LocRot%x3|LocRotSize%x4|Avail%x9");
+ else
+ strcpy(menustr, "Insert Key%t|Loc%x0|Rot%x1|Size%x2|LocRot%x3|LocRotSize%x4|Layer%x5|Avail%x9");
+
+
+ if( (ob = OBACT)) {
+ if(ob->type==OB_MESH) strcat(menustr, "| %x6|Mesh%x7");
+ else if(ob->type==OB_LATTICE) strcat(menustr, "| %x6|Lattice%x7");
+ else if(ob->type==OB_CURVE) strcat(menustr, "| %x6|Curve%x7");
+ else if(ob->type==OB_SURF) strcat(menustr, "| %x6|Surface%x7");
+ else if(ob->type==OB_IKA) strcat(menustr, "| %x6|Effector%x8");
+ if(ob->flag & OB_FROMGROUP) strcat(menustr, "| %x6|Entire Group%x10");
+ }
+
+ event= pupmenu(menustr);
+ if(event== -1) return;
+
+ if(event==7) {
+ if(ob->type==OB_MESH) insert_meshkey(ob->data);
+ else if ELEM(ob->type, OB_CURVE, OB_SURF) insert_curvekey(ob->data);
+ else if(ob->type==OB_LATTICE) insert_lattkey(ob->data);
+
+ allqueue(REDRAWIPO, 0);
+ allqueue(REDRAWACTION, 0);
+ allqueue(REDRAWNLA, 0);
+ allqueue(REDRAWBUTSANIM, 0);
+ return;
+ }
+
+ if(event==10) {
+ Group *group= find_group(ob);
+ if(group) {
+ add_group_key(group);
+ allqueue(REDRAWBUTSANIM, 0);
+ }
+ }
+
+ base= FIRSTBASE;
+ if (G.obpose){
+ bAction *act;
+ bPose *pose;
+ bPoseChannel *chan;
+ bActionChannel *achan;
+
+ ob = G.obpose;
+
+ /* Get action & pose from object */
+ act=ob->action;
+ pose=ob->pose;
+
+ collect_pose_garbage(ob);
+
+ if (!act){
+ act=G.obpose->action=add_empty_action();
+ allqueue(REDRAWACTION, 0);
+ allqueue(REDRAWNLA, 0);
+ }
+ if (!pose){
+ error ("No pose!"); /* Should never happen */
+ }
+
+ if (act->id.lib)
+ {
+ error ("Can't key libactions");
+ return;
+ }
+ filter_pose_keys ();
+ for (chan=pose->chanbase.first; chan; chan=chan->next)
+ {
+ if (chan->flag & POSE_KEY){
+ // set_action_key(act, chan);
+ if(event==0 || event==3 ||event==4) {
+ set_action_key(act, chan, AC_LOC_X, 1);
+ set_action_key(act, chan, AC_LOC_Y, 1);
+ set_action_key(act, chan, AC_LOC_Z, 1);
+ }
+ if(event==1 || event==3 ||event==4) {
+ set_action_key(act, chan, AC_QUAT_X, 1);
+ set_action_key(act, chan, AC_QUAT_Y, 1);
+ set_action_key(act, chan, AC_QUAT_Z, 1);
+ set_action_key(act, chan, AC_QUAT_W, 1);
+ }
+ if(event==2 || event==4) {
+ set_action_key(act, chan, AC_SIZE_X, 1);
+ set_action_key(act, chan, AC_SIZE_Y, 1);
+ set_action_key(act, chan, AC_SIZE_Z, 1);
+ }
+ if (event==9){
+ for (achan = act->chanbase.first; achan; achan=achan->next){
+ if (achan->ipo && !strcmp (achan->name, chan->name)){
+ for (icu = achan->ipo->curve.first; icu; icu=icu->next){
+ set_action_key(act, chan, icu->adrcode, 0);
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ remake_action_ipos(act);
+ }
+ allqueue(REDRAWIPO, 0);
+ allqueue(REDRAWACTION, 0);
+ allqueue(REDRAWNLA, 0);
+
+ }
+ else
+ {
+ while(base) {
+ if TESTBASELIB(base) {
+ id= (ID *)(base->object);
+
+ /* alle curves in ipo deselect */
+ if(base->object->ipo) {
+ icu= base->object->ipo->curve.first;
+ while(icu) {
+ icu->flag &= ~IPO_SELECT;
+ if(event==9) insertkey(id, icu->adrcode);
+ icu= icu->next;
+ }
+ }
+
+ if(event==0 || event==3 ||event==4) {
+ insertkey(id, OB_LOC_X);
+ insertkey(id, OB_LOC_Y);
+ insertkey(id, OB_LOC_Z);
+ }
+ if(event==1 || event==3 ||event==4) {
+ insertkey(id, OB_ROT_X);
+ insertkey(id, OB_ROT_Y);
+ insertkey(id, OB_ROT_Z);
+ }
+ if(event==2 || event==4) {
+ insertkey(id, OB_SIZE_X);
+ insertkey(id, OB_SIZE_Y);
+ insertkey(id, OB_SIZE_Z);
+ }
+ if(event==5) {
+ /* localview weghalen */
+ tlay= base->object->lay;
+ base->object->lay &= 0xFFFFFF;
+ insertkey(id, OB_LAY);
+ base->object->lay= tlay;
+ }
+ if(event==8) {
+ /* deze patch moet omdat duplicators de positie van effg veranderen */
+ Ika *ika= ob->data;
+ VecMat4MulVecfl(ika->effg, ob->obmat, ika->effn);
+
+ insertkey(id, OB_EFF_X);
+ insertkey(id, OB_EFF_Y);
+ insertkey(id, OB_EFF_Z);
+ }
+ }
+ base= base->next;
+ }
+ }
+ allspace(REMAKEIPO, 0);
+ allqueue(REDRAWIPO, 0);
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWACTION, 0);
+ allqueue(REDRAWNLA, 0);
+ }
+
+}
+
+
+/* **************************************************** */
+
+/* IPOKEY:
+ *
+ * er zijn drie manieren om hiermee om te gaan:
+ * 1. hieronder: voor tekenen en editen in Ipo window
+ * 2. voor tekenen keys in View3D (zie ipo.c en drawobject.c)
+ * 3. voor editen keys in View3D (hieronder en editobject.c)
+ *
+ */
+
+
+void free_ipokey(ListBase *lb)
+{
+ IpoKey *ik;
+
+ ik= lb->first;
+ while(ik) {
+ if(ik->data) MEM_freeN(ik->data);
+ ik= ik->next;
+ }
+ BLI_freelistN(lb);
+}
+
+
+void add_to_ipokey(ListBase *lb, BezTriple *bezt, int nr, int len)
+{
+ IpoKey *ik, *ikn;
+
+ ik= lb->first;
+ while(ik) {
+
+ if( ik->val==bezt->vec[1][0] ) {
+ if(ik->data[nr]==0) { /* dubbele punten! */
+ ik->data[nr]= bezt;
+ if(bezt->f2 & 1) ik->flag= 1;
+ return;
+ }
+ }
+ else if(ik->val > bezt->vec[1][0]) break;
+
+ ik= ik->next;
+ }
+
+ ikn= MEM_callocN(sizeof(IpoKey), "add_to_ipokey");
+ if(ik) BLI_insertlinkbefore(lb, ik, ikn);
+ else BLI_addtail(lb, ikn);
+
+ ikn->data= MEM_callocN(sizeof(float *)*len, "add_to_ipokey");
+ ikn->data[nr]= bezt;
+ ikn->val= bezt->vec[1][0];
+
+ if(bezt->f2 & 1) ikn->flag= 1;
+}
+
+void make_ipokey(void)
+{
+ EditIpo *ei;
+ IpoKey *ik;
+ ListBase *lb;
+ BezTriple *bezt;
+ int a, b, sel, desel, totvert;
+
+ lb= &G.sipo->ipokey;
+ free_ipokey(lb);
+
+ ei= G.sipo->editipo;
+ if(ei==0) return;
+ for(a=0; a<G.sipo->totipo; a++, ei++) {
+ if ISPOIN(ei, flag & IPO_VISIBLE, icu) {
+ bezt= ei->icu->bezt;
+ totvert= ei->icu->totvert;
+
+ for(b=0; b<totvert; b++, bezt++) {
+ add_to_ipokey(lb, bezt, a, G.sipo->totipo);
+ }
+
+ ei->flag &= ~IPO_SELECT;
+ ei->flag &= ~IPO_EDIT;
+ ei->icu->flag= ei->flag;
+ }
+ }
+
+ /* selectflags testen */
+ ik= lb->first;
+ while(ik) {
+ sel= desel= 0;
+ for(a=0; a<G.sipo->totipo; a++) {
+ if(ik->data[a]) {
+ bezt= ik->data[a];
+ if(bezt->f2 & 1) sel++;
+ else desel++;
+ }
+ }
+ if(sel && desel) sel= 0;
+ for(a=0; a<G.sipo->totipo; a++) {
+ if(ik->data[a]) {
+ bezt= ik->data[a];
+ if(sel) {
+ bezt->f1 |= 1;
+ bezt->f2 |= 1;
+ bezt->f3 |= 1;
+ }
+ else {
+ bezt->f1 &= ~1;
+ bezt->f2 &= ~1;
+ bezt->f3 &= ~1;
+ }
+ }
+ }
+ if(sel) ik->flag = 1;
+ else ik->flag= 0;
+
+ ik= ik->next;
+ }
+ get_status_editipo();
+}
+
+void make_ipokey_transform(Object *ob, ListBase *lb, int sel)
+{
+ IpoCurve *icu;
+ BezTriple *bezt;
+ int a, adrcode = 0, ok, dloc=0, drot=0, dsize=0;
+
+ if(ob->ipo==0) return;
+ if(ob->ipo->showkey==0) return;
+
+ /* testen: zijn er delta curves? */
+ icu= ob->ipo->curve.first;
+ while(icu) {
+ if(icu->flag & IPO_VISIBLE) {
+ switch(icu->adrcode) {
+ case OB_DLOC_X:
+ case OB_DLOC_Y:
+ case OB_DLOC_Z:
+ dloc= 1;
+ break;
+ case OB_DROT_X:
+ case OB_DROT_Y:
+ case OB_DROT_Z:
+ drot= 1;
+ break;
+ case OB_DSIZE_X:
+ case OB_DSIZE_Y:
+ case OB_DSIZE_Z:
+ dsize= 1;
+ break;
+ }
+ }
+ icu= icu->next;
+ }
+
+ icu= ob->ipo->curve.first;
+ while(icu) {
+ if(icu->flag & IPO_VISIBLE) {
+ ok= 0;
+
+ switch(icu->adrcode) {
+ case OB_DLOC_X:
+ case OB_DLOC_Y:
+ case OB_DLOC_Z:
+ case OB_DROT_X:
+ case OB_DROT_Y:
+ case OB_DROT_Z:
+ case OB_DSIZE_X:
+ case OB_DSIZE_Y:
+ case OB_DSIZE_Z:
+ ok= 1;
+ break;
+
+ case OB_LOC_X:
+ case OB_LOC_Y:
+ case OB_LOC_Z:
+ if(dloc==0) ok= 1;
+ break;
+ case OB_ROT_X:
+ case OB_ROT_Y:
+ case OB_ROT_Z:
+ if(drot==0) ok= 1;
+ break;
+ case OB_SIZE_X:
+ case OB_SIZE_Y:
+ case OB_SIZE_Z:
+ if(dsize==0) ok= 1;
+ break;
+ }
+ if(ok) {
+ for(a=0; a<OB_TOTIPO; a++) {
+ if(icu->adrcode==ob_ar[a]) {
+ adrcode= a;
+ break;
+ }
+ }
+
+ bezt= icu->bezt;
+ a= icu->totvert;
+ while(a--) {
+ if(sel==0 || (bezt->f2 & 1)) {
+ add_to_ipokey(lb, bezt, adrcode, OB_TOTIPO);
+ }
+ bezt++;
+ }
+ }
+ }
+ icu= icu->next;
+ }
+}
+
+void update_ipokey_val() /* na verplaatsen vertices */
+{
+ IpoKey *ik;
+ int a;
+
+ ik= G.sipo->ipokey.first;
+ while(ik) {
+ for(a=0; a<G.sipo->totipo; a++) {
+ if(ik->data[a]) {
+ ik->val= ik->data[a]->vec[1][0];
+ break;
+ }
+ }
+ ik= ik->next;
+ }
+}
+
+void set_tob_old(float *old, float *poin)
+{
+ old[0]= *(poin);
+ old[3]= *(poin-3);
+ old[6]= *(poin+3);
+}
+
+void set_ipo_pointers_transob(IpoKey *ik, TransOb *tob)
+{
+ BezTriple *bezt;
+ int a, delta= 0;
+
+ tob->locx= tob->locy= tob->locz= 0;
+ tob->rotx= tob->roty= tob->rotz= 0;
+ tob->sizex= tob->sizey= tob->sizez= 0;
+
+ for(a=0; a<OB_TOTIPO; a++) {
+ if(ik->data[a]) {
+ bezt= ik->data[a];
+
+ switch( ob_ar[a] ) {
+ case OB_LOC_X:
+ case OB_DLOC_X:
+ tob->locx= &(bezt->vec[1][1]); break;
+ case OB_LOC_Y:
+ case OB_DLOC_Y:
+ tob->locy= &(bezt->vec[1][1]); break;
+ case OB_LOC_Z:
+ case OB_DLOC_Z:
+ tob->locz= &(bezt->vec[1][1]); break;
+
+ case OB_DROT_X:
+ delta= 1;
+ case OB_ROT_X:
+ tob->rotx= &(bezt->vec[1][1]); break;
+ case OB_DROT_Y:
+ delta= 1;
+ case OB_ROT_Y:
+ tob->roty= &(bezt->vec[1][1]); break;
+ case OB_DROT_Z:
+ delta= 1;
+ case OB_ROT_Z:
+ tob->rotz= &(bezt->vec[1][1]); break;
+
+ case OB_SIZE_X:
+ case OB_DSIZE_X:
+ tob->sizex= &(bezt->vec[1][1]); break;
+ case OB_SIZE_Y:
+ case OB_DSIZE_Y:
+ tob->sizey= &(bezt->vec[1][1]); break;
+ case OB_SIZE_Z:
+ case OB_DSIZE_Z:
+ tob->sizez= &(bezt->vec[1][1]); break;
+ }
+ }
+ }
+
+ /* oldvals voor o.a. undo */
+ if(tob->locx) set_tob_old(tob->oldloc, tob->locx);
+ if(tob->locy) set_tob_old(tob->oldloc+1, tob->locy);
+ if(tob->locz) set_tob_old(tob->oldloc+2, tob->locz);
+
+ /* bewaar de eerste oldrot, ivm mapping curves ('1'=10 graden) en correcte berekening */
+ if(tob->rotx) set_tob_old(tob->oldrot+3, tob->rotx);
+ if(tob->roty) set_tob_old(tob->oldrot+4, tob->roty);
+ if(tob->rotz) set_tob_old(tob->oldrot+5, tob->rotz);
+
+ /* bewaar de eerste oldsize, dit mag niet de dsize zijn! */
+ if(tob->sizex) set_tob_old(tob->oldsize+3, tob->sizex);
+ if(tob->sizey) set_tob_old(tob->oldsize+4, tob->sizey);
+ if(tob->sizez) set_tob_old(tob->oldsize+5, tob->sizez);
+
+ tob->flag= TOB_IPO;
+ if(delta) tob->flag |= TOB_IPODROT;
+}
+
+
+
+void nextkey(ListBase *elems, int dir)
+{
+ IpoKey *ik, *previk;
+ int totsel;
+
+ if(dir==1) ik= elems->last;
+ else ik= elems->first;
+ previk= 0;
+ totsel= 0;
+
+ while(ik) {
+
+ if(ik->flag) totsel++;
+
+ if(previk) {
+ if(G.qual & LR_SHIFTKEY) {
+ if(ik->flag) previk->flag= 1;
+ }
+ else previk->flag= ik->flag;
+ }
+
+ previk= ik;
+ if(dir==1) ik= ik->prev;
+ else ik= ik->next;
+
+ if(G.qual & LR_SHIFTKEY);
+ else if(ik==0) previk->flag= 0;
+ }
+
+ /* als geen een key select: */
+ if(totsel==0) {
+ if(dir==1) ik= elems->first;
+ else ik= elems->last;
+
+ if(ik) ik->flag= 1;
+ }
+}
+
+static int float_to_frame (float frame)
+{
+ int to= (int) frame;
+
+ if (frame-to>0.5) to++;
+
+ return to;
+}
+
+void movekey_ipo(int dir) /* alleen extern aanroepen vanuit view3d queue */
+{
+ IpoKey *ik;
+ float toframe = 0.0;
+ int a;
+
+ if(G.sipo->showkey==0) return;
+
+ ik= G.sipo->ipokey.first;
+ if (dir==-1) {
+ while (ik && float_to_frame(ik->val)<CFRA) {
+ toframe= ik->val;
+ ik= ik->next;
+ }
+ } else {
+ while (ik && float_to_frame(ik->val)<=CFRA) {
+ ik= ik->next;
+ }
+ if (ik) toframe= ik->val;
+ }
+
+ a= float_to_frame(toframe);
+
+ if (a!=CFRA && a>0) {
+ CFRA= a;
+
+ update_for_newframe();
+ }
+
+ allqueue(REDRAWNLA, 0);
+ allqueue(REDRAWACTION, 0);
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWIPO, 0);
+ allspace(REMAKEIPO, 0);
+
+}
+
+void movekey_obipo(int dir) /* alleen extern aanroepen vanuit view3d queue */
+{
+ Base *base;
+ Object *ob;
+ ListBase elems;
+ IpoKey *ik;
+ int a;
+ float toframe= CFRA;
+
+ base= FIRSTBASE;
+ while(base) {
+ if TESTBASE(base) {
+ ob= base->object;
+ if(ob->ipo && ob->ipo->showkey) {
+ elems.first= elems.last= 0;
+ make_ipokey_transform(ob, &elems, 0);
+
+ if(elems.first) {
+ ik= elems.first;
+ if (dir==-1) {
+ while (ik && float_to_frame(ik->val)<CFRA) {
+ toframe= ik->val;
+ ik= ik->next;
+ }
+ } else {
+ while (ik && float_to_frame(ik->val)<=CFRA) {
+ ik= ik->next;
+ }
+ if (ik) toframe= ik->val;
+ }
+
+ free_ipokey(&elems);
+ }
+ }
+ }
+
+ base= base->next;
+ }
+
+ a= float_to_frame(toframe);
+
+ if (a!=CFRA && a>0) {
+ CFRA= a;
+
+ update_for_newframe();
+ }
+
+ allqueue(REDRAWNLA, 0);
+ allqueue(REDRAWACTION, 0);
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWIPO, 0);
+ allspace(REMAKEIPO, 0);
+
+}
+
+void nextkey_ipo(int dir) /* aanroepen vanuit ipo queue */
+{
+ IpoKey *ik;
+ int a;
+
+ if(G.sipo->showkey==0) return;
+
+ nextkey(&G.sipo->ipokey, dir);
+
+ /* kopieeren naar beziers */
+ ik= G.sipo->ipokey.first;
+ while(ik) {
+ for(a=0; a<G.sipo->totipo; a++) {
+ if(ik->data[a]) ik->data[a]->f1= ik->data[a]->f2= ik->data[a]->f3= ik->flag;
+ }
+ ik= ik->next;
+ }
+
+ allqueue(REDRAWNLA, 0);
+ allqueue(REDRAWACTION, 0);
+ allqueue(REDRAWIPO, 0);
+ if(G.sipo->blocktype == ID_OB) allqueue(REDRAWVIEW3D, 0);
+}
+
+void nextkey_obipo(int dir) /* alleen extern aanroepen vanuit view3d queue */
+{
+ Base *base;
+ Object *ob;
+ ListBase elems;
+ IpoKey *ik;
+ int a;
+
+ /* problem: this doesnt work when you mix dLoc keys with Loc keys */
+
+ base= FIRSTBASE;
+ while(base) {
+ if TESTBASE(base) {
+ ob= base->object;
+ if( (ob->ipoflag & OB_DRAWKEY) && ob->ipo && ob->ipo->showkey) {
+ elems.first= elems.last= 0;
+ make_ipokey_transform(ob, &elems, 0);
+
+ if(elems.first) {
+
+ nextkey(&elems, dir);
+
+ /* kopieeren naar beziers */
+ ik= elems.first;
+ while(ik) {
+ for(a=0; a<OB_TOTIPO; a++) {
+ if(ik->data[a]) ik->data[a]->f1= ik->data[a]->f2= ik->data[a]->f3= ik->flag;
+ }
+ ik= ik->next;
+ }
+
+ free_ipokey(&elems);
+ }
+ }
+ }
+
+ base= base->next;
+ }
+ allqueue(REDRAWNLA, 0);
+ allqueue(REDRAWACTION, 0);
+ allqueue(REDRAWVIEW3D, 0);
+ allspace(REMAKEIPO, 0);
+ allqueue(REDRAWIPO, 0);
+}
+
+
+/* **************************************************** */
+
+
+void remake_ipo_transverts(TransVert *transmain, float *dvec, int tot)
+{
+ EditIpo *ei;
+ TransVert *tv;
+ BezTriple *bezt;
+ int a, b;
+
+ ei= G.sipo->editipo;
+ for(a=0; a<G.sipo->totipo; a++, ei++) {
+
+ if ISPOIN(ei, flag & IPO_VISIBLE, icu) {
+
+ if(ei->icu->bezt) {
+ sort_time_ipocurve(ei->icu);
+ }
+ }
+ }
+
+ ei= G.sipo->editipo;
+ tv= transmain;
+ for(a=0; a<G.sipo->totipo; a++, ei++) {
+
+ if ISPOIN(ei, flag & IPO_VISIBLE, icu) {
+ if( (ei->flag & IPO_EDIT) || G.sipo->showkey) {
+ if(ei->icu->bezt) {
+ bezt= ei->icu->bezt;
+ b= ei->icu->totvert;
+ while(b--) {
+ if(ei->icu->ipo==IPO_BEZ) {
+ if(bezt->f1 & 1) {
+ tv->loc= bezt->vec[0];
+ tv++;
+ }
+ if(bezt->f3 & 1) {
+ tv->loc= bezt->vec[2];
+ tv++;
+ }
+ }
+ if(bezt->f2 & 1) {
+ tv->loc= bezt->vec[1];
+ tv++;
+ }
+
+ bezt++;
+ }
+ testhandles_ipocurve(ei->icu);
+ }
+ }
+ }
+ }
+
+ if(G.sipo->showkey) make_ipokey();
+
+ if(dvec==0) return;
+
+ tv= transmain;
+ for(a=0; a<tot; a++, tv++) {
+ tv->oldloc[0]= tv->loc[0]-dvec[0];
+ tv->oldloc[1]= tv->loc[1]-dvec[1];
+ }
+}
+
+void transform_ipo(int mode)
+{
+ EditIpo *ei;
+ BezTriple *bezt;
+ TransVert *transmain = NULL, *tv;
+ float xref=1.0, yref=1.0, dx, dy, dvec[2], min[3], max[3], vec[2], div, cent[2], size[2], sizefac;
+ int tot=0, a, b, firsttime=1, afbreek=0, midtog= 0, dosort, proj = 0;
+ unsigned short event = 0;
+ short mval[2], val, xo, yo, xn, yn, xc, yc;
+ char str[32];
+
+ if(G.sipo->ipo && G.sipo->ipo->id.lib) return;
+ if(G.sipo->editipo==0) return;
+ if(mode=='r') return; /* vanuit gesture */
+
+ INIT_MINMAX(min, max);
+
+ /* welke vertices doen mee */
+ get_status_editipo();
+ if(totipo_vertsel) {
+ tot= totipo_vertsel;
+ tv=transmain= MEM_callocN(tot*sizeof(TransVert), "transmain");
+
+ ei= G.sipo->editipo;
+ for(a=0; a<G.sipo->totipo; a++, ei++) {
+
+ if ISPOIN(ei, flag & IPO_VISIBLE, icu) {
+ if( (ei->flag & IPO_EDIT) || G.sipo->showkey) {
+
+
+ if(ei->icu->bezt) {
+ bezt= ei->icu->bezt;
+ b= ei->icu->totvert;
+ while(b--) {
+ if(ei->icu->ipo==IPO_BEZ) {
+ if(bezt->f1 & 1) {
+ tv->loc= bezt->vec[0];
+ VECCOPY(tv->oldloc, tv->loc);
+ if(ei->disptype==IPO_DISPBITS) tv->flag= 1;
+
+ /* let op: we nemen middelste vertex */
+ DO_MINMAX2(bezt->vec[1], min, max);
+
+ tv++;
+ }
+ if(bezt->f3 & 1) {
+ tv->loc= bezt->vec[2];
+ VECCOPY(tv->oldloc, tv->loc);
+ if(ei->disptype==IPO_DISPBITS) tv->flag= 1;
+
+ /* let op: we nemen middelste vertex */
+ DO_MINMAX2(bezt->vec[1], min, max);
+
+ tv++;
+ }
+ }
+ if(bezt->f2 & 1) {
+ tv->loc= bezt->vec[1];
+ VECCOPY(tv->oldloc, tv->loc);
+ if(ei->disptype==IPO_DISPBITS) tv->flag= 1;
+ DO_MINMAX2(bezt->vec[1], min, max);
+ tv++;
+ }
+ bezt++;
+ }
+ }
+ }
+ }
+ }
+
+ }
+ else if(totipo_edit==0 && totipo_sel!=0) {
+
+ ei= G.sipo->editipo;
+ for(a=0; a<G.sipo->totipo; a++, ei++) {
+ if ISPOIN3(ei, flag & IPO_VISIBLE, flag & IPO_SELECT, icu) {
+ if(ei->icu->bezt && ei->icu->ipo==IPO_BEZ) tot+= 3*ei->icu->totvert;
+ else tot+= ei->icu->totvert;
+ }
+ }
+ if(tot==0) return;
+
+ tv=transmain= MEM_callocN(tot*sizeof(TransVert), "transmain");
+
+ ei= G.sipo->editipo;
+ for(a=0; a<G.sipo->totipo; a++, ei++) {
+ if ISPOIN3(ei, flag & IPO_VISIBLE, flag & IPO_SELECT, icu) {
+ if(ei->icu->bezt) {
+
+ bezt= ei->icu->bezt;
+ b= ei->icu->totvert;
+ while(b--) {
+ if(ei->icu->ipo==IPO_BEZ) {
+ tv->loc= bezt->vec[0];
+ VECCOPY(tv->oldloc, tv->loc);
+ if(ei->disptype==IPO_DISPBITS) tv->flag= 1;
+ tv++;
+
+ tv->loc= bezt->vec[2];
+ VECCOPY(tv->oldloc, tv->loc);
+ if(ei->disptype==IPO_DISPBITS) tv->flag= 1;
+ tv++;
+ }
+ tv->loc= bezt->vec[1];
+ VECCOPY(tv->oldloc, tv->loc);
+ if(ei->disptype==IPO_DISPBITS) tv->flag= 1;
+
+ DO_MINMAX2(bezt->vec[1], min, max);
+
+ tv++;
+
+ bezt++;
+ }
+ }
+ }
+ }
+
+ }
+
+ if(tot==0) {
+ if(totipo_edit==0) move_keys();
+ return;
+ }
+
+ cent[0]= (float)((min[0]+max[0])/2.0);
+ cent[1]= (float)((min[1]+max[1])/2.0);
+
+ if(G.sipo->showkey) {
+ midtog= 1;
+ proj= 1;
+ }
+
+ ipoco_to_areaco(G.v2d, cent, mval);
+ xc= mval[0];
+ yc= mval[1];
+
+ getmouseco_areawin(mval);
+ xo= xn= mval[0];
+ yo= yn= mval[1];
+ dvec[0]= dvec[1]= 0.0;
+
+ sizefac= (float)(sqrt( (float)((yc-yn)*(yc-yn)+(xn-xc)*(xn-xc)) ));
+ if(sizefac<2.0) sizefac= 2.0;
+
+ while(afbreek==0) {
+ getmouseco_areawin(mval);
+ if(mval[0]!=xo || mval[1]!=yo || firsttime) {
+
+ if(mode=='g') {
+
+ dx= (float)(mval[0]- xo);
+ dy= (float)(mval[1]- yo);
+
+ div= (float)(G.v2d->mask.xmax-G.v2d->mask.xmin);
+ dvec[0]+= (G.v2d->cur.xmax-G.v2d->cur.xmin)*(dx)/div;
+
+ div= (float)(G.v2d->mask.ymax-G.v2d->mask.ymin);
+ dvec[1]+= (G.v2d->cur.ymax-G.v2d->cur.ymin)*(dy)/div;
+
+ if(midtog) dvec[proj]= 0.0;
+
+ /* vec wordt verderop nog gebruikt: remake_ipo_transverts */
+ vec[0]= dvec[0];
+ vec[1]= dvec[1];
+
+ apply_keyb_grid(vec, 0.0, (float)1.0, (float)0.1, U.flag & AUTOGRABGRID);
+ apply_keyb_grid(vec+1, 0.0, (float)1.0, (float)0.1, 0);
+
+ tv= transmain;
+ for(a=0; a<tot; a++, tv++) {
+ tv->loc[0]= tv->oldloc[0]+vec[0];
+
+ if(tv->flag==0) tv->loc[1]= tv->oldloc[1]+vec[1];
+ }
+
+ sprintf(str, "X: %.3f Y: %.3f ", vec[0], vec[1]);
+ headerprint(str);
+ }
+ else if(mode=='s') {
+
+ size[0]=size[1]=(float)( (sqrt( (float)((yc-mval[1])*(yc-mval[1])+(mval[0]-xc)*(mval[0]-xc)) ))/sizefac);
+
+ if(midtog) size[proj]= 1.0;
+ size[0]*= xref;
+ size[1]*= yref;
+
+ apply_keyb_grid(size, 0.0, (float)0.2, (float)0.1, U.flag & AUTOSIZEGRID);
+ apply_keyb_grid(size+1, 0.0, (float)0.2, (float)0.1, U.flag & AUTOSIZEGRID);
+
+ tv= transmain;
+
+ for(a=0; a<tot; a++, tv++) {
+ tv->loc[0]= size[0]*(tv->oldloc[0]-cent[0])+ cent[0];
+ if(tv->flag==0) tv->loc[1]= size[1]*(tv->oldloc[1]-cent[1])+ cent[1];
+ }
+
+ sprintf(str, "sizeX: %.3f sizeY: %.3f ", size[0], size[1]);
+ headerprint(str);
+
+ }
+
+ xo= mval[0];
+ yo= mval[1];
+
+ dosort= 0;
+ ei= G.sipo->editipo;
+ for(a=0; a<G.sipo->totipo; a++, ei++) {
+ if ISPOIN(ei, flag & IPO_VISIBLE, icu) {
+
+ /* let op: als de tijd verkeerd is: niet de handles corrigeren */
+ if (test_time_ipocurve(ei->icu) ) dosort++;
+ else testhandles_ipocurve(ei->icu);
+ }
+ }
+
+ if(dosort) {
+ if(mode=='g') remake_ipo_transverts(transmain, vec, tot);
+ else remake_ipo_transverts(transmain, 0, tot);
+ }
+ if(G.sipo->showkey) update_ipokey_val();
+
+ calc_ipo(G.sipo->ipo, (float)CFRA);
+
+ /* update realtime */
+ if(G.sipo->lock) {
+ if(G.sipo->blocktype==ID_MA) {
+ force_draw_plus(SPACE_BUTS);
+ }
+ else if(G.sipo->blocktype==ID_KE) {
+ do_ob_key(OBACT);
+ makeDispList(OBACT);
+ force_draw_plus(SPACE_VIEW3D);
+ }
+ else if(G.sipo->blocktype==ID_AC) {
+ do_all_actions();
+ force_draw_all();
+ }
+ else if(G.sipo->blocktype==ID_OB) {
+ Base *base= FIRSTBASE;
+
+ while(base) {
+ if(base->object->ipo==G.sipo->ipo) do_ob_ipo(base->object);
+ base= base->next;
+ }
+ force_draw_plus(SPACE_VIEW3D);
+ }
+ else force_draw();
+ }
+ else {
+ force_draw();
+ }
+ firsttime= 0;
+ }
+ else BIF_wait_for_statechange();
+
+ while(qtest()) {
+ event= extern_qread(&val);
+ if(val) {
+ switch(event) {
+ case ESCKEY:
+ case LEFTMOUSE:
+ case RIGHTMOUSE:
+ case SPACEKEY:
+ case RETKEY:
+ afbreek= 1;
+ break;
+ case MIDDLEMOUSE:
+ if(G.sipo->showkey==0) {
+ midtog= ~midtog;
+ if(midtog) {
+ if( abs(mval[0]-xn) > abs(mval[1]-yn)) proj= 1;
+ else proj= 0;
+ firsttime= 1;
+ }
+ }
+ break;
+ case XKEY:
+ case YKEY:
+ if(event==XKEY) xref= -xref;
+ else if(G.sipo->showkey==0) yref= -yref;
+ firsttime= 1;
+ break;
+ case LEFTCTRLKEY:
+ case RIGHTCTRLKEY:
+ firsttime= 1;
+ break;
+ default:
+ if(mode=='g') {
+ if(G.qual & LR_CTRLKEY) {
+ if(event==LEFTARROWKEY) {dvec[0]-= 1.0; firsttime= 1;}
+ else if(event==RIGHTARROWKEY) {dvec[0]+= 1.0; firsttime= 1;}
+ else if(event==UPARROWKEY) {dvec[1]+= 1.0; firsttime= 1;}
+ else if(event==DOWNARROWKEY) {dvec[1]-= 1.0; firsttime= 1;}
+ }
+ else arrows_move_cursor(event);
+ }
+ else arrows_move_cursor(event);
+ }
+ }
+ if(afbreek) break;
+ }
+ }
+
+ if(event==ESCKEY || event==RIGHTMOUSE) {
+ tv= transmain;
+ for(a=0; a<tot; a++, tv++) {
+ tv->loc[0]= tv->oldloc[0];
+ tv->loc[1]= tv->oldloc[1];
+ }
+
+ dosort= 0;
+ ei= G.sipo->editipo;
+ for(a=0; a<G.sipo->totipo; a++, ei++) {
+ if ISPOIN(ei, flag & IPO_VISIBLE, icu) {
+ if( (ei->flag & IPO_EDIT) || G.sipo->showkey) {
+ if( test_time_ipocurve(ei->icu)) {
+ dosort= 1;
+ break;
+ }
+ }
+ }
+ }
+
+ if(dosort) remake_ipo_transverts(transmain, 0, tot);
+
+ ei= G.sipo->editipo;
+ for(a=0; a<G.sipo->totipo; a++, ei++) {
+ if ISPOIN(ei, flag & IPO_VISIBLE, icu) {
+ if( (ei->flag & IPO_EDIT) || G.sipo->showkey) {
+ testhandles_ipocurve(ei->icu);
+ }
+ }
+ }
+ calc_ipo(G.sipo->ipo, (float)CFRA);
+ }
+
+ editipo_changed(G.sipo, 1);
+
+ MEM_freeN(transmain);
+}
+
+void clever_numbuts_ipo()
+{
+ BezTriple *bezt=0, *bezt1;
+ Key *key;
+ KeyBlock *kb;
+ EditIpo *ei;
+ float far, delta[3], old[3];
+ int a, b, scale10=0, totbut=2;
+
+ if(G.sipo->ipo && G.sipo->ipo->id.lib) return;
+ if(G.sipo->editipo==0) return;
+
+ /* welke vertices doen mee */
+ get_status_editipo();
+
+ if(G.qual & LR_SHIFTKEY) totbut= 1;
+
+ if(G.vd==0) far= 10000.0;
+ else far= (float)(MAX2(G.vd->far, 10000.0));
+
+ if(totipo_vertsel) {
+
+ ei= G.sipo->editipo;
+ for(a=0; a<G.sipo->totipo; a++, ei++) {
+
+ if ISPOIN(ei, flag & IPO_VISIBLE, icu) {
+ if( (ei->flag & IPO_EDIT) || G.sipo->showkey) {
+
+ if(ei->icu->bezt) {
+ bezt1= ei->icu->bezt;
+ b= ei->icu->totvert;
+ while(b--) {
+ if(BEZSELECTED(bezt1)) {
+ bezt= bezt1;
+ break;
+ }
+ bezt1++;
+ }
+
+ }
+ }
+ }
+ if(bezt) break;
+ }
+
+ if(bezt==0) return;
+
+ if(bezt->f2 & 1) {
+
+ VECCOPY(old, bezt->vec[1]);
+
+ if(totipo_vis==1 && G.sipo->blocktype==ID_OB) {
+ if ELEM4(ei->icu->adrcode, OB_TIME, OB_ROT_X, OB_ROT_Y, OB_ROT_Z) scale10= 1;
+ if ELEM3(ei->icu->adrcode, OB_DROT_X, OB_DROT_Y, OB_DROT_Z) scale10= 1;
+ }
+ if(scale10) bezt->vec[1][1]*= 10.0;
+
+ add_numbut(0, NUM|FLO, "LocX:", -1000, 10000, bezt->vec[1], 0);
+ if(totbut==2) add_numbut(1, NUM|FLO, "LocY:", -far, far, bezt->vec[1]+1, 0);
+ do_clever_numbuts("Active BezierPoint", totbut, REDRAW);
+
+ if(scale10) bezt->vec[1][1]/= 10.0;
+
+ VecSubf(delta, bezt->vec[1], old);
+ VECCOPY(bezt->vec[1], old);
+
+ /* apply */
+ ei= G.sipo->editipo;
+ for(a=0; a<G.sipo->totipo; a++, ei++) {
+ if ISPOIN(ei, flag & IPO_VISIBLE, icu) {
+ if( (ei->flag & IPO_EDIT) || G.sipo->showkey) {
+ if(ei->icu->bezt) {
+ bezt= ei->icu->bezt;
+ b= ei->icu->totvert;
+ while(b--) {
+ if(bezt->f2 & 1) {
+ bezt->vec[0][0]+= delta[0];
+ bezt->vec[1][0]+= delta[0];
+ bezt->vec[2][0]+= delta[0];
+
+ bezt->vec[0][1]+= delta[1];
+ bezt->vec[1][1]+= delta[1];
+ bezt->vec[2][1]+= delta[1];
+ }
+ bezt++;
+ }
+ }
+ }
+ }
+ }
+
+ ei= G.sipo->editipo;
+ for(a=0; a<G.sipo->totipo; a++, ei++) {
+ if ISPOIN(ei, flag & IPO_VISIBLE, icu) {
+ sort_time_ipocurve(ei->icu);
+ testhandles_ipocurve(ei->icu);
+ }
+ }
+
+ }
+ else if(bezt->f1 & 1) {
+ add_numbut(0, NUM|FLO, "LocX:", -1000, 10000, bezt->vec[0], 0);
+ if(totbut==2) add_numbut(1, NUM|FLO, "LocY:", -far, far, bezt->vec[0]+1, 0);
+
+ do_clever_numbuts("Active HandlePoint", totbut, REDRAW);
+ }
+ else if(bezt->f3 & 1) {
+ add_numbut(0, NUM|FLO, "LocX:", -1000, 10000, bezt->vec[0], 0);
+ if(totbut==2) add_numbut(1, NUM|FLO, "LocY:", -far, far, bezt->vec[2]+1, 0);
+
+ do_clever_numbuts("Active HandlePoint", totbut, REDRAW);
+ }
+
+ editipo_changed(G.sipo, 1);
+ }
+ else {
+
+ if(G.sipo->blocktype==ID_KE) {
+ key= (Key *)G.sipo->from;
+
+ if(key==0) return;
+
+ kb= key->block.first;
+ while(kb) {
+ if(kb->flag & SELECT) break;
+ kb= kb->next;
+ }
+ if(kb && G.sipo->rowbut&1) {
+ add_numbut(0, NUM|FLO, "Pos:", -100, 100, &kb->pos, 0);
+ do_clever_numbuts("Active Key", 1, REDRAW);
+ sort_keys(key);
+ }
+ }
+ }
+}
+
+void filter_sampledata(float *data, int sfra, int efra)
+{
+ float *da;
+ int a;
+
+ da= data+1;
+ for(a=sfra+1; a<efra; a++, da++) {
+ da[0]=(float)( 0.25*da[-1] + 0.5*da[0] + 0.25*da[1]);
+ }
+
+}
+
+void sampledata_to_ipocurve(float *data, int sfra, int efra, IpoCurve *icu)
+{
+ BezTriple *bezt;
+ float *da;
+ int a, tot;
+
+ filter_sampledata(data, sfra, efra);
+ filter_sampledata(data, sfra, efra);
+
+ icu->ipo= IPO_LIN;
+
+ if(icu->bezt) MEM_freeN(icu->bezt);
+ icu->bezt= 0;
+
+ tot= 1; /* eerste punt */
+ da= data+1;
+ for(a=sfra+1; a<efra; a++, da++) {
+ if( IS_EQ(da[0], da[1])==0 && IS_EQ(da[1], da[2])==0 ) tot++;
+ }
+
+ icu->totvert= tot;
+ bezt= icu->bezt= MEM_callocN(tot*sizeof(BezTriple), "samplebezt");
+ bezt->vec[1][0]= (float)sfra;
+ bezt->vec[1][1]= data[0];
+ bezt++;
+ da= data+1;
+ for(a=sfra+1; a<efra; a++, da++) {
+ if( IS_EQ(da[0], da[1])==0 && IS_EQ(da[1], da[2])==0 ) {
+ bezt->vec[1][0]= (float)a;
+ bezt->vec[1][1]= da[0];
+ bezt++;
+ }
+ }
+}
+
+void ipo_record()
+{
+ /* 1 of 2 aktieve curves
+ * kopie maken (ESC)
+ *
+ * nulpunt is de huidige stand (of 0)
+ * dx (dy identiek) is de hoogteverhouding
+ * CTRL start record
+ */
+ extern double tottime;
+ EditIpo *ei, *ei1=0, *ei2=0;
+ ScrArea *sa, *oldarea;
+ Ipo *ipo;
+ void *poin;
+ double swaptime;
+ float or1, or2 = 0.0, fac, *data1, *data2;
+ int type, a, afbreek=0, firsttime=1, cfrao, cfra, sfra, efra;
+ unsigned short event = 0;
+ short anim, val, xn, yn, mvalo[2], mval[2];
+ char str[128];
+
+ if(G.sipo->from==0) return;
+ if(SFRA>=EFRA) return;
+
+ anim= pupmenu("Record Mouse %t|Still %x1|Play anim %x2");
+ if(anim < 1) return;
+ if(anim!=2) anim= 0;
+
+ ipo= get_ipo(G.sipo->from, G.sipo->blocktype, 1); /* 1= make */
+ if(G.sipo) G.sipo->ipo= ipo;
+
+ /* find the curves... */
+
+ ei= G.sipo->editipo;
+ for(a=0; a<G.sipo->totipo; a++) {
+ if(ei->flag & IPO_VISIBLE) {
+
+ if(ei1==0) ei1= ei;
+ else if(ei2==0) ei2= ei;
+ else {
+ error("Max 2 visible curves");
+ return;
+ }
+ }
+ ei++;
+ }
+
+ if(ei1==0) {
+ error("Select 1 or 2 channels");
+ return;
+ }
+
+ /* curves gereedmaken, startwaardes */
+ if(ei1->icu==0) ei1->icu= get_ipocurve(G.sipo->from, G.sipo->blocktype, ei1->adrcode, 0);
+ if(ei1->icu==0) return;
+ poin= get_ipo_poin(G.sipo->from, ei1->icu, &type);
+ if(poin) ei1->icu->curval= read_ipo_poin(poin, type);
+ or1= ei1->icu->curval;
+ ei1->icu->flag |= IPO_LOCK;
+
+ if(ei2) {
+ if(ei2->icu==0) ei2->icu= get_ipocurve(G.sipo->from, G.sipo->blocktype, ei2->adrcode, 0);
+ if(ei2->icu==0) return;
+ poin= get_ipo_poin(G.sipo->from, ei2->icu, &type);
+ if(poin) ei2->icu->curval= read_ipo_poin(poin, type);
+ or2= ei2->icu->curval;
+ ei2->icu->flag |= IPO_LOCK;
+ }
+
+ fac= G.v2d->cur.ymax - G.v2d->cur.ymin;
+ fac/= (float)curarea->winy;
+
+ /* welke area */
+ oldarea= curarea;
+ sa= G.curscreen->areabase.first;
+ while(sa) {
+ if(sa->win) {
+ if(G.sipo->blocktype==ID_MA || G.sipo->blocktype==ID_LA) {
+ if(sa->spacetype==SPACE_BUTS) break;
+ }
+ else {
+ if(sa->spacetype==SPACE_VIEW3D) break;
+ }
+ }
+ sa= sa->next;
+ }
+ if(sa) areawinset(sa->win);
+
+ /* kandie? */
+ while(get_mbut()&L_MOUSE) BIF_wait_for_statechange();
+ data1= MEM_callocN(sizeof(float)*(EFRA-SFRA+1), "data1");
+ data2= MEM_callocN(sizeof(float)*(EFRA-SFRA+1), "data2");
+
+ getmouseco_areawin(mvalo);
+ xn= mvalo[0]; yn= mvalo[1];
+ waitcursor(1);
+
+ tottime= 0.0;
+ swaptime= speed_to_swaptime(G.animspeed);
+ cfrao= CFRA;
+ cfra=efra= SFRA;
+ sfra= EFRA;
+
+ while(afbreek==0) {
+
+ getmouseco_areawin(mval);
+
+ if(mval[0]!= mvalo[0] || mval[1]!=mvalo[1] || firsttime || (G.qual & LR_CTRLKEY)) {
+ if(anim) CFRA= cfra;
+ else firsttime= 0;
+
+ set_timecursor(cfra);
+
+ /* ipo doen: eerst alles daarna de specifieke */
+ if(anim==2) {
+ do_all_ipos();
+ do_all_keys();
+ }
+
+ ei1->icu->curval= or1 + fac*(mval[0]-xn);
+ if(ei2) ei2->icu->curval= or2 + fac*(mval[1]-yn);
+
+ do_ipo_nocalc(G.sipo->ipo);
+ do_all_visible_ikas();
+
+ if(G.qual & LR_CTRLKEY) {
+ sprintf(str, "Recording... %d\n", cfra);
+ data1[ cfra-SFRA ]= ei1->icu->curval;
+ if(ei2) data2[ cfra-SFRA ]= ei2->icu->curval;
+
+ sfra= MIN2(sfra, cfra);
+ efra= MAX2(efra, cfra);
+ }
+ else sprintf(str, "Mouse Recording. Use CTRL to start. LeftMouse or Space to end");
+
+ do_ob_key(OBACT);
+
+ headerprint(str);
+
+ if(sa) scrarea_do_windraw(sa);
+
+ /* minimaal swaptime laten voorbijgaan */
+ tottime -= swaptime;
+ while (update_time()) PIL_sleep_ms(1);
+
+ screen_swapbuffers();
+
+ tottime= 0.0;
+
+ mvalo[0]= mval[0];
+ mvalo[1]= mval[1];
+
+ if(anim || (G.qual & LR_CTRLKEY)) {
+ cfra++;
+ if(cfra>EFRA) cfra= SFRA;
+ }
+ }
+
+ while(qtest()) {
+ event= extern_qread(&val);
+ if(val) {
+ switch(event) {
+ case LEFTMOUSE: case ESCKEY: case SPACEKEY: case RETKEY:
+ afbreek= 1;
+ break;
+ }
+ }
+ if(afbreek) break;
+ }
+ }
+
+ if(event!=ESCKEY) {
+ sampledata_to_ipocurve(data1+sfra-SFRA, sfra, efra, ei1->icu);
+ if(ei2) sampledata_to_ipocurve(data2+sfra-SFRA, sfra, efra, ei2->icu);
+
+ /* vervelend als dat aanstaat */
+ if(G.sipo->showkey) {
+ G.sipo->showkey= 0;
+ free_ipokey(&G.sipo->ipokey);
+ }
+ }
+ else {
+ /* undo: startwaardes */
+ poin= get_ipo_poin(G.sipo->from, ei1->icu, &type);
+ if(poin) write_ipo_poin(poin, type, or1);
+ if(ei1->icu->bezt==0) {
+ BLI_remlink( &(G.sipo->ipo->curve), ei1->icu);
+ MEM_freeN(ei1->icu);
+ ei1->icu= 0;
+ }
+ if(ei2) {
+ poin= get_ipo_poin(G.sipo->from, ei2->icu, &type);
+ if(poin) write_ipo_poin(poin, type, or2);
+ if(ei2->icu->bezt==0) {
+ BLI_remlink( &(G.sipo->ipo->curve), ei2->icu);
+ MEM_freeN(ei2->icu);
+ ei2->icu= 0;
+ }
+ }
+ }
+
+ if(ei1->icu) ei1->icu->flag &= ~IPO_LOCK;
+ if(ei2 && ei2->icu) ei2->icu->flag &= ~IPO_LOCK;
+
+ editipo_changed(G.sipo, 0);
+ do_ipo(G.sipo->ipo);
+ waitcursor(0);
+ allqueue(REDRAWVIEW3D, 0);
+ if(sa) scrarea_queue_headredraw(sa); /* headerprint */
+ scrarea_queue_redraw(oldarea);
+ CFRA= cfrao;
+
+ /* vooropig? */
+ update_for_newframe();
+
+ MEM_freeN(data1);
+ MEM_freeN(data2);
+}
+
+
+
+void remake_object_ipos(Object *ob)
+{
+ IpoCurve *icu;
+
+ if (!ob)
+ return;
+ if (!ob->ipo)
+ return;
+
+ for (icu = ob->ipo->curve.first; icu; icu=icu->next){
+ sort_time_ipocurve(icu);
+ testhandles_ipocurve(icu);
+ }
+}
+
+
+int is_ipo_key_selected(Ipo *ipo)
+{
+ int i;
+ IpoCurve *icu;
+
+ if (!ipo)
+ return 0;
+
+ for (icu=ipo->curve.first; icu; icu=icu->next){
+ for (i=0; i<icu->totvert; i++)
+ if (BEZSELECTED(&icu->bezt[i]))
+ return 1;
+ }
+
+ return 0;
+}
+
+
+void set_ipo_key_selection(Ipo *ipo, int sel)
+{
+ int i;
+ IpoCurve *icu;
+
+ if (!ipo)
+ return;
+
+ for (icu=ipo->curve.first; icu; icu=icu->next){
+ for (i=0; i<icu->totvert; i++){
+ if (sel){
+ icu->bezt[i].f1|=1;
+ icu->bezt[i].f2|=1;
+ icu->bezt[i].f3|=1;
+ }
+ else{
+ icu->bezt[i].f1&=~1;
+ icu->bezt[i].f2&=~1;
+ icu->bezt[i].f3&=~1;
+ }
+ }
+ }
+}
+
+void delete_ipo_keys(Ipo *ipo)
+{
+ IpoCurve *icu, *next;
+ int i;
+
+ if (!ipo)
+ return;
+
+ for (icu=ipo->curve.first; icu; icu=next){
+ next = icu->next;
+ for (i=0; i<icu->totvert; i++){
+ if (icu->bezt[i].f2 & 1){
+ // Delete the item
+ memcpy (&icu->bezt[i], &icu->bezt[i+1], sizeof (BezTriple)*(icu->totvert-i-1));
+ icu->totvert--;
+ i--;
+ }
+ }
+ if (!icu->totvert){
+ /* Delete the curve */
+ BLI_remlink( &(ipo->curve), icu);
+ if(icu->bezt) MEM_freeN(icu->bezt);
+ MEM_freeN(icu);
+ }
+ }
+}
+
+int fullselect_ipo_keys(Ipo *ipo)
+{
+ int i;
+ IpoCurve *icu;
+ int tvtot = 0;
+
+ if (!ipo)
+ return tvtot;
+
+ for (icu=ipo->curve.first; icu; icu=icu->next){
+ for (i=0; i<icu->totvert; i++){
+ if (icu->bezt[i].f2 & 1){
+ tvtot+=3;
+ icu->bezt[i].f1 |= 1;
+ icu->bezt[i].f3 |= 1;
+ }
+ }
+ }
+
+ return tvtot;
+}
+
+int add_trans_ipo_keys(Ipo *ipo, TransVert *tv, int tvtot)
+{
+ int i;
+ IpoCurve *icu;
+
+ if (!ipo)
+ return tvtot;
+
+ for (icu=ipo->curve.first; icu; icu=icu->next){
+ for (i=0; i<icu->totvert; i++){
+ if (icu->bezt[i].f2 & 1){
+ tv[tvtot+0].loc=icu->bezt[i].vec[0];
+ tv[tvtot+1].loc=icu->bezt[i].vec[1];
+ tv[tvtot+2].loc=icu->bezt[i].vec[2];
+
+ memcpy (&tv[tvtot+0].oldloc, icu->bezt[i].vec[0], sizeof (float)*3);
+ memcpy (&tv[tvtot+1].oldloc, icu->bezt[i].vec[1], sizeof (float)*3);
+ memcpy (&tv[tvtot+2].oldloc, icu->bezt[i].vec[2], sizeof (float)*3);
+ tvtot+=3;
+ }
+ }
+ }
+
+ return tvtot;
+}
+
+void duplicate_ipo_keys(Ipo *ipo)
+{
+ IpoCurve *icu;
+ int i;
+ BezTriple *newbezt;
+
+ if (!ipo)
+ return;
+
+ for (icu=ipo->curve.first; icu; icu=icu->next){
+ for (i=0; i<icu->totvert; i++){
+ /* If a key is selected */
+ if (icu->bezt[i].f2 & 1){
+ /* Expand the list */
+ newbezt = MEM_callocN(sizeof(BezTriple) * (icu->totvert+1), "beztriple");
+ memcpy (newbezt, icu->bezt, sizeof(BezTriple) * (i+1));
+ memcpy (newbezt+i+1, icu->bezt+i, sizeof(BezTriple));
+ memcpy (newbezt+i+2, icu->bezt+i+1, sizeof (BezTriple) *(icu->totvert-(i+1)));
+ icu->totvert++;
+ MEM_freeN (icu->bezt);
+ icu->bezt=newbezt;
+ /* Unselect the current key*/
+ icu->bezt[i].f1 &= ~ 1;
+ icu->bezt[i].f2 &= ~ 1;
+ icu->bezt[i].f3 &= ~ 1;
+ i++;
+ /* Select the copied key */
+ icu->bezt[i].f1 |= 1;
+ icu->bezt[i].f2 |= 1;
+ icu->bezt[i].f3 |= 1;
+
+ }
+ }
+ }
+}
+
+void borderselect_ipo_key(Ipo *ipo, float xmin, float xmax, int val)
+{
+ int i;
+ IpoCurve *icu;
+
+ if (!ipo)
+ return;
+
+ for (icu=ipo->curve.first; icu; icu=icu->next){
+ for (i=0; i<icu->totvert; i++){
+ if (icu->bezt[i].vec[1][0] > xmin && icu->bezt[i].vec[1][0] < xmax ){
+ if (val==1){
+ icu->bezt[i].f1 |= 1;
+ icu->bezt[i].f2 |= 1;
+ icu->bezt[i].f3 |= 1;
+ }
+ else{
+ icu->bezt[i].f1 &= ~1;
+ icu->bezt[i].f2 &= ~1;
+ icu->bezt[i].f3 &= ~1;
+ }
+ }
+ }
+ }
+}
+
+void select_ipo_key(Ipo *ipo, float selx, int sel)
+{
+ int i;
+ IpoCurve *icu;
+
+ if (!ipo)
+ return;
+
+ for (icu=ipo->curve.first; icu; icu=icu->next){
+ for (i=0; i<icu->totvert; i++){
+ if (icu->bezt[i].vec[1][0]==selx){
+ if (sel) {
+ icu->bezt[i].f1 &= ~1;
+ icu->bezt[i].f2 &= ~1;
+ icu->bezt[i].f3 &= ~1;
+ }
+ else {
+ icu->bezt[i].f1 |= 1;
+ icu->bezt[i].f2 |= 1;
+ icu->bezt[i].f3 |= 1;
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/source/blender/src/editkey.c b/source/blender/src/editkey.c
new file mode 100644
index 00000000000..9ef514102f4
--- /dev/null
+++ b/source/blender/src/editkey.c
@@ -0,0 +1,654 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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>
+#ifndef WIN32
+#include <unistd.h>
+#else
+#include <io.h>
+#include "BLI_winstuff.h"
+#endif
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+
+#include "DNA_curve_types.h"
+#include "DNA_ipo_types.h"
+#include "DNA_key_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_view2d_types.h"
+#include "DNA_lattice_types.h"
+#include "DNA_scene_types.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_anim.h"
+#include "BKE_curve.h"
+#include "BKE_global.h"
+#include "BKE_ipo.h"
+#include "BKE_key.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+#include "BKE_object.h"
+
+#include "BIF_editkey.h"
+#include "BIF_editview.h"
+#include "BIF_mywindow.h"
+#include "BIF_screen.h"
+#include "BIF_space.h"
+#include "BIF_toolbox.h"
+
+#include "BSE_editipo.h"
+#include "BSE_trans_types.h"
+
+#include "BDR_editobject.h"
+
+#include "blendef.h"
+#include "mydevice.h"
+#include "ipo.h"
+
+extern ListBase editNurb; /* in editcurve.c */
+
+static void default_key_ipo(Key *key)
+{
+ IpoCurve *icu;
+ BezTriple *bezt;
+
+ key->ipo= add_ipo("KeyIpo", ID_KE);
+
+ icu= MEM_callocN(sizeof(IpoCurve), "ipocurve");
+
+ icu->blocktype= ID_KE;
+ icu->adrcode= KEY_SPEED;
+ icu->flag= IPO_VISIBLE+IPO_SELECT;
+ set_icu_vars(icu);
+
+ BLI_addtail( &(key->ipo->curve), icu);
+
+ icu->bezt= bezt= MEM_callocN(2*sizeof(BezTriple), "defaultipo");
+ icu->totvert= 2;
+
+ bezt->hide= IPO_BEZ;
+ bezt->f1=bezt->f2= bezt->f3= SELECT;
+ bezt->h1= bezt->h2= HD_AUTO;
+ bezt++;
+ bezt->vec[1][0]= 100.0;
+ bezt->vec[1][1]= 1.0;
+ bezt->hide= IPO_BEZ;
+ bezt->f1=bezt->f2= bezt->f3= SELECT;
+ bezt->h1= bezt->h2= HD_AUTO;
+
+ calchandles_ipocurve(icu);
+}
+
+
+
+/* **************************************** */
+
+void mesh_to_key(Mesh *me, KeyBlock *kb)
+{
+ MVert *mvert;
+ float *fp;
+ int a;
+
+ if(me->totvert==0) return;
+
+ if(kb->data) MEM_freeN(kb->data);
+
+ kb->data= MEM_callocN(me->key->elemsize*me->totvert, "kb->data");
+ kb->totelem= me->totvert;
+
+ mvert= me->mvert;
+ fp= kb->data;
+ for(a=0; a<kb->totelem; a++, fp+=3, mvert++) {
+ VECCOPY(fp, mvert->co);
+
+ }
+}
+
+void key_to_mesh(KeyBlock *kb, Mesh *me)
+{
+ MVert *mvert;
+ float *fp;
+ int a, tot;
+
+ mvert= me->mvert;
+ fp= kb->data;
+
+ tot= MIN2(kb->totelem, me->totvert);
+
+ for(a=0; a<tot; a++, fp+=3, mvert++) {
+ VECCOPY(mvert->co, fp);
+ }
+}
+
+
+
+void insert_meshkey(Mesh *me)
+{
+ Key *key;
+ KeyBlock *kb, *kkb;
+ float curpos;
+
+ if(me->key==0) {
+ me->key= add_key( (ID *)me);
+ default_key_ipo(me->key);
+ }
+ key= me->key;
+
+ kb= MEM_callocN(sizeof(KeyBlock), "Keyblock");
+ BLI_addtail(&key->block, kb);
+ kb->type= KEY_CARDINAL;
+
+ curpos= bsystem_time(0, 0, (float)CFRA, 0.0);
+ if(calc_ipo_spec(me->key->ipo, KEY_SPEED, &curpos)==0) {
+ curpos /= 100.0;
+ }
+ kb->pos= curpos;
+
+ key->totkey++;
+ if(key->totkey==1) key->refkey= kb;
+
+ mesh_to_key(me, kb);
+
+ sort_keys(me->key);
+
+ /* curent actief: */
+ kkb= key->block.first;
+ while(kkb) {
+ kkb->flag &= ~SELECT;
+ if(kkb==kb) kkb->flag |= SELECT;
+
+ kkb= kkb->next;
+ }
+}
+
+/* ******************** */
+
+void latt_to_key(Lattice *lt, KeyBlock *kb)
+{
+ BPoint *bp;
+ float *fp;
+ int a, tot;
+
+ tot= lt->pntsu*lt->pntsv*lt->pntsw;
+ if(tot==0) return;
+
+ if(kb->data) MEM_freeN(kb->data);
+
+ kb->data= MEM_callocN(lt->key->elemsize*tot, "kb->data");
+ kb->totelem= tot;
+
+ bp= lt->def;
+ fp= kb->data;
+ for(a=0; a<kb->totelem; a++, fp+=3, bp++) {
+ VECCOPY(fp, bp->vec);
+ }
+}
+
+void key_to_latt(KeyBlock *kb, Lattice *lt)
+{
+ BPoint *bp;
+ float *fp;
+ int a, tot;
+
+ bp= lt->def;
+ fp= kb->data;
+
+ tot= lt->pntsu*lt->pntsv*lt->pntsw;
+ tot= MIN2(kb->totelem, tot);
+
+ for(a=0; a<tot; a++, fp+=3, bp++) {
+ VECCOPY(bp->vec, fp);
+ }
+
+}
+
+void insert_lattkey(Lattice *lt)
+{
+ Key *key;
+ KeyBlock *kb, *kkb;
+ float curpos;
+
+ if(lt->key==0) {
+ lt->key= add_key( (ID *)lt);
+ default_key_ipo(lt->key);
+ }
+ key= lt->key;
+
+ kb= MEM_callocN(sizeof(KeyBlock), "Keyblock");
+ BLI_addtail(&key->block, kb);
+ kb->type= KEY_CARDINAL;
+
+ curpos= bsystem_time(0, 0, (float)CFRA, 0.0);
+ if(calc_ipo_spec(lt->key->ipo, KEY_SPEED, &curpos)==0) {
+ curpos /= 100.0;
+ }
+ kb->pos= curpos;
+
+ key->totkey++;
+ if(key->totkey==1) key->refkey= kb;
+
+ latt_to_key(lt, kb);
+
+ sort_keys(lt->key);
+
+ /* curent actief: */
+ kkb= key->block.first;
+ while(kkb) {
+ kkb->flag &= ~SELECT;
+ if(kkb==kb) kkb->flag |= SELECT;
+
+ kkb= kkb->next;
+ }
+}
+
+/* ******************************** */
+
+void curve_to_key(Curve *cu, KeyBlock *kb, ListBase *nurb)
+{
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ float *fp;
+ int a, tot;
+
+ /* tellen */
+ tot= count_curveverts(nurb);
+ if(tot==0) return;
+
+ if(kb->data) MEM_freeN(kb->data);
+
+ kb->data= MEM_callocN(cu->key->elemsize*tot, "kb->data");
+ kb->totelem= tot;
+
+ nu= nurb->first;
+ fp= kb->data;
+ while(nu) {
+
+ if(nu->bezt) {
+ bezt= nu->bezt;
+ a= nu->pntsu;
+ while(a--) {
+ VECCOPY(fp, bezt->vec[0]);
+ fp+= 3;
+ VECCOPY(fp, bezt->vec[1]);
+ fp+= 3;
+ VECCOPY(fp, bezt->vec[2]);
+ fp+= 3;
+ fp+= 3; /* alfa's */
+ bezt++;
+ }
+ }
+ else {
+ bp= nu->bp;
+ a= nu->pntsu*nu->pntsv;
+ while(a--) {
+ VECCOPY(fp, bp->vec);
+ fp[3]= bp->alfa;
+
+ fp+= 4;
+ bp++;
+ }
+ }
+ nu= nu->next;
+ }
+}
+
+void key_to_curve(KeyBlock *kb, Curve *cu, ListBase *nurb)
+{
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ float *fp;
+ int a, tot;
+
+ nu= nurb->first;
+ fp= kb->data;
+
+ tot= count_curveverts(nurb);
+
+ tot= MIN2(kb->totelem, tot);
+
+ while(nu && tot>0) {
+
+ if(nu->bezt) {
+ bezt= nu->bezt;
+ a= nu->pntsu;
+ while(a-- && tot>0) {
+ VECCOPY(bezt->vec[0], fp);
+ fp+= 3;
+ VECCOPY(bezt->vec[1], fp);
+ fp+= 3;
+ VECCOPY(bezt->vec[2], fp);
+ fp+= 3;
+ fp+= 3; /* alfa's */
+
+ tot-= 3;
+ bezt++;
+ }
+ }
+ else {
+ bp= nu->bp;
+ a= nu->pntsu*nu->pntsv;
+ while(a-- && tot>0) {
+ VECCOPY(bp->vec, fp);
+ bp->alfa= fp[3];
+
+ fp+= 4;
+ tot--;
+ bp++;
+ }
+ }
+ nu= nu->next;
+ }
+}
+
+
+
+void insert_curvekey(Curve *cu)
+{
+ Key *key;
+ KeyBlock *kb, *kkb;
+ float curpos;
+
+ if(cu->key==0) {
+ cu->key= add_key( (ID *)cu);
+ default_key_ipo(cu->key);
+ }
+ key= cu->key;
+
+ kb= MEM_callocN(sizeof(KeyBlock), "Keyblock");
+ BLI_addtail(&key->block, kb);
+ kb->type= KEY_CARDINAL;
+
+ curpos= bsystem_time(0, 0, (float)CFRA, 0.0);
+ if(calc_ipo_spec(cu->key->ipo, KEY_SPEED, &curpos)==0) {
+ curpos /= 100.0;
+ }
+ kb->pos= curpos;
+
+ key->totkey++;
+ if(key->totkey==1) key->refkey= kb;
+
+ if(editNurb.first) curve_to_key(cu, kb, &editNurb);
+ else curve_to_key(cu, kb, &cu->nurb);
+
+ sort_keys(cu->key);
+
+ /* curent actief: */
+ kkb= key->block.first;
+ while(kkb) {
+ kkb->flag &= ~SELECT;
+ if(kkb==kb) kkb->flag |= SELECT;
+
+ kkb= kkb->next;
+ }
+}
+
+
+/* ******************** */
+
+Key *give_current_key(Object *ob)
+{
+ Mesh *me;
+ Curve *cu;
+ Lattice *lt;
+
+ if(ob->type==OB_MESH) {
+ me= ob->data;
+ return me->key;
+ }
+ else if ELEM(ob->type, OB_CURVE, OB_SURF) {
+ cu= ob->data;
+ return cu->key;
+ }
+ else if(ob->type==OB_LATTICE) {
+ lt= ob->data;
+ return lt->key;
+ }
+ return 0;
+}
+
+void showkeypos(Key *key, KeyBlock *kb)
+{
+ Object *ob;
+ Mesh *me;
+ Lattice *lt;
+ Curve *cu;
+ int tot;
+
+ /* vanuit ipo */
+ ob= OBACT;
+ if(ob==0) return;
+
+ if(key == give_current_key(ob)) {
+
+ if(ob->type==OB_MESH) {
+ me= ob->data;
+
+ cp_key(0, me->totvert, me->totvert, (char *)me->mvert->co, me->key, kb, 0);
+
+ make_displists_by_obdata(me);
+ }
+ else if(ob->type==OB_LATTICE) {
+ lt= ob->data;
+ tot= lt->pntsu*lt->pntsv*lt->pntsw;
+
+ cp_key(0, tot, tot, (char *)lt->def->vec, lt->key, kb, 0);
+
+ make_displists_by_parent(ob);
+ }
+ else if ELEM(ob->type, OB_CURVE, OB_SURF) {
+ cu= ob->data;
+ tot= count_curveverts(&cu->nurb);
+ cp_cu_key(cu, kb, 0, tot);
+
+/* make_displists_by_obdata(me); */
+ make_displists_by_obdata(cu);
+ }
+
+ allqueue(REDRAWVIEW3D, 0);
+ }
+}
+
+void deselectall_key(void)
+{
+ KeyBlock *kb;
+ Key *key;
+
+ if(G.sipo->blocktype!=ID_KE) return;
+ key= (Key *)G.sipo->from;
+ if(key==0) return;
+
+ kb= key->block.first;
+ while(kb) {
+ kb->flag &= ~SELECT;
+ kb= kb->next;
+ }
+}
+
+
+void delete_key(void)
+{
+ KeyBlock *kb, *kbn;
+ Key *key;
+
+ if(G.sipo->blocktype!=ID_KE) return;
+
+ if(okee("Erase selected keys")==0) return;
+
+ key= (Key *)G.sipo->from;
+ if(key==0) return;
+
+ kb= key->block.first;
+ while(kb) {
+ kbn= kb->next;
+ if(kb->flag & SELECT) {
+ BLI_remlink(&key->block, kb);
+ key->totkey--;
+ if(key->refkey== kb) key->refkey= key->block.first;
+
+ if(kb->data) MEM_freeN(kb->data);
+ MEM_freeN(kb);
+
+ }
+ kb= kbn;
+ }
+
+ if(key->totkey==0) {
+ if(GS(key->from->name)==ID_ME) ((Mesh *)key->from)->key= 0;
+ else if(GS(key->from->name)==ID_CU) ((Curve *)key->from)->key= 0;
+ else if(GS(key->from->name)==ID_LT) ((Lattice *)key->from)->key= 0;
+
+ free_libblock_us(&(G.main->key), key);
+ scrarea_queue_headredraw(curarea); /* ipo ook weg */
+ }
+ else do_spec_key(key);
+
+ allqueue(REDRAWVIEW3D, 0);
+ scrarea_queue_winredraw(curarea);
+}
+
+void move_keys(void)
+{
+ Key *key;
+ KeyBlock *kb;
+ TransVert *transmain, *tv;
+ float div, dy, vec[3], dvec[3];
+ int a, tot=0, afbreek=0, firsttime= 1;
+ unsigned short event = 0;
+ short mval[2], val, xo, yo;
+ char str[32];
+
+ if(G.sipo->blocktype!=ID_KE) return;
+
+ if(G.sipo->ipo && G.sipo->ipo->id.lib) return;
+ if(G.sipo->editipo==0) return;
+
+ key= (Key *)G.sipo->from;
+ if(key==0) return;
+
+ /* welke keys doen mee */
+ kb= key->block.first;
+ while(kb) {
+ if(kb->flag & SELECT) tot++;
+ kb= kb->next;
+ }
+
+ if(tot==0) return;
+
+ tv=transmain= MEM_callocN(tot*sizeof(TransVert), "transmain");
+ kb= key->block.first;
+ while(kb) {
+ if(kb->flag & SELECT) {
+ tv->loc= &kb->pos;
+ tv->oldloc[0]= kb->pos;
+ tv++;
+ }
+ kb= kb->next;
+ }
+
+ getmouseco_areawin(mval);
+ xo= mval[0];
+ yo= mval[1];
+ dvec[0]=dvec[1]=dvec[2]= 0.0;
+
+
+ while(afbreek==0) {
+ getmouseco_areawin(mval);
+ if(mval[0]!=xo || mval[1]!=yo || firsttime) {
+ firsttime= 0;
+
+ dy= (float)(mval[1]- yo);
+
+ div= (float)(G.v2d->mask.ymax-G.v2d->mask.ymin);
+ dvec[1]+= (G.v2d->cur.ymax-G.v2d->cur.ymin)*(dy)/div;
+
+ VECCOPY(vec, dvec);
+
+ apply_keyb_grid(vec, 0.0, 1.0, 0.1, U.flag & AUTOGRABGRID);
+ apply_keyb_grid(vec+1, 0.0, 1.0, 0.1, U.flag & AUTOGRABGRID);
+
+ tv= transmain;
+ for(a=0; a<tot; a++, tv++) {
+ tv->loc[0]= tv->oldloc[0]+vec[1];
+ }
+
+ sprintf(str, "Y: %.3f ", vec[1]);
+ headerprint(str);
+
+ xo= mval[0];
+ yo= mval[1];
+
+ force_draw();
+ }
+ else BIF_wait_for_statechange();
+
+ while(qtest()) {
+ event= extern_qread(&val);
+ if(val) {
+ switch(event) {
+ case ESCKEY:
+ case LEFTMOUSE:
+ case SPACEKEY:
+ afbreek= 1;
+ break;
+ default:
+ arrows_move_cursor(event);
+ }
+ }
+ }
+ }
+
+ if(event==ESCKEY) {
+ tv= transmain;
+ for(a=0; a<tot; a++, tv++) {
+ tv->loc[0]= tv->oldloc[0];
+ }
+ }
+
+ sort_keys(key);
+ do_spec_key(key);
+
+ /* voor boundbox */
+ editipo_changed(G.sipo, 0);
+
+ MEM_freeN(transmain);
+ allqueue(REDRAWVIEW3D, 0);
+ scrarea_queue_redraw(curarea);
+}
diff --git a/source/blender/src/editlattice.c b/source/blender/src/editlattice.c
new file mode 100644
index 00000000000..68c16ea2d44
--- /dev/null
+++ b/source/blender/src/editlattice.c
@@ -0,0 +1,318 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * i.t.t. wat de naam doet vermoeden: ook algemene lattice (calc) functies
+ */
+
+#include <stdlib.h>
+#include <math.h>
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_lattice_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_key_types.h"
+#include "DNA_view3d_types.h"
+
+#include "BKE_key.h"
+#include "BKE_displist.h"
+#include "BKE_lattice.h"
+#include "BKE_global.h"
+
+#include "BIF_toolbox.h"
+#include "BIF_space.h"
+#include "BIF_screen.h"
+#include "BIF_editlattice.h"
+#include "BIF_editkey.h"
+
+#include "BSE_edit.h"
+
+#include "BDR_editobject.h"
+#include "BDR_drawobject.h"
+
+#include "blendef.h"
+#include "mydevice.h"
+
+#include "render.h"
+
+#include "BKE_armature.h"
+
+void apply_lattice(void)
+{
+ Base *base;
+ Object *par;
+
+ if(okee("Apply Lattice Deform")==0) return;
+
+ base= FIRSTBASE;
+ while(base) {
+ if TESTBASELIB(base) {
+ if( (par= base->object->parent) ) {
+ if(par->type==OB_LATTICE) {
+
+ lt_applyflag= 1;
+ object_deform(base->object);
+ lt_applyflag= 0;
+
+ base->object->parent= 0;
+ }
+ }
+ }
+ base= base->next;
+ }
+
+ allqueue(REDRAWVIEW3D, 0);
+}
+
+/* ***************************** */
+
+
+
+
+void free_editLatt(void)
+{
+ if(editLatt) {
+ if(editLatt->def) MEM_freeN(editLatt->def);
+ MEM_freeN(editLatt);
+ editLatt= 0;
+ }
+}
+
+
+static void setflagsLatt(int flag)
+{
+ BPoint *bp;
+ int a;
+
+ bp= editLatt->def;
+
+ a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
+
+ while(a--) {
+ if(bp->hide==0) {
+ bp->f1= flag;
+ }
+ bp++;
+ }
+}
+
+
+
+void make_editLatt(void)
+{
+ Lattice *lt;
+ KeyBlock *actkey=0;
+
+ free_editLatt();
+
+ lt= G.obedit->data;
+
+ /* keys? */
+ if(lt->key) {
+ actkey= lt->key->block.first;
+ while(actkey) {
+ if(actkey->flag & SELECT) break;
+ actkey= actkey->next;
+ }
+ }
+
+ if(actkey) {
+ key_to_latt(actkey, lt);
+ }
+
+ editLatt= MEM_dupallocN(lt);
+
+ editLatt->def= MEM_dupallocN(lt->def);
+
+ setflagsLatt(0);
+}
+
+
+void load_editLatt(void)
+{
+ Lattice *lt;
+ KeyBlock *actkey=0;
+ BPoint *bp;
+ float *fp;
+ int tot;
+
+ lt= G.obedit->data;
+
+ /* zijn er keys? */
+ if(lt->key) {
+ actkey= lt->key->block.first;
+ while(actkey) {
+ if(actkey->flag & SELECT) break;
+ actkey= actkey->next;
+ }
+ }
+
+ if(actkey) {
+ /* aktieve key: vertices */
+ tot= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
+
+ if(actkey->data) MEM_freeN(actkey->data);
+
+ fp=actkey->data= MEM_callocN(lt->key->elemsize*tot, "actkey->data");
+ actkey->totelem= tot;
+
+ bp= editLatt->def;
+ while(tot--) {
+ VECCOPY(fp, bp->vec);
+ fp+= 3;
+ bp++;
+ }
+
+ if(actkey) do_spec_key(lt->key);
+ }
+ else {
+
+ MEM_freeN(lt->def);
+
+ lt->def= MEM_dupallocN(editLatt->def);
+
+ lt->flag= editLatt->flag;
+
+ lt->pntsu= editLatt->pntsu;
+ lt->pntsv= editLatt->pntsv;
+ lt->pntsw= editLatt->pntsw;
+
+ lt->typeu= editLatt->typeu;
+ lt->typev= editLatt->typev;
+ lt->typew= editLatt->typew;
+ }
+}
+
+void remake_editLatt(void)
+{
+ if(okee("Reload Original data")==0) return;
+
+ make_editLatt();
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWBUTSEDIT, 0);
+}
+
+
+void deselectall_Latt(void)
+{
+ BPoint *bp;
+ int a;
+
+ bp= editLatt->def;
+
+ a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
+
+ allqueue(REDRAWVIEW3D, 0);
+
+ while(a--) {
+ if(bp->hide==0) {
+ if(bp->f1) {
+ setflagsLatt(0);
+ return;
+ }
+ }
+ bp++;
+ }
+ setflagsLatt(1);
+}
+
+
+static BPoint *findnearestLattvert(int sel)
+{
+ /* sel==1: selected krijgen een nadeel */
+ /* in bp wordt nearest weggeschreven */
+ BPoint *bp1, *bp;
+ short dist= 100, temp, mval[2], a;
+
+ bp= 0;
+
+ /* projektie doen */
+ calc_lattverts_ext(); /* drawobject.c */
+
+ getmouseco_areawin(mval);
+
+
+ bp1= editLatt->def;
+
+ a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
+
+ while(a--) {
+ if(bp1->hide==0) {
+ temp= abs(mval[0]- bp1->s[0])+ abs(mval[1]- bp1->s[1]);
+ if( (bp1->f1 & 1)==sel) temp+=5;
+ if(temp<dist) {
+ bp= bp1;
+ dist= temp;
+ }
+ }
+ bp1++;
+ }
+
+ return bp;
+}
+
+
+void mouse_lattice(void)
+{
+ BPoint *bp=0;
+
+ bp= findnearestLattvert(1);
+
+ if(bp) {
+ if((G.qual & LR_SHIFTKEY)==0) {
+
+ setflagsLatt(0);
+ bp->f1 |= 1;
+
+ allqueue(REDRAWVIEW3D, 0);
+ }
+ else {
+
+ if(bp->f1 & 1) bp->f1 &= ~1;
+ else bp->f1 |= 1;
+
+ allqueue(REDRAWVIEW3D, 0);
+
+ }
+
+ countall();
+ }
+
+ rightmouse_transform();
+
+}
diff --git a/source/blender/src/editmball.c b/source/blender/src/editmball.c
new file mode 100644
index 00000000000..329157fcda0
--- /dev/null
+++ b/source/blender/src/editmball.c
@@ -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 *****
+ */
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+
+#include "DNA_screen_types.h"
+#include "DNA_meta_types.h"
+#include "DNA_object_types.h"
+#include "DNA_view3d_types.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_displist.h"
+#include "BKE_global.h"
+#include "BKE_object.h"
+
+#include "BIF_gl.h"
+#include "BIF_graphics.h"
+#include "BIF_screen.h"
+#include "BIF_toolbox.h"
+#include "BIF_space.h"
+
+#include "BDR_editobject.h"
+#include "BDR_editmball.h"
+
+#include "BSE_edit.h"
+#include "BSE_view.h"
+
+#include "render.h"
+#include "blendef.h"
+#include "mydevice.h"
+
+extern short editbutflag;
+
+ListBase editelems= {0, 0};
+MetaElem *lastelem;
+
+void make_editMball()
+{
+ MetaBall *mb;
+ MetaElem *ml, *newmb;
+
+ BLI_freelistN(&editelems);
+ lastelem= 0;
+
+ mb= G.obedit->data;
+ ml= mb->elems.first;
+
+ while(ml) {
+ newmb= MEM_dupallocN(ml);
+ BLI_addtail(&editelems, newmb);
+ if(ml->flag & SELECT) lastelem= newmb;
+
+ ml= ml->next;
+ }
+
+ allqueue(REDRAWBUTSEDIT, 0);
+
+ countall();
+}
+
+void load_editMball()
+{
+ /* load mball in object */
+ MetaBall *mb;
+ MetaElem *ml, *newml;
+
+ if(G.obedit==0) return;
+
+ mb= G.obedit->data;
+ BLI_freelistN(&(mb->elems));
+
+
+ ml= editelems.first;
+ while(ml) {
+ newml= MEM_dupallocN(ml);
+ BLI_addtail(&(mb->elems), newml);
+
+ ml= ml->next;
+ }
+}
+
+void add_primitiveMball(int dummy_argument)
+{
+ MetaElem *ml;
+ float *curs, mat[3][3], cent[3], imat[3][3], cmat[3][3];
+
+ if(G.scene->id.lib) return;
+
+ /* this function also comes from an info window */
+ if ELEM(curarea->spacetype, SPACE_VIEW3D, SPACE_INFO); else return;
+
+ check_editmode(OB_MBALL);
+
+ /* als geen obedit: nieuw object en in editmode gaan */
+ if(G.obedit==0) {
+ add_object(OB_MBALL);
+ base_init_from_view3d(BASACT, G.vd);
+ G.obedit= BASACT->object;
+
+ where_is_object(G.obedit);
+
+ make_editMball();
+ setcursor_space(SPACE_VIEW3D, CURSOR_EDIT);
+ }
+
+ /* deselecteren */
+ ml= editelems.first;
+ while(ml) {
+ ml->flag &= ~SELECT;
+ ml= ml->next;
+ }
+
+ /* imat en centrum en afmeting */
+ Mat3CpyMat4(mat, G.obedit->obmat);
+
+ curs= give_cursor();
+ VECCOPY(cent, curs);
+ cent[0]-= G.obedit->obmat[3][0];
+ cent[1]-= G.obedit->obmat[3][1];
+ cent[2]-= G.obedit->obmat[3][2];
+
+ Mat3CpyMat4(imat, G.vd->viewmat);
+ Mat3MulVecfl(imat, cent);
+ Mat3MulMat3(cmat, imat, mat);
+ Mat3Inv(imat,cmat);
+
+ Mat3MulVecfl(imat, cent);
+
+ ml= MEM_callocN(sizeof(MetaElem), "metaelem");
+ BLI_addtail(&editelems, ml);
+
+ ml->x= cent[0];
+ ml->y= cent[1];
+ ml->z= cent[2];
+ ml->rad= 1.0;
+ ml->lay= 1;
+ ml->s= 2.0;
+ ml->len= 1.0;
+ ml->expx= ml->expy= ml->expz= 2.0;
+ ml->flag= SELECT;
+
+ lastelem= ml;
+
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWBUTSALL, 0);
+ makeDispList(G.obedit);
+}
+
+void deselectall_mball()
+{
+ MetaElem *ml;
+ int sel= 0;
+
+ ml= editelems.first;
+ while(ml) {
+ if(ml->flag & SELECT) break;
+ ml= ml->next;
+ }
+
+ if(ml) sel= 1;
+
+ ml= editelems.first;
+ while(ml) {
+ if(sel) ml->flag &= ~SELECT;
+ else ml->flag |= SELECT;
+ ml= ml->next;
+ }
+ allqueue(REDRAWVIEW3D, 0);
+}
+
+void mouse_mball()
+{
+ static MetaElem *startelem=0;
+ MetaElem *ml, *act=0;
+ int a, hits;
+ /* was IGLuint ... but is stupid */
+ GLuint buffer[MAXPICKBUF];
+
+ hits= selectprojektie(buffer, 0, 0, 0, 0);
+
+ /* bestaat startelem? */
+ ml= editelems.first;
+ while(ml) {
+ if(ml==startelem) break;
+ ml= ml->next;
+ }
+ if(ml==0) startelem= editelems.first;
+
+ if(hits>0) {
+ ml= startelem;
+ while(ml) {
+ /* if(base->lay & G.vd->lay) { */
+
+ for(a=0; a<hits; a++) {
+ /* index converted for gl stuff */
+ if(ml->selcol==buffer[ 4 * a + 3 ]) act= ml;
+ }
+ /* } */
+
+ if(act) break;
+
+ ml= ml->next;
+ if(ml==0) ml= editelems.first;
+ if(ml==startelem) break;
+ }
+ if(act) {
+ if((G.qual & LR_SHIFTKEY)==0) {
+ deselectall_mball();
+ if(act->flag & SELECT) deselectall_mball();
+ act->flag |= SELECT;
+ }
+ else {
+ if(act->flag & SELECT) {
+ act->flag &= ~SELECT;
+ }
+ else act->flag |= SELECT;
+ }
+ lastelem= act;
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWBUTSEDIT, 0);
+ }
+ }
+ rightmouse_transform();
+}
+
+void adduplicate_mball()
+{
+ MetaElem *ml, *newml;
+
+ ml= editelems.last;
+ while(ml) {
+ if(ml->flag & SELECT) {
+ newml= MEM_dupallocN(ml);
+ BLI_addtail(&editelems, newml);
+ lastelem= newml;
+ ml->flag &= ~SELECT;
+ }
+ ml= ml->prev;
+ }
+
+ transform('g');
+ allqueue(REDRAWBUTSEDIT, 0);
+}
+
+void delete_mball()
+{
+ MetaElem *ml, *next;
+
+ if(okee("Erase selected")==0) return;
+
+ ml= editelems.first;
+ while(ml) {
+ next= ml->next;
+ if(ml->flag & SELECT) {
+ if(lastelem==ml) lastelem= 0;
+ BLI_remlink(&editelems, ml);
+ MEM_freeN(ml);
+ }
+ ml= next;
+ }
+
+ makeDispList(G.obedit);
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWBUTSEDIT, 0);
+}
diff --git a/source/blender/src/editmesh.c b/source/blender/src/editmesh.c
new file mode 100644
index 00000000000..7597e0b8cd3
--- /dev/null
+++ b/source/blender/src/editmesh.c
@@ -0,0 +1,6387 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 <math.h>
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+#include "BLI_rand.h"
+
+#include "MTC_matrixops.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_key_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_material_types.h"
+#include "DNA_texture_types.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_key.h"
+#include "BKE_object.h"
+#include "BKE_texture.h"
+#include "BKE_displist.h"
+#include "BKE_global.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+#include "BKE_material.h"
+#include "BKE_mesh.h"
+
+#include "BIF_gl.h"
+#include "BIF_graphics.h"
+#include "BIF_editkey.h"
+#include "BIF_space.h"
+#include "BIF_toolbox.h"
+#include "BIF_screen.h"
+#include "BIF_interface.h"
+#include "BIF_editmesh.h"
+#include "BIF_mywindow.h"
+
+#include "BSE_view.h"
+#include "BSE_edit.h"
+#include "BSE_trans_types.h"
+
+#include "BDR_drawobject.h"
+#include "BDR_editobject.h"
+#include "BDR_editface.h"
+#include "BDR_vpaint.h"
+
+#include "mydevice.h"
+#include "blendef.h"
+#include "interface.h" /* MAART: for NUM and FLO types */
+#include "nla.h" /* For __NLA : Important - Do not remove! */
+#include "render.h"
+
+/****/
+
+static void free_editverts(ListBase *edve);
+static float convex(float *v1, float *v2, float *v3, float *v4);
+
+/****/
+
+
+/* extern ListBase fillvertbase, filledgebase; */ /* scanfill.c, in
+ the lib... already in BLI_blenlib.h */
+
+/* voor debug:
+#define free(a) freeN(a)
+#define malloc(a) mallocN(a, "malloc")
+#define calloc(a, b) callocN((a)*(b), "calloc")
+#define freelist(a) freelistN(a)
+*/
+
+extern short editbutflag;
+
+static float icovert[12][3] = {
+ {0,0,-200},
+ {144.72, -105.144,-89.443},
+ {-55.277, -170.128,-89.443},
+ {-178.885,0,-89.443},
+ {-55.277,170.128,-89.443},
+ {144.72,105.144,-89.443},
+ {55.277,-170.128,89.443},
+ {-144.72,-105.144,89.443},
+ {-144.72,105.144,89.443},
+ {55.277,170.128,89.443},
+ {178.885,0,89.443},
+ {0,0,200}
+};
+static short icovlak[20][3] = {
+ {1,0,2},
+ {1,0,5},
+ {2,0,3},
+ {3,0,4},
+ {4,0,5},
+ {1,5,10},
+ {2,1,6},
+ {3,2,7},
+ {4,3,8},
+ {5,4,9},
+ {10,1,6},
+ {6,2,7},
+ {7,3,8},
+ {8,4,9},
+ {9,5,10},
+ {6,10,11},
+ {7,6,11},
+ {8,7,11},
+ {9,8,11},
+ {10,9,11}
+};
+
+/* DEFINES */
+#define UVCOPY(t, s) memcpy(t, s, 2 * sizeof(float));
+
+#define TEST_EDITMESH if(G.obedit==0) return; \
+ if( (G.vd->lay & G.obedit->lay)==0 ) return;
+
+#define FACE_MARKCLEAR(f) (f->f1 = 1)
+
+/* ***************** HASH ********************* */
+
+/* HASH struct voor snel opzoeken edges */
+struct HashEdge {
+ struct EditEdge *eed;
+ struct HashEdge *next;
+};
+
+struct HashEdge *hashedgetab=0;
+
+/********* qsort routines *********/
+
+
+struct xvertsort {
+ float x;
+ EditVert *v1;
+};
+
+/* Functions */
+static int vergxco(const void *v1, const void *v2)
+{
+ const struct xvertsort *x1=v1, *x2=v2;
+
+ if( x1->x > x2->x ) return 1;
+ else if( x1->x < x2->x) return -1;
+ return 0;
+}
+
+struct vlaksort {
+ long x;
+ struct EditVlak *evl;
+};
+
+
+static int vergvlak(const void *v1, const void *v2)
+{
+ const struct vlaksort *x1=v1, *x2=v2;
+
+ if( x1->x > x2->x ) return 1;
+ else if( x1->x < x2->x) return -1;
+ return 0;
+}
+
+
+/* ************ ADD / REMOVE / FIND ****************** */
+
+#define EDHASH(a, b) ( (a)*256 + (b) )
+#define EDHASHSIZE 65536
+
+#if 0
+static void check_hashedge(void)
+{
+ int i, i2, doubedge=0;
+ struct HashEdge *he, *he2;
+
+ for (i=0; i<64; i++) {
+ he= hashedgetab+i;
+
+ while (he && he->eed) {
+ for (i2=i+1; i2<64; i2++) {
+ he2= hashedgetab+i2;
+
+ while (he2) {
+ if (he->eed == he2->eed) doubedge++;
+
+ he2= he2->next;
+ }
+ }
+
+ he= he->next;
+ }
+ }
+
+ if (doubedge) printf("%d double edges!\n", doubedge);
+}
+#endif
+
+EditVert *addvertlist(float *vec)
+{
+ EditVert *eve;
+ static unsigned char hashnr= 0;
+
+ eve= calloc(sizeof(EditVert),1);
+ BLI_addtail(&G.edve, eve);
+
+ if(vec) VECCOPY(eve->co, vec);
+
+ eve->hash= hashnr++;
+
+ return eve;
+}
+
+EditEdge *findedgelist(EditVert *v1, EditVert *v2)
+{
+ EditVert *v3;
+ struct HashEdge *he;
+
+ if(hashedgetab==0) {
+ hashedgetab= MEM_callocN(EDHASHSIZE*sizeof(struct HashEdge), "hashedgetab");
+ }
+
+ /* swap ? */
+ if( (long)v1 > (long)v2) {
+ v3= v2;
+ v2= v1;
+ v1= v3;
+ }
+
+ /* eerst even op de flip-plek kijken */
+
+/* he= hashedgetab + EDHASH(v2->hash, v1->hash); */
+/* if(he->eed && he->eed->v1==v1 && he->eed->v2==v2) return he->eed; */
+
+
+ he= hashedgetab + EDHASH(v1->hash, v2->hash);
+
+ while(he) {
+
+ if(he->eed && he->eed->v1==v1 && he->eed->v2==v2) return he->eed;
+
+ he= he->next;
+ }
+ return 0;
+}
+
+static void insert_hashedge(EditEdge *eed)
+{
+ /* er van uitgaande dat eed nog niet in lijst zit, en eerst een find is gedaan */
+
+ struct HashEdge *first, *he;
+
+ /* eerst even op de flip-plek kijken */
+/* he= hashedgetab + EDHASH(eed->v2->hash, eed->v1->hash); */
+
+/* if(he->eed==0) { */
+/* he->eed= eed; */
+/* return; */
+/* } */
+
+ first= hashedgetab + EDHASH(eed->v1->hash, eed->v2->hash);
+
+ if( first->eed==0 ) {
+ first->eed= eed;
+ }
+ else {
+ he= (struct HashEdge *)malloc(sizeof(struct HashEdge));
+ he->eed= eed;
+ he->next= first->next;
+ first->next= he;
+ }
+}
+
+static void remove_hashedge(EditEdge *eed)
+{
+ /* er van uitgaande dat eed in lijst zit */
+
+ struct HashEdge *first, *he, *prev=NULL;
+
+
+ /* eerst even op de flip-plek kijken */
+/* first= hashedgetab + EDHASH(eed->v2->hash, eed->v1->hash); */
+
+/* if(first->eed==eed) { */
+ /* uit lijst verwijderen */
+
+/* if(first->next) { */
+/* he= first->next; */
+/* first->eed= he->eed; */
+/* first->next= he->next; */
+/* free(he); */
+/* } */
+/* else first->eed= 0; */
+
+/* return; */
+/* } */
+
+
+ he=first= hashedgetab + EDHASH(eed->v1->hash, eed->v2->hash);
+
+ while(he) {
+ if(he->eed == eed) {
+ /* uit lijst verwijderen */
+ if(he==first) {
+ if(first->next) {
+ he= first->next;
+ first->eed= he->eed;
+ first->next= he->next;
+ free(he);
+ }
+ else he->eed= 0;
+ }
+ else {
+ prev->next= he->next;
+ free(he);
+ }
+ return;
+ }
+ prev= he;
+ he= he->next;
+ }
+}
+
+void free_hashedgetab(void)
+{
+ struct HashEdge *he, *first, *hen;
+ int a;
+/* int test[30], nr, toted=0; */
+
+ /* for(a=0; a<30; a++) test[a]=0; */
+
+ if(hashedgetab) {
+
+ first= hashedgetab;
+ for(a=0; a<EDHASHSIZE; a++, first++) {
+ he= first->next;
+ /* nr= 0; */
+ /* if(first->eed) toted++; */
+ /* if(first->eed) nr++; */
+ while(he) {
+ hen= he->next;
+ free(he);
+ he= hen;
+ /* nr++; */
+ }
+ /* if(nr>29) nr= 29; */
+ /* test[nr]++; */
+ }
+ MEM_freeN(hashedgetab);
+ hashedgetab= 0;
+
+ /* printf("toted %d\n", toted); */
+ /* toted= 0; */
+ /* for(a=0; a<30; a++) { */
+ /* printf("tab %d %d\n", a, test[a]); */
+ /* } */
+ }
+}
+
+EditEdge *addedgelist(EditVert *v1, EditVert *v2)
+{
+ EditVert *v3;
+ EditEdge *eed;
+ int swap= 0;
+
+ /* swap ? */
+ if(v1>v2) {
+ v3= v2;
+ v2= v1;
+ v1= v3;
+ swap= 1;
+ }
+
+ if(v1==v2) return 0;
+ if(v1==0 || v2==0) return 0;
+
+ /* opzoeken in hashlijst */
+ eed= findedgelist(v1, v2);
+
+ if(eed==0) {
+
+ eed= (EditEdge *)calloc(sizeof(EditEdge), 1);
+ eed->v1= v1;
+ eed->v2= v2;
+ BLI_addtail(&G.eded, eed);
+ eed->dir= swap;
+ insert_hashedge(eed);
+ }
+ return eed;
+}
+
+
+void remedge(EditEdge *eed)
+{
+
+ BLI_remlink(&G.eded, eed);
+
+ remove_hashedge(eed);
+}
+
+static void freevlak(EditVlak *evl)
+{
+ free(evl);
+}
+
+static void freevlaklist(ListBase *lb)
+{
+ EditVlak *evl, *next;
+
+ evl= lb->first;
+ while(evl) {
+ next= evl->next;
+ freevlak(evl);
+ evl= next;
+ }
+ lb->first= lb->last= 0;
+}
+
+EditVlak *addvlaklist(EditVert *v1, EditVert *v2, EditVert *v3, EditVert *v4, EditVlak *example)
+{
+ EditVlak *evl;
+ EditEdge *e1, *e2=0, *e3=0, *e4=0;
+
+
+ /* voeg vlak toe aan lijst en doe meteen de edges */
+ e1= addedgelist(v1, v2);
+ if(v3) e2= addedgelist(v2, v3);
+ if(v4) e3= addedgelist(v3, v4); else e3= addedgelist(v3, v1);
+ if(v4) e4= addedgelist(v4, v1);
+
+ if(v1==v2 || v2==v3 || v1==v3) return 0;
+ if(e2==0) return 0;
+
+ evl= (EditVlak *)calloc(sizeof(EditVlak), 1);
+ evl->v1= v1;
+ evl->v2= v2;
+ evl->v3= v3;
+ evl->v4= v4;
+
+ evl->e1= e1;
+ evl->e2= e2;
+ evl->e3= e3;
+ evl->e4= e4;
+
+ if(example) {
+ evl->mat_nr= example->mat_nr;
+ evl->tface= example->tface;
+ evl->flag= example->flag;
+ memcpy(evl->col, example->col, sizeof(example->col));
+ memcpy(evl->uv, example->uv, sizeof(example->uv));
+ }
+ else {
+ if (G.obedit && G.obedit->actcol)
+ evl->mat_nr= G.obedit->actcol-1;
+ default_uv(evl->uv, 1.0);
+
+ /* Initialize colors */
+ evl->col[0]= evl->col[1]= evl->col[2]= evl->col[3]= vpaint_get_current_col();
+ }
+
+ BLI_addtail(&G.edvl, evl);
+
+ if(evl->v4) CalcNormFloat4(v1->co, v2->co, v3->co, v4->co, evl->n);
+ else CalcNormFloat(v1->co, v2->co, v3->co, evl->n);
+
+ return evl;
+}
+
+static int comparevlak(EditVlak *vl1, EditVlak *vl2)
+{
+ EditVert *v1, *v2, *v3, *v4;
+
+ if(vl1->v4 && vl2->v4) {
+ v1= vl2->v1;
+ v2= vl2->v2;
+ v3= vl2->v3;
+ v4= vl2->v4;
+
+ if(vl1->v1==v1 || vl1->v2==v1 || vl1->v3==v1 || vl1->v4==v1) {
+ if(vl1->v1==v2 || vl1->v2==v2 || vl1->v3==v2 || vl1->v4==v2) {
+ if(vl1->v1==v3 || vl1->v2==v3 || vl1->v3==v3 || vl1->v4==v3) {
+ if(vl1->v1==v4 || vl1->v2==v4 || vl1->v3==v4 || vl1->v4==v4) {
+ return 1;
+ }
+ }
+ }
+ }
+ }
+ else if(vl1->v4==0 && vl2->v4==0) {
+ v1= vl2->v1;
+ v2= vl2->v2;
+ v3= vl2->v3;
+
+ if(vl1->v1==v1 || vl1->v2==v1 || vl1->v3==v1) {
+ if(vl1->v1==v2 || vl1->v2==v2 || vl1->v3==v2) {
+ if(vl1->v1==v3 || vl1->v2==v3 || vl1->v3==v3) {
+ return 1;
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+
+#if 0
+static int dubbelvlak(EditVlak *evltest)
+{
+
+ EditVlak *evl;
+
+ evl= G.edvl.first;
+ while(evl) {
+ if(evl!=evltest) {
+ if(comparevlak(evltest, evl)) return 1;
+ }
+ evl= evl->next;
+ }
+ return 0;
+}
+#endif
+
+static int exist_vlak(EditVert *v1, EditVert *v2, EditVert *v3, EditVert *v4)
+{
+ EditVlak *evl, evltest;
+
+ evltest.v1= v1;
+ evltest.v2= v2;
+ evltest.v3= v3;
+ evltest.v4= v4;
+
+ evl= G.edvl.first;
+ while(evl) {
+ if(comparevlak(&evltest, evl)) return 1;
+ evl= evl->next;
+ }
+ return 0;
+}
+
+
+static int vlakselectedOR(EditVlak *evl, int flag)
+{
+
+ if(evl->v1->f & flag) return 1;
+ if(evl->v2->f & flag) return 1;
+ if(evl->v3->f & flag) return 1;
+ if(evl->v4 && (evl->v4->f & 1)) return 1;
+ return 0;
+}
+
+int vlakselectedAND(EditVlak *evl, int flag)
+{
+ if(evl->v1->f & flag) {
+ if(evl->v2->f & flag) {
+ if(evl->v3->f & flag) {
+ if(evl->v4) {
+ if(evl->v4->f & flag) return 1;
+ }
+ else return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+void recalc_editnormals(void)
+{
+ EditVlak *evl;
+
+ evl= G.edvl.first;
+ while(evl) {
+ if(evl->v4) CalcNormFloat4(evl->v1->co, evl->v2->co, evl->v3->co, evl->v4->co, evl->n);
+ else CalcNormFloat(evl->v1->co, evl->v2->co, evl->v3->co, evl->n);
+ evl= evl->next;
+ }
+}
+
+static void flipvlak(EditVlak *evl)
+{
+ if(evl->v4) {
+ SWAP(EditVert *, evl->v2, evl->v4);
+ SWAP(EditEdge *, evl->e1, evl->e4);
+ SWAP(EditEdge *, evl->e2, evl->e3);
+ SWAP(unsigned int, evl->col[1], evl->col[3]);
+ if(evl->tface) {
+ SWAP(float, evl->uv[1][0], evl->uv[3][0]);
+ SWAP(float, evl->uv[1][1], evl->uv[3][1]);
+ }
+ }
+ else {
+ SWAP(EditVert *, evl->v2, evl->v3);
+ SWAP(EditEdge *, evl->e1, evl->e3);
+ SWAP(unsigned int, evl->col[1], evl->col[2]);
+ evl->e2->dir= 1-evl->e2->dir;
+ if(evl->tface) {
+ SWAP(float, evl->uv[1][0], evl->uv[2][0]);
+ SWAP(float, evl->uv[1][1], evl->uv[2][1]);
+ }
+ }
+ if(evl->v4) CalcNormFloat4(evl->v1->co, evl->v2->co, evl->v3->co, evl->v4->co, evl->n);
+ else CalcNormFloat(evl->v1->co, evl->v2->co, evl->v3->co, evl->n);
+}
+
+
+void flip_editnormals(void)
+{
+ EditVlak *evl;
+
+ evl= G.edvl.first;
+ while(evl) {
+ if( vlakselectedAND(evl, 1) ) {
+ flipvlak(evl);
+ }
+ evl= evl->next;
+ }
+}
+
+/* ************************ IN & OUT ***************************** */
+
+static void edge_normal_compare(EditEdge *eed, EditVlak *evl1)
+{
+ EditVlak *evl2;
+ float cent1[3], cent2[3];
+ float inp;
+
+ evl2= (EditVlak *)eed->vn;
+ if(evl1==evl2) return;
+
+ inp= evl1->n[0]*evl2->n[0] + evl1->n[1]*evl2->n[1] + evl1->n[2]*evl2->n[2];
+ if(inp<0.999 && inp >-0.999) eed->f= 1;
+
+ if(evl1->v4) CalcCent4f(cent1, evl1->v1->co, evl1->v2->co, evl1->v3->co, evl1->v4->co);
+ else CalcCent3f(cent1, evl1->v1->co, evl1->v2->co, evl1->v3->co);
+ if(evl2->v4) CalcCent4f(cent2, evl2->v1->co, evl2->v2->co, evl2->v3->co, evl2->v4->co);
+ else CalcCent3f(cent2, evl2->v1->co, evl2->v2->co, evl2->v3->co);
+
+ VecSubf(cent1, cent2, cent1);
+ Normalise(cent1);
+ inp= cent1[0]*evl1->n[0] + cent1[1]*evl1->n[1] + cent1[2]*evl1->n[2];
+
+ if(inp < -0.001 ) eed->f1= 1;
+}
+
+static void edge_drawflags(void)
+{
+ EditVert *eve;
+ EditEdge *eed, *e1, *e2, *e3, *e4;
+ EditVlak *evl;
+
+ /* - tel aantal keren in vlakken gebruikt: 0 en 1 is tekenen
+ * - edges meer dan 1 keer: in *vn zit pointer naar (eerste) vlak
+ * - loop alle vlakken af, is normaal te afwijkend: tekenen (flag wordt 1)
+ */
+
+ recalc_editnormals();
+
+ /* init */
+ eve= G.edve.first;
+ while(eve) {
+ eve->f1= 1; /* wordt bij test op nul gezet */
+ eve= eve->next;
+ }
+ eed= G.eded.first;
+ while(eed) {
+ eed->f= eed->f1= 0;
+ eed->vn= 0;
+ eed= eed->next;
+ }
+
+ evl= G.edvl.first;
+ while(evl) {
+ e1= evl->e1;
+ e2= evl->e2;
+ e3= evl->e3;
+ e4= evl->e4;
+ if(e1->f<3) e1->f+= 1;
+ if(e2->f<3) e2->f+= 1;
+ if(e3->f<3) e3->f+= 1;
+ if(e4 && e4->f<3) e4->f+= 1;
+
+ if(e1->vn==0) e1->vn= (EditVert *)evl;
+ if(e2->vn==0) e2->vn= (EditVert *)evl;
+ if(e3->vn==0) e3->vn= (EditVert *)evl;
+ if(e4 && e4->vn==0) e4->vn= (EditVert *)evl;
+
+ evl= evl->next;
+ }
+
+ if(G.f & G_ALLEDGES) {
+ evl= G.edvl.first;
+ while(evl) {
+ if(evl->e1->f>=2) evl->e1->f= 1;
+ if(evl->e2->f>=2) evl->e2->f= 1;
+ if(evl->e3->f>=2) evl->e3->f= 1;
+ if(evl->e4 && evl->e4->f>=2) evl->e4->f= 1;
+
+ evl= evl->next;
+ }
+ }
+ else {
+
+ /* single-edges afvangen voor cylinder flag */
+
+ eed= G.eded.first;
+ while(eed) {
+ if(eed->f==1) eed->f1= 1;
+ eed= eed->next;
+ }
+
+ /* alle vlakken, alle edges met flag==2: vergelijk normaal */
+ evl= G.edvl.first;
+ while(evl) {
+ if(evl->e1->f==2) edge_normal_compare(evl->e1, evl);
+ if(evl->e2->f==2) edge_normal_compare(evl->e2, evl);
+ if(evl->e3->f==2) edge_normal_compare(evl->e3, evl);
+ if(evl->e4 && evl->e4->f==2) edge_normal_compare(evl->e4, evl);
+
+ evl= evl->next;
+ }
+
+ /* sphere collision flag */
+
+ eed= G.eded.first;
+ while(eed) {
+ if(eed->f1!=1) {
+ eed->v1->f1= eed->v2->f1= 0;
+ }
+ eed= eed->next;
+ }
+
+ }
+}
+
+static int contrpuntnorm(float *n, float *puno)
+{
+ float inp;
+
+ inp= n[0]*puno[0]+n[1]*puno[1]+n[2]*puno[2];
+
+ /* angles 90 degrees: dont flip */
+ if(inp> -0.000001) return 0;
+
+ return 1;
+}
+
+void vertexnormals(int testflip)
+{
+ Mesh *me;
+ EditVert *eve;
+ EditVlak *evl;
+ float n1[3], n2[3], n3[3], n4[3], co[4], fac1, fac2, fac3, fac4, *temp;
+ float *f1, *f2, *f3, *f4, xn, yn, zn;
+ float opp, len;
+
+ if(G.obedit && G.obedit->type==OB_MESH) {
+ me= G.obedit->data;
+ if((me->flag & ME_TWOSIDED)==0) testflip= 0;
+ }
+
+ if(G.totvert==0) return;
+
+ if(G.totface==0) {
+ /* namaak puno's voor halopuno! */
+ eve= G.edve.first;
+ while(eve) {
+ VECCOPY(eve->no, eve->co);
+ Normalise( (float *)eve->no);
+ eve= eve->next;
+ }
+ return;
+ }
+
+ /* clear normals */
+ eve= G.edve.first;
+ while(eve) {
+ eve->no[0]= eve->no[1]= eve->no[2]= 0.0;
+ eve= eve->next;
+ }
+
+ /* berekenen cos hoeken en oppervlakte en optellen bij puno */
+ evl= G.edvl.first;
+ while(evl) {
+ VecSubf(n1, evl->v2->co, evl->v1->co);
+ VecSubf(n2, evl->v3->co, evl->v2->co);
+ Normalise(n1);
+ Normalise(n2);
+
+ if(evl->v4==0) {
+ VecSubf(n3, evl->v1->co, evl->v3->co);
+ Normalise(n3);
+
+ /* opp= AreaT3Dfl(evl->v1->co, evl->v2->co, evl->v3->co); */
+ /* if(opp!=0.0) opp=1.0/opp; */
+ /* opp= sqrt(opp); */
+ /* for smooth subdivide...*/
+ opp= 1.0;
+ co[0]= opp*saacos(-n3[0]*n1[0]-n3[1]*n1[1]-n3[2]*n1[2]);
+ co[1]= opp*saacos(-n1[0]*n2[0]-n1[1]*n2[1]-n1[2]*n2[2]);
+ co[2]= opp*saacos(-n2[0]*n3[0]-n2[1]*n3[1]-n2[2]*n3[2]);
+
+ }
+ else {
+ VecSubf(n3, evl->v4->co, evl->v3->co);
+ VecSubf(n4, evl->v1->co, evl->v4->co);
+ Normalise(n3);
+ Normalise(n4);
+
+ /* opp= AreaQ3Dfl(evl->v1->co, evl->v2->co, evl->v3->co, evl->v4->co); */
+ /* if(opp!=0.0) opp=1.0/opp; */
+ /* opp= sqrt(opp); */
+ /* for smooth subdivide...*/
+ opp= 1.0;
+ co[0]= opp*saacos(-n4[0]*n1[0]-n4[1]*n1[1]-n4[2]*n1[2]);
+ co[1]= opp*saacos(-n1[0]*n2[0]-n1[1]*n2[1]-n1[2]*n2[2]);
+ co[2]= opp*saacos(-n2[0]*n3[0]-n2[1]*n3[1]-n2[2]*n3[2]);
+ co[3]= opp*saacos(-n3[0]*n4[0]-n3[1]*n4[1]-n3[2]*n4[2]);
+ }
+
+ temp= evl->v1->no;
+ if(testflip && contrpuntnorm(evl->n, temp) ) co[0]= -co[0];
+ temp[0]+= co[0]*evl->n[0];
+ temp[1]+= co[0]*evl->n[1];
+ temp[2]+= co[0]*evl->n[2];
+
+ temp= evl->v2->no;
+ if(testflip && contrpuntnorm(evl->n, temp) ) co[1]= -co[1];
+ temp[0]+= co[1]*evl->n[0];
+ temp[1]+= co[1]*evl->n[1];
+ temp[2]+= co[1]*evl->n[2];
+
+ temp= evl->v3->no;
+ if(testflip && contrpuntnorm(evl->n, temp) ) co[2]= -co[2];
+ temp[0]+= co[2]*evl->n[0];
+ temp[1]+= co[2]*evl->n[1];
+ temp[2]+= co[2]*evl->n[2];
+
+ if(evl->v4) {
+ temp= evl->v4->no;
+ if(testflip && contrpuntnorm(evl->n, temp) ) co[3]= -co[3];
+ temp[0]+= co[3]*evl->n[0];
+ temp[1]+= co[3]*evl->n[1];
+ temp[2]+= co[3]*evl->n[2];
+ }
+
+ evl= evl->next;
+ }
+
+ /* normaliseren puntnormalen */
+ eve= G.edve.first;
+ while(eve) {
+ len= Normalise(eve->no);
+ if(len==0.0) {
+ VECCOPY(eve->no, eve->co);
+ Normalise( eve->no);
+ }
+ eve= eve->next;
+ }
+
+ /* puntnormaal omklap-vlaggen voor bij shade */
+ evl= G.edvl.first;
+ while(evl) {
+ evl->f=0;
+
+ if(testflip) {
+ f1= evl->v1->no;
+ f2= evl->v2->no;
+ f3= evl->v3->no;
+
+ fac1= evl->n[0]*f1[0] + evl->n[1]*f1[1] + evl->n[2]*f1[2];
+ if(fac1<0.0) {
+ evl->f = ME_FLIPV1;
+ }
+ fac2= evl->n[0]*f2[0] + evl->n[1]*f2[1] + evl->n[2]*f2[2];
+ if(fac2<0.0) {
+ evl->f += ME_FLIPV2;
+ }
+ fac3= evl->n[0]*f3[0] + evl->n[1]*f3[1] + evl->n[2]*f3[2];
+ if(fac3<0.0) {
+ evl->f += ME_FLIPV3;
+ }
+ if(evl->v4) {
+ f4= evl->v4->no;
+ fac4= evl->n[0]*f4[0] + evl->n[1]*f4[1] + evl->n[2]*f4[2];
+ if(fac4<0.0) {
+ evl->f += ME_FLIPV4;
+ }
+ }
+ }
+ /* proj voor cubemap! */
+ xn= fabs(evl->n[0]);
+ yn= fabs(evl->n[1]);
+ zn= fabs(evl->n[2]);
+
+ if(zn>xn && zn>yn) evl->f += ME_PROJXY;
+ else if(yn>xn && yn>zn) evl->f += ME_PROJXZ;
+ else evl->f += ME_PROJYZ;
+
+ evl= evl->next;
+ }
+}
+
+void free_editMesh(void)
+{
+
+// if(G.edve.first) BLI_freelist(&G.edve);
+ if(G.edve.first) free_editverts(&G.edve);
+ if(G.eded.first) BLI_freelist(&G.eded);
+ if(G.edvl.first) freevlaklist(&G.edvl);
+ free_hashedgetab();
+ G.totvert= G.totface= 0;
+}
+
+static void free_editverts(ListBase *edve) {
+#ifdef __NLA
+ EditVert *eve;
+#endif
+
+ if (!edve)
+ return;
+
+ if (!edve->first)
+ return;
+
+#ifdef __NLA
+ for (eve= edve->first; eve; eve=eve->next){
+ if (eve->dw)
+ MEM_freeN (eve->dw);
+ }
+#endif
+
+ BLI_freelist (edve);
+
+}
+
+static void free_editvert (EditVert *eve)
+{
+#ifdef __NLA
+ if (eve->dw)
+ MEM_freeN (eve->dw);
+#endif
+ free (eve);
+}
+
+void make_editMesh(void)
+{
+ Mesh *me;
+ MFace *mface;
+ TFace *tface;
+ MVert *mvert;
+ KeyBlock *actkey=0;
+ EditVert *eve, **evlist, *eve1, *eve2, *eve3, *eve4;
+ EditVlak *evl;
+ int tot, a;
+
+ if(G.obedit==0) return;
+
+ /* ivm reload */
+ free_editMesh();
+
+ me= get_mesh(G.obedit);
+ G.totvert= tot= me->totvert;
+
+ if(tot==0) {
+ countall();
+ return;
+ }
+
+ waitcursor(1);
+
+ /* keys? */
+ if(me->key) {
+ actkey= me->key->block.first;
+ while(actkey) {
+ if(actkey->flag & SELECT) break;
+ actkey= actkey->next;
+ }
+ }
+
+ if(actkey) {
+ key_to_mesh(actkey, me);
+ tot= actkey->totelem;
+ }
+
+ /* editverts aanmaken */
+ mvert= me->mvert;
+
+ evlist= (EditVert **)MEM_mallocN(tot*sizeof(void *),"evlist");
+ for(a=0; a<tot; a++, mvert++) {
+ eve= addvertlist(mvert->co);
+ evlist[a]= eve;
+ eve->no[0]= mvert->no[0]/32767.0;
+ eve->no[1]= mvert->no[1]/32767.0;
+ eve->no[2]= mvert->no[2]/32767.0;
+#ifdef __NLA
+
+ /* OLD VERSION */
+ /*
+ eve->totweight = mvert->totweight;
+ if (mvert->dw){
+ eve->dw = BLI_callocN (sizeof(MDeformWeight) * mvert->totweight, "deformWeight");
+ memcpy (eve->dw, mvert->dw, sizeof(MDeformWeight) * mvert->totweight);
+ }
+ */
+
+ /* NEW VERSION */
+ if (me->dvert){
+ eve->totweight = me->dvert[a].totweight;
+ if (me->dvert[a].dw){
+ eve->dw = MEM_callocN (sizeof(MDeformWeight) * me->dvert[a].totweight, "deformWeight");
+ memcpy (eve->dw, me->dvert[a].dw, sizeof(MDeformWeight) * me->dvert[a].totweight);
+ }
+ }
+
+#endif
+ }
+
+ if(actkey && actkey->totelem!=me->totvert);
+ else {
+ unsigned int *mcol;
+
+ /* edges en vlakken maken */
+ mface= me->mface;
+ tface= me->tface;
+ mcol= (unsigned int *)me->mcol;
+
+ for(a=0; a<me->totface; a++, mface++) {
+ eve1= evlist[mface->v1];
+ eve2= evlist[mface->v2];
+ if(mface->v3) eve3= evlist[mface->v3]; else eve3= 0;
+ if(mface->v4) eve4= evlist[mface->v4]; else eve4= 0;
+
+ evl= addvlaklist(eve1, eve2, eve3, eve4, NULL);
+
+ if(evl) {
+ if(mcol) memcpy(evl->col, mcol, 4*sizeof(int));
+
+ if(me->tface) {
+ memcpy(evl->col, tface->col, sizeof(tface->col));
+ memcpy(evl->uv, tface->uv, sizeof(tface->uv));
+
+ if( tface->flag & TF_SELECT) {
+ if(G.f & G_FACESELECT) {
+ eve1->f |= 1;
+ eve2->f |= 1;
+ if(eve3) eve3->f |= 1;
+ if(eve4) eve4->f |= 1;
+ }
+ }
+ }
+
+ evl->mat_nr= mface->mat_nr;
+ evl->flag= mface->flag;
+ evl->tface= tface;
+ }
+
+ if(me->tface) tface++;
+ if(mcol) mcol+=4;
+ }
+ }
+ MEM_freeN(evlist);
+
+ countall();
+
+ if (mesh_uses_displist(me))
+ makeDispList(G.obedit);
+
+ waitcursor(0);
+}
+
+/** Rotates MFace and UVFace vertices in case the last
+ * vertex index is = 0.
+ * This function is a hack and may only be called in the
+ * conversion from EditMesh to Mesh data.
+ * This function is similar to test_index_mface in
+ * blenkernel/intern/mesh.c.
+ * To not clutter the blenkernel code with more bad level
+ * calls/structures, this function resides here.
+ */
+
+
+static void fix_faceindices(MFace *mface, EditVlak *evl, int nr)
+{
+ int a;
+ float tmpuv[2];
+ unsigned int tmpcol;
+
+/*
+mface = ((MFace *) me->mface) + index;
+ tface = ((TFace *) me->tface) + index;
+
+*/
+
+ /* first test if the face is legal */
+
+ if(mface->v3 && mface->v3==mface->v4) {
+ mface->v4= 0;
+ nr--;
+ }
+ if(mface->v2 && mface->v2==mface->v3) {
+ mface->v3= mface->v4;
+ mface->v4= 0;
+ nr--;
+ }
+ if(mface->v1==mface->v2) {
+ mface->v2= mface->v3;
+ mface->v3= mface->v4;
+ mface->v4= 0;
+ nr--;
+ }
+
+ /* voorkom dat een nul op de verkeerde plek staat */
+ if(nr==2) {
+ if(mface->v2==0) SWAP(int, mface->v1, mface->v2);
+ }
+ else if(nr==3) {
+ if(mface->v3==0) {
+ SWAP(int, mface->v1, mface->v2);
+ SWAP(int, mface->v2, mface->v3);
+ /* rotate face UV coordinates, too */
+ UVCOPY(tmpuv, evl->uv[0]);
+ UVCOPY(evl->uv[0], evl->uv[1]);
+ UVCOPY(evl->uv[1], evl->uv[2]);
+ UVCOPY(evl->uv[2], tmpuv);
+ /* same with vertex colours */
+ tmpcol = evl->col[0];
+ evl->col[0] = evl->col[1];
+ evl->col[1] = evl->col[2];
+ evl->col[2] = tmpcol;
+
+
+ a= mface->edcode;
+ mface->edcode= 0;
+ if(a & ME_V1V2) mface->edcode |= ME_V3V1;
+ if(a & ME_V2V3) mface->edcode |= ME_V1V2;
+ if(a & ME_V3V1) mface->edcode |= ME_V2V3;
+
+ a= mface->puno;
+ mface->puno &= ~15;
+ if(a & ME_FLIPV1) mface->puno |= ME_FLIPV2;
+ if(a & ME_FLIPV2) mface->puno |= ME_FLIPV3;
+ if(a & ME_FLIPV3) mface->puno |= ME_FLIPV1;
+ }
+ }
+ else if(nr==4) {
+ if(mface->v3==0 || mface->v4==0) {
+ SWAP(int, mface->v1, mface->v3);
+ SWAP(int, mface->v2, mface->v4);
+ /* swap UV coordinates */
+ UVCOPY(tmpuv, evl->uv[0]);
+ UVCOPY(evl->uv[0], evl->uv[2]);
+ UVCOPY(evl->uv[2], tmpuv);
+ UVCOPY(tmpuv, evl->uv[1]);
+ UVCOPY(evl->uv[1], evl->uv[3]);
+ UVCOPY(evl->uv[3], tmpuv);
+ /* swap vertex colours */
+ tmpcol = evl->col[0];
+ evl->col[0] = evl->col[2];
+ evl->col[2] = tmpcol;
+ tmpcol = evl->col[1];
+ evl->col[1] = evl->col[3];
+ evl->col[3] = tmpcol;
+
+ a= mface->edcode;
+ mface->edcode= 0;
+ if(a & ME_V1V2) mface->edcode |= ME_V3V4;
+ if(a & ME_V2V3) mface->edcode |= ME_V2V3;
+ if(a & ME_V3V4) mface->edcode |= ME_V1V2;
+ if(a & ME_V4V1) mface->edcode |= ME_V4V1;
+
+ a= mface->puno;
+ mface->puno &= ~15;
+ if(a & ME_FLIPV1) mface->puno |= ME_FLIPV3;
+ if(a & ME_FLIPV2) mface->puno |= ME_FLIPV4;
+ if(a & ME_FLIPV3) mface->puno |= ME_FLIPV1;
+ if(a & ME_FLIPV4) mface->puno |= ME_FLIPV2;
+ }
+ }
+
+}
+
+
+
+/* load from EditMode to Mesh */
+
+void load_editMesh(void)
+{
+ Mesh *me;
+ MFace *mface;
+ MVert *mvert;
+ MSticky *ms;
+ KeyBlock *actkey=0;
+ EditVert *eve;
+ EditVlak *evl;
+ EditEdge *eed;
+ float *fp, nor[3];
+ int i, a, ototvert;
+#ifdef __NLA
+ MDeformVert *dvert;
+ int usedDvert = 0;
+#endif
+
+ waitcursor(1);
+ countall();
+
+ me= get_mesh(G.obedit);
+
+ ototvert= me->totvert;
+
+ /* zijn er keys? */
+ if(me->key) {
+ actkey= me->key->block.first;
+ while(actkey) {
+ if(actkey->flag & SELECT) break;
+ actkey= actkey->next;
+ }
+ }
+
+
+ if(actkey && me->key->refkey!=actkey) {
+ /* aktieve key && niet de refkey: alleen vertices */
+
+ if(G.totvert) {
+ if(actkey->data) MEM_freeN(actkey->data);
+
+ fp=actkey->data= MEM_callocN(me->key->elemsize*G.totvert, "actkey->data");
+ actkey->totelem= G.totvert;
+
+ eve= G.edve.first;
+ while(eve) {
+ VECCOPY(fp, eve->co);
+ fp+= 3;
+ eve= eve->next;
+ }
+ }
+ }
+ else if(me->key && actkey==0) {
+ /* er zijn keys, alleen veranderingen in mverts schrijven */
+ /* als aantal vertices verschillen, beetje onvoorspelbaar */
+
+ eve= G.edve.first;
+ mvert= me->mvert;
+ for(a=0; a<me->totvert; a++, mvert++) {
+ VECCOPY(mvert->co, eve->co);
+ eve= eve->next;
+ if(eve==0) break;
+ }
+ }
+ else {
+ /* als er keys zijn: de refkey, anders gewoon de me */
+
+ /* deze telt ook of edges niet in vlakken zitten: */
+ /* eed->f==0 niet in vlak, f==1 is tekenen */
+ /* eed->f1 : flag voor dynaface (cylindertest) */
+ /* eve->f1 : flag voor dynaface (sphere test) */
+ edge_drawflags();
+
+ /* LET OP: op evl->f de punoflag */
+ vertexnormals( (me->flag & ME_NOPUNOFLIP)==0 );
+
+ eed= G.eded.first;
+ while(eed) {
+ if(eed->f==0) G.totface++;
+ eed= eed->next;
+ }
+
+ /* nieuw Face blok */
+ if(G.totface==0) mface= 0;
+ else mface= MEM_callocN(G.totface*sizeof(MFace), "loadeditMesh1");
+ /* nieuw Vertex blok */
+ if(G.totvert==0) mvert= 0;
+ else mvert= MEM_callocN(G.totvert*sizeof(MVert), "loadeditMesh2");
+
+#ifdef __NLA
+ if (G.totvert==0) dvert=0;
+ else dvert = MEM_callocN(G.totvert*sizeof(MDeformVert), "loadeditMesh3");
+
+ if (me->dvert) free_dverts(me->dvert, me->totvert);
+ me->dvert=dvert;
+#endif
+ if(me->mvert) MEM_freeN(me->mvert);
+ me->mvert= mvert;
+
+ if(me->mface) MEM_freeN(me->mface);
+ me->mface= mface;
+ me->totvert= G.totvert;
+ me->totface= G.totface;
+
+ /* de vertices, gebruik ->vn als teller */
+ eve= G.edve.first;
+ a=0;
+
+
+
+ while(eve) {
+ VECCOPY(mvert->co, eve->co);
+ mvert->mat_nr= 255; /* waarvoor ook al weer, haloos? */
+
+ /* puno */
+ VECCOPY(nor, eve->no);
+ VecMulf(nor, 32767.0);
+ VECCOPY(mvert->no, nor);
+#ifdef __NLA
+/* OLD VERSION */
+/* mvert->totweight = eve->totweight;
+ if (eve->dw){
+ int cv;
+ mvert->dw = BLI_callocN (sizeof(MDeformWeight)*eve->totweight, "deformWeight");
+ memcpy (mvert->dw, eve->dw, sizeof(MDeformWeight)*eve->totweight);
+ }
+*/
+ /* NEW VERSION */
+ if (dvert){
+ dvert->totweight=eve->totweight;
+ if (eve->dw){
+ dvert->dw = MEM_callocN (sizeof(MDeformWeight)*eve->totweight, "deformWeight");
+ memcpy (dvert->dw, eve->dw, sizeof(MDeformWeight)*eve->totweight);
+ usedDvert++;
+ }
+ }
+#endif
+
+ eve->vn= (EditVert *)(long)(a++); /* teller */
+
+ mvert->flag= 0;
+ if(eve->f1==1) mvert->flag |= ME_SPHERETEST;
+
+ eve= eve->next;
+ mvert++;
+#ifdef __NLA
+ dvert++;
+#endif
+ }
+
+#ifdef __NLA
+ /* If we didn't actually need the dverts, get rid of them */
+ if (!usedDvert){
+ free_dverts(me->dvert, G.totvert);
+ me->dvert=NULL;
+ }
+#endif
+
+ /* de vlakken */
+ evl= G.edvl.first;
+ i = 0;
+ while(evl) {
+ mface= &((MFace *) me->mface)[i];
+
+ mface->v1= (unsigned int) evl->v1->vn;
+ mface->v2= (unsigned int) evl->v2->vn;
+ mface->v3= (unsigned int) evl->v3->vn;
+ if(evl->v4) mface->v4= (unsigned int) evl->v4->vn;
+
+ mface->mat_nr= evl->mat_nr;
+ mface->puno= evl->f;
+ mface->flag= evl->flag;
+
+ /* mat_nr in vertex */
+ if(me->totcol>1) {
+ mvert= me->mvert+mface->v1;
+ if(mvert->mat_nr == 255) mvert->mat_nr= mface->mat_nr;
+ mvert= me->mvert+mface->v2;
+ if(mvert->mat_nr == 255) mvert->mat_nr= mface->mat_nr;
+ mvert= me->mvert+mface->v3;
+ if(mvert->mat_nr == 255) mvert->mat_nr= mface->mat_nr;
+ if(mface->v4) {
+ mvert= me->mvert+mface->v4;
+ if(mvert->mat_nr == 255) mvert->mat_nr= mface->mat_nr;
+ }
+ }
+
+ /* dyna cilinder flag minder kritisch testen: 'dubbel' in vlakken laten zitten.
+ * gaat anders fout bij scherpe hoeken (inpspeed voor een wel, ander niet!)
+ * Mogelijk oplossen door volgorde aan te passen: sphere-cyl-face. Kost te veel?
+ */
+
+ /* letop: evl->e1->f==0 is losse edge */
+
+ if(evl->e1->f==1) {
+ mface->edcode |= ME_V1V2;
+ evl->e1->f= 2;
+ }
+ if(evl->e2->f==1) {
+ mface->edcode |= ME_V2V3;
+ evl->e2->f= 2;
+ }
+ if(evl->e3->f==1) {
+ if(evl->v4) {
+ mface->edcode |= ME_V3V4;
+ }
+ else {
+ mface->edcode |= ME_V3V1;
+ }
+ evl->e3->f= 2;
+ }
+ if(evl->e4 && evl->e4->f==1) {
+ mface->edcode |= ME_V4V1;
+ evl->e4->f= 2;
+ }
+
+ /* geen index '0' op plek 3 of 4 */
+ if(evl->v4) fix_faceindices(mface, evl, 4);
+ else fix_faceindices(mface, evl, 3);
+
+ i++;
+ evl= evl->next;
+ }
+
+ /* losse edges als vlak toevoegen */
+ eed= G.eded.first;
+ while(eed) {
+ if( eed->f==0 ) {
+ mface= &((MFace *) me->mface)[i];
+ mface->v1= (unsigned int) eed->v1->vn;
+ mface->v2= (unsigned int) eed->v2->vn;
+ test_index_mface(mface, 2);
+ mface->edcode= ME_V1V2;
+ i++;
+ }
+ eed= eed->next;
+ }
+
+ tex_space_mesh(me);
+ if(actkey) mesh_to_key(me, actkey);
+
+ /* texmesh: ahv ->tface alles opnieuw maken */
+ if(me->tface && me->totface) {
+ TFace *tfn, *tf;
+
+ tf=tfn= MEM_callocN(sizeof(TFace)*me->totface, "tface");
+ evl= G.edvl.first;
+ while(evl) {
+
+ if(evl->tface) *tf= *(evl->tface);
+ else default_tface(tf);
+
+ memcpy(tf->col, evl->col, sizeof(tf->col));
+ memcpy(tf->uv, evl->uv, sizeof(tf->uv));
+
+ if(G.f & G_FACESELECT) {
+ if( vlakselectedAND(evl, 1) ) tf->flag |= TF_SELECT;
+ else tf->flag &= ~TF_SELECT;
+ }
+
+ /* sometimes editmode doesn't free (before render) */
+ evl->tface= tf;
+
+ tf++;
+ evl= evl->next;
+ }
+
+ MEM_freeN(me->tface);
+ me->tface= tfn;
+ }
+ else if(me->tface) {
+ /* freeN(me->tface); */
+ /* me->tface= 0; */
+ }
+
+ /* mcol: ahv indexnrs opnieuw maken */
+ if(me->mcol && me->totface) {
+ unsigned int *mcn, *mc;
+
+ mc=mcn= MEM_mallocN(4*sizeof(int)*me->totface, "mcol");
+ evl= G.edvl.first;
+ while(evl) {
+
+ memcpy(mc, evl->col, 4*sizeof(int));
+
+ mc+=4;
+ evl= evl->next;
+ }
+
+ MEM_freeN(me->mcol);
+ me->mcol= (MCol *)mcn;
+ }
+ else if(me->mcol) {
+ MEM_freeN(me->mcol);
+ me->mcol= 0;
+ }
+ }
+
+ if(actkey) do_spec_key(me->key);
+
+ /* voor zekerheid: ->vn pointers wissen */
+ eve= G.edve.first;
+ while(eve) {
+ eve->vn= 0;
+ eve= eve->next;
+ }
+
+ /* displisten van alle users, ook deze */
+ freedisplist(&me->disp);
+ freedisplist(&G.obedit->disp);
+
+ /* sticky */
+ if(me->msticky) {
+ if (ototvert<me->totvert) {
+ ms= MEM_callocN(me->totvert*sizeof(MSticky), "msticky");
+ memcpy(ms, me->msticky, ototvert*sizeof(MSticky));
+ MEM_freeN(me->msticky);
+ me->msticky= ms;
+ error("Sticky was too small");
+ }
+ }
+ waitcursor(0);
+}
+
+
+void remake_editMesh(void)
+{
+
+ if(okee("Reload Original data")==0) return;
+
+ make_editMesh();
+ allqueue(REDRAWVIEW3D, 0);
+ makeDispList(G.obedit);
+}
+
+/* ********************* TOOLS ********************* */
+
+
+
+void make_sticky(void)
+{
+ Object *ob;
+ Base *base;
+ MVert *mvert;
+ Mesh *me;
+ MSticky *ms;
+ float ho[4], mat[4][4];
+ int a;
+
+ if(G.scene->camera==0) return;
+
+ if(G.obedit) {
+ error("Unable to perform function in EditMode");
+ return;
+ }
+ base= FIRSTBASE;
+ while(base) {
+ if TESTBASELIB(base) {
+ if(base->object->type==OB_MESH) {
+ ob= base->object;
+
+ me= ob->data;
+ mvert= me->mvert;
+ if(me->msticky) MEM_freeN(me->msticky);
+ me->msticky= MEM_mallocN(me->totvert*sizeof(MSticky), "sticky");
+
+ /* stukje roteerscene */
+ R.r= G.scene->r;
+ R.r.xsch= (R.r.size*R.r.xsch)/100;
+ R.r.ysch= (R.r.size*R.r.ysch)/100;
+
+ R.afmx= R.r.xsch/2;
+ R.afmy= R.r.ysch/2;
+
+ R.ycor= ( (float)R.r.yasp)/( (float)R.r.xasp);
+
+ R.rectx= R.r.xsch;
+ R.recty= R.r.ysch;
+ R.xstart= -R.afmx;
+ R.ystart= -R.afmy;
+ R.xend= R.xstart+R.rectx-1;
+ R.yend= R.ystart+R.recty-1;
+
+ where_is_object(G.scene->camera);
+ Mat4CpyMat4(R.viewinv, G.scene->camera->obmat);
+ Mat4Ortho(R.viewinv);
+ Mat4Invert(R.viewmat, R.viewinv);
+
+ RE_setwindowclip(1, -1);
+
+ where_is_object(ob);
+ Mat4MulMat4(mat, ob->obmat, R.viewmat);
+
+ ms= me->msticky;
+ for(a=0; a<me->totvert; a++, ms++, mvert++) {
+ VECCOPY(ho, mvert->co);
+ Mat4MulVecfl(mat, ho);
+ RE_projectverto(ho, ho);
+ ms->co[0]= ho[0]/ho[3];
+ ms->co[1]= ho[1]/ho[3];
+ }
+ }
+ }
+ base= base->next;
+ }
+ allqueue(REDRAWBUTSEDIT, 0);
+}
+
+void fasterdraw(void)
+{
+ Base *base;
+ Mesh *me;
+ MFace *mface;
+ int toggle, a;
+
+ if(G.obedit) return;
+
+ /* vlaggen resetten */
+ me= G.main->mesh.first;
+ while(me) {
+ me->flag &= ~ME_ISDONE;
+ me= me->id.next;
+ }
+
+ base= FIRSTBASE;
+ while(base) {
+ if( TESTBASELIB(base) && (base->object->type==OB_MESH)) {
+ me= base->object->data;
+ if(me->id.lib==0 && (me->flag & ME_ISDONE)==0) {
+ me->flag |= ME_ISDONE;
+ mface= me->mface;
+ toggle= 0;
+ for(a=0; a<me->totface; a++) {
+ if( (mface->edcode & ME_V1V2) && ( (toggle++) & 1) ) {
+ mface->edcode-= ME_V1V2;
+ }
+ if( (mface->edcode & ME_V2V3) && ( (toggle++) & 1)) {
+ mface->edcode-= ME_V2V3;
+ }
+ if( (mface->edcode & ME_V3V1) && ( (toggle++) & 1)) {
+ mface->edcode-= ME_V3V1;
+ }
+ if( (mface->edcode & ME_V4V1) && ( (toggle++) & 1)) {
+ mface->edcode-= ME_V4V1;
+ }
+ if( (mface->edcode & ME_V3V4) && ( (toggle++) & 1)) {
+ mface->edcode-= ME_V3V4;
+ }
+ mface++;
+ }
+ }
+ }
+ base= base->next;
+ }
+
+ /* belangrijk?: vlaggen weer resetten */
+ me= G.main->mesh.first;
+ while(me) {
+ me->flag &= ~ME_ISDONE;
+ me= me->id.next;
+ }
+
+ allqueue(REDRAWVIEW3D, 0);
+}
+
+void slowerdraw(void) /* reset fasterdraw */
+{
+ Base *base;
+ Mesh *me;
+ MFace *mface;
+ int a;
+
+ if(G.obedit) return;
+
+ base= FIRSTBASE;
+ while(base) {
+ if( TESTBASELIB(base) && (base->object->type==OB_MESH)) {
+ me= base->object->data;
+ if(me->id.lib==0) {
+
+ mface= me->mface;
+
+ for(a=0; a<me->totface; a++) {
+
+ mface->edcode |= ME_V1V2|ME_V2V3;
+ mface++;
+ }
+ }
+ }
+ base= base->next;
+ }
+
+ allqueue(REDRAWVIEW3D, 0);
+}
+
+
+void convert_to_triface(int all)
+{
+ EditVlak *evl, *evln, *next;
+
+ evl= G.edvl.first;
+ while(evl) {
+ next= evl->next;
+ if(evl->v4) {
+ if(all || vlakselectedAND(evl, 1) ) {
+
+ evln= addvlaklist(evl->v1, evl->v2, evl->v3, 0, evl);
+ evln= addvlaklist(evl->v1, evl->v3, evl->v4, 0, evl);
+
+ if(evl->tface) {
+ evln->uv[1][0]= evln->uv[2][0];
+ evln->uv[1][1]= evln->uv[2][1];
+ evln->uv[2][0]= evln->uv[3][0];
+ evln->uv[2][1]= evln->uv[3][1];
+ }
+
+ evln->col[1]= evln->col[2];
+ evln->col[2]= evln->col[3];
+
+ BLI_remlink(&G.edvl, evl);
+ freevlak(evl);
+ }
+ }
+ evl= next;
+ }
+
+}
+
+
+void deselectall_mesh(void) /* toggle */
+{
+ EditVert *eve;
+ int a;
+
+ if(G.obedit->lay & G.vd->lay) {
+ a= 0;
+ eve= G.edve.first;
+ while(eve) {
+ if(eve->f & 1) {
+ a= 1;
+ break;
+ }
+ eve= eve->next;
+ }
+ eve= G.edve.first;
+ while(eve) {
+ if(eve->h==0) {
+ if(a) eve->f&= -2;
+ else eve->f|= 1;
+ }
+ eve= eve->next;
+ }
+ tekenvertices_ext(a==0);
+ }
+ countall();
+}
+
+
+void righthandfaces(int select) /* maakt vlakken rechtsdraaiend */
+{
+ EditEdge *eed, *ed1, *ed2, *ed3, *ed4;
+ EditVlak *evl, *startvl;
+ float maxx, nor[3], cent[3];
+ int totsel, found, foundone, direct, turn;
+
+ /* op basis selectconnected om losse objecten te onderscheiden */
+
+ /* tel per edge hoeveel vlakken het heeft */
+
+ /* vind het meest linkse, voorste, bovenste vlak */
+
+ /* zet normaal naar buiten en de eerste richtings vlaggen in de edges */
+
+ /* loop object af en zet richtingen / richtingsvlaggen: alleen bij edges van 1 of 2 vlakken */
+ /* dit is in feit de select connected */
+
+ /* indien nog (selected) vlakken niet gedaan: opnieuw vind de meest linkse ... */
+
+ waitcursor(1);
+
+ eed= G.eded.first;
+ while(eed) {
+ eed->f= 0;
+ eed->f1= 0;
+ eed= eed->next;
+ }
+
+ /* vlakken en edges tellen */
+ totsel= 0;
+ evl= G.edvl.first;
+ while(evl) {
+ if(select==0 || vlakselectedAND(evl, 1) ) {
+ evl->f= 1;
+ totsel++;
+ evl->e1->f1++;
+ evl->e2->f1++;
+ evl->e3->f1++;
+ if(evl->v4) evl->e4->f1++;
+ }
+ else evl->f= 0;
+
+ evl= evl->next;
+ }
+
+ while(totsel>0) {
+ /* van buiten naar binnen */
+
+ evl= G.edvl.first;
+ startvl= 0;
+ maxx= -1.0e10;
+
+ while(evl) {
+ if(evl->f) {
+ CalcCent3f(cent, evl->v1->co, evl->v2->co, evl->v3->co);
+ cent[0]= fabs(cent[0])+fabs(cent[1])+fabs(cent[2]);
+
+ if(cent[0]>maxx) {
+ maxx= cent[0];
+ startvl= evl;
+ }
+ }
+ evl= evl->next;
+ }
+
+ /* eerste vlak goedzetten: normaal berekenen */
+ CalcNormFloat(startvl->v1->co, startvl->v2->co, startvl->v3->co, nor);
+ CalcCent3f(cent, startvl->v1->co, startvl->v2->co, startvl->v3->co);
+
+ /* eerste normaal staat zus of zo */
+ if(select) {
+ if(select==2) {
+ if(cent[0]*nor[0]+cent[1]*nor[1]+cent[2]*nor[2] > 0.0) flipvlak(startvl);
+ }
+ else {
+ if(cent[0]*nor[0]+cent[1]*nor[1]+cent[2]*nor[2] < 0.0) flipvlak(startvl);
+ }
+ }
+ else if(cent[0]*nor[0]+cent[1]*nor[1]+cent[2]*nor[2] < 0.0) flipvlak(startvl);
+
+
+ eed= startvl->e1;
+ if(eed->v1==startvl->v1) eed->f= 1;
+ else eed->f= 2;
+
+ eed= startvl->e2;
+ if(eed->v1==startvl->v2) eed->f= 1;
+ else eed->f= 2;
+
+ eed= startvl->e3;
+ if(eed->v1==startvl->v3) eed->f= 1;
+ else eed->f= 2;
+
+ eed= startvl->e4;
+ if(eed) {
+ if(eed->v1==startvl->v4) eed->f= 1;
+ else eed->f= 2;
+ }
+
+ startvl->f= 0;
+ totsel--;
+
+ /* de normalen testen */
+ found= 1;
+ direct= 1;
+ while(found) {
+ found= 0;
+ if(direct) evl= G.edvl.first;
+ else evl= G.edvl.last;
+ while(evl) {
+ if(evl->f) {
+ turn= 0;
+ foundone= 0;
+
+ ed1= evl->e1;
+ ed2= evl->e2;
+ ed3= evl->e3;
+ ed4= evl->e4;
+
+ if(ed1->f) {
+ if(ed1->v1==evl->v1 && ed1->f==1) turn= 1;
+ if(ed1->v2==evl->v1 && ed1->f==2) turn= 1;
+ foundone= 1;
+ }
+ else if(ed2->f) {
+ if(ed2->v1==evl->v2 && ed2->f==1) turn= 1;
+ if(ed2->v2==evl->v2 && ed2->f==2) turn= 1;
+ foundone= 1;
+ }
+ else if(ed3->f) {
+ if(ed3->v1==evl->v3 && ed3->f==1) turn= 1;
+ if(ed3->v2==evl->v3 && ed3->f==2) turn= 1;
+ foundone= 1;
+ }
+ else if(ed4 && ed4->f) {
+ if(ed4->v1==evl->v4 && ed4->f==1) turn= 1;
+ if(ed4->v2==evl->v4 && ed4->f==2) turn= 1;
+ foundone= 1;
+ }
+
+ if(foundone) {
+ found= 1;
+ totsel--;
+ evl->f= 0;
+
+ if(turn) {
+ if(ed1->v1==evl->v1) ed1->f= 2;
+ else ed1->f= 1;
+ if(ed2->v1==evl->v2) ed2->f= 2;
+ else ed2->f= 1;
+ if(ed3->v1==evl->v3) ed3->f= 2;
+ else ed3->f= 1;
+ if(ed4) {
+ if(ed4->v1==evl->v4) ed4->f= 2;
+ else ed4->f= 1;
+ }
+
+ flipvlak(evl);
+
+ }
+ else {
+ if(ed1->v1== evl->v1) ed1->f= 1;
+ else ed1->f= 2;
+ if(ed2->v1==evl->v2) ed2->f= 1;
+ else ed2->f= 2;
+ if(ed3->v1==evl->v3) ed3->f= 1;
+ else ed3->f= 2;
+ if(ed4) {
+ if(ed4->v1==evl->v4) ed4->f= 1;
+ else ed4->f= 2;
+ }
+ }
+ }
+ }
+ if(direct) evl= evl->next;
+ else evl= evl->prev;
+ }
+ direct= 1-direct;
+ }
+ }
+
+ recalc_editnormals();
+
+ makeDispList(G.obedit);
+
+ waitcursor(0);
+}
+
+static EditVert *findnearestvert(short sel)
+{
+ /* als sel==1 krijgen vertices met flag==1 een nadeel */
+ EditVert *eve,*act=0;
+ static EditVert *acto=0;
+ short dist=100,temp,mval[2];
+
+ if(G.edve.first==0) return 0;
+
+ /* projektie doen */
+ calc_meshverts_ext(); /* drawobject.c */
+
+ /* er wordt geteld van acto->next tot last en van first tot acto */
+ /* bestaat acto ? */
+ eve= G.edve.first;
+ while(eve) {
+ if(eve==acto) break;
+ eve= eve->next;
+ }
+ if(eve==0) acto= G.edve.first;
+
+ if(acto==0) return 0;
+
+ /* is er een aangegeven vertex? deel 1 */
+ getmouseco_areawin(mval);
+ eve= acto->next;
+ while(eve) {
+ if(eve->h==0) {
+ temp= abs(mval[0]- eve->xs)+ abs(mval[1]- eve->ys);
+ if( (eve->f & 1)==sel ) temp+=5;
+ if(temp<dist) {
+ act= eve;
+ dist= temp;
+ if(dist<4) break;
+ }
+ }
+ eve= eve->next;
+ }
+ /* is er een aangegeven vertex? deel 2 */
+ if(dist>3) {
+ eve= G.edve.first;
+ while(eve) {
+ if(eve->h==0) {
+ temp= abs(mval[0]- eve->xs)+ abs(mval[1]- eve->ys);
+ if( (eve->f & 1)==sel ) temp+=5;
+ if(temp<dist) {
+ act= eve;
+ if(temp<4) break;
+ dist= temp;
+ }
+ if(eve== acto) break;
+ }
+ eve= eve->next;
+ }
+ }
+
+ acto= act;
+ return act;
+}
+
+static void tekenvertices_special(int mode, EditVert *act)
+{
+ /* voor speciale gevallen:
+ * mode 0: deselect geselecteerde, teken ze, behalve act
+ * mode 1: teken alleen act
+ */
+ ScrArea *tempsa, *sa;
+ View3D *vd;
+ EditVert *eve;
+ float mat[4][4];
+ int doit=0;
+
+ /* eerst testen of er wel special vertices zijn */
+
+ eve= (EditVert *)G.edve.first;
+ while(eve) {
+ eve->f1= 0;
+ if(eve->h==0) {
+ if(mode==0) {
+ if(eve!=act && eve->f & 1) {
+ doit= 1;
+ eve->f1= 1;
+ eve->f -= 1;
+ }
+ }
+ else if(mode==1) {
+ if(eve==act) eve->f1= 1;
+ doit= 1;
+ }
+ }
+ eve= eve->next;
+ }
+ if(doit==0) return;
+
+ if(G.f & (G_FACESELECT+G_DRAWFACES)) {
+ scrarea_queue_winredraw(curarea);
+ return;
+ }
+
+ if(G.zbuf) glDisable(GL_DEPTH_TEST);
+
+ glDrawBuffer(GL_FRONT);
+
+ /* alle views aflopen */
+ tempsa= curarea;
+ sa= G.curscreen->areabase.first;
+ while(sa) {
+ if(sa->spacetype==SPACE_VIEW3D) {
+ vd= sa->spacedata.first;
+ if(G.obedit->lay & vd->lay) {
+ areawinset(sa->win);
+ mymultmatrix(G.obedit->obmat);
+
+ MTC_Mat4SwapMat4(G.vd->persmat, mat);
+ mygetsingmatrix(G.vd->persmat);
+
+ tekenvertices(0);
+ tekenvertices(1);
+
+ MTC_Mat4SwapMat4(G.vd->persmat, mat);
+
+ sa->win_swap= WIN_FRONT_OK;
+
+ myloadmatrix(G.vd->viewmat);
+ }
+ }
+ sa= sa->next;
+ }
+ if(curarea!=tempsa) areawinset(tempsa->win);
+
+ glDrawBuffer(GL_BACK);
+ if(G.zbuf) glEnable(GL_DEPTH_TEST);
+}
+
+void mouse_mesh(void)
+{
+ EditVert *act=0;
+
+ act= findnearestvert(1);
+ if(act) {
+
+ if((G.qual & LR_SHIFTKEY)==0) {
+ tekenvertices_special(0, act);
+ }
+ if( (act->f & 1)==0) act->f+= 1;
+ else if(G.qual & LR_SHIFTKEY) act->f-= 1;
+
+ tekenvertices_special(1, act);
+ countall();
+ }
+
+ rightmouse_transform();
+}
+
+static void selectconnectedAll(void)
+{
+ EditVert *v1,*v2;
+ EditEdge *eed;
+ short flag=1,toggle=0;
+
+ if(G.eded.first==0) return;
+
+ while(flag==1) {
+ flag= 0;
+ toggle++;
+ if(toggle & 1) eed= G.eded.first;
+ else eed= G.eded.last;
+ while(eed) {
+ v1= eed->v1;
+ v2= eed->v2;
+ if(eed->h==0) {
+ if(v1->f & 1) {
+ if( (v2->f & 1)==0 ) {
+ v2->f |= 1;
+ flag= 1;
+ }
+ }
+ else if(v2->f & 1) {
+ if( (v1->f & 1)==0 ) {
+ v1->f |= 1;
+ flag= 1;
+ }
+ }
+ }
+ if(toggle & 1) eed= eed->next;
+ else eed= eed->prev;
+ }
+ }
+ countall();
+
+ tekenvertices_ext(1);
+
+}
+
+
+void selectconnected_mesh(void)
+{
+ EditVert *eve,*v1,*v2,*act= 0;
+ EditEdge *eed;
+ short flag=1,sel,toggle=0;
+
+ if(G.eded.first==0) return;
+
+ if(G.qual & LR_CTRLKEY) {
+ selectconnectedAll();
+ return;
+ }
+
+ sel= 3;
+ if(G.qual & LR_SHIFTKEY) sel=2;
+
+ act= findnearestvert(sel-2);
+ if(act==0) {
+ error(" Nothing indicated ");
+ return;
+ }
+
+ /* testflaggen wissen */
+ eve= G.edve.first;
+ while(eve) {
+ eve->f&= ~2;
+ eve= eve->next;
+ }
+ act->f= (act->f & ~3) | sel;
+
+ while(flag==1) {
+ flag= 0;
+ toggle++;
+ if(toggle & 1) eed= G.eded.first;
+ else eed= G.eded.last;
+ while(eed) {
+ v1= eed->v1;
+ v2= eed->v2;
+ if(eed->h==0) {
+ if(v1->f & 2) {
+ if( (v2->f & 2)==0 ) {
+ v2->f= (v2->f & ~3) | sel;
+ flag= 1;
+ }
+ }
+ else if(v2->f & 2) {
+ if( (v1->f & 2)==0 ) {
+ v1->f= (v1->f & ~3) | sel;
+ flag= 1;
+ }
+ }
+ }
+ if(toggle & 1) eed= eed->next;
+ else eed= eed->prev;
+ }
+ }
+ countall();
+
+ tekenvertices_ext( sel==3 );
+}
+
+
+short extrudeflag(short flag,short type)
+{
+ /* als type=1 worden oude extrudevlakken verwijderd (ivm spin etc) */
+ /* alle verts met (flag & 'flag') extrude */
+ /* van oude wordt flag 'flag' gewist, van nieuwe gezet */
+
+ EditVert *eve, *v1, *v2, *v3, *v4, *nextve;
+ EditEdge *eed, *e1, *e2, *e3, *e4, *nexted;
+ EditVlak *evl, *nextvl;
+ short sel=0, deloud= 0;
+
+ if(G.obedit==0 || get_mesh(G.obedit)==0) return 0;
+
+ /* de vert flag f1 wissen, hiermee test op losse geselecteerde vert */
+ eve= G.edve.first;
+ while(eve) {
+ if(eve->f & flag) eve->f1= 1;
+ else eve->f1= 0;
+ eve= eve->next;
+ }
+ /* de edges tellerflag wissen, als selected op 1 zetten */
+ eed= G.eded.first;
+ while(eed) {
+ if( (eed->v1->f & flag) && (eed->v2->f & flag) ) {
+ eed->f= 1;
+ eed->v1->f1= 0;
+ eed->v2->f1= 0;
+ }
+ else eed->f= 0;
+
+ eed->f1= 1; /* aangeven is 'oude' edge (er worden in deze routine nieuwe gemaakt */
+
+ eed= eed->next;
+ }
+
+
+ /* in alle vlak sel een dupl.flag zetten en bijhorende edgeflags ophogen */
+
+ evl= G.edvl.first;
+ while(evl) {
+ evl->f= 0;
+
+ if(vlakselectedAND(evl, flag)) {
+ e1= evl->e1;
+ e2= evl->e2;
+ e3= evl->e3;
+ e4= evl->e4;
+
+ if(e1->f < 3) e1->f++;
+ if(e2->f < 3) e2->f++;
+ if(e3->f < 3) e3->f++;
+ if(e4 && e4->f < 3) e4->f++;
+ evl->f= 1;
+ }
+ else if(vlakselectedOR(evl, flag)) {
+ e1= evl->e1;
+ e2= evl->e2;
+ e3= evl->e3;
+ e4= evl->e4;
+
+ if( (e1->v1->f & flag) && (e1->v2->f & flag) ) e1->f1= 2;
+ if( (e2->v1->f & flag) && (e2->v2->f & flag) ) e2->f1= 2;
+ if( (e3->v1->f & flag) && (e3->v2->f & flag) ) e3->f1= 2;
+ if( e4 && (e4->v1->f & flag) && (e4->v2->f & flag) ) e4->f1= 2;
+ }
+
+ evl= evl->next;
+ }
+
+ /* set direction of edges */
+ evl= G.edvl.first;
+ while(evl) {
+ if(evl->f== 0) {
+ if(evl->e1->f==2) {
+ if(evl->e1->v1 == evl->v1) evl->e1->dir= 0;
+ else evl->e1->dir= 1;
+ }
+ if(evl->e2->f==2) {
+ if(evl->e2->v1 == evl->v2) evl->e2->dir= 0;
+ else evl->e2->dir= 1;
+ }
+ if(evl->e3->f==2) {
+ if(evl->e3->v1 == evl->v3) evl->e3->dir= 0;
+ else evl->e3->dir= 1;
+ }
+ if(evl->e4 && evl->e4->f==2) {
+ if(evl->e4->v1 == evl->v4) evl->e4->dir= 0;
+ else evl->e4->dir= 1;
+ }
+ }
+ evl= evl->next;
+ }
+
+
+ /* de stand van zaken nu:
+ eve->f1==1: losse selected vertex
+
+ eed->f==0 : edge niet selected, geen extrude
+ eed->f==1 : edge selected, komt niet in vlak voor, extrude
+ eed->f==2 : edge selected, komt 1 keer in vlak voor, extrude
+ eed->f==3 : edge selected, komt in meer vlakken voor, geen extrude
+
+ eed->f1==0: nieuwe edge
+ eed->f1==1: edge selected, komt in selected vlak voor, als f==3: remove
+ eed->f1==2: edge selected, komt in NIET selected vlak voor
+
+
+ evl->f==1 : vlak dupliceren
+ */
+
+ /* alle geselecteerde vertices kopieeren, */
+ /* de pointer naar nieuwe vert in oude struct schrijven op eve->vn */
+ eve= G.edve.last;
+ while(eve) {
+ eve->f&= ~128; /* wissen voor test later op losse verts */
+ if(eve->f & flag) {
+ sel= 1;
+ v1= addvertlist(0);
+
+ VECCOPY(v1->co, eve->co);
+ v1->f= eve->f;
+ eve->f-= flag;
+ eve->vn= v1;
+ }
+ else eve->vn= 0;
+ eve= eve->prev;
+ }
+
+ if(sel==0) return 0;
+
+ /* alle edges met eed->f==1 of eed->f==2 worden vlakken */
+ /* als deloud==1 worden edges eed->f>2 verwijderd */
+ eed= G.eded.last;
+ while(eed) {
+ nexted= eed->prev;
+ if( eed->f<3) {
+ eed->v1->f|=128; /* =geen losse vert! */
+ eed->v2->f|=128;
+ }
+ if( (eed->f==1 || eed->f==2) ) {
+ if(eed->f1==2) deloud=1;
+
+ /* that dir thing does work somewhat... */
+
+ if(eed->dir==1) addvlaklist(eed->v1, eed->v2, eed->v2->vn, eed->v1->vn, NULL);
+ else addvlaklist(eed->v2, eed->v1, eed->v1->vn, eed->v2->vn, NULL);
+ }
+
+ eed= nexted;
+ }
+ if(deloud) {
+ eed= G.eded.first;
+ while(eed) {
+ nexted= eed->next;
+ if(eed->f==3 && eed->f1==1) {
+ remedge(eed);
+ free(eed);
+ }
+ eed= nexted;
+ }
+ }
+ /* de vlakken dupliceren, eventueel oude verwijderen */
+ evl= G.edvl.first;
+ while(evl) {
+ nextvl= evl->next;
+ if(evl->f & 1) {
+
+ v1= evl->v1->vn;
+ v2= evl->v2->vn;
+ v3= evl->v3->vn;
+ if(evl->v4) v4= evl->v4->vn; else v4= 0;
+
+ addvlaklist(v1, v2, v3, v4, evl);
+
+ if(deloud) {
+ BLI_remlink(&G.edvl, evl);
+ freevlak(evl);
+ }
+
+ }
+ evl= nextvl;
+ }
+ /* alle verts met eve->vn!=0
+ als eve->f1==1: edge maken
+ als flag!=128 :als deloud==1: verwijderen
+ */
+ eve= G.edve.last;
+ while(eve) {
+ nextve= eve->prev;
+ if(eve->vn) {
+ if(eve->f1==1) addedgelist(eve,eve->vn);
+ else if( (eve->f & 128)==0) {
+ if(deloud) {
+ BLI_remlink(&G.edve,eve);
+// free(eve);
+ free_editvert(eve);
+ eve= NULL;
+ }
+ }
+ }
+ if(eve) eve->f&= ~128;
+
+ eve= nextve;
+ }
+
+ /* debug temp: testen op consistente:
+ evl= G.edvl.first;
+ while(evl) {
+ e1= findedgelist(evl->v1, evl->v2);
+ e2= findedgelist(evl->v2, evl->v3);
+ e3= findedgelist(evl->v3, evl->v1);
+ if(e1==0 || e2==0 || e3==0) {
+ error("edge not in edgelist");
+ break;
+ }
+ evl= evl->next;
+ }
+ */
+
+ return 1;
+}
+
+void rotateflag(short flag, float *cent, float rotmat[][3])
+{
+ /* alle verts met (flag & 'flag') rotate */
+
+ EditVert *eve;
+
+ eve= G.edve.first;
+ while(eve) {
+ if(eve->f & flag) {
+ eve->co[0]-=cent[0];
+ eve->co[1]-=cent[1];
+ eve->co[2]-=cent[2];
+ Mat3MulVecfl(rotmat,eve->co);
+ eve->co[0]+=cent[0];
+ eve->co[1]+=cent[1];
+ eve->co[2]+=cent[2];
+ }
+ eve= eve->next;
+ }
+}
+
+void translateflag(short flag, float *vec)
+{
+ /* alle verts met (flag & 'flag') translate */
+
+ EditVert *eve;
+
+ eve= G.edve.first;
+ while(eve) {
+ if(eve->f & flag) {
+ eve->co[0]+=vec[0];
+ eve->co[1]+=vec[1];
+ eve->co[2]+=vec[2];
+ }
+ eve= eve->next;
+ }
+}
+
+short removedoublesflag(short flag, float limit) /* return aantal */
+{
+ /* alle verts met (flag & 'flag') worden getest */
+ EditVert *eve, *v1, *nextve;
+ EditEdge *eed, *e1, *nexted;
+ EditVlak *evl, *nextvl;
+ struct xvertsort *sortblock, *sb, *sb1;
+ struct vlaksort *vlsortblock, *vsb, *vsb1;
+ float dist;
+ int a, b, test, aantal;
+
+ /* flag 128 wordt gewist, aantal tellen */
+ eve= G.edve.first;
+ aantal= 0;
+ while(eve) {
+ eve->f&= ~128;
+ if(eve->f & flag) aantal++;
+ eve= eve->next;
+ }
+ if(aantal==0) return 0;
+
+ /* geheugen reserveren en qsorten */
+ sb= sortblock= (struct xvertsort *)MEM_mallocN(sizeof(struct xvertsort)*aantal,"sortremovedoub");
+ eve= G.edve.first;
+ while(eve) {
+ if(eve->f & flag) {
+ sb->x= eve->co[0]+eve->co[1]+eve->co[2];
+ sb->v1= eve;
+ sb++;
+ }
+ eve= eve->next;
+ }
+ qsort(sortblock, aantal, sizeof(struct xvertsort), vergxco);
+
+ /* testen op doubles */
+ sb= sortblock;
+ for(a=0; a<aantal; a++) {
+ eve= sb->v1;
+ if( (eve->f & 128)==0 ) {
+ sb1= sb+1;
+ for(b=a+1; b<aantal; b++) {
+ /* eerste test: simpel dist */
+ dist= sb1->x - sb->x;
+ if(dist > limit) break;
+
+ /* tweede test: is vertex toegestaan */
+ v1= sb1->v1;
+ if( (v1->f & 128)==0 ) {
+
+ dist= fabs(v1->co[0]-eve->co[0]);
+ if(dist<=limit) {
+ dist= fabs(v1->co[1]-eve->co[1]);
+ if(dist<=limit) {
+ dist= fabs(v1->co[2]-eve->co[2]);
+ if(dist<=limit) {
+ v1->f|= 128;
+ v1->vn= eve;
+ }
+ }
+ }
+ }
+ sb1++;
+ }
+ }
+ sb++;
+ }
+ MEM_freeN(sortblock);
+
+ /* edges testen en opnieuw invoegen */
+ eed= G.eded.first;
+ while(eed) {
+ eed->f= 0;
+ eed= eed->next;
+ }
+ eed= G.eded.last;
+ while(eed) {
+ nexted= eed->prev;
+
+ if(eed->f==0) {
+ if( (eed->v1->f & 128) || (eed->v2->f & 128) ) {
+ remedge(eed);
+
+ if(eed->v1->f & 128) eed->v1= eed->v1->vn;
+ if(eed->v2->f & 128) eed->v2= eed->v2->vn;
+
+ e1= addedgelist(eed->v1,eed->v2);
+
+ if(e1) e1->f= 1;
+ if(e1!=eed) free(eed);
+ }
+ }
+ eed= nexted;
+ }
+
+ /* eerst aantal testvlakken tellen */
+ evl= (struct EditVlak *)G.edvl.first;
+ aantal= 0;
+ while(evl) {
+ evl->f= 0;
+ if(evl->v1->f & 128) evl->f= 1;
+ else if(evl->v2->f & 128) evl->f= 1;
+ else if(evl->v3->f & 128) evl->f= 1;
+ else if(evl->v4 && (evl->v4->f & 128)) evl->f= 1;
+
+ if(evl->f==1) aantal++;
+ evl= evl->next;
+ }
+
+ /* vlakken testen op dubbele punten en eventueel verwijderen */
+ evl= (struct EditVlak *)G.edvl.first;
+ while(evl) {
+ nextvl= evl->next;
+ if(evl->f==1) {
+
+ if(evl->v1->f & 128) evl->v1= evl->v1->vn;
+ if(evl->v2->f & 128) evl->v2= evl->v2->vn;
+ if(evl->v3->f & 128) evl->v3= evl->v3->vn;
+ if(evl->v4 && (evl->v4->f & 128)) evl->v4= evl->v4->vn;
+
+ test= 0;
+ if(evl->v1==evl->v2) test+=1;
+ if(evl->v2==evl->v3) test+=2;
+ if(evl->v3==evl->v1) test+=4;
+ if(evl->v4==evl->v1) test+=8;
+ if(evl->v3==evl->v4) test+=16;
+ if(evl->v2==evl->v4) test+=32;
+
+ if(test) {
+ if(evl->v4) {
+ if(test==1 || test==2) {
+ evl->v2= evl->v3;
+ evl->v3= evl->v4;
+ evl->v4= 0;
+ test= 0;
+ }
+ else if(test==8 || test==16) {
+ evl->v4= 0;
+ test= 0;
+ }
+ else {
+ BLI_remlink(&G.edvl, evl);
+ freevlak(evl);
+ aantal--;
+ }
+ }
+ else {
+ BLI_remlink(&G.edvl, evl);
+ freevlak(evl);
+ aantal--;
+ }
+ }
+
+ if(test==0) {
+ /* edgepointers goedzetten */
+ evl->e1= findedgelist(evl->v1, evl->v2);
+ evl->e2= findedgelist(evl->v2, evl->v3);
+ if(evl->v4==0) {
+ evl->e3= findedgelist(evl->v3, evl->v1);
+ evl->e4= 0;
+ }
+ else {
+ evl->e3= findedgelist(evl->v3, evl->v4);
+ evl->e4= findedgelist(evl->v4, evl->v1);
+ }
+ }
+ }
+ evl= nextvl;
+ }
+
+ /* dubbele vlakken: sortblock */
+ /* opnieuw tellen, nu alle selected vlakken */
+ aantal= 0;
+ evl= G.edvl.first;
+ while(evl) {
+ evl->f= 0;
+ if(vlakselectedAND(evl, 1)) {
+ evl->f= 1;
+ aantal++;
+ }
+ evl= evl->next;
+ }
+
+ if(aantal) {
+ /* dubbele vlakken: sortblock */
+ vsb= vlsortblock= MEM_mallocN(sizeof(struct vlaksort)*aantal, "sortremovedoub");
+ evl= G.edvl.first;
+ while(evl) {
+ if(evl->f & 1) {
+ if(evl->v4) vsb->x= (long) MIN4( (long)evl->v1, (long)evl->v2, (long)evl->v3, (long)evl->v4);
+ else vsb->x= (long) MIN3( (long)evl->v1, (long)evl->v2, (long)evl->v3);
+
+ vsb->evl= evl;
+ vsb++;
+ }
+ evl= evl->next;
+ }
+
+ qsort(vlsortblock, aantal, sizeof(struct vlaksort), vergvlak);
+
+ vsb= vlsortblock;
+ for(a=0; a<aantal; a++) {
+ evl= vsb->evl;
+ if( (evl->f & 128)==0 ) {
+ vsb1= vsb+1;
+
+ for(b=a+1; b<aantal; b++) {
+
+ /* eerste test: zelfde poin? */
+ if(vsb->x != vsb1->x) break;
+
+ /* tweede test: is test toegestaan */
+ evl= vsb1->evl;
+ if( (evl->f & 128)==0 ) {
+ if( comparevlak(evl, vsb->evl)) evl->f |= 128;
+
+ }
+ vsb1++;
+ }
+ }
+ vsb++;
+ }
+
+ MEM_freeN(vlsortblock);
+
+ /* dubbele vlakken eruit */
+ evl= (struct EditVlak *)G.edvl.first;
+ while(evl) {
+ nextvl= evl->next;
+ if(evl->f & 128) {
+ BLI_remlink(&G.edvl, evl);
+ freevlak(evl);
+ }
+ evl= nextvl;
+ }
+ }
+
+ /* dubbele vertices eruit */
+ a= 0;
+ eve= (struct EditVert *)G.edve.first;
+ while(eve) {
+ nextve= eve->next;
+ if(eve->f & flag) {
+ if(eve->f & 128) {
+ a++;
+ BLI_remlink(&G.edve, eve);
+
+// free(eve);
+ free_editvert(eve);
+ }
+ }
+ eve= nextve;
+ }
+ return a; /* aantal */
+}
+
+void xsortvert_flag(int flag)
+//short flag;
+{
+ /* alle verts met (flag & 'flag') worden gesorteerd */
+ EditVert *eve;
+ struct xvertsort *sortblock, *sb;
+ ListBase tbase;
+ int aantal;
+
+ /* aantal tellen */
+ eve= G.edve.first;
+ aantal= 0;
+ while(eve) {
+ if(eve->f & flag) aantal++;
+ eve= eve->next;
+ }
+ if(aantal==0) return;
+
+ /* geheugen reserveren en qsorten */
+ sb= sortblock= (struct xvertsort *)MEM_mallocN(sizeof(struct xvertsort)*aantal,"sortremovedoub");
+ eve= G.edve.first;
+ while(eve) {
+ if(eve->f & flag) {
+ sb->x= eve->xs;
+ sb->v1= eve;
+ sb++;
+ }
+ eve= eve->next;
+ }
+ qsort(sortblock, aantal, sizeof(struct xvertsort), vergxco);
+
+ /* tijdelijke listbase maken */
+ tbase.first= tbase.last= 0;
+ sb= sortblock;
+ while(aantal--) {
+ eve= sb->v1;
+ BLI_remlink(&G.edve, eve);
+ BLI_addtail(&tbase, eve);
+ sb++;
+ }
+
+ addlisttolist(&G.edve, &tbase);
+
+ MEM_freeN(sortblock);
+}
+
+
+void hashvert_flag(int flag)
+{
+ EditVert *eve;
+ struct xvertsort *sortblock, *sb, onth, *newsort;
+ ListBase tbase;
+ int aantal, a, b;
+
+ /* aantal tellen */
+ eve= G.edve.first;
+ aantal= 0;
+ while(eve) {
+ if(eve->f & flag) aantal++;
+ eve= eve->next;
+ }
+ if(aantal==0) return;
+
+ /* geheugen reserveren */
+ sb= sortblock= (struct xvertsort *)MEM_mallocN(sizeof(struct xvertsort)*aantal,"sortremovedoub");
+ eve= G.edve.first;
+ while(eve) {
+ if(eve->f & flag) {
+ sb->v1= eve;
+ sb++;
+ }
+ eve= eve->next;
+ }
+
+ BLI_srand(1);
+
+ sb= sortblock;
+ for(a=0; a<aantal; a++, sb++) {
+ b= aantal*BLI_drand();
+ if(b>=0 && b<aantal) {
+ newsort= sortblock+b;
+ onth= *sb;
+ *sb= *newsort;
+ *newsort= onth;
+ }
+ }
+
+ /* tijdelijke listbase maken */
+ tbase.first= tbase.last= 0;
+ sb= sortblock;
+ while(aantal--) {
+ eve= sb->v1;
+ BLI_remlink(&G.edve, eve);
+ BLI_addtail(&tbase, eve);
+ sb++;
+ }
+
+ addlisttolist(&G.edve, &tbase);
+
+ MEM_freeN(sortblock);
+}
+
+static unsigned int cpack_half(unsigned int col1, unsigned int col2)
+{
+ char *cp1, *cp2, *cp;
+ unsigned int col=0;
+
+ cp1= (char *)&col1;
+ cp2= (char *)&col2;
+ cp= (char *)&col;
+
+ cp[0]= (cp1[0]+cp2[0])>>1;
+ cp[1]= (cp1[1]+cp2[1])>>1;
+ cp[2]= (cp1[2]+cp2[2])>>1;
+ cp[3]= (cp1[3]+cp2[3])>>1;
+
+ return col;
+}
+
+
+static void uv_half(float *uv, float *uv1, float *uv2)
+{
+ uv[0]= (uv1[0]+uv2[0])/2.0;
+ uv[1]= (uv1[1]+uv2[1])/2.0;
+
+}
+
+static void uv_quart(float *uv, float *uv1)
+{
+ uv[0]= (uv1[0]+uv1[2]+uv1[4]+uv1[6])/4.0;
+ uv[1]= (uv1[1]+uv1[3]+uv1[5]+uv1[7])/4.0;
+}
+
+static void set_wuv(int tot, EditVlak *evl, int v1, int v2, int v3, int v4)
+{
+ /* deze vreemde fie alleen bij de subdiv te gebruiken, de 'w' in de naam slaat nergens op! */
+ float *uv, uvo[4][2];
+ unsigned int *col, colo[4], col1, col2;
+ int a, v;
+
+ memcpy(uvo, evl->uv, sizeof(uvo));
+ uv= evl->uv[0];
+
+ memcpy(colo, evl->col, sizeof(colo));
+ col= evl->col;
+
+ if(tot==4) {
+ for(a=0; a<4; a++, uv+=2, col++) {
+ if(a==0) v= v1;
+ else if(a==1) v= v2;
+ else if(a==2) v= v3;
+ else v= v4;
+
+ if(a==3 && v4==0) break;
+
+ if(v<=4) {
+ uv[0]= uvo[v-1][0];
+ uv[1]= uvo[v-1][1];
+ *col= colo[v-1];
+ }
+ else if(v==8) {
+ uv_half(uv, uvo[3], uvo[0]);
+ *col= cpack_half(colo[3], colo[0]);
+ }
+ else if(v==9) {
+ uv_quart(uv, uvo[0]);
+ col1= cpack_half(colo[1], colo[0]);
+ col2= cpack_half(colo[2], colo[3]);
+ *col= cpack_half(col1, col2);
+ }
+ else {
+ uv_half(uv, uvo[v-5], uvo[v-4]);
+ *col= cpack_half(colo[v-5], colo[v-4]);
+ }
+ }
+ }
+ else {
+ for(a=0; a<3; a++, uv+=2, col++) {
+ if(a==0) v= v1;
+ else if(a==1) v= v2;
+ else v= v3;
+
+ if(v<=4) {
+ uv[0]= uvo[v-1][0];
+ uv[1]= uvo[v-1][1];
+ *col= colo[v-1];
+ }
+ else if(v==7) {
+ uv_half(uv, uvo[2], uvo[0]);
+ *col= cpack_half(colo[2], colo[0]);
+ }
+ else {
+ uv_half(uv, uvo[v-5], uvo[v-4]);
+ *col= cpack_half(colo[v-5], colo[v-4]);
+ }
+ }
+ }
+}
+
+static EditVert *vert_from_number(EditVlak *evl, int nr)
+{
+ switch(nr) {
+ case 0:
+ return 0;
+ case 1:
+ return evl->v1;
+ case 2:
+ return evl->v2;
+ case 3:
+ return evl->v3;
+ case 4:
+ return evl->v4;
+ case 5:
+ return evl->e1->vn;
+ case 6:
+ return evl->e2->vn;
+ case 7:
+ return evl->e3->vn;
+ case 8:
+ return evl->e4->vn;
+ }
+
+ return NULL;
+}
+
+static void addvlak_subdiv(EditVlak *evl, int val1, int val2, int val3, int val4, EditVert *eve)
+{
+ EditVlak *w;
+ EditVert *v1, *v2, *v3, *v4;
+
+ if(val1==9) v1= eve;
+ else v1= vert_from_number(evl, val1);
+
+ if(val2==9) v2= eve;
+ else v2= vert_from_number(evl, val2);
+
+ if(val3==9) v3= eve;
+ else v3= vert_from_number(evl, val3);
+
+ if(val4==9) v4= eve;
+ else v4= vert_from_number(evl, val4);
+
+ w= addvlaklist(v1, v2, v3, v4, evl);
+
+ if(w) {
+ if(evl->v4) set_wuv(4, w, val1, val2, val3, val4);
+ else set_wuv(3, w, val1, val2, val3, val4);
+ }
+}
+
+static float smoothperc= 0.0;
+
+static void smooth_subdiv_vec(float *v1, float *v2, float *n1, float *n2, float *vec)
+{
+ float len, fac, nor[3], nor1[3], nor2[3];
+
+ VecSubf(nor, v1, v2);
+ len= 0.5*Normalise(nor);
+
+ VECCOPY(nor1, n1);
+ VECCOPY(nor2, n2);
+
+ /* cosine angle */
+ fac= nor[0]*nor1[0] + nor[1]*nor1[1] + nor[2]*nor1[2] ;
+
+ vec[0]= fac*nor1[0];
+ vec[1]= fac*nor1[1];
+ vec[2]= fac*nor1[2];
+
+ /* cosine angle */
+ fac= -nor[0]*nor2[0] - nor[1]*nor2[1] - nor[2]*nor2[2] ;
+
+ vec[0]+= fac*nor2[0];
+ vec[1]+= fac*nor2[1];
+ vec[2]+= fac*nor2[2];
+
+ vec[0]*= smoothperc*len;
+ vec[1]*= smoothperc*len;
+ vec[2]*= smoothperc*len;
+}
+
+static void smooth_subdiv_quad(EditVlak *evl, float *vec)
+{
+
+ float nor1[3], nor2[3];
+ float vec1[3], vec2[3];
+ float cent[3];
+
+ /* vlr->e1->vn is new vertex inbetween v1 / v2 */
+
+ VecMidf(nor1, evl->v1->no, evl->v2->no);
+ Normalise(nor1);
+ VecMidf(nor2, evl->v3->no, evl->v4->no);
+ Normalise(nor2);
+
+ smooth_subdiv_vec( evl->e1->vn->co, evl->e3->vn->co, nor1, nor2, vec1);
+
+ VecMidf(nor1, evl->v2->no, evl->v3->no);
+ Normalise(nor1);
+ VecMidf(nor2, evl->v4->no, evl->v1->no);
+ Normalise(nor2);
+
+ smooth_subdiv_vec( evl->e2->vn->co, evl->e4->vn->co, nor1, nor2, vec2);
+
+ VecAddf(vec1, vec1, vec2);
+
+ CalcCent4f(cent, evl->v1->co, evl->v2->co, evl->v3->co, evl->v4->co);
+ VecAddf(vec, cent, vec1);
+}
+
+void subdivideflag(int flag, float rad, int beauty)
+{
+ /* divide alle vlakken met (vertflag & flag) */
+ /* als rad>0.0 zet dan nieuw vert op afstand rad van 0,0,0 */
+ extern float doublimit;
+ EditVert *eve;
+ EditEdge *eed, *e1, *e2, *e3, *e4, *nexted;
+ EditVlak *evl;
+ float fac, vec[3], vec1[3], len1, len2, len3;
+ short test;
+
+ if(beauty & B_SMOOTH) {
+ short perc= 100;
+
+ if(button(&perc, 10, 500, "Percentage:")==0) return;
+
+ smoothperc= 0.292*perc/100.0;
+ }
+
+ /* edgeflags */
+ eed= G.eded.first;
+ while(eed) {
+
+ if( (eed->v1->f & flag) && (eed->v2->f & flag) ) eed->f= flag;
+ else eed->f= 0;
+
+ eed= eed->next;
+ }
+
+ /* als beauty: opp testen en edgeflags wissen van 'lelijke' edges */
+ if(beauty & B_BEAUTY) {
+ evl= G.edvl.first;
+ while(evl) {
+ if( vlakselectedAND(evl, flag) ) {
+ if(evl->v4) {
+
+ /* opp */
+ len1= AreaQ3Dfl(evl->v1->co, evl->v2->co, evl->v3->co, evl->v4->co);
+ if(len1 <= doublimit) {
+ evl->e1->f = 0;
+ evl->e2->f = 0;
+ evl->e3->f = 0;
+ evl->e4->f = 0;
+ }
+ else {
+ len1= VecLenf(evl->v1->co, evl->v2->co) + VecLenf(evl->v3->co, evl->v4->co);
+ len2= VecLenf(evl->v2->co, evl->v3->co) + VecLenf(evl->v1->co, evl->v4->co);
+
+ if(len1 < len2) {
+ evl->e1->f = 0;
+ evl->e3->f = 0;
+ }
+ else if(len1 > len2) {
+ evl->e2->f = 0;
+ evl->e4->f = 0;
+ }
+ }
+ }
+ else {
+
+ /* opp */
+ len1= AreaT3Dfl(evl->v1->co, evl->v2->co, evl->v3->co);
+ if(len1 <= doublimit) {
+ evl->e1->f = 0;
+ evl->e2->f = 0;
+ evl->e3->f = 0;
+ }
+ else {
+
+ len1= VecLenf(evl->v1->co, evl->v2->co) ;
+ len2= VecLenf(evl->v2->co, evl->v3->co) ;
+ len3= VecLenf(evl->v3->co, evl->v1->co) ;
+
+ if(len1<len2 && len1<len3) {
+ evl->e1->f = 0;
+ }
+ else if(len2<len3 && len2<len1) {
+ evl->e2->f = 0;
+ }
+ else if(len3<len2 && len3<len1) {
+ evl->e3->f = 0;
+ }
+ }
+ }
+ }
+ evl= evl->next;
+ }
+ }
+
+ if(beauty & B_SMOOTH) {
+
+ vertexnormals(0); /* no1*/
+
+ }
+
+ /* nieuw punt maken en in edge wegschrijven, flag wissen! is voor vlakkenmaak stuk nodig */
+ eed= G.eded.first;
+ while(eed) {
+ if(eed->f & flag) {
+
+ vec[0]= (eed->v1->co[0]+eed->v2->co[0])/2.0;
+ vec[1]= (eed->v1->co[1]+eed->v2->co[1])/2.0;
+ vec[2]= (eed->v1->co[2]+eed->v2->co[2])/2.0;
+
+ if(rad > 0.0) { /* perf sph */
+ Normalise(vec);
+ vec[0]*= rad;
+ vec[1]*= rad;
+ vec[2]*= rad;
+ }
+ else if(rad< 0.0) { /* fract */
+ fac= rad* VecLenf(eed->v1->co, eed->v2->co);
+ vec1[0]= fac*BLI_drand();
+ vec1[1]= fac*BLI_drand();
+ vec1[2]= fac*BLI_drand();
+ VecAddf(vec, vec, vec1);
+ }
+
+ if(beauty & B_SMOOTH) {
+ smooth_subdiv_vec(eed->v1->co, eed->v2->co, eed->v1->no, eed->v2->no, vec1);
+ VecAddf(vec, vec, vec1);
+ }
+
+ eed->vn= addvertlist(vec);
+ eed->vn->f= eed->v1->f;
+
+ }
+ else eed->vn= 0;
+
+ eed->f= 0; /* moet! */
+
+ eed= eed->next;
+ }
+
+ /* alle vlakken testen op subdiv edges, 8 of 16 gevallen! */
+
+ evl= G.edvl.last;
+ while(evl) {
+ if( vlakselectedOR(evl, flag) ) {
+ e1= evl->e1;
+ e2= evl->e2;
+ e3= evl->e3;
+ e4= evl->e4;
+
+ test= 0;
+ if(e1 && e1->vn) {
+ test+= 1;
+ e1->f= 1;
+ }
+ if(e2 && e2->vn) {
+ test+= 2;
+ e2->f= 1;
+ }
+ if(e3 && e3->vn) {
+ test+= 4;
+ e3->f= 1;
+ }
+ if(e4 && e4->vn) {
+ test+= 8;
+ e4->f= 1;
+ }
+
+ if(test) {
+ if(evl->v4==0) {
+ if((test & 3)==3) addvlak_subdiv(evl, 2, 2+4, 1+4, 0, 0);
+ if((test & 6)==6) addvlak_subdiv(evl, 3, 3+4, 2+4, 0, 0);
+ if((test & 5)==5) addvlak_subdiv(evl, 1, 1+4, 3+4, 0, 0);
+
+ if(test==7) { /* vier nieuwe vlakken, oude vernieuwt */
+ evl->v1= e1->vn;
+ evl->v2= e2->vn;
+ evl->v3= e3->vn;
+ set_wuv(3, evl, 1+4, 2+4, 3+4, 0);
+ }
+ else if(test==3) {
+ addvlak_subdiv(evl, 1+4, 2+4, 3, 0, 0);
+ evl->v2= e1->vn;
+ set_wuv(3, evl, 1, 1+4, 3, 0);
+ }
+ else if(test==6) {
+ addvlak_subdiv(evl, 2+4, 3+4, 1, 0, 0);
+ evl->v3= e2->vn;
+ set_wuv(3, evl, 1, 2, 2+4, 0);
+ }
+ else if(test==5) {
+ addvlak_subdiv(evl, 3+4, 1+4, 2, 0, 0);
+ evl->v1= e3->vn;
+ set_wuv(3, evl, 3+4, 2, 3, 0);
+ }
+ else if(test==1) {
+ addvlak_subdiv(evl, 1+4, 2, 3, 0, 0);
+ evl->v2= e1->vn;
+ set_wuv(3, evl, 1, 1+4, 3, 0);
+ }
+ else if(test==2) {
+ addvlak_subdiv(evl, 2+4, 3, 1, 0, 0);
+ evl->v3= e2->vn;
+ set_wuv(3, evl, 1, 2, 2+4, 0);
+ }
+ else if(test==4) {
+ addvlak_subdiv(evl, 3+4, 1, 2, 0, 0);
+ evl->v1= e3->vn;
+ set_wuv(3, evl, 3+4, 2, 3, 0);
+ }
+ evl->e1= addedgelist(evl->v1, evl->v2);
+ evl->e2= addedgelist(evl->v2, evl->v3);
+ evl->e3= addedgelist(evl->v3, evl->v1);
+
+ }
+ else {
+ if(test==15) {
+ /* nog een nieuw punt toevoegen */
+ CalcCent4f(vec, evl->v1->co, evl->v2->co, evl->v3->co, evl->v4->co);
+
+ if(beauty & B_SMOOTH) {
+ smooth_subdiv_quad(evl, vec); /* adds */
+ }
+ eve= addvertlist(vec);
+
+ eve->f |= flag;
+
+ addvlak_subdiv(evl, 2, 2+4, 9, 1+4, eve);
+ addvlak_subdiv(evl, 3, 3+4, 9, 2+4, eve);
+ addvlak_subdiv(evl, 4, 4+4, 9, 3+4, eve);
+
+ evl->v2= e1->vn;
+ evl->v3= eve;
+ evl->v4= e4->vn;
+ set_wuv(4, evl, 1, 1+4, 9, 4+4);
+ }
+ else {
+ /* kleine hoekpunten */
+ if((test & 3)==3) addvlak_subdiv(evl, 1+4, 2, 2+4, 0, 0);
+ if((test & 6)==6) addvlak_subdiv(evl, 2+4, 3, 3+4, 0, 0);
+ if((test & 12)==12) addvlak_subdiv(evl, 3+4, 4, 4+4, 0, 0);
+ if((test & 9)==9) addvlak_subdiv(evl, 4+4, 1, 1+4, 0, 0);
+
+ if(test==1) {
+ addvlak_subdiv(evl, 1+4, 2, 3, 0, 0);
+ addvlak_subdiv(evl, 1+4, 3, 4, 0, 0);
+ evl->v2= e1->vn;
+ evl->v3= evl->v4;
+ evl->v4= 0;
+ set_wuv(4, evl, 1, 1+4, 4, 0);
+ }
+ else if(test==2) {
+ addvlak_subdiv(evl, 2+4, 3, 4, 0, 0);
+ addvlak_subdiv(evl, 2+4, 4, 1, 0, 0);
+ evl->v3= e2->vn;
+ evl->v4= 0;
+ set_wuv(4, evl, 1, 2, 2+4, 0);
+ }
+ else if(test==4) {
+ addvlak_subdiv(evl, 3+4, 4, 1, 0, 0);
+ addvlak_subdiv(evl, 3+4, 1, 2, 0, 0);
+ evl->v1= evl->v2;
+ evl->v2= evl->v3;
+ evl->v3= e3->vn;
+ evl->v4= 0;
+ set_wuv(4, evl, 2, 3, 3+4, 0);
+ }
+ else if(test==8) {
+ addvlak_subdiv(evl, 4+4, 1, 2, 0, 0);
+ addvlak_subdiv(evl, 4+4, 2, 3, 0, 0);
+ evl->v1= evl->v3;
+ evl->v2= evl->v4;
+ evl->v3= e4->vn;
+ evl->v4= 0;
+ set_wuv(4, evl, 3, 4, 4+4, 0);
+ }
+ else if(test==3) {
+ addvlak_subdiv(evl, 1+4, 2+4, 4, 0, 0);
+ addvlak_subdiv(evl, 2+4, 3, 4, 0, 0);
+ evl->v2= e1->vn;
+ evl->v3= evl->v4;
+ evl->v4= 0;
+ set_wuv(4, evl, 1, 1+4, 4, 0);
+ }
+ else if(test==6) {
+ addvlak_subdiv(evl, 2+4, 3+4, 1, 0, 0);
+ addvlak_subdiv(evl, 3+4, 4, 1, 0, 0);
+ evl->v3= e2->vn;
+ evl->v4= 0;
+ set_wuv(4, evl, 1, 2, 2+4, 0);
+ }
+ else if(test==12) {
+ addvlak_subdiv(evl, 3+4, 4+4, 2, 0, 0);
+ addvlak_subdiv(evl, 4+4, 1, 2, 0, 0);
+ evl->v1= evl->v2;
+ evl->v2= evl->v3;
+ evl->v3= e3->vn;
+ evl->v4= 0;
+ set_wuv(4, evl, 2, 3, 3+4, 0);
+ }
+ else if(test==9) {
+ addvlak_subdiv(evl, 4+4, 1+4, 3, 0, 0);
+ addvlak_subdiv(evl, 1+4, 2, 3, 0, 0);
+ evl->v1= evl->v3;
+ evl->v2= evl->v4;
+ evl->v3= e4->vn;
+ evl->v4= 0;
+ set_wuv(4, evl, 3, 4, 4+4, 0);
+ }
+ else if(test==5) {
+ addvlak_subdiv(evl, 1+4, 2, 3, 3+4, 0);
+ evl->v2= e1->vn;
+ evl->v3= e3->vn;
+ set_wuv(4, evl, 1, 1+4, 3+4, 4);
+ }
+ else if(test==10) {
+ addvlak_subdiv(evl, 2+4, 3, 4, 4+4, 0);
+ evl->v3= e2->vn;
+ evl->v4= e4->vn;
+ set_wuv(4, evl, 1, 2, 2+4, 4+4);
+ }
+
+ else if(test==7) {
+ addvlak_subdiv(evl, 1+4, 2+4, 3+4, 0, 0);
+ evl->v2= e1->vn;
+ evl->v3= e3->vn;
+ set_wuv(4, evl, 1, 1+4, 3+4, 4);
+ }
+ else if(test==14) {
+ addvlak_subdiv(evl, 2+4, 3+4, 4+4, 0, 0);
+ evl->v3= e2->vn;
+ evl->v4= e4->vn;
+ set_wuv(4, evl, 1, 2, 2+4, 4+4);
+ }
+ else if(test==13) {
+ addvlak_subdiv(evl, 3+4, 4+4, 1+4, 0, 0);
+ evl->v4= e3->vn;
+ evl->v1= e1->vn;
+ set_wuv(4, evl, 1+4, 3, 3, 3+4);
+ }
+ else if(test==11) {
+ addvlak_subdiv(evl, 4+4, 1+4, 2+4, 0, 0);
+ evl->v1= e4->vn;
+ evl->v2= e2->vn;
+ set_wuv(4, evl, 4+4, 2+4, 3, 4);
+ }
+ }
+ evl->e1= addedgelist(evl->v1, evl->v2);
+ evl->e2= addedgelist(evl->v2, evl->v3);
+ if(evl->v4) evl->e3= addedgelist(evl->v3, evl->v4);
+ else evl->e3= addedgelist(evl->v3, evl->v1);
+ if(evl->v4) evl->e4= addedgelist(evl->v4, evl->v1);
+ else evl->e4= 0;
+ }
+ }
+ }
+ evl= evl->prev;
+ }
+
+ /* alle oude edges verwijderen, eventueel nog nieuwe maken */
+ eed= G.eded.first;
+ while(eed) {
+ nexted= eed->next;
+ if( eed->vn ) {
+ if(eed->f==0) { /* niet gebruikt in vlak */
+ addedgelist(eed->v1,eed->vn);
+ addedgelist(eed->vn,eed->v2);
+ }
+ remedge(eed);
+ free(eed);
+ }
+ eed= nexted;
+ }
+ countall();
+ allqueue(REDRAWVIEW3D, 0);
+ makeDispList(G.obedit);
+}
+
+void adduplicateflag(int flag)
+{
+ /* oude verts hebben flag 128 gezet en flag 'flag' gewist
+ nieuwe verts hebben flag 'flag' gezet */
+ EditVert *eve, *v1, *v2, *v3, *v4;
+ EditEdge *eed;
+ EditVlak *evl;
+
+ /* eerst vertices */
+ eve= G.edve.last;
+ while(eve) {
+ eve->f&= ~128;
+ if(eve->f & flag) {
+ v1= addvertlist(eve->co);
+ v1->f= eve->f;
+ eve->f-= flag;
+ eve->f|= 128;
+ eve->vn= v1;
+#ifdef __NLA
+ /* >>>>> FIXME: Copy deformation weight ? */
+ v1->totweight = eve->totweight;
+ if (eve->totweight){
+ v1->dw = MEM_mallocN (eve->totweight * sizeof(MDeformWeight), "deformWeight");
+ memcpy (v1->dw, eve->dw, eve->totweight * sizeof(MDeformWeight));
+ }
+ else
+ v1->dw=NULL;
+#endif
+ }
+ eve= eve->prev;
+ }
+ eed= G.eded.first;
+ while(eed) {
+ if( (eed->v1->f & 128) && (eed->v2->f & 128) ) {
+ v1= eed->v1->vn;
+ v2= eed->v2->vn;
+ addedgelist(v1,v2);
+ }
+ eed= eed->next;
+ }
+
+ /* tenslotte de vlakken dupliceren */
+ evl= G.edvl.first;
+ while(evl) {
+ if( (evl->v1->f & 128) && (evl->v2->f & 128) && (evl->v3->f & 128) ) {
+ if(evl->v4) {
+ if(evl->v4->f & 128) {
+ v1= evl->v1->vn;
+ v2= evl->v2->vn;
+ v3= evl->v3->vn;
+ v4= evl->v4->vn;
+ addvlaklist(v1, v2, v3, v4, evl);
+ }
+ }
+ else {
+ v1= evl->v1->vn;
+ v2= evl->v2->vn;
+ v3= evl->v3->vn;
+ addvlaklist(v1, v2, v3, 0, evl);
+ }
+ }
+ evl= evl->next;
+ }
+}
+
+static void delvlakflag(int flag)
+{
+ /* alle vlak 3/4 verts flag + edges + losse vertices deleten */
+ /* van alle verts wordt 'flag' gewist */
+ EditVert *eve,*nextve;
+ EditEdge *eed, *nexted;
+ EditVlak *evl,*nextvl;
+
+ eed= G.eded.first;
+ while(eed) {
+ eed->f= 0;
+ eed= eed->next;
+ }
+
+ evl= G.edvl.first;
+ while(evl) {
+ nextvl= evl->next;
+ if(vlakselectedAND(evl, flag)) {
+
+ evl->e1->f= 1;
+ evl->e2->f= 1;
+ evl->e3->f= 1;
+ if(evl->e4) {
+ evl->e4->f= 1;
+ }
+
+ BLI_remlink(&G.edvl, evl);
+ freevlak(evl);
+ }
+ evl= nextvl;
+ }
+ /* alle vlakken 1, 2 (3) verts select edges behouden */
+ evl= G.edvl.first;
+ while(evl) {
+ evl->e1->f= 0;
+ evl->e2->f= 0;
+ evl->e3->f= 0;
+ if(evl->e4) {
+ evl->e4->f= 0;
+ }
+
+ evl= evl->next;
+ }
+
+ /* alle edges testen op vertices met flag en wissen */
+ eed= G.eded.first;
+ while(eed) {
+ nexted= eed->next;
+ if(eed->f==1) {
+ remedge(eed);
+ free(eed);
+ }
+ else if( (eed->v1->f & flag) || (eed->v2->f & flag) ) {
+ eed->v1->f&= ~flag;
+ eed->v2->f&= ~flag;
+ }
+ eed= nexted;
+ }
+ /* vertices met flag nog gezet zijn losse en worden verwijderd */
+ eve= G.edve.first;
+ while(eve) {
+ nextve= eve->next;
+ if(eve->f & flag) {
+ BLI_remlink(&G.edve, eve);
+// free(eve);
+ free_editvert(eve);
+ }
+ eve= nextve;
+ }
+
+}
+
+void extrude_mesh(void)
+{
+ short a;
+
+ TEST_EDITMESH
+
+ if(okee("Extrude")==0) return;
+
+ waitcursor(1);
+
+ a= extrudeflag(1,1);
+ waitcursor(0);
+ if(a==0) {
+ error("Can't extrude");
+ }
+ else {
+ countall(); /* voor G.totvert in calc_meshverts() */
+ calc_meshverts();
+ transform('d');
+ }
+
+}
+
+void adduplicate_mesh(void)
+{
+
+ TEST_EDITMESH
+
+ waitcursor(1);
+ adduplicateflag(1);
+ waitcursor(0);
+
+ countall(); /* voor G.totvert in calc_meshverts() */
+ transform('d');
+}
+
+void split_mesh(void)
+{
+
+ TEST_EDITMESH
+
+ if(okee(" Split ")==0) return;
+
+ waitcursor(1);
+
+ /* eerst duplicate maken */
+ adduplicateflag(1);
+ /* oude vlakken hebben 3x flag 128 gezet, deze deleten */
+ delvlakflag(128);
+
+ waitcursor(0);
+
+ countall();
+ allqueue(REDRAWVIEW3D, 0);
+ makeDispList(G.obedit);
+}
+
+void separate_mesh(void)
+{
+ EditVert *eve, *v1;
+ EditEdge *eed, *e1;
+ EditVlak *evl, *vl1;
+ Object *oldob;
+ Mesh *me, *men;
+ Base *base, *oldbase;
+ ListBase edve, eded, edvl;
+ float trans[9];
+ int ok, flag;
+
+ TEST_EDITMESH
+
+ if(okee("Separate")==0) return;
+
+ waitcursor(1);
+
+ me= get_mesh(G.obedit);
+ if(me->key) {
+ error("Can't separate with vertex keys");
+ return;
+ }
+
+ /* we gaan de zaak als volgt neppen:
+ * 1. duplicate object: dit wordt de nieuwe, oude pointer onthouden
+ * 2: split doen als modig.
+ * 3. alle NIET geselecteerde verts, edges, vlakken apart zetten
+ * 4. loadobeditdata(): dit is de nieuwe ob
+ * 5. freelist en oude verts, eds, vlakken weer terughalen
+ */
+
+ /* alleen obedit geselecteerd */
+ base= FIRSTBASE;
+ while(base) {
+ if(base->lay & G.vd->lay) {
+ if(base->object==G.obedit) base->flag |= SELECT;
+ else base->flag &= ~SELECT;
+ }
+ base= base->next;
+ }
+
+ /* testen of split */
+ ok= 0;
+ eed= G.eded.first;
+ while(eed) {
+ flag= (eed->v1->f & 1)+(eed->v2->f & 1);
+ if(flag==1) {
+ ok= 1;
+ break;
+ }
+ eed= eed->next;
+ }
+ if(ok) {
+ /* SPLIT: eerst duplicate maken */
+ adduplicateflag(1);
+ /* SPLIT: oude vlakken hebben 3x flag 128 gezet, deze deleten */
+ delvlakflag(128);
+ }
+
+ /* apart zetten: alles wat maar enigszins NIET select is */
+ edve.first= edve.last= eded.first= eded.last= edvl.first= edvl.last= 0;
+ eve= G.edve.first;
+ while(eve) {
+ v1= eve->next;
+ if((eve->f & 1)==0) {
+ BLI_remlink(&G.edve, eve);
+ BLI_addtail(&edve, eve);
+ }
+ eve= v1;
+ }
+ eed= G.eded.first;
+ while(eed) {
+ e1= eed->next;
+ if( (eed->v1->f & 1)==0 || (eed->v2->f & 1)==0 ) {
+ BLI_remlink(&G.eded, eed);
+ BLI_addtail(&eded, eed);
+ }
+ eed= e1;
+ }
+ evl= G.edvl.first;
+ while(evl) {
+ vl1= evl->next;
+ if( (evl->v1->f & 1)==0 || (evl->v2->f & 1)==0 || (evl->v3->f & 1)==0 ) {
+ BLI_remlink(&G.edvl, evl);
+ BLI_addtail(&edvl, evl);
+ }
+ evl= vl1;
+ }
+
+ oldob= G.obedit;
+ oldbase= BASACT;
+
+ trans[0]=trans[1]=trans[2]=trans[3]=trans[4]=trans[5]= 0.0;
+ trans[6]=trans[7]=trans[8]= 1.0;
+ G.qual |= LR_ALTKEY; /* patch om zeker te zijn van gelinkte dupli */
+ adduplicate(trans);
+ G.qual &= ~LR_ALTKEY;
+
+ G.obedit= BASACT->object; /* basact wordt in adduplicate() gezet */
+
+ men= copy_mesh(me);
+ set_mesh(G.obedit, men);
+ /* omdat nieuwe mesh een kopie is: aantal users verlagen */
+ men->id.us--;
+
+ load_editMesh();
+
+ BASACT->flag &= ~SELECT;
+
+ makeDispList(G.obedit);
+ free_editMesh();
+
+ G.edve= edve;
+ G.eded= eded;
+ G.edvl= edvl;
+
+ /* hashedges are freed now, make new! */
+ eed= G.eded.first;
+ while(eed) {
+ if( findedgelist(eed->v1, eed->v2)==NULL )
+ insert_hashedge(eed);
+ eed= eed->next;
+ }
+
+ G.obedit= oldob;
+ BASACT= oldbase;
+ BASACT->flag |= SELECT;
+
+ waitcursor(0);
+
+ countall();
+ allqueue(REDRAWVIEW3D, 0);
+ makeDispList(G.obedit);
+
+}
+
+void extrude_repeat_mesh(int steps, float offs)
+{
+ float dvec[3], tmat[3][3], bmat[3][3];
+/* float phi; */
+ short a,ok;
+
+ TEST_EDITMESH
+ waitcursor(1);
+
+ /* dvec */
+ dvec[0]= G.vd->persinv[2][0];
+ dvec[1]= G.vd->persinv[2][1];
+ dvec[2]= G.vd->persinv[2][2];
+ Normalise(dvec);
+ dvec[0]*= offs;
+ dvec[1]*= offs;
+ dvec[2]*= offs;
+
+ /* base correctie */
+ Mat3CpyMat4(bmat, G.obedit->obmat);
+ /* phi= ((struct ObData *)G.obedit->d)->vv->ws; */
+ /* Mat3MulFloat(bmat, phi); */
+ Mat3Inv(tmat, bmat);
+ Mat3MulVecfl(tmat, dvec);
+
+ for(a=0;a<steps;a++) {
+ ok= extrudeflag(1,1);
+ if(ok==0) {
+ error("Can't extrude");
+ break;
+ }
+ translateflag(1, dvec);
+ }
+
+ countall();
+ allqueue(REDRAWVIEW3D, 0);
+ makeDispList(G.obedit);
+ waitcursor(0);
+}
+
+void spin_mesh(int steps,int degr,float *dvec, int mode)
+{
+ EditVert *eve,*nextve;
+ float *curs, si,n[3],q[4],cmat[3][3],imat[3][3], tmat[3][3];
+ float cent[3],bmat[3][3];
+ float phi;
+ short a,ok;
+
+ TEST_EDITMESH
+
+ waitcursor(1);
+
+ /* imat en centrum en afmeting */
+ Mat3CpyMat4(bmat, G.obedit->obmat);
+ Mat3Inv(imat,bmat);
+
+ curs= give_cursor();
+ VECCOPY(cent, curs);
+ cent[0]-= G.obedit->obmat[3][0];
+ cent[1]-= G.obedit->obmat[3][1];
+ cent[2]-= G.obedit->obmat[3][2];
+ Mat3MulVecfl(imat, cent);
+
+ phi= degr*M_PI/360.0;
+ phi/= steps;
+ if(editbutflag & B_CLOCKWISE) phi= -phi;
+
+ if(dvec) {
+ n[0]=n[1]= 0.0;
+ n[2]= 1.0;
+ } else {
+ n[0]= G.vd->viewinv[2][0];
+ n[1]= G.vd->viewinv[2][1];
+ n[2]= G.vd->viewinv[2][2];
+ Normalise(n);
+ }
+
+ q[0]= cos(phi);
+ si= sin(phi);
+ q[1]= n[0]*si;
+ q[2]= n[1]*si;
+ q[3]= n[2]*si;
+ QuatToMat3(q, cmat);
+
+ Mat3MulMat3(tmat,cmat,bmat);
+ Mat3MulMat3(bmat,imat,tmat);
+
+ if(mode==0) if(editbutflag & B_KEEPORIG) adduplicateflag(1);
+ ok= 1;
+
+ for(a=0;a<steps;a++) {
+ if(mode==0) ok= extrudeflag(1,1);
+ else adduplicateflag(1);
+ if(ok==0) {
+ error("Can't spin");
+ break;
+ }
+ rotateflag(1, cent, bmat);
+ if(dvec) {
+ Mat3MulVecfl(bmat,dvec);
+ translateflag(1,dvec);
+ }
+ }
+
+ waitcursor(0);
+ if(ok==0) {
+ /* geen of alleen losse verts select, dups verwijderen */
+ eve= G.edve.first;
+ while(eve) {
+ nextve= eve->next;
+ if(eve->f & 1) {
+ BLI_remlink(&G.edve,eve);
+// free(eve);
+ free_editvert(eve);
+ }
+ eve= nextve;
+ }
+ }
+ countall();
+ recalc_editnormals();
+ allqueue(REDRAWVIEW3D, 0);
+ makeDispList(G.obedit);
+}
+
+void screw_mesh(int steps,int turns)
+{
+ EditVert *eve,*v1=0,*v2=0;
+ EditEdge *eed;
+ float dvec[3], nor[3];
+
+ TEST_EDITMESH
+
+ /* eerste voorwaarde: frontview! */
+ if(G.vd->view!=1) {
+ error("Only in frontview!");
+ return;
+ }
+
+ /* flags wissen */
+ eve= G.edve.first;
+ while(eve) {
+ eve->f1= 0;
+ eve= eve->next;
+ }
+ /* edges zetten flags in verts */
+ eed= G.eded.first;
+ while(eed) {
+ if(eed->v1->f & 1) {
+ if(eed->v2->f & 1) {
+ /* oppassen f1 is een byte */
+ if(eed->v1->f1<2) eed->v1->f1++;
+ if(eed->v2->f1<2) eed->v2->f1++;
+ }
+ }
+ eed= eed->next;
+ }
+ /* vind twee vertices met eve->f1==1, meer of minder is fout */
+ eve= G.edve.first;
+ while(eve) {
+ if(eve->f1==1) {
+ if(v1==0) v1= eve;
+ else if(v2==0) v2= eve;
+ else {
+ v1=0;
+ break;
+ }
+ }
+ eve= eve->next;
+ }
+ if(v1==0 || v2==0) {
+ error("No curve selected");
+ return;
+ }
+
+ /* bereken dvec */
+ dvec[0]= ( (v1->co[0]- v2->co[0]) )/(steps);
+ dvec[1]= ( (v1->co[1]- v2->co[1]) )/(steps);
+ dvec[2]= ( (v1->co[2]- v2->co[2]) )/(steps);
+
+ VECCOPY(nor, G.obedit->obmat[2]);
+
+ if(nor[0]*dvec[0]+nor[1]*dvec[1]+nor[2]*dvec[2]>0.000) {
+ dvec[0]= -dvec[0];
+ dvec[1]= -dvec[1];
+ dvec[2]= -dvec[2];
+ }
+
+ spin_mesh(turns*steps, turns*360, dvec, 0);
+
+}
+
+void selectswap_mesh(void)
+{
+ EditVert *eve;
+
+ eve= G.edve.first;
+ while(eve) {
+ if(eve->h==0) {
+ if(eve->f & 1) eve->f&= ~1;
+ else eve->f|= 1;
+ }
+ eve= eve->next;
+ }
+ countall();
+ allqueue(REDRAWVIEW3D, 0);
+
+}
+
+/* ******************************* ADD ********************* */
+
+void addvert_mesh(void)
+{
+ EditVert *eve,*v1=0;
+ float *curs, mat[3][3],imat[3][3];
+
+ TEST_EDITMESH
+
+ Mat3CpyMat4(mat, G.obedit->obmat);
+ Mat3Inv(imat, mat);
+
+ v1= G.edve.first;
+ while(v1) {
+ if(v1->f & 1) break;
+ v1= v1->next;
+ }
+ eve= v1; /* voorkomen dat er nog meer select zijn */
+ while(eve) {
+ eve->f&= ~1;
+ eve= eve->next;
+ }
+
+ eve= addvertlist(0);
+
+ curs= give_cursor();
+ VECCOPY(eve->co, curs);
+ eve->xs= G.vd->mx;
+ eve->ys= G.vd->my;
+ VecSubf(eve->co, eve->co, G.obedit->obmat[3]);
+
+ Mat3MulVecfl(imat, eve->co);
+ eve->f= 1;
+
+ if(v1) {
+ addedgelist(v1, eve);
+ v1->f= 0;
+ }
+ countall();
+ allqueue(REDRAWVIEW3D, 0);
+ makeDispList(G.obedit);
+
+ while(get_mbut()&R_MOUSE);
+
+}
+
+void addedgevlak_mesh(void)
+{
+ EditVert *eve, *neweve[4];
+ EditVlak *evl;
+ float con1, con2, con3;
+ short aantal=0;
+
+ if( (G.vd->lay & G.obedit->lay)==0 ) return;
+
+ /* hoeveel geselecteerd ? */
+ eve= G.edve.first;
+ while(eve) {
+ if(eve->f & 1) {
+ aantal++;
+ if(aantal>4) break;
+ neweve[aantal-1]= eve;
+ }
+ eve= eve->next;
+ }
+ if(aantal==2) {
+ addedgelist(neweve[0], neweve[1]);
+ allqueue(REDRAWVIEW3D, 0);
+ makeDispList(G.obedit);
+ return;
+ }
+ if(aantal<2 || aantal>4) {
+ error("Can't make edge/face");
+ return;
+ }
+
+ evl= NULL; // check later
+
+ if(aantal==3) {
+ if(exist_vlak(neweve[0], neweve[1], neweve[2], 0)==0) {
+
+ evl= addvlaklist(neweve[0], neweve[1], neweve[2], 0, NULL);
+
+ }
+ else error("Already a face");
+ }
+ else if(aantal==4) {
+ if(exist_vlak(neweve[0], neweve[1], neweve[2], neweve[3])==0) {
+
+ con1= convex(neweve[0]->co, neweve[1]->co, neweve[2]->co, neweve[3]->co);
+ con2= convex(neweve[0]->co, neweve[2]->co, neweve[3]->co, neweve[1]->co);
+ con3= convex(neweve[0]->co, neweve[3]->co, neweve[1]->co, neweve[2]->co);
+
+ if(con1>=con2 && con1>=con3)
+ evl= addvlaklist(neweve[0], neweve[1], neweve[2], neweve[3], NULL);
+ else if(con2>=con1 && con2>=con3)
+ evl= addvlaklist(neweve[0], neweve[2], neweve[3], neweve[1], NULL);
+ else
+ evl= addvlaklist(neweve[0], neweve[2], neweve[1], neweve[3], NULL);
+
+ }
+ else error("Already a face");
+ }
+
+ if(evl) { // now we're calculating direction of normal
+ float inp;
+ /* dot product view mat with normal, should give info! */
+
+ CalcNormFloat(evl->v1->co, evl->v2->co, evl->v3->co, evl->n);
+
+ inp= evl->n[0]*G.vd->viewmat[0][2] + evl->n[1]*G.vd->viewmat[1][2] + evl->n[2]*G.vd->viewmat[2][2];
+
+ if(inp < 0.0) flipvlak(evl);
+ }
+
+ countall();
+ allqueue(REDRAWVIEW3D, 0);
+ makeDispList(G.obedit);
+}
+
+static void erase_edges(ListBase *l)
+{
+ EditEdge *ed, *nexted;
+
+ ed = (EditEdge *) l->first;
+ while(ed) {
+ nexted= ed->next;
+ if( (ed->v1->f & 1) || (ed->v2->f & 1) ) {
+ remedge(ed);
+ free(ed);
+ }
+ ed= nexted;
+ }
+}
+
+static void erase_faces(ListBase *l)
+{
+ EditVlak *f, *nextf;
+
+ f = (EditVlak *) l->first;
+
+ while(f) {
+ nextf= f->next;
+ if( vlakselectedOR(f, 1) ) {
+ BLI_remlink(l, f);
+ freevlak(f);
+ }
+ f = nextf;
+ }
+}
+
+static void erase_vertices(ListBase *l)
+{
+ EditVert *v, *nextv;
+
+ v = (EditVert *) l->first;
+ while(v) {
+ nextv= v->next;
+ if(v->f & 1) {
+ BLI_remlink(l, v);
+ free_editvert(v);
+ }
+ v = nextv;
+ }
+}
+
+void delete_mesh(void)
+{
+ EditVlak *evl, *nextvl;
+ EditVert *eve,*nextve;
+ EditEdge *eed,*nexted;
+ short event;
+ int count;
+
+ TEST_EDITMESH
+
+ event= pupmenu("ERASE %t|Vertices%x10|Edges%x1|Faces%x2|All%x3|Edges & Faces%x4|Only Faces%x5");
+ if(event<1) return;
+
+ if(event==10 ) {
+ erase_edges(&G.eded);
+ erase_faces(&G.edvl);
+ erase_vertices(&G.edve);
+ }
+ else if(event==4) {
+ evl= G.edvl.first;
+ while(evl) {
+ nextvl= evl->next;
+ /* delete only faces with 2 or more vertices selected */
+ count= 0;
+ if(evl->v1->f & 1) count++;
+ if(evl->v2->f & 1) count++;
+ if(evl->v3->f & 1) count++;
+ if(evl->v4 && (evl->v4->f & 1)) count++;
+ if(count>1) {
+ BLI_remlink(&G.edvl, evl);
+ freevlak(evl);
+ }
+ evl= nextvl;
+ }
+ eed= G.eded.first;
+ while(eed) {
+ nexted= eed->next;
+ if( (eed->v1->f & 1) && (eed->v2->f & 1) ) {
+ remedge(eed);
+ free(eed);
+ }
+ eed= nexted;
+ }
+ evl= G.edvl.first;
+ while(evl) {
+ nextvl= evl->next;
+ event=0;
+ if( evl->v1->f & 1) event++;
+ if( evl->v2->f & 1) event++;
+ if( evl->v3->f & 1) event++;
+ if(evl->v4 && (evl->v4->f & 1)) event++;
+
+ if(event>1) {
+ BLI_remlink(&G.edvl, evl);
+ freevlak(evl);
+ }
+ evl= nextvl;
+ }
+ }
+ else if(event==1) {
+ eed= G.eded.first;
+ while(eed) {
+ nexted= eed->next;
+ if( (eed->v1->f & 1) && (eed->v2->f & 1) ) {
+ remedge(eed);
+ free(eed);
+ }
+ eed= nexted;
+ }
+ evl= G.edvl.first;
+ while(evl) {
+ nextvl= evl->next;
+ event=0;
+ if( evl->v1->f & 1) event++;
+ if( evl->v2->f & 1) event++;
+ if( evl->v3->f & 1) event++;
+ if(evl->v4 && (evl->v4->f & 1)) event++;
+
+ if(event>1) {
+ BLI_remlink(&G.edvl, evl);
+ freevlak(evl);
+ }
+ evl= nextvl;
+ }
+ /* om losse vertices te wissen: */
+ eed= G.eded.first;
+ while(eed) {
+ if( eed->v1->f & 1) eed->v1->f-=1;
+ if( eed->v2->f & 1) eed->v2->f-=1;
+ eed= eed->next;
+ }
+ eve= G.edve.first;
+ while(eve) {
+ nextve= eve->next;
+ if(eve->f & 1) {
+ BLI_remlink(&G.edve,eve);
+// free(eve);
+ free_editvert(eve);
+ }
+ eve= nextve;
+ }
+
+ }
+ else if(event==2) delvlakflag(1);
+ else if(event==3) {
+// if(G.edve.first) BLI_freelist(&G.edve);
+ if(G.edve.first) free_editverts(&G.edve);
+ if(G.eded.first) BLI_freelist(&G.eded);
+ if(G.edvl.first) freevlaklist(&G.edvl);
+ }
+ else if(event==5) {
+ evl= G.edvl.first;
+ while(evl) {
+ nextvl= evl->next;
+ if(vlakselectedAND(evl, 1)) {
+ BLI_remlink(&G.edvl, evl);
+ freevlak(evl);
+ }
+ evl= nextvl;
+ }
+ }
+
+ countall();
+ allqueue(REDRAWVIEW3D, 0);
+ makeDispList(G.obedit);
+}
+
+
+
+void add_primitiveMesh(int type)
+{
+ Mesh *me;
+ EditVert *eve, *v1=NULL, *v2, *v3, *v4=NULL, *vtop, *vdown;
+ float *curs, d, dia, phi, phid, cent[3], vec[3], imat[3][3], mat[3][3];
+ float q[4], cmat[3][3];
+ static short tot=32, seg=32, subdiv=2;
+ short a, b, ext=0, fill=0, totoud, newob=0;
+
+ if(G.scene->id.lib) return;
+
+ /* this function also comes from an info window */
+ if ELEM(curarea->spacetype, SPACE_VIEW3D, SPACE_INFO); else return;
+ if(G.vd==0) return;
+
+ check_editmode(OB_MESH);
+
+ G.f &= ~(G_VERTEXPAINT+G_FACESELECT+G_TEXTUREPAINT);
+ setcursor_space(SPACE_VIEW3D, CURSOR_STD);
+
+ /* als geen obedit: nieuw object en in editmode gaan */
+ if(G.obedit==0) {
+ /* add_object actually returns an object ! :-)
+ But it also stores the added object struct in
+ G.scene->basact->object (BASACT->object) */
+
+ add_object(OB_MESH);
+ base_init_from_view3d(BASACT, G.vd);
+ G.obedit= BASACT->object;
+
+ where_is_object(G.obedit);
+
+ make_editMesh();
+ setcursor_space(SPACE_VIEW3D, CURSOR_EDIT);
+ newob= 1;
+ }
+ me= G.obedit->data;
+
+ /* deselectall */
+ eve= G.edve.first;
+ while(eve) {
+ if(eve->f & 1) eve->f&= ~1;
+ eve= eve->next;
+ }
+
+ totoud= tot; /* onthouden en terugzetten als cube/plane */
+
+ /* imat en centrum en afmeting */
+ Mat3CpyMat4(mat, G.obedit->obmat);
+
+ curs= give_cursor();
+ VECCOPY(cent, curs);
+ cent[0]-= G.obedit->obmat[3][0];
+ cent[1]-= G.obedit->obmat[3][1];
+ cent[2]-= G.obedit->obmat[3][2];
+
+ if(type!= 11) {
+ Mat3CpyMat4(imat, G.vd->viewmat);
+ Mat3MulVecfl(imat, cent);
+ Mat3MulMat3(cmat, imat, mat);
+ Mat3Inv(imat,cmat);
+ } else {
+ Mat3Inv(imat, mat);
+ }
+
+ /* ext==extrudeflag, tot==aantal verts in basis */
+
+ switch(type) {
+ case 0: /* plane */
+ tot= 4;
+ ext= 0;
+ fill= 1;
+ if(newob) rename_id((ID *)G.obedit, "Plane");
+ if(newob) rename_id((ID *)me, "Plane");
+ break;
+ case 1: /* cube */
+ tot= 4;
+ ext= 1;
+ fill= 1;
+ if(newob) rename_id((ID *)G.obedit, "Cube");
+ if(newob) rename_id((ID *)me, "Cube");
+ break;
+ case 4: /* circle */
+ if(button(&tot,3,100,"Vertices:")==0) return;
+ ext= 0;
+ fill= 0;
+ if(newob) rename_id((ID *)G.obedit, "Circle");
+ if(newob) rename_id((ID *)me, "Circle");
+ break;
+ case 5: /* cylinder */
+ if(button(&tot,3,100,"Vertices:")==0) return;
+ ext= 1;
+ fill= 1;
+ if(newob) rename_id((ID *)G.obedit, "Cylinder");
+ if(newob) rename_id((ID *)me, "Cylinder");
+ break;
+ case 6: /* tube */
+ if(button(&tot,3,100,"Vertices:")==0) return;
+ ext= 1;
+ fill= 0;
+ if(newob) rename_id((ID *)G.obedit, "Tube");
+ if(newob) rename_id((ID *)me, "Tube");
+ break;
+ case 7: /* cone */
+ if(button(&tot,3,100,"Vertices:")==0) return;
+ ext= 0;
+ fill= 1;
+ if(newob) rename_id((ID *)G.obedit, "Cone");
+ if(newob) rename_id((ID *)me, "Cone");
+ break;
+ case 10: /* grid */
+ if(button(&tot,2,100,"X res:")==0) return;
+ if(button(&seg,2,100,"Y res:")==0) return;
+ if(newob) rename_id((ID *)G.obedit, "Grid");
+ if(newob) rename_id((ID *)me, "Grid");
+ break;
+ case 11: /* UVsphere */
+ if(button(&seg,3,100,"Segments:")==0) return;
+ if(button(&tot,3,100,"Rings:")==0) return;
+ if(newob) rename_id((ID *)G.obedit, "Sphere");
+ if(newob) rename_id((ID *)me, "Sphere");
+ break;
+ case 12: /* Icosphere */
+ if(button(&subdiv,1,5,"Subdivision:")==0) return;
+ if(newob) rename_id((ID *)G.obedit, "Sphere");
+ if(newob) rename_id((ID *)me, "Sphere");
+ break;
+ case 13: /* Monkey */
+ if(newob) rename_id((ID *)G.obedit, "Suzanne");
+ if(newob) rename_id((ID *)me, "Suzanne");
+ break;
+ }
+
+ dia= sqrt(2.0)*G.vd->grid;
+ d= -G.vd->grid;
+ phid= 2*M_PI/tot;
+ phi= .25*M_PI;
+
+
+ if(type<10) { /* alles behalve grid of sphere */
+ if(ext==0 && type!=7) d= 0;
+
+ /* de vertices */
+ vtop= vdown= v1= v2= 0;
+ for(b=0; b<=ext; b++) {
+ for(a=0; a<tot; a++) {
+
+ vec[0]= cent[0]+dia*sin(phi);
+ vec[1]= cent[1]+dia*cos(phi);
+ vec[2]= cent[2]+d;
+
+ Mat3MulVecfl(imat, vec);
+ eve= addvertlist(vec);
+ eve->f= 1;
+ if(a==0) {
+ if(b==0) v1= eve;
+ else v2= eve;
+ }
+ phi+=phid;
+ }
+ d= -d;
+ }
+ /* centrum vertices */
+ if(fill && type>1) {
+ VECCOPY(vec,cent);
+ vec[2]-= -d;
+ Mat3MulVecfl(imat,vec);
+ vdown= addvertlist(vec);
+ if(ext || type==7) {
+ VECCOPY(vec,cent);
+ vec[2]-= d;
+ Mat3MulVecfl(imat,vec);
+ vtop= addvertlist(vec);
+ }
+ } else {
+ vdown= v1;
+ vtop= v2;
+ }
+ if(vtop) vtop->f= 1;
+ if(vdown) vdown->f= 1;
+
+ /* boven en ondervlak */
+ if(fill) {
+ if(tot==4 && (type==0 || type==1)) {
+ v3= v1->next->next;
+ if(ext) v4= v2->next->next;
+
+ addvlaklist(v3, v1->next, v1, v3->next, NULL);
+ if(ext) addvlaklist(v2, v2->next, v4, v4->next, NULL);
+
+ }
+ else {
+ v3= v1;
+ v4= v2;
+ for(a=1; a<tot; a++) {
+ addvlaklist(vdown, v3, v3->next, 0, NULL);
+ v3= v3->next;
+ if(ext) {
+ addvlaklist(vtop, v4, v4->next, 0, NULL);
+ v4= v4->next;
+ }
+ }
+ if(type>1) {
+ addvlaklist(vdown, v3, v1, 0, NULL);
+ if(ext) addvlaklist(vtop, v4, v2, 0, NULL);
+ }
+ }
+ }
+ else if(type==4) { /* wel edges bij circle */
+ v3= v1;
+ for(a=1;a<tot;a++) {
+ addedgelist(v3,v3->next);
+ v3= v3->next;
+ }
+ addedgelist(v3,v1);
+ }
+ /* zijvlakken */
+ if(ext) {
+ v3= v1;
+ v4= v2;
+ for(a=1; a<tot; a++) {
+ addvlaklist(v3, v3->next, v4->next, v4, NULL);
+ v3= v3->next;
+ v4= v4->next;
+ }
+ addvlaklist(v3, v1, v2, v4, NULL);
+ }
+ else if(type==7) { /* cone */
+ v3= v1;
+ for(a=1; a<tot; a++) {
+ addvlaklist(vtop, v3->next, v3, 0, NULL);
+ v3= v3->next;
+ }
+ addvlaklist(vtop, v1, v3, 0, NULL);
+ }
+
+ if(type<2) tot= totoud;
+
+ }
+ else if(type==10) { /* grid */
+ /* alle flags wissen */
+ eve= G.edve.first;
+ while(eve) {
+ eve->f= 0;
+ eve= eve->next;
+ }
+ dia= G.vd->grid;
+ /* eerst een segment: de X as */
+ phi= -1.0;
+ phid= 2.0/((float)tot-1);
+ for(a=0;a<tot;a++) {
+ vec[0]= cent[0]+dia*phi;
+ vec[1]= cent[1]- dia;
+ vec[2]= cent[2];
+ Mat3MulVecfl(imat,vec);
+ eve= addvertlist(vec);
+ eve->f= 1+2+4;
+ if (a) addedgelist(eve->prev,eve);
+ phi+=phid;
+ }
+ /* extruden en transleren */
+ vec[0]= vec[2]= 0.0;
+ vec[1]= dia*phid;
+ Mat3MulVecfl(imat, vec);
+ for(a=0;a<seg-1;a++) {
+ extrudeflag(2,0);
+ translateflag(2, vec);
+ }
+ }
+ else if(type==11) { /* UVsphere */
+ float tmat[3][3];
+
+ /* alle flags wissen */
+ eve= G.edve.first;
+ while(eve) {
+ eve->f= 0;
+ eve= eve->next;
+ }
+
+ /* eerst een segment */
+ phi= 0;
+ phid/=2;
+ for(a=0; a<=tot; a++) {
+ vec[0]= cent[0]+dia*sin(phi);
+ vec[1]= cent[1];
+ vec[2]= cent[2]+dia*cos(phi);
+ Mat3MulVecfl(imat,vec);
+ eve= addvertlist(vec);
+ eve->f= 1+2+4;
+ if(a==0) v1= eve;
+ else addedgelist(eve->prev, eve);
+ phi+= phid;
+ }
+
+ /* extruden en roteren */
+ phi= M_PI/seg;
+ q[0]= cos(phi);
+ q[3]= sin(phi);
+ q[1]=q[2]= 0;
+ QuatToMat3(q, cmat);
+ Mat3MulMat3(tmat, cmat, mat);
+ Mat3MulMat3(cmat, imat, tmat);
+
+ for(a=0; a<seg; a++) {
+ extrudeflag(2, 0);
+ rotateflag(2, v1->co, cmat);
+ }
+ removedoublesflag(4, 0.01);
+ }
+ else if(type==12) { /* Icosphere */
+ EditVert *eva[12];
+
+ /* alle flags wissen */
+ eve= G.edve.first;
+ while(eve) {
+ eve->f= 0;
+ eve= eve->next;
+ }
+ dia/=200;
+ for(a=0;a<12;a++) {
+ vec[0]= dia*icovert[a][0];
+ vec[1]= dia*icovert[a][1];
+ vec[2]= dia*icovert[a][2];
+ eva[a]= addvertlist(vec);
+ eva[a]->f= 1+2;
+ }
+ for(a=0;a<20;a++) {
+ v1= eva[ icovlak[a][0] ];
+ v2= eva[ icovlak[a][1] ];
+ v3= eva[ icovlak[a][2] ];
+ addvlaklist(v1, v2, v3, 0, NULL);
+ }
+
+ dia*=200;
+ for(a=1; a<subdiv; a++) subdivideflag(2, dia, 0);
+ /* nu pas met imat */
+ eve= G.edve.first;
+ while(eve) {
+ if(eve->f & 2) {
+ VecAddf(eve->co,eve->co,cent);
+ Mat3MulVecfl(imat,eve->co);
+ }
+ eve= eve->next;
+ }
+ } else if (type==13) { /* Monkey */
+ extern int monkeyo, monkeynv, monkeynf;
+ extern signed char monkeyf[][4];
+ extern signed char monkeyv[][3];
+ EditVert **tv= MEM_mallocN(sizeof(*tv)*monkeynv*2, "tv");
+ int i;
+
+ for (i=0; i<monkeynv; i++) {
+ float v[3];
+ v[0]= (monkeyv[i][0]+127)/128.0, v[1]= monkeyv[i][1]/128.0, v[2]= monkeyv[i][2]/128.0;
+ tv[i]= addvertlist(v);
+ tv[monkeynv+i]= (fabs(v[0]= -v[0])<0.001)?tv[i]:addvertlist(v);
+ }
+ for (i=0; i<monkeynf; i++) {
+ addvlaklist(tv[monkeyf[i][0]+i-monkeyo], tv[monkeyf[i][1]+i-monkeyo], tv[monkeyf[i][2]+i-monkeyo], (monkeyf[i][3]!=monkeyf[i][2])?tv[monkeyf[i][3]+i-monkeyo]:NULL, NULL);
+ addvlaklist(tv[monkeynv+monkeyf[i][2]+i-monkeyo], tv[monkeynv+monkeyf[i][1]+i-monkeyo], tv[monkeynv+monkeyf[i][0]+i-monkeyo], (monkeyf[i][3]!=monkeyf[i][2])?tv[monkeynv+monkeyf[i][3]+i-monkeyo]:NULL, NULL);
+ }
+
+ MEM_freeN(tv);
+ }
+
+ if(type!=0 && type!=10) righthandfaces(1);
+ countall();
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWIPO, 0);
+ allqueue(REDRAWHEADERS, 0);
+ allqueue(REDRAWINFO, 1); /* 1, want header->win==0! */
+ allqueue(REDRAWBUTSEDIT, 0);
+ makeDispList(G.obedit);
+
+ if (type==13) notice("Oooh Oooh Oooh");
+}
+
+void vertexsmooth(void)
+{
+ struct EditVert *eve;
+ struct EditEdge *eed;
+ float *adror, *adr, fac;
+ float fvec[3];
+ int teller=0;
+
+ if(G.obedit==0) return;
+
+ /* aantal tellen */
+ eve= G.edve.first;
+ while(eve) {
+ if(eve->f & 1) teller++;
+ eve= eve->next;
+ }
+ if(teller==0) return;
+
+ adr=adror= (float *)MEM_callocN(3*sizeof(float *)*teller, "vertsmooth");
+ eve= G.edve.first;
+ while(eve) {
+ if(eve->f & 1) {
+ eve->vn= (EditVert *)adr;
+ eve->f1= 0;
+ adr+= 3;
+ }
+ eve= eve->next;
+ }
+
+ eed= G.eded.first;
+ while(eed) {
+ if( (eed->v1->f & 1) || (eed->v2->f & 1) ) {
+ fvec[0]= (eed->v1->co[0]+eed->v2->co[0])/2.0;
+ fvec[1]= (eed->v1->co[1]+eed->v2->co[1])/2.0;
+ fvec[2]= (eed->v1->co[2]+eed->v2->co[2])/2.0;
+
+ if((eed->v1->f & 1) && eed->v1->f1<255) {
+ eed->v1->f1++;
+ VecAddf((float *)eed->v1->vn, (float *)eed->v1->vn, fvec);
+ }
+ if((eed->v2->f & 1) && eed->v2->f1<255) {
+ eed->v2->f1++;
+ VecAddf((float *)eed->v2->vn, (float *)eed->v2->vn, fvec);
+ }
+ }
+ eed= eed->next;
+ }
+
+ eve= G.edve.first;
+ while(eve) {
+ if(eve->f & 1) {
+ if(eve->f1) {
+ adr= (float *)eve->vn;
+ fac= 0.5/(float)eve->f1;
+
+ eve->co[0]= 0.5*eve->co[0]+fac*adr[0];
+ eve->co[1]= 0.5*eve->co[1]+fac*adr[1];
+ eve->co[2]= 0.5*eve->co[2]+fac*adr[2];
+ }
+ eve->vn= 0;
+ }
+ eve= eve->next;
+ }
+ MEM_freeN(adror);
+
+ allqueue(REDRAWVIEW3D, 0);
+ makeDispList(G.obedit);
+}
+
+
+void vertexnoise(void)
+{
+ extern float Tin;
+ Material *ma;
+ Tex *tex;
+ EditVert *eve;
+ float b2, ofs, vec[3];
+
+ if(G.obedit==0) return;
+
+ ma= give_current_material(G.obedit, G.obedit->actcol);
+ if(ma==0 || ma->mtex[0]==0 || ma->mtex[0]->tex==0) {
+ return;
+ }
+ tex= ma->mtex[0]->tex;
+
+ ofs= tex->turbul/200.0;
+
+ eve= (struct EditVert *)G.edve.first;
+ while(eve) {
+ if(eve->f & 1) {
+
+ if(tex->type==TEX_STUCCI) {
+
+ b2= BLI_hnoise(tex->noisesize, eve->co[0], eve->co[1], eve->co[2]);
+ if(tex->stype) ofs*=(b2*b2);
+ vec[0]= 0.2*(b2-BLI_hnoise(tex->noisesize, eve->co[0]+ofs, eve->co[1], eve->co[2]));
+ vec[1]= 0.2*(b2-BLI_hnoise(tex->noisesize, eve->co[0], eve->co[1]+ofs, eve->co[2]));
+ vec[2]= 0.2*(b2-BLI_hnoise(tex->noisesize, eve->co[0], eve->co[1], eve->co[2]+ofs));
+
+ VecAddf(eve->co, eve->co, vec);
+ }
+ else {
+
+ externtex(ma->mtex[0], eve->co);
+
+ eve->co[2]+= 0.05*Tin;
+ }
+ }
+ eve= eve->next;
+ }
+
+ allqueue(REDRAWVIEW3D, 0);
+ makeDispList(G.obedit);
+}
+
+void hide_mesh(int swap)
+{
+ struct EditVert *eve;
+ struct EditEdge *eed;
+
+ if(G.obedit==0) return;
+
+ if(swap) {
+ eve= G.edve.first;
+ while(eve) {
+ if((eve->f & 1)==0) {
+ eve->xs= 3200;
+ eve->h= 1;
+ }
+ eve= eve->next;
+ }
+ }
+ else {
+ eve= G.edve.first;
+ while(eve) {
+ if(eve->f & 1) {
+ eve->f-=1;
+ eve->xs= 3200;
+ eve->h= 1;
+ }
+ eve= eve->next;
+ }
+ }
+ eed= G.eded.first;
+ while(eed) {
+ if(eed->v1->h || eed->v2->h) eed->h= 1;
+ else eed->h= 0;
+ eed= eed->next;
+ }
+
+ allqueue(REDRAWVIEW3D, 0);
+ makeDispList(G.obedit);
+}
+
+
+void reveal_mesh(void)
+{
+ struct EditVert *eve;
+ struct EditEdge *eed;
+
+ if(G.obedit==0) return;
+
+ eve= G.edve.first;
+ while(eve) {
+ if(eve->h) {
+ eve->h= 0;
+ eve->f|=1;
+ }
+ eve= eve->next;
+ }
+
+ eed= G.eded.first;
+ while(eed) {
+ eed->h= 0;
+ eed= eed->next;
+ }
+
+ allqueue(REDRAWVIEW3D, 0);
+ makeDispList(G.obedit);
+}
+
+static float convex(float *v1, float *v2, float *v3, float *v4)
+{
+ float cross[3], test[3];
+ float inpr;
+
+ CalcNormFloat(v1, v2, v3, cross);
+ CalcNormFloat(v1, v3, v4, test);
+
+ inpr= cross[0]*test[0]+cross[1]*test[1]+cross[2]*test[2];
+
+ return inpr;
+}
+
+/* returns vertices of two adjacent triangles forming a quad
+ - can be righthand or lefthand
+
+ 4-----3
+ |\ |
+ | \ 2 | <- evl1
+ | \ |
+ evl-> | 1 \ |
+ | \|
+ 1-----2
+
+*/
+#define VTEST(face, num, other) \
+ (face->v##num != other->v1 && face->v##num != other->v2 && face->v##num != other->v3)
+
+static void givequadverts(EditVlak *evl, EditVlak *evl1, EditVert **v1, EditVert **v2, EditVert **v3, EditVert **v4, float **uv, unsigned int *col)
+{
+ if VTEST(evl, 1, evl1) {
+ //if(evl->v1!=evl1->v1 && evl->v1!=evl1->v2 && evl->v1!=evl1->v3) {
+ *v1= evl->v1;
+ *v2= evl->v2;
+ uv[0] = evl->uv[0];
+ uv[1] = evl->uv[1];
+ col[0] = evl->col[0];
+ col[1] = evl->col[1];
+ }
+ else if VTEST(evl, 2, evl1) {
+ //else if(evl->v2!=evl1->v1 && evl->v2!=evl1->v2 && evl->v2!=evl1->v3) {
+ *v1= evl->v2;
+ *v2= evl->v3;
+ uv[0] = evl->uv[1];
+ uv[1] = evl->uv[2];
+ col[0] = evl->col[1];
+ col[1] = evl->col[2];
+ }
+ else if VTEST(evl, 3, evl1) {
+ // else if(evl->v3!=evl1->v1 && evl->v3!=evl1->v2 && evl->v3!=evl1->v3) {
+ *v1= evl->v3;
+ *v2= evl->v1;
+ uv[0] = evl->uv[2];
+ uv[1] = evl->uv[0];
+ col[0] = evl->col[2];
+ col[1] = evl->col[0];
+ }
+
+ if VTEST(evl1, 1, evl) {
+ // if(evl1->v1!=evl->v1 && evl1->v1!=evl->v2 && evl1->v1!=evl->v3) {
+ *v3= evl1->v1;
+ uv[2] = evl1->uv[0];
+ col[2] = evl1->col[0];
+
+ *v4= evl1->v2;
+ uv[3] = evl1->uv[1];
+ col[3] = evl1->col[1];
+/*
+if(evl1->v2== *v2) {
+ *v4= evl1->v3;
+ uv[3] = evl1->uv[2];
+ } else {
+ *v4= evl1->v2;
+ uv[3] = evl1->uv[1];
+ }
+ */
+ }
+ else if VTEST(evl1, 2, evl) {
+ // else if(evl1->v2!=evl->v1 && evl1->v2!=evl->v2 && evl1->v2!=evl->v3) {
+ *v3= evl1->v2;
+ uv[2] = evl1->uv[1];
+ col[2] = evl1->col[1];
+
+ *v4= evl1->v3;
+ uv[3] = evl1->uv[2];
+ col[3] = evl1->col[2];
+/*
+if(evl1->v3== *v2) {
+ *v4= evl1->v1;
+ uv[3] = evl1->uv[0];
+ } else {
+ *v4= evl1->v3;
+ uv[3] = evl1->uv[2];
+ }
+ */
+ }
+ else if VTEST(evl1, 3, evl) {
+ // else if(evl1->v3!=evl->v1 && evl1->v3!=evl->v2 && evl1->v3!=evl->v3) {
+ *v3= evl1->v3;
+ uv[2] = evl1->uv[2];
+ col[2] = evl1->col[2];
+
+ *v4= evl1->v1;
+ uv[3] = evl1->uv[0];
+ col[3] = evl1->col[0];
+/*
+if(evl1->v1== *v2) {
+ *v4= evl1->v2;
+ uv[3] = evl1->uv[3];
+ } else {
+ *v4= evl1->v1;
+ uv[3] = evl1->uv[0];
+ }
+ */
+ }
+ else {
+ pupmenu("Wanna crash?%t|Yes Please!%x1");
+ return;
+ }
+
+}
+
+
+/* ook weer twee zeer vreemde 'patch' functies om de uv van tfaces te bewaren */
+/*
+static float *set_correct_uv(EditVert *eve, EditVlak **evla)
+{
+
+ if(eve== evla[1]->v3) return evla[1]->uv[2];
+ if(eve== evla[0]->v3) return evla[0]->uv[2];
+ if(eve== evla[1]->v2) return evla[1]->uv[1];
+ if(eve== evla[0]->v2) return evla[0]->uv[1];
+ if(eve== evla[1]->v1) return evla[1]->uv[0];
+ if(eve== evla[0]->v1) return evla[0]->uv[0];
+ return 0;
+}
+
+crazy code commented out..
+static void restore_wuv(EditVlak *evl, void **evla)
+{
+ int *lp;
+
+ lp= (int *)set_correct_uv(evl->v1, (EditVlak **)evla);
+ ((int *)(evl->uv[0]))[0]= lp[0];
+ ((int *)(evl->uv[0]))[4]= lp[4];
+
+ lp= (int *)set_correct_uv(evl->v2, (EditVlak **)evla);
+ ((int *)(evl->uv[1]))[0]= lp[0];
+ ((int *)(evl->uv[1]))[4]= lp[4];
+
+ lp= (int *)set_correct_uv(evl->v3, (EditVlak **)evla);
+ ((int *)(evl->uv[2]))[0]= lp[0];
+ ((int *)(evl->uv[2]))[4]= lp[4];
+
+}
+*/
+
+
+/* Helper functions for edge/quad edit features*/
+/*
+
+*/
+
+static void untag_edges(EditVlak *f)
+{
+ f->e1->f = 0;
+ f->e2->f = 0;
+ if (f->e3) f->e3->f = 0;
+ if (f->e4) f->e4->f = 0;
+}
+
+#if 0
+static void mark_clear_edges(EditVlak *f)
+{
+ f->e1->f1 = 1;
+ f->e2->f1 = 1;
+ if (f->e3) f->e3->f1 = 1;
+ if (f->e4) f->e4->f1 = 1;
+}
+#endif
+
+static int count_edges(EditEdge *ed)
+{
+ int totedge = 0;
+ while(ed) {
+ ed->vn= 0;
+ if( (ed->v1->f & 1) && (ed->v2->f & 1) ) totedge++;
+ ed= ed->next;
+ }
+ return totedge;
+}
+
+/** remove and free list of tagged edges */
+static void free_tagged_edgelist(EditEdge *eed)
+{
+ EditEdge *nexted;
+
+ while(eed) {
+ nexted= eed->next;
+ if(eed->f1) {
+ remedge(eed);
+ free(eed);
+ }
+ eed= nexted;
+ }
+}
+/** remove and free list of tagged faces */
+
+static void free_tagged_facelist(EditVlak *evl)
+{
+ EditVlak *nextvl;
+
+ while(evl) {
+ nextvl= evl->next;
+ if(evl->f1) {
+ BLI_remlink(&G.edvl, evl);
+ freevlak(evl);
+ }
+ evl= nextvl;
+ }
+}
+
+typedef EditVlak *EVPtr;
+typedef EVPtr EVPTuple[2];
+
+/** builds EVPTuple array evla of face tuples (in fact pointers to EditVlaks)
+ sharing one edge.
+ arguments: selected edge list, face list.
+ Edges will also be tagged accordingly (see eed->f) */
+
+static int collect_quadedges(EVPTuple *evla, EditEdge *eed, EditVlak *evl)
+{
+ int i = 0;
+ EditEdge *e1, *e2, *e3;
+ EVPtr *evp;
+
+ /* run through edges, if selected, set pointer edge-> facearray */
+ while(eed) {
+ eed->f= 0;
+ eed->f1= 0;
+ if( (eed->v1->f & 1) && (eed->v2->f & 1) ) {
+ eed->vn= (EditVert *) (&evla[i]);
+ i++;
+ }
+ eed= eed->next;
+ }
+
+
+ /* find edges pointing to 2 faces by procedure:
+
+ - run through faces and their edges, increase
+ face counter e->f for each face
+ */
+
+ while(evl) {
+ evl->f1= 0;
+ if(evl->v4==0) { /* if triangle */
+ if(vlakselectedAND(evl, 1)) {
+
+ e1= evl->e1;
+ e2= evl->e2;
+ e3= evl->e3;
+ if(e1->f<3) {
+ if(e1->f<2) {
+ evp= (EVPtr *) e1->vn;
+ evp[(int)e1->f]= evl;
+ }
+ e1->f+= 1;
+ }
+ if(e2->f<3) {
+ if(e2->f<2) {
+ evp= (EVPtr *) e2->vn;
+ evp[(int)e2->f]= evl;
+ }
+ e2->f+= 1;
+ }
+ if(e3->f<3) {
+ if(e3->f<2) {
+ evp= (EVPtr *) e3->vn;
+ evp[(int)e3->f]= evl;
+ }
+ e3->f+= 1;
+ }
+ }
+ }
+ evl= evl->next;
+ }
+ return i;
+}
+
+
+void join_triangles(void)
+{
+ EditVert *v1, *v2, *v3, *v4;
+ EditVlak *evl, *w;
+ EVPTuple *evlar;
+ EVPtr *evla;
+ EditEdge *eed, *nexted;
+ int totedge, ok;
+ float *uv[4];
+ unsigned int col[4];
+
+
+ totedge = count_edges(G.eded.first);
+ if(totedge==0) return;
+
+ evlar= (EVPTuple *) MEM_callocN(totedge * sizeof(EVPTuple), "jointris");
+
+ ok = collect_quadedges(evlar, G.eded.first, G.edvl.first);
+ if (G.f & G_DEBUG) {
+ printf("edges selected: %d\n", ok);
+ }
+
+ eed= G.eded.first;
+ while(eed) {
+ nexted= eed->next;
+
+ if(eed->f==2) { /* points to 2 faces */
+
+ evla= (EVPtr *) eed->vn;
+
+ /* don't do it if flagged */
+
+ ok= 1;
+ evl= evla[0];
+ if(evl->e1->f1 || evl->e2->f1 || evl->e3->f1) ok= 0;
+ evl= evla[1];
+ if(evl->e1->f1 || evl->e2->f1 || evl->e3->f1) ok= 0;
+
+ if(ok) {
+ /* test convex */
+ givequadverts(evla[0], evla[1], &v1, &v2, &v3, &v4, uv, col);
+
+/*
+ 4-----3 4-----3
+ |\ | | |
+ | \ 1 | | |
+ | \ | -> | |
+ | 0 \ | | |
+ | \| | |
+ 1-----2 1-----2
+*/
+ /* make new faces */
+ if( convex(v1->co, v2->co, v3->co, v4->co) > 0.01) {
+ if(exist_vlak(v1, v2, v3, v4)==0) {
+ w = addvlaklist(v1, v2, v3, v4, evla[0]);
+ untag_edges(w);
+ if (w->tface) {
+ UVCOPY(w->uv[0], uv[0]);
+ UVCOPY(w->uv[1], uv[1]);
+ UVCOPY(w->uv[2], uv[2]);
+ UVCOPY(w->uv[3], uv[3]);
+ }
+ memcpy(w->col, col, sizeof(w->col));
+ }
+ /* tag as to-be-removed */
+ FACE_MARKCLEAR(evla[0]);
+ FACE_MARKCLEAR(evla[1]);
+ eed->f1 = 1;
+ } /* endif test convex */
+ }
+ }
+ eed= nexted;
+ }
+ free_tagged_edgelist(G.eded.first);
+ free_tagged_facelist(G.edvl.first);
+
+ MEM_freeN(evlar);
+
+ allqueue(REDRAWVIEW3D, 0);
+ makeDispList(G.obedit);
+
+}
+
+/* quick hack, basically a copy of beauty_fill */
+void edge_flip(void)
+{
+ EditVert *v1, *v2, *v3, *v4;
+ EditEdge *eed, *nexted;
+ EditVlak *evl, *w;
+ //void **evlar, **evla;
+ EVPTuple *evlar;
+ EVPtr *evla;
+
+ float *uv[4];
+ unsigned int col[4];
+
+ int totedge, ok;
+
+ /* - alle geselecteerde edges met 2 vlakken
+ * - vind die vlakken: opslaan in edges (extra datablok)
+ * - per edge: - test convex
+ * - test edge: flip?
+ - zoja: remedge, addedge, alle randedges nieuwe vlakpointers
+ */
+
+ totedge = count_edges(G.eded.first);
+ if(totedge==0) return;
+
+ /* temporary array for : edge -> face[1], face[2] */
+ evlar= (EVPTuple *) MEM_callocN(totedge * sizeof(EVPTuple), "edgeflip");
+
+ ok = collect_quadedges(evlar, G.eded.first, G.edvl.first);
+
+ eed= G.eded.first;
+ while(eed) {
+ nexted= eed->next;
+
+ if(eed->f==2) { /* points to 2 faces */
+
+ evla= (EVPtr *) eed->vn;
+
+ /* don't do it if flagged */
+
+ ok= 1;
+ evl= evla[0];
+ if(evl->e1->f1 || evl->e2->f1 || evl->e3->f1) ok= 0;
+ evl= evla[1];
+ if(evl->e1->f1 || evl->e2->f1 || evl->e3->f1) ok= 0;
+
+ if(ok) {
+ /* test convex */
+ givequadverts(evla[0], evla[1], &v1, &v2, &v3, &v4, uv, col);
+
+/*
+ 4-----3 4-----3
+ |\ | | /|
+ | \ 1 | | 1 / |
+ | \ | -> | / |
+ | 0 \ | | / 0 |
+ | \| |/ |
+ 1-----2 1-----2
+*/
+ /* make new faces */
+ if (v1 && v2 && v3){
+ if( convex(v1->co, v2->co, v3->co, v4->co) > 0.01) {
+ if(exist_vlak(v1, v2, v3, v4)==0) {
+ w = addvlaklist(v1, v2, v3, 0, evla[1]);
+
+ untag_edges(w);
+ if (w->tface) {
+ UVCOPY(w->uv[0], uv[0]);
+ UVCOPY(w->uv[1], uv[1]);
+ UVCOPY(w->uv[2], uv[2]);
+ }
+ w->col[0] = col[0]; w->col[1] = col[1]; w->col[2] = col[2];
+
+ w = addvlaklist(v1, v3, v4, 0, evla[1]);
+ untag_edges(w);
+ if (w->tface) {
+ UVCOPY(w->uv[0], uv[0]);
+ UVCOPY(w->uv[1], uv[2]);
+ UVCOPY(w->uv[2], uv[3]);
+ }
+ w->col[0] = col[0]; w->col[1] = col[2]; w->col[2] = col[3];
+
+ /* erase old faces and edge */
+ }
+ /* tag as to-be-removed */
+ FACE_MARKCLEAR(evla[1]);
+ FACE_MARKCLEAR(evla[0]);
+ eed->f1 = 1;
+
+ } /* endif test convex */
+ }
+ }
+ }
+ eed= nexted;
+ }
+
+ /* clear tagged edges and faces: */
+ free_tagged_edgelist(G.eded.first);
+ free_tagged_facelist(G.edvl.first);
+
+ MEM_freeN(evlar);
+
+ allqueue(REDRAWVIEW3D, 0);
+ makeDispList(G.obedit);
+}
+
+void beauty_fill(void)
+{
+ EditVert *v1, *v2, *v3, *v4;
+ EditEdge *eed, *nexted;
+ EditEdge dia1, dia2;
+ EditVlak *evl, *w;
+ // void **evlar, **evla;
+ EVPTuple *evlar;
+ EVPtr *evla;
+ float *uv[4];
+ unsigned int col[4];
+ float len1, len2, len3, len4, len5, len6, opp1, opp2, fac1, fac2;
+ int totedge, ok, notbeauty=8, onedone;
+
+ /* - alle geselecteerde edges met 2 vlakken
+ * - vind die vlakken: opslaan in edges (extra datablok)
+ * - per edge: - test convex
+ * - test edge: flip?
+ - zoja: remedge, addedge, alle randedges nieuwe vlakpointers
+ */
+
+ totedge = count_edges(G.eded.first);
+ if(totedge==0) return;
+
+ if(okee("Beauty Fill")==0) return;
+
+ /* tempblok met vlakpointers */
+ evlar= (EVPTuple *) MEM_callocN(totedge * sizeof(EVPTuple), "beautyfill");
+
+ while (notbeauty) {
+ notbeauty--;
+
+ ok = collect_quadedges(evlar, G.eded.first, G.edvl.first);
+
+ /* gaatie */
+ onedone= 0;
+
+ eed= G.eded.first;
+ while(eed) {
+ nexted= eed->next;
+
+ if(eed->f==2) {
+
+ evla = (EVPtr *) eed->vn;
+
+ /* geen van de vlakken mag al gedaan zijn */
+ ok= 1;
+ evl= evla[0];
+ if(evl->e1->f1 || evl->e2->f1 || evl->e3->f1) ok= 0;
+ evl= evla[1];
+ if(evl->e1->f1 || evl->e2->f1 || evl->e3->f1) ok= 0;
+
+ if(ok) {
+ /* test convex */
+ givequadverts(evla[0], evla[1], &v1, &v2, &v3, &v4, uv, col);
+ if( convex(v1->co, v2->co, v3->co, v4->co) > -0.5) {
+
+ /* test edges */
+ if( ((long)v1) > ((long)v3) ) {
+ dia1.v1= v3;
+ dia1.v2= v1;
+ }
+ else {
+ dia1.v1= v1;
+ dia1.v2= v3;
+ }
+
+ if( ((long)v2) > ((long)v4) ) {
+ dia2.v1= v4;
+ dia2.v2= v2;
+ }
+ else {
+ dia2.v1= v2;
+ dia2.v2= v4;
+ }
+
+ /* testregel:
+ * de oppervlakte gedeeld door de totale edgelengte
+ *
+ */
+
+ len1= VecLenf(v1->co, v2->co);
+ len2= VecLenf(v2->co, v3->co);
+ len3= VecLenf(v3->co, v4->co);
+ len4= VecLenf(v4->co, v1->co);
+ len5= VecLenf(v1->co, v3->co);
+ len6= VecLenf(v2->co, v4->co);
+
+ opp1= AreaT3Dfl(v1->co, v2->co, v3->co);
+ opp2= AreaT3Dfl(v1->co, v3->co, v4->co);
+
+ fac1= opp1/(len1+len2+len5) + opp2/(len3+len4+len5);
+
+ opp1= AreaT3Dfl(v2->co, v3->co, v4->co);
+ opp2= AreaT3Dfl(v2->co, v4->co, v1->co);
+
+ fac2= opp1/(len2+len3+len6) + opp2/(len4+len1+len6);
+
+ ok= 0;
+ if(fac1 > fac2) {
+ if(dia2.v1==eed->v1 && dia2.v2==eed->v2) {
+ eed->f1= 1;
+ evl= evla[0];
+ evl->f1= 1;
+ evl= evla[1];
+ evl->f1= 1;
+
+ w= addvlaklist(v1, v2, v3, 0, evl);
+ if (w->tface) {
+ UVCOPY(w->uv[0], uv[0]);
+ UVCOPY(w->uv[1], uv[1]);
+ UVCOPY(w->uv[2], uv[2]);
+ }
+ w->col[0] = col[0]; w->col[1] = col[1]; w->col[2] = col[2];
+ w= addvlaklist(v1, v3, v4, 0, evl);
+ if (w->tface) {
+ UVCOPY(w->uv[0], uv[0]);
+ UVCOPY(w->uv[1], uv[2]);
+ UVCOPY(w->uv[2], uv[3]);
+ }
+ w->col[0] = col[0]; w->col[1] = col[2]; w->col[2] = col[3];
+
+ onedone= 1;
+ }
+ }
+ else if(fac1 < fac2) {
+ if(dia1.v1==eed->v1 && dia1.v2==eed->v2) {
+ eed->f1= 1;
+ evl= evla[0];
+ evl->f1= 1;
+ evl= evla[1];
+ evl->f1= 1;
+
+ w= addvlaklist(v2, v3, v4, 0, evl);
+ if (w->tface) {
+ UVCOPY(w->uv[0], uv[1]);
+ UVCOPY(w->uv[1], uv[3]);
+ UVCOPY(w->uv[2], uv[4]);
+ }
+
+ w= addvlaklist(v1, v2, v4, 0, evl);
+ if (w->tface) {
+ UVCOPY(w->uv[0], uv[0]);
+ UVCOPY(w->uv[1], uv[1]);
+ UVCOPY(w->uv[2], uv[3]);
+ }
+ onedone= 1;
+ }
+ }
+ }
+ }
+
+ }
+ eed= nexted;
+ }
+
+ free_tagged_edgelist(G.eded.first);
+ free_tagged_facelist(G.edvl.first);
+
+ if(onedone==0) break;
+ }
+
+ MEM_freeN(evlar);
+
+ allqueue(REDRAWVIEW3D, 0);
+ makeDispList(G.obedit);
+}
+
+/** tests whether selected mesh objects have tfaces */
+static int testSelected_TfaceMesh(void)
+{
+ Base *base;
+ Mesh *me;
+
+ base = FIRSTBASE;
+ while (base) {
+ if TESTBASE(base) {
+ if(base->object->type==OB_MESH) {
+ me= base->object->data;
+ if (me->tface)
+ return 1;
+ }
+ }
+ base= base->next;
+ }
+ return 0;
+}
+
+void join_mesh(void)
+{
+ Base *base, *nextb;
+ Object *ob;
+ Material **matar, *ma;
+ Mesh *me;
+ MVert *mvert, *mvertmain;
+ MFace *mface = NULL, *mfacemain;
+ TFace *tface = NULL, *tfacemain;
+ unsigned int *mcol=NULL, *mcolmain;
+ float imat[4][4], cmat[4][4];
+ int a, b, totcol, totvert=0, totface=0, ok=0, vertofs, map[MAXMAT];
+#ifdef __NLA
+ int i, j, index;
+ bDeformGroup *dg, *odg;
+ MDeformVert *dvert, *dvertmain;
+#endif
+
+ if(G.obedit) return;
+
+ ob= OBACT;
+ if(!ob || ob->type!=OB_MESH) return;
+
+ /* tellen */
+
+ base= FIRSTBASE;
+ while(base) {
+ if TESTBASE(base) {
+ if(base->object->type==OB_MESH) {
+ me= base->object->data;
+ totvert+= me->totvert;
+ totface+= me->totface;
+
+ if(base->object == ob) ok= 1;
+ }
+ }
+ base= base->next;
+ }
+
+ /* zodoende is het aktieve object altijd select */
+ if(ok==0) return;
+
+ if(totvert==0 || totvert>65000) return;
+
+ if(okee("Join selected Meshes")==0) return;
+
+ /* nieuwe materiaal indexen en hoofdarray */
+ matar= MEM_callocN(sizeof(void *)*MAXMAT, "join_mesh");
+ totcol= ob->totcol;
+
+ /* obact materials in nieuw hoofdarray, is mooiere start! */
+ for(a=1; a<=ob->totcol; a++) {
+ matar[a-1]= give_current_material(ob, a);
+ id_us_plus((ID *)matar[a-1]);
+ /* id->us ophogen: wordt ook verlaagd */
+ }
+
+ base= FIRSTBASE;
+ while(base) {
+ if TESTBASE(base) {
+ if(ob!=base->object && base->object->type==OB_MESH) {
+ me= base->object->data;
+#ifdef __NLA
+ // Join this object's vertex groups to the base one's
+ for (dg=base->object->defbase.first; dg; dg=dg->next){
+ /* See if this group exists in the object */
+ for (odg=ob->defbase.first; odg; odg=odg->next){
+ if (!strcmp(odg->name, dg->name)){
+ break;
+ }
+ }
+ if (!odg){
+ odg = MEM_callocN (sizeof(bDeformGroup), "deformGroup");
+ memcpy (odg, dg, sizeof(bDeformGroup));
+ BLI_addtail(&ob->defbase, odg);
+ }
+
+ }
+ if (ob->defbase.first && ob->actdef==0)
+ ob->actdef=1;
+#endif
+ if(me->totvert) {
+ for(a=1; a<=base->object->totcol; a++) {
+ ma= give_current_material(base->object, a);
+ if(ma) {
+ for(b=0; b<totcol; b++) {
+ if(ma == matar[b]) break;
+ }
+ if(b==totcol) {
+ matar[b]= ma;
+ ma->id.us++;
+ totcol++;
+ }
+ if(totcol>=MAXMAT-1) break;
+ }
+ }
+ }
+ }
+ if(totcol>=MAXMAT-1) break;
+ }
+ base= base->next;
+ }
+
+ me= ob->data;
+ mvert= mvertmain= MEM_mallocN(totvert*sizeof(MVert), "joinmesh1");
+
+ if (totface) mface= mfacemain= MEM_mallocN(totface*sizeof(MFace), "joinmesh2");
+ else mfacemain= 0;
+
+ if(me->mcol) mcol= mcolmain= MEM_callocN(totface*4*sizeof(int), "joinmesh3");
+ else mcolmain= 0;
+
+ /* if active object doesn't have Tfaces, but one in the selection does,
+ make TFaces for active, so we don't lose texture information in the
+ join process */
+ if(me->tface || testSelected_TfaceMesh()) tface= tfacemain= MEM_callocN(totface*4*sizeof(TFace), "joinmesh4");
+ else
+ tfacemain= 0;
+
+#ifdef __NLA
+ if(me->dvert)
+ dvert= dvertmain= MEM_callocN(totvert*sizeof(MDeformVert), "joinmesh5");
+ else dvert=dvertmain= NULL;
+#endif
+
+ vertofs= 0;
+
+ /* alle geselecteerde meshes invers transformen in obact */
+ Mat4Invert(imat, ob->obmat);
+
+ base= FIRSTBASE;
+ while(base) {
+ nextb= base->next;
+ if TESTBASE(base) {
+ if(base->object->type==OB_MESH) {
+
+ me= base->object->data;
+
+ if(me->totvert) {
+
+ memcpy(mvert, me->mvert, me->totvert*sizeof(MVert));
+
+#ifdef __NLA
+ copy_dverts(dvert, me->dvert, me->totvert);
+
+ /* >>>>> FIXME: Ensure that deformation groups are updated correctly */
+ /* OLD VERSION */
+ /*
+ for (i=0; i<me->totvert; i++){
+ for (j=0; j<mvert[i].totweight; j++){
+ // Find the old vertex group
+ odg = BLI_findlink (&base->object->defbase, mvert[i].dw[j].def_nr);
+
+ // Search for a match in the new object
+ for (dg=ob->defbase.first, index=0; dg; dg=dg->next, index++){
+ if (!strcmp(dg->name, odg->name)){
+ mvert[i].dw[j].def_nr = index;
+ break;
+ }
+ }
+ }
+ }
+ */
+ /* NEW VERSION */
+ if (dvertmain){
+ for (i=0; i<me->totvert; i++){
+ for (j=0; j<dvert[i].totweight; j++){
+ // Find the old vertex group
+ odg = BLI_findlink (&base->object->defbase, dvert[i].dw[j].def_nr);
+
+ // Search for a match in the new object
+ for (dg=ob->defbase.first, index=0; dg; dg=dg->next, index++){
+ if (!strcmp(dg->name, odg->name)){
+ dvert[i].dw[j].def_nr = index;
+ break;
+ }
+ }
+ }
+ }
+ dvert+=me->totvert;
+ }
+
+#endif
+ if(base->object != ob) {
+ /* let op: matmul omkeren is ECHT fout */
+ Mat4MulMat4(cmat, base->object->obmat, imat);
+
+ a= me->totvert;
+ while(a--) {
+ Mat4MulVecfl(cmat, mvert->co);
+ mvert++;
+ }
+ }
+ else mvert+= me->totvert;
+
+ if(mcolmain) {
+ if(me->mcol) memcpy(mcol, me->mcol, me->totface*4*4);
+ mcol+= 4*me->totface;
+ }
+ }
+ if(me->totface) {
+
+ /* mapping maken voor materialen */
+ memset(map, 0, 4*MAXMAT);
+ for(a=1; a<=base->object->totcol; a++) {
+ ma= give_current_material(base->object, a);
+ if(ma) {
+ for(b=0; b<totcol; b++) {
+ if(ma == matar[b]) {
+ map[a-1]= b;
+ break;
+ }
+ }
+ }
+ }
+
+ memcpy(mface, me->mface, me->totface*sizeof(MFace));
+
+ a= me->totface;
+ while(a--) {
+ mface->v1+= vertofs;
+ mface->v2+= vertofs;
+ if(mface->v3) mface->v3+= vertofs;
+ if(mface->v4) mface->v4+= vertofs;
+
+ mface->mat_nr= map[(int)mface->mat_nr];
+
+ mface++;
+ }
+
+ if(tfacemain) {
+ if(me->tface) memcpy(tface, me->tface, me->totface*sizeof(TFace));
+ tface+= me->totface;
+ }
+
+ }
+ vertofs+= me->totvert;
+
+ if(base->object!=ob) {
+ free_and_unlink_base(base);
+ }
+ }
+ }
+ base= nextb;
+ }
+
+ me= ob->data;
+
+ if(me->mface) MEM_freeN(me->mface);
+ me->mface= mfacemain;
+ if(me->mvert) MEM_freeN(me->mvert);
+#ifdef __NLA
+ if(me->dvert) free_dverts(me->dvert, me->totvert);
+ me->dvert = dvertmain;
+#endif
+ me->mvert= mvertmain;
+ if(me->mcol) MEM_freeN(me->mcol);
+ me->mcol= (MCol *)mcolmain;
+ if(me->tface) MEM_freeN(me->tface);
+ me->tface= tfacemain;
+ me->totvert= totvert;
+ me->totface= totface;
+
+ /* oude material array */
+ for(a=1; a<=ob->totcol; a++) {
+ ma= ob->mat[a-1];
+ if(ma) ma->id.us--;
+ }
+ for(a=1; a<=me->totcol; a++) {
+ ma= me->mat[a-1];
+ if(ma) ma->id.us--;
+ }
+ if(ob->mat) MEM_freeN(ob->mat);
+ if(me->mat) MEM_freeN(me->mat);
+ ob->mat= me->mat= 0;
+
+ if(totcol) {
+ me->mat= matar;
+ ob->mat= MEM_callocN(sizeof(void *)*totcol, "join obmatar");
+ }
+ else MEM_freeN(matar);
+
+ ob->totcol= me->totcol= totcol;
+ ob->colbits= 0;
+
+ /* andere mesh gebruikers */
+ test_object_materials((ID *)me);
+
+ enter_editmode();
+ exit_editmode(1);
+
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWBUTSMAT, 0);
+ makeDispList(G.obedit);
+
+}
+
+void clever_numbuts_mesh(void)
+{
+ EditVert *eve;
+
+ eve= G.edve.first;
+ while(eve) {
+ if(eve->f & 1) break;
+ eve= eve->next;
+ }
+ if(eve==0) return;
+
+ add_numbut(0, NUM|FLO, "LocX:", -G.vd->far, G.vd->far, eve->co, 0);
+ add_numbut(1, NUM|FLO, "LocY:", -G.vd->far, G.vd->far, eve->co+1, 0);
+ add_numbut(2, NUM|FLO, "LocZ:", -G.vd->far, G.vd->far, eve->co+2, 0);
+
+ do_clever_numbuts("Active Vertex", 3, REDRAW);
+}
+
+/* never used, see CVS */
+/* static void insert_radiogour(char *str) */
+
+static void permutate(void *list, int num, int size, int *index)
+{
+ void *buf;
+ int len;
+ int i;
+
+ len = num * size;
+
+ buf = malloc(len);
+ memcpy(buf, list, len);
+
+ for (i = 0; i < num; i++) {
+ memcpy((char *)list + (i * size), (char *)buf + (index[i] * size), size);
+ }
+ free(buf);
+}
+
+static MVert *mvertbase;
+static MFace *mfacebase;
+
+static int verg_mface(const void *v1, const void *v2)
+{
+ MFace *x1, *x2;
+
+ MVert *ve1, *ve2;
+ int i1, i2;
+
+ i1 = ((int *) v1)[0];
+ i2 = ((int *) v2)[0];
+
+ x1 = mfacebase + i1;
+ x2 = mfacebase + i2;
+
+ ve1= mvertbase+x1->v1;
+ ve2= mvertbase+x2->v1;
+
+ if( ve1->co[2] > ve2->co[2] ) return 1;
+ else if( ve1->co[2] < ve2->co[2]) return -1;
+ return 0;
+}
+
+
+void sort_faces(void)
+{
+ Object *ob= OBACT;
+ Mesh *me;
+
+ int i, *index;
+
+ if(ob==0) return;
+ if(G.obedit) return;
+ if(ob->type!=OB_MESH) return;
+
+ if(okee("Sort Faces in Z")==0) return;
+ me= ob->data;
+ if(me->totface==0) return;
+
+/* create index list */
+ index = (int *) malloc(sizeof(int) * me->totface);
+ for (i = 0; i < me->totface; i++) {
+ index[i] = i;
+ }
+ mvertbase= me->mvert;
+ mfacebase = me->mface;
+
+/* sort index list instead of faces itself
+ and apply this permutation to the face list plus
+ to the texture faces */
+ qsort(index, me->totface, sizeof(int), verg_mface);
+
+ permutate(mfacebase, me->totface, sizeof(MFace), index);
+ if (me->tface)
+ permutate(me->tface, me->totface, sizeof(TFace), index);
+
+ free(index);
+
+ allqueue(REDRAWVIEW3D, 0);
+ makeDispList(G.obedit);
+}
+
+void vertices_to_sphere(void)
+{
+ EditVert *eve;
+ Object *ob= OBACT;
+ float *curs, len, vec[3], cent[3], fac, facm, imat[3][3], bmat[3][3];
+ int tot;
+ short perc=100;
+
+ if(ob==0) return;
+ TEST_EDITMESH
+
+ if(button(&perc, 1, 100, "Percentage:")==0) return;
+ fac= perc/100.0;
+ facm= 1.0-fac;
+
+ Mat3CpyMat4(bmat, ob->obmat);
+ Mat3Inv(imat, bmat);
+
+ /* centrum */
+ curs= give_cursor();
+ cent[0]= curs[0]-ob->obmat[3][0];
+ cent[1]= curs[1]-ob->obmat[3][1];
+ cent[2]= curs[2]-ob->obmat[3][2];
+ Mat3MulVecfl(imat, cent);
+
+ len= 0.0;
+ tot= 0;
+ eve= G.edve.first;
+ while(eve) {
+ if(eve->f & 1) {
+ tot++;
+ len+= VecLenf(cent, eve->co);
+ }
+ eve= eve->next;
+ }
+ len/=tot;
+
+ if(len==0.0) len= 10.0;
+
+ eve= G.edve.first;
+ while(eve) {
+ if(eve->f & 1) {
+ vec[0]= eve->co[0]-cent[0];
+ vec[1]= eve->co[1]-cent[1];
+ vec[2]= eve->co[2]-cent[2];
+
+ Normalise(vec);
+
+ eve->co[0]= fac*(cent[0]+vec[0]*len) + facm*eve->co[0];
+ eve->co[1]= fac*(cent[1]+vec[1]*len) + facm*eve->co[1];
+ eve->co[2]= fac*(cent[2]+vec[2]*len) + facm*eve->co[2];
+
+ }
+ eve= eve->next;
+ }
+
+ allqueue(REDRAWVIEW3D, 0);
+ makeDispList(G.obedit);
+}
+
+/* Got this from scanfill.c. You will need to juggle around the
+ * callbacks for the scanfill.c code a bit for this to work. */
+void fill_mesh(void)
+{
+ EditVert *eve,*v1;
+ EditEdge *eed,*e1,*nexted;
+ EditVlak *evl,*nextvl;
+ short ok;
+
+ if(G.obedit==0 || (G.obedit->type!=OB_MESH)) return;
+
+ waitcursor(1);
+
+ /* alle selected vertices kopieeren */
+ eve= G.edve.first;
+ while(eve) {
+ if(eve->f & 1) {
+ v1= BLI_addfillvert(eve->co);
+ eve->vn= v1;
+ v1->vn= eve;
+ v1->h= 0;
+ }
+ eve= eve->next;
+ }
+ /* alle selected edges kopieeren */
+ eed= G.eded.first;
+ while(eed) {
+ if( (eed->v1->f & 1) && (eed->v2->f & 1) ) {
+ e1= BLI_addfilledge(eed->v1->vn, eed->v2->vn);
+ e1->v1->h++;
+ e1->v2->h++;
+ }
+ eed= eed->next;
+ }
+ /* van alle selected vlakken vertices en edges verwijderen om dubbels te voorkomen */
+ /* alle edges tellen punten op, vlakken trekken af,
+ edges met vertices ->h<2 verwijderen */
+ evl= G.edvl.first;
+ ok= 0;
+ while(evl) {
+ nextvl= evl->next;
+ if( vlakselectedAND(evl, 1) ) {
+ evl->v1->vn->h--;
+ evl->v2->vn->h--;
+ evl->v3->vn->h--;
+ if(evl->v4) evl->v4->vn->h--;
+ ok= 1;
+
+ }
+ evl= nextvl;
+ }
+ if(ok) { /* er zijn vlakken geselecteerd */
+ eed= filledgebase.first;
+ while(eed) {
+ nexted= eed->next;
+ if(eed->v1->h<2 || eed->v2->h<2) {
+ BLI_remlink(&filledgebase,eed);
+ }
+ eed= nexted;
+ }
+ }
+
+ /* tijd=clock(); */
+
+ /* to make edgefill work */
+ BLI_setScanFillObjectRef(G.obedit);
+ BLI_setScanFillColourRef(&G.obedit->actcol);
+
+ ok= BLI_edgefill(0);
+
+ /* printf("time: %d\n",(clock()-tijd)/1000); */
+
+ if(ok) {
+ evl= fillvlakbase.first;
+ while(evl) {
+ addvlaklist(evl->v1->vn, evl->v2->vn, evl->v3->vn, 0, evl);
+ evl= evl->next;
+ }
+ }
+ /* else printf("fill error\n"); */
+
+ BLI_end_edgefill();
+
+ waitcursor(0);
+
+ countall();
+ allqueue(REDRAWVIEW3D, 0);
+ makeDispList(G.obedit);
+}
+
+/* ***************** */
+
+/* this one for NOT in editmode
+
+(only used by external modules, that is, until now by the
+python NMesh module)
+
+TODO: Probably it's better to convert the mesh into a EditMesh, call
+vertexnormals() and convert it back to a Mesh again.
+
+*/
+
+void vertexnormals_mesh(Mesh *me, float *extverts)
+{
+ MVert *mvert;
+ MFace *mface;
+ float n1[3], n2[3], n3[3], n4[3], co[4], fac1, fac2, fac3, fac4, *temp;
+ float *f1, *f2, *f3, *f4, xn, yn, zn, *normals;
+ float *v1, *v2, *v3, *v4, len, vnor[3];
+ int a, testflip;
+
+ if(me->totvert==0) return;
+
+ testflip= (me->flag & ME_NOPUNOFLIP)==0;
+ if((me->flag & ME_TWOSIDED)==0) testflip= 0; /* grote hoeken */
+
+ if(me->totface==0) {
+ /* namaak puno's voor halopuno! */
+ mvert= me->mvert;
+ for(a=0; a<me->totvert; a++, mvert++) {
+ VECCOPY(n1, mvert->co);
+ Normalise(n1);
+ mvert->no[0]= 32767.0*n1[0];
+ mvert->no[1]= 32767.0*n1[1];
+ mvert->no[2]= 32767.0*n1[2];
+ }
+ return;
+ }
+
+ normals= MEM_callocN(me->totvert*3*sizeof(float), "normals");
+
+ /* berekenen cos hoeken en oppervlakte en optellen bij puno */
+ mface= me->mface;
+ mvert= me->mvert;
+ for(a=0; a<me->totface; a++, mface++) {
+
+ if(mface->v3==0) continue;
+
+ if(extverts) {
+ v1= extverts+3*mface->v1;
+ v2= extverts+3*mface->v2;
+ v3= extverts+3*mface->v3;
+ v4= extverts+3*mface->v4;
+ }
+ else {
+ v1= (mvert+mface->v1)->co;
+ v2= (mvert+mface->v2)->co;
+ v3= (mvert+mface->v3)->co;
+ v4= (mvert+mface->v4)->co;
+ }
+
+ VecSubf(n1, v2, v1);
+ VecSubf(n2, v3, v2);
+ Normalise(n1);
+ Normalise(n2);
+
+ if(mface->v4==0) {
+ VecSubf(n3, v1, v3);
+ Normalise(n3);
+
+ co[0]= saacos(-n3[0]*n1[0]-n3[1]*n1[1]-n3[2]*n1[2]);
+ co[1]= saacos(-n1[0]*n2[0]-n1[1]*n2[1]-n1[2]*n2[2]);
+ co[2]= saacos(-n2[0]*n3[0]-n2[1]*n3[1]-n2[2]*n3[2]);
+
+ }
+ else {
+ VecSubf(n3, v4, v3);
+ VecSubf(n4, v1, v4);
+ Normalise(n3);
+ Normalise(n4);
+
+ co[0]= saacos(-n4[0]*n1[0]-n4[1]*n1[1]-n4[2]*n1[2]);
+ co[1]= saacos(-n1[0]*n2[0]-n1[1]*n2[1]-n1[2]*n2[2]);
+ co[2]= saacos(-n2[0]*n3[0]-n2[1]*n3[1]-n2[2]*n3[2]);
+ co[3]= saacos(-n3[0]*n4[0]-n3[1]*n4[1]-n3[2]*n4[2]);
+ }
+
+ CalcNormFloat(v1, v2, v3, vnor);
+
+ temp= normals+3*mface->v1;
+ if(testflip && contrpuntnorm(vnor, temp) ) co[0]= -co[0];
+ temp[0]+= co[0]*vnor[0];
+ temp[1]+= co[0]*vnor[1];
+ temp[2]+= co[0]*vnor[2];
+
+ temp= normals+3*mface->v2;
+ if(testflip && contrpuntnorm(vnor, temp) ) co[1]= -co[1];
+ temp[0]+= co[1]*vnor[0];
+ temp[1]+= co[1]*vnor[1];
+ temp[2]+= co[1]*vnor[2];
+
+ temp= normals+3*mface->v3;
+ if(testflip && contrpuntnorm(vnor, temp) ) co[2]= -co[2];
+ temp[0]+= co[2]*vnor[0];
+ temp[1]+= co[2]*vnor[1];
+ temp[2]+= co[2]*vnor[2];
+
+ if(mface->v4) {
+ temp= normals+3*mface->v4;
+ if(testflip && contrpuntnorm(vnor, temp) ) co[3]= -co[3];
+ temp[0]+= co[3]*vnor[0];
+ temp[1]+= co[3]*vnor[1];
+ temp[2]+= co[3]*vnor[2];
+ }
+ }
+
+ /* normaliseren puntnormalen */
+ mvert= me->mvert;
+ for(a=0; a<me->totvert; a++, mvert++) {
+ len= Normalise(normals+3*a);
+ if(len!=0.0) {
+ VECCOPY(n1, normals+3*a);
+ Normalise(n1);
+
+ mvert->no[0]= 32767.0*n1[0];
+ mvert->no[1]= 32767.0*n1[1];
+ mvert->no[2]= 32767.0*n1[2];
+ }
+ }
+
+ /* puntnormaal omklap-vlaggen voor bij shade */
+ mface= me->mface;
+ mvert= me->mvert;
+ for(a=0; a<me->totface; a++, mface++) {
+ mface->puno=0;
+
+ if(mface->v3==0) continue;
+
+ if(extverts) {
+ v1= extverts+3*mface->v1;
+ v2= extverts+3*mface->v2;
+ v3= extverts+3*mface->v3;
+ }
+ else {
+ v1= (mvert+mface->v1)->co;
+ v2= (mvert+mface->v2)->co;
+ v3= (mvert+mface->v3)->co;
+ }
+
+ CalcNormFloat(v1, v2, v3, vnor);
+
+ if(testflip) {
+ f1= normals + 3*mface->v1;
+ f2= normals + 3*mface->v2;
+ f3= normals + 3*mface->v3;
+
+ fac1= vnor[0]*f1[0] + vnor[1]*f1[1] + vnor[2]*f1[2];
+ if(fac1<0.0) {
+ mface->puno = ME_FLIPV1;
+ }
+ fac2= vnor[0]*f2[0] + vnor[1]*f2[1] + vnor[2]*f2[2];
+ if(fac2<0.0) {
+ mface->puno += ME_FLIPV2;
+ }
+ fac3= vnor[0]*f3[0] + vnor[1]*f3[1] + vnor[2]*f3[2];
+ if(fac3<0.0) {
+ mface->puno += ME_FLIPV3;
+ }
+ if(mface->v4) {
+ f4= normals + 3*mface->v4;
+ fac4= vnor[0]*f4[0] + vnor[1]*f4[1] + vnor[2]*f4[2];
+ if(fac4<0.0) {
+ mface->puno += ME_FLIPV4;
+ }
+ }
+ }
+ /* proj voor cubemap! */
+ xn= fabs(vnor[0]);
+ yn= fabs(vnor[1]);
+ zn= fabs(vnor[2]);
+
+ if(zn>xn && zn>yn) mface->puno += ME_PROJXY;
+ else if(yn>xn && yn>zn) mface->puno += ME_PROJXZ;
+ else mface->puno += ME_PROJYZ;
+
+ }
+
+ MEM_freeN(normals);
+}
+
+/***/
+
+static int editmesh_nfaces_selected(void)
+{
+ EditVlak *evl;
+ int count= 0;
+
+ for (evl= G.edvl.first; evl; evl= evl->next)
+ if (vlakselectedAND(evl, SELECT))
+ count++;
+
+ return count;
+}
+
+static int editmesh_nvertices_selected(void)
+{
+ EditVert *eve;
+ int count= 0;
+
+ for (eve= G.edve.first; eve; eve= eve->next)
+ if (eve->f & SELECT)
+ count++;
+
+ return count;
+}
+
+static void editmesh_calc_selvert_center(float cent_r[3])
+{
+ EditVert *eve;
+ int nsel= 0;
+
+ cent_r[0]= cent_r[1]= cent_r[0]= 0.0;
+
+ for (eve= G.edve.first; eve; eve= eve->next) {
+ if (eve->f & SELECT) {
+ cent_r[0]+= eve->co[0];
+ cent_r[1]+= eve->co[1];
+ cent_r[2]+= eve->co[2];
+ nsel++;
+ }
+ }
+
+ if (nsel) {
+ cent_r[0]/= nsel;
+ cent_r[1]/= nsel;
+ cent_r[2]/= nsel;
+ }
+}
+
+static int tface_is_selected(TFace *tf)
+{
+ return (!(tf->flag & TF_HIDE) && (tf->flag & TF_SELECT));
+}
+
+static int faceselect_nfaces_selected(Mesh *me)
+{
+ int i, count= 0;
+
+ for (i=0; i<me->totface; i++) {
+ MFace *mf= ((MFace*) me->mface) + i;
+ TFace *tf= ((TFace*) me->tface) + i;
+
+ if (mf->v3 && tface_is_selected(tf))
+ count++;
+ }
+
+ return count;
+}
+
+ /* XXX, code for both these functions should be abstract,
+ * then unified, then written for other things (like objects,
+ * which would use same as vertices method), then added
+ * to interface! Hoera! - zr
+ */
+void faceselect_align_view_to_selected(View3D *v3d, Mesh *me, int axis)
+{
+ if (!faceselect_nfaces_selected(me)) {
+ error("No faces selected.");
+ } else {
+ float norm[3];
+ int i;
+
+ norm[0]= norm[1]= norm[2]= 0.0;
+ for (i=0; i<me->totface; i++) {
+ MFace *mf= ((MFace*) me->mface) + i;
+ TFace *tf= ((TFace*) me->tface) + i;
+
+ if (mf->v3 && tface_is_selected(tf)) {
+ float *v1, *v2, *v3, fno[3];
+
+ v1= me->mvert[mf->v1].co;
+ v2= me->mvert[mf->v2].co;
+ v3= me->mvert[mf->v3].co;
+ if (mf->v4) {
+ float *v4= me->mvert[mf->v4].co;
+ CalcNormFloat4(v1, v2, v3, v4, fno);
+ } else {
+ CalcNormFloat(v1, v2, v3, fno);
+ }
+
+ norm[0]+= fno[0];
+ norm[1]+= fno[1];
+ norm[2]+= fno[2];
+ }
+ }
+
+ view3d_align_axis_to_vector(v3d, axis, norm);
+ }
+}
+
+void editmesh_align_view_to_selected(View3D *v3d, int axis)
+{
+ int nselverts= editmesh_nvertices_selected();
+
+ if (nselverts<3) {
+ if (nselverts==0) {
+ error("No faces or vertices selected.");
+ } else {
+ error("At least one face or three vertices must be selected.");
+ }
+ } else if (editmesh_nfaces_selected()) {
+ float norm[3];
+ EditVlak *evl;
+
+ norm[0]= norm[1]= norm[2]= 0.0;
+ for (evl= G.edvl.first; evl; evl= evl->next) {
+ if (vlakselectedAND(evl, SELECT)) {
+ float fno[3];
+ if (evl->v4) CalcNormFloat4(evl->v1->co, evl->v2->co, evl->v3->co, evl->v4->co, fno);
+ else CalcNormFloat(evl->v1->co, evl->v2->co, evl->v3->co, fno);
+ /* XXX, fixme, should be flipped intp a
+ * consistent direction. -zr
+ */
+ norm[0]+= fno[0];
+ norm[1]+= fno[1];
+ norm[2]+= fno[2];
+ }
+ }
+
+ view3d_align_axis_to_vector(v3d, axis, norm);
+ } else {
+ float cent[3], norm[3];
+ EditVert *eve, *leve= NULL;
+
+ norm[0]= norm[1]= norm[2]= 0.0;
+ editmesh_calc_selvert_center(cent);
+ for (eve= G.edve.first; eve; eve= eve->next) {
+ if (eve->f & SELECT) {
+ if (leve) {
+ float tno[3];
+ CalcNormFloat(cent, leve->co, eve->co, tno);
+
+ /* XXX, fixme, should be flipped intp a
+ * consistent direction. -zr
+ */
+ norm[0]+= tno[0];
+ norm[1]+= tno[1];
+ norm[2]+= tno[2];
+ }
+ leve= eve;
+ }
+ }
+
+ view3d_align_axis_to_vector(v3d, axis, norm);
+ }
+} \ No newline at end of file
diff --git a/source/blender/src/editnla.c b/source/blender/src/editnla.c
new file mode 100644
index 00000000000..54ee4682c0e
--- /dev/null
+++ b/source/blender/src/editnla.c
@@ -0,0 +1,1738 @@
+/**
+* $Id$
+*
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+* This file is a horrible mess: An attmept to cram some
+* final functionality into blender before it is too late.
+*
+* Hopefully it can be tidied up at a later date...
+*/
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "PIL_time.h"
+
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_library.h"
+#include "BKE_nla.h"
+#include "BKE_action.h"
+
+#include "BIF_screen.h"
+#include "BIF_interface.h"
+#include "BIF_buttons.h"
+#include "BIF_space.h"
+#include "BIF_mywindow.h"
+#include "BIF_editview.h"
+#include "BIF_toolbox.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_ipo_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_object_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_action_types.h"
+#include "DNA_nla_types.h"
+#include "DNA_constraint_types.h"
+
+#include "BSE_editipo.h"
+#include "BSE_editnla_types.h"
+#include "BSE_headerbuttons.h"
+#include "BSE_drawipo.h"
+#include "BSE_trans_types.h"
+#include "BSE_edit.h"
+#include "BDR_editobject.h"
+
+#include "interface.h"
+#include "blendef.h"
+#include "mydevice.h"
+#include "blendertimer.h"
+#include "license_key.h"
+#include "keyed_functions.h"
+
+/* Note: A lot of these pretty much duplicate the behaviour of the
+action windows. The functions should be shared, not copy-pasted */
+typedef struct NlaParam{
+ SpaceNla *snla;
+ unsigned short event;
+ short val;
+}NlaParam;
+
+static void deselect_nlachannel_keys (int test);
+static void deselect_nlachannels(int test);
+static void transform_nlachannel_keys(char mode);
+static void delete_nlachannel_keys(void);
+static void delete_nlachannels(void);
+static void duplicate_nlachannel_keys(void);
+static void borderselect_nla(void);
+static void mouse_nla(void);
+static Base *get_nearest_nlachannel_ob_key (float *index, short *sel);
+static bAction *get_nearest_nlachannel_ac_key (float *index, short *sel);
+static Base *get_nearest_nlastrip (bActionStrip **rstrip, short *sel);
+
+static void mouse_nlachannels(short mval[2]);
+static void add_nlablock(short mval[2]);
+static bActionStrip *get_active_nlastrip(void);
+static void convert_nla(short mval[2]);
+
+extern int count_nla_levels(void); /* From drawnla.c */
+extern int nla_filter (Base* base, int flags); /* From drawnla.c */
+
+/* ******************** SPACE: NLA ********************** */
+
+/* Protected creator function */
+int calc_memleak (void* ptr){
+ int doredraw= 0;
+ short mval[2];
+ float dx,dy;
+ int cfra;
+ SpaceNla *snla;
+ NlaParam *params=(NlaParam*) ptr;
+ unsigned short event;
+ short val ;
+
+ if (!ptr)
+ return -1;
+
+ snla= params->snla;
+ event = params->event;
+ val = params->val;
+
+ if (LICENSE_KEY_VALID){
+ if(curarea->win==0) return 0;
+
+ if (!snla)
+ return 0;
+
+ if(val) {
+ if( uiDoBlocks(&curarea->uiblocks, event)!=UI_NOTHING ) event= 0;
+
+ getmouseco_areawin(mval);
+
+ switch(event) {
+ case UI_BUT_EVENT:
+ do_blenderbuttons(val);
+ break;
+ case HOMEKEY:
+ do_nla_buttons(B_NLAHOME);
+ break;
+ case DKEY:
+ if (G.qual & LR_SHIFTKEY && mval[0]>=NLAWIDTH){
+ duplicate_nlachannel_keys();
+ update_for_newframe();
+ }
+ break;
+ case DELKEY:
+ case XKEY:
+ if (mval[0]>=NLAWIDTH)
+ delete_nlachannel_keys ();
+ else
+ delete_nlachannels();
+ update_for_newframe();
+ break;
+ case GKEY:
+ if (mval[0]>=NLAWIDTH)
+ transform_nlachannel_keys ('g');
+ update_for_newframe();
+ break;
+ case SKEY:
+ if (mval[0]>=NLAWIDTH)
+ transform_nlachannel_keys ('s');
+ update_for_newframe();
+ break;
+ case BKEY:
+ borderselect_nla();
+ break;
+ case CKEY:
+ convert_nla(mval);
+ break;
+
+ case AKEY:
+ if (G.qual & LR_SHIFTKEY){
+ add_nlablock(mval);
+ allqueue (REDRAWNLA, 0);
+ allqueue (REDRAWVIEW3D, 0);
+ }
+ else{
+ if (mval[0]>=NLAWIDTH)
+ deselect_nlachannel_keys(1);
+ else{
+ deselect_nlachannels(1);
+ allqueue (REDRAWVIEW3D, 0);
+ }
+ allqueue (REDRAWNLA, 0);
+ allqueue (REDRAWIPO, 0);
+ }
+ break;
+ case RIGHTMOUSE:
+ if (mval[0]>=NLAWIDTH)
+ mouse_nla();
+ else
+ mouse_nlachannels(mval);
+ break;
+ case LEFTMOUSE:
+ if (mval[0]>NLAWIDTH){
+ do {
+ getmouseco_areawin(mval);
+
+ areamouseco_to_ipoco(G.v2d, mval, &dx, &dy);
+
+ cfra= (int)dx;
+ if(cfra< 1) cfra= 1;
+
+ if( cfra!=CFRA ) {
+ CFRA= cfra;
+ update_for_newframe();
+ force_draw_plus(SPACE_VIEW3D);
+ force_draw_plus(SPACE_IPO);
+ }
+
+ } while(get_mbut()&L_MOUSE);
+ }
+
+ break;
+ case MIDDLEMOUSE:
+ view2dmove(); /* in drawipo.c */
+ break;
+ }
+ }
+
+ if(doredraw) scrarea_queue_winredraw(curarea);
+ }
+ return 0;
+}
+
+void winqreadnlaspace(unsigned short event, short val, char ascii)
+{
+ NlaParam param;
+ Base *base;
+ bActionStrip *strip, *next;
+ short mval[2];
+ float dx, dy;
+ int cfra;
+
+ param.event = event;
+ param.val = val;
+ param.snla = curarea->spacedata.first;
+
+
+ /* Call the protected (&obfuscated) eventloop function */
+ if (KEY_NLA_EVENT){
+ KEY_NLA_EVENT(&param);
+ }
+ else{
+ getmouseco_areawin(mval);
+ switch(event) {
+ case GKEY:
+ case SKEY:
+ case AKEY:
+ case CKEY:
+ case NKEY:
+ case RIGHTMOUSE:
+ notice ("NLA window editing only available in Blender Publisher");
+ break;
+ case LEFTMOUSE:
+ if (mval[0]>NLAWIDTH){
+ do {
+ getmouseco_areawin(mval);
+
+ areamouseco_to_ipoco(G.v2d, mval, &dx, &dy);
+
+ cfra= (int)dx;
+ if(cfra< 1) cfra= 1;
+
+ if( cfra!=CFRA ) {
+ CFRA= cfra;
+ update_for_newframe();
+ force_draw_plus(SPACE_VIEW3D);
+ force_draw_plus(SPACE_IPO);
+ }
+
+ } while(get_mbut()&L_MOUSE);
+ }
+
+ break;
+ case MIDDLEMOUSE:
+ view2dmove(); /* in drawipo.c */
+ break;
+ case DELKEY:
+ case XKEY:
+ if (okee ("This will remove all NLA information from all objects!")){
+ for (base = G.scene->base.first; base; base=base->next){
+ for (strip=base->object->nlastrips.first; strip; strip=next){
+ next=strip->next;
+ free_actionstrip(strip);
+ BLI_freelinkN(&base->object->nlastrips, strip);
+ }
+ }
+ update_for_newframe();
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+static void convert_nla(short mval[2])
+{
+ short event;
+ float ymax, ymin;
+ Base *base;
+ float x,y;
+ int sel=0;
+ bActionStrip *strip, *nstrip;
+ if (LICENSE_KEY_VALID){
+ /* Find out what strip we're over */
+ ymax = count_nla_levels() * (NLACHANNELSKIP+NLACHANNELHEIGHT);
+ areamouseco_to_ipoco(G.v2d, mval, &x, &y);
+
+ for (base=G.scene->base.first; base; base=base->next){
+ if (nla_filter(base, 0)){
+ /* Check object ipo */
+ ymin=ymax-(NLACHANNELSKIP+NLACHANNELHEIGHT);
+ if (y>=ymin && y<=ymax)
+ break;
+ ymax=ymin;
+
+ if (base->object->type==OB_ARMATURE){
+ /* Check action ipo */
+ ymin=ymax-(NLACHANNELSKIP+NLACHANNELHEIGHT);
+ if (y>=ymin && y<=ymax)
+ break;
+ ymax=ymin;
+
+ /* Check nlastrips */
+ for (strip=base->object->nlastrips.first; strip; strip=strip->next){
+ ymin=ymax-(NLACHANNELSKIP+NLACHANNELHEIGHT);
+ if (y>=ymin && y<=ymax){
+ sel = 1;
+ break;
+ }
+ ymax=ymin;
+ }
+ if (sel)
+ break;
+ }
+ }
+ }
+
+ if (!base)
+ return;
+
+ if (base->object->type==OB_ARMATURE){
+ event = pupmenu("Convert%t|Action to NLAstrip%x1");
+ switch (event){
+ case 1:
+ if (base->object->action){
+ /* Make new actionstrip */
+ nstrip = MEM_callocN(sizeof(bActionStrip), "bActionStrip");
+
+ deselect_nlachannel_keys(0);
+
+ /* Link the action to the nstrip */
+ nstrip->act = base->object->action;
+ nstrip->actstart = calc_action_start(base->object->action); /* MAKE THIS THE FIRST FRAME OF THE ACTION */
+ nstrip->actend = calc_action_end(base->object->action);
+ nstrip->start = nstrip->actstart;
+ nstrip->end = nstrip->actend;
+ nstrip->flag = ACTSTRIP_SELECT;
+ nstrip->repeat = 1.0;
+
+ BLI_addtail(&base->object->nlastrips, nstrip);
+
+ /* Unlink action */
+ base->object->action = NULL;
+
+ allqueue (REDRAWNLA, 0);
+ }
+
+
+ break;
+ default:
+ break;
+ }
+ }
+ }
+}
+
+static void add_nlablock(short mval[2])
+{
+ /* Make sure we are over an armature */
+ Base *base;
+ bAction *act=NULL;
+ bActionStrip *strip;
+ int foundsel=0;
+ float ymin, ymax;
+ float x, y;
+ rctf rectf;
+ short event;
+ char *str;
+ short nr;
+ int cur;
+
+ if (LICENSE_KEY_VALID){
+ areamouseco_to_ipoco(G.v2d, mval, &x, &y);
+
+ mval[0]-=7;
+ areamouseco_to_ipoco(G.v2d, mval, &rectf.xmin, &rectf.ymin);
+
+ mval[0]+=14;
+ areamouseco_to_ipoco(G.v2d, mval, &rectf.xmax, &rectf.ymax);
+
+ ymax = count_nla_levels();
+ ymax*=(NLACHANNELHEIGHT + NLACHANNELSKIP);
+
+ for (base=G.scene->base.first; base; base=base->next){
+ /* Handle object ipo selection */
+ if (nla_filter(base, 0)){
+
+ /* STUPID STUPID STUPID */
+ ymin=ymax-(NLACHANNELHEIGHT+NLACHANNELSKIP);
+
+ /* Handle object ipos */
+ if (base->object->type==OB_ARMATURE){
+ if (!((ymax < rectf.ymin) || (ymin > rectf.ymax)))
+ break;
+ }
+
+ ymax=ymin;
+
+ /* Handle action ipos & Action strips */
+ if (base->object->type==OB_ARMATURE){
+ ymin=ymax-(NLACHANNELHEIGHT+NLACHANNELSKIP)*(BLI_countlist(&base->object->nlastrips) + 1);
+ if (!((ymax < rectf.ymin) || (ymin > rectf.ymax)))
+ break;
+ ymax=ymin;
+
+
+ }
+ }
+ }
+
+ /* Make sure we have an armature */
+ if (!base){
+ error ("Not an armature!");
+ return;
+ }
+
+ /* Popup action menu */
+ IDnames_to_pupstring(&str, "Add action", NULL, &G.main->action, (ID *)G.scene, &nr);
+
+ event = pupmenu(str);
+
+ if (event!=-1){
+ for (cur = 1, act=G.main->action.first; act; act=act->id.next, cur++){
+ if (cur==event){
+ break;
+ }
+ }
+ }
+
+ MEM_freeN(str);
+
+ /* Bail out if no action was chosen */
+ if (!act){
+ return;
+ }
+
+ /* Initialize the new action block */
+ strip = MEM_callocN(sizeof(bActionStrip), "bActionStrip");
+
+ deselect_nlachannel_keys(0);
+
+ /* Link the action to the strip */
+ strip->act = act;
+ strip->actstart = 1.0;
+ strip->actend = calc_action_end(act);
+ strip->start = G.scene->r.cfra; /* Should be mval[0] */
+ strip->end = strip->start + (strip->actend-strip->actstart);
+ strip->flag = ACTSTRIP_SELECT;
+ strip->repeat = 1.0;
+
+ act->id.us++;
+
+ BLI_addtail(&base->object->nlastrips, strip);
+ }
+}
+
+static void mouse_nlachannels(short mval[2])
+{
+ /* Find which strip has been clicked */
+// bActionChannel *chan;
+ bConstraintChannel *conchan=NULL;
+ bActionStrip *strip;
+ float click;
+ int wsize;
+ int sel;
+ Base *base;
+
+ wsize = (count_nla_levels ()*(NLACHANNELHEIGHT+NLACHANNELSKIP));
+
+
+ click = (wsize-(mval[1]+G.v2d->cur.ymin));
+ click += NLACHANNELHEIGHT/2;
+ click /= (NLACHANNELHEIGHT+NLACHANNELSKIP);
+
+ if (click<0)
+ return;
+
+ for (base = G.scene->base.first; base; base=base->next){
+ if (nla_filter(base, 0)){
+ /* See if this is a base selected */
+ if ((int)click==0)
+ break;
+
+ click--;
+
+ /* Check for click in a constraint */
+ for (conchan=base->object->constraintChannels.first; conchan; conchan=conchan->next){
+ if ((int)click==0){
+ base=G.scene->base.last;
+ break;
+ }
+ click--;
+ }
+
+ /* See if this is an action */
+ if (base->object->type==OB_ARMATURE && base->object->action){
+ if ((int)click==0){
+ break;
+ }
+ click--;
+ }
+
+ /* See if this is an nla strip */
+ for (strip = base->object->nlastrips.first; strip; strip=strip->next){
+ if ((int)click==0){
+ base=G.scene->base.last;
+ break;
+ }
+ click--;
+ }
+ }
+ }
+
+ if (!base && !conchan)
+ return;
+
+ /* Handle constraint strip selection */
+ if (conchan){
+ if (conchan->flag & CONSTRAINT_CHANNEL_SELECT)
+ sel = 0;
+ else
+ sel =1;
+
+ /* Channel names clicking */
+ if (G.qual & LR_SHIFTKEY){
+ // select_poseelement_by_name(chan->name, !(chan->flag & ACHAN_SELECTED));
+ if (conchan->flag & CONSTRAINT_CHANNEL_SELECT){
+ conchan->flag &= ~CONSTRAINT_CHANNEL_SELECT;
+ // hilight_channel(act, chan, 0);
+ }
+ else{
+ conchan->flag |= CONSTRAINT_CHANNEL_SELECT;
+ // hilight_channel(act, chan, 1);
+ }
+ }
+ else{
+ deselect_nlachannels (0); // Auto clear
+ conchan->flag |= CONSTRAINT_CHANNEL_SELECT;
+ // hilight_channel(act, chan, 1);
+ // act->achan = chan;
+ // select_poseelement_by_name(chan->name, 1);
+ }
+
+ }
+
+ /* Handle object strip selection */
+ else if (base)
+ {
+ /* Choose the mode */
+ if (base->flag & SELECT)
+ sel = 0;
+ else
+ sel =1;
+
+ /* Channel names clicking */
+ if (G.qual & LR_SHIFTKEY){
+ // select_poseelement_by_name(chan->name, !(chan->flag & ACHAN_SELECTED));
+ if (base->flag & SELECT){
+ base->flag &= ~SELECT;
+ // hilight_channel(act, chan, 0);
+ }
+ else{
+ base->flag |= SELECT;
+ // hilight_channel(act, chan, 1);
+ }
+ }
+ else{
+ deselect_nlachannels (0); // Auto clear
+ base->flag |= SELECT;
+ // hilight_channel(act, chan, 1);
+ // act->achan = chan;
+ // select_poseelement_by_name(chan->name, 1);
+ }
+
+ }
+ allqueue (REDRAWIPO, 0);
+ allqueue (REDRAWVIEW3D, 0);
+ allqueue (REDRAWACTION, 0);
+ allqueue(REDRAWNLA, 0);
+
+}
+
+void init_nlaspace(ScrArea *sa)
+{
+ SpaceNla *snla;
+
+ snla= MEM_callocN(sizeof(SpaceNla), "initnlaspace");
+ BLI_addhead(&sa->spacedata, snla);
+
+ snla->spacetype= SPACE_NLA;
+
+ snla->v2d.tot.xmin= 1.0;
+ snla->v2d.tot.ymin= 0.0;
+ snla->v2d.tot.xmax= 1000.0;
+ snla->v2d.tot.ymax= 1000.0;
+
+ snla->v2d.cur.xmin= -5.0;
+ snla->v2d.cur.ymin= 0.0;
+ snla->v2d.cur.xmax= 65.0;
+ snla->v2d.cur.ymax= 1000.0;
+
+ snla->v2d.min[0]= 0.0;
+ snla->v2d.min[1]= 0.0;
+
+ snla->v2d.max[0]= 1000.0;
+ snla->v2d.max[1]= 1000.0;
+
+ snla->v2d.minzoom= 0.1F;
+ snla->v2d.maxzoom= 10;
+
+ snla->v2d.scroll= R_SCROLL+B_SCROLL;
+ snla->v2d.keepaspect= 0;
+ snla->v2d.keepzoom= V2D_LOCKZOOM_Y;
+ snla->v2d.keeptot= 0;
+
+ snla->lock = 0;
+};
+
+static void deselect_nlachannel_keys (int test)
+{
+ Base *base;
+ int sel=1;
+ bActionChannel *chan;
+ bActionStrip *strip;
+ bConstraintChannel *conchan;
+
+ /* Determine if this is selection or deselection */
+ if (LICENSE_KEY_VALID){
+ if (test){
+ for (base=G.scene->base.first; base && sel; base=base->next){
+
+ /* Test object ipos */
+ if (is_ipo_key_selected(base->object->ipo)){
+ sel = 0;
+ break;
+ }
+
+ /* Test object constraint ipos */
+ if (sel){
+ for (conchan=base->object->constraintChannels.first; conchan; conchan=conchan->next){
+ if (is_ipo_key_selected(conchan->ipo)){
+ sel=0;
+ break;
+ }
+ }
+ }
+
+ /* Test action ipos */
+ if (sel){
+ if (base->object->type==OB_ARMATURE && base->object->action){
+ for (chan=base->object->action->chanbase.first; chan; chan=chan->next){
+ if (is_ipo_key_selected(chan->ipo)){
+ sel=0;
+ break;
+ }
+
+ /* Test action constraints */
+ if (sel){
+ for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next){
+ if (is_ipo_key_selected(conchan->ipo)){
+ sel=0;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* Test NLA strips */
+ if (sel){
+ if (base->object->type==OB_ARMATURE){
+ for (strip=base->object->nlastrips.first; strip; strip=strip->next){
+ if (strip->flag & ACTSTRIP_SELECT){
+ sel = 0;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ sel=0;
+
+
+ /* Set the flags */
+ for (base=G.scene->base.first; base; base=base->next){
+ /* Set the object ipos */
+ set_ipo_key_selection(base->object->ipo, sel);
+
+
+ /* Set the object constraint ipos */
+ for (conchan=base->object->constraintChannels.first; conchan; conchan=conchan->next){
+ set_ipo_key_selection(conchan->ipo, sel);
+ }
+
+ /* Set the action ipos */
+ if (base->object->type==OB_ARMATURE && base->object->action){
+ for (chan=base->object->action->chanbase.first; chan; chan=chan->next){
+ set_ipo_key_selection(chan->ipo, sel);
+ /* Set the action constraint ipos */
+ for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next)
+ set_ipo_key_selection(conchan->ipo, sel);
+ }
+ }
+
+ /* Set the nlastrips */
+ if (base->object->type==OB_ARMATURE){
+ for (strip=base->object->nlastrips.first; strip; strip=strip->next){
+ if (sel)
+ strip->flag |= ACTSTRIP_SELECT;
+ else
+ strip->flag &= ~ACTSTRIP_SELECT;
+ }
+ }
+ }
+ }
+}
+
+
+static void transform_nlachannel_keys(char mode)
+{
+ Base *base;
+ TransVert *tv;
+ int /*sel=0,*/ i;
+ short mvals[2], mvalc[2];
+ // short cent[2];
+ float sval[2], cval[2], lastcval[2];
+ short cancel=0;
+ float fac=0.0F;
+ int loop=1;
+ int tvtot=0;
+ float deltax, startx;
+ // float cenf[2];
+ int invert=0, firsttime=1;
+ char str[256];
+ bActionChannel *chan;
+ bActionStrip *strip;
+ bConstraintChannel *conchan;
+
+ if (LICENSE_KEY_VALID){
+ /* Ensure that partial selections result in beztriple selections */
+ for (base=G.scene->base.first; base; base=base->next){
+
+ /* Check object ipos */
+ tvtot+=fullselect_ipo_keys(base->object->ipo);
+
+ /* Check object constraint ipos */
+ for(conchan=base->object->constraintChannels.first; conchan; conchan=conchan->next)
+ tvtot+=fullselect_ipo_keys(conchan->ipo);
+
+ /* Check action ipos */
+ if (base->object->type == OB_ARMATURE && base->object->action){
+ for (chan=base->object->action->chanbase.first; chan; chan=chan->next){
+ tvtot+=fullselect_ipo_keys(chan->ipo);
+
+ /* Check action constraint ipos */
+ for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next)
+ tvtot+=fullselect_ipo_keys(conchan->ipo);
+ }
+
+ }
+
+ /* Check nlastrips */
+ if (base->object->type==OB_ARMATURE){
+ for (strip=base->object->nlastrips.first; strip; strip=strip->next){
+ if (strip->flag & ACTSTRIP_SELECT)
+ tvtot+=2;
+ }
+ }
+ }
+
+ /* If nothing is selected, bail out */
+ if (!tvtot)
+ return;
+
+
+ /* Build the transvert structure */
+ tv = MEM_callocN (sizeof(TransVert) * tvtot, "transVert");
+ tvtot=0;
+ for (base=G.scene->base.first; base; base=base->next){
+ /* Manipulate object ipos */
+ tvtot=add_trans_ipo_keys(base->object->ipo, tv, tvtot);
+
+ /* Manipulate object constraint ipos */
+ for (conchan=base->object->constraintChannels.first; conchan; conchan=conchan->next)
+ tvtot=add_trans_ipo_keys(conchan->ipo, tv, tvtot);
+
+ /* Manipulate action ipos */
+ if (base->object->type==OB_ARMATURE && base->object->action){
+ for (chan=base->object->action->chanbase.first; chan; chan=chan->next){
+ tvtot=add_trans_ipo_keys(chan->ipo, tv, tvtot);
+
+ /* Manipulate action constraint ipos */
+ for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next)
+ tvtot=add_trans_ipo_keys(conchan->ipo, tv, tvtot);
+ }
+ }
+
+ /* Manipulate nlastrips */
+ for (strip=base->object->nlastrips.first; strip; strip=strip->next){
+ if (strip->flag & ACTSTRIP_SELECT){
+ tv[tvtot+0].val=&strip->start;
+ tv[tvtot+1].val=&strip->end;
+
+ tv[tvtot+0].oldval = strip->start;
+ tv[tvtot+1].oldval = strip->end;
+
+ tvtot+=2;
+ }
+ }
+ }
+
+ /* Do the event loop */
+ // cent[0] = curarea->winx + (G.snla->v2d.hor.xmax)/2;
+ // cent[1] = curarea->winy + (G.snla->v2d.hor.ymax)/2;
+
+ // areamouseco_to_ipoco(cent, &cenf[0], &cenf[1]);
+
+ getmouseco_areawin (mvals);
+ areamouseco_to_ipoco(G.v2d, mvals, &sval[0], &sval[1]);
+
+ startx=sval[0];
+ while (loop) {
+ /* Get the input */
+ /* If we're cancelling, reset transformations */
+ /* Else calc new transformation */
+ /* Perform the transformations */
+ while (qtest()) {
+ short val;
+ unsigned short event= extern_qread(&val);
+
+ if (val) {
+ switch (event) {
+ case LEFTMOUSE:
+ case SPACEKEY:
+ case RETKEY:
+ loop=0;
+ break;
+ case XKEY:
+ break;
+ case ESCKEY:
+ case RIGHTMOUSE:
+ cancel=1;
+ loop=0;
+ break;
+ default:
+ arrows_move_cursor(event);
+ break;
+ };
+ }
+ }
+
+ if (cancel) {
+ for (i=0; i<tvtot; i++) {
+ if (tv[i].loc){
+ tv[i].loc[0]=tv[i].oldloc[0];
+ tv[i].loc[1]=tv[i].oldloc[1];
+ }
+ if (tv[i].val)
+ tv[i].val[0]=tv[i].oldval;
+ }
+ }
+ else {
+ getmouseco_areawin (mvalc);
+ areamouseco_to_ipoco(G.v2d, mvalc, &cval[0], &cval[1]);
+
+ if (!firsttime && lastcval[0]==cval[0] && lastcval[1]==cval[1]) {
+ PIL_sleep_ms(1);
+ }
+ else {
+ for (i=0; i<tvtot; i++){
+ if (tv[i].loc)
+ tv[i].loc[0]=tv[i].oldloc[0];
+ if (tv[i].val)
+ tv[i].val[0]=tv[i].oldval;
+
+ switch (mode){
+ case 'g':
+ deltax = cval[0]-sval[0];
+ fac= deltax;
+
+ apply_keyb_grid(&fac, 0.0F, 1.0F, 0.1F, U.flag & AUTOGRABGRID);
+
+ if (tv[i].loc)
+ tv[i].loc[0]+=fac;
+ if (tv[i].val)
+ tv[i].val[0]+=fac;
+ break;
+ case 's':
+ startx=mvals[0]-(NLAWIDTH/2+(curarea->winrct.xmax-curarea->winrct.xmin)/2);
+ deltax=mvalc[0]-(NLAWIDTH/2+(curarea->winrct.xmax-curarea->winrct.xmin)/2);
+ fac= (float)fabs(deltax/startx);
+
+ apply_keyb_grid(&fac, 0.0F, 0.2F, 0.1F, U.flag & AUTOSIZEGRID);
+
+ if (invert){
+ if (i % 03 == 0){
+ memcpy (tv[i].loc, tv[i].oldloc, sizeof(tv[i+2].oldloc));
+ }
+ if (i % 03 == 2){
+ memcpy (tv[i].loc, tv[i].oldloc, sizeof(tv[i-2].oldloc));
+ }
+
+ fac*=-1;
+ }
+ startx= (G.scene->r.cfra);
+
+ if (tv[i].loc){
+ tv[i].loc[0]-= startx;
+ tv[i].loc[0]*=fac;
+ tv[i].loc[0]+= startx;
+ }
+ if (tv[i].val){
+ tv[i].val[0]-= startx;
+ tv[i].val[0]*=fac;
+ tv[i].val[0]+= startx;
+ }
+
+ break;
+ }
+ }
+ }
+
+ if (mode=='s'){
+ sprintf(str, "sizeX: %.3f", fac);
+ headerprint(str);
+ }
+ else if (mode=='g'){
+ sprintf(str, "deltaX: %.3f", fac);
+ headerprint(str);
+ }
+
+ if (G.snla->lock){
+ allqueue (REDRAWVIEW3D, 0);
+ allqueue (REDRAWNLA, 0);
+ allqueue (REDRAWIPO, 0);
+ force_draw_all();
+ }
+ else {
+ addqueue (curarea->win, REDRAWALL, 0);
+ force_draw ();
+ }
+ }
+
+ lastcval[0]= cval[0];
+ lastcval[1]= cval[1];
+ firsttime= 0;
+ }
+
+ allspace(REMAKEALLIPO, 0);
+ allqueue (REDRAWVIEW3D, 0);
+ allqueue (REDRAWNLA, 0);
+ allqueue (REDRAWIPO, 0);
+ MEM_freeN (tv);
+ }
+}
+
+static void delete_nlachannel_keys(void)
+{
+ Base *base;
+ bActionChannel *chan;
+ bConstraintChannel *conchan;
+ bActionStrip *strip, *nextstrip;
+
+ if (LICENSE_KEY_VALID){
+ if (!okee("Erase selected keys"))
+ return;
+
+ for (base = G.scene->base.first; base; base=base->next){
+
+ /* Delete object ipos */
+ delete_ipo_keys(base->object->ipo);
+
+ /* Delete object constraint keys */
+ for(conchan=base->object->constraintChannels.first; conchan; conchan=conchan->next)
+ delete_ipo_keys(conchan->ipo);
+
+ /* Delete NLA strips */
+ if (base->object->type==OB_ARMATURE){
+ for (strip = base->object->nlastrips.first; strip; strip=nextstrip){
+ nextstrip=strip->next;
+ if (strip->flag & ACTSTRIP_SELECT){
+ free_actionstrip(strip);
+ BLI_remlink(&base->object->nlastrips, strip);
+ MEM_freeN(strip);
+ }
+ }
+ }
+
+ /* Delete action ipos */
+ if (base->object->type==OB_ARMATURE && base->object->action){
+ for (chan=base->object->action->chanbase.first; chan; chan=chan->next){
+ delete_ipo_keys(chan->ipo);
+ /* Delete action constraint keys */
+ for(conchan=chan->constraintChannels.first; conchan; conchan=conchan->next)
+ delete_ipo_keys(conchan->ipo);
+ }
+ }
+ }
+
+ allspace(REMAKEALLIPO, 0);
+ allqueue(REDRAWNLA, 0);
+ allqueue(REDRAWIPO, 0);
+ }
+}
+
+static void duplicate_nlachannel_keys(void)
+{
+ Base *base;
+ bActionChannel *chan;
+ bConstraintChannel *conchan;
+ bActionStrip *strip, *laststrip;
+ if (LICENSE_KEY_VALID){
+
+ /* Find selected items */
+ for (base = G.scene->base.first; base; base=base->next){
+ /* Duplicate object keys */
+ duplicate_ipo_keys(base->object->ipo);
+
+ /* Duplicate object constraint keys */
+ for(conchan=base->object->constraintChannels.first; conchan; conchan=conchan->next)
+ duplicate_ipo_keys(conchan->ipo);
+
+ /* Duplicate nla strips */
+ if (base->object->type == OB_ARMATURE){
+ laststrip = base->object->nlastrips.last;
+ for (strip=base->object->nlastrips.first; strip; strip=strip->next){
+ if (strip->flag & ACTSTRIP_SELECT){
+ bActionStrip *newstrip;
+
+ copy_actionstrip(&newstrip, &strip);
+
+ BLI_addtail(&base->object->nlastrips, newstrip);
+
+ strip->flag &= ~ACTSTRIP_SELECT;
+ newstrip->flag |= ACTSTRIP_SELECT;
+
+ }
+ if (strip==laststrip)
+ break;
+ }
+ }
+
+ /* Duplicate actionchannel keys */
+ if (base->object->type == OB_ARMATURE && base->object->action){
+ for (chan=base->object->action->chanbase.first; chan; chan=chan->next){
+ duplicate_ipo_keys(chan->ipo);
+ /* Duplicate action constraint keys */
+ for(conchan=chan->constraintChannels.first; conchan; conchan=conchan->next)
+ duplicate_ipo_keys(conchan->ipo);
+ }
+ }
+ }
+
+ transform_nlachannel_keys ('g');
+ }
+}
+
+static void borderselect_nla(void)
+{
+ Base *base;
+ rcti rect;
+ rctf rectf;
+ int val;
+ short mval[2];
+ float ymin, ymax;
+ bActionStrip *strip;
+ bConstraintChannel *conchan;
+
+ if (LICENSE_KEY_VALID){
+ val= get_border (&rect, 3);
+
+ if (val){
+ mval[0]= rect.xmin;
+ mval[1]= rect.ymin+2;
+ areamouseco_to_ipoco(G.v2d, mval, &rectf.xmin, &rectf.ymin);
+ mval[0]= rect.xmax;
+ mval[1]= rect.ymax-2;
+ areamouseco_to_ipoco(G.v2d, mval, &rectf.xmax, &rectf.ymax);
+
+ ymax = count_nla_levels();
+ ymax*= (NLACHANNELHEIGHT+NLACHANNELSKIP);
+
+ for (base=G.scene->base.first; base; base=base->next){
+ /* Check object ipos */
+ if (nla_filter(base, 0)){
+ ymin=ymax-(NLACHANNELHEIGHT+NLACHANNELSKIP);
+ if (base->object->ipo){
+ if (!((ymax < rectf.ymin) || (ymin > rectf.ymax)))
+ borderselect_ipo_key(base->object->ipo, rectf.xmin, rectf.xmax, val);
+ }
+ ymax=ymin;
+
+ /* Check object constraint ipos */
+ for (conchan=base->object->constraintChannels.first; conchan; conchan=conchan->next){
+ ymin=ymax-(NLACHANNELHEIGHT+NLACHANNELSKIP);
+ if (!((ymax < rectf.ymin) || (ymin > rectf.ymax)))
+ borderselect_ipo_key(conchan->ipo, rectf.xmin, rectf.xmax, val);
+ ymax=ymin;
+ }
+
+ /* Check action ipos */
+ if (ACTIVE_ARMATURE(base)){
+ ymin=ymax-(NLACHANNELHEIGHT+NLACHANNELSKIP);
+ if (base->object->action){
+ bActionChannel *chan;
+
+ if (!((ymax < rectf.ymin) || (ymin > rectf.ymax))){
+ for (chan=base->object->action->chanbase.first; chan; chan=chan->next){
+ borderselect_ipo_key(chan->ipo, rectf.xmin, rectf.xmax, val);
+ /* Check action constraint ipos */
+ for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next)
+ borderselect_ipo_key(conchan->ipo, rectf.xmin, rectf.xmax, val);
+ }
+ }
+ }
+ ymax=ymin;
+ } /* End of if armature */
+
+ /* Skip nlastrips */
+ if (base->object->type==OB_ARMATURE){
+ for (strip=base->object->nlastrips.first; strip; strip=strip->next){
+ ymin=ymax-(NLACHANNELHEIGHT+NLACHANNELSKIP);
+ //
+ if (!((ymax < rectf.ymin) || (ymin > rectf.ymax))){
+ if (!((rectf.xmax<strip->start) || (rectf.xmin>strip->end))){
+ if (val==1)
+ strip->flag |= ACTSTRIP_SELECT;
+ else
+ strip->flag &= ~ACTSTRIP_SELECT;
+ }
+ }
+
+ ymax=ymin;
+ }
+ }
+
+ } /* End of object filter */
+ }
+ allqueue(REDRAWNLA, 0);
+ allqueue(REDRAWACTION, 0);
+ allqueue(REDRAWIPO, 0);
+ }
+ }
+}
+
+static void mouse_nla(void)
+{
+ short sel;
+ float selx;
+ short mval[2];
+ Base *base;
+ bAction *act;
+ bActionChannel *chan;
+ bActionStrip *rstrip;
+ bConstraintChannel *conchan;
+
+ if (LICENSE_KEY_VALID){
+ getmouseco_areawin (mval);
+
+ /* Try object ipo selection */
+ base=get_nearest_nlachannel_ob_key(&selx, &sel);
+ if (base){
+ if (!(G.qual & LR_SHIFTKEY)){
+ deselect_nlachannel_keys(0);
+ sel = 0;
+ }
+
+ select_ipo_key(base->object->ipo, selx, sel);
+
+ /* Try object constraint selection */
+ for (conchan=base->object->constraintChannels.first; conchan; conchan=conchan->next)
+ select_ipo_key(conchan->ipo, selx, sel);
+
+
+ allqueue(REDRAWIPO, 0);
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWNLA, 0);
+ return;
+ }
+
+ /* Try action ipo selection */
+ act=get_nearest_nlachannel_ac_key(&selx, &sel);
+ if (act){
+ if (!(G.qual & LR_SHIFTKEY)){
+ deselect_nlachannel_keys(0);
+ sel = 0;
+ }
+
+ for (chan=act->chanbase.first; chan; chan=chan->next){
+ select_ipo_key(chan->ipo, selx, sel);
+ /* Try action constraint selection */
+ for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next)
+ select_ipo_key(conchan->ipo, selx, sel);
+ }
+
+ allqueue(REDRAWIPO, 0);
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWNLA, 0);
+ return;
+ }
+
+ /* Try nla strip selection */
+ base=get_nearest_nlastrip(&rstrip, &sel);
+ if (base){
+ if (!(G.qual & LR_SHIFTKEY)){
+ deselect_nlachannel_keys(0);
+ sel = 0;
+ }
+
+ if (sel)
+ rstrip->flag &= ~ACTSTRIP_SELECT;
+ else
+ rstrip->flag |= ACTSTRIP_SELECT;
+
+ allqueue(REDRAWIPO, 0);
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWNLA, 0);
+ return;
+
+ }
+
+ }
+
+}
+
+static Base *get_nearest_nlastrip (bActionStrip **rstrip, short *sel)
+/* This function is currently more complicated than it seems like it should be.
+* However, this will be needed once the nla strip timeline is more complex */
+{
+ Base *base, *firstbase=NULL;
+ short mval[2];
+ short foundsel = 0;
+ rctf rectf;
+ float ymin, ymax;
+ bActionStrip *strip, *firststrip, *foundstrip;
+
+ if (LICENSE_KEY_VALID){
+ getmouseco_areawin (mval);
+
+ mval[0]-=7;
+ areamouseco_to_ipoco(G.v2d, mval, &rectf.xmin, &rectf.ymin);
+
+ mval[0]+=14;
+ areamouseco_to_ipoco(G.v2d, mval, &rectf.xmax, &rectf.ymax);
+
+ ymax = count_nla_levels();
+ ymax*=(NLACHANNELHEIGHT + NLACHANNELSKIP);
+
+ for (base = G.scene->base.first; base; base=base->next){
+ if (nla_filter(base, 0)){
+ /* Skip object ipos */
+ // if (base->object->ipo)
+ ymax-=(NLACHANNELHEIGHT+NLACHANNELSKIP);
+
+ if (base->object->type==OB_ARMATURE){
+ /* Skip action ipos */
+ if (base->object->action)
+ ymax-=(NLACHANNELHEIGHT+NLACHANNELSKIP);
+
+ for (strip=base->object->nlastrips.first; strip; strip=strip->next){
+ ymin=ymax-(NLACHANNELHEIGHT+NLACHANNELSKIP);
+ /* Do Ytest */
+ if (!((ymax < rectf.ymin) || (ymin > rectf.ymax))){
+ /* Do XTest */
+ if (!((rectf.xmax<strip->start) || (rectf.xmin>strip->end))){
+ if (!firstbase){
+ firstbase=base;
+ firststrip=strip;
+ *sel = strip->flag & ACTSTRIP_SELECT;
+ }
+
+ if (strip->flag & ACTSTRIP_SELECT){
+ if (!foundsel){
+ foundsel=1;
+ foundstrip = strip;
+ }
+ }
+ else if (foundsel && strip != foundstrip){
+ *rstrip=strip;
+ *sel = 0;
+ return base;
+ }
+ }
+ }
+ ymax=ymin;
+ }
+ }
+ }
+ }
+ *rstrip=firststrip;
+ return firstbase;
+ }
+ else
+ return NULL;
+}
+
+static Base *get_nearest_nlachannel_ob_key (float *index, short *sel)
+{
+ Base *base;
+ IpoCurve *icu;
+ Base *firstbase=NULL;
+ bConstraintChannel *conchan;
+ int foundsel=0;
+ float firstvert=-1, foundx=-1;
+ int i;
+ short mval[2];
+ float ymin, ymax;
+ rctf rectf;
+
+ if (LICENSE_KEY_VALID){
+ *index=0;
+
+ getmouseco_areawin (mval);
+
+ mval[0]-=7;
+ areamouseco_to_ipoco(G.v2d, mval, &rectf.xmin, &rectf.ymin);
+
+ mval[0]+=14;
+ areamouseco_to_ipoco(G.v2d, mval, &rectf.xmax, &rectf.ymax);
+
+ ymax = count_nla_levels();
+
+ ymax*=(NLACHANNELHEIGHT + NLACHANNELSKIP);
+
+ *sel=0;
+
+ for (base=G.scene->base.first; base; base=base->next){
+ /* Handle object ipo selection */
+ if (nla_filter(base, 0)){
+ ymin=ymax-(NLACHANNELHEIGHT+NLACHANNELSKIP);
+ if (base->object->ipo){
+ if (!((ymax < rectf.ymin) || (ymin > rectf.ymax))){
+ for (icu=base->object->ipo->curve.first; icu; icu=icu->next){
+ for (i=0; i<icu->totvert; i++){
+ if (icu->bezt[i].vec[1][0] > rectf.xmin && icu->bezt[i].vec[1][0] <= rectf.xmax ){
+ if (!firstbase){
+ firstbase=base;
+ firstvert=icu->bezt[i].vec[1][0];
+ *sel = icu->bezt[i].f2 & 1;
+ }
+
+ if (icu->bezt[i].f2 & 1){
+ if (!foundsel){
+ foundsel=1;
+ foundx = icu->bezt[i].vec[1][0];
+ }
+ }
+ else if (foundsel && icu->bezt[i].vec[1][0] != foundx){
+ *index=icu->bezt[i].vec[1][0];
+ *sel = 0;
+ return base;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ ymax=ymin;
+
+ /* Handle object constraint ipos */
+ for (conchan=base->object->constraintChannels.first; conchan; conchan=conchan->next){
+ ymin=ymax-(NLACHANNELHEIGHT+NLACHANNELSKIP);
+ if (!((ymax < rectf.ymin) || (ymin > rectf.ymax))){
+ for (icu=conchan->ipo->curve.first; icu; icu=icu->next){
+ for (i=0; i<icu->totvert; i++){
+ if (icu->bezt[i].vec[1][0] > rectf.xmin && icu->bezt[i].vec[1][0] <= rectf.xmax ){
+ if (!firstbase){
+ firstbase=base;
+ firstvert=icu->bezt[i].vec[1][0];
+ *sel = icu->bezt[i].f2 & 1;
+ }
+
+ if (icu->bezt[i].f2 & 1){
+ if (!foundsel){
+ foundsel=1;
+ foundx = icu->bezt[i].vec[1][0];
+ }
+ }
+ else if (foundsel && icu->bezt[i].vec[1][0] != foundx){
+ *index=icu->bezt[i].vec[1][0];
+ *sel = 0;
+ return base;
+ }
+ }
+ }
+ }
+ }
+ ymax=ymin;
+ }
+
+ /* Skip action ipos */
+ if (ACTIVE_ARMATURE(base)){
+ ymax-=(NLACHANNELHEIGHT+NLACHANNELSKIP);
+ }
+ /* Skip nlastrips */
+ if (base->object->type==OB_ARMATURE){
+ ymax-=(NLACHANNELHEIGHT+NLACHANNELSKIP)*BLI_countlist(&base->object->nlastrips);
+ }
+ }
+ }
+
+ *index=firstvert;
+ return firstbase;
+ }
+ else
+ return NULL;
+}
+
+static bAction *get_nearest_nlachannel_ac_key (float *index, short *sel)
+{
+ Base *base;
+ IpoCurve *icu;
+ bAction *firstact=NULL;
+ int foundsel=0;
+ float firstvert=-1, foundx=-1;
+ int i;
+ short mval[2];
+ float ymin, ymax;
+ rctf rectf;
+ bActionChannel *chan;
+ bConstraintChannel *conchan;
+
+ if (LICENSE_KEY_VALID){
+ *index=0;
+
+ getmouseco_areawin (mval);
+
+ mval[0]-=7;
+ areamouseco_to_ipoco(G.v2d, mval, &rectf.xmin, &rectf.ymin);
+
+ mval[0]+=14;
+ areamouseco_to_ipoco(G.v2d, mval, &rectf.xmax, &rectf.ymax);
+
+ ymax = count_nla_levels();
+
+ ymax*=(NLACHANNELHEIGHT + NLACHANNELSKIP);
+
+ *sel=0;
+
+ for (base=G.scene->base.first; base; base=base->next){
+ /* Handle object ipo selection */
+ if (nla_filter(base, 0)){
+ /* Skip object ipo */
+ ymin=ymax-(NLACHANNELHEIGHT+NLACHANNELSKIP);
+ ymax=ymin;
+
+ /* Handle action ipos */
+ if (ACTIVE_ARMATURE(base)){
+ ymin=ymax-(NLACHANNELHEIGHT+NLACHANNELSKIP);
+ if (!((ymax < rectf.ymin) || (ymin > rectf.ymax))){
+ for (chan=base->object->action->chanbase.first; chan; chan=chan->next){
+ for (icu=chan->ipo->curve.first; icu; icu=icu->next){
+ for (i=0; i<icu->totvert; i++){
+ if (icu->bezt[i].vec[1][0] > rectf.xmin && icu->bezt[i].vec[1][0] <= rectf.xmax ){
+ if (!firstact){
+ firstact=base->object->action;
+ firstvert=icu->bezt[i].vec[1][0];
+ *sel = icu->bezt[i].f2 & 1;
+ }
+
+ if (icu->bezt[i].f2 & 1){
+ if (!foundsel){
+ foundsel=1;
+ foundx = icu->bezt[i].vec[1][0];
+ }
+ }
+ else if (foundsel && icu->bezt[i].vec[1][0] != foundx){
+ *index=icu->bezt[i].vec[1][0];
+ *sel = 0;
+ return base->object->action;
+ }
+ }
+ }
+ }
+
+
+ for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next){
+ ymin=ymax-(NLACHANNELHEIGHT+NLACHANNELSKIP);
+ if (!((ymax < rectf.ymin) || (ymin > rectf.ymax))){
+ for (icu=conchan->ipo->curve.first; icu; icu=icu->next){
+ for (i=0; i<icu->totvert; i++){
+ if (icu->bezt[i].vec[1][0] > rectf.xmin && icu->bezt[i].vec[1][0] <= rectf.xmax ){
+ if (!firstact){
+ firstact=base->object->action;
+ firstvert=icu->bezt[i].vec[1][0];
+ *sel = icu->bezt[i].f2 & 1;
+ }
+
+ if (icu->bezt[i].f2 & 1){
+ if (!foundsel){
+ foundsel=1;
+ foundx = icu->bezt[i].vec[1][0];
+ }
+ }
+ else if (foundsel && icu->bezt[i].vec[1][0] != foundx){
+ *index=icu->bezt[i].vec[1][0];
+ *sel = 0;
+ return base->object->action;
+ }
+ }
+ }
+ }
+ }
+ ymax=ymin;
+ }
+
+
+ }
+ }
+ ymax=ymin;
+ }
+
+ /* Skip nlastrips */
+ if (base->object->type==OB_ARMATURE){
+ ymax-=(NLACHANNELHEIGHT+NLACHANNELSKIP)*BLI_countlist(&base->object->nlastrips);
+ }
+ }
+ }
+
+ *index=firstvert;
+ return firstact;
+ }
+ else
+ return NULL;
+}
+
+static bActionStrip *get_active_nlastrip(void)
+/* For now just returns the first selected strip */
+{
+ Base *base;
+ bActionStrip *strip;
+
+ if (LICENSE_KEY_VALID){
+ for (base=G.scene->base.first; base; base=base->next){
+ if (nla_filter(base, 0) && base->object->type==OB_ARMATURE){
+ for (strip=base->object->nlastrips.first; strip; strip=strip->next){
+ if (strip->flag & ACTSTRIP_SELECT)
+ return strip;
+ }
+ }
+ }
+
+ return NULL;
+ }
+ else
+ return NULL;
+}
+
+void clever_numbuts_nla(void){
+ bActionStrip *strip;
+ int but=0;
+ if (LICENSE_KEY_VALID){
+
+ /* Determine if an nla strip has been selected */
+ strip = get_active_nlastrip();
+ if (!strip)
+ return;
+
+ add_numbut(but++, LABEL, "Timeline Range:", 1.0, 18000.0, 0, 0);
+ add_numbut(but++, NUM|FLO, "Strip Start:", 1.0, 18000.0, &strip->start, "First frame in the timeline");
+ add_numbut(but++, NUM|FLO, "Strip End:", 1.0, 18000.0, &strip->end, "Last frame in the timeline");
+ add_numbut(but++, LABEL, "Action Range:", 1.0, 18000.0, 0, 0);
+ add_numbut(but++, NUM|FLO, "Action Start:", 1.0, 18000.0, &strip->actstart, "First frame of the action to map to the playrange");
+ add_numbut(but++, NUM|FLO, "Action End:", 1.0, 18000.0, &strip->actend, "Last frame of the action to map to the playrange");
+ add_numbut(but++, LABEL, "Blending:", 1.0, 18000.0, 0, 0);
+ add_numbut(but++, NUM|FLO, "Blendin:", 0.0, 18000.0, &strip->blendin, "Number of frames of ease-in");
+ add_numbut(but++, NUM|FLO, "Blendout:", 0.0, 18000.0, &strip->blendout, "Number of frames of ease-out");
+ add_numbut(but++, LABEL, "Options:", 1.0, 18000.0, 0, 0);
+ add_numbut(but++, NUM|FLO, "Repeat:", 0.0001, 18000.0, &strip->repeat, "Number of times the action should repeat");
+ add_numbut(but++, NUM|FLO, "Stride:", 0.0001, 1000.0, &strip->stridelen, "Distance covered by one complete cycle of the action specified in the Action Range");
+ {
+ /* STUPID HACK BECAUSE NUMBUTS ARE BROKEN WITH MULTIPLE TOGGLES */
+ short hold= (strip->flag & ACTSTRIP_HOLDLASTFRAME) ? 1 : 0;
+ short frompath=(strip->flag & ACTSTRIP_USESTRIDE) ? 1 : 0;
+
+ add_numbut(but++, TOG|SHO, "Use Path", 0, 0, &frompath, "Plays action based on position on path & stride length. Only valid for armatures that are parented to a path");
+ add_numbut(but++, TOG|SHO, "Hold", 0, 0, &hold, "Toggles whether or not to continue displaying the last frame past the end of the strip");
+ add_numbut(but++, TOG|SHO, "Add", 0, 0, &strip->mode, "Toggles additive blending mode");
+
+ do_clever_numbuts("Action", but, REDRAW);
+
+ /* STUPID HACK BECAUSE NUMBUTS ARE BROKEN WITH MULTIPLE TOGGLES */
+ if (hold) strip->flag |= ACTSTRIP_HOLDLASTFRAME;
+ else strip->flag &= ~ACTSTRIP_HOLDLASTFRAME;
+
+ if (frompath) strip->flag |= ACTSTRIP_USESTRIDE;
+ else strip->flag &= ~ACTSTRIP_USESTRIDE;
+
+ }
+
+ if (strip->end<strip->start)
+ strip->end=strip->start;
+
+
+ if (strip->blendin>(strip->end-strip->start))
+ strip->blendin = strip->end-strip->start;
+
+ if (strip->blendout>(strip->end-strip->start))
+ strip->blendout = strip->end-strip->start;
+
+ if (strip->blendin > (strip->end-strip->start-strip->blendout))
+ strip->blendin = (strip->end-strip->start-strip->blendout);
+
+ if (strip->blendout > (strip->end-strip->start-strip->blendin))
+ strip->blendout = (strip->end-strip->start-strip->blendin);
+
+
+ update_for_newframe();
+ allqueue (REDRAWNLA, 0);
+ allqueue (REDRAWVIEW3D, 0);
+ }
+}
+
+static void deselect_nlachannels(int test){
+ int sel = 1;
+ Base *base;
+ bConstraintChannel *conchan;
+
+ if (test){
+ for (base=G.scene->base.first; base; base=base->next){
+ /* Check base flags for previous selection */
+ if (base->flag & SELECT){
+ sel=0;
+ break;
+ }
+
+ /* Check constraint flags for previous selection */
+ for (conchan=base->object->constraintChannels.first; conchan; conchan=conchan->next){
+ if (conchan->flag & CONSTRAINT_CHANNEL_SELECT){
+ sel=0;
+ base = G.scene->base.last;
+ break;
+ }
+ }
+ }
+ }
+ else
+ sel = 0;
+
+ /* Select objects */
+ for (base=G.scene->base.first; base; base=base->next){
+ if (sel){
+ if (nla_filter(base, 0))
+ base->flag |= SELECT;
+ }
+ else
+ base->flag &= ~SELECT;
+
+ /* Select constraint channels */
+ for (conchan=base->object->constraintChannels.first; conchan; conchan=conchan->next){
+ if (sel){
+ if (nla_filter(base, 0))
+ conchan->flag |= CONSTRAINT_CHANNEL_SELECT;
+ }
+ else
+ conchan->flag &= ~CONSTRAINT_CHANNEL_SELECT;
+ }
+ }
+}
+
+static void delete_nlachannels(void){
+ Base *base;
+ bConstraintChannel *conchan, *nextchan;
+ int sel=0;
+
+ /* See if there is anything selected */
+ for (base = G.scene->base.first; base && (!sel); base=base->next){
+ /* Check constraints */
+ for (conchan=base->object->constraintChannels.first; conchan; conchan=conchan->next){
+ if (conchan->flag & CONSTRAINT_CHANNEL_SELECT){
+ sel = 1;
+ break;
+ }
+ }
+ }
+
+ if (!sel)
+ return;
+
+ if (okee ("Delete selected channels")){
+ for (base=G.scene->base.first; base; base=base->next){
+ for (conchan=base->object->constraintChannels.first; conchan; conchan=nextchan){
+ nextchan = conchan->next;
+
+ if (conchan->flag & CONSTRAINT_CHANNEL_SELECT){
+ /* If we're the active constraint, unlink us */
+ if (conchan==base->object->activecon)
+ base->object->activecon = NULL;
+
+ if (conchan->ipo)
+ conchan->ipo->id.us--;
+ BLI_freelinkN(&base->object->constraintChannels, conchan);
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/source/blender/src/editobject.c b/source/blender/src/editobject.c
new file mode 100644
index 00000000000..31f542a2b1b
--- /dev/null
+++ b/source/blender/src/editobject.c
@@ -0,0 +1,5944 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/**
+ * Theorie: (matrices) A x B x C == A x ( B x C x Binv) x B
+ * ofwel: OB x PAR x EDIT = OB x (PAR x EDIT x PARinv) x PAR
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#ifndef WIN32
+#include <unistd.h>
+#else
+#include <io.h>
+#include "BLI_winstuff.h"
+#endif
+#include "MEM_guardedalloc.h"
+#include "PIL_time.h"
+
+#include "BMF_Api.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+#include "BLI_ghash.h"
+
+#include "IMB_imbuf_types.h"
+
+#include "DNA_camera_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_effect_types.h"
+#include "DNA_ika_types.h"
+#include "DNA_image_types.h"
+#include "DNA_ipo_types.h"
+#include "DNA_key_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_lattice_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meta_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_world_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_property_types.h"
+#include "DNA_vfont_types.h"
+#include "DNA_constraint_types.h"
+
+#include "BKE_nla.h"
+#include "BKE_utildefines.h"
+#include "BKE_anim.h"
+#include "BKE_blender.h"
+#include "BKE_curve.h"
+#include "BKE_displist.h"
+#include "BKE_effect.h"
+#include "BKE_font.h"
+#include "BKE_global.h"
+#include "BKE_ika.h"
+#include "BKE_ipo.h"
+#include "BKE_key.h"
+#include "BKE_lattice.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+#include "BKE_material.h"
+#include "BKE_mball.h"
+#include "BKE_mesh.h"
+#include "BKE_object.h"
+#include "BKE_property.h"
+#include "BKE_sca.h"
+#include "BKE_scene.h"
+#include "BKE_subsurf.h"
+#include "BKE_texture.h"
+#include "BKE_booleanops.h"
+
+#include "BIF_gl.h"
+#include "BIF_graphics.h"
+#include "BIF_interface.h"
+#include "BIF_mywindow.h"
+#include "BIF_toolbox.h"
+#include "BIF_screen.h"
+#include "BIF_space.h"
+#include "BIF_buttons.h"
+#include "BIF_editdeform.h"
+#include "BIF_editfont.h"
+#include "BIF_editika.h"
+#include "BIF_editlattice.h"
+#include "BIF_editmesh.h"
+#include "BIF_editoops.h"
+#include "BIF_editview.h"
+#include "BIF_editarmature.h"
+
+#include "BSE_edit.h"
+#include "BSE_editaction.h"
+#include "BSE_editipo.h"
+#include "BSE_filesel.h" /* For activate_databrowse() */
+#include "BSE_view.h"
+#include "BSE_trans_types.h"
+#include "BSE_editipo_types.h"
+
+#include "BDR_vpaint.h"
+#include "BDR_editmball.h"
+#include "BDR_editobject.h"
+#include "BDR_drawobject.h"
+#include "BDR_editcurve.h"
+
+#include "render.h"
+#include <time.h>
+#include "mydevice.h"
+#include "nla.h"
+
+#include "blendef.h"
+/* #include "graphics.h" */
+#include "interface.h"
+
+#include "BKE_constraint.h"
+#include "BIF_editconstraint.h"
+
+#include "BKE_action.h"
+#include "DNA_action_types.h"
+#include "BKE_armature.h"
+#include "DNA_armature_types.h"
+#include "BIF_poseobject.h"
+
+
+#include "license_key.h" // For functions behind the key
+
+/* extern Lattice *copy_lattice(Lattice *lt); */
+extern ListBase editNurb;
+extern ListBase editelems;
+
+TransOb *transmain= 0;
+TransVert *transvmain= 0;
+int tottrans=0, transmode=0; /* 1: texspace */
+
+float prop_size= 1.0;
+int prop_mode= 0;
+float prop_cent[3];
+
+/* used in editipo, editcurve and here */
+#define BEZSELECTED(bezt) (((bezt)->f1 & 1) || ((bezt)->f2 & 1) || ((bezt)->f3 & 1))
+
+#define TRANS_TEX 1
+
+#define KEYFLAG_ROT 0x00000001
+#define KEYFLAG_LOC 0x00000002
+#define KEYFLAG_SIZE 0x00000004
+
+float centre[3], centroid[3];
+
+void add_object_draw(int type) /* voor toolbox */
+{
+ Object *ob;
+
+ G.f &= ~(G_VERTEXPAINT+G_FACESELECT+G_TEXTUREPAINT+G_WEIGHTPAINT);
+ setcursor_space(SPACE_VIEW3D, CURSOR_STD);
+
+ if ELEM3(curarea->spacetype, SPACE_VIEW3D, SPACE_BUTS, SPACE_INFO) {
+ if (G.obedit) exit_editmode(1);
+ ob= add_object(type);
+ base_init_from_view3d(BASACT, G.vd);
+
+ if(type==OB_IKA) {
+ where_is_object(ob);
+ while(TRUE) {
+ if( extrude_ika(ob, 1) ) break;
+ }
+
+ calc_ika(ob->data, 0);
+ init_defstate_ika(ob);
+ }
+
+ allqueue(REDRAWVIEW3D, 0);
+ }
+
+ redraw_test_buttons(BASACT);
+ allqueue(REDRAWIPO, 0);
+ allqueue(REDRAWBUTSEDIT, 0);
+ allqueue(REDRAWACTION,0);
+ allqueue(REDRAWHEADERS, 0);
+ allqueue(REDRAWNLA, 0);
+ deselect_all_area_oops();
+ set_select_flag_oops();
+ allqueue(REDRAWINFO, 1); /* 1, want header->win==0! */
+
+}
+
+void free_and_unlink_base(Base *base)
+{
+ if (base==BASACT)
+ BASACT= NULL;
+
+ BLI_remlink(&G.scene->base, base);
+ free_libblock_us(&G.main->object, base->object);
+ MEM_freeN(base);
+}
+
+void delete_obj(int ok)
+{
+ Base *base;
+
+ if(G.obpose) return;
+ if(G.obedit) return;
+ if(G.scene->id.lib) return;
+
+ base= FIRSTBASE;
+ while(base) {
+ Base *nbase= base->next;
+
+ if TESTBASE(base) {
+ if(ok==0 && (ok=okee("ERASE SELECTED"))==0) return;
+
+ free_and_unlink_base(base);
+ }
+
+ base= nbase;
+ }
+ countall();
+
+ G.f &= ~(G_VERTEXPAINT+G_FACESELECT+G_TEXTUREPAINT+G_WEIGHTPAINT);
+ setcursor_space(SPACE_VIEW3D, CURSOR_STD);
+
+ test_scene_constraints();
+ allqueue(REDRAWVIEW3D, 0);
+ redraw_test_buttons(BASACT);
+ allqueue (REDRAWACTION, 0);
+ allqueue(REDRAWIPO, 0);
+ allqueue(REDRAWDATASELECT, 0);
+ allqueue(REDRAWOOPS, 0);
+ allqueue(REDRAWACTION, 0);
+ allqueue(REDRAWNLA, 0);
+}
+
+
+void make_track(void)
+{
+ Base *base;
+
+ if(G.scene->id.lib) return;
+ if(G.obedit) {
+ return;
+ }
+ if(BASACT==0) return;
+
+#if 0
+ /* Not yet */
+ notice ("Make Track no longer supported. Use constraints instead.");
+ return;
+#endif
+
+ if(okee("Make Track")==0) return;
+
+ base= FIRSTBASE;
+ while(base) {
+ if TESTBASELIB(base) {
+ if(base!=BASACT) {
+
+ base->object->track= BASACT->object;
+ }
+ }
+ base= base->next;
+ }
+
+ test_scene_constraints();
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWOOPS, 0);
+ sort_baselist(G.scene);
+}
+
+void apply_obmat(Object *ob)
+{
+ float mat[3][3], imat[3][3], tmat[3][3];
+
+ /* from obmat to loc rot size */
+
+ if(ob==0) return;
+ Mat3CpyMat4(mat, ob->obmat);
+
+ VECCOPY(ob->loc, ob->obmat[3]);
+
+ if(ob->transflag & OB_QUAT) {
+ Mat3ToQuat(mat, ob->quat);
+ QuatToMat3(ob->quat, tmat);
+ }
+ else {
+ Mat3ToEul(mat, ob->rot);
+ EulToMat3(ob->rot, tmat);
+ }
+ Mat3Inv(imat, tmat);
+
+ Mat3MulMat3(tmat, imat, mat);
+
+ ob->size[0]= tmat[0][0];
+ ob->size[1]= tmat[1][1];
+ ob->size[2]= tmat[2][2];
+
+}
+
+void clear_parent(void)
+{
+ Object *par;
+ Base *base;
+ int mode;
+
+ if(G.obedit) return;
+ if(G.scene->id.lib) return;
+
+ mode= pupmenu("OK? %t|Clear Parent %x1| ... and keep transform (clr track) %x2|Clear parent inverse %x3");
+
+ if(mode<1) return;
+
+ base= FIRSTBASE;
+ while(base) {
+ if TESTBASELIB(base) {
+ par= 0;
+ if(mode==1 || mode==2) {
+ if(base->object->type==OB_IKA) {
+ Ika *ika= base->object->data;
+ ika->parent= 0;
+ }
+ par= base->object->parent;
+ base->object->parent= 0;
+
+ if(mode==2) {
+ base->object->track= 0;
+ apply_obmat(base->object);
+ }
+ }
+ else if(mode==3) {
+ Mat4One(base->object->parentinv);
+ }
+
+ if(par) {
+ if(par->type==OB_LATTICE) makeDispList(base->object);
+ if(par->type==OB_IKA) makeDispList(base->object);
+ if(par->type==OB_ARMATURE) makeDispList(base->object);
+ }
+ }
+ base= base->next;
+ }
+
+ test_scene_constraints();
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWOOPS, 0);
+}
+
+void clear_track(void)
+{
+ Base *base;
+ int mode;
+
+ if(G.obedit) return;
+ if(G.scene->id.lib) return;
+
+ mode= pupmenu("OK? %t|Clear Track %x1| ... and keep transform %x2");
+
+ if(mode<1) return;
+
+ base= FIRSTBASE;
+ while(base) {
+ if TESTBASELIB(base) {
+ base->object->track= 0;
+
+ if(mode==2) {
+ apply_obmat(base->object);
+ }
+ }
+ base= base->next;
+ }
+ test_scene_constraints();
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWOOPS, 0);
+}
+
+void clear_object(char mode)
+{
+ Base *base;
+ float *v1, *v3, mat[3][3];
+
+ if(G.obedit) return;
+ if(G.scene->id.lib) return;
+
+ if(mode=='r' && okee("Clear rotation")==0) return;
+ else if(mode=='g' && okee("Clear location")==0) return;
+ else if(mode=='s' && okee("Clear size")==0) return;
+ else if(mode=='o' && okee("Clear origin")==0) return;
+
+ if (G.obpose){
+
+ switch (G.obpose->type){
+ case OB_ARMATURE:
+ clear_armature (G.obpose, mode);
+#if 1
+ make_displists_by_armature (G.obpose);
+#endif
+ break;
+ }
+
+ allqueue(REDRAWVIEW3D, 0);
+ return;
+ }
+
+ base= FIRSTBASE;
+ while(base) {
+ if TESTBASELIB(base) {
+ if(mode=='r') {
+ memset(base->object->rot, 0, 3*sizeof(float));
+ memset(base->object->drot, 0, 3*sizeof(float));
+ QuatOne(base->object->quat);
+ QuatOne(base->object->dquat);
+ }
+ else if(mode=='g') {
+ memset(base->object->loc, 0, 3*sizeof(float));
+ memset(base->object->dloc, 0, 3*sizeof(float));
+ }
+ else if(mode=='s') {
+ memset(base->object->dsize, 0, 3*sizeof(float));
+ base->object->size[0]= 1.0;
+ base->object->size[1]= 1.0;
+ base->object->size[2]= 1.0;
+ }
+ else if(mode=='o') {
+ if(base->object->parent) {
+ v1= base->object->loc;
+ v3= base->object->parentinv[3];
+
+ Mat3CpyMat4(mat, base->object->parentinv);
+ VECCOPY(v3, v1);
+ v3[0]= -v3[0];
+ v3[1]= -v3[1];
+ v3[2]= -v3[2];
+ Mat3MulVecfl(mat, v3);
+ }
+ }
+ }
+ base= base->next;
+ }
+
+ allqueue(REDRAWVIEW3D, 0);
+}
+
+void reset_slowparents(void)
+{
+ /* terug op correcte plek */
+ Base *base;
+
+ base= FIRSTBASE;
+ while(base) {
+ if(base->object->parent) {
+ if(base->object->partype & PARSLOW) {
+ base->object->partype -= PARSLOW;
+ where_is_object(base->object);
+ base->object->partype |= PARSLOW;
+ }
+ }
+ base= base->next;
+ }
+}
+
+void set_slowparent(void)
+{
+ Base *base;
+
+ if( okee("Set Slow parent")==0 ) return;
+
+ base= FIRSTBASE;
+ while(base) {
+ if TESTBASELIB(base) {
+ if(base->object->parent) base->object->partype |= PARSLOW;
+ }
+ base= base->next;
+ }
+
+}
+
+void make_vertex_parent(void)
+{
+ EditVert *eve;
+ Base *base;
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ Object *par, *ob;
+ int a, v1=0, v2=0, v3=0, nr=1;
+
+ /* er moet 1 of 3 vertices select zijn */
+
+ if(G.obedit->type==OB_MESH) {
+ eve= G.edve.first;
+ while(eve) {
+ if(eve->f & 1) {
+ if(v1==0) v1= nr;
+ else if(v2==0) v2= nr;
+ else if(v3==0) v3= nr;
+ else break;
+ }
+ nr++;
+ eve= eve->next;
+ }
+ }
+ else if ELEM(G.obedit->type, OB_SURF, OB_CURVE) {
+ nu= editNurb.first;
+ while(nu) {
+ if((nu->type & 7)==CU_BEZIER) {
+ bezt= nu->bezt;
+ a= nu->pntsu;
+ while(a--) {
+ if(BEZSELECTED(bezt)) {
+ if(v1==0) v1= nr;
+ else if(v2==0) v2= nr;
+ else if(v3==0) v3= nr;
+ else break;
+ }
+ nr++;
+ bezt++;
+ }
+ }
+ else {
+ bp= nu->bp;
+ a= nu->pntsu*nu->pntsv;
+ while(a--) {
+ if(bp->f1 & SELECT) {
+ if(v1==0) v1= nr;
+ else if(v2==0) v2= nr;
+ else if(v3==0) v3= nr;
+ else break;
+ }
+ nr++;
+ bp++;
+ }
+ }
+ nu= nu->next;
+ }
+
+ }
+
+ if( !(v1 && v2==0 && v3==0) && !(v1 && v2 && v3) ) {
+ error("select 1 or 3 vertices");
+ return;
+ }
+
+ if(okee("Make vertex-parent")==0) return;
+
+ base= FIRSTBASE;
+ while(base) {
+ if TESTBASELIB(base) {
+ if(base!=BASACT) {
+ ob= base->object;
+ par= BASACT->object->parent;
+
+ while(par) {
+ if(par==ob) break;
+ par= par->parent;
+ }
+ if(par) {
+ error("Loop in parents");
+ }
+ else {
+ ob->parent= BASACT->object;
+ if(v3) {
+ ob->partype= PARVERT3;
+ ob->par1= v1-1;
+ ob->par2= v2-1;
+ ob->par3= v3-1;
+
+ /* inverse parent matrix berekenen */
+ what_does_parent(ob);
+ Mat4Invert(ob->parentinv, workob.obmat);
+ clear_workob();
+ }
+ else {
+ ob->partype= PARVERT1;
+ ob->par1= v1-1;
+
+ /* inverse parent matrix berekenen */
+ what_does_parent(ob);
+ Mat4Invert(ob->parentinv, workob.obmat);
+ clear_workob();
+ }
+ }
+ }
+ }
+ base= base->next;
+ }
+ allqueue(REDRAWVIEW3D, 0);
+
+}
+
+int test_parent_loop(Object *par, Object *ob)
+{
+ /* test if 'ob' is a parent somewhere in par's parents */
+
+ if(par==0) return 0;
+ if(ob == par) return 1;
+
+ if(par->type==OB_IKA) {
+ Ika *ika= par->data;
+
+ if( ob == ika->parent ) return 1;
+ if( test_parent_loop(ika->parent, ob) ) return 1;
+ }
+
+ return test_parent_loop(par->parent, ob);
+
+}
+
+void make_parent(void)
+{
+ Base *base;
+ Object *par;
+ Ika *ika;
+ short qual, ok, mode=0, limbnr=0, effchild=0;
+ char *bonestr=NULL;
+ Bone *bone=NULL;
+ int bonenr;
+
+ if(G.scene->id.lib) return;
+ if(G.obedit) {
+ if ELEM3(G.obedit->type, OB_MESH, OB_CURVE, OB_SURF) make_vertex_parent();
+ else if (G.obedit->type==OB_ARMATURE) make_bone_parent();
+ return;
+ }
+ if(BASACT==0) return;
+
+ qual= G.qual;
+ par= BASACT->object;
+
+ if(par->type==OB_IKA) {
+
+ if(qual & LR_SHIFTKEY)
+ mode= pupmenu("Make Parent without inverse%t|Use Vertex %x1|Use Limb %x2|Use Skeleton %x3");
+ else
+ mode= pupmenu("Make Parent %t|Use Vertex %x1|Use Limb %x2|Use Skeleton %x3");
+
+ if(mode==1) {
+ draw_ika_nrs(par, 0);
+ if(button(&limbnr, 0, 99, "Vertex: ")==0) {
+ allqueue(REDRAWVIEW3D, 0);
+ return;
+ }
+ }
+ else if(mode==2) {
+ draw_ika_nrs(par, 1);
+ if(button(&limbnr, 0, 99, "Limb: ")==0) {
+ allqueue(REDRAWVIEW3D, 0);
+ return;
+ }
+ }
+ else if(mode==3) {
+ ika= par->data;
+ if(ika->def==0) {
+ error("No skeleton available: use CTRL K");
+ return;
+ }
+ }
+ else return;
+
+ if(mode==1) mode= PARVERT1;
+ else if(mode==2) mode= PARLIMB;
+ else if(mode==3) mode= PARSKEL;
+
+ /* test effchild */
+ base= FIRSTBASE;
+ while(base) {
+ if TESTBASELIB(base) {
+ if(base->object->type==OB_IKA && base->object!=par && mode==PARVERT1 ) {
+ if(effchild==0) {
+ if(okee("Effector as Child")) effchild= 1;
+ else effchild= 2;
+ }
+ }
+ }
+ if(effchild) break;
+ base= base->next;
+ }
+ }
+ else if(par->type == OB_ARMATURE){
+ mode= pupmenu("Make Parent %t|Use Bone %x1|Use Armature %x2|Use Object %x3");
+ switch (mode){
+ case 1:
+ mode=PARBONE;
+ /* Make bone popup menu */
+
+ bonestr = make_bone_menu(get_armature(par));
+ // if(mbutton(&bone, bonestr, 1, 24, "Bone: ")==0) {
+
+ bonenr= pupmenu_col(bonestr, 20);
+ if (bonestr)
+ MEM_freeN (bonestr);
+
+ if (bonenr==-1){
+ allqueue(REDRAWVIEW3D, 0);
+ return;
+ }
+
+ apply_pose_armature(get_armature(par), par->pose, 0);
+ bone=get_indexed_bone(get_armature(par), bonenr);
+ if (!bone){
+ // error ("Invalid bone! Warn reevan@blender.nl");
+ allqueue(REDRAWVIEW3D, 0);
+ return;
+ }
+
+ break;
+ case 2:
+ mode=PARSKEL;
+ break;
+ case 3:
+ mode=PAROBJECT;
+ break;
+ default:
+ return;
+ }
+ }
+ else {
+ if(qual & LR_SHIFTKEY) {
+ if(okee("Make Parent without inverse")==0) return;
+ }
+ else {
+ if(qual & LR_ALTKEY) {
+ if(okee("Make VertexParent")==0) return;
+ }
+ else if(okee("Make Parent")==0) return;
+
+ /* test effchild */
+ base= FIRSTBASE;
+ while(base) {
+ if TESTBASELIB(base) {
+ if(base->object->type==OB_IKA && base->object != par) {
+ if(effchild==0) {
+ if(okee("Effector as Child")) effchild= 1;
+ else effchild= 2;
+ }
+ }
+ }
+ if(effchild) break;
+ base= base->next;
+ }
+
+ /* nu gaan we alle objecten clearparentandkeeptransformen */
+ base= FIRSTBASE;
+ while(base) {
+ if TESTBASELIB(base) {
+ if(base!=BASACT && base->object->parent) {
+ if(base->object->type==OB_IKA && effchild==1);
+ else {
+ base->object->parent= 0;
+ apply_obmat(base->object);
+ }
+ }
+ }
+ base= base->next;
+ }
+ }
+ }
+
+
+ base= FIRSTBASE;
+ while(base) {
+ if TESTBASELIB(base) {
+ if(base!=BASACT) {
+
+ ok= 1;
+ if(base->object->type==OB_IKA) {
+
+ if(effchild==1) {
+
+ if( test_parent_loop(par, base->object)==0 ) {
+
+ Ika *ika= base->object->data;
+
+ ika->parent= par;
+ ika->par1= limbnr;
+ ika->partype= mode;
+ itterate_ika(base->object);
+ ok= 0;
+ }
+ else {
+ ok= 0;
+ error("Loop in parents");
+ }
+ }
+ }
+
+ if(ok) {
+ if( test_parent_loop(par, base->object) ) {
+ error("Loop in parents");
+ }
+ else {
+
+ if(par->type==OB_IKA){
+ base->object->partype= mode;
+ base->object->par1= limbnr;
+ }
+ else if (par->type==OB_ARMATURE){
+ base->object->partype= mode;
+ if (bone)
+ strcpy (base->object->parsubstr, bone->name);
+ else
+ base->object->parsubstr[0]=0;
+ }
+
+ else if(qual & LR_ALTKEY) {
+ base->object->partype= PARVERT1;
+ }
+ else {
+ base->object->partype= PAROBJECT;
+ }
+
+ base->object->parent= par;
+
+ /* inverse parent matrix berekenen? */
+ if( (qual & LR_SHIFTKEY) ) {
+ /* niet dus... */
+ Mat4One(base->object->parentinv);
+ memset(base->object->loc, 0, 3*sizeof(float));
+ }
+ else {
+ if(mode==PARSKEL && par->type == OB_ARMATURE) {
+ base->object->partype= PAROBJECT;
+ what_does_parent(base->object);
+ Mat4One (base->object->parentinv);
+ base->object->partype= mode;
+ }
+ else
+ what_does_parent(base->object);
+ Mat4Invert(base->object->parentinv, workob.obmat);
+ }
+
+ if(par->type==OB_LATTICE) makeDispList(base->object);
+ if(par->type==OB_IKA && mode==PARSKEL) makeDispList(base->object);
+ if(par->type==OB_ARMATURE && mode == PARSKEL){
+ verify_defgroups(base->object);
+ makeDispList(base->object);
+ }
+ }
+ }
+ }
+ }
+ base= base->next;
+ }
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWOOPS, 0);
+
+ test_scene_constraints();
+ sort_baselist(G.scene);
+}
+
+
+void enter_editmode(void)
+{
+ Base *base;
+ Object *ob;
+ Ika *ika;
+ ID *id;
+ Mesh *me;
+ int ok= 0;
+ bArmature *arm;
+
+ if(G.scene->id.lib) return;
+ base= BASACT;
+ if(base==0) return;
+ if((base->lay & G.vd->lay)==0) return;
+
+ ob= base->object;
+ if(ob->data==0) return;
+
+ id= ob->data;
+ if(id->lib) {
+ error("Can't edit libdata");
+ return;
+ }
+
+ if(ob->type==OB_MESH) {
+ me= get_mesh(ob);
+ if( me==0 ) return;
+ if(me->id.lib) {
+ error("Can't edit libdata");
+ return;
+ }
+ ok= 1;
+ G.obedit= ob;
+ make_editMesh();
+ allqueue(REDRAWBUTSGAME, 0);
+ }
+ if (ob->type==OB_ARMATURE){
+ arm=base->object->data;
+ if (!arm) return;
+ if (arm->id.lib){
+ error("Can't edit libdata");
+ return;
+ }
+ ok=1;
+ G.obedit=ob;
+ make_editArmature();
+ allqueue (REDRAWVIEW3D,0);
+ }
+ else if(ob->type==OB_IKA) { /* grabtype */
+ base= FIRSTBASE;
+ while(base) {
+ if TESTBASE(base) {
+ if(base->object->type==OB_IKA) {
+ ika= base->object->data;
+ if(ika->flag & IK_GRABEFF) ika->flag &= ~IK_GRABEFF;
+ else ika->flag |= IK_GRABEFF;
+ }
+ }
+ base= base->next;
+ }
+ allqueue(REDRAWVIEW3D, 0);
+ }
+ else if(ob->type==OB_FONT) {
+ G.obedit= ob;
+ ok= 1;
+ make_editText();
+ }
+ else if(ob->type==OB_MBALL) {
+ G.obedit= ob;
+ ok= 1;
+ make_editMball();
+ }
+ else if(ob->type==OB_LATTICE) {
+ G.obedit= ob;
+ ok= 1;
+ make_editLatt();
+ }
+ else if(ob->type==OB_SURF || ob->type==OB_CURVE) {
+ ok= 1;
+ G.obedit= ob;
+ make_editNurb();
+ }
+ allqueue(REDRAWBUTSEDIT, 0);
+ countall();
+
+ if(ok) {
+ setcursor_space(SPACE_VIEW3D, CURSOR_EDIT);
+
+ allqueue(REDRAWVIEW3D, 0);
+ }
+ else G.obedit= 0;
+
+ if (G.obpose)
+ exit_posemode (1);
+ scrarea_queue_headredraw(curarea);
+}
+
+void make_displists_by_parent(Object *ob) {
+ Base *base;
+
+ for (base= FIRSTBASE; base; base= base->next)
+ if (ob==base->object->parent)
+ makeDispList(base->object);
+}
+
+void exit_editmode(int freedata) /* freedata==0 bij render */
+{
+ Base *base;
+ Object *ob;
+ Curve *cu;
+
+ if(G.obedit==0) return;
+
+ if(G.obedit->type==OB_MESH) {
+
+ /* tijdelijk */
+ countall();
+ if(G.totvert>65000) {
+ error("too many vertices");
+ return;
+ }
+ load_editMesh();
+
+ if(freedata) free_editMesh();
+ if(G.f & G_FACESELECT) allqueue(REDRAWIMAGE, 0);
+
+ build_particle_system(G.obedit);
+ }
+ else if (G.obedit->type==OB_ARMATURE){
+ load_editArmature();
+ if (freedata) free_editArmature();
+ }
+ else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
+ load_editNurb();
+ if(freedata) freeNurblist(&editNurb);
+ }
+ else if(G.obedit->type==OB_FONT && freedata==1) {
+ load_editText();
+ }
+ else if(G.obedit->type==OB_LATTICE) {
+ load_editLatt();
+ if(freedata) free_editLatt();
+ }
+ else if(G.obedit->type==OB_MBALL) {
+ load_editMball();
+ if(freedata) BLI_freelistN(&editelems);
+ }
+
+ ob= G.obedit;
+
+ /* obedit moet 0 zijn voor curve-extrude, niet voor smeshes */
+ if(ob->type==OB_CURVE) G.obedit= 0;
+ G.obedit= 0;
+ makeDispList(ob);
+
+
+
+ /* heeft dit nog invloed op andere bases? */
+ if(ob->type==OB_CURVE) {
+
+ /* test of ob als bevelcurve of textoncurve wordt gebruikt */
+ base= FIRSTBASE;
+ while(base) {
+ if ELEM(base->object->type, OB_CURVE, OB_FONT) {
+ cu= base->object->data;
+
+ if(cu->textoncurve==ob) {
+ text_to_curve(base->object, 0);
+ makeDispList(base->object);
+ }
+ if(cu->bevobj== ob) {
+ makeDispList(base->object);
+ }
+ }
+ base= base->next;
+ }
+
+ }
+ else if(ob->type==OB_LATTICE) {
+ make_displists_by_parent(ob);
+ }
+
+ if(freedata) {
+ setcursor_space(SPACE_VIEW3D, CURSOR_STD);
+
+ countall();
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWBUTSEDIT, 0);
+ allqueue(REDRAWBUTSGAME, 0);
+ }
+ else {
+ G.obedit= ob;
+ }
+ scrarea_queue_headredraw(curarea);
+
+}
+
+void check_editmode(int type)
+{
+
+ if (G.obedit==0 || G.obedit->type==type) return;
+
+ exit_editmode(1);
+}
+
+static int centremode= 0; /* 0 == do centre, 1 == centre new, 2 == centre cursor */
+
+void docentre(void)
+{
+ Base *base;
+ Object *ob;
+ Mesh *me, *tme;
+ Curve *cu;
+ MVert *mvert;
+// BezTriple *bezt;
+// BPoint *bp;
+ Nurb *nu, *nu1;
+ EditVert *eve;
+ float cent[3], centn[3], min[3], max[3], omat[3][3];
+ int a;
+
+ if(G.scene->id.lib) return;
+
+ if(G.obedit) {
+
+ INIT_MINMAX(min, max);
+
+ if(G.obedit->type==OB_MESH) {
+ eve= G.edve.first;
+ while(eve) {
+ DO_MINMAX(eve->co, min, max);
+ eve= eve->next;
+ }
+ cent[0]= (min[0]+max[0])/2.0;
+ cent[1]= (min[1]+max[1])/2.0;
+ cent[2]= (min[2]+max[2])/2.0;
+
+ eve= G.edve.first;
+ while(eve) {
+ VecSubf(eve->co, eve->co, cent);
+ eve= eve->next;
+ }
+ }
+ }
+
+ /* vlaggen resetten */
+ base= FIRSTBASE;
+ while(base) {
+ if TESTBASELIB(base) {
+ base->object->flag &= ~OB_DONE;
+ }
+ base= base->next;
+ }
+ me= G.main->mesh.first;
+ while(me) {
+ me->flag &= ~ME_ISDONE;
+ me= me->id.next;
+ }
+
+ base= FIRSTBASE;
+ while(base) {
+
+ if TESTBASELIB(base) {
+ if((base->object->flag & OB_DONE)==0) {
+
+ base->object->flag |= OB_DONE;
+
+ if(G.obedit==0 && (me=get_mesh(base->object)) ) {
+
+ if(me->key) {
+ error("Mesh with vertexkey!");
+ return;
+ }
+
+ if(centremode==2) {
+ VECCOPY(cent, give_cursor());
+ Mat4Invert(base->object->imat, base->object->obmat);
+ Mat4MulVecfl(base->object->imat, cent);
+ } else {
+ INIT_MINMAX(min, max);
+
+ mvert= me->mvert;
+ for(a=0; a<me->totvert; a++, mvert++) {
+ DO_MINMAX(mvert->co, min, max);
+ }
+
+ cent[0]= (min[0]+max[0])/2.0;
+ cent[1]= (min[1]+max[1])/2.0;
+ cent[2]= (min[2]+max[2])/2.0;
+ }
+
+ mvert= me->mvert;
+ for(a=0; a<me->totvert; a++, mvert++) {
+ VecSubf(mvert->co, mvert->co, cent);
+ }
+ me->flag |= ME_ISDONE;
+
+ if(centremode) {
+ Mat3CpyMat4(omat, base->object->obmat);
+
+ VECCOPY(centn, cent);
+ Mat3MulVecfl(omat, centn);
+ base->object->loc[0]+= centn[0];
+ base->object->loc[1]+= centn[1];
+ base->object->loc[2]+= centn[2];
+
+ /* andere users? */
+ ob= G.main->object.first;
+ while(ob) {
+ if((ob->flag & OB_DONE)==0) {
+ tme= get_mesh(ob);
+
+ if(tme==me) {
+
+ ob->flag |= OB_DONE;
+
+ Mat3CpyMat4(omat, ob->obmat);
+ VECCOPY(centn, cent);
+ Mat3MulVecfl(omat, centn);
+ ob->loc[0]+= centn[0];
+ ob->loc[1]+= centn[1];
+ ob->loc[2]+= centn[2];
+
+ if(tme && (tme->flag & ME_ISDONE)==0) {
+ mvert= tme->mvert;
+ for(a=0; a<tme->totvert; a++, mvert++) {
+ VecSubf(mvert->co, mvert->co, cent);
+ }
+ tme->flag |= ME_ISDONE;
+ }
+ }
+ }
+
+ ob= ob->id.next;
+ }
+ }
+
+ /* displisten van alle users, ook deze base */
+ makeDispList(base->object);
+
+ /* DOEN: alle users aflopen... */
+ tex_space_mesh(me);
+
+ }
+ else if ELEM(base->object->type, OB_CURVE, OB_SURF) {
+
+ if(G.obedit) {
+ nu1= editNurb.first;
+ }
+ else {
+ cu= base->object->data;
+ nu1= cu->nurb.first;
+ }
+
+ if(centremode==2) {
+ VECCOPY(cent, give_cursor());
+ Mat4Invert(base->object->imat, base->object->obmat);
+ Mat4MulVecfl(base->object->imat, cent);
+
+ /* Curves need to be 2d, never offset in
+ * Z. Is a somewhat arbitrary restriction,
+ * would probably be nice to remove.
+ */
+ cent[2]= 0.0;
+ } else {
+ INIT_MINMAX(min, max);
+
+ nu= nu1;
+ while(nu) {
+ minmaxNurb(nu, min, max);
+ nu= nu->next;
+ }
+
+ cent[0]= (min[0]+max[0])/2.0;
+ cent[1]= (min[1]+max[1])/2.0;
+ cent[2]= (min[2]+max[2])/2.0;
+ }
+
+ nu= nu1;
+ while(nu) {
+ if( (nu->type & 7)==1) {
+ a= nu->pntsu;
+ while (a--) {
+ VecSubf(nu->bezt[a].vec[0], nu->bezt[a].vec[0], cent);
+ VecSubf(nu->bezt[a].vec[1], nu->bezt[a].vec[1], cent);
+ VecSubf(nu->bezt[a].vec[2], nu->bezt[a].vec[2], cent);
+ }
+ }
+ else {
+ a= nu->pntsu*nu->pntsv;
+ while (a--)
+ VecSubf(nu->bp[a].vec, nu->bp[a].vec, cent);
+ }
+ nu= nu->next;
+ }
+
+ if(centremode && G.obedit==0) {
+ Mat3CpyMat4(omat, base->object->obmat);
+
+ Mat3MulVecfl(omat, cent);
+ base->object->loc[0]+= cent[0];
+ base->object->loc[1]+= cent[1];
+ base->object->loc[2]+= cent[2];
+ }
+
+ if(G.obedit) {
+ makeDispList(G.obedit);
+ break;
+ }
+ else makeDispList(base->object);
+
+ }
+ else if(base->object->type==OB_FONT) {
+ /* uit de bb halen */
+
+ cu= base->object->data;
+ if(cu->bb==0) return;
+
+ cu->xof= -0.5*( cu->bb->vec[4][0] - cu->bb->vec[0][0]);
+ cu->yof= -0.5 -0.5*( cu->bb->vec[0][1] - cu->bb->vec[2][1]); /* extra 0.5 is de hoogte van de bovenste regel */
+
+ /* klopt niet helemaal, een keer goed doen! */
+ cu->xof /= cu->fsize;
+ cu->yof /= cu->fsize;
+
+ text_to_curve(base->object, 0);
+ makeDispList(base->object);
+
+ allqueue(REDRAWBUTSEDIT, 0);
+ }
+ }
+ }
+ base= base->next;
+ }
+
+ allqueue(REDRAWVIEW3D, 0);
+}
+
+void docentre_new(void)
+{
+ if(G.scene->id.lib) return;
+
+ if(G.obedit) {
+ error("Unable to perform function in EditMode");
+ }
+ else {
+ centremode= 1;
+ docentre();
+ centremode= 0;
+ }
+}
+
+void docentre_cursor(void)
+{
+ if(G.scene->id.lib) return;
+
+ if(G.obedit) {
+ error("Unable to perform function in EditMode");
+ }
+ else {
+ centremode= 2;
+ docentre();
+ centremode= 0;
+ }
+}
+
+void movetolayer(void)
+{
+ Base *base;
+ unsigned int lay= 0, local;
+
+ if(G.scene->id.lib) return;
+
+ base= FIRSTBASE;
+ while(base) {
+ if TESTBASE(base) lay |= base->lay;
+ base= base->next;
+ }
+ if(lay==0) return;
+ lay &= 0xFFFFFF;
+
+ if( movetolayer_buts(&lay)==0 ) return;
+ if(lay==0) return;
+
+ base= FIRSTBASE;
+ while(base) {
+ if TESTBASE(base) {
+ local= base->lay & 0xFF000000;
+ base->lay= lay + local;
+
+ base->object->lay= lay;
+ }
+ base= base->next;
+ }
+ countall();
+ allqueue(REDRAWBUTSEDIT, 0);
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWOOPS, 0);
+ allqueue(REDRAWINFO, 0);
+}
+
+
+void special_editmenu(void)
+{
+ extern short editbutflag;
+ extern float doublimit;
+ float fac;
+ int nr;
+ short randfac;
+
+ if(G.obedit==0) {
+ if(G.f & G_FACESELECT) {
+ Mesh *me= get_mesh(OBACT);
+ TFace *tface;
+ int a;
+
+ if(me==0 || me->tface==0) return;
+
+ nr= pupmenu("Specials%t|Set Tex%x1| Shared%x2| Light%x3| Invisible%x4| Collision%x5|Clr Tex%x6| Shared%x7| Light%x8| Invisible%x9| Collision%x10");
+
+ for(a=me->totface, tface= me->tface; a>0; a--, tface++) {
+ if(tface->flag & SELECT) {
+ switch(nr) {
+ case 1:
+ tface->mode |= TF_TEX; break;
+ case 2:
+ tface->mode |= TF_SHAREDCOL; break;
+ case 3:
+ tface->mode |= TF_LIGHT; break;
+ case 4:
+ tface->mode |= TF_INVISIBLE; break;
+ case 5:
+ tface->mode |= TF_DYNAMIC; break;
+ case 6:
+ tface->mode &= ~TF_TEX;
+ tface->tpage= 0;
+ break;
+ case 7:
+ tface->mode &= ~TF_SHAREDCOL; break;
+ case 8:
+ tface->mode &= ~TF_LIGHT; break;
+ case 9:
+ tface->mode &= ~TF_INVISIBLE; break;
+ case 10:
+ tface->mode &= ~TF_DYNAMIC; break;
+ }
+ }
+ }
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWBUTSGAME, 0);
+ }
+ else if(G.f & G_VERTEXPAINT) {
+ Mesh *me= get_mesh(OBACT);
+
+ if(me==0 || (me->mcol==NULL && me->tface==NULL) ) return;
+
+ nr= pupmenu("Specials%t|Shared VertexCol%x1");
+ if(nr==1) {
+
+ if(me->tface) tface_to_mcol(me);
+
+ copy_vpaint_undo( (unsigned int *)me->mcol, me->totface);
+ do_shared_vertexcol(me);
+
+ if(me->tface) mcol_to_tface(me, 1);
+ }
+ }
+ else {
+ Base *base, *base_select= NULL;
+
+ // Get the active object mesh.
+ Mesh *me= get_mesh(OBACT);
+
+ // If the active object is a mesh and license key valid..
+ if(me && LICENSE_KEY_VALID) {
+ // Bring up a little menu with the boolean operation choices on.
+ nr= pupmenu("Boolean %t|Intersect%x1|Union%x2|Difference%x3");
+
+ if (nr > 0) {
+ // user has made a choice of a menu element.
+ // All of the boolean functions require 2 mesh objects
+ // we search through the object list to find the other
+ // selected item and make sure it is distinct and a mesh.
+
+ base= FIRSTBASE;
+ while(base) {
+ if(base->flag & SELECT) {
+ if(base->object != OBACT) base_select= base;
+ }
+
+ base= base->next;
+ }
+
+ if (base_select) {
+ if (get_mesh(base_select->object)) {
+ waitcursor(1);
+
+ if (!NewBooleanMesh(BASACT,base_select,nr)) {
+ error("An internal error occurred -- sorry!");
+ }
+
+ waitcursor(0);
+ } else {
+ error("Please select 2 meshes");
+ }
+ } else {
+ error("Please select 2 meshes");
+ }
+ }
+
+ allqueue(REDRAWVIEW3D, 0);
+ }
+ }
+ }
+ else if(G.obedit->type==OB_MESH) {
+
+ nr= pupmenu("Specials%t|Subdivide%x1|Subdivide Fractal%x2|Subdivide Smooth%x3|Remove Doubles%x4|Hide%x5|Reveal%x6|Select swap%x7|Flip Normals %x8|Smooth %x9");
+ if(nr>0) waitcursor(1);
+
+ switch(nr) {
+ case 1:
+ subdivideflag(1, 0.0, editbutflag);
+ break;
+ case 2:
+ randfac= 10;
+ if(button(&randfac, 1, 100, "Rand fac:")==0) return;
+ fac= -( (float)randfac )/100;
+ subdivideflag(1, fac, editbutflag);
+ break;
+ case 3:
+ subdivideflag(1, 0.0, editbutflag | B_SMOOTH);
+ break;
+ case 4:
+ notice("Removed: %d\n", removedoublesflag(1, doublimit));
+ break;
+ case 5:
+ hide_mesh(0);
+ break;
+ case 6:
+ reveal_mesh();
+ break;
+ case 7:
+ selectswap_mesh();
+ break;
+ case 8:
+ flip_editnormals();
+ break;
+ case 9:
+ vertexsmooth();
+ break;
+ }
+
+ makeDispList(G.obedit);
+
+ if(nr>0) waitcursor(0);
+
+ }
+/* else if (G.obedit->type==OB_ARMATURE){
+ nr= pupmenu("Specials%t|");
+ if (nr>0) waitcursor (1);
+ switch (nr){
+ case 1:
+ }
+ if (nr>0) waitcursor (0);
+ }
+*/
+ else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
+
+ /* nr= pupmenu("Specials%t|Subdivide%x1|Hide%x5|Reveal%x6|Select swap%x7"); */
+ nr= pupmenu("Specials%t|Subdivide%x1|Switch Direction%x2");
+
+ switch(nr) {
+ case 1:
+ subdivideNurb();
+ break;
+ case 2:
+ switchdirectionNurb2();
+ break;
+ }
+ }
+
+
+
+
+ countall();
+ allqueue(REDRAWVIEW3D, 0);
+
+}
+
+void convertmenu(void)
+{
+ Base *base, *basen, *basact;
+ Object *ob, *ob1;
+ Curve *cu;
+ MetaBall *mb;
+ Mesh *me;
+ DispList *dl;
+ int ok=0, nr = 0, a;
+
+ if(G.scene->id.lib) return;
+
+ ob= OBACT;
+ if(ob==0) return;
+ if(G.obedit) return;
+
+ basact= BASACT; /* will be restored */
+
+ if(ob->type==OB_FONT) {
+ nr= pupmenu("Convert Font to%t|Curve");
+ if(nr>0) ok= 1;
+ }
+ else if(ob->type==OB_MBALL) {
+ nr= pupmenu("Convert MetaBall to%t|Mesh (keep original)");
+ if(nr>0) ok= 1;
+ }
+ else if(ob->type==OB_CURVE) {
+ nr= pupmenu("Convert Curve to%t|Mesh");
+ if(nr>0) ok= 1;
+ }
+ else if(ob->type==OB_SURF) {
+ nr= pupmenu("Convert Nurbs Surf to%t|Mesh");
+ if(nr>0) ok= 1;
+ }
+ else if(ob->type==OB_MESH && ((Mesh*) ob->data)->flag&ME_SUBSURF) {
+ nr= pupmenu("Convert SubSurf to%t|Mesh (keep original)");
+ if(nr>0) ok= 1;
+ }
+ if(ok==0) return;
+
+ /* denk aan meerdere users! */
+
+ /* vlaggen resetten */
+ base= FIRSTBASE;
+ while(base) {
+ if TESTBASELIB(base) {
+ base->object->flag &= ~OB_DONE;
+ }
+ base= base->next;
+ }
+
+ base= FIRSTBASE;
+ while(base) {
+ if TESTBASELIB(base) {
+
+ ob= base->object;
+
+ if(ob->flag & OB_DONE);
+ else if(ob->type==OB_MESH) {
+ Mesh *oldme= ob->data;
+
+ if (oldme->flag&ME_SUBSURF) {
+ ob->flag |= OB_DONE;
+
+ ob1= copy_object(ob);
+
+ basen= MEM_mallocN(sizeof(Base), "duplibase");
+ *basen= *base;
+ BLI_addhead(&G.scene->base, basen); /* addhead: anders oneindige lus */
+ basen->object= ob1;
+ basen->flag &= ~SELECT;
+
+ me= ob1->data;
+ me->id.us--;
+
+ ob1->data= add_mesh();
+ G.totmesh++;
+ ob1->type= OB_MESH;
+
+ me= ob1->data;
+ me->totcol= oldme->totcol;
+ if(ob1->totcol) {
+ me->mat= MEM_dupallocN(oldme->mat);
+ for(a=0; a<ob1->totcol; a++) id_us_plus((ID *)me->mat[a]);
+ }
+
+ subsurf_to_mesh(ob, ob1->data);
+
+ tex_space_mesh(me);
+ }
+ }
+ else if(ob->type==OB_FONT) {
+ if(nr==1) {
+
+ ob->flag |= OB_DONE;
+
+ ob->type= OB_CURVE;
+ cu= ob->data;
+
+ if(cu->vfont) {
+ cu->vfont->id.us--;
+ cu->vfont= 0;
+ }
+ /* andere users */
+ if(cu->id.us>1) {
+ ob1= G.main->object.first;
+ while(ob1) {
+ if(ob1->data==cu) ob1->type= OB_CURVE;
+ ob1= ob1->id.next;
+ }
+ }
+ }
+ }
+ else if ELEM(ob->type, OB_CURVE, OB_SURF) {
+ if(nr==1) {
+
+ ob->flag |= OB_DONE;
+ cu= ob->data;
+
+ dl= cu->disp.first;
+ if(dl==0) makeDispList(ob);
+
+ nurbs_to_mesh(ob); /* doet ook users */
+
+ /* texspace en normalen */
+ BASACT= base;
+ enter_editmode();
+ exit_editmode(1);
+ BASACT= basact;
+ }
+ }
+ else if(ob->type==OB_MBALL) {
+
+ if(nr==1) {
+ ob= find_basis_mball(ob);
+
+ if(ob->disp.first && !(ob->flag&OB_DONE)) {
+
+ ob->flag |= OB_DONE;
+
+ ob1= copy_object(ob);
+
+ basen= MEM_mallocN(sizeof(Base), "duplibase");
+ *basen= *base;
+ BLI_addhead(&G.scene->base, basen); /* addhead: anders oneindige lus */
+ basen->object= ob1;
+ basen->flag &= ~SELECT;
+
+ mb= ob1->data;
+ mb->id.us--;
+
+ ob1->data= add_mesh();
+ G.totmesh++;
+ ob1->type= OB_MESH;
+
+ me= ob1->data;
+ me->totcol= mb->totcol;
+ if(ob1->totcol) {
+ me->mat= MEM_dupallocN(mb->mat);
+ for(a=0; a<ob1->totcol; a++) id_us_plus((ID *)me->mat[a]);
+ }
+
+ mball_to_mesh(&ob->disp, ob1->data);
+ tex_space_mesh(me);
+ }
+ }
+ }
+ }
+ base= base->next;
+ }
+
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWOOPS, 0);
+ allqueue(REDRAWBUTSEDIT, 0);
+}
+
+void copymenu_properties(Object *ob)
+{
+ bProperty *prop, *propn, *propc;
+ Base *base;
+ int nr, tot=0;
+ char *str;
+
+ prop= ob->prop.first;
+ while(prop) {
+ tot++;
+ prop= prop->next;
+ }
+
+ if(tot==0) {
+ error("No properties in Object");
+ return;
+ }
+
+ str= MEM_callocN(24+32*tot, "copymenu prop");
+
+ strcpy(str, "Copy Property %t");
+
+ tot= 0;
+ prop= ob->prop.first;
+ while(prop) {
+ tot++;
+ strcat(str, " |");
+ strcat(str, prop->name);
+ prop= prop->next;
+ }
+
+ nr= pupmenu(str);
+ if(nr>0) {
+ tot= 0;
+ prop= ob->prop.first;
+ while(prop) {
+ tot++;
+ if(tot==nr) break;
+ prop= prop->next;
+ }
+ if(prop) {
+ propc= prop;
+
+ base= FIRSTBASE;
+ while(base) {
+ if(base != BASACT) {
+ if(TESTBASELIB(base)) {
+ prop= get_property(base->object, propc->name);
+ if(prop) {
+ free_property(prop);
+ BLI_remlink(&base->object->prop, prop);
+ }
+ propn= copy_property(propc);
+ BLI_addtail(&base->object->prop, propn);
+ }
+ }
+ base= base->next;
+ }
+ }
+ }
+ MEM_freeN(str);
+ allqueue(REDRAWVIEW3D, 0);
+}
+
+void copymenu_logicbricks(Object *ob)
+{
+ Base *base;
+
+ base= FIRSTBASE;
+ while(base) {
+ if(base->object != ob) {
+ if(TESTBASELIB(base)) {
+
+ /* first: free all logic */
+ free_sensors(&base->object->sensors);
+ unlink_controllers(&base->object->controllers);
+ free_controllers(&base->object->controllers);
+ unlink_actuators(&base->object->actuators);
+ free_actuators(&base->object->actuators);
+
+ /* now copy it, this also works without logicbricks! */
+ clear_sca_new_poins_ob(ob);
+ copy_sensors(&base->object->sensors, &ob->sensors);
+ copy_controllers(&base->object->controllers, &ob->controllers);
+ copy_actuators(&base->object->actuators, &ob->actuators);
+ set_sca_new_poins_ob(base->object);
+
+ /* some menu settings */
+ base->object->scavisflag= ob->scavisflag;
+ base->object->scaflag= ob->scaflag;
+
+ }
+ }
+ base= base->next;
+ }
+}
+
+void copymenu()
+{
+ Object *ob, *obt;
+ Base *base;
+ Curve *cu, *cu1;
+ void *poin1, *poin2=0;
+ short event;
+ char str[256];
+
+ if(G.scene->id.lib) return;
+
+ if(OBACT==0) return;
+ if(G.obedit) {
+ /* obedit_copymenu(); */
+ return;
+ }
+
+ strcpy(str, "COPY %t|Loc%x1|Rot%x2|Size%x3|Drawtype%x4|TimeOffs%x5|Dupli%x6|%l|Mass%x7|Damping%x8|Properties%x9|Logic Bricks%x10");
+
+ ob= OBACT;
+
+ if ELEM5(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL) {
+ strcat(str, "|Tex Space%x17");
+ if(ob->type==OB_MESH) poin2= &(((Mesh *)ob->data)->texflag);
+ else if ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT) poin2= &(((Curve *)ob->data)->texflag);
+ else if(ob->type==OB_MBALL) poin2= &(((MetaBall *)ob->data)->texflag);
+ }
+
+ if(ob->type == OB_FONT) strcat(str, "|Font Settings%x18|Bevel Settings%x19");
+ if(ob->type == OB_CURVE) strcat(str, "|Bevel Settings%x19");
+
+ if(ob->type==OB_MESH){
+ strcat(str, "|Subdiv%x21");
+ }
+
+ if( give_parteff(ob) ) strcat(str, "|Particle Settings%x20");
+
+ strcat (str, "|Object Constraints%x22");
+
+ event= pupmenu(str);
+ if(event<= 0) return;
+
+ if(event==9) {
+ copymenu_properties(ob);
+ return;
+ }
+ else if(event==10) {
+ copymenu_logicbricks(ob);
+ return;
+ }
+
+ base= FIRSTBASE;
+ while(base) {
+ if(base != BASACT) {
+ if(TESTBASELIB(base)) {
+
+ if(event==1) { /* loc */
+ VECCOPY(base->object->loc, ob->loc);
+ VECCOPY(base->object->dloc, ob->dloc);
+ }
+ else if(event==2) { /* rot */
+ VECCOPY(base->object->rot, ob->rot);
+ VECCOPY(base->object->drot, ob->drot);
+ VECCOPY(base->object->quat, ob->quat);
+ VECCOPY(base->object->dquat, ob->dquat);
+ }
+ else if(event==3) { /* size */
+ VECCOPY(base->object->size, ob->size);
+ VECCOPY(base->object->dsize, ob->dsize);
+ }
+ else if(event==4) { /* drawtype */
+ base->object->dt= ob->dt;
+ base->object->dtx= ob->dtx;
+ }
+ else if(event==5) { /* time offs */
+ base->object->sf= ob->sf;
+ }
+ else if(event==6) { /* dupli */
+ base->object->dupon= ob->dupon;
+ base->object->dupoff= ob->dupoff;
+ base->object->dupsta= ob->dupsta;
+ base->object->dupend= ob->dupend;
+
+ base->object->transflag &= ~OB_DUPLI;
+ base->object->transflag |= (ob->transflag & OB_DUPLI);
+ }
+ else if(event==7) { /* mass */
+ base->object->mass= ob->mass;
+ }
+ else if(event==8) { /* damping */
+ base->object->damping= ob->damping;
+ base->object->rdamping= ob->rdamping;
+ }
+ else if(event==17) { /* tex space */
+ obt= base->object;
+ poin1= 0;
+ if(obt->type==OB_MESH) poin1= &(((Mesh *)obt->data)->texflag);
+ else if ELEM3(obt->type, OB_CURVE, OB_SURF, OB_FONT) poin1= &(((Curve *)obt->data)->texflag);
+ else if(obt->type==OB_MBALL) poin1= &(((MetaBall *)obt->data)->texflag);
+
+ if(poin1) {
+ memcpy(poin1, poin2, 4+12+12+12);
+
+ if(obt->type==OB_MESH) tex_space_mesh(obt->data);
+ else if(obt->type==OB_MBALL) tex_space_mball(obt);
+ else tex_space_curve(obt->data);
+ }
+ }
+ else if(event==18) { /* font settings */
+
+ if(base->object->type==ob->type) {
+ cu= ob->data;
+ cu1= base->object->data;
+
+ cu1->spacemode= cu->spacemode;
+ cu1->spacing= cu->spacing;
+ cu1->linedist= cu->linedist;
+ cu1->shear= cu->shear;
+ cu1->fsize= cu->fsize;
+ cu1->xof= cu->xof;
+ cu1->yof= cu->yof;
+ cu1->textoncurve= cu->textoncurve;
+ if(cu1->vfont) cu1->vfont->id.us--;
+ cu1->vfont= cu->vfont;
+ id_us_plus((ID *)cu1->vfont);
+ text_to_curve(base->object, 0);
+
+ strcpy(cu1->family, cu->family);
+
+ makeDispList(base->object);
+ }
+ }
+ else if(event==19) { /* bevel settings */
+
+ if ELEM(base->object->type, OB_CURVE, OB_FONT) {
+ cu= ob->data;
+ cu1= base->object->data;
+
+ cu1->bevobj= cu->bevobj;
+ cu1->width= cu->width;
+ cu1->bevresol= cu->bevresol;
+ cu1->ext1= cu->ext1;
+ cu1->ext2= cu->ext2;
+
+ makeDispList(base->object);
+ }
+ }
+ else if(event==20) { /* particle settings */
+ PartEff *pa1, *pa2;
+ char *p1, *p2;
+
+ pa1= give_parteff(ob);
+ pa2= give_parteff(base->object);
+
+ if(pa1==0 && pa2) {
+ BLI_remlink( &(base->object->effect), pa2);
+ free_effect( (Effect *) pa2);
+ }
+ else if(pa1 && pa2==0) {
+ free_effects(&(base->object->effect));
+ copy_effects(&(base->object->effect), &ob->effect);
+ build_particle_system(base->object);
+ }
+ else if(pa1 && pa2) {
+ if(pa2->keys) MEM_freeN(pa2->keys);
+
+ p1= (char *)pa1; p2= (char *)pa2;
+ memcpy( p2+8, p1+8, sizeof(PartEff) - 8);
+ pa2->keys= 0;
+
+ build_particle_system(base->object);
+ }
+ }
+ else if(event==21){
+ if (base->object->type==OB_MESH) {
+ Mesh *targetme= base->object->data;
+ Mesh *sourceme= ob->data;
+
+ targetme->flag= (targetme->flag&~ME_SUBSURF) | (sourceme->flag&ME_SUBSURF);
+ targetme->subdiv= sourceme->subdiv;
+ targetme->subdivr= sourceme->subdivr;
+ makeDispList(base->object);
+ }
+ }
+ else if(event==22){
+ /* Clear the constraints on the target */
+ free_constraints(&base->object->constraints);
+ free_constraint_channels(&base->object->constraintChannels);
+
+ /* Copy the constraint channels over */
+ copy_constraints(&base->object->constraints, &ob->constraints);
+ if (U.dupflag&DUPIPO)
+ copy_constraint_channels(&base->object->constraintChannels, &ob->constraintChannels);
+ else
+ clone_constraint_channels (&base->object->constraintChannels, &ob->constraintChannels, NULL);
+
+ base->object->activecon = NULL;
+ }
+ }
+ }
+ base= base->next;
+ }
+
+ allqueue(REDRAWVIEW3D, 0);
+ if(event==20) {
+ allqueue(REDRAWBUTSANIM, 0);
+ }
+
+}
+
+void link_to_scene(unsigned short nr)
+{
+ Scene *sce= (Scene*) BLI_findlink(&G.main->scene, G.curscreen->scenenr-1);
+ Base *base, *nbase;
+
+ if(sce==0) return;
+ if(sce->id.lib) return;
+
+ base= FIRSTBASE;
+ while(base) {
+ if(TESTBASE(base)) {
+
+ nbase= MEM_mallocN( sizeof(Base), "newbase");
+ *nbase= *base;
+ BLI_addhead( &(sce->base), nbase);
+ id_us_plus((ID *)base->object);
+ }
+ base= base->next;
+ }
+}
+
+void linkmenu()
+{
+ Object *ob, *obt;
+ Base *base, *nbase, *sbase;
+ Scene *sce = NULL;
+ ID *id;
+ Material ***matarar, ***obmatarar, **matar1, **matar2;
+ int a;
+ short event, *totcolp, nr;
+ char str[140], *strp;
+
+
+ if(OBACT==0) return;
+ ob= OBACT;
+
+ strcpy(str, "MAKE LINKS %t|To scene...%x1|Object Ipo%x4");
+
+ if(ob->type==OB_MESH)
+ strcat(str, "|Mesh data%x2|Materials%x3");
+ else if(ob->type==OB_CURVE)
+ strcat(str, "|Curve data%x2|Materials%x3");
+ else if(ob->type==OB_FONT)
+ strcat(str, "|Font data%x2|Materials%x3");
+ else if(ob->type==OB_SURF)
+ strcat(str, "|Surf data%x2|Materials%x3");
+ else if(ob->type==OB_MBALL)
+ strcat(str, "|Materials%x3");
+ else if(ob->type==OB_CAMERA)
+ strcat(str, "|Camera data%x2");
+ else if(ob->type==OB_LAMP)
+ strcat(str, "|Lamp data%x2");
+ else if(ob->type==OB_LATTICE)
+ strcat(str, "|Lattice data%x2");
+ else if(ob->type==OB_ARMATURE)
+ strcat(str, "|Armature data%x2");
+ event= pupmenu(str);
+ if(event<= 0) return;
+
+ if(event==1) {
+ IDnames_to_pupstring(&strp, NULL, NULL, &(G.main->scene), 0, &nr);
+
+ if(strncmp(strp, "DataBrow", 8)==0) {
+ MEM_freeN(strp);
+
+ activate_databrowse((ID *)G.scene, ID_SCE, 0, B_INFOSCE, &(G.curscreen->scenenr), link_to_scene );
+
+ return;
+ }
+ else {
+ event= pupmenu(strp);
+ MEM_freeN(strp);
+
+ if(event<= 0) return;
+
+ nr= 1;
+ sce= G.main->scene.first;
+ while(sce) {
+ if(nr==event) break;
+ nr++;
+ sce= sce->id.next;
+ }
+ if(sce==G.scene) {
+ error("This is current scene");
+ return;
+ }
+ if(sce==0 || sce->id.lib) return;
+
+ /* denk eraan: is verderop nog nodig */
+ event= 1;
+ }
+ }
+
+ base= FIRSTBASE;
+ while(base) {
+ if(event==1 || base != BASACT) {
+
+ obt= base->object;
+
+ if(TESTBASE(base)) {
+
+ if(event==1) { /* to scene */
+
+ /* testen of het soms al gelinkt is */
+ sbase= sce->base.first;
+ while(sbase) {
+ if(sbase->object==base->object) break;
+ sbase= sbase->next;
+ }
+ if(sbase) { /* eruit */
+ base= base->next;
+ continue;
+ }
+
+ nbase= MEM_mallocN( sizeof(Base), "newbase");
+ *nbase= *base;
+ BLI_addhead( &(sce->base), nbase);
+ id_us_plus((ID *)base->object);
+ }
+ }
+ if(TESTBASELIB(base)) {
+ if(event==2 || event==5) { /* obdata */
+ if(ob->type==obt->type) {
+
+ id= obt->data;
+ id->us--;
+
+ id= ob->data;
+ id_us_plus(id);
+ obt->data= id;
+
+ /* als aantal mat indices veranderd zijn: */
+ test_object_materials(obt->data);
+ }
+ }
+ else if(event==4) { /* ob ipo */
+ if(obt->ipo) obt->ipo->id.us--;
+ obt->ipo= ob->ipo;
+ if(obt->ipo) {
+ id_us_plus((ID *)obt->ipo);
+ do_ob_ipo(obt);
+ }
+ }
+ else if(event==3) { /* materials */
+
+ /* alleen als obt geen materiaal heeft: arrays maken */
+ /* van ob naar obt! */
+
+ obmatarar= give_matarar(ob);
+ matarar= give_matarar(obt);
+ totcolp= give_totcolp(obt);
+
+ /* als 1 van de 2 nul is: geen renderbaar object */
+ if( matarar && obmatarar) {
+
+ /* voorzichtig met users! Dus eerst kopie orig: */
+
+ if(ob->totcol) {
+ matar1= MEM_dupallocN(ob->mat);
+ matar2= MEM_dupallocN(*obmatarar);
+ }
+ else {
+ matar1= matar2= 0;
+ }
+
+ /* alles van obt los linken */
+ for(a=0; a<obt->totcol; a++) {
+ if(obt->mat[a]) obt->mat[a]->id.us--;
+ if( (*matarar)[a]) (*matarar)[a]->id.us--;
+ }
+
+ /* vrijgeven */
+ if(obt->mat) MEM_freeN(obt->mat);
+ if(*matarar) MEM_freeN(*matarar);
+
+ /* hangen kopie er aan */
+ obt->mat= matar1;
+ *matarar= matar2;
+ obt->totcol= ob->totcol;
+ *totcolp= ob->totcol;
+
+ /* users ophogen */
+ for(a=0; a<obt->totcol; a++) {
+ if(obt->mat[a]) id_us_plus((ID *)obt->mat[a]);
+ if( (*matarar)[a]) id_us_plus((ID *)(*matarar)[a]);
+ }
+
+ obt->colbits= ob->colbits;
+
+ /* als aantal mat indices veranderd zijn: */
+ test_object_materials(obt->data);
+ }
+ }
+ }
+ }
+ base= base->next;
+ }
+
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWOOPS, 0);
+ allqueue(REDRAWBUTSHEAD, 0);
+}
+
+void make_duplilist_real()
+{
+ Base *base, *basen;
+ Object *ob;
+ extern ListBase duplilist;
+
+ if(okee("Make dupli's real")==0) return;
+
+ base= FIRSTBASE;
+ while(base) {
+ if TESTBASELIB(base) {
+
+ if(base->object->transflag & OB_DUPLI) {
+
+ make_duplilist(G.scene, base->object);
+ ob= duplilist.first;
+ while(ob) {
+
+ /* font dupli's kunnen totcol hebben zonder mat, halen ze van parent af
+ * dit zou netter moeten
+ */
+ if(ob->mat==0) ob->totcol= 0;
+
+ basen= MEM_dupallocN(base);
+ basen->flag &= ~OB_FROMDUPLI;
+ BLI_addhead(&G.scene->base, basen); /* addhead: anders oneindige lus */
+ ob->ipo= 0; /* zeker weten dat de apply werkt */
+ ob->parent= ob->track= 0;
+ ob->disp.first= ob->disp.last= 0;
+ ob->transflag &= ~OB_DUPLI;
+ basen->object= copy_object(ob);
+
+ apply_obmat(basen->object);
+ ob= ob->id.next;
+ }
+
+ free_duplilist();
+
+ base->object->transflag &= ~OB_DUPLI;
+ }
+ }
+ base= base->next;
+ }
+
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWOOPS, 0);
+}
+
+void apply_object()
+{
+ Base *base, *basact;
+ Object *ob;
+ Mesh *me;
+ Curve *cu;
+ Nurb *nu;
+ BPoint *bp;
+ BezTriple *bezt;
+ MVert *mvert;
+ float mat[3][3];
+ int a;
+
+ if(G.scene->id.lib) return;
+ if(G.obedit) return;
+ basact= BASACT;
+
+ if(G.qual & LR_SHIFTKEY) {
+ ob= OBACT;
+ if(ob==0) return;
+
+ if(ob->transflag & OB_DUPLI) make_duplilist_real();
+ else if(ob->parent && ob->parent->type==OB_LATTICE) apply_lattice();
+
+ return;
+ }
+
+ if(okee("Apply size/rot")==0) return;
+
+ base= FIRSTBASE;
+ while(base) {
+ if TESTBASELIB(base) {
+ ob= base->object;
+
+ if(ob->type==OB_MESH) {
+ object_to_mat3(ob, mat);
+ me= ob->data;
+
+ if(me->id.us>1) {
+ error("Can't do multi user mesh");
+ return;
+ }
+ if(me->key) {
+ error("Can't do key && mesh");
+ return;
+ }
+
+ mvert= me->mvert;
+ for(a=0; a<me->totvert; a++, mvert++) {
+ Mat3MulVecfl(mat, mvert->co);
+ }
+ ob->size[0]= ob->size[1]= ob->size[2]= 1.0;
+ ob->rot[0]= ob->rot[1]= ob->rot[2]= 0.0;
+ QuatOne(ob->quat);
+
+ where_is_object(ob);
+
+ /* texspace en normalen */
+ BASACT= base;
+ enter_editmode();
+ exit_editmode(1);
+ BASACT= basact;
+
+ }
+ else if (ob->type==OB_ARMATURE){
+ bArmature *arm;
+
+ object_to_mat3(ob, mat);
+ arm= ob->data;
+ if(arm->id.us>1) {
+ error("Can't do multi user armature");
+ return;
+ }
+
+ apply_rot_armature (ob, mat);
+ /* Reset the object's transforms */
+ ob->size[0]= ob->size[1]= ob->size[2]= 1.0;
+ ob->rot[0]= ob->rot[1]= ob->rot[2]= 0.0;
+ QuatOne(ob->quat);
+
+ where_is_object(ob);
+ }
+ else if ELEM(ob->type, OB_CURVE, OB_SURF) {
+ object_to_mat3(ob, mat);
+ cu= ob->data;
+
+ if(cu->id.us>1) {
+ error("Can't do multi user curve");
+ return;
+ }
+ if(cu->key) {
+ error("Can't do keys");
+ return;
+ }
+
+ nu= cu->nurb.first;
+ while(nu) {
+ if( (nu->type & 7)==1) {
+ a= nu->pntsu;
+ bezt= nu->bezt;
+ while(a--) {
+ Mat3MulVecfl(mat, bezt->vec[0]);
+ Mat3MulVecfl(mat, bezt->vec[1]);
+ Mat3MulVecfl(mat, bezt->vec[2]);
+ bezt++;
+ }
+ }
+ else {
+ a= nu->pntsu*nu->pntsv;
+ bp= nu->bp;
+ while(a--) {
+ Mat3MulVecfl(mat, bp->vec);
+ bp++;
+ }
+ }
+ nu= nu->next;
+ }
+
+ ob->size[0]= ob->size[1]= ob->size[2]= 1.0;
+ ob->rot[0]= ob->rot[1]= ob->rot[2]= 0.0;
+ QuatOne(ob->quat);
+
+ where_is_object(ob);
+
+ /* texspace en normalen */
+ BASACT= base;
+ enter_editmode();
+ exit_editmode(1);
+ BASACT= basact;
+ }
+ }
+ base= base->next;
+ }
+
+ allqueue(REDRAWVIEW3D, 0);
+}
+
+
+
+/* ************ ALGEMENE *************** */
+
+static Object *is_a_parent_selected_int(Object *startob, Object *ob, GHash *done_hash) {
+ if (ob!=startob && TESTBASE(ob))
+ return ob;
+
+ if (BLI_ghash_haskey(done_hash, ob))
+ return NULL;
+ else
+ BLI_ghash_insert(done_hash, ob, NULL);
+
+ if (ob->parent) {
+ Object *par= is_a_parent_selected_int(startob, ob->parent, done_hash);
+ if (par)
+ return par;
+ }
+
+ /* IK is more complex in parents... */
+
+ /* XXX, should we be handling armatures or constraints here? - zr */
+
+ if(ob->type==OB_IKA) {
+ Ika *ika= ob->data;
+
+ if (ika->def) {
+ int i;
+
+ for (i=0; i<ika->totdef; i++) {
+ Deform *def= &ika->def[i];
+
+ if (def->ob && ob!=def->ob && def->ob!=startob) {
+ Object *par= is_a_parent_selected_int(startob, def->ob, done_hash);
+ if (par)
+ return par;
+ }
+ }
+ }
+
+ if (ika->parent) {
+ Object *par= is_a_parent_selected_int(startob, ika->parent, done_hash);
+ if (par)
+ return par;
+ }
+ }
+
+ return NULL;
+}
+
+static Object *is_a_parent_selected(Object *ob) {
+ GHash *gh= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+ Object *res= is_a_parent_selected_int(ob, ob, gh);
+ BLI_ghash_free(gh, NULL, NULL);
+
+ return res;
+}
+
+static void setbaseflags_for_editing(int mode) /* 0,'g','r','s' */
+{
+ /*
+ if base selected and has parent selected:
+ base->flag= BA_WASSEL+BA_PARSEL
+ if base not selected and parent selected:
+ base->flag= BA_PARSEL
+
+ */
+ GHash *object_to_base_hash= NULL; /* built on demand, see below - zr */
+ Base *base;
+
+ copy_baseflags();
+
+ for (base= FIRSTBASE; base; base= base->next) {
+ base->flag &= ~(BA_PARSEL+BA_WASSEL);
+
+ if( (base->lay & G.vd->lay) && base->object->id.lib==0) {
+ Object *ob= base->object;
+ Object *parsel= is_a_parent_selected(ob);
+
+ /* hier ook parentkey? */
+
+ if(parsel) {
+ if(base->flag & SELECT) {
+ base->flag &= ~SELECT;
+ base->flag |= (BA_PARSEL+BA_WASSEL);
+ }
+ else base->flag |= BA_PARSEL;
+ }
+
+ if(mode=='g') {
+ if(ob->track && TESTBASE(ob->track) && (base->flag & SELECT)==0)
+ base->flag |= BA_PARSEL;
+ }
+
+ /* updates? */
+ /* ivm automatische portals */
+ if(ob->type==OB_IKA) {
+ Ika *ika= ob->data;
+ if(ika->parent && parsel) base->flag |= BA_WHERE_UPDATE;
+ }
+
+ if(base->flag & (SELECT | BA_PARSEL)) {
+
+ base->flag |= BA_WHERE_UPDATE;
+
+ if(ob->parent) {
+ if(ob->parent->type==OB_LATTICE) base->flag |= BA_DISP_UPDATE;
+ if(ob->parent->type==OB_IKA && ob->partype==PARSKEL) base->flag |= BA_DISP_UPDATE;
+ if(ob->parent->type==OB_ARMATURE && ob->partype==PARSKEL) base->flag |= BA_DISP_UPDATE;
+ }
+ if(ob->track) {
+ ;
+ }
+
+ if( give_parteff(ob) ) base->flag |= BA_DISP_UPDATE;
+
+ if(ob->type==OB_MBALL) {
+ Base *b;
+
+ /* Only bother building the object to base
+ * hash if we are going to be needing it... - zr
+ */
+ if (!object_to_base_hash) {
+ object_to_base_hash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+
+ for (b= FIRSTBASE; b; b= b->next)
+ BLI_ghash_insert(object_to_base_hash, b->object, b);
+ }
+
+ b= BLI_ghash_lookup(object_to_base_hash, find_basis_mball(ob));
+ b->flag |= BA_DISP_UPDATE;
+ }
+ }
+ }
+ }
+
+ if (object_to_base_hash)
+ BLI_ghash_free(object_to_base_hash, NULL, NULL);
+}
+
+
+void clearbaseflags_for_editing()
+{
+ Base *base;
+
+ base= FIRSTBASE;
+ while(base) {
+ if(base->flag & BA_WASSEL) base->flag |= SELECT;
+ base->flag &= ~(BA_PARSEL+BA_WASSEL);
+
+ base->flag &= ~(BA_DISP_UPDATE+BA_WHERE_UPDATE+BA_DO_IPO);
+
+ base= base->next;
+ }
+ copy_baseflags();
+}
+
+void ob_to_transob(Object *ob, TransOb *tob)
+{
+ float totmat[3][3];
+ Object *tr;
+ void *cfirst, *clast;
+
+ tob->ob= ob;
+
+ cfirst = ob->constraints.first;
+ clast = ob->constraints.last;
+
+ ob->constraints.first=ob->constraints.last=NULL;
+
+ tr= ob->track;
+ ob->track= 0;
+ where_is_object(ob);
+ ob->track= tr;
+ ob->constraints.first = cfirst;
+ ob->constraints.last = clast;
+
+
+
+ tob->loc= ob->loc;
+ VECCOPY(tob->oldloc, tob->loc);
+
+ tob->rot= ob->rot;
+ VECCOPY(tob->oldrot, ob->rot);
+ VECCOPY(tob->olddrot, ob->drot);
+
+ tob->quat= ob->quat;
+ QUATCOPY(tob->oldquat, ob->quat);
+ QUATCOPY(tob->olddquat, ob->dquat);
+
+ tob->size= ob->size;
+ VECCOPY(tob->oldsize, ob->size);
+
+ VECCOPY(tob->olddsize, ob->dsize);
+
+ /* alleen object, geen parent */
+ object_to_mat3(ob, tob->obmat);
+ Mat3Inv(tob->obinv, tob->obmat);
+
+ Mat3CpyMat4(totmat, ob->obmat);
+
+ /* dit is totmat zonder obmat: dus parmat */
+ Mat3MulMat3(tob->parmat, totmat, tob->obinv);
+ Mat3Inv(tob->parinv, tob->parmat);
+
+ Mat3MulMat3(tob->axismat, tob->parmat, tob->obmat); // New!
+ Mat3Ortho(tob->axismat);
+
+ VECCOPY(tob->obvec, ob->obmat[3]);
+
+ centroid[0]+= tob->obvec[0];
+ centroid[1]+= tob->obvec[1];
+ centroid[2]+= tob->obvec[2];
+
+ tob->eff= 0;
+
+ if(ob->type==OB_IKA) {
+ Ika *ika=ob->data;
+
+ calc_ika(ika, 0);
+
+ ika->effn[0]= ika->eff[0];
+ ika->effn[1]= ika->eff[1];
+ ika->effn[2]= 0.0;
+
+ VecMat4MulVecfl(ika->effg, ob->obmat, ika->effn);
+
+ if(ika->flag & IK_GRABEFF) {
+
+ tob->eff= ika->effg;
+ VECCOPY(tob->oldeff, tob->eff);
+ tob->flag |= TOB_IKA;
+
+ /* zodat alleen eff update wordt */
+ tob->loc= 0;
+ }
+
+ /* set_ika_undo_vals(); */
+ }
+}
+
+void ob_to_tex_transob(Object *ob, TransOb *tob)
+{
+ Mesh *me;
+ Curve *cu;
+ MetaBall *mb;
+ ID *id;
+
+ ob_to_transob(ob, tob);
+
+ id= ob->data;
+ if(id==0);
+ else if( GS(id->name)==ID_ME) {
+ me= ob->data;
+ me->texflag &= ~AUTOSPACE;
+ tob->loc= me->loc;
+ tob->rot= me->rot;
+ tob->size= me->size;
+ }
+ else if( GS(id->name)==ID_CU) {
+ cu= ob->data;
+ cu->texflag &= ~AUTOSPACE;
+ tob->loc= cu->loc;
+ tob->rot= cu->rot;
+ tob->size= cu->size;
+ }
+ else if( GS(id->name)==ID_MB) {
+ mb= ob->data;
+ mb->texflag &= ~AUTOSPACE;
+ tob->loc= mb->loc;
+ tob->rot= mb->rot;
+ tob->size= mb->size;
+ }
+
+ VECCOPY(tob->oldloc, tob->loc);
+ VECCOPY(tob->oldrot, tob->rot);
+ VECCOPY(tob->oldsize, tob->size);
+}
+
+void make_trans_objects()
+{
+ Base *base;
+ Object *ob;
+ TransOb *tob = NULL;
+ ListBase elems;
+ IpoKey *ik;
+ float cfraont, min[3], max[3];
+ int ipoflag;
+
+ tottrans= 0;
+
+ INIT_MINMAX(min, max);
+ centroid[0]=centroid[1]=centroid[2]= 0.0;
+
+ /* aantal tellen */
+ base= FIRSTBASE;
+ while(base) {
+ if TESTBASELIB(base) {
+ ob= base->object;
+
+ if(transmode==TRANS_TEX) {
+ if(ob->dtx & OB_TEXSPACE) tottrans++;
+ }
+ else {
+ if(ob->ipo && ob->ipo->showkey && (ob->ipoflag & OB_DRAWKEY)) {
+ elems.first= elems.last= 0;
+ make_ipokey_transform(ob, &elems, 1); /* '1' alleen selected keys */
+
+ pushdata(&elems, sizeof(ListBase));
+
+ ik= elems.first;
+ while(ik) {
+ tottrans++;
+ ik= ik->next;
+ }
+ if(elems.first==0) tottrans++;
+ }
+ else tottrans++;
+ }
+ }
+ base= base->next;
+ }
+
+ if(tottrans) tob= transmain= MEM_mallocN(tottrans*sizeof(TransOb), "transmain");
+
+ reset_slowparents();
+
+
+ /* dit hieronder wel doen als tottrans==0, i.v.m. vrijgeven pushpop en ipokeys */
+
+ base= FIRSTBASE;
+ while(base) {
+ if TESTBASELIB(base) {
+ ob= base->object;
+
+ if(transmode==TRANS_TEX) {
+ if(ob->dtx & OB_TEXSPACE) {
+ tob->flag= 0;
+
+ ob_to_tex_transob(ob, tob);
+ DO_MINMAX(tob->obvec, min, max);
+
+ tob++;
+ }
+ }
+ else {
+
+ /* van belang! (o.a. bevobj) */
+ if(base->flag & SELECT) ob->flag|= SELECT; else ob->flag &= ~SELECT;
+
+ if(ob->ipo && ob->ipo->showkey && (ob->ipoflag & OB_DRAWKEY)) {
+
+ popfirst(&elems);
+
+ if(elems.first) {
+ base->flag |= BA_DO_IPO+BA_WASSEL;
+ base->flag &= ~SELECT;
+
+ cfraont= CFRA;
+ set_no_parent_ipo(1);
+ ipoflag= ob->ipoflag;
+ ob->ipoflag &= ~OB_OFFS_OB;
+
+ pushdata(ob->loc, 7*3*4);
+
+ ik= elems.first;
+ while(ik) {
+
+ CFRA= ik->val/G.scene->r.framelen;
+
+ do_ob_ipo(ob);
+ where_is_object(ob);
+
+ ob_to_transob(ob, tob);
+ DO_MINMAX(tob->obvec, min, max);
+
+ /* doet ook tob->flag en oldvals, moet NA ob_to_transob()! */
+ set_ipo_pointers_transob(ik, tob);
+
+ tob++;
+ ik= ik->next;
+ }
+ free_ipokey(&elems);
+
+ poplast(ob->loc);
+ set_no_parent_ipo(0);
+
+ CFRA= cfraont;
+ ob->ipoflag= ipoflag;
+ }
+ else {
+ tob->flag= 0;
+
+ ob_to_transob(ob, tob);
+ DO_MINMAX(tob->obvec, min, max);
+
+ tob++;
+ }
+ }
+ else {
+ tob->flag= 0;
+
+ ob_to_transob(ob, tob);
+ DO_MINMAX(tob->obvec, min, max);
+
+ tob++;
+ }
+ }
+
+ }
+ base= base->next;
+ }
+
+ pushpop_test(); /* alleen voor debug & zekerheid */
+
+ if(tottrans==0) return;
+
+ centroid[0]/= tottrans;
+ centroid[1]/= tottrans;
+ centroid[2]/= tottrans;
+
+ centre[0]= (min[0]+max[0])/2.0;
+ centre[1]= (min[1]+max[1])/2.0;
+ centre[2]= (min[2]+max[2])/2.0;
+}
+
+/* mode: 1 = proportional */
+void make_trans_verts(float *min, float *max, int mode)
+{
+/* extern Lattice *editLatt; already in BKE_lattice.h */
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ TransVert *tv;
+ MetaElem *ml;
+ EditVert *eve;
+ int a;
+ EditBone *ebo;
+ tottrans= 0;
+
+ INIT_MINMAX(min, max);
+ centroid[0]=centroid[1]=centroid[2]= 0.0;
+
+ countall();
+ if(mode) tottrans= G.totvert;
+ else tottrans= G.totvertsel;
+
+ if(G.totvertsel==0) {
+ tottrans= 0;
+ return;
+ }
+
+ tv=transvmain= MEM_callocN(tottrans*sizeof(TransVert), "maketransverts");
+
+ /* we count again because of hide */
+ tottrans= 0;
+
+ if(G.obedit->type==OB_MESH) {
+ eve= G.edve.first;
+ while(eve) {
+ if(eve->h==0) {
+ if(mode==1 || (eve->f & 1)) {
+ VECCOPY(tv->oldloc, eve->co);
+ tv->loc= eve->co;
+ tv->nor= eve->no;
+ tv->flag= eve->f & 1;
+ tv++;
+ tottrans++;
+ }
+ }
+ eve= eve->next;
+ }
+ }
+ else if (G.obedit->type==OB_ARMATURE){
+ for (ebo=G.edbo.first;ebo;ebo=ebo->next){
+ if (ebo->flag & BONE_TIPSEL){
+ VECCOPY (tv->oldloc, ebo->tail);
+ tv->loc= ebo->tail;
+ tv->nor= NULL;
+ tv->flag= 1;
+ tv++;
+ tottrans++;
+ }
+
+ /* Only add the root if there is no selected IK parent */
+ if (ebo->flag & BONE_ROOTSEL){
+ if (!(ebo->parent && (ebo->flag & BONE_IK_TOPARENT) && ebo->parent->flag & BONE_TIPSEL)){
+ VECCOPY (tv->oldloc, ebo->head);
+ tv->loc= ebo->head;
+ tv->nor= NULL;
+ tv->flag= 1;
+ tv++;
+ tottrans++;
+ }
+ }
+
+ }
+ }
+ else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
+ nu= editNurb.first;
+ while(nu) {
+ if((nu->type & 7)==CU_BEZIER) {
+ a= nu->pntsu;
+ bezt= nu->bezt;
+ while(a--) {
+ if(bezt->hide==0) {
+ if(mode==1 || (bezt->f1 & 1)) {
+ VECCOPY(tv->oldloc, bezt->vec[0]);
+ tv->loc= bezt->vec[0];
+ tv->flag= bezt->f1 & 1;
+ tv++;
+ tottrans++;
+ }
+ if(mode==1 || (bezt->f2 & 1)) {
+ VECCOPY(tv->oldloc, bezt->vec[1]);
+ tv->loc= bezt->vec[1];
+ tv->val= &(bezt->alfa);
+ tv->oldval= bezt->alfa;
+ tv->flag= bezt->f2 & 1;
+ tv++;
+ tottrans++;
+ }
+ if(mode==1 || (bezt->f3 & 1)) {
+ VECCOPY(tv->oldloc, bezt->vec[2]);
+ tv->loc= bezt->vec[2];
+ tv->flag= bezt->f3 & 1;
+ tv++;
+ tottrans++;
+ }
+ }
+ bezt++;
+ }
+ }
+ else {
+ a= nu->pntsu*nu->pntsv;
+ bp= nu->bp;
+ while(a--) {
+ if(bp->hide==0) {
+ if(mode==1 || (bp->f1 & 1)) {
+ VECCOPY(tv->oldloc, bp->vec);
+ tv->loc= bp->vec;
+ tv->val= &(bp->alfa);
+ tv->oldval= bp->alfa;
+ tv->flag= bp->f1 & 1;
+ tv++;
+ tottrans++;
+ }
+ }
+ bp++;
+ }
+ }
+ nu= nu->next;
+ }
+ }
+ else if(G.obedit->type==OB_MBALL) {
+ ml= editelems.first;
+ while(ml) {
+ if(ml->flag & SELECT) {
+ tv->loc= &ml->x;
+ VECCOPY(tv->oldloc, tv->loc);
+ tv->val= &(ml->rad);
+ tv->oldval= ml->rad;
+ tv->flag= 1;
+ tv++;
+ tottrans++;
+ }
+ ml= ml->next;
+ }
+ }
+ else if(G.obedit->type==OB_LATTICE) {
+ bp= editLatt->def;
+
+ a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
+
+ while(a--) {
+ if(mode==1 || (bp->f1 & 1)) {
+ if(bp->hide==0) {
+ VECCOPY(tv->oldloc, bp->vec);
+ tv->loc= bp->vec;
+ tv->flag= bp->f1 & 1;
+ tv++;
+ tottrans++;
+ }
+ }
+ bp++;
+ }
+ }
+
+ /* cent enz berekenen */
+ tv= transvmain;
+ for(a=0; a<tottrans; a++, tv++) {
+ if(tv->flag) {
+ centroid[0]+= tv->oldloc[0];
+ centroid[1]+= tv->oldloc[1];
+ centroid[2]+= tv->oldloc[2];
+
+ DO_MINMAX(tv->oldloc, min, max);
+ }
+ }
+ centroid[0]/= G.totvertsel;
+ centroid[1]/= G.totvertsel;
+ centroid[2]/= G.totvertsel;
+
+ centre[0]= (min[0]+max[0])/2.0;
+ centre[1]= (min[1]+max[1])/2.0;
+ centre[2]= (min[2]+max[2])/2.0;
+
+}
+
+void draw_prop_circle()
+{
+ float tmat[4][4], imat[4][4];
+
+ if(G.moving) {
+ setlinestyle(1);
+ cpack(0x303030);
+ mygetmatrix(tmat);
+ Mat4Invert(imat, tmat);
+ setlinestyle(2);
+ drawcircball(prop_cent, prop_size, imat);
+ myloadmatrix(G.vd->viewmat);
+ setlinestyle(0);
+ }
+}
+
+void set_proportional_weight(TransVert *tv, float *min, float *max)
+{
+ float dist, xdist, ydist, zdist;
+
+ if(tv->oldloc[0]<min[0]) xdist= tv->oldloc[0]-min[0];
+ else if(tv->oldloc[0]>max[0]) xdist= tv->oldloc[0]-max[0];
+ else xdist= 0.0;
+
+ if(tv->oldloc[1]<min[1]) ydist= tv->oldloc[1]-min[1];
+ else if(tv->oldloc[1]>max[1]) ydist= tv->oldloc[1]-max[1];
+ else ydist= 0.0;
+
+ if(tv->oldloc[2]<min[2]) zdist= tv->oldloc[2]-min[2];
+ else if(tv->oldloc[2]>max[2]) zdist= tv->oldloc[2]-max[2];
+ else zdist= 0.0;
+
+ dist= sqrt(xdist*xdist + ydist*ydist + zdist*zdist);
+ if(dist==0.0) tv->fac= 1.0;
+ else if(dist > prop_size) tv->fac= 0.0;
+ else {
+ dist= (prop_size-dist)/prop_size;
+ if(prop_mode==1) tv->fac= 3.0*dist*dist - 2.0*dist*dist*dist;
+ else tv->fac= dist*dist;
+ }
+}
+
+void special_trans_update(int keyflags)
+{
+/* extern Lattice *editLatt; already in BKE_lattice.h */
+ Base *base;
+ Curve *cu;
+ IpoCurve *icu;
+
+ if(G.obedit) {
+ if(G.obedit->type==OB_CURVE) {
+ cu= G.obedit->data;
+ if(cu->flag & CU_3D) makeBevelList(G.obedit);
+
+ calc_curvepath(G.obedit);
+ }
+ else if(G.obedit->type==OB_ARMATURE){
+ EditBone *ebo;
+
+ /* Ensure all bones are correctly adjusted */
+ for (ebo=G.edbo.first; ebo; ebo=ebo->next){
+
+ if ((ebo->flag & BONE_IK_TOPARENT) && ebo->parent){
+ /* If this bone has a parent tip that has been moved */
+ if (ebo->parent->flag & BONE_TIPSEL){
+ VECCOPY (ebo->head, ebo->parent->tail);
+ }
+ /* If this bone has a parent tip that has NOT been moved */
+ else{
+ VECCOPY (ebo->parent->tail, ebo->head);
+ }
+ }
+ }
+ }
+ else if(G.obedit->type==OB_LATTICE) {
+
+ if(editLatt->flag & LT_OUTSIDE) outside_lattice(editLatt);
+
+ base= FIRSTBASE;
+ while(base) {
+ if(base->lay & G.vd->lay) {
+ if(base->object->parent==G.obedit) {
+ makeDispList(base->object);
+ }
+ }
+ base= base->next;
+ }
+ }
+ }
+ else if(G.obpose){
+ int i;
+ bPoseChannel *chan;
+
+ if (!G.obpose->pose) G.obpose->pose= MEM_callocN(sizeof(bPose), "pose");
+
+ switch (G.obpose->type){
+ case OB_ARMATURE:
+
+ /* Make channels for the transforming bones (in posemode) */
+ for (i=0; i< tottrans; i++){
+ chan = MEM_callocN (sizeof (bPoseChannel), "transPoseChannel");
+
+ if (keyflags & KEYFLAG_ROT){
+ chan->flag |= POSE_ROT;
+ memcpy (chan->quat, transmain[i].quat, sizeof (chan->quat));
+ }
+ if (keyflags & KEYFLAG_LOC){
+ chan->flag |= POSE_LOC;
+ memcpy (chan->loc, transmain[i].loc, sizeof (chan->loc));
+ }
+ if (keyflags & KEYFLAG_SIZE){
+ chan->flag |= POSE_SIZE;
+ memcpy (chan->size, transmain[i].size, sizeof (chan->size));
+ }
+
+ strcpy (chan->name, ((Bone*) transmain[i].data)->name);
+
+ set_pose_channel (G.obpose->pose, chan);
+ }
+ break;
+ }
+ }
+ else {
+ base= FIRSTBASE;
+ while(base) {
+ if(base->flag & BA_DO_IPO) {
+
+ base->object->ctime= -1234567.0;
+
+ icu= base->object->ipo->curve.first;
+ while(icu) {
+ calchandles_ipocurve(icu);
+ icu= icu->next;
+ }
+
+ }
+ if(base->object->partype & PARSLOW) {
+ base->object->partype -= PARSLOW;
+ where_is_object(base->object);
+ base->object->partype |= PARSLOW;
+ }
+ else if(base->flag & BA_WHERE_UPDATE) {
+ where_is_object(base->object);
+ if(base->object->type==OB_IKA) {
+ itterate_ika(base->object);
+ }
+
+ }
+
+ base= base->next;
+ }
+
+ base= FIRSTBASE;
+ while(base) {
+
+ if(base->flag & BA_DISP_UPDATE) makeDispList(base->object);
+
+ base= base->next;
+ }
+
+ }
+
+#if 0
+ if (G.obpose && G.obpose->type == OB_ARMATURE)
+ make_displists_by_armature(G.obpose);
+#endif
+
+ if(G.vd->drawtype == OB_SHADED) reshadeall_displist();
+
+}
+
+
+void special_aftertrans_update(char mode, int flip, short canceled, int keyflags)
+{
+ Object *ob;
+ Base *base;
+ MetaBall *mb;
+ Curve *cu;
+ Ika *ika;
+ int doit,redrawipo=0;
+
+
+ /* displaylisten e.d. */
+
+ if(G.obedit) {
+ if(G.obedit->type==OB_MBALL) {
+ mb= G.obedit->data;
+ if(mb->flag != MB_UPDATE_ALWAYS) makeDispList(G.obedit);
+ }
+ else if(G.obedit->type==OB_MESH) {
+ if(flip) flip_editnormals();
+
+ recalc_editnormals();
+ }
+ }
+ else if (G.obpose){
+ bAction *act;
+ bPose *pose;
+ bPoseChannel *pchan;
+
+ if (U.flag & (0x01<<14) && !canceled){
+ act=G.obpose->action;
+ pose=G.obpose->pose;
+
+ if (!act)
+ act=G.obpose->action=add_empty_action();
+
+ collect_pose_garbage(G.obpose);
+ filter_pose_keys ();
+ for (pchan=pose->chanbase.first; pchan; pchan=pchan->next){
+ if (pchan->flag & POSE_KEY){
+ if (keyflags & KEYFLAG_ROT){
+ set_action_key(act, pchan, AC_QUAT_X, 1);
+ set_action_key(act, pchan, AC_QUAT_Y, 1);
+ set_action_key(act, pchan, AC_QUAT_Z, 1);
+ set_action_key(act, pchan, AC_QUAT_W, 1);
+ }
+ if (keyflags & KEYFLAG_SIZE){
+ set_action_key(act, pchan, AC_SIZE_X, 1);
+ set_action_key(act, pchan, AC_SIZE_Y, 1);
+ set_action_key(act, pchan, AC_SIZE_Z, 1);
+ }
+ if (keyflags & KEYFLAG_LOC){
+ set_action_key(act, pchan, AC_LOC_X, 1);
+ set_action_key(act, pchan, AC_LOC_Y, 1);
+ set_action_key(act, pchan, AC_LOC_Z, 1);
+ }
+ }
+ }
+
+
+ remake_action_ipos (act);
+ allspace(REMAKEIPO, 0);
+ allqueue(REDRAWACTION, 0);
+ allqueue(REDRAWIPO, 0);
+ allqueue(REDRAWNLA, 0);
+ }
+ }
+ else {
+ base= FIRSTBASE;
+ while(base) {
+
+ ob= base->object;
+
+ if(base->flag & BA_WHERE_UPDATE) {
+
+ where_is_object(ob);
+
+ if(ob->type==OB_IKA) {
+ ika= ob->data;
+ /* vooral voor ika NIET in GRABEFF mode, updaten van globale effector */
+ VecMat4MulVecfl(ika->effg, ob->obmat, ika->eff);
+ itterate_ika(ob);
+ }
+ }
+ if(base->flag & BA_DISP_UPDATE) {
+ if(ob->type==OB_MBALL) {
+ mb= ob->data;
+ if(mb->flag != MB_UPDATE_ALWAYS) makeDispList(ob);
+ }
+ if( give_parteff(ob) ) build_particle_system(ob);
+ }
+ if(base->flag & BA_DO_IPO) redrawipo= 1;
+
+ if(mode=='s' && ob->type==OB_FONT) {
+ doit= 0;
+ cu= ob->data;
+
+ if(cu->bevobj && (cu->bevobj->flag & SELECT) ) doit= 1;
+ else if(cu->textoncurve) {
+ if(cu->textoncurve->flag & SELECT) doit= 1;
+ else if(ob->flag & SELECT) doit= 1;
+ }
+
+ if(doit) {
+ text_to_curve(ob, 0);
+ makeDispList(ob);
+ }
+ }
+ if(mode=='s' && ob->type==OB_CURVE) {
+ doit= 0;
+ cu= ob->data;
+
+ if(cu->bevobj && (cu->bevobj->flag & SELECT) )
+ makeDispList(ob);
+ }
+
+ where_is_object(ob); /* altijd ivm track eytc */
+
+ /* Set autokey if necessary */
+ if ((U.flag & (0x01<<15)) && (!canceled) && (base->flag & SELECT)){
+ if (keyflags & KEYFLAG_ROT){
+ insertkey(&base->object->id, OB_ROT_X);
+ insertkey(&base->object->id, OB_ROT_Y);
+ insertkey(&base->object->id, OB_ROT_Z);
+ }
+ if (keyflags & KEYFLAG_LOC){
+ insertkey(&base->object->id, OB_LOC_X);
+ insertkey(&base->object->id, OB_LOC_Y);
+ insertkey(&base->object->id, OB_LOC_Z);
+ }
+ if (keyflags & KEYFLAG_SIZE){
+ insertkey(&base->object->id, OB_SIZE_X);
+ insertkey(&base->object->id, OB_SIZE_Y);
+ insertkey(&base->object->id, OB_SIZE_Z);
+ }
+
+ remake_object_ipos (ob);
+ allqueue(REDRAWIPO, 0);
+ allspace(REMAKEIPO, 0);
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWNLA, 0);
+ }
+
+ base= base->next;
+ }
+
+ }
+
+ if(redrawipo) {
+ allqueue(REDRAWNLA, 0);
+ allqueue(REDRAWACTION, 0);
+ allqueue(REDRAWIPO, 0);
+ }
+
+ if(G.vd->drawtype == OB_SHADED) reshadeall_displist();
+
+}
+
+
+
+void calc_trans_verts(void)
+{
+ if (ELEM(G.obedit->type, OB_MESH, OB_MBALL))
+ makeDispList(G.obedit);
+ else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
+ Nurb *nu= editNurb.first;
+ while(nu) {
+ test2DNurb(nu);
+ testhandlesNurb(nu); /* test ook op bezier */
+ nu= nu->next;
+ }
+ makeDispList(G.obedit);
+ }
+}
+
+
+static int test_midtog_proj(short xn, short yn, short *mval)
+{
+ float x,y,z;
+
+ /* welke beweging is het grootst? die wordt het */
+ xn= (xn-mval[0]);
+ yn= (yn-mval[1]);
+ x = fabs(G.vd->persinv[0][0]*xn + G.vd->persinv[1][0]*yn);
+ y = fabs(G.vd->persinv[0][1]*xn + G.vd->persinv[1][1]*yn);
+ z = fabs(G.vd->persinv[0][2]*xn + G.vd->persinv[1][2]*yn);
+
+ if(x>=y && x>=z) return 0;
+ else if(y>=x && y>=z) return 1;
+ else return 2;
+}
+
+void apply_keyb_grid(float *val, float fac1, float fac2, float fac3, int invert)
+{
+ /* fac1 is voor 'niets', fac2 voor CTRL fac3 voor SHIFT */
+ int ctrl;
+
+ if(invert) {
+ if(G.qual & LR_CTRLKEY) ctrl= 0;
+ else ctrl= 1;
+ }
+ else ctrl= (G.qual & LR_CTRLKEY);
+
+ if(ctrl && (G.qual & LR_SHIFTKEY)) {
+ if(fac3!= 0.0) *val= fac3*floor(*val/fac3 +.5);
+ }
+ else if(ctrl) {
+ if(fac2!= 0.0) *val= fac2*floor(*val/fac2 +.5);
+ }
+ else {
+ if(fac1!= 0.0) *val= fac1*floor(*val/fac1 +.5);
+ }
+
+}
+
+
+void compatible_eul(float *eul, float *oldrot)
+{
+ float dx, dy, dz;
+
+ /* verschillen van ong 360 graden eerst corrigeren */
+
+ dx= eul[0] - oldrot[0];
+ dy= eul[1] - oldrot[1];
+ dz= eul[2] - oldrot[2];
+
+/* printf("komt binnen: \n"); */
+/* PRINT3(f, f, f, eul[0], eul[1], eul[2]); */
+/* PRINT3(f, f, f, dx, dy, dz); */
+
+ while( fabs(dx) > 5.1) {
+ if(dx > 0.0) eul[0] -= 2.0*M_PI; else eul[0]+= 2.0*M_PI;
+ dx= eul[0] - oldrot[0];
+ }
+ while( fabs(dy) > 5.1) {
+ if(dy > 0.0) eul[1] -= 2.0*M_PI; else eul[1]+= 2.0*M_PI;
+ dy= eul[1] - oldrot[1];
+ }
+ while( fabs(dz) > 5.1 ) {
+ if(dz > 0.0) eul[2] -= 2.0*M_PI; else eul[2]+= 2.0*M_PI;
+ dz= eul[2] - oldrot[2];
+ }
+
+/* PRINT3(f, f, f, oldrot[0], oldrot[1], oldrot[2]); */
+
+
+ /* is 1 van de asrotaties groter dan 180 graden en de andere klein? GEEN ELSEIF!! */
+ if( fabs(dx) > 3.2 && fabs(dy)<1.6 && fabs(dz)<1.6 ) {
+ if(dx > 0.0) eul[0] -= 2.0*M_PI; else eul[0]+= 2.0*M_PI;
+ }
+ if( fabs(dy) > 3.2 && fabs(dz)<1.6 && fabs(dx)<1.6 ) {
+ if(dy > 0.0) eul[1] -= 2.0*M_PI; else eul[1]+= 2.0*M_PI;
+ }
+ if( fabs(dz) > 3.2 && fabs(dx)<1.6 && fabs(dy)<1.6 ) {
+ if(dz > 0.0) eul[2] -= 2.0*M_PI; else eul[2]+= 2.0*M_PI;
+ }
+
+return;
+ /* opnieuw berekenen */
+ dx= eul[0] - oldrot[0];
+ dy= eul[1] - oldrot[1];
+ dz= eul[2] - oldrot[2];
+
+ /* dit is een bijzonder geval, voor x-z getest */
+
+ if( (fabs(dx) > 3.1 && fabs(dz) > 1.5 ) || ( fabs(dx) > 1.5 && fabs(dz) > 3.1 ) ) {
+ if(dx > 0.0) eul[0] -= M_PI; else eul[0]+= M_PI;
+ if(eul[1] > 0.0) eul[1]= M_PI - eul[1]; else eul[1]= -M_PI - eul[1];
+ if(dz > 0.0) eul[2] -= M_PI; else eul[2]+= M_PI;
+
+ }
+ else if( (fabs(dx) > 3.1 && fabs(dy) > 1.5 ) || ( fabs(dx) > 1.5 && fabs(dy) > 3.1 ) ) {
+ if(dx > 0.0) eul[0] -= M_PI; else eul[0]+= M_PI;
+ if(dy > 0.0) eul[1] -= M_PI; else eul[1]+= M_PI;
+ if(eul[2] > 0.0) eul[2]= M_PI - eul[2]; else eul[2]= -M_PI - eul[2];
+ }
+ else if( (fabs(dy) > 3.1 && fabs(dz) > 1.5 ) || ( fabs(dy) > 1.5 && fabs(dz) > 3.1 ) ) {
+ if(eul[0] > 0.0) eul[0]= M_PI - eul[0]; else eul[0]= -M_PI - eul[0];
+ if(dy > 0.0) eul[1] -= M_PI; else eul[1]+= M_PI;
+ if(dz > 0.0) eul[2] -= M_PI; else eul[2]+= M_PI;
+ }
+
+/* PRINT3(f, f, f, eul[0], eul[1], eul[2]); */
+/* printf("\n"); */
+}
+
+void headerprint(char *str)
+{
+ areawinset(curarea->headwin);
+
+ headerbox(0xA09090, curarea->winx);
+ cpack(0x0);
+ glRasterPos2i(20+curarea->headbutofs, 6);
+ BMF_DrawString(G.font, str);
+
+ curarea->head_swap= WIN_BACK_OK;
+ areawinset(curarea->win);
+}
+
+void add_ipo_tob_poin(float *poin, float *old, float delta)
+{
+ if(poin) {
+ poin[0]= old[0]+delta;
+ poin[-3]= old[3]+delta;
+ poin[3]= old[6]+delta;
+ }
+}
+
+void restore_tob(TransOb *tob)
+{
+
+ if(tob->flag & TOB_IPO) {
+ add_ipo_tob_poin(tob->locx, tob->oldloc, 0.0);
+ add_ipo_tob_poin(tob->locy, tob->oldloc+1, 0.0);
+ add_ipo_tob_poin(tob->locz, tob->oldloc+2, 0.0);
+/* QUAT! */
+ add_ipo_tob_poin(tob->rotx, tob->oldrot+3, 0.0);
+ add_ipo_tob_poin(tob->roty, tob->oldrot+4, 0.0);
+ add_ipo_tob_poin(tob->rotz, tob->oldrot+5, 0.0);
+
+ add_ipo_tob_poin(tob->sizex, tob->oldsize, 0.0);
+ add_ipo_tob_poin(tob->sizey, tob->oldsize+1, 0.0);
+ add_ipo_tob_poin(tob->sizez, tob->oldsize+2, 0.0);
+
+ }
+ else {
+ if(tob->eff) VECCOPY(tob->eff, tob->oldeff);
+ if(tob->loc) VECCOPY(tob->loc, tob->oldloc);
+ if(tob->rot) VECCOPY(tob->rot, tob->oldrot);
+
+ QUATCOPY(tob->quat, tob->oldquat);
+ VECCOPY(tob->size, tob->oldsize);
+ }
+}
+
+int cylinder_intersect_test(void)
+{
+ extern float editbutsize;
+ float *oldloc, speed[3], s, t, labda, labdacor, dist, len, len2, axis[3], *base, rc[3], n[3], o[3];
+ EditVert *v1;
+
+ v1= G.edve.first;
+
+ base= v1->co;
+ v1= v1->next;
+ VecSubf(axis, v1->co, base);
+
+ v1= v1->next;
+ oldloc= v1->co;
+ v1= v1->next;
+ VecSubf(speed, v1->co, oldloc);
+
+ VecSubf(rc, oldloc, base);
+
+ /* als we nou speed normaliseren (kan van te voren! */
+
+ /* en de axis ook alvast */
+ len2= Normalise(axis);
+
+ Crossf(n, speed, axis);
+ len= Normalise(n);
+ if(len==0.0) return 0;
+
+ dist= fabs( rc[0]*n[0] + rc[1]*n[1] + rc[2]*n[2] );
+
+ if( dist>=editbutsize ) return 0;
+
+ Crossf(o, rc, axis);
+ t= -(o[0]*n[0] + o[1]*n[1] + o[2]*n[2])/len;
+
+ Crossf(o, n, axis);
+ s= fabs(sqrt(editbutsize*editbutsize-dist*dist) / (o[0]*speed[0] + o[1]*speed[1] + o[2]*speed[2]));
+
+ labdacor= t-s;
+ labda= t+s;
+
+ /* twee gevallen waarbij geen snijpunt is */
+ if(labdacor>=1.0 && labda>=1.0) return 0;
+ if(labdacor<=0.0 && labda<=0.0) return 0;
+
+ /* normaalvector berekenen */
+ /* snijpunt: */
+
+ rc[0]= oldloc[0] + labdacor*speed[0] - base[0];
+ rc[1]= oldloc[1] + labdacor*speed[1] - base[1];
+ rc[2]= oldloc[2] + labdacor*speed[2] - base[2];
+
+ s= (rc[0]*axis[0] + rc[1]*axis[1] + rc[2]*axis[2]) ;
+
+ if(s<0.0 || s>len2) return 0;
+
+ n[0]= (rc[0] - s*axis[0]);
+ n[1]= (rc[1] - s*axis[1]);
+ n[2]= (rc[2] - s*axis[2]);
+
+ printf("var1: %f, var2: %f, var3: %f\n", labdacor, len2, s);
+ printf("var1: %f, var2: %f, var3: %f\n", rc[0], rc[1], rc[2]);
+ printf("var1: %f, var2: %f, var3: %f\n", n[0], n[1], n[2]);
+
+ return 1;
+}
+
+int sphere_intersect_test(void)
+{
+ extern float editbutsize;
+ float *oldloc, speed[3], labda, labdacor, len, bsq, u, disc, *base, rc[3];
+ EditVert *v1;
+
+ v1= G.edve.first;
+ base= v1->co;
+
+ v1= v1->next;
+ oldloc= v1->co;
+
+ v1= v1->next;
+ VecSubf(speed, v1->co, oldloc);
+ len= Normalise(speed);
+ if(len==0.0) return 0;
+
+ VecSubf(rc, oldloc, base);
+ bsq= rc[0]*speed[0] + rc[1]*speed[1] + rc[2]*speed[2];
+ u= rc[0]*rc[0] + rc[1]*rc[1] + rc[2]*rc[2] - editbutsize*editbutsize;
+
+ disc= bsq*bsq - u;
+
+ if(disc>=0.0) {
+ disc= sqrt(disc);
+ labdacor= (-bsq - disc)/len; /* intrede */
+ labda= (-bsq + disc)/len;
+
+ printf("var1: %f, var2: %f, var3: %f\n", labdacor, labda, editbutsize);
+ }
+ else return 0;
+
+ /* snijpunt en normaal */
+ rc[0]= oldloc[0] + labdacor*speed[0] - base[0];
+ rc[1]= oldloc[1] + labdacor*speed[1] - base[1];
+ rc[2]= oldloc[2] + labdacor*speed[2] - base[2];
+
+
+ return 1;
+}
+
+#ifndef CLOCKS_PER_SEC
+#define CLOCKS_PER_SEC 1000000
+#endif
+
+int my_clock(void)
+{
+ float ftime;
+
+ ftime= (float)clock();
+ ftime*= 100.0/CLOCKS_PER_SEC;
+
+ return (int)ftime;
+}
+
+#define XROT 0x01
+#define YROT 0x02
+#define ZROT 0x04
+#define ROTLOCAL 0x80
+#define XROTLOCAL (XROT|ROTLOCAL)
+#define YROTLOCAL (YROT|ROTLOCAL)
+#define ZROTLOCAL (ZROT|ROTLOCAL)
+
+void transform(int mode) /* 'g' 'G' 'r' 'R' 's' 'S' 't' or 'w' 'N' */
+{
+ short canceled = 0;
+ TransOb *tob;
+ TransVert *tv;
+ float vec[3], min[3], max[3], dvec[3], d_dvec[3], dvecp[3], rot0[3], rot1[3], rot2[3], axis[3];
+ float totmat[3][3], omat[3][3], imat[3][3], mat[3][3], tmat[3][3], phi, dphi;
+
+ float persinv[3][3], persmat[3][3], viewinv[4][4], imat4[4][4];
+ float *curs, dx1, dx2, dy1, dy2, eul[3], quat[4], rot[3], phi0, phi1, deler, rad = 0.0;
+ float sizefac, size[3], sizelo[3], smat[3][3], xref=1.0, yref=1.0, zref= 1.0;
+ float si, co, dist, startomtrekfac = 0.0, omtrekfac, oldval[3];
+ int rotmode=0, time, fast=0, a, midtog=0, firsttime=1, proj= 0, fout= 0, cameragrab= 0, gridflag;
+ unsigned short event=0;
+ short mval[2], afbreek=0, doit, xn, yn, xc, yc, xo, yo = 0, val;
+ char str[100];
+ int keyflags = 0;
+
+ if(G.obedit && (G.f & G_PROPORTIONAL)) {
+ if(mode=='g') mode= 'G';
+ if(mode=='r') mode= 'R';
+ if(mode=='s') mode= 'C';
+ }
+ /* form duplicate routines */
+ if(mode=='d') mode= 'g';
+
+ /* kan floating exception veroorzaken op alpha */
+ d_dvec[0]= d_dvec[1]= d_dvec[2]= 0.0;
+ dvec[0]= dvec[1]= dvec[2]= 0.0;
+
+ if(G.scene->id.lib) return;
+
+ if(mode=='t') {
+ if(G.obedit==0 || G.obedit->type!=OB_CURVE) return;
+ }
+ if(mode=='w' && G.obedit==0) return;
+
+ /* welke data wordt behandeld? */
+ if(G.obedit) {
+ if(mode=='N') vertexnormals(0);
+
+ /* min en max zijn nodig voor de warp */
+ if(mode=='G' || mode=='R' || mode=='C') make_trans_verts(min, max, 1);
+ else make_trans_verts(min, max, 0);
+ }
+ else if (G.obpose){
+
+ switch (G.obpose->type) {
+ case OB_ARMATURE:
+ make_trans_bones(mode);
+ break;
+ }
+ }
+ else {
+ int opt= 0;
+ if (mode=='g' || mode=='G') opt= 'g';
+ else if (mode=='r' || mode=='R') opt= 'r';
+ else if (mode=='s' || mode=='S') opt= 's';
+
+ setbaseflags_for_editing(opt);
+
+ make_trans_objects();
+ }
+
+ if(tottrans==0) {
+ if(G.obedit==0) clearbaseflags_for_editing();
+ return;
+ }
+
+ if(G.obedit==0 && mode=='S') return;
+
+ if(G.vd->around==V3D_LOCAL) {
+ if(G.obedit) {
+ centre[0]= centre[1]= centre[2]= 0.0;
+ }
+
+ }
+ if(G.vd->around==V3D_CENTROID) {
+ VECCOPY(centre, centroid);
+ }
+ else if(G.vd->around==V3D_CURSOR) {
+ curs= give_cursor();
+ VECCOPY(centre, curs);
+
+ if(G.obedit) {
+ VecSubf(centre, centre, G.obedit->obmat[3]);
+ Mat3CpyMat4(mat, G.obedit->obmat);
+ Mat3Inv(imat, mat);
+ Mat3MulVecfl(imat, centre);
+ }
+
+ }
+
+ /* Always rotate around object centroid */
+ if (G.obpose){
+ VECCOPY (centre, centroid);
+ }
+
+ /* moving: onderscheid i.v.m. drawobj */
+ if(G.obedit) G.moving= 2;
+ else G.moving= 1;
+
+ areawinset(curarea->win);
+
+ /* de persinv is vervuild met translatie, niet gebruiken!! */
+ Mat3CpyMat4(persmat, G.vd->persmat);
+ Mat3Inv(persinv, persmat);
+
+ VECCOPY(rot0, persinv[0]);
+ Normalise(rot0);
+ VECCOPY(rot1, persinv[1]);
+ Normalise(rot1);
+ VECCOPY(rot2, persinv[2]);
+ Normalise(rot2);
+
+ /* init vars */
+
+ Mat4Invert(viewinv, G.vd->viewmat);
+
+ if(transvmain) {
+ VECCOPY(vec, centre);
+ Mat4MulVecfl(G.obedit->obmat, vec);
+ initgrabz(vec[0], vec[1], vec[2]);
+ project_short_noclip(vec, mval);
+ }
+ else {
+ /* voor pannen vanuit cameraview */
+ if( G.vd->camera==OBACT && G.vd->persp>1) {
+ /* 6.0 = 6 grideenheden */
+ centre[0]+= -6.0*rot2[0];
+ centre[1]+= -6.0*rot2[1];
+ centre[2]+= -6.0*rot2[2];
+ }
+
+ initgrabz(centre[0], centre[1], centre[2]);
+ project_short_noclip(centre, mval);
+
+ if( G.vd->camera==OBACT && G.vd->persp>1) {
+ centre[0]+= 6.0*rot2[0];
+ centre[1]+= 6.0*rot2[1];
+ centre[2]+= 6.0*rot2[2];
+ }
+ }
+
+ VECCOPY(prop_cent, centre);
+
+ xc= mval[0];
+ yc= mval[1];
+
+ if(G.obedit) {
+ Mat3CpyMat4(omat, G.obedit->obmat);
+ Mat3Inv(imat, omat);
+
+ Mat4Invert(imat4, G.obedit->obmat);
+ }
+
+ else if(G.obpose) {
+ Mat3CpyMat4(omat, G.obpose->obmat);
+ Mat3Inv(imat, omat);
+
+ Mat4Invert(imat4, G.obpose->obmat);
+ }
+
+ else {
+ if(transmain) {
+ if(OBACT && G.vd->persp>1 && G.vd->camera==OBACT) {
+ cameragrab= 1;
+ xc= curarea->winx/2;
+ yc= curarea->winy/2;
+ }
+ }
+ }
+
+ if((mode=='r' || mode=='s' || mode=='S') && xc==32000) {
+ error("centre far out of view");
+ fout= 1;
+ }
+
+ if(mode=='w' && G.obedit) {
+ Mat4MulVecfl(G.obedit->obmat, min);
+ Mat4MulVecfl(G.vd->viewmat, min);
+ Mat4MulVecfl(G.obedit->obmat, max);
+ Mat4MulVecfl(G.vd->viewmat, max);
+
+ centre[0]= (min[0]+max[0])/2.0;
+ centre[1]= (min[1]+max[1])/2.0;
+ centre[2]= (min[2]+max[2])/2.0;
+
+ /* middelpunt is cursor */
+ curs= give_cursor();
+ VECCOPY(axis, curs);
+ Mat4MulVecfl(G.vd->viewmat, axis);
+ rad= sqrt( (axis[0]-centre[0])*(axis[0]-centre[0])+(axis[1]-centre[1])*(axis[1]-centre[1]) );
+ dist= max[0]-centre[0];
+ if(dist==0.0) fout= 1;
+ else startomtrekfac= (90*rad*M_PI)/(360.0*dist);
+ }
+
+ getmouseco_areawin(mval);
+ xn=xo= mval[0];
+ yn=xo= mval[1];
+ dx1= xc-xn;
+ dy1= yc-yn;
+ phi= phi0= phi1= 0.0;
+
+ sizefac= sqrt( (float)((yc-yn)*(yc-yn)+(xn-xc)*(xn-xc)) );
+ if(sizefac<2.0) sizefac= 2.0;
+
+ gridflag= U.flag;
+
+ while(fout==0 && afbreek==0) {
+
+ getmouseco_areawin(mval);
+ if(mval[0]!=xo || mval[1]!=yo || firsttime) {
+ if(firsttime) {
+
+ /* niet zo netjes, maar toch! */
+ oldval[0]= oldval[1]= oldval[2]= MAXFLOAT;
+
+ /* proportional precalc */
+ if(mode=='G' || mode=='R' || mode=='C') {
+ if(transvmain) {
+ tv= transvmain;
+ for(a=0; a<tottrans; a++, tv++) {
+ set_proportional_weight(tv, min, max);
+ }
+ }
+ }
+ }
+ firsttime= 0;
+
+ if(mode=='g' || mode=='G') {
+
+ keyflags |= KEYFLAG_LOC;
+ /* if(G.edve.first) sphere_intersect_test(); */
+
+ if(midtog) {
+ if(cameragrab) {
+ dx1= 0.002*(mval[1]-yn)*G.vd->grid;
+ dvec[0]-= dx1*G.vd->viewinv[2][0];
+ dvec[1]-= dx1*G.vd->viewinv[2][1];
+ dvec[2]-= dx1*G.vd->viewinv[2][2];
+ firsttime= 1; /* blijftie lopen */
+ }
+ else {
+ window_to_3d(dvec, mval[0]-xn, mval[1]-yn);
+ if(proj==0) dvec[1]=dvec[2]= 0.0;
+ if(proj==1) dvec[0]=dvec[2]= 0.0;
+ if(proj==2) dvec[0]=dvec[1]= 0.0;
+ }
+ }
+ else window_to_3d(dvec, mval[0]-xn, mval[1]-yn);
+
+ /* grids */
+ if(G.qual & LR_SHIFTKEY) {
+ dvec[0]= 0.1*(dvec[0]-d_dvec[0])+d_dvec[0];
+ dvec[1]= 0.1*(dvec[1]-d_dvec[1])+d_dvec[1];
+ dvec[2]= 0.1*(dvec[2]-d_dvec[2])+d_dvec[2];
+ }
+ apply_keyb_grid(dvec, 0.0, G.vd->grid, 0.1*G.vd->grid, gridflag & AUTOGRABGRID);
+ apply_keyb_grid(dvec+1, 0.0, G.vd->grid, 0.1*G.vd->grid, gridflag & AUTOGRABGRID);
+ apply_keyb_grid(dvec+2, 0.0, G.vd->grid, 0.1*G.vd->grid, gridflag & AUTOGRABGRID);
+
+ if(dvec[0]!=oldval[0] ||dvec[1]!=oldval[1] ||dvec[2]!=oldval[2]) {
+ VECCOPY(oldval, dvec);
+
+ /* speedup for vertices */
+ if (G.obedit) {
+ VECCOPY(dvecp, dvec);
+ Mat3MulVecfl(imat, dvecp);
+ }
+
+
+ /* apply */
+ tob= transmain;
+ tv= transvmain;
+ for(a=0; a<tottrans; a++, tob++, tv++) {
+
+ if(transmain) {
+ VECCOPY(dvecp, dvec);
+
+ if(transmode==TRANS_TEX) Mat3MulVecfl(tob->obinv, dvecp);
+
+ if(tob->flag & TOB_IKA) {
+ VecAddf(tob->eff, tob->oldeff, dvecp);
+ }
+ else
+ Mat3MulVecfl(tob->parinv, dvecp);
+
+ if(tob->flag & TOB_IPO) {
+ add_ipo_tob_poin(tob->locx, tob->oldloc, dvecp[0]);
+ add_ipo_tob_poin(tob->locy, tob->oldloc+1, dvecp[1]);
+ add_ipo_tob_poin(tob->locz, tob->oldloc+2, dvecp[2]);
+ }
+ else if(tob->loc) {
+ VecAddf(tob->loc, tob->oldloc, dvecp);
+ }
+ }
+ else {
+ if(mode=='G') {
+ tv->loc[0]= tv->oldloc[0]+tv->fac*dvecp[0];
+ tv->loc[1]= tv->oldloc[1]+tv->fac*dvecp[1];
+ tv->loc[2]= tv->oldloc[2]+tv->fac*dvecp[2];
+ }
+ else VecAddf(tv->loc, tv->oldloc, dvecp);
+ }
+
+ }
+ sprintf(str, "Dx: %.4f Dy: %.4f Dz: %.4f", dvec[0], dvec[1], dvec[2]);
+ headerprint(str);
+
+ time= my_clock();
+
+ if(G.obedit) calc_trans_verts();
+ special_trans_update(keyflags);
+
+ if(fast==0) {
+ force_draw();
+ time= my_clock()-time;
+ if(time>50) fast= 1;
+ }
+ else {
+ scrarea_do_windraw(curarea);
+ screen_swapbuffers();
+ }
+ }
+ }
+ else if(mode=='r' || mode=='t' || mode=='R') {
+ doit= 0;
+ keyflags |= KEYFLAG_ROT;
+ dx2= xc-mval[0];
+ dy2= yc-mval[1];
+
+ if(midtog && (mode=='r' || mode=='R')) {
+ phi0+= .007*(float)(dy2-dy1);
+ phi1+= .007*(float)(dx1-dx2);
+
+ apply_keyb_grid(&phi0, 0.0, (5.0/180)*M_PI, (1.0/180)*M_PI, gridflag & AUTOROTGRID);
+ apply_keyb_grid(&phi1, 0.0, (5.0/180)*M_PI, (1.0/180)*M_PI, gridflag & AUTOROTGRID);
+
+
+ if(oldval[0]!=phi0 || oldval[1]!=phi1) {
+ VecRotToMat3(rot0, phi0, smat);
+ VecRotToMat3(rot1, phi1, totmat);
+
+ Mat3MulMat3(mat, smat, totmat);
+ dx1= dx2;
+ dy1= dy2;
+ oldval[0]= phi0;
+ oldval[1]= phi1;
+ doit= 1;
+ }
+ }
+ else {
+ deler= sqrt( (dx1*dx1+dy1*dy1)*(dx2*dx2+dy2*dy2));
+ if(deler>1.0) {
+
+ dphi= (dx1*dx2+dy1*dy2)/deler;
+ dphi= saacos(dphi);
+ if( (dx1*dy2-dx2*dy1)>0.0 ) dphi= -dphi;
+
+ if(G.qual & LR_SHIFTKEY) phi+= dphi/30.0;
+ else phi+= dphi;
+
+ apply_keyb_grid(&phi, 0.0, (5.0/180)*M_PI, (1.0/180)*M_PI, gridflag & AUTOROTGRID);
+
+ if(oldval[2]!=phi) {
+ dx1= dx2;
+ dy1= dy2;
+ oldval[2]= phi;
+ doit= 1;
+ if(rotmode) {
+
+ if(rotmode==XROT) vec[0]= -1.0; else vec[0]= 0.0;
+ if(rotmode==YROT) vec[1]= 1.0; else vec[1]= 0.0;
+ if(rotmode==ZROT) vec[2]= -1.0; else vec[2]= 0.0;
+
+ VecRotToMat3(vec, phi, mat);
+ }
+ else VecRotToMat3(rot2, phi, mat);
+ }
+ }
+
+ }
+ if(doit) {
+ /* apply */
+ tob= transmain;
+ tv= transvmain;
+
+ for(a=0; a<tottrans; a++, tob++, tv++) {
+ if(transmain) {
+ /* rotatie in drie stappen:
+ * 1. editrot corrigeren voor parent
+ * 2. hier de euler uit destilleren. Deze stap moet omdat de MatToEul nogal zwak is
+ * 3. deze vermenigvuldigen met eigen rot, euler berekenen.
+ */
+
+ /* Roll around local axis */
+ if (mode=='r' || mode=='R'){
+ if (tob && rotmode){
+ if (rotmode == XROTLOCAL){
+ VECCOPY(vec, tob->axismat[0]);
+ }
+ if (rotmode == YROTLOCAL){
+ VECCOPY(vec, tob->axismat[1]);
+ }
+ if (rotmode == ZROTLOCAL){
+ VECCOPY(vec, tob->axismat[2]);
+ }
+
+ /* Correct the vector */
+ if ((rotmode & ROTLOCAL) && ((G.vd->viewmat[0][2] * vec[0]+G.vd->viewmat[1][2] * vec[1]+G.vd->viewmat[2][2] * vec[2])>0)){
+ vec[0]*=-1;
+ vec[1]*=-1;
+ vec[2]*=-1;
+ }
+
+ VecRotToMat3(vec, phi, mat);
+ }
+ }
+ Mat3MulSerie(smat, tob->parmat, mat, tob->parinv, 0, 0, 0, 0, 0);
+
+ /* 2 */
+ if( (tob->ob->transflag & OB_QUAT) == 0 && tob->rot){
+ Mat3ToEul(smat, eul);
+ EulToMat3(eul, smat);
+ }
+
+ /* 3 */
+ /* we werken even met de rot+drot */
+
+ if(tob->ob->transflag & OB_QUAT || !tob->rot)
+ {
+ /* drot+rot NOG DOEN! */
+ Mat3ToQuat(smat, quat); // Original
+ QuatMul(tob->quat, quat, tob->oldquat);
+
+ if(tob->flag & TOB_IPO) {
+
+ if(tob->flag & TOB_IPODROT) {
+ /* VecSubf(rot, eul, tob->oldrot); */
+ }
+ else {
+ /* VecSubf(rot, eul, tob->olddrot); */
+// VecSubf(rot, eul, tob->olddrot);
+ }
+
+ /* VecMulf(rot, 9.0/M_PI_2); */
+ /* VecSubf(rot, rot, tob->oldrot+3); */
+
+ /* add_ipo_tob_poin(tob->rotx, tob->oldrot+3, rot[0]); */
+ /* add_ipo_tob_poin(tob->roty, tob->oldrot+4, rot[1]); */
+ /* add_ipo_tob_poin(tob->rotz, tob->oldrot+5, rot[2]); */
+
+ }
+ else {
+ /* QuatSub(tob->quat, quat, tob->oldquat); */
+// QuatSub(tob->quat, quat, tob->oldquat);
+ }
+ }
+ else {
+ VecAddf(eul, tob->oldrot, tob->olddrot);
+ EulToMat3(eul, tmat);
+
+ Mat3MulMat3(totmat, smat, tmat);
+
+ Mat3ToEul(totmat, eul);
+
+ /* Eul mag niet te gek afwijken van oude eul.
+ * Dit is alleen nog maar getest voor dx && dz
+ */
+
+ compatible_eul(eul, tob->oldrot);
+
+ if(tob->flag & TOB_IPO) {
+
+ if(tob->flag & TOB_IPODROT) {
+ VecSubf(rot, eul, tob->oldrot);
+ }
+ else {
+ VecSubf(rot, eul, tob->olddrot);
+ }
+
+ VecMulf(rot, 9.0/M_PI_2);
+ VecSubf(rot, rot, tob->oldrot+3);
+
+
+ add_ipo_tob_poin(tob->rotx, tob->oldrot+3, rot[0]);
+ add_ipo_tob_poin(tob->roty, tob->oldrot+4, rot[1]);
+ add_ipo_tob_poin(tob->rotz, tob->oldrot+5, rot[2]);
+
+ }
+ else {
+ VecSubf(tob->rot, eul, tob->olddrot);
+ }
+
+ /* See if we've moved */
+ if (!VecCompare (tob->loc, tob->oldloc, 0.01)){
+ keyflags |= KEYFLAG_LOC;
+ }
+
+ }
+
+ if(G.vd->around!=V3D_LOCAL && (!G.obpose)) {
+ /* translatie */
+ VecSubf(vec, tob->obvec, centre);
+ Mat3MulVecfl(mat, vec);
+ VecAddf(vec, vec, centre);
+ /* vec is nu de plek waar het object moet komen */
+ VecSubf(vec, vec, tob->obvec);
+ Mat3MulVecfl(tob->parinv, vec);
+
+ if(tob->flag & TOB_IPO) {
+ add_ipo_tob_poin(tob->locx, tob->oldloc, vec[0]);
+ add_ipo_tob_poin(tob->locy, tob->oldloc+1, vec[1]);
+ add_ipo_tob_poin(tob->locz, tob->oldloc+2, vec[2]);
+ }
+ else if(tob->loc) {
+ VecAddf(tob->loc, tob->oldloc, vec);
+ }
+ }
+ }
+ else {
+ if(mode=='t') {
+ if(tv->val) *(tv->val)= tv->oldval-phi;
+ }
+ else {
+
+ if(mode=='R') {
+
+ if(midtog) {
+ VecRotToMat3(rot0, tv->fac*phi0, smat);
+ VecRotToMat3(rot1, tv->fac*phi1, totmat);
+ Mat3MulMat3(mat, smat, totmat);
+ }
+ else VecRotToMat3(rot2, tv->fac*phi, mat);
+
+ }
+
+ Mat3MulMat3(totmat, mat, omat);
+ Mat3MulMat3(smat, imat, totmat);
+
+ VecSubf(vec, tv->oldloc, centre);
+ Mat3MulVecfl(smat, vec);
+
+ VecAddf(tv->loc, vec, centre);
+ }
+ }
+ }
+
+ if(midtog) sprintf(str, "Rotx: %.2f Roty: %.2f", 180.0*phi0/M_PI, 180.0*phi1/M_PI);
+ else if(rotmode) {
+ if(rotmode==XROT) sprintf(str, "Rot X: %.2f", 180.0*phi/M_PI);
+ else if(rotmode==YROT) sprintf(str, "Rot Y: %.2f", 180.0*phi/M_PI);
+ else if(rotmode==ZROT) sprintf(str, "Rot Z: %.2f", 180.0*phi/M_PI);
+ else if(rotmode==XROTLOCAL) sprintf(str, "Local Rot X: %.2f", 180.0*phi/M_PI);
+ else if(rotmode==YROTLOCAL) sprintf(str, "Local Rot Y: %.2f", 180.0*phi/M_PI);
+ else if(rotmode==ZROTLOCAL) sprintf(str, "Local Rot Z: %.2f", 180.0*phi/M_PI);
+ }
+ else sprintf(str, "Rot: %.2f", 180.0*phi/M_PI);
+ headerprint(str);
+
+ time= my_clock();
+
+ if(G.obedit) calc_trans_verts();
+ special_trans_update(keyflags);
+
+ if(fast==0) {
+ force_draw();
+ time= my_clock()-time;
+ if(time>50) fast= 1;
+ }
+ else {
+ scrarea_do_windraw(curarea);
+ screen_swapbuffers();
+ }
+ if(tottrans>1 || G.vd->around==V3D_CURSOR) helpline(centre);
+ else if (G.obpose) helpline (centre);
+ }
+ }
+ else if(mode=='s' || mode=='S' || mode=='C' || mode=='N') {
+ keyflags |= KEYFLAG_SIZE;
+
+ if(mode=='S') {
+ size[0]= 1.0-(float)(xn-mval[0])*0.005;
+ size[1]= 1.0-(float)(yn-mval[1])*0.005;
+ size[2]= 1.0;
+ }
+ else size[0]=size[1]=size[2]= (sqrt( (float)((yc-mval[1])*(yc-mval[1])+(mval[0]-xc)*(mval[0]-xc)) ))/sizefac;
+
+ if(midtog && mode=='s') {
+ /* shear has no midtog */
+ if(proj==0) size[1]=size[2]= 1.0;
+ if(proj==1) size[0]=size[2]= 1.0;
+ if(proj==2) size[1]=size[0]= 1.0;
+ }
+
+/* X en Y flip, twee methodes: bij |**| commentaar weghalen maakt flips lokaal */
+
+/**/ /* if(transvmain) { */
+
+ /* x flip */
+ val= test_midtog_proj(mval[0]+10, mval[1], mval);
+ size[val]*= xref;
+ /* y flip */
+ val= test_midtog_proj(mval[0], mval[1]+10, mval);
+ size[val]*= yref;
+
+/**/ /* } */
+
+
+ /* grid */
+ apply_keyb_grid(size, 0.0, 0.1, 0.01, gridflag & AUTOSIZEGRID);
+ apply_keyb_grid(size+1, 0.0, 0.1, 0.01, gridflag & AUTOSIZEGRID);
+ apply_keyb_grid(size+2, 0.0, 0.1, 0.01, gridflag & AUTOSIZEGRID);
+
+ if(transmain) {
+ size[0]= MINSIZE(size[0], 0.01);
+ size[1]= MINSIZE(size[1], 0.01);
+ size[2]= MINSIZE(size[2], 0.01);
+ }
+
+ if(size[0]!=oldval[0] ||size[1]!=oldval[1] ||size[2]!=oldval[2]) {
+ VECCOPY(oldval, size);
+
+ SizeToMat3(size, mat);
+
+ /* apply */
+ tob= transmain;
+ tv= transvmain;
+
+ for(a=0; a<tottrans; a++, tob++, tv++) {
+ if(transmain) {
+ /* size moet lokaal t.o.v. ouder EN van eigen rotatie */
+ /* lokaal tov. ouder: */
+
+
+
+ Mat3MulSerie(smat, tob->parmat, mat, tob->parinv, 0, 0,0 ,0, 0);
+
+ /* lokaal tov. eigen rot: */
+ Mat3MulSerie(totmat, tob->obmat, smat, tob->obinv, 0, 0, 0,0 ,0);
+
+ /* XXX this can yield garbage in case of inverted sizes (< 0.0)
+ */
+ if(!midtog) {
+ sizelo[0]= size[0];
+ sizelo[1]= size[1];
+ sizelo[2]= size[2];
+ } else {
+ /* dan klopt de vorige berekening van de juiste size niet meer precies */
+ sizelo[0]= totmat[0][0];
+ sizelo[1]= totmat[1][1];
+ sizelo[2]= totmat[2][2];
+ apply_keyb_grid(sizelo, 0.0, 0.1, 0.01, gridflag & AUTOSIZEGRID);
+ apply_keyb_grid(sizelo+1, 0.0, 0.1, 0.01, gridflag & AUTOSIZEGRID);
+ apply_keyb_grid(sizelo+2, 0.0, 0.1, 0.01, gridflag & AUTOSIZEGRID);
+ }
+
+ /* x flip */
+/**/ /* sizelo[0]*= xref; */
+ /* y flip */
+/**/ /* sizelo[1]*= yref; */
+ /* z flip */
+/**/ /* sizelo[2]*= zref; */
+
+
+ /* what you see is what you want; not what you get! */
+ /* correctie voor delta size */
+ if(tob->flag & TOB_IPO) {
+ /* deltasize berekenen (gelijk voor size en dsize) */
+
+ vec[0]= (tob->oldsize[0]+tob->olddsize[0])*(sizelo[0] -1.0);
+ vec[1]= (tob->oldsize[1]+tob->olddsize[1])*(sizelo[1] -1.0);
+ vec[2]= (tob->oldsize[2]+tob->olddsize[2])*(sizelo[2] -1.0);
+
+ add_ipo_tob_poin(tob->sizex, tob->oldsize+3, vec[0]);
+ add_ipo_tob_poin(tob->sizey, tob->oldsize+4, vec[1]);
+ add_ipo_tob_poin(tob->sizez, tob->oldsize+5, vec[2]);
+
+ }
+ else {
+ tob->size[0]= (tob->oldsize[0]+tob->olddsize[0])*sizelo[0] -tob->olddsize[0];
+ tob->size[1]= (tob->oldsize[1]+tob->olddsize[1])*sizelo[1] -tob->olddsize[1];
+ tob->size[2]= (tob->oldsize[2]+tob->olddsize[2])*sizelo[2] -tob->olddsize[2];
+ }
+
+ if(G.vd->around!=V3D_LOCAL && !G.obpose) {
+ /* translatie */
+ VecSubf(vec, tob->obvec, centre);
+ Mat3MulVecfl(mat, vec);
+ VecAddf(vec, vec, centre);
+ /* vec is nu de plek waar het object moet komen */
+ VecSubf(vec, vec, tob->obvec);
+ Mat3MulVecfl(tob->parinv, vec);
+
+ if(tob->flag & TOB_IPO) {
+ add_ipo_tob_poin(tob->locx, tob->oldloc, vec[0]);
+ add_ipo_tob_poin(tob->locy, tob->oldloc+1, vec[1]);
+ add_ipo_tob_poin(tob->locz, tob->oldloc+2, vec[2]);
+ }
+ else if(tob->loc) {
+ if(transmode==TRANS_TEX) ;
+ else VecAddf(tob->loc, tob->oldloc, vec);
+ }
+ }
+ }
+ else { /* vertices */
+
+ /* for print */
+ VECCOPY(sizelo, size);
+
+ if(mode=='C') {
+ size[0]= tv->fac*size[0]+ 1.0-tv->fac;;
+ size[1]= tv->fac*size[1]+ 1.0-tv->fac;;
+ size[2]= tv->fac*size[2]+ 1.0-tv->fac;;
+ SizeToMat3(size, mat);
+ VECCOPY(size, oldval);
+ }
+
+ if(mode=='S') { /* shear */
+ Mat3One(tmat);
+ tmat[0][0]= tmat[2][2]= tmat[1][1]= 1.0;
+ tmat[1][0]= size[0]-1.0;
+
+ Mat3MulMat3(totmat, persmat, omat);
+ Mat3MulMat3(mat, tmat, totmat);
+ Mat3MulMat3(totmat, persinv, mat);
+ Mat3MulMat3(smat, imat, totmat);
+ }
+ else {
+ Mat3MulMat3(totmat, mat, omat);
+ Mat3MulMat3(smat, imat, totmat);
+ }
+
+ if(mode=='N' && tv->nor!=NULL) {
+ tv->loc[0]= tv->oldloc[0] + (size[0]-1.0)*tv->nor[0];
+ tv->loc[1]= tv->oldloc[1] + (size[1]-1.0)*tv->nor[1];
+ tv->loc[2]= tv->oldloc[2] + (size[2]-1.0)*tv->nor[2];
+ }
+ else {
+ VecSubf(vec, tv->oldloc, centre);
+ Mat3MulVecfl(smat, vec);
+ VecAddf(tv->loc, vec, centre);
+
+ if(G.obedit->type==OB_MBALL) *(tv->val)= size[0]*tv->oldval;
+ }
+ }
+ }
+ if(mode=='s')
+ sprintf(str, "Sizex: %.3f Sizey: %.3f Sizez: %.3f", sizelo[0], sizelo[1], sizelo[2]);
+ else if (mode=='S')
+ sprintf(str, "Shear: %.3f ", sizelo[0]);
+ else if (mode=='C')
+ sprintf(str, "Size: %.3f ", sizelo[0]);
+ else if (mode=='N')
+ sprintf(str, "Shrink/Fatten: %.3f ", size[0]);
+
+ headerprint(str);
+
+ time= my_clock();
+
+ if(G.obedit) calc_trans_verts();
+ special_trans_update(keyflags);
+
+
+ if(fast==0) {
+ force_draw();
+ time= my_clock()-time;
+ if(time>50) fast= 1;
+ }
+ else {
+ scrarea_do_windraw(curarea);
+ screen_swapbuffers();
+ }
+ if(tottrans>1 || G.vd->around==V3D_CURSOR) helpline(centre);
+ }
+ }
+ else if(mode=='w') {
+
+ window_to_3d(dvec, 1, 1);
+
+ omtrekfac= startomtrekfac+ 0.05*( mval[1] - yn)*Normalise(dvec);
+
+ /* berekenen hoek voor print */
+ dist= max[0]-centre[0];
+ phi0= 360*omtrekfac*dist/(rad*M_PI);
+
+ if(G.qual & LR_CTRLKEY) {
+ phi0= 5.0*floor(phi0/5.0);
+ omtrekfac= (phi0*rad*M_PI)/(360.0*dist);
+ }
+
+
+ sprintf(str, "Warp %3.3f", phi0);
+ headerprint(str);
+
+ /* elke vertex moet apart geroteerd */
+ tob= transmain;
+ tv= transvmain;
+
+ for(a=0; a<tottrans; a++, tob++, tv++) {
+ if(transvmain) {
+
+ /* punt transleren naar centre, zodanig roteren dat omtrekafstand==afstand */
+
+ VECCOPY(vec, tv->oldloc);
+ Mat4MulVecfl(G.obedit->obmat, vec);
+ Mat4MulVecfl(G.vd->viewmat, vec);
+
+ dist= vec[0]-centre[0];
+
+ phi0= (omtrekfac*dist/rad) - 0.5*M_PI;
+
+ co= cos(phi0);
+ si= sin(phi0);
+
+ vec[0]= (centre[0]-axis[0]);
+ vec[1]= (vec[1]-axis[1]);
+
+ tv->loc[0]= si*vec[0]+co*vec[1]+axis[0];
+
+ tv->loc[1]= co*vec[0]-si*vec[1]+axis[1];
+ tv->loc[2]= vec[2];
+
+ Mat4MulVecfl(viewinv, tv->loc);
+ Mat4MulVecfl(imat4, tv->loc);
+
+ }
+ }
+
+ if(G.obedit) calc_trans_verts();
+ special_trans_update(keyflags);
+
+ if(fast==0) {
+ time= my_clock();
+ force_draw();
+ time= my_clock()-time;
+ if(time>50) fast= 1;
+ }
+ else {
+ scrarea_do_windraw(curarea);
+ screen_swapbuffers();
+ }
+ }
+ }
+
+ while( qtest() ) {
+ event= extern_qread(&val);
+
+ if(val) {
+ switch(event) {
+ case ESCKEY:
+ case LEFTMOUSE:
+ case RIGHTMOUSE:
+ case SPACEKEY:
+ case RETKEY:
+ afbreek= 1;
+ break;
+ case MIDDLEMOUSE:
+ midtog= ~midtog;
+ if(midtog) {
+ proj= test_midtog_proj(xn, yn, mval);
+ phi0= phi1= 0.0;
+ if(cameragrab) {
+ dvec[0]= dvec[1]= dvec[2]= 0.0;
+ }
+ }
+ firsttime= 1;
+ break;
+ case GKEY:
+ case RKEY:
+ case SKEY:
+ getmouseco_areawin(mval);
+ xn=xo= mval[0];
+ yn=xo= mval[1];
+ dx1= xc-xn;
+ dy1= yc-yn;
+ phi= phi0= phi1= 0.0;
+ sizefac= sqrt( (float)((yc-yn)*(yc-yn)+(xn-xc)*(xn-xc)) );
+ if(sizefac<2.0) sizefac= 2.0;
+
+ if (G.obedit && (G.f & G_PROPORTIONAL)) {
+ if(event==GKEY) mode= 'G';
+ else if(event==RKEY) mode= 'R';
+ else if(event==SKEY) mode= 'C';
+ } else {
+ if(event==GKEY) mode= 'g';
+ else if(event==RKEY) mode= 'r';
+ else if(event==SKEY) mode= 's';
+ }
+
+ firsttime= 1;
+
+ tob= transmain;
+ tv= transvmain;
+ for(a=0; a<tottrans; a++, tob++, tv++) {
+ if(transmain) {
+ restore_tob(tob);
+ }
+ else {
+ VECCOPY(tv->loc, tv->oldloc);
+ }
+ }
+ break;
+
+ case XKEY:
+ if (rotmode==XROT)
+ rotmode=XROTLOCAL;
+ else if (rotmode==XROTLOCAL)
+ rotmode=0;
+ else{
+ xref= -xref;
+ rotmode= XROT;
+ }
+ firsttime=1;
+ break;
+
+ case YKEY:
+ if (rotmode==YROT)
+ rotmode=YROTLOCAL;
+ else if (rotmode==YROTLOCAL)
+ rotmode=0;
+ else{
+ yref= -yref;
+ rotmode= YROT;
+ }
+ firsttime=1;
+ break;
+
+ case ZKEY:
+ if (rotmode==ZROT)
+ rotmode=ZROTLOCAL;
+ else if (rotmode==ZROTLOCAL)
+ rotmode=0;
+ else{
+ zref= -zref;
+ rotmode= ZROT;
+ }
+ firsttime=1;
+ break;
+
+ case PADPLUSKEY:
+ if(G.f & G_PROPORTIONAL) {
+ prop_size*= 1.1;
+ firsttime= 1;
+ }
+ break;
+ case PADMINUS:
+ if(G.f & G_PROPORTIONAL) {
+ prop_size*= 0.90909090;
+ firsttime= 1;
+ }
+ break;
+
+ case LEFTSHIFTKEY:
+ case RIGHTSHIFTKEY:
+ VECCOPY(d_dvec, dvec);
+ case LEFTCTRLKEY:
+ case RIGHTCTRLKEY:
+ firsttime= 1;
+ break;
+ }
+
+ arrows_move_cursor(event);
+ }
+ if(event==0 || afbreek) break;
+
+ }
+ xo= mval[0];
+ yo= mval[1];
+
+ if( qtest()==0) PIL_sleep_ms(1);
+
+ }
+ G.moving= 0;
+
+ if(event==ESCKEY || event==RIGHTMOUSE) {
+ canceled=1;
+ tv= transvmain;
+ tob= transmain;
+ for(a=0; a<tottrans; a++, tob++, tv++) {
+ if(transmain) {
+ restore_tob(tob);
+ }
+ else {
+ VECCOPY(tv->loc, tv->oldloc);
+ if(tv->val) *(tv->val)= tv->oldval;
+ }
+ }
+ if(G.obedit) calc_trans_verts();
+ special_trans_update(keyflags);
+ }
+
+ a= 0;
+ if(xref<0) a++;
+ if(yref<0) a++;
+ if(zref<0) a++;
+ special_aftertrans_update(mode, a & 1, canceled, keyflags);
+
+ allqueue(REDRAWVIEW3D, 0);
+ scrarea_queue_headredraw(curarea);
+
+ clearbaseflags_for_editing();
+
+ if(transmain) MEM_freeN(transmain);
+ transmain= 0;
+ if(transvmain) MEM_freeN(transvmain);
+ transvmain= 0;
+
+ tottrans= 0;
+}
+
+void std_rmouse_transform(void (*xf_func)(int))
+{
+ short mval[2];
+ short xo, yo;
+
+ getmouseco_areawin(mval);
+ xo= mval[0];
+ yo= mval[1];
+
+ while(get_mbut()&R_MOUSE) {
+ getmouseco_areawin(mval);
+ if(abs(mval[0]-xo)+abs(mval[1]-yo) > 10) {
+ xf_func('g');
+ while(get_mbut()&R_MOUSE) BIF_wait_for_statechange();
+ return;
+ }
+
+ BIF_wait_for_statechange();
+ }
+}
+
+void rightmouse_transform(void)
+{
+ std_rmouse_transform(transform);
+}
+
+
+/* ************************************** */
+
+
+void single_object_users(int flag)
+ /* hierna wel clear_id_newpoins() aanroepen */
+{
+ Base *base;
+ Object *ob, *obn;
+
+ clear_sca_new_poins(); /* sensor/contr/act */
+
+ /* dupliceren */
+ base= FIRSTBASE;
+ while(base) {
+ ob= base->object;
+
+ if( (base->flag & flag)==flag) {
+
+ if(ob->id.lib==0 && ob->id.us>1) {
+
+ obn= copy_object(ob);
+ ob->id.us--;
+ base->object= obn;
+ }
+ }
+ base= base->next;
+ }
+
+ ID_NEW(G.scene->camera);
+ if(G.vd) ID_NEW(G.vd->camera);
+
+ /* evt object pointers */
+ base= FIRSTBASE;
+ while(base) {
+ ob= base->object;
+ if(ob->id.lib==0) {
+ if( (base->flag & flag)==flag) {
+
+ ID_NEW(ob->parent);
+ ID_NEW(ob->track);
+
+ }
+ }
+ base= base->next;
+ }
+
+ set_sca_new_poins();
+}
+
+void new_id_matar(Material **matar, int totcol)
+{
+ ID *id;
+ int a;
+
+ for(a=0; a<totcol; a++) {
+ id= (ID *)matar[a];
+ if(id && id->lib==0) {
+ if(id->newid) {
+ matar[a]= (Material *)id->newid;
+ id_us_plus(id->newid);
+ id->us--;
+ }
+ else if(id->us>1) {
+ matar[a]= copy_material(matar[a]);
+ id->us--;
+ id->newid= (ID *)matar[a];
+ }
+ }
+ }
+}
+
+void single_obdata_users(int flag)
+{
+ Object *ob;
+ Lamp *la;
+ Curve *cu;
+ Ika *ika;
+ Deform *def;
+ Base *base;
+ Mesh *me;
+ ID *id;
+ int a;
+
+ base= FIRSTBASE;
+ while(base) {
+ ob= base->object;
+ if(ob->id.lib==0 && (base->flag & flag)==flag ) {
+ id= ob->data;
+
+ if(id && id->us>1 && id->lib==0) {
+
+ switch(ob->type) {
+ case OB_LAMP:
+ if(id && id->us>1 && id->lib==0) {
+ ob->data= la= copy_lamp(ob->data);
+ for(a=0; a<8; a++) {
+ if(la->mtex[a]) {
+ ID_NEW(la->mtex[a]->object);
+ }
+ }
+ }
+ break;
+ case OB_CAMERA:
+ ob->data= copy_camera(ob->data);
+ break;
+ case OB_MESH:
+ ob->data= copy_mesh(ob->data);
+ break;
+ case OB_MBALL:
+ ob->data= copy_mball(ob->data);
+ break;
+ case OB_CURVE:
+ case OB_SURF:
+ case OB_FONT:
+ ob->data= cu= copy_curve(ob->data);
+ ID_NEW(cu->bevobj);
+ makeDispList(ob);
+ break;
+ case OB_LATTICE:
+ ob->data= copy_lattice(ob->data);
+ break;
+ case OB_ARMATURE:
+ ob->data=copy_armature(ob->data);
+ break;
+ case OB_IKA:
+ /* this never occurs? IK is always single user */
+ ob->data= ika= copy_ika(ob->data);
+ ID_NEW(ika->parent);
+
+ if(ika->totdef) {
+ a= ika->totdef;
+ def= ika->def;
+ while(a--) {
+ ID_NEW(def->ob);
+ def++;
+ }
+ }
+
+ break;
+ default:
+ printf("ERROR single_obdata_users: %s\n", id->name);
+ error("Read console");
+ return;
+ }
+
+ id->us--;
+ id->newid= ob->data;
+
+ }
+
+ id= (ID *)ob->action;
+ if (id && id->us>1 && id->lib==0){
+ if(id->newid){
+ ob->action= (bAction *)id->newid;
+ id_us_plus(id->newid);
+ }
+ else {
+ ob->action=copy_action(ob->action);
+ ob->activecon=NULL;
+ id->us--;
+ id->newid=(ID *)ob->action;
+ }
+ }
+ id= (ID *)ob->ipo;
+ if(id && id->us>1 && id->lib==0) {
+ if(id->newid) {
+ ob->ipo= (Ipo *)id->newid;
+ id_us_plus(id->newid);
+ }
+ else {
+ ob->ipo= copy_ipo(ob->ipo);
+ id->us--;
+ id->newid= (ID *)ob->ipo;
+ }
+ }
+ switch(ob->type) {
+ case OB_LAMP:
+ la= ob->data;
+ if(la->ipo && la->ipo->id.us>1) {
+ la->ipo->id.us--;
+ la->ipo= copy_ipo(la->ipo);
+ }
+ }
+
+ }
+ base= base->next;
+ }
+
+ me= G.main->mesh.first;
+ while(me) {
+ ID_NEW(me->texcomesh);
+ me= me->id.next;
+ }
+}
+
+
+void single_mat_users(int flag)
+{
+ Object *ob;
+ Base *base;
+ Material *ma, *man;
+ Tex *tex;
+ int a, b;
+
+
+ base= FIRSTBASE;
+ while(base) {
+ ob= base->object;
+ if(ob->id.lib==0 && (flag==0 || (base->flag & SELECT)) ) {
+
+ for(a=1; a<=ob->totcol; a++) {
+ ma= give_current_material(ob, a);
+ if(ma) {
+ /* hier niet LIB_NEW testen: deze fie geeft gegarandeerde single_users! */
+
+ if(ma->id.us>1) {
+ man= copy_material(ma);
+
+ man->id.us= 0;
+ assign_material(ob, man, a);
+
+ if(ma->ipo) {
+ man->ipo= copy_ipo(ma->ipo);
+ ma->ipo->id.us--;
+ }
+
+ for(b=0; b<8; b++) {
+ if(ma->mtex[b] && ma->mtex[b]->tex) {
+ tex= ma->mtex[b]->tex;
+ if(tex->id.us>1) {
+ ma->mtex[b]->tex= copy_texture(tex);
+ tex->id.us--;
+ }
+ }
+ }
+
+ }
+ }
+ }
+ }
+ base= base->next;
+ }
+}
+
+void do_single_tex_user(Tex **from)
+{
+ Tex *tex, *texn;
+
+ tex= *from;
+ if(tex==0) return;
+
+ if(tex->id.newid) {
+ *from= (Tex *)tex->id.newid;
+ id_us_plus(tex->id.newid);
+ tex->id.us--;
+ }
+ else if(tex->id.us>1) {
+ texn= copy_texture(tex);
+ tex->id.newid= (ID *)texn;
+ tex->id.us--;
+ *from= texn;
+ }
+
+}
+
+void single_tex_users_expand()
+{
+ /* alleen als 'ouder' blokken LIB_NEW zijn */
+ Material *ma;
+ Lamp *la;
+ World *wo;
+ int b;
+
+ ma= G.main->mat.first;
+ while(ma) {
+ if(ma->id.flag & LIB_NEW) {
+ for(b=0; b<8; b++) {
+ if(ma->mtex[b] && ma->mtex[b]->tex) {
+ do_single_tex_user( &(ma->mtex[b]->tex) );
+ }
+ }
+ }
+ ma= ma->id.next;
+ }
+
+ la= G.main->lamp.first;
+ while(la) {
+ if(la->id.flag & LIB_NEW) {
+ for(b=0; b<6; b++) {
+ if(la->mtex[b] && la->mtex[b]->tex) {
+ do_single_tex_user( &(la->mtex[b]->tex) );
+ }
+ }
+ }
+ la= la->id.next;
+ }
+ wo= G.main->world.first;
+ while(wo) {
+ if(wo->id.flag & LIB_NEW) {
+ for(b=0; b<6; b++) {
+ if(wo->mtex[b] && wo->mtex[b]->tex) {
+ do_single_tex_user( &(wo->mtex[b]->tex) );
+ }
+ }
+ }
+ wo= wo->id.next;
+ }
+}
+
+void single_mat_users_expand(void)
+{
+ /* alleen als 'ouder' blokken LIB_NEW zijn */
+
+ Object *ob;
+ Mesh *me;
+ Curve *cu;
+ MetaBall *mb;
+ Material *ma;
+ int a;
+
+ ob= G.main->object.first;
+ while(ob) {
+ if(ob->id.flag & LIB_NEW) {
+ new_id_matar(ob->mat, ob->totcol);
+ }
+ ob= ob->id.next;
+ }
+
+ me= G.main->mesh.first;
+ while(me) {
+ if(me->id.flag & LIB_NEW) {
+ new_id_matar(me->mat, me->totcol);
+ }
+ me= me->id.next;
+ }
+
+ cu= G.main->curve.first;
+ while(cu) {
+ if(cu->id.flag & LIB_NEW) {
+ new_id_matar(cu->mat, cu->totcol);
+ }
+ cu= cu->id.next;
+ }
+
+ mb= G.main->mball.first;
+ while(mb) {
+ if(mb->id.flag & LIB_NEW) {
+ new_id_matar(mb->mat, mb->totcol);
+ }
+ mb= mb->id.next;
+ }
+
+ /* material imats */
+ ma= G.main->mat.first;
+ while(ma) {
+ if(ma->id.flag & LIB_NEW) {
+ for(a=0; a<8; a++) {
+ if(ma->mtex[a]) {
+ ID_NEW(ma->mtex[a]->object);
+ }
+ }
+ }
+ ma= ma->id.next;
+ }
+}
+
+void single_user(void)
+{
+ int nr;
+
+ if(G.scene->id.lib) return;
+
+ nr= pupmenu("Make Single User%t|Object|Object & ObData|Object & ObData & Materials+Tex|Materials+Tex");
+ if(nr>0) {
+
+ if(nr==1) single_object_users(1);
+
+ else if(nr==2) {
+ single_object_users(1);
+ single_obdata_users(1);
+ }
+ else if(nr==3) {
+ single_object_users(1);
+ single_obdata_users(1);
+ single_mat_users(1); /* ook tex */
+
+ }
+ else if(nr==4) {
+ single_mat_users(1);
+ }
+
+ clear_id_newpoins();
+
+ countall();
+ allqueue(REDRAWALL, 0);
+ }
+}
+
+/* ************************************************************* */
+
+
+void make_local(void)
+{
+ Base *base;
+ Object *ob;
+ Material *ma, ***matarar;
+ Lamp *la;
+ Curve *cu;
+ ID *id;
+ int a, b, mode;
+
+ /* LETOP: de functie new_id(..) voegt het id blok opnieuw in!!! */
+
+ if(G.scene->id.lib) return;
+
+ mode= pupmenu("Make Local%t|Selected %x1|All %x2");
+
+ if(mode==2) {
+ all_local();
+ allqueue(REDRAWALL, 0);
+ return;
+ }
+ else if(mode!=1) return;
+
+ clear_id_newpoins();
+
+ base= FIRSTBASE;
+ while(base) {
+ ob= base->object;
+ if( (base->flag & SELECT)) {
+ if(ob->id.lib) {
+ make_local_object(ob);
+ }
+ }
+ base= base->next;
+ }
+
+ /* evt object pointers */
+ base= FIRSTBASE;
+ while(base) {
+ ob= base->object;
+ if( (base->flag & SELECT)) {
+ if(ob->id.lib==0) {
+ ID_NEW(ob->parent);
+ ID_NEW(ob->track);
+ }
+ }
+ base= base->next;
+ }
+
+ base= FIRSTBASE;
+ while(base) {
+ ob= base->object;
+ if( (base->flag & SELECT) ) {
+
+ id= ob->data;
+
+ if(id) {
+
+ switch(ob->type) {
+ case OB_LAMP:
+ make_local_lamp((Lamp *)id);
+
+ la= ob->data;
+ id= (ID *)la->ipo;
+ if(id && id->lib) make_local_ipo(la->ipo);
+
+ break;
+ case OB_CAMERA:
+ make_local_camera((Camera *)id);
+ break;
+ case OB_MESH:
+ make_local_mesh((Mesh *)id);
+ make_local_key( ((Mesh *)id)->key );
+ break;
+ case OB_MBALL:
+ make_local_mball((MetaBall *)id);
+ break;
+ case OB_CURVE:
+ case OB_SURF:
+ case OB_FONT:
+ cu= (Curve *)id;
+ make_local_curve(cu);
+ id= (ID *)cu->ipo;
+ if(id && id->lib) make_local_ipo(cu->ipo);
+ make_local_key( cu->key );
+ break;
+ case OB_LATTICE:
+ make_local_lattice((Lattice *)id);
+ make_local_key( ((Lattice *)id)->key );
+ break;
+ case OB_ARMATURE:
+ make_local_armature ((bArmature *)id);
+ break;
+ }
+ }
+ id= (ID *)ob->ipo;
+ if(id && id->lib) make_local_ipo(ob->ipo);
+
+ id= (ID *)ob->action;
+ if(id && id->lib) make_local_action(ob->action);
+ }
+ base= base->next;
+ }
+
+ base= FIRSTBASE;
+ while(base) {
+ ob= base->object;
+ if(base->flag & SELECT ) {
+
+ if(ob->type==OB_LAMP) {
+ la= ob->data;
+ for(b=0; b<8; b++) {
+ if(la->mtex[b] && la->mtex[b]->tex) {
+ make_local_texture(la->mtex[b]->tex);
+ }
+ }
+ }
+ else {
+
+ for(a=0; a<ob->totcol; a++) {
+ ma= ob->mat[a];
+ if(ma) {
+ make_local_material(ma);
+
+ for(b=0; b<8; b++) {
+ if(ma->mtex[b] && ma->mtex[b]->tex) {
+ make_local_texture(ma->mtex[b]->tex);
+ }
+ }
+ id= (ID *)ma->ipo;
+ if(id && id->lib) make_local_ipo(ma->ipo);
+ }
+ }
+
+ matarar= (Material ***)give_matarar(ob);
+
+ for(a=0; a<ob->totcol; a++) {
+ ma= (*matarar)[a];
+ if(ma) {
+ make_local_material(ma);
+
+ for(b=0; b<8; b++) {
+ if(ma->mtex[b] && ma->mtex[b]->tex) {
+ make_local_texture(ma->mtex[b]->tex);
+ }
+ }
+ id= (ID *)ma->ipo;
+ if(id && id->lib) make_local_ipo(ma->ipo);
+ }
+ }
+ }
+ }
+ base= base->next;
+ }
+
+
+ allqueue(REDRAWALL, 0);
+
+}
+
+
+void adduplicate(float *dtrans)
+/* dtrans is 3 x 3xfloat dloc, drot en dsize */
+{
+ Base *base, *basen;
+ Object *ob, *obn;
+ Ika *ika;
+ Deform *def;
+ Material ***matarar, *ma, *mao;
+ ID *id;
+ bConstraintChannel *chan;
+ int a, didit, dupflag;
+
+ if(G.scene->id.lib) return;
+ clear_id_newpoins();
+ clear_sca_new_poins(); /* sensor/contr/act */
+
+ if( G.qual & LR_ALTKEY ) dupflag= 0;
+ else dupflag= U.dupflag;
+
+ base= FIRSTBASE;
+ while(base) {
+ if TESTBASELIB(base) {
+
+ ob= base->object;
+ obn= copy_object(ob);
+
+ basen= MEM_mallocN(sizeof(Base), "duplibase");
+ *basen= *base;
+ BLI_addhead(&G.scene->base, basen); /* addhead: anders oneindige lus */
+ basen->object= obn;
+ base->flag &= ~SELECT;
+ basen->flag &= ~OB_FROMGROUP;
+
+ if(BASACT==base) BASACT= basen;
+
+ /* duplicates ahv userflags */
+
+ if(dupflag & DUPIPO) {
+ id= (ID *)obn->ipo;
+ if(id) {
+ ID_NEW_US( obn->ipo)
+ else obn->ipo= copy_ipo(obn->ipo);
+ id->us--;
+ }
+ /* Handle constraint ipos */
+ for (chan=obn->constraintChannels.first; chan; chan=chan->next){
+ id= (ID *)chan->ipo;
+ if(id) {
+ ID_NEW_US( chan->ipo)
+ else chan->ipo= copy_ipo(chan->ipo);
+ id->us--;
+ }
+ }
+ }
+ if(dupflag & DUPACT){
+ id= (ID *)obn->action;
+ if (id){
+ ID_NEW_US(obn->action)
+ else{
+ obn->action= copy_action(obn->action);
+ obn->activecon=NULL;
+ }
+ id->us--;
+ }
+ }
+ if(dupflag & DUPMAT) {
+ for(a=0; a<obn->totcol; a++) {
+ id= (ID *)obn->mat[a];
+ if(id) {
+ ID_NEW_US(obn->mat[a])
+ else obn->mat[a]= copy_material(obn->mat[a]);
+ id->us--;
+ }
+ }
+ }
+
+ id= obn->data;
+ didit= 0;
+
+ switch(obn->type) {
+ case OB_MESH:
+ if(dupflag & DUPMESH) {
+ ID_NEW_US2( obn->data )
+ else {
+ obn->data= copy_mesh(obn->data);
+ didit= 1;
+ }
+ id->us--;
+ }
+ break;
+ case OB_CURVE:
+ if(dupflag & DUPCURVE) {
+ ID_NEW_US2(obn->data )
+ else {
+ obn->data= copy_curve(obn->data);
+ makeDispList(ob);
+ didit= 1;
+ }
+ id->us--;
+ }
+ break;
+ case OB_SURF:
+ if(dupflag & DUPSURF) {
+ ID_NEW_US2( obn->data )
+ else {
+ obn->data= copy_curve(obn->data);
+ makeDispList(ob);
+ didit= 1;
+ }
+ id->us--;
+ }
+ break;
+ case OB_FONT:
+ if(dupflag & DUPFONT) {
+ ID_NEW_US2( obn->data )
+ else {
+ obn->data= copy_curve(obn->data);
+ makeDispList(ob);
+ didit= 1;
+ }
+ id->us--;
+ }
+ break;
+ case OB_MBALL:
+ if(dupflag & DUPMBALL) {
+ ID_NEW_US2(obn->data )
+ else {
+ obn->data= copy_mball(obn->data);
+ didit= 1;
+ }
+ id->us--;
+ }
+ break;
+ case OB_LAMP:
+ if(dupflag & DUPLAMP) {
+ ID_NEW_US2(obn->data )
+ else obn->data= copy_lamp(obn->data);
+ id->us--;
+ }
+ break;
+
+ case OB_ARMATURE:
+ if(dupflag & DUPARM) {
+ ID_NEW_US2(obn->data )
+ else {
+ obn->data= copy_armature(obn->data);
+ didit= 1;
+ }
+ id->us--;
+ }
+ break;
+ /* always dupli's */
+
+ case OB_LATTICE:
+ ID_NEW_US2(obn->data )
+ else obn->data= copy_lattice(obn->data);
+ id->us--;
+ break;
+ case OB_CAMERA:
+ ID_NEW_US2(obn->data )
+ else obn->data= copy_camera(obn->data);
+ id->us--;
+ break;
+ case OB_IKA:
+ ID_NEW_US2(obn->data )
+ else obn->data= copy_ika(obn->data);
+ id->us--;
+ break;
+ }
+
+ if(dupflag & DUPMAT) {
+ matarar= give_matarar(obn);
+ if(didit && matarar) {
+ for(a=0; a<obn->totcol; a++) {
+ id= (ID *)(*matarar)[a];
+ if(id) {
+ ID_NEW_US( (*matarar)[a] )
+ else (*matarar)[a]= copy_material((*matarar)[a]);
+
+ id->us--;
+ }
+ }
+ }
+ }
+
+ }
+ base= base->next;
+ }
+
+ /* evt object pointers */
+ base= FIRSTBASE;
+ while(base) {
+ if TESTBASELIB(base) {
+
+ {
+ bPoseChannel *chan;
+
+ relink_constraints(&base->object->constraints);
+ if (base->object->pose){
+ for (chan = base->object->pose->chanbase.first; chan; chan=chan->next){
+ relink_constraints(&chan->constraints);
+ }
+ }
+ }
+ ID_NEW(base->object->parent);
+ ID_NEW(base->object->track);
+
+ if(base->object->type==OB_IKA) {
+ ika= base->object->data;
+ ID_NEW(ika->parent);
+
+ a= ika->totdef;
+ def= ika->def;
+ while(a--) {
+ ID_NEW(def->ob);
+ def++;
+ }
+ }
+ }
+ base= base->next;
+ }
+
+ /* materialen */
+ if( dupflag & DUPMAT) {
+ mao= G.main->mat.first;
+ while(mao) {
+ if(mao->id.newid) {
+
+ ma= (Material *)mao->id.newid;
+
+ if(dupflag & DUPTEX) {
+ for(a=0; a<8; a++) {
+ if(ma->mtex[a]) {
+ id= (ID *)ma->mtex[a]->tex;
+ if(id) {
+ ID_NEW_US(ma->mtex[a]->tex)
+ else ma->mtex[a]->tex= copy_texture(ma->mtex[a]->tex);
+ id->us--;
+ }
+ }
+ }
+ }
+ id= (ID *)ma->ipo;
+ if(id) {
+ ID_NEW_US(ma->ipo)
+ else ma->ipo= copy_ipo(ma->ipo);
+ id->us--;
+ }
+ }
+ mao= mao->id.next;
+ }
+ }
+
+ sort_baselist(G.scene);
+ set_sca_new_poins();
+
+ clear_id_newpoins();
+
+ countall();
+ if(dtrans==0) transform('g');
+
+ set_active_base(BASACT);
+
+ allqueue(REDRAWNLA, 0);
+ allqueue(REDRAWACTION, 0); /* ook oops */
+ allqueue(REDRAWIPO, 0); /* ook oops */
+}
+
+
+void selectlinks(void)
+{
+ Object *ob;
+ Base *base;
+ void *obdata = NULL;
+ Ipo *ipo = NULL;
+ Material *mat = NULL, *mat1;
+ Tex *tex=0;
+ int a, b, nr;
+
+ ob= OBACT;
+ if(ob==0) return;
+ nr= pupmenu("Select links%t|Object Ipo|Object Data|Current Material|Current texture");
+
+ if(nr==1) {
+ ipo= ob->ipo;
+ if(ipo==0) return;
+ }
+ else if(nr==2) {
+ if(ob->data==0) return;
+ obdata= ob->data;
+ }
+ else if(nr==3 || nr==4) {
+ mat= give_current_material(ob, ob->actcol);
+ if(mat==0) return;
+ if(nr==4) {
+ if(mat->mtex[ mat->texact ]) tex= mat->mtex[ mat->texact ]->tex;
+ if(tex==0) return;
+ }
+ }
+ else return;
+
+ base= FIRSTBASE;
+ while(base) {
+ if(base->lay & G.vd->lay) {
+ if(nr==1) {
+ if(base->object->ipo==ipo) base->flag |= SELECT;
+ }
+ else if(nr==2) {
+ if(base->object->data==obdata) base->flag |= SELECT;
+ }
+ else if(nr==3 || nr==4) {
+ ob= base->object;
+
+ for(a=1; a<=ob->totcol; a++) {
+ mat1= give_current_material(ob, a);
+ if(nr==3) {
+ if(mat1==mat) base->flag |= SELECT;
+ }
+ else if(mat1 && nr==4) {
+ for(b=0; b<8; b++) {
+ if(mat1->mtex[b]) {
+ if(tex==mat1->mtex[b]->tex) base->flag |= SELECT;
+ }
+ }
+ }
+ }
+ }
+ base->object->flag= base->flag;
+ }
+ base= base->next;
+ }
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWDATASELECT, 0);
+ allqueue(REDRAWOOPS, 0);
+}
+
+void image_aspect(void)
+{
+ /* alle geselecteerde objecten die imap hebben: scalen in ima verhouding */
+ Base *base;
+ Object *ob;
+ Material *ma;
+ Tex *tex;
+ Mesh *me;
+ Curve *cu;
+ float x, y, space;
+ int a, b, done;
+
+ if(G.obedit) return;
+ if(G.scene->id.lib) return;
+
+ base= FIRSTBASE;
+ while(base) {
+ if TESTBASELIB(base) {
+ ob= base->object;
+ done= 0;
+
+ for(a=1; a<=ob->totcol; a++) {
+ ma= give_current_material(ob, a);
+ if(ma) {
+ for(b=0; b<8; b++) {
+ if(ma->mtex[b] && ma->mtex[b]->tex) {
+ tex= ma->mtex[b]->tex;
+ if(tex->type==TEX_IMAGE && tex->ima && tex->ima->ibuf) {
+ /* texturespace */
+ space= 1.0;
+ if(ob->type==OB_MESH) {
+ me= ob->data;
+ space= me->size[0]/me->size[1];
+ }
+ else if ELEM3(ob->type, OB_CURVE, OB_FONT, OB_SURF) {
+ cu= ob->data;
+ space= cu->size[0]/cu->size[1];
+ }
+
+ x= tex->ima->ibuf->x/space;
+ y= tex->ima->ibuf->y;
+
+ if(x>y) ob->size[0]= ob->size[1]*x/y;
+ else ob->size[1]= ob->size[0]*y/x;
+
+ done= 1;
+ }
+ }
+ if(done) break;
+ }
+ }
+ if(done) break;
+ }
+ }
+ base= base->next;
+ }
+
+ allqueue(REDRAWVIEW3D, 0);
+}
+
+void set_ob_ipoflags(void)
+{
+ Base *base;
+ int set= 1;
+
+ base= FIRSTBASE;
+ while(base) {
+ if TESTBASE(base) {
+ if(base->object->ipoflag & OB_DRAWKEY) {
+ set= 0;
+ break;
+ }
+ }
+ base= base->next;
+ }
+
+ base= FIRSTBASE;
+ while(base) {
+ if TESTBASE(base) {
+ if(set) {
+ base->object->ipoflag |= OB_DRAWKEY;
+ if(base->object->ipo) base->object->ipo->showkey= 1;
+ }
+ else {
+ base->object->ipoflag &= ~OB_DRAWKEY;
+ }
+ }
+ base= base->next;
+ }
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWBUTSANIM, 0);
+ if(set) {
+ allqueue(REDRAWNLA, 0);
+ allqueue (REDRAWACTION, 0);
+ allspace(REMAKEIPO, 0);
+ allqueue(REDRAWIPO, 0);
+ }
+}
+
+void select_select_keys(void)
+{
+ Base *base;
+ IpoCurve *icu;
+ BezTriple *bezt;
+ int a;
+
+ if(G.scene->id.lib) return;
+
+ if(okee("show and select all keys")==0) return;
+
+ base= FIRSTBASE;
+ while(base) {
+ if TESTBASELIB(base) {
+ if(base->object->ipo) {
+ base->object->ipoflag |= OB_DRAWKEY;
+ base->object->ipo->showkey= 1;
+ icu= base->object->ipo->curve.first;
+ while(icu) {
+ a= icu->totvert;
+ bezt= icu->bezt;
+ while(a--) {
+ bezt->f1 |= SELECT;
+ bezt->f2 |= SELECT;
+ bezt->f3 |= SELECT;
+ bezt++;
+ }
+ icu= icu->next;
+ }
+ }
+ }
+ base= base->next;
+ }
+
+ allqueue(REDRAWNLA, 0);
+ allqueue(REDRAWACTION, 0);
+ allqueue(REDRAWVIEW3D, 0);
+ allspace(REMAKEIPO, 0);
+ allqueue(REDRAWIPO, 0);
+
+}
+
+
+MVert *verg_vert;
+
+int verg_hoogste_zco(const void *a1, const void *a2)
+{
+ const MFace *x1=a1, *x2=a2;
+ float z1, z2;
+ MVert *v1, *v2, *v3;
+
+ v1= verg_vert+x1->v1;
+ v2= verg_vert+x1->v2;
+ v3= verg_vert+x1->v3;
+ z1= MAX3(v1->co[2], v2->co[2], v3->co[2]);
+
+ v1= verg_vert+x2->v1;
+ v2= verg_vert+x2->v2;
+ v3= verg_vert+x2->v3;
+ z2= MAX3(v1->co[2], v2->co[2], v3->co[2]);
+
+ if( z1 > z2 ) return 1;
+ else if( z1 < z2) return -1;
+ return 0;
+}
+
+
+
+void sortfaces(void)
+{
+ Mesh *me;
+
+ if(G.scene->id.lib) return;
+
+ if(G.obedit!=0 || BASACT==0 || OBACT->type!= OB_MESH) return;
+ if(okee("Sort faces")==0) return;
+
+ me= OBACT->data;
+ verg_vert= me->mvert;
+
+ qsort(me->mface, me->totface, sizeof(MFace), verg_hoogste_zco);
+}
+
+int vergbaseco(const void *a1, const void *a2)
+{
+ Base **x1, **x2;
+
+ x1= (Base **) a1;
+ x2= (Base **) a2;
+
+ if( (*x1)->sy > (*x2)->sy ) return 1;
+ else if( (*x1)->sy < (*x2)->sy) return -1;
+ else if( (*x1)->sx > (*x2)->sx ) return 1;
+ else if( (*x1)->sx < (*x2)->sx ) return -1;
+
+ return 0;
+}
+
+
+void auto_timeoffs(void)
+{
+ Base *base, **basesort, **bs;
+ float start, delta;
+ int tot=0, a;
+ short offset=25;
+
+ if(BASACT==0) return;
+ if(button(&offset, 0, 1000,"Total time")==0) return;
+
+ /* maak array van alle bases, xco yco (scherm) */
+ base= FIRSTBASE;
+ while(base) {
+ if(TESTBASELIB(base)) {
+ tot++;
+ }
+ base= base->next;
+ }
+
+ delta= (float)offset/(float)tot;
+ start= OBACT->sf;
+
+ bs= basesort= MEM_mallocN(sizeof(void *)*tot,"autotimeoffs");
+ base= FIRSTBASE;
+
+ while(base) {
+ if(TESTBASELIB(base)) {
+ *bs= base;
+ bs++;
+ }
+ base= base->next;
+ }
+ qsort(basesort, tot, sizeof(void *), vergbaseco);
+
+ bs= basesort;
+ for(a=0; a<tot; a++) {
+
+ (*bs)->object->sf= start;
+ start+= delta;
+
+ bs++;
+ }
+ MEM_freeN(basesort);
+
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWBUTSANIM, 0);
+}
+
+void texspace_edit(void)
+{
+ Base *base;
+ int nr=0;
+
+ /* eerst testen of van de zichtbare en geselecteerde ob's
+ * wel de texspacedraw aanstaat:
+ */
+
+ if(G.obedit) return;
+
+ base= FIRSTBASE;
+ while(base) {
+ if TESTBASELIB(base) {
+ break;
+ }
+ base= base->next;
+ }
+
+ if(base==0) {
+ return;
+ }
+
+ /* nr= pupmenu("Texture space %t|Grabber%x1|Size%x2|Rotate%x3"); */
+ nr= pupmenu("Texture space %t|Grabber%x1|Size%x2");
+ if(nr<1) return;
+
+ base= FIRSTBASE;
+ while(base) {
+ if TESTBASELIB(base) {
+ base->object->dtx |= OB_TEXSPACE;
+ }
+ base= base->next;
+ }
+
+
+ transmode= TRANS_TEX;
+
+ if(nr==1) transform('g');
+ else if(nr==2) transform('s');
+ else if(nr==3) transform('r');
+
+ transmode= 0;
+}
+
+void first_base(void)
+{
+ /* maakt de select bases los en insert ze aan begin */
+ Base *base, *next;
+
+ if(okee("make first base")==0) return;
+
+ base= FIRSTBASE;
+ while(base) {
+ next= base->next;
+
+ if(base->flag & SELECT) {
+ BLI_remlink(&G.scene->base, base);
+ BLI_addtail(&G.scene->base, base);
+ }
+
+ base= next;
+ }
+
+}
+
+void make_displists_by_obdata(void *obdata) {
+ Base *base;
+
+ for (base= FIRSTBASE; base; base= base->next)
+ if (obdata==base->object->data)
+ makeDispList(base->object);
+}
+
diff --git a/source/blender/src/editoops.c b/source/blender/src/editoops.c
new file mode 100644
index 00000000000..9ec2001ce5f
--- /dev/null
+++ b/source/blender/src/editoops.c
@@ -0,0 +1,595 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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>
+#ifndef WIN32
+#include <unistd.h>
+#else
+#include <io.h>
+#include "BLI_winstuff.h"
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+
+#include "DNA_material_types.h"
+#include "DNA_object_types.h"
+#include "DNA_oops_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+
+#include "BKE_global.h"
+#include "BKE_scene.h"
+#include "BKE_material.h"
+
+#include "BIF_space.h"
+#include "BIF_screen.h"
+#include "BIF_editoops.h"
+#include "BIF_editview.h"
+#include "BIF_drawscene.h"
+#include "BIF_mywindow.h"
+
+#include "BDR_editobject.h"
+
+#include "BSE_edit.h"
+#include "BSE_drawipo.h"
+
+#include "blendef.h"
+#include "mydevice.h"
+
+
+typedef struct TransOops {
+ float *loc;
+ float oldloc[2];
+} TransOops;
+
+
+static void oops_to_select_objects(void)
+{
+ Oops *oops;
+ Base *base;
+ Object *ob;
+
+ if(G.soops==0) return;
+
+ oops= G.soops->oops.first;
+ while(oops) {
+ if(oops->hide==0) {
+ if(oops->type==ID_OB) {
+ ob= (Object *)oops->id;
+ if(oops->flag & SELECT) ob->flag |= SELECT;
+ else ob->flag &= ~SELECT;
+ }
+ }
+ oops= oops->next;
+ }
+ base= FIRSTBASE;
+ while(base) {
+ if(base->flag != base->object->flag) {
+ base->flag= base->object->flag;
+ }
+ base= base->next;
+ }
+
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWOOPS, 0);
+}
+
+void swap_select_all_oops(void)
+{
+ Oops *oops;
+ int sel= 0;
+
+ if(G.soops==0) return;
+
+ oops= G.soops->oops.first;
+ while(oops) {
+ if(oops->hide==0) {
+ if(oops->flag & SELECT) {
+ sel= 1;
+ break;
+ }
+ }
+ oops= oops->next;
+ }
+
+ oops= G.soops->oops.first;
+ while(oops) {
+ if(oops->hide==0) {
+ if(sel) oops->flag &= ~SELECT;
+ else oops->flag |= SELECT;
+ }
+ oops= oops->next;
+ }
+
+ oops_to_select_objects(); /* ook redr */
+
+ G.soops->lockpoin= 0;
+}
+
+/* never used... check CVS 1.12 for the code */
+/* static void select_swap_oops(void) */
+
+static void deselect_all_oops(void)
+{
+ Oops *oops;
+
+ if(G.soops==0) return;
+
+ oops= G.soops->oops.first;
+ while(oops) {
+ if(oops->hide==0) {
+ oops->flag &= ~SELECT;
+ }
+ oops= oops->next;
+ }
+ G.soops->lockpoin= 0;
+}
+
+void set_select_flag_oops(void) /* alle areas */
+{
+ SpaceOops *so;
+ ScrArea *sa;
+
+ sa= G.curscreen->areabase.first;
+ while(sa) {
+ if(sa->spacetype==SPACE_OOPS) {
+ so= sa->spacedata.first;
+ so->flag |= SO_NEWSELECTED;
+ }
+ sa= sa->next;
+ }
+ if(G.soops) G.soops->lockpoin= 0;
+}
+
+void deselect_all_area_oops(void) /* alle areas */
+{
+ SpaceOops *so;
+ Oops *oops;
+ ScrArea *sa;
+
+ sa= G.curscreen->areabase.first;
+ while(sa) {
+ if(sa->spacetype==SPACE_OOPS) {
+ so= sa->spacedata.first;
+
+ oops= so->oops.first;
+ while(oops) {
+ oops->flag &= ~SELECT;
+ oops= oops->next;
+ }
+ }
+ sa= sa->next;
+ }
+
+ if(G.soops) G.soops->lockpoin= 0;
+}
+
+void transform_oops(int mode)
+{
+ TransOops *transmain, *tv;
+ Oops *oops;
+ float dx, dy, div, dvec[3], cent[3], min[3], max[3];
+ float sizefac, size[2], xref=1.0, yref=1.0;
+ int a, tot= 0, midtog= 0;
+ unsigned short event = 0;
+ short firsttime= 1, proj = 0, afbreek=0, xc, yc, xo, yo, xn, yn, mval[2];
+ short val;
+ char str[32];
+
+ if(G.soops==0) return;
+
+ /* welke oopsen doen mee */
+ oops= G.soops->oops.first;
+ while(oops) {
+ if(oops->hide==0) {
+ if(oops->flag & SELECT) {
+ tot++;
+ }
+ }
+ oops= oops->next;
+ }
+
+ if(tot==0) return;
+
+ G.moving= 1;
+
+ INIT_MINMAX(min, max);
+
+ tv=transmain= MEM_callocN(tot*sizeof(TransOops), "transmain");
+ oops= G.soops->oops.first;
+ while(oops) {
+ if(oops->hide==0) {
+ if(oops->flag & SELECT) {
+ tv->loc= &oops->x;
+ tv->oldloc[0]= tv->loc[0];
+ tv->oldloc[1]= tv->loc[1];
+ DO_MINMAX2(tv->loc, min, max);
+ tv++;
+ }
+ }
+ oops= oops->next;
+ }
+
+ cent[0]= (min[0]+max[0])/2.0;
+ cent[1]= (min[1]+max[1])/2.0;
+
+ ipoco_to_areaco_noclip(G.v2d, cent, mval);
+ xc= mval[0];
+ yc= mval[1];
+
+ getmouseco_areawin(mval);
+ xo= xn= mval[0];
+ yo= yn= mval[1];
+ dvec[0]= dvec[1]= 0.0;
+
+ sizefac= sqrt( (float)((yc-yn)*(yc-yn)+(xn-xc)*(xn-xc)) );
+ if(sizefac<2.0) sizefac= 2.0;
+
+ while(afbreek==0) {
+ getmouseco_areawin(mval);
+ if(mval[0]!=xo || mval[1]!=yo || firsttime) {
+
+ if(mode=='g') {
+
+ dx= mval[0]- xo;
+ dy= mval[1]- yo;
+
+ div= G.v2d->mask.xmax-G.v2d->mask.xmin;
+ dvec[0]+= (G.v2d->cur.xmax-G.v2d->cur.xmin)*(dx)/div;
+
+ div= G.v2d->mask.ymax-G.v2d->mask.ymin;
+ dvec[1]+= (G.v2d->cur.ymax-G.v2d->cur.ymin)*(dy)/div;
+
+ if(midtog) dvec[proj]= 0.0;
+
+ tv= transmain;
+ for(a=0; a<tot; a++, tv++) {
+
+ tv->loc[0]= tv->oldloc[0]+dvec[0];
+ tv->loc[1]= tv->oldloc[1]+dvec[1];
+
+ }
+
+ sprintf(str, "X: %.2f Y: %.2f ", dvec[0], dvec[1]);
+ headerprint(str);
+ }
+ else if(mode=='s') {
+ size[0]=size[1]= (sqrt( (float)((yc-mval[1])*(yc-mval[1])+(mval[0]-xc)*(mval[0]-xc)) ))/sizefac;
+
+ if(midtog) size[proj]= 1.0;
+ size[0]*= xref;
+ size[1]*= yref;
+
+ tv= transmain;
+ for(a=0; a<tot; a++, tv++) {
+
+ tv->loc[0]= size[0]*(tv->oldloc[0]-cent[0])+ cent[0];
+ tv->loc[1]= size[1]*(tv->oldloc[1]-cent[1])+ cent[1];
+
+ }
+
+ sprintf(str, "sizeX: %.3f sizeY: %.3f ", size[0], size[1]);
+ headerprint(str);
+ }
+
+
+ xo= mval[0];
+ yo= mval[1];
+
+ force_draw();
+
+ firsttime= 0;
+
+ }
+ else BIF_wait_for_statechange();
+
+ while(qtest()) {
+ event= extern_qread(&val);
+ if(val) {
+ switch(event) {
+ case ESCKEY:
+ case LEFTMOUSE:
+ case SPACEKEY:
+ case RETKEY:
+ afbreek= 1;
+ break;
+ case MIDDLEMOUSE:
+
+ midtog= ~midtog;
+ if(midtog) {
+ if( abs(mval[0]-xn) > abs(mval[1]-yn)) proj= 1;
+ else proj= 0;
+ firsttime= 1;
+ }
+
+ break;
+ default:
+ arrows_move_cursor(event);
+ }
+ }
+ if(afbreek) break;
+ }
+ }
+
+ if(event==ESCKEY) {
+ tv= transmain;
+ for(a=0; a<tot; a++, tv++) {
+ tv->loc[0]= tv->oldloc[0];
+ tv->loc[1]= tv->oldloc[1];
+ }
+ }
+ MEM_freeN(transmain);
+
+ G.moving= 0;
+
+ scrarea_queue_redraw(curarea);
+}
+
+static Oops *find_nearest_oops(void)
+{
+ Oops *oops;
+ float x, y;
+ short mval[2];
+
+ getmouseco_areawin(mval);
+ areamouseco_to_ipoco(G.v2d, mval, &x, &y);
+
+ oops= G.soops->oops.first;
+ while(oops) {
+ if(oops->hide == 0) {
+ if(oops->x <=x && oops->x+OOPSX >= x) {
+ if(oops->y <=y && oops->y+OOPSY >= y) {
+ return oops;
+ }
+ }
+ }
+ oops= oops->next;
+ }
+ return 0;
+}
+
+static void do_activate_oops(Oops *oops)
+{
+ Base *base;
+ Object *ob;
+
+ switch(oops->type) {
+ case ID_SCE:
+ if(oops->id) set_scene((Scene *)oops->id);
+ break;
+ case ID_OB:
+ base= FIRSTBASE;
+ while(base) {
+ if(base->object == (Object *)oops->id) break;
+ base= base->next;
+ }
+ if(base) {
+ set_active_base(base); /* editview.c */
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWINFO, 1);
+ }
+ break;
+ case ID_MA:
+ ob= OBACT;
+ if(ob && oops->id) {
+ assign_material(ob, (Material *)oops->id, ob->actcol);
+ allqueue(REDRAWBUTSMAT, 0);
+ scrarea_queue_winredraw(curarea);
+ }
+ break;
+
+ }
+}
+
+void mouse_select_oops(void)
+{
+ Oops *oops;
+ extern float oopslastx, oopslasty; /* oops.c */
+
+ if(G.soops==0) return;
+
+ /* welke oopsen doen mee */
+ oops= G.soops->oops.first;
+
+ oops= find_nearest_oops();
+ if(oops==0) return;
+
+ if((G.qual & LR_SHIFTKEY)==0) deselect_all_oops();
+
+ if(oops) {
+ /* last_seq= seq; */
+
+ if(G.qual==0) {
+ oops->flag |= SELECT;
+ }
+ else {
+ if(oops->flag & SELECT) {
+ oops->flag &= ~SELECT;
+ }
+ else {
+ oops->flag |= SELECT;
+ }
+ }
+
+ oopslastx= oops->x;
+ oopslasty= oops->y;
+
+ if(G.qual & LR_CTRLKEY) do_activate_oops(oops);
+ G.soops->lockpoin= oops;
+ }
+
+ oops_to_select_objects(); /* ook redr */
+ scrarea_queue_headredraw(curarea);
+
+ force_draw();
+
+ std_rmouse_transform(transform_oops);
+}
+
+void borderselect_oops(void)
+{
+ Oops *oops;
+ rcti rect;
+ rctf rectf, rq;
+ int val;
+ short mval[2];
+
+ if(G.soops==0) return;
+
+ val= get_border(&rect, 3);
+
+ if(val) {
+ mval[0]= rect.xmin;
+ mval[1]= rect.ymin;
+ areamouseco_to_ipoco(G.v2d, mval, &rectf.xmin, &rectf.ymin);
+ mval[0]= rect.xmax;
+ mval[1]= rect.ymax;
+ areamouseco_to_ipoco(G.v2d, mval, &rectf.xmax, &rectf.ymax);
+
+ oops= G.soops->oops.first;
+ while(oops) {
+ if(oops->hide == 0) {
+
+ rq.xmin= oops->x;
+ rq.xmax= oops->x+OOPSX;
+ rq.ymin= oops->y;
+ rq.ymax= oops->y+OOPSY;
+
+ if(BLI_isect_rctf(&rq, &rectf, 0)) {
+ if(val==LEFTMOUSE) {
+ oops->flag |= SELECT;
+ }
+ else {
+ oops->flag &= ~SELECT;
+ }
+ }
+ }
+ oops= oops->next;
+ }
+
+ oops_to_select_objects(); /* ook redr */
+ }
+}
+
+static void select_oops_lib(ID *id)
+{
+ Oops *oops;
+
+ oops= G.soops->oops.first;
+ while(oops) {
+ if(oops->hide==0) {
+ if(oops->id->lib== (Library *)id) oops->flag |= OOPS_DOSELECT;
+ }
+ oops= oops->next;
+ }
+}
+
+void select_linked_oops(void)
+{
+ Oops *oops;
+ OopsLink *ol;
+
+ if(G.soops==0) return;
+
+ oops= G.soops->oops.first;
+ while(oops) {
+ if(oops->hide==0) {
+ if(oops->flag & SELECT) {
+ if(oops->type==ID_LI) select_oops_lib(oops->id);
+ ol= oops->link.first;
+ while(ol) {
+ if(ol->to && ol->to->hide==0) ol->to->flag |= OOPS_DOSELECT;
+ ol= ol->next;
+ }
+ }
+ }
+ oops= oops->next;
+ }
+
+ oops= G.soops->oops.first;
+ while(oops) {
+ if(oops->hide==0) {
+ if(oops->flag & OOPS_DOSELECT) {
+ oops->flag |= SELECT;
+ oops->flag &= ~OOPS_DOSELECT;
+ }
+ }
+ oops= oops->next;
+ }
+
+ oops_to_select_objects(); /* ook redr */
+
+}
+
+void select_backlinked_oops(void)
+{
+ Oops *oops;
+ OopsLink *ol;
+
+ if(G.soops==0) return;
+
+ oops= G.soops->oops.first;
+ while(oops) {
+ if(oops->hide==0) {
+ if( (oops->flag & SELECT)==0) {
+ ol= oops->link.first;
+ while(ol) {
+ if(ol->to && ol->to->hide==0) {
+ if(ol->to->flag & SELECT) oops->flag |= OOPS_DOSELECT;
+ }
+ ol= ol->next;
+ }
+ }
+ }
+ oops= oops->next;
+ }
+
+ oops= G.soops->oops.first;
+ while(oops) {
+ if(oops->hide==0) {
+ if(oops->flag & OOPS_DOSELECT) {
+ oops->flag |= SELECT;
+ oops->flag &= ~OOPS_DOSELECT;
+ }
+ }
+ oops= oops->next;
+ }
+
+ oops_to_select_objects(); /* ook redr */
+
+}
diff --git a/source/blender/src/editsca.c b/source/blender/src/editsca.c
new file mode 100644
index 00000000000..6357a4c7ac2
--- /dev/null
+++ b/source/blender/src/editsca.c
@@ -0,0 +1,2647 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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>
+
+#ifndef WIN32
+#include <unistd.h>
+#else
+#include <io.h>
+#include "BLI_winstuff.h"
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+
+#include "DNA_action_types.h"
+#include "DNA_material_types.h"
+#include "DNA_sensor_types.h"
+#include "DNA_actuator_types.h"
+#include "DNA_controller_types.h"
+#include "DNA_property_types.h"
+#include "DNA_object_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_sound_types.h"
+#include "DNA_text_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_mesh_types.h"
+
+#include "BKE_library.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_sca.h"
+#include "BKE_property.h"
+
+#include "BIF_gl.h"
+#include "BIF_resources.h"
+#include "BIF_space.h"
+#include "BIF_interface.h"
+#include "BIF_screen.h"
+#include "BIF_editsca.h"
+#include "BIF_keyval.h"
+#include "BIF_editsound.h"
+
+#include "BDR_editcurve.h"
+#include "BSE_buttons.h"
+
+#include "blendef.h"
+#include "mydevice.h"
+#include "interface.h"
+#include "nla.h" /* For __NLA : Important, do not remove */
+
+#include "license_key.h"
+extern int LICENSE_KEY_VALID;
+
+#define B_DIFF 1
+#define B_ADD_PROP 2701
+#define B_CHANGE_PROP 2702
+
+#define B_ADD_SENS 2703
+#define B_CHANGE_SENS 2704
+#define B_DEL_SENS 2705
+
+#define B_ADD_CONT 2706
+#define B_CHANGE_CONT 2707
+#define B_DEL_CONT 2708
+
+#define B_ADD_ACT 2709
+#define B_CHANGE_ACT 2710
+#define B_DEL_ACT 2711
+
+#define B_SOUNDACT_BROWSE 2712
+
+/* internals */
+
+/****/
+
+static ID **get_selected_and_linked_obs(short *count, short scavisflag);
+static char *actuator_pup(Object *owner);
+
+/****/
+
+static void del_property(void *selpropv, void *data2_unused)
+{
+ bProperty *prop, *selprop= selpropv;
+ Object *ob;
+ int a=0;
+
+ ob= OBACT;
+ if(ob==NULL) return;
+
+ prop= ob->prop.first;
+ while(prop) {
+ if(prop==selprop) {
+ if (strcmp(prop->name,"Text") == 0) {
+ allqueue(REDRAWVIEW3D, 0);
+ }
+ BLI_remlink(&ob->prop, prop);
+ free_property(prop);
+ break;
+ }
+ a++;
+ prop= prop->next;
+ }
+ allqueue(REDRAWBUTSGAME, 0);
+
+}
+
+static int vergname(const void *v1, const void *v2)
+{
+ char **x1, **x2;
+
+ x1= (char **)v1;
+ x2= (char **)v2;
+
+ return strcmp(*x1, *x2);
+}
+
+void make_unique_prop_names(char *str)
+{
+ Object *ob;
+ bProperty *prop;
+ bSensor *sens;
+ bController *cont;
+ bActuator *act;
+ ID **idar;
+ short a, obcount, propcount=0, nr;
+ char **names;
+
+ /* this function is called by a Button, and gives the current
+ * stringpointer as an argument, this is the one that can change
+ */
+
+ idar= get_selected_and_linked_obs(&obcount, BUTS_SENS_SEL|BUTS_SENS_ACT|BUTS_ACT_SEL|BUTS_ACT_ACT|BUTS_CONT_SEL|BUTS_CONT_ACT);
+
+ /* for each object, make properties and sca names unique */
+
+ /* count total names */
+ for(a=0; a<obcount; a++) {
+ ob= (Object *)idar[a];
+ propcount+= BLI_countlist(&ob->prop);
+ propcount+= BLI_countlist(&ob->sensors);
+ propcount+= BLI_countlist(&ob->controllers);
+ propcount+= BLI_countlist(&ob->actuators);
+ }
+ if(propcount==0) {
+ if(idar) MEM_freeN(idar);
+ return;
+ }
+
+ /* make names array for sorting */
+ names= MEM_callocN(propcount*sizeof(void *), "names");
+
+ /* count total names */
+ nr= 0;
+ for(a=0; a<obcount; a++) {
+ ob= (Object *)idar[a];
+ prop= ob->prop.first;
+ while(prop) {
+ names[nr++]= prop->name;
+ prop= prop->next;
+ }
+ sens= ob->sensors.first;
+ while(sens) {
+ names[nr++]= sens->name;
+ sens= sens->next;
+ }
+ cont= ob->controllers.first;
+ while(cont) {
+ names[nr++]= cont->name;
+ cont= cont->next;
+ }
+ act= ob->actuators.first;
+ while(act) {
+ names[nr++]= act->name;
+ act= act->next;
+ }
+ }
+
+ qsort(names, propcount, sizeof(void *), vergname);
+
+ /* now we check for double names, and change them */
+
+ for(nr=0; nr<propcount; nr++) {
+ if(names[nr]!=str && strcmp( names[nr], str )==0 ) {
+ BLI_newname(str, +1);
+ }
+ }
+
+ MEM_freeN(idar);
+ MEM_freeN(names);
+}
+
+static void make_unique_prop_names_cb(void *strv, void *redraw_view3d_flagv)
+{
+ char *str= strv;
+ int redraw_view3d_flag= (int) redraw_view3d_flagv;
+
+ make_unique_prop_names(str);
+ if (redraw_view3d_flag) allqueue(REDRAWVIEW3D, 0);
+}
+
+static void sca_move_sensor(void *datav, void *data2_unused)
+{
+ bSensor *sens_to_delete= datav;
+ int val;
+ Base *base;
+ bSensor *sens;
+
+ val= pupmenu("Move up%x1|Move down %x2");
+
+ if(val>0) {
+ /* now find out which object has this ... */
+ base= FIRSTBASE;
+ while(base) {
+
+ sens= base->object->sensors.first;
+ while(sens) {
+ if(sens == sens_to_delete) break;
+ sens= sens->next;
+ }
+
+ if(sens) {
+ if( val==1 && sens->prev) {
+ BLI_remlink(&base->object->sensors, sens);
+ BLI_insertlinkbefore(&base->object->sensors, sens->prev, sens);
+ }
+ else if( val==2 && sens->next) {
+ BLI_remlink(&base->object->sensors, sens);
+ BLI_insertlink(&base->object->sensors, sens->next, sens);
+ }
+ allqueue(REDRAWBUTSGAME, 0);
+ break;
+ }
+
+ base= base->next;
+ }
+ }
+}
+
+static void sca_move_controller(void *datav, void *data2_unused)
+{
+ bController *controller_to_del= datav;
+ int val;
+ Base *base;
+ bController *cont;
+
+ val= pupmenu("Move up%x1|Move down %x2");
+
+ if(val>0) {
+ /* now find out which object has this ... */
+ base= FIRSTBASE;
+ while(base) {
+
+ cont= base->object->controllers.first;
+ while(cont) {
+ if(cont == controller_to_del) break;
+ cont= cont->next;
+ }
+
+ if(cont) {
+ if( val==1 && cont->prev) {
+ BLI_remlink(&base->object->controllers, cont);
+ BLI_insertlinkbefore(&base->object->controllers, cont->prev, cont);
+ }
+ else if( val==2 && cont->next) {
+ BLI_remlink(&base->object->controllers, cont);
+ BLI_insertlink(&base->object->controllers, cont->next, cont);
+ }
+ allqueue(REDRAWBUTSGAME, 0);
+ break;
+ }
+
+ base= base->next;
+ }
+ }
+}
+
+static void sca_move_actuator(void *datav, void *data2_unused)
+{
+ bActuator *actuator_to_move= datav;
+ int val;
+ Base *base;
+ bActuator *act;
+
+ val= pupmenu("Move up%x1|Move down %x2");
+
+ if(val>0) {
+ /* now find out which object has this ... */
+ base= FIRSTBASE;
+ while(base) {
+
+ act= base->object->actuators.first;
+ while(act) {
+ if(act == actuator_to_move) break;
+ act= act->next;
+ }
+
+ if(act) {
+ if( val==1 && act->prev) {
+ BLI_remlink(&base->object->actuators, act);
+ BLI_insertlinkbefore(&base->object->actuators, act->prev, act);
+ }
+ else if( val==2 && act->next) {
+ BLI_remlink(&base->object->actuators, act);
+ BLI_insertlink(&base->object->actuators, act->next, act);
+ }
+ allqueue(REDRAWBUTSGAME, 0);
+ break;
+ }
+
+ base= base->next;
+ }
+ }
+}
+
+void do_gamebuts(unsigned short event)
+{
+ bProperty *prop;
+ bSensor *sens;
+ bController *cont;
+ bActuator *act;
+ Base *base;
+ Object *ob;
+ int didit;
+
+ ob= OBACT;
+ if(ob==0) return;
+
+ switch(event) {
+
+ case B_ADD_PROP:
+ prop= new_property(PROP_FLOAT);
+ make_unique_prop_names(prop->name);
+ BLI_addtail(&ob->prop, prop);
+ allqueue(REDRAWBUTSGAME, 0);
+ break;
+
+ case B_CHANGE_PROP:
+ prop= ob->prop.first;
+ while(prop) {
+ if(prop->type!=prop->otype) {
+ init_property(prop);
+ if (strcmp(prop->name, "Text") == 0) {
+ allqueue(REDRAWVIEW3D, 0);
+ }
+ }
+ prop= prop->next;
+ }
+ allqueue(REDRAWBUTSGAME, 0);
+ break;
+
+ case B_ADD_SENS:
+ base= FIRSTBASE;
+ while(base) {
+ if(base->object->scaflag & OB_ADDSENS) {
+ base->object->scaflag &= ~OB_ADDSENS;
+ sens= new_sensor(SENS_ALWAYS);
+ BLI_addtail(&(base->object->sensors), sens);
+ make_unique_prop_names(sens->name);
+ base->object->scaflag |= OB_SHOWSENS;
+ }
+ base= base->next;
+ }
+
+ allqueue(REDRAWBUTSGAME, 0);
+ break;
+
+ case B_CHANGE_SENS:
+ base= FIRSTBASE;
+ while(base) {
+ sens= base->object->sensors.first;
+ while(sens) {
+ if(sens->type != sens->otype) {
+ init_sensor(sens);
+ sens->otype= sens->type;
+ break;
+ }
+ sens= sens->next;
+ }
+ base= base->next;
+ }
+ allqueue(REDRAWBUTSGAME, 0);
+ break;
+
+ case B_DEL_SENS:
+ base= FIRSTBASE;
+ while(base) {
+ sens= base->object->sensors.first;
+ while(sens) {
+ if(sens->flag & SENS_DEL) {
+ BLI_remlink(&(base->object->sensors), sens);
+ free_sensor(sens);
+ break;
+ }
+ sens= sens->next;
+ }
+ base= base->next;
+ }
+ allqueue(REDRAWBUTSGAME, 0);
+ break;
+
+ case B_ADD_CONT:
+ base= FIRSTBASE;
+ while(base) {
+ if(base->object->scaflag & OB_ADDCONT) {
+ base->object->scaflag &= ~OB_ADDCONT;
+ cont= new_controller(CONT_LOGIC_AND);
+ make_unique_prop_names(cont->name);
+ base->object->scaflag |= OB_SHOWCONT;
+ BLI_addtail(&(base->object->controllers), cont);
+ }
+ base= base->next;
+ }
+ allqueue(REDRAWBUTSGAME, 0);
+ break;
+
+ case B_CHANGE_CONT:
+ base= FIRSTBASE;
+ while(base) {
+ cont= base->object->controllers.first;
+ while(cont) {
+ if(cont->type != cont->otype) {
+ init_controller(cont);
+ cont->otype= cont->type;
+ break;
+ }
+ cont= cont->next;
+ }
+ base= base->next;
+ }
+ allqueue(REDRAWBUTSGAME, 0);
+ break;
+
+
+ case B_DEL_CONT:
+ base= FIRSTBASE;
+ while(base) {
+ cont= base->object->controllers.first;
+ while(cont) {
+ if(cont->flag & CONT_DEL) {
+ BLI_remlink(&(base->object->controllers), cont);
+ unlink_controller(cont);
+ free_controller(cont);
+ break;
+ }
+ cont= cont->next;
+ }
+ base= base->next;
+ }
+ allqueue(REDRAWBUTSGAME, 0);
+ break;
+
+ case B_ADD_ACT:
+ base= FIRSTBASE;
+ while(base) {
+ if(base->object->scaflag & OB_ADDACT) {
+ base->object->scaflag &= ~OB_ADDACT;
+ act= new_actuator(ACT_OBJECT);
+ make_unique_prop_names(act->name);
+ BLI_addtail(&(base->object->actuators), act);
+ base->object->scaflag |= OB_SHOWACT;
+ }
+ base= base->next;
+ }
+ allqueue(REDRAWBUTSGAME, 0);
+ break;
+
+ case B_CHANGE_ACT:
+ base= FIRSTBASE;
+ while(base) {
+ act= base->object->actuators.first;
+ while(act) {
+ if(act->type != act->otype) {
+ init_actuator(act);
+ act->otype= act->type;
+ break;
+ }
+ act= act->next;
+ }
+ base= base->next;
+ }
+ allqueue(REDRAWBUTSGAME, 0);
+ break;
+
+ case B_DEL_ACT:
+ base= FIRSTBASE;
+ while(base) {
+ act= base->object->actuators.first;
+ while(act) {
+ if(act->flag & ACT_DEL) {
+ BLI_remlink(&(base->object->actuators), act);
+ unlink_actuator(act);
+ free_actuator(act);
+ break;
+ }
+ act= act->next;
+ }
+ base= base->next;
+ }
+ allqueue(REDRAWBUTSGAME, 0);
+ break;
+
+ case B_SOUNDACT_BROWSE:
+ /* since we don't know which... */
+ didit= 0;
+ base= FIRSTBASE;
+ while(base)
+ {
+ act= base->object->actuators.first;
+ while(act)
+ {
+ if(act->type==ACT_SOUND)
+ {
+ bSoundActuator *sa= act->data;
+ if(sa->sndnr)
+ {
+ bSound *sound= G.main->sound.first;
+ int nr= 1;
+
+ while(sound)
+ {
+ if(nr==sa->sndnr)
+ break;
+ nr++;
+ sound= sound->id.next;
+ }
+
+ if(sa->sound)
+ sa->sound->id.us--;
+
+ sa->sound= sound;
+
+ if(sound)
+ sound->id.us++;
+
+ sa->sndnr= 0;
+ didit= 1;
+ }
+ }
+ act= act->next;
+ }
+ if(didit)
+ break;
+ base= base->next;
+ }
+ allqueue(REDRAWBUTSGAME, 0);
+ allqueue(REDRAWSOUND, 0);
+
+ break;
+
+ }
+}
+
+
+static char *sensor_name(int type)
+{
+ switch (type) {
+ case SENS_ALWAYS:
+ return "Always";
+ case SENS_TOUCH:
+ return "Touch";
+ case SENS_NEAR:
+ return "Near";
+ case SENS_KEYBOARD:
+ return "Keyboard";
+ case SENS_PROPERTY:
+ return "Property";
+ case SENS_MOUSE:
+ return "Mouse";
+ case SENS_COLLISION:
+ return "Collision";
+ case SENS_RADAR:
+ return "Radar";
+ case SENS_RANDOM:
+ return "Random";
+ case SENS_RAY:
+ return "Ray";
+ case SENS_MESSAGE:
+ return "Message";
+ }
+ return "unknown";
+}
+
+static char *sensor_pup(void)
+{
+ /* the number needs to match defines in game.h */
+ return "Sensors %t|Always %x0|Keyboard %x3|Mouse %x5|"
+ "Touch %x1|Collision %x6|Near %x2|Radar %x7|"
+ "Property %x4|Random %x8|Ray %x9|Message %x10";
+}
+
+static char *controller_name(int type)
+{
+ switch (type) {
+ case CONT_LOGIC_AND:
+ return "AND";
+ case CONT_LOGIC_OR:
+ return "OR";
+ case CONT_EXPRESSION:
+ return "Expression";
+ case CONT_PYTHON:
+ return "Python";
+ }
+ return "unknown";
+}
+
+static char *controller_pup(void)
+{
+ return "Controllers %t|AND %x0|OR %x1|Expression %x2|Python %x3";
+}
+
+static char *actuator_name(int type)
+{
+ switch (type) {
+ case ACT_ACTION:
+ return "Action";
+ case ACT_OBJECT:
+ return "Motion";
+ case ACT_IPO:
+ return "Ipo";
+ case ACT_LAMP:
+ return "Lamp";
+ case ACT_CAMERA:
+ return "Camera";
+ case ACT_MATERIAL:
+ return "Material";
+ case ACT_SOUND:
+ return "Sound";
+ case ACT_CD:
+ return "CD";
+ case ACT_PROPERTY:
+ return "Property";
+ case ACT_EDIT_OBJECT:
+ return "Edit Object";
+ case ACT_CONSTRAINT:
+ return "Constraint";
+ case ACT_SCENE:
+ return "Scene";
+ case ACT_GROUP:
+ return "Group";
+ case ACT_RANDOM:
+ return "Random";
+ case ACT_MESSAGE:
+ return "Message";
+ case ACT_GAME:
+ return "Game";
+ case ACT_VISIBILITY:
+ return "Game";
+ }
+ return "unknown";
+}
+
+
+
+
+static char *actuator_pup(Object *owner)
+{
+ if (LICENSE_KEY_VALID)
+ {
+ switch (owner->type)
+ {
+ case OB_ARMATURE:
+ return "Actuators %t|Action %x15|Motion %x0|Constraint %x9|Ipo %x1"
+ "|Camera %x3|Sound %x5|Property %x6|Edit Object %x10"
+ "|Scene %x11|Random %x13|Message %x14|CD %x16|Game %x17"
+ "|Visibility %x18";
+ break;
+ default:
+ return "Actuators %t|Motion %x0|Constraint %x9|Ipo %x1"
+ "|Camera %x3|Sound %x5|Property %x6|Edit Object %x10"
+ "|Scene %x11|Random %x13|Message %x14|CD %x16|Game %x17"
+ "|Visibility %x18";
+ }
+ }
+ else
+ {
+ switch (owner->type)
+ {
+ case OB_ARMATURE:
+ return "Actuators %t|Action %x15|Motion %x0|Constraint %x9|Ipo %x1"
+ "|Camera %x3|Sound %x5|Property %x6|Edit Object %x10"
+ "|Scene %x11|Random %x13|Message %x14|Visibility %x18";
+ break;
+ default:
+ return "Actuators %t|Motion %x0|Constraint %x9|Ipo %x1"
+ "|Camera %x3|Sound %x5|Property %x6|Edit Object %x10"
+ "|Scene %x11|Random %x13|Message %x14|Visibility %x18";
+ }
+ }
+
+}
+
+
+
+static void set_sca_ob(Object *ob)
+{
+ bController *cont;
+ bActuator *act;
+
+ cont= ob->controllers.first;
+ while(cont) {
+ cont->mynew= (bController *)ob;
+ cont= cont->next;
+ }
+ act= ob->actuators.first;
+ while(act) {
+ act->mynew= (bActuator *)ob;
+ act= act->next;
+ }
+}
+
+static ID **get_selected_and_linked_obs(short *count, short scavisflag)
+{
+ Base *base;
+ Object *ob, *obt;
+ ID **idar;
+ bSensor *sens;
+ bController *cont;
+ unsigned int lay;
+ int a, nr, doit;
+
+ /* we need a sorted object list */
+ /* set scavisflags flags in Objects to indicate these should be evaluated */
+ /* also hide ob pointers in ->new entries of controllerss/actuators */
+
+ *count= 0;
+
+ if(G.scene==NULL) return NULL;
+
+ ob= G.main->object.first;
+ while(ob) {
+ ob->scavisflag= 0;
+ set_sca_ob(ob);
+ ob= ob->id.next;
+ }
+
+ if(G.vd) lay= G.vd->lay;
+ else lay= G.scene->lay;
+
+ base= FIRSTBASE;
+ while(base) {
+ if(base->lay & lay) {
+ if(base->flag & SELECT) {
+ if(scavisflag & BUTS_SENS_SEL) base->object->scavisflag |= OB_VIS_SENS;
+ if(scavisflag & BUTS_CONT_SEL) base->object->scavisflag |= OB_VIS_CONT;
+ if(scavisflag & BUTS_ACT_SEL) base->object->scavisflag |= OB_VIS_ACT;
+ }
+ }
+ base= base->next;
+ }
+
+ if(OBACT) {
+ if(scavisflag & BUTS_SENS_ACT) OBACT->scavisflag |= OB_VIS_SENS;
+ if(scavisflag & BUTS_CONT_ACT) OBACT->scavisflag |= OB_VIS_CONT;
+ if(scavisflag & BUTS_ACT_ACT) OBACT->scavisflag |= OB_VIS_ACT;
+ }
+
+ if(scavisflag & (BUTS_SENS_LINK|BUTS_CONT_LINK|BUTS_ACT_LINK)) {
+ doit= 1;
+ while(doit) {
+ doit= 0;
+
+ ob= G.main->object.first;
+ while(ob) {
+
+ /* 1st case: select sensor when controller selected */
+ if((scavisflag & BUTS_SENS_LINK) && (ob->scavisflag & OB_VIS_SENS)==0) {
+ sens= ob->sensors.first;
+ while(sens) {
+ for(a=0; a<sens->totlinks; a++) {
+ if(sens->links[a]) {
+ obt= (Object *)sens->links[a]->mynew;
+ if(obt && (obt->scavisflag & OB_VIS_CONT)) {
+ doit= 1;
+ ob->scavisflag |= OB_VIS_SENS;
+ break;
+ }
+ }
+ }
+ if(doit) break;
+ sens= sens->next;
+ }
+ }
+
+ /* 2nd case: select cont when act selected */
+ if((scavisflag & BUTS_CONT_LINK) && (ob->scavisflag & OB_VIS_CONT)==0) {
+ cont= ob->controllers.first;
+ while(cont) {
+ for(a=0; a<cont->totlinks; a++) {
+ if(cont->links[a]) {
+ obt= (Object *)cont->links[a]->mynew;
+ if(obt && (obt->scavisflag & OB_VIS_ACT)) {
+ doit= 1;
+ ob->scavisflag |= OB_VIS_CONT;
+ break;
+ }
+ }
+ }
+ if(doit) break;
+ cont= cont->next;
+ }
+ }
+
+ /* 3rd case: select controller when sensor selected */
+ if((scavisflag & BUTS_CONT_LINK) && (ob->scavisflag & OB_VIS_SENS)) {
+ sens= ob->sensors.first;
+ while(sens) {
+ for(a=0; a<sens->totlinks; a++) {
+ if(sens->links[a]) {
+ obt= (Object *)sens->links[a]->mynew;
+ if(obt && (obt->scavisflag & OB_VIS_CONT)==0) {
+ doit= 1;
+ obt->scavisflag |= OB_VIS_CONT;
+ }
+ }
+ }
+ sens= sens->next;
+ }
+ }
+
+ /* 4th case: select actuator when controller selected */
+ if( (scavisflag & BUTS_ACT_LINK) && (ob->scavisflag & OB_VIS_CONT)) {
+ cont= ob->controllers.first;
+ while(cont) {
+ for(a=0; a<cont->totlinks; a++) {
+ if(cont->links[a]) {
+ obt= (Object *)cont->links[a]->mynew;
+ if(obt && (obt->scavisflag & OB_VIS_ACT)==0) {
+ doit= 1;
+ obt->scavisflag |= OB_VIS_ACT;
+ }
+ }
+ }
+ cont= cont->next;
+ }
+
+ }
+ ob= ob->id.next;
+ }
+ }
+ }
+
+ /* now we count */
+ ob= G.main->object.first;
+ while(ob) {
+ if( ob->scavisflag ) (*count)++;
+ ob= ob->id.next;
+ }
+
+ if(*count==0) return NULL;
+ if(*count>24) *count= 24; /* temporal */
+
+ idar= MEM_callocN( (*count)*sizeof(void *), "idar");
+
+ ob= G.main->object.first;
+ nr= 0;
+ while(ob) {
+ if( ob->scavisflag ) {
+ idar[nr]= (ID *)ob;
+ nr++;
+ }
+ if(nr>=24) break;
+ ob= ob->id.next;
+ }
+
+ /* just to be sure... these were set in set_sca_done_ob() */
+ clear_sca_new_poins();
+
+ return idar;
+}
+
+
+static BIFColorID get_col_sensor(int type)
+{
+ switch(type) {
+ case SENS_ALWAYS: return BUTACTION;
+ case SENS_TOUCH: return BUTCAMERA;
+ case SENS_COLLISION: return BUTCAMERA;
+ case SENS_NEAR: return BUTRANDOM;
+ case SENS_KEYBOARD: return BUTIPO;
+ case SENS_PROPERTY: return BUTPROPERTY;
+ case SENS_MOUSE: return BUTAUDIO;
+ case SENS_RADAR: return BUTEDITOBJECT;
+ case SENS_RANDOM: return BUTSCENE;
+ case SENS_RAY: return BUTMOTION;
+ case SENS_MESSAGE: return BUTMESSAGE;
+ default: return BUTGREY;
+ }
+}
+static void set_col_sensor(int type, int medium)
+{
+ BIFColorID col= get_col_sensor(type);
+ BIF_set_color(col, medium?COLORSHADE_MEDIUM:COLORSHADE_GREY);
+}
+
+/**
+ * Draws a toggle for pulse mode, a frequency fiels and a toggle to invert
+ * the value of this sensor. Operates on the shared data block of sensors.
+ */
+static void draw_default_sensor_header(bSensor *sens,
+ uiBlock *block,
+ short x,
+ short y,
+ short w)
+{
+ /* Pulsing and frequency */
+ uiDefIconButS(block, TOG|BIT|0, 1, ICON_DOTSUP,
+ (short)(x + 10), (short)(y - 19), (short)(0.15 * (w-20)), 19,
+ &sens->pulse, 0.0, 0.0, 0, 0,
+ "Activate TRUE pulse mode");
+ uiDefIconButS(block, TOG|BIT|2, 1, ICON_DOTSDOWN,
+ (short)(x + 10 + 0.15 * (w-20)), (short)(y - 19), (short)(0.15 * (w-20)), 19,
+ &sens->pulse, 0.0, 0.0, 0, 0,
+ "Activate FALSE pulse mode");
+ uiDefButS(block, NUM, 1, "f:",
+ (short)(x + 10 + 0.3 * (w-20)), (short)(y - 19), (short)(0.275 * (w-20)), 19,
+ &sens->freq, 0.0, 10000.0, 0, 0,
+ "Frequency of pulses (in 1/50 sec)");
+
+ /* value or shift? */
+ uiDefButS(block, TOG, 1, "Inv",
+ (short)(x + 10 + 0.85 * (w-20)), (short)(y - 19), (short)(0.15 * (w-20)), 19,
+ &sens->invert, 1.0, SENS_NOT, 0, 0,
+ "Invert the output of this sensor");
+}
+
+static short draw_sensorbuttons(bSensor *sens, uiBlock *block, short xco, short yco, short width,char* objectname)
+{
+ bNearSensor *ns = NULL;
+ bTouchSensor *ts = NULL;
+ bKeyboardSensor *ks = NULL;
+ bPropertySensor *ps = NULL;
+ bMouseSensor *ms = NULL;
+ bCollisionSensor *cs = NULL;
+ bRadarSensor *rs = NULL;
+ bRandomSensor *randomSensor = NULL;
+ bRaySensor *raySens = NULL;
+ bMessageSensor *mes = NULL;
+ short ysize;
+ char *str;
+
+ /* yco is at the top of the rect, draw downwards */
+
+ uiBlockSetEmboss(block, UI_EMBOSSW);
+
+ set_col_sensor(sens->type, 0);
+
+ switch (sens->type)
+ {
+ case SENS_ALWAYS:
+ {
+ ysize= 24;
+
+ glRects(xco, yco-ysize, xco+width, yco);
+ uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
+
+ draw_default_sensor_header(sens, block, xco, yco, width);
+
+ yco-= ysize;
+
+ break;
+ }
+ case SENS_TOUCH:
+ {
+ ysize= 48;
+
+ glRects(xco, yco-ysize, xco+width, yco);
+ uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
+
+ draw_default_sensor_header(sens, block, xco, yco, width);
+
+ ts= sens->data;
+
+ /* uiDefBut(block, TEX, 1, "Property:", xco,yco-22,width, 19, &ts->name, 0, 31, 0, 0, "Only look for Objects with this property"); */
+ uiDefIDPoinBut(block, test_matpoin_but, 1, "MA:",(short)(xco + 10),(short)(yco-44), (short)(width - 20), 19, &ts->ma, "Only look for floors with this Material");
+ ///* uiDefButF(block, NUM, 1, "Margin:", xco+width/2,yco-44,width/2, 19, &ts->dist, 0.0, 10.0, 100, 0, "Extra margin (distance) for larger sensitivity");
+ yco-= ysize;
+ break;
+ }
+ case SENS_COLLISION:
+ {
+ ysize= 48;
+
+ glRects(xco, yco-ysize, xco+width, yco);
+ uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
+
+ draw_default_sensor_header(sens, block, xco, yco, width);
+ cs= sens->data;
+
+ /* The collision sensor will become a generic collision (i.e. it */
+ /* absorb the old touch sensor). */
+ uiDefButS(block, TOG|BIT|0, B_REDR, "M/P",(short)(xco + 10),(short)(yco - 44),
+ (short)(0.20 * (width-20)), 19, &cs->mode, 0.0, 0.0, 0, 0,
+ "Toggle collision on material or property.");
+
+ if (cs->mode & SENS_COLLISION_MATERIAL) {
+ uiDefBut(block, TEX, 1, "Material:", (short)(xco + 10 + 0.20 * (width-20)),
+ (short)(yco-44), (short)(0.8*(width-20)), 19, &cs->materialName, 0, 31, 0, 0,
+ "Only look for Objects with this material");
+ } else {
+ uiDefBut(block, TEX, 1, "Property:", (short)(xco + 10 + 0.20 * (width-20)), (short)(yco-44),
+ (short)(0.8*(width-20)), 19, &cs->name, 0, 31, 0, 0,
+ "Only look for Objects with this property");
+ }
+
+ /* uiDefButS(block, NUM, 1, "Damp:", xco+10+width-90,yco-24, 70, 19, &cs->damp, 0, 250, 0, 0, "For 'damp' time don't detect another collision"); */
+
+ yco-= ysize;
+ break;
+ }
+ case SENS_NEAR:
+ {
+ ysize= 72;
+
+ glRects(xco, yco-ysize, xco+width, yco);
+ uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
+
+ draw_default_sensor_header(sens, block, xco, yco, width);
+ ns= sens->data;
+
+ uiDefBut(block, TEX, 1, "Property:",(short)(10+xco),(short)(yco-44), (short)(width-20), 19,
+ &ns->name, 0, 31, 0, 0, "Only look for Objects with this property");
+ uiDefButF(block, NUM, 1, "Dist",(short)(10+xco),(short)(yco-68),(short)((width-22)/2), 19,
+ &ns->dist, 0.0, 1000.0, 1000, 0, "Trigger distance");
+ uiDefButF(block, NUM, 1, "Reset",(short)(10+xco+(width-22)/2), (short)(yco-68), (short)((width-22)/2), 19,
+ &ns->resetdist, 0.0, 1000.0, 1000, 0, "Reset distance");
+ yco-= ysize;
+ break;
+ }
+ case SENS_RADAR:
+ {
+ ysize= 72;
+
+ glRects(xco, yco-ysize, xco+width, yco);
+ uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
+
+ draw_default_sensor_header(sens, block, xco, yco, width);
+
+ rs= sens->data;
+
+ uiDefBut(block, TEX, 1, "Prop:",
+ (short)(10+xco),(short)(yco-44), (short)(0.7 * (width-20)), 19,
+ &rs->name, 0, 31, 0, 0,
+ "Only look for Objects with this property");
+ uiDefButS(block, ROW, 1, "X",
+ (short)(10+xco+0.7 * (width-20)),(short)(yco-44), (short)(0.1 * (width-22)),19,
+ &rs->axis, 2.0, 0, 0, 0,
+ "Cast the cone along the object's positive x-axis");
+ uiDefButS(block, ROW, 1, "Y",
+ (short)(10+xco+0.8 * (width-20)),(short)(yco-44),(short)(0.1 * (width-22)), 19,
+ &rs->axis, 2.0, 1, 0, 0,
+ "Cast the cone along the object's positive y-axis");
+ uiDefButS(block, ROW, 1, "Z",
+ (short)(10+xco+0.9 * (width-20)), (short)(yco-44), (short)(0.1 * (width-22)), 19,
+ &rs->axis, 2.0, 2, 0, 0,
+ "Cast the cone along the object's positive z-axis");
+ uiDefButF(block, NUM, 1, "Ang:",
+ (short)(10+xco), (short)(yco-68), (short)((width-20)/2), 19,
+ &rs->angle, 0.0, 179.9, 10, 0,
+ "Opening angle of the radar cone.");
+ uiDefButF(block, NUM, 1, "Dist:",
+ (short)(xco+10 + (width-20)/2), (short)(yco-68), (short)((width-20)/2), 19,
+ &rs->range, 0.01, 10000.0, 100, 0,
+ "Depth of the radar cone");
+ yco-= ysize;
+ break;
+ }
+ case SENS_KEYBOARD:
+ {
+ /* 5 lines: 120 height */
+ ysize= 120;
+
+ glRects(xco, yco-ysize, xco+width, yco);
+ uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
+
+ /* header line */
+ draw_default_sensor_header(sens, block, xco, yco, width);
+ ks= sens->data;
+
+ /* line 2: hotkey and allkeys toggle */
+ uiDefKeyevtButS(block, B_DIFF, "", xco+40, yco-44, (width)/2, 19, &ks->key, "Key code");
+
+ /* line 3: two key modifyers (qual1, qual2) */
+ uiDefKeyevtButS(block, B_DIFF, "", xco+40, yco-68, (width-50)/2, 19, &ks->qual, "Modifier key code");
+ uiDefKeyevtButS(block, B_DIFF, "", xco+40+(width-50)/2, yco-68, (width-50)/2, 19, &ks->qual2, "Second Modifier key code");
+
+ /* labels for line 1 and 2 */
+ uiDefBut(block, LABEL, 0, "Key", xco, yco-44, 40, 19, NULL, 0, 0, 0, 0, "");
+ uiDefBut(block, LABEL, 0, "Hold", xco, yco-68, 40, 19, NULL, 0, 0, 0, 0, "");
+
+ /* part of line 1 */
+ uiBlockSetCol(block, BUTPURPLE);
+ uiDefButS(block, TOG|BIT|0, 0, "All keys", xco+40+(width/2), yco-44, (width/2)-50, 19,
+ &ks->type, 0, 0, 0, 0, "");
+
+ /* line 4: toggle property for string logging mode */
+ uiDefBut(block, TEX, 1, "LogToggle: ",
+ xco+10, yco-92, (width-20), 19,
+ ks->toggleName, 0, 31, 0, 0,
+ "Property that indicates whether to log "
+ "keystrokes as a string.");
+
+ /* line 5: target property for string logging mode */
+ uiDefBut(block, TEX, 1, "Target: ",
+ xco+10, yco-116, (width-20), 19,
+ ks->targetName, 0, 31, 0, 0,
+ "Property that receives the keystrokes in case "
+ "a string is logged.");
+
+ yco-= ysize;
+ break;
+ }
+ case SENS_PROPERTY:
+ {
+ ysize= 96;
+
+ glRects(xco, yco-ysize, xco+width, yco);
+ uiEmboss((float)xco, (float)yco-ysize,
+ (float)xco+width, (float)yco, 1);
+
+ draw_default_sensor_header(sens, block, xco, yco, width);
+ ps= sens->data;
+
+ str= "Type %t|Equal %x0|Not Equal %x1|Interval %x2|Changed %x3";
+ /* str= "Type %t|Equal %x0|Not Equal %x1"; */
+ uiDefButI(block, MENU, B_REDR, str, xco+30,yco-44,width-60, 19,
+ &ps->type, 0, 31, 0, 0, "Type");
+
+ if (ps->type != SENS_PROP_EXPRESSION)
+ {
+ uiDefBut(block, TEX, 1, "Prop: ", xco+30,yco-68,width-60, 19,
+ ps->name, 0, 31, 0, 0, "Property name");
+ }
+
+ if(ps->type == SENS_PROP_INTERVAL)
+ {
+ uiDefBut(block, TEX, 1, "Min: ", xco,yco-92,width/2, 19,
+ ps->value, 0, 31, 0, 0, "test for value");
+ uiDefBut(block, TEX, 1, "Max: ", xco+width/2,yco-92,width/2, 19,
+ ps->maxvalue, 0, 31, 0, 0, "test for max value");
+ }
+ else if(ps->type == SENS_PROP_CHANGED);
+ else
+ {
+ uiDefBut(block, TEX, 1, "Value: ", xco+30,yco-92,width-60, 19,
+ ps->value, 0, 31, 0, 0, "test for value");
+ }
+
+ yco-= ysize;
+ break;
+ }
+ case SENS_MOUSE:
+ {
+ ms= sens->data;
+ /* Two lines: 48 pixels high. */
+ ysize = 48;
+
+ glRects(xco, yco-ysize, xco+width, yco);
+ uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
+
+ /* line 1: header */
+ draw_default_sensor_header(sens, block, xco, yco, width);
+
+ /* Line 2: type selection. The number are a bit mangled to get
+ * proper compatibility with older .blend files. */
+ str= "Type %t|Left button %x1|Middle button %x2|"
+ "Right button %x4|Movement %x8|Mouse over %x16";
+ uiDefButS(block, MENU, B_REDR, str, xco+10, yco-44, width-20, 19,
+ &ms->type, 0, 31, 0, 0,
+ "Specify the type of event this mouse sensor should trigger on.");
+
+ yco-= ysize;
+ break;
+ }
+ case SENS_RANDOM:
+ {
+ ysize = 48;
+
+ glRects(xco, yco-ysize, xco+width, yco);
+ uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
+
+ draw_default_sensor_header(sens, block, xco, yco, width);
+ randomSensor = sens->data;
+ /* some files were wrongly written, avoid crash now */
+ if (randomSensor)
+ {
+ uiDefButI(block, NUM, 1, "Seed: ", xco+10,yco-44,(width-20), 19,
+ &randomSensor->seed, 0, 1000, 0, 0,
+ "Initial seed of the generator. (Choose 0 for not random)");
+ }
+ yco-= ysize;
+ break;
+ }
+ case SENS_RAY:
+ {
+ ysize = 72;
+ glRects(xco, yco-ysize, xco+width, yco);
+ uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
+
+ draw_default_sensor_header(sens, block, xco, yco, width);
+ raySens = sens->data;
+
+ /* 1. property or material */
+ uiDefButS(block, TOG|BIT|0, B_REDR, "M/P",
+ xco + 10,yco - 44, 0.20 * (width-20), 19,
+ &raySens->mode, 0.0, 0.0, 0, 0,
+ "Toggle collision on material or property.");
+
+ if (raySens->mode & SENS_COLLISION_MATERIAL)
+ {
+ uiDefBut(block, TEX, 1, "Material:", xco + 10 + 0.20 * (width-20), yco-44, 0.8*(width-20), 19,
+ &raySens->matname, 0, 31, 0, 0,
+ "Only look for Objects with this material");
+ }
+ else
+ {
+ uiDefBut(block, TEX, 1, "Property:", xco + 10 + 0.20 * (width-20), yco-44, 0.8*(width-20), 19,
+ &raySens->propname, 0, 31, 0, 0,
+ "Only look for Objects with this property");
+ }
+
+ /* 2. sensing range */
+ uiDefButF(block, NUM, 1, "Range", xco+10, yco-68, 0.6 * (width-20), 19,
+ &raySens->range, 0.01, 10000.0, 100, 0,
+ "Sense objects no farther than this distance");
+
+ /* 3. axis choice */
+ str = "Type %t|+ X axis %x1|+ Y axis %x0|+ Z axis %x2|- X axis %x3|- Y axis %x4|- Z axis %x5";
+ uiDefButI(block, MENU, B_REDR, str, xco+10 + 0.6 * (width-20), yco-68, 0.4 * (width-20), 19,
+ &raySens->axisflag, 2.0, 31, 0, 0,
+ "Specify along which axis the ray is cast.");
+
+ yco-= ysize;
+ break;
+ }
+ case SENS_MESSAGE:
+ {
+ mes = sens->data;
+ ysize = 2 * 24; /* total number of lines * 24 pixels/line */
+
+ glRects(xco, yco-ysize, xco+width, yco);
+ uiEmboss((float)xco, (float)yco-ysize,
+ (float)xco+width, (float)yco, 1);
+
+ /* line 1: header line */
+ draw_default_sensor_header(sens, block, xco, yco, width);
+
+ /* line 2: Subject filter */
+ uiDefBut(block, TEX, 1, "Subject: ",
+ (xco+10), (yco-44), (width-20), 19,
+ mes->subject, 0, 31, 0, 0,
+ "Optional subject filter: only accept messages with this subject"
+ ", or empty for all");
+
+ yco -= ysize;
+ break;
+ }
+ }
+
+ uiBlockSetEmboss(block, UI_EMBOSSM);
+ uiBlockSetCol(block, BUTGREY);
+
+ return yco-4;
+}
+
+
+
+static short draw_controllerbuttons(bController *cont, uiBlock *block, short xco, short yco, short width)
+{
+ bExpressionCont *ec;
+ bPythonCont *pc;
+ short ysize;
+
+ uiBlockSetEmboss(block, UI_EMBOSSW);
+
+ switch (cont->type) {
+ case CONT_EXPRESSION:
+ ysize= 28;
+
+ BIF_set_color(BUTPROPERTY, COLORSHADE_GREY);
+ glRects(xco, yco-ysize, xco+width, yco);
+ uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
+
+ /* uiDefBut(block, LABEL, 1, "Not yet...", xco,yco-24,80, 19, NULL, 0, 0, 0, 0, ""); */
+ ec= cont->data;
+ /* uiDefBut(block, BUT, 1, "Variables", xco,yco-24,80, 19, NULL, 0, 0, 0, 0, "Available variables for expression"); */
+ uiDefBut(block, TEX, 1, "Exp:", xco + 10 , yco-21, width-20, 19,
+ ec->str, 0, 127, 0, 0,
+ "Expression");
+
+ yco-= ysize;
+ break;
+ case CONT_PYTHON:
+ ysize= 28;
+
+ if(cont->data==NULL) init_controller(cont);
+ pc= cont->data;
+
+ BIF_set_color(BUTMESSAGE, COLORSHADE_GREY);
+ glRects(xco, yco-ysize, xco+width, yco);
+ uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
+
+ uiDefIDPoinBut(block, test_scriptpoin_but, 1, "Script: ", xco+45,yco-24,width-90, 19, &pc->text, "");
+
+ yco-= ysize;
+ break;
+
+ default:
+ ysize= 4;
+
+ BIF_set_color(BUTIPO, COLORSHADE_GREY);
+ glRects(xco, yco-ysize, xco+width, yco);
+ uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
+
+ yco-= ysize;
+ }
+
+ uiBlockSetEmboss(block, UI_EMBOSSM);
+ uiBlockSetCol(block, BUTGREY);
+
+ return yco;
+}
+
+static BIFColorID get_col_actuator(int type)
+{
+ switch(type) {
+ case ACT_ACTION: return BUTACTION;
+ case ACT_OBJECT: return BUTMOTION;
+ case ACT_IPO: return BUTIPO;
+ case ACT_PROPERTY: return BUTPROPERTY;
+ case ACT_SOUND: return BUTAUDIO;
+ case ACT_CD: return BUTCD;
+ case ACT_CAMERA: return BUTCAMERA;
+ case ACT_EDIT_OBJECT: return BUTEDITOBJECT;
+ case ACT_GROUP: return BUTYELLOW;
+ case ACT_RANDOM: return BUTRANDOM;
+ case ACT_SCENE: return BUTSCENE;
+ case ACT_MESSAGE: return BUTMESSAGE;
+ case ACT_GAME: return BUTGAME;
+ case ACT_VISIBILITY: return BUTVISIBILITY;
+ default: return BUTGREY;
+ }
+}
+static void set_col_actuator(int item, int medium)
+{
+ if (item==ACT_CONSTRAINT) {
+ BIF_set_color(BUTRUST, medium?COLORSHADE_HILITE:COLORSHADE_MEDIUM);
+ } else {
+ BIFColorID col= get_col_actuator(item);
+ BIF_set_color(col, medium?COLORSHADE_MEDIUM:COLORSHADE_GREY);
+ }
+}
+
+static short draw_actuatorbuttons(bActuator *act, uiBlock *block, short xco, short yco, short width)
+{
+ bSoundActuator *sa = NULL;
+ bCDActuator *cda = NULL;
+ bObjectActuator *oa = NULL;
+ bIpoActuator *ia = NULL;
+ bPropertyActuator *pa = NULL;
+ bCameraActuator *ca = NULL;
+ bEditObjectActuator *eoa = NULL;
+ bConstraintActuator *coa = NULL;
+ bSceneActuator *sca = NULL;
+ bGroupActuator *ga = NULL;
+ bRandomActuator *randAct = NULL;
+ bMessageActuator *ma = NULL;
+ bActionActuator *aa = NULL;
+ bGameActuator *gma = NULL;
+ bVisibilityActuator *visAct = NULL;
+
+ float *fp;
+ short ysize = 0, wval;
+ char *str;
+ int myline;
+
+ /* yco is at the top of the rect, draw downwards */
+ uiBlockSetEmboss(block, UI_EMBOSSW);
+ set_col_actuator(act->type, 0);
+
+ switch (act->type)
+ {
+ case ACT_OBJECT:
+ {
+ ysize= 129;
+
+ glRects(xco, yco-ysize, xco+width, yco);
+ uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
+ uiBlockSetCol(block, BUTGREY);
+
+ oa = act->data;
+ wval = (width-100)/3;
+
+ uiDefBut(block, LABEL, 0, "Force", xco, yco-22, 55, 19, NULL, 0, 0, 0, 0, "Sets the force");
+ uiDefButF(block, NUM, 0, "", xco+45, yco-22, wval, 19, oa->forceloc, -10000.0, 10000.0, 10, 0, "");
+ uiDefButF(block, NUM, 0, "", xco+45+wval, yco-22, wval, 19, oa->forceloc+1, -10000.0, 10000.0, 10, 0, "");
+ uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-22, wval, 19, oa->forceloc+2, -10000.0, 10000.0, 10, 0, "");
+
+ uiDefBut(block, LABEL, 0, "Torque", xco, yco-41, 55, 19, NULL, 0, 0, 0, 0, "Sets the torque");
+ uiDefButF(block, NUM, 0, "", xco+45, yco-41, wval, 19, oa->forcerot, -10000.0, 10000.0, 10, 0, "");
+ uiDefButF(block, NUM, 0, "", xco+45+wval, yco-41, wval, 19, oa->forcerot+1, -10000.0, 10000.0, 10, 0, "");
+ uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-41, wval, 19, oa->forcerot+2, -10000.0, 10000.0, 10, 0, "");
+
+ uiDefBut(block, LABEL, 0, "dLoc", xco, yco-64, 45, 19, NULL, 0, 0, 0, 0, "Sets the dLoc");
+ uiDefButF(block, NUM, 0, "", xco+45, yco-64, wval, 19, oa->dloc, -10000.0, 10000.0, 10, 0, "");
+ uiDefButF(block, NUM, 0, "", xco+45+wval, yco-64, wval, 19, oa->dloc+1, -10000.0, 10000.0, 10, 0, "");
+ uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-64, wval, 19, oa->dloc+2, -10000.0, 10000.0, 10, 0, "");
+
+ uiDefBut(block, LABEL, 0, "dRot", xco, yco-83, 45, 19, NULL, 0, 0, 0, 0, "Sets the dRot");
+ uiDefButF(block, NUM, 0, "", xco+45, yco-83, wval, 19, oa->drot, -10000.0, 10000.0, 10, 0, "");
+ uiDefButF(block, NUM, 0, "", xco+45+wval, yco-83, wval, 19, oa->drot+1, -10000.0, 10000.0, 10, 0, "");
+ uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-83, wval, 19, oa->drot+2, -10000.0, 10000.0, 10, 0, "");
+
+ uiDefBut(block, LABEL, 0, "linV", xco, yco-106, 45, 19, NULL, 0, 0, 0, 0, "Sets the linear velocity");
+ uiDefButF(block, NUM, 0, "", xco+45, yco-106, wval, 19, oa->linearvelocity, -10000.0, 10000.0, 10, 0, "");
+ uiDefButF(block, NUM, 0, "", xco+45+wval, yco-106, wval, 19, oa->linearvelocity+1, -10000.0, 10000.0, 10, 0, "");
+ uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-106, wval, 19, oa->linearvelocity+2, -10000.0, 10000.0, 10, 0, "");
+
+ uiDefBut(block, LABEL, 0, "angV", xco, yco-125, 45, 19, NULL, 0, 0, 0, 0, "Sets the angular velocity");
+ uiDefButF(block, NUM, 0, "", xco+45, yco-125, wval, 19, oa->angularvelocity, -10000.0, 10000.0, 10, 0, "");
+ uiDefButF(block, NUM, 0, "", xco+45+wval, yco-125, wval, 19, oa->angularvelocity+1, -10000.0, 10000.0, 10, 0, "");
+ uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-125, wval, 19, oa->angularvelocity+2, -10000.0, 10000.0, 10, 0, "");
+
+ uiBlockSetCol(block, BUTGREEN);
+ uiDefButI(block, TOG|BIT|0, 0, "L", xco+45+3*wval, yco-22, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Local transformation");
+ uiDefButI(block, TOG|BIT|1, 0, "L", xco+45+3*wval, yco-41, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Local transformation");
+ uiDefButI(block, TOG|BIT|2, 0, "L", xco+45+3*wval, yco-64, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Local transformation");
+ uiDefButI(block, TOG|BIT|3, 0, "L", xco+45+3*wval, yco-83, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Local transformation");
+ uiDefButI(block, TOG|BIT|4, 0, "L", xco+45+3*wval, yco-106, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Local transformation");
+ uiDefButI(block, TOG|BIT|5, 0, "L", xco+45+3*wval, yco-125, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Local transformation");
+
+ uiBlockSetCol(block, BUTGREEN);
+ uiDefButI(block, TOG|BIT|6, 0, "add",xco+45+3*wval+15, yco-106, 35, 19, &oa->flag, 0.0, 0.0, 0, 0, "Toggles between ADD and SET linV");
+ uiBlockSetCol(block, BUTGREY);
+
+ yco-= ysize;
+ break;
+ }
+ case ACT_ACTION:
+ {
+ /* DrawAct */
+#ifdef __NLA_ACTION_BY_MOTION_ACTUATOR
+ ysize = 112;
+#else
+ ysize= 92;
+#endif
+
+ glRects(xco, yco-ysize, xco+width, yco);
+ uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
+
+ aa = act->data;
+ wval = (width-60)/3;
+
+ uiBlockSetCol(block, BUTGREY);
+ // str= "Action types %t|Play %x0|Ping Pong %x1|Flipper %x2|Loop Stop %x3|Loop End %x4|Property %x6";
+#ifdef __NLA_ACTION_BY_MOTION_ACTUATOR
+ str= "Action types %t|Play %x0|Flipper %x2|Loop Stop %x3|Loop End %x4|Property %x6|Displacement %x7";
+#else
+ str= "Action types %t|Play %x0|Flipper %x2|Loop Stop %x3|Loop End %x4|Property %x6";
+#endif
+ uiDefButS(block, MENU, B_REDR, str, xco+30, yco-24, width-60, 19, &aa->type, 0.0, 0.0, 0.0, 0.0, "Action playback type");
+ uiDefIDPoinBut(block, test_actionpoin_but, 1, "AC: ", xco+30, yco-44, width-60, 19, &aa->act, "Action name");
+
+ if(aa->type == ACT_ACTION_FROM_PROP)
+ {
+ uiDefBut(block, TEX, 0, "Prop: ",xco+30, yco-64, width-60, 19, aa->name, 0.0, 31.0, 0, 0, "Use this property to define the Action position");
+ }
+ else
+ {
+ uiDefButS(block, NUM, 0, "Sta: ",xco+30, yco-64, (width-60)/2, 19, &aa->sta, 0.0, 18000.0, 0, 0, "Start frame");
+ uiDefButS(block, NUM, 0, "End: ",xco+30+(width-60)/2, yco-64, (width-60)/2, 19, &aa->end, 0.0, 18000.0, 0, 0, "End frame");
+ }
+
+
+
+ uiDefButS(block, NUM, 0, "Blendin: ", xco+30, yco-84, (width-60)/2, 19, &aa->blendin, 0.0, 18000.0, 0.0, 0.0, "Number of frames of motion blending");
+ uiDefButS(block, NUM, 0, "Priority: ", xco+30+(width-60)/2, yco-84, (width-60)/2, 19, &aa->priority, 0.0, 100.0, 0.0, 0.0, "Execution priority - lower numbers will override actions with higher numbers");
+
+#ifdef __NLA_ACTION_BY_MOTION_ACTUATOR
+ if(aa->type == ACT_ACTION_MOTION)
+ {
+ uiDefButF(block, NUM, 0, "Cycle: ",xco+30, yco-104, (width-60)/2, 19, &aa->stridelength, 0.0, 2500.0, 0, 0, "Distance covered by a single cycle of the action");
+ }
+#endif
+
+ yco-=ysize;
+ break;
+ }
+ case ACT_IPO:
+ {
+ ia= act->data;
+
+ if(ia->type==ACT_IPO_KEY2KEY)
+ ysize= 72;
+ else
+ ysize= 52;
+
+ glRects(xco, yco-ysize, xco+width, yco);
+ uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
+
+ str = "Ipo types %t|Play %x0|Ping Pong %x1|Flipper %x2|Loop Stop %x3|Loop End %x4|Property %x6";
+
+ uiDefButS(block, MENU, B_REDR, str, xco+20, yco-24, width-40 - (width-40)/3, 19, &ia->type, 0, 0, 0, 0, "");
+ uiBlockSetCol(block, BUTGREEN);
+ uiDefButS(block, TOG|BIT|ACT_IPOCHILD_BIT, B_REDR,
+ "Child", xco+20+0.666*(width-40), yco-24, (width-40)/3, 19,
+ &ia->flag, 0, 0, 0, 0,
+ "Add all children Objects as well");
+ uiBlockSetCol(block, BUTGREY);
+ /*
+ Key2key was disabled.... the settings below should not be reused without
+ thought, because they interfere with other variables.
+
+ if(ia->type==ACT_IPO_KEY2KEY) {
+ uiBlockSetCol(block, BUTGREEN);
+
+ uiDefButS(block, TOG|BIT|0, 0, "Prev", xco+20, yco-44, (width-40)/3, 19, &ia->flag, 0, 0, 0, 0, "Play backwards");
+ uiDefButS(block, TOG|BIT|1, 0, "Cycl", xco+20+(width-40)/3, yco-44, (width-40)/3, 19, &ia->flag, 0, 0, 0, 0, "Play cyclic");
+ uiDefButS(block, TOG|BIT|3, 0, "Hold", xco+20+2*(width-40)/3, yco-44, (width-40)/3, 19, &ia->flag, 0, 0, 0, 0, "Keep playing while activated");
+
+ uiDefBut(block, TEX, 0, "Prop: ", xco+20, yco-66, width-40, 19, ia->name, 0.0, 31.0, 0, 0, "Set property to key position");
+ } else
+ */
+ if(ia->type==ACT_IPO_FROM_PROP) {
+ uiDefBut(block, TEX, 0,
+ "Prop: ", xco+20, yco-44, width-40, 19,
+ ia->name, 0.0, 31.0, 0, 0,
+ "Use this property to define the Ipo position");
+ }
+ else {
+ uiDefButS(block, NUM, 0,
+ "Sta", xco+20, yco-44, (width-100)/2, 19,
+ &ia->sta, 0.0, 18000.0, 0, 0,
+ "Start frame");
+ uiDefButS(block, NUM, 0,
+ "End", xco+18+(width-90)/2, yco-44, (width-100)/2, 19,
+ &ia->end, 0.0, 18000.0, 0, 0,
+ "End frame");
+
+ uiBlockSetCol(block, BUTGREEN);
+ uiDefButS(block, TOG|BIT|ACT_IPOFORCE_BIT, B_REDR,
+ "Force", xco+width-78, yco-44, 43, 19,
+ &ia->flag, 0, 0, 0, 0,
+ "Convert Ipo to force");
+
+ /* Only show the do-force-local toggle if force is requested */
+ if (ia->flag & ACT_IPOFORCE) {
+ uiDefButS(block, TOG|BIT|ACT_IPOFORCE_LOCAL_BIT, 0,
+ "L", xco+width-35, yco-44, 15, 19,
+ &ia->flag, 0, 0, 0, 0,
+ "Let the force-ipo act in local coordinates.");
+ }
+
+ }
+ yco-= ysize;
+ break;
+ }
+ case ACT_PROPERTY:
+ {
+ ysize= 68;
+
+ glRects(xco, yco-ysize, xco+width, yco);
+ uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
+
+ pa= act->data;
+
+ str= "Type %t|Assign %x0|Add %x1|Copy %x2";
+ uiDefButI(block, MENU, B_REDR, str, xco+30,yco-24,width-60, 19, &pa->type, 0, 31, 0, 0, "Type");
+
+ uiDefBut(block, TEX, 1, "Prop: ", xco+30,yco-44,width-60, 19, pa->name, 0, 31, 0, 0, "Property name");
+
+ if(pa->type==ACT_PROP_COPY) {
+ uiDefIDPoinBut(block, test_obpoin_but, 1, "OB:", xco+10, yco-64, (width-20)/2, 19, &(pa->ob), "Copy from this Object");
+ uiDefBut(block, TEX, 1, "Prop: ", xco+10+(width-20)/2, yco-64, (width-20)/2, 19, pa->value, 0, 31, 0, 0, "Copy this property");
+ }
+ else {
+ uiDefBut(block, TEX, 1, "Value: ", xco+30,yco-64,width-60, 19, pa->value, 0, 31, 0, 0, "change with this value");
+ }
+ yco-= ysize;
+
+ break;
+ }
+ case ACT_SOUND:
+ {
+ ysize = 70;
+
+ sa = act->data;
+ sa->sndnr = 0;
+
+ wval = (width-20)/2;
+ glRects(xco, yco-ysize, xco+width, yco);
+ uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
+
+ IDnames_to_pupstring(&str, "Sound files", NULL, &(G.main->sound), (ID *)sa->sound, &(sa->sndnr));
+
+ if(str[0])
+ {
+ /* reset this value, it is for handling the event */
+ sa->sndnr = 0;
+ uiDefButS(block, MENU, B_SOUNDACT_BROWSE, str, xco+10,yco-22,20,19, &(sa->sndnr), 0, 0, 0, 0, "");
+
+ if(sa->sound)
+ {
+ char dummy_str[] = "Sound mode %t|Play Stop %x0|Play End %x1|Loop Stop %x2|Loop End %x3|Loop Ping Pong Stop %x5|Loop Ping Pong %x4";
+ uiDefBut(block, TEX, B_IDNAME, "SO:",xco+30,yco-22,width-40,19, sa->sound->id.name+2, 0.0, 18.0, 0, 0, "");
+ uiDefButS(block, MENU, 1, dummy_str,xco+10,yco-44,width-20, 19, &sa->type, 0.0, 0.0, 0, 0, "");
+ uiDefButF(block, NUM, 0, "Volume:", xco+10,yco-66,wval, 19, &sa->sound->volume, 0.0, 1.0, 0, 0, "Sets the volume of this sound");
+ uiDefButF(block, NUM, 0, "Pitch:",xco+wval+10,yco-66,wval, 19, &sa->sound->pitch,-12.0, 12.0, 0, 0, "Sets the pitch of this sound");
+ }
+ }
+ else
+ {
+ uiDefBut(block, LABEL, 0, "Use Sound window to load files", xco, yco-24, width, 19, NULL, 0, 0, 0, 0, "");
+ }
+
+ MEM_freeN(str);
+
+ yco-= ysize;
+
+ break;
+ }
+ case ACT_CD:
+ {
+ char cd_type_str[] = "Sound mode %t|Play all tracks %x0|Play one track %x1|"
+ "Volume %x3|Stop %x4|Pause %x5|Resume %x6";
+ cda = act->data;
+
+ if (cda)
+ {
+ if (cda->track == 0)
+ {
+ cda->track = 1;
+ cda->volume = 1;
+ cda->type = ACT_CD_PLAY_ALL;
+ }
+
+ if (cda->type == ACT_CD_PLAY_TRACK || cda->type == ACT_CD_LOOP_TRACK)
+ {
+ ysize = 48;
+ glRects(xco, yco-ysize, xco+width, yco);
+ uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
+ uiDefButS(block, NUM, 0, "Track:", xco+10,yco-44,width-20, 19, &cda->track, 1, 99, 0, 0, "Select the track to be played");
+ }
+ else if (cda->type == ACT_CD_VOLUME)
+ {
+ ysize = 48;
+ glRects(xco, yco-ysize, xco+width, yco);
+ uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
+ uiDefButF(block, NUM, 0, "Volume:", xco+10,yco-44,width-20, 19, &cda->volume, 0, 1, 0, 0, "Set the volume for CD playback");
+ }
+ else
+ {
+ ysize = 28;
+ glRects(xco, yco-ysize, xco+width, yco);
+ uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
+ }
+ uiDefButS(block, MENU, B_REDR, cd_type_str,xco+10,yco-22,width-20, 19, &cda->type, 0.0, 0.0, 0, 0, "");
+ }
+ yco-= ysize;
+ break;
+ }
+ case ACT_CAMERA:
+
+ ysize= 48;
+
+ glRects(xco, yco-ysize, xco+width, yco);
+ uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
+
+ ca= act->data;
+
+ uiDefIDPoinBut(block, test_obpoin_but, 1, "OB:", xco+10, yco-24, (width-20)/2, 19, &(ca->ob), "Look at this Object");
+ uiDefButF(block, NUM, 0, "Height:", xco+10+(width-20)/2, yco-24, (width-20)/2, 19, &ca->height, 0.0, 20.0, 0, 0, "");
+
+ uiDefButF(block, NUM, 0, "Min:", xco+10, yco-44, (width-60)/2, 19, &ca->min, 0.0, 20.0, 0, 0, "");
+
+ if(ca->axis==0) ca->axis= 'x';
+ uiDefButS(block, ROW, 0, "X", xco+10+(width-60)/2, yco-44, 20, 19, &ca->axis, 4.0, (float)'x', 0, 0, "Camera tries to get behind the X axis");
+ uiDefButS(block, ROW, 0, "Y", xco+30+(width-60)/2, yco-44, 20, 19, &ca->axis, 4.0, (float)'y', 0, 0, "Camera tries to get behind the Y axis");
+
+ uiDefButF(block, NUM, 0, "Max:", xco+20+(width)/2, yco-44, (width-60)/2, 19, &ca->max, 0.0, 20.0, 0, 0, "");
+
+ yco-= ysize;
+
+ break;
+
+ case ACT_EDIT_OBJECT:
+
+ eoa= act->data;
+
+ if(eoa->type==ACT_EDOB_ADD_OBJECT) {
+ int wval; /* just a temp width */
+ ysize = 72;
+ glRects(xco, yco-ysize, xco+width, yco);
+ uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
+
+ uiDefIDPoinBut(block, test_obpoin_but, 1, "OB:", xco+10, yco-44, (width-20)/2, 19, &(eoa->ob), "Add this Object");
+ uiDefButI(block, NUM, 0, "Time:", xco+10+(width-20)/2, yco-44, (width-20)/2, 19, &eoa->time, 0.0, 2000.0, 0, 0, "Duration the new Object lives");
+
+ wval= (width-60)/3;
+ uiDefBut(block, LABEL, 0, "linV", xco, yco-68, 45, 19,
+ NULL, 0, 0, 0, 0,
+ "Velocity upon creation.");
+ uiDefButF(block, NUM, 0, "", xco+45, yco-68, wval, 19,
+ eoa->linVelocity, -100.0, 100.0, 10, 0,
+ "Velocity upon creation, x component.");
+ uiDefButF(block, NUM, 0, "", xco+45+wval, yco-68, wval, 19,
+ eoa->linVelocity+1, -100.0, 100.0, 10, 0,
+ "Velocity upon creation, y component.");
+ uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-68, wval, 19,
+ eoa->linVelocity+2, -100.0, 100.0, 10, 0,
+ "Velocity upon creation, z component.");
+ uiDefButS(block, TOG|BIT|1, 0, "L", xco+45+3*wval, yco-68, 15, 19,
+ &eoa->localflag, 0.0, 0.0, 0, 0,
+ "Apply the transformation locally");
+
+ }
+ else if(eoa->type==ACT_EDOB_END_OBJECT) {
+ ysize= 28;
+ glRects(xco, yco-ysize, xco+width, yco);
+ uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
+ }
+ else if(eoa->type==ACT_EDOB_REPLACE_MESH) {
+ ysize= 48;
+ glRects(xco, yco-ysize, xco+width, yco);
+ uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
+
+ uiDefIDPoinBut(block, test_meshpoin_but, 1, "ME:", xco+40, yco-44, (width-80), 19, &(eoa->me), "Add this Object");
+ }
+ else if(eoa->type==ACT_EDOB_TRACK_TO) {
+ ysize= 48;
+ glRects(xco, yco-ysize, xco+width, yco);
+ uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
+
+ uiDefIDPoinBut(block, test_obpoin_but, 1, "OB:", xco+10, yco-44, (width-20)/2, 19, &(eoa->ob), "Track to this Object");
+ uiDefButI(block, NUM, 0, "Time:", xco+10+(width-20)/2, yco-44, (width-20)/2-40, 19, &eoa->time, 0.0, 2000.0, 0, 0, "Duration the tracking takes");
+ uiBlockSetCol(block, BUTGREEN);
+ uiDefButS(block, TOG, 0, "3D", xco+width-50, yco-44, 40, 19, &eoa->flag, 0.0, 0.0, 0, 0, "Enable 3D tracking");
+ uiBlockSetCol(block, BUTGREY);
+ }
+
+ str= "Edit Object %t|Add Object %x0|End Object %x1|Replace Mesh %x2|Track to %x3";
+ uiDefButS(block, MENU, B_REDR, str, xco+40, yco-24, (width-80), 19, &eoa->type, 0.0, 0.0, 0, 0, "");
+
+ yco-= ysize;
+
+ break;
+
+ case ACT_CONSTRAINT:
+
+ ysize= 44;
+
+ glRects(xco, yco-ysize, xco+width, yco);
+ uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
+
+ coa= act->data;
+
+/* str= "Limit %t|None %x0|Loc X %x1|Loc Y %x2|Loc Z %x4|Rot X %x8|Rot Y %x16|Rot Z %x32"; */
+ str= "Limit %t|None %x0|Loc X %x1|Loc Y %x2|Loc Z %x4";
+ uiDefButS(block, MENU, 1, str, xco+10, yco-40, 70, 19, &coa->flag, 0.0, 0.0, 0, 0, "");
+
+ uiDefButS(block, NUM, 0, "Damp:", xco+10, yco-20, 70, 19, &coa->damp, 0.0, 100.0, 0, 0, "");
+ uiDefBut(block, LABEL, 0, "Min", xco+80, yco-20, (width-90)/2, 19, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefBut(block, LABEL, 0, "Max", xco+80+(width-90)/2, yco-20, (width-90)/2, 19, NULL, 0.0, 0.0, 0, 0, "");
+
+ if(coa->flag & ACT_CONST_LOCX) fp= coa->minloc;
+ else if(coa->flag & ACT_CONST_LOCY) fp= coa->minloc+1;
+ else if(coa->flag & ACT_CONST_LOCZ) fp= coa->minloc+2;
+ else if(coa->flag & ACT_CONST_ROTX) fp= coa->minrot;
+ else if(coa->flag & ACT_CONST_ROTY) fp= coa->minrot+1;
+ else fp= coa->minrot+2;
+
+ uiDefButF(block, NUM, 0, "", xco+80, yco-40, (width-90)/2, 19, fp, -2000.0, 2000.0, 10, 0, "");
+ uiDefButF(block, NUM, 0, "", xco+80+(width-90)/2, yco-40, (width-90)/2, 19, fp+3, -2000.0, 2000.0, 10, 0, "");
+
+ yco-= ysize;
+
+ break;
+
+ case ACT_SCENE:
+ sca= act->data;
+
+ if(sca->type==ACT_SCENE_RESTART) {
+ ysize= 28;
+ glRects(xco, yco-ysize, xco+width, yco);
+ uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
+ }
+ else if(sca->type==ACT_SCENE_CAMERA) {
+
+ ysize= 48;
+ glRects(xco, yco-ysize, xco+width, yco);
+ uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
+
+ uiDefIDPoinBut(block, test_obpoin_but, 1, "OB:", xco+40, yco-44, (width-80), 19, &(sca->camera), "Set this Camera");
+ }
+ else if(sca->type==ACT_SCENE_SET) {
+
+ ysize= 48;
+ glRects(xco, yco-ysize, xco+width, yco);
+ uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
+
+ uiDefIDPoinBut(block, test_scenepoin_but, 1, "SCE:", xco+40, yco-44, (width-80), 19, &(sca->scene), "Set this Scene");
+ }
+ else if(sca->type==ACT_SCENE_ADD_FRONT) {
+
+ ysize= 48;
+ glRects(xco, yco-ysize, xco+width, yco);
+ uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
+
+ uiDefIDPoinBut(block, test_scenepoin_but, 1, "SCE:", xco+40, yco-44, (width-80), 19, &(sca->scene), "Add an Overlay Scene");
+ }
+ else if(sca->type==ACT_SCENE_ADD_BACK) {
+
+ ysize= 48;
+ glRects(xco, yco-ysize, xco+width, yco);
+ uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
+
+ uiDefIDPoinBut(block, test_scenepoin_but, 1, "SCE:", xco+40, yco-44, (width-80), 19, &(sca->scene), "Add a Background Scene");
+ }
+ else if(sca->type==ACT_SCENE_REMOVE) {
+
+ ysize= 48;
+ glRects(xco, yco-ysize, xco+width, yco);
+ uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
+
+ uiDefIDPoinBut(block, test_scenepoin_but, 1, "SCE:", xco+40, yco-44, (width-80), 19, &(sca->scene), "Remove a Scene");
+ }
+ else if(sca->type==ACT_SCENE_SUSPEND) {
+
+ ysize= 48;
+ glRects(xco, yco-ysize, xco+width, yco);
+ uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
+
+ uiDefIDPoinBut(block, test_scenepoin_but, 1, "SCE:", xco+40, yco-44, (width-80), 19, &(sca->scene), "Pause a Scene");
+ }
+ else if(sca->type==ACT_SCENE_RESUME) {
+
+ ysize= 48;
+ glRects(xco, yco-ysize, xco+width, yco);
+ uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
+
+ uiDefIDPoinBut(block, test_scenepoin_but, 1, "SCE:", xco+40, yco-44, (width-80), 19, &(sca->scene), "Unpause a Scene");
+ }
+
+ str= "Scene %t|Restart %x0|Set Scene %x1|Set Camera %x2|Add OverlayScene %x3|Add BackgroundScene %x4|Remove Scene %x5|Suspend Scene %x6|Resume Scene %x7";
+ uiDefButS(block, MENU, B_REDR, str, xco+40, yco-24, (width-80), 19, &sca->type, 0.0, 0.0, 0, 0, "");
+
+ yco-= ysize;
+ break;
+ case ACT_GAME:
+ {
+ gma = act->data;
+ if (gma->type == ACT_GAME_LOAD)
+ {
+ //ysize = 68;
+ ysize = 48;
+ glRects(xco, yco-ysize, xco+width, yco);
+ uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
+ uiDefBut(block, TEX, 1, "File: ", xco+10, yco-44,width-20,19, &(gma->filename), 0, 63, 0, 0, "Load this file");
+// uiDefBut(block, TEX, 1, "Anim: ", xco+10, yco-64,width-20,19, &(gma->loadaniname), 0, 63, 0, 0, "Use this loadinganimation");
+ }
+/* else if (gma->type == ACT_GAME_START)
+ {
+ ysize = 68;
+ glRects(xco, yco-ysize, xco+width, yco);
+ uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
+
+ uiDefBut(block, TEX, 1, "File: ", xco+10, yco-44,width-20,19, &(gma->filename), 0, 63, 0, 0, "Load this file");
+ uiDefBut(block, TEX, 1, "Anim: ", xco+10, yco-64,width-20,19, &(gma->loadaniname), 0, 63, 0, 0, "Use this loadinganimation");
+ }
+*/ else if (gma->type == ACT_GAME_RESTART)
+ {
+ ysize = 28;
+ glRects(xco, yco-ysize, xco+width, yco);
+ uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
+ }
+ else if (gma->type == ACT_GAME_QUIT)
+ {
+ ysize = 28;
+ glRects(xco, yco-ysize, xco+width, yco);
+ uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
+ }
+
+ //str = "Scene %t|Load game%x0|Start loaded game%x1|Restart this game%x2|Quit this game %x3";
+ str = "Scene %t|Start new game%x0|Restart this game%x2|Quit this game %x3";
+ uiDefButS(block, MENU, B_REDR, str, xco+40, yco-24, (width-80), 19, &gma->type, 0.0, 0.0, 0, 0, "");
+
+ yco -= ysize;
+ break;
+ }
+ case ACT_GROUP:
+ ga= act->data;
+
+ ysize= 52;
+
+ glRects(xco, yco-ysize, xco+width, yco);
+ uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
+
+ str= "GroupKey types %t|Set Key %x6|Play %x0|Ping Pong %x1|Flipper %x2|Loop Stop %x3|Loop End %x4|Property %x5";
+
+ uiDefButS(block, MENU, 1, str, xco+20, yco-24, width-40, 19, &ga->type, 0, 0, 0, 0, "");
+ if(ga->type==ACT_GROUP_SET) {
+ uiDefBut(block, TEX, 0, "Key: ", xco+20, yco-44, (width-10)/2, 19, ga->name, 0.0, 31.0, 0, 0, "This name defines groupkey to be set");
+ uiDefButS(block, NUM, 0, "Frame:", xco+20+(width-10)/2, yco-44, (width-70)/2, 19, &ga->sta, 0.0, 2500.0, 0, 0, "Set this frame");
+ }
+ else if(ga->type==ACT_GROUP_FROM_PROP) {
+ uiDefBut(block, TEX, 0, "Prop: ", xco+20, yco-44, width-40, 19, ga->name, 0.0, 31.0, 0, 0, "Use this property to define the Group position");
+ }
+ else {
+ uiDefButS(block, NUM, 0, "Sta", xco+20, yco-44, (width-40)/2, 19, &ga->sta, 0.0, 2500.0, 0, 0, "Start frame");
+ uiDefButS(block, NUM, 0, "End", xco+20+(width-40)/2, yco-44, (width-40)/2, 19, &ga->end, 0.0, 2500.0, 0, 0, "End frame");
+ }
+ yco-= ysize;
+ break;
+
+ case ACT_VISIBILITY:
+ ysize = 24;
+
+ glRects(xco, yco-ysize, xco+width, yco);
+ uiEmboss((float)xco,
+ (float)yco-ysize, (float)xco+width, (float)yco, 1);
+
+ visAct = act->data;
+
+ str= "Visibility %t|Visible %x0|Invisible %x1";
+
+ uiDefButI(block, MENU, B_REDR, str,
+ xco + 10, yco - 24, width - 20, 19, &visAct->flag,
+ 0.0, 0.0, 0, 0,
+ "Make the object invisible or visible.");
+/*
+ uiDefButI(block, TOG|BIT|ACT_VISIBILITY_INVISIBLE_BIT, 0,
+ "Invisible",
+ xco + 10, yco - 24, width - 20, 19, &visAct->flag,
+ 0.0, 0.0, 0, 0,
+ "Make the object invisible or visible.");
+*/
+ yco-= ysize;
+
+ break;
+
+ case ACT_RANDOM:
+ ysize = 69;
+
+ glRects(xco, yco-ysize, xco+width, yco);
+ uiEmboss((float)xco,
+ (float)yco-ysize, (float)xco+width, (float)yco, 1);
+
+ randAct = act->data;
+
+ /* 1. seed */
+ uiDefButI(block, NUM, 1, "Seed: ", (xco+10),yco-24, 0.4 *(width-20), 19,
+ &randAct->seed, 0, 1000, 0, 0,
+ "Initial seed of the random generator. Use Python for more freedom. "
+ " (Choose 0 for not random)");
+
+ /* 2. distribution type */
+ /* One pick per distribution. These numbers MUST match the #defines */
+ /* in game.h !!! */
+ str= "Distribution %t|Bool Constant %x0|Bool Uniform %x1"
+ "|Bool Bernoulli %x2|Int Constant %x3|Int Uniform %x4"
+ "|Int Poisson %x5|Float Constant %x6|Float Uniform %x7"
+ "|Float Normal %x8|Float Neg. Exp. %x9";
+ uiDefButI(block, MENU, B_REDR, str, (xco+10) + 0.4 * (width-20), yco-24, 0.6 * (width-20), 19,
+ &randAct->distribution, 0.0, 0.0, 0, 0,
+ "Choose the type of distribution");
+
+ /* 3. property */
+ uiDefBut(block, TEX, 1, "Property:", (xco+10), yco-44, (width-20), 19,
+ &randAct->propname, 0, 31, 0, 0,
+ "Assign the random value to this property");
+
+ /*4. and 5. arguments for the distribution*/
+ switch (randAct->distribution) {
+ case ACT_RANDOM_BOOL_CONST:
+ uiDefButI(block, TOG|BIT|0, 1, "Always true", (xco+10), yco-64, (width-20), 19,
+ &randAct->int_arg_1, 2.0, 1, 0, 0,
+ "Always false or always true");
+ break;
+ case ACT_RANDOM_BOOL_UNIFORM:
+ uiDefBut(block, LABEL, 0, " Do a 50-50 pick.", (xco+10), yco-64, (width-20), 19,
+ NULL, 0, 0, 0, 0,
+ "Choose between true and false, 50%% chance each.");
+ break;
+ case ACT_RANDOM_BOOL_BERNOUILLI:
+ uiDefButF(block, NUM, 1, "Chance", (xco+10), yco-64, (width-20), 19,
+ &randAct->float_arg_1, 0.0, 1.0, 0, 0,
+ "Pick a number between 0 and 1. Success if you stay "
+ "below this value");
+ break;
+ case ACT_RANDOM_INT_CONST:
+ uiDefButI(block, NUM, 1, "Value: ", (xco+10), yco-64, (width-20), 19,
+ &randAct->int_arg_1, -1000, 1000, 0, 0,
+ "Always return this number");
+ break;
+ case ACT_RANDOM_INT_UNIFORM:
+ uiDefButI(block, NUM, 1, "Min: ", (xco+10), yco-64, (width-20)/2, 19,
+ &randAct->int_arg_1, -1000, 1000, 0, 0,
+ "Choose a number from a range. "
+ "Lower boundary of the range.");
+ uiDefButI(block, NUM, 1, "Max: ", (xco+10) + (width-20)/2, yco-64, (width-20)/2, 19,
+ &randAct->int_arg_2, -1000, 1000, 0, 0,
+ "Choose a number from a range. "
+ "Upper boundary of the range.");
+ break;
+ case ACT_RANDOM_INT_POISSON:
+ uiDefButF(block, NUM, 1, "Mean: ", (xco+10), yco-64, (width-20), 19,
+ &randAct->float_arg_1, 0.01, 100.0, 0, 0,
+ "Expected mean value of the distribution.");
+ break;
+ case ACT_RANDOM_FLOAT_CONST:
+ uiDefButF(block, NUM, 1, "Value: ", (xco+10), yco-64, (width-20), 19,
+ &randAct->float_arg_1, 0.0, 1.0, 0, 0,
+ "Always return this number");
+ break;
+ case ACT_RANDOM_FLOAT_UNIFORM:
+ uiDefButF(block, NUM, 1, "Min: ", (xco+10), yco-64, (width-20)/2, 19,
+ &randAct->float_arg_1, -10000.0, 10000.0, 0, 0,
+ "Choose a number from a range. "
+ "Lower boundary of the range.");
+ uiDefButF(block, NUM, 1, "Max: ", (xco+10) + (width-20)/2, yco-64, (width-20)/2, 19,
+ &randAct->float_arg_2, -10000.0, 10000.0, 0, 0,
+ "Choose a number from a range. "
+ "Upper boundary of the range.");
+ break;
+ case ACT_RANDOM_FLOAT_NORMAL:
+ uiDefButF(block, NUM, 1, "Mean: ", (xco+10), yco-64, (width-20)/2, 19,
+ &randAct->float_arg_1, -10000.0, 10000.0, 0, 0,
+ "A normal distribution. Mean of the distribution.");
+ uiDefButF(block, NUM, 1, "SD: ", (xco+10) + (width-20)/2, yco-64, (width-20)/2, 19,
+ &randAct->float_arg_2, 0.0, 10000.0, 0, 0,
+ "A normal distribution. Standard deviation of the "
+ "distribution.");
+ break;
+ case ACT_RANDOM_FLOAT_NEGATIVE_EXPONENTIAL:
+ uiDefButF(block, NUM, 1, "Half-life time: ", (xco+10), yco-64, (width-20), 19,
+ &randAct->float_arg_1, 0.001, 10000.0, 0, 0,
+ "Negative exponential dropoff.");
+ break;
+ default:
+ ; /* don't know what this distro is... can be useful for testing */
+ /* though :) */
+ }
+
+ yco-= ysize;
+ break;
+ case ACT_MESSAGE:
+ ma = act->data;
+
+#define MESSAGE_SENSOR_TO_FIELD_WORKS /* Really? Not really. Don't remove this ifdef yet */
+
+#ifdef MESSAGE_SENSOR_TO_FIELD_WORKS
+ ysize = 4 + (3 * 24); /* footer + number of lines * 24 pixels/line */
+#else
+ ysize = 4 + (2 * 24); /* footer + number of lines * 24 pixels/line */
+#endif
+ glRects(xco, yco-ysize, xco+width, yco);
+ uiEmboss((float)xco, (float)yco-ysize,
+ (float)xco+width, (float)yco, 1);
+
+ myline=1;
+
+
+#ifdef MESSAGE_SENSOR_TO_FIELD_WORKS
+ /* line 1: To */
+ uiDefBut(block, TEX, 1, "To: ",
+ (xco+10), (yco-(myline++*24)), (width-20), 19,
+ &ma->toPropName, 0, 31, 0, 0,
+ "Optional send message to objects with this property only"
+ ", or empty to broadcast");
+
+#endif
+
+ /* line 2: Message Subject */
+ uiDefBut(block, TEX, 1, "Subject: ",
+ (xco+10), (yco-(myline++*24)), (width-20), 19,
+ &ma->subject, 0, 31, 0, 0,
+ "Optional message subject. This is what can be filtered on.");
+
+ /* line 3: Text/Property */
+ uiDefButS(block, TOG|BIT|0, B_REDR, "T/P",
+ (xco+10),(yco-(myline*24)), (0.20 * (width-20)), 19,
+ &ma->bodyType, 0.0, 0.0, 0, 0,
+ "Toggle message type: either Text or a PropertyName.");
+
+ if (ma->bodyType == ACT_MESG_MESG)
+ {
+ /* line 3: Message Body */
+ uiDefBut(block, TEX, 1, "Body: ",
+ (xco+10+(0.20*(width-20))),(yco-(myline++*24)),(0.8*(width-20)),19,
+ &ma->body, 0, 31, 0, 0,
+ "Optional message body Text");
+ } else
+ {
+ /* line 3: Property body (set by property) */
+ uiDefBut(block, TEX, 1, "Propname: ",
+ (xco+10+(0.20*(width-20))),(yco-(myline++*24)),(0.8*(width-20)),19,
+ &ma->body, 0, 31, 0, 0,
+ "The message body will be set by the Property Value");
+ }
+
+ yco -= ysize;
+ break;
+ default:
+ ysize= 4;
+
+ glRects(xco, yco-ysize, xco+width, yco);
+ uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
+
+ yco-= ysize;
+ break;
+ }
+
+ uiBlockSetEmboss(block, UI_EMBOSSM);
+ uiBlockSetCol(block, BUTGREY);
+
+ return yco-4;
+}
+
+static void do_sensor_menu(void *arg, int event)
+{
+ ID **idar;
+ Object *ob;
+ bSensor *sens;
+ short count, a;
+
+ idar= get_selected_and_linked_obs(&count, G.buts->scaflag);
+
+ for(a=0; a<count; a++) {
+ ob= (Object *)idar[a];
+ if(event==0 || event==2) ob->scaflag |= OB_SHOWSENS;
+ else if(event==1) ob->scaflag &= ~OB_SHOWSENS;
+ }
+
+ for(a=0; a<count; a++) {
+ ob= (Object *)idar[a];
+ sens= ob->sensors.first;
+ while(sens) {
+ if(event==2) sens->flag |= SENS_SHOW;
+ else if(event==3) sens->flag &= ~SENS_SHOW;
+ sens= sens->next;
+ }
+ }
+
+ if(idar) MEM_freeN(idar);
+ allqueue(REDRAWBUTSGAME, 0);
+}
+
+static uiBlock *sensor_menu(void *arg_unused)
+{
+ uiBlock *block;
+ int yco=0;
+
+ block= uiNewBlock(&curarea->uiblocks, "filemenu", UI_EMBOSSP, UI_HELV, curarea->win);
+ uiBlockSetButmFunc(block, do_sensor_menu, NULL);
+
+ uiDefBut(block, BUTM, 1, "Show Objects", 0, (short)(yco-=20), 160, 19, NULL, 0.0, 0.0, 1, 0, "");
+ uiDefBut(block, BUTM, 1, "Hide Objects", 0, (short)(yco-=20), 160, 19, NULL, 0.0, 0.0, 1, 1, "");
+ uiDefBut(block, SEPR, 0, "", 0, (short)(yco-=6), 160, 6, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefBut(block, BUTM, 1, "Show Sensors", 0, (short)(yco-=20), 160, 19, NULL, 0.0, 0.0, 1, 2, "");
+ uiDefBut(block, BUTM, 1, "Hide Sensors", 0, (short)(yco-=20), 160, 19, NULL, 0.0, 0.0, 1, 3, "");
+
+ uiBlockSetDirection(block, UI_TOP);
+
+ return block;
+}
+
+static void do_controller_menu(void *arg, int event)
+{
+ ID **idar;
+ Object *ob;
+ bController *cont;
+ short count, a;
+
+ idar= get_selected_and_linked_obs(&count, G.buts->scaflag);
+
+ for(a=0; a<count; a++) {
+ ob= (Object *)idar[a];
+ if(event==0 || event==2) ob->scaflag |= OB_SHOWCONT;
+ else if(event==1) ob->scaflag &= ~OB_SHOWCONT;
+ }
+
+ for(a=0; a<count; a++) {
+ ob= (Object *)idar[a];
+ cont= ob->controllers.first;
+ while(cont) {
+ if(event==2) cont->flag |= CONT_SHOW;
+ else if(event==3) cont->flag &= ~CONT_SHOW;
+ cont= cont->next;
+ }
+ }
+
+ if(idar) MEM_freeN(idar);
+ allqueue(REDRAWBUTSGAME, 0);
+}
+
+static uiBlock *controller_menu(void *arg_unused)
+{
+ uiBlock *block;
+ int yco=0;
+
+ block= uiNewBlock(&curarea->uiblocks, "filemenu", UI_EMBOSSP, UI_HELV, curarea->win);
+ uiBlockSetButmFunc(block, do_controller_menu, NULL);
+
+ uiDefBut(block, BUTM, 1, "Show Objects", 0, (short)(yco-=20), 160, 19, NULL, 0.0, 0.0, 1, 0, "");
+ uiDefBut(block, BUTM, 1, "Hide Objects", 0,(short)(yco-=20), 160, 19, NULL, 0.0, 0.0, 1, 1, "");
+ uiDefBut(block, SEPR, 0, "", 0, (short)(yco-=6), 160, 6, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefBut(block, BUTM, 1, "Show Controllers", 0, (short)(yco-=20), 160, 19, NULL, 0.0, 0.0, 2, 2, "");
+ uiDefBut(block, BUTM, 1, "Hide Controllers", 0, (short)(yco-=20), 160, 19, NULL, 0.0, 0.0, 3, 3, "");
+
+ uiBlockSetDirection(block, UI_TOP);
+
+ return block;
+}
+
+static void do_actuator_menu(void *arg, int event)
+{
+ ID **idar;
+ Object *ob;
+ bActuator *act;
+ short count, a;
+
+ idar= get_selected_and_linked_obs(&count, G.buts->scaflag);
+
+ for(a=0; a<count; a++) {
+ ob= (Object *)idar[a];
+ if(event==0 || event==2) ob->scaflag |= OB_SHOWACT;
+ else if(event==1) ob->scaflag &= ~OB_SHOWACT;
+ }
+
+ for(a=0; a<count; a++) {
+ ob= (Object *)idar[a];
+ act= ob->actuators.first;
+ while(act) {
+ if(event==2) act->flag |= ACT_SHOW;
+ else if(event==3) act->flag &= ~ACT_SHOW;
+ act= act->next;
+ }
+ }
+
+ if(idar) MEM_freeN(idar);
+ allqueue(REDRAWBUTSGAME, 0);
+}
+
+static uiBlock *actuator_menu(void *arg_unused)
+{
+ uiBlock *block;
+ int xco=0;
+
+ block= uiNewBlock(&curarea->uiblocks, "filemenu", UI_EMBOSSP, UI_HELV, curarea->win);
+ uiBlockSetButmFunc(block, do_actuator_menu, NULL);
+
+ uiDefBut(block, BUTM, 1, "Show Objects", 0, (short)(xco-=20), 160, 19, NULL, 0.0, 0.0, 1, 0, "");
+ uiDefBut(block, BUTM, 1, "Hide Objects", 0, (short)(xco-=20), 160, 19, NULL, 0.0, 0.0, 1, 1, "");
+ uiDefBut(block, SEPR, 0, "", 0, (short)(xco-=6), 160, 6, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefBut(block, BUTM, 1, "Show Actuators", 0, (short)(xco-=20), 160, 19, NULL, 0.0, 0.0, 1, 2, "");
+ uiDefBut(block, BUTM, 1, "Hide Actuators", 0, (short)(xco-=20), 160, 19, NULL, 0.0, 0.0, 1, 3, "");
+
+ uiBlockSetDirection(block, UI_TOP);
+
+ return block;
+}
+
+/* never used, see CVS 1.134 for the code */
+/* static FreeCamera *new_freecamera(void) */
+
+/* never used, see CVS 1.120 for the code */
+/* static uiBlock *freecamera_menu(void) */
+
+void gamebuts(void)
+{
+ ID **idar;
+ Object *ob;
+ bProperty *prop;
+ bSensor *sens;
+ bController *cont;
+ bActuator *act;
+ uiBlock *block;
+ uiBut *but;
+ int a;
+ short xco, yco, count, width, ycoo;
+ char *pupstr, name[32];
+ int butreturn = 0;
+
+ ob= OBACT;
+
+ if(ob==0) return;
+ uiSetButLock(ob->id.lib!=0, "Can't edit library data");
+
+ sprintf(name, "buttonswin %d", curarea->win);
+ block= uiNewBlock(&curarea->uiblocks, name, UI_EMBOSSX, UI_HELV, curarea->win);
+
+ uiBlockSetCol(block, BUTPURPLE);
+ // uiDefButI(block, TOG|BIT|0, B_REDR, "X",
+ // 15,205,10,19, &ob->gameflag2, 0, 0, 0, 0,
+ // "Toggle to always ignore activity culling.");
+ uiDefButI(block, TOG|BIT|2, B_REDR, "Actor",
+ 25,205,60,19, &ob->gameflag, 0, 0, 0, 0,
+ "Objects that are evaluated by the engine ");
+
+ if(ob->gameflag & OB_ACTOR) {
+ uiDefButI(block, TOG|BIT|9, B_REDR, "Ghost", 85,205,65,19, &ob->gameflag, 0, 0, 0, 0, "Objects that don't restitute collisions (like a ghost)");
+ uiDefButI(block, TOG|BIT|0, B_REDR, "Dynamic", 150,205,65,19, &ob->gameflag, 0, 0, 0, 0, "Motion defined by laws of physics");
+
+ if(ob->gameflag & OB_DYNAMIC) {
+
+ uiDefButI(block, TOG|BIT|10, B_REDR, "Rigid Body", 215,205,135,19, &ob->gameflag, 0, 0, 0, 0, "");
+
+ uiDefButI(block, TOG|BIT|6, B_DIFF, "Do Fh", 10,185,50,19, &ob->gameflag, 0, 0, 0, 0, "Use Fh settings in Materials");
+ uiDefButI(block, TOG|BIT|7, B_DIFF, "Rot Fh", 60,185,50,19, &ob->gameflag, 0, 0, 0, 0, "Use face normal to rotate Object");
+
+ uiBlockSetCol(block, BUTGREY);
+
+ uiDefButF(block, NUM, B_DIFF, "Mass:", 110, 185, 80, 19, &ob->mass, 0.01, 100.0, 10, 0, "The mass of the Object");
+ uiDefButF(block, NUM, REDRAWVIEW3D, "Size:", 190, 185, 80, 19, &ob->inertia, 0.01, 10.0, 10, 0, "Bounding sphere size");
+ uiDefButF(block, NUM, B_DIFF, "Form:", 270, 185, 80, 19, &ob->formfactor, 0.01, 100.0, 10, 0, "Form factor");
+
+ uiDefButF(block, NUM, B_DIFF, "Damp:", 10, 165, 100, 19, &ob->damping, 0.0, 1.0, 10, 0, "General movement damping");
+ uiDefButF(block, NUM, B_DIFF, "RotDamp:", 110, 165, 120, 19, &ob->rdamping, 0.0, 1.0, 10, 0, "General rotation damping");
+ uiDefButI(block, TOG|BIT|8, B_REDR, "Anisotropic", 230, 165, 120, 19,
+ &ob->gameflag, 0.0, 1.0, 10, 0,
+ "Enable anisotropic friction");
+ }
+ }
+
+ if (ob->gameflag & OB_ANISOTROPIC_FRICTION) {
+ uiDefButF(block, NUM, B_DIFF, "x friction:", 10, 145, 114, 19,
+ &ob->anisotropicFriction[0], 0.0, 1.0, 10, 0,
+ "Relative friction coefficient in the x-direction.");
+ uiDefButF(block, NUM, B_DIFF, "y friction:", 124, 145, 113, 19,
+ &ob->anisotropicFriction[1], 0.0, 1.0, 10, 0,
+ "Relative friction coefficient in the y-direction.");
+ uiDefButF(block, NUM, B_DIFF, "z friction:", 237, 145, 113, 19,
+ &ob->anisotropicFriction[2], 0.0, 1.0, 10, 0,
+ "Relative friction coefficient in the z-direction.");
+ }
+
+ uiBlockSetCol(block, BUTSALMON);
+ uiDefBut(block, BUT, B_ADD_PROP, "ADD property", 10, 110, 340, 24,
+ NULL, 0.0, 100.0, 100, 0,
+ "");
+
+ pupstr= "Types %t|Bool %x0|Int %x1|Float %x2|String %x3|Timer %x5";
+
+ a= 0;
+ prop= ob->prop.first;
+ while(prop) {
+
+ uiBlockSetCol(block, BUTSALMON);
+ but= uiDefBut(block, BUT, 1, "Del", 10, (short)(90-20*a), 40, 19, NULL, 0.0, 0.0, 1, (float)a, "");
+ uiButSetFunc(but, del_property, prop, NULL);
+ uiBlockSetCol(block, BUTGREY);
+ uiDefButS(block, MENU, B_CHANGE_PROP, pupstr, 50, (short)(90-20*a), 60, 19, &prop->type, 0, 0, 0, 0, "");
+ but= uiDefBut(block, TEX, 1, "Name:", 110, (short)(90-20*a), 105, 19, prop->name, 0, 31, 0, 0, "");
+ uiButSetFunc(but, make_unique_prop_names_cb, prop->name, (void*) 1);
+
+ if (strcmp(prop->name, "Text") == 0) {
+ butreturn = REDRAWVIEW3D;
+ } else {
+ butreturn = 0;
+ }
+
+ if(prop->type==PROP_BOOL) {
+ uiBlockSetCol(block, BUTGREEN);
+ uiDefButI(block, TOG|BIT|0, B_REDR, "True", 215, (short)(90-20*a), 55, 19, &prop->data, 0, 0, 0, 0, "");
+ uiDefButI(block, TOGN|BIT|0, B_REDR, "False", 270, (short)(90-20*a), 55, 19, &prop->data, 0, 0, 0, 0, "");
+ uiBlockSetCol(block, BUTGREY);
+ }
+ else if(prop->type==PROP_INT)
+ uiDefButI(block, NUM, butreturn, "", 215, (short)(90-20*a), 110, 19, &prop->data, -10000, 10000, 0, 0, "");
+ else if(prop->type==PROP_FLOAT)
+ uiDefButF(block, NUM, butreturn, "", 215, (short)(90-20*a), 110, 19, (float*) &prop->data, -10000, 10000, 100, 0, "");
+ else if(prop->type==PROP_STRING)
+ uiDefBut(block, TEX, butreturn, "", 215, (short)(90-20*a), 110, 19, prop->poin, 0, 127, 0, 0, "");
+ else if(prop->type==PROP_TIME)
+ uiDefButF(block, NUM, butreturn, "", 215, (short)(90-20*a), 110, 19, (float*) &prop->data, -10000, 10000, 0, 0, "");
+
+ uiDefButS(block, TOG|BIT|0, 0, "D", 325, (short)(90-20*a), 20, 19, &prop->flag, 0, 0, 0, 0, "Print Debug info");
+
+ a++;
+ prop= prop->next;
+ }
+
+ uiClearButLock();
+
+ idar= get_selected_and_linked_obs(&count, G.buts->scaflag);
+
+ /* ******************************* */
+ xco= 375; yco= 170; width= 230;
+
+ uiBlockSetCol(block, BUTGREY);
+ uiBlockSetEmboss(block, UI_EMBOSSM);
+ uiDefBlockBut(block, sensor_menu, NULL, "Sensors", xco-10, yco+35, 80, 19, "");
+ uiBlockSetCol(block, BUTGREEN);
+ uiBlockSetEmboss(block, UI_EMBOSSX);
+ uiDefButS(block, TOG|BIT|0, B_REDR, "Sel", xco+110, yco+35, (width-100)/3, 19, &G.buts->scaflag, 0, 0, 0, 0, "Show all selected Objects");
+ uiDefButS(block, TOG|BIT|1, B_REDR, "Act", xco+110+(width-100)/3, yco+35, (width-100)/3, 19, &G.buts->scaflag, 0, 0, 0, 0, "Show active Object");
+ uiDefButS(block, TOG|BIT|2, B_REDR, "Link", xco+110+2*(width-100)/3, yco+35, (width-100)/3, 19, &G.buts->scaflag, 0, 0, 0, 0, "Show linked Objects to Controller");
+
+ for(a=0; a<count; a++) {
+ ob= (Object *)idar[a];
+ uiClearButLock();
+ uiSetButLock(ob->id.lib!=0, "Can't edit library data");
+
+ if( (ob->scavisflag & OB_VIS_SENS) == 0) continue;
+
+ /* presume it is only objects for now */
+ uiBlockSetEmboss(block, UI_EMBOSSX);
+ uiBlockSetCol(block, BUTGREY);
+ if(ob->sensors.first) uiSetCurFont(block, UI_HELVB);
+ uiBlockSetCol(block, MIDGREY);
+ uiDefButS(block, TOG|BIT|6, B_REDR, ob->id.name+2,(short)(xco-10), yco, (short)(width-30), 19, &ob->scaflag, 0, 31, 0, 0, "Object name, click to show/hide sensors");
+ if(ob->sensors.first) uiSetCurFont(block, UI_HELV);
+ uiBlockSetCol(block, BUTSALMON);
+ uiDefButS(block, TOG|BIT|8, B_ADD_SENS, "Add",(short)(xco+width-40), yco, 50, 19, &ob->scaflag, 0, 0, 0, 0, "Add a new Sensor");
+ yco-=20;
+
+ if(ob->scaflag & OB_SHOWSENS) {
+
+ sens= ob->sensors.first;
+ while(sens) {
+ uiBlockSetEmboss(block, UI_EMBOSSW);
+ uiBlockSetCol(block, BUTSALMON);
+ uiDefIconButS(block, TOG|BIT|1, B_DEL_SENS, ICON_X, xco, yco, 22, 19, &sens->flag, 0, 0, 0, 0, "Delete Sensor");
+ uiBlockSetCol(block, BUTGREY);
+ uiDefIconButS(block, ICONTOG|BIT|0, B_REDR, ICON_RIGHTARROW, (short)(xco+width-22), yco, 22, 19, &sens->flag, 0, 0, 0, 0, "Sensor settings");
+
+ ycoo= yco;
+ if(sens->flag & SENS_SHOW)
+ {
+ uiBlockSetCol(block, BUTYELLOW);
+
+ uiDefButS(block, MENU, B_CHANGE_SENS, sensor_pup(), (short)(xco+22), yco, 100, 19, &sens->type, 0, 0, 0, 0, "Sensor type");
+ but= uiDefBut(block, TEX, 1, "", (short)(xco+122), yco, (short)(width-144), 19, sens->name, 0, 31, 0, 0, "Sensor name");
+ uiButSetFunc(but, make_unique_prop_names_cb, sens->name, (void*) 0);
+
+ sens->otype= sens->type;
+ uiBlockSetCol(block, BUTGREY);
+ yco= draw_sensorbuttons(sens, block, xco, yco, width,ob->id.name);
+ if(yco-6 < ycoo) ycoo= (yco+ycoo-20)/2;
+ }
+ else {
+ set_col_sensor(sens->type, 1);
+ glRecti(xco+22, yco, xco+width-22,yco+19);
+ but= uiDefBut(block, LABEL, 0, sensor_name(sens->type), (short)(xco+22), yco, 100, 19, sens, 0, 0, 0, 0, "");
+ uiButSetFunc(but, sca_move_sensor, sens, NULL);
+ but= uiDefBut(block, LABEL, 0, sens->name, (short)(xco+122), yco, (short)(width-144), 19, sens, 0, 31, 0, 0, "");
+ uiButSetFunc(but, sca_move_sensor, sens, NULL);
+ }
+
+ but= uiDefIconBut(block, LINK, 0, ICON_LINK, (short)(xco+width), ycoo, 19, 19, NULL, 0, 0, 0, 0, "");
+ uiSetButLink(but, NULL, (void ***)&(sens->links), &sens->totlinks, LINK_SENSOR, LINK_CONTROLLER);
+
+ yco-=20;
+
+ sens= sens->next;
+ }
+ yco-= 6;
+ }
+ }
+
+ /* ******************************* */
+ xco= 675; yco= 170; width= 230;
+
+ uiBlockSetCol(block, BUTGREY);
+ uiBlockSetEmboss(block, UI_EMBOSSM);
+ uiDefBlockBut(block, controller_menu, NULL, "Controllers", xco-10, yco+35, 100, 19, "");
+ uiBlockSetCol(block, BUTGREEN);
+ uiBlockSetEmboss(block, UI_EMBOSSX);
+ uiDefButS(block, TOG|BIT|3, B_REDR, "Sel", xco+110, yco+35, (width-100)/3, 19, &G.buts->scaflag, 0, 0, 0, 0, "Show all selected Objects");
+ uiDefButS(block, TOG|BIT|4, B_REDR, "Act", xco+110+(width-100)/3, yco+35, (width-100)/3, 19, &G.buts->scaflag, 0, 0, 0, 0, "Show active Object");
+ uiDefButS(block, TOG|BIT|5, B_REDR, "Link", xco+110+2*(width-100)/3, yco+35, (width-100)/3, 19, &G.buts->scaflag, 0, 0, 0, 0, "Show linked Objects to Sensor/Actuator");
+
+ ob= OBACT;
+
+ for(a=0; a<count; a++) {
+ ob= (Object *)idar[a];
+ uiClearButLock();
+ uiSetButLock(ob->id.lib!=0, "Can't edit library data");
+ if( (ob->scavisflag & OB_VIS_CONT) == 0) continue;
+
+ /* presume it is only objects for now */
+ uiBlockSetEmboss(block, UI_EMBOSSX);
+ uiBlockSetCol(block, BUTSALMON);
+ uiDefButS(block, TOG|BIT|9, B_ADD_CONT, "Add",(short)(xco+width-40), yco, 50, 19, &ob->scaflag, 0, 0, 0, 0, "Add a new Controller");
+ uiBlockSetCol(block, MIDGREY);
+ if(ob->controllers.first) uiSetCurFont(block, UI_HELVB);
+ uiDefButS(block, TOG|BIT|11, B_REDR, ob->id.name+2,(short)(xco-10), yco, (short)(width-30), 19, &ob->scaflag, 0, 0, 0, 0, "Active Object name");
+ if(ob->controllers.first) uiSetCurFont(block, UI_HELV);
+ yco-=20;
+
+ if(ob->scaflag & OB_SHOWCONT) {
+
+ cont= ob->controllers.first;
+ while(cont) {
+ uiBlockSetEmboss(block, UI_EMBOSSW);
+ uiBlockSetCol(block, BUTSALMON);
+ uiDefIconButS(block, TOG|BIT|1, B_DEL_CONT, ICON_X, xco, yco, 22, 19, &cont->flag, 0, 0, 0, 0, "Delete Controller");
+ uiBlockSetCol(block, BUTGREY);
+ uiDefIconButS(block, ICONTOG|BIT|0, B_REDR, ICON_RIGHTARROW, (short)(xco+width-22), yco, 22, 19, &cont->flag, 0, 0, 0, 0, "Controller settings");
+
+ if(cont->flag & CONT_SHOW) {
+ uiBlockSetCol(block, BUTYELLOW);
+ cont->otype= cont->type;
+ uiDefButS(block, MENU, B_CHANGE_CONT, controller_pup(),(short)(xco+22), yco, 100, 19, &cont->type, 0, 0, 0, 0, "Controller type");
+ but= uiDefBut(block, TEX, 1, "", (short)(xco+122), yco, (short)(width-144), 19, cont->name, 0, 31, 0, 0, "Controller name");
+ uiButSetFunc(but, make_unique_prop_names_cb, cont->name, (void*) 0);
+ uiBlockSetCol(block, BUTGREY);
+
+ ycoo= yco;
+ yco= draw_controllerbuttons(cont, block, xco, yco, width);
+ if(yco-6 < ycoo) ycoo= (yco+ycoo-20)/2;
+ }
+ else {
+ cpack(0x999999);
+ glRecti(xco+22, yco, xco+width-22,yco+19);
+ but= uiDefBut(block, LABEL, 0, controller_name(cont->type), (short)(xco+22), yco, 100, 19, cont, 0, 0, 0, 0, "Controller type");
+ uiButSetFunc(but, sca_move_controller, cont, NULL);
+ but= uiDefBut(block, LABEL, 0, cont->name,(short)(xco+122), yco,(short)(width-144), 19, cont, 0, 0, 0, 0, "Controller name");
+ uiButSetFunc(but, sca_move_controller, cont, NULL);
+ ycoo= yco;
+ }
+
+ but= uiDefIconBut(block, LINK, 0, ICON_LINK, (short)(xco+width), ycoo, 19, 19, NULL, 0, 0, 0, 0, "");
+ uiSetButLink(but, NULL, (void ***)&(cont->links), &cont->totlinks, LINK_CONTROLLER, LINK_ACTUATOR);
+
+ uiDefIconBut(block, INLINK, 0, ICON_INLINK,(short)(xco-19), ycoo, 19, 19, cont, LINK_CONTROLLER, 0, 0, 0, "");
+
+ yco-=20;
+
+ cont= cont->next;
+ }
+ yco-= 6;
+ }
+ }
+
+ /* ******************************* */
+ xco= 985; yco= 170; width= 280;
+
+ uiBlockSetCol(block, BUTGREY);
+ uiBlockSetEmboss(block, UI_EMBOSSM);
+ uiDefBlockBut(block, actuator_menu, NULL, "Actuators", xco-10, yco+35, 100, 19, "");
+ uiBlockSetCol(block, BUTGREEN);
+ uiBlockSetEmboss(block, UI_EMBOSSX);
+ uiDefButS(block, TOG|BIT|6, B_REDR, "Sel", xco+110, yco+35, (width-110)/3, 19, &G.buts->scaflag, 0, 0, 0, 0, "Show all selected Objects");
+ uiDefButS(block, TOG|BIT|7, B_REDR, "Act", xco+110+(width-110)/3, yco+35, (width-110)/3, 19, &G.buts->scaflag, 0, 0, 0, 0, "Show active Object");
+ uiDefButS(block, TOG|BIT|8, B_REDR, "Link", xco+110+2*(width-110)/3, yco+35, (width-110)/3, 19, &G.buts->scaflag, 0, 0, 0, 0, "Show linked Objects to Controller");
+
+ for(a=0; a<count; a++) {
+ ob= (Object *)idar[a];
+ uiClearButLock();
+ uiSetButLock(ob->id.lib!=0, "Can't edit library data");
+ if( (ob->scavisflag & OB_VIS_ACT) == 0) continue;
+
+ /* presume it is only objects for now */
+ uiBlockSetEmboss(block, UI_EMBOSSX);
+ uiBlockSetCol(block, BUTGREY);
+ if(ob->actuators.first) uiSetCurFont(block, UI_HELVB);
+ uiBlockSetCol(block, MIDGREY);
+ uiDefButS(block, TOG|BIT|7, B_REDR, ob->id.name+2,(short)(xco-10), yco,(short)(width-30), 19, &ob->scaflag, 0, 31, 0, 0, "Object name, click to show/hide actuators");
+ if(ob->actuators.first) uiSetCurFont(block, UI_HELV);
+ uiBlockSetCol(block, BUTSALMON);
+ uiDefButS(block, TOG|BIT|10, B_ADD_ACT, "Add",(short)(xco+width-40), yco, 50, 19, &ob->scaflag, 0, 0, 0, 0, "Add a new Actuator");
+ yco-=20;
+
+ if(ob->scaflag & OB_SHOWACT) {
+
+ act= ob->actuators.first;
+ while(act) {
+ uiBlockSetEmboss(block, UI_EMBOSSW);
+ uiBlockSetCol(block, BUTSALMON);
+ uiDefIconButS(block, TOG|BIT|1, B_DEL_ACT, ICON_X, xco, yco, 22, 19, &act->flag, 0, 0, 0, 0, "Delete Actuator");
+ uiBlockSetCol(block, BUTGREY);
+ uiDefIconButS(block, ICONTOG|BIT|0, B_REDR, ICON_RIGHTARROW, (short)(xco+width-22), yco, 22, 19, &act->flag, 0, 0, 0, 0, "Actuator settings");
+
+ if(act->flag & ACT_SHOW) {
+ uiBlockSetCol(block, BUTYELLOW);
+ act->otype= act->type;
+ uiDefButS(block, MENU, B_CHANGE_ACT, actuator_pup(ob), (short)(xco+22), yco, 100, 19, &act->type, 0, 0, 0, 0, "Actuator type");
+ but= uiDefBut(block, TEX, 1, "", (short)(xco+122), yco, (short)(width-144), 19, act->name, 0, 31, 0, 0, "Actuator name");
+ uiButSetFunc(but, make_unique_prop_names_cb, act->name, (void*) 0);
+ uiBlockSetCol(block, BUTGREY);
+
+ ycoo= yco;
+ yco= draw_actuatorbuttons(act, block, xco, yco, width);
+ if(yco-6 < ycoo) ycoo= (yco+ycoo-20)/2;
+ }
+ else {
+ set_col_actuator(act->type, 1);
+ glRecti((short)(xco+22), yco, (short)(xco+width-22),(short)(yco+19));
+ but= uiDefBut(block, LABEL, 0, actuator_name(act->type), (short)(xco+22), yco, 100, 19, act, 0, 0, 0, 0, "Actuator type");
+ uiButSetFunc(but, sca_move_actuator, act, NULL);
+ but= uiDefBut(block, LABEL, 0, act->name, (short)(xco+122), yco, (short)(width-144), 19, act, 0, 0, 0, 0, "Actuator name");
+ uiButSetFunc(but, sca_move_actuator, act, NULL);
+ ycoo= yco;
+ }
+
+ uiDefIconBut(block, INLINK, 0, ICON_INLINK,(short)(xco-19), ycoo, 19, 19, act, LINK_ACTUATOR, 0, 0, 0, "");
+
+ yco-=20;
+
+ act= act->next;
+ }
+ yco-= 6;
+ }
+ }
+
+ uiComposeLinks(block);
+ uiDrawBlock(block);
+
+ if(idar) MEM_freeN(idar);
+}
+
diff --git a/source/blender/src/editscreen.c b/source/blender/src/editscreen.c
new file mode 100644
index 00000000000..d71ae8c8e3d
--- /dev/null
+++ b/source/blender/src/editscreen.c
@@ -0,0 +1,2931 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * All screen functions that are related to the interface
+ * handling and drawing. Might be split up as well later...
+ */
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+#include "nla.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "PIL_time.h"
+
+#include "BMF_Api.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "DNA_action_types.h"
+#include "DNA_object_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_sound_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_userdef_types.h"
+
+#include "BLO_writefile.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_global.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+#include "BKE_blender.h"
+#include "BKE_screen.h"
+
+#include "BIF_editsound.h"
+#include "BIF_glutil.h"
+#include "BIF_gl.h"
+#include "BIF_graphics.h"
+#include "BIF_interface.h"
+#include "BIF_mainqueue.h"
+#include "BIF_mywindow.h"
+#include "BIF_renderwin.h"
+#include "BIF_screen.h"
+#include "BIF_space.h"
+#include "BIF_toets.h"
+#include "BIF_toolbox.h"
+#include "BIF_usiblender.h"
+#include "BIF_keyval.h"
+
+#include "BSE_edit.h"
+#include "BSE_filesel.h"
+#include "BSE_headerbuttons.h"
+#include "BSE_view.h"
+
+#include "license_key.h"
+#include "interface.h"
+#include "mydevice.h"
+#include "blendef.h"
+#include "render.h"
+
+#include "winlay.h"
+
+/* TIPS:
+ *
+ * - LET OP DE EDGES, VERTICES ERVAN MOETEN IN VOLGORDE
+ (laagste pointer eerst). Anders onvoorspelbare effecten!
+ * - probleem: flags zijn nog niet echt netjes. Altijd na gebruik
+ op nul zetten.
+ */
+
+static void testareas(void);
+static void area_autoplayscreen(void);
+static void wait_for_event(void);
+
+/* ********* Globals *********** */
+
+static Window *mainwin= NULL;
+static int prefsizx= 0, prefsizy= 0, prefstax= 0, prefstay= 0, start_maximized= 1;
+static short dodrawscreen= 0;
+static ScrArea *areawinar[MAXWIN];
+static ScrArea *g_activearea= NULL;
+short winqueue_break= 0;
+ScrArea *curarea= 0;
+
+/**********************************************************************/
+
+static void screen_set_cursor(bScreen *sc)
+{
+ if (sc->winakt>3) {
+ ScrArea *sa= areawinar[sc->winakt];
+
+ set_cursor(sa->cursor);
+ } else {
+ set_cursor(CURSOR_STD);
+ }
+}
+
+void waitcursor(int val)
+{
+ if(val) {
+ set_cursor(CURSOR_WAIT);
+ } else {
+ screen_set_cursor(G.curscreen);
+ }
+}
+
+static int choose_cursor(ScrArea *sa)
+{
+ if (sa->spacetype==SPACE_VIEW3D) {
+ if(G.obedit) return CURSOR_EDIT;
+ else if(G.f & G_VERTEXPAINT) return CURSOR_VPAINT;
+ else if(G.f & G_WEIGHTPAINT) return CURSOR_VPAINT;
+ else if(G.f & G_FACESELECT) return CURSOR_FACESEL;
+ else return CURSOR_STD;
+ } else {
+ return CURSOR_STD;
+ }
+}
+
+void wich_cursor(ScrArea *sa)
+{
+ sa->cursor= choose_cursor(sa);
+
+ screen_set_cursor(G.curscreen);
+}
+
+
+void setcursor_space(int spacetype, short cur)
+{
+ bScreen *sc;
+ ScrArea *sa;
+
+ for (sc= G.main->screen.first; sc; sc= sc->id.next)
+ for (sa= sc->areabase.first; sa; sa= sa->next)
+ if(sa->spacetype==spacetype)
+ sa->cursor= cur;
+
+ screen_set_cursor(G.curscreen);
+}
+
+
+/* ********* IN/OUT ************* */
+
+void getmouseco_sc(short *mval) /* screen coordinaten */
+{
+ getmouse(mval);
+}
+
+void getmouseco_areawin(short *mval) /* interne area coordinaten */
+{
+ getmouseco_sc(mval);
+
+ if(g_activearea && g_activearea->win) {
+ mval[0]-= g_activearea->winrct.xmin;
+ mval[1]-= g_activearea->winrct.ymin;
+ }
+}
+
+void getmouseco_headwin(short *mval) /* interne area coordinaten */
+{
+ getmouseco_sc(mval);
+
+ if(g_activearea && g_activearea->headwin) {
+ mval[0]-= g_activearea->headrct.xmin;
+ mval[1]-= g_activearea->headrct.ymin;
+ }
+}
+
+/* *********** STUFF ************** */
+
+static int scredge_is_horizontal(ScrEdge *se)
+{
+ return (se->v1->vec.y == se->v2->vec.y);
+}
+
+static ScrEdge *screen_find_active_scredge(bScreen *sc, short *mval)
+{
+ ScrEdge *se;
+
+ for (se= sc->edgebase.first; se; se= se->next) {
+ if (scredge_is_horizontal(se)) {
+ if (abs(mval[1]-se->v1->vec.y)<=EDGEWIDTH2 &&
+ abs(mval[0]-se->v1->vec.x)<=abs(se->v2->vec.x-se->v1->vec.x))
+ return se;
+ } else {
+ if (abs(mval[0]-se->v1->vec.x)<=EDGEWIDTH2 &&
+ abs(mval[1]-se->v1->vec.y)<=abs(se->v2->vec.y-se->v1->vec.y))
+ return se;
+ }
+ }
+
+ return NULL;
+}
+
+void areawinset(short win)
+{
+ if(win>3) {
+ curarea= areawinar[win];
+ if(curarea==0) {
+ printf("error in areawinar %d ,areawinset\n", win);
+ return;
+ }
+
+ switch(curarea->spacetype) {
+ case SPACE_VIEW3D:
+ G.vd= curarea->spacedata.first;
+ break;
+ case SPACE_IPO:
+ if(G.sipo != curarea->spacedata.first) allqueue(REDRAWBUTSANIM, 0);
+ G.sipo= curarea->spacedata.first;
+ G.v2d= &G.sipo->v2d;
+ break;
+ case SPACE_BUTS:
+ G.buts= curarea->spacedata.first;
+ G.v2d= &G.buts->v2d;
+ break;
+ case SPACE_SEQ: {
+ SpaceSeq *sseq= curarea->spacedata.first;
+ G.v2d= &sseq->v2d;
+ break;
+ }
+ case SPACE_OOPS:
+ G.soops= curarea->spacedata.first;
+ G.v2d= &G.soops->v2d;
+ break;
+ case SPACE_IMAGE:
+ G.sima= curarea->spacedata.first;
+ G.v2d= &G.sima->v2d;
+ case SPACE_SOUND:
+ G.ssound= curarea->spacedata.first;
+ G.v2d= &G.ssound->v2d;
+ break;
+ case SPACE_ACTION:
+ G.saction= curarea->spacedata.first;
+ G.v2d= &G.saction->v2d;
+ break;
+ case SPACE_NLA:
+ G.snla= curarea->spacedata.first;
+ G.v2d= &G.snla->v2d;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if(win) mywinset(win);
+}
+
+void headerbox(int selcol, int width)
+{
+ if(selcol) glClearColor(.75, .75, .75, 0.0);
+ else glClearColor(.65, .65, .65, 0.0);
+
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ glColor3ub(0, 0, 0);
+ sdrawbox(0, 0, width, HEADERY);
+
+ glColor3ub(220, 220, 220);
+ sdrawline(0, HEADERY-1, width, HEADERY-1);
+
+ glColor3ub(176, 176, 176);
+ sdrawline(0, HEADERY-2, width, HEADERY-2);
+
+ glColor3ub(128, 128, 128);
+ sdrawline(0, 2, width, 2);
+
+ glColor3ub(64, 64, 64);
+ sdrawline(0, 1, width, 1);
+
+ glColor3ub(0, 0, 0);
+ sdrawline(0, 0, width, 0);
+}
+
+int area_is_active_area(ScrArea *area)
+{
+ return (g_activearea && area==g_activearea);
+}
+
+void scrarea_do_headdraw(ScrArea *area)
+{
+ areawinset(area->headwin);
+
+ headerbox(area_is_active_area(area), area->winx+100);
+
+ switch(area->spacetype) {
+ case SPACE_FILE: file_buttons(); break;
+ case SPACE_INFO: info_buttons(); break;
+ case SPACE_VIEW3D: view3d_buttons(); break;
+ case SPACE_IPO: ipo_buttons(); break;
+ case SPACE_BUTS: buts_buttons(); break;
+ case SPACE_SEQ: seq_buttons(); break;
+ case SPACE_IMAGE: image_buttons(); break;
+ case SPACE_IMASEL: imasel_buttons(); break;
+ case SPACE_OOPS: oops_buttons(); break;
+ case SPACE_TEXT: text_buttons(); break;
+ case SPACE_SOUND: sound_buttons(); break;
+ case SPACE_ACTION: action_buttons(); break;
+ case SPACE_NLA: nla_buttons(); break;
+ }
+
+ area->head_swap= WIN_BACK_OK;
+}
+void scrarea_do_headchange(ScrArea *area)
+{
+ float ofs= area->headbutofs;
+
+ if (area->headertype==HEADERDOWN) {
+ bwin_ortho2(area->headwin, 0.5+ofs, area->headrct.xmax-area->headrct.xmin-0.5+ofs, +0.6, area->headrct.ymax-area->headrct.ymin+0.6);
+ } else {
+ bwin_ortho2(area->headwin, -0.5+ofs, area->headrct.xmax-area->headrct.xmin-0.5+ofs, -0.5, area->headrct.ymax-area->headrct.ymin-0.5);
+ }
+}
+
+
+static void openheadwin(ScrArea *sa);
+static void closeheadwin(ScrArea *sa);
+
+static void scrarea_change_headertype(ScrArea *sa, int newtype)
+{
+ sa->headertype= newtype;
+
+ if (!newtype) {
+ if (sa->headwin) {
+ uiFreeBlocksWin(&sa->uiblocks, sa->headwin);
+ closeheadwin(sa);
+ }
+ } else {
+ if (!sa->headwin) {
+ openheadwin(sa);
+ }
+ }
+
+ testareas();
+ winqueue_break= 1;
+}
+
+static void headmenu(ScrArea *sa)
+{
+ short val= pupmenu("Header %t|Top%x2|Bottom %x1|No Header %x0");
+
+ if(val> -1) {
+ scrarea_change_headertype(sa, val);
+ }
+}
+
+static void addqueue_ext(short win, unsigned short event, short val, char ascii)
+{
+ if (win<4 || !areawinar[win]) {
+ printf("bad call to addqueue: %d (%d, %d)\n", win, event, val);
+ } else {
+ bwin_qadd(win, event, val, ascii);
+ }
+}
+
+void addqueue(short win, unsigned short event, short val)
+{
+ addqueue_ext(win, event, val, 0);
+}
+
+void scrarea_queue_winredraw(ScrArea *area)
+{
+ addqueue(area->win, REDRAW, 1);
+}
+void scrarea_queue_headredraw(ScrArea *area)
+{
+ if (area->headwin) addqueue(area->headwin, REDRAW, 1);
+}
+void scrarea_queue_redraw(ScrArea *area)
+{
+ scrarea_queue_winredraw(area);
+ scrarea_queue_headredraw(area);
+}
+
+static void scrollheader(ScrArea *area);
+static void scrarea_dispatch_header_events(ScrArea *sa)
+{
+ ScrArea *tempsa;
+ short do_redraw=0, do_change=0;
+
+ areawinset(sa->headwin);
+
+ while(bwin_qtest(sa->headwin)) {
+ char ascii;
+ short val;
+ unsigned short event= bwin_qread(sa->headwin, &val, &ascii);
+
+ if(val) {
+ if( uiDoBlocks(&curarea->uiblocks, event)!=UI_NOTHING ) event= 0;
+
+ switch(event) {
+ case UI_BUT_EVENT:
+ do_headerbuttons(val);
+ break;
+
+ case LEFTMOUSE:
+ if (G.qual & LR_CTRLKEY) {
+ window_lower(mainwin);
+ } else {
+ window_raise(mainwin);
+ }
+ break;
+
+ case MIDDLEMOUSE:
+ scrollheader(sa);
+ break;
+ case RIGHTMOUSE:
+ headmenu(sa);
+ break;
+ case REDRAW:
+ do_redraw= 1;
+ break;
+ case CHANGED:
+ sa->head_swap= 0;
+ do_change= 1;
+ do_redraw= 1;
+ break;
+ default:
+ if (winqueue_break == 0) {
+ scrarea_do_winhandle(sa, event, val, ascii);
+ if (winqueue_break == 0) areawinset(sa->headwin);
+ }
+ }
+
+ if(winqueue_break) return;
+ }
+ }
+
+ /* test: bestaat window nog */
+ tempsa= areawinar[sa->headwin];
+ if(tempsa==0) return;
+
+ /* dit onderscheid loopt niet lekker... */
+ if(do_change) scrarea_do_headchange(sa);
+ if(do_redraw) scrarea_do_headdraw(sa);
+}
+
+static void scrarea_dispatch_events(ScrArea *sa)
+{
+ ScrArea *tempsa;
+ short do_redraw=0, do_change=0;
+
+ if(sa!=curarea || sa->win!=mywinget()) areawinset(sa->win);
+
+ while(bwin_qtest(sa->win)) {
+ char ascii;
+ short val;
+ unsigned short event= bwin_qread(sa->win, &val, &ascii);
+
+ if(event==REDRAW) {
+ do_redraw= 1;
+ }
+ else if(event==CHANGED) {
+ sa->win_swap= 0;
+ do_change= 1;
+ do_redraw= 1;
+ }
+ else {
+ scrarea_do_winhandle(sa, event, val, ascii);
+ }
+
+ if(winqueue_break) return;
+ }
+
+ /* test: bestaat window nog */
+ tempsa= areawinar[sa->win];
+ if(tempsa==0) return;
+
+ if (do_change || do_redraw) {
+ areawinset(sa->win);
+ if(do_change)
+ scrarea_do_winchange(curarea);
+ if(do_redraw)
+ scrarea_do_windraw(curarea);
+ }
+}
+
+/***/
+
+
+void markdirty_all()
+{
+ ScrArea *sa;
+
+ for (sa= G.curscreen->areabase.first; sa; sa= sa->next) {
+ scrarea_queue_winredraw(sa);
+ sa->win_swap &= ~WIN_FRONT_OK;
+
+ scrarea_queue_headredraw(sa);
+ sa->head_swap &= ~WIN_FRONT_OK;
+ }
+}
+
+int is_allowed_to_change_screen(bScreen *new)
+{
+ /* niet als curscreen is full
+ * niet als obedit && old->scene!=new->scene
+ */
+
+ if(new==0) return 0;
+ if(G.curscreen->full != SCREENNORMAL) return 0;
+ if(curarea->full) return 0;
+ if(G.obedit) {
+ if(G.curscreen->scene!=new->scene) return 0;
+ }
+ return 1;
+}
+
+void splash(void *data, int datasize, char *string)
+{
+ ImBuf *bbuf;
+ int oldwin;
+ short val;
+
+ bbuf= IMB_ibImageFromMemory((int *)data, datasize, IB_rect);
+
+ if (bbuf) {
+
+ oldwin = mywinget();
+ mywinset(G.curscreen->mainwin);
+
+ if (string) {
+ int x, y, maxy;
+ unsigned int *rect;
+
+ rect = bbuf->rect;
+ maxy = MIN2(bbuf->y, 18);
+
+ for (y = 0; y < maxy; y++) {
+ for (x = 0; x < bbuf->x; x++) {
+ *rect = 0xffffffff;
+ rect++;
+ }
+ }
+ }
+ glDrawBuffer(GL_FRONT);
+
+ /*
+ // this dims the whole screen a bit. I didn't like it afterall
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glColor4f(0.0,0.0,0.0,0.3);
+ glRecti(0, 0, G.curscreen->sizex, G.curscreen->sizey);
+ glDisable(GL_BLEND);
+ */
+
+ glRasterPos2i((prefsizx-bbuf->x)/2, (prefsizy-bbuf->y)/2);
+ glDrawPixels(bbuf->x, bbuf->y, GL_RGBA, GL_UNSIGNED_BYTE, bbuf->rect);
+
+ if (string) {
+ void *font;
+ int width;
+
+ if (BMF_GetStringWidth(font= G.font, string) > bbuf->x)
+ if (BMF_GetStringWidth(font= G.fonts, string) > bbuf->x)
+ font= G.fontss;
+
+ width= BMF_GetStringWidth(font, string);
+
+ glColor3ub(0, 0, 0);
+ glRasterPos2i((prefsizx-width)/2, (prefsizy-bbuf->y)/2 + 6);
+ BMF_DrawString(font, string);
+ }
+
+ glFinish();
+ glDrawBuffer(GL_BACK);
+
+ IMB_freeImBuf(bbuf);
+
+ // flush input buffers ....
+ // this might break some things
+
+ while (get_mbut()) {
+ BIF_wait_for_statechange();
+ }
+ while(qtest()) {
+ extern_qread(&val);
+ }
+
+ wait_for_event();
+
+ mywinset(oldwin);
+ markdirty_all();
+ mainqenter(DRAWEDGES, 1);
+ }
+}
+
+static void moveareas(ScrEdge *edge);
+static void joinarea(ScrArea *sa, ScrEdge *onedge);
+static void splitarea_interactive(ScrArea *area, ScrEdge *onedge);
+
+static void screen_edge_edit_event(ScrArea *actarea, ScrEdge *actedge, short evt, short val) {
+ if (val) {
+ // don't allow users to edit full screens
+ if (actarea && actarea->full) {
+ return;
+ }
+
+ if (evt==LEFTMOUSE) {
+ moveareas(actedge);
+ } else if (evt==MIDDLEMOUSE || evt==RIGHTMOUSE) {
+ int edgeop;
+
+ if (!actarea->headertype) {
+ edgeop= pupmenu("Split Area|Join Areas|Add header");
+ } else {
+ edgeop= pupmenu("Split Area|Join Areas|No header");
+ }
+
+ if (edgeop==1) {
+ splitarea_interactive(actarea, actedge);
+ } else if (edgeop==2) {
+ joinarea(actarea, actedge);
+ } else if (edgeop==3) {
+ scrarea_change_headertype(actarea, actarea->headertype?0:HEADERDOWN);
+ }
+ }
+ }
+}
+
+/***/
+
+void mywindow_init_mainwin(Window *win, int orx, int ory, int sizex, int sizey);
+void test_scale_screen(bScreen *);
+
+static void resize_screens(int x, int y, int w, int h) {
+ prefstax= x;
+ prefstay= y;
+ prefsizx= w;
+ prefsizy= h;
+
+ test_scale_screen(G.curscreen);
+ testareas();
+}
+
+static void init_mainwin(void)
+{
+ int orx, ory, sizex, sizey;
+
+ glEnable(GL_SCISSOR_TEST);
+
+ window_get_position(mainwin, &orx, &ory);
+ window_get_size(mainwin, &sizex, &sizey);
+
+ /* XXX, temporary stupid fix for minimize at windows */
+ if (!sizex && !sizey) {
+ return;
+ }
+
+ mywindow_init_mainwin(mainwin, orx, ory, sizex, sizey);
+ resize_screens(orx, ory, sizex, sizey);
+}
+
+/***/
+
+static short afterqueue[MAXQUEUE][3];
+static int nafterqitems= 0;
+
+void addafterqueue(short win, unsigned short evt, short val)
+{
+ if (nafterqitems<MAXQUEUE) {
+ afterqueue[nafterqitems][0]= win;
+ afterqueue[nafterqitems][1]= evt;
+ afterqueue[nafterqitems][2]= val;
+ nafterqitems++;
+ }
+}
+
+static void append_afterqueue(void)
+{
+ while (nafterqitems) {
+ short win= afterqueue[nafterqitems-1][0];
+ unsigned short evt= afterqueue[nafterqitems-1][1];
+ short val= afterqueue[nafterqitems-1][2];
+
+ addqueue(win, evt, val);
+
+ nafterqitems--;
+ }
+}
+
+static char ext_load_str[256]= {0, 0};
+void add_readfile_event(char *filename)
+{
+ mainqenter(LOAD_FILE, 1);
+ strcpy(ext_load_str, filename);
+ BLI_convertstringcode(ext_load_str, G.sce, G.scene->r.cfra);
+}
+
+static short ext_reshape= 0, ext_redraw=0, ext_inputchange=0, ext_mousemove=0;
+
+static void flush_extqd_events(void) {
+ if (ext_inputchange) {
+ mainqenter(INPUTCHANGE, ext_inputchange);
+ } else if (ext_reshape) {
+ mainqenter(RESHAPE, ext_redraw);
+ } else if (ext_redraw) {
+ mainqenter(REDRAW, ext_redraw);
+ } else if (ext_mousemove) {
+ short mouse[2];
+
+ getmouseco_sc(mouse);
+
+ mainqenter(MOUSEX, mouse[0]);
+ mainqenter(MOUSEY, mouse[1]);
+ }
+
+ ext_inputchange= ext_reshape= ext_redraw= ext_mousemove= 0;
+}
+
+unsigned short qtest(void)
+{
+ if (!mainqtest()) {
+ winlay_process_events(0);
+ }
+
+ return mainqtest();
+}
+
+ /* return true if events are waiting anywhere */
+int anyqtest(void)
+{
+ ScrArea *sa;
+
+ if (nafterqitems || qtest()) return 1;
+
+ for (sa= G.curscreen->areabase.first; sa; sa= sa->next) {
+ if (bwin_qtest(sa->win)) return 1;
+ if (sa->headwin && bwin_qtest(sa->headwin)) return 1;
+ }
+
+ return 0;
+}
+
+static void wait_for_event(void)
+{
+ while (!mainqtest()) {
+ winlay_process_events(1);
+ }
+}
+
+unsigned short screen_qread(short *val, char *ascii)
+{
+ unsigned short event;
+
+ wait_for_event();
+
+ event= mainqread(val, ascii);
+
+ if(event==RIGHTSHIFTKEY || event==LEFTSHIFTKEY) {
+ if(*val) G.qual |= LR_SHIFTKEY;
+ else G.qual &= ~LR_SHIFTKEY;
+ }
+ else if(event==RIGHTALTKEY || event==LEFTALTKEY) {
+ if(*val) G.qual |= LR_ALTKEY;
+ else G.qual &= ~LR_ALTKEY;
+ }
+ else if(event==RIGHTCTRLKEY || event==LEFTCTRLKEY) {
+ if(*val) G.qual |= LR_CTRLKEY;
+ else G.qual &= ~LR_CTRLKEY;
+ }
+
+ return event;
+}
+
+unsigned short extern_qread_ext(short *val, char *ascii)
+{
+ /* bewaart de laatste INPUTCHANGE en de laatste REDRAW */
+ unsigned short event;
+
+ event= screen_qread(val, ascii);
+ if(event==RESHAPE) ext_reshape= *val;
+ else if(event==REDRAW) ext_redraw= *val;
+ else if(event==INPUTCHANGE) ext_inputchange= *val;
+ else if(event==MOUSEY || event==MOUSEX) ext_mousemove= 1;
+ else if((G.qual & LR_CTRLKEY) && event==F3KEY) {
+ BIF_screendump();
+ }
+
+ return event;
+}
+unsigned short extern_qread(short *val)
+{
+ char ascii;
+ return extern_qread_ext(val, &ascii);
+}
+
+void reset_autosave(void) {
+ window_set_timer(mainwin, U.savetime*60*1000, AUTOSAVE_FILE);
+}
+
+static void screen_dispatch_events(void) {
+ int events_remaining= 1;
+ ScrArea *sa;
+
+ while (events_remaining) {
+ events_remaining= 0;
+
+ winqueue_break= 0;
+ for (sa= G.curscreen->areabase.first; sa; sa= sa->next) {
+ /* bewust eerst header afhandelen, dan rest. Header is soms init */
+ if (sa->headwin && bwin_qtest(sa->headwin)) {
+ scrarea_dispatch_header_events(sa);
+ events_remaining= 1;
+ }
+ if (winqueue_break) break;
+
+ if (bwin_qtest(sa->win)) {
+ scrarea_dispatch_events(sa);
+ events_remaining= 1;
+ }
+ if (winqueue_break) break;
+ }
+
+ if (winqueue_break) break;
+ }
+
+ if (dodrawscreen) {
+ drawscreen();
+ dodrawscreen= 0;
+ }
+
+ screen_swapbuffers();
+}
+
+static ScrArea *screen_find_area_for_pt(bScreen *sc, short *mval)
+{
+ ScrArea *sa;
+
+ for (sa= sc->areabase.first; sa; sa= sa->next)
+ if (BLI_in_rcti(&sa->totrct, mval[0], mval[1]))
+ return sa;
+
+ return NULL;
+}
+
+void screenmain(void)
+{
+ int has_input= 1;
+ int firsttime = 1;
+ while (1) {
+ unsigned short event;
+ short val, towin;
+ char ascii;
+
+ flush_extqd_events();
+ if (nafterqitems && !qtest()) {
+ append_afterqueue();
+ event= 0;
+ } else {
+ event= screen_qread(&val, &ascii);
+ }
+
+ window_make_active(mainwin);
+
+ if (event==INPUTCHANGE) {
+ has_input= val;
+ }
+
+ if (has_input) {
+ ScrArea *newactarea;
+ int newactwin;
+ short mval[2];
+
+ getmouseco_sc(mval);
+ newactarea= screen_find_area_for_pt(G.curscreen, mval);
+
+ if (newactarea) {
+ if (BLI_in_rcti(&newactarea->headrct, mval[0], mval[1])) {
+ newactwin= newactarea->headwin;
+ } else {
+ newactwin= newactarea->win;
+ }
+ } else {
+ newactwin= 0;
+ }
+
+ if (newactarea && (newactarea != g_activearea)) {
+ if (g_activearea) scrarea_queue_headredraw(g_activearea);
+ scrarea_queue_headredraw(newactarea);
+ set_cursor(newactarea->cursor);
+ g_activearea= newactarea;
+ }
+
+ G.curscreen->winakt= newactwin;
+ if (G.curscreen->winakt) {
+ areawinset(G.curscreen->winakt);
+ set_cursor(choose_cursor(g_activearea));
+ }
+ } else {
+ if (g_activearea) {
+ scrarea_queue_headredraw(g_activearea);
+ }
+ g_activearea= NULL;
+ G.curscreen->winakt= 0;
+ }
+
+ towin= 0;
+ if (event==WINCLOSE) {
+ exit_usiblender();
+ }
+ else if (event==DRAWEDGES) {
+ dodrawscreen= 1;
+ }
+ else if (event==RESHAPE) {
+ init_mainwin();
+ markdirty_all();
+ dodrawscreen= 1;
+ }
+ else if (event==REDRAW) {
+ markdirty_all();
+ dodrawscreen= 1;
+ }
+ else if (event==AUTOSAVE_FILE) {
+ BIF_write_autosave();
+ }
+ else if (event==LOAD_FILE) {
+ BIF_read_file(ext_load_str);
+ sound_initialize_sounds();
+ }
+ else {
+ towin= 1;
+ }
+
+ if (!g_activearea) {
+ towin= 0;
+ }
+ else if (!G.curscreen->winakt) {
+ ScrEdge *actedge;
+ short mval[2];
+
+ getmouseco_sc(mval);
+ actedge= screen_find_active_scredge(G.curscreen, mval);
+
+ if (actedge) {
+ if (scredge_is_horizontal(actedge)) {
+ set_cursor(CURSOR_Y_MOVE);
+ } else {
+ set_cursor(CURSOR_X_MOVE);
+ }
+
+ screen_edge_edit_event(g_activearea, actedge, event, val);
+ } else {
+ set_cursor(CURSOR_STD);
+ }
+
+ towin= 0;
+ }
+ else if (event==QKEY) {
+ if((G.obedit && G.obedit->type==OB_FONT && g_activearea->spacetype==SPACE_VIEW3D)||g_activearea->spacetype==SPACE_TEXT);
+ else {
+ if(val && okee("QUIT BLENDER")) exit_usiblender();
+ towin= 0;
+ }
+ }
+ else if (event==ZKEY) {
+ if(val && G.qual==(LR_ALTKEY|LR_SHIFTKEY|LR_CTRLKEY)) {
+ extern void set_debug_swapbuffers_ovveride(bScreen *sc, int mode);
+
+ int which= pupmenu("Swapbuffers%t|Simple|Debug|DebugSwap|Redraw|Default|KillSwap");
+
+ switch (which) {
+ case 1: set_debug_swapbuffers_ovveride(G.curscreen, 's'); break;
+ case 2: set_debug_swapbuffers_ovveride(G.curscreen, 'd'); break;
+ case 3: set_debug_swapbuffers_ovveride(G.curscreen, 'f'); break;
+ case 4: set_debug_swapbuffers_ovveride(G.curscreen, 'r'); break;
+ case 5: set_debug_swapbuffers_ovveride(G.curscreen, 0); break;
+ case 6:
+ if (g_activearea) {
+ g_activearea->head_swap= 0;
+ g_activearea->win_swap= 0;
+ }
+ break;
+ }
+ towin= 0;
+ }
+ }
+ else if (event==SPACEKEY) {
+ if((G.obedit && G.obedit->type==OB_FONT && g_activearea->spacetype==SPACE_VIEW3D)||g_activearea->spacetype==SPACE_TEXT);
+ else {
+ if(val) toolbox();
+ towin= 0;
+ }
+ }
+ else if(ELEM(event, LEFTARROWKEY, RIGHTARROWKEY)) {
+ if(val && (G.qual & LR_CTRLKEY)) {
+ bScreen *sc= (event==LEFTARROWKEY)?G.curscreen->id.prev:G.curscreen->id.next;
+ if(is_allowed_to_change_screen(sc)) setscreen(sc);
+ g_activearea= NULL;
+ towin= 0;
+ }
+ }
+ else if(ELEM(event, UPARROWKEY, DOWNARROWKEY)) {
+ if(val && (G.qual & LR_CTRLKEY)) {
+ area_fullscreen();
+ g_activearea= NULL;
+ towin= 0;
+ }
+ }
+
+ if (towin) {
+ if (blenderqread(event, val))
+ addqueue_ext(G.curscreen->winakt, event, val, ascii);
+ }
+
+ /* only process subwindow queue's once the
+ * main queue has been emptyied.
+ */
+ event= qtest();
+ if (event==0 || event==EXECUTE) {
+ screen_dispatch_events();
+ }
+
+ /* Bizar hack. The event queue has mutated... */
+ if ( (firsttime) && (event == 0) ) {
+ if (G.fileflags & G_FILE_AUTOPLAY) {
+ // SET AUTOPLAY in G.flags for
+ // other fileloads
+
+ G.flags |= G_FLAGS_AUTOPLAY;
+ area_autoplayscreen();
+
+ // Let The Games Begin
+ // fake a 'p' keypress
+
+ mainqenter(PKEY, 1);
+ } else {
+ extern char datatoc_splash_jpg[];
+ extern int datatoc_splash_jpg_size;
+ extern char datatoc_ton[];
+ extern int datatoc_tonize;
+
+ if (! ((G.main->versionfile >= G.version)
+ || G.save_over)) {
+ if (LICENSE_KEY_VALID) {
+ splash((void *)datatoc_ton,
+ datatoc_tonize,
+ NULL);
+ } else {
+ splash((void *)datatoc_splash_jpg,
+ datatoc_splash_jpg_size,
+ NULL);
+ }
+ }
+ }
+ firsttime = 0;
+ }
+ }
+}
+
+void mainwindow_raise(void) {
+ window_raise(mainwin);
+}
+void mainwindow_make_active(void) {
+ window_make_active(mainwin);
+}
+void mainwindow_close(void) {
+ window_destroy(mainwin);
+ mainwin= NULL;
+}
+
+/* ********* AREAS ************* */
+
+void setprefsize(int stax, int stay, int sizx, int sizy)
+{
+ int scrwidth, scrheight;
+
+ winlay_get_screensize(&scrwidth, &scrheight);
+
+ if(stax<0) stax= 0;
+ if(stay<0) stay= 0;
+ if(sizx<320) sizx= 320;
+ if(sizy<256) sizy= 256;
+
+ if(stax+sizx>scrwidth) sizx= scrwidth-stax;
+ if(stay+sizy>scrheight) sizy= scrheight-stay;
+ if(sizx<320 || sizy<256) {
+ printf("ERROR: illegal prefsize\n");
+ return;
+ }
+
+ prefstax= stax;
+ prefstay= stay;
+ prefsizx= sizx;
+ prefsizy= sizy;
+
+ start_maximized= 0;
+}
+
+
+static ScrVert *screen_addvert(bScreen *sc, short x, short y)
+{
+ ScrVert *sv= MEM_callocN(sizeof(ScrVert), "addscrvert");
+ sv->vec.x= x;
+ sv->vec.y= y;
+
+ BLI_addtail(&sc->vertbase, sv);
+ return sv;
+}
+
+static void sortscrvert(ScrVert **v1, ScrVert **v2)
+{
+ ScrVert *tmp;
+
+ if ((long)*v1 > (long)*v2) {
+ tmp= *v1;
+ *v1= *v2;
+ *v2= tmp;
+ }
+}
+
+static ScrEdge *screen_addedge(bScreen *sc, ScrVert *v1, ScrVert *v2)
+{
+ ScrEdge *se= MEM_callocN(sizeof(ScrEdge), "addscredge");
+
+ sortscrvert(&v1, &v2);
+ se->v1= v1;
+ se->v2= v2;
+
+ BLI_addtail(&sc->edgebase, se);
+ return se;
+}
+
+static ScrEdge *screen_findedge(bScreen *sc, ScrVert *v1, ScrVert *v2)
+{
+ ScrEdge *se;
+
+ sortscrvert(&v1, &v2);
+ for (se= sc->edgebase.first; se; se= se->next)
+ if(se->v1==v1 && se->v2==v2)
+ return se;
+
+ return NULL;
+}
+
+static void removedouble_scrverts(void)
+{
+ ScrVert *v1, *verg;
+ ScrEdge *se;
+ ScrArea *sa;
+
+ verg= G.curscreen->vertbase.first;
+ while(verg) {
+ if(verg->newv==0) { /* !!! */
+ v1= verg->next;
+ while(v1) {
+ if(v1->newv==0) { /* !?! */
+ if(v1->vec.x==verg->vec.x && v1->vec.y==verg->vec.y) {
+ /* printf("doublevert\n"); */
+ v1->newv= verg;
+ }
+ }
+ v1= v1->next;
+ }
+ }
+ verg= verg->next;
+ }
+
+ /* vervang pointers in edges en vlakken */
+ se= G.curscreen->edgebase.first;
+ while(se) {
+ if(se->v1->newv) se->v1= se->v1->newv;
+ if(se->v2->newv) se->v2= se->v2->newv;
+ /* edges zijn veranderd: dus.... */
+ sortscrvert(&(se->v1), &(se->v2));
+ se= se->next;
+ }
+ sa= G.curscreen->areabase.first;
+ while(sa) {
+ if(sa->v1->newv) sa->v1= sa->v1->newv;
+ if(sa->v2->newv) sa->v2= sa->v2->newv;
+ if(sa->v3->newv) sa->v3= sa->v3->newv;
+ if(sa->v4->newv) sa->v4= sa->v4->newv;
+ sa= sa->next;
+ }
+
+ /* verwijderen */
+ verg= G.curscreen->vertbase.first;
+ while(verg) {
+ v1= verg->next;
+ if(verg->newv) {
+ BLI_remlink(&G.curscreen->vertbase, verg);
+ MEM_freeN(verg);
+ }
+ verg= v1;
+ }
+
+}
+
+static void removenotused_scrverts(void)
+{
+ ScrVert *sv, *svn;
+ ScrEdge *se;
+
+ /* ga ervan uit dat de edges goed zijn */
+
+ se= G.curscreen->edgebase.first;
+ while(se) {
+ se->v1->flag= 1;
+ se->v2->flag= 1;
+ se= se->next;
+ }
+
+ sv= G.curscreen->vertbase.first;
+ while(sv) {
+ svn= sv->next;
+ if(sv->flag==0) {
+ BLI_remlink(&G.curscreen->vertbase, sv);
+ MEM_freeN(sv);
+ }
+ else sv->flag= 0;
+ sv= svn;
+ }
+}
+
+static void removedouble_scredges(void)
+{
+ ScrEdge *verg, *se, *sn;
+
+ /* vergelijken */
+ verg= G.curscreen->edgebase.first;
+ while(verg) {
+ se= verg->next;
+ while(se) {
+ sn= se->next;
+ if(verg->v1==se->v1 && verg->v2==se->v2) {
+ BLI_remlink(&G.curscreen->edgebase, se);
+ MEM_freeN(se);
+ }
+ se= sn;
+ }
+ verg= verg->next;
+ }
+}
+
+static void removenotused_scredges(void)
+{
+ ScrEdge *se, *sen;
+ ScrArea *sa;
+ int a=0;
+
+ /* zet flag als edge gebruikt wordt in area */
+ sa= G.curscreen->areabase.first;
+ while(sa) {
+ se= screen_findedge(G.curscreen, sa->v1, sa->v2);
+ if(se==0) printf("error: area %d edge 1 bestaat niet\n", a);
+ else se->flag= 1;
+ se= screen_findedge(G.curscreen, sa->v2, sa->v3);
+ if(se==0) printf("error: area %d edge 2 bestaat niet\n", a);
+ else se->flag= 1;
+ se= screen_findedge(G.curscreen, sa->v3, sa->v4);
+ if(se==0) printf("error: area %d edge 3 bestaat niet\n", a);
+ else se->flag= 1;
+ se= screen_findedge(G.curscreen, sa->v4, sa->v1);
+ if(se==0) printf("error: area %d edge 4 bestaat niet\n", a);
+ else se->flag= 1;
+ sa= sa->next;
+ a++;
+ }
+ se= G.curscreen->edgebase.first;
+ while(se) {
+ sen= se->next;
+ if(se->flag==0) {
+ BLI_remlink(&G.curscreen->edgebase, se);
+ MEM_freeN(se);
+ }
+ else se->flag= 0;
+ se= sen;
+ }
+}
+
+void calc_arearcts(ScrArea *sa)
+{
+
+ if(sa->v1->vec.x>0) sa->totrct.xmin= sa->v1->vec.x+EDGEWIDTH2+1;
+ else sa->totrct.xmin= sa->v1->vec.x;
+ if(sa->v4->vec.x<G.curscreen->sizex-1) sa->totrct.xmax= sa->v4->vec.x-EDGEWIDTH2-1;
+ else sa->totrct.xmax= sa->v4->vec.x;
+
+ if(sa->v1->vec.y>0) sa->totrct.ymin= sa->v1->vec.y+EDGEWIDTH2+1;
+ else sa->totrct.ymin= sa->v1->vec.y;
+ if(sa->v2->vec.y<G.curscreen->sizey-1) sa->totrct.ymax= sa->v2->vec.y-EDGEWIDTH2-1;
+ else sa->totrct.ymax= sa->v2->vec.y;
+
+ sa->winrct= sa->totrct;
+ if(sa->headertype) {
+ sa->headrct= sa->totrct;
+ if(sa->headertype==HEADERDOWN) {
+ sa->headrct.ymax= sa->headrct.ymin+HEADERY-1;
+ sa->winrct.ymin= sa->headrct.ymax+1;
+ }
+ else if(sa->headertype==HEADERTOP) {
+ sa->headrct.ymin= sa->headrct.ymax-HEADERY+1;
+ sa->winrct.ymax= sa->headrct.ymin-1;
+ }
+ }
+ if(sa->winrct.ymin>sa->winrct.ymax) sa->winrct.ymin= sa->winrct.ymax;
+
+ /* als speedup voor berekeningen */
+ sa->winx= sa->winrct.xmax-sa->winrct.xmin+1;
+ sa->winy= sa->winrct.ymax-sa->winrct.ymin+1;
+}
+
+static void openheadwin(ScrArea *sa)
+{
+ sa->headwin= myswinopen(G.curscreen->mainwin,
+ sa->headrct.xmin, sa->headrct.xmax, sa->headrct.ymin, sa->headrct.ymax);
+
+ glMatrixMode(GL_MODELVIEW);
+
+ areawinar[sa->headwin]= sa; /* anders doet addqueue het niet */
+ addqueue(sa->headwin, CHANGED, 1);
+}
+
+static void openareawin(ScrArea *sa)
+{
+ sa->win= myswinopen(G.curscreen->mainwin,
+ sa->winrct.xmin, sa->winrct.xmax, sa->winrct.ymin, sa->winrct.ymax);
+
+ areawinar[sa->win]= sa; /* anders doet addqueue het niet */
+ addqueue(sa->win, CHANGED, 1);
+}
+
+static void closeheadwin(ScrArea *sa)
+{
+ if(sa->headwin) mywinclose(sa->headwin);
+ sa->headwin= 0;
+}
+
+static void closeareawin(ScrArea *sa)
+{
+ uiFreeBlocksWin(&sa->uiblocks, sa->win);
+
+ if(sa->win) mywinclose(sa->win);
+ sa->win= 0;
+}
+
+static void del_area(ScrArea *sa)
+{
+ closeareawin(sa);
+ closeheadwin(sa);
+
+ freespacelist(&sa->spacedata);
+
+ uiFreeBlocks(&sa->uiblocks);
+
+ if(sa==curarea) curarea= 0;
+ if(sa==g_activearea) g_activearea= 0;
+}
+
+static void copy_areadata(ScrArea *sa1, ScrArea *sa2)
+{
+ sa1->headertype= sa2->headertype;
+ sa1->spacetype= sa2->spacetype;
+ Mat4CpyMat4(sa1->winmat, sa2->winmat);
+
+ freespacelist(&sa1->spacedata);
+
+ duplicatespacelist(sa1, &sa1->spacedata, &sa2->spacedata);
+}
+
+static ScrArea *screen_addarea(bScreen *sc, ScrVert *v1, ScrVert *v2, ScrVert *v3, ScrVert *v4, short headertype, short spacetype)
+{
+ ScrArea *sa= MEM_callocN(sizeof(ScrArea), "addscrarea");
+ sa->cursor= CURSOR_STD;
+ sa->v1= v1;
+ sa->v2= v2;
+ sa->v3= v3;
+ sa->v4= v4;
+ sa->headertype= headertype;
+ sa->spacetype= spacetype;
+
+ calc_arearcts(sa);
+
+ if (sa->headertype) openheadwin(sa);
+ openareawin(sa);
+
+ BLI_addtail(&sc->areabase, sa);
+ return sa;
+}
+
+static int rcti_eq(rcti *a, rcti *b) {
+ return ((a->xmin==b->xmin && a->xmax==b->xmax) &&
+ (a->ymin==b->ymin && a->ymax==b->ymax));
+}
+
+static void testareas(void)
+{
+ ScrArea *sa;
+
+ /* testen of header er moet zijn, of weg moet, of verplaatst */
+ /* testen of window er moet zijn, of weg moet, of verplaatst */
+
+ for (sa= G.curscreen->areabase.first; sa; sa= sa->next) {
+ rcti oldhr= sa->headrct;
+ rcti oldwr= sa->winrct;
+
+ calc_arearcts(sa);
+
+ /* test header */
+ if (sa->headwin) {
+ if (!rcti_eq(&oldhr, &sa->headrct)) {
+ mywinposition(sa->headwin, sa->headrct.xmin, sa->headrct.xmax, sa->headrct.ymin, sa->headrct.ymax);
+ addqueue(sa->headwin, CHANGED, 1);
+ }
+
+ if(sa->headbutlen<sa->winx) {
+ sa->headbutofs= 0;
+ addqueue(sa->headwin, CHANGED, 1);
+ }
+ else if(sa->headbutofs+sa->winx > sa->headbutlen) {
+ sa->headbutofs= sa->headbutlen-sa->winx;
+ addqueue(sa->headwin, CHANGED, 1);
+ }
+ }
+
+ if (!rcti_eq(&oldwr, &sa->winrct)) {
+ mywinposition(sa->win, sa->winrct.xmin, sa->winrct.xmax, sa->winrct.ymin, sa->winrct.ymax);
+ addqueue(sa->win, CHANGED, 1);
+ }
+ }
+
+ /* remake global windowarray */
+ memset(areawinar, 0, sizeof(void *)*MAXWIN);
+ for (sa= G.curscreen->areabase.first; sa; sa= sa->next) {
+ areawinar[sa->headwin]= sa;
+ areawinar[sa->win]= sa;
+ }
+
+ /* test of winakt in orde is */
+ if( areawinar[G.curscreen->winakt]==0) G.curscreen->winakt= 0;
+}
+
+static ScrArea *test_edge_area(ScrArea *sa, ScrEdge *se)
+{
+ /* test of edge in area ligt, zo niet,
+ vind een area die 'm wel heeft */
+
+ ScrEdge *se1=0, *se2=0, *se3=0, *se4=0;
+
+ if(sa) {
+ se1= screen_findedge(G.curscreen, sa->v1, sa->v2);
+ se2= screen_findedge(G.curscreen, sa->v2, sa->v3);
+ se3= screen_findedge(G.curscreen, sa->v3, sa->v4);
+ se4= screen_findedge(G.curscreen, sa->v4, sa->v1);
+ }
+ if(se1!=se && se2!=se && se3!=se && se4!=se) {
+
+ sa= G.curscreen->areabase.first;
+ while(sa) {
+ /* een beetje optimaliseren? */
+ if(se->v1==sa->v1 || se->v1==sa->v2 || se->v1==sa->v3 || se->v1==sa->v4) {
+ se1= screen_findedge(G.curscreen, sa->v1, sa->v2);
+ se2= screen_findedge(G.curscreen, sa->v2, sa->v3);
+ se3= screen_findedge(G.curscreen, sa->v3, sa->v4);
+ se4= screen_findedge(G.curscreen, sa->v4, sa->v1);
+ if(se1==se || se2==se || se3==se || se4==se) return sa;
+ }
+ sa= sa->next;
+ }
+ }
+
+ return sa; /* is keurig 0 als niet gevonden */
+}
+
+ScrArea *closest_bigger_area(void)
+{
+ ScrArea *sa, *big=0;
+ float cent[3], vec[3],len, len1, len2, len3, dist=1000;
+ short mval[2];
+
+ getmouseco_sc(mval);
+
+ cent[0]= mval[0];
+ cent[1]= mval[1];
+ cent[2]= vec[2]= 0;
+
+ sa= G.curscreen->areabase.first;
+ while(sa) {
+ if(sa!=curarea) {
+ if(sa->winy>=curarea->winy) {
+
+ /* mimimum van vier hoekpunten */
+ vec[0]= sa->v1->vec.x; vec[1]= sa->v1->vec.y;
+ len= VecLenf(vec, cent);
+ vec[0]= sa->v2->vec.x; vec[1]= sa->v2->vec.y;
+ len1= VecLenf(vec, cent);
+ vec[0]= sa->v3->vec.x; vec[1]= sa->v3->vec.y;
+ len2= VecLenf(vec, cent);
+ vec[0]= sa->v4->vec.x; vec[1]= sa->v4->vec.y;
+ len3= VecLenf(vec, cent);
+
+ len= MIN4(len, len1, len2, len3);
+
+ /* plus centrum */
+ vec[0]= (sa->v2->vec.x+sa->v3->vec.x)/2;
+ vec[1]= (sa->v1->vec.y+sa->v2->vec.y)/2;
+
+ len+= 0.5*VecLenf(vec, cent);
+
+ /* min afmeting */
+ len-= sa->winy+sa->winx;
+
+ if(len<dist) {
+ dist= len;
+ big= sa;
+ }
+ }
+ }
+ sa= sa->next;
+ }
+
+ if(big) return big;
+ else return curarea;
+}
+
+/* ************ SCREENBEHEER ************** */
+
+static int statechanged= 0;
+void BIF_wait_for_statechange(void)
+{
+ if (!statechanged) {
+ /* Safety, don't wait more than 0.1 seconds */
+ double stime= PIL_check_seconds_timer();
+ while (!statechanged) {
+ winlay_process_events(1);
+ if ((PIL_check_seconds_timer()-stime)>0.1) break;
+ }
+ statechanged= 0;
+ }
+}
+void getmouse(short *mval)
+{
+ winlay_process_events(0);
+ window_get_mouse(mainwin, mval);
+}
+short get_qual(void)
+{
+ winlay_process_events(0);
+ return window_get_qual(mainwin);
+}
+short get_mbut(void)
+{
+ winlay_process_events(0);
+ return window_get_mbut(mainwin);
+}
+
+static unsigned short convert_for_nonumpad(unsigned short event)
+{
+ if (event>=ZEROKEY && event<=NINEKEY) {
+ return event - ZEROKEY + PAD0;
+ } else if (event==MINUSKEY) {
+ return PADMINUS;
+ } else if (event==EQUALKEY) {
+ return PADPLUSKEY;
+ } else if (event==BACKSLASHKEY) {
+ return PADSLASHKEY;
+ } else {
+ return event;
+ }
+}
+
+void add_to_mainqueue(Window *win, void *user_data, short evt, short val, char ascii)
+{
+ short qual= window_get_qual(win);
+
+ statechanged= 1;
+
+ if (U.flag&NONUMPAD) {
+ evt= convert_for_nonumpad(evt);
+ }
+
+ /* enforce some guarentees about ascii values... these should
+ * be enforced in ghost probably - zr
+ */
+
+ if (!val || !isprint(ascii) || (qual&~LR_SHIFTKEY)) {
+ ascii= '\0';
+ }
+
+ mainqenter_ext(evt, val, ascii);
+}
+
+static bScreen *addscreen(char *name) /* gebruik de setprefsize() als je anders dan fullscreen wilt */
+{
+ /* deze functie zet de variabele G.curscreen
+ * omdat alle hulpfuncties moeten weten welk screen
+ */
+ bScreen *sc;
+ ScrVert *sv1, *sv2, *sv3, *sv4;
+ short startx, starty, endx, endy;
+
+ sc= G.curscreen= alloc_libblock(&G.main->screen, ID_SCR, name);
+
+ if (!prefsizx) {
+ prefstax= 0;
+ prefstay= 0;
+
+ winlay_get_screensize(&prefsizx, &prefsizy);
+ }
+
+ startx= prefstax;
+ starty= prefstay;
+ endx= prefstax+prefsizx-1;
+ endy= prefstay+prefsizy-1;
+
+ sc->startx= startx; sc->starty= starty;
+ sc->endx= endx; sc->endy= endy;
+ sc->sizex= sc->endx-sc->startx+1;
+ sc->sizey= sc->endy-sc->starty+1;
+
+ sc->scene= G.scene;
+
+ if (!mainwin) {
+ mainwin= window_open("Blender", sc->startx, sc->starty, sc->sizex, sc->sizey, start_maximized);
+ if (!mainwin) {
+ printf("ERROR: Unable to open Blender window\n");
+ exit(1);
+ }
+
+ window_set_handler(mainwin, add_to_mainqueue, NULL);
+ init_mainwin();
+ mywinset(1);
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ myortho2(-0.5, sc->sizex-0.5, -0.5, sc->sizey-0.5);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ glDrawBuffer(GL_FRONT);
+ glClearColor(.45, .45, .45, 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+ glDrawBuffer(GL_BACK);
+
+ warp_pointer(sc->sizex/2, sc->sizey/2);
+
+ mainqenter(REDRAW, 1);
+ }
+
+ sc->mainwin= 1;
+
+ sv1= screen_addvert(sc, 0, 0);
+ sv2= screen_addvert(sc, 0, sc->endy-sc->starty);
+ sv3= screen_addvert(sc, sc->sizex-1, sc->sizey-1);
+ sv4= screen_addvert(sc, sc->sizex-1, 0);
+
+ screen_addedge(sc, sv1, sv2);
+ screen_addedge(sc, sv2, sv3);
+ screen_addedge(sc, sv3, sv4);
+ screen_addedge(sc, sv4, sv1);
+
+ screen_addarea(sc, sv1, sv2, sv3, sv4, HEADERDOWN, SPACE_INFO);
+
+ G.curscreen= sc;
+
+ return sc;
+}
+
+void setscreen(bScreen *sc)
+{
+ bScreen *sc1;
+ ScrArea *sa;
+ short mval[2];
+
+ if(sc->full) { /* vind de bijhorende full */
+ sc1= G.main->screen.first;
+ while(sc1) {
+ sa= sc1->areabase.first;
+ if(sa->full==sc) {
+ sc= sc1;
+ break;
+ }
+ sc1= sc1->id.next;
+ }
+ if(sc1==0) printf("setscreen error\n");
+ }
+
+ /* G.curscreen de-activeren */
+ if (G.curscreen && G.curscreen != sc) {
+ sa= G.curscreen->areabase.first;
+ while(sa) {
+ if(sa->win) mywinclose(sa->win);
+ sa->win= 0;
+ if(sa->headwin) mywinclose(sa->headwin);
+ sa->headwin= 0;
+
+ uiFreeBlocks(&sa->uiblocks);
+
+ sa= sa->next;
+ }
+ }
+
+ if (G.curscreen != sc) {
+ mywinset(sc->mainwin);
+ }
+
+ G.curscreen= sc;
+
+ for (sa= sc->areabase.first; sa; sa= sa->next) {
+ /* XXX, fixme zr */
+/* if (sa->win || sa->headwin) */
+/* printf("error in setscreen (win): %d, %d\n", sa->win, sa->headwin); */
+ if (!sa->win)
+ openareawin(sa);
+ if (!sa->headwin && sa->headertype)
+ openheadwin(sa);
+ }
+
+ /* recalculate winakt */
+ getmouseco_sc(mval);
+
+ test_scale_screen(sc);
+ testareas();
+
+ for (sa= sc->areabase.first; sa; sa= sa->next) {
+ SpaceLink *sl;
+
+ for (sl= sa->spacedata.first; sl; sl= sl->next) {
+ sl->area= sa;
+
+ if (sl->spacetype==SPACE_OOPS) {
+ SpaceOops *soops= (SpaceOops*) sl;
+
+ /* patch als deze in oude files zit */
+ if (soops->v2d.cur.xmin==soops->v2d.cur.xmax) {
+ extern void init_v2d_oops(View2D*);
+ init_v2d_oops(&soops->v2d);
+ }
+ }
+ }
+
+ sa->cursor= CURSOR_STD;
+ }
+
+ G.scene= sc->scene;
+ countall();
+
+ G.curscreen->winakt= 0;
+ curarea= sc->areabase.first;
+
+ mainqenter(DRAWEDGES, 1);
+ dodrawscreen= 1; /* patch! even gets lost,,,? */
+
+ winqueue_break= 1; /* overal uit de queue's gaan */
+}
+
+static void splitarea(ScrArea *sa, char dir, float fac);
+
+void area_fullscreen(void) /* met curarea */
+{
+ /* deze funktie toggelt: als area full is wordt de parent weer zichtbaar */
+ bScreen *sc, *oldscreen;
+ ScrArea *newa, *old;
+ short headertype, fulltype;
+
+ if(curarea->full) {
+ sc= curarea->full; /* de oude screen */
+ fulltype = sc->full;
+
+ // refuse to go out of SCREENAUTOPLAY as long as G_FLAGS_AUTOPLAY
+ // is set
+
+ if (fulltype != SCREENAUTOPLAY || (G.flags & G_FLAGS_AUTOPLAY) == 0) {
+ sc->full= 0;
+
+ /* vind oude area */
+ old= sc->areabase.first;
+ while(old) {
+ if(old->full) break;
+ old= old->next;
+ }
+ if(old==0) {error("something wrong in areafullscreen"); return;}
+
+ if (fulltype == SCREENAUTOPLAY) {
+ // in autoplay screens the headers are disabled by
+ // default. So use the old headertype instead
+ headertype = old->headertype;
+ } else {
+ // normal fullscreen. Use current headertype
+ headertype = curarea->headertype;
+ }
+
+ copy_areadata(old, curarea);
+ old->headertype = headertype;
+
+ old->full= 0;
+
+ unlink_screen(G.curscreen);
+ free_libblock(&G.main->screen, G.curscreen);
+ G.curscreen= NULL;
+
+ setscreen(sc);
+ }
+
+ }
+ else {
+ /* is er maar 1 area? */
+ if(G.curscreen->areabase.first==G.curscreen->areabase.last) return;
+ if(curarea->spacetype==SPACE_INFO) return;
+
+ G.curscreen->full = SCREENFULL;
+
+ old= curarea;
+ oldscreen= G.curscreen;
+ sc= addscreen("temp"); /* deze zet G.curscreen */
+
+ splitarea( (ScrArea *)sc->areabase.first, 'h', 0.99);
+ newa= sc->areabase.first;
+ newspace(newa->next, SPACE_INFO);
+
+ curarea= old;
+ G.curscreen= oldscreen; /* moet voor setscreen */
+
+ /* area kopieeren */
+ copy_areadata(newa, curarea);
+
+ curarea->full= oldscreen;
+ newa->full= oldscreen;
+ newa->next->full= oldscreen;
+
+ setscreen(sc);
+ wich_cursor(newa);
+ }
+}
+
+static void area_autoplayscreen(void)
+{
+ bScreen *sc, *oldscreen;
+ ScrArea *newa, *old, *sa;
+
+ if (curarea->full) {
+ area_fullscreen();
+ }
+
+ if (curarea->full == NULL) {
+ sa = G.curscreen->areabase.first;
+ while (sa) {
+ if (sa->spacetype == SPACE_VIEW3D) {
+ break;
+ }
+ sa= sa->next;
+ }
+
+ if (sa) {
+ areawinset(sa->win);
+ G.curscreen->full = SCREENAUTOPLAY;
+
+ old= curarea;
+ oldscreen= G.curscreen;
+ sc= addscreen("temp"); /* deze zet G.curscreen */
+
+ newa= sc->areabase.first;
+
+ curarea= old;
+ G.curscreen= oldscreen; /* moet voor setscreen */
+
+ /* copy area settings */
+ copy_areadata(newa, curarea);
+ newa->headertype= 0;
+
+ curarea->full= oldscreen;
+ newa->full= oldscreen;
+
+ setscreen(sc);
+ wich_cursor(newa);
+ }
+ }
+}
+
+static void copy_screen(bScreen *to, bScreen *from)
+{
+ ScrVert *s1, *s2;
+ ScrEdge *se;
+ ScrArea *sa;
+ ListBase lbase;
+
+ /* alles van to vrijgeven */
+ free_screen(to);
+ winqueue_break= 1; /* overal uit queue's gaan */
+
+ duplicatelist(&to->vertbase, &from->vertbase);
+ duplicatelist(&to->edgebase, &from->edgebase);
+ duplicatelist(&to->areabase, &from->areabase);
+
+ s1= from->vertbase.first;
+ s2= to->vertbase.first;
+ while(s1) {
+ s1->newv= s2;
+ s2= s2->next;
+ s1= s1->next;
+ }
+ se= to->edgebase.first;
+ while(se) {
+ se->v1= se->v1->newv;
+ se->v2= se->v2->newv;
+ sortscrvert(&(se->v1), &(se->v2));
+ se= se->next;
+ }
+
+ sa= to->areabase.first;
+ while(sa) {
+ sa->v1= sa->v1->newv;
+ sa->v2= sa->v2->newv;
+ sa->v3= sa->v3->newv;
+ sa->v4= sa->v4->newv;
+ sa->win= 0;
+ sa->headwin= 0;
+
+ sa->uiblocks.first= sa->uiblocks.last= NULL;
+
+ duplicatespacelist(sa, &lbase, &sa->spacedata);
+ sa->spacedata= lbase;
+
+ sa= sa->next;
+ }
+
+ /* op nul zetten (nodig?) */
+ s1= from->vertbase.first;
+ while(s1) {
+ s1->newv= 0;
+ s1= s1->next;
+ }
+}
+
+void duplicate_screen(void)
+{
+ bScreen *sc, *oldscreen;
+
+ if(G.curscreen->full != SCREENNORMAL) return;
+
+ /* nieuw screen maken: */
+
+ oldscreen= G.curscreen;
+ sc= addscreen(oldscreen->id.name+2); /* deze zet G.curscreen */
+ copy_screen(sc, oldscreen);
+
+ G.curscreen= oldscreen;
+ setscreen(sc);
+
+}
+
+
+/* ************ END SCREENBEHEER ************** */
+/* ************ JOIN/SPLIT/MOVE ************** */
+
+static void joinarea(ScrArea *sa, ScrEdge *onedge)
+{
+ ScrArea *sa2;
+ ScrArea *up=0, *down=0, *right=0, *left=0;
+ ScrEdge *setest;
+ short val=0;
+
+ sa= test_edge_area(sa, onedge);
+ if (sa==0) return;
+
+ /* welke edges kunnen ermee? */
+ /* vind richtingen met zelfde edge */
+ sa2= G.curscreen->areabase.first;
+ while(sa2) {
+ if(sa2 != sa) {
+ setest= screen_findedge(G.curscreen, sa2->v1, sa2->v2);
+ if(onedge==setest) right= sa2;
+ setest= screen_findedge(G.curscreen, sa2->v2, sa2->v3);
+ if(onedge==setest) down= sa2;
+ setest= screen_findedge(G.curscreen, sa2->v3, sa2->v4);
+ if(onedge==setest) left= sa2;
+ setest= screen_findedge(G.curscreen, sa2->v4, sa2->v1);
+ if(onedge==setest) up= sa2;
+ }
+ sa2= sa2->next;
+ }
+
+ sa2= 0;
+ setest= 0;
+
+ if(left) val++;
+ if(up) val++;
+ if(right) val++;
+ if(down) val++;
+
+ if(val==0) return;
+ else if(val==1) {
+ if(left) sa2= left;
+ else if(up) sa2= up;
+ else if(right) sa2= right;
+ else if(down) sa2= down;
+ }
+
+
+ if(sa2) {
+ /* nieuwe area is oude sa */
+ if(sa2==left) {
+ sa->v1= sa2->v1;
+ sa->v2= sa2->v2;
+ screen_addedge(G.curscreen, sa->v2, sa->v3);
+ screen_addedge(G.curscreen, sa->v1, sa->v4);
+ }
+ else if(sa2==up) {
+ sa->v2= sa2->v2;
+ sa->v3= sa2->v3;
+ screen_addedge(G.curscreen, sa->v1, sa->v2);
+ screen_addedge(G.curscreen, sa->v3, sa->v4);
+ }
+ else if(sa2==right) {
+ sa->v3= sa2->v3;
+ sa->v4= sa2->v4;
+ screen_addedge(G.curscreen, sa->v2, sa->v3);
+ screen_addedge(G.curscreen, sa->v1, sa->v4);
+ }
+ else if(sa2==down) {
+ sa->v1= sa2->v1;
+ sa->v4= sa2->v4;
+ screen_addedge(G.curscreen, sa->v1, sa->v2);
+ screen_addedge(G.curscreen, sa->v3, sa->v4);
+ }
+
+ /* edge en area weg */
+ /* remlink(&G.curscreen->edgebase, setest); */
+ /* freeN(setest); */
+ del_area(sa2);
+ BLI_remlink(&G.curscreen->areabase, sa2);
+ MEM_freeN(sa2);
+
+ removedouble_scredges();
+ removenotused_scredges();
+ removenotused_scrverts(); /* moet als laatste */
+
+ testareas();
+ mainqenter(DRAWEDGES, 1);
+ /* test cursor en inputwindow */
+ mainqenter(MOUSEY, -1);
+ }
+}
+
+static short testsplitpoint(ScrArea *sa, char dir, float fac)
+/* return 0: geen split mogelijk */
+/* else return (integer) screencoordinaat splitpunt */
+{
+ short x, y;
+
+ /* area groot genoeg? */
+ if(sa->v4->vec.x- sa->v1->vec.x <= 2*AREAMINX) return 0;
+ if(sa->v2->vec.y- sa->v1->vec.y <= 2*AREAMINY) return 0;
+
+ /* voor zekerheid */
+ if(fac<0.0) fac= 0.0;
+ if(fac>1.0) fac= 1.0;
+
+ if(dir=='h') {
+ y= sa->v1->vec.y+ fac*(sa->v2->vec.y- sa->v1->vec.y);
+
+ if(sa->v2->vec.y==G.curscreen->sizey-1 && sa->v2->vec.y- y < HEADERY+EDGEWIDTH2)
+ y= sa->v2->vec.y- HEADERY-EDGEWIDTH2;
+
+ else if(sa->v1->vec.y==0 && y- sa->v1->vec.y < HEADERY+EDGEWIDTH2)
+ y= sa->v1->vec.y+ HEADERY+EDGEWIDTH2;
+
+ else if(y- sa->v1->vec.y < AREAMINY) y= sa->v1->vec.y+ AREAMINY;
+ else if(sa->v2->vec.y- y < AREAMINY) y= sa->v2->vec.y- AREAMINY;
+ else y-= (y % AREAGRID);
+
+ return y;
+ }
+ else {
+ x= sa->v1->vec.x+ fac*(sa->v4->vec.x- sa->v1->vec.x);
+ if(x- sa->v1->vec.x < AREAMINX) x= sa->v1->vec.x+ AREAMINX;
+ else if(sa->v4->vec.x- x < AREAMINX) x= sa->v4->vec.x- AREAMINX;
+ else x-= (x % AREAGRID);
+
+ return x;
+ }
+}
+
+static void splitarea(ScrArea *sa, char dir, float fac)
+{
+ bScreen *sc;
+ ScrArea *newa;
+ ScrVert *sv1, *sv2;
+ short split;
+
+ if(sa==0) return;
+
+ split= testsplitpoint(sa, dir, fac);
+ if(split==0) return;
+
+ sc= G.curscreen;
+
+ areawinset(sa->win);
+
+ if(dir=='h') {
+ /* nieuwe vertices */
+ sv1= screen_addvert(sc, sa->v1->vec.x, split);
+ sv2= screen_addvert(sc, sa->v4->vec.x, split);
+
+ /* nieuwe edges */
+ screen_addedge(sc, sa->v1, sv1);
+ screen_addedge(sc, sv1, sa->v2);
+ screen_addedge(sc, sa->v3, sv2);
+ screen_addedge(sc, sv2, sa->v4);
+ screen_addedge(sc, sv1, sv2);
+
+ /* nieuwe areas: boven */
+ newa= screen_addarea(sc, sv1, sa->v2, sa->v3, sv2, sa->headertype, sa->spacetype);
+ copy_areadata(newa, sa);
+
+ /* area onder */
+ sa->v2= sv1;
+ sa->v3= sv2;
+
+ }
+ else {
+ /* nieuwe vertices */
+ sv1= screen_addvert(sc, split, sa->v1->vec.y);
+ sv2= screen_addvert(sc, split, sa->v2->vec.y);
+
+ /* nieuwe edges */
+ screen_addedge(sc, sa->v1, sv1);
+ screen_addedge(sc, sv1, sa->v4);
+ screen_addedge(sc, sa->v2, sv2);
+ screen_addedge(sc, sv2, sa->v3);
+ screen_addedge(sc, sv1, sv2);
+
+ /* nieuwe areas: links */
+ newa= screen_addarea(sc, sa->v1, sa->v2, sv2, sv1, sa->headertype, sa->spacetype);
+ copy_areadata(newa, sa);
+
+ /* area rechts */
+ sa->v1= sv1;
+ sa->v2= sv2;
+ }
+
+ /* dubbele vertices en edges verwijderen */
+ removedouble_scrverts();
+ removedouble_scredges();
+ removenotused_scredges();
+
+ mainqenter(DRAWEDGES, 1);
+ dodrawscreen= 1; /* patch! even gets lost,,,? */
+ testareas();
+}
+
+static void scrarea_draw_splitpoint(ScrArea *sa, char dir, float fac)
+{
+ int split= testsplitpoint(sa, dir, fac);
+
+ if (split) {
+ if(dir=='h') {
+ glutil_draw_front_xor_line(sa->totrct.xmin, split, sa->totrct.xmax, split);
+ glutil_draw_front_xor_line(sa->totrct.xmin, split-1, sa->totrct.xmax, split-1);
+ } else {
+ glutil_draw_front_xor_line(split, sa->totrct.ymin, split, sa->totrct.ymax);
+ glutil_draw_front_xor_line(split-1, sa->totrct.ymin, split-1, sa->totrct.ymax);
+ }
+ }
+}
+
+static void splitarea_interactive(ScrArea *area, ScrEdge *onedge)
+{
+ ScrArea *sa= area;
+ float fac;
+ unsigned short event;
+ short ok= 0, val, split = 0, mval[2], mvalo[2], first= 1;
+ char dir;
+
+ if(sa->win==0) return;
+ if(sa->full) return;
+
+ dir= scredge_is_horizontal(onedge)?'v':'h';
+
+ mywinset(G.curscreen->mainwin);
+ /* hoort al goede matrix te hebben */
+
+ /* rekening houden met grid en minsize */
+ while(ok==0) {
+ getmouseco_sc(mval);
+
+ if (first || mval[0]!=mvalo[0] || mval[1]!=mvalo[1]) {
+ if (!first) {
+ scrarea_draw_splitpoint(sa, dir, fac);
+ }
+
+ if(dir=='h') {
+ fac= mval[1]- (sa->v1->vec.y);
+ fac/= sa->v2->vec.y- sa->v1->vec.y;
+ } else {
+ fac= mval[0]- sa->v1->vec.x;
+ fac/= sa->v4->vec.x- sa->v1->vec.x;
+ }
+
+ split= testsplitpoint(sa, dir, fac);
+ if (split) {
+ scrarea_draw_splitpoint(sa, dir, fac);
+ } else {
+ ok= -1;
+ }
+
+ mvalo[0]= mval[0];
+ mvalo[1]= mval[1];
+ first= 0;
+ }
+
+ event= extern_qread(&val);
+ if(val && event==LEFTMOUSE) {
+ if(dir=='h') {
+ fac= split- (sa->v1->vec.y);
+ fac/= sa->v2->vec.y- sa->v1->vec.y;
+ }
+ else {
+ fac= split- sa->v1->vec.x;
+ fac/= sa->v4->vec.x- sa->v1->vec.x;
+ }
+ ok= 1;
+ }
+ if(val && event==ESCKEY) {
+ ok= -1;
+ }
+ }
+
+ if (!first) {
+ scrarea_draw_splitpoint(sa, dir, fac);
+ }
+
+ if(ok==1) {
+ splitarea(sa, dir, fac);
+ mainqenter(DRAWEDGES, 1);
+ dodrawscreen= 1; /* patch! even gets lost,,,? */
+ }
+}
+
+View3D *find_biggest_view3d(void)
+{
+ ScrArea *sa= find_biggest_area_of_type(SPACE_VIEW3D);
+
+ if (sa) {
+ return (View3D*) sa->spacedata.first;
+ } else {
+ return NULL;
+ }
+}
+
+ScrArea *find_biggest_area_of_type(int spacecode)
+{
+ ScrArea *sa, *biggest= NULL;
+ int bigsize;
+
+ for (sa= G.curscreen->areabase.first; sa; sa= sa->next) {
+ if (spacecode==0 || sa->spacetype==spacecode) {
+ int x= sa->v3->vec.x - sa->v1->vec.x;
+ int y= sa->v3->vec.y - sa->v1->vec.y;
+ int size= x*x + y*y;
+
+ if (!biggest || size>bigsize) {
+ biggest= sa;
+ bigsize= size;
+ }
+ }
+ }
+
+ return biggest;
+}
+
+ScrArea *find_biggest_area(void)
+{
+ return find_biggest_area_of_type(0);
+}
+
+static void select_connected_scredge(bScreen *sc, ScrEdge *edge)
+{
+ ScrEdge *se;
+ ScrVert *sv;
+ int oneselected;
+ char dir;
+
+ /* select connected, alleen in de juiste richting */
+ /* 'dir' is de richting van de EDGE */
+
+ if(edge->v1->vec.x==edge->v2->vec.x) dir= 'v';
+ else dir= 'h';
+
+ sv= sc->vertbase.first;
+ while(sv) {
+ sv->flag= 0;
+ sv= sv->next;
+ }
+
+ edge->v1->flag= 1;
+ edge->v2->flag= 1;
+
+ oneselected= 1;
+ while(oneselected) {
+ se= sc->edgebase.first;
+ oneselected= 0;
+ while(se) {
+ if(se->v1->flag + se->v2->flag==1) {
+ if(dir=='h') if(se->v1->vec.y==se->v2->vec.y) {
+ se->v1->flag= se->v2->flag= 1;
+ oneselected= 1;
+ }
+ if(dir=='v') if(se->v1->vec.x==se->v2->vec.x) {
+ se->v1->flag= se->v2->flag= 1;
+ oneselected= 1;
+ }
+ }
+ se= se->next;
+ }
+ }
+}
+
+void test_scale_screen(bScreen *sc)
+/* testen of screenvertices vergroot/verkleind moeten worden */
+/* testen of offset nog klopt */
+{
+ ScrVert *sv=0;
+ ScrEdge *se;
+ ScrArea *sa, *san;
+ int yval;
+ float facx, facy, tempf, min[2], max[2];
+
+ sc->startx= prefstax;
+ sc->starty= prefstay;
+ sc->endx= prefstax+prefsizx-1;
+ sc->endy= prefstay+prefsizy-1;
+
+ /* calculate size */
+ sv= sc->vertbase.first;
+ min[0]= min[1]= 0.0;
+ max[0]= sc->sizex;
+ max[1]= sc->sizey;
+ while(sv) {
+ min[0]= MIN2(min[0], sv->vec.x);
+ min[1]= MIN2(min[1], sv->vec.y);
+ max[0]= MAX2(max[0], sv->vec.x);
+ max[1]= MAX2(max[1], sv->vec.y);
+ sv= sv->next;
+ }
+
+ /* always make 0.0 left under */
+ sv= sc->vertbase.first;
+ while(sv) {
+ sv->vec.x -= min[0];
+ sv->vec.y -= min[1];
+ sv= sv->next;
+ }
+
+
+ sc->sizex= max[0]-min[0];
+ sc->sizey= max[1]-min[1];
+
+ if(sc->sizex!= prefsizx || sc->sizey!= prefsizy) {
+ facx= prefsizx;
+ facx/= (float)sc->sizex;
+ facy= prefsizy;
+ facy/= (float)sc->sizey;
+
+ /* make sure it fits! */
+ sv= sc->vertbase.first;
+ while(sv) {
+ tempf= ((float)sv->vec.x)*facx;
+ sv->vec.x= (short)(tempf+0.5);
+ sv->vec.x+= AREAGRID-1;
+ sv->vec.x-= (sv->vec.x % AREAGRID);
+
+ CLAMP(sv->vec.x, 0, prefsizx);
+
+ tempf= ((float)sv->vec.y )*facy;
+ sv->vec.y= (short)(tempf+0.5);
+ sv->vec.y+= AREAGRID-1;
+ sv->vec.y-= (sv->vec.y % AREAGRID);
+
+ CLAMP(sv->vec.y, 0, prefsizy);
+
+ sv= sv->next;
+ }
+
+ sc->sizex= prefsizx;
+ sc->sizey= prefsizy;
+ }
+
+ /* test for collapsed areas. This could happen in some blender version... */
+ sa= sc->areabase.first;
+ while(sa) {
+ san= sa->next;
+ if(sa->v1==sa->v2 || sa->v3==sa->v4 || sa->v2==sa->v3) {
+ del_area(sa);
+ BLI_remlink(&sc->areabase, sa);
+ MEM_freeN(sa);
+ }
+ sa= san;
+ }
+
+ /* make each window at least HEADERY high */
+
+ sa= sc->areabase.first;
+ while(sa) {
+
+ if(sa->v1->vec.y+HEADERY > sa->v2->vec.y) {
+ /* lower edge */
+ se= screen_findedge(sc, sa->v4, sa->v1);
+ if(se && sa->v1!=sa->v2 ) {
+ select_connected_scredge(sc, se);
+
+ /* all selected vertices get the right offset */
+ yval= sa->v2->vec.y-HEADERY;
+ sv= sc->vertbase.first;
+ while(sv) {
+ /* if is a collapsed area */
+ if(sv!=sa->v2 && sv!=sa->v3) {
+ if(sv->flag) sv->vec.y= yval;
+ }
+ sv= sv->next;
+ }
+ }
+ }
+
+ sa= sa->next;
+ }
+
+}
+
+static void draw_front_xor_dirdist_line(char dir, int dist, int start, int end)
+{
+ if (dir=='h') {
+ glutil_draw_front_xor_line(start, dist, end, dist);
+ glutil_draw_front_xor_line(start, dist+1, end, dist+1);
+ } else {
+ glutil_draw_front_xor_line(dist, start, dist, end);
+ glutil_draw_front_xor_line(dist+1, start, dist+1, end);
+ }
+}
+
+static void moveareas(ScrEdge *edge)
+{
+ ScrVert *v1;
+ ScrArea *sa;
+ short mvalo[2];
+ short edge_start, edge_end, edge_position;
+ short bigger, smaller, headery, areaminy;
+ int delta, doit;
+ char dir;
+
+ if(edge->border) return;
+
+ dir= scredge_is_horizontal(edge)?'h':'v';
+
+ select_connected_scredge(G.curscreen, edge);
+
+ edge_position= (dir=='h')?edge->v1->vec.y:edge->v1->vec.x;
+ edge_start= 10000;
+ edge_end= -10000;
+ for (v1= G.curscreen->vertbase.first; v1; v1= v1->next) {
+ if (v1->flag) {
+ if (dir=='h') {
+ edge_start= MIN2(edge_start, v1->vec.x);
+ edge_end= MAX2(edge_end, v1->vec.x);
+ } else {
+ edge_start= MIN2(edge_start, v1->vec.y);
+ edge_end= MAX2(edge_end, v1->vec.y);
+ }
+ }
+ }
+
+ /* nu zijn alle vertices met 'flag==1' degene die verplaatst kunnen worden. */
+ /* we lopen de areas af en testen vrije ruimte met MINSIZE */
+ bigger= smaller= 10000;
+ sa= G.curscreen->areabase.first;
+ while(sa) {
+ if(dir=='h') { /* als top of down edge select, test hoogte */
+ if(sa->headertype) {
+ headery= HEADERY;
+ areaminy= AREAMINY;
+ }
+ else {
+ headery= 0;
+ areaminy= EDGEWIDTH;
+ }
+
+ if(sa->v1->flag && sa->v4->flag) {
+ int y1;
+ if(sa->v2->vec.y==G.curscreen->sizey-1) /* bovenste edge */
+ y1= sa->v2->vec.y - sa->v1->vec.y-headery-EDGEWIDTH;
+ else
+ y1= sa->v2->vec.y - sa->v1->vec.y-areaminy;
+ bigger= MIN2(bigger, y1);
+ }
+ else if(sa->v2->flag && sa->v3->flag) {
+ int y1;
+ if(sa->v1->vec.y==0) /* onderste edge */
+ y1= sa->v2->vec.y - sa->v1->vec.y-headery-EDGEWIDTH;
+ else
+ y1= sa->v2->vec.y - sa->v1->vec.y-areaminy;
+ smaller= MIN2(smaller, y1);
+ }
+ }
+ else { /* als left of right edge select, test breedte */
+ if(sa->v1->flag && sa->v2->flag) {
+ int x1= sa->v4->vec.x - sa->v1->vec.x-AREAMINX;
+ bigger= MIN2(bigger, x1);
+ }
+ else if(sa->v3->flag && sa->v4->flag) {
+ int x1= sa->v4->vec.x - sa->v1->vec.x-AREAMINX;
+ smaller= MIN2(smaller, x1);
+ }
+ }
+ sa= sa->next;
+ }
+
+ mywinset(G.curscreen->mainwin);
+
+ doit= delta= 0;
+ getmouseco_sc(mvalo);
+ draw_front_xor_dirdist_line(dir, edge_position+delta, edge_start, edge_end);
+ while (!doit) {
+ short val;
+ unsigned short event= extern_qread(&val);
+
+ if (event==MOUSEY) {
+ short mval[2];
+
+ getmouseco_sc(mval);
+
+ draw_front_xor_dirdist_line(dir, edge_position+delta, edge_start, edge_end);
+
+ delta= (dir=='h')?(mval[1]-mvalo[1]):(mval[0]-mvalo[0]);
+ delta= CLAMPIS(delta, -smaller, bigger);
+
+ draw_front_xor_dirdist_line(dir, edge_position+delta, edge_start, edge_end);
+ } else if (event==LEFTMOUSE) {
+ doit= 1;
+ } else if (val) {
+ if (ELEM(event, ESCKEY, RIGHTMOUSE))
+ doit= -1;
+ else if (ELEM(event, SPACEKEY, RETKEY))
+ doit= 1;
+ }
+ }
+ draw_front_xor_dirdist_line(dir, edge_position+delta, edge_start, edge_end);
+
+ if (doit==1) {
+ for (v1= G.curscreen->vertbase.first; v1; v1= v1->next) {
+ if (v1->flag) {
+ /* zo is AREAGRID netjes */
+ if((dir=='v') && v1->vec.x>0 && v1->vec.x<G.curscreen->sizex-1) {
+ v1->vec.x+= delta;
+ if(delta != bigger && delta != -smaller) v1->vec.x-= (v1->vec.x % AREAGRID);
+ }
+ if((dir=='h') && v1->vec.y>0 && v1->vec.y<G.curscreen->sizey-1) {
+ v1->vec.y+= delta;
+
+ /* with these lines commented out you can pull the top bar exact to the screen border. */
+ /* if(delta != bigger && delta != -smaller) { */
+ v1->vec.y+= AREAGRID-1;
+ v1->vec.y-= (v1->vec.y % AREAGRID);
+
+ /* } */
+ }
+ }
+ v1->flag= 0;
+ }
+
+ removedouble_scrverts();
+ removedouble_scredges();
+ testareas();
+ }
+
+ glDrawBuffer(GL_BACK);
+ mainqenter(DRAWEDGES, 1);
+ dodrawscreen= 1; /* patch! even gets lost,,,? */
+}
+
+static void scrollheader(ScrArea *area)
+{
+ short mval[2], mvalo[2];
+
+ if(area->headbutlen<area->winx) {
+ area->headbutofs= 0;
+ }
+ else if(area->headbutofs+area->winx > area->headbutlen) {
+ area->headbutofs= area->headbutlen-area->winx;
+ }
+
+ getmouseco_sc(mvalo);
+
+ while(get_mbut() & M_MOUSE) {
+ getmouseco_sc(mval);
+ if(mval[0]!=mvalo[0]) {
+ area->headbutofs-= (mval[0]-mvalo[0]);
+
+ if(area->headbutlen-area->winx < area->headbutofs) area->headbutofs= area->headbutlen-area->winx;
+ if(area->headbutofs<0) area->headbutofs= 0;
+
+ scrarea_do_headchange(area);
+ scrarea_do_headdraw(area);
+
+ screen_swapbuffers();
+
+ mvalo[0]= mval[0];
+ } else {
+ BIF_wait_for_statechange();
+ }
+ }
+}
+
+int select_area(int spacetype)
+{
+ /* vanuit editroutines aanroepen, als er meer area's
+ * zijn van type 'spacetype' kan er een area aangegeven worden
+ */
+ ScrArea *sa, *sact = NULL;
+ int tot=0;
+ unsigned short event = 0;
+ short val, mval[2];
+
+ sa= G.curscreen->areabase.first;
+ while(sa) {
+ if(sa->spacetype==spacetype) {
+ sact= sa;
+ tot++;
+ }
+ sa= sa->next;
+ }
+
+ if(tot==0) {
+ error("Can't do this! Open correct window");
+ return 0;
+ }
+
+ if(tot==1) {
+ if(curarea!=sact) areawinset(sact->win);
+ return 1;
+ }
+ else if(tot>1) {
+ set_cursor(CURSOR_HELP);
+ while(1) {
+ event= extern_qread(&val);
+
+ if (val) {
+ if(event==ESCKEY) break;
+ if(event==LEFTMOUSE) break;
+ if(event==SPACEKEY) break;
+ } else {
+ BIF_wait_for_statechange();
+ }
+ }
+ screen_set_cursor(G.curscreen);
+
+ /* recalculate winakt */
+ getmouseco_sc(mval);
+
+ if(event==LEFTMOUSE) {
+ ScrArea *sa= screen_find_area_for_pt(G.curscreen, mval);
+
+ if (sa &&sa->spacetype==spacetype) {
+ G.curscreen->winakt= sa->win;
+ areawinset(G.curscreen->winakt);
+ } else {
+ error("wrong window");
+ return 0;
+ }
+ }
+ }
+
+ if(event==LEFTMOUSE) return 1;
+ else return 0;
+}
+
+/* ************ END JOIN/SPLIT/MOVE ************** */
+/* **************** DRAW SCREENEDGES ***************** */
+
+#define EDGE_EXTEND 3
+
+void drawedge(short x1, short y1, short x2, short y2)
+{
+ static unsigned int edcol[EDGEWIDTH]= {0x0, 0x505050, 0x909090, 0xF0F0F0, 0x0};
+ int a;
+
+ if(x1==x2) { /* vertical */
+ if (y2<y1)
+ y1^= y2^= y1^= y2;
+
+ if (y1==0) y1-= EDGE_EXTEND;
+ if (y2==G.curscreen->sizey) y2+= EDGE_EXTEND;
+
+ x1+= EDGEWIDTH2;
+ x2+= EDGEWIDTH2;
+
+ glBegin(GL_LINES);
+ for(a=0; a<EDGEWIDTH; a++) {
+ int rounding= abs(a-EDGEWIDTH2);
+
+ cpack(edcol[a]);
+ glVertex2i(x1-a, y1+rounding);
+ glVertex2i(x2-a, y2-rounding);
+ }
+ glEnd();
+ }
+ else { /* horizontal */
+ if (x2<x1)
+ x1^= x2^= x1^= x2;
+
+ if (x1==0) x1-= EDGE_EXTEND;
+ if (x2==G.curscreen->sizex) x2+= EDGE_EXTEND;
+
+ y1-= EDGEWIDTH2;
+ y2-= EDGEWIDTH2;
+
+ glBegin(GL_LINES);
+ for(a=0; a<EDGEWIDTH; a++) {
+ int rounding= abs(a-EDGEWIDTH2);
+
+ cpack(edcol[a]);
+ glVertex2i(x1+rounding, y1+a);
+ glVertex2i(x2-rounding, y2+a);
+ }
+ glEnd();
+ }
+}
+
+static void drawscredge(ScrEdge *se)
+{
+ bScreen *sc;
+ vec2s *v1, *v2;
+
+ sc= G.curscreen;
+
+ v1= &(se->v1->vec);
+ v2= &(se->v2->vec);
+
+ /* borders screen niet tekenen */
+ /* vanwege resolutie verschillen (PC/SGI files) de linit een
+ * beetje afronden?
+ */
+ se->border= 1;
+ if(v1->x<=1 && v2->x<=1) return;
+ if(v1->x>=sc->sizex-2 && v2->x>=sc->sizex-2) return;
+ if(v1->y<=1 && v2->y<=1) return;
+ if(v1->y>=sc->sizey-2 && v2->y>=sc->sizey-2) return;
+ se->border= 0;
+
+ drawedge(v1->x, v1->y, v2->x, v2->y);
+}
+
+void drawscreen(void)
+{
+ ScrEdge *se;
+
+ mywinset(G.curscreen->mainwin);
+ myortho2(-0.5, (float)G.curscreen->sizex-0.5, -0.5, (float)G.curscreen->sizey-0.5);
+
+ /* two times, because there is no 'win_swap' for this available */
+ glDrawBuffer(GL_FRONT);
+ se= G.curscreen->edgebase.first;
+ while(se) {
+ drawscredge(se);
+ se= se->next;
+ }
+
+ glDrawBuffer(GL_BACK);
+ se= G.curscreen->edgebase.first;
+ while(se) {
+ drawscredge(se);
+ se= se->next;
+ }
+}
+
+/* ********************************* */
+
+bScreen *default_twosplit()
+{
+ bScreen *sc= addscreen("screen");
+ ScrArea *sa;
+
+ splitarea( (ScrArea *)sc->areabase.first, 'h', 0.99);
+ sa= sc->areabase.first;
+ newspace(sa, SPACE_VIEW3D);
+ newspace(sa->next, SPACE_INFO);
+
+ return sc;
+}
+
+void initscreen(void)
+{
+ default_twosplit();
+}
+
+/***/
+
+void screen_draw_info_text(bScreen *sc, char *text) {
+ Window *oldactwin= winlay_get_active_window();
+ ScrArea *sa;
+
+ /*
+ * Because this is called from within rendering
+ * internals it is possible our window is not
+ * active.
+ */
+ window_make_active(mainwin);
+
+ for (sa= sc->areabase.first; sa; sa= sa->next) {
+ if (sa->spacetype==SPACE_INFO) {
+ int x= sa->headbutlen - 28;
+ int y= 6;
+
+ areawinset(sa->headwin);
+ glDrawBuffer(GL_FRONT);
+
+ cpack(0xA08060);
+ glRecti(x-11, y-6, x+55, y+13);
+
+ cpack(0x909090);
+ glRecti(x+55, y-6, x+1280, y+14);
+
+ cpack(0x0);
+ glRasterPos2i(x, y);
+ BMF_DrawString(G.fonts, text);
+
+ glFinish();
+ glDrawBuffer(GL_BACK);
+
+ sa->head_swap= WIN_FRONT_OK;
+ }
+ }
+
+ if (oldactwin && oldactwin!=mainwin) window_make_active(oldactwin);
+}
+
+static int curcursor;
+
+int get_cursor(void) {
+ return curcursor;
+}
+
+void set_cursor(int curs) {
+ if (!(R.flag & R_RENDERING)) {
+ if (curs!=curcursor) {
+ curcursor= curs;
+ window_set_cursor(mainwin, curs);
+ }
+ }
+}
+
+void unlink_screen(bScreen *sc) {
+ ScrArea *sa;
+
+ for (sa= sc->areabase.first; sa; sa= sa->next)
+ del_area(sa);
+}
+
+void warp_pointer(int x, int y)
+{
+ window_warp_pointer(mainwin, x, y);
+}
+
+void set_timecursor(int nr)
+{
+ /* 10 8x8 digits */
+ static char number_bitmaps[10][8]= {
+ {0, 56, 68, 68, 68, 68, 68, 56},
+ {0, 24, 16, 16, 16, 16, 16, 56},
+ {0, 60, 66, 32, 16, 8, 4, 126},
+ {0, 124, 32, 16, 56, 64, 66, 60},
+ {0, 32, 48, 40, 36, 126, 32, 32},
+ {0, 124, 4, 60, 64, 64, 68, 56},
+ {0, 56, 4, 4, 60, 68, 68, 56},
+ {0, 124, 64, 32, 16, 8, 8, 8},
+ {0, 60, 66, 66, 60, 66, 66, 60},
+ {0, 56, 68, 68, 120, 64, 68, 56}
+ };
+ unsigned char mask[16][2];
+ unsigned char bitmap[16][2];
+ int i, idx;
+
+ memset(&bitmap, 0x00, sizeof(bitmap));
+ memset(&mask, 0xFF, sizeof(mask));
+
+ /* print number bottom right justified */
+ for (idx= 3; nr && idx>=0; idx--) {
+ char *digit= number_bitmaps[nr%10];
+ int x = idx%2;
+ int y = idx/2;
+
+ for (i=0; i<8; i++)
+ bitmap[i + y*8][x]= digit[i];
+ nr/= 10;
+ }
+
+ curcursor= CURSOR_NONE;
+ window_set_custom_cursor(mainwin, mask, bitmap);
+ BIF_renderwin_set_custom_cursor(mask, bitmap);
+}
+
diff --git a/source/blender/src/editseq.c b/source/blender/src/editseq.c
new file mode 100644
index 00000000000..608988458d0
--- /dev/null
+++ b/source/blender/src/editseq.c
@@ -0,0 +1,1855 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 <string.h>
+#ifndef WIN32
+#include <unistd.h>
+#else
+#include <io.h>
+#include "BLI_winstuff.h"
+#endif
+#include <sys/types.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+#include "BLI_storage_types.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "DNA_ipo_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_sequence_types.h"
+#include "DNA_view2d_types.h"
+#include "DNA_userdef_types.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_plugin_types.h"
+#include "BKE_global.h"
+#include "BKE_image.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+
+#include "BIF_space.h"
+#include "BIF_interface.h"
+#include "BIF_screen.h"
+#include "BIF_drawseq.h"
+#include "BIF_editseq.h"
+#include "BIF_mywindow.h"
+#include "BIF_toolbox.h"
+#include "BIF_writemovie.h"
+#include "BIF_editview.h"
+#include "BIF_scrarea.h"
+
+#include "BSE_edit.h"
+#include "BSE_sequence.h"
+#include "BSE_filesel.h"
+#include "BSE_drawipo.h"
+
+#include "BDR_editobject.h"
+
+#include "blendef.h"
+#include "mydevice.h"
+#include "interface.h" /* MAART: for button types, pupmenu */
+
+Sequence *last_seq=0;
+char last_imagename[80]= "/";
+
+/* void transform_seq(int mode); already in BIF_editseq.h */
+
+#define SEQ_DESEL ~(SELECT+SEQ_LEFTSEL+SEQ_RIGHTSEL)
+
+static int test_overlap_seq(Sequence *);
+static void shuffle_seq(Sequence *);
+
+static void change_plugin_seq(char *str) /* aangeroepen vanuit fileselect */
+{
+/* extern Sequence *last_seq; already done few lines before !!!*/
+
+ if(last_seq && last_seq->type!=SEQ_PLUGIN) return;
+
+ free_plugin_seq(last_seq->plugin);
+
+ last_seq->plugin= (PluginSeq *)add_plugin_seq(str, last_seq->name+2);
+
+ last_seq->machine= MAX3(last_seq->seq1->machine, last_seq->seq2->machine, last_seq->seq3->machine);
+ if( test_overlap_seq(last_seq) ) shuffle_seq(last_seq);
+}
+
+
+void boundbox_seq(void)
+{
+ Sequence *seq;
+ Editing *ed;
+ float min[2], max[2];
+
+ ed= G.scene->ed;
+ if(ed==0) return;
+
+ min[0]= 0.0;
+ max[0]= EFRA+1;
+ min[1]= 0.0;
+ max[1]= 8.0;
+
+ seq= ed->seqbasep->first;
+ while(seq) {
+
+ if( min[0] > seq->startdisp-1) min[0]= seq->startdisp-1;
+ if( max[0] < seq->enddisp+1) max[0]= seq->enddisp+1;
+ if( max[1] < seq->machine+2.0) max[1]= seq->machine+2.0;
+
+ seq= seq->next;
+ }
+
+ G.v2d->tot.xmin= min[0];
+ G.v2d->tot.xmax= max[0];
+ G.v2d->tot.ymin= min[1];
+ G.v2d->tot.ymax= max[1];
+
+}
+
+Sequence *find_nearest_seq(int *hand)
+{
+ Sequence *seq;
+ Editing *ed;
+ float x, y, facx, facy;
+ short mval[2];
+
+ *hand= 0;
+
+ ed= G.scene->ed;
+ if(ed==0) return 0;
+
+ getmouseco_areawin(mval);
+ areamouseco_to_ipoco(G.v2d, mval, &x, &y);
+
+ seq= ed->seqbasep->first;
+ while(seq) {
+ if(seq->machine == (int)y) {
+ if(seq->startdisp<=x && seq->enddisp>=x) {
+
+ if(seq->type < SEQ_EFFECT) {
+ if( seq->handsize+seq->startdisp >=x ) {
+ /* binnen de driehoek? */
+ facx= (x-seq->startdisp)/seq->handsize;
+ if( (y - (int)y) <0.5) {
+ facy= (y - 0.2 - (int)y)/0.3;
+ if( facx < facy ) *hand= 1;
+ }
+ else {
+ facy= (y - 0.5 - (int)y)/0.3;
+ if( facx+facy < 1.0 ) *hand= 1;
+ }
+
+ }
+ else if( -seq->handsize+seq->enddisp <=x ) {
+ /* binnen de driehoek? */
+ facx= 1.0 - (seq->enddisp-x)/seq->handsize;
+ if( (y - (int)y) <0.5) {
+ facy= (y - 0.2 - (int)y)/0.3;
+ if( facx+facy > 1.0 ) *hand= 2;
+ }
+ else {
+ facy= (y - 0.5 - (int)y)/0.3;
+ if( facx > facy ) *hand= 2;
+ }
+ }
+ }
+
+ return seq;
+ }
+ }
+ seq= seq->next;
+ }
+ return 0;
+}
+
+void clear_last_seq(void)
+{
+ /* vanuit (bijv) ipo: als ie veranderd is, ook meteen de effecten metzelfde ipo */
+ Sequence *seq;
+ Editing *ed;
+ StripElem *se;
+ int a;
+
+ if(last_seq) {
+
+ ed= G.scene->ed;
+ if(ed==0) return;
+
+ WHILE_SEQ(&ed->seqbase) {
+ if(seq==last_seq || (last_seq->ipo && seq->ipo==last_seq->ipo)) {
+ a= seq->len;
+ se= seq->strip->stripdata;
+ if(se) {
+ while(a--) {
+ if(se->ibuf) IMB_freeImBuf(se->ibuf);
+ se->ibuf= 0;
+ se->ok= 1;
+ se++;
+ }
+ }
+ }
+ }
+ END_SEQ
+ }
+}
+
+static int test_overlap_seq(Sequence *test)
+{
+ Sequence *seq;
+ Editing *ed;
+
+ ed= G.scene->ed;
+ if(ed==0) return 0;
+
+ seq= ed->seqbasep->first;
+ while(seq) {
+ if(seq!=test) {
+ if(test->machine==seq->machine) {
+ if(test->depth==seq->depth) {
+ if( (test->enddisp <= seq->startdisp) || (test->startdisp >= seq->enddisp) );
+ else return 1;
+ }
+ }
+ }
+ seq= seq->next;
+ }
+ return 0;
+}
+
+static void shuffle_seq(Sequence *test)
+{
+ Editing *ed;
+ Sequence *seq;
+ int a, start;
+
+ ed= G.scene->ed;
+ if(ed==0) return;
+
+ /* als er meerdere select zijn: alleen y shuffelen */
+ a=0;
+ seq= ed->seqbasep->first;
+ while(seq) {
+ if(seq->flag & SELECT) a++;
+ seq= seq->next;
+ }
+
+ if(a<2 && test->type==SEQ_IMAGE) {
+ start= test->start;
+
+ for(a= 1; a<50; a++) {
+ test->start= start+a;
+ calc_sequence(test);
+ if( test_overlap_seq(test)==0) return;
+ test->start= start-a;
+ calc_sequence(test);
+ if( test_overlap_seq(test)==0) return;
+ }
+ test->start= start;
+ }
+
+ test->machine++;
+ calc_sequence(test);
+ while( test_overlap_seq(test) ) {
+ if(test->machine >= MAXSEQ) {
+ error("No space to add sequence ");
+
+ BLI_remlink(ed->seqbasep, test);
+ free_sequence(test);
+ return;
+ }
+ test->machine++;
+ calc_sequence(test);
+ }
+}
+
+static void deselect_all_seq(void)
+{
+ Sequence *seq;
+ Editing *ed;
+
+ ed= G.scene->ed;
+ if(ed==0) return;
+
+ WHILE_SEQ(ed->seqbasep) {
+ seq->flag &= SEQ_DESEL;
+ }
+ END_SEQ
+}
+
+static void recurs_sel_seq(Sequence *seqm)
+{
+ Sequence *seq;
+
+ seq= seqm->seqbase.first;
+ while(seq) {
+
+ if(seqm->flag & (SEQ_LEFTSEL+SEQ_RIGHTSEL)) seq->flag &= SEQ_DESEL;
+ else if(seqm->flag & SELECT) seq->flag |= SELECT;
+ else seq->flag &= SEQ_DESEL;
+
+ if(seq->seqbase.first) recurs_sel_seq(seq);
+
+ seq= seq->next;
+ }
+}
+
+void swap_select_seq(void)
+{
+ Sequence *seq;
+ Editing *ed;
+ int sel=0;
+
+ ed= G.scene->ed;
+ if(ed==0) return;
+
+ WHILE_SEQ(ed->seqbasep) {
+ if(seq->flag & SELECT) sel= 1;
+ }
+ END_SEQ
+
+ WHILE_SEQ(ed->seqbasep) {
+ /* alles voor zekerheid altijd deselecteren */
+ seq->flag &= SEQ_DESEL;
+ if(sel==0) seq->flag |= SELECT;
+ }
+ END_SEQ
+
+ allqueue(REDRAWSEQ, 0);
+}
+
+void mouse_select_seq(void)
+{
+ Sequence *seq;
+ int hand;
+
+ seq= find_nearest_seq(&hand);
+
+ if(G.qual==0) deselect_all_seq();
+
+ if(seq) {
+ last_seq= seq;
+
+ if ELEM(seq->type, SEQ_IMAGE, SEQ_MOVIE) {
+ if(seq->strip) strcpy(last_imagename, seq->strip->dir);
+ }
+
+ if(G.qual==0) {
+ seq->flag |= SELECT;
+ if(hand==1) seq->flag |= SEQ_LEFTSEL;
+ if(hand==2) seq->flag |= SEQ_RIGHTSEL;
+ }
+ else {
+ if(seq->flag & SELECT) {
+ if(hand==0) seq->flag &= SEQ_DESEL;
+ else if(hand==1) {
+ if(seq->flag & SEQ_LEFTSEL) seq->flag &= ~SEQ_LEFTSEL;
+ else seq->flag |= SEQ_LEFTSEL;
+ }
+ else if(hand==2) {
+ if(seq->flag & SEQ_RIGHTSEL) seq->flag &= ~SEQ_RIGHTSEL;
+ else seq->flag |= SEQ_RIGHTSEL;
+ }
+ }
+ else {
+ seq->flag |= SELECT;
+ if(hand==1) seq->flag |= SEQ_LEFTSEL;
+ if(hand==2) seq->flag |= SEQ_RIGHTSEL;
+ }
+ }
+ recurs_sel_seq(seq);
+ }
+
+ force_draw();
+
+ if(last_seq) allqueue(REDRAWIPO, 0);
+
+ std_rmouse_transform(transform_seq);
+}
+
+static Sequence *alloc_sequence(int cfra, int machine)
+{
+ Editing *ed;
+ Sequence *seq;
+
+ ed= G.scene->ed;
+
+ seq= MEM_callocN( sizeof(Sequence), "addseq");
+ BLI_addtail(ed->seqbasep, seq);
+
+ last_seq= seq;
+
+ *( (short *)seq->name )= ID_SEQ;
+ seq->name[2]= 0;
+
+ seq->flag= SELECT;
+ seq->start= cfra;
+ seq->machine= machine;
+
+ return seq;
+}
+
+static Sequence *sfile_to_sequence(SpaceFile *sfile, int cfra, int machine, int last)
+{
+ Sequence *seq;
+ Strip *strip;
+ StripElem *se;
+ int totsel, a;
+
+ /* zijn er geselecteerde files? */
+ totsel= 0;
+ for(a=0; a<sfile->totfile; a++) {
+ if(sfile->filelist[a].flags & ACTIVE) {
+ if( (sfile->filelist[a].type & S_IFDIR)==0 ) {
+ totsel++;
+ }
+ }
+ }
+
+ if(last) {
+ /* of anders een aangegeven file? */
+ if(totsel==0 && sfile->file[0]) totsel= 1;
+ }
+
+ if(totsel==0) return 0;
+
+ /* seq maken */
+ seq= alloc_sequence(cfra, machine);
+ seq->len= totsel;
+
+ if(totsel==1) {
+ seq->startstill= 25;
+ seq->endstill= 24;
+ }
+
+ calc_sequence(seq);
+
+ /* strip en stripdata */
+ seq->strip= strip= MEM_callocN(sizeof(Strip), "strip");
+ strip->len= totsel;
+ strip->us= 1;
+ strcpy(strip->dir, sfile->dir);
+ strip->stripdata= se= MEM_callocN(totsel*sizeof(StripElem), "stripelem");
+
+ for(a=0; a<sfile->totfile; a++) {
+ if(sfile->filelist[a].flags & ACTIVE) {
+ if( (sfile->filelist[a].type & S_IFDIR)==0 ) {
+ strcpy(se->name, sfile->filelist[a].relname);
+ se->ok= 1;
+ se++;
+ }
+ }
+ }
+ /* geen geselecteerde file: */
+ if(totsel==1 && se==strip->stripdata) {
+ strcpy(se->name, sfile->file);
+ se->ok= 1;
+ }
+
+ /* laatste aktieve naam */
+ strcpy(last_imagename, seq->strip->dir);
+
+ return seq;
+}
+
+static void sfile_to_mv_sequence(SpaceFile *sfile, int cfra, int machine)
+{
+ Sequence *seq;
+ struct anim *anim;
+ Strip *strip;
+ StripElem *se;
+ int totframe, a;
+ char str[256];
+
+ totframe= 0;
+
+ strcpy(str, sfile->dir);
+ strcat(str, sfile->file);
+
+ /* is er sprake van een movie */
+ anim = openanim(str, IB_rect);
+ if(anim==0) {
+ error("Not a movie");
+ return;
+ }
+
+ totframe= IMB_anim_get_duration(anim);
+
+ /* seq maken */
+ seq= alloc_sequence(cfra, machine);
+ seq->len= totframe;
+ seq->type= SEQ_MOVIE;
+ seq->anim= anim;
+
+ calc_sequence(seq);
+
+ /* strip en stripdata */
+ seq->strip= strip= MEM_callocN(sizeof(Strip), "strip");
+ strip->len= totframe;
+ strip->us= 1;
+ strcpy(strip->dir, sfile->dir);
+ strip->stripdata= se= MEM_callocN(totframe*sizeof(StripElem), "stripelem");
+
+ /* naam movie in eerste strip */
+ strcpy(se->name, sfile->file);
+
+ for(a=1; a<=totframe; a++, se++) {
+ se->ok= 1;
+ se->nr= a;
+ }
+
+ /* laatste aktieve naam */
+ strcpy(last_imagename, seq->strip->dir);
+}
+
+static void add_image_strips(char *name)
+{
+ SpaceFile *sfile;
+ struct direntry *files;
+ float x, y;
+ int a, totfile, cfra, machine;
+ short mval[2];
+
+ deselect_all_seq();
+
+ /* is voor restore windowmatrices */
+ areawinset(curarea->win);
+ drawseqspace();
+
+ /* sfile zoeken */
+ sfile= scrarea_find_space_of_type(curarea, SPACE_FILE);
+ if(sfile==0) return;
+
+ /* waar komen ze */
+ getmouseco_areawin(mval);
+ areamouseco_to_ipoco(G.v2d, mval, &x, &y);
+ cfra= (int)(x+0.5);
+ machine= (int)(y+0.5);
+
+ waitcursor(1);
+
+ /* ook inhoud van geselecteerde directories lezen */
+ files= sfile->filelist;
+ totfile= sfile->totfile;
+ sfile->filelist= 0;
+ sfile->totfile= 0;
+
+ for(a=0; a<totfile; a++) {
+ if(files[a].flags & ACTIVE) {
+ if( (files[a].type & S_IFDIR) ) {
+ strcat(sfile->dir, files[a].relname);
+ strcat(sfile->dir,"/");
+ read_dir(sfile);
+
+ /* selecteer alles */
+ swapselect_file(sfile);
+
+ if ( sfile_to_sequence(sfile, cfra, machine, 0) ) machine++;
+
+ parent(sfile);
+ }
+ }
+ }
+
+ sfile->filelist= files;
+ sfile->totfile= totfile;
+
+ /* directory zelf lezen */
+ sfile_to_sequence(sfile, cfra, machine, 1);
+
+ waitcursor(0);
+
+ transform_seq('g');
+
+}
+
+static void add_movie_strip(char *name)
+{
+ SpaceFile *sfile;
+ float x, y;
+ int cfra, machine;
+ short mval[2];
+
+ deselect_all_seq();
+
+ /* is voor restore windowmatrices */
+ areawinset(curarea->win);
+ drawseqspace();
+
+ /* sfile zoeken */
+ sfile= scrarea_find_space_of_type(curarea, SPACE_FILE);
+ if(sfile==0) return;
+
+ /* waar komen ze */
+ getmouseco_areawin(mval);
+ areamouseco_to_ipoco(G.v2d, mval, &x, &y);
+ cfra= (int)(x+0.5);
+ machine= (int)(y+0.5);
+
+ waitcursor(1);
+
+ /* directory zelf lezen */
+ sfile_to_mv_sequence(sfile, cfra, machine);
+
+ waitcursor(0);
+
+ transform_seq('g');
+
+}
+
+static void reload_image_strip(char *name)
+{
+ Editing *ed;
+ Sequence *seq, *seqact;
+ SpaceFile *sfile;
+
+ ed= G.scene->ed;
+
+ if(last_seq==0 || last_seq->type!=SEQ_IMAGE) return;
+ seqact= last_seq; /* last_seq verandert in alloc_sequence */
+
+ /* sfile zoeken */
+ sfile= scrarea_find_space_of_type(curarea, SPACE_FILE);
+ if(sfile==0) return;
+
+ waitcursor(1);
+
+ seq= sfile_to_sequence(sfile, seqact->start, seqact->machine, 1);
+ if(seq && seq!=seqact) {
+ free_strip(seqact->strip);
+
+ seqact->strip= seq->strip;
+
+ seqact->len= seq->len;
+ calc_sequence(seqact);
+
+ seq->strip= 0;
+ free_sequence(seq);
+ BLI_remlink(ed->seqbasep, seq);
+
+ seq= ed->seqbasep->first;
+ while(seq) {
+ if(seq->type & SEQ_EFFECT) {
+ /* new_stripdata is clear */
+ if(seq->seq1==seqact || seq->seq2==seqact || seq->seq3==seqact) {
+ calc_sequence(seq);
+ new_stripdata(seq);
+ }
+ }
+ seq= seq->next;
+ }
+ }
+ waitcursor(0);
+
+ allqueue(REDRAWSEQ, 0);
+}
+
+static int event_to_efftype(int event)
+{
+ if(event==2) return SEQ_CROSS;
+ if(event==3) return SEQ_GAMCROSS;
+ if(event==4) return SEQ_ADD;
+ if(event==5) return SEQ_SUB;
+ if(event==6) return SEQ_MUL;
+ if(event==7) return SEQ_ALPHAOVER;
+ if(event==8) return SEQ_ALPHAUNDER;
+ if(event==9) return SEQ_OVERDROP;
+ if(event==10) return SEQ_PLUGIN;
+ return 0;
+}
+
+static int add_seq_effect(int type)
+{
+ Editing *ed;
+ Sequence *seq, *seq1, *seq2, *seq3;
+ Strip *strip;
+ float x, y;
+ int cfra, machine;
+ short mval[2];
+
+ if(G.scene->ed==0) return 0;
+ ed= G.scene->ed;
+
+ /* behalve de last_seq moet er nog een of twee geselecteerde seq zijn */
+ seq1= seq3= 0;
+ seq2= last_seq; /* last_seq verandert bij alloc_seq! */
+ seq= ed->seqbasep->first;
+ while(seq) {
+ if(seq->flag & SELECT) {
+ if(seq != seq2) {
+ if(seq1==0) seq1= seq;
+ else if(seq3==0) seq3= seq;
+ else {
+ seq1= 0;
+ break;
+ }
+ }
+ }
+ seq= seq->next;
+ }
+
+ if(type==10) { /* plugin: minimaal 1 select */
+ if(seq2==0) {
+ error("Need minimum one active sequence");
+ return 0;
+ }
+ if(seq1==0) seq1= seq2;
+ if(seq3==0) seq3= seq2;
+ }
+ else {
+ if(seq1==0 || seq2==0) {
+ error("Need 2 selected sequences");
+ return 0;
+ }
+ if(seq3==0) seq3= seq2;
+ }
+
+ deselect_all_seq();
+
+ /* waar komt ie (cfra is eigenlijk niet nodig) */
+ getmouseco_areawin(mval);
+ areamouseco_to_ipoco(G.v2d, mval, &x, &y);
+ cfra= (int)(x+0.5);
+ machine= (int)(y+0.5);
+
+ seq= alloc_sequence(cfra, machine);
+
+ seq->type= event_to_efftype(type);
+
+ if(seq->type==SEQ_ALPHAUNDER || seq->type==SEQ_ALPHAOVER) {
+ seq->seq2= seq1;
+ seq->seq1= seq2;
+ }
+ else {
+ seq->seq1= seq1;
+ seq->seq2= seq2;
+ }
+ seq->seq3= seq3;
+ calc_sequence(seq);
+
+ seq->strip= strip= MEM_callocN(sizeof(Strip), "strip");
+ strip->len= seq->len;
+ strip->us= 1;
+ if(seq->len>0) strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelem");
+
+ return 1;
+}
+
+static void load_plugin_seq(char *str) /* aangeroepen vanuit fileselect */
+{
+/* extern Sequence *last_seq; already present in this file... */
+ Editing *ed;
+
+ add_seq_effect(10); /* deze zet last_seq */
+
+ free_plugin_seq(last_seq->plugin);
+
+ last_seq->plugin= (PluginSeq *)add_plugin_seq(str, last_seq->name+2);
+
+ if(last_seq->plugin==0) {
+ ed= G.scene->ed;
+ BLI_remlink(ed->seqbasep, last_seq);
+ free_sequence(last_seq);
+ last_seq= 0;
+ }
+ else {
+ last_seq->machine= MAX3(last_seq->seq1->machine, last_seq->seq2->machine, last_seq->seq3->machine);
+ if( test_overlap_seq(last_seq) ) shuffle_seq(last_seq);
+
+ transform_seq('g');
+ }
+}
+
+void add_sequence(int type)
+{
+ Editing *ed;
+ Sequence *seq;
+ Strip *strip;
+ Scene *sce;
+ float x, y;
+ int cfra, machine;
+ short nr, event, mval[2];
+ char *str;
+
+ event= pupmenu("Add sequence%t|Images%x1|Movie%x102|Scene%x101|Plugin%x10|Cross%x2|GammaCross%x3|Add%x4|Sub%x5|Mul%x6|AlphaOver%x7|AlphaUnder%x8|AlphaOverDrop%x9");
+
+ if(event<1) return;
+
+ if(G.scene->ed==0) {
+ ed= G.scene->ed= MEM_callocN( sizeof(Editing), "addseq");
+ ed->seqbasep= &ed->seqbase;
+ }
+ else ed= G.scene->ed;
+
+ switch(event) {
+ case 1:
+
+ activate_fileselect(FILE_SPECIAL, "SELECT IMAGES", last_imagename, add_image_strips);
+ break;
+ case 102:
+
+ activate_fileselect(FILE_SPECIAL, "SELECT MOVIE", last_imagename, add_movie_strip);
+ break;
+ case 101:
+ /* nieuwe menu: */
+ IDnames_to_pupstring(&str, NULL, NULL, &G.main->scene, (ID *)G.scene, &nr);
+
+ event= pupmenu(str);
+
+ if(event> -1) {
+ nr= 1;
+ sce= G.main->scene.first;
+ while(sce) {
+ if( event==nr) break;
+ nr++;
+ sce= sce->id.next;
+ }
+ if(sce) {
+
+ deselect_all_seq();
+
+ /* waar komt ie ? */
+ getmouseco_areawin(mval);
+ areamouseco_to_ipoco(G.v2d, mval, &x, &y);
+ cfra= (int)(x+0.5);
+ machine= (int)(y+0.5);
+
+ seq= alloc_sequence(cfra, machine);
+ seq->type= SEQ_SCENE;
+ seq->scene= sce;
+ seq->sfra= sce->r.sfra;
+ seq->len= sce->r.efra - sce->r.sfra + 1;
+
+ seq->strip= strip= MEM_callocN(sizeof(Strip), "strip");
+ strip->len= seq->len;
+ strip->us= 1;
+ if(seq->len>0) strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelem");
+
+ transform_seq('g');
+ }
+ }
+ MEM_freeN(str);
+
+ break;
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ case 10:
+
+ if(last_seq==0) error("Need minimum one active sequence");
+ else if(event==10) {
+ activate_fileselect(FILE_SPECIAL, "SELECT PLUGIN", U.plugseqdir, load_plugin_seq);
+ }
+ else {
+ if( add_seq_effect(event) ) transform_seq('g');
+ }
+
+ break;
+ }
+}
+
+void change_sequence(void)
+{
+ Scene *sce;
+ short event;
+
+ if(last_seq==0) return;
+
+ if(last_seq->type & SEQ_EFFECT) {
+ event= pupmenu("Change effect%t|Switch a-b %x1|Switch b-c %x10|Plugin%x11|Recalculate%x12|Cross%x2|GammaCross%x3|Add%x4|Sub%x5|Mul%x6|AlphaOver%x7|AlphaUnder%x8|AlphaOverdrop%x9");
+ if(event>0) {
+ if(event==1) {
+ SWAP(Sequence *, last_seq->seq1, last_seq->seq2);
+ }
+ else if(event==10) {
+ SWAP(Sequence *, last_seq->seq2, last_seq->seq3);
+ }
+ else if(event==11) {
+ activate_fileselect(FILE_SPECIAL, "SELECT PLUGIN", U.plugseqdir, change_plugin_seq);
+ }
+ else if(event==12); /* recalculate: alleen new_stripdata */
+ else {
+ /* voor zekerheid plugin vrijgeven */
+ free_plugin_seq(last_seq->plugin);
+ last_seq->plugin= 0;
+ last_seq->type= event_to_efftype(event);
+ }
+ new_stripdata(last_seq);
+ allqueue(REDRAWSEQ, 0);
+ }
+ }
+ else if(last_seq->type == SEQ_IMAGE) {
+ if(okee("Change images")) {
+ activate_fileselect(FILE_SPECIAL, "SELECT IMAGES", last_imagename, reload_image_strip);
+ }
+ }
+ else if(last_seq->type == SEQ_MOVIE) {
+ ;
+ }
+ else if(last_seq->type == SEQ_SCENE) {
+ event= pupmenu("Change Scene%t|Update Start and End");
+
+ if(event==1) {
+ sce= last_seq->scene;
+
+ last_seq->len= sce->r.efra - sce->r.sfra + 1;
+ last_seq->sfra= sce->r.sfra;
+ new_stripdata(last_seq);
+ calc_sequence(last_seq);
+
+ allqueue(REDRAWSEQ, 0);
+ }
+ }
+
+}
+
+static int is_a_sequence(Sequence *test)
+{
+ Sequence *seq;
+ Editing *ed;
+
+ ed= G.scene->ed;
+ if(ed==0 || test==0) return 0;
+
+ seq= ed->seqbasep->first;
+ while(seq) {
+ if(seq==test) return 1;
+ seq= seq->next;
+ }
+
+ return 0;
+}
+
+static void recurs_del_seq(ListBase *lb)
+{
+ Sequence *seq, *seqn;
+
+ seq= lb->first;
+ while(seq) {
+ seqn= seq->next;
+ if(seq->flag & SELECT) {
+ BLI_remlink(lb, seq);
+ if(seq==last_seq) last_seq= 0;
+ if(seq->type==SEQ_META) recurs_del_seq(&seq->seqbase);
+ if(seq->ipo) seq->ipo->id.us--;
+ free_sequence(seq);
+ }
+ seq= seqn;
+ }
+}
+
+void del_seq(void)
+{
+ Sequence *seq, *seqn;
+ MetaStack *ms;
+ Editing *ed;
+ int doit;
+
+ if(okee("Erase selected")==0) return;
+
+ ed= G.scene->ed;
+ if(ed==0) return;
+
+ recurs_del_seq(ed->seqbasep);
+
+ /* effecten testen */
+ doit= 1;
+ while(doit) {
+ doit= 0;
+ seq= ed->seqbasep->first;
+ while(seq) {
+ seqn= seq->next;
+ if(seq->type & SEQ_EFFECT) {
+ if( is_a_sequence(seq->seq1)==0 || is_a_sequence(seq->seq2)==0 || is_a_sequence(seq->seq3)==0 ) {
+ BLI_remlink(ed->seqbasep, seq);
+ if(seq==last_seq) last_seq= 0;
+ free_sequence(seq);
+ doit= 1;
+ }
+ }
+ seq= seqn;
+ }
+ }
+
+ /* lengtes en zo updaten */
+ seq= ed->seqbasep->first;
+ while(seq) {
+ calc_sequence(seq);
+ seq= seq->next;
+ }
+
+ /* parent meta's vrijgeven */
+ ms= ed->metastack.last;
+ while(ms) {
+ ms->parseq->strip->len= 0; /* forceer nieuwe alloc */
+ calc_sequence(ms->parseq);
+ ms= ms->prev;
+ }
+
+ allqueue(REDRAWSEQ, 0);
+}
+
+
+
+static void recurs_dupli_seq(ListBase *old, ListBase *new)
+{
+ Sequence *seq, *seqn;
+ StripElem *se;
+ int a;
+
+ seq= old->first;
+
+ while(seq) {
+ seq->newseq= 0;
+ if(seq->flag & SELECT) {
+
+ if(seq->type==SEQ_META) {
+ seqn= MEM_dupallocN(seq);
+ seq->newseq= seqn;
+ BLI_addtail(new, seqn);
+
+ seqn->strip= MEM_dupallocN(seq->strip);
+
+ if(seq->len>0) seq->strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelem");
+
+ seq->flag &= SEQ_DESEL;
+ seqn->flag &= ~(SEQ_LEFTSEL+SEQ_RIGHTSEL);
+
+ seqn->seqbase.first= seqn->seqbase.last= 0;
+ recurs_dupli_seq(&seq->seqbase, &seqn->seqbase);
+
+ }
+ else if(seq->type == SEQ_SCENE) {
+ seqn= MEM_dupallocN(seq);
+ seq->newseq= seqn;
+ BLI_addtail(new, seqn);
+
+ seqn->strip= MEM_dupallocN(seq->strip);
+
+ if(seq->len>0) seqn->strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelem");
+
+ seq->flag &= SEQ_DESEL;
+ seqn->flag &= ~(SEQ_LEFTSEL+SEQ_RIGHTSEL);
+ }
+ else if(seq->type == SEQ_MOVIE) {
+ seqn= MEM_dupallocN(seq);
+ seq->newseq= seqn;
+ BLI_addtail(new, seqn);
+
+ seqn->strip= MEM_dupallocN(seq->strip);
+ seqn->anim= 0;
+
+ if(seqn->len>0) {
+ seqn->strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelem");
+ /* kopie eerste elem */
+ *seqn->strip->stripdata= *seq->strip->stripdata;
+ se= seqn->strip->stripdata;
+ a= seq->len;
+ while(a--) {
+ se->ok= 1;
+ se++;
+ }
+ }
+
+ seq->flag &= SEQ_DESEL;
+ seqn->flag &= ~(SEQ_LEFTSEL+SEQ_RIGHTSEL);
+ }
+ else if(seq->type < SEQ_EFFECT) {
+ seqn= MEM_dupallocN(seq);
+ seq->newseq= seqn;
+ BLI_addtail(new, seqn);
+
+ seqn->strip->us++;
+ seq->flag &= SEQ_DESEL;
+
+ seqn->flag &= ~(SEQ_LEFTSEL+SEQ_RIGHTSEL);
+ }
+ else {
+ if(seq->seq1->newseq) {
+
+ seqn= MEM_dupallocN(seq);
+ seq->newseq= seqn;
+ BLI_addtail(new, seqn);
+
+ seqn->seq1= seq->seq1->newseq;
+ if(seq->seq2 && seq->seq2->newseq) seqn->seq2= seq->seq2->newseq;
+ if(seq->seq3 && seq->seq3->newseq) seqn->seq3= seq->seq3->newseq;
+
+ if(seqn->ipo) seqn->ipo->id.us++;
+
+ if(seq->plugin) {
+ seqn->plugin= MEM_dupallocN(seq->plugin);
+ open_plugin_seq(seqn->plugin, seqn->name+2);
+ }
+ seqn->strip= MEM_dupallocN(seq->strip);
+
+ if(seq->len>0) seq->strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelem");
+
+ seq->flag &= SEQ_DESEL;
+
+ seqn->flag &= ~(SEQ_LEFTSEL+SEQ_RIGHTSEL);
+ }
+ }
+
+ }
+ seq= seq->next;
+ }
+}
+
+void add_duplicate_seq(void)
+{
+ Editing *ed;
+ ListBase new;
+
+ ed= G.scene->ed;
+ if(ed==0) return;
+
+ new.first= new.last= 0;
+
+ recurs_dupli_seq(ed->seqbasep, &new);
+ addlisttolist(ed->seqbasep, &new);
+
+ transform_seq('g');
+}
+
+int insert_gap(int gap, int cfra)
+{
+ Sequence *seq;
+ Editing *ed;
+ int done=0;
+
+ /* alle strips >= cfra opschuiven */
+ ed= G.scene->ed;
+ if(ed==0) return 0;
+
+ WHILE_SEQ(ed->seqbasep) {
+ if(seq->startdisp >= cfra) {
+ seq->start+= gap;
+ calc_sequence(seq);
+ done= 1;
+ }
+ }
+ END_SEQ
+
+ return done;
+}
+
+void touch_seq_files(void)
+{
+ Sequence *seq;
+ Editing *ed;
+/* int done=0; */
+ char str[256];
+
+ /* alle strips movies touchen */
+ ed= G.scene->ed;
+ if(ed==0) return;
+
+ if(okee("Touch & print selected Movies")==0) return;
+
+ waitcursor(1);
+
+ WHILE_SEQ(ed->seqbasep) {
+ if(seq->flag & SELECT) {
+ if(seq->type==SEQ_MOVIE) {
+ if(seq->strip && seq->strip->stripdata) {
+ BLI_make_file_string(G.sce, str, seq->strip->dir, seq->strip->stripdata->name);
+ BLI_touch(seq->name);
+ }
+ }
+
+ }
+ }
+ END_SEQ
+
+ waitcursor(0);
+}
+
+void set_filter_seq(void)
+{
+ Sequence *seq;
+ Editing *ed;
+/* int done=0; */
+
+ ed= G.scene->ed;
+ if(ed==0) return;
+
+ if(okee("Set FilterY")==0) return;
+
+ WHILE_SEQ(ed->seqbasep) {
+ if(seq->flag & SELECT) {
+ if(seq->type==SEQ_MOVIE) {
+ seq->flag |= SEQ_FILTERY;
+ }
+
+ }
+ }
+ END_SEQ
+
+}
+
+
+
+void no_gaps(void)
+{
+ Editing *ed;
+ int cfra, first= 0, done;
+
+ ed= G.scene->ed;
+ if(ed==0) return;
+
+ for(cfra= CFRA; cfra<=EFRA; cfra++) {
+ if(first==0) {
+ if( evaluate_seq_frame(cfra) ) first= 1;
+ }
+ else {
+ done= 1;
+ while( evaluate_seq_frame(cfra) == 0) {
+ done= insert_gap(-1, cfra);
+ if(done==0) break;
+ }
+ if(done==0) break;
+ }
+ }
+ allqueue(REDRAWSEQ, 0);
+}
+
+
+/* ****************** META ************************* */
+
+void make_meta(void)
+{
+ Sequence *seq, *seqm, *next;
+ Editing *ed;
+ int tot;
+
+ ed= G.scene->ed;
+ if(ed==0) return;
+
+ /* is er wel meer dan 1 select */
+ tot= 0;
+ seq= ed->seqbasep->first;
+ while(seq) {
+ if(seq->flag & SELECT) tot++;
+ seq= seq->next;
+ }
+ if(tot < 2) return;
+
+ if(okee("Make Meta")==0) return;
+
+ /* samenhang testen */
+ seq= ed->seqbasep->first;
+ while(seq) {
+ if(seq->flag & SELECT) {
+ if(seq->type & SEQ_EFFECT) {
+ if((seq->seq1->flag & SELECT)==0) tot= 0;
+ if((seq->seq2->flag & SELECT)==0) tot= 0;
+ if((seq->seq3->flag & SELECT)==0) tot= 0;
+ }
+ }
+ else if(seq->type & SEQ_EFFECT) {
+ if(seq->seq1->flag & SELECT) tot= 0;
+ if(seq->seq2->flag & SELECT) tot= 0;
+ if(seq->seq3->flag & SELECT) tot= 0;
+ }
+ if(tot==0) break;
+ seq= seq->next;
+ }
+ if(tot==0) {
+ error("Select all related strips");
+ return;
+ }
+
+ /* alle select uit hoofdlijst halen en in meta stoppen */
+
+ seqm= alloc_sequence(1, 1);
+ seqm->type= SEQ_META;
+ seqm->flag= SELECT;
+
+ seq= ed->seqbasep->first;
+ while(seq) {
+ next= seq->next;
+ if(seq!=seqm && (seq->flag & SELECT)) {
+ BLI_remlink(ed->seqbasep, seq);
+ BLI_addtail(&seqm->seqbase, seq);
+ }
+ seq= next;
+ }
+ calc_sequence(seqm);
+
+ seqm->strip= MEM_callocN(sizeof(Strip), "metastrip");
+ seqm->strip->len= seqm->len;
+ seqm->strip->us= 1;
+ if(seqm->len) seqm->strip->stripdata= MEM_callocN(seqm->len*sizeof(StripElem), "metastripdata");
+
+ set_meta_stripdata(seqm);
+
+ allqueue(REDRAWSEQ, 0);
+}
+
+void un_meta(void)
+{
+ Editing *ed;
+ Sequence *seq, *seqn;
+ int doit;
+
+ ed= G.scene->ed;
+ if(ed==0) return;
+
+ if(last_seq==0 || last_seq->type!=SEQ_META) return;
+
+ if(okee("Un Meta")==0) return;
+
+ addlisttolist(ed->seqbasep, &last_seq->seqbase);
+
+ last_seq->seqbase.first= 0;
+ last_seq->seqbase.last= 0;
+
+ BLI_remlink(ed->seqbasep, last_seq);
+ free_sequence(last_seq);
+
+ /* effecten testen */
+ doit= 1;
+ while(doit) {
+ doit= 0;
+ seq= ed->seqbasep->first;
+ while(seq) {
+ seqn= seq->next;
+ if(seq->type & SEQ_EFFECT) {
+ if( is_a_sequence(seq->seq1)==0 || is_a_sequence(seq->seq2)==0 || is_a_sequence(seq->seq3)==0 ) {
+ BLI_remlink(ed->seqbasep, seq);
+ if(seq==last_seq) last_seq= 0;
+ free_sequence(seq);
+ doit= 1;
+ }
+ }
+ seq= seqn;
+ }
+ }
+
+
+ /* testen op effects en overlap */
+ WHILE_SEQ(ed->seqbasep) {
+ if(seq->flag & SELECT) {
+ seq->flag &= ~SEQ_OVERLAP;
+ if( test_overlap_seq(seq) ) {
+ shuffle_seq(seq);
+ }
+ }
+ }
+ END_SEQ;
+
+ allqueue(REDRAWSEQ, 0);
+
+}
+
+static void exit_meta(void)
+{
+ Sequence *seq;
+ MetaStack *ms;
+ Editing *ed;
+
+ ed= G.scene->ed;
+ if(ed==0) return;
+
+ if(ed->metastack.first==0) return;
+
+ ms= ed->metastack.last;
+ BLI_remlink(&ed->metastack, ms);
+
+ ed->seqbasep= ms->oldbasep;
+
+ /* de hele meta herberekenen */
+ set_meta_stripdata(ms->parseq);
+
+ /* allemaal herberekenen: de meta kan effecten eraan hebben hangen */
+ seq= ed->seqbasep->first;
+ while(seq) {
+ calc_sequence(seq);
+ seq= seq->next;
+ }
+
+ last_seq= ms->parseq;
+
+ last_seq->flag= SELECT;
+ recurs_sel_seq(last_seq);
+
+ MEM_freeN(ms);
+ allqueue(REDRAWSEQ, 0);
+}
+
+
+void enter_meta(void)
+{
+ MetaStack *ms;
+ Editing *ed;
+
+ ed= G.scene->ed;
+ if(ed==0) return;
+
+ if(last_seq==0 || last_seq->type!=SEQ_META || last_seq->flag==0) {
+ exit_meta();
+ return;
+ }
+
+ ms= MEM_mallocN(sizeof(MetaStack), "metastack");
+ BLI_addtail(&ed->metastack, ms);
+ ms->parseq= last_seq;
+ ms->oldbasep= ed->seqbasep;
+
+ ed->seqbasep= &last_seq->seqbase;
+
+ last_seq= 0;
+ allqueue(REDRAWSEQ, 0);
+}
+
+
+/* ****************** END META ************************* */
+
+
+typedef struct TransSeq {
+ int start, machine;
+ int startstill, endstill;
+ int startofs, endofs;
+} TransSeq;
+
+void transform_seq(int mode)
+{
+ Sequence *seq;
+ Editing *ed;
+ float dx, dy, dvec[2], div;
+ TransSeq *transmain, *ts;
+ int tot=0, ix, iy, firsttime=1, afbreek=0, midtog= 0, proj= 0;
+ unsigned short event = 0;
+ short mval[2], val, xo, yo, xn, yn;
+ char str[32];
+
+ if(mode!='g') return; /* vanuit gesture */
+
+ /* welke seqs doen mee */
+ ed= G.scene->ed;
+ if(ed==0) return;
+
+ WHILE_SEQ(ed->seqbasep) {
+ if(seq->flag & SELECT) tot++;
+ }
+ END_SEQ
+
+ if(tot==0) return;
+
+ G.moving= 1;
+
+ ts=transmain= MEM_callocN(tot*sizeof(TransSeq), "transseq");
+
+ WHILE_SEQ(ed->seqbasep) {
+
+ if(seq->flag & SELECT) {
+
+ ts->start= seq->start;
+ ts->machine= seq->machine;
+ ts->startstill= seq->startstill;
+ ts->endstill= seq->endstill;
+ ts->startofs= seq->startofs;
+ ts->endofs= seq->endofs;
+
+ ts++;
+ }
+ }
+ END_SEQ
+
+ getmouseco_areawin(mval);
+ xo=xn= mval[0];
+ yo=yn= mval[1];
+ dvec[0]= dvec[1]= 0.0;
+
+ while(afbreek==0) {
+ getmouseco_areawin(mval);
+ if(mval[0]!=xo || mval[1]!=yo || firsttime) {
+ firsttime= 0;
+
+ if(mode=='g') {
+
+ dx= mval[0]- xo;
+ dy= mval[1]- yo;
+
+ div= G.v2d->mask.xmax-G.v2d->mask.xmin;
+ dx= (G.v2d->cur.xmax-G.v2d->cur.xmin)*(dx)/div;
+
+ div= G.v2d->mask.ymax-G.v2d->mask.ymin;
+ dy= (G.v2d->cur.ymax-G.v2d->cur.ymin)*(dy)/div;
+
+ if(G.qual & LR_SHIFTKEY) {
+ if(dx>1.0) dx= 1.0; else if(dx<-1.0) dx= -1.0;
+ }
+
+ dvec[0]+= dx;
+ dvec[1]+= dy;
+
+ if(midtog) dvec[proj]= 0.0;
+ ix= floor(dvec[0]+0.5);
+ iy= floor(dvec[1]+0.5);
+
+
+ ts= transmain;
+
+ WHILE_SEQ(ed->seqbasep) {
+ if(seq->flag & SELECT) {
+ if(seq->flag & SEQ_LEFTSEL) {
+ if(ts->startstill) {
+ seq->startstill= ts->startstill-ix;
+ if(seq->startstill<0) seq->startstill= 0;
+ }
+ else if(ts->startofs) {
+ seq->startofs= ts->startofs+ix;
+ if(seq->startofs<0) seq->startofs= 0;
+ }
+ else {
+ if(ix>0) {
+ seq->startofs= ix;
+ seq->startstill= 0;
+ }
+ else {
+ seq->startstill= -ix;
+ seq->startofs= 0;
+ }
+ }
+ if(seq->len <= seq->startofs+seq->endofs) {
+ seq->startofs= seq->len-seq->endofs-1;
+ }
+ }
+ if(seq->flag & SEQ_RIGHTSEL) {
+ if(ts->endstill) {
+ seq->endstill= ts->endstill+ix;
+ if(seq->endstill<0) seq->endstill= 0;
+ }
+ else if(ts->endofs) {
+ seq->endofs= ts->endofs-ix;
+ if(seq->endofs<0) seq->endofs= 0;
+ }
+ else {
+ if(ix<0) {
+ seq->endofs= -ix;
+ seq->endstill= 0;
+ }
+ else {
+ seq->endstill= ix;
+ seq->endofs= 0;
+ }
+ }
+ if(seq->len <= seq->startofs+seq->endofs) {
+ seq->endofs= seq->len-seq->startofs-1;
+ }
+ }
+ if( (seq->flag & (SEQ_LEFTSEL+SEQ_RIGHTSEL))==0 ) {
+ if(seq->type<SEQ_EFFECT) seq->start= ts->start+ ix;
+
+ if(seq->depth==0) seq->machine= ts->machine+ iy;
+
+ if(seq->machine<1) seq->machine= 1;
+ else if(seq->machine>= MAXSEQ) seq->machine= MAXSEQ;
+ }
+
+ calc_sequence(seq);
+
+ ts++;
+ }
+ }
+ END_SEQ
+
+ sprintf(str, "X: %d Y: %d ", ix, iy);
+ headerprint(str);
+ }
+
+ xo= mval[0];
+ yo= mval[1];
+
+ /* testen op effect en overlap */
+
+ WHILE_SEQ(ed->seqbasep) {
+ if(seq->flag & SELECT) {
+ seq->flag &= ~SEQ_OVERLAP;
+ if( test_overlap_seq(seq) ) {
+ seq->flag |= SEQ_OVERLAP;
+ }
+ }
+ else if(seq->type & SEQ_EFFECT) {
+ if(seq->seq1->flag & SELECT) calc_sequence(seq);
+ else if(seq->seq2->flag & SELECT) calc_sequence(seq);
+ else if(seq->seq3->flag & SELECT) calc_sequence(seq);
+ }
+ }
+ END_SEQ;
+
+ force_draw();
+ }
+ else BIF_wait_for_statechange();
+
+ while(qtest()) {
+ event= extern_qread(&val);
+ if(val) {
+ switch(event) {
+ case ESCKEY:
+ case LEFTMOUSE:
+ case SPACEKEY:
+ afbreek= 1;
+ break;
+ case MIDDLEMOUSE:
+ midtog= ~midtog;
+ if(midtog) {
+ if( abs(mval[0]-xn) > abs(mval[1]-yn)) proj= 1;
+ else proj= 0;
+ firsttime= 1;
+ }
+ break;
+ default:
+ arrows_move_cursor(event);
+ }
+ }
+ if(afbreek) break;
+ }
+ }
+
+ if(event==ESCKEY) {
+
+ ts= transmain;
+ WHILE_SEQ(ed->seqbasep) {
+ if(seq->flag & SELECT) {
+ seq->start= ts->start;
+ seq->machine= ts->machine;
+ seq->startstill= ts->startstill;
+ seq->endstill= ts->endstill;
+ seq->startofs= ts->startofs;
+ seq->endofs= ts->endofs;
+
+ calc_sequence(seq);
+ seq->flag &= ~SEQ_OVERLAP;
+
+ ts++;
+ } else if(seq->type & SEQ_EFFECT) {
+ if(seq->seq1->flag & SELECT) calc_sequence(seq);
+ else if(seq->seq2->flag & SELECT) calc_sequence(seq);
+ else if(seq->seq3->flag & SELECT) calc_sequence(seq);
+ }
+
+ }
+ END_SEQ
+ }
+ else {
+
+ /* images, effecten en overlap */
+ WHILE_SEQ(ed->seqbasep) {
+ if(seq->type == SEQ_META) {
+ calc_sequence(seq);
+ seq->flag &= ~SEQ_OVERLAP;
+ if( test_overlap_seq(seq) ) shuffle_seq(seq);
+ }
+ else if(seq->flag & SELECT) {
+ calc_sequence(seq);
+ seq->flag &= ~SEQ_OVERLAP;
+ if( test_overlap_seq(seq) ) shuffle_seq(seq);
+ }
+ else if(seq->type & SEQ_EFFECT) calc_sequence(seq);
+ }
+ END_SEQ
+
+ /* als laatste: */
+ sort_seq();
+ }
+
+ G.moving= 0;
+ MEM_freeN(transmain);
+
+ allqueue(REDRAWSEQ, 0);
+}
+
+
+void clever_numbuts_seq(void)
+{
+ PluginSeq *pis;
+ StripElem *se;
+ VarStruct *varstr;
+ int a;
+
+ if(last_seq==0) return;
+ if(last_seq->type==SEQ_PLUGIN) {
+ pis= last_seq->plugin;
+ if(pis->vars==0) return;
+
+ varstr= pis->varstr;
+ if(varstr) {
+ for(a=0; a<pis->vars; a++, varstr++) {
+ add_numbut(a, varstr->type, varstr->name, varstr->min, varstr->max, &(pis->data[a]), varstr->tip);
+ }
+
+ if( do_clever_numbuts(pis->pname, pis->vars, REDRAW) ) {
+ new_stripdata(last_seq);
+ free_imbuf_effect_spec(CFRA);
+ allqueue(REDRAWSEQ, 0);
+ }
+ }
+ }
+ else if(last_seq->type==SEQ_MOVIE) {
+
+ if(last_seq->mul==0.0) last_seq->mul= 1.0;
+
+ add_numbut(0, TEX, "Name:", 0.0, 21.0, last_seq->name+2, 0);
+ add_numbut(1, TOG|SHO|BIT|4, "FilterY", 0.0, 1.0, &last_seq->flag, 0);
+ /* waarschuwing: alleen een enkele bitjes-button mogelijk: er wordt op kopiedata gewerkt! */
+ add_numbut(2, NUM|FLO, "Mul", 0.01, 5.0, &last_seq->mul, 0);
+
+ if( do_clever_numbuts("Movie", 3, REDRAW) ) {
+ se= last_seq->curelem;
+
+ if(se && se->ibuf ) {
+ IMB_freeImBuf(se->ibuf);
+ se->ibuf= 0;
+ }
+ allqueue(REDRAWSEQ, 0);
+ }
+ }
+ else if(last_seq->type==SEQ_META) {
+
+ add_numbut(0, TEX, "Name:", 0.0, 21.0, last_seq->name+2, 0);
+
+ if( do_clever_numbuts("Meta", 1, REDRAW) ) {
+ allqueue(REDRAWSEQ, 0);
+ }
+ }
+}
+
+void seq_snapmenu(void)
+{
+ Editing *ed;
+ Sequence *seq;
+ short event;
+
+ ed= G.scene->ed;
+ if(ed==0) return;
+
+ event= pupmenu("Snap %t|Seq to frame%x1");
+
+ if(event<1) return;
+
+ /* problem: contents of meta's are all shifted to the same position... */
+
+ /* ook meta's aflopen */
+ WHILE_SEQ(ed->seqbasep) {
+ if(seq->flag & SELECT) {
+ if(seq->type<SEQ_EFFECT) seq->start= CFRA-seq->startofs+seq->startstill;
+ calc_sequence(seq);
+ }
+ }
+ END_SEQ
+
+
+ /* testen op effects en overlap */
+ WHILE_SEQ(ed->seqbasep) {
+ if(seq->flag & SELECT) {
+ seq->flag &= ~SEQ_OVERLAP;
+ if( test_overlap_seq(seq) ) {
+ shuffle_seq(seq);
+ }
+ }
+ else if(seq->type & SEQ_EFFECT) {
+ if(seq->seq1->flag & SELECT) calc_sequence(seq);
+ else if(seq->seq2->flag & SELECT) calc_sequence(seq);
+ else if(seq->seq3->flag & SELECT) calc_sequence(seq);
+ }
+ }
+ END_SEQ;
+
+ /* als laatste: */
+ sort_seq();
+
+ allqueue(REDRAWSEQ, 0);
+}
+
+void borderselect_seq(void)
+{
+ Sequence *seq;
+ Editing *ed;
+ rcti rect;
+ rctf rectf, rq;
+ int val;
+ short mval[2];
+
+ ed= G.scene->ed;
+ if(ed==0) return;
+
+ val= get_border(&rect, 3);
+
+ if(val) {
+ mval[0]= rect.xmin;
+ mval[1]= rect.ymin;
+ areamouseco_to_ipoco(G.v2d, mval, &rectf.xmin, &rectf.ymin);
+ mval[0]= rect.xmax;
+ mval[1]= rect.ymax;
+ areamouseco_to_ipoco(G.v2d, mval, &rectf.xmax, &rectf.ymax);
+
+ seq= ed->seqbasep->first;
+ while(seq) {
+
+ if(seq->startstill) rq.xmin= seq->start;
+ else rq.xmin= seq->startdisp;
+ rq.ymin= seq->machine+0.2;
+ if(seq->endstill) rq.xmax= seq->start+seq->len;
+ else rq.xmax= seq->enddisp;
+ rq.ymax= seq->machine+0.8;
+
+ if(BLI_isect_rctf(&rq, &rectf, 0)) {
+ if(val==LEFTMOUSE) {
+ seq->flag |= SELECT;
+ }
+ else {
+ seq->flag &= ~SELECT;
+ }
+ }
+
+ seq= seq->next;
+ }
+
+ addqueue(curarea->win, REDRAW, 1);
+ }
+}
diff --git a/source/blender/src/editsima.c b/source/blender/src/editsima.c
new file mode 100644
index 00000000000..3aa2f43d19f
--- /dev/null
+++ b/source/blender/src/editsima.c
@@ -0,0 +1,905 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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>
+
+#ifndef WIN32
+#include <unistd.h>
+#else
+#include <io.h>
+#include "BLI_winstuff.h"
+#endif
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+
+#include "IMB_imbuf_types.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_space_types.h"
+#include "DNA_image_types.h"
+#include "DNA_object_types.h" // only for uvedit_selectionCB() (struct Object)
+
+#include "BKE_global.h"
+#include "BKE_mesh.h"
+
+#include "BIF_gl.h"
+#include "BIF_interface.h"
+#include "BIF_screen.h"
+#include "BIF_drawimage.h"
+#include "BIF_editview.h"
+#include "BIF_space.h"
+#include "BIF_editsima.h"
+#include "BIF_toolbox.h"
+#include "BIF_mywindow.h"
+
+#include "BSE_drawipo.h"
+#include "BSE_edit.h"
+#include "BSE_trans_types.h"
+
+#include "BDR_editobject.h"
+
+#include "blendef.h"
+#include "mydevice.h"
+#include "interface.h"
+
+static int is_uv_tface_editing_allowed(void)
+{
+ Mesh *me;
+
+ if(G.obedit) {error("Unable to perform function in EditMode"); return 0;}
+ if(G.sima->mode!=SI_TEXTURE) return 0;
+ if(!(G.f & G_FACESELECT)) return 0;
+ me= get_mesh(OBACT);
+ if(me==0 || me->tface==0) return 0;
+
+ return 1;
+}
+
+void clever_numbuts_sima(void)
+{
+ float ocent[2], cent[2]= {0.0, 0.0};
+ int imx, imy;
+ int i, nactive= 0;
+ Mesh *me;
+
+ if( is_uv_tface_editing_allowed()==0 ) return;
+ me= get_mesh(OBACT);
+
+ if (G.sima->image && G.sima->image->ibuf) {
+ imx= G.sima->image->ibuf->x;
+ imy= G.sima->image->ibuf->y;
+ } else
+ imx= imy= 256;
+
+ for (i=0; i<me->totface; i++) {
+ MFace *mf= &((MFace*) me->mface)[i];
+ TFace *tf= &((TFace*) me->tface)[i];
+
+ if (!mf->v3 || !(tf->flag & TF_SELECT))
+ continue;
+
+ if (tf->flag & TF_SEL1) {
+ cent[0]+= tf->uv[0][0];
+ cent[1]+= tf->uv[0][1];
+ nactive++;
+ }
+ if (tf->flag & TF_SEL2) {
+ cent[0]+= tf->uv[1][0];
+ cent[1]+= tf->uv[1][1];
+ nactive++;
+ }
+ if (tf->flag & TF_SEL3) {
+ cent[0]+= tf->uv[2][0];
+ cent[1]+= tf->uv[2][1];
+ nactive++;
+ }
+ if (mf->v4 && (tf->flag & TF_SEL4)) {
+ cent[0]+= tf->uv[3][0];
+ cent[1]+= tf->uv[3][1];
+ nactive++;
+ }
+ }
+
+ if (nactive) {
+ cent[0]= (cent[0]*imx)/nactive;
+ cent[1]= (cent[1]*imy)/nactive;
+
+ add_numbut(0, NUM|FLO, "LocX:", -imx*20, imx*20, &cent[0], NULL);
+ add_numbut(1, NUM|FLO, "LocY:", -imy*20, imy*20, &cent[1], NULL);
+
+ ocent[0]= cent[0];
+ ocent[1]= cent[1];
+ if (do_clever_numbuts((nactive==1)?"Active Vertex":"Selected Center", 2, REDRAW)) {
+ float delta[2];
+
+ delta[0]= (cent[0]-ocent[0])/imx;
+ delta[1]= (cent[1]-ocent[1])/imy;
+
+ for (i=0; i<me->totface; i++) {
+ MFace *mf= &((MFace*) me->mface)[i];
+ TFace *tf= &((TFace*) me->tface)[i];
+
+ if (!mf->v3 || !(tf->flag & TF_SELECT))
+ continue;
+
+ if (tf->flag & TF_SEL1) {
+ tf->uv[0][0]+= delta[0];
+ tf->uv[0][1]+= delta[1];
+ }
+ if (tf->flag & TF_SEL2) {
+ tf->uv[1][0]+= delta[0];
+ tf->uv[1][1]+= delta[1];
+ }
+ if (tf->flag & TF_SEL3) {
+ tf->uv[2][0]+= delta[0];
+ tf->uv[2][1]+= delta[1];
+ }
+ if (mf->v4 && (tf->flag & TF_SEL4)) {
+ tf->uv[3][0]+= delta[0];
+ tf->uv[3][1]+= delta[1];
+ }
+ }
+
+ allqueue(REDRAWVIEW3D, 0);
+ }
+ }
+}
+
+static void sima_pixelgrid(float *loc, float sx, float sy)
+{
+ float y;
+ float x;
+
+ if(G.sima->image && G.sima->image->ibuf) {
+ x= G.sima->image->ibuf->x;
+ y= G.sima->image->ibuf->y;
+
+ sx= floor(x*sx)/x;
+ if(G.sima->flag & SI_CLIP_UV) {
+ CLAMP(sx, 0, 1.0);
+ }
+ loc[0]= sx;
+
+ sy= floor(y*sy)/y;
+ if(G.sima->flag & SI_CLIP_UV) {
+ CLAMP(sy, 0, 1.0);
+ }
+ loc[1]= sy;
+ }
+ else {
+ loc[0]= sx;
+ loc[1]= sy;
+ }
+}
+
+
+static void be_square_tface_uv(Mesh *me)
+{
+ TFace *tface;
+ MFace *mface;
+ int a;
+
+ /* als 1 punt select: doit (met het select punt) */
+ for(a=me->totface, mface= me->mface, tface= me->tface; a>0; a--, tface++, mface++) {
+ if(mface->v4) {
+ if(tface->flag & TF_SELECT) {
+ if(tface->flag & TF_SEL1) {
+ if( tface->uv[1][0] == tface->uv[2][0] ) {
+ tface->uv[1][1]= tface->uv[0][1];
+ tface->uv[3][0]= tface->uv[0][0];
+ }
+ else {
+ tface->uv[1][0]= tface->uv[0][0];
+ tface->uv[3][1]= tface->uv[0][1];
+ }
+
+ }
+ if(tface->flag & TF_SEL2) {
+ if( tface->uv[2][1] == tface->uv[3][1] ) {
+ tface->uv[2][0]= tface->uv[1][0];
+ tface->uv[0][1]= tface->uv[1][1];
+ }
+ else {
+ tface->uv[2][1]= tface->uv[1][1];
+ tface->uv[0][0]= tface->uv[1][0];
+ }
+
+ }
+ if(tface->flag & TF_SEL3) {
+ if( tface->uv[3][0] == tface->uv[0][0] ) {
+ tface->uv[3][1]= tface->uv[2][1];
+ tface->uv[1][0]= tface->uv[2][0];
+ }
+ else {
+ tface->uv[3][0]= tface->uv[2][0];
+ tface->uv[1][1]= tface->uv[2][1];
+ }
+ }
+ if(tface->flag & TF_SEL4) {
+ if( tface->uv[0][1] == tface->uv[1][1] ) {
+ tface->uv[0][0]= tface->uv[3][0];
+ tface->uv[2][1]= tface->uv[3][1];
+ }
+ else {
+ tface->uv[0][1]= tface->uv[3][1];
+ tface->uv[2][0]= tface->uv[3][0];
+ }
+
+ }
+ }
+ }
+ }
+
+}
+
+void tface_do_clip(void)
+{
+ Mesh *me;
+ TFace *tface;
+ int a, b;
+
+ if( is_uv_tface_editing_allowed()==0 ) return;
+ me= get_mesh(OBACT);
+ tface= me->tface;
+
+ for(a=0; a<me->totface; a++, tface++) {
+ if(tface->flag & TF_SELECT) {
+ for(b=0; b<4; b++) {
+ CLAMP(tface->uv[b][0], 0.0, 1.0);
+ CLAMP(tface->uv[b][1], 0.0, 1.0);
+ }
+ }
+ }
+
+}
+
+void transform_tface_uv(int mode)
+{
+ MFace *mface;
+ TFace *tface;
+ Mesh *me;
+ TransVert *transmain, *tv;
+ float asp, dx1, dx2, dy1, dy2, phi, dphi, co, si;
+ float xref=1.0, yref=1.0, size[2], sizefac;
+ float dx, dy, dvec2[2], dvec[2], div, cent[2];
+ float x, y, min[2], max[2], vec[2], xtra[2], ivec[2];
+ int xim, yim, tot=0, a, b, firsttime=1, afbreek=0, midtog= 0, proj = 0;
+ unsigned short event = 0;
+ short mval[2], val, xo, yo, xn, yn, xc, yc;
+ char str[32];
+
+ if( is_uv_tface_editing_allowed()==0 ) return;
+ me= get_mesh(OBACT);
+
+ min[0]= min[1]= 10000.0;
+ max[0]= max[1]= -10000.0;
+
+ calc_image_view(G.sima, 'f');
+
+ if(G.sima->image && G.sima->image->ibuf) {
+ xim= G.sima->image->ibuf->x;
+ yim= G.sima->image->ibuf->y;
+ }
+ else {
+ xim= yim= 256;
+ }
+ /* welke vertices doen mee */
+
+ for(a=me->totface, tface= me->tface, mface= me->mface; a>0; a--, tface++, mface++) {
+ if((tface->flag & TF_SELECT) && mface->v3) {
+ if(tface->flag & TF_SEL1) tot++;
+ if(tface->flag & TF_SEL2) tot++;
+ if(tface->flag & TF_SEL3) tot++;
+ if(tface->flag & TF_SEL4) tot++;
+ }
+ }
+ if(tot==0) return;
+
+ tv=transmain= MEM_callocN(tot*sizeof(TransVert), "transmain");
+
+ for(a=me->totface, tface= me->tface, mface= me->mface; a>0; a--, tface++, mface++) {
+ if((tface->flag & TF_SELECT) && mface->v3) {
+ if(tface->flag & TF_SEL1) {
+ tv->loc= tface->uv[0];
+ tv++;
+ }
+ if(tface->flag & TF_SEL2) {
+ tv->loc= tface->uv[1];
+ tv++;
+ }
+ if(tface->flag & TF_SEL3) {
+ tv->loc= tface->uv[2];
+ tv++;
+ }
+ if(tface->flag & TF_SEL4) {
+ tv->loc= tface->uv[3];
+ tv++;
+ }
+ }
+ }
+
+ a= tot;
+ tv= transmain;
+ while(a--) {
+ tv->oldloc[0]= tv->loc[0];
+ tv->oldloc[1]= tv->loc[1];
+ DO_MINMAX2(tv->loc, min, max);
+ tv++;
+ }
+
+ cent[0]= (min[0]+max[0])/2.0;
+ cent[1]= (min[1]+max[1])/2.0;
+
+ ipoco_to_areaco_noclip(G.v2d, cent, mval);
+ xc= mval[0];
+ yc= mval[1];
+
+ getmouseco_areawin(mval);
+ xo= xn= mval[0];
+ yo= yn= mval[1];
+ dvec[0]= dvec[1]= 0.0;
+ dx1= xc-xn;
+ dy1= yc-yn;
+ phi= 0.0;
+
+
+ sizefac= sqrt( (float)((yc-yn)*(yc-yn)+(xn-xc)*(xn-xc)) );
+ if(sizefac<2.0) sizefac= 2.0;
+
+ while(afbreek==0) {
+ getmouseco_areawin(mval);
+ if(mval[0]!=xo || mval[1]!=yo || firsttime) {
+
+ if(mode=='g') {
+
+ dx= mval[0]- xo;
+ dy= mval[1]- yo;
+
+ div= G.v2d->mask.xmax-G.v2d->mask.xmin;
+ dvec[0]+= (G.v2d->cur.xmax-G.v2d->cur.xmin)*(dx)/div;
+
+ div= G.v2d->mask.ymax-G.v2d->mask.ymin;
+ dvec[1]+= (G.v2d->cur.ymax-G.v2d->cur.ymin)*(dy)/div;
+
+ if(midtog) dvec[proj]= 0.0;
+
+ dvec2[0]= dvec[0];
+ dvec2[1]= dvec[1];
+ apply_keyb_grid(dvec2, 0.0, 1.0/8.0, 1.0/16.0, U.flag & AUTOGRABGRID);
+ apply_keyb_grid(dvec2+1, 0.0, 1.0/8.0, 1.0/16.0, U.flag & AUTOGRABGRID);
+
+ vec[0]= dvec2[0];
+ vec[1]= dvec2[1];
+
+ if(G.sima->flag & SI_CLIP_UV) {
+ if(vec[0]< -min[0]) vec[0]= -min[0];
+ if(vec[1]< -min[1]) vec[1]= -min[1];
+ if(vec[0]> 1.0-max[0]) vec[0]= 1.0-max[0];
+ if(vec[1]> 1.0-max[1]) vec[1]= 1.0-max[1];
+ }
+ tv= transmain;
+ for(a=0; a<tot; a++, tv++) {
+
+ x= tv->oldloc[0]+vec[0];
+ y= tv->oldloc[1]+vec[1];
+
+ sima_pixelgrid(tv->loc, x, y);
+ }
+ ivec[0]= (vec[0]*xim);
+ ivec[1]= (vec[1]*yim);
+
+ if(G.sima->flag & SI_BE_SQUARE) be_square_tface_uv(me);
+
+ sprintf(str, "X: %.4f Y: %.4f ", ivec[0], ivec[1]);
+ headerprint(str);
+ }
+ else if(mode=='r') {
+
+ dx2= xc-mval[0];
+ dy2= yc-mval[1];
+
+ div= sqrt( (dx1*dx1+dy1*dy1)*(dx2*dx2+dy2*dy2));
+ if(div>1.0) {
+
+ dphi= (dx1*dx2+dy1*dy2)/div;
+ dphi= saacos(dphi);
+ if( (dx1*dy2-dx2*dy1)<0.0 ) dphi= -dphi;
+
+ if(G.qual & LR_SHIFTKEY) phi+= dphi/30.0;
+ else phi+= dphi;
+
+ apply_keyb_grid(&phi, 0.0, (5.0/180)*M_PI, (1.0/180)*M_PI, U.flag & AUTOROTGRID);
+
+ dx1= dx2;
+ dy1= dy2;
+
+ co= cos(phi);
+ si= sin(phi);
+ asp= (float)yim/(float)xim;
+
+
+ tv= transmain;
+ for(a=0; a<tot; a++, tv++) {
+
+ x= ( co*( tv->oldloc[0]-cent[0]) - si*asp*(tv->oldloc[1]-cent[1]) ) +cent[0];
+ y= ( si*( tv->oldloc[0]-cent[0])/asp + co*(tv->oldloc[1]-cent[1]) ) +cent[1];
+ sima_pixelgrid(tv->loc, x, y);
+
+ if(G.sima->flag & SI_CLIP_UV) {
+ if(tv->loc[0]<0.0) tv->loc[0]= 0.0;
+ else if(tv->loc[0]>1.0) tv->loc[0]= 1.0;
+ if(tv->loc[1]<0.0) tv->loc[1]= 0.0;
+ else if(tv->loc[1]>1.0) tv->loc[1]= 1.0;
+ }
+ }
+
+
+ sprintf(str, "Rot: %.3f ", phi*180.0/M_PI);
+ headerprint(str);
+ }
+ }
+ else if(mode=='s') {
+
+ size[0]=size[1]= (sqrt( (float)((yc-mval[1])*(yc-mval[1])+(mval[0]-xc)*(mval[0]-xc)) ))/sizefac;
+
+ if(midtog) size[proj]= 1.0;
+
+ apply_keyb_grid(size, 0.0, 0.1, 0.01, U.flag & AUTOSIZEGRID);
+ apply_keyb_grid(size+1, 0.0, 0.1, 0.01, U.flag & AUTOSIZEGRID);
+
+ size[0]*= xref;
+ size[1]*= yref;
+
+ xtra[0]= xtra[1]= 0;
+
+ if(G.sima->flag & SI_CLIP_UV) {
+ /* boundbox limit: four step plan: XTRA X */
+
+ a=b= 0;
+ if(size[0]*(min[0]-cent[0]) + cent[0] + xtra[0] < 0)
+ a= -size[0]*(min[0]-cent[0]) - cent[0];
+ if(size[0]*(max[0]-cent[0]) + cent[0] + xtra[0] > 1.0)
+ b= 1.0 - size[0]*(max[0]-cent[0]) - cent[0];
+ xtra[0]= (a+b)/2;
+
+ /* SIZE X */
+ if(size[0]*(min[0]-cent[0]) + cent[0] + xtra[0] < 0)
+ size[0]= (-cent[0]-xtra[0])/(min[0]-cent[0]);
+ if(size[0]*(max[0]-cent[0]) + cent[0] +xtra[0] > 1.0)
+ size[0]= (1.0-cent[0]-xtra[0])/(max[0]-cent[0]);
+
+ /* XTRA Y */
+ a=b= 0;
+ if(size[1]*(min[1]-cent[1]) + cent[1] + xtra[1] < 0)
+ a= -size[1]*(min[1]-cent[1]) - cent[1];
+ if(size[1]*(max[1]-cent[1]) + cent[1] + xtra[1] > 1.0)
+ b= 1.0 - size[1]*(max[1]-cent[1]) - cent[1];
+ xtra[1]= (a+b)/2;
+
+ /* SIZE Y */
+ if(size[1]*(min[1]-cent[1]) + cent[1] +xtra[1] < 0)
+ size[1]= (-cent[1]-xtra[1])/(min[1]-cent[1]);
+ if(size[1]*(max[1]-cent[1]) + cent[1] + xtra[1]> 1.0)
+ size[1]= (1.0-cent[1]-xtra[1])/(max[1]-cent[1]);
+ }
+
+ /* if(midtog==0) { */
+ /* if(size[1]>size[0]) size[1]= size[0]; */
+ /* else if(size[0]>size[1]) size[0]= size[1]; */
+ /* } */
+
+ tv= transmain;
+ for(a=0; a<tot; a++, tv++) {
+
+ x= size[0]*(tv->oldloc[0]-cent[0])+ cent[0] + xtra[0];
+ y= size[1]*(tv->oldloc[1]-cent[1])+ cent[1] + xtra[1];
+ sima_pixelgrid(tv->loc, x, y);
+ }
+
+ sprintf(str, "sizeX: %.3f sizeY: %.3f ", size[0], size[1]);
+ headerprint(str);
+
+ }
+
+ xo= mval[0];
+ yo= mval[1];
+
+ if(G.sima->lock) force_draw_plus(SPACE_VIEW3D);
+ else force_draw();
+
+ firsttime= 0;
+
+ }
+ else BIF_wait_for_statechange();
+
+ while(qtest()) {
+ event= extern_qread(&val);
+ if(val) {
+ switch(event) {
+ case ESCKEY:
+ case RIGHTMOUSE:
+ case LEFTMOUSE:
+ case SPACEKEY:
+ case RETKEY:
+ afbreek= 1;
+ break;
+ case MIDDLEMOUSE:
+
+ midtog= ~midtog;
+ if(midtog) {
+ if( abs(mval[0]-xn) > abs(mval[1]-yn)) proj= 1;
+ else proj= 0;
+ firsttime= 1;
+ }
+
+ break;
+ case XKEY:
+ case YKEY:
+ if(event==XKEY) xref= -xref;
+ else yref= -yref;
+
+ firsttime= 1;
+ break;
+ default:
+ arrows_move_cursor(event);
+ }
+ }
+ if(afbreek) break;
+ }
+ }
+
+ if(event==ESCKEY || event == RIGHTMOUSE) {
+ tv= transmain;
+ for(a=0; a<tot; a++, tv++) {
+ tv->loc[0]= tv->oldloc[0];
+ tv->loc[1]= tv->oldloc[1];
+ }
+ }
+ MEM_freeN(transmain);
+
+ if(mode=='g') if(G.sima->flag & SI_BE_SQUARE) be_square_tface_uv(me);
+
+ allqueue(REDRAWVIEW3D, 0);
+ scrarea_queue_headredraw(curarea);
+ scrarea_queue_winredraw(curarea);
+}
+
+void select_swap_tface_uv(void)
+{
+ Mesh *me;
+ TFace *tface;
+ MFace *mface;
+ int a, sel=0;
+
+ if( is_uv_tface_editing_allowed()==0 ) return;
+ me= get_mesh(OBACT);
+
+ for(a=me->totface, tface= me->tface; a>0; a--, tface++) {
+ if(tface->flag & TF_SELECT) {
+ if(tface->flag & (TF_SEL1+TF_SEL2+TF_SEL3+TF_SEL4)) {
+ sel= 1;
+ break;
+ }
+ }
+ }
+
+ mface= me->mface;
+ for(a=me->totface, tface= me->tface; a>0; a--, tface++, mface++) {
+ if(tface->flag & TF_SELECT) {
+ if(mface->v4) {
+ if(sel) tface->flag &= ~(TF_SEL1+TF_SEL2+TF_SEL3+TF_SEL4);
+ else tface->flag |= (TF_SEL1+TF_SEL2+TF_SEL3+TF_SEL4);
+ }
+ else if(mface->v3) {
+ if(sel) tface->flag &= ~(TF_SEL1+TF_SEL2+TF_SEL3+TF_SEL4);
+ else tface->flag |= (TF_SEL1+TF_SEL2+TF_SEL3);
+ }
+ }
+ }
+
+ allqueue(REDRAWIMAGE, 0);
+}
+
+void mouse_select_sima(void)
+{
+ Mesh *me;
+ TFace *tface;
+ MFace *mface;
+ int temp, dist=100;
+ int a;
+ short mval[2], uval[2], val = 0;
+ char *flagpoin =0;
+
+ if( is_uv_tface_editing_allowed()==0 ) return;
+ me= get_mesh(OBACT);
+
+ getmouseco_areawin(mval);
+
+ mface= me->mface;
+ for(a=me->totface, tface= me->tface; a>0; a--, tface++, mface++) {
+
+ if(tface->flag & TF_SELECT) {
+
+ uvco_to_areaco_noclip(tface->uv[0], uval);
+ temp= abs(mval[0]- uval[0])+ abs(mval[1]- uval[1]);
+ if( tface->flag & TF_SEL1) temp+=5;
+ if(temp<dist) {
+ flagpoin= &tface->flag;
+ dist= temp;
+ val= TF_SEL1;
+ }
+
+ uvco_to_areaco_noclip(tface->uv[1], uval);
+ temp= abs(mval[0]- uval[0])+ abs(mval[1]- uval[1]);
+ if( tface->flag & TF_SEL2) temp+=5;
+ if(temp<dist) {
+ flagpoin= &tface->flag;
+ dist= temp;
+ val= TF_SEL2;
+ }
+
+ uvco_to_areaco_noclip(tface->uv[2], uval);
+ temp= abs(mval[0]- uval[0])+ abs(mval[1]- uval[1]);
+ if( tface->flag & TF_SEL3) temp+=5;
+ if(temp<dist) {
+ flagpoin= &tface->flag;
+ dist= temp;
+ val= TF_SEL3;
+ }
+
+ if(mface->v4) {
+ uvco_to_areaco_noclip(tface->uv[3], uval);
+ temp= abs(mval[0]- uval[0])+ abs(mval[1]- uval[1]);
+ if( tface->flag & TF_SEL4) temp+=5;
+ if(temp<dist) {
+ flagpoin= &tface->flag;
+ dist= temp;
+ val= TF_SEL4;
+ }
+ }
+
+ }
+ }
+
+ if(flagpoin) {
+ if(G.qual & LR_SHIFTKEY) {
+ if(*flagpoin & val) *flagpoin &= ~val;
+ else *flagpoin |= val;
+ }
+ else {
+ for(a=me->totface, tface= me->tface; a>0; a--, tface++) {
+ if(tface->flag & TF_SELECT) {
+ tface->flag &= ~(TF_SEL1+TF_SEL2+TF_SEL3+TF_SEL4);
+ }
+ }
+
+ *flagpoin |= val;
+ }
+
+
+ glDrawBuffer(GL_FRONT);
+ draw_tfaces();
+ glDrawBuffer(GL_BACK);
+
+ std_rmouse_transform(transform_tface_uv);
+ }
+}
+
+void borderselect_sima(void)
+{
+ Mesh *me;
+ TFace *tface;
+ MFace *mface;
+ rcti rect;
+ rctf rectf;
+ int a, val;
+ short mval[2];
+
+ if( is_uv_tface_editing_allowed()==0 ) return;
+ me= get_mesh(OBACT);
+
+ val= get_border(&rect, 3);
+
+ if(val) {
+ mval[0]= rect.xmin;
+ mval[1]= rect.ymin;
+ areamouseco_to_ipoco(G.v2d, mval, &rectf.xmin, &rectf.ymin);
+ mval[0]= rect.xmax;
+ mval[1]= rect.ymax;
+ areamouseco_to_ipoco(G.v2d, mval, &rectf.xmax, &rectf.ymax);
+
+ mface= me->mface;
+ for(a=me->totface, tface= me->tface; a>0; a--, tface++, mface++) {
+
+ if(tface->flag & TF_SELECT) {
+
+ if(BLI_in_rctf(&rectf, (float)tface->uv[0][0], (float)tface->uv[0][1])) {
+ if(val==LEFTMOUSE) tface->flag |= TF_SEL1;
+ else tface->flag &= ~TF_SEL1;
+ }
+ if(BLI_in_rctf(&rectf, (float)tface->uv[1][0], (float)tface->uv[1][1])) {
+ if(val==LEFTMOUSE) tface->flag |= TF_SEL2;
+ else tface->flag &= ~TF_SEL2;
+ }
+ if(BLI_in_rctf(&rectf, (float)tface->uv[2][0], (float)tface->uv[2][1])) {
+ if(val==LEFTMOUSE) tface->flag |= TF_SEL3;
+ else tface->flag &= ~TF_SEL3;
+ }
+ if(mface->v4 && BLI_in_rctf(&rectf, (float)tface->uv[3][0], (float)tface->uv[3][1])) {
+ if(val==LEFTMOUSE) tface->flag |= TF_SEL4;
+ else tface->flag &= ~TF_SEL4;
+ }
+ }
+
+ }
+ scrarea_queue_winredraw(curarea);
+ }
+}
+
+/** This is an ugly function to set the Tface selection flags depending
+ * on whether its UV coordinates are inside the normalized
+ * area with radius rad and offset offset. These coordinates must be
+ * normalized to 1.0
+ * Just for readability...
+ */
+
+void sel_uvco_inside_radius(short sel, TFace *tface, int index, float *offset, float *ell, short select_mask)
+{
+ // normalized ellipse: ell[0] = scaleX,
+ // [1] = scaleY
+
+ float *uv = tface->uv[index];
+ float x, y, r2;
+
+ x = (uv[0] - offset[0]) * ell[0];
+ y = (uv[1] - offset[1]) * ell[1];
+
+ r2 = x * x + y * y;
+ if (r2 < 1.0) {
+ if (sel == LEFTMOUSE) tface->flag |= select_mask;
+ else tface->flag &= ~select_mask;
+ }
+}
+
+// see below:
+/** gets image dimensions of the 2D view 'v' */
+static void getSpaceImageDimension(SpaceImage *sima, float *xy)
+{
+ Image *img = sima->image;
+ float z;
+
+ z = sima->zoom;
+
+ if (img) {
+ xy[0] = img->ibuf->x * z;
+ xy[1] = img->ibuf->y * z;
+ } else {
+ xy[0] = 256 * z;
+ xy[1] = 256 * z;
+ }
+}
+
+/** Callback function called by circle_selectCB to enable
+ * brush select in UV editor.
+ */
+
+void uvedit_selectionCB(short selecting, Object *editobj, short *mval, float rad)
+{
+ float offset[2];
+ Mesh *me;
+ MFace *mface;
+ TFace *tface;
+ int i;
+
+ float ellipse[2]; // we need to deal with ellipses, as
+ // non square textures require for circle
+ // selection. this ellipse is normalized; r = 1.0
+
+ me = get_mesh(editobj);
+
+ getSpaceImageDimension(curarea->spacedata.first, ellipse);
+ ellipse[0] /= rad;
+ ellipse[1] /= rad;
+
+ areamouseco_to_ipoco(G.v2d, mval, &offset[0], &offset[1]);
+
+ mface= me->mface;
+ tface= me->tface;
+
+ if (selecting) {
+ for(i = 0; i < me->totface; i++) {
+ sel_uvco_inside_radius(selecting, tface, 0, offset, ellipse, TF_SEL1);
+ sel_uvco_inside_radius(selecting, tface, 1, offset, ellipse, TF_SEL2);
+ sel_uvco_inside_radius(selecting, tface, 2, offset, ellipse, TF_SEL3);
+ if (mface->v4)
+ sel_uvco_inside_radius(selecting, tface, 3, offset, ellipse, TF_SEL4);
+
+ tface++; mface++;
+
+ }
+ // force_draw() is no good here...
+ glDrawBuffer(GL_FRONT);
+ draw_tfaces();
+ glDrawBuffer(GL_BACK);
+ }
+}
+
+
+void mouseco_to_curtile(void)
+{
+ float fx, fy;
+ short mval[2];
+
+ if( is_uv_tface_editing_allowed()==0) return;
+
+ if(G.sima->image && G.sima->image->tpageflag & IMA_TILES) {
+
+ G.sima->flag |= SI_EDITTILE;
+
+ while(get_mbut()&L_MOUSE) {
+
+ calc_image_view(G.sima, 'f');
+
+ getmouseco_areawin(mval);
+ areamouseco_to_ipoco(G.v2d, mval, &fx, &fy);
+
+ if(fx>=0.0 && fy>=0.0 && fx<1.0 && fy<1.0) {
+
+ fx= (fx)*G.sima->image->xrep;
+ fy= (fy)*G.sima->image->yrep;
+
+ mval[0]= fx;
+ mval[1]= fy;
+
+ G.sima->curtile= mval[1]*G.sima->image->xrep + mval[0];
+ }
+
+ scrarea_do_windraw(curarea);
+ screen_swapbuffers();
+
+ }
+
+ G.sima->flag &= ~SI_EDITTILE;
+
+ image_changed(G.sima, 1);
+
+ allqueue(REDRAWVIEW3D, 0);
+ scrarea_queue_winredraw(curarea);
+ }
+}
diff --git a/source/blender/src/editsound.c b/source/blender/src/editsound.c
new file mode 100644
index 00000000000..53a3628aa48
--- /dev/null
+++ b/source/blender/src/editsound.c
@@ -0,0 +1,1017 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 <math.h>
+#include <string.h>
+#include <fcntl.h>
+#ifndef WIN32
+#include <unistd.h>
+#else
+#include <io.h>
+#endif
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "DNA_object_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_sound_types.h"
+#include "DNA_packedFile_types.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_sound.h"
+#include "BKE_library.h"
+#include "BKE_packedFile.h"
+
+#include "BIF_space.h"
+#include "BIF_screen.h"
+#include "BIF_interface.h"
+#include "BIF_editsound.h"
+#include "BIF_mywindow.h"
+
+#include "BSE_drawipo.h"
+#include "BSE_headerbuttons.h"
+
+#include "blendef.h"
+
+#include "interface.h"
+#include "mydevice.h"
+
+#include "SND_C-api.h"
+#include "SND_DependKludge.h"
+
+#include "SYS_System.h"
+
+#include "license_key.h"
+
+extern int LICENSE_KEY_VALID;
+
+/* this might move to the external header */
+void* sound_get_libraryinterface(void);
+
+static SND_SceneHandle ghSoundScene;
+static SND_AudioDeviceInterfaceHandle ghAudioDeviceInterface;
+
+/* que? why only here? because of the type define? */
+bSound *sound_find_sound(char *id_name);
+void sound_read_wav_data(bSound * sound, PackedFile * pf);
+void sound_stop_sound(void *object, bSound *sound);
+void winqreadsoundspace(unsigned short event, short val, char ascii);
+/* void sound_stop_all_sounds(void); already in BIF_editsound.h */
+
+
+
+/* Right. Now for some implementation: */
+void winqreadsoundspace(unsigned short event, short val, char ascii)
+{
+ float dx, dy;
+ int doredraw= 0, cfra, first = 0;
+ short mval[2];
+
+ if(curarea->win==0) return;
+
+ if(val) {
+
+ if( uiDoBlocks(&curarea->uiblocks, event)!=UI_NOTHING ) event= 0;
+
+ switch(event)
+ {
+ case LEFTMOUSE:
+ if( view2dmove()==0 )
+ {
+ do
+ {
+ getmouseco_areawin(mval);
+ areamouseco_to_ipoco(G.v2d, mval, &dx, &dy);
+
+ cfra = (int)dx;
+ if(cfra< 1) cfra= 1;
+
+ if( cfra!=CFRA || first )
+ {
+ first= 0;
+ CFRA= cfra;
+ update_for_newframe();
+ force_draw_plus(SPACE_VIEW3D);
+ }
+
+ } while(get_mbut()&L_MOUSE);
+
+ }
+ break;
+ case MIDDLEMOUSE:
+ view2dmove(); /* in drawipo.c */
+ break;
+ case RIGHTMOUSE:
+ /* mouse_select_seq(); */
+ break;
+ case PADPLUSKEY:
+ dx= (float)(0.1154*(G.v2d->cur.xmax-G.v2d->cur.xmin));
+ G.v2d->cur.xmin+= dx;
+ G.v2d->cur.xmax-= dx;
+ test_view2d(G.v2d, curarea->winx, curarea->winy);
+
+ doredraw= 1;
+ break;
+ case PADMINUS:
+ dx= (float)(0.15*(G.v2d->cur.xmax-G.v2d->cur.xmin));
+ G.v2d->cur.xmin-= dx;
+ G.v2d->cur.xmax+= dx;
+ test_view2d(G.v2d, curarea->winx, curarea->winy);
+
+ doredraw= 1;
+ break;
+ case HOMEKEY:
+ do_sound_buttons(B_SOUNDHOME);
+ break;
+ }
+ }
+
+ if(doredraw)
+ scrarea_queue_winredraw(curarea);
+}
+
+
+
+void sound_initialize_sounds(void)
+{
+ bSound* sound;
+
+ /* clear the soundscene */
+ SND_RemoveAllSounds(ghSoundScene);
+ SND_RemoveAllSamples(ghSoundScene);
+
+ /* initialize sounds */
+ sound = G.main->sound.first;
+ while (sound)
+ {
+ sound_sample_is_null(sound);
+ sound = (bSound *) sound->id.next;
+ }
+}
+
+
+
+bSound* sound_make_copy(bSound* originalsound)
+{
+ bSound* sound = NULL;
+ char name[160];
+ int len;
+
+ /* only copy sounds that are sounds */
+ if (originalsound)
+ {
+ /* do some name magic */
+ strcpy(name, originalsound->name);
+ len = strlen(name);
+ while ((len > 0) && (name[len - 1] != '/') && (name[len - 1] != '\\'))
+ len--;
+
+ /* allocate the needed memory */
+ sound = alloc_libblock(&G.main->sound, ID_SO, name + len);
+
+ /* create a soundobject */
+ sound->snd_sound = SND_CreateSound();
+
+ /* set the samplename */
+ strcpy(sound->name, name);
+ SND_SetSampleName(sound->snd_sound, sound->name);
+
+ /* add the new object to the soundscene */
+ SND_AddSound(ghSoundScene, sound->snd_sound);
+
+ /* and copy the data from the original */
+ sound->attenuation = originalsound->attenuation;
+ sound->distance = originalsound->distance;
+ sound->max_gain = originalsound->max_gain;
+ sound->min_gain = originalsound->min_gain;
+ sound->newpackedfile = originalsound->newpackedfile;
+ sound->panning = originalsound->panning;
+ sound->pitch = originalsound->pitch;
+ sound->sample = originalsound->sample;
+ sound->volume = originalsound->volume;
+
+ if (originalsound->flags & SOUND_FLAGS_3D)
+ sound->flags |= SOUND_FLAGS_3D;
+ else
+ sound->flags &= ~SOUND_FLAGS_3D;
+ }
+
+ return sound;
+}
+
+
+
+void sound_initialize_sample(bSound* sound)
+{
+ if (sound && sound->sample == NULL)
+ sound_sample_is_null(sound);
+}
+
+
+
+void sound_read_wav_data(bSound* sound, PackedFile* pf)
+{
+ int i, temp;
+ short shortbuf, *temps;
+ int longbuf;
+ char buffer[25];
+ char *data = NULL;
+ char *tempc;
+ bSample *sample = NULL;
+ int channels, rate, bits, len;
+
+ /* prepare for the worst... */
+ sound->sample->type = SAMPLE_INVALID;
+
+ rewindPackedFile(pf);
+
+ /* check to see if it is a file in "RIFF WAVE fmt" format */
+ if (readPackedFile(pf, buffer, 16) != 16)
+ {
+ if (G.f & G_DEBUG) printf("File too short\n");
+ return;
+ }
+
+ if(!(memcmp(buffer, "RIFF", 4) && memcmp(&(buffer[8]), "WAVEfmt ", 8)))
+ {
+ readPackedFile(pf, &i, 4);// start of data
+ if(G.order==B_ENDIAN)
+ SWITCH_INT(i);
+
+ /* read the sampleformat */
+ readPackedFile(pf, &shortbuf, 2);
+ if(G.order==B_ENDIAN)
+ {
+ /* was SWITCH_SHORT before */
+ char s_i, *p_i;
+ p_i= (char *)&(shortbuf);
+ s_i= p_i[0];
+ p_i[0]= p_i[1];
+ p_i[1]= s_i;
+ }
+
+ /* read the number of channels */
+ readPackedFile(pf, &shortbuf, 2);
+ if(G.order==B_ENDIAN)
+ {
+ /* was SWITCH_SHORT before */
+ char s_i, *p_i;
+ p_i= (char *)&(shortbuf);
+ s_i= p_i[0];
+ p_i[0]= p_i[1];
+ p_i[1]= s_i;
+ }
+
+ /* check the number of channels */
+ if(shortbuf != 1 && shortbuf != 2)
+ {
+ if (G.f & G_DEBUG) printf("Unsupported number of channels\n");
+ return;
+ }
+ channels = shortbuf;
+
+ /* read the samplerate */
+ readPackedFile(pf, &longbuf, 4);
+ if(G.order==B_ENDIAN)
+ SWITCH_INT(longbuf);
+ rate = longbuf;
+
+ /* read the bitrate */
+ // Ton's way
+ readPackedFile(pf, &temp, 4);
+ if(G.order==B_ENDIAN)
+ SWITCH_INT(temp);
+
+ if(channels && rate)
+ bits= 8*temp/(rate * channels);
+
+ // Frank's way
+ readPackedFile(pf, &shortbuf, 2);
+ readPackedFile(pf, &shortbuf, 2);
+ if(G.order==B_ENDIAN)
+ {
+ /* was SWITCH_SHORT before */
+ char s_i, *p_i;
+ p_i= (char *)&(shortbuf);
+ s_i= p_i[0];
+ p_i[0]= p_i[1];
+ p_i[1]= s_i;
+ }
+ bits = shortbuf;
+
+ seekPackedFile(pf, i-16, SEEK_CUR);
+ readPackedFile(pf, buffer, 4);
+
+ /* check if we have a 'data' chunk */
+ while(memcmp(buffer, "data", 4)!=0)
+ {
+ if (readPackedFile(pf, &i, 4) != 4)
+ break;
+
+ if(G.order==B_ENDIAN)
+ SWITCH_INT(i);
+
+ seekPackedFile(pf, i, SEEK_CUR);
+
+ if (readPackedFile(pf, buffer, 4) != 4)
+ break;
+ }
+
+ /* guess not */
+ if (memcmp(buffer, "data", 4) !=0)
+ {
+ if (G.f & G_DEBUG) printf("No data found\n");
+ }
+ /* or maybe we do! */
+ else
+ {
+ readPackedFile(pf, &longbuf, 4);
+ if(G.order==B_ENDIAN) SWITCH_INT(longbuf);
+
+ /* handle 8 and 16 bit samples differently */
+ if (bits == 8)
+ data = (char *)MEM_mallocN(2 * longbuf, "sample data");
+ else if (bits == 16)
+ data = (char *)MEM_mallocN(longbuf, "sample data");
+
+ len = longbuf;
+
+ if(data)
+ {
+ readPackedFile(pf, data, len);
+
+ /* data is only used to draw! */
+ if (bits == 8)
+ {
+ temps = (short *) data;
+ tempc = (char *) data;
+ for (i = len - 1; i >= 0; i--)
+ temps[i] = tempc[i] << 8;
+ }
+ else
+ {
+ if(G.order==B_ENDIAN)
+ {
+ temps= (short *)data;
+ for(i=0; i< len / 2; i++, temps++)
+ {
+ /* was SWITCH_SHORT before */
+ char s_i, *p_i;
+ p_i= (char *)&(temps);
+ s_i= p_i[0];
+ p_i[0]= p_i[1];
+ p_i[1]= s_i;
+ }
+ }
+ }
+
+ /* fill the sound with the found data */
+ sample = sound->sample;
+ sample->channels = channels;
+ sample->rate = rate;
+ sample->bits = bits;
+ sample->len = len;
+ sample->data = data;
+ sample->type = SAMPLE_WAV;
+ }
+ }
+ }
+ else
+ {
+ sound->sample->type = SAMPLE_INVALID;
+ if (G.f & G_DEBUG) printf("Unsupported sound format: %s\n", sound->name);
+ }
+}
+
+
+
+/* ugly, but it works (for now) */
+int sound_get_filetype_from_header(bSound* sound, PackedFile* pf)
+{
+ int i, filetype = SAMPLE_INVALID;
+ char buffer[25];
+ short shortbuf;
+
+ rewindPackedFile(pf);
+
+ if (readPackedFile(pf, buffer, 16) != 16)
+ {
+ if (G.f & G_DEBUG) printf("File too short\n");
+ return filetype;
+ }
+
+ if(!(memcmp(buffer, "RIFF", 4) && memcmp(&(buffer[8]), "WAVEfmt ", 8)))
+ {
+ readPackedFile(pf, &i, 4);
+ if(G.order==B_ENDIAN)
+ SWITCH_INT(i);
+
+ /* read the sampleformat */
+ readPackedFile(pf, &shortbuf, 2);
+ if(G.order==B_ENDIAN)
+ {
+ char s_i, *p_i;
+ p_i= (char *)&(shortbuf);
+ s_i= p_i[0];
+ p_i[0]= p_i[1];
+ p_i[1]= s_i;
+ }
+
+ if (shortbuf == SND_WAVE_FORMAT_PCM)
+ {
+ filetype = SAMPLE_WAV;
+ }
+ else
+ /* 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:
+ filetype = SAMPLE_WAV;
+ break;
+ default:
+#endif
+ {
+ filetype = SAMPLE_INVALID;
+ if (G.f & G_DEBUG) printf("Unsupported wav compression\n");
+ }
+ }
+#ifdef USE_FMOD
+ }
+ }
+ }
+ /* only valid publishers may use ogg vorbis */
+ else if (!memcmp(buffer, "OggS", 4) && LICENSE_KEY_VALID)
+ {
+ filetype = SAMPLE_OGG_VORBIS;
+ }
+ /* only valid publishers may use mp3 */
+ else if (((!memcmp(buffer, "ID3", 3)) || (!memcmp(buffer, "ÿû", 2))) && LICENSE_KEY_VALID)
+ {
+ filetype = SAMPLE_MP3;
+ }
+#endif
+ else
+ {
+ filetype = SAMPLE_INVALID;
+ if (G.f & G_DEBUG) printf("Unsupported sound format: %s\n", sound->name);
+ }
+
+ return filetype;
+}
+
+
+
+int check_filetype(bSound* sound, PackedFile* pf)
+{
+// char* pdest;
+ sound->sample->type = SAMPLE_INVALID;
+/*
+ // parse the name for the extension to see what kind of sample it is
+ pdest = strrchr(sound->sample->name, '.');
+
+ // a simple check to see what kind of sample we're dealing with
+ if (stricmp(pdest, ".wav") == 0)
+ sound->sample->type = SAMPLE_WAV;
+
+#ifdef USE_FMOD
+ if (stricmp(pdest, ".mp2") == 0)
+ sound->sample->type = SAMPLE_MP2;
+ if (stricmp(pdest, ".mp3") == 0)
+ sound->sample->type = SAMPLE_MP3;
+ if (stricmp(pdest, ".ogg") == 0)
+ sound->sample->type = SAMPLE_OGG_VORBIS;
+ if (stricmp(pdest, ".raw") == 0)
+ sound->sample->type = SAMPLE_RAW;
+ if (stricmp(pdest, ".wma") == 0)
+ sound->sample->type = SAMPLE_WMA;
+ if (stricmp(pdest, ".asf") == 0)
+ sound->sample->type = SAMPLE_ASF;
+#endif
+*/
+ sound->sample->type = sound_get_filetype_from_header(sound, pf);
+
+ /* get some info from the sample */
+ switch (sound->sample->type)
+ {
+ case SAMPLE_WAV:
+ {
+ sound_read_wav_data(sound, pf);
+ break;
+ }
+ case SAMPLE_OGG_VORBIS:
+ case SAMPLE_MP3:
+ case SAMPLE_MP2:
+ case SAMPLE_RAW:
+ case SAMPLE_WMA:
+ case SAMPLE_ASF:
+ break;
+ default:
+ {
+ if (G.f & G_DEBUG) printf("No valid sample: %s\n", sound->name);
+ break;
+ }
+ }
+
+ return sound->sample->type;
+}
+
+
+
+int sound_load_sample(bSound* sound)
+{
+ int result = FALSE;
+ PackedFile* pf;
+ int freePF = FALSE;
+ int buffer = -1;
+
+ /* check the sample (valid?) */
+ if (sound->sample->type == SAMPLE_UNKNOWN || sound->snd_sound == NULL)
+ {
+ /* find... */
+ pf = sound_find_packedfile(sound);
+
+ /* ...or create a (temp)packedfile */
+ if (pf == NULL)
+ {
+ pf = newPackedFile(sound->name);
+
+ /* if autopack is off, free the pf afterwards */
+ if ((G.fileflags & G_AUTOPACK) == 0)
+ freePF = TRUE;
+ }
+
+ /* if we have a valid pf... */
+ if (pf)
+ {
+ /* check the content of the pf */
+ check_filetype(sound, pf);
+
+ /* check if the sampletype is supported */
+ if (sound->sample->type != SAMPLE_INVALID && sound->sample->type != SAMPLE_UNKNOWN)
+ {
+ /* register the sample at the audiodevice */
+ buffer = SND_AddSample(ghSoundScene, sound->sample->name, pf->data, pf->size);
+
+ /* create a soundobject */
+ sound->snd_sound = SND_CreateSound();
+ SND_SetSampleName(sound->snd_sound, sound->sample->name);
+
+ /* add the soundobject to the soundscene */
+ if (SND_CheckBuffer(ghSoundScene, sound->snd_sound))
+ SND_AddSound(ghSoundScene, sound->snd_sound);
+ else
+ if (G.f & G_DEBUG) printf("error: sample didn't load properly\n");
+
+ /* if it was places in buffer[0] or higher, it succeeded */
+ if (buffer >= 0)
+ result = TRUE;
+ }
+ /* if not, free the pf */
+ else
+ {
+ freePF = TRUE;
+ }
+
+ /* if you want it freed, make it so */
+ if (freePF)
+ {
+ freePackedFile(pf);
+ pf = NULL;
+ }
+ /* or else connect the pf to the sound and sample */
+// else
+// {
+ sound->newpackedfile = pf;
+ sound->sample->packedfile = pf;
+// }
+ }
+ else
+ {
+ if (G.f & G_DEBUG) printf("%s: File not found!\n", sound->name);
+ sound->sample->type = SAMPLE_INVALID;
+ }
+ }
+ /* if the sample ain't invalid, we're ready to go! */
+ else if (sound->sample->type != SAMPLE_INVALID)
+ {
+ result = TRUE;
+ }
+
+ return result;
+}
+
+
+
+bSound* sound_new_sound(char* name)
+{
+ bSound *sound = NULL;
+ int len, file;
+ char str[FILE_MAXDIR+FILE_MAXFILE];
+
+ /* convert the name to absolute path */
+ strcpy(str, name);
+ BLI_convertstringcode(str, G.sce, G.scene->r.cfra);
+
+ /* check if the sample on disk can be opened */
+ file = open(str, O_BINARY|O_RDONLY);
+
+ if (file != -1)
+ {
+ close(file);
+
+ /* do some name magic */
+ len = strlen(name);
+ while (len > 0 && name[len - 1] != '/' && name[len - 1] != '\\')
+ len--;
+
+ /* allocate some memory for the sound */
+ sound = alloc_libblock(&G.main->sound, ID_SO, name + len);
+ strcpy(sound->name, name);
+
+ /* intialize and check the sample */
+ sound_initialize_sample(sound);
+
+ /* load the sample & check if this blender supports the sound format */
+// sound_load_sample(sound);
+
+ if (sound->sample->type == SAMPLE_INVALID)
+ {
+ free_libblock(&G.main->sound, sound);
+ sound = NULL;
+ }
+ else
+ {
+ sound->volume = 1.0;
+ sound->attenuation = 1.0;
+ sound->distance = 1.0;
+ sound->min_gain = 0.0;
+ sound->max_gain = 1.0;
+ }
+ }
+
+ return (sound);
+}
+
+
+
+int sound_set_sample(bSound *sound, bSample *sample)
+{
+ int result = TRUE;
+
+ /* decrease the usernumber for this sample */
+ if (sound->sample)
+ sound->sample->id.us--;
+
+ /* delete the soundobject */
+ if (sound->snd_sound)
+ {
+ SND_RemoveSound(ghSoundScene, sound->snd_sound);
+ sound->snd_sound = NULL;
+ }
+
+ /* connect the sample to the sound */
+ sound->sample = sample;
+ sound->newpackedfile = NULL;
+
+ /* increase the usercount */
+ if (sound->sample)
+ {
+ sound->sample->id.us++;
+
+ /* and set the right pf */
+ sound->newpackedfile = sample->packedfile;
+
+ /* if the sampletype is unknown initialize it */
+ if (sound->sample->type == SAMPLE_UNKNOWN)
+ {
+ sound_initialize_sample(sound);
+
+ /* load the sample & check if this blender supports the sound format */
+ if (!sound_load_sample(sound))
+ {
+ result = FALSE;
+ }
+ }
+ }
+ return result;
+}
+
+
+
+bSample *sound_new_sample(bSound * sound)
+{
+ bSample *sample = NULL;
+ int len;
+ char *name;
+
+ if (sound != NULL)
+ {
+ name = sound->name;
+ len = strlen(name);
+ /* do some name magic */
+ while (len > 0 && name[len - 1] != '/' && name[len - 1] != '\\')
+ len--;
+
+ /* allocate the memory for the sample */
+ sample = alloc_libblock(samples, ID_SAMPLE, name + len);
+ sample->data = &sample->fakedata[0];
+ sample->type = SAMPLE_UNKNOWN;
+
+ /* some default settings. We get divide by zero if these values are not set */
+ sample->channels = 1;
+ sample->rate = 44100;
+ sample->bits = 16;
+ sample->alindex = SAMPLE_INVALID;
+
+ /* convert sound->name to abolute filename */
+ strcpy(sample->name, sound->name);
+ BLI_convertstringcode(sample->name, G.sce, G.scene->r.cfra);
+
+ /* connect the pf to the sample */
+ if (sound->newpackedfile)
+ sample->packedfile = sound->newpackedfile;
+ else
+ sample->packedfile = sound_find_packedfile(sound);
+ }
+
+ return(sample);
+}
+
+
+
+/* find a sample that might already be loaded */
+bSample* sound_find_sample(bSound* sound)
+{
+ bSample* sample;
+ char name[FILE_MAXDIR + FILE_MAXFILE];
+ char samplename[FILE_MAXDIR + FILE_MAXFILE];
+
+ // convert sound->name to abolute filename
+ strcpy(name, sound->name);
+ BLI_convertstringcode(name, G.sce, G.scene->r.cfra);
+
+ /* search through the list of loaded samples */
+ sample = samples->first;
+
+ while (sample)
+ {
+ strcpy(samplename, sample->name);
+ BLI_convertstringcode(samplename, G.sce, G.scene->r.cfra);
+
+ if (strcmp(name, samplename) == 0)
+ {
+ break;
+ }
+ sample = sample->id.next;
+ }
+
+ return (sample);
+}
+
+
+
+int sound_sample_is_null(bSound* sound)
+{
+ int result = FALSE;
+ bSample* sample;
+
+ /* find the right sample or else create one */
+ if (sound->sample == NULL)
+ {
+ /* find... */
+ sample = sound_find_sample(sound);
+
+ /* or a new one? */
+ if (sample == NULL)
+ sample = sound_new_sample(sound);
+
+ if (sound_set_sample(sound, sample))
+ result = TRUE;
+ }
+
+ return result;
+}
+
+
+
+void sound_stop_all_sounds(void)
+{
+ SND_StopAllSounds(ghSoundScene);
+ SND_Proceed(ghAudioDeviceInterface, ghSoundScene);
+}
+
+
+
+void sound_end_all_sounds(void)
+{
+ sound_stop_all_sounds();
+ SND_RemoveAllSounds(ghSoundScene);
+}
+
+
+
+void sound_play_sound(bSound* sound)
+{
+ /* first check if we want sound or not */
+ SND_IsPlaybackWanted(ghSoundScene);
+
+ /* stop all previous sounds */
+ SND_StopAllSounds(ghSoundScene);
+
+ if (sound != NULL && sound->sample != NULL)
+ {
+ /* load the sample if needed */
+ if (sound_load_sample(sound))
+ {
+ /* set all kinds of parameters */
+ SND_SetListenerGain(ghSoundScene, G.listener->gain);
+ SND_SetDopplerFactor(ghSoundScene, G.listener->dopplerfactor);
+ SND_SetDopplerVelocity(ghSoundScene, G.listener->dopplervelocity);
+
+ SND_SetGain((SND_ObjectHandle)sound->snd_sound, (sound->volume));
+ SND_SetPitch((SND_ObjectHandle)sound->snd_sound, (exp((sound->pitch / 12.0) * log(2.0))));
+
+ if (sound->flags & SOUND_FLAGS_LOOP)
+ {
+ SND_SetLoopMode((SND_ObjectHandle)sound->snd_sound, SND_LOOP_NORMAL);
+#ifdef SOUND_UNDER_DEVELOPMENT
+/* SND_SetLoopPoints((SND_ObjectHandle)sound->snd_sound, sound->loopstart, sound->loopend);
+*/
+#endif
+ if (sound->flags & SOUND_FLAGS_BIDIRECTIONAL_LOOP)
+ SND_SetLoopMode((SND_ObjectHandle)sound->snd_sound, SND_LOOP_BIDIRECTIONAL);
+ else
+ SND_SetLoopMode((SND_ObjectHandle)sound->snd_sound, SND_LOOP_NORMAL);
+
+ }
+ else
+ {
+ SND_SetLoopMode((SND_ObjectHandle)sound->snd_sound, SND_LOOP_OFF);
+ }
+
+ if (sound->flags & SOUND_FLAGS_3D)
+ {
+ SND_SetRollOffFactor((SND_ObjectHandle)sound->snd_sound, sound->attenuation);
+ SND_SetReferenceDistance((SND_ObjectHandle)sound->snd_sound, sound->distance);
+ SND_SetMinimumGain((SND_ObjectHandle)sound->snd_sound, sound->min_gain);
+ SND_SetMaximumGain((SND_ObjectHandle)sound->snd_sound, sound->max_gain);
+ }
+ else
+ {
+ SND_SetRollOffFactor((SND_ObjectHandle)sound->snd_sound, 0);
+ SND_SetReferenceDistance((SND_ObjectHandle)sound->snd_sound, 1);
+ SND_SetMinimumGain((SND_ObjectHandle)sound->snd_sound, 1);
+ SND_SetMaximumGain((SND_ObjectHandle)sound->snd_sound, 1);
+ }
+
+ if (G.f & G_DEBUG) printf("Set pitch to: %f\n", SND_GetPitch((SND_ObjectHandle)sound->snd_sound));
+ if (G.f & G_DEBUG) printf("Set gain to: %f\n", SND_GetGain((SND_ObjectHandle)sound->snd_sound));
+ if (G.f & G_DEBUG) printf("Set looping to: %d\n", SND_GetLoopMode((SND_ObjectHandle)sound->snd_sound));
+
+ /* play the sound */
+ SND_StartSound(ghSoundScene, (SND_ObjectHandle)sound->snd_sound);
+
+ /* update the device */
+ SND_Proceed(ghAudioDeviceInterface, ghSoundScene);
+ }
+ }
+ else
+ {
+ if (G.f & G_DEBUG)
+ {
+ printf("uninitialized sound !\n");
+ if (sound)
+ {
+ printf("sound: %p\n", sound);
+ if (sound->sample)
+ {
+ printf("sample: %p\n", sound->sample);
+ if (sound->snd_sound)
+ printf("hSoundObject: %p\n", sound->snd_sound);
+ }
+ }
+ else
+ {
+ printf("sound == NULL\n");
+ }
+ }
+ }
+}
+
+
+
+bSound *sound_find_sound(char *id_name)
+{
+ bSound *sound;
+
+ // look for sound with same *id* name
+ sound = G.main->sound.first;
+ while (sound)
+ {
+ if (strcmp(sound->id.name + 2, id_name) == 0)
+ break;
+
+ sound = sound->id.next;
+ }
+
+ return sound;
+}
+
+
+
+static void sound_init_listener(void)
+{
+ G.listener = MEM_callocN(sizeof(bSoundListener), "soundlistener");
+ G.listener->gain = 1.0;
+ G.listener->dopplerfactor = 1.0;
+ G.listener->dopplervelocity = 1.0;
+}
+
+
+
+void sound_init_audio(void)
+{
+ int noaudio;
+ SYS_SystemHandle hSystem = NULL;
+ ghAudioDeviceInterface = NULL;
+
+ hSystem = SYS_GetSystem();
+ noaudio = SYS_GetCommandLineInt(hSystem,"noaudio",0);
+
+ if (noaudio)
+ SND_SetDeviceType(snd_e_dummydevice);
+
+ ghAudioDeviceInterface = SND_GetAudioDevice();
+ ghSoundScene = SND_CreateScene(ghAudioDeviceInterface);
+
+ sound_init_listener();
+}
+
+
+
+int sound_get_mixrate(void)
+{
+ return MIXRATE;
+}
+
+
+
+static void sound_exit_listener(void)
+{
+ MEM_freeN(G.listener);
+}
+
+
+
+void sound_exit_audio(void)
+{
+ SND_DeleteScene(ghSoundScene);
+ SND_ReleaseDevice();
+ sound_exit_listener();
+}
diff --git a/source/blender/src/editview.c b/source/blender/src/editview.c
new file mode 100644
index 00000000000..1ca7672f4d9
--- /dev/null
+++ b/source/blender/src/editview.c
@@ -0,0 +1,1328 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * cursor/gestures/selecteren
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+
+#include "IMB_imbuf.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_meta_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_lattice_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_view3d_types.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_global.h"
+#include "BKE_armature.h"
+#include "BKE_lattice.h"
+
+#include "BIF_gl.h"
+#include "BIF_mywindow.h"
+#include "BIF_space.h"
+#include "BIF_screen.h"
+#include "BIF_buttons.h"
+#include "BIF_editgroup.h"
+#include "BIF_editmesh.h"
+#include "BIF_editoops.h"
+#include "BIF_editsima.h"
+#include "BIF_editview.h"
+#include "BIF_glutil.h"
+#include "BIF_editarmature.h"
+
+#include "BDR_editobject.h" /* For headerprint */
+#include "BDR_vpaint.h"
+#include "BDR_editface.h"
+#include "BDR_drawobject.h"
+#include "BDR_editcurve.h"
+
+#include "BSE_edit.h"
+#include "BSE_view.h" /* give_cursor() */
+#include "BSE_editipo.h"
+#include "BSE_drawview.h"
+#include "BSE_editaction.h"
+
+#include "blendertimer.h"
+
+#include "blendef.h"
+#include "mydevice.h"
+
+extern ListBase editNurb; /* originally from exports.h, memory from editcurve.c*/
+/* editmball.c */
+extern ListBase editelems;
+
+
+
+void arrows_move_cursor(unsigned short event)
+{
+ short mval[2];
+
+ getmouseco_sc(mval);
+
+ if(event==UPARROWKEY) {
+ warp_pointer(mval[0], mval[1]+1);
+ } else if(event==DOWNARROWKEY) {
+ warp_pointer(mval[0], mval[1]-1);
+ } else if(event==LEFTARROWKEY) {
+ warp_pointer(mval[0]-1, mval[1]);
+ } else if(event==RIGHTARROWKEY) {
+ warp_pointer(mval[0]+1, mval[1]);
+ }
+}
+
+#define MOVES 50
+
+
+static char interpret_move(short mcord[][2], int count)
+{
+ float x1, x2, y1, y2, d1, d2, inp, sq, mouse[MOVES][2];
+ int i, j, dir = 0;
+
+ if (count <= 10) return ('g');
+
+ /* van short naar float (tekenen is met shorts) */
+ for(j=0; j<count; j++) {
+ mouse[j][0]= mcord[j][0];
+ mouse[j][1]= mcord[j][1];
+ }
+
+ /* nieuwe opzet:
+ *
+ * vanuit eindpunten middelpunt met maximale afstand berekenen
+ * aan de hand van de hoek wordt s / g / r bepaald
+ */
+
+
+ /* filteren */
+
+ for( j = 3 ; j > 0; j--){
+ x1 = mouse[1][0];
+ y1 = mouse[1][1];
+ for (i = 2; i < count; i++){
+ x2 = mouse[i-1][0];
+ y2 = mouse[i-1][1];
+ mouse[i-1][0] = ((x1 + mouse[i][0]) /4.0) + (x2 / 2.0);
+ mouse[i-1][1] = ((y1 + mouse[i][1]) /4.0) + (y2 / 2.0);
+ x1 = x2;
+ y1 = y2;
+ }
+ }
+
+ /* maak directions overzicht */
+ for (i = 0; i <= count - 2; i++){
+ x1 = mouse[i][0] - mouse[i + 1][0];
+ y1 = mouse[i][1] - mouse[i + 1][1];
+
+ if (x1 < -0.5){
+ if (y1 < -0.5) dir |= 32;
+ else if (y1 > 0.5) dir |= 128;
+ else dir |= 64;
+ } else if (x1 > 0.5){
+ if (y1 < -0.5) dir |= 8;
+ else if (y1 > 0.5) dir |= 2;
+ else dir |= 4;
+ } else{
+ if (y1 < -0.5) dir |= 16;
+ else if (y1 > 0.5) dir |= 1;
+ else dir |= 0;
+ }
+ }
+
+ /* alle kruisjes naar rechts halen */
+ for (i = 7; i>=0 ; i--){
+ if (dir & 128) dir = (dir << 1) + 1;
+ else break;
+ }
+ dir &= 255;
+ for (i = 7; i>=0 ; i--){
+ if ((dir & 1) == 0) dir >>= 1;
+ else break;
+ }
+
+ /* theorie zegt: 1 richting: rechte lijn
+ * meer aaneengesloten richtingen: cirkel
+ * onderbroken en minstens 1 bit gezet in hoogste 4 bits: size
+ */
+ switch(dir){
+ case 1:
+ return ('g');
+ break;
+ case 3:
+ case 7:
+ x1 = mouse[0][0] - mouse[count >> 1][0];
+ y1 = mouse[0][1] - mouse[count >> 1][1];
+ x2 = mouse[count >> 1][0] - mouse[count - 1][0];
+ y2 = mouse[count >> 1][1] - mouse[count - 1][1];
+ d1 = (x1 * x1) + (y1 * y1);
+ d2 = (x2 * x2) + (y2 * y2);
+ sq = sqrt(d1);
+ x1 /= sq;
+ y1 /= sq;
+ sq = sqrt(d2);
+ x2 /= sq;
+ y2 /= sq;
+ inp = (x1 * x2) + (y1 * y2);
+ /*printf("%f\n", inp);*/
+ if (inp > 0.9) return ('g');
+ else return ('r');
+ break;
+ case 15:
+ case 31:
+ case 63:
+ case 127:
+ case 255:
+ return ('r');
+ break;
+ default:
+ /* bij size moeten minstens een van de hogere bits gezet zijn */
+ if (dir < 16) return ('r');
+ else return ('s');
+ }
+
+ return (0);
+}
+
+int gesture(void)
+{
+ short mcords[MOVES][2];
+ int i= 1, end= 0, a;
+ unsigned short event;
+ short mval[2], val;
+
+ glDrawBuffer(GL_FRONT);
+ persp(0); /* heeft ortho op pixelnivo */
+
+ getmouseco_areawin(mval);
+
+ mcords[0][0] = mval[0];
+ mcords[0][1] = mval[1];
+
+ while(get_mbut()&L_MOUSE) {
+
+ event= extern_qread(&val);
+
+ switch (event) {
+ case MOUSEY:
+ getmouseco_areawin(mval);
+ if( abs(mval[0]-mcords[i-1][0])>3 || abs(mval[1]-mcords[i-1][1])>3 ) {
+ mcords[i][0] = mval[0];
+ mcords[i][1] = mval[1];
+ if(i) {
+ sdrawXORline(mcords[i-1][0], mcords[i-1][1], mcords[i][0], mcords[i][1]);
+ glFlush();
+ }
+ i++;
+ }
+ break;
+ case MOUSEX:
+ break;
+ case LEFTMOUSE:
+ break;
+ default:
+ if(event) end= 1; /* blender returns 0 */
+ break;
+ }
+ if (i == MOVES || end == 1) break;
+ }
+
+ for(a=1; a<i; a++) {
+ sdrawXORline(mcords[a-1][0], mcords[a-1][1], mcords[a][0], mcords[a][1]);
+ }
+
+ persp(1);
+ glDrawBuffer(GL_BACK);
+
+ if (i > 2) {
+ i = interpret_move(mcords, i);
+
+ if(i) {
+ if(curarea->spacetype==SPACE_IPO) transform_ipo(i);
+ else if(curarea->spacetype==SPACE_IMAGE) transform_tface_uv(i);
+ else if(curarea->spacetype==SPACE_OOPS) transform_oops('g');
+ else transform(i);
+ }
+
+ return 1;
+ }
+ return 0;
+}
+
+void mouse_cursor(void)
+{
+ extern float zfac; /* view.c */
+ float dx, dy, fz, *fp = NULL, dvec[3], oldcurs[3];
+ short mval[2], mx, my, lr_click=0;
+
+ if(gesture()) return;
+
+ getmouseco_areawin(mval);
+
+ if(mval[0]!=G.vd->mx || mval[1]!=G.vd->my) {
+
+ mx= mval[0];
+ my= mval[1];
+
+ fp= give_cursor();
+
+ if(G.obedit && ((G.qual & LR_CTRLKEY) || get_mbut()&R_MOUSE )) lr_click= 1;
+ VECCOPY(oldcurs, fp);
+
+ project_short_noclip(fp, mval);
+
+ initgrabz(fp[0], fp[1], fp[2]);
+
+ if(mval[0]!=3200) {
+
+ window_to_3d(dvec, mval[0]-mx, mval[1]-my);
+ VecSubf(fp, fp, dvec);
+
+ }
+ else {
+
+ dx= ((float)(mx-(curarea->winx/2)))*zfac/(curarea->winx/2);
+ dy= ((float)(my-(curarea->winy/2)))*zfac/(curarea->winy/2);
+
+ fz= G.vd->persmat[0][3]*fp[0]+ G.vd->persmat[1][3]*fp[1]+ G.vd->persmat[2][3]*fp[2]+ G.vd->persmat[3][3];
+ fz= fz/zfac;
+
+ fp[0]= (G.vd->persinv[0][0]*dx + G.vd->persinv[1][0]*dy+ G.vd->persinv[2][0]*fz)-G.vd->ofs[0];
+ fp[1]= (G.vd->persinv[0][1]*dx + G.vd->persinv[1][1]*dy+ G.vd->persinv[2][1]*fz)-G.vd->ofs[1];
+ fp[2]= (G.vd->persinv[0][2]*dx + G.vd->persinv[1][2]*dy+ G.vd->persinv[2][2]*fz)-G.vd->ofs[2];
+ }
+
+ allqueue(REDRAWVIEW3D, 1);
+ }
+
+ if(lr_click) {
+ if(G.obedit->type==OB_MESH) addvert_mesh();
+ else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) addvert_Nurb(0);
+ else if (G.obedit->type==OB_ARMATURE) addvert_armature();
+ VECCOPY(fp, oldcurs);
+ }
+
+}
+
+void deselectall(void) /* is toggle */
+{
+ Base *base;
+ int a=0;
+
+ base= FIRSTBASE;
+ while(base) {
+ if TESTBASE(base) {
+ a= 1;
+ break;
+ }
+ base= base->next;
+ }
+
+ base= FIRSTBASE;
+ while(base) {
+ if(base->lay & G.vd->lay) {
+ if(a) base->flag &= ~SELECT;
+ else base->flag |= SELECT;
+ base->object->flag= base->flag;
+ }
+ base= base->next;
+ }
+
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWDATASELECT, 0);
+ allqueue(REDRAWNLA, 0);
+
+ countall();
+
+}
+
+static void deselectall_ex(Base *b) /* ALLES deselect behalve b */
+{
+ Base *base;
+
+ base= FIRSTBASE;
+ while(base) {
+ if (base->flag & SELECT) {
+ if(b!=base) {
+
+ base->flag &= ~SELECT;
+ base->object->flag= base->flag;
+ draw_object_ext(base); /* deze test op layer */
+ }
+ }
+ base= base->next;
+ }
+ countall();
+}
+
+static unsigned int samplerect(unsigned int *buf, int size, unsigned int dontdo)
+{
+ Base *base;
+ unsigned int *bufmin,*bufmax;
+ int a,b,rc,tel,aantal,dirvec[4][2],maxob;
+ unsigned int retval=0;
+
+ base= LASTBASE;
+ if(base==0) return 0;
+ maxob= base->selcol;
+
+ aantal= (size-1)/2;
+ rc= 0;
+
+ dirvec[0][0]= 1;
+ dirvec[0][1]= 0;
+ dirvec[1][0]= 0;
+ dirvec[1][1]= -size;
+ dirvec[2][0]= -1;
+ dirvec[2][1]= 0;
+ dirvec[3][0]= 0;
+ dirvec[3][1]= size;
+
+ bufmin= buf;
+ bufmax= buf+ size*size;
+ buf+= aantal*size+ aantal;
+
+ for(tel=1;tel<=size;tel++) {
+
+ for(a=0;a<2;a++) {
+ for(b=0;b<tel;b++) {
+
+ if(*buf && *buf<=maxob && *buf!=dontdo) return *buf;
+ if( *buf==dontdo ) retval= dontdo; /* als alleen kleur dontdo aanwezig is, wel dontdo teruggeven */
+
+ buf+= (dirvec[rc][0]+dirvec[rc][1]);
+
+ if(buf<bufmin || buf>=bufmax) return retval;
+ }
+ rc++;
+ rc &= 3;
+ }
+ }
+ return retval;
+}
+
+#define SELECTSIZE 51
+
+void set_active_base(Base *base)
+{
+
+ BASACT= base;
+
+ /* signalen naar buttons */
+ redraw_test_buttons(base);
+
+ set_active_group();
+
+ /* signaal naar ipo */
+
+ if (base) {
+ allqueue(REDRAWIPO, base->object->ipowin);
+ allqueue(REDRAWACTION, 0);
+ allqueue(REDRAWNLA, 0);
+ }
+
+
+}
+
+void set_active_object(Object *ob)
+{
+ Base *base;
+
+ base= FIRSTBASE;
+ while(base) {
+ if(base->object==ob) {
+ set_active_base(base);
+ return;
+ }
+ base= base->next;
+ }
+}
+
+void mouse_select(void)
+{
+ Base *base, *startbase=0, *basact=0, *oldbasact;
+ GLuint buffer[MAXPICKBUF];
+ int temp, a, dist=100;
+ short hits, mval[2];
+
+ /* iedere keer lijst starten vanuit basact */
+ startbase= FIRSTBASE;
+ if(BASACT && BASACT->next) startbase= BASACT->next;
+
+ getmouseco_areawin(mval);
+
+ if(G.obedit==0 && (G.qual & LR_CTRLKEY)) {
+
+ base= startbase;
+ while(base) {
+
+ if(base->lay & G.vd->lay) {
+
+ project_short(base->object->obmat[3], &base->sx);
+
+ temp= abs(base->sx -mval[0]) + abs(base->sy -mval[1]);
+ if(base==BASACT) temp+=10;
+ if(temp<dist ) {
+ basact= base;
+ dist= temp;
+ }
+ }
+ base= base->next;
+
+ if(base==0) base= FIRSTBASE;
+ if(base==startbase) break;
+ }
+
+ /* volledige redraw als */
+ if(G.f & (G_VERTEXPAINT+G_FACESELECT+G_TEXTUREPAINT+G_WEIGHTPAINT)) allqueue(REDRAWVIEW3D, 0);
+
+ }
+ else {
+ hits= selectprojektie(buffer, mval[0]-7, mval[1]-7, mval[0]+7, mval[1]+7);
+ if(hits==0) hits= selectprojektie(buffer, mval[0]-21, mval[1]-21, mval[0]+21, mval[1]+21);
+
+ if(hits>0) {
+
+ base= startbase;
+ while(base) {
+ if(base->lay & G.vd->lay) {
+ for(a=0; a<hits; a++) {
+ /* index was converted */
+ if(base->selcol==buffer[ (4 * a) + 3 ]) basact= base;
+ }
+ }
+ if(basact) break;
+
+ base= base->next;
+ if(base==0) base= FIRSTBASE;
+ if(base==startbase) break;
+ }
+ }
+ }
+
+ if(basact) {
+ if(G.obedit) {
+ /* alleen select doen */
+ deselectall_ex(BASACT);
+ basact->flag |= SELECT;
+ draw_object_ext(basact);
+ }
+ else {
+ oldbasact= BASACT;
+ BASACT= basact;
+
+ if((G.qual & LR_SHIFTKEY)==0) {
+ deselectall_ex(basact);
+ basact->flag |= SELECT;
+ }
+ else {
+ if(oldbasact) if(oldbasact != basact) draw_object_ext(oldbasact);
+
+ if(basact->flag & SELECT) {
+ if(basact==oldbasact)
+ basact->flag &= ~SELECT;
+ }
+ else basact->flag |= SELECT;
+ }
+
+ /* if((basact->flag & SELECT)==0) BASACT= 0; */
+ basact->object->flag= basact->flag;
+
+ draw_object_ext(basact);
+
+ if(oldbasact != basact) {
+
+ set_active_base(basact);
+
+ }
+
+ if(basact->object->type!=OB_MESH) {
+ if(G.f & G_WEIGHTPAINT) {
+ set_wpaint(); /* toggle */
+ }
+ if(G.f & G_VERTEXPAINT) {
+ set_vpaint(); /* toggle */
+ }
+ if(G.f & G_FACESELECT) {
+ set_faceselect(); /* toggle */
+ }
+ }
+
+ allqueue(REDRAWBUTSGAME, 0);
+ allqueue(REDRAWDATASELECT, 0);
+ allqueue(REDRAWBUTSCONSTRAINT, 0);
+ allqueue(REDRAWACTION, 0);
+ allqueue(REDRAWNLA, 0);
+ allqueue(REDRAWHEADERS, 0); /* To force display update for the posebutton */
+ }
+
+ }
+
+ countall();
+
+ rightmouse_transform();
+}
+
+/* ------------------------------------------------------------------------- */
+/**
+ * Does the 'borderselect' command. (Select verts based on selecting with a
+ * border: key 'b'). All selecting seems to be done in the get_border part.
+ */
+void borderselect(void)
+{
+ rcti rect;
+ Base *base;
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ MetaElem *ml;
+ struct EditVert *eve;
+ /* was IGLuint */
+ GLuint buffer[MAXPICKBUF];
+ int a, index;
+ short hits, val, tel;
+
+ if(G.obedit==0 && (G.f & G_FACESELECT)) {
+ face_borderselect();
+ return;
+ }
+
+ val= get_border(&rect, 3);
+ if(val) {
+ if (G.obpose){
+ if(G.obpose->type==OB_ARMATURE) {
+ Bone *bone;
+ hits= selectprojektie(buffer, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+ base= FIRSTBASE;
+ for (a=0; a<hits; a++){
+ index = buffer[(4*a)+3];
+ if (val==LEFTMOUSE){
+ if (index != -1){
+ bone = get_indexed_bone(G.obpose->data, index &~(BONESEL_TIP|BONESEL_ROOT));
+ bone->flag |= BONE_SELECTED;
+ select_actionchannel_by_name(G.obpose->action, bone->name, 1);
+ }
+ }
+ else{
+ if (index != -1){
+ bone = get_indexed_bone(G.obpose->data, index &~(BONESEL_TIP|BONESEL_ROOT));
+ bone->flag &= ~BONE_SELECTED;
+ select_actionchannel_by_name(G.obpose->action, bone->name, 0);
+ }
+ }
+ }
+
+ allqueue(REDRAWBUTSEDIT, 0);
+ allqueue(REDRAWBUTSCONSTRAINT, 0);
+ allqueue(REDRAWACTION, 0);
+ allqueue(REDRAWNLA, 0);
+ allqueue(REDRAWVIEW3D, 0);
+ }
+ }
+ else
+ if(G.obedit) {
+ /* used to be a bigger test, also included sector and life */
+ if(G.obedit->type==OB_MESH) {
+
+ calc_meshverts_ext(); /* drawobject.c */
+ eve= G.edve.first;
+ while(eve) {
+ if(eve->h==0 && eve->xs>rect.xmin && eve->xs<rect.xmax) {
+ if(eve->ys>rect.ymin && eve->ys<rect.ymax) {
+ if(val==LEFTMOUSE) eve->f|= 1;
+ else eve->f&= 254;
+ }
+ }
+ eve= eve->next;
+ }
+ if(val!=LEFTMOUSE) tekenvertices_ext(0);
+ tekenvertices_ext(1);
+
+ }
+ else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
+
+ calc_nurbverts_ext(); /* drawobject.c */
+ nu= editNurb.first;
+ while(nu) {
+ if((nu->type & 7)==CU_BEZIER) {
+ bezt= nu->bezt;
+ a= nu->pntsu;
+ while(a--) {
+ if(bezt->hide==0) {
+ if(bezt->s[0][0]>rect.xmin && bezt->s[0][0]<rect.xmax) {
+ if(bezt->s[0][1]>rect.ymin && bezt->s[0][1]<rect.ymax) {
+ if(val==LEFTMOUSE) bezt->f1|= 1;
+ else bezt->f1 &= ~1;
+ }
+ }
+ if(bezt->s[1][0]>rect.xmin && bezt->s[1][0]<rect.xmax) {
+ if(bezt->s[1][1]>rect.ymin && bezt->s[1][1]<rect.ymax) {
+ if(val==LEFTMOUSE) {
+ bezt->f1|= 1; bezt->f2|= 1; bezt->f3|= 1;
+ }
+ else {
+ bezt->f1 &= ~1; bezt->f2 &= ~1; bezt->f3 &= ~1;
+ }
+ }
+ }
+ if(bezt->s[2][0]>rect.xmin && bezt->s[2][0]<rect.xmax) {
+ if(bezt->s[2][1]>rect.ymin && bezt->s[2][1]<rect.ymax) {
+ if(val==LEFTMOUSE) bezt->f3|= 1;
+ else bezt->f3 &= ~1;
+ }
+ }
+ }
+ bezt++;
+ }
+ }
+ else {
+ bp= nu->bp;
+ a= nu->pntsu*nu->pntsv;
+ while(a--) {
+ if(bp->hide==0) {
+ if(bp->s[0]>rect.xmin && bp->s[0]<rect.xmax) {
+ if(bp->s[1]>rect.ymin && bp->s[1]<rect.ymax) {
+ if(val==LEFTMOUSE) bp->f1|= 1;
+ else bp->f1 &= ~1;
+ }
+ }
+ }
+ bp++;
+ }
+ }
+ nu= nu->next;
+ }
+ allqueue(REDRAWVIEW3D, 0);
+ }
+ else if(G.obedit->type==OB_MBALL) {
+ hits= selectprojektie(buffer, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+
+ ml= editelems.first;
+
+ while(ml) {
+ for(a=0; a<hits; a++) {
+ if(ml->selcol==buffer[ (4 * a) + 3 ]) {
+ if(val==LEFTMOUSE) ml->flag |= SELECT;
+ else ml->flag &= ~SELECT;
+ break;
+ }
+ }
+ ml= ml->next;
+ }
+ allqueue(REDRAWVIEW3D, 0);
+ }
+ else if(G.obedit->type==OB_ARMATURE) {
+ EditBone *ebone;
+
+ hits= selectprojektie(buffer, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+
+ base= FIRSTBASE;
+ for (a=0; a<hits; a++){
+ index = buffer[(4*a)+3];
+ if (val==LEFTMOUSE){
+ if (index!=-1){
+ ebone = BLI_findlink(&G.edbo, index & ~(BONESEL_TIP|BONESEL_ROOT));
+ if (index & BONESEL_TIP)
+ ebone->flag |= BONE_TIPSEL;
+ if (index & BONESEL_ROOT)
+ ebone->flag |= BONE_ROOTSEL;
+ }
+ }
+ else{
+ if (index!=-1){
+ ebone = BLI_findlink(&G.edbo, index & ~(BONESEL_TIP|BONESEL_ROOT));
+ if (index & BONESEL_TIP)
+ ebone->flag &= ~BONE_TIPSEL;
+ if (index & BONESEL_ROOT)
+ ebone->flag &= ~BONE_ROOTSEL;
+ }
+ }
+ }
+
+ /* XXX, are all these really needed?
+ * I just copied them from the G.obpose
+ * OB_ARMATURE section above. - zr
+ */
+ allqueue(REDRAWBUTSEDIT, 0);
+ allqueue(REDRAWBUTSCONSTRAINT, 0);
+ allqueue(REDRAWACTION, 0);
+ allqueue(REDRAWVIEW3D, 0);
+ }
+ else if(G.obedit->type==OB_LATTICE) {
+
+ calc_lattverts_ext();
+
+ bp= editLatt->def;
+
+ a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
+ while(a--) {
+ if(bp->hide==0) {
+ if(bp->s[0]>rect.xmin && bp->s[0]<rect.xmax) {
+ if(bp->s[1]>rect.ymin && bp->s[1]<rect.ymax) {
+ if(val==LEFTMOUSE) bp->f1|= 1;
+ else bp->f1 &= ~1;
+ }
+ }
+ }
+ bp++;
+ }
+ allqueue(REDRAWVIEW3D, 0);
+ }
+
+ }
+ else {
+
+ hits= selectprojektie(buffer, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+
+ base= FIRSTBASE;
+ while(base) {
+ if(base->lay & G.vd->lay) {
+ for(a=0; a<hits; a++) {
+ /* converted index */
+ if(base->selcol==buffer[ (4 * a) + 3 ]) {
+ if(val==LEFTMOUSE) base->flag |= SELECT;
+ else base->flag &= ~SELECT;
+ base->object->flag= base->flag;
+
+ draw_object_ext(base);
+ break;
+ }
+ }
+ }
+
+ base= base->next;
+ }
+ allqueue(REDRAWDATASELECT, 0);
+
+ /* i.v.m. backbufprojektie */
+ tel= 1;
+ base= FIRSTBASE;
+ while(base) {
+ /* elke base ivm meerdere windows */
+ base->selcol = ((tel & 0xF00)<<12)
+ + ((tel & 0xF0)<<8)
+ + ((tel & 0xF)<<4);
+ tel++;
+ base= base->next;
+ }
+ /* new */
+ allqueue(REDRAWBUTSGAME, 0);
+ allqueue(REDRAWNLA, 0);
+ }
+ countall();
+
+ allqueue(REDRAWINFO, 0);
+ }
+} /* end of borderselect() */
+
+/* ------------------------------------------------------------------------- */
+
+/** The following functions are quick & dirty callback functions called
+ * on the Circle select function (press B twice in Editmode)
+ * They were torn out of the circle_select to make the latter more reusable
+ * The callback version of circle_select (called circle_selectCB) was moved
+ * to edit.c because of it's (wanted) generality.
+
+ XXX These callback functions are still dirty, because they call globals...
+ */
+
+void mesh_selectionCB(int selecting, Object *editobj, short *mval, float rad)
+{
+ EditVert *eve;
+ float x, y, r;
+
+ calc_meshverts_ext(); /* drawobject.c */
+ eve= G.edve.first;
+ while(eve) {
+ if(eve->h==0) {
+ x= eve->xs-mval[0];
+ y= eve->ys-mval[1];
+ r= sqrt(x*x+y*y);
+ if(r<=rad) {
+ if(selecting==LEFTMOUSE) eve->f|= 1;
+ else eve->f&= 254;
+ }
+ }
+ eve= eve->next;
+ }
+ if(G.f & (G_FACESELECT+G_DRAWFACES)) {
+ draw_sel_circle(0, 0, 0, 0, 0); /* signal */
+ force_draw();
+ }
+ else {
+ if(selecting!=LEFTMOUSE) tekenvertices_ext(0);
+ /* altijd geselecteerde vertices tekenen */
+ tekenvertices_ext(1);
+ }
+}
+
+
+void nurbscurve_selectionCB(int selecting, Object *editobj, short *mval, float rad)
+{
+ Nurb *nu;
+ BPoint *bp;
+ BezTriple *bezt;
+ float x, y, r;
+ int a;
+
+ calc_nurbverts_ext(); /* drawobject.c */
+ nu= editNurb.first;
+ while(nu) {
+ if((nu->type & 7)==CU_BEZIER) {
+ bezt= nu->bezt;
+ a= nu->pntsu;
+ while(a--) {
+ if(bezt->hide==0) {
+ x= bezt->s[0][0]-mval[0];
+ y= bezt->s[0][1]-mval[1];
+ r= sqrt(x*x+y*y);
+ if(r<=rad) {
+ if(selecting==LEFTMOUSE) bezt->f1|= 1;
+ else bezt->f1 &= ~1;
+ }
+ x= bezt->s[1][0]-mval[0];
+ y= bezt->s[1][1]-mval[1];
+ r= sqrt(x*x+y*y);
+ if(r<=rad) {
+ if(selecting==LEFTMOUSE) bezt->f2|= 1;
+ else bezt->f2 &= ~1;
+ }
+ x= bezt->s[2][0]-mval[0];
+ y= bezt->s[2][1]-mval[1];
+ r= sqrt(x*x+y*y);
+ if(r<=rad) {
+ if(selecting==LEFTMOUSE) bezt->f3|= 1;
+ else bezt->f3 &= ~1;
+ }
+
+ }
+ bezt++;
+ }
+ }
+ else {
+ bp= nu->bp;
+ a= nu->pntsu*nu->pntsv;
+ while(a--) {
+ if(bp->hide==0) {
+ x= bp->s[0]-mval[0];
+ y= bp->s[1]-mval[1];
+ r= sqrt(x*x+y*y);
+ if(r<=rad) {
+ if(selecting==LEFTMOUSE) bp->f1|= 1;
+ else bp->f1 &= ~1;
+ }
+ }
+ bp++;
+ }
+ }
+ nu= nu->next;
+ }
+ draw_sel_circle(0, 0, 0, 0, 0); /* signal */
+ force_draw();
+
+
+}
+
+void lattice_selectionCB(int selecting, Object *editobj, short *mval, float rad)
+{
+ BPoint *bp;
+ float x, y, r;
+ int a;
+
+ calc_lattverts_ext();
+
+ bp= editLatt->def;
+
+ a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
+ while(a--) {
+ if(bp->hide==0) {
+ x= bp->s[0]-mval[0];
+ y= bp->s[1]-mval[1];
+ r= sqrt(x*x+y*y);
+ if(r<=rad) {
+ if(selecting==LEFTMOUSE) bp->f1|= 1;
+ else bp->f1 &= ~1;
+ }
+ }
+ bp++;
+ }
+ draw_sel_circle(0, 0, 0, 0, 0); /* signal */
+ force_draw();
+}
+
+/** Callbacks for selection in Editmode */
+
+void obedit_selectionCB(short selecting, Object *editobj, short *mval, float rad)
+{
+ switch(editobj->type) {
+ case OB_MESH:
+ mesh_selectionCB(selecting, editobj, mval, rad);
+ break;
+ case OB_CURVE:
+ case OB_SURF:
+ nurbscurve_selectionCB(selecting, editobj, mval, rad);
+ break;
+ case OB_LATTICE:
+ lattice_selectionCB(selecting, editobj, mval, rad);
+ break;
+ }
+}
+
+/** The circle select function - should be replaced by the callback
+ * version circle_selectCB(). Why ? Because it's not nice as it is!
+ *
+ */
+
+void circle_select(void)
+{
+ Nurb *nu;
+ BPoint *bp;
+ BezTriple *bezt;
+ EditVert *eve;
+ static float rad= 40.0;
+ float rado, x, y, trad;
+ int a, firsttime=1;
+ unsigned short event;
+ short mvalo[2], mval[2], val;
+ short selecting=0;
+
+ if(G.obedit==0) return;
+
+ getmouseco_areawin(mvalo);
+ draw_sel_circle(mvalo, 0, rad, 0.0, selecting);
+
+ rado= rad;
+
+ while(TRUE) {
+
+ /* als een renderwindow open is en de muis gaat erin */
+
+ mywinset(curarea->win);
+
+ getmouseco_areawin(mval);
+
+ if(mval[0]!=mvalo[0] || mval[1]!=mvalo[1] || rado!=rad || firsttime) {
+ firsttime= 0;
+
+ draw_sel_circle(mval, mvalo, rad, rado, selecting);
+
+ mvalo[0]= mval[0];
+ mvalo[1]= mval[1];
+ rado= rad;
+
+ if(selecting) {
+
+ if(G.obedit->type==OB_MESH) {
+
+ calc_meshverts_ext(); /* drawobject.c */
+ eve= G.edve.first;
+ while(eve) {
+ if(eve->h==0) {
+ x= eve->xs-mval[0];
+ y= eve->ys-mval[1];
+ trad= sqrt(x*x+y*y);
+ if(trad<=rad) {
+ if(selecting==LEFTMOUSE) eve->f|= 1;
+ else eve->f&= 254;
+ }
+ }
+ eve= eve->next;
+ }
+ if(G.f & (G_FACESELECT+G_DRAWFACES)) {
+ draw_sel_circle(0, 0, 0, 0, 0); /* signal */
+ force_draw();
+ }
+ else {
+ if(selecting!=LEFTMOUSE) tekenvertices_ext(0);
+ /* altijd geselecteerde vertices tekenen */
+ tekenvertices_ext(1);
+ }
+ }
+ else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
+
+ calc_nurbverts_ext(); /* drawobject.c */
+ nu= editNurb.first;
+ while(nu) {
+ if((nu->type & 7)==CU_BEZIER) {
+ bezt= nu->bezt;
+ a= nu->pntsu;
+ while(a--) {
+ if(bezt->hide==0) {
+ x= bezt->s[0][0]-mval[0];
+ y= bezt->s[0][1]-mval[1];
+ trad= sqrt(x*x+y*y);
+ if(trad<=rad) {
+ if(selecting==LEFTMOUSE) bezt->f1|= 1;
+ else bezt->f1 &= ~1;
+ }
+ x= bezt->s[1][0]-mval[0];
+ y= bezt->s[1][1]-mval[1];
+ trad= sqrt(x*x+y*y);
+ if(trad<=rad) {
+ if(selecting==LEFTMOUSE) bezt->f2|= 1;
+ else bezt->f2 &= ~1;
+ }
+ x= bezt->s[2][0]-mval[0];
+ y= bezt->s[2][1]-mval[1];
+ trad= sqrt(x*x+y*y);
+ if(trad<=rad) {
+ if(selecting==LEFTMOUSE) bezt->f3|= 1;
+ else bezt->f3 &= ~1;
+ }
+
+ }
+ bezt++;
+ }
+ }
+ else {
+ bp= nu->bp;
+ a= nu->pntsu*nu->pntsv;
+ while(a--) {
+ if(bp->hide==0) {
+ x= bp->s[0]-mval[0];
+ y= bp->s[1]-mval[1];
+ trad= sqrt(x*x+y*y);
+ if(trad<=rad) {
+ if(selecting==LEFTMOUSE) bp->f1|= 1;
+ else bp->f1 &= ~1;
+ }
+ }
+ bp++;
+ }
+ }
+ nu= nu->next;
+ }
+ draw_sel_circle(0, 0, 0, 0, 0); /* signal */
+ force_draw();
+ }
+ else if(G.obedit->type==OB_LATTICE) {
+ calc_lattverts_ext();
+
+ bp= editLatt->def;
+
+ a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
+ while(a--) {
+ if(bp->hide==0) {
+ x= bp->s[0]-mval[0];
+ y= bp->s[1]-mval[1];
+ trad= sqrt(x*x+y*y);
+ if(trad<=rad) {
+ if(selecting==LEFTMOUSE) bp->f1|= 1;
+ else bp->f1 &= ~1;
+ }
+ }
+ bp++;
+ }
+ draw_sel_circle(0, 0, 0, 0, 0); /* signal */
+ force_draw();
+ }
+ }
+ }
+
+ event= extern_qread(&val);
+ if (event) {
+ int afbreek= 0;
+
+ switch(event) {
+ case LEFTMOUSE:
+ case MIDDLEMOUSE:
+ if(val) selecting= event;
+ else selecting= 0;
+ firsttime= 1;
+
+ break;
+ case PADPLUSKEY:
+ if(val) if(rad<200.0) rad*= 1.2;
+ break;
+ case PADMINUS:
+ if(val) if(rad>5.0) rad/= 1.2;
+ break;
+
+ case ESCKEY: case SPACEKEY: case RIGHTMOUSE:
+ case GKEY: case SKEY: case RKEY: case XKEY: case EKEY: case TABKEY:
+ afbreek= 1;
+ break;
+
+ }
+
+ if(afbreek) break;
+ }
+ }
+
+ /* cirkel wissen */
+ draw_sel_circle(0, mvalo, 0, rad, 1);
+
+ countall();
+ allqueue(REDRAWINFO, 0);
+}
+
+void set_render_border(void)
+{
+ rcti rect;
+ short val;
+
+ if(G.vd->persp!=2) return;
+
+ val= get_border(&rect, 2);
+ if(val) {
+ rcti vb;
+
+ calc_viewborder(G.vd, &vb);
+
+ G.scene->r.border.xmin= (float) (rect.xmin-vb.xmin)/(vb.xmax-vb.xmin);
+ G.scene->r.border.ymin= (float) (rect.ymin-vb.ymin)/(vb.ymax-vb.ymin);
+ G.scene->r.border.xmax= (float) (rect.xmax-vb.xmin)/(vb.xmax-vb.xmin);
+ G.scene->r.border.ymax= (float) (rect.ymax-vb.ymin)/(vb.ymax-vb.ymin);
+
+ CLAMP(G.scene->r.border.xmin, 0.0, 1.0);
+ CLAMP(G.scene->r.border.ymin, 0.0, 1.0);
+ CLAMP(G.scene->r.border.xmax, 0.0, 1.0);
+ CLAMP(G.scene->r.border.ymax, 0.0, 1.0);
+
+ allqueue(REDRAWVIEWCAM, 1);
+ }
+}
+
+
+
+void fly(void)
+{
+ float speed=0.0, speedo=1.0, zspeed=0.0, dvec[3], *quat, mat[3][3];
+ float oldvec[3], oldrot[3];
+ int loop=1;
+ unsigned short toets;
+ short val, cent[2];
+ short mval[2];
+
+ if(curarea->spacetype!=SPACE_VIEW3D) return;
+ if(G.vd->camera == 0) return;
+ if(G.vd->persp<2) return;
+
+ VECCOPY(oldvec, G.vd->camera->loc);
+ VECCOPY(oldrot, G.vd->camera->rot);
+
+ cent[0]= curarea->winrct.xmin+(curarea->winx)/2;
+ cent[1]= curarea->winrct.ymin+(curarea->winy)/2;
+
+ warp_pointer(cent[0], cent[1]);
+
+ cent[0]= (curarea->winx)/2;
+ cent[1]= (curarea->winy)/2;
+
+ headerprint("Fly");
+
+ while(loop) {
+ getmouseco_areawin(mval);
+
+ while(qtest()) {
+
+ toets= extern_qread(&val);
+
+ if(val) {
+ if(toets==ESCKEY) {
+ VECCOPY(G.vd->camera->loc, oldvec);
+ VECCOPY(G.vd->camera->rot, oldrot);
+ loop= 0;
+ break;
+ }
+ else if(toets==SPACEKEY) {
+ loop= 0;
+ break;
+ }
+ else if(toets==LEFTMOUSE) {
+ speed+= G.vd->grid/75.0;
+ if(get_mbut()&M_MOUSE) speed= 0.0;
+ }
+ else if(toets==MIDDLEMOUSE) {
+ speed-= G.vd->grid/75.0;
+ if(get_mbut()&L_MOUSE) speed= 0.0;
+ }
+ }
+ }
+ if(loop==0) break;
+
+ /* dvec bepalen */
+ val= mval[0]-cent[0];
+ if(val>20) val-= 20; else if(val< -20) val+= 20; else val= 0;
+ dvec[0]= 0.000001*val*val;
+ if(val>0) dvec[0]= -dvec[0];
+
+ val= mval[1]-cent[1];
+ if(val>20) val-= 20; else if(val< -20) val+= 20; else val= 0;
+ dvec[1]= 0.000001*val*val;
+ if(val>0) dvec[1]= -dvec[1];
+
+ dvec[2]= 1.0;
+
+ zspeed= 0.0;
+ if(get_qual()&LR_CTRLKEY) zspeed= -G.vd->grid/25.0;
+ if(get_qual()&LR_ALTKEY) zspeed= G.vd->grid/25.0;
+
+ if(speedo!=0.0 || zspeed!=0.0 || dvec[0]!=0.0 || dvec[1]!=0.0) {
+
+ Normalise(dvec);
+
+ Mat3CpyMat4(mat, G.vd->viewinv);
+ Mat3MulVecfl(mat, dvec);
+ quat= vectoquat(dvec, 5, 1); /* track en upflag, niet die van de base: cameraview-berekening gebruikt ze niet */
+
+ QuatToEul(quat, G.vd->camera->rot);
+
+ compatible_eul(G.vd->camera->rot, oldrot);
+
+ VecMulf(dvec, speed);
+ G.vd->camera->loc[0]-= dvec[0];
+ G.vd->camera->loc[1]-= dvec[1];
+ G.vd->camera->loc[2]-= (dvec[2]-zspeed);
+
+ scrarea_do_windraw(curarea);
+ screen_swapbuffers();
+ }
+ speedo= speed;
+ }
+
+ allqueue(REDRAWVIEW3D, 0);
+ scrarea_queue_headredraw(curarea);
+
+}
+
diff --git a/source/blender/src/eventdebug.c b/source/blender/src/eventdebug.c
new file mode 100644
index 00000000000..6c9a5ee005b
--- /dev/null
+++ b/source/blender/src/eventdebug.c
@@ -0,0 +1,203 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "mydevice.h"
+#include "blendef.h"
+
+char *event_to_string(short evt) {
+#define smap(evt) case evt: return #evt
+ switch (evt) {
+ default: return "<unknown>";
+ smap(CHANGED);
+ smap(DRAWEDGES);
+ smap(BACKBUFDRAW);
+ smap(EXECUTE);
+ smap(LOAD_FILE);
+ smap(RESHAPE);
+ smap(UI_BUT_EVENT);
+ smap(REDRAWVIEW3D);
+ smap(REDRAWBUTSHEAD);
+ smap(REDRAWBUTSALL);
+ smap(REDRAWBUTSVIEW);
+ smap(REDRAWBUTSLAMP);
+ smap(REDRAWBUTSMAT);
+ smap(REDRAWBUTSTEX);
+ smap(REDRAWBUTSANIM);
+ smap(REDRAWBUTSWORLD);
+ smap(REDRAWBUTSRENDER);
+ smap(REDRAWBUTSEDIT);
+ smap(REDRAWVIEWCAM);
+ smap(REDRAWHEADERS);
+ smap(REDRAWBUTSGAME);
+ smap(REDRAWBUTSRADIO);
+ smap(REDRAWVIEW3D_Z);
+ smap(REDRAWALL);
+ smap(REDRAWINFO);
+ smap(RENDERPREVIEW);
+ smap(REDRAWIPO);
+ smap(REDRAWDATASELECT);
+ smap(REDRAWSEQ);
+ smap(REDRAWIMAGE);
+ smap(REDRAWOOPS);
+ smap(REDRAWIMASEL);
+ smap(AFTERIMASELIMA);
+ smap(AFTERIMASELGET);
+ smap(AFTERIMAWRITE);
+ smap(IMALEFTMOUSE);
+ smap(AFTERPIBREAD);
+ smap(REDRAWTEXT);
+ smap(REDRAWBUTSSCRIPT);
+ smap(REDRAWSOUND);
+ smap(REDRAWBUTSSOUND);
+ smap(REDRAWACTION);
+ smap(LEFTMOUSE);
+ smap(MIDDLEMOUSE);
+ smap(RIGHTMOUSE);
+ smap(MOUSEX);
+ smap(MOUSEY);
+ smap(TIMER0);
+ smap(TIMER1);
+ smap(TIMER2);
+ smap(TIMER3);
+ smap(KEYBD);
+ smap(RAWKEYBD);
+ smap(REDRAW);
+ smap(INPUTCHANGE);
+ smap(QFULL);
+ smap(WINFREEZE);
+ smap(WINTHAW);
+ smap(WINCLOSE);
+ smap(WINQUIT);
+ smap(Q_FIRSTTIME);
+ smap(AKEY);
+ smap(BKEY);
+ smap(CKEY);
+ smap(DKEY);
+ smap(EKEY);
+ smap(FKEY);
+ smap(GKEY);
+ smap(HKEY);
+ smap(IKEY);
+ smap(JKEY);
+ smap(KKEY);
+ smap(LKEY);
+ smap(MKEY);
+ smap(NKEY);
+ smap(OKEY);
+ smap(PKEY);
+ smap(QKEY);
+ smap(RKEY);
+ smap(SKEY);
+ smap(TKEY);
+ smap(UKEY);
+ smap(VKEY);
+ smap(WKEY);
+ smap(XKEY);
+ smap(YKEY);
+ smap(ZKEY);
+ smap(ZEROKEY);
+ smap(ONEKEY);
+ smap(TWOKEY);
+ smap(THREEKEY);
+ smap(FOURKEY);
+ smap(FIVEKEY);
+ smap(SIXKEY);
+ smap(SEVENKEY);
+ smap(EIGHTKEY);
+ smap(NINEKEY);
+ smap(CAPSLOCKKEY);
+ smap(LEFTCTRLKEY);
+ smap(LEFTALTKEY);
+ smap(RIGHTALTKEY);
+ smap(RIGHTCTRLKEY);
+ smap(RIGHTSHIFTKEY);
+ smap(LEFTSHIFTKEY);
+ smap(ESCKEY);
+ smap(TABKEY);
+ smap(RETKEY);
+ smap(SPACEKEY);
+ smap(LINEFEEDKEY);
+ smap(BACKSPACEKEY);
+ smap(DELKEY);
+ smap(SEMICOLONKEY);
+ smap(PERIODKEY);
+ smap(COMMAKEY);
+ smap(QUOTEKEY);
+ smap(ACCENTGRAVEKEY);
+ smap(MINUSKEY);
+ smap(SLASHKEY);
+ smap(BACKSLASHKEY);
+ smap(EQUALKEY);
+ smap(LEFTBRACKETKEY);
+ smap(RIGHTBRACKETKEY);
+ smap(LEFTARROWKEY);
+ smap(DOWNARROWKEY);
+ smap(RIGHTARROWKEY);
+ smap(UPARROWKEY);
+ smap(PAD0);
+ smap(PAD1);
+ smap(PAD2);
+ smap(PAD3);
+ smap(PAD4);
+ smap(PAD5);
+ smap(PAD6);
+ smap(PAD7);
+ smap(PAD8);
+ smap(PAD9);
+ smap(PADPERIOD);
+ smap(PADSLASHKEY);
+ smap(PADASTERKEY);
+ smap(PADMINUS);
+ smap(PADENTER);
+ smap(PADPLUSKEY);
+ smap(F1KEY);
+ smap(F2KEY);
+ smap(F3KEY);
+ smap(F4KEY);
+ smap(F5KEY);
+ smap(F6KEY);
+ smap(F7KEY);
+ smap(F8KEY);
+ smap(F9KEY);
+ smap(F10KEY);
+ smap(F11KEY);
+ smap(F12KEY);
+ smap(PAUSEKEY);
+ smap(INSERTKEY);
+ smap(HOMEKEY);
+ smap(PAGEUPKEY);
+ smap(PAGEDOWNKEY);
+ smap(ENDKEY);
+ smap(REDRAWBUTSCONSTRAINT);
+ smap(REDRAWNLA);
+ }
+ #undef smap
+}
diff --git a/source/blender/src/filesel.c b/source/blender/src/filesel.c
new file mode 100644
index 00000000000..7a63a7779a0
--- /dev/null
+++ b/source/blender/src/filesel.c
@@ -0,0 +1,2376 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 <math.h>
+
+#ifdef WIN32
+#include <io.h>
+#include <direct.h>
+#include "BLI_winstuff.h"
+#else
+#include <unistd.h>
+#include <sys/times.h>
+#endif
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include "MEM_guardedalloc.h"
+
+#include "BMF_Api.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+#include "BLI_linklist.h"
+#include "BLI_storage_types.h"
+#include "BLI_dynstr.h"
+
+#include "IMB_imbuf.h"
+
+#include "DNA_curve_types.h"
+#include "DNA_image_types.h"
+#include "DNA_ipo_types.h"
+#include "DNA_vfont_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_userdef_types.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_displist.h"
+#include "BKE_library.h"
+#include "BKE_curve.h"
+#include "BKE_font.h"
+#include "BKE_material.h"
+
+#include "BIF_gl.h"
+#include "BIF_interface.h"
+#include "BIF_toolbox.h"
+#include "BIF_mywindow.h"
+#include "BIF_editview.h"
+#include "BIF_space.h"
+#include "BIF_screen.h"
+
+#include "BLO_readfile.h"
+
+#include "BDR_editcurve.h"
+#include "BSE_filesel.h"
+#include "BSE_view.h"
+
+#include "mydevice.h"
+#include "blendef.h"
+#include "render.h"
+#include "interface.h"
+#include "nla.h"
+
+#if defined WIN32 || defined __BeOS
+ int fnmatch(){return 0;}
+#else
+ #include <fnmatch.h>
+#endif
+
+#ifndef WIN32
+#include <sys/param.h>
+#endif
+
+#define FILESELHEAD 60
+#define FILESEL_DY 16
+
+#define NOTACTIVE 0
+#define ACTIVATE 1
+#define INACTIVATE 2
+
+#define STARTSWITH(x, y) (strncmp(x, y, sizeof(x) - 1) == 0)
+
+static int is_a_library(SpaceFile *sfile, char *dir, char *group);
+static void do_library_append(SpaceFile *sfile);
+static void library_to_filelist(SpaceFile *sfile);
+static void filesel_select_objects(struct SpaceFile *sfile);
+static void active_file_object(struct SpaceFile *sfile);
+static int groupname_to_code(char *group);
+
+/* local globals */
+
+static rcti scrollrct, textrct, bar;
+static int filebuty1, filebuty2, page_ofs, collumwidth, selecting=0;
+static int filetoname= 0;
+static float pixels_to_ofs;
+static char otherdir[FILE_MAXDIR];
+static ScrArea *otherarea;
+
+/* FSMENU HANDLING */
+
+ /* FSMenuEntry's without paths indicate seperators */
+typedef struct _FSMenuEntry FSMenuEntry;
+struct _FSMenuEntry {
+ FSMenuEntry *next;
+
+ char *path;
+};
+
+static FSMenuEntry *fsmenu= 0, *lseperator= 0;
+
+int fsmenu_get_nentries(void)
+{
+ FSMenuEntry *fsme;
+ int count= 0;
+
+ for (fsme= fsmenu; fsme; fsme= fsme->next)
+ count++;
+
+ return count;
+}
+int fsmenu_is_entry_a_seperator(int idx)
+{
+ FSMenuEntry *fsme;
+
+ for (fsme= fsmenu; fsme && idx; fsme= fsme->next)
+ idx--;
+
+ return (fsme && !fsme->path)?1:0;
+}
+char *fsmenu_get_entry(int idx)
+{
+ FSMenuEntry *fsme;
+
+ for (fsme= fsmenu; fsme && idx; fsme= fsme->next)
+ idx--;
+
+ return fsme?fsme->path:NULL;
+}
+char *fsmenu_build_menu(void)
+{
+ DynStr *ds= BLI_dynstr_new();
+ FSMenuEntry *fsme;
+ char *menustr;
+
+ for (fsme= fsmenu; fsme; fsme= fsme->next) {
+ if (!fsme->path) {
+ /* ignore consecutive or trailing seperators */
+ if (fsme->next && fsme->next->path)
+ BLI_dynstr_append(ds, "%l|");
+ } else {
+ BLI_dynstr_append(ds, fsme->path);
+ if (fsme->next) BLI_dynstr_append(ds, "|");
+ }
+ }
+
+ menustr= BLI_dynstr_get_cstring(ds);
+ BLI_dynstr_free(ds);
+ return menustr;
+}
+void fsmenu_insert_entry(char *path, int sorted)
+{
+ FSMenuEntry *fsme, *prev;
+
+ if (lseperator) {
+ prev= lseperator;
+ fsme= lseperator->next;
+ } else {
+ prev= NULL;
+ fsme= fsmenu;
+ }
+ for (; fsme; prev= fsme, fsme= fsme->next) {
+ if (fsme->path) {
+ if (BLI_streq(path, fsme->path)) {
+ return;
+ } else if (sorted && strcmp(path, fsme->path)<0) {
+ break;
+ }
+ }
+ }
+
+ fsme= MEM_mallocN(sizeof(*fsme), "fsme");
+ fsme->path= BLI_strdup(path);
+
+ if (prev) {
+ fsme->next= prev->next;
+ prev->next= fsme;
+ } else {
+ fsme->next= fsmenu;
+ fsmenu= fsme;
+ }
+}
+void fsmenu_append_seperator(void)
+{
+ if (fsmenu) {
+ FSMenuEntry *fsme= fsmenu;
+
+ while (fsme->next) fsme= fsme->next;
+
+ lseperator= MEM_mallocN(sizeof(*fsme), "fsme");
+ lseperator->next= NULL;
+ lseperator->path= NULL;
+
+ fsme->next= lseperator;
+ }
+}
+void fsmenu_remove_entry(int idx)
+{
+ FSMenuEntry *prev= NULL, *fsme= fsmenu;
+
+ for (fsme= fsmenu; fsme && idx; prev= fsme, fsme= fsme->next)
+ if (fsme->path)
+ idx--;
+
+ if (fsme) {
+ if (prev) {
+ prev->next= fsme->next;
+ } else {
+ fsmenu= fsme->next;
+ }
+
+ MEM_freeN(fsme->path);
+ MEM_freeN(fsme);
+ }
+}
+void fsmenu_free(void)
+{
+ FSMenuEntry *fsme= fsmenu;
+
+ while (fsme) {
+ FSMenuEntry *n= fsme->next;
+
+ if (fsme->path) MEM_freeN(fsme->path);
+ MEM_freeN(fsme);
+
+ fsme= n;
+ }
+}
+
+/* ******************* SORT ******************* */
+
+static int compare_name(const void *a1, const void *a2)
+{
+ const struct direntry *entry1=a1, *entry2=a2;
+
+ /* type is gelijk aan stat.st_mode */
+
+ if (S_ISDIR(entry1->type)){
+ if (S_ISDIR(entry2->type)==0) return (-1);
+ } else{
+ if (S_ISDIR(entry2->type)) return (1);
+ }
+ if (S_ISREG(entry1->type)){
+ if (S_ISREG(entry2->type)==0) return (-1);
+ } else{
+ if (S_ISREG(entry2->type)) return (1);
+ }
+ if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) return (-1);
+ if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1);
+ return (strcasecmp(entry1->relname,entry2->relname));
+}
+
+static int compare_date(const void *a1, const void *a2)
+{
+ const struct direntry *entry1=a1, *entry2=a2;
+
+ /* type is gelijk aan stat.st_mode */
+
+ if (S_ISDIR(entry1->type)){
+ if (S_ISDIR(entry2->type)==0) return (-1);
+ } else{
+ if (S_ISDIR(entry2->type)) return (1);
+ }
+ if (S_ISREG(entry1->type)){
+ if (S_ISREG(entry2->type)==0) return (-1);
+ } else{
+ if (S_ISREG(entry2->type)) return (1);
+ }
+ if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) return (-1);
+ if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1);
+
+/*
+ if ( entry1->s.st_ctime < entry2->s.st_ctime) return 1;
+ if ( entry1->s.st_ctime > entry2->s.st_ctime) return -1;
+*/
+ if ( entry1->s.st_mtime < entry2->s.st_mtime) return 1;
+ if ( entry1->s.st_mtime > entry2->s.st_mtime) return -1;
+ else return strcasecmp(entry1->relname,entry2->relname);
+}
+
+static int compare_size(const void *a1, const void *a2)
+{
+ const struct direntry *entry1=a1, *entry2=a2;
+
+ /* type is gelijk aan stat.st_mode */
+
+ if (S_ISDIR(entry1->type)){
+ if (S_ISDIR(entry2->type)==0) return (-1);
+ } else{
+ if (S_ISDIR(entry2->type)) return (1);
+ }
+ if (S_ISREG(entry1->type)){
+ if (S_ISREG(entry2->type)==0) return (-1);
+ } else{
+ if (S_ISREG(entry2->type)) return (1);
+ }
+ if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) return (-1);
+ if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1);
+
+ if ( entry1->s.st_size < entry2->s.st_size) return 1;
+ if ( entry1->s.st_size > entry2->s.st_size) return -1;
+ else return strcasecmp(entry1->relname,entry2->relname);
+}
+
+
+/* **************************************** */
+
+void clear_global_filesel_vars()
+{
+ selecting= 0;
+}
+
+
+void filesel_statistics(SpaceFile *sfile, int *totfile, int *selfile, float *totlen, float *sellen)
+{
+ int a, len;
+
+ *totfile= *selfile= 0;
+ *totlen= *sellen= 0;
+
+ if(sfile->filelist==0) return;
+
+ for(a=0; a<sfile->totfile; a++) {
+ if( (sfile->filelist[a].type & S_IFDIR)==0 ) {
+ (*totfile) ++;
+
+ len = sfile->filelist[a].s.st_size;
+ (*totlen) += (len/1048576.0);
+
+ if(sfile->filelist[a].flags & ACTIVE) {
+ (*selfile) ++;
+ (*sellen) += (len/1048576.0);
+ }
+ }
+ }
+}
+
+/* *************** HULPFUNKTIES ******************* */
+
+/* This is a really ugly function... its purpose is to
+ * take the space file name and clean it up, replacing
+ * excess file entry stuff (like /tmp/../tmp/../)
+ */
+
+void checkdir(char *dir)
+{
+ short a;
+ char *start, *eind;
+ char tmp[FILE_MAXDIR+FILE_MAXFILE];
+
+ BLI_make_file_string(G.sce, tmp, dir, "");
+ strcpy(dir, tmp);
+
+#ifdef WIN32
+ if(dir[0]=='.') { /* komt voor, o.a. bij FILE_MAIN */
+ dir[0]= '\\';
+ dir[1]= 0;
+ return;
+ }
+
+ while (start = strstr(dir, "\\..\\")) {
+ eind = start + strlen("\\..\\") - 1;
+ a = start-dir-1;
+ while (a>0) {
+ if (dir[a] == '\\') break;
+ a--;
+ }
+ strcpy(dir+a,eind);
+ }
+
+ while (start = strstr(dir,"\\.\\")){
+ eind = start + strlen("\\.\\") - 1;
+ strcpy(start,eind);
+ }
+
+ while (start = strstr(dir,"\\\\" )){
+ eind = start + strlen("\\\\") - 1;
+ strcpy(start,eind);
+ }
+
+ if(a = strlen(dir)){ /* eerst alle '\\' weghalen aan het eind */
+ while(a>0 && dir[a-1] == '\\'){
+ a--;
+ dir[a] = 0;
+ }
+ }
+
+ strcat(dir, "\\");
+#else
+ if(dir[0]=='.') { /* komt voor, o.a. bij FILE_MAIN */
+ dir[0]= '/';
+ dir[1]= 0;
+ return;
+ }
+
+ while ( (start = strstr(dir, "/../")) ) {
+ eind = start + strlen("/../") - 1;
+ a = start-dir-1;
+ while (a>0) {
+ if (dir[a] == '/') break;
+ a--;
+ }
+ strcpy(dir+a,eind);
+ }
+
+ while ( (start = strstr(dir,"/./")) ){
+ eind = start + strlen("/./") - 1;
+ strcpy(start,eind);
+ }
+
+ while ( (start = strstr(dir,"//" )) ){
+ eind = start + strlen("//") - 1;
+ strcpy(start,eind);
+ }
+
+ if( (a = strlen(dir)) ){ /* eerst alle '/' weghalen aan het eind */
+ while(dir[a-1] == '/'){
+ a--;
+ dir[a] = 0;
+ if (a<=0) break;
+ }
+ }
+
+ strcat(dir, "/");
+#endif
+}
+
+void test_flags_file(SpaceFile *sfile)
+{
+ struct direntry *file;
+ int num;
+
+ file= sfile->filelist;
+
+ for(num=0; num<sfile->totfile; num++, file++) {
+ file->flags= 0;
+ file->type= file->s.st_mode; /* restore het geknoei van hieronder */
+
+ /* Don't check extensions for directories */
+ if (file->type&S_IFDIR)
+ continue;
+
+ if(sfile->type==FILE_BLENDER || sfile->type==FILE_LOADLIB) {
+ if(BLO_has_bfile_extension(file->relname)) {
+ file->flags |= BLENDERFILE;
+ if(sfile->type==FILE_LOADLIB) {
+ file->type &= ~S_IFMT;
+ file->type |= S_IFDIR;
+ }
+ }
+ else if(BLI_testextensie(file->relname, ".psx")) {
+ file->flags |= PSXFILE;
+ }
+ } else if (sfile->type==FILE_SPECIAL){
+ if(BLI_testextensie(file->relname, ".jpg") ||
+ BLI_testextensie(file->relname, ".tga") ||
+ BLI_testextensie(file->relname, ".rgb") ||
+ BLI_testextensie(file->relname, ".png") ||
+ BLI_testextensie(file->relname, ".sgi")) {
+ file->flags |= IMAGEFILE;
+ }
+ else if(BLI_testextensie(file->relname, ".avi") ||
+ BLI_testextensie(file->relname, ".mv")) {
+ file->flags |= MOVIEFILE;
+ }
+ }
+ }
+}
+
+
+void sort_filelist(SpaceFile *sfile)
+{
+ struct direntry *file;
+ int num;/* , act= 0; */
+
+ switch(sfile->sort) {
+ case FILE_SORTALPHA:
+ qsort(sfile->filelist, sfile->totfile, sizeof(struct direntry), compare_name);
+ break;
+ case FILE_SORTDATE:
+ qsort(sfile->filelist, sfile->totfile, sizeof(struct direntry), compare_date);
+ break;
+ case FILE_SORTSIZE:
+ qsort(sfile->filelist, sfile->totfile, sizeof(struct direntry), compare_size);
+ break;
+ case FILE_SORTEXTENS:
+ qsort(sfile->filelist, sfile->totfile, sizeof(struct direntry), compare_name);
+ break;
+ }
+
+ sfile->act= -1;
+
+ file= sfile->filelist;
+ for(num=0; num<sfile->totfile; num++, file++) {
+ file->flags &= ~HILITE;
+ }
+
+}
+
+void read_dir(SpaceFile *sfile)
+{
+ int num, len;
+ char wdir[FILE_MAXDIR];
+
+ /* sfile->act wordt gebruikt o.a. bij databrowse: dubbele namen van library objecten */
+ sfile->act= -1;
+
+ if(sfile->type==FILE_MAIN) {
+ main_to_filelist(sfile);
+ return;
+ }
+ else if(sfile->type==FILE_LOADLIB) {
+ library_to_filelist(sfile);
+ if(sfile->libfiledata) return;
+ }
+
+ BLI_hide_dot_files(sfile->flag & FILE_HIDE_DOT);
+
+ BLI_getwdN(wdir);
+ sfile->totfile= BLI_getdir(sfile->dir, &(sfile->filelist));
+ chdir(wdir);
+
+ if(sfile->sort!=FILE_SORTALPHA) sort_filelist(sfile);
+
+ sfile->maxnamelen= 0;
+
+ for (num=0; num<sfile->totfile; num++) {
+
+ len = BMF_GetStringWidth(G.font, sfile->filelist[num].relname);
+ if (len > sfile->maxnamelen) sfile->maxnamelen = len;
+
+ if(filetoname) {
+ if(strcmp(sfile->file, sfile->filelist[num].relname)==0) {
+
+ sfile->ofs= num-( sfile->collums*(curarea->winy-FILESELHEAD-20)/(2*FILESEL_DY));
+ filetoname= 0;
+ }
+ }
+ }
+ test_flags_file(sfile);
+
+ filetoname= 0;
+}
+
+void freefilelist(SpaceFile *sfile)
+{
+ int num;
+
+ num= sfile->totfile-1;
+
+ if (sfile->filelist==0) return;
+
+ for(; num>=0; num--){
+ free(sfile->filelist[num].relname);
+
+ if (sfile->filelist[num].string) free(sfile->filelist[num].string);
+ }
+ free(sfile->filelist);
+ sfile->filelist= 0;
+}
+
+static void split_sfile(SpaceFile *sfile, char *s1)
+{
+ char string[FILE_MAXDIR+FILE_MAXFILE], dir[FILE_MAXDIR], file[FILE_MAXFILE];
+
+ strcpy(string, s1);
+
+ BLI_split_dirfile(string, dir, file);
+
+ if(sfile->filelist) {
+ if(strcmp(dir, sfile->dir)!=0) {
+ freefilelist(sfile);
+ }
+ else test_flags_file(sfile);
+ }
+ strcpy(sfile->file, file);
+ BLI_make_file_string(G.sce, sfile->dir, dir, "");
+}
+
+
+void parent(SpaceFile *sfile)
+{
+ short a;
+ char *dir;
+
+ /* als databrowse: geen parent */
+ if(sfile->type==FILE_MAIN && sfile->returnfunc) return;
+
+ dir= sfile->dir;
+
+#ifdef WIN32
+ if(a = strlen(dir)) { /* eerst alle '/' weghalen aan het eind */
+ while(dir[a-1] == '\\') {
+ a--;
+ dir[a] = 0;
+ if (a<=0) break;
+ }
+ }
+ if(a = strlen(dir)) { /* daarna alles weghalen tot aan '/' */
+ while(dir[a-1] != '\\') {
+ a--;
+ dir[a] = 0;
+ if (a<=0) break;
+ }
+ }
+ if (a = strlen(dir)) {
+ if (dir[a-1] != '\\') strcat(dir,"\\");
+ }
+ else if(sfile->type!=FILE_MAIN) strcpy(dir,"\\");
+#else
+ if( (a = strlen(dir)) ) { /* eerst alle '/' weghalen aan het eind */
+ while(dir[a-1] == '/') {
+ a--;
+ dir[a] = 0;
+ if (a<=0) break;
+ }
+ }
+ if( (a = strlen(dir)) ) { /* daarna alles weghalen tot aan '/' */
+ while(dir[a-1] != '/') {
+ a--;
+ dir[a] = 0;
+ if (a<=0) break;
+ }
+ }
+ if ( (a = strlen(dir)) ) {
+ if (dir[a-1] != '/') strcat(dir,"/");
+ }
+ else if(sfile->type!=FILE_MAIN) strcpy(dir,"/");
+#endif
+
+ /* to be sure */
+ BLI_make_exist(sfile->dir);
+
+ freefilelist(sfile);
+ sfile->ofs= 0;
+ scrarea_queue_winredraw(curarea);
+}
+
+void swapselect_file(SpaceFile *sfile)
+{
+ struct direntry *file;
+ int num, act= 0;
+
+ file= sfile->filelist;
+ for(num=0; num<sfile->totfile; num++, file++) {
+ if(file->flags & ACTIVE) {
+ act= 1;
+ break;
+ }
+ }
+ file= sfile->filelist+2;
+ for(num=2; num<sfile->totfile; num++, file++) {
+ if(act) file->flags &= ~ACTIVE;
+ else file->flags |= ACTIVE;
+ }
+}
+
+static int find_active_file(SpaceFile *sfile, short x, short y)
+{
+ int ofs;
+
+ if(y > textrct.ymax) y= textrct.ymax;
+ if(y <= textrct.ymin) y= textrct.ymin+1;
+
+ ofs= (x-textrct.xmin)/collumwidth;
+ if(ofs<0) ofs= 0;
+ ofs*= (textrct.ymax-textrct.ymin);
+
+ return sfile->ofs+ (ofs+textrct.ymax-y)/FILESEL_DY;
+
+}
+
+
+/* ********************** DRAW ******************************* */
+
+static void calc_file_rcts(SpaceFile *sfile)
+{
+ int tot, h, len;
+ float fac, start, totfile;
+
+ scrollrct.xmin= 15;
+ scrollrct.xmax= 35;
+ scrollrct.ymin= 10;
+ scrollrct.ymax= curarea->winy-10-FILESELHEAD;
+
+ textrct.xmin= scrollrct.xmax+10;
+ textrct.xmax= curarea->winx-10;
+ textrct.ymin= scrollrct.ymin;
+ textrct.ymax= scrollrct.ymax;
+
+ if(textrct.xmax-textrct.xmin <60) textrct.xmax= textrct.xmin+60;
+
+ len= (textrct.ymax-textrct.ymin) % FILESEL_DY;
+ textrct.ymin+= len;
+ scrollrct.ymin+= len;
+
+ filebuty1= curarea->winy-FILESELHEAD;
+ filebuty2= filebuty1+FILESELHEAD/2 -6;
+
+
+ /* aantal kolommen */
+ len= sfile->maxnamelen+25;
+
+ if(sfile->type==FILE_MAIN) len+= 100;
+ else if(sfile->flag & FILE_SHOWSHORT) len+= 100;
+ else len+= 380;
+
+ sfile->collums= (textrct.xmax-textrct.xmin)/len;
+
+ if(sfile->collums<1) sfile->collums= 1;
+ else if(sfile->collums>8) sfile->collums= 8;
+
+ if((U.flag & FSCOLLUM)==0) if(sfile->type!=FILE_MAIN) sfile->collums= 1;
+
+ collumwidth= (textrct.xmax-textrct.xmin)/sfile->collums;
+
+
+ totfile= sfile->totfile + 0.5;
+
+ tot= FILESEL_DY*totfile;
+ if(tot) fac= ((float)sfile->collums*(scrollrct.ymax-scrollrct.ymin))/( (float)tot);
+ else fac= 1.0;
+
+ if(sfile->ofs<0) sfile->ofs= 0;
+
+ if(tot) start= ( (float)sfile->ofs)/(totfile);
+ else start= 0.0;
+ if(fac>1.0) fac= 1.0;
+
+ if(start+fac>1.0) {
+ sfile->ofs= ceil((1.0-fac)*totfile);
+ start= ( (float)sfile->ofs)/(totfile);
+ fac= 1.0-start;
+ }
+
+ bar.xmin= scrollrct.xmin+2;
+ bar.xmax= scrollrct.xmax-2;
+ h= (scrollrct.ymax-scrollrct.ymin)-4;
+ bar.ymax= scrollrct.ymax-2- start*h;
+ bar.ymin= bar.ymax- fac*h;
+
+ pixels_to_ofs= (totfile)/(float)(h+3);
+ page_ofs= fac*totfile;
+}
+
+int filescrollselect= 0;
+
+static void draw_filescroll(SpaceFile *sfile)
+{
+
+ if(scrollrct.ymin+10 >= scrollrct.ymax) return;
+
+ cpack(0x707070);
+ glRecti(scrollrct.xmin, scrollrct.ymin, scrollrct.xmax, scrollrct.ymax);
+
+ uiEmboss(scrollrct.xmin, scrollrct.ymin, scrollrct.xmax, scrollrct.ymax, 1);
+
+ cpack(0x909090);
+ glRecti(bar.xmin+2, bar.ymin+2, bar.xmax-2, bar.ymax-2);
+
+ uiEmboss(bar.xmin+2, bar.ymin+2, bar.xmax-2, bar.ymax-2, filescrollselect);
+
+}
+
+static void regelrect(unsigned int col, int x, int y)
+{
+ cpack(col);
+ glRects(x-17, y-3, x+collumwidth-21, y+11);
+
+}
+
+static void printregel(SpaceFile *sfile, struct direntry *files, int x, int y)
+{
+ unsigned int boxcol=0;
+ char *s;
+
+ switch(files->flags & (HILITE + ACTIVE)) {
+ case HILITE+ACTIVE:
+ boxcol= (0xC09090);
+ break;
+ case HILITE:
+ boxcol= (0x909090);
+ break;
+ case ACTIVE:
+ boxcol= (0xB08080);
+ break;
+ }
+
+ if(boxcol) {
+ regelrect(boxcol, x, y);
+ }
+
+ if(files->flags & BLENDERFILE) {
+ cpack(0xA0A0);
+ glRects(x-14, y, x-8, y+7);
+ }
+ else if(files->flags & PSXFILE) {
+ cpack(0xA060B0);
+ glRects(x-14, y, x-8, y+7);
+ }
+ else if(files->flags & IMAGEFILE) {
+ cpack(0xF08040);
+ glRects(x-14, y, x-8, y+7);
+ }
+ else if(files->flags & MOVIEFILE) {
+ cpack(0x70A070);
+ glRects(x-14, y, x-8, y+7);
+ }
+
+ if(S_ISDIR(files->type)) cpack(0xFFFFFF);
+ else cpack(0x0);
+
+ s = files->string;
+ if(s) {
+ glRasterPos2i(x, y);
+ BMF_DrawString(G.font, files->relname);
+
+ x += sfile->maxnamelen + 100;
+
+ glRasterPos2i(x - BMF_GetStringWidth(G.font, files->size), y);
+ BMF_DrawString(G.font, files->size);
+
+ if(sfile->flag & FILE_SHOWSHORT) return;
+
+#ifndef WIN32
+ /* rwx rwx rwx */
+ x += 20; glRasterPos2i(x, y);
+ BMF_DrawString(G.font, files->mode1);
+
+ x += 30; glRasterPos2i(x, y);
+ BMF_DrawString(G.font, files->mode2);
+
+ x += 30; glRasterPos2i(x, y);
+ BMF_DrawString(G.font, files->mode3);
+
+ /* owner time date */
+ x += 30; glRasterPos2i(x, y);
+ BMF_DrawString(G.font, files->owner);
+#endif
+
+ x += 60; glRasterPos2i(x, y);
+ BMF_DrawString(G.font, files->time);
+
+ x += 50; glRasterPos2i(x, y);
+ BMF_DrawString(G.font, files->date);
+ }
+ else {
+ glRasterPos2i(x, y);
+ BMF_DrawString(G.font, files->relname);
+
+ if(files->nr) { /* extra info */
+ x+= sfile->maxnamelen+20;
+ glRasterPos2i(x, y);
+ BMF_DrawString(G.font, files->extra);
+ }
+ }
+}
+
+
+static int calc_filesel_regel(SpaceFile *sfile, int nr, int *valx, int *valy)
+{
+ /* sco van de de regel */
+ int val, coll;
+
+ nr-= sfile->ofs;
+
+ /* aantal regels in de hoogte */
+ val= (textrct.ymax-textrct.ymin)/FILESEL_DY;
+ coll= nr/val;
+ nr -= coll*val;
+
+ *valy= textrct.ymax-FILESEL_DY+3 - nr*FILESEL_DY;
+ *valx= coll*collumwidth + textrct.xmin+20;
+
+ if(nr<0 || coll > sfile->collums) return 0;
+ return 1;
+}
+
+static void set_active_file(SpaceFile *sfile, int act)
+{
+ struct direntry *file;
+ int num, redraw= 0, newflag;
+ int old=0, newi=0;
+
+ file= sfile->filelist;
+ if(file==0) return;
+
+ for(num=0; num<sfile->totfile; num++, file++) {
+ if(num==act) {
+
+ if(selecting && num>1) {
+ newflag= HILITE | (file->flags & ~ACTIVE);
+ if(selecting==ACTIVATE) newflag |= ACTIVE;
+
+ if(file->flags != newflag) redraw|= 1;
+ file->flags= newflag;
+ }
+ else {
+ if(file->flags & HILITE);
+ else {
+ file->flags |= HILITE;
+ redraw|= 2;
+ newi= num;
+ }
+ }
+ }
+ else {
+ if(file->flags & HILITE) {
+ file->flags &= ~HILITE;
+ redraw|= 2;
+ old= num;
+ }
+ }
+
+ }
+
+ if(redraw==2) {
+ int x, y;
+
+ glDrawBuffer(GL_FRONT);
+
+ glScissor(curarea->winrct.xmin, curarea->winrct.ymin, curarea->winx-12, curarea->winy);
+
+ if( calc_filesel_regel(sfile, old, &x, &y) ) {
+ regelrect(0x717171, x, y);
+ printregel(sfile, sfile->filelist+old, x, y);
+ }
+ if( calc_filesel_regel(sfile, newi, &x, &y) ) {
+ printregel(sfile, sfile->filelist+newi, x, y);
+ }
+
+ glScissor(curarea->winrct.xmin, curarea->winrct.ymin, curarea->winx, curarea->winy);
+
+ glFinish(); /* for geforce, to show it in the frontbuffer */
+ glDrawBuffer(GL_BACK);
+ }
+ else if(redraw) {
+ scrarea_queue_winredraw(curarea);
+ }
+}
+
+
+static void draw_filetext(SpaceFile *sfile)
+{
+ struct direntry *files;
+ int a, x, y;
+ short mval[2];
+
+ if(textrct.ymin+10 >= textrct.ymax) return;
+
+
+ /* kader */
+ cpack(0x717171);
+ glRecti(textrct.xmin, textrct.ymin, textrct.xmax, textrct.ymax);
+
+ /* kolommen */
+ x= textrct.xmin+collumwidth;
+ for(a=1; a<sfile->collums; a++, x+= collumwidth) {
+ cpack(0x303030);
+ sdrawline(x, textrct.ymin, x, textrct.ymax);
+ cpack(0xB0B0B0);
+ sdrawline(x+1, textrct.ymin, x+1, textrct.ymax);
+ }
+
+ if(sfile->filelist==0) return;
+
+ /* test: als muis niet in area staat: de HILITE wissen */
+ getmouseco_areawin(mval);
+
+ if(mval[0]<0 || mval[0]>curarea->winx) {
+ files= sfile->filelist+sfile->ofs;
+ for(a= sfile->ofs; a<sfile->totfile; a++, files++) files->flags &= ~HILITE;
+ }
+
+ files= sfile->filelist+sfile->ofs;
+ for(a= sfile->ofs; a<sfile->totfile; a++, files++) {
+
+ if( calc_filesel_regel(sfile, a, &x, &y)==0 ) break;
+
+ printregel(sfile, files, x, y);
+ }
+
+ /* wissen tekenfoutjes, tekst teveel aan de rechterkant: */
+ uiEmboss(textrct.xmin, textrct.ymin, textrct.xmax, textrct.ymax, 1);
+
+ glColor3f(.5625, .5625, .5625);
+ glRecti(textrct.xmax+2, textrct.ymin, textrct.xmax+10, textrct.ymax);
+}
+
+void drawfilespace()
+{
+ SpaceFile *sfile;
+ uiBlock *block;
+ int act, loadbutton;
+ short mval[2];
+ char name[20];
+ char *menu;
+
+ myortho2(-0.5, curarea->winrct.xmax-curarea->winrct.xmin-0.5, -0.5, curarea->winrct.ymax-curarea->winrct.ymin-0.5);
+
+ glClearColor(.56, .56, .56, 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ sfile= curarea->spacedata.first;
+ if(sfile->filelist==0) {
+ read_dir(sfile);
+
+ calc_file_rcts(sfile);
+
+ /* act berekenen */
+ getmouseco_areawin(mval);
+ act= find_active_file(sfile, mval[0], mval[1]);
+ if(act>=0 && act<sfile->totfile)
+ sfile->filelist[act].flags |= HILITE;
+ }
+ else calc_file_rcts(sfile);
+
+ /* HEADER */
+ sprintf(name, "win %d", curarea->win);
+ block= uiNewBlock(&curarea->uiblocks, name, UI_EMBOSSF, UI_HELV, curarea->win);
+
+ uiSetButLock( sfile->type==FILE_MAIN && sfile->returnfunc, NULL);
+
+ /* space available for load/save buttons? */
+ loadbutton= MAX2(80, 20+BMF_GetStringWidth(G.font, sfile->title));
+ if(textrct.xmax-textrct.xmin > loadbutton+20) {
+ if(sfile->title[0]==0) loadbutton= 0;
+ }
+ else loadbutton= 0;
+
+ uiDefBut(block, TEX, 1,"", textrct.xmin, filebuty1, textrct.xmax-textrct.xmin-loadbutton, 21, sfile->file, 0.0, (float)FILE_MAXFILE-1, 0, 0, "");
+ uiDefBut(block, TEX, 2,"", textrct.xmin, filebuty2, textrct.xmax-textrct.xmin-loadbutton, 21, sfile->dir, 0.0, (float)FILE_MAXFILE-1, 0, 0, "");
+ if(loadbutton) {
+ uiSetCurFont(block, UI_HELV);
+ uiDefBut(block, BUT, 5, sfile->title, textrct.xmax-loadbutton, filebuty2, loadbutton, 21, sfile->dir, 0.0, (float)FILE_MAXFILE-1, 0, 0, "");
+ uiDefBut(block, BUT, 6, "Cancel", textrct.xmax-loadbutton, filebuty1, loadbutton, 21, sfile->file, 0.0, (float)FILE_MAXFILE-1, 0, 0, "");
+ }
+
+ menu= fsmenu_build_menu();
+ uiDefButS(block, MENU, 3, menu, scrollrct.xmin, filebuty1, scrollrct.xmax-scrollrct.xmin, 21, &sfile->menu, 0, 0, 0, 0, "");
+ MEM_freeN(menu);
+
+ uiDefBut(block, BUT, 4, "P", scrollrct.xmin, filebuty2, scrollrct.xmax-scrollrct.xmin, 21, 0, 0, 0, 0, 0, "Move to the parent directory (PKEY)");
+
+ draw_filescroll(sfile);
+ draw_filetext(sfile);
+
+ /* andere diskfree etc ? */
+ scrarea_queue_headredraw(curarea);
+
+ uiDrawBlock(block);
+
+ curarea->win_swap= WIN_BACK_OK;
+}
+
+static void do_filescroll(SpaceFile *sfile)
+{
+ short mval[2], oldy, yo;
+
+ calc_file_rcts(sfile);
+
+ filescrollselect= 1;
+ /* voor mooiigheid */
+
+ glDrawBuffer(GL_FRONT);
+ draw_filescroll(sfile);
+ glDrawBuffer(GL_BACK);
+
+ getmouseco_areawin(mval);
+ oldy= yo= mval[1];
+
+ while(get_mbut()&L_MOUSE) {
+ getmouseco_areawin(mval);
+
+ if(yo!=mval[1]) {
+ int dy= floor(0.5+((float)(oldy-mval[1]))*pixels_to_ofs);
+
+ if(dy) {
+ sfile->ofs+= dy;
+ if(sfile->ofs<0) {
+ sfile->ofs= 0;
+ oldy= mval[1];
+ }
+ else oldy= floor(0.5+ (float)oldy - (float)dy/pixels_to_ofs);
+
+ scrarea_do_windraw(curarea);
+ screen_swapbuffers();
+
+ }
+
+ yo= mval[1];
+ }
+ else BIF_wait_for_statechange();
+ }
+ filescrollselect= 0;
+
+ /* voor mooiigheid */
+ glDrawBuffer(GL_FRONT);
+ draw_filescroll(sfile);
+ glDrawBuffer(GL_BACK);
+
+}
+
+void activate_fileselect(int type, char *title, char *file, void (*func)(char *))
+{
+ SpaceFile *sfile;
+ char group[24], name[FILE_MAXDIR], temp[FILE_MAXDIR];
+
+ if(curarea==0) return;
+ if(curarea->win==0) return;
+
+ newspace(curarea, SPACE_FILE);
+ scrarea_queue_winredraw(curarea);
+
+ /* is misschien dubbelop, voor geval area al SPACE_FILE is met andere filename */
+ addqueue(curarea->headwin, CHANGED, 1);
+
+
+ name[2]= 0;
+ strcpy(name, file);
+
+ sfile= curarea->spacedata.first;
+ /* sfile wants a (*)(short), but get (*)(char*) */
+ sfile->returnfunc= func;
+ sfile->type= type;
+ sfile->ofs= 0;
+ /* sfile->act wordt gebruikt bij databrowse: dubbele namen van library objecten */
+ sfile->act= -1;
+
+ if(BLI_convertstringcode(name, G.sce, G.scene->r.cfra)) sfile->flag |= FILE_STRINGCODE;
+ else sfile->flag &= ~FILE_STRINGCODE;
+
+ if(type==FILE_MAIN) {
+ char *groupname;
+
+ strcpy(sfile->file, name+2);
+
+ groupname = BLO_idcode_to_name( GS(name) );
+ if (groupname) {
+ strcpy(sfile->dir, groupname);
+ strcat(sfile->dir, "/");
+ }
+
+ /* alles vrijgeven */
+ if(sfile->libfiledata) BLO_blendhandle_close(sfile->libfiledata);
+ sfile->libfiledata= 0;
+
+ freefilelist(sfile);
+ }
+ else if(type==FILE_LOADLIB) {
+ strcpy(sfile->dir, name);
+ if( is_a_library(sfile, temp, group) ) {
+ /* dit geval is om een reload van library-filelist te veroorzaken */
+ if(sfile->libfiledata==0) {
+ freefilelist(sfile);
+ }
+ }
+ else {
+ split_sfile(sfile, name);
+ if(sfile->libfiledata) BLO_blendhandle_close(sfile->libfiledata);
+ sfile->libfiledata= 0;
+ }
+ }
+ else { /* FILE_BLENDER */
+ split_sfile(sfile, name); /* test ook de filelist */
+
+ /* vrijgeven: filelist en libfiledata kloppen niet meer */
+ if(sfile->libfiledata) BLO_blendhandle_close(sfile->libfiledata);
+ sfile->libfiledata= 0;
+ }
+ BLI_strncpy(sfile->title, title, sizeof(sfile->title));
+ filetoname= 1;
+}
+
+void activate_imageselect(int type, char *title, char *file, void (*func)(char *))
+{
+ SpaceImaSel *simasel;
+ char dir[FILE_MAXDIR], name[FILE_MAXFILE];
+
+ if(curarea==0) return;
+ if(curarea->win==0) return;
+
+ newspace(curarea, SPACE_IMASEL);
+
+ /* is misschien dubbelop, voor geval area al SPACE_FILE is met andere filename */
+ addqueue(curarea->headwin, CHANGED, 1);
+ addqueue(curarea->win, CHANGED, 1);
+
+ name[2]= 0;
+ strcpy(name, file);
+
+ simasel= curarea->spacedata.first;
+ simasel->returnfunc= func;
+
+ if(BLI_convertstringcode(name, G.sce, G.scene->r.cfra)) simasel->mode |= IMS_STRINGCODE;
+ else simasel->mode &= ~IMS_STRINGCODE;
+
+ BLI_split_dirfile(name, dir, simasel->file);
+ if(strcmp(dir, simasel->dir)!=0) simasel->fase= 0;
+ strcpy(simasel->dir, dir);
+
+ BLI_strncpy(simasel->title, title, sizeof(simasel->title));
+
+
+
+ /* filetoname= 1; */
+}
+
+
+void activate_databrowse(ID *id, int idcode, int fromcode, int retval, short *menup, void (*func)(unsigned short))
+{
+ ListBase *lb;
+ SpaceFile *sfile;
+ char str[32];
+
+ if(id==0) {
+ lb= wich_libbase(G.main, idcode);
+ id= lb->first;
+ }
+
+ if(id) strcpy(str, id->name);
+ else return;
+
+ activate_fileselect(FILE_MAIN, "SELECT DATABLOCK", str, (void (*) (char*))func);
+
+ sfile= curarea->spacedata.first;
+ sfile->retval= retval;
+ sfile->ipotype= fromcode;
+ sfile->menup= menup;
+}
+
+void filesel_prevspace()
+{
+ SpaceFile *sfile;
+
+ sfile= curarea->spacedata.first;
+ if(sfile->next) {
+
+ BLI_remlink(&curarea->spacedata, sfile);
+ BLI_addtail(&curarea->spacedata, sfile);
+
+ sfile= curarea->spacedata.first;
+ newspace(curarea, sfile->spacetype);
+ }
+ else newspace(curarea, SPACE_INFO);
+}
+
+static int countselect(SpaceFile *sfile)
+{
+ int a, count=0;
+
+ for(a=0; a<sfile->totfile; a++) {
+ if(sfile->filelist[a].flags & ACTIVE) {
+ count++;
+ }
+ }
+ return count;
+}
+
+static int getotherdir(void)
+{
+ ScrArea *sa;
+ SpaceFile *sfile=0;
+
+ sa= G.curscreen->areabase.first;
+ while(sa) {
+ if(sa!=curarea) {
+ if(sa->spacetype==SPACE_FILE) {
+
+ /* al een gevonden */
+ if(sfile) return 0;
+
+ sfile= sa->spacedata.first;
+
+ if(sfile->type & FILE_UNIX) {
+ otherarea= sa;
+ BLI_make_file_string(G.sce, otherdir, sfile->dir, "");
+ }
+ else sfile= 0;
+ }
+ }
+ sa= sa->next;
+ }
+ if(sfile) return 1;
+ return 0;
+}
+
+static void reread_other_fs(void)
+{
+ SpaceFile *sfile;
+
+ /* oppassen: alleen aanroepen als getotherdir goed is afgelopen */
+
+ sfile= otherarea->spacedata.first;
+ freefilelist(sfile);
+ scrarea_queue_winredraw(otherarea);
+}
+
+
+void free_filesel_spec(char *dir)
+{
+ /* alle filesels met 'dir' worden vrijgegeven */
+ bScreen *sc;
+
+ sc= G.main->screen.first;
+ while(sc) {
+ ScrArea *sa= sc->areabase.first;
+ while(sa) {
+ SpaceLink *sl= sa->spacedata.first;
+ while(sl) {
+ if(sl->spacetype==SPACE_FILE) {
+ SpaceFile *sfile= (SpaceFile*) sl;
+ if (BLI_streq(sfile->dir, dir)) {
+ freefilelist(sfile);
+ }
+ }
+ sl= sl->next;
+ }
+ sa= sa->next;
+ }
+ sc= sc->id.next;
+ }
+}
+
+
+static void filesel_execute(SpaceFile *sfile)
+{
+ struct direntry *files;
+ char name[FILE_MAXDIR];
+ int a;
+
+ filesel_prevspace();
+
+ if(sfile->type==FILE_LOADLIB) {
+ do_library_append(sfile);
+
+ allqueue(REDRAWALL, 1);
+ }
+ else if(sfile->returnfunc) {
+ fsmenu_insert_entry(sfile->dir, 1);
+
+ if(sfile->type==FILE_MAIN) {
+ if (sfile->menup) {
+ if(sfile->act>=0) {
+ if(sfile->filelist) {
+ files= sfile->filelist+sfile->act;
+ *sfile->menup= files->nr;
+ }
+ else *sfile->menup= sfile->act+1;
+ }
+ else {
+ *sfile->menup= -1;
+ for(a=0; a<sfile->totfile; a++) {
+ if( strcmp(sfile->filelist[a].relname, sfile->file)==0) {
+ *sfile->menup= a+1;
+ break;
+ }
+ }
+ }
+ }
+ sfile->returnfunc((char*) sfile->retval);
+ }
+ else {
+ if(strncmp(sfile->title, "SAVE", 4)==0) free_filesel_spec(sfile->dir);
+
+ strcpy(name, sfile->dir);
+ strcat(name, sfile->file);
+
+ if(sfile->flag & FILE_STRINGCODE) BLI_makestringcode(G.sce, name);
+
+ sfile->returnfunc(name);
+ }
+ }
+}
+
+static void do_filesel_buttons(short event, SpaceFile *sfile)
+{
+ char butname[FILE_MAXDIR];
+
+ if (event == 1) {
+ if (strchr(sfile->file, '*') || strchr(sfile->file, '?') || strchr(sfile->file, '[')) {
+ int i, match = FALSE;
+
+ for (i = 2; i < sfile->totfile; i++) {
+ if (fnmatch(sfile->file, sfile->filelist[i].relname, 0) == 0) {
+ sfile->filelist[i].flags |= ACTIVE;
+ match = TRUE;
+ }
+ }
+ if (match) strcpy(sfile->file, "");
+ if(sfile->type==FILE_MAIN) filesel_select_objects(sfile);
+ scrarea_queue_winredraw(curarea);
+ }
+ }
+ else if(event== 2) {
+ /* reuse the butname variable */
+ checkdir(sfile->dir);
+
+ BLI_make_file_string(G.sce, butname, sfile->dir, "");
+ /* strip the trailing slash if its a real dir */
+ if (strlen(butname)!=1)
+ butname[strlen(butname)-1]=0;
+
+ if(sfile->type & FILE_UNIX) {
+ if (!BLI_exists(butname)) {
+ if (okee("Makedir")) {
+ BLI_recurdir_fileops(butname);
+ if (!BLI_exists(butname)) parent(sfile);
+ } else parent(sfile);
+ }
+ }
+ freefilelist(sfile);
+ sfile->ofs= 0;
+ scrarea_queue_winredraw(curarea);
+ }
+ else if(event== 3) {
+ char *selected= fsmenu_get_entry(sfile->menu-1);
+
+ /* welke string */
+ if (selected) {
+ strcpy(sfile->dir, selected);
+ BLI_make_exist(sfile->dir);
+ checkdir(sfile->dir);
+ freefilelist(sfile);
+ sfile->ofs= 0;
+ scrarea_queue_winredraw(curarea);
+ }
+
+ sfile->act= -1;
+
+ }
+ else if(event== 4) parent(sfile);
+ else if(event== 5) {
+ if(sfile->type) filesel_execute(sfile);
+ }
+ else if(event== 6) filesel_prevspace();
+
+}
+
+/****/
+
+typedef void (*ReplaceFP)(ID *oldblock, ID *newblock);
+
+static void change_id_link(void *linkpv, void *newlinkv) {
+ ID **linkp= (ID**) linkpv;
+ ID *newlink= newlinkv;
+
+ if (*linkp) {
+ (*linkp)->us--;
+ }
+ (*linkp)= newlink;
+ if (newlink) {
+ id_us_plus(newlink);
+ }
+}
+
+static void replace_image(ID *oldblock, ID *newblock) {
+ Image *oldima= (Image*) oldblock;
+ Image *newima= (Image*) newblock;
+ bScreen *sc;
+ Scene *sce;
+ Tex *tex;
+ Mesh *me;
+
+ for (tex= G.main->tex.first; tex; tex= tex->id.next) {
+ if (tex->env && tex->env->type == ENV_LOAD && tex->env->ima == oldima)
+ change_id_link(&tex->env->ima, newima);
+ if (tex->ima == oldima)
+ change_id_link(&tex->ima, newima);
+ }
+
+ for (sce= G.main->scene.first; sce; sce= sce->id.next) {
+ if (sce->ima == oldima)
+ change_id_link(&sce->ima, newima);
+ }
+
+ for (sc= G.main->screen.first; sc; sc= sc->id.next) {
+ ScrArea *sa;
+
+ for (sa= sc->areabase.first; sa; sa= sa->next) {
+ SpaceLink *sl;
+
+ for (sl= sa->spacedata.first; sl; sl= sl->next) {
+ if (sl->spacetype == SPACE_VIEW3D) {
+ View3D *v3d= (View3D*) sl;
+ BGpic *bgp= v3d->bgpic;
+
+ if (bgp && bgp->ima == oldima)
+ change_id_link(&bgp->ima, newima);
+ } else if (sl->spacetype == SPACE_IMAGE) {
+ SpaceImage *sima= (SpaceImage*) sl;
+
+ if (sima->image == oldima)
+ change_id_link(&sima->image, newima);
+ }
+ }
+ }
+ }
+
+ for (me= G.main->mesh.first; me; me= me->id.next) {
+ TFace *tfaces= me->tface;
+
+ if (tfaces) {
+ int i;
+
+ for (i=0; i<me->totface; i++) {
+ TFace *tf= &tfaces[i];
+
+ if (tf->tpage == oldima) {
+ /* not change_id_link, tpage's aren't owners :(
+ * see hack below.
+ */
+ tf->tpage= newima;
+ }
+ }
+ }
+ }
+
+ /* Nasty hack, necessary because tpages don't act
+ * as a user, so there lots of image user count
+ * munging occurs... this will ensure the image
+ * really dies.
+ */
+ oldima->id.us= 0;
+}
+
+static void replace_material(ID *oldblock, ID *newblock)
+{
+ Material *old= (Material*) oldblock;
+ Material *new= (Material*) newblock;
+ Material ***matarar;
+ ID *id;
+ Object *ob;
+ int a;
+
+ ob= G.main->object.first;
+ while(ob) {
+ if(ob->totcol && ob->id.lib==0) {
+ matarar= give_matarar(ob);
+ for(a=1; a<=ob->totcol; a++) {
+ if(ob->mat[a-1] == old) {
+ if(old) old->id.us--;
+ id_us_plus((ID *)new);
+ ob->mat[a-1]= new;
+ }
+ id= ob->data;
+ if( (*matarar)[a-1] == old && id->lib==0) {
+ if(old) old->id.us--;
+ id_us_plus((ID *)new);
+ (*matarar)[a-1]= new;
+ }
+ }
+ }
+ ob= ob->id.next;
+ }
+}
+
+static ReplaceFP get_id_replace_function(int idcode) {
+ switch (idcode) {
+ case ID_MA:
+ return &replace_material;
+ case ID_IM:
+ return &replace_image;
+ default:
+ return NULL;
+ }
+}
+
+static void databrowse_replace(SpaceFile *sfile, int idcode)
+{
+ ReplaceFP replace_func= get_id_replace_function(idcode);
+
+ if (!replace_func) {
+ error("Replacing %s blocks is unsupported", BLO_idcode_to_name(idcode));
+ } else if (sfile->act==-1) {
+ error("Select target with leftmouse");
+ } else {
+ ID *target= (ID*) sfile->filelist[sfile->act].poin;
+
+ if (target) {
+ char buf[128];
+
+ sprintf(buf, "Replace with %s: %s", BLO_idcode_to_name(idcode), target->name+2);
+
+ if (okee(buf)) {
+ int i;
+
+ for (i = 0; i <sfile->totfile; i++)
+ if ((sfile->filelist[i].flags&ACTIVE) && sfile->filelist[i].poin!=target)
+ replace_func(sfile->filelist[i].poin, target);
+ }
+ }
+ }
+
+ freefilelist(sfile);
+ scrarea_queue_winredraw(curarea);
+}
+
+static void fs_fake_users(SpaceFile *sfile)
+{
+ ID *id;
+ int a;
+
+ /* alleen bij F4 DATABROWSE */
+ if(sfile->returnfunc) return;
+
+ for(a=0; a<sfile->totfile; a++) {
+ if(sfile->filelist[a].flags & ACTIVE) {
+ id= (ID *)sfile->filelist[a].poin;
+ if(id) {
+ if( id->flag & LIB_FAKEUSER) {
+ id->flag -= LIB_FAKEUSER;
+ id->us--;
+ }
+ else {
+ id->flag |= LIB_FAKEUSER;
+ id->us++;
+ }
+ }
+ }
+ }
+ freefilelist(sfile);
+ scrarea_queue_winredraw(curarea);
+}
+
+void winqreadfilespace(unsigned short event, short val, char ascii)
+{
+ static int acto=0;
+ SpaceFile *sfile;
+ int act, do_draw= 0, i, test, ret = 0;
+ short qual, mval[2];
+ char str[FILE_MAXDIR+FILE_MAXFILE+12];
+
+ sfile= curarea->spacedata.first;
+ if(sfile==0) return;
+ if(sfile->filelist==0) {
+ /* wel buttons doen */
+ if(val && event==LEFTMOUSE) {
+ /* FrontbufferButs(TRUE); */
+ /* event= DoButtons(); */
+ /* FrontbufferButs(FALSE); */
+ /* NIET de headerbuttons! */
+ /* if(event) do_filesel_buttons(event, sfile); */
+ }
+ return;
+ }
+
+ if(curarea->win==0) return;
+ calc_file_rcts(sfile);
+ getmouseco_areawin(mval);
+
+ /* om hangen te voorkomen */
+ if(selecting && !(get_mbut() & R_MOUSE)) selecting= 0;
+
+ if(val) {
+
+ if( event!=RETKEY && event!=PADENTER)
+ if( uiDoBlocks(&curarea->uiblocks, event)!=UI_NOTHING ) event= 0;
+
+ switch(event) {
+
+ case UI_BUT_EVENT:
+ do_filesel_buttons(val, sfile);
+ break;
+
+ case LEFTMOUSE:
+ case MIDDLEMOUSE:
+ if(mval[0]>scrollrct.xmin && mval[0]<scrollrct.xmax && mval[1]>scrollrct.ymin && mval[1]<scrollrct.ymax) {
+ do_filescroll(sfile);
+ }
+ else if(mval[0]>textrct.xmin && mval[0]<textrct.xmax && mval[1]>textrct.ymin && mval[1]<textrct.ymax) {
+
+ /* sfile->act wordt gebruikt bij databrowse: dubbelenamen van library objecten */
+
+ sfile->act= act= find_active_file(sfile, mval[0], mval[1]);
+
+ if(act>=0 && act<sfile->totfile) {
+ if(S_ISDIR(sfile->filelist[act].type)) {
+ strcat(sfile->dir, sfile->filelist[act].relname);
+ strcat(sfile->dir,"/");
+ checkdir(sfile->dir);
+ freefilelist(sfile);
+ sfile->ofs= 0;
+ do_draw= 1;
+ }
+ else {
+ if( strcmp(sfile->file, sfile->filelist[act].relname)) {
+ do_draw= 1;
+ strcpy(sfile->file, sfile->filelist[act].relname);
+ }
+ if(event==MIDDLEMOUSE && sfile->type) filesel_execute(sfile);
+ }
+ }
+ }
+ else {
+ /* FrontbufferButs(TRUE); */
+ /* event= DoButtons(); */
+ /* FrontbufferButs(FALSE); */
+ /* NIET de headerbuttons! */
+ /* if(event) do_filesel_buttons(event, sfile); */
+ }
+ break;
+ case RIGHTMOUSE:
+ act= find_active_file(sfile, mval[0], mval[1]);
+ acto= act;
+ if(act>=0 && act<sfile->totfile) {
+
+ if (sfile->filelist[act].flags & ACTIVE) {
+ sfile->filelist[act].flags &= ~ACTIVE;
+ selecting = INACTIVATE;
+ }
+ else {
+ test= sfile->filelist[act].relname[0];
+ if (act>=2 || test!='.') sfile->filelist[act].flags |= ACTIVE;
+
+ selecting = ACTIVATE;
+ }
+ do_draw= 1;
+ }
+ break;
+ case MOUSEY:
+ act= find_active_file(sfile, mval[0], mval[1]);
+ if (act!=acto) {
+ set_active_file(sfile, act);
+ }
+ if(selecting && act!=acto) {
+
+ while(1) {
+ if (acto >= 2 && acto < sfile->totfile) {
+ if (selecting == ACTIVATE) sfile->filelist[acto].flags |= ACTIVE;
+ else if (selecting == INACTIVATE) sfile->filelist[acto].flags &= ~ACTIVE;
+ }
+ if (acto < act) acto++;
+ else if (acto > act) acto--;
+ else break;
+
+ }
+
+ }
+ acto= act;
+ break;
+
+ case PAGEUPKEY:
+ sfile->ofs-= page_ofs;
+ do_draw= 1;
+ break;
+ case PAGEDOWNKEY:
+ sfile->ofs+= page_ofs;
+ do_draw= 1;
+ break;
+ case HOMEKEY:
+ sfile->ofs= 0;
+ do_draw= 1;
+ break;
+ case ENDKEY:
+ sfile->ofs= sfile->totfile;
+ do_draw= 1;
+ break;
+
+ case AKEY:
+ swapselect_file(sfile);
+ if(sfile->type==FILE_MAIN) filesel_select_objects(sfile);
+ do_draw= 1;
+ break;
+
+ case BKEY:
+ case CKEY:
+ case LKEY:
+ if(event==LKEY && sfile->type==FILE_MAIN && (G.qual & LR_CTRLKEY)) {
+ databrowse_replace(sfile, groupname_to_code(sfile->dir));
+ break;
+ }
+ /* doorgeven */
+ case MKEY:
+ if(sfile->type==FILE_MAIN) break;
+
+ if(!countselect(sfile)) {
+ error("No files selected");
+ break;
+ }
+
+ if(!getotherdir()) {
+ error("No second fileselect");
+ break;
+ }
+
+ if (!strcmp(sfile->dir, otherdir)) {
+ error("Same directories");
+ break;
+ }
+
+ if(event==BKEY) sprintf(str, "Backup to %s", otherdir);
+ else if(event==CKEY) sprintf(str, "Copy to %s", otherdir);
+ else if(event==LKEY) sprintf(str, "Linked copy to %s", otherdir);
+ else if(event==MKEY) sprintf(str, "Move to %s", otherdir);
+
+ if (!okee(str)) break;
+
+ for (i = 0; i<sfile->totfile; i++){
+ if (sfile->filelist[i].flags & ACTIVE) {
+ BLI_make_file_string(G.sce, str, sfile->dir, sfile->filelist[i].relname);
+
+ if(event==BKEY) ret= BLI_backup(sfile->filelist[i].relname, sfile->dir, otherdir);
+ else if(event==CKEY) ret= BLI_copy_fileops(str, otherdir);
+ else if(event==LKEY) ret= BLI_link(str, otherdir);
+ else if(event==MKEY) ret= BLI_move(str, otherdir);
+
+ if (ret) {error("Command failed, see console"); break;}
+ else sfile->filelist[i].flags &= ~ACTIVE;
+ }
+ }
+ do_draw= 1;
+ if(event==BKEY || event==MKEY)
+ freefilelist(sfile);
+
+ reread_other_fs();
+
+ break;
+ case RKEY:
+ if(sfile->type==FILE_MAIN) {
+ databrowse_replace(sfile, groupname_to_code(sfile->dir));
+ break;
+ }
+ /* doorgeven aan TKEY! */
+
+ case TKEY:
+ if(sfile->type==FILE_MAIN) break;
+
+ if(!countselect(sfile)) {
+ error("No files selected");
+ break;
+ }
+
+ if(event==TKEY) sprintf(str, "Touch");
+ else if(event==RKEY) sprintf(str, "Remove from %s", sfile->dir);
+
+ qual= G.qual; /* want na okee() heb je de shift losgelaten */
+ if (!okee(str)) break;
+
+ for (i = 0; i <sfile->totfile; i++) {
+ if (sfile->filelist[i].flags & ACTIVE) {
+ BLI_make_file_string(G.sce, str, sfile->dir, sfile->filelist[i].relname);
+
+ if(event==TKEY) ret= BLI_touch(str);
+ else if(event==RKEY) {
+ if(qual & LR_SHIFTKEY) ret= BLI_delete(str, 0, 1);
+ else if(S_ISDIR(sfile->filelist[i].type)) ret= BLI_delete(str, 1, 0);
+ else ret= BLI_delete(str, 0, 0);
+ }
+
+ if (ret) {error("Command failed, see console"); break;}
+ else sfile->filelist[i].flags &= ~ACTIVE;
+ }
+ }
+ do_draw= 1;
+ freefilelist(sfile);
+
+ break;
+
+ case PKEY:
+ if(G.qual & LR_SHIFTKEY) {
+ extern char bprogname[]; /* usiblender.c */
+
+ sprintf(str, "%s -a \"%s%s\"", bprogname, sfile->dir, sfile->file);
+ system(str);
+ }
+ else
+ parent(sfile);
+
+ break;
+
+ case IKEY:
+ if(sfile->type==FILE_MAIN) break;
+
+ sprintf(str, "$IMAGEEDITOR %s%s", sfile->dir, sfile->file);
+ system(str);
+ break;
+
+ case EKEY:
+ if(sfile->type==FILE_MAIN) break;
+
+ sprintf(str, "$WINEDITOR %s%s", sfile->dir, sfile->file);
+ system(str);
+ break;
+
+ case FKEY:
+ if(sfile->type==FILE_MAIN) {
+ fs_fake_users(sfile);
+ }
+ break;
+
+ case PADPLUSKEY:
+ case EQUALKEY:
+ if (G.qual & LR_CTRLKEY) BLI_newname(sfile->file, +100);
+ else if (G.qual & LR_SHIFTKEY) BLI_newname(sfile->file, +10);
+ else BLI_newname(sfile->file, +1);
+
+ do_draw= 1;
+ break;
+
+ case PADMINUS:
+ case MINUSKEY:
+ if (G.qual & LR_CTRLKEY) BLI_newname(sfile->file, -100);
+ else if (G.qual & LR_SHIFTKEY) BLI_newname(sfile->file, -10);
+ else BLI_newname(sfile->file, -1);
+
+ do_draw= 1;
+ break;
+
+ case BACKSLASHKEY:
+ case SLASHKEY:
+ if(sfile->type==FILE_MAIN) break;
+
+#ifdef WIN32
+ strcpy(sfile->dir, "\\");
+#else
+ strcpy(sfile->dir, "/");
+#endif
+ freefilelist(sfile);
+ sfile->ofs= 0;
+ do_draw= 1;
+ break;
+ case PERIODKEY:
+ freefilelist(sfile);
+ do_draw= 1;
+ break;
+ case ESCKEY:
+ filesel_prevspace();
+ break;
+ case PADENTER:
+ case RETKEY:
+ if(sfile->type) filesel_execute(sfile);
+ break;
+ }
+ }
+ else if(event==RIGHTMOUSE) {
+ selecting = NOTACTIVE;
+ if(sfile->type==FILE_MAIN) filesel_select_objects(sfile);
+ }
+ else if(event==LEFTMOUSE) {
+ if(sfile->type==FILE_MAIN) active_file_object(sfile);
+ }
+
+ /* XXX, stupid patch, curarea can become undone
+ * because of file loading... fixme zr
+ */
+ if(do_draw && curarea) scrarea_queue_winredraw(curarea);
+}
+
+
+
+
+/* ************* LIBRARY FILESEL ******************* */
+
+static int groupname_to_code(char *group)
+{
+ char buf[32];
+ char *lslash;
+
+ strcpy(buf, group);
+ lslash= BLI_last_slash(buf);
+ if (lslash)
+ lslash[0]= '\0';
+
+ return BLO_idcode_from_name(buf);
+}
+
+static int is_a_library(SpaceFile *sfile, char *dir, char *group)
+{
+ /* return ok als een blenderfile, in dir staat de filename,
+ * in group het type libdata
+ */
+ int len;
+ char *fd;
+
+ strcpy(dir, sfile->dir);
+ len= strlen(dir);
+ if(len<7) return 0;
+ if( dir[len-1] != '/' && dir[len-1] != '\\') return 0;
+
+ group[0]= 0;
+ dir[len-1]= 0;
+
+ /* Find the last slash */
+ fd= (strrchr(dir, '/')>strrchr(dir, '\\'))?strrchr(dir, '/'):strrchr(dir, '\\');
+
+ if(fd==0) return 0;
+ *fd= 0;
+ if(BLO_has_bfile_extension(fd+1)) {
+ *fd= '/';
+ }
+ else {
+ strcpy(group, fd+1);
+
+ /* Find the last slash */
+ fd= (strrchr(dir, '/')>strrchr(dir, '\\'))?strrchr(dir, '/'):strrchr(dir, '\\');
+ if (!fd || !BLO_has_bfile_extension(fd+1)) return 0;
+ }
+ return 1;
+}
+
+static void do_library_append(SpaceFile *sfile)
+{
+ char dir[FILE_MAXDIR], group[32];
+
+ if ( is_a_library(sfile, dir, group)==0 ) {
+ error("Not a library");
+ } else if (!sfile->libfiledata) {
+ error("Library not loaded");
+ } else if (group[0]==0) {
+ error("Nothing indicated");
+ } else if (BLI_streq(G.main->name, dir)) {
+ error("Cannot use current file as library");
+ } else {
+ Object *ob;
+ int idcode = groupname_to_code(group);
+
+ BLO_library_append(sfile, dir, idcode);
+
+ /* DISPLISTEN */
+ ob= G.main->object.first;
+ set_displist_onlyzero(1);
+ while(ob) {
+ if(ob->id.lib) {
+ if(ob->type==OB_FONT) {
+ Curve *cu= ob->data;
+ if(cu->nurb.first==0) text_to_curve(ob, 0);
+ }
+ makeDispList(ob);
+ }
+ else if(ob->type==OB_MESH && ob->parent && ob->parent->type==OB_LATTICE ) {
+ makeDispList(ob);
+ }
+
+ ob= ob->id.next;
+ }
+ set_displist_onlyzero(0);
+
+ /* in sfile->dir staat de HELE libnaam */
+ strcpy(G.lib, sfile->dir);
+
+ if((sfile->flag & FILE_LINK)==0) all_local();
+ }
+}
+
+static void library_to_filelist(SpaceFile *sfile)
+{
+ char dir[FILE_MAXDIR], group[24];
+ int ok, i, nnames, idcode;
+ LinkNode *l, *names;
+
+ /* name testen */
+ ok= is_a_library(sfile, dir, group);
+ if (!ok) {
+ /* vrijgeven */
+ if(sfile->libfiledata) BLO_blendhandle_close(sfile->libfiledata);
+ sfile->libfiledata= 0;
+ return;
+ }
+
+ /* en daar gaat ie */
+ /* voorlopig alleen filedata inlezen als libfiledata==0 */
+ if (sfile->libfiledata==0) {
+ sfile->libfiledata= BLO_blendhandle_from_file(dir);
+ if(sfile->libfiledata==0) return;
+ }
+
+ if (idcode= groupname_to_code(group)) {
+ names= BLO_blendhandle_get_datablock_names(sfile->libfiledata, idcode);
+ } else {
+ names= BLO_blendhandle_get_linkable_groups(sfile->libfiledata);
+ }
+
+ nnames= BLI_linklist_length(names);
+
+ sfile->totfile= nnames + 2;
+ sfile->filelist= malloc(sfile->totfile * sizeof(*sfile->filelist));
+ memset(sfile->filelist, 0, sfile->totfile * sizeof(*sfile->filelist));
+
+ sfile->filelist[0].relname= strdup(".");
+ sfile->filelist[0].type |= S_IFDIR;
+ sfile->filelist[1].relname= strdup("..");
+ sfile->filelist[1].type |= S_IFDIR;
+
+ for (i=0, l= names; i<nnames; i++, l= l->next) {
+ char *blockname= l->link;
+
+ sfile->filelist[i + 2].relname= blockname;
+ if (!idcode)
+ sfile->filelist[i + 2].type |= S_IFDIR;
+ }
+
+ BLI_linklist_free(names, NULL);
+
+ qsort(sfile->filelist, sfile->totfile, sizeof(struct direntry), compare_name);
+
+ sfile->maxnamelen= 0;
+ for(i=0; i<sfile->totfile; i++) {
+ int len = BMF_GetStringWidth(G.font, sfile->filelist[i].relname);
+ if (len > sfile->maxnamelen)
+ sfile->maxnamelen = len;
+ }
+}
+
+/* ******************* DATA SELECT ********************* */
+
+static void filesel_select_objects(SpaceFile *sfile)
+{
+ Object *ob;
+ Base *base;
+ Scene *sce;
+ int a;
+
+ /* alleen bij F4 DATABROWSE */
+ if(sfile->returnfunc) return;
+
+ if( strcmp(sfile->dir, "Object/")==0 ) {
+ for(a=0; a<sfile->totfile; a++) {
+
+ ob= (Object *)sfile->filelist[a].poin;
+
+ if(ob) {
+ if(sfile->filelist[a].flags & ACTIVE) ob->flag |= SELECT;
+ else ob->flag &= ~SELECT;
+ }
+
+ }
+ base= FIRSTBASE;
+ while(base) {
+ base->flag= base->object->flag;
+ base= base->next;
+ }
+ allqueue(REDRAWVIEW3D, 0);
+ }
+ else if( strcmp(sfile->dir, "Scene/")==0 ) {
+
+ for(a=0; a<sfile->totfile; a++) {
+
+ sce= (Scene *)sfile->filelist[a].poin;
+ if(sce) {
+ if(sfile->filelist[a].flags & ACTIVE) sce->r.scemode |= R_BG_RENDER;
+ else sce->r.scemode &= ~R_BG_RENDER;
+ }
+
+ }
+ allqueue(REDRAWBUTSRENDER, 0);
+ }
+}
+
+static void active_file_object(SpaceFile *sfile)
+{
+ Object *ob;
+
+ /* alleen bij F4 DATABROWSE */
+ if(sfile->returnfunc) return;
+
+ if( strcmp(sfile->dir, "Object/")==0 ) {
+ if(sfile->act >= 0) {
+
+ ob= (Object *)sfile->filelist[sfile->act].poin;
+
+ if(ob) {
+ set_active_object(ob);
+ if(BASACT && BASACT->object==ob) {
+ BASACT->flag |= SELECT;
+ sfile->filelist[sfile->act].flags |= ACTIVE;
+ allqueue(REDRAWVIEW3D, 0);
+ scrarea_queue_winredraw(curarea);
+ }
+ }
+ }
+ }
+}
+
+
+void main_to_filelist(SpaceFile *sfile)
+{
+ ID *id;
+ struct direntry *files, *firstlib = NULL;
+ ListBase *lb;
+ int a, fake, idcode, len, ok, totlib, totbl;
+
+ if(sfile->dir[0]=='/') sfile->dir[0]= 0;
+
+ if(sfile->dir[0]) {
+ idcode= groupname_to_code(sfile->dir);
+ if(idcode==0) sfile->dir[0]= 0;
+ }
+
+ if( sfile->dir[0]==0) {
+
+ /* directories maken */
+ sfile->totfile= 22;
+ sfile->filelist= (struct direntry *)malloc(sfile->totfile * sizeof(struct direntry));
+
+ for(a=0; a<sfile->totfile; a++) {
+ memset( &(sfile->filelist[a]), 0 , sizeof(struct direntry));
+ sfile->filelist[a].type |= S_IFDIR;
+ }
+
+ sfile->filelist[0].relname= strdup("..");
+ sfile->filelist[1].relname= strdup(".");
+ sfile->filelist[2].relname= strdup("Scene");
+ sfile->filelist[3].relname= strdup("Object");
+ sfile->filelist[4].relname= strdup("Mesh");
+ sfile->filelist[5].relname= strdup("Curve");
+ sfile->filelist[6].relname= strdup("Metaball");
+ sfile->filelist[7].relname= strdup("Material");
+ sfile->filelist[8].relname= strdup("Texture");
+ sfile->filelist[9].relname= strdup("Image");
+ sfile->filelist[10].relname= strdup("Ika");
+ sfile->filelist[11].relname= strdup("Wave");
+ sfile->filelist[12].relname= strdup("Lattice");
+ sfile->filelist[13].relname= strdup("Lamp");
+ sfile->filelist[14].relname= strdup("Camera");
+ sfile->filelist[15].relname= strdup("Ipo");
+ sfile->filelist[16].relname= strdup("World");
+ sfile->filelist[17].relname= strdup("Screen");
+ sfile->filelist[18].relname= strdup("VFont");
+ sfile->filelist[19].relname= strdup("Text");
+ sfile->filelist[20].relname= strdup("Armature");
+ sfile->filelist[21].relname= strdup("Action");
+ qsort(sfile->filelist, sfile->totfile, sizeof(struct direntry), compare_name);
+ }
+ else {
+
+ /* files maken */
+ idcode= groupname_to_code(sfile->dir);
+
+ lb= wich_libbase(G.main, idcode );
+ if(lb==0) return;
+
+ id= lb->first;
+ sfile->totfile= 0;
+ while(id) {
+
+ if(sfile->returnfunc && idcode==ID_IP) {
+ if(sfile->ipotype== ((Ipo *)id)->blocktype) sfile->totfile++;
+ }
+ else sfile->totfile++;
+
+ id= id->next;
+ }
+
+ if(sfile->returnfunc==0) sfile->totfile+= 2;
+ sfile->filelist= (struct direntry *)malloc(sfile->totfile * sizeof(struct direntry));
+
+ files= sfile->filelist;
+
+ if(sfile->returnfunc==0) {
+ memset( &(sfile->filelist[0]), 0 , sizeof(struct direntry));
+ sfile->filelist[0].relname= strdup(".");
+ sfile->filelist[0].type |= S_IFDIR;
+ memset( &(sfile->filelist[1]), 0 , sizeof(struct direntry));
+ sfile->filelist[1].relname= strdup("..");
+ sfile->filelist[1].type |= S_IFDIR;
+
+ files+= 2;
+ }
+
+ id= lb->first;
+ totlib= totbl= 0;
+
+ while(id) {
+
+ ok= 0;
+ if(sfile->returnfunc && idcode==ID_IP) {
+ if(sfile->ipotype== ((Ipo *)id)->blocktype) ok= 1;
+ }
+ else ok= 1;
+
+ if(ok) {
+
+ memset( files, 0 , sizeof(struct direntry));
+ files->relname= strdup(id->name+2);
+
+ if(sfile->returnfunc==0) { /* F4 DATA BROWSE */
+ if(idcode==ID_OB) {
+ if( ((Object *)id)->flag & SELECT) files->flags |= ACTIVE;
+ }
+ else if(idcode==ID_SCE) {
+ if( ((Scene *)id)->r.scemode & R_BG_RENDER) files->flags |= ACTIVE;
+ }
+ }
+ files->nr= totbl+1;
+ files->poin= id;
+ fake= id->flag & LIB_FAKEUSER;
+
+ if(id->lib && fake) sprintf(files->extra, "LF %d", id->us);
+ else if(id->lib) sprintf(files->extra, "L %d", id->us);
+ else if(fake) sprintf(files->extra, "F %d", id->us);
+ else sprintf(files->extra, " %d", id->us);
+
+ if(id->lib) {
+ if(totlib==0) firstlib= files;
+ totlib++;
+ }
+
+ files++;
+ totbl++;
+ }
+
+ id= id->next;
+ }
+
+ /* alleen qsort van libraryblokken */
+ if(totlib>1) {
+ qsort(firstlib, totlib, sizeof(struct direntry), compare_name);
+ }
+ }
+
+ sfile->maxnamelen= 0;
+ for(a=0; a<sfile->totfile; a++) {
+ len = BMF_GetStringWidth(G.font, sfile->filelist[a].relname);
+ if (len > sfile->maxnamelen) sfile->maxnamelen = len;
+
+ if(filetoname) {
+ if( strcmp(sfile->file, sfile->filelist[a].relname)==0) {
+ sfile->ofs= a-( sfile->collums*(curarea->winy-FILESELHEAD-10)/(2*FILESEL_DY));
+ filetoname= 0;
+ if(sfile->returnfunc) sfile->filelist[a].flags |= ACTIVE;
+ }
+ }
+ }
+}
+
+
+
diff --git a/source/blender/src/ghostwinlay.c b/source/blender/src/ghostwinlay.c
new file mode 100644
index 00000000000..1280278edf6
--- /dev/null
+++ b/source/blender/src/ghostwinlay.c
@@ -0,0 +1,572 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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>
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+
+#include "GHOST_C-api.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_global.h"
+
+#include "BIF_gl.h"
+#include "BIF_graphics.h"
+#include "BIF_mywindow.h"
+#include "BIF_screen.h"
+#include "BIF_usiblender.h"
+
+#include "mydevice.h"
+#include "blendef.h"
+
+#include "winlay.h"
+
+static GHOST_SystemHandle g_system= 0;
+
+ /* Some simple ghost <-> blender conversions */
+
+static GHOST_TStandardCursor convert_cursor(int curs) {
+ switch(curs) {
+ default:
+ case CURSOR_STD: return GHOST_kStandardCursorDefault;
+ case CURSOR_VPAINT: return GHOST_kStandardCursorLeftArrow;
+ case CURSOR_FACESEL: return GHOST_kStandardCursorRightArrow;
+ case CURSOR_WAIT: return GHOST_kStandardCursorWait;
+ case CURSOR_EDIT: return GHOST_kStandardCursorCrosshair;
+ case CURSOR_HELP: return GHOST_kStandardCursorHelp;
+ case CURSOR_X_MOVE: return GHOST_kStandardCursorLeftRight;
+ case CURSOR_Y_MOVE: return GHOST_kStandardCursorUpDown;
+ }
+}
+
+static int convert_mbut(GHOST_TButtonMask but) {
+ if (but == GHOST_kButtonMaskLeft) {
+ return LEFTMOUSE;
+ } else if (but == GHOST_kButtonMaskRight) {
+ return RIGHTMOUSE;
+ } else {
+ return MIDDLEMOUSE;
+ }
+}
+
+static int convert_key(GHOST_TKey key) {
+ if (key>=GHOST_kKeyA && key<=GHOST_kKeyZ) {
+ return (AKEY + ((int) key - GHOST_kKeyA));
+ } else if (key>=GHOST_kKey0 && key<=GHOST_kKey9) {
+ return (ZEROKEY + ((int) key - GHOST_kKey0));
+ } else if (key>=GHOST_kKeyNumpad0 && key<=GHOST_kKeyNumpad9) {
+ return (PAD0 + ((int) key - GHOST_kKeyNumpad0));
+ } else if (key>=GHOST_kKeyF1 && key<=GHOST_kKeyF12) {
+ return (F1KEY + ((int) key - GHOST_kKeyF1));
+ } else {
+ switch (key) {
+ case GHOST_kKeyBackSpace: return BACKSPACEKEY;
+ case GHOST_kKeyTab: return TABKEY;
+ case GHOST_kKeyLinefeed: return LINEFEEDKEY;
+ case GHOST_kKeyClear: return 0;
+ case GHOST_kKeyEnter: return RETKEY;
+
+ case GHOST_kKeyEsc: return ESCKEY;
+ case GHOST_kKeySpace: return SPACEKEY;
+ case GHOST_kKeyQuote: return QUOTEKEY;
+ case GHOST_kKeyComma: return COMMAKEY;
+ case GHOST_kKeyMinus: return MINUSKEY;
+ case GHOST_kKeyPeriod: return PERIODKEY;
+ case GHOST_kKeySlash: return SLASHKEY;
+
+ case GHOST_kKeySemicolon: return SEMICOLONKEY;
+ case GHOST_kKeyEqual: return EQUALKEY;
+
+ case GHOST_kKeyLeftBracket: return LEFTBRACKETKEY;
+ case GHOST_kKeyRightBracket: return RIGHTBRACKETKEY;
+ case GHOST_kKeyBackslash: return BACKSLASHKEY;
+ case GHOST_kKeyAccentGrave: return ACCENTGRAVEKEY;
+
+ case GHOST_kKeyLeftShift: return LEFTSHIFTKEY;
+ case GHOST_kKeyRightShift: return RIGHTSHIFTKEY;
+ case GHOST_kKeyLeftControl: return LEFTCTRLKEY;
+ case GHOST_kKeyRightControl: return RIGHTCTRLKEY;
+ case GHOST_kKeyLeftAlt: return LEFTALTKEY;
+ case GHOST_kKeyRightAlt: return RIGHTALTKEY;
+
+ case GHOST_kKeyCapsLock: return CAPSLOCKKEY;
+ case GHOST_kKeyNumLock: return 0;
+ case GHOST_kKeyScrollLock: return 0;
+
+ case GHOST_kKeyLeftArrow: return LEFTARROWKEY;
+ case GHOST_kKeyRightArrow: return RIGHTARROWKEY;
+ case GHOST_kKeyUpArrow: return UPARROWKEY;
+ case GHOST_kKeyDownArrow: return DOWNARROWKEY;
+
+ case GHOST_kKeyPrintScreen: return 0;
+ case GHOST_kKeyPause: return PAUSEKEY;
+
+ case GHOST_kKeyInsert: return INSERTKEY;
+ case GHOST_kKeyDelete: return DELKEY;
+ case GHOST_kKeyHome: return HOMEKEY;
+ case GHOST_kKeyEnd: return ENDKEY;
+ case GHOST_kKeyUpPage: return PAGEUPKEY;
+ case GHOST_kKeyDownPage: return PAGEDOWNKEY;
+
+ case GHOST_kKeyNumpadPeriod: return PADPERIOD;
+ case GHOST_kKeyNumpadEnter: return PADENTER;
+ case GHOST_kKeyNumpadPlus: return PADPLUSKEY;
+ case GHOST_kKeyNumpadMinus: return PADMINUS;
+ case GHOST_kKeyNumpadAsterisk: return PADASTERKEY;
+ case GHOST_kKeyNumpadSlash: return PADSLASHKEY;
+ case GHOST_kKeyUnknown: return UNKNOWNKEY;
+
+ default:
+ return 0;
+ }
+ }
+}
+
+ /***/
+
+struct _Window {
+ GHOST_WindowHandle ghostwin;
+
+ /* Handler and private data for handler */
+ WindowHandlerFP handler;
+ void *user_data;
+
+ /* Window state */
+ int size[2], position[2];
+ int active, visible;
+
+ /* Last known mouse/button/qualifier state */
+ int lmouse[2];
+ int lqual; /* (LR_SHFTKEY, LR_CTRLKEY, LR_ALTKEY) */
+ int lmbut; /* (L_MOUSE, M_MOUSE, R_MOUSE) */
+ int commandqual;
+
+ /* Tracks the faked mouse button, if non-zero it is
+ * the event number of the last faked button.
+ */
+ int faked_mbut;
+
+ GHOST_TimerTaskHandle timer;
+ int timer_event;
+};
+
+static Window *window_new(GHOST_WindowHandle ghostwin)
+{
+ Window *win= MEM_callocN(sizeof(*win), "Window");
+ win->ghostwin= ghostwin;
+
+ return win;
+}
+
+static void window_handle(Window *win, short event, short val)
+{
+ if (win->handler) {
+ win->handler(win, win->user_data, event, val, 0);
+ }
+}
+static void window_handle_ext(Window *win, short event, short val, short extra)
+{
+ if (win->handler) {
+ win->handler(win, win->user_data, event, val, extra);
+ }
+}
+
+static void window_free(Window *win)
+{
+ MEM_freeN(win);
+}
+
+ /***/
+
+static Window *active_gl_window= NULL;
+
+Window *window_open(char *title, int posx, int posy, int sizex, int sizey, int start_maximized)
+{
+ GHOST_WindowHandle ghostwin;
+ GHOST_TWindowState inital_state;
+ int scr_w, scr_h;
+
+ winlay_get_screensize(&scr_w, &scr_h);
+ posy= (scr_h-posy-sizey);
+
+ inital_state= start_maximized?GHOST_kWindowStateMaximized:GHOST_kWindowStateNormal;
+ ghostwin= GHOST_CreateWindow(g_system,
+ title,
+ posx, posy, sizex, sizey,
+ inital_state,
+ GHOST_kDrawingContextTypeOpenGL,
+ 0 /* no stereo */);
+
+ if (ghostwin) {
+ Window *win= window_new(ghostwin);
+
+ if (win) {
+ GHOST_SetWindowUserData(ghostwin, win);
+
+ win->position[0]= posx;
+ win->position[1]= posy;
+ win->size[0]= sizex;
+ win->size[1]= sizey;
+
+ win->lmouse[0]= win->size[0]/2;
+ win->lmouse[1]= win->size[1]/2;
+ } else {
+ GHOST_DisposeWindow(g_system, ghostwin);
+ }
+
+ return win;
+ } else {
+ return NULL;
+ }
+}
+
+void window_set_handler(Window *win, WindowHandlerFP handler, void *user_data)
+{
+ win->handler= handler;
+ win->user_data= user_data;
+}
+
+static void window_timer_proc(GHOST_TimerTaskHandle timer, GHOST_TUns64 time)
+{
+ Window *win= GHOST_GetTimerTaskUserData(timer);
+
+ win->handler(win, win->user_data, win->timer_event, 0, 0);
+}
+
+void window_set_timer(Window *win, int delay_ms, int event)
+{
+ if (win->timer) GHOST_RemoveTimer(g_system, win->timer);
+
+ win->timer_event= event;
+ win->timer= GHOST_InstallTimer(g_system, delay_ms, delay_ms, window_timer_proc, win);
+}
+
+void window_destroy(Window *win) {
+ if (active_gl_window==win) {
+ active_gl_window= NULL;
+ }
+
+ if (win->timer) {
+ GHOST_RemoveTimer(g_system, win->timer);
+ win->timer= NULL;
+ }
+
+ GHOST_DisposeWindow(g_system, win->ghostwin);
+ window_free(win);
+}
+
+void window_set_cursor(Window *win, int curs) {
+ if (curs==CURSOR_NONE) {
+ GHOST_SetCursorVisibility(win->ghostwin, 0);
+ } else {
+ GHOST_SetCursorVisibility(win->ghostwin, 1);
+ GHOST_SetCursorShape(win->ghostwin, convert_cursor(curs));
+ }
+}
+
+void window_set_custom_cursor(Window *win, unsigned char mask[16][2], unsigned char bitmap[16][2]) {
+ GHOST_SetCustomCursorShape(win->ghostwin, bitmap, mask, 7, 7);
+}
+
+void window_make_active(Window *win) {
+ if (win != active_gl_window) {
+ active_gl_window= win;
+ GHOST_ActivateWindowDrawingContext(win->ghostwin);
+ }
+}
+void window_swap_buffers(Window *win) {
+ GHOST_SwapWindowBuffers(win->ghostwin);
+}
+
+static int query_qual(char qual) {
+ GHOST_TModifierKeyMask left, right;
+ int val= 0;
+
+ if (qual=='s') {
+ left= GHOST_kModifierKeyLeftShift;
+ right= GHOST_kModifierKeyRightShift;
+ } else if (qual=='c') {
+ left= GHOST_kModifierKeyLeftControl;
+ right= GHOST_kModifierKeyRightControl;
+ } else if (qual=='C') {
+ left= right= GHOST_kModifierKeyCommand;
+ } else {
+ left= GHOST_kModifierKeyLeftAlt;
+ right= GHOST_kModifierKeyRightAlt;
+ }
+
+ GHOST_GetModifierKeyState(g_system, left, &val);
+ if (!val)
+ GHOST_GetModifierKeyState(g_system, right, &val);
+
+ return val;
+}
+static int change_bit(int val, int bit, int to_on) {
+ return to_on?(val|bit):(val&~bit);
+}
+static int event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr private) {
+ GHOST_TEventType type= GHOST_GetEventType(evt);
+
+ if (type == GHOST_kEventQuit) {
+ exit_usiblender();
+ } else {
+ GHOST_WindowHandle ghostwin= GHOST_GetEventWindow(evt);
+ GHOST_TEventDataPtr data= GHOST_GetEventData(evt);
+ Window *win;
+
+ if (!ghostwin) {
+ printf("GHOST event error - no window - type: %d\n", type);
+ return 1;
+ } else if (!GHOST_ValidWindow(g_system, ghostwin)) {
+ printf("GHOST event error - invalid window - win: %p\n", ghostwin);
+ return 1;
+ } else {
+ win= GHOST_GetWindowUserData(ghostwin);
+ }
+
+ switch (type) {
+ case GHOST_kEventCursorMove: {
+ GHOST_TEventCursorData *cd= data;
+ int cx, cy;
+
+ GHOST_ScreenToClient(win->ghostwin, cd->x, cd->y, &cx, &cy);
+ win->lmouse[0]= cx;
+ win->lmouse[1]= (win->size[1]-1) - cy;
+
+ window_handle(win, MOUSEX, win->lmouse[0]);
+ window_handle(win, MOUSEY, win->lmouse[1]);
+
+ break;
+ }
+ case GHOST_kEventButtonDown:
+ case GHOST_kEventButtonUp: {
+ GHOST_TEventButtonData *bd= data;
+ int val= (type==GHOST_kEventButtonDown);
+ int bbut= convert_mbut(bd->button);
+
+ if (bbut==LEFTMOUSE) {
+ if (val) {
+ if (win->commandqual) {
+ bbut= win->faked_mbut= RIGHTMOUSE;
+ } else if (win->lqual & LR_ALTKEY) {
+ bbut= win->faked_mbut= MIDDLEMOUSE;
+ }
+ } else {
+ if (win->faked_mbut) {
+ bbut= win->faked_mbut;
+ win->faked_mbut= 0;
+ }
+ }
+ }
+
+ if (bbut==LEFTMOUSE) {
+ win->lmbut= change_bit(win->lmbut, L_MOUSE, val);
+ } else if (bbut==MIDDLEMOUSE) {
+ win->lmbut= change_bit(win->lmbut, M_MOUSE, val);
+ } else {
+ win->lmbut= change_bit(win->lmbut, R_MOUSE, val);
+ }
+ window_handle(win, bbut, val);
+
+ break;
+ }
+
+ case GHOST_kEventKeyDown:
+ case GHOST_kEventKeyUp: {
+ GHOST_TEventKeyData *kd= data;
+ int val= (type==GHOST_kEventKeyDown);
+ int bkey= convert_key(kd->key);
+
+ if (kd->key == GHOST_kKeyCommand) {
+ win->commandqual= val;
+ }
+
+ if (bkey) {
+ if (bkey==LEFTSHIFTKEY || bkey==RIGHTSHIFTKEY) {
+ win->lqual= change_bit(win->lqual, LR_SHIFTKEY, val);
+ } else if (bkey==LEFTCTRLKEY || bkey==RIGHTCTRLKEY) {
+ win->lqual= change_bit(win->lqual, LR_CTRLKEY, val);
+ } else if (bkey==LEFTALTKEY || bkey==RIGHTALTKEY) {
+ win->lqual= change_bit(win->lqual, LR_ALTKEY, val);
+ }
+
+ window_handle_ext(win, bkey, val, kd->ascii);
+ }
+
+ break;
+ }
+
+ case GHOST_kEventWindowDeactivate:
+ case GHOST_kEventWindowActivate: {
+ win->active= (type==GHOST_kEventWindowActivate);
+ window_handle(win, INPUTCHANGE, win->active);
+
+ if (win->active) {
+ if ((win->lqual & LR_SHIFTKEY) && !query_qual('s')) {
+ win->lqual= change_bit(win->lqual, LR_SHIFTKEY, 0);
+ window_handle(win, LEFTSHIFTKEY, 0);
+ }
+ if ((win->lqual & LR_CTRLKEY) && !query_qual('c')) {
+ win->lqual= change_bit(win->lqual, LR_CTRLKEY, 0);
+ window_handle(win, LEFTCTRLKEY, 0);
+ }
+ if ((win->lqual & LR_ALTKEY) && !query_qual('a')) {
+ win->lqual= change_bit(win->lqual, LR_ALTKEY, 0);
+ window_handle(win, LEFTALTKEY, 0);
+ }
+ win->commandqual= query_qual('C');
+
+ /*
+ * XXX quick hack so OSX version works better
+ * when the window is clicked on (focused).
+ */
+ window_handle(win, MOUSEX, win->lmouse[0]);
+ window_handle(win, MOUSEY, win->lmouse[1]);
+ }
+
+ break;
+ }
+ case GHOST_kEventWindowClose: {
+ window_handle(win, WINCLOSE, 1);
+ break;
+ }
+ case GHOST_kEventWindowUpdate: {
+ window_handle(win, REDRAW, 1);
+ break;
+ }
+ case GHOST_kEventWindowSize: {
+ GHOST_RectangleHandle client_rect;
+ int l, t, r, b, scr_w, scr_h;
+
+ client_rect= GHOST_GetClientBounds(win->ghostwin);
+ GHOST_GetRectangle(client_rect, &l, &t, &r, &b);
+
+ GHOST_DisposeRectangle(client_rect);
+
+ winlay_get_screensize(&scr_w, &scr_h);
+ win->position[0]= l;
+ win->position[1]= scr_h - b - 1;
+ win->size[0]= r-l;
+ win->size[1]= b-t;
+
+ window_handle(win, RESHAPE, 1);
+ break;
+ }
+ }
+ }
+
+ return 1;
+}
+
+char *window_get_title(Window *win) {
+ char *title= GHOST_GetTitle(win->ghostwin);
+ char *mem_title= BLI_strdup(title);
+ free(title);
+
+ return mem_title;
+}
+void window_set_title(Window *win, char *title) {
+ GHOST_SetTitle(win->ghostwin, title);
+}
+
+short window_get_qual(Window *win) {
+ return win->lqual;
+}
+short window_get_mbut(Window *win) {
+ return win->lmbut;
+}
+void window_get_mouse(Window *win, short *mval) {
+ mval[0]= win->lmouse[0];
+ mval[1]= win->lmouse[1];
+}
+void window_get_position(Window *win, int *posx_r, int *posy_r) {
+ *posx_r= win->position[0];
+ *posy_r= win->position[1];
+}
+void window_get_size(Window *win, int *width_r, int *height_r) {
+ *width_r= win->size[0];
+ *height_r= win->size[1];
+}
+
+void window_set_size(Window *win, int width, int height) {
+ GHOST_SetClientSize(win->ghostwin, width, height);
+}
+
+void window_lower(Window *win) {
+ GHOST_SetWindowOrder(win->ghostwin, GHOST_kWindowOrderBottom);
+}
+void window_raise(Window *win) {
+ GHOST_SetWindowOrder(win->ghostwin, GHOST_kWindowOrderTop);
+}
+
+void window_warp_pointer(Window *win, int x, int y) {
+ y= win->size[1] - y - 1;
+ GHOST_ClientToScreen(win->ghostwin, x, y, &x, &y);
+ GHOST_SetCursorPosition(g_system, x, y);
+}
+
+void window_queue_redraw(Window *win) {
+ GHOST_InvalidateWindow(win->ghostwin);
+}
+
+/***/
+
+void winlay_process_events(int wait_for_event) {
+ GHOST_ProcessEvents(g_system, wait_for_event);
+ GHOST_DispatchEvents(g_system);
+}
+
+void winlay_get_screensize(int *width_r, int *height_r) {
+ unsigned int uiwidth;
+ unsigned int uiheight;
+
+ if (!g_system) {
+ GHOST_EventConsumerHandle consumer= GHOST_CreateEventConsumer(event_proc, NULL);
+
+ g_system= GHOST_CreateSystem();
+ GHOST_AddEventConsumer(g_system, consumer);
+ }
+
+ GHOST_GetMainDisplayDimensions(g_system, &uiwidth, &uiheight);
+ *width_r= uiwidth;
+ *height_r= uiheight;
+}
+
+Window *winlay_get_active_window(void) {
+ return active_gl_window;
+}
diff --git a/source/blender/src/glutil.c b/source/blender/src/glutil.c
new file mode 100644
index 00000000000..c6144e36ae6
--- /dev/null
+++ b/source/blender/src/glutil.c
@@ -0,0 +1,411 @@
+
+
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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>
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_vec_types.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+ /* Invert line handling */
+
+#define glToggle(mode, onoff) (((onoff)?glEnable:glDisable)(mode))
+
+static void set_inverted_drawing(int enable)
+{
+ glLogicOp(enable?GL_INVERT:GL_COPY);
+
+ /* Use GL_BLEND_EQUATION_EXT on sgi (if we have it),
+ * apparently GL_COLOR_LOGIC_OP doesn't work on O2?
+ * Is this an sgi bug or our bug?
+ */
+#if defined(__sgi) && defined(GL_BLEND_EQUATION_EXT)
+ glBlendEquationEXT(enable?GL_LOGIC_OP:GL_FUNC_ADD_EXT);
+ glToggle(GL_BLEND, enable);
+#else
+ glToggle(GL_COLOR_LOGIC_OP, enable);
+#endif
+
+ glToggle(GL_DITHER, !enable);
+}
+
+void sdrawXORline(int x0, int y0, int x1, int y1)
+{
+ if(x0==x1 && y0==y1) return;
+
+ set_inverted_drawing(1);
+
+ glBegin(GL_LINES);
+ glVertex2i(x0, y0);
+ glVertex2i(x1, y1);
+ glEnd();
+
+ set_inverted_drawing(0);
+}
+
+void glutil_draw_front_xor_line(int x0, int y0, int x1, int y1)
+{
+ glDrawBuffer(GL_FRONT);
+ sdrawXORline(x0, y0, x1, y1);
+ glFinish();
+ glDrawBuffer(GL_BACK);
+}
+
+void sdrawXORline4(int nr, int x0, int y0, int x1, int y1)
+{
+ static short old[4][2][2];
+ static char flags[4]= {0, 0, 0, 0};
+
+ /* automatische onthoud, max 4 lijnen */
+
+ set_inverted_drawing(1);
+
+ glBegin(GL_LINES);
+ if(nr== -1) { /* flush */
+ for (nr=0; nr<4; nr++) {
+ if (flags[nr]) {
+ glVertex2sv(old[nr][0]);
+ glVertex2sv(old[nr][1]);
+ flags[nr]= 0;
+ }
+ }
+ } else {
+ if(nr>=0 && nr<4) {
+ if(flags[nr]) {
+ glVertex2sv(old[nr][0]);
+ glVertex2sv(old[nr][1]);
+ }
+
+ old[nr][0][0]= x0;
+ old[nr][0][1]= y0;
+ old[nr][1][0]= x1;
+ old[nr][1][1]= y1;
+
+ flags[nr]= 1;
+ }
+
+ glVertex2i(x0, y0);
+ glVertex2i(x1, y1);
+ }
+ glEnd();
+
+ set_inverted_drawing(0);
+}
+
+void sdrawXORcirc(short xofs, short yofs, float rad)
+{
+ set_inverted_drawing(1);
+
+ glPushMatrix();
+ glTranslatef(xofs, yofs, 0.0);
+ glutil_draw_lined_arc(0.0, M_PI*2, rad, 20);
+ glPopMatrix();
+
+ set_inverted_drawing(0);
+}
+
+void glutil_draw_filled_arc(float start, float angle, float radius, int nsegments) {
+ int i;
+
+ glBegin(GL_TRIANGLE_FAN);
+ glVertex2f(0.0, 0.0);
+ for (i=0; i<nsegments; i++) {
+ float t= (float) i/(nsegments-1);
+ float cur= start + t*angle;
+
+ glVertex2f(cos(cur)*radius, sin(cur)*radius);
+ }
+ glEnd();
+}
+
+void glutil_draw_lined_arc(float start, float angle, float radius, int nsegments) {
+ int i;
+
+ glBegin(GL_LINE_STRIP);
+ for (i=0; i<nsegments; i++) {
+ float t= (float) i/(nsegments-1);
+ float cur= start + t*angle;
+
+ glVertex2f(cos(cur)*radius, sin(cur)*radius);
+ }
+ glEnd();
+}
+
+int glaGetOneInteger(int param)
+{
+ int i;
+ glGetIntegerv(param, &i);
+ return i;
+}
+
+float glaGetOneFloat(int param)
+{
+ float v;
+ glGetFloatv(param, &v);
+ return v;
+}
+
+void glaRasterPosSafe2f(float x, float y, float known_good_x, float known_good_y)
+{
+ GLubyte dummy= 0;
+
+ /* As long as known good coordinates are correct
+ * this is guarenteed to generate an ok raster
+ * position (ignoring potential (real) overflow
+ * issues).
+ */
+ glRasterPos2f(known_good_x, known_good_y);
+
+ /* Now shift the raster position to where we wanted
+ * it in the first place using the glBitmap trick.
+ */
+ glBitmap(1, 1, 0, 0, x - known_good_x, y - known_good_y, &dummy);
+}
+
+static int get_cached_work_texture(int *w_r, int *h_r)
+{
+ static int texid= -1;
+ static int tex_w= 256;
+ static int tex_h= 256;
+
+ if (texid==-1) {
+ GLint ltexid= glaGetOneInteger(GL_TEXTURE_2D);
+ unsigned char *tbuf;
+
+ glGenTextures(1, &texid);
+
+ glBindTexture(GL_TEXTURE_2D, texid);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+
+ tbuf= MEM_callocN(tex_w*tex_h*4, "tbuf");
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, tex_w, tex_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, tbuf);
+ MEM_freeN(tbuf);
+
+ glBindTexture(GL_TEXTURE_2D, ltexid);
+ }
+
+ *w_r= tex_w;
+ *h_r= tex_h;
+ return texid;
+}
+
+void glaDrawPixelsTex(float x, float y, int img_w, int img_h, void *rect)
+{
+ unsigned char *uc_rect= (unsigned char*) rect;
+ float xzoom= glaGetOneFloat(GL_ZOOM_X), yzoom= glaGetOneFloat(GL_ZOOM_Y);
+ int ltexid= glaGetOneInteger(GL_TEXTURE_2D);
+ int lrowlength= glaGetOneInteger(GL_UNPACK_ROW_LENGTH);
+ int subpart_x, subpart_y, tex_w, tex_h;
+ int texid= get_cached_work_texture(&tex_w, &tex_h);
+ int nsubparts_x= (img_w+(tex_w-1))/tex_w;
+ int nsubparts_y= (img_h+(tex_h-1))/tex_h;
+
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, img_w);
+ glBindTexture(GL_TEXTURE_2D, texid);
+
+ for (subpart_y=0; subpart_y<nsubparts_y; subpart_y++) {
+ for (subpart_x=0; subpart_x<nsubparts_x; subpart_x++) {
+ int subpart_w= (subpart_x==nsubparts_x-1)?(img_w-subpart_x*tex_w):tex_w;
+ int subpart_h= (subpart_y==nsubparts_y-1)?(img_h-subpart_y*tex_h):tex_h;
+ float rast_x= x+subpart_x*tex_w*xzoom;
+ float rast_y= y+subpart_y*tex_h*yzoom;
+
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, subpart_w, subpart_h, GL_RGBA, GL_UNSIGNED_BYTE, &uc_rect[(subpart_y*tex_w)*img_w*4 + (subpart_x*tex_w)*4]);
+
+ glColor3ub(255, 255, 255);
+ glEnable(GL_TEXTURE_2D);
+ glBegin(GL_QUADS);
+ glTexCoord2f(0, 0);
+ glVertex2f(rast_x, rast_y);
+
+ glTexCoord2f((float) subpart_w/tex_w, 0);
+ glVertex2f(rast_x+subpart_w*xzoom, rast_y);
+
+ glTexCoord2f((float) subpart_w/tex_w, (float) subpart_h/tex_h);
+ glVertex2f(rast_x+subpart_w*xzoom, rast_y+subpart_h*yzoom);
+
+ glTexCoord2f(0, (float) subpart_h/tex_h);
+ glVertex2f(rast_x, rast_y+subpart_h*yzoom);
+ glEnd();
+ glDisable(GL_TEXTURE_2D);
+ }
+ }
+
+ glBindTexture(GL_TEXTURE_2D, ltexid);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, lrowlength);
+}
+
+void glaDrawPixelsSafe(float x, float y, int img_w, int img_h, void *rect)
+{
+ unsigned char *uc_rect= (unsigned char*) rect;
+ float origin_x= 0.375;
+ float origin_y= 0.375;
+
+ /* Trivial case */
+ if (x>=origin_x && y>=origin_y) {
+ glRasterPos2f(x, y);
+ glDrawPixels(img_w, img_h, GL_RGBA, GL_UNSIGNED_BYTE, uc_rect);
+ } else {
+ int old_row_length= glaGetOneInteger(GL_UNPACK_ROW_LENGTH);
+ float xzoom= glaGetOneFloat(GL_ZOOM_X);
+ float yzoom= glaGetOneFloat(GL_ZOOM_Y);
+
+ /* The pixel space coordinate of the intersection of
+ * the [zoomed] image with the origin.
+ */
+ float ix= (origin_x-x)/xzoom;
+ float iy= (origin_y-y)/yzoom;
+
+ /* The maximum pixel amounts the image can cropped
+ * without exceeding the origin.
+ */
+ int off_x= floor((ix>origin_x)?ix:origin_x);
+ int off_y= floor((iy>origin_y)?iy:origin_y);
+
+ /* The zoomed space coordinate of the raster
+ * position.
+ */
+ float rast_x= x + off_x*xzoom;
+ float rast_y= y + off_y*yzoom;
+
+ if (off_x<img_w && off_y<img_h) {
+ glaRasterPosSafe2f(rast_x, rast_y, origin_x, origin_y);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, img_w);
+ glDrawPixels(img_w-off_x, img_h-off_y, GL_RGBA, GL_UNSIGNED_BYTE, uc_rect+off_y*img_w*4+off_x*4);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, old_row_length);
+ }
+ }
+}
+
+/* 2D Drawing Assistance */
+
+void glaDefine2DArea(rcti *screen_rect)
+{
+ int sc_w= screen_rect->xmax - screen_rect->xmin;
+ int sc_h= screen_rect->ymax - screen_rect->ymin;
+
+ glViewport(screen_rect->xmin, screen_rect->ymin, sc_w, sc_h);
+ glScissor(screen_rect->xmin, screen_rect->ymin, sc_w, sc_h);
+
+ /* The 0.375 magic number is to shift the matrix so that
+ * both raster and vertex integer coordinates fall at pixel
+ * centers properly. For a longer discussion see the OpenGL
+ * Programming Guide, Appendix H, Correctness Tips.
+ */
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(0.0, sc_w, 0.0, sc_h, -1, 1);
+ glTranslatef(0.375, 0.375, 0.0);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+}
+
+struct gla2DDrawInfo {
+ int orig_vp[4], orig_sc[4];
+ float orig_projmat[16], orig_viewmat[16];
+
+ rcti screen_rect;
+ rctf world_rect;
+
+ float wo_to_sc[2];
+};
+
+gla2DDrawInfo *glaBegin2DDraw(rcti *screen_rect, rctf *world_rect)
+{
+ gla2DDrawInfo *di= MEM_mallocN(sizeof(*di), "gla2DDrawInfo");
+ int sc_w, sc_h;
+ float wo_w, wo_h;
+
+ glGetIntegerv(GL_VIEWPORT, di->orig_vp);
+ glGetIntegerv(GL_SCISSOR_BOX, di->orig_sc);
+ glGetFloatv(GL_PROJECTION_MATRIX, di->orig_projmat);
+ glGetFloatv(GL_MODELVIEW_MATRIX, di->orig_viewmat);
+
+ di->screen_rect= *screen_rect;
+ if (world_rect) {
+ di->world_rect= *world_rect;
+ } else {
+ di->world_rect.xmin= di->screen_rect.xmin;
+ di->world_rect.ymin= di->screen_rect.ymin;
+ di->world_rect.xmax= di->screen_rect.xmax;
+ di->world_rect.ymax= di->screen_rect.ymax;
+ }
+
+ sc_w= (di->screen_rect.xmax-di->screen_rect.xmin);
+ sc_h= (di->screen_rect.ymax-di->screen_rect.ymin);
+ wo_w= (di->world_rect.xmax-di->world_rect.xmin);
+ wo_h= (di->world_rect.ymax-di->world_rect.ymin);
+
+ di->wo_to_sc[0]= sc_w/wo_w;
+ di->wo_to_sc[1]= sc_h/wo_h;
+
+ glaDefine2DArea(&di->screen_rect);
+
+ return di;
+}
+
+void gla2DDrawTranslatePt(gla2DDrawInfo *di, float wo_x, float wo_y, int *sc_x_r, int *sc_y_r)
+{
+ *sc_x_r= (wo_x - di->world_rect.xmin)*di->wo_to_sc[0];
+ *sc_y_r= (wo_y - di->world_rect.ymin)*di->wo_to_sc[1];
+}
+void gla2DDrawTranslatePtv(gla2DDrawInfo *di, float world[2], int screen_r[2])
+{
+ screen_r[0]= (world[0] - di->world_rect.xmin)*di->wo_to_sc[0];
+ screen_r[1]= (world[1] - di->world_rect.ymin)*di->wo_to_sc[1];
+}
+
+void glaEnd2DDraw(gla2DDrawInfo *di)
+{
+ glViewport(di->orig_vp[0], di->orig_vp[1], di->orig_vp[2], di->orig_vp[3]);
+ glScissor(di->orig_vp[0], di->orig_vp[1], di->orig_vp[2], di->orig_vp[3]);
+ glMatrixMode(GL_PROJECTION);
+ glLoadMatrixf(di->orig_projmat);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadMatrixf(di->orig_viewmat);
+
+ MEM_freeN(di);
+}
diff --git a/source/blender/src/headerbuttons.c b/source/blender/src/headerbuttons.c
new file mode 100644
index 00000000000..71cbac51dea
--- /dev/null
+++ b/source/blender/src/headerbuttons.c
@@ -0,0 +1,5577 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 <string.h>
+#include <math.h>
+
+#include <sys/types.h>
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "BMF_Api.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+#include "BLI_storage_types.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "DNA_ID.h"
+#include "DNA_action_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_group_types.h"
+#include "DNA_image_types.h"
+#include "DNA_ipo_types.h"
+#include "DNA_key_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_lattice_types.h"
+#include "DNA_material_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meta_types.h"
+#include "DNA_object_types.h"
+#include "DNA_oops_types.h"
+#include "DNA_packedFile_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_sequence_types.h"
+#include "DNA_sound_types.h"
+#include "DNA_space_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_text_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_view2d_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_world_types.h"
+#include "DNA_constraint_types.h"
+
+#include "BKE_utildefines.h"
+
+#include "BKE_constraint.h"
+#include "BKE_action.h"
+#include "BKE_armature.h"
+#include "BKE_blender.h"
+#include "BKE_curve.h"
+#include "BKE_displist.h"
+#include "BKE_exotic.h"
+#include "BKE_global.h"
+#include "BKE_image.h"
+#include "BKE_ika.h"
+#include "BKE_ipo.h"
+#include "BKE_key.h"
+#include "BKE_lattice.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+#include "BKE_material.h"
+#include "BKE_mball.h"
+#include "BKE_mesh.h"
+#include "BKE_object.h"
+#include "BKE_packedFile.h"
+#include "BKE_sca.h"
+#include "BKE_scene.h"
+#include "BKE_texture.h"
+#include "BKE_text.h"
+#include "BKE_world.h"
+
+#include "BLO_readfile.h"
+#include "BLO_writefile.h"
+
+#include "BIF_drawimage.h"
+#include "BIF_drawoops.h"
+#include "BIF_drawscene.h"
+#include "BIF_drawtext.h"
+#include "BIF_editarmature.h"
+#include "BIF_editfont.h"
+#include "BIF_editlattice.h"
+#include "BIF_editconstraint.h"
+#include "BIF_editmesh.h"
+#include "BIF_editmesh.h"
+#include "BIF_editsima.h"
+#include "BIF_editsound.h"
+#include "BIF_editsound.h"
+#include "BIF_gl.h"
+#include "BIF_imasel.h"
+#include "BIF_interface.h"
+#include "BIF_mainqueue.h"
+#include "BIF_mywindow.h"
+#include "BIF_poseobject.h"
+#include "BIF_renderwin.h"
+#include "BIF_resources.h"
+#include "BIF_screen.h"
+#include "BIF_space.h"
+#include "BIF_toets.h"
+#include "BIF_toets.h"
+#include "BIF_toolbox.h"
+#include "BIF_usiblender.h"
+#include "BIF_previewrender.h"
+#include "BIF_writeimage.h"
+
+#include "BSE_edit.h"
+#include "BSE_filesel.h"
+#include "BSE_headerbuttons.h"
+#include "BSE_view.h"
+#include "BSE_sequence.h"
+#include "BSE_editaction.h"
+#include "BSE_editaction_types.h"
+#include "BSE_editipo.h"
+#include "BSE_drawipo.h"
+
+#include "BDR_drawmesh.h"
+#include "BDR_vpaint.h"
+#include "BDR_editface.h"
+#include "BDR_editobject.h"
+#include "BDR_editcurve.h"
+#include "BDR_editmball.h"
+
+#include "BPY_extern.h" // Blender Python library
+
+#include "interface.h"
+#include "mydevice.h"
+#include "blendef.h"
+#include "render.h"
+#include "ipo.h"
+#include "nla.h" /* __NLA : To be removed later */
+
+#include "TPT_DependKludge.h"
+
+/* these are needed to hide functions behind function tables,
+ which are initialized by the python key code */
+#include "keyed_functions.h"
+#include "license_key.h"
+
+/* local (?) functions */
+void do_file_buttons(short event);
+void do_text_buttons(unsigned short event);
+void load_space_sound(char *str);
+void load_sound_buttons(char *str);
+void load_space_image(char *str);
+void image_replace(Image *old, Image *new);
+void replace_space_image(char *str);
+void do_image_buttons(unsigned short event);
+void do_imasel_buttons(short event);
+static void check_packAll(void);
+static void unique_bone_name(Bone *bone, bArmature *arm);
+static void validate_bonebutton(void *data1, void *data2);
+static int bonename_exists(Bone *orig, char *name, ListBase *list);
+
+static void test_idbutton_cb(void *namev, void *arg2_unused)
+{
+ char *name= namev;
+ test_idbutton(name+2);
+}
+
+#define SPACEICONMAX 13 /* See release/datafiles/blenderbuttons */
+
+#include "BIF_poseobject.h"
+
+#include "SYS_System.h"
+
+#include "license_key.h"
+static int std_libbuttons(uiBlock *block,
+ int xco, int pin, short *pinpoin,
+ int browse, ID *id, ID *parid,
+ short *menupoin, int users,
+ int lib, int del, int autobut);
+
+
+extern char versionstr[]; /* from blender.c */
+/* extern void add_text_fs(char *file); *//* from text.c, BIF_text.h*/
+
+ /* LET OP: alle headerbuttons voor zelfde window steeds zelfde naam
+ * event B_REDR is standaard redraw
+ *
+ */
+
+
+/*
+ * The next define turns the newest menu structure on.
+ * There are some loose ends here at the moment so leave this undefined for now.
+ */
+/* #define EXPERIMENTAL_MENUS */
+
+
+#define XIC 20
+#define YIC 20
+
+static int viewmovetemp=0;
+
+/* extern void info_buttons(); in BSE_headerbuttons.c */
+
+extern char videosc_dir[]; /* exotic.c */
+
+/* *********************************************************************** */
+
+void write_videoscape_fs()
+{
+ if(G.obedit) {
+ error("Can't save Videoscape. Press TAB to leave EditMode");
+ }
+ else {
+ if(videosc_dir[0]==0) strcpy(videosc_dir, G.sce);
+ activate_fileselect(FILE_SPECIAL, "SAVE VIDEOSCAPE", videosc_dir, write_videoscape);
+ }
+}
+
+void write_vrml_fs()
+{
+ if(G.obedit) {
+ error("Can't save VRML. Press TAB to leave EditMode");
+ }
+ else {
+ if(videosc_dir[0]==0) strcpy(videosc_dir, G.sce);
+
+ activate_fileselect(FILE_SPECIAL, "SAVE VRML1", videosc_dir, write_vrml);
+ }
+
+}
+
+void write_dxf_fs()
+{
+ if(G.obedit) {
+ error("Can't save DXF. Press TAB to leave EditMode");
+ }
+ else {
+
+ if(videosc_dir[0]==0) strcpy(videosc_dir, G.sce);
+
+ activate_fileselect(FILE_SPECIAL, "SAVE DXF", videosc_dir, write_dxf);
+ }
+}
+
+/* ********************** GLOBAL ****************************** */
+
+static int std_libbuttons(uiBlock *block, int xco, int pin, short *pinpoin, int browse, ID *id, ID *parid, short *menupoin, int users, int lib, int del, int autobut)
+{
+ ListBase *lb;
+ Object *ob;
+ Ipo *ipo;
+ uiBut *but;
+ int len, idwasnul=0, idtype, oldcol;
+ char *str=NULL, str1[10];
+
+ oldcol= uiBlockGetCol(block);
+
+ if(id && pin) {
+ uiDefIconButS(block, ICONTOG, pin, ICON_PIN_DEHLT, (short)xco,0,XIC,YIC, pinpoin, 0, 0, 0, 0, "Pin this data block; no update according Object selection");
+ xco+= XIC;
+ }
+ if(browse) {
+ if(id==0) {
+ idwasnul= 1;
+ /* alleen de browse button */
+ ob= OBACT;
+ if(curarea->spacetype==SPACE_IMAGE) {
+ id= G.main->image.first;
+ }
+ else if(curarea->spacetype==SPACE_SOUND) {
+ id= G.main->sound.first;
+ }
+ else if(curarea->spacetype==SPACE_ACTION) {
+ id= G.main->action.first;
+ }
+ else if(curarea->spacetype==SPACE_NLA) {
+ id=NULL;
+ }
+ else if(curarea->spacetype==SPACE_IPO) {
+ id= G.main->ipo.first;
+ /* testen op ipotype */
+ while(id) {
+ ipo= (Ipo *)id;
+ if(G.sipo->blocktype==ipo->blocktype) break;
+ id= id->next;
+ }
+ }
+ else if(curarea->spacetype==SPACE_BUTS) {
+ if(browse==B_WORLDBROWSE) {
+ id= G.main->world.first;
+ }
+ else if(ob && ob->type && (ob->type<OB_LAMP)) {
+ if(G.buts->mainb==BUTS_MAT) id= G.main->mat.first;
+ else if(G.buts->mainb==BUTS_TEX) id= G.main->tex.first;
+ }
+ }
+ else if(curarea->spacetype==SPACE_TEXT) {
+ id= G.main->text.first;
+ }
+ }
+ if(id) {
+ char *extrastr= NULL;
+
+ idtype= GS(id->name);
+ lb= wich_libbase(G.main, GS(id->name));
+
+ if(idwasnul) id= NULL;
+ else if(id->us>1) uiBlockSetCol(block, BUTDBLUE);
+
+ if (pin && *pinpoin) {
+ uiBlockSetCol(block, BUTDPINK);
+ }
+
+ if ELEM7( idtype, ID_SCE, ID_SCR, ID_MA, ID_TE, ID_WO, ID_IP, ID_AC) extrastr= "ADD NEW %x 32767";
+ else if (idtype==ID_TXT) extrastr= "OPEN NEW %x 32766 |ADD NEW %x 32767";
+ else if (idtype==ID_SO) extrastr= "OPEN NEW %x 32766";
+
+ uiSetButLock(G.scene->id.lib!=0, "Can't edit library data");
+ if( idtype==ID_SCE || idtype==ID_SCR ) uiClearButLock();
+
+ if(curarea->spacetype==SPACE_BUTS)
+ uiSetButLock(idtype!=ID_SCR && G.obedit!=0 && G.buts->mainb==BUTS_EDIT, NULL);
+
+ if(parid) uiSetButLock(parid->lib!=0, "Can't edit library data");
+
+ if (lb) {
+ if( idtype==ID_IP)
+ IPOnames_to_pupstring(&str, NULL, extrastr, lb, id, menupoin, G.sipo->blocktype);
+ else
+ IDnames_to_pupstring(&str, NULL, extrastr, lb, id, menupoin);
+ }
+
+ uiDefButS(block, MENU, browse, str, (short)xco,0,XIC,YIC, menupoin, 0, 0, 0, 0, "Browse Datablock or Add NEW");
+
+ uiClearButLock();
+
+ MEM_freeN(str);
+ xco+= XIC;
+ }
+ else if(curarea->spacetype==SPACE_BUTS) {
+ if ELEM3(G.buts->mainb, BUTS_MAT, BUTS_TEX, BUTS_WORLD) {
+ uiSetButLock(G.scene->id.lib!=0, "Can't edit library data");
+ if(parid) uiSetButLock(parid->lib!=0, "Can't edit library data");
+ uiDefButS(block, MENU, browse, "ADD NEW %x 32767",(short) xco,0,XIC,YIC, menupoin, 0, 0, 0, 0, "Browse Datablock");
+ uiClearButLock();
+ } else if (G.buts->mainb == BUTS_SOUND) {
+ uiDefButS(block, MENU, browse, "OPEN NEW %x 32766",(short) xco,0,XIC,YIC, menupoin, 0, 0, 0, 0, "Browse Datablock");
+ }
+ }
+ else if(curarea->spacetype==SPACE_TEXT) {
+ uiDefButS(block, MENU, browse, "OPEN NEW %x 32766 | ADD NEW %x 32767", (short)xco,0,XIC,YIC, menupoin, 0, 0, 0, 0, "Browse Datablock");
+ }
+ else if(curarea->spacetype==SPACE_SOUND) {
+ uiDefButS(block, MENU, browse, "OPEN NEW %x 32766",(short)xco,0,XIC,YIC, menupoin, 0, 0, 0, 0, "Browse Datablock");
+ }
+ else if(curarea->spacetype==SPACE_NLA) {
+ }
+ else if(curarea->spacetype==SPACE_ACTION) {
+ uiSetButLock(G.scene->id.lib!=0, "Can't edit library data");
+ if(parid) uiSetButLock(parid->lib!=0, "Can't edit library data");
+
+ uiDefButS(block, MENU, browse, "ADD NEW %x 32767", xco,0,XIC,YIC, menupoin, 0, 0, 0, 0, "Browse Datablock");
+ uiClearButLock();
+ }
+ else if(curarea->spacetype==SPACE_IPO) {
+ uiSetButLock(G.scene->id.lib!=0, "Can't edit library data");
+ if(parid) uiSetButLock(parid->lib!=0, "Can't edit library data");
+
+ uiDefButS(block, MENU, browse, "ADD NEW %x 32767", (short)xco,0,XIC,YIC, menupoin, 0, 0, 0, 0, "Browse Datablock");
+ uiClearButLock();
+ }
+ }
+
+
+ uiBlockSetCol(block, oldcol);
+
+ if(id) {
+
+ /* name */
+ if(id->us>1) uiBlockSetCol(block, BUTDBLUE);
+ /* Pinned data ? */
+ if (pin && *pinpoin) {
+ uiBlockSetCol(block, BUTDPINK);
+ }
+ /* Redalert overrides pin color */
+ if(id->us<=0) uiBlockSetCol(block, REDALERT);
+
+ uiSetButLock(id->lib!=0, "Can't edit library data");
+
+ str1[0]= id->name[0];
+ str1[1]= id->name[1];
+ str1[2]= ':';
+ str1[3]= 0;
+ if(strcmp(str1, "SC:")==0) strcpy(str1, "SCE:");
+ else if(strcmp(str1, "SR:")==0) strcpy(str1, "SCR:");
+
+ if( GS(id->name)==ID_IP) len= 110;
+ else len= 120;
+
+ but= uiDefBut(block, TEX, B_IDNAME, str1,(short)xco, 0, (short)len, YIC, id->name+2, 0.0, 19.0, 0, 0, "Datablock name");
+ uiButSetFunc(but, test_idbutton_cb, id->name, NULL);
+
+ uiClearButLock();
+
+ xco+= len;
+
+ if(id->lib) {
+
+ if(parid && parid->lib) uiDefIconBut(block, BUT, 0, ICON_DATALIB,(short)xco,0,XIC,YIC, 0, 0, 0, 0, 0, "Indirect Library Datablock");
+ else uiDefIconBut(block, BUT, lib, ICON_PARLIB, (short)xco,0,XIC,YIC, 0, 0, 0, 0, 0, "Library DataBlock, press to make local");
+
+ xco+= XIC;
+ }
+
+
+ if(users && id->us>1) {
+ uiSetButLock (pin && *pinpoin, "Can't make pinned data single-user");
+
+ sprintf(str1, "%d", id->us);
+ if(id->us<100) {
+
+ uiDefBut(block, BUT, users, str1, (short)xco,0,XIC,YIC, 0, 0, 0, 0, 0, "Number of users, press to make single-user");
+ xco+= XIC;
+ }
+ else {
+ uiDefBut(block, BUT, users, str1, (short)xco, 0, XIC+10, YIC, 0, 0, 0, 0, 0, "Number of users, press to make single-user");
+ xco+= XIC+10;
+ }
+
+ uiClearButLock();
+
+ }
+
+ if(del) {
+
+ uiSetButLock (pin && *pinpoin, "Can't unlink pinned data");
+ if(parid && parid->lib);
+ else {
+ uiDefIconBut(block, BUT, del, ICON_X, (short)xco,0,XIC,YIC, 0, 0, 0, 0, 0, "Delete link to this Datablock");
+ xco+= XIC;
+ }
+
+ uiClearButLock();
+ }
+
+ if(autobut) {
+ if(parid && parid->lib);
+ else {
+ uiDefIconBut(block, BUT, autobut, ICON_AUTO,(short)xco,0,XIC,YIC, 0, 0, 0, 0, 0, "Automatic name");
+ xco+= XIC;
+ }
+
+
+ }
+ }
+ else xco+=XIC;
+
+ uiBlockSetCol(block, oldcol);
+
+ return xco;
+}
+
+void update_for_newframe(void)
+{
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWACTION,0);
+ allqueue(REDRAWNLA,0);
+ allqueue(REDRAWIPO, 0);
+ allqueue(REDRAWINFO, 1);
+ allqueue(REDRAWSEQ, 1);
+ allqueue(REDRAWSOUND, 1);
+ allqueue(REDRAWBUTSHEAD, 1);
+ allqueue(REDRAWBUTSMAT, 1);
+ allqueue(REDRAWBUTSLAMP, 1);
+
+ /* layers/materials, object ipos are calculted in where_is_object (too) */
+ do_all_ipos();
+ BPY_do_all_scripts(SCRIPT_FRAMECHANGED);
+ do_all_keys();
+ do_all_actions();
+ do_all_ikas();
+
+ test_all_displists();
+}
+
+static void show_splash(void)
+{
+ extern char datatoc_splash_jpg[];
+ extern int datatoc_splash_jpg_size;
+ char *string = NULL;
+
+#ifdef NAN_BUILDINFO
+ char buffer[1024];
+ extern char * build_date;
+ extern char * build_time;
+ extern char * build_platform;
+ extern char * build_type;
+
+ string = &buffer[0];
+ sprintf(string,"Built on %s %s Version %s %s", build_date, build_time, build_platform, build_type);
+#endif
+
+ splash((void *)datatoc_splash_jpg, datatoc_splash_jpg_size, string);
+}
+
+void do_global_buttons(unsigned short event)
+{
+ ListBase *lb;
+ Object *ob;
+ Material *ma;
+ MTex *mtex;
+ Ipo *ipo;
+ Lamp *la;
+ World *wrld;
+ Sequence *seq;
+ bAction *act;
+ ID *id, *idtest, *from;
+ int nr= 1;
+
+ ob= OBACT;
+
+ id= 0; /* id op nul voor texbrowse */
+
+ switch(event) {
+
+ case B_NEWFRAME:
+ scrarea_queue_winredraw(curarea);
+ scrarea_queue_headredraw(curarea);
+
+ update_for_newframe();
+ break;
+ case B_REDR:
+ scrarea_queue_winredraw(curarea);
+ scrarea_queue_headredraw(curarea);
+ break;
+ case B_EDITBROWSE:
+ if(ob==0) return;
+ if(ob->id.lib) return;
+ id= ob->data;
+ if(id==0) return;
+
+ if(G.buts->menunr== -2) {
+ activate_databrowse((ID *)G.buts->lockpoin, GS(id->name), 0, B_EDITBROWSE, &G.buts->menunr, do_global_buttons);
+ return;
+ }
+ if(G.buts->menunr < 0) return;
+
+ lb= wich_libbase(G.main, GS(id->name));
+ idtest= lb->first;
+ while(idtest) {
+ if(nr==G.buts->menunr) {
+ if(idtest!=id) {
+ id->us--;
+ id_us_plus(idtest);
+
+ ob->data= idtest;
+
+ test_object_materials(idtest);
+
+ if( GS(idtest->name)==ID_CU ) {
+ test_curve_type(ob);
+ allqueue(REDRAWBUTSEDIT, 0);
+ makeDispList(ob);
+ }
+ else if( ob->type==OB_MESH ) {
+ makeDispList(ob);
+ }
+
+ allqueue(REDRAWBUTSEDIT, 0);
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWACTION,0);
+ allqueue(REDRAWIPO, 0);
+ allqueue(REDRAWNLA,0);
+ }
+ break;
+ }
+ nr++;
+ idtest= idtest->next;
+ }
+
+ break;
+ case B_MESHBROWSE:
+ if(ob==0) return;
+ if(ob->id.lib) return;
+
+ id= ob->data;
+ if(id==0) id= G.main->mesh.first;
+ if(id==0) return;
+
+ if(G.buts->menunr== -2) {
+ activate_databrowse((ID *)G.buts->lockpoin, GS(id->name), 0, B_MESHBROWSE, &G.buts->menunr, do_global_buttons);
+ return;
+ }
+ if(G.buts->menunr < 0) return;
+
+
+ idtest= G.main->mesh.first;
+ while(idtest) {
+ if(nr==G.buts->menunr) {
+
+ set_mesh(ob, (Mesh *)idtest);
+
+ allqueue(REDRAWBUTSEDIT, 0);
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWACTION,0);
+ allqueue(REDRAWIPO, 0);
+
+ break;
+ }
+ nr++;
+ idtest= idtest->next;
+ }
+
+ break;
+ case B_MATBROWSE:
+ if(G.buts->menunr== -2) {
+ activate_databrowse((ID *)G.buts->lockpoin, ID_MA, 0, B_MATBROWSE, &G.buts->menunr, do_global_buttons);
+ return;
+ }
+
+ if(G.buts->menunr < 0) return;
+
+ if(G.buts->pin) {
+
+ }
+ else {
+
+ ma= give_current_material(ob, ob->actcol);
+ nr= 1;
+
+ id= (ID *)ma;
+
+ idtest= G.main->mat.first;
+ while(idtest) {
+ if(nr==G.buts->menunr) {
+ break;
+ }
+ nr++;
+ idtest= idtest->next;
+ }
+ if(idtest==0) { /* new mat */
+ if(id) idtest= (ID *)copy_material((Material *)id);
+ else {
+ idtest= (ID *)add_material("Material");
+ }
+ idtest->us--;
+ }
+ if(idtest!=id) {
+ assign_material(ob, (Material *)idtest, ob->actcol);
+
+ allqueue(REDRAWBUTSHEAD, 0);
+ allqueue(REDRAWBUTSMAT, 0);
+ allqueue(REDRAWIPO, 0);
+ BIF_preview_changed(G.buts);
+ }
+
+ }
+ break;
+ case B_MATDELETE:
+ if(G.buts->pin) {
+
+ }
+ else {
+ ma= give_current_material(ob, ob->actcol);
+ if(ma) {
+ assign_material(ob, 0, ob->actcol);
+ allqueue(REDRAWBUTSHEAD, 0);
+ allqueue(REDRAWBUTSMAT, 0);
+ allqueue(REDRAWIPO, 0);
+ BIF_preview_changed(G.buts);
+ }
+ }
+ break;
+ case B_TEXDELETE:
+ if(G.buts->pin) {
+
+ }
+ else {
+ if(G.buts->texfrom==0) { /* from mat */
+ ma= give_current_material(ob, ob->actcol);
+ if(ma) {
+ mtex= ma->mtex[ ma->texact ];
+ if(mtex) {
+ if(mtex->tex) mtex->tex->id.us--;
+ MEM_freeN(mtex);
+ ma->mtex[ ma->texact ]= 0;
+ allqueue(REDRAWBUTSTEX, 0);
+ allqueue(REDRAWIPO, 0);
+ BIF_preview_changed(G.buts);
+ }
+ }
+ }
+ else if(G.buts->texfrom==1) { /* from world */
+ wrld= G.scene->world;
+ if(wrld) {
+ mtex= wrld->mtex[ wrld->texact ];
+ if(mtex) {
+ if(mtex->tex) mtex->tex->id.us--;
+ MEM_freeN(mtex);
+ wrld->mtex[ wrld->texact ]= 0;
+ allqueue(REDRAWBUTSTEX, 0);
+ allqueue(REDRAWIPO, 0);
+ BIF_preview_changed(G.buts);
+ }
+ }
+ }
+ else { /* from lamp */
+ la= ob->data;
+ if(la && ob->type==OB_LAMP) { /* voor zekerheid */
+ mtex= la->mtex[ la->texact ];
+ if(mtex) {
+ if(mtex->tex) mtex->tex->id.us--;
+ MEM_freeN(mtex);
+ la->mtex[ la->texact ]= 0;
+ allqueue(REDRAWBUTSTEX, 0);
+ allqueue(REDRAWIPO, 0);
+ BIF_preview_changed(G.buts);
+ }
+ }
+ }
+ }
+ break;
+ case B_EXTEXBROWSE:
+ case B_TEXBROWSE:
+
+ if(G.buts->texnr== -2) {
+
+ id= G.buts->lockpoin;
+ if(event==B_EXTEXBROWSE) {
+ id= 0;
+ ma= give_current_material(ob, ob->actcol);
+ if(ma) {
+ mtex= ma->mtex[ ma->texact ];
+ if(mtex) id= (ID *)mtex->tex;
+ }
+ }
+
+ activate_databrowse(id, ID_TE, 0, B_TEXBROWSE, &G.buts->texnr, do_global_buttons);
+ return;
+ }
+ if(G.buts->texnr < 0) break;
+
+ if(G.buts->pin) {
+
+ }
+ else {
+ id= 0;
+
+ ma= give_current_material(ob, ob->actcol);
+ if(ma) {
+ mtex= ma->mtex[ ma->texact ];
+ if(mtex) id= (ID *)mtex->tex;
+ }
+
+ idtest= G.main->tex.first;
+ while(idtest) {
+ if(nr==G.buts->texnr) {
+ break;
+ }
+ nr++;
+ idtest= idtest->next;
+ }
+ if(idtest==0) { /* new tex */
+ if(id) idtest= (ID *)copy_texture((Tex *)id);
+ else idtest= (ID *)add_texture("Tex");
+ idtest->us--;
+ }
+ if(idtest!=id && ma) {
+
+ if( ma->mtex[ma->texact]==0) ma->mtex[ma->texact]= add_mtex();
+
+ ma->mtex[ ma->texact ]->tex= (Tex *)idtest;
+ id_us_plus(idtest);
+ if(id) id->us--;
+
+ allqueue(REDRAWBUTSHEAD, 0);
+ allqueue(REDRAWBUTSTEX, 0);
+ allqueue(REDRAWBUTSMAT, 0);
+ allqueue(REDRAWIPO, 0);
+ BIF_preview_changed(G.buts);
+ }
+ }
+ break;
+ case B_ACTIONDELETE:
+ act=ob->action;
+
+ if (act)
+ act->id.us--;
+ ob->action=NULL;
+ allqueue(REDRAWACTION, 0);
+ allqueue(REDRAWNLA, 0);
+ allqueue(REDRAWIPO, 0);
+ break;
+ case B_ACTIONBROWSE:
+ if (!ob)
+ break;
+ act=ob->action;
+ id= (ID *)act;
+
+ if (G.saction->actnr== -2){
+ activate_databrowse((ID *)G.saction->action, ID_AC, 0, B_ACTIONBROWSE, &G.saction->actnr, do_global_buttons);
+ return;
+ }
+
+ if(G.saction->actnr < 0) break;
+
+ /* See if we have selected a valid action */
+ for (idtest= G.main->action.first; idtest; idtest= idtest->next) {
+ if(nr==G.saction->actnr) {
+ break;
+ }
+ nr++;
+
+ }
+
+ if(G.saction->pin) {
+ G.saction->action= (bAction *)idtest;
+ allqueue(REDRAWACTION, 0);
+ }
+ else {
+
+ /* Store current action */
+ if (!idtest){
+ if (act)
+ idtest= (ID *)copy_action(act);
+ else
+ idtest=(ID *)add_empty_action();
+ idtest->us--;
+ }
+
+
+ if(idtest!=id && ob) {
+ act= (bAction *)idtest;
+
+ ob->action= act;
+ ob->activecon=NULL;
+ id_us_plus(idtest);
+
+ if(id) id->us--;
+
+ // Update everything
+ do_global_buttons (B_NEWFRAME);
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWNLA, 0);
+ allqueue(REDRAWACTION, 0);
+ allqueue(REDRAWHEADERS, 0);
+ }
+ }
+
+ break;
+ case B_IPOBROWSE:
+
+ ipo= get_ipo_to_edit(&from);
+ id= (ID *)ipo;
+ if(from==0) return;
+
+ if(G.sipo->menunr== -2) {
+ activate_databrowse((ID *)G.sipo->ipo, ID_IP, GS(from->name), B_IPOBROWSE, &G.sipo->menunr, do_global_buttons);
+ return;
+ }
+
+ if(G.sipo->menunr < 0) break;
+
+ idtest= G.main->ipo.first;
+ while(idtest) {
+ if( ((Ipo *)idtest)->blocktype == G.sipo->blocktype) {
+ if(nr==G.sipo->menunr) {
+ break;
+ }
+ nr++;
+ }
+ idtest= idtest->next;
+ }
+
+ if(G.sipo->pin) {
+ if(idtest) {
+ G.sipo->ipo= (Ipo *)idtest;
+ allspace(REMAKEIPO, 0); // in fact it should only do this one, but there is no function for it
+ }
+ }
+ else {
+ // assign the ipo to ...
+
+ if(idtest==0) {
+ if(ipo) idtest= (ID *)copy_ipo(ipo);
+ else {
+ nr= GS(from->name);
+ if(nr==ID_OB){
+ if (G.sipo->blocktype==IPO_CO)
+ idtest= (ID *)add_ipo("CoIpo", IPO_CO); /* BLEARGH! */
+ else
+ idtest= (ID *)add_ipo("ObIpo", nr);
+ }
+ else if(nr==ID_MA) idtest= (ID *)add_ipo("MatIpo", nr);
+ else if(nr==ID_SEQ) idtest= (ID *)add_ipo("MatSeq", nr);
+ else if(nr==ID_CU) idtest= (ID *)add_ipo("CuIpo", nr);
+ else if(nr==ID_KE) idtest= (ID *)add_ipo("KeyIpo", nr);
+ else if(nr==ID_WO) idtest= (ID *)add_ipo("WoIpo", nr);
+ else if(nr==ID_LA) idtest= (ID *)add_ipo("LaIpo", nr);
+ else if(nr==ID_CA) idtest= (ID *)add_ipo("CaIpo", nr);
+ else if(nr==ID_SO) idtest= (ID *)add_ipo("SndIpo", nr);
+ else if(nr==ID_AC) idtest= (ID *)add_ipo("ActIpo", nr);
+ else error("Warn bugs@blender.nl!");
+ }
+ idtest->us--;
+ }
+ if(idtest!=id && from) {
+ ipo= (Ipo *)idtest;
+
+ if (ipo->blocktype==IPO_CO){
+ ((Object*)from)->activecon->ipo = ipo;
+ id_us_plus(idtest);
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWACTION, 0);
+ allqueue(REDRAWNLA, 0);
+ }
+ else if(ipo->blocktype==ID_OB) {
+ ( (Object *)from)->ipo= ipo;
+ id_us_plus(idtest);
+ allqueue(REDRAWVIEW3D, 0);
+ }
+ else if(ipo->blocktype==ID_AC) {
+ bActionChannel *chan;
+ chan = get_hilighted_action_channel ((bAction*)from);
+ if (!chan){
+ error ("Create an action channel first");
+ return;
+ }
+ chan->ipo=ipo;
+ id_us_plus(idtest);
+ allqueue(REDRAWNLA, 0);
+ allqueue(REDRAWACTION, 0);
+ }
+ else if(ipo->blocktype==ID_MA) {
+ ( (Material *)from)->ipo= ipo;
+ id_us_plus(idtest);
+ allqueue(REDRAWBUTSMAT, 0);
+ }
+ else if(ipo->blocktype==ID_SEQ) {
+ seq= (Sequence *)from;
+ if(seq->type & SEQ_EFFECT) {
+ id_us_plus(idtest);
+ seq->ipo= ipo;
+ }
+ }
+ else if(ipo->blocktype==ID_CU) {
+ ( (Curve *)from)->ipo= ipo;
+ id_us_plus(idtest);
+ allqueue(REDRAWVIEW3D, 0);
+ }
+ else if(ipo->blocktype==ID_KE) {
+ ( (Key *)from)->ipo= ipo;
+
+ id_us_plus(idtest);
+ allqueue(REDRAWVIEW3D, 0);
+
+ }
+ else if(ipo->blocktype==ID_WO) {
+ ( (World *)from)->ipo= ipo;
+ id_us_plus(idtest);
+ allqueue(REDRAWBUTSWORLD, 0);
+ }
+ else if(ipo->blocktype==ID_LA) {
+ ( (Lamp *)from)->ipo= ipo;
+ id_us_plus(idtest);
+ allqueue(REDRAWBUTSLAMP, 0);
+ }
+ else if(ipo->blocktype==ID_CA) {
+ ( (Camera *)from)->ipo= ipo;
+ id_us_plus(idtest);
+ allqueue(REDRAWBUTSEDIT, 0);
+ }
+ else if(ipo->blocktype==ID_SO) {
+ ( (bSound *)from)->ipo= ipo;
+ id_us_plus(idtest);
+ allqueue(REDRAWBUTSEDIT, 0);
+ }
+ else
+ printf("error in browse ipo \n");
+
+ if(id) id->us--;
+
+ scrarea_queue_winredraw(curarea);
+ scrarea_queue_headredraw(curarea);
+ allqueue(REDRAWIPO, 0);
+ }
+ }
+ break;
+ case B_IPODELETE:
+ ipo= get_ipo_to_edit(&from);
+ if(from==0) return;
+
+ ipo->id.us--;
+
+ if(ipo->blocktype==ID_OB) ( (Object *)from)->ipo= 0;
+ else if(ipo->blocktype==ID_MA) ( (Material *)from)->ipo= 0;
+ else if(ipo->blocktype==ID_SEQ) ( (Sequence *)from)->ipo= 0;
+ else if(ipo->blocktype==ID_CU) ( (Curve *)from)->ipo= 0;
+ else if(ipo->blocktype==ID_KE) ( (Key *)from)->ipo= 0;
+ else if(ipo->blocktype==ID_WO) ( (World *)from)->ipo= 0;
+ else if(ipo->blocktype==ID_LA) ( (Lamp *)from)->ipo= 0;
+ else if(ipo->blocktype==ID_WO) ( (World *)from)->ipo= 0;
+ else if(ipo->blocktype==ID_CA) ( (Camera *)from)->ipo= 0;
+ else if(ipo->blocktype==ID_SO) ( (bSound *)from)->ipo= 0;
+ else if(ipo->blocktype==ID_AC) get_hilighted_action_channel((bAction*)from)->ipo= 0;
+ else if(ipo->blocktype==IPO_CO) ((Object *)from)->activecon->ipo= 0;
+
+ else error("Warn bugs@blender.nl!");
+
+ editipo_changed(G.sipo, 1); /* doredraw */
+ allqueue(REDRAWIPO, 0);
+ allqueue(REDRAWNLA, 0);
+ allqueue (REDRAWACTION, 0);
+
+ break;
+ case B_WORLDBROWSE:
+
+ if(G.buts->menunr==-2) {
+ activate_databrowse((ID *)G.scene->world, ID_WO, 0, B_WORLDBROWSE, &G.buts->menunr, do_global_buttons);
+ break;
+ }
+
+ if(G.buts->menunr < 0) break;
+ /* geen lock */
+
+ wrld= G.scene->world;
+ nr= 1;
+
+ id= (ID *)wrld;
+
+ idtest= G.main->world.first;
+ while(idtest) {
+ if(nr==G.buts->menunr) {
+ break;
+ }
+ nr++;
+ idtest= idtest->next;
+ }
+ if(idtest==0) { /* new world */
+ if(id) idtest= (ID *)copy_world((World *)id);
+ else idtest= (ID *)add_world("World");
+ idtest->us--;
+ }
+ if(idtest!=id) {
+ G.scene->world= (World *)idtest;
+ id_us_plus(idtest);
+ if(id) id->us--;
+
+ allqueue(REDRAWBUTSHEAD, 0);
+ allqueue(REDRAWBUTSWORLD, 0);
+ allqueue(REDRAWIPO, 0);
+ BIF_preview_changed(G.buts);
+ }
+ break;
+ case B_WORLDDELETE:
+ if(G.scene->world) {
+ G.scene->world->id.us--;
+ G.scene->world= 0;
+ allqueue(REDRAWBUTSWORLD, 0);
+ allqueue(REDRAWIPO, 0);
+ }
+
+ break;
+ case B_WTEXBROWSE:
+
+ if(G.buts->texnr== -2) {
+ id= 0;
+ wrld= G.scene->world;
+ if(wrld) {
+ mtex= wrld->mtex[ wrld->texact ];
+ if(mtex) id= (ID *)mtex->tex;
+ }
+
+ activate_databrowse((ID *)id, ID_TE, 0, B_WTEXBROWSE, &G.buts->texnr, do_global_buttons);
+ return;
+ }
+ if(G.buts->texnr < 0) break;
+
+ if(G.buts->pin) {
+
+ }
+ else {
+ id= 0;
+
+ wrld= G.scene->world;
+ if(wrld) {
+ mtex= wrld->mtex[ wrld->texact ];
+ if(mtex) id= (ID *)mtex->tex;
+ }
+
+ idtest= G.main->tex.first;
+ while(idtest) {
+ if(nr==G.buts->texnr) {
+ break;
+ }
+ nr++;
+ idtest= idtest->next;
+ }
+ if(idtest==0) { /* new tex */
+ if(id) idtest= (ID *)copy_texture((Tex *)id);
+ else idtest= (ID *)add_texture("Tex");
+ idtest->us--;
+ }
+ if(idtest!=id && wrld) {
+
+ if( wrld->mtex[wrld->texact]==0) {
+ wrld->mtex[wrld->texact]= add_mtex();
+ wrld->mtex[wrld->texact]->texco= TEXCO_VIEW;
+ }
+ wrld->mtex[ wrld->texact ]->tex= (Tex *)idtest;
+ id_us_plus(idtest);
+ if(id) id->us--;
+
+ allqueue(REDRAWBUTSHEAD, 0);
+ allqueue(REDRAWBUTSTEX, 0);
+ allqueue(REDRAWBUTSWORLD, 0);
+ allqueue(REDRAWIPO, 0);
+ BIF_preview_changed(G.buts);
+ }
+ }
+ break;
+ case B_LAMPBROWSE:
+ /* geen lock */
+ if(ob==0) return;
+ if(ob->type!=OB_LAMP) return;
+
+ if(G.buts->menunr== -2) {
+ activate_databrowse((ID *)G.buts->lockpoin, ID_LA, 0, B_LAMPBROWSE, &G.buts->menunr, do_global_buttons);
+ return;
+ }
+ if(G.buts->menunr < 0) break;
+
+ la= ob->data;
+ nr= 1;
+ id= (ID *)la;
+
+ idtest= G.main->lamp.first;
+ while(idtest) {
+ if(nr==G.buts->menunr) {
+ break;
+ }
+ nr++;
+ idtest= idtest->next;
+ }
+ if(idtest==0) { /* geen new lamp */
+ return;
+ }
+ if(idtest!=id) {
+ ob->data= (Lamp *)idtest;
+ id_us_plus(idtest);
+ if(id) id->us--;
+
+ allqueue(REDRAWBUTSHEAD, 0);
+ allqueue(REDRAWBUTSLAMP, 0);
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWIPO, 0);
+ BIF_preview_changed(G.buts);
+ }
+ break;
+
+ case B_LTEXBROWSE:
+
+ if(ob==0) return;
+ if(ob->type!=OB_LAMP) return;
+
+ if(G.buts->texnr== -2) {
+ id= 0;
+ la= ob->data;
+ mtex= la->mtex[ la->texact ];
+ if(mtex) id= (ID *)mtex->tex;
+
+ activate_databrowse(id, ID_TE, 0, B_LTEXBROWSE, &G.buts->texnr, do_global_buttons);
+ return;
+ }
+ if(G.buts->texnr < 0) break;
+
+ if(G.buts->pin) {
+
+ }
+ else {
+ id= 0;
+
+ la= ob->data;
+ mtex= la->mtex[ la->texact ];
+ if(mtex) id= (ID *)mtex->tex;
+
+ idtest= G.main->tex.first;
+ while(idtest) {
+ if(nr==G.buts->texnr) {
+ break;
+ }
+ nr++;
+ idtest= idtest->next;
+ }
+ if(idtest==0) { /* new tex */
+ if(id) idtest= (ID *)copy_texture((Tex *)id);
+ else idtest= (ID *)add_texture("Tex");
+ idtest->us--;
+ }
+ if(idtest!=id && la) {
+
+ if( la->mtex[la->texact]==0) {
+ la->mtex[la->texact]= add_mtex();
+ la->mtex[la->texact]->texco= TEXCO_GLOB;
+ }
+ la->mtex[ la->texact ]->tex= (Tex *)idtest;
+ id_us_plus(idtest);
+ if(id) id->us--;
+
+ allqueue(REDRAWBUTSHEAD, 0);
+ allqueue(REDRAWBUTSTEX, 0);
+ allqueue(REDRAWBUTSLAMP, 0);
+ allqueue(REDRAWIPO, 0);
+ BIF_preview_changed(G.buts);
+ }
+ }
+ break;
+
+ case B_IMAGEDELETE:
+ G.sima->image= 0;
+ image_changed(G.sima, 0);
+ allqueue(REDRAWIMAGE, 0);
+ break;
+
+ case B_AUTOMATNAME:
+ automatname(G.buts->lockpoin);
+ allqueue(REDRAWBUTSHEAD, 0);
+ break;
+ case B_AUTOTEXNAME:
+ if(G.buts->mainb==BUTS_TEX) {
+ autotexname(G.buts->lockpoin);
+ allqueue(REDRAWBUTSHEAD, 0);
+ allqueue(REDRAWBUTSTEX, 0);
+ }
+ else if(G.buts->mainb==BUTS_MAT) {
+ ma= G.buts->lockpoin;
+ if(ma->mtex[ ma->texact]) autotexname(ma->mtex[ma->texact]->tex);
+ allqueue(REDRAWBUTSMAT, 0);
+ }
+ else if(G.buts->mainb==BUTS_WORLD) {
+ wrld= G.buts->lockpoin;
+ if(wrld->mtex[ wrld->texact]) autotexname(wrld->mtex[wrld->texact]->tex);
+ allqueue(REDRAWBUTSWORLD, 0);
+ }
+ else if(G.buts->mainb==BUTS_LAMP) {
+ la= G.buts->lockpoin;
+ if(la->mtex[ la->texact]) autotexname(la->mtex[la->texact]->tex);
+ allqueue(REDRAWBUTSLAMP, 0);
+ }
+ break;
+
+ case B_RESETAUTOSAVE:
+ reset_autosave();
+ break;
+ case B_SOUNDTOGGLE:
+ SYS_WriteCommandLineInt(SYS_GetSystem(), "noaudio", (U.gameflags & USERDEF_DISABLE_SOUND));
+ break;
+ case B_SHOWSPLASH:
+ if ((LICENSE_KEY_VALID) && ((G.qual & LR_SHIFTKEY) == 0)) {
+ SHOW_LICENSE_KEY();
+ } else {
+ show_splash();
+ }
+ break;
+ case B_MIPMAPCHANGED:
+ set_mipmap(!(U.gameflags & USERDEF_DISABLE_SOUND));
+ allqueue(REDRAWVIEW3D, 0);
+ break;
+ case B_NEWSPACE:
+ newspace(curarea, curarea->butspacetype);
+ break;
+ case B_LOADTEMP: /* is button uit space.c */
+ BIF_read_autosavefile();
+ break;
+ case B_FULL:
+ if(curarea->spacetype!=SPACE_INFO) {
+ area_fullscreen();
+ }
+ break;
+
+ case B_IDNAME:
+ /* changing a metaballs name, sadly enough,
+ * can require it to be updated because its
+ * basis might have changed... -zr
+ */
+ if (OBACT && OBACT->type==OB_MBALL)
+ makeDispList(OBACT);
+
+ /* redraw omdat naam veranderd is: nieuwe pup */
+ scrarea_queue_headredraw(curarea);
+ allqueue(REDRAWBUTSHEAD, 0);
+ allqueue(REDRAWINFO, 1);
+ allqueue(REDRAWOOPS, 1);
+ /* naam scene ook in set PUPmenu */
+ if ELEM(curarea->spacetype, SPACE_BUTS, SPACE_INFO) allqueue(REDRAWBUTSALL, 0);
+
+ allqueue(REDRAWHEADERS, 0);
+
+ break;
+ }
+}
+
+
+void do_global_buttons2(short event)
+{
+ Base *base;
+ Object *ob;
+ Material *ma;
+ MTex *mtex;
+ Mesh *me;
+ Curve *cu;
+ MetaBall *mb;
+ Ipo *ipo;
+ Lamp *la;
+ Lattice *lt;
+ World *wrld;
+ ID *idfrom;
+ bAction *act;
+
+ /* algemeen: Single User mag als from==LOCAL
+ * Make Local mag als (from==LOCAL && id==LIB)
+ */
+
+ ob= OBACT;
+
+ switch(event) {
+
+ case B_LAMPALONE:
+ if(ob && ob->id.lib==0) {
+ la= ob->data;
+ if(la->id.us>1) {
+ if(okee("Single user")) {
+ ob->data= copy_lamp(la);
+ la->id.us--;
+ }
+ }
+ }
+ break;
+ case B_LAMPLOCAL:
+ if(ob && ob->id.lib==0) {
+ la= ob->data;
+ if(la->id.lib) {
+ if(okee("Make local")) {
+ make_local_lamp(la);
+ }
+ }
+ }
+ break;
+
+ case B_ARMLOCAL:
+ if (ob&&ob->id.lib==0){
+ bArmature *arm=ob->data;
+ if (arm->id.lib){
+ if(okee("Make local")) {
+ make_local_armature(arm);
+ }
+ }
+ }
+ break;
+ case B_ARMALONE:
+ if(ob && ob->id.lib==0) {
+ bArmature *arm=ob->data;
+ if(arm->id.us>1) {
+ if(okee("Single user")) {
+ ob->data= copy_armature(arm);
+ arm->id.us--;
+ }
+ }
+ }
+ break;
+ case B_ACTLOCAL:
+ if(ob && ob->id.lib==0) {
+ act= ob->action;
+ if(act->id.lib) {
+ if(okee("Make local")) {
+ make_local_action(act);
+ allqueue(REDRAWACTION,0);
+ }
+ }
+ }
+ break;
+ case B_ACTALONE:
+ if (ob)
+ act= ob->action;
+
+ if(ob && ob->id.lib==0) {
+ if(act->id.us>1) {
+ if(okee("Single user")) {
+ ob->action=copy_action(act);
+ ob->activecon=NULL;
+ act->id.us--;
+ allqueue(REDRAWACTION, 0);
+ }
+ }
+ }
+ break;
+
+ case B_CAMERAALONE:
+ if(ob && ob->id.lib==0) {
+ Camera *ca= ob->data;
+ if(ca->id.us>1) {
+ if(okee("Single user")) {
+ ob->data= copy_camera(ca);
+ ca->id.us--;
+ }
+ }
+ }
+ break;
+ case B_CAMERALOCAL:
+ if(ob && ob->id.lib==0) {
+ Camera *ca= ob->data;
+ if(ca->id.lib) {
+ if(okee("Make local")) {
+ make_local_camera(ca);
+ }
+ }
+ }
+ break;
+ case B_WORLDALONE:
+ wrld= G.scene->world;
+ if(wrld->id.us>1) {
+ if(okee("Single user")) {
+ G.scene->world= copy_world(wrld);
+ wrld->id.us--;
+ }
+ }
+ break;
+ case B_WORLDLOCAL:
+ wrld= G.scene->world;
+ if(wrld && wrld->id.lib) {
+ if(okee("Make local")) {
+ make_local_world(wrld);
+ }
+ }
+ break;
+
+ case B_LATTALONE:
+ if(ob && ob->id.lib==0) {
+ lt= ob->data;
+ if(lt->id.us>1) {
+ if(okee("Single user")) {
+ ob->data= copy_lattice(lt);
+ lt->id.us--;
+ }
+ }
+ }
+ break;
+ case B_LATTLOCAL:
+ if(ob && ob->id.lib==0) {
+ lt= ob->data;
+ if(lt->id.lib) {
+ if(okee("Make local")) {
+ make_local_lattice(lt);
+ }
+ }
+ }
+ break;
+
+ case B_MATALONE:
+ if(ob==0) return;
+ ma= give_current_material(ob, ob->actcol);
+ idfrom= material_from(ob, ob->actcol);
+ if(idfrom && idfrom->lib==0) {
+ if(ma->id.us>1) {
+ if(okee("Single user")) {
+ ma= copy_material(ma);
+ ma->id.us= 0;
+ assign_material(ob, ma, ob->actcol);
+ }
+ }
+ }
+ break;
+ case B_MATLOCAL:
+ if(ob==0) return;
+ idfrom= material_from(ob, ob->actcol);
+ if(idfrom->lib==0) {
+ ma= give_current_material(ob, ob->actcol);
+ if(ma && ma->id.lib) {
+ if(okee("Make local")) {
+ make_local_material(ma);
+ }
+ }
+ }
+ break;
+
+ case B_MESHLOCAL:
+ if(ob && ob->id.lib==0) {
+ me= ob->data;
+ if(me && me->id.lib) {
+ if(okee("Make local")) {
+ make_local_mesh(me);
+ make_local_key( me->key );
+ }
+ }
+ }
+ break;
+
+ case B_MBALLALONE:
+ if(ob && ob->id.lib==0) {
+ mb= ob->data;
+ if(mb->id.us>1) {
+ if(okee("Single user")) {
+ ob->data= copy_mball(mb);
+ mb->id.us--;
+ if(ob==G.obedit) allqueue(REDRAWVIEW3D, 0);
+ }
+ }
+ }
+ break;
+ case B_MBALLLOCAL:
+ if(ob && ob->id.lib==0) {
+ mb= ob->data;
+ if(mb->id.lib) {
+ if(okee("Make local")) {
+ make_local_mball(mb);
+ }
+ }
+ }
+ break;
+
+ case B_CURVEALONE:
+ if(ob && ob->id.lib==0) {
+ cu= ob->data;
+ if(cu->id.us>1) {
+ if(okee("Single user")) {
+ ob->data= copy_curve(cu);
+ cu->id.us--;
+ makeDispList(ob);
+ if(ob==G.obedit) allqueue(REDRAWVIEW3D, 0);
+ }
+ }
+ }
+ break;
+ case B_CURVELOCAL:
+ if(ob && ob->id.lib==0) {
+ cu= ob->data;
+ if(cu->id.lib) {
+ if(okee("Make local")) {
+ make_local_curve(cu);
+ make_local_key( cu->key );
+ makeDispList(ob);
+ }
+ }
+ }
+ break;
+
+ case B_TEXALONE:
+ if(G.buts->texfrom==0) { /* from mat */
+ if(ob==0) return;
+ ma= give_current_material(ob, ob->actcol);
+ if(ma && ma->id.lib==0) {
+ mtex= ma->mtex[ ma->texact ];
+ if(mtex->tex && mtex->tex->id.us>1) {
+ if(okee("Single user")) {
+ mtex->tex->id.us--;
+ mtex->tex= copy_texture(mtex->tex);
+ }
+ }
+ }
+ }
+ else if(G.buts->texfrom==1) { /* from world */
+ wrld= G.scene->world;
+ if(wrld->id.lib==0) {
+ mtex= wrld->mtex[ wrld->texact ];
+ if(mtex->tex && mtex->tex->id.us>1) {
+ if(okee("Single user")) {
+ mtex->tex->id.us--;
+ mtex->tex= copy_texture(mtex->tex);
+ }
+ }
+ }
+ }
+ else if(G.buts->texfrom==2) { /* from lamp */
+ if(ob==0 || ob->type!=OB_LAMP) return;
+ la= ob->data;
+ if(la->id.lib==0) {
+ mtex= la->mtex[ la->texact ];
+ if(mtex->tex && mtex->tex->id.us>1) {
+ if(okee("Single user")) {
+ mtex->tex->id.us--;
+ mtex->tex= copy_texture(mtex->tex);
+ }
+ }
+ }
+ }
+ break;
+ case B_TEXLOCAL:
+ if(G.buts->texfrom==0) { /* from mat */
+ if(ob==0) return;
+ ma= give_current_material(ob, ob->actcol);
+ if(ma && ma->id.lib==0) {
+ mtex= ma->mtex[ ma->texact ];
+ if(mtex->tex && mtex->tex->id.lib) {
+ if(okee("Make local")) {
+ make_local_texture(mtex->tex);
+ }
+ }
+ }
+ }
+ else if(G.buts->texfrom==1) { /* from world */
+ wrld= G.scene->world;
+ if(wrld->id.lib==0) {
+ mtex= wrld->mtex[ wrld->texact ];
+ if(mtex->tex && mtex->tex->id.lib) {
+ if(okee("Make local")) {
+ make_local_texture(mtex->tex);
+ }
+ }
+ }
+ }
+ else if(G.buts->texfrom==2) { /* from lamp */
+ if(ob==0 || ob->type!=OB_LAMP) return;
+ la= ob->data;
+ if(la->id.lib==0) {
+ mtex= la->mtex[ la->texact ];
+ if(mtex->tex && mtex->tex->id.lib) {
+ if(okee("Make local")) {
+ make_local_texture(mtex->tex);
+ }
+ }
+ }
+ }
+ break;
+
+ case B_IPOALONE:
+ ipo= get_ipo_to_edit(&idfrom);
+
+ if(idfrom && idfrom->lib==0) {
+ if(ipo->id.us>1) {
+ if(okee("Single user")) {
+ if(ipo->blocktype==ID_OB) ((Object *)idfrom)->ipo= copy_ipo(ipo);
+ else if(ipo->blocktype==ID_MA) ((Material *)idfrom)->ipo= copy_ipo(ipo);
+ else if(ipo->blocktype==ID_SEQ) ((Sequence *)idfrom)->ipo= copy_ipo(ipo);
+ else if(ipo->blocktype==ID_CU) ((Curve *)idfrom)->ipo= copy_ipo(ipo);
+ else if(ipo->blocktype==ID_KE) ((Key *)idfrom)->ipo= copy_ipo(ipo);
+ else if(ipo->blocktype==ID_LA) ((Lamp *)idfrom)->ipo= copy_ipo(ipo);
+ else if(ipo->blocktype==ID_WO) ((World *)idfrom)->ipo= copy_ipo(ipo);
+ else if(ipo->blocktype==ID_CA) ((Camera *)idfrom)->ipo= copy_ipo(ipo);
+ else if(ipo->blocktype==ID_SO) ((bSound *)idfrom)->ipo= copy_ipo(ipo);
+ else if(ipo->blocktype==ID_AC) get_hilighted_action_channel((bAction *)idfrom)->ipo= copy_ipo(ipo);
+ else if(ipo->blocktype==IPO_CO) ((Object *)idfrom)->activecon->ipo= copy_ipo(ipo);
+ else error("Warn ton!");
+
+ ipo->id.us--;
+ allqueue(REDRAWIPO, 0);
+ }
+ }
+ }
+ break;
+ case B_IPOLOCAL:
+ ipo= get_ipo_to_edit(&idfrom);
+
+ if(idfrom && idfrom->lib==0) {
+ if(ipo->id.lib) {
+ if(okee("Make local")) {
+ make_local_ipo(ipo);
+ allqueue(REDRAWIPO, 0);
+ }
+ }
+ }
+ break;
+
+ case B_OBALONE:
+ if(G.scene->id.lib==0) {
+ if(ob->id.us>1) {
+ if(okee("Single user")) {
+ base= FIRSTBASE;
+ while(base) {
+ if(base->object==ob) {
+ base->object= copy_object(ob);
+ ob->id.us--;
+ allqueue(REDRAWVIEW3D, 0);
+ break;
+ }
+ base= base->next;
+ }
+ }
+ }
+ }
+ break;
+ case B_OBLOCAL:
+ if(G.scene->id.lib==0) {
+ if(ob->id.lib) {
+ if(okee("Make local")) {
+ make_local_object(ob);
+ allqueue(REDRAWVIEW3D, 0);
+ }
+ }
+ }
+ break;
+ case B_MESHALONE:
+ if(ob && ob->id.lib==0) {
+
+ me= ob->data;
+
+ if(me && me->id.us>1) {
+ if(okee("Single user")) {
+ Mesh *men= copy_mesh(me);
+ men->id.us= 0;
+
+ set_mesh(ob, men);
+
+ if(ob==G.obedit) allqueue(REDRAWVIEW3D, 0);
+ }
+ }
+ }
+ break;
+ }
+
+ allqueue(REDRAWBUTSALL, 0);
+ allqueue(REDRAWOOPS, 0);
+}
+
+/* ********************** EMPTY ****************************** */
+/* ********************** INFO ****************************** */
+
+int buttons_do_unpack()
+{
+ int how;
+ char menu[2048];
+ char line[128];
+ int ret_value = RET_OK, count = 0;
+
+ count = countPackedFiles();
+
+ if (count) {
+ if (count == 1) {
+ sprintf(menu, "Unpack 1 file%%t");
+ } else {
+ sprintf(menu, "Unpack %d files%%t", count);
+ }
+
+ sprintf(line, "|Use files in current directory (create when necessary)%%x%d", PF_USE_LOCAL);
+ strcat(menu, line);
+
+ sprintf(line, "|Write files to current directory (overwrite existing files)%%x%d", PF_WRITE_LOCAL);
+ strcat(menu, line);
+
+ sprintf(line, "|%%l|Use files in original location (create when necessary)%%x%d", PF_USE_ORIGINAL);
+ strcat(menu, line);
+
+ sprintf(line, "|Write files to original location (overwrite existing files)%%x%d", PF_WRITE_ORIGINAL);
+ strcat(menu, line);
+
+ sprintf(line, "|%%l|Disable AutoPack, keep all packed files %%x%d", PF_KEEP);
+ strcat(menu, line);
+
+ sprintf(line, "|Ask for each file %%x%d", PF_ASK);
+ strcat(menu, line);
+
+ how = pupmenu(menu);
+
+ if(how != -1) {
+ if (how != PF_KEEP) {
+ unpackAll(how);
+ }
+ G.fileflags &= ~G_AUTOPACK;
+ } else {
+ ret_value = RET_CANCEL;
+ }
+ } else {
+ pupmenu("No packed files. Autopack disabled");
+ }
+
+ return (ret_value);
+}
+
+/* here, because of all creator stuff */
+
+Scene *copy_scene(Scene *sce, int level)
+{
+ /* level 0: alle objects shared
+ * level 1: alle objectdata shared
+ * level 2: volledige kopie
+ */
+ Scene *scen;
+ Base *base, *obase;
+
+
+ /* level 0 */
+ scen= copy_libblock(sce);
+ duplicatelist(&(scen->base), &(sce->base));
+
+ clear_id_newpoins();
+
+ id_us_plus((ID *)scen->world);
+ id_us_plus((ID *)scen->set);
+
+ scen->ed= 0;
+ scen->radio= 0;
+
+ obase= sce->base.first;
+ base= scen->base.first;
+ while(base) {
+ base->object->id.us++;
+ if(obase==sce->basact) scen->basact= base;
+
+ obase= obase->next;
+ base= base->next;
+ }
+
+ if(level==0) return scen;
+
+ /* level 1 */
+ G.scene= scen;
+ single_object_users(0);
+
+ /* camera */
+ ID_NEW(G.scene->camera);
+
+ /* level 2 */
+ if(level>=2) {
+ if(scen->world) {
+ scen->world->id.us--;
+ scen->world= copy_world(scen->world);
+ }
+ single_obdata_users(0);
+ single_mat_users_expand();
+ single_tex_users_expand();
+ }
+
+ clear_id_newpoins();
+
+ BPY_copy_scriptlink(&sce->scriptlink);
+
+
+
+ // make a private copy of the avicodecdata
+
+ if (sce->r.avicodecdata) {
+
+ scen->r.avicodecdata = MEM_dupallocN(sce->r.avicodecdata);
+
+ scen->r.avicodecdata->lpFormat = MEM_dupallocN(scen->r.avicodecdata->lpFormat);
+
+ scen->r.avicodecdata->lpParms = MEM_dupallocN(scen->r.avicodecdata->lpParms);
+
+ }
+
+ return scen;
+}
+
+void do_info_buttons(unsigned short event)
+{
+ bScreen *sc, *oldscreen;
+ Scene *sce, *sce1;
+ ScrArea *sa;
+ int nr;
+
+ switch(event) {
+
+ case B_INFOSCR: /* menu select screen */
+
+ if( G.curscreen->screennr== -2) {
+ if(curarea->winy <50) {
+ sa= closest_bigger_area();
+ areawinset(sa->win);
+ }
+ activate_databrowse((ID *)G.curscreen, ID_SCR, 0, B_INFOSCR, &G.curscreen->screennr, do_info_buttons);
+ return;
+ }
+ if( G.curscreen->screennr < 0) return;
+
+ sc= G.main->screen.first;
+ nr= 1;
+ while(sc) {
+ if(nr==G.curscreen->screennr) {
+ if(is_allowed_to_change_screen(sc)) setscreen(sc);
+ else error("Unable to perform function in EditMode");
+ break;
+ }
+ nr++;
+ sc= sc->id.next;
+ }
+ /* laatste item: NEW SCREEN */
+ if(sc==0) {
+ duplicate_screen();
+ }
+ break;
+ case B_INFODELSCR:
+ /* dit event alleen met buttons doen, zodoende nooit vanuit full aanroepbaar */
+
+ if(G.curscreen->id.prev) sc= G.curscreen->id.prev;
+ else if(G.curscreen->id.next) sc= G.curscreen->id.next;
+ else return;
+ if(okee("Delete current screen")) {
+ /* vind nieuwe G.curscreen */
+
+ oldscreen= G.curscreen;
+ setscreen(sc); /* deze test of sc een full heeft */
+ unlink_screen(oldscreen);
+ free_libblock(&G.main->screen, oldscreen);
+ }
+ scrarea_queue_headredraw(curarea);
+
+ break;
+ case B_INFOSCE: /* menu select scene */
+
+ if( G.obedit) {
+ error("Unable to perform function in EditMode");
+ return;
+ }
+ if( G.curscreen->scenenr== -2) {
+ if(curarea->winy <50) {
+ sa= closest_bigger_area();
+ areawinset(sa->win);
+ }
+ activate_databrowse((ID *)G.scene, ID_SCE, 0, B_INFOSCE, &G.curscreen->scenenr, do_info_buttons);
+ return;
+ }
+ if( G.curscreen->scenenr < 0) return;
+
+ sce= G.main->scene.first;
+ nr= 1;
+ while(sce) {
+ if(nr==G.curscreen->scenenr) {
+ if(sce!=G.scene) set_scene(sce);
+ break;
+ }
+ nr++;
+ sce= sce->id.next;
+ }
+ /* laatste item: NEW SCENE */
+ if(sce==0) {
+ nr= pupmenu("Add scene%t|Empty|Link Objects|Link ObData|Full Copy");
+ if(nr<= 0) return;
+ if(nr==1) {
+ sce= add_scene(G.scene->id.name+2);
+ sce->r= G.scene->r;
+ }
+ else sce= copy_scene(G.scene, nr-2);
+
+ set_scene(sce);
+ }
+
+ break;
+ case B_INFODELSCE:
+
+ if(G.scene->id.prev) sce= G.scene->id.prev;
+ else if(G.scene->id.next) sce= G.scene->id.next;
+ else return;
+ if(okee("Delete current scene")) {
+
+ /* alle sets aflopen */
+ sce1= G.main->scene.first;
+ while(sce1) {
+ if(sce1->set == G.scene) sce1->set= 0;
+ sce1= sce1->id.next;
+ }
+
+ /* alle sequences aflopen */
+ clear_scene_in_allseqs(G.scene);
+
+ /* alle schermen */
+ sc= G.main->screen.first;
+ while(sc) {
+ if(sc->scene == G.scene) sc->scene= sce;
+ sc= sc->id.next;
+ }
+ free_libblock(&G.main->scene, G.scene);
+ set_scene(sce);
+ }
+
+ break;
+ case B_FILEMENU:
+ tbox_setmain(9);
+ toolbox();
+ break;
+ }
+}
+
+/* strubi shamelessly abused the status line as a progress bar...
+ feel free to kill him after release */
+
+static int g_progress_bar = 0;
+static char *g_progress_info = 0;
+static float g_done;
+
+int start_progress_bar(void)
+{
+ g_progress_bar = 1;
+ return 1; // we never fail (yet)
+}
+
+void end_progress_bar(void)
+{
+ g_progress_bar = 0;
+}
+
+static void update_progress_bar(float done, char *info)
+{
+ g_done = done;
+ g_progress_info = info;
+}
+
+/** Progress bar
+ 'done': a value between 0.0 and 1.0, showing progress
+ 'info': a info text what is currently being done
+
+ Make sure that the progress bar is always called with:
+ done = 0.0 first
+ and
+ done = 1.0 last -- or alternatively use:
+
+ start_progressbar();
+ do_stuff_and_callback_progress_bar();
+ end_progressbar();
+*/
+int progress_bar(float done, char *busy_info)
+{
+ ScrArea *sa;
+ short val;
+
+ /* User break (ESC) */
+ while (qtest()) {
+ if (extern_qread(&val) == ESCKEY)
+ return 0;
+ }
+ if (done == 0.0) {
+ start_progress_bar();
+ } else if (done > 0.99) {
+ end_progress_bar();
+ }
+
+ sa= G.curscreen->areabase.first;
+ while(sa) {
+ if (sa->spacetype == SPACE_INFO) {
+ update_progress_bar(done, busy_info);
+
+ curarea = sa;
+
+ scrarea_do_headdraw(curarea);
+ areawinset(curarea->win);
+ sa->head_swap= WIN_BACK_OK;
+ screen_swapbuffers();
+ }
+ sa = sa->next;
+ }
+ return 1;
+}
+
+
+static void check_packAll()
+{
+ // first check for dirty images
+ Image *ima;
+
+ ima = G.main->image.first;
+ while (ima) {
+ if (ima->ibuf && (ima->ibuf->userflags &= IB_BITMAPDIRTY)) {
+ break;
+ }
+ ima= ima->id.next;
+ }
+
+ if (ima == 0 || okee("Some images are painted on. These changes will be lost. Continue ?")) {
+ packAll();
+ G.fileflags |= G_AUTOPACK;
+ }
+}
+
+
+/* KEYED FUNCTIONS
+ --------------- */
+
+/* this function name is meaningless and only called that way for some
+ obscurity
+ It is called by a function table from the license_key;
+ see include/keyed_functions.h
+*/
+
+struct twostrings
+{
+ char *outname;
+ char *exename;
+};
+
+/** This function is called for writing runtimes.
+ * It's locked behind the key and called through a function table
+ * which is initialized properly by the Python key code (if valid)
+ */
+int make_beautiful_animation(void *vp)
+{
+ char *freestr= NULL;
+ struct twostrings *twostrings = (struct twostrings *) vp;
+ char *str = twostrings->outname;
+ char *ext = 0;
+
+#ifdef _WIN32
+ ext = ".exe";
+#endif
+
+#ifdef __APPLE__
+ ext = ".app";
+#endif
+ if (ext && (!BLI_testextensie(str, ext))) {
+ freestr= MEM_mallocN(strlen(str) + strlen(ext) + 1, "write_runtime_check");
+ strcpy(freestr, str);
+ strcat(freestr, ext);
+ str= freestr;
+ }
+
+ if (!BLI_exists(str) || saveover(str))
+ BLO_write_runtime(str, twostrings->exename);
+
+ if (freestr)
+ MEM_freeN(freestr);
+
+ return 0;
+}
+
+int make_nice_software(void)
+{
+ Fptr f = KEY_RETURN_TRUE;
+ if (f) return f(0);
+ else return 0;
+}
+
+static void write_runtime_check_dynamic(char *str)
+{
+ Fptr f = KEY_WRITE_RUNTIME;
+ struct twostrings twostrings;
+
+ twostrings.outname = str;
+ twostrings.exename = "blenderdynplayer.exe";
+
+ if (f) f((void *) &twostrings);
+}
+
+static void write_runtime_check(char *str)
+{
+ Fptr f = KEY_WRITE_RUNTIME;
+ struct twostrings twostrings;
+ char player[128];
+
+ twostrings.outname = str;
+ twostrings.exename = player;
+
+ strcpy(player, "blenderplayer");
+
+#ifdef _WIN32
+ strcat(player, ".exe");
+#endif
+
+#ifdef __APPLE__
+ strcat(player, ".app");
+#endif
+
+ if (f) f((void *) &twostrings);
+}
+/* end keyed functions */
+
+
+static void do_info_filemenu(void *arg, int event)
+{
+ ScrArea *sa;
+ char dir[FILE_MAXDIR];
+
+ if(curarea->spacetype==SPACE_INFO) {
+ sa= closest_bigger_area();
+ areawinset(sa->win);
+ }
+
+ /* these are no defines, easier this way, the codes are in the function below */
+ switch(event) {
+ case 0:
+ if (okee("ERASE ALL")) {
+ if (!BIF_read_homefile())
+ error("No file ~/.B.blend");
+ }
+ break;
+ case 1:
+ activate_fileselect(FILE_BLENDER, "LOAD FILE", G.sce, BIF_read_file);
+ break;
+ case 2:
+ {
+ char *s= MEM_mallocN(strlen(G.sce) + 11 + 1, "okee_reload");
+ strcpy(s, "Open file: ");
+ strcat(s, G.sce);
+ if (okee(s))
+ BIF_read_file(G.sce);
+ MEM_freeN(s);
+ }
+ break;
+ case 3:
+ activate_fileselect(FILE_LOADLIB, "LOAD LIBRARY", G.lib, 0);
+ break;
+ case 4:
+ strcpy(dir, G.sce);
+ untitled(dir);
+ activate_fileselect(FILE_BLENDER, "SAVE FILE", dir, BIF_write_file);
+ break;
+ case 5:
+ strcpy(dir, G.sce);
+ if (untitled(dir)) {
+ activate_fileselect(FILE_BLENDER, "SAVE FILE", dir, BIF_write_file);
+ } else {
+ BIF_write_file(dir);
+ free_filesel_spec(dir);
+ }
+ break;
+ case 6:
+ mainqenter(F3KEY, 1);
+ break;
+ case 7:
+ write_vrml_fs();
+ break;
+ case 8:
+ write_dxf_fs();
+ break;
+ case 9:
+ write_videoscape_fs();
+ break;
+ case 20:
+ strcpy(dir, G.sce);
+ activate_fileselect(FILE_SPECIAL, "INSTALL LICENSE KEY", dir, loadKeyboard);
+ break;
+ case 21:
+ SHOW_LICENSE_KEY();
+ break;
+ case 22:
+ activate_fileselect(FILE_SPECIAL, "WRITE RUNTIME", "", write_runtime_check);
+ break;
+ case 23:
+ activate_fileselect(FILE_SPECIAL, "WRITE DYNAMIC RUNTIME", "", write_runtime_check_dynamic);
+ break;
+ case 30:
+ // import menu, no handling
+ break;
+
+#ifdef EXPERIMENTAL_MENUS
+ case 10:
+ check_packAll();
+ break;
+ case 11:
+ unpackAll(PF_WRITE_LOCAL);
+ G.fileflags &= ~G_AUTOPACK;
+ break;
+ case 12:
+ if (buttons_do_unpack() != RET_CANCEL) {
+ /* Clear autopack bit only if user selected one of the unpack options */
+ G.fileflags &= ~G_AUTOPACK;
+ }
+ break;
+ case 13:
+#else /* EXPERIMENTAL_MENUS */
+ case 10:
+#endif /* EXPERIMENTAL_MENUS */
+ exit_usiblender();
+ break;
+ }
+ allqueue(REDRAWINFO, 0);
+}
+
+void do_info_file_optionsmenu(void *arg, int event)
+{
+ G.fileflags ^= (1 << event);
+
+ // allqueue(REDRAWINFO, 0);
+}
+
+
+static uiBlock *info_file_optionsmenu(void *arg_unused)
+{
+ uiBlock *block;
+ short yco= 0, xco = 20;
+
+ block= uiNewBlock(&curarea->uiblocks, "runtime_options", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
+ uiBlockSetButmFunc(block, do_info_file_optionsmenu, NULL);
+ uiBlockSetXOfs(block,-40); // offset to parent button
+
+ /* flags are case-values */
+ uiDefBut(block, BUTM, 1, "Compress File", xco, yco-=20, 100, 19, NULL, 0.0, 0.0, 0, G_FILE_COMPRESS_BIT, "Use file compression");
+ uiDefBut(block, BUTM, 1, "Sign File", xco, yco-=20, 100, 19, NULL, 0.0, 0.0, 0, G_FILE_SIGN_BIT, "Add signature to file");
+ uiDefBut(block, BUTM, 1, "Lock File", xco, yco-=20, 100, 19, NULL, 0.0, 0.0, 0, G_FILE_LOCK_BIT, "Protect the file from editing by others");
+
+ /* Toggle buttons */
+
+ yco= 0;
+ xco -= 20;
+ uiBlockSetEmboss(block, UI_EMBOSSW);
+ uiBlockSetButmFunc(block, NULL, NULL);
+ /* flags are defines */
+ uiDefIconButI(block, ICONTOG|BIT|G_FILE_COMPRESS_BIT, 0, ICON_CHECKBOX_DEHLT, xco, yco-=20, 19, 19, &G.fileflags, 0.0, 0.0, 0, 0, "");
+ uiDefIconButI(block, ICONTOG|BIT|G_FILE_SIGN_BIT, 0, ICON_CHECKBOX_DEHLT, xco, yco-=20, 19, 19, &G.fileflags, 0.0, 0.0, 0, 0, "");
+ uiDefIconButI(block, ICONTOG|BIT|G_FILE_LOCK_BIT, 0, ICON_CHECKBOX_DEHLT, xco, yco-=20, 19, 19, &G.fileflags, 0.0, 0.0, 0, 0, "");
+
+ uiBlockSetDirection(block, UI_RIGHT);
+
+ return block;
+}
+
+static uiBlock *info_runtime_optionsmenu(void *arg_unused)
+{
+ uiBlock *block;
+ short yco= 0, xco = 20;
+
+ block= uiNewBlock(&curarea->uiblocks, "add_surfacemenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
+ uiBlockSetXOfs(block, -40); // offset to parent button
+
+ uiBlockSetEmboss(block, UI_EMBOSSW);
+
+ uiDefBut(block, LABEL, 0, "Size options:", xco, yco-=20, 114, 19, 0, 0.0, 0.0, 0, 0, "");
+ uiDefButS(block, NUM, 0, "X:", xco+19, yco-=20, 95, 19, &G.scene->r.xplay, 10.0, 2000.0, 0, 0, "X screen/window resolution");
+ uiDefButS(block, NUM, 0, "Y:", xco+19, yco-=20, 95, 19, &G.scene->r.yplay, 10.0, 2000.0, 0, 0, "Y screen/window resolution");
+
+ uiDefBut(block, SEPR, 0, "", xco, yco-=4, 114, 4, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefBut(block, LABEL, 0, "Fullscreen options:", xco, yco-=20, 114, 19, 0, 0.0, 0.0, 0, 0, "");
+ uiDefButS(block, TOG, 0, "Fullscreen", xco + 19, yco-=20, 95, 19, &G.scene->r.fullscreen, 0.0, 0.0, 0, 0, "Starts player in a new fullscreen display");
+ uiDefButS(block, NUM, 0, "Freq:", xco+19, yco-=20, 95, 19, &G.scene->r.freqplay, 10.0, 120.0, 0, 0, "Clock frequency of fullscreen display");
+ uiDefButS(block, NUM, 0, "Bits:", xco+19, yco-=20, 95, 19, &G.scene->r.depth, 1.0, 32.0, 0, 0, "Bit depth of full screen disply");
+
+ uiDefBut(block, SEPR, 0, "", xco, yco-=4, 114, 4, NULL, 0.0, 0.0, 0, 0, "");
+
+ /* stereo settings */
+ /* can't use any definition from the game engine here so hardcode it. Change it here when it changes there!
+ * RAS_IRasterizer has definitions:
+ * RAS_STEREO_NOSTEREO 1
+ * RAS_STEREO_QUADBUFFERED 2
+ * RAS_STEREO_ABOVEBELOW 3
+ * RAS_STEREO_INTERLACED 4 future
+ */
+ uiDefBut(block, LABEL, 0, "Stereo options", xco, yco-=20, 114, 19, 0, 0.0, 0.0, 0, 0, "");
+ uiDefButS(block, ROW, 0, "no stereo", xco+19, yco-=20, 95, 19, &(G.scene->r.stereomode), 6.0, 1.0, 0, 0, "Disables stereo");
+ uiDefButS(block, ROW, 0, "h/w pageflip", xco+19, yco-=20, 95, 19, &(G.scene->r.stereomode), 6.0, 2.0, 0, 0, "Enables h/w pageflip stereo method");
+ uiDefButS(block, ROW, 0, "syncdoubling", xco+19, yco-=20, 95, 19, &(G.scene->r.stereomode), 6.0, 3.0, 0, 0, "Enables syncdoubling stereo method");
+#if 0
+ // future
+ uiDefButS(block, ROW, 0, "syncdoubling", xco+19, yco, 95, 19, &(G.scene->r.stereomode), 5.0, 4.0, 0, 0, "Enables interlaced stereo method");
+#endif
+
+ uiBlockSetDirection(block, UI_RIGHT);
+
+ return block;
+}
+
+static uiBlock *info_file_importmenu(void *arg_unused)
+{
+ uiBlock *block;
+ short yco= 0, xco = 20;
+
+ block= uiNewBlock(&curarea->uiblocks, "importmenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
+ uiBlockSetXOfs(block, -40); // offset to parent button
+
+ uiBlockSetEmboss(block, UI_EMBOSSW);
+
+ /* flags are defines */
+ uiDefBut(block, LABEL, 0, "VRML 2.0 options", xco, yco, 125, 19, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefButS(block, TOG|BIT|0, 0, "SepLayers", xco, yco-=20, 75, 19, &U.vrmlflag, 0.0, 0.0, 0, 0, "Separate Empties, Lamps, etc. into Layers");
+ uiDefButS(block, TOG|BIT|1, 0, "Scale 1/100", xco, yco-=20, 75, 19, &U.vrmlflag, 0.0, 0.0, 0, 0, "Scale scene by 1/100 (3DS VRML)");
+ uiDefButS(block, TOG|BIT|2, 0, "Two Sided", xco, yco-=20, 75, 19, &U.vrmlflag, 0.0, 0.0, 0, 0, "Import two sided faces");
+
+ uiBlockSetDirection(block, UI_RIGHT);
+
+ return block;
+}
+
+static uiBlock *info_filemenu(void *arg_unused)
+{
+ uiBlock *block;
+ short xco=0;
+
+ block= uiNewBlock(&curarea->uiblocks, "filemenu", UI_EMBOSSP, UI_HELV, curarea->headwin);
+ uiBlockSetButmFunc(block, do_info_filemenu, NULL);
+
+ uiDefBut(block, BUTM, 1, "New|Ctrl X", 0, xco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "Start a new project (and delete the current)");
+ uiDefBut(block, BUTM, 1, "Open|F1", 0, xco-=20, 160, 19, NULL, 0.0, 0.0, 1, 1, "Open a new file");
+ uiDefBut(block, BUTM, 1, "Reopen Last|Ctrl O", 0, xco-=20, 160, 19, NULL, 0.0, 0.0, 1, 2, "Revert to the last version saved to file");
+ uiDefBut(block, BUTM, 1, "Append|Shift F1", 0, xco-=20, 160, 19, NULL, 0.0, 0.0, 1, 3, "Append contents of a file to the current project");
+ uiDefBlockBut(block, info_file_importmenu, NULL, "Import Settings|>>", 0, xco-=20, 160, 19, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, xco-=6, 160, 6, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefBut(block, BUTM, 1, "Save As|F2", 0, xco-=20, 160, 19, NULL, 0.0, 0.0, 1, 4, "Save to a new file");
+ uiDefBut(block, BUTM, 1, "Save|Ctrl W", 0, xco-=20, 160, 19, NULL, 0.0, 0.0, 1, 5, "Save to the current file");
+
+ if (LICENSE_KEY_VALID && make_nice_software()) {
+ uiDefBlockBut(block, info_file_optionsmenu, NULL, "File options|>>", 0, xco-=20, 160, 19, "Click to open the File Options menu");
+
+ uiDefBut(block, SEPR, 0, "", 0, xco-=6, 160, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefBut(block, BUTM, 1, "Save Runtime", 0, xco-=20, 160, 19, NULL, 0.0, 0.0, 1, 22, "Create a runtime executable with the current project");
+#ifdef _WIN32
+ uiDefBut(block, BUTM, 1, "Save dynamic Runtime", 0, xco-=20, 160, 19, NULL, 0.0, 0.0, 1, 23, "Create a dynamic runtime executable with the current project (requieres extenal python20.dll)");
+#endif
+ uiDefBlockBut(block, info_runtime_optionsmenu, NULL, "Runtime options|>>", 0, xco-=20, 160, 19, "Click to open the File Options menu");
+ }
+
+ uiDefBut(block, SEPR, 0, "", 0, xco-=6, 160, 6, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefBut(block, BUTM, 1, "Save Image|F3", 0, xco-=20, 160, 19, NULL, 0.0, 0.0, 1, 6, "Save the image in the render buffer to a file");
+ uiDefBut(block, BUTM, 1, "Save VRML 1.0|Ctrl F2", 0, xco-=20, 160, 19, NULL, 0.0, 0.0, 1, 7, "Save the current scene to a file in VRML 1.0 format");
+ uiDefBut(block, BUTM, 1, "Save DXF|Shift F2", 0, xco-=20, 160, 19, NULL, 0.0, 0.0, 1, 8, "Save the current scene to a file in DXF format");
+ uiDefBut(block, BUTM, 1, "Save VideoScape|Alt W", 0, xco-=20, 160, 19, NULL, 0.0, 0.0, 1, 9, "Save the current scene to a file in VideoScape format");
+
+
+ if (LICENSE_KEY_VALID) {
+ uiDefBut(block, SEPR, 0, "", 0, xco-=6, 160, 6, NULL, 0.0, 0.0, 1, 0, "");
+ uiDefBut(block, BUTM, 1, "Show License Key", 0, xco-=20, 140, 19, NULL, 0.0, 0.0, 1, 21, "Show the personal information stored in your Blender License Key");
+ uiDefIconBut(block, BUTM, 1, ICON_PUBLISHER, 141,xco, 19, 19, NULL, 0.0, 0.0, 1, 21, "Show the personal information stored in your Blender License Key");
+ } else if (I_AM_PUBLISHER) {
+ uiDefBut(block, SEPR, 0, "", 0, xco-=6, 160, 6, NULL, 0.0, 0.0, 1, 0, "");
+ uiDefBut(block, BUTM, 1, "Install License Key", 0, xco-=20, 140, 19, NULL, 0.0, 0.0, 1, 20, "Install your Blender License Key");
+ uiDefIconBut(block, BUTM, 1, ICON_PUBLISHER, 141,xco, 19, 19, NULL, 0.0, 0.0, 1, 20, "Install your Blender License Key");
+ }
+
+
+ uiDefBut(block, SEPR, 0, "", 0, xco-=6, 160, 6, NULL, 0.0, 0.0, 1, 0, "");
+
+#ifdef EXPERIMENTAL_MENUS
+ uiDefBut(block, BUTM, 1, "Pack Data", 0, xco-=20, 160, 19, NULL, 0.0, 0.0, 1, 10, "");
+ uiDefBut(block, BUTM, 1, "Unpack Data to current dir", 0, xco-=20, 160, 19, NULL, 0.0, 0.0, 1, 11, "");
+ uiDefBut(block, BUTM, 1, "Advanced Unpack", 0, xco-=20, 160, 19, NULL, 0.0, 0.0, 1, 12, "");
+ uiDefBut(block, SEPR, 0, "", 0, xco-=6, 160, 6, NULL, 0.0, 0.0, 1, 0, "");
+ uiDefBut(block, BUTM, 1, "Quit | Q", 0, xco-=20, 160, 19, NULL, 0.0, 0.0, 1, 13, "Quit Blender immediately");
+#else /* EXPERIMENTAL_MENUS */
+ uiDefBut(block, BUTM, 1, "Quit | Q", 0, xco-=20, 160, 19, NULL, 0.0, 0.0, 1, 10, "Quit Blender immediately");
+#endif /* EXPERIMENTAL_MENUS */
+ uiBlockSetDirection(block, UI_DOWN);
+
+
+ return block;
+}
+
+static void do_info_editmenu(void *arg, int event)
+{
+ int oldqual;
+
+ switch(event) {
+
+ case 0:
+ /* (De)Select All */
+ if(select_area(SPACE_VIEW3D)) mainqenter(AKEY, 1);
+ break;
+ /* Border Select */
+ case 1:
+ if(select_area(SPACE_VIEW3D)) mainqenter(BKEY, 1);
+ break;
+ case 2:
+ /* Circle Select */
+ /*if(select_area(SPACE_VIEW3D)) {
+ winqread3d(BKEY, 1, 0);
+ winqread3d(BKEY, 1, 0);
+ }*/
+ break;
+ case 3:
+ /* Duplicate */
+ if(select_area(SPACE_VIEW3D)) {
+ oldqual = G.qual;
+ G.qual = LR_SHIFTKEY;
+ winqread3d(DKEY, 1, 0);
+ G.qual = oldqual;
+ }
+ break;
+ case 4:
+ /* Delete */
+ if(select_area(SPACE_VIEW3D)) {
+ winqread3d(XKEY, 1, 0);
+ }
+ break;
+ case 5:
+ /* Edit Mode */
+ if(select_area(SPACE_VIEW3D)) {
+ blenderqread(TABKEY, 1);
+ }
+ break;
+ case 6:
+ /* Grabber */
+ if(select_area(SPACE_VIEW3D)) {
+ transform('g');
+ }
+ break;
+ case 7:
+ /* Rotate */
+ if(select_area(SPACE_VIEW3D)) {
+ transform('r');
+ }
+ break;
+ case 8:
+ /* Scale */
+ if(select_area(SPACE_VIEW3D)) {
+ transform('s');
+ }
+ break;
+ case 9:
+ /* Shear */
+ if (!G.obedit) {
+ enter_editmode();
+ /* ### put these into a deselectall_gen() */
+ if(G.obedit->type==OB_MESH) deselectall_mesh();
+ else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) deselectall_nurb();
+ else if(G.obedit->type==OB_MBALL) deselectall_mball();
+ else if(G.obedit->type==OB_LATTICE) deselectall_Latt();
+ /* ### */
+ }
+ if(select_area(SPACE_VIEW3D)) {
+ transform('S');
+ }
+ break;
+ case 10:
+ /* Warp/Bend */
+ if (!G.obedit) {
+ enter_editmode();
+ /* ### put these into a deselectall_gen() */
+ if(G.obedit->type==OB_MESH) deselectall_mesh();
+ else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) deselectall_nurb();
+ else if(G.obedit->type==OB_MBALL) deselectall_mball();
+ else if(G.obedit->type==OB_LATTICE) deselectall_Latt();
+ /* ### */
+ }
+ if(select_area(SPACE_VIEW3D)) {
+ oldqual = G.qual;
+ G.qual = LR_SHIFTKEY;
+ winqread3d(WKEY, 1, 0);
+ G.qual = oldqual;
+ }
+ break;
+ case 11:
+ /* Snap */
+ if(select_area(SPACE_VIEW3D)) {
+ oldqual = G.qual;
+ G.qual = LR_SHIFTKEY;
+ winqread3d(SKEY, 1, 0);
+ G.qual = oldqual;
+ }
+ break;
+ }
+ allqueue(REDRAWINFO, 0);
+}
+
+
+static uiBlock *info_editmenu(void *arg_unused)
+{
+/* static short tog=0; */
+ uiBlock *block;
+ short xco= 0;
+
+ block= uiNewBlock(&curarea->uiblocks, "editmenu", UI_EMBOSSP, UI_HELV, curarea->headwin);
+ uiBlockSetButmFunc(block, do_info_editmenu, NULL);
+
+ uiDefBut(block, BUTM, 1, "(De)Select All|A", 0, xco-=20, 120, 19, NULL, 0.0, 0.0, 1, 0, "Select all objects in the scene or empty the selection");
+ uiDefBut(block, BUTM, 1, "Border Select|B", 0, xco-=20, 120, 19, NULL, 0.0, 0.0, 1, 1, "Select objects in a rectangular area (press B again to activate circle select in edit mode)");
+
+ /* uiDefBut(block, BUTM, 1, "Circle Select", 0, xco-=20, 120, 19, NULL, 0.0, 0.0, 1, 2, "Select objects in a circular area"); */
+ uiDefBut(block, SEPR, 0, "", 0, xco-=6, 120, 6, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefBut(block, BUTM, 1, "Duplicate|Shift D", 0, xco-=20, 120, 19, NULL, 0.0, 0.0, 1, 3, "Duplicate the selected object(s)");
+ uiDefBut(block, BUTM, 1, "Delete|X", 0, xco-=20, 120, 19, NULL, 0.0, 0.0, 1, 4, "Delete the selected object(s)");
+ uiDefBut(block, BUTM, 1, "Edit Mode|Tab", 0, xco-=20, 120, 19, NULL, 0.0, 0.0, 1, 5, "Toggle between object and edit mode");
+ uiDefBut(block, SEPR, 0, "", 0, xco-=6, 120, 6, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefBut(block, BUTM, 1, "Grabber|G", 0, xco-=20, 120, 19, NULL, 0.0, 0.0, 1, 6, "Move the selected object(s)");
+ uiDefBut(block, BUTM, 1, "Rotate|R", 0, xco-=20, 120, 19, NULL, 0.0, 0.0, 1, 7, "Rotate the selected object(s)");
+ uiDefBut(block, BUTM, 1, "Scale|S", 0, xco-=20, 120, 19, NULL, 0.0, 0.0, 1, 8, "Scale the selected object(s)");
+ uiDefBut(block, SEPR, 0, "", 0, xco-=6, 120, 6, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefBut(block, BUTM, 1, "Shear|Ctrl S", 0, xco-=20, 120, 19, NULL, 0.0, 0.0, 1, 9, "Shear the selected object(s)");
+ uiDefBut(block, BUTM, 1, "Warp/Bend|Shift W", 0, xco-=20, 120, 19, NULL, 0.0, 0.0, 1, 10, "Warp or bend the selected objects");
+ uiDefBut(block, BUTM, 1, "Snap Menu|Shift S", 0, xco-=20, 120, 19, NULL, 0.0, 0.0, 1, 11, "Activate the snap menu");
+
+ uiBlockSetDirection(block, UI_DOWN);
+
+ return block;
+}
+
+static void do_info_add_meshmenu(void *arg, int event)
+{
+
+ switch(event) {
+#ifdef EXPERIMENTAL_MENUS
+ /* Maarten's proposal for a new Add Mesh menu */
+ case 0:
+ /* Line */
+ //add_primitiveMesh(4);
+ break;
+ case 1:
+ /* Circle */
+ if(select_area(SPACE_VIEW3D)) {
+ add_primitiveMesh(4);
+ }
+ break;
+ case 2:
+ /* Plane */
+ add_primitiveMesh(0);
+ break;
+ case 3:
+ /* Cube */
+ add_primitiveMesh(1);
+ break;
+ case 4:
+ /* UVsphere */
+ add_primitiveMesh(11);
+ break;
+ case 5:
+ /* IcoSphere */
+ add_primitiveMesh(12);
+ break;
+ case 6:
+ /* Cylinder */
+ add_primitiveMesh(5);
+ break;
+ case 7:
+ /* Tube */
+ add_primitiveMesh(6);
+ break;
+ case 8:
+ /* Cone */
+ add_primitiveMesh(7);
+ break;
+ case 9:
+ /* Grid */
+ add_primitiveMesh(10);
+ break;
+#else /* EXPERIMENTAL_MENUS*/
+ case 0:
+ /* Plane */
+ add_primitiveMesh(0);
+ break;
+ case 1:
+ /* Cube */
+ add_primitiveMesh(1);
+ break;
+ case 2:
+ /* Circle */
+ add_primitiveMesh(4);
+ break;
+ case 3:
+ /* UVsphere */
+ add_primitiveMesh(11);
+ break;
+ case 4:
+ /* IcoSphere */
+ add_primitiveMesh(12);
+ break;
+ case 5:
+ /* Cylinder */
+ add_primitiveMesh(5);
+ break;
+ case 6:
+ /* Tube */
+ add_primitiveMesh(6);
+ break;
+ case 7:
+ /* Cone */
+ add_primitiveMesh(7);
+ break;
+ case 8:
+ /* Grid */
+ add_primitiveMesh(10);
+ break;
+#endif /* EXPERIMENTAL_MENUS */
+ default:
+ break;
+ }
+ allqueue(REDRAWINFO, 0);
+}
+
+static uiBlock *info_add_meshmenu(void *arg_unused)
+{
+/* static short tog=0; */
+ uiBlock *block;
+ short xco= 0;
+
+ block= uiNewBlock(&curarea->uiblocks, "add_meshmenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
+ uiBlockSetButmFunc(block, do_info_add_meshmenu, NULL);
+
+#ifdef EXPERIMENTAL_MENUS
+ /* Maarten's proposal for a new Add Mesh menu */
+ uiDefBut(block, BUTM, 1, "Line|", 0, xco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "Add a Mesh Line");
+ uiDefBut(block, BUTM, 1, "Circle|", 0, xco-=20, 160, 19, NULL, 0.0, 0.0, 1, 1, "Add a Mesh Circle");
+ uiDefBut(block, SEPR, 0, "", 0, xco-=6, 160, 6, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefBut(block, BUTM, 1, "Plane|", 0, xco-=20, 160, 19, NULL, 0.0, 0.0, 1, 2, "Add a Mesh Plane");
+ uiDefBut(block, BUTM, 1, "Cube|", 0, xco-=20, 160, 19, NULL, 0.0, 0.0, 1, 3, "Add a Mesh Cube");
+ uiDefBut(block, BUTM, 1, "UVsphere", 0, xco-=20, 160, 19, NULL, 0.0, 0.0, 1, 4, "Add a Mesh Sphere");
+ uiDefBut(block, BUTM, 1, "IcoSphere|", 0, xco-=20, 160, 19, NULL, 0.0, 0.0, 1, 5, "Add a Mesh Isocohedron Sphere");
+ uiDefBut(block, BUTM, 1, "Cylinder With Caps|", 0, xco-=20, 160, 19, NULL, 0.0, 0.0, 1, 6, "Add a Mesh Cylinder with caps");
+ uiDefBut(block, BUTM, 1, "Cylinder Without Caps|", 0, xco-=20, 160, 19, NULL, 0.0, 0.0, 1, 7, "Add a Mesh Cylinder without caps");
+ uiDefBut(block, BUTM, 1, "Cone|", 0, xco-=20, 160, 19, NULL, 0.0, 0.0, 1, 8, "Add a Mesh Cone");
+ uiDefBut(block, BUTM, 1, "Grid|", 0, xco-=20, 160, 19, NULL, 0.0, 0.0, 1, 9, "Add a Mesh Grid");
+#else /* EXPERIMENTAL_MENUS */
+ uiDefBut(block, BUTM, 1, "Plane|", 0, xco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "Add a Mesh Plane");
+ uiDefBut(block, BUTM, 1, "Cube|", 0, xco-=20, 160, 19, NULL, 0.0, 0.0, 1, 1, "Add a Mesh Cube");
+ uiDefBut(block, BUTM, 1, "Circle|", 0, xco-=20, 160, 19, NULL, 0.0, 0.0, 1, 2, "Add a Mesh Circle");
+ uiDefBut(block, BUTM, 1, "UVsphere", 0, xco-=20, 160, 19, NULL, 0.0, 0.0, 1, 3, "Add a Mesh Sphere");
+ uiDefBut(block, BUTM, 1, "IcoSphere|", 0, xco-=20, 160, 19, NULL, 0.0, 0.0, 1, 4, "Add a Mesh Isocohedron Sphere");
+ uiDefBut(block, BUTM, 1, "Cylinder|", 0, xco-=20, 160, 19, NULL, 0.0, 0.0, 1, 5, "Add a Mesh Cylinder");
+ uiDefBut(block, BUTM, 1, "Tube|", 0, xco-=20, 160, 19, NULL, 0.0, 0.0, 1, 6, "Add a Mesh Tube");
+ uiDefBut(block, BUTM, 1, "Cone|", 0, xco-=20, 160, 19, NULL, 0.0, 0.0, 1, 7, "Add a Mesh Cone");
+ uiDefBut(block, SEPR, 0, "", 0, xco-=6, 160, 6, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefBut(block, BUTM, 1, "Grid|", 0, xco-=20, 160, 19, NULL, 0.0, 0.0, 1, 8, "Add a Mesh Grid");
+#endif /* EXPERIMENTAL_MENUS */
+
+ uiBlockSetDirection(block, UI_RIGHT);
+
+ return block;
+}
+
+static void do_info_add_curvemenu(void *arg, int event)
+{
+
+ switch(event) {
+ case 0:
+ /* Bezier Curve */
+ add_primitiveCurve(10);
+ break;
+ case 1:
+ /* Bezier Circle */
+ add_primitiveCurve(11);
+ break;
+ case 2:
+ /* NURB Curve */
+ add_primitiveCurve(40);
+ break;
+ case 3:
+ /* NURB Circle */
+ add_primitiveCurve(41);
+ break;
+ case 4:
+ /* Path */
+ add_primitiveCurve(46);
+ break;
+ default:
+ break;
+ }
+ allqueue(REDRAWINFO, 0);
+}
+
+static uiBlock *info_add_curvemenu(void *arg_unused)
+{
+/* static short tog=0; */
+ uiBlock *block;
+ short xco= 0;
+
+ block= uiNewBlock(&curarea->uiblocks, "add_curvemenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
+ uiBlockSetButmFunc(block, do_info_add_curvemenu, NULL);
+
+ uiDefBut(block, BUTM, 1, "Bezier Curve|", 0, xco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "Add a Bezier curve");
+ uiDefBut(block, BUTM, 1, "Bezier Circle|", 0, xco-=20, 160, 19, NULL, 0.0, 0.0, 1, 1, "Add a Bezier circle");
+ uiDefBut(block, BUTM, 1, "NURBS Curve|", 0, xco-=20, 160, 19, NULL, 0.0, 0.0, 1, 2, "Add a NURB curve");
+ uiDefBut(block, BUTM, 1, "NURBS Circle", 0, xco-=20, 160, 19, NULL, 0.0, 0.0, 1, 3, "Add a NURB circle");
+ uiDefBut(block, BUTM, 1, "Path|", 0, xco-=20, 160, 19, NULL, 0.0, 0.0, 1, 4, "Add a path");
+
+ uiBlockSetDirection(block, UI_RIGHT);
+
+ return block;
+}
+
+
+static void do_info_add_surfacemenu(void *arg, int event)
+{
+
+ switch(event) {
+ case 0:
+ /* Curve */
+ add_primitiveNurb(0);
+ break;
+ case 1:
+ /* Circle */
+ add_primitiveNurb(1);
+ break;
+ case 2:
+ /* Surface */
+ add_primitiveNurb(2);
+ break;
+ case 3:
+ /* Tube */
+ add_primitiveNurb(3);
+ break;
+ case 4:
+ /* Sphere */
+ add_primitiveNurb(4);
+ break;
+ case 5:
+ /* Donut */
+ add_primitiveNurb(5);
+ break;
+ default:
+ break;
+ }
+ allqueue(REDRAWINFO, 0);
+}
+
+static uiBlock *info_add_surfacemenu(void *arg_unused)
+{
+/* static short tog=0; */
+ uiBlock *block;
+ short xco= 0;
+
+ block= uiNewBlock(&curarea->uiblocks, "add_surfacemenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
+ uiBlockSetButmFunc(block, do_info_add_surfacemenu, NULL);
+
+ uiDefBut(block, BUTM, 1, "NURBS Curve|", 0, xco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "Add a curve");
+ uiDefBut(block, BUTM, 1, "NURBS Circle|", 0, xco-=20, 160, 19, NULL, 0.0, 0.0, 1, 1, "Add a circle");
+ uiDefBut(block, BUTM, 1, "NURBS Surface|", 0, xco-=20, 160, 19, NULL, 0.0, 0.0, 1, 2, "Add a surface");
+ uiDefBut(block, BUTM, 1, "NURBS Tube", 0, xco-=20, 160, 19, NULL, 0.0, 0.0, 1, 3, "Add a tube");
+ uiDefBut(block, BUTM, 1, "NURBS Sphere|", 0, xco-=20, 160, 19, NULL, 0.0, 0.0, 1, 4, "Add a sphere");
+ uiDefBut(block, BUTM, 1, "NURBS Donut|", 0, xco-=20, 160, 19, NULL, 0.0, 0.0, 1, 5, "Add a donut");
+
+ uiBlockSetDirection(block, UI_RIGHT);
+
+ return block;
+}
+
+static void do_info_addmenu(void *arg, int event)
+{
+
+ switch(event) {
+ case 0:
+ /* Mesh */
+ break;
+ case 1:
+ /* Curve */
+ break;
+ case 2:
+ /* Surface */
+ break;
+ case 3:
+ /* Text (argument is discarded) */
+ add_primitiveFont(event);
+ break;
+ case 4:
+ /* Metaball (argument is discarded) */
+ add_primitiveMball(event);
+ break;
+ case 5:
+ /* Empty */
+ add_object_draw(OB_EMPTY);
+ break;
+ case 6:
+ /* Camera */
+ add_object_draw(OB_CAMERA);
+ break;
+ case 7:
+ /* Lamp */
+ add_object_draw(OB_LAMP);
+ break;
+ case 8:
+ /* Armature */
+ add_primitiveArmature(OB_ARMATURE);
+ break;
+ case 9:
+ /* Lattice */
+ add_object_draw(OB_LATTICE);
+ break;
+ default:
+ break;
+ }
+ allqueue(REDRAWINFO, 0);
+}
+
+
+static uiBlock *info_addmenu(void *arg_unused)
+{
+/* static short tog=0; */
+ uiBlock *block;
+ short xco= 0;
+
+ block= uiNewBlock(&curarea->uiblocks, "addmenu", UI_EMBOSSP, UI_HELV, curarea->headwin);
+ uiBlockSetButmFunc(block, do_info_addmenu, NULL);
+
+ uiDefBlockBut(block, info_add_meshmenu, NULL, "Mesh|>>", 0, xco-=20, 120, 19, "Click to open the Add Mesh menu");
+ uiDefBlockBut(block, info_add_curvemenu, NULL, "Curve|>>", 0, xco-=20, 120, 19, "Click to open the Add Curve menu");
+ uiDefBlockBut(block, info_add_surfacemenu, NULL, "Surface|>>", 0, xco-=20, 120, 19, "Click to open the Add Surface menu");
+
+ uiDefBut(block, SEPR, 0, "", 0, xco-=6, 120, 6, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefBut(block, BUTM, 1, "Text|", 0, xco-=20, 120, 19, NULL, 0.0, 0.0, 1, 3, "");
+ uiDefBut(block, BUTM, 1, "Metaball|", 0, xco-=20, 120, 19, NULL, 0.0, 0.0, 1, 4, "");
+ uiDefBut(block, BUTM, 1, "Empty|", 0, xco-=20, 120, 19, NULL, 0.0, 0.0, 1, 5, "");
+ uiDefBut(block, SEPR, 0, "", 0, xco-=6, 120, 6, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefBut(block, BUTM, 1, "Camera|", 0, xco-=20, 120, 19, NULL, 0.0, 0.0, 1, 6, "");
+ uiDefBut(block, BUTM, 1, "Lamp|", 0, xco-=20, 120, 19, NULL, 0.0, 0.0, 1, 7, "");
+// uiDefBut(block, BUTM, 1, "Armature|", 0, xco-=20, 120, 19, NULL, 0.0, 0.0, 1, 8, "");
+ uiDefBut(block, SEPR, 0, "", 0, xco-=6, 120, 6, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefBut(block, BUTM, 1, "Lattice|", 0, xco-=20, 120, 19, NULL, 0.0, 0.0, 1, 9, "");
+
+ uiBlockSetDirection(block, UI_DOWN);
+
+ return block;
+}
+
+static void do_info_viewmenu(void *arg, int event)
+{
+ switch(event) {
+ case 0:
+ if(select_area(SPACE_VIEW3D)) mainqenter(PAD1, 1);
+ break;
+ case 1:
+ if(select_area(SPACE_VIEW3D)) mainqenter(PAD3, 1);
+ break;
+ case 2:
+ if(select_area(SPACE_VIEW3D)) mainqenter(PAD7, 1);
+ break;
+ case 3:
+ if(select_area(SPACE_VIEW3D)) mainqenter(PAD0, 1);
+ break;
+ case 4:
+ if(select_area(SPACE_VIEW3D)) mainqenter(PADPLUSKEY, 1);
+ break;
+ case 5:
+ if(select_area(SPACE_VIEW3D)) mainqenter(PADMINUS, 1);
+ break;
+ case 6:
+ if(select_area(SPACE_VIEW3D)) mainqenter(CKEY, 1);
+ break;
+ case 7:
+ if(select_area(SPACE_VIEW3D)) mainqenter(HOMEKEY, 1);
+ break;
+ }
+ allqueue(REDRAWINFO, 0);
+}
+
+static uiBlock *info_viewmenu(void *arg_unused)
+{
+/* static short tog=0; */
+ uiBlock *block;
+ short xco= 0;
+
+ block= uiNewBlock(&curarea->uiblocks, "filemenu", UI_EMBOSSP, UI_HELV, curarea->headwin);
+ uiBlockSetButmFunc(block, do_info_viewmenu, NULL);
+
+ // uiBlockSetCol(block, BUTBLUE);
+
+ uiDefBut(block, BUTM, 1, "Front|NumPad 1", 0, xco-=20, 140, 19, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefBut(block, BUTM, 1, "Right|NumPad 3", 0, xco-=20, 140, 19, NULL, 0.0, 0.0, 0, 1, "");
+ uiDefBut(block, BUTM, 1, "Top|NumPad 7", 0, xco-=20, 140, 19, NULL, 0.0, 0.0, 0, 2, "");
+ uiDefBut(block, BUTM, 1, "Camera|NumPad 0", 0, xco-=20, 140, 19, NULL, 0.0, 0.0, 0, 3, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, xco-=6, 140, 6, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefBut(block, BUTM, 1, "Zoom In|NumPad +", 0, xco-=20, 140, 19, NULL, 0.0, 0.0, 0, 4, "");
+ uiDefBut(block, BUTM, 1, "Zoom Out|NumPad -", 0, xco-=20, 140, 19, NULL, 0.0, 0.0, 0, 5, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, xco-=6, 140, 6, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefBut(block, BUTM, 1, "Center|C", 0, xco-=20, 140, 19, NULL, 0.0, 0.0, 0, 6, "");
+ uiDefBut(block, BUTM, 1, "View All|Home", 0, xco-=20, 140, 19, NULL, 0.0, 0.0, 0, 7, "");
+
+ uiBlockSetDirection(block, UI_DOWN);
+
+ return block;
+}
+
+static void do_game_menu(void *arg, int event)
+{
+ switch (event) {
+ case G_FILE_ENABLE_ALL_FRAMES_BIT:
+ case G_FILE_SHOW_FRAMERATE_BIT:
+ case G_FILE_SHOW_DEBUG_PROPS_BIT:
+ case G_FILE_AUTOPLAY_BIT:
+ G.fileflags ^= (1 << event);
+ break;
+ default:
+ ; /* ignore the rest */
+ }
+}
+
+
+static uiBlock *info_gamemenu(void *arg_unused)
+{
+ uiBlock *block;
+ short yco= 0;
+
+ block= uiNewBlock(&curarea->uiblocks, "gamemenu", UI_EMBOSSP, UI_HELV, curarea->headwin);
+ uiBlockSetCol(block, BUTBLUE);
+ uiBlockSetDirection(block, UI_DOWN);
+
+ uiDefBut(block, BUTM, B_STARTGAME, "Start Game|P",
+ 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 0, 0,
+ "Start the game (press the Escape key to stop)");
+ uiDefBut(block, SEPR, 0, "",
+ -20, yco-=6, 180, 6, NULL, 0.0, 0.0, 1, 0, "");
+
+ /* flags are case-values */
+ uiBlockSetButmFunc(block, do_game_menu, NULL);
+ uiDefBut(block, BUTM, 1, "Enable All Frames",
+ 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, G_FILE_ENABLE_ALL_FRAMES_BIT,
+ "Toggle between draw all frames on (no frames dropped) and off (full speed)");
+ uiDefBut(block, BUTM, 1, "Show framerate and profile",
+ 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, G_FILE_SHOW_FRAMERATE_BIT,
+ "Toggle between showing and not showing the framerate and profile");
+ uiDefBut(block, BUTM, 1, "Show debug properties",
+ 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, G_FILE_SHOW_DEBUG_PROPS_BIT,
+ "Toggle between showing and not showing debug properties");
+ uiDefBut(block, SEPR, 0, "", -20, yco-=6, 180, 6, NULL, 0.0, 0.0, 1, 0, "");
+ uiDefBut(block, BUTM, 1, "Autostart",
+ 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, G_FILE_AUTOPLAY_BIT,
+ "Toggle between automatic game start on and off");
+
+ /* Toggle buttons */
+ yco= -26;
+ uiBlockSetEmboss(block, UI_EMBOSSW);
+ /* flags are defines */
+
+ uiBlockSetButmFunc(block, NULL, NULL); // to prevent it from calling the menu function
+ uiDefIconButI(block, ICONTOG|BIT|G_FILE_ENABLE_ALL_FRAMES_BIT,
+ 0, ICON_CHECKBOX_DEHLT, -20, yco-=20, 19, 19,
+ &G.fileflags, 0.0, 0.0, 0, 0, "");
+ uiDefIconButI(block, ICONTOG|BIT|G_FILE_SHOW_FRAMERATE_BIT,
+ 0, ICON_CHECKBOX_DEHLT, -20, yco-=20, 19, 19,
+ &G.fileflags, 0.0, 0.0, 0, 0, "");
+ uiDefIconButI(block, ICONTOG|BIT|G_FILE_SHOW_DEBUG_PROPS_BIT,
+ 0, ICON_CHECKBOX_DEHLT, -20, yco-=20, 19, 19,
+ &G.fileflags, 0.0, 0.0, 0, 0, "");
+ yco-=6;
+ uiDefIconButI(block, ICONTOG|BIT|G_FILE_AUTOPLAY_BIT,
+ 0, ICON_CHECKBOX_DEHLT, -20, yco-=20, 19, 19,
+ &G.fileflags, 0.0, 0.0, 0, 0, "");
+
+ return block;
+}
+
+#ifndef EXPERIMENTAL_MENUS
+/* In the Maarten's new menu structure proposal, the tools menu moved to the file menu */
+static void do_info_toolsmenu(void *arg, int event)
+{
+
+ switch(event) {
+ case 0:
+ check_packAll();
+ break;
+ case 1:
+ unpackAll(PF_WRITE_LOCAL);
+ G.fileflags &= ~G_AUTOPACK;
+ break;
+ case 2:
+ if (buttons_do_unpack() != RET_CANCEL) {
+ // clear autopack bit only if
+ // user selected one of the unpack options
+ G.fileflags &= ~G_AUTOPACK;
+ }
+ break;
+ }
+ allqueue(REDRAWINFO, 0);
+}
+
+static uiBlock *info_toolsmenu(void *arg_unused)
+{
+/* static short tog=0; */
+ uiBlock *block;
+ short xco= 0;
+
+ block= uiNewBlock(&curarea->uiblocks, "toolsmenu", UI_EMBOSSP, UI_HELV, curarea->headwin);
+ uiBlockSetButmFunc(block, do_info_toolsmenu, NULL);
+ // uiBlockSetCol(block, BUTBLUE);
+
+ uiDefBut(block, BUTM, 1, "Pack Data", 0, xco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
+ uiDefBut(block, BUTM, 1, "Unpack Data to current dir", 0, xco-=20, 160, 19, NULL, 0.0, 0.0, 1, 1, "");
+ uiDefBut(block, BUTM, 1, "Advanced Unpack", 0, xco-=20, 160, 19, NULL, 0.0, 0.0, 1, 2, "");
+ uiBlockSetDirection(block, UI_DOWN);
+
+ return block;
+}
+#endif /* EXPERIMENTAL_MENUS */
+
+
+static void info_text(int x, int y)
+{
+ Object *ob;
+ extern float hashvectf[];
+ extern int mem_in_use;
+ unsigned int swatch_color;
+ float fac1, fac2, fac3;
+ char infostr[300];
+ char *headerstr;
+ int hsize;
+
+
+ if(G.obedit) {
+ sprintf(infostr,"Ve:%d-%d Fa:%d-%d Mem:%.2fM ",
+ G.totvertsel, G.totvert, G.totfacesel, G.totface,
+ (mem_in_use>>10)/1024.0);
+ }
+ else {
+ sprintf(infostr,"Ve:%d Fa:%d Ob:%d-%d La:%d Mem:%.2fM ",
+ G.totvert, G.totface, G.totobj, G.totobjsel, G.totlamp, (mem_in_use>>10)/1024.0);
+ }
+ ob= OBACT;
+ if(ob) {
+ strcat(infostr, ob->id.name+2);
+ }
+
+ if (g_progress_bar) {
+ hsize = 4 + (120.0 * g_done);
+ fac1 = 0.5 * g_done; // do some rainbow colours on progress
+ fac2 = 1.0;
+ fac3 = 0.9;
+ } else {
+ hsize = 124;
+ /* promise! Never change these lines again! */
+ fac1= fabs(hashvectf[ 2*G.version+4]);
+ fac2= 0.5+0.1*hashvectf[ G.version+3];
+ fac3= 0.7;
+ }
+
+ if (g_progress_bar && g_progress_info) {
+ headerstr= g_progress_info;
+ } else {
+ headerstr= versionstr;
+ }
+
+ swatch_color= hsv_to_cpack(fac1, fac2, fac3);
+
+ cpack( swatch_color );
+ glRecti(x-24, y-4, x-24+hsize, y+13);
+
+ glColor3ub(0, 0, 0);
+
+ glRasterPos2i(x, y);
+ BMF_DrawString(G.fonts, headerstr);
+
+ glRasterPos2i(x+120, y);
+ BMF_DrawString(G.fonts, infostr);
+}
+
+void info_buttons(void)
+{
+ uiBlock *block;
+ short xco= 32;
+ char naam[20];
+
+ sprintf(naam, "header %d", curarea->headwin);
+ block= uiNewBlock(&curarea->uiblocks, naam, UI_EMBOSSM, UI_HELV, curarea->headwin);
+ uiBlockSetCol(block, BUTGREY);
+
+ uiDefBlockBut(block, info_filemenu, NULL, "File", xco, 3, 40, 15, "");
+ xco+= 40;
+ uiDefBlockBut(block, info_editmenu, NULL, "Edit", xco, 3, 40, 15, "");
+ xco+= 40;
+
+ uiDefBlockBut(block, info_addmenu, NULL, "Add", xco, 3, 40, 15, "");
+ xco+= 40;
+
+ uiDefBlockBut(block, info_viewmenu, NULL, "View", xco, 3, 40, 15, "");
+ xco+= 40;
+ uiDefBlockBut(block, info_gamemenu, NULL, "Game", xco, 3, 40, 15, "");
+ xco+= 40;
+
+#ifndef EXPERIMENTAL_MENUS
+ /* In the Maarten's new menu structure proposal, the tools menu moved to the file menu */
+ uiDefBlockBut(block, info_toolsmenu, NULL, "Tools", xco, 3, 40, 15, "");
+ xco+= 40;
+#endif /* EXPERIMENTAL_MENUS */
+
+ /* pack icon indicates a packed file */
+
+ if (G.fileflags & G_AUTOPACK) {
+ uiBlockSetEmboss(block, UI_EMBOSSN);
+ uiDefIconBut(block, LABEL, 0, ICON_PACKAGE, xco, 0, XIC, YIC, &G.fileflags, 0.0, 0.0, 0, 0, "This is a Packed file. See File menu.");
+ xco += 24;
+ uiBlockSetEmboss(block, UI_EMBOSSX);
+ }
+
+ uiBlockSetEmboss(block, UI_EMBOSSX);
+
+ if (curarea->full == 0) {
+ curarea->butspacetype= SPACE_INFO;
+ uiDefIconButC(block, ICONROW,B_NEWSPACE, ICON_VIEW3D, 6,0,XIC,YIC, &(curarea->butspacetype), 1.0, SPACEICONMAX, 0, 0, "Current window type ");
+
+ /* STD SCREEN BUTTONS */
+ xco+= XIC;
+ xco= std_libbuttons(block, xco, 0, NULL, B_INFOSCR, (ID *)G.curscreen, 0, &G.curscreen->screennr, 1, 1, B_INFODELSCR, 0);
+
+ /* STD SCENE BUTTONS */
+ xco+= 5;
+ xco= std_libbuttons(block, xco, 0, NULL, B_INFOSCE, (ID *)G.scene, 0, &G.curscreen->scenenr, 1, 1, B_INFODELSCE, 0);
+ }
+ else xco= 430;
+
+ info_text(xco+24, 6);
+
+ uiBlockSetEmboss(block, UI_EMBOSSN);
+ uiDefIconBut(block, BUT, B_SHOWSPLASH, ICON_BLENDER, xco+1, 0,XIC,YIC, 0, 0, 0, 0, 0, "");
+ uiBlockSetEmboss(block, UI_EMBOSSX);
+
+ if (LICENSE_KEY_VALID) {
+ uiBlockSetEmboss(block, UI_EMBOSSN);
+ uiDefIconBut(block, LABEL, 0, ICON_PUBLISHER, xco+125, 0,XIC,YIC, 0, 0, 0, 0, 0, "");
+ uiBlockSetEmboss(block, UI_EMBOSSX);
+ }
+
+ /* altijd als laatste doen */
+ curarea->headbutlen= xco+2*XIC;
+
+ if(curarea->headbutlen + 4*XIC < curarea->winx) {
+ uiDefIconBut(block, BUT, B_FILEMENU, ICON_HELP, (short)(curarea->winx-XIC-2), 0,XIC,YIC, 0, 0, 0, 0, 0, "Toolbox menu, hotkey: SPACE");
+ }
+
+ uiDrawBlock(block);
+}
+
+/* ********************** END INFO ****************************** */
+/* ********************** SEQUENCE ****************************** */
+
+void do_seq_buttons(short event)
+{
+ Editing *ed;
+
+ ed= G.scene->ed;
+ if(ed==0) return;
+
+ switch(event) {
+ case B_SEQHOME:
+ G.v2d->cur= G.v2d->tot;
+ test_view2d(G.v2d, curarea->winx, curarea->winy);
+ scrarea_queue_winredraw(curarea);
+ break;
+ case B_SEQCLEAR:
+ free_imbuf_seq();
+ allqueue(REDRAWSEQ, 1);
+ break;
+ }
+
+}
+
+void seq_buttons()
+{
+ SpaceSeq *sseq;
+ short xco;
+ char naam[20];
+ uiBlock *block;
+
+ sseq= curarea->spacedata.first;
+
+ sprintf(naam, "header %d", curarea->headwin);
+ block= uiNewBlock(&curarea->uiblocks, naam, UI_EMBOSSX, UI_HELV, curarea->headwin);
+ uiBlockSetCol(block, BUTPURPLE);
+
+ curarea->butspacetype= SPACE_SEQ;
+ uiDefIconButC(block, ICONROW,B_NEWSPACE, ICON_VIEW3D, 6,0,XIC,YIC, &(curarea->butspacetype), 1.0, SPACEICONMAX, 0, 0, "Current window type ");
+
+ /* FULL WINDOW */
+ xco= 25;
+ if(curarea->full) uiDefIconBut(block, BUT,B_FULL, ICON_SPLITSCREEN, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Restore smaller windows (CTRL+Up arrow)");
+ else uiDefIconBut(block, BUT,B_FULL, ICON_FULLSCREEN, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Make fullscreen window (CTRL+Down arrow)");
+
+ /* HOME */
+ uiDefIconBut(block, BUT, B_SEQHOME, ICON_HOME, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Home (HOMEKEY)");
+ xco+= XIC;
+
+ /* IMAGE */
+ uiDefIconButS(block, TOG, B_REDR, ICON_IMAGE_COL, xco+=XIC,0,XIC,YIC, &sseq->mainb, 0, 0, 0, 0, "Toggles image display");
+
+ /* ZOOM en BORDER */
+ xco+= XIC;
+ uiDefIconButI(block, TOG, B_VIEW2DZOOM, ICON_VIEWZOOM, xco+=XIC,0,XIC,YIC, &viewmovetemp, 0, 0, 0, 0, "Zoom view (CTRL+MiddleMouse)");
+ uiDefIconBut(block, BUT, B_IPOBORDER, ICON_BORDERMOVE, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Translate view (MiddleMouse)");
+
+ /* CLEAR MEM */
+ xco+= XIC;
+ uiDefBut(block, BUT, B_SEQCLEAR, "Clear", xco+=XIC,0,2*XIC,YIC, 0, 0, 0, 0, 0, "Forces a clear of all buffered images in memory");
+
+ uiDrawBlock(block);
+}
+
+/* ********************** END SEQ ****************************** */
+/* ********************** VIEW3D ****************************** */
+
+void do_view3d_buttons(short event)
+{
+ int bit;
+
+ /* pas op: als curarea->win niet bestaat, afvangen als direkt tekenroutines worden aangeroepen */
+
+ switch(event) {
+ case B_HOME:
+ view3d_home(0);
+ break;
+ case B_SCENELOCK:
+ if(G.vd->scenelock) {
+ G.vd->lay= G.scene->lay;
+ /* layact zoeken */
+ bit= 0;
+ while(bit<32) {
+ if(G.vd->lay & (1<<bit)) {
+ G.vd->layact= 1<<bit;
+ break;
+ }
+ bit++;
+ }
+ G.vd->camera= G.scene->camera;
+ scrarea_queue_winredraw(curarea);
+ scrarea_queue_headredraw(curarea);
+ }
+ break;
+ case B_LOCALVIEW:
+ if(G.vd->localview) initlocalview();
+ else endlocalview(curarea);
+ scrarea_queue_headredraw(curarea);
+ break;
+ case B_EDITMODE:
+ if (G.f & G_VERTEXPAINT) {
+ /* Switch off vertex paint */
+ G.f &= ~G_VERTEXPAINT;
+ }
+ if (G.f & G_WEIGHTPAINT){
+ /* Switch off weight paint */
+ G.f &= ~G_WEIGHTPAINT;
+ }
+#ifdef NAN_TPT
+ if (G.f & G_TEXTUREPAINT) {
+ /* Switch off texture paint */
+ G.f &= ~G_TEXTUREPAINT;
+ }
+#endif /* NAN_VPT */
+ if(G.obedit==0) enter_editmode();
+ else exit_editmode(1);
+ scrarea_queue_headredraw(curarea);
+ break;
+ case B_POSEMODE:
+ /* if (G.obedit){
+ error("Unable to perform function in EditMode");
+ G.vd->flag &= ~V3D_POSEMODE;
+ scrarea_queue_headredraw(curarea);
+ }
+ else{
+ */
+ if (G.obpose==NULL) enter_posemode();
+ else exit_posemode(1);
+
+ allqueue(REDRAWHEADERS, 0);
+
+ break;
+ case B_WPAINT:
+ if (G.f & G_VERTEXPAINT) {
+ /* Switch off vertex paint */
+ G.f &= ~G_VERTEXPAINT;
+ }
+#ifdef NAN_TPT
+ if ((!(G.f & G_WEIGHTPAINT)) && (G.f & G_TEXTUREPAINT)) {
+ /* Switch off texture paint */
+ G.f &= ~G_TEXTUREPAINT;
+ }
+#endif /* NAN_VPT */
+ if(G.obedit) {
+ error("Unable to perform function in EditMode");
+ G.vd->flag &= ~V3D_WEIGHTPAINT;
+ scrarea_queue_headredraw(curarea);
+ }
+ else if(G.obpose) {
+ error("Unable to perform function in PoseMode");
+ G.vd->flag &= ~V3D_WEIGHTPAINT;
+ scrarea_queue_headredraw(curarea);
+ }
+ else set_wpaint();
+ break;
+ case B_VPAINT:
+ if ((!(G.f & G_VERTEXPAINT)) && (G.f & G_WEIGHTPAINT)) {
+ G.f &= ~G_WEIGHTPAINT;
+ }
+#ifdef NAN_TPT
+ if ((!(G.f & G_VERTEXPAINT)) && (G.f & G_TEXTUREPAINT)) {
+ /* Switch off texture paint */
+ G.f &= ~G_TEXTUREPAINT;
+ }
+#endif /* NAN_VPT */
+ if(G.obedit) {
+ error("Unable to perform function in EditMode");
+ G.vd->flag &= ~V3D_VERTEXPAINT;
+ scrarea_queue_headredraw(curarea);
+ }
+ else if(G.obpose) {
+ error("Unable to perform function in PoseMode");
+ G.vd->flag &= ~V3D_VERTEXPAINT;
+ scrarea_queue_headredraw(curarea);
+ }
+ else set_vpaint();
+ break;
+
+#ifdef NAN_TPT
+ case B_TEXTUREPAINT:
+ if (G.f & G_TEXTUREPAINT) {
+ G.f &= ~G_TEXTUREPAINT;
+ }
+ else {
+ if (G.obedit) {
+ error("Unable to perform function in EditMode");
+ G.vd->flag &= ~V3D_TEXTUREPAINT;
+ }
+ else {
+ if (G.f & G_WEIGHTPAINT){
+ /* Switch off weight paint */
+ G.f &= ~G_WEIGHTPAINT;
+ }
+ if (G.f & G_VERTEXPAINT) {
+ /* Switch off vertex paint */
+ G.f &= ~G_VERTEXPAINT;
+ }
+ if (G.f & G_FACESELECT) {
+ /* Switch off face select */
+ G.f &= ~G_FACESELECT;
+ }
+ G.f |= G_TEXTUREPAINT;
+ scrarea_queue_headredraw(curarea);
+ }
+ }
+ break;
+#endif /* NAN_TPT */
+
+ case B_FACESEL:
+ if(G.obedit) {
+ error("Unable to perform function in EditMode");
+ G.vd->flag &= ~V3D_FACESELECT;
+ scrarea_queue_headredraw(curarea);
+ }
+ else if(G.obpose) {
+ error("Unable to perform function in PoseMode");
+ G.vd->flag &= ~V3D_FACESELECT;
+ scrarea_queue_headredraw(curarea);
+ }
+ else set_faceselect();
+ break;
+
+ case B_VIEWBUT:
+
+ if(G.vd->viewbut==1) persptoetsen(PAD7);
+ else if(G.vd->viewbut==2) persptoetsen(PAD1);
+ else if(G.vd->viewbut==3) persptoetsen(PAD3);
+ break;
+
+ case B_PERSP:
+
+ if(G.vd->persp==2) persptoetsen(PAD0);
+ else {
+ G.vd->persp= 1-G.vd->persp;
+ persptoetsen(PAD5);
+ }
+
+ break;
+ case B_PROPTOOL:
+ allqueue(REDRAWHEADERS, 0);
+ break;
+ case B_VIEWRENDER:
+ if (curarea->spacetype==SPACE_VIEW3D) {
+ BIF_do_ogl_render(curarea->spacedata.first, G.qual!=0 );
+ }
+ break;
+ case B_STARTGAME:
+ if (select_area(SPACE_VIEW3D)) {
+ start_game();
+ }
+ break;
+ case B_VIEWZOOM:
+ viewmovetemp= 0;
+ viewmove(2);
+ scrarea_queue_headredraw(curarea);
+ break;
+ case B_VIEWTRANS:
+ viewmovetemp= 0;
+ viewmove(1);
+ scrarea_queue_headredraw(curarea);
+ break;
+
+ default:
+
+ if(event>=B_LAY && event<B_LAY+31) {
+ if(G.vd->lay!=0 && (G.qual & LR_SHIFTKEY)) {
+
+ /* wel actieve layer zoeken */
+
+ bit= event-B_LAY;
+ if( G.vd->lay & (1<<bit)) G.vd->layact= 1<<bit;
+ else {
+ if( (G.vd->lay & G.vd->layact) == 0) {
+ bit= 0;
+ while(bit<32) {
+ if(G.vd->lay & (1<<bit)) {
+ G.vd->layact= 1<<bit;
+ break;
+ }
+ bit++;
+ }
+ }
+ }
+ }
+ else {
+ bit= event-B_LAY;
+ G.vd->lay= 1<<bit;
+ G.vd->layact= G.vd->lay;
+ scrarea_queue_headredraw(curarea);
+ }
+ scrarea_queue_winredraw(curarea);
+ countall();
+
+ if(G.vd->scenelock) handle_view3d_lock();
+ allqueue(REDRAWOOPS, 0);
+ }
+ break;
+ }
+}
+
+void do_layer_buttons(short event)
+{
+ static int oldlay= 1;
+
+ if(G.vd==0) return;
+ if(G.vd->localview) return;
+
+ if(event==-1 && (G.qual & LR_CTRLKEY)) {
+ G.vd->scenelock= !G.vd->scenelock;
+ do_view3d_buttons(B_SCENELOCK);
+ } else if (event==-1) {
+ if(G.vd->lay== (2<<20)-1) {
+ if(G.qual & LR_SHIFTKEY) G.vd->lay= oldlay;
+ }
+ else {
+ oldlay= G.vd->lay;
+ G.vd->lay= (2<<20)-1;
+ }
+
+ if(G.vd->scenelock) handle_view3d_lock();
+ scrarea_queue_winredraw(curarea);
+ }
+ else {
+ if(G.qual & LR_ALTKEY) {
+ if(event<11) event+= 10;
+ }
+ if(G.qual & LR_SHIFTKEY) {
+ if(G.vd->lay & (1<<event)) G.vd->lay -= (1<<event);
+ else G.vd->lay += (1<<event);
+ }
+ do_view3d_buttons(event+B_LAY);
+ }
+ /* redraw lijkt dubbelop: wordt in queue netjes afgehandeld */
+ scrarea_queue_headredraw(curarea);
+
+ if(curarea->spacetype==SPACE_OOPS) allqueue(REDRAWVIEW3D, 1); /* 1==ook headwin */
+
+}
+
+void do_nla_buttons(unsigned short event)
+{
+ View2D *v2d;
+
+ switch(event){
+ case B_NLAHOME:
+ // Find X extents
+ v2d= &(G.snla->v2d);
+
+ v2d->cur.xmin = G.scene->r.sfra;
+ v2d->cur.ymin=-SCROLLB;
+
+// if (!G.saction->action){
+ v2d->cur.xmax=G.scene->r.efra;
+// }
+// else
+// {
+// v2d->cur.xmax=calc_action_length(G.saction->action)+1;
+// }
+
+ test_view2d(G.v2d, curarea->winx, curarea->winy);
+ addqueue (curarea->win, REDRAW, 1);
+ break;
+ }
+}
+
+void nla_buttons(void)
+{
+ SpaceNla *snla;
+ short xco;
+ char naam[20];
+ uiBlock *block;
+
+ snla= curarea->spacedata.first;
+
+ sprintf(naam, "header %d", curarea->headwin);
+ block= uiNewBlock(&curarea->uiblocks, naam, UI_EMBOSSX, UI_HELV, curarea->headwin);
+ uiBlockSetCol(block, BUTCHOKE);
+
+ curarea->butspacetype= SPACE_NLA;
+ uiDefIconButC(block, ICONROW,B_NEWSPACE, ICON_VIEW3D, 6,0,XIC,YIC, &(curarea->butspacetype), 1.0, SPACEICONMAX, 0, 0, "Current window type ");
+
+ /* FULL WINDOW */
+ xco= 25;
+ if(curarea->full) uiDefIconBut(block, BUT,B_FULL, ICON_SPLITSCREEN, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Restore smaller windows (CTRL+Up arrow)");
+ else uiDefIconBut(block, BUT,B_FULL, ICON_FULLSCREEN, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Make fullscreen window (CTRL+Down arrow)");
+
+ /* HOME */
+ uiDefIconBut(block, BUT, B_NLAHOME, ICON_HOME, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Home (HOMEKEY)");
+ xco+= XIC;
+
+ /* IMAGE */
+// uiDefIconButS(block, TOG, B_REDR, ICON_IMAGE_COL, xco+=XIC,0,XIC,YIC, &sseq->mainb, 0, 0, 0, 0, "Toggles image display");
+
+ /* ZOOM en BORDER */
+// xco+= XIC;
+// uiDefIconButI(block, TOG, B_VIEW2DZOOM, ICON_VIEWZOOM, xco+=XIC,0,XIC,YIC, &viewmovetemp, 0, 0, 0, 0, "Zoom view (CTRL+MiddleMouse)");
+// uiDefIconBut(block, BUT, B_NLABORDER, ICON_BORDERMOVE, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Translate view (MiddleMouse)");
+
+ /* draw LOCK */
+ xco+= XIC/2;
+ uiDefIconButI(block, ICONTOG, 1, ICON_UNLOCKED, xco+=XIC,0,XIC,YIC, &(G.snla->lock), 0, 0, 0, 0, "Lock redraw of other windows while editing");
+
+ uiDrawBlock(block);}
+
+void action_buttons(void)
+{
+ uiBlock *block;
+ short xco;
+ char naam[256];
+ Object *ob;
+ ID *from;
+
+ if (!G.saction)
+ return;
+
+ // copy from drawactionspace....
+ if (!G.saction->pin) {
+ if (OBACT)
+ G.saction->action = OBACT->action;
+ else
+ G.saction->action=NULL;
+ }
+
+ sprintf(naam, "header %d", curarea->headwin);
+ block= uiNewBlock(&curarea->uiblocks, naam, UI_EMBOSSX, UI_HELV, curarea->headwin);
+ uiBlockSetCol(block, BUTPINK);
+
+ curarea->butspacetype= SPACE_ACTION;
+ uiDefIconButC(block, ICONROW,B_NEWSPACE, ICON_VIEW3D, 6,0,XIC,YIC, &(curarea->butspacetype), 1.0, SPACEICONMAX, 0, 0, "Current window type");
+
+ /* FULL WINDOW */
+ xco= 25;
+ if(curarea->full) uiDefIconBut(block, BUT,B_FULL, ICON_SPLITSCREEN, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Restore smaller windows (CTRL+Up arrow)");
+ else uiDefIconBut(block, BUT,B_FULL, ICON_FULLSCREEN, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Make fullscreen window (CTRL+Down arrow)");
+ uiDefIconBut(block, BUT, B_ACTHOME, ICON_HOME, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Home (HOMEKEY)");
+
+
+ /* NAME ETC */
+ ob=OBACT;
+ from = (ID*) ob;
+
+ xco= std_libbuttons(block, xco+1.5*XIC, B_ACTPIN, &G.saction->pin, B_ACTIONBROWSE, (ID*)G.saction->action, from, &(G.saction->actnr), B_ACTALONE, B_ACTLOCAL, B_ACTIONDELETE, 0);
+
+#ifdef __NLA_BAKE
+ /* Draw action baker */
+ uiDefBut(block, BUT, B_ACTBAKE, "Bake", xco+=XIC, 0, 64, YIC, 0, 0, 0, 0, 0, "Generate an action with the constraint effects converted into ipo keys");
+ xco+=64;
+#endif
+ uiClearButLock();
+
+ /* draw LOCK */
+ xco+= XIC/2;
+ uiDefIconButS(block, ICONTOG, 1, ICON_UNLOCKED, xco+=XIC,0,XIC,YIC, &(G.saction->lock), 0, 0, 0, 0, "Lock redraw of other windows while editing");
+
+
+ /* always as last */
+ curarea->headbutlen= xco+2*XIC;
+
+ uiDrawBlock(block);
+}
+
+void view3d_buttons(void)
+{
+ uiBlock *block;
+ int a;
+ short xco;
+ char naam[20];
+
+ sprintf(naam, "header %d", curarea->headwin);
+ block= uiNewBlock(&curarea->uiblocks, naam, UI_EMBOSSX, UI_HELV, curarea->headwin);
+ uiBlockSetCol(block, BUTBLUE);
+
+ curarea->butspacetype= SPACE_VIEW3D;
+ uiDefIconButC(block, ICONROW,B_NEWSPACE, ICON_VIEW3D, 6,0,XIC,YIC, &(curarea->butspacetype), 1.0, SPACEICONMAX, 0, 0, "Current window type ");
+
+
+ /* FULL WINDOW */
+ xco= 25;
+ if(curarea->full) uiDefIconBut(block, BUT,B_FULL, ICON_SPLITSCREEN, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Restore smaller windows (CTRL+Up arrow)");
+ else uiDefIconBut(block, BUT,B_FULL, ICON_FULLSCREEN, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Make fullscreen window (CTRL+Down arrow)");
+
+ /* HOME */
+ uiDefIconBut(block, BUT, B_HOME, ICON_HOME, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Home (HOMEKEY)");
+
+ xco+= XIC+8;
+ if(G.vd->localview==0) {
+ /* LAYERS */
+ for(a=0; a<10; a++) {
+ uiDefButI(block, TOG|BIT|(a+10), B_LAY+10+a, "",(short)(xco+a*(XIC/2)), 0, XIC/2, (YIC)/2, &(G.vd->lay), 0, 0, 0, 0, "Layers");
+ uiDefButI(block, TOG|BIT|a, B_LAY+a, "", (short)(xco+a*(XIC/2)), (short)(YIC/2),(short)(XIC/2),(short)(YIC/2), &(G.vd->lay), 0, 0, 0, 0, "Layers");
+ if(a==4) xco+= 5;
+ }
+ xco+= (a-2)*(XIC/2)+5;
+
+ /* LOCK */
+ uiDefIconButS(block, ICONTOG, B_SCENELOCK, ICON_UNLOCKED, xco+=XIC,0,XIC,YIC, &(G.vd->scenelock), 0, 0, 0, 0, "Lock layers and used Camera to Scene");
+ xco+= XIC;
+
+ }
+ else xco+= (10+2)*(XIC/2)+10;
+
+ /* LOCALVIEW */
+ uiDefIconButS(block, ICONROW, B_LOCALVIEW, ICON_LOCALVIEW, xco+=XIC,0,XIC,YIC, &(G.vd->localview), 0.0, 2.0, 0, 0, "Local View (NumPad /)");
+
+ /* PERSP */
+ xco+= XIC/2;
+ uiDefIconButS(block, ICONROW, B_PERSP, ICON_ORTHO, xco+=XIC,0,XIC,YIC, &(G.vd->persp), 0.0, 2.0, 0, 0, "Perspective mode (NumPad 5, Numpad 0)");
+
+ xco+= XIC/2;
+ /* AANZICHT */
+
+ if(G.vd->view==7) G.vd->viewbut= 1;
+ else if(G.vd->view==1) G.vd->viewbut= 2;
+ else if(G.vd->view==3) G.vd->viewbut= 3;
+ else G.vd->viewbut= 0;
+
+ uiDefIconButS(block, ICONROW, B_VIEWBUT, ICON_VIEW_AXIS_NONE, xco+=XIC,0,XIC,YIC, &G.vd->viewbut, 0.0, 3.0, 0, 0, "Top/Front or Side views (Numpad 7, 1, 3)");
+
+ /* DRAWTYPE */
+ xco+= XIC/2;
+ uiDefIconButS(block, ICONROW, B_REDR, ICON_BBOX, xco+=XIC,0,XIC,YIC, &(G.vd->drawtype), 1.0, 5.0, 0, 0, "Drawtype: boundbox/wire/solid/shaded (ZKEY, SHIFT+Z)");
+
+ /* VIEWMOVE */
+ xco+= XIC/2;
+ uiDefIconButI(block, TOG, B_VIEWTRANS, ICON_VIEWMOVE, xco+=XIC,0,XIC,YIC, &viewmovetemp, 0, 0, 0, 0, "Translate view (SHIFT+MiddleMouse)");
+ uiDefIconButI(block, TOG, B_VIEWZOOM, ICON_VIEWZOOM, xco+=XIC,0,XIC,YIC, &viewmovetemp, 0, 0, 0, 0, "Zoom view (CTRL+MiddleMouse)");
+
+ /* around */
+ xco+= XIC/2;
+ uiDefIconButS(block, ROW, 1, ICON_ROTATE, xco+=XIC,0,XIC,YIC, &G.vd->around, 3.0, 0.0, 0, 0, "Rotation/Scaling around boundbox center (COMMAKEY)");
+ uiDefIconButS(block, ROW, 1, ICON_ROTATECENTER, xco+=XIC,0,XIC,YIC, &G.vd->around, 3.0, 3.0, 0, 0, "Rotation/Scaling around median point");
+ uiDefIconButS(block, ROW, 1, ICON_CURSOR, xco+=XIC,0,XIC,YIC, &G.vd->around, 3.0, 1.0, 0, 0, "Rotation/Scaling around cursor (DOTKEY)");
+ uiDefIconButS(block, ROW, 1, ICON_ROTATECOLLECTION, xco+=XIC,0,XIC,YIC, &G.vd->around, 3.0, 2.0, 0, 0, "Rotation/Scaling around individual centers");
+
+ /* mode */
+ G.vd->flag &= ~V3D_MODE;
+ if(G.obedit) G.vd->flag |= V3D_EDITMODE;
+ if(G.f & G_VERTEXPAINT) G.vd->flag |= V3D_VERTEXPAINT;
+ if(G.f & G_WEIGHTPAINT) G.vd->flag |= V3D_WEIGHTPAINT;
+#ifdef NAN_TPT
+ if (G.f & G_TEXTUREPAINT) G.vd->flag |= V3D_TEXTUREPAINT;
+#endif /* NAN_TPT */
+ if(G.f & G_FACESELECT) G.vd->flag |= V3D_FACESELECT;
+ if(G.obpose){
+ G.vd->flag |= V3D_POSEMODE;
+ }
+
+ xco+= XIC/2;
+ /* If there is a posable object hilighted & selected, display this button */
+ if (OBACT){
+ if (OBACT->type==OB_ARMATURE){
+ uiDefIconButS(block, ICONTOG|BIT|7, B_POSEMODE, ICON_POSE_DEHLT, xco+=XIC,0,XIC,YIC, &G.vd->flag, 0, 0, 0, 0, "PoseMode (CTRL+TAB)");
+ }
+ }
+ uiDefIconButS(block, ICONTOG|BIT|4, B_EDITMODE, ICON_EDITMODE_DEHLT, xco+=XIC,0,XIC,YIC, &G.vd->flag, 0, 0, 0, 0, "EditMode (TAB)");
+ if (!G.obpose && !G.obedit)
+ {
+ xco+= XIC/2;
+ /* Only if mesh is selected */
+ if (OBACT && OBACT->type == OB_MESH){
+ uiDefIconButS(block, ICONTOG|BIT|5, B_VPAINT, ICON_VPAINT_DEHLT, xco+=XIC,0,XIC,YIC, &G.vd->flag, 0, 0, 0, 0, "VertexPaint Mode (VKEY)");
+ /* Only if deformable mesh is selected */
+ if ((((Mesh*)(OBACT->data))->dvert))
+ uiDefIconButS(block, ICONTOG|BIT|9, B_WPAINT, ICON_WPAINT_DEHLT, xco+=XIC,0,XIC,YIC, &G.vd->flag, 0, 0, 0, 0, "WeightPaint Mode");
+#ifdef NAN_TPT
+ uiDefIconButS(block, ICONTOG|BIT|8, B_TEXTUREPAINT, ICON_TPAINT_DEHLT, xco+=XIC,0,XIC,YIC, &G.vd->flag, 0, 0, 0, 0, "TexturePaint Mode");
+#endif /* NAN_TPT */
+ uiDefIconButS(block, ICONTOG|BIT|6, B_FACESEL, ICON_FACESEL_DEHLT, xco+=XIC,0,XIC,YIC, &G.vd->flag, 0, 0, 0, 0, "FaceSelect Mode (FKEY)");
+ }
+ }
+ if (G.obpose){
+ /* Copy paste - WAS in action window */
+ xco+= XIC/2;
+ // xco-= XIC/2; // Used in action window
+ if(curarea->headertype==HEADERTOP) {
+ uiDefIconBut(block, BUT, B_ACTCOPY, ICON_COPYUP, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Copies the current pose to the buffer");
+ uiSetButLock(G.obpose->id.lib!=0, "Can't edit library data");
+ uiDefIconBut(block, BUT, B_ACTPASTE, ICON_PASTEUP, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Pastes the pose from the buffer");
+ uiDefIconBut(block, BUT, B_ACTPASTEFLIP, ICON_PASTEFLIPUP, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Pastes the flipped pose from the buffer");
+ }
+ else {
+ uiDefIconBut(block, BUT, B_ACTCOPY, ICON_COPYDOWN, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Copies the current pose to the buffer");
+ uiSetButLock(G.obpose->id.lib!=0, "Can't edit library data");
+ uiDefIconBut(block, BUT, B_ACTPASTE, ICON_PASTEDOWN, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Pastes the pose from the buffer");
+ uiDefIconBut(block, BUT, B_ACTPASTEFLIP, ICON_PASTEFLIPDOWN, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Pastes the flipped pose from the buffer");
+ }
+// xco+=XIC/2; // Used in action window
+ }
+ if(G.vd->bgpic) {
+ xco+= XIC/2;
+ uiDefIconButS(block, TOG|BIT|1, B_REDR, ICON_IMAGE_COL, xco+=XIC,0,XIC,YIC, &G.vd->flag, 0, 0, 0, 0, "Display Background picture");
+ }
+ if(G.obedit) {
+ extern int prop_mode;
+ xco+= XIC/2;
+ uiDefIconButI(block, ICONTOG|BIT|14, B_PROPTOOL, ICON_GRID, xco+=XIC,0,XIC,YIC, &G.f, 0, 0, 0, 0, "Proportional vertex editing (OKEY)");
+ if(G.f & G_PROPORTIONAL) {
+ uiDefIconButI(block, ROW, 0, ICON_SHARPCURVE, xco+=XIC,0,XIC,YIC, &prop_mode, 4.0, 0.0, 0, 0, "Sharp falloff (SHIFT+OKEY)");
+ uiDefIconButI(block, ROW, 0, ICON_SMOOTHCURVE, xco+=XIC,0,XIC,YIC, &prop_mode, 4.0, 1.0, 0, 0, "Smooth falloff (SHIFT+OKEY)");
+ }
+ }
+
+ xco+=XIC;
+ uiDefIconBut(block, BUT, B_VIEWRENDER, ICON_SCENE, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Render this view. (Hold SHIFT for Anim render)");
+ xco+=XIC;
+ uiDefIconBut(block, BUT, B_STARTGAME, ICON_GAME, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Start game (PKEY)");
+
+
+ /* Always do this last */
+ curarea->headbutlen= xco+2*XIC;
+
+ uiDrawBlock(block);
+}
+
+/* ********************** VIEW3D ****************************** */
+/* ********************** IPO ****************************** */
+
+void do_ipo_buttons(short event)
+{
+ EditIpo *ei;
+ View2D *v2d;
+ rcti rect;
+ float xmin, ymin, dx, dy;
+ int a, val, first;
+ short mval[2];
+
+ if(curarea->win==0) return;
+
+ switch(event) {
+ case B_IPOHOME:
+
+ /* boundbox */
+
+ v2d= &(G.sipo->v2d);
+ first= 1;
+
+ ei= G.sipo->editipo;
+ if(ei==0) return;
+ for(a=0; a<G.sipo->totipo; a++, ei++) {
+ if ISPOIN(ei, flag & IPO_VISIBLE, icu) {
+
+ boundbox_ipocurve(ei->icu);
+
+ if(first) {
+ v2d->tot= ei->icu->totrct;
+ first= 0;
+ }
+ else BLI_union_rctf(&(v2d->tot), &(ei->icu->totrct));
+ }
+ }
+
+ /* speciale home */
+ if(G.qual & LR_SHIFTKEY) {
+ v2d->tot.xmin= SFRA;
+ v2d->tot.xmax= EFRA;
+ }
+
+ /* beetje uitzoomen */
+ dx= 0.10*(v2d->tot.xmax-v2d->tot.xmin);
+ dy= 0.10*(v2d->tot.ymax-v2d->tot.ymin);
+
+ if(dx<v2d->min[0]) dx= v2d->min[0];
+ if(dy<v2d->min[1]) dy= v2d->min[1];
+
+ v2d->cur.xmin= v2d->tot.xmin- dx;
+ v2d->cur.xmax= v2d->tot.xmax+ dx;
+ v2d->cur.ymin= v2d->tot.ymin- dy;
+ v2d->cur.ymax= v2d->tot.ymax+ dy;
+
+ test_view2d(G.v2d, curarea->winx, curarea->winy);
+ scrarea_queue_winredraw(curarea);
+ break;
+ case B_IPOBORDER:
+ val= get_border(&rect, 2);
+ if(val) {
+ mval[0]= rect.xmin;
+ mval[1]= rect.ymin;
+ areamouseco_to_ipoco(G.v2d, mval, &xmin, &ymin);
+ mval[0]= rect.xmax;
+ mval[1]= rect.ymax;
+ areamouseco_to_ipoco(G.v2d, mval, &(G.v2d->cur.xmax), &(G.v2d->cur.ymax));
+ G.v2d->cur.xmin= xmin;
+ G.v2d->cur.ymin= ymin;
+
+ test_view2d(G.v2d, curarea->winx, curarea->winy);
+ scrarea_queue_winredraw(curarea);
+ }
+ break;
+
+ case B_IPOPIN:
+ allqueue (REDRAWIPO, 0);
+ break;
+
+ case B_IPOCOPY:
+ copy_editipo();
+ break;
+ case B_IPOPASTE:
+ paste_editipo();
+ break;
+ case B_IPOCONT:
+ set_exprap_ipo(IPO_HORIZ);
+ break;
+ case B_IPOEXTRAP:
+ set_exprap_ipo(IPO_DIR);
+ break;
+ case B_IPOCYCLIC:
+ set_exprap_ipo(IPO_CYCL);
+ break;
+ case B_IPOCYCLICX:
+ set_exprap_ipo(IPO_CYCLX);
+ break;
+ case B_IPOMAIN:
+ make_editipo();
+ scrarea_queue_winredraw(curarea);
+ scrarea_queue_headredraw(curarea);
+
+ break;
+ case B_IPOSHOWKEY:
+ /* waarde omkeren vanwege winqread */
+ G.sipo->showkey= 1-G.sipo->showkey;
+ winqreadipo(KKEY, 1, 0);
+ break;
+ case B_VIEW2DZOOM:
+ viewmovetemp= 0;
+ view2dzoom();
+ scrarea_queue_headredraw(curarea);
+ break;
+
+ }
+}
+
+void ipo_buttons(void)
+{
+ Object *ob;
+ ID *id, *from;
+ uiBlock *block;
+ short xco;
+ char naam[20];
+
+ sprintf(naam, "header %d", curarea->headwin);
+ block= uiNewBlock(&curarea->uiblocks, naam, UI_EMBOSSX, UI_HELV, curarea->headwin);
+ uiBlockSetCol(block, BUTSALMON);
+
+ curarea->butspacetype= SPACE_IPO;
+ uiDefIconButC(block, ICONROW,B_NEWSPACE, ICON_VIEW3D, 6,0,XIC,YIC, &(curarea->butspacetype), 1.0, SPACEICONMAX, 0, 0, "Current window type ");
+
+ test_editipo(); /* test of huidige editipo klopt, make_editipo zet de v2d->cur */
+
+ /* FULL WINDOW en HOME */
+ xco= 25;
+ if(curarea->full) uiDefIconBut(block, BUT,B_FULL, ICON_SPLITSCREEN, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Restore smaller windows (CTRL+Up arrow)");
+ else uiDefIconBut(block, BUT,B_FULL, ICON_FULLSCREEN, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Make fullscreen window (CTRL+Down arrow)");
+ uiDefIconBut(block, BUT, B_IPOHOME, ICON_HOME, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Home (HOMEKEY)");
+ uiDefIconButS(block, ICONTOG, B_IPOSHOWKEY, ICON_KEY_DEHLT, xco+=XIC,0,XIC,YIC, &G.sipo->showkey, 0, 0, 0, 0, "Toggles curve/key display (KKEY)");
+
+ /* mainmenu, only when data is there and no pin */
+ uiSetButLock(G.sipo->pin, "Can't change because of pinned data");
+
+ ob= OBACT;
+ xco+= XIC/2;
+ uiDefIconButS(block, ROW, B_IPOMAIN, ICON_OBJECT, xco+=XIC,0,XIC,YIC, &G.sipo->blocktype, 1.0, (float)ID_OB, 0, 0, "Display Object Ipos ");
+
+ if(ob && give_current_material(ob, ob->actcol)) {
+ uiDefIconButS(block, ROW, B_IPOMAIN, ICON_MATERIAL, xco+=XIC,0,XIC,YIC, &G.sipo->blocktype, 1.0, (float)ID_MA, 0, 0, "Display Material Ipos ");
+ if(G.sipo->blocktype==ID_MA) {
+ uiDefButS(block, NUM, B_IPOMAIN, "", xco+=XIC,0,XIC-4,YIC, &G.sipo->channel, 0.0, 7.0, 0, 0, "Channel Number of the active Material texture");
+ xco-= 4;
+ }
+ }
+ if(G.scene->world) {
+ uiDefIconButS(block, ROW, B_IPOMAIN, ICON_WORLD, xco+=XIC,0,XIC,YIC, &G.sipo->blocktype, 1.0, (float)ID_WO, 0, 0, "Display World Ipos");
+ if(G.sipo->blocktype==ID_WO) {
+ uiDefButS(block, NUM, B_IPOMAIN, "", xco+=XIC,0,XIC-4,YIC, &G.sipo->channel, 0.0, 7.0, 0, 0, "Channel Number of the active World texture");
+ xco-= 4;
+ }
+ }
+
+ if(ob && ob->type==OB_CURVE)
+ uiDefIconButS(block, ROW, B_IPOMAIN, ICON_ANIM, xco+=XIC,0,XIC,YIC, &G.sipo->blocktype, 1.0, (float)ID_CU, 0, 0, "Display Curve Ipos");
+
+ if(ob && ob->type==OB_CAMERA)
+ uiDefIconButS(block, ROW, B_IPOMAIN, ICON_CAMERA, xco+=XIC,0,XIC,YIC, &G.sipo->blocktype, 1.0, (float)ID_CA, 0, 0, "Display Camera Ipos");
+
+ if(ob && ob->type==OB_LAMP) {
+ uiDefIconButS(block, ROW, B_IPOMAIN, ICON_LAMP, xco+=XIC,0,XIC,YIC, &G.sipo->blocktype, 1.0, (float)ID_LA, 0, 0, "Display Lamp Ipos");
+ if(G.sipo->blocktype==ID_LA) {
+ uiDefButS(block, NUM, B_IPOMAIN, "", xco+=XIC,0,XIC-4,YIC, &G.sipo->channel, 0.0, 7.0, 0, 0, "Channel Number of the active Lamp texture");
+ xco-= 4;
+ }
+ }
+
+ if(ob) {
+ if ELEM4(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_LATTICE)
+ uiDefIconButS(block, ROW, B_IPOMAIN, ICON_EDIT, xco+=XIC,0,XIC,YIC, &G.sipo->blocktype, 1.0, (float)ID_KE, 0, 0, "Display VertexKeys Ipos");
+ if (ob->action)
+ uiDefIconButS(block, ROW, B_IPOMAIN, ICON_ACTION, xco+=XIC,0,XIC,YIC, &G.sipo->blocktype, 1.0, (float)ID_AC, 0, 0, "Display Action Ipos");
+#ifdef __CON_IPO
+ uiDefIconButS(block, ROW, B_IPOMAIN, ICON_CONSTRAINT, xco+=XIC,0,XIC,YIC, &G.sipo->blocktype, 1.0, (float)IPO_CO, 0, 0, "Display Constraint Ipos");
+#endif
+ }
+ uiDefIconButS(block, ROW, B_IPOMAIN, ICON_SEQUENCE, xco+=XIC,0,XIC,YIC, &G.sipo->blocktype, 1.0, (float)ID_SEQ, 0, 0, "Display Sequence Ipos");
+
+ if(G.buts && G.buts->mainb == BUTS_SOUND && G.buts->lockpoin)
+ uiDefIconButS(block, ROW, B_IPOMAIN, ICON_SOUND, xco+=XIC,0,XIC,YIC, &G.sipo->blocktype, 1.0, (float)ID_SO, 0, 0, "Display Sound Ipos");
+
+
+ uiClearButLock();
+
+ /* NAME ETC */
+ id= (ID *)get_ipo_to_edit(&from);
+
+ xco= std_libbuttons(block, (short)(xco+1.5*XIC), B_IPOPIN, &G.sipo->pin, B_IPOBROWSE, (ID*)G.sipo->ipo, from, &(G.sipo->menunr), B_IPOALONE, B_IPOLOCAL, B_IPODELETE, 0);
+
+ uiSetButLock(id && id->lib, "Can't edit library data");
+
+ /* COPY PASTE */
+ xco-= XIC/2;
+ if(curarea->headertype==HEADERTOP) {
+ uiDefIconBut(block, BUT, B_IPOCOPY, ICON_COPYUP, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Copies the selected curves to the buffer");
+ uiSetButLock(id && id->lib, "Can't edit library data");
+ uiDefIconBut(block, BUT, B_IPOPASTE, ICON_PASTEUP, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Pastes the curves from the buffer");
+ }
+ else {
+ uiDefIconBut(block, BUT, B_IPOCOPY, ICON_COPYDOWN, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Copies the selected curves to the buffer");
+ uiSetButLock(id && id->lib, "Can't edit library data");
+ uiDefIconBut(block, BUT, B_IPOPASTE, ICON_PASTEDOWN, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Pastes the curves from the buffer");
+ }
+ xco+=XIC/2;
+
+ /* EXTRAP */
+ uiDefIconBut(block, BUT, B_IPOCONT, ICON_CONSTANT, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Sets the extend mode to constant");
+ uiDefIconBut(block, BUT, B_IPOEXTRAP, ICON_LINEAR, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Sets the extend mode to extrapolation");
+ uiDefIconBut(block, BUT, B_IPOCYCLIC, ICON_CYCLICLINEAR, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Sets the extend mode to cyclic");
+ uiDefIconBut(block, BUT, B_IPOCYCLICX, ICON_CYCLIC, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Sets the extend mode to cyclic extrapolation");
+ xco+= XIC/2;
+
+ uiClearButLock();
+ /* ZOOM en BORDER */
+ uiDefIconButI(block, TOG, B_VIEW2DZOOM, ICON_VIEWZOOM, xco+=XIC,0,XIC,YIC, &viewmovetemp, 0, 0, 0, 0, "Zoom view (CTRL+MiddleMouse)");
+ uiDefIconBut(block, BUT, B_IPOBORDER, ICON_BORDERMOVE, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Translate view (MiddleMouse)");
+
+ /* draw LOCK */
+ uiDefIconButS(block, ICONTOG, 1, ICON_UNLOCKED, xco+=XIC,0,XIC,YIC, &(G.sipo->lock), 0, 0, 0, 0, "Lock redraw of other windows while editing");
+
+ /* altijd als laatste doen */
+ curarea->headbutlen= xco+2*XIC;
+
+ uiDrawBlock(block);
+}
+
+/* ********************** IPO ****************************** */
+/* ********************** BUTS ****************************** */
+
+Material matcopybuf;
+
+void clear_matcopybuf(void)
+{
+ memset(&matcopybuf, 0, sizeof(Material));
+}
+
+void free_matcopybuf(void)
+{
+ extern MTex mtexcopybuf; /* buttons.c */
+ int a;
+
+ for(a=0; a<8; a++) {
+ if(matcopybuf.mtex[a]) {
+ MEM_freeN(matcopybuf.mtex[a]);
+ matcopybuf.mtex[a]= 0;
+ }
+ }
+
+ default_mtex(&mtexcopybuf);
+}
+
+void do_buts_buttons(short event)
+{
+ static short matcopied=0;
+ MTex *mtex;
+ Material *ma;
+ ID id;
+ int a;
+
+ if(curarea->win==0) return;
+
+ switch(event) {
+ case B_BUTSHOME:
+ G.v2d->cur= G.v2d->tot;
+ test_view2d(G.v2d, curarea->winx, curarea->winy);
+ scrarea_queue_winredraw(curarea);
+ break;
+ case B_BUTSPREVIEW:
+ BIF_preview_changed(G.buts);
+ scrarea_queue_headredraw(curarea);
+ scrarea_queue_winredraw(curarea);
+ break;
+ case B_MATCOPY:
+ if(G.buts->lockpoin) {
+
+ if(matcopied) free_matcopybuf();
+
+ memcpy(&matcopybuf, G.buts->lockpoin, sizeof(Material));
+ for(a=0; a<8; a++) {
+ mtex= matcopybuf.mtex[a];
+ if(mtex) {
+ matcopybuf.mtex[a]= MEM_dupallocN(mtex);
+ }
+ }
+ matcopied= 1;
+ }
+ break;
+ case B_MATPASTE:
+ if(matcopied && G.buts->lockpoin) {
+ ma= G.buts->lockpoin;
+ /* vrijgeven huidige mat */
+ for(a=0; a<8; a++) {
+ mtex= ma->mtex[a];
+ if(mtex && mtex->tex) mtex->tex->id.us--;
+ if(mtex) MEM_freeN(mtex);
+ }
+
+ id= (ma->id);
+ memcpy(G.buts->lockpoin, &matcopybuf, sizeof(Material));
+ (ma->id)= id;
+
+ for(a=0; a<8; a++) {
+ mtex= ma->mtex[a];
+ if(mtex) {
+ ma->mtex[a]= MEM_dupallocN(mtex);
+ if(mtex->tex) id_us_plus((ID *)mtex->tex);
+ }
+ }
+ BIF_preview_changed(G.buts);
+ scrarea_queue_winredraw(curarea);
+ }
+ break;
+ case B_MESHTYPE:
+ allqueue(REDRAWBUTSEDIT, 0);
+ allqueue(REDRAWVIEW3D, 0);
+ break;
+ }
+}
+
+void buttons_active_id(ID **id, ID **idfrom)
+{
+ Object *ob= OBACT;
+ Material *ma;
+ ID * search;
+
+ *id= NULL;
+ *idfrom= (ID *)ob;
+
+ if(G.buts->mainb==BUTS_LAMP) {
+ if(ob && ob->type==OB_LAMP) {
+ *id= ob->data;
+ }
+ }
+ else if(G.buts->mainb==BUTS_MAT) {
+ if(ob && (ob->type<OB_LAMP) && ob->type) {
+ *id= (ID *)give_current_material(ob, ob->actcol);
+ *idfrom= material_from(ob, ob->actcol);
+ }
+ }
+ else if(G.buts->mainb==BUTS_TEX) {
+ MTex *mtex;
+
+ if(G.buts->mainbo != G.buts->mainb) {
+ if(G.buts->mainbo==BUTS_LAMP) G.buts->texfrom= 2;
+ else if(G.buts->mainbo==BUTS_WORLD) G.buts->texfrom= 1;
+ else if(G.buts->mainbo==BUTS_MAT) G.buts->texfrom= 0;
+ }
+
+ if(G.buts->texfrom==0) {
+ if(ob && ob->type<OB_LAMP && ob->type) {
+ ma= give_current_material(ob, ob->actcol);
+ *idfrom= (ID *)ma;
+ if(ma) {
+ mtex= ma->mtex[ ma->texact ];
+ if(mtex) *id= (ID *)mtex->tex;
+ }
+ }
+ }
+ else if(G.buts->texfrom==1) {
+ World *wrld= G.scene->world;
+ *idfrom= (ID *)wrld;
+ if(wrld) {
+ mtex= wrld->mtex[ wrld->texact];
+ if(mtex) *id= (ID *)mtex->tex;
+ }
+ }
+ else if(G.buts->texfrom==2) {
+ Lamp *la;
+ if(ob && ob->type==OB_LAMP) {
+ la= ob->data;
+ *idfrom= (ID *)la;
+ mtex= la->mtex[ la->texact];
+ if(mtex) *id= (ID *)mtex->tex;
+ }
+ }
+ }
+ else if ELEM3(G.buts->mainb, BUTS_ANIM, BUTS_GAME, BUTS_CONSTRAINT) {
+ if(ob) {
+ *idfrom= (ID *)G.scene;
+ *id= (ID *)ob;
+ }
+ }
+ else if(G.buts->mainb==BUTS_WORLD) {
+ *id= (ID *)G.scene->world;
+ *idfrom= (ID *)G.scene;
+ }
+ else if(G.buts->mainb==BUTS_RENDER) {
+ *id= (ID *)G.scene;
+
+ }
+ else if(G.buts->mainb==BUTS_EDIT) {
+ if(ob && ob->data) {
+ *id= ob->data;
+ }
+ }
+ else if (G.buts->mainb == BUTS_SOUND) {
+ // printf("lockp: %d\n", G.buts->lockpoin);
+
+ if (G.buts->lockpoin) {
+ search = G.main->sound.first;
+ while (search) {
+ if (search == G.buts->lockpoin) {
+ break;
+ }
+ search = search->next;
+ }
+ if (search == NULL) {
+ *id = G.main->sound.first;
+ } else {
+ *id = search;
+ }
+ } else {
+ *id = G.main->sound.first;
+ }
+ // printf("id: %d\n\n", *id);
+ }
+}
+
+static void validate_bonebutton(void *bonev, void *data2_unused){
+ Bone *bone= bonev;
+ bArmature *arm;
+
+ arm = get_armature(G.obpose);
+ unique_bone_name(bone, arm);
+}
+
+
+static int bonename_exists(Bone *orig, char *name, ListBase *list)
+{
+ Bone *curbone;
+
+ for (curbone=list->first; curbone; curbone=curbone->next){
+ /* Check this bone */
+ if (orig!=curbone){
+ if (!strcmp(curbone->name, name))
+ return 1;
+ }
+
+ /* Check Children */
+ if (bonename_exists(orig, name, &curbone->childbase))
+ return 1;
+ }
+
+ return 0;
+
+}
+
+static void unique_bone_name (Bone *bone, bArmature *arm)
+{
+ char tempname[64];
+ char oldname[64];
+ int number;
+ char *dot;
+
+ if (!arm)
+ return;
+
+ strcpy(oldname, bone->name);
+
+ /* See if we even need to do this */
+ if (!bonename_exists(bone, bone->name, &arm->bonebase))
+ return;
+
+ /* Strip off the suffix */
+ dot=strchr(bone->name, '.');
+ if (dot)
+ *dot=0;
+
+ for (number = 1; number <=999; number++){
+ sprintf (tempname, "%s.%03d", bone->name, number);
+
+ if (!bonename_exists(bone, tempname, &arm->bonebase)){
+ strcpy (bone->name, tempname);
+ return;
+ }
+ }
+}
+
+void buts_buttons(void)
+{
+ ID *id, *idfrom;
+ Object *ob;
+ uiBlock *block;
+ uiBut *but;
+ short xco;
+ int alone, local, browse;
+ char naam[20];
+ short type;
+ void *data=NULL;
+ char str[256];
+
+ sprintf(naam, "header %d", curarea->headwin);
+ block= uiNewBlock(&curarea->uiblocks, naam, UI_EMBOSSX, UI_HELV, curarea->headwin);
+ uiBlockSetCol(block, BUTGREY);
+
+ curarea->butspacetype= SPACE_BUTS;
+ uiDefIconButC(block, ICONROW,B_NEWSPACE, ICON_VIEW3D, 6,0,XIC,YIC, &(curarea->butspacetype), 1.0, SPACEICONMAX, 0, 0, "Current window type ");
+
+ /* FULL WINDOW */
+ xco= 25;
+ if(curarea->full) uiDefIconBut(block, BUT,B_FULL, ICON_SPLITSCREEN, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Restore smaller windows (CTRL+Up arrow)");
+ else uiDefIconBut(block, BUT,B_FULL, ICON_FULLSCREEN, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Make fullscreen window (CTRL+Down arrow)");
+
+ /* HOME */
+ uiDefIconBut(block, BUT, B_BUTSHOME, ICON_HOME, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Home (HOMEKEY)");
+
+ /* keuzemenu */
+ xco+= 2*XIC;
+ uiDefIconButS(block, ROW, B_REDR, ICON_EYE, xco+=XIC, 0, 30, YIC, &(G.buts->mainb), 1.0, (float)BUTS_VIEW, 0, 0, "View buttons");
+ uiDefIconButS(block, ROW, B_BUTSPREVIEW, ICON_LAMP, xco+=30, 0, 30, YIC, &(G.buts->mainb), 1.0, (float)BUTS_LAMP, 0, 0, "Lamp buttons (F4)");
+ uiDefIconButS(block, ROW, B_BUTSPREVIEW, ICON_MATERIAL, xco+=30, 0, 30, YIC, &(G.buts->mainb), 1.0, (float)BUTS_MAT, 0, 0, "Material buttons (F5)");
+ uiDefIconButS(block, ROW, B_BUTSPREVIEW, ICON_TEXTURE, xco+=30, 0, 30, YIC, &(G.buts->mainb), 1.0, (float)BUTS_TEX, 0, 0, "Texture buttons (F6)");
+ uiDefIconButS(block, ROW, B_REDR, ICON_ANIM, xco+=30, 0, 30, YIC, &(G.buts->mainb), 1.0, (float)BUTS_ANIM, 0, 0, "Animation buttons (F7)");
+ uiDefIconButS(block, ROW, B_REDR, ICON_GAME, xco+=30, 0, 30, YIC, &(G.buts->mainb), 1.0, (float)BUTS_GAME, 0, 0, "Realtime buttons (F8)");
+ uiDefIconButS(block, ROW, B_REDR, ICON_EDIT, xco+=30, 0, 30, YIC, &(G.buts->mainb), 1.0, (float)BUTS_EDIT, 0, 0, "Edit buttons (F9)");
+ uiDefIconButS(block, ROW, B_REDR, ICON_CONSTRAINT,xco+=30, 0, 30, YIC, &(G.buts->mainb), 1.0, (float)BUTS_CONSTRAINT, 0, 0, "Constraint buttons");
+ uiDefIconButS(block, ROW, B_REDR, ICON_SPEAKER,xco+=30, 0, 30, YIC, &(G.buts->mainb), 1.0, (float)BUTS_SOUND, 0, 0, "Sound buttons");
+ uiDefIconButS(block, ROW, B_BUTSPREVIEW, ICON_WORLD, xco+=30, 0, 30, YIC, &(G.buts->mainb), 1.0, (float)BUTS_WORLD, 0, 0, "World buttons");
+ uiDefIconButS(block, ROW, B_REDR, ICON_PAINT,xco+=30, 0, 30, YIC, &(G.buts->mainb), 1.0, (float)BUTS_FPAINT, 0, 0, "Paint buttons");
+ uiDefIconButS(block, ROW, B_REDR, ICON_RADIO,xco+=30, 0, 30, YIC, &(G.buts->mainb), 1.0, (float)BUTS_RADIO, 0, 0, "Radiosity buttons");
+ uiDefIconButS(block, ROW, B_REDR, ICON_SCRIPT,xco+=30, 0, 30, YIC, &(G.buts->mainb), 1.0, (float)BUTS_SCRIPT, 0, 0, "Script buttons");
+ uiDefIconButS(block, ROW, B_REDR, ICON_SCENE, xco+=30, 0, 50, YIC, &(G.buts->mainb), 1.0, (float)BUTS_RENDER, 0, 0, "Display buttons (F10)");
+ xco+= 80;
+
+ ob= OBACT;
+
+ buttons_active_id(&id, &idfrom);
+
+ G.buts->lockpoin= id;
+
+ if(G.buts->mainb==BUTS_LAMP) {
+ if(id) {
+ xco= std_libbuttons(block, xco, 0, NULL, B_LAMPBROWSE, id, (ID *)ob, &(G.buts->menunr), B_LAMPALONE, B_LAMPLOCAL, 0, 0);
+ }
+ }
+ else if(G.buts->mainb==BUTS_MAT) {
+ if(ob && (ob->type<OB_LAMP) && ob->type) {
+ xco= std_libbuttons(block, xco, 0, NULL, B_MATBROWSE, id, idfrom, &(G.buts->menunr), B_MATALONE, B_MATLOCAL, B_MATDELETE, B_AUTOMATNAME);
+ }
+
+ /* COPY PASTE */
+ if(curarea->headertype==HEADERTOP) {
+ uiDefIconBut(block, BUT, B_MATCOPY, ICON_COPYUP, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Copy Material to the buffer");
+ uiSetButLock(id && id->lib, "Can't edit library data");
+ uiDefIconBut(block, BUT, B_MATPASTE, ICON_PASTEUP, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Paste Material from the buffer");
+ }
+ else {
+ uiDefIconBut(block, BUT, B_MATCOPY, ICON_COPYDOWN, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Copy Material to the buffer");
+ uiSetButLock(id && id->lib, "Can't edit library data");
+ uiDefIconBut(block, BUT, B_MATPASTE, ICON_PASTEDOWN, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Paste Material from the buffer");
+ }
+ xco+=XIC;
+
+ }
+ else if(G.buts->mainb==BUTS_TEX) {
+ if(G.buts->texfrom==0) {
+ if(idfrom) {
+ xco= std_libbuttons(block, xco, 0, NULL, B_TEXBROWSE, id, idfrom, &(G.buts->texnr), B_TEXALONE, B_TEXLOCAL, B_TEXDELETE, B_AUTOTEXNAME);
+ }
+ }
+ else if(G.buts->texfrom==1) {
+ if(idfrom) {
+ xco= std_libbuttons(block, xco, 0, NULL, B_WTEXBROWSE, id, idfrom, &(G.buts->texnr), B_TEXALONE, B_TEXLOCAL, B_TEXDELETE, B_AUTOTEXNAME);
+ }
+ }
+ else if(G.buts->texfrom==2) {
+ if(idfrom) {
+ xco= std_libbuttons(block, xco, 0, NULL, B_LTEXBROWSE, id, idfrom, &(G.buts->texnr), B_TEXALONE, B_TEXLOCAL, B_TEXDELETE, B_AUTOTEXNAME);
+ }
+ }
+ }
+ else if(G.buts->mainb==BUTS_ANIM) {
+ if(id) {
+ xco= std_libbuttons(block, xco, 0, NULL, 0, id, idfrom, &(G.buts->menunr), B_OBALONE, B_OBLOCAL, 0, 0);
+
+ if(G.scene->group) {
+ Group *group= G.scene->group;
+ but= uiDefBut(block, TEX, B_IDNAME, "GR:", xco, 0, 135, YIC, group->id.name+2, 0.0, 19.0, 0, 0, "Active Group name");
+ uiButSetFunc(but, test_idbutton_cb, group->id.name, NULL);
+ xco+= 135;
+ }
+ }
+ }
+ else if(G.buts->mainb==BUTS_GAME) {
+ if(id) {
+ xco= std_libbuttons(block, xco, 0, NULL, 0, id, idfrom, &(G.buts->menunr), B_OBALONE, B_OBLOCAL, 0, 0);
+ }
+ }
+ else if(G.buts->mainb==BUTS_WORLD) {
+ xco= std_libbuttons(block, xco, 0, NULL, B_WORLDBROWSE, id, idfrom, &(G.buts->menunr), B_WORLDALONE, B_WORLDLOCAL, B_WORLDDELETE, 0);
+ }
+ else if (G.buts->mainb==BUTS_SOUND) {
+ xco= std_libbuttons(block, xco, 0, NULL, B_SOUNDBROWSE2, id, idfrom, &(G.buts->texnr), 1, 0, 0, 0);
+ }
+
+ else if(G.buts->mainb==BUTS_RENDER) {
+ xco= std_libbuttons(block, xco, 0, NULL, B_INFOSCE, (ID *)G.scene, 0, &(G.curscreen->scenenr), 1, 1, B_INFODELSCE, 0);
+ }
+ else if(G.buts->mainb==BUTS_EDIT) {
+ if(id) {
+
+ alone= 0;
+ local= 0;
+ browse= B_EDITBROWSE;
+ xco+= 10;
+
+ if(ob->type==OB_MESH) {
+ browse= B_MESHBROWSE;
+ alone= B_MESHALONE;
+ local= B_MESHLOCAL;
+ uiSetButLock(G.obedit!=0, "Unable to perform function in EditMode");
+ }
+ else if(ob->type==OB_MBALL) {
+ alone= B_MBALLALONE;
+ local= B_MBALLLOCAL;
+ }
+ else if ELEM3(ob->type, OB_CURVE, OB_FONT, OB_SURF) {
+ alone= B_CURVEALONE;
+ local= B_CURVELOCAL;
+ }
+ else if(ob->type==OB_CAMERA) {
+ alone= B_CAMERAALONE;
+ local= B_CAMERALOCAL;
+ }
+ else if(ob->type==OB_LAMP) {
+ alone= B_LAMPALONE;
+ local= B_LAMPLOCAL;
+ }
+ else if (ob->type==OB_ARMATURE){
+ alone = B_ARMALONE;
+ local = B_ARMLOCAL;
+ }
+ else if(ob->type==OB_LATTICE) {
+ alone= B_LATTALONE;
+ local= B_LATTLOCAL;
+ }
+
+ xco= std_libbuttons(block, xco, 0, NULL, browse, id, idfrom, &(G.buts->menunr), alone, local, 0, 0);
+
+ xco+= XIC;
+ }
+ if(ob) {
+ but= uiDefBut(block, TEX, B_IDNAME, "OB:", xco, 0, 135, YIC, ob->id.name+2, 0.0, 19.0, 0, 0, "Active Object name");
+ uiButSetFunc(but, test_idbutton_cb, ob->id.name, NULL);
+ xco+= 135;
+ }
+ }
+ else if(G.buts->mainb==BUTS_CONSTRAINT){
+ if(id) {
+
+
+ xco= std_libbuttons(block, xco, 0, NULL, 0, id, idfrom, &(G.buts->menunr), B_OBALONE, B_OBLOCAL, 0, 0);
+
+ get_constraint_client(NULL, &type, &data);
+ if (data && type==TARGET_BONE){
+ sprintf(str, "BO:%s", ((Bone*)data)->name);
+#if 0
+ /* XXXXX, not idname... but check redrawing */
+ but= uiDefBut(block, TEX, 1, "BO:", xco, 0, 135, YIC, ((Bone*)data)->name, 0.0, 19.0, 0, 0, "Active Bone name");
+ uiButSetFunc(but, validate_bonebutton, data, NULL);
+#else
+ but= uiDefBut(block, LABEL, 1, str, xco, 0, 135, YIC, ((Bone*)data)->name, 0.0, 19.0, 0, 0, "Active Bone name");
+#endif
+ xco+= 135;
+ }
+ }
+ }
+ else if(G.buts->mainb==BUTS_SCRIPT) {
+ if(ob)
+ uiDefIconButS(block, ROW, B_REDR, ICON_OBJECT, xco,0,XIC,YIC, &G.buts->scriptblock, 2.0, (float)ID_OB, 0, 0, "Display Object script links");
+
+ if(ob && give_current_material(ob, ob->actcol))
+ uiDefIconButS(block, ROW, B_REDR, ICON_MATERIAL, xco+=XIC,0,XIC,YIC, &G.buts->scriptblock, 2.0, (float)ID_MA, 0, 0, "Display Material script links ");
+
+ if(G.scene->world)
+ uiDefIconButS(block, ROW, B_REDR, ICON_WORLD, xco+=XIC,0,XIC,YIC, &G.buts->scriptblock, 2.0, (float)ID_WO, 0, 0, "Display World script links");
+
+ if(ob && ob->type==OB_CAMERA)
+ uiDefIconButS(block, ROW, B_REDR, ICON_CAMERA, xco+=XIC,0,XIC,YIC, &G.buts->scriptblock, 2.0, (float)ID_CA, 0, 0, "Display Camera script links");
+
+ if(ob && ob->type==OB_LAMP)
+ uiDefIconButS(block, ROW, B_REDR, ICON_LAMP, xco+=XIC,0,XIC,YIC, &G.buts->scriptblock, 2.0, (float)ID_LA, 0, 0, "Display Lamp script links");
+
+ xco+= 20;
+ }
+
+ uiDefButS(block, NUM, B_NEWFRAME, "", (short)(xco+20),0,60,YIC, &(G.scene->r.cfra), 1.0, 18000.0, 0, 0, "Current Frame");
+ xco+= 80;
+
+ G.buts->mainbo= G.buts->mainb;
+
+ /* altijd als laatste doen */
+ uiDrawBlock(block);
+ curarea->headbutlen= xco;
+}
+
+/* ********************** BUTS ****************************** */
+/* ******************** FILE ********************** */
+
+void do_file_buttons(short event)
+{
+ SpaceFile *sfile;
+
+ if(curarea->win==0) return;
+ sfile= curarea->spacedata.first;
+
+ switch(event) {
+ case B_SORTFILELIST:
+ sort_filelist(sfile);
+ scrarea_queue_winredraw(curarea);
+ break;
+ case B_RELOADDIR:
+ freefilelist(sfile);
+ scrarea_queue_winredraw(curarea);
+ break;
+ }
+
+}
+
+void file_buttons(void)
+{
+ SpaceFile *sfile;
+ uiBlock *block;
+ float df, totlen, sellen;
+ short xco;
+ int totfile, selfile;
+ char naam[256];
+
+ sfile= curarea->spacedata.first;
+
+ sprintf(naam, "header %d", curarea->headwin);
+ block= uiNewBlock(&curarea->uiblocks, naam, UI_EMBOSSX, UI_HELV, curarea->headwin);
+ uiBlockSetCol(block, BUTGREY);
+
+ curarea->butspacetype= SPACE_FILE;
+ uiDefIconButC(block, ICONROW,B_NEWSPACE, ICON_VIEW3D, 6,0,XIC,YIC, &(curarea->butspacetype), 1.0, SPACEICONMAX, 0, 0, "Current window type");
+
+ /* FULL WINDOW */
+ xco= 25;
+ if(curarea->full) uiDefIconBut(block, BUT,B_FULL, ICON_SPLITSCREEN, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Restore smaller windows (CTRL+Up arrow)");
+ else uiDefIconBut(block, BUT,B_FULL, ICON_FULLSCREEN, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Make fullscreen window (CTRL+Down arrow)");
+
+ /* SORT TYPE */
+ xco+=XIC;
+ uiDefIconButS(block, ROW, B_SORTFILELIST, ICON_SORTALPHA, xco+=XIC,0,XIC,YIC, &sfile->sort, 1.0, 0.0, 0, 0, "Sort files alphabetically");
+ uiDefIconButS(block, ROW, B_SORTFILELIST, ICON_SORTTIME, xco+=XIC,0,XIC,YIC, &sfile->sort, 1.0, 1.0, 0, 0, "Sort files by time");
+ uiDefIconButS(block, ROW, B_SORTFILELIST, ICON_SORTSIZE, xco+=XIC,0,XIC,YIC, &sfile->sort, 1.0, 2.0, 0, 0, "Sort files by size");
+
+ cpack(0x0);
+ glRasterPos2i(xco+=XIC+10, 5);
+ BMF_DrawString(uiBlockGetCurFont(block), sfile->title);
+
+ xco+= BMF_GetStringWidth(G.font, sfile->title);
+
+ uiDefIconButS(block, ICONTOG|BIT|0, B_SORTFILELIST, ICON_LONGDISPLAY,xco+=XIC,0,XIC,YIC, &sfile->flag, 0, 0, 0, 0, "Toggle long info");
+ uiDefIconButS(block, TOG|BIT|3, B_RELOADDIR, ICON_GHOST,xco+=XIC,0,XIC,YIC, &sfile->flag, 0, 0, 0, 0, "Hide dot files");
+
+ xco+=XIC+10;
+
+ if(sfile->type==FILE_LOADLIB) {
+ uiDefButS(block, TOGN|BIT|2, B_REDR, "Append", xco+=XIC,0,100,YIC, &sfile->flag, 0, 0, 0, 0, "Causes selected data to be copied into current file");
+ uiDefButS(block, TOG|BIT|2, B_REDR, "Link", xco+=100,0,100,YIC, &sfile->flag, 0, 0, 0, 0, "Causes selected data to be linked by current file");
+ }
+
+ if(sfile->type==FILE_UNIX) {
+ df= BLI_diskfree(sfile->dir)/(1048576.0);
+
+ filesel_statistics(sfile, &totfile, &selfile, &totlen, &sellen);
+
+ sprintf(naam, "Free: %.3f Mb Files: (%d) %d (%.3f) %.3f Mb",
+ df, selfile,totfile, sellen, totlen);
+
+ cpack(0x0);
+ glRasterPos2i(xco, 5);
+ BMF_DrawString(uiBlockGetCurFont(block), naam);
+ }
+ /* altijd als laatste doen */
+ curarea->headbutlen= xco+2*XIC;
+
+ uiDrawBlock(block);
+}
+
+
+/* ********************** FILE ****************************** */
+/* ******************** OOPS ********************** */
+
+void do_oops_buttons(short event)
+{
+ float dx, dy;
+
+ if(curarea->win==0) return;
+
+ switch(event) {
+ case B_OOPSHOME:
+ boundbox_oops();
+ G.v2d->cur= G.v2d->tot;
+ dx= 0.15*(G.v2d->cur.xmax-G.v2d->cur.xmin);
+ dy= 0.15*(G.v2d->cur.ymax-G.v2d->cur.ymin);
+ G.v2d->cur.xmin-= dx;
+ G.v2d->cur.xmax+= dx;
+ G.v2d->cur.ymin-= dy;
+ G.v2d->cur.ymax+= dy;
+ test_view2d(G.v2d, curarea->winx, curarea->winy);
+ scrarea_queue_winredraw(curarea);
+ break;
+
+ case B_NEWOOPS:
+ scrarea_queue_winredraw(curarea);
+ scrarea_queue_headredraw(curarea);
+ G.soops->lockpoin= 0;
+ break;
+ }
+
+}
+
+void oops_buttons(void)
+{
+ SpaceOops *soops;
+ Oops *oops;
+ uiBlock *block;
+ short xco;
+ char naam[256];
+
+ soops= curarea->spacedata.first;
+
+ sprintf(naam, "header %d", curarea->headwin);
+ block= uiNewBlock(&curarea->uiblocks, naam, UI_EMBOSSX, UI_HELV, curarea->headwin);
+ uiBlockSetCol(block, BUTGREEN);
+
+ curarea->butspacetype= SPACE_OOPS;
+ uiDefIconButC(block, ICONROW,B_NEWSPACE, ICON_VIEW3D, 6,0,XIC,YIC, &(curarea->butspacetype), 1.0, SPACEICONMAX, 0, 0, "Current window type");
+
+ /* FULL WINDOW */
+ xco= 25;
+ if(curarea->full) uiDefIconBut(block, BUT,B_FULL, ICON_SPLITSCREEN, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Restore smaller windows (CTRL+Up arrow)");
+ else uiDefIconBut(block, BUT,B_FULL, ICON_FULLSCREEN, (short)(xco+=XIC),0,XIC,YIC, 0, 0, 0, 0, 0, "Make fullscreen window (CTRL+Down arrow)");
+
+ /* HOME */
+ uiDefIconBut(block, BUT, B_OOPSHOME, ICON_HOME, (short)(xco+=XIC),0,XIC,YIC, 0, 0, 0, 0, 0, "Home (HOMEKEY)");
+ xco+= XIC;
+
+ /* ZOOM en BORDER */
+ xco+= XIC;
+ uiDefIconButI(block, TOG, B_VIEW2DZOOM, ICON_VIEWZOOM, (short)(xco+=XIC),0,XIC,YIC, &viewmovetemp, 0, 0, 0, 0, "Zoom view (CTRL+MiddleMouse)");
+ uiDefIconBut(block, BUT, B_OOPSBORDER, ICON_BORDERMOVE, (short)(xco+=XIC),0,XIC,YIC, 0, 0, 0, 0, 0, "Translate view (MiddleMouse)");
+
+ /* VISIBLE */
+ xco+= XIC;
+ uiDefButS(block, TOG|BIT|10,B_NEWOOPS, "lay", (short)(xco+=XIC),0,XIC+10,YIC, &soops->visiflag, 0, 0, 0, 0, "Display Objects based on layer");
+ uiDefIconButS(block, TOG|BIT|0, B_NEWOOPS, ICON_SCENE_HLT, (short)(xco+=XIC+10),0,XIC,YIC, &soops->visiflag, 0, 0, 0, 0, "Display Scene data");
+ uiDefIconButS(block, TOG|BIT|1, B_NEWOOPS, ICON_OBJECT_HLT, (short)(xco+=XIC),0,XIC,YIC, &soops->visiflag, 0, 0, 0, 0, "Display Object data");
+ uiDefIconButS(block, TOG|BIT|2, B_NEWOOPS, ICON_MESH_HLT, (short)(xco+=XIC),0,XIC,YIC, &soops->visiflag, 0, 0, 0, 0, "Display Mesh data");
+ uiDefIconButS(block, TOG|BIT|3, B_NEWOOPS, ICON_CURVE_HLT, (short)(xco+=XIC),0,XIC,YIC, &soops->visiflag, 0, 0, 0, 0, "Display Curve/Surface/Font data");
+ uiDefIconButS(block, TOG|BIT|4, B_NEWOOPS, ICON_MBALL_HLT, (short)(xco+=XIC),0,XIC,YIC, &soops->visiflag, 0, 0, 0, 0, "Display Metaball data");
+ uiDefIconButS(block, TOG|BIT|5, B_NEWOOPS, ICON_LATTICE_HLT, (short)(xco+=XIC),0,XIC,YIC, &soops->visiflag, 0, 0, 0, 0, "Display Lattice data");
+ uiDefIconButS(block, TOG|BIT|6, B_NEWOOPS, ICON_LAMP_HLT, (short)(xco+=XIC),0,XIC,YIC, &soops->visiflag, 0, 0, 0, 0, "Display Lamp data");
+ uiDefIconButS(block, TOG|BIT|7, B_NEWOOPS, ICON_MATERIAL_HLT, (short)(xco+=XIC),0,XIC,YIC, &soops->visiflag, 0, 0, 0, 0, "Display Material data");
+ uiDefIconButS(block, TOG|BIT|8, B_NEWOOPS, ICON_TEXTURE_HLT, (short)(xco+=XIC),0,XIC,YIC, &soops->visiflag, 0, 0, 0, 0, "Display Texture data");
+ uiDefIconButS(block, TOG|BIT|9, B_NEWOOPS, ICON_IPO_HLT, (short)(xco+=XIC),0,XIC,YIC, &soops->visiflag, 0, 0, 0, 0, "Display Ipo data");
+ uiDefIconButS(block, TOG|BIT|12, B_NEWOOPS, ICON_IMAGE_HLT, (short)(xco+=XIC),0,XIC,YIC, &soops->visiflag, 0, 0, 0, 0, "Display Image data");
+ uiDefIconButS(block, TOG|BIT|11, B_NEWOOPS, ICON_LIBRARY_HLT, (short)(xco+=XIC),0,XIC,YIC, &soops->visiflag, 0, 0, 0, 0, "Display Library data");
+
+ /* naam */
+ if(G.soops->lockpoin) {
+ oops= G.soops->lockpoin;
+ if(oops->type==ID_LI) strcpy(naam, ((Library *)oops->id)->name);
+ else strcpy(naam, oops->id->name);
+
+ cpack(0x0);
+ glRasterPos2i(xco+=XIC+10, 5);
+ BMF_DrawString(uiBlockGetCurFont(block), naam);
+
+ }
+
+ /* altijd als laatste doen */
+ curarea->headbutlen= xco+2*XIC;
+
+ uiDrawBlock(block);
+}
+
+
+/* ********************** OOPS ****************************** */
+/* ********************** TEXT ****************************** */
+
+void do_text_buttons(unsigned short event)
+{
+ SpaceText *st= curarea->spacedata.first;
+ ID *id, *idtest;
+ int nr= 1;
+ Text *text;
+
+ if (!st) return;
+ if (st->spacetype != SPACE_TEXT) return;
+
+ switch (event) {
+ case B_TEXTBROWSE:
+ if (st->menunr==-2) {
+ activate_databrowse((ID *)st->text, ID_TXT, 0, B_TEXTBROWSE, &st->menunr, do_text_buttons);
+ break;
+ }
+ if(st->menunr < 0) break;
+
+ text= st->text;
+
+ nr= 1;
+ id= (ID *)text;
+
+ if (st->menunr==32767) {
+ st->text= (Text *)add_empty_text();
+
+ st->top= 0;
+
+ allqueue(REDRAWTEXT, 0);
+ allqueue(REDRAWHEADERS, 0);
+ }
+ else if (st->menunr==32766) {
+ activate_fileselect(FILE_SPECIAL, "LOAD TEXT FILE", G.sce, add_text_fs);
+ return;
+ }
+ else {
+ idtest= G.main->text.first;
+ while(idtest) {
+ if(nr==st->menunr) {
+ break;
+ }
+ nr++;
+ idtest= idtest->next;
+ }
+ if(idtest==0) { /* new text */
+ activate_fileselect(FILE_SPECIAL, "LOAD TEXT FILE", G.sce, add_text_fs);
+ return;
+ }
+ if(idtest!=id) {
+ st->text= (Text *)idtest;
+ st->top= 0;
+
+ pop_space_text(st);
+
+ allqueue(REDRAWTEXT, 0);
+ allqueue(REDRAWHEADERS, 0);
+ }
+ }
+ break;
+
+ case B_TEXTDELETE:
+ if(!okee("Really delete text?")) return;
+
+ text= st->text;
+ if (!text) return;
+
+ BPY_clear_bad_scriptlinks(text);
+ free_text_controllers(text);
+
+ unlink_text(text);
+ free_libblock(&G.main->text, text);
+
+ break;
+
+/*
+ case B_TEXTSTORE:
+ st->text->flags ^= TXT_ISEXT;
+
+ allqueue(REDRAWHEADERS, 0);
+ break;
+*/
+ case B_TEXTFONT:
+ switch(st->font_id) {
+ case 0:
+ st->lheight= 12; break;
+ case 1:
+ st->lheight= 15; break;
+ }
+
+ allqueue(REDRAWTEXT, 0);
+ allqueue(REDRAWHEADERS, 0);
+
+ break;
+ }
+}
+
+void text_buttons(void)
+{
+ uiBlock *block;
+ SpaceText *st= curarea->spacedata.first;
+ short xco;
+ char naam[256];
+
+ if (!st || st->spacetype != SPACE_TEXT) return;
+
+ sprintf(naam, "header %d", curarea->headwin);
+ block= uiNewBlock(&curarea->uiblocks, naam, UI_EMBOSSX, UI_HELV, curarea->headwin);
+ uiBlockSetCol(block, BUTGREY);
+
+ curarea->butspacetype= SPACE_TEXT;
+ uiDefIconButC(block, ICONROW,B_NEWSPACE, ICON_VIEW3D, 6,0,XIC,YIC, &(curarea->butspacetype), 1.0, SPACEICONMAX, 0, 0, "Current window type");
+
+ /* FULL WINDOW */
+ xco= 25;
+ if(curarea->full) uiDefIconBut(block, BUT,B_FULL, ICON_SPLITSCREEN, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Restore smaller windows (CTRL+Up arrow)");
+ else uiDefIconBut(block, BUT,B_FULL, ICON_FULLSCREEN, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Make fullscreen window (CTRL+Down arrow)");
+
+
+ /* STD TEXT BUTTONS */
+ if (!BPY_spacetext_is_pywin(st)) {
+ xco+= 2*XIC;
+ xco= std_libbuttons(block, xco, 0, NULL, B_TEXTBROWSE, (ID*)st->text, 0, &(st->menunr), 0, 0, B_TEXTDELETE, 0);
+
+ /*
+ if (st->text) {
+ if (st->text->flags & TXT_ISDIRTY && (st->text->flags & TXT_ISEXT || !(st->text->flags & TXT_ISMEM)))
+ uiDefIconBut(block, BUT,0, ICON_ERROR, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "The text has been changed");
+ if (st->text->flags & TXT_ISEXT)
+ uiDefBut(block, BUT,B_TEXTSTORE, ICON(), xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Store text in .blend file");
+ else
+ uiDefBut(block, BUT,B_TEXTSTORE, ICON(), xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Don't store text in .blend file");
+ xco+=10;
+ }
+ */
+
+ xco+=XIC;
+ if(st->font_id>1) st->font_id= 0;
+ uiDefButI(block, MENU, B_TEXTFONT, "Screen 12 %x0|Screen 15%x1", xco,0,100,YIC, &st->font_id, 0, 0, 0, 0, "Font display menu");
+ xco+=100;
+ }
+
+ /* always as last */
+ curarea->headbutlen= xco+2*XIC;
+
+ uiDrawBlock(block);
+}
+
+
+
+/* ******************** TEXT ********************** */
+/* ******************** SOUND ********************** */
+
+void load_space_sound(char *str) /* called from fileselect */
+{
+ bSound *sound;
+
+ sound= sound_new_sound(str);
+ if (sound) {
+ if (G.ssound) {
+ G.ssound->sound= sound;
+ }
+ } else {
+ error("Not a valid sample: %s", str);
+ }
+
+ allqueue(REDRAWSOUND, 0);
+ allqueue(REDRAWBUTSGAME, 0);
+}
+
+
+void load_sound_buttons(char *str) /* called from fileselect */
+{
+ bSound *sound;
+
+ sound= sound_new_sound(str);
+ if (sound) {
+ if (curarea && curarea->spacetype==SPACE_BUTS) {
+ if (G.buts->mainb == BUTS_SOUND) {
+ G.buts->lockpoin = sound;
+ }
+ }
+ } else {
+ error("Not a valid sample: %s", str);
+ }
+
+ allqueue(REDRAWBUTSSOUND, 0);
+}
+
+void do_action_buttons(unsigned short event)
+{
+ View2D *v2d;
+
+ switch(event){
+#ifdef __NLA_BAKE
+ case B_ACTBAKE:
+ bake_action_with_client (G.saction->action, OBACT, 0.01);
+ break;
+#endif
+ case B_ACTCONT:
+ set_exprap_action(IPO_HORIZ);
+ break;
+// case B_ACTEXTRAP:
+// set_exprap_ipo(IPO_DIR);
+// break;
+ case B_ACTCYCLIC:
+ set_exprap_action(IPO_CYCL);
+ break;
+// case B_ACTCYCLICX:
+// set_exprap_ipo(IPO_CYCLX);
+// break;
+ case B_ACTHOME:
+ // Find X extents
+ v2d= &(G.saction->v2d);
+
+// v2d->cur.xmin = 0;
+ v2d->cur.ymin=-SCROLLB;
+
+ if (!G.saction->action){
+ v2d->cur.xmax=100;
+ }
+ else
+ {
+ v2d->cur.xmin=calc_action_start(G.saction->action)-1;
+ v2d->cur.xmax=calc_action_end(G.saction->action)+1;
+ }
+
+
+// G.v2d->cur= G.v2d->tot;
+ test_view2d(G.v2d, curarea->winx, curarea->winy);
+ addqueue (curarea->win, REDRAW, 1);
+ break;
+ case B_ACTCOPY:
+ copy_posebuf();
+ allqueue(REDRAWVIEW3D, 1);
+ break;
+ case B_ACTPASTE:
+ paste_posebuf(0);
+ allqueue(REDRAWVIEW3D, 1);
+ break;
+ case B_ACTPASTEFLIP:
+ paste_posebuf(1);
+ allqueue(REDRAWVIEW3D, 1);
+ break;
+
+ case B_ACTPIN: /* __PINFAKE */
+/* if (G.saction->flag & SACTION_PIN){
+ if (G.saction->action)
+ G.saction->action->id.us ++;
+
+ }
+ else {
+ if (G.saction->action)
+ G.saction->action->id.us --;
+ }
+*/ /* end PINFAKE */
+ allqueue(REDRAWACTION, 1);
+ break;
+
+ }
+}
+
+void do_sound_buttons(unsigned short event)
+{
+ ID *id, *idtest;
+ int nr;
+ char name[256];
+
+ switch(event) {
+
+ case B_SOUNDBROWSE:
+ if(G.ssound->sndnr== -2) {
+ activate_databrowse((ID *)G.ssound->sound, ID_SO, 0, B_SOUNDBROWSE, &G.ssound->sndnr, do_sound_buttons);
+ return;
+ }
+ if (G.ssound->sndnr < 0) break;
+ if (G.ssound->sndnr == 32766) {
+ if (G.ssound && G.ssound->sound) strcpy(name, G.ssound->sound->name);
+ else strcpy(name, U.sounddir);
+ activate_fileselect(FILE_SPECIAL, "SELECT WAV FILE", name, load_space_sound);
+ } else {
+ nr= 1;
+ id= (ID *)G.ssound->sound;
+
+ idtest= G.main->sound.first;
+ while(idtest) {
+ if(nr==G.ssound->sndnr) {
+ break;
+ }
+ nr++;
+ idtest= idtest->next;
+ }
+
+ if(idtest==0) { /* geen new */
+ return;
+ }
+
+ if(idtest!=id) {
+ G.ssound->sound= (bSound *)idtest;
+ if(idtest->us==0) idtest->us= 1;
+ allqueue(REDRAWSOUND, 0);
+ }
+ }
+
+ break;
+ case B_SOUNDBROWSE2:
+ id = (ID *)G.buts->lockpoin;
+ if(G.buts->texnr == -2) {
+ activate_databrowse(id, ID_SO, 0, B_SOUNDBROWSE2, &G.buts->texnr, do_sound_buttons);
+ return;
+ }
+ if (G.buts->texnr < 0) break;
+ if (G.buts->texnr == 32766) {
+ if (id) strcpy(name, ((bSound *)id)->name);
+ else strcpy(name, U.sounddir);
+ activate_fileselect(FILE_SPECIAL, "SELECT WAV FILE", name, load_sound_buttons);
+ } else {
+ nr= 1;
+
+ idtest= G.main->sound.first;
+ while (idtest) {
+ if(nr == G.buts->texnr) {
+ break;
+ }
+ nr++;
+ idtest = idtest->next;
+ }
+
+ if (idtest == 0) { /* geen new */
+ return;
+ }
+
+ if (idtest != id) {
+ G.buts->lockpoin = (bSound *)idtest;
+ if(idtest->us==0) idtest->us= 1;
+ allqueue(REDRAWBUTSSOUND, 0);
+ BIF_preview_changed(G.buts);
+ }
+ }
+
+ break;
+ case B_SOUNDHOME:
+
+ G.v2d->cur= G.v2d->tot;
+ test_view2d(G.v2d, curarea->winx, curarea->winy);
+ scrarea_queue_winredraw(curarea);
+ break;
+ }
+}
+
+void sound_buttons(void)
+{
+ uiBlock *block;
+ short xco;
+ char naam[256];
+ char ch[20];
+
+ sprintf(naam, "header %d", curarea->headwin);
+ block= uiNewBlock(&curarea->uiblocks, naam, UI_EMBOSSX, UI_HELV, curarea->headwin);
+ uiBlockSetCol(block, BUTYELLOW);
+
+ curarea->butspacetype= SPACE_SOUND;
+ uiDefIconButC(block, ICONROW,B_NEWSPACE, ICON_VIEW3D, 6,0,XIC,YIC, &(curarea->butspacetype), 1.0, SPACEICONMAX, 0, 0, "Current window type");
+
+ /* FULL WINDOW */
+ xco= 25;
+ if(curarea->full) uiDefIconBut(block, BUT,B_FULL, ICON_SPLITSCREEN, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Restore smaller windows (CTRL+Up arrow)");
+ else uiDefIconBut(block, BUT,B_FULL, ICON_FULLSCREEN, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Make fullscreen window (CTRL+Down arrow)");
+ uiDefIconBut(block, BUT, B_SOUNDHOME, ICON_HOME, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Home (HOMEKEY)");
+
+ xco= std_libbuttons(block, xco+40, 0, NULL, B_SOUNDBROWSE, (ID *)G.ssound->sound, 0, &(G.ssound->sndnr), 1, 0, 0, 0);
+
+ if(G.ssound->sound) {
+ bSound *sound= G.ssound->sound;
+
+ if (sound->sample && sound->sample->len)
+ {
+ if (sound->sample->channels == 1)
+ strcpy(ch, "Mono");
+ else if (sound->sample->channels == 2)
+ strcpy(ch, "Stereo");
+ else
+ strcpy(ch, "Unknown");
+
+ sprintf(naam, "Sample: %s, %d bit, %d Hz, %d samples", ch, sound->sample->bits, sound->sample->rate, sound->sample->len);
+ cpack(0x0);
+ glRasterPos2i(xco+10, 5);
+ BMF_DrawString(uiBlockGetCurFont(block), naam);
+ }
+ else
+ {
+ sprintf(naam, "No sample info available.");
+ cpack(0x0);
+ glRasterPos2i(xco+10, 5);
+ BMF_DrawString(uiBlockGetCurFont(block), naam);
+ }
+
+ }
+
+ /* always as last */
+ curarea->headbutlen= xco+2*XIC;
+
+ uiDrawBlock(block);
+}
+
+
+/* ******************** SOUND ********************** */
+/* ******************** IMAGE ********************** */
+
+void load_space_image(char *str) /* aangeroepen vanuit fileselect */
+{
+ Image *ima=0;
+
+ if(G.obedit) {
+ error("Can't perfom this in editmode");
+ return;
+ }
+
+ ima= add_image(str);
+ if(ima) {
+
+ G.sima->image= ima;
+
+ free_image_buffers(ima); /* forceer opnieuw inlezen */
+ ima->ok= 1;
+ image_changed(G.sima, 0);
+
+ }
+
+ allqueue(REDRAWIMAGE, 0);
+}
+
+void image_replace(Image *old, Image *new)
+{
+ TFace *tface;
+ Mesh *me;
+ int a, rep=0;
+
+ new->tpageflag= old->tpageflag;
+ new->twsta= old->twsta;
+ new->twend= old->twend;
+ new->xrep= old->xrep;
+ new->yrep= old->yrep;
+
+ me= G.main->mesh.first;
+ while(me) {
+
+ if(me->tface) {
+ tface= me->tface;
+ a= me->totface;
+ while(a--) {
+ if(tface->tpage==old) {
+ tface->tpage= new;
+ rep++;
+ }
+ tface++;
+ }
+ }
+ me= me->id.next;
+
+ }
+ if(rep) {
+ if(new->id.us==0) new->id.us= 1;
+ }
+ else error("Nothing replaced");
+}
+
+void replace_space_image(char *str) /* aangeroepen vanuit fileselect */
+{
+ Image *ima=0;
+
+ if(G.obedit) {
+ error("Can't perfom this in editmode");
+ return;
+ }
+
+ ima= add_image(str);
+ if(ima) {
+
+ if(G.sima->image != ima) {
+ image_replace(G.sima->image, ima);
+ }
+
+ G.sima->image= ima;
+
+ free_image_buffers(ima); /* forceer opnieuw inlezen */
+ ima->ok= 1;
+ /* replace kent ook toe: */
+ image_changed(G.sima, 0);
+
+ }
+ allqueue(REDRAWIMAGE, 0);
+}
+
+void save_paint(char *name)
+{
+ char str[FILE_MAXDIR+FILE_MAXFILE];
+ Image *ima = G.sima->image;
+ ImBuf *ibuf;
+
+ if (ima && ima->ibuf) {
+ BLI_strncpy(str, name, sizeof(str));
+
+ BLI_convertstringcode(str, G.sce, G.scene->r.cfra);
+
+ if (saveover(str)) {
+ ibuf = IMB_dupImBuf(ima->ibuf);
+
+ if (ibuf) {
+ if (BIF_write_ibuf(ibuf, str)) {
+ BLI_strncpy(ima->name, name, sizeof(ima->name));
+ ima->ibuf->userflags &= ~IB_BITMAPDIRTY;
+ allqueue(REDRAWHEADERS, 0);
+ allqueue(REDRAWBUTSTEX, 0);
+ } else {
+ error("Couldn't write image: %s", str);
+ }
+
+ IMB_freeImBuf(ibuf);
+ }
+ }
+ }
+}
+
+
+void do_image_buttons(unsigned short event)
+{
+ Image *ima;
+ ID *id, *idtest;
+ int nr;
+ char name[256], str[256];
+
+ if(curarea->win==0) return;
+
+ switch(event) {
+ case B_SIMAGEHOME:
+ image_home();
+ break;
+
+ case B_SIMABROWSE:
+ if(G.sima->imanr== -2) {
+ activate_databrowse((ID *)G.sima->image, ID_IM, 0, B_SIMABROWSE, &G.sima->imanr, do_image_buttons);
+ return;
+ }
+ if(G.sima->imanr < 0) break;
+
+ nr= 1;
+ id= (ID *)G.sima->image;
+
+ idtest= G.main->image.first;
+ while(idtest) {
+ if(nr==G.sima->imanr) {
+ break;
+ }
+ nr++;
+ idtest= idtest->next;
+ }
+ if(idtest==0) { /* geen new */
+ return;
+ }
+
+ if(idtest!=id) {
+ G.sima->image= (Image *)idtest;
+ if(idtest->us==0) idtest->us= 1;
+ allqueue(REDRAWIMAGE, 0);
+ }
+ image_changed(G.sima, 0); /* ook als image gelijk is: assign! 0==geen tileflag */
+
+ break;
+ case B_SIMAGELOAD:
+ case B_SIMAGELOAD1:
+
+ if(G.sima->image) strcpy(name, G.sima->image->name);
+ else strcpy(name, U.textudir);
+
+ if(event==B_SIMAGELOAD)
+ activate_imageselect(FILE_SPECIAL, "SELECT IMAGE", name, load_space_image);
+ else
+ activate_fileselect(FILE_SPECIAL, "SELECT IMAGE", name, load_space_image);
+ break;
+ case B_SIMAGEREPLACE:
+ case B_SIMAGEREPLACE1:
+
+ if(G.sima->image) strcpy(name, G.sima->image->name);
+ else strcpy(name, U.textudir);
+
+ if(event==B_SIMAGEREPLACE)
+ activate_imageselect(FILE_SPECIAL, "REPLACE IMAGE", name, replace_space_image);
+ else
+ activate_fileselect(FILE_SPECIAL, "REPLACE IMAGE", name, replace_space_image);
+ break;
+ case B_SIMAGEDRAW:
+
+ if(G.f & G_FACESELECT) {
+ make_repbind(G.sima->image);
+ image_changed(G.sima, 1);
+ }
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWIMAGE, 0);
+ break;
+
+ case B_SIMAGEDRAW1:
+ image_changed(G.sima, 2); /* 2: alleen tileflag */
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWIMAGE, 0);
+ break;
+
+ case B_TWINANIM:
+ ima = G.sima->image;
+ if (ima) {
+ if(ima->flag & IMA_TWINANIM) {
+ nr= ima->xrep*ima->yrep;
+ if(ima->twsta>=nr) ima->twsta= 1;
+ if(ima->twend>=nr) ima->twend= nr-1;
+ if(ima->twsta>ima->twend) ima->twsta= 1;
+ allqueue(REDRAWIMAGE, 0);
+ }
+ }
+ break;
+
+ case B_CLIP_UV:
+ tface_do_clip();
+ allqueue(REDRAWIMAGE, 0);
+ allqueue(REDRAWVIEW3D, 0);
+ break;
+
+ case B_SIMAGEPAINTTOOL:
+ // check for packed file here
+ allqueue(REDRAWIMAGE, 0);
+ allqueue(REDRAWVIEW3D, 0);
+ break;
+ case B_SIMAPACKIMA:
+ ima = G.sima->image;
+ if (ima) {
+ if (ima->packedfile) {
+ if (G.fileflags & G_AUTOPACK) {
+ if (okee("Disable AutoPack ?")) {
+ G.fileflags &= ~G_AUTOPACK;
+ }
+ }
+
+ if ((G.fileflags & G_AUTOPACK) == 0) {
+ unpackImage(ima, PF_ASK);
+ }
+ } else {
+ if (ima->ibuf && (ima->ibuf->userflags & IB_BITMAPDIRTY)) {
+ error("Can't pack painted image. Save image first.");
+ } else {
+ ima->packedfile = newPackedFile(ima->name);
+ }
+ }
+ allqueue(REDRAWBUTSTEX, 0);
+ allqueue(REDRAWHEADERS, 0);
+ }
+ break;
+ case B_SIMAGESAVE:
+ ima = G.sima->image;
+ if (ima) {
+ strcpy(name, ima->name);
+ if (ima->ibuf) {
+ save_image_filesel_str(str);
+ activate_fileselect(FILE_SPECIAL, str, name, save_paint);
+ }
+ }
+ break;
+ }
+}
+
+/* This should not be a stack var! */
+static int headerbuttons_packdummy;
+void image_buttons(void)
+{
+ uiBlock *block;
+ short xco;
+ char naam[256];
+ headerbuttons_packdummy = 0;
+
+ sprintf(naam, "header %d", curarea->headwin);
+ block= uiNewBlock(&curarea->uiblocks, naam, UI_EMBOSSX, UI_HELV, curarea->headwin);
+ uiBlockSetCol(block, BUTBLUE);
+
+ what_image(G.sima);
+
+ curarea->butspacetype= SPACE_IMAGE;
+ uiDefIconButC(block, ICONROW,B_NEWSPACE, ICON_VIEW3D, 6,0,XIC,YIC, &(curarea->butspacetype), 1.0, SPACEICONMAX, 0, 0, "Current window type ");
+
+ /* FULL WINDOW */
+ xco= 25;
+ if(curarea->full) uiDefIconBut(block, BUT,B_FULL, ICON_SPLITSCREEN, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Restore smaller windows (CTRL+Up arrow)");
+ else uiDefIconBut(block, BUT,B_FULL, ICON_FULLSCREEN, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Make fullscreen window (CTRL+Down arrow)");
+
+ /* HOME*/
+ uiDefIconBut(block, BUT, B_SIMAGEHOME, ICON_HOME, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Home (HOMEKEY)");
+ uiDefIconButS(block, TOG|BIT|0, B_BE_SQUARE, ICON_KEEPRECT, xco+=XIC,0,XIC,YIC, &G.sima->flag, 0, 0, 0, 0, "Keep UV polygons square while editing");
+ uiDefIconButS(block, ICONTOG|BIT|2, B_CLIP_UV, ICON_CLIPUV_DEHLT,xco+=XIC,0,XIC,YIC, &G.sima->flag, 0, 0, 0, 0, "Clip UV with image size");
+
+ xco= std_libbuttons(block, xco+40, 0, NULL, B_SIMABROWSE, (ID *)G.sima->image, 0, &(G.sima->imanr), 0, 0, B_IMAGEDELETE, 0);
+
+ if (G.sima->image) {
+ if (G.sima->image->packedfile) {
+ headerbuttons_packdummy = 1;
+ }
+ uiDefIconButI(block, TOG|BIT|0, B_SIMAPACKIMA, ICON_PACKAGE, xco,0,XIC,YIC, &headerbuttons_packdummy, 0, 0, 0, 0, "Pack/Unpack this Image");
+ xco += XIC;
+ }
+
+ uiBlockSetCol(block, BUTSALMON);
+ uiDefBut(block, BUT, B_SIMAGELOAD, "Load", xco+=XIC,0,2*XIC,YIC, 0, 0, 0, 0, 0, "Load image - thumbnail view");
+
+ uiBlockSetCol(block, BUTGREY);
+ uiDefBut(block, BUT, B_SIMAGELOAD1, "", (short)(xco+=2*XIC+2),0,10,YIC, 0, 0, 0, 0, 0, "Load image - file select view");
+ xco+=XIC/2;
+
+ if (G.sima->image) {
+ uiBlockSetCol(block, BUTSALMON);
+ uiDefBut(block, BUT, B_SIMAGEREPLACE, "Replace",xco+=XIC,0,(short)(3*XIC),YIC, 0, 0, 0, 0, 0, "Replace current image - thumbnail view");
+
+ uiBlockSetCol(block, BUTGREY);
+ uiDefBut(block, BUT, B_SIMAGEREPLACE1, "", (short)(xco+=3*XIC+2),0,10,YIC, 0, 0, 0, 0, 0, "Replace current image - file select view");
+ xco+=XIC/2;
+
+ uiDefIconButS(block, TOG|BIT|4, 0, ICON_ENVMAP, xco+=XIC,0,XIC,YIC, &G.sima->image->flag, 0, 0, 0, 0, "Use this image as a reflection map (UV coordinates are ignored)");
+ xco+=XIC/2;
+
+ uiDefIconButS(block, TOG|BIT|0, B_SIMAGEDRAW1, ICON_GRID, xco+=XIC,0,XIC,YIC, &G.sima->image->flag, 0, 0, 0, 0, "");
+ uiDefButS(block, NUM, B_SIMAGEDRAW, "", xco+=XIC,0,XIC,YIC, &G.sima->image->xrep, 1.0, 16.0, 0, 0, "");
+ uiDefButS(block, NUM, B_SIMAGEDRAW, "", xco+=XIC,0,XIC,YIC, &G.sima->image->yrep, 1.0, 16.0, 0, 0, "");
+
+ uiDefButS(block, TOG|BIT|1, B_TWINANIM, "Anim", xco+=XIC,0,(short)(2*XIC),YIC, &G.sima->image->tpageflag, 0, 0, 0, 0, "");
+ uiDefButS(block, NUM, B_TWINANIM, "", (short)(xco+=2*XIC),0,XIC,YIC, &G.sima->image->twsta, 0.0, 128.0, 0, 0, "");
+ uiDefButS(block, NUM, B_TWINANIM, "", xco+=XIC,0,XIC,YIC, &G.sima->image->twend, 0.0, 128.0, 0, 0, "");
+// uiDefButS(block, TOG|BIT|2, 0, "Cycle", xco+=XIC,0,2*XIC,YIC, &G.sima->image->tpageflag, 0, 0, 0, 0, "");
+ uiDefButS(block, NUM, 0, "Speed", xco+=(2*XIC),0,4*XIC,YIC, &G.sima->image->animspeed, 1.0, 100.0, 0, 0, "Speed of the animation in frames per second");
+
+#ifdef NAN_TPT
+ xco+= 4*XIC;
+ uiDefIconButS(block, ICONTOG|BIT|3, B_SIMAGEPAINTTOOL, ICON_TPAINT_DEHLT, xco+=XIC,0,XIC,YIC, &G.sima->flag, 0, 0, 0, 0, "TexturePaint Mode");
+ if (G.sima->image && G.sima->image->ibuf && (G.sima->image->ibuf->userflags & IB_BITMAPDIRTY)) {
+ uiDefBut(block, BUT, B_SIMAGESAVE, "Save", xco+=XIC,0,2*XIC,YIC, 0, 0, 0, 0, 0, "Save image");
+ xco += XIC;
+ }
+#endif /* NAN_TPT */
+ xco+= XIC;
+ }
+
+ /* draw LOCK */
+ xco+= XIC/2;
+ uiDefIconButS(block, ICONTOG, 0, ICON_UNLOCKED, (short)(xco+=XIC),0,XIC,YIC, &(G.sima->lock), 0, 0, 0, 0, "Lock redraw of other windows while editing");
+
+
+ /* Always do this last */
+ curarea->headbutlen= xco+2*XIC;
+
+ uiDrawBlock(block);
+}
+
+
+/* ********************** IMAGE ****************************** */
+/* ******************** IMASEL ********************** */
+
+void do_imasel_buttons(short event)
+{
+ SpaceImaSel *simasel;
+ char name[256];
+
+ simasel= curarea->spacedata.first;
+
+ if(curarea->win==0) return;
+
+ switch(event) {
+ case B_IMASELHOME:
+ break;
+
+ case B_IMASELREMOVEBIP:
+
+ if(bitset(simasel->fase, IMS_FOUND_BIP)){
+
+ strcpy(name, simasel->dir);
+ strcat(name, ".Bpib");
+
+ remove(name);
+
+ simasel->fase &= ~ IMS_FOUND_BIP;
+ }
+ break;
+ }
+}
+
+void imasel_buttons(void)
+{
+ SpaceImaSel *simasel;
+ uiBlock *block;
+ short xco;
+ char naam[256];
+
+ simasel= curarea->spacedata.first;
+
+ sprintf(naam, "header %d", curarea->headwin);
+ block= uiNewBlock(&curarea->uiblocks, naam, UI_EMBOSSX, UI_HELV, curarea->headwin);
+ uiBlockSetCol(block, BUTBLUE);
+
+ curarea->butspacetype= SPACE_IMASEL;
+ uiDefIconButC(block, ICONROW,B_NEWSPACE, ICON_VIEW3D, 6,0,XIC,YIC, &(curarea->butspacetype), 1.0, SPACEICONMAX, 0, 0, "Current window type");
+
+ /* FULL WINDOW */
+ xco= 25;
+ if(curarea->full) uiDefIconBut(block, BUT,B_FULL, ICON_SPLITSCREEN, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "");
+ else uiDefIconBut(block, BUT,B_FULL, ICON_FULLSCREEN, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "");
+
+ xco+=XIC;
+ if (simasel->title){
+ xco+=25;
+ glRasterPos2i(xco, 4);
+ BMF_DrawString(G.font, simasel->title);
+ xco+=BMF_GetStringWidth(G.fonts, simasel->title);
+ xco+=25;
+ }
+ uiDefIconBut(block, BUT, B_IMASELREMOVEBIP, ICON_BPIBFOLDER_X, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "");/* remove */
+
+ uiDefIconButS(block, TOG|BIT|0, B_REDR, ICON_BPIBFOLDERGREY, xco+=XIC,0,XIC,YIC, &simasel->mode, 0, 0, 0, 0, "");/* dir */
+ uiDefIconButS(block, TOG|BIT|1, B_REDR, ICON_INFO, xco+=XIC,0,XIC,YIC, &simasel->mode, 0, 0, 0, 0, "");/* info */
+ uiDefIconButS(block, TOG|BIT|2, B_REDR, ICON_IMAGE_COL, xco+=XIC,0,XIC,YIC, &simasel->mode, 0, 0, 0, 0, "");/* image */
+ uiDefIconButS(block, TOG|BIT|3, B_REDR, ICON_MAGNIFY, xco+=XIC,0,XIC,YIC, &simasel->mode, 0, 0, 0, 0, "");/* loep */
+
+ /* altijd als laatste doen */
+ curarea->headbutlen= xco+2*XIC;
+
+ uiDrawBlock(block);
+}
+
+/* ********************** IMASEL ****************************** */
+
+/* ******************** ALGEMEEN ********************** */
+
+void do_headerbuttons(short event)
+{
+
+ if(event<=50) do_global_buttons2(event);
+ else if(event<=100) do_global_buttons(event);
+ else if(event<200) do_view3d_buttons(event);
+ else if(event<250) do_ipo_buttons(event);
+ else if(event<300) do_oops_buttons(event);
+ else if(event<350) do_info_buttons(event);
+ else if(event<400) do_image_buttons(event);
+ else if(event<450) do_buts_buttons(event);
+ else if(event<500) do_imasel_buttons(event);
+ else if(event<550) do_text_buttons(event);
+ else if(event<600) do_file_buttons(event);
+ else if(event<650) do_seq_buttons(event);
+ else if(event<700) do_sound_buttons(event);
+ else if(event<800) do_action_buttons(event);
+ else if(event<900) do_nla_buttons(event);
+}
+
diff --git a/source/blender/src/imasel.c b/source/blender/src/imasel.c
new file mode 100644
index 00000000000..e75fa8eba26
--- /dev/null
+++ b/source/blender/src/imasel.c
@@ -0,0 +1,900 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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>
+#ifndef WIN32
+#include <unistd.h>
+#else
+#include "BLI_winstuff.h"
+#include <io.h>
+#include <direct.h>
+#endif
+#include <fcntl.h>
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_global.h"
+
+#include "BIF_imasel.h"
+#include "BIF_space.h"
+#include "BIF_screen.h"
+
+#include "blendef.h"
+#include "mydevice.h"
+
+#ifndef WIN32
+#include <dirent.h>
+#endif
+
+#include <sys/stat.h>
+#include "datatoc.h"
+
+/* locals */
+void longtochar(char *des, unsigned int *src, int size);
+void chartolong(unsigned int *des, char *src, int size);
+int dir_compare(const void *a1, const void *a2);
+void issort( int te, ImaDir **firstentry);
+int ima_compare(const void *a1, const void *a2);
+void imsort(OneSelectableIma **firstentry);
+void append_pib(SpaceImaSel *simasel, OneSelectableIma *ima);
+void add_ima(int who, SpaceImaSel *simasel, ImaDir *direntry);
+
+/* implementation */
+int bitset(int l, int bit)
+{ return (( l & bit) == bit); }
+
+void longtochar(char *des, unsigned int *src, int size)
+{ int i;for (i = 0; i<size; i++){ des[i] = src[i] & 0xFF; }}
+
+void chartolong(unsigned int *des, char *src, int size)
+{ int i;for (i = 0; i<size; i++){ des[i] = src[i]; }}
+
+int dir_compare(const void *a1, const void *a2)
+{
+ ImaDir **in1, **in2;
+ ImaDir *use1, *use2;
+
+ in1= (ImaDir **)a1;
+ in2= (ImaDir **)a2;
+
+ use1 = *in1;
+ use2 = *in2;
+
+ return strcasecmp(use1->name, use2->name);
+}
+
+void issort( int te, ImaDir **firstentry)
+{
+ ImaDir **sort;
+ ImaDir *use;
+ int i = 0;
+
+ sort = MEM_mallocN(te * sizeof(void *), "dir Sorteer temp");
+ use = *firstentry;
+
+ while (use){
+ sort[i++] = use;
+ use = use->next;
+ }
+
+ qsort (sort, te, sizeof(void *), dir_compare);
+
+ *firstentry = sort[0];
+ use = *firstentry;
+
+
+ for (i=0; i<te; i++){
+ if (i != 0) use->prev = sort[i-1]; else use->prev = 0;
+ if (i != te-1) use->next = sort[i+1]; else use->next = 0;
+
+ use = use->next;
+ }
+
+ MEM_freeN(sort);
+}
+
+
+int ima_compare(const void *a1, const void *a2)
+{
+ OneSelectableIma **in1, **in2;
+ OneSelectableIma *use1, *use2;
+
+ in1= (OneSelectableIma **)a1;
+ in2= (OneSelectableIma **)a2;
+
+ use1 = *in1; use2 = *in2;
+ return strcasecmp(use1->file_name, use2->file_name);
+}
+
+void imsort(OneSelectableIma **firstentry)
+{
+ OneSelectableIma **sort;
+ OneSelectableIma *use;
+ int tot = 0, i = 0;
+
+ use = *firstentry;
+ while (use){
+ tot++;
+ use = use->next;
+ }
+
+ if (tot){
+ sort = MEM_mallocN(tot * sizeof(void *), "Sorteer imsort temp");
+ use = *firstentry;
+ while (use){
+ sort[i++] = use;
+ use = use->next;
+ }
+
+ qsort (sort, tot, sizeof(void *), ima_compare);
+
+ *firstentry = sort[0];
+ use = *firstentry;
+ for (i=0; i<tot; i++){
+ if (i != 0) use->prev = sort[i-1]; else use->prev = 0;
+ if (i != tot-1) use->next = sort[i+1]; else use->next = 0;
+
+ use = use->next;
+ }
+ MEM_freeN(sort);
+ }
+}
+
+static int write_msb_int(int fd, int i) {
+ unsigned int ui= (unsigned int) i;
+ unsigned char buf[4];
+ buf[0]= (ui>>24)&0xFF;
+ buf[1]= (ui>>16)&0xFF;
+ buf[2]= (ui>>8)&0xFF;
+ buf[3]= (ui>>0)&0xFF;
+ return write(fd, buf, 4);
+}
+static int write_msb_short(int fd, short s) {
+ unsigned short us= (unsigned short) s;
+ unsigned char buf[2];
+ buf[0]= (us>>8)&0xFF;
+ buf[1]= (us>>0)&0xFF;
+ return write(fd, buf, 2);
+}
+
+static int read_msb_int(int fd, int *i_r) {
+ unsigned char buf[4];
+ int rcount= read(fd, buf, 4);
+
+ if (i_r)
+ *i_r= (buf[0]<<24)|(buf[1]<<16)|(buf[2]<<8)|(buf[3]<<0);
+
+ return rcount;
+}
+static int read_msb_short(int fd, short *s_r) {
+ unsigned char buf[2];
+ int rcount= read(fd, buf, 2);
+
+ if (s_r)
+ *s_r= (buf[0]<<8)|(buf[1]<<0);
+
+ return rcount;
+}
+
+void append_pib(SpaceImaSel *simasel, OneSelectableIma *ima)
+{
+ int file;
+ char name[FILE_MAXDIR+FILE_MAXFILE];
+
+ if ( bitset (simasel->fase, IMS_WRITE_NO_BIP)) return;
+
+ strcpy(name, simasel->dir);
+ strcat(name, ".Bpib");
+
+ file = open(name, O_BINARY|O_APPEND | O_RDWR | O_CREAT, 0666);
+ if (file == -1) {
+ /* printf("Could not write .Bpib file in dir %s\n", simasel->dir); */
+ simasel->fase |= IMS_WRITE_NO_BIP;
+ return;
+ }
+
+ lseek(file, 0, SEEK_END);
+
+ write(file, "BIP2", 4);
+ write_msb_int(file, ima->ibuf_type);
+ write_msb_int(file, 0);
+ write_msb_int(file, 0);
+ write_msb_int(file, 0);
+ write_msb_short(file, ima->cmap);
+ write_msb_short(file, ima->image);
+ write_msb_short(file, ima->draw_me);
+ write_msb_short(file, ima->rt);
+ write_msb_short(file, ima->sx);
+ write_msb_short(file, ima->sy);
+ write_msb_short(file, ima->ex);
+ write_msb_short(file, ima->ey);
+ write_msb_short(file, ima->dw);
+ write_msb_short(file, ima->dh);
+ write_msb_short(file, ima->selectable);
+ write_msb_short(file, ima->selected);
+ write_msb_int(file, ima->mtime);
+ write_msb_int(file, ima->disksize);
+ write(file, ima->file_name, 64);
+ write_msb_short(file, ima->orgx);
+ write_msb_short(file, ima->orgy);
+ write_msb_short(file, ima->orgd);
+ write_msb_short(file, ima->anim);
+ write_msb_int(file, 0); /* pad to 128 boundary */
+ write(file, ima->pict_rect, 3968);
+
+ close(file);
+}
+
+void write_new_pib(SpaceImaSel *simasel)
+{
+ OneSelectableIma *ima;
+ char name[FILE_MAXDIR+FILE_MAXFILE];
+
+ strcpy(name, simasel->dir);
+ strcat(name, ".Bpib");
+ remove(name);
+
+ ima = simasel->first_sel_ima;
+ while (ima) {
+ append_pib(simasel, ima);
+ ima = ima->next;
+ }
+}
+
+void free_ima_dir(ImaDir *firstdir)
+{
+ ImaDir *n;
+
+ while(firstdir){
+ n = firstdir->next;
+ MEM_freeN(firstdir);
+ firstdir = n;
+ }
+}
+
+void free_sel_ima(OneSelectableIma *firstima)
+{
+ OneSelectableIma *n;
+
+ while(firstima){
+
+ if (firstima->pict) {
+ IMB_freeImBuf(firstima->pict);
+ }
+ n = firstima->next;
+ MEM_freeN(firstima);
+ firstima = n;
+ }
+}
+
+void check_for_pib(SpaceImaSel *simasel)
+{
+ ImaDir *direntry;
+
+ direntry = simasel->firstfile;
+ while(direntry){
+ if ((strlen(direntry->name) > 4) && (0==strcmp(direntry->name, ".Bpib")) ){
+ simasel->fase |= IMS_FOUND_BIP;
+ direntry = 0;
+ }else{
+ direntry = direntry->next;
+ }
+ }
+}
+
+void clear_ima_dir(SpaceImaSel *simasel)
+{
+ if(simasel->first_sel_ima) free_sel_ima(simasel->first_sel_ima);
+ if(simasel->firstdir) free_ima_dir(simasel->firstdir);
+ if(simasel->firstfile) free_ima_dir(simasel->firstfile);
+
+ simasel->first_sel_ima = 0;
+ simasel->firstdir = 0;
+ simasel->firstfile = 0;
+
+ simasel->totaldirs = 0;
+ simasel->totalfiles = 0;
+ simasel->totalima = 0;
+ simasel->topdir = -1;
+ simasel->topfile = -1;
+ simasel->topima = 0;
+ simasel->image_slider = 0.0;
+ simasel->slider_height = 0.0;
+ simasel->slider_space = 0.0;
+ simasel->hilite = -1;
+ simasel->curimax = 0;
+ simasel->curimay = 0;
+
+ simasel->total_selected = 0;
+ simasel->fase = 0;
+ simasel->subfase = 0;
+ simasel->imafase = 0;
+ simasel->ima_redraw = 0;
+}
+
+int get_ima_dir(char *dirname, int dtype, int *td, ImaDir **first)
+{
+ DIR *dirp;
+ struct dirent *dep;
+ struct ImaDir *temp;
+ struct ImaDir *dnext = NULL, *fnext;
+ struct stat status;
+ char olddir[FILE_MAXDIR+FILE_MAXFILE];
+ char getdirname[FILE_MAXDIR+FILE_MAXFILE];
+ int /* i=0, */ tot=0;
+ int isdir;
+
+ if(!BLI_getwdN(olddir)) return -1;
+
+ if (chdir(dirname) == -1) return(-1);
+
+ strcpy(getdirname, ".");
+
+ dirp = (DIR *) opendir(getdirname);
+ if (dirp == NULL) return (-1);
+
+ waitcursor(1);
+
+ while((dep = (struct dirent*) readdir(dirp)) != NULL){
+
+ strcpy(getdirname, dirname);
+ strcat(getdirname,dep->d_name);
+
+ stat(getdirname, &status);
+ isdir = S_ISDIR(status.st_mode);
+
+ if ( ((dtype == IMS_DIR) && isdir) || ((dtype == IMS_FILE) && !isdir)){
+ /* yes, searching for this type */
+ tot++;
+ if (tot == 1){
+ dnext = MEM_callocN(sizeof(struct ImaDir), "get first");
+ *first = dnext;
+
+ dnext->prev = 0;
+ dnext->next = 0;
+ }else{
+ fnext = MEM_callocN(sizeof(struct ImaDir), "get nextdir");
+ dnext->next = fnext;
+
+ temp = dnext;
+ dnext = fnext;
+
+ dnext ->prev = temp;
+ dnext ->next = 0;
+ }
+
+ dnext->type = dtype;
+ dnext->selected = 0;
+ dnext->hilite = 0;
+
+ dnext->mtime = status.st_ctime;
+ dnext->size = (int)status.st_size;
+ strcpy(dnext->name, dep->d_name);
+ }
+ }
+ closedir(dirp);
+
+ if (tot) issort(tot, first);
+
+ waitcursor(0);
+
+ *td = tot;
+
+ chdir (olddir);
+
+ return (tot);
+}
+
+void imadir_parent(SpaceImaSel *simasel)
+{
+
+#ifdef WIN32
+ if (strlen(simasel->dir) > 1){
+ simasel->dir[strlen(simasel->dir)-1] = 0;
+ while(simasel->dir[strlen(simasel->dir)-1] != '\\'){
+ if(strlen(simasel->dir)==0) break;
+ simasel->dir[strlen(simasel->dir)-1] = 0;
+ }
+ }
+#else
+ if (strlen(simasel->dir) > 1){
+ simasel->dir[strlen(simasel->dir)-1] = 0;
+ while(simasel->dir[strlen(simasel->dir)-1] != '/') {
+ if(strlen(simasel->dir)==0) break;
+ simasel->dir[strlen(simasel->dir)-1] = 0;
+ }
+ }
+#endif
+}
+
+
+void get_next_image(SpaceImaSel *simasel)
+{
+ OneSelectableIma * ima;
+ ImBuf * ibuf;
+ struct anim * anim;
+ int i = 0, size;
+ char name[FILE_MAXDIR+FILE_MAXFILE];
+
+ ima = simasel->first_sel_ima;
+ if (ima == 0){
+ simasel->imafase = 0;
+ simasel->fase |= IMS_KNOW_IMA;
+ simasel->fase &= ~IMS_DOTHE_IMA;
+ return;
+ }
+ if (simasel->imafase > simasel->totalima){
+ simasel->imafase = 0;
+ simasel->fase &= ~IMS_DOTHE_IMA;
+ simasel->fase |= IMS_KNOW_IMA;
+ }
+
+ ima = simasel->first_sel_ima;
+ i = 0;
+ while(i < simasel->imafase){
+ if ((ima) && (ima->next)) ima = ima->next;
+ i++;
+ }
+
+ if (ima->image == 0) {
+ if (ima->anim == 1) {
+ /* open movie, get len, get middle picture */
+
+ strcpy(name, simasel->dir);
+ strcat(name, ima->file_name);
+
+ anim = IMB_open_anim(name, IB_rect);
+
+ if (anim == 0) {
+ // ibuf= IMB_loadiffmem((int*)datatoc_cmovie_tga, IB_rect);
+ ibuf= IMB_ibImageFromMemory((int *)datatoc_cmovie_tga, datatoc_cmovie_tga_size, IB_rect);
+ }
+ else{
+ int animlen;
+
+ ibuf = IMB_anim_nextpic(anim);
+ IMB_freeImBuf(ibuf);
+
+ animlen= IMB_anim_get_duration(anim);
+ ibuf = IMB_anim_absolute(anim, animlen / 2);
+
+ IMB_free_anim(anim);
+ }
+ }
+ else {
+
+ strcpy(name, simasel->dir);
+ strcat(name, ima->file_name);
+
+ ibuf = IMB_loadiffname(name, IB_rect);
+ if(ibuf && ibuf->zbuf) IMB_freezbufImBuf(ibuf);
+ }
+
+ if (ibuf){
+ if (ima->dw < 4) ima->dw = 4;
+ if (ima->dh < 4) ima->dh = 4;
+
+ IMB_scaleImBuf(ibuf, ima->dw, ima->dh);
+ /* the whole cmap system is wacko */
+
+ if (G.order==B_ENDIAN)
+ IMB_convert_rgba_to_abgr(ima->dw*ima->dh, ibuf->rect);
+
+ ibuf->mincol = 0;
+ ibuf->maxcol = 256;
+ ibuf->cbits = 5;
+ ibuf->depth = 8;
+
+ IMB_freecmapImBuf(ibuf);
+ ibuf->cmap = simasel->cmap->cmap;
+
+ IMB_converttocmap(ibuf);
+
+ /* copy ibuf->rect naar ima->pict_rect */
+ size = ima->dw * ima->dh; if (size > 3968) size = 3968;
+ longtochar(ima->pict_rect, ibuf->rect, size);
+
+ IMB_applycmap(ibuf);
+ IMB_convert_rgba_to_abgr(size, ibuf->rect);
+
+ if (ima->pict) IMB_freeImBuf(ima->pict);
+ ima->pict = ibuf;
+ ibuf = 0;
+ ima->cmap = 1;
+ ima->image = 1;
+
+ append_pib(simasel, ima);
+ }
+ }
+ simasel->ima_redraw++;
+ simasel->imafase ++;
+ if (simasel->imafase == simasel->totalima){
+ simasel->imafase = 0;
+ simasel->fase &= ~IMS_DOTHE_IMA;
+ simasel->fase |= IMS_KNOW_IMA;
+ }
+}
+
+void add_ima(int who, SpaceImaSel *simasel, ImaDir *direntry)
+{
+ OneSelectableIma *ima, *prev_ima;
+ ImBuf *ibuf;
+ char name[FILE_MAXDIR+FILE_MAXFILE];
+
+ strcpy(name , simasel->dir);
+ strcat(name , direntry->name);
+
+ prev_ima = simasel->first_sel_ima;
+ while((prev_ima)&&(prev_ima->next)){
+ prev_ima = prev_ima->next;
+ }
+
+ ima = MEM_callocN(sizeof(OneSelectableIma), "OSIbip");
+ if (direntry->type == IMS_IMA){
+ /* Picture is an Image */
+ ibuf = IMB_loadiffname(name, IB_test);
+ if (ibuf){
+ ima->anim = 0;
+ ima->pict = ibuf;
+ ima->ibuf_type= ibuf->ftype;
+ ima->orgx = ibuf->x;
+ ima->orgy = ibuf->y;
+ ima->orgd = ibuf->depth;
+
+ ima->dw = 64;
+ ima->dh = 51;
+ ima->cmap = 0;
+ ima->image = 0;
+ if (ima->orgx > ima->orgy){
+ ima->dw = 64;
+ ima->dh = (short)(62 * ((float)ima->orgy / (float)ima->orgx));
+ }else{
+ ima->dw = (short)(64 * ((float)ima->orgx / (float)ima->orgy));
+ ima->dh = 62;
+ }
+ }else{
+ printf("%s image with no imbuf ???\n", name);
+ }
+ ibuf = 0;
+ }else{
+ /* Picture is an Animation */
+
+ ima->pict = 0;
+ ima->anim = 1;
+ ima->ibuf_type= 0;
+ ima->orgx = 64;
+ ima->orgy = 51;
+ ima->orgd = 24;
+
+ ima->dw = 64;
+ ima->dh = 51;
+ ima->cmap = 0;
+ ima->image = 0;
+ }
+
+ strcpy(name, direntry->name); name[63] = 0;
+ strcpy(ima->file_name, name);
+ ima->disksize = (int)direntry->size;
+ ima->mtime = (int)direntry->mtime;
+
+ ima->next = 0;
+ ima->prev = prev_ima;
+
+ if (prev_ima) {
+ prev_ima->next = ima;
+ }else{
+ simasel->first_sel_ima = ima;
+ }
+
+ simasel->ima_redraw++;
+ simasel->totalima++;
+}
+
+
+void get_file_info(SpaceImaSel *simasel)
+{
+ OneSelectableIma *prev_ima;
+ ImaDir *direntry;
+ char name[FILE_MAXDIR+FILE_MAXFILE];
+ int i = 0;
+
+ if (!simasel->firstfile){
+ simasel->subfase = 0;
+ simasel->fase |= IMS_KNOW_INF;
+ simasel->fase &= ~IMS_DOTHE_INF;
+ return;
+ }
+ if (simasel->subfase > simasel->totalfiles){
+ simasel->subfase = 0;
+ simasel->fase |= IMS_KNOW_INF;
+ simasel->fase &= ~IMS_DOTHE_INF;
+ }
+
+ direntry = simasel->firstfile;
+ while(i < simasel->subfase){
+ direntry = direntry->next;
+ i++;
+ }
+
+ prev_ima = simasel->first_sel_ima;
+ while((prev_ima)&&(prev_ima->next)){
+ prev_ima = prev_ima->next;
+ }
+
+ strcpy(name , simasel->dir);
+ strcat(name , direntry->name);
+
+ if (IMB_ispic(name)) {
+ direntry->type = IMS_IMA;
+ }else{
+ if (IMB_isanim(name)) {
+ direntry->type = IMS_ANIM;
+ }else{
+ direntry->type = IMS_NOIMA;
+ }
+ }
+
+ if (direntry->type != IMS_NOIMA){
+ add_ima(1, simasel, direntry);
+ }
+
+ simasel->subfase++;
+
+ if (simasel->subfase == simasel->totalfiles){
+ simasel->subfase = 0;
+ simasel->fase |= IMS_KNOW_INF;
+ simasel->fase &= ~IMS_DOTHE_INF;
+ }
+}
+
+/* Note: the thumbnails are saved in ABGR format in the .Bpib
+cache file */
+
+void get_pib_file(SpaceImaSel *simasel)
+{
+ ImaDir *direntry, *prev_dir, *next_dir;
+ OneSelectableIma *ima, *prev_ima;
+ int flen;
+ int dl, file, first, trd=0, rd, size, found, ima_added = 0;
+ char name[FILE_MAXDIR+FILE_MAXFILE];
+
+ if (bitset(simasel->fase , IMS_KNOW_BIP)) return;
+
+ waitcursor(1);
+
+ strcpy(name, simasel->dir);
+ strcat(name, ".Bpib");
+
+ file = open(name, O_BINARY|O_RDONLY);
+
+ flen = BLI_filesize(file);
+
+ simasel->totalima = 0;
+ prev_ima = 0;
+ first = 1;
+ trd = 0;
+
+ while(trd < flen){
+ char header[5];
+
+ ima = MEM_callocN(sizeof(OneSelectableIma), "Ima");
+
+ rd= 0;
+ rd+= read(file, header, 4);
+ rd+= read_msb_int(file, &ima->ibuf_type);
+ rd+= read_msb_int(file, NULL);
+ rd+= read_msb_int(file, NULL);
+ rd+= read_msb_int(file, NULL);
+ rd+= read_msb_short(file, &ima->cmap);
+ rd+= read_msb_short(file, &ima->image);
+ rd+= read_msb_short(file, &ima->draw_me);
+ rd+= read_msb_short(file, &ima->rt);
+ rd+= read_msb_short(file, &ima->sx);
+ rd+= read_msb_short(file, &ima->sy);
+ rd+= read_msb_short(file, &ima->ex);
+ rd+= read_msb_short(file, &ima->ey);
+ rd+= read_msb_short(file, &ima->dw);
+ rd+= read_msb_short(file, &ima->dh);
+ rd+= read_msb_short(file, &ima->selectable);
+ rd+= read_msb_short(file, &ima->selected);
+ rd+= read_msb_int(file, &ima->mtime);
+ rd+= read_msb_int(file, &ima->disksize);
+ rd+= read(file, ima->file_name, 64);
+ rd+= read_msb_short(file, &ima->orgx);
+ rd+= read_msb_short(file, &ima->orgy);
+ rd+= read_msb_short(file, &ima->orgd);
+ rd+= read_msb_short(file, &ima->anim);
+ rd+= read_msb_int(file, NULL);
+ rd+= read(file, ima->pict_rect, 3968);
+
+ found = 0;
+
+ if (rd != sizeof(OneSelectableIma) || memcmp(header, "BIP2", 4)!=0) {
+ printf("Error in Bpib file\n");
+ strcpy(name, simasel->dir);
+ strcat(name, ".Bpib");
+ dl = remove(name);
+ if (dl == 0) printf("corrupt Bpib file removed\n");
+ trd = flen;
+ } else {
+ /* find matching direntry (if possible) */
+ for (direntry= simasel->firstfile; direntry; direntry= direntry->next)
+ if (BLI_streq(direntry->name, ima->file_name))
+ break;
+
+ if (direntry) {
+ if (direntry->mtime == ima->mtime) {
+ /* ima found and same, load pic */
+ size = ima->dw * ima->dh;
+ if (size > 3968) size = 3968;
+ if (size) {
+ ima->pict = IMB_allocImBuf(ima->dw, ima->dh, 24, IB_rect | IB_cmap, 0);
+ chartolong(ima->pict->rect, ima->pict_rect, size);
+ ima->pict->cmap = simasel->cmap->cmap;
+ ima->pict->maxcol = 256;
+ IMB_applycmap(ima->pict);
+ IMB_convert_rgba_to_abgr(size, ima->pict->rect);
+ }
+ ima->selected = 0;
+ ima->selectable = 0;
+
+ if(prev_ima) prev_ima->next = ima;
+ ima->next = 0;
+ ima->prev = prev_ima;
+
+ prev_ima = ima;
+
+ if (first){ first = 0;simasel->first_sel_ima = ima; }
+ simasel->totalima++;
+ found = 1;
+ }
+
+ /* remove direntry */
+ prev_dir = direntry->prev;
+ next_dir = direntry->next;
+
+ if(prev_dir) prev_dir->next = next_dir;
+ if(next_dir) next_dir->prev = prev_dir;
+
+ MEM_freeN(direntry);
+ }
+ }
+ if (!found) MEM_freeN(ima);
+
+ trd+=rd;
+ }
+ close(file);
+
+ direntry = simasel->firstfile;
+
+ while(direntry){
+
+ strcpy(name , simasel->dir);
+ strcat(name , direntry->name);
+
+ if (IMB_ispic(name)) {
+ direntry->type = IMS_IMA;
+ }else{
+ if (IMB_isanim(name)) {
+ direntry->type = IMS_ANIM;
+ }else{
+ direntry->type = IMS_NOIMA;
+ }
+ }
+
+ if (direntry->type != IMS_NOIMA){
+ prev_ima = simasel->first_sel_ima;
+ while((prev_ima)&&(prev_ima->next)){
+ prev_ima = prev_ima->next;
+ }
+ add_ima(2, simasel, direntry);
+ ima_added = 1;
+ }
+ direntry = direntry->next;
+ }
+
+ imsort(&simasel->first_sel_ima);
+
+ simasel->fase |= IMS_KNOW_BIP;
+ simasel->fase |= IMS_KNOW_INF;
+ simasel->fase |= IMS_KNOW_IMA;
+
+ if (ima_added){
+ simasel->fase |= IMS_DOTHE_IMA;
+ simasel->fase &= ~IMS_KNOW_IMA;
+ addafterqueue(curarea->win, AFTERIMASELGET, 1);
+ }else{
+ write_new_pib(simasel);
+ }
+
+ waitcursor(0);
+}
+
+void change_imadir(SpaceImaSel *simasel)
+{
+ ImaDir *direntry;
+ int i;
+
+ direntry = simasel->firstdir;
+ for (i=0; i<simasel->hilite; i++){
+ direntry = direntry->next;
+ }
+
+ if(direntry==NULL);
+ else if (direntry->name[0] != '.'){
+ strcat(simasel->dir, direntry->name);
+ strcat(simasel->dir, "/");
+ }
+ else {
+ if (direntry->name[1] == '.'){
+ imadir_parent(simasel);
+ }
+ }
+
+ clear_ima_dir(simasel);
+}
+
+void check_imasel_copy(SpaceImaSel *simasel)
+{
+
+ /* LET OP: wordt ook gebruikt bij inlezen blender file */
+ /* dingen op nul zetten, opnieuw malloccen etc */
+ simasel->first_sel_ima = 0;
+ simasel->hilite_ima = 0;
+ simasel->firstdir = 0;
+ simasel->firstfile = 0;
+ simasel->cmap = 0;
+ clear_ima_dir(simasel);
+
+ // simasel->cmap= IMB_loadiffmem((int*)datatoc_cmap_tga, IB_rect|IB_cmap);
+ simasel->cmap= IMB_ibImageFromMemory((int *)datatoc_cmap_tga, datatoc_cmap_tga_size, IB_rect|IB_cmap);
+}
+
+void free_imasel(SpaceImaSel *simasel)
+{
+ /* NIET de imasel zelf vrijgeven */
+
+ clear_ima_dir(simasel);
+ IMB_freeImBuf(simasel->cmap);
+}
+
diff --git a/source/blender/src/interface.c b/source/blender/src/interface.c
new file mode 100644
index 00000000000..454d4355bdf
--- /dev/null
+++ b/source/blender/src/interface.c
@@ -0,0 +1,4105 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 <stdlib.h>
+#include <string.h>
+
+#ifndef WIN32
+#include <unistd.h>
+#else
+#include <io.h>
+#include "BLI_winstuff.h"
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "PIL_time.h"
+
+#include "BMF_Api.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+
+#include "DNA_screen_types.h"
+#include "DNA_userdef_types.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_global.h"
+
+#include "BIF_gl.h"
+#include "BIF_graphics.h"
+#include "BIF_keyval.h"
+#include "BIF_mainqueue.h"
+#include "BIF_resources.h"
+#include "BIF_screen.h"
+#include "BIF_toolbox.h"
+#include "BIF_mywindow.h"
+#include "BIF_space.h"
+#include "BIF_glutil.h"
+#include "BIF_interface.h"
+
+#include "BSE_view.h"
+
+#include "blendertimer.h"
+
+#include "mydevice.h"
+#include "interface.h"
+#include "blendef.h"
+
+/* naming conventions:
+ *
+ * uiBlahBlah() external function
+ * ui_blah_blah() internal function
+ */
+
+/***/
+
+typedef struct {
+ short xim, yim;
+ unsigned int *rect;
+ short xofs, yofs;
+} uiIconImage;
+
+typedef struct {
+ short mval[2];
+ short qual, val;
+ int event;
+} uiEvent;
+
+typedef struct {
+ void *xl, *large, *medium, *small;
+} uiFont;
+
+typedef struct uiLinkLine uiLinkLine;
+struct uiLinkLine { /* only for draw/edit */
+ uiLinkLine *next, *prev;
+
+ short flag, pad;
+
+ uiBut *from, *to;
+};
+
+typedef struct {
+ void **poin; /* pointer to original pointer */
+ void ***ppoin; /* pointer to original pointer-array */
+ short *totlink; /* if pointer-array, here is the total */
+
+ short maxlink, pad;
+ short fromcode, tocode;
+
+ ListBase lines;
+} uiLink;
+
+struct uiBut {
+ uiBut *next, *prev;
+ short type, pointype, bit, bitnr, retval, flag, strwidth, ofs, pos;
+
+ char *str;
+ char strdata[UI_MAX_NAME_STR];
+ char drawstr[UI_MAX_DRAW_STR];
+
+ float x1, y1, x2, y2;
+
+ char *poin;
+ float min, max;
+ float a1, a2, rt[4];
+ float aspect;
+
+ void (*func)(void *, void *);
+ void *func_arg1;
+ void *func_arg2;
+
+ void (*embossfunc)(BIFColorID, float, float, float, float, float, int);
+
+ uiLink *link;
+
+ char *tip, *lockstr;
+
+ BIFColorID col;
+ void *font;
+
+ BIFIconID icon;
+ short lock, win;
+ short iconadd;
+
+ /* IDPOIN data */
+ uiIDPoinFuncFP idpoin_func;
+ ID **idpoin_idpp;
+
+ /* BLOCK data */
+ uiBlockFuncFP block_func;
+
+ /* BUTM data */
+ void (*butm_func)(void *arg, int event);
+ void *butm_func_arg;
+};
+
+struct uiBlock {
+ uiBlock *next, *prev;
+
+ ListBase buttons;
+
+ char name[UI_MAX_NAME_STR];
+
+ float winmat[4][4];
+
+ float minx, miny, maxx, maxy;
+ float aspect;
+
+ void (*butm_func)(void *arg, int event);
+ void *butm_func_arg;
+
+ void (*func)(void *arg1, void *arg2);
+ void *func_arg1;
+ void *func_arg2;
+
+ BIFColorID col;
+ short font; /* indices */
+ int afterval;
+ void *curfont;
+
+ short autofill, flag, win, winq, direction, dt;
+ void *saveunder;
+
+ float xofs, yofs; // offset to parent button
+};
+
+/* ************ GLOBALS ************* */
+
+int UIfrontbuf= 0;
+
+static float UIwinmat[4][4];
+static int UIlock= 0, UIafterval;
+static char *UIlockstr=NULL;
+static void (*UIafterfunc)(void *arg, int event);
+static void *UIafterfunc_arg;
+
+static uiFont UIfont[UI_ARRAY]= {0};
+static uiBut *UIbuttip;
+
+/* ****************************** */
+
+static void ui_check_but(uiBut *but);
+static void ui_set_but_val(uiBut *but, double value);
+static double ui_get_but_val(uiBut *but);
+
+/* ****************************** */
+
+static int uibut_contains_pt(uiBut *but, short *pt)
+{
+ return ((but->x1<pt[0] && but->x2>=pt[0]) &&
+ (but->y1<pt[1] && but->y2>=pt[1]));
+}
+
+static void uibut_do_func(uiBut *but)
+{
+ if (but->func) {
+ but->func(but->func_arg1, but->func_arg2);
+ }
+}
+
+/* ************* SAVE UNDER ************ */
+
+typedef struct {
+ short x, y, sx, sy, oldwin;
+ int oldcursor;
+ unsigned int *rect;
+} uiSaveUnder;
+
+
+static void ui_paste_under(uiSaveUnder *su)
+{
+
+ if(su) {
+ glDisable(GL_DITHER);
+ glRasterPos2f( su->x-0.5, su->y-0.5 );
+ glDrawPixels(su->sx, su->sy, GL_RGBA, GL_UNSIGNED_BYTE, su->rect);
+ glEnable(GL_DITHER);
+
+ if(su->oldwin) {
+ mywinset(su->oldwin);
+ if (su->oldcursor) {
+ set_cursor(su->oldcursor);
+ }
+ }
+
+ MEM_freeN(su->rect);
+ MEM_freeN(su);
+ }
+}
+
+
+static uiSaveUnder *ui_save_under(int x, int y, int sx, int sy)
+{
+ uiSaveUnder *su=NULL;
+
+ if(sx>1 && sy>1) {
+
+ su= MEM_callocN(sizeof(uiSaveUnder), "save under");
+
+ su->rect= MEM_mallocN(sx*sy*4, "temp_frontbuffer_image");
+ su->x= x;
+ su->y= y;
+ su->sx= sx;
+ su->sy= sy;
+ glReadPixels(x, y, sx, sy, GL_RGBA, GL_UNSIGNED_BYTE, su->rect);
+ }
+
+ return su;
+}
+
+
+
+
+
+/* ************* DRAW ************** */
+
+
+static void ui_graphics_to_window(int win, float *x, float *y) /* voor rectwrite b.v. */
+{
+ float gx, gy;
+ int sx, sy;
+ int getsizex, getsizey;
+
+ bwin_getsize(win, &getsizex, &getsizey);
+ bwin_getsuborigin(win, &sx, &sy);
+
+ gx= *x;
+ gy= *y;
+ *x= sx + getsizex*(0.5+ 0.5*(gx*UIwinmat[0][0]+ gy*UIwinmat[1][0]+ UIwinmat[3][0]));
+ *y= sy + getsizey*(0.5+ 0.5*(gx*UIwinmat[0][1]+ gy*UIwinmat[1][1]+ UIwinmat[3][1]));
+}
+
+
+
+static void ui_window_to_graphics(int win, float *x, float *y) /* voor muiscursor b.v. */
+{
+ float a, b, c, d, e, f, px, py;
+ int getsizex, getsizey;
+
+ bwin_getsize(win, &getsizex, &getsizey);
+
+ a= .5*getsizex*UIwinmat[0][0];
+ b= .5*getsizex*UIwinmat[1][0];
+ c= .5*getsizex*(1.0+UIwinmat[3][0]);
+
+ d= .5*getsizey*UIwinmat[0][1];
+ e= .5*getsizey*UIwinmat[1][1];
+ f= .5*getsizey*(1.0+UIwinmat[3][1]);
+
+ px= *x;
+ py= *y;
+
+ *y= (a*(py-f) + d*(c-px))/(a*e-d*b);
+ *x= (px- b*(*y)- c)/a;
+
+}
+
+static uiSaveUnder *ui_bgnpupdraw(int startx, int starty, int endx, int endy, int cursor)
+{
+ uiSaveUnder *su;
+ short oldwin;
+
+ #if defined(__sgi) || defined(__sun)
+ /* this is a dirty patch: gets sometimes the backbuffer */
+ my_get_frontbuffer_image(0, 0, 1, 1);
+ my_put_frontbuffer_image();
+ #endif
+
+ oldwin= mywinget();
+
+ mywinset(G.curscreen->mainwin);
+
+ /* pietsje groter, 1 pixel aan de rand */
+
+ glReadBuffer(GL_FRONT);
+ glDrawBuffer(GL_FRONT);
+
+ /* for geforce and other cards */
+ glFinish();
+
+ su= ui_save_under(startx-1, starty-1, endx-startx+2, endy-starty+6);
+ if(su) su->oldwin= oldwin;
+
+ if(su && cursor) {
+ su->oldcursor= get_cursor();
+ set_cursor(CURSOR_STD);
+ }
+
+ return su;
+}
+
+static void ui_endpupdraw(uiSaveUnder *su)
+{
+
+ /* for geforce and other cards */
+
+ glReadBuffer(GL_FRONT);
+ glDrawBuffer(GL_FRONT);
+
+ glFinish();
+
+ if(su) {
+ ui_paste_under(su);
+ }
+ glReadBuffer(GL_BACK);
+ glDrawBuffer(GL_BACK);
+}
+
+static void ui_draw_icon(uiBut *but, BIFIconID icon)
+{
+ float xs= (but->x1+but->x2- BIF_get_icon_width(icon))/2.0;
+ float ys= (but->y1+but->y2- BIF_get_icon_height(icon))/2.0;
+
+ glRasterPos2f(xs, ys);
+
+ if(but->aspect>1.1) glPixelZoom(1.0/but->aspect, 1.0/but->aspect);
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ if(but->flag & UI_SELECT) {
+ if(but->flag & UI_ACTIVE) {
+ BIF_draw_icon_blended(icon, but->col, COLORSHADE_DARK);
+ } else {
+ BIF_draw_icon_blended(icon, but->col, COLORSHADE_GREY);
+ }
+ }
+ else {
+ if ((but->flag & UI_ACTIVE) && but->type==BUTM) {
+ BIF_draw_icon_blended(icon, BUTMACTIVE, COLORSHADE_MEDIUM);
+ } else if (but->flag & UI_ACTIVE) {
+ BIF_draw_icon_blended(icon, but->col, COLORSHADE_HILITE);
+ } else {
+ BIF_draw_icon_blended(icon, but->col, COLORSHADE_MEDIUM);
+ }
+ }
+
+ glBlendFunc(GL_ONE, GL_ZERO);
+ glDisable(GL_BLEND);
+
+ glPixelZoom(1.0, 1.0);
+}
+
+static void ui_draw_outlineX(float x1, float y1, float x2, float y2, float asp1)
+{
+ float vec[2];
+
+ glBegin(GL_LINE_LOOP);
+ vec[0]= x1+asp1; vec[1]= y1-asp1;
+ glVertex2fv(vec);
+ vec[0]= x2-asp1;
+ glVertex2fv(vec);
+ vec[0]= x2+asp1; vec[1]= y1+asp1;
+ glVertex2fv(vec);
+ vec[1]= y2-asp1;
+ glVertex2fv(vec);
+ vec[0]= x2-asp1; vec[1]= y2+asp1;
+ glVertex2fv(vec);
+ vec[0]= x1+asp1;
+ glVertex2fv(vec);
+ vec[0]= x1-asp1; vec[1]= y2-asp1;
+ glVertex2fv(vec);
+ vec[1]= y1+asp1;
+ glVertex2fv(vec);
+ glEnd();
+
+}
+
+static void ui_emboss_X(BIFColorID bc, float asp, float x1, float y1, float x2, float y2, int flag)
+{
+ /* paper */
+ if(flag & UI_SELECT) {
+ if(flag & UI_ACTIVE) BIF_set_color(bc, COLORSHADE_DARK);
+ else BIF_set_color(bc, COLORSHADE_GREY);
+ }
+ else {
+ if(flag & UI_ACTIVE) BIF_set_color(bc, COLORSHADE_HILITE);
+ else BIF_set_color(bc, COLORSHADE_MEDIUM);
+ }
+
+ glRectf(x1+1, y1+1, x2-1, y2-1);
+
+ x1+= asp;
+ x2-= asp;
+ y1+= asp;
+ y2-= asp;
+
+ /* below */
+ if(flag & UI_SELECT) BIF_set_color(bc, COLORSHADE_MEDIUM);
+ else BIF_set_color(bc, COLORSHADE_DARK);
+ fdrawline(x1, y1, x2, y1);
+
+ /* right */
+ fdrawline(x2, y1, x2, y2);
+
+ /* top */
+ if(flag & UI_SELECT) BIF_set_color(bc, COLORSHADE_DARK);
+ else BIF_set_color(bc, COLORSHADE_WHITE);
+ fdrawline(x1, y2, x2, y2);
+
+ /* left */
+ fdrawline(x1, y1, x1, y2);
+
+ /* outline */
+ glColor3ub(0,0,0);
+ ui_draw_outlineX(x1, y1, x2, y2, asp);
+}
+
+void uiEmboss(float x1, float y1, float x2, float y2, int sel)
+{
+
+ /* below */
+ if(sel) glColor3ub(255,255,255);
+ else glColor3ub(0,0,0);
+ fdrawline(x1, y1, x2, y1);
+
+ /* right */
+ fdrawline(x2, y1, x2, y2);
+
+ /* top */
+ if(sel) glColor3ub(0,0,0);
+ else glColor3ub(255,255,255);
+ fdrawline(x1, y2, x2, y2);
+
+ /* left */
+ fdrawline(x1, y1, x1, y2);
+
+}
+
+/* super minimal button as used in logic menu */
+static void ui_emboss_W(BIFColorID bc, float asp, float x1, float y1, float x2, float y2, int flag)
+{
+
+ x1+= asp;
+ x2-= asp;
+ y1+= asp;
+ y2-= asp;
+
+ /* paper */
+ if(flag & UI_SELECT) {
+ if(flag & UI_ACTIVE) BIF_set_color(bc, COLORSHADE_DARK);
+ else BIF_set_color(bc, COLORSHADE_GREY);
+ }
+ else {
+ if(flag & UI_ACTIVE) BIF_set_color(bc, COLORSHADE_HILITE);
+ else BIF_set_color(bc, COLORSHADE_MEDIUM);
+ }
+
+ glRectf(x1, y1, x2, y2);
+
+ if(flag & UI_SELECT) {
+ BIF_set_color(bc, COLORSHADE_LIGHT);
+
+ /* below */
+ fdrawline(x1, y1, x2, y1);
+
+ /* right */
+ fdrawline(x2, y1, x2, y2);
+ }
+ else if(flag & UI_ACTIVE) {
+ BIF_set_color(bc, COLORSHADE_WHITE);
+
+ /* top */
+ fdrawline(x1, y2, x2, y2);
+
+ /* left */
+ fdrawline(x1, y1, x1, y2);
+ }
+}
+
+/* minimal button with small black outline */
+static void ui_emboss_F(BIFColorID bc, float asp, float x1, float y1, float x2, float y2, int flag)
+{
+ float asp1;
+
+ /* paper */
+ if(flag & UI_SELECT) {
+ if(flag & UI_ACTIVE) BIF_set_color(bc, COLORSHADE_DARK);
+ else BIF_set_color(bc, COLORSHADE_GREY);
+ }
+ else {
+ if(flag & UI_ACTIVE) BIF_set_color(bc, COLORSHADE_HILITE);
+ else BIF_set_color(bc, COLORSHADE_MEDIUM);
+ }
+
+ glRectf(x1+1, y1+1, x2-1, y2-1);
+
+ asp1= asp;
+
+ x1+= asp1;
+ x2-= asp1;
+ y1+= asp1;
+ y2-= asp1;
+
+ /* below */
+ if(flag & UI_SELECT) BIF_set_color(bc, COLORSHADE_WHITE);
+ else BIF_set_color(bc, COLORSHADE_DARK);
+ fdrawline(x1, y1, x2, y1);
+
+ /* right */
+ fdrawline(x2, y1, x2, y2);
+
+ /* top */
+ if(flag & UI_SELECT) BIF_set_color(bc, COLORSHADE_DARK);
+ else BIF_set_color(bc, COLORSHADE_WHITE);
+ fdrawline(x1, y2, x2, y2);
+
+ /* left */
+ fdrawline(x1, y1, x1, y2);
+
+ glColor3ub(0,0,0);
+ fdrawbox(x1-asp1, y1-asp1, x2+asp1, y2+asp1);
+}
+
+/* minimal for menu's */
+static void ui_emboss_M(BIFColorID bc, float asp, float x1, float y1, float x2, float y2, int flag)
+{
+ x1+= 1.0;
+ y1+= 1.0;
+ x2-= 1.0+asp;
+ y2-= 1.0+asp;
+
+
+ if(flag & UI_SELECT) {
+ BIF_set_color(bc, COLORSHADE_LIGHT);
+
+ /* below */
+ fdrawline(x1, y1, x2, y1);
+
+ /* right */
+ fdrawline(x2, y1, x2, y2);
+ }
+ else if(flag & UI_ACTIVE) {
+ BIF_set_color(bc, COLORSHADE_WHITE);
+
+ /* top */
+ fdrawline(x1, y2, x2, y2);
+
+ /* left */
+ fdrawline(x1, y1, x1, y2);
+ }
+ else {
+ BIF_set_color(bc, COLORSHADE_MEDIUM);
+
+ fdrawbox(x1, y1, x2, y2);
+ }
+}
+
+
+/* nothing! */
+static void ui_emboss_N(BIFColorID bc, float asp, float x1, float y1, float x2, float y2, int sel)
+{
+}
+
+/* pulldown menu */
+static void ui_emboss_P(BIFColorID bc, float asp, float x1, float y1, float x2, float y2, int flag)
+{
+
+ BIF_set_color(bc, COLORSHADE_MEDIUM);
+ glRectf(x1, y1, x2, y2);
+
+ if(flag & UI_ACTIVE) {
+ BIF_set_color(BUTMACTIVE, COLORSHADE_MEDIUM);
+ glRectf(x1, y1, x2, y2);
+ }
+
+}
+
+static void ui_emboss_slider(uiBut *but, float fac)
+{
+ float h;
+
+ h= (but->y2-but->y1);
+
+ BIF_set_color(but->col, COLORSHADE_DARK);
+ glRectf(but->x1, but->y1, but->x2, but->y2);
+ glColor3ub(0,0,0);
+ ui_draw_outlineX(but->x1+1, but->y1+1, but->x2-1, but->y2-1, but->aspect);
+
+ /* het blokje */
+ if(but->flag & UI_SELECT) BIF_set_color(but->col, COLORSHADE_LIGHT);
+ else BIF_set_color(but->col, COLORSHADE_GREY);
+ glRects(but->x1+fac, but->y1+1, but->x1+fac+h, but->y2-1);
+
+ BIF_set_color(but->col, COLORSHADE_WHITE);
+ fdrawline(but->x1+fac, but->y2-1, but->x1+fac+h, but->y2-1);
+ fdrawline(but->x1+fac, but->y1+1, but->x1+fac, but->y2-1);
+
+ glColor3ub(0,0,0);
+ fdrawline(but->x1+fac, but->y1+1, but->x1+fac+h, but->y1+1);
+ fdrawline(but->x1+fac+h, but->y1+1, but->x1+fac+h, but->y2-1);
+}
+
+static void ui_draw_but_BUT(uiBut *but)
+{
+ float x;
+
+ but->embossfunc(but->col, but->aspect, but->x1, but->y1, but->x2, but->y2, but->flag);
+
+ if( but->flag & UI_HAS_ICON ) {
+ ui_draw_icon(but, (BIFIconID) (but->icon+but->iconadd));
+ }
+ else if(but->drawstr[0]!=0) {
+ if(but->flag & UI_SELECT) glColor3ub(255,255,255);
+ else glColor3ub(0,0,0);
+
+ if(but->flag & UI_TEXT_LEFT) x= but->x1+4.0;
+ else x= (but->x1+but->x2-but->strwidth+1)/2.0;
+
+ glRasterPos2f( x, (but->y1+but->y2- 9.0)/2.0);
+
+ BMF_DrawString(but->font, but->drawstr+but->ofs);
+ }
+}
+
+static void ui_draw_but_TOG3(uiBut *but)
+{
+ float x;
+
+ but->embossfunc(but->col, but->aspect, but->x1, but->y1, but->x2, but->y2, but->flag);
+
+ if( but->flag & UI_HAS_ICON ) {
+ ui_draw_icon(but, but->icon);
+ }
+ else if(but->drawstr[0]!=0) {
+ if(but->flag & UI_SELECT) {
+ int ok= 0;
+
+ if( but->pointype==CHA ) {
+ if( BTST( *(but->poin+2), but->bitnr )) ok= 1;
+ }
+ else if( but->pointype ==SHO ) {
+ short *sp= (short *)but->poin;
+ if( BTST( sp[1], but->bitnr )) ok= 1;
+ }
+
+ if (ok) {
+ glColor3ub(255, 255, 0);
+ } else {
+ glColor3ub(255, 255, 255);
+ }
+ } else {
+ glColor3ub(0, 0, 0);
+ }
+
+ if(but->flag & UI_TEXT_LEFT) x= but->x1+4.0;
+ else x= (but->x1+but->x2-but->strwidth+1)/2.0;
+
+ glRasterPos2f( x, (but->y1+but->y2- 9.0)/2.0);
+
+ BMF_DrawString(but->font, but->drawstr+but->ofs);
+ }
+}
+
+static void ui_draw_but_TEX(uiBut *but)
+{
+ float x;
+ short pos, sel, t;
+ char ch;
+
+ /* exception for text buttons using embossF */
+ sel= but->flag;
+ if(but->embossfunc==ui_emboss_F) sel |= UI_SELECT;
+
+ but->embossfunc(but->col, but->aspect, but->x1, but->y1, but->x2, but->y2, sel);
+
+ sel= but->flag & UI_SELECT;
+
+ /* draw cursor */
+ if(but->pos != -1) {
+
+ pos= but->pos+strlen(but->str);
+ if(pos >= but->ofs) {
+ ch= but->drawstr[pos];
+ but->drawstr[pos]= 0;
+ t= but->aspect*BMF_GetStringWidth(but->font, but->drawstr+but->ofs) + 3;
+
+ but->drawstr[pos]= ch;
+ glColor3ub(255,0,0);
+
+ glRects(but->x1+t, but->y1+2, but->x1+t+3, but->y2-2);
+ }
+ }
+ if(but->drawstr[0]!=0) {
+ if(sel) glColor3ub(255,255,255);
+ else glColor3ub(0,0,0);
+
+ if(but->flag & UI_TEXT_LEFT) x= but->x1+4.0;
+ else x= (but->x1+but->x2-but->strwidth+1)/2.0;
+
+ glRasterPos2f( x, (but->y1+but->y2- 9.0)/2.0);
+
+ BMF_DrawString(but->font, but->drawstr+but->ofs);
+ }
+}
+
+static void ui_draw_but_BUTM(uiBut *but)
+{
+ float x;
+ short len;
+ char *cpoin;
+
+ but->embossfunc(but->col, but->aspect, but->x1, but->y1, but->x2, but->y2, but->flag);
+
+ if( but->flag & UI_HAS_ICON ) {
+ ui_draw_icon(but, but->icon);
+ }
+ else {
+ if(but->drawstr[0]!=0) {
+ cpoin= strchr(but->drawstr, '|');
+ if(cpoin) *cpoin= 0;
+
+ if(but->embossfunc==ui_emboss_P) {
+ if(but->flag & UI_ACTIVE) glColor3ub(255,255,255);
+ else glColor3ub(0,0,0);
+ } else {
+ glColor3ub(0,0,0);
+ }
+
+ x= but->x1+4.0;
+
+ glRasterPos2f( x, (but->y1+but->y2- 9.0)/2.0);
+ BMF_DrawString(but->font, but->drawstr);
+
+ if(cpoin) {
+ len= BMF_GetStringWidth(but->font, cpoin+1);
+ glRasterPos2f( but->x2 - len*but->aspect-3, (but->y1+but->y2- 9.0)/2.0);
+ BMF_DrawString(but->font, cpoin+1);
+ *cpoin= '|';
+ }
+ }
+ }
+}
+
+static void ui_draw_but_LABEL(uiBut *but)
+{
+ float x;
+ int sel;
+
+ sel= but->min!=0.0;
+
+ if(sel) glColor3ub(255,255,255);
+ else glColor3ub(0,0,0);
+
+ if( but->flag & UI_HAS_ICON ) {
+ ui_draw_icon(but, but->icon);
+ }
+ else if(but->drawstr[0]!=0) {
+
+ if(but->flag & UI_TEXT_LEFT) x= but->x1+4.0;
+ else x= (but->x1+but->x2-but->strwidth+1)/2.0;
+
+ glRasterPos2f( x, (but->y1+but->y2- 9.0)/2.0);
+
+ BMF_DrawString(but->font, but->drawstr+but->ofs);
+ }
+}
+
+static void ui_draw_but_SEPR(uiBut *but)
+{
+ float y= (but->y1+but->y2)/2.0;
+
+ glColor3ub(0,0,0);
+ fdrawline(but->x1, y+but->aspect, but->x2, y+but->aspect);
+ glColor3ub(255,255,255);
+ fdrawline(but->x1, y, but->x2, y);
+}
+
+static void ui_draw_but_LINK(uiBut *but)
+{
+ ui_draw_icon(but, but->icon);
+}
+
+
+static void ui_draw_but(uiBut *but)
+{
+ double value;
+ float fac, x1, y1, x2, y2, *fp;
+ short a;
+ char colr, colg, colb;
+
+ if(but==0) return;
+
+ if(UIfrontbuf) {
+ glDrawBuffer(GL_FRONT);
+ if(but->win==curarea->headwin) curarea->head_swap= WIN_FRONT_OK;
+ else curarea->win_swap= WIN_FRONT_OK;
+ }
+
+ switch (but->type) {
+
+ case BUT:
+ case ROW:
+ case TOG:
+ case TOGR:
+ case TOGN:
+ case ICONTOG:
+ case NUM:
+ case KEYEVT:
+ case IDPOIN:
+ ui_draw_but_BUT(but);
+ break;
+
+ case TEX:
+ ui_draw_but_TEX(but);
+ break;
+
+ case BUTM:
+ case BLOCK:
+ ui_draw_but_BUTM(but);
+ break;
+
+ case ICONROW:
+ ui_draw_but_BUT(but);
+
+ /* teken pijltjes, icon is standaard RGB */
+ a= (but->y1+but->y2)/2;
+
+ glColor3ub(0,0,0);
+ sdrawline((short)(but->x1-1), (short)(a-2), (short)(but->x1-1), (short)(a+2));
+ sdrawline((short)(but->x1-2), (short)(a-1), (short)(but->x1-2), (short)(a+1));
+ sdrawline((short)(but->x1-3), a, (short)(but->x1-3), a);
+ glColor3ub(255,255,255);
+ sdrawline((short)(but->x1-3), (short)(a-1), (short)(but->x1-1), (short)(a-3));
+
+ glColor3ub(0,0,0);
+ sdrawline((short)(but->x2+1), (short)(a-2), (short)(but->x2+1), (short)(a+2));
+ sdrawline((short)(but->x2+2), (short)(a-1), (short)(but->x2+2), (short)(a+1));
+ sdrawline((short)(but->x2+3), a, (short)(but->x2+3), a);
+ glColor3ub(255,255,255);
+ sdrawline((short)(but->x2+3), (short)(a-1), (short)(but->x2+1), (short)(a-3));
+
+ break;
+
+ case MENU:
+
+ ui_draw_but_BUT(but);
+
+ /* als er ruimte is: teken symbooltje */
+ if(but->strwidth+10 < but->x2-but->x1) {
+ int h;
+
+ h= but->y2- but->y1;
+ x1= but->x2-0.66*h; x2= x1+.33*h;
+ y1= but->y1+.42*h; y2= y1+.16*h;
+
+ glColor3ub(0,0,0);
+ glRecti(x1, y1, x2, y2);
+ glColor3ub(255,255,255);
+ glRecti(x1-1, y1+1, x2-1, y2+1);
+ }
+ break;
+
+ case NUMSLI:
+ case HSVSLI:
+
+ ui_draw_but_BUT(but);
+
+ /* de slider */
+
+ x1= but->x1; x2= but->x2;
+ y1= but->y1; y2= but->y2;
+
+ but->x1= (but->x1+but->x2)/2;
+ but->x2-= 9;
+ but->y1= -2+(but->y1+but->y2)/2;
+ but->y2= but->y1+6;
+
+ value= ui_get_but_val(but);
+ fac= (value-but->min)*(but->x2-but->x1-but->y2+but->y1)/(but->max - but->min);
+ ui_emboss_slider(but, fac);
+
+ but->x1= x1; but->x2= x2;
+ but->y1= y1; but->y2= y2;
+
+ break;
+
+ case TOG3:
+ ui_draw_but_TOG3(but);
+ break;
+
+ case LABEL:
+ ui_draw_but_LABEL(but);
+ break;
+
+ case SLI:
+ break;
+
+ case SCROLL:
+ break;
+
+ case SEPR:
+ ui_draw_but_SEPR(but);
+ break;
+
+ case COL:
+ ui_draw_but_BUT(but);
+
+ if( but->pointype==FLO ) {
+ fp= (float *)but->poin;
+ colr= floor(255.0*fp[0]+0.5);
+ colg= floor(255.0*fp[1]+0.5);
+ colb= floor(255.0*fp[2]+0.5);
+ }
+ else {
+ char *cp= (char *)but->poin;
+ colr= cp[0];
+ colg= cp[1];
+ colb= cp[2];
+ }
+ glColor3ub(colr, colg, colb);
+ glRects((short)(but->x1+2), (short)(but->y1+2), (short)(but->x2-2), (short)(but->y2-2));
+ break;
+
+ case LINK:
+ ui_draw_but_LINK(but);
+ break;
+
+ case INLINK:
+ ui_draw_but_LINK(but);
+ break;
+ }
+
+ if(UIfrontbuf) {
+ glFinish();
+ glDrawBuffer(GL_BACK);
+ }
+}
+
+void uiDrawMenuBox(float minx, float miny, float maxx, float maxy)
+{
+ glRectf(minx, miny, maxx, maxy);
+
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+
+ glColor4ub(0, 0, 0, 100);
+ fdrawline(minx+4, miny-1, maxx+1, miny-1);
+ fdrawline(maxx+1, miny-1, maxx+1, maxy-4);
+
+ glColor4ub(0, 0, 0, 75);
+ fdrawline(minx+4, miny-2, maxx+2, miny-2);
+ fdrawline(maxx+2, miny-2, maxx+2, maxy-4);
+
+ glColor4ub(0, 0, 0, 50);
+ fdrawline(minx+4, miny-3, maxx+3, miny-3);
+ fdrawline(maxx+3, miny-3, maxx+3, maxy-4);
+
+ glDisable(GL_BLEND);
+
+ /* below */
+ glColor3ub(0,0,0);
+ fdrawline(minx, miny, maxx, miny);
+
+ /* right */
+ fdrawline(maxx, miny, maxx, maxy);
+
+ /* top */
+ glColor3ub(255,255,255);
+ fdrawline(minx, maxy, maxx, maxy);
+
+ /* left */
+ fdrawline(minx, miny, minx, maxy);
+}
+
+static void ui_draw_linkline(BIFColorID col, uiLinkLine *line)
+{
+ float vec1[2], vec2[2];
+
+ if(line->from==NULL || line->to==NULL) return;
+
+ vec1[0]= (line->from->x1+line->from->x2)/2.0;
+ vec1[1]= (line->from->y1+line->from->y2)/2.0;
+ vec2[0]= (line->to->x1+line->to->x2)/2.0;
+ vec2[1]= (line->to->y1+line->to->y2)/2.0;
+
+ if(line->flag & UI_SELECT) BIF_set_color(col, COLORSHADE_LIGHT);
+ else glColor3ub(0,0,0);
+ fdrawline(vec1[0], vec1[1], vec2[0], vec2[1]);
+}
+
+static void ui_draw_links(uiBlock *block)
+{
+ uiBut *but;
+ uiLinkLine *line;
+
+ but= block->buttons.first;
+ while(but) {
+ if(but->type==LINK && but->link) {
+ line= but->link->lines.first;
+ while(line) {
+ ui_draw_linkline(but->col, line);
+ line= line->next;
+ }
+ }
+ but= but->next;
+ }
+}
+
+
+
+/* ******************* block calc ************************* */
+
+void uiBoundsBlock(uiBlock *block, int addval)
+{
+ uiBut *bt;
+
+ block->minx= block->miny= 10000;
+ block->maxx= block->maxy= -10000;
+
+ bt= block->buttons.first;
+ while(bt) {
+ if(bt->x1 < block->minx) block->minx= bt->x1;
+ if(bt->y1 < block->miny) block->miny= bt->y1;
+
+ if(bt->x2 > block->maxx) block->maxx= bt->x2;
+ if(bt->y2 > block->maxy) block->maxy= bt->y2;
+
+ bt= bt->next;
+ }
+
+ block->minx -= addval;
+ block->miny -= addval;
+ block->maxx += addval;
+ block->maxy += addval;
+}
+
+static void ui_positionblock(uiBlock *block, uiBut *but)
+{
+ /* position block relative to but */
+ uiBut *bt;
+ int xsize, ysize, xof=0, yof=0;
+
+ block->minx= block->miny= 10000;
+ block->maxx= block->maxy= -10000;
+
+ bt= block->buttons.first;
+ while(bt) {
+ if(bt->x1 < block->minx) block->minx= bt->x1;
+ if(bt->y1 < block->miny) block->miny= bt->y1;
+
+ if(bt->x2 > block->maxx) block->maxx= bt->x2;
+ if(bt->y2 > block->maxy) block->maxy= bt->y2;
+
+ bt= bt->next;
+ }
+
+ block->minx-= 2.0; block->miny-= 2.0;
+ block->maxx+= 2.0; block->maxy+= 2.0;
+
+ xsize= block->maxx - block->minx;
+ ysize= block->maxy - block->miny;
+
+ if(but) {
+ rctf butrct;
+ short left=0, right=0, top=0, down=0;
+ short dir1, dir2 = 0;
+
+ butrct.xmin= but->x1; butrct.xmax= but->x2;
+ butrct.ymin= but->y1; butrct.ymax= but->y2;
+
+ /* added this for submenu's... */
+ Mat4CpyMat4(UIwinmat, block->winmat);
+
+ ui_graphics_to_window(block->win, &butrct.xmin, &butrct.ymin);
+ ui_graphics_to_window(block->win, &butrct.xmax, &butrct.ymax);
+
+ if( butrct.xmin-xsize > 0.0) left= 1;
+ if( butrct.xmax+xsize < G.curscreen->sizex) right= 1;
+ if( butrct.ymin-ysize > 0.0) down= 1;
+ if( butrct.ymax+ysize < G.curscreen->sizey) top= 1;
+
+ dir1= block->direction;
+ if(dir1==UI_LEFT || dir1==UI_RIGHT) dir2= UI_DOWN;
+ if(dir1==UI_TOP || dir1==UI_DOWN) dir2= UI_LEFT;
+
+ if(dir1==UI_LEFT && left==0) dir1= UI_RIGHT;
+ if(dir1==UI_RIGHT && right==0) dir1= UI_LEFT;
+ /* this is aligning, not append! */
+ if(dir2==UI_LEFT && right==0) dir2= UI_RIGHT;
+ if(dir2==UI_RIGHT && left==0) dir2= UI_LEFT;
+
+ if(dir1==UI_TOP && top==0) dir1= UI_DOWN;
+ if(dir1==UI_DOWN && down==0) dir1= UI_TOP;
+ if(dir2==UI_TOP && top==0) dir2= UI_DOWN;
+ if(dir2==UI_DOWN && down==0) dir2= UI_TOP;
+
+ if(dir1==UI_LEFT) {
+ xof= but->x1 - block->maxx;
+ if(dir2==UI_TOP) yof= but->y1 - block->miny;
+ else yof= but->y2 - block->maxy;
+ }
+ else if(dir1==UI_RIGHT) {
+ xof= but->x2 - block->minx;
+ if(dir2==UI_TOP) yof= but->y1 - block->miny;
+ else yof= but->y2 - block->maxy;
+ }
+ else if(dir1==UI_TOP) {
+ yof= but->y2 - block->miny+1;
+ if(dir2==UI_RIGHT) xof= but->x2 - block->maxx;
+ else xof= but->x1 - block->minx;
+ }
+ else if(dir1==UI_DOWN) {
+ yof= but->y1 - block->maxy-1;
+ if(dir2==UI_RIGHT) xof= but->x2 - block->maxx;
+ else xof= but->x1 - block->minx;
+ }
+
+
+
+ // apply requested offset in the block
+
+ xof += block->xofs;
+
+ yof += block->yofs;
+
+ }
+
+ /* apply */
+ bt= block->buttons.first;
+ while(bt) {
+ bt->x1 += xof;
+ bt->x2 += xof;
+ bt->y1 += yof;
+ bt->y2 += yof;
+
+ ui_graphics_to_window(block->win, &bt->x1, &bt->y1);
+ ui_graphics_to_window(block->win, &bt->x2, &bt->y2);
+
+ bt->aspect= 1.0;
+
+ bt= bt->next;
+ }
+
+ block->minx += xof;
+ block->miny += yof;
+ block->maxx += xof;
+ block->maxy += yof;
+
+ ui_graphics_to_window(block->win, &block->minx, &block->miny);
+ ui_graphics_to_window(block->win, &block->maxx, &block->maxy);
+
+}
+
+
+static void ui_autofill(uiBlock *block)
+{
+ uiBut *but;
+ float *maxw, *maxh, startx = 0, starty, height = 0;
+ float totmaxh;
+ int rows=0, /* cols=0, */ i, lasti;
+
+
+ /* first count rows */
+ but= block->buttons.last;
+ rows= but->x1+1;
+
+ /* calculate max width / height for each row */
+ maxw= MEM_callocN(sizeof(float)*rows, "maxw");
+ maxh= MEM_callocN(sizeof(float)*rows, "maxh");
+ but= block->buttons.first;
+ while(but) {
+ i= but->x1;
+ if( maxh[i] < but->y2) maxh[i]= but->y2;
+ maxw[i] += but->x2;
+ but= but->next;
+ }
+
+ totmaxh= 0.0;
+ for(i=0; i<rows; i++) totmaxh+= maxh[i];
+
+ /* apply widths/heights */
+ starty= block->maxy;
+ but= block->buttons.first;
+ lasti= -1;
+ while(but) {
+
+ i= but->x1;
+
+ if(i!=lasti) {
+ startx= block->minx;
+ height= (maxh[i]*(block->maxy-block->miny))/totmaxh;
+ starty-= height;
+ lasti= i;
+ }
+
+ but->y1= starty+but->aspect;
+ but->y2= but->y1+height-but->aspect;
+
+ but->x2= (but->x2*(block->maxx-block->minx))/maxw[i];
+ but->x1= startx+but->aspect;
+
+ startx+= but->x2;
+ but->x2+= but->x1-but->aspect;
+
+ ui_check_but(but);
+
+ but= but->next;
+ }
+
+ MEM_freeN(maxw); MEM_freeN(maxh);
+ block->autofill= 0;
+}
+
+static void ui_drawblock_int(uiBlock *block)
+{
+ uiBut *but;
+
+ if(block->autofill) ui_autofill(block);
+ if(block->minx==0.0 && block->maxx==0.0) uiBoundsBlock(block, 0);
+
+ if(block->flag & UI_BLOCK_LOOP) {
+ BIF_set_color(block->col, COLORSHADE_HILITE);
+ uiDrawMenuBox(block->minx, block->miny, block->maxx, block->maxy);
+ }
+
+ for (but= block->buttons.first; but; but= but->next) {
+ ui_draw_but(but);
+ }
+
+ if(UIfrontbuf) glDrawBuffer(GL_FRONT);
+ ui_draw_links(block);
+ if(UIfrontbuf) {
+ glFinish();
+ glDrawBuffer(GL_BACK);
+ }
+}
+
+void uiDrawBlock(uiBlock *block)
+{
+ ui_drawblock_int(block);
+}
+
+/* ************* MENUBUTS *********** */
+
+typedef struct {
+ char *str;
+ int retval;
+} MenuEntry;
+
+typedef struct {
+ char *instr;
+ char *title;
+
+ MenuEntry *items;
+ int nitems, itemssize;
+} MenuData;
+
+static MenuData *menudata_new(char *instr) {
+ MenuData *md= MEM_mallocN(sizeof(*md), "MenuData");
+
+ md->instr= instr;
+ md->title= NULL;
+ md->items= NULL;
+ md->nitems= md->itemssize= 0;
+
+ return md;
+}
+
+static void menudata_set_title(MenuData *md, char *title) {
+ if (!md->title)
+ md->title= title;
+}
+
+static void menudata_add_item(MenuData *md, char *str, int retval) {
+ if (md->nitems==md->itemssize) {
+ int nsize= md->itemssize?(md->itemssize<<1):1;
+ MenuEntry *oitems= md->items;
+
+ md->items= MEM_mallocN(nsize*sizeof(*md->items), "md->items");
+ if (oitems) {
+ memcpy(md->items, oitems, md->nitems*sizeof(*md->items));
+ MEM_freeN(oitems);
+ }
+
+ md->itemssize= nsize;
+ }
+
+ md->items[md->nitems].str= str;
+ md->items[md->nitems].retval= retval;
+ md->nitems++;
+}
+
+static void menudata_free(MenuData *md) {
+ MEM_freeN(md->instr);
+ if (md->items)
+ MEM_freeN(md->items);
+ MEM_freeN(md);
+}
+
+ /**
+ * Parse menu description strings, string is of the
+ * form "[sss%t|]{(sss[%xNN]|), (%l|)}", ssss%t indicates the
+ * menu title, sss or sss%xNN indicates an option,
+ * if %xNN is given then NN is the return value if
+ * that option is selected otherwise the return value
+ * is the index of the option (starting with 1). %l
+ * indicates a seperator.
+ *
+ * @param str String to be parsed.
+ * @retval new menudata structure, free with menudata_free()
+ */
+static MenuData *decompose_menu_string(char *str)
+{
+ char *instr= BLI_strdup(str);
+ MenuData *md= menudata_new(instr);
+ char *nitem= NULL, *s= instr;
+ int nretval= 1, nitem_is_title= 0;
+
+ while (1) {
+ char c= *s;
+
+ if (c=='%') {
+ if (s[1]=='x') {
+ nretval= atoi(s+2);
+
+ *s= '\0';
+ s++;
+ } else if (s[1]=='t') {
+ nitem_is_title= 1;
+
+ *s= '\0';
+ s++;
+ } else if (s[1]=='l') {
+ nitem= "%l";
+ s++;
+ }
+ } else if (c=='|' || c=='\0') {
+ if (nitem) {
+ *s= '\0';
+
+ if (nitem_is_title) {
+ menudata_set_title(md, nitem);
+ nitem_is_title= 0;
+ } else {
+ menudata_add_item(md, nitem, nretval);
+ nretval= md->nitems+1;
+ }
+
+ nitem= NULL;
+ }
+
+ if (c=='\0')
+ break;
+ } else if (!nitem)
+ nitem= s;
+
+ s++;
+ }
+
+ return md;
+}
+
+static void ui_set_name_menu(uiBut *but, int value)
+{
+ MenuData *md;
+ int i;
+
+ md= decompose_menu_string(but->str);
+ for (i=0; i<md->nitems; i++)
+ if (md->items[i].retval==value)
+ strcpy(but->drawstr, md->items[i].str);
+ menudata_free(md);
+}
+
+
+static int ui_do_but_MENU(uiBut *but)
+{
+ uiBlock *block;
+ ListBase listb={NULL, NULL};
+ double fvalue;
+ int width, height, a, xmax, ymax, starty, endx, endy;
+ short startx;
+ int columns=1, rows=0, boxh, event;
+ short x1, y1;
+ short mval[2], mousemove[2];
+ MenuData *md;
+
+ but->flag |= UI_SELECT;
+ ui_draw_but(but);
+
+ block= uiNewBlock(&listb, "menu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
+ block->flag= UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_NUMSELECT;
+
+ md= decompose_menu_string(but->str);
+
+ /* columns and row calculation */
+ columns= (md->nitems+20)/20;
+ if (columns<1) columns= 1;
+
+ rows= (int) md->nitems/columns;
+ if (rows<1) rows= 1;
+
+ while (rows*columns<md->nitems) rows++;
+
+ /* size and location */
+ if(md->title) width= 2*strlen(md->title)+BMF_GetStringWidth(block->curfont, md->title);
+ else width= 0;
+ for(a=0; a<md->nitems; a++) {
+ xmax= BMF_GetStringWidth(block->curfont, md->items[a].str);
+ if(xmax>width) width= xmax;
+ }
+
+ width+= 10;
+ if (width<50) width=50;
+
+ boxh= TBOXH;
+
+ height= rows*boxh;
+ if (md->title) height+= boxh;
+
+ xmax = G.curscreen->sizex;
+ ymax = G.curscreen->sizey;
+
+ getmouseco_sc(mval);
+
+ /* find active item */
+ fvalue= ui_get_but_val(but);
+ for(a=0; a<md->nitems; a++) {
+ if( md->items[a].retval== (int)fvalue ) break;
+ }
+ /* no active item? */
+ if(a==md->nitems) {
+ if(md->title) a= -1;
+ else a= 0;
+ }
+
+ if(a>0) startx = mval[0]-width/2 - ((int)(a)/rows)*width;
+ else startx= mval[0]-width/2;
+ starty = mval[1]-height + boxh/2 + ((a)%rows)*boxh;
+
+ if (md->title) starty+= boxh;
+
+ mousemove[0]= mousemove[1]= 0;
+
+ if(startx<10) {
+ mousemove[0]= 10-startx;
+ startx= 10;
+ }
+ if(starty<10) {
+ mousemove[1]= 10-starty;
+ starty= 10;
+ }
+
+ endx= startx+width*columns;
+ endy= starty+height;
+
+ if(endx>xmax) {
+ mousemove[0]= xmax-endx-10;
+ endx= xmax-10;
+ startx= endx-width*columns;
+ }
+ if(endy>ymax) {
+ mousemove[1]= ymax-endy-10;
+ endy= ymax-10;
+ starty= endy-height;
+ }
+
+ warp_pointer(mval[0]+mousemove[0], mval[1]+mousemove[1]);
+
+ mousemove[0]= mval[0];
+ mousemove[1]= mval[1];
+
+ /* here we go! */
+
+ if(md->title) {
+ uiBut *bt;
+ uiSetCurFont(block, block->font+1);
+ bt= uiDefBut(block, LABEL, 0, md->title, startx, (short)(starty+rows*boxh), (short)width, (short)boxh, NULL, 0.0, 0.0, 0, 0, "");
+ uiSetCurFont(block, block->font);
+ bt->flag= UI_TEXT_LEFT;
+ }
+
+ for(a=0; a<md->nitems; a++) {
+
+ x1= startx + width*((int)a/rows);
+ y1= starty - boxh*(a%rows) + (rows-1)*boxh;
+
+ if (strcmp(md->items[a].str, "%l")==0) {
+ uiDefBut(block, SEPR, B_NOP, "", x1, y1,(short)(width-(rows>1)), (short)(boxh-1), NULL, 0.0, 0.0, 0, 0, "");
+ }
+ else {
+ uiDefBut(block, BUTM|but->pointype, but->retval, md->items[a].str, x1, y1,(short)(width-(rows>1)), (short)(boxh-1), but->poin, (float) md->items[a].retval, 0.0, 0, 0, "");
+ }
+ }
+
+ uiBoundsBlock(block, 3);
+
+ event= uiDoBlocks(&listb, 0);
+
+ /* ready, restore stuff */
+ UIfrontbuf= 1;
+
+ menudata_free(md);
+
+ if((event & UI_RETURN_OUT)==0) warp_pointer(mousemove[0], mousemove[1]);
+
+ but->flag &= ~UI_SELECT;
+ ui_check_but(but);
+ ui_draw_but(but);
+
+ uibut_do_func(but);
+
+ return event;
+}
+
+/* ************* EVENTS ************* */
+
+void uiGetMouse(int win, short *adr)
+{
+ int x, y;
+ float xwin, ywin;
+
+ getmouseco_sc(adr);
+ if (win == G.curscreen->mainwin) return;
+
+ bwin_getsuborigin(win, &x, &y);
+
+ adr[0]-= x;
+ adr[1]-= y;
+
+ xwin= adr[0];
+ ywin= adr[1];
+
+ ui_window_to_graphics(win, &xwin, &ywin);
+
+ adr[0]= (short)(xwin+0.5);
+ adr[1]= (short)(ywin+0.5);
+}
+
+static void ui_is_but_sel(uiBut *but)
+{
+ double value;
+ int lvalue;
+ short push=0, true=1;
+
+ value= ui_get_but_val(but);
+
+ if( but->type==TOGN ) true= 0;
+
+ if( but->bit ) {
+ lvalue= (int)value;
+ if( BTST(lvalue, (but->bitnr)) ) push= true;
+ else push= !true;
+ }
+ else {
+ switch(but->type) {
+ case BUT:
+ push= 0;
+ break;
+ case KEYEVT:
+ if (value==-1) push= 1;
+ break;
+ case TOG:
+ case TOGR:
+ case TOG3:
+ case ICONTOG:
+ if(value!=0.0) push= 1;
+ break;
+ case TOGN:
+ if(value==0.0) push= 1;
+ break;
+ case ROW:
+ if(value == but->max) push= 1;
+ break;
+ case COL:
+ push= 1;
+ break;
+ default:
+ push= 2;
+ break;
+ }
+ }
+
+ if(push==2);
+ else if(push==1) but->flag |= UI_SELECT;
+ else but->flag &= ~UI_SELECT;
+}
+
+static int ui_do_but_BUT(uiBut *but)
+{
+ int activated;
+
+ do {
+ int oflag= but->flag;
+ short mval[2];
+
+ uiGetMouse(mywinget(), mval);
+
+ if (uibut_contains_pt(but, mval))
+ but->flag |= UI_SELECT;
+ else
+ but->flag &= ~UI_SELECT;
+
+ if (but->flag != oflag)
+ ui_draw_but(but);
+
+ PIL_sleep_ms(1);
+ } while (get_mbut() & L_MOUSE);
+
+ activated= (but->flag & UI_SELECT);
+
+ if(activated) {
+ uibut_do_func(but);
+ }
+
+ but->flag &= ~UI_SELECT;
+ ui_draw_but(but);
+
+ return activated?but->retval:0;
+}
+
+static int ui_do_but_KEYEVT(uiBut *but)
+{
+ unsigned short event= 0;
+ short val;
+
+ /* flag for ui_check_but */
+ ui_set_but_val(but, -1);
+ ui_check_but(but);
+ ui_draw_but(but);
+
+ do {
+ event= extern_qread(&val);
+ } while (!event || !val || ELEM(event, MOUSEX, MOUSEY));
+
+ if (!key_event_to_string(event)[0]) event= 0;
+
+ ui_set_but_val(but, (double) event);
+ ui_check_but(but);
+ ui_draw_but(but);
+
+ return (event!=0);
+}
+
+static int ui_do_but_TOG(uiBlock *block, uiBut *but)
+{
+ uiBut *bt;
+ double value;
+ int w, lvalue, push;
+
+ value= ui_get_but_val(but);
+ lvalue= (int)value;
+
+ if(but->bit) {
+ w= BTST(lvalue, but->bitnr);
+ if(w) lvalue = BCLR(lvalue, but->bitnr);
+ else lvalue = BSET(lvalue, but->bitnr);
+
+ if(but->type==TOGR) {
+ if( (get_qual() & LR_SHIFTKEY)==0 ) {
+ lvalue= 1<<(but->bitnr);
+
+ ui_set_but_val(but, (double)lvalue);
+
+ bt= block->buttons.first;
+ while(bt) {
+ if( bt!=but && bt->poin==but->poin ) {
+ ui_is_but_sel(bt);
+ ui_draw_but(bt);
+ }
+ bt= bt->next;
+ }
+ }
+ else {
+ if(lvalue==0) lvalue= 1<<(but->bitnr);
+ }
+ }
+ ui_set_but_val(but, (double)lvalue);
+ if(but->type==ICONTOG) ui_check_but(but);
+ ui_draw_but(but);
+ }
+ else {
+
+ if(value==0.0) push= 1;
+ else push= 0;
+
+ if(but->type==TOGN) push= !push;
+ ui_set_but_val(but, (double)push);
+ if(but->type==ICONTOG) ui_check_but(but);
+ ui_draw_but(but);
+ }
+
+ /* no while loop...this button is used for viewmove */
+
+ uibut_do_func(but);
+
+ return but->retval;
+}
+
+static int ui_do_but_ROW(uiBlock *block, uiBut *but)
+{
+ uiBut *bt;
+
+ ui_set_but_val(but, but->max);
+ ui_draw_but(but);
+
+ bt= block->buttons.first;
+ while(bt) {
+ if( bt!=but && bt->type==ROW ) {
+ if(bt->min==but->min) {
+ ui_is_but_sel(bt);
+ ui_draw_but(bt);
+ }
+ }
+ bt= bt->next;
+ }
+ return but->retval;
+}
+
+static int ui_do_but_TEX(uiBut *but)
+{
+ unsigned short dev;
+ short x, mval[2], len=0, dodraw;
+ char *str, backstr[UI_MAX_DRAW_STR];
+
+ str= (char *)but->poin;
+
+ but->flag |= UI_SELECT;
+
+ uiGetMouse(mywinget(), mval);
+
+ /* calculate cursor pos with current mousecoords */
+ BLI_strncpy(backstr, but->drawstr, UI_MAX_DRAW_STR);
+ but->pos= strlen(backstr)-but->ofs;
+ while((but->aspect*BMF_GetStringWidth(but->font, backstr+but->ofs) + but->x1) > mval[0]) {
+ if (but->pos <= 0) break;
+ but->pos--;
+ backstr[but->pos+but->ofs] = 0;
+ }
+
+ but->pos -= strlen(but->str);
+ but->pos += but->ofs;
+ if(but->pos<0) but->pos= 0;
+
+ /* backup */
+ BLI_strncpy(backstr, but->poin, UI_MAX_DRAW_STR);
+
+ ui_draw_but(but);
+
+ while (get_mbut() & L_MOUSE) BIF_wait_for_statechange();
+ len= strlen(str);
+ but->min= 0.0;
+
+ while(TRUE) {
+ char ascii;
+ short val;
+
+ dodraw= 0;
+ dev = extern_qread_ext(&val, &ascii);
+
+ if(dev==INPUTCHANGE) break;
+ else if(get_mbut() & L_MOUSE) break;
+ else if(get_mbut() & R_MOUSE) break;
+ else if(dev==ESCKEY) break;
+ else if(dev==MOUSEX) val= 0;
+ else if(dev==MOUSEY) val= 0;
+
+ if(ascii) {
+ if( ascii>31 && ascii<127) {
+ if(len < but->max) {
+ for(x= but->max; x>but->pos; x--)
+ str[x]= str[x-1];
+ str[but->pos]= ascii;
+ but->pos++;
+ len++;
+ str[len]= '\0';
+ dodraw= 1;
+ }
+ }
+ }
+ else if(val) {
+
+ if(dev==RIGHTARROWKEY) {
+ if(G.qual & LR_SHIFTKEY) but->pos= strlen(str);
+ else but->pos++;
+ if(but->pos>strlen(str)) but->pos= strlen(str);
+ dodraw= 1;
+ }
+ else if(dev==LEFTARROWKEY) {
+ if(G.qual & LR_SHIFTKEY) but->pos= 0;
+ else if(but->pos>0) but->pos--;
+ dodraw= 1;
+ }
+ else if(dev==PADENTER || dev==RETKEY) {
+ break;
+ }
+ else if(dev==BACKSPACEKEY) {
+ if(len!=0) {
+ if(get_qual() & LR_SHIFTKEY) {
+ str[0]= 0;
+ but->pos= 0;
+ len= 0;
+ dodraw= 1;
+ }
+ else if(but->pos>0) {
+ for(x=but->pos; x<=strlen(str); x++)
+ str[x-1]= str[x];
+ but->pos--;
+ str[--len]='\0';
+ dodraw= 1;
+ }
+ }
+ }
+ }
+ if(dodraw) {
+ ui_check_but(but);
+ ui_draw_but(but);
+ }
+ }
+
+ if(dev==ESCKEY) strcpy(but->poin, backstr);
+ but->pos= -1;
+ but->flag &= ~UI_SELECT;
+
+ uibut_do_func(but);
+
+ ui_check_but(but);
+ ui_draw_but(but);
+
+ if(dev!=ESCKEY) return but->retval;
+ else return 0;
+}
+
+
+static int uiActAsTextBut(uiBut *but)
+{
+ double value;
+ float min, max;
+ int temp, retval, textleft;
+ char str[UI_MAX_DRAW_STR], *point;
+
+
+ value= ui_get_but_val(but);
+ if( but->pointype==FLO ) {
+ sprintf(str, "%.3f", value);
+ }
+ else {
+ sprintf(str, "%d", (int)value);
+ }
+ point= but->poin;
+ but->poin= str;
+ min= but->min;
+ max= but->max;
+ but->min= 0.0;
+ but->max= 15.0;
+ temp= but->type;
+ but->type= TEX;
+ textleft= but->flag & UI_TEXT_LEFT;
+ but->flag |= UI_TEXT_LEFT;
+ ui_check_but(but);
+
+ retval= ui_do_but_TEX(but);
+
+ but->type= temp;
+ but->poin= point;
+ but->min= min;
+ but->max= max;
+ if(textleft==0) but->flag &= ~UI_TEXT_LEFT;
+
+ if( but->pointype==FLO ) value= atof(str);
+ else value= atoi(str);
+
+ if(value<min) value= min;
+ if(value>max) value= max;
+
+ ui_set_but_val(but, value);
+ ui_check_but(but);
+ ui_draw_but(but);
+
+ return retval;
+}
+
+static int ui_do_but_NUM(uiBut *but)
+{
+ double value;
+ float deler, fstart, f, tempf;
+ int lvalue, temp; /* , firsttime=1; */
+ short qual, sx, mval[2], pos=0;
+
+
+ but->flag |= UI_SELECT;
+ ui_draw_but(but);
+
+ uiGetMouse(mywinget(), mval);
+ value= ui_get_but_val(but);
+
+ sx= mval[0];
+ fstart= (value - but->min)/(but->max-but->min);
+ f= fstart;
+
+ temp= (int)value;
+ tempf= value;
+
+ if(get_qual() & LR_SHIFTKEY) { /* make it textbut */
+ if( uiActAsTextBut(but) ) return but->retval;
+ else return 0;
+ }
+
+ /* firsttime: this button can be approached with enter as well */
+ while (get_mbut() & L_MOUSE) {
+ qual= get_qual();
+
+ deler= 500;
+ if( but->pointype!=FLO ) {
+
+ if( (but->max-but->min)<100 ) deler= 200.0;
+ if( (but->max-but->min)<25 ) deler= 50.0;
+
+ }
+ if(qual & LR_SHIFTKEY) deler*= 10.0;
+ if(qual & LR_ALTKEY) deler*= 20.0;
+
+ uiGetMouse(mywinget(), mval);
+
+ if(mval[0] != sx) {
+
+ f+= ((float)(mval[0]-sx))/deler;
+ if(f>1.0) f= 1.0;
+ if(f<0.0) f= 0.0;
+ sx= mval[0];
+ tempf= ( but->min + f*(but->max-but->min));
+
+ if( but->pointype!=FLO ) {
+
+ temp= floor(tempf+.5);
+
+ if(tempf==but->min || tempf==but->max);
+ else if(qual & LR_CTRLKEY) temp= 10*(temp/10);
+
+ if( temp>=but->min && temp<=but->max) {
+
+ value= ui_get_but_val(but);
+ lvalue= (int)value;
+
+ if(temp != lvalue ) {
+ pos= 1;
+ ui_set_but_val(but, (double)temp);
+ ui_check_but(but);
+ ui_draw_but(but);
+
+ uibut_do_func(but);
+ }
+ }
+
+ }
+ else {
+ temp= 0;
+ if(qual & LR_CTRLKEY) {
+ if(tempf==but->min || tempf==but->max);
+ else if(but->max-but->min < 2.10) tempf= 0.1*floor(10*tempf);
+ else if(but->max-but->min < 21.0) tempf= floor(tempf);
+ else tempf= 10.0*floor(tempf/10.0);
+ }
+
+ if( tempf>=but->min && tempf<=but->max) {
+ value= ui_get_but_val(but);
+
+ if(tempf != value ) {
+ pos= 1;
+ ui_set_but_val(but, tempf);
+ ui_check_but(but);
+ ui_draw_but(but);
+ }
+ }
+
+ }
+ }
+ BIF_wait_for_statechange();
+ }
+
+ if(pos==0) { /* plus 1 or minus 1 */
+ if( but->pointype!=FLO ) {
+
+ if(sx<(but->x1+but->x2)/2) temp--;
+ else temp++;
+
+ if( temp>=but->min && temp<=but->max)
+ ui_set_but_val(but, (double)temp);
+
+ }
+ else {
+
+ if(sx<(but->x1+but->x2)/2) tempf-= 0.01*but->a1;
+ else tempf+= 0.01*but->a1;
+
+ if (tempf < but->min) tempf = but->min;
+ if (tempf > but->max) tempf = but->max;
+
+ ui_set_but_val(but, tempf);
+
+ }
+ }
+
+ but->flag &= ~UI_SELECT;
+ ui_check_but(but);
+ ui_draw_but(but);
+
+ return but->retval;
+}
+
+static int ui_do_but_TOG3(uiBut *but)
+{
+
+ if( but->pointype==SHO ) {
+ short *sp= (short *)but->poin;
+
+ if( BTST(sp[1], but->bitnr)) {
+ sp[1]= BCLR(sp[1], but->bitnr);
+ sp[0]= BCLR(sp[0], but->bitnr);
+ }
+ else if( BTST(sp[0], but->bitnr)) {
+ sp[1]= BSET(sp[1], but->bitnr);
+ } else {
+ sp[0]= BSET(sp[0], but->bitnr);
+ }
+ }
+ else {
+ if( BTST(*(but->poin+2), but->bitnr)) {
+ *(but->poin+2)= BCLR(*(but->poin+2), but->bitnr);
+ *(but->poin)= BCLR(*(but->poin), but->bitnr);
+ }
+ else if( BTST(*(but->poin), but->bitnr)) {
+ *(but->poin+2)= BSET(*(but->poin+2), but->bitnr);
+ } else {
+ *(but->poin)= BSET(*(but->poin), but->bitnr);
+ }
+ }
+
+ ui_is_but_sel(but);
+ ui_draw_but(but);
+
+ return but->retval;
+}
+
+static int ui_do_but_ICONROW(uiBut *but)
+{
+ ListBase listb= {NULL, NULL};
+ uiBlock *block;
+ int a;
+
+ but->flag |= UI_SELECT;
+ ui_draw_but(but);
+
+ /* here we go! */
+ block= uiNewBlock(&listb, "menu", UI_EMBOSSP, UI_HELV, but->win);
+ block->flag= UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_NUMSELECT;
+
+ for(a=(int)but->min; a<=(int)but->max; a++) {
+ uiDefIconBut(block, BUTM|but->pointype, but->retval, but->icon+(a-but->min), 0, (short)(18*a), (short)(but->x2-but->x1-4), 18, but->poin, (float)a, 0.0, 0, 0, "");
+ }
+ block->direction= UI_TOP;
+ ui_positionblock(block, but);
+
+ /* the block is made with but-win, but is handled in mainwin space...
+ this is needs better implementation */
+ block->win= G.curscreen->mainwin;
+
+ uiDoBlocks(&listb, 0);
+
+ /* ready, restore stuff */
+ UIfrontbuf= 1;
+
+ but->flag &= ~UI_SELECT;
+ ui_check_but(but);
+ ui_draw_but(but);
+
+ return but->retval;
+}
+
+static int ui_do_but_IDPOIN(uiBut *but)
+{
+ char str[UI_MAX_DRAW_STR];
+ ID *id;
+
+ id= *but->idpoin_idpp;
+ if(id) strcpy(str, id->name+2);
+ else str[0]= 0;
+
+ but->type= TEX;
+ but->poin= str;
+ but->min= 0.0;
+ but->max= 22.0;
+ ui_do_but_TEX(but);
+ but->poin= NULL;
+ but->type= IDPOIN;
+
+ but->idpoin_func(str, but->idpoin_idpp);
+ ui_check_but(but);
+ ui_draw_but(but);
+
+ return but->retval;
+}
+
+static int ui_do_but_SLI(uiBut *but)
+{
+ float f, fstart, tempf = 0.0, deler, value;
+ int sx, h, temp, pos=0, lvalue, redraw;
+ short mval[2], qual;
+ float curmatrix[4][4];
+
+ value= ui_get_but_val(but);
+ uiGetMouse(mywinget(), mval);
+
+ sx= mval[0];
+ h= but->y2-but->y1;
+ fstart= but->max-but->min;
+ fstart= (value - but->min)/fstart;
+ temp= 32767;
+
+ if( but->type==NUMSLI) deler= ( (but->x2-but->x1)/2 - h);
+ else if( but->type==HSVSLI) deler= ( (but->x2-but->x1)/2 - h);
+ else deler= (but->x2-but->x1-h);
+
+
+ while (get_mbut() & L_MOUSE) {
+
+ qual= get_qual();
+ uiGetMouse(mywinget(), mval);
+
+ f= (float)(mval[0]-sx)/deler +fstart;
+
+ if(qual & LR_CTRLKEY) {
+ if(qual & LR_SHIFTKEY) f= floor(f*100.0)/100.0;
+ else f= floor(f*10.0)/10.0;
+ }
+ else if (qual & LR_SHIFTKEY) {
+ f= (f-fstart)/10.0 + fstart;
+ }
+
+ CLAMP(f, 0.0, 1.0);
+ tempf= but->min+f*(but->max-but->min);
+
+ temp= floor(tempf+.5);
+
+ value= ui_get_but_val(but);
+ lvalue= (int) value;
+
+ if( but->pointype!=FLO )
+ redraw= (temp != lvalue);
+ else
+ redraw= (tempf != value);
+
+ if (redraw) {
+ pos= 1;
+
+ ui_set_but_val(but, tempf);
+ ui_check_but(but);
+ ui_draw_but(but);
+
+ if(but->a1) { /* colornummer */
+ uiBut *bt= but->prev;
+ while(bt) {
+ if(bt->retval == but->a1) ui_draw_but(bt);
+ bt= bt->prev;
+ }
+ bt= but->next;
+ while(bt) {
+ if(bt->retval == but->a1) ui_draw_but(bt);
+ bt= bt->next;
+ }
+ }
+ /* save current window matrix (global UIwinmat)
+ because button callback function MIGHT change it
+ - which has until now occured through the Python API
+ */
+ Mat4CpyMat4(curmatrix, UIwinmat);
+ uibut_do_func(but);
+ Mat4CpyMat4(UIwinmat, curmatrix);
+ }
+ else BIF_wait_for_statechange();
+ }
+
+
+ if(temp!=32767 && pos==0) { /* plus 1 of min 1 */
+
+ if( but->type==SLI) f= (float)(mval[0]-but->x1)/(but->x2-but->x1-h);
+ else f= (float)(mval[0]- (but->x1+but->x2)/2)/( (but->x2-but->x1)/2 - h);
+
+ f= but->min+f*(but->max-but->min);
+
+ if( but->pointype!=FLO ) {
+
+ if(f<temp) temp--;
+ else temp++;
+ if( temp>=but->min && temp<=but->max)
+ ui_set_but_val(but, (float)temp);
+
+ }
+ else {
+
+ if(f<tempf) tempf-=.01;
+ else tempf+=.01;
+ if( tempf>=but->min && tempf<=but->max)
+ ui_set_but_val(but, tempf);
+
+ }
+ }
+ ui_check_but(but);
+ ui_draw_but(but);
+
+ return but->retval;
+}
+
+static int ui_do_but_NUMSLI(uiBut *but)
+{
+ short mval[2];
+
+ /* eerste bepalen of het slider is of textbut */
+ uiGetMouse(mywinget(), mval);
+
+ if(mval[0]>= -6+(but->x1+but->x2)/2 ) { /* slider */
+ but->flag |= UI_SELECT;
+ ui_draw_but(but);
+ ui_do_but_SLI(but);
+ but->flag &= ~UI_SELECT;
+ }
+ else {
+ uiActAsTextBut(but);
+ }
+
+ while(get_mbut() & L_MOUSE) BIF_wait_for_statechange();
+
+ ui_draw_but(but);
+
+ /* hsv patch */
+ if(but->type==HSVSLI) {
+
+ if(but->str[0]=='H') {
+ ui_draw_but(but->next);
+ ui_draw_but(but->next->next);
+ }
+ else if(but->str[0]=='S') {
+ ui_draw_but(but->next);
+ ui_draw_but(but->prev);
+ }
+ else if(but->str[0]=='V') {
+ ui_draw_but(but->prev);
+ ui_draw_but(but->prev->prev);
+ }
+ }
+
+ return but->retval;
+}
+
+static int ui_do_but_BLOCK(uiBut *but)
+{
+ uiBlock *block;
+
+ but->flag |= UI_SELECT;
+ ui_draw_but(but);
+
+ block= but->block_func(0);
+
+ ui_positionblock(block, but);
+ block->flag |= UI_BLOCK_LOOP;
+ block->win= G.curscreen->mainwin;
+
+ /* postpone draw, this will cause a new window matrix, first finish all other buttons */
+ block->flag |= UI_BLOCK_REDRAW;
+
+ but->flag &= ~UI_SELECT;
+
+ return 0;
+}
+
+static int ui_do_but_BUTM(uiBut *but)
+{
+
+ ui_set_but_val(but, but->min);
+ UIafterfunc= but->butm_func;
+ UIafterfunc_arg= but->butm_func_arg;
+ UIafterval= but->a2;
+
+ return but->retval;
+}
+
+static int ui_do_but_LABEL(uiBut *but)
+{
+ uibut_do_func(but);
+ return but->retval;
+}
+
+static uiBut *ui_get_valid_link_button(uiBlock *block, uiBut *but, short *mval)
+{
+ uiBut *bt;
+
+ /* find button to link to */
+ for (bt= block->buttons.first; bt; bt= bt->next)
+ if(bt!=but && uibut_contains_pt(bt, mval))
+ break;
+
+ if (bt) {
+ if (but->type==LINK && bt->type==INLINK) {
+ if( but->link->tocode == (int)bt->min ) {
+ return bt;
+ }
+ }
+ else if(but->type==INLINK && bt->type==LINK) {
+ if( bt->link->tocode == (int)but->min ) {
+ return bt;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+static int ui_is_a_link(uiBut *from, uiBut *to)
+{
+ uiLinkLine *line;
+ uiLink *link;
+
+ link= from->link;
+ if(link) {
+ line= link->lines.first;
+ while(line) {
+ if(line->from==from && line->to==to) return 1;
+ line= line->next;
+ }
+ }
+ return 0;
+}
+
+static uiBut *ui_find_inlink(uiBlock *block, void *poin)
+{
+ uiBut *but;
+
+ but= block->buttons.first;
+ while(but) {
+ if(but->type==INLINK) {
+ if(but->poin == poin) return but;
+ }
+ but= but->next;
+ }
+ return NULL;
+}
+
+static void ui_add_link_line(ListBase *listb, uiBut *but, uiBut *bt)
+{
+ uiLinkLine *line;
+
+ line= MEM_callocN(sizeof(uiLinkLine), "linkline");
+ BLI_addtail(listb, line);
+ line->from= but;
+ line->to= bt;
+}
+
+
+void uiComposeLinks(uiBlock *block)
+{
+ uiBut *but, *bt;
+ uiLink *link;
+ void ***ppoin;
+ int a;
+
+ but= block->buttons.first;
+ while(but) {
+ if(but->type==LINK) {
+ link= but->link;
+
+ /* for all pointers in the array */
+ if(link) {
+ if(link->ppoin) {
+ ppoin= link->ppoin;
+ for(a=0; a < *(link->totlink); a++) {
+ bt= ui_find_inlink(block, (*ppoin)[a] );
+ if(bt) {
+ ui_add_link_line(&link->lines, but, bt);
+ }
+ }
+ }
+ else if(link->poin) {
+ bt= ui_find_inlink(block, *(link->poin) );
+ if(bt) {
+ ui_add_link_line(&link->lines, but, bt);
+ }
+ }
+ }
+ }
+ but= but->next;
+ }
+}
+
+static void ui_add_link(uiBut *from, uiBut *to)
+{
+ /* in 'from' we have to add a link to 'to' */
+ uiLink *link;
+ void **oldppoin;
+ int a;
+
+ if(ui_is_a_link(from, to)) {
+ printf("already exists\n");
+ return;
+ }
+
+ link= from->link;
+
+ /* are there more pointers allowed? */
+ if(link->ppoin) {
+ oldppoin= *(link->ppoin);
+
+ (*(link->totlink))++;
+ *(link->ppoin)= MEM_callocN( *(link->totlink)*sizeof(void *), "new link");
+
+ for(a=0; a< (*(link->totlink))-1; a++) {
+ (*(link->ppoin))[a]= oldppoin[a];
+ }
+ (*(link->ppoin))[a]= to->poin;
+
+ if(oldppoin) MEM_freeN(oldppoin);
+ }
+ else {
+ *(link->poin)= to->poin;
+ }
+
+}
+
+static int ui_do_but_LINK(uiBlock *block, uiBut *but)
+{
+ /*
+ * This button only visualizes, the dobutton mode
+ * can add a new link, but then the whole system
+ * should be redrawn/initialized.
+ *
+ */
+ uiBut *bt=0, *bto=NULL;
+ short sval[2], mval[2], mvalo[2], first= 1;
+
+ uiGetMouse(curarea->win, sval);
+ mvalo[0]= sval[0];
+ mvalo[1]= sval[1];
+
+ while (get_mbut() & L_MOUSE) {
+ uiGetMouse(curarea->win, mval);
+
+ if(mval[0]!=mvalo[0] || mval[1]!=mvalo[1] || first) {
+ /* clear completely, because of drawbuttons */
+ bt= ui_get_valid_link_button(block, but, mval);
+ if(bt) {
+ bt->flag |= UI_ACTIVE;
+ ui_draw_but(bt);
+ }
+ if(bto && bto!=bt) {
+ bto->flag &= ~UI_ACTIVE;
+ ui_draw_but(bto);
+ }
+ bto= bt;
+
+ if (!first) {
+ glutil_draw_front_xor_line(sval[0], sval[1], mvalo[0], mvalo[1]);
+ }
+ glutil_draw_front_xor_line(sval[0], sval[1], mval[0], mval[1]);
+
+ mvalo[0]= mval[0];
+ mvalo[1]= mval[1];
+
+ first= 0;
+ }
+ else BIF_wait_for_statechange();
+ }
+
+ if (!first) {
+ glutil_draw_front_xor_line(sval[0], sval[1], mvalo[0], mvalo[1]);
+ }
+
+ if(bt) {
+ if(but->type==LINK) ui_add_link(but, bt);
+ else ui_add_link(bt, but);
+
+ scrarea_queue_winredraw(curarea);
+ }
+
+ return 0;
+}
+
+
+/* ************************************************ */
+
+void uiSetButLock(int val, char *lockstr)
+{
+ UIlock |= val;
+ if (val) UIlockstr= lockstr;
+}
+
+void uiClearButLock()
+{
+ UIlock= 0;
+ UIlockstr= NULL;
+}
+
+/* ********************** NEXT/PREV for arrowkeys etc ************** */
+
+static uiBut *ui_but_prev(uiBut *but)
+{
+ while(but->prev) {
+ but= but->prev;
+ if(but->type!=LABEL && but->type!=SEPR) return but;
+ }
+ return NULL;
+}
+
+static uiBut *ui_but_next(uiBut *but)
+{
+ while(but->next) {
+ but= but->next;
+ if(but->type!=LABEL && but->type!=SEPR) return but;
+ }
+ return NULL;
+}
+
+static uiBut *ui_but_first(uiBlock *block)
+{
+ uiBut *but;
+
+ but= block->buttons.first;
+ while(but) {
+ if(but->type!=LABEL && but->type!=SEPR) return but;
+ but= but->next;
+ }
+ return NULL;
+}
+
+static uiBut *ui_but_last(uiBlock *block)
+{
+ uiBut *but;
+
+ but= block->buttons.last;
+ while(but) {
+ if(but->type!=LABEL && but->type!=SEPR) return but;
+ but= but->prev;
+ }
+ return NULL;
+}
+
+/* *************************************************************** */
+
+
+/* is called when LEFTMOUSE is pressed or released
+ * return: butval or zero
+ */
+static int ui_do_button(uiBlock *block, uiBut *but, uiEvent *uevent)
+{
+ int retval= 0;
+
+ if(but->lock) {
+ if (but->lockstr) {
+ error("%s", but->lockstr);
+ return 0;
+ }
+ }
+ else {
+ if( but->pointype ) { /* er is pointer nodig */
+ if(but->poin==0 ) {
+ printf("DoButton pointer error: %s\n",but->str);
+ return 0;
+ }
+ }
+ }
+
+ block->flag |= UI_BLOCK_BUSY;
+
+ switch(but->type) {
+ case BUT:
+ if(uevent->val) retval= ui_do_but_BUT(but);
+ break;
+
+ case KEYEVT:
+ if(uevent->val) retval= ui_do_but_KEYEVT(but);
+ break;
+
+ case TOG:
+ case TOGR:
+ case ICONTOG:
+ case TOGN:
+ if(uevent->val) {
+ retval= ui_do_but_TOG(block, but);
+ }
+ break;
+
+ case ROW:
+ if(uevent->val) retval= ui_do_but_ROW(block, but);
+ break;
+
+ case SCROLL:
+ /* DrawBut(b, 1); */
+ /* do_scrollbut(b); */
+ /* DrawBut(b,0); */
+ break;
+
+ case NUM:
+ if(uevent->val) retval= ui_do_but_NUM(but);
+ break;
+
+ case SLI:
+ case NUMSLI:
+ case HSVSLI:
+ if(uevent->val) retval= ui_do_but_NUMSLI(but);
+ break;
+
+ case LABEL:
+ if(uevent->val) retval= ui_do_but_LABEL(but);
+ break;
+
+ case TOG3:
+ if(uevent->val) retval= ui_do_but_TOG3(but);
+ break;
+
+ case TEX:
+ if(uevent->val) retval= ui_do_but_TEX(but);
+ break;
+
+ case MENU:
+ if(uevent->val) retval= ui_do_but_MENU(but);
+ break;
+
+ case ICONROW:
+ if(uevent->val) retval= ui_do_but_ICONROW(but);
+ break;
+
+ case IDPOIN:
+ if(uevent->val) retval= ui_do_but_IDPOIN(but);
+ break;
+
+ case BLOCK:
+ if(uevent->val) retval= ui_do_but_BLOCK(but);
+ break;
+
+ case BUTM:
+ retval= ui_do_but_BUTM(but);
+ break;
+
+ case LINK:
+ case INLINK:
+ retval= ui_do_but_LINK(block, but);
+ break;
+ }
+
+ block->flag &= ~UI_BLOCK_BUSY;
+
+ return retval;
+}
+
+static void ui_delete_active_linkline(uiBlock *block)
+{
+ uiBut *but;
+ uiLink *link;
+ uiLinkLine *line, *nline;
+ int a, b;
+
+ but= block->buttons.first;
+ while(but) {
+ if(but->type==LINK && but->link) {
+ line= but->link->lines.first;
+ while(line) {
+
+ nline= line->next;
+
+ if(line->flag & UI_SELECT) {
+ BLI_remlink(&but->link->lines, line);
+
+ link= line->from->link;
+
+ /* are there more pointers allowed? */
+ if(link->ppoin) {
+
+ if(*(link->totlink)==1) {
+ *(link->totlink)= 0;
+ MEM_freeN(*(link->ppoin));
+ *(link->ppoin)= NULL;
+ }
+ else {
+ b= 0;
+ for(a=0; a< (*(link->totlink)); a++) {
+
+ if( (*(link->ppoin))[a] != line->to->poin ) {
+ (*(link->ppoin))[b]= (*(link->ppoin))[a];
+ b++;
+ }
+ }
+ (*(link->totlink))--;
+ }
+ }
+ else {
+ *(link->poin)= NULL;
+ }
+
+ MEM_freeN(line);
+ }
+ line= nline;
+ }
+ }
+ but= but->next;
+ }
+
+ /* temporal! these buttons can be everywhere... */
+ allqueue(REDRAWBUTSGAME, 0);
+}
+
+static void ui_do_active_linklines(uiBlock *block, short *mval)
+{
+ uiBut *but;
+ uiLinkLine *line, *act=NULL;
+ float mindist= 12.0, fac, v1[2], v2[2], v3[3];
+/* int foundone=0; */
+
+ if(mval) {
+ v1[0]= mval[0];
+ v1[1]= mval[1];
+
+ /* find a line close to the mouse */
+ but= block->buttons.first;
+ while(but) {
+ if(but->type==LINK && but->link) {
+ line= but->link->lines.first;
+ while(line) {
+ v2[0]= line->from->x2;
+ v2[1]= (line->from->y1+line->from->y2)/2.0;
+ v3[0]= line->to->x1;
+ v3[1]= (line->to->y1+line->to->y2)/2.0;
+
+ fac= PdistVL2Dfl(v1, v2, v3);
+ if(fac < mindist) {
+ mindist= fac;
+ act= line;
+ }
+ line= line->next;
+ }
+ }
+ but= but->next;
+ }
+ }
+ /* draw */
+ glDrawBuffer(GL_FRONT);
+
+ but= block->buttons.first;
+ while(but) {
+ if(but->type==LINK && but->link) {
+ line= but->link->lines.first;
+ while(line) {
+ if(line==act) {
+ if((line->flag & UI_SELECT)==0) {
+ line->flag |= UI_SELECT;
+ ui_draw_linkline(but->col, line);
+ }
+ }
+ else if(line->flag & UI_SELECT) {
+ line->flag &= ~UI_SELECT;
+ ui_draw_linkline(but->col, line);
+ }
+ line= line->next;
+ }
+ }
+ but= but->next;
+ }
+
+ glFinish();
+ glDrawBuffer(GL_BACK);
+}
+
+/* return:
+ * UI_NOTHING pass event to other ui's
+ * UI_CONT don't pass event to other ui's
+ * UI_RETURN something happened, return, swallow event
+ */
+static int ui_do_block(uiBlock *block, uiEvent *uevent)
+{
+ uiBut *but, *bt;
+ int butevent, event, retval=UI_NOTHING, count, act=0;
+ int inside= 0, active=0;
+
+ if(block->win != mywinget()) return UI_NOTHING;
+
+ /* filter some unwanted events */
+ if(uevent->event==LEFTSHIFTKEY || uevent->event==RIGHTSHIFTKEY) return UI_NOTHING;
+
+ if(block->flag & UI_BLOCK_ENTER_OK) {
+ if(uevent->event == RETKEY && uevent->val) {
+ // printf("qual: %d %d %d\n", uevent->qual, get_qual(), G.qual);
+ if ((G.qual & LR_SHIFTKEY) == 0) {
+ return UI_RETURN_OK;
+ }
+ }
+ }
+
+ Mat4CpyMat4(UIwinmat, block->winmat);
+ uiGetMouse(mywinget(), uevent->mval); /* transformed mouseco */
+
+ /* check boundbox */
+ if( block->minx <= uevent->mval[0] && block->maxx >= uevent->mval[0] ) {
+ if( block->miny <= uevent->mval[1] && block->maxy >= uevent->mval[1] ) {
+ inside= 1;
+ }
+ }
+
+ switch(uevent->event) {
+ case PAD8: case PAD2:
+ case UPARROWKEY:
+ case DOWNARROWKEY:
+ if(inside || (block->flag & UI_BLOCK_LOOP)) {
+ /* arrowkeys: only handle for block_loop blocks */
+ event= 0;
+ if(block->flag & UI_BLOCK_LOOP) {
+ event= uevent->event;
+ if(event==PAD8) event= UPARROWKEY;
+ if(event==PAD2) event= DOWNARROWKEY;
+ }
+ else {
+ if(uevent->event==PAD8) event= UPARROWKEY;
+ if(uevent->event==PAD2) event= DOWNARROWKEY;
+ }
+ if(event && uevent->val) {
+
+ but= block->buttons.first;
+ while(but) {
+
+ but->flag &= ~UI_MOUSE_OVER;
+
+ if(but->flag & UI_ACTIVE) {
+ but->flag &= ~UI_ACTIVE;
+ ui_draw_but(but);
+
+ bt= ui_but_prev(but);
+ if(bt && event==UPARROWKEY) {
+ bt->flag |= UI_ACTIVE;
+ ui_draw_but(bt);
+ break;
+ }
+ bt= ui_but_next(but);
+ if(bt && event==DOWNARROWKEY) {
+ bt->flag |= UI_ACTIVE;
+ ui_draw_but(bt);
+ break;
+ }
+ }
+ but= but->next;
+ }
+
+ /* nothing done */
+ if(but==NULL) {
+
+ if(event==UPARROWKEY) but= ui_but_last(block);
+ else but= ui_but_first(block);
+
+ if(but) {
+ but->flag |= UI_ACTIVE;
+ ui_draw_but(but);
+ }
+ }
+ retval= UI_CONT;
+ }
+ }
+ break;
+
+ case ONEKEY: act= 1;
+ case TWOKEY: if(act==0) act= 2;
+ case THREEKEY: if(act==0) act= 3;
+ case FOURKEY: if(act==0) act= 4;
+ case FIVEKEY: if(act==0) act= 5;
+ case SIXKEY: if(act==0) act= 6;
+ case SEVENKEY: if(act==0) act= 7;
+ case EIGHTKEY: if(act==0) act= 8;
+ case NINEKEY: if(act==0) act= 9;
+ case ZEROKEY: if(act==0) act= 10;
+
+ if( block->flag & UI_BLOCK_NUMSELECT ) {
+
+ if(get_qual() & LR_ALTKEY) act+= 10;
+
+ but= block->buttons.first;
+ count= 0;
+ while(but) {
+ if( but->type!=LABEL && but->type!=SEPR) count++;
+ if(count==act) {
+ but->flag |= UI_ACTIVE;
+ if(uevent->val==1) ui_draw_but(but);
+ else {
+ uevent->event= RETKEY;
+ uevent->val= 1; /* patch: to avoid UI_BLOCK_RET_1 type not working */
+ addqueue(block->winq, RIGHTARROWKEY, 1);
+ }
+ }
+ else if(but->flag & UI_ACTIVE) {
+ but->flag &= ~UI_ACTIVE;
+ ui_draw_but(but);
+ }
+ but= but->next;
+ }
+ }
+
+ break;
+
+ default:
+ if (uevent->event!=RETKEY) { /* when previous command was arrow */
+ but= block->buttons.first;
+ while(but) {
+
+ but->flag &= ~UI_MOUSE_OVER;
+
+ /* check boundbox */
+ if (uibut_contains_pt(but, uevent->mval)) {
+ but->flag |= UI_MOUSE_OVER;
+ UIbuttip= but;
+ }
+ /* hilite case 1 */
+ if(but->flag & UI_MOUSE_OVER) {
+ if( (but->flag & UI_ACTIVE)==0) {
+ but->flag |= UI_ACTIVE;
+ ui_draw_but(but);
+ }
+ }
+ /* hilite case 2 */
+ if(but->flag & UI_ACTIVE) {
+ if( (but->flag & UI_MOUSE_OVER)==0) {
+ but->flag &= ~UI_ACTIVE;
+ ui_draw_but(but);
+ }
+ if(but->flag & UI_ACTIVE) active= 1;
+ }
+
+ but= but->next;
+ }
+
+ /* if there are no active buttons... otherwise clear lines */
+ if(active) ui_do_active_linklines(block, 0);
+ else ui_do_active_linklines(block, uevent->mval);
+
+ }
+ }
+
+ /* middlemouse exception, not for regular blocks */
+ if( (block->flag & UI_BLOCK_LOOP) && uevent->event==MIDDLEMOUSE) uevent->event= LEFTMOUSE;
+
+ /* the final dobutton */
+ but= block->buttons.first;
+ while(but) {
+ if(but->flag & UI_ACTIVE) {
+
+ /* UI_BLOCK_RET_1: not return when val==0 */
+
+ if(uevent->val || (block->flag & UI_BLOCK_RET_1)==0) {
+ if ELEM3(uevent->event, LEFTMOUSE, PADENTER, RETKEY) {
+
+ butevent= ui_do_button(block, but, uevent);
+ if(butevent) addqueue(block->winq, UI_BUT_EVENT, (short)butevent);
+
+ /* i doubt about the next line! */
+ /* if(but->func) mywinset(block->win); */
+
+ if( (block->flag & UI_BLOCK_LOOP) && but->type==BLOCK);
+ else
+ if(/*but->func ||*/ butevent) retval= UI_RETURN_OK;
+ }
+ }
+ }
+
+ but= but->next;
+ }
+
+ /* the linkines... why not make buttons from it? Speed? Memory? */
+ if(uevent->val && (uevent->event==XKEY || uevent->event==DELKEY))
+ ui_delete_active_linkline(block);
+
+ if(block->flag & UI_BLOCK_LOOP) {
+
+ if(inside==0 && uevent->val==1) {
+ if ELEM3(uevent->event, LEFTMOUSE, MIDDLEMOUSE, RIGHTMOUSE)
+ return UI_RETURN_OUT;
+ }
+
+ if(uevent->event==ESCKEY && uevent->val==1) return UI_RETURN_CANCEL;
+
+ /* check outside */
+ if(block->direction==UI_RIGHT) count= 140; else count= 40;
+ if(uevent->mval[0]<block->minx-count) return UI_RETURN_OUT;
+
+ if(uevent->mval[1]<block->miny-40) return UI_RETURN_OUT;
+
+ if(block->direction==UI_LEFT) count= 140; else count= 40;
+ if(uevent->mval[0]>block->maxx+count) return UI_RETURN_OUT;
+
+ if(uevent->mval[1]>block->maxy+40) return UI_RETURN_OUT;
+
+ }
+
+ return retval;
+}
+
+static uiSaveUnder *ui_draw_but_tip(uiBut *but)
+{
+ uiSaveUnder *su;
+ float x1, x2, y1, y2;
+
+ x1= (but->x1+but->x2)/2; x2= 10+x1+ but->aspect*BMF_GetStringWidth(but->font, but->tip);
+ y1= but->y1-19; y2= but->y1-2;
+
+ /* for pulldown menus it doesnt work */
+ if(mywinget()==G.curscreen->mainwin);
+ else {
+ ui_graphics_to_window(mywinget(), &x1, &y1);
+ ui_graphics_to_window(mywinget(), &x2, &y2);
+ }
+
+ if(x2 > G.curscreen->sizex) {
+ x1 -= x2-G.curscreen->sizex;
+ x2= G.curscreen->sizex;
+ }
+ if(y1 < 0) {
+ y1 += 36;
+ y2 += 36;
+ }
+
+ su= ui_bgnpupdraw((int)(x1-1), (int)(y1-1), (int)(x2+4), (int)(y2+4), 0);
+
+ glColor3ub(0xD0, 0xD0, 0xC0);
+ glRectf(x1, y1, x2, y2);
+
+ /* below */
+ glColor3ub(0,0,0);
+ fdrawline(x1, y1, x2, y1);
+ /* right */
+ fdrawline(x2, y1, x2, y2);
+ /* top */
+ glColor3ub(255,255,255);
+ fdrawline(x1, y2, x2, y2);
+ /* left */
+ fdrawline(x1, y1, x1, y2);
+
+ glColor3ub(0,0,0);
+ glRasterPos2f( x1+3, y1+4);
+ BMF_DrawString(but->font, but->tip);
+
+ glFinish(); /* for geforce, to show it in the frontbuffer */
+ return su;
+}
+
+static void ui_do_but_tip(void)
+{
+ uiSaveUnder *su;
+ int time;
+
+ if (UIbuttip && UIbuttip->tip && UIbuttip->tip[0]) {
+ /* Pause for a moment to see if we
+ * should really display the tip
+ * or if the user will keep moving
+ * the pointer.
+ */
+ for (time= 0; time<10; time++) {
+ if (anyqtest())
+ return;
+ else
+ PIL_sleep_ms(2);
+ }
+
+ /* Display the tip, and keep it displayed
+ * as long as the mouse remains on top
+ * of the button that owns it.
+ */
+ su= ui_draw_but_tip(UIbuttip);
+
+ while (1) {
+ char ascii;
+ short val;
+ unsigned short evt= extern_qread_ext(&val, &ascii);
+
+ if (evt==MOUSEX || evt==MOUSEY) {
+ short mouse[2];
+ uiGetMouse(su->oldwin, mouse);
+
+ if (!uibut_contains_pt(UIbuttip, mouse))
+ break;
+ } else {
+ mainqpushback(evt, val, ascii);
+ break;
+ }
+ }
+
+ ui_endpupdraw(su);
+ UIbuttip= NULL;
+ }
+}
+
+/* returns UI_NOTHING, if nothing happened */
+int uiDoBlocks(ListBase *lb, int event)
+{
+ /* return when: firstblock != BLOCK_LOOP
+ * The mainloop is constructed in such a way
+ * that the last mouse event from a sub-block
+ * is passed on to the next block.
+ *
+ * 'cont' is used to make sure you can press a menu button while another
+ * is active. otherwise you have to press twice...
+ */
+
+ uiBlock *block;
+ uiEvent uevent;
+ int retval= UI_NOTHING, cont= 1;
+
+ if(lb->first==0) return UI_NOTHING;
+
+ UIfrontbuf= 1;
+ UIbuttip= NULL;
+ UIafterfunc= NULL; /* to prevent infinite loops, this shouldnt be a global! */
+
+ uevent.qual= G.qual;
+ uevent.event= event;
+ uevent.val= 1;
+
+ while(cont) {
+ block= lb->first;
+ while(block) {
+
+ /* this here, to make sure it also draws when event==0 */
+ if(block->flag & UI_BLOCK_REDRAW) {
+ if( block->flag & UI_BLOCK_LOOP) {
+ block->saveunder= ui_bgnpupdraw((int)block->minx-1, (int)block->miny-4, (int)block->maxx+4, (int)block->maxy+1, 1);
+ }
+ uiDrawBlock(block);
+ block->flag &= ~UI_BLOCK_REDRAW;
+ }
+
+ retval= ui_do_block(block, &uevent);
+ if(retval==UI_CONT || retval & UI_RETURN) break;
+
+ block= block->next;
+ }
+
+ /* this is here, to allow closed loop-blocks (menu's) to return to the previous block */
+ block= lb->first;
+ if(block==NULL || (block->flag & UI_BLOCK_LOOP)==0) cont= 0;
+
+ while( (block= lb->first) && (block->flag & UI_BLOCK_LOOP)) {
+
+ /* this here, for menu buts */
+ if(block->flag & UI_BLOCK_REDRAW) {
+
+ if( block->flag & UI_BLOCK_LOOP) {
+ block->saveunder= ui_bgnpupdraw((int)block->minx-1, (int)block->miny-4, (int)block->maxx+4, (int)block->maxy+1, 1);
+ }
+ uiDrawBlock(block);
+ block->flag &= ~UI_BLOCK_REDRAW;
+ }
+
+ uevent.event= extern_qread(&uevent.val);
+
+ if(uevent.event) {
+
+ retval= ui_do_block(block, &uevent);
+
+ if(retval & UI_RETURN) {
+ /* free this block */
+ ui_endpupdraw(block->saveunder);
+
+ BLI_remlink(lb, block);
+ uiFreeBlock(block);
+ }
+ if(retval==UI_RETURN_OK) {
+ /* free other menus */
+ while( (block= lb->first) && (block->flag & UI_BLOCK_LOOP)) {
+ ui_endpupdraw(block->saveunder);
+ BLI_remlink(lb, block);
+ uiFreeBlock(block);
+ }
+ }
+ }
+
+ /* tooltip */
+ if(retval==UI_NOTHING && (uevent.event==MOUSEX || uevent.event==MOUSEY)) {
+ if(U.flag & TOOLTIPS) ui_do_but_tip();
+ }
+
+ }
+
+ if(retval==UI_CONT || (retval & UI_RETURN_OK)) cont= 0;
+ }
+
+ UIfrontbuf= 0;
+
+
+ if(retval & UI_RETURN_OK) {
+ if(UIafterfunc) UIafterfunc(UIafterfunc_arg, UIafterval);
+ UIafterfunc= NULL;
+ }
+
+ /* tooltip */
+ if(retval==UI_NOTHING && (uevent.event==MOUSEX || uevent.event==MOUSEY)) {
+ if(U.flag & TOOLTIPS) ui_do_but_tip();
+ }
+
+ return retval;
+}
+
+/* ************** DATA *************** */
+
+
+static double ui_get_but_val(uiBut *but)
+{
+ void *poin;
+ double value = 0.0;
+
+ poin= but->poin;
+
+ if(but->type== HSVSLI) {
+ float h, s, v, *fp= (float *) poin;
+
+ rgb_to_hsv(fp[0], fp[1], fp[2], &h, &s, &v);
+
+ switch(but->str[0]) {
+ case 'H': value= h; break;
+ case 'S': value= s; break;
+ case 'V': value= v; break;
+ }
+
+ }
+ else if( but->pointype == CHA ) {
+ value= *(char *)poin;
+ }
+ else if( but->pointype == SHO ) {
+ value= *(short *)poin;
+ }
+ else if( but->pointype == INT ) {
+ value= *(int *)poin;
+ }
+ else if( but->pointype == FLO ) {
+ value= *(float *)poin;
+ }
+
+ return value;
+}
+
+static void ui_set_but_val(uiBut *but, double value)
+{
+ void *poin;
+
+ if(but->pointype==0) return;
+ poin= but->poin;
+
+ /* value is een hsvwaarde: omzetten naar de rgb */
+ if( but->type==HSVSLI ) {
+ float h, s, v, *fp= (float *)but->poin;
+
+ rgb_to_hsv(fp[0], fp[1], fp[2], &h, &s, &v);
+
+ switch(but->str[0]) {
+ case 'H': h= value; break;
+ case 'S': s= value; break;
+ case 'V': v= value; break;
+ }
+
+ hsv_to_rgb(h, s, v, fp, fp+1, fp+2);
+
+ }
+ else if( but->pointype==CHA )
+ *((char *)poin)= (char)value;
+ else if( but->pointype==SHO )
+ *((short *)poin)= (short)value;
+ else if( but->pointype==INT )
+ *((int *)poin)= (int)value;
+ else if( but->pointype==FLO )
+ *((float *)poin)= value;
+
+ /* update select flag */
+ ui_is_but_sel(but);
+
+}
+
+void uiSetCurFont(uiBlock *block, int index)
+{
+
+ if(block->aspect<0.60) {
+ block->curfont= UIfont[index].xl;
+ }
+ else if(block->aspect<1.15) {
+ block->curfont= UIfont[index].large;
+ }
+ else if(block->aspect<1.59) {
+ block->curfont= UIfont[index].medium;
+ }
+ else {
+ block->curfont= UIfont[index].small;
+ }
+
+ if(block->curfont==NULL) block->curfont= UIfont[index].large;
+ if(block->curfont==NULL) block->curfont= UIfont[index].medium;
+ if(block->curfont==NULL) printf("error block no font %s\n", block->name);
+}
+
+void uiDefFont(unsigned int index, void *xl, void *large, void *medium, void *small)
+{
+ if(index>=UI_ARRAY) return;
+
+ UIfont[index].xl= xl;
+ UIfont[index].large= large;
+ UIfont[index].medium= medium;
+ UIfont[index].small= small;
+}
+
+static void ui_free_link(uiLink *link)
+{
+ if(link) {
+ BLI_freelistN(&link->lines);
+ MEM_freeN(link);
+ }
+}
+
+static void ui_free_but(uiBut *but)
+{
+ if(but->str && but->str != but->strdata) MEM_freeN(but->str);
+ ui_free_link(but->link);
+
+ MEM_freeN(but);
+}
+
+void uiFreeBlock(uiBlock *block)
+{
+ uiBut *but;
+
+ if(block->flag & UI_BLOCK_BUSY) printf("var1: %x\n", block);
+
+ while( (but= block->buttons.first) ) {
+ BLI_remlink(&block->buttons, but);
+ ui_free_but(but);
+ }
+
+ MEM_freeN(block);
+ UIbuttip= NULL;
+}
+
+void uiFreeBlocks(ListBase *lb)
+{
+ uiBlock *block;
+
+ while( (block= lb->first) ) {
+ BLI_remlink(lb, block);
+ uiFreeBlock(block);
+ }
+}
+
+void uiFreeBlocksWin(ListBase *lb, int win)
+{
+ uiBlock *block, *blockn;
+
+ block= lb->first;
+ while(block) {
+ blockn= block->next;
+ if(block->win==win) {
+ BLI_remlink(lb, block);
+ uiFreeBlock(block);
+ }
+ block= blockn;
+ }
+}
+
+uiBlock *uiNewBlock(ListBase *lb, char *name, short dt, short font, short win)
+{
+ uiBlock *block;
+
+ /* each listbase only has one block with this name */
+ if(lb) {
+ for (block= lb->first; block; block= block->next)
+ if (BLI_streq(block->name, name))
+ break;
+ if (block) {
+ BLI_remlink(lb, block);
+ uiFreeBlock(block);
+ }
+ }
+
+ block= MEM_callocN(sizeof(uiBlock), "iuBlock");
+ if(lb) BLI_addhead(lb, block); /* at the beginning of the list! */
+
+ strcpy(block->name, name);
+ /* draw win */
+ block->win= win;
+ /* window where queue event should be added, pretty weak this way!
+ this is because the 'mainwin' pup menu's */
+ block->winq= mywinget();
+ block->dt= dt;
+ block->col= BUTGREY;
+
+ /* aspect */
+ bwin_getsinglematrix(win, block->winmat);
+
+ if (win==G.curscreen->mainwin) {
+ block->aspect= 1.0;
+ } else {
+ int getsizex, getsizey;
+
+ bwin_getsize(win, &getsizex, &getsizey);
+ block->aspect= 2.0/( (getsizex)*block->winmat[0][0]);
+ }
+
+ uiSetCurFont(block, font);
+
+ return block;
+}
+
+uiBlock *uiGetBlock(char *name, ScrArea *sa)
+{
+ uiBlock *block= sa->uiblocks.first;
+
+ while(block) {
+ if( strcmp(name, block->name)==0 ) return block;
+ block= block->next;
+ }
+
+ return NULL;
+}
+
+static void ui_check_but(uiBut *but)
+{
+ /* if something changed in the button */
+ ID *id;
+ double value;
+ short pos;
+
+ ui_is_but_sel(but);
+
+ /* name: */
+ switch( but->type ) {
+
+ case MENU:
+
+ if(but->x2 - but->x1 > 24) {
+ value= ui_get_but_val(but);
+ ui_set_name_menu(but, (int)value);
+ }
+ break;
+
+ case NUM:
+ case NUMSLI:
+ case HSVSLI:
+
+ value= ui_get_but_val(but);
+
+ if( but->pointype==FLO ) {
+ if(but->max<10.001) sprintf(but->drawstr, "%s%.3f", but->str, value);
+ else sprintf(but->drawstr, "%s%.2f", but->str, value);
+ }
+ else {
+ sprintf(but->drawstr, "%s%d", but->str, (int)value);
+ }
+ break;
+
+ case IDPOIN:
+ id= *(but->idpoin_idpp);
+ strcpy(but->drawstr, but->str);
+ if(id) strcat(but->drawstr, id->name+2);
+ break;
+
+ case TEX:
+ strcpy(but->drawstr, but->str);
+ strcat(but->drawstr, but->poin);
+ break;
+
+ case KEYEVT:
+ strcpy(but->drawstr, but->str);
+ if (but->flag & UI_SELECT) {
+ strcat(but->drawstr, "Press a key");
+ } else {
+ strcat(but->drawstr, key_event_to_string((short) ui_get_but_val(but)));
+ }
+ break;
+
+ default:
+ strcpy(but->drawstr, but->str);
+
+ }
+
+ if(but->drawstr[0]) but->strwidth= but->aspect*BMF_GetStringWidth(but->font, but->drawstr);
+ else but->strwidth= 0;
+
+ /* automatic width */
+ if(but->x2==0.0) {
+ but->x2= (but->x1+but->strwidth+6);
+ }
+
+ /* calc but->ofs, to draw the string shorter if too long */
+ but->ofs= 0;
+ while(but->strwidth > (int)(but->x2-but->x1-7) ) {
+ but->ofs++;
+
+ if(but->drawstr[but->ofs])
+ but->strwidth= but->aspect*BMF_GetStringWidth(but->font, but->drawstr+but->ofs);
+ else but->strwidth= 0;
+
+ /* textbut exception */
+ if(but->pos != -1) {
+ pos= but->pos+strlen(but->str);
+ if(pos-1 < but->ofs) {
+ pos= but->ofs-pos+1;
+ but->ofs -= pos;
+ if(but->ofs<0) {
+ but->ofs= 0;
+ pos--;
+ }
+ but->drawstr[ strlen(but->drawstr)-pos ]= 0;
+ }
+ }
+
+ if(but->strwidth < 10) break;
+ }
+
+ /* test for min and max, icon sliders, etc */
+
+ switch( but->type ) {
+ case NUM:
+ case SLI:
+ case SCROLL:
+ case NUMSLI:
+ case HSVSLI:
+ value= ui_get_but_val(but);
+ if(value < but->min) value= but->min;
+ if(value > but->max) value= but->max;
+ ui_set_but_val(but, value);
+ break;
+
+ case ICONTOG:
+ if(but->flag & UI_SELECT) but->iconadd= 1;
+ else but->iconadd= 0;
+ break;
+
+ case ICONROW:
+ value= ui_get_but_val(but);
+ but->iconadd= (int)value- (int)(but->min);
+ break;
+ }
+}
+
+static uiBut *ui_def_but(uiBlock *block, int type, int retval, char *str, short x1, short y1, short x2, short y2, void *poin, float min, float max, float a1, float a2, char *tip)
+{
+ uiBut *but;
+ short slen;
+
+ if(type & BUTPOIN) { /* er is pointer nodig */
+ if(poin==0) {
+ /* als pointer nul is wordt button gewist en niet gedefinieerd */
+ BIF_set_color(block->col, COLORSHADE_MEDIUM);
+ glRects(x1, y1, x1+x2, y1+y2);
+ return NULL;
+ }
+ }
+
+ but= MEM_callocN(sizeof(uiBut), "uiBut");
+
+ but->type= type & BUTTYPE;
+ but->pointype= type & BUTPOIN;
+ but->bit= type & BIT;
+ but->bitnr= type & 31;
+
+ BLI_addtail(&block->buttons, but);
+
+ but->retval= retval;
+ if( strlen(str)>=UI_MAX_NAME_STR-1 ) {
+ but->str= MEM_callocN( strlen(str)+2, "uiDefBut");
+ strcpy(but->str, str);
+ }
+ else {
+ but->str= but->strdata;
+ strcpy(but->str, str);
+ }
+ but->x1= x1;
+ but->y1= y1;
+ if(block->autofill) {
+ but->x2= x2;
+ but->y2= y2;
+ }
+ else {
+ but->x2= (x1+x2);
+ but->y2= (y1+y2);
+ }
+ but->poin= poin;
+ but->min= min;
+ but->max= max;
+ but->a1= a1;
+ but->a2= a2;
+ but->tip= tip;
+
+ but->font= block->curfont;
+ but->col= block->col;
+
+ but->lock= UIlock;
+ but->lockstr= UIlockstr;
+
+ but->aspect= block->aspect;
+ but->win= block->win;
+
+ if (but->type==BUTM) {
+ but->butm_func= block->butm_func;
+ but->butm_func_arg= block->butm_func_arg;
+ } else {
+ but->func= block->func;
+ but->func_arg1= block->func_arg1;
+ but->func_arg2= block->func_arg2;
+ }
+
+ if(block->dt==UI_EMBOSSX) but->embossfunc= ui_emboss_X;
+ else if(block->dt==UI_EMBOSSW) but->embossfunc= ui_emboss_W;
+ else if(block->dt==UI_EMBOSSF) but->embossfunc= ui_emboss_F;
+ else if(block->dt==UI_EMBOSSM) but->embossfunc= ui_emboss_M;
+ else if(block->dt==UI_EMBOSSP) but->embossfunc= ui_emboss_P;
+ else but->embossfunc= ui_emboss_N;
+
+ but->pos= -1; /* cursor invisible */
+
+ if(but->type==NUM) { /* spatie toevoegen achter naam */
+ slen= strlen(but->str);
+ if(slen>0 && slen<UI_MAX_NAME_STR-2) {
+ if(but->str[slen-1]!=' ') {
+ but->str[slen]= ' ';
+ but->str[slen+1]= 0;
+ }
+ }
+ }
+
+ if ELEM6(but->type, HSVSLI , NUMSLI, TEX, LABEL, IDPOIN, BLOCK) {
+ but->flag |= UI_TEXT_LEFT;
+ }
+
+ return but;
+}
+
+uiBut *uiDefBut(uiBlock *block, int type, int retval, char *str, short x1, short y1, short x2, short y2, void *poin, float min, float max, float a1, float a2, char *tip)
+{
+ uiBut *but= ui_def_but(block, type, retval, str, x1, y1, x2, y2, poin, min, max, a1, a2, tip);
+
+ ui_check_but(but);
+
+ return but;
+}
+uiBut *uiDefButF(uiBlock *block, int type, int retval, char *str, short x1, short y1, short x2, short y2, float *poin, float min, float max, float a1, float a2, char *tip)
+{
+ return uiDefBut(block, type|FLO, retval, str, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip);
+}
+uiBut *uiDefButI(uiBlock *block, int type, int retval, char *str, short x1, short y1, short x2, short y2, int *poin, float min, float max, float a1, float a2, char *tip)
+{
+ return uiDefBut(block, type|INT, retval, str, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip);
+}
+uiBut *uiDefButS(uiBlock *block, int type, int retval, char *str, short x1, short y1, short x2, short y2, short *poin, float min, float max, float a1, float a2, char *tip)
+{
+ return uiDefBut(block, type|SHO, retval, str, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip);
+}
+uiBut *uiDefButC(uiBlock *block, int type, int retval, char *str, short x1, short y1, short x2, short y2, char *poin, float min, float max, float a1, float a2, char *tip)
+{
+ return uiDefBut(block, type|CHA, retval, str, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip);
+}
+
+uiBut *uiDefIconBut(uiBlock *block, int type, int retval, int icon, short x1, short y1, short x2, short y2, void *poin, float min, float max, float a1, float a2, char *tip)
+{
+ uiBut *but= ui_def_but(block, type, retval, "", x1, y1, x2, y2, poin, min, max, a1, a2, tip);
+
+ but->icon= (BIFIconID) icon;
+ but->flag|= UI_HAS_ICON;
+
+ ui_check_but(but);
+
+ return but;
+}
+
+uiBut *uiDefIconButF(uiBlock *block, int type, int retval, int icon, short x1, short y1, short x2, short y2, float *poin, float min, float max, float a1, float a2, char *tip)
+{
+ return uiDefIconBut(block, type|FLO, retval, icon, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip);
+}
+uiBut *uiDefIconButI(uiBlock *block, int type, int retval, int icon, short x1, short y1, short x2, short y2, int *poin, float min, float max, float a1, float a2, char *tip)
+{
+ return uiDefIconBut(block, type|INT, retval, icon, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip);
+}
+uiBut *uiDefIconButS(uiBlock *block, int type, int retval, int icon, short x1, short y1, short x2, short y2, short *poin, float min, float max, float a1, float a2, char *tip)
+{
+ return uiDefIconBut(block, type|SHO, retval, icon, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip);
+}
+uiBut *uiDefIconButC(uiBlock *block, int type, int retval, int icon, short x1, short y1, short x2, short y2, char *poin, float min, float max, float a1, float a2, char *tip)
+{
+ return uiDefIconBut(block, type|CHA, retval, icon, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip);
+}
+
+void uiAutoBlock(uiBlock *block, float minx, float miny, float sizex, float sizey, int flag)
+{
+ block->minx= minx;
+ block->maxx= minx+sizex;
+ block->miny= miny;
+ block->maxy= miny+sizey;
+
+ block->autofill= flag; /* also check for if it has to be done */
+
+}
+
+void uiSetButLink(uiBut *but, void **poin, void ***ppoin, short *tot, int from, int to)
+{
+ uiLink *link;
+
+ link= but->link= MEM_callocN(sizeof(uiLink), "new uilink");
+
+ link->poin= poin;
+ link->ppoin= ppoin;
+ link->totlink= tot;
+ link->fromcode= from;
+ link->tocode= to;
+}
+
+/* cruft to make uiBlock and uiBut private */
+
+int uiBlocksGetYMin(ListBase *lb)
+{
+ uiBlock *block;
+ int min= 0;
+
+ for (block= lb->first; block; block= block->next)
+ if (block==lb->first || block->miny<min)
+ min= block->miny;
+
+ return min;
+}
+
+int uiBlockGetCol(uiBlock *block)
+{
+ return block->col;
+}
+void uiBlockSetCol(uiBlock *block, int col)
+{
+ block->col= col;
+}
+void uiBlockSetEmboss(uiBlock *block, int emboss)
+{
+ block->dt= emboss;
+}
+void uiBlockSetDirection(uiBlock *block, int direction)
+{
+ block->direction= direction;
+}
+void uiBlockSetFlag(uiBlock *block, int flag)
+{
+ block->flag= flag;
+}
+void uiBlockSetXOfs(uiBlock *block, int xofs)
+{
+ block->xofs= xofs;
+}
+void* uiBlockGetCurFont(uiBlock *block)
+{
+ return block->curfont;
+}
+
+void uiButSetFlag(uiBut *but, int flag)
+{
+ but->flag|= flag;
+}
+
+int uiButGetRetVal(uiBut *but)
+{
+ return but->retval;
+}
+
+
+void uiBlockSetButmFunc(uiBlock *block, void (*menufunc)(void *arg, int event), void *arg)
+{
+ block->butm_func= menufunc;
+ block->butm_func_arg= arg;
+}
+
+void uiBlockSetFunc(uiBlock *block, void (*func)(void *arg1, void *arg2), void *arg1, void *arg2)
+{
+ block->func= func;
+ block->func_arg1= arg1;
+ block->func_arg2= arg2;
+}
+void uiButSetFunc(uiBut *but, void (*func)(void *arg1, void *arg2), void *arg1, void *arg2)
+{
+ but->func= func;
+ but->func_arg1= arg1;
+ but->func_arg2= arg2;
+}
+
+void uiDefIDPoinBut(uiBlock *block, uiIDPoinFuncFP func, int retval, char *str, short x1, short y1, short x2, short y2, void *idpp, char *tip)
+{
+ uiBut *but= ui_def_but(block, IDPOIN, retval, str, x1, y1, x2, y2, NULL, 0.0, 0.0, 0.0, 0.0, tip);
+ but->idpoin_func= func;
+ but->idpoin_idpp= (ID**) idpp;
+ ui_check_but(but);
+}
+
+void uiDefBlockBut(uiBlock *block, uiBlockFuncFP func, void *arg, char *str, short x1, short y1, short x2, short y2, char *tip)
+{
+ uiBut *but= ui_def_but(block, BLOCK, 0, str, x1, y1, x2, y2, arg, 0.0, 0.0, 0.0, 0.0, tip);
+ but->block_func= func;
+ ui_check_but(but);
+}
+
+void uiDefKeyevtButS(uiBlock *block, int retval, char *str, short x1, short y1, short x2, short y2, short *spoin, char *tip)
+{
+ uiBut *but= ui_def_but(block, KEYEVT|SHO, retval, str, x1, y1, x2, y2, spoin, 0.0, 0.0, 0.0, 0.0, tip);
+ ui_check_but(but);
+}
+
+/* ******************** PUPmenu ****************** */
+
+short pupmenu(char *instr)
+{
+ uiBlock *block;
+ ListBase listb= {NULL, NULL};
+ int event;
+ static int lastselected= 0;
+ short width, height, mousexmove = 0, mouseymove, xmax, ymax, mval[2], val= -1;
+ short a, startx, starty, endx, endy, boxh=TBOXH, x1, y1;
+ static char laststring[UI_MAX_NAME_STR];
+ MenuData *md;
+
+ /* block stuff first, need to know the font */
+ block= uiNewBlock(&listb, "menu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
+ uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_RET_1|UI_BLOCK_NUMSELECT);
+
+ md= decompose_menu_string(instr);
+
+ /* size and location, title slightly bigger for bold */
+ if(md->title) width= 2*strlen(md->title)+BMF_GetStringWidth(uiBlockGetCurFont(block), md->title);
+ else width= 0;
+ for(a=0; a<md->nitems; a++) {
+ xmax= BMF_GetStringWidth(uiBlockGetCurFont(block), md->items[a].str);
+ if(xmax>width) width= xmax;
+ }
+ width+= 10;
+
+ height= boxh*md->nitems;
+
+ xmax = G.curscreen->sizex;
+ ymax = G.curscreen->sizey;
+
+ getmouseco_sc(mval);
+
+ if(strncmp(laststring, instr, UI_MAX_NAME_STR-1)!=0) lastselected= 0;
+ BLI_strncpy(laststring, instr, UI_MAX_NAME_STR);
+
+ startx= mval[0]-width/2;
+ if(lastselected>=0 && lastselected<md->nitems) {
+ starty= mval[1]-height+boxh/2+lastselected*boxh;
+ }
+ else starty= mval[1]-height/2;
+
+ mouseymove= 0;
+
+ if(startx<10) startx= 10;
+ if(starty<10) {
+ mouseymove= 10-starty;
+ starty= 10;
+ }
+
+ endx= startx+width;
+ endy= starty+height;
+ if(endx>xmax) {
+ endx= xmax-10;
+ startx= endx-width;
+ }
+ if(endy>ymax-20) {
+ mouseymove= ymax-endy-20;
+ endy= ymax-20;
+ starty= endy-height;
+
+ }
+
+ if(mouseymove) {
+ warp_pointer(mval[0], mouseymove+mval[1]);
+ mousexmove= mval[0];
+ mouseymove= mval[1];
+ }
+
+ /* here we go! */
+ if(md->title) {
+ uiBut *bt;
+ uiSetCurFont(block, UI_HELVB);
+ bt= uiDefBut(block, LABEL, 0, md->title, startx, (short)(starty+md->nitems*boxh), width, boxh, NULL, 0.0, 0.0, 0, 0, "");
+ bt->flag= UI_TEXT_LEFT;
+ uiSetCurFont(block, UI_HELV);
+ }
+
+ y1= starty + boxh*(md->nitems-1);
+ x1= startx;
+ for(a=0; a<md->nitems; a++, y1-=boxh) {
+ char *name= md->items[a].str;
+
+ if( strcmp(name, "%l")==0) {
+ uiDefBut(block, SEPR, B_NOP, "", x1, y1, width, boxh, NULL, 0, 0.0, 0, 0, "");
+ }
+ else {
+ uiDefButS(block, BUTM, B_NOP, name, x1, y1, width, boxh-1, &val, (float) md->items[a].retval, 0.0, 0, 0, "");
+ }
+ }
+
+ uiBoundsBlock(block, 2);
+
+ event= uiDoBlocks(&listb, 0);
+
+ /* calculate last selected */
+ lastselected= 0;
+ for(a=0; a<md->nitems; a++) {
+ if(val==md->items[a].retval) lastselected= a;
+ }
+
+ /* ready, restore stuff */
+ UIfrontbuf= 0;
+
+ menudata_free(md);
+
+ if(mouseymove && (event & UI_RETURN_OUT)==0) warp_pointer(mousexmove, mouseymove);
+ return val;
+}
+
+short pupmenu_col(char *instr, int maxrow)
+{
+ uiBlock *block;
+ ListBase listb= {NULL, NULL};
+ int columns, rows;
+ short mousemove[2], mval[2], event;
+ int width, height, xmax, ymax, val= -1;
+ int a, startx, starty, endx, endy, boxh=TBOXH, x1, y1;
+ MenuData *md;
+
+ block= uiNewBlock(&listb, "menu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
+ uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_NUMSELECT);
+
+ md= decompose_menu_string(instr);
+
+ /* collumns and row calculation */
+ columns= (md->nitems+maxrow)/maxrow;
+ if (columns<1) columns= 1;
+
+ rows= (int) md->nitems/columns;
+ if (rows<1) rows= 1;
+
+ while (rows*columns<md->nitems) rows++;
+
+ /* size and location */
+ if(md->title) width= 2*strlen(md->title)+BMF_GetStringWidth(uiBlockGetCurFont(block), md->title);
+ else width= 0;
+ for(a=0; a<md->nitems; a++) {
+ xmax= BMF_GetStringWidth(uiBlockGetCurFont(uiBlockGetCurFont(block)), md->items[a].str);
+ if(xmax>width) width= xmax;
+ }
+
+ width+= 10;
+ if (width<50) width=50;
+
+ boxh= TBOXH;
+
+ height= rows*boxh;
+ if (md->title) height+= boxh;
+
+ xmax = G.curscreen->sizex;
+ ymax = G.curscreen->sizey;
+
+ getmouseco_sc(mval);
+
+ /* find active item */
+#if 0
+ fvalue= ui_get_but_val(but);
+ for(a=0; a<md->nitems; a++) {
+ if( md->items[a].retval== (int)fvalue ) break;
+ }
+#endif
+ /* no active item? */
+ if(a==md->nitems) {
+ if(md->title) a= -1;
+ else a= 0;
+ }
+
+ if(a>0)
+ startx = mval[0]-width/2 - ((int)(a)/rows)*width;
+ else
+ startx= mval[0]-width/2;
+ starty = mval[1]-height + boxh/2 + ((a)%rows)*boxh;
+
+ if (md->title) starty+= boxh;
+
+ mousemove[0]= mousemove[1]= 0;
+
+ if(startx<10) {
+ mousemove[0]= 10-startx;
+ startx= 10;
+ }
+ if(starty<10) {
+ mousemove[1]= 10-starty;
+ starty= 10;
+ }
+
+ endx= startx+width*columns;
+ endy= starty+height;
+
+ if(endx>xmax) {
+ mousemove[0]= xmax-endx-10;
+ endx= xmax-10;
+ startx= endx-width*columns;
+ }
+ if(endy>ymax) {
+ mousemove[1]= ymax-endy-10;
+ endy= ymax-10;
+ starty= endy-height;
+ }
+
+ warp_pointer(mval[0]+mousemove[0], mval[1]+mousemove[1]);
+
+ mousemove[0]= mval[0];
+ mousemove[1]= mval[1];
+
+ /* here we go! */
+
+ if(md->title) {
+ uiBut *bt;
+ uiSetCurFont(block, UI_HELVB);
+ bt= uiDefBut(block, LABEL, 0, md->title, startx, (short)(starty+rows*boxh), (short)width, (short)boxh, NULL, 0.0, 0.0, 0, 0, "");
+ uiSetCurFont(block, UI_HELV);
+ bt->flag= UI_TEXT_LEFT;
+ }
+
+ for(a=0; a<md->nitems; a++) {
+
+ x1= startx + width*((int)a/rows);
+ y1= starty - boxh*(a%rows) + (rows-1)*boxh;
+
+ uiDefButI(block, BUTM, B_NOP, md->items[a].str, x1, y1, (short)(width-(rows>1)), (short)(boxh-1), &val, (float)md->items[a].retval, 0.0, 0, 0, "");
+ }
+
+ uiBoundsBlock(block, 3);
+
+ event= uiDoBlocks(&listb, 0);
+
+ /* ready, restore stuff */
+ UIfrontbuf= 1;
+
+ menudata_free(md);
+
+ if((event & UI_RETURN_OUT)==0) warp_pointer(mousemove[0], mousemove[1]);
+
+ return val;
+}
+
diff --git a/source/blender/src/keyval.c b/source/blender/src/keyval.c
new file mode 100644
index 00000000000..2390bc59d4e
--- /dev/null
+++ b/source/blender/src/keyval.c
@@ -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 *****
+ */
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+
+
+#include "BIF_keyval.h"
+
+#include "blendef.h"
+
+#include "mydevice.h"
+
+char *key_event_to_string(unsigned short event)
+{
+
+ switch(event) {
+ case AKEY:
+ return "A";
+ break;
+ case BKEY:
+ return "B";
+ break;
+ case CKEY:
+ return "C";
+ break;
+ case DKEY:
+ return "D";
+ break;
+ case EKEY:
+ return "E";
+ break;
+ case FKEY:
+ return "F";
+ break;
+ case GKEY:
+ return "G";
+ break;
+ case HKEY:
+ return "H";
+ break;
+ case IKEY:
+ return "I";
+ break;
+ case JKEY:
+ return "J";
+ break;
+ case KKEY:
+ return "K";
+ break;
+ case LKEY:
+ return "L";
+ break;
+ case MKEY:
+ return "M";
+ break;
+ case NKEY:
+ return "N";
+ break;
+ case OKEY:
+ return "O";
+ break;
+ case PKEY:
+ return "P";
+ break;
+ case QKEY:
+ return "Q";
+ break;
+ case RKEY:
+ return "R";
+ break;
+ case SKEY:
+ return "S";
+ break;
+ case TKEY:
+ return "T";
+ break;
+ case UKEY:
+ return "U";
+ break;
+ case VKEY:
+ return "V";
+ break;
+ case WKEY:
+ return "W";
+ break;
+ case XKEY:
+ return "X";
+ break;
+ case YKEY:
+ return "Y";
+ break;
+ case ZKEY:
+ return "Z";
+ break;
+
+ case ZEROKEY:
+ return "Zero";
+ break;
+ case ONEKEY:
+ return "One";
+ break;
+ case TWOKEY:
+ return "Two";
+ break;
+ case THREEKEY:
+ return "Three";
+ break;
+ case FOURKEY:
+ return "Four";
+ break;
+ case FIVEKEY:
+ return "Five";
+ break;
+ case SIXKEY:
+ return "Six";
+ break;
+ case SEVENKEY:
+ return "Seven";
+ break;
+ case EIGHTKEY:
+ return "Eight";
+ break;
+ case NINEKEY:
+ return "Nine";
+ break;
+
+ case LEFTCTRLKEY:
+ return "Leftctrl";
+ break;
+ case LEFTALTKEY:
+ return "Leftalt";
+ break;
+ case RIGHTALTKEY:
+ return "Rightalt";
+ break;
+ case RIGHTCTRLKEY:
+ return "Rightctrl";
+ break;
+ case RIGHTSHIFTKEY:
+ return "Rightshift";
+ break;
+ case LEFTSHIFTKEY:
+ return "Leftshift";
+ break;
+
+ case ESCKEY:
+ return "Esc";
+ break;
+ case TABKEY:
+ return "Tab";
+ break;
+ case RETKEY:
+ return "Ret";
+ break;
+ case SPACEKEY:
+ return "Space";
+ break;
+ case LINEFEEDKEY:
+ return "Linefeed";
+ break;
+ case BACKSPACEKEY:
+ return "Backspace";
+ break;
+ case DELKEY:
+ return "Del";
+ break;
+ case SEMICOLONKEY:
+ return "Semicolon";
+ break;
+ case PERIODKEY:
+ return "Period";
+ break;
+ case COMMAKEY:
+ return "Comma";
+ break;
+ case QUOTEKEY:
+ return "Quote";
+ break;
+ case ACCENTGRAVEKEY:
+ return "Accentgrave";
+ break;
+ case MINUSKEY:
+ return "Minus";
+ break;
+ case SLASHKEY:
+ return "Slash";
+ break;
+ case BACKSLASHKEY:
+ return "Backslash";
+ break;
+ case EQUALKEY:
+ return "Equal";
+ break;
+ case LEFTBRACKETKEY:
+ return "Leftbracket";
+ break;
+ case RIGHTBRACKETKEY:
+ return "Rightbracket";
+ break;
+
+ case LEFTARROWKEY:
+ return "Leftarrow";
+ break;
+ case DOWNARROWKEY:
+ return "Downarrow";
+ break;
+ case RIGHTARROWKEY:
+ return "Rightarrow";
+ break;
+ case UPARROWKEY:
+ return "Uparrow";
+ break;
+
+ case PAD2:
+ return "Pad2";
+ break;
+ case PAD4:
+ return "Pad4";
+ break;
+ case PAD6:
+ return "Pad6";
+ break;
+ case PAD8:
+ return "Pad8";
+ break;
+ case PAD1:
+ return "Pad1";
+ break;
+ case PAD3:
+ return "Pad3";
+ break;
+ case PAD5:
+ return "Pad5";
+ break;
+ case PAD7:
+ return "Pad7";
+ break;
+ case PAD9:
+ return "Pad9";
+ break;
+
+ case PADPERIOD:
+ return "Padperiod";
+ break;
+ case PADSLASHKEY:
+ return "Padslash";
+ break;
+ case PADASTERKEY:
+ return "Padaster";
+ break;
+
+ case PAD0:
+ return "Pad0";
+ break;
+ case PADMINUS:
+ return "Padminus";
+ break;
+ case PADENTER:
+ return "Padenter";
+ break;
+ case PADPLUSKEY:
+ return "Padplus";
+ break;
+
+ case F1KEY:
+ return "F1";
+ break;
+ case F2KEY:
+ return "F2";
+ break;
+ case F3KEY:
+ return "F3";
+ break;
+ case F4KEY:
+ return "F4";
+ break;
+ case F5KEY:
+ return "F5";
+ break;
+ case F6KEY:
+ return "F6";
+ break;
+ case F7KEY:
+ return "F7";
+ break;
+ case F8KEY:
+ return "F8";
+ break;
+ case F9KEY:
+ return "F9";
+ break;
+ case F10KEY:
+ return "F10";
+ break;
+ case F11KEY:
+ return "F11";
+ break;
+ case F12KEY:
+ return "F12";
+ break;
+
+ case PAUSEKEY:
+ return "Pause";
+ break;
+ case INSERTKEY:
+ return "Insert";
+ break;
+ case HOMEKEY:
+ return "Home";
+ break;
+ case PAGEUPKEY:
+ return "Pageup";
+ break;
+ case PAGEDOWNKEY:
+ return "Pagedown";
+ break;
+ case ENDKEY:
+ return "End";
+ break;
+ }
+
+ return "";
+}
diff --git a/source/blender/src/mainqueue.c b/source/blender/src/mainqueue.c
new file mode 100644
index 00000000000..ac78beb9440
--- /dev/null
+++ b/source/blender/src/mainqueue.c
@@ -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 *****
+ *
+ * Just the functions to maintain a central event
+ * queue.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "BIF_mainqueue.h"
+
+typedef struct {
+ unsigned short event;
+ short val;
+ char ascii;
+} QEvent;
+
+static QEvent mainqueue[MAXQUEUE];
+static unsigned int nevents= 0;
+
+unsigned short mainqread(short *val, char *ascii)
+{
+ if (nevents) {
+ nevents--;
+
+ *val= mainqueue[nevents].val;
+ *ascii= mainqueue[nevents].ascii;
+ return mainqueue[nevents].event;
+ } else
+ return 0;
+}
+
+void mainqenter(unsigned short event, short val)
+{
+ mainqenter_ext(event, val, 0);
+}
+
+void mainqenter_ext(unsigned short event, short val, char ascii)
+{
+ if (!event)
+ return;
+
+ if (nevents<MAXQUEUE) {
+ memmove(mainqueue+1, mainqueue, sizeof(*mainqueue)*nevents);
+
+ mainqueue[0].event= event;
+ mainqueue[0].val= val;
+ mainqueue[0].ascii= ascii;
+
+ nevents++;
+ }
+}
+
+void mainqpushback(unsigned short event, short val, char ascii)
+{
+ if (nevents<MAXQUEUE) {
+ mainqueue[nevents].event= event;
+ mainqueue[nevents].val= val;
+ mainqueue[nevents].ascii= ascii;
+ nevents++;
+ }
+}
+
+unsigned short mainqtest()
+{
+ if (nevents)
+ return mainqueue[nevents-1].event;
+ else
+ return 0;
+}
diff --git a/source/blender/src/mywindow.c b/source/blender/src/mywindow.c
new file mode 100644
index 00000000000..cf6d002ee5f
--- /dev/null
+++ b/source/blender/src/mywindow.c
@@ -0,0 +1,645 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * vervanging voor een aantal fie's zoals swinopen, winset, (zie onder)
+ * dit alles omdat GL en X te traag zijn
+ * feb: Opengl en toch maar naar X!
+ */
+
+#include <string.h>
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+#include "BLI_gsqueue.h"
+
+#include "DNA_screen_types.h"
+
+#include "BKE_global.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+#include "BIF_mywindow.h"
+#include "BIF_screen.h"
+
+#include "mydevice.h"
+#include "blendef.h"
+
+#include "winlay.h"
+
+
+typedef struct {
+ unsigned short event;
+ short val;
+ char ascii;
+} QEvent;
+
+typedef struct {
+ struct bWindow *next, *prev;
+ int id, pad;
+
+ int xmin, xmax, ymin, ymax;
+ float viewmat[4][4], winmat[4][4];
+
+ GSQueue *qevents;
+} bWindow;
+
+/* globals */
+static Window *winlay_mainwindow;
+static int curswin=0;
+static bWindow *swinarray[MAXWIN]= {0};
+static bWindow mainwindow, renderwindow;
+static int mainwin_color_depth;
+
+void mywindow_init_mainwin(Window *win, int orx, int ory, int sizex, int sizey)
+{
+ int r, g, b;
+
+ winlay_mainwindow= win;
+
+ swinarray[1]= &mainwindow;
+ curswin= 1;
+
+ mainwindow.xmin= orx;
+ mainwindow.ymin= ory;
+ mainwindow.xmax= orx+sizex-1;
+ mainwindow.ymax= ory+sizey-1;
+ mainwindow.qevents= NULL;
+
+ myortho2(-0.5, (float)sizex-0.5, -0.5, (float)sizey-0.5);
+ glLoadIdentity();
+
+ glGetFloatv(GL_PROJECTION_MATRIX, (float *)mainwindow.winmat);
+ glGetFloatv(GL_MODELVIEW_MATRIX, (float *)mainwindow.viewmat);
+
+ glGetIntegerv(GL_RED_BITS, &r);
+ glGetIntegerv(GL_GREEN_BITS, &g);
+ glGetIntegerv(GL_BLUE_BITS, &b);
+
+ mainwin_color_depth= r + g + b;
+}
+
+/* XXXXXXXXXXXXXXXX very hacky, not allowed to release
+ * again after 2.24
+ */
+void mywindow_build_and_set_renderwin(void)
+{
+ glGetFloatv(GL_PROJECTION_MATRIX, (float *)renderwindow.winmat);
+ glGetFloatv(GL_MODELVIEW_MATRIX, (float *)renderwindow.viewmat);
+
+ swinarray[2]= &renderwindow;
+ renderwindow.qevents= NULL;
+
+ curswin= 2;
+}
+
+/* ------------------------------------------------------------------------- */
+
+ /* XXXXX, remove later */
+static bWindow *bwin_from_winid(int winid)
+{
+ bWindow *bwin= swinarray[winid];
+ if (!bwin) {
+ printf("bwin_from_winid: Internal error, bad winid: %d\n", winid);
+ }
+ return bwin;
+}
+
+int bwin_qtest(int winid)
+{
+ return !BLI_gsqueue_is_empty(bwin_from_winid(winid)->qevents);
+}
+unsigned short bwin_qread(int winid, short *val_r, char *ascii_r)
+{
+ if (bwin_qtest(winid)) {
+ QEvent evt;
+ BLI_gsqueue_pop(bwin_from_winid(winid)->qevents, &evt);
+ *val_r= evt.val;
+ *ascii_r= evt.ascii;
+ return evt.event;
+ } else {
+ *val_r= 0;
+ return 0;
+ }
+}
+void bwin_qadd(int winid, unsigned short event, short val, char ascii)
+{
+ QEvent evt;
+ evt.event= event;
+ evt.val= val;
+ evt.ascii= ascii;
+ BLI_gsqueue_push(bwin_from_winid(winid)->qevents, &evt);
+}
+
+/* ------------------------------------------------------------------------- */
+
+void bwin_get_rect(int winid, rcti *rect_r)
+{
+ bWindow *win= bwin_from_winid(winid);
+
+ rect_r->xmin= win->xmin;
+ rect_r->ymin= win->ymin;
+ rect_r->xmax= win->xmax;
+ rect_r->ymax= win->ymax;
+}
+
+void bwin_getsize(int win, int *x, int *y)
+{
+ if(win<4) {
+ if (win==1) {
+ window_get_size(winlay_mainwindow, x, y);
+ } else {
+ printf("bwin_getsize: Internal error, bad winid: %d\n", win);
+ *x= *y= 0;
+ }
+ } else {
+ bWindow *bwin= swinarray[win];
+ if (bwin) {
+ *x= bwin->xmax-bwin->xmin+1;
+ *y= bwin->ymax-bwin->ymin+1;
+ }
+ }
+}
+
+void bwin_getsuborigin(int win, int *x, int *y)
+{
+ if(win<4) {
+ *x= *y= 0;
+ } else {
+ bWindow *bwin= swinarray[win];
+ if (bwin) {
+ *x= bwin->xmin;
+ *y= bwin->ymin;
+ }
+ }
+}
+
+void bwin_getsinglematrix(int winid, float mat[][4])
+{
+ bWindow *win;
+ float matview[4][4], matproj[4][4];
+
+ win= swinarray[winid];
+ if(win==0) {
+ glGetFloatv(GL_PROJECTION_MATRIX, (float *)matproj);
+ glGetFloatv(GL_MODELVIEW_MATRIX, (float *)matview);
+ Mat4MulMat4(mat, matview, matproj);
+ }
+ else {
+ Mat4MulMat4(mat, win->viewmat, win->winmat);
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
+void bwin_load_viewmatrix(int winid, float mat[][4])
+{
+ bWindow *win= bwin_from_winid(winid);
+
+ glLoadMatrixf(mat);
+ Mat4CpyMat4(win->viewmat, mat);
+}
+void bwin_load_winmatrix(int winid, float mat[][4])
+{
+ bWindow *win= bwin_from_winid(winid);
+
+ glLoadMatrixf(mat);
+ Mat4CpyMat4(win->winmat, mat);
+}
+
+void bwin_get_viewmatrix(int winid, float mat[][4])
+{
+ bWindow *win= bwin_from_winid(winid);
+ Mat4CpyMat4(mat, win->viewmat);
+}
+void bwin_get_winmatrix(int winid, float mat[][4])
+{
+ bWindow *win= bwin_from_winid(winid);
+ Mat4CpyMat4(mat, win->winmat);
+}
+
+void bwin_multmatrix(int winid, float mat[][4])
+{
+ bWindow *win= bwin_from_winid(winid);
+
+ glMultMatrixf((float*) mat);
+ glGetFloatv(GL_MODELVIEW_MATRIX, (float *)win->viewmat);
+}
+
+void bwin_clear_viewmat(int swin)
+{
+ bWindow *win;
+
+ win= swinarray[swin];
+ if(win==0) return;
+
+ memset(win->viewmat, 0, sizeof(win->viewmat));
+ win->viewmat[0][0]= 1.0;
+ win->viewmat[1][1]= 1.0;
+ win->viewmat[2][2]= 1.0;
+ win->viewmat[3][3]= 1.0;
+}
+
+
+void myloadmatrix(float mat[][4])
+{
+ if (glaGetOneInteger(GL_MATRIX_MODE)==GL_MODELVIEW) {
+ bwin_load_viewmatrix(curswin, mat);
+ } else {
+ bwin_load_winmatrix(curswin, mat);
+ }
+}
+
+void mygetmatrix(float mat[][4])
+{
+ if (glaGetOneInteger(GL_MATRIX_MODE)==GL_MODELVIEW) {
+ bwin_get_viewmatrix(curswin, mat);
+ } else {
+ bwin_get_winmatrix(curswin, mat);
+ }
+}
+
+void mymultmatrix(float mat[][4])
+{
+ bwin_multmatrix(curswin, mat);
+}
+
+void mygetsingmatrix(float mat[][4])
+{
+ bwin_getsinglematrix(curswin, mat);
+}
+
+int mywinget(void)
+{
+ return curswin;
+}
+
+void mywinset(int wid)
+{
+ bWindow *win;
+
+ win= swinarray[wid];
+ if(win==0) {
+ printf("mywinset %d: doesn't exist\n", wid);
+ return;
+ }
+
+ if (wid == 1) { /* main window */
+ glViewport(0, 0, ( win->xmax-win->xmin)+1, ( win->ymax-win->ymin)+1);
+ glScissor(0, 0, ( win->xmax-win->xmin)+1, ( win->ymax-win->ymin)+1);
+ }
+ else {
+ int width= (win->xmax - win->xmin)+1;
+ int height= (win->ymax - win->ymin)+1;
+
+ /* CRITICAL, this clamping ensures that
+ * the viewport never goes outside the screen
+ * edges (assuming the x, y coords aren't
+ * outside). This causes a hardware lock
+ * on Matrox cards if it happens.
+ *
+ * Really Blender should never _ever_ try
+ * to do such a thing, but just to be safe
+ * clamp it anyway (or fix the bScreen
+ * scaling routine, and be damn sure you
+ * fixed it). - zr
+ */
+ if (win->xmin + width>G.curscreen->sizex)
+ width= G.curscreen->sizex - win->xmin;
+ if (win->ymin + height>G.curscreen->sizey)
+ height= G.curscreen->sizey - win->ymin;
+
+ glViewport(win->xmin, win->ymin, width, height);
+ glScissor(win->xmin, win->ymin, width, height);
+ }
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadMatrixf(&win->winmat[0][0]);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadMatrixf(&win->viewmat[0][0]);
+
+ glFinish();
+
+ curswin= wid;
+}
+
+int myswinopen(int parentid, int xmin, int xmax, int ymin, int ymax)
+{
+ bWindow *win= NULL;
+ int freewinid;
+
+ for (freewinid= 4; freewinid<MAXWIN; freewinid++)
+ if (!swinarray[freewinid])
+ break;
+
+ if (freewinid==MAXWIN) {
+ printf("too many windows\n");
+
+ return 0;
+ } else {
+ win= MEM_callocN(sizeof(*win), "winopen");
+
+ win->id= freewinid;
+ swinarray[win->id]= win;
+
+ win->xmin= xmin;
+ win->ymin= ymin;
+ win->xmax= xmax;
+ win->ymax= ymax;
+
+ win->qevents= BLI_gsqueue_new(sizeof(QEvent));
+
+ Mat4One(win->viewmat);
+ Mat4One(win->winmat);
+
+ mywinset(win->id);
+
+ return win->id;
+ }
+}
+
+void mywinclose(int winid)
+{
+ if (winid<4) {
+ if (winid==1) {
+ window_destroy(winlay_mainwindow);
+ winlay_mainwindow= NULL;
+ } else {
+ printf("mwinclose: Internal error, bad winid: %d\n", winid);
+ }
+ } else {
+ bWindow *win= swinarray[winid];
+
+ if (win) {
+ BLI_gsqueue_free(win->qevents);
+ MEM_freeN(win);
+ } else {
+ printf("mwinclose: Internal error, bad winid: %d\n", winid);
+ }
+ }
+
+ swinarray[winid]= 0;
+ if (curswin==winid) curswin= 0;
+}
+
+void mywinposition(int winid, int xmin, int xmax, int ymin, int ymax) /* let op: andere syntax */
+{
+ bWindow *win= bwin_from_winid(winid);
+
+ win->xmin= xmin;
+ win->ymin= ymin;
+ win->xmax= xmax;
+ win->ymax= ymax;
+}
+
+
+void bwin_ortho(int winid, float x1, float x2, float y1, float y2, float n, float f)
+{
+ bWindow *bwin= bwin_from_winid(winid);
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(x1, x2, y1, y2, n, f);
+
+ glGetFloatv(GL_PROJECTION_MATRIX, (float *)bwin->winmat);
+ glMatrixMode(GL_MODELVIEW);
+}
+
+void bwin_ortho2(int win, float x1, float x2, float y1, float y2)
+{
+ bwin_ortho(win, x1, x2, y1, y2, -1, 1);
+}
+
+void bwin_frustum(int winid, float x1, float x2, float y1, float y2, float n, float f)
+{
+ bWindow *win= bwin_from_winid(winid);
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glFrustum(x1, x2, y1, y2, n, f);
+
+ glGetFloatv(GL_PROJECTION_MATRIX, (float *)win->winmat);
+ glMatrixMode(GL_MODELVIEW);
+}
+
+void myortho(float x1, float x2, float y1, float y2, float n, float f)
+{
+ bwin_ortho(curswin, x1, x2, y1, y2, n, f);
+}
+
+void myortho2(float x1, float x2, float y1, float y2)
+{
+ bwin_ortho(curswin, x1, x2, y1, y2, -1, 1);
+}
+
+void mywindow(float x1, float x2, float y1, float y2, float n, float f)
+{
+ bwin_frustum(curswin, x1, x2, y1, y2, n, f);
+}
+
+unsigned int index_to_framebuffer(int index)
+{
+ unsigned int i= index;
+
+ switch(mainwin_color_depth) {
+ case 8:
+ i= ((i & 48)<<18) + ((i & 12)<<12) + ((i & 3)<<6);
+ i |= 0x3F3F3F;
+ break;
+ case 12:
+ i= ((i & 0xF00)<<12) + ((i & 0xF0)<<8) + ((i & 0xF)<<4);
+ /* sometimes dithering subtracts! */
+ i |= 0x0F0F0F;
+ break;
+ case 15:
+ case 16:
+ i= ((i & 0x7C00)<<9) + ((i & 0x3E0)<<6) + ((i & 0x1F)<<3);
+ i |= 0x070707;
+ break;
+ default:
+ i= ((i & 0x3F000)<<6) + ((i & 0xFC0)<<4) + ((i & 0x3F)<<2);
+ i |= 0x030303;
+ break;
+ }
+
+ return i;
+}
+
+int framebuffer_to_index(unsigned int col)
+{
+ if (col==0) return 0;
+
+ switch(mainwin_color_depth) {
+ case 8:
+ return ((col & 0xC00000)>>18) + ((col & 0xC000)>>12) + ((col & 0xC0)>>6);
+ case 12:
+ return ((col & 0xF00000)>>12) + ((col & 0xF000)>>8) + ((col & 0xF0)>>4);
+ case 15:
+ case 16:
+ return ((col & 0xF80000)>>9) + ((col & 0xF800)>>6) + ((col & 0xF8)>>3);
+ default:
+ return ((col & 0xFC0000)>>6) + ((col & 0xFC00)>>4) + ((col & 0xFC)>>2);
+ }
+}
+
+
+/* ********** END MY WINDOW ************** */
+
+#ifdef WIN32
+static int is_a_really_crappy_nvidia_card(void) {
+ static int well_is_it= -1;
+
+ /* Do you understand the implication? Do you? */
+ if (well_is_it==-1)
+ well_is_it= (strcmp((char*) glGetString(GL_VENDOR), "NVIDIA Corporation") == 0);
+
+ return well_is_it;
+}
+#endif
+
+void myswapbuffers(void)
+{
+ ScrArea *sa;
+
+ sa= G.curscreen->areabase.first;
+ while(sa) {
+ if(sa->win_swap==WIN_BACK_OK) sa->win_swap= WIN_FRONT_OK;
+ if(sa->head_swap==WIN_BACK_OK) sa->head_swap= WIN_FRONT_OK;
+
+ sa= sa->next;
+ }
+
+ /* HACK, some windows drivers feel they should honor the scissor
+ * test when swapping buffers, disable the test while swapping
+ * on WIN32. (namely Matrox and NVidia's new drivers around Oct 1 2001)
+ * - zr
+ */
+
+#ifdef WIN32
+ /* HACK, in some NVidia driver release some kind of
+ * fancy optimiziation (I presume) was put in which for
+ * some reason causes parts of the buffer not to be
+ * swapped. One way to defeat it is the following wierd
+ * code (which we only do for nvidia cards). This should
+ * be removed if NVidia fixes their drivers. - zr
+ */
+ if (is_a_really_crappy_nvidia_card()) {
+ glDrawBuffer(GL_FRONT);
+
+ glBegin(GL_LINES);
+ glEnd();
+
+ glDrawBuffer(GL_BACK);
+ }
+
+ glDisable(GL_SCISSOR_TEST);
+ window_swap_buffers(winlay_mainwindow);
+ glEnable(GL_SCISSOR_TEST);
+#else
+ window_swap_buffers(winlay_mainwindow);
+#endif
+}
+
+
+/* *********************** PATTERNS ENZO ***************** */
+
+void setlinestyle(int nr)
+{
+ if(nr==0) {
+ glDisable(GL_LINE_STIPPLE);
+ }
+ else {
+
+ glEnable(GL_LINE_STIPPLE);
+ glLineStipple(nr, 0xAAAA);
+ }
+}
+
+/*******************/
+/*******************/
+/* Menu utilities */
+
+static int *frontbuffer_save= NULL;
+static int ov_x, ov_y, ov_sx, ov_sy;
+
+void my_put_frontbuffer_image(void)
+{
+ if (frontbuffer_save) {
+ glRasterPos2f( (float)ov_x -0.5, (float)ov_y - 0.5 );
+ glDrawPixels(ov_sx, ov_sy, GL_RGBA, GL_UNSIGNED_BYTE, frontbuffer_save);
+ MEM_freeN(frontbuffer_save);
+ frontbuffer_save= NULL;
+ }
+}
+
+void my_get_frontbuffer_image(int x, int y, int sx, int sy)
+{
+ if(frontbuffer_save) return;
+
+ ov_x= x;
+ ov_y= y;
+ ov_sx= sx;
+ ov_sy= sy;
+
+ if(sx>1 && sy>1) {
+ frontbuffer_save= MEM_mallocN(sx*sy*4, "temp_frontbuffer_image");
+ glReadPixels(x, y, sx, sy, GL_RGBA, GL_UNSIGNED_BYTE, frontbuffer_save);
+ }
+
+ #ifdef WIN32
+ /* ander coordinatensysteem! */
+ y= (G.curscreen->sizey-y);
+
+ if(curswin>3) {
+ y -= curarea->winrct.ymin;
+ }
+ #endif
+}
+
+int mywin_inmenu(void) {
+ return frontbuffer_save?1:0;
+}
+
+void mywin_getmenu_rect(int *x, int *y, int *sx, int *sy) {
+ *x= ov_x;
+ *sx= ov_sx;
+ *sy= ov_sy;
+
+#if defined(WIN32) || defined (__BeOS)
+ *y= ov_y;
+#else
+ *y= (G.curscreen->sizey - ov_y) - ov_sy;
+#endif
+}
diff --git a/source/blender/src/oops.c b/source/blender/src/oops.c
new file mode 100644
index 00000000000..06688d2db9d
--- /dev/null
+++ b/source/blender/src/oops.c
@@ -0,0 +1,1044 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+
+#include "DNA_curve_types.h"
+#include "DNA_image_types.h"
+#include "DNA_ipo_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_material_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meta_types.h"
+#include "DNA_object_types.h"
+#include "DNA_oops_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_space_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_key_types.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_global.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+
+#include "BIF_screen.h"
+#include "BIF_space.h"
+#include "BIF_toolbox.h"
+#include "BIF_oops.h"
+#include "BIF_drawoops.h"
+
+#include "blendef.h"
+#include "mydevice.h"
+
+static int correct_oops_y(Oops *oops);
+
+
+Oops *add_oops(void *id)
+{
+ Oops *oops;
+
+ if(G.soops==0) return NULL;
+ oops= MEM_callocN(sizeof(Oops), "oops");
+
+ BLI_addtail(&G.soops->oops, oops);
+
+ oops->id= id;
+ oops->type= GS(oops->id->name);
+
+ return oops;
+}
+
+
+Oops *find_oops(ID *id)
+{
+ Oops *oops;
+
+ /* op zoek naar een oops met dit ID */
+ oops= G.soops->oops.first;
+ while(oops) {
+ if(oops->id == id) {
+ /* deze fout kwam een keer voor. beveiliging kan geen kwaad */
+ if(oops->type != GS(id->name)) oops->id= 0;
+ else break;
+ }
+ oops= oops->next;
+ }
+ return oops;
+}
+
+int test_oops(Oops *oops)
+{
+ /* test of de eigen ID block nog bestaat */
+ ListBase *lb;
+ ID *id;
+
+ if(G.soops==0) return 0;
+
+ lb= wich_libbase(G.main, oops->type);
+ id= lb->first;
+ while(id) {
+ if(id==oops->id) break;
+ id= id->next;
+ }
+
+ if(id==0) return 0;
+
+
+ return 1;
+}
+
+void test_oopslinko(OopsLink *ol)
+{
+ /* test of links bestaan */
+ Oops *oops;
+ ListBase *lb;
+ ID *id, *from;
+
+ if(G.soops==0) return;
+
+ ol->to= 0;
+ from= *ol->idfrom;
+
+ if(from==0) return;
+
+ lb= wich_libbase(G.main, ol->type);
+ id= lb->first;
+ while(id) {
+ if(id==from) break;
+ id= id->next;
+ }
+
+ if(id==0) {
+ /* ID bestaat niet meer */
+ *ol->idfrom= 0;
+ }
+ else {
+ /* op zoek naar een oops met dit ID */
+ oops= G.soops->oops.first;
+ while(oops) {
+ if(oops->id == id) break;
+ oops= oops->next;
+ }
+
+ ol->to= oops;
+ }
+}
+
+void test_oopslink(OopsLink *ol)
+{
+ /* test of links bestaan */
+ Oops *oops;
+ ID *from;
+
+ if(G.soops==0) return;
+
+ ol->to= 0;
+ from= *ol->idfrom;
+
+ if(from==0) return;
+
+ /* op zoek naar een oops met dit ID */
+ oops= G.soops->oops.first;
+ while(oops) {
+ if(oops->id == from) break;
+ oops= oops->next;
+ }
+
+ ol->to= oops;
+ if(oops) oops->flag |= OOPS_REFER;
+}
+
+
+OopsLink *add_oopslink(char *name, Oops *oops, short type, void *from, float xof, float yof)
+{
+ OopsLink *ol;
+
+ if(G.soops==0) return NULL;
+
+ /* testen offie al bestaat: een andere manier mag ook (linkbuffer) */
+ /* ol= oops->link.first; */
+ /* while(ol) { */
+ /* if(ol->idfrom == from) { */
+ /* strncpy(ol->name, name, 11); */
+ /* ol->type= type; */
+ /* ol->xof= xof; */
+ /* ol->yof= yof; */
+ /* return ol; */
+ /* } */
+ /* ol= ol->next; */
+ /* } */
+
+ if(* ((int *)from) == 0) return NULL;
+
+ /* nieuwe maken */
+ ol= MEM_callocN(sizeof(OopsLink), "oopslink");
+
+ BLI_addtail(&oops->link, ol);
+
+ ol->type= type;
+ ol->idfrom= from;
+ ol->xof= xof;
+ ol->yof= yof;
+ BLI_strncpy(ol->name, name, sizeof(ol->name));
+
+ return ol;
+}
+
+int oops_test_overlap(Oops *test)
+{
+ Oops *oops;
+ rctf rt, ro;
+
+ rt.xmin= test->x;
+ rt.xmax= (float)(test->x+OOPSX);
+ rt.ymin= test->y;
+ rt.ymax= (float)(test->y+OOPSY);
+
+ oops= G.soops->oops.first;
+ while(oops) {
+ if(oops!=test) { /* niet op hide testen: is slechts tijdelijke flag */
+
+ ro.xmin= oops->x;
+ ro.xmax= (float)(oops->x+OOPSX);
+ ro.ymin= oops->y;
+ ro.ymax= (float)(oops->y+OOPSY);
+
+ if( BLI_isect_rctf(&rt, &ro, 0) ) return 1;
+
+ }
+ oops= oops->next;
+ }
+
+ return 0;
+}
+
+int oops_test_overlaphide(Oops *test)
+{
+ Oops *oops;
+ rctf rt, ro;
+
+ rt.xmin= (float)(test->x);
+ rt.xmax= (float)(test->x+OOPSX);
+ rt.ymin= (float)(test->y);
+ rt.ymax= (float)(test->y+OOPSY);
+
+ oops= G.soops->oops.first;
+ while(oops) {
+ if(oops->hide==0 && oops!=test) { /* wel op hide testen, niet gebruiken tijdens build_oops */
+
+ ro.xmin= oops->x;
+ ro.xmax= (float)(oops->x+OOPSX);
+ ro.ymin= oops->y;
+ ro.ymax= (float)(oops->y+OOPSY);
+
+ if( BLI_isect_rctf(&rt, &ro, 0) ) return 1;
+
+ }
+ oops= oops->next;
+ }
+
+ return 0;
+}
+
+float oopslink_totlen(Oops *oops)
+{
+ OopsLink *ol;
+ float vec[4], dx, dy, len= 0.0;
+
+
+ ol= oops->link.first;
+ while(ol) {
+ if(ol->to) {
+ give_oopslink_line(oops, ol, vec, vec+2);
+
+ dx= vec[0]-vec[2];
+ dy= vec[1]-vec[3];
+
+ len+= (float)sqrt( dx*dx + dy*dy );
+ }
+ ol= ol->next;
+ }
+ return len;
+}
+
+
+void add_from_link(Oops *from, Oops *oops)
+{
+ OopsLink *ol;
+
+ ol= MEM_callocN(sizeof(OopsLink), "oopslinktemp");
+ BLI_addtail(&oops->link, ol);
+ ol->from= from;
+
+}
+
+void shuffle_oops()
+{
+ Oops *o2, *oops;
+ OopsLink *ol, *oln;
+ float olen, len1, f1, f2;
+ int go= 1, tot=0, dir=1, type1, type2;
+
+
+ /* we nemen twee oopsen, berkekenen de 'beauty' en de verwisselde beauty */
+
+ if(G.soops==0) return;
+
+ if(okee("Shuffle oops")==0) return;
+
+ waitcursor(1);
+
+ /* om de zaak 100% OK en snel te doen: voegen tijdelijk
+ * aan de ooplinklijst - per oops - de 'from' links ook in.
+ * Wel weer vrijgeven!
+ */
+
+ oops= G.soops->oops.first;
+ while(oops) {
+ if(oops->hide==0) {
+ ol= oops->link.first;
+ while(ol) {
+ if(ol->to && ol->to->hide==0) {
+ if(ol->to->flag & SELECT) {
+ add_from_link(oops, ol->to);
+ }
+ }
+ ol= ol->next;
+ }
+ }
+ oops= oops->next;
+ }
+
+ while(go) {
+
+ go= 0;
+ dir= 1-dir;
+ tot++;
+
+ if(dir) oops= G.soops->oops.last;
+ else oops= G.soops->oops.first;
+ while(oops) {
+
+ if(oops->link.first && oops->hide==0 && (oops->flag & SELECT)) {
+ /* vind een goed verwisselbaar paar */
+ olen= oopslink_totlen(oops);
+
+ if(dir) o2= oops->prev;
+ else o2= oops->next;
+
+ if ELEM3(oops->type, ID_OB, ID_LI, ID_SCE) type1= 1; else type1= 0;
+
+
+ while(o2) {
+ if(o2->hide==0 && (o2->flag & SELECT)) {
+
+ if ELEM3(o2->type, ID_OB, ID_LI, ID_SCE) type2= 1; else type2= 0;
+
+ if(type1==type2) {
+
+ len1= oopslink_totlen(o2);
+
+ SWAP(float, oops->x, o2->x);
+ SWAP(float, oops->y, o2->y);
+
+ f1= oopslink_totlen(oops);
+ f2= oopslink_totlen(o2);
+
+ if( f1<=olen && f2<len1) { /* 1 x <= !!! */
+ olen= oopslink_totlen(oops);
+ go= 1;
+ }
+ else {
+ SWAP(float, oops->x, o2->x);
+ SWAP(float, oops->y, o2->y);
+ }
+ }
+ }
+ if(dir) o2= o2->prev;
+ else o2= o2->next;
+ }
+ }
+ if(dir) oops= oops->prev;
+ else oops= oops->next;
+
+
+ }
+ if(tot>5) break;
+ }
+ waitcursor(0);
+
+ /* from links vrijgeven */
+ oops= G.soops->oops.first;
+ while(oops) {
+ if(oops->hide==0) {
+ ol= oops->link.first;
+ while(ol) {
+ oln= ol->next;
+ if(ol->from) {
+ BLI_remlink(&oops->link, ol);
+ MEM_freeN(ol);
+ }
+ ol= oln;
+ }
+ }
+ oops= oops->next;
+ }
+
+ allqueue(REDRAWOOPS, 1);
+}
+
+void shrink_oops()
+{
+ Oops *oops;
+ OopsLink *ol;
+ float vec[4];
+ int /* go= 1, */tot=4;
+
+
+ if(G.soops==0) return;
+
+ if(okee("Shrink oops")==0) return;
+
+ waitcursor(1);
+
+ /* clear */
+ oops= G.soops->oops.first;
+ while(oops) {
+ oops->dx= oops->dy= 0.0;
+ oops= oops->next;
+ }
+
+ while(tot) {
+ tot--;
+
+ /* shrink */
+ oops= G.soops->oops.first;
+ while(oops) {
+ if(oops->link.first && oops->hide==0 && (oops->flag & SELECT)) {
+
+ ol= oops->link.first;
+ while(ol) {
+ if(ol->to && ol->to->hide==0) {
+
+ give_oopslink_line(oops, ol, vec, vec+2);
+
+ oops->dx= (float)(.8*oops->dx + .2*( vec[2]-vec[0]));
+ oops->dy= (float)(.8*oops->dy + .2*( vec[3]-vec[1]));
+
+ if(ol->to->flag & SELECT) {
+ ol->to->dx= (float)(.8*ol->to->dx + .2*( vec[0]-vec[2]));
+ ol->to->dy= (float)(.8*ol->to->dy + .2*( vec[1]-vec[3]));
+ }
+ }
+
+ ol= ol->next;
+ }
+ }
+ oops= oops->next;
+ }
+
+ /* apply */
+ oops= G.soops->oops.first;
+ while(oops) {
+ if(oops->hide==0 && (oops->flag & SELECT)) {
+
+ /* shrink */
+ oops->x+= oops->dx;
+ oops->y+= oops->dy;
+
+ if(oops_test_overlaphide(oops)) {
+ oops->x-= oops->dx;
+ oops->y-= oops->dy;
+ }
+
+ oops->dx= oops->dy= 0.0;
+ }
+ oops= oops->next;
+ }
+ }
+ waitcursor(0);
+
+ allqueue(REDRAWOOPS, 1);
+}
+
+#define LIMSCE -20.0
+#define LIMOB 14.0
+#define LIMDATA 24.0
+
+static int correct_oops_y(Oops *oops)
+{
+ float y;
+
+ y= oops->y;
+
+ switch(oops->type) {
+ case ID_SCE:
+ case ID_LI:
+ if(oops->y > LIMSCE-OOPSY) oops->y= (float)(LIMSCE-OOPSY);
+ break;
+ case ID_OB:
+ CLAMP(oops->y, LIMSCE, LIMOB);
+ break;
+ case ID_IP:
+ case ID_MA:
+ case ID_TE:
+ if(oops->y < LIMDATA+OOPSY) oops->y= (float)(LIMDATA+OOPSY);
+ break;
+ default:
+ CLAMP(oops->y, (float)(LIMOB+OOPSY), LIMDATA);
+ break;
+ }
+
+ if(y==oops->y) return 0;
+ else return 1;
+}
+
+float oopslastx=0.0, oopslasty= 0.0;
+
+void new_oops_location(Oops *new)
+{
+ float dirvec[4][2];
+ static int cnt=0;
+ int a, b, rc= 1, tel=1, ok=0;
+
+ if(G.soops==0) return;
+
+ if(G.soops->oops.first==G.soops->oops.last) {
+ oopslastx= oopslasty= 0.0;
+ }
+
+ cnt++;
+
+ new->x= oopslastx;
+ new->y= oopslasty;
+
+ correct_oops_y(new);
+
+ /* vanuit centrum vrije plek vinden */
+ dirvec[cnt & 3][0]= 1.2*OOPSX;
+ dirvec[cnt & 3][1]= 0;
+ cnt++;
+ dirvec[cnt & 3][0]= 0;
+ dirvec[cnt & 3][1]= (float)(-1.2*OOPSY);
+ cnt++;
+ dirvec[cnt & 3][0]= -1.2*OOPSX;
+ dirvec[cnt & 3][1]= 0;
+ cnt++;
+ dirvec[cnt & 3][0]= 0;
+ dirvec[cnt & 3][1]= (float)(1.2*OOPSY);
+ cnt++;
+
+
+ new->x+= dirvec[ (rc-2) & 3][0];
+ new->y+= dirvec[ (rc-2) & 3][1];
+ rc+= correct_oops_y(new);
+
+ if( oops_test_overlap(new)==0 ) {
+ ok= 1;
+ }
+
+ rc++;
+
+ if(ok==0) {
+ new->x+= dirvec[ (rc-1) & 3][0];
+ new->y+= dirvec[ (rc-1) & 3][1];
+ rc+= correct_oops_y(new);
+
+ if(oops_test_overlap(new)==0 ) {
+ ok= 1;
+ }
+ rc++;
+ }
+
+
+ while(ok==0) {
+
+ for(a=0;a<2;a++) {
+ for(b=0;b<tel;b++) {
+
+ if( oops_test_overlap(new)==0 ) {
+ ok= 1;
+ break;
+ }
+
+ rc &= 3;
+ new->x += dirvec[rc][0];
+ new->y += dirvec[rc][1];
+ rc+= correct_oops_y(new);
+ }
+ rc++;
+
+
+
+ if(ok) break;
+ }
+ if(ok || tel>100) break;
+ tel++;
+ }
+ oopslastx= new->x;
+ oopslasty= new->y;
+
+}
+
+
+void free_oops(Oops *oops) /* ook oops zelf */
+{
+ BLI_freelistN(&oops->link);
+ MEM_freeN(oops);
+}
+
+void free_oopspace(SpaceOops *so)
+{
+ Oops *oops;
+
+ while( (oops= so->oops.first) ) {
+ BLI_remlink(&so->oops, oops);
+ free_oops(oops);
+ }
+}
+
+void add_material_oopslinks(Material *ma, Oops *oops, short flag)
+{
+ int a;
+
+ if(flag & OOPS_TE) {
+ for(a=0; a<8; a++) {
+ if(ma->mtex[a]) add_oopslink("tex", oops, ID_TE, &(ma->mtex[a]->tex), (float)(0.5*OOPSX), (float)OOPSY);
+ }
+ }
+ if(flag & OOPS_OB) {
+ for(a=0; a<8; a++) {
+ if(ma->mtex[a]) add_oopslink("ob", oops, ID_OB, &(ma->mtex[a]->object), 0.0, (float)(0.2*OOPSY));
+ }
+ }
+ if(flag & OOPS_IP) {
+ if(ma->ipo) add_oopslink("ipo", oops, ID_IP, &(ma->ipo), OOPSX, (float)(0.5*OOPSY));
+ }
+}
+
+
+void add_object_oopslinks(Object *ob, Oops *oops, short flag)
+{
+ ID *id;
+
+ if(ob->parent) add_oopslink("parent", oops, ID_OB, &ob->parent, (float)(.6*OOPSX), (float)OOPSY);
+ if(ob->track) add_oopslink("parent", oops, ID_OB, &ob->track, (float)(.4*OOPSX), (float)OOPSY);
+
+ id= ob->data;
+ if(id) {
+ switch( GS(id->name) ) {
+ case ID_ME:
+ if(flag & OOPS_ME) add_oopslink("data", oops, ID_ME, &ob->data, (float)(.5*OOPSX), (float)OOPSY);
+ break;
+ case ID_CU:
+ if(flag & OOPS_CU) add_oopslink("data", oops, ID_CU, &ob->data, (float)(.5*OOPSX), (float)OOPSY);
+ break;
+ case ID_MB:
+ if(flag & OOPS_MB) add_oopslink("data", oops, ID_MB, &ob->data, (float)(.5*OOPSX), (float)OOPSY);
+ break;
+ case ID_LT:
+ if(flag & OOPS_LT) add_oopslink("data", oops, ID_LT, &ob->data, (float)(.5*OOPSX), (float)OOPSY);
+ break;
+ case ID_LA:
+ if(flag & OOPS_LA) add_oopslink("data", oops, ID_LA, &ob->data, (float)(.5*OOPSX), (float)OOPSY);
+ break;
+ }
+ }
+
+ if(flag & OOPS_MA) {
+ short a;
+
+ for(a=0; a<ob->totcol; a++) {
+ if(ob->mat[a]) {
+ add_oopslink("mat", oops, ID_MA, ob->mat+a, 0, (float)(0.5*OOPSY));
+ }
+ }
+ }
+
+ if(flag & OOPS_IP) add_oopslink("ipo", oops, ID_IP, &ob->ipo, OOPSX, (float)(0.5*OOPSY));
+}
+
+void add_mesh_oopslinks(Mesh *me, Oops *oops, short flag)
+{
+ int a;
+
+ if(flag & OOPS_MA) {
+ for(a=0; a<me->totcol; a++) {
+ if(me->mat[a]) {
+ add_oopslink("ma", oops, ID_MA, me->mat+a, 0.0, (float)(0.5*OOPSY));
+ }
+ }
+ }
+ if(flag & OOPS_IP) {
+ if(me->key) add_oopslink("ipo", oops, ID_IP, &me->key->ipo, OOPSX, (float)(0.5*OOPSY));
+ }
+}
+
+void add_curve_oopslinks(Curve *cu, Oops *oops, short flag)
+{
+ int a;
+
+ if(flag & OOPS_MA) {
+ for(a=0; a<cu->totcol; a++) {
+ if(cu->mat[a]) {
+ add_oopslink("ma", oops, ID_MA, cu->mat+a, 0.0, (float)(0.5*OOPSY));
+ }
+ }
+ }
+ if(flag & OOPS_IP) {
+ add_oopslink("speed", oops, ID_IP, &cu->ipo, OOPSX, (float)(0.5*OOPSY));
+ if(cu->key) add_oopslink("ipo", oops, ID_IP, &cu->key->ipo, OOPSX, (float)(0.5*OOPSY));
+ }
+
+}
+
+void add_mball_oopslinks(MetaBall *mb, Oops *oops, short flag)
+{
+ int a;
+
+ if(flag & OOPS_MA) {
+ for(a=0; a<mb->totcol; a++) {
+ if(mb->mat[a]) {
+ add_oopslink("ma", oops, ID_MA, mb->mat+a, 0.0, (float)(0.5*OOPSY));
+ }
+ }
+ }
+}
+
+Oops *add_test_oops(void *id) /* incl links */
+{
+ Oops *oops;
+ Object *ob;
+ Lamp *la;
+ Tex *tex;
+
+ if(id==0) return NULL;
+
+ /* eerst test ofie al bestaat */
+ oops= find_oops(id);
+
+ if(oops) {
+ oops->hide= 0;
+ }
+ else {
+ oops= add_oops(id);
+ new_oops_location(oops);
+ if(G.soops->flag & SO_NEWSELECTED) {
+ oops->flag |= SELECT;
+ }
+ }
+
+ switch( GS( ((ID *)id)->name)) {
+ case ID_SCE:
+ add_oopslink("set", oops, ID_SCE, &((Scene *)id)->set, (float)(.5*OOPSX), (float)OOPSY);
+ break;
+ case ID_OB:
+ ob= (Object *)id;
+ if(ob->flag & SELECT) oops->flag |= SELECT;
+ else oops->flag &= ~SELECT;
+ add_object_oopslinks(ob, oops, G.soops->visiflag);
+ break;
+ case ID_ME:
+ add_mesh_oopslinks((Mesh *)id, oops, G.soops->visiflag);
+ break;
+ case ID_CU:
+ add_curve_oopslinks((Curve *)id, oops, G.soops->visiflag);
+ break;
+ case ID_MB:
+ add_mball_oopslinks((MetaBall *)id, oops, G.soops->visiflag);
+ break;
+ case ID_LA:
+ /* textures nog doen */
+ la= (Lamp *)id;
+ if(la->ipo) if(G.soops->visiflag & OOPS_IP) add_oopslink("ipo", oops, ID_IP, &la->ipo, OOPSX, (float)(0.3*OOPSY));
+ break;
+ case ID_IP:
+
+ break;
+ case ID_MA:
+ add_material_oopslinks((Material *)id, oops, G.soops->visiflag);
+ break;
+ case ID_TE:
+ tex= (Tex *)id;
+ if(tex->ima) if(G.soops->visiflag & OOPS_IM) add_oopslink("image", oops, ID_IM, &tex->ima, OOPSX, (float)(0.3*OOPSY));
+ }
+
+ return oops;
+}
+
+void add_texture_oops(Material *ma)
+{
+ int a;
+
+ for(a=0; a<8; a++) {
+ if(ma->mtex[a]) {
+ add_test_oops(ma->mtex[a]->tex);
+ if(ma->mtex[a]->tex) if(G.soops->visiflag & OOPS_IM) add_test_oops(ma->mtex[a]->tex->ima);
+ }
+ }
+}
+
+void build_oops()
+{
+ Oops *oops;
+ OopsLink *ol;
+ ID *id;
+ Base *base;
+ Object *ob;
+ short a, type;
+
+ /* altijd alles bouwen! */
+
+ if(G.soops==0) return;
+
+ /* set hide flags */
+ oops= G.soops->oops.first;
+ while(oops) {
+ oops->hide= 1;
+ oops->flag &= ~OOPS_REFER;
+
+ BLI_freelistN(&oops->link); /* veel veiliger */
+
+ oops= oops->next;
+ }
+
+ /* oopsen maken,is ook testen of ie al bestaat */
+
+ /* altijd */
+ if(G.soops->visiflag & OOPS_LI) {
+ Library *li= G.main->library.first;
+ while(li) {
+ oops= add_test_oops(li);
+ li= li->id.next;
+ }
+ }
+
+ /* rest op twee manieren: of alles (OOPS_SCE) of alleen gebruikt in deze scene */
+
+ if(G.soops->visiflag & OOPS_SCE) {
+ Scene *sce= G.main->scene.first;
+
+ while(sce) {
+
+ oops= add_test_oops(sce);
+
+ if(G.soops->visiflag & OOPS_OB) {
+ base= sce->base.first;
+ while(base) {
+
+ add_oopslink("object", oops, ID_OB, &base->object, (float)(.5*OOPSX), (float)OOPSY);
+ base= base->next;
+ }
+ }
+
+ sce= sce->id.next;
+ }
+
+ if(G.soops->visiflag & OOPS_OB) {
+ Object *ob= G.main->object.first;
+
+ while(ob) {
+ oops= add_test_oops(ob);
+ ob= ob->id.next;
+ }
+ }
+ if(G.soops->visiflag & OOPS_ME) {
+ Mesh *me= G.main->mesh.first;
+ while(me) {
+ oops= add_test_oops(me);
+ me= me->id.next;
+ }
+ }
+
+ if(G.soops->visiflag & OOPS_CU) {
+ Curve *cu= G.main->curve.first;
+ while(cu) {
+ oops= add_test_oops(cu);
+ cu= cu->id.next;
+ }
+ }
+
+ if(G.soops->visiflag & OOPS_MB) {
+ MetaBall *mb= G.main->mball.first;
+ while(mb) {
+ oops= add_test_oops(mb);
+ mb= mb->id.next;
+ }
+ }
+
+ if(G.soops->visiflag & OOPS_LA) {
+ Lamp *la= G.main->lamp.first;
+ while(la) {
+ oops= add_test_oops(la);
+ la= la->id.next;
+ }
+ }
+
+ if(G.soops->visiflag & OOPS_IP) {
+ Ipo *ipo= G.main->ipo.first;
+ while(ipo) {
+ oops= add_test_oops(ipo);
+ ipo= ipo->id.next;
+ }
+ }
+
+ if(G.soops->visiflag & OOPS_MA) {
+ Material *ma= G.main->mat.first;
+ while(ma) {
+ oops= add_test_oops(ma);
+ ma= ma->id.next;
+ }
+ }
+ if(G.soops->visiflag & OOPS_TE) {
+ Tex *tex= G.main->tex.first;
+ while(tex) {
+ oops= add_test_oops(tex);
+ tex= tex->id.next;
+ }
+ }
+ if(G.soops->visiflag & OOPS_IM) {
+ Image *ima= G.main->image.first;
+ while(ima) {
+ oops= add_test_oops(ima);
+ ima= ima->id.next;
+ }
+ }
+
+ }
+ else {
+
+ /* alleen blokken uit huidige scene */
+
+ base= FIRSTBASE;
+ while(base) {
+
+ /* layer? */
+ if( (G.soops->visiflag & OOPS_LAY)==0 || (base->lay & G.scene->lay)) {
+ ob= base->object;
+
+ if(G.soops->visiflag & OOPS_OB) {
+ oops= add_test_oops(ob);
+ }
+ if(G.soops->visiflag & OOPS_MA) {
+ for(a=0; a<ob->totcol; a++) {
+ if(ob->mat[a]) {
+ oops= add_test_oops(ob->mat[a]);
+ if(G.soops->visiflag & OOPS_TE) add_texture_oops(ob->mat[a]);
+ }
+ }
+ }
+ if(G.soops->visiflag & OOPS_IP) oops= add_test_oops(ob->ipo);
+
+ id= ob->data;
+ if(id) {
+ type= GS(id->name);
+
+ if(type==ID_ME && G.soops->visiflag & OOPS_ME) {
+ Mesh *me= ob->data;
+ oops= add_test_oops(ob->data);
+
+ if(G.soops->visiflag & OOPS_MA) {
+ for(a=0; a<me->totcol; a++) {
+ if(me->mat[a]) {
+ oops= add_test_oops(me->mat[a]);
+ if(G.soops->visiflag & OOPS_TE) add_texture_oops(me->mat[a]);
+ }
+ }
+ }
+ if(G.soops->visiflag & OOPS_IP) {
+ if(me->key) oops= add_test_oops(me->key->ipo);
+ }
+ }
+ else if(type==ID_CU && G.soops->visiflag & OOPS_CU) {
+ Curve *cu= ob->data;
+ oops= add_test_oops(ob->data);
+
+ if(G.soops->visiflag & OOPS_MA) {
+ for(a=0; a<cu->totcol; a++) {
+ if(cu->mat[a]) {
+ oops= add_test_oops(cu->mat[a]);
+ if(G.soops->visiflag & OOPS_TE) add_texture_oops(cu->mat[a]);
+ }
+ }
+ }
+ if(G.soops->visiflag & OOPS_IP) {
+ if(cu->ipo) oops= add_test_oops(cu->ipo);
+ if(cu->key) oops= add_test_oops(cu->key->ipo);
+ }
+ }
+ else if(type==ID_MB && G.soops->visiflag & OOPS_MB) {
+ oops= add_test_oops(ob->data);
+
+ if(G.soops->visiflag & OOPS_MA) {
+ MetaBall *mb= ob->data;
+ for(a=0; a<mb->totcol; a++) {
+ if(mb->mat[a]) {
+ oops= add_test_oops(mb->mat[a]);
+ if(G.soops->visiflag & OOPS_TE) add_texture_oops(mb->mat[a]);
+ }
+ }
+ }
+ }
+ else if(type==ID_LA && G.soops->visiflag & OOPS_LA) {
+ oops= add_test_oops(ob->data);
+ }
+ }
+ }
+ base= base->next;
+ }
+ }
+
+
+
+
+ /* links testen */
+ oops= G.soops->oops.first;
+ while(oops) {
+ if(oops->hide==0) {
+ ol= oops->link.first;
+ while(ol) {
+ test_oopslink(ol);
+ ol= ol->next;
+ }
+ }
+ oops= oops->next;
+ }
+
+ G.soops->flag &= ~SO_NEWSELECTED;
+}
diff --git a/source/blender/src/osx_creator_splash.jpg.c b/source/blender/src/osx_creator_splash.jpg.c
new file mode 100644
index 00000000000..cf01f410dc6
--- /dev/null
+++ b/source/blender/src/osx_creator_splash.jpg.c
@@ -0,0 +1,971 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 __APPLE__
+
+/* DataToC output of file <splash_jpg> */
+int datatoc_splash_jpg_size= 29805;
+char datatoc_splash_jpg[]= {
+255,216,255,224, 0, 16, 74, 70, 73, 70, 0, 1, 2,
+ 0, 0,100, 0,100, 0, 0,255,236, 0, 17, 68,117, 99,107,121, 0, 1, 0, 4, 0, 0, 0, 50, 0, 0,255,238, 0, 14, 65,100,
+111, 98,101, 0,100,192, 0, 0, 0, 1,255,219, 0,132, 0, 8, 6, 6, 6, 6, 6, 8, 6, 6, 8, 12, 8, 7, 8, 12, 14, 10,
+ 8, 8, 10, 14, 16, 13, 13, 14, 13, 13, 16, 17, 12, 14, 13, 13, 14, 12, 17, 15, 18, 19, 20, 19, 18, 15, 24, 24, 26, 26, 24, 24,
+ 35, 34, 34, 34, 35, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 1, 9, 8, 8, 9, 10, 9, 11, 9, 9, 11, 14, 11, 13, 11, 14, 17,
+ 14, 14, 14, 14, 17, 19, 13, 13, 14, 13, 13, 19, 24, 17, 15, 15, 15, 15, 17, 24, 22, 23, 20, 20, 20, 23, 22, 26, 26, 24, 24, 26,
+ 26, 33, 33, 32, 33, 33, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,255,192, 0, 17, 8, 1, 15, 1,244, 3, 1, 34, 0, 2, 17, 1,
+ 3, 17, 1,255,196, 0,192, 0, 0, 1, 5, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 2, 4, 5, 6, 0, 7,
+ 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 16, 0, 2, 1, 3, 2,
+ 4, 2, 5, 7, 7, 8, 6, 6, 6, 11, 0, 1, 2, 3, 0, 17, 4, 18, 5, 33, 49, 19, 6, 65, 20, 81, 97,113, 34, 50,129,145,
+161,209, 66, 21, 7,193,225, 82,146,178, 35, 51,177, 98,114,130, 67,115, 36, 22,240,210, 83, 99,131, 52,162,163,195,211, 84, 54,
+147,179,132,196, 37, 69,241,194,226, 68,100,116,148,164, 53, 38, 23, 17, 0, 2, 1, 3, 2, 4, 3, 6, 4, 6, 3, 1, 0, 0,
+ 0, 0, 0, 1, 2, 17, 3, 4, 33, 18, 49, 65, 81, 5, 97,113, 19,129,145,161,209, 34, 50,177,193, 66,146,240,225, 82,114, 51,
+ 20, 98,147, 21, 52,255,218, 0, 12, 3, 1, 0, 2, 17, 3, 17, 0, 63, 0,246, 67, 44,170,177,170,200,202, 58,113,216, 2, 64,
+248, 22,157, 28,211, 27,222, 70, 63,214, 52, 39,251, 31,221,199,251, 11, 78,136,112,160, 31, 36,211,134, 22,145,173,111,210, 52,
+195,147, 48, 63,196,127,214, 53,210, 94,255, 0, 37, 9,175,107,154, 16, 55,152,154,215, 18, 55,235, 26, 97,159, 32,155,117, 92,
+127, 88,253,116,197,189,175,110, 52,224, 63, 61, 0, 65, 52,252,140,175,250,199,235,164,234, 77,225, 52,159,172,105, 56, 87,112,
+ 20, 2,153,114, 57,137, 95,245,141, 55,204,100,218,253, 86,253, 99, 93,198,247,240,166,158, 30,202, 0,121, 25, 89, 74, 20,117,
+ 93,110,111,112,198,132,217,153, 86,176,158, 75,255, 0, 77,190,186,102, 91, 19, 34,173,248, 1,113,242,159,205, 64,191, 11,212,
+101, 14, 50,242,207, 60,137, 63, 93,190,186,119,155,202,183,241,228,253,118,250,232, 11,114, 44, 41,116,250,104, 7,140,204,195,
+202,121, 63, 93,190,186,112,202,204, 60, 60,196,159,174,223, 93, 13, 0, 6,187, 80,185, 52, 4,129,147,148, 0,253,252,159,174,
+223, 93,115,101,228,143,237,228,253, 99,245,212,114,215,181,171,135, 30, 38,128,145, 30,108,250,142,169,220,122, 46,199,235,162,
+140,169,219,148,237,111, 78,179,245,208,225, 95,112,146, 1, 23, 63, 85,119, 78, 34, 73,208, 56,115, 60, 42, 0,167, 43, 33, 64,
+ 61, 71, 35,211,168,253,116,225,149, 63,140,175,234,247,143,215, 81, 66, 33, 54, 26,138,155,145,107,216, 91,217, 74,177, 48,184,
+ 12,126, 95, 69, 1, 32,100,228, 17,126,179,241,240,212,126,186,239, 49,147,199,247,175,250,199,235,168,218, 92, 88,171, 2, 7,
+170,156, 76,136,190,242,131,236, 60,120,252,148, 1,252,196,246,254, 51,254,177,250,232, 47,147,144,150, 38,121, 63, 93,143,229,
+166, 23, 60,244,145,235,166, 18, 30,192, 11, 91,159, 10,160, 41,204,200,182,161, 59,129,107,147,169,190,186,140,217,217,142,196,
+137,229, 3,192, 7,111,174,147, 32, 16, 84,125,147, 77, 69,176, 44,220, 7, 59,250, 5, 80, 27,206,101,162,221,178, 36, 62,129,
+173,184,159,158,155,231,115, 87,226,200,144,147,196,251,237, 97,244,208, 12,128,176, 39,151, 36, 20,215, 12,198,224,216,122,104,
+ 3, 28,204,208,110,114,165, 3,208, 29,190,186,112,206,203, 97,117,200,151,245,219,235,168,227, 73, 22, 62,245,169, 1, 55,176,
+ 22, 20, 1,198,102,117,253,236,153, 7,245,219,235,164,243,249,136,226,249, 50,144,124, 53,183,215, 64,144, 1,196,154,116, 49,
+235, 58,156,112,160, 38,121,252,163,192, 79, 33,191,243,219,235,161,249,172,245,185,108,137,120,242, 29, 70,250,235,128, 0,220,
+ 10, 70, 26,143,178,128,107,102,231,248, 79, 47,235,183,215, 74, 50,183, 6, 23,243, 18,175,245,219,235,174, 0, 6,231,242, 83,
+ 76,161,156,170,142, 2,128, 42,207,153,194,249, 51, 31,248,140, 7,242,211,219, 59, 34, 62, 7, 34, 75,255, 0, 77,190,186,134,
+229,239,197,172, 41, 27, 79,197,107,154, 2, 75,103,102, 91,221,158, 67,127,231,183,215, 76, 57,249,129,108,114, 36,213,234,118,
+250,232, 58,137, 94, 60, 9,166,132, 0,223,153,160, 12,185,153,195,137,201,151,229,145,190,186, 47,222, 25, 96, 91,175, 33, 62,
+146,237,245,212,106,235, 84,169,104, 27,207,102,159,254,241, 47,235,183,215, 93,231,115,127,241, 50,254,187,125,116, 27,250, 41,
+ 56,208, 18, 60,238,103,254, 38, 95,215,111,174,187,206,230,255, 0,226, 37,253,118,250,232, 43, 27, 55,194,164,219,157,133, 19,
+203,184,248,172,190,178, 71,228,161, 71,121,204,223,252, 76,191,174,223, 93, 47,156,204,255, 0,196, 75,250,237,245,210, 8,163,
+ 28,216,183,166,195,242,154,112, 69, 81,112,156,127,156,105, 66, 85, 29,231, 51,127,241, 18,254,187,125,116,245,159,112, 99, 97,
+ 52,191, 43,176,254, 83, 72, 11, 95,221, 54,229,125, 34,212,225, 30,175, 18,125, 55,160,168,241, 54, 88, 54,124,183, 30,144, 29,
+137,254, 90, 32,201,144, 0,122,243,185,231,241,144, 15,242,208, 68,126,241, 82, 61,119,163, 8,174,188, 57,114, 62,186, 1,222,
+123, 37, 72, 84,118, 23, 63,105,153,191,104,210, 54, 70, 91, 30, 51, 72, 61,140, 64,225,236,174,110,130, 47,190,203,123,250,105,
+146,229, 99, 34,168, 4,144, 7,128,231, 66, 14, 25, 25, 36, 92, 79, 39, 47,210,110,127, 61, 59,173,153,123,117,100,183, 11,157,
+ 77,245,212, 39,220,208,112,142, 47,148,154,103,159,152,241,176,183,162,169, 75, 50,249, 86,184,158, 65,253,115,245,210, 28,169,
+ 35, 35, 86, 75,124,174, 79,229,170, 89, 38,153,237,169,201,191,174,146, 40, 89,220, 15, 77, 5, 11,179,156, 44,109,147, 33,241,
+ 98, 11, 27, 15,201, 76,109,217, 84,112,154, 70, 54,181,238, 71,229,170,239, 46,121,120,248,208,229,132,139, 0, 57,208, 23, 31,
+120, 47, 71,171,169,245,116, 53,107,185,189,186,250, 57,243,174,168, 90, 63,194,219,255, 0,194,219,255, 0,221, 87, 84, 26,150,
+ 15,246, 63,187,143,246, 22,136,160,218,212,198,226, 99,254,132,127,176,180, 81,194,169, 0,200,164, 17,199,194,152,110,124, 47,
+106, 36,196,106, 30,202, 24,106, 16, 80, 79, 42, 69,102,185,191, 42, 80, 69,113,183, 43,208, 14, 6,184,154, 78, 0,113,174,184,
+160, 20, 48, 96, 64,240,166, 53,185, 82,222,222, 20,210, 13,232, 8, 51, 13, 83, 48, 7,213,243, 10, 64,162,245,197,174,229,189,
+ 60,105, 46,126,122,133, 9,112, 13, 48,177, 53,195,157, 41,240,160, 56, 3, 92, 71, 10,237, 94, 20,134,228,208, 28,197, 80, 18,
+120, 0, 56,213, 44,155,236,186,255, 0,115, 26,232, 28,181, 92,147,243, 17, 87,122, 1, 6,252,106,143, 63,104,104,245, 79,138,
+ 53, 39, 54,143,196,123, 61, 85,243,251,147,202, 86,227, 44,102,210,141, 92,233,247,120,123, 15,118, 2,198,115,113,200, 85,114,
+162,141,126,210,235,108,221,113,114,163, 17,159,114, 97,114,200,120,223,250, 54,169, 98, 72,205,205,192, 62,190, 21,133, 86,100,
+ 96,202, 74,176,226, 8,224, 65,171,236, 13,228, 72, 86, 28,178, 3,219, 74,203,200, 31,233,122,235,134, 23,116,141,202, 91,200,
+106, 50,224,165,194, 50,243,232,206,217,157,181,194,183, 44, 86, 81,231, 30,113,242,234,139,164,107,129,165,192, 4,220,241,240,
+245, 81,149,184,243, 60,168, 34, 61, 86, 28, 8,183,186,105,161, 69,129,224, 44,109,195,135, 3,236,175,172,124,176,254,233, 60,
+ 15, 19,198,146, 79,179,224, 65,227,242, 87, 44, 99,152, 98,170,120,158, 55,183,201, 76,100, 55,187, 57, 62,178, 7,141, 0,230,
+ 32,241,229, 72, 64, 55, 35,149, 48,137,111,204, 31,146,156,188, 5,219,153,231, 85, 0, 83, 41, 98,183,227, 99,107, 84,121, 36,
+ 14,116,253,133, 60, 79,164,210,228, 77,173,138,175, 33,194,244, 6, 96, 45,164, 85, 3,223, 81,248, 69, 32,226, 44, 91,219, 72,
+ 25,217,109,106,229,136,243, 39,230,160, 19, 90,169,178,143,109, 43, 6,127,132, 88, 83,130,133,227,252,180,186,212,155, 14, 38,
+128,103, 70,226,228,222,136,134,223, 37, 51, 83,223,143, 1, 72,193,126, 35,243, 80, 7,189,197, 32,231,199,133, 10,228,175, 0,
+ 65,165, 86,178,241,231, 64, 61,157, 67,105, 28, 73,230,104,100,144,108, 61,209, 92, 73, 39,209, 92, 17,155,144, 38,149, 45, 4,
+ 98, 27,194,244,188,104,171, 3, 31,137,149,125,167,234,189, 61, 97,136, 91, 83, 51, 95,193, 69,190,147, 80, 17,235,184,158, 3,
+141, 73, 8,163,225, 64,109,226,198,255, 0, 80,165, 1,143, 5, 54,241, 32, 11, 80, 84, 0,138, 67,225,111,111, 15,229,167, 44,
+ 43,246,156, 15,103, 19, 70, 9,127, 14, 55,177, 38,136, 34, 0, 27,240,181, 81, 80, 41, 28, 67,236,179, 31, 89,176, 63,150,136,
+ 44,132,104,141, 86,198,230,227, 81, 31, 43, 94,156, 12, 42, 6,183, 23,245,154,107,102, 98,198, 44, 46,199,194,194,160, 28,194,
+ 70,247,152,146,180,206,159,160,115,229,122,105,220, 3, 0, 18, 62, 3,210,106, 60,185,179,158, 2,203,236, 21, 72, 77, 16,146,
+ 56,252,181,207,210, 65,119,113,235,185,170,240,243, 72, 46, 88,159,150,152,209,177,107, 31, 10, 22,132,241,145,142,128,216,223,
+216, 41,143,184, 5,176, 72,254,122, 12, 80,251,154,169,100,131, 77,155,195,149, 0,158,114,118,185, 22, 95,101, 14, 73,103,127,
+137,201,249,105,225, 2, 45,207,143, 26,145, 20, 75, 56, 10,182, 30, 36,212, 53, 77, 8, 73, 27, 22, 30,186,147,229,143,207,198,
+164,152, 70, 61,217,200, 60, 56, 90,163, 12,171,191, 46, 28,133, 83, 36,115, 29,184, 91,141, 28, 71,165, 64, 53, 32,105,190,178,
+ 61,227,196, 26,137, 49,102,114,163,144,168,105,105,168, 97, 7, 82,197,124, 42, 66, 66,208, 27,183, 6,240, 30,170, 14, 27, 16,
+116,183,133, 74,157,137,141,152, 11, 26, 17,186,186,145,222,120, 80,233, 13, 99,234,166,185,141,192, 1,175,127,181, 81, 89, 0,
+ 23,241, 52,232, 65, 23,244, 81,136,241,212,176,233,127,133,248,133,188,181,188,127,241, 55,174,167,216,121,109, 62, 30, 95,255,
+ 0,120,174,168,111, 79,137, 36,124, 81,223,194, 56,255, 0, 97,104,151, 20,136,183,210,127,221,199,251, 11, 79, 49, 3,225, 90,
+ 57, 17,230,182,161,236,160, 26,145, 52, 87,111,146,130, 98, 54,161, 6,131, 75,171,198,144,194, 71,137,167, 8,184,115,160, 18,
+254, 55,174,213,227, 74, 33, 35,198,184,163, 91,133, 0,151, 52,174,196, 35, 16,120,128, 72,249,169, 44,195,194,133, 53,250,100,
+122,109,106, 2, 56,224, 41, 9, 23,246, 87,105,244,210,129, 80,162,113,168, 19,238,248,145, 62,129,170, 82, 57,149,181,190,115,
+ 83,229, 93,104,200, 13,139, 2,160,250, 46, 43, 50,251,118,100,108, 84,196, 77,188, 87,136,175,159,220, 50, 50,109, 40, 44,120,
+ 55,186,181,146, 91,169,224,123,176,108, 99,221,114,245,231, 74, 82,145,174,218,248,150, 99,125,199, 31,217, 63,209, 75,247,238,
+ 63,251, 39,250, 42,167,200,102,127,176,127,154,184,224,229,128, 73,133,128, 28, 73, 35,149,124,207,247,251,143,244,191,250,255,
+ 0,145,244, 63,210,192,254,165,251,255, 0,153,111,247,244, 22,254, 19,253, 20,131,127,132,127,100,255, 0, 69, 80,215, 87, 63,
+253,108,191,234, 95,181, 29, 63,243, 49,127,165,254,230, 76,205,159, 19, 32,245, 32,137,162,147,237,114,210,125,126,218,135, 82,
+ 49,240,115, 50,191,229,177,228,148,122, 81, 73, 31, 56,163,190,203,187, 70,186,159, 10, 96, 61, 33, 9,254, 74,242,205, 93,186,
+221,223, 77,235,171,113,141, 35,240, 61, 48,118,173, 37,111,122,211,130,148,170,254, 33,118,221,230, 92, 50, 34,154,242, 65,200,
+126,146,251, 43, 69, 22, 84, 19, 42, 73, 27,134, 67,198,245,138,101,101, 37, 88, 21, 97,192,131,192,138,145,133,157, 62, 12,154,
+226, 55, 83,241, 70,126, 19, 94,220, 46,231, 59, 52,183,122,178,135, 10,254,168,252,209,227,204,237,208,187, 91,150,169, 25,241,
+167,233,151,243, 54,183,140,252, 45,123,211, 69,175,196,251, 7,133, 3, 11, 51, 27,113,139,169, 24,247,199,199, 25,181,212,209,
+210, 40,155, 87,187,106,253, 12, 39, 25,197, 78, 13, 74, 47, 84,209,240,167, 9, 66, 78, 19, 78, 45,113, 76, 91, 17,196, 26,135,
+ 60,167,140,106,127,164,106,179,112,238,222,222,218,183, 70,218,179,231,147, 30,100, 10,218,217, 88,199,103, 26,135, 21,213,244,
+138,145,143,153,135,158,173, 62, 14, 66,100, 66, 88,129, 36,108, 24,112,240,225,227, 93,125, 57,164,164,226,210,122,167, 77, 14,
+ 81,185, 9, 55, 24,201, 54,184,170,234,189,129, 2,169,224,120,211,186,104,188,105,108, 71, 30, 0, 83, 24,134, 62,161,202,161,
+177, 89,213, 71,166,184,179, 21,247,120,122,104, 51, 77, 20, 8,102,157,214, 40,215,226,145,200, 85, 23,225,204,212,120,247, 93,
+182, 87, 17, 67,155, 4,146, 57,178,162,202,140, 73,244, 0, 13,234,164,222,169, 50, 54,147,163,105, 18,197,185, 51, 92,215,113,
+ 6,202,182, 30, 38,144, 15, 17,206,138,139,170,197,135,176, 84, 40,198, 1,173,196,251, 5, 61, 99,148,139, 4,183,183,243,209,
+213, 91,144,225,106,126,131,192,147,106, 2, 55, 68,253,166, 31,203, 74, 35, 65,235,162,185,137,110, 75, 11, 83, 58,240,142, 87,
+106, 3,130,128,108, 7,178,136, 16,145,252,181, 31,205,221,189,213,166,201,147, 63, 37, 58,125,148, 4,200,227,225,126, 92, 62,
+ 74, 95,220,174,157, 78, 47,237,170,226,101, 96,110,196,211,162,132,147,199,149, 66,178, 91,229, 99, 41, 60,216,248, 0, 62,186,
+ 97,205, 28,209, 56,248, 94,129, 36, 54, 34,194,247,229, 76,158,108, 92, 40,140,217,147, 36, 49, 39,197, 36,140, 21, 71,135, 51,
+ 87,193, 5,205,189, 18,234, 19,205,228, 72,108, 13,135,168, 82, 74,102, 34,236,196,213, 62, 31,119,118,252,251,140, 59,102, 38,
+ 65,200,158, 98, 85, 90, 52, 58, 1, 0,177,187,182,159, 1,225, 87,204,233, 32, 32, 26,179,140,163, 77,241,113,170,174,186, 25,
+132,225, 58,236,146,149, 29, 52,117, 34, 34, 18, 77, 61,161, 32,139,211,222,209,129,167,137,162, 70,225,197,217,111,198,178,109,
+209,104, 54, 56,149, 83,143,137,225, 93, 44,100,183, 1,126, 20,217,157,217,172, 13,128,227,106,114, 57,233,241,231,122, 49, 21,
+ 86,117,196, 75,164,243,163, 42, 35,141, 68,219,217, 81,153, 75, 57, 39,194,141, 25,208,131,133, 3,124,134, 75, 35, 33, 10,188,
+135, 47,101, 18, 41, 25,214,231,195,133,169,179, 43, 94,246,231,202,150, 52,101, 22,183,182,140,177,234,198, 78, 11, 16, 7, 0,
+105,216,247, 66,195,213,249,104,226, 30,167,168,142, 68,209,132, 40,138, 1, 96, 90,220,104,137, 39, 86, 6,123,152,200, 28,120,
+ 84, 48,154,136, 2,172, 21, 99, 28, 25,174, 79, 10,105, 16,167, 4, 94,126, 52, 32, 22, 63,102,252,121, 87, 28,119, 55,117, 23,
+ 7,209, 69,241,224,188,121,210,135,150,198,198,223,158,129,177, 35, 78,146,155,241, 99, 79, 14, 25,108, 64,246, 26,102,150,191,
+188,109,115,107,215,116,195, 29, 55,189,207, 58,180, 37, 65, 54, 48, 36,126,241,109,227,115,202,138, 32,141, 80, 1, 42,223,196,
+241,227, 92, 99, 65,194,231, 95, 38, 30, 30,170,120,129,116,139,145,195,137,168, 90,135,210,190, 94,221, 65,255, 0, 47,107,216,
+242,235,243,174,174,176,242,247,208,109,229,237,255, 0, 95,254,134,186,130,164,232,192, 8,135,210,145,254,194,211,152,138, 96,
+224,137,127,246,105,251, 34,148, 16, 69,234,153, 3, 41, 32,252,148, 59,222,151, 33,189,241,225,194,133,123, 80, 4,225, 74, 8,
+ 20, 16,192,248,211,239, 64, 59, 80, 62,170,234,101, 40, 32, 80, 11,227,114, 42, 62, 83, 13, 1, 71,166,255, 0, 53, 25,154,161,
+228,146, 93, 87,194,212, 97, 2, 4,218,194,184, 92,241,165, 28, 5, 40, 32, 10,133, 18,222, 52,150,187, 82,220,218,161,102,103,
+197,134, 52,223, 92,199,146, 15, 15,233, 87, 59,183, 97,106, 14,119, 36,163, 21,205,155,183,110,119, 36,161,110, 46, 77,242, 68,
+169,178, 33,197,143, 92,173, 97,224, 60, 79,168, 10,207,102,238, 50,229,146,163,220,138,252, 16,120,255, 0, 74,163,207,145, 46,
+ 75,245, 37,107,159, 1,224, 7,170,133, 95,157,205,238, 83,191, 88, 91,172, 45,244,231, 47,238,249, 31,123, 15,183,194,205, 39,
+ 58, 78,127, 8,249,124,206,173,174,195,218,145, 44,105,153,186, 38,185, 26,204,152,231,225, 81,225,175,210,125, 85, 71,218,248,
+ 73,155,187,196, 36, 23,142, 16,102, 97,233,211,109, 63,244,136,173, 15,226, 7,113, 75,219, 93,181,145,155,138, 64,203,153,151,
+ 31, 21,143,217,121, 47,239,255, 0, 85, 84,145,235,175, 87,102,192,141,231,234,205, 41,125, 91, 97, 23,194,188,228,207, 55,118,
+206,118, 98,237,197,184,210, 59,166,215, 26,116, 67,247,222,247,237,142,215, 35, 27, 55, 36,121,133, 28, 49, 49,215, 91,168,254,
+114,175, 5,254,177, 21, 67,143,248,203,218, 83, 73,162, 88,242,241,214,255, 0,196,146, 37, 43,242,244,221,219,232,175, 5,150,
+ 89, 38,145,230,153,218, 73,100, 37,157,216,146,204,199,137, 36,158,100,211, 43,246,113,237,246,148,105, 38,219,234,180,247, 35,
+241,211,238, 87,156,171, 21, 20,186, 61,125,236,250,159,165,176,247, 86, 16,202,198,146, 60,168,159,132,121, 80,145,169, 79,162,
+252,193, 31,162,213,133,221,246,153,246,140,163, 4,190,242, 55,189, 20,163,147, 47,214, 60,107,207,127, 15,251,159, 43,183, 55,
+252,107, 72,124,142,100,137, 6,100, 36,251,165, 92,233, 18, 91,244,144,155,223,228,175,123,238,156, 37,203,218, 37,123,126,243,
+ 31,247,168,125,159, 16,253, 90,252,255, 0,123,237, 80, 81,148,226,190,164,156,148,150,142, 73,113,140,143,208,118,110,233, 41,
+ 56,194, 95,107,106, 50,143, 21, 22,248, 74, 39,159, 97,229, 73,135, 58,207, 25,229,241, 47,131, 15, 16,107,105,141,147, 28,177,
+ 44,202,195, 76,158,240, 39,133, 97, 43, 75,219,179,179,227,201, 1,254,201,131, 47,177,191, 56,175,143,217,242, 28,110,187, 13,
+253, 51, 77,175, 9, 47,154, 62,175,117,176,165,109, 94, 75,234,131, 73,248,197,252,153,229, 95,137, 68, 30,235,200, 42, 65, 29,
+ 40,120,143,232, 10,210,254, 31,102, 98, 96,246,220,211,229,204,144, 70,185, 47,119,145,130,143,129, 60, 77,102,191, 18,133,187,
+175, 32,127,186,135,246, 5, 81,237, 91, 94,231,190, 72, 48,112,129,116,142,238,218,154,209,199,170,192,177,246,219,219, 95,185,
+244,227,115, 18,220,101, 45,169, 70, 45,191, 4,143,196, 43,178,183,153,114, 81,142,249, 57, 73, 37,226,217,234,242,119,191,108,
+ 23,233,157,192,122,200,142, 66,191, 56, 75, 85,158, 14,229,183,110,104, 95, 3, 34, 60,128,188,194, 48, 36,123, 71, 49, 94,113,
+ 47,225,174,240,176, 25, 33,200,130,105, 0,191, 72, 22, 82,125, 64,176,183,207, 89, 84,147, 63,103,205, 37, 25,241,115, 49,216,
+131,111,117,149,135, 48,107,138,196,177,113, 63, 70,235,109,117,254, 17,232,121,185, 22,154,245,237, 36,159, 77, 62,103,172,247,
+176, 35,182,115,245,122, 35,225,255, 0, 21, 43,204,251, 87,255, 0, 49,109,214,255, 0,108, 63, 45,109,119, 13,233,119,238,195,
+203,204, 96, 23, 37, 58,113,100,168,228, 28, 73, 31, 16, 61, 12, 13,235, 23,218,130,253,197,183, 15,247,195,249, 13,116,198,139,
+142, 61,232,203, 70,156,147,253,167, 60,169,198,121, 54, 39, 23, 85, 37, 6,191,113,237,151, 85, 82,206,225, 85, 69,216,146, 0,
+ 0,122, 73,170, 60,206,252,237,204, 25, 12, 99, 39,174,227,129,232,169,112, 63,173,240,253, 53,138,239,206,225,159, 39, 58, 77,
+155, 25,202, 98, 99, 29, 51,128,109,212,144,115,213,234, 94, 86,244,212, 94,213,236,230,223,226,124,204,153,142, 62, 26, 55, 77,
+ 74,139,187,176, 23, 58,111,192, 1,126,117,194, 24,150,227,109, 93,191, 39, 20,245, 73,120,240, 59,220,204,185, 43,174,206, 60,
+ 84,154,209,183,225,196,219, 71,248,141,177, 76,250, 76,210, 66, 15, 13, 79, 25,183,253, 29, 85,123,141,157, 14,227, 24,159, 15,
+ 33,103,136,253,184,216, 48,191,160,218,176,251,191,225,180, 48,226,188,251, 86, 76,143, 50, 2,194, 9,180,157,118, 23,178,178,
+133,177,244,112,172,126,195,190,101,236, 57,233,151, 3, 19, 29,192,200,134,254,235,167,136, 35,211,232, 62, 21, 86, 45,155,176,
+114,199,147,170,229, 32,242,239,217,154,134, 76, 21, 37,250,162,123,139,199,101,164, 10,136,132,185, 0, 0, 73, 39,128, 0, 87,
+155,254, 33,231,200,242,109,147, 99, 76,235, 28,208,188,138, 81,138,220, 49, 82, 15, 15, 85,101,246,230,222,247, 73, 14,211,133,
+ 44,178,156,162, 58,145,151, 54, 33, 46,110,228,158, 10, 47,198,177,111, 9,206,218,184,230,162,159, 26,174, 20,122,155,185,158,
+161,117,218, 86,220,154,225, 71,198,171, 77, 15, 83,200,239, 78,217,193,148,196,249,130, 87, 28, 15, 69, 90, 64, 63,172,163, 79,
+211, 82,246,238,230,216, 55,135, 17,225,102, 41,152,242,134, 64, 99,115,253, 16,224, 95,228,172, 43,126, 24,238,171, 14,191, 57,
+ 1,150,223,195,179,218,254,141, 86,252,149,140,158, 12,140, 28,153, 49,230, 6, 44,136, 28,171, 15, 21,101, 62, 4, 87, 88, 98,
+ 99, 92, 77, 91,184,220,151,241,192,227, 60,220,171, 77, 74,237,164,162,249,127, 58,159, 66, 64,234,100,210,194,232,104, 91,166,
+227,131,182,198, 31, 34,120,241,145,188,100, 96, 9,246, 95,157,102,112, 59,148,227,246, 84,123,254, 80,234,100, 70, 12, 10, 15,
+246,147, 6, 40,183,246,129,168,215,150,230,231,110, 27,214,113,200,202,119,200,202,157,130,168,231,196,155, 42, 34,248, 15, 64,
+ 21,198,198, 20,167, 41,110,123, 99, 6,226,223, 86,186, 29,242, 51,227, 8,195, 98,221, 41,165, 36,186, 39,212,245,244,239,190,
+216, 4, 35,103,141, 92,175,211,146,223, 62,139, 85, 95,121,102,225,238, 61,173,149,145,133, 58,100, 71,174, 33,170, 54, 13,111,
+222, 47, 3,110, 85,157,196,252, 50,222,231,128, 75,145, 60, 24,206,194,253, 38, 44,204, 63,165,160, 17,244,213, 14,243,177,238,
+253,185, 33,198,204,225, 14, 64,176,146, 38, 38, 41, 66,155,250,185, 30, 54, 34,187,219,199,199,245, 35,233, 93,172,162,211,163,
+214,180,232,121,238,229,101,122, 82, 87,108,210, 50,139, 85, 90, 82,189,120,134,236,223,252,205,183,255, 0, 77,191,245,109, 94,
+208, 10, 68,175, 52,140, 18, 53, 23,103, 99,101, 0,122, 73,175, 24,236,175,252,211,182,240,191,190,220, 63,225,181, 89,247,239,
+114, 79,184,110, 50,237, 56,237,211,192,195,109, 12,138,109,212,149,126, 38,127, 78,147,192, 10,185, 86, 37,123, 34, 49, 78,137,
+ 66,173,248, 85,153,196,200,141,140,105,205,170,183, 58, 37,213,209, 27, 60,222,249,237,188, 89, 10,121,163, 59, 11,223,162,133,
+199,235,112, 83,242, 26,102, 47,226, 15,108,200,193, 30,105, 33,212,126, 41, 35, 54, 23,254,134,170,199,246,143, 98,183,112,227,
+182,225,153, 57,198,195, 12, 82, 61, 0, 23,144,175,196, 65,110, 0, 95,133, 91,239,191,134, 49, 98,225, 75,151,180,100,201, 36,
+144,169,115,143, 48, 82, 92, 1,114, 21,144, 47, 31, 71, 10,230,236,225,198, 94,156,167, 45,220, 27,229, 95,113,213, 95,206,156,
+125, 88,194, 27,120,165,205,175,121,190,199,151, 23,112,137,114,176,167,142,120, 91,147,198,193,133,254, 74,144, 98, 81,195, 87,
+ 10,240,158,218,238, 12,158,223,220, 99,201, 66, 91, 25,136, 92,168, 47,193,211,199,135,233, 15, 3, 90,127,196,204,169, 83,114,
+192,147, 22,103, 72,165,197, 14,165, 24,168, 96, 93,172,220, 61, 85,137, 96,181,122, 54,247,105, 36,218,149, 58,114, 55, 14,224,
+157,153, 92,219,245, 69,164,227, 94,188,211, 61, 51, 35, 39, 15, 19, 29,167,201,117,138, 24,197,222, 87, 33, 64, 30,178,106,143,
+ 7,188,246, 29,211,113, 77,179, 5,222, 73,164, 45,211,109, 4, 33,208,165,207, 22,177,228,190,138,242, 28, 36,222,119,169, 83,
+105,196,121,114, 90,102, 14, 33, 46, 74,221, 65,247,219, 81,176, 0, 30,102,189, 7,182, 63, 15,247, 29,147,119,197,221, 51,114,
+241,202,194, 31, 92, 49,150,102,247,227,104,248, 29, 32,112, 45, 90,158, 45,155, 80,151,169,114,178,163,113, 75, 79, 35, 54,243,
+ 47, 94,156,125, 59,116,133, 82,155,122,249,235,161,190,213, 37,248,127,165,169,193, 92,248,250, 62,154, 85,147, 29,120,117, 47,
+110,118, 23,174,243, 24,232,120, 43, 55,209, 94, 19,232, 29,164,155,141, 94,240,240,165, 17,240,247,185,155, 0,105,158,104, 2,
+116,198, 62, 83, 93,231, 38,228,161, 84,123, 42, 20, 48,132,220, 48, 23, 60,192,162,152, 8, 23,210,110, 71, 63, 10,132,114,178,
+ 15,246,132, 15, 64,225, 65,146, 73, 88, 18, 92,159,150,132, 44, 76, 77,111,125,148, 14, 2,247, 28,133, 55,252, 58,157, 77, 40,
+ 54,240, 21, 90, 27,135, 30,124, 40,160,112,160, 38, 25,241, 64,226, 75,159,101, 8,229,192,131,221,136,155,122, 77, 70,123, 0,
+125, 84, 34,218,190,138,181, 4,225,154,130,218, 96, 3,218,196,210,156,214, 38,226, 36, 4,248,241, 63,150,160,150, 32,240, 23,
+184,176,167,169,224, 47,207,198,160, 45,124,204,158, 94,250, 87,248, 26,173,110, 23,243, 26,125, 53,212, 27,255, 0,134,255, 0,
+217,191,247,154,234, 2,208,142, 9,253, 4,253,145, 93, 92, 79,193,253, 4,253,145, 93,122,164, 35,228,124, 66,254,138, 1, 23,
+225, 70,157,189,240, 61, 84, 49,123,240, 20, 3, 2,170,147,233, 52,237, 39,192,211,133,169, 45,198,128, 64, 13,136, 52,154, 8,
+ 55,191, 63, 10, 40, 23,165, 34,128, 23, 31, 26,133, 48,213, 43, 17,203,234, 21, 61,133,170,184,184, 44, 91,211,198,212,101, 66,
+133, 28,141, 56,128, 61, 64, 83, 67, 85, 6,235,159, 36,146,190, 50, 29, 49,161,210,214,251, 68,115,189,121,114,242,161,141,111,
+124,149, 91,116,138, 92,217,232,198,198,158, 69,205,145,209, 45, 91,124,145, 35, 63,119, 11,120,177, 13,207, 35, 47,128,254,141,
+ 82,146, 88,150, 99,114,120,146,121,210, 85,142,223,181, 73,148, 68,178,221, 33,240,244,183,178,191, 59, 59,153, 57,215,146,251,
+159, 40,175,182, 43,248,230,125,232,195, 31, 14,211,124, 23, 57, 63,186, 76,141,141,135, 46, 86,162,130,209,160, 37,156,242, 22,
+168,245,178, 88, 99,142, 62,138, 40, 84,181,128, 30,186,200, 75, 25,138, 71,141,185,161, 42,126, 74,233,157,130,177,161,107, 93,
+206, 85,220,249, 87, 74, 36,115,195,204,121, 19,187,166,213, 26,109, 92,233,173, 91, 52, 61,149, 42,166,235, 36,103,156,144,176,
+ 95,104, 42,223,200, 41,223,139,155,100,251,135,105, 52,208, 41,118,193,157, 50, 93, 71, 62,152, 13, 27,159,147, 93,234,131, 15,
+ 42, 92, 28,168,178,225,248,226, 96,195,215,233, 7,218, 43,211,240,115,177, 55,108, 49, 52, 86,120,228, 26,101,137,172,108, 72,
+247,145,197,125, 62,197,149, 24,199,211,253, 86,229,185, 46,177,103,206,239, 88,174,109,203,244,220,142,214,250, 73, 31, 37,215,
+ 87,180,119, 47,224,212, 89, 51,190, 95,109,228,166, 48,114, 88,225,100, 95,166,164,255, 0,179,117, 12, 64,245, 16,125,181,157,
+199,252, 25,238,153, 37, 11,145, 54, 36, 17,248,201,212,103, 54,245, 42,165,126,194, 57,118, 37, 26,239, 75,193,241, 63, 31, 44,
+ 44,136,203,110,198,252, 87, 3, 27,219,155,100,251,198,251,129,183, 99,169,102,154,100, 12, 71,217, 64,117, 59,159,232,168, 38,
+190,156,223,101, 88,118,124,215,115, 96, 98,100, 30,215, 26, 7,210,106,151,179,251, 19,106,237, 8,218, 72, 9,201,207,149,116,
+205,153, 32, 0,233,231,162, 53,227,165,106, 15,119,111,113,229, 48,219,113, 91, 84,113,182,169,220,114, 44, 57, 40,246,120,215,
+196,239, 57,246,213,169, 52,244,218,227, 10,241,148,164,125,222,205,129,113, 77, 39,197,201, 74,116,225, 24,196,202,213,215,110,
+179, 9,167, 0, 18, 10,139,129,237,170, 90,209,246,228, 5, 97,150,114, 63,136,193, 87,216,191,156,215,229, 59,100, 92,178,237,
+211,244,213,191, 42, 31,166,238, 50, 81,197,185, 94,116, 75,206,167,149,254, 36, 27,247, 86, 65,177, 31,186,135,159,244, 5,105,
+ 63, 13, 22, 17,180,100,149, 23,153,178, 8,144,248,233, 8,186,127,148,214,115,241, 39,143,117,228,127,119, 23,236, 10,168,216,
+183,252,254,223,157,167,197, 1,162,152,105,150, 23,190,151,211,236,241, 23,231, 95,208,157,169, 92,195,132, 35,199,108, 95,157,
+ 15,192,198,236,109,102,206,114, 90,110,146,126, 21,230,123,112, 37, 27,249,166,188,159,241, 21, 97, 29,198, 76, 86,214,208, 70,
+102,183,233,241, 31,178, 5, 88,205,248,153, 51, 69,104,118,245, 89,109,241, 60,133,148, 31,232,133, 82,126,122,198, 77, 54,110,
+239,156,210,201,171, 35, 47, 37,249, 40,185,102, 60, 2,168, 31, 69,115,195,198,185,110,110,119, 22,213, 70,184,157,115,114,173,
+ 93,182,173,219,123,155,105,240,249,151,123, 49,127,242,167,113, 15,236,199,149,183,244,186,156,106, 31,105,255, 0,230, 77,183,
+251,225,249,107, 99,151,177, 29,135,176, 51, 96,154,222,106,110,156,217, 54,240, 99, 34, 0,159,213, 31, 77, 99,123, 79,255, 0,
+ 50,109,191,223, 15,228, 53,218, 51, 83,183,145, 40,240,110, 95, 8,164,112,156, 37, 11,152,208,151, 20,163, 95,108,219, 34,111,
+ 58,254,247,220, 58,159, 31,153,155, 85,253, 58,218,167,109,155, 47,115,230, 98, 44,251, 92, 83, 54, 43, 22, 10, 99,148, 42,220,
+ 27, 55, 13, 98,174,187,251,183, 39,197,206,147,121,198, 66,248,153, 39, 84,228, 11,244,228,228,117,122,155,157,253, 53, 15,181,
+ 59,206,110,221, 71,196,150, 31, 49,135, 35,107,210, 14,151, 70, 34,196,173,248, 16,109,202,181,234, 74,118, 35, 59, 42, 50,116,
+ 90, 63,138,243, 50,237,198, 25, 18,133,247, 40, 42,191,169,124, 31,144,131,182,123,232,255, 0, 97,146,127,227,143,251,202,140,
+123, 35,186,185,157,185,255, 0, 94, 63,245,235, 71,187,254, 38, 52,248,146, 99,237, 56,207, 4,178,130,167, 34, 86, 23, 64,120,
+ 93, 21, 47,199,208,111, 82,123, 23,186,119,221,203, 37,118,220,168, 78,108, 10, 61,252,210,116,180, 67,192,200,220,155,249,107,
+151,169,149, 27,110,227,133,184,211,138,224,233,239, 58,250, 88,146,184,173,171,151, 37, 94, 13,106,171,238, 40, 59,195, 27, 39,
+ 15,111,216, 49,243, 20,166, 68,120,172,146, 33, 32,144, 85,148, 1,194,254, 21,105,248, 89, 18, 54, 86,229, 41, 23,117,142, 53,
+ 83,232, 12, 88,159,217, 20,239,197, 96,163, 47,109,177,191,238,164,253,165,167,126, 21, 50, 44,187,161,111,209,134,223, 60,149,
+153, 74,184, 46, 92, 43,175,190,102,163, 20,187,130,143, 26,105,175,132, 15, 72, 28,173,107,215,137,247,202,132,238,157,192, 1,
+111,121, 9,246,152,210,245,237,162,120,193,176, 91,250,107,197, 59,232,134,238,172,242, 5,133,227,225,255, 0, 9, 43,135,110,
+255, 0, 52,191,177,254, 40,244,119, 63,240,199,251,215,224,195,230, 25,127,200, 59,104, 4,244,142,116,183, 30, 23,210,214,252,
+180, 62,193,138, 9,123,167, 9,103,181,135, 81,163,191,233,136,216,173,105,118, 45,168,239,189,130,118,208, 66,201,214,146, 88,
+ 24,248, 72,173,194,231,208,121, 87,159, 21,206,218, 51,134,160,248,185,184,174, 24, 95,131, 43, 41,184, 53,236,131, 83,141,251,
+ 73,210, 91,166,191,119, 51,195,113, 59,114,177,121,170,199,108, 31,237,228,125, 23,209,111,209,181,188, 77,100, 63, 18, 98,135,
+252,176,237, 54,158,170,205, 17,135,136,190,162,108,109,253, 91,214,103, 27,241, 67, 41, 97, 11,153,130, 38,148, 15,226, 36,133,
+ 1, 62,146,165, 95,249,107, 57,220, 61,205,184,119, 27,169,157, 68, 88,208,251,209,193, 29,200, 4,240,212,196,243, 62, 21,228,
+177,135,122, 55, 99, 41, 45,170, 46,181,175, 26, 30,204,140,219, 18,179, 40,193,185, 57, 42, 82,156, 43,212,127,100,144, 59,167,
+109, 44,108, 53,181,207,252, 55,170,124,253, 94,123, 39, 95,199,213,147, 85,249,223, 81,189, 90,246,119,254,101,219,255, 0,166,
+223,176,213,103,223, 61,187,145,131,159, 46,235, 4,101,176,178,219, 91,149, 31,195,145,190, 32,222,166, 60, 65,175,115,185, 24,
+228,237,122,110,130,167,154,111, 67,192,173,202, 88,187,214,170, 23, 29,124,154, 90,149,187,118,205,221, 89, 88,113,207,182,164,
+231, 17,239,211, 49,202, 21,120, 18, 13,151, 88,241, 21, 43,252,191,222,230,227,167,146,125, 63,191, 31,247,148,238,216,239, 57,
+182, 24, 78, 20,241, 28,140, 66,197,144, 41,179,161, 63, 22,155,240, 32,250, 42,199,120,252, 69,124,156, 87,198,218,160,124,118,
+148, 21,108,135, 97,169, 65,253, 0,190, 62,187,215, 57,203, 39,212,113,141,184, 56,215, 73, 62,158, 58,157, 97, 28, 95, 73, 74,
+ 87,110, 41, 37,172, 87, 95, 13, 10, 63,242, 95,115,159,254, 94,255, 0,175, 31,250,245, 55,189,147, 42, 36,216,224,205, 5,114,
+ 33,219,227,142, 69, 38,228, 20, 37,109,113,127, 69,104,123, 35,185,183,237,210,111, 35,147, 1,203,134, 49,239,230,143,117,147,
+208, 28,242,107,252,245, 85,248,155,168,238,152, 69,133,191,195,155,126,187, 86, 99,118,235,201,141,187,138, 63, 74,111,233,242,
+ 53, 43, 86,150, 44,174,218,115,250,154, 77, 75,193,147,127, 11,113,227, 45,184,229,145,251,213, 17,196,173,232, 86,212,205,243,
+149, 21,232, 78,108,121,251, 43, 5,248, 88,140,240,110,122,109,193,226,189,253,143, 94,130,113,143,218,113,242, 10,240,230,255,
+ 0,244, 79,217,248, 30,252, 26, 44,104,123,127, 22, 9, 56,113,244,154, 53,175, 76, 68,240, 28,106, 66,198, 77,121,143, 80, 45,
+ 53,196, 90,140,176,233, 26,126, 90, 86,138,224,128,104, 64, 58, 65, 91,138, 99,139, 3, 82, 85, 2,173,175,202,129, 38,146, 56,
+ 30, 38,247,161, 65, 44, 50,177, 4, 33,249,104,139, 20,173,232, 31, 45, 17, 36, 10, 0,241,224, 0,246,210, 43,132,247,136,225,
+126, 52, 7, 12, 87,107,221,192,249, 43,134, 40,241,115,242, 10,147, 13,202, 2,120, 19, 78,211, 66, 17,188,170, 14,108,255, 0,
+233,242, 82,249,104,189, 46,126, 90,146, 69, 37,168, 2,116, 35,242,214,177,255, 0,151,181,239,198,222, 99, 85,117, 26,223,225,
+253, 93, 31,251,106,234,160, 51, 22, 5, 5,190,194,126,200,165,212,125, 20,227,246, 79,243, 19,246, 69, 55, 85, 1, 30,127,140,
+ 27, 30, 84, 35, 37,188, 13, 72,148,241,184,244, 80,109,168,241,160, 27,168,219,151,205, 72,178, 18,120,139, 81,128,183,178,186,
+128,110,171, 10, 93, 64,248,210,144, 57, 26,110,144, 9,189, 0,201, 26,202, 74,155,216, 19,243, 84, 32, 42, 84,224, 8,152,142,
+ 7,128, 31, 61, 69,210,109,206,163, 42, 56,218,168,243,182,169,222,119,150, 11, 58,200,117, 17,123, 16, 79, 62,117,116, 71,141,
+119, 32, 43,207,147,139,111, 34, 10, 23, 43,163,170,107, 70,142,248,249, 55, 44, 73,202,221, 53, 84,105,234,138,156, 45,160, 35,
+117, 50,172,196,114,140,113, 31,214,171,158, 32,112, 22,183, 42, 64, 56,209,121, 10,184,248,214,172, 71,101,168,211,171,124, 95,
+155, 37,252,139,151,165,186,227,175, 69,201,121, 32, 68,177,170, 77,227, 12,134,243, 72, 46, 15, 9, 63, 33,171,202,105, 10,192,
+134, 23, 7,129, 6,166, 86, 60,114, 45, 74,220,180,230,159, 73,114,101,198,191, 43, 23, 85,200,235,201,174,171,161,142,169, 88,
+ 59,134, 94,221, 55, 91, 18, 83, 27,114, 97,205, 88,122, 24, 30, 6,164,231,109, 79, 17, 50,227, 13,113,243, 41,226,191, 88,170,
+202,252,189,219, 55,177,174, 82, 73,194, 75,132,151,227, 22,126,142,221,219, 89, 22,235, 26, 74, 47,138,127,131, 70,203, 23,190,
+ 70,144, 51,113, 78,175, 23,136,240, 63,213,111,174,164, 63,124, 96, 1,251,188,105,153,189, 13,165, 71,207,118,172, 45,117,122,
+ 35,221,115, 18,166,244,252, 92, 85, 78, 15,182,226,183, 93,141,120, 38,232, 94,238,125,213,184,231,169,134, 59, 99, 66,220, 25,
+ 99, 55, 98, 61, 5,254,170,162,174,163,227, 97,207,150,250, 33, 91,143, 23, 60, 20,123, 77,121,167,114,254, 69,197,185,202,228,
+158,137,113,247, 35,209, 24, 89,177, 7,181, 70,220, 86,173,252,216,220,108,121, 50,166, 88, 34, 23,102, 60,252, 0,241, 38,182,
+ 48,196,216,208, 36, 17, 91, 74, 11, 15, 73,244,154, 22, 6,223, 22,223, 29,151,222,145,135,191, 33,230,125, 67,213, 82, 73,231,
+111, 26,253, 7,110,194,255, 0, 94, 14, 83,255, 0, 36,248,255, 0,197,116,249,159, 11, 63, 51,215,146,140, 62,200,112,255, 0,
+147,234, 80,110,253,183,179,238, 89, 94,111, 59, 5, 36,200,112, 3, 72, 89,238, 66,128, 7, 34, 42, 48,237,109,140,225,156, 6,
+195, 79, 45,168,200, 19,143, 7, 32, 2,202,196,234, 28, 7,129,171,220,151, 96,234,160, 94,194,128,125,225,207,219,106,250,170,
+229,202, 37,190, 84, 92, 53,122, 31, 59,210,183, 86,246, 70,175,142,139, 83, 44,223,135,189,182, 31, 86,137,130,254,136,144,219,
+235,171,157,171, 98,217,182,143,123,111,197, 88,156,139, 25, 77,217,200,254,155,220,212,241,232,183, 15, 73,164, 62,233,230, 79,
+168, 85,149,235,178, 84,148,228,215, 70,201, 27, 22,162,235, 27,113, 79,170, 67, 51, 49, 49, 55, 28,119,195,203, 65, 52, 18, 91,
+ 92,102,224, 27, 16,195,149,143, 49, 85,248,189,171,219,248,121, 49,229, 98,224,164,115, 68,117, 70,225,156,144,125, 60, 90,172,
+205,212,234, 28, 61, 52, 64,111,199,211, 89, 83,154, 84, 82,105, 62, 41, 61, 13, 59,112,147, 82,148, 83,107,131,106,172, 86, 85,
+101, 42,224, 50,145, 98,167,136, 32,214,111, 51,178,187,111, 50, 70,115,137,209, 99,204,194,204,131,245, 65,211,244, 86,146,187,
+161,115,123,243,227, 72,220,156, 53,132,156,124,157, 4,237,194,122, 78, 42, 94,106,166, 82, 62,193,237,184, 88, 51, 67, 36,182,
+240,146, 70,183,253, 29, 53,161,194,198,197,193,132, 99,225,196,144, 68,188,145, 0, 81,244, 84,193,142,167,153,165, 49, 70,163,
+136,164,238,220,159,223, 41, 75,205,153,133,171,112,251, 33, 24,249, 34,175,113,217,118,157,217,163,125,199, 25,103,104,129, 17,
+150, 44, 44, 15, 63,132,138, 77,191,102,218,246,158,161,219,113,150, 3, 45,132,133, 75, 27,233,189,190, 34,125, 52,205,255, 0,
+127,194,237,220, 63, 51,144,134, 89,100, 37, 96,129, 77,139,176,231,199,192, 15, 19, 88,184,123,187,188,247,167,115,179,225,175,
+ 77, 79, 30,140, 90,194,250,153,228, 36, 94,166,249,237,219,185,237,233, 93, 61,198,189, 56,110,223,182, 59,186,211, 95,121,232,
+168, 9, 53, 93,153,218,251, 14,225,146,249,121,152, 75, 46, 68,182, 47, 33, 46, 9,210, 2,142, 76, 7, 33, 88,184,187,235,184,
+118,140,193,143,191, 97, 43,114, 46,133, 12, 82, 91,150,165, 63, 9,249,171, 77,220,189,210,216, 61,191,135,188,236,173, 28,131,
+ 42,100, 64,100, 82,195, 67, 36,140, 69,129, 22, 96,201, 99, 72,202, 81,117,139,113,126, 14,130, 81,140,149, 37, 21, 37,226,170,
+ 93,225,109,216,123, 94, 58,226,224,194, 33,128, 18, 68, 96,147,197,185,159,120,154, 14,235,177,237, 91,178,129,184, 98,164,197,
+ 69,149,248,135, 3,212,203, 99, 88,129,248,147,158,219, 98, 34, 65, 28,187,172,146, 48,184, 70, 17,164, 96, 13, 62,237,201,102,
+ 60,124,106,207,181,123,151,119,206,109,192,239,172, 35,143, 30, 53,144, 22,143,165,165,125,237, 71,144,225,238,211,116,147,220,
+155,175, 90,235,239, 27, 34,227,181,197,109,233, 77, 61,196,129,248,115,219,167,247,132, 75,111,208,234, 27,125,117,113, 7,104,
+236, 17, 97,190, 10, 98, 47,151,150,198, 85,227,118,210,110,186,158,250,141,143,174,177,217, 61,251,187,238, 57,131, 7,183, 48,
+195, 2,109, 25,117, 47, 35,129,246,180,130, 21, 71,182,157,145,190,126, 34,108,113,121,205,199, 21, 27, 24, 91, 81,100,141,212,
+ 14, 94,241,199,107,175, 63, 26,219,189,118, 84,172,228,233,226, 97, 88,179, 26,237,183, 21, 93, 56, 35, 97,137,218, 29,189,131,
+144,153, 88,184, 75, 28,241, 27,163,234,123,130, 69,188, 91,209, 86,237,141, 4,138, 81,227, 86, 70, 22,101, 97,112, 65,244,131,
+ 84,221,171,221, 88,189,203,142,246, 78,134,100, 54,235,193,123,139, 30, 78,135,197,127,146,168,123,167,191,114,118,253,197,246,
+125,150, 5,151, 34, 50, 35,146,105, 1,111,222, 31,177, 26, 41, 23, 34,246,227,227,225, 88,148,165, 39, 89, 73,183,226,234,106,
+ 48,140, 85, 35, 21, 20,249, 37, 66,223, 47,176, 59, 99, 45,203,249, 62,131, 30,102, 7,100, 31,171,114,191, 69, 14, 15,195,174,
+215,133,195,156,121, 38,183,132,146, 49, 31, 50,233,170,163, 55,226,154,161,200,232,196, 64, 26,186, 32, 65,170,222,139,106,191,
+211,122, 55,104,247,238, 78,239,184, 46,209,186,192,145,228, 72, 24, 67, 52,119, 80, 89, 1, 98,142,140, 77,137, 0,241,191,170,
+213,211,215,189, 74,122,146,167,155, 49,254,189,154,215,211,133,124,145,107,188,111,187, 63,103,195,139,138,216,174,144,204, 31,
+163, 30, 42, 38,145,163, 78,173, 90,153, 63, 74,153, 6, 38,193,221,216,152,187,174, 70, 17,148, 58,178, 66,102,186,178,170, 72,
+202,192,136,222,220,193,175, 60,239, 28,254,225,206,151, 28,111,184,158, 89, 98,105, 70, 41,233,180,122,193, 41,171,226, 38,246,
+178,213,223,101,110,125,210,137,182,225, 99,225,107,217,204,133, 91, 39,164,199,220,105, 24,200,117,222,220, 24,159, 10,230,165,
+ 36,247, 41, 52,250,167,169,209,198, 46, 59, 92, 83, 93, 26,208,244, 29,175,100,218,246,117,145,118,220,101,199, 19, 16,100, 10,
+ 88,220,173,237,241, 19,233,171, 2,183,172, 55,117,126, 33, 46,209,148,251,110,213, 10,207,149, 23,187, 60,210, 95,166,141,250,
+ 1, 86,197,136,241,227,194,170, 7,112,254, 36,188, 94,117,112,223,161,109, 90, 70, 48,229,233,210,125,251, 81,182,221,100,219,
+111,155, 17,138,138,164, 82, 73,114, 90, 30,136,197,144,144, 56, 95,129,162,249,133, 21,135,237,175,196, 72,247, 12,200,246,253,
+243, 22, 56,102,149,130, 71,149, 24, 33, 75,158, 1,100, 70, 39, 77,253, 55,165,239, 14,242,221,123,115,117,143, 15,111,143, 28,
+197, 36, 11, 49,234,198, 88,234, 47, 34,112, 33,135, 11, 32,168, 83,108,114, 73, 60, 20,159,101, 15, 94, 83,159,117, 90,222,139,
+ 87,159,238, 31,137, 91,198, 73,143, 31, 96,199, 82,235, 26, 28,137,196, 69,216,200, 84,107,208,156,149, 67, 95,157,235,109,218,
+ 27,190,227,186,108,112,101,238,109,254, 41,158, 69,147,221,209,240, 57, 81,117, 22,181, 1, 40,193,154,252,116, 53, 42, 97,228,
+ 94,236,182, 3,157,205, 89, 23, 99,227,194,132,196,159, 26,130,160,150, 33,123,218,228, 14,116,216, 84, 48, 32,143, 26,144, 56,
+ 41,249,168, 56,252, 9, 35,192,208, 7, 81,164, 82,218,184,122,105, 65,240, 53, 64,219,113,165,181,113,240,174, 30,170, 2, 79,
+246, 31,240,127,237,171,171,191,177,191,251,159,251,106,234, 0,236,120, 45,191, 65, 63,100, 83, 26,252, 13,169, 73,107, 37,249,
+232, 75,254,168,164, 60,124, 40, 0,203,123,242,227,106, 64, 62, 79, 77, 44,164,235, 3,208, 40,106,205,115,126, 84, 1, 47,127,
+ 10,227,195,194,154, 15,166,148,158, 20, 7,115,226,105, 9,189,112, 99,168,130, 44, 41, 24,219,149, 1, 27, 37,193, 85, 30,187,
+143,146,132, 88, 1, 78,202, 55,117, 95, 0, 47,127,111,255, 0, 69, 7,215, 81,148,226,110, 43,184,250, 41, 84,112,189, 47,133,
+ 0,129,184,211,139, 19,192, 80,193,230,105,192,128, 40, 14, 2,244,161, 69,114,145, 75,126, 52, 2,162, 2,224,120, 95,136, 62,
+138,110, 78,215,133,145,239, 60, 64,127, 57,120, 31,162,137, 25, 26,193, 38,214,227, 69, 12,182,231,249,171, 19,132, 38,182,206,
+ 42, 75,163, 85, 53, 9,206, 15,116, 36,226,250,167, 66,142, 94,223,135, 94,152,166,101,191,131, 40,111,167,221,165, 29,180,183,
+183,154, 63,169,255, 0,218,171,166, 3, 90,241,249, 5, 19, 85,254, 19,196, 87,145,246,220, 54,235,233, 47,100,164,191, 51,210,
+187,134, 90, 84,245, 95,186, 47,242, 43, 96,237,236, 24,236, 95, 84,173,252,227, 97,243, 10,152, 32, 72,192, 72,253,213, 30, 2,
+214, 21, 35, 95,143, 58, 97, 11,227,206,189, 22,172, 90,180,169,110, 17,143,146,215,222,112,185,122,237,199, 91,147,114,243,122,
+123,129,244,217,155, 65,115, 96, 61, 85,198, 39, 31,108,145,236, 20,244, 62,241,167,139, 3,233, 21,212,230, 86,228,112,148,163,
+ 27,218,220,126, 75,208, 47,164,240,229,226,104,217, 45,170,103, 97,202,246,227,234,225, 65, 6,252,171, 64, 83, 99,199,159,170,
+148, 27,139, 30, 6,152, 77,141, 47,182,128,238, 3,135, 63, 73, 52, 65,206,212, 16, 65, 54, 30, 52,117, 28,111, 70, 5, 85,185,
+ 21, 34,212, 52, 28, 69, 26,161, 14, 2,153, 34,220, 90,158, 41, 30,214, 53, 65,229,127,137,194, 81,155,128, 79,240,140, 79,163,
+250, 90,189,239,163, 77,108,251, 24,227, 30,216,193,242,214,224, 24, 77,110,125, 77, 71, 94,175, 95,228,169, 59,247,110,226,119,
+ 22, 8,197,201, 38, 57, 16,235,130,117, 0,178, 55,176,243, 7,196, 86, 30, 62,196,239, 13,166, 86, 59, 78,122, 42, 55, 54,134,
+103,136,159,233,169, 22,250, 77, 1,172,238,153,251, 83, 25,177,207,112,162,201, 43,135,242,234, 80,185, 0,105,213,240,131, 97,
+ 89,190,242,109,154, 94,205,193,159, 99,140,199,132,217,163,166, 44,202, 56, 36,225,172,173,252,224,104, 80,254, 29,111,155,134,
+ 72,201,223,179,214,196,128,236, 29,166,152,139,242, 5,192, 81,243,159,101,105,251,159,181,100,220,246, 28, 77,151,104, 49, 64,
+184,178,163,168,152,176, 93, 9, 28,137,205, 21,201, 98, 94,244, 5, 79,225,102, 6, 25,219,114,247, 25, 34, 87,201, 51,152, 3,
+176,185, 84, 84, 71,178,250, 46, 95,141, 95,247,186,176,237,109,199,203,160, 15,161, 47, 97,246,122,137,175,254,141,233,189,151,
+176,230,118,238,215, 54, 22,107,197, 36,178,100, 52,202,208,150,101,210,201, 26, 88,235, 84, 55,186, 85,244,209, 71,145, 19,193,
+ 50,135,138, 85, 41, 34, 55, 16, 85,133,136, 62,218, 3,196,251, 74, 62,224,147, 42,117,237,233,163,135, 35, 66,245, 58,130, 50,
+ 74, 95,236,245, 21,248, 95,157,171, 91,145,131,248,153, 54, 60,177,100,230,227,156,119, 70, 89,131,140,112,165, 8,179, 92,244,
+189, 20, 28,223,195,157,199, 7, 52,102,118,230,112,139,222, 45, 18, 72,204,142,159,205, 18, 32,109, 67,219,106, 76,142,216,252,
+ 65,221,163,242,123,142,225, 31,150, 54,214,173, 37,148,129,250, 75, 18,123,223, 45, 10, 47,100,246,214,233,179,239,139,149, 52,
+184,239, 11, 68,241,202,176,204,174,214, 32, 17,238,175,243,128,168,121,157,239,189,110,251,184,193,237,248,161,131,169, 46,140,
+105, 12,104,210, 55, 30, 14,205, 32, 42, 61, 60,184, 86,215,181,187, 75, 15,182, 99,118, 87, 57, 25,179, 0,179,100, 17, 97,164,
+113,208,131,141,135,167,211, 89, 61,207,240,227,117,199,220, 78,119,111,228,160, 65, 39, 86, 20,102, 49,201, 17,190,160, 20,128,
+ 65, 3,195,149, 8, 89,174,199,248,137,144, 9,202,223, 97,133, 79, 22,233,240, 97,233,248, 34,140,124,198,177, 93,156,161, 59,
+199, 5, 21,250,170,179, 72, 4,131,147, 0,143,239,124,181,177,255, 0, 46,247,238,235, 31,150,222, 55,132,131, 16,251,178, 44,
+ 90,117,178,248,143,221, 36,119,249, 90,129,178,254, 31,110,219, 62,255, 0,143,185, 44,248,242, 98, 99,202,197, 84,187,245, 76,
+100, 50,139,142,144, 93, 90, 79,166,215,160, 25,248,181,255, 0,201,255, 0,246,159,251, 26,209,254, 31,255, 0,229, 61,191,254,
+ 55,254,190, 74, 15,123,246,212,221,199,141,142,113,100, 72,242, 49, 25,202, 9, 46, 21,132,128,106, 91,168, 54, 62,224,170, 30,
+223,237,126,245,219,114,112,215,205,136,182,232,167,142, 73,177,214,118,210, 99,214, 26, 69, 8, 5,189,225,126, 20, 6, 79,108,
+ 49, 47,120, 66,119, 59,105, 25,199,175,175,150,190,161,248,181,120,106,231,122,247,123, 86, 35,186, 63, 15,225,222,178, 95,113,
+219,166, 92, 92,185, 56,205, 27,130, 99,118,253, 43,173,202,147,227,192,213, 26,246,151,226, 10, 69,228,147,114, 35, 24, 13, 33,
+ 70, 84,129, 52,250, 7, 11,219,213, 64,103,123,199,162,221,215,184,121, 14, 32,204,186,122,127,237,116,175, 82,214,241,234, 94,
+172,255, 0, 18,245,125,251,141,174,218,252,154,106,183, 43,245,101,189,105,187,107,240,225, 54,188,184,247, 13,222,116,201,158,
+ 19,174, 40, 98, 7,166,174, 56,135,102, 96, 11, 91,195,128,164,238,238,203,221,123,147,115,143, 59, 6,108,120,226,142, 17, 9,
+ 19, 51,171,106, 87,145,238, 52, 70,226,214,127, 77, 1,163,237, 12, 28,108, 14,220,219,134, 58, 4, 51,227,199, 60,204, 7, 22,
+121, 84, 72, 75, 31, 30,118,171,207, 26,137,180, 98, 73,131,181,224,224,204, 85,164,197,199,138, 25, 10, 92,169,104,209, 80,233,
+184, 6,215, 30,138,151,192, 80, 28, 77, 54,150,184,143, 69, 1,222, 22,161,192, 56, 55,180,209,109,194,133, 0,184,111,105,160,
+ 12,183, 30, 52,190, 20,203,211,129,240,160, 59,215, 75,126, 22,164,183, 31, 93,117,135, 42, 2, 85,191,113,255, 0, 7,254,218,
+186,146,223,184,183,251,159,251,106,234, 0,206,126, 31,232, 39,236,138, 64,126,154,231,191,187,253, 4,253,145, 76,191,207, 64,
+ 50, 91,106, 30,206, 38,152, 64,244,243,164,152,251,227,217, 76,213,198,244, 1, 47, 97, 93,168, 86, 71, 47,241, 35,178,112,114,
+231,195,203,222, 35,139, 39, 26, 71,134,120,202, 74, 74,201, 25, 40,235,193, 8,224, 69, 46,245,248,131,219, 91, 38,209,143,190,
+201,144,115, 48,114,164, 49, 99,201,134, 4,186,156, 2, 74,252, 74, 1, 22, 60,205, 1,172,185,164,181,249,154,137,131,153, 30,
+225,133,141,159, 8,101,139, 42, 36,157, 21,192, 12, 22, 69, 14,161,172, 72,189,143,166,164,222,212, 4, 41,238,102, 96, 56,218,
+192,124,212,203, 55, 42,121, 33,164, 45,224, 77,234,171,184, 59,135,110,237,157,181,247,109,204,184,198, 70, 84, 61, 37,214,218,
+155,225, 0, 92, 84, 41,104, 20,242,165,211,225, 81, 54,141,211, 31,120,219,113,119, 92,101,116,131, 46, 53,154, 37,144, 0,225,
+ 88, 92,106, 10, 88, 95,229,169,122,168, 6,170, 95,133, 46,129,122, 85, 96, 9,168,249, 27,150,223,132,234,153,153,112,227,188,
+132,116,214,105, 21, 11, 95,244, 67, 17,122, 2, 80, 80, 45, 75, 96, 5, 38,176,108, 71, 16,120,131, 81,178,247, 61,191, 13,210,
+ 60,188,168,113,217,254, 5,150, 69, 66,215,225,238,134, 34,244, 4,196, 80, 88, 3,225,115, 78,210,191,162, 62,106, 7,154,198,
+129, 12,217, 18,164, 81,139,126,241,216, 42,241,229,197,184, 87, 67,185,109,217, 46, 99,199,203,134, 86,181,244,199, 34,177,176,
+230,108, 13, 64, 74, 9, 25,251, 0,154,225, 18,122, 57,212, 29,219,121,219,118, 77,189,247, 29,207, 41,113,177, 35, 33, 94, 86,
+ 5,128, 44,116,175,192, 9,226, 77, 35,111,155, 92, 91, 87,223,143,146,163,110, 48,140,147,147,199, 79, 73,134,160,246,181,248,
+131,232,160, 39, 20, 77, 95, 39, 42,227, 26,112,183,242,154,139,182,238,216, 59,174, 20,123,142,221, 48,159, 19, 35,222,138, 80,
+ 8, 12, 1, 42, 77,152, 3,204, 84,192,202, 79,179,136, 52, 3, 4, 98,231,152,249,105, 26, 63,231, 55,206,105,228,142, 36, 16,
+ 42,163,124,238, 93,143,183, 82, 55,222,115, 87, 20,205,113, 12,118,103,119, 35,158,136,227, 14,237,111, 80,160, 28,199,223, 99,
+110, 4,147,115, 77, 36, 14, 55,191,170,160,109,123,214,209,189,226, 62,118,221,155, 30, 70, 60, 68,137, 92, 18,166, 50, 5,200,
+145, 92, 43, 39, 15,210, 21, 23,108,239, 30,215,221,179, 70,223,182,103, 44,249, 39, 86,133, 17,200,170,250, 62, 46,156,142,138,
+143,107,125,147, 90, 5,215,188, 71,186, 45,235,165, 8, 62,209,189, 67,220,119,140, 13,172,227, 12,249,215, 28,101,202,184,248,
+229,129,179, 74,255, 0, 10, 92, 2, 1, 62,186,231,220,240, 6,226,187, 87, 88, 28,246,136,228, 8, 44, 73,233, 6,209,172,216,
+ 88, 13, 92, 56,154, 2, 96,210, 24, 42,142,117, 33, 69, 81,238,125,193,180,108, 77, 1,221,242, 70, 63,152, 44, 32,186, 59,106,
+ 40, 1, 96, 58,106,220,175, 83, 54,141,247,105,223, 97,121,246,140,180,202,142, 54,209, 38,139,130,141,206,206,172, 3, 15,148,
+ 84, 96,180, 95, 10,120,166, 47, 58,108, 25, 56,249, 73,213,198,149, 38,142,229, 75,198,193,215, 82,155, 48,186,147,196, 26,164,
+ 11, 67,149,173, 97,233,162, 26,107,129,107,208, 10,188, 20, 83,129,227, 76, 44, 5,129, 52,183,241,189, 1,210,120, 15, 75, 10,
+ 32,160,187,128,203,115,227,115, 75,215, 79, 14, 52, 1, 9,240,174,166,151, 22,227, 77,105, 81, 79,143,207, 82,162,131,155,227,
+ 65,237,167,212,115, 48,212, 8,240,191,211, 69, 15, 74,138, 4,231, 74, 5, 4,202,160, 94,194,134,217, 32, 14, 85, 69, 9,118,
+ 54,229, 77, 38,220,248, 80, 35,201, 46,214,181,135,166,136, 94,194,245, 27, 69,163, 7, 36,124, 89,239,236,163, 37,130,168,191,
+133, 2,105,192, 26, 71, 27,243,166,121,166, 0, 11,114,162, 4,190, 2,184, 17,127,205, 65,134, 86,126, 39,149, 22,252, 46, 57,
+212,114, 72,109, 99,201,161,195,109, 36,131,126, 38,153, 36,225, 69,188, 77, 9,102, 42, 44,181, 83,169, 40, 76, 23,191, 35,244,
+ 82,177, 4,212, 88,178, 11, 16, 26,142, 13,234,129,235,111, 79,209, 72,121,240,174, 21,198,128, 95, 10, 20, 12, 44,220, 45,198,
+141,225,122, 14, 63, 16,195,215, 64, 20, 94,150,222,154,238, 70,184,216, 11,154, 16, 82, 43,129,161,245, 86,214,191, 42,238,170,
+208,164,219,254,227,151,246, 63,246,213,212,206,168,232, 95,253,205,255, 0,235,173, 93, 64, 35,203, 37,147,143,246,113,147,192,
+120,162,211, 58,143,233,174,113,252, 63,238,227,253,133,166, 80,160,178, 36,147, 88, 1,184, 91,208, 40, 66, 89, 44,120,220,250,
+197,118, 73, 58,199,179,242,154, 7, 26,160,249,171, 55, 34,104,187,179,189,132, 91, 80,221, 76,255, 0,121,196,247, 93, 94, 85,
+ 91, 38,231, 48, 13, 45,198, 43,112, 60, 45,126,116,153,178,237,255, 0,255, 0,152,224,227, 97,206,242,204,187,179,203,152,146,
+ 46,147, 28,143,142, 84, 42,113,107,166,148, 22, 62,155,214,219, 39,240,215,189,163,223,119,221,211,104,220, 48, 49,226,222, 95,
+ 42, 55,214,210, 25, 60,182, 84,189, 82,132,116, 24, 43, 88, 14, 71,216,105,114,127, 7, 55, 20,237,136,182,156, 12,220,121, 55,
+ 7,203, 25,121,115, 76, 94, 56,180,172,109, 26,199, 30,132,145,141,181, 94,228, 10,128, 15,114,247,222,235,128,253,187,219,120,
+123,167,220,152, 67,110,197,151, 55,113, 88,140,206, 11,197,238,141, 42, 25,180,141, 35,225,244,213, 59,254, 40,247,140,221,158,
+178, 46,224, 99,206,199,205, 92,121, 50,150, 56,181,201, 12,145, 52,136, 24,148, 54,101,104,207, 17, 98,107, 99,220, 95,135, 27,
+214, 76,251, 54,243,176,229,193, 14,241,182, 98,193,141, 50, 77,115, 19,152, 23, 78,180, 37, 26,252,202,217,150,196, 80,183,238,
+196,239, 94,230,216, 35,195,220,178,118,229,207, 76,193,144, 4, 65,162,133, 33, 17, 24,244, 94, 56, 73, 47,173,137,226, 62, 90,
+ 2,155,183,187,195,187,176,187,215, 3,109,223,183, 17,149,135,147,138,146,203, 18, 40,208, 35,124, 95, 52,140, 61,213,109,107,
+ 97,115,227,198,179, 93,197,220,221,213,221,219, 38,225,187,101,229, 36, 91, 44, 89,145, 65, 30,220,170,162,204,225,228, 79,120,
+ 46,163,160, 47, 18, 79, 27,215,161, 71,248,111,188,127,155,246,237,242,121,177, 91, 3, 27, 22, 12, 92,136,131,201,213,110,158,
+ 47,149,125, 3,165,166,215,229,118,229, 89,255, 0,255, 0,200,123,194, 60, 28,237,155, 27,114,195, 27,108,185, 9,145, 18, 72,
+ 94,242, 52,122,145, 25,200,137,138, 29, 15,196, 11,241,249,232, 8,217,189,235,184,224, 97,118,191,110, 98,110,159,114, 97,125,
+221,143, 54,110,226,177, 25,156, 23, 82, 84,104, 80,205,164,105, 31, 15,167,213, 81, 91,241, 51,187, 37,236,225, 42,231,152,243,
+160,205, 92,121, 50,150, 56,181, 73, 12,145, 59,168,107,161,179, 43, 70,125,225, 99, 90,189,211,240,203,125, 9,176,238,123, 38,
+102, 60, 59,214,211,139, 14, 44,235, 38,163, 12,134, 16,108,232, 90, 54,191, 6, 42, 67, 45,136,162,239,253,139,222,221,205,176,
+ 69,133,185,228,237,203,158,185,131, 33, 68, 65,226,133, 33, 17, 24,244, 94, 56, 73, 47,173,137,226, 62, 90,128,208,246, 7,249,
+187, 41,114,247, 94,230,147,252, 54,116,120,210,237,112, 43, 43, 8,227, 42,229,181, 5,227,168,174,130,111, 89,159,197, 14,204,
+237,188, 77,187,119,238,172,236,137,134,231,148,241,140, 69, 46, 2,117, 44,168,177, 34,105,227,117, 82, 77,205,122,110,211,143,
+ 38, 6,215,131,131, 49, 13, 38, 54, 60, 80,200,201,114,165,163, 69, 66, 84,144, 13,174, 61, 21,231, 95,136, 29,141,222, 93,227,
+187, 71, 52, 25, 88, 48,237,152,130,216, 88,242,201, 45,238,108, 94, 73, 20, 64,203,169,136,229,196, 91,229,160, 52, 63,133,203,
+185, 47,100,109,191,121, 22, 46, 67,156,113, 37,245, 8, 11,158,149,239,225,167,225,254,109,171, 45,248,161,217,157,183,139,183,
+110,221,215,157,145, 48,221, 50,158, 49,136,165,192, 78,165,149, 22, 36, 77, 60,110,170, 73,185,171,105,123,127,241, 41,187,106,
+ 12, 8,183,188,116,222, 35,202,105, 36,202, 86,101,140,227,116,244,164, 75,167, 31,193,184,219, 71,203, 85,253,245,216,157,237,
+222, 27,132, 18, 38,102, 4,120, 24,104, 23, 22, 9, 36,152,146,246, 29, 73,100, 81,142,203,169,136,249,190, 90, 2, 11,237,253,
+193,159,248, 39,133,130, 49,103,204,205,201,157, 6, 52, 72,141, 36,190, 88, 74,210, 71,112, 1, 33, 66,167, 2,120,105,181,119,
+224,254, 71,107,227,239,175,183, 29,175, 39,110,238, 88,241, 91, 30,115,145, 33,145, 36, 40, 80,207,104,217, 80,196,250,146,250,
+108,108, 46, 47, 91, 8, 54, 95,196,136, 59, 78, 28, 72, 55,188, 63,243, 4, 25,157,110,185,254, 3, 98,116,140, 99, 28,131, 0,
+227,169,175,240,120,115,168, 61,141,248,125,187,109,125,195,149,221,253,213,157, 6, 86,235, 56,125, 9, 1,247, 67, 75,193,221,
+142,152,197,244,251,160, 40,181, 1,117,248,139, 10,100,236,216,120,130, 48,233,151,186,109,248,238,166,220, 67,100, 39, 14, 62,
+155, 86, 79,105,119,204,237, 61,163,178,165, 58,242,134,246,219, 62,104,251, 70, 12, 9, 91, 54, 95,250,152,213,107,115,220,251,
+ 62, 86,246,155, 66,225,203, 10, 12, 45,215, 19, 63, 32,204,204, 47, 14, 59, 51,186,199,161, 94,238,120, 88, 27, 15, 93, 85,237,
+189,153, 54, 23,226, 6,127,116, 62, 68, 45,181, 76,175, 38, 30, 40,102,234, 38, 76,233, 12,115,200,192,168, 95,120, 70,220,155,
+198,128,206,118,134,122, 97,126, 26,118,249,109,235,238,115, 35,229,160,104,241,215, 47, 34,102,243, 19,105,142, 24,153,100, 55,
+ 28,205,144,209,240, 59,223,124,155,182,158, 49,211,159,124,151,124,110,222,194,203,158, 3, 7,130,191,153,159, 31,221,208,202,
+164,221, 45,192,218,227,157, 38,201,216,157,209,219,184,251, 12,248, 83,237,249, 27,142,209,231, 34,151, 30,105, 37,242,239, 22,
+ 91,107,234, 71, 32,136, 50,186,248,251,188,106, 92, 93,137,189,141,155, 55,173,157,134,155,233,223,100,238, 29,186,120,117,182,
+ 56,145,130, 14,156,170,224, 56, 86,179, 92, 13, 86,225,196,208, 27, 61,143,108,221, 48,113,221,119,141,207,239,105, 89,181, 71,
+ 41,199,143, 27, 74,219,224,211, 23, 3,199,198,179, 27, 84, 17,102,254, 36,119, 62, 94, 74,131, 46,211,137,131,141,129,171,142,
+152,242, 34,105,229,100,191, 47,120, 90,226,180,219, 36,251,251,193, 35,119, 26, 97, 65, 53,192,134, 60, 41, 36,144, 88, 14, 37,
+218, 85, 94,103,144, 30, 21, 69,190,236, 91,196, 59,233,238,126,216,155, 24,228,207, 2,226,238, 56, 25,101,150, 41,209, 27, 84,
+114, 35,198, 24,172,139,203,136,181,168, 12,230,239,182, 9,251,219,116,218,112,159,203,141,255, 0, 98,144,229, 20,224, 58,203,
+ 33,134, 57,156, 14,126,235,105, 53, 51,180,247,185,113,101,195,236,222,224,192, 27,126,235,135, 8, 92, 23, 64, 27, 31, 38, 56,
+ 83, 73,146, 7, 28,155, 69,203, 15,111,178,164,237,251, 6,255, 0, 30,102,229,220, 89,249, 24,173,191,229,227,140, 92, 24,227,
+ 14,216,184,209, 41,234, 44,100,157, 46,225,159,139,125, 20,200, 54, 94,227,221, 55,237,191,120,238, 63, 39,143, 6,208, 37, 56,
+152,248, 77, 36,141, 36,179, 47, 77,158, 71,145, 83, 74,129,200, 15,150,168, 44, 59,207,109,196,221,123,107,113,198,204,144, 64,
+145,196,211,199,146,220, 58, 82, 66, 58,137, 37,199, 30, 4,113,245, 85, 31,225,140,146,111,152,153,189,205,157, 42,205,187,102,
+ 72,184,217, 33, 69,186, 41,140,170,137, 22,159, 13, 87,214,125,181,121,220,219, 54,127,112,195,137,181,227,188,113,224, 73,144,
+143,186,134, 44, 36,146, 8,200,126,140, 96, 41, 30,249, 30,241, 36,112,162,109,157,179,155,179,119,110,118,233,183,201, 8,217,
+119, 72, 80,230, 98,146,203, 34,229,199,117, 89, 98, 80,165, 52,178,243,247,135, 63, 85, 1, 79,223, 82,203,131,220, 61,161,145,
+ 6, 52,153,146,166, 70, 81, 92,104, 74,137, 28,244, 64,178,153, 25, 87,198,252, 77, 65,216,247,168,176,247, 30,245,238, 60,236,
+118,193,220, 35,134, 41,164,217,156, 17, 32,139, 26, 38,233,200,236, 6,135, 50,159, 21,184, 30,158, 53,164,238,237,147,120,220,
+119, 45,139,115,217, 78, 41,151,105,150,121, 94, 60,199,146, 53,126,172, 98, 48, 1,138, 57, 15,166,161,224,246,126,110,102, 94,
+245,185,247, 52,208,190, 86,241,139,247,121,199,195, 13,210,135, 31, 77,142,151,148, 6,102, 39,141,236, 62,168, 12,254,211,222,
+ 91,214, 94,102,215, 4,123,212,121,114,239, 81,201, 30, 68, 11,132, 85,118,249,222, 34,240, 73, 19, 21, 78,170,163,217, 88, 59,
+155,250,105,157,145, 46,227,182,246, 76,153,217, 93,192,155,126, 19,101, 72,144,177,197, 70,104,216, 77, 32,144, 38,162,221, 71,
+148,252, 35, 79,187,232, 53,169,237,252, 78,246,218,134, 30,213,184,182,223, 54,219,134,130, 31, 59, 25,151,204, 73, 20,104, 86,
+ 33,210, 32, 34,191, 5,212, 75,124,245, 65,141,217, 93,219,137,129,139,141,141, 38, 11,253,201,184,182,227,182,107,105,109,144,
+ 36,103,102, 73,215, 71,184,203,175,221, 34,254, 62,218,160,186,236, 62,226,220,247, 93,199,125,218,183, 12,151,205, 77,177,241,
+155, 23, 46,124,111, 39, 59,199,146,143, 37,164,131, 76,118,182,142, 7, 72,184,227, 91,105, 13,150,178, 93,173,179,111,120, 59,
+238,255, 0,190,111,143,139,213,222, 60,153, 72,241, 26, 66, 19,203, 70,241, 21,110,170,175,164, 88,248,243,176,229, 90,119,147,
+ 81, 32,114,240,161, 14, 23,102,213, 69, 98, 21, 73, 60,169,131,221, 80, 60,105,174,192,139, 30, 53,142, 44,215, 0, 26,153,137,
+ 52, 72,148,146, 88,215, 40, 6,159,112, 15, 14, 85,167,192, 33,236, 66,161, 36, 84, 93, 68,220,209,100, 33,128, 28,125,116, 48,
+162,162, 84, 12,124, 75,168,221,185, 10,146,156,175, 66, 93, 42, 0,181,115, 48, 9,194,250,143,213, 81,213,178,130,150, 66, 95,
+135, 33, 77, 37,143, 15, 77, 48,209,162, 85, 30,241,249, 43, 92, 17, 2,198,186, 20, 83,221,180, 45,205,168,122,135,230,161, 76,
+234,205,164,114, 31,203, 88,165, 89, 70, 95, 81, 36,210,170,234, 96,180,193, 82, 96, 80, 1, 98, 56,147,194,182,221, 17, 3, 40,
+ 10, 0, 95, 10, 43, 54,133,185, 60, 0,160,221,125, 28, 56,208,242, 36, 83,238, 47,202,107,154, 85,101, 2,236, 93,203, 26,238,
+ 64,113,166,159, 80,163, 66,138, 72,102, 28, 5,116,224,140,132,130, 43, 11,158,102,140,166,198,212,221, 75,225,192,120,215, 49,
+ 64, 11, 30, 96, 86, 19,117,243, 52,214,129,212,142, 20,230,181,174, 79, 42,138,153, 8, 1,191, 19,232,161,188,205, 33,227,193,
+125, 21,208,197, 3,174, 72,107,171, 11, 15, 3, 86, 24,219,111,238, 86, 94,175,241, 0,123,105,229,113,127, 77, 82,151, 26, 74,
+ 91,226, 35,141,107, 32, 83, 28, 17, 68,220,209, 21, 77,185,112, 22,164,117, 15, 68, 65,108, 27,113,234,127,209,252,245, 95, 54,
+174,155, 91,199,133, 94,205,196,112,172,236,185, 9,121, 33,251, 74,197,126, 99,106,173, 82,132, 92, 16,134, 21, 17,235,235, 49,
+ 58,110,170, 57,222,153,251,157, 23, 18, 72, 95,197,120,125, 84,130, 70,141,150, 67, 31,186,163, 77,207, 35, 76,137,139, 92,219,
+137, 55,172,212,213, 11, 30,154,249, 14,166,182,215,208,181,189, 93,125, 87,174,165,185,242, 90,111,253,135, 63,248,246,174,171,
+ 81, 65,210, 15,225,255, 0,119, 31,236, 45, 14,159, 39,246,127,221,199,251, 11, 76,160, 34,228,219, 88,246,126, 83, 64, 60,168,
+249, 63,196, 30,207,202,104, 60,170,131, 34, 59,251,110, 84, 70,146, 7, 82,216, 57, 91,131,241, 4, 47,148,105, 17,225, 39,244,
+137,133,237,236,171,168,247,253,186, 71,242,166, 80,185,203, 23, 86, 76, 78, 55, 86, 17,137,154, 61, 86, 10, 92, 43, 92,175, 59,
+113,181,171, 31,151,248,125,184, 79, 46,107, 38, 68, 10,153, 27,136,154, 37, 37,253,220, 9, 14, 75,100, 99,176, 9,241, 22,204,
+144,170,142, 28,184,213,154,246,166, 96,238, 28,141,192,132,124,119,158,124,184,102,124,140,139,171, 79,141,229,122, 99, 16, 30,
+130,176, 37,175, 39, 18, 87,133,189, 0, 92, 97,119, 78,209,147, 22,220,100,157,113,242, 55, 44,120, 50,161,199,123,221, 87, 33,
+117, 70,174,192,105, 5,184,133,185,247,136,225, 68,135,186, 59,126,124,121, 50,226,220, 35,104, 34,104,209,228,247,128,188,231,
+ 76, 54,184,185, 18, 31,132,142, 7,194,179,184,125,169,188, 97,195, 6, 7,248, 73,113,231,194,219,177,115,167,114,204,209, 54,
+ 12,109, 28,134, 4,100,247,203, 92,116,216,149,210,120,218,186, 30,211,221,228, 24,210,100,182, 60, 82,226, 13,163, 29, 86, 55,
+118, 71,135,107,200, 57, 18, 74,111, 24, 33,228, 12, 66,167,135,139, 80, 26, 28,110,232,216, 50,186,134, 12,244,101,134, 23,201,
+148,176,100, 11, 20,103, 76,142, 75,170,252, 7,131, 14,107,227, 83,113,119, 61,191, 51, 18, 76,236,105,131,227,197,168, 74,214,
+ 96, 80,160,187, 43, 35, 0,192,129,198,196, 86, 58, 78,201,220,165,197,147, 28,207, 2,151,196,221, 49,213,131, 73,252, 76,220,
+244,206,131,146,131,164, 42, 89,200,226, 15, 43,214,139,182,118,169,246,172,108,175, 49, 26,195, 46, 94, 75,100,180, 99, 34,124,
+182, 23, 72,226, 29, 73,242,137,119,107, 70, 61, 3,195,215, 81,128,123,103,121,108, 27,164, 59,124,139,144, 32,155,113, 72,228,
+135, 30, 80, 67,142,171, 20, 69,114, 1, 80, 89,148,170,241,247,143, 43,210,247, 39,119,109,253,183, 32,131, 38, 55,150,102,196,
+200,205, 85, 65,192,174, 54,155,173,207,139,106, 54,246,113,240,172,238,217,217,155,214, 38, 38, 62,221, 59, 99, 24, 92,109,169,
+149, 60,114,185,100, 27, 92,253,101, 49,171, 68,186,186,202, 20,113, 35, 73,191,197, 86,189,235,219,219,151,112,116,254,238,120,
+ 23,252, 22,126, 20,158, 97,221, 45,230,196, 58, 29,116, 71, 37,244,180, 60, 71, 14, 7,228,168, 11,100,238, 45,179, 34, 76,113,
+137, 60,114, 69, 44,242,227, 75, 35, 49,140,163,195, 11,100,176,210,234, 53,123,170, 15,135,186,117,114,169, 27,126,243,181,238,
+145, 75, 62, 6, 74,205, 28, 54, 50,155, 50,149, 12,186,213,172,224, 29, 44,188, 84,242, 35,149,103,228,237,141,201,183, 41, 51,
+145,241,217, 27,114,200,207, 84,147, 91, 3, 28,219,103,221,234,174,161, 69,207, 83,139, 11,252, 62, 55,225, 70,237,189,147,114,
+219,112,243,241,242,132,113, 36,234,145,226,227, 36,210,100, 44, 65, 99, 40,192, 77, 50, 44,157, 61, 95, 2, 27,233, 95,154,128,
+177, 94,234,237,215,130, 25,215, 62, 51, 22, 65, 34, 25, 0,109, 44, 6,141, 77,123,112, 65,212, 91,177,247, 65, 54,189,114,119,
+ 46,217, 23,159, 57,143,229,151, 11, 48,224, 93,174,198, 73, 4, 17,229, 18,138,128,181,130, 73,199,135, 11, 19,202,179, 57,253,
+147,159,145,183,108,248, 71,165, 57,198,218,147,105,204, 79, 51,147,143, 16, 32, 69,170, 95,240,218, 26,116,247, 27,247,111,107,
+240,169, 27,151,105,110, 83,205,149,153, 19, 71, 41,147,114,151, 54, 56, 6, 84,248,133,162,155, 10, 44, 43, 60,248,192, 58,178,
+188,122,138,139,134, 94, 23,240,160, 53, 35,125,217, 83, 43, 31, 4,230, 71,230,178, 85, 26, 37, 82, 88, 17, 40, 45, 21,221, 65,
+ 81,212, 10,116,220,251,222, 21, 28,247, 71,111,234,200,182,108,127,225,172,178,216, 55, 18,100,232,254,239,221,253,231,239, 61,
+207,114,254,247, 14,117,158,147,180,247,117,204,218,196, 47,143,228,118,213,219,122, 72, 39,154, 37, 83,133,117,153,122, 65, 36,
+234, 22, 91,104,105, 24,145,107,112,189,234, 52,189,155,188, 76,211,181,241,160,141,101,139, 34, 60, 76,124,169,209, 37,145, 50,
+124,196,141, 12,154,122,184, 98, 68, 63, 12,108, 70,190, 62,186, 3,114,155,142,222,219,127,222,163, 34, 63,187,214, 54,153,178,
+137,247, 21, 18,250,203, 19,203, 77,141,253, 21, 77,153,222, 91, 76, 41,183,249, 54, 25,141,184,102, 12, 24,128,213, 31, 77,194,
+ 25, 36,105, 3, 38,161,165,109,238,145,115,113,225,198,154,157,186,223,228,217,187,111, 92, 80,100, 76,147,145,166, 73,102,137,
+101,154, 87,200, 26,164,156,153, 92,106,111,121,143, 19,196,216,114,168,233,176,110, 19,231,197,187,100,180, 16,228, 73,188, 38,
+231,145,140,146, 52,136,145, 69,128,219,122,162, 63, 77, 53, 57, 54, 99,112, 7,205,196, 9,187,175,122,237, 91, 70,230,251, 78,
+ 74, 57,158, 33,134,100,112,182, 80,185,147,249, 96, 79,244, 62, 35,234, 60, 56,212,247,238,126,221,232, 99,101,140,196, 72,115,
+ 11,249,119, 33,133,196,108, 34,144,176, 34,232, 21,253,214, 45,107, 30, 6,169,247,238,222,207,220,187,130, 45,207, 22, 76,113,
+139,109,179,172, 36,119, 89, 20,237,249,205,154,218, 85, 99,117,109,105, 33, 2,236, 56,143, 93,197, 54,103, 98,231,205, 4, 48,
+ 51, 67,144, 29,119, 8, 39,143,205,101, 99,198,169,155,154,217,145,200,195, 27, 67, 76, 4,109,165,163,107, 13, 86,227,227, 64,
+108, 55,173,225,182,201, 48, 49,161,196, 57, 89, 59,140,175, 4, 40,174,177,128, 99,134, 76,134, 44,207,195,225,140,213, 70, 63,
+121,237,185,240, 75, 51,198,248,145,227,195,139, 60,141, 41, 7,142, 75,207, 10,196,130, 61, 90,142,184, 8, 26,111,170,226,213,
+ 39,186,246,105, 55,183,218,165,135, 19, 15,112,143, 3, 34, 73,178, 48,119, 6,100,134, 85,120, 37,129,120,136, 50, 69,213,164,
+ 13,197, 60, 43, 52,189,133,185,199,137, 52,103, 34, 57, 72,242, 15, 4, 49,205, 52, 31,242,153, 57, 83,182, 58,204,171,212,141,
+ 86, 60,133,142, 39, 94, 62,239, 16, 40, 13, 4,253,207,176,227, 65, 14, 68,249,177,172, 83,163, 75, 19,123,198,232,140, 17,219,
+221, 4,128,172,192, 53,249,120,208,231,238, 45,190, 61,227, 27,100,141,250,185, 83,202,240,200,171,202, 34,152,239,151,239,146,
+ 45,240, 40,224, 15, 11,139,213, 52,253,139,159, 38,218,112,225,108,120, 93,246,189,199, 8,169,150,121, 20,100,103,100,199,148,
+167,169, 42,188,142,163, 75,106, 99,196,159,179,232,153, 47,106,110, 82,111, 38, 69,108,117,219, 78,110, 78,113,159, 91,245,255,
+ 0,197, 96,190, 23, 76, 69,163, 77,209,219, 85,245,241, 30,186,160,184,199,238, 62,222, 24,146,103, 46,124, 93, 8,217, 18, 73,
+141,192, 6, 83,104,173,112, 9, 87,251, 44, 56, 55,133, 31,112,222, 27, 26, 44, 73, 48,177, 37,206,124,211,251,148,142,209,168,
+ 77, 6, 82,242,188,186, 85, 6,145,110, 60,110,109, 89, 93,179,178,247, 28,124, 88,226,148, 67, 28,233, 62,210,206,231, 43, 39,
+ 40,201, 22,219, 55, 85,219, 86, 64, 58, 53, 93,186,113,170,128, 60, 79,163, 67,221, 24, 27,190,229,137, 22, 30,217,210, 48, 73,
+ 39,255, 0, 17,138, 89,228,198,105, 96,210,111, 10, 77, 12, 83,178,235,107,106, 32, 95, 77,192, 60,106, 1,205,220, 17, 79,179,
+ 97,239, 56, 56,211,101, 46,114,194,216,216,234,160, 72, 78, 65, 93, 58,201, 58, 80, 45,238,204, 77,128,244,211,240, 55,220, 60,
+173,174,109,218,127,240,112,227, 52,209,101, 9,136,253,219,227,200,208,202, 53, 41, 42,195, 82, 27, 17,206,161,238, 56,189,201,
+ 38,216,248, 91, 92,120,120, 18,116,177,227,132, 71, 52,128, 70,161,136,200,142, 55,242,254,237,163, 1, 98,110,159,174,194,194,
+156, 54,137,255, 0,202,242,236,241,224, 97,194,253, 51, 18, 97, 52,178,207,140, 86,247, 58,230,233,195, 41,103, 23, 37,180,223,
+ 87, 30, 52, 1,219,185,182, 13, 16,202,217,200,171, 49,116, 80,193,149,131, 33, 85,126,162,178,134,143, 73,117,185,112, 45,113,
+233,167,203,220,123,100, 51,182, 12, 83,199, 46, 92,115,195,143, 60, 37,138,104, 51,201, 28, 98,237,164,141, 95,189, 5, 87,237,
+ 86, 63, 39,177,183,140,149, 81,146,209,206, 38,143, 35, 29,224,151, 55, 41,122, 81, 77, 36,110,157,105,160, 17, 62, 94,149, 70,
+ 12,178, 90,252, 56,240,189, 95,205,219, 89,207,231,180,201, 8,243, 59,230, 30,236,151, 45,194, 12,127, 41,173, 27,220,248,207,
+151,107, 14, 92,184,213, 33,101,254, 98,216,175,152, 27, 50, 59,225, 6,108,130, 73, 1, 86, 54,208,228, 18, 44,218, 88,105, 58,
+111, 99,195,157, 27,111,207,196,220,161, 57, 88, 82, 9, 98, 12, 80,240, 42, 85,215,226, 87, 87, 1,148,143, 65, 21,141,199,236,
+220,252,115,158,141, 14, 54, 73,120,114,113,241,219, 39, 39, 42, 84,153, 50,114, 70, 78,150,134,225, 49,198,149, 0,244,193, 58,
+189,239,109,255, 0,111,224,111, 59, 86, 55,151,206, 49, 60, 18, 52,210,241,149,230,157, 11, 50,116, 99,105, 94, 52,234,217, 53,
+106,118,247,175, 97,196,113,168,250, 21, 23, 18, 72,215,225, 66, 50, 63,166,140,171,195,141, 13,210,238, 69,236, 5, 10, 52, 74,
+227,198,187,170,254,154, 94,152,253, 33, 75,209, 31,166, 42,144,103, 81,253, 52,162, 71, 30, 52,254,128, 36,141, 67,213, 77, 49,
+ 17,226, 62,122, 3,186,210,122,107,132,174, 77,137,225, 77,233,181, 33, 82, 57,138, 0,142,193,109,165,245, 95,159, 11, 82,117,
+159,151,162,146, 48, 25,192, 60,141, 73, 24,241,154, 2, 55, 85,233, 53,177,169,126, 85, 45,235,174,242,139,233,160, 34,235,106,
+120,158, 75, 88, 84,147,134,131,145,164,242,131,211, 80, 0,235,201,234,166,245, 28,243, 2,140, 33, 5, 72,244, 92,222,187,160,
+ 45,127, 69, 40, 1,235,106,120,153,192,210, 0,165,147, 28,158, 42,109,225, 81,220, 58, 54,150,231, 74, 2,122,182,160, 47,254,
+158,170, 4,178, 18,116,142, 66,134,146, 20, 91, 19,241,114,174,168,163,169,106, 31, 29, 18, 86,179,177, 95, 69,170, 88,192,132,
+241,235, 55,204, 42,185, 24,171, 11, 26,178,133,245, 47,174,180,101,149, 51,111, 61,165,141, 60,152,249, 29,195,131, 12,241, 49,
+142, 72,164,201,129, 25, 93, 77,153, 93, 89,193, 82, 15, 59,213,217,239, 94,203,176,255, 0,251, 30,215,255, 0,235,113,255, 0,
+239, 43,231,236,110,223,218,243,183,174,250,223,114,246,153,187,143, 43,109,220,222, 60,125,143, 30, 73, 35,102, 89,242, 37, 15,
+144,253, 11,202, 85, 52,219,221,249,107, 59,221,125,169,180,109,189,243,137,177, 98,179,225, 97,102,174, 36,179, 99, 76,225,229,
+195,108,149, 86,147, 25,223,197,146,252,205, 71, 37, 24,185, 62, 9, 85,251, 10,162,228,212, 87, 22,232,189,167,211,207,222,189,
+155,126, 29,197,182, 91,255, 0,206,227,255, 0,222, 85, 6, 95,113,246,129,150, 89, 87,184,182,226, 89,139, 0, 50,224, 60,205,
+255, 0, 78,190,124,238, 45,143,110,135,104,203,205,139,107,155,102,155, 7, 45,113, 97, 19, 72,206, 50,145,181, 93,128,147,237,
+ 46,155,146,188, 43, 95,218,221,139,219,217,155, 95,110,193, 62,197,149,187,127,152, 98,150, 76,238,225,130,119, 72,246,230, 70,
+100,208, 17, 1,143,247,122,110,253, 78,126, 30,138,205,171,241,189, 13,209, 77, 81,211, 90,126, 85, 71, 75,182,165,106, 74, 45,
+167, 85, 93, 43,249,209,158,193,182,238,123,102,241, 9, 59,118,108, 57,145, 67,101,144, 99,202,146,217,143, 17,168,198,205,106,
+152,177,128,186,163,184, 39,192,215,147,126, 8,121,124, 60,110,224,135,174,143, 26,101,199, 28,115, 92, 0,225, 85,198,161,127,
+ 72,227, 94,186,172,178, 68, 25, 24, 48,113,117, 96,110, 8, 60,136, 34,180,115, 36, 95,252, 23,243,186, 63,251,197,117, 47, 76,
+249,109, 54, 23,232, 91,254,190,245,212, 2,184,225, 31,247,113,254,194,211,105,207,246, 63,187,143,246, 22,153, 90, 4, 92,159,
+140,123, 63, 41,160, 27,222,143,146, 61,241,236,252,166,133,106, 3,205,101,239, 29,250, 60, 12,236,204,121, 83, 33,224, 77,205,
+165,143,203,176, 76, 95, 41, 44,145,227,177,148,123,141,175, 64, 5, 79, 19,225,200,214,144,119,158, 3,111,239,176, 42, 7,157,
+ 94, 72, 16, 36,168,211, 52,177, 65,230,155,252, 61,245,132,210, 10,135, 60, 11, 11,122,234,115,118,214, 11,108, 57, 93,188,100,
+155,202,101,249,158,164,154,151,168, 60,220,178, 79, 38,147,167, 79, 6,144,233,247,121,122,105, 63,203,152,227, 63, 39, 47,205,
+228,172, 25, 45, 36,178, 97, 43, 40,139,173, 52, 67, 30, 73, 46, 23, 89,186, 14, 10, 90,192,241,181, 1, 81, 31,125,227,182, 14,
+102, 83, 98,133,147, 14, 76,104,164, 81, 60,109, 18,121,174, 10,211,206,151, 88,250,102,226, 78, 7, 73, 30, 52,225,223,184, 11,
+159,133,129, 60, 2, 25,178,252,186,180,111, 52,125, 64,249,110,209, 69,210,140, 27,202,183, 0,179, 47, 0,164, 31,100,140, 62,
+205,139, 7, 29,226,198,220,243, 18, 66,152,241,137, 65,132,123,184,129,146, 37, 40,177, 4,101, 40,250, 93, 88, 16,121,243,227,
+ 68,194,236,236, 45,186, 92,118,194,203,202,138, 40,132, 61,104, 21,227, 11, 59, 99,187,201, 19, 74, 68, 96,143,122, 67,117, 66,
+170,120, 11, 90,128,145,187,111,178,109,249,177, 96,226,224, 75,159, 49,133,242,231, 72,136, 12,144,198,233, 25, 40,164,126,241,
+201,126, 10, 61, 28,234,151,111,239,137, 34,197,201,125,223, 24,129, 4, 91,134, 84,121, 17,178,129, 36,120, 89,167, 19,167,160,
+219, 73,247,144, 92,158, 60, 79, 10,189,221,187,126, 45,215, 34, 44,161,149, 62, 28,171, 19, 99, 76,216,204,170,100,129,217, 36,
+104,201,101, 98,190,244, 98,204,150, 60,248,212, 79,242, 94,210,208,188, 45, 36,236,143, 6,110, 49,247,214,225,115,242, 6,108,
+140, 8, 79,137, 36, 81,163,213,206,245, 24, 1,143,222,209,103, 99, 68,118,220, 65,155,155, 38, 84,184, 98, 24, 39, 71,132,180,
+ 48, 12,167,116,200, 80, 85,151,166,194,214, 31, 17,183,164,211,118, 46,236,125,211,121,204,217,222, 22,243, 17,204,100, 16,176,
+ 17,190, 54, 39,151,198,144, 25,193,185,214,101,152,160, 3,215,232,169,179,118,183, 90, 8,245,110,121,126,126, 41,228,200, 93,
+194,241,117, 3, 75, 17,199,145, 21, 58,125, 37, 77, 7,128, 11,192,241,231, 93,133,217,219,110, 6, 92,121,248,210, 78, 50,163,
+155,175,215,102, 86,118, 83,143, 30, 35, 67, 35, 50, 18,209,178,196,172,111,199, 87, 27,212, 5,110,255, 0,220,251,214,221,190,
+182,217,137,140,141,142,163,107, 40,196,141, 78,115, 51, 27, 26, 69,226,120,106, 85,210, 61, 4, 95,198,147, 39,241, 27,110,193,
+194,198,202,204,128, 66,210,140,151,158, 23,158, 53, 42, 49, 39, 56,146,172, 58,244,245,156,186,146,170,163,136, 30, 21,115,185,
+118,198, 38,231,186, 71,186,205, 60,241,203, 24,197, 13, 20,101, 4,111,228,242, 60,228, 37,181,198,205,193,201, 6,204, 46, 15,
+176,212,115,217,184,136,144,174, 54,102, 86, 49, 79, 50,178,188, 76,129,229,139, 47, 32,230, 75, 19, 49,143,221, 2, 67,238,178,
+ 89,128,225,127, 26, 3,187,175,119,201,218,229,218, 98,131, 35,202,197,153,145, 36, 89, 19,172, 13,146,202,169,143, 44,203,166,
+ 36, 4,155,180, 99,144,229, 84,221,189,220,251,182,237,184,227, 99,229,100,180, 72,248,216,115,175,148,193,147, 37, 36, 57, 18,
+ 78,133,166,146, 37,145,113,195, 44, 74,125,242, 52,220,254,137,182,199, 47,110,131, 51, 55, 3, 54, 86,113, 38,221, 43,205, 0,
+ 82, 2,150,146, 25, 49,136,123,130, 72,211, 41,229,110, 53, 87,182,118,132, 59, 94, 89,201,219,119, 76,220, 93,106,137, 60, 75,
+229,157, 37, 84,150,105,213, 91,171,140,236, 5,231,113,238, 17,195,215,198,128,162,206,239,125,202, 9, 59,145,161,104, 58, 24,
+248,217,114,236,163, 69,200,125,185,151, 31, 35, 89,191,189,170, 71,184,245, 81,187,131,184,187,147,105,131,117,219,113,165,135,
+ 39,115,197,151,109,242, 89, 38, 16,161,147,112,149,224,209, 36, 97,136, 44,173, 17,226, 45,192,138,179,159,240,235,183,102,219,
+225,193, 13, 44, 45, 20,115,195, 46,100, 93, 21,200,157,114, 81,163,148,228, 73,210, 58,201,213,171,151,196, 7,178,166,142,213,
+192,102,105, 50,243,114, 50,178,229,202,197,204,151, 50,102,136, 72,205,130,226, 88, 35,211, 12, 81,198,177,130, 56,133, 64,120,
+158, 55,227, 64,101, 51,187,255, 0,115,151, 39,117,200,218,204, 71,110,199,217, 31, 63, 16,148,212,124,210, 38, 36,247, 45,246,
+148, 38, 98,139,122,107,111,178,229, 73, 62, 20,249, 18,205,147,150, 81,155, 72,159, 10, 76, 25,125,213, 13,165, 33,200, 72,153,
+175,126, 13,107, 95,133,248, 85, 34,126, 31,246,236, 24,147, 97, 69, 60,201, 20,248,217,152,110, 21,227,191, 79, 54, 88,231,144,
+143,221,218,233,210, 85, 79, 66,142, 32,243,171,248, 49, 26, 60, 57,241,114,247, 41,247, 30,184,101,105,114, 6, 58, 58,171, 46,
+146,171,229, 33,129,126,112, 77, 1, 69,141,223,152,249, 56,211,200,184, 36,228,193,147,133,137,229,226,158, 41, 70,188,247, 88,
+162, 86,145,125,213,116, 98, 67,175,217, 35,153,168, 59,183,127,101,166,201, 54, 94,217,129,167, 62, 60, 76,252,169, 67,186,178,
+ 64,112,167, 56,108,120,129,213,188,163,128,225,238,143,146,172,112,251, 47,109,196,133, 34,108,220,169,250,109,128,234, 91,164,
+ 5,246,199,234, 99, 11, 71, 10,240,224, 3,250,125, 71,141, 38, 87, 98,237,121,120,173,132,153,185,120,241, 73, 30,100, 25, 13,
+ 17,140,188,144,231, 78,115, 37,136,151,133,192,211, 41,247, 72, 23,183, 14, 52, 5,214,249,188,201,181,182, 30, 54, 46, 27,102,
+230,231, 72,233, 4, 10,226, 49,104,163,105,228,102,118, 13,111,117, 44, 5,184,146, 61,181, 76,189,235, 28,249,113,196,251,108,
+208,226, 60,167, 13,114, 38, 42,174, 50,134, 47,158,104, 94, 31,137,108,170, 86,255, 0,164, 61, 28,106,223,122,218,161,221,252,
+180,139,149, 62, 22, 86, 35,179,227,229, 99, 42,235, 94,164,109, 4,139,105, 81,212,134, 71, 62, 28, 13,136,170,163,218, 56, 49,
+206, 37,131, 34,118,138, 50,102,135, 22,102, 13, 31,154,242,222, 75,204,179, 20,234, 22, 49,243,187, 90,228,181,175, 68, 8,184,
+125,241, 4,233,138,211,237,239,143,231, 6,223, 52,119,117,123, 99,238,108,241, 65, 51, 21,229,105, 19, 75, 47,172, 84, 57,187,
+232,229,109,153,249,120,120, 50,195, 22, 46, 0,220, 31, 44, 52, 68,164,114,245,250, 5, 17,199,190,207,208,191, 43,113,160,158,
+199,205,139,181,228,219, 86,113,149,187,100,224,225,109,198,105,100,211, 22, 58,226, 13, 74,208, 24,226, 86, 43, 28,172,206,186,
+134,163,195,143, 10,189,126,206,218,159, 15, 59, 7, 92,169, 14,126, 14, 62,217, 40, 70, 81,162, 28,101,145, 35, 49, 93, 13,154,
+210,155,222,227,151, 10,160,141,151,221,237, 22,224,248,113, 96,191,151, 25, 79,183, 38,105,117,183,153, 76,118,203, 97,210,248,
+180,133, 91, 95,211,244,211, 69,223, 27,188,157,191, 30, 72,193, 95,188,146, 45,158,105, 88,186,244,228,143,115,145, 99, 46,170,
+ 45,164,146,172, 0,191, 11,131,233, 21, 59, 35,181, 51,114,123,144,101,137, 4, 91, 82,229, 28,246, 69,154,250,164,108, 87,196,
+107, 64, 97,247, 92,150,185,110,169, 91, 14, 10, 9, 53, 56,118, 78,216, 48,159, 5, 50, 50, 81, 95, 27,111,196, 18,134,143, 90,
+174,214,230, 76,105, 22,241,149,215,168,221,174,164, 31, 64,168, 4,238, 46,233, 27, 12,133,124,147,100,149,196,151,112,155, 76,
+138,129, 33,199,120,146, 79,136, 29, 77,251,222, 3,198,148,247, 73, 27,155,224, 38, 11,188, 39, 41,246,248,114,140,138,161,242,
+211, 28,229,244,180, 30, 33, 74,169, 93,126,159, 11,113,163,238,253,181,133,189, 60,167, 46, 89,129,151, 10,125,181,204,101, 7,
+238,178, 26, 55,119,226,135,223,188, 34,222, 28,248, 83,211,182,241, 6,232, 55, 62,180,165, 6, 65,205, 92, 51,163,162, 50,154,
+ 31, 42,103, 30,238,187,244,239,195, 85,174,111,107,208, 25,157,155,189,243,178,112,227,202,204,199, 50,230,205,143,182,152,177,
+ 35, 40,145, 52,185,207, 52,106,202,254,243, 40, 61, 61, 77,170,246, 3,135, 26,159, 39,127, 99, 69,184, 98,237,121,120,173,139,
+149, 51,195, 12,176, 77, 42, 44,203, 46, 68,173, 4, 98, 40,143,189, 42,106, 75,151, 31,100,131,236, 54, 39, 99,237,216, 80, 54,
+ 46, 62, 94, 86,181, 92, 69,198,157,204, 76,240,249, 9, 36,155, 31, 64, 17, 42,155,117, 74,157, 96,221,125,124,106, 76, 93,171,
+ 6, 30, 68, 89, 41,184,102, 19,120,155, 45, 89,208,249,153, 33,121, 38,141,230,109, 26,135,189, 41,186,161, 85, 34,194,214, 21,
+ 64, 29,235,184,151,100,204,146, 73, 86, 73, 34,131,109,202,220, 30, 4, 8, 3,116, 36,129, 62, 38,247,131,126,243,135,133, 13,
+251,182,119, 39, 18, 61,177,159,114, 92,217,112, 70, 39, 85,108,122, 88,235,152,210,117,116,219,248,110, 5,173,241,112,229,198,
+167,110,221,183,131,189,188,207,151, 36,168,102,194,159,110,110,145, 81,104,178, 26, 57, 29,134,164,111,124, 24,133,188, 61, 84,
+ 12,142,214,197,200,158,124,140,124,188,140, 76,169,114,159, 56,100,196, 99, 44,143, 38, 58,225, 72,136, 29, 25,116,152,208,115,
+ 4,134,227,122,207, 50,144,182,238,236,146, 76,137,162,203,129,215,173,159, 38, 46, 44,108,162, 55,137, 35,219,163,220, 74,204,
+167,237, 95, 82,159, 93, 69,159,188,167,203, 27,123,109,184,165, 99,201,125,165,242,102,148,169,233,166,231, 42,129, 16, 95,180,
+122,119,187, 14, 68,143,146,116,189,157,133, 18, 39,151,203,201,138, 69,201, 57,107, 54,164,119, 12,216,163,111,117,188,177,189,
+195, 68,188,205,206,174, 55,164,199,236,188, 0,112,250, 89, 89, 49,195,134,184, 42,209, 3, 25, 19, 54,218,193,241,158, 82,209,
+147,127, 6,209,166,255, 0, 37, 80, 67, 78,254,218,221,247, 21, 72,250,135, 6, 25,242, 18, 56,165, 71,145,215, 30, 81,142, 86,
+ 68, 83,120,153,221,151, 64,110,106,111, 86,189,189,184,103,110, 79,186,174,124, 75, 11,225,231, 28,100,137, 72,109, 40, 49,224,
+150,218,199,197,239, 74,120,250, 41,171,217,216,102, 28,220, 71,202,201,124, 60,148,154, 40,241,181,170,164, 11,145, 33,157,250,
+ 90, 80, 18,193,248,169,125, 86, 28, 61, 55,157,180,109, 13,181, 12,179, 20,242,229,203,153, 63,154,202,154,126,152, 38, 83, 28,
+112,157, 34, 36,141, 66,218, 33,194,212, 4,253, 30,245,173, 76, 96, 47,195,133, 74, 69,234, 33,123, 89,135, 49, 64, 96, 44, 77,
+ 0,145,240, 20,104,177,155, 41, 79, 16,182,241, 52, 21, 66, 65, 96,218,107,144,100, 1,120,175,111, 85, 82, 18, 70,221, 44, 95,
+189, 44, 8, 78, 38,140, 12,119,168,101,242,194,217,181,105, 60, 13,234, 64, 23,229,195,215, 64, 72, 83, 31, 27,210,106,143,157,
+ 15, 70,145,107,234, 60,233,109,194,128, 45,163, 60,207,203, 79,211, 29,249,242,168,230,231,228,229, 72, 79, 59,208, 18, 58, 81,
+219,194,184,192,156,175, 64,185, 7,157, 46,179,122, 1,239, 26,168,176, 53, 11, 50, 63,116, 55,136,163,181,203, 88, 82,116,196,
+238,168,126, 30,109,236, 20, 64,136, 49,229, 97, 25, 8,196, 31, 16, 13, 59,161, 63,251, 39,253, 83, 87, 74, 0, 1, 64,176, 28,
+ 0, 20,224, 7,162,183,179,196,149, 42, 34,197,148,157, 77, 19, 88,120,105, 53, 38, 8,102, 91,142,147, 1,127, 21, 53,100,130,
+164, 32,183,174,162,130,175, 17,185,112, 62,122,237,216,224, 94,240,239, 12,201,182,180, 39, 15,114,200, 51,111,185, 27,180,251,
+ 68, 88,203, 36,206,139, 3, 62, 56, 37,140,140, 57, 86, 39,190, 54,153,231,239, 52,218, 54,253,145,182,236,220,142,146, 38, 42,
+102, 73,159,230,101,153,139, 38, 66,100,205,197,132,161,215,253, 47, 86,219,159,115,227,236,221,203,222,123, 86,245,180,253,239,
+176,238, 91,182, 67,205, 7, 85,241,217,103,130,121, 90, 55,138,116, 13, 99,102,226, 45,196, 84, 41,247,189,255, 0,115,252, 64,
+218, 55, 63, 47, 7,111,228,227,140, 97,180,193,158, 94, 28, 88, 49,177,215,247, 11, 36,146,128,198, 50,170,110,222, 55,172,148,
+139,221,125,157,220,251, 70,222,155,134,229,185, 99,238,216,152,178,140, 76,134,196,203, 57, 94, 82,114, 47,208,152, 31,128,240,
+240,225, 91,254,206,194,199,151,180,177, 96, 78,219,143, 86,227, 17,233,225, 73,220, 25, 88, 83,110,173, 16,211, 44,176,225,160,
+208,110, 87,145,254, 74,175,239,200,241,177,123, 87,112,139,100,109,135, 18, 12,236,152,179, 55,136,182,253,212,231,228,228, 74,
+ 24,132, 88, 99,100, 77, 17,163, 72, 90,194,169, 59,127,190,223, 30, 45,155, 22,126,217,251,219,184,182,104,204,125,189,152, 36,
+153, 89, 81,181, 75, 31, 83, 26, 53, 61,109, 26,139, 39, 17,249,106, 36,146,162, 84, 94, 5,109,183, 86,235,230, 94,254, 24,174,
+ 44,184, 27,208,108, 73, 98,134, 77,202, 52,131, 18, 55, 5,163,102, 73,116, 66, 76,162,238, 71,195,202,247,175,114,195,195,200,
+ 76, 88, 16,227,202,154, 99, 81,161,193, 44, 44, 7, 6, 35,129, 53,227,191,131, 83,228, 28, 13,218, 76,150,101,203,147,119,197,
+105, 99, 42,218,158, 75, 72,204,140,170, 87, 79,189,250, 92, 1,175,161,198,166, 85,102, 5, 88,128, 89, 46, 13,143,162,226,173,
+ 8, 85,116,101,232,219,166,215,233, 90,214, 60,250,183,183,205, 93, 86,190, 31, 39,229,174,171, 66, 20,111,246, 63,187,143,246,
+ 22,155, 78,127,236,255, 0,187,143,246, 22,155,227, 66,145,178, 71,190, 61,159,150,131,234,163,100,124, 99,217,249,104, 39,137,
+225, 64,121,179,247,150,253, 30, 83,224,234,136,200,174,219,102,173, 2,255, 0,120, 62,107,195, 9,183, 14, 30, 93, 3,219,249,
+215,240,170,189,243, 59,113,125,169, 39,135, 40,226,198,112,251,143, 84, 16,130,138, 91, 31, 48, 70,175,125, 87,213,196, 27,248,
+113,183, 58,245, 47,186,182,222,161,144,225,193,212, 51, 12,162,253, 36,213,215, 11,160, 79,123, 95,168, 23,134,174,118,166, 77,
+178,108,217, 48,164, 89, 27,118, 52,177,196,101,104,209,224,141,149, 76,228,153,138,169, 83, 99, 38,163,171,211,126, 52, 5,118,
+195,153,184,229,141,235, 19, 43, 36, 73, 54, 22,107,226,193,146, 35, 85, 33, 78, 60, 19,169, 40, 56, 29, 45, 49,249, 57,214, 15,
+182,183, 93,239, 29, 48,114,188,251, 76, 36,135, 96,139, 33, 37, 80,250,215, 51, 35, 34, 6,247,152,146, 25, 85,190, 33,196,144,
+ 47, 94,171, 30, 60, 16,180,143, 12, 75, 27, 76,253, 73,153, 20, 41,119,210, 19, 91,145,241, 54,149, 2,231,192, 84, 88,118, 93,
+155, 24, 21,199,219,177,162, 82,201, 33, 9, 12,106, 53,196,230, 88,219,221, 94,104,236, 89, 79,129, 55,160, 49, 11,191,238,216,
+216, 88,179, 99, 73, 22, 62, 34,207,156,114,186, 72,146, 50, 21,220,100,130, 55,158, 38,110,168,133,128, 96, 94, 49,125,126,170,
+157,248,129,184,238, 49,227,103,237,248,153, 62, 86, 20,218,114,179,100, 96,160,188,140,175, 28, 74,129,184, 21,182,178,110,188,
+110, 71,203,168,109,139,102,153,161,121, 54,252,103,108,118,105, 32, 38, 36,186, 51,191, 85,217,125,222, 4,191,190,127,157,199,
+157, 23, 63,105,218,247, 65, 31,222, 88, 80,102, 8,181,116,198, 68,107, 32, 93, 66,204, 0,112,121,219,141, 1,141,206,222,183,
+ 92, 89, 55,127,187,153, 34,232,238,146,172,253, 21,141,242, 90, 24,240,113,229,234, 36, 83,176, 18, 5,119, 29, 77, 62,246,142,
+ 92,106, 62,223,186,239,178,247, 4,184,184,251,154,148,220,243,225,143,169,210,212,145,198,118,149,206,253,194, 72,125,208, 72,
+ 0, 95,218,120,147, 91,140,173,143,102,205, 12,185,120, 24,243,171,201,215,113, 36, 72,218,165,210, 35, 50, 53,199, 22, 40,161,
+ 73, 62, 28, 57, 83,198,211,182,174, 88,207, 92, 40, 6, 96,181,178, 68, 73,213, 26, 81,162, 95,222, 91, 87, 4, 98,163,143, 35,
+106,203, 7,157,190,239,185, 64,159,121, 97,100, 38, 28,152,123,118,255, 0,148, 35, 8, 26, 41, 14, 38,226,186, 80,163,155, 93,
+244,241,110,124, 77,173,122,208,199,220,123,174, 86,236,155,122,186, 66,146,238,147,224, 45,208, 22, 72,147,107, 92,228,231,205,
+150,102,227,234,225, 90, 9,118, 45,146, 97, 23, 95,109,197,147,162,204,240,234,134, 51,161,164,126,179,149,247,120,106,127,121,
+189, 39,137,162, 29,171,107, 25,231,116, 24, 48,121,242, 65,243,157, 36,234,223, 65,138,253, 75,106,190,131,167,217,194,128,243,
+126,219,222,119,120,246,216, 35, 76,133,108,172,156,109,138, 19,184, 72,154,228, 65,153, 54, 76,108, 95, 81, 33,202,129,165,117,
+125,163,198,252,170,102,111,117,119, 4, 88,115,180,121, 17,172,184, 24,155,182, 67,205,209, 82, 50, 27,109,205,143, 22, 50, 3,
+112, 85,145, 73,213,111,146,213,183, 77,151,100,138, 9,177,162,219,113, 99,131, 32, 5,158, 36,134, 53, 87, 10,204,234, 28, 42,
+139,217,157,152,122,201, 53, 38, 29,159,104,104, 4, 7, 3, 28,196,176,182, 42,198, 98, 66,162, 7, 33,158, 27, 17,240, 49, 80,
+ 74,242, 54,160, 39,167, 65,181,132, 42,218, 14,151, 11, 99,102,176, 54, 54,228,108,105,225, 1,224, 7, 2, 40,113,193,143, 11,
+ 74,208, 68,145, 52,239,213,156,162,133, 47, 38,149, 77,111,111,137,180,160, 23, 62, 2,136, 29, 87,153,245, 84, 2,233, 94, 2,
+223, 69, 34,166,166, 55,240,241,165, 50, 70,121,176,249,233,171, 42, 93,142,170, 0,154,120,145,225, 92, 87,133,148,123,104,109,
+ 56, 55,176,249,108,105, 4,192,139,241,191, 43, 88,208, 4, 80, 60,120,154,140,233,118, 54, 36, 15, 1, 79,234,250, 1,191,178,
+212, 61, 76, 71,215, 85, 1,186, 72,225,170,156,169,126, 36,210,123,228, 95,144, 53,193,157,121,124,245, 64,223, 22,167, 10,104,
+185, 36,250,105, 65,183, 58,128, 21,238,111,233,162, 45, 12, 83,193,181, 1,202, 56,147,235, 52,178, 88,138, 84, 28, 61,181,207,
+200,213, 33, 25,158,202, 64,230,105, 33,241, 52,199,248,141, 18, 30, 70,161,164, 54,126, 36, 94,150, 3,101,249,233, 89, 11,191,
+ 2, 5,135,141,116, 98,203,242,154,114, 4,165, 75, 70,163,197,137, 55, 62,128, 42, 58, 9, 8, 58, 31, 72, 67,113,242,241,163,
+ 74,223,195, 65,250, 55, 63, 47, 10, 96,190,151, 32,124, 67,135,201, 80,163,177,111,118, 45,227,207,219, 67,145, 64,184, 30,154,
+ 85,144, 95,135,141,184, 83, 93,184,113,241, 52, 3, 44, 52, 17,254,156, 41,240,230,188, 11,161, 64, 32,154,103, 52, 63, 45, 27,
+ 28,225,232, 2, 80,117,123,109, 90, 50, 61,247, 19, 36,125, 34,128, 23,225,123, 82,175,137,245,211,166, 76, 19, 24,104,143,239,
+ 46, 52,143,150,146,194,214,160, 28, 79,163,232,165, 0, 21, 30, 39,198,155,111, 77, 82,109,253,219,181,231,239,249,157,185, 16,
+150, 60,236, 48, 75, 25, 21, 68,114,105,211,171,164,193,152,155,106, 28,192,160, 47,121,210, 1,115,234,244, 85,124, 59,206, 44,
+219,198, 78,198,171, 32,202,197,133, 50, 36,144,129,211, 43, 33, 33, 66,157, 90,175,195,209, 86, 54,249, 77, 1,196,112, 20,150,
+177, 53, 18,125,219, 11, 31,114,196,218,101,114, 50,243, 86, 71,199,143, 73, 32,172, 67, 83,146,220,133,170,105, 4,208, 3,183,
+190, 15,162,231,232,169, 88,209, 21, 95,123,226, 60, 77, 10, 37,187,223,192, 81,167,157, 49,113,229,200,112, 74, 66,141, 35, 5,
+231,101, 26,141,175,106,212,122,145,176,225,125,116,240, 24,114,170, 14,216,238,189,179,187,112, 95, 63,109, 18, 34,199, 33,138,
+ 72,103, 85, 89, 20,216, 48, 36, 35, 56,179, 3,192,222,166,108, 91,238, 38,253,136,249,152,139, 34, 71, 28,210,227,178,204, 20,
+ 54,168, 91, 67, 17,165,152, 90,227,133,111,113, 30,188, 11, 80,214,240,162, 35,159, 1, 76, 12,180,245,101,168,186,150,157, 79,
+ 17,192,201,237,220,108, 31,196,137,123,171, 12,230,237, 45,220, 38, 57,213, 45,212,139,171, 52,145,137,226,241, 12,154,175,194,
+179, 95,136,147,108,185,255, 0,136,157,186,248, 91,142, 63,221, 7, 15,111, 72,247, 28,133, 89,224, 88,209,221,117,207, 25,176,
+107, 91,222, 86,183,174,213,238, 83,126, 27,118, 46,225,149,145,153,153,179, 67, 52,249, 82, 52,217, 14, 76,131, 92,142,197,217,
+216, 7, 2,228,155,214,123, 51,177,123, 15, 27,188,118,238,220, 94,218,195, 56,217,184,147,229, 60,197,166,234, 6,133,130,133,
+ 31,188,211, 99,122,195, 84, 98,180, 60,203,241, 49,182, 60,206,213,193,108, 76,253,191, 47,116,219,243,167,130,105,161,151, 12,
+228,205,142,120, 68,250, 48, 99,137, 52, 31,136, 45,142,145,194,247,189,109,187,127,113,236,188, 44,111,195,165,238, 24,252,174,
+232, 48, 82,109,179,119,184, 85, 12, 47, 23,150,157,191, 65,181,240,213,192, 31, 71,141,148,127,133,219, 26,103, 24,114,187,107,
+ 12, 98,117,228,117,200, 12,111,209,185,233,199,164, 75,123,218,222, 31, 85, 8,254, 28,108,239, 54, 28,139,218,184,178, 71,166,
+101,202,195, 50,241, 4, 55,238, 89, 28,203,111,132, 92,139,213,218,233, 81, 83, 53,248,106,136,211,247, 12,154, 87, 88,238, 8,
+ 66,202, 85, 90,192,188,183, 28, 72,224,107,232, 34, 9,228, 43,207,118,158,215,159,100, 18, 98,237,125,189,143,137,143,144,241,
+203, 47,151,156,162,135,140,190,151,187, 74, 94,246,106,244, 24,215, 66, 42,220,157, 32, 11,146, 73,224, 60, 73,226,106, 20, 94,
+ 62,142, 54,174,165,241,174,160, 40, 31,148,127,221,199,251, 11, 77,245,222,158,255, 0, 96,127,187,143,246, 22,153,199,149, 1,
+ 27, 32,251,227,217,249,104, 87,162,100,131,172,112,240,250,232, 52, 3,238, 46, 9,164, 12, 1,172,252, 29,209,141, 58,109,206,
+ 98, 49,166,225,149,153,134,172,236, 45, 25,194,243, 26,221,207,232,183,150, 54,246,209,227,238,109,134, 92, 87,205, 76,216,206,
+ 60, 79, 28,110,228, 48,247,166,183, 74,192,128, 72,147, 80,210, 71, 3,225, 66, 23, 5,135, 17, 77,230, 57, 85, 68,157,209,176,
+195, 28, 19, 73,157, 26,199,144,172,241, 49, 13,240,198,226, 57, 25,133,174,161, 24,217,181, 91, 79,141, 75,139,119,219,101,157,
+113, 99,201, 86,153,229,151, 29, 99, 23,185,150, 1,170, 84,229,246, 69, 10, 78, 2,223, 45,112,245,213, 36, 61,213,182,203,157,
+155,181,179, 24,179, 49, 38,120, 18, 38,254,212,199, 2,101, 49, 67,109, 35,221,115,192,155,251,166,159,133,220,219, 86,108, 27,
+107, 60,194, 12,141,207, 30, 12,152,113,159,139, 42,228, 46,184,213,216, 13, 32,183, 16,183, 62,241, 6,212, 33,114, 13, 60, 90,
+169, 83,185,182, 7,108,149, 92,232,201,196,142, 89,242, 24,234, 1, 99,129,186,114,182,162, 44,116, 55, 6,183, 42,141,133,221,
+120, 91,132,197, 49,192, 88,151, 50, 76, 19, 36,141,160,177,139, 20,102,179,164,108,186,143, 6,177, 83, 98, 44, 77, 70, 83, 68,
+109, 93,107,138,163,143,186,246, 9,113,167,204,143, 62, 54,131, 28, 68,101,112, 27,150, 71, 8,116,141, 55,126,161,224,186,111,
+115,195,157, 63, 27,185,118,252,204,204, 28, 76, 22,243, 41,157, 30, 84,137,144,135,221, 83,134,209, 71, 34, 48, 54, 55,213, 55,
+209, 80, 22,228, 81, 98,141, 45,169,184,147, 67,184,169, 32,105, 81, 96, 0,168, 4, 88,226, 7,136, 30,170, 36, 73, 29,137,210,
+ 57,211,120, 90,254,142, 84,248,192, 10, 13,253,124,104, 7,170,174,174, 64, 82, 27,234, 0, 1,167,196,210,135, 91,113,112,191,
+ 45, 53,229,128,114,113,243,208, 14, 42, 0,231,196, 10,142,165, 72, 60, 47, 99, 79, 51, 37,142,147,115,243,208,250,170, 7,194,
+110, 61, 70,128,113, 35,149, 0,241, 28, 20,223,149, 57,165, 6,215, 6,212,210,227,215,243, 85, 64,224, 88,120,114,245,210, 18,
+214,176,164,212, 44,120, 26, 66,222,129,194,168, 16, 26, 82,125,211,236,166,147,194,145,137,211, 80, 8, 41,222, 20,130,157,110,
+ 20, 3,199, 0, 41,178,155, 33, 52,251, 80,230, 23, 75, 26,164, 34, 0, 93,184,120,212,133, 80, 46, 41,144,167, 27,252,212,183,
+ 34, 66,125,117,158, 44,208,226,188,111, 67, 78, 92,105,224,146,198,255, 0, 37, 51,209, 84, 7,146,196,150,244, 34,255, 0, 45,
+ 17, 37,141, 88, 70,124, 77,175,235,244, 80,201,178,137, 8,247, 72,208,212, 34, 95, 64, 10,162,199,222,215,232,168, 81,204,170,
+ 11, 50,139, 89,244,130, 61, 66,230,134,231, 85,168,160,169,178,167, 21,141, 73, 45,233,102,231, 66,107, 90,169, 14, 32,232,229,
+206,134,201,196, 27, 84,227,112,128, 16, 8,181, 52,233, 54,247,106,144,136, 0, 18,165,185,112,254, 90,154, 15,207,233,168,132,
+222,113,225,232,169,105,198,194,128,117,197,121,156,155, 86, 70,102, 79,112,238,155, 80,255, 0,227, 91, 62,234,114,176,128, 28,
+ 93,122, 17,137, 96, 63,205,149, 69,173,226,107,211,116,142, 3,198,171,246,237,155, 23,108,203,220, 50,224,121, 26, 77,202, 97,
+145, 56,114, 10,134, 10, 18,201,165, 86,194,195,198,244, 12,197,227,119, 4, 89,187,158,243,220, 91,111,189,109,130, 60,152,144,
+216,149,146, 51, 59, 24,219,214,172,186, 77, 71,147,100,138, 30,198, 94,234, 76,188,143,191,134, 34,110, 63,121, 25,228,215,212,
+ 96, 37, 49,233,215,163, 79, 29, 26,116,218,181,120, 29,171,178,108,187,158,227,184,227,107,213,186, 2, 50, 49, 92,169,133, 67,
+ 18,204, 35, 93, 32,128,196,158, 23, 53, 5,123, 35,109, 56,235,183, 29,207, 56,236,193,181,125,210,101, 94,141,131,107,233,151,
+209,213, 49,223,236,234,161, 10, 93,207,106,195,223, 59,187,182,178, 51, 4,200,219,166, 12,179,100,172,115, 73, 29,157, 33, 66,
+ 2,105, 97,163,215,110,126, 53,232,123,142, 86, 62,223,129,147,155,150,229, 49,224,137,229,149,151,152, 85, 4,157, 54,241,244,
+ 85, 86,241,219,155,118,243, 62, 14, 83,100,100, 97,100, 96,107, 24,243,225, 73,209,112,146, 0,175, 29,244,183,186, 64,171,140,
+172, 60,125,199, 22,124, 44,165,234, 99,100,198,209, 74,135,133,209,193, 86, 23, 30,163, 68, 83,203, 89,114, 49, 51, 59, 99,122,
+219,182,185,246,172,108,205,207, 23, 24,102,100,103, 73, 54, 70, 76, 57, 55,225, 52, 4,186,168,100, 23,226,215, 21,234,155,183,
+255, 0,198,102,255, 0,113, 47,236, 26,206,193,248,123,133, 24,219,198, 70,237,185,100,195,181,100, 69,149,129, 4,179, 33,141,
+ 12, 6,232,133,122, 94,240,240,244,219,128, 35,141,106,230,199, 76,156,121, 96,144,144,179, 35, 70,197,121,128,195, 73,181,239,
+233,173,197, 25, 60,187,102, 31,229,140, 30,220,238,232, 56,109,153,216,152,216, 59,248, 91,105, 94, 1, 32,203,111,232, 49,208,
+199,209, 77,121,230,135,179,166,124,121, 90, 50,221,196,234, 90, 54, 43,117,108,195,113,117,240, 53,232,152,221,185,182,227,118,
+250,246,211, 43, 79,183,172, 7, 24,137,136, 46,200, 65, 28, 74,133, 23,227,204, 10,173,198,236, 93,150, 14,217,151,181, 58,153,
+ 18, 96,200,230, 94,179,186,245,213,203,137, 3,171,162, 40, 5, 88,112,247,106,209,252, 0, 14,232,158,120,251,171,179,227, 73,
+ 25, 18, 92,140,161, 34, 41, 32, 48, 16, 92,106, 3,157, 85,109,157,191,139,220,187,223,117,197,187,100,101,203, 20, 25,130, 44,
+104, 87, 38,100,142, 61, 81, 6,214,168,142,160,144, 79, 0,110, 7,162,175,177,123, 31, 25, 55, 29,191,117,205,221,119, 13,195,
+ 51,109,103,108,118,201,153, 25, 44,235,160,169, 65, 24, 28,188, 71, 19,226,106,235,107,216,113, 54,188,205,203, 55, 29,228,121,
+ 55, 73,134, 70, 66,200, 84,170,184, 80,150,143, 74,169, 2,195,196,154,187,107,173, 1,229,152,123, 82,231,254, 22,127,155,242,
+179,243,159,125,198,138, 73,113, 50,252,212,195,165,229,167,120, 81, 35, 69,112,128,104, 78, 38,215,191, 27,214,171,119,192,198,
+238, 62,244,237,120, 55, 54,149,162,159,104,154, 89,196, 50,201, 1,115,251,182, 33,154, 6, 70,210, 73,228, 13,104,112,251, 43,
+108,199,237, 38,236,212,150,115,183, 52,114, 68,102, 44,157,125, 50,200,211, 55,189,211,209,125, 77,195,220,163,110, 93,149,135,
+185,101,109,249,209,110, 57,219,126, 86,219,140,112,224,155, 14, 72,145,140,109,107,235,234, 67, 39, 19,167,194,213,134,137,161,
+146,199,150,126,210,222,123,175,102,218,166,155, 43,108,219,182,191,189,113,113,167,145,166, 56,211, 5,118,232, 35, 72, 89,180,
+189,181, 88,154,160,194,218,123,191, 51,100,192,223,118, 77,159, 57,251,138, 85,135, 49, 55,201, 55, 24, 52, 77,172,137, 29, 30,
+ 6,200, 3,164,200, 74,132,210, 45,227,227, 94,181,178,246,174,211,177,195,148,152,200,243,203,158,117,103,229,229,185,158,124,
+131,109, 63,190,145,249,128, 15, 1,202,169,241,255, 0, 14, 49,112,191,195, 96,239, 91,166, 46,209,171, 88,218, 34,200, 81, 0,
+187,106, 49,171, 20, 50, 8,207,138,234,249,106, 87, 74, 13, 74, 89,118,175,243, 15,226, 78,108, 27,150, 70, 76,120,184, 88, 88,
+ 57, 99, 2, 41,136,137,166, 14, 72, 18, 1,193,148, 88,220, 14,117,233, 26,219,194,171, 34,216,113, 49,247,236,190,225, 71,144,
+229,230, 65, 22, 52,177,177, 94,144, 72, 73, 42, 84,105,213,126, 60,125,234,177,183,164,213, 66,146,228, 63, 83,125, 23,250,107,
+169, 44, 45,207,195,242,215, 85, 46,191, 2,153,237,238, 31,247,113,254,194,211,105,207,253,152,255, 0,119, 31,236, 45, 37,197,
+100,209, 19, 39,227, 28, 60, 63, 41,160,139, 95,194,143,146,125,241,236,250,232, 4, 92,208, 24,156, 94,199,108, 89, 54,252,200,
+ 98,194,143,114,199,203,220,114, 50,243, 21, 7, 82, 72,242,215, 45, 96, 82,230, 61, 79,167,175, 30,165,110, 28, 56, 95,133, 86,
+127,150,251,135,111,195,234,203, 18,100,229, 79,151,179, 49, 68,154,105,206,188, 76,133,234,200,229,162,247, 34,251, 94,232,178,
+ 47,135, 10,244,155, 91,149, 39, 11,208, 30,109,147,219, 91,241,149,176,163,130, 35, 54,231,183,239, 9,149, 43, 52,158, 95, 29,
+183, 44,200,165,208,178, 8,206,166, 69,123,133, 32,106,210,106,219,102,218, 93, 59,215,115,204, 64,255, 0,119,226,198, 4, 44,
+232,200, 14, 94, 66, 67, 22, 67, 33, 96, 3, 89, 49, 18,228,112,247,205,108,237,232,174,177,231, 64, 99,223,182, 55,105,119,121,
+164,102,129,112, 31,113,147,117,142, 85,119, 51, 93,176, 62,239, 88, 89, 12, 97, 71,188,117, 18, 24,240,168,152,125,145,184, 99,
+228,237, 93,110,148,241,227, 65,181,166, 67,249,156,152,210, 57,118,209,239, 20,199,143, 68,115,235, 33, 74, 52,159, 15, 30, 30,
+ 21,187,185,174,191, 27,208, 24,121, 59, 31,115,147, 22, 72, 26,108,117,102,196,221, 32, 83,119, 35,169,155,158,153,240, 92,104,
+ 30,232, 84,179,250, 15, 43,209,224,237,157,226, 92,209,184,101,249,104, 94, 77,203, 35, 61,225,142, 87,147, 76,115,109,191,119,
+162,106, 49, 37,216, 73,196,240,181,190,106,217, 94,230,184,113,244, 80, 30,125, 47,108,238, 91, 54,219, 30, 99,152,166,147, 3,
+ 27, 99,141, 99,136, 77, 32,105,118,198,144, 77,168, 71, 19, 72, 35, 61, 91,134, 84, 98, 57,149,225, 86,125,165,181,230, 4,199,
+221, 51, 49,146, 57, 12,219,172,151,109,113,186,174,110, 90,204,133, 33,145, 53, 89,214, 59,251,197, 72, 22,225,199,134,187,136,
+ 21,215,225, 89, 7, 31,134,244, 93, 62,150,111,101,205, 12, 88,128, 61,148, 82, 56,240,168, 4,233,169,231,199,212, 77, 60, 70,
+135,134,158,116,128, 30,118,183,174,156, 79,141, 0,141,161, 69,173, 93, 97,164,120, 14, 84,211,102, 2,230,252,105,204,234,188,
+136,191,163,133, 0,240, 7,143, 10,226,109, 76, 50,165,129,213,115,232,166,117, 1,230, 15,204,106,129,197,184, 91,194,244,219,
+175, 14, 52,215, 58,135,194, 64,244,154, 75, 15, 69, 0,183, 95, 77, 37,213,141,188,105, 57, 48,167,112,184, 62, 53, 65,196, 10,
+100,156, 19,218,105,196,241,166, 73,200, 15, 93, 64, 32,231, 78, 62,143,244,231, 77, 28,233,224,251,192,123, 40, 64,148, 25,249,
+ 90,138, 77,170, 60,134,228, 85, 3,147,128,161,107, 26,236,124,104,132,217,109, 67, 69, 7,137, 23,168,145,166, 58,227,222, 34,
+153,224, 47, 76, 12, 22,234, 5,133, 61,151,221,181, 24, 68,200,216, 5,100,110, 32,218,244,178, 68,134, 61, 34,250,124, 42, 58,
+201, 97,107,127,160, 21,221,115,200, 19, 82,133, 28,218, 85,116, 39, 1, 65, 38,231,217, 78, 44, 10,243,164,107, 1,113,232, 53,
+ 72, 62, 57, 68,192,240,181,185,215, 97,197,213, 47,168,155,120,113,246,211, 49,134,148,107,248,253, 85, 47, 13, 81, 3,104, 7,
+136, 23,191,166,169, 6,182, 13,157, 93, 90,246,244,251, 40,134, 7, 30, 23,163,179, 89,120,120, 83, 18, 75,141, 68, 90,254, 20,
+ 21, 4, 85,151,157, 34,250,184,210,188,225,180,133, 60, 24,216,210,173,135, 42, 2,187, 47,248,198,128, 57,209,242, 69,231,107,
+114,164, 84, 55,189, 0,171, 19,151, 9,196, 30, 28,189, 21,109, 10, 5, 0, 15, 10, 2,168, 50,151,246, 15,154,165,198, 42,160,
+ 60,143, 10, 90, 80, 46,109, 79, 43, 91, 70, 27, 25,196,210,133,165,181,188,105,233,122,210, 21,168,208, 8,229, 69, 82,124,105,
+192, 19,225, 68, 84, 30, 52,149,121, 10,208,114, 15, 27,209, 65,181, 32, 81,106,112, 28,107, 1,161,193,169, 25,155,236,211,173,
+ 93,102,169,161,164, 12,177,241, 20,195,110,116,109, 55,231, 77, 40, 42,166,138, 51,134,159,234,255, 0,245,171,169,250, 69,190,
+ 79,203, 93, 86,191,136, 41, 36,191,238,255, 0,187,143,246, 22,155,232,167,184,224,159,221,199,251, 11, 77, 60,171, 0,139,147,
+252, 81,236,252,180, 43, 91,213, 69,201,182,177,236,161,124,159, 45, 0,132, 19, 74,214, 28,171,169,166,244, 7, 95,141, 47, 26,
+ 65, 79, 2,226,252,232, 65,188,184, 82,123,105,228,113,189,171,188,121, 10, 1, 45,235,164,226, 41,108, 7,141,119, 51,207,133,
+ 0,163,136,227, 75, 97, 72, 60,125, 84,170,111,122,203, 41,201, 30,179,166,246,176,189, 19,162,111,197,207,209, 75, 15,218,249,
+ 56,218,138,110,220,252, 42, 0, 5, 20,178,168, 36,250, 69,232,157, 24,137,181,137,245, 19, 73,166,210,114, 3,215, 68, 39,196,
+ 90,224,208, 10,176, 71,110, 10, 5, 49,149, 65,176, 2,137,175,198,247,166, 22, 81,196,219,141, 0,219, 2,203,111,109, 16,141,
+ 92, 45, 65, 18, 38,191,136, 90,158,211, 71,194,168, 27, 58,240, 85,185,249, 40, 58, 86,246,185,162, 59, 25, 56,142, 94,177, 77,
+208,121,234,227, 64, 38,133,224,109, 77,176, 4, 90,159,111,231, 30, 20,210, 0, 34,212, 2, 53, 49,252, 40,156,205, 13,254, 47,
+146,128, 65,241, 83,255, 0,180,166, 47, 58, 86, 54,123,250,141, 8, 17,207, 10,142,109,168,122,234, 66,157, 74, 13, 6, 65,103,
+246, 85, 7, 31, 26, 69, 60, 45, 93,122, 19,135, 82,116,242, 53, 13, 14,176,107,240, 30,163, 79,107,145,242, 10, 4,114, 53,194,
+250, 77, 74,140,160, 36,185,176,224, 56,209,132, 10,252, 62, 67, 77, 60, 15, 31, 65, 21, 46,208,186,182,159, 3,252,180,198,199,
+ 7,213,122,133, 35,139, 95,143, 42,123, 91, 79, 15, 69,169,239, 1, 3,129,255, 0, 79,244, 52,198, 22, 79, 95, 42, 1,227,132,
+100,255, 0,167, 42, 38,222,204, 99, 98,120,251,223,146,152,120, 66,215,231, 99,252,148,252, 14, 17, 55,173,171, 72,203, 37, 31,
+ 10, 67, 93,242,215, 80,132,105, 84, 43,198, 7, 43,220,209, 5,201,245, 83, 39,254, 52,107,237,162,128,109,195,157, 10, 64,154,
+221,102,244, 95,242, 83,227, 93, 70,222,194,105,146, 92,202,222,218,145, 18,219,143,141, 1, 34, 49, 82,208, 88, 84,104,133, 75,
+ 81,200, 86,146, 32,225,192, 95,198,146,231,211, 74, 72,174,181,249, 86,226,140,241, 59,135,137,167,163,133,229, 67, 43, 92, 5,
+ 86, 97,166,157, 73, 33,201,241,162, 41,245,212,117,176,167, 6,227, 87,145,164,215, 50, 72, 99, 68, 6,130,188, 71, 58,118,150,
+ 28,107, 45, 34,238,168,117, 97, 78,214, 60, 42, 54,163, 78, 12,107, 46, 37, 65,175,126,116,158,232,166,131, 72,199,209, 74, 26,
+105, 14,225,111,147,242,215, 83,110,116,255, 0, 87,242,215, 82,159,137, 40,138,103, 60, 19,251,184,255, 0, 97,105,183,167, 56,
+248, 63,187,142,199,250,139, 77, 3,159,162,178, 82, 54, 65,247,199, 31, 10, 9,226, 42, 91,195,212, 55,213,111, 11,115,252,180,
+209,139,252,251,252,148, 4, 91, 26, 91,112,181,234, 79,149, 22,248,190, 91, 87, 12, 95,231,125, 31,158,128,140, 7,174,184, 84,
+159, 44, 65,248,254,143,207, 93,229,135,233,253, 20, 4,114,192,143, 73,164, 23,231,106,144, 49,120,252,127, 71,231,165, 24,227,
+145,111,162,128, 7,200, 41, 56,219,157, 31,203,255, 0, 59,232,252,245,222, 88,223,226,250, 63, 61, 0, 1,199,141, 58,194,215,
+163,121,123,125,191,162,151,203,255, 0, 59,232,168,192, 36, 14, 1, 11,107,115,227, 79,247,201, 23, 97,127, 27, 10, 52,120,228,
+ 41, 26,185,155,242,252,244,239, 47,252,238, 62,202,200, 1,211,227,169,156,223,228,229, 74, 34,181,253,227,199,215, 71,233,105,
+ 31, 21,253,162,148, 68, 71, 54,191,163,133, 80, 70, 49,174,174, 60,173,200,154, 82,136, 0,176, 31, 53, 24, 68, 6,171,183, 63,
+ 87,231,165,232, 3,195, 87,175,149, 0, 13, 34,246,176,174, 96,188,141,168,205, 18,248,184,191,179,243,211, 58,105,195,222,213,
+232,225,198,128,142, 94,204,120, 94,155,172,183, 0, 62,122, 57,128, 18, 78,191,162,154, 32, 0,124, 95, 71,231,160, 2, 3,113,
+ 23, 28,105,188,117,122,106, 80,199, 39,147,125, 31,158,147,203,113, 62,247,209, 64, 71,185, 6,152,196,147,198,165,249,107,253,
+175,163,243,211, 27, 26,228,251,223, 71,231,160, 35,175, 58,100,196,134, 22, 28, 45,252,181, 48, 99, 91,237,125, 31,158,148, 64,
+ 3, 88,183, 49,232,160, 32,199, 46,144, 69,115, 62,174, 62,154,158,216,113, 30, 36,253, 21, 25,176,198,187, 43,240,246,126,122,
+ 0, 32, 18, 62, 90,115,241, 70,183,128, 53, 39,202, 88, 15,127,199,209,249,233, 36,197,247, 27,223,181,199,163,243,208,165,108,
+ 92, 92, 94,142,227,221, 39,215, 70,143, 11, 76,131,223,240,191, 47, 87,182,138,216,122,148,217,172, 47,232,252,244, 97, 17,177,
+154,204, 65,228, 71,242, 84,162, 77,169, 97,194,210, 46, 95,143,179,243,209,124,183, 31,142,255, 0, 39,231,168,202, 69,144,159,
+ 10, 12,156, 22,222,207,229,169,239,143,252,235, 95,135, 47,207, 81,228,196,189,134,191, 31, 71,231,160, 4,125,228,208, 57,159,
+ 26, 44, 3,163, 3, 22,227, 99,200, 83,198, 45,190,223,209,249,233, 30, 11,130,161,249,250,191, 61,104,200,209,155, 1,225, 98,
+ 15,174,156,114,177,202,144, 73, 23,241,168,190, 76,220,217,254,143,207, 93,228,219,244,254,143,207, 64, 42, 56,121,144, 95, 85,
+129,185,169,170,126,186, 6, 46, 17, 15,175, 87, 47, 87,231,169,158, 95,141,245,125, 20, 41, 92, 83,247,205,127, 3,252,180,117,
+ 28,168,205,143,169,139, 22,231,234,252,244,248,241,184,252, 95, 69, 8, 58, 53,225, 71, 28, 22,149, 32, 0,113,110, 3,157, 33,
+100,189,184,144, 61, 67,235,173, 38,151, 18, 81,242, 58,220, 43,129,181, 40, 43,235,249,135,215, 93,101, 62,159,152,125,117,119,
+174,166, 62,190,131,131, 10,112,227,202,154, 20,122,254, 97,245,209, 1, 81,224,126, 97,245,213,223, 30,168,180,151, 65, 44,212,
+161,120,242,165, 12, 7,129,249,135,215, 78, 18,143,209, 63, 48,250,234,239,143, 80,226,250, 4, 75, 10, 56,126, 22,168,162, 69,
+253, 22,249,135,215, 79, 19,160,251, 45,243, 15,174,163,148,122,149, 71,192, 63, 19,225, 74, 20,208,124,210,126,139,124,195,235,
+174,243,107,250, 45,243, 15,174,179,185,117, 17, 82, 92, 80,123, 94,147, 77, 8,101,160,251, 45,243, 15,174,184,229,199,250, 13,
+243, 15,174,166,229,212,178, 77,240, 13,167,249, 63, 45,117, 11,204, 46,157, 86,111,135, 87,135,233,105,244,215, 85,220,186,146,
+143,224, 85,184, 30,229,249,152,227,253,133,166,113, 7,133, 20,196,236, 35, 96, 86,221, 56,249,186,131,240, 47,129, 34,147,162,
+255, 0,204,253,116,255, 0, 90,161,160,124,248,215, 92,113,254, 74, 39, 69,239,205, 63, 93, 62,186, 94,131,223,226, 78, 92,125,
+245,255, 0, 90,128,243, 13,133,114,242,247,190,219,105,178,153,225, 71,238, 25, 4, 46, 53,123,240,238, 29, 37,109, 68,243,209,
+ 38,149,253, 16, 56,115,163,110,253,223,191,224,103,111, 27,116, 38, 51, 54,214,185,153,108,206,151, 81,138, 98,198, 56,108,222,
+199,201,107,250,122,102,182,248,176,236,125,104, 60,145,193,234,255, 0,138,242,157, 23,199,215,252, 81,231,122, 90, 26,255, 0,
+197,183, 86,223,107,226,227, 81, 32,218,182,156,125,227,120,206,201,205,131, 35, 59, 42, 8,134, 94, 60,242,227,218, 28, 52, 18,
+104, 86,140, 88,136,201,103,187, 63, 63,146,128,206,175,113,239,120,155,152,218, 50, 39, 76,161, 14,225, 54, 35,230, 24,149, 58,
+177,174,212,119, 37, 22, 79,116, 50, 73, 96,109,225, 83,100,223, 55, 73,123, 71,183,247, 24,229, 72,115,183,143,187, 35,155, 32,
+ 32, 43, 25,204,233,245, 93, 17,189,219,251,196, 40, 62, 38,167,182, 55,100,141,170, 5,115,180,253,208, 39, 39, 24,180,184,167,
+ 31,204, 89,137,208, 89,244,117, 45,170,254, 54,189, 78,200,131, 99,109,141, 87, 35,200,253,194, 98,140, 33,121,113,198, 39, 68,
+233,232,233, 58,186, 97,126, 29, 22,245, 90,160, 60,243, 23,127,223,176,182, 54, 56,185,170,173,133,141,189,238,146, 75, 44, 98,
+ 79, 50,248,155,132,145,164, 3, 91,123,169, 99,111,116,220, 93,109,235,187,196,238, 45,234,126,230,139, 26, 73, 85,112,100,220,
+230,219,142, 39, 72,106, 8,155, 98,238, 33,140,159, 22,161, 39, 15,101, 93, 60, 29,156,216,123,125,198,208, 48, 68,174,118,207,
+222,226,136,122,221, 67,212,242,246, 96,186,186,159, 22,159,181,207,141, 78, 16,236,231, 52,104,242, 3, 59,204,189,180,190, 63,
+ 91,205,244, 6,191,181,171,171,229,249,253,173, 31,205,160, 51,155, 6, 38,225,182,247, 81,218,103,220, 95, 46, 12, 45,143,111,
+ 77, 46,182, 14,235, 38, 68, 13, 53,139, 53,153,140, 90,137,185, 60,109,126, 2,169, 31,189,187,133, 50,223, 3, 84, 70, 69,118,
+218,131,104, 23,251,198, 76,233, 32,128,219,135, 15, 44,138,246,254,117,249, 10,244, 23,131,110, 59,180,125, 67,135,247,207, 65,
+186, 87,120, 6, 87,151,213,239,105,247,186,157, 61,124,252, 47, 81, 14, 63,110,249,131,168,237,190, 99,206,174,171,201,141,175,
+207,244,206,139,251,215,243, 29, 59,219,237,105,245, 80, 24,201,123,207,124,134, 29,242,116,149,102, 76,125,191, 47, 59, 10, 86,
+133, 18, 33, 38, 54, 67, 99,129, 18,135, 50, 52,126, 7,170, 1, 44, 13,184, 81,231,220,119,188,141,199, 7, 22,109,203,254, 79,
+185, 14, 11, 72,145,170,117, 97, 59,113,203, 10,234,166,196, 2,236,182,246, 30, 98,175,211, 27,178, 21,178,244, 54,205,168,172,
+231, 59,247,184,100,232,212, 60,207, 91,222,248,117, 91,169,126, 23,231, 83,114,113,251,118,207,231, 14,219,111, 56,157, 78,172,
+152,223,243,250, 19,167,171, 83,127, 31, 70,157, 63,106,214,160, 51, 59,222,231,189,225,119,124,240,224,102,152,226,201,198,218,
+177,209, 25, 3,164, 30,107, 54,120, 26, 80,164,216,191,187, 96, 79, 50,192, 30, 64, 85,198, 46,241,189,205,218, 57,249,171, 38,
+ 56,220,241, 38,204,195,131, 42,114,176,195, 43,227,228,201,139, 28,158,241, 8, 53,232, 30, 58,117,122,170,102,233,141,219,103,
+ 33,134,242,118,223, 52,113,200,111, 53, 46, 48,151,203,107, 23,254, 35,106,233,235,183,171, 87,174,166, 44,123, 74,236,133, 88,
+ 96,182,195,209, 34,230, 72, 60,167, 67,219,171,167,163,232,168, 12, 6, 71,122,119, 66,196,113,241, 3,207,145,135, 30, 92,249,
+ 11, 52,120,176, 56, 56,242, 69, 26,195,154,211, 79, 20, 74,171,212, 58,154, 2,220,212,143, 26,188,194,238, 13,251, 39,187,223,
+111,233,145,181,140,217,240, 11, 63,151, 84, 2, 28, 65,146, 25, 47, 47,152,121, 75,243, 29, 61, 58, 15,170,245,107,229,251, 12,
+ 98,237,253, 67,179,249,116,149,254,238,213, 46, 39, 79,173,169, 68,157, 31,122,204,250,244,234,183, 29, 86,191, 26,177,142, 30,
+220, 27,251,188,103,111,255, 0, 48,104,180,128, 60, 7, 51, 64, 85,248,133,250,150,209,167,228,183,133,168, 12, 31,119, 62,230,
+189,218,208, 65,184,201, 20, 44, 54, 30,156, 32,123,168,210,238,114, 68,205, 96,194,255, 0, 7,189,250, 64,216,240, 20,184,251,
+246,241, 42,197, 56,147, 21,247, 53,219,119,132,139, 47, 39, 76, 74,210,226,238,112,224,195,168,146,177,174,177,110, 28,139, 91,
+194,183, 91,140, 93,179,247,158, 63,222,167,110,251,218,209,249, 79, 50,216,254,102,221,101,233,116,186,135, 93,186,250,116,219,
+237,218,220,104,114, 69,218, 93, 7, 18, 29,175,160, 97,202,234,106,124,109, 29, 14,176,243,186,174,109,163,175,110,175,134,191,
+139,141, 1,158, 29,195,185, 67,216,251,222,241,212, 45,184,237,131, 36, 32,200,133, 99,150, 55,133,117, 44,121, 9, 25, 49, 22,
+ 23,226, 99, 58, 72,181, 1, 55,158,225,155, 54, 77,147,207,164, 82,253,237,145,133,247,145,129, 46, 33,135, 1, 55, 5, 65, 25,
+247, 46, 93,200,185,251, 35,211,198,181, 56,208,118,210,236, 82,174, 57,219,190,224, 11, 32,200,210,248,231, 19, 77,207, 87,170,
+117, 24,249,223, 86,175,150,153,184,193,218,173,139,150, 55, 67,182,249,111, 50, 60,239, 94, 76,112,158,107,166,182,235, 23,107,
+117,122, 90,126, 47,123, 77,188, 40, 15, 60, 27,230,237,157,185,237,155,158, 84,131, 70,126, 39,110,206,248, 12,135,164,143,149,
+158,241,188,145,139,240, 60, 11, 3,235, 30,129, 83,229,238,174,224, 76, 72,179, 35,203,138,105, 55, 60,135,131, 31,110,137, 34,
+243, 56,234,185,254, 72, 24,122,205, 28,111,238,123,164,202,214,234, 17,225,194,182, 89, 80,246,183,157,196,243,167,108,243,250,
+ 34,242, 29,103,198,235,116,250,171,209,232,107,109, 90,122,218,116,105,251, 86,183, 26,140,248,189,144, 91,116,234, 54,211,173,
+200,251,226,242,226,222,253, 75, 15, 51,239,123,167,171,250, 95,111,215, 84, 17, 32,223,183, 21,236,153,247,156,231,139, 19, 62,
+ 20,200, 13, 35, 42,206,170, 97,153,224, 71,100,197,119, 66,228, 40, 37, 85,236, 27,133, 80,174,237,190,110, 50,108,194,124,169,
+ 49,164,199,238, 25, 48, 38, 12,145, 44,146, 70,184,147, 76,171, 56,129,218, 43,142, 42, 66,155,114, 60,197,110, 60,190,194,118,
+ 50, 53, 96,253,195,209, 32,218, 72, 60,159, 66,220,120,234,233,232,183,201, 80, 98,199,236,197,197, 81, 17,218, 60,160,201,136,
+ 45,164,196, 49,249,189, 35,163,199, 85,186,218,109,167,237, 91,149, 1, 87,187,239, 27,206, 63,114,197,131, 14, 82, 65,183,202,
+208, 99, 35,164,113,206,171, 52,194, 66, 83, 40,106,235, 71, 35,123,166, 46, 26, 15,218,172,191,109,119, 54,247, 14, 47,110,227,
+156,198,204,142, 68,219,162,203, 13, 26,157, 35, 55,168, 63,127, 52,143,212,105, 61,223,115, 64, 63, 9,215,206,189, 22,108,126,
+218,251,238, 22,201,109,187,239,208, 0,131,169, 38, 63,155,177, 13,167, 64,102,234,114,213,107,120, 95,215, 85,152,216,223,135,
+221,120,219, 25,182, 62,189,212, 69,211,147, 11, 86,174,177,209,164, 43,115,235, 94,214,251, 87,241,160, 51, 89, 59,159,112,101,
+227,236,187,172,155,151, 77,101,222,242,241,147, 30, 40,130,168,143, 21,119, 8,213, 93,181, 93,245, 8, 56,131,195,145,230, 41,
+240,119,126,247,147,137,142,194,104,162,150,124,126,220,115, 47, 76, 16,143,187, 74,241,100,182,146,109,200, 2,163,194,182,147,
+193,219, 94, 70, 31, 48,118,223, 33,230,143,150,234, 62, 55, 71,206,117, 94,253, 61, 77,167,173,213,215,203,222,213,127, 26,165,
+125,179,176,242,176, 94, 60, 92,141,170, 12, 24,231,195,159, 37,177, 39,195, 84, 99, 20,198, 92,104,231, 32,149, 40,238, 25, 66,
+158,124, 66,208, 22, 93,183,186, 79,185,109,204, 51,101, 89, 50,161,201,204,197,234, 40, 11,214, 76, 76,153, 49,132,193, 7,164,
+ 40,189,184, 94,177,115,119,142,255, 0,139,131,153,157,215,142,102,124, 77,230,120, 35,233, 0, 32,125,179, 45,113,162, 45, 99,
+118, 14,175,239, 95,198,214,173,214, 6, 14,193,215,193,155,105,147, 14,241,226,205, 22, 12,120,179, 65,164,227, 52,177, 25,154,
+ 49, 27,123,202, 36, 68,185, 28, 1,245,154,172,218,246,190,202,193,135,112,134, 60,141,183, 36,145,144,251,156,179, 79,137, 35,
+244,164,158, 73,166, 92,146, 8,253,218, 72,229,125,225,194,192, 30, 85, 24, 69,102, 78,251,220,152,125,193, 14,212, 27,205, 65,
+141, 38, 4,121,115,149,199,134, 38, 25,210,200,174,205,212,153,101, 5, 80, 90, 37,141, 90,229, 78,171,222,160,191,114,119, 51,
+ 62, 86, 40,201,137,178,101,117,124, 88,163, 24,228, 75, 1,201, 49,234,219, 38, 50,116,165,110,144,182,137,142,173,119,240,173,
+190, 94, 63,111,157,235, 17,179,206,223,247,192, 91, 97,117,164,199,243, 58, 73,107,116,131,182,190,122,173,111, 95,174,171,164,
+196,236, 51, 30, 96,213,179,104,121, 80,238, 31,189,196, 22,125,109,167,170,117,240,110,165,237,127,181,127, 27,209, 20,169,205,
+220, 36,220,251, 95,103,155, 35, 35,169, 30,126,110, 30, 62,108,168,173,143,170, 38,202, 17, 60,110,183,186,106,210, 17,192, 54,
+226, 64,225, 81,183, 29,167, 99, 87,192,198,192,121,101, 72,247,165,195,200,141,158, 85, 88,131,196,243,190, 36,118,208, 12, 96,
+176, 97,107,216,240,191, 11, 13,123,227,236, 71,102,180,231, 3,238, 19, 10,129,121, 49,198, 31, 71,236,219,222,233,232,189,173,
+225, 75,129,141,219, 73,131,136,155,123,109,199, 4, 79,108, 35, 12,152,230, 47, 51,239,127, 4,171, 91,171,241,114,247,185,208,
+ 30,111,186,121,156,125,199,116,200,141, 30, 56, 32,222, 6, 34,238, 41,144,250,227, 67,183,195,167, 23,203,240, 83, 27,179, 88,
+182,174, 26,175,106,215,203,191, 79,177,246, 22, 54,233, 12, 18,101,100,197,181, 9,208,232, 50, 32,146, 60, 97, 32,105,236,202,
+193, 53, 14, 38,245,117,147, 7,111, 24,167,243, 71,111,233,121,149,243, 93, 71,199,211,231, 52, 38,142,174,166,183, 91, 70,139,
+ 95,222,181,189, 85, 3,108,199,236,111, 41,184,253,198,219, 41,193,233,255, 0,241, 99,135, 38, 31, 75,165,165,255, 0,230,186,
+ 77,167, 70,157,127, 31, 11, 95,215, 64, 85,238,155,148,153, 59,226,203,162,124, 72,142,199,185,183, 70,112, 99, 58,227,151, 18,
+207,166,228, 92, 6, 54, 53, 11,116,202,220,113,182, 62,202,201,199,200,116,110,164, 29,120,128,185,152,141,190,121,116, 57,230,
+110, 82,214,244,155,243, 2,181, 91,254, 47,110, 52,112, 14,230,109,187,166, 25,142, 55,222, 18,227,129,112, 61,253, 29,118,244,
+124, 86,240,231, 71,220,241,246,159, 47,143,247,169,194,242,253,104,252,175,154,146, 13, 29,127,236,122, 93, 86,182,191,209,183,
+ 31, 69, 1,159,237, 45,239,117,205,157,177,247, 60,132,204, 18,237,216, 59,154, 77, 28, 98, 49, 27,102,117,131,193,238,146, 10,
+142,144, 42, 79, 27,122,106,139, 35,188,247,168,240, 50,114, 81,162,234,197,183,239, 89,107,116,225,212,192,207, 92, 72, 56, 95,
+151, 76,241,244,154,219,108,248,155, 24, 92,143,184, 91, 3, 73,146,249, 62, 74, 92,114, 58,132,127,105,210,110,118,244,213, 70,
+110,213,217,153,176,238,248, 99, 39,108,198,159, 34, 28,132,220,242, 49,178, 48,211, 34, 56,217,148,100,180,143,168,149,179,233,
+215,168, 91, 85,175,198,169, 10,201,247,157,237,115,178, 59,127,206,198, 26, 60,217,160,109,200, 68,190,252, 73,182,141,196, 70,
+ 18,250, 65,214,246, 36, 27,233, 30,158, 53, 23,105,238, 61,214, 8, 59, 95, 22, 41,186,208, 62, 46,205, 22,100,102, 53, 32,121,
+216,136,102,158,105, 28, 72,210, 54,157, 73,211, 4,112, 58,185,214,177,113,187, 47,238,162, 38, 59, 71,221,126,100,183, 25,113,
+124,191,154,177, 99,199, 86,142,165,175,195,157,184,114,162, 54, 63,100,121,140, 86, 99,179,249,142,142, 48,193,188,152,154,186,
+ 26,135,148,232,141, 95, 6,171,116,180,240,253, 26, 3, 7, 15,114,119, 70,216,185,184,216,114,182,115,193,145,187,229, 51, 63,
+151, 69,182, 54,119,151, 88,229,124,169,162,209, 15, 19,125, 23, 97,117, 3,128,227,177,239,126,224,206,237,172, 92,109,198, 13,
+ 39, 21,188,204, 51, 33, 93, 76,103, 56,210, 75,137,111,108,177, 4,254,176,169, 89, 24,253,136,114,127,197,157,155,205, 46, 83,
+ 22,234, 73,136, 36,243,126,224,125, 87,107,153,126, 11,223,143,195,234,169, 61,201,181, 96,231,193,135,247,182,108,120,184, 88,
+249, 80,204,200,242,192,145,205, 42, 56,104, 35,119,148,248,200, 7, 5, 35, 87, 42, 3, 43, 15,112,119, 28, 57,209,249,169,227,
+145, 70,115,237, 50,225, 44, 64, 16,209,109,199, 52,229,107, 30,247, 25, 22,246,248,116,145,237,161, 99,247,134,255, 0,147,133,
+143,210,150, 24,242, 50, 49,251,109,132,134, 32,193,100,221,229,120,178, 91, 78,161,113, 96, 52,139,240,173,154,227,236, 31,125,
+179,106,192,251,243,167,103,253,228, 30,107,167, 97,204,106,234,105,211,111,146,163,237,144,246, 42,196,195,105, 59, 57,143,169,
+140, 91,203, 62, 33, 29, 83, 35,121, 59,232,111,139,171,126,151,243,190, 26, 1, 55,237,215, 63,105,159, 98,194,142, 85,144,230,
+ 60,241,102, 74,232, 1,126,142, 20,249, 1,128, 28, 22,242, 68, 9,183,178,178,112,247,126,253,167,103,220, 39,154, 51,139,149,
+133,131, 44,169, 10, 36,136,114,114, 49,218,121, 97,200, 10,221,104, 93,253,222,137, 11,163,211, 91,173,238, 13,137,224,139,252,
+200,216, 35, 31,170,166, 31, 62,240,132,235, 5,109, 58, 58,205,109, 90,117,124,151,168,112,227,246,111,222, 24, 45,142,219, 87,
+222, 2, 24,198,219,211,147, 23,171,208, 40,122, 62, 92, 43,106,209,211,190,141, 63,102,246,225, 89,110,175,129, 81,145,192,238,
+190,234,159,108, 15, 49, 72, 39,201,155,102, 24,211,204,184,236, 66,238,147,116,165,180, 56,179,201,251,181, 22, 49,153, 8, 99,
+126, 60,171, 81,220,185,155,158, 26,237, 27,102, 54, 98,195, 38,111, 93,114,179, 90, 53, 37,134, 62, 36,147,144,169,193, 87,168,
+201,115,110, 66,246,244,212,157,186, 14,204, 92,102, 27, 89,218,188,177,201,132,183,151,124, 99, 31,155, 46,167, 31,224,107,117,
+117,233,233,248,222,218,106,126,251, 14,198,216,104, 59,140,225,121, 62,170,152,252,251,194, 35,234,128,197,116,245,142,157, 90,
+117,124,151,240,167,176, 30,123,178,119,102,253, 20,125,187,135,143, 25,151, 18, 44, 29,141, 50,228,144,192, 17,252,242,104,150,
+ 73,100,158,100,152,184, 2,241,136,209,174,192,223,157, 87, 65,220,155,206,193, 6,227, 38, 54,103,153,200,243,251,150, 86, 74,
+116, 16,151, 88, 51,198, 32,105,228,145,215, 76, 90,125,208,177,251,224,144, 7,186, 43,124,248,253,166,217,155, 99, 33,218,252,
+216,134, 49,179,218, 76, 81, 39,151, 32,244,188,168,213,125, 22,190,141, 28, 45,123, 80, 51, 49,187, 32,176, 59,147,108,250,131,
+100,219,175, 46, 39,197,175,252,101,195,183, 19,212,254, 47,243,190, 46, 53,125,128,129, 63,119,238, 45,186,205,183, 18,130, 3,
+186,229,224,112, 91, 55, 66, 45,164,103, 37,141,254, 46,177,231,232,225, 89,173,187,122,238, 12,113,183, 62, 6,123, 59,203,219,
+219, 17, 24,174, 99, 50, 49,145,166, 19,156,111, 50,203, 27,228, 21,141,136,213,241,114, 60,133,110,252,183,104,253,238, 73,109,
+171,239,147,206,242, 98,249,174, 16,159, 13, 90,255, 0,129,127,234,122,168, 25,184,221,140,209,227, 46,123,108,218, 14, 44, 99,
+ 11,171, 38, 32,255, 0, 9,169,122, 93, 2,205,252, 45, 90,116,233,247,111,107, 84,246, 2,203,182,183,229,220,246,124, 92,153,
+166, 76,140,150, 75,204,202,134, 35,241, 50, 2,241, 18, 74, 31,112,131,225,112,109,194,173,252,236,126,138,168,219, 49,246, 59,
+159,185,155, 6,253, 24,111,229, 36,131,254, 95,223,242,255, 0,194,111,225,252,122, 60, 57,219,198,172,124,185,253, 36,255, 0,
+210, 39,250,212,167,128,168,111, 59, 31,162,187,206,197,232,160,121,115,250, 73,255, 0,164, 79,245,171,188,185,253, 36,255, 0,
+210, 39,250,212,160,169, 35,206,199,250, 53,222,114, 63, 69, 3,160,127, 73, 63, 93, 63,214,167, 8, 63,156,159,174,159, 93, 41,
+224, 9, 94, 97, 58,122,173,253,157,254, 78,166,154,234, 30,129,167,167,113,126,143, 59,141, 63,197,253, 46, 85,212, 7,255,217,
+};
+
+#endif
diff --git a/source/blender/src/playanim.c b/source/blender/src/playanim.c
new file mode 100644
index 00000000000..ef07d910cc1
--- /dev/null
+++ b/source/blender/src/playanim.c
@@ -0,0 +1,711 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 <sys/types.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#ifndef WIN32
+#include <unistd.h>
+#include <sys/times.h>
+#include <sys/wait.h>
+#else
+#include <io.h>
+#include "BLI_winstuff.h"
+#endif
+#include "MEM_guardedalloc.h"
+
+#include "PIL_time.h"
+
+#include <math.h>
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "BDR_editcurve.h"
+
+#include "BKE_global.h"
+#include "BKE_utildefines.h"
+
+#include "BIF_gl.h"
+#include "BIF_screen.h"
+#include "BIF_mywindow.h"
+
+#include "playanim_ext.h"
+#include "mydevice.h"
+#include "blendef.h"
+#include "winlay.h"
+
+/* ***************** gl_util.c ****************** */
+
+static Window *g_window = NULL;
+static int qualN = 0;
+
+#define LSHIFT (1<<0)
+#define RSHIFT (1<<1)
+#define SHIFT (LSHIFT | RSHIFT)
+#define LALT (1<<2)
+#define RALT (1<<3)
+#define ALT (LALT | RALT)
+#define LCTRL (1<<4)
+#define RCTRL (1<<5)
+#define LMOUSE (1<<16)
+#define MMOUSE (1<<17)
+#define RMOUSE (1<<18)
+#define MOUSE (LMOUSE | MMOUSE | RMOUSE)
+
+unsigned short screen_qread(short *val, char *ascii);
+
+/* implementation */
+static int qreadN(short *val)
+{
+ char ascii;
+ int event = screen_qread(val, &ascii);
+
+ switch(event){
+ case LEFTMOUSE:
+ if (*val) qualN |= LMOUSE;
+ else qualN &= ~LMOUSE;
+ break;
+ case MIDDLEMOUSE:
+ if (*val) qualN |= MMOUSE;
+ else qualN &= ~MMOUSE;
+ break;
+ case RIGHTMOUSE:
+ if (*val) qualN |= RMOUSE;
+ else qualN &= ~RMOUSE;
+ break;
+ case LEFTSHIFTKEY:
+ if (*val) qualN |= LSHIFT;
+ else qualN &= ~LSHIFT;
+ break;
+ case RIGHTSHIFTKEY:
+ if (*val) qualN |= RSHIFT;
+ else qualN &= ~RSHIFT;
+ break;
+ case LEFTCTRLKEY:
+ if (*val) qualN |= LCTRL;
+ else qualN &= ~LCTRL;
+ break;
+ case RIGHTCTRLKEY:
+ if (*val) qualN |= RCTRL;
+ else qualN &= ~RCTRL;
+ break;
+ case LEFTALTKEY:
+ if (*val) qualN |= LALT;
+ else qualN &= ~LALT;
+ break;
+ case RIGHTALTKEY:
+ if (*val) qualN |= RALT;
+ else qualN &= ~RALT;
+ break;
+ }
+
+ return(event);
+}
+
+/* ***************** gl_util.c ****************** */
+
+
+
+
+typedef struct pict{
+ struct pict *next, *prev;
+ char *mem;
+ int size;
+ char *name;
+ struct ImBuf *ibuf;
+ struct anim *anim;
+ int frame;
+ int IB_flags;
+}Pict;
+
+static struct ListBase _picsbase = {0,0};
+static struct ListBase *picsbase = &_picsbase;
+static int fromdisk = FALSE;
+static float zoomx = 1.0 , zoomy = 1.0;
+static double ptottime = 0.0, swaptime = 0.04;
+
+static int pupdate_time(void)
+{
+ static double ltime;
+ double time;
+
+ time = PIL_check_seconds_timer();
+
+ ptottime += (time - ltime);
+ ltime = time;
+ return (ptottime < 0);
+}
+
+static void toscreen(struct ImBuf *ibuf)
+{
+ if (ibuf == 0){
+ printf("no ibuf !\n");
+ return;
+ }
+
+ glRasterPos2f(-1, -1);
+
+ glDrawPixels(ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
+
+ pupdate_time();
+
+ window_swap_buffers(g_window);
+}
+
+static void build_pict_list(char * first)
+{
+ int size,pic,file;
+ char *mem, name[256];
+ short val;
+ struct pict * picture = 0;
+ struct ImBuf *ibuf = 0;
+ int count = 0;
+ char str[100];
+ struct anim * anim;
+
+ if (IMB_isanim(first)) {
+ anim = IMB_open_anim(first, IB_rect);
+ if (anim) {
+ ibuf = IMB_anim_absolute(anim, 0);
+ if (ibuf) {
+ toscreen(ibuf);
+ IMB_freeImBuf(ibuf);
+ }
+
+ for (pic = 0; pic < IMB_anim_get_duration(anim); pic ++) {
+ picture = (Pict*)MEM_callocN(sizeof(Pict),"Pict");
+ picture->anim = anim;
+ picture->frame = pic;
+ picture->IB_flags = IB_rect;
+ sprintf(str, "%s : %d", first, pic + 1);
+ picture->name = strdup(str);
+ BLI_addtail(picsbase, picture);
+ }
+ } else printf("couldn't open anim %s\n", first);
+ } else {
+
+ strcpy(name,first);
+
+ pupdate_time();
+ ptottime = 1.0;
+
+/*
+ O_DIRECT
+ If set, all reads and writes on the resulting file descriptor will
+ be performed directly to or from the user program buffer, provided
+ appropriate size and alignment restrictions are met. Refer to the
+ F_SETFL and F_DIOINFO commands in the fcntl(2) manual entry for
+ information about how to determine the alignment constraints.
+ O_DIRECT is a Silicon Graphics extension and is only supported on
+ local EFS and XFS file systems.
+*/
+ while(IMB_ispic(name)){
+ file = open(name, O_BINARY|O_RDONLY, 0);
+ if (file < 0) return;
+ picture = (struct pict*)calloc(1, sizeof(struct pict));
+ if (picture == 0){
+ printf("Not enough memory for pict struct \n");
+ close(file);
+ return;
+ }
+ size = BLI_filesize(file);
+ picture->size = size;
+ picture->IB_flags = IB_rect;
+
+ if (fromdisk == FALSE) {
+ mem=(char *)malloc(size);
+ if (mem==0){
+ printf("Couldn't get memory\n");
+ close(file);
+ free(picture);
+ return;
+ }
+
+ if (read(file,mem,size) != size){
+ printf("Error while reading %s\n",name);
+ close(file);
+ free(picture);
+ free(mem);
+ return;
+ }
+ } else mem = 0;
+
+ picture->mem = mem;
+ picture->name = strdup(name);
+ close(file);
+ BLI_addtail(picsbase,picture);
+ count++;
+
+ pupdate_time();
+
+ if (ptottime > 1.0) {
+ if (picture->mem) ibuf = IMB_ibImageFromMemory((int *) picture->mem, picture->size, picture->IB_flags);
+ else ibuf = IMB_loadiffname(picture->name, picture->IB_flags);
+ if (ibuf) {
+ toscreen(ibuf);
+ IMB_freeImBuf(ibuf);
+ glDrawBuffer(GL_FRONT);
+
+ cpack(-1);
+ glRasterPos2i(10, 10);
+ sprintf(str, "%4d: %s", count, name);
+ glCallLists(strlen(str), GL_UNSIGNED_BYTE, str);
+ glDrawBuffer(GL_BACK);
+ }
+ pupdate_time();
+ ptottime = 0.0;
+ }
+
+ BLI_newname(name, +1);
+
+ while(qtest()){
+ switch(qreadN(&val)){
+ case ESCKEY:
+ if (val) return;
+ break;
+ }
+ }
+ }
+ }
+ return;
+}
+
+void playanim(int argc, char **argv)
+{
+ struct ImBuf *ibuf = 0;
+ struct pict *picture = 0;
+ char name[256];
+ short val = 0, go = TRUE, ibufx = 0, ibufy = 0;
+ int event, stopped = FALSE, maxwinx, maxwiny;
+ short /* c233 = FALSE, */ /* yuvx = FALSE, */ once = FALSE, sstep = FALSE, wait2 = FALSE, /* resetmap = FALSE, */ pause = 0;
+ short pingpong = FALSE, direction = 1, next = 1, turbo = FALSE, /* doubleb = TRUE, */ noskip = FALSE;
+ int sizex, sizey, ofsx, ofsy, i;
+ /* This was done to disambiguate the name for use under c++. */
+ struct anim * anim = 0;
+ int start_x= 0, start_y= 0;
+
+ while (argc > 1) {
+ if (argv[1][0] == '-'){
+ switch(argv[1][1]) {
+ case 'm':
+ fromdisk = TRUE;
+ break;
+ case 'p':
+ if (argc>3) {
+ start_x= atoi(argv[2]);
+ start_y= atoi(argv[3]);
+ argc-= 2;
+ argv+= 2;
+ } else {
+ printf("too few arguments for -p (need 2): skipping\n");
+ }
+ break;
+ default:
+ printf("unknown option '%c': skipping\n", argv[1][1]);
+ break;
+ }
+ argc--;
+ argv++;
+ } else break;
+ }
+
+ if (argc > 1) strcpy(name,argv[1]);
+ else {
+ BLI_getwdN(name);
+ if (name[strlen(name)-1] != '/') strcat(name,"/");
+ }
+
+ if (IMB_isanim(name)) {
+ anim = IMB_open_anim(name, IB_rect);
+ if (anim) {
+ ibuf = IMB_anim_absolute(anim, 0);
+ IMB_close_anim(anim);
+ anim = NULL;
+ }
+ } else if (!IMB_ispic(name)) {
+ exit(1);
+ }
+
+ if (ibuf == 0) ibuf = IMB_loadiffname(name, IB_rect);
+ if (ibuf == 0){
+ printf("couldn't open %s\n",name);
+ exit(1);
+ }
+
+ #if !defined(WIN32) && !defined(__APPLE__)
+ if (fork()) exit(0);
+ #endif
+
+ winlay_get_screensize(&maxwinx, &maxwiny);
+
+ /* XXX, fixme zr */
+ {
+ extern void add_to_mainqueue(Window *win, void *user_data, short evt, short val, char ascii);
+
+ g_window = window_open("Blender:Anim", start_x, start_y, ibuf->x, ibuf->y, 0);
+ window_set_handler(g_window, add_to_mainqueue, NULL);
+ }
+
+ ibufx = ibuf->x;
+ ibufy = ibuf->y;
+
+ if (maxwinx % ibuf->x) maxwinx = ibuf->x * (1 + (maxwinx / ibuf->x));
+ if (maxwiny % ibuf->y) maxwiny = ibuf->y * (1 + (maxwiny / ibuf->y));
+
+ glClearColor(0.0, 0.0, 0.0, 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ window_swap_buffers(g_window);
+
+ build_pict_list(name);
+
+ for (i = 2; i < argc; i++){
+ strcpy(name, argv[i]);
+ build_pict_list(name);
+ }
+
+ IMB_freeImBuf(ibuf);
+ ibuf = 0;
+
+ pupdate_time();
+ ptottime = 0;
+
+ while (go){
+ if (pingpong) direction = -direction;
+
+ if (direction == 1) picture = picsbase->first;
+ else picture = picsbase->last;
+
+ if (picture == 0){
+ printf("couldn't find pictures\n");
+ go = FALSE;
+ }
+ if (pingpong){
+ if (direction == 1) picture = picture->next;
+ else picture = picture->prev;
+ }
+ if (ptottime > 0.0) ptottime = 0.0;
+
+ while (picture){
+ if (ibuf != 0 && ibuf->type == 0) IMB_freeImBuf(ibuf);
+
+ if (picture->ibuf) ibuf = picture->ibuf;
+ else if (picture->anim) ibuf = IMB_anim_absolute(picture->anim, picture->frame);
+ else if (picture->mem) ibuf = IMB_ibImageFromMemory((int *) picture->mem, picture->size, picture->IB_flags);
+ else ibuf = IMB_loadiffname(picture->name, picture->IB_flags);
+
+ if (ibuf){
+ strcpy(ibuf->name, picture->name);
+
+ while (pupdate_time()) PIL_sleep_ms(1);
+ ptottime -= swaptime;
+ toscreen(ibuf);
+ } /* else deleten */
+ else {
+ printf("error: can't play this image type\n");
+ exit(0);
+ }
+
+ if (once){
+ if (picture->next == 0) wait2 = TRUE;
+ else if (picture->prev == 0) wait2 = TRUE;
+ }
+
+ next = direction;
+
+ while ((qtest() != 0 ) || ( wait2 != 0)){
+ if (wait2 && stopped) {
+ stopped = FALSE;
+ }
+
+ event = qreadN(&val);
+ /* printf("%d %d\n", event, val); */
+
+ if (wait2){
+ pupdate_time();
+ ptottime = 0;
+ }
+ switch (event){
+ case AKEY:
+ if (val)
+ noskip = !noskip;
+ break;
+ case PKEY:
+ if (val)
+ pingpong = !pingpong;
+ break;
+ case SLASHKEY:
+ if (val) {
+ if (qualN & SHIFT) {
+ if (ibuf)
+ printf(" Name: %s | Speed: %.2f frames/s\n", ibuf->name, 1.0 / swaptime);
+ } else {
+ swaptime = 1.0 / 5.0;
+ }
+ }
+ break;
+ case LEFTARROWKEY:
+ if (val){
+ sstep = TRUE;
+ wait2 = FALSE;
+ if (qualN & SHIFT) {
+ picture = picsbase->first;
+ next = 0;
+ } else {
+ next = -1;
+ }
+ }
+ break;
+ case DOWNARROWKEY:
+ if (val){
+ wait2 = FALSE;
+ if (qualN & SHIFT) {
+ next = direction = -1;
+ } else {
+ next = -10;
+ sstep = TRUE;
+ }
+ }
+ break;
+ case RIGHTARROWKEY:
+ if (val){
+ sstep = TRUE;
+ wait2 = FALSE;
+ if (qualN & SHIFT) {
+ picture = picsbase->last;
+ next = 0;
+ } else {
+ next = 1;
+ }
+ }
+ break;
+ case UPARROWKEY:
+ if (val){
+ wait2 = FALSE;
+ if (qualN & SHIFT) {
+ next = direction = 1;
+ } else {
+ next = 10;
+ sstep = TRUE;
+ }
+ }
+ break;
+ case LEFTMOUSE:
+ case MOUSEX:
+ if (qualN & LMOUSE) {
+ window_get_size(g_window,&sizex,&sizey);
+ picture = picsbase->first;
+ i = 0;
+ while (picture){
+ i ++;
+ picture = picture->next;
+ }
+ i = (i * val) / sizex;
+ picture = picsbase->first;
+ for (; i > 0; i--){
+ if (picture->next == 0) break;
+ picture = picture->next;
+ }
+ sstep = TRUE;
+ wait2 = FALSE;
+ next = 0;
+ }
+ break;
+ go= FALSE;
+ break;
+ case EQUALKEY:
+ if (val) {
+ if (qualN & SHIFT) {
+ pause ++;
+ printf("pause:%d\n", pause);
+ } else swaptime /= 1.1;
+ }
+ break;
+ case MINUSKEY:
+ if (val) {
+ if (qualN & SHIFT) {
+ pause --;
+ printf("pause:%d\n", pause);
+ } else swaptime *= 1.1;
+ }
+ break;
+ case PAD0:
+ if (val){
+ if (once) once = wait2 = FALSE;
+ else {
+ picture = 0;
+ once = TRUE;
+ wait2 = FALSE;
+ }
+ }
+ break;
+ case RETKEY:
+ case PADENTER:
+ if (val){
+ wait2 = sstep = FALSE;
+ }
+ break;
+ case PADPERIOD:
+ if (val){
+ if (sstep) wait2 = FALSE;
+ else {
+ sstep = TRUE;
+ wait2 = !wait2;
+ }
+ }
+ break;
+ case PAD1:
+ swaptime = 1.0 / 60.0;
+ break;
+ case PAD2:
+ swaptime = 1.0 / 50.0;
+ break;
+ case PAD3:
+ swaptime = 1.0 / 30.0;
+ break;
+ case PAD4:
+ swaptime = 1.0 / 25.0;
+ break;
+ case PAD5:
+ swaptime = 1.0 / 20.0;
+ break;
+ case PAD6:
+ swaptime = 1.0 / 15.0;
+ break;
+ case PAD7:
+ swaptime = 1.0 / 12.0;
+ break;
+ case PAD8:
+ swaptime = 1.0 / 10.0;
+ break;
+ case PAD9:
+ swaptime = 1.0 / 6.0;
+ break;
+ case PADPLUSKEY:
+ if (val == 0) break;
+ zoomx += 2.0;
+ zoomy += 2.0;
+ case PADMINUS:
+ if (val == 0) break;
+ if (zoomx > 1.0) zoomx -= 1.0;
+ if (zoomy > 1.0) zoomy -= 1.0;
+ window_get_position(g_window,&ofsx,&ofsy);
+ window_get_size(g_window,&sizex,&sizey);
+ ofsx += sizex/2;
+ ofsy += sizey/2;
+ sizex = zoomx * ibufx;
+ sizey = zoomy * ibufy;
+ ofsx -= sizex/2;
+ ofsy -= sizey/2;
+/* window_set_position(g_window,sizex,sizey); */
+ window_set_size(g_window,sizex,sizey);
+ break;
+ case RESHAPE:
+ case REDRAW:
+ window_get_size(g_window,&sizex,&sizey);
+ window_make_active(g_window);
+
+ glViewport(0, 0, sizex, sizey);
+ glScissor(0, 0, sizex, sizey);
+
+ zoomx = (float) sizex / ibufx;
+ zoomy = (float) sizey / ibufy;
+ zoomx = floor(zoomx + 0.5);
+ zoomy = floor(zoomy + 0.5);
+ if (zoomx < 1.0) zoomx = 1.0;
+ if (zoomy < 1.0) zoomy = 1.0;
+
+ sizex = zoomx * ibufx;
+ sizey = zoomy * ibufy;
+
+ glPixelZoom(zoomx, zoomy);
+ glEnable(GL_DITHER);
+ ptottime = 0.0;
+ toscreen(ibuf);
+ while (qtest()) qreadN(&val);
+
+ break;
+ case ESCKEY:
+ case WINCLOSE:
+ case WINQUIT:
+ go = FALSE;
+ break;
+ }
+ if (go == FALSE) break;
+ }
+
+ wait2 = sstep;
+
+ if (wait2 == 0 && stopped == 0) {
+ stopped = TRUE;
+ }
+
+ pupdate_time();
+
+ if (picture && next) {
+ /* altijd minstens 1 stap zetten */
+ while (picture){
+ if (next < 0) picture = picture->prev;
+ else picture = picture->next;
+
+ if (once && picture != 0){
+ if (picture->next == 0) wait2 = TRUE;
+ else if (picture->prev == 0) wait2 = TRUE;
+ }
+
+ if (wait2 || ptottime < swaptime || turbo || noskip) break;
+ ptottime -= swaptime;
+ }
+ if (picture == 0 && sstep) {
+ if (next < 0) picture = picsbase->last;
+ else if (next > 0) picture = picsbase->first;
+ }
+ }
+ if (go == FALSE) break;
+ }
+ }
+ picture = picsbase->first;
+ anim = NULL;
+ while (picture) {
+ if (picture && picture->anim && (anim != picture->anim)) {
+ // to prevent divx crashes
+ anim = picture->anim;
+ IMB_close_anim(anim);
+ }
+ picture = picture->next;
+ }
+}
diff --git a/source/blender/src/poseobject.c b/source/blender/src/poseobject.c
new file mode 100644
index 00000000000..d93a93028a7
--- /dev/null
+++ b/source/blender/src/poseobject.c
@@ -0,0 +1,222 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * support for animation modes - Reevan McKay
+ */
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+
+#include "DNA_action_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_view3d_types.h"
+
+#include "BKE_action.h"
+#include "BKE_armature.h"
+#include "BKE_global.h"
+#include "BKE_displist.h"
+
+#include "BIF_gl.h"
+#include "BIF_graphics.h"
+#include "BIF_space.h"
+#include "BIF_toolbox.h"
+#include "BIF_screen.h"
+#include "BIF_poseobject.h"
+
+#include "BDR_editobject.h"
+
+#include "BSE_edit.h"
+
+#include "mydevice.h"
+#include "blendef.h"
+
+static void armature_filter_pose_keys (bPose *pose, bArmature* arm);
+static void armature_bonechildren_filter_pose_keys (bPose *pose, Bone *bone);
+
+void collect_pose_garbage(Object *ob)
+{
+ bPoseChannel *pchan, *next;
+ Bone *bone;
+
+ if (!ob)
+ return;
+
+ if (!ob->pose)
+ return;
+
+ switch (ob->type){
+ case OB_ARMATURE:
+ /* Remove unused pose channels */
+ for (pchan = ob->pose->chanbase.first; pchan; pchan=next){
+ next=pchan->next;
+ bone = get_named_bone(ob->data, pchan->name);
+ if (!bone)
+ BLI_freelinkN(&ob->pose->chanbase, pchan);
+ }
+ break;
+ default:
+ break;
+ }
+
+}
+
+void enter_posemode(void)
+{
+ Base *base;
+ Object *ob;
+ bArmature *arm;
+
+ if(G.scene->id.lib) return;
+ base= BASACT;
+ if(base==0) return;
+ if((base->lay & G.vd->lay)==0) return;
+
+ ob= base->object;
+ if(ob->data==0) return;
+
+ if (ob->id.lib){
+ error ("Can't pose libdata");
+ return;
+ }
+
+ switch (ob->type){
+ case OB_ARMATURE:
+ arm= get_armature(ob);
+ if( arm==0 ) return;
+ G.obpose= ob;
+ /* make_poseMesh(); */
+ allqueue(REDRAWVIEW3D, 0);
+ break;
+ default:
+ return;
+ }
+
+ if (G.obedit) exit_editmode(1);
+ G.f &= ~(G_VERTEXPAINT | G_FACESELECT | G_TEXTUREPAINT | G_WEIGHTPAINT);
+
+
+}
+
+void filter_pose_keys (void)
+{
+
+
+ Object *ob;
+ bPoseChannel *chan;
+
+ ob=G.obpose;
+ if (!ob)
+ return;
+
+ switch (ob->type){
+ case OB_ARMATURE:
+ armature_filter_pose_keys (ob->pose, (bArmature*)ob->data);
+ break;
+ default:
+ if (ob->pose){
+ for (chan=ob->pose->chanbase.first; chan; chan=chan->next){
+ chan->flag |= POSE_KEY;
+ }
+ }
+ break;
+ }
+}
+
+static void armature_filter_pose_keys (bPose *pose, bArmature *arm)
+{
+ Bone *bone;
+
+ if (!pose)
+ return;
+ if (!arm)
+ return;
+
+ for (bone=arm->bonebase.first; bone; bone=bone->next){
+ armature_bonechildren_filter_pose_keys (pose, bone);
+ }
+}
+
+static void armature_bonechildren_filter_pose_keys (bPose *pose, Bone *bone)
+{
+ Bone *curbone;
+ bPoseChannel *chan;
+
+ if (!bone)
+ return;
+
+ for (chan=pose->chanbase.first; chan; chan=chan->next){
+ if (BLI_streq(chan->name, bone->name))
+ break;
+ }
+
+ if (chan){
+ if (bone->flag & BONE_SELECTED){
+ chan->flag |= POSE_KEY;
+ }
+ else {
+ chan->flag &= ~POSE_KEY;
+ }
+ }
+
+ for (curbone=bone->childbase.first; curbone; curbone=curbone->next){
+ armature_bonechildren_filter_pose_keys (pose, curbone);
+ }
+}
+
+void exit_posemode (int freedata)
+{
+ Object *ob;
+
+ if(G.obpose==0) return;
+
+ ob= G.obpose;
+
+ G.obpose= 0;
+ makeDispList(ob);
+
+ if(freedata) {
+ setcursor_space(SPACE_VIEW3D, CURSOR_STD);
+
+ countall();
+ allqueue(REDRAWVIEW3D, 0);
+ }
+ else {
+ G.obpose= ob;
+ }
+
+ scrarea_queue_headredraw(curarea);
+}
diff --git a/source/blender/src/previewrender.c b/source/blender/src/previewrender.c
new file mode 100644
index 00000000000..1180248c16e
--- /dev/null
+++ b/source/blender/src/previewrender.c
@@ -0,0 +1,1074 @@
+/* previewrender.c GRAPHICS
+ *
+ * maart 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 *****
+ */
+
+/* global includes */
+
+#include <stdlib.h>
+#include <math.h>
+
+#ifndef WIN32
+#include <unistd.h>
+#else
+#include <io.h>
+#endif
+#include "MEM_guardedalloc.h"
+#include "BLI_arithb.h"
+#include "BKE_utildefines.h"
+
+#include "MTC_matrixops.h"
+
+#include "render.h"
+#include "mydevice.h"
+
+#include "DNA_texture_types.h"
+#include "DNA_world_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_image_types.h"
+#include "DNA_object_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+
+#include "BKE_global.h"
+#include "BKE_image.h"
+#include "BKE_texture.h"
+#include "BKE_material.h"
+#include "BKE_world.h"
+#include "BKE_texture.h"
+
+#include "BIF_gl.h"
+#include "BIF_screen.h"
+#include "BIF_space.h" /* allqueue */
+#include "BIF_drawimage.h" /* rectwrite_part */
+//#include "BIF_previewrender.h"
+#include "BIF_mywindow.h"
+
+#include "RE_renderconverter.h"
+
+//#include "mydevice.h"
+
+#define PR_RECTX 101
+#define PR_RECTY 101
+#define PR_XMIN 10
+#define PR_YMIN 10
+#define PR_XMAX 190
+#define PR_YMAX 190
+
+#define PR_FACY (PR_YMAX-PR_YMIN-4)/(PR_RECTY)
+
+static rcti prerect;
+static int pr_sizex, pr_sizey;
+static float pr_facx, pr_facy;
+
+
+/* implementation */
+
+static short snijpunt(float *v1,
+ float *v2,
+ float *v3,
+ float *rtlabda,
+ float *ray1,
+ float *ray2)
+{
+ float x0,x1,x2,t00,t01,t02,t10,t11,t12,t20,t21,t22;
+ float m0,m1,m2,deeldet,det1,det2,det3;
+ float rtu, rtv;
+
+ t00= v3[0]-v1[0];
+ t01= v3[1]-v1[1];
+ t02= v3[2]-v1[2];
+ t10= v3[0]-v2[0];
+ t11= v3[1]-v2[1];
+ t12= v3[2]-v2[2];
+ t20= ray1[0]-ray2[0];
+ t21= ray1[1]-ray2[1];
+ t22= ray1[2]-ray2[2];
+
+ x0= t11*t22-t12*t21;
+ x1= t12*t20-t10*t22;
+ x2= t10*t21-t11*t20;
+
+ deeldet= t00*x0+t01*x1+t02*x2;
+ if(deeldet!=0.0) {
+ m0= ray1[0]-v3[0];
+ m1= ray1[1]-v3[1];
+ m2= ray1[2]-v3[2];
+ det1= m0*x0+m1*x1+m2*x2;
+ rtu= det1/deeldet;
+ if(rtu<=0.0) {
+ det2= t00*(m1*t22-m2*t21);
+ det2+= t01*(m2*t20-m0*t22);
+ det2+= t02*(m0*t21-m1*t20);
+ rtv= det2/deeldet;
+ if(rtv<=0.0) {
+ if(rtu+rtv>= -1.0) {
+
+ det3= m0*(t12*t01-t11*t02);
+ det3+= m1*(t10*t02-t12*t00);
+ det3+= m2*(t11*t00-t10*t01);
+ *rtlabda= det3/deeldet;
+
+ if(*rtlabda>=0.0 && *rtlabda<=1.0) {
+ return 1;
+ }
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+static float rcubev[7][3]= {
+ {-0.002055, 6.627364, -3.369742},
+ {-6.031684, -3.750204, -1.992980},
+ {-6.049086, 3.817431, 1.969788},
+ { 6.031685, 3.833064, 1.992979},
+ { 6.049086, -3.734571, -1.969787},
+ { 0.002054, -6.544502, 3.369744},
+ {-0.015348, 1.023131, 7.332510} };
+
+static int rcubi[3][4]= {
+ {3, 6, 5, 4},
+ {1, 5, 6, 2},
+ {3, 0, 2, 6} };
+
+
+static int ray_previewrender(int x,
+ int y,
+ float *vec)
+{
+ float scalef= 12.8/100.0;
+ float ray1[3], ray2[3];
+ float minlabda, labda;
+ int totface= 3, hitface= -1;
+ int a;
+
+ ray1[0]= ray2[0]= x*scalef;
+ ray1[1]= ray2[1]= y*scalef;
+ ray1[2]= -10.0;
+ ray2[2]= 10.0;
+
+ minlabda= 1.0;
+ for(a=0; a<totface; a++) {
+ if(snijpunt( rcubev[rcubi[a][0]], rcubev[rcubi[a][1]], rcubev[rcubi[a][2]], &labda, ray1, ray2)) {
+ if( labda < minlabda) {
+ minlabda= labda;
+ hitface= a;
+ }
+ }
+ if(snijpunt( rcubev[rcubi[a][0]], rcubev[rcubi[a][2]], rcubev[rcubi[a][3]], &labda, ray1, ray2)) {
+ if( labda < minlabda) {
+ minlabda= labda;
+ hitface= a;
+ }
+ }
+ }
+
+ if(hitface > -1) {
+
+ CalcNormFloat(rcubev[rcubi[hitface][0]], rcubev[rcubi[hitface][1]], rcubev[rcubi[hitface][2]], R.vn);
+
+ vec[0]= (minlabda*(ray1[0]-ray2[0])+ray2[0])/3.7;
+ vec[1]= (minlabda*(ray1[1]-ray2[1])+ray2[1])/3.7;
+ vec[2]= (minlabda*(ray1[2]-ray2[2])+ray2[2])/3.7;
+
+ return 1;
+ }
+ return 0;
+}
+
+
+static unsigned int previewback(int type, int x, int y)
+{
+ if(type & MA_DARK) {
+ if(abs(x)>abs(y)) return 0;
+ else return 0x40404040;
+ }
+ else {
+ if(abs(x)>abs(y)) return 0x40404040;
+ else return 0xa0a0a0a0;
+ }
+}
+
+static void view2d_to_window(int win, int *x_r, int *y_r)
+{
+ int x= *x_r, y= *y_r;
+ int size[2], origin[2];
+ float winmat[4][4];
+
+ bwin_getsinglematrix(win, winmat);
+ bwin_getsize(win, &size[0], &size[1]);
+ bwin_getsuborigin(win, &origin[0], &origin[1]);
+
+ *x_r= origin[0] + (size[0]*(0.5 + 0.5*(x*winmat[0][0] + y*winmat[1][0] + winmat[3][0])));
+ *y_r= origin[1] + (size[1]*(0.5 + 0.5*(x*winmat[0][1] + y*winmat[1][1] + winmat[3][1])));
+}
+
+static void set_previewrect(int win, int xmin, int ymin, int xmax, int ymax)
+{
+ prerect.xmin= xmin;
+ prerect.ymin= ymin;
+ prerect.xmax= xmax;
+ prerect.ymax= ymax;
+
+ view2d_to_window(win, &prerect.xmin, &prerect.ymin);
+ view2d_to_window(win, &prerect.xmax, &prerect.ymax);
+
+ pr_sizex= (prerect.xmax-prerect.xmin);
+ pr_sizey= (prerect.ymax-prerect.ymin);
+
+ pr_facx= ( (float)pr_sizex-1)/PR_RECTX;
+ pr_facy= ( (float)pr_sizey-1)/PR_RECTY;
+}
+
+static void display_pr_scanline(unsigned int *rect, int recty)
+{
+ /* we display 3 new scanlines, one old */
+
+ if(recty % 2) return;
+ if(recty<2) return;
+
+ rect+= (recty-2)*PR_RECTX;
+
+ /* iets meer uitvergroten in y om GL/mesa bugje te verhelpen */
+ glPixelZoom(pr_facx, pr_facy);
+
+ glRasterPos2f( (float)PR_XMIN+0.5, 1.0+(float)PR_YMIN + (recty*PR_FACY) );
+ glDrawPixels(PR_RECTX, 3, GL_RGBA, GL_UNSIGNED_BYTE, rect);
+
+ glPixelZoom(1.0, 1.0);
+}
+
+static void draw_tex_crop(Tex *tex)
+{
+ rcti rct;
+ int ret= 0;
+
+ if(tex==0) return;
+
+ if(tex->type==TEX_IMAGE) {
+ if(tex->cropxmin==0.0) ret++;
+ if(tex->cropymin==0.0) ret++;
+ if(tex->cropxmax==1.0) ret++;
+ if(tex->cropymax==1.0) ret++;
+ if(ret==4) return;
+
+ rct.xmin= PR_XMIN+2+tex->cropxmin*(PR_XMAX-PR_XMIN-4);
+ rct.xmax= PR_XMIN+2+tex->cropxmax*(PR_XMAX-PR_XMIN-4);
+ rct.ymin= PR_YMIN+2+tex->cropymin*(PR_YMAX-PR_YMIN-4);
+ rct.ymax= PR_YMIN+2+tex->cropymax*(PR_YMAX-PR_YMIN-4);
+
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+
+ glColor3ub(0, 0, 0);
+ glRecti(rct.xmin+1, rct.ymin-1, rct.xmax+1, rct.ymax-1);
+
+ glColor3ub(255, 255, 255);
+ glRecti(rct.xmin, rct.ymin, rct.xmax, rct.ymax);
+
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ }
+
+}
+
+void BIF_preview_changed(SpaceButs *sbuts)
+{
+ sbuts->cury= 0;
+ addafterqueue(sbuts->area->win, RENDERPREVIEW, 1);
+}
+
+void BIF_previewdraw(SpaceButs *sbuts)
+{
+ set_previewrect(sbuts->area->win, PR_XMIN, PR_YMIN, PR_XMAX, PR_YMAX);
+
+ if (sbuts->rect==0 || sbuts->cury==0) {
+ BIF_preview_changed(sbuts);
+ } else {
+ int y;
+
+ for (y=0; y<PR_RECTY; y++) {
+ display_pr_scanline(sbuts->rect, y);
+ }
+
+ if (sbuts->mainb==BUTS_TEX) {
+ draw_tex_crop(sbuts->lockpoin);
+ }
+ }
+}
+
+static void sky_preview_pixel(float lens, int x, int y, char *rect)
+{
+
+ if(R.wrld.skytype & WO_SKYPAPER) {
+ R.view[0]= (2*x)/(float)PR_RECTX;
+ R.view[1]= (2*y)/(float)PR_RECTY;
+ R.view[2]= 0.0;
+ }
+ else {
+ R.view[0]= x;
+ R.view[1]= y;
+ R.view[2]= -lens*PR_RECTX/32.0;
+ Normalise(R.view);
+ }
+ RE_sky(rect);
+}
+
+static void lamp_preview_pixel(LampRen *la, int x, int y, char *rect)
+{
+ float inpr, i, t, dist, distkw, vec[3];
+ int col;
+
+ R.co[0]= (float)x/(PR_RECTX/4);
+ R.co[1]= (float)y/(PR_RECTX/4);
+ R.co[2]= 0;
+
+ vec[0]= 0.02*x;
+ vec[1]= 0.02*y;
+ vec[2]= 0.005*PR_RECTX;
+ VECCOPY(R.view, vec);
+ dist= Normalise(R.view);
+
+ if(la->mode & LA_TEXTURE) do_lamp_tex(la, vec);
+
+ if(la->type==LA_SUN || la->type==LA_HEMI) {
+ dist= 1.0;
+ }
+ else {
+
+ if(la->mode & LA_QUAD) {
+
+ t= 1.0;
+ if(la->ld1>0.0)
+ t= la->dist/(la->dist+la->ld1*dist);
+ if(la->ld2>0.0) {
+ distkw= la->dist*la->dist;
+ t= t*distkw/(t*distkw+la->ld2*dist*dist);
+ }
+ dist= t;
+ }
+ else {
+ dist= (la->dist/(la->dist+dist));
+ }
+ }
+
+ if(la->type==LA_SPOT) {
+
+
+ if(la->mode & LA_SQUARE) {
+ /* slightly smaller... */
+ inpr= 1.7*cos(MAX2(fabs(R.view[0]/R.view[2]) , fabs(R.view[1]/R.view[2]) ));
+ }
+ else {
+ inpr= R.view[2];
+ }
+
+ t= la->spotsi;
+ if(inpr<t) dist= 0.0;
+ else {
+ t= inpr-t;
+ if(t<la->spotbl && la->spotbl!=0.0) {
+ /* zachte gebied */
+ i= t/la->spotbl;
+ t= i*i;
+ i= t*i;
+ inpr*=(3.0*t-2.0*i);
+ }
+ }
+ dist*=inpr;
+ }
+ else if(la->type==LA_LOCAL) dist*= R.view[2];
+
+ col= 255.0*dist*la->r;
+ if(col<=0) rect[0]= 0; else if(col>=255) rect[0]= 255; else rect[0]= col;
+
+ col= 255.0*dist*la->g;
+ if(col<=0) rect[1]= 0; else if(col>=255) rect[1]= 255; else rect[1]= col;
+
+ col= 255.0*dist*la->b;
+ if(col<=0) rect[2]= 0; else if(col>=255) rect[2]= 255; else rect[2]= col;
+}
+
+static void init_previewhalo(HaloRen *har, Material *mat)
+{
+
+ har->type= 0;
+ if(mat->mode & MA_HALO_XALPHA) har->type |= HA_XALPHA;
+ har->mat= mat;
+ har->hard= mat->har;
+ har->rad= PR_RECTX/2.0;
+ har->radsq= PR_RECTX*PR_RECTX/4.0;
+ har->alfa= mat->alpha;
+ har->add= 255.0*mat->add;
+ har->r= 255.0*mat->r;
+ har->g= 255.0*mat->g;
+ har->b= 255.0*mat->b;
+ har->xs= PR_RECTX/2.0;
+ har->ys= PR_RECTX/2.0;
+ har->zs= har->zd= 0;
+ har->seed= (mat->seed1 % 256);
+
+ if( (mat->mode & MA_HALOTEX) && mat->mtex[0] ) har->tex= 1; else har->tex=0;
+
+ if(mat->mode & MA_STAR) har->starpoints= mat->starc; else har->starpoints= 0;
+ if(mat->mode & MA_HALO_LINES) har->linec= mat->linec; else har->linec= 0;
+ if(mat->mode & MA_HALO_RINGS) har->ringc= mat->ringc; else har->ringc= 0;
+ if(mat->mode & MA_HALO_FLARE) har->flarec= mat->flarec; else har->flarec= 0;
+
+ if(har->flarec) {
+ har->xs-= PR_RECTX/3;
+ har->ys+= PR_RECTX/3;
+
+ har->rad*= 0.3;
+ har->radsq= har->rad*har->rad;
+
+ har->pixels= har->rad*har->rad*har->rad;
+ }
+}
+
+static void halo_preview_pixel(HaloRen *har, int startx, int endx, int y, char *rect)
+{
+ float dist, xn, yn, xsq, ysq;
+ int x;
+ char front[4];
+
+ if(har->flarec) yn= y-PR_RECTX/3;
+ else yn= y;
+ ysq= yn*yn;
+
+ for(x=startx; x<endx; x++) {
+
+ if(har->flarec) xn= x+PR_RECTX/3;
+ else xn= x;
+
+ xsq= xn*xn;
+ dist= xsq+ysq;
+
+
+
+ if(dist<har->radsq) {
+ RE_shadehalo(har, front, 0, dist, xn, yn, har->flarec);
+ RE_addalphaAddfac(rect, front, har->add);
+ }
+ rect+= 4;
+ }
+}
+
+static void previewflare(SpaceButs *sbuts, HaloRen *har, unsigned int *rect)
+{
+ float ycor;
+ unsigned int *rectot;
+ int afmx, afmy, rectx, recty;
+
+ /* temps */
+ ycor= R.ycor;
+ rectx= R.rectx;
+ recty= R.recty;
+ afmx= R.afmx;
+ afmy= R.afmy;
+ rectot= R.rectot;
+
+ R.ycor= 1.0;
+ R.rectx= PR_RECTX;
+ R.recty= PR_RECTY;
+ R.afmx= PR_RECTX/2;
+ R.afmy= PR_RECTY/2;
+ R.rectot= rect;
+
+ waitcursor(1);
+
+ RE_renderflare(har);
+
+ BIF_previewdraw(sbuts);
+
+ waitcursor(0);
+
+ /* temps */
+ R.ycor= ycor;
+ R.rectx= rectx;
+ R.recty= recty;
+ R.afmx= afmx;
+ R.afmy= afmy;
+ R.rectot= rectot;
+}
+
+extern float Tin, Tr, Tg, Tb, Ta; /* texture.c */
+static void texture_preview_pixel(Tex *tex, int x, int y, char *rect)
+{
+ float i, v1, xsq, ysq, texvec[3];
+ int rgbnor, tracol, skip=0;
+
+ if(tex->type==TEX_IMAGE) {
+ v1= 1.0/PR_RECTX;
+
+ texvec[0]= 0.5+v1*x;
+ texvec[1]= 0.5+v1*y;
+
+ /* geen coordmapping, uitzondering: repeat */
+ if(tex->xrepeat>1) {
+ texvec[0] *= tex->xrepeat;
+ if(texvec[0]>1.0) texvec[0] -= (int)(texvec[0]);
+ }
+ if(tex->yrepeat>1) {
+ texvec[1] *= tex->yrepeat;
+ if(texvec[1]>1.0) texvec[1] -= (int)(texvec[1]);
+ }
+
+ }
+ else if(tex->type==TEX_ENVMAP) {
+ if(tex->env) {
+ ysq= y*y;
+ xsq= x*x;
+ if(xsq+ysq < (PR_RECTX/2)*(PR_RECTY/2)) {
+ texvec[2]= sqrt( (float)((PR_RECTX/2)*(PR_RECTY/2)-xsq-ysq) );
+ texvec[0]= -x;
+ texvec[1]= -y;
+ Normalise(texvec);
+
+ i= 2.0*(texvec[2]);
+ texvec[0]= (i*texvec[0]);
+ texvec[1]= (i*texvec[1]);
+ texvec[2]= (-1.0+i*texvec[2]);
+
+ }
+ else {
+ skip= 1;
+ Ta= 0.0;
+ }
+ }
+ else {
+ skip= 1;
+ Ta= 0.0;
+ }
+ }
+ else {
+ v1= 2.0/PR_RECTX;
+
+ texvec[0]= v1*x;
+ texvec[1]= v1*y;
+ texvec[2]= 0.0;
+ }
+
+ /* geeft geen Tin terug */
+ if(tex->type==TEX_STUCCI) {
+ tex->nor= R.vn;
+ R.vn[0]= 1.0;
+ R.vn[1]= R.vn[2]= 0.0;
+ }
+
+ if(skip==0) rgbnor= multitex(tex, texvec, 0, 0);
+ else rgbnor= 1;
+
+ if(rgbnor & 1) {
+
+ rect[0]= 255.0*Tr;
+ rect[1]= 255.0*Tg;
+ rect[2]= 255.0*Tb;
+
+ if(Ta!=1.0) {
+ tracol= 64+100*(abs(x)>abs(y));
+ tracol= (1.0-Ta)*tracol;
+
+ rect[0]= tracol+ (rect[0]*Ta) ;
+ rect[1]= tracol+ (rect[1]*Ta) ;
+ rect[2]= tracol+ (rect[2]*Ta) ;
+
+ }
+ }
+ else {
+
+ if(tex->type==TEX_STUCCI) {
+ Tin= 0.5 + 0.7*tex->nor[0];
+ CLAMP(Tin, 0.0, 1.0);
+ }
+ rect[0]= 255.0*Tin;
+ rect[1]= 255.0*Tin;
+ rect[2]= 255.0*Tin;
+ }
+}
+
+static float pr1_lamp[3]= {2.3, -2.4, -4.6};
+static float pr2_lamp[3]= {-8.8, -5.6, -1.5};
+static float pr1_col[3]= {0.8, 0.8, 0.8};
+static float pr2_col[3]= {0.5, 0.6, 0.7};
+
+static void shade_preview_pixel(float *vec,
+ int x,
+ int y,
+ char *rect,
+ int smooth)
+{
+ Material *mat;
+ float v1,inp, inprspec=0, isr=0.0, isb=0.0, isg=0.0;
+ float ir=0.0, ib=0.0, ig=0.0;
+ float view[3], lv[3], *la, alpha;
+ float eul[3], tmat[3][3], imat[3][3];
+ int temp, a;
+ char tracol;
+
+ mat= R.matren;
+ /* pr1_lamp[0]= mat->mtex[0]->ofs[0]; */
+ /* pr1_lamp[1]= mat->mtex[0]->ofs[1]; */
+ /* pr1_lamp[2]= mat->mtex[0]->ofs[2]; */
+
+ /* pr2_lamp[0]= mat->mtex[0]->size[0]; */
+ /* pr2_lamp[1]= mat->mtex[0]->size[1]; */
+ /* pr2_lamp[2]= mat->mtex[0]->size[2]; */
+
+ v1= 1.0/PR_RECTX;
+ view[0]= v1*x;
+ view[1]= v1*y;
+ view[2]= 1.0;
+ Normalise(view);
+
+ R.refcol[0]= R.refcol[1]= R.refcol[2]= R.refcol[3]= 0.0;
+
+ /* texture afhandeling */
+ if(mat->texco) {
+
+ VECCOPY(R.lo, vec);
+
+ if(mat->pr_type==MA_CUBE) {
+
+ eul[0]= (297)*M_PI/180.0;
+ eul[1]= 0.0;
+ eul[2]= (45)*M_PI/180.0;
+ EulToMat3(eul, tmat);
+
+ MTC_Mat3MulVecfl(tmat, R.lo);
+ MTC_Mat3MulVecfl(tmat, R.vn);
+ /* hack for cubemap, why!!! */
+ SWAP(float, R.vn[0], R.vn[1]);
+ }
+
+ if(mat->texco & TEXCO_GLOB) {
+ VECCOPY(R.gl, R.lo);
+ }
+ if(mat->texco & TEXCO_WINDOW) {
+ VECCOPY(R.winco, R.lo);
+ }
+ if(mat->texco & TEXCO_STICKY) {
+ VECCOPY(R.sticky, R.lo);
+ }
+ if(mat->texco & TEXCO_UV) {
+ VECCOPY(R.uv, R.lo);
+ }
+ if(mat->texco & TEXCO_OBJECT) {
+ VECCOPY(R.co, R.lo);
+ }
+ if(mat->texco & TEXCO_NORM) {
+ R.orn[0]= R.vn[0];
+ R.orn[1]= -R.vn[1];
+ R.orn[2]= R.vn[2];
+ }
+ if(mat->texco & TEXCO_REFL) {
+ /* for bump texture */
+ VECCOPY(R.view, view);
+
+ inp= -2.0*(R.vn[0]*view[0]+R.vn[1]*view[1]+R.vn[2]*view[2]);
+ R.ref[0]= (view[0]+inp*R.vn[0]);
+ R.ref[1]= -(view[1]+inp*R.vn[1]);
+ R.ref[2]= (view[2]+inp*R.vn[2]);
+ }
+
+ do_material_tex();
+
+ if(mat->pr_type==MA_CUBE) {
+ /* rotate normal back for normals texture */
+ SWAP(float, R.vn[0], R.vn[1]);
+ MTC_Mat3Inv(imat, tmat);
+ MTC_Mat3MulVecfl(imat, R.vn);
+ }
+
+ }
+
+ if(mat->mode & MA_SHLESS) {
+ temp= 255.0*(mat->r);
+ if(temp>255) rect[0]= 255; else if(temp<0) rect[0]= 0; else rect[0]= temp;
+
+ temp= 255.0*(mat->g);
+ if(temp>255) rect[1]= 255; else if(temp<0) rect[1]= 0; else rect[1]= temp;
+
+ temp= 255.0*(mat->b);
+ if(temp>255) rect[2]= 255; else if(temp<0) rect[2]= 0; else rect[2]= temp;
+ }
+ else {
+
+ for(a=0; a<2; a++) {
+
+ if(a==0) la= pr1_lamp;
+ else la= pr2_lamp;
+
+ lv[0]= vec[0]-la[0];
+ lv[1]= vec[1]-la[1];
+ lv[2]= vec[2]-la[2];
+ Normalise(lv);
+
+ inp= R.vn[0]*lv[0]+R.vn[1]*lv[1]+R.vn[2]*lv[2];
+ if(inp<0.0) inp= 0.0;
+
+ if(mat->spec) {
+
+ lv[0]+= view[0];
+ lv[1]+= view[1];
+ lv[2]+= view[2];
+ Normalise(lv);
+
+ if(inp>0.0) {
+ v1= lv[0]*R.vn[0]+lv[1]*R.vn[1]+lv[2]*R.vn[2];
+ if(v1>0.0) {
+ v1= RE_Spec(v1, mat->har);
+ inprspec= v1*mat->spec;
+ isr+= inprspec*mat->specr;
+ isg+= inprspec*mat->specg;
+ isb+= inprspec*mat->specb;
+ }
+ }
+ }
+ inp= (mat->ref*inp + mat->emit);
+
+ if(a==0) la= pr1_col;
+ else la= pr2_col;
+
+ ir+= inp*la[0];
+ ig+= inp*la[1];
+ ib+= inp*la[2];
+ }
+
+ if(R.refcol[0]==0.0) {
+ a= 255.0*( mat->r*ir +mat->ambr +isr);
+ if(a>255) a=255; else if(a<0) a= 0;
+ rect[0]= a;
+ a= 255.0*(mat->g*ig +mat->ambg +isg);
+ if(a>255) a=255; else if(a<0) a= 0;
+ rect[1]= a;
+ a= 255*(mat->b*ib +mat->ambb +isb);
+ if(a>255) a=255; else if(a<0) a= 0;
+ rect[2]= a;
+ }
+ else {
+ a= 255.0*( mat->mirr*R.refcol[1] + (1.0 - mat->mirr*R.refcol[0])*(mat->r*ir +mat->ambr) +isr);
+ if(a>255) a=255; else if(a<0) a= 0;
+ rect[0]= a;
+ a= 255.0*( mat->mirg*R.refcol[2] + (1.0 - mat->mirg*R.refcol[0])*(mat->g*ig +mat->ambg) +isg);
+ if(a>255) a=255; else if(a<0) a= 0;
+ rect[1]= a;
+ a= 255.0*( mat->mirb*R.refcol[3] + (1.0 - mat->mirb*R.refcol[0])*(mat->b*ib +mat->ambb) +isb);
+ if(a>255) a=255; else if(a<0) a= 0;
+ rect[2]= a;
+ }
+ }
+
+ if(mat->alpha!=1.0) {
+
+ alpha= mat->alpha;
+
+ /* ztra shade */
+ if(mat->spectra!=0.0) {
+ inp= mat->spectra*inprspec;
+ if(inp>1.0) inp= 1.0;
+
+ alpha= (1.0-inp)*alpha+ inp;
+ }
+
+ tracol= previewback(mat->pr_back, x, y) & 255;
+
+ tracol= (1.0-alpha)*tracol;
+
+ rect[0]= tracol+ (rect[0]*alpha) ;
+ rect[1]= tracol+ (rect[1]*alpha) ;
+ rect[2]= tracol+ (rect[2]*alpha) ;
+
+ }
+}
+
+
+void BIF_previewrender(SpaceButs *sbuts)
+{
+ Material *mat=0;
+ Tex *tex = NULL;
+ Image *ima;
+ Lamp *la;
+ LampRen *lar = NULL;
+ HaloRen har;
+ Object *ob;
+ World *wrld;
+ float lens = 0.0, vec[3];
+ int x, y, starty, startx, endy, endx, radsq, xsq, ysq, last = 0;
+ unsigned int *rect;
+
+ if(sbuts->cury>=PR_RECTY) return;
+
+ if ELEM4(sbuts->mainb, BUTS_MAT, BUTS_TEX, BUTS_LAMP, BUTS_WORLD);
+ else return;
+
+ har.flarec= 0; /* verderop test op postrender flare */
+
+ if(qtest()) {
+ addafterqueue(curarea->win, RENDERPREVIEW, 1);
+ return;
+ }
+
+ MTC_Mat4One(R.viewmat);
+ MTC_Mat4One(R.viewinv);
+
+ R.osatex= 0;
+ if(sbuts->mainb==BUTS_MAT) {
+ mat= sbuts->lockpoin;
+ if(mat==0) return;
+
+ /* rendervars */
+ init_render_world();
+ init_render_material(mat);
+
+ /* clear imats */
+ for(x=0; x<8; x++) {
+ if(mat->mtex[x]) {
+ if(mat->mtex[x]->tex) {
+ init_render_texture(mat->mtex[x]->tex);
+
+ if(mat->mtex[x]->tex->env && mat->mtex[x]->tex->env->object)
+ MTC_Mat4One(mat->mtex[x]->tex->env->object->imat);
+ }
+ if(mat->mtex[x]->object) MTC_Mat4One(mat->mtex[x]->object->imat);
+ if(mat->mtex[x]->object) MTC_Mat4One(mat->mtex[x]->object->imat);
+ }
+ }
+ R.vlr= 0;
+ R.mat= mat;
+ R.matren= mat->ren;
+
+ if(mat->mode & MA_HALO) init_previewhalo(&har, mat);
+ }
+ else if(sbuts->mainb==BUTS_TEX) {
+ tex= sbuts->lockpoin;
+ if(tex==0) return;
+ ima= tex->ima;
+ if(ima) last= ima->lastframe;
+ init_render_texture(tex);
+ free_unused_animimages();
+ if(tex->ima) {
+ if(tex->ima!=ima) allqueue(REDRAWBUTSTEX, 0);
+ else if(last!=ima->lastframe) allqueue(REDRAWBUTSTEX, 0);
+ }
+ if(tex->env && tex->env->object)
+ MTC_Mat4Invert(tex->env->object->imat, tex->env->object->obmat);
+ }
+ else if(sbuts->mainb==BUTS_LAMP) {
+ ob= ((G.scene->basact)? (G.scene->basact)->object: 0);
+ if(ob==0 || ob->type!=OB_LAMP) return;
+ la= ob->data;
+ init_render_world();
+ init_render_textures(); /* ze mogen niet twee keer!! (brightness) */
+ R.totlamp= 0;
+ RE_add_render_lamp(ob, 0); /* 0=no shadbuf */
+ lar= R.la[0];
+
+ /* uitzonderingen: */
+ lar->spottexfac= 1.0;
+ lar->spotsi= cos( M_PI/3.0 );
+ lar->spotbl= (1.0-lar->spotsi)*la->spotblend;
+
+ MTC_Mat3One(lar->imat);
+ }
+ else {
+ wrld= sbuts->lockpoin;
+ if(wrld==0) return;
+
+ lens= 35.0;
+ if(G.scene->camera) {
+ lens= ( (Camera *)G.scene->camera->data)->lens;
+ }
+
+ init_render_world();
+ init_render_textures(); /* dont do it twice!! (brightness) */
+ }
+
+ set_previewrect(sbuts->area->win, PR_XMIN, PR_YMIN, PR_XMAX, PR_YMAX);
+
+ if(sbuts->rect==0) {
+ sbuts->rect= MEM_callocN(sizeof(int)*PR_RECTX*PR_RECTY, "butsrect");
+
+ /* built in emboss */
+ rect= sbuts->rect;
+ for(y=0; y<PR_RECTY; y++, rect++) *rect= 0xFFFFFFFF;
+
+ rect= sbuts->rect + PR_RECTX-1;
+ for(y=0; y<PR_RECTY; y++, rect+=PR_RECTX) *rect= 0xFFFFFFFF;
+ }
+
+ starty= -PR_RECTY/2;
+ endy= starty+PR_RECTY;
+ starty+= sbuts->cury;
+
+ /* offset +1 for emboss */
+ startx= -PR_RECTX/2 +1;
+ endx= startx+PR_RECTX -2;
+
+ radsq= (PR_RECTX/2)*(PR_RECTY/2);
+
+ glDrawBuffer(GL_FRONT);
+
+ if(mat) {
+ if(mat->pr_type==MA_SPHERE) {
+ pr1_lamp[0]= 2.3; pr1_lamp[1]= -2.4; pr1_lamp[2]= -4.6;
+ pr2_lamp[0]= -8.8; pr2_lamp[1]= -5.6; pr2_lamp[2]= -1.5;
+ }
+ else {
+ pr1_lamp[0]= 1.9; pr1_lamp[1]= 3.1; pr1_lamp[2]= -8.5;
+ pr2_lamp[0]= 1.2; pr2_lamp[1]= -18; pr2_lamp[2]= 3.2;
+ }
+ }
+
+ for(y=starty; y<endy; y++) {
+
+ rect= sbuts->rect + 1 + PR_RECTX*sbuts->cury;
+
+ if(y== -PR_RECTY/2 || y==endy-1); /* emboss */
+ else if(sbuts->mainb==BUTS_MAT) {
+
+ if(mat->mode & MA_HALO) {
+ for(x=startx; x<endx; x++, rect++) {
+ rect[0]= previewback(mat->pr_back, x, y);
+ }
+
+ if(har.flarec) {
+ if(y==endy-2) previewflare(sbuts, &har, sbuts->rect);
+ }
+ else {
+ halo_preview_pixel(&har, startx, endx, y, (char *) (rect-PR_RECTX));
+ }
+ }
+ else {
+ ysq= y*y;
+ for(x=startx; x<endx; x++, rect++) {
+ xsq= x*x;
+ if(mat->pr_type==MA_SPHERE) {
+
+ if(xsq+ysq < radsq) {
+ R.vn[0]= x;
+ R.vn[1]= y;
+ R.vn[2]= sqrt( (float)(radsq-xsq-ysq) );
+ Normalise(R.vn);
+
+ vec[0]= R.vn[0];
+ vec[1]= R.vn[2];
+ vec[2]= -R.vn[1];
+
+ shade_preview_pixel(vec, x, y, (char *)rect, 1);
+ }
+ else {
+ rect[0]= previewback(mat->pr_back, x, y);
+ }
+ }
+ else if(mat->pr_type==MA_CUBE) {
+ if( ray_previewrender(x, y, vec) ) {
+
+ shade_preview_pixel(vec, x, y, (char *)rect, 0);
+ }
+ else {
+ rect[0]= previewback(mat->pr_back, x, y);
+ }
+ }
+ else {
+ vec[0]= x*(2.0/PR_RECTX);
+ vec[1]= y*(2.0/PR_RECTX);
+ vec[2]= 0.0;
+
+ R.vn[0]= R.vn[1]= 0.0;
+ R.vn[2]= 1.0;
+
+ shade_preview_pixel(vec, x, y, (char *)rect, 0);
+ }
+ }
+ }
+ }
+ else if(sbuts->mainb==BUTS_TEX) {
+ for(x=startx; x<endx; x++, rect++) {
+ texture_preview_pixel(tex, x, y, (char *)rect);
+ }
+ }
+ else if(sbuts->mainb==BUTS_LAMP) {
+ for(x=startx; x<endx; x++, rect++) {
+ lamp_preview_pixel(lar, x, y, (char *)rect);
+ }
+ }
+ else {
+ for(x=startx; x<endx; x++, rect++) {
+ sky_preview_pixel(lens, x, y, (char *)rect);
+ }
+ }
+
+ if(y<endy-2) {
+
+ if(qtest()) {
+ addafterqueue(curarea->win, RENDERPREVIEW, 1);
+ break;
+ }
+ }
+
+ display_pr_scanline(sbuts->rect, sbuts->cury);
+
+ sbuts->cury++;
+ }
+
+ if(sbuts->cury>=PR_RECTY && sbuts->mainb==BUTS_TEX)
+ draw_tex_crop(sbuts->lockpoin);
+
+ glDrawBuffer(GL_BACK);
+ BIF_previewdraw(sbuts);
+
+ if(sbuts->mainb==BUTS_MAT) {
+ end_render_material(mat);
+ for(x=0; x<8; x++) {
+ if(mat->mtex[x] && mat->mtex[x]->tex) end_render_texture(mat->mtex[x]->tex);
+ }
+ }
+ else if(sbuts->mainb==BUTS_TEX) {
+ end_render_texture(tex);
+ }
+ else if(sbuts->mainb==BUTS_WORLD) {
+ end_render_textures();
+ }
+ else if(sbuts->mainb==BUTS_LAMP) {
+ if(R.totlamp) {
+ if(R.la[0]->org) MEM_freeN(R.la[0]->org);
+ MEM_freeN(R.la[0]);
+ }
+ R.totlamp= 0;
+ end_render_textures();
+ }
+}
+
diff --git a/source/blender/src/pub/license_key.c b/source/blender/src/pub/license_key.c
new file mode 100644
index 00000000000..fb6402cbaeb
--- /dev/null
+++ b/source/blender/src/pub/license_key.c
@@ -0,0 +1,451 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "license_key.h"
+#include "keyed_functions.h"
+#include "BKE_utildefines.h"
+#include "BIF_screen.h" // splash
+#include "BIF_toolbox.h"
+#include "blenkey.h"
+#include <stdio.h>
+#include <string.h>
+
+#include "BLI_blenlib.h"
+
+#include "BLO_readfile.h"
+#include "BLO_keyStore.h"
+
+int LICENSE_KEY_VALID = FALSE;
+int I_AM_PUBLISHER = TRUE;
+
+static UserStruct User;
+
+// Python stuff
+
+#include "Python.h"
+#include "marshal.h"
+#include "compile.h" /* to give us PyCodeObject */
+#include "eval.h" /* prototype for PyEval_EvalCode */
+
+#include "BPY_extern.h"
+
+#include "IMB_imbuf.h"
+
+Fptr g_functab[PYKEY_TABLEN];
+Fptr g_ptrtab[PYKEY_TABLEN];
+
+static int g_seed[3] = PYKEY_SEED;
+static PyObject *g_module_self;
+static PyObject *g_main;
+
+
+// end Python stuff
+
+// **************** PYTHON STUFF **************************
+/* ----------------------------------------------------- */
+/* this is the dummy functions to demonstrate */
+
+int sticky_shoes(void *vp)
+{
+ return 0;
+}
+
+/*
+int key_func1(void *vp) {
+ printf("function 1 called\n");
+}
+
+*/
+int key_return_true(void *vp) {
+ return 1;
+}
+
+
+/* ----------------------------------------------------- */
+
+/* Declarations for objects of type Fplist */
+
+
+static char prot_getseed__doc__[] = "";
+
+static PyObject *
+prot_getseed(self, args)
+ PyObject *self; /* Not used */
+ PyObject *args;
+{
+ PyObject *p;
+ p = PyTuple_New(3);
+ PyTuple_SetItem(p, 0, PyInt_FromLong(g_seed[0]));
+ PyTuple_SetItem(p, 1, PyInt_FromLong(g_seed[1]));
+ PyTuple_SetItem(p, 2, PyInt_FromLong(g_seed[2]));
+ return p;
+}
+
+static char prot_getlen__doc__[] = "";
+static PyObject *
+prot_getlen(self, args)
+ PyObject *self; /* Not used */
+ PyObject *args;
+{
+ return Py_BuildValue("i", PYKEY_TABLEN);
+}
+
+static char prot_getptr__doc__[] =
+""
+;
+
+static PyObject *
+prot_getptr(self, args)
+ PyObject *self; /* Not used */
+ PyObject *args;
+{
+ PyObject *p;
+ Fptr f;
+ int index;
+ /* we don't catch errors here, we're in the key code */
+ if (!g_functab)
+ return NULL;
+ if (!PyArg_ParseTuple(args, "i", &index))
+ return NULL;
+ if (index >= PYKEY_TABLEN)
+ return NULL;
+
+ f = g_functab[index];
+ p = PyCObject_FromVoidPtr(f , NULL);
+ return p;
+}
+
+static char prot_setptr__doc__[] =
+""
+;
+static PyObject *
+prot_setptr(self, args)
+ PyObject *self; /* Not used */
+ PyObject *args;
+{
+ PyObject *p;
+
+ int index;
+
+ if (!g_ptrtab)
+ return NULL;
+ if (!PyArg_ParseTuple(args, "iO", &index, &p))
+ return NULL;
+ if (index >= PYKEY_TABLEN)
+ return NULL;
+ if (!PyCObject_Check(p)) {
+ return NULL;
+ }
+
+ g_ptrtab[index] = PyCObject_AsVoidPtr(p);
+ return Py_BuildValue("i", 1);
+}
+
+static PyObject *callkeycode(
+ unsigned char *keycode,
+ int keycodelen)
+{
+ PyCodeObject *code;
+ PyObject *maindict = PyModule_GetDict(g_main);
+
+ code = (PyCodeObject *) PyMarshal_ReadObjectFromString(keycode, keycodelen);
+ if (!PyEval_EvalCode(code, maindict, maindict))
+ return NULL;
+ return Py_BuildValue("i", 1);
+}
+
+
+
+/* List of methods defined in the module */
+
+static struct PyMethodDef prot_methods[] = {
+ {"getlen", (PyCFunction)prot_getlen, METH_VARARGS, prot_getlen__doc__},
+ {"getseed", (PyCFunction)prot_getseed, METH_VARARGS, prot_getseed__doc__},
+ {"getptr", (PyCFunction)prot_getptr, METH_VARARGS, prot_getptr__doc__},
+ {"setptr", (PyCFunction)prot_setptr, METH_VARARGS, prot_setptr__doc__},
+
+ {NULL, (PyCFunction)NULL, 0, NULL} /* sentinel */
+};
+
+
+/* Initialization function for the module (*must* be called initprot) */
+
+static char prot_module_documentation[] = "No Documentation";
+
+static void init_ftable(void) // initializes functiontable
+{
+ int i;
+
+ g_functab[0] = &key_func1;
+ g_functab[1] = &key_func2;
+ g_functab[2] = &key_func3;
+/* add more key_funcs here */
+
+ for (i = 3; i < PYKEY_TABLEN; i++)
+ {
+ g_functab[i] = &sticky_shoes;
+ }
+}
+
+
+static void init_ptable(void) // initializes functiontable
+{
+ int i;
+
+ for (i = 0; i < PYKEY_TABLEN; i++)
+ {
+ g_ptrtab[i] = &sticky_shoes;
+ }
+}
+
+
+static void insertname(PyObject *m,PyObject *p, char *name)
+{
+ PyObject *d = PyModule_GetDict(m);
+
+ PyDict_SetItemString(d, name, p);
+ Py_DECREF(p);
+}
+
+/* initialisation */
+static void initprot()
+{
+ PyObject *m, *d;
+ PyObject *capi1;
+ PyObject *ErrorObject;
+
+ init_ftable();
+
+ g_main = PyImport_AddModule("__main__");
+
+ m = Py_InitModule4("prot", prot_methods,
+ prot_module_documentation,
+ (PyObject*)NULL,PYTHON_API_VERSION);
+ g_module_self = m;
+ d = PyModule_GetDict(m);
+ ErrorObject = PyString_FromString("prot.error");
+ PyDict_SetItemString(d, "error", ErrorObject);
+
+ /* add global object */
+
+ capi1 = PyCObject_FromVoidPtr((void *)g_functab , NULL);
+ if (capi1) {
+ insertname(m, capi1, "APIfunctab");
+ }
+
+ /* Check for errors */
+ if (PyErr_Occurred())
+ Py_FatalError("can't initialize module prot");
+
+ init_ptable();
+}
+
+// ******************************* KEY STUFF *********************
+
+static void create_key_name(char * keyname)
+{
+ sprintf(keyname, "%s/.BPkey", BLI_gethome());
+}
+
+void checkhome()
+{
+ int keyresult;
+ char *HexPriv, *HexPub, *HexPython;
+ byte *Byte;
+ char keyname[FILE_MAXDIR + FILE_MAXFILE];
+ int wasInitialized;
+ unsigned char *keycode = NULL;
+ int keycodelen = 0;
+
+ create_key_name(keyname);
+ keyresult = ReadKeyFile(keyname, &User, &HexPriv, &HexPub,
+ &Byte, &HexPython);
+ if (keyresult != 0) {
+ // printf("\nReadKeyFile error %d\n", keyresult);
+ } else {
+ // printf("\nReadKeyFile OK\n");
+ LICENSE_KEY_VALID = TRUE;
+
+ wasInitialized = Py_IsInitialized();
+
+ // make it failsafe if python interpreter was already initialized
+ if (wasInitialized)
+ Py_Initialize();
+
+ initprot(); // initialize module and function tables
+ // get python byte code
+ keycode = DeHexify(HexPython);
+ keycodelen = strlen(HexPython) / 2;
+
+ callkeycode(keycode, keycodelen);
+
+ Py_Finalize();
+
+ if (wasInitialized) // if we were initialized,
+ BPY_start_python(); // restart creator python
+
+ //some debugging stuff
+ // print_ptable();
+
+ // Store key stuff for use by stream
+ keyStoreConstructor(
+ &User,
+ HexPriv,
+ HexPub,
+ Byte,
+ HexPython);
+
+ // other initialization code
+
+ // enable png writing in the ImBuf library
+ IMB_fp_png_encode = IMB_png_encode;
+ }
+}
+
+void SHOW_LICENSE_KEY(void)
+{
+ extern int datatoc_tonize;
+ extern char datatoc_ton[];
+ char string[1024];
+ int maxtype, type;
+ char *typestrings[] = {
+ "",
+ "Individual",
+ "Company",
+ "Unlimited",
+ "Educational"};
+
+ maxtype = (sizeof(typestrings) / sizeof(char *)) - 1;
+ type = User.keytype;
+ if (type > maxtype) {
+ type = 0;
+ }
+
+ if (LICENSE_KEY_VALID) {
+ sprintf(string, "%s License registered to: %s (%s)", typestrings[type], User.name, User.email);
+ splash((void *)datatoc_ton, datatoc_tonize, string);
+ }
+}
+
+void loadKeyboard(char * name)
+{
+ char keyname[FILE_MAXDIR + FILE_MAXFILE];
+ FILE *in, *out;
+ char string[1024], *match = 0;
+ int i, c;
+ int found = 0;
+
+ // make sure we don't overwrite a valid key...
+
+ if (!LICENSE_KEY_VALID) {
+ in = fopen(name, "rb");
+ if (in) {
+ // scan for blender key magic, read strings
+ // with anything but a newline
+ while (fscanf(in, "%1000[^\n\r]", string) != EOF) {
+ match = strstr(string, BLENKEYMAGIC);
+ if (match) {
+ break;
+ }
+ fscanf(in, "\n");
+ }
+
+ if (match) {
+ // found blender key magic, open output file
+ // to copy key information
+
+ create_key_name(keyname);
+ out = fopen(keyname, "wb");
+ if (out) {
+ // printout first line
+ fprintf(out, "%s", match);
+ for (i = 0; i < 350; i++) {
+ // handle control characters (\n\r)
+ while (1) {
+ c = getc(in);
+ if (c == '\n') {
+ // output a \n for each \n in the input
+ fprintf(out, "\n");
+ } else if (c == EOF) {
+ break;
+ } else if (c < ' ') {
+ // skip control characters
+ } else {
+ ungetc(c, in);
+ break;
+ }
+ }
+
+ if (fscanf(in, "%1000[^\n\r]", string) != EOF) {
+ if (strcmp(string, BLENKEYSEPERATOR) == 0) {
+ found++;
+ }
+ fprintf(out, "%s", string);
+ } else {
+ break;
+ }
+
+ if (found >= 2) {
+ break;
+ }
+ }
+
+ fclose(out);
+
+ checkhome();
+ if (LICENSE_KEY_VALID) {
+ SHOW_LICENSE_KEY();
+ } else {
+ error("Not a valid license key ! Removing installed key.");
+ BLI_delete(keyname, 0, 0);
+ }
+
+ } else {
+ error("Can't install key");
+ }
+ } else {
+ error("File doesn't contain a valid key: %s", name);
+ }
+
+ fclose(in);
+
+ if (LICENSE_KEY_VALID) {
+ if (okee("Remove input file: '%s'?", name)) {
+ BLI_delete(name, 0, 0);
+ }
+ }
+
+ } else {
+ error("File doesn't exist: %s", name);
+ }
+ }
+}
diff --git a/source/blender/src/pub/osx_publisher_splash.jpg.c b/source/blender/src/pub/osx_publisher_splash.jpg.c
new file mode 100644
index 00000000000..3ac6b870d18
--- /dev/null
+++ b/source/blender/src/pub/osx_publisher_splash.jpg.c
@@ -0,0 +1,984 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+/* DataToC output of file <splash_jpg> */
+#ifdef __APPLE__
+
+int datatoc_tonize= 30248;
+char datatoc_ton[]= {
+255,216,255,224, 0, 16, 74, 70,
+ 73, 70, 0, 1, 2, 0, 0,100, 0,100, 0, 0,255,236, 0, 17, 68,117, 99,107,121, 0, 1, 0, 4, 0, 0, 0, 50, 0, 0,255,
+238, 0, 14, 65,100,111, 98,101, 0,100,192, 0, 0, 0, 1,255,219, 0,132, 0, 8, 6, 6, 6, 6, 6, 8, 6, 6, 8, 12, 8,
+ 7, 8, 12, 14, 10, 8, 8, 10, 14, 16, 13, 13, 14, 13, 13, 16, 17, 12, 14, 13, 13, 14, 12, 17, 15, 18, 19, 20, 19, 18, 15, 24,
+ 24, 26, 26, 24, 24, 35, 34, 34, 34, 35, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 1, 9, 8, 8, 9, 10, 9, 11, 9, 9, 11, 14,
+ 11, 13, 11, 14, 17, 14, 14, 14, 14, 17, 19, 13, 13, 14, 13, 13, 19, 24, 17, 15, 15, 15, 15, 17, 24, 22, 23, 20, 20, 20, 23, 22,
+ 26, 26, 24, 24, 26, 26, 33, 33, 32, 33, 33, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,255,192, 0, 17, 8, 1, 15, 1,244, 3, 1,
+ 34, 0, 2, 17, 1, 3, 17, 1,255,196, 0,194, 0, 0, 1, 5, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 2,
+ 4, 5, 6, 0, 7, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 16,
+ 0, 2, 1, 3, 2, 4, 3, 4, 5, 6, 10, 6, 7, 6, 2, 11, 1, 2, 3, 0, 17, 4, 18, 5, 33, 49, 19, 6, 65, 81, 20, 97,
+113, 34, 50,129,145,209, 21, 7,161,225, 66, 82,146, 35,177,193, 98,114,130,178, 51, 67, 36, 22,240,210, 83, 99,115,131,162,179,
+195, 52, 84,116, 54,147,163,211,196, 37, 23,241, 53,194,226, 68,100,132,148,164, 69,133, 38, 71, 17, 0, 2, 1, 3, 2, 4, 3,
+ 6, 4, 6, 3, 1, 0, 0, 0, 0, 0, 1, 2, 17, 3, 4, 33, 18, 49, 65, 81, 5, 97,113, 19,129,145,161,209, 34, 50,177,193,
+ 66,146,240,225, 82,114, 51, 20, 98,147, 21, 52,255,218, 0, 12, 3, 1, 0, 2, 17, 3, 17, 0, 63, 0,244,254,224,238, 9, 59,
+127,111,143, 51, 67,204,154, 98, 78,154,190,139, 94, 48,111,227, 84,189,187,248,157,181,111,121,203,182, 74,211, 97,102,202,116,
+192,147, 54,164,144,254,170, 72,167,230,246, 16, 42,195,187, 50, 59,119, 27,111,129,187,154, 24,230,194, 99, 18,162, 76,130, 69,
+234,116,174, 13,155,135, 32,107,198, 59,154, 93,139,117,238, 13,167, 19,177, 96, 16,100, 52,145,170, 24, 87, 66, 9,117,130,140,
+ 20,114,211,109, 71,221,122, 3,232,137, 38,156, 48,180,141,107,126,177,166, 28,153,129,254,209,255, 0,104,215, 73,123,143, 59,
+ 80,154,246,185,161, 3,122,137,173,113, 35,126,209,166, 25,242, 9,183, 85,199,244,143,219, 76, 91,218,246,227, 78, 3,243,208,
+ 4, 19, 79,200,202,255, 0,180,126,218, 78,164,222, 19, 73,251, 70,147,133,119, 1, 64, 41,151, 35,152,149,255, 0,104,211,125,
+ 70, 77,175,213,111,218, 53,220,111,127, 10,105,225,238,160, 7,145,149,148,161, 71, 85,214,230,247, 12,104, 77,153,149,107, 9,
+228,191,243,219,237,166,101,177, 50, 42,223,128, 23, 31, 73,252,212, 11,240,189, 70, 80,227, 47, 44,243,200,147,246,219,237,167,
+122,188,171,127,111, 39,237,183,219, 64, 91,145, 97, 75,167,206,128,120,204,204, 60,167,147,246,219,237,167, 12,172,195,195,212,
+ 73,251,109,246,208,208, 0,107,181, 11,147, 64, 72, 25, 57, 64, 15,223,201,251,109,246,215, 54, 94, 72,254,254, 79,218, 63,109,
+ 71, 45,123, 90,184,113,226,104, 9, 17,230,207,168,234,157,199,149,216,253,180, 81,149, 59,114,157,173,231,172,253,180, 56, 87,
+224, 36,128, 69,207,217, 93,211,136,146,116, 14, 28,207, 10,128, 41,202,200, 80, 15, 81,200,243,212,126,218,112,202,159,198, 87,
+246,124, 71,237,168,161, 16,155, 13, 69, 77,200,181,236, 45,238,165, 88,152, 92, 6, 63, 79,149, 1, 32,100,228, 17,126,179,241,
+240,212,126,218,239, 81,147,199,247,175,251, 71,237,168,218, 92, 88,171, 2, 7,178,156, 76,136,191, 18,131,238, 60,120,253, 20,
+ 1,253, 68,246,254,217,255, 0,104,253,180, 23,201,200, 75, 19, 60,159,182,199,248,233,133,207, 61, 36,123,105,132,135,176, 2,
+214,231,194,168, 10,115, 50, 45,168, 78,224, 90,228,234,111,182,163, 54,118, 99,177, 34,121, 64,240, 1,219,237,164,200, 4, 21,
+ 31,162,105,168,182, 5,155,128,231,127, 33, 84, 6,245,153,104,183,108,137, 15,144,214,220, 79,215, 77,245,185,171,243,100, 72,
+ 73,226,126, 54,176,252,180, 3, 32, 44, 9,229,201, 5, 53,195, 49,184, 54, 30,116, 1,142,102,104, 55, 57, 82,129,228, 29,190,
+218,112,206,203, 97,117,200,151,246,219,237,168,227, 73, 22, 63, 21,169, 1, 55,176, 22, 20, 1,198,102,117,254, 44,153, 7,244,
+219,237,164,245,249,136,226,249, 50,144,124, 53,183,219, 64,144, 1,196,154,116, 49,235, 58,156,112,160, 38,122,252,163,192, 79,
+ 33,191,242,219,237,161,250,172,245,185,108,137,120,242, 29, 70,251,107,128, 0,220, 10, 70, 26,143,186,128,107,102,231,248, 79,
+ 47,237,183,219, 74, 50,183, 6, 23,245, 18,175,244,219,237,174, 0, 6,231,244, 83, 76,161,156,170,142, 2,128, 42,207,153,194,
+249, 51, 31,249,140, 7,240,211,219, 59, 34, 62, 7, 34, 75,255, 0, 61,190,218,134,229,239,197,172, 41, 27, 79,205,107,154, 2,
+ 75,103,102, 91,225,158, 67,127,229,183,219, 76, 57,249,129,108,114, 36,213,236,118,251,104, 58,137, 94, 60, 9,166,132, 0,223,
+153,160, 12,185,153,195,137,201,151,233,145,190,218, 47,222, 25, 96, 91,175, 33, 62,101,219,237,168,213,214,169, 82,208, 55,174,
+205, 63,254,209, 47,237,183,219, 93,235,115,127,241, 50,254,219,125,180, 27,249, 82,113,160, 36,122,220,207,252, 76,191,182,223,
+109,119,173,205,255, 0,196, 75,251,109,246,208, 86, 54,111,149, 73,183, 59, 10, 39,167,113,243, 89,125,164,143,226,161, 71,122,
+204,223,252, 76,191,182,223,109, 47,172,204,255, 0,196, 75,251,109,246,210, 8,163, 28,216,183,157,135,241,154,112, 69, 81,112,
+156,127,148,105, 66, 85, 29,235, 51,127,241, 18,254,219,125,180,245,159,112, 99, 97, 52,191, 75,176,254, 19, 72, 11, 95,225, 54,
+229,125, 34,212,225, 30,175, 18,124,239, 65, 81,226,108,176,108,249,110, 60,192,118, 39,248,104,131, 38, 64, 1,235,206,231,159,
+206, 64, 63,195, 65, 17,252, 69, 72,246,222,140, 34,186,240,229,200,251,104, 7,122,236,149, 33, 81,216, 92,254,147, 51,127, 88,
+210, 54, 70, 91, 30, 51, 72, 61,204, 64,225,238,174,110,130, 47,198,203,123,249,211, 37,202,198, 69, 80, 9, 32, 15, 1,206,132,
+ 28, 50, 50, 72,184,158, 78, 95,172,220,254,186,119, 91, 50,246,234,201,110, 23, 58,155,237,168, 79,185,160,225, 28, 95, 73, 52,
+207, 95, 49,227, 97,111, 42,165, 44,203,229, 90,226,121, 7,244,207,219, 72,114,164,140,141, 89, 45,244,185, 63,199, 84,178, 77,
+ 51,219, 83,147,127,109, 36, 80,179,184, 30,116, 20, 46,206,112,177,182, 76,135,197,136, 44,108, 63,138,152,219,178,168,225, 52,
+140,109,107,220,143,227,170,239, 78,121,120,248,208,229,132,139, 0, 57,208, 23, 31,120, 47, 71,171,169,245,116, 53,107,185,189,
+186,250, 57,243,174,168, 90, 63,194,219,255, 0,221,109,255, 0,245, 85,213, 6,165,111,122,246,183,249,183,108,199,219,189, 89,
+195,233, 52, 83,245, 4,125, 75,218, 34,154,109,169, 63, 91,206,151,181,251, 27, 97,237,116, 73,112,177,196,155,135, 77, 82,108,
+233, 53, 52,140, 64,179,148, 14,205,211, 12,120,144,181,162,110, 38, 63,230, 71,253, 69,162,142, 21, 72, 6, 69, 32,142, 62, 20,
+195,115,225,123, 81, 38, 35, 80,247, 80,195, 80,130,130,121, 82, 43, 53,205,249, 82,130, 43,141,185, 94,128,112, 53,196,210,112,
+ 3,141,117,197, 0,161,131, 2, 7,133, 49,173,202,150,246,240,166,144,111, 64, 65,152,106,153,128, 62,207,168, 82, 5, 23,174,
+ 45,119, 45,231,198,146,231,235,168, 80,151, 0,211, 11, 19, 92, 57,210,159, 10, 3,128, 53,196,112,174,213,225, 72,110, 77, 1,
+204, 85, 1, 39,128, 3,141, 82,201,190,203,175,247, 49,174,129,203, 85,201, 63, 81, 21,119,160, 16,111,198,168,243,246,134,143,
+ 84,248,163, 82,115,104,252, 71,187,217, 95, 63,185, 60,165,110, 50,198,109, 40,213,206,159,119,135,176,247, 96, 44,103, 55, 28,
+133, 87, 42, 40,215,237, 46,182,205,215, 23, 42, 49, 25,248, 38, 23, 44,135,141,255, 0,155,106,150, 36,140,220,220, 3,237,225,
+ 88, 85,102, 70, 12,164,171, 14, 32,142, 4, 26,190,192,222, 68,133, 97,203, 32, 61,180,172,188,129,254,119,182,184, 97,119, 72,
+220,165,188,134,163, 46, 10, 92, 35, 47, 62,140,237,153,219, 92, 43,114,197,101, 30,113,231, 31, 46,168,186, 70,184, 26, 92, 0,
+ 77,207, 31, 15,101, 25, 91,143, 51,202,130, 35,213, 97,192,139,124, 38,154, 20, 88, 30, 2,198,220, 56,112, 62,234,250,199,203,
+ 15,240,147,192,241, 60,105, 36,253, 31, 2, 15, 31,162,185, 99, 28,195, 21, 83,196,241,189,190,138, 99, 33,189,217,201,246,144,
+ 60,104, 7, 49, 7,143, 42, 66, 1,185, 28,169,132, 75,126, 96,253, 20,229,224, 46,220,207, 58,168, 2,153, 75, 21,191, 27, 27,
+ 90,163,201, 32,115,167,244, 20,241, 62,102,151, 34,109,108, 85,121, 14, 23,160, 51, 1,109, 34,168, 30,250,143,202, 41, 7, 17,
+ 98,222,250, 64,206,203,107, 87, 44, 71,153, 63, 85, 0,154,213, 77,148,123,233, 88, 51,252,162,194,156, 20, 47, 31,225,165,214,
+164,216,113, 52, 3, 58, 55, 23, 38,244, 68, 54,250, 41,154,158,252,120, 10, 70, 11,243, 31,170,128, 61,238, 41, 7, 62, 60, 40,
+ 87, 37,120, 2, 13, 42,181,151,143, 58, 1,236,234, 27, 72,226, 79, 51, 67, 36,131, 97,240,138,226, 73, 62, 85,193, 25,185, 2,
+105, 82,208, 70, 33,188, 47, 75,198,138,176, 49,249,153, 87,222,126,203,211,214, 24,133,181, 51, 53,252, 20, 91,242,154,128,143,
+ 93,196,240, 28,106, 72, 69, 31, 42, 3,111, 22, 55,251, 5, 40, 12,120, 41,183,137, 0, 90,130,160, 4, 82, 31, 11,123,248,127,
+ 13, 57, 97, 95,210,112, 61,220, 77, 24, 37,252, 56,222,196,154, 32,136, 0,111,194,213, 69, 64,164,113, 15,209,102, 62,211, 96,
+127,142,136, 44,132,104,141, 86,198,230,227, 81, 31, 75, 94,156, 12, 42, 6,183, 23,246,154,107,102, 98,198, 44, 46,199,194,194,
+160, 28,194, 70,248,152,146,180,206,159,144,231,202,244,211,184, 6, 0, 36,124, 7,153,168,242,230,206,120, 11, 47,184, 85, 33,
+ 52, 66, 72,227,244,215, 63, 73, 5,221,199,182,230,171,195,205, 32,185, 98,126,154, 99, 70,197,172,124, 40, 90, 19,198, 70, 58,
+ 3, 99,127,112,166, 62,224, 22,193, 35,250,232, 49, 67,240,106,165,146, 13, 54,111, 14, 84, 2,122,201,218,228, 89,125,212, 57,
+ 37,157,254,103, 39,233,167,132, 8,183, 62, 60,106, 68, 81, 44,224, 42,216,120,147, 80,213, 52, 33, 36,108, 88,123,106, 79,166,
+ 63, 95, 26,146, 97, 24,247,103, 32,240,225,106,140, 50,174,252,184,114, 21, 76,145,204,118,225,110, 52,113, 30,149, 0,212,129,
+166,250,200,248,143, 16,106, 36,197,153,202,142, 66,161,165,166,161,132, 29, 75, 21,240,169, 9, 11, 64,110,220, 27,192,123, 40,
+ 56,108, 65,210,222, 21, 42,118, 38, 54, 96, 44,104, 70,234,234, 71,121,225, 67,164, 53,143,178,154,230, 55, 0, 6,189,255, 0,
+ 74,162,178, 0, 47,226,105,208,130, 47,229, 70, 35,199, 82,195,165,254, 23,230, 22,244,214,241,255, 0,196,222,186,159, 97,233,
+180,248,122,127,254, 98,186,161,189, 62, 36,145,243, 71,127, 8,227,254,162,209, 46, 41, 17,111,164,255, 0,187,143,250,139, 79,
+ 49, 3,225, 90, 57, 17,230,182,161,238,160, 26,145, 52, 87,111,162,130, 98, 54,161, 6,131, 75,171,198,144,194, 71,137,167, 8,
+184,115,160, 18,254, 55,174,213,227, 74, 33, 35,198,184,163, 91,133, 0,151, 52,174,196, 35, 16,120,128, 72,250,169, 44,195,194,
+133, 53,250,100,121,218,212, 4,113,192, 82, 18, 47,238,174,211,231, 74, 5, 66,137,198,160, 79,187,226, 68,250, 6,169, 72,230,
+ 86,214,250,205, 79,149,117,163, 32, 54, 44, 10,131,229,113, 89,151,219,179, 35, 98,166, 34,109,226,188, 69,124,254,225,145,147,
+105, 65, 99,193,189,213,172,146,221, 79, 3,221,131, 99, 30,235,151,175, 58, 82,148,141,118,215,196,179, 27,238, 56,254,233,255,
+ 0, 37, 47,223,184,255, 0,236,159,242, 85, 79,160,204,255, 0, 96,255, 0, 85,113,193,203, 0,147, 11, 0, 56,146, 71, 42,249,
+159,239,247, 31,233,127,245,255, 0, 35,232,127,165,129,253, 75,247,255, 0, 50,223,239,232, 45,253,147,254, 74, 65,191,194, 63,
+186,127,201, 84, 53,213,207,255, 0, 91, 47,250,151,237, 71, 79,252,204, 95,233,127,185,147, 51,103,196,200, 61, 72, 34,104,164,
+253, 46, 90, 79,183,223, 80,234, 70, 62, 14,102, 87,253,219, 30, 73, 71,154, 41, 35,235, 20,119,217,119,104,215, 83,225, 76, 7,
+152, 66,127,130,188,179, 87,110,183,119,211,122,234,220, 99, 72,252, 15, 76, 29,171, 73, 91,222,180,224,165, 42,191,136, 93,183,
+121,151, 12,136,166,188,144,114, 31,172,190,234,209, 69,149, 4,202,146, 70,225,144,241,189, 98,153, 89, 73, 86, 5, 88,112, 32,
+240, 34,164, 97,103, 79,131, 38,184,141,212,252,209,159,148,215,183, 11,185,206,205, 45,222,172,161,194,191,170, 63, 52,120,243,
+ 59,116, 46,214,229,170, 70,124,105,250,101,252,205,173,227, 63, 43, 94,244,209,107,241, 62,225,225, 64,194,204,198,220, 98,234,
+ 70, 62, 49,243,198,109,117, 52,116,138, 38,213,240,218,191, 67, 9,198,113, 83,131, 82,139,213, 52,124, 41,194, 80,147,132,211,
+139, 92, 83, 22,196,113, 6,161,207, 41,227, 26,159,231, 26,172,220, 59,183,183,182,173,209,182,172,249,228,199,153, 2,182,182,
+ 86, 49,217,198,161,197,117,126, 81, 82, 49,243, 48,243,213,167,193,200, 76,136, 75, 16, 36,141,131, 14, 30, 28, 60,107,175,167,
+ 52,148,156, 90, 79, 84,233,161,202, 55, 33, 38,227, 25, 38,215, 21, 93, 87,176, 32, 85, 60, 15, 26,119, 77, 23,141, 45,136,227,
+192, 10, 99, 16,199,216, 57, 84, 54, 43, 58,168,243,174, 44,197,126, 30, 30,116, 25,166,138, 4, 51, 78,235, 20,107,243, 72,228,
+ 42,139,240,230,106, 60,123,174,219, 43,136,161,205,130, 73, 28,217, 81,101, 70, 36,249, 0, 13,234,164,222,169, 50, 54,147,163,
+105, 18,197,185, 51, 92,215,113, 6,202,182, 30, 38,144, 15, 17,206,138,139,170,197,135,184, 84, 40,198, 1,173,196,251,133, 61,
+ 99,148,139, 4,183,191,243,209,213, 91,144,225,106,126,131,192,147,106, 2, 55, 68,254,147, 15,225,165, 17,160,246,209, 92,196,
+183, 37,133,169,157,120, 71, 43,181, 1,193, 64, 54, 3,221, 68, 8, 72,254, 26,143,234,238,223, 10,211,100,201,159,146,157, 62,
+234, 2,100,113,240,191, 46, 31, 69, 47,238, 87, 78,167, 23,247,213,113, 50,176, 55, 98,105,209, 66, 73,227,202,161, 89, 45,242,
+177,148,158,108,124, 0, 31,109, 48,230,142,104,156,124, 47, 64,146, 27, 17, 97,123,242,166, 79, 54, 46, 20, 70,108,201,146, 24,
+147,230,146, 70, 10,163,195,153,171,224,130,230,222,137,117, 9,234,242, 36, 54, 6,195,216, 41, 37, 51, 17,118, 98,106,159, 15,
+187,187,126,125,198, 29,179, 19, 32,228, 79, 49, 42,173, 26, 29, 0,128, 88,221,219, 79,128,240,171,230,116,144, 16, 13, 89,198,
+ 81,166,248,184,213, 87, 93, 12,194,112,157,118, 73, 74,142,154, 58,145, 17, 9, 38,158,208,144, 69,233,239,104,192,211,196,209,
+ 35,112,226,236,183,227, 89, 54,232,180, 27, 28, 74,169,199,196,240,174,150, 50, 91,128,191, 10,108,206,236,214, 6,192,113,181,
+ 57, 28,244,248,243,189, 24,138,171, 58,226, 37,210,121,209,149, 17,198,162,109,238,168,204,165,156,147,225, 70,140,232, 65,194,
+129,190, 67, 37,145,144,133, 94, 67,151,186,137, 20,140,235,115,225,194,212,217,149,175,123,115,229, 75, 26, 50,139, 91,223, 70,
+ 88,245, 99, 39, 5,136, 3,128, 52,236,123,161, 97,236,254, 58, 56,135,169,236, 35,145, 52, 97, 10, 34,128, 88, 22,183, 26, 34,
+ 73,213,129,158,230, 50, 7, 30, 21, 12, 38,162, 0,171, 5, 88,199, 6,107,147,194,154, 68, 41,193, 23,159,141, 8, 5,143,232,
+223,143, 42,227,142,230,238,162,224,249, 81,124,120, 47, 30,116,161,229,177,177,183,231,160,108, 72,211,164,166,252, 88,211,195,
+134, 91, 16, 61,198,153,165,175,241, 27, 92,218,245,221, 48,199, 77,239,115,206,173, 9, 80, 77,140, 9, 31,188, 91,120,220,242,
+162,136, 35, 84, 0, 74,183,241, 60,120,215, 24,208,112,185,215,201,135,135,178,158, 32, 93, 34,228,112,226,106, 22,161,244,175,
+167,183, 80,127,221,237,123, 30, 93,126,117,213,214, 30,158,250, 13,189, 61,191,247,255, 0,232,107,168, 42, 78,140, 0,136,124,
+210, 63,234, 45, 57,136,166, 14, 8,151,255, 0,102,159,213, 20,160,130, 47, 84,200, 25, 73, 7,232,161,222,244,185, 13,241,143,
+ 14, 20, 43,218,128, 39, 10, 80, 64,160,134, 7,198,159,122, 1,218,129,246, 87, 83, 41, 65, 2,128, 95, 27,145, 81,242,152,104,
+ 10, 60,239,245, 81,153,170, 30, 73, 37,213,124, 45, 70, 16, 32, 77,172, 43,133,207, 26, 81,192, 82,130, 0,168, 81, 45,227, 73,
+107,181, 45,205,170, 22,102,124, 88, 99, 77,245,204,121, 32,240,254,117,115,187,118, 22,160,231,114, 74, 49, 92,217,187,118,231,
+114, 74, 22,226,228,223, 36, 74,155, 34, 28, 88,245,202,214, 30, 3,196,251, 0,172,246,110,227, 46, 89, 42, 62, 8,175,193, 7,
+143,243,170, 60,249, 18,228,191, 82, 86,185,240, 30, 0,123, 40, 85,249,220,222,229, 59,245,133,186,194,223, 78,114,254,239,145,
+247,176,251,124, 44,210,115,164,231,240,143,151,204,234,218,236, 61,169, 18,198,153,155,162,107,145,172,201,142,126, 85, 30, 26,
+252,207,178,168,251, 95, 9, 51,119,120,132,130,241,194, 12,204, 60,244,219, 79,253, 34, 43, 67,248,129,220, 82,246,215,109,100,
+102,226,144, 50,230,101,199,197, 99,250, 47, 37,254, 63,232,170,146, 61,181,234,236,216, 17,188,253, 89,165, 47,171,108, 34,248,
+ 87,156,153,230,238,217,206,204, 93,184,183, 26, 71,116,218,227, 78,136,126,251,222,253,177,218,228, 99,102,228,143, 80,163,134,
+ 38, 58,235,117, 31,202, 85,224,191,210, 34,168,113,255, 0, 25,123, 74,105, 52, 75, 30, 94, 58,223,251, 73, 34, 82,191, 79, 77,
+221,191, 37,120, 44,178,201, 52,143, 52,206,210, 75, 33, 44,238,196,150,102, 60, 73, 36,243, 38,153, 95,179,143,111,180,163, 73,
+ 54,223, 85,167,185, 31,142,159,114,188,229, 88,168,165,209,235,239,103,212,253, 45,135,186,176,134, 86, 52,145,229, 68,252, 35,
+202,132,141, 74,124,175,204, 17,250,173, 88, 93,223,105,159,104,202, 48, 75,241, 35,124, 81, 74, 57, 50,253,163,198,188,247,240,
+255, 0,185,242,187,115,127,198,180,135,208,230, 72,144,102, 66, 79,194, 85,206,145, 37,191, 89, 9,189,254,138,247,190,233,194,
+ 92,189,162, 87,183,239, 49,255, 0,122,135,221,243, 15,217,175,207,247,190,213, 5, 25, 78, 43,234, 73,201, 73,104,228,151, 24,
+200,253, 7,102,238,146,147,140, 37,246,182,163, 40,241, 81,111,132,162,121,246, 30, 84,152,115,172,241,158, 95, 50,248, 48,241,
+ 6,182,152,217, 49,203, 18,204,172, 52,201,241, 2,120, 86, 18,180,189,187, 59, 62, 60,144, 31,238,152, 50,251,155,243,138,248,
+253,159, 33,198,235,176,223,211, 52,218,240,146,249,163,234,247, 91, 10, 86,213,228,190,168, 52,159,140, 95,201,158, 85,248,148,
+ 65,238,188,130,164, 17,210,135,136,254, 96,173, 47,225,246,102, 38, 15,109,205, 62, 92,201, 4,107,146,247,121, 24, 40,249, 19,
+196,214,107,241, 40, 91,186,242, 7,251,168,127,168, 42,143,106,218,247, 61,242, 65,131,132, 11,164,119,118,212,214,142, 61, 86,
+ 5,143,190,222,250,253,207,167, 27,152,150,227, 41,109, 74, 49,109,248, 36,126, 33, 93,149,188,203,146,140,119,201,202, 73, 47,
+ 22,207, 87,147,189,251, 96,191, 76,238, 3,218, 68,114, 21,250,194, 90,172,240,119, 45,187,115, 66,248, 25, 17,228, 5,230, 17,
+129, 35,222, 57,138,243,137,127, 13,119,133,128,201, 14, 68, 19, 72, 5,250, 64,178,147,236, 5,133,190,186,202,164,153,251, 62,
+105, 40,207,139,153,142,196, 27,124, 44,172, 57,131, 92, 86, 37,139,137,250, 55, 91,107,175,240,143, 67,205,200,180,215,175,105,
+ 36,250,105,243, 61,103,189,129, 29,179,159,171,202, 62, 31,243, 82,188,207,181,127,245, 22,221,111,246,195,248,235,107,184,111,
+ 75,191,118, 30, 94, 99, 0,185, 41,211,139, 37, 71, 32,226, 72,248,129,228,192,222,177,125,168, 47,220, 91,112,255, 0,124, 63,
+128,215, 76,104,184,227,222,140,180,105,201, 63,218,115,202,156,103,147, 98,113,117, 82, 80,107,247, 30,217,117, 85, 44,238, 21,
+ 84, 93,137, 32, 0, 7,153, 53, 71,153,223,157,185,131, 33,140,100,245,220,112, 61, 21, 46, 7,244,190, 95,203, 88,174,252,238,
+ 25,242,115,164,217,177,156,166, 38, 49,211, 56, 6,221, 73, 7, 61, 94,197,229,111, 58,139,218,189,156,219,252, 79,153,147, 49,
+199,195, 70,233,169, 81,119,118, 2,231, 77,248, 0, 47,206,184, 67, 18,220,109,171,183,228,226,158,169, 47, 30, 7,123,153,151,
+ 37,117,217,199,138,147, 90, 54,252, 56,155,104,255, 0, 17,182, 41,159, 73,154, 72, 65,225,169,227, 54,255, 0,163,170,175,113,
+179,161,220, 99, 19,225,228, 44,241, 31,211,141,131, 11,249, 27, 86, 31,119,252, 54,134, 28, 87,159,106,201,145,230, 64, 88, 65,
+ 54,147,174,194,246, 86, 80,182, 62, 92, 43, 31,176,239,153,123, 14,122,101,192,196,199,112, 50, 33,191,194,233,226, 8,243,242,
+ 62, 21, 86, 45,155,176,114,199,147,170,229, 32,242,239,217,154,134, 76, 21, 37,250,162,123,139,199,101,164, 10,136,132,185, 0,
+ 0, 73, 39,128, 0, 87,155,254, 33,231,200,242,109,147, 99, 76,235, 28,208,188,138, 81,138,220, 49, 82, 15, 15,101,101,246,230,
+222,247, 73, 14,211,133, 44,178,156,162, 58,145,151, 54, 33, 46,110,228,158, 10, 47,198,177,111, 9,206,218,184,230,162,159, 26,
+174, 20,122,155,185,158,161,117,218, 86,220,154,225, 71,198,171, 77, 15, 83,200,239, 78,217,193,148,196,249,130, 87, 28, 15, 69,
+ 90, 64, 63,164,163, 79,229,169,123,119,115,108, 27,195,136,240,179, 20,204,121, 67, 32, 49,185,254,104,112, 47,244, 86, 21,191,
+ 12,119, 85,135, 95,172,128,203,111,236,236,246,191,150,171,127, 21, 99, 39,131, 35, 7, 38, 76,121,129,139, 34, 7, 42,195,197,
+ 89, 79,129, 21,214, 24,152,215, 19, 86,238, 55, 37,252,112, 56,207, 55, 42,211, 82,187,105, 40,190, 95,206,167,208,144, 58,153,
+ 52,176,186, 26, 22,233,184,224,237,177,135,200,158, 60,100,111, 25, 24, 2,125,215,231, 89,156, 14,229, 56,253,149, 30,255, 0,
+148, 58,153, 17,131, 2,131,253,228,193,138, 45,253,224,106, 53,229,185,185,219,134,245,156,114, 50,157,242, 50,167, 96,170, 57,
+241, 38,202,136,190, 3,200, 10,227, 99, 10, 83,148,183, 61,177,131,113,111,171, 93, 14,249, 25,241,132, 97,177,110,148,210,146,
+ 93, 19,234,122,250,119,223,108, 2, 17,179,198,174, 87,233,201,111,175, 69,170,175,188,179,112,247, 30,214,202,200,194,157, 50,
+ 35,215, 16,213, 27, 6,183,239, 23,129,183, 42,206,226,126, 25,111,115,192, 37,200,158, 12,103, 97,126,147, 22,102, 31,206,208,
+ 8,252,181, 67,188,236,123,191,110, 72,113,179, 56, 67,144, 44, 36,137,137,138, 80,166,254,206, 71,141,136,174,246,241,241,253,
+ 72,250, 87,107, 40,180,232,245,173, 58, 30,123,185, 89, 94,148,149,219, 52,140,162,213, 86,148,175, 94, 33,187, 55,255, 0, 83,
+109,255, 0,207,111,250,182,175,104, 5, 34, 87,154, 70, 9, 26,139,179,177,178,128, 60,201,175, 24,236,175,253, 83,182,240,191,
+198,220, 63,229,181, 89,247,239,114, 79,184,110, 50,237, 56,237,211,192,195,109, 12,138,109,212,149,126,102,127, 61, 39,128, 21,
+114,172, 74,246, 68, 98,157, 18,133, 91,240,171, 51,137,145, 27, 24,211,155, 85,110,116, 75,171,162, 54,121,189,243,219,120,178,
+ 20,245, 70,118, 23,191, 69, 11,143,218,224,167,232, 52,204, 95,196, 30,217,145,130, 60,210, 67,168,252,210, 70,108, 47,252,205,
+ 85,143,237, 30,197,110,225,199,109,195, 50,115,141,134, 24,164,122, 0, 47, 33, 95,152,130,220, 0,191, 10,183,223,127, 12, 98,
+197,194,151, 47,104,201,146, 73, 33, 82,231, 30, 96,164,184, 2,228, 43, 32, 94, 62, 92, 43,155,179,135, 25,122,114,156,183,112,
+111,149,125,199, 85,127, 58,113,245, 99, 8,109,226,151, 54,189,230,251, 30, 92, 93,194, 37,202,194,158, 57,225,110, 79, 27, 6,
+ 23,250, 42, 65,137, 71, 13, 92, 43,194,123,107,184, 50,123,127,113,143, 37, 9,108,102, 33,114,160,191, 7, 79, 30, 31,172, 60,
+ 13,105,255, 0, 19, 50,165, 77,203, 2, 76, 89,157, 34,151, 20, 58,148, 98,161,129,118,179,112,246, 86, 37,130,213,232,219,221,
+164,147,106, 84,233,200,220, 59,130,118,101,115,111,213, 22,147,141,122,243, 76,244,204,140,156, 60, 76,118,159, 37,214, 40, 99,
+ 23,121, 92,133, 0,123, 73,170, 60, 30,243,216,119, 77,197, 54,204, 23,121, 38,144,183, 77,180, 16,135, 66,151, 60, 90,199,146,
+249, 87,144,225, 38,243,189, 74,155, 78, 35,203,146,211, 48,113, 9,114, 86,234, 15,198,218,141,128, 0,243, 53,232, 61,177,248,
+127,184,236,155,190, 46,233,155,151,142, 86, 16,250,225,140,179, 55,199, 27, 71,192,233, 3,129,106,212,241,108,218,132,189, 75,
+149,149, 27,138, 90,121, 25,183,153,122,244,227,233,219,164, 42,148,219,215,207, 93, 13,246,169, 47,195,253, 45, 78, 10,231,199,
+203,242,210,172,152,235,195,169,123,115,176,189,119,168,199, 67,193, 89,191, 37,120, 79,160,118,146,110, 53,124, 67,194,148, 71,
+195,226,230,108, 1,166,122,160, 9,211, 24,250, 77,119,172,155,146,133, 81,238,168, 80,194, 19,112,192, 92,243, 2,138, 96, 32,
+ 95, 73,185, 28,252, 42, 17,202,200, 63,222, 16, 60,135, 10, 12,146, 74,192,146,228,253, 52, 33, 98, 98,107,124,108,160,112, 23,
+184,228, 41,191,225,212,234,105, 65,183,128,170,208,220, 56,243,225, 69, 3,133, 1, 48,207,138, 7, 18, 92,251,168, 71, 46, 4,
+ 31, 12, 68,219,204,212,103,176, 7,217, 66, 45,171,242, 85,168, 39, 12,212, 22,211, 0, 30,246, 38,148,230,177, 55, 17, 32, 39,
+199,137,254, 58,130, 88,131,192, 94,226,194,158,167,128,191, 63, 26,128,181,245, 50,122,123,233, 95,236, 53, 90,220, 47,234, 52,
+249,215, 80,111,254, 27,255, 0,225,191,249,154,234, 2,208,142, 9,252,196,254,168,174,174, 39,228,254, 98,127, 84, 87, 94,169,
+ 8,249, 31, 48,191,149, 0,139,240,163, 78,223, 24, 30,202, 24,189,248, 10, 1,129, 85, 73,243, 52,237, 39,192,211,133,169, 45,
+198,128, 64, 13,136, 52,154, 8, 55,191, 63, 10, 40, 23,165, 34,128, 23, 31, 26,133, 48,213, 43, 17,203,236, 21, 61,133,170,184,
+184, 44, 91,207,141,168,202,133, 10, 57, 26,113, 0,123, 0,166,134,170, 13,215, 62, 73, 37,124,100, 58, 99, 67,165,173,250, 68,
+115,189,121,114,242,161,141,111,124,149, 91,116,138, 92,217,232,198,198,158, 69,205,145,209, 45, 91,124,145, 35, 63,119, 11,120,
+177, 13,207, 35, 47,128,254,109, 82,146, 88,150, 99,114,120,146,121,210, 85,142,223,181, 73,148, 68,178,221, 33,240,243,111,117,
+126,118,119, 50,115,175, 37,247, 62, 81, 95,108, 87,241,204,251,209,134, 62, 29,166,248, 46,114,127,116,153, 27, 27, 14, 92,173,
+ 69, 5,163, 64, 75, 57,228, 45, 81,235,100,176,199, 28,125, 20, 80,169,107, 0, 61,181,144,150, 51, 20,143, 27,115, 66, 84,253,
+ 21,211, 59, 5, 99, 66,214,187,156,171,185,242,174,148, 72,231,135,152,242, 39,119, 77,170, 52,218,185,211, 90,182,104,123, 42,
+ 85, 77,214, 72,207, 57, 33, 96,190,240, 85,191,128, 83,191, 23, 54,201,247, 14,210,105,160, 82,237,131, 58,100,186,142,125, 48,
+ 26, 55, 63, 70,187,213, 6, 30, 84,184, 57, 81,101,195,243,196,193,135,183,204, 31,120,175, 79,193,206,196,221,176,196,209, 89,
+227,144,105,150, 38,177,177, 35,226, 71, 21,244,251, 22, 84, 99, 31, 79,245, 91,150,228,186,197,159, 59,189, 98,185,183, 47,211,
+114, 59, 91,233, 36,124,151, 93, 94,209,220,191,131, 81,100,206,249,125,183,146,152,193,201, 99,133,145,126,154,147,254,205,212,
+ 49, 3,216, 65,247,214,119, 31,240,103,186,100,148, 46, 68,216,144, 71,227, 39, 81,156,219,216,170,149,251, 8,229,216,148,107,
+189, 47, 7,196,252,124,176,178, 35, 45,187, 27,241, 92, 12,111,110,109,147,239, 27,238, 6,221,142,165,154,105,144, 49, 31,162,
+128,234,119, 63,205, 80, 77,125, 57,190,202,176,236,249,174,230,192,196,200, 61,238, 52, 15,202,106,151,179,251, 19,106,237, 8,
+218, 72, 9,201,207,149,116,205,153, 32, 0,233,231,162, 53,227,165,106, 15,119,111,113,229, 48,219,113, 91, 84,113,182,169,220,
+114, 44, 57, 40,247,120,215,196,239, 57,246,213,169, 52,244,218,227, 10,241,148,164,125,222,205,129,113, 77, 39,197,201, 74,116,
+225, 24,196,202,213,215,110,179, 9,167, 0, 18, 10,139,129,239,170, 90,209,246,228, 5, 97,150,114, 63,180, 96,171,238, 95,206,
+107,242,157,178, 46, 89,118,233,250,106,223,149, 15,211,119, 25, 40,226,220,175, 58, 37,231, 83,202,255, 0, 18, 13,251,171, 32,
+216,143,221, 67,207,249,130,180,159,134,139, 8,218, 50, 74,139,204,217, 4, 72,124,116,132, 93, 63,194,107, 57,248,147,199,186,
+242, 63,225,197,253, 65, 85, 27, 22,255, 0,159,219,243,180,248,160, 52, 83, 13, 50,194,247,210,250,125,222, 34,252,235,250, 19,
+181, 43,152,112,132,120,237,139,243,161,248, 24,221,141,172,217,206, 75, 77,210, 79,194,188,207,110, 4,163,127, 36,215,147,254,
+ 34,172, 35,184,201,138,218,218, 8,204,214,253,126, 35,250,160, 85,140,223,137,147, 52, 86,135,111, 85,150,223, 51,200, 89, 65,
+254,104, 85, 39,235,172,100,211,102,238,249,205, 44,154,178, 50,242, 95,146,139,150, 99,192, 42,129,249, 43,158, 30, 53,203,115,
+115,184,182,170, 53,196,235,155,149,106,237,181,110,219,220,219, 79,135,204,187,217,139,255, 0,149, 59,136,127,118, 61, 45,191,
+157,212,227, 80,251, 79,255, 0, 82,109,191,241,135,241,214,199, 47, 98, 59, 15, 96,102,193, 53,189, 84,221, 57,178,109,224,198,
+ 68, 1, 63,162, 63, 45, 99,123, 79,255, 0, 82,109,191,241,135,240, 26,237, 25,169,219,200,148,120, 55, 47,132, 82, 56, 78, 18,
+133,204,104, 75,138, 81,175,182,109,145, 55,157,127,123,238, 29, 79,159,212,205,170,254,122,218,167,109,155, 47,115,230, 98, 44,
+251, 92, 83, 54, 43, 22, 10, 99,148, 42,220, 27, 55, 13, 98,174,187,251,183, 39,197,206,147,121,198, 66,248,153, 39, 84,228, 11,
+244,228,228,117,123, 27,157,252,234, 31,106,119,156,221,186,143,137, 44, 62,163, 14, 70,215,164, 29, 46,140, 69,137, 91,240, 32,
+219,149,107,212,148,236, 70,118, 84,100,232,180,127, 21,230,101,219,140, 50, 37, 11,238, 80, 85,127, 82,248, 63, 33, 7,108,247,
+209,254,227, 36,255, 0,207, 31,252, 74,140,123, 35,186,185,157,185,255, 0,110, 63,245,235, 71,187,254, 38, 52,248,146, 99,237,
+ 56,207, 4,178,130,167, 34, 86, 23, 64,120, 93, 21, 47,199,200,222,164,246, 47,116,239,187,150, 74,237,185, 80,156,216, 20,124,
+121,164,233,104,135,129,145,185, 55,240,215, 47, 83, 42, 54,221,199, 11,113,167, 21,193,211,222,117,244,177, 37,113, 91, 87, 46,
+ 74,188, 26,213, 87,220, 80,119,134, 54, 78, 30,223,176, 99,230, 41, 76,136,241, 89, 36, 66, 65, 32,171, 40, 3,133,252, 42,211,
+240,178, 36,108,173,202, 82, 46,235, 28,106,167,200, 49, 98,127,170, 41,223,138,193, 70, 94,219, 99,127,221, 73,253,101,167,126,
+ 21, 50, 44,187,161,111,213,134,223, 92,149,153, 74,184, 46, 92, 43,175,190,102,163, 20,187,130,143, 26,105,175,132, 15, 72, 28,
+173,107,215,137,247,202,132,238,157,192, 1,111,137, 9,247,152,210,245,237,162,120,193,176, 91,249,215,138,119,209, 13,221, 89,
+228, 11, 11,199,195,254, 82, 87, 14,221,254,105,127, 99,252, 81,232,238,127,225,143,247,175,193,135,204, 50,255, 0,144,118,208,
+ 9,233, 28,233,110, 60, 47,165,173,252,116, 62,193,138, 9,123,167, 9,103,181,135, 81,163,191,235,136,216,173,105,118, 45,168,
+239,189,130,118,208, 66,201,214,146, 88, 24,248, 72,173,194,231,200,242,175, 62, 43,157,180,103, 13, 65,241,115,113, 92, 48,191,
+ 6, 86, 83,112,107,217, 6,167, 27,246,147,164,183, 77,126,238,103,134,226,118,229, 98,243, 85,142,216, 63,219,200,250, 47,162,
+223,171,107,120,154,200,126, 36,197, 15,249, 97,218,109, 61, 85,154, 35, 15, 17,125, 68,216,219,250, 55,172,206, 55,226,134, 82,
+194, 23, 51, 4, 77, 40, 31,218, 36,133, 1, 62,101, 74,191,240,214,115,184,123,155,112,238, 55, 83, 58,136,177,161,248,163,130,
+ 59,144, 9,225,169,137,230,124, 43,201, 99, 14,244,110,198, 82, 91, 84, 93,107, 94, 52, 61,153, 25,182, 37,102, 81,131,114,114,
+ 84,165, 56, 87,168,254,201, 32,119, 78,218, 88,216,107,107,159,249,111, 84,249,250,189,118, 78,191,159,171, 38,171,243,190,163,
+122,181,236,239,253, 75,183,255, 0, 61,191,168,213,103,223, 61,187,145,131,159, 46,235, 4,101,176,178,219, 91,149, 31,217,200,
+223, 48,111, 99, 30, 32,215,185,220,140,114,118,189, 55, 65, 83,205, 55,161,224, 86,229, 44, 93,235, 85, 11,142,190, 77, 45, 74,
+221,187,102,238,172,172, 56,231,219, 82,115,136,247,233,152,229, 10,188, 9, 6,203,172,120,138,149,254, 95,239,115,113,211,201,
+ 62,127,191, 31,252, 74,119,108,119,156,219, 12, 39, 10,120,142, 70, 33, 98,200, 20,217,208,159,155, 77,248, 16,124,170,199,120,
+252, 69,124,156, 87,198,218,160,124,118,148, 21,108,135, 97,169, 65,253, 64,190, 62,219,215, 57,203, 39,212,113,141,184, 56,215,
+ 73, 62,158, 58,157, 97, 28, 95, 73, 74, 87,110, 41, 37,172, 87, 95, 13, 10, 63,242, 95,115,159,255, 0,183,191,237,199,254,189,
+ 77,239,100,202,137, 54, 56, 51, 65, 92,136,118,248,227,145, 73,185, 5, 9, 91, 92, 95,202,180, 61,145,220,219,246,233, 55,161,
+201,128,229,195, 24,248,243, 71,194,201,228, 28,242,107,253,117, 85,248,155,168,238,152, 69,133,191,195,155,126,219, 86, 99,118,
+235,201,141,187,138, 63, 74,111,233,242, 53, 43, 86,150, 44,174,218,115,250,154, 77, 75,193,147,127, 11,113,227, 45,184,229,145,
+251,213, 17,196,173,228,173,169,155,235, 42, 43,208,156,216,243,247, 86, 11,240,177, 25,224,220,244,219,131,197,123,251,158,189,
+ 4,227, 31,210,113,244, 10,240,230,255, 0,244, 79,217,248, 30,252, 26, 44,104,123,127, 22, 9, 56,113,243, 52,107, 94,152,137,
+224, 56,212,133,140,154,243, 30,160, 90,107,136,181, 25, 97,210, 52,253, 52,173, 21,193, 0,208,128,116,130,183, 20,199, 22, 6,
+164,170, 5, 91, 95,149, 2, 77, 36,112, 60, 77,239, 66,130, 88,101, 98, 8, 67,244,209, 22, 41, 91,200,125, 52, 68,144, 40, 3,
+199,128, 3,223, 72,174, 19,226, 35,133,248,208, 28, 49, 93,175,119, 3,232,174, 24,163,197,207,208, 42, 76, 55, 40, 9,224, 77,
+ 59, 77, 8, 70,244,168, 57,179,255, 0,167,209, 75,233,162,243,115,244,212,146, 41, 45, 64, 19,161, 31,166,181,143,253,222,215,
+191, 27,122,141, 85,212,107,127,135,246,116,127,237,171,170,128,204, 88, 20, 22,253, 4,254,168,165,212,124,169,199,244, 79,242,
+ 19,250,162,155,170,128,143, 63,206, 13,143, 42, 17,146,222, 6,164, 74,120,220,121, 80,109,168,241,160, 27,168,219,151,213, 72,
+178, 18,120,139, 81,128,183,186,186,128,110,171, 10, 93, 64,248,210,144, 57, 26,110,144, 9,189, 0,201, 26,202, 74,155,216, 19,
+245, 84, 32, 42, 84,224, 8,152,142, 7,128, 31, 93, 69,210,109,206,163, 42, 56,218,168,243,182,169,222,119,150, 11, 58,200,117,
+ 17,123, 16, 79, 62,117,116, 71,141,119, 32, 43,207,147,139,111, 34, 10, 23, 43,163,170,107, 70,142,248,249, 55, 44, 73,202,221,
+ 53, 84,105,234,138,156, 45,160, 35,117, 50,172,196,114,140,113, 31,210,171,158, 32,112, 22,183, 42, 64, 56,209,121, 10,184,248,
+214,172, 71,101,168,211,171,124, 95,155, 37,252,139,151,165,186,227,175, 69,201,121, 32, 68,177,170, 77,227, 12,134,245, 72, 46,
+ 15, 9, 63,136,213,229, 52,133, 96, 67, 11,131,192,131, 83, 43, 30, 57, 22,165,110, 90,115, 79,164,185, 50,227, 95,149,139,170,
+228,117,228,215, 85,208,199, 84,172, 29,195, 47,110,155,173,137, 41,141,185, 48,230,172, 60,152, 30, 6,164,231,109, 79, 17, 50,
+227, 13,113,243, 41,226,191,104,170,202,252,189,219, 55,177,174, 82, 73,194, 75,132,151,227, 22,126,142,221,219, 89, 22,235, 26,
+ 74, 47,138,127,131, 70,203, 23,190, 70,144, 51,113, 78,175, 23,136,240, 63,209,111,182,164, 63,124, 96, 1,251,188,105,153,188,
+155, 74,143,174,237, 88, 90,234,244, 71,186,230, 37, 77,233,248,184,170,156, 31,109,197,110,187, 26,240, 77,208,189,220,251,171,
+113,207, 83, 12,118,198,133,184, 50,198,110,196,121, 23,251, 42,138,186,143,141,135, 62, 91,232,133,110, 60, 92,240, 81,239, 53,
+230,157,203,249, 23, 22,231, 43,146,122, 37,199,220,143, 68, 97,102,196, 30,213, 27,113, 90,183,243, 99,113,177,228,202,153, 96,
+136, 93,152,243,240, 3,196,154,216,195, 19, 99, 64,144, 69,109, 40, 44, 60,207,153,161, 96,109,241,109,241,217,126, 41, 24,124,
+114, 30,103,216, 61,149, 36,158,118,241,175,208,118,236, 47,245,224,229, 63,242, 79,143,252, 87, 79,153,240,179,243, 61,121, 40,
+195,236,135, 15,249, 62,165, 6,239,219,123, 62,229,149,234,243,176, 82, 76,135, 0, 52,133,158,228, 40, 0,114, 34,163, 14,214,
+216,206, 25,192,108, 52,244,218,140,129, 56,240,114, 0, 44,172, 78,161,192,120, 26,189,201,118, 14,170, 5,236, 40, 7,226, 28,
+253,246,175,170,174, 92,162, 91,229, 69,195, 87,161,243,189, 43,117,111,100,106,248,232,181, 50,205,248,123,219, 97,245,104,152,
+ 47,234,137, 13,190,218,185,218,182, 45,155,104,248,182,252, 85,137,200,177,148,221,156,143,231,189,205, 79, 30, 86,225,230,105,
+ 15,194,121,147,236, 21,101,122,236,149, 37, 57, 53,209,178, 70,197,168,186,198,220, 83,234,144,204,204, 76, 77,199, 29,240,242,
+208, 77, 4,150,215, 25,184, 6,196, 48,229, 99,204, 85,126, 47,106,246,254, 30, 76,121, 88,184, 41, 28,209, 29, 81,184,103, 36,
+ 31, 62, 45, 86,102,234,117, 14, 30,116, 64,111,199,206,178,167, 52,168,164,210,124, 82,122, 26,118,225, 38,165, 40,166,215, 6,
+213, 88,172,170,202, 85,192,101, 34,197, 79, 16, 65,172,222,103,101,118,222,100,140,231, 19,162,199,153,133,153, 7,236,131,167,
+242, 86,146,187,161,115,123,243,227, 72,220,156, 53,132,156,124,157, 4,237,194,122, 78, 42, 94,106,166, 82, 62,193,237,184, 88,
+ 51, 67, 36,182,240,146, 70,183,253, 29, 53,161,194,198,197,193,132, 99,225,196,144, 68,188,145, 0, 81,249, 43, 17,220,157,225,
+186,109, 27,254, 70,221, 10,196,113,161, 49, 88,178, 18,214,120,210, 70,226, 24,126,181, 2,126,234,238,205,200,190, 78,203,183,
+186, 96,130, 68,110,176,153, 73, 3,205,136, 42, 79,152, 94, 85,103,114,228,254,249, 57,121,178, 66,213,184,125,144,140,124,145,
+183,220,118, 93,167,118,104,223,113,198, 89,218, 32, 68,101,139, 11, 3,207,229, 34,147,111,217,182,189,167,168,118,220,101,128,
+203, 97, 33, 82,198,250,111,111,152,159, 58,198,108,191,136,121, 17,229, 46, 46,253, 2, 8,153,180, 52,241,169, 71,140,222,215,
+116, 60,192,241,181,143,190,175,123,223,185, 51,187,125,118,246,219, 68, 76,185, 66, 82,230, 69, 46, 44,157, 61, 58,108,195,245,
+234,111,158,221,187,158,222,149,211,220, 54, 67,118,253,171,119, 90,107,239, 52,136, 9, 53, 93,153,218,251, 14,225,146,249,121,
+152, 75, 46, 68,182, 47, 33, 46, 9,210, 2,142, 76, 7, 33, 93,218,251,148,219,182,205,139,159,152, 20, 79, 63, 83, 88, 65,101,
+248, 36,116, 28, 46,124, 22,169,123,215,187, 55, 46,223,206,199,198,219,196, 38, 57, 97,234, 63, 81, 75, 27,234, 43,194,204, 60,
+170, 70, 82,139,172, 91,139,240,116, 44,161, 25, 42, 74, 42, 75,142,170,165,134,235,153,129,217, 91, 84, 79,137,135,124,118,155,
+166, 33, 71, 43,102,117,103, 45,118,213,250,148, 12, 6,217,251,227,111,124,220,221,185, 87,165, 43, 64,186,154,238, 44,170,247,
+ 14,154, 72,249,249, 85, 71,122,110, 15,185,118,102,213,151, 48, 29,121,166,134, 73, 52,139, 45,204, 50,222,220,234,131,183, 59,
+147,117,219,182,231,218, 54,108, 79, 81,149, 52,207, 51, 62,150,146,202, 86, 52, 26, 81, 61,171,196,158, 20,221, 36,247, 38,247,
+117,174,190,241,178, 46, 59, 92, 86,222,148,211,220,108,135,225,207,110,159,222, 17, 45,191, 83,168,109,246,212,252,158,220,237,
+253,175,101,205, 11,132, 31, 26, 40,154,121,162, 4,134,147,162, 12,128, 25, 56,183, 53,172, 91,119,175,119,109, 51,170,110,184,
+227, 73,226, 34,158, 19, 21,199, 11,232,101,211,245,241,173,167,223, 24,187,239,103,238,153,248,196,128,113, 50, 82, 72,154,218,
+145,150, 38,186,155,123,239, 91,119,174,202,149,156,157, 60, 76, 43, 22, 99, 93,182,226,171,167, 4, 80,118,124,253,179,187,110,
+198, 60, 29,155,209,228, 99, 68,217, 9, 49,153,159,147, 44,118,183, 15,246,149, 57,187,223, 9,247,179,176, 62,218, 91, 86, 95,
+161,105, 25,193, 83,121, 58, 58,138,149,229,227,106,206,254, 22,255, 0,234, 12,159,252,155,255, 0,214,195, 83,127,205,185,255,
+ 0,230,239,186,189, 54, 39, 71,239, 47, 77,212,232,254,243, 79, 95,167,171, 93,254,107,120,249,214, 37, 41, 73,214, 82,109,248,
+186,155,140, 35, 20,212, 98,162,186, 37, 67, 79,151,216, 29,177,150,229,253, 31, 65,143, 51, 3,178, 15,217,185, 95,201, 67,131,
+240,235,181,225,112,231, 30, 73,173,225, 36,140, 71,212,186,104, 61,229,222,205,219,211, 38,223,131, 10,205,152,232, 36,119,146,
+250, 17, 77,192,248, 84,130, 88,219,206,170, 34,220,255, 0, 19,242,177,215, 62, 12,101,244,238,162, 68, 1, 33, 4,169, 26,129,
+ 8,205,212, 55, 21,211,215,189, 74,122,146,167,155, 57,255, 0,175,102,181,244,225,238, 70,242, 28,124, 92, 24,151, 19, 18, 37,
+130, 37, 31, 4,113,168, 85,246,242,172, 71,121,110,155, 22, 30,225, 6, 62,235,180,250,249,122, 10,233, 47, 84,166,149,105, 28,
+105,176,254,109, 11,183,255, 0, 16,114,242,183, 24,182,221,238, 4, 70,149,250, 43, 60, 96,161, 89, 15,194, 22, 68, 98,121,183,
+ 15, 11, 85, 71,226, 88,182,249,139,255, 0,147, 79,250,217,171,154,148,147,220,155, 79,170,122,157, 28, 34,214,215, 20,215, 70,
+180, 61, 35,182,246,237,171, 27,110,135, 51,107,196, 24,107,159, 20, 83,188, 97,153,190,100,214,160,150, 39,150,170,184, 43,122,
+242,220, 94,238,238,124,141,183, 19, 11,183, 54,215,104,112,177,226,130, 92,145, 19, 76,197,227,141, 84,218,223, 0,226, 57,113,
+ 52,221,171,241, 39,119,198,205, 92,125,250, 53,146, 13, 90, 38, 96,157, 57, 99,227,107,216, 88,112,241, 22,163,109,186,201,182,
+223, 54, 20, 84, 85, 34,146, 75,146,208,244,134, 44,132,129,194,252, 13, 23,212, 40,170,206,230,238, 61,187,183, 48,211, 39, 34,
+ 17, 62, 76,196,140,120, 65,177,114, 57,146,120,217, 71,137,172,102, 15,115,119,246,249,212,159,100,194,137, 96, 13,243, 44,104,
+ 19,135,232,135,201,107, 19,231,106,133, 61, 20,228,146,120, 41, 62,234, 30,188,167, 63, 10,181,188,173, 88, 40,255, 0, 16,123,
+155, 98,206, 92, 78,229,193, 66,166,197,180,160,142, 77, 60,181,161, 82, 99, 97,254,151,173,142,255, 0,220,146, 98,118,188,219,
+246,211, 34, 75,240,196,248,236,224,149, 34, 73, 17, 13,214,224,242, 99,244,208, 19, 12, 25,175,199, 67, 82,166, 30, 69,238,203,
+ 96, 57,220,215,158,226,254, 41,238, 67, 3, 33,178,226,142,108,246,117, 92, 72,209, 89, 80, 2, 14,167,147,226, 55,227,107, 1,
+ 83,251, 67,185,251,151,119,222, 91, 19,119, 26, 49,222, 23,145, 20,195,211,226,165,109,164,145,115,206,161, 77,218,196, 47,123,
+ 92,129,206,155, 10,134, 4, 17,227, 82, 7, 5, 63, 85, 7, 31,129, 36,120, 26, 16, 58,141, 34,150,213,195,206,148, 31, 3, 84,
+ 13,183, 26, 91, 87, 31, 10,225,236,160, 36,255, 0,113,255, 0, 39,254,218,186,187,251,155,255, 0,185,255, 0,182,174,160, 14,
+199,130,219,245, 19,250,162,152,215,224,109, 74, 75, 89, 47,207, 66, 95,246, 69, 33,227,225, 64, 6, 91,223,151, 27, 82, 1,244,
+121,210,202, 78,176, 60,133, 13, 89,174,111,202,128, 37,239,225, 92,120,120, 83, 65,243,165, 39,133, 1,220,248,154, 66,111, 92,
+ 24,234, 32,139, 10, 70, 54,229, 64, 70,201,112, 85, 71,182,227,232,161, 22, 0, 83,178,141,221, 87,192, 11,223,223,255, 0,225,
+ 65,246,212,101, 56,155,138,238, 62, 84,170, 56, 94,151,194,128, 64,220,105,197,137,224, 40, 96,243, 52,224, 64, 20, 7, 1,122,
+ 80,162,185, 72,165,191, 26, 1, 81, 1,112, 60, 47,196, 31, 42,110, 78,215,133,145,241, 60, 64,127, 41,120, 31,201, 68,140,141,
+ 96,147,107,113,162,134, 91,115,252,213,137,194, 19, 91,103, 21, 37,209,170,154,132,231, 7,186, 18,113,125, 83,161, 71, 47,111,
+195,175, 76, 83, 50,223,193,148, 55,229,248,105, 71,109, 45,237,234,143,236,127,250,213,116,192,107, 94, 63, 64,162,106,191,202,
+120,138,242, 62,219,134,221,125, 37,236,148,151,230,122, 87,112,203, 74,158,171,247, 69,254, 69,108, 29,189,131, 29,139,234,149,
+191,148,108, 62,161, 83, 4, 9, 24, 9, 31,194,163,192, 90,194,164,107,241,231, 76, 33,124,121,215,162,213,139, 86,149, 45,194,
+ 49,242, 90,251,206, 23, 47, 93,184,235,114,110, 94,111, 79,112, 62,155, 51,104, 46,108, 7,178,184,196,227,244,201, 30,225, 79,
+ 67,241, 26,120,176, 62, 98,186,156,202,220,142, 18,148, 99,123, 91,143,209,122, 5,244,158, 28,188, 77, 27, 37,181, 76,236, 57,
+ 94,220,125,156, 40, 32,223,149,104, 10,108,120,243,246, 82,131,113, 99,192,211, 9,177,165,247,208, 29,192,112,231,230, 77, 16,
+115,181, 4, 16, 77,135,141, 29, 71, 27,209,129, 85,110, 69, 72,181, 13, 7, 17, 70,168, 67,197, 59,239, 72,238,236,253, 87,211,
+120, 53, 91,157,186, 17,242,175, 97,198,244,143,133, 1,193,210,113, 58,107,208,209,242,232,183,195,111,162,188,119,191,127,245,
+102,225,255, 0, 39,254,162, 58,208,101,118, 47,115,237,236,240,236,155,155, 28, 22, 36,172, 66,105, 33, 54, 62, 14,171,240, 31,
+125, 80, 82,254, 32,156, 67,220, 45,233,180,235, 16,160,201,211,254,214,237,207,219,163, 77, 77,239,133,153, 54, 46,214, 92,139,
+245, 70, 51,235,191, 59,232,199,224,111,227,231, 86, 91, 15,225,180,139,146,153,123,236,201, 34, 41, 14, 49,162, 37,181,155,223,
+247,142,192,112,243, 3,159,157,106,187,171,182, 98,238, 76, 20,131,169,209,200,128,151,199,146,215, 81,113,102, 86, 30, 70,128,
+135,216,139, 19,246,158, 19, 6, 37,151,172,172, 1,228,122,206,108,126,131, 88,239,196,233, 49,206,247,143, 12, 45,119,135, 29,
+ 68,162,247,179, 51, 51, 0,125,182,177,162, 99,118, 39,121, 96,187, 69,137,154,152,209, 57, 1,222, 28,137, 17, 91,194,228, 34,
+130,126,170,147,157,248, 95,185, 58,196,248,185,177, 77, 59,106,108,169,114, 11,173,216,158, 26, 2,164,132,251,201,160, 23,186,
+ 22, 49,248,121,177, 21, 80, 28,190, 61,219,196,254,226, 90,176,252, 46,108, 47,186,243, 21, 2,156,222,189,230,189,139,116,244,
+142,159,244,111,171,233,189, 78,222,123, 83,113,220,123, 87,109,216,224,150, 5,201,195,104,154, 87,118,113, 25, 9, 27,198,116,
+144,133,185,183,136,170, 24,191, 13,247,172, 76, 84,200,195,207, 72, 55, 68,102, 7,165, 36,138,133, 13,180,233,144, 42,178,183,
+ 63, 11, 80, 23,255, 0,136,231, 13,123,105,214,125, 61,118,150, 63, 75,127,155, 88,111,139, 79,244, 53, 86, 83,178,122,223,229,
+238,234,255, 0, 97,232,218,215,229,175,165, 55, 47,163,159,209, 79,255, 0,237,247,116,238, 57, 8,219,182,106,121, 25,165,149,
+231,112, 63,146, 15,250,194,183, 88,253,179,143,183,118,230,102,199,183, 17,212,201,130, 88,204,242,240,215, 44,168, 83, 91,149,
+ 6,195,143,128,224, 40, 12, 15,225,111,254,160,201,255, 0,201,191,253,108, 53, 91,255, 0,253, 3,255, 0,243, 63,252,213,109,
+123, 51,178,247, 78,220,221, 38,205,206,155, 30, 72,164,199,104, 64,133,157,155, 83, 60,111,115,174, 52, 22,178, 84, 79,242, 14,
+240,123,163,239,190,190, 55,166,245,254,179, 70,185, 58,157, 62,183, 90,214,233,219, 85,189,180, 1,251,223,182,176,183,156,209,
+151, 6,231,141,139,157, 26, 8,230,199,201,145, 80, 48, 31, 18,159, 22, 83,102,242,170,168,182,127,196,173,187, 29, 19, 3, 37,
+166,199, 69, 29, 49, 28,209,186,133,240,210, 38,183, 11,114,181,104,123,187,177, 87,127,156,110, 56, 83,174, 62,110,144,146, 44,
+128,152,228, 11,193, 73, 43,114,164, 14, 28,141, 83, 99,118,255, 0,226, 70, 4, 11,135,137,158,139,142,128, 42, 1, 40, 96, 20,
+114, 11,173, 53, 0, 40, 10,220, 46,250,222,118,237,195,210,239,216,241, 76, 21,244,100,234,137, 99,153, 13,248,176,233,133, 23,
+ 28,249,113,166,254, 39,127,249,238, 47,254, 74, 63,250,217,170,207,110,252, 58,206,147, 59,239, 14,224,204, 73,126, 62,164,145,
+198, 90, 71,145,190,107, 59,184, 91, 95,199,157, 88,119,127,101,238,157,199,184,193,157,133, 54, 60,113, 71,142,144,149,153,157,
+ 91, 80,119,126, 26, 35,113,111,143,206,133, 52,253,175, 4, 80,118,230,214,144,168, 85,108, 88,100, 32,120,180,136, 36,115,244,
+179, 26,242,159,196, 69, 85,238,188,187, 0, 53, 36, 36,219,196,244,214,189,135,105,198,147, 7,106,193,193,152,171, 75,141,143,
+ 20, 46,203,114,165,163, 69, 66, 86,224, 27,112,172, 63,117,118, 38,239,191,111, 83,110, 88,147,227, 36, 50, 44,106, 22, 86,144,
+ 53,209, 66,155,133,141,135,135,157, 8, 82,254, 38, 9, 70,225,182, 22,254,199,209, 46,143, 45, 90,219, 95,228,211, 82,246, 12,
+127,196, 25, 54,156,102,217,179, 32, 76, 2,191,184, 91, 65,112, 47,196, 29, 81, 19,123,243,185,173,182,255, 0,219, 24,125,195,
+183, 69,135,150,221, 57,224, 3,161,146,130,229, 26,192, 55, 3,107,169,183, 17, 88,204, 62,208,239,141,155, 90,108,187,140,125,
+ 6,111,149, 92,128, 79,235, 24,228, 66,160,251,168, 0,239,157,189,222,251,170,194,155,230, 94, 35,136,139, 24, 53,188, 49, 17,
+123,106,177, 68, 66,121, 10,157,149,129,153,182,126, 25,230,225,102, 60,110,209,200,157, 54,137,196,139,161,178, 34,111,152,127,
+ 40,154, 28,127,135,189,195,188,230, 46, 87,114,238, 42, 84, 88, 29, 44,100,147, 72,227,165,110, 21, 16,123,190,170,215,111, 93,
+184,185, 29,173, 47,110,237, 34, 56, 6,152,146, 14,161, 33, 64, 73, 82, 86, 44, 85, 88,220,233, 62, 28,232, 12, 79,225, 86, 14,
+ 52,249,155,134,108,168, 30,108, 85,137, 96, 44, 47,167,170, 95, 83, 15,111,193, 94,167, 89, 30,199,237, 93,195,182,125,127,175,
+146, 25, 61, 87, 71,167,208,103,107,116,250,151,213,173, 19,245,197,107,200,242,160, 59,194,212, 56, 7, 6,247,154, 45,184, 80,
+160, 23, 13,239, 52, 1,150,227,198,151,194,153,122,112, 62, 20, 7,123,105,111,194,212,150,227,237,174,176,229, 64, 74,183,238,
+ 63,228,255, 0,219, 87, 82, 91,247, 22,255, 0,115,255, 0,109, 93, 64, 25,207,203,252,196,254,168,164, 7,242,215, 61,254, 31,
+230, 39,245, 69, 50,255, 0, 93, 0,201,109,168,123,184,154, 97, 3,207,157, 36,199,227, 30,234,102,174, 55,160, 9,123, 10,237,
+ 66,178, 57,127,137, 29,147,131,151, 62, 30, 94,241, 28, 89, 56,210, 60, 51,198, 82, 82, 86, 72,201, 71, 94, 8, 71, 2, 41,119,
+175,196, 30,218,217, 54,140,125,246, 76,131,153,131,149, 33,139, 30, 76, 48, 37,212,224, 18, 87,230, 80, 8,177,230,104, 13,101,
+205, 37,175,204,212, 76, 28,200,247, 12, 44,108,248, 67, 44, 89, 81, 36,232,174, 0, 96,178, 40,117, 13, 98, 69,236,124,234, 77,
+237, 64, 66,158,230,102, 3,141,172, 7,213, 76,179,114,167,146, 26, 66,222, 4,222,170,187,131,184,118,238,217,219, 95,118,220,
+203,140,100,101, 67,210, 93,109,169,190, 80, 5,197, 66,150,129, 79, 42, 93, 62, 21, 19,104,221, 49,247,141,183, 23,117,198, 87,
+ 72, 50,227, 89,162, 89, 0, 14, 21,133,198,160,165,133,254,154,151,170,128,106,165,248, 82,232, 23,165, 86, 0,154,143,145,185,
+109,248, 78,169,153,151, 14, 59,200, 71, 77,102,145, 80,181,255, 0, 84, 49, 23,160, 37, 5, 2,212,182, 0, 82,107, 6,196,113,
+ 7,136, 53, 27, 47,115,219,240,221, 35,203,202,135, 29,159,228, 89,100, 84, 45,126, 31, 8, 98, 47, 64, 76, 69, 5,128, 62, 23,
+ 52,237, 43,250,163,234,160,122,172,104, 16,205,145, 42, 69, 24,183,239, 29,130,175, 30, 92, 91,133,116, 59,150,221,146,230, 60,
+124,184,101,107, 95, 76,114, 43, 27, 14,102,192,212, 4,160,145,159,208, 4,215, 8,147,203,157, 65,221,183,157,183,100,219,223,
+113,220,242,151, 27, 18, 50, 21,229, 96, 88, 2,199, 74,252,128,158, 36,210, 54,249,181,197,181,125,248,249, 42, 54,227, 8,201,
+ 57, 60,116,244,152,106, 15,107, 95,136, 62, 84, 4,226,137,171,232,229, 92, 99, 78, 22,254, 19, 81,118,221,219, 7,117,194,143,
+113,219,166, 19,226,100,124, 81, 74, 1, 1,128, 37, 73,179, 0,121,138,152, 25, 73,247,113, 6,128, 96,140, 92,243, 31, 77, 35,
+ 71,252,166,250,205, 60,145,196,130, 5, 84,111,157,203,177,246,234, 70,251,206,106,226,153,174, 33,142,204,238,228,115,209, 28,
+ 97,221,173,236, 20, 3,152,252,108,109,192,146,110,105,164,129,198,247,246, 84, 13,175,122,218, 55,188, 71,206,219,179, 99,200,
+199,136,145, 43,130, 84,198, 64,185, 18, 43,133,100,225,250,194,162,237,157,227,218,251,182,104,219,246,204,229,159, 36,234,208,
+162, 57, 21, 95, 71,205,211,145,209, 81,237,111,209, 53,160, 93,124, 68,124, 34,222,218, 80,131,244,141,234, 30,227,188, 96,109,
+103, 24,103,206,184,227, 46, 85,199,199, 44, 13,154, 87,249, 82,224, 16, 9,246,215, 62,231,128, 55, 21,218,186,192,231,180, 71,
+ 32, 65, 98, 79, 72, 54,141,102,194,192,106,225,196,208, 19, 6,144,193, 84,115,169, 10, 42,143,115,238, 13,163, 98,104, 14,239,
+146, 49,253, 65, 97, 5,209,219, 81, 64, 11, 1,211, 86,229,122,153,180,111,187, 78,251, 11,207,180,101,166, 84,113,182,137, 52,
+ 92, 20,110,118,117, 96, 24,125, 34,163, 5,162,248, 83,197, 49,121,211, 96,201,199,202, 78,174, 52,169, 52,119, 42, 94, 54, 14,
+186,148,217,133,212,158, 32,213, 33,146,223,127, 15,225,222,247, 89,247, 71,206,104, 90,125, 23,140, 70, 24, 13, 8,177,243,212,
+ 63, 86,181,210,181,172, 60,232,134,154,224, 90,244, 2,175, 5, 20,224,120,211, 11, 1, 96, 77, 45,252,111, 64,116,158, 3,205,
+133, 16, 80, 93,192,101,185,241,185,165,235,167,135, 26, 0,132,248, 87, 83, 75,139,113,166,180,168,167,199,235,169, 81, 65,205,
+243,160,247,211,234, 57,152,106, 4,120, 95,242,209, 67,210,162,129, 57,210,129, 65, 50,168, 23,176,161,182, 72, 3,149, 81, 66,
+ 93,141,185, 83, 73,183, 62, 20, 8,242, 75,181,173, 97,231, 68, 47, 97,122,141,162,209,131,146, 62, 44,247,247, 81,146,193, 84,
+ 95,194,129, 52,224, 13, 35,141,249,211, 61, 83, 0, 5,185, 81, 2, 95, 1, 92, 8,191,230,160,195, 43, 63, 19,202,139,126, 23,
+ 28,234, 57, 36, 54,177,228,208,225,182,146, 65,191, 19, 76,146,112,162,222, 38,132,179, 21, 22, 90,169,212,148, 38, 11,223,145,
+252,148,172, 65, 53, 22, 44,130,196, 6,163,131,122,160,122,219,207,242, 82, 30,124, 43,133,113,160, 23,194,133, 3, 11, 55, 11,
+113,163,120, 94,131,143,196, 48,246,208, 5, 23,165,183,157,119, 35, 92,108, 5,205, 8, 41, 21,192,208,250,171,107, 95,149,119,
+ 85,104, 82,109,255, 0,113,203,251,159,251,106,234,103, 84,116, 47,254,230,255, 0,251,235, 87, 80, 8,242,201,100,227,253,220,
+100,240, 30, 40,180,206,163,249,215, 56,254,207,254, 28,127,212, 90,101, 10, 11, 34, 73, 53,128, 27,133,188,133, 8, 75, 37,143,
+ 27,159,104,174,201, 39, 88,247,127, 25,160,113,170, 15,154,179,114, 38,139,187, 59,216, 69,181, 13,212,207,247,156, 79,117,213,
+233, 85,178,110,115, 0,210,220, 98,183, 3,194,215,231, 73,155, 46,223,255, 0,219, 28, 28,108, 57,222, 89,151,118,121,115, 18,
+ 69,210, 99,145,241,202,133, 78, 45,116,210,130,199,206,245,182,201,252, 53,239,104,247,221,247,116,218, 55, 12, 12,120,183,151,
+202,141,245,180,134, 79, 77,149, 47, 84,161, 29, 6, 10,214, 3,145,247, 26, 92,159,193,205,197, 59, 98, 45,167, 3, 55, 30, 77,
+193,242,198, 94, 92,211, 23,142, 45, 43, 27, 70,177,199,161, 36, 99,109, 87,185, 2,160, 3,220,189,247,186,224, 63,110,246,222,
+ 30,233,247, 38, 16,219,177,101,205,220, 86, 35, 51,130,241,124, 35, 74,134,109, 35, 72,249,124,234,157,255, 0, 20,123,198,110,
+207, 89, 23,112, 49,231, 99,230,174, 60,153, 75, 28, 90,228,134, 72,154, 68, 12, 74, 27, 50,180,103,136,177, 53,177,238, 47,195,
+141,235, 38,125,155,121,216,114,224,135,120,219, 49, 96,198,153, 38,185,137,204, 11,167, 90, 18,141,126,101,108,203, 98, 40, 91,
+247, 98,119,175,115,108, 17,225,238, 89, 59,114,231,166, 96,200, 2, 32,209, 66,144,136,140,122, 47, 28, 36,151,214,196,241, 31,
+ 77, 1, 77,219,221,225,221,216, 93,235,129,182,239,219,136,202,195,201,197, 73,101,137, 20,104, 17,190, 47,170, 70, 31, 10,182,
+181,176,185,241,227, 89,174,226,238,110,234,238,237,147,112,221,178,242,146, 45,150, 44,200,160,143,110, 85, 81,102,112,242, 39,
+196, 23, 81,208, 23,137, 39,141,235,208,163,252, 55,222, 63,205,251,118,249, 60,216,173,129,141,139, 6, 46, 68, 65,228,234,183,
+ 79, 23,210,190,129,210,211,107,242,187,114,172,255, 0,255, 0,104,123,194, 60, 28,237,155, 27,114,195, 27,108,185, 9,145, 18,
+ 72, 94,242, 52,122,145, 25,200,137,138, 29, 15,196, 11,241,250,232, 8,217,189,235,184,224, 97,118,191,110, 98,110,159,114, 97,
+125,221,143, 54,110,226,177, 25,156, 23, 82, 84,104, 80,205,164,105, 31, 47,159,178,162,183,226,103,118, 75,217,194, 85,207, 49,
+231, 65,154,184,242,101, 44,113,106,146, 25, 34,119, 80,215, 67,102, 86,140,252, 66,198,181,123,167,225,150,250, 19, 97,220,246,
+ 76,204,120,119,173,167, 22, 28, 89,214, 77, 70, 25, 12, 32,217,208,180,109,126, 12, 84,134, 91, 17, 69,223,251, 23,189,187,155,
+ 96,139, 11,115,201,219,151, 61,115, 6, 66,136,131,197, 10, 66, 34, 49,232,188,112,146, 95, 91, 19,196,125, 53, 1,161,236, 15,
+243,118, 82,229,238,189,205, 39,248,108,232,241,165,218,224, 86, 86, 17,198, 85,203,106, 11,199, 81, 93, 4,222,179, 63,138, 29,
+153,219,120,155,118,239,221, 89,217, 19, 13,207, 41,227, 24,138, 92, 4,234, 89, 81, 98, 68,211,198,234,164,155,154,244,221,167,
+ 30, 76, 13,175, 7, 6, 98, 26, 76,108,120,161,145,146,229, 75, 70,138,132,169, 32, 27, 92,121, 87,157,126, 32,118, 55,121,119,
+142,237, 28,208,101, 96,195,182, 98, 11, 97, 99,203, 36,183,185,177,121, 36, 81, 3, 46,166, 35,151, 17,111,166,128,208,254, 23,
+ 46,228,189,145,182,253,228, 88,185, 14,113,196,151,212, 32, 46,122, 87,191,134,159,151,249, 54,172,183,226,135,102,118,222, 46,
+221,187,119, 94,118, 68,195,116,202,120,198, 34,151, 1, 58,150, 84, 88,145, 52,241,186,169, 38,230,173,165,237,255, 0,196,166,
+237,168, 48, 34,222,241,211,120,143, 41,164,147, 41, 89,150, 51,141,211,210,145, 46,156,127, 6,227,109, 31, 77, 87,247,215, 98,
+119,183,120,110, 16, 72,153,152, 17,224, 97,160, 92, 88, 36,146, 98, 75,216,117, 37,145, 70, 59, 46,166, 35,234,250,104, 8, 47,
+183,247, 6,127,224,158, 22, 8,197,159, 51, 55, 38,116, 24,209, 34, 52,146,250, 97, 43, 73, 29,192, 4,133, 10,156, 9,225,166,
+213,223,131,249, 29,175,143,190,190,220,118,188,157,187,185, 99,197,108,121,206, 68,134, 68,144,161, 67, 61,163,101, 67, 19,234,
+ 75,233,177,176,184,189,108, 32,217,127, 18, 32,237, 56,113, 32,222,240,255, 0,204, 16,102,117,186,231,251, 6,196,233, 24,198,
+ 57, 6, 1,199, 83, 95,228,240,231, 80,123, 27,240,251,118,218,251,135, 43,187,251,171, 58, 12,173,214,112,250, 18, 3,240,134,
+151,131,187, 29, 49,139,233,248, 64, 81,106, 2,235,241, 22, 20,201,217,176,241, 4, 97,211, 47,116,219,241,221, 77,184,134,200,
+ 78, 28,124,237, 89, 61,165,223, 51,180,246,142,202,148,235,202, 27,219,108,249,163,244,140, 24, 18,182,108,191,251,152,213,107,
+115,220,251, 62, 86,246,155, 66,225,203, 10, 12, 45,215, 19, 63, 32,204,204, 47, 14, 59, 51,186,199,161, 94,238,120, 88, 27, 15,
+109, 85,237,189,153, 54, 23,226, 6,127,116, 62, 68, 45,181, 76,175, 38, 30, 40,102,234, 38, 76,233, 12,115,200,192,168, 95,136,
+ 70,220,155,198,128,206,118,134,122, 97,126, 26,118,249,109,235,238,115, 35,229,160,104,241,215, 47, 34,102,245, 19,105,142, 24,
+153,100, 55, 28,205,144,209,240, 59,223,124,155,182,158, 49,211,159,124,151,124,110,222,194,203,158, 3, 7,130,191,169,159, 31,
+225,208,202,164,221, 45,192,218,227,157, 38,201,216,157,209,219,184,251, 12,248, 83,237,249, 27,142,209,235, 34,151, 30,105, 37,
+244,239, 22, 91,107,234, 71, 32,136, 50,186,248,252, 60,106, 92, 93,137,189,141,155, 55,173,157,134,155,233,223,100,238, 29,186,
+120,117,182, 56,145,130, 14,156,170,224, 56, 86,179, 92, 13, 86,225,196,208, 27, 61,143,108,221, 48,113,221,119,141,207,239,105,
+ 89,181, 71, 41,199,143, 27, 74,219,228,211, 23, 3,199,198,179, 27, 84, 17,102,254, 36,119, 62, 94, 74,131, 46,211,137,131,141,
+129,171,142,152,242, 34,105,229,100,191, 47,136, 90,226,180,219, 36,251,251,193, 35,119, 26, 97, 65, 53,192,134, 60, 41, 36,144,
+ 88, 14, 37,218, 85, 94,103,144, 30, 21, 69,190,236, 91,196, 59,233,238,126,216,155, 24,228,207, 2,226,238, 56, 25,101,150, 41,
+209, 27, 84,114, 35,198, 24,172,139,203,136,181,168, 12,230,239,182, 9,251,219,116,218,112,159,211,141,255, 0, 98,144,229, 20,
+224, 58,203, 33,134, 57,156, 14,127, 11,105, 53, 51,180,247,185,113,101,195,236,222,224,192, 27,126,235,135, 8, 92, 23, 64, 27,
+ 31, 38, 56, 83, 73,146, 7, 28,155, 69,203, 15,127,186,164,237,251, 6,255, 0, 30,102,229,220, 89,249, 24,173,191,229,227,140,
+ 92, 24,227, 14,216,184,209, 41,234, 44,100,157, 46,225,159,139,126, 74,100, 27, 47,113,238,155,246,223,188,119, 31,163,199,131,
+104, 18,156, 76,124, 38,146, 70,146, 89,151,166,207, 35,200,169,165, 64,228, 7,211, 84, 22, 29,231,182,226,110,189,181,184,227,
+102, 72, 32, 72,226,105,227,201,110, 29, 41, 33, 29, 68,146,227,143, 2, 56,251, 42,143,240,198, 73, 55,204, 76,222,230,206,149,
+102,221,179, 36, 92,108,144,162,221, 20,198, 85, 68,139, 79,134,171,235, 62,250,188,238,109,155, 63,184, 97,196,218,241,222, 56,
+240, 36,200, 71,221, 67, 22, 18, 73, 4,100, 63, 70, 48, 20,143,140,143,136,146, 56, 81, 54,206,217,205,217,187,183, 59,116,219,
+228,132,108,187,164, 40,115, 49, 73,101,145,114,227,186,172,177, 40, 82,154, 89,121,252, 67,159,178,128,167,239,169,101,193,238,
+ 30,208,200,131, 26, 76,201, 83, 35, 40,174, 52, 37, 68,142,122, 32, 89, 76,140,171,227,126, 38,160,236,123,212, 88,123,143,122,
+247, 30,118, 59, 96,238, 17,195, 20,210,108,206, 8,144, 69,141, 19,116,228,118, 3, 67,153, 79,138,220, 15, 62, 53,164,238,237,
+147,120,220,119, 45,139,115,217, 78, 41,151,105,150,121, 94, 60,199,146, 53,126,172, 98, 48, 1,138, 57, 15,157, 67,193,236,252,
+220,204,189,235,115,238,105,161,124,173,227, 23,238,243,143,134, 27,165, 14, 62,155, 29, 47, 40, 12,204, 79, 27,216,125,144, 25,
+253,167,188,183,172,188,205,174, 8,247,168,242,229,222,163,146, 60,136, 23, 8,170,237,243,188, 69,224,146, 38, 42,157, 85, 71,
+178,176,119, 55,243,166,118, 68,187,142,219,217, 50,103,101,119, 2,109,248, 77,149, 34, 66,199, 21, 25,163, 97, 52,130, 64,154,
+139,117, 30, 83,242,141, 63, 15,145,173, 79,111,226,119,182,212, 48,246,173,197,182,249,182,220, 52, 16,250,216,204,190,162, 72,
+163, 66,177, 14,145, 1, 21,248, 46,162, 91,235,170, 12,110,202,238,220, 76, 12, 92,108,105, 48, 95,238, 77,197,183, 29,179, 91,
+ 75,108,129, 35, 59, 50, 78,186, 62, 6, 93,127, 9, 23,241,247,213, 5,215, 97,247, 22,231,186,238, 59,238,213,184,100,190,106,
+109,143,140,216,185,115,227,122, 57,222, 60,148,121, 45, 36, 26, 99,181,180,112, 58, 69,199, 26,219, 72,108,181,146,237,109,155,
+123,193,223,119,253,243,124,124, 94,174,241,232,202, 71,136,210, 16,158,154, 55,136,171,117, 85,124,197,143,143, 59, 14, 85,167,
+121, 53, 18, 7, 47, 10, 16,225,118,109, 84, 86, 33, 84,147,202,152, 62, 21, 3,198,154,236, 8,177,227, 88,226,205,112, 1,169,
+152,147, 68,137, 73, 37,141,114,128,105,247, 0,240,229, 90,124, 2, 30,196, 42, 18, 69, 69,212, 77,205, 22, 66, 24, 1,199,219,
+ 67, 10, 42, 37, 64,199,196,186,141,219,144,169, 41,202,244, 37,210,160, 11, 87, 51, 0,156, 47,168,253,149, 29, 91, 40, 41,100,
+ 37,248,114, 20,210, 88,240,243,166, 26, 52, 74,163,226, 63, 69,107,130, 32, 88,215, 66,138,123,182,133,185,181, 15, 80,252,212,
+ 41,157, 89,180,142, 67,248,107, 20,171, 40,203,234, 36,154, 85, 93, 76, 22,152, 42, 76, 10, 0, 44, 71, 18,120, 86,219,162, 32,
+101, 1, 64, 11,225, 69,102,208,183, 39,128, 20, 27,175,151, 14, 52, 60,137, 20,252, 11,244,154,230,149, 89, 64,187, 23,114,198,
+187,144, 28,105,167,216, 40,208,162,146, 25,135, 1, 93, 56, 35, 33, 32,138,194,231,153,163, 41,177,181, 55, 82,248,112, 30, 53,
+204, 80, 2,199,152, 21,132,221,124,205, 53,160,117, 35,133, 57,173,107,147,202,162,166, 66, 0,111,196,249, 80,222,102,144,241,
+224,190, 85,208,197, 3,174, 72,107,171, 11, 15, 3, 86, 24,219,111,238, 86, 94,175,246,128, 61,180,242,184,191,157, 82,151, 26,
+ 74, 91,230, 35,141,107, 32, 83, 28, 17, 68,220,209, 21, 77,185,112, 22,164,117, 15, 68, 65,108, 27,113,234,127,209,252,245, 95,
+ 54,174,155, 91,199,133, 94,205,196,112,172,236,185, 9,121, 33,253, 37, 98,191, 81,181, 86,169, 66, 46, 8, 67, 10,136,245,245,
+152,157, 55, 85, 28,239, 76,253,206,139,137, 36, 47,226,188, 62,202, 65, 35, 70,203, 33,143,225, 81,166,231,145,166, 68,197,174,
+109,196,155,214,106,106,133,143, 77,125, 7, 83, 91,107,232, 90,222,206,190,171,215, 82,220,250, 45, 55,254,227,159,252,251, 87,
+ 85,168,160,233, 7,246,127,240,227,254,162,208,233,242,127,119,255, 0, 14, 63,234, 45, 50,128,139,147,109, 99,221,252,102,128,
+121, 81,242,127,180, 30,239,227, 52, 30, 85, 65,145, 29,253,183, 42, 35, 73, 3,169,108, 28,173,193,248,130, 23,210, 52,136,240,
+147,250,196,194,246,247, 85,212,123,254,221, 35,250, 83, 40, 92,229,139,171, 38, 39, 27,171, 8,196,205, 30,171, 5, 46, 21,174,
+ 87,157,184,218,213,143,203,252, 62,220, 39,151, 53,147, 34, 5, 76,141,196, 77, 18,146,255, 0, 14, 4,135, 37,178, 49,216, 4,
+249,139,102, 72, 85, 71, 14, 92,106,205,123, 83, 48,119, 14, 70,224, 66, 62, 59,207, 62, 92, 51, 62, 70, 69,213,167,198,244,189,
+ 49,136, 15, 65, 88, 18,215,147,137, 43,194,222, 64, 92, 97,119, 78,209,147, 22,220,100,157,113,242, 55, 44,120, 50,161,199,123,
+221, 87, 33,117, 70,174,192,105, 5,184,133,185,248,136,225, 68,135,186, 59,126,124,121, 50,226,220, 35,104, 34,104,209,228,248,
+128,188,231, 76, 54,184,185, 18, 31,148,142, 7,194,179,184,125,169,188, 97,195, 6, 7,248, 73,113,231,194,219,177,115,167,114,
+204,209, 54, 12,109, 28,134, 4,100,248,203, 92,116,216,149,210,120,218,186, 30,211,221,228, 24,210,100,182, 60, 82,226, 13,163,
+ 29, 86, 55,118, 71,135,107,200, 57, 18, 74,111, 24, 33,228, 12, 66,167,135,139, 80, 26, 28,110,232,216, 50,186,134, 12,244,101,
+134, 23,201,148,176,100, 11, 20,103, 76,142, 75,170,252,135,131, 14,107,227, 83,113,119, 61,191, 51, 18, 76,236,105,131,227,197,
+168, 74,214, 96, 80,160,187, 43, 35, 0,192,129,198,196, 86, 58, 78,201,220,165,197,147, 28,207, 2,151,196,221, 49,213,131, 73,
+253,166,110,122,103, 65,201, 65,210, 21, 44,228,113, 7,149,235, 69,219, 59, 84,251, 86, 54, 87,168,141, 97,151, 47, 37,178, 90,
+ 49,145, 62, 91, 11,164,113, 14,164,249, 68,187,181,163, 30, 67,195,219, 81,128,123,103,121,108, 27,164, 59,124,139,144, 32,155,
+113, 72,228,135, 30, 80, 67,142,171, 20, 69,114, 1, 80, 89,148,170,241,248,143, 43,210,247, 39,119,109,253,183, 32,131, 38, 55,
+150,102,196,200,205, 85, 65,192,174, 54,155,173,207,139,106, 54,247,113,240,172,238,217,217,155,214, 38, 38, 62,221, 59, 99, 24,
+ 92,109,169,149, 60,114,185,100, 27, 92,253,101, 49,171, 68,186,186,202, 20,113, 35, 73,191,205, 86,189,235,219,219,151,112,116,
+254,238,120, 23,252, 22,126, 20,158,161,221, 45,234,196, 58, 29,116, 71, 37,244,180, 60, 71, 14, 7,232,168, 11,100,238, 45,179,
+ 34, 76,113,137, 60,114, 69, 44,242,227, 75, 35, 49,140,163,195, 11,100,176,210,234, 53,124, 42, 15,135,194,117,114,169, 27,126,
+243,181,238,145, 75, 62, 6, 74,205, 28, 54, 50,155, 50,149, 12,186,213,172,224, 29, 44,188, 84,242, 35,149,103,228,237,141,201,
+183, 41, 51,145,241,217, 27,114,200,207, 84,147, 91, 3, 28,219,103,221,234,174,161, 69,207, 83,139, 11,252,190, 55,225, 70,237,
+189,147,114,219,112,243,241,242,132,113, 36,234,145,226,227, 36,210,100, 44, 65, 99, 40,192, 77, 50, 44,157, 61, 95, 34, 27,233,
+ 95,170,128,177, 94,234,237,215,130, 25,215, 62, 51, 22, 65, 34, 25, 0,109, 44, 6,141, 77,123,112, 65,212, 91,177,248, 65, 54,
+189,114,119, 46,217, 23,175, 57,143,233,151, 11, 48,224, 93,174,198, 73, 4, 17,229, 18,138,128,181,130, 73,199,135, 11, 19,202,
+179, 57,253,147,159,145,183,108,248, 71,165, 57,198,218,147,105,204, 79, 83,147,143, 16, 32, 69,170, 95,240,218, 26,116,248, 27,
+247,111,107,240,169, 27,151,105,110, 83,205,149,153, 19, 71, 41,147,114,151, 54, 56, 6, 84,248,133,162,155, 10, 44, 43, 60,248,
+192, 58,178,188,122,138,139,134, 94, 23,240,160, 53, 35,125,217, 83, 43, 31, 4,230, 71,234,178, 85, 26, 37, 82, 88, 17, 40, 45,
+ 21,221, 65, 81,212, 10,116,220,252, 94, 21, 28,247, 71,111,234,200,182,108,127,225,172,178,216, 55, 18,100,232,254,239,225,253,
+231,239, 62, 15,130,255, 0, 23, 14,117,158,147,180,247,117,204,218,196, 47,143,232,118,213,219,122, 72, 39,154, 37, 83,133,117,
+153,122, 65, 36,234, 22, 91,104,105, 24,145,107,112,189,234, 52,189,155,188, 76,211,181,241,160,141,101,139, 34, 60, 76,124,169,
+209, 37,145, 50,125, 68,141, 12,154,122,184, 98, 68, 63, 44,108, 70,190, 62,218, 3,114,155,142,222,219,127,222,163, 34, 63,187,
+214, 54,153,178,137,248, 21, 18,250,203, 19,203, 77,141,252,170,155, 51,188,182,152, 83,111,244,108, 51, 27,112,204, 24, 49, 1,
+170, 62,155,132, 50, 72,210, 6, 77, 67, 74,219,225, 34,230,227,195,141, 53, 59,117,191,201,179,118,222,184,160,200,153, 39, 35,
+ 76,146,205, 18,203, 52,175,144, 53, 73, 57, 50,184,212,223, 19, 30, 39,137,176,229, 81,211, 96,220, 39,207,139,118,201,104, 33,
+200,147,120, 77,207, 35, 25, 36,105, 17, 34,139, 1,182,245, 68,126,154,106,114,108,198,224, 15,171,136, 19,119, 94,245,218,182,
+141,205,246,156,148,115, 60, 67, 12,200,225,108,161,115, 39,244,192,159,230,124,199,216,120,113,169,239,220,253,187,208,198,203,
+ 25,136,144,230, 23,244,238, 67, 11,136,216, 69, 33, 96, 69,208, 43,252, 44, 90,214, 60, 13, 83,239,221,189,159,185,119, 4, 91,
+158, 44,152,227, 22,219,103, 88, 72,238,178, 41,219,243,155, 53,180,170,198,234,218,210, 66, 5,216,113, 30,219,138,108,206,197,
+207,154, 8, 96,102,135, 32, 58,238, 16, 79, 31,170,202,199,141, 83, 55, 53,179, 35,145,134, 54,134,152, 8,219, 75, 70,214, 26,
+173,199,198,128,216,111, 91,195,109,146, 96, 99, 67,136,114,178,119, 25, 94, 8, 81, 93, 99, 0,199, 12,153, 12, 89,159,135,203,
+ 25,170,140,126,243,219,115,224,150,103,141,241, 35,199,135, 22,121, 26, 82, 15, 28,151,158, 21,137, 4,122,181, 29,112, 16, 52,
+223, 85,197,170, 79,117,236,210,111,111,181, 75, 14, 38, 30,225, 30, 6, 68,147,100, 96,238, 12,201, 12,170,240, 75, 2,241, 16,
+100,139,171, 72, 27,138,120, 86,105,123, 11,115,143, 18,104,206, 68,114,145,232, 30, 8, 99,154,104, 63,238,153, 57, 83,182, 58,
+204,171,212,141, 86, 60,133,142, 39, 94, 63, 15, 16, 40, 13, 4,253,207,176,227, 65, 14, 68,249,177,172, 83,163, 75, 19,124, 70,
+232,140, 17,219,225, 4,128,172,192, 53,249,120,208,231,238, 45,190, 61,227, 27,100,141,250,185, 83,202,240,200,171,202, 34,152,
+239,151,241,146, 45,242, 40,224, 15, 11,139,213, 52,253,139,159, 38,218,112,225,108,120, 93,246,189,199, 8,169,150,121, 20,100,
+103,100,199,148,167,169, 42,188,142,163, 75,106, 99,196,159,209,242,153, 47,106,110, 82,111, 38, 69,108,117,219, 78,110, 78,113,
+159, 91,245,255, 0,197, 96,190, 23, 76, 69,163, 77,209,219, 85,245,241, 30,218,160,184,199,238, 62,222, 24,146,103, 46,124, 93,
+ 8,217, 18, 73,141,192, 6, 83,104,173,112, 9, 87,253, 22, 28, 27,194,143,184,111, 13,141, 22, 36,152, 88,146,231, 62,105,253,
+202, 71,104,212, 38,131, 41,121, 94, 93, 42,131, 72,183, 30, 55, 54,172,174,217,217,123,142, 62, 44,113, 74, 33,142,116,159,105,
+103,115,149,147,148,100,139,109,155,170,237,171, 32, 29, 26,174,221, 56,213, 64, 30, 39,203, 67,221, 24, 27,190,229,137, 22, 30,
+217,210, 48, 73, 39,255, 0, 81,138, 89,228,198,105, 96,210,111, 10, 77, 12, 83,178,235,107,106, 32, 95, 77,192, 60,106, 1,205,
+220, 17, 79,179, 97,239, 56, 56,211,101, 46,114,194,216,216,234,160, 72, 78, 65, 93, 58,201, 58, 80, 45,238,204, 77,128,243,167,
+224,111,184,121, 91, 92,219,180,255, 0,224,225,198,105,162,202, 19, 17,251,183,199,145,161,148,106, 82, 85,134,164, 54, 35,157,
+ 67,220,113,123,146, 77,177,240,182,184,240,240, 36,233, 99,199, 8,142,105, 0,141, 67, 17,145, 28,111,233,254, 27, 70, 2,196,
+221, 63,109,133,133, 56,109, 19,255, 0,149,229,217,227,192,195,133,250,102, 36,194,105,101,159, 24,173,238,117,205,211,134, 82,
+206, 46, 75,105,190,174, 60,104, 3,183,115,108, 26, 33,149,179,145, 86, 98,232,161,131, 43, 6, 66,170,253, 69,101, 13, 30,146,
+235,114,224, 90,227,206,159, 47,113,237,144,206,216, 49, 79, 28,185,113,207, 14, 60,240,150, 41,160,207, 36,113,139,182,146, 53,
+126,244, 21, 95,210,172,126, 79, 99,111, 25, 42,163, 37,163,156, 77, 30, 70, 59,193, 46,110, 82,244,162,154, 72,221, 58,211, 64,
+ 34,124,189, 42,140, 25,100,181,248,113,225,122,191,155,182,179,159,215,105,146, 17,234,119,204, 61,217, 46, 91,132, 24,254,147,
+ 90, 55,193,243,159, 78,214, 28,185,113,170, 66,203,252,197,177, 95, 48, 54,100,119,194, 12,217, 4,146, 2,172,109,161,200, 36,
+ 89,180,176,210,116,222,199,135, 58, 54,223,159,137,185, 66,114,176,164, 18,196, 24,161,224, 84,171,175,204,174,174, 3, 41, 30,
+ 68, 86, 55, 31,179,115,241,206,122, 52, 56,217, 37,225,201,199,199,108,156,156,169, 82,100,201,201, 25, 58, 90, 27,132,199, 26,
+ 84, 3,211, 4,234,248,189,247,253,191,129,188,237, 88,222,159, 56,196,240, 72,211, 75,198, 87,154,116, 44,201,209,141,165,120,
+211,171,100,213,169,219,226,189,135, 17,198,163,232, 84, 92, 73, 35, 95,133, 8,200,254,116,101, 94, 28,104,110,151,114, 47, 96,
+ 40, 81,162, 87, 30, 53,221, 87,243,165,233,143,214, 20,189, 17,250,226,169, 6,117, 31,206,148, 72,227,198,159,208, 4,145,168,
+123, 41,166, 34, 60, 71,215, 64,119, 90, 79, 58,225, 43,147, 98,120, 83,122,109, 72, 84,142, 98,128, 35,176, 91,105,125, 87,231,
+194,212,157,103,229,229, 73, 24, 12,224, 30, 70,164,140,120,205, 1, 27,170,244,154,216,212,191, 74,150,246,215,122, 69,243,160,
+ 34,235,106,120,158, 75, 88, 84,147,134,131,145,164,244,131,206,160, 1,215,147,217, 77,234, 57,230, 5, 24, 66, 10,145,229,115,
+122,238,128,181,252,169, 64, 15, 91, 83,196,206, 6,144, 5, 44,152,228,241, 83,111, 10,142,225,209,180,183, 58, 80, 19,213,181,
+ 1,127,244,246, 80, 37,144,147,164,114, 20, 52,144,162,216,159,155,149,117, 69, 29, 75, 80,248,232,146,181,157,138,249, 90,165,
+140, 8, 79, 30,179,125, 66,171,145,138,176,177,171, 40, 95, 82,251,107, 70, 89, 83, 54,243,218, 88,211,201,143,145,220, 56, 48,
+207, 19, 24,228,138, 76,152, 17,149,212,217,149,213,156, 21, 32,243,189, 93,158,245,236,187, 15,255, 0,216,246,191,255, 0,157,
+199,255, 0,226, 87,207,216,221,191,181,231,111, 93,245,190,229,237, 51,119, 30, 86,219,185,188,120,251, 30, 60,146, 70,204,179,
+228, 74, 31, 33,250, 23,148,170,105,183,195,244,214,119,186,251, 83,104,219,123,231, 19, 98,197,103,194,194,205, 92, 73,102,198,
+153,195,203,134,217, 42,173, 38, 51,191,139, 37,249,154,142, 74, 49,114,124, 18,171,246, 21, 69,201,168,174, 45,209,123, 79,167,
+159,189,123, 54,252, 59,139,108,183,254,119, 31,255, 0,137, 84, 25,125,199,218, 6, 89,101, 94,226,219,137,102, 44, 0,203,128,
+243, 55,253,122,249,243,184,182, 61,186, 29,163, 47, 54, 45,174,109,154,108, 28,181,197,132, 77, 35, 56,202, 70,213,118, 2, 79,
+210, 93, 55, 37,120, 86,191,181,187, 23,183,179, 54,190,221,130,125,139, 43,118,255, 0, 48,197, 44,153,221,195, 4,238,145,237,
+204,140,201,160, 34, 3, 31,238,244,221,250,156,252, 60,171, 54,175,198,244, 55, 69, 53, 71, 77,105,249, 85, 29, 46,218,149,169,
+ 40,182,157, 85,116,175,231, 70,123, 6,219,185,237,155,196, 36,237,217,176,230, 69, 13,150, 65,143, 42, 75,102, 60, 70,163, 27,
+ 53,170, 98,198, 2,234,142,224,159, 3, 94, 77,248, 33,233,240,241,187,130, 30,186, 60,105,151, 28,113,205,112, 3,133, 87, 26,
+133,252,199, 26,245,213,101,146, 32,200,193,131,139,171, 3,112, 65,228, 65, 21,163,153, 34,255, 0,224,191,149,209,255, 0,230,
+ 43,169,122,103,211,105,176,191, 66,223,251,251,215, 80, 10,227,132,127,240,227,254,162,211,105,207,250, 31,240,227,254,162,211,
+ 43, 64,139,147,243,143,119,241,154, 1,189,232,249, 35,227, 30,239,227, 52, 43, 80, 30,107, 47,120,239,209,224,103,102, 99,202,
+153, 15, 2,110,109, 44,126,157,130, 98,250, 73,100,143, 29,140,163,224,109,122, 0, 42,120,159, 14, 70,180,131,188,240, 27,127,
+125,129, 80, 60,234,242, 64,129, 37, 70,153,165,138, 15, 84,223,225,239,172, 38,144, 84, 57,224, 88, 91,219, 83,155,182,176, 91,
+ 97,202,237,227, 36,222,147, 47,212,245, 36,212,189, 65,234,229,146,121, 52,157, 58,120, 52,135, 79,195,203,206,147,252,185,142,
+ 51,242,114,253, 94, 74,193,146,210, 75, 38, 18,178,136,186,211, 68, 49,228,146,225,117,155,160,224,165,172, 15, 27, 80, 21, 17,
+247,222, 59, 96,230,101, 54, 40, 89, 48,228,198,138, 69, 19,198,209, 39,170,224,173, 60,233,117,143,166,110, 36,224,116,145,227,
+ 78, 29,251,128,185,248, 88, 19,192, 33,155, 47,211,171, 70,243, 71,212, 15,150,237, 20, 93, 40,193,188,171,112, 11, 50,240, 10,
+ 65,247, 72,195,236,216,176,113,222, 44,109,207, 49, 36, 41,143, 24,148, 24, 71,195,136, 25, 34, 82,139, 16, 70, 82,143,165,213,
+129, 7,159, 62, 52, 76, 46,206,194,219,165,199,108, 44,188,168,162,136, 67,214,129, 94, 48,179,182, 59,188,145, 52,164, 70, 8,
+248,164, 55, 84, 42,167,128,181,168, 9, 27,182,251, 38,223,155, 22, 14, 46, 4,185,243, 24, 95, 46,116,136,128,201, 12,110,145,
+146,138, 71,239, 28,151,224,163,203,157, 82,237,253,241, 36, 88,185, 47,187,227, 16, 32,139,112,202,143, 34, 54, 80, 36,143, 11,
+ 52,226,116,244, 27,105, 63, 18, 11,147,199,137,225, 87,187,183,111,197,186,228, 69,148, 50,167,195,149, 98,108,105,155, 25,149,
+ 76,144, 59, 36,141, 25, 44,172, 87,226,140, 89,146,199,159, 26,137,254, 75,218, 90, 23,133,164,157,145,224,205,198, 63, 26,220,
+ 46,126, 64,205,145,129, 9,243, 36,138, 52,123, 57,222,163, 0, 49,251,218, 44,236,104,142,219,136, 51,115,100,202,151, 12, 67,
+ 4,232,240,150,134, 1,148,238,153, 10, 10,178,244,216, 90,195,230, 54,243, 52,221,139,187, 31,116,222,115, 54,119,133,189, 68,
+115, 25, 4, 44, 4,111,141,137,233,241,164, 6,112,110,117,153,102, 40, 0,246,249, 84,217,187, 91,173, 4,122,183, 60,191, 95,
+ 20,242,100, 46,225,120,186,129,165,136,227,200,138,157, 62,146,166,131,192, 5,224,120,243,174,194,236,237,183, 3, 46, 60,252,
+105, 39, 25, 81,205,215,235,179, 43, 59, 41,199,143, 17,161,145,153, 9,104,217, 98, 86, 55,227,171,141,234, 2,183,127,238,125,
+235,110,223, 91,108,196,198, 70,199, 81,181,148, 98, 70,167, 57,153,141,141, 34,241, 60, 53, 42,233, 30, 68, 95,198,147, 39,241,
+ 27,110,193,194,198,202,204,128, 66,210,140,151,158, 23,158, 53, 42, 49, 39, 56,146,172, 58,244,245,156,186,146,170,163,136, 30,
+ 21,115,185,118,198, 38,231,186, 71,186,205, 60,241,203, 24,197, 13, 20,101, 4,111,232,242, 61,100, 37,181,198,205,193,201, 6,
+204, 46, 15,184,212,115,217,184,136,144,174, 54,102, 86, 49, 79, 82,178,188, 76,129,229,139, 47, 32,230, 75, 19, 49,143,225, 2,
+ 67,240,178, 89,128,225,127, 26, 3,187,175,119,201,218,229,218, 98,131, 35,210,197,153,145, 36, 89, 19,172, 13,146,202,169,143,
+ 44,203,166, 36, 4,155,180, 99,144,229, 84,221,189,220,251,182,237,184,227, 99,229,100,180, 72,248,216,115,175,164,193,147, 37,
+ 36, 57, 18, 78,133,166,146, 37,145,113,195, 44, 74,126, 50, 52,220,254,169,182,199, 47,110,131, 51, 55, 3, 54, 86,113, 38,221,
+ 43,205, 0, 82, 2,150,146, 25, 49,136,123,130, 72,211, 41,229,110, 53, 87,182,118,132, 59, 94, 89,201,219,119, 76,220, 93,106,
+137, 60, 75,233,157, 37, 84,150,105,213, 91,171,140,236, 5,231,113,240, 17,195,219,198,128,162,206,239,125,202, 9, 59,145,161,
+104, 58, 24,248,217,114,236,163, 69,200,125,185,151, 31, 35, 89,191,197,170, 71,184,246, 81,187,131,184,187,147,105,131,117,219,
+113,165,135, 39,115,197,151,109,244, 89, 38, 16,161,147,112,149,224,209, 36, 97,136, 44,173, 17,226, 45,192,138,179,159,240,235,
+183,102,219,225,193, 13, 44, 45, 20,115,195, 46,100, 93, 21,200,157,114, 81,163,148,228, 73,210, 58,201,213,171,151,204, 7,186,
+166,142,213,192,102,105, 50,243,114, 50,178,229,202,197,204,151, 50,102,136, 72,205,130,226, 88, 35,211, 12, 81,198,177,130, 56,
+133, 64,120,158, 55,227, 64,101, 51,187,255, 0,115,151, 39,117,200,218,204, 71,110,199,217, 31, 63, 16,148,212,125, 82, 38, 36,
+247, 45,250, 74, 19, 49, 69,188,235,111,178,229, 73, 62, 20,249, 18,205,147,150, 81,155, 72,159, 10, 76, 25,126, 21, 13,165, 33,
+200, 72,153,175,126, 13,107, 95,133,248, 85, 34,126, 31,246,236, 24,147, 97, 69, 60,201, 20,248,217,152,110, 21,227,191, 79, 54,
+ 88,231,144,143,221,218,233,210, 85, 79, 37, 28, 65,231, 87,240, 98, 52,120,115,226,229,238, 83,238, 61,112,202,210,228, 12,116,
+117, 86, 93, 37, 87,210, 67, 2,253, 96,154, 2,139, 27,191, 49,242,113,167,145,112, 73,201,131, 39, 11, 19,211,197, 60, 82,141,
+121,238,177, 68,173, 34,252, 42,232,196,135, 95,209, 35,153,168, 59,183,127,101,166,201, 54, 94,217,129,167, 62, 60, 76,252,169,
+ 67,186,178, 64,112,167, 56,108,120,129,213,188,163,128,225,240,143,162,172,112,251, 47,109,196,133, 34,108,220,169,250,109,128,
+234, 91,164, 5,246,199,234, 99, 11, 71, 10,240,224, 3,249,251, 15, 26, 76,174,197,218,242,241, 91, 9, 51,114,241,226,146, 60,
+200, 50, 26, 35, 25,121, 33,206,156,230, 75, 17, 47, 11,129,166, 83,240,144, 47,110, 28,104, 11,173,243,121,147,107,108, 60,108,
+ 92, 54,205,205,206,145,210, 8, 21,196, 98,209, 70,211,200,204,236, 26,223, 10, 88, 11,113, 36,123,234,153,123,214, 57,242,227,
+137,246,217,161,196,121, 78, 26,228, 76, 85, 92,101, 12, 95, 92,208,188, 63, 50,217, 84,173,255, 0, 88,121,113,171,125,235,106,
+135,119,244,210, 46, 84,248, 89, 88,142,207,143,149,140,171,173,122,145,180, 18, 45,165, 71, 82, 25, 28,248,112, 54, 34,170,143,
+104,224,199, 56,150, 12,137,218, 40,201,154, 28, 89,152, 52,126,171,211,122, 47, 82,204, 83,168, 88,199,206,237,107,146,214,189,
+ 16, 34,225,247,196, 19,166, 43, 79,183,190, 63,172, 27,124,209,221,213,237,143,185,179,197, 4,204, 87,149,164, 77, 44,190,209,
+ 80,230,239,163,149,182,103,229,225,224,203, 12, 88,184, 3,112,124,176,209, 18,145,203,215,232, 20, 71, 31, 27, 63, 66,252,173,
+198,130,123, 31, 54, 46,215,147,109, 89,198, 86,237,147,131,133,183, 25,165,147, 76, 88,235,136, 53, 43, 64, 99,137, 88,172,114,
+179, 58,234, 26,143, 14, 60, 42,245,251, 59,106,124, 60,236, 29,114,164, 57,248, 56,251,100,161, 25, 70,136,113,150, 68,140,197,
+116, 54,107, 74,111,123,142, 92, 42,130, 54, 95,119,180, 91,131,225,197,130,254,156,101, 62,220,153,165,214,222,165, 49,219, 45,
+135, 75,230,210, 21,109,127, 63,203, 77, 23,124,110,242,118,252,121, 35, 5,126,242, 72,182,121,165, 98,235,211,146, 61,206, 69,
+140,186,168,182,146, 74,176, 2,252, 46, 15,152,169,217, 29,169,155,147,220,131, 44, 72, 34,218,151, 40,231,178, 44,215,213, 35,
+ 98,190, 35, 90, 3, 15,194,228,181,203,117, 74,216,112, 80, 73,169,195,178,118,193,132,248, 41,145,146,138,248,219,126, 32,148,
+ 52,122,213,118,183, 50, 99, 72,183,140,174,189, 70,237,117, 32,249, 10,128, 78,226,238,145,176,200, 87,209, 54, 73, 92, 73,119,
+ 9,180,200,168, 18, 28,119,137, 36,249,129,212,223,189,224, 60,105, 79,116,145,185,190, 2, 96,187,194,114,159,111,135, 40,200,
+170, 31, 45, 49,206, 95, 75, 65,226, 20,170,149,215,231,225,110, 52,125,223,182,176,183,167,148,229,203, 48, 50,225, 79,182,185,
+140,160,253,214, 67, 70,238,252, 80,252,119,132, 91,195,159, 10,122,118,222, 32,221, 6,231,214,148,160,200, 57,171,134,116,116,
+ 70, 83, 67,233, 76,227,225,215,126,157,248,106,181,205,237,122, 3, 51,179,119,190,118, 78, 28,121, 89,152,230, 92,217,177,246,
+211, 22, 36,101, 18, 38,151, 57,230,141, 89, 95,226,101, 7,167,169,181, 94,192,112,227, 83,228,239,236,104,183, 12, 93,175, 47,
+ 21,177,114,166,120, 97,150, 9,165, 69,153,101,200,149,160,140, 69, 17,248,165, 77, 73,114,227,244, 72, 62,227, 98,118, 62,221,
+133, 3, 98,227,229,229,107, 85,196, 92,105,220,196,207, 15,160,146, 73,177,244, 1, 18,169,183, 84,169,214, 13,215,219,198,164,
+197,218,176, 97,228, 69,146,155,134, 97, 55,137,178,213,157, 15,169,146, 23,146,104,222,102,209,168,124, 82,155,170, 21, 82, 44,
+ 45, 97, 84, 1,222,187,137,118, 76,201, 36,149,100,146, 40, 54,220,173,193,224, 64,128, 55, 66, 72, 19,230,111,136, 55,239, 56,
+120, 80,223,187,103,114,113, 35,219, 25,247, 37,205,151, 4, 98,117, 86,199,165,142,185,141, 39, 87, 77,191,179,112, 45,111,155,
+135, 46, 53, 59,118,237,188, 29,237,230,124,185, 37, 67, 54, 20,251,115,116,138,139, 69,144,209,200,236, 53, 35,124, 96,196, 45,
+225,236,160,100,118,182, 46, 68,243,228, 99,229,228, 98,101, 75,148,249,195, 38, 35, 25,100,121, 49,215, 10, 68, 64,232,203,164,
+198,131,152, 36, 55, 27,214,121,148,133,183,119,100,146,100, 77, 22, 92, 14,189,108,249, 49,113, 99,101, 17,188, 73, 30,221, 30,
+226, 86,101, 63,165,125, 74,125,181, 22,126,242,159, 44,109,237,182,226,149,143, 37,246,151,201,154, 82,167,166,155,156,170, 4,
+ 65,127, 72,244,239,118, 28,137, 31, 68,233,123, 59, 10, 36, 79, 79,151,147, 20,139,146,114,214,109, 72,238, 25,177, 70,222,235,
+121, 99,123,134,137,121,155,157, 92,111, 73,143,217,120, 0,225,244,178,178, 99,135, 13,112, 85,162, 6, 50, 38,109,181,131,227,
+ 60,165,163, 38,254, 13,163, 77,254,138,160,134,157,253,181,187,238, 42,145,245, 14, 12, 51,228, 36,113, 74,143, 35,174, 60,163,
+ 28,172,136,166,241, 51,187, 46,128,220,212,222,173,123,123,112,206,220,159,117, 92,248,150, 23,195,206, 56,201, 18,144,218, 80,
+ 99,193, 45,181,143,155,226,148,241,242,166,175,103, 97,152,115,113, 31, 43, 37,240,242, 82,104,163,198,214,170,144, 46, 68,134,
+119,233,105, 64, 75, 7,226,165,245, 88,112,243,188,237,163,104,109,168,101,152,167,151, 46, 92,201,253, 86, 84,211,244,193, 50,
+152,227,132,233, 17, 36,106, 22,209, 14, 22,160, 39,232,248,173,106, 99, 1,126, 28, 42, 82, 47, 81, 11,218,204, 57,138, 3, 1,
+ 98,104, 4,143,128,163, 69,140,217, 74,120,133,183,137,160,170, 18, 11, 6,211, 92,131, 32, 11,197,123,123, 42,144,146, 54,233,
+ 98,253,233, 96, 66,113, 52, 96, 99,189, 67, 47,150, 22,205,171, 73,224,111, 82, 0,191, 46, 30,218, 2, 66,152,248,222,147, 84,
+124,232,122, 52,139, 95, 81,231, 75,110, 20, 1,109, 25,230,126,154,126,152,239,207,149, 71, 55, 63, 71, 42, 66,121,222,128,145,
+210,142,222, 21,198, 4,229,122, 5,200, 60,233,117,155,208, 15,120,213, 69,129,168, 89,145,252, 33,188, 69, 29,174, 90,194,147,
+166, 39,117, 67,242,243,111,112,162, 4, 65,143, 43, 8,200, 70, 32,248,128,105,221, 9,255, 0,217, 63,236,154,186, 80, 0, 10,
+ 5,128,224, 0,167, 0, 60,171,123, 60, 73, 82,162, 44, 89, 73,212,209, 53,135,134,147, 82, 96,134,101,184,233, 48, 23,241, 83,
+ 86, 72, 42, 66, 11,123,106, 40, 42,241, 27,151, 3,231,174,221,142, 5,239, 14,240,204,155,107, 66,112,247, 44,131, 54,251,145,
+187, 79,180, 69,140,178, 76,232,176, 51,227,130, 88,200,195,149, 98,123,227,105,158,126,243, 77,163,111,217, 27,110,205,200,233,
+ 34, 98,166,100,153,254,166, 89,152,178,100, 38, 76,220, 88, 74, 29,127,210,245,109,185,247, 62, 62,205,220,189,231,181,111, 91,
+ 79,222,251, 14,229,187,100, 60,208,117, 95, 29,150,120, 39,149,163,120,167, 64,214, 54,110, 34,220, 69, 66,159,123,223,247, 63,
+196, 13,163,115,244,240,118,254, 78, 56,198, 27, 76, 25,229,225,197,131, 27, 29,127,112,178, 73, 40, 12, 99, 42,166,237,227,122,
+201, 72,189,215,217,221,207,180,109,233,184,110, 91,150, 62,237,137,139, 40,196,200,108, 76,179,149,233, 39, 34,253, 9,129,249,
+ 15, 15, 14, 21,191,236,236, 44,121,123, 75, 22, 4,237,184,245,110, 49, 30,158, 20,157,193,149,133, 54,234,209, 13, 50,203, 14,
+ 26, 13, 6,229,121, 31,224,170,254,252,143, 27, 23,181,119, 8,182, 70,216,113, 32,206,201,139, 51,120,139,111,221, 78,126, 78,
+ 68,161,136, 69,134, 54, 68,209, 26, 52,133,172, 42,147,183,251,237,241,226,217,177,103,237,159,189,187,139,102,140,199,219,217,
+130, 73,149,149, 27, 84,177,245, 49,163, 83,214,209,168,178,113, 31,199, 81, 36,149, 18,162,240, 43,109,186,183, 95, 50,247,240,
+197,113,101,192,222,131, 98, 75, 20, 50,110, 81,164, 24,145,184, 45, 27, 50, 75,162, 18,101, 23,114, 62, 94, 87,189,123,150, 30,
+ 30, 66, 98,192,135, 30, 84,211, 26,141, 14, 9, 97, 96, 56, 49, 28, 9,175, 29,252, 26,159, 32,224,110,210,100,179, 46, 92,155,
+190, 43, 75, 25, 86,212,242, 90, 70,100,101, 82,186,126, 47,214,224, 13,125, 14, 53, 50,171, 48, 42,196, 2,201,112,108,124,174,
+ 42,208,133, 87, 70, 94,141,186,109,126,149,173, 99,207,171,123,125, 85,213,107,225,244,127, 29,117, 90, 16,163,127,208,255, 0,
+135, 31,245, 22,155, 78,127,238,255, 0,225,199,253, 69,166,248,208,164,108,145,241,143,119,241,208,125,148,108,143,156,123,191,
+142,130,120,158, 20, 7,155, 63,121,111,209,229, 62, 14,168,140,138,237,182,106,208, 47,247,131,230,188, 48,155,112,225,233,208,
+ 61,191,149,127, 10,171,223, 51,183, 23,218,146,120,114,142, 44,103, 15,184,245, 65, 8, 40,165,177,243, 4,106,247,213,125, 92,
+ 65,191,135, 27,115,175, 82,251,171,109,234, 25, 14, 28, 29, 67, 48,202, 47,210, 77, 93,112,186, 4,247,181,250,129,120,106,231,
+106,100,219, 38,205,147, 10, 69,145,183, 99, 75, 28, 70, 86,141, 30, 8,217, 84,206, 73,152,170,149, 54, 50,106, 58,188,239,198,
+128,174,216,115, 55, 28,177,189, 98,101,100,137, 38,194,205,124, 88, 50, 68,106,164, 41,199,130,117, 37, 7, 3,165,166, 63, 71,
+ 58,193,246,214,235,189,227,166, 14, 87,175,105,132,144,236, 17,100, 36,170, 31, 90,230,100,100, 64,223, 19, 18, 67, 42,183,204,
+ 56,146, 5,235,213, 99,199,130, 22,145,225,137, 99,105,159,169, 51, 34,133, 46,250, 66,107,114, 62,102,210,160, 92,248, 10,139,
+ 14,203,179, 99, 2,184,251,118, 52, 74, 89, 36, 33, 33,141, 70,184,156,203, 27,124, 43,205, 29,139, 41,240, 38,244, 6, 33,119,
+253,219, 27, 11, 22,108,105, 34,199,196, 89,243,142, 87, 73, 18, 70, 66,187,140,144, 70,243,196,205,213, 16,176, 12, 11,198, 47,
+175,217, 83,191, 16, 55, 29,198, 60,108,253,191, 19, 39,210,194,155, 78, 86,108,140, 20, 23,145,149,227,137, 80, 55, 2,182,214,
+ 77,215,141,200,250,117, 13,177,108,211, 52, 47, 38,223,140,237,142,205, 36, 4,196,151, 70,119,234,187, 47,195,192,151,248,207,
+242,184,243,162,231,237, 59, 94,232, 35,251,203, 10, 12,193, 22,174,152,200,141,100, 11,168, 89,128, 14, 15, 59,113,160, 49,185,
+219,214,235,139, 38,239,247,115, 36, 93, 29,210, 85,159,162,177,190, 75, 67, 30, 14, 60,189, 68,138,118, 2, 64,174,227,169,167,
+226,209,203,141, 71,219,247, 93,246, 94,224,151, 23, 31,115, 82,155,158,124, 49,245, 58, 90,146, 56,206,210,185,223,184, 73, 15,
+194, 9, 0, 11,251,207, 18,107,113,149,177,236,217,161,151, 47, 3, 30,117,121, 58,238, 36,137, 27, 84,186, 68,102, 70,184,226,
+197, 20, 41, 39,195,135, 42,120,218,118,213,203, 25,235,133, 0,204, 22,182, 72,137, 58,163, 74, 52, 75,251,203,106,224,140, 84,
+113,228,109, 89, 96,243,183,221,247, 40, 19,239, 44, 44,132,195,147, 15,110,223,242,132, 97, 3, 69, 33,196,220, 87, 74, 20,115,
+107,190,158, 45,207,137,181,175, 90, 24,251,143,117,202,221,147,111, 87, 72, 82, 93,210,124, 5,186, 2,201, 18,109,107,156,156,
+249,178,204,220,125,156, 43, 65, 46,197,178, 76, 34,235,237,184,178,116, 89,158, 29, 80,198,116, 52,143,214,114,191, 15, 13, 79,
+241, 55,153,226,104,135,106,218,198,121,221, 6, 12, 30,188,144,125,103, 73, 58,183,208, 98,191, 82,218,175,160,233,247,112,160,
+ 60,223,182,247,157,222, 61,182, 8,211, 33, 91, 43, 39, 27, 98,132,238, 18, 38,185, 16,102, 77,147, 27, 23,212, 72,114,160,105,
+ 93, 95,164,120,223,149, 76,205,238,174,224,139, 14,118,143, 34, 53,151, 3, 19,118,200,121,186, 42, 70, 67,109,185,177,226,198,
+ 64,110, 10,178, 41, 58,173,244, 90,182,233,178,236,145, 65, 54, 52, 91,110, 44,112,100, 0,179,196,144,198,170,225, 89,157, 67,
+133, 81,123, 51,179, 15,105, 38,164,195,179,237, 13, 0,128,224, 99,152,150, 22,197, 88,204, 72, 84, 64,228, 51,195, 98, 62, 70,
+ 42, 9, 94, 70,212, 4,244,232, 54,176,133, 91, 65,210,225,108,108,214, 6,198,220,141,141, 60, 32, 60, 0,224, 69, 14, 56, 49,
+225,105, 90, 8,146, 38,157,250,179,148, 80,165,228,210,169,173,237,243, 54,148, 2,231,192, 81, 3,170,243, 62,202,128, 93, 43,
+192, 91,242, 82, 42,106, 99,127, 15, 26, 83, 36,103,155, 15,174,154,178,165,216,234,160, 9,167,137, 30, 21,197,120, 89, 71,190,
+134,211,131,123, 15,166,198,144, 76, 8,191, 27,242,181,141, 0, 69, 3,199,137,168,206,151, 99, 98, 64,240, 20,254,175,144, 55,
+247, 90,135,169,136,251,106,160, 55, 73, 28, 53, 83,149, 47,196,154, 79,140,139,242, 6,184, 51,175, 47,174,168, 27,226,212,225,
+ 77, 23, 36,159, 58, 80,109,206,160, 5,123,155,249,209, 22,134, 41,224,218,128,229, 28, 73,246,154, 89, 44, 69, 42, 14, 30,250,
+231,228,106,144,140,207,101, 32,115, 52,144,248,154, 99,252,198,137, 15, 35, 80,210, 27, 63, 18, 47, 75, 1,178,253,116,172,133,
+223,129, 2,195,198,186, 49,101,250, 77, 57, 2, 82,165,163, 81,226,196,155,159, 32, 42, 58, 9, 8, 58, 31, 72, 67,113,244,241,
+163, 74,223,217,160,253, 91,159,167,133, 48, 95, 75,144, 62, 97,195,232,168, 81,216,183,187, 22,241,231,239,161,200,160, 92, 15,
+ 58, 85,144, 95,135,141,184, 83, 93,184,113,241, 52, 3, 44, 52, 17,254,156, 41,240,230,188, 11,161, 64, 32,154,103, 52, 63, 77,
+ 27, 28,225,232, 2, 80,117,123,237, 90, 50, 61,247, 19, 36,125, 34,128, 23,225,123, 82,175,137,246,211,166, 76, 19, 24,104,143,
+239, 46, 52,143,166,146,194,214,160, 28, 79,151,228,165, 0, 21, 30, 39,198,155,111, 58,164,219,251,183,107,207,223,243, 59,114,
+ 33, 44,121,216, 96,150, 50, 42,136,228,211,167, 87, 73,131, 49, 54,212, 57,129, 64, 94,243,164, 2,231,217,229, 85,240,239, 56,
+179,111, 25, 59, 26,172,131, 43, 22, 20,200,146, 66, 7, 76,172,132,133, 10,117,106,191, 15, 42,177,183,210,104, 14, 35,128,164,
+181,137,168,147,238,216, 88,251,150, 38,211, 43,145,151,154,178, 62, 60,122, 73, 5, 98, 26,156,150,228, 45, 83, 72, 38,128, 29,
+190, 48,124,174,127, 37, 74,198,136,170,252, 95, 49,226,104, 81, 45,222,254, 2,141, 60,233,139,143, 46, 67,130, 82, 20,105, 24,
+ 47, 59, 40,212,109,123, 86,163,212,141,135, 11,237,167,128,195,149, 80,118,199,117,237,157,219,130,249,251,104,145, 22, 57, 12,
+ 82, 67, 58,170,200,166,193,129, 33, 25,197,152, 30, 6,245, 51, 98,223,113, 55,236, 71,204,196, 89, 18, 56,230,151, 29,150, 96,
+161,181, 66,218, 24,141, 44,194,215, 28, 43,123,136,245,224, 90,134,183,133, 17, 28,248, 10, 96,101,167,171, 45, 69,212,180,234,
+120,142, 6, 79,110,227, 96,254, 36, 75,221, 88,103, 55,105,110,225, 49,206,169,110,164, 93, 89,164,140, 79, 23,136,100,213,126,
+ 21,154,252, 68,155,101,207,252, 68,237,215,194,220,113,254,232, 56,123,122, 71,184,228, 42,207, 2,198,142,235,174,120,205,131,
+ 90,223, 18,181,189,182,175,114,155,240,219,177,119, 12,172,140,204,205,154, 25,167,202,145,166,200,114,100, 26,228,118, 46,206,
+192, 56, 23, 36,222,179,217,157,139,216,120,221,227,183,118,226,246,214, 25,198,205,196,159, 41,230, 45, 55, 80, 52, 44, 20, 40,
+253,230,155, 27,214, 26,163, 21,161,230, 95,137,141,177,230,118,174, 11, 98,103,237,249,123,166,223,157, 60, 19, 77, 12,184,103,
+ 38,108,115,194, 39,209,131, 28, 73,160,252,193,108,116,142, 23,189,235,109,219,251,143,101,225, 99,126, 29, 47,112,199,233,119,
+ 65,130,147,109,155,189,194,168, 97,120,189, 52,237,250,141,175,134,174, 0,249,120,217, 71,248, 93,177,166,113,135, 43,182,176,
+198, 39, 94, 71, 92,128,198,253, 27,158,156,122, 68,183,189,173,225,246, 80,143,225,198,206,243, 97,200,189,171,139, 36,122,102,
+ 92,172, 51, 47, 16, 67,126,229,145,204,182,249, 69,200,189, 93,174,149, 21, 51, 95,134,168,141, 63,112,201,165,117,142,224,132,
+ 44,165, 85,172, 11,203,113,196,142, 6,190,130, 32,158, 66,188,247,105,237,121,246, 65, 38, 46,215,219,216,248,152,249, 15, 28,
+178,250,121,202, 40,120,203,233,123,180,165,239,102,175, 65,141,116, 34,173,201,210, 0,185, 36,158, 3,196,158, 38,161, 69,227,
+229,198,213,212,190, 53,212, 5, 3,242,143,254, 28,127,212, 90,111,182,244,247,253, 1,254,238, 63,234, 45, 51,143, 42, 2, 54,
+ 65,248,199,187,248,232, 87,162,100,131,172,112,240,251,104, 52, 3,238, 46, 9,164, 12, 1,172,252, 29,209,141, 58,109,206, 98,
+ 49,166,225,149,153,134,172,236, 45, 25,194,245, 26,221,207,234,183,166, 54,247,209,227,238,109,134, 92, 87,205, 76,216,206, 60,
+ 79, 28,110,228, 48,248,166,183, 74,192,128, 72,147, 80,210, 71, 3,225, 66, 23, 5,135, 17, 77,230, 57, 85, 68,157,209,176,195,
+ 28, 19, 73,157, 26,199,144,172,241, 49, 13,242,198,226, 57, 25,133,174,161, 24,217,181, 91, 79,141, 75,139,119,219,101,157,113,
+ 99,201, 86,153,229,151, 29, 99, 23,185,150, 1,170, 84,229,250, 34,133, 39, 1,111,166,184,123,106,146, 30,234,219,101,206,205,
+218,217,140, 89,152,147, 60, 9, 19,127,122, 99,129, 50,152,161,182,145,240,185,224, 77,254, 19, 79,194,238,109,171, 54, 13,181,
+158, 97, 6, 70,231,143, 6, 76, 56,207,197,149,114, 23, 92,106,236, 6,144, 91,136, 91,159,136,131,106, 16,185, 6,158, 45, 84,
+169,220,219, 3,182, 74,174,116,100,226, 71, 44,249, 12,117, 0,177,192,221, 57, 91, 81, 22, 58, 27,131, 91,149, 70,194,238,188,
+ 45,194, 98,152,224, 44, 75,153, 38, 9,146, 70,208, 88,197,138, 51, 89,210, 54, 93, 71,131, 88,169,177, 22, 38,163, 41,162, 54,
+174,181,197, 81,199,221,123, 4,184,211,230, 71,159, 27, 65,142, 34, 50,184, 13,203, 35,132, 58, 70,155,191, 80,240, 93, 55,185,
+225,206,159,141,220,187,126,102,102, 14, 38, 11,122,148,206,143, 42, 68,200, 67,240,169,195,104,163,145, 24, 27, 27,234,155,242,
+ 84, 5,185, 20, 88,163, 75,106,110, 36,208,238, 42, 72, 26, 84, 88, 0, 42, 1, 22, 56,129,226, 7,178,137, 18, 71, 98,116,142,
+116,222, 22,191,151, 42,124, 96, 5, 6,254,222, 52, 3,213, 87, 87, 32, 41, 13,245, 0, 0,211,226,105, 67,173,184,184, 95,166,
+154,242,192, 57, 56,250,232, 7, 21, 0,115,226, 5, 71, 82,164, 30, 23,177,167,153,146,199, 73,185,250,232,125, 85, 3,229, 55,
+ 30,195, 64, 56,145,202,128,120,142, 10,111,202,156,210,131,107,131,106,105,113,237,250,170,160,112, 44, 60, 57,123,105, 9,107,
+ 88, 82,106, 22, 60, 13, 33,111, 33,194,168, 16, 26, 82,126, 19,238,166,147,194,145,137,211, 80, 8, 41,222, 20,130,157,110, 20,
+ 3,199, 0, 41,178,155, 33, 52,251, 80,230, 23, 75, 26,164, 34, 0, 93,184,120,212,133, 80, 46, 41,144,167, 27,253, 84,183, 34,
+ 66,125,181,158, 44,208,226,188,111, 67, 78, 92,105,224,146,198,255, 0, 69, 51,202,168, 15, 37,137, 45,228,139,252, 52, 68,150,
+ 53, 97, 25,241, 54,191,183,202,134, 77,148, 72, 71,194, 70,134,161, 18,250, 0, 85, 22, 63, 22,191, 42,133, 28,202,160,179, 40,
+181,159, 72, 35,216, 46,104,110,117, 90,138, 10,155, 42,113, 88,212,146,222,108,220,232, 77,107, 85, 33,196, 29, 28,185,208,217,
+ 56,131,106,156,110, 16, 2, 1, 22,166,157, 38,223, 13, 82, 17, 0, 2, 84,183, 46, 31,195, 83, 65,250,252,234, 33, 55,156,120,
+121, 84,180,227, 97, 64, 58,226,188,206, 77,171, 35, 51, 39,184,119, 77,168,127,245,173,159,117, 57, 88, 64, 14, 46,189, 8,196,
+176, 31,228,202,162,214,241, 53,233,186, 71, 1,227, 85,251,118,205,139,182,101,238, 25,112, 60,141, 38,229, 48,200,156, 57, 5,
+ 67, 5, 9,100,210,171, 97, 97,227,122, 6, 98,241,187,130, 44,221,207,121,238, 45,183,226,182,193, 30, 76, 72,108, 74,201, 25,
+157,140,109,237, 86, 93, 38,163,201,178, 69, 15, 99, 47,117, 38, 94, 71,223,195, 17, 55, 31,188,140,242,107,234, 48, 18,152,244,
+235,209,167,142,141, 58,109, 90,188, 14,213,217, 54, 93,207,113,220,113,181,234,221, 1, 25, 24,174, 84,194,161,137,102, 17,174,
+144, 64, 98, 79, 11,154,130,189,145,182,156,117,219,142,231,156,118, 96,218,190,233, 50,175, 70,193,181,244,203,232,234,152,239,
+250, 58,168, 66,151,115,218,176,247,206,238,237,172,140,193, 50, 54,233,131, 44,217, 43, 28,210, 71,103, 72, 80,128,154, 88,104,
+246,219,159,141,122, 30,227,149,143,183,224,100,230,229,185, 76,120, 34,121,101,101,230, 21, 65, 39, 77,188,124,170,171,120,237,
+205,187,121,159, 7, 41,178, 50, 48,178, 48, 53,140,121,240,164,232,184, 73, 0, 87,142,250, 91,225, 32, 85,198, 86, 30, 62,227,
+139, 62, 22, 82,245, 49,178, 99,104,165, 67,194,232,224,171, 11,143, 97,162, 41,229,172,185, 24,153,157,177,189,109,219, 92,251,
+ 86, 54,102,231,139,140, 51, 50, 51,164,155, 35, 38, 28,155,240,154, 2, 93, 84, 50, 11,241,107,138,245, 77,219,255, 0,203, 51,
+127,224, 75,253, 67, 89,216, 63, 15,112,163, 27,120,200,221,183, 44,152,118,172,136,178,176, 32,150,100, 49,161,128,221, 16,175,
+ 75,226, 30, 30,118,224, 8,227, 90,185,177,211, 39, 30, 88, 36, 36, 44,200,209,177, 94, 96, 48,210,109,123,249,214,226,140,158,
+ 93,179, 15,242,198, 15,110,119,116, 28, 54,204,236, 76,108, 29,252, 45,180,175, 0,144,101,183,243, 24,232, 99,229, 77,121,230,
+135,179,166,124,121, 90, 50,221,196,234, 90, 54, 43,117,108,195,113,117,240, 53,232,152,221,185,182,227,118,250,246,211, 43, 79,
+183,172, 7, 24,137,136, 46,200, 65, 28, 74,133, 23,227,204, 10,173,198,236, 93,150, 14,217,151,181, 58,153, 18, 96,200,230, 94,
+179,186,245,213,203,137, 3,171,162, 40, 5, 88,112,248,106,209,252, 0, 14,232,158,120,251,171,179,227, 73, 25, 18, 92,140,161,
+ 34, 41, 32, 48, 16, 92,106, 3,157, 85,109,157,191,139,220,187,223,117,197,187,100,101,203, 20, 25,130, 44,104, 87, 38,100,142,
+ 61, 81, 6,214,168,142,160,144, 79, 0,110, 7,149, 95, 98,246, 62, 50,110, 59,126,235,155,186,238, 27,134,102,218,206,216,237,
+147, 50, 50, 89,215, 65, 82,130, 48, 57,120,142, 39,196,213,214,215,176,226,109,121,155,150,110, 59,200,242,110,147, 12,140,133,
+144,169, 85,112,161, 45, 30,149, 82, 5,135,137, 53,118,215, 90, 3,203, 48,246,165,207,252, 44,255, 0, 55,229,103,231, 62,251,
+141, 20,146,226,101,250,169,135, 75,211, 78,240,162, 70,138,225, 0,208,156, 77,175,126, 55,173, 86,239,129,141,220,125,233,218,
+240,110,109, 43, 69, 62,209, 52,179,136,101,146, 2,231,247,108, 67, 52, 12,141,164,147,200, 26,208,225,246, 86,217,143,218, 77,
+217,169, 44,231,110,104,228,136,204, 89, 58,250,101,145,166,111,139,167,162,250,155,135,193, 70,220,187, 43, 15,114,202,219,243,
+162,220,115,182,252,173,183, 24,225,193, 54, 28,145, 35, 24,218,215,215,212,134, 78, 39, 79,133,171, 13, 19, 67, 37,143, 44,253,
+165,188,247, 94,205,181, 77, 54, 86,217,183,109,127,122,226,227, 79, 35, 76,113,166, 10,237,208, 70,144,179,105,123,106,177, 53,
+ 65,133,180,247,126,102,201,129,190,236,155, 62,115,247, 20,171, 14, 98,111,146,110, 48,104,155, 89, 18, 58, 60, 13,144, 7, 73,
+144,149, 9,164, 91,199,198,189,107,101,237, 93,167, 99,135, 41, 49,145,231,151, 60,234,207,203,203,115, 60,249, 6,218,127,125,
+ 35,243, 0, 30, 3,149, 83,227,254, 28, 98,225,127,134,193,222,183, 76, 93,163, 86,177,180, 69,144,162, 1,118,212, 99, 86, 40,
+100, 17,159, 21,213,244,212,174,148, 26,148,178,237, 95,230, 31,196,156,216, 55, 44,140,152,241,112,176,176,114,198, 4, 83, 17,
+ 19, 76, 28,144, 36, 3,131, 40,177,184, 28,235,210, 53,183,133, 86, 69,176,226, 99,239,217,125,194,143, 33,203,204,130, 44,105,
+ 99, 98,189, 32,144,146, 84,168,211,170,252,120,252, 85, 99,111, 51, 85, 10, 75,144,253, 77,249, 47,249,107,169, 44, 45,207,195,
+248,235,170,151, 95,129, 76,246,248, 15,251,184,255, 0,168,180,218,115,255, 0,118, 63,221,199,253, 69,164,184,172,154, 34,100,
+252,227,135,135,241,154, 8,181,252, 40,249, 39,227, 30,239,182,128, 69,205, 1,137,197,236,118,197,147,111,204,134, 44, 40,247,
+ 44,124,189,199, 35, 47, 49, 80,117, 36,143, 45,114,214, 5, 46, 99,212,250,122,241,234, 86,225,195,133,248, 85,103,249,111,184,
+118,252, 62,172,177, 38, 78, 84,249,123, 51, 20, 73,166,156,235,196,200, 94,172,142, 90, 47,130, 47,210,248, 69,145,124, 56, 87,
+164,218,220,169, 56, 94,128,243,108,158,218,223,140,173,133, 28, 17, 25,183, 61,191,120, 76,169, 89,164,244,248,237,185,102, 69,
+ 46,133,144, 70,117, 50, 43,220, 41, 3, 86,147, 86,219, 54,210,233,222,187,158, 98, 7,251,191, 22, 48, 33,103, 70, 64,114,242,
+ 18, 24,178, 25, 11, 0, 26,201,136,151, 35,135,198,107,103,111, 42,235, 30,116, 6, 61,251, 99,118,151,119,154, 70,104, 23, 1,
+247, 25, 55, 88,229, 87,115, 53,219, 3,238,245,133,144,198, 20,124, 71, 81, 33,143, 10,137,135,217, 27,134, 62, 78,213,214,233,
+ 79, 30, 52, 27, 90,100, 63,169,201,141, 35,151,109, 31, 17, 76,120,244, 71, 62,178, 20,163, 73,242,241,225,225, 91,187,154,235,
+241,189, 1,135,147,177,247, 57, 49,100,129,166,199, 86,108, 77,210, 5, 55,114, 58,153,185,233,159, 5,198,129,240,133, 75, 63,
+145,229,122, 60, 29,179,188, 75,154, 55, 12,191, 77, 11,201,185,100,103,188, 49,202,242,105,142,109,183,238,244, 77, 70, 36,187,
+ 9, 56,158, 22,183,213, 91, 43,220,215, 14, 62, 84, 7,159, 75,219, 59,150,205,182,199,152,230, 41,164,192,198,216,227, 88,226,
+ 19, 72, 26, 93,177,164, 19,106, 17,196,210, 8,207, 86,225,149, 24,142,101,120, 85,159,105,109,121,129, 49,247, 76,204,100,142,
+ 67, 54,235, 37,219, 92,110,171,155,150,179, 33, 72,100, 77, 86,117,142,255, 0, 17, 82, 5,184,113,225,174,226, 5,117,248, 86,
+ 65,199,229,189, 23, 79,155, 55,186,230,134, 44, 64, 30,234, 41, 28,120, 84, 2,116,212,243,227,236, 38,158, 35, 67,195, 79, 58,
+ 64, 15, 59, 91,219, 78, 39,198,128, 70,208,162,214,174,176,210, 60, 7, 42,105,179, 1,115,126, 52,230,117, 94, 68, 95,203,133,
+ 0,240, 7,143, 10,226,109, 76, 50,165,129,213,115,229, 76,234, 3,204, 31,168,213, 3,139,112,183,133,233,183, 94, 28,105,174,
+117, 15,148,129,230,105, 44, 60,168, 5,186,249,210, 93, 88,219,198,147,147, 10,119, 11,131,227, 84, 28, 64,166, 73,193, 61,230,
+156, 79, 26,100,156,128,246,212, 2, 14,116,227,229,254,156,233,163,157, 60, 31,136, 15,117, 8, 18,131, 63, 43, 81, 73,181, 71,
+144,220,138,160,114,112, 20, 45, 99, 93,143,141, 16,155, 45,168,104,160,241, 34,245, 18, 52,199, 92,124, 68, 83, 60, 5,233,129,
+130,221, 64,176,167,178,252, 54,163, 8,153, 27, 0,172,141,196, 27, 94,150, 72,144,199,164, 95, 79,133, 71, 89, 44, 45,111,244,
+ 2,187,174,121, 2,106, 80,163,155, 74,174,132,224, 40, 36,220,251,169,197,129, 94,116,141, 96, 46, 60,141, 82, 15,142, 81, 48,
+ 60, 45,110,117,216,113,117, 75,234, 38,222, 28,125,244,204, 97,165, 26,254, 63,101, 75,195, 84, 64,218, 1,226, 5,239,231, 84,
+131, 91, 6,206,174,173,123,121,251,168,134, 7, 30, 23,163,179, 89,120,120, 83, 18, 75,141, 68, 90,254, 20, 21, 4, 85,151,157,
+ 34,251, 56,210,188,225,180,133, 60, 24,216,210,173,135, 42, 2,187, 47,251, 99, 64, 28,232,249, 34,243,181,185, 82, 42, 27,222,
+128, 85,137,203,132,226, 15, 14, 94, 85,109, 10, 5, 0, 15, 10, 2,168, 50,151,247, 15,170,165,198, 42,160, 60,143, 10, 90, 80,
+ 46,109, 79, 43, 91, 70, 27, 25,196,210,133,165,181,188,105,233,122,210, 21,168,208, 8,229, 69, 82,124,105,192, 19,225, 68, 84,
+ 30, 52,149,121, 10,208,114, 15, 27,209, 65,181, 32, 81,106,112, 28,107, 1,161,193,169, 25,155,244,105,214,174,179, 84,208,210,
+ 6, 88,248,138, 97,183, 58, 54,155,243,166,148, 21, 83, 69, 25,195, 79,244,127,253, 42,234,126,145,111,163,248,235,170,215,241,
+ 5, 36,151,253,223,252, 56,255, 0,168,180,223, 42,123,142, 9,255, 0, 14, 63,234, 45, 52,242,172, 2, 46, 79,246,163,221,252,
+116, 43, 91,217, 69,201,182,177,238,161,125, 31, 77, 0,132, 19, 74,214, 28,171,169,166,244, 7, 95,141, 47, 26, 65, 79, 2,226,
+252,232, 65,188,184, 82,123,233,228,113,189,171,188,121, 10, 1, 45,237,164,226, 41,108, 7,141,119, 51,207,133, 0,163,136,227,
+ 75, 97, 72, 60,125,148,170,111,122,203, 41,201, 30,179,166,246,176,189, 19,162,111,197,207,228,165,135,244,190,142, 54,162,155,
+183, 63, 10,128, 1, 69, 44,170, 9, 62, 98,244, 78,140, 68,218,196,251, 9,164,211,105, 57, 1,237,162, 19,226, 45,112,104, 5,
+ 88, 35,183, 5, 2,152,202,160,216, 1, 68,215,227,123,211, 11, 40,226,109,198,128,109,129,101,183,190,136, 70,174, 22,160,137,
+ 19, 95,204, 45, 79,105,163,225, 84, 13,157,120, 42,220,253, 20, 29, 43,123, 92,209, 29,140,156, 71, 47,104,166,232, 60,245,113,
+160, 19, 66,240, 54,166,216, 2, 45, 79,183,242,143, 10,105, 0, 17,106, 1, 26,152,254, 20, 78,102,134,255, 0, 55,209, 64, 32,
+249,169,255, 0,222, 83, 23,157, 43, 27, 61,253,134,132, 8,231,133, 71, 54,212, 61,181, 33, 78,165, 6,131, 32,179,251,170,131,
+143,141, 34,158, 22,174,189, 9,195,169, 58,121, 26,134,135, 88, 53,248, 15, 97,167,181,200,250, 5, 2, 57, 26,225,124,205, 74,
+140,160, 36,185,176,224, 56,209,132, 10,252, 62,131, 77, 60, 15, 31, 34, 42, 93,161,117,109, 62, 7,248,105,141,142, 15,178,245,
+ 10, 71, 22,191, 30, 84,246,182,158, 30, 86,167,188, 4, 14, 7,253, 63,208,211, 24, 89, 61,188,168, 7,142, 17,147,254,156,168,
+155,123, 49,141,137,227,241,127, 21, 48,240,133,175,206,199,248, 41,248, 28, 34,111,107, 86,145,150, 74, 62, 20,134,187,233,174,
+161, 8,210,168, 87,140, 14, 87,185,162, 11,147,236,166, 79,253,180,107,239,162,128,109,195,157, 10, 64,154,221,102,242,191,241,
+ 83,227, 93, 70,222,226,105,146, 92,202,222,250,145, 18,219,143,141, 1, 34, 49, 82,208, 88, 84,104,133, 75, 81,200, 86,146, 32,
+225,192, 95,198,146,231,206,148,145, 93,107,242,173,197, 25,226,119, 15, 19, 79, 71, 11,202,134, 86,184, 10,172,195, 77, 58,146,
+ 67,147,227, 68, 83,237,168,235, 97, 78, 13,198,175, 35, 73,174,100,144,198,136, 13, 5,120,142,116,237, 44, 56,214, 90, 69,221,
+ 80,234,194,157,172,120, 84,109, 70,156, 24,214, 92, 74,131, 94,252,233, 62, 17, 77, 6,145,143,149, 40,105,164, 59,133,190,143,
+227,174,166,220,233,254,143,241,215, 82,159,137, 40,138,103, 60, 19,254, 28,127,212, 90,109,233,206, 62, 79,248,113,216,255, 0,
+ 65,105,160,115,242,172,148,141,144,126, 49,199,194,130,120,138,150,240,245, 13,245, 91,194,220,255, 0,142,154, 49,127,151,127,
+162,128,139, 99, 75,110, 22,189, 73,244,162,223, 55,211,106,225,139,252,175,201,249,232, 8,192,123,107,133, 73,244,196, 31,159,
+242,126,122,239, 76, 63, 95,242, 80, 17,203, 2, 60,205, 32,191, 59, 84,129,139,199,231,252,159,158,148, 99,142, 69,191, 37, 0,
+ 15,160, 82,113,183, 58, 63,167,254, 87,228,252,245,222,152,223,230,252,159,158,128, 0,227,198,157, 97,107,209,189, 61,191, 79,
+242, 82,250,127,229,126, 74,140, 2, 64,224, 16,182,183, 62, 52,255, 0,140,145,118, 23,241,176,163, 71,142, 66,145,171,153,191,
+ 47,207, 78,244,255, 0,202,227,238,172,128, 29, 62, 58,153,205,254,142, 84,162, 43, 95,226, 60,125,180,126,150,145,243, 95,222,
+ 41, 68, 68,115,107,249,112,170, 8,198, 53,213,199,149,185, 19, 74, 81, 0, 22, 3,234,163, 8,128,213,118,231,236,252,244,189,
+ 0,120,106,246,242,160, 1,164, 94,214, 21,204, 23,145,181, 25,162, 95, 23, 23,247,126,122,103, 77, 56,124, 90,188,184,113,160,
+ 35,151,179, 30, 23,166,235, 45,192, 15,174,142, 96, 4,147,175,242, 83, 68, 0, 15,155,242,126,122, 0, 32, 55, 17,113,198,155,
+199, 87,157, 74, 24,228,242,111,201,249,233, 61, 55, 19,241,126, 74, 2, 61,200, 52,198, 36,158, 53, 47,211, 95,244,191, 39,231,
+166, 54, 53,201,248,191, 39,231,160, 35,175, 58,100,196,134, 22, 28, 45,252, 53, 48, 99, 91,244,191, 39,231,165, 16, 0,214, 45,
+204,121, 80, 16, 99,151, 72, 34,185,159, 87, 31, 58,158,216,113, 30, 36,254, 74,140,216, 99, 93,149,248,123,191, 61, 0, 16, 9,
+ 31, 77, 57,248,163, 91,192, 26,147,233, 44, 7,199,227,229,249,233, 36,197,248, 27,227,181,199,151,231,161, 74,216,184,184,189,
+ 29,199,194, 79,182,141, 30, 22,153, 7,199,225,126, 94,207,125, 21,176,245, 41,179, 88, 95,203,243,209,132, 70,198,107, 49, 7,
+145, 31,193, 82,137, 54,165,135, 11, 72,185,126, 62,239,207, 69,244,220,126,123,253, 31,158,163, 41, 22, 66,124, 40, 50,112, 91,
+123,191,134,167,190, 63,242,173,126, 28,191, 61, 71,147, 18,246, 26,252,124,191, 61, 0, 35,241, 38,129,204,248,209, 96, 29, 24,
+ 24,183, 27, 30, 66,158, 49,109,250,127,147,243,210, 60, 23, 5, 67,243,246,126,122,209,145,163, 54, 3,194,196, 31,109, 56,229,
+ 99,149, 32,146, 47,227, 81,125, 25,185,179,254, 79,207, 93,232,219,245,255, 0, 39,231,160, 21, 28, 60,200, 47,170,192,220,212,
+213, 63,109, 3, 23, 8,135,215,171,151,179,243,212,207, 79,198,250,191, 37, 10, 87, 20,253,243, 95,192,255, 0, 13, 29, 71, 42,
+ 51, 99,234, 98,197,185,251, 63, 61, 62, 60,110, 63, 55,228,161, 7, 70,188, 40,227,130,210,164, 0, 14, 45,192,115,164, 44,151,
+183, 18, 7,176,125,181,164,210,226, 74, 62, 71, 91,133,112, 54,165, 5,125,191, 80,251,107,172,167,207,234, 31,109, 93,235,169,
+143,175,160,224,194,156, 56,242,166,133, 30,223,168,125,180, 64, 84,120, 31,168,125,181,119,199,170, 45, 37,208, 75, 53, 40, 94,
+ 60,169, 67, 1,224,126,161,246,211,132,163,245, 79,212, 62,218,187,227,212, 56,190,129, 18,194,142, 31,133,170, 40,145,127, 85,
+190,161,246,211,196,232, 63, 69,190,161,246,212,114,143, 82,168,248, 7,226,124, 41, 66,154, 15,170, 79,213,111,168,125,181,222,
+173,127, 85,190,161,246,214,119, 46,162, 42, 75,138, 15,107,210,105,161, 12,180, 31,162,223, 80,251,107,142, 92,127,168,223, 80,
+251,106,110, 93, 75, 36,223, 0,218,127,131,248,235,168, 94,161,116,234,179,124,186,188, 63, 91, 79,157,117, 93,203,169, 40,254,
+ 5, 91,129,240, 95,153,142, 63,234, 45, 51,136, 60, 40,166, 39, 97, 27, 2,182,233,199,205,212, 31,145,124, 9, 20,157, 23,254,
+ 71,237,167,250,213, 13, 3,231,198,186,227,143,240, 81, 58, 47,126,105,251,105,246,210,244, 30,255, 0, 50,114,227,241,175,250,
+212, 7,152,108, 43,151,151,189,246,219, 77,148,207, 10, 63,112,200, 33,113,171,227,135,112,233, 43,106, 39,158,137, 52,175,234,
+129,195,157, 27,119,238,253,255, 0, 3, 59,120,219,161, 49,153,182,181,204,203,102,116,186,140, 83, 22, 49,195,102,247, 62, 75,
+ 95,207,166,107,111,139, 14,199,214,131,209, 28, 30,175,248,175, 73,209,124,125,127,218,143, 91,210,208,215,254,214,221, 91,126,
+151,205,198,162, 65,181,109, 56,251,198,241,157,147,155, 6, 70,118, 84, 17, 12,188,121,229,199,180, 56,104, 36,208,173, 24,177,
+ 17,146,207,118,126,127, 69, 1,157, 94,227,222,241, 55, 49,180,100, 78,153, 66, 29,194,108, 71,204, 49, 42,117, 99, 93,168,238,
+ 74, 44,159, 8,100,146,192,219,194,166,201,190,110,146,246,143,111,238, 49,202,144,231,111, 31,118, 71, 54, 64, 64, 86, 51,153,
+211,234,186, 35,124, 55,248,136, 80,124, 77, 79,108,110,201, 27, 84, 10,231,105,251,160, 78, 78, 49,105,113, 78, 63,168,179, 19,
+160,179,232,234, 91, 85,252,109,122,157,145, 6,198,219, 26,174, 71,161,251,132,197, 24, 66,242,227,140, 78,137,211,209,210,117,
+116,194,252,186, 45,236,181, 64,121,230, 46,255, 0,191, 97,108,108,113,115, 85, 91, 11, 27,123,221, 36,150, 88,196,158,165,241,
+ 55, 9, 35, 72, 6,182,248, 82,198,223, 9,184,186,219,219,119,137,220, 91,212,253,205, 22, 52,146,170,224,201,185,205,183, 28,
+ 78,144,212, 17, 54,197,220, 67, 25, 62,109, 66, 78, 30,234,186,120, 59, 57,176,246,251,141,160, 96,137, 92,237,159,189,197, 16,
+245,186,135,169,233,236,193,117,117, 62,109, 63,165,207,141, 78, 16,236,231, 52,104,244, 3, 59,212,189,180,190, 63, 91,213,244,
+ 6,191,210,213,213,244,252,255, 0, 75, 71,242,104, 12,230,193,137,184,109,189,212,118,153,247, 23,203,131, 11, 99,219,211, 75,
+173,131,186,201,145, 3, 77, 98,205,102, 99, 22,162,110, 79, 27, 95,128,170, 71,239,110,225, 76,183,192,213, 17,145, 93,182,160,
+218, 5,254,241,147, 58, 72, 32, 54,225,195,211, 34,189,191,149,126, 66,189, 5,224,219,142,237, 31, 80,225,253,243,208,110,149,
+222, 1,149,233,245,124, 90,126, 46,167, 79, 95, 63, 11,212, 67,143,219,190,160,234, 59,111,168,245,171,170,242, 99,107,245,253,
+ 51,162,255, 0, 21,253, 71, 78,246,253, 45, 62,202, 3, 25, 47,121,239,144,195,190, 78,146,172,201,143,183,229,231, 97, 74,208,
+162, 68, 36,198,200,108,112, 34, 80,230, 70,143,192,245, 64, 37,129,183, 10, 60,251,142,247,145,184,224,226,205,185,127,220,251,
+144,224,180,137, 26,167, 86, 19,183, 28,176,174,170,108, 64, 46,203,111,113,230, 42,253, 49,187, 33, 91, 47, 67,108,218,138,206,
+115,191,123,134, 78,141, 67,212,245,190, 47,151, 85,186,151,225,126,117, 55, 39, 31,183,108,254,176,237,182,245,137,212,234,201,
+141,255, 0,127,208,157, 61, 90,155,251,125, 26,116,254,149,173, 64,102,119,189,207,123,194,238,249,225,192,205, 49,197,147,141,
+181, 99,162, 50, 7, 72, 61, 86,108,240, 52,161, 73,177,127,134,192,158,101,128, 60,128,171,140, 93,227,123,155,180,115,243, 86,
+ 76,113,185,226, 77,153,135, 6, 84,229, 97,134, 87,199,201,147, 22, 57, 62, 34, 16,107,208, 60,116,234,246, 84,205,211, 27,182,
+206, 67, 13,228,237,190,168,227,144,222,170, 92, 97, 47,166,214, 47,253,163,106,233,235,183,179, 87,182,166, 44,123, 74,236,133,
+ 88, 96,182,195,209, 34,230, 72, 61, 39, 67,223,171,167,163,242, 84, 6, 3, 35,189, 59,161, 98, 56,248,129,231,200,195,143, 46,
+124,133,154, 60, 88, 28, 28,121, 34,141, 97,205,105,167,138, 37, 85,234, 29, 77, 1,110,106, 71,141, 94, 97,119, 6,253,147,221,
+239,183,244,200,218,198,108,248, 5,159,211,170, 1, 14, 32,201, 12,151,151,212, 60,165,249,142,158,157, 7,217,122,181,244,253,
+134, 49,118,254,161,217,253, 58, 74,255, 0,119,106,151, 19,167,214,212,162, 78,143,197,102,125,122,117, 91,142,171, 95,141, 88,
+199, 15,110, 13,253,222, 51,183,255, 0,152, 52, 90, 64, 30, 3,153,160, 42,252,194,253, 75,104,211,244, 91,194,212, 6, 15,187,
+159,115, 94,237,104, 32,220,100,138, 22, 27, 15, 78, 16, 62, 20,105,119, 57, 34,102,176, 97,127,147,226,253, 96,108,120, 10, 92,
+125,251,120,149, 98,156, 73,138,251,154,237,187,194, 69,151,147,166, 37,105,113,119, 56,112, 97,212, 73, 88,215, 88,183, 14, 69,
+173,225, 91,173,198, 46,217,251,207, 31,239, 83,183,125,237,104,253, 39,169,108,127, 83,110,178,244,186, 93, 67,174,221,125, 58,
+109,250,118,183, 26, 28,145,118,151, 65,196,135,107,232, 24,114,186,154,159, 27, 71, 67,172, 61,110,171,155,104,235,219,171,225,
+175,230,227, 64,103,135,112,238, 80,246, 62,247,188,117, 11,110, 59, 96,201, 8, 50, 33, 88,229,141,225, 93, 75, 30, 66, 70, 76,
+ 69,133,248,152,206,146, 45, 64, 77,231,184,102,205,147,100,245,233, 20,191,123,100, 97,125,228, 96, 75,136, 97,192, 77,193, 80,
+ 70,126, 11,151,114, 46,127, 68,121,241,173, 78, 52, 29,180,187, 20,171,142,118,239,184, 2,200, 50, 52,190, 57,196,211,115,213,
+234,157, 70, 62,119,213,171,233,166,110, 48,118,171, 98,229,141,208,237,190,155,212,143, 91,215,147, 28, 39,170,233,173,186,197,
+218,221, 94,150,159,155,226,211,111, 10, 3,207, 6,249,187,103,110,123,102,231,149, 32,209,159,137,219,179,190, 3, 33,233, 35,
+229,103,188,111, 36, 98,252, 15, 2,192,251, 71,144,169,242,247, 87,112, 38, 36, 89,145,229,197, 52,155,158, 67,193,143,183, 68,
+145,122,156,117, 92,255, 0, 68, 12, 61,102,142, 55,248, 62, 18,101,107,117, 8,240,225, 91, 44,168,123, 91,214,226,122,211,182,
+122,253, 17,122, 14,179,227,117,186,125, 85,232,244, 53,182,173, 61,109, 58, 52,254,149,173,198,163, 62, 47,100, 22,221, 58,141,
+180,235,114, 62,248,188,184,183,191, 82,195,212,252, 95, 9,234,254,183,233,251,106,130, 36, 27,246,226,189,147, 62,243,156,241,
+ 98,103,194,153, 1,164,101, 89,213, 76, 51, 60, 8,236,152,174,232, 92,133, 4,170,189,131,112,170, 21,221,183,205,198, 77,152,
+ 79,149, 38, 52,152,253,195, 38, 4,193,146, 37,146, 72,215, 18,105,149,103, 16, 59, 69,113,197, 72, 83,110, 71,152,173,199,167,
+216, 78,198, 70,172, 31,184,122, 36, 27, 73, 7,163,232, 91,143, 29, 93, 61, 22,250, 42, 12, 88,253,152,184,170, 34, 59, 71,164,
+ 25, 49, 5,180,152,134, 63, 87,164,116,120,234,183, 91, 77,180,254,149,185, 80, 21,123,190,241,188,227,247, 44, 88, 48,229, 36,
+ 27,124,173, 6, 50, 58, 71, 28,234,179, 76, 36, 37, 50,134,174,180,114, 55,194, 98,225,160,254,149,101,251,107,185,183,184,113,
+123,119, 28,230, 54,100,114, 38,221, 22, 88,104,212,233, 25,189, 65,251,249,164,126,163, 73,240,252, 26, 1,249, 78,190,117,232,
+179, 99,246,215,223,112,182, 75,109,223,126,128, 4, 29, 73, 49,253, 93,136,109, 58, 3, 55, 83,150,171, 91,194,254,218,172,198,
+198,252, 62,235,198,216,205,177,245,238,162, 46,156,152, 90,181,117,142,141, 33, 91,159, 90,246,183,233, 95,198,128,205,100,238,
+125,193,151,143,178,238,178,110, 93, 53,151,123,203,198, 76,120,162, 10,162, 60, 85,220, 35, 85,118,213,119,212, 32,226, 15, 14,
+ 71,152,167,193,221,251,222, 78, 38, 59, 9,162,138, 89,241,251,113,204,189, 48, 66, 62,237, 43,197,146,218, 73,183, 32, 10,143,
+ 10,218, 79, 7,109,122, 24,125, 65,219,125, 7,170, 62,155,168,248,221, 31, 89,213,123,244,245, 54,158,183, 87, 95, 47,139, 85,
+252,106,149,246,206,195,202,193,120,241,114, 54,168, 48, 99,159, 14,124,150,196,159, 13, 81,140, 83, 25,113,163,156,130, 84,163,
+184,101, 10,121,241, 11, 64, 89,118,222,233, 62,229,183, 48,205,149,100,202,135, 39, 51, 23,168,160, 47, 89, 49, 50,100,198, 19,
+ 4, 30, 97, 69,237,194,245,139,155,188,119,252, 92, 28,204,238,188,115, 51,226,111, 51,193, 31, 72, 1, 3,237,153,107,141, 17,
+107, 27,176,117,127,138,254, 54,181,110,176, 48,118, 14,190, 12,219, 76,152,119,143, 22,104,176, 99,197,154, 13, 39, 25,165,136,
+204,209,136,219,226, 81, 34, 37,200,224, 15,180,213,102,215,181,246, 86, 12, 59,132, 49,228,109,185, 36,140,135,220,229,154,124,
+ 73, 31,165, 36,242, 77, 50,228,144, 71,238,210, 71, 43,241, 14, 22, 0,242,168,194, 43, 50,119,222,228,195,238, 8,118,160,222,
+170, 12,105, 48, 35,203,156,174, 60, 49, 48,206,150, 69,118,110,164,203, 40, 42,130,209, 44,106,215, 42,117, 94,245, 5,251,147,
+185,153,242,177, 70, 76, 77,147, 43,171,226,197, 24,199, 34, 88, 14, 73,143, 86,217, 49,147,165, 43,116,133,180, 76,117,107,191,
+133,109,242,241,251,124,239, 88,141,158,118,255, 0,190, 2,219, 11,173, 38, 63,169,210, 75, 91,164, 29,181,243,213,107,123,125,
+181, 93, 38, 39, 97,152,243, 6,173,155, 67,202,135,112,253,238, 32,179,235,109, 61, 83,175,131,117, 47,107,254,149,252,111, 68,
+ 82,167, 55,112,147,115,237,125,158,108,140,142,164,121,249,184,120,249,178,162,182, 62,168,155, 40, 68,241,186,222,233,171, 72,
+ 71, 0,219,137, 3,133, 70,220,118,157,141, 95, 3, 27, 1,229,149, 35,222,151, 15, 34, 54,121, 85, 98, 15, 19,206,248,145,219,
+ 64, 49,130,193,133,175, 99,194,252, 44, 53,239,143,177, 29,154,211,156, 15,184, 76, 42, 5,228,199, 24,125, 31,209,183,197,211,
+209,123, 91,194,151, 3, 27,182,147, 7, 17, 54,246,219,142, 8,158,216, 70, 25, 49,204, 94,167,226,254,196,171, 91,171,243,114,
+248,185,208, 30,111,186,122,156,125,199,116,200,141, 30, 56, 32,222, 6, 34,238, 41,144,250,227, 67,183,195,167, 23,211,240, 83,
+ 27,179, 88,182,174, 26,175,106,215,203,191, 79,177,246, 22, 54,233, 12, 18,101,100,197,181, 9,208,232, 50, 32,146, 60, 97, 32,
+105,236,202,193, 53, 14, 38,245,117,147, 7,111, 24,167,245, 71,111,233,122,149,245, 93, 71,199,211,235, 52, 38,142,174,166,183,
+ 91, 70,139, 95,226,181,189,149, 3,108,199,236,111, 73,184,253,198,219, 41,193,233,255, 0,245, 99,135, 38, 31, 75,165,165,255,
+ 0,239, 93, 38,211,163, 78,191,159,133,175,237,160, 42,247, 77,202, 76,157,241,101,209, 62, 36, 71, 99,220,219,163, 56, 49,157,
+113,203,137,103,211,114, 46, 3, 27, 26,133,186,101,110, 56,219, 31,101,100,227,228, 58, 55, 82, 14,188, 64, 92,204, 70,223, 60,
+186, 28,243, 55, 41,107,121,155,243, 2,181, 91,254, 47,110, 52,112, 14,230,109,187,166, 25,142, 55,222, 18,227,129,112, 62, 61,
+ 29,118,242,249,173,225,206,143,185,227,237, 62,159, 31,239, 83,133,233,250,209,250, 95, 85, 36, 26, 58,255, 0,220,244,186,173,
+109,127,171,110, 62, 84, 6,127,180,183,189,215, 54,118,199,220,242, 19, 48, 75,183, 96,238,105, 52,113,136,196,109,153,214, 15,
+ 7,194, 72, 42, 58, 64,169, 60,109,231, 84, 89, 29,231,189, 71,129,147,146,141, 23, 86, 45,191,122,203, 91,167, 14,166, 6,122,
+226, 65,194,252,186,103,143,153,173,182,207,137,177,133,200,251,133,176, 52,153, 47,147,232,165,199, 35,168, 71,247,157, 38,231,
+111, 58,168,205,218,187, 51, 54, 29,223, 12,100,237,152,211,228, 67,144,155,158, 70, 54, 70, 26,100, 71, 27, 50,140,150,145,245,
+ 18,182,125, 58,245, 11,106,181,248,213, 33, 89, 62,243,189,174,118, 71,111,250,216,195, 71,155, 52, 13,185, 8,151,227,137, 54,
+209,184,136,194, 95, 72, 58,222,196,131,125, 35,207,141, 69,218,123,143,117,130, 14,215,197,138,110,180, 15,139,179, 69,153, 25,
+141, 72, 30,182, 34, 25,167,154, 71, 18, 52,141,167, 82,116,193, 28, 14,174,117,172, 92,110,203,251,168,137,142,209,247, 95,169,
+ 45,198, 92, 95, 79,234,172, 88,241,213,163,169,107,240,231,110, 28,168,141,143,217, 30,163, 21,152,236,254,163,163,140, 48,111,
+ 38, 38,174,134,161,233, 58, 35, 87,201,170,221, 45, 60, 63, 86,128,193,195,220,157,209,182, 46,110, 54, 28,173,156,240,100,110,
+249, 76,207,233,209,109,141,157,233,214, 57, 95, 42,104,180, 67,196,223, 69,216, 93, 64,224, 56,236,123,223,184, 51,187,107, 23,
+ 27,113,131, 73,197,111, 83, 12,200, 87, 83, 25,206, 52,146,226, 91,223, 44, 65, 63,164, 42, 86, 70, 63, 98, 28,159,241,103,102,
+245, 75,148,197,186,146, 98, 9, 61, 95,192, 31, 85,218,230, 95,146,247,227,242,251, 42, 79,114,109, 88, 57,240, 97,253,237,155,
+ 30, 46, 22, 62, 84, 51, 50, 60,176, 36,115, 74,142, 26, 8,221,229, 62, 50, 1,193, 72,213,202,128,202,195,220, 29,199, 14,116,
+126,170,120,228, 81,156,251, 76,184, 75, 16, 4, 52, 91,113,205, 57, 90,199,197,198, 69,189,190, 93, 36,123,232, 88,253,225,191,
+228,225, 99,244,165,134, 60,140,140,126,219, 97, 33,136, 48, 89, 55,121, 94, 44,150,211,168, 92, 88, 13, 34,252, 43,102,184,251,
+ 7,223,108,218,176, 62,252,233,217,255, 0,121, 7,170,233,216,115, 26,186,154,116,219,232,168,251,100, 61,138,177, 48,218, 78,
+206, 99,234, 99, 22,244,207,136, 71, 84,200,222,142,250, 27,230,234,223,165,252,175,150,128, 77,251,117,207,218,103,216,176,163,
+149,100, 57,143, 60, 89,146,186, 0, 95,163,133, 62, 64, 96, 7, 5,188,145, 2,109,238,172,156, 61,223,191,105,217,247, 9,230,
+140,226,229, 97, 96,203, 42, 66,137, 34, 28,156,140,118,158, 88,114, 2,183, 90, 23,127,135,162, 66,232,243,173,214,247, 6,196,
+240, 69,254,100,108, 17,143,213, 83, 15,175,120, 66,117,130,182,157, 29,102,182,173, 58,190,139,212, 56,113,251, 55,239, 12, 22,
+199,109,171,239, 1, 12, 99,109,233,201,139,213,232, 20, 61, 31, 78, 21,181,104,233,223, 70,159,209,189,184, 86, 91,171,224, 84,
+100,112, 59,175,186,167,219, 3,204, 82, 9,242,102,217,134, 52,243, 46, 59, 16,187,164,221, 41,109, 14, 44,242,126,237, 69,140,
+102, 66, 24,223,143, 42,212,119, 46,102,231,134,187, 70,217,141,152,176,201,155,215, 92,172,214,141, 73, 97,143,137, 36,228, 42,
+112, 85,234, 50, 92,219,144,189,188,234, 78,221, 7,102, 46, 51, 13,172,237, 94,152,228,194, 91,211,190, 49,143,213,151, 83,143,
+242, 53,186,186,244,244,252,111,109, 53, 63,125,135, 99,108, 52, 29,198,112,189, 31, 85, 76,126,189,225, 17,245, 64, 98,186,122,
+199, 78,173, 58,190,139,248, 83,216, 15, 61,217, 59,179,126,138, 62,221,195,199,140,203,137, 22, 14,198,153,114, 72, 96, 8,254,
+185, 52, 75, 36,178, 79, 50, 76, 92, 1,120,196,104,215, 96,111,206,171,160,238, 77,231, 96,131,113,147, 27, 51,212,228,122,253,
+203, 43, 37, 58, 8, 75,172, 25,227, 16, 52,242, 72,235,166, 45, 63, 8, 88,254, 48, 72, 3,225, 21,190,124,126,211,108,205,177,
+144,237,126,172, 67, 24,217,237, 38, 40,147,211,144,122, 94,148,106,190,139, 95, 70,142, 22,189,168, 25,152,221,144, 88, 29,201,
+182,125, 65,178,109,215,151, 19,230,215,254, 50,225,219,137,234,127,107,252,175,155,141, 95, 96, 32, 79,221,251,139,110,179,109,
+196,160,128,238,185,120, 28, 22,205,208,139,105, 25,201, 99,127,155,172,121,249,112,172,214,221,189,119, 6, 56,219,159, 3, 61,
+157,229,237,237,136,140, 87, 49,153, 24,200,211, 9,206, 55,169,101,141,242, 10,198,196,106,249,185, 30, 66,183,126,155,180,126,
+247, 36,182,213,247,201,231,121, 49,125, 87, 8, 79,134,173,127,216, 95,250, 30,202, 6,110, 55, 99, 52,120,203,158,219, 54,131,
+139, 24,194,234,201,136, 63,194,106, 94,151, 64,179,127,101,171, 78,157, 63, 13,237,106,158,192, 89,118,214,252,187,158,207,139,
+147, 52,201,145,146,201,121,153, 80,196,126,102, 64, 94, 34, 73, 67,240, 16,124, 46, 13,184, 85,191,173,143,202,170, 54,204,125,
+142,231,238,102,193,191, 70, 27,250, 73, 32,255, 0,187,252,126,159,251, 38,254,207,231,209,225,206,222, 53, 99,233,207,235, 39,
+254,209, 63,214,165, 60, 5, 67,122,216,252,171,189,108, 94, 84, 15, 78,127, 89, 63,246,137,254,181,119,167, 63,172,159,251, 68,
+255, 0, 90,148, 21, 36,122,216,255, 0, 86,187,214, 71,229, 64,232, 31,214, 79,219, 79,245,169,194, 15,229, 39,237,167,219, 74,
+120, 2, 87,168, 78,158,171,127,119,127,163,169,166,186,135,160,105,233,220, 95,163,206,227, 79,246,191,173,202,186,128,255,217,
+};
+#endif
diff --git a/source/blender/src/pub/unix_publisher_splash.jpg.c b/source/blender/src/pub/unix_publisher_splash.jpg.c
new file mode 100644
index 00000000000..c1ec0dc0430
--- /dev/null
+++ b/source/blender/src/pub/unix_publisher_splash.jpg.c
@@ -0,0 +1,950 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+/* DataToC output of file <splash_jpg> */
+#if !defined(WIN32) && !defined(__APPLE__)
+int datatoc_tonize= 29208;
+char datatoc_ton[]= {
+255,216,255,224, 0, 16, 74, 70, 73, 70, 0, 1, 2, 0, 0,100, 0,100, 0, 0,255,236, 0, 17,
+ 68,117, 99,107,121, 0, 1, 0, 4, 0, 0, 0, 50, 0, 0,255,238, 0, 14, 65,100,111, 98,101, 0,100,192, 0, 0, 0, 1,255,
+219, 0,132, 0, 8, 6, 6, 6, 6, 6, 8, 6, 6, 8, 12, 8, 7, 8, 12, 14, 10, 8, 8, 10, 14, 16, 13, 13, 14, 13, 13, 16,
+ 17, 12, 14, 13, 13, 14, 12, 17, 15, 18, 19, 20, 19, 18, 15, 24, 24, 26, 26, 24, 24, 35, 34, 34, 34, 35, 39, 39, 39, 39, 39, 39,
+ 39, 39, 39, 39, 1, 9, 8, 8, 9, 10, 9, 11, 9, 9, 11, 14, 11, 13, 11, 14, 17, 14, 14, 14, 14, 17, 19, 13, 13, 14, 13, 13,
+ 19, 24, 17, 15, 15, 15, 15, 17, 24, 22, 23, 20, 20, 20, 23, 22, 26, 26, 24, 24, 26, 26, 33, 33, 32, 33, 33, 39, 39, 39, 39, 39,
+ 39, 39, 39, 39, 39,255,192, 0, 17, 8, 1, 15, 1,244, 3, 1, 34, 0, 2, 17, 1, 3, 17, 1,255,196, 0,194, 0, 0, 1, 5,
+ 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 2, 4, 5, 6, 7, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 16, 0, 2, 1, 3, 2, 4, 3, 4, 4, 9, 8, 6, 7, 6, 2, 11,
+ 1, 2, 3, 0, 17, 4, 18, 5, 33, 49, 19, 6, 65, 81, 20, 97,113, 34, 50,129,145,209, 7,161,193,225, 66, 82,146,178, 35, 21,
+177, 98,114,130, 51, 67, 36, 22,240,210, 83, 99,115,131,162,179,195, 52, 84,116, 54,147,163,211,196, 37, 23,241, 53,194,226, 68,
+100,132,148,164, 69,133, 38, 71, 17, 0, 2, 1, 3, 2, 4, 3, 6, 4, 6, 3, 1, 0, 0, 0, 0, 0, 1, 2, 17, 3, 4, 33,
+ 18, 49, 65, 81, 5, 97,113, 19,129,145,161,209, 34, 50,177,193, 66,146,240,225, 82,114, 51, 20, 98,147, 21, 52,255,218, 0, 12,
+ 3, 1, 0, 2, 17, 3, 17, 0, 63, 0,244,254,224,238, 9, 59,127,111,143, 51, 67,204,154, 98, 78,154,190,139, 94, 48,111,227,
+ 88,189,187,247,157,181,111,121,203,182, 74,211, 97,102,202,116,192,147, 54,164,144,254,138, 72,167,230,246, 16, 43, 67,187, 50,
+ 59,119, 27,111,129,187,154, 24,230,194, 99, 18,162, 76,130, 69,234,116,174, 13,155,135, 32,107,198, 59,154, 93,139,117,238, 13,
+167, 19,177, 96, 16,100, 52,145,170, 24, 87, 66, 9,117,130,140, 20,114,211,109, 71,221,122, 3,232,137, 38,156, 48,180,141,107,
+126,145,168, 28,153,129,254,209,255, 0, 88,210,146,247, 30,118,161, 53,237,115, 66, 6,245, 19, 90,226, 70,253, 99, 80, 51,228,
+ 19,110,171,143,235, 31,182,160,183,181,237,198,164, 7,229,160, 8, 38,159,145,149,255, 0, 88,253,180,221, 73,188, 38,147,245,
+141, 55, 10, 92, 5, 0,230, 92,142, 98, 87,253, 99, 81,245, 25, 54,191, 85,191, 88,210,227,123,248, 84, 79, 15,117, 0, 60,140,
+172,165, 10, 58,174,183, 55,184, 99, 66,108,204,171, 88, 79, 37,255, 0,166,223,109, 67, 45,137,145, 86,252, 0,184,250, 79,228,
+160, 95,133,234, 50,135, 25,121,103,158, 68,159,174,223,109, 75,213,229, 91,251,121, 63, 93,190,218, 2,220,139, 10,125, 62,116,
+ 4,198,102, 97,229, 60,159,174,223,109, 72,101,102, 30, 30,162, 79,215,111,182,134,128, 3, 75, 80,185, 52, 5,129,147,148, 0,
+253,252,159,174,223,109, 38,203,201, 31,223,201,250,199,237,170,229,175,107, 82, 28,120,154, 2,196,121,179,234, 58,167,113,229,
+118, 63,109, 20,101, 78,220,167,107,121,235, 63,109, 14, 21,248, 9, 32, 17,115,246, 82,233,196, 73, 58, 7, 14,103,133, 64, 20,
+229,100, 40, 7,168,228,121,234, 63,109, 72,101, 79,227, 43,251, 62, 35,246,213, 80,136, 77,134,162,166,228, 90,246, 22,247, 83,
+172, 76, 46, 3, 31,167,202,128,176, 50,114, 8,191, 89,248,248,106, 63,109, 47, 81,147,199,247,175,250,199,237,170,218, 92, 88,
+171, 2, 7,178,164, 76,136,191, 18,131,238, 60,120,253, 20, 1,253, 68,246,254,217,255, 0, 88,253,180, 23,201,200, 75, 19, 60,
+159,174,199,241,212, 11,158,122, 72,246,212, 9, 15, 96, 5,173,207,133, 80, 20,230,100, 91, 80,157,192,181,201,212,223,109, 86,
+108,236,199, 98, 68,242,129,224, 3,183,219, 77,144, 8, 42, 63, 52,212, 81,108, 11, 55, 1,206,254, 66,168, 13,235, 50,209,110,
+217, 18, 31, 33,173,184,159,174,163,235,115, 87,230,200,144,147,196,252,109, 97,248,104, 6, 64, 88, 19,203,146, 10,139,134, 99,
+112,108, 60,232, 3, 28,204,208,110,114,165, 3,200, 59,125,181, 33,157,150,194,235,145, 47,235,183,219, 85,198,146, 44,126, 43,
+ 83, 2,111, 96, 44, 40, 3,140,204,235,252, 89, 50, 15,235,183,219, 77,235,243, 17,197,242,101, 32,248,107,111,182,129, 32, 3,
+137, 53, 40, 99,214,117, 56,225, 64, 92,245,249, 71,128,158, 67,127,231,183,219, 67,245, 89,235,114,217, 18,241,228, 58,141,246,
+210, 0, 3,112, 41,152,106, 62,234, 2, 45,155,159,225, 60,191,174,223,109, 56,202,220, 24, 95,212, 74,191,215,111,182,144, 0,
+ 55, 63,162,162,101, 12,229, 84,112, 20, 1, 86,124,206, 23,201,152,255, 0,204, 96, 63,150,166,217,217, 17,240, 57, 18, 95,250,
+109,246,213, 55, 47,126, 45, 97, 76,218,126,107, 92,208, 22, 91, 59, 50,223, 12,242, 27,255, 0, 61,190,218,129,207,204, 11, 99,
+145, 38,175, 99,183,219, 65,212, 74,241,224, 77, 68, 32, 6,252,205, 0,101,204,206, 28, 78, 76,191, 76,141,246,209,127,136,101,
+129,110,188,132,249,151,111,182,171, 82,181, 74,150,129,189,118,105,255, 0,246,137,127, 93,190,218, 94,183, 55,255, 0, 19, 47,
+235,183,219, 65,191,149, 55, 26, 2,199,173,204,255, 0,196,203,250,237,246,210,245,185,191,248,137,127, 93,190,218, 10,198,205,
+242,169, 54,231, 97, 68,244,238, 62,107, 47,180,145,248,168, 82, 94,179, 55,255, 0, 19, 47,235,183,219, 79,235, 51, 63,241, 18,
+254,187,125,180,194, 40,199, 54, 45,231, 97,248,205, 72, 34,168,184, 78, 63,206, 52,161, 42,133,235, 51,127,241, 18,254,187,125,
+181, 53,159,112, 99, 97, 52,191, 75,176,254, 83, 76, 11, 95,225, 54,229,125, 34,213, 33, 30,175, 18,124,239, 65, 82, 98,108,176,
+108,249,110, 60,192,118, 39,249,104,131, 38, 64, 1,235,206,231,159,206, 64, 63,203, 65, 17,252, 69, 72,246,222,140, 34,186,240,
+229,200,251,104, 9,122,236,149, 33, 81,216, 92,254,115, 51,126,209,166,108,140,182, 60,102,144,123,152,129,195,221, 73,186, 8,
+191, 27, 45,239,231, 80,151, 43, 25, 21, 64, 36,128, 60, 7, 58, 16,144,200,201, 34,226,121, 57,126,147,115,250,234, 93,108,203,
+219,171, 37,184, 92,234,111,182,169, 62,230,131,132,113,125, 36,212, 61,124,199,141,133,188,170,148,211, 47,149,107,137,228, 31,
+215, 63,109, 49,202,146, 50, 53,100,183,210,228,254, 58,197,146,105,158,218,156,155,251,105,162,133,157,192,243,160,161,182,115,
+133,141,178,100, 62, 44, 65, 99, 97,248,170, 13,187, 42,142, 19, 72,198,214,189,200,252,117,157,233,207, 47, 31, 26, 28,176,145,
+ 96, 7, 58, 3, 99,248,130,244,122,186,159, 87, 67, 86,187,155,219,175,163,159, 58, 85, 75, 71,248, 91,127,251,173,191,254,170,
+149, 65,169,155,222,189,173,254,109,219, 49,246,239, 86,112,250, 77, 20,253, 65, 31, 82,246,136,166,155,106, 79,210,243,167,237,
+126,198,216,123, 93, 18, 92, 44,113, 38,225,211, 84,155, 58, 77, 77, 35, 16, 44,229, 3,179,116,195, 30, 36, 45,116, 77,196,199,
+253, 8,255, 0, 97,104,163,133, 82, 1,145, 72, 35,143,133, 64,220,248, 94,212, 73,136,212, 61,212, 48,212, 32,224,158, 84,202,
+205,115,126, 84,224,138, 70,220,175, 64, 72, 26, 68,211,112, 3,141, 43,138, 1,195, 6, 4, 15, 10,131, 91,149, 61,237,225, 81,
+ 32,222,128,163, 48,213, 51, 0,125,159, 80,166, 10, 47, 72,181,220,183,159, 26,107,159,174,161, 66, 92, 3, 80, 44, 77, 33,206,
+156,248, 80, 8, 3, 72,142, 20,181,120, 83, 27,147, 64, 38, 42,128,147,192, 1,198,177,100,223,101,215,251,152,215, 64,229,170,
+228,159,168,138,219,208, 8, 55,227, 88,121,251, 67, 71,170,124, 81,169, 57,180,126, 35,221,236,175,159,220,158, 82,183, 25, 99,
+ 54,148,106,231, 79,187,195,216,123,176, 22, 51,155,142, 66,171,149, 20,107,246,155, 91,102,235,139,149, 24,140,252, 19, 11,150,
+ 67,198,255, 0,209,181, 91, 18, 70,110,110, 1,246,240,174, 21, 89,145,131, 41, 42,195,136, 35,129, 6,183,176, 55,145, 33, 88,
+114,200, 15,109, 43, 47, 32,127,165,237,174, 24, 93,210, 55, 41,111, 33,168,203,130,151, 8,203,207,163, 59,102,118,215, 10,220,
+177, 89, 71,156,121,199,203,170, 54,145,174, 6,151, 0, 19,115,199,195,217, 70, 86,227,204,242,160,136,245, 88,112, 34,223, 9,
+168,133, 22, 7,128,177,183, 14, 28, 15,186,190,177,242,195,252, 36,240, 60, 79, 26,105, 63, 55,192,131,199,232,164,177,142, 97,
+138,169,226,120,222,223, 69, 65,144,222,236,228,251, 72, 30, 52, 4,152,131,199,149, 49, 0,220,142, 85, 2, 37,191, 48,126,138,
+146,240, 23,110,103,157, 84, 1, 76,165,138,223,141,141,173, 85,228,144, 57,211,249,138,120,159, 51, 79,145, 54,182, 42,188,135,
+ 11,208, 25,128,182,145, 84, 19,125, 71,229, 20,195,136,177,111,125, 48,103,101,181,169, 44, 71,153, 63, 85, 0,218,213, 77,148,
+123,233,216, 51,252,162,194,164, 20, 47, 31,229,167,214,164,216,113, 52, 4, 58, 55, 23, 38,244, 68, 54,250, 42, 26,158,252,120,
+ 10,102, 11,243, 31,170,128, 61,238, 41,135, 62, 60, 40, 87, 37,120, 2, 13, 58,181,151,143, 58, 2,108,234, 27, 72,226, 79, 51,
+ 67, 36,131, 97,240,138, 68,146,124,169, 4,102,228, 9,165, 75, 65,152,134,240,189, 63, 26, 42,192,199,230,101, 95,121,251, 47,
+ 83, 88, 98, 22,212,204,215,240, 81,111,194,106, 2,189, 46, 39,128,227, 86, 66, 40,249, 80, 27,120,177,191,216, 41,192, 99,193,
+ 77,188, 72, 2,212, 21, 0, 34,144,248, 91,223,195,249,106, 75, 10,254,115,129,238,226,104,193, 47,225,198,246, 36,209, 4, 64,
+ 3,126, 22,170, 42, 5, 35,136,126,107, 49,246,155, 3,248,232,130,200, 70,136,213,108,110,110, 53, 17,244,181,234, 64,194,160,
+107,113,127,105,168,182,102, 44, 98,194,236,124, 44, 42, 2, 76, 36,111,137,137, 43, 80,233,249, 14,124,175, 81, 59,128, 96, 2,
+ 71,192,121,154,175, 46,108,231,128,178,251,133, 82, 23, 68, 36,142, 63, 77, 39,233, 32,187,184,246,220,214,120,121,164, 23, 44,
+ 79,211, 80,104,216,181,143,133, 11, 66,248,200,199, 64,108,111,238, 21, 7,220, 2,216, 36,127, 93, 6, 40,126, 13, 84,242, 65,
+166,205,225,202,128,111, 89, 59, 92,139, 47,186,135, 36,179,191,204,228,253, 53, 48,129, 22,231,199,141, 88,138, 37,156, 5, 91,
+ 15, 18,106, 26,166,133, 36,141,139, 15,109, 89,244,199,235,227, 86, 76, 35, 30,236,228, 30, 28, 45, 85,134, 85,223,151, 14, 66,
+169,146,185,142,220, 45,198,142, 35,210,160, 26,176, 52,223, 89, 31, 17,226, 13, 84,152,179, 57, 81,200, 84, 52,180,212, 48,131,
+169, 98,190, 21, 97, 33,104, 13,219,131,120, 15,101, 7, 13,136, 58, 91,194,173, 78,196,198,204, 5,141, 8,221, 93, 74,239, 60,
+ 40,116,134,177,246, 84, 92,198,224, 0,215,191,231, 85, 86, 64, 5,252, 77, 74, 16, 69,252,168,196,120,234,104,116,191,194,252,
+194,222,154,222, 63,248,155,210,169,216,122,109, 62, 30,159,255, 0,152,165, 80,222,159, 18,200,249,163,191,132,113,254,194,209,
+ 46, 41,145,111,164,255, 0,187,143,246, 22,166, 98, 7,194,180,114, 43,205,109, 67,221, 64, 53, 98,104,174,223, 69, 4,196,109,
+ 66, 17, 6,159, 87,141, 49,132,143, 19, 82, 17,112,231, 64, 53,252,111, 75, 87,141, 56,132,143, 26, 69, 26,220, 40, 6,185,167,
+118, 33, 24,131,196, 2, 71,213, 77,102, 30, 20, 41,175,211, 35,206,214,160, 43,142, 2,152,145,127,117, 45, 62,116,224, 84, 40,
+220,106,132,251,190, 36, 79,160,106,148,142,101,109,111,172,213,249, 87, 90, 50, 3, 98,192,168, 62, 87, 21,204,190,221,153, 27,
+ 21, 49, 19,111, 21,226, 43,231,247, 12,140,155, 74, 11, 30, 13,238,173,100,150,234,120, 30,236, 27, 24,247, 92,189,121,210,148,
+164,107,182,190, 38,152,223,113,199,247, 79,248, 41,255, 0,142,227,255, 0,178,127,193, 89, 62,131, 51,253,131,253, 84,142, 14,
+ 88, 4,152, 88, 1,196,146, 57, 87,204,255, 0,127,184,255, 0, 75,255, 0,175,249, 31, 67,253, 44, 15,234, 95,191,249,154,255,
+ 0,199,160,183,246, 79,248, 41,134,255, 0, 8,254,233,255, 0, 5, 96,210,174,127,250,217,127,212,191,106, 58,127,230, 98,255,
+ 0, 75,253,204,185,155, 62, 38, 65,234, 65, 19, 69, 39,231,114,210,125,190,250,167, 86, 49,240,115, 50,191,238,216,242, 74, 60,
+209, 73, 31, 88,163,190,203,187, 70,186,159, 10, 96, 60,194, 19,252,149,229,154,187,117,187,190,155,215, 86,227, 26, 71,224,122,
+ 96,237, 90, 74,222,245,167, 5, 41, 85,252, 66,237,187,204,184,100, 69, 53,228,131,144,253, 37,247, 87, 69, 22, 84, 19, 42, 73,
+ 27,134, 67,198,245,197, 50,178,146,172, 10,176,224, 65,224, 69, 88,194,206,159, 6, 77,113, 27,169,249,163, 63, 41,175,110, 23,
+115,157,154, 91,189, 89, 67,133,127, 84,126,104,241,230,118,232, 93,173,203, 84,140,248,211,244,203,249,157,173,227, 63, 43, 94,
+245, 17,107,241, 62,225,225, 64,194,204,198,220, 98,234, 70, 62, 49,243,198,109,117, 52,116,138, 38,213,240,218,191, 67, 9,198,
+113, 83,131, 82,139,213, 52,124, 41,194, 80,147,132,211,139, 92, 83, 30,196,113, 6,169,207, 41,227, 26,159,233, 26,204,220, 59,
+183,183,182,173,209,182,172,249,228,199,153, 2,182,182, 86, 49,217,198,161,197,117,126, 17, 86, 49,243, 48,243,213,167,193,200,
+ 76,136, 75, 16, 36,141,131, 14, 30, 28, 60,107,175,167, 52,148,156, 90, 79, 84,233,161,202, 55, 33, 38,227, 25, 38,215, 21, 93,
+ 87,176, 32, 85, 60, 15, 26,151, 77, 23,141, 61,136,227,192, 10,131, 16,199,216, 57, 84, 54, 59, 58,168,243,164, 89,138,252, 60,
+ 60,232, 51, 77, 20, 8,102,157,214, 40,215,230,145,200, 85, 23,225,204,213,120,247, 93,182, 87, 17, 67,155, 4,146, 57,178,162,
+202,140, 73,242, 0, 27,213, 73,189, 82,100,109, 39, 70,210, 45,139,114,102,185,165,196, 27, 42,216,120,154, 96, 60, 71, 58, 42,
+ 46,171, 22, 30,225, 80,164, 24, 6,183, 19,238, 21, 53,142, 82, 44, 18,222,255, 0,203, 71, 85,110, 67,133,170,122, 15, 2, 77,
+168, 10,221, 19,249,204, 63,150,156, 70,131,219, 69,115, 18,220,150, 22,168,117,225, 28,174,212, 2, 10, 1,176, 30,234, 32, 66,
+ 71,242,213,127, 87,118,248, 86,163, 38, 76,252,148,233,247, 80, 23, 35,143,133,249,112,250, 41,255, 0,114,186,117, 56,191,190,
+179,137,149,129,187, 19, 82,138, 18, 79, 30, 85, 10,203,111,149,140,164,243, 99,224, 0,251,106, 7, 52,115, 68,227,225,122, 4,
+144,216,139, 11,223,149, 66,121,177,112,162, 51,102, 76,144,196,159, 52,146, 48, 85, 30, 28,205, 95, 4, 23, 54,244, 75,168, 79,
+ 87,145, 33,176, 54, 30,193, 77, 41,152,139,179, 19, 88,248,125,221,219,243,238, 48,237,152,153, 7, 34,121,137, 85,104,208,232,
+ 4, 2,198,238,218,124, 7,133,111, 51,164,128,128,106,206, 50,141, 55,197,198,170,186,232,102, 19,132,235,178, 74, 84,116,209,
+212,168,136, 73, 53, 54,132,130, 47, 83,123, 70, 6,158, 38,137, 27,135, 23,101,191, 26,201,183, 69,161, 24,226, 85, 78, 62, 39,
+133, 41, 99, 37,184, 11,240,168,204,238,205, 96,108, 7, 27, 84,145,207, 79,143, 59,209,136,170,177, 92, 68,186, 79, 58, 50,162,
+ 56,212, 77,189,213, 89,148,179,146,124, 40,209,157, 8, 56, 80, 55,200,132,178, 50, 16,171,200,114,247, 81, 34,145,157,110,124,
+ 56, 90,163, 50,181,239,110,124,169,227, 70, 81,107,123,232,203, 30,172,132,224,177, 0,112, 6,165,143,116, 44, 61,159,142,142,
+ 33,234,123, 8,228, 77, 24, 66,136,160, 22, 5,173,198,136,146,117, 96,103,185,140,129,199,133, 83, 9,168,128, 43, 65, 86, 49,
+193,154,228,240,168,145, 10,112, 69,231,227, 66, 1, 99,249,183,227,202,145,199,115,119, 81,112,124,168,190, 60, 23,143, 58,112,
+242,216,216,219,242,208, 54, 52,105,210, 83,126, 44,106, 97,195, 45,136, 30,227, 80,210,215,248,141,174,109,122, 93, 48,199, 77,
+239,115,206,173, 9, 80, 77,140, 9, 31,188, 91,120,220,242,162,136, 35, 84, 0, 74,183,241, 60,120,210, 49,160,225,115,175,147,
+ 15, 15,101, 76, 64,186, 69,200,225,196,212, 45, 67,233, 95, 79,110,160,255, 0,187,218,246, 60,186,252,233, 82,176,244,247,208,
+109,233,237,255, 0,191,255, 0, 67, 74,130,165,232,192, 8,135,205, 35,253,133,169, 49, 21, 1,193, 18,255, 0,236,211,246, 69,
+ 56, 32,139,213, 50, 6, 82, 65,250, 40,119,189, 62, 67,124, 99,195,133, 10,246,160, 9,194,156, 16, 40, 33,129,241,169,222,128,
+150,160,125,148,170, 20,224,129, 64, 63,141,200,170,249, 76, 52, 5, 30,119,250,168,204,213, 79, 36,146,234,190, 22,163, 8, 16,
+ 38,214, 20,133,207, 26,113,192, 83,130, 0,168, 81,173,227, 77,107,181, 61,205,170,150,102,124, 88, 99, 77,245,204,121, 32,240,
+254,149,115,187,118, 22,160,231,114, 74, 49, 92,217,187,118,231,114, 74, 22,226,228,223, 36, 90,155, 34, 28, 88,245,202,214, 30,
+ 3,196,251, 0,174,123, 55,113,151, 44,149, 31, 4, 87,224,131,199,250, 85, 94,124,137,114, 95,169, 43, 92,248, 15, 0, 61,148,
+ 42,252,238,111,114,157,250,194,221, 97,111,167, 57,127,119,200,251,216,125,190, 22,105, 57,210,115,248, 71,203,230, 42,237,118,
+ 30,212,137, 99, 76,205,209, 53,200,214,100,199, 63, 42,143, 13,126,103,217, 88,125,175,132,153,187,188, 66, 65,120,225, 6,102,
+ 30,122,109,167,254,145, 21,208,253,224,119, 20,189,181,219, 89, 25,184,164, 12,185,153,113,241, 88,254,107,201,127,143,250,170,
+164,143,109,122,187, 54, 4,111, 63, 86,105, 75,234,219, 8,190, 21,231, 38,121,187,182,115,179, 23,110, 45,198,145,221, 54,184,
+211,162, 39,190,247,191,108,118,185, 24,217,185, 35,212, 40,225,137,142,186,221, 71,243,149,120, 47,245,136,172, 28,127,190, 94,
+210,154, 77, 18,199,151,142,183,254,210, 72,148,175,211,211,119,111,193, 94, 11, 44,178, 77, 35,205, 51,180,146,200, 75, 59,177,
+ 37,153,143, 18, 73, 60,201,168, 87,236,227,219,237, 40,210, 77,183,213,105,238, 71,227,167,220,175, 57, 86, 42, 41,116,122,251,
+217,245, 63, 75, 97,238,172, 33,149,141, 36,121, 81, 63, 8,242,161, 35, 82,159, 43,243, 4,126,139, 87, 11,187,237, 51,237, 25,
+ 70, 9,126, 36,111,138, 41, 71, 38, 95,180,120,215,158,253,223,247, 62, 87,110,111,248,214,144,250, 28,201, 18, 12,200, 73,248,
+ 74,185,210, 36,183,233, 33, 55,191,209, 94,247,221, 56, 75,151,180, 74,246,253,230, 63,239, 80,251,190, 97,250,181,249,254,247,
+218,160,163, 41,197,125, 73, 57, 41, 45, 28,146,227, 25, 31,160,236,221,210, 82,113,132,190,214,212,101, 30, 42, 45,240,148, 79,
+ 62,195,202,147, 14,117,158, 51,203,230, 95, 6, 30, 32,215,105,141,147, 28,177, 44,202,195, 76,159, 16, 39,133,112,149,210,246,
+236,236,248,242, 64,127,186, 96,203,238,111,202, 43,227,246,124,135, 27,174,195,127, 76,211,107,194, 75,230,143,171,221,108, 41,
+ 91, 87,146,250,160,210,126, 49,127, 38,121, 87,222, 81, 7,186,242, 10,144, 71, 74, 30, 35,250, 2,186, 95,187,236,204, 76, 30,
+219,154,124,185,146, 8,215, 37,238,242, 48, 81,242, 39,137,174,107,239, 40, 91,186,242, 7,251,168,127, 96, 86, 30,213,181,238,
+123,228,131, 7, 8, 23, 72,238,237,169,173, 28,122,172, 11, 31,125,189,245,251,159, 78, 55, 49, 45,198, 82,218,148, 98,219,240,
+ 72,252, 66,187, 43,121,151, 37, 24,239,147,148,146, 94, 45,158,175, 39,123,246,193,126,153,220, 7,180,136,228, 43,245,132,181,
+105,224,238, 91,118,230,133,240, 50, 35,200, 11,204, 35, 2, 71,188,115, 21,231, 18,253,218,239, 11, 1,146, 28,136, 38,144, 11,
+244,129,101, 39,216, 11, 11,125,117,202,164,153,251, 62,105, 40,207,139,153,142,196, 27,124, 44,172, 57,131, 92, 86, 37,139,137,
+250, 55, 91,107,175,240,143, 67,205,200,180,215,175,105, 36,250,105,243, 61,103,189,129, 29,179,159,171,202, 62, 31,243, 82,188,
+207,181,127,245, 22,221,111,246,195,241,215,107,184,111, 75,191,118, 30, 94, 99, 0,185, 41,211,139, 37, 71, 32,226, 72,248,129,
+228,192,222,184,190,212, 23,238, 45,184,127,190, 31,200,107,166, 52, 92,113,239, 70, 90, 52,228,159,237, 57,229, 78, 51,201,177,
+ 56,186,169, 40, 53,251,143,108,186,170,150,119, 10,170, 46,196,144, 0, 3,204,154,195,204,239,206,220,193,144,198, 50,122,238,
+ 56, 30,138,151, 3,250,223, 47,225,174, 43,191, 59,134,124,156,233, 54,108,103, 41,137,140,116,206, 1,183, 82, 65,207, 87,177,
+121, 91,206,170,246,175,103, 54,255, 0, 19,230,100,204,113,240,209,186,106, 84, 93,221,128,185,211,126, 0, 11,243,174, 16,196,
+183, 27,106,237,249, 56,167,170, 75,199,129,222,230,101,201, 93,118,113,226,164,214,141,191, 14, 39,109, 31,222, 54,197, 51,233,
+ 51, 73, 8, 60, 53, 60,102,223,244,117, 86,238, 54,116, 59,140, 98,124, 60,133,158, 35,249,241,176, 97,127, 35,106,225,247,127,
+187,104, 97,197,121,246,172,153, 30,100, 5,132, 19,105, 58,236, 47,101,101, 11, 99,229,194,184,253,135,124,203,216,115,211, 46,
+ 6, 38, 59,129,145, 13,254, 23, 79, 16, 71,159,145,240,170,177,108,221,131,150, 60,157, 87, 41, 7,151,126,204,212, 50, 96,169,
+ 47,213, 19,220, 94, 59, 45, 48, 84, 68, 37,200, 0, 2, 73, 60, 0, 2,188,223,239, 15, 62, 71,147,108,155, 26,103, 88,230,133,
+228, 82,140, 86,225,138,144,120,123, 43,151,219,155,123,221, 36, 59, 78, 20,178,202,114,136,234, 70, 92,216,132,185,187,146,120,
+ 40,191, 26,197,188, 39, 59,106,227,154,138,124,106,184, 81,234,110,230,122,133,215,105, 91,114,107,133, 31, 26,173, 52, 61, 79,
+ 35,189, 59,103, 6, 83, 19,230, 9, 92,112, 61, 21,105, 0,254,178,141, 63,134,173,237,221,205,176,111, 14, 35,194,204, 83, 49,
+229, 12,128,198,231,250, 33,192,191,209, 92, 43,125,216,238,171, 14,191, 89, 1,150,223,217,217,237,127, 45, 86,252, 85,198, 79,
+ 6, 70, 14, 76,152,243, 3, 22, 68, 14, 85,135,138,178,159, 2, 43,172, 49, 49,174, 38,173,220,110, 75,248,224,113,158,110, 85,
+166,165,118,210, 81,124,191,157, 79,161, 32,117, 50,105, 97,116, 52, 45,211,113,193,219, 99, 15,145, 60,120,200,222, 50, 48, 4,
+251,175,206,185,156, 14,229, 56,253,149, 30,255, 0,148, 58,153, 17,131, 2,131,253,228,193,138, 45,253,224,106, 53,229,185,185,
+219,134,245,156,114, 50,157,242, 50,167, 96,170, 57,241, 38,202,136,190, 3,200, 10,227, 99, 10, 83,148,183, 61,177,131,113,111,
+171, 93, 14,249, 25,241,132, 97,177,110,148,210,146, 93, 19,234,122,250,119,223,108, 2, 17,179,198,174, 87,233,201,111,175, 69,
+171, 47,188,179,112,247, 30,214,202,200,194,157, 50, 35,215, 16,213, 27, 6,183,239, 23,129,183, 42,231,113, 62,236,183,185,224,
+ 18,228, 79, 6, 51,176,191, 73,139, 51, 15,233,104, 4,126, 26,193,222,118, 61,223,183, 36, 56,217,156, 33,200, 22, 18, 68,196,
+197, 40, 83,127,103, 35,198,196, 87,123,120,248,254,164,125, 43,181,148, 90,116,122,214,157, 15, 61,220,172,175, 74, 74,237,154,
+ 70, 81,106,171, 74, 87,175, 16,221,155,255, 0,169,182,255, 0,233,183,253, 91, 87,180, 2,145, 43,205, 35, 4,141, 69,217,216,
+217, 64, 30,100,215,140,118, 87,254,169,219,120, 95,227,110, 31,242,218,180,251,247,185, 39,220, 55, 25,118,156,118,233,224, 97,
+182,134, 69, 54,234, 74,191, 51, 63,158,147,192, 10,185, 86, 37,123, 34, 49, 78,137, 66,173,248, 85,153,196,200,141,140,105,205,
+170,183, 58, 37,213,209, 29,158,111,124,246,222, 44,133, 61, 81,157,133,239,209, 66,227,245,184, 41,250, 13, 67, 23,239, 7,182,
+100, 96,143, 52,144,234, 63, 52,145,155, 11,255, 0, 67, 85,113,253,163,216,173,220, 56,237,184,102, 78,113,176,195, 20,143, 64,
+ 5,228, 43,243, 16, 91,128, 23,225, 90,251,239,221,140, 88,184, 82,229,237, 25, 50, 73, 36, 42, 92,227,204, 20,151, 0, 92,133,
+100, 11,199,203,133,115,118,112,227, 47, 78, 83,150,238, 13,242,175,184,234,175,231, 78, 62,172, 97, 13,188, 82,230,215,188,239,
+177,229,197,220, 34, 92,172, 41,227,158, 22,228,241,176, 97,127,162,172, 24,148,112,213,194,188, 39,182,187,131, 39,183,247, 24,
+242, 80,150,198, 98, 23, 42, 11,240,116,241,225,250, 67,192,215, 79,247,153,149, 42,110, 88, 18, 98,204,233, 20,184,161,212,163,
+ 21, 12, 11,181,155,135,178,177, 44, 22,175, 70,222,237, 36,155, 82,167, 78, 70,225,220, 19,179, 43,155,126,168,180,156,107,215,
+154,103,166,100,100,225,226, 99,180,249, 46,177, 67, 24,187,202,228, 40, 3,218, 77, 97,224,247,158,195,186,110, 41,182, 96,187,
+201, 52,133,186,109,160,132, 58, 20,185,226,214, 60,151,202,188,135, 9, 55,157,234, 84,218,113, 30, 92,150,153,131,136, 75,146,
+183, 80,126, 54,212,108, 0, 7,153,175, 65,237,143,187,253,199,100,221,241,119, 76,220,188,114,176,135,215, 12,101,153,190, 56,
+218, 62, 7, 72, 28, 11, 86,167,139,102,212, 37,234, 92,172,168,220, 82,211,200,205,188,203,215,167, 31, 78,221, 33, 84,166,222,
+190,122,232,119,218,164,191, 15,244,181, 72, 43,159, 31, 47,195, 78,178, 99,175, 14,165,237,206,194,244,189, 70, 58, 30, 10,205,
+248, 43,194,125, 1,105, 38,227, 87,196, 60, 41,196,124, 62, 46,102,192, 26,135,170, 0,157, 49,143,164,210,245,147,114, 80,170,
+ 61,213, 10, 24, 66,110, 24, 11,158, 96, 81, 76, 4, 11,233, 55, 35,159,133, 82, 57, 89, 7,251,194, 7,144,225, 65,146, 73, 88,
+ 18, 92,159,166,132, 52, 76, 77,111,141,148, 14, 2,247, 28,133, 71,252, 58,157, 77, 40, 54,240, 21,154, 27,135, 30,124, 40,160,
+112,160, 46, 25,241, 64,226, 75,159,117, 8,229,192,131,225,136,155,121,154,172,246, 0,251, 40, 69,181,126, 10,181, 5,225,154,
+130,218, 96, 3,222,196,211,156,214, 38,226, 36, 4,248,241, 63,142,168,150, 32,240, 23,184,176,169,169,224, 47,207,198,160, 53,
+125, 76,158,158,250, 87,251, 13, 86,183, 11,250,141, 62,116,168, 55,255, 0, 13,255, 0,240,223,252,205, 42, 3, 80,142, 9,253,
+ 4,253,145, 74,145, 63, 39,244, 19,246, 69, 43,213, 33, 95, 35,230, 23,242,160, 17,126, 20,105,219,227, 3,217, 67, 23,191, 1,
+ 64, 64, 42,169, 62,102,165,164,248, 26,144,181, 53,184,208, 12, 1,177, 6,155, 65, 6,247,231,225, 69, 2,244,228, 80, 2,227,
+227, 84,166, 26,165, 98, 57,125,130,175,176,181,103, 23, 5,139,121,241,181, 25, 80,225, 71, 35, 82, 32, 15, 96, 21, 16,213,129,
+186,231,201, 36,175,140,135, 76,104,116,181,191, 56,142,119,175, 46, 94, 84, 49,173,239,146,171,110,145, 75,155, 61, 24,216,211,
+200,185,178, 58, 37,171,111,146, 44,103,238,225,111, 22, 33,185,228,101,240, 31,209,172, 82, 75, 18,204,110, 79, 18, 79, 58,106,
+209,219,246,169, 50,136,150, 91,164, 62, 30,109,238,175,206,206,230, 78,117,228,190,231,202, 43,237,138,254, 57,159,122, 48,199,
+195,180,223, 5,206, 79,238,147, 43, 99, 97,203,149,168,160,180,104, 9,103, 60,133,170,189,118, 75, 12,113,199,209, 69, 10,150,
+176, 3,219, 92,132,177,152,164,120,219,154, 18,167,232,174,153,216, 43, 26, 22,181,220,229, 93,207,149,116,162, 71, 60, 60,199,
+145, 59,186,109, 81,166,213,206,154,213,179,161,236,169, 85, 55, 89, 35, 60,228,133,130,251,193, 86,254, 65, 82,251,220,219, 39,
+220, 59, 73,166,129, 75,182, 12,233,146,234, 57,244,192,104,220,253, 26,239, 88, 24,121, 82,224,229, 69,151, 15,207, 19, 6, 30,
+223, 48,125,226,189, 63, 7, 59, 19,118,195, 19, 69,103,142, 65,166, 88,154,198,196,143,137, 28, 87,211,236, 89, 81,140,125, 63,
+213,110, 91,146,235, 22,124,238,245,138,230,220,191, 77,200,237,111,164,145,242, 93, 42,246,142,229,251,154,139, 38,119,203,237,
+188,148,198, 14, 75, 28, 44,139,244,212,159,246,110,161,136, 30,194, 15,190,185,220,127,185,158,233,146, 80,185, 19, 98, 65, 31,
+140,157, 70,115,111, 98,170, 87,236, 35,151, 98, 81,174,244,188, 31, 19,241,242,194,200,140,182,236,111,197,112, 56,222,220,219,
+ 39,222, 55,220, 13,187, 29, 75, 52,211, 32, 98, 63, 53, 1,212,238,127,162,160,154,250,115,125,149, 97,217,243, 93,205,129,137,
+144,123,220,104, 31,132,214, 47,103,246, 38,213,218, 17,180,144, 19,147,159, 42,233,155, 50, 64, 1,211,207, 68,107,199, 74,213,
+ 30,238,222,227,202, 97,182,226,182,168,227,109, 83,184,228, 88,114, 81,238,241,175,137,222,115,237,171, 82,105,233,181,198, 21,
+227, 41, 72,251,189,155, 2,226,154, 79,139,146,148,233,194, 49,137,202,214,215,110,179, 9,167, 0, 18, 10,139,129,239,172, 90,
+232,251,114, 2,176,203, 57, 31,218, 48, 85,247, 47,229, 53,249, 78,217, 23, 44,187,116,253, 53,111,202,135,233,187,140,148,113,
+110, 87,157, 18,243,169,229,127,121, 6,253,213,144,108, 71,238,161,231,253, 1, 93, 39,221,162,194, 54,140,146,162,243, 54, 65,
+ 18, 31, 29, 33, 23, 79,242,154,231, 62,242,120,247, 94, 71,252, 56,191, 96, 86, 70,197,191,231,246,252,237, 62, 40, 13, 20,195,
+ 76,176,189,244,190,159,119,136,191, 58,254,132,237, 74,230, 28, 33, 30, 59, 98,252,232,126, 6, 55, 99,107, 54,115,146,211,116,
+147,240,175, 51,219,129, 40,223,205, 53,228,255, 0,120,171, 8,238, 50, 98,182,182,130, 51, 53,191, 79,136,253,144, 43, 70,111,
+188,201,154, 43, 67,183,170,203,111,153,228, 44,160,255, 0, 68, 42,147,245,215, 25, 52,217,187,190,115, 75, 38,172,140,188,151,
+228,162,229,152,240, 10,160,126, 10,231,135,141,114,220,220,238, 45,170,141,113, 58,230,229, 90,187,109, 91,182,247, 54,211,225,
+243, 54,246, 98,255, 0,229, 78,226, 31,221,143, 75,111,233,117, 56,213, 62,211,255, 0,212,155,111,252, 97,248,235,177,203,216,
+142,195,216, 25,176, 77,111, 85, 55, 78,108,155,120, 49,145, 0, 79,234,143,195, 92,111,105,255, 0,234, 77,183,254, 48,254, 67,
+ 93,163, 53, 59,121, 18,143, 6,229,240,138, 71, 9,194, 80,185,141, 9,113, 74, 53,246,205,178,166,243,175,248,190,225,212,249,
+253, 76,218,175,231,173,170,246,217,178,247, 62,102, 34,207,181,197, 51, 98,177, 96,166, 57, 66,173,193,179,112,214, 43,107,191,
+187,114,124, 92,233, 55,156,100, 47,137,146,117, 78, 64,191, 78, 78, 71, 87,177,185,223,206,169,246,167,121,205,219,168,248,146,
+195,234, 48,228,109,122, 65,210,232,196, 88,149,191, 2, 13,185, 86,189, 73, 78,196,103,101, 70, 78,139, 71,241, 94,102, 93,184,
+195, 34, 80,190,229, 5, 87,245, 47,131,242, 24,118,207,125, 31,238, 50, 79,252,241,255, 0,196,170,199,178, 59,171,153,219,159,
+245,227,255, 0, 94,186, 61,223,239, 49,167,196,147, 31,105,198,120, 37,148, 21, 57, 18,176,186, 3,194,232,169,126, 62, 70,245,
+103,177,123,167,125,220,178, 87,109,202,132,230,192,163,227,205, 39, 75, 68, 60, 12,141,201,191,150,185,122,153, 81,182,238, 56,
+ 91,141, 56,174, 14,158,243,175,165,137, 43,138,218,185,114, 85,224,214,170,190,227, 3,188, 49,178,112,246,253,131, 31, 49, 74,
+100, 71,138,201, 34, 18, 9, 5, 89, 64, 28, 47,225, 90,159,117,145, 35,101,110, 82,145,119, 88,227, 85, 62, 65,139, 19,251, 34,
+165,247,172, 20,101,237,182, 55,253,212,159,180,181, 47,186,166, 69,151,116, 45,250, 48,219,235,146,179, 41, 87, 5,203,133,117,
+247,204,212, 98,151,112, 81,227, 77, 53,240,129,233, 3,149,173,122,241, 62,249, 80,157,211,184, 0, 45,241, 33, 62,243, 26, 94,
+189,180, 79, 24, 54, 11,127, 58,241, 78,250, 33,187,171, 60,129, 97,120,248,127,202, 74,225,219,191,205, 47,236,127,138, 61, 29,
+207,252, 49,254,245,248, 48,249,134, 95,242, 14,218, 1, 61, 35,157, 45,199,133,244,181,191, 29, 15,176, 98,130, 94,233,194, 89,
+237, 97,212,104,239,250, 98, 54, 43, 93, 46,197,181, 29,247,176, 78,218, 8, 89, 58,210, 75, 3, 31, 9, 21,184, 92,249, 30, 85,
+231,197,115,182,140,225,168, 62, 46,110, 43,134, 23,224,202,202,110, 13,123, 32,212,227,126,210,116,150,233,175,221,204,240,220,
+ 78,220,172, 94,106,177,219, 7,251,121, 31, 69,244, 91,244,109,111, 19, 92,135,222, 76, 80,255, 0,150, 29,166,211,213, 89,162,
+ 48,241, 23,212, 77,141,191,171,122,230,113,190,244, 50,150, 16,185,152, 34,105, 64,254,209, 36, 40, 9,243, 42, 85,255, 0,150,
+185,206,225,238,109,195,184,221, 76,234, 34,198,135,226,142, 8,238, 64, 39,134,166, 39,153,240,175, 37,140, 59,209,187, 25, 73,
+109, 81,117,173,120,208,246,100,102,216,149,153, 70, 13,201,201, 82,148,225, 94,164,251, 36,129,221, 59,105, 99, 97,173,174,127,
+229,189, 99,231,234,245,217, 58,254,126,172,154,175,206,250,141,235, 87,179,191,245, 46,223,253, 54,253,134,173, 62,249,237,220,
+140, 28,249,119, 88, 35, 45,133,150,218,220,168,254,206, 70,249,131,123, 24,241, 6,189,206,228, 99,147,181,233,186, 10,158,105,
+189, 15, 2,183, 41, 98,239, 90,168, 92,117,242,105,106,102,237,219, 55,117,101, 97,199, 62,218,147,156, 71,191, 76,199, 40, 85,
+224, 72, 54, 93, 99,196, 85,175,242,255, 0,123,155,142,158, 73,243,253,248,255, 0,226, 84,187, 99,188,230,216, 97, 56, 83,196,
+114, 49, 11, 22, 64,166,206,132,252,218,111,192,131,229, 90, 59,199,222, 43,228,226,190, 54,213, 3,227,180,160,171,100, 59, 13,
+ 74, 15,232, 5,241,246,222,185,206, 89, 62,163,140,109,193,198,186, 73,244,241,212,235, 8,226,250, 74, 82,187,113, 73, 45, 98,
+186,248,104, 97,255, 0,146,251,156,255, 0,253,189,255, 0, 94, 63,245,234,239,123, 38, 84, 73,177,193,154, 10,228, 67,183,199,
+ 28,138, 77,200, 40, 74,218,226,254, 85,208,246, 71,115,111,219,164,222,135, 38, 3,151, 12, 99,227,205, 31, 11, 39,144,115,201,
+175,245,214, 87,222,110,163,186, 97, 22, 22,255, 0, 14,109,250,237, 89,141,219,175, 38, 54,238, 40,253, 41,191,167,200,212,173,
+ 90, 88,178,187,105,207,234,105, 53, 47, 6, 93,251,173,199,140,182,227,150, 71,239, 84, 71, 18,183,146,182,166,111,172,168,175,
+ 66,115, 99,207,221, 92, 23,221, 98, 51,193,185,233,183, 7,138,247,247, 61,122, 9,198, 63,156,227,232, 21,225,205,255, 0,232,
+159,179,240, 61,248, 52, 88,208,246,254, 44, 18,112,227,230,104,214,189, 65, 19,192,113,171, 11, 25, 53,230, 61, 64,180,210, 34,
+212,101,135, 72,211,244,211,180, 87, 4, 3, 66, 1,210, 10,220, 84, 28, 88, 26,178,168, 21,109,126, 84, 9, 52,145,192,241, 55,
+189, 10, 9, 97,149,136, 33, 15,211, 68, 88,165,111, 33,244,209, 18, 64,160, 15, 30, 0, 15,125, 50,184, 79,136,142, 23,227, 64,
+ 33,138,237,123,184, 31, 69, 33,138, 60, 92,253, 2,172,195,114,128,158, 4,212,180,208,133,111, 74,131,155, 63,250,125, 20,254,
+154, 47, 55, 63, 77, 89, 34,154,212, 1, 58, 17,250,107, 88,255, 0,221,237,123,241,183,168,213, 74,141,111,240,254,206,143,253,
+181, 42,160, 51, 22, 5, 5,191, 49, 63,100, 83,234, 62, 85, 35,249,167,249,137,251, 34,163,170,128,175, 63,206, 13,143, 42, 17,
+146,222, 6,172, 74,120,220,121, 80,109,168,241,160, 35,168,219,151,213, 76,178, 18,120,139, 81,128,183,186,149, 1, 29, 86, 20,
+250,129,241,167, 32,114, 53, 29, 32, 19,122, 2, 18, 53,148,149, 55,176, 39,234,170, 64, 85,169,192, 17, 49, 28, 15, 0, 62,186,
+171,164,219,157, 70, 84, 35,106,195,206,218,167,121,222, 88, 44,235, 33,212, 69,236, 65, 60,249,214,209, 30, 52,185, 1, 94,124,
+156, 91,121, 16, 80,185, 93, 29, 83, 90, 52,119,199,201,185, 98, 78, 86,233,170,163, 79, 84,100,225,109, 1, 27,169,149,102, 35,
+148, 99,136,254,181,108,241, 3,128,181,185, 83, 1,198,139,200, 85,199,198,181, 98, 59, 45, 70,157, 91,226,252,217, 47,228, 92,
+189, 45,215, 29,122, 46, 75,201, 2, 37,141, 98,111, 24,100, 55,170, 65,112,120, 73,248,141,110, 84, 72, 86, 4, 48,184, 60, 8,
+ 53, 50,177,227,145,106, 86,229,167, 52,250, 75,147, 46, 53,249, 88,186,174, 71, 94, 77,117, 93, 14, 58,173, 96,238, 25,123,116,
+221,108, 73, 76,109,201,135, 53, 97,228,192,240, 53,103, 59,106,120,137,151, 24,107,143,153, 79, 21,251, 69,102, 87,229,238,217,
+189,141,114,146, 78, 18, 92, 36,191, 24,179,244,118,238,218,200,183, 88,210, 81,124, 83,252, 26, 59, 44, 94,249, 26, 64,205,197,
+ 58,188, 94, 35,192,255, 0, 85,190,218,176,253,241,128, 7,238,241,166,102,242,109, 42, 62,187,181,112,180,171,209, 30,235,152,
+149, 55,167,226,226,170,112,125,183, 21,186,236,107,193, 55, 67,119,115,238,173,199, 61, 76, 49,219, 26, 22,224,203, 25,187, 17,
+228, 95,236,172, 42, 84,124,108, 57,242,223, 68, 43,113,226,231,130,143,121,175, 52,238, 95,200,184,183, 57, 92,147,209, 46, 62,
+228,122, 35, 11, 54, 32,246,168,219,138,213,191,155, 35,141,143, 38, 84,203, 4, 66,236,199,159,128, 30, 36,215, 99, 12, 77,141,
+ 2, 65, 21,180,160,176,243, 62,102,133,129,183,197,183,199,101,248,164, 97,241,200,121,159, 96,246, 85,146,121,219,198,191, 65,
+219,176,191,215,131,148,255, 0,201, 62, 63,241, 93, 62,103,194,207,204,245,228,163, 15,178, 28, 63,228,250,152, 27,191,109,236,
+251,150, 87,171,206,193, 73, 50, 28, 0,210, 22,123,144,160, 1,200,138,172, 59, 91, 99, 56,103, 1,176,211,211,106, 50, 4,227,
+193,200, 0,178,177, 58,135, 1,224,107,119, 37,216, 58,168, 23,176,160, 31,136,115,247,218,190,170,185,114,137,111,149, 23, 13,
+ 94,135,206,244,173,213,189,145,171,227,162,212,229,155,238,247,182,195,234,209, 48, 95,209, 18, 27,125,181,179,181,108, 91, 54,
+209,241,109,248,171, 19,145, 99, 41,187, 57, 31,211,123,154,190, 60,173,195,204,211, 31,132,243, 39,216, 42,202,245,217, 42, 74,
+114,107,163,100,141,139, 81,117,141,184,167,213, 34, 25,152,152,155,142, 59,225,229,160,154, 9, 45,174, 51,112, 13,136, 97,202,
+199,152,172,252, 94,213,237,252, 60,152,242,177,112, 82, 57,162, 58,163,112,206, 72, 62,124, 90,180,205,212,234, 28, 60,232,128,
+223,143,157,101, 78,105, 81, 73,164,248,164,244, 52,237,194, 77, 74, 81, 77,174, 13,170,177,217, 85,148,171,128,202, 69,138,158,
+ 32,131, 92,222,103,101,118,222,100,140,231, 19,162,199,153,133,153, 7,234,131,167,240, 87, 73, 75,161,115,123,243,227, 72,220,
+156, 53,132,156,124,157, 4,237,194,122, 78, 42, 94,106,167, 41, 31, 96,246,220, 44, 25,161,146, 91,120, 73, 35, 91,254,142,154,
+232,112,177,177,112, 97, 24,248,113, 36, 17, 47, 36, 64, 20,126, 10,226, 59,147,188, 55, 77,163,127,200,219,161, 88,142, 52, 38,
+ 43, 22, 66, 90,207, 26, 72,220, 67, 15,210,160, 79,221, 93,217,185, 23,201,217,118,247, 76, 16, 72,141,214, 19, 41, 32,121,177,
+ 5, 73,243, 11,202,172,238, 92,159,223, 39, 47, 54, 72, 90,183, 15,178, 17,143,146, 59,125,199,101,218,119,102,141,247, 28,101,
+157,162, 4, 70, 88,176,176, 60,254, 82, 41,182,253,155,107,218,122,135,109,198, 88, 12,182, 18, 21, 44,111,166,246,249,137,243,
+174, 51,101,251,195,200,143, 41,113,119,232, 16, 68,205,161,167,141, 74, 60,102,246,187,161,230, 7,141,172,125,245,187,222,253,
+201,157,219,235,183,182,218, 34,101,202, 18,151, 50, 41,113,100,233,233,211,102, 31,167, 83,124,246,237,220,246,244,174,158,225,
+178, 27,183,237, 91,186,211, 95,121,210, 32, 36,214,118,103,107,236, 59,134, 75,229,230, 97, 44,185, 18,216,188,132,184, 39, 72,
+ 10, 57, 48, 28,133, 46,215,220,166,221,182,108, 92,252,192,162,121,250,154,194, 11, 47,193, 35,160,225,115,224,181,139,222,189,
+217,185,118,254,118, 62, 54,222, 33, 49,203, 15, 81,250,138, 88,223, 81, 94, 22, 97,229, 82, 50,148, 93, 98,220, 95,131,161,101,
+ 8,201, 82, 81, 82, 92,117, 85, 52, 55, 92,204, 14,202,218,162,124, 76, 59,227,180,221, 49, 10, 57, 91, 51,171, 57,107,182,175,
+208,160, 96, 54,207,223, 27,123,230,230,237,202,189, 41, 90, 5,212,215,113,101, 87,184,116,210, 71,207,202,178, 59,211,112,125,
+203,179, 54,172,185,128,235,205, 52, 50, 73,164, 89,110, 97,150,246,231, 88, 29,185,220,155,174,221,183, 62,209,179, 98,122,140,
+169,166,121,153,244,180,150, 82,177,160,210,137,237, 94, 36,240,166,233, 39,185, 55,187,173,117,247,141,145,113,218,226,182,244,
+166,158,227,178, 31,119, 61,186,127,120, 68,182,253, 14,161,183,219, 87,242,123,115,183,246,189,151, 52, 46, 16,124,104,162,105,
+230,136, 18, 26, 78,136, 50, 0,100,226,220,214,184,182,239, 94,238,218,103, 84,221,113,198,147,196, 69, 60, 38, 43,142, 23,208,
+203,167,235,227, 93,167,241,140, 93,247,179,247, 76,252, 98, 64, 56,153, 41, 36, 77,109, 72,203, 19, 93, 77,189,247,173,187,215,
+101, 74,206, 78,158, 38, 21,139, 49,174,219,113, 85,211,130, 48, 59, 62,126,217,221,183, 99, 30, 14,205,232,242, 49,162,108,132,
+152,204,207,201,150, 59, 91,135,251, 74,188,221,239,132,251,217,216, 31,109, 45,171, 47,208,180,140,224,169,188,157, 29, 69, 74,
+242,241,181,115,191,117,191,250,131, 39,255, 0, 38,255, 0,245,176,213,223,243,110,127,249,187,248, 87,166,196,232,255, 0, 18,
+244,221, 78,143,239, 52,245,250,122,181,223,230,183,143,157, 98, 82,148,157,101, 38,223,139,169,184,194, 49, 77, 70, 42, 43,162,
+ 84, 58,124,190,192,237,140,183, 47,232,250, 12,121,152, 29,144,126,173,202,254, 10, 28, 31,119, 93,175, 11,135, 56,242, 77,111,
+ 9, 36, 98, 62,165,211, 65,239, 46,246,110,222,153, 54,252, 24, 86,108,199, 65, 35,188,151,208,138,110, 7,194,164, 18,198,222,
+117,145, 22,231,247,159,149,142,185,240, 99, 47,167,117, 18, 32, 9, 8, 37, 72,212, 8, 70,110,161,184,174,158,189,234, 83,212,
+149, 60,217,207,253,123, 53,175,167, 15,114, 59,200,113,241,112, 98, 92, 76, 72,150, 8,148,124, 17,198,161, 87,219,202,184,142,
+242,221, 54, 44, 61,194, 12,125,215,105,245,242,244, 21,210, 94,169, 77, 42,210, 56,211, 97,253, 26, 23,111,253,224,229,229,110,
+ 49,109,187,220, 8,141, 43,244, 86,120,193, 66,178, 31,132, 44,136,196,243,110, 30, 22,172,143,188,177,109,243, 23,255, 0, 38,
+159,245,179, 87, 53, 41, 39,185, 54,159, 84,245, 58, 56, 69,173,174, 41,174,141,104,122, 71,109,237,219, 86, 54,221, 14,102,215,
+136, 48,215, 62, 40,167,120,195, 51,124,201,173, 65, 44, 79, 45, 85,176, 86,245,229,184,189,221,220,249, 27,110, 38, 23,110,109,
+174,208,225, 99,197, 4,185, 34, 38,153,139,199, 26,169,181,190, 1,196,114,226,106, 59, 87,222, 78,239,141,154,184,251,244,107,
+ 36, 26,180, 76,193, 58,114,199,198,215,176,176,225,226, 45, 70,219,117,147,109,190,108, 40,168,170, 69, 36,151, 37,161,233, 12,
+ 89, 9, 3,133,248, 26, 47,168, 81, 89,157,205,220,123,119,110, 97,166, 78, 68, 34,124,153,137, 24,240,131, 98,228,115, 36,241,
+178,143, 19, 92,102, 15,115,119,246,249,212,159,100,194,137, 96, 13,243, 44,104, 19,135,230,135,201,107, 19,231,106,133, 61, 20,
+228,146,120, 41, 62,234, 30,188,167, 63, 10,181,188,173, 92, 20,127,120, 61,205,177,103, 46, 39,114,224,161, 83, 98,218, 80, 71,
+ 38,158, 90,208,169, 49,176,255, 0, 75,215, 99,191,247, 36,152,157,175, 54,253,180,200,146,252, 49, 62, 59, 56, 37, 72,146, 68,
+ 67,117,184, 60,152,253, 52, 5,195, 6,107,241,208,212,233,135,145,123,178,216, 14,119, 53,231,184,191,122,123,144,192,200,108,
+184,163,155, 61,157, 87, 18, 52, 86, 84, 0,131,169,228,248,141,248,218,192, 85,254,208,238,126,229,221,247,150,196,221,198,140,
+119,133,228, 69, 48,244,248,169, 91,105, 36, 92,243,168, 83,187, 88,133,239,107,144, 57,212, 97, 80,192,130, 60,106,192,224,167,
+234,160,227,240, 36,143, 3, 66, 7, 81,164, 83,218,144,243,167, 7,192,213, 4,109,198,158,212,143,133, 33,236,160, 44,255, 0,
+113,255, 0, 39,254,218,149, 47,238,111,254,231,254,218,149, 0,118, 60, 22,223,160,159,178, 42, 13,126, 6,212,228,181,146,252,
+244, 37,255, 0, 84, 83, 30, 62, 20, 0,101,189,249,113,181, 48, 31, 71,157, 60,164,235, 3,200, 80,213,154,230,252,168, 2, 94,
+254, 20,143, 15, 10,136, 62,116,228,240,160, 23, 62, 38,152,155,210, 12,117, 16, 69,133, 51, 27,114,160, 43,100,184, 42,163,219,
+113,244, 80,139, 0, 42, 89, 70,238,171,224, 5,239,239,255, 0,240,160,251,106, 50,136,155,138, 92,124,169,212,112,189, 63,133,
+ 0,193,184,212,139, 19,192, 80,193,230,106, 64,128, 40, 4, 5,233,194,138, 74, 69, 61,248,208, 14,136, 11,129,225,126, 32,249,
+ 84,114,118,188, 44,143,137,226, 3,249,203,192,254, 10, 36,100,107, 4,155, 91,141, 20, 50,219,159,228,172, 78, 16,154,219, 56,
+169, 46,141, 84,212, 39, 56, 61,208,147,139,234,157, 12, 57,123,126, 29,122, 98,153,150,254, 12,161,191, 15,195, 78, 59,105,111,
+111, 84,127, 83,255, 0,214,173,166, 3, 90,241,250, 5, 19, 85,254, 83,196, 87,145,246,220, 54,235,233, 47,100,164,191, 51,210,
+187,134, 90, 84,245, 95,186, 47,242, 51, 96,237,236, 24,236, 95, 84,173,252,227, 97,245, 10,184, 32, 72,192, 72,254, 21, 30, 2,
+214, 21, 99, 95,143, 58,129, 11,227,206,189, 22,172, 90,180,169,110, 17,143,146,215,222,112,185,122,237,199, 91,147,114,243,122,
+123,129,244,217,155, 65,115, 96, 61,148,140, 78, 63, 60,145,238, 21, 52, 63, 17,169,139, 3,230, 43,169,204,205,200,225, 41, 70,
+ 55,181,184,253, 23,160, 95, 73,225,203,196,209,178, 91, 84,206,195,149,237,199,217,194,130, 13,249, 86,128,230,199,143, 63,101,
+ 56, 55, 22, 60, 13, 64,155, 26,127,125, 0,184, 14, 28,252,201,162, 14,118,160,130, 9,176,241,163,168,227,122, 48, 58,173,200,
+171, 22,161,160,226, 40,213, 8,120,167,125,233, 29,221,159,170,250,111, 6,171,115,183, 66, 62, 85,236, 56,222,145,240,160, 56,
+ 58, 78, 39, 77,122, 26, 62, 93, 22,248,109,244, 87,142,247,239,254,172,220, 63,228,255, 0,212, 71, 93, 6, 87, 98,247, 62,222,
+207, 14,201,185,177,193, 98, 74,196, 38,146, 19, 99,224,234,191, 1,247,213, 6, 47,222, 9,196, 61,194,222,155, 78,177, 10, 12,
+157, 63,237,110,220,253,186, 52,213,222,248, 89,147, 98,237,101,200,191, 84, 99, 62,187,243,190,140,126, 6,254, 62,117,165,176,
+253,219, 72,185, 41,151,190,204,146, 34,144,227, 26, 34, 91, 89,189,255, 0,120,236, 7, 15, 48, 57,249,215, 85,221, 93,179, 23,
+114, 96,164, 29, 78,142, 68, 4,190, 60,150,186,139,139, 50,176,242, 52, 5, 62,196, 88,159,180,240,152, 49, 44,189,101, 96, 15,
+ 35,214,115, 99,244, 26,227,190,243,164,199, 59,222, 60, 48,181,222, 28,117, 18,139,222,204,204,204, 1,246,218,198,137,141,216,
+157,229,130,237, 22, 38,106, 99, 68,228, 7,120,114, 36, 69,111, 11,144,138, 9,250,170,206,119,221,126,228,235, 19,226,230,197,
+ 52,237,169,178,165,200, 46,183, 98,120,104, 10,146, 19,239, 38,128,126,232, 88,199,221,230,196, 85, 64,114,248,247,111, 19,251,
+137,107, 67,238,185,176,191,133,230, 42, 5, 57,189,123,205,123, 22,233,233, 29, 63,234,223, 87,211,122,189,188,246,166,227,184,
+246,174,219,177,193, 44, 11,147,134,209, 52,174,236,226, 50, 18, 55,140,233, 33, 11,115,111, 17, 88, 49,125,219,239, 88,152,169,
+145,135,158,144,110,136,204, 15, 74, 73, 21, 10, 27,105,211, 32, 85,101,110,126, 22,160, 55,254,241,206, 26,246,211,172,250,122,
+237, 44,126,150,255, 0, 54,176,223, 22,159,234,106,174, 83,178,122,223,229,238,234,255, 0, 97,232,218,215,229,175,165, 55, 47,
+163,159,209, 83,255, 0,237,247,116,238, 57, 8,219,182,106,121, 25,165,149,231,112, 63,154, 15,250,194,187,172,126,217,199,219,
+187,115, 51, 99,219,136,234,100,193, 44,102,121,120,107,150, 84, 41,173,202,131, 97,199,192,112, 20, 7, 3,247, 91,255, 0,168,
+ 50,127,242,111,255, 0, 91, 13,102,255, 0,255, 0, 64,255, 0,252,207,255, 0, 53, 93,175,102,118, 94,233,219,155,164,217,185,
+211, 99,201, 20,152,237, 8, 16,179,179,106,103,141,238,117,198,130,214, 74,169,254, 65,222, 15,116,127, 27,235,227,122,111, 95,
+235, 52,107,147,169,211,235,117,173,110,157,181, 91,219, 64, 31,189,251,107, 11,121,205, 25,112,110,120,216,185,209,160,142,108,
+124,153, 21, 3, 1,241, 41,241,101, 54,111, 42,202,139,103,251,202,219,177,209, 48, 50, 90,108,116, 81,211, 17,205, 27,168, 95,
+ 13, 34,107,112,183, 43, 87, 67,221,221,138,187,252,227,113,194,157,113,243,116,132,145,100, 4,199, 32, 94, 10, 73, 91,149, 32,
+112,228,107, 27, 27,183,254,242, 48, 32, 92, 60, 76,244, 92,116, 1, 80, 9, 67, 0,163,144, 93,105,168, 1, 64,102,225,119,214,
+243,183,110, 30,151,126,199,138, 96,175,163, 39, 84, 75, 28,200,111,197,135, 76, 40,184,231,203,141, 71,239, 59,255, 0,207,113,
+127,242, 81,255, 0,214,205, 90,123,119,221,214,116,153,223,196, 59,131, 49, 37,248,250,146, 71, 25,105, 30, 70,249,172,238,225,
+109,127, 30,117,161,221,253,151,186,119, 30,227, 6,118, 20,216,241,197, 30, 58, 66, 86,102,117,109, 65,221,248,104,141,197,190,
+ 63, 58, 20,233,251, 94, 8,160,237,205,173, 33, 80,170,216,176,200, 64,241,105, 16, 72,231,233,102, 53,229, 63,120,138,171,221,
+121,118, 0,106, 72, 73,183,137,233,173,123, 14,211,141, 38, 14,213,131,131, 49, 86,151, 27, 30, 40, 93,150,229, 75, 70,138,132,
+173,192, 54,225, 92, 63,117,118, 38,239,191,111, 83,110, 88,147,227, 36, 50, 44,106, 22, 86,144, 53,209, 66,155,133,141,135,135,
+157, 8, 98,253,230, 9, 70,225,182, 22,254,199,209, 46,143, 45, 90,219, 95,224,211, 86,246, 12,127,188, 25, 54,156,102,217,179,
+ 32, 76, 2,191,184, 91, 65,112, 47,196, 29, 81, 19,123,243,185,174,219,127,237,140, 62,225,219,162,195,203,110,156,240, 1,208,
+201, 65,114,141, 96, 27,129,181,212,219,136,174, 51, 15,180, 59,227,102,214,155, 46,227, 31, 65,155,229, 87, 32, 19,250, 70, 57,
+ 16,168, 62,234, 0, 59,231,111,119,190,234,176,166,249,151,136,226, 34,198, 13,111, 12, 68, 94,218,172, 81, 16,158, 66,175,101,
+ 96,102,109,159,118,121,184, 89,143, 27,180,114, 39, 77,162,113, 34,232,108,136,155,230, 31,206, 38,135, 31,221,239,112,239, 57,
+139,149,220,187,138,149, 22, 7, 75, 25, 36,210, 56,233, 91,133, 68, 30,239,170,186,237,235,183, 23, 35,181,165,237,221,164, 71,
+ 0,211, 18, 65,212, 36, 40, 9, 42, 74,197,138,171, 27,157, 39,195,157, 1,196,253,213, 96,227, 79,153,184,102,202,129,230,197,
+ 88,150, 2,194,250,122,165,245, 48,246,252, 21,234,117,200,246, 63,106,238, 29,179,235,253,124,144,201,234,186, 61, 62,131, 59,
+ 91,167,212,190,173,104,159,166, 43,175, 35,202,128, 94, 22,161,192, 56, 55,188,209,109,194,133, 0,184,111,121,160, 12,183, 30,
+ 52,254, 21, 11,212,129,240,160, 23,182,158,252, 45, 77,110, 62,218, 86, 28,168, 11, 86,253,199,252,159,251,106, 84,214,253,197,
+191,220,255, 0,219, 82,160, 12,231,229,254,130,126,200,166, 7,240,210,123,252, 63,208, 79,217, 21, 11,253,116, 4, 37,182,161,
+238,226,106, 4, 15, 62,116,211, 31,140,123,170, 26,184,222,128, 37,236, 41,106, 21,200,229,253,228,118, 78, 14, 92,248,121,123,
+196,113,100,227, 72,240,207, 25, 73, 73, 89, 35, 37, 29,120, 33, 28, 8,167,222,190,240,123,107,100,218, 49,247,217, 50, 14,102,
+ 14, 84,134, 44,121, 48,192,151, 83,128, 73, 95,153, 64, 34,199,153,160, 58,203,154,107, 95,153,170,152, 57,145,238, 24, 88,217,
+240,134, 88,178,162, 73,209, 92, 0,193,100, 80,234, 26,196,139,216,249,213,155,218,128,165, 61,204,204, 7, 27, 88, 15,170,161,
+102,229, 83, 36, 52,133,188, 9,189,101,119, 7,112,237,221,179,182,190,237,185,151, 24,200,202,135,164,186,219, 83,124,160, 11,
+138,133, 53, 2,158, 84,250,124, 42,166,209,186, 99,239, 27,110, 46,235,140,174,144,101,198,179, 68,178, 0, 28, 43, 11,141, 65,
+ 75, 11,253, 53,111, 85, 1, 21, 75,240,167,208, 47, 78,172, 1, 53, 95, 35,114,219,240,157, 83, 51, 46, 28,119,144,142,154,205,
+ 34,161,107,254,136, 98, 47, 64, 90, 10, 5,169,236, 0,166,214, 13,136,226, 15, 16,106,182, 94,231,183,225,186, 71,151,149, 14,
+ 59, 63,200,178,200,168, 90,252, 62, 16,196, 94,128,184,138, 11, 0,124, 46,106, 90, 87,244, 71,213, 64,245, 88,208, 33,155, 34,
+ 84,138, 49,111,222, 59, 5, 94, 60,184,183, 10, 80,238, 91,118, 75,152,241,242,225,149,173,125, 49,200,172,108, 57,155, 3, 80,
+ 22,130, 70,127, 48, 19, 72, 68,158, 92,233,139,141, 23, 87, 20,203, 34,248, 30, 62, 52, 3,148, 77, 95, 71, 42, 70, 52,225,111,
+229, 52,186,128,106,246,154,144,101, 39,221,196, 26, 2, 2, 49,115,204,125, 52,205, 31,243,155,235, 53, 50, 71, 18, 8, 21, 22,
+ 34,196,147,225,203,194,128,204, 99,241,177,183, 2, 73,185,168,146, 7, 27,223,217, 83,233,146, 62, 51, 75,224, 94, 67,141,104,
+ 17,248,136,248, 69,189,180,225, 7,231, 27,211,179,183,184, 84, 24,131,199,153,160, 36, 52,134, 10,163,157, 88, 81, 85,163,185,
+ 96, 79,133, 89, 6,163, 1, 23,194,166, 42, 11,206,167, 84,135, 27,190,253,223,195,189,238,179,238,143,156,208,180,250, 47, 24,
+140, 48, 26, 17, 99,231,168,126,141,117,210,181,172, 60,232,134,162,224, 90,244, 3,175, 5, 21, 32,120,212, 11, 1, 96, 77, 61,
+252,111, 64, 41, 60, 7,155, 10, 32,160,187,128,203,115,227,115, 79,215, 79, 14, 52, 1, 9,240,165, 81, 46, 45,198,162,210,162,
+159, 31,174,165, 69, 9, 55,206,131,223, 83,170,230, 97,168, 17,225,127,195, 69, 15, 74,138, 4,231, 78, 5, 4,202,160, 94,194,
+134,217, 32, 14, 85, 69, 11,118, 54,229, 81, 38,220,248, 80, 35,201, 46,214,181,135,157, 16,189,133,234, 54,139, 70, 14, 72,248,
+179,223,221, 70, 75, 5, 81,127, 10, 4,211,128, 52,142, 55,231, 80,245, 76, 0, 22,229, 68, 11,124, 5, 32, 69,255, 0, 37, 6,
+ 25, 89,248,158, 84, 91,240,184,231, 81,201, 33,181,147, 38,135, 13,180,146, 13,248,154,132,147,133, 22,241, 52, 37,152,168,178,
+213, 78,164,161,112, 94,252,143,224,167, 98, 9,170,177,100, 22, 32, 53, 28, 27,213, 4,214,222,127,130,152,243,225, 72, 82, 52,
+ 3,248, 80,160, 97,102,225,110, 52,111, 11,208,113,248,134, 30,218, 0,162,244,246,243,165,200,210, 54, 2,230,132, 28,138, 64,
+208,250,171,107, 95,149, 46,170,208,165,219,254,227,151,247, 63,246,212,170, 29, 81,208,191,251,155,255, 0,239,173, 74,128,103,
+150, 75, 39, 31,238,227, 39,128,241, 69,168,117, 31,206,147,143,236,255, 0,225,199,251, 11, 80,161, 65,100, 73, 38,176, 3,112,
+183,144,161, 9,100,177,227,115,237, 20,178, 73,214, 61,223,140,208, 56,213, 7,205, 89,185, 19, 69,221,157,236, 34,218,134,234,
+103,254, 39, 19,221,117,122, 85,108,155,156,192, 52,183, 24,173,192,240,181,249,211,102,203,183,255, 0,246,199, 7, 27, 14,119,
+150,101,221,158, 92,196,145,116,152,228,124,114,161, 83,139, 93, 52,160,177,243,189,118,217, 63,118,189,237, 30,251,190,238,155,
+ 70,225,129,143, 22,242,249, 81,190,182,144,201,233,178,165,234,148, 35,160,193, 90,192,114, 62,227, 79,147,247, 57,184,167,108,
+ 69,180,224,102,227,201,184, 62, 88,203,203,154, 98,241,197,165, 99,104,214, 56,244, 36,140,109,170,247, 32, 84, 0,123,151,190,
+247, 92, 7,237,222,219,195,221, 63,130, 97, 13,187, 22, 92,221,197, 98, 51, 56, 47, 23,194, 52,168,102,210, 52,143,151,206,177,
+223,239, 71,188,102,236,245,145,119, 3, 30,118, 62,106,227,201,148,177,197,174, 72,100,137,164, 64,196,161,179, 43, 70,120,139,
+ 19, 93,143,113,125,220,111, 89, 51,236,219,206,195,151, 4, 59,198,217,139, 6, 52,201, 53,204, 78, 96, 93, 58,208,148,107,243,
+ 43,102, 91, 17, 66,223,187, 19,189,123,155, 96,143, 15,114,201,219,151, 61, 51, 6, 64, 17, 6,138, 20,132, 68, 99,209,120,225,
+ 36,190,182, 39,136,250,104, 12,110,222,239, 14,238,194,239, 92, 13,183,126,220, 70, 86, 30, 78, 42, 75, 44, 72,163, 64,141,241,
+125, 82, 48,248, 85,181,173,133,207,143, 26,230,187,139,185,187,171,187,182, 77,195,118,203,202, 72,182, 88,179, 34,130, 61,185,
+ 85, 69,153,195,200,159, 16, 93, 71, 64, 94, 36,158, 55,175, 66,143,238,223,120,255, 0, 55,237,219,228,243, 98,182, 6, 54, 44,
+ 24,185, 17, 7,147,170,221, 60, 95, 74,250, 7, 75, 77,175,202,237,202,185,255, 0,254,208,247,132,120, 57,219, 54, 54,229,134,
+ 54,217,114, 19, 34, 36,144,189,228,104,245, 34, 51,145, 19, 20, 58, 31,136, 23,227,245,208, 21,179,123,215,113,192,194,237,126,
+220,196,221, 63,130, 97,127, 14,199,155, 55,113, 88,140,206, 11,169, 42, 52, 40,102,210, 52,143,151,207,217, 85, 91,239, 51,187,
+ 37,236,225, 42,231,152,243,160,205, 92,121, 50,150, 56,181, 73, 12,145, 59,168,107,161,179, 43, 70,126, 33, 99, 93, 94,233,247,
+101,190,132,216,119, 61,147, 51, 30, 29,235,105,197,135, 22,117,147, 81,134, 67, 8, 54,116, 45, 27, 95,131, 21, 33,150,196, 81,
+119,254,197,239,110,230,216, 34,194,220,242,118,229,207, 92,193,144,162, 32,241, 66,144,136,140,122, 47, 28, 36,151,214,196,241,
+ 31, 77, 64,116, 61,129,254,110,202, 92,189,215,185,164,255, 0, 13,157, 30, 52,187, 92, 10,202,194, 56,202,185,109, 65,120,234,
+ 43,160,155,215, 51,247,161,217,157,183,137,183,110,253,213,157,145, 48,220,242,158, 49,136,165,192, 78,165,149, 22, 36, 77, 60,
+110,170, 73,185,175, 77,218,113,228,192,218,240,112,102, 33,164,198,199,138, 25, 25, 46, 84,180,104,168, 74,146, 1,181,199,149,
+121,215,222, 7, 99,119,151,120,238,209,205, 6, 86, 12, 59,102, 32,182, 22, 60,178, 75,123,155, 23,146, 69, 16, 50,234, 98, 57,
+113, 22,250,104, 14,135,238,185,119, 37,236,141,183,248,145, 98,228, 57,199, 18, 95, 80,128,185,233, 94,254, 26,126, 95,230,218,
+185,111,189, 14,204,237,188, 93,187,118,238,188,236,137,134,233,148,241,140, 69, 46, 2,117, 44,168,177, 34,105,227,117, 82, 77,
+205,107, 75,219,255, 0,121, 77,219, 80, 96, 69,189,227,166,241, 30, 83, 73, 38, 82,179, 44,103, 27,167,165, 34, 93, 56,254, 13,
+198,218, 62,154,207,239,174,196,239,110,240,220, 32,145, 51, 48, 35,192,195, 64,184,176, 73, 36,196,151,176,234, 75, 34,140,118,
+ 93, 76, 71,213,244,208, 20, 95,111,238, 12,255, 0,185, 60, 44, 17,139, 62,102,110, 76,232, 49,162, 68,105, 37,244,194, 86,146,
+ 59,128, 9, 10, 21, 56, 19,195, 77,169,125,207,228,118,190, 62,250,251,113,218,242,118,238,229,143, 21,177,231, 57, 18, 25, 18,
+ 66,133, 12,246,141,149, 12, 79,169, 47,166,198,194,226,245,216, 65,178,253,228, 65,218,112,226, 65,189,225,255, 0,152, 32,204,
+235,117,207,246, 13,137,210, 49,140,114, 12, 3,142,166,191,201,225,206,168,246, 55,221,246,237,181,247, 14, 87,119,247, 86,116,
+ 25, 91,172,225,244, 36, 7,225, 13, 47, 7,118, 58, 99, 23,211,240,128,162,212, 7,164, 0, 11,234, 68, 22, 38,198,254, 66,164,
+ 34, 82,120,168,227, 66, 5, 72, 63,188, 10, 9,252, 30, 84, 94,164,119,230, 45,239, 21, 0,198, 52,190,157, 2,222,116,230, 40,
+194,234,208, 62,170, 99, 42,147,164, 21,246,220,248,123, 41, 60,168, 23,225, 96,110, 57, 92, 80, 17, 88,144,168,107, 15,111, 10,
+139,196,130, 54,109, 32, 16, 15,224,169,117, 16, 1,118, 30,235,208,167,116,104,136, 12, 13,237,195,233,170, 10, 76,110,111,206,
+152,155,251,253,148,143, 3,231, 76,120,113,254, 74,160, 87,181, 58, 33,115,194,162, 1,118, 0, 11,147,200, 85,228,141, 99, 26,
+ 71,210,104, 1,232,208,163,219,206,144,169,202,120, 40,250,106, 34,160, 30,228,114, 23,164, 26, 70,228,181, 23, 98,188,188,168,
+145,179,104, 38,169, 7, 66,215,179, 11, 83,200,108,180, 52,147,141,219,157, 69,228,212, 72, 28,188, 40, 4, 46,205,170,138,196,
+ 42,146,121, 84, 7,194,160,120,212, 93,129, 22, 60,107, 28, 89,174, 0, 53, 51, 18,104,145, 41, 36,177,164,160, 26,157,192, 60,
+ 57, 86,159, 0,137,177, 10,132,145, 85,117, 19,115, 69,144,134, 0,113,246,208,194,138,137, 80, 50,113, 46,163,118,228, 42,202,
+114,189, 9,116,168, 2,212,153,128, 78, 23,212,126,202,142,173,148, 20,178, 18,252, 57, 10,137, 44,120,121,212, 13, 26, 37, 81,
+241, 31,162,181,193, 16, 44,107,161, 69, 77,219, 66,220,218,135,168,126, 74, 20,206,172,218, 71, 33,252,181,138, 85,148,133,245,
+ 18, 77, 58,174,166, 11, 80, 21,102, 5, 0, 22, 35,137, 60, 43,109,209, 16, 50,128,160, 5,240,162,179,104, 91,147,192, 10, 13,
+215,203,135, 26, 30, 68,138,126, 5,250, 77,115, 74,172,160, 93,139,185, 99, 75,144, 28,106, 39,216, 40,208,162,146, 25,135, 1,
+ 93, 56, 35, 33, 32,138,194,231,153,163, 41,177,181, 71, 82,248,112, 30, 52,152,160, 5,143, 48, 43, 9,186,249,154,107, 64,234,
+ 71, 10,147, 90,215, 39,149, 85, 76,132, 0,223,137,242,161,188,205, 33,227,193,124,171,161,138, 7, 92,144,215, 86, 22, 30, 6,
+180, 49,182,223,220,172,189, 95,237, 0,123,105,229,113,127, 58,197, 46, 52,148,183,204, 71, 26,235, 32, 83, 28, 17, 68,220,209,
+ 21, 77,185,112, 22,164,117, 15, 68, 81,108, 27,113,234,127,209,252,181,159, 54,174,155, 91,199,133,110,205,196,112,174,118, 92,
+132,188,144,254,114,177, 95,168,218,171, 84,161, 23, 4, 49,133, 68,122,250,204, 78,155,170,142,119,168,126,231, 69,196,146, 23,
+241, 94, 31,101, 48,145,163,101,144,199,240,168,211,115,200,212, 34, 98,215, 54,226, 77,235, 53, 53, 67, 71,166,190,131,169,173,
+181,244, 45,111,103, 95, 85,233, 83,220,250, 45, 55,254,227,159,252,251, 82,171, 81, 66, 82, 15,236,255, 0,225,199,251, 11, 67,
+169,201,253,223,252, 56,255, 0, 97,106, 20, 5, 92,155,107, 30,239,198,104, 7,149, 31, 39,251, 65,238,252,102,131,202,168, 57,
+ 17,223,219,114,162, 52,144, 58,150,193,202,220, 31,136, 33,125, 35, 72,143, 9, 63,164, 76, 47,111,117,109, 71,191,237,210, 63,
+165, 50,133,206, 88,186,178, 98,113,186,176,140, 76,209,234,176, 82,225, 90,229,121,219,141,173, 92,126, 95,221,246,225, 60,185,
+172,153, 16, 42,100,110, 34,104,148,151,248,112, 36, 57, 45,145,142,192, 39,204, 91, 50, 66,170, 56,114,227, 90,107,218,153,131,
+184,114, 55, 2, 17,241,222,121,242,225,153,242, 50, 46,173, 62, 55,165,233,140, 64,122, 10,192,150,188,156, 73, 94, 22,242, 3,
+ 99, 11,186,118,140,152,182,227, 36,235,143,145,185, 99,193,149, 14, 59,222,234,185, 11,170, 53,118, 3, 72, 45,196, 45,207,196,
+ 71, 10, 36, 61,209,219,243,227,201,151, 22,225, 27, 65, 19, 70,143, 39,196, 5,231, 58, 97,181,197,200,144,252,164,112, 62, 21,
+206,225,246,166,241,135, 12, 24, 31,225, 37,199,159, 11,110,197,206,157,203, 51, 68,216, 49,180,114, 24, 17,147,227, 45,113,211,
+ 98, 87, 73,227,106, 80,246,158,239, 32,198,147, 37,177,226,151, 16,109, 24,234,177,187,178, 60, 59, 94, 65,200,146, 83,120,193,
+ 15, 32, 98, 21, 60, 60, 90,128,232,113,187,163, 96,202,234, 24, 51,209,150, 24, 95, 38, 82,193,144, 44, 81,157, 50, 57, 46,171,
+242, 30, 12, 57,175,141, 93,197,220,246,252,204, 73, 51,177,166, 15,143, 22,161, 43, 89,129, 66,130,236,172,140, 3, 2, 7, 27,
+ 17, 92,116,157,147,185, 75,139, 38, 57,158, 5, 47,137,186, 99,171, 6,147,251, 76,220,244,206,131,146,131,164, 42, 89,200,226,
+ 15, 43,215, 69,219, 59, 84,251, 86, 54, 87,168,141, 97,151, 47, 37,178, 90, 49,145, 62, 91, 11,164,113, 14,164,249, 68,187,181,
+163, 30, 67,195,219, 81,128,123,103,121,108, 27,164, 59,124,139,144, 32,155,113, 72,228,135, 30, 80, 67,142,171, 20, 69,114, 1,
+ 80, 89,148,170,241,248,143, 43,211,247, 39,119,109,253,183, 32,131, 38, 55,150,102,196,200,205, 85, 65,192,174, 54,155,173,207,
+139,106, 54,247,113,240,174,119,108,236,205,235, 19, 19, 31,110,157,177,140, 46, 54,212,202,158, 57, 92,178, 13,174,126,178,152,
+213,162, 93, 93,101, 10, 56,145,164,223,230,173, 94,245,237,237,203,184, 58,127,195,158, 5,255, 0, 5,159,133, 39,168,119, 75,
+122,177, 14,135, 93, 17,201,125, 45, 15, 17,195,129,250, 42, 3, 89, 59,139,108,200,147, 28, 98, 79, 28,145, 75, 60,184,210,200,
+204, 99, 40,240,194,217, 44, 52,186,141, 95, 10,131,225,240,157, 92,170,198,223,188,237,123,164, 82,207,129,146,179, 71, 13,140,
+166,204,165, 67, 46,181,107, 56, 7, 75, 47, 21, 60,136,229, 92,252,157,177,185, 54,229, 38,114, 62, 59, 35,110, 89, 25,234,146,
+107, 96, 99,155,108,254, 30,170,234, 20, 92,245, 56,176,191,203,227,126, 20,110,219,217, 55, 45,183, 15, 63, 31, 40, 71, 18, 78,
+169, 30, 46, 50, 77, 38, 66,196, 22, 50,140, 4,211, 34,201,211,213,242, 33,190,149,250,168, 13, 21,238,174,221,120, 33,157,115,
+227, 49,100, 18, 33,144, 6,210,192,104,212,215,183, 4, 29, 69,187, 31,132, 19,107,210, 78,229,219, 34,245,231, 49,253, 50,225,
+102, 28, 11,181,216,201, 32,130, 60,162, 81, 80, 22,176, 73, 56,240,225, 98,121, 87, 51,159,217, 57,249, 27,118,207,132,122, 83,
+156,109,169, 54,156,196,245, 57, 56,241, 2, 4, 90,165,255, 0, 13,161,167, 79,129,191,118,246,191, 10,177,185,118,150,229, 60,
+217, 89,145, 52,114,153, 55, 41,115, 99,128,101, 79,136, 90, 41,176,162,194,179,207,140, 3,171, 43,199,168,168,184,101,225,127,
+ 10, 3,169, 27,238,202,153, 88,248, 39, 50, 63, 85,146,168,209, 42,146,192,137, 65,104,174,234, 10,142,160, 83,166,231,226,240,
+170,231,186, 59,127, 86, 69,179, 99,255, 0, 13,101,150,193,184,147, 39, 71,247,127, 15,239, 63,121,240,124, 23,248,184,115,174,
+122, 78,211,221,215, 51,107, 16,190, 63,161,219, 87,109,233, 32,158,104,149, 78, 21,214,101,233, 4,147,168, 89,109,161,164, 98,
+ 69,173,194,247,170,210,246,110,241, 51, 78,215,198,130, 53,150, 44,136,241, 49,242,167, 68,150, 68,201,245, 18, 52, 50,105,234,
+225,137, 16,252,177,177, 26,248,251,104, 14,229, 55, 29,189,182,255, 0,226,163, 34, 63,225,235, 27, 76,217, 68,252, 10,137,125,
+101,137,229,166,198,254, 85,141,153,222, 91, 76, 41,183,250, 54, 25,141,184,102, 12, 24,128,213, 31, 77,194, 25, 36,105, 3, 38,
+161,165,109,240,145,115,113,225,198,162,157,186,223,228,217,187,111, 92, 80,100, 76,147,145,166, 73,102,137,101,154, 87,200, 26,
+164,156,153, 92,106,111,137,143, 19,196,216,114,170,233,176,110, 19,231,197,187,100,180, 16,228, 73,188, 38,231,145,140,146, 52,
+136,145, 69,128,219,122,162, 63, 77, 53, 57, 54, 99,112, 7,213,196, 11,187,175,122,237, 91, 70,230,251, 78, 74, 57,158, 33,134,
+100,112,182, 80,185,147,250, 96, 79,244, 62, 99,236, 60, 56,213,247,238,126,221,232, 99,101,140,196, 72,115, 11,250,119, 33,133,
+196,108, 34,144,176, 34,232, 21,254, 22, 45,107, 30, 6,177,247,238,222,207,220,187,130, 45,207, 22, 76,113,139,109,179,172, 36,
+119, 89, 20,237,249,205,154,218, 85, 99,117,109,105, 33, 2,236, 56,143,109,198, 54,103, 98,231,205, 4, 48, 51, 67,144, 29,119,
+ 8, 39,143,213,101, 99,198,169,155,154,217,145,200,195, 27, 67, 76, 4,109,165,163,107, 13, 86,227,227, 64,118, 27,214,240,219,
+100,152, 24,208,226, 28,172,157,198, 87,130, 20, 87, 88,192, 49,195, 38, 67, 22,103,225,242,198,107, 35, 31,188,246,220,248, 37,
+153,227,124, 72,241,225,197,158, 70,148,131,199, 37,231,133, 98, 65, 30,173, 71, 92, 4, 13, 55,213,113,106,179,221,123, 52,155,
+219,237, 82,195,137,135,184, 71,129,145, 36,217, 24, 59,131, 50, 67, 42,188, 18,192,188, 68, 25, 34,234,210, 6,226,158, 21,205,
+ 47, 97,110,113,226, 77, 25,200,142, 82, 61, 3,193, 12,115, 77, 7,253,211, 39, 42,118,199, 89,149,122,145,170,199,144,177,196,
+235,199,225,226, 5, 1,208, 79,220,251, 14, 52, 16,228, 79,155, 26,197, 58, 52,177, 55,196,110,136,193, 29,190, 16, 72, 10,204,
+ 3, 95,151,141, 14,126,226,219,227,222, 49,182, 72,223,171,149, 60,175, 12,138,188,162, 41,142,249,127, 25, 34,223, 34,142, 0,
+240,184,189, 99, 79,216,185,242,109,167, 14, 22,199,133,223,107,220,112,138,153,103,145, 70, 70,118, 76,121, 74,122,146,171,200,
+234, 52,182,166, 60, 73,252,223, 43,146,246,166,229, 38,242,100, 86,199, 93,180,230,228,231, 25,245,191, 95,252, 86, 11,225,116,
+196, 90, 52,221, 29,181, 95, 95, 17,237,170, 13,140,126,227,237,225,137, 38,114,231,197,208,141,145, 36,152,220, 0,101, 54,138,
+215, 0,149,127,205, 97,193,188, 40,251,134,240,216,209, 98, 73,133,137, 46,115,230,159,220,164,118,141, 66,104, 50,151,149,229,
+210,168, 52,139,113,227,115,106,229,118,206,203,220,113,241, 99,138, 81, 12,115,164,251, 75, 59,156,172,156,163, 36, 91,108,221,
+ 87,109, 89, 0,232,213,118,233,198,170, 0,241, 62, 93, 15,116, 96,110,251,150, 36, 88,123,103, 72,193, 36,159,253, 70, 41,103,
+147, 25,165,131, 73,188, 41, 52, 49, 78,203,173,173,168,129,125, 55, 0,241,168, 9, 55,112, 69, 62,205,135,188,224,227, 77,148,
+185,203, 11, 99, 99,170,129, 33, 57, 5,116,235, 36,233, 64,183,187, 49, 54, 3,206,167,129,190,225,229,109,115,110,211,255, 0,
+131,135, 25,166,139, 40, 76, 71,238,223, 30, 70,134, 81,169, 73, 86, 26,144,216,142,117, 79,113,197,238, 73, 54,199,194,218,227,
+195,192,147,165,143, 28, 34, 57,164, 2, 53, 12, 70, 68,113,191,167,248,109, 24, 11, 19,116,253,182, 22, 21, 33,180, 79,254, 87,
+151,103,143, 3, 14, 23,233,152,147, 9,165,150,124, 98,183,185,215, 55, 78, 25, 75, 56,185, 45,166,250,184,241,160, 14,221,205,
+176,104,134, 86,206, 69, 89,139,162,134, 12,172, 25, 10,171,245, 21,148, 52,122, 75,173,203,129,107,143, 58,156,189,199,182, 67,
+ 59, 96,197, 60,114,229,199, 60, 56,243,194, 88,166,131, 60,145,198, 46,218, 72,213,251,208, 85,127, 58,184,252,158,198,222, 50,
+ 85, 70, 75, 71, 56,154, 60,140,119,130, 92,220,165,233, 69, 52,145,186,117,166,128, 68,249,122, 85, 24, 50,201,107,240,227,194,
+245,191, 55,109,103, 63,174,211, 36, 35,212,239,152,123,178, 92,183, 8, 49,253, 38,180,111,131,231, 62,157,172, 57,114,227, 84,
+134,151,249,139, 98,190, 96,108,200,239,132, 25,178, 9, 36, 5, 88,219, 67,144, 72,179,105, 97,164,233,189,143, 14,116,109,191,
+ 63, 19,114,132,229, 97, 72, 37,136, 49, 67,192,169, 87, 95,153, 93, 92, 6, 82, 60,136,174, 55, 31,179,115,241,206,122, 52, 56,
+217, 37,225,201,199,199,108,156,156,169, 82,100,201,201, 25, 58, 90, 27,132,199, 26, 84, 3,211, 4,234,248,189,251,253,191,129,
+188,237, 88,222,159, 56,196,240, 72,211, 75,198, 87,154,116, 44,201,209,141,165,120,211,171,100,213,169,219,226,189,135, 17,198,
+163,232, 84,108, 73, 35, 95,133, 8,200,254,116,101, 94, 28,104,110,151,114, 47, 96, 40, 82, 34, 87, 30, 52,186,175,231, 79,211,
+ 31,164, 41,250, 35,244,197, 82, 16,234, 63,157, 56,145,199,141, 79,160, 9, 35, 80,246, 84, 76, 68,120,143,174,128, 93,105, 60,
+233, 9, 92,155, 19,194,163,211,106, 98,164,115, 20, 1, 29,130,219, 75,234,191, 62, 22,166,235, 63, 47, 42,104,192,103, 0,242,
+ 53,100, 99,198,104, 10,221, 87,166,214,198,173,250, 84,183,182,151,164, 95, 58, 2,174,182,169,137,228,181,133, 89, 56,104, 57,
+ 26,111, 72, 60,234, 0, 29,121, 61,149, 30,163,158, 96, 81,132, 32,169, 30, 87, 55,165,208, 22,191,149, 40, 1,235,106,152,153,
+192,210, 0,167,147, 28,158, 42,109,225, 85,220, 58, 54,150,231, 74, 2,250,182,160, 47,254,158,202, 4,178, 18,116,142, 66,134,
+146, 20, 91, 19,243,114,165, 81, 71, 82,212, 62, 58, 36,173,103, 98,190, 86,171, 99, 2, 19,199,172,223, 80,172,228, 98,172, 44,
+107, 74, 23,212,190,218,209,150,100,205,188,246,150, 52,242, 99,228,119, 14, 12, 51,196,198, 57, 34,147, 38, 4,101,117, 54,101,
+117,103, 5, 72, 60,239, 91,103,189,123, 46,195,255, 0,246, 61,175,255, 0,231,113,255, 0,248,149,243,246, 55,111,237,121,219,
+215,125,111,185,123, 76,221,199,149,182,238,111, 30, 62,199,143, 36,145,179, 44,249, 18,135,200,126,133,229, 42,154,109,240,253,
+ 53,206,247, 95,106,109, 27,111,124,226,108, 88,172,248, 88, 89,171,137, 44,216,211, 56,121,112,219, 37, 85,164,198,119,241,100,
+191, 51, 81,201, 70, 46, 79,130, 85,126,194,168,185, 53, 21,197,186, 47,105,244,243,247,175,102,223,135,113,109,150,255, 0,206,
+227,255, 0,241, 43, 3, 47,184,251, 64,203, 44,171,220, 91,113, 44,197,128, 25,112, 30,102,255, 0,167, 95, 62,119, 22,199,183,
+ 67,180,101,230,197,181,205,179, 77,131,150,184,176,137,164,103, 25, 72,218,174,192, 73,249,203,166,228,175, 10,235,251, 91,177,
+123,123, 51,107,237,216, 39,216,178,183,111,243, 12, 82,201,157,220, 48, 78,233, 30,220,200,204,154, 2, 32, 49,254,239, 77,223,
+169,207,195,202,179,106,252,111, 67,116, 83, 84,116,214,159,149, 81,210,237,169, 90,146,139,105,213, 87, 74,254,116,103,176,109,
+187,158,217,188, 66, 78,221,155, 14,100, 80,217,100, 24,242,164,182, 99,196,106, 49,179, 90,174, 44, 96, 46,168,238, 9,240, 53,
+228,223,114, 30,159, 15, 27,184, 33,235,163,198,153,113,199, 28,215, 0, 56, 85,113,168, 95,204,113,175, 93, 86, 89, 34, 12,140,
+ 24, 56,186,176, 55, 4, 30, 68, 17, 90, 57,150, 47,254, 11,249,221, 31,254, 98,149, 63, 76,250,109, 54, 23,232, 91,255, 0,127,
+122, 84, 3,184,225, 31,252, 56,255, 0, 97,106, 53, 39,252,207,248,113,254,194,212, 43, 64,171,147,243,143,119,227, 52, 3,123,
+209,242, 71,198, 61,223,140,208,173, 64,121,172,189,227,191, 71,129,157,153,143, 42,100, 60, 9,185,180,177,250,118, 9,139,233,
+ 37,146, 60,118, 50,143,129,181,232, 0,169,226,124, 57, 26,233, 7,121,224, 54,254,251, 2,160,121,213,228,129, 2, 74,141, 51,
+ 75, 20, 30,169,191,195,223, 88, 77, 32,168,115,192,176,183,182,175, 55,109, 96,182,195,149,219,198, 73,189, 38, 95,169,234, 73,
+169,122,131,213,203, 36,242,105, 58,116,240,105, 14,159,135,151,157, 55,249,115, 28,103,228,229,250,188,149,131, 37,164,150, 76,
+ 37,101, 17,117,166,136, 99,201, 37,194,235, 55, 65,193, 75, 88, 30, 54,160, 50, 35,239,188,118,193,204,202,108, 80,178, 97,201,
+141, 20,138, 39,141,162, 79, 85,193, 90,121,210,235, 31, 76,220, 73,192,233, 35,198,164, 59,247, 1,115,240,176, 39,128, 67, 54,
+ 95,167, 86,141,230,143,168, 31, 45,218, 40,186, 81,131,121, 86,224, 22,101,224, 20,131,238,177,135,217,177, 96,227,188, 88,219,
+158, 98, 72, 83, 30, 49, 40, 48,143,135, 16, 50, 68,165, 22, 32,140,165, 31, 75,171, 2, 15, 62,124,104,152, 93,157,133,183, 75,
+142,216, 89,121, 81, 69, 16,135,173, 2,188, 97,103,108,119,121, 34,105, 72,140, 17,241, 72,110,168, 85, 79, 1,107, 80, 22, 55,
+109,246, 77,191, 54, 44, 28, 92, 9,115,230, 48,190, 92,233, 17, 1,146, 24,221, 35, 37, 20,143,222, 57, 47,193, 71,151, 58,197,
+219,251,226, 72,177,114, 95,119,198, 32, 65, 22,225,149, 30, 68,108,160, 73, 30, 22,105,196,233,232, 54,210,126, 36, 23, 39,143,
+ 19,194,183,119,110,223,139,117,200,139, 40,101, 79,135, 42,196,216,211, 54, 51, 42,153, 32,118, 73, 26, 50, 89, 88,175,197, 24,
+179, 37,143, 62, 53, 83,252,151,180,180, 47, 11, 73, 59, 35,193,155,140,126, 53,184, 92,252,129,155, 35, 2, 19,230, 73, 20,104,
+246,115,189, 70, 0, 99,247,180, 89,216,209, 29,183, 16,102,230,201,149, 46, 24,134, 9,209,225, 45, 12, 3, 41,221, 50, 20, 21,
+101,233,176,181,135,204,109,230,106, 59, 23,118, 62,233,188,230,108,239, 11,122,136,230, 50, 8, 88, 8,223, 27, 19,211,227, 72,
+ 12,224,220,235, 50,204, 80, 1,237,242,171,179,118,183, 90, 8,245,110,121,126,190, 41,228,200, 93,194,241,117, 3, 75, 17,199,
+145, 21, 58,125, 37, 77, 7,128, 11,192,241,231, 75, 11,179,182,220, 12,184,243,241,164,156,101, 71, 55, 95,174,204,172,236,167,
+ 30, 60, 70,134, 70,100, 37,163,101,137, 88,223,142,174, 55,168, 12,221,255, 0,185,247,173,187,125,109,179, 19, 25, 27, 29, 70,
+214, 81,137, 26,156,230,102, 54, 52,139,196,240,212,171,164,121, 17,127, 26,108,159,188,109,187, 7, 11, 27, 43, 50, 1, 11, 74,
+ 50, 94,120, 94,120,212,168,196,156,226, 74,176,235,211,214,114,234, 74,170,142, 32,120, 86,206,229,219, 24,155,158,233, 30,235,
+ 52,243,199, 44, 99, 20, 52, 81,148, 17,191,163,200,245,144,150,215, 27, 55, 7, 36, 27, 48,184, 62,227, 85,207,102,226, 34, 66,
+184,217,153, 88,197, 61, 74,202,241, 50, 7,150, 44,188,131,153, 44, 76,198, 63,132, 9, 15,194,201,102, 3,133,252,104, 5,221,
+123,190, 78,215, 46,211, 20, 25, 30,150, 44,204,137, 34,200,157, 96,108,150, 85, 76,121,102, 93, 49, 32, 36,221,163, 28,135, 42,
+198,237,238,231,221,183,109,199, 27, 31, 43, 37,162, 71,198,195,157,125, 38, 12,153, 41, 33,200,146,116, 45, 52,145, 44,139,142,
+ 25, 98, 83,241,145,166,231,244, 77,187, 28,189,186, 12,204,220, 12,217, 89,196,155,116,175, 52, 1, 72, 10, 90, 72,100,198, 33,
+238, 9, 35, 76,167,149,184,214, 94,217,218, 16,237,121,103, 39,109,221, 51,113,117,170, 36,241, 47,166,116,149, 82, 89,167, 85,
+110,174, 51,176, 23,157,199,192, 71, 15,111, 26, 3, 11, 59,189,247, 40, 36,238, 70,133,160,232, 99,227,101,203,178,141, 23, 33,
+246,230, 92,124,141,102,255, 0, 22,169, 30,227,217, 70,238, 14,226,238, 77,166, 13,215,109,198,150, 28,157,207, 22, 93,183,209,
+100,152, 66,134, 77,194, 87,131, 68,145,134, 32,178,180, 71,136,183, 2, 43, 78,127,187,174,221,155,111,135, 4, 52,176,180, 81,
+207, 12,185,145,116, 87, 34,117,201, 70,142, 83,145, 39, 72,235, 39, 86,174, 95, 48, 30,234,186, 59, 87, 1,153,164,203,205,200,
+202,203,151, 43, 23, 50, 92,201,154, 33, 35, 54, 11,137, 96,143, 76, 49, 71, 26,198, 8,226, 21, 1,226,120,223,141, 1,202,103,
+119,254,231, 46, 78,235,145,181,152,142,221,143,178, 62,126, 33, 41,168,250,164, 76, 73,238, 91,243,148, 38, 98,139,121,215,111,
+178,229, 73, 62, 20,249, 18,205,147,150, 81,155, 72,159, 10, 76, 25,126, 21, 13,165, 33,200, 72,153,175,126, 13,107, 95,133,248,
+ 86, 34,125,223,246,236, 24,147, 97, 69, 60,201, 20,248,217,152,110, 21,227,191, 79, 54, 88,231,144,143,221,218,233,210, 85, 79,
+ 37, 28, 65,231, 91,240, 98, 52,120,115,226,229,238, 83,238, 61,112,202,210,228, 12,116,117, 86, 93, 37, 87,210, 67, 2,253, 96,
+154, 3, 11, 27,191, 49,242,113,167,145,112, 73,201,131, 39, 11, 19,211,197, 60, 82,141,121,238,177, 68,173, 34,252, 42,232,196,
+135, 95,205, 35,153,170, 59,183,127,101,166,201, 54, 94,217,129,167, 62, 60, 76,252,169, 67,186,178, 64,112,167, 56,108,120,129,
+213,188,163,128,225,240,143,162,180,112,251, 47,109,196,133, 34,108,220,169,250,109,128,234, 91,164, 5,246,199,234, 99, 11, 71,
+ 10,240,224, 3,249,251, 15, 26,108,174,197,218,242,241, 91, 9, 51,114,241,226,146, 60,200, 50, 26, 35, 25,121, 33,206,156,230,
+ 75, 17, 47, 11,129,166, 83,240,144, 47,110, 28,104, 13,173,243,121,147,107,108, 60,108, 92, 54,205,205,206,145,210, 8, 21,196,
+ 98,209, 70,211,200,204,236, 26,223, 10, 88, 11,113, 36,123,235, 25,123,214, 57,242,227,137,246,217,161,196,121, 78, 26,228, 76,
+ 85, 92,101, 12, 95, 92,208,188, 63, 50,217, 84,173,255, 0, 72,121,113,173,125,235,106,135,119,244,210, 46, 84,248, 89, 88,142,
+207,143,149,140,171,173,122,145,180, 18, 45,165, 71, 82, 25, 28,248,112, 54, 34,178,143,104,224,199, 56,150, 12,137,218, 40,201,
+154, 28, 89,152, 52,126,171,211,122, 47, 82,204, 83,168, 88,199,206,237,107,146,214,189, 16, 42,225,247,196, 19,166, 43, 79,183,
+190, 63,172, 27,124,209,221,213,237,143,185,179,197, 4,204, 87,149,164, 77, 44,190,209, 84,230,239,163,149,182,103,229,225,224,
+203, 12, 88,184, 3,112,124,176,209, 18,145,203,215,232, 20, 71, 31, 27, 63, 66,252,173,198,130,123, 31, 54, 46,215,147,109, 89,
+198, 86,237,147,131,133,183, 25,165,147, 76, 88,235,136, 53, 43, 64, 99,137, 88,172,114,179, 58,234, 26,143, 14, 60, 43,117,251,
+ 59,106,124, 60,236, 29,114,164, 57,248, 56,251,100,161, 25, 70,136,113,150, 68,140,197,116, 54,107, 74,111,123,142, 92, 42,130,
+182, 95,119,180, 91,131,225,197,130,254,156,101, 62,220,153,165,214,222,165, 49,219, 45,135, 75,230,210, 21,109,127, 63,195,141,
+ 23,124,110,242,118,252,121, 35, 5,127,137, 36, 91, 60,210,177,117,233,201, 30,231, 34,198, 93, 84, 91, 73, 37, 88, 1,126, 23,
+ 7,204, 85,236,142,212,205,201,238, 65,150, 36, 17,109, 75,148,115,217, 22,107,234,145,177, 95, 17,173, 1,135,225,114, 90,229,
+186,165,108, 56, 40, 36,213,225,217, 59, 96,194,124, 20,200,201, 69,124,109,191, 16, 74, 26, 61,106,187, 91,153, 49,164, 91,198,
+ 87, 94,163,118,186,144,124,133, 64, 55,113,119, 72,216,100, 43,232,155, 36,174, 36,187,132,218,100, 84, 9, 14, 59,196,146,124,
+192,234,111,222,240, 30, 52,231,186, 72,220,223, 1, 48, 93,225, 57, 79,183,195,148,100, 85, 15,150,152,231, 47,165,160,241, 10,
+ 85, 74,235,243,240,183, 26, 62,239,219, 88, 91,211,202,114,229,152, 25,112,167,219, 92,198, 80,126,235, 33,163,119,126, 40,126,
+ 59,194, 45,225,207,133, 77, 59,111, 16,110,131,115,235, 74, 80,100, 28,213,195, 58, 58, 35, 41,161,244,166,113,240,235,191, 78,
+252, 53, 90,230,246,189, 1,204,236,221,239,157,147,135, 30, 86,102, 57,151, 54,108,125,180,197,137, 25, 68,137,165,206,121,163,
+ 86, 87,248,153, 65,233,234,109, 87,176, 28, 56,213,249, 59,251, 26, 45,195, 23,107,203,197,108, 92,169,158, 24,101,130,105, 81,
+102, 89,114, 37,104, 35, 17, 68,126, 41, 83, 82, 92,184,252,210, 15,184,216,157,143,183, 97, 64,216,184,249,121, 90,213,113, 23,
+ 26,119, 49, 51,195,232, 36,146,108,125, 0, 68,170,109,213, 42,117,131,117,246,241,171, 49,118,172, 24,121, 17,100,166,225,152,
+ 77,226,108,181,103, 67,234,100,133,228,154, 55,153,180,106, 31, 20,166,234,133, 84,139, 11, 88, 85, 0,119,174,226, 93,147, 50,
+ 73, 37, 89, 36,138, 13,183, 43,112,120, 16, 32, 13,208,146, 4,249,155,226, 13,251,206, 30, 20, 55,238,217,220,156, 72,246,198,
+125,201,115,101,193, 24,157, 85,177,233, 99,174, 99, 73,213,211,111,236,220, 11, 91,230,225,203,141, 94,221,187,111, 7,123,121,
+159, 46, 73, 80,205,133, 62,220,221, 34,162,209,100, 52,114, 59, 13, 72,223, 24, 49, 11,120,123, 40, 25, 29,173,139,145, 60,249,
+ 24,249,121, 24,153, 82,229, 62,112,201,136,198, 89, 30, 76,117,194,145, 16, 58, 50,233, 49,160,230, 9, 13,198,245,158,101, 41,
+109,221,217, 36,153, 19, 69,151, 3,175, 91, 62, 76, 92, 88,217, 68,111, 18, 71,183, 71,184,149,153, 79,231, 95, 82,159,109, 85,
+159,188,167,203, 27,123,109,184,165, 99,201,125,165,242,102,148,169,233,166,231, 42,129, 16, 95,206, 61, 59,221,135, 34, 71,209,
+122, 94,206,194,137, 19,211,229,228,197, 34,228,156,181,155, 82, 59,134,108, 81,183,186,222, 88,222,225,162, 94,102,231, 87, 27,
+211, 99,246, 94, 0, 56,125, 44,172,152,225,195, 92, 21,104,129,140,137,155,109, 96,248,207, 41,104,201,191,131,104,211,127,162,
+168, 41,167,127,109,110,251,138,164,125, 67,131, 12,249, 9, 28, 82,163,200,235,143, 40,199, 43, 34, 41,188, 76,238,203,160, 55,
+ 53, 55,173, 94,222,220, 51,183, 39,221, 87, 62, 37,133,240,243,142, 50, 68,164, 54,148, 24,240, 75,109, 99,230,248,165, 60,124,
+170, 43,217,216,102, 28,220, 71,202,201,124, 60,148,154, 40,241,181,170,164, 11,145, 33,157,250, 90, 80, 18,193,248,169,125, 86,
+ 28, 60,239,123,104,218, 27,106, 25,102, 41,229,203,151, 50,127, 85,149, 52,253, 48, 76,166, 56,225, 58, 68, 73, 26,133,180, 67,
+133,168, 11,250, 62, 43, 90,160,192, 95,135, 10,180,139,212, 66,246,179, 14, 98,128,192, 88,154, 1,163,224, 40,209, 99, 54, 82,
+158, 33,109,226,104, 42,132,130,193,180,210, 65,144, 5,226,189,189,149, 72, 89, 27,116,177,126,244,176, 33, 56,154, 48, 49,222,
+169,151,203, 11,102,213,164,240, 55,171, 0, 95,151, 15,109, 1, 97, 76,124,111, 77,170, 62,116, 61, 26, 69,175,168,243,167,183,
+ 10, 0,182,140,243, 63, 77, 79, 76,119,231,202,171,155,159,163,149, 49, 60,239, 64, 88,233, 71,111, 10, 70, 4,229,122, 5,200,
+ 60,233,245,155,208, 19,120,213, 69,129,170, 89,145,252, 33,188, 69, 29,174, 90,194,155,166, 39,117, 67,242,243,111,112,162, 5,
+ 65,143, 43, 8,200, 70, 32,248,128,106, 93, 9,255, 0,217, 63,234,154,218, 80, 0, 10, 5,128,224, 0,169, 0, 60,171,123, 60,
+ 73, 83, 34, 44, 89, 73,212,209, 53,135,134,147, 86, 96,134,101,184,233, 48, 23,241, 83, 90, 72, 42,194, 11,123,106, 40, 42,241,
+ 27,151, 3,231,174,221,142, 5,239, 14,240,204,155,107, 66,112,247, 44,131, 54,251,145,187, 79,180, 69,140,178, 76,232,176, 51,
+227,130, 88,200,195,149,113, 61,241,180,207, 63,121,166,209,183,236,141,183,102,228,116,145, 49, 83, 50, 76,255, 0, 83, 44,204,
+ 89, 50, 19, 38,110, 44, 37, 14,191,233,122,214,220,251,159, 31,102,238, 94,243,218,183,173,167,248,190,195,185,110,217, 15, 52,
+ 29, 87,199,101,158, 9,229,104,222, 41,208, 53,141,155,136,183, 17, 84,167,222,247,253,207,239, 3,104,220,253, 60, 29,191,147,
+142, 49,134,211, 6,121,120,113, 96,198,199, 95,220, 44,146, 74, 3, 24,202,169,187,120,222,178, 82,175,117,246,119,115,237, 27,
+122,110, 27,150,229,143,187, 98, 98,202, 49, 50, 27, 19, 44,229,122, 73,200,191, 66, 96,126, 67,195,195,133,119,253,157,133,143,
+ 47,105, 98,192,157,183, 30,173,198, 35,211,194,147,184, 50,176,166,221, 90, 33,166, 89, 97,195, 65,160,220,175, 35,252,149,159,
+223,145,227, 98,246,174,225, 22,200,219, 14, 36, 25,217, 49,102,111, 17,109,251,169,207,201,200,148, 49, 8,176,198,200,154, 35,
+ 70,144,181,133, 98,118,255, 0,125,190, 60, 91, 54, 44,253,179,252, 91,184,182,104,204,125,189,152, 36,153, 89, 81,181, 75, 31,
+ 83, 26, 53, 61,109, 26,139, 39, 17,248,234, 36,146,162, 84, 94, 5,109,183, 86,235,230,110,253,216,174, 44,184, 27,208,108, 73,
+ 98,134, 77,202, 52,131, 18, 55, 5,163,102, 73,116, 66, 76,162,238, 71,203,202,247,175,114,195,195,200, 76, 88, 16,227,202,154,
+ 99, 81,161,193, 44, 44, 7, 6, 35,129, 53,227,191,115, 83,228, 28, 13,218, 76,150,101,203,147,119,197,105, 99, 42,218,158, 75,
+ 72,204,140,170, 87, 79,197,250, 92, 1,175,161,198,166, 85,102, 5, 88,128, 89, 46, 13,143,149,197, 90, 16,202,232,203,209,183,
+ 77,175,210,181,172,121,245,111,111,170,149,106,248,125, 31,142,149, 90, 16,195,127,204,255, 0,135, 31,236, 45, 70,164,255, 0,
+221,255, 0,195,143,246, 22,163,227, 66,149,178, 71,198, 61,223,142,131,236,163,100,124,227,221,248,232, 39,137,225, 64,121,179,
+247,150,253, 30, 83,224,234,136,200,174,219,102,173, 2,255, 0,196, 31, 53,225,132,219,135, 15, 78,129,237,252,235,248, 86, 94,
+249,157,184,190,212,147,195,148,113, 99, 56,125,199,170, 8, 65, 69, 45,143,152, 35, 87,190,171,234,226, 13,252, 56,219,157,122,
+151,240,173,183,168,100, 56,112,117, 12,195, 40,191, 73, 53,117,194,232, 19,222,215,234, 5,225,171,157,170, 19,108,155, 54, 76,
+ 41, 22, 70,221,141, 44,113, 25, 90, 52,120, 35,101, 83, 57, 38, 98,170, 84,216,201,168,234,243,191, 26, 3, 59, 97,204,220,114,
+198,245,137,149,146, 36,155, 11, 53,241, 96,201, 17,170,144,167, 30, 9,212,148, 28, 14,150,152,253, 28,235,131,237,173,215,123,
+199, 76, 28,175, 94,211, 9, 33,216, 34,200, 73, 84, 62,181,204,200,200,129,190, 38, 36,134, 85,111,152,113, 36, 11,215,170,199,
+143, 4, 45, 35,195, 18,198,211, 63, 82,102, 69, 10, 93,244,132,214,228,124,205,165, 64,185,240, 21, 86, 29,151,102,198, 5,113,
+246,236,104,148,178, 72, 66, 67, 26,141,113, 57,150, 54,248, 87,154, 59, 22, 83,224, 77,232, 14, 33,119,253,219, 27, 11, 22,108,
+105, 34,199,196, 89,243,142, 87, 73, 18, 70, 66,187,140,144, 70,243,196,205,213, 16,176, 12, 11,198, 47,175,217, 87,190,240, 55,
+ 29,198, 60,108,253,191, 19, 39,210,194,155, 78, 86,108,140, 20, 23,145,149,227,137, 80, 55, 2,182,214, 77,215,141,200,250,122,
+134,216,182,105,154, 23,147,111,198,118,199,102,146, 2, 98, 75,163, 59,245, 93,151,225,224, 75,252,103,249,220,121,209,115,246,
+157,175,116, 17,255, 0, 18,194,131, 48, 69,171,166, 50, 35, 89, 2,234, 22, 96, 3,131,206,220,104, 14, 55, 59,122,221,113,100,
+221,255, 0,135, 50, 69,209,221, 37, 89,250, 43, 27,228,180, 49,224,227,203,212, 72,167, 96, 36, 10,238, 58,154,126, 45, 28,184,
+213,125,191,117,223,101,238, 9,113,113,247, 53, 41,185,231,195, 31, 83,165,169, 35,140,237, 43,157,251,132,144,252, 32,144, 0,
+191,188,241, 38,187,140,173,143,102,205, 12,185,120, 24,243,171,201,215,113, 36, 72,218,165,210, 35, 50, 53,199, 22, 40,161, 73,
+ 62, 28, 57, 84,198,211,182,174, 88,207, 92, 40, 6, 96,181,178, 68, 73,213, 26, 81,162, 95,222, 91, 87, 4, 98,163,143, 35,106,
+203, 7,157,190,239,185, 64,159,196,176,178, 19, 14, 76, 61,187,127,202, 17,132, 13, 20,135, 19,113, 93, 40, 81,205,174,250,120,
+183, 62, 38,214,189,116, 49,247, 30,235,149,187, 38,222,174,144,164,187,164,248, 11,116, 5,146, 36,218,215, 57, 57,243,101,153,
+184,251, 56, 87, 65, 46,197,178, 76, 34,235,237,184,178,116, 89,158, 29, 80,198,116, 52,143,214,114,191, 15, 13, 79,241, 55,153,
+226,104,135,106,218,198,121,221, 6, 12, 30,188,144,125,103, 73, 58,183,208, 98,191, 82,218,175,160,233,247,112,160, 60,223,182,
+247,157,222, 61,182, 8,211, 33, 91, 43, 39, 27, 98,132,238, 18, 38,185, 16,102, 77,147, 27, 23,212, 72,114,160,105, 93, 95,156,
+120,223,149, 92,205,238,174,224,139, 14,118,143, 34, 53,151, 3, 19,118,200,121,186, 42, 70, 67,109,185,177,226,198, 64,110, 10,
+178, 41, 58,173,244, 90,187,116,217,118, 72,160,155, 26, 45,183, 22, 56, 50, 0, 89,226, 72, 99, 85,112,172,206,161,194,168,189,
+153,217,135,180,147, 86, 97,217,246,134,128, 64,112, 49,204, 75, 11, 98,172,102, 36, 42, 32,114, 25,225,177, 31, 35, 21, 4,175,
+ 35,106, 2,250,116, 27, 88, 66,173,160,233,112,182, 54,107, 3, 99,110, 70,198,166, 16, 30, 0,112, 34,135, 28, 24,240,180,173,
+ 4, 73, 19, 78,253, 89,202, 40, 82,242,105, 84,214,246,249,155, 74, 1,115,224, 40,129,213,121,159,101, 64, 62,149,224, 45,248,
+ 41,149, 53, 49,191,135,141, 57,146, 51,205,135,215, 81, 89, 82,236,117, 80, 4,211,196,143, 10, 69,120, 89, 71,190,134,211,131,
+123, 15,166,198,152, 76, 8,191, 27,242,181,141, 0, 69, 3,199,137,170,206,151, 99, 98, 64,240, 21, 62,175,144, 55,247, 90,135,
+169,136,251,106,160, 71, 73, 28, 53, 84,149, 47,196,154,111,140,139,242, 6,144,103, 94, 95, 93, 80, 71,197,170, 66,162, 46, 73,
+ 62,116,224,219,157, 64, 10,247, 55,243,162, 45, 12, 84,193,181, 0,148,113, 39,218,105,228,177, 20,232, 56,123,233, 63, 35, 84,
+133,102,123, 41, 3,153,166,135,196,212, 31,230, 52, 72,121, 26,134,145, 25,248,145,122,120, 13,151,235,167,100, 46,252, 8, 22,
+ 30, 52,163, 22, 95,164,211,144, 45, 42, 90, 53, 30, 44, 73,185,242, 2,171,160,144,131,161,244,132, 55, 31, 79, 26, 52,173,253,
+154, 15,209,185,250,120, 84, 5,244,185, 3,230, 28, 62,138,133, 37,139,123,177,111, 30,126,250, 28,138, 5,192,243,167, 89, 5,
+248,120,219,133, 69,219,135, 31, 19, 64, 66,195, 65, 31,233,194,167, 14,107,192,186, 20, 2, 9,168,115, 67,244,209,177,206, 30,
+128, 37, 7, 87,190,213,163, 36,223,113, 50, 71,210, 40, 1,126, 23,181, 58,248,159,109, 74,100,193, 49,134,136,254,242,227, 72,
+250,105,172, 45,106, 2, 68,249,126, 10,112, 1, 81,226,124,106, 54,243,172, 77,191,187,118,188,253,255, 0, 51,183, 34, 18,199,
+157,134, 9, 99, 34,168,142, 77, 58,117,116,152, 51, 19,109, 67,152, 20, 6,239, 58, 96, 46,125,158, 85,159, 14,243,139, 54,241,
+147,177,170,200, 50,177, 97, 76,137, 36, 32,116,202,200, 72, 80,167, 86,171,240,242,173, 27,125, 38,128, 68,112, 20,214,177, 53,
+ 82,125,219, 11, 31,114,196,218,101,114, 50,243, 86, 71,199,143, 73, 32,172, 67, 83,146,220,133,170,233, 4,208, 3,183,198, 15,
+149,207,224,171, 88,209, 21, 95,139,230, 60, 77, 10, 37,187,223,192, 81,167,157, 49,113,229,200,112, 74, 66,141, 35, 5,231,101,
+ 26,141,175,106,212,122,145,176,225,125,181, 48, 24,114,172, 14,216,238,189,179,187,112, 95, 63,109, 18, 34,199, 33,138, 72,103,
+ 85, 89, 20,216, 48, 36, 35, 56,179, 3,192,222,174,108, 91,238, 38,253,136,249,152,139, 34, 71, 28,210,227,178,204, 20, 54,168,
+ 91, 67, 17,165,152, 90,227,133,111,113, 30,188, 13, 80,214,240,162, 35,159, 1, 80, 12,181, 53,101,168,186,150,157, 79, 17,192,
+201,237,220,108, 31,188,137,123,171, 12,230,237, 45,220, 38, 57,213, 45,212,139,171, 52,145,137,226,241, 12,154,175,194,185,175,
+188, 73,182, 92,255, 0,188, 78,221,124, 45,199, 31,248, 65,195,219,210, 61,199, 33, 86,120, 22, 52,119, 93,115,198,108, 26,214,
+248,149,173,237,181,123,148,223,118,221,139,184,101,100,102,102,108,208,205, 62, 84,141, 54, 67,147, 32,215, 35,177,118,118, 1,
+192,185, 38,245,207,102,118, 47, 97,227,119,142,221,219,139,219, 88,103, 27, 55, 18,124,167,152,180,221, 64,208,176, 80,163,247,
+154,108,111, 88,106,140, 86,135,153,125,230, 54,199,153,218,184, 45,137,159,183,229,238,155,126,116,240, 77, 52, 50,225,156,153,
+177,207, 8,159, 70, 12,113, 38,131,243, 5,177,210, 56, 94,247,174,219,183,247, 30,203,194,198,251,186, 94,225,143,210,238,131,
+ 5, 38,219, 55,123,133, 80,194,241,122,105,219,244, 27, 95, 13, 92, 1,242,241,210,143,238,187, 99, 76,227, 14, 87,109, 97,140,
+ 78,188,142,185, 1,141,250, 55, 61, 56,244,137,111,123, 91,195,236,161, 31,187,141,157,230,195,145,123, 87, 22, 72,244,204,185,
+ 88,102, 94, 32,134,253,203, 35,153,109,242,139,145,122,187, 93, 42, 42,115, 95,118,168,141, 63,112,201,165,117,142,224,132, 44,
+165, 85,172, 11,203,113,196,142, 6,190,130, 32,158, 66,188,247,105,237,121,246, 65, 38, 46,215,219,216,248,152,249, 15, 28,178,
+250,121,202, 40,120,203,233,123,180,165,239,102,175, 65,141,116, 34,173,201,210, 0,185, 36,158, 3,196,158, 38,161, 71,227,229,
+198,212,169,252,105, 80, 24, 15,202, 63,248,113,254,194,212,125,183,169,191,230, 15,247,113,254,194,212, 56,242,160, 43,100, 31,
+140,123,191, 29, 10,244, 76,144,117,142, 30, 31,109, 6,128,157,197,193, 52,193,128, 53,207,193,221, 24,211,166,220,230, 35, 26,
+110, 25, 89,152,106,206,194,209,156, 47, 81,173,220,254,139,122, 99,111,125, 30, 62,230,216,101,197,124,212,205,140,227,196,241,
+198,238, 67, 15,138,107,116,172, 8, 4,137, 53, 13, 36,112, 62, 20, 33,176, 88,113, 21, 30, 99,149,100, 73,221, 27, 12, 49,193,
+ 52,153,209,172,121, 10,207, 19, 16,223, 44,110, 35,145,152, 90,234, 17,141,155, 85,180,248,213,184,183,125,182, 89,215, 22, 60,
+149,105,158, 89,113,214, 49,123,153, 96, 26,165, 78, 95,154, 40, 82,240, 22,250,105, 15,109, 98, 67,221, 91,108,185,217,187, 91,
+ 49,139, 51, 18,103,129, 34,111,239, 76,112, 38, 83, 20, 54,210, 62, 23, 60, 9,191,194,106,120, 93,205,181,102,193,182,179,204,
+ 32,200,220,241,224,201,135, 25,248,178,174, 66,235,141, 93,128,210, 11,113, 11,115,241, 16,109, 66, 27, 32,212,197,171, 21, 59,
+155, 96,118,201, 85,206,140,156, 72,229,159, 33,142,160, 22, 56, 27,167, 43,106, 34,199, 67,112,107,114,170,216, 93,215,133,184,
+ 76, 83, 28, 5,137,115, 36,193, 50, 72,218, 11, 24,177, 70,107, 58, 70,203,168,240,107, 21, 54, 34,196,212,101, 58, 35,106, 86,
+184,172, 56,251,175, 96,151, 26,124,200,243,227,104, 49,196, 70, 87, 1,185,100,112,135, 72,211,119,234, 30, 11,166,247, 60, 57,
+212,241,187,151,111,204,204,193,196,193,111, 82,153,209,229, 72,153, 8,126, 21, 56,109, 20,114, 35, 3, 99,125, 83,126, 10,128,
+215, 34,139, 20,105,109, 77,196,154, 29,197, 89, 3, 74,139, 0, 5, 64, 50,199, 16, 60, 64,246, 81, 34, 72,236, 78,145,206,163,
+194,215,242,229, 83,140, 0,160,223,219,198,128,154,170,234,228, 5, 49,190,160, 0, 26,124, 77, 56,117,183, 23, 11,244,212, 94,
+ 88, 7, 39, 31, 93, 1, 34,160, 14,124, 64,170,234, 84,131,194,246, 53, 51, 50, 88,233, 55, 63, 93, 15,170,160,124,166,227,216,
+104, 9, 18, 57, 80, 15, 17,193, 77,249, 84,154, 80,109,112,109, 81, 46, 61,191, 85, 84, 4, 11, 15, 14, 94,218, 98, 90,214, 20,
+218,133,143, 3, 76, 91,200,112,170, 6, 6,156,159,132,251,170, 36,240,166, 98,116,212, 3, 10,151,133, 48,169, 91,133, 1, 49,
+192, 10,140,166,200, 77, 78,212, 57,133,210,198,169, 10,128, 23,110, 30, 53, 97, 84, 11,138,132, 41,198,255, 0, 85, 61,200,144,
+159,109,103,139, 52, 72,175, 27,208,211,151, 26,152, 36,177,191,209, 80,242,170, 3,201, 98, 75,121, 34,255, 0, 45, 17, 37,141,
+ 88, 70,124, 77,175,237,242,161,147,101, 18, 17,240,145,161,168, 68,190,128, 21, 69,143,197,175,202,161, 73, 50,168, 44,202, 45,
+103,210, 8,246, 11,154, 27,157, 86,162,130,166,202,156, 86, 53, 36,183,155, 55, 58, 19, 90,213, 72, 34, 14,142, 92,232,108,156,
+ 65,181, 94, 55, 8, 1, 0,139, 84, 78,147,111,134,169, 10,128, 1, 42, 91,151, 15,229,171,160,253,126,117, 80,155,206, 60, 60,
+170,218,113,176,160, 37,113, 94,103, 38,213,145,153,147,220, 59,166,212, 63,250,214,207,186,156,172, 32, 7, 23, 94,132, 98, 88,
+ 15,243,101, 81,107,120,154,244,221, 35,128,241,172,253,187,102,197,219, 50,247, 12,184, 30, 70,147,114,152,100, 78, 28,130,161,
+130,132,178,105, 85,176,176,241,189, 3, 56,188,110,224,139, 55,115,222,123,139,109,248,173,176, 71,147, 18, 27, 18,178, 70,103,
+ 99, 27,123, 85,151, 73,170,242,108,145, 67,216,203,221, 73,151,145,252,120, 98, 38,227,252, 72,207, 38,190,163, 1, 41,143, 78,
+189, 26,120,232,211,166,213,213,224,118,174,201,178,238,123,142,227,141,175, 86,232, 8,200,197,114,166, 21, 12, 75, 48,141,116,
+130, 3, 18,120, 92,213, 21,236,141,180,227,174,220,119, 60,227,179, 6,213,252, 36,202,189, 27, 6,215,211, 47,163,170, 99,191,
+230,234,161, 12, 93,207,106,195,223, 59,187,182,178, 51, 4,200,219,166, 12,179,100,172,115, 73, 29,157, 33, 66, 2,105, 97,163,
+219,110,126, 53,232,123,142, 86, 62,223,129,147,155,150,229, 49,224,137,229,149,151,152, 85, 4,157, 54,241,242,172,173,227,183,
+ 54,237,230,124, 28,166,200,200,194,200,192,214, 49,231,194,147,162,225, 36, 1, 94, 59,233,111,132,129, 91, 25, 88,120,251,142,
+ 44,248, 89, 75,212,198,201,141,162,149, 15, 11,163,130,172, 46, 61,134,136,167,150,178,228, 98,102,118,198,245,183,109,115,237,
+ 88,217,155,158, 46, 48,204,200,206,146,108,140,152,114,111,194,104, 9,117, 80,200, 47,197,174, 43,213, 55,111,255, 0, 44,205,
+255, 0,129, 47,236, 26,231, 96,251,189,194,140,109,227, 35,118,220,178, 97,218,178, 34,202,192,130, 89,144,198,134, 3,116, 66,
+189, 47,136,120,121,219,128, 35,141,117,115, 99,166, 78, 60,176, 72, 72, 89,145,163, 98,188,192, 97,164,218,247,243,173,197, 25,
+ 60,187,102, 31,229,140, 30,220,238,232, 56,109,153,216,152,216, 59,248, 91,105, 94, 1, 32,203,111,232, 49,208,199,202,162,243,
+205, 15,103, 76,248,242,180,101,187,137,212,180,108, 86,234,217,134,226,235,224,107,209, 49,187,115,109,198,237,245,237,166, 86,
+159,111, 88, 14, 49, 19, 16, 93,144,130, 56,149, 10, 47,199,152, 21,155,141,216,187, 44, 29,179, 47,106,117, 50, 36,193,145,204,
+189,103,117,235,171,151, 18, 7, 87, 68, 80, 10,176,225,240,213,163,248, 0, 29,209, 60,241,247, 87,103,198,146, 50, 36,185, 25,
+ 66, 68, 82, 64, 96, 32,184,212, 7, 58,202,219, 59,127, 23,185,119,190,235,139,118,200,203,150, 40, 51, 4, 88,208,174, 76,201,
+ 28,122,162, 13,173, 81, 29, 65, 32,158, 0,220, 15, 42,222,197,236,124,100,220,118,253,215, 55,117,220, 55, 12,205,181,157,177,
+219, 38,100,100,179,174,130,165, 4, 96,114,241, 28, 79,137,173,173,175, 97,196,218,243, 55, 44,220,119,145,228,221, 38, 25, 25,
+ 11, 33, 82,170,225, 66, 90, 61, 42,164, 11, 15, 18,106,237,174,180, 7,150, 97,237, 75,159,247, 89,254,111,202,207,206,125,247,
+ 26, 41, 37,196,203,245, 83, 14,151,166,157,225, 68,141, 21,194, 1,161, 56,155, 94,252,111, 93, 86,239,129,141,220,125,233,218,
+240,110,109, 43, 69, 62,209, 52,179,136,101,146, 2,231,247,108, 67, 52, 12,141,164,147,200, 26,232,112,251, 43,108,199,237, 38,
+236,212,150,115,183, 52,114, 68,102, 44,157,125, 50,200,211, 55,197,211,209,125, 77,195,224,163,110, 93,149,135,185,101,109,249,
+209,110, 57,219,126, 86,219,140,112,224,155, 14, 72,145,140,109,107,235,234, 67, 39, 19,167,194,213,134,137,161,201, 99,203, 63,
+105,111, 61,215,179,109, 83, 77,149,182,109,219, 95,241, 92, 92,105,228,105,142, 52,193, 93,186, 8,210, 22,109, 47,109, 86, 38,
+176, 48,182,158,239,204,217, 48, 55,221,147,103,206,126,226,149, 97,204, 77,242, 77,198, 13, 19,107, 34, 71, 71,129,178, 0,233,
+ 50, 18,161, 52,139,120,248,215,173,108,189,171,180,236,112,229, 38, 50, 60,242,231,157, 89,249,121,110,103,159, 32,219, 79,239,
+164,126, 96, 3,192,114,172,124,127,187,140, 92, 47,240,216, 59,214,233,139,180,106,214, 54,136,178, 20, 64, 46,218,140,106,197,
+ 12,130, 51,226,186,190,154,149,210,131, 83, 22, 93,171,252,195,247,147,155, 6,229,145,147, 30, 46, 22, 22, 14, 88,192,138, 98,
+ 34,105,131,146, 4,128,112,101, 22, 55, 3,157,122, 70,182,240,172,200,182, 28, 76,125,251, 47,184, 81,228, 57,121,144, 69,141,
+ 44,108, 87,164, 18, 18, 74,149, 26,117, 95,143, 31,138,180,109,230,106,161, 73,114, 39,169,191, 5,255, 0, 13, 42,107, 11,115,
+240,252,116,170,151, 95,129,140,246,248, 15,251,184,255, 0, 97,106, 53, 39,254,236,127,187,143,246, 22,154,226,178,104,169,147,
+243,142, 30, 31,140,208, 69,175,225, 71,201, 63, 24,247,125,180, 2, 46,104, 14, 39, 23,177,219, 22, 77,191, 50, 24,176,163,220,
+177,242,247, 28,140,188,197, 65,212,146, 60,181,203, 88, 20,185,143, 83,233,235,199,169, 91,135, 14, 23,225, 89,159,229,190,225,
+219,240,250,178,196,153, 57, 83,229,236,204, 81, 38,154,115,175, 19, 33,122,178, 57,104,190, 8,191, 59,225, 22, 69,240,225, 94,
+147,107,114,166,225,122, 3,205,178,123,107,126, 50,182, 20,112, 68,102,220,246,253,225, 50,165,102,147,211,227,182,229,153, 20,
+186, 22, 65, 25,212,200,175,112,164, 13, 90, 77,107,108,219, 75,167,122,238,121,136, 31,248,126, 44, 96, 66,206,140,128,229,228,
+ 36, 49,100, 50, 22, 0, 53,147, 17, 46, 71, 15,140,215,103,111, 42, 86, 60,232, 14, 61,251, 99,118,151,119,154, 70,104, 23, 1,
+247, 25, 55, 88,229, 87,115, 53,219, 3,248,122,194,200, 99, 10, 62, 35,168,144,199,133, 84,195,236,141,195, 31, 39,106,235,116,
+167,143, 26, 13,173, 50, 31,212,228,198,145,203,182,143,136,166, 60,122, 35,159, 89, 10, 81,164,249,120,240,240,174,238,230,149,
+248,222,128,225,228,236,125,206, 76, 89, 32,105,177,213,155, 19,116,129, 77,220,142,166,110,122,103,193,113,160,124, 33, 82,207,
+228,121, 94,143, 7,108,239, 18,230,141,195, 47,211, 66,242,110, 89, 25,239, 12,114,188,154, 99,155,109,254, 30,137,168,196,151,
+ 97, 39, 19,194,214,250,171,178,189,205, 33,199,202,128,243,233,123,103,114,217,182,216,243, 28,197, 52,152, 24,219, 28,107, 28,
+ 66,105, 3, 75,182, 52,130,109, 66, 56,154, 65, 25,234,220, 50,163, 17,204,175, 10,211,237, 45,175, 48, 38, 62,233,153,140,145,
+200,102,221,100,187,107,141,213,115,114,214,100, 41, 12,137,170,206,177,223,226, 42, 64,183, 14, 60, 58,238, 32, 82,191, 10,200,
+ 17,249,111, 69,211,230,205,238,185,161,139, 16, 7,186,138, 71, 30, 21, 0,221, 53, 60,248,251, 9,169,136,208,240,211,206,152,
+ 3,206,214,246,212,137,241,160, 25,180, 40,181,169, 88,105, 30, 3,149, 68,217,128,185,191, 26,147, 58,175, 34, 47,229,194,128,
+152, 3,199,133, 34,109, 80, 50,165,129,213,115,229, 80,234, 3,204, 31,168,213, 4,139,112,183,133,234, 55, 94, 28,106, 46,117,
+ 15,148,129,230,105,172, 60,168, 7,186,249,211, 93, 88,219,198,155,147, 10,151, 11,131,227, 84, 8,129, 80,147,130,123,205, 72,
+158, 53, 9, 57, 1,237,168, 6, 28,234, 71,203,253, 57,212, 71, 58,152, 63, 16, 30,234, 16, 37, 6,126, 86,162,147,106,175, 33,
+185, 21, 65, 36,224, 40, 90,198,187, 31, 26, 33, 54, 91, 80,209, 65,226, 69,234, 36,105,146,184,248,136,168,120, 11,212, 3, 5,
+186,129, 97, 83,101,248,109, 70, 17,114, 54, 1, 89, 27,136, 54,189, 60,145, 33,143, 72,190,159, 10,174,178, 88, 90,223,232, 5,
+ 46,185,228, 9,169, 66,146,109, 42,186, 19,128,160,147,115,238,169, 22, 5,121,211, 53,128,184,242, 53, 72, 78, 57, 68,192,240,
+181,185,210,195,139,170, 95, 81, 54,240,227,239,168, 99, 13, 40,215,241,251, 42,222, 26,162, 6,208, 15, 16, 47,127, 58,164, 34,
+216, 54,117,117,107,219,207,221, 68, 48, 56,240,189, 29,154,203,195,194,160,146, 92,106, 34,215,240,160,168, 34,172,188,233,151,
+217,198,157,231, 13,164, 41,224,198,198,157,108, 57, 80, 25,217,127,219, 26, 0,231, 71,201, 23,157,173,202,153, 80,222,244, 3,
+172, 78, 92, 39, 16,120,114,242,173,104, 80, 40, 0,120, 80, 21, 65,148,191,184,125, 85,110, 49, 85, 2,100,120, 83,211,129,115,
+106,153, 90,218, 48,217, 14, 38,156, 45, 61,173,227, 83, 75,214,144,173, 72,128, 71, 42, 42,147,227, 82, 0,159, 10, 34,160,241,
+164,171,200, 86,132,144,120,222,138, 13,169,130,139, 84,128,227, 88, 13, 18, 13, 76,204,223,155, 82,181, 43, 53, 77, 13, 32,101,
+143,136,168, 27,115,163,105,191, 58,137, 65, 85, 52, 82, 28, 52,255, 0, 87,255, 0,210,165, 83,210, 45,244,126, 58, 85,107,248,
+131, 18, 75,254,239,254, 28,127,176,181, 31, 42,155,142, 9,255, 0, 14, 63,216, 90,137,229, 88, 5, 92,159,237, 71,187,241,208,
+173,111,101, 23, 38,218,199,186,133,244,125, 52, 3, 16, 77, 59, 88,114,165, 81, 55,160, 21,248,211,241,166, 21, 48, 46, 47,206,
+132, 35,203,133, 55,190,166, 71, 27,218,151,143, 33, 64, 53,189,180,220, 69, 61,128,241,165,204,243,225, 64, 56,226, 56,211,216,
+ 83, 15, 31,101, 58,155,222,178,202, 36,143, 89,211,123, 88, 94,137,209, 55,226,231,240, 83,195,249,223, 71, 27, 81, 77,219,159,
+133, 64, 0,162,150, 85, 4,159, 49,122, 39, 70, 34,109, 98,125,132,211,105,180,156,128,246,209, 9,241, 22,184, 52, 3,172, 17,
+219,130,129, 80,101, 80,108, 0,162,107,241,189,234, 5,148,113, 54,227, 64, 70,192,178,219,223, 68, 35, 87, 11, 80, 68,137,175,
+230, 22,169,180,209,240,170, 8,206,188, 21,110,126,138, 14,149,189,174,104,142,198, 78, 35,151,180, 84,116, 30,122,184,208, 13,
+161,120, 27, 84,108, 1, 22,169,219,249,199,133, 68,128, 8,181, 0,205, 80,127, 10, 39, 51, 67,127,155,232,160, 24,124,213, 63,
+239, 42, 11,206,157,141,158,254,195, 66, 4,115,194,171,155,106, 30,218,176,167, 82,131, 65,144, 89,253,213, 64,143,141, 50,158,
+ 22,165,122, 19,135, 82,116,242, 53, 13, 18,176,107,240, 30,195, 83,107,145,244, 10, 4,114, 53,194,249,154,181, 25, 64, 73,115,
+ 97,192,113,163, 8, 21,248,125, 6,162,120, 30, 62, 68, 85,187, 66,234,218,124, 15,242,212, 27, 28, 31,101,234, 20,174, 45,126,
+ 60,170,109,109, 60, 60,173, 83,120, 8, 28, 15,250,127,161,168, 48,178,123,121, 80, 19, 28, 35, 39,253, 57, 81, 54,246, 99, 27,
+ 19,199,226,252, 85, 3,194, 22,191, 59, 31,228,169,224,112,137,189,173, 90, 70, 89,104,248, 83, 26, 95, 77, 42, 16,173, 42,133,
+120,192,229,123,154, 32,185, 62,202,132,255, 0,219, 70,190,250, 40, 6,220, 57,208,165, 9,173,214,111, 43,254, 42,156,107,168,
+219,220, 77, 66, 75,153, 91,223, 86, 34, 91,113,241,160, 44, 70, 42,218, 11, 10,173, 16,171,106, 57, 10,210, 68, 36, 56, 11,248,
+211, 92,249,211,146, 41, 90,252,171,113, 70,120,139,135,137,169,163,133,229, 67, 43, 72, 10,172,195, 77, 58,150, 67,147,227, 68,
+ 83,237,170,235, 97, 82, 13,198,175, 35, 73,174,101,144,198,136, 13, 5,120,142,117, 45, 44, 56,214, 90, 69,221, 80,234,194,165,
+172,120, 85,109, 70,164, 24,214, 92, 74,131, 94,252,233,190, 17, 81, 6,153,143,149, 40,105,164, 75,133,190,143,199, 74,163,115,
+167,250,191,142,149, 41,248,146,136,198,115,193, 63,225,199,251, 11, 81,189, 73,199,201,255, 0, 14, 59, 31,234, 45, 68, 14,126,
+ 85,146,149,178, 15,198, 56,248, 80, 79, 17, 86,222, 30,161,190,171,120, 91,159,227,168,140, 95,231,223,232,160, 42,216,211,219,
+133,175, 86,125, 40,183,205,244,218,144,197,254,119,224,252,180, 5, 96, 61,180,133, 89,244,196, 31,159,240,126, 90, 94,152,126,
+159,224,160, 43,150, 4,121,154, 97,126,118,171, 3, 23,143,207,248, 63, 45, 56,199, 28,139,126, 10, 0, 31, 64,166,227,110,116,
+127, 79,252,239,193,249,105,122, 99,127,155,240,126, 90, 0, 3,143, 26,149,133,175, 70,244,246,252,255, 0,193, 79,233,255, 0,
+157,248, 42, 48, 9, 3,128, 66,218,220,248,212,254, 50, 69,216, 95,198,194,141, 30, 57, 10, 70,174,102,252,191, 45, 75,211,255,
+ 0, 59,143,186,178, 0,116,248,234,103, 55,250, 57, 83,136,173,127,136,241,246,209,250, 90, 71,205,127,120,167, 17, 17,205,175,
+229,194,168, 43, 24,215, 87, 30, 86,228, 77, 57, 68, 0, 88, 15,170,140, 34, 3, 85,219,159,179,242,211,244, 1,225,171,219,202,
+128, 6,145,123, 88, 82, 96,188,141,168,205, 18,248,184,191,187,242,212, 58,105,195,226,213,229,195,141, 1, 92,189,152,240,189,
+ 71, 89,110, 0,125,116,115, 0, 36,157,127,130,162, 32, 0,124,223,131,242,208, 1, 1,184,139,142, 53, 30, 58,188,234,208,199,
+ 39,147,126, 15,203, 77,233,184,159,139,240, 80, 21,238, 65,168, 49, 36,241,171,126,154,255, 0,157,248, 63, 45, 65,177,174, 79,
+197,248, 63, 45, 1, 93,121,212, 38, 36, 48,176,225,111,229,171,131, 26,223,157,248, 63, 45, 56,128, 6,177,110, 99,202,128,163,
+ 28,186, 65, 20,153,245,113,243,171,237,135, 17,226, 79,224,170,205,134, 53,217, 95,135,187,242,208, 1, 0,145,244,212,159,138,
+ 53,188, 1,171, 62,146,192,124,126, 62, 95,150,154, 76, 95,129,190, 59, 92,121,126, 90, 20,205,139,139,139,209,220,124, 36,251,
+104,209,225,105,144,124,126, 23,229,236,247,209, 91, 15, 82,155, 53,133,252,191, 45, 24, 69,108,102,179, 16,121, 17,252,149,104,
+147,106,120,112,180,139,151,227,238,252,180, 95, 77,199,231,191,209,249,106, 50,149,100, 39,194,131, 39, 5,183,187,249,106,251,
+227,255, 0, 58,215,225,203,242,213,121, 49, 47, 97,175,199,203,242,208, 2, 63, 18,104, 28,207,141, 22, 1,209,129,139,113,177,
+228, 42, 99, 22,223,159,248, 63, 45, 51,193,112, 84, 63, 63,103,229,173, 25, 34, 51, 96, 60, 44, 65,246,212,142, 86, 57, 82, 9,
+ 34,254, 53, 87,209,155,155, 63,224,252,180,189, 27,126,159,224,252,180, 3,163,135,153, 5,245, 88, 27,154,186,167,237,160, 98,
+225, 16,250,245,114,246,126, 90,185,233,248,223, 87,224,161, 76,226,159,190,107,248, 31,229,163,168,229, 70,108,125, 76, 88,183,
+ 63,103,229,169,199,141,199,230,252, 20, 33, 40,215,133, 28,112, 90,116,128, 1,197,184, 14,116,197,146,246,226, 64,246, 15,182,
+180,154, 92, 73, 71,200, 86,225, 72, 27, 83,130,190,223,168,125,180,172,167,207,234, 31,109, 93,235,169,143,175,161, 32,194,164,
+ 56,242,168,133, 30,223,168,125,180, 64, 84,120, 31,168,125,181,119,199,170, 45, 37,208,107, 53, 56, 94, 60,169,195, 1,224,126,
+161,246,212,132,163,244, 79,212, 62,218,187,227,212, 56,190,129, 18,194,142, 31,133,170,168,145,127, 69,190,161,246,212,196,232,
+ 63, 53,190,161,246,212,114,143, 82,168,248, 7,226,124, 41,194,154, 15,170, 79,209,111,168,125,180,189, 90,254,139,125, 67,237,
+172,238, 93, 68, 84,151, 20, 30,215,166,211, 66, 25,104, 63, 53,190,161,246,210, 57,113,254,131,125, 67,237,169,185,117, 44,147,
+124, 3,105,254, 79,199, 74,133,234, 23, 78,171, 55,203,171,195,244,180,249,210,171,185,117, 37, 31,192,203,112, 62, 11,243, 49,
+199,251, 11, 80,226, 15, 10, 41,137,216, 70,192,173,186,113,243,117, 7,228, 95, 2, 69, 55, 69,255, 0,153,250,233,254,181, 67,
+ 64,249,241,165,113,199,249, 40,157, 23,191, 52,253,116,251,105,250, 15,127,153, 57,113,248,215,253,106, 3,204, 54, 21,203,203,
+222,251,109,166,202,103,133, 31,184,100, 16,184,213,241,195,184,116,149,181, 19,207, 68,154, 87,244, 64,225,206,141,187,247,126,
+255, 0,129,157,188,109,208,152,204,219, 90,230,101,179, 58, 93, 70, 41,139, 24,225,179,123,159, 37,175,231,211, 53,219,226,195,
+177,245,160,244, 71, 7,171,254, 43,210,116, 95, 31, 95,246,163,214,244,180, 53,255, 0,181,183, 86,223,157,243,113,170,144,109,
+ 91, 78, 62,241,188,103,100,230,193,145,157,149, 4, 67, 47, 30,121,113,237, 14, 26, 9, 52, 43, 70, 44, 68,100,179,221,159,159,
+209, 64,115,171,220,123,222, 38,230, 54,140,137,211, 40, 67,184, 77,136,249,134, 37, 78,172,107,181, 29,201, 69,147,225, 12,146,
+ 88, 27,120, 85,217, 55,205,210, 94,209,237,253,198, 57, 82, 28,237,227,248,100,115,100, 4, 5, 99, 57,157, 62,171,162, 55,195,
+127,136,133, 7,196,213,246,198,236,145,181, 64,174,118,159,225, 2,114,113,139, 75,138,113,253, 69,152,157, 5,159, 71, 82,218,
+175,227,107,213,236,136, 54, 54,216,213,114, 61, 15,240, 19, 20, 97, 11,203,142, 49, 58, 39, 79, 71, 73,213,211, 11,242,232,183,
+178,213, 1,231,152,187,254,253,133,177,177,197,205, 85,108, 44,109,239,116,146, 89, 99, 18,122,151,196,220, 36,141, 32, 26,219,
+225, 75, 27,124, 38,226,235,111,110,222, 39,113,111, 83,247, 52, 88,210, 74,171,131, 38,231, 54,220,113, 58, 67, 80, 68,219, 23,
+113, 12,100,249,181, 9, 56,123,171,105,224,236,230,195,219,238, 54,129,130, 37,115,182,126,247, 20, 67,214,234, 30,167,167,179,
+ 5,213,212,249,180,254,119, 62, 53,120, 67,179,156,209,163,208, 12,239, 82,246,210,248,253,111, 87,208, 26,255, 0, 59, 87, 87,
+211,243,252,237, 31,205,160, 57,205,131, 19,112,219,123,168,237, 51,238, 47,151, 6, 22,199,183,166,151, 91, 7,117,147, 34, 6,
+154,197,154,204,198, 45, 68,220,158, 54,191, 1, 88,143,222,221,194,153,111,129,170, 35, 34,187,109, 65,180, 11,255, 0, 17,147,
+ 58, 72, 32, 54,225,195,211, 34,189,191,157,126, 66,189, 5,224,219,142,237, 31, 80,225,255, 0, 25,232, 55, 74,239, 0,202,244,
+250,190, 45, 63, 23, 83,167,175,159,133,234,161,199,237,223, 80,117, 29,183,212,122,213,213,121, 49,181,250,254,153,209,127,138,
+254,163,167,123,126,118,159,101, 1,198, 75,222,123,228, 48,239,147,164,171, 50, 99,237,249,121,216, 82,180, 40,145, 9, 49,178,
+ 27, 28, 8,148, 57,145,163,240, 61, 80, 9, 96,109,194,143, 62,227,189,228,110, 56, 56,179,110, 95,247, 62,228, 56, 45, 34, 70,
+169,213,132,237,199, 44, 43,170,155, 16, 11,178,219,220,121,138,223, 76,110,200, 86,203,208,219, 54,162,179,156,239,222,225,147,
+163, 80,245, 61,111,139,229,213,110,165,248, 95,157, 93,201,199,237,219, 63,172, 59,109,189, 98,117, 58,178, 99,127,223,244, 39,
+ 79, 86,166,254,223, 70,157, 63,157,107, 80, 28,206,247,185,239,120, 93,223, 60, 56, 25,166, 56,178,113,182,172,116, 70, 64,233,
+ 7,170,205,158, 6,148, 41, 54, 47,240,216, 19,204,176, 7,144, 21,177,139,188,111,115,118,142,126,106,201,142, 55, 60, 73,179,
+ 48,224,202,156,172, 48,202,248,249, 50, 98,199, 39,196, 66, 13,122, 7,142,157, 94,202,185,186, 99,118,217,200, 97,188,157,183,
+213, 28,114, 27,213, 75,140, 37,244,218,197,255, 0,180,109, 93, 61,118,246,106,246,213,197,143,105, 93,144,171, 12, 22,216,122,
+ 36, 92,201, 7,164,232,123,245,116,244,126, 10,128,224, 50, 59,211,186, 22, 35,143,136, 30,124,140, 56,242,231,200, 89,163,197,
+129,193,199,146, 40,214, 28,214,154,120,162, 85, 94,161,212,208, 22,230,164,120,214,230, 23,112,111,217, 61,222,251,127, 76,141,
+172,102,207,128, 89,253, 58,160, 16,226, 12,144,201,121,125, 67,202, 95,152,233,233,208,125,151,173, 95, 79,216, 99, 23,111,234,
+ 29,159,211,164,175,252, 59, 84,184,157, 62,182,165, 18,116,126, 43, 51,235,211,170,220,117, 90,252,107, 70, 56,123,112,111,238,
+241,157,191,252,193,162,210, 0,240, 28,205, 1, 87,230, 23,234, 91, 70,159,162,222, 22,160, 56, 62,238,125,205,123,181,160,131,
+113,146, 40, 88,108, 61, 56, 64,248, 81,165,220,228,137,154,193,133,254, 79,139,244,129,177,224, 41,241,247,237,226, 85,138,113,
+ 38, 43,238,107,182,239, 9, 22, 94, 78,152,149,165,197,220,225,193,135, 81, 37, 99, 93, 98,220, 57, 22,183,133,119, 91,140, 93,
+179,252, 79, 31,248,169,219,191,139, 90, 63, 73,234, 91, 31,212,219,172,189, 46,151, 80,235,183, 95, 78,155,126,125,173,198,135,
+ 36, 93,165,208,113, 33,218,250, 6, 28,174,166,167,198,209,208,235, 15, 91,170,230,218, 58,246,234,248,107,249,184,208, 28,240,
+238, 29,202, 30,199,222,247,142,161,109,199,108, 25, 33, 6, 68, 43, 28,177,188, 43,169, 99,200, 72,201,136,176,191, 19, 25,210,
+ 69,168, 9,188,247, 12,217,178,108,158,189, 34,151,248,182, 70, 23,241, 35, 2, 92, 67, 14, 2,110, 10,130, 51,240, 92,187,145,
+115,249,163,207,141,117, 56,208,118,210,236, 82,174, 57,219,191,128, 5,144,100,105,124,115,137,166,231,171,213, 58,140,124,239,
+171, 87,211, 80,220, 96,237, 86,197,203, 27,161,219,125, 55,169, 30,183,175, 38, 56, 79, 85,211, 91,117,139,181,186,189, 45, 63,
+ 55,197,166,222, 20, 7,158, 13,243,118,206,220,246,205,207, 42, 65,163, 63, 19,183,103,124, 6, 67,210, 71,202,207,120,222, 72,
+197,248, 30, 5,129,246,143, 33, 87,229,238,174,224, 76, 72,179, 35,203,138,105, 55, 60,135,131, 31,110,137, 34,245, 56,234,185,
+254,136, 24,122,205, 28,111,240,124, 36,202,214,234, 17,225,194,187, 44,168,123, 91,214,226,122,211,182,122,253, 17,122, 14,179,
+227,117,186,125, 85,232,244, 53,182,173, 61,109, 58, 52,254,117,173,198,171, 62, 47,100, 22,221, 58,141,180,235,114, 63,140, 94,
+ 92, 91,223,169, 97,234,126, 47,132,245,127, 75,243,253,181, 65, 82, 13,251,113, 94,201,159,121,206,120,177, 51,225, 76,128,210,
+ 50,172,234,166, 25,158, 4,118, 76, 87,116, 46, 66,130, 85, 94,193,184, 86, 10,238,219,230,227, 38,204, 39,202,147, 26, 76,126,
+225,147, 2, 96,201, 18,201, 36,107,137, 52,202,179,136, 29,162,184,226,164, 41,183, 35,204, 87,113,233,246, 19,177,145,171, 7,
+248, 15, 68,131,105, 32,244,125, 11,113,227,171,167,162,223, 69, 81,139, 31,179, 23, 21, 68, 71,104,244,131, 38, 32,182,147, 16,
+199,234,244,142,143, 29, 86,235,105,182,159,206,183, 42, 3, 47,119,222, 55,156,126,229,139, 6, 28,164,131,111,149,160,198, 71,
+ 72,227,157, 86,105,132,132,166, 80,213,214,142, 70,248, 76, 92, 52, 31,206,174, 95,182,187,155,123,135, 23,183,113,206, 99,102,
+ 71, 34,109,209,101,134,141, 78,145,155,212, 31,191,154, 71,234, 52,159, 15,193,160, 31,148,235,231, 94,139, 54, 63,109,127, 27,
+133,178, 91,110,254, 58, 0, 16,117, 36,199,245,118, 33,180,232, 12,221, 78, 90,173,111, 11,251,107, 51, 27, 27,238,251,175, 27,
+ 99, 54,199,215,186,136,186,114, 97,106,213,214, 58, 52,133,110,125,107,218,223,157,127, 26, 3,154,201,220,251,131, 47, 31,101,
+221,100,220,186,107, 46,247,151,140,152,241, 68, 21, 68,120,171,184, 70,170,237,170,239,168, 65,196, 30, 28,143, 49, 83,131,187,
+247,188,156, 76,118, 19, 69, 20,179,227,246,227,153,122, 96,132,125,218, 87,139, 37,180,147,110, 64, 21, 30, 21,218, 79, 7,109,
+122, 24,125, 65,219,125, 7,170, 62,155,168,248,221, 31, 89,213,123,244,245, 54,158,183, 87, 95, 47,139, 85,252,107, 21,246,206,
+195,202,193,120,241,114, 54,168, 48, 99,159, 14,124,150,196,159, 13, 81,140, 83, 25,113,163,156,130, 84,163,184,101, 10,121,241,
+ 11, 64,105,118,222,233, 62,229,183, 48,205,149,100,202,135, 39, 51, 23,168,160, 47, 89, 49, 50,100,198, 19, 4, 30, 97, 69,237,
+194,245,197,205,222, 59,254, 46, 14,102,119, 94, 57,153,241, 55,153,224,143,164, 0,129,246,204,181,198,136,181,141,216, 58,191,
+197,127, 27, 90,187,172, 12, 29,131,175,131, 54,211, 38, 29,227,197,154, 44, 24,241,102,131, 73,198,105, 98, 51, 52, 98, 54,248,
+148, 72,137,114, 56, 3,237, 53,153,181,237,125,149,131, 14,225, 12,121, 27,110, 73, 35, 33,247, 57,102,159, 18, 71,233, 73, 60,
+147, 76,185, 36, 17,251,180,145,202,252, 67,133,128, 60,170, 48,140,204,157,247,185, 48,251,130, 29,168, 55,170,131, 26, 76, 8,
+242,231, 43,143, 12, 76, 51,165,145, 93,155,169, 50,202, 10,160,180, 75, 26,181,202,157, 87,189, 81,126,228,238,102,124,172, 81,
+147, 19,100,202,234,248,177, 70, 49,200,150, 3,146, 99,213,182, 76,100,233, 74,221, 33,109, 19, 29, 90,239,225, 93,190, 94, 63,
+111,157,235, 17,179,206,223,252, 96, 45,176,186,210, 99,250,157, 36,181,186, 65,219, 95, 61, 86,183,183,219, 89,210, 98,118, 25,
+143, 48,106,217,180, 60,168,119, 15,222,226, 11, 62,182,211,213, 58,248, 55, 82,246,191,231, 95,198,244, 69, 50,115,119, 9, 55,
+ 62,215,217,230,200,200,234, 71,159,155,135,143,155, 42, 43, 99,234,137,178,132, 79, 27,173,238,154,180,132,112, 13,184,144, 56,
+ 85,109,199,105,216,213,240, 49,176, 30, 89, 82, 61,233,112,242, 35,103,149, 86, 32,241, 60,239,137, 29,180, 3, 24, 44, 24, 90,
+246, 60, 47,194,195,175,124,125,136,236,214,156,224,127, 1, 48,168, 23,147, 28, 97,244,127, 54,223, 23, 79, 69,237,111, 10,124,
+ 12,110,218, 76, 28, 68,219,219,110, 56, 34,123, 97, 24,100,199, 49,122,159,139,251, 18,173,110,175,205,203,226,231, 64,121,190,
+233,234,113,247, 29,211, 34, 52,120,224,131,120, 24,139,184,166, 67,235,141, 14,223, 14,156, 95, 79,193, 76,110,205, 98,218,184,
+106,189,171,175,151,126,159, 99,236, 44,109,210, 24, 36,202,201,139,106, 19,161,208,100, 65, 36,120,194, 64,211,217,149,130,106,
+ 28, 77,235,107, 38, 14,222, 49, 79,234,142,223,210,245, 43,234,186,143,143,167,214,104, 77, 29, 93, 77,110,182,141, 22,191,197,
+107,123, 42,134,217,143,216,222,147,113,254, 6,219, 41,193,233,255, 0,245, 99,135, 38, 31, 75,165,165,255, 0,239, 93, 38,211,
+163, 78,191,159,133,175,237,160, 50,247, 77,202, 76,157,241,101,209, 62, 36, 71, 99,220,219,163, 56, 49,157,113,203,137,103,211,
+114, 46, 3, 27, 26,165,186,101,110, 56,219, 31,101,100,227,228, 58, 55, 82, 14,188, 64, 92,204, 70,223, 60,186, 28,243, 55, 41,
+107,121,155,243, 2,186,173,255, 0, 23,183, 26, 56, 7,115, 54,221,211, 12,199, 27,248,132,184,224, 92, 15,143, 71, 93,188,190,
+107,120,115,163,238,120,251, 79,167,199,254, 42,112,189, 63, 90, 63, 75,234,164,131, 71, 95,251,158,151, 85,173,175,244,109,199,
+202,128,231,251, 75,123,221,115,103,108,125,207, 33, 51, 4,187,118, 14,230,147, 71, 24,140, 70,217,157, 96,240,124, 36,130,163,
+164, 10,147,198,222,117,133,145,222,123,212,120, 25, 57, 40,209,117, 98,219,247,172,181,186,112,234, 96,103,174, 36, 28, 47,203,
+166,120,249,154,237,182,124, 77,140, 46, 71,240, 22,192,210,100,190, 79,162,151, 28,142,161, 31,222,116,155,157,188,235, 35, 55,
+106,236,204,216,119,124, 49,147,182, 99, 79,145, 14, 66,110,121, 24,217, 24,105,145, 28,108,202, 50, 90, 71,212, 74,217,244,235,
+212, 45,170,215,227, 84,134,100,251,206,246,185,217, 29,191,235, 99, 13, 30,108,208, 54,228, 34, 95,142, 36,219, 70,226, 35, 9,
+125, 32,235,123, 18, 13,244,143, 62, 53, 87,105,238, 61,214, 8, 59, 95, 22, 41,186,208, 62, 46,205, 22,100,102, 53, 32,122,216,
+136,102,158,105, 28, 72,210, 54,157, 73,211, 4,112, 58,185,215, 88,184,221,151,252, 40,137,142,209,252, 47,212,150,227, 46, 47,
+167,245, 86, 44,120,234,209,212,181,248,115,183, 14, 84, 70,199,236,143, 81,138,204,118,127, 81,209,198, 24, 55,147, 19, 87, 67,
+ 80,244,157, 17,171,228,213,110,150,158, 31,163, 64,112,112,247, 39,116,109,139,155,141,135, 43,103, 60, 25, 27,190, 83, 51,250,
+116, 91, 99,103,122,117,142, 87,202,154, 45, 16,241, 55,209,118, 23, 80, 56, 14, 61,143,123,247, 6,119,109, 98,227,110, 48,105,
+ 56,173,234, 97,153, 10,234, 99, 57,198,146, 92, 75,123,229,136, 39,245,133, 90,200,199,236, 67,147,254, 44,236,222,169,114,152,
+183, 82, 76, 65, 39,171,248, 3,234,187, 92,203,242, 94,252,126, 95,101, 89,238, 77,171, 7, 62, 12, 63,226,217,177,226,225, 99,
+229, 67, 51, 35,203, 2, 71, 52,168,225,160,141,222, 83,227, 32, 28, 20,141, 92,168, 14, 86, 30,224,238, 56,115,163,245, 83,199,
+ 34,140,231,218,101,194, 88,128, 33,162,219,142,105,202,214, 62, 46, 50, 45,237,242,233, 35,223, 66,199,239, 13,255, 0, 39, 11,
+ 31,165, 44, 49,228,100, 99,246,219, 9, 12, 65,130,201,187,202,241,100,182,157, 66,226,192,105, 23,225, 93,154,227,236, 31,198,
+217,181, 96,127, 28,233,217,255, 0,121, 7,170,233,216,115, 26,186,154,116,219,232,170,251,100, 61,138,177, 48,218, 78,206, 99,
+234, 99, 22,244,207,136, 71, 84,200,222,142,250, 27,230,234,223,165,252,239,150,128,109,251,117,207,218,103,216,176,163,149,100,
+ 57,143, 60, 89,146,186, 0, 95,163,133, 62, 64, 96, 7, 5,188,145, 2,109,238,174, 78, 30,239,223,180,236,251,132,243, 70,113,
+114,176,176,101,149, 33, 68,145, 14, 78, 70, 59, 79, 44, 57, 1, 91,173, 11,191,195,209, 33,116,121,215,117,189,193,177, 60, 17,
+127,153, 27, 4, 99,245, 84,195,235,222, 16,157, 96,173,167, 71, 89,173,171, 78,175,162,245, 78, 28,126,205,254, 33,130,216,237,
+181,127, 16, 16,198, 54,222,156,152,189, 94,129, 67,209,244,225, 91, 86,142,157,244,105,252,219,219,133,101,186,190, 5, 71, 35,
+129,221,125,213, 62,216, 30, 98,144, 79,147, 54,204, 49,167,153,113,216,133,221, 38,233, 75,104,113,103,147,247,106, 44, 99, 50,
+ 16,198,252,121, 87, 81,220,185,155,158, 26,237, 27,102, 54, 98,195, 38,111, 93,114,179, 90, 53, 37,134, 62, 36,147,144,169,193,
+ 87,168,201,115,110, 66,246,243,171, 59,116, 29,152,184,204, 54,179,181,122, 99,147, 9,111, 78,248,198, 63, 86, 93, 78, 63,200,
+214,234,235,211,211,241,189,180,213,253,246, 29,141,176,208,119, 25,194,244,125, 85, 49,250,247,132, 71,213, 1,138,233,235, 29,
+ 58,180,234,250, 47,225, 79, 96, 60,247,100,238,205,250, 40,251,119, 15, 30, 51, 46, 36, 88, 59, 26,101,201, 33,128, 35,250,228,
+209, 44,146,201, 60,201, 49,112, 5,227, 17,163, 93,129,191, 58,206,131,185, 55,157,130, 13,198, 76,108,207, 83,145,235,247, 44,
+172,148,232, 33, 46,176,103,140, 64,211,201, 35,174,152,180,252, 33, 99,248,193, 32, 15,132, 87,124,248,253,166,217,155, 99, 33,
+218,253, 88,134, 49,179,218, 76, 81, 39,167, 32,244,189, 40,213,125, 22,190,141, 28, 45,123, 80, 51, 49,187, 32,176, 59,147,108,
+250,131,100,219,175, 46, 39,205,175,252,101,195,183, 19,212,254,215,249,223, 55, 26,190,192, 80,159,187,247, 22,221,102,219,137,
+ 65, 1,221,114,240, 56, 45,155,161, 22,210, 51,146,198,255, 0, 55, 88,243,242,225, 92,214,221,189,119, 6, 56,219,159, 3, 61,
+157,229,237,237,136,140, 87, 49,153, 24,200,211, 9,206, 55,169,101,141,242, 10,198,196,106,249,185, 30, 66,187,191, 77,218, 63,
+197,201, 45,181,127, 25, 60,239, 38, 47,170,225, 9,240,213,175,251, 11,255, 0, 83,217, 64,205,198,236,102,143, 25,115,219,102,
+208,113, 99, 24, 93, 89, 49, 7,248, 77, 75,210,232, 22,111,236,181,105,211,167,225,189,173, 83,216, 13, 46,218,223,151,115,217,
+241,114,102,153, 50, 50, 89, 47, 51, 42, 24,143,204,200, 11,196, 73, 40,126, 2, 15,133,193,183, 10,215,245,177,249, 86, 70,217,
+143,177,220,255, 0, 6,108, 27,244, 97,191,164,146, 15,251,191,199,233,255, 0,178,111,236,254,125, 30, 28,237,227, 90, 62,156,
+254,146,127,237, 19,253,106, 83,192, 84, 55,173,143,202,151,173,139,202,129,233,207,233, 39,254,209, 63,214,165,233,207,233, 39,
+254,209, 63,214,165, 5, 75, 30,182, 63,209,165,235, 35,242,160,116, 15,233, 39,235,167,250,213, 33, 7,243,147,245,211,237,165,
+ 60, 1,107,212, 39, 79, 85,191,187,191,209,212,211, 74,135,160,105,233,220, 95,163,206,227, 79,246,191,165,202,149, 1,255,217,
+};
+#endif
diff --git a/source/blender/src/pub/windows_publisher_splash.jpg.c b/source/blender/src/pub/windows_publisher_splash.jpg.c
new file mode 100644
index 00000000000..520c58bc9f2
--- /dev/null
+++ b/source/blender/src/pub/windows_publisher_splash.jpg.c
@@ -0,0 +1,1002 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+/* DataToC output of file <splash_jpg> */
+#ifdef _WIN32
+
+int datatoc_tonize= 30796;
+char datatoc_ton[]= {
+255,216,255,224, 0, 16, 74, 70, 73, 70, 0, 1,
+ 2, 0, 0,100, 0,100, 0, 0,255,236, 0, 17, 68,117, 99,107,121, 0, 1, 0, 4, 0, 0, 0, 50, 0, 0,255,238, 0, 14, 65,
+100,111, 98,101, 0,100,192, 0, 0, 0, 1,255,219, 0,132, 0, 8, 6, 6, 6, 6, 6, 8, 6, 6, 8, 12, 8, 7, 8, 12, 14,
+ 10, 8, 8, 10, 14, 16, 13, 13, 14, 13, 13, 16, 17, 12, 14, 13, 13, 14, 12, 17, 15, 18, 19, 20, 19, 18, 15, 24, 24, 26, 26, 24,
+ 24, 35, 34, 34, 34, 35, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 1, 9, 8, 8, 9, 10, 9, 11, 9, 9, 11, 14, 11, 13, 11, 14,
+ 17, 14, 14, 14, 14, 17, 19, 13, 13, 14, 13, 13, 19, 24, 17, 15, 15, 15, 15, 17, 24, 22, 23, 20, 20, 20, 23, 22, 26, 26, 24, 24,
+ 26, 26, 33, 33, 32, 33, 33, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,255,192, 0, 17, 8, 1, 15, 1,244, 3, 1, 34, 0, 2, 17,
+ 1, 3, 17, 1,255,196, 0,196, 0, 0, 1, 5, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 2, 4, 5, 6, 0,
+ 7, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 16, 0, 2, 1, 3,
+ 2, 4, 2, 5, 7, 7, 8, 6, 7, 5, 6, 7, 1, 2, 3, 0, 17, 4, 18, 5, 33, 49, 19, 6, 65, 20, 81, 97,113, 34, 50,129,
+145,209, 66, 35, 21, 7,161,193,225, 82,146,178, 51,177, 98,114,130, 67,115, 36, 22,240,210, 83, 99,131, 54,162,179,195,211, 52,
+ 84,116,147,163,196, 37, 23,241,194,226, 68,100, 53,132,148,164, 69,133, 38, 71, 17, 0, 2, 2, 1, 2, 4, 4, 3, 5, 7, 4,
+ 3, 0, 0, 0, 0, 0, 1, 17, 2, 3, 33, 4, 49, 65, 81, 18, 97,113, 19, 5,129,145, 34,161,177,193,209, 50,240,225, 66, 82,
+ 98,146, 20,114, 35, 51, 21,241,147, 52,255,218, 0, 12, 3, 1, 0, 2, 17, 3, 17, 0, 63, 0,244,254,224,238, 9, 59,127,111,
+143, 51, 67,204,154, 98, 78,154,190,139, 94, 48,111,227, 84,189,187,248,157,181,111,121,203,182, 74,211, 97,102,202,116,192,147,
+ 54,164,144,254,170, 72,167,226,245, 16, 42,195,187, 50, 59,119, 27,111,129,187,154, 24,230,194, 99, 18,162, 76,130, 69,234,116,
+174, 13,155,135, 32,107,198, 59,154, 93,139,117,238, 13,167, 19,177, 96, 16,100, 52,145,170, 24, 87, 66, 9,117,130,140, 20,114,
+211,109, 71,217,122, 3,232,137, 38,156, 48,180,141,107,126,177,166, 28,153,129,254, 35,254,209,174,146,247, 30,155, 80,154,246,
+185,161, 3,121,137,173,113, 35,126,209,166, 25,242, 9,183, 85,199,245,143,211, 76, 91,218,246,227, 78, 3,244,208, 4, 19, 79,
+200,202,255, 0,180,126,154, 78,164,222, 19, 73,251, 70,147,133,119, 1, 64, 41,151, 35,152,149,255, 0,104,211,124,198, 77,175,
+213,111,218, 53,220,111,127, 10,105,225,236,160, 7,145,149,148,161, 71, 85,214,230,247, 12,104, 77,153,149,107, 9,228,191,244,
+219,233,166,101,177, 50, 42,223,128, 23, 31, 41,253, 20, 11,240,189, 70, 80,227, 47, 44,243,200,147,246,219,233,167,121,188,171,
+127, 30, 79,219,111,166,128,183, 34,194,151, 79,166,128,120,204,204, 60,167,147,246,219,233,167, 12,172,195,195,204, 73,251,109,
+244,208,208, 0,107,181, 11,147, 64, 72, 25, 57, 64, 15,183,147,246,219,233,174,108,188,145,253,188,159,180,126,154,142, 90,246,
+181,112,227,196,208, 18, 35,205,159, 81,213, 59,143, 69,216,253, 52, 81,149, 59,114,157,173,233,214,126,154, 28, 43,238, 18, 64,
+ 34,231,232,174,233,196, 73, 58, 7, 14,103,133, 64, 20,229,100, 40, 7,168,228,122,117, 31,166,156, 50,167,241,149,253, 94,241,
+250,106, 40, 68, 38,195, 81, 83,114, 45,123, 11,123, 41, 86, 38, 23, 1,143,203,232,160, 36, 12,156,130, 47,214,126, 62, 26,143,
+211, 93,230, 50,120,253,171,254,209,250,106, 54,151, 22, 42,192,129,234,167, 19, 34, 47,188,160,251, 15, 30, 63, 37, 0,127, 49,
+ 61,191,140,255, 0,180,126,154, 11,228,228, 37,137,158, 79,219, 99,249,233,133,207, 61, 36,122,233,132,135,176, 2,214,231,194,
+168, 10,115, 50, 45,168, 78,224, 90,228,234,111,166,163, 54,118, 99,177, 34,121, 64,240, 1,219,233,164,200, 4, 21, 31, 84,211,
+ 81,108, 11, 55, 1,206,254,129, 84, 6,243,153,104,183,108,137, 15,160,107,110, 39,231,166,249,220,213,248,178, 36, 36,241, 62,
+251, 88,126, 90, 1,144, 22, 4,242,228,130,154,225,152,220, 27, 15, 77, 0, 99,153,154, 13,206, 84,160,122, 3,183,211, 78, 25,
+217,108, 46,185, 18,254,219,125, 53, 28,105, 34,199,222,181, 32, 38,246, 2,194,128, 56,204,206,191,189,147, 32,254,187,125, 52,
+158,127, 49, 28, 95, 38, 82, 15,134,182,250,104, 18, 0, 56,147, 78,134, 61,103, 83,142, 20, 4,207, 63,148,120, 9,228, 55,254,
+123,125, 52, 63, 53,158,183, 45,145, 47, 30, 67,168,223, 77,112, 0, 27,129, 72,195, 81,246, 80, 13,108,220,255, 0, 9,229,253,
+182,250,105, 70, 86,224,194,254, 98, 85,254,187,125, 53,192, 0,220,254, 74,105,148, 51,149, 81,192, 80, 5, 89,243, 56, 95, 38,
+ 99,255, 0, 17,128,254, 90,123,103,100, 71,192,228, 73,127,233,183,211, 80,220,189,248,181,133, 35,105,248,173,115, 64, 73,108,
+236,203,123,179,200,111,252,246,250,105,135, 63, 48, 45,142, 68,154,189, 78,223, 77, 7, 81, 43,199,129, 52,208,128, 27,243, 52,
+ 1,151, 51, 56,113, 57, 50,252,178, 55,211, 69,251,195, 44, 11,117,228, 39,210, 93,190,154,141, 93,106,146, 88, 13,231,179, 79,
+255, 0,152,151,246,219,233,174,243,185,191,249,153,127,109,190,154, 13,253, 20,156,104, 9, 30,119, 51,255, 0, 51, 47,237,183,
+211, 93,231,115,127,243, 18,254,219,125, 52, 21,141,155,225, 82,109,206,194,137,229,220,124, 86, 95, 89, 35,243, 80,163,188,230,
+111,254,102, 95,219,111,166,151,206,102,127,230, 37,253,182,250,105, 4, 81,142,108, 91,211, 97,249,205, 56, 34,168,184, 78, 63,
+206, 52,130, 74, 59,206,102,255, 0,230, 37,253,182,250,105,235, 62,224,198,194,105,126, 87, 97,252,166,144, 22,191,186,109,202,
+250, 69,169,194, 61, 94, 36,250,111, 65, 35,196,217, 96,217,242,220,122, 64,118, 39,249,104,131, 38, 64, 1,235,206,231,159,198,
+ 64, 63,203, 65, 17,251,197, 72,245,222,140, 34,186,240,229,200,250,232, 7,121,236,149, 33, 81,216, 92,253,102,102,253,227, 72,
+217, 25,108,120,205, 32,246, 49, 3,135,178,185,186, 8,190,251, 45,239,233,166, 75,149,140,138,160, 18, 64, 30, 3,157, 8, 56,
+100,100,145,113, 60,156,191, 89,185,252,244,238,182,101,237,213,146,220, 46,117, 55,211, 80,159,115, 65,194, 56,190, 82,105,158,
+126, 99,198,194,222,138,165, 44,203,229, 90,226,121, 7,245,207,211, 72,114,164,140,141, 89, 45,242,185, 63,158,169,100,154,103,
+182,167, 38,254,186, 72,161,103,112, 61, 52, 16, 93,156,225, 99,108,153, 15,139, 16, 88,216,126,106, 99,110,202,163,132,210, 49,
+181,175,114, 63, 61, 87,121,115,203,199,198,135, 44, 36, 88, 1,206,128,184,251,193,122, 61, 93, 79,171,161,171, 93,205,237,215,
+209,207,157,117, 66,209,254, 22,223,254,150,223,255, 0, 85, 93, 80,106, 86,247,175,107,127,155,118,204,125,187,205,156, 62,147,
+ 69, 63, 80, 71,212,189,162, 41,166,218,147,245,189, 52,189,175,216,219, 15,107,162, 75,133,142, 36,220, 58,106,147,103, 73,169,
+164, 98, 5,156,160,118,110,152, 99,196,133,173, 19,113, 49,255, 0, 66, 63,220, 90, 40,225, 84,128,100, 82, 8,227,225, 76, 55,
+ 62, 23,181, 18, 98, 53, 15,101, 12, 53, 8, 40, 39,149, 34,179, 92,223,149, 40, 34,184,219,149,232, 7, 3, 92, 77, 39, 0, 56,
+215, 92, 80, 10, 24, 48, 32,120, 83, 26,220,169,111,111, 10,105, 6,244, 4, 25,134,169,152, 3,234,249,133, 32, 81,122,226,215,
+114,222,158, 52,151, 63, 61, 66,132,184, 6,152, 88,154,225,206,148,248, 80, 28, 1,174, 35,133,118,175, 10, 67,114,104, 14, 98,
+168, 9, 60, 0, 28,106,150, 77,246, 93,127, 99, 26,232, 28,181, 92,147,243, 17, 87,122, 1, 6,252,106,143, 63,104,104,245, 79,
+138, 53, 39, 54,143,196,123, 61, 85,243,253,201,238,150, 58,219,108,218, 85,151,120,253, 94, 31, 3,221,176, 91,103,119, 93,194,
+151,104, 85,159,210, 93,109,155,174, 46, 84, 98, 51,238, 76, 46, 89, 15, 27,255, 0, 70,213, 44, 73, 25,185,184, 7,215,194,176,
+170,204,140, 25, 73, 86, 28, 65, 28, 8, 53,125,129,188,137, 10,195,150, 64,123,105, 89,121, 3,253, 47, 93,112,217,123,165,114,
+ 70, 61,195, 85,183, 5,110, 21,183,159, 70,118,222,123,107,164,228,193, 54,175, 58,243,175,151, 84, 93, 35, 92, 13, 46, 0, 38,
+231,143,135,170,140,173,199,153,229, 65, 17,234,176,224, 69,189,211, 77, 10, 44, 15, 1, 99,110, 28, 56, 31,101,125, 99,229,135,
+247, 73,224,120,158, 52,146,125, 95, 2, 15, 31,146,185, 99, 28,195, 21, 83,196,241,189,190, 74, 99, 33,189,217,201,245,144, 60,
+104, 7, 49, 7,143, 42, 66, 1,185, 28,169,132, 75,126, 96,252,148,229,224, 46,220,207, 58,168, 2,153, 75, 21,191, 27, 27, 90,
+163,201, 32,115,167,234, 41,226,125, 38,151, 34,109,108, 85,121, 14, 23,160, 51, 1,109, 34,168, 30,250,143,194, 41, 7, 17, 98,
+222,218, 64,206,203,107, 87, 44, 71,153, 63, 53, 0,154,213, 77,148,123,105, 88, 51,252, 34,194,156, 20, 47, 31,229,165,214,164,
+216,113, 52, 3, 58, 55, 23, 38,244, 68, 54,249, 41,154,158,252,120, 10, 70, 11,241, 31,154,128, 61,238, 41, 7, 62, 60, 40, 87,
+ 37,120, 2, 13, 42,181,151,143, 58, 1,236,234, 27, 72,226, 79, 51, 67, 36,131, 97,238,138,226, 73, 62,138,224,140,220,129, 52,
+146,192,140, 67,120, 94,151,141, 21, 96, 99,241, 50,175,180,253, 23,167,172, 49, 11,106,102,107,248, 40,183,229, 53, 1, 30,187,
+137,224, 56,212,144,138, 62, 20, 6,222, 44,111,244, 10, 80, 24,240, 83,111, 18, 0,181, 4,128, 17, 72,124, 45,237,225,252,180,
+229,133,126,179,129,236,226,104,193, 47,225,198,246, 36,209, 4, 64, 3,126, 22,170, 36, 10, 71, 16,250,172,199,214,108, 15,231,
+162, 11, 33, 26, 35, 85,177,185,184,212, 71,202,215,167, 3, 10,129,173,197,253,102,154,217,152,177,139, 11,177,240,176,168, 7,
+ 48,145,189,230, 36,173, 51,167,232, 28,249, 94,154,119, 0,192, 4,143,128,244,154,143, 46,108,231,128,178,251, 5, 82, 19, 68,
+ 36,142, 63, 45,115,244,144, 93,220,122,238,106,188, 60,210, 11,150, 39,229,166, 52,108, 90,199,194,133,130,120,200,199, 64,108,
+111,236, 20,199,220, 2,216, 36,127, 61, 6, 40,125,205, 84,178, 65,166,205,225,202,128, 79, 57, 59, 92,139, 47,178,135, 36,179,
+191,196,228,252,180,240,129, 22,231,199,141, 72,138, 37,156, 5, 91, 15, 18,106, 26,141, 8, 73, 27, 22, 30,186,147,229,143,207,
+198,164,152, 70, 61,217,200, 60, 56, 90,163, 12,171,191, 46, 28,133, 83, 36,115, 29,184, 91,141, 28, 71,165, 64, 53, 32,105,190,
+178, 61,227,196, 26,137, 49,102,114,163,144,168,105,105,168, 97, 7, 82,197,124, 42, 66, 66,208, 27,183, 6,240, 30,170, 14, 27,
+ 16,116,183,133, 74,157,137,141,152, 11, 26, 17,185,114, 71,121,225, 67,164, 53,143,170,154,230, 55, 0, 6,189,254,181, 69,100,
+ 0, 95,196,211,161, 4, 95,209, 70, 43,199, 82,195,165,254, 23,226, 22,242,214,241,255, 0,204,222,186,159, 97,229,180,248,121,
+127,254, 34,186,161,189, 62,210, 72,248,163,191,132,113,254,226,209, 46, 41, 17,111,164,255, 0,187,143,247, 22,158, 98, 7,194,
+180,114, 35,205,109, 67,217, 64, 53, 34,104,174,223, 37, 4,196,109, 66, 13, 6,151, 87,141, 33,132,143, 19, 78, 17,112,231, 64,
+ 37,252,111, 93,171,198,148, 66, 71,141,113, 70,183, 10, 1, 46,105, 93,136, 70, 32,241, 0,145,243, 82, 89,135,133, 10,107,244,
+200,244,218,212, 4,113,192, 82, 18, 47,236,174,211,233,165, 2,161, 68,227, 80, 39,221,241, 34,125, 3, 84,164,115, 43,107,124,
+230,167,202,186,209,144, 27, 22, 5, 65,244, 92, 86,101,246,236,200,216,169,136,155,120,175, 17, 95, 63,220, 55, 27,156, 74,139,
+111, 70,251,166,108,151,116,120, 30,237,142, 13,190, 87,111, 94,241, 17, 21,158,217,241, 44,198,251,142, 63,178,127,201, 75,247,
+238, 63,251, 39,252,149, 83,228, 51, 63,216, 63,205, 92,112,114,192, 36,194,192, 14, 36,145,202,190,103,249,254,227,252,175,255,
+ 0, 95,238, 62,135,248, 91, 15,230, 95,223,251,203,127,191,160,183,240,159,242, 82, 13,254, 17,253,147,254, 74,161,174,174,127,
+246,219,191,230, 95,218,142,159,245,155, 95,229,127,220,201,153,179,226,100, 30,164, 17, 52, 82,125,110, 90, 79,175,219, 80,234,
+ 70, 62, 14,102, 87,254, 27, 30, 73, 71,165, 20,145,243,138, 59,236,187,180,107,169,240,166, 3,210, 16,159,228,175, 45,214, 92,
+173,229,244,222,186,183, 90,197,126,195,211, 71,139, 18, 88,251,214,156, 21,173, 47,237, 11,182,239, 50,225,145, 20,215,146, 14,
+ 67,245,151,217, 90, 40,178,160,153, 82, 72,220, 50, 30, 55,172, 83, 43, 41, 42,192,171, 14, 4, 30, 4, 84,140, 44,233,240,100,
+215, 17,186,159,138, 51,240,154,246,236,189,206,248, 99, 30,105,181, 56, 79,241, 87,243, 71,143,121,237,212,203, 57, 49, 69,111,
+198, 63,134,223,188,218,222, 51,240,181,239, 77, 22,191, 19,236, 30, 20, 12, 44,204,109,198, 46,164, 99,223, 31, 28,102,215, 83,
+ 71, 72,162,109, 94,237,171,244, 52,189,111, 85,122, 53,106,189, 83, 71,194,189, 45, 75, 58, 93, 58,181,197, 49,108, 71, 16,106,
+ 28,242,158, 49,169,254,145,170,205,195,187,123,123,106,221, 27,106,207,158, 76,121,144, 43,107,101, 99, 29,156,106, 28, 87, 87,
+229, 21, 35, 31, 51, 15, 61, 90,124, 28,132,200,132,177, 2, 72,216, 48,225,225,195,198,186,250,119, 73, 89,213,164,245, 78, 52,
+ 57, 87, 37, 44,221,107,100,218,226,167, 85,240, 8, 21, 79, 3,198,157,211, 69,227, 75, 98, 56,240, 2,152,196, 49,245, 14, 85,
+ 13,138,206,170, 61, 53,197,152,175,187,195,211, 65,154,104,160, 67, 52,238,177, 70,191, 20,142, 66,168,191, 14,102,163,199,186,
+237,178,184,138, 28,216, 36,145,205,149, 22, 84, 98, 79,160, 0,111, 85, 38,245, 73,145,180,156, 54,145, 44, 91,147, 53,205,119,
+ 16,108,171, 97,226,105, 0,241, 28,232,168,186,172, 88,123, 5, 66,140, 96, 26,220, 79,176, 83,214, 57, 72,176, 75,123,127, 77,
+ 29, 85,185, 14, 22,167,232, 60, 9, 54,160, 35,116, 79,214, 97,252,180,162, 52, 30,186, 43,152,150,228,176,181, 51,175, 8,229,
+118,160, 56, 40, 6,192,123, 40,129, 9, 31,203, 81,252,221,219,221, 90,108,153, 51,242, 83,167,217, 64, 76,142, 62, 23,229,195,
+228,165,251, 21,211,169,197,253,181, 92, 76,172, 13,216,154,116, 80,146,120,242,168, 86, 75,124,172,101, 39,155, 31, 0, 7,211,
+ 76, 57,163,154, 39, 31, 11,208, 36,134,196, 88, 94,252,169,147,205,139,133, 17,155, 50,100,134, 36,248,164,145,130,168,240,230,
+106,248, 32,185,183,162, 93, 66,121,188,137, 13,129,176,245, 10, 73, 76,196, 93,152,154,167,195,238,238,223,159,113,135,108,196,
+200, 57, 19,204, 74,171, 70,135, 64, 32, 22, 55,118,211,224, 60, 42,249,157, 36, 4, 3, 86,245,181, 99,190,174,178,167, 93, 12,
+210,244,188,246, 89, 90, 28,104,228,136,136, 73, 52,246,132,130, 47, 79,123, 70, 6,158, 38,137, 27,135, 23,101,191, 26,201,183,
+ 11, 65,177,196,170,156,124, 79, 10,233, 99, 37,184, 11,240,166,204,238,205, 96,108, 7, 27, 83,145,207, 79,143, 59,209,138,169,
+103, 92, 68,186, 79, 58, 50,162, 56,212, 77,189,149, 25,148,179,146,124, 40,209,157, 8, 56, 80, 55,200,100,178, 50, 16,171,200,
+114,246, 81, 34,145,157,110,124, 56, 90,155, 50,181,239,110,124,169, 99, 70, 81,107,123,104,203, 94,172,100,224,177, 0,112, 6,
+157,143,116, 44, 61, 95,158,142, 33,234,122,136,228, 77, 24, 66,136,160, 22, 5,173,198,136,150,114,192,207,115, 25, 3,143, 10,
+134, 19, 81, 0, 85,130,172, 99,131, 53,201,225, 77, 34, 20,224,139,207,198,132, 2,199,234,223,143, 42,227,142,230,238,162,224,
+250, 40,190, 60, 23,143, 58, 80,242,216,216,219,244,208, 54, 36,105,210, 83,126, 44,105,225,195, 45,136, 30,195, 76,210,215,247,
+141,174,109,122,238,152, 99,166,247,185,231, 86, 9, 32,155, 24, 18, 62,209,109,227,115,202,138, 32,141, 80, 1, 42,223,196,241,
+227, 92, 99, 65,194,231, 95, 38, 30, 30,170,120,129,116,139,145,195,137,168, 89, 15,165,124,189,186,131,255, 0, 15,107,216,242,
+235,243,174,174,176,242,247,208,109,229,237,255, 0,191,255, 0, 67, 93, 65, 36,232,192, 8,135,210,145,254,226,211,152,138, 96,
+224,137,127,246,105,251,162,148, 16, 69,234,153, 3, 41, 32,252,148, 59,222,151, 33,189,241,225,194,133,123, 80, 4,225, 74, 8,
+ 20, 16,192,248,211,239, 64, 59, 80, 62,170,234,101, 40, 32, 80, 11,227,114, 42, 62, 83, 13, 1, 71,166,255, 0, 53, 25,154,161,
+228,146, 93, 87,194,212, 97, 2, 4,218,194,184, 92,241,165, 28, 5, 40, 32, 10,133, 18,222, 52,150,187, 82,220,218,161,102,103,
+197,134, 52,223, 92,199,146, 15, 15,233, 87, 60,185,105,138,142,249, 44,171, 85,205,155,199,142,249, 44,169,142,174,205,242, 68,
+169,178, 33,197,143, 92,173, 97,224, 60, 79,168, 10,207,102,238, 50,229,146,163,220,138,252, 16,120,255, 0, 74,163,207,145, 46,
+ 75,245, 37,107,159, 1,224, 7,170,133, 95,157,222,251,149,243,205, 49,205, 49,244,231,111,245,126, 71,222,217,251,125, 48,197,
+239, 23,191,217, 95, 47,204,234,218,236, 61,169, 18,198,153,155,162,107,145,172,201,142,126, 21, 30, 26,253, 39,213, 84,125,175,
+132,153,187,188, 66, 65,120,225, 6,102, 30,157, 54,211,255, 0, 72,138,208,254, 32,119, 20,189,181,219, 89, 25,184,164, 12,185,
+153,113,241, 88,253, 87,146,254,255, 0,245, 85, 73, 30,186,245,123, 54,194,185,159,171,116,173,245,118,210,175,132,243,179, 60,
+222,237,190,120,106,241,213,186,197,123,174,215, 24,232,135,239,189,239,219, 29,174, 70, 54,110, 72,243, 10, 56, 98, 99,174,183,
+ 81,252,229, 94, 11,253, 98, 42,135, 31,241,151,180,166,147, 68,177,229,227,173,255, 0,137, 36, 74, 87,229,233,187,183,228,175,
+ 5,150, 89, 38,145,230,153,218, 73,100, 37,157,216,146,204,199,137, 36,158,100,211, 43,246,117,246,252, 74,177,102,219,234,180,
+249, 35,241,215,247, 44,206,211, 85, 84,186, 61,126,108,250,159,165,176,247, 86, 16,202,198,146, 60,168,159,132,121, 80,145,169,
+ 79,162,252,193, 31,170,213,133,221,246,153,246,140,163, 4,190,242, 55,189, 20,163,147, 47,210, 60,107,207,127, 15,251,159, 43,
+183, 55,252,107, 72,124,142,100,137, 6,100, 36,251,165, 92,233, 18, 91,245,144,155,223,228,175,123,238,156, 37,203,218, 37,123,
+125,166, 63,218,161,246,124, 67,246,107,243,254,247,237, 84, 85,181,234,190,164,157,149,150,142,201,113,173,143,208,123, 55,186,
+ 90,206,180,183,233,109, 86,213,226,170,223, 11, 84,243,236, 60,169, 48,231, 89,227, 60,190, 37,240, 97,226, 13,109, 49,178, 99,
+150, 37,153, 88,105,147,222, 4,240,172, 37,105,123,118,118,124,121, 32, 63,217, 48,101,246, 55,233, 21,241,253,159,112,235,149,
+224,111,233,186,109,120, 89,126,104,250,190,235,129, 91, 26,204,151,213, 70,147,241,171,252,153,229, 95,137, 68, 30,235,200, 42,
+ 65, 29, 40,120,143,232, 10,210,254, 31,102, 98, 96,246,220,211,229,204,144, 70,185, 47,119,145,130,143,129, 60, 77,102,191, 18,
+133,187,175, 32,127,186,135,247, 5, 81,237, 91, 94,231,190, 72, 48,112,129,116,142,238,218,154,209,199,170,192,177,246,219,219,
+ 95,185,244,235,147,105,142,182,183,106, 85,171,111,193, 35,241, 11, 45,177,239, 50, 90,181,239,179,181,146, 94, 45,158,175, 39,
+123,246,193,126,153,220, 7,172,136,228, 43,243,132,181, 89,224,238, 91,118,230,133,240, 50, 35,200, 11,204, 35, 2, 71,180,115,
+ 21,231, 18,254, 26,239, 11, 1,146, 28,136, 38,144, 11,244,129,101, 39,212, 11, 11,124,245,149, 73, 51,246,124,210, 81,159, 23,
+ 51, 29,136, 54,247, 89, 88,115, 6,184,173,166, 12,137,250, 57, 91,107,175,236,143, 67,222,238, 49, 53,235,226, 73, 62,154,126,
+103,172,247,176, 35,182,115,245,122, 35,225,255, 0, 21, 43,204,251, 87,254, 98,219,173,254,216,126,122,218,238, 27,210,239,221,
+135,151,152,192, 46, 74,116,226,201, 81,200, 56,146, 62, 32,122, 24, 27,214, 47,181, 5,251,139,110, 31,239,135,242, 26,233,182,
+171,174,223, 53,109,163, 78,201,255, 0,105,207,117,122,223,115,130,245,114,172,168,215,247, 30,217,117, 85, 44,238, 21, 84, 93,
+137, 32, 0, 7,164,154,163,204,239,206,220,193,144,198, 50,122,238, 56, 30,138,151, 3,250,223, 15,229,172, 87,126,119, 12,249,
+ 57,210,108,216,206, 83, 19, 24,233,156, 3,110,164,131,158,175, 82,242,183,166,162,246,175,103, 54,255, 0, 19,230,100,204,113,
+240,209,186,106, 84, 93,221,128,185,211,126, 0, 11,243,174, 20,218, 99,174, 53,151, 61,157, 83,213, 37,227,192,239,147,121,146,
+217, 94, 29,189, 85,154,209,183,225,196,219, 71,248,141,177, 76,250, 76,210, 66, 15, 13, 79, 25,183,253, 29, 85,123,141,157, 14,
+227, 24,159, 15, 33,103,136,253,120,216, 48,191,160,218,176,251,191,225,180, 48,226,188,251, 86, 76,143, 50, 2,194, 9,180,157,
+118, 23,178,178,133,177,244,112,172,126,195,190,101,236, 57,233,151, 3, 19, 29,192,200,134,254,235,167,136, 35,211,232, 62, 21,
+ 86,215, 14, 90, 59,109,236,229,114,176,123,188,248,110,169,185,162,139,127, 21, 79,113,120,236,180,129, 81, 16,151, 32, 0, 9,
+ 36,240, 0, 10,243,127,196, 60,249, 30, 77,178,108,105,157, 99,154, 23,145, 74, 49, 91,134, 42, 65,225,234,172,190,220,219,222,
+233, 33,218,112,165,150, 83,148, 71, 82, 50,230,196, 37,205,220,147,193, 69,248,214, 49,236,157,241,172,142,234,169,241,149,194,
+ 30,166,242,111,213, 50,188, 75, 27,179, 92, 33,241,149,166,135,169,228,119,167,108,224,202, 98,124,193, 43,142, 7,162,173, 32,
+ 31,214, 81,167,242,212,189,187,185,182, 13,225,196,120, 89,138,102, 60,161,144, 24,220,255, 0, 68, 56, 23,249, 43, 10,223,134,
+ 59,170,195,175,206, 64,101,183,240,236,246,191,163, 85,191, 53, 99, 39,131, 35, 7, 38, 76,121,129,139, 34, 7, 42,195,197, 89,
+ 79,129, 21,214,155, 77,182, 68,214, 60,141,217,126,220, 14, 55,222,238,177, 53,108,184,146,171,229,251,228,250, 18, 7, 83, 38,
+150, 23, 67, 66,221, 55, 28, 29,182, 48,249, 19,199,140,141,227, 35, 0, 79,178,252,235, 51,129,220,167, 31,178,163,223,242,135,
+ 83, 34, 48, 96, 80,127,180,152, 49, 69,191,180, 13, 70,188,183, 55, 59,112,222,179,142, 70, 83,190, 70, 84,236, 21, 71, 62, 36,
+217, 81, 23,192,122, 0,174, 56, 54, 86,189,173,220,251,107, 70,234,223, 86,186, 29,247, 27,250,210,180,236, 93,214,186, 86, 75,
+162,125, 79, 95, 78,251,237,128, 66, 54,120,213,202,253, 57, 45,243,232,181, 85,247,150,110, 30,227,218,217, 89, 24, 83,166, 68,
+122,226, 26,163, 96,214,251, 69,224,109,202,179,184,159,134, 91,220,240, 9,114, 39,131, 25,216, 95,164,197,153,135,244,180, 2,
+ 63, 45, 80,239, 59, 30,239,219,146, 28,108,206, 16,228, 11, 9, 34, 98, 98,148, 41,191,171,145,227, 98, 43,190, 61,190,223,212,
+175,165,150,109, 86,156, 61,102, 58, 30,124,187,173,215,165,101,151, 12, 86,213,106, 86,145, 61,120,134,236,223,249,155,111,254,
+155,127,213,181,123, 64, 41, 18,188,210, 48, 72,212, 93,157,141,148, 1,233, 38,188, 99,178,191,230,157,183,133,253,246,225,255,
+ 0, 13,170,207,191,123,146,125,195,113,151,105,199,110,158, 6, 27,104,100, 83,110,164,171,241, 51,250,116,158, 0, 85,221, 96,
+182,109,197,106,156, 37, 73,111,194, 89,157,166,226,184, 54,215,187, 82,221,225, 46,174, 17,179,205,239,158,219,197,144,167,154,
+ 51,176,189,250, 40, 92,126,215, 5, 63, 33,166, 98,254, 32,246,204,140, 17,230,146, 29, 71,226,146, 51, 97,127,232,106,172,127,
+104,246, 43,119, 14, 59,110, 25,147,156,108, 48,197, 35,208, 1,121, 10,252, 68, 22,224, 5,248, 85,190,251,248, 99, 22, 46, 20,
+185,123, 70, 76,146, 73, 10,151, 56,243, 5, 37,192, 23, 33, 89, 2,241,244,112,174,111, 14,206,182,244,237,123,119,112,111,148,
+252,142,171, 62,250,245,245,107, 74,118,241, 75,155, 95, 51,125,143, 46, 46,225, 18,229, 97, 79, 28,240,183, 39,141,131, 11,252,
+149, 32,196,163,134,174, 21,225, 61,181,220, 25, 61,191,184,199,146,132,182, 51, 16,185, 80, 95,131,167,143, 15,214, 30, 6,180,
+255, 0,137,153, 82,166,229,129, 38, 44,206,145, 75,138, 29, 74, 49, 80,192,187, 89,184,122,171, 22,216,181,154,184,251,180,178,
+109, 90, 58,114, 55, 79,112, 79, 13,178,118,253, 85,105, 58,207, 94,105,158,153,145,147,135,137,142,211,228,186,197, 12, 98,239,
+ 43,144,160, 15, 89, 53, 71,131,222,123, 14,233,184,166,217,130,239, 36,210, 22,233,182,130, 16,232, 82,231,139, 88,242, 95, 69,
+121, 14, 18,111, 59,212,169,180,226, 60,185, 45, 51, 7, 16,151, 37,110,160,251,237,168,216, 0, 15, 51, 94,131,219, 31,135,251,
+142,201,187,226,238,153,185,120,229, 97, 15,174, 24,203, 51,123,241,180,124, 14,144, 56, 22,173, 95,107,135, 21, 45,234,100,155,
+ 67,117, 75, 79, 35, 56,247,153,179, 94,190,158, 56,164,165,118,245,243,215, 67,125,170, 75,240,255, 0, 75, 83,130,185,241,244,
+126, 90, 85,147, 29,120,117, 47,110,118, 23,174,243, 24,232,120, 43, 55,228,175, 9,244, 14,210, 77,198,175,120,120, 82,136,248,
+123,220,205,128, 52,207, 52, 1, 58, 99, 31, 41,174,243,147,114, 80,170, 61,149, 10, 24, 66,110, 24, 11,158, 96, 81, 76, 4, 11,
+233, 55, 35,159,133, 66, 57, 89, 7,251, 66, 7,160,112,160,201, 36,172, 9, 46, 79,203, 66, 22, 38, 38,183,190,202, 7, 1,123,
+142, 66,155,254, 29, 78,166,148, 27,120, 10,173, 13,195,143, 62, 20, 80, 56, 80, 19, 12,248,160,113, 37,207,178,132,114,224, 65,
+238,196, 77,189, 38,163, 61,128, 62,170, 17,109, 95,146,172,130,112,205, 65,109, 48, 1,237, 98,105, 78,107, 19,113, 18, 2,124,
+120,159,207, 80, 75, 16,120, 11,220, 88, 83,212,240, 23,231,227, 80, 22,190,102, 79, 47,125, 43,252, 13, 86,183, 11,249,141, 62,
+154,234, 13,255, 0,195,127,252, 55,255, 0, 19, 93, 64, 90, 17,193, 63,160,159,186, 43,171,137,248, 63,160,159,186, 43,175, 84,
+132,124,143,136, 95,209, 64, 34,252, 40,211,183,190, 7,170,134, 47,126, 2,128, 96, 85, 82,125, 38,157,164,248, 26,112,181, 37,
+184,208, 8, 1,177, 6,147, 65, 6,247,231,225, 69, 2,244,164, 80, 2,227,227, 80,166, 26,165, 98, 57,125, 2,167,176,181, 87,
+ 23, 5,139,122,120,218,140,168, 80,163,145,167, 16, 7,168, 10,104,106,160,221,115,228,146, 87,198, 67,166, 52, 58, 90,223, 88,
+142,119,175, 46,239,117, 77,182, 62,251, 41,109,197, 82,230,207, 70,219,109,125,198, 78,202,232,150,173,190, 72,145,159,187,133,
+188, 88,134,231,145,151,192,127, 70,169, 73, 44, 75, 49,185, 60, 73, 60,233, 42,199,111,218,164,202, 34, 89,110,144,248,122, 91,
+217, 95,157,190, 77,206,251, 50, 95,169,242,170,253, 53, 95,183, 51,239, 86,155,125,158, 38,248, 46,118,127,170,204,141,141,135,
+ 46, 86,162,130,209,160, 37,156,242, 22,168,245,178, 88, 99,142, 62,138, 40, 84,181,128, 30,186,200, 75, 25,138, 71,141,185,161,
+ 42,126, 74,233,190,216,173,181, 49,107,220,237, 61,207,148,233, 9, 28,246,123,199,184,190, 93, 59, 85, 99,181,115,141,101,179,
+ 67,217, 82,170,110,178, 70,121,201, 11, 5,246,130,173,252,130,157,248,185,182, 79,184,118,147, 77, 2,151,108, 25,211, 37,212,
+115,233,128,209,185,249, 53,222,168, 48,242,165,193,202,139, 46, 31,142, 38, 12, 61,126,144,125,162,189, 63, 7, 59, 19,118,195,
+ 19, 69,103,142, 65,166, 88,154,198,196,143,121, 28, 87,211,246, 45,213,107, 95, 79,248,177,219,185, 46,181,103,206,247,173,171,
+187,118,254, 28,149,237,111,165,145,242, 93,117,123, 71,114,254, 13, 69,147, 59,229,246,222, 74, 99, 7, 37,142, 22, 69,250,106,
+ 79,251, 55, 80,196, 15, 81, 7,219, 89,220,127,193,158,233,146, 80,185, 19, 98, 65, 31,140,157, 70,115,111, 82,170, 87,236, 43,
+187,193,106,207,122, 94, 15,137,248,251,108,183, 21,183,111, 99,126, 43,129,141,237,205,178,125,227,125,192,219,177,212,179, 77,
+ 50, 6, 35,234,160, 58,157,207,244, 84, 19, 95, 78,111,178,172, 59, 62,107,185,176, 49, 50, 15,107,141, 3,242,154,165,236,254,
+196,218,187, 66, 54,146, 2,114,115,229, 93, 51,102, 72, 0, 58,121,232,141,120,233, 90,131,221,219,220,121, 76, 54,220, 86,213,
+ 28,109,170,119, 28,139, 14, 74, 61,158, 53,241, 61,231,127,141, 98,179, 79, 78,215, 90, 79, 27, 90,199,221,246,109,134, 69,116,
+159, 23,101,107,199, 10,214,166, 86,174,187,117,152, 77, 56, 0,144, 84, 92, 15,109, 82,214,143,183, 32, 43, 12,179,145,252, 70,
+ 10,190,197,253, 38,191, 41,237,149,118,221,227,143,225,150,252,160,253, 55,184,217, 87,107,146,121,194, 94,114,121, 95,226, 65,
+191,117,100, 27, 17,246, 80,243,254,128,173, 39,225,162,194, 54,140,146,162,243, 54, 65, 18, 31, 29, 33, 23, 79,242,154,206,126,
+ 36,241,238,188,143,238,226,253,193, 85, 27, 22,255, 0,159,219,243,180,248,160, 52, 83, 13, 50,194,247,210,250,125,158, 34,252,
+235,250, 19,197,108,155, 58, 82,188,123,106,252,224,252, 13,114,215, 22,246,247,178,211,186,201,248, 79, 51,219,129, 40,223,205,
+ 53,228,255, 0,136,171, 8,238, 50, 98,182,182,130, 51, 53,191, 95,136,253,208, 42,198,111,196,201,154, 43, 67,183,170,203,111,
+137,228, 44,160,255, 0, 68, 42,147,243,214, 50,105,179,119,124,230,150, 77, 89, 25,121, 47,201, 69,203, 49,224, 21, 64,252,149,
+207,103,182,201,142,238,249, 23,106,134,184,157,119,187,172, 89,113,172,120,223,115,109, 62, 31,153,119,179, 23,255, 0, 42,119,
+ 16,254,204,121, 91,127, 75,169,198,161,246,159,252,201,182,255, 0,124, 63, 61,108,114,246, 35,176,246, 6,108, 19, 91,205, 77,
+211,155, 38,222, 12,100, 64, 19,250,163,242,214, 55,180,255, 0,230, 77,183,251,225,252,134,187, 86,234,248,247, 22,175, 6,237,
+246, 85, 35,133,233,106,100,219, 82,220, 82,172,252,110,217, 19,121,215,247,190,225,212,248,252,204,218,175,233,214,213, 59,108,
+217,123,159, 51, 17,103,218,226,153,177, 88,176, 83, 28,161, 86,224,217,184,107, 21,117,223,221,185, 62, 46,116,155,206, 50, 23,
+196,201, 58,167, 32, 95,167, 39, 35,171,212,220,239,233,168,125,169,222,115,118,234, 62, 36,176,249,140, 57, 27, 94,144,116,186,
+ 49, 22, 37,111,192,131,110, 85,175, 82,215,193, 91,225, 85,179,133,163,251, 87,153,151,142,180,220, 90,153,221,168,165,253, 75,
+236,126, 66, 14,217,239,163,253,134, 73,255, 0,142, 63,239, 42, 49,236,142,234,230,118,231,253,184,255, 0,215,173, 30,239,248,
+152,211,226, 73,143,180,227, 60, 18,202, 10,156,137, 88, 93, 1,225,116, 84,191, 31, 65,189, 73,236, 94,233,223,119, 44,149,219,
+114,161, 57,176, 40,247,243, 73,210,209, 15, 3, 35,114,111,229,174, 94,166,234,184,222, 71, 76,117,142, 43,131,143,153,215,210,
+218, 91, 34,198,178,100,180,240,107, 85, 63, 34,131,188, 49,178,112,246,253,131, 31, 49, 74,100, 71,138,201, 34, 18, 9, 5, 89,
+ 64, 28, 47,225, 86,159,133,145, 35,101,110, 82,145,119, 88,227, 85, 62,128,197,137,253,209, 78,252, 86, 10, 50,246,219, 27,253,
+148,159,188,180,239,194,166, 69,151,116, 45,250,176,219,231,146,179,107, 78,197,219,132,235,243,185,170,213, 47,112, 85,227, 26,
+107,225, 67,210, 7, 43, 90,245,226,125,242,161, 59,167,112, 0, 91,222, 66,125,166, 52,189,123,104,158, 48,108, 22,254,154,241,
+ 78,250, 33,187,171, 60,129, 97,120,248,127,194, 74,225,237,223,243, 91,253, 15,239, 71,163,220,255, 0,225,175,250,215,220,195,
+230, 25,127,200, 59,104, 4,244,142,116,183, 30, 23,210,214,252,244, 62,193,138, 9,123,167, 9,103,181,135, 81,163,191,235,136,
+216,173,105,118, 45,168,239,189,130,118,208, 66,201,214,146, 88, 24,248, 72,173,194,231,208,121, 87,159, 21,206,218, 51,134,160,
+248,185,184,174, 24, 95,131, 43, 41,184, 53,236,163, 87,174,124, 73,197,187,174,191,187,153,225,200,158, 59, 96,204,212,215,182,
+143,251,121, 31, 69,244, 91,245,109,111, 19, 89, 15,196,152,161,255, 0, 44, 59, 77,167,170,179, 68, 97,226, 47,168,155, 27,127,
+ 86,245,153,198,252, 80,202, 88, 66,230, 96,137,165, 3,248,137, 33, 64, 79,164,169, 87,254, 90,206,119, 15,115,110, 29,198,234,
+103, 81, 22, 52, 62,244,112, 71,114, 1, 60, 53, 49, 60,207,133,121, 48,108,243, 87, 45,109,101,218,170,230,103,140, 30,205,198,
+247, 5,176,218,180,110,206,202, 34, 56, 79, 81,253,146, 64,238,157,180,177,176,214,215, 63,240,222,169,243,245,121,236,157,127,
+ 31, 86, 77, 87,231,125, 70,245,107,217,223,243, 46,223,253, 54,253,198,171, 62,249,237,220,140, 28,249,119, 88, 35, 45,133,150,
+218,220,168,254, 28,141,241, 6,245, 49,226, 13,123,158, 74,215,115,218,244,238,162,143, 52,222,135,129, 99,181,182,189,235, 85,
+ 76,142,124,154, 90,149,187,118,205,221, 89, 88,113,207,182,164,231, 17,239,211, 49,202, 21,120, 18, 13,151, 88,241, 21, 43,252,
+191,222,230,227,167,146,125, 63,110, 63,239, 41,221,177,222,115,108, 48,156, 41,226, 57, 24,133,139, 32, 83,103, 66,126, 45, 55,
+224, 65,244, 85,142,241,248,138,249, 56,175,141,181, 64,248,237, 40, 42,217, 14,195, 82,131,250,129,124,125,119,174,119,182,231,
+212,117,174, 58, 58,206,150,125, 60,117, 58,210,187, 95, 73, 90,217,114, 43, 37,173, 87, 95, 13, 10, 63,242, 95,115,159,255, 0,
+183,191,237,199,254,189, 77,239,100,202,137, 54, 56, 51, 65, 92,136,118,248,227,145, 73,185, 5, 9, 91, 92, 95,209, 90, 30,200,
+238,109,251,116,155,200,228,192,114,225,140,123,249,163,221,100,244, 7, 60,154,255, 0, 61, 85,126, 38,234, 59,166, 17, 97,111,
+240,230,223,182,213,154,229,202,247, 53,199,145, 87,233, 77,253, 62, 70,173,139, 18,218,219, 46, 39,127,169,164,213,188, 25, 55,
+240,183, 30, 50,219,142, 89, 31,106,162, 56,149,189, 10,218,153,190,114,162,189, 9,205,143, 63,101, 96,191, 11, 17,158, 13,207,
+ 77,184, 60, 87,191,177,235,208, 78, 49,250,206, 62, 65, 94, 29,239,255, 0, 69,254, 31,113,239,216,194,219, 83,227,247,176, 73,
+195,143,164,209,173,122, 98, 39,128,227, 82, 22, 50,107,204,122,129,105,174, 34,212,101,135, 72,211,242,210,180, 87, 4, 3, 66,
+ 1,210, 10,220, 83, 28, 88, 26,146,168, 21,109,126, 84, 9, 52,145,192,241, 55,189, 10, 9, 97,149,136, 33, 15,203, 68, 88,165,
+111, 64,249,104,137, 32, 80, 7,143, 0, 7,182,145, 92, 39,188, 71, 11,241,160, 56, 98,187, 94,238, 7,201, 92, 49, 71,139,159,
+144, 84,152,110, 80, 19,192,154,118,154, 16,141,229, 80,115,103,255, 0, 79,146,151,203, 69,233,115,242,212,146, 41, 45, 64, 19,
+161, 31,150,181,143,254, 30,215,191, 27,121,141, 85,212,107,127,135,245,116,127,237,171,170,128,204, 88, 20, 22,250,137,251,162,
+151, 81,244, 83,143,213, 63,204, 79,221, 20,221, 84, 4,121,254, 48,108,121, 80,140,150,240, 53, 34, 83,198,227,209, 65,182,163,
+198,128,110,163,110, 95, 53, 34,200, 73,226, 45, 70, 2,222,202,234, 1,186,172, 41,117, 3,227, 74, 64,228,105,186, 64, 38,244,
+ 3, 36,107, 41, 42,111, 96, 79,205, 80,128,169, 83,128, 34, 98, 56, 30, 0,124,245, 23, 73,183, 58,140,168,227,106,163,206,218,
+167,121,222, 88, 44,235, 33,212, 69,236, 65, 60,249,213,209, 30, 53,220,128,175, 62,231,107,143,113, 69, 76,147,163,148,214,141,
+ 29,246,251,156,152, 44,237,142, 53, 80,211,213, 21, 56, 91, 64, 70,234,101, 89,136,229, 24,226, 63,173, 87, 60, 64,224, 45,110,
+ 84,128,113,162,242, 21,118,251,108, 88, 43,217,138,177,213,190, 47,205,147, 62,227, 38,107,119,100,115,209,114, 94, 72, 17, 44,
+106,147,120,195, 33,188,210, 11,131,194, 79,204,106,242,154, 66,176, 33,133,193,224, 65,169,186,219,215,113,138,216,237,167, 52,
+250, 91,147, 46,219, 61,176,101, 89, 43,175, 38,186,174,134, 58,165, 96,238, 25,123,116,221,108, 73, 76,109,201,135, 53, 97,232,
+ 96,120, 26,147,157,181, 60, 68,203,140, 53,199,204,167,138,253, 34,171, 43,242,249,112,230,219,100,139, 39, 75, 46, 22, 95,125,
+ 89,250, 60,121,113,110, 49,205, 98,213,124, 83,251,154, 54, 88,189,242, 52,129,155,138,117,120,188, 71,129,254,171,125, 53, 33,
+251,227, 0, 15,179,198,153,155,208,218, 84,124,247,106,194,215, 87,162,190,235,188, 74, 59,211,241,117, 82,112,126,219,181,110,
+123, 26,240, 77,193,123,185,247, 86,227,158,166, 24,237,141, 11,112,101,140,221,136,244, 23,250, 42,138,186,143,141,135, 62, 91,
+232,133,110, 60, 92,240, 81,237, 53,230,190, 76,251,140,139,185,219, 37,158,137,113,249, 35,209, 90, 97,193, 71,218,171,142,171,
+ 86,255, 0, 54, 55, 27, 30, 76,169,150, 8,133,217,143, 63, 0, 60, 73,173,140, 49, 54, 52, 9, 4, 86,210,130,195,210,125, 38,
+133,129,183,197,183,199,101,247,164, 97,239,200,121,159, 80,245, 84,146,121,219,198,191, 65,237,219, 47,241,232,237,127,249, 47,
+199,250, 87, 79,204,248, 91,253,231,175,101, 90,126,138,112,254,167,212,160,221,251,111,103,220,178,188,222,118, 10, 73,144,224,
+ 6,144,179,220,133, 0, 14, 68, 84, 97,218,219, 25,195, 56, 13,134,158, 91, 81,144, 39, 30, 14, 64, 5,149,137,212, 56, 15, 3,
+ 87,185, 46,193,213, 64,189,133, 0,251,195,159,182,213,245, 86, 76,144,151,125,161,112,213,232,124,239, 75, 28,183,217, 89,124,
+116, 90,153,102,252, 61,237,176,250,180, 76, 23,245, 68,134,223, 77, 92,237, 91, 22,205,180,123,219,126, 42,196,228, 88,202,110,
+206, 71,244,222,230,167,143, 69,184,122, 77, 33,247, 79, 50,125, 66,173,179,101,178,139, 94,205,116,108,149,193,138,174,107,142,
+169,245, 72,102,102, 38, 38,227,142,248,121,104, 38,130, 75,107,140,220, 3, 98, 24,114,177,230, 42,191, 23,181,123,127, 15, 38,
+ 60,172, 92, 20,142,104,142,168,220, 51,146, 15,167,139, 85,153,186,157, 67,135,166,136, 13,248,250,107, 42,247, 74, 21,154, 79,
+138, 79, 67, 79, 29, 44,213,173, 84,218,224,218,150, 43, 42,178,149,112, 25, 72,177, 83,196, 16,107, 55,153,217, 93,183,153, 35,
+ 57,196,232,177,230, 97,102, 65,251, 32,233,252,149,164,174,232, 92,222,252,248,210,185, 47, 77,105,103, 95, 39, 2,248,233,125,
+ 47, 85,111, 53, 38, 82, 62,193,237,184, 88, 51, 67, 36,182,240,146, 70,183,253, 29, 53,161,194,198,197,193,132, 99,225,196,144,
+ 68,188,145, 0, 81,249, 43, 17,220,157,225,186,109, 27,254, 70,221, 10,196,113,161, 49, 88,178, 18,214,120,210, 70,226, 24,126,
+181, 2,126,234,238,205,200,190, 78,203,183,186, 96,130, 68,110,176,153, 73, 3,210,196, 21, 39,210, 23,149, 91,228,201,127,215,
+103,111, 54, 74, 98,199, 79,209, 74,215,201, 27,125,199,101,218,119,102,141,247, 28,101,157,162, 4, 70, 88,176,176, 60,254, 18,
+ 41, 54,253,155,107,218,122,135,109,198, 88, 12,182, 18, 21, 44,111,166,246,248,137,244,214, 51,101,252, 67,200,143, 41,113,119,
+232, 16, 68,205,161,167,141, 74, 60,102,246,187,161,230, 7,141,172,125,181,123,222,253,201,157,219,235,183,182,218, 34,101,202,
+ 18,151, 50, 41,113,100,233,233,211,102, 31,175, 83,190,253,189,189,207,183,164,233,242, 29,148,238,239,237, 93,221, 99, 95,153,
+164, 64, 73,170,236,206,215,216,119, 12,151,203,204,194, 89,114, 37,177,121, 9,112, 78,144, 20,114, 96, 57, 10,238,215,220,166,
+221,182,108, 92,252,192,162,121,250,154,194, 11, 47,185, 35,160,225,115,224,181, 75,222,189,217,185,118,254,118, 62, 54,222, 33,
+ 49,203, 15, 81,250,138, 88,223, 81, 94, 22, 97,232,169, 91, 90,174,106,221, 95,131,130,218,149,178,139, 85, 89,113,213, 73, 97,
+186,230, 96,118, 86,213, 19,226, 97,223, 29,166,233,136, 81,202,217,157, 89,203, 93,181,126,165, 3, 1,182,126,248,219,223, 55,
+ 55,110, 85,233, 74,208, 46,166,187,139, 42,189,195,166,146, 62, 62, 85, 81,222,155,131,238, 93,153,181,101,204, 7, 94,105,161,
+146, 77, 34,203,115, 12,183,183, 58,160,237,206,228,221,118,237,185,246,141,155, 19,204,101, 77, 51,204,207,165,164,178,149,141,
+ 6,148, 79, 90,241, 39,133, 59,172,159,114,111,187,172,235,243, 29,149,117,237,117, 93,189, 35, 79,145,178, 31,135, 61,186,126,
+208,137,109,250,157, 67,111,166,167,228,246,231,111,237,123, 46,104, 92, 32,248,209, 68,211,205, 16, 36, 52,157, 16,100, 0,201,
+197,185,173, 98,219,189,123,187,105,157, 83,117,199, 26, 79, 17, 20,240,152,174, 56, 95, 67, 46,159,159,141,109, 62,248,197,223,
+123, 63,116,207,198, 36, 3,137,146,146, 68,214,212,140,177, 53,212,219,219,122,219,205,150,209, 55,179,143, 19, 11, 6, 26,207,
+110, 58,169,211,130, 40, 59, 62,126,217,221,183, 99, 30, 14,205,228,242, 49,162,108,132,152,204,207,201,150, 59, 91,135,251, 74,
+156,221,239,132,251,217,216, 31,109, 45,171, 47,200,180,140,224,169,188,157, 29, 69, 74,242,241,181,103,127, 11,127,230, 12,159,
+253, 27,255, 0,214,195, 83,127,205,185,255, 0,230,239,186,188,182, 39, 71,239, 47, 45,212,232,253,166,158,191, 79, 86,187,252,
+ 86,241,244,214, 45,107, 89,205,172,219,241,114,110,180,173, 83, 85,170,170,232,148, 26,124,190,192,237,140,183, 47,228,250, 12,
+121,152, 29,144,126,205,202,254, 74, 28, 31,135, 93,175, 11,135, 56,242, 77,111, 9, 36, 98, 62,101,211, 65,239, 46,246,110,222,
+153, 54,252, 24, 86,108,199, 65, 35,188,151,208,138,110, 7,186,164, 18,198,222,154,168,139,115,252, 79,202,199, 92,248, 49,151,
+203,186,137, 16, 4,132, 18,164,106, 4, 35, 55, 80,220, 87, 79, 95, 52, 71,169,104,243,103, 63,241,240,204,250,116,249, 35,121,
+ 14, 62, 46, 12, 75,137,137, 18,193, 18,143,114, 56,212, 42,250,249, 86, 35,188,183, 77,139, 15,112,131, 31,117,218,124,252,189,
+ 5,116,151,170, 83, 74,180,142, 52,216,127, 70,133,219,255, 0,136, 57,121, 91,140, 91,110,247, 2, 35, 74,253, 21,158, 48, 80,
+172,135,221, 11, 34, 49, 60,219,135,133,170,163,241, 44, 91,124,197,255, 0,209,167,253,108,213,205, 90,201,247, 38,211,234,158,
+167, 71, 74,181,218,234,154,232,214,135,164,118,222,221,181, 99,109,208,230,109,120,131, 13,115,226,138,119,140, 51, 55,196,154,
+212, 18,196,242,213, 87, 5,111, 94, 91,139,221,221,207,145,182,226, 97,118,230,218,237, 14, 22, 60, 80, 75,146, 34,105,152,188,
+113,170,155, 91,220, 28, 71, 46, 38,155,181,126, 36,238,248,217,171,143,191, 70,178, 65,171, 68,204, 19,167, 44,124,109,123, 11,
+ 14, 30, 34,212,109,183, 54,109,183,205,133, 85, 85, 21, 73, 37,201,104,122, 67, 22, 66, 64,225,126, 6,139,230, 20, 85,103,115,
+119, 30,221,219,152,105,147,145, 8,159, 38, 98, 70, 60, 32,216,185, 28,201, 60,108,163,196,214, 51, 7,185,187,251,124,234, 79,
+178, 97, 68,176, 6,248,150, 52, 9,195,234,135,201,107, 19,233,181, 66,158,138,114, 73, 60, 20,159,101, 15, 94, 83,159,117, 90,
+222,139, 86, 10, 63,196, 30,230,216,179,151, 19,185,112, 80,169,177,109, 40, 35,147, 79, 45,104, 84,152,216,127,165,235, 99,191,
+247, 36,152,157,175, 54,253,180,200,146,251,177, 62, 59, 56, 37, 72,146, 68, 67,117,184, 60,152,252,180, 4,195, 6,107,241,208,
+212,169,135,145,123,178,216, 14,119, 53,231,184,191,138,123,144,192,200,108,184,163,155, 61,157, 87, 18, 52, 86, 84, 0,131,169,
+228,247,141,248,218,192, 84,254,208,238,126,229,221,247,150,196,221,198,140,119,133,228, 69, 48,244,248,169, 91,105, 36, 92,243,
+168, 83,118,177, 11,222,215, 32,115,166,194,161,129, 4,120,212,129,193, 79,205, 65,199,224, 73, 30, 6,132, 14,163, 72,165,181,
+112,244,210,131,224,106,129,182,227, 75,106,227,225, 92, 61, 84, 4,159,236, 63,224,255, 0,219, 87, 87,127, 99,127,247, 63,246,
+213,212, 1,216,240, 91,126,162,126,232,166, 53,248, 27, 82,146,214, 75,243,208,151,253,145, 72,120,248, 80, 1,150,247,229,198,
+212,128,124,158,154, 89, 73,214, 7,160, 80,213,154,230,252,168, 2, 94,254, 21,199,135,133, 52, 31, 77, 41, 60, 40, 14,231,196,
+210, 19,122,224,199, 81, 4, 88, 82, 49,183, 42, 2, 54, 75,130,170, 61,119, 31, 37, 8,176, 2,157,148,110,234,190, 0, 94,254,
+223,254,202, 15,174,163, 41,196,220, 87,113,244, 82,168,225,122, 95, 10, 1, 3,113,167, 22, 39,128,161,131,204,211,129, 0, 80,
+ 28, 5,233, 66,138,229, 34,150,252,104, 5, 68, 5,192,240,191, 16,125, 20,220,157,175, 11, 35,222,120,128,254,114,240, 63,146,
+137, 25, 26,193, 38,214,227, 69, 12,182,231,250, 43, 23,165, 46,187,111, 85,101,209,169, 53, 75,222,143,186,150,117,125, 83,130,
+142, 94,223,135, 94,152,166,101,191,131, 40,111,203,238,210,142,218, 91,219,205, 31,216,255, 0,241, 85,211, 1,173,120,252,130,
+137,170,255, 0, 9,226, 43,200,253,183,102,220,250, 75,225,107, 47,196,244,175,112,221,165, 30,171,249, 85,254, 5,108, 29,189,
+131, 29,139,234,149,191,156,108, 62, 97, 83, 4, 9, 24, 9, 31,186,163,192, 90,194,164,107,241,231, 76, 33,124,121,215,163, 22,
+ 12, 88,148, 99,165,107,228,181,249,156, 50,102,203,145,206, 75,187,121,189, 62, 64,250,108,205,160,185,176, 30,170,227, 19,143,
+174, 72,246, 10,122, 31,120,211,197,129,244,138,234,115, 43,114, 56, 74, 81,141,237,110, 63, 37,232, 23,210,120,114,241, 52,108,
+150,213, 51,176,229,123,113,245,112,160,131,126, 85,160, 41,177,227,207,213, 74, 13,197,143, 3, 76, 38,198,151,219, 64,119, 1,
+195,159,164,154, 32,231,106, 8, 32,155, 15, 26, 58,142, 55,163, 2,170,220,138,145,106, 26, 14, 34,141, 80,135,138,119,222,145,
+221,217,250,175,166,240,106,183, 59,116, 35,229, 94,195,141,229, 31, 10, 3,131,164,226,116,215,161,163,225,209,111,118,223, 37,
+120,239,126,255, 0,205,155,135,252, 31,250,136,235, 65,149,216,189,207,183,179,195,178,110,108,112, 88,146,177, 9,164,132,216,
+248, 58,175,184,125,181, 65, 75,248,130,113, 15,112,183,150,211,172, 66,131, 39, 79,251, 91,183, 63, 94,141, 53, 55,190, 22,100,
+216,187, 89,114, 47,213, 24,207,174,252,239,163, 31,129,191,143,166,172,182, 31,195,105, 23, 37, 50,247,217,146, 68, 82, 28, 99,
+ 68, 75,107, 55,191,218, 59, 1,195,210, 7, 63, 77,106,187,171,182, 98,238, 76, 20,131,169,209,200,128,151,199,146,215, 81,113,
+102, 86, 30,131, 64, 67,236, 69,137,251, 79, 9,131, 18,203,214, 86, 0,242, 61,103, 54, 63, 33,172,119,226,116,152,231,123,199,
+134, 22,187,195,142,162, 81,123,217,153,153,128, 62,187, 88,209, 49,187, 19,188,176, 93,162,196,205, 76,104,156,128,239, 14, 68,
+136,173,225,114, 17, 65, 63, 53, 73,206,252, 47,220,157, 98,124, 92,216,166,157,181, 54, 84,185, 5,214,236, 79, 13, 1, 82, 66,
+125,164,208, 11,221, 11, 24,252, 60,216,138,168, 14, 95, 30,237,226,126,194, 90,176,252, 46,108, 47,186,243, 21, 2,156,222,189,
+230,189,139,116,244,142,159,245,111,171,229,189, 78,222,123, 83,113,220,123, 87,109,216,224,150, 5,201,195,104,154, 87,118,113,
+ 25, 9, 27,198,116,144,133,185,183,136,170, 24,191, 13,247,172, 76, 84,200,195,207, 72, 55, 68,102, 7,165, 36,138,133, 13,180,
+233,144, 42,178,183, 63, 11, 80, 23,255, 0,136,231, 13,123,105,214,125, 61,118,150, 63, 43,127,139, 88,111,123, 79,245, 53, 86,
+ 83,178,122,223,229,238,234,255, 0, 97,228,218,215,229,175,165, 55, 47,147,159,201, 79,255, 0,233,247,116,238, 57, 8,219,182,
+106,122, 12,210,202,243,184, 31,205, 7,253, 97, 91,172,126,217,199,219,187,115, 51, 99,219,136,234,100,193, 44,102,121,120,107,
+150, 84, 41,173,202,131, 97,199,192,112, 20, 6, 7,240,183,254, 96,201,255, 0,209,191,253,108, 53, 91,255, 0,253, 3,255, 0,
+243, 63,252, 85,109,123, 51,178,247, 78,220,221, 38,205,206,155, 30, 72,164,199,104, 64,133,157,155, 83, 60,111,115,174, 52, 22,
+178, 84, 79,242, 14,240,123,163,239,190,190, 55,150,243,254,115, 70,185, 58,157, 62,183, 90,214,233,219, 85,189,116, 1,251,223,
+182,176,183,156,209,151, 6,231,141,139,157, 26, 8,230,199,201,145, 80, 48, 30,242,159, 22, 83,102,244, 85, 84, 91, 63,226, 86,
+221,142,137,129,146,211, 99,162,142,152,142,104,221, 66,248,105, 19, 91,133,185, 90,180, 61,221,216,171,191,206, 55, 28, 41,215,
+ 31, 55, 72, 73, 22, 64, 76,114, 5,224,164,149,185, 82, 7, 14, 70,169,177,187,127,241, 35, 2, 5,195,196,207, 69,199, 64, 21,
+ 0,148, 48, 10, 57, 5,214,154,128, 20, 5,110, 23,125,111, 59,118,225,229,119,236,120,166, 10,250, 50,117, 68,177,204,134,252,
+ 88,116,194,139,142,124,184,211,127, 19,191,253,247, 23,255, 0, 69, 31,253,108,213,103,183,126, 29,103, 73,157,247,135,112,102,
+ 36,190,255, 0, 82, 72,227, 45, 35,200,223, 21,157,220, 45,175,227,206,172, 59,191,178,247, 78,227,220, 96,206,194,155, 30, 56,
+163,199, 72, 74,204,206,173,168, 59,191, 13, 17,184,183,191,233,161, 77, 63,107,193, 20, 29,185,181,164, 42, 21, 91, 22, 25, 8,
+ 30, 45, 34, 9, 28,252,172,198,188,167,241, 17, 85,123,175, 46,192, 13, 73, 9, 54,241, 61, 53,175, 97,218,113,164,193,218,176,
+112,102, 42,210,227, 99,197, 11,178,220,169,104,209, 80,149,184, 6,220, 43, 15,221, 93,137,187,239,219,212,219,150, 36,248,201,
+ 12,139, 26,133,149,164, 13,116, 80,166,225, 99, 97,225,233,161, 10, 95,196,193, 40,220, 54,194,223,193,242, 75,163,209,171, 91,
+107,252,154,106, 94,193,143,248,131, 38,211,140,219, 54,100, 9,128, 87,236, 22,208, 92, 11,241, 7, 84, 68,222,252,238,107,109,
+191,246,198, 31,112,237,209, 97,229,183, 78,120, 0,232,100,160,185, 70,176, 13,192,218,234,109,196, 86, 51, 15,180, 59,227,102,
+214,155, 46,227, 31, 65,155,225, 87, 32, 19,250,198, 57, 16,168, 62,202, 0, 59,231,111,119,190,234,176,166,249,151,136,226, 34,
+198, 13,111, 12, 68, 94,218,172, 81, 16,158, 66,167,101, 96,102,109,159,134,121,184, 89,143, 27,180,114, 39, 77,162,113, 34,232,
+108,136,155,226, 31,206, 38,135, 31,225,239,112,239, 57,139,149,220,187,138,149, 22, 7, 75, 25, 36,210, 56,233, 91,133, 68, 30,
+207,154,181,219,215,110, 46, 71,107, 75,219,187, 72,142, 1,166, 36,131,168, 72, 80, 18, 84,149,139, 21, 86, 55, 58, 79,135, 58,
+ 3, 19,248, 85,131,141, 62,102,225,155, 42, 7,155, 21, 98, 88, 11, 11,233,234,151,212,195,215,238, 87,169,214, 71,177,251, 87,
+112,237,159, 63,231,228,134, 79, 53,209,233,244, 25,218,221, 62,165,245,107, 68,253,113, 90,242, 61, 20, 7,120, 90,135, 0,224,
+222,211, 69,183, 10, 20, 2,225,189,166,128, 50,220,120,210,248, 83, 47, 78, 7,194,128,239, 93, 45,248, 90,146,220,125,117,214,
+ 28,168, 9, 86,251, 15,248, 63,246,213,212,150,251, 11,127,185,255, 0,182,174,160, 12,231,225,254,130,126,232,164, 7,242,215,
+ 61,253,223,232, 39,238,138,101,254,122, 1,146,219, 80,246,113, 52,194, 7,167,157, 36,199,223, 30,202,102,174, 55,160, 9,123,
+ 10,237, 66,178, 57,127,137, 29,147,131,151, 62, 30, 94,241, 28, 89, 56,210, 60, 51,198, 82, 82, 86, 72,201, 71, 94, 8, 71, 2,
+ 41,119,175,196, 30,218,217, 54,140,125,246, 76,131,153,131,149, 33,139, 30, 76, 48, 37,212,224, 18, 87,226, 80, 8,177,230,104,
+ 13,101,205, 37,175,204,212, 76, 28,200,247, 12, 44,108,248, 67, 44, 89, 81, 36,232,174, 0, 96,178, 40,117, 13, 98, 69,236,125,
+ 53, 38,246,160, 33, 79,115, 51, 1,198,214, 3,230,166, 89,185, 83,201, 13, 33,111, 2,111, 85, 93,193,220, 59,119,108,237,175,
+187,110,101,198, 50, 50,161,233, 46,182,212,223, 8, 2,226,161, 75, 64,167,149, 46,159, 10,137,180,110,152,251,198,219,139,186,
+227, 43,164, 25,113,172,209, 44,128, 7, 10,194,227, 80, 82,194,255, 0, 45, 75,213, 64, 53, 82,252, 41,116, 11,210,171, 0, 77,
+ 71,200,220,182,252, 39, 84,204,203,135, 29,228, 35,166,179, 72,168, 90,255, 0,170, 24,139,208, 18,130,129,106, 91, 0, 41, 53,
+131, 98, 56,131,196, 26,141,151,185,237,248,110,145,229,229, 67,142,207,240, 44,178, 42, 22,191, 15,116, 49, 23,160, 38, 34,130,
+192, 31, 11,154,118,149,253, 81,243, 80, 60,214, 52, 8,102,200,149, 34,140, 91,237, 29,130,175, 30, 92, 91,133,116, 59,150,221,
+146,230, 60,124,184,101,107, 95, 76,114, 43, 27, 14,102,192,212, 4,160,145,159,168, 9,174, 17, 39,163,157, 33,113,162,234,226,
+145,100, 95, 3,199,198,128, 82,137,171,228,229, 92, 99, 78, 22,254, 83, 93,212, 3, 87,172,211,131, 41, 62,206, 32,208, 12, 17,
+139,158, 99,229,164,104,255, 0,156,223, 57,167,146, 56,144, 64,166,177, 22, 36,159, 14, 94, 20, 5, 99, 31,125,141,184, 18, 77,
+205, 52,144, 56,222,254,170,127, 76,145,239,154,239,113,121, 14, 53,160, 55,222, 35,221, 22,245,210,132, 31, 88,222,149,157,189,
+130,152,196, 30, 60,205, 0,225,164, 48, 85, 28,234, 66,138,141, 29,203, 2,124, 42, 72, 53, 24, 8,190, 20,241, 76, 94,116,250,
+164, 49,187,239,225,252, 59,222,235, 62,232,249,205, 11, 79,162,241,136,195, 1,161, 22, 62,122,135,234,214,186, 86,181,135,166,
+136,105,174, 5,175, 64, 42,240, 81, 78, 7,141, 48,176, 22, 4,210,223,198,244, 7, 73,224, 61, 44, 40,130,130,238, 3, 45,207,
+141,205, 47, 93, 60, 56,208, 4, 39,194,186,154, 92, 91,141, 53,165, 69, 62, 63, 61, 73, 16, 57,190, 52, 30,218,125, 71, 51, 13,
+ 64,143, 11,254, 90, 40,122, 72,128,156,233, 64,160,153, 84, 11,216, 80,219, 36, 1,202,168,130, 93,141,185, 83, 73,183, 62, 20,
+ 8,242, 75,181,173, 97,233,162, 23,176,189, 70,209, 97,131,146, 62, 44,247,246, 81,146,193, 84, 95,194,129, 52,224, 13, 35,141,
+249,211, 60,211, 0, 5,185, 81, 2, 95, 1, 92, 8,191,232,160,195, 43, 63, 19,202,139,126, 23, 28,234, 59, 36, 59, 88,242,104,
+112,219, 73, 32,223,137,166, 73, 56, 81,111, 19, 66, 89,138,139, 45, 84,228,144, 76, 23,191, 35,249, 41, 88,130,106, 44, 89, 5,
+136, 13, 71, 6,245, 64,245,183,167,242, 82, 30,124, 43,133,113,160, 23,194,133, 3, 11, 55, 11,113,163,120, 94,131,143,196, 48,
+245,208, 5, 23,165,183,166,187,145,174, 54, 2,230,132, 20,138,224,104,125, 85,181,175,202,187,170,180, 41, 54,255, 0, 97,203,
+251, 31,251,106,234,103, 84,116, 47,254,230,255, 0,251,235, 87, 80, 8,242,201,100,227,253,156,100,240, 30, 40,180,206,163,250,
+107,156,127, 15,251,184,255, 0,113,105,148, 40, 44,137, 36,214, 0,110, 22,244, 10, 16,150, 75, 30, 55, 62,177, 93,146, 78,177,
+236,252,230,129,198,168, 62,106,205,200,154, 46,236,239, 97, 22,212, 55, 83, 63,222,113, 61,215, 87,149, 86,201,185,204, 3, 75,
+113,138,220, 15, 11, 95,157, 38,108,187,127,255, 0, 76,112,113,176,231,121,102, 93,217,229,204, 73, 23, 73,142, 71,199, 42, 21,
+ 56,181,211, 74, 11, 31, 77,235,109,147,248,107,222,209,239,187,238,233,180,110, 24, 24,241,111, 47,149, 27,235,105, 12,158, 91,
+ 42, 94,169, 66, 58, 12, 21,172, 7, 35,236, 52,185, 63,131,155,138,118,196, 91, 78, 6,110, 60,155,131,229,140,188,185,166, 47,
+ 28, 90, 86, 54,141, 99,143, 66, 72,198,218,175,114, 5, 64, 7,185,123,239,117,192,126,221,237,188, 61,211,238, 76, 33,183, 98,
+203,155,184,172, 70,103, 5,226,247, 70,149, 12,218, 70,145,240,250,106,157,255, 0, 20,123,198,110,207, 89, 23,112, 49,231, 99,
+230,174, 60,153, 75, 28, 90,228,134, 72,154, 68, 12, 74, 27, 50,180,103,136,177, 53,177,238, 47,195,141,235, 38,125,155,121,216,
+114,224,135,120,219, 49, 96,198,153, 38,185,137,204, 11,167, 90, 18,141,126,101,108,203, 98, 40, 91,247, 98,119,175,115,108, 17,
+225,238, 89, 59,114,231,166, 96,200, 2, 32,209, 66,144,136,140,122, 47, 28, 36,151,214,196,241, 31, 45, 1, 77,219,221,225,221,
+216, 93,235,129,182,239,219,136,202,195,201,197, 73,101,137, 20,104, 17,190, 47,154, 70, 30,234,182,181,176,185,241,227, 89,174,
+226,238,110,234,238,237,147,112,221,178,242,146, 45,150, 44,200,160,143,110, 85, 81,102,112,242, 39,188, 23, 81,208, 23,137, 39,
+141,235,208,163,252, 55,222, 63,205,251,118,249, 60,216,173,129,141,139, 6, 46, 68, 65,228,234,183, 79, 23,202,190,129,210,211,
+107,242,187,114,172,255, 0,255, 0, 72,123,194, 60, 28,237,155, 27,114,195, 27,108,185, 9,145, 18, 72, 94,242, 52,122,145, 25,
+200,137,138, 29, 15,196, 11,241,249,232, 8,217,189,235,184,224, 97,118,191,110, 98,110,159,114, 97,125,221,143, 54,110,226,177,
+ 25,156, 23, 82, 84,104, 80,205,164,105, 31, 15,167,213, 81, 91,241, 51,187, 37,236,225, 42,231,152,243,160,205, 92,121, 50,150,
+ 56,181, 73, 12,145, 59,168,107,161,179, 43, 70,125,225, 99, 90,189,211,240,203,125, 9,176,238,123, 38,102, 60, 59,214,211,139,
+ 14, 44,235, 38,163, 12,134, 16,108,232, 90, 54,191, 6, 42, 67, 45,136,162,239,253,139,222,221,205,176, 69,133,185,228,237,203,
+158,185,131, 33, 68, 65,226,133, 33, 17, 24,244, 94, 56, 73, 47,173,137,226, 62, 90,128,208,246, 7,249,187, 41,114,247, 94,230,
+147,252, 54,116,120,210,237,112, 43, 43, 8,227, 42,229,181, 5,227,168,174,130,111, 89,159,197, 14,204,237,188, 77,187,119,238,
+172,236,137,134,231,148,241,140, 69, 46, 2,117, 44,168,177, 34,105,227,117, 82, 77,205,122,110,211,143, 38, 6,215,131,131, 49,
+ 13, 38, 54, 60, 80,200,201,114,165,163, 69, 66, 84,144, 13,174, 61, 21,231, 95,136, 29,141,222, 93,227,187, 71, 52, 25, 88, 48,
+237,152,130,216, 88,242,201, 45,238,108, 94, 73, 20, 64,203,169,136,229,196, 91,229,160, 52, 63,133,203,185, 47,100,109,191,121,
+ 22, 46, 67,156,113, 37,245, 8, 11,158,149,239,225,167,225,254,109,171, 45,248,161,217,157,183,139,183,110,221,215,157,145, 48,
+221, 50,158, 49,136,165,192, 78,165,149, 22, 36, 77, 60,110,170, 73,185,171,105,123,127,241, 41,187,106, 12, 8,183,188,116,222,
+ 35,202,105, 36,202, 86,101,140,227,116,244,164, 75,167, 31,193,184,219, 71,203, 85,253,245,216,157,237,222, 27,132, 18, 38,102,
+ 4,120, 24,104, 23, 22, 9, 36,152,146,246, 29, 73,100, 81,142,203,169,136,249,190, 90, 2, 11,237,253,193,159,248, 39,133,130,
+ 49,103,204,205,201,157, 6, 52, 72,141, 36,190, 88, 74,210, 71,112, 1, 33, 66,167, 2,120,105,181,119,224,254, 71,107,227,239,
+175,183, 29,175, 39,110,238, 88,241, 91, 30,115,145, 33,145, 36, 40, 80,207,104,217, 80,196,250,146,250,108,108, 46, 47, 91, 8,
+ 54, 95,196,136, 59, 78, 28, 72, 55,188, 63,243, 4, 25,157,110,185,254, 3, 98,116,140, 99, 28,131, 0,227,169,175,240,120,115,
+168, 61,141,248,125,187,109,125,195,149,221,253,213,157, 6, 86,235, 56,125, 9, 1,247, 67, 75,193,221,142,152,197,244,251,160,
+ 40,181, 1,233, 0, 2,250,145, 5,137,177,191,160, 83,132, 74, 79, 21, 28,104, 64,169, 7,237, 2,130,127, 39,162,139,212,142,
+252,197,189,162,160, 16,198,151,211,160, 91,211, 74, 98,140, 46,173, 3,230,164, 50,169, 58, 65, 95, 93,207,135,170,185,229, 64,
+190,235, 3,113,202,226,128,106,196,133, 67, 88,122,248, 83, 94, 36, 17,179,105, 0,128,127, 37, 59,168,128, 11,176,246, 94,133,
+ 59,163, 68, 64, 96,111,110, 31, 45, 80, 66, 99,115,126,116,132,223,219,234,174, 60, 15,166,144,240,227,252,149, 65,215,181, 42,
+ 33,115,194,154, 1,118, 0, 11,147,200, 84,228,141, 99, 26, 71,202,104, 1,232,208,163,215,206,184, 83,229, 60, 20,124,180,209,
+ 80, 11,114, 57, 11,215, 6,145,185, 45, 53,216,175, 47, 69, 18, 54,109, 4,213, 32,168, 90,246, 97,106, 89, 13,150,134,146,113,
+187,115,166,188,154,137, 3,151,133, 1,194,236,218,168,172, 66,169, 39,149, 48,123,170, 7,141, 53,216, 17, 99,198,177,197,154,
+224, 3, 83, 49, 38,137, 18,146, 75, 26,229, 0,211,238, 1,225,202,180,248, 4, 61,136, 84, 36,138,139,168,155,154, 44,132, 48,
+ 3,143,174,134, 20, 84, 74, 3, 31, 18,234, 55,110, 66,164,167, 43,208,151, 74,128, 45, 92,204, 2,112,190,163,244, 84,114,217,
+ 65, 75, 33, 47,195,144,166,146,199,135,166,152,104,209, 42,143,120,252,149,174, 8,129, 99, 93, 10, 41,238,218, 22,230,212, 61,
+ 67,244, 80,166,117,102,210, 57, 15,229,172, 68,178,140,190,162, 73,165, 85,212,193,105,130,164,192,160, 2,196,113, 39,133,109,
+184, 68, 12,160, 40, 1,124, 40,172,218, 22,228,240, 2,131,117,244,112,227, 67,200,145, 79,184,191, 41,174,105, 75, 40, 23, 98,
+238, 88,215,114, 3,141, 52,250,133, 26, 20, 82, 67, 48,224, 43,167, 4,100, 36, 17, 88, 92,243, 52,101, 54, 54,166,234, 95, 14,
+ 3,198,185,138, 0, 88,243, 2,176,155,159, 51, 77,104, 29, 72,225, 78,107, 90,228,242,168,169,144,128, 27,241, 62,138, 27,204,
+210, 30, 60, 23,209, 93, 12, 64,117,201, 13,117, 97, 97,224,106,195, 27,109,251, 21,151,171,252, 64, 30,218,121, 92, 95,211, 84,
+165,198,146,150,248,136,227, 90,200, 20,199, 4, 81, 55, 52, 69, 83,110, 92, 5,169, 93, 67,209, 16, 91, 6,220,122,159,244,127,
+ 77, 87,205,171,166,214,241,225, 87,179,113, 28, 43, 59, 46, 66, 94, 72,126,178,177, 95,152,218,171, 81, 4, 92, 16,134, 21, 17,
+235,235, 49, 58,110,170, 57,222,153,246, 58, 46, 36,144,191,138,240,250, 41, 4,141, 27, 44,134, 63,117, 70,155,158, 70,153, 19,
+ 22,185,183, 18,111, 89,147, 80, 88,244,215,200,117, 53,182,190,133,173,234,235,234,189,117, 45,207,146,211,127,236, 57,255, 0,
+199,181,117, 89, 16, 58, 65,252, 63,238,227,253,197,161,211,228,254,207,251,184,255, 0,113,105,148, 4, 92,155,107, 30,207,206,
+104, 7,149, 31, 39,248,131,217,249,205, 7,149, 80,100, 71,127,109,202,136,210, 64,234, 91, 7, 43,112,126, 32,133,242,141, 34,
+ 60, 36,254,177, 48,189,189,149,117, 30,255, 0,183, 72,254, 84,202, 23, 57, 98,234,201,137,198,234,194, 49, 51, 71,170,193, 75,
+133,107,149,231,110, 54,181, 99,242,255, 0, 15,183, 9,229,205,100,200,129, 83, 35,113, 19, 68,164,191,187,129, 33,201,108,140,
+118, 1, 62, 34,217,146, 21, 81,195,151, 26,179, 94,212,204, 29,195,145,184, 16,143,142,243,207,151, 12,207,145,145,117,105,241,
+188,175, 76, 98, 3,208, 86, 4,181,228,226, 74,240,183,160, 11,140, 46,233,218, 50, 98,219,140,147,174, 62, 70,229,143, 6, 84,
+ 56,239,123,170,228, 46,168,213,216, 13, 32,183, 16,183, 62,241, 28, 40,144,247, 71,111,207,143, 38, 92, 91,132,109, 4, 77, 26,
+ 60,158,240, 23,156,233,134,215, 23, 34, 67,240,145,192,248, 86,119, 15,181, 55,140, 56, 96,192,255, 0, 9, 46, 60,248, 91,118,
+ 46,116,238, 89,154, 38,193,141,163,144,192,140,158,249,107,142,155, 18,186, 79, 27, 87, 67,218,123,188,131, 26, 76,150,199,138,
+ 92, 65,180, 99,170,198,238,200,240,237,121, 7, 34, 73, 77,227, 4, 60,129,136, 84,240,241,106, 3, 67,141,221, 27, 6, 87, 80,
+193,158,140,176,194,249, 50,150, 12,129, 98,140,233,145,201,117, 95,128,240, 97,205,124,106,110, 46,231,183,230, 98, 73,157,141,
+ 48,124,120,181, 9, 90,204, 10, 20, 23,101,100, 96, 24, 16, 56,216,138,199, 73,217, 59,148,184,178, 99,153,224, 82,248,155,166,
+ 58,176,105, 63,137,155,158,153,208,114, 80,116,133, 75, 57, 28, 65,229,122,209,118,206,213, 62,213,141,149,230, 35, 88,101,203,
+201,108,150,140,100, 79,150,194,233, 28, 67,169, 62, 81, 46,237,104,199,160,120,122,234, 48, 15,108,239, 45,131,116,135,111,145,
+114, 4, 19,110, 41, 28,144,227,202, 8,113,213, 98,136,174, 64, 42, 11, 50,149, 94, 62,241,229,122, 94,228,238,237,191,182,228,
+ 16,100,198,242,204,216,153, 25,170,168, 56, 21,198,211,117,185,241,109, 70,222,206, 62, 21,157,219, 59, 51,122,196,196,199,219,
+167,108, 99, 11,141,181, 50,167,142, 87, 44,131,107,159,172,166, 53,104,151, 87, 89, 66,142, 36,105, 55,248,170,215,189,123,123,
+114,238, 14,159,221,207, 2,255, 0,130,207,194,147,204, 59,165,188,216,135, 67,174,136,228,190,150,135,136,225,192,252,149, 1,
+108,157,197,182,100, 73,142, 49, 39,142, 72,165,158, 92,105,100,102, 49,148,120, 97,108,150, 26, 93, 70,175,117, 65,240,247, 78,
+174, 85, 35,111,222,118,189,210, 41,103,192,201, 89,163,134,198, 83,102, 82,161,151, 90,181,156, 3,165,151,138,158, 68,114,172,
+252,157,177,185, 54,229, 38,114, 62, 59, 35,110, 89, 25,234,146,107, 96, 99,155,108,251,189, 85,212, 40,185,234,113, 97,127,135,
+198,252, 40,221,183,178,110, 91,110, 30,126, 62, 80,142, 36,157, 82, 60, 92,100,154, 76,133,136, 44,101, 24, 9,166, 69,147,167,
+171,224, 67,125, 43,243, 80, 22, 43,221, 93,186,240, 67, 58,231,198, 98,200, 36, 67, 32, 13,165,128,209,169,175,110, 8, 58,139,
+118, 62,232, 38,215,174, 78,229,219, 34,243,231, 49,252,178,225,102, 28, 11,181,216,201, 32,130, 60,162, 81, 80, 22,176, 73, 56,
+240,225, 98,121, 86,103, 63,178,115,242, 54,237,159, 8,244,167, 56,219, 82,109, 57,137,230,114,113,226, 4, 8,181, 75,254, 27,
+ 67, 78,158,227,125,155,218,252, 42, 70,229,218, 91,148,243,101,102, 68,209,202,100,220,165,205,142, 1,149, 62, 33,104,166,194,
+139, 10,207, 62, 48, 14,172,175, 30,162,162,225,151,133,252, 40, 13, 72,223,118, 84,202,199,193, 57,145,249,172,149, 70,137, 84,
+150, 4, 74, 11, 69,119, 80, 84,117, 2,157, 55, 62,247,133, 71, 61,209,219,250,178, 45,155, 31,248,107, 44,182, 13,196,153, 58,
+ 63,103,238,253,167,218,123,158,229,253,238, 28,235, 61, 39,105,238,235,153,181,136, 95, 31,200,237,171,182,244,144, 79, 52, 74,
+167, 10,235, 50,244,130, 73,212, 44,182,208,210, 49, 34,214,225,123,212,105,123, 55,120,153,167,107,227, 65, 26,203, 22, 68,120,
+152,249, 83,162, 75, 34,100,249,137, 26, 25, 52,245,112,196,136,126, 24,216,141,124,125,116, 6,229, 55, 29,189,182,255, 0,189,
+ 70, 68,127,119,172,109, 51,101, 19,238, 42, 37,245,150, 39,150,155, 27,250, 42,155, 51,188,182,152, 83,111,242,108, 51, 27,112,
+204, 24, 49, 1,170, 62,155,132, 50, 72,210, 6, 77, 67, 74,219,221, 34,230,227,195,141, 53, 59,117,191,201,179,118,222,184,160,
+200,153, 39, 35, 76,146,205, 18,203, 52,175,144, 53, 73, 57, 50,184,212,222,243, 30, 39,137,176,229, 81,211, 96,220, 39,207,139,
+118,201,104, 33,200,147,120, 77,207, 35, 25, 36,105, 17, 34,139, 1,182,245, 68,126,154,106,114,108,198,224, 15,155,136, 19,119,
+ 94,245,218,182,141,205,246,156,148,115, 60, 67, 12,200,225,108,161,115, 39,242,192,159,232,124, 71,212,120,113,169,239,220,253,
+187,208,198,203, 25,136,144,230, 23,242,238, 67, 11,136,216, 69, 33, 96, 69,208, 43,251,172, 90,214, 60, 13, 83,239,221,189,159,
+185,119, 4, 91,158, 44,152,227, 22,219,103, 88, 72,238,178, 41,219,243,155, 53,180,170,198,234,218,210, 66, 5,216,113, 30,187,
+138,108,206,197,207,154, 8, 96,102,135, 32, 58,238, 16, 79, 31,154,202,199,141, 83, 55, 53,179, 35,145,134, 54,134,152, 8,219,
+ 75, 70,214, 26,173,199,198,128,216,111, 91,195,109,146, 96, 99, 67,136,114,178,119, 25, 94, 8, 81, 93, 99, 0,199, 12,153, 12,
+ 89,159,135,195, 25,170,140,126,243,219,115,224,150,103,141,241, 35,199,135, 22,121, 26, 82, 15, 28,151,158, 21,137, 4,122,181,
+ 29,112, 16, 52,223, 85,197,170, 79,117,236,210,111,111,181, 75, 14, 38, 30,225, 30, 6, 68,147,100, 96,238, 12,201, 12,170,240,
+ 75, 2,241, 16,100,139,171, 72, 27,138,120, 86,105,123, 11,115,143, 18,104,206, 68,114,145,228, 30, 8, 99,154,104, 63,240,153,
+ 57, 83,182, 58,204,171,212,141, 86, 60,133,142, 39, 94, 62,239, 16, 40, 13, 4,253,207,176,227, 65, 14, 68,249,177,172, 83,163,
+ 75, 19,123,198,232,140, 17,219,221, 4,128,172,192, 53,249,120,208,231,238, 45,190, 61,227, 27,100,141,250,185, 83,202,240,200,
+171,202, 34,152,239,151,239,146, 45,240, 40,224, 15, 11,139,213, 52,253,139,159, 38,218,112,225,108,120, 93,246,189,199, 8,169,
+150,121, 20,100,103,100,199,148,167,169, 42,188,142,163, 75,106, 99,196,159,171,232,153, 47,106,110, 82,111, 38, 69,108,117,219,
+ 78,110, 78,113,159, 91,245,255, 0,197, 96,190, 23, 76, 69,163, 77,209,219, 85,245,241, 30,186,160,184,199,238, 62,222, 24,146,
+103, 46,124, 93, 8,217, 18, 73,141,192, 6, 83,104,173,112, 9, 87,250,172, 56, 55,133, 31,112,222, 27, 26, 44, 73, 48,177, 37,
+206,124,211,246, 41, 29,163, 80,154, 12,165,229,121,116,170, 13, 34,220,120,220,218,178,187,103,101,238, 56,248,177,197, 40,134,
+ 57,210,125,165,157,206, 86, 78, 81,146, 45,182,110,171,182,172,128,116,106,187,116,227, 85, 0,120,159, 70,135,186, 48, 55,125,
+203, 18, 44, 61,179,164, 96,146, 79,254, 99, 20,179,201,140,210,193,164,222, 20,154, 24,167,101,214,214,212, 64,190,155,128,120,
+212, 3,155,184, 34,159,102,195,222,112,113,166,202, 92,229,133,177,177,213, 64,144,156,130,186,117,146,116,160, 91,221,152,155,
+ 1,233,167,224,111,184,121, 91, 92,219,180,255, 0,224,225,198,105,162,202, 19, 17,246,111,143, 35, 67, 40,212,164,171, 13, 72,
+108, 71, 58,135,184,226,247, 36,155, 99,225,109,113,225,224, 73,210,199,142, 17, 28,210, 1, 26,134, 35, 34, 56,223,203,251,182,
+140, 5,137,186,126,187, 11, 10,112,218, 39,255, 0, 43,203,179,199,129,135, 11,244,204, 73,132,210,203, 62, 49, 91,220,235,155,
+167, 12,165,156, 92,150,211,125, 92,120,208, 7,110,230,216, 52, 67, 43,103, 34,172,197,209, 67, 6, 86, 12,133, 85,250,138,202,
+ 26, 61, 37,214,229,192,181,199,166,159, 47,113,237,144,206,216, 49, 79, 28,185,113,207, 14, 60,240,150, 41,160,207, 36,113,139,
+182,146, 53,125,168, 42,191, 90,177,249, 61,141,188,100,170,140,150,142,113, 52,121, 24,239, 4,185,185, 75,210,138,105, 35,116,
+235, 77, 0,137,242,244,170, 48,101,146,215,225,199,133,234,254,110,218,206,127, 61,166, 72, 71,153,223, 48,247,100,185,110, 16,
+ 99,249, 77,104,222,231,198,124,187, 88,114,229,198,169, 11, 47,243, 22,197,124,192,217,145,223, 8, 51,100, 18, 72, 10,177,182,
+135, 32,145,102,210,195, 73,211,123, 30, 28,232,219,126,126, 38,229, 9,202,194,144, 75, 16, 98,135,129, 82,174,191, 18,186,184,
+ 12,164,122, 8,172,110, 63,102,231,227,156,244,104,113,178, 75,195,147,143,142,217, 57, 57, 82,164,201,147,146, 50,116,180, 55,
+ 9,142, 52,168, 7,166, 9,213,239,123,111,251,127, 3,121,218,177,188,190,113,137,224,145,166,151,140,175, 52,232, 89,147,163,
+ 27, 74,241,167, 86,201,171, 83,183,189,123, 14, 35,141, 71,208,168,184,146, 70,191, 10, 17,145,253, 52,101, 94, 28,104,110,151,
+114, 47, 96, 40, 81,162, 87, 30, 53,221, 87,244,210,244,199,235, 10, 94,136,253,113, 84,131, 58,143,233,165, 18, 56,241,167,244,
+ 1, 36,106, 30,170,105,136,143, 17,243,208, 29,214,147,211, 92, 37,114,108, 79, 10,111, 77,169, 10,145,204, 80, 4,118, 11,109,
+ 47,170,252,248, 90,147,172,252,189, 20,145,128,206, 1,228,106, 72,199,140,208, 17,186,175, 73,173,141, 75,242,169,111, 93,119,
+148, 95, 77, 1, 23, 91, 83,196,242, 90,194,164,156, 52, 28,141, 39,148, 30,154,128, 7, 94, 79, 85, 55,168,231,152, 20, 97, 8,
+ 42, 71,162,230,245,221, 1,107,250, 41, 0, 30,182,167,137,156, 13, 32, 10, 89, 49,201,226,166,222, 21, 29,195,163,105,110,116,
+128, 79, 86,212, 5,255, 0,211,213, 64,150, 66, 78,145,200, 80,210, 66,139, 98,126, 46, 85,213, 21,117, 44,135,199, 68,149,172,
+236, 87,209,106,150, 48, 33, 60,122,205,243, 10,174, 70, 42,194,198,172,161,125, 75,235,173, 25,101, 76,219,207,105, 99, 79, 38,
+ 62, 71,112,224,195, 60, 76, 99,146, 41, 50, 96, 70, 87, 83,102, 87, 86,112, 84,131,206,245,118,123,215,178,236, 63,255, 0, 99,
+218,255, 0,254,119, 31,254,242,190,126,198,237,253,175, 59,122,239,173,247, 47,105,155,184,242,182,221,205,227,199,216,241,228,
+146, 54,101,159, 34, 80,249, 15,208,188,165, 83, 77,189,223,150,179,189,215,218,155, 70,219,223, 56,155, 22, 43, 62, 22, 22,106,
+226, 75, 54, 52,206, 30, 92, 54,201, 85,105, 49,157,252, 89, 47,204,212,118, 85,171,179,224,148,191,129, 85, 93,154,170,226,220,
+ 47,137,244,243,247,175,102,223,135,113,109,150,255, 0,214,227,255, 0,222, 85, 6, 95,113,246,129,150, 89, 87,184,182,226, 89,
+139, 0, 50,224, 60,205,255, 0, 94,190,124,238, 45,143,110,135,104,203,205,139,107,155,102,155, 7, 45,113, 97, 19, 72,206, 50,
+145,181, 93,128,147,235, 46,155,146,188, 43, 95,218,221,139,219,217,155, 95,110,193, 62,197,149,187,127,152, 98,150, 76,238,225,
+130,119, 72,246,230, 70,100,208, 17, 1,143,236,244,221,250,156,252, 61, 21,156, 89,235,154,157,213, 77, 67,141, 99,240,148,116,
+203,138,216,172,170,218,114,167, 73,252, 97,158,193,182,238,123,102,241, 9, 59,118,108, 57,145, 67,101,144, 99,202,146,217,143,
+ 17,168,198,205,106,152,177,128,186,163,184, 39,192,215,147,126, 8,121,124, 60,110,224,135,174,143, 26,101,199, 28,115, 92, 0,
+225, 85,198,161,127, 72,227, 94,186,172,178, 68, 25, 24, 48,113,117, 96,110, 8, 60,136, 34,180,115, 36, 95,252, 23,243,186, 63,
+252, 69,117, 47, 76,249,109, 54, 23,232, 91,255, 0,127,122,234, 1, 92,112,143,251,184,255, 0,113,105,180,231,250,159,221,199,
+251,139, 76,173, 2, 46, 79,198, 61,159,156,208, 13,239, 71,201, 30,248,246,126,115, 66,181, 1,230,178,247,142,253, 30, 6,118,
+102, 60,169,144,240, 38,230,210,199,229,216, 38, 47,148,150, 72,241,216,202, 61,198,215,160, 2,167,137,240,228,107, 72, 59,207,
+ 1,183,247,216, 21, 3,206,175, 36, 8, 18, 84,105,154, 88,160,243, 77,254, 30,250,194,105, 5, 67,158, 5,133,189,117, 57,187,
+107, 5,182, 28,174,222, 50, 77,229, 50,252,207, 82, 77, 75,212, 30,110, 89, 39,147, 73,211,167,131, 72,116,251,188,189, 52,159,
+229,204,113,159,147,151,230,242, 86, 12,150,146, 89, 48,149,148, 69,214,154, 33,143, 36,151, 11,172,221, 7, 5, 45, 96,120,218,
+128,168,143,190,241,219, 7, 51, 41,177, 66,201,135, 38, 52, 82, 40,158, 54,137, 60,215, 5,105,231, 75,172,125, 51,113, 39, 3,
+164,143, 26,112,239,220, 5,207,194,192,158, 1, 12,217,126, 93, 90, 55,154, 62,160,124,183,104,162,233, 70, 13,229, 91,128, 89,
+151,128, 82, 15,178, 70, 31,102,197,131,142,241, 99,110,121,137, 33, 76,120,196,160,194, 61,220, 64,201, 18,148, 88,130, 50,148,
+125, 46,172, 8, 60,249,241,162, 97,118,118, 22,221, 46, 59, 97,101,229, 69, 20, 66, 30,180, 10,241,133,157,177,221,228,137,165,
+ 34, 48, 71,189, 33,186,161, 85, 60, 5,173, 64, 72,221,183,217, 54,252,216,176,113,112, 37,207,152,194,249,115,164, 68, 6, 72,
+ 99,116,140,148, 82, 62,209,201,126, 10, 61, 28,234,151,111,239,137, 34,197,201,125,223, 24,129, 4, 91,134, 84,121, 17,178,129,
+ 36,120, 89,167, 19,167,160,219, 73,247,144, 92,158, 60, 79, 10,189,221,187,126, 45,215, 34, 44,161,149, 62, 28,171, 19, 99, 76,
+216,204,170,100,129,217, 36,104,201,101, 98,190,244, 98,204,150, 60,248,212, 79,242, 94,210,208,188, 45, 36,236,143, 6,110, 49,
+247,214,225,115,242, 6,108,140, 8, 79,137, 36, 81,163,213,206,245, 24, 1,143,222,209,103, 99, 68,118,220, 65,155,155, 38, 84,
+184, 98, 24, 39, 71,132,180, 48, 12,167,116,200, 80, 85,151,166,194,214, 31, 17,183,164,211,118, 46,236,125,211,121,204,217,222,
+ 22,243, 17,204,100, 16,176, 17,190, 54, 39,151,198,144, 25,193,185,214,101,152,160, 3,215,232,169,179,118,183, 90, 8,245,110,
+121,126,126, 41,228,200, 93,194,241,117, 3, 75, 17,199,145, 21, 58,125, 37, 77, 7,128, 11,192,241,231, 93,133,217,219,110, 6,
+ 92,121,248,210, 78, 50,163,155,175,215,102, 86,118, 83,143, 30, 35, 67, 35, 50, 18,209,178,196,172,111,199, 87, 27,212, 5,110,
+255, 0,220,251,214,221,190,182,217,137,140,141,142,163,107, 40,196,141, 78,115, 51, 27, 26, 69,226,120,106, 85,210, 61, 4, 95,
+198,147, 39,241, 27,110,193,194,198,202,204,128, 66,210,140,151,158, 23,158, 53, 42, 49, 39, 56,146,172, 58,244,245,156,186,146,
+170,163,136, 30, 21,115,185,118,198, 38,231,186, 71,186,205, 60,241,203, 24,197, 13, 20,101, 4,111,228,242, 60,228, 37,181,198,
+205,193,201, 6,204, 46, 15,176,212,115,217,184,136,144,174, 54,102, 86, 49, 79, 50,178,188, 76,129,229,139, 47, 32,230, 75, 19,
+ 49,143,221, 2, 67,238,178, 89,128,225,127, 26, 3,187,175,119,201,218,229,218, 98,131, 35,202,197,153,145, 36, 89, 19,172, 13,
+146,202,169,143, 44,203,166, 36, 4,155,180, 99,144,229, 84,221,189,220,251,182,237,184,227, 99,229,100,180, 72,248,216,115,175,
+148,193,147, 37, 36, 57, 18, 78,133,166,146, 37,145,113,195, 44, 74,125,242, 52,220,254,169,182,199, 47,110,131, 51, 55, 3, 54,
+ 86,113, 38,221, 43,205, 0, 82, 2,150,146, 25, 49,136,123,130, 72,211, 41,229,110, 53, 87,182,118,132, 59, 94, 89,201,219,119,
+ 76,220, 93,106,137, 60, 75,229,157, 37, 84,150,105,213, 91,171,140,236, 5,231,113,238, 17,195,215,198,128,162,206,239,125,202,
+ 9, 59,145,161,104, 58, 24,248,217,114,236,163, 69,200,125,185,151, 31, 35, 89,191,189,170, 71,184,245, 81,187,131,184,187,147,
+105,131,117,219,113,165,135, 39,115,197,151,109,242, 89, 38, 16,161,147,112,149,224,209, 36, 97,136, 44,173, 17,226, 45,192,138,
+179,159,240,235,183,102,219,225,193, 13, 44, 45, 20,115,195, 46,100, 93, 21,200,157,114, 81,163,148,228, 73,210, 58,201,213,171,
+151,196, 7,178,166,142,213,192,102,105, 50,243,114, 50,178,229,202,197,204,151, 50,102,136, 72,205,130,226, 88, 35,211, 12, 81,
+198,177,130, 56,133, 64,120,158, 55,227, 64,101, 51,187,255, 0,115,151, 39,117,200,218,204, 71,110,199,217, 31, 63, 16,148,212,
+124,210, 38, 36,247, 45,245,148, 38, 98,139,122,107,111,178,229, 73, 62, 20,249, 18,205,147,150, 81,155, 72,159, 10, 76, 25,125,
+213, 13,165, 33,200, 72,153,175,126, 13,107, 95,133,248, 85, 34,126, 31,246,236, 24,147, 97, 69, 60,201, 20,248,217,152,110, 21,
+227,191, 79, 54, 88,231,144,143,179,181,211,164,170,158,133, 28, 65,231, 87,240, 98, 52,120,115,226,229,238, 83,238, 61,112,202,
+210,228, 12,116,117, 86, 93, 37, 87,202, 67, 2,252,224,154, 2,139, 27,191, 49,242,113,167,145,112, 73,201,131, 39, 11, 19,203,
+197, 60, 82,141,121,238,177, 68,173, 34,251,170,232,196,135, 95,170, 71, 51, 80,119,110,254,203, 77,146,108,189,179, 3, 78,124,
+120,153,249, 82,135,117,100,128,225, 78,112,216,241, 3,171,121, 71, 1,195,221, 31, 37, 88,225,246, 94,219,137, 10, 68,217,185,
+ 83,244,219, 1,212,183, 72, 11,237,143,212,198, 22,142, 21,225,192, 7,244,250,143, 26, 76,174,197,218,242,241, 91, 9, 51,114,
+241,226,146, 60,200, 50, 26, 35, 25,121, 33,206,156,230, 75, 17, 47, 11,129,166, 83,238,144, 47,110, 28,104, 11,173,243,121,147,
+107,108, 60,108, 92, 54,205,205,206,145,210, 8, 21,196, 98,209, 70,211,200,204,236, 26,222,234, 88, 11,113, 36,123,106,153,123,
+214, 57,242,227,137,246,217,161,196,121, 78, 26,228, 76, 85, 92,101, 12, 95, 60,208,188, 63, 18,217, 84,173,255, 0, 88,122, 56,
+213,190,245,181, 67,187,249,105, 23, 42,124, 44,172, 71,103,199,202,198, 85,214,189, 72,218, 9, 22,210,163,169, 12,142,124, 56,
+ 27, 17, 85, 71,180,112, 99,156, 75, 6, 68,237, 20,100,205, 14, 44,204, 26, 63, 53,229,188,151,153,102, 41,212, 44, 99,231,118,
+181,201,107, 94,136, 17,112,251,226, 9,211, 21,167,219,223, 31,206, 13,190,104,238,234,246,199,220,217,226,130,102, 43,202,210,
+ 38,150, 95, 88,168,115,119,209,202,219, 51,242,240,240,101,134, 44, 92, 1,184, 62, 88,104,137, 72,229,235,244, 10, 35,143,125,
+159,161,126, 86,227, 65, 61,143,155, 23,107,201,182,172,227, 43,118,201,193,194,219,140,210,201,166, 44,117,196, 26,149,160, 49,
+196,172, 86, 57, 89,157,117, 13, 71,135, 30, 21,122,253,157,181, 62, 30,118, 14,185, 82, 28,252, 28,125,178, 80,140,163, 68, 56,
+203, 34, 70, 98,186, 27, 53,165, 55,189,199, 46, 21, 65, 27, 47,187,218, 45,193,240,226,193,127, 46, 50,159,110, 76,210,235,111,
+ 50,152,237,150,195,165,241,105, 10,182,191,167,242,211, 69,223, 27,188,157,191, 30, 72,193, 95,188,146, 45,158,105, 88,186,244,
+228,143,115,145, 99, 46,170, 45,164,146,172, 0,191, 11,131,233, 21, 59, 35,181, 51,114,123,144,101,137, 4, 91, 82,229, 28,246,
+ 69,154,250,164,108, 87,196,107, 64, 97,247, 92,150,185,110,169, 91, 14, 10, 9, 53, 56,118, 78,216, 48,159, 5, 50, 50, 81, 95,
+ 27,111,196, 18,134,143, 90,174,214,230, 76,105, 22,241,149,215,168,221,174,164, 31, 64,168, 4,238, 46,233, 27, 12,133,124,147,
+100,149,196,151,112,155, 76,138,129, 33,199,120,146, 79,136, 29, 77,246,188, 7,141, 41,238,146, 55, 55,192, 76, 23,120, 78, 83,
+237,240,229, 25, 21, 67,229,166, 57,203,233,104, 60, 66,149, 82,186,253, 62, 22,227, 71,221,251,107, 11,122,121, 78, 92,179, 3,
+ 46, 20,251,107,152,202, 15,178,200,104,221,223,138, 31,126,240,139,120,115,225, 79, 78,219,196, 27,160,220,250,210,148, 25, 7,
+ 53,112,206,142,136,202,104,124,169,156,123,186,239,211,191, 13, 86,185,189,175, 64,102,118,110,247,206,201,195,143, 43, 51, 28,
+203,155, 54, 62,218, 98,196,140,162, 68,210,231, 60,209,171, 43,251,204,160,244,245, 54,171,216, 14, 28,106,124,157,253,141, 22,
+225,139,181,229,226,182, 46, 84,207, 12, 50,193, 52,168,179, 44,185, 18,180, 17,136,162, 62,244,169,169, 46, 92,125, 82, 15,176,
+216,157,143,183, 97, 64,216,184,249,121, 90,213,113, 23, 26,119, 49, 51,195,228, 36,146,108,125, 0, 68,170,109,213, 42,117,131,
+117,245,241,169, 49,118,172, 24,121, 17,100,166,225,152, 77,226,108,181,103, 67,230,100,133,228,154, 55,153,180,106, 30,244,166,
+234,133, 84,139, 11, 88, 85, 0,119,174,226, 93,147, 50, 73, 37, 89, 36,138, 13,183, 43,112,120, 16, 32, 13,208,146, 4,248,155,
+222, 13,246,156, 60, 40,111,221,179,185, 56,145,237,140,251,146,230,203,130, 49, 58,171, 99,210,199, 92,198,147,171,166,223,195,
+112, 45,111,139,135, 46, 53, 59,118,237,188, 29,237,230,124,185, 37, 67, 54, 20,251,115,116,138,139, 69,144,209,200,236, 53, 35,
+123,224,196, 45,225,234,160,100,118,182, 46, 68,243,228, 99,229,228, 98,101, 75,148,249,195, 38, 35, 25,100,121, 49,215, 10, 68,
+ 64,232,203,164,198,131,152, 36, 55, 27,214,121,148,133,183,119,100,146,100, 77, 22, 92, 14,189,108,249, 49,113, 99,101, 17,188,
+ 73, 30,221, 30,226, 86,101, 63, 90,250,148,250,234, 44,253,229, 62, 88,219,219,109,197, 43, 30, 75,237, 47,147, 52,165, 79, 77,
+ 55, 57, 84, 8,130,253, 99,211,189,216,114, 36,124,147,165,236,236, 40,145, 60,190, 94, 76, 82, 46, 73,203, 89,181, 35,184,102,
+197, 27,123,173,229,141,238, 26, 37,230,110,117,113,189, 38, 63,101,224, 3,135,210,202,201,142, 28, 53,193, 86,136, 24,200,153,
+182,214, 15,140,242,150,140,155,248, 54,141, 55,249, 42,130, 26,119,246,214,239,184,170, 71,212, 56, 48,207,144,145,197, 42, 60,
+142,184,242,140,114,178, 34,155,196,206,236,186, 3,115, 83,122,181,237,237,195, 59,114,125,213,115,226, 88, 95, 15, 56,227, 36,
+ 74, 67,105, 65,143, 4,182,214, 62, 47,122, 83,199,209, 77, 94,206,195, 48,230,226, 62, 86, 75,225,228,164,209, 71,141,173, 85,
+ 32, 92,137, 12,239,210,210,128,150, 15,197, 75,234,176,225,233,188,237,163,104,109,168,101,152,167,151, 46, 92,201,252,214, 84,
+211,244,193, 50,152,227,132,233, 17, 36,106, 22,209, 14, 22,160, 39,232,247,173,106, 99, 1,126, 28, 42, 82, 47, 81, 11,218,204,
+ 57,138, 3, 1, 98,104, 4,143,128,163, 69,140,217, 74,120,133,183,137,160,170, 18, 11, 6,211, 92,131, 32, 11,197,123,122,170,
+144,146, 54,233, 98,251, 82,192,132,226,104,192,199,122,134, 95, 44, 45,155, 86,147,192,222,164, 1,126, 92, 61,116, 4,133, 49,
+241,189, 38,168,249,208,244,105, 22,190,163,206,150,220, 40, 2,218, 51,204,252,180,253, 49,223,159, 42,142,110,126, 78, 84,132,
+243,189, 1, 35,165, 29,188, 43,140, 9,202,244, 11,144,121,210,235, 55,160, 30,241,170,139, 3, 80,179, 35,247, 67,120,138, 59,
+ 92,181,133, 39, 76, 78,234,135,225,230,222,193, 68, 8,131, 30, 86, 17,144,140, 65,241, 0,211,186, 19,255, 0,178,127,217, 53,
+116,160, 0, 20, 11, 1,192, 1, 78, 0,122, 43,125,158, 36,146,162, 44, 89, 73,212,209, 53,135,134,147, 82, 96,134,101,184,233,
+ 48, 23,241, 83, 86, 72, 42, 66, 11,122,234, 42, 41,226, 59,151, 3,231,174,221,142, 5,239, 14,240,204,155,107, 66,112,247, 44,
+131, 54,251,145,187, 79,180, 69,140,178, 76,232,176, 51,227,130, 88,200,195,149, 98,123,227,105,158,126,243, 77,163,111,217, 27,
+110,205,200,233, 34, 98,166,100,153,254,102, 89,152,178,100, 38, 76,220, 88, 74, 29,127,210,245,109,185,247, 62, 62,205,220,189,
+231,181,111, 91, 79,222,251, 14,229,187,100, 60,208,117, 95, 29,150,120, 39,149,163,120,167, 64,214, 54,110, 34,220, 69, 66,159,
+123,223,247, 63,196, 13,163,115,242,240,118,254, 78, 56,198, 27, 76, 25,229,225,197,131, 27, 29,126,193,100,146, 80, 24,198, 85,
+ 77,219,198,245,146,145,123,175,179,187,159,104,219,211,112,220,183, 44,125,219, 19, 22, 81,137,144,216,153,103, 43,202, 78, 69,
+250, 19, 3,240, 30, 30, 28, 43,127,217,216, 88,242,246,150, 44, 9,219,113,234,220, 98, 61, 60, 41, 59,131, 43, 10,109,213,162,
+ 26,101,150, 28, 52, 26, 13,202,242, 63,201, 85,253,249, 30, 54, 47,106,238, 17,108,141,176,226, 65,157,147, 22,102,241, 22,223,
+186,156,252,156,137, 67, 16,139, 12,108,137,162, 52,105, 11, 88, 85, 39,111,247,219,227,197,179, 98,207,219, 63,123,119, 22,205,
+ 25,143,183,179, 4,147, 43, 42, 54,169, 99,234, 99, 70,167,173,163, 81,100,226, 63, 61, 68,146, 80,148, 47, 2,182,219,150,231,
+204,189,252, 49, 92, 89,112, 55,160,216,146,197, 12,155,148,105, 6, 36,110, 11, 70,204,146,232,132,153, 69,220,143,135,149,239,
+ 94,229,135,135,144,152,176, 33,199,149, 52,198,163, 67,130, 88, 88, 14, 12, 71, 2,107,199,127, 6,167,200, 56, 27,180,153, 44,
+203,151, 38,239,138,210,198, 85,181, 60,150,145,153, 25, 84,174,159,123,245,184, 3, 95, 67,141, 76,170,204, 10,177, 0,178, 92,
+ 27, 31, 69,197, 88, 33, 85,209,151,163,110,155, 95,165,107, 88,243,234,222,223, 53,117, 90,248,124,159,158,186,172, 16,163,127,
+169,253,220,127,184,180,218,115,255, 0,103,253,220,127,184,180,223, 26, 20,141,146, 61,241,236,252,244, 31, 85, 27, 35,227, 30,
+207,207, 65, 60, 79, 10, 3,205,159,188,183,232,242,159, 7, 84, 70, 69,118,219, 53,104, 23,251,193,243, 94, 24, 77,184,112,242,
+232, 30,223,206,191,133, 85,239,153,219,139,237, 73, 60, 57, 71, 22, 51,135,220,122,160,132, 20, 82,216,249,130, 53,123,234,190,
+174, 32,223,195,141,185,215,169,125,213,182,245, 12,135, 14, 14,161,152,101, 23,233, 38,174,184, 93, 2,123,218,253, 64,188, 53,
+115,181, 50,109,147,102,201,133, 34,200,219,177,165,142, 35, 43, 70,143, 4,108,170,103, 36,204, 85, 74,155, 25, 53, 29, 94,155,
+241,160, 43,182, 28,205,199, 44,111, 88,153, 89, 34, 73,176,179, 95, 22, 12,145, 26,169, 10,113,224,157, 73, 65,192,233,105,143,
+201,206,176,125,181,186,239,120,233,131,149,231,218, 97, 36, 59, 4, 89, 9, 42,135,214,185,153, 25, 16, 55,188,196,144,202,173,
+241, 14, 36,129,122,245, 88,241,224,133,164,120, 98, 88,218,103,234, 76,200,161, 75,190,144,154,220,143,137,180,168, 23, 62, 2,
+162,195,178,236,216,192,174, 62,221,141, 18,150, 73, 8, 72, 99, 81,174, 39, 50,198,222,234,243, 71, 98,202,124, 9,189, 1,136,
+ 93,255, 0,118,198,194,197,155, 26, 72,177,241, 22,124,227,149,210, 68,145,144,174,227, 36, 17,188,241, 51,117, 68, 44, 3, 2,
+241,139,235,245, 84,239,196, 13,199,113,143, 27, 63,111,196,201,242,176,166,211,149,155, 35, 5, 5,228,101,120,226, 84, 13,192,
+173,181,147,117,227,114, 62, 93, 67,108, 91, 52,205, 11,201,183,227, 59, 99,179, 73, 1, 49, 37,209,157,250,174,203,238,240, 37,
+253,243,252,238, 60,232,185,251, 78,215,186, 8,254,242,194,131, 48, 69,171,166, 50, 35, 89, 2,234, 22, 96, 3,131,206,220,104,
+ 12,110,118,245,186,226,201,187,253,220,201, 23, 71,116,149,103,232,172,111,146,208,199,131,143, 47, 81, 34,157,128,144, 43,184,
+234,105,247,180,114,227, 81,246,253,215,125,151,184, 37,197,199,220,212,166,231,159, 12,125, 78,150,164,142, 51,180,174,119,216,
+ 36,135,221, 4,128, 5,253,167,137, 53,184,202,216,246,108,208,203,151,129,143, 58,188,157,119, 18, 68,141,170, 93, 34, 51, 35,
+ 92,113, 98,138, 20,147,225,195,149, 60,109, 59,106,229,140,245,194,128,102, 11, 91, 36, 68,157, 81,165, 26, 37,251, 75,106,224,
+140, 84,113,228,109, 89, 96,243,183,221,247, 40, 19,239, 44, 44,132,195,147, 15,110,223,242,132, 97, 3, 69, 33,196,220, 87, 74,
+ 20,115,107,190,158, 45,207,137,181,175, 90, 24,251,143,117,202,221,147,111, 87, 72, 82, 93,210,124, 5,186, 2,201, 18,109,107,
+156,156,249,178,204,220,125, 92, 43, 65, 46,197,178, 76, 34,235,237,184,178,116, 89,158, 29, 80,198,116, 52,143,214,114,190,239,
+ 13, 79,239, 55,164,241, 52, 67,181,109, 99, 60,238,131, 6, 15, 62, 72, 62,115,164,157, 91,232, 49, 95,169,109, 87,208,116,251,
+ 56, 80, 30,111,219,123,206,239, 30,219, 4,105,144,173,149,147,141,177, 66,119, 9, 19, 92,136, 51, 38,201,141,139,234, 36, 57,
+ 80, 52,174,175,172,120,223,149, 76,205,238,174,224,139, 14,118,143, 34, 53,151, 3, 19,118,200,121,186, 42, 70, 67,109,185,177,
+226,198, 64,110, 10,178, 41, 58,173,242, 90,182,233,178,236,145, 65, 54, 52, 91,110, 44,112,100, 0,179,196,144,198,170,225, 89,
+157, 67,133, 81,123, 51,179, 15, 89, 38,164,195,179,237, 13, 0,128,224, 99,152,150, 22,197, 88,204, 72, 84, 64,228, 51,195, 98,
+ 62, 6, 42, 9, 94, 70,212, 4,244,232, 54,176,133, 91, 65,210,225,108,108,214, 6,198,220,141,141, 60, 32, 60, 0,224, 69, 14,
+ 56, 49,225,105, 90, 8,146, 38,157,250,179,148, 80,165,228,210,169,173,237,241, 54,148, 2,231,192, 81, 3,170,243, 62,170,128,
+ 93, 43,192, 91,242, 82, 42,106, 99,127, 15, 26, 83, 36,103,155, 15,158,154,178,165,216,234,160, 9,167,137, 30, 21,197,120, 89,
+ 71,182,134,211,131,123, 15,150,198,144, 76, 8,191, 27,242,181,141, 0, 69, 3,199,137,168,206,151, 99, 98, 64,240, 20,254,175,
+160, 27,251, 45, 67,212,196,125, 53, 80, 27,164,142, 26,169,202,151,226, 77, 39,190, 69,249, 3, 92, 25,215,151,207, 84, 13,241,
+106,112,166,139,146, 79,166,148, 27,115,168, 1, 94,230,254,154, 34,208,197, 60, 27, 80, 28,163,137, 62,179, 75, 37,136,165, 65,
+195,219, 92,252,141, 82, 17,153,236,164, 14,102,146, 31, 19, 76,127,136,209, 33,228,106, 26, 67,103,226, 69,233, 96, 54, 95,158,
+149,144,187,240, 32, 88,120,215, 70, 44,191, 41,167, 32, 74, 84,180,106, 60, 88,147,115,232, 2,163,160,144,131,161,244,132, 55,
+ 31, 47, 26, 52,173,252, 52, 31,171,115,242,240,166, 11,233,114, 7,196, 56,124,149, 10, 59, 22,247, 98,222, 60,253,180, 57, 20,
+ 11,129,233,165, 89, 5,248,120,219,133, 53,219,135, 31, 19, 64, 50,195, 65, 31,233,194,159, 14,107,192,186, 20, 2, 9,166,115,
+ 67,242,209,177,206, 30,128, 37, 7, 87,182,213,163, 35,223,113, 50, 71,210, 40, 1,126, 23,181, 42,248,159, 93, 58,100,193, 49,
+134,136,253,165,198,145,242,210, 88, 90,212, 3,137,244,126, 74, 80, 1, 81,226,124,105,182,244,213, 38,223,221,187, 94,126,255,
+ 0,153,219,145, 9, 99,206,195, 4,177,145, 84, 71, 38,157, 58,186, 76, 25,137,182,161,204, 10, 2,247,157, 32, 23, 62,175, 69,
+ 87,195,188,226,205,188,100,236,106,178, 12,172, 88, 83, 34, 73, 8, 29, 50,178, 18, 20, 41,213,170,252, 61, 21, 99,111,148,208,
+ 28, 71, 1, 73,107, 19, 81, 39,221,176,177,247, 44, 77,166, 87, 35, 47, 53,100,124,120,244,146, 10,196, 53, 57, 45,200, 90,166,
+144, 77, 0, 59,123,224,250, 46,127, 37, 74,198,136,170,251,223, 17,226,104, 81, 45,222,254, 2,141, 60,233,139,143, 46, 67,130,
+ 82, 20,105, 24, 47, 59, 40,212,109,123, 86,171,212,141,135, 11,235,167,128,195,149, 80,118,199,117,237,157,219,130,249,251,104,
+145, 22, 57, 12, 82, 67, 58,170,200,166,193,129, 33, 25,197,152, 30, 6,245, 51, 98,223,113, 55,236, 71,204,196, 89, 18, 56,230,
+151, 29,150, 96,161,181, 66,218, 24,141, 44,194,215, 28, 43,125,196,122,240, 45, 67, 91,194,136,142,124, 5, 48, 50,211,213,150,
+162,234, 88,234,120,142, 6, 79,110,227, 96,254, 36, 75,221, 88,103, 55,105,110,225, 49,206,169,110,164, 93, 89,164,140, 79, 23,
+136,100,213,126, 21,154,252, 68,155,101,207,252, 68,237,215,194,220,113,254,232, 56,123,122, 71,184,228, 42,207, 2,198,142,235,
+174,120,205,131, 90,222,242,181,189,118,175,114,155,240,219,177,119, 12,172,140,204,205,154, 25,167,202,145,166,200,114,100, 26,
+228,118, 46,206,192, 56, 23, 36,222,179,217,157,139,216,120,221,227,183,118,226,246,214, 25,198,205,196,159, 41,230, 45, 55, 80,
+ 52, 44, 20, 40,251, 77, 54, 55,172, 53, 12, 76, 30,101,248,152,219, 30,103,106,224,182, 38,126,223,151,186,109,249,211,193, 52,
+208,203,134,114,102,199, 60, 34,125, 24, 49,196,154, 15,196, 22,199, 72,225,123,222,182,221,191,184,246, 94, 22, 55,225,210,247,
+ 12,126, 87,116, 24, 41, 54,217,187,220, 42,134, 23,139,203, 78,223,168,218,248,106,224, 15,163,198,202, 63,194,237,141, 51,140,
+ 57, 93,181,134, 49, 58,242, 58,228, 6, 55,232,220,244,227,210, 37,189,237,111, 15,162,132,127, 14, 54,119,155, 14, 69,237, 92,
+ 89, 35,211, 50,229, 97,153,120,130, 27,236, 89, 28,203,111,132, 92,139,213,237,113, 34, 76,215,225,170, 35, 79,220, 50,105, 93,
+ 99,184, 33, 11, 41, 85,107, 2,242,220,113, 35,129,175,160,136, 39,144,175, 61,218,123, 94,125,144, 73,139,181,246,246, 62, 38,
+ 62, 67,199, 44,190, 94,114,138, 30, 50,250, 94,237, 41,123,217,171,208, 99, 93, 8,171,114,116,128, 46, 73, 39,128,241, 39,137,
+168, 81,120,250, 56,218,186,151,198,186,128,160,126, 81,255, 0,119, 31,238, 45, 55,215,122,123,253, 65,254,238, 63,220, 90,103,
+ 30, 84, 4,108,131,239,143,103,231,161, 94,137,146, 14,177,195,195,233,160,208, 15,184,184, 38,144, 48, 6,179,240,119, 70, 52,
+233,183, 57,136,198,155,134, 86,102, 26,179,176,180,103, 11,204,107,119, 63,170,222, 88,219,219, 71,143,185,182, 25,113, 95, 53,
+ 51, 99, 56,241, 60,113,187,144,195,222,154,221, 43, 2, 1, 34, 77, 67, 73, 28, 15,133, 8, 92, 22, 28, 69, 55,152,229, 85, 18,
+119, 70,195, 12,112, 77, 38,116,107, 30, 66,179,196,196, 55,195, 27,136,228,102, 22,186,132, 99,102,213,109, 62, 53, 46, 45,223,
+109,150,117,197,143, 37, 90,103,150, 92,117,140, 94,230, 88, 6,169, 83,151,213, 20, 41, 56, 11,124,181,195,215, 84,144,247, 86,
+219, 46,118,110,214,204, 98,204,196,153,224, 72,155,251, 83, 28, 9,148,197, 13,180,143,117,207, 2,111,238,154,126, 23,115,109,
+ 89,176,109,172,243, 8, 50, 55, 60,120, 50, 97,198,126, 44,171,144,186,227, 87, 96, 52,130,220, 66,220,251,196, 27, 80,133,200,
+ 52,241,106,165, 78,230,216, 29,178, 85,115,163, 39, 18, 57,103,200, 99,168, 5,142, 6,233,202,218,136,177,208,220, 26,220,170,
+ 54, 23,117,225,110, 19, 20,199, 1, 98, 92,201, 48, 76,146, 54,130,198, 44, 81,154,206,145,178,234, 60, 26,197, 77,136,177, 53,
+ 25, 77, 17,181,117,174, 42,142, 62,235,216, 37,198,159, 50, 60,248,218, 12,113, 17,149,192,110, 89, 28, 33,210, 52,221,250,135,
+130,233,189,207, 14,116,252,110,229,219,243, 51, 48,113, 48, 91,204,166,116,121, 82, 38, 66, 31,117, 78, 27, 69, 28,136,192,216,
+223, 84,223,146,160, 45,200,162,197, 26, 91, 83,113, 38,135,113, 82, 64,210,162,192, 1, 80, 8,177,196, 15, 16, 61, 84, 72,146,
+ 59, 19,164,115,166,240,181,253, 28,169,241,128, 20, 27,250,248,208, 15, 85, 93, 92,128,164, 55,212, 0, 3, 79,137,165, 14,182,
+226,225,126, 90,107,203, 0,228,227,231,160, 28, 84, 1,207,136, 21, 29, 74,144,120, 94,198,158,102, 75, 29, 38,231,231,161,245,
+ 84, 15,132,220,122,141, 0,226, 71, 42, 1,226, 56, 41,191, 42,115, 74, 13,174, 13,169,165,199,175,230,170,129,192,176,240,229,
+235,164, 37,173, 97, 73,168, 88,240, 52,133,189, 3,133, 80, 32, 52,164,251,167,217, 77, 39,133, 35, 19,166,160, 16, 83,188, 41,
+ 5, 58,220, 40, 7,142, 0, 83,101, 54, 66,105,246,161,204, 46,150, 53, 72, 68, 0,187,112,241,169, 10,160, 92, 83, 33, 78, 55,
+249,169,110, 68,132,250,235, 60, 89,161,197,120,222,134,156,184,211,193, 37,141,254, 74,103,162,168, 15, 37,137, 45,232, 69,254,
+ 90, 34, 75, 26,176,140,248,155, 95,215,232,161,147,101, 18, 17,238,145,161,168, 68,190,128, 21, 69,143,189,175,209, 80,163,153,
+ 84, 22,101, 22,179,233, 4,122,133,205, 13,206,171, 81, 65, 83,101, 78, 43, 26,146, 91,210,205,206,132,214,181, 82, 28, 65,209,
+203,157, 13,147,136, 54,169,198,225, 0, 32, 17,106,105,210,109,238,213, 33, 16, 0, 37, 75,114,225,252,181, 52, 31,159,211, 81,
+ 9,188,227,195,209, 82,211,141,133, 0,235,138,243, 57, 54,172,140,204,158,225,221, 54,161,255, 0,206,182,125,212,229, 97, 0,
+ 56,186,244, 35, 18,192,127,155, 42,139, 91,196,215,166,233, 28, 7,141, 87,237,219, 54, 46,217,151,184,101,192,242, 52,155,148,
+195, 34,112,228, 21, 12, 20, 37,147, 74,173,133,135,141,232, 25,139,198,238, 8,179,119, 61,231,184,182,223,122,219, 4,121, 49,
+ 33,177, 43, 36,102,118, 49,183,173, 89,116,154,143, 38,201, 20, 61,140,189,212,153,121, 31,127, 12, 68,220,126,242, 51,201,175,
+168,192, 74, 99,211,175, 70,158, 58, 52,233,181,106,240, 59, 87,100,217,119, 61,199,113,198,215,171,116, 4,100, 98,185, 83, 10,
+134, 37,152, 70,186, 65, 1,137, 60, 46,106, 10,246, 70,218,113,215,110, 59,158,113,217,131,106,251,164,202,189, 27, 6,215,211,
+ 47,163,170, 99,191,213,213, 66, 20,187,158,213,135,190,119,119,109,100,102, 9,145,183, 76, 25,102,201, 88,230,146, 59, 58, 66,
+132, 4,210,195, 71,174,220,252,107,208,247, 28,172,125,191, 3, 39, 55, 45,202, 99,193, 19,203, 43, 47, 48,170, 9, 58,109,227,
+232,170,173,227,183, 54,237,230,124, 28,166,200,200,194,200,192,214, 49,231,194,147,162,225, 36, 1, 94, 59,233,111,116,129, 87,
+ 25, 88,120,251,142, 44,248, 89, 75,212,198,201,141,162,149, 15, 11,163,130,172, 46, 61, 70,136,167,150,178,228, 98,102,118,198,
+245,183,109,115,237, 88,217,155,158, 46, 48,204,200,206,146,108,140,152,114,111,194,104, 9,117, 80,200, 47,197,174, 43,213, 55,
+111,255, 0,108,205,254,226, 95,220, 53,157,131,240,247, 10, 49,183,140,141,219,114,201,135,106,200,139, 43, 2, 9,102, 67, 26,
+ 24, 13,209, 10,244,189,225,225,233,183, 0, 71, 26,213,205,142,153, 56,242,193, 33, 33,102, 70,141,138,243, 1,134,147,107,223,
+211, 91,170, 50,121,118,204, 63,203, 24, 61,185,221,208,112,219, 51,177, 49,176,119,240,182,210,188, 2, 65,150,223,208, 99,161,
+143,162,154,243,205, 15,103, 76,248,242,180,101,187,137,212,180,108, 86,234,217,134,226,235,224,107,209, 49,187,115,109,198,237,
+245,237,166, 86,159,111, 88, 14, 49, 19, 16, 93,144,130, 56,149, 10, 47,199,152, 21, 91,141,216,187, 44, 29,179, 47,106,117, 50,
+ 36,193,145,204,189,103,117,235,171,151, 18, 7, 87, 68, 80, 10,176,225,238,213,135,246, 0, 29,209, 60,241,247, 87,103,198,146,
+ 50, 36,185, 25, 66, 68, 82, 64, 96, 32,184,212, 7, 58,170,219, 59,127, 23,185,119,190,235,139,118,200,203,150, 40, 51, 4, 88,
+208,174, 76,201, 28,122,162, 13,173, 81, 29, 65, 32,158, 0,220, 15, 69, 95, 98,246, 62, 50,110, 59,126,235,155,186,238, 27,134,
+102,218,206,216,237,147, 50, 50, 89,215, 65, 82,130, 48, 57,120,142, 39,196,213,214,215,176,226,109,121,155,150,110, 59,200,242,
+110,147, 12,140,133,144,169, 85,112,161, 45, 30,149, 82, 5,135,137, 53,123,103, 88, 7,150, 97,237, 75,159,248, 89,254,111,202,
+207,206,125,247, 26, 41, 37,196,203,243, 83, 14,151,150,157,225, 68,141, 21,194, 1,161, 56,155, 94,252,111, 90,173,223, 3, 27,
+184,251,211,181,224,220,218, 86,138,125,162,105,103, 16,203, 36, 5,207,217,177, 12,208, 50, 54,146, 79, 32,107, 67,135,217, 91,
+102, 63,105, 55,102,164,179,157,185,163,146, 35, 49,100,235,233,150, 70,153,189,238,158,139,234,110, 30,229, 27,114,236,172, 61,
+203, 43,111,206,139,113,206,219,242,182,220, 99,135, 4,216,114, 68,140, 99,107, 95, 95, 82, 25, 56,157, 62, 22,172, 52, 77, 12,
+150, 60,179,246,150,243,221,123, 54,213, 52,217, 91,102,221,181,253,235,139,141, 60,141, 49,198,152, 43,183, 65, 26, 66,205,165,
+237,170,196,213, 6, 22,211,221,249,155, 38, 6,251,178,108,249,207,220, 82,172, 57,137,190, 73,184,193,162,109,100, 72,232,240,
+ 54, 64, 29, 38, 66, 84, 38,145,111, 31, 26,245,173,151,181,118,157,142, 28,164,198, 71,158, 92,243,171, 63, 47, 45,204,243,228,
+ 27,105,251,105, 31,152, 0,240, 28,170,159, 31,240,227, 23, 11,252, 54, 14,245,186, 98,237, 26,181,141,162, 44,133, 16, 11,182,
+163, 26,177, 67, 32,140,248,174,175,150,164,233, 3, 82,150, 93,171,252,195,248,147,155, 6,229,145,147, 30, 46, 22, 22, 14, 88,
+192,138, 98, 34,105,131,146, 4,128,112,101, 22, 55, 3,157,122, 70,182,240,170,200,182, 28, 76,125,251, 47,184, 81,228, 57,121,
+144, 69,141, 44,108, 87,164, 18, 18, 74,149, 26,117, 95,143, 31,122,172,109,233, 53, 80,139,114, 31,169,191, 37,255, 0, 45,117,
+ 37,133,185,248,126,122,234,165,215,236, 41,158,222,225,255, 0,119, 31,238, 45, 54,156,255, 0,217,143,247,113,254,226,210, 92,
+ 86, 77, 17, 50,126, 49,195,195,243,154, 8,181,252, 40,249, 39,223, 30,207,166,128, 69,205, 1,137,197,236,118,197,147,111,204,
+134, 44, 40,247, 44,124,189,199, 35, 47, 49, 80,117, 36,143, 45,114,214, 5, 46, 99,212,250,122,241,234, 86,225,195,133,248, 85,
+103,249,111,184,118,252, 62,172,177, 38, 78, 84,249,123, 51, 20, 73,166,156,235,196,200, 94,172,142, 90, 47,114, 47,173,238,139,
+ 34,248,112,175, 73,181,185, 82,112,189, 1,230,217, 61,181,191, 25, 91, 10, 56, 34, 51,110,123,126,240,153, 82,179, 73,229,241,
+219,114,204,138, 93, 11, 32,140,234,100, 87,184, 82, 6,173, 38,173,182,109,165,211,189,119, 60,196, 15,247,126, 44, 96, 66,206,
+140,128,229,228, 36, 49,100, 50, 22, 0, 53,147, 17, 46, 71, 15,124,214,206,222,138,235, 30,116, 6, 61,251, 99,118,151,119,154,
+ 70,104, 23, 1,247, 25, 55, 88,229, 87,115, 53,219, 3,238,245,133,144,198, 20,123,199, 81, 33,143, 10,137,135,217, 27,134, 62,
+ 78,213,214,233, 79, 30, 52, 27, 90,100, 63,153,201,141, 35,151,109, 30,241, 76,120,244, 71, 62,178, 20,163, 73,240,241,225,225,
+ 91,187,154,235,241,189, 1,135,147,177,247, 57, 49,100,129,166,199, 86,108, 77,210, 5, 55,114, 58,153,185,233,159, 5,198,129,
+238,133, 75, 63,160,242,189, 30, 14,217,222, 37,205, 27,134, 95,150,133,228,220,178, 51,222, 24,229,121, 52,199, 54,219,247,122,
+ 38,163, 18, 93,132,156, 79, 11, 91,230,173,149,238,107,135, 31, 69, 1,231,210,246,206,229,179,109,177,230, 57,138,105, 48, 49,
+182, 56,214, 56,132,210, 6,151,108,105, 4,218,132,113, 52,130, 51,213,184,101, 70, 35,153, 94, 21,103,218, 91, 94, 96, 76,125,
+211, 51, 25, 35,144,205,186,201,118,215, 27,170,230,229,172,200, 82, 25, 19, 85,157, 99,191,188, 84,129,110, 28,120,107,184,129,
+ 93,126, 21,144,113,248,111, 69,211,233,102,246, 92,208,197,136, 3,217, 69, 35,143, 10,128, 78,154,158,124,125, 68,211,196,104,
+120,105,231, 72, 1,231,107,122,233,196,248,208, 8,218, 20, 90,213,214, 26, 71,128,229, 77, 54, 96, 46,111,198,156,206,171,200,
+139,250, 56, 80, 15, 0,120,240,174, 38,212,195, 42, 88, 29, 87, 62,138,103, 80, 30, 96,252,198,168, 28, 91,133,188, 47, 77,186,
+240,227, 77,115,168,124, 36, 15, 73,164,176,244, 80, 11,117,244,210, 93, 88,219,198,147,147, 10,119, 11,131,227, 84, 28, 64,166,
+ 73,193, 61,166,156, 79, 26,100,156,128,245,212, 2, 14,116,227,232,255, 0, 78,116,209,206,158, 15,188, 7,178,132, 9, 65,159,
+149,168,164,218,163,200,110, 69, 80, 57, 56, 10, 22,177,174,199,198,136, 77,150,212, 52, 80,120,145,122,137, 26, 99,174, 61,226,
+ 41,158, 2,244,192,193,110,160, 88, 83,217,125,219, 81,132, 76,141,128, 86, 70,226, 13,175, 75, 36, 72, 99,210, 47,167,194,163,
+172,150, 22,183,250, 1, 93,215, 60,129, 53, 32,163,155, 74,174,132,224, 40, 36,220,251, 41,197,129, 94,116,141, 96, 46, 61, 6,
+169, 7,199, 40,152, 30, 22,183, 58,236, 56,186,165,245, 19,111, 14, 62,218,102, 48,210,141,127, 31,162,165,225,170, 32,109, 0,
+241, 2,247,244,213, 32,214,193,179,171,171, 94,222,159,101, 16,192,227,194,244,118,107, 47, 15, 10, 98, 73,113,168,139, 95,194,
+130, 65, 21,101,231, 72,190,174, 52,175, 56,109, 33, 79, 6, 54, 52,171, 97,202,128,174,203,254, 49,160, 14,116,124,145,121,218,
+220,169, 21, 13,239, 64, 42,196,229,194,113, 7,135, 47, 69, 91, 66,129, 64, 3,194,128,170, 12,165,253,131,230,169,113,138,168,
+ 15, 35,194,150,148, 11,155, 83,202,214,209,134,198,113, 52,161,105,109,111, 26,122, 94,180,132,200,208, 8,229, 69, 82,124,105,
+192, 19,225, 68, 84, 30, 52,180,242, 19, 3,144,120,222,138, 13,169, 2,139, 83,128,227, 88, 13, 14, 13, 72,204,223, 86,157,106,
+235, 53, 77, 13, 32,101,143,136,166, 27,115,163,105,191, 58,105, 65, 85, 52, 81,156, 52,255, 0, 87,255, 0,189, 93, 79,210, 45,
+242,126,122,234,179,247,130,146, 75,253,159,247,113,254,226,211,125, 20,247, 28, 19,251,184,255, 0,113,105,167,149, 96, 17,114,
+127,138, 61,159,158,133,107,122,168,185, 54,214, 61,148, 47,147,229,160, 35, 67,157,137,147,145, 62, 44, 19, 44,147, 99, 16, 39,
+141, 77,202, 19,224,222,186,146,214, 28,171,207,226,218, 37, 92,183,137, 83, 37, 32,159,123,145,102,211, 36,192, 54, 58,197,169,
+ 75, 29, 95, 9, 99,197,188,125, 52,237,171, 15,114,198,201,218,230,139,204,245,100,151,112,138, 99, 51,202,201,211,141, 24, 99,
+ 43,135, 36, 5,186,139,122,107,209,108, 21,134,213,249, 78,171,193,191,192,242,215,113,121, 74,212,231, 26, 63, 20,191, 19,121,
+126, 52, 35,149, 0,202,242, 93, 65,230, 76,125, 97, 23,214,233,134,209,171,217,115,106,243,181, 27,175,150,199,251,171,207,125,
+241,229,242,190,247,234,245,173,171, 67,105,254, 39,185,175, 95,240,244, 85,183,109,195,140,123,141, 38,193, 76,163,142, 54,205,
+ 19, 73,146,178,219,174,101,141,153, 67, 79,245,173,204, 14, 30,138, 61,186, 73,183,105,132,249,116,235,231,200, 87,114,237,106,
+165, 88,150,150,175,175, 79, 46,125, 13,167, 46, 20,158,218,204,100,109,249, 83,101,100,206,233,146, 73,221, 34,142, 50,175, 42,
+143, 42, 98,137,100,208, 20,129,160,221,181, 17,249,168,120,254,115,109,205,110,164,121, 62, 76, 46,124, 56,234,169, 44,190,241,
+150, 39,135,128, 12,120,168,109, 4,214, 61, 36,214,150,214, 56,124, 36,223,172,211,214,176,166, 38,124, 96,214,219,215, 67,138,
+ 88,230,143,169, 11, 7, 75,178,220,122, 85,138, 48,249, 8,172,111, 75, 62, 33,182, 75, 42,228,205,145,229, 48,129,199,101,157,
+ 92, 72,160,117, 12,115, 70, 74, 43,127,180, 89, 87,229,181, 29, 86,126,156, 31,123,199,150,248,131,207,144,177, 9,139,245, 78,
+ 75,116,117, 8,189,238, 49,127, 12,158, 31,146,171,194,191,154,117,229,248, 17,103,127,203, 26,115,126, 92, 95, 35, 91, 44,209,
+ 99,194,249, 25, 14, 35,138, 37, 47, 35,177,176, 10, 57,147, 77,197,202,198,205,135,175,138,226, 72,238, 84,155, 16, 67, 47, 2,
+172, 26,196, 17,232, 53, 81,186, 46, 67,246,242,192,177,202,122,201, 20, 89, 38, 69,235, 77, 28, 79,165,100,145,149, 62, 57, 16,
+113,225,227,198,129,218, 82,102,167,155,196,203,142, 67, 26,183, 83, 31, 45,226,145, 14, 64,102,109, 83, 59, 73,245,207,186, 52,
+240,244,142, 21,135,141,118, 90,243,170,113, 30, 6,253, 87,234, 86,145,163, 83, 62, 38,145, 35,214,116,222,214, 23,162,116, 77,
+248,185,252,149,136, 72,247, 88,165,220, 19, 0,100,205,146,209,229, 90,114, 39,137,208,147,169, 21,245,151,130, 70,240,137,144,
+143,101,175, 82, 38, 19, 44,189,125,162, 60,212,219,161, 56, 82,101, 36,139, 62,178,201,146,166, 93, 9, 55,218, 49, 17, 95,169,
+164,113,246,222,175,161,253, 92,124, 63,111,129,159, 95,250,120,120,253,223,137,174, 40,165,149, 65, 39,210, 47, 68,232,196, 77,
+172, 79,168,154,200,199, 14,102,225,185,175, 82, 60,165,193,151,115,148,157, 66,104,129,199, 24, 32, 45,239,164,136,218, 81,227,
+192,154,100, 17,207, 18,224,174,236,153,141,133, 16,205,142, 36,140, 78,206, 36, 25, 37,113,250,157, 31,180,254, 0,251, 50,120,
+124,182,169,232,240,250,181,142, 9,107,207,242, 47,172,255, 0,151, 73,137,111, 78, 95,102,166,195, 20,226,101, 64,153, 24,197,
+ 94, 41, 5,209,199, 34, 57, 80,243, 50,113, 48, 99, 18,228,200,177, 33, 96,129,143,139, 49,176, 80, 7, 18,107, 54,145,110, 81,
+118,102, 28, 16, 36,177,204,162, 33,147, 19, 43,245,132, 38, 95,181, 5, 99, 43, 33, 58,121,133, 55,181,237, 81, 98,192,155, 38,
+ 12, 78,184,154, 88, 19,116, 15, 7,187, 52, 33, 33, 49,123,229, 3,200,210,116,245,242, 47,107,120,112,181, 85,138,178,219,182,
+138,205,120,232, 71,154,208,146,174,174,169,248, 75, 53,176,101, 98,228,205, 44, 56,242, 43,190, 57,211, 56, 95,170,214,248, 73,
+244,212,162, 53,112,181, 96,228,194,201,196,137,196, 41, 34, 98,201,185, 78,217, 97,196,242,222, 33,175,162,197, 35,113, 33,143,
+ 85,174, 87,159, 11,240,163, 71,214, 92,108, 20,222, 6,100,248, 43, 14, 79, 76, 71, 28,203, 39, 84,202, 4, 29, 69,141,158, 75,
+244,184, 70, 92,223,245,172,212,120,107,197, 91,236,212,139, 53,184, 90,186,196,204,233,196,215, 78,241,117, 6, 63, 80,117,130,
+235, 49,130, 53,105, 38,193,180,243,181,199, 58,102,149,189,174,107, 41,155,135, 36,185,109, 56, 76,232,164,155,106, 88,210,117,
+ 18, 75, 42,202,183,212,175,211, 34, 62,166,159, 11,139,159,135,141, 77,237,248,231, 56,217,168, 86, 68, 75,142,148,170, 38, 69,
+114, 83,222, 48,197,151,239,165,143, 49,114, 47,227,206,163,196,149,123,149,167,135, 35, 85,202,221,187, 93, 99,143, 63,192,191,
+208,188, 13,169,182, 0,139, 86, 30, 8,179,224,194,201,150, 3,144,210, 96, 71, 22, 95, 93,132,240, 9, 30, 7, 45, 36, 83, 69,
+144, 88,117, 30, 59,134, 40,196, 31,154,146,120,242,230,197,131,116,145,242, 36,108,225, 62, 76,120,218,114, 25, 2,200, 84,227,
+164,111,140, 75, 69, 40,141, 87, 73, 42, 71, 19,227, 91,244, 53,253, 92,227,134,179, 19,192,207,249, 14, 63, 70,177, 60,116,137,
+142, 38,219,171, 27,187,198,142,173, 36,118, 18, 40, 32,149, 36,106, 26,135,133,197,115,248, 86, 63, 39, 23, 54, 57, 55, 57, 49,
+224,200,142,108,131,137, 36,164,137,164, 6, 18, 16,100, 42,180,100, 6, 96,111,112,135, 85,175,166,157,139,137,153, 59,225,195,
+ 41,157,240, 91, 54, 82, 64, 73,161, 65, 15,150,114, 7,190,237, 39, 72,203,203, 93,184,240, 28, 45, 89,120, 84, 79,119, 41,225,
+225, 37, 89,156,199,103, 56,227,227, 6,180,124, 84,255, 0,237, 43, 29,139,135,145,143, 30, 28,178,174,104, 13, 14,100,121,102,
+ 54,153,165,208,172, 4, 32,113, 36, 54,145,238, 91,141, 74,238,179,184, 99,237,248,123,150,215,214,121,176,221, 89,161, 26,139,
+188,114, 47, 76,235, 81,197,152, 18, 15, 26,122, 75,186,181, 86,253, 77,169,229, 43, 65,235, 62,219, 89,215,244,164,225,113,135,
+169,169,115,194,163,155,106, 30,186,193,237, 27,103,112,230, 38,118,223,153, 54, 66,121, 12, 73, 33,197,152,187,175, 82,121,216,
+202,143,170,254,246,155,105,245, 84, 76, 15,243, 54,118,126, 33,203, 92,136,160,220,165,142, 73,239,212, 65, 18, 98,106, 14,190,
+ 26,122,150,249,107,127,227, 47,171,253,202,253, 63,249,251,140, 45,211,250,127,219,183,213,167,199,131,159,142,135,164,159, 26,
+ 12,217, 48, 98, 65, 38, 70, 76,139, 20, 49, 13, 82, 72,198,192, 15, 93,121,214,119,249,159, 11, 47, 40, 99,140,153, 97,219,100,
+148, 65, 99, 35,117, 83, 51, 80,143,211,171,167,113,236,245, 85,182,241, 4,146,118,190, 94,210, 19, 34,108,188, 8,160,234, 49,
+ 18,125,164,173, 98,197, 27,251, 65,206,252,197, 63,199, 73,210,110,154,179, 75, 78, 73,243,251, 81, 86,229,181,120,163, 78,169,
+181, 60,218,229,246, 51, 93, 12,177,101, 68,179,194, 67,197, 32, 13, 27,143, 16,124,104,205,114, 62, 65, 94,125,149,183,228,156,
+140,193, 31,155,251, 60,220, 88, 49,202,203, 63, 8, 25, 85,101,210,117,113, 4, 30, 45, 82,122, 89,120,240, 73, 4,254,105,118,
+152,183,137, 18,112,134, 83, 32,196,208, 10, 89,150,242, 24,181,158, 54,168,240, 39, 13, 95,143, 40,248,252,202,183, 22, 83, 52,
+225,206,116,227, 29, 56,104,109,175,195,228, 52, 12,124,172,124,184, 87, 35, 26, 65, 44, 46, 24, 43,175, 34, 84,149, 63, 49, 21,
+137,135, 81,201, 67,184,121,239,242,224,155, 47,201, 91,175,174,214, 78,142,189, 31,107,167,227,233,234,171,158,215,103,198,216,
+118,237,189,225,157, 51, 50, 23, 41,161,234,198,214, 82,178,202,235,214,107, 89,111,195,159, 58,151,193,219, 89,153,114,185,105,
+ 26,207,197, 70,166,169,185,238,188, 58,246,168,124,245,159,166, 62, 14,116,234,104,133,175,199,149, 61,173,167,135,162,213,230,
+242, 38,225,228,161,242, 35, 63,239, 79, 47,149,247,200,144, 79,109, 90, 27, 71,197,238,234,215,240,104,171, 60,204, 17,131,247,
+ 84, 57, 35, 50, 93,189,225,146, 76,129, 11,204,242,182, 83, 42, 89,164,233,157,126,157, 62, 0,213,123,116,154, 93,250,185,210,
+ 53,250,126, 60,249, 25, 91,166,211,125,154, 40,214,116,250,190, 28,185,155,129,194, 50,127,211,149, 19,111,102, 49,177, 60,125,
+239,205, 89,238,205,150, 73,123, 87, 22, 73,157,228,144,245,193,121, 73,103, 32, 77, 32, 26,137,245, 86,135, 3,132, 77,235,106,
+229,106,246,222,213,227,218,218,249, 29,169,110,250, 86,241, 29,201, 56,243, 37, 31, 10, 67, 93,242,215, 86, 74, 70,149, 66,188,
+ 96,114,189,205, 16, 92,159, 85, 50,127,227, 70,190,218, 40, 6,220, 57,208,164, 9,173,214,111, 69,255, 0, 53, 62, 53,212,109,
+236, 38,153, 37,204,173,237,169, 17, 45,184,248,208, 18, 35, 21, 45, 5,133, 70,136, 84,181, 28,133,105, 34, 14, 28, 5,252,105,
+ 46,125, 52,164,138,235, 95,149,110,168,207, 19,184,120,154,122, 56, 94, 84, 50,181,192, 85,102, 26,105,201, 36, 57, 62, 52, 69,
+ 62,186,142,182, 20,224,220,106,242, 52,154,230, 73, 12,104,128,208, 87,136,231, 78,210,195,141,101,164, 94,233, 14,172, 41,218,
+199,133, 70,212,105,193,141,101,212,168, 53,239,206,147,221, 20,208,105, 24,250, 41, 6,154, 67,184, 91,228,252,245,212,219,157,
+ 63,213,252,245,212,143,188,144,138,103, 60, 19,251,184,255, 0,113,105,183,167, 56,248, 63,187,142,199,250,139, 77, 3,159,162,
+178, 82, 54, 65,247,199, 31, 10, 9,226, 42, 91,195,212, 55,213,111, 11,115,252,244,209,139,252,251,252,148, 4, 91, 26, 91,112,
+181,234, 79,149, 22,248,190, 91, 87, 12, 95,231,126, 79,211, 64, 70, 3,215, 92, 42, 79,150, 32,252,127,147,244,215,121, 97,250,
+255, 0,146,128,142, 88, 17,233, 52,130,252,237, 82, 6, 47, 31,143,242,126,154, 81,142, 57, 22,252,148, 0, 62, 65, 73,198,220,
+232,254, 95,249,223,147,244,215,121, 99,127,139,242,126,154, 0, 3,143, 26,117,133,175, 70,242,246,250,255, 0,146,151,203,255,
+ 0, 59,242, 84, 96, 18, 7, 0,133,181,185,241,167,251,228,139,176,191,141,133, 26, 60,114, 20,141, 92,205,249,126,154,119,151,
+254,119, 31,101,100, 0,233,241,212,206,111,242,114,165, 17, 90,254,241,227,235,163,244,180,143,138,254,209, 74, 34, 35,155, 95,
+209,194,168, 35, 24,215, 87, 30, 86,228, 77, 41, 68, 0, 88, 15,154,140, 34, 3, 85,219,159,171,244,210,244, 1,225,171,215,202,
+128, 6,145,123, 88, 87, 48, 94, 70,212,102,137,124, 92, 95,217,250,105,157, 52,225,239,106,244,112,227, 64, 71, 47,102, 60, 47,
+ 77,214, 91,128, 31, 61, 28,192, 9, 39, 95,228,166,136, 0, 31, 23,228,253, 52, 4, 60,172, 56,115,160,124, 92,165, 15, 12,159,
+ 28,119, 32, 17,232, 58, 72,225,234,167,133, 9,100, 64, 2,168, 10, 0, 22, 0, 15, 0, 42, 88,199, 39,147,126, 79,211, 73,229,
+184,159,123,242, 85,151, 16, 72, 83, 49,169, 30,228, 26, 99, 18, 79, 26,151,229,175,245,191, 39,233,166, 54, 53,201,247,191, 39,
+233,168, 82, 58,243,166, 76, 72, 97, 97,194,223,203, 83, 6, 53,190,183,228,253, 52,162, 0, 26,197,185,143, 69, 1, 6, 57,116,
+130, 43,153,245,113,244,212,246,195,136,241, 39,242, 84,102,195, 26,236,175,195,217,250,104, 0,128, 72,249,105,207,197, 26,222,
+ 0,212,159, 41, 96, 61,255, 0, 31, 71,233,164,147, 23,220,111,126,215, 30,143,211, 66,149,177,113,113,122, 59,143,116,159, 93,
+ 26, 60, 45, 50, 15,127,194,252,189, 94,218, 43, 97,234, 83,102,176,191,163,244,209,132, 70,198,107, 49, 7,145, 31,201, 82,137,
+ 54,165,135, 11, 72,185,126, 62,207,211, 69,242,220,126, 59,252,159,166,163, 41, 22, 66,124, 42,179,114,218,176, 55, 46,147,102,
+ 68, 93,225,191, 74, 69,119,141,151, 85,131, 0,209,178,181,143,141, 94, 62, 63,243,173,126, 28,191, 77, 71,147, 18,246, 26,252,
+125, 31,166,173, 91, 78, 83,105,245, 68,178, 86, 81,100,154,232,200,184,248,208, 98,226,166, 22, 36, 98, 40, 99, 26, 99, 69,228,
+ 5, 74,128,116, 96, 98,220,108,121, 10,120,197,183,215,252,159,166,145,224,184, 42, 31,159,171,244,213,158,108,144,150,139, 72,
+ 26, 51, 96, 60, 44, 65,245,211,142, 86, 57, 82, 9, 34,254, 53, 23,201,155,155, 63,228,253, 53,222, 77,191, 95,242,126,154, 1,
+ 81,195,204,130,250,172, 13,205, 77, 83,244,208, 49,112,136,125,122,185,122,191, 77, 76,242,252,111,171,242, 80,165,113, 79,182,
+107,248, 31,229,163,168,229, 70,108,125, 76, 88,183, 63, 87,233,167,199,141,199,226,252,148, 32,232,215,133, 28,112, 90, 84,128,
+ 1,197,184, 14,116,133,146,246,226, 64,245, 15,166,180,154, 92, 73, 15,145,214,225, 92, 13,169, 65, 95, 95,204, 62,154,235, 41,
+244,252,195,233,171,222,186,152,250,250, 14, 12, 41,195,143, 42,104, 81,235,249,135,211, 68, 5, 71,129,249,135,211, 87,190,189,
+ 81, 98,221, 4,179, 82,133,227,202,148, 48, 30, 7,230, 31, 77, 56, 74, 63, 84,252,195,233,171,223, 94,161,213,244, 8,150, 20,
+112,252, 45, 81, 68,139,250,173,243, 15,166,158, 39, 65,245, 91,230, 31, 77, 71,106,245, 42,175,128,126, 39,194,148, 41,160,249,
+164,253, 86,249,135,211, 93,230,215,245, 91,230, 31, 77,103,185,117, 21, 86, 92, 80,123, 94,147, 77, 8,101,160,250,173,243, 15,
+166,184,229,199,250,141,243, 15,166,167,114,234, 91, 38,248, 6,211,252,159,158,186,133,230, 23, 78,171, 55,195,171,195,245,180,
+250,107,170,247, 46,164,135,246, 21,110, 7,185,126,102, 56,255, 0,113,105,156, 65,225, 69, 49, 59, 8,216, 21,183, 78, 62,110,
+160,252, 11,224, 72,164,232,191,243, 63,109, 63,214,168,104, 31, 62, 53,215, 28,127,146,137,209,123,243, 79,219, 79,166,151,160,
+247,248,147,151, 31,125,127,214,160, 60,195, 97, 92,188,189,239,182,218,108,166,120, 81,251,134, 65, 11,141, 94,252, 59,135, 73,
+ 91, 81, 60,244, 73,165,127, 84, 14, 28,232,219,191,119,239,248, 25,219,198,221, 9,140,205,181,174,102, 91, 51,165,212, 98,152,
+177,142, 27, 55,177,242, 90,254,158,153,173,190, 44, 59, 31, 90, 15, 36,112,122,191,226,188,167, 69,241,245,255, 0, 20,121,222,
+150,134,191,241,109,213,183,214,248,184,212, 72, 54,173,167, 31,120,222, 51,178,115, 96,200,206,202,130, 33,151,143, 60,184,246,
+135, 13, 4,154, 21,163, 22, 34, 50, 89,238,207,207,228,160, 51,171,220,123,222, 38,230, 54,140,137,211, 40, 67,184, 77,136,249,
+134, 37, 78,172,107,181, 29,201, 69,147,221, 12,146, 88, 27,120, 84,217, 55,205,210, 94,209,237,253,198, 57, 82, 28,237,227,238,
+200,230,200, 8, 10,198,115, 58,125, 87, 68,111,118,254,241, 10, 15,137,169,237,141,217, 35,106,129, 92,237, 63,116, 9,201,198,
+ 45, 46, 41,199,243, 22, 98,116, 22,125, 29, 75,106,191,141,175, 83,178, 32,216,219, 99, 85,200,242, 63,112,152,163, 8, 94, 92,
+113,137,209, 58,122, 58, 78,174,152, 95,135, 69,189, 86,168, 15, 60,197,223,247,236, 45,141,142, 46,106,171, 97, 99,111,123,164,
+146,203, 24,147,204,190, 38,225, 36,105, 0,214,222,234, 88,219,221, 55, 23, 91,122,238,241, 59,139,122,159,185,162,198,146, 85,
+ 92, 25, 55, 57,182,227,137,210, 26,130, 38,216,187,136, 99, 39,197,168, 73,195,217, 87, 79, 7,103, 54, 30,223,113,180, 12, 17,
+ 43,157,179,237,113, 68, 61,110,161,234,121,123, 48, 93, 93, 79,139, 79,214,231,198,167, 8,118,115,154, 52,121, 1,157,230, 94,
+218, 95, 31,173,230,250, 3, 95,214,213,213,242,252,254,182,143,230,208, 25,205,131, 19,112,219,123,168,237, 51,238, 47,151, 6,
+ 22,199,183,166,151, 91, 7,117,147, 34, 6,154,197,154,204,198, 45, 68,220,158, 54,191, 1, 84,143,222,221,194,153,111,129,170,
+ 35, 34,187,109, 65,180, 11,253,227, 38,116,144, 64,109,195,135,150, 69,123,127, 58,252,133,122, 11,193,183, 29,218, 62,161,195,
+251,231,160,221, 43,188, 3, 43,203,234,247,180,251,221, 78,158,190,126, 23,168,135, 31,183,124,193,212,118,223, 49,231, 87, 85,
+228,198,215,231,250,103, 69,253,235,249,142,157,237,245,180,250,168, 12,100,189,231,190, 67, 14,249, 58, 74,179, 38, 62,223,151,
+157,133, 43, 66,137, 16,147, 27, 33,177,192,137, 67,153, 26, 63, 3,213, 0,150, 6,220, 40,243,238, 59,222, 70,227,131,139, 54,
+229,255, 0,131,238, 67,130,210, 36,106,157, 88, 78,220,114,194,186,169,177, 0,187, 45,189,135,152,171,244,198,236,133,108,189,
+ 13,179,106, 43, 57,206,251, 92, 50,116,106, 30,103,173,239,124, 58,173,212,191, 11,243,169,185, 56,253,187,103,243,135,109,183,
+156, 78,167, 86, 76,111,252,126,132,233,234,212,223,199,209,167, 79,214,181,168, 12,206,247,185,239,120, 93,223, 60, 56, 25,166,
+ 56,178,113,182,172,116, 70, 64,233, 7,154,205,158, 6,148, 41, 54, 47,238,216, 19,204,176, 7,144, 21,113,139,188,111,115,118,
+142,126,106,201,142, 55, 60, 73,179, 48,224,202,156,172, 48,202,248,249, 50, 98,199, 39,188, 66, 13,122, 7,142,157, 94,170,153,
+186, 99,118,217,200, 97,188,157,183,205, 28,114, 27,205, 75,140, 37,242,218,197,255, 0,136,218,186,122,237,234,213,235,169,139,
+ 30,210,187, 33, 86, 24, 45,176,244, 72,185,146, 15, 41,208,246,234,233,232,252,149, 1,128,200,239, 78,232, 88,142, 62, 32,121,
+242, 48,227,203,159, 33,102,143, 22, 7, 7, 30, 72,163, 88,115, 90,105,226,137, 85,122,135, 83, 64, 91,154,145,227, 87,152, 93,
+193,191,100,247,123,237,253, 50, 54,177,155, 62, 1,103,242,234,128, 67,136, 50, 67, 37,229,243, 15, 41,126, 99,167,167, 65,245,
+ 94,173,124,191, 97,140, 93,191,168,118,127, 46,146,191,221,218,165,196,233,245,181, 40,147,163,239, 89,159, 94,157, 86,227,170,
+215,227, 86, 49,195,219,131,127,119,140,237,255, 0,230, 13, 22,144, 7,128,230,104, 10,191, 16,191, 82,218, 52,252,150,240,181,
+ 1,131,238,231,220,215,187, 90, 8, 55, 25, 34,133,134,195,211,132, 15,117, 26, 93,206, 72,153,172, 24, 95,224,247,191, 88, 27,
+ 30, 2,151, 31,126,222, 37, 88,167, 18, 98,190,230,187,110,240,145,101,228,233,137, 90, 92, 93,206, 28, 24,117, 18, 86, 53,214,
+ 45,195,145,107,120, 86,235,113,139,182,126,243,199,251,212,237,223,123, 90, 63, 41,230, 91, 31,204,219,172,189, 46,151, 80,235,
+183, 95, 78,155,125,123, 91,141, 14, 72,187, 75,160,226, 67,181,244, 12, 57, 93, 77, 79,141,163,161,214, 30,119, 85,205,180,117,
+237,213,240,215,241,113,160, 51,195,184,119, 40,123, 31,123,222, 58,133,183, 29,176,100,132, 25, 16,172,114,198,240,174,165,143,
+ 33, 35, 38, 34,194,252, 76,103, 73, 22,160, 38,243,220, 51,102,201,178,121,244,138, 95,189,178, 48,190,242, 48, 37,196, 48,224,
+ 38,224,168, 35, 62,229,203,185, 23, 63, 84,122,120,214,167, 26, 14,218, 93,138, 85,199, 59,119,220, 1,100, 25, 26, 95, 28,226,
+105,185,234,245, 78,163, 31, 59,234,213,242,211, 55, 24, 59, 85,177,114,198,232,118,223, 45,230, 71,157,235,201,142, 19,205,116,
+214,221, 98,237,110,175, 75, 79,197,239,105,183,133, 1,231,131,124,221,179,183, 61,179,115,202,144,104,207,196,237,217,223, 1,
+144,244,145,242,179,222, 55,146, 49,126, 7,129, 96,125, 99,208, 42,124,189,213,220, 9,137, 22,100,121,113, 77, 38,231,144,240,
+ 99,237,209, 36, 94,103, 29, 87, 63,201, 3, 15, 89,163,141,253,207,116,153, 90,221, 66, 60, 56, 86,203, 42, 30,214,243,184,158,
+116,237,158,127, 68, 94, 67,172,248,221,110,159, 85,122, 61, 13,109,171, 79, 91, 78,141, 63, 90,214,227, 81,159, 23,178, 11,110,
+157, 70,218,117,185, 31,124, 94, 92, 91,223,169, 97,230,125,239,116,245,127, 91,235,250,234,130, 36, 27,246,226,189,147, 62,243,
+156,241, 98,103,194,153, 1,164,101, 89,213, 76, 51, 60, 8,236,152,174,232, 92,133, 4,170,189,131,112,170, 21,221,183,205,198,
+ 77,152, 79,149, 38, 52,152,253,195, 38, 4,193,146, 37,146, 72,215, 18,105,149,103, 16, 59, 69,113,197, 72, 83,110, 71,152,173,
+199,151,216, 78,198, 70,172, 31,184,122, 36, 27, 73, 7,147,232, 91,143, 29, 93, 61, 22,249, 42, 12, 88,253,152,184,170, 34, 59,
+ 71,148, 25, 49, 5,180,152,134, 63, 55,164,116,120,234,183, 91, 77,180,253,107,114,160, 42,247,125,227,121,199,238, 88,176, 97,
+202, 72, 54,249, 90, 12,100,116,142, 57,213,102,152, 72, 74,101, 13, 93,104,228,111,116,197,195, 65,250,213,151,237,174,230,222,
+225,197,237,220,115,152,217,145,200,155,116, 89, 97,163, 83,164,102,245, 7,219,205, 35,245, 26, 79,119,220,208, 15,194,117,243,
+175, 69,155, 31,182,190,251,133,178, 91,110,251,244, 0, 32,234, 73,143,230,236, 67,105,208, 25,186,156,181, 90,222, 23,245,213,
+102, 54, 55,225,247, 94, 54,198,109,143,175,117, 17,116,228,194,213,171,172,116,105, 10,220,250,215,181,190,181,252,104, 12,214,
+ 78,231,220, 25,120,251, 46,235, 38,229,211, 89,119,188,188,100,199,138, 32,170, 35,197, 93,194, 53, 87,109, 87,125, 66, 14, 32,
+240,228,121,138,124, 29,223,189,228,226, 99,176,154, 40,165,159, 31,183, 28,203,211, 4, 35,238,210,188, 89, 45,164,155,114, 0,
+168,240,173,164,240,118,215,145,135,204, 29,183,200,121,163,229,186,143,141,209,243,157, 87,191, 79, 83,105,235,117,117,242,247,
+181, 95,198,169, 95,108,236, 60,172, 23,143, 23, 35,106,131, 6, 57,240,231,201,108, 73,240,213, 24,197, 49,151, 26, 57,200, 37,
+ 74, 59,134, 80,167,159, 16,180, 5,151,109,238,147,238, 91,115, 12,217, 86, 76,168,114,115, 49,122,138, 2,245,147, 19, 38, 76,
+ 97, 48, 65,233, 10, 47,110, 23,172, 92,221,227,191,226,224,230,103,117,227,153,159, 19,121,158, 8,250, 64, 8, 31,108,203, 92,
+104,139, 88,221,131,171,251,215,241,181,171,117,129,131,176,117,240,102,218,100,195,188,120,179, 69,131, 30, 44,208,105, 56,205,
+ 44, 70,102,140, 70,222,242,137, 17, 46, 71, 0,125,102,171, 54,189,175,178,176, 97,220, 33,143, 35,109,201, 36,100, 62,231, 44,
+211,226, 72,253, 41, 39,146,105,151, 36,130, 62,205, 36,114,190,240,225, 96, 15, 42,140, 34,179, 39,125,238, 76, 62,224,135,106,
+ 13,230,160,198,147, 2, 60,185,202,227,195, 19, 12,233,100, 87,102,234, 76,178,130,168, 45, 18,198,173,114,167, 85,239, 80, 95,
+185, 59,153,159, 43, 20,100,196,217, 50,186,190, 44, 81,140,114, 37,128,228,152,245,109,147, 25, 58, 82,183, 72, 91, 68,199, 86,
+187,248, 86,223, 47, 31,183,206,245,136,217,231,111,251,224, 45,176,186,210, 99,249,157, 36,181,186, 65,219, 95, 61, 86,183,175,
+215, 85,210, 98,118, 25,143, 48,106,217,180, 60,168,119, 15,181,196, 22,125,109,167,170,117,240,110,165,237,127,173,127, 27,209,
+ 20,169,205,220, 36,220,251, 95,103,155, 35, 35,169, 30,126,110, 30, 62,108,168,173,143,170, 38,202, 17, 60,110,183,186,106,210,
+ 17,192, 54,226, 64,225, 81,183, 29,167, 99, 87,192,198,192,121,101, 72,247,165,195,200,141,158, 85, 88,131,196,243,190, 36,118,
+208, 12, 96,176, 97,107,216,240,191, 11, 13,123,227,236, 71,102,180,231, 3,238, 19, 10,129,121, 49,198, 31, 71,234,219,222,233,
+232,189,173,225, 75,129,141,219, 73,131,136,155,123,109,199, 4, 79,108, 35, 12,152,230, 47, 51,239,127, 4,171, 91,171,241,114,
+247,185,208, 30,111,186,121,156,125,199,116,200,141, 30, 56, 32,222, 6, 34,238, 41,144,250,227, 67,183,195,167, 23,203,240, 83,
+ 27,179, 88,182,174, 26,175,106,215,203,191, 79,177,246, 22, 54,233, 12, 18,101,100,197,181, 9,208,232, 50, 32,146, 60, 97, 32,
+105,236,202,193, 53, 14, 38,245,117,147, 7,111, 24,167,243, 71,111,233,121,149,243, 93, 71,199,211,231, 52, 38,142,174,166,183,
+ 91, 70,139, 95,222,181,189, 85, 3,108,199,236,111, 41,184,253,198,219, 41,193,233,255, 0,243, 99,135, 38, 31, 75,165,165,255,
+ 0,241, 93, 38,211,163, 78,191,143,133,175,235,160, 42,247, 77,202, 76,157,241,101,209, 62, 36, 71, 99,220,219,163, 56, 49,157,
+113,203,137,103,211,114, 46, 3, 27, 26,133,186,101,110, 56,219, 31,101,100,227,228, 58, 55, 82, 14,188, 64, 92,204, 70,223, 60,
+186, 28,243, 55, 41,107,122, 77,249,129, 90,173,255, 0, 23,183, 26, 56, 7,115, 54,221,211, 12,199, 27,239, 9,113,192,184, 30,
+254,142,187,122, 62, 43,120,115,163,238,120,251, 79,151,199,251,212,225,121,126,180,126, 87,205, 73, 6,142,191,246, 61, 46,171,
+ 91, 95,234,219,143,162,128,207,246,150,247,186,230,206,216,251,158, 66,102, 9,118,236, 29,205, 38,142, 49, 24,141,179, 58,193,
+224,247, 73, 5, 71, 72, 21, 39,141,189, 53, 69,145,222,123,212,120, 25, 57, 40,209,117, 98,219,247,172,181,186,112,234, 96,103,
+174, 36, 28, 47,203,166,120,250, 77,109,182,124, 77,140, 46, 71,220, 45,129,164,201,124,159, 37, 46, 57, 29, 66, 63,180,233, 55,
+ 59,122,106,163, 55,106,236,204,216,119,124, 49,147,182, 99, 79,145, 14, 66,110,121, 24,217, 24,105,145, 28,108,202, 50, 90, 71,
+212, 74,217,244,235,212, 45,170,215,227, 84,133,100,251,206,246,185,217, 29,191,231, 99, 13, 30,108,208, 54,228, 34, 95,126, 36,
+219, 70,226, 35, 9,125, 32,235,123, 18, 13,244,143, 79, 26,139,180,247, 30,235, 4, 29,175,139, 20,221,104, 31, 23,102,139, 50,
+ 51, 26,144, 60,236, 68, 51, 79, 52,142, 36,105, 27, 78,164,233,130, 56, 29, 92,235, 88,184,221,151,247, 81, 19, 29,163,238,191,
+ 50, 91,140,184,190, 95,205, 88,177,227,171, 71, 82,215,225,206,220, 57, 81, 27, 31,178, 60,198, 43, 49,217,252,199, 71, 24, 96,
+222, 76, 77, 93, 13, 67,202,116, 70,175,131, 85,186, 90,120,126,173, 1,131,135,185, 59,163,108, 92,220,108, 57, 91, 57,224,200,
+221,242,153,159,203,162,219, 27, 59,203,172,114,190, 84,209,104,135,137,190,139,176,186,129,192,113,216,247,191,112,103,118,214,
+ 46, 54,227, 6,147,138,222,102, 25,144,174,166, 51,156,105, 37,196,183,182, 88,130,127, 88, 84,172,140,126,196, 57, 63,226,206,
+205,230,151, 41,139,117, 36,196, 18,121,191,112, 62,171,181,204,191, 5,239,199,225,245, 84,158,228,218,176,115,224,195,251,219,
+ 54, 60, 92, 44,124,168,102,100,121, 96, 72,230,149, 28, 52, 17,187,202,124,100, 3,130,145,171,149, 1,149,135,184, 59,142, 28,
+232,252,212,241,200,163, 57,246,153,112,150, 32, 8,104,182,227,154,114,181,143,123,140,139,123,124, 58, 72,246,208,177,251,195,
+127,201,194,199,233, 75, 12,121, 25, 24,253,182,194, 67, 16, 96,178,110,242,188, 89, 45,167, 80,184,176, 26, 69,248, 86,205,113,
+246, 15,190,217,181, 96,125,249,211,179,253,164, 30,107,167, 97,204,106,234,105,211,111,146,163,237,144,246, 42,196,195,105, 59,
+ 57,143,169,140, 91,203, 62, 33, 29, 83, 35,121, 59,232,111,139,171,126,151,243,190, 26, 1, 55,237,215, 63,105,159, 98,194,142,
+ 85,144,230, 60,241,102, 74,232, 1,126,142, 20,249, 1,128, 28, 22,242, 68, 9,183,178,178,112,247,126,253,167,103,220, 39,154,
+ 51,139,149,133,131, 44,169, 10, 36,136,114,114, 49,218,121, 97,200, 10,221,104, 93,253,222,137, 11,163,211, 91,173,238, 13,137,
+224,139,252,200,216, 35, 31,170,166, 31, 62,240,132,235, 5,109, 58, 58,205,109, 90,117,124,151,168,112,227,246,111,222, 24, 45,
+142,219, 87,222, 2, 24,198,219,211,147, 23,171,208, 40,122, 62, 92, 43,106,209,211,190,141, 63, 86,246,225, 89,110, 95, 2,163,
+ 35,129,221,125,213, 62,216, 30, 98,144, 79,147, 54,204, 49,167,153,113,216,133,221, 38,233, 75,104,113,103,147,236,212, 88,198,
+100, 33,141,248,242,173, 71,114,230,110,120,107,180,109,152,217,139, 12,153,189,117,202,205,104,212,150, 24,248,146, 78, 66,167,
+ 5, 94,163, 37,205,185, 11,219,211, 82,118,232, 59, 49,113,152,109,103,106,242,199, 38, 18,222, 93,241,140,126,108,186,156,127,
+129,173,213,215,167,167,227,123,105,169,251,236, 59, 27, 97,160,238, 51,133,228,250,170, 99,243,239, 8,143,170, 3, 21,211,214,
+ 58,117,105,213,242, 95,194,159, 0,121,238,201,221,155,244, 81,246,238, 30, 60,102, 92, 72,176,118, 52,203,146, 67, 0, 71,243,
+201,162, 89, 37,146,121,146, 98,224, 11,198, 35, 70,187, 3,126,117, 93, 7,114,111, 59, 4, 27,140,152,217,158,103, 35,207,238,
+ 89, 89, 41,208, 66, 93, 96,207, 24,129,167,146, 71, 93, 49,105,247, 66,199,239,130, 64, 30,232,173,243,227,246,155,102,109,140,
+135,107,243, 98, 24,198,207,105, 49, 68,158, 92,131,210,242,163, 85,244, 90,250, 52,112,181,237, 64,204,198,236,130,192,238, 77,
+179,234, 13,147,110,188,184,159, 22,191,241,151, 14,220, 79, 83,248,191,206,248,184,213,248, 2, 4,253,223,184,182,235, 54,220,
+ 74, 8, 14,235,151,129,193,108,221, 8,182,145,156,150, 55,248,186,199,159,163,133,102,182,237,235,184, 49,198,220,248, 25,236,
+239, 47,111,108, 68, 98,185,140,200,198, 70,152, 78,113,188,203, 44,111,144, 86, 54, 35, 87,197,200,242, 21,187,242,221,163,247,
+185, 37,182,175,190, 79, 59,201,139,230,184, 66,124, 53,107,254, 5,255, 0,169,234,160,102,227,118, 51, 71,140,185,237,179,104,
+ 56,177,140, 46,172,152,131,252, 38,165,233,116, 11, 55,240,181,105,211,167,221,189,173, 83,224, 11, 46,218,223,151,115,217,241,
+114,102,153, 50, 50, 89, 47, 51, 42, 24,143,196,200, 11,196, 73, 40,125,194, 15,133,193,183, 10,183,243,177,250, 42,163,108,199,
+216,238,126,230,108, 27,244, 97,191,148,146, 15,252, 63,191,229,255, 0,132,223,195,248,244,120,115,183,141, 88,249,115,250,201,
+255, 0,180, 79,245,169, 30, 2, 67,121,216,253, 21,222,118, 47, 69, 3,203,159,214, 79,253,162,127,173, 93,229,207,235, 39,254,
+209, 63,214,164, 9, 36,121,216,255, 0, 86,187,206, 71,232,160,116, 15,235, 39,237,167,250,212,225, 7,243,147,246,211,233,164,
+120, 2, 87,152, 78,158,171,127,103,127,147,169,166,186,135,160,105,233,220, 95,163,206,227, 79,241,127, 91,149,117, 1,255,217,
+};
+
+#endif
diff --git a/source/blender/src/renderwin.c b/source/blender/src/renderwin.c
new file mode 100644
index 00000000000..77252808170
--- /dev/null
+++ b/source/blender/src/renderwin.c
@@ -0,0 +1,809 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 <string.h>
+#include <stdarg.h>
+#include <math.h>
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+#include "BLI_blenlib.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BMF_Api.h"
+
+#include "DNA_view3d_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_vec_types.h"
+
+#include "BKE_global.h"
+#include "BKE_utildefines.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+#include "BIF_graphics.h"
+#include "BIF_screen.h"
+#include "BIF_space.h"
+#include "BIF_mywindow.h"
+#include "BIF_renderwin.h"
+#include "BIF_toets.h"
+
+#include "BDR_editobject.h"
+
+#include "BSE_view.h"
+#include "BSE_drawview.h"
+#include "BSE_filesel.h"
+#include "BSE_headerbuttons.h"
+
+#include "blendertimer.h"
+
+#include "blendef.h"
+#include "mydevice.h"
+#include "winlay.h"
+#include "render.h"
+
+/***/
+
+typedef struct {
+ Window *win;
+
+ float zoom, zoomofs[2];
+ int active;
+
+ int mbut[3];
+ int lmouse[2];
+
+ /* flags escape presses during event handling
+ * so we can test for user break later.
+ */
+#define RW_FLAGS_ESCAPE (1<<0)
+ /* old zoom style (2x, locked to mouse, exits
+ * when mouse leaves window), to be removed
+ * at some point.
+ */
+#define RW_FLAGS_OLDZOOM (1<<1)
+ /* on when image is being panned with middlemouse
+ */
+#define RW_FLAGS_PANNING (1<<2)
+ /* on when the mouse is dragging over the image
+ * to examine pixel values.
+ */
+#define RW_FLAGS_PIXEL_EXAMINING (1<<3)
+ unsigned int flags;
+
+ float pan_mouse_start[2], pan_ofs_start[2];
+
+ char *info_text;
+} RenderWin;
+
+static RenderWin *renderwin_new(Window *win)
+{
+ RenderWin *rw= MEM_mallocN(sizeof(*rw), "RenderWin");
+ rw->win= win;
+ rw->zoom= 1.0;
+ rw->active= 0;
+ rw->flags= 0;
+ rw->zoomofs[0]= rw->zoomofs[1]= 0;
+ rw->info_text= NULL;
+
+ rw->lmouse[0]= rw->lmouse[1]= 0;
+ rw->mbut[0]= rw->mbut[1]= rw->mbut[2]= 0;
+
+ return rw;
+}
+static void renderwin_destroy(RenderWin *rw)
+{
+ if (rw->info_text) MEM_freeN(rw->info_text);
+ window_destroy(rw->win);
+ MEM_freeN(rw);
+}
+
+/***/
+
+static void close_renderwin(void);
+
+static RenderWin *render_win= NULL;
+
+/**/
+
+static void renderwin_queue_redraw(RenderWin *rw)
+{
+ window_queue_redraw(rw->win);
+}
+
+static void renderwin_reshape(RenderWin *rw)
+{
+ ;
+}
+
+static void renderwin_get_disprect(RenderWin *rw, float disprect_r[2][2])
+{
+ float display_w, display_h;
+ float cent_x, cent_y;
+ int w, h;
+
+ window_get_size(rw->win, &w, &h);
+
+ display_w= R.rectx*rw->zoom;
+ display_h= R.recty*rw->zoom;
+ cent_x= (rw->zoomofs[0] + R.rectx/2)*rw->zoom;
+ cent_y= (rw->zoomofs[1] + R.recty/2)*rw->zoom;
+
+ disprect_r[0][0]= w/2 - cent_x;
+ disprect_r[0][1]= h/2 - cent_y;
+ disprect_r[1][0]= disprect_r[0][0] + display_w;
+ disprect_r[1][1]= disprect_r[0][1] + display_h;
+}
+
+ /**
+ * Project window coordinate to image pixel coordinate.
+ * Returns true if resulting coordinate is within image.
+ */
+static int renderwin_win_to_image_co(RenderWin *rw, int winco[2], int imgco_r[2])
+{
+ float disprect[2][2];
+
+ renderwin_get_disprect(rw, disprect);
+
+ imgco_r[0]= (winco[0]-disprect[0][0])/rw->zoom;
+ imgco_r[1]= (winco[1]-disprect[0][1])/rw->zoom;
+
+ return (imgco_r[0]>=0 && imgco_r[1]>=0 && imgco_r[0]<R.rectx && imgco_r[1]<R.recty);
+}
+
+ /**
+ * Project window coordinates to normalized device coordinates
+ * Returns true if resulting coordinate is within window.
+ */
+static int renderwin_win_to_ndc(RenderWin *rw, int win_co[2], float ndc_r[2])
+{
+ int w, h;
+
+ window_get_size(rw->win, &w, &h);
+
+ ndc_r[0]= (float) (win_co[0]*2)/(w-1) - 1.0;
+ ndc_r[1]= (float) (win_co[1]*2)/(h-1) - 1.0;
+
+ return (fabs(ndc_r[0])<=1.0 && fabs(ndc_r[1])<=1.0);
+}
+
+static void renderwin_set_infotext(RenderWin *rw, char *info_text)
+{
+ if (rw->info_text) MEM_freeN(rw->info_text);
+ rw->info_text= info_text?BLI_strdup(info_text):NULL;
+}
+
+static void renderwin_draw(RenderWin *rw, int just_clear)
+{
+ float disprect[2][2];
+ rcti rect;
+
+ rect.xmin= rect.ymin= 0;
+ window_get_size(rw->win, &rect.xmax, &rect.ymax);
+ renderwin_get_disprect(rw, disprect);
+
+ window_make_active(rw->win);
+
+ glEnable(GL_SCISSOR_TEST);
+ glaDefine2DArea(&rect);
+
+ glClearColor(.1875, .1875, .1875, 1.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ if (just_clear || !R.rectot) {
+ glColor3ub(0, 0, 0);
+ glRectfv(disprect[0], disprect[1]);
+ } else {
+ glPixelZoom(rw->zoom, rw->zoom);
+ glaDrawPixelsSafe(disprect[0][0], disprect[0][1], R.rectx, R.recty, R.rectot);
+ glPixelZoom(1.0, 1.0);
+ }
+
+ if (rw->info_text) {
+ glColor3ub(255, 255, 255);
+ glRasterPos2i(10, 10);
+ BMF_DrawString(G.font, rw->info_text);
+ }
+
+ window_swap_buffers(rw->win);
+}
+
+ /* XXX, this is not good, we do this without any regard to state
+ * ... better is to make this an optimization of a more clear
+ * implementation. the bug shows up when you do something like
+ * open the window, then draw part of the progress, then get
+ * a redraw event. whatever can go wrong will.
+ */
+static void renderwin_progress(RenderWin *rw, int start_y, int nlines, int rect_w, int rect_h, unsigned char *rect)
+{
+ float disprect[2][2];
+ rcti win_rct;
+
+ win_rct.xmin= win_rct.ymin= 0;
+ window_get_size(rw->win, &win_rct.xmax, &win_rct.ymax);
+ renderwin_get_disprect(rw, disprect);
+
+ window_make_active(rw->win);
+
+ glEnable(GL_SCISSOR_TEST);
+ glaDefine2DArea(&win_rct);
+
+ glDrawBuffer(GL_FRONT);
+ glPixelZoom(rw->zoom, rw->zoom);
+ glaDrawPixelsSafe(disprect[0][0], disprect[0][1] + start_y*rw->zoom, rect_w, nlines, &rect[start_y*rect_w*4]);
+ glPixelZoom(1.0, 1.0);
+ glFlush();
+ glDrawBuffer(GL_BACK);
+}
+
+static void renderwin_mouse_moved(RenderWin *rw)
+{
+ if (rw->flags&RW_FLAGS_PIXEL_EXAMINING) {
+ int imgco[2];
+ char buf[64];
+
+ if (R.rectot && renderwin_win_to_image_co(rw, rw->lmouse, imgco)) {
+ unsigned char *pxl= (char*) &R.rectot[R.rectx*imgco[1] + imgco[0]];
+
+ sprintf(buf, "R: %d, G: %d, B: %d, A: %d", pxl[0], pxl[1], pxl[2], pxl[3]);
+ renderwin_set_infotext(rw, buf);
+ renderwin_queue_redraw(rw);
+ } else {
+ renderwin_set_infotext(rw, NULL);
+ renderwin_queue_redraw(rw);
+ }
+ } else if (rw->flags&RW_FLAGS_PANNING) {
+ int delta_x= rw->lmouse[0] - rw->pan_mouse_start[0];
+ int delta_y= rw->lmouse[1] - rw->pan_mouse_start[1];
+
+ rw->zoomofs[0]= rw->pan_ofs_start[0] - delta_x/rw->zoom;
+ rw->zoomofs[1]= rw->pan_ofs_start[1] - delta_y/rw->zoom;
+ rw->zoomofs[0]= CLAMPIS(rw->zoomofs[0], -R.rectx/2, R.rectx/2);
+ rw->zoomofs[1]= CLAMPIS(rw->zoomofs[1], -R.recty/2, R.recty/2);
+
+ renderwin_queue_redraw(rw);
+ } else if (rw->flags&RW_FLAGS_OLDZOOM) {
+ float ndc[2];
+ int w, h;
+
+ window_get_size(rw->win, &w, &h);
+ renderwin_win_to_ndc(rw, rw->lmouse, ndc);
+
+ rw->zoomofs[0]= -0.5*ndc[0]*(w-R.rectx*rw->zoom)/rw->zoom;
+ rw->zoomofs[1]= -0.5*ndc[1]*(h-R.recty*rw->zoom)/rw->zoom;
+
+ renderwin_queue_redraw(rw);
+ }
+}
+
+static void renderwin_mousebut_changed(RenderWin *rw)
+{
+ if (rw->mbut[0]) {
+ rw->flags|= RW_FLAGS_PIXEL_EXAMINING;
+ } else if (rw->mbut[1]) {
+ rw->flags|= RW_FLAGS_PANNING;
+ rw->pan_mouse_start[0]= rw->lmouse[0];
+ rw->pan_mouse_start[1]= rw->lmouse[1];
+ rw->pan_ofs_start[0]= rw->zoomofs[0];
+ rw->pan_ofs_start[1]= rw->zoomofs[1];
+ } else {
+ if (rw->flags&RW_FLAGS_PANNING) {
+ rw->flags&= ~RW_FLAGS_PANNING;
+ renderwin_queue_redraw(rw);
+ }
+ if (rw->flags&RW_FLAGS_PIXEL_EXAMINING) {
+ rw->flags&= ~RW_FLAGS_PIXEL_EXAMINING;
+ renderwin_set_infotext(rw, NULL);
+ renderwin_queue_redraw(rw);
+ }
+ }
+}
+
+static void renderwin_reset_view(RenderWin *rw)
+{
+ if (rw->info_text) renderwin_set_infotext(rw, NULL);
+
+ rw->zoom= 1.0;
+ rw->zoomofs[0]= rw->zoomofs[1]= 0;
+ renderwin_queue_redraw(rw);
+}
+
+static void renderwin_handler(Window *win, void *user_data, short evt, short val, char ascii)
+{
+ RenderWin *rw= user_data;
+
+ if (evt==RESHAPE) {
+ renderwin_reshape(rw);
+ } else if (evt==REDRAW) {
+ renderwin_draw(rw, 0);
+ } else if (evt==WINCLOSE) {
+ close_renderwin();
+ } else if (evt==INPUTCHANGE) {
+ rw->active= val;
+
+ if (!val && (rw->flags&RW_FLAGS_OLDZOOM)) {
+ rw->flags&= ~RW_FLAGS_OLDZOOM;
+ renderwin_reset_view(rw);
+ }
+ } else if (ELEM(evt, MOUSEX, MOUSEY)) {
+ rw->lmouse[evt==MOUSEY]= val;
+ renderwin_mouse_moved(rw);
+ } else if (ELEM3(evt, LEFTMOUSE, MIDDLEMOUSE, RIGHTMOUSE)) {
+ int which= (evt==LEFTMOUSE)?0:(evt==MIDDLEMOUSE)?1:2;
+ rw->mbut[which]= val;
+ renderwin_mousebut_changed(rw);
+ } else if (val) {
+ if (evt==ESCKEY) {
+ if (rw->flags&RW_FLAGS_OLDZOOM) {
+ rw->flags&= ~RW_FLAGS_OLDZOOM;
+ renderwin_reset_view(rw);
+ } else {
+ rw->flags|= RW_FLAGS_ESCAPE;
+ mainwindow_raise();
+ }
+ } else if (evt==JKEY) {
+ BIF_swap_render_rects();
+ } else if (evt==ZKEY) {
+ if (rw->flags&RW_FLAGS_OLDZOOM) {
+ rw->flags&= ~RW_FLAGS_OLDZOOM;
+ renderwin_reset_view(rw);
+ } else {
+ rw->zoom= 2.0;
+ rw->flags|= RW_FLAGS_OLDZOOM;
+ renderwin_mouse_moved(rw);
+ }
+ } else if (evt==PADPLUSKEY) {
+ if (rw->zoom<15.9) {
+ rw->zoom*= 2.0;
+ renderwin_queue_redraw(rw);
+ }
+ } else if (evt==PADMINUS) {
+ if (rw->zoom>0.26) {
+ rw->zoom*= 0.5;
+ renderwin_queue_redraw(rw);
+ }
+ } else if (evt==PADENTER || evt==HOMEKEY) {
+ if (rw->flags&RW_FLAGS_OLDZOOM) {
+ rw->flags&= ~RW_FLAGS_OLDZOOM;
+ }
+ renderwin_reset_view(rw);
+ } else if (evt==F3KEY) {
+ mainwindow_raise();
+ mainwindow_make_active();
+ areawinset(find_biggest_area()->win);
+ BIF_save_rendered_image();
+ } else if (evt==F11KEY) {
+ BIF_toggle_render_display();
+ } else if (evt==F12KEY) {
+ BIF_do_render(0);
+ }
+ }
+}
+
+/**/
+
+ /* Render window render callbacks */
+
+void calc_renderwin_rectangle(int posmask, int renderpos_r[2], int rendersize_r[2])
+{
+ int scr_w, scr_h, x, y, div= 0;
+ float ndc_x= 0.0, ndc_y= 0.0;
+
+ /* XXX, we temporarily hack the screen size and position so
+ * the window is always 30 pixels away from a side, really need
+ * a GHOST_GetMaxWindowBounds or so - zr
+ */
+ winlay_get_screensize(&scr_w, &scr_h);
+
+ rendersize_r[0]= (G.scene->r.size*G.scene->r.xsch)/100;
+ rendersize_r[1]= (G.scene->r.size*G.scene->r.ysch)/100;
+ if(G.scene->r.mode & R_PANORAMA) {
+ rendersize_r[0]*= G.scene->r.xparts;
+ rendersize_r[1]*= G.scene->r.yparts;
+ }
+
+ rendersize_r[0]= CLAMPIS(rendersize_r[0], 100, scr_w-90);
+ rendersize_r[1]= CLAMPIS(rendersize_r[1], 100, scr_h-90);
+
+ for (y=-1; y<=1; y++) {
+ for (x=-1; x<=1; x++) {
+ if (posmask & (1<<((y+1)*3 + (x+1)))) {
+ ndc_x+= x;
+ ndc_y+= y;
+ div++;
+ }
+ }
+ }
+
+ if (div) {
+ ndc_x/= div;
+ ndc_y/= div;
+ }
+
+ renderpos_r[0]= 60 + (scr_w-90-rendersize_r[0])*(ndc_x*0.5 + 0.5);
+ renderpos_r[1]= 60 + (scr_h-90-rendersize_r[1])*(ndc_y*0.5 + 0.5);
+}
+
+static void open_renderwin(int winpos[2], int winsize[2])
+{
+ Window *win;
+
+ win= window_open("Blender:Render", winpos[0], winpos[1], winsize[0], winsize[1], 0);
+
+ render_win= renderwin_new(win);
+
+ window_set_handler(win, renderwin_handler, render_win);
+
+ winlay_process_events(0);
+ window_make_active(render_win->win);
+ winlay_process_events(0);
+
+ renderwin_draw(render_win, 1);
+ renderwin_draw(render_win, 1);
+}
+
+static void close_renderwin(void)
+{
+ if (render_win) {
+ renderwin_destroy(render_win);
+ render_win= NULL;
+ }
+}
+
+static void renderwin_init_display_cb(void)
+{
+ if (G.afbreek == 0) {
+ int rendersize[2], renderpos[2];
+
+ calc_renderwin_rectangle(R.winpos, renderpos, rendersize);
+
+ if (!render_win) {
+ open_renderwin(renderpos, rendersize);
+ } else {
+ int win_x, win_y;
+ int win_w, win_h;
+
+ window_get_position(render_win->win, &win_x, &win_y);
+ window_get_size(render_win->win, &win_w, &win_h);
+
+ /* XXX, this is nasty and I guess bound to cause problems,
+ * but to ensure the window is at the user specified position
+ * and size we reopen the window all the time... we need
+ * a ghost _set_position to fix this -zr
+ */
+ close_renderwin();
+ open_renderwin(renderpos, rendersize);
+
+ renderwin_reset_view(render_win);
+ render_win->flags&= ~RW_FLAGS_ESCAPE;
+ }
+ }
+}
+static void renderwin_clear_display_cb(short ignore)
+{
+ if (render_win) {
+ window_make_active(render_win->win);
+ renderwin_draw(render_win, 1);
+ }
+}
+
+static void renderwin_progress_display_cb(int y1, int y2, int w, int h, unsigned int *rect)
+{
+ if (render_win) {
+ renderwin_progress(render_win, y1, y2-y1+1, w, h, (unsigned char*) rect);
+ }
+}
+
+ /* Render view render callbacks */
+
+static View3D *render_view3d = NULL;
+
+static void renderview_init_display_cb(void)
+{
+ ScrArea *sa;
+
+ /* Choose the first view with a persp camera,
+ * if one doesn't exist we will get the first
+ * View3D window.
+ */
+ render_view3d= NULL;
+ for (sa= G.curscreen->areabase.first; sa; sa= sa->next) {
+ if (sa->win && sa->spacetype==SPACE_VIEW3D) {
+ View3D *vd= sa->spacedata.first;
+
+ if (vd->persp==2 && vd->camera==G.scene->camera) {
+ render_view3d= vd;
+ break;
+ } else if (!render_view3d) {
+ render_view3d= vd;
+ }
+ }
+ }
+}
+
+static void renderview_progress_display_cb(int y1, int y2, int w, int h, unsigned int *rect)
+{
+ if (render_view3d) {
+ View3D *v3d= render_view3d;
+ int nlines= y2-y1+1;
+ float sx, sy, facx, facy;
+ rcti win_rct, vb;
+
+ calc_viewborder(v3d, &vb);
+
+ facx= (float) (vb.xmax-vb.xmin)/R.rectx;
+ facy= (float) (vb.ymax-vb.ymin)/R.recty;
+
+ bwin_get_rect(v3d->area->win, &win_rct);
+
+ glaDefine2DArea(&win_rct);
+
+ glDrawBuffer(GL_FRONT);
+
+ sx= vb.xmin;
+ sy= vb.ymin + facy*y1;
+
+ glPixelZoom(facx, facy);
+ glaDrawPixelsSafe(sx, sy, w, nlines, rect+w*y1);
+ glPixelZoom(1.0, 1.0);
+
+ glFlush();
+ glDrawBuffer(GL_BACK);
+
+ v3d->flag |= V3D_DISPIMAGE;
+
+ v3d->area->win_swap= WIN_FRONT_OK;
+ }
+}
+
+ /* Shared render callbacks */
+
+static int test_break(void)
+{
+ if (!G.afbreek) {
+ if (MISC_test_break()) {
+ ;
+ } else if (render_win) {
+ winlay_process_events(0);
+ // render_win can be closed in winlay_process_events()
+ if (render_win == 0 || (render_win->flags & RW_FLAGS_ESCAPE))
+ G.afbreek= 1;
+ }
+ }
+
+ return G.afbreek;
+}
+
+static void printrenderinfo_cb(double time, int sample)
+{
+ extern int mem_in_use;
+ float megs_used_memory= mem_in_use/(1024.0*1024.0);
+ char str[300], tstr[32], *spos= str;
+
+ timestr(time, tstr);
+ spos+= sprintf(spos, "RENDER Fra:%d Ve:%d Fa:%d La:%d", (G.scene->r.cfra), R.totvert, R.totvlak, R.totlamp);
+ spos+= sprintf(spos, "Mem:%.2fM Time:%s ", megs_used_memory, tstr);
+
+ if (R.r.mode & R_FIELDS) {
+ spos+= sprintf(spos, "Field %c ", (R.flag&R_SEC_FIELD)?'B':'A');
+ }
+ if (sample!=-1) {
+ spos+= sprintf(spos, "Sample: %d ", sample);
+ }
+
+ screen_draw_info_text(G.curscreen, str);
+}
+
+/***/
+
+void BIF_renderwin_set_custom_cursor(unsigned char mask[16][2], unsigned char bitmap[16][2])
+{
+ if (render_win) {
+ window_set_custom_cursor(render_win->win, mask, bitmap);
+ }
+}
+
+static void do_crap(int force_dispwin)
+{
+ if (R.displaymode == R_DISPLAYWIN || force_dispwin) {
+ RE_set_initrenderdisplay_callback(NULL);
+ RE_set_clearrenderdisplay_callback(renderwin_clear_display_cb);
+ RE_set_renderdisplay_callback(renderwin_progress_display_cb);
+
+ renderwin_init_display_cb();
+ } else {
+ BIF_close_render_display();
+
+ RE_set_initrenderdisplay_callback(renderview_init_display_cb);
+ RE_set_clearrenderdisplay_callback(NULL);
+ RE_set_renderdisplay_callback(renderview_progress_display_cb);
+ }
+
+ RE_set_test_break_callback(test_break);
+ RE_set_timecursor_callback(set_timecursor);
+ RE_set_printrenderinfo_callback(printrenderinfo_cb);
+}
+
+static void do_render(View3D *ogl_render_view3d, int anim, int force_dispwin)
+{
+ do_crap(force_dispwin);
+
+ if (render_win) window_set_cursor(render_win->win, CURSOR_WAIT);
+ waitcursor(1);
+
+ G.afbreek= 0;
+ if(G.obedit && !(G.scene->r.scemode & R_OGL)) {
+ exit_editmode(0); /* 0 = geen freedata */
+ }
+
+ if(anim) {
+ RE_animrender(ogl_render_view3d);
+ }
+ else {
+ RE_initrender(ogl_render_view3d);
+ }
+ update_for_newframe();
+ R.flag= 0;
+
+ if (render_win) window_set_cursor(render_win->win, CURSOR_STD);
+ waitcursor(0);
+
+ free_filesel_spec(G.scene->r.pic);
+
+ G.afbreek= 0;
+
+ mainwindow_make_active();
+}
+
+void BIF_do_render(int anim)
+{
+ do_render(NULL, anim, 0);
+}
+
+void BIF_do_ogl_render(View3D *ogl_render_view3d, int anim)
+{
+ G.scene->r.scemode |= R_OGL;
+ do_render(ogl_render_view3d, anim, 1);
+ G.scene->r.scemode &= ~R_OGL;
+}
+
+static ScrArea *find_dispimage_v3d(void)
+{
+ ScrArea *sa;
+
+ for (sa= G.curscreen->areabase.first; sa; sa= sa->next) {
+ if (sa->spacetype==SPACE_VIEW3D) {
+ View3D *vd= sa->spacedata.first;
+ if (vd->flag & V3D_DISPIMAGE)
+ return sa;
+ }
+ }
+
+ return NULL;
+}
+
+static void redraw_render_display(void)
+{
+ if (R.displaymode == R_DISPLAYWIN) {
+ // don't open render_win if rendering has been
+ // canceled or the render_win has been actively closed
+ if (render_win) {
+ renderwin_queue_redraw(render_win);
+ }
+ } else {
+ renderview_init_display_cb();
+ renderview_progress_display_cb(0, R.recty-1, R.rectx, R.recty, R.rectot);
+ }
+}
+
+static void scalefastrect(unsigned int *recto, unsigned int *rectn, int oldx, int oldy, int newx, int newy)
+{
+ unsigned int *rect, *newrect;
+ int x, y;
+ int ofsx, ofsy, stepx, stepy;
+
+ stepx = (int)((65536.0 * (oldx - 1.0) / (newx - 1.0)) + 0.5);
+ stepy = (int)((65536.0 * (oldy - 1.0) / (newy - 1.0)) + 0.5);
+ ofsy = 32768;
+ newrect= rectn;
+
+ for (y = newy; y > 0 ; y--){
+ rect = recto;
+ rect += (ofsy >> 16) * oldx;
+ ofsy += stepy;
+ ofsx = 32768;
+ for (x = newx ; x>0 ; x--){
+ *newrect++ = rect[ofsx >> 16];
+ ofsx += stepx;
+ }
+ }
+}
+
+void BIF_swap_render_rects(void)
+{
+ unsigned int *temp;
+
+ if(R.rectspare==0) {
+ R.rectspare= (unsigned int *)MEM_callocN(sizeof(int)*R.rectx*R.recty, "rectot");
+ R.sparex= R.rectx;
+ R.sparey= R.recty;
+ }
+ else if(R.sparex!=R.rectx || R.sparey!=R.recty) {
+ temp= (unsigned int *)MEM_callocN(sizeof(int)*R.rectx*R.recty, "rectot");
+
+ scalefastrect(R.rectspare, temp, R.sparex, R.sparey, R.rectx, R.recty);
+ MEM_freeN(R.rectspare);
+ R.rectspare= temp;
+
+ R.sparex= R.rectx;
+ R.sparey= R.recty;
+ }
+
+ temp= R.rectot;
+ R.rectot= R.rectspare;
+ R.rectspare= temp;
+
+ redraw_render_display();
+}
+
+void BIF_toggle_render_display(void)
+{
+ ScrArea *sa= find_dispimage_v3d();
+
+ if (render_win && render_win->active) {
+ if (R.displaymode == R_DISPLAYVIEW) {
+ BIF_close_render_display();
+ }
+ mainwindow_raise();
+ } else if (sa) {
+ View3D *vd= sa->spacedata.first;
+ vd->flag &= ~V3D_DISPIMAGE;
+ scrarea_queue_winredraw(sa);
+ } else {
+ if (R.displaymode == R_DISPLAYWIN) {
+ renderwin_init_display_cb();
+ } else {
+ if (render_win) {
+ BIF_close_render_display();
+ }
+ renderview_init_display_cb();
+ renderview_progress_display_cb(0, R.recty-1, R.rectx, R.recty, R.rectot);
+ }
+ }
+}
+
+void BIF_close_render_display(void)
+{
+ close_renderwin();
+}
diff --git a/source/blender/src/resources.c b/source/blender/src/resources.c
new file mode 100644
index 00000000000..41645ba126d
--- /dev/null
+++ b/source/blender/src/resources.c
@@ -0,0 +1,304 @@
+
+
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 <stdlib.h>
+#include <string.h>
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+
+#include "BIF_gl.h"
+#include "BIF_resources.h"
+
+#include "datatoc.h"
+
+typedef struct {
+ unsigned char *data;
+ int w, h;
+} Icon;
+
+static Icon *icon_from_data(unsigned char *rect, int w, int h, int rowstride)
+{
+ Icon *icon= MEM_mallocN(sizeof(*icon), "internicon");
+ int y;
+ icon->data= MEM_mallocN(w*h*4, "icon->data");
+ icon->w= w;
+ icon->h= h;
+ for (y=0; y<h; y++)
+ memcpy(&icon->data[y*w*4], &rect[y*rowstride], w*4);
+ return icon;
+}
+static void icon_draw(Icon *icon)
+{
+ glDrawPixels(icon->w, icon->h, GL_RGBA, GL_UNSIGNED_BYTE, icon->data);
+}
+static unsigned char colclamp(int val)
+{
+ return (val<0)?(0):((val>255)?255:val);
+}
+static void icon_draw_blended(Icon *icon, unsigned char blendcol[3])
+{
+ unsigned char temprect[20*21*4]; /* XXX, not so safe */
+ unsigned char *bgcol= icon->data;
+ int blendfac[3];
+ int x, y;
+
+ blendfac[0]= bgcol[0]? (blendcol[0]<<8)/bgcol[0] : 0;
+ blendfac[1]= bgcol[1]? (blendcol[1]<<8)/bgcol[1] : 0;
+ blendfac[2]= bgcol[2]? (blendcol[2]<<8)/bgcol[2] : 0;
+
+ for (y=0; y<icon->h; y++) {
+ unsigned char *row= &icon->data[y*(icon->w*4)];
+ unsigned char *orow= &temprect[y*(icon->w*4)];
+
+ for (x=0; x<icon->w; x++) {
+ unsigned char *pxl= &row[x*4];
+ unsigned char *opxl= &orow[x*4];
+
+ opxl[0]= colclamp((pxl[0]*blendfac[0])>>8);
+ opxl[1]= colclamp((pxl[1]*blendfac[1])>>8);
+ opxl[2]= colclamp((pxl[2]*blendfac[2])>>8);
+ opxl[3]= pxl[3];
+ }
+ }
+
+ glDrawPixels(icon->w, icon->h, GL_RGBA, GL_UNSIGNED_BYTE, temprect);
+}
+static void icon_free(Icon *icon)
+{
+ MEM_freeN(icon->data);
+ MEM_freeN(icon);
+}
+
+/***/
+
+typedef struct {
+ unsigned char cols[BIFNCOLORSHADES][3];
+} Color;
+
+static Color *common_colors_arr= NULL;
+
+static unsigned char *get_color(BIFColorID colorid, BIFColorShade shade)
+{
+ int coloridx= colorid-BIFCOLORID_FIRST;
+ int shadeidx= shade-BIFCOLORSHADE_FIRST;
+ if (coloridx>=0 && coloridx<BIFNCOLORIDS && shadeidx>=0&& shadeidx<BIFNCOLORSHADES) {
+ return common_colors_arr[coloridx].cols[shadeidx];
+ } else {
+ static unsigned char errorcol[3]= {0xFF, 0x33, 0x33};
+
+ return errorcol;
+ }
+}
+
+void BIF_set_color(BIFColorID colorid, BIFColorShade shade)
+{
+ glColor3ubv(get_color(colorid, shade));
+}
+
+static void rgbaCCol_addNT(unsigned char *t, unsigned char *a, int N)
+{
+ t[0]= colclamp(a[0]+N);
+ t[1]= colclamp(a[1]+N);
+ t[2]= colclamp(a[2]+N);
+}
+static void def_col(BIFColorID colorid, unsigned char r, unsigned char g, unsigned char b)
+{
+ int coloridx= colorid-BIFCOLORID_FIRST;
+ if (coloridx>=0 && coloridx<BIFNCOLORIDS) {
+ unsigned char col[3];
+
+ col[0]= r, col[1]= g, col[2]= b;
+ rgbaCCol_addNT(get_color(colorid, COLORSHADE_WHITE), col, 60);
+ rgbaCCol_addNT(get_color(colorid, COLORSHADE_LIGHT), col, 35);
+ rgbaCCol_addNT(get_color(colorid, COLORSHADE_HILITE), col, 20);
+ rgbaCCol_addNT(get_color(colorid, COLORSHADE_MEDIUM), col, 0);
+ rgbaCCol_addNT(get_color(colorid, COLORSHADE_GREY), col, -45);
+ rgbaCCol_addNT(get_color(colorid, COLORSHADE_DARK), col, -60);
+ } else {
+ printf("def_col: Internal error, bad color ID: %d\n", colorid);
+ }
+}
+
+/***/
+
+static Icon **common_icons_arr= NULL;
+
+static Icon *get_icon(BIFIconID icon)
+{
+ int iconidx= icon-BIFICONID_FIRST;
+ if (iconidx>=0 && iconidx<BIFNICONIDS) {
+ return common_icons_arr[iconidx];
+ } else {
+ return common_icons_arr[ICON_ERROR-BIFICONID_FIRST];
+ }
+}
+static void free_common_icons(void)
+{
+ int i;
+
+ for (i=0; i<BIFNICONIDS; i++) {
+ icon_free(common_icons_arr[i+BIFICONID_FIRST]);
+ }
+}
+
+void BIF_draw_icon(BIFIconID icon)
+{
+ icon_draw(get_icon(icon));
+}
+void BIF_draw_icon_blended(BIFIconID icon, BIFColorID color, BIFColorShade shade)
+{
+ icon_draw_blended(get_icon(icon), get_color(color, shade));
+}
+int BIF_get_icon_width(BIFIconID icon)
+{
+ return get_icon(icon)->w;
+}
+int BIF_get_icon_height(BIFIconID icon)
+{
+ return get_icon(icon)->h;
+}
+
+static void def_icon(ImBuf *bbuf, BIFIconID icon, int xidx, int yidx, int w, int h, int offsx, int offsy)
+{
+ int iconidx= icon-BIFICONID_FIRST;
+ if (iconidx>=0 && iconidx<BIFNICONIDS) {
+ int rowstride= bbuf->x*4;
+ unsigned char *start= ((char*) bbuf->rect) + (yidx*21 + 3 + offsy)*rowstride + (xidx*20 + 3 + offsx)*4;
+ common_icons_arr[iconidx]= icon_from_data(start, w, h, rowstride);
+ } else {
+ printf("def_icon: Internal error, bad icon ID: %d\n", icon);
+ }
+}
+
+/***/
+
+static void clear_transp_rect(unsigned char *transp, unsigned char *rect, int w, int h, int rowstride)
+{
+ int x,y;
+ for (y=0; y<h; y++) {
+ unsigned char *row= &rect[y*rowstride];
+ for (x=0; x<w; x++) {
+ unsigned char *pxl= &row[x*4];
+ if (*((unsigned int*) pxl)==*((unsigned int*) transp)) {
+ pxl[3]= 0;
+ }
+ }
+ }
+}
+
+void BIF_resources_init(void)
+{
+ ImBuf *bbuf= IMB_ibImageFromMemory((int *)datatoc_blenderbuttons, datatoc_blenderbuttons_size, IB_rect);
+ int x, y;
+
+ common_icons_arr= MEM_mallocN(sizeof(*common_icons_arr)*BIFNICONIDS, "common_icons");
+ common_colors_arr= MEM_mallocN(sizeof(*common_colors_arr)*BIFNCOLORIDS, "common_colors");
+
+ for (y=0; y<10; y++) {
+ for (x=0; x<21; x++) {
+ int rowstride= bbuf->x*4;
+ unsigned char *start= ((char*) bbuf->rect) + (y*21 + 3)*rowstride + (x*20 + 3)*4;
+ unsigned char transp[4];
+ transp[0]= start[0];
+ transp[1]= start[1];
+ transp[2]= start[2];
+ transp[3]= start[3];
+ clear_transp_rect(transp, start, 20, 21, rowstride);
+ }
+ }
+
+ /* hack! */
+ for (y=0; y<10; y++) {
+ for (x=0; x<21; x++) {
+ if (x==11 && y==6) {
+ def_icon(bbuf, ICON_BEVELBUT_HLT, x, y, 7, 13, 4, 2);
+ } else if (x==12 && y==6) {
+ def_icon(bbuf, ICON_BEVELBUT_DEHLT, x, y, 7, 13, 4, 2);
+ } else {
+ def_icon(bbuf, BIFICONID_FIRST + y*21 + x, x, y, 15, 16, 0, 0);
+ }
+ }
+ }
+
+ IMB_freeImBuf(bbuf);
+
+ def_col(BUTGREY, 0xB0,0xB0,0xB0);
+ def_col(BUTGREEN, 0x88,0xA0,0xA4);
+ def_col(BUTBLUE, 0xA0,0xA0,0xB0);
+ def_col(BUTSALMON, 0xB0,0xA0,0x90);
+ def_col(MIDGREY, 0x90,0x90,0x90);
+ def_col(BUTPURPLE, 0xA2,0x98,0xA9);
+ def_col(BUTYELLOW, 0xB2,0xB2,0x99);
+ def_col(BUTRUST, 0x80,0x70,0x70);
+ def_col(REDALERT, 0xB0,0x40,0x40);
+ def_col(BUTWHITE, 0xD0,0xD0,0xD0);
+ def_col(BUTDBLUE, 0x80,0x80,0xA0);
+ def_col(BUTDPINK, 0xAA,0x88,0x55);
+ def_col(BUTPINK, 0xE8,0xBD,0xA7);
+ def_col(BUTMACTIVE, 0x70,0x70,0xC0);
+
+ def_col(BUTIPO, 0xB0,0xB0,0x99);
+ def_col(BUTAUDIO, 0xB0,0xA0,0x90);
+ def_col(BUTCAMERA, 0x99,0xB2,0xA5);
+ def_col(BUTRANDOM, 0xA9,0x9A,0x98);
+ def_col(BUTEDITOBJECT, 0xA2,0x98,0xA9);
+ def_col(BUTPROPERTY, 0xA0,0xA0,0xB0);
+ def_col(BUTSCENE, 0x99,0x99,0xB2);
+ def_col(BUTMOTION, 0x98,0xA7,0xA9);
+ def_col(BUTMESSAGE, 0x88,0xA0,0x94);
+ def_col(BUTACTION, 0xB2,0xA9,0x99);
+ def_col(BUTVISIBILITY, 0xB2,0xA9,0x99);
+ def_col(BUTCD, 0xB0,0x95,0x90);
+ def_col(BUTGAME, 0x99,0xB2,0x9C);
+ def_col(BUTYUCK, 0xB0,0x99,0xB0);
+ def_col(BUTSEASICK, 0x99,0xB0,0xB0);
+ def_col(BUTCHOKE, 0x88,0x94,0xA0);
+ def_col(BUTIMPERIAL, 0x94,0x88,0xA0);
+}
+
+void BIF_resources_free(void)
+{
+ free_common_icons();
+
+ MEM_freeN(common_colors_arr);
+ MEM_freeN(common_icons_arr);
+}
diff --git a/source/blender/src/scrarea.c b/source/blender/src/scrarea.c
new file mode 100644
index 00000000000..c1386473f5e
--- /dev/null
+++ b/source/blender/src/scrarea.c
@@ -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 *****
+ */
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+
+#include "BIF_scrarea.h"
+
+void *scrarea_find_space_of_type(ScrArea *sa, int type)
+{
+ SpaceLink *sl;
+
+ for (sl= sa->spacedata.first; sl; sl= sl->next)
+ if (sl->spacetype==type)
+ return (void*) sl;
+
+ return 0;
+}
+
+int scrarea_get_win_x(ScrArea *sa)
+{
+ return sa->winrct.xmin;
+}
+
+int scrarea_get_win_y(ScrArea *sa)
+{
+ return sa->winrct.ymin;
+}
+
+int scrarea_get_win_width(ScrArea *sa)
+{
+ return sa->winx;
+}
+
+int scrarea_get_win_height(ScrArea *sa)
+{
+ return sa->winy;
+}
diff --git a/source/blender/src/screendump.c b/source/blender/src/screendump.c
new file mode 100644
index 00000000000..657305930e5
--- /dev/null
+++ b/source/blender/src/screendump.c
@@ -0,0 +1,150 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * Making screendumps.
+ */
+
+#include <string.h>
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_global.h"
+#include "BKE_material.h"
+#include "BKE_sca.h"
+
+#include "BIF_gl.h"
+#include "BIF_toolbox.h"
+#include "BIF_mywindow.h"
+#include "BIF_screen.h"
+#include "BIF_toets.h"
+
+#include "BSE_filesel.h"
+
+#include "render.h"
+#include "mydevice.h"
+
+static unsigned int *dumprect=0;
+static int dumpsx, dumpsy;
+
+void write_screendump(char *name);
+
+void write_screendump(char *name)
+{
+ ImBuf *ibuf;
+
+ if(dumprect) {
+
+ strcpy(G.ima, name);
+ BLI_convertstringcode(name, G.sce, G.scene->r.cfra);
+
+ if(saveover(name)) {
+ waitcursor(1);
+
+ ibuf= IMB_allocImBuf(dumpsx, dumpsy, 24, 0, 0);
+ ibuf->rect= dumprect;
+
+ if(G.scene->r.imtype== R_IRIS) ibuf->ftype= IMAGIC;
+ else if(G.scene->r.imtype==R_IRIZ) ibuf->ftype= IMAGIC;
+ else if(G.scene->r.imtype==R_TARGA) ibuf->ftype= TGA;
+ else if(G.scene->r.imtype==R_RAWTGA) ibuf->ftype= RAWTGA;
+ else if(G.scene->r.imtype==R_PNG) ibuf->ftype= PNG;
+ else if(G.scene->r.imtype==R_HAMX) ibuf->ftype= AN_hamx;
+ else if(ELEM5(G.scene->r.imtype, R_MOVIE, R_AVICODEC, R_AVIRAW, R_AVIJPEG, R_JPEG90)) {
+ ibuf->ftype= JPG|G.scene->r.quality;
+ }
+ else ibuf->ftype= TGA;
+
+ IMB_saveiff(ibuf, name, IB_rect);
+ IMB_freeImBuf(ibuf);
+
+ waitcursor(0);
+ }
+ MEM_freeN(dumprect);
+ dumprect= 0;
+ }
+}
+
+
+void BIF_screendump(void)
+{
+ /* dump pakken van frontbuffer */
+ int x=0, y=0;
+ char imstr[32];
+
+ dumpsx= 0;
+ dumpsy= 0;
+
+ if(dumprect) MEM_freeN(dumprect);
+ dumprect= 0;
+
+ if (G.qual & LR_SHIFTKEY) {
+ x= 0;
+ y= 0;
+
+ dumpsx= G.curscreen->sizex;
+ dumpsy= G.curscreen->sizey;
+
+ }
+ else {
+ if(mywin_inmenu()) {
+ mywin_getmenu_rect(&x, &y, &dumpsx, &dumpsy);
+ } else {
+ int win= mywinget();
+
+ bwin_getsuborigin(win, &x, &y);
+ bwin_getsize(win, &dumpsx, &dumpsy);
+ }
+ }
+
+ if (dumpsx && dumpsy) {
+ save_image_filesel_str(imstr);
+
+ dumprect= MEM_mallocN(sizeof(int)*dumpsx*dumpsy, "dumprect");
+ glReadBuffer(GL_FRONT);
+ glReadPixels(x, y, dumpsx, dumpsy, GL_RGBA, GL_UNSIGNED_BYTE, dumprect);
+
+ /* filesel openen */
+
+ activate_fileselect(FILE_SPECIAL, imstr, G.ima, write_screendump);
+ }
+}
diff --git a/source/blender/src/sequence.c b/source/blender/src/sequence.c
new file mode 100644
index 00000000000..ec98ed3889b
--- /dev/null
+++ b/source/blender/src/sequence.c
@@ -0,0 +1,1647 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 <string.h>
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+#include "MEM_guardedalloc.h"
+#include "PIL_dynlib.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "DNA_ipo_types.h"
+#include "DNA_sequence_types.h"
+#include "DNA_view3d_types.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_plugin_types.h"
+#include "BKE_global.h"
+#include "BKE_texture.h"
+#include "BKE_image.h"
+#include "BKE_main.h"
+#include "BKE_scene.h"
+#include "BKE_ipo.h"
+
+#include "BIF_screen.h"
+#include "BIF_interface.h"
+#include "BIF_toolbox.h"
+#include "BSE_filesel.h"
+#include "BSE_headerbuttons.h"
+#include "BSE_sequence.h"
+
+#include "interface.h" /* MAART: for INT and FLO types */
+#include "blendef.h"
+#include "render.h"
+
+Sequence *seq_arr[MAXSEQ+1];
+int seqrectx, seqrecty;
+
+/* Alle support voor plugin sequences: */
+
+void open_plugin_seq(PluginSeq *pis, char *seqname)
+{
+ int (*version)();
+ char *cp;
+
+ /* voor zekerheid: (hier wordt op getest) */
+ pis->doit= 0;
+ pis->pname= 0;
+ pis->varstr= 0;
+ pis->cfra= 0;
+ pis->version= 0;
+
+ /* clear the error list */
+ PIL_dynlib_get_error_as_string(NULL);
+
+ /* if(pis->handle) PIL_dynlib_close(pis->handle); */
+ /* pis->handle= 0; */
+
+ /* open the needed object */
+ pis->handle= PIL_dynlib_open(pis->name);
+ if(test_dlerr(pis->name, pis->name)) return;
+
+ if (pis->handle != 0) {
+ /* find the address of the version function */
+ version= (int (*)())PIL_dynlib_find_symbol(pis->handle, "plugin_seq_getversion");
+ if (test_dlerr(pis->name, "plugin_seq_getversion")) return;
+
+ if (version != 0) {
+ pis->version= version();
+ if (pis->version==2 || pis->version==3) {
+ int (*info_func)(PluginInfo *);
+ PluginInfo *info= (PluginInfo*) MEM_mallocN(sizeof(PluginInfo), "plugin_info");;
+
+ info_func= (int (*)(PluginInfo *))PIL_dynlib_find_symbol(pis->handle, "plugin_getinfo");
+
+ if(info_func == NULL) error("No info func");
+ else {
+ info_func(info);
+
+ pis->pname= info->name;
+ pis->vars= info->nvars;
+ pis->cfra= info->cfra;
+
+ pis->varstr= info->varstr;
+
+ pis->doit= (void(*)(void))info->seq_doit;
+ if (info->init)
+ info->init();
+ }
+ MEM_freeN(info);
+
+ cp= PIL_dynlib_find_symbol(pis->handle, "seqname");
+ if(cp) strcpy(cp, seqname);
+ } else {
+ printf ("Plugin returned unrecognized version number\n");
+ return;
+ }
+ }
+ }
+}
+
+PluginSeq *add_plugin_seq(char *str, char *seqname)
+{
+ PluginSeq *pis;
+ VarStruct *varstr;
+ int a;
+
+ pis= MEM_callocN(sizeof(PluginSeq), "PluginSeq");
+
+ strcpy(pis->name, str);
+ open_plugin_seq(pis, seqname);
+
+ if(pis->doit==0) {
+ if(pis->handle==0) error("no plugin: %s", str);
+ else error("in plugin: %s", str);
+ MEM_freeN(pis);
+ return 0;
+ }
+
+ /* default waardes */
+ varstr= pis->varstr;
+ for(a=0; a<pis->vars; a++, varstr++) {
+ if( (varstr->type & FLO)==FLO)
+ pis->data[a]= varstr->def;
+ else if( (varstr->type & INT)==INT)
+ *((int *)(pis->data+a))= (int) varstr->def;
+ }
+
+ return pis;
+}
+
+void free_plugin_seq(PluginSeq *pis)
+{
+
+ if(pis==0) return;
+
+ /* geen PIL_dynlib_close: dezelfde plugin kan meerdere keren geopend zijn: 1 handle */
+ MEM_freeN(pis);
+}
+
+/* ***************** END PLUGIN ************************ */
+
+void free_stripdata(int len, StripElem *se)
+{
+ StripElem *seo;
+ int a;
+
+ seo= se;
+
+ for(a=0; a<len; a++, se++) {
+ if(se->ibuf && se->ok!=2) IMB_freeImBuf(se->ibuf);
+ }
+
+ MEM_freeN(seo);
+
+}
+
+void free_strip(Strip *strip)
+{
+ strip->us--;
+ if(strip->us>0) return;
+ if(strip->us<0) {
+ printf("error: negative users in strip\n");
+ return;
+ }
+
+ if(strip->stripdata) {
+ free_stripdata(strip->len, strip->stripdata);
+ }
+ MEM_freeN(strip);
+}
+
+void new_stripdata(Sequence *seq)
+{
+
+ if(seq->strip) {
+ if(seq->strip->stripdata) free_stripdata(seq->strip->len, seq->strip->stripdata);
+ seq->strip->stripdata= 0;
+ seq->strip->len= seq->len;
+ if(seq->len>0) seq->strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelems");
+ }
+}
+
+void free_sequence(Sequence *seq)
+{
+ extern Sequence *last_seq;
+
+ if(seq->strip) free_strip(seq->strip);
+
+ if(seq->anim) IMB_free_anim(seq->anim);
+
+ free_plugin_seq(seq->plugin);
+
+ if(seq==last_seq) last_seq= 0;
+
+ MEM_freeN(seq);
+}
+
+void do_seq_count(ListBase *seqbase, int *totseq)
+{
+ Sequence *seq;
+
+ seq= seqbase->first;
+ while(seq) {
+ (*totseq)++;
+ if(seq->seqbase.first) do_seq_count(&seq->seqbase, totseq);
+ seq= seq->next;
+ }
+}
+
+void do_build_seqar(ListBase *seqbase, Sequence ***seqar, int depth)
+{
+ Sequence *seq;
+
+ seq= seqbase->first;
+ while(seq) {
+ seq->depth= depth;
+ if(seq->seqbase.first) do_build_seqar(&seq->seqbase, seqar, depth+1);
+ **seqar= seq;
+ (*seqar)++;
+ seq= seq->next;
+ }
+}
+
+void build_seqar(ListBase *seqbase, Sequence ***seqar, int *totseq)
+{
+ Sequence **tseqar;
+
+ *totseq= 0;
+ do_seq_count(seqbase, totseq);
+
+ if(*totseq==0) {
+ *seqar= 0;
+ return;
+ }
+ *seqar= MEM_mallocN(sizeof(void *)* *totseq, "seqar");
+ tseqar= *seqar;
+
+ do_build_seqar(seqbase, seqar, 0);
+ *seqar= tseqar;
+}
+
+void free_editing(Editing *ed)
+{
+ MetaStack *ms;
+ Sequence *seq;
+
+ if(ed==0) return;
+
+ WHILE_SEQ(&ed->seqbase) {
+ free_sequence(seq);
+ }
+ END_SEQ
+
+ while( (ms= ed->metastack.first) ) {
+ BLI_remlink(&ed->metastack, ms);
+ MEM_freeN(ms);
+ }
+
+ MEM_freeN(ed);
+}
+
+void calc_sequence(Sequence *seq)
+{
+ Sequence *seqm;
+ int min, max;
+
+ /* eerst recursief alle meta's aflopen */
+ seqm= seq->seqbase.first;
+ while(seqm) {
+ if(seqm->seqbase.first) calc_sequence(seqm);
+ seqm= seqm->next;
+ }
+
+ /* effecten: en meta automatische start en end */
+
+ if(seq->type & SEQ_EFFECT) {
+ /* pointers */
+ if(seq->seq2==0) seq->seq2= seq->seq1;
+ if(seq->seq3==0) seq->seq3= seq->seq1;
+
+ /* effecten gaan van seq1 -> seq2: testen */
+
+ /* we nemen de grootste start en de kleinste eind */
+
+ // seq->start= seq->startdisp= MAX2(seq->seq1->startdisp, seq->seq2->startdisp);
+ // seq->enddisp= MIN2(seq->seq1->enddisp, seq->seq2->enddisp);
+
+ seq->start= seq->startdisp= MAX3(seq->seq1->startdisp, seq->seq2->startdisp, seq->seq3->startdisp);
+ seq->enddisp= MIN3(seq->seq1->enddisp, seq->seq2->enddisp, seq->seq3->enddisp);
+ seq->len= seq->enddisp - seq->startdisp;
+
+ if(seq->strip && seq->len!=seq->strip->len) {
+ new_stripdata(seq);
+ }
+
+ }
+ else {
+ if(seq->type==SEQ_META) {
+ seqm= seq->seqbase.first;
+ if(seqm) {
+ min= 1000000;
+ max= -1000000;
+ while(seqm) {
+ if(seqm->startdisp < min) min= seqm->startdisp;
+ if(seqm->enddisp > max) max= seqm->enddisp;
+ seqm= seqm->next;
+ }
+ seq->start= min;
+ seq->len= max-min;
+
+ if(seq->strip && seq->len!=seq->strip->len) {
+ new_stripdata(seq);
+ }
+ }
+ }
+
+
+ if(seq->startofs && seq->startstill) seq->startstill= 0;
+ if(seq->endofs && seq->endstill) seq->endstill= 0;
+
+ seq->startdisp= seq->start + seq->startofs - seq->startstill;
+ seq->enddisp= seq->start+seq->len - seq->endofs + seq->endstill;
+
+ seq->handsize= 10.0; /* 10 frames */
+ if( seq->enddisp-seq->startdisp < 20 ) {
+ seq->handsize= (float)(0.5*(seq->enddisp-seq->startdisp));
+ }
+ else if(seq->enddisp-seq->startdisp > 250) {
+ seq->handsize= (float)((seq->enddisp-seq->startdisp)/25);
+ }
+ }
+}
+
+void sort_seq()
+{
+ /* alle strips in soort bij elkaar en op volgorde van machine */
+ ListBase seqbase, effbase;
+ Editing *ed;
+ Sequence *seq, *seqt;
+
+ ed= G.scene->ed;
+ if(ed==0) return;
+
+ seqbase.first= seqbase.last= 0;
+ effbase.first= effbase.last= 0;
+
+ while( (seq= ed->seqbasep->first) ) {
+ BLI_remlink(ed->seqbasep, seq);
+
+ if(seq->type & SEQ_EFFECT) {
+ seqt= effbase.first;
+ while(seqt) {
+ if(seqt->machine>=seq->machine) {
+ BLI_insertlinkbefore(&effbase, seqt, seq);
+ break;
+ }
+ seqt= seqt->next;
+ }
+ if(seqt==0) BLI_addtail(&effbase, seq);
+ }
+ else {
+ seqt= seqbase.first;
+ while(seqt) {
+ if(seqt->machine>=seq->machine) {
+ BLI_insertlinkbefore(&seqbase, seqt, seq);
+ break;
+ }
+ seqt= seqt->next;
+ }
+ if(seqt==0) BLI_addtail(&seqbase, seq);
+ }
+ }
+
+ addlisttolist(&seqbase, &effbase);
+ *(ed->seqbasep)= seqbase;
+}
+
+
+void clear_scene_in_allseqs(Scene *sce)
+{
+ Scene *sce1;
+ Editing *ed;
+ Sequence *seq;
+
+ /* als er een scene delete is: alle seqs testen */
+
+ sce1= G.main->scene.first;
+ while(sce1) {
+ if(sce1!=sce && sce1->ed) {
+ ed= sce1->ed;
+
+ WHILE_SEQ(&ed->seqbase) {
+
+ if(seq->scene==sce) seq->scene= 0;
+
+ }
+ END_SEQ
+ }
+
+ sce1= sce1->id.next;
+ }
+}
+
+/* ***************** DO THE SEQUENCE ***************** */
+
+void do_alphaover_effect(float facf0, float facf1, int x, int y, unsigned int *rect1, unsigned int *rect2, unsigned int *out)
+{
+ int fac2, mfac, fac, fac4;
+ int xo, tempc;
+ char *rt1, *rt2, *rt;
+
+ xo= x;
+ rt1= (char *)rect1;
+ rt2= (char *)rect2;
+ rt= (char *)out;
+
+ fac2= (int)(256.0*facf0);
+ fac4= (int)(256.0*facf1);
+
+ while(y--) {
+
+ x= xo;
+ while(x--) {
+
+ /* rt = rt1 over rt2 (alpha van rt1) */
+
+ fac= fac2;
+ mfac= 256 - ( (fac2*rt1[3])>>8 );
+
+ if(fac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt2);
+ else if(mfac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt1);
+ else {
+ tempc= ( fac*rt1[0] + mfac*rt2[0])>>8;
+ if(tempc>255) rt[0]= 255; else rt[0]= tempc;
+ tempc= ( fac*rt1[1] + mfac*rt2[1])>>8;
+ if(tempc>255) rt[1]= 255; else rt[1]= tempc;
+ tempc= ( fac*rt1[2] + mfac*rt2[2])>>8;
+ if(tempc>255) rt[2]= 255; else rt[2]= tempc;
+ tempc= ( fac*rt1[3] + mfac*rt2[3])>>8;
+ if(tempc>255) rt[3]= 255; else rt[3]= tempc;
+ }
+ rt1+= 4; rt2+= 4; rt+= 4;
+ }
+
+ if(y==0) break;
+ y--;
+
+ x= xo;
+ while(x--) {
+
+ fac= fac4;
+ mfac= 256 - ( (fac4*rt1[3])>>8 );
+
+ if(fac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt2);
+ else if(mfac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt1);
+ else {
+ tempc= ( fac*rt1[0] + mfac*rt2[0])>>8;
+ if(tempc>255) rt[0]= 255; else rt[0]= tempc;
+ tempc= ( fac*rt1[1] + mfac*rt2[1])>>8;
+ if(tempc>255) rt[1]= 255; else rt[1]= tempc;
+ tempc= ( fac*rt1[2] + mfac*rt2[2])>>8;
+ if(tempc>255) rt[2]= 255; else rt[2]= tempc;
+ tempc= ( fac*rt1[3] + mfac*rt2[3])>>8;
+ if(tempc>255) rt[3]= 255; else rt[3]= tempc;
+ }
+ rt1+= 4; rt2+= 4; rt+= 4;
+ }
+ }
+}
+
+void do_alphaunder_effect(float facf0, float facf1, int x, int y, unsigned int *rect1, unsigned int *rect2, unsigned int *out)
+{
+ int fac2, mfac, fac, fac4;
+ int xo;
+ char *rt1, *rt2, *rt;
+
+ xo= x;
+ rt1= (char *)rect1;
+ rt2= (char *)rect2;
+ rt= (char *)out;
+
+ fac2= (int)(256.0*facf0);
+ fac4= (int)(256.0*facf1);
+
+ while(y--) {
+
+ x= xo;
+ while(x--) {
+
+ /* rt = rt1 under rt2 (alpha van rt2) */
+
+ /* deze ingewikkelde optimalisering is omdat
+ * de 'skybuf' ingecrosst kan worden
+ */
+ if(rt2[3]==0 && fac2==256) *( (unsigned int *)rt) = *( (unsigned int *)rt1);
+ else if(rt2[3]==255) *( (unsigned int *)rt) = *( (unsigned int *)rt2);
+ else {
+ mfac= rt2[3];
+ fac= (fac2*(256-mfac))>>8;
+
+ if(fac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt2);
+ else {
+ rt[0]= ( fac*rt1[0] + mfac*rt2[0])>>8;
+ rt[1]= ( fac*rt1[1] + mfac*rt2[1])>>8;
+ rt[2]= ( fac*rt1[2] + mfac*rt2[2])>>8;
+ rt[3]= ( fac*rt1[3] + mfac*rt2[3])>>8;
+ }
+ }
+ rt1+= 4; rt2+= 4; rt+= 4;
+ }
+
+ if(y==0) break;
+ y--;
+
+ x= xo;
+ while(x--) {
+
+ if(rt2[3]==0 && fac4==256) *( (unsigned int *)rt) = *( (unsigned int *)rt1);
+ else if(rt2[3]==255) *( (unsigned int *)rt) = *( (unsigned int *)rt2);
+ else {
+ mfac= rt2[3];
+ fac= (fac4*(256-mfac))>>8;
+
+ if(fac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt2);
+ else {
+ rt[0]= ( fac*rt1[0] + mfac*rt2[0])>>8;
+ rt[1]= ( fac*rt1[1] + mfac*rt2[1])>>8;
+ rt[2]= ( fac*rt1[2] + mfac*rt2[2])>>8;
+ rt[3]= ( fac*rt1[3] + mfac*rt2[3])>>8;
+ }
+ }
+ rt1+= 4; rt2+= 4; rt+= 4;
+ }
+ }
+}
+
+
+void do_cross_effect(float facf0, float facf1, int x, int y, unsigned int *rect1, unsigned int *rect2, unsigned int *out)
+{
+ int fac1, fac2, fac3, fac4;
+ int xo;
+ char *rt1, *rt2, *rt;
+
+ xo= x;
+ rt1= (char *)rect1;
+ rt2= (char *)rect2;
+ rt= (char *)out;
+
+ fac2= (int)(256.0*facf0);
+ fac1= 256-fac2;
+ fac4= (int)(256.0*facf1);
+ fac3= 256-fac4;
+
+ while(y--) {
+
+ x= xo;
+ while(x--) {
+
+ rt[0]= (fac1*rt1[0] + fac2*rt2[0])>>8;
+ rt[1]= (fac1*rt1[1] + fac2*rt2[1])>>8;
+ rt[2]= (fac1*rt1[2] + fac2*rt2[2])>>8;
+ rt[3]= (fac1*rt1[3] + fac2*rt2[3])>>8;
+
+ rt1+= 4; rt2+= 4; rt+= 4;
+ }
+
+ if(y==0) break;
+ y--;
+
+ x= xo;
+ while(x--) {
+
+ rt[0]= (fac3*rt1[0] + fac4*rt2[0])>>8;
+ rt[1]= (fac3*rt1[1] + fac4*rt2[1])>>8;
+ rt[2]= (fac3*rt1[2] + fac4*rt2[2])>>8;
+ rt[3]= (fac3*rt1[3] + fac4*rt2[3])>>8;
+
+ rt1+= 4; rt2+= 4; rt+= 4;
+ }
+
+ }
+}
+
+void do_gammacross_effect(float facf0, float facf1, int x, int y, unsigned int *rect1, unsigned int *rect2, unsigned int *out)
+{
+/* extern unsigned short *igamtab1, *gamtab; render.h */
+ int fac1, fac2, col;
+ int xo;
+ char *rt1, *rt2, *rt;
+
+ xo= x;
+ rt1= (char *)rect1;
+ rt2= (char *)rect2;
+ rt= (char *)out;
+
+ fac2= (int)(256.0*facf0);
+ fac1= 256-fac2;
+
+ while(y--) {
+
+ x= xo;
+ while(x--) {
+
+ col= (fac1*igamtab1[rt1[0]] + fac2*igamtab1[rt2[0]])>>8;
+ if(col>65535) rt[0]= 255; else rt[0]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
+ col=(fac1*igamtab1[rt1[1]] + fac2*igamtab1[rt2[1]])>>8;
+ if(col>65535) rt[1]= 255; else rt[1]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
+ col= (fac1*igamtab1[rt1[2]] + fac2*igamtab1[rt2[2]])>>8;
+ if(col>65535) rt[2]= 255; else rt[2]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
+ col= (fac1*igamtab1[rt1[3]] + fac2*igamtab1[rt2[3]])>>8;
+ if(col>65535) rt[3]= 255; else rt[3]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
+
+ rt1+= 4; rt2+= 4; rt+= 4;
+ }
+
+ if(y==0) break;
+ y--;
+
+ x= xo;
+ while(x--) {
+
+ col= (fac1*igamtab1[rt1[0]] + fac2*igamtab1[rt2[0]])>>8;
+ if(col>65535) rt[0]= 255; else rt[0]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
+ col= (fac1*igamtab1[rt1[1]] + fac2*igamtab1[rt2[1]])>>8;
+ if(col>65535) rt[1]= 255; else rt[1]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
+ col= (fac1*igamtab1[rt1[2]] + fac2*igamtab1[rt2[2]])>>8;
+ if(col>65535) rt[2]= 255; else rt[2]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
+ col= (fac1*igamtab1[rt1[3]] + fac2*igamtab1[rt2[3]])>>8;
+ if(col>65535) rt[3]= 255; else rt[3]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
+
+ rt1+= 4; rt2+= 4; rt+= 4;
+ }
+
+ }
+}
+
+void do_add_effect(float facf0, float facf1, int x, int y, unsigned int *rect1, unsigned int *rect2, unsigned int *out)
+{
+ int col, xo, fac1, fac3;
+ char *rt1, *rt2, *rt;
+
+ xo= x;
+ rt1= (char *)rect1;
+ rt2= (char *)rect2;
+ rt= (char *)out;
+
+ fac1= (int)(256.0*facf0);
+ fac3= (int)(256.0*facf1);
+
+ while(y--) {
+
+ x= xo;
+ while(x--) {
+
+ col= rt1[0]+ ((fac1*rt2[0])>>8);
+ if(col>255) rt[0]= 255; else rt[0]= col;
+ col= rt1[1]+ ((fac1*rt2[1])>>8);
+ if(col>255) rt[1]= 255; else rt[1]= col;
+ col= rt1[2]+ ((fac1*rt2[2])>>8);
+ if(col>255) rt[2]= 255; else rt[2]= col;
+ col= rt1[3]+ ((fac1*rt2[3])>>8);
+ if(col>255) rt[3]= 255; else rt[3]= col;
+
+ rt1+= 4; rt2+= 4; rt+= 4;
+ }
+
+ if(y==0) break;
+ y--;
+
+ x= xo;
+ while(x--) {
+
+ col= rt1[0]+ ((fac3*rt2[0])>>8);
+ if(col>255) rt[0]= 255; else rt[0]= col;
+ col= rt1[1]+ ((fac3*rt2[1])>>8);
+ if(col>255) rt[1]= 255; else rt[1]= col;
+ col= rt1[2]+ ((fac3*rt2[2])>>8);
+ if(col>255) rt[2]= 255; else rt[2]= col;
+ col= rt1[3]+ ((fac3*rt2[3])>>8);
+ if(col>255) rt[3]= 255; else rt[3]= col;
+
+ rt1+= 4; rt2+= 4; rt+= 4;
+ }
+ }
+}
+
+void do_sub_effect(float facf0, float facf1, int x, int y, unsigned int *rect1, unsigned int *rect2, unsigned int *out)
+{
+ int col, xo, fac1, fac3;
+ char *rt1, *rt2, *rt;
+
+ xo= x;
+ rt1= (char *)rect1;
+ rt2= (char *)rect2;
+ rt= (char *)out;
+
+ fac1= (int)(256.0*facf0);
+ fac3= (int)(256.0*facf1);
+
+ while(y--) {
+
+ x= xo;
+ while(x--) {
+
+ col= rt1[0]- ((fac1*rt2[0])>>8);
+ if(col<0) rt[0]= 0; else rt[0]= col;
+ col= rt1[1]- ((fac1*rt2[1])>>8);
+ if(col<0) rt[1]= 0; else rt[1]= col;
+ col= rt1[2]- ((fac1*rt2[2])>>8);
+ if(col<0) rt[2]= 0; else rt[2]= col;
+ col= rt1[3]- ((fac1*rt2[3])>>8);
+ if(col<0) rt[3]= 0; else rt[3]= col;
+
+ rt1+= 4; rt2+= 4; rt+= 4;
+ }
+
+ if(y==0) break;
+ y--;
+
+ x= xo;
+ while(x--) {
+
+ col= rt1[0]- ((fac3*rt2[0])>>8);
+ if(col<0) rt[0]= 0; else rt[0]= col;
+ col= rt1[1]- ((fac3*rt2[1])>>8);
+ if(col<0) rt[1]= 0; else rt[1]= col;
+ col= rt1[2]- ((fac3*rt2[2])>>8);
+ if(col<0) rt[2]= 0; else rt[2]= col;
+ col= rt1[3]- ((fac3*rt2[3])>>8);
+ if(col<0) rt[3]= 0; else rt[3]= col;
+
+ rt1+= 4; rt2+= 4; rt+= 4;
+ }
+ }
+}
+
+/* Must be > 0 or add precopy, etc to the function */
+#define XOFF 8
+#define YOFF 8
+
+void do_drop_effect(float facf0, float facf1, int x, int y, unsigned int *rect2i, unsigned int *rect1i, unsigned int *outi)
+{
+ int height, width, temp, fac, fac1, fac2;
+ char *rt1, *rt2, *out;
+ int field= 1;
+
+ width= x;
+ height= y;
+
+ fac1= (int)(70.0*facf0);
+ fac2= (int)(70.0*facf1);
+
+ rt2= (char*) (rect2i + YOFF*width);
+ rt1= (char*) rect1i;
+ out= (char*) outi;
+ for (y=0; y<height-YOFF; y++) {
+ if(field) fac= fac1;
+ else fac= fac2;
+ field= !field;
+
+ memcpy(out, rt1, sizeof(int)*XOFF);
+ rt1+= XOFF*4;
+ out+= XOFF*4;
+
+ for (x=XOFF; x<width; x++) {
+ temp= ((fac*rt2[3])>>8);
+
+ *(out++)= MAX2(0, *rt1 - temp); rt1++;
+ *(out++)= MAX2(0, *rt1 - temp); rt1++;
+ *(out++)= MAX2(0, *rt1 - temp); rt1++;
+ *(out++)= MAX2(0, *rt1 - temp); rt1++;
+ rt2+=4;
+ }
+ rt2+=XOFF*4;
+ }
+ memcpy(out, rt1, sizeof(int)*YOFF*width);
+}
+
+ /* L E T O P: rect2 en rect1 omgekeerd */
+void do_drop_effect2(float facf0, float facf1, int x, int y, unsigned int *rect2, unsigned int *rect1, unsigned int *out)
+{
+ int col, xo, yo, temp, fac1, fac3;
+ int xofs= -8, yofs= 8;
+ char *rt1, *rt2, *rt;
+
+ xo= x;
+ yo= y;
+
+ rt2= (char *)(rect2 + yofs*x + xofs);
+
+ rt1= (char *)rect1;
+ rt= (char *)out;
+
+ fac1= (int)(70.0*facf0);
+ fac3= (int)(70.0*facf1);
+
+ while(y-- > 0) {
+
+ temp= y-yofs;
+ if(temp > 0 && temp < yo) {
+
+ x= xo;
+ while(x--) {
+
+ temp= x+xofs;
+ if(temp > 0 && temp < xo) {
+
+ temp= ((fac1*rt2[3])>>8);
+
+ col= rt1[0]- temp;
+ if(col<0) rt[0]= 0; else rt[0]= col;
+ col= rt1[1]- temp;
+ if(col<0) rt[1]= 0; else rt[1]= col;
+ col= rt1[2]- temp;
+ if(col<0) rt[2]= 0; else rt[2]= col;
+ col= rt1[3]- temp;
+ if(col<0) rt[3]= 0; else rt[3]= col;
+ }
+ else *( (unsigned int *)rt) = *( (unsigned int *)rt1);
+
+ rt1+= 4; rt2+= 4; rt+= 4;
+ }
+ }
+ else {
+ x= xo;
+ while(x--) {
+ *( (unsigned int *)rt) = *( (unsigned int *)rt1);
+ rt1+= 4; rt2+= 4; rt+= 4;
+ }
+ }
+
+ if(y==0) break;
+ y--;
+
+ temp= y-yofs;
+ if(temp > 0 && temp < yo) {
+
+ x= xo;
+ while(x--) {
+
+ temp= x+xofs;
+ if(temp > 0 && temp < xo) {
+
+ temp= ((fac3*rt2[3])>>8);
+
+ col= rt1[0]- temp;
+ if(col<0) rt[0]= 0; else rt[0]= col;
+ col= rt1[1]- temp;
+ if(col<0) rt[1]= 0; else rt[1]= col;
+ col= rt1[2]- temp;
+ if(col<0) rt[2]= 0; else rt[2]= col;
+ col= rt1[3]- temp;
+ if(col<0) rt[3]= 0; else rt[3]= col;
+ }
+ else *( (unsigned int *)rt) = *( (unsigned int *)rt1);
+
+ rt1+= 4; rt2+= 4; rt+= 4;
+ }
+ }
+ else {
+ x= xo;
+ while(x--) {
+ *( (unsigned int *)rt) = *( (unsigned int *)rt1);
+ rt1+= 4; rt2+= 4; rt+= 4;
+ }
+ }
+ }
+}
+
+
+void do_mul_effect(float facf0, float facf1, int x, int y, unsigned int *rect1, unsigned int *rect2, unsigned int *out)
+{
+ int xo, fac1, fac3;
+ char *rt1, *rt2, *rt;
+
+ xo= x;
+ rt1= (char *)rect1;
+ rt2= (char *)rect2;
+ rt= (char *)out;
+
+ fac1= (int)(256.0*facf0);
+ fac3= (int)(256.0*facf1);
+
+ /* formule:
+ * fac*(a*b) + (1-fac)*a => fac*a*(b-1)+a
+ */
+
+ while(y--) {
+
+ x= xo;
+ while(x--) {
+
+ rt[0]= rt1[0] + ((fac1*rt1[0]*(rt2[0]-256))>>16);
+ rt[1]= rt1[1] + ((fac1*rt1[1]*(rt2[1]-256))>>16);
+ rt[2]= rt1[2] + ((fac1*rt1[2]*(rt2[2]-256))>>16);
+ rt[3]= rt1[3] + ((fac1*rt1[3]*(rt2[3]-256))>>16);
+
+ rt1+= 4; rt2+= 4; rt+= 4;
+ }
+
+ if(y==0) break;
+ y--;
+
+ x= xo;
+ while(x--) {
+
+ rt[0]= rt1[0] + ((fac3*rt1[0]*(rt2[0]-256))>>16);
+ rt[1]= rt1[1] + ((fac3*rt1[1]*(rt2[1]-256))>>16);
+ rt[2]= rt1[2] + ((fac3*rt1[2]*(rt2[2]-256))>>16);
+ rt[3]= rt1[3] + ((fac3*rt1[3]*(rt2[3]-256))>>16);
+
+ rt1+= 4; rt2+= 4; rt+= 4;
+ }
+ }
+}
+
+void make_black_ibuf(ImBuf *ibuf)
+{
+ unsigned int *rect;
+ int tot;
+
+ if(ibuf==0 || ibuf->rect==0) return;
+
+ tot= ibuf->x*ibuf->y;
+ rect= ibuf->rect;
+ while(tot--) *(rect++)= 0;
+
+}
+
+void multibuf(ImBuf *ibuf, float fmul)
+{
+ char *rt;
+ int a, mul, icol;
+
+ mul= (int)(256.0*fmul);
+
+ a= ibuf->x*ibuf->y;
+ rt= (char *)ibuf->rect;
+ while(a--) {
+
+ icol= (mul*rt[0])>>8;
+ if(icol>254) rt[0]= 255; else rt[0]= icol;
+ icol= (mul*rt[1])>>8;
+ if(icol>254) rt[1]= 255; else rt[1]= icol;
+ icol= (mul*rt[2])>>8;
+ if(icol>254) rt[2]= 255; else rt[2]= icol;
+ icol= (mul*rt[3])>>8;
+ if(icol>254) rt[3]= 255; else rt[3]= icol;
+
+ rt+= 4;
+ }
+}
+
+void do_effect(int cfra, Sequence *seq, StripElem *se)
+{
+ StripElem *se1, *se2, *se3;
+ float fac, facf;
+ int x, y;
+ char *cp;
+
+ if(se->se1==0 || se->se2==0 || se->se3==0) {
+ make_black_ibuf(se->ibuf);
+ return;
+ }
+
+ /* als metastrip: andere se's */
+ if(se->se1->ok==2) se1= se->se1->se1;
+ else se1= se->se1;
+
+ if(se->se2->ok==2) se2= se->se2->se1;
+ else se2= se->se2;
+
+ if(se->se3->ok==2) se3= se->se3->se1;
+ else se3= se->se3;
+
+ if(se1==0 || se2==0 || se3==0 || se1->ibuf==0 || se2->ibuf==0 || se3->ibuf==0) {
+ make_black_ibuf(se->ibuf);
+ return;
+ }
+
+ x= se2->ibuf->x;
+ y= se2->ibuf->y;
+
+ if(seq->ipo && seq->ipo->curve.first) {
+ do_seq_ipo(seq);
+ fac= seq->facf0;
+ facf= seq->facf1;
+ }
+ else if ELEM3( seq->type, SEQ_CROSS, SEQ_GAMCROSS, SEQ_PLUGIN) {
+ fac= (float)(cfra - seq->startdisp);
+ facf= (float)(fac+0.5);
+ fac /= seq->len;
+ facf /= seq->len;
+ }
+ else {
+ fac= facf= 1.0;
+ }
+
+ if( G.scene->r.mode & R_FIELDS ); else facf= fac;
+
+ switch(seq->type) {
+ case SEQ_CROSS:
+ do_cross_effect(fac, facf, x, y, se1->ibuf->rect, se2->ibuf->rect, se->ibuf->rect);
+ break;
+ case SEQ_GAMCROSS:
+ do_gammacross_effect(fac, facf, x, y, se1->ibuf->rect, se2->ibuf->rect, se->ibuf->rect);
+ break;
+ case SEQ_ADD:
+ do_add_effect(fac, facf, x, y, se1->ibuf->rect, se2->ibuf->rect, se->ibuf->rect);
+ break;
+ case SEQ_SUB:
+ do_sub_effect(fac, facf, x, y, se1->ibuf->rect, se2->ibuf->rect, se->ibuf->rect);
+ break;
+ case SEQ_MUL:
+ do_mul_effect(fac, facf, x, y, se1->ibuf->rect, se2->ibuf->rect, se->ibuf->rect);
+ break;
+ case SEQ_ALPHAOVER:
+ do_alphaover_effect(fac, facf, x, y, se1->ibuf->rect, se2->ibuf->rect, se->ibuf->rect);
+ break;
+ case SEQ_OVERDROP:
+ do_drop_effect(fac, facf, x, y, se1->ibuf->rect, se2->ibuf->rect, se->ibuf->rect);
+ do_alphaover_effect(fac, facf, x, y, se1->ibuf->rect, se->ibuf->rect, se->ibuf->rect);
+ break;
+ case SEQ_ALPHAUNDER:
+ do_alphaunder_effect(fac, facf, x, y, se1->ibuf->rect, se2->ibuf->rect, se->ibuf->rect);
+ break;
+ case SEQ_PLUGIN:
+ if(seq->plugin && seq->plugin->doit) {
+
+ if((G.f & G_PLAYANIM)==0) waitcursor(1);
+
+ if(seq->plugin->cfra) *(seq->plugin->cfra)= frame_to_float(CFRA);
+
+ cp= PIL_dynlib_find_symbol(seq->plugin->handle, "seqname");
+ if(cp) strcpy(cp, seq->name+2);
+
+ if (seq->plugin->version<=2) {
+ if(se1->ibuf) IMB_convert_rgba_to_abgr(se1->ibuf->x*se1->ibuf->y, se1->ibuf->rect);
+ if(se2->ibuf) IMB_convert_rgba_to_abgr(se2->ibuf->x*se2->ibuf->y, se2->ibuf->rect);
+ if(se3->ibuf) IMB_convert_rgba_to_abgr(se3->ibuf->x*se3->ibuf->y, se3->ibuf->rect);
+ }
+
+ ((SeqDoit)seq->plugin->doit)(seq->plugin->data, fac, facf, x, y,
+ se1->ibuf, se2->ibuf, se->ibuf, se3->ibuf);
+
+ if (seq->plugin->version<=2) {
+ if(se1->ibuf) IMB_convert_rgba_to_abgr(se1->ibuf->x*se1->ibuf->y, se1->ibuf->rect);
+ if(se2->ibuf) IMB_convert_rgba_to_abgr(se2->ibuf->x*se2->ibuf->y, se2->ibuf->rect);
+ if(se3->ibuf) IMB_convert_rgba_to_abgr(se3->ibuf->x*se3->ibuf->y, se3->ibuf->rect);
+ IMB_convert_rgba_to_abgr(se->ibuf->x*se->ibuf->y, se->ibuf->rect);
+ }
+
+ if((G.f & G_PLAYANIM)==0) waitcursor(0);
+ }
+ break;
+ }
+
+}
+
+int evaluate_seq_frame(int cfra)
+{
+ Sequence *seq;
+ Editing *ed;
+ int totseq=0;
+
+ memset(seq_arr, 0, 4*MAXSEQ);
+
+ ed= G.scene->ed;
+ if(ed==0) return 0;
+
+ seq= ed->seqbasep->first;
+ while(seq) {
+ if(seq->startdisp <=cfra && seq->enddisp > cfra) {
+ seq_arr[seq->machine]= seq;
+ totseq++;
+ }
+ seq= seq->next;
+ }
+
+ return totseq;
+}
+
+StripElem *give_stripelem(Sequence *seq, int cfra)
+{
+ Strip *strip;
+ StripElem *se;
+ int nr;
+
+ strip= seq->strip;
+ se= strip->stripdata;
+
+ if(se==0) return 0;
+ if(seq->startdisp >cfra || seq->enddisp <= cfra) return 0;
+
+ if(cfra <= seq->start) nr= 0;
+ else if(cfra >= seq->start+seq->len-1) nr= seq->len-1;
+ else nr= cfra-seq->start;
+
+ se+= nr;
+ se->nr= nr;
+
+ return se;
+}
+
+void set_meta_stripdata(Sequence *seqm)
+{
+ Sequence *seq, *seqim, *seqeff;
+ Editing *ed;
+ ListBase *tempbase;
+ StripElem *se;
+ int a, cfra, b;
+
+ /* zet alle ->se1 pointers in stripdata, dan kan daar de ibuf uitgelezen */
+
+ ed= G.scene->ed;
+ if(ed==0) return;
+
+ tempbase= ed->seqbasep;
+ ed->seqbasep= &seqm->seqbase;
+
+ se= seqm->strip->stripdata;
+ for(a=0; a<seqm->len; a++, se++) {
+ cfra= a+seqm->start;
+ if(evaluate_seq_frame(cfra)) {
+
+ /* we nemen de hoogste effectstrip of de laagste imagestrip/metastrip */
+ seqim= seqeff= 0;
+
+ for(b=1; b<MAXSEQ; b++) {
+ if(seq_arr[b]) {
+ seq= seq_arr[b];
+ if(seq->type & SEQ_EFFECT) {
+ if(seqeff==0) seqeff= seq;
+ else if(seqeff->machine < seq->machine) seqeff= seq;
+ }
+ else {
+ if(seqim==0) seqim= seq;
+ else if(seqim->machine > seq->machine) seqim= seq;
+ }
+ }
+ }
+ if(seqeff) seq= seqeff;
+ else if(seqim) seq= seqim;
+ else seq= 0;
+
+ if(seq) {
+ se->se1= give_stripelem(seq, cfra);
+ }
+ else se->se1= 0;
+ }
+ }
+
+ ed->seqbasep= tempbase;
+}
+
+
+
+/* HULPFUNKTIES VOOR GIVE_IBUF_SEQ */
+
+void do_seq_count_cfra(ListBase *seqbase, int *totseq, int cfra)
+{
+ Sequence *seq;
+
+ seq= seqbase->first;
+ while(seq) {
+ if(seq->startdisp <=cfra && seq->enddisp > cfra) {
+
+ if(seq->seqbase.first) {
+
+ if(cfra< seq->start) do_seq_count_cfra(&seq->seqbase, totseq, seq->start);
+ else if(cfra> seq->start+seq->len-1) do_seq_count_cfra(&seq->seqbase, totseq, seq->start+seq->len-1);
+ else do_seq_count_cfra(&seq->seqbase, totseq, cfra);
+ }
+
+ (*totseq)++;
+ }
+ seq= seq->next;
+ }
+}
+
+void do_build_seqar_cfra(ListBase *seqbase, Sequence ***seqar, int cfra)
+{
+ Sequence *seq;
+ StripElem *se;
+ Scene *oldsce;
+ unsigned int *rectot;
+ int oldx, oldy, oldcfra, doseq;
+ char name[FILE_MAXDIR];
+
+ seq= seqbase->first;
+ while(seq) {
+
+ /* op nul zetten ivm free_imbuf_seq... */
+ seq->curelem= 0;
+
+ if(seq->startdisp <=cfra && seq->enddisp > cfra) {
+
+ if(seq->seqbase.first) {
+ if(cfra< seq->start) do_build_seqar_cfra(&seq->seqbase, seqar, seq->start);
+ else if(cfra> seq->start+seq->len-1) do_build_seqar_cfra(&seq->seqbase, seqar, seq->start+seq->len-1);
+ else do_build_seqar_cfra(&seq->seqbase, seqar, cfra);
+ }
+
+ **seqar= seq;
+ (*seqar)++;
+
+ se=seq->curelem= give_stripelem(seq, cfra);
+
+ if(se) {
+ if(seq->type == SEQ_META) {
+ se->ok= 2;
+ if(se->se1==0) set_meta_stripdata(seq);
+ if(se->se1) {
+ se->ibuf= se->se1->ibuf;
+ }
+ }
+ else if(seq->type & SEQ_EFFECT) {
+
+ /* testen of image te klein is: opnieuw maken */
+ if(se->ibuf) {
+ if(se->ibuf->x < seqrectx || se->ibuf->y < seqrecty) {
+ IMB_freeImBuf(se->ibuf);
+ se->ibuf= 0;
+ }
+ }
+
+ /* moet het effect (opnieuw) berekend? */
+
+ if(se->ibuf==0 || (se->se1 != seq->seq1->curelem) || (se->se2 != seq->seq2->curelem) || (se->se3 != seq->seq3->curelem)) {
+ se->se1= seq->seq1->curelem;
+ se->se2= seq->seq2->curelem;
+ se->se3= seq->seq3->curelem;
+
+ if(se->ibuf==0) se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rect, 0);
+
+ do_effect(cfra, seq, se);
+ }
+
+ /* size testen */
+ if(se->ibuf) {
+ if(se->ibuf->x != seqrectx || se->ibuf->y != seqrecty ) {
+ if(G.scene->r.mode & R_OSA)
+ IMB_scaleImBuf(se->ibuf, (short)seqrectx, (short)seqrecty);
+ else
+ IMB_scalefastImBuf(se->ibuf, (short)seqrectx, (short)seqrecty);
+ }
+ }
+ }
+ else if(seq->type < SEQ_EFFECT) {
+
+ if(se->ibuf) {
+ /* testen of image te klein is: opnieuw laden */
+ if(se->ibuf->x < seqrectx || se->ibuf->y < seqrecty) {
+ IMB_freeImBuf(se->ibuf);
+ se->ibuf= 0;
+ se->ok= 1;
+ }
+ }
+
+ if(seq->type==SEQ_IMAGE) {
+ if(se->ok && se->ibuf==0) {
+
+ /* als playanim of render: geen waitcursor doen */
+ if((G.f & G_PLAYANIM)==0) waitcursor(1);
+
+ strcpy(name, seq->strip->dir);
+ strcat(name, se->name);
+ BLI_convertstringcode(name, G.sce, G.scene->r.cfra);
+ se->ibuf= IMB_loadiffname(name, IB_rect);
+
+ if((G.f & G_PLAYANIM)==0) waitcursor(0);
+
+ if(se->ibuf==0) se->ok= 0;
+ else {
+ if(se->ibuf->depth==32 && se->ibuf->zbuf==0) converttopremul(se->ibuf);
+ seq->strip->orx= se->ibuf->x;
+ seq->strip->ory= se->ibuf->y;
+ }
+ }
+ }
+ else if(seq->type==SEQ_MOVIE) {
+ if(se->ok && se->ibuf==0) {
+
+ /* als playanim of render: geen waitcursor doen */
+ if((G.f & G_PLAYANIM)==0) waitcursor(1);
+
+ if(seq->anim==0) {
+ strcpy(name, seq->strip->dir);
+ strcat(name, seq->strip->stripdata->name);
+ BLI_convertstringcode(name, G.sce, G.scene->r.cfra);
+
+ seq->anim = openanim(name, IB_rect);
+ }
+ if(seq->anim) {
+ se->ibuf = IMB_anim_absolute(seq->anim, se->nr);
+ }
+
+ if(se->ibuf==0) se->ok= 0;
+ else {
+ if(se->ibuf->depth==32) converttopremul(se->ibuf);
+ seq->strip->orx= se->ibuf->x;
+ seq->strip->ory= se->ibuf->y;
+ if(seq->flag & SEQ_FILTERY) IMB_filtery(se->ibuf);
+ if(seq->mul==0.0) seq->mul= 1.0;
+ if(seq->mul != 1.0) multibuf(se->ibuf, seq->mul);
+ }
+ if((G.f & G_PLAYANIM)==0) waitcursor(0);
+ }
+ }
+ else if(seq->type==SEQ_SCENE && se->ibuf==0) {
+ View3D *vd;
+
+ oldsce= G.scene;
+ set_scene_bg(seq->scene);
+
+ /* oneindige lus voorkomen */
+ doseq= G.scene->r.scemode & R_DOSEQ;
+ G.scene->r.scemode &= ~R_DOSEQ;
+
+ /* vanalles bewaren */
+ oldcfra= CFRA; CFRA= seq->sfra + se->nr;
+ waitcursor(1);
+
+ rectot= R.rectot; R.rectot= 0;
+ oldx= R.rectx; oldy= R.recty;
+ /* dit is nodig omdat de huidige 3D window niet de layers mag leveren, alsof het background render is */
+ vd= G.vd;
+ G.vd= 0;
+
+ RE_initrender(NULL);
+ if (!G.background) {
+ if(R.r.mode & R_FIELDS) update_for_newframe();
+ R.flag= 0;
+
+ free_filesel_spec(G.scene->r.pic);
+ }
+
+ se->ibuf= IMB_allocImBuf(R.rectx, R.recty, 32, IB_rect, 0);
+ if(R.rectot) memcpy(se->ibuf->rect, R.rectot, 4*R.rectx*R.recty);
+ if(R.rectz) {
+ se->ibuf->zbuf= (int *)R.rectz;
+ /* make sure ibuf frees it */
+ se->ibuf->mall |= IB_zbuf;
+ R.rectz= 0;
+ }
+
+ /* and restore */
+ G.vd= vd;
+
+ if((G.f & G_PLAYANIM)==0) waitcursor(0);
+ CFRA= oldcfra;
+ if(R.rectot) MEM_freeN(R.rectot);
+ R.rectot= rectot;
+ R.rectx=oldx; R.recty=oldy;
+ G.scene->r.scemode |= doseq;
+ set_scene_bg(oldsce);
+
+ /* restore!! */
+ R.rectx= seqrectx;
+ R.recty= seqrecty;
+
+ /* added because this flag is checked for
+ * movie writing when rendering an anim.
+ * very convoluted. fix. -zr
+ */
+ R.r.imtype= G.scene->r.imtype;
+ }
+
+ /* size testen */
+ if(se->ibuf) {
+ if(se->ibuf->x != seqrectx || se->ibuf->y != seqrecty ) {
+
+ if (G.scene->r.mode & R_FIELDS) {
+
+ if (seqrecty > 288) IMB_scalefieldImBuf(se->ibuf, (short)seqrectx, (short)seqrecty);
+ else {
+ IMB_de_interlace(se->ibuf);
+
+ if(G.scene->r.mode & R_OSA)
+ IMB_scaleImBuf(se->ibuf, (short)seqrectx, (short)seqrecty);
+ else
+ IMB_scalefastImBuf(se->ibuf, (short)seqrectx, (short)seqrecty);
+ }
+ }
+ else {
+ if(G.scene->r.mode & R_OSA)
+ IMB_scaleImBuf(se->ibuf,(short)seqrectx, (short)seqrecty);
+ else
+ IMB_scalefastImBuf(se->ibuf, (short)seqrectx, (short)seqrecty);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ seq= seq->next;
+ }
+}
+
+ImBuf *give_ibuf_seq(int cfra)
+{
+ Sequence **tseqar, **seqar;
+ Sequence *seq, *seqfirst=0;/* , *effirst=0; */
+ Editing *ed;
+ StripElem *se;
+ int seqnr, totseq;
+
+ /* we maken recursief een 'stack' van sequences, deze is ook
+ * gesorteerd en kan gewoon doorlopen worden.
+ * Deze methode is vooral ontwikkeld voor stills voor en achter meta's
+ */
+
+ totseq= 0;
+ ed= G.scene->ed;
+ if(ed==0) return 0;
+ do_seq_count_cfra(ed->seqbasep, &totseq, cfra);
+
+ if(totseq==0) return 0;
+
+ seqrectx= (G.scene->r.size*G.scene->r.xsch)/100;
+ if(G.scene->r.mode & R_PANORAMA) seqrectx*= G.scene->r.xparts;
+ seqrecty= (G.scene->r.size*G.scene->r.ysch)/100;
+
+
+ /* tseqar is nodig omdat in do_build_... de pointer verandert */
+ seqar= tseqar= MEM_callocN(sizeof(void *)*totseq, "seqar");
+
+ /* deze fie laadt en maakt ook de ibufs */
+ do_build_seqar_cfra(ed->seqbasep, &seqar, cfra);
+ seqar= tseqar;
+
+ for(seqnr=0; seqnr<totseq; seqnr++) {
+ seq= seqar[seqnr];
+
+ se= seq->curelem;
+ if(se) {
+ if(seq->type==SEQ_META) {
+
+ /* onderste strip! */
+ if(seqfirst==0) seqfirst= seq;
+ else if(seqfirst->depth > seq->depth) seqfirst= seq;
+ else if(seqfirst->machine > seq->machine) seqfirst= seq;
+
+ }
+ else if(seq->type & SEQ_EFFECT) {
+
+ /* bovenste strip! */
+ if(seqfirst==0) seqfirst= seq;
+ else if(seqfirst->depth > seq->depth) seqfirst= seq;
+ else if(seqfirst->machine < seq->machine) seqfirst= seq;
+
+
+ }
+ else if(seq->type < SEQ_EFFECT) { /* images */
+
+ /* onderste strip! zodat je bovenin altijd hulptroep kan bewaren */
+
+ if(seqfirst==0) seqfirst= seq;
+ else if(seqfirst->depth > seq->depth) seqfirst= seq;
+ else if(seqfirst->machine > seq->machine) seqfirst= seq;
+
+ }
+ }
+ }
+
+ MEM_freeN(seqar);
+
+ if(seqfirst->curelem==0) return 0;
+ return seqfirst->curelem->ibuf;
+
+}
+
+void free_imbuf_effect_spec(int cfra)
+{
+ Sequence *seq;
+ StripElem *se;
+ Editing *ed;
+ int a;
+
+ ed= G.scene->ed;
+ if(ed==0) return;
+
+ WHILE_SEQ(&ed->seqbase) {
+
+ if(seq->strip) {
+
+ if(seq->type & SEQ_EFFECT) {
+ se= seq->strip->stripdata;
+ for(a=0; a<seq->len; a++, se++) {
+ if(se==seq->curelem && se->ibuf) {
+ IMB_freeImBuf(se->ibuf);
+ se->ibuf= 0;
+ se->ok= 1;
+ se->se1= se->se2= se->se3= 0;
+ }
+ }
+ }
+ }
+ }
+ END_SEQ
+}
+
+void free_imbuf_seq_except(int cfra)
+{
+ Sequence *seq;
+ StripElem *se;
+ Editing *ed;
+ int a;
+
+ ed= G.scene->ed;
+ if(ed==0) return;
+
+ WHILE_SEQ(&ed->seqbase) {
+
+ if(seq->strip) {
+
+ if( seq->type==SEQ_META ) {
+ ;
+ }
+ else {
+ se= seq->strip->stripdata;
+ for(a=0; a<seq->len; a++, se++) {
+ if(se!=seq->curelem && se->ibuf) {
+ IMB_freeImBuf(se->ibuf);
+ se->ibuf= 0;
+ se->ok= 1;
+ se->se1= se->se2= se->se3= 0;
+ }
+ }
+ }
+
+ if(seq->type==SEQ_MOVIE) {
+ if(seq->startdisp > cfra || seq->enddisp < cfra) {
+ if(seq->anim) {
+ IMB_free_anim(seq->anim);
+ seq->anim = 0;
+ }
+ }
+ }
+ }
+ }
+ END_SEQ
+}
+
+void free_imbuf_seq()
+{
+ Sequence *seq;
+ StripElem *se;
+ Editing *ed;
+ int a;
+
+ ed= G.scene->ed;
+ if(ed==0) return;
+
+ WHILE_SEQ(&ed->seqbase) {
+
+ if(seq->strip) {
+
+ if( seq->type==SEQ_META ) {
+ ;
+ }
+ else {
+ se= seq->strip->stripdata;
+ for(a=0; a<seq->len; a++, se++) {
+ if(se->ibuf) {
+ IMB_freeImBuf(se->ibuf);
+ se->ibuf= 0;
+ se->ok= 1;
+ se->se1= se->se2= se->se3= 0;
+ }
+ }
+ }
+
+ if(seq->type==SEQ_MOVIE) {
+ if(seq->anim) {
+ IMB_free_anim(seq->anim);
+ seq->anim = 0;
+ }
+ }
+ }
+ }
+ END_SEQ
+}
+
+void do_render_seq()
+{
+/* static ImBuf *lastibuf=0; */
+ ImBuf *ibuf;
+
+ /* plaatje in R.rectot kopieeren */
+
+ G.f |= G_PLAYANIM; /* waitcursor patch */
+
+ ibuf= give_ibuf_seq(CFRA);
+ if(ibuf) {
+
+ memcpy(R.rectot, ibuf->rect, 4*R.rectx*R.recty);
+
+ /* if (ibuf->zbuf) { */
+ /* if (R.rectz) freeN(R.rectz); */
+ /* R.rectz = BLI_dupallocN(ibuf->zbuf); */
+ /* } */
+
+ free_imbuf_seq_except(CFRA);
+ }
+ G.f &= ~G_PLAYANIM;
+
+}
diff --git a/source/blender/src/space.c b/source/blender/src/space.c
new file mode 100644
index 00000000000..1ee6cf013ae
--- /dev/null
+++ b/source/blender/src/space.c
@@ -0,0 +1,2974 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * - hier het initialiseren en vrijgeven van SPACE data
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+#include "BLI_linklist.h"
+
+#include "DNA_action_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_image_types.h"
+#include "DNA_ipo_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_sequence_types.h"
+#include "DNA_sound_types.h"
+#include "DNA_space_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_view2d_types.h"
+#include "DNA_view3d_types.h"
+
+#include "BKE_blender.h"
+#include "BKE_curve.h"
+#include "BKE_displist.h"
+#include "BKE_global.h"
+#include "BKE_ipo.h"
+#include "BKE_main.h"
+#include "BKE_scene.h"
+#include "BKE_utildefines.h"
+
+#include "BIF_buttons.h"
+#include "BIF_drawimage.h"
+#include "BIF_drawseq.h"
+#include "BIF_drawtext.h"
+#include "BIF_editarmature.h"
+#include "BIF_editfont.h"
+#include "BIF_editika.h"
+#include "BIF_editkey.h"
+#include "BIF_editlattice.h"
+#include "BIF_editmesh.h"
+#include "BIF_editoops.h"
+#include "BIF_editseq.h"
+#include "BIF_editsima.h"
+#include "BIF_editsound.h"
+#include "BIF_editview.h"
+#include "BIF_gl.h"
+#include "BIF_imasel.h"
+#include "BIF_interface.h"
+#include "BIF_mywindow.h"
+#include "BIF_oops.h"
+#include "BIF_resources.h"
+#include "BIF_screen.h"
+#include "BIF_space.h"
+#include "BIF_spacetypes.h"
+#include "BIF_toets.h"
+#include "BIF_toolbox.h"
+#include "BIF_usiblender.h"
+#include "BIF_previewrender.h"
+
+#include "BSE_edit.h"
+#include "BSE_view.h"
+#include "BSE_editipo.h"
+#include "BSE_drawipo.h"
+#include "BSE_drawview.h"
+#include "BSE_drawnla.h"
+#include "BSE_filesel.h"
+#include "BSE_headerbuttons.h"
+#include "BSE_editnla_types.h"
+
+#include "BDR_vpaint.h"
+#include "BDR_editmball.h"
+#include "BDR_editobject.h"
+#include "BDR_editcurve.h"
+#include "BDR_editface.h"
+#include "BDR_drawmesh.h"
+
+#include "BLO_readfile.h" /* for BLO_blendhandle_close */
+
+#include "interface.h"
+#include "mydevice.h"
+#include "blendef.h"
+#include "datatoc.h"
+
+#include "BPY_extern.h" // Blender Python library
+
+#include "TPT_DependKludge.h"
+#ifdef NAN_TPT
+#include "BSE_trans_types.h"
+#include "../img/IMG_Api.h"
+#endif /* NAN_TPT */
+
+#include "SYS_System.h" /* for the user def menu ... should move elsewhere. */
+
+extern void StartKetsjiShell(ScrArea *area, char* startscenename, struct Main* maggie, int always_use_expand_framing);
+
+/**
+ * When the mipmap setting changes, we want to redraw the view right
+ * away to reflect this setting.
+ */
+void space_mipmap_button_function(int event);
+
+
+unsigned short convert_for_nonumpad(unsigned short event);
+void free_soundspace(SpaceSound *ssound);
+
+/* ************* SPACE: VIEW3D ************* */
+
+/* extern void drawview3d(); BSE_drawview.h */
+
+
+void copy_view3d_lock(short val)
+{
+ bScreen *sc;
+ int bit;
+
+ /* van G.scene naar andere views kopieeren */
+ sc= G.main->screen.first;
+
+ while(sc) {
+ if(sc->scene==G.scene) {
+ ScrArea *sa= sc->areabase.first;
+ while(sa) {
+ SpaceLink *sl= sa->spacedata.first;
+ while(sl) {
+ if(sl->spacetype==SPACE_OOPS && val==REDRAW) {
+ if(sa->win) scrarea_queue_winredraw(sa);
+ }
+ else if(sl->spacetype==SPACE_VIEW3D) {
+ View3D *vd= (View3D*) sl;
+ if(vd->scenelock && vd->localview==0) {
+ vd->lay= G.scene->lay;
+ vd->camera= G.scene->camera;
+
+ if(vd->camera==0 && vd->persp>1) vd->persp= 1;
+
+ if( (vd->lay & vd->layact) == 0) {
+ bit= 0;
+ while(bit<32) {
+ if(vd->lay & (1<<bit)) {
+ vd->layact= 1<<bit;
+ break;
+ }
+ bit++;
+ }
+ }
+
+ if(val==REDRAW && vd==sa->spacedata.first) {
+ scrarea_queue_redraw(sa);
+ }
+ }
+ }
+ sl= sl->next;
+ }
+ sa= sa->next;
+ }
+ }
+ sc= sc->id.next;
+ }
+}
+
+void handle_view3d_lock()
+{
+ if (G.vd != NULL) {
+ if(G.vd->localview==0 && G.vd->scenelock && curarea->spacetype==SPACE_VIEW3D) {
+
+ /* naar scene kopieeren */
+ G.scene->lay= G.vd->lay;
+ G.scene->camera= G.vd->camera;
+
+ copy_view3d_lock(REDRAW);
+ }
+ }
+}
+
+void space_set_commmandline_options(void) {
+ SYS_SystemHandle syshandle;
+ int a;
+
+ if ( (syshandle = SYS_GetSystem()) ) {
+ /* User defined settings */
+ a= (U.gameflags & USERDEF_VERTEX_ARRAYS);
+ SYS_WriteCommandLineInt(syshandle, "vertexarrays", a);
+
+ a= (U.gameflags & USERDEF_DISABLE_SOUND);
+ SYS_WriteCommandLineInt(syshandle, "noaudio", a);
+
+ a= (U.gameflags & USERDEF_DISABLE_MIPMAP);
+ set_mipmap(!a);
+ SYS_WriteCommandLineInt(syshandle, "nomipmap", a);
+
+ /* File specific settings: */
+ /* Only test the first one. These two are switched
+ * simultaneously. */
+ a= (G.fileflags & G_FILE_SHOW_FRAMERATE);
+ SYS_WriteCommandLineInt(syshandle, "show_framerate", a);
+ SYS_WriteCommandLineInt(syshandle, "show_profile", a);
+
+ /* When in wireframe mode, always draw debug props. */
+ if (G.vd) {
+ a = ( (G.fileflags & G_FILE_SHOW_DEBUG_PROPS)
+ || (G.vd->drawtype == OB_WIRE)
+ || (G.vd->drawtype == OB_SOLID) );
+ SYS_WriteCommandLineInt(syshandle, "show_properties", a);
+ }
+
+ a= (G.fileflags & G_FILE_ENABLE_ALL_FRAMES);
+ SYS_WriteCommandLineInt(syshandle, "fixedtime", a);
+ }
+}
+
+ /**
+ * These two routines imported from the gameengine,
+ * I suspect a lot of the resetting stuff is cruft
+ * and can be removed, but it should be checked.
+ */
+static void SaveState(void)
+{
+ glPushAttrib(GL_ALL_ATTRIB_BITS);
+
+ init_realtime_GL();
+ init_gl_stuff();
+
+ if(G.scene->camera==0 || G.scene->camera->type!=OB_CAMERA)
+ error("no (correct) camera");
+
+ waitcursor(1);
+}
+
+static void RestoreState(void)
+{
+ curarea->win_swap = 0;
+ curarea->head_swap=0;
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWBUTSALL, 0);
+ reset_slowparents();
+ waitcursor(0);
+ G.qual= 0;
+ glPopAttrib();
+}
+
+static LinkNode *save_and_reset_all_scene_cfra(void)
+{
+ LinkNode *storelist= NULL;
+ Scene *sc;
+
+ for (sc= G.main->scene.first; sc; sc= sc->id.next) {
+ BLI_linklist_prepend(&storelist, (void*) sc->r.cfra);
+ sc->r.cfra= 1;
+
+ set_scene_bg(sc);
+ }
+
+ BLI_linklist_reverse(&storelist);
+
+ return storelist;
+}
+
+static void restore_all_scene_cfra(LinkNode *storelist) {
+ LinkNode *sc_store= storelist;
+ Scene *sc;
+
+ for (sc= G.main->scene.first; sc; sc= sc->id.next) {
+ int stored_cfra= (int) sc_store->link;
+
+ sc->r.cfra= stored_cfra;
+ set_scene_bg(sc);
+
+ sc_store= sc_store->next;
+ }
+
+ BLI_linklist_free(storelist, NULL);
+}
+
+void start_game(void)
+{
+ Scene *sc, *startscene = G.scene;
+ LinkNode *scene_cfra_store;
+
+ /* XXX, silly code - the game engine can
+ * access any scene through logic, so we try
+ * to make sure each scene has a valid camera,
+ * just in case the game engine tries to use it.
+ *
+ * Better would be to make a better routine
+ * in the game engine for finding the camera.
+ * - zr
+ */
+ for (sc= G.main->scene.first; sc; sc= sc->id.next) {
+ if (!sc->camera) {
+ Base *base;
+
+ for (base= sc->base.first; base; base= base->next)
+ if (base->object->type==OB_CAMERA)
+ break;
+
+ sc->camera= base?base->object:NULL;
+ }
+ }
+
+ /* these two lines make sure front and backbuffer are equal. for swapbuffers */
+ markdirty_all();
+ screen_swapbuffers();
+
+ /* can start from header */
+ mywinset(curarea->win);
+
+ scene_cfra_store= save_and_reset_all_scene_cfra();
+
+ BPY_end_python();
+
+ sound_stop_all_sounds();
+
+ /* Before jumping into Ketsji, we configure some settings. */
+ space_set_commmandline_options();
+
+ SaveState();
+ StartKetsjiShell(curarea, startscene->id.name+2, G.main, 1);
+ RestoreState();
+
+ BPY_start_python();
+
+ restore_all_scene_cfra(scene_cfra_store);
+ set_scene_bg(startscene);
+
+ if (G.flags & G_FLAGS_AUTOPLAY)
+ exit_usiblender();
+
+ /* groups could have changed ipo */
+ allqueue(REDRAWNLA, 0);
+ allqueue(REDRAWACTION, 0);
+ allspace(REMAKEIPO, 0);
+ allqueue(REDRAWIPO, 0);
+}
+
+void changeview3d()
+{
+
+ setwinmatrixview3d(0); /* 0= geen pick rect */
+
+}
+
+ /* Callable from editmode and faceselect mode from the
+ * moment, would be nice (and is easy) to generalize
+ * to any mode.
+ */
+static void align_view_to_selected(View3D *v3d)
+{
+ int nr= pupmenu("Align view%t|To selection (top)%x2|To selection (front)%x1|To selection (side)%x0");
+
+ if (nr!=-1) {
+ int axis= nr;
+
+ if (G.obedit && (G.obedit->type == OB_MESH)) {
+ editmesh_align_view_to_selected(v3d, axis);
+ addqueue(v3d->area->win, REDRAW, 1);
+ } else if (G.f & G_FACESELECT) {
+ Object *obact= OBACT;
+ if (obact && obact->type==OB_MESH) {
+ Mesh *me= obact->data;
+
+ if (me->tface) {
+ faceselect_align_view_to_selected(v3d, me, axis);
+ addqueue(v3d->area->win, REDRAW, 1);
+ }
+ }
+ }
+ }
+}
+
+void winqread3d(unsigned short event, short val, char ascii)
+{
+ View3D *v3d= curarea->spacedata.first;
+ Object *ob;
+ float *curs;
+ int doredraw= 0, pupval;
+
+ if(curarea->win==0) return; /* hier komtie vanuit sa->headqread() */
+ if(event==MOUSEY) return;
+
+ if(val) {
+
+ if( uiDoBlocks(&curarea->uiblocks, event)!=UI_NOTHING ) event= 0;
+
+ /* TEXTEDITING?? */
+ if(G.obedit && G.obedit->type==OB_FONT) {
+ switch(event) {
+
+ case LEFTMOUSE:
+ mouse_cursor();
+ break;
+ case MIDDLEMOUSE:
+ if(U.flag & VIEWMOVE) {
+ if(G.qual & LR_SHIFTKEY) viewmove(0);
+ else if(G.qual & LR_CTRLKEY) viewmove(2);
+ else viewmove(1);
+ }
+ else {
+ if(G.qual & LR_SHIFTKEY) viewmove(1);
+ else if(G.qual & LR_CTRLKEY) viewmove(2);
+ else viewmove(0);
+ }
+ case UKEY:
+ if(G.qual & LR_ALTKEY) {
+ remake_editText();
+ doredraw= 1;
+ } else {
+ do_textedit(event, val, ascii);
+ }
+ break;
+ case PAD0: case PAD1: case PAD2: case PAD3: case PAD4:
+ case PAD5: case PAD6: case PAD7: case PAD8: case PAD9:
+ case PADENTER:
+ persptoetsen(event);
+ doredraw= 1;
+ break;
+
+ default:
+ do_textedit(event, val, ascii);
+ break;
+ }
+ }
+ else {
+ switch(event) {
+
+ case BACKBUFDRAW:
+ backdrawview3d(1);
+ break;
+
+ case LEFTMOUSE:
+ if (G.obedit || !(G.f&(G_VERTEXPAINT|G_WEIGHTPAINT|G_TEXTUREPAINT))) {
+ mouse_cursor();
+ }
+ else if (G.f & G_VERTEXPAINT) {
+ vertex_paint();
+ }
+ else if (G.f & G_WEIGHTPAINT){
+ weight_paint();
+ }
+ else if (G.f & G_TEXTUREPAINT) {
+ face_draw();
+ }
+ break;
+ case MIDDLEMOUSE:
+ if(U.flag & VIEWMOVE) {
+ if(G.qual & LR_SHIFTKEY) viewmove(0);
+ else if(G.qual & LR_CTRLKEY) viewmove(2);
+ else viewmove(1);
+ }
+ else {
+ if(G.qual & LR_SHIFTKEY) viewmove(1);
+ else if(G.qual & LR_CTRLKEY) viewmove(2);
+ else viewmove(0);
+ }
+ break;
+ case RIGHTMOUSE:
+ if(G.obedit && (G.qual & LR_CTRLKEY)==0) {
+ if(G.obedit->type==OB_MESH) mouse_mesh();
+ else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) mouse_nurb();
+ else if(G.obedit->type==OB_MBALL) mouse_mball();
+ else if(G.obedit->type==OB_LATTICE) mouse_lattice();
+ else if(G.obedit->type==OB_ARMATURE) mouse_armature();
+ }
+ else if(G.obpose) {
+ if (G.obpose->type==OB_ARMATURE) mousepose_armature();
+ }
+ else if( G.qual & LR_CTRLKEY ) mouse_select();
+ else if(G.f & G_FACESELECT) face_select();
+ else if( G.f & (G_VERTEXPAINT|G_TEXTUREPAINT)) sample_vpaint();
+ else
+ mouse_select();
+ break;
+
+ case ONEKEY:
+ do_layer_buttons(0); break;
+ case TWOKEY:
+ do_layer_buttons(1); break;
+ case THREEKEY:
+ do_layer_buttons(2); break;
+ case FOURKEY:
+ do_layer_buttons(3); break;
+ case FIVEKEY:
+ do_layer_buttons(4); break;
+ case SIXKEY:
+ do_layer_buttons(5); break;
+ case SEVENKEY:
+ do_layer_buttons(6); break;
+ case EIGHTKEY:
+ do_layer_buttons(7); break;
+ case NINEKEY:
+ do_layer_buttons(8); break;
+ case ZEROKEY:
+ do_layer_buttons(9); break;
+ case MINUSKEY:
+ do_layer_buttons(10); break;
+ case EQUALKEY:
+ do_layer_buttons(11); break;
+ case ACCENTGRAVEKEY:
+ do_layer_buttons(-1); break;
+
+ case AKEY:
+ if(G.qual & LR_CTRLKEY) apply_object();
+ else if(G.qual & LR_SHIFTKEY) {
+ tbox_setmain(0);
+ toolbox();
+ }
+ else {
+ if(G.obedit) {
+ if(G.obedit->type==OB_MESH) deselectall_mesh();
+ else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) deselectall_nurb();
+ else if(G.obedit->type==OB_MBALL) deselectall_mball();
+ else if(G.obedit->type==OB_LATTICE) deselectall_Latt();
+ else if(G.obedit->type==OB_ARMATURE) deselectall_armature();
+ }
+ else if (G.obpose){
+ switch (G.obpose->type){
+ case OB_ARMATURE:
+ deselectall_posearmature(1);
+ break;
+ }
+ }
+ else {
+ if(G.f & G_FACESELECT) deselectall_tface();
+ else deselectall();
+ }
+ }
+ break;
+ case BKEY:
+ if(G.qual & LR_SHIFTKEY) set_render_border();
+ else borderselect();
+ break;
+ case CKEY:
+ if(G.qual & LR_CTRLKEY) {
+ copymenu();
+ }
+ else if(G.qual & LR_ALTKEY) {
+ convertmenu(); /* editobject.c */
+ }
+ else if(G.qual & LR_SHIFTKEY) {
+ view3d_home(1);
+ curs= give_cursor();
+ curs[0]=curs[1]=curs[2]= 0.0;
+ scrarea_queue_winredraw(curarea);
+ }
+ else if(G.obedit!=0 && ELEM(G.obedit->type, OB_CURVE, OB_SURF) ) {
+ makecyclicNurb();
+ makeDispList(G.obedit);
+ allqueue(REDRAWVIEW3D, 0);
+ }
+ else {
+ curs= give_cursor();
+ G.vd->ofs[0]= -curs[0];
+ G.vd->ofs[1]= -curs[1];
+ G.vd->ofs[2]= -curs[2];
+ scrarea_queue_winredraw(curarea);
+ }
+
+ break;
+ case DKEY:
+ if(G.qual & LR_SHIFTKEY) {
+ if(G.obedit) {
+ if(G.obedit->type==OB_MESH) adduplicate_mesh();
+ else if(G.obedit->type==OB_ARMATURE) adduplicate_armature();
+ else if(G.obedit->type==OB_MBALL) adduplicate_mball();
+ else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) adduplicate_nurb();
+ }
+ else if(G.obpose){
+ error ("Duplicate not possible in posemode.");
+ }
+ else adduplicate(0);
+ }
+ else if(G.qual & LR_ALTKEY) {
+ if(G.obpose) error ("Duplicate not possible in posemode.");
+ else
+ if(G.obedit==0) adduplicate(0);
+ }
+ else if(G.qual & LR_CTRLKEY) {
+ imagestodisplist();
+ }
+ else {
+ pupval= pupmenu("Draw mode%t|BoundBox %x1|Wire %x2|OpenGL Solid %x3|Shaded Solid %x4");
+ if(pupval>0) {
+ G.vd->drawtype= pupval;
+ doredraw= 1;
+
+ }
+ }
+
+ break;
+ case EKEY:
+ if(G.obedit) {
+ if(G.obedit->type==OB_MESH) extrude_mesh();
+ else if(G.obedit->type==OB_CURVE) addvert_Nurb('e');
+ else if(G.obedit->type==OB_SURF) extrude_nurb();
+ else if(G.obedit->type==OB_ARMATURE) extrude_armature();
+ }
+ else {
+ ob= OBACT;
+ if(ob && ob->type==OB_IKA) if(okee("extrude IKA")) extrude_ika(ob, 1);
+ }
+ break;
+ case FKEY:
+ if(G.obedit) {
+ if(G.obedit->type==OB_MESH) {
+ if(G.qual & LR_SHIFTKEY) fill_mesh();
+ else if(G.qual & LR_ALTKEY) beauty_fill();
+ else if(G.qual & LR_CTRLKEY) edge_flip();
+ else addedgevlak_mesh();
+ }
+ else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) addsegment_nurb();
+ }
+ else if(G.qual & LR_CTRLKEY) sort_faces();
+ else if(G.qual & LR_SHIFTKEY) fly();
+ else {
+ set_faceselect();
+ }
+
+ break;
+ case GKEY:
+ /* RMGRP if(G.qual & LR_CTRLKEY) add_selected_to_group();
+ else if(G.qual & LR_ALTKEY) rem_selected_from_group();
+ else if(G.qual & LR_SHIFTKEY) group_menu();
+ else */
+ if(G.qual & LR_ALTKEY) clear_object('g');
+ else
+ transform('g');
+ break;
+ case HKEY:
+ if(G.obedit) {
+ if(G.obedit->type==OB_MESH) {
+ if(G.qual & LR_ALTKEY) reveal_mesh();
+ else hide_mesh(G.qual & LR_SHIFTKEY);
+ }
+ else if(G.obedit->type== OB_SURF) {
+ if(G.qual & LR_ALTKEY) revealNurb();
+ else hideNurb(G.qual & LR_SHIFTKEY);
+ }
+ else if(G.obedit->type==OB_CURVE) {
+
+ if(G.qual & LR_CTRLKEY) autocalchandlesNurb_all(1); /* flag=1, selected */
+ else if(G.qual & LR_SHIFTKEY) sethandlesNurb(1);
+ else sethandlesNurb(3);
+
+ makeDispList(G.obedit);
+
+ allqueue(REDRAWVIEW3D, 0);
+ }
+ }
+ else if(G.f & G_FACESELECT) hide_tface();
+
+ break;
+ case IKEY:
+ break;
+
+ case JKEY:
+ if(G.qual & LR_CTRLKEY) {
+ if( (ob= OBACT) ) {
+ if(ob->type == OB_MESH) join_mesh();
+ else if(ob->type == OB_CURVE) join_curve(OB_CURVE);
+ else if(ob->type == OB_SURF) join_curve(OB_SURF);
+ else if(ob->type == OB_ARMATURE) join_armature ();
+ }
+ else if (G.obedit && ELEM(G.obedit->type, OB_CURVE, OB_SURF)) addsegment_nurb();
+ } else if(G.obedit) {
+ if(G.obedit->type==OB_MESH) {
+ join_triangles();
+ }
+ }
+
+ break;
+ case KKEY:
+ if(G.obedit) {
+ if(G.obedit->type==OB_SURF) printknots();
+ }
+ else {
+ if(G.qual & LR_SHIFTKEY) {
+ if(G.f & G_FACESELECT) clear_vpaint_selectedfaces();
+ else if(G.f & G_VERTEXPAINT) clear_vpaint();
+ else select_select_keys();
+ }
+ else if(G.qual & LR_CTRLKEY) make_skeleton();
+/* else if(G.qual & LR_ALTKEY) delete_skeleton(); */
+ else set_ob_ipoflags();
+ }
+
+ break;
+ case LKEY:
+ if(G.obedit) {
+ if(G.obedit->type==OB_MESH) selectconnected_mesh();
+ if(G.obedit->type==OB_ARMATURE) selectconnected_armature();
+ else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) selectconnected_nurb();
+ }
+ else if(G.obpose) {
+ if(G.obpose->type==OB_ARMATURE) selectconnected_posearmature();
+ }
+ else {
+
+ if(G.qual & LR_SHIFTKEY) selectlinks();
+ else if(G.qual & LR_CTRLKEY) linkmenu();
+ else if(G.f & G_FACESELECT) select_linked_tfaces();
+ else make_local();
+ }
+ break;
+ case MKEY:
+ movetolayer();
+ break;
+ case NKEY:
+ if(G.obedit) {
+ switch (G.obedit->type){
+ case OB_ARMATURE:
+ if (okee("Recalc bone roll angles")) auto_align_armature();
+ break;
+ case OB_MESH:
+ if(G.qual & LR_SHIFTKEY) {
+ if(okee("Recalc normals inside")) righthandfaces(2);
+ }
+ else {
+ if(okee("Recalc normals outside")) righthandfaces(1);
+ }
+ break;
+ }
+ allqueue(REDRAWVIEW3D, 0);
+ }
+ break;
+ case OKEY:
+ if(G.qual & LR_ALTKEY) clear_object('o');
+ else if(G.obedit) {
+ extern int prop_mode;
+
+ if (G.qual & LR_SHIFTKEY) prop_mode= !prop_mode;
+ else G.f ^= G_PROPORTIONAL;
+
+ allqueue(REDRAWHEADERS, 0);
+ }
+ break;
+ case PKEY:
+
+ if(G.obedit) {
+ if(G.qual) {
+ if(G.qual & LR_CTRLKEY) make_parent();
+ }
+ else if(G.obedit->type==OB_MESH) separate_mesh();
+ else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) separate_nurb();
+ }
+ else if(G.qual & LR_CTRLKEY) make_parent();
+ else if(G.qual & LR_ALTKEY) clear_parent();
+ else {
+ start_game();
+ }
+ break;
+ case RKEY:
+ if(G.obedit==0 && (G.f & G_FACESELECT)) rotate_uv_tface();
+ else if(G.qual & LR_ALTKEY) clear_object('r');
+ else if(G.qual & LR_SHIFTKEY) selectrow_nurb();
+ else transform('r');
+ break;
+ case SKEY:
+ if(G.qual & LR_ALTKEY) {
+ if(G.obedit) transform('N'); /* scale by vertex normal */
+ else clear_object('s');
+ }
+ else if(G.qual & LR_SHIFTKEY) snapmenu();
+ else if(G.qual & LR_CTRLKEY) {
+ if(G.obedit) transform('S');
+ }
+ else transform('s');
+ break;
+ case TKEY:
+ if(G.qual & LR_CTRLKEY) {
+ if(G.obedit) {
+ if(G.obedit->type==OB_MESH) {
+ convert_to_triface(0);
+ allqueue(REDRAWVIEW3D, 0);
+ countall();
+ makeDispList(G.obedit);
+ }
+ }
+ else make_track();
+ }
+ else if(G.qual & LR_ALTKEY) {
+ if(G.obedit && G.obedit->type==OB_CURVE) clear_tilt();
+ else clear_track();
+ }
+ else {
+ if(G.obedit) transform('t');
+ else texspace_edit();
+ }
+
+ break;
+ case UKEY:
+ if(G.obedit) {
+ if(G.obedit->type==OB_MESH) remake_editMesh();
+ else if(G.obedit->type==OB_ARMATURE) remake_editArmature();
+ else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) remake_editNurb();
+ else if(G.obedit->type==OB_LATTICE) remake_editLatt();
+ }
+ else if(G.f & G_FACESELECT) uv_autocalc_tface();
+ else if(G.f & G_WEIGHTPAINT) wpaint_undo();
+ else if(G.f & G_VERTEXPAINT) vpaint_undo();
+ else single_user();
+
+ break;
+ case VKEY:
+ if(G.qual==LR_SHIFTKEY) {
+ if (G.obedit && G.obedit->type==OB_MESH) {
+ align_view_to_selected(v3d);
+ } else if (G.f & G_FACESELECT) {
+ align_view_to_selected(v3d);
+ }
+ } else {
+ if(G.obedit) {
+ if(G.obedit->type==OB_CURVE) {
+ sethandlesNurb(2);
+ makeDispList(G.obedit);
+ allqueue(REDRAWVIEW3D, 0);
+ }
+ }
+ else if(G.qual & LR_ALTKEY) image_aspect();
+ else set_vpaint();
+ }
+ break;
+ case WKEY:
+ if(G.qual & LR_SHIFTKEY) {
+ transform('w');
+ }
+ else if(G.qual & LR_ALTKEY) {
+ /* if(G.obedit && G.obedit->type==OB_MESH) write_videoscape(); */
+ }
+ else if(G.qual & LR_CTRLKEY) {
+ if(G.obedit) {
+ if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
+ switchdirectionNurb2();
+ }
+ }
+ }
+ else special_editmenu();
+
+ break;
+ case XKEY:
+ case DELKEY:
+ if(G.obedit) {
+ if(G.obedit->type==OB_MESH) delete_mesh();
+ else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) delNurb();
+ else if(G.obedit->type==OB_MBALL) delete_mball();
+ else if (G.obedit->type==OB_ARMATURE) delete_armature();
+ }
+ else delete_obj(0);
+ break;
+ case YKEY:
+ if(G.obedit) {
+ if(G.obedit->type==OB_MESH) split_mesh();
+ }
+ break;
+ case ZKEY:
+ if(G.qual & LR_CTRLKEY) {
+ reshadeall_displist();
+ G.vd->drawtype= OB_SHADED;
+ }
+ else if(G.qual & LR_SHIFTKEY) {
+ if(G.vd->drawtype== OB_SHADED) G.vd->drawtype= OB_WIRE;
+ else G.vd->drawtype= OB_SHADED;
+ }
+ else if(G.qual & LR_ALTKEY) {
+ if(G.vd->drawtype== OB_TEXTURE) G.vd->drawtype= OB_SOLID;
+ else G.vd->drawtype= OB_TEXTURE;
+ }
+ else {
+ if(G.vd->drawtype==OB_SOLID || G.vd->drawtype==OB_SHADED) G.vd->drawtype= OB_WIRE;
+ else G.vd->drawtype= OB_SOLID;
+ }
+
+
+ scrarea_queue_headredraw(curarea);
+ scrarea_queue_winredraw(curarea);
+ break;
+
+
+ case HOMEKEY:
+ view3d_home(0);
+ break;
+ case COMMAKEY:
+ G.vd->around= V3D_CENTRE;
+ scrarea_queue_headredraw(curarea);
+ break;
+
+ case PERIODKEY:
+ G.vd->around= V3D_CURSOR;
+ scrarea_queue_headredraw(curarea);
+ break;
+
+ case PADSLASHKEY:
+ if(G.vd->localview) {
+ G.vd->localview= 0;
+ endlocalview(curarea);
+ }
+ else {
+ G.vd->localview= 1;
+ initlocalview();
+ }
+ scrarea_queue_headredraw(curarea);
+ break;
+ case PADASTERKEY: /* '*' */
+ ob= OBACT;
+ if(ob) {
+ obmat_to_viewmat(ob);
+ if(G.vd->persp==2) G.vd->persp= 1;
+ scrarea_queue_winredraw(curarea);
+ }
+ break;
+ case PADPERIOD: /* '.' */
+ centreview();
+ break;
+
+ case PAGEUPKEY:
+ if(G.qual & LR_CTRLKEY) movekey_obipo(1);
+ else nextkey_obipo(1); /* in editipo.c */
+ break;
+
+ case PAGEDOWNKEY:
+ if(G.qual & LR_CTRLKEY) movekey_obipo(-1);
+ else nextkey_obipo(-1);
+ break;
+
+ case PAD0: case PAD1: case PAD2: case PAD3: case PAD4:
+ case PAD5: case PAD6: case PAD7: case PAD8: case PAD9:
+ case PADMINUS: case PADPLUSKEY: case PADENTER:
+ persptoetsen(event);
+ doredraw= 1;
+ break;
+
+ case ESCKEY:
+ if (G.vd->flag & V3D_DISPIMAGE) {
+ G.vd->flag &= ~V3D_DISPIMAGE;
+ doredraw= 1;
+ }
+ break;
+ }
+ }
+ }
+
+ if(doredraw) {
+ scrarea_queue_winredraw(curarea);
+ scrarea_queue_headredraw(curarea);
+ }
+}
+
+void initview3d(ScrArea *sa)
+{
+ View3D *vd;
+
+ vd= MEM_callocN(sizeof(View3D), "initview3d");
+ BLI_addhead(&sa->spacedata, vd); /* addhead! niet addtail */
+
+ vd->spacetype= SPACE_VIEW3D;
+ vd->viewquat[0]= 1.0;
+ vd->viewquat[1]= vd->viewquat[2]= vd->viewquat[3]= 0.0;
+ vd->persp= 1;
+ vd->drawtype= OB_WIRE;
+ vd->view= 7;
+ vd->dist= 10.0;
+ vd->lens= 35.0;
+ vd->near= 0.01;
+ vd->far= 500.0;
+ vd->grid= 1.0;
+ vd->gridlines= 16;
+ vd->lay= vd->layact= 1;
+ if(G.scene) {
+ vd->lay= vd->layact= G.scene->lay;
+ vd->camera= G.scene->camera;
+ }
+ vd->scenelock= 1;
+}
+
+
+/* ******************** SPACE: IPO ********************** */
+
+void changeview2d()
+{
+ if(G.v2d==0) return;
+
+ test_view2d(G.v2d, curarea->winx, curarea->winy);
+ myortho2(G.v2d->cur.xmin, G.v2d->cur.xmax, G.v2d->cur.ymin, G.v2d->cur.ymax);
+}
+
+void winqreadipo(unsigned short event, short val, char ascii)
+{
+ SpaceIpo *sipo= curarea->spacedata.first;
+ View2D *v2d= &sipo->v2d;
+ float dx, dy;
+ int cfra, doredraw= 0;
+ short mval[2];
+
+ if(curarea->win==0) return;
+
+ if(val) {
+ if( uiDoBlocks(&curarea->uiblocks, event)!=UI_NOTHING ) event= 0;
+
+ switch(event) {
+ case UI_BUT_EVENT:
+ if(val>0) do_ipowin_buts(val-1);
+ break;
+ case LEFTMOUSE:
+ if( in_ipo_buttons() ) {
+ do_ipo_selectbuttons();
+ doredraw= 1;
+ }
+ else if(G.qual & LR_CTRLKEY) add_vert_ipo();
+ else {
+ do {
+ getmouseco_areawin(mval);
+ areamouseco_to_ipoco(v2d, mval, &dx, &dy);
+
+ cfra= (int)dx;
+ if(cfra< 1) cfra= 1;
+
+ if( cfra!=CFRA ) {
+ CFRA= cfra;
+ update_for_newframe();
+ force_draw_plus(SPACE_VIEW3D);
+ force_draw_plus(SPACE_ACTION);
+ force_draw_plus(SPACE_BUTS); /* To make constraint sliders redraw */
+ }
+
+ } while(get_mbut()&L_MOUSE);
+ }
+
+ break;
+ case MIDDLEMOUSE:
+ if(in_ipo_buttons()) {
+ scroll_ipobuts();
+ }
+ else view2dmove(); /* in drawipo.c */
+ break;
+ case RIGHTMOUSE:
+ mouse_select_ipo();
+ allqueue (REDRAWACTION, 0);
+ allqueue(REDRAWNLA, 0);
+ break;
+ case PADPLUSKEY:
+
+ dx= 0.1154*(v2d->cur.xmax-v2d->cur.xmin);
+ dy= 0.1154*(v2d->cur.ymax-v2d->cur.ymin);
+ if(val==SPACE_BUTS) {
+ dx/=2.0; dy/= 2.0;
+ }
+ v2d->cur.xmin+= dx;
+ v2d->cur.xmax-= dx;
+ v2d->cur.ymin+= dy;
+ v2d->cur.ymax-= dy;
+ test_view2d(G.v2d, curarea->winx, curarea->winy);
+ doredraw= 1;
+ break;
+ case PADMINUS:
+ dx= 0.15*(v2d->cur.xmax-v2d->cur.xmin);
+ dy= 0.15*(v2d->cur.ymax-v2d->cur.ymin);
+ if(val==SPACE_BUTS) {
+ dx/=2.0; dy/= 2.0;
+ }
+ v2d->cur.xmin-= dx;
+ v2d->cur.xmax+= dx;
+ v2d->cur.ymin-= dy;
+ v2d->cur.ymax+= dy;
+ test_view2d(G.v2d, curarea->winx, curarea->winy);
+ doredraw= 1;
+ break;
+ case PAGEUPKEY:
+ if(G.qual & LR_CTRLKEY) movekey_ipo(1);
+ else nextkey_ipo(1);
+ break;
+ case PAGEDOWNKEY:
+ if(G.qual & LR_CTRLKEY) movekey_ipo(-1);
+ else nextkey_ipo(-1);
+ break;
+ case HOMEKEY:
+ do_ipo_buttons(B_IPOHOME);
+ break;
+
+ case AKEY:
+ if(in_ipo_buttons()) {
+ swap_visible_editipo();
+ }
+ else swap_selectall_editipo();
+ allspace (REMAKEIPO, 0);
+ allqueue (REDRAWNLA, 0);
+ allqueue (REDRAWACTION, 0);
+ break;
+ case BKEY:
+ borderselect_ipo();
+ break;
+ case CKEY:
+ move_to_frame();
+ break;
+ case DKEY:
+ if(G.qual & LR_SHIFTKEY) add_duplicate_editipo();
+ break;
+ case GKEY:
+ transform_ipo('g');
+ break;
+ case HKEY:
+ if(G.qual & LR_SHIFTKEY) sethandles_ipo(HD_AUTO);
+ else sethandles_ipo(HD_ALIGN);
+ break;
+ case JKEY:
+ join_ipo();
+ break;
+ case KKEY:
+ if(G.sipo->showkey) {
+ G.sipo->showkey= 0;
+ swap_selectall_editipo(); /* sel all */
+ }
+ else G.sipo->showkey= 1;
+ free_ipokey(&G.sipo->ipokey);
+ if(G.sipo->ipo) G.sipo->ipo->showkey= G.sipo->showkey;
+
+ scrarea_queue_headredraw(curarea);
+ allqueue(REDRAWVIEW3D, 0);
+ doredraw= 1;
+ break;
+ case RKEY:
+ ipo_record();
+ break;
+ case SKEY:
+ if(G.qual & LR_SHIFTKEY) ipo_snapmenu();
+ else transform_ipo('s');
+ break;
+ case TKEY:
+ set_ipotype();
+ break;
+ case VKEY:
+ sethandles_ipo(HD_VECT);
+ break;
+ case XKEY:
+ case DELKEY:
+ if(G.qual & LR_SHIFTKEY) delete_key();
+ else del_ipo();
+ break;
+ }
+ }
+
+ if(doredraw) scrarea_queue_winredraw(curarea);
+}
+
+void initipo(ScrArea *sa)
+{
+ SpaceIpo *sipo;
+
+ sipo= MEM_callocN(sizeof(SpaceIpo), "initipo");
+ BLI_addhead(&sa->spacedata, sipo);
+
+ sipo->spacetype= SPACE_IPO;
+ /* sipo space loopt van (0,-?) tot (??,?) */
+ sipo->v2d.tot.xmin= 0.0;
+ sipo->v2d.tot.ymin= -10.0;
+ sipo->v2d.tot.xmax= G.scene->r.efra;
+ sipo->v2d.tot.ymax= 10.0;
+
+ sipo->v2d.cur= sipo->v2d.tot;
+
+ sipo->v2d.min[0]= 0.01;
+ sipo->v2d.min[1]= 0.01;
+
+ sipo->v2d.max[0]= 15000.0;
+ sipo->v2d.max[1]= 10000.0;
+
+ sipo->v2d.scroll= L_SCROLL+B_SCROLL;
+ sipo->v2d.keeptot= 0;
+
+ sipo->blocktype= ID_OB;
+}
+
+/* ******************** SPACE: INFO ********************** */
+
+void space_mipmap_button_function(int event) {
+ set_mipmap(!(U.gameflags & USERDEF_DISABLE_MIPMAP));
+
+ allqueue(REDRAWVIEW3D, 0);
+}
+
+void space_sound_button_function(int event)
+{
+ int a;
+ SYS_SystemHandle syshandle;
+
+ if ((syshandle = SYS_GetSystem()))
+ {
+ a = (U.gameflags & USERDEF_DISABLE_SOUND);
+ SYS_WriteCommandLineInt(syshandle, "noaudio", a);
+ }
+}
+
+void drawinfospace(void)
+{
+ uiBlock *block;
+ float fac;
+ int dx;
+ char naam[32];
+
+ if(curarea->win==0) return;
+
+ glClearColor(0.5, 0.5, 0.5, 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ fac= ((float)curarea->winx)/1280.0;
+ myortho2(0.0, 1280.0, 0.0, curarea->winy/fac);
+
+ sprintf(naam, "infowin %d", curarea->win);
+ block= uiNewBlock(&curarea->uiblocks, naam, UI_EMBOSSX, UI_HELV, curarea->win);
+
+ uiBlockSetCol(block, BUTBLUE);
+ uiDefButS(block, TOG|BIT|0, B_RESETAUTOSAVE, "Auto Temp Save", 45,32,126,20, &(U.flag), 0, 0, 0, 0, "Enables/Disables the automatic temp. file saving");
+ uiBlockSetCol(block, BUTGREY);
+ uiDefBut(block, TEX, 0, "Dir:", 45,10,127,20, U.tempdir, 1.0, 63.0, 0, 0, "The directory for temp. files");
+ uiDefButI(block, NUM, B_RESETAUTOSAVE, "Time:", 174,32,91,20, &(U.savetime), 1.0, 60.0, 0, 0, "The time in minutes to wait between temp. saves");
+ uiBlockSetCol(block, BUTSALMON);
+ uiDefBut(block, BUT, B_LOADTEMP, "Load Temp", 174,10,90,20, 0, 0, 0, 0, 0, "Loads the most recently saved temp file");
+
+ uiBlockSetCol(block, BUTGREY);
+ uiDefButS(block, NUM, 0, "Versions:", 281,10,86,42, &U.versions, 0.0, 32.0, 0, 0, "The number of old versions to maintain when saving");
+
+ uiBlockSetCol(block, BUTYELLOW);
+ uiDefButI(block, TOG|BIT|USERDEF_VERTEX_ARRAYS_BIT, 0, "Vertex arrays",
+ 389,54,86,20, &(U.gameflags), 0, 0, 0, 0,
+ "Toggle between vertex arrays on (less reliable) and off (more reliable)");
+ uiDefButI(block, TOG|BIT|USERDEF_DISABLE_SOUND_BIT, B_SOUNDTOGGLE, "No sound",
+ 478,54,86,20, &(U.gameflags), 0, 0, 0, 0,
+ "Toggle between sound on and sound off");
+
+ uiDefButI(block, TOG|BIT|USERDEF_DISABLE_MIPMAP_BIT, B_MIPMAPCHANGED, "No Mipmaps",
+ 569,54,78,20, &(U.gameflags), 0, 0, 0, 0,
+ "Toggle between Mipmap textures on (beautiful) and off (fast)");
+
+ uiBlockSetCol(block, BUTGREEN);
+ uiDefButS(block, TOG|BIT|4, 0, "Scene Global",
+ 389,32,86,20, &(U.flag), 0, 0, 0, 0,
+ "Forces the current Scene to be displayed in all Screens");
+ uiDefButS(block, TOG|BIT|5, 0, "TrackBall",
+ 389,10,86,20, &(U.flag), 0, 0, 0, 0,
+ "Switches between trackball and turntable view rotation methods (MiddleMouse)");
+ uiDefButS(block, TOG|BIT|12, 0, "2-Mouse",
+ 478,10,86,20, &(U.flag), 0, 0, 0, 0,
+ "Maps ALT+LeftMouse to MiddleMouse button");
+ uiDefButS(block, TOG|BIT|8, 0, "Mat on Obj",
+ 569,9,78,20, &(U.flag), 0, 0, 0, 0,
+ "Sets whether Material data is linked to Obj or ObjData");
+ uiDefButS(block, TOG|BIT|9, B_U_CAPSLOCK, "NoCapsLock",
+ 478,32,86,20, &(U.flag), 0, 0, 0, 0,
+ "Deactives the CapsLock button (only applies to text input)");
+ uiDefButS(block, TOG|BIT|10, 0, "Viewmove",
+ 569,32,78,20, &(U.flag), 0, 0, 0, 0,
+ "Sets the default action for the middle mouse button");
+
+ uiDefButS(block, TOG|BIT|13, 0, "noNumpad",
+ 653,10,76,20, &(U.flag), 0, 0, 0, 0,
+ "For laptops: keys 1 to 0 become numpad keys");
+ uiDefButS(block, TOG|BIT|11, 0, "ToolTips",
+ 653,32,76,20, &(U.flag), 0, 0, 0, 0,
+ "Enables/Disables tooltips");
+
+// uiDefButS(block, ICONTOG|BIT|14, 0, ICON(), 733,10,50,42, &(U.flag), 0, 0, 0, 0, "Automatic keyframe insertion");
+ uiDefButS(block, TOG|BIT|14, 0, "KeyAC", 733,32,50,20, &(U.flag), 0, 0, 0, 0, "Automatic keyframe insertion for actions");
+ uiDefButS(block, TOG|BIT|15, 0, "KeyOB", 733,10,50,20, &(U.flag), 0, 0, 0, 0, "Automatic keyframe insertion for objects");
+
+ uiDefButS(block, TOG|BIT|1, 0, "Grab Grid", 788,32,106,20, &(U.flag), 0, 0, 0, 0, "Changes default step mode for grabbing");
+ uiDefButS(block, TOG|BIT|2, 0, "Rot", 842,10,52,20, &(U.flag), 0, 0, 0, 0, "Changes default step mode for rotation");
+ uiDefButS(block, TOG|BIT|3, 0, "Size", 788,10,52,20, &(U.flag), 0, 0, 0, 0, "Changes default step mode for scaling");
+
+ uiDefButS(block, TOG|BIT|0, 0, "Dupli Mesh", 902,32,90,20, &(U.dupflag), 0, 0, 0, 0, "Causes Mesh data to be duplicated with Shift+D");
+ uiDefButS(block, TOG|BIT|9, 0, "Armature", 902,10,90,20, &(U.dupflag), 0, 0, 0, 0, "Causes Armature data to be duplicated with Shift+D");
+
+ uiDefButS(block, TOG|BIT|1, 0, "Curve", 995,32,50,20, &(U.dupflag), 0, 0, 0, 0, "Causes Curve data to be duplicated with Shift+D");
+ uiDefButS(block, TOG|BIT|2, 0, "Surf", 995,10,50,20, &(U.dupflag), 0, 0, 0, 0, "Causes Surface data to be duplicated with Shift+D");
+ uiDefButS(block, TOG|BIT|3, 0, "Text", 1048,32,50,20, &(U.dupflag), 0, 0, 0, 0, "Causes Text data to be duplicated with Shift+D");
+ uiDefButS(block, TOG|BIT|4, 0, "MBall", 1048,10,50,20, &(U.dupflag), 0, 0, 0, 0, "Causes Metaball data to be duplicated with Shift+D");
+ uiDefButS(block, TOG|BIT|5, 0, "Lamp", 1101,32,50,20, &(U.dupflag), 0, 0, 0, 0, "Causes Lamp data to be duplicated with Shift+D");
+ uiDefButS(block, TOG|BIT|6, 0, "Ipo", 1101,10,50,20, &(U.dupflag), 0, 0, 0, 0, "Causes Ipo data to be duplicated with Shift+D");
+ uiDefButS(block, TOG|BIT|7, 0, "Material", 1153,32,70,20, &(U.dupflag), 0, 0, 0, 0, "Causes Material data to be duplicated with Shift+D");
+ uiDefButS(block, TOG|BIT|8, 0, "Texture", 1153,10,70,20, &(U.dupflag), 0, 0, 0, 0, "Causes Texture data to be duplicated with Shift+D");
+
+
+
+ uiBlockSetCol(block, BUTGREY);
+ dx= (1280-90)/6;
+
+
+#define _XPOS_ 45
+#define _YPOS_ 80
+#define _BUTH_ 20
+#define _RULESPACE_ 2
+ uiDefBut(block, TEX, 0, "Python:",
+ _XPOS_,_YPOS_-_BUTH_-_RULESPACE_,(short)dx,_BUTH_, U.pythondir, 1.0, 63.0, 0, 0,
+ "The default directory for Python scripts");
+ uiDefBut(block, TEX, 0, "Fonts:",
+ _XPOS_,_YPOS_,(short)dx,_BUTH_, U.fontdir, 1.0, 63.0, 0, 0,
+ "The default directory to search when loading fonts");
+ uiDefBut(block, TEX, 0, "Render:",
+ (short)(_XPOS_+dx),_YPOS_,(short)dx,_BUTH_, U.renderdir, 1.0, 63.0, 0, 0,
+ "The default directory to choose for rendering");
+ uiDefBut(block, TEX, 0, "Textures:",
+ (short)(_XPOS_+2*dx),_YPOS_,(short)dx,_BUTH_, U.textudir, 1.0, 63.0, 0, 0,
+ "The default directory to search when loading textures");
+ uiDefBut(block, TEX, 0, "TexPlugin:",
+ (short)(_XPOS_+3*dx),_YPOS_,(short)dx,_BUTH_, U.plugtexdir, 1.0, 63.0, 0, 0,
+ "The default directory to search when loading texture plugins");
+ uiDefBut(block, TEX, 0, "SeqPlugin:",
+ (short)(_XPOS_+4*dx),_YPOS_,(short)dx,_BUTH_, U.plugseqdir, 1.0, 63.0, 0, 0,
+ "The default directory to search when loading sequence plugins");
+ uiDefBut(block, TEX, 0, "Sounds:",
+ (short)(_XPOS_+5*dx),_YPOS_,(short)dx,_BUTH_, U.sounddir, 1.0, 63.0, 0, 0,
+ "The default directory to search when loading sounds");
+#undef _XPOS_
+#undef _YPOS_
+#undef _BUTH_
+#undef _RULESPACE_
+ uiDrawBlock(block);
+}
+
+void winqreadinfospace(unsigned short event, short val, char ascii)
+{
+ if(val) {
+ if( uiDoBlocks(&curarea->uiblocks, event)!=UI_NOTHING ) event= 0;
+
+ switch(event) {
+ case UI_BUT_EVENT:
+ do_global_buttons(val);
+
+ break;
+ }
+ }
+}
+
+void init_infospace(ScrArea *sa)
+{
+ SpaceInfo *sinfo;
+
+ sinfo= MEM_callocN(sizeof(SpaceInfo), "initinfo");
+ BLI_addhead(&sa->spacedata, sinfo);
+}
+
+/* ******************** SPACE: BUTS ********************** */
+
+extern void drawbutspace(void); /* buttons.c */
+
+void changebutspace(void)
+{
+ if(G.v2d==0) return;
+
+ test_view2d(G.v2d, curarea->winx, curarea->winy);
+ myortho2(G.v2d->cur.xmin, G.v2d->cur.xmax, G.v2d->cur.ymin, G.v2d->cur.ymax);
+}
+
+void winqreadbutspace(unsigned short event, short val, char ascii)
+{
+ SpaceButs *sbuts= curarea->spacedata.first;
+ ScrArea *sa, *sa3d;
+ int doredraw= 0;
+
+ if(val) {
+
+ if( uiDoBlocks(&curarea->uiblocks, event)!=UI_NOTHING ) event= 0;
+
+ switch(event) {
+ case UI_BUT_EVENT:
+ do_blenderbuttons(val);
+ break;
+
+ case MIDDLEMOUSE:
+ view2dmove(); /* in drawipo.c */
+ break;
+ case PADPLUSKEY:
+ case PADMINUS:
+ val= SPACE_BUTS;
+ winqreadipo(event, val, 0);
+ break;
+ case RENDERPREVIEW:
+ BIF_previewrender(sbuts);
+ break;
+
+ case HOMEKEY:
+ do_buts_buttons(B_BUTSHOME);
+ break;
+
+
+ /* if only 1 view, also de persp, excluding arrowkeys */
+ case PAD0: case PAD1: case PAD3:
+ case PAD5: case PAD7: case PAD9:
+ case PADENTER: case ZKEY: case PKEY:
+ sa3d= 0;
+ sa= G.curscreen->areabase.first;
+ while(sa) {
+ if(sa->spacetype==SPACE_VIEW3D) {
+ if(sa3d) return;
+ sa3d= sa;
+ }
+ sa= sa->next;
+ }
+ if(sa3d) {
+ sa= curarea;
+ areawinset(sa3d->win);
+
+ if(event==PKEY) start_game();
+ else if(event==ZKEY) winqread3d(event, val, 0);
+ else persptoetsen(event);
+
+ scrarea_queue_winredraw(sa3d);
+ scrarea_queue_headredraw(sa3d);
+ areawinset(sa->win);
+ }
+ }
+ }
+
+ if(doredraw) scrarea_queue_winredraw(curarea);
+}
+
+void set_rects_butspace(SpaceButs *buts)
+{
+ /* buts space loopt van (0,0) tot (1280, 228) */
+
+ buts->v2d.tot.xmin= 0.0;
+ buts->v2d.tot.ymin= 0.0;
+ buts->v2d.tot.xmax= 1279.0;
+ buts->v2d.tot.ymax= 228.0;
+
+ buts->v2d.min[0]= 256.0;
+ buts->v2d.min[1]= 42.0;
+
+ buts->v2d.max[0]= 1600.0;
+ buts->v2d.max[1]= 450.0;
+
+ buts->v2d.minzoom= 0.5;
+ buts->v2d.maxzoom= 1.41;
+
+ buts->v2d.scroll= 0;
+ buts->v2d.keepaspect= 1;
+ buts->v2d.keepzoom= 1;
+ buts->v2d.keeptot= 1;
+
+}
+
+void test_butspace(void)
+{
+ ScrArea *area= curarea;
+ int blocksmin= uiBlocksGetYMin(&area->uiblocks)-10.0;
+
+ G.buts->v2d.tot.ymin= MIN2(0.0, blocksmin-10.0);
+}
+
+void init_butspace(ScrArea *sa)
+{
+ SpaceButs *buts;
+
+ buts= MEM_callocN(sizeof(SpaceButs), "initbuts");
+ BLI_addhead(&sa->spacedata, buts);
+
+ buts->spacetype= SPACE_BUTS;
+ buts->scaflag= BUTS_SENS_LINK|BUTS_SENS_ACT|BUTS_CONT_ACT|BUTS_ACT_ACT|BUTS_ACT_LINK;
+
+ /* set_rects doet alleen defaults, zodat na het filezen de cur niet verandert */
+ set_rects_butspace(buts);
+ buts->v2d.cur= buts->v2d.tot;
+}
+
+void extern_set_butspace(int fkey)
+{
+ ScrArea *sa;
+ SpaceButs *sbuts;
+
+ /* als een ftoets ingedrukt: de dichtsbijzijnde buttonwindow wordt gezet */
+ if(curarea->spacetype==SPACE_BUTS) sa= curarea;
+ else {
+ /* area vinden */
+ sa= G.curscreen->areabase.first;
+ while(sa) {
+ if(sa->spacetype==SPACE_BUTS) break;
+ sa= sa->next;
+ }
+ }
+
+ if(sa==0) return;
+
+ if(sa!=curarea) areawinset(sa->win);
+
+ sbuts= sa->spacedata.first;
+
+ if(fkey==F4KEY) sbuts->mainb= BUTS_LAMP;
+ else if(fkey==F5KEY) sbuts->mainb= BUTS_MAT;
+ else if(fkey==F6KEY) sbuts->mainb= BUTS_TEX;
+ else if(fkey==F7KEY) sbuts->mainb= BUTS_ANIM;
+ else if(fkey==F8KEY) sbuts->mainb= BUTS_GAME;
+ else if(fkey==F9KEY) sbuts->mainb= BUTS_EDIT;
+ else if(fkey==F10KEY) sbuts->mainb= BUTS_RENDER;
+
+ scrarea_queue_headredraw(sa);
+ scrarea_queue_winredraw(sa);
+ BIF_preview_changed(sbuts);
+}
+
+/* ******************** SPACE: SEQUENCE ********************** */
+
+/* extern void drawseqspace(); BIF_drawseq.h */
+
+void winqreadsequence(unsigned short event, short val, char ascii)
+{
+ SpaceSeq *sseq= curarea->spacedata.first;
+ View2D *v2d= &sseq->v2d;
+ extern Sequence *last_seq;
+ float dx, dy;
+ int doredraw= 0, cfra, first;
+ short mval[2];
+
+ if(curarea->win==0) return;
+
+ if(val) {
+
+ if( uiDoBlocks(&curarea->uiblocks, event)!=UI_NOTHING ) event= 0;
+
+ switch(event) {
+ case LEFTMOUSE:
+ if(sseq->mainb || view2dmove()==0) {
+
+ first= 1;
+ set_special_seq_update(1);
+
+ do {
+ getmouseco_areawin(mval);
+ areamouseco_to_ipoco(v2d, mval, &dx, &dy);
+
+ cfra= (int)dx;
+ if(cfra< 1) cfra= 1;
+ /* else if(cfra> EFRA) cfra= EFRA; */
+
+ if( cfra!=CFRA || first ) {
+ first= 0;
+
+ CFRA= cfra;
+ force_draw();
+ }
+
+ } while(get_mbut()&L_MOUSE);
+
+ set_special_seq_update(0);
+
+ update_for_newframe();
+ }
+ break;
+ case MIDDLEMOUSE:
+ if(sseq->mainb) break;
+ view2dmove(); /* in drawipo.c */
+ break;
+ case RIGHTMOUSE:
+ if(sseq->mainb) break;
+ mouse_select_seq();
+ break;
+ case PADPLUSKEY:
+ if(sseq->mainb) {
+ sseq->zoom++;
+ if(sseq->zoom>8) sseq->zoom= 8;
+ }
+ else {
+ if(G.qual) {
+ if(G.qual & LR_SHIFTKEY) insert_gap(25, CFRA);
+ else if(G.qual & LR_ALTKEY) insert_gap(250, CFRA);
+ allqueue(REDRAWSEQ, 0);
+ }
+ else {
+ dx= 0.1154*(v2d->cur.xmax-v2d->cur.xmin);
+ v2d->cur.xmin+= dx;
+ v2d->cur.xmax-= dx;
+ test_view2d(G.v2d, curarea->winx, curarea->winy);
+ }
+ }
+ doredraw= 1;
+ break;
+ case PADMINUS:
+ if(sseq->mainb) {
+ sseq->zoom--;
+ if(sseq->zoom<1) sseq->zoom= 1;
+ }
+ else {
+ if(G.qual) {
+ if(G.qual & LR_SHIFTKEY) no_gaps();
+ }
+ else {
+ dx= 0.15*(v2d->cur.xmax-v2d->cur.xmin);
+ v2d->cur.xmin-= dx;
+ v2d->cur.xmax+= dx;
+ test_view2d(G.v2d, curarea->winx, curarea->winy);
+ }
+ }
+ doredraw= 1;
+ break;
+ case HOMEKEY:
+ do_seq_buttons(B_SEQHOME);
+ break;
+ case PADPERIOD:
+ if(last_seq) {
+ CFRA= last_seq->startdisp;
+ v2d->cur.xmin= last_seq->startdisp- (last_seq->len/20);
+ v2d->cur.xmax= last_seq->enddisp+ (last_seq->len/20);
+ update_for_newframe();
+ }
+ break;
+
+ case AKEY:
+ if(sseq->mainb) break;
+ if(G.qual & LR_SHIFTKEY) {
+ add_sequence(0);
+ }
+ else swap_select_seq();
+ break;
+ case BKEY:
+ if(sseq->mainb) break;
+ borderselect_seq();
+ break;
+ case CKEY:
+ if(last_seq && (last_seq->flag & (SEQ_LEFTSEL+SEQ_RIGHTSEL))) {
+ if(last_seq->flag & SEQ_LEFTSEL) CFRA= last_seq->startdisp;
+ else CFRA= last_seq->enddisp-1;
+
+ dx= CFRA-(v2d->cur.xmax+v2d->cur.xmin)/2;
+ v2d->cur.xmax+= dx;
+ v2d->cur.xmin+= dx;
+ update_for_newframe();
+ }
+ else change_sequence();
+ break;
+ case DKEY:
+ if(sseq->mainb) break;
+ if(G.qual & LR_SHIFTKEY) add_duplicate_seq();
+ break;
+ case EKEY:
+ break;
+ case FKEY:
+ set_filter_seq();
+ break;
+ case GKEY:
+ if(sseq->mainb) break;
+ transform_seq('g');
+ break;
+ case MKEY:
+ if(G.qual & LR_ALTKEY) un_meta();
+ else make_meta();
+ break;
+ case SKEY:
+ if(G.qual & LR_SHIFTKEY) seq_snapmenu();
+ break;
+ case TKEY:
+ touch_seq_files();
+ break;
+ case XKEY:
+ case DELKEY:
+ if(sseq->mainb) break;
+ del_seq();
+ break;
+ }
+ }
+
+ if(doredraw) scrarea_queue_winredraw(curarea);
+}
+
+
+void init_seqspace(ScrArea *sa)
+{
+ SpaceSeq *sseq;
+
+ sseq= MEM_callocN(sizeof(SpaceSeq), "initseqspace");
+ BLI_addhead(&sa->spacedata, sseq);
+
+ sseq->spacetype= SPACE_SEQ;
+ sseq->zoom= 1;
+
+ /* seq space loopt van (0,8) tot (250, 0) */
+
+ sseq->v2d.tot.xmin= 0.0;
+ sseq->v2d.tot.ymin= 0.0;
+ sseq->v2d.tot.xmax= 250.0;
+ sseq->v2d.tot.ymax= 8.0;
+
+ sseq->v2d.cur= sseq->v2d.tot;
+
+ sseq->v2d.min[0]= 10.0;
+ sseq->v2d.min[1]= 4.0;
+
+ sseq->v2d.max[0]= 32000.0;
+ sseq->v2d.max[1]= MAXSEQ;
+
+ sseq->v2d.minzoom= 0.1;
+ sseq->v2d.maxzoom= 10.0;
+
+ sseq->v2d.scroll= L_SCROLL+B_SCROLL;
+ sseq->v2d.keepaspect= 0;
+ sseq->v2d.keepzoom= 0;
+ sseq->v2d.keeptot= 0;
+}
+
+/* ******************** SPACE: ACTION ********************** */
+extern void drawactionspace(void);
+extern void winqreadactionspace(unsigned short, short, char ascii);
+
+void init_actionspace(ScrArea *sa)
+{
+ SpaceAction *saction;
+
+ saction= MEM_callocN(sizeof(SpaceAction), "initactionspace");
+ BLI_addhead(&sa->spacedata, saction);
+
+ saction->spacetype= SPACE_ACTION;
+
+ saction->v2d.tot.xmin= 1.0;
+ saction->v2d.tot.ymin= 0.0;
+ saction->v2d.tot.xmax= 1000.0;
+ saction->v2d.tot.ymax= 1000.0;
+
+ saction->v2d.cur.xmin= -5.0;
+ saction->v2d.cur.ymin= 0.0;
+ saction->v2d.cur.xmax= 65.0;
+ saction->v2d.cur.ymax= 1000.0;
+
+
+ saction->v2d.min[0]= 0.0;
+ saction->v2d.min[1]= 0.0;
+
+ saction->v2d.max[0]= 1000.0;
+ saction->v2d.max[1]= 1000.0;
+
+ saction->v2d.minzoom= 0.1;
+ saction->v2d.maxzoom= 10;
+
+ saction->v2d.scroll= R_SCROLL+B_SCROLL;
+ saction->v2d.keepaspect= 0;
+ saction->v2d.keepzoom= V2D_LOCKZOOM_Y;
+ saction->v2d.keeptot= 0;
+
+}
+
+void free_actionspace(SpaceAction *saction)
+{
+ /* don't free saction itself */
+
+ /* __PINFAKE */
+/* if (saction->flag & SACTION_PIN)
+ if (saction->action)
+ saction->action->id.us --;
+
+*/ /* end PINFAKE */
+}
+
+
+/* ******************** SPACE: FILE ********************** */
+
+void init_filespace(ScrArea *sa)
+{
+ SpaceFile *sfile;
+
+ sfile= MEM_callocN(sizeof(SpaceFile), "initfilespace");
+ BLI_addhead(&sa->spacedata, sfile);
+
+ sfile->dir[0]= '/';
+ sfile->type= FILE_UNIX;
+
+ sfile->spacetype= SPACE_FILE;
+}
+
+void init_textspace(ScrArea *sa)
+{
+ SpaceText *st;
+
+ st= MEM_callocN(sizeof(SpaceText), "inittextspace");
+ BLI_addhead(&sa->spacedata, st);
+
+ st->spacetype= SPACE_TEXT;
+
+ st->text= NULL;
+ st->flags= 0;
+
+ st->font_id= 5;
+ st->lheight= 12;
+
+ st->top= 0;
+}
+
+void init_imaselspace(ScrArea *sa)
+{
+ SpaceImaSel *simasel;
+
+ simasel= MEM_callocN(sizeof(SpaceImaSel), "initimaselspace");
+ BLI_addhead(&sa->spacedata, simasel);
+
+ simasel->spacetype= SPACE_IMASEL;
+
+ simasel->mode = 7;
+ strcpy (simasel->dir, U.textudir); /* TON */
+ strcpy (simasel->file, "");
+ strcpy(simasel->fole, simasel->file);
+ strcpy(simasel->dor, simasel->dir);
+
+ simasel->first_sel_ima = 0;
+ simasel->hilite_ima = 0;
+ simasel->firstdir = 0;
+ simasel->firstfile = 0;
+ simasel->cmap = 0;
+ simasel->returnfunc = 0;
+
+ simasel->title[0] = 0;
+
+ clear_ima_dir(simasel);
+
+ // simasel->cmap= IMB_loadiffmem((int*)datatoc_cmap_tga, IB_rect|IB_cmap);
+ simasel->cmap= IMB_ibImageFromMemory((int *)datatoc_cmap_tga, datatoc_cmap_tga_size, IB_rect|IB_cmap);
+ if (!simasel->cmap) {
+ error("in console");
+ printf("Image select cmap file not found \n");
+ }
+}
+
+/* ******************** SPACE: SOUND ********************** */
+
+extern void drawsoundspace(void);
+extern void winqreadsoundspace(unsigned short, short, char ascii);
+
+void init_soundspace(ScrArea *sa)
+{
+ SpaceSound *ssound;
+
+ ssound= MEM_callocN(sizeof(SpaceSound), "initsoundspace");
+ BLI_addhead(&sa->spacedata, ssound);
+
+ ssound->spacetype= SPACE_SOUND;
+
+ /* sound space loopt van (0,8) tot (250, 0) */
+
+ ssound->v2d.tot.xmin= -4.0;
+ ssound->v2d.tot.ymin= -4.0;
+ ssound->v2d.tot.xmax= 250.0;
+ ssound->v2d.tot.ymax= 255.0;
+
+ ssound->v2d.cur.xmin= -4.0;
+ ssound->v2d.cur.ymin= -4.0;
+ ssound->v2d.cur.xmax= 50.0;
+ ssound->v2d.cur.ymax= 255.0;
+
+ ssound->v2d.min[0]= 1.0;
+ ssound->v2d.min[1]= 259.0;
+
+ ssound->v2d.max[0]= 32000.0;
+ ssound->v2d.max[1]= 259;
+
+ ssound->v2d.minzoom= 0.1;
+ ssound->v2d.maxzoom= 10.0;
+
+ ssound->v2d.scroll= B_SCROLL;
+ ssound->v2d.keepaspect= 0;
+ ssound->v2d.keepzoom= 0;
+ ssound->v2d.keeptot= 0;
+
+}
+
+void free_soundspace(SpaceSound *ssound)
+{
+ /* don't free ssound itself */
+
+
+}
+
+/* ******************** SPACE: IMAGE ********************** */
+
+/* extern void drawimagespace(); BIF_drawimage.h */
+
+void winqreadimagespace(unsigned short event, short val, char ascii)
+{
+ SpaceImage *sima= curarea->spacedata.first;
+ View2D *v2d= &sima->v2d;
+ int width, height;
+#ifdef NAN_TPT
+ IMG_BrushPtr brush;
+ IMG_CanvasPtr canvas;
+ int rowBytes;
+ short xy_prev[2], xy_curr[2];
+ float uv_prev[2], uv_curr[2];
+ extern VPaint Gvp;
+#endif /* NAN_TPT */
+ if(val==0) return;
+
+ if( uiDoBlocks(&curarea->uiblocks, event)!=UI_NOTHING ) event= 0;
+
+ if (sima->flag & SI_DRAWTOOL) {
+#ifdef NAN_TPT
+ /* Draw tool is active */
+ switch(event) {
+ case LEFTMOUSE:
+ /* Paranoia checks */
+ if (!sima) break;
+ if (!sima->image) break;
+ if (!sima->image->ibuf) break;
+ if (sima->image->packedfile) {
+ error("Painting in packed images not supported");
+ break;
+ }
+
+ brush = IMG_BrushCreate(Gvp.size, Gvp.size, Gvp.r, Gvp.g, Gvp.b, Gvp.a);
+ /* MAART: skipx is not set most of the times. Make a guess. */
+ rowBytes = sima->image->ibuf->skipx ? sima->image->ibuf->skipx : sima->image->ibuf->x * 4;
+ canvas = IMG_CanvasCreateFromPtr(sima->image->ibuf->rect, sima->image->ibuf->x, sima->image->ibuf->y, rowBytes);
+
+ getmouseco_areawin(xy_prev);
+ while (get_mbut() & L_MOUSE) {
+ getmouseco_areawin(xy_curr);
+ /* Check if mouse position changed */
+ if ((xy_prev[0] != xy_curr[0]) || (xy_prev[1] != xy_curr[1])) {
+ /* Convert mouse coordinates to u,v and draw */
+ areamouseco_to_ipoco(v2d, xy_prev, &uv_prev[0], &uv_prev[1]);
+ areamouseco_to_ipoco(v2d, xy_curr, &uv_curr[0], &uv_curr[1]);
+ IMG_CanvasDrawLineUV(canvas, brush, uv_prev[0], uv_prev[1], uv_curr[0], uv_curr[1]);
+ if (G.sima->lock) {
+ /* Make OpenGL aware of a changed texture */
+ free_realtime_image(sima->image);
+ /* Redraw this view and the 3D view */
+ force_draw_plus(SPACE_VIEW3D);
+ }
+ else {
+ /* Redraw only this view */
+ force_draw();
+ }
+ xy_prev[0] = xy_curr[0];
+ xy_prev[1] = xy_curr[1];
+ }
+ }
+ /* Set the dirty bit in the image so that it is clear that it has been modified. */
+ sima->image->ibuf->userflags |= IB_BITMAPDIRTY;
+ if (!G.sima->lock) {
+ /* Make OpenGL aware of a changed texture */
+ free_realtime_image(sima->image);
+ /* Redraw this view and the 3D view */
+ force_draw_plus(SPACE_VIEW3D);
+ }
+ IMG_BrushDispose(brush);
+ IMG_CanvasDispose(canvas);
+ allqueue(REDRAWHEADERS, 0);
+ break;
+ }
+#endif /* NAN_TPT */
+ }
+ else {
+ /* Draw tool is inactive */
+ switch(event) {
+ case LEFTMOUSE:
+ if(G.qual & LR_SHIFTKEY) mouseco_to_curtile();
+ else gesture();
+ break;
+ case MIDDLEMOUSE:
+ image_viewmove();
+ break;
+ case RIGHTMOUSE:
+ mouse_select_sima();
+ break;
+ case AKEY:
+ select_swap_tface_uv();
+ break;
+ case BKEY:
+ borderselect_sima();
+ break;
+ case GKEY:
+ transform_tface_uv('g');
+ break;
+ case NKEY:
+ if(G.qual & LR_CTRLKEY) replace_names_but();
+ break;
+ case RKEY:
+ transform_tface_uv('r');
+ break;
+ case SKEY:
+ transform_tface_uv('s');
+ break;
+ }
+ }
+
+ /* Events handled always (whether the draw tool is active or not) */
+ switch (event) {
+ case MIDDLEMOUSE:
+ image_viewmove();
+ break;
+ case PADPLUSKEY:
+ sima->zoom *= 2;
+ scrarea_queue_winredraw(curarea);
+ break;
+ case HOMEKEY:
+ image_home();
+ break;
+ case PADMINUS:
+ sima->zoom /= 2;
+ /* Check if the image will still be visible after zooming out */
+ if (sima->zoom < 1) {
+ calc_image_view(G.sima, 'p');
+ if (sima->image) {
+ if (sima->image->ibuf) {
+ width = sima->image->ibuf->x * sima->zoom;
+ height = sima->image->ibuf->y * sima->zoom;
+ if ((width < 4) && (height < 4)) {
+ /* Image will become too small, reset value */
+ sima->zoom *= 2;
+ }
+ }
+ }
+ }
+ scrarea_queue_winredraw(curarea);
+ break;
+ }
+}
+
+
+void init_imagespace(ScrArea *sa)
+{
+ SpaceImage *sima;
+
+ sima= MEM_callocN(sizeof(SpaceImage), "initimaspace");
+ BLI_addhead(&sa->spacedata, sima);
+
+ sima->spacetype= SPACE_IMAGE;
+ sima->zoom= 1;
+}
+
+
+/* ******************** SPACE: IMASEL ********************** */
+
+extern void drawimasel(void);
+extern void winqreadimasel(unsigned short, short, char ascii);
+
+
+/* alles naar imasel.c */
+
+
+/* ******************** SPACE: OOPS ********************** */
+
+extern void drawoopsspace(void);
+
+void winqreadoopsspace(unsigned short event, short val, char ascii)
+{
+ SpaceOops *soops= curarea->spacedata.first;
+ View2D *v2d= &soops->v2d;
+ float dx, dy;
+
+ if(val==0) return;
+
+ if( uiDoBlocks(&curarea->uiblocks, event)!=UI_NOTHING ) event= 0;
+
+ switch(event) {
+ case LEFTMOUSE:
+ gesture();
+ break;
+ case MIDDLEMOUSE:
+ view2dmove(); /* in drawipo.c */
+ break;
+ case RIGHTMOUSE:
+ mouse_select_oops();
+ break;
+ case PADPLUSKEY:
+
+ dx= 0.1154*(v2d->cur.xmax-v2d->cur.xmin);
+ dy= 0.1154*(v2d->cur.ymax-v2d->cur.ymin);
+ v2d->cur.xmin+= dx;
+ v2d->cur.xmax-= dx;
+ v2d->cur.ymin+= dy;
+ v2d->cur.ymax-= dy;
+ test_view2d(G.v2d, curarea->winx, curarea->winy);
+ scrarea_queue_winredraw(curarea);
+ break;
+
+ case PADMINUS:
+
+ dx= 0.15*(v2d->cur.xmax-v2d->cur.xmin);
+ dy= 0.15*(v2d->cur.ymax-v2d->cur.ymin);
+ v2d->cur.xmin-= dx;
+ v2d->cur.xmax+= dx;
+ v2d->cur.ymin-= dy;
+ v2d->cur.ymax+= dy;
+ test_view2d(G.v2d, curarea->winx, curarea->winy);
+ scrarea_queue_winredraw(curarea);
+ break;
+
+ case HOMEKEY:
+ do_oops_buttons(B_OOPSHOME);
+ break;
+
+ case AKEY:
+ swap_select_all_oops();
+ scrarea_queue_winredraw(curarea);
+ break;
+ case BKEY:
+ borderselect_oops();
+ break;
+ case GKEY:
+ transform_oops('g');
+ break;
+ case LKEY:
+ if(G.qual & LR_SHIFTKEY) select_backlinked_oops();
+ else select_linked_oops();
+ break;
+ case SKEY:
+
+ if(G.qual & LR_ALTKEY) shrink_oops();
+ else if(G.qual & LR_SHIFTKEY) shuffle_oops();
+ else transform_oops('s');
+ break;
+
+ case ONEKEY:
+ do_layer_buttons(0); break;
+ case TWOKEY:
+ do_layer_buttons(1); break;
+ case THREEKEY:
+ do_layer_buttons(2); break;
+ case FOURKEY:
+ do_layer_buttons(3); break;
+ case FIVEKEY:
+ do_layer_buttons(4); break;
+ case SIXKEY:
+ do_layer_buttons(5); break;
+ case SEVENKEY:
+ do_layer_buttons(6); break;
+ case EIGHTKEY:
+ do_layer_buttons(7); break;
+ case NINEKEY:
+ do_layer_buttons(8); break;
+ case ZEROKEY:
+ do_layer_buttons(9); break;
+ case MINUSKEY:
+ do_layer_buttons(10); break;
+ case EQUALKEY:
+ do_layer_buttons(11); break;
+ case ACCENTGRAVEKEY:
+ do_layer_buttons(-1); break;
+
+ }
+}
+
+void init_v2d_oops(View2D *v2d)
+{
+ v2d->tot.xmin= -28.0;
+ v2d->tot.xmax= 28.0;
+ v2d->tot.ymin= -28.0;
+ v2d->tot.ymax= 28.0;
+
+ v2d->cur= v2d->tot;
+
+ v2d->min[0]= 10.0;
+ v2d->min[1]= 4.0;
+
+ v2d->max[0]= 320.0;
+ v2d->max[1]= 320.0;
+
+ v2d->minzoom= 0.01;
+ v2d->maxzoom= 2.0;
+
+ /* v2d->scroll= L_SCROLL+B_SCROLL; */
+ v2d->scroll= 0;
+ v2d->keepaspect= 1;
+ v2d->keepzoom= 0;
+ v2d->keeptot= 0;
+
+}
+
+void init_oopsspace(ScrArea *sa)
+{
+ SpaceOops *soops;
+
+ soops= MEM_callocN(sizeof(SpaceOops), "initoopsspace");
+ BLI_addhead(&sa->spacedata, soops);
+
+ soops->visiflag= OOPS_OB+OOPS_MA+OOPS_ME+OOPS_TE+OOPS_CU+OOPS_IP;
+
+ soops->spacetype= SPACE_OOPS;
+ init_v2d_oops(&soops->v2d);
+}
+
+/* ******************** SPACE: PAINT ********************** */
+
+
+/* ******************** SPACE: Text ********************** */
+
+extern void drawtextspace(void);
+extern void winqreadtextspace(unsigned short, short, char ascii);
+
+/* ******************** SPACE: ALGEMEEN ********************** */
+
+void newspace(ScrArea *sa, int type)
+{
+ if(type>=0) {
+ if(sa->spacetype != type) {
+ SpaceLink *sl;
+
+ sa->spacetype= type;
+ sa->headbutofs= 0;
+
+ uiFreeBlocks(&sa->uiblocks);
+ wich_cursor(sa);
+
+ if (sa->headwin) addqueue(sa->headwin, CHANGED, 1);
+ scrarea_queue_headredraw(sa);
+
+ addqueue(sa->win, CHANGED, 1);
+ scrarea_queue_winredraw(sa);
+
+ areawinset(sa->win);
+
+ bwin_clear_viewmat(sa->win);
+
+ for (sl= sa->spacedata.first; sl; sl= sl->next)
+ if(sl->spacetype==type)
+ break;
+
+ if (sl) {
+ BLI_remlink(&sa->spacedata, sl);
+ BLI_addhead(&sa->spacedata, sl);
+ } else {
+ if(type==SPACE_VIEW3D)
+ initview3d(sa);
+ else if(type==SPACE_IPO)
+ initipo(sa);
+ else if(type==SPACE_INFO)
+ init_infospace(sa);
+ else if(type==SPACE_BUTS)
+ init_butspace(sa);
+ else if(type==SPACE_FILE)
+ init_filespace(sa);
+ else if(type==SPACE_SEQ)
+ init_seqspace(sa);
+ else if(type==SPACE_IMAGE)
+ init_imagespace(sa);
+ else if(type==SPACE_IMASEL)
+ init_imaselspace(sa);
+ else if(type==SPACE_OOPS)
+ init_oopsspace(sa);
+ else if(type==SPACE_ACTION)
+ init_actionspace(sa);
+ else if(type==SPACE_TEXT)
+ init_textspace(sa);
+ else if(type==SPACE_SOUND)
+ init_soundspace(sa);
+ else if(type==SPACE_NLA)
+ init_nlaspace(sa);
+
+ sl= sa->spacedata.first;
+ sl->area= sa;
+ }
+ }
+ }
+
+
+ /* uitzondering: filespace */
+ if(curarea->spacetype==SPACE_FILE) {
+ SpaceFile *sfile= curarea->spacedata.first;
+
+ if(sfile->type==FILE_MAIN) {
+ freefilelist(sfile);
+ } else {
+ sfile->type= FILE_UNIX;
+ }
+
+ sfile->returnfunc= 0;
+ sfile->title[0]= 0;
+ if(sfile->filelist) test_flags_file(sfile);
+ }
+ /* uitzondering: imasel space */
+ else if(curarea->spacetype==SPACE_IMASEL) {
+ SpaceImaSel *simasel= curarea->spacedata.first;
+ simasel->returnfunc= 0;
+ simasel->title[0]= 0;
+ }
+}
+
+void freespacelist(ListBase *lb)
+{
+ SpaceLink *sl;
+
+ for (sl= lb->first; sl; sl= sl->next) {
+ if(sl->spacetype==SPACE_FILE) {
+ SpaceFile *sfile= (SpaceFile*) sl;
+ if(sfile->libfiledata)
+ BLO_blendhandle_close(sfile->libfiledata);
+ }
+ else if(sl->spacetype==SPACE_BUTS) {
+ SpaceButs *buts= (SpaceButs*) sl;
+ if(buts->rect) MEM_freeN(buts->rect);
+ if(G.buts==buts) G.buts= 0;
+ }
+ else if(sl->spacetype==SPACE_IPO) {
+ SpaceIpo *si= (SpaceIpo*) sl;
+ if(si->editipo) MEM_freeN(si->editipo);
+ free_ipokey(&si->ipokey);
+ if(G.sipo==si) G.sipo= 0;
+ }
+ else if(sl->spacetype==SPACE_VIEW3D) {
+ View3D *vd= (View3D*) sl;
+ if(vd->bgpic) {
+ if(vd->bgpic->rect) MEM_freeN(vd->bgpic->rect);
+ if(vd->bgpic->ima) vd->bgpic->ima->id.us--;
+ MEM_freeN(vd->bgpic);
+ }
+ if(vd->localvd) MEM_freeN(vd->localvd);
+ if(G.vd==vd) G.vd= 0;
+ }
+ else if(sl->spacetype==SPACE_OOPS) {
+ free_oopspace((SpaceOops *)sl);
+ }
+ else if(sl->spacetype==SPACE_IMASEL) {
+ free_imasel((SpaceImaSel *)sl);
+ }
+ else if(sl->spacetype==SPACE_ACTION) {
+ free_actionspace((SpaceAction*)sl);
+ }
+ else if(sl->spacetype==SPACE_NLA){
+/* free_nlaspace((SpaceNla*)sl); */
+ }
+ else if(sl->spacetype==SPACE_TEXT) {
+ free_textspace((SpaceText *)sl);
+ }
+ else if(sl->spacetype==SPACE_SOUND) {
+ free_soundspace((SpaceSound *)sl);
+ }
+ }
+
+ BLI_freelistN(lb);
+}
+
+void duplicatespacelist(ScrArea *newarea, ListBase *lb1, ListBase *lb2)
+{
+ SpaceLink *sl;
+
+ duplicatelist(lb1, lb2);
+
+ /* lb1 is kopie van lb2, van lb2 geven we de filelist vrij */
+
+ sl= lb2->first;
+ while(sl) {
+ if(sl->spacetype==SPACE_FILE) {
+ SpaceFile *sfile= (SpaceFile*) sl;
+ sfile->libfiledata= 0;
+ sfile->filelist= 0;
+ }
+ else if(sl->spacetype==SPACE_OOPS) {
+ SpaceOops *so= (SpaceOops *)sl;
+ so->oops.first= so->oops.last= 0;
+ }
+ else if(sl->spacetype==SPACE_IMASEL) {
+ check_imasel_copy((SpaceImaSel *) sl);
+ }
+ else if(sl->spacetype==SPACE_TEXT) {
+ }
+ /* __PINFAKE */
+/* else if(sfile->spacetype==SPACE_ACTION) {
+ SpaceAction *sa= (SpaceAction *)sfile;
+ if (sa->flag & SACTION_PIN)
+ if (sa->action)
+ sa->action->id.us++;
+
+ }
+*/ /* end PINFAKE */
+
+ sl= sl->next;
+ }
+
+ sl= lb1->first;
+ while(sl) {
+ sl->area= newarea;
+
+ if(sl->spacetype==SPACE_BUTS) {
+ SpaceButs *buts= (SpaceButs *)sl;
+ buts->rect= 0;
+ }
+ else if(sl->spacetype==SPACE_IPO) {
+ SpaceIpo *si= (SpaceIpo *)sl;
+ si->editipo= 0;
+ si->ipokey.first= si->ipokey.last= 0;
+ }
+ else if(sl->spacetype==SPACE_VIEW3D) {
+ View3D *vd= (View3D *)sl;
+ if(vd->bgpic) {
+ vd->bgpic= MEM_dupallocN(vd->bgpic);
+ vd->bgpic->rect= 0;
+ if(vd->bgpic->ima) vd->bgpic->ima->id.us++;
+ }
+ }
+ sl= sl->next;
+ }
+
+ /* nog een keer: van oude View3D de localview restoren (ivm full) */
+ sl= lb2->first;
+ while(sl) {
+ if(sl->spacetype==SPACE_VIEW3D) {
+ View3D *v3d= (View3D*) sl;
+ if(v3d->localvd) {
+ restore_localviewdata(v3d);
+ v3d->localvd= 0;
+ v3d->localview= 0;
+ v3d->lay &= 0xFFFFFF;
+ }
+ }
+ sl= sl->next;
+ }
+}
+
+/* wordt overal aangeroepen */
+void allqueue(unsigned short event, short val)
+{
+ ScrArea *sa;
+ View3D *v3d;
+ SpaceButs *buts;
+ SpaceFile *sfile;
+
+ sa= G.curscreen->areabase.first;
+ while(sa) {
+ if(event==REDRAWALL) {
+ scrarea_queue_winredraw(sa);
+ scrarea_queue_headredraw(sa);
+ }
+ else if(sa->win != val) {
+ switch(event) {
+
+ case REDRAWHEADERS:
+ scrarea_queue_headredraw(sa);
+ break;
+ case REDRAWVIEW3D:
+ if(sa->spacetype==SPACE_VIEW3D) {
+ scrarea_queue_winredraw(sa);
+ if(val) scrarea_queue_headredraw(sa);
+ }
+ break;
+ case REDRAWVIEW3D_Z:
+ if(sa->spacetype==SPACE_VIEW3D) {
+ v3d= sa->spacedata.first;
+ if(v3d->drawtype==OB_SOLID) {
+ scrarea_queue_winredraw(sa);
+ if(val) scrarea_queue_headredraw(sa);
+ }
+ }
+ break;
+ case REDRAWVIEWCAM:
+ if(sa->spacetype==SPACE_VIEW3D) {
+ v3d= sa->spacedata.first;
+ if(v3d->persp>1) scrarea_queue_winredraw(sa);
+ }
+ break;
+ case REDRAWINFO:
+ if(sa->spacetype==SPACE_INFO) {
+ scrarea_queue_headredraw(sa);
+ }
+ break;
+ case REDRAWIMAGE:
+ if(sa->spacetype==SPACE_IMAGE) {
+ scrarea_queue_winredraw(sa);
+ scrarea_queue_headredraw(sa);
+ }
+ break;
+ case REDRAWIPO:
+ if(sa->spacetype==SPACE_IPO) {
+ SpaceIpo *si;
+ scrarea_queue_winredraw(sa);
+ scrarea_queue_headredraw(sa);
+ if(val) {
+ si= sa->spacedata.first;
+ if (!G.sipo->pin)
+ si->blocktype= val;
+ }
+ }
+ else if(sa->spacetype==SPACE_OOPS) {
+ scrarea_queue_winredraw(sa);
+ }
+
+ break;
+
+ case REDRAWBUTSALL:
+ if(sa->spacetype==SPACE_BUTS) {
+ scrarea_queue_winredraw(sa);
+ scrarea_queue_headredraw(sa);
+ }
+ break;
+ case REDRAWBUTSHEAD:
+ if(sa->spacetype==SPACE_BUTS) {
+ scrarea_queue_headredraw(sa);
+ }
+ break;
+ case REDRAWBUTSVIEW:
+ if(sa->spacetype==SPACE_BUTS) {
+ buts= sa->spacedata.first;
+ if(buts->mainb==BUTS_VIEW) {
+ scrarea_queue_winredraw(sa);
+ scrarea_queue_headredraw(sa);
+ }
+ }
+ break;
+ case REDRAWBUTSLAMP:
+ if(sa->spacetype==SPACE_BUTS) {
+ buts= sa->spacedata.first;
+ if(buts->mainb==BUTS_LAMP) {
+ scrarea_queue_winredraw(sa);
+ scrarea_queue_headredraw(sa);
+ }
+ }
+ break;
+ case REDRAWBUTSMAT:
+ if(sa->spacetype==SPACE_BUTS) {
+ buts= sa->spacedata.first;
+ if(buts->mainb==BUTS_MAT) {
+ scrarea_queue_winredraw(sa);
+ scrarea_queue_headredraw(sa);
+ }
+ }
+ break;
+ case REDRAWBUTSTEX:
+ if(sa->spacetype==SPACE_BUTS) {
+ buts= sa->spacedata.first;
+ if(buts->mainb==BUTS_TEX) {
+ scrarea_queue_winredraw(sa);
+ scrarea_queue_headredraw(sa);
+ }
+ }
+ break;
+ case REDRAWBUTSANIM:
+ if(sa->spacetype==SPACE_BUTS) {
+ buts= sa->spacedata.first;
+ if(buts->mainb==BUTS_ANIM) {
+ scrarea_queue_winredraw(sa);
+ scrarea_queue_headredraw(sa);
+ }
+ }
+ break;
+ case REDRAWBUTSWORLD:
+ if(sa->spacetype==SPACE_BUTS) {
+ buts= sa->spacedata.first;
+ if(buts->mainb==BUTS_WORLD) {
+ scrarea_queue_winredraw(sa);
+ scrarea_queue_headredraw(sa);
+ }
+ }
+ break;
+ case REDRAWBUTSRENDER:
+ if(sa->spacetype==SPACE_BUTS) {
+ buts= sa->spacedata.first;
+ if(buts->mainb==BUTS_RENDER) {
+ scrarea_queue_winredraw(sa);
+ scrarea_queue_headredraw(sa);
+ }
+ }
+ break;
+ case REDRAWBUTSEDIT:
+ if(sa->spacetype==SPACE_BUTS) {
+ buts= sa->spacedata.first;
+ if(buts->mainb==BUTS_EDIT) {
+ scrarea_queue_winredraw(sa);
+ scrarea_queue_headredraw(sa);
+ }
+ }
+ break;
+ case REDRAWBUTSGAME:
+ if(sa->spacetype==SPACE_BUTS) {
+ buts= sa->spacedata.first;
+ if ELEM(buts->mainb, BUTS_GAME, BUTS_FPAINT) {
+ scrarea_queue_winredraw(sa);
+ scrarea_queue_headredraw(sa);
+ }
+ }
+ break;
+ case REDRAWBUTSRADIO:
+ if(sa->spacetype==SPACE_BUTS) {
+ buts= sa->spacedata.first;
+ if(buts->mainb==BUTS_RADIO) {
+ scrarea_queue_winredraw(sa);
+ scrarea_queue_headredraw(sa);
+ }
+ }
+ break;
+ case REDRAWBUTSSCRIPT:
+ if(sa->spacetype==SPACE_BUTS) {
+ buts= sa->spacedata.first;
+ if(buts->mainb==BUTS_SCRIPT) {
+ scrarea_queue_winredraw(sa);
+ scrarea_queue_headredraw(sa);
+ }
+ }
+ break;
+ case REDRAWBUTSSOUND:
+ if(sa->spacetype==SPACE_BUTS) {
+ buts= sa->spacedata.first;
+ if(buts->mainb==BUTS_SOUND) {
+ scrarea_queue_winredraw(sa);
+ scrarea_queue_headredraw(sa);
+ }
+ }
+ break;
+ case REDRAWBUTSCONSTRAINT:
+ if(sa->spacetype==SPACE_BUTS) {
+ buts= sa->spacedata.first;
+ if(buts->mainb==BUTS_CONSTRAINT) {
+ scrarea_queue_winredraw(sa);
+ scrarea_queue_headredraw(sa);
+ }
+ }
+ break;
+ case REDRAWDATASELECT:
+ if(sa->spacetype==SPACE_FILE) {
+ sfile= sa->spacedata.first;
+ if(sfile->type==FILE_MAIN) {
+ freefilelist(sfile);
+ scrarea_queue_winredraw(sa);
+ }
+ }
+ else if(sa->spacetype==SPACE_OOPS) {
+ scrarea_queue_winredraw(sa);
+ }
+ break;
+ case REDRAWSEQ:
+ if(sa->spacetype==SPACE_SEQ) {
+ addqueue(sa->win, CHANGED, 1);
+ scrarea_queue_winredraw(sa);
+ scrarea_queue_headredraw(sa);
+ }
+ break;
+ case REDRAWOOPS:
+ if(sa->spacetype==SPACE_OOPS) {
+ scrarea_queue_winredraw(sa);
+ }
+ break;
+ case REDRAWNLA:
+ if(sa->spacetype==SPACE_NLA) {
+ scrarea_queue_headredraw(sa);
+ scrarea_queue_winredraw(sa);
+ }
+ case REDRAWACTION:
+ if(sa->spacetype==SPACE_ACTION) {
+ scrarea_queue_headredraw(sa);
+ scrarea_queue_winredraw(sa);
+ }
+ break;
+ case REDRAWTEXT:
+ if(sa->spacetype==SPACE_TEXT) {
+ scrarea_queue_winredraw(sa);
+ }
+ break;
+ case REDRAWSOUND:
+ if(sa->spacetype==SPACE_SOUND) {
+ scrarea_queue_headredraw(sa);
+ scrarea_queue_winredraw(sa);
+ }
+ break;
+ }
+ }
+ sa= sa->next;
+ }
+}
+
+void allspace(unsigned short event, short val)
+{
+ bScreen *sc;
+
+ sc= G.main->screen.first;
+ while(sc) {
+ ScrArea *sa= sc->areabase.first;
+ while(sa) {
+ SpaceLink *sl= sa->spacedata.first;
+ while(sl) {
+ switch(event) {
+ case REMAKEALLIPO:
+ {
+ Ipo *ipo;
+ IpoCurve *icu;
+
+ /* Go to each ipo */
+ for (ipo=G.main->ipo.first; ipo; ipo=ipo->id.next){
+ for (icu = ipo->curve.first; icu; icu=icu->next){
+ sort_time_ipocurve(icu);
+ testhandles_ipocurve(icu);
+ }
+ }
+ }
+ break;
+ case REMAKEIPO:
+ if(sl->spacetype==SPACE_IPO) {
+ SpaceIpo *si= (SpaceIpo *)sl;
+ {
+ if(si->editipo) MEM_freeN(si->editipo);
+ si->editipo= 0;
+ free_ipokey(&si->ipokey);
+ }
+ }
+ break;
+
+ case OOPS_TEST:
+ if(sl->spacetype==SPACE_OOPS) {
+ SpaceOops *so= (SpaceOops *)sl;
+ so->flag |= SO_TESTBLOCKS;
+ }
+ break;
+ }
+
+ sl= sl->next;
+ }
+ sa= sa->next;
+ }
+ sc= sc->id.next;
+ }
+}
+
+
+void force_draw()
+{
+ /* alle area's die (ongeveer) zelfde laten zien als curarea */
+ ScrArea *tempsa, *sa;
+
+ scrarea_do_windraw(curarea);
+
+ tempsa= curarea;
+ sa= G.curscreen->areabase.first;
+ while(sa) {
+ if(sa!=tempsa && sa->spacetype==tempsa->spacetype) {
+ if(sa->spacetype==SPACE_VIEW3D) {
+ if( ((View3D *)sa->spacedata.first)->lay & ((View3D *)tempsa->spacedata.first)->lay) {
+ areawinset(sa->win);
+ scrarea_do_windraw(sa);
+ }
+ }
+ else if(sa->spacetype==SPACE_IPO) {
+ areawinset(sa->win);
+ scrarea_do_windraw(sa);
+ }
+ else if(sa->spacetype==SPACE_SEQ) {
+ areawinset(sa->win);
+ scrarea_do_windraw(sa);
+ }
+ else if(sa->spacetype==SPACE_ACTION) {
+ areawinset(sa->win);
+ scrarea_do_windraw(sa);
+ }
+ }
+ sa= sa->next;
+ }
+ if(curarea!=tempsa) areawinset(tempsa->win);
+
+ screen_swapbuffers();
+
+}
+
+void force_draw_plus(int type)
+{
+ /* alle area's die (ongeveer) zelfde laten zien als curarea EN areas van 'type' */
+ ScrArea *tempsa, *sa;
+
+ scrarea_do_windraw(curarea);
+
+ tempsa= curarea;
+ sa= G.curscreen->areabase.first;
+ while(sa) {
+ if(sa!=tempsa && (sa->spacetype==tempsa->spacetype || sa->spacetype==type)) {
+ if(ELEM5(sa->spacetype, SPACE_VIEW3D, SPACE_IPO, SPACE_SEQ, SPACE_BUTS, SPACE_ACTION)) {
+ areawinset(sa->win);
+ scrarea_do_windraw(sa);
+ }
+ }
+ sa= sa->next;
+ }
+ if(curarea!=tempsa) areawinset(tempsa->win);
+
+ screen_swapbuffers();
+}
+
+void force_draw_all(void)
+{
+ /* alle area's die (ongeveer) zelfde laten zien als curarea EN areas van 'type' */
+ ScrArea *tempsa, *sa;
+
+ drawscreen();
+
+ tempsa= curarea;
+ sa= G.curscreen->areabase.first;
+ while(sa) {
+ if(sa->headwin) {
+ scrarea_do_headdraw(sa);
+ scrarea_do_headchange(sa);
+ }
+ if(sa->win) {
+ scrarea_do_windraw(sa);
+ }
+ sa= sa->next;
+ }
+ if(curarea!=tempsa) areawinset(tempsa->win);
+
+ screen_swapbuffers();
+}
+
+/***/
+
+SpaceType *spaceaction_get_type(void)
+{
+ static SpaceType *st= NULL;
+
+ if (!st) {
+ st= spacetype_new("Action");
+ spacetype_set_winfuncs(st, drawactionspace, changeview2d, winqreadactionspace);
+ }
+
+ return st;
+}
+SpaceType *spacebuts_get_type(void)
+{
+ static SpaceType *st= NULL;
+
+ if (!st) {
+ st= spacetype_new("Buts");
+ spacetype_set_winfuncs(st, drawbutspace, changebutspace, winqreadbutspace);
+ }
+
+ return st;
+}
+SpaceType *spacefile_get_type(void)
+{
+ static SpaceType *st= NULL;
+
+ if (!st) {
+ st= spacetype_new("File");
+ spacetype_set_winfuncs(st, drawfilespace, NULL, winqreadfilespace);
+ }
+
+ return st;
+}
+SpaceType *spaceimage_get_type(void)
+{
+ static SpaceType *st= NULL;
+
+ if (!st) {
+ st= spacetype_new("Image");
+ spacetype_set_winfuncs(st, drawimagespace, NULL, winqreadimagespace);
+ }
+
+ return st;
+}
+SpaceType *spaceimasel_get_type(void)
+{
+ static SpaceType *st= NULL;
+
+ if (!st) {
+ st= spacetype_new("Imasel");
+ spacetype_set_winfuncs(st, drawimasel, NULL, winqreadimasel);
+ }
+
+ return st;
+}
+SpaceType *spaceinfo_get_type(void)
+{
+ static SpaceType *st= NULL;
+
+ if (!st) {
+ st= spacetype_new("Info");
+ spacetype_set_winfuncs(st, drawinfospace, NULL, winqreadinfospace);
+ }
+
+ return st;
+}
+SpaceType *spaceipo_get_type(void)
+{
+ static SpaceType *st= NULL;
+
+ if (!st) {
+ st= spacetype_new("Ipo");
+ spacetype_set_winfuncs(st, drawipo, changeview2d, winqreadipo);
+ }
+
+ return st;
+}
+SpaceType *spacenla_get_type(void)
+{
+ static SpaceType *st= NULL;
+
+ if (!st) {
+ st= spacetype_new("Nla");
+ spacetype_set_winfuncs(st, drawnlaspace, changeview2d, winqreadnlaspace);
+ }
+
+ return st;
+}
+SpaceType *spaceoops_get_type(void)
+{
+ static SpaceType *st= NULL;
+
+ if (!st) {
+ st= spacetype_new("Oops");
+ spacetype_set_winfuncs(st, drawoopsspace, changeview2d, winqreadoopsspace);
+ }
+
+ return st;
+}
+SpaceType *spaceseq_get_type(void)
+{
+ static SpaceType *st= NULL;
+
+ if (!st) {
+ st= spacetype_new("Sequence");
+ spacetype_set_winfuncs(st, drawseqspace, changeview2d, winqreadsequence);
+ }
+
+ return st;
+}
+SpaceType *spacesound_get_type(void)
+{
+ static SpaceType *st= NULL;
+
+ if (!st) {
+ st= spacetype_new("Sound");
+ spacetype_set_winfuncs(st, drawsoundspace, NULL, winqreadsoundspace);
+ }
+
+ return st;
+}
+SpaceType *spacetext_get_type(void)
+{
+ static SpaceType *st= NULL;
+
+ if (!st) {
+ st= spacetype_new("Text");
+ spacetype_set_winfuncs(st, drawtextspace, NULL, winqreadtextspace);
+ }
+
+ return st;
+}
+SpaceType *spaceview3d_get_type(void)
+{
+ static SpaceType *st= NULL;
+
+ if (!st) {
+ st= spacetype_new("View3D");
+ spacetype_set_winfuncs(st, drawview3d, changeview3d, winqread3d);
+ }
+
+ return st;
+}
diff --git a/source/blender/src/spacetypes.c b/source/blender/src/spacetypes.c
new file mode 100644
index 00000000000..4a756e5924f
--- /dev/null
+++ b/source/blender/src/spacetypes.c
@@ -0,0 +1,137 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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>
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+#include "BLI_blenlib.h"
+
+#include "DNA_screen_types.h"
+
+#include "BIF_gl.h"
+#include "BIF_mywindow.h"
+#include "BIF_screen.h"
+#include "BIF_spacetypes.h"
+
+/***/
+
+struct _SpaceType {
+ char name[32];
+
+ SpaceDrawFP windraw;
+ SpaceChangeFP winchange;
+ SpaceHandleFP winhandle;
+};
+
+
+SpaceType *spacetype_new(char *name)
+{
+ SpaceType *st= calloc(1, sizeof(*st));
+ BLI_strncpy(st->name, name, sizeof(st->name));
+
+ return st;
+}
+
+void spacetype_set_winfuncs(SpaceType *st, SpaceDrawFP draw, SpaceChangeFP change, SpaceHandleFP handle)
+{
+ st->windraw= draw;
+ st->winchange= change;
+ st->winhandle= handle;
+}
+
+ /***/
+
+SpaceType *spacetype_from_code(int spacecode)
+{
+ switch (spacecode) {
+ case SPACE_ACTION: return spaceaction_get_type();
+ case SPACE_BUTS: return spacebuts_get_type();
+ case SPACE_FILE: return spacefile_get_type();
+ case SPACE_IMAGE: return spaceimage_get_type();
+ case SPACE_IMASEL: return spaceimasel_get_type();
+ case SPACE_INFO: return spaceinfo_get_type();
+ case SPACE_IPO: return spaceipo_get_type();
+ case SPACE_NLA: return spacenla_get_type();
+ case SPACE_OOPS: return spaceoops_get_type();
+ case SPACE_SEQ: return spaceseq_get_type();
+ case SPACE_SOUND: return spacesound_get_type();
+ case SPACE_TEXT: return spacetext_get_type();
+ case SPACE_VIEW3D: return spaceview3d_get_type();
+ default:
+ return NULL;
+ }
+}
+
+void scrarea_do_windraw(ScrArea *area)
+{
+ SpaceType *st= spacetype_from_code(area->spacetype);
+
+ areawinset(area->win);
+
+ if(area->win && st->windraw) {
+ st->windraw();
+ }
+ else {
+ glClearColor(0.4375, 0.4375, 0.4375, 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+ }
+
+ area->win_swap= WIN_BACK_OK;
+}
+void scrarea_do_winchange(ScrArea *area)
+{
+ SpaceType *st= spacetype_from_code(area->spacetype);
+
+ areawinset(area->win);
+
+ if (st->winchange) {
+ st->winchange();
+ } else {
+ if (!BLI_rcti_is_empty(&area->winrct)) {
+ bwin_ortho2(area->win, -0.5, area->winrct.xmax-area->winrct.xmin-0.5, -0.5, area->winrct.ymax-area->winrct.ymin-0.5);
+ glLoadIdentity();
+ }
+ }
+}
+void scrarea_do_winhandle(ScrArea *area, unsigned short event, short val, char ascii)
+{
+ SpaceType *st= spacetype_from_code(area->spacetype);
+
+ areawinset(area->win);
+
+ if (st->winhandle) {
+ st->winhandle(event, val, ascii);
+ }
+}
diff --git a/source/blender/src/swapbuffers.c b/source/blender/src/swapbuffers.c
new file mode 100644
index 00000000000..5d90392b145
--- /dev/null
+++ b/source/blender/src/swapbuffers.c
@@ -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 *****
+ */
+
+#include <stdlib.h>
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+#include "DNA_space_types.h"
+#include "DNA_screen_types.h"
+
+#include "BKE_global.h"
+
+#include "BIF_gl.h"
+#include "BIF_interface.h"
+#include "BIF_mywindow.h"
+#include "BIF_screen.h"
+#include "BIF_space.h"
+
+#include "winlay.h"
+
+#if 0
+static void copy_back_to_front(void)
+{
+ int actually_swap= 0;
+ int winx, winy;
+ char *data;
+
+ winlay_get_winsize(&winx, &winy);
+
+ if (actually_swap) {
+ data= malloc(4*winx*winy);
+ glReadPixels(0, 0, winx, winy, GL_RGBA, GL_UNSIGNED_BYTE, data);
+ }
+
+ mywinset(1);
+ glRasterPos2f(-0.5,-0.5);
+ glReadBuffer(GL_BACK);
+ glDrawBuffer(GL_FRONT);
+ glCopyPixels(0, 0, winx, winy, GL_COLOR);
+ glDrawBuffer(GL_BACK);
+ glFinish();
+
+ if (actually_swap) {
+ glRasterPos2f(-0.5,-0.5);
+ glDrawPixels(winx, winy, GL_RGBA, GL_UNSIGNED_BYTE, data);
+ glFinish();
+ free(data);
+ }
+}
+#endif
+
+static void screen_swapbuffers_REDRAW(bScreen *sc)
+{
+ ScrArea *sa;
+ int doswap= 0, swap;
+
+ /* dit is een nieuwe implementatie: uitsluitend met redraws en normale swapbuffer */
+
+ /* allemaal front ok? */
+ sa= sc->areabase.first;
+ while(sa) {
+ if(sa->win && (sa->win_swap & WIN_FRONT_OK)==0) break;
+ if(!sa->headertype) sa->head_swap= WIN_EQUAL;
+ if((sa->head_swap & WIN_FRONT_OK)==0) break;
+ sa= sa->next;
+ }
+ if(sa==0) return;
+
+ sa= sc->areabase.first;
+ while(sa) {
+
+ swap= sa->win_swap;
+ if( (swap & WIN_BACK_OK) == 0) {
+ scrarea_do_windraw(sa);
+ doswap= 1;
+ sa->win_swap= swap | WIN_BACK_OK;
+ }
+ else if( sa->win_swap==WIN_BACK_OK) doswap= 1;
+
+ swap= sa->head_swap;
+ if( (swap & WIN_BACK_OK) == 0) {
+ if (sa->headertype) scrarea_do_headdraw(sa);
+ doswap= 1;
+ sa->head_swap = swap | WIN_BACK_OK;
+ }
+ else if( sa->head_swap==WIN_BACK_OK) doswap= 1;
+
+ sa= sa->next;
+ }
+
+ /* de hele backbuffer moet nu OK zijn */
+ if(doswap) {
+ myswapbuffers();
+ }
+}
+
+#include "BMF_Api.h"
+#include <stdio.h>
+
+static void draw_debug_win(int win)
+{
+ static int drawcounter= 0;
+ char buf[64];
+ int x, y;
+ int w, h;
+
+ bwin_getsuborigin(win, &x, &y);
+ bwin_getsize(win, &w, &h);
+
+ mywinset(win);
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(0, w, 0, h, -1, 1);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ glColor3f(0.8, 0.8, 0.8);
+ glRecti(0, 0, w, h);
+
+ glColor3f(0.6, 0.6, 0.6);
+ glRecti(2, 2, w-4, h-4);
+
+ glColor3ub(0, 0, 0);
+ glRasterPos2i(5, 5);
+
+ sprintf(buf, "win: %d - (%d, %d, %d, %d) %d\n", win, x, y, w, h, drawcounter++);
+ BMF_DrawString(G.font, buf);
+}
+
+static void screen_swapbuffers_DEBUG(bScreen *sc)
+{
+ ScrArea *sa;
+
+ for (sa= sc->areabase.first; sa; sa= sa->next) {
+ draw_debug_win(sa->win);
+ if (sa->headwin) draw_debug_win(sa->headwin);
+ }
+
+ myswapbuffers();
+}
+
+static void screen_swapbuffers_DEBUG_SWAP(bScreen *sc)
+{
+ ScrArea *sa;
+ int doswap= 0, swap;
+
+ /* dit is een nieuwe implementatie: uitsluitend met redraws en normale swapbuffer */
+
+ /* allemaal front ok? */
+ sa= sc->areabase.first;
+ while(sa) {
+ if(sa->win && (sa->win_swap & WIN_FRONT_OK)==0) break;
+ if(!sa->headertype) sa->head_swap= WIN_EQUAL;
+ if((sa->head_swap & WIN_FRONT_OK)==0) break;
+ sa= sa->next;
+ }
+ if(sa==0) return;
+
+ sa= sc->areabase.first;
+ while(sa) {
+
+ swap= sa->win_swap;
+ if( (swap & WIN_BACK_OK) == 0) {
+ scrarea_do_windraw(sa);
+ draw_debug_win(sa->win);
+
+ doswap= 1;
+ sa->win_swap= swap | WIN_BACK_OK;
+ }
+ else if( sa->win_swap==WIN_BACK_OK) doswap= 1;
+
+ swap= sa->head_swap;
+ if( (swap & WIN_BACK_OK) == 0) {
+ if (sa->headertype) {
+ scrarea_do_headdraw(sa);
+ draw_debug_win(sa->headwin);
+ }
+ doswap= 1;
+ sa->head_swap = swap | WIN_BACK_OK;
+ }
+ else if( sa->head_swap==WIN_BACK_OK) doswap= 1;
+
+ sa= sa->next;
+ }
+
+ /* de hele backbuffer moet nu OK zijn */
+ if(doswap) {
+ myswapbuffers();
+ }
+}
+
+static void screen_swapbuffers_SIMPLE(bScreen *sc)
+{
+ ScrArea *sa;
+
+ mywinset(1);
+ glClearColor(0.8, 0.6, 0.7, 1.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ for (sa= sc->areabase.first; sa; sa= sa->next) {
+ scrarea_do_windraw(sa);
+ if (sa->headertype) scrarea_do_headdraw(sa);
+ }
+
+ myswapbuffers();
+}
+
+static int drawmode_default= 'r';
+int debug_swapbuffers_override= 0;
+
+void set_debug_swapbuffers_ovveride(bScreen *sc, int mode)
+{
+ ScrArea *sa;
+ for (sa= sc->areabase.first; sa; sa= sa->next) {
+ sa->win_swap= 0;
+ sa->head_swap= 0;
+ }
+ debug_swapbuffers_override= mode;
+}
+
+void screen_swapbuffers(void)
+{
+ ScrArea *tempsa;
+
+ bScreen *sc= G.curscreen;
+ int drawmode;
+
+ if (debug_swapbuffers_override) {
+ drawmode= debug_swapbuffers_override;
+ } else {
+ drawmode= drawmode_default;
+ }
+
+ tempsa= curarea;
+ areawinset(1);
+
+ if (drawmode=='s') {
+ screen_swapbuffers_SIMPLE(sc);
+ } else if (drawmode=='d') {
+ screen_swapbuffers_DEBUG(sc);
+ } else if (drawmode=='f') {
+ screen_swapbuffers_DEBUG_SWAP(sc);
+ } else {
+ screen_swapbuffers_REDRAW(sc);
+ }
+
+ areawinset(tempsa->win);
+} \ No newline at end of file
diff --git a/source/blender/src/toets.c b/source/blender/src/toets.c
new file mode 100644
index 00000000000..cde64754df8
--- /dev/null
+++ b/source/blender/src/toets.c
@@ -0,0 +1,874 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * Algemene toetsen, bijzondere in de space.c
+ */
+
+#include <string.h>
+#include <math.h>
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "PIL_time.h"
+
+#include "nla.h" /* Only for the #ifdef flag - To be removed later */
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+
+#include "DNA_object_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_view3d_types.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_global.h"
+#include "BKE_anim.h"
+#include "BKE_scene.h"
+#include "BKE_ipo.h"
+#include "BKE_action.h"
+#include "BKE_ika.h"
+#include "BKE_key.h"
+
+#include "BIF_interface.h"
+#include "BIF_screen.h"
+#include "BIF_space.h"
+#include "BIF_buttons.h"
+#include "BIF_renderwin.h"
+#include "BIF_toolbox.h"
+#include "BIF_toets.h"
+#include "BIF_editseq.h"
+#include "BIF_editsound.h"
+#include "BIF_poseobject.h"
+#include "BIF_usiblender.h"
+
+#include "BDR_vpaint.h"
+#include "BDR_editobject.h"
+#include "BDR_editface.h"
+
+#include "BSE_filesel.h" /* For activate_fileselect */
+#include "BSE_drawview.h" /* For play_anim */
+#include "BSE_view.h"
+#include "BSE_edit.h"
+#include "BSE_editipo.h"
+#include "BSE_headerbuttons.h"
+
+#include "blendef.h"
+#include "interface.h"
+#include "render.h"
+#include "blendertimer.h" /* timer functions */
+
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+
+#include "mydevice.h"
+#include "license_key.h"
+
+#include "BIF_poseobject.h"
+
+/* only used in toets.c */
+/* this function doesn't really belong here */
+/* ripped from render module */
+void schrijfplaatje(char *name);
+
+
+void write_imag(char *name)
+{
+ /* vanuit filesel */
+ char str[256];
+
+ strcpy(str, name);
+ BLI_convertstringcode(str, G.sce, G.scene->r.cfra);
+
+ if(saveover(str)) {
+ if(BLI_testextensie(str,".blend")) {
+ error("Wrong filename");
+ return;
+ }
+ waitcursor(1); /* from screen.c */
+ schrijfplaatje(str);
+ strcpy(G.ima, name);
+ waitcursor(0);
+ }
+}
+
+/* ripped from render module */
+/* void schrijfplaatje(char *name); */
+
+
+/* From matrix.h: it's really a [4][4]! */
+/* originally in initrender... maybe add fileControl thingy? */
+void schrijfplaatje(char *name)
+{
+ struct ImBuf *ibuf=0;
+ unsigned int *temprect=0;
+ char str[FILE_MAXDIR+FILE_MAXFILE];
+
+ /* Staat RGBA aan? Zo ja: gebruik alphakanaal voor kleur 0 */
+ IMB_alpha_to_col0(FALSE);
+
+ if(R.r.planes == 32) {
+ /* alles met minder dan 50 % alpha -> col 0 */
+ if(R.r.alphamode == R_ALPHAKEY) IMB_alpha_to_col0(2);
+ /* uitsluitend met 0 alpha -> col 0 */
+ else IMB_alpha_to_col0(1);
+ }
+
+ /* Seems to me this is also superfluous.... */
+ if (R.r.imtype==R_FTYPE) {
+ strcpy(str, R.r.ftype);
+ BLI_convertstringcode(str, G.sce, G.scene->r.cfra);
+
+ ibuf = IMB_loadiffname(str, IB_test);
+ if(ibuf) {
+ ibuf->x = R.rectx;
+ ibuf->y = R.recty;
+ }
+ else {
+ error("Can't find filetype");
+ G.afbreek= 1;
+ return;
+ }
+ /* setdither(2); */
+ }
+
+ if(ibuf == 0) {
+ ibuf= IMB_allocImBuf(R.rectx, R.recty, R.r.planes, 0, 0);
+ }
+
+ if(ibuf) {
+ ibuf->rect= (unsigned int *) R.rectot;
+
+ if(R.r.planes == 8) IMB_cspace(ibuf, rgb_to_bw);
+
+ if(R.r.imtype== R_IRIS) {
+ ibuf->ftype= IMAGIC;
+ }
+ else if(R.r.imtype==R_IRIZ) {
+ ibuf->ftype= IMAGIC;
+ if (ibuf->zbuf == 0) {
+ if (R.rectz) {
+ ibuf->zbuf = (int *)R.rectz;
+ }
+ else printf("no zbuf\n");
+ }
+ }
+ else if((R.r.imtype==R_PNG) && (LICENSE_KEY_VALID)) {
+ ibuf->ftype= PNG;
+ }
+ else if((R.r.imtype==R_TARGA) || (R.r.imtype==R_PNG)) {
+ ibuf->ftype= TGA;
+ }
+ else if(R.r.imtype==R_RAWTGA) {
+ ibuf->ftype= RAWTGA;
+ }
+ else if(R.r.imtype==R_HAMX) {
+ /* kopie maken */
+ temprect= MEM_dupallocN(R.rectot);
+ ibuf->ftype= AN_hamx;
+ }
+ else if(ELEM5(R.r.imtype, R_MOVIE, R_AVICODEC, R_AVIRAW, R_AVIJPEG, R_JPEG90)) {
+ if(R.r.quality < 10) R.r.quality= 90;
+
+ if(R.r.mode & R_FIELDS) ibuf->ftype= JPG_VID|R.r.quality;
+ else ibuf->ftype= JPG|R.r.quality;
+ }
+
+ RE_make_existing_file(name);
+
+ if(IMB_saveiff(ibuf, name, IB_rect | IB_zbuf)==0) {
+ perror(name);
+ G.afbreek= 1;
+ }
+
+ IMB_freeImBuf(ibuf);
+
+ if (R.r.imtype==R_HAMX) {
+ MEM_freeN(R.rectot);
+ R.rectot= temprect;
+ }
+ }
+ else {
+ G.afbreek= 1;
+ }
+}
+
+
+
+/* ------------------------------------------------------------------------- */
+
+static int is_an_active_object(void *ob) {
+ Base *base;
+
+ for (base= FIRSTBASE; base; base= base->next)
+ if (base->object == ob)
+ return 1;
+
+ return 0;
+}
+
+void persptoetsen(unsigned short event)
+{
+ static Object *oldcamera=0;
+ float phi, si, q1[4], vec[3];
+ static int perspo=1;
+
+ if(event==PADENTER) {
+ if (G.qual == LR_SHIFTKEY) {
+ view3d_set_1_to_1_viewborder(G.vd);
+ } else {
+ if (G.vd->persp==2) {
+ G.vd->camzoom= 0.0;
+ } else {
+ G.vd->dist= 10.0;
+ }
+ }
+ }
+ else if((G.qual & (LR_SHIFTKEY | LR_CTRLKEY)) && (event != PAD0)) {
+ if(event==PAD0) {
+ /* G.vd->persp= 3; */
+ }
+ else if(event==PAD7) {
+ G.vd->viewquat[0]= 0.0;
+ G.vd->viewquat[1]= -1.0;
+ G.vd->viewquat[2]= 0.0;
+ G.vd->viewquat[3]= 0.0;
+ G.vd->view= 7;
+ }
+ else if(event==PAD1) {
+ G.vd->viewquat[0]= 0.0;
+ G.vd->viewquat[1]= 0.0;
+ G.vd->viewquat[2]= (float)-cos(M_PI/4.0);
+ G.vd->viewquat[3]= (float)-cos(M_PI/4.0);
+ G.vd->view=1;
+ }
+ else if(event==PAD3) {
+ G.vd->viewquat[0]= 0.5;
+ G.vd->viewquat[1]= -0.5;
+ G.vd->viewquat[2]= 0.5;
+ G.vd->viewquat[3]= 0.5;
+ G.vd->view=3;
+ }
+ else if(event==PADMINUS) {
+ /* deze min en max staan ook in viewmove() */
+ if(G.vd->persp==2) {
+ G.vd->camzoom-= 10;
+ if(G.vd->camzoom<-30) G.vd->camzoom= -30;
+ }
+ else if(G.vd->dist<10.0*G.vd->far) G.vd->dist*=1.2;
+ }
+ else if(event==PADPLUSKEY) {
+ if(G.vd->persp==2) {
+ G.vd->camzoom+= 10;
+ if(G.vd->camzoom>300) G.vd->camzoom= 300;
+ }
+ else if(G.vd->dist> 0.001*G.vd->grid) G.vd->dist*=.83333;
+ }
+ else {
+
+ initgrabz(0.0, 0.0, 0.0);
+
+ if(event==PAD6) window_to_3d(vec, -32, 0);
+ else if(event==PAD4) window_to_3d(vec, 32, 0);
+ else if(event==PAD8) window_to_3d(vec, 0, -25);
+ else if(event==PAD2) window_to_3d(vec, 0, 25);
+ G.vd->ofs[0]+= vec[0];
+ G.vd->ofs[1]+= vec[1];
+ G.vd->ofs[2]+= vec[2];
+ }
+ }
+ else {
+
+ if(event==PAD7) {
+ G.vd->viewquat[0]= 1.0;
+ G.vd->viewquat[1]= 0.0;
+ G.vd->viewquat[2]= 0.0;
+ G.vd->viewquat[3]= 0.0;
+ G.vd->view=7;
+ if(G.vd->persp>=2) G.vd->persp= perspo;
+ }
+ else if(event==PAD1) {
+ G.vd->viewquat[0]= (float)cos(M_PI/4.0);
+ G.vd->viewquat[1]= (float)-sin(M_PI/4.0);
+ G.vd->viewquat[2]= 0.0;
+ G.vd->viewquat[3]= 0.0;
+ G.vd->view=1;
+ if(G.vd->persp>=2) G.vd->persp= perspo;
+ }
+ else if(event==PAD3) {
+ G.vd->viewquat[0]= 0.5;
+ G.vd->viewquat[1]= -0.5;
+ G.vd->viewquat[2]= -0.5;
+ G.vd->viewquat[3]= -0.5;
+ G.vd->view=3;
+ if(G.vd->persp>=2) G.vd->persp= perspo;
+ }
+ else if(event==PADMINUS) {
+ /* deze min en max staan ook in viewmove() */
+ if(G.vd->persp==2) {
+ G.vd->camzoom= MAX2(-30, G.vd->camzoom-5);
+ }
+ else if(G.vd->dist<10.0*G.vd->far) G.vd->dist*=1.2;
+ }
+ else if(event==PADPLUSKEY) {
+ if(G.vd->persp==2) {
+ G.vd->camzoom= MIN2(300, G.vd->camzoom+5);
+ }
+ else if(G.vd->dist> 0.001*G.vd->grid) G.vd->dist*=.83333;
+ }
+ else if(event==PAD5) {
+ if(G.vd->persp==1) G.vd->persp=0;
+ else G.vd->persp=1;
+ }
+ else if(event==PAD0) {
+ if(G.qual & LR_ALTKEY) {
+ if(oldcamera && is_an_active_object(oldcamera)) {
+ G.vd->camera= oldcamera;
+ }
+
+ handle_view3d_lock();
+ }
+ else if(BASACT) {
+ if(G.qual & LR_CTRLKEY) {
+ if(G.vd->camera != OBACT) {
+ if(G.vd->camera && G.vd->camera->type==OB_CAMERA)
+ oldcamera= G.vd->camera;
+
+ G.vd->camera= OBACT;
+ handle_view3d_lock();
+ }
+ }
+ else if(G.vd->camera==0 && OBACT->type==OB_CAMERA) {
+ G.vd->camera= OBACT;
+ handle_view3d_lock();
+ }
+ }
+ if(G.vd->camera==0) {
+ G.vd->camera= scene_find_camera(G.scene);
+ handle_view3d_lock();
+ }
+
+ if(G.vd->camera) {
+ G.vd->persp= 2;
+ G.vd->view= 0;
+ }
+
+ }
+ else if(event==PAD9) {
+ countall();
+ do_all_ipos();
+ do_all_keys();
+ do_all_actions();
+ do_all_ikas();
+
+ reset_slowparents(); /* editobject.c */
+ }
+ else if(G.vd->persp<2) {
+ if(event==PAD4 || event==PAD6) {
+ /* z-as */
+ phi= (float)(M_PI/24.0);
+ if(event==PAD6) phi= -phi;
+ si= (float)sin(phi);
+ q1[0]= (float)cos(phi);
+ q1[1]= q1[2]= 0.0;
+ q1[3]= si;
+ QuatMul(G.vd->viewquat, G.vd->viewquat, q1);
+ G.vd->view= 0;
+ }
+ if(event==PAD2 || event==PAD8) {
+
+ /* liggende as */
+ VECCOPY(q1+1, G.vd->viewinv[0]);
+
+ Normalise(q1+1);
+ phi= (float)(M_PI/24.0);
+ if(event==PAD2) phi= -phi;
+ si= (float)sin(phi);
+ q1[0]= (float)cos(phi);
+ q1[1]*= si;
+ q1[2]*= si;
+ q1[3]*= si;
+ QuatMul(G.vd->viewquat, G.vd->viewquat, q1);
+ G.vd->view= 0;
+ }
+ }
+
+ if(G.vd->persp<2) perspo= G.vd->persp;
+ }
+ scrarea_queue_redraw(curarea);
+}
+
+int untitled(char * name)
+{
+ if (G.save_over == 0 ) {
+ char * c= BLI_last_slash(name);
+
+ if (c)
+ strcpy(&c[1], "untitled.blend");
+ else
+ strcpy(name, "untitled.blend");
+
+ return(TRUE);
+ }
+
+ return(FALSE);
+}
+
+int save_image_filesel_str(char *str)
+{
+ switch(G.scene->r.imtype) {
+ case R_PNG:
+ if (LICENSE_KEY_VALID) {
+ strcpy(str, "SAVE PNG"); return 1;
+ }
+ case R_TARGA:
+ strcpy(str, "SAVE TARGA"); return 1;
+ case R_RAWTGA:
+ strcpy(str, "SAVE RAW TARGA"); return 1;
+ case R_IRIS:
+ strcpy(str, "SAVE IRIS"); return 1;
+ case R_IRIZ:
+ strcpy(str, "SAVE IRIS"); return 1;
+ case R_HAMX:
+ strcpy(str, "SAVE HAMX"); return 1;
+ case R_FTYPE:
+ strcpy(str, "SAVE FTYPE"); return 1;
+ case R_JPEG90:
+ strcpy(str, "SAVE JPEG"); return 1;
+ default:
+ strcpy(str, "SAVE IMAGE"); return 0;
+ }
+}
+
+void BIF_save_rendered_image(void)
+{
+ if(!R.rectot) {
+ error("No image rendered");
+ } else {
+ char dir[FILE_MAXDIR * 2], str[FILE_MAXFILE * 2];
+
+ if(G.ima[0]==0) {
+ strcpy(dir, G.sce);
+ BLI_splitdirstring(dir, str);
+ strcpy(G.ima, dir);
+ }
+
+ R.r.imtype= G.scene->r.imtype;
+ R.r.quality= G.scene->r.quality;
+ R.r.planes= G.scene->r.planes;
+
+ if (!save_image_filesel_str(str)) {
+ error("Select an image type in DisplayButtons(F10)");
+ } else {
+ activate_fileselect(FILE_SPECIAL, str, G.ima, write_imag);
+ }
+ }
+}
+
+int blenderqread(unsigned short event, short val)
+{
+ /* hier alle algemene toetsafhandelingen (niet screen/window/space) */
+ /* return 0: niet aan andere queue's doorgeven */
+/* extern char videosc_dir[]; */
+ extern int textediting;
+ ScrArea *sa;
+ Object *ob;
+ int textspace=0;
+ /* Changed str and dir size to 160, to make sure there is enough
+ * space for filenames. */
+ char dir[FILE_MAXDIR * 2], str[FILE_MAXFILE * 2];
+
+ if(val==0) return 1;
+ if(event==MOUSEY || event==MOUSEX) return 1;
+ if (G.flags & G_FLAGS_AUTOPLAY) return 1;
+
+ if (curarea && curarea->spacetype==SPACE_TEXT) textspace= 1;
+
+ switch(event) {
+
+ case F1KEY:
+ if(G.qual==0) {
+ /* this exception because of the '?' button */
+ if(curarea->spacetype==SPACE_INFO) {
+ sa= closest_bigger_area();
+ areawinset(sa->win);
+ }
+
+ activate_fileselect(FILE_BLENDER, "LOAD FILE", G.sce, BIF_read_file);
+ return 0;
+ }
+ else if(G.qual & LR_SHIFTKEY) {
+ activate_fileselect(FILE_LOADLIB, "LOAD LIBRARY", G.lib, 0);
+ return 0;
+ }
+ break;
+ case F2KEY:
+ if(G.qual==0) {
+ strcpy(dir, G.sce);
+ untitled(dir);
+ activate_fileselect(FILE_BLENDER, "SAVE FILE", dir, BIF_write_file);
+ return 0;
+ }
+ else if(G.qual & LR_CTRLKEY) {
+ write_vrml_fs();
+ return 0;
+ }
+ else if(G.qual & LR_SHIFTKEY) {
+ write_dxf_fs();
+ return 0;
+ }
+ break;
+ case F3KEY:
+ if(G.qual==0) {
+ BIF_save_rendered_image();
+ return 0;
+ }
+ else if(G.qual & LR_CTRLKEY) {
+ BIF_screendump();
+ }
+ break;
+ case F4KEY:
+ if(G.qual & LR_SHIFTKEY) {
+
+ memset(str, 0, 16);
+ ob= OBACT;
+ if(ob) strcpy(str, ob->id.name);
+
+ activate_fileselect(FILE_MAIN, "DATA SELECT", str, 0);
+ return 0;
+ }
+ else extern_set_butspace(event);
+
+ break;
+ case F5KEY:
+ if(G.qual & LR_SHIFTKEY) {
+ newspace(curarea, SPACE_VIEW3D);
+ return 0;
+ }
+ else extern_set_butspace(event);
+ break;
+ case F6KEY:
+ if(G.qual & LR_SHIFTKEY) {
+ newspace(curarea, SPACE_IPO);
+ return 0;
+ }
+ else extern_set_butspace(event);
+ break;
+ case F7KEY:
+ if(G.qual & LR_SHIFTKEY) {
+ newspace(curarea, SPACE_BUTS);
+ return 0;
+ }
+ else extern_set_butspace(event);
+ break;
+ case F8KEY:
+ if(G.qual & LR_SHIFTKEY) {
+ newspace(curarea, SPACE_SEQ);
+ return 0;
+ }
+ else extern_set_butspace(event);
+ break;
+ case F9KEY:
+ if(G.qual & LR_SHIFTKEY) {
+ newspace(curarea, SPACE_OOPS);
+ return 0;
+ }
+ else extern_set_butspace(event);
+ break;
+ case F10KEY:
+ if(G.qual & LR_SHIFTKEY) {
+ newspace(curarea, SPACE_IMAGE);
+ return 0;
+ }
+ else extern_set_butspace(event);
+ break;
+ case F11KEY:
+ if(G.qual & LR_SHIFTKEY) {
+ newspace(curarea, SPACE_TEXT);
+ return 0;
+ }
+ else BIF_toggle_render_display();
+ return 0;
+ break;
+ case F12KEY:
+ if(G.qual & LR_SHIFTKEY) {
+ if (G.qual & LR_CTRLKEY){
+ newspace(curarea, SPACE_NLA);
+ return 0;
+ }
+ newspace(curarea, SPACE_ACTION);
+ return 0;
+ }
+ else BIF_do_render(0);
+ return 0;
+ break;
+
+ case LEFTARROWKEY:
+ case DOWNARROWKEY:
+ if(textediting==0 && textspace==0) {
+ if(event==DOWNARROWKEY) CFRA-= 10;
+ else CFRA--;
+
+ if(G.qual & LR_SHIFTKEY) CFRA= SFRA;
+ if(CFRA<1) CFRA=1;
+
+ update_for_newframe();
+ return 0;
+ }
+ break;
+
+ case RIGHTARROWKEY:
+ case UPARROWKEY:
+ if(textediting==0 && textspace==0) {
+ if(event==UPARROWKEY) CFRA+= 10;
+ else CFRA++;
+ if(G.qual & LR_SHIFTKEY) CFRA= EFRA;
+
+ update_for_newframe();
+ }
+ break;
+
+ case ESCKEY:
+ sound_stop_all_sounds();
+ break;
+ case TABKEY:
+ if(G.qual==0 ) {
+ if(textspace==0) {
+ if(curarea->spacetype==SPACE_IPO) set_editflag_editipo();
+ else if(curarea->spacetype==SPACE_SEQ) enter_meta();
+ else if(G.vd) {
+ /* ook als Alt-E */
+ if(G.obedit==0) enter_editmode();
+ else exit_editmode(1);
+ }
+ return 0;
+ }
+ }
+ else if(G.qual & LR_CTRLKEY){
+ if(G.obpose) exit_posemode(1);
+ else
+ enter_posemode();
+ allqueue(REDRAWHEADERS, 0);
+
+ }
+ else if(G.qual & LR_SHIFTKEY) {
+ if(G.obedit) exit_editmode(1);
+ if(G.f & G_FACESELECT) set_faceselect();
+ if(G.f & G_VERTEXPAINT) set_vpaint();
+ if(G.f & G_WEIGHTPAINT) set_wpaint();
+ if(G.obpose) exit_posemode(1);
+ }
+ break;
+
+ case BACKSPACEKEY:
+ break;
+
+ case AKEY:
+ if(textediting==0 && textspace==0) {
+ if(G.qual & LR_ALTKEY) {
+ if(G.qual & LR_SHIFTKEY) play_anim(1);
+ else play_anim(0);
+ return 0;
+ }
+ }
+ break;
+ case EKEY:
+ if(G.qual & LR_ALTKEY) {
+ if(G.vd && textspace==0) {
+ if(G.obedit==0) enter_editmode();
+ else exit_editmode(1);
+ return 0;
+ }
+ }
+ break;
+ case IKEY:
+ if(textediting==0 && textspace==0 && curarea->spacetype!=SPACE_FILE && curarea->spacetype!=SPACE_IMASEL) {
+ if(G.qual==0) {
+ common_insertkey();
+ return 0;
+ }
+ }
+ break;
+ case JKEY:
+ if(textediting==0 && textspace==0) {
+ if(R.rectot && G.qual==0) {
+ BIF_swap_render_rects();
+ return 0;
+ }
+ }
+ break;
+
+ case NKEY:
+ if(textediting==0 && textspace==0 ) {
+ if(G.qual & LR_CTRLKEY);
+ else if(G.qual==0 || (G.qual & LR_SHIFTKEY)) {
+ clever_numbuts();
+ return 0;
+ }
+ }
+ break;
+
+ case OKEY:
+ if(textediting==0) {
+ if(G.qual & LR_CTRLKEY) {
+ /* There seem to be crashes here sometimes.... String
+ * bound overwrites? I changed dir and str sizes,
+ * let's see if this reoccurs. */
+ sprintf(str, "Open file: %s", G.sce);
+
+ if(okee(str)) {
+ strcpy(dir, G.sce);
+ BIF_read_file(dir);
+ }
+ return 0;
+ }
+ }
+ break;
+
+ case SKEY:
+ if(G.obpose==0 && G.obedit==0) {
+ if(G.qual & LR_CTRLKEY) {
+ if(G.qual & LR_SHIFTKEY);
+ else {
+ strcpy(dir, G.sce);
+ if (untitled(dir)) {
+ activate_fileselect(FILE_BLENDER, "SAVE FILE", dir, BIF_write_file);
+ } else {
+ BIF_write_file(dir);
+ free_filesel_spec(dir);
+ }
+ return 0;
+ }
+ }
+ }
+ break;
+
+ case TKEY:
+ if(G.qual & LR_ALTKEY) {
+ if(G.qual & LR_CTRLKEY) {
+ int a;
+
+ if (G.qual & LR_SHIFTKEY) {
+ double delta, stime;
+
+ waitcursor(1);
+
+ stime= PIL_check_seconds_timer();
+ for(a=0; a<100000; a++) {
+ scrarea_do_windraw(curarea);
+
+ delta= PIL_check_seconds_timer()-stime;
+ if (delta>5.0) break;
+ }
+
+ waitcursor(0);
+ notice("FPS: %f (%d iterations)", a/delta, a);
+ } else {
+ int event= pupmenu("10 Timer%t|draw|draw+swap");
+ if(event>0) {
+ double stime= PIL_check_seconds_timer();
+ char tmpstr[128];
+ int time;
+
+ printf("start timer\n");
+ waitcursor(1);
+
+ for(a=0; a<10; a++) {
+ scrarea_do_windraw(curarea);
+ if(event==2) screen_swapbuffers();
+ }
+
+ time= (PIL_check_seconds_timer()-stime)*1000;
+
+ if(event==1) sprintf(tmpstr, "draw %%t|%d", time);
+ if(event==2) sprintf(tmpstr, "d+sw %%t|%d", time);
+
+ waitcursor(0);
+ pupmenu(tmpstr);
+
+ }
+ }
+ return 0;
+ }}
+ break;
+
+ case UKEY:
+
+ if(textediting==0) {
+ if(G.qual & LR_CTRLKEY) {
+ if(okee("SAVE USER DEFAULTS")) {
+ BIF_write_homefile();
+ }
+ return 0;
+ }
+ }
+ break;
+
+ case WKEY:
+ if(textediting==0) {
+ if(G.qual & LR_CTRLKEY) {
+ if(G.qual & LR_SHIFTKEY);
+ else {
+ strcpy(dir, G.sce);
+ if (untitled(dir)) {
+ activate_fileselect(FILE_BLENDER, "SAVE FILE", dir, BIF_write_file);
+ } else {
+ BIF_write_file(dir);
+ free_filesel_spec(dir);
+ }
+ return 0;
+ }
+ }
+ else if(G.qual & LR_ALTKEY) {
+ write_videoscape_fs();
+ }
+ }
+ break;
+
+ case XKEY:
+ if(G.qual & LR_CTRLKEY) {
+ if(okee("ERASE ALL")) {
+ if( BIF_read_homefile()==0) error("No file ~/.B.blend");
+ }
+ return 0;
+ }
+
+ break;
+ }
+
+ return 1;
+}
+
+/* eof */
diff --git a/source/blender/src/toolbox.c b/source/blender/src/toolbox.c
new file mode 100644
index 00000000000..d811c740d3c
--- /dev/null
+++ b/source/blender/src/toolbox.c
@@ -0,0 +1,1454 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 PY_TOOLBOX 1
+#include <math.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+
+#ifndef WIN32
+#include <unistd.h>
+#else
+#include <io.h>
+#include "BLI_winstuff.h"
+#endif
+
+#include <fcntl.h>
+#include "MEM_guardedalloc.h"
+
+#include "BMF_Api.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+
+#include "DNA_image_types.h"
+#include "DNA_object_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_view3d_types.h"
+
+#include "BKE_plugin_types.h"
+#include "BKE_utildefines.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+
+#include "BIF_gl.h"
+#include "BIF_graphics.h"
+#include "BIF_mainqueue.h"
+#include "BIF_interface.h"
+#include "BIF_toolbox.h"
+#include "BIF_mywindow.h"
+#include "BIF_editarmature.h"
+#include "BIF_editfont.h"
+#include "BIF_editmesh.h"
+#include "BIF_editseq.h"
+#include "BIF_editlattice.h"
+#include "BIF_editsima.h"
+#include "BIF_screen.h"
+#include "BIF_tbcallback.h"
+#include "BIF_editnla.h"
+
+#include "BDR_editobject.h"
+#include "BDR_editcurve.h"
+#include "BDR_editmball.h"
+
+#include "BSE_editipo.h"
+#include "BSE_buttons.h"
+
+#include "IMB_imbuf.h"
+
+#include "mydevice.h"
+#include "blendef.h"
+
+#include "interface.h"
+#include "render.h"
+
+/* ******** NOTES *********** *****************************
+
+ - Toolbox items zelf invullen
+ - de colormap kleuren staan met comments in de bgntoolbox()
+ - de funktie extern_qread eventueel vervangen
+ - let op de benaming van bijzondere toetsen (NumL etc)
+ - meelinken: Button.c, ivm rawcodes
+
+ ***************************** *****************************
+*/
+
+
+static int tbx1, tbx2, tby1, tby2, tbfontyofs, tbmain=0;
+static int tbmemx=TBOXX/2, tbmemy=(TBOXEL-0.5)*TBOXH, tboldwin, addmode= 0;
+static int oldcursor;
+
+ /* variabelen per item */
+static char *tbstr, *tbstr1, *keystr;
+static void (*tbfunc)(int);
+static int tbval;
+
+/* *********** PC PATCH ************* */
+
+void ColorFunc(int i)
+{
+ if(i==TBOXBLACK) glColor3ub(0, 0, 0);
+ else if(i==TBOXWHITE) glColor3ub(240, 240, 240);
+ else if(i==TBOXGREY) glColor3ub(160, 160, 160);
+ else glColor3ub(0, 0, 0);
+}
+
+/* ********************* PYTHON TOOLBOX CALLBACK ************************* */
+
+#ifdef PY_TOOLBOX
+/* see bpython/intern/py_toolbox.c */
+
+/* moved to BIF_toolbox.h */
+/* typedef char** (*tbox_callback)(int, int); */
+
+TBcallback *callback_dummy(int level, int entry)
+{
+ return NULL;
+}
+
+/* callback func ptr for py_toolbox */
+Tbox_callbackfunc g_toolbox_menucallback = &callback_dummy;
+
+void tboxSetCallback(Tbox_callbackfunc f)
+{
+ g_toolbox_menucallback = f;
+}
+
+#endif
+
+/* ********************* TOOLBOX ITEMS ************************* */
+
+void tbox_setinfo(int x, int y)
+{
+ /* afhankelijk van tbmain worden vars gezet */
+ tbstr= 0;
+ tbstr1= 0;
+ tbfunc= 0;
+ tbval= 0;
+ keystr = NULL;
+
+/* main menu entries: defined in BIF_toolbox.h */
+
+ if(x==0) {
+ switch(y) {
+ case TBOX_MAIN_FILE: tbstr= "FILE"; break;
+ case TBOX_MAIN_EDIT: tbstr= "EDIT"; break;
+ case TBOX_MAIN_ADD:
+ if (addmode==OB_MESH) tbstr= " MESH";
+ else if(addmode==OB_CURVE) tbstr= " CURVE";
+ else if(addmode==OB_SURF) tbstr= " SURF";
+ else tbstr= "ADD";
+ break;
+ case TBOX_MAIN_OBJECT1: tbstr= "OBJECT"; break;
+ case TBOX_MAIN_OBJECT2: tbstr= "OBJECT"; break;
+ case TBOX_MAIN_MESH: tbstr= "MESH"; break;
+ case TBOX_MAIN_CURVE: tbstr= "CURVE"; break;
+ case TBOX_MAIN_KEY: tbstr= "KEY"; break;
+ case TBOX_MAIN_RENDER: tbstr= "RENDER"; break;
+ case TBOX_MAIN_VIEW: tbstr= "VIEW"; break;
+#ifdef PY_TOOLBOX
+ case TBOX_MAIN_PYTOOL:
+ {
+ if (g_toolbox_menucallback(0, 0)) // valid callback?
+ tbstr= "PYTOOL";
+ break;
+ }
+#endif
+ }
+ }
+
+/* TOPICS */
+ else {
+
+
+/* FILE TOPICS */
+ if(tbmain==TBOX_MAIN_FILE) {
+ switch(y) {
+ case 0: tbstr= "New"; tbstr1= "c|x"; keystr= "Ctrl X"; break;
+ case 1: tbstr= "Open"; tbstr1= "F1"; keystr= "F1"; break;
+ case 2: tbstr= "Reopen Last"; tbstr1= "c|o"; keystr= "Ctrl O"; break;
+ case 3: tbstr= "Append"; tbstr1= "shift+F1"; keystr= "Shift F1"; break;
+ case 4: tbstr= ""; tbstr1= ""; keystr= ""; break;
+ case 5: tbstr= "Save As"; tbstr1= "F2"; keystr= "F2"; break;
+ case 6: tbstr= "Save"; tbstr1= "c|w"; keystr= "Ctrl W"; break;
+ case 7: tbstr= ""; tbstr1= ""; keystr= ""; break;
+ case 8: tbstr= "Save Image"; tbstr1= "F3"; keystr= "F3"; break;
+ case 9: tbstr= "Save VRML"; tbstr1= "c|F2"; keystr= "Ctrl F2"; break;
+ case 10: tbstr= "Save DXF"; tbstr1= "shift+F2"; keystr= "Shift F2"; break;
+ case 11: tbstr= "Save VideoScape"; tbstr1= "a|w"; keystr= "Alt W"; break;
+/* case 12: tbstr= ""; tbstr1= ""; keystr= ""; break; */
+ case 13: tbstr= "Quit"; tbstr1= "q"; keystr= "Q"; break;
+ }
+ }
+
+/* EDIT TOPICS */
+ if(tbmain==TBOX_MAIN_EDIT) {
+ switch(y) {
+ case 0: tbstr= "(De)Select All"; tbstr1= "a"; keystr= "A"; break;
+ case 1: tbstr= "Border Select"; tbstr1= "b"; keystr= "B"; break;
+ case 2: tbstr= ""; tbstr1= ""; keystr= ""; break;
+ case 3: tbstr= "Duplicate"; tbstr1= "D"; keystr= "Shift D"; break;
+ case 4: tbstr= "Delete"; tbstr1= "x"; keystr= "X"; break;
+ case 5: tbstr= "Edit Mode"; tbstr1= "Tab"; keystr= "Tab"; break;
+ case 6: tbstr= ""; tbstr1= ""; keystr= ""; break;
+ case 7: tbstr= "Grabber"; tbstr1= "g"; keystr= "G"; break;
+ case 8: tbstr= "Rotate"; tbstr1= "r"; keystr= "R"; break;
+ case 9: tbstr= "Scale"; tbstr1= "s"; keystr= "S"; break;
+/* case 10: tbstr= ""; tbstr1= ""; keystr= ""; break; */
+ case 11: tbstr= "Shear"; tbstr1= "c|s"; keystr= "Ctrl S"; break;
+ case 12: tbstr= "Warp/Bend"; tbstr1= "W"; keystr= "Shift W"; break;
+ case 13: tbstr= "Snap Menu"; tbstr1= "S"; keystr= "Shift S"; break;
+ }
+ }
+
+/* ADD TOPICS */
+ if(tbmain==TBOX_MAIN_ADD) {
+
+ if(addmode==0) {
+ switch(y) {
+ case 0: tbstr= "Mesh"; tbstr1= ">>"; keystr= ">>"; tbval=OB_MESH; break;
+ case 1: tbstr= "Curve"; tbstr1= ">>"; keystr= ">>"; tbval=OB_CURVE; ; break;
+ case 2: tbstr= "Surface"; tbstr1= ">>"; keystr= ">>"; tbval=OB_SURF; break;
+ case 3: tbstr= "Text"; tbstr1= ""; keystr= ""; tbval=OB_FONT; tbfunc= add_primitiveFont; break;
+ case 4: tbstr= "MetaBall"; tbstr1= ""; keystr= ""; tbval=OB_MBALL; tbfunc= add_primitiveMball; break;
+ case 5: tbstr= "Empty"; tbstr1= "A"; keystr= ""; tbval=OB_EMPTY; break;
+ case 6: tbstr= ""; tbstr1= ""; keystr= ""; tbval=0; break;
+ case 7: tbstr= "Camera"; tbstr1= "A"; keystr= ""; tbval=OB_CAMERA; break;
+ case 8: tbstr= "Lamp"; tbstr1= "A"; keystr= ""; tbval=OB_LAMP; break;
+ case 9: tbstr= "Armature"; tbstr1= ""; keystr= ""; tbval=OB_ARMATURE; tbfunc=add_primitiveArmature; break;
+ case 10: tbstr= ""; tbstr1= ""; keystr= ""; tbval=0; break;
+ case 11: tbstr= "Lattice"; tbstr1= "A"; keystr= ""; tbval=OB_LATTICE; break;
+ case 12: tbstr= ""; tbstr1= ""; keystr= ""; tbval=0; break;
+ case 13: tbstr= ""; tbstr1= ""; keystr= ""; tbval=0; break;
+ }
+ if(tbstr1 && tbstr1[0]=='A') tbfunc= (void (*)(int) )add_object_draw;
+ }
+ else if(addmode==OB_MESH) {
+ switch(y) {
+ case 0: tbstr= ">Plane"; tbstr1= "A"; keystr= ""; tbval=0; break;
+ case 1: tbstr= ">Cube"; tbstr1= "A"; keystr= ""; tbval=1; break;
+ case 2: tbstr= ">Circle"; tbstr1= "A"; keystr= ""; tbval=4; break;
+ case 3: tbstr= ">UVsphere"; tbstr1= "A"; keystr= ""; tbval=11; break;
+ case 4: tbstr= ">Icosphere";tbstr1= "A"; keystr= ""; tbval=12; break;
+ case 5: tbstr= ">Cylinder"; tbstr1= "A"; keystr= ""; tbval=5; break;
+ case 6: tbstr= ">Tube"; tbstr1= "A"; keystr= ""; tbval=6; break;
+ case 7: tbstr= ">Cone"; tbstr1= "A"; keystr= ""; tbval=7; break;
+ case 8: tbstr= ">"; tbstr1= ""; keystr= ""; break;
+ case 9: tbstr= ">Grid"; tbstr1= "A"; keystr= ""; tbval=10; break;
+ case 13: tbstr= ">Monkey"; tbstr1= "A"; keystr= ""; tbval=13; break;
+ }
+ if(tbstr1 && tbstr1[0]=='A') tbfunc= add_primitiveMesh;
+ }
+ else if(addmode==OB_SURF) {
+ switch(y) {
+ case 0: tbstr= ">Curve"; tbstr1= "A"; keystr= ""; tbval=0; break;
+ case 1: tbstr= ">Circle"; tbstr1= "A"; keystr= ""; tbval=1; break;
+ case 2: tbstr= ">Surface"; tbstr1= "A"; keystr= ""; tbval=2; break;
+ case 3: tbstr= ">Tube"; tbstr1= "A"; keystr= ""; tbval=3; break;
+ case 4: tbstr= ">Sphere"; tbstr1= "A"; keystr= ""; tbval=4; break;
+ case 5: tbstr= ">Donut"; tbstr1= "A"; keystr= ""; tbval=5; break;
+ }
+ if(tbstr1 && tbstr1[0]=='A') tbfunc= add_primitiveNurb;
+ }
+/* else if (addmode==OB_ARMATURE){
+ switch(y) {
+ case 0: tbstr= ">Bone"; tbstr1= "A"; keystr= ""; tbval=0; break;
+ case 1: tbstr= ">Hand"; tbstr1= "A"; keystr= ""; tbval=1; break;
+ case 2: tbstr= ">Biped"; tbstr1= "A"; keystr= ""; tbval=2; break;
+ }
+ if(tbstr1 && tbstr1[0]=='A') tbfunc= add_primitiveArmature;
+ }
+*/
+ else if(addmode==OB_CURVE) {
+ switch(y) {
+ case 0: tbstr= ">Bezier Curve"; tbstr1= "A"; keystr= ""; tbval=10; break;
+ case 1: tbstr= ">Bezier Circle"; tbstr1= "A"; keystr= ""; tbval=11; break;
+ case 2: tbstr= ">"; tbstr1= ""; keystr= ""; break;
+ case 3: tbstr= ">Nurbs Curve"; tbstr1= "A"; keystr= ""; tbval=40; break;
+ case 4: tbstr= ">Nurbs Circle"; tbstr1= "A"; keystr= ""; tbval=41; break;
+ case 5: tbstr= ">"; tbstr1= ""; keystr= ""; break;
+ case 6: tbstr= ">Path"; tbstr1= "A"; keystr= ""; tbval=46; break;
+ }
+ if(tbstr1 && tbstr1[0]=='A') tbfunc= add_primitiveCurve;
+ }
+/* else if(addmode==OB_MBALL) {
+ switch(y) {
+ case 0: tbstr= "Ball"; tbstr1= "A"; tbval=1; break;
+ case 1: tbstr= ""; tbstr1= ""; break;
+ case 2: tbstr= ""; tbstr1= ""; break;
+ case 3: tbstr= ""; tbstr1= ""; break;
+ case 4: tbstr= ""; tbstr1= ""; break;
+ case 5: tbstr= ""; tbstr1= ""; break;
+ case 6: tbstr= ""; tbstr1= ""; break;
+ case 7: tbstr= ""; tbstr1= ""; break;
+ case 8: tbstr= ""; tbstr1= ""; break;
+ case 9: tbstr= ""; tbstr1= ""; break;
+ case 10: tbstr= ""; tbstr1= ""; break;
+ case 11: tbstr= "Duplicate";tbstr1= "D"; break;
+ }
+ if(tbstr1 && tbstr1[0]=='A') tbfunc= add_primitiveMball;
+ }*/
+ }
+
+/* OB TOPICS 1 */
+ else if(tbmain==TBOX_MAIN_OBJECT1) {
+ switch(y) {
+ case 0: tbstr= "Clear Size"; tbstr1= "a|s"; keystr= "Alt S"; break;
+ case 1: tbstr= "Clear Rotation"; tbstr1= "a|r"; keystr= "Alt R"; break;
+ case 2: tbstr= "Clear Location"; tbstr1= "a|g"; keystr= "Alt G"; break;
+ case 3: tbstr= "Clear Origin"; tbstr1= "a|o"; keystr= "Alt O"; break;
+ case 4: tbstr= "Make Parent"; tbstr1= "c|p"; keystr= "Ctrl P"; break;
+ case 5: tbstr= "Clear Parent"; tbstr1= "a|p"; keystr= "Alt P"; break;
+ case 6: tbstr= "Make Track"; tbstr1= "c|t"; keystr= "Ctrl T"; break;
+ case 7: tbstr= "Clear Track"; tbstr1= "a|t"; keystr= "Alt T"; break;
+/* case 8: tbstr= ""; tbstr1= ""; keystr= ""; break;
+ case 9: tbstr= ""; tbstr1= ""; keystr= ""; break; */
+ case 10: tbstr= "Image Displist"; tbstr1= "c|d"; keystr= "Ctrl D"; break;
+ case 11: tbstr= "Image Aspect"; tbstr1= "a|v"; keystr= "Alt V"; break;
+ }
+ }
+
+/* OB TOPICS 2 */
+ else if(tbmain==TBOX_MAIN_OBJECT2) {
+ switch(y) {
+ case 0: tbstr= "Edit Mode"; tbstr1= "Tab"; keystr= "Tab"; break;
+ case 1: tbstr= "Move To Layer"; tbstr1= "m"; keystr= "M"; break;
+ case 2: tbstr= "Delete"; tbstr1= "x"; keystr= "X"; break;
+ case 3: tbstr= "Delete All"; tbstr1= "c|x"; keystr= "Ctrl X"; break;
+ case 4: tbstr= "Apply Size/Rot"; tbstr1= "c|a"; keystr= "Ctrl A"; break;
+ case 5: tbstr= "Apply Deform"; tbstr1= "c|A"; keystr= "Ctrl Shift A"; break;
+ case 6: tbstr= "Join"; tbstr1= "c|j"; keystr= "Ctrl J"; break;
+ case 7: tbstr= "Make Local"; tbstr1= "l"; keystr= "L"; break;
+ case 8: tbstr= "Select Linked"; tbstr1= "L"; keystr= "Shift L"; break;
+ case 9: tbstr= "Make Links"; tbstr1= "c|l"; keystr= "Ctrl L"; break;
+ case 10: tbstr= "Copy Menu"; tbstr1= "c|c"; keystr= "Ctrl C"; break;
+ case 11: tbstr= "Convert Menu"; tbstr1= "a|c"; keystr= "Alt C"; break;
+ }
+ }
+
+/* mesh TOPICS */
+ else if(tbmain==TBOX_MAIN_MESH) {
+ switch(y) {
+ case 0: tbstr= "Select Linked"; tbstr1= "l"; keystr= "L"; break;
+ case 1: tbstr= "Deselect Linked"; tbstr1= "L"; keystr= "Shift L"; break;
+ case 2: tbstr= "Extrude"; tbstr1= "e"; keystr= "E"; break;
+ case 3: tbstr= "Delete Menu"; tbstr1= "x"; keystr= "X"; break;
+ case 4: tbstr= "Make edge/face"; tbstr1= "f"; keystr= "F"; break;
+ case 5: tbstr= "Fill"; tbstr1= "F"; keystr= "Shift F"; break;
+ case 6: tbstr= "Split"; tbstr1= "y"; keystr= "Y"; break;
+ case 7: tbstr= "Undo/reload"; tbstr1= "u"; keystr= "U"; break;
+ case 8: tbstr= "Calc Normals"; tbstr1= "c|n"; keystr= "Ctrl N"; break;
+ case 9: tbstr= "Separate"; tbstr1= "p"; keystr= "P"; break;
+ case 10: tbstr= "Write Videosc"; tbstr1= "a|w"; keystr= "Alt W"; break;
+/* case 11: tbstr= ""; tbstr1= ""; keystr= ""; break; */
+ }
+ }
+
+/* CURVE TOPICS */
+ else if(tbmain==TBOX_MAIN_CURVE) {
+ switch(y) {
+ case 0: tbstr= "Select Linked"; tbstr1= "l"; keystr= "L"; break;
+ case 1: tbstr= "Deselect Linked"; tbstr1= "L"; keystr= "Shift L"; break;
+ case 2: tbstr= "Extrude"; tbstr1= "e"; keystr= "E"; break;
+ case 3: tbstr= "Delete Menu"; tbstr1= "x"; keystr= "X"; break;
+ case 4: tbstr= "Make Segment"; tbstr1= "f"; keystr= "F"; break;
+ case 5: tbstr= "Cyclic"; tbstr1= "c"; keystr= "C"; break;
+/* case 6: tbstr= ""; tbstr1= ""; keystr= ""; break; */
+ case 7: tbstr= "Select Row"; tbstr1= "R"; keystr= "Shift R"; break;
+ case 8: tbstr= "Calc Handle"; tbstr1= "h"; keystr= "H"; break;
+ case 9: tbstr= "Auto Handle"; tbstr1= "H"; keystr= "Shift H"; break;
+ case 10: tbstr= "Vect Handle"; tbstr1= "v"; keystr= "V"; break;
+ case 11: tbstr= "Specials"; tbstr1= "w"; keystr= "W"; break;
+ }
+ }
+
+/* KEY TOPICS */
+ else if(tbmain==TBOX_MAIN_KEY) {
+ switch(y) {
+ case 0: tbstr= "Insert"; tbstr1= "i"; keystr= "I"; break;
+ case 1: tbstr= "Show"; tbstr1= "k"; keystr= "K"; break;
+ case 2: tbstr= "Next"; tbstr1= "PageUp"; keystr= "PgUp"; break;
+ case 3: tbstr= "Prev"; tbstr1= "PageDn"; keystr= "PgDn"; break;
+ case 4: tbstr= "Show+Sel"; tbstr1= "K"; keystr= "Shift K"; break;
+/* case 5: tbstr= ""; tbstr1= ""; keystr= ""; break;
+ case 6: tbstr= ""; tbstr1= ""; keystr= ""; break;
+ case 7: tbstr= ""; tbstr1= ""; keystr= ""; break;
+ case 8: tbstr= ""; tbstr1= ""; keystr= ""; break;
+ case 9: tbstr= ""; tbstr1= ""; keystr= ""; break;
+ case 10: tbstr= ""; tbstr1= ""; keystr= ""; break;
+ case 11: tbstr= ""; tbstr1= ""; keystr= ""; break; */
+ }
+ }
+
+/* RENDER TOPICS */
+ else if(tbmain==TBOX_MAIN_RENDER) {
+ switch(y) {
+ case 0: tbstr= "Render Window"; tbstr1= "F11"; keystr= "F11"; break;
+ case 1: tbstr= "Render"; tbstr1= "F12"; keystr= "F12"; break;
+ case 2: tbstr= "Set Border"; tbstr1= "B"; keystr= "Shift B"; break;
+ case 3: tbstr= "Image Zoom"; tbstr1= "z"; keystr= "Z"; break;
+/* case 4: tbstr= ""; tbstr1= ""; keystr= ""; break;
+ case 5: tbstr= ""; tbstr1= ""; keystr= ""; break;
+ case 6: tbstr= ""; tbstr1= ""; keystr= ""; break;
+ case 7: tbstr= ""; tbstr1= ""; keystr= ""; break;
+ case 8: tbstr= ""; tbstr1= ""; keystr= ""; break;
+ case 9: tbstr= ""; tbstr1= ""; keystr= ""; break;
+ case 10: tbstr= ""; tbstr1= ""; keystr= ""; break;
+ case 11: tbstr= ""; tbstr1= ""; keystr= ""; break; */
+ }
+ }
+
+/* VIEW TOPICS */
+ else if(tbmain==TBOX_MAIN_VIEW) {
+ switch(y) {
+/* case 0: tbstr= ""; tbstr1= ""; break;
+ case 1: tbstr= ""; tbstr1= ""; break;
+ case 2: tbstr= ""; tbstr1= ""; break;
+ case 3: tbstr= ""; tbstr1= ""; break; */
+ case 4: tbstr= "Centre"; tbstr1= "c"; keystr= "C"; break;
+ case 5: tbstr= "Home"; tbstr1= "C"; keystr= "Shift C"; break;
+/* case 6: tbstr= ""; tbstr1= ""; break;
+ case 7: tbstr= ""; tbstr1= ""; break;
+ case 8: tbstr= ""; tbstr1= ""; break;*/
+ case 9: tbstr= "Z-Buffer"; tbstr1= "z"; keystr= "Z"; break;
+/* case 10: tbstr= ""; tbstr1= ""; break;
+ case 11: tbstr= ""; tbstr1= ""; break;*/
+ }
+ }
+#ifdef PY_TOOLBOX
+ else if(tbmain==TBOX_MAIN_PYTOOL) {
+ TBcallback *t= g_toolbox_menucallback(0, y); // call python menu constructor
+ if (t) {
+ tbstr = t->desc;
+ keystr = t->key;
+ tbfunc = t->cb;
+ tbval = t->val;
+ }
+ }
+#endif
+ }
+}
+
+/* ******************** INIT ************************** */
+
+void dummy(void)
+{
+
+}
+
+
+void bgnpupdraw(int startx, int starty, int endx, int endy)
+{
+ #if defined(__sgi) || defined(__sun__)
+ /* this is a dirty patch: XgetImage gets sometimes the backbuffer */
+ my_get_frontbuffer_image(0, 0, 1, 1);
+ my_put_frontbuffer_image();
+ #endif
+
+ tboldwin= mywinget();
+
+ mywinset(G.curscreen->mainwin);
+
+ /* pietsje groter, 1 pixel aan de rand */
+
+ glReadBuffer(GL_FRONT);
+ glDrawBuffer(GL_FRONT);
+
+ glFinish();
+
+ my_get_frontbuffer_image(startx-1, starty-4, endx-startx+5, endy-starty+6);
+
+ oldcursor= get_cursor();
+ set_cursor(CURSOR_STD);
+
+ tbfontyofs= (TBOXH-11)/2; /* toolbox, hier stond ooit getheigh */
+}
+
+void endpupdraw(void)
+{
+ glFinish();
+ my_put_frontbuffer_image();
+
+ if(tboldwin) {
+ mywinset(tboldwin);
+ set_cursor(oldcursor);
+ }
+
+ glReadBuffer(GL_BACK);
+ glDrawBuffer(GL_BACK);
+}
+
+/* ********************************************** */
+
+void asciitoraw(int ch, unsigned short *event, unsigned short *qual)
+{
+ if( isalpha(ch)==0 ) return;
+
+ if( isupper(ch) ) {
+ *qual= LEFTSHIFTKEY;
+ ch= tolower(ch);
+ }
+
+ switch(ch) {
+ case 'a': *event= AKEY; break;
+ case 'b': *event= BKEY; break;
+ case 'c': *event= CKEY; break;
+ case 'd': *event= DKEY; break;
+ case 'e': *event= EKEY; break;
+ case 'f': *event= FKEY; break;
+ case 'g': *event= GKEY; break;
+ case 'h': *event= HKEY; break;
+ case 'i': *event= IKEY; break;
+ case 'j': *event= JKEY; break;
+ case 'k': *event= KKEY; break;
+ case 'l': *event= LKEY; break;
+ case 'm': *event= MKEY; break;
+ case 'n': *event= NKEY; break;
+ case 'o': *event= OKEY; break;
+ case 'p': *event= PKEY; break;
+ case 'q': *event= QKEY; break;
+ case 'r': *event= RKEY; break;
+ case 's': *event= SKEY; break;
+ case 't': *event= TKEY; break;
+ case 'u': *event= UKEY; break;
+ case 'v': *event= VKEY; break;
+ case 'w': *event= WKEY; break;
+ case 'x': *event= XKEY; break;
+ case 'y': *event= YKEY; break;
+ case 'z': *event= ZKEY; break;
+ }
+}
+
+void tbox_execute(void)
+{
+ /* als tbfunc: functie aanroepen */
+ /* als tbstr1 is een string: value tbval in queue stopen */
+ unsigned short event=0;
+ unsigned short qual1=0, qual2=0;
+
+ if(tbfunc) {
+ tbfunc(tbval);
+ }
+ else if(tbstr1) {
+ if(strcmp(tbstr1, "Tab")==0) {
+ event= TABKEY;
+ }
+ else if(strcmp(tbstr1, "PageUp")==0) {
+ event= PAGEUPKEY;
+ }
+ else if(strcmp(tbstr1, "PageDn")==0) {
+ event= PAGEDOWNKEY;
+ }
+ else if(strcmp(tbstr1, "shift+F1")==0) {
+ qual1= LEFTSHIFTKEY;
+ event= F1KEY;
+ }
+ else if(strcmp(tbstr1, "shift+F2")==0) {
+ qual1= LEFTSHIFTKEY;
+ event= F2KEY;
+ }
+ /* ctrl-s (Shear): switch into editmode ### */
+ else if(strcmp(tbstr1, "c|s")==0) {
+ if (!G.obedit) {
+ enter_editmode();
+ /* ### put these into a deselectall_gen() */
+ if(G.obedit->type==OB_MESH) deselectall_mesh();
+ else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) deselectall_nurb();
+ else if(G.obedit->type==OB_MBALL) deselectall_mball();
+ else if(G.obedit->type==OB_LATTICE) deselectall_Latt();
+ /* ### */
+ }
+ qual1 = LEFTCTRLKEY;
+ event = SKEY;
+ }
+ else if(strcmp(tbstr1, "W")==0) {
+ if (!G.obedit) {
+ enter_editmode();
+ /* ### put these into a deselectall_gen() */
+ if(G.obedit->type==OB_MESH) deselectall_mesh();
+ else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) deselectall_nurb();
+ else if(G.obedit->type==OB_MBALL) deselectall_mball();
+ else if(G.obedit->type==OB_LATTICE) deselectall_Latt();
+ /* ### */
+ }
+ qual1 = LEFTSHIFTKEY;
+ event = WKEY;
+ }
+
+ else if(strlen(tbstr1)<4 || (strlen(tbstr1)==4 && tbstr1[2]=='F')) {
+
+ if(tbstr1[1]=='|') {
+ if(tbstr1[0]=='c') qual1= LEFTCTRLKEY;
+ else if(tbstr1[0]=='a') qual1= LEFTALTKEY;
+
+ if (tbstr1[2]=='F') {
+ switch(tbstr1[3]) {
+ case '1': event= F1KEY; break;
+ case '2': event= F2KEY; break;
+ case '3': event= F3KEY; break;
+ case '4': event= F4KEY; break;
+ case '5': event= F5KEY; break;
+ case '6': event= F6KEY; break;
+ case '7': event= F7KEY; break;
+ case '8': event= F8KEY; break;
+ case '9': event= F9KEY; break;
+ }
+ }
+ else asciitoraw(tbstr1[2], &event, &qual2);
+ }
+ else if(tbstr1[1]==0) {
+ asciitoraw(tbstr1[0], &event, &qual2);
+ }
+ else if(tbstr1[0]=='F') {
+ event= atoi(tbstr1+1);
+ switch(event) {
+ case 1: event= F1KEY; break;
+ case 2: event= F2KEY; break;
+ case 3: event= F3KEY; break;
+ case 4: event= F4KEY; break;
+ case 5: event= F5KEY; break;
+ case 6: event= F6KEY; break;
+ case 7: event= F7KEY; break;
+ case 8: event= F8KEY; break;
+ case 9: event= F9KEY; break;
+ case 10: event= F10KEY; break;
+ case 11: event= F11KEY; break;
+ case 12: event= F12KEY; break;
+ }
+ }
+ }
+
+ if(event) {
+ if(qual1) mainqenter(qual1, 1);
+ if(qual2) mainqenter(qual2, 1);
+ mainqenter(event, 1);
+ mainqenter(event, 0);
+ mainqenter(EXECUTE, 1);
+ if(qual1) mainqenter(qual1, 0);
+ if(qual2) mainqenter(qual2, 0);
+ }
+ }
+
+}
+
+void tbox_getmouse(mval)
+short *mval;
+{
+
+ getmouseco_sc(mval);
+
+}
+
+void tbox_setmain(int val)
+{
+ tbmain= val;
+
+ if(tbmain==0 && G.obedit) {
+ addmode= G.obedit->type;
+ }
+}
+
+void bgntoolbox(void)
+{
+ short xmax, ymax, mval[2];
+
+ xmax = G.curscreen->sizex;
+ ymax = G.curscreen->sizey;
+
+ tbox_getmouse(mval);
+
+ if(mval[0]<95) mval[0]= 95;
+ if(mval[0]>xmax-95) mval[0]= xmax-95;
+
+ warp_pointer(mval[0], mval[1]);
+
+ tbx1= mval[0]-tbmemx;
+ tby1= mval[1]-tbmemy;
+ if(tbx1<10) tbx1= 10;
+ if(tby1<10) tby1= 10;
+
+ tbx2= tbx1+TBOXX;
+ tby2= tby1+TBOXY;
+ if(tbx2>xmax) {
+ tbx2= xmax-10;
+ tbx1= tbx2-TBOXX;
+ }
+ if(tby2>ymax) {
+ tby2= ymax-10;
+ tby1= tby2-TBOXY;
+ }
+
+ bgnpupdraw(tbx1, tby1, tbx2, tby2);
+}
+
+void endtoolbox(void)
+{
+ short mval[2];
+
+ tbox_getmouse(mval);
+ if(mval[0]>tbx1 && mval[0]<tbx2)
+ if(mval[1]>tby1 && mval[1]<tby2) {
+ tbmemx= mval[0]-(tbx1);
+ tbmemy= mval[1]-(tby1);
+ }
+
+ endpupdraw();
+}
+
+
+void tbox_embossbox(short x1, short y1, short x2, short y2, short type)
+/* type: 0=menu, 1=menusel, 2=topic, 3=topicsel */
+{
+
+ if(type==0) {
+ glColor3ub(160, 160, 160);
+ glRects(x1+1, y1+1, x2-1, y2-1);
+ }
+ if(type==1) {
+ glColor3ub(50, 50, 100);
+ glRects(x1+1, y1+1, x2-1, y2-1);
+ }
+ if(type==2) {
+ glColor3ub(190, 190, 190);
+ glRects(x1+1, y1+1, x2-1, y2-1);
+ }
+ if(type==3) {
+ cpack(0xc07070);
+ glRects(x1+1, y1+1, x2-1, y2-1);
+ }
+
+ if(type & 1) cpack(0xFFFFFF);
+ else cpack(0x0);
+}
+
+
+void tbox_drawelem_body(x, y, type)
+{
+ int x1 = 0, y1, x2 = 0, y2;
+
+ if(x==0) {
+ x1= tbx1; x2= tbx1+TBOXXL;
+ }
+ else if(x==1) {
+ x1= tbx1+TBOXXL;
+ x2= x1+ TBOXXR-1;
+ }
+
+ y1= tby1+ (TBOXEL-y-1)*TBOXH;
+ y2= y1+TBOXH-1;
+
+ tbox_embossbox(x1, y1, x2, y2, type);
+
+}
+
+void tbox_drawelem_text(x, y, type)
+{
+ int x1 = 0, y1, x2 = 0, y2, len1, len2;
+
+ if(x==0) {
+ x1= tbx1; x2= tbx1+TBOXXL;
+ }
+ else if(x==1) {
+ x1= tbx1+TBOXXL;
+ x2= x1+ TBOXXR-1;
+ }
+
+ y1= tby1+ (TBOXEL-y-1)*TBOXH;
+ y2= y1+TBOXH-1;
+
+ if(type==0 || type==2) {
+ ColorFunc(TBOXBLACK);
+ }
+ else {
+ glColor3ub(240, 240, 240);
+ }
+
+ /* tekst */
+ tbox_setinfo(x, y);
+ if(tbstr && tbstr[0]) {
+ len1= 5+BMF_GetStringWidth(G.font, tbstr);
+// if(tbstr1) len2= 5+BMF_GetStringWidth(G.font, tbstr1); else len2= 0;
+ if(keystr) len2= 5+BMF_GetStringWidth(G.font, keystr); else len2= 0;
+
+ while(len1>0 && (len1+len2+5>x2-x1) ) {
+ tbstr[strlen(tbstr)-1]= 0;
+ len1= BMF_GetStringWidth(G.font, tbstr);
+ }
+
+ glRasterPos2i(x1+5, y1+tbfontyofs);
+ BMF_DrawString(G.font, tbstr);
+
+// if(tbstr1 && tbstr1[0]) {
+ if(keystr && keystr[0]) {
+ if(type & 1) {
+ ColorFunc(TBOXBLACK);
+
+ glRecti(x2-len2-2, y1+2, x2-3, y2-2);
+ ColorFunc(TBOXWHITE);
+ glRasterPos2i(x2-len2, y1+tbfontyofs);
+// BMF_DrawString(G.font, tbstr1);
+ BMF_DrawString(G.font, keystr);
+ }
+ else {
+ ColorFunc(TBOXBLACK);
+ glRasterPos2i(x2-len2, y1+tbfontyofs);
+// BMF_DrawString(G.font, tbstr1);
+ BMF_DrawString(G.font, keystr);
+ }
+ }
+ }
+}
+
+
+void tbox_drawelem(x, y, type)
+int x, y, type;
+{
+ /* type: 0=menu, 1=menusel, 2=topic, 3=topicsel */
+
+ tbox_drawelem_body(x, y, type);
+ tbox_drawelem_text(x, y, type);
+
+}
+
+void tbox_getactive(x, y)
+int *x, *y;
+{
+ short mval[2];
+
+ tbox_getmouse(mval);
+
+ mval[0]-=tbx1;
+ if(mval[0]<TBOXXL) *x= 0;
+ else *x= 1;
+
+ *y= mval[1]-tby1;
+ *y/= TBOXH;
+ *y= TBOXEL- *y-1;
+ if(*y<0) *y= 0;
+ if(*y>TBOXEL-1) *y= TBOXEL-1;
+
+}
+
+void drawtoolbox(void)
+{
+ int x, y, actx, acty, type;
+
+ tbox_getactive(&actx, &acty);
+
+ /* de background */
+ for(x=0; x<2; x++) {
+
+ for(y=0; y<TBOXEL; y++) {
+
+ if(x==0) type= 0;
+ else type= 2;
+
+ if(actx==x && acty==y) type++;
+ if(type==0) {
+ if(tbmain==y) type= 1;
+ }
+
+ tbox_drawelem_body(x, y, type);
+
+ }
+ }
+
+ /* de text */
+ for(x=0; x<2; x++) {
+
+ for(y=0; y<TBOXEL; y++) {
+
+ if(x==0) type= 0;
+ else type= 2;
+
+ if(actx==x && acty==y) type++;
+ if(type==0) {
+ if(tbmain==y) type= 1;
+ }
+
+ tbox_drawelem_text(x, y, type);
+
+ }
+ }
+ glFinish(); /* for geforce, to show it in the frontbuffer */
+
+}
+
+
+void toolbox(void)
+{
+ int actx, acty, y;
+ unsigned short event;
+ short val, mval[2], xo= -1, yo=0;
+
+ bgntoolbox();
+ glColor3ub(0xB0, 0xB0, 0xB0);
+ uiDrawMenuBox((float)tbx1, (float)tby1-1, (float)tbx2, (float)tby2);
+ drawtoolbox();
+
+ /*
+ * De aktieve window wordt in queue terug gestopt.
+ */
+
+ while(1) {
+ event= extern_qread(&val);
+ if(event) {
+ switch(event) {
+ case LEFTMOUSE: case MIDDLEMOUSE: case RIGHTMOUSE: case RETKEY: case PADENTER:
+ if(val==1) {
+ tbox_getactive(&actx, &acty);
+ tbox_setinfo(actx, acty);
+
+ if(event==RIGHTMOUSE) {
+ if(addmode) {
+ addmode= 0;
+ drawtoolbox();
+ }
+ }
+ else if(tbstr1 && tbstr1[0]=='>') {
+ addmode= tbval;
+ drawtoolbox();
+ }
+ else {
+ endtoolbox();
+ tbox_execute();
+ return;
+ }
+ }
+ break;
+ case ESCKEY:
+ /* altkeys: om conflicten met overdraw en stow/push/pop te voorkomen */
+#ifndef MAART
+/* Temporary for making screen dumps (Alt+PrtSc) */
+ case LEFTALTKEY:
+ case RIGHTALTKEY:
+#endif /* MAART */
+ if(val) endtoolbox();
+ return;
+ }
+ }
+
+ tbox_getmouse(mval);
+ if(mval[0]<tbx1-10 || mval[0]>tbx2+10 || mval[1]<tby1-10 || mval[1]>tby2+10) break;
+
+ tbox_getactive(&actx, &acty);
+
+ /* muisafhandeling en redraw */
+ if(xo!=actx || yo!=acty) {
+ if(actx==0) {
+ if (acty==0) addmode=0;
+
+ tbox_drawelem(0, tbmain, 0);
+ tbox_drawelem(0, acty, 1);
+
+ tbmain= acty;
+ addmode= 0;
+ for(y=0; y<TBOXEL; y++) tbox_drawelem(1, y, 2);
+ }
+ else if(xo> -1) {
+ if(xo==0) tbox_drawelem(xo, yo, 1);
+ else tbox_drawelem(xo, yo, 2);
+ tbox_drawelem(actx, acty, 3);
+ }
+
+ glFinish(); /* for geforce, to show it in the frontbuffer */
+
+ xo= actx;
+ yo= acty;
+ }
+ }
+
+ endtoolbox();
+}
+
+/* ************************************ */
+
+static int vconfirm(char *title, char *itemfmt, va_list ap)
+{
+ char *s, buf[512];
+
+ s= buf;
+ if (title) s+= sprintf(s, "%s%%t|", title);
+ vsprintf(s, itemfmt, ap);
+
+ return (pupmenu(buf)>=0);
+}
+
+static int confirm(char *title, char *itemfmt, ...)
+{
+ va_list ap;
+ int ret;
+
+ va_start(ap, itemfmt);
+ ret= vconfirm(title, itemfmt, ap);
+ va_end(ap);
+
+ return ret;
+}
+
+int okee(char *str, ...)
+{
+ va_list ap;
+ int ret;
+
+ va_start(ap, str);
+ ret= vconfirm("OK?", str, ap);
+ va_end(ap);
+
+ return ret;
+}
+
+void notice(char *str, ...)
+{
+ va_list ap;
+
+ va_start(ap, str);
+ vconfirm(NULL, str, ap);
+ va_end(ap);
+}
+
+void error(char *fmt, ...)
+{
+ va_list ap;
+ char nfmt[256];
+
+ sprintf(nfmt, "ERROR: %s", fmt);
+
+ va_start(ap, fmt);
+ if (G.background || !G.curscreen) {
+ vprintf(nfmt, ap);
+ printf("\n");
+ } else {
+ vconfirm(NULL, nfmt, ap);
+ }
+ va_end(ap);
+}
+
+int saveover(char *file)
+{
+ return (!BLI_exists(file) || confirm("SAVE OVER", file));
+}
+
+/* ****************** EXTRAATJE **************** */
+
+short button(short *var, short min, short max, char *str)
+{
+ uiBlock *block;
+ ListBase listb={0, 0};
+ short x1,y1;
+ short mval[2], ret=0;
+
+ if(min>max) min= max;
+
+ getmouseco_sc(mval);
+
+ if(mval[0]<150) mval[0]=150;
+ if(mval[1]<30) mval[1]=30;
+ if(mval[0]>G.curscreen->sizex) mval[0]= G.curscreen->sizex-10;
+ if(mval[1]>G.curscreen->sizey) mval[1]= G.curscreen->sizey-10;
+
+ block= uiNewBlock(&listb, "button", UI_EMBOSSX, UI_HELV, G.curscreen->mainwin);
+ uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_RET_1);
+
+ x1=mval[0]-150;
+ y1=mval[1]-20;
+
+ uiDefButS(block, NUM, 0, str, (short)(x1+5),(short)(y1+10),125,20, var,(float)min,(float)max, 0, 0, "");
+ uiDefBut(block, BUT, 1, "OK", (short)(x1+136),(short)(y1+10),25,20, NULL, 0, 0, 0, 0, "");
+
+ uiBoundsBlock(block, 5);
+
+ ret= uiDoBlocks(&listb, 0);
+
+ if(ret==UI_RETURN_OK) return 1;
+ return 0;
+}
+
+short sbutton(char *var, float min, float max, char *str)
+{
+ uiBlock *block;
+ ListBase listb={0, 0};
+ short x1,y1;
+ short mval[2], ret=0;
+
+ if(min>max) min= max;
+
+ getmouseco_sc(mval);
+
+ if(mval[0]<150) mval[0]=150;
+ if(mval[1]<30) mval[1]=30;
+ if(mval[0]>G.curscreen->sizex) mval[0]= G.curscreen->sizex-10;
+ if(mval[1]>G.curscreen->sizey) mval[1]= G.curscreen->sizey-10;
+
+ block= uiNewBlock(&listb, "button", UI_EMBOSSX, UI_HELV, G.curscreen->mainwin);
+ uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_RET_1);
+
+ x1=mval[0]-150;
+ y1=mval[1]-20;
+
+ uiDefButC(block, TEX, 0, str, x1+5,y1+10,125,20, var,(float)min,(float)max, 0, 0, "");
+ uiDefBut(block, BUT, 1, "OK", x1+136,y1+10,25,20, NULL, 0, 0, 0, 0, "");
+
+ uiBoundsBlock(block, 5);
+
+ ret= uiDoBlocks(&listb, 0);
+
+ if(ret==UI_RETURN_OK) return 1;
+ return 0;
+}
+
+short fbutton(float *var, float min, float max, char *str)
+{
+ uiBlock *block;
+ ListBase listb={0, 0};
+ short x1,y1;
+ short mval[2], ret=0;
+
+ if(min>max) min= max;
+
+ getmouseco_sc(mval);
+
+ if(mval[0]<150) mval[0]=150;
+ if(mval[1]<30) mval[1]=30;
+ if(mval[0]>G.curscreen->sizex) mval[0]= G.curscreen->sizex-10;
+ if(mval[1]>G.curscreen->sizey) mval[1]= G.curscreen->sizey-10;
+
+ block= uiNewBlock(&listb, "button", UI_EMBOSSX, UI_HELV, G.curscreen->mainwin);
+ uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_RET_1);
+
+ x1=mval[0]-150;
+ y1=mval[1]-20;
+
+ uiDefButF(block, NUM, 0, str,(short)(x1+5),(short)(y1+10),125,20, var, min, max, 0, 0, "");
+ uiDefBut(block, BUT, 1, "OK",(short)(x1+136),(short)(y1+10), 35, 20, NULL, 0, 0, 0, 0, "");
+
+ uiBoundsBlock(block, 2);
+
+ ret= uiDoBlocks(&listb, 0);
+
+ if(ret==UI_RETURN_OK) return 1;
+ return 0;
+}
+
+int movetolayer_buts(unsigned int *lay)
+{
+ uiBlock *block;
+ ListBase listb={0, 0};
+ int dx, dy, a, x1, y1, sizex=160, sizey=30;
+ short pivot[2], mval[2], ret=0;
+
+ if(G.vd->localview) {
+ error("Not in localview ");
+ return ret;
+ }
+
+ getmouseco_sc(mval);
+
+ pivot[0]= CLAMPIS(mval[0], (sizex+10), G.curscreen->sizex-30);
+ pivot[1]= CLAMPIS(mval[1], (sizey/2)+10, G.curscreen->sizey-(sizey/2)-10);
+
+ if (pivot[0]!=mval[0] || pivot[1]!=mval[1])
+ warp_pointer(pivot[0], pivot[1]);
+
+ mywinset(G.curscreen->mainwin);
+
+ x1= pivot[0]-sizex+10;
+ y1= pivot[1]-sizey/2;
+
+ block= uiNewBlock(&listb, "button", UI_EMBOSSX, UI_HELV, G.curscreen->mainwin);
+ uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_NUMSELECT|UI_BLOCK_RET_1);
+
+ dx= (sizex-5)/12;
+ dy= sizey/2;
+
+ for(a=0; a<10; a++) {
+ uiDefButI(block, TOGR|BIT|a, 0, "",(short)(x1+a*dx),(short)(y1+dy),(short)dx,(short)dy, lay, 0, 0, 0, 0, "");
+ if(a==4) x1+= 5;
+ }
+ x1-= 5;
+
+ for(a=0; a<10; a++) {
+ uiDefButI(block, TOGR|BIT|(a+10), 0, "",(short)(x1+a*dx),(short)y1,(short)dx,(short)dy, lay, 0, 0, 0, 0, "");
+ if(a==4) x1+= 5;
+ }
+ x1-= 5;
+
+ uiDefBut(block, BUT, 1, "OK", (short)(x1+10*dx+10), (short)y1, (short)(3*dx), (short)(2*dy), NULL, 0, 0, 0, 0, "");
+
+ uiBoundsBlock(block, 2);
+
+ ret= uiDoBlocks(&listb, 0);
+
+ if(ret==UI_RETURN_OK) return 1;
+ return 0;
+}
+
+/* ********************** CLEVER_NUMBUTS ******************** */
+
+#define MAXNUMBUTS 24
+
+VarStruct numbuts[MAXNUMBUTS];
+void *numbpoin[MAXNUMBUTS];
+int numbdata[MAXNUMBUTS];
+
+void draw_numbuts_tip(char *str, int x1, int y1, int x2, int y2)
+{
+ static char *last=0; /* avoid ugly updates! */
+ int temp;
+
+ if(str==last) return;
+ last= str;
+ if(str==0) return;
+
+ glColor3ub(160, 160, 160); /* MGREY */
+ glRecti(x1+4, y2-36, x2-4, y2-16);
+
+ cpack(0x0);
+
+ temp= 0;
+ while( BMF_GetStringWidth(G.fonts, str+temp)>(x2 - x1-24)) temp++;
+ glRasterPos2i(x1+16, y2-30);
+ BMF_DrawString(G.fonts, str+temp);
+}
+
+int do_clever_numbuts(char *name, int tot, int winevent)
+{
+ ListBase listb= {NULL, NULL};
+ uiBlock *block;
+ VarStruct *varstr;
+ int a, sizex, sizey, x1, y2;
+ short mval[2], event;
+
+ if(tot<=0 || tot>MAXNUMBUTS) return 0;
+
+ getmouseco_sc(mval);
+
+ /* size */
+ sizex= 235;
+ sizey= 30+20*(tot+1);
+
+ /* midden */
+ if(mval[0]<sizex/2) mval[0]=sizex/2;
+ if(mval[1]<sizey/2) mval[1]=sizey/2;
+ if(mval[0]>G.curscreen->sizex -sizex/2) mval[0]= G.curscreen->sizex -sizex/2;
+ if(mval[1]>G.curscreen->sizey -sizey/2) mval[1]= G.curscreen->sizey -sizey/2;
+
+ mywinset(G.curscreen->mainwin);
+
+ x1= mval[0]-sizex/2;
+ y2= mval[1]+sizey/2;
+
+ block= uiNewBlock(&listb, "numbuts", UI_EMBOSSX, UI_HELV, G.curscreen->mainwin);
+ uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_RET_1|UI_BLOCK_ENTER_OK);
+
+ /* LET OP: TEX BUTTON UITZONDERING */
+ /* WAARSCHUWING: ALLEEN EEN ENKELE BITJES-BUTTON MOGELIJK: ER WORDT OP KOPIEDATA GEWERKT! */
+
+ uiDefBut(block, LABEL, 0, name, (short)(x1+15), (short)(y2-35), (short)(sizex-60), 19, 0, 1.0, 0.0, 0, 0, "");
+
+ if(name[0]=='A' && name[7]=='O') {
+ y2 -= 20;
+ uiDefBut(block, LABEL, 0, "Rotations in degrees!", (short)(x1+15), (short)(y2-35), (short)(sizex-60), 19, 0, 0.0, 0.0, 0, 0, "");
+ }
+
+ varstr= &numbuts[0];
+ for(a=0; a<tot; a++, varstr++) {
+ if(varstr->type==TEX) {
+ uiDefBut(block, TEX, 0, varstr->name,(short)(x1+15),(short)(y2-55-20*a),(short)(sizex-60), 19, numbpoin[a], varstr->min, varstr->max, 0, 0, varstr->tip);
+ }
+ else {
+ uiDefBut(block, varstr->type, 0, varstr->name,(short)(x1+15),(short)(y2-55-20*a), (short)(sizex-60), 19, &(numbdata[a]), varstr->min, varstr->max, 100, 0, varstr->tip);
+ }
+ }
+
+ uiDefBut(block, BUT, 4000, "OK", (short)(x1+sizex-40),(short)(y2-35-20*a), 25, (short)(sizey-50), 0, 0, 0, 0, 0, "OK: Assign Values");
+
+ uiBoundsBlock(block, 5);
+
+ event= uiDoBlocks(&listb, 0);
+
+ areawinset(curarea->win);
+
+ if(event & UI_RETURN_OK) {
+
+ varstr= &numbuts[0];
+ for(a=0; a<tot; a++, varstr++) {
+ if(varstr->type==TEX);
+ else if ELEM( (varstr->type & BUTPOIN), FLO, INT ) memcpy(numbpoin[a], numbdata+a, 4);
+ else if((varstr->type & BUTPOIN)==SHO ) *((short *)(numbpoin[a]))= *( (short *)(numbdata+a));
+
+ if( strncmp(varstr->name, "Rot", 3)==0 ) {
+ float *fp;
+
+ fp= numbpoin[a];
+ fp[0]= M_PI*fp[0]/180.0;
+ }
+ }
+
+ if(winevent) {
+ ScrArea *sa;
+
+ sa= G.curscreen->areabase.first;
+ while(sa) {
+ if(sa->spacetype==curarea->spacetype) addqueue(sa->win, winevent, 1);
+ sa= sa->next;
+ }
+ }
+
+ return 1;
+ }
+ return 0;
+}
+
+void add_numbut(int nr, int type, char *str, float min, float max, void *poin, char *tip)
+{
+ if(nr>=MAXNUMBUTS) return;
+
+ numbuts[nr].type= type;
+ strcpy(numbuts[nr].name, str);
+ numbuts[nr].min= min;
+ numbuts[nr].max= max;
+ if(tip) strcpy(numbuts[nr].tip, tip);
+
+ /* LET OP: TEX BUTTON UITZONDERING */
+
+ numbpoin[nr]= poin;
+
+ if ELEM( (type & BUTPOIN), FLO, INT ) memcpy(numbdata+nr, poin, 4);
+ if((type & BUTPOIN)==SHO ) *((short *)(numbdata+nr))= *( (short *)poin);
+
+ if( strncmp(numbuts[nr].name, "Rot", 3)==0 ) {
+ float *fp;
+
+ fp= (float *)(numbdata+nr);
+ fp[0]= 180.0*fp[0]/M_PI;
+ }
+
+}
+
+void clever_numbuts(void)
+{
+ Object *ob;
+ float lim;
+ char str[128];
+
+ if(curarea->spacetype==SPACE_VIEW3D) {
+ lim= 1000.0*MAX2(1.0, G.vd->grid);
+
+ if(G.obpose){
+ if (G.obpose->type == OB_ARMATURE) clever_numbuts_posearmature();
+ }
+ else if(G.obedit==0) {
+ ob= OBACT;
+ if(ob==0) return;
+
+ add_numbut(0, NUM|FLO, "LocX:", -lim, lim, ob->loc, 0);
+ add_numbut(1, NUM|FLO, "LocY:", -lim, lim, ob->loc+1, 0);
+ add_numbut(2, NUM|FLO, "LocZ:", -lim, lim, ob->loc+2, 0);
+
+ add_numbut(3, NUM|FLO, "RotX:", -10.0*lim, 10.0*lim, ob->rot, 0);
+ add_numbut(4, NUM|FLO, "RotY:", -10.0*lim, 10.0*lim, ob->rot+1, 0);
+ add_numbut(5, NUM|FLO, "RotZ:", -10.0*lim, 10.0*lim, ob->rot+2, 0);
+
+ add_numbut(6, NUM|FLO, "SizeX:", -lim, lim, ob->size, 0);
+ add_numbut(7, NUM|FLO, "SizeY:", -lim, lim, ob->size+1, 0);
+ add_numbut(8, NUM|FLO, "SizeZ:", -lim, lim, ob->size+2, 0);
+
+ sprintf(str, "Active Object: %s", ob->id.name+2);
+ do_clever_numbuts(str, 9, REDRAW);
+
+ }
+ else if(G.obedit->type==OB_MESH) clever_numbuts_mesh();
+ else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) clever_numbuts_curve();
+ else if (G.obedit->type==OB_ARMATURE) clever_numbuts_armature();
+ }
+ else if(curarea->spacetype==SPACE_NLA){
+ clever_numbuts_nla();
+ }
+ else if(curarea->spacetype==SPACE_IPO) {
+ clever_numbuts_ipo();
+ }
+ else if(curarea->spacetype==SPACE_SEQ) {
+ clever_numbuts_seq();
+ }
+ else if(curarea->spacetype==SPACE_IMAGE) {
+ clever_numbuts_sima();
+ }
+ else if(curarea->spacetype==SPACE_BUTS){
+ clever_numbuts_buts();
+ }
+
+
+}
+
+
+void replace_names_but(void)
+{
+ Image *ima= G.main->image.first;
+ short len, tot=0;
+ char old[64], new[64], temp[80];
+
+ strcpy(old, "/");
+ strcpy(new, "/");
+
+ add_numbut(0, TEX, "Old:", 0, 63, old, 0);
+ add_numbut(1, TEX, "New:", 0, 63, new, 0);
+
+ if (do_clever_numbuts("Replace image name", 2, REDRAW) ) {
+
+ len= strlen(old);
+
+ while(ima) {
+
+ if(strncmp(old, ima->name, len)==0) {
+
+ strcpy(temp, new);
+ strcat(temp, ima->name+len);
+ BLI_strncpy(ima->name, temp, sizeof(ima->name));
+
+ if(ima->ibuf) IMB_freeImBuf(ima->ibuf);
+ ima->ibuf= 0;
+ ima->ok= 1;
+
+ tot++;
+ }
+
+ ima= ima->id.next;
+ }
+
+ notice("Replaced %d names", tot);
+ }
+
+}
diff --git a/source/blender/src/unix_creator_splash.jpg.c b/source/blender/src/unix_creator_splash.jpg.c
new file mode 100644
index 00000000000..f9da6b88ea3
--- /dev/null
+++ b/source/blender/src/unix_creator_splash.jpg.c
@@ -0,0 +1,939 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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__)
+
+/* DataToC output of file <splash_jpg> */
+
+int datatoc_splash_jpg_size= 28762;
+char datatoc_splash_jpg[]= {
+255,216,255,224, 0, 16, 74, 70, 73, 70, 0, 1, 2, 0, 0,100, 0,100, 0, 0,255,236, 0, 17, 68,117,
+ 99,107,121, 0, 1, 0, 4, 0, 0, 0, 50, 0, 0,255,238, 0, 14, 65,100,111, 98,101, 0,100,192, 0, 0, 0, 1,255,219, 0,
+132, 0, 8, 6, 6, 6, 6, 6, 8, 6, 6, 8, 12, 8, 7, 8, 12, 14, 10, 8, 8, 10, 14, 16, 13, 13, 14, 13, 13, 16, 17, 12,
+ 14, 13, 13, 14, 12, 17, 15, 18, 19, 20, 19, 18, 15, 24, 24, 26, 26, 24, 24, 35, 34, 34, 34, 35, 39, 39, 39, 39, 39, 39, 39, 39,
+ 39, 39, 1, 9, 8, 8, 9, 10, 9, 11, 9, 9, 11, 14, 11, 13, 11, 14, 17, 14, 14, 14, 14, 17, 19, 13, 13, 14, 13, 13, 19, 24,
+ 17, 15, 15, 15, 15, 17, 24, 22, 23, 20, 20, 20, 23, 22, 26, 26, 24, 24, 26, 26, 33, 33, 32, 33, 33, 39, 39, 39, 39, 39, 39, 39,
+ 39, 39, 39,255,192, 0, 17, 8, 1, 15, 1,244, 3, 1, 34, 0, 2, 17, 1, 3, 17, 1,255,196, 0,192, 0, 0, 1, 5, 1, 1,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 2, 4, 5, 6, 7, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 16, 0, 2, 1, 3, 2, 4, 3, 4, 4, 9, 9, 4, 7, 5, 6, 7, 1, 2,
+ 3, 0, 17, 4, 18, 5, 33, 49, 19, 6, 65, 81, 20, 97,113, 34, 50,129,145,209, 7,161,193,225, 66, 82,146,178, 35, 21,177, 98,
+114,130, 51, 67,115, 36, 22,240,210, 99,131,162, 83,195,211, 52, 84, 54,147,163,179,196, 37,241,194,226,132, 69, 23, 68,100,116,
+148,164, 53, 38, 17, 0, 2, 1, 3, 2, 4, 3, 6, 4, 6, 3, 1, 0, 0, 0, 0, 0, 1, 2, 17, 3, 4, 33, 18, 49, 65, 81,
+ 5, 97,113, 19,129,145,161,209, 34, 50,177,193, 66,146,240,225, 82,114, 51, 20, 98,147, 21, 52,255,218, 0, 12, 3, 1, 0, 2,
+ 17, 3, 17, 0, 63, 0,246, 67, 44,170,177,170,200,202, 58,113,216, 2, 64,249, 22,165, 28,211, 27,222, 70, 63,214, 52, 39,252,
+207,240,227,253,133,169, 68, 56, 80, 19,146,105,195, 11, 72,214,183,233, 26,129,201,152, 31,237, 31,245,141, 41, 47,127,162,132,
+215,181,205, 8, 27,212, 77,107,137, 27,245,141, 64,207,144, 77,186,174, 63,172,126,218,130,222,215,183, 26,144, 31,150,128, 32,
+154,126, 70, 87,253, 99,246,211,117, 38,240,154, 79,214, 52,220, 41,112, 20, 3,153,114, 57,137, 95,245,141, 71,212,100,218,253,
+ 86,253, 99, 75,141,239,225, 81, 60, 61,212, 0,242, 50,178,148, 40,234,186,220,222,225,141, 9,179, 50,173, 97, 60,151,254,155,
+125,181, 12,182, 38, 69, 91,240, 2,227,233, 63,146,129,126, 23,168,202, 28,101,229,158,121, 18,126,187,125,181, 47, 87,149,111,
+237,228,253,118,251,104, 11,114, 44, 41,244,249,208, 19, 25,153,135,148,242,126,187,125,181, 33,149,152,120,122,137, 63, 93,190,
+218, 26, 0, 13, 45, 66,228,208, 22, 6, 78, 80, 3,247,242,126,187,125,180,155, 47, 36,127,127, 39,235, 31,182,171,150,189,173,
+ 72,113,226,104, 11, 17,230,207,168,234,157,199,149,216,253,180, 81,149, 59,114,157,173,231,172,253,180, 56, 87,224, 36,128, 69,
+207,217, 75,167, 17, 36,232, 28, 57,158, 21, 0, 83,149,144,160, 30,163,145,231,168,253,181, 33,149, 63,140,175,236,248,143,219,
+ 85, 66, 33, 54, 26,138,155,145,107,216, 91,221, 78,177, 48,184, 12,126,159, 42, 2,192,201,200, 34,253,103,227,225,168,253,180,
+189, 70, 79, 31,222,191,235, 31,182,171,105,113, 98,172, 8, 30,202,145, 50, 34,252, 74, 15,184,241,227,244, 80, 7,245, 19,219,
+251,103,253, 99,246,208, 95, 39, 33, 44, 76,242,126,187, 31,199, 80, 46,121,233, 35,219, 80, 36, 61,128, 22,183, 62, 21, 64, 83,
+153,145,109, 66,119, 2,215, 39, 83,125,181, 89,179,179, 29,137, 19,202, 7,128, 14,223,109, 54, 64, 32,168,252,211, 81, 69,176,
+ 44,220, 7, 59,249, 10,160, 55,172,203, 69,187,100, 72,124,134,182,226,126,186,143,173,205, 95,155, 34, 66, 79, 19,241,181,135,
+225,160, 25, 1, 96, 79, 46, 72, 42, 46, 25,141,193,176,243,160, 12,115, 51, 65,185,202,148, 15, 32,237,246,212,134,118, 91, 11,
+174, 68,191,174,223,109, 87, 26, 72,177,248,173, 76, 9,189,128,176,160, 14, 51, 51,175,241,100,200, 63,174,223,109, 55,175,204,
+ 71, 23,201,148,131,225,173,190,218, 4,128, 14, 36,212,161,143, 89,212,227,133, 1,115,215,229, 30, 2,121, 13,255, 0,158,223,
+109, 15,213,103,173,203,100, 75,199,144,234, 55,219, 72, 0, 13,192,166, 97,168,251,168, 8,182,110,127,132,242,254,187,125,180,
+227, 43,112, 97,127, 81, 42,255, 0, 93,190,218, 64, 0,220,254,138,137,148, 51,149, 81,192, 80, 5, 89,243, 56, 95, 38, 99,255,
+ 0, 49,128,254, 90,155,103,100, 71,192,228, 73,127,233,183,219, 84,220,189,248,181,133, 51,105,249,173,115, 64, 89,108,236,203,
+124, 51,200,111,252,246,251,106, 7, 63, 48, 45,142, 68,154,189,142,223,109, 7, 81, 43,199,129, 53, 16,128, 27,243, 52, 1,151,
+ 51, 56,113, 57, 50,253, 50, 55,219, 69,254, 33,150, 5,186,242, 19,230, 93,190,218,173, 74,213, 42, 90, 6,245,217,167,255, 0,
+226, 37,253,118,251,105,122,220,223,252,204,191,174,223,109, 6,254, 84,220,104, 11, 30,183, 51,255, 0, 51, 47,235,183,219, 75,
+214,230,255, 0,230, 37,253,118,251,104, 43, 27, 55,202,164,219,157,133, 19,211,184,249,172,190,210, 71,226,161, 73,122,204,223,
+252,204,191,174,223,109, 63,172,204,255, 0,204, 75,250,237,246,211, 8,163, 28,216,183,157,135,227, 53, 32,138,162,225, 56,255,
+ 0, 56,210,132,170, 23,172,205,255, 0,204, 75,250,237,246,212,214,125,193,141,132,210,253, 46,195,249, 77, 48, 45,127,132,219,
+149,244,139, 84,132,122,188, 73,243,189, 5, 73,137,178,193,179,229,184,243, 1,216,159,229,162, 12,153, 0, 7,175, 59,158,127,
+ 57, 0,255, 0, 45, 4, 71,241, 21, 35,219,122, 48,138,235,195,151, 35,237,160, 37,235,178, 84,133, 71, 97,115,249,204,205,251,
+ 70,153,178, 50,216,241,154, 65,238, 98, 7, 15,117, 38,232, 34,252,108,183,191,157, 66, 92,172,100, 85, 0,146, 0,240, 28,232,
+ 66, 67, 35, 36,139,137,228,229,250, 77,207,235,169,117,179, 47,110,172,150,225,115,169,190,218,164,251,154, 14, 17,197,244,147,
+ 80,245,243, 30, 54, 22,242,170, 83, 76,190, 85,174, 39,144,127, 92,253,180,199, 42, 72,200,213,146,223, 75,147,248,235, 22, 73,
+166,123,106,114,111,237,166,138, 22,119, 3,206,130,134,217,206, 22, 54,201,144,248,177, 5,141,135,226,168, 54,236,170, 56, 77,
+ 35, 27, 90,247, 35,241,214,119,167, 60,188,124,104,114,194, 69,128, 28,232, 13,143,226, 11,209,234,234,125, 93, 13, 90,238,111,
+110,190,142,124,233, 85, 45, 31,229,109,255, 0,242,182,255, 0,252,170, 85, 6,166,131,254,103,248,113,254,194,209, 20, 27, 90,
+160,220, 76,127,208,143,246, 22,138, 56, 85, 32, 25, 20,130, 56,248, 84, 13,207,133,237, 68,152,141, 67,221, 67, 13, 66, 14, 9,
+229, 76,172,215, 55,229, 78, 8,164,109,202,244, 4,129,164, 77, 55, 0, 56,210,184,160, 28, 48, 96, 64,240,168, 53,185, 83,222,
+222, 21, 18, 13,232, 10, 51, 13, 83, 48, 7,217,245, 10, 96,162,244,139, 93,203,121,241,166,185,250,234, 20, 37,192, 53, 2,196,
+210, 28,233,207,133, 0,128, 52,136,225, 75, 87,133, 49,185, 52, 2, 98,168, 9, 60, 0, 28,107, 22, 77,246, 93,127,185,141,116,
+ 14, 90,174, 73,250,136,173,189, 0,131,126, 53,135,159,180, 52,122,167,197, 26,147,155, 71,226, 61,222,202,249,253,201,229, 43,
+113,150, 51,105, 70,174,116,251,188, 61,135,187, 1, 99, 57,184,228, 42,185, 81, 70,191,105,181,182,110,184,185, 81,136,207,193,
+ 48,185,100, 60,111,253, 27, 85,177, 36,102,230,224, 31,111, 10,225, 85,153, 24, 50,146,172, 56,130, 56, 16,107,123, 3,121, 18,
+ 21,135, 44,128,246,210,178,242, 7,250, 94,218,225,133,221, 35,114,150,242, 26,140,184, 41,112,140,188,250, 51,182,103,109,112,
+173,203, 21,148,121,199,156,124,186,163,105, 26,224,105,112, 1, 55, 60,124, 61,148,101,110, 60,207, 42, 8,143, 85,135, 2, 45,
+240,154,136, 81, 96,120, 11, 27,112,225,192,251,171,235, 31, 44, 63,194, 79, 3,196,241,166,147,243,124, 8, 60,126,138, 75, 24,
+230, 24,170,158, 39,141,237,244, 84, 25, 13,238,206, 79,180,129,227, 64, 73,136, 60,121, 83, 16, 13,200,229, 80, 34, 91,243, 7,
+232,169, 47, 1,118,230,121,213, 64, 20,202, 88,173,248,216,218,213, 94, 73, 3,157, 63,152,167,137,243, 52,249, 19,107, 98,171,
+200,112,189, 1,152, 11,105, 21, 65, 55,212,126, 81, 76, 56,139, 22,247,211, 6,118, 91, 90,146,196,121,147,245, 80, 13,173, 84,
+217, 71,190,157,131, 63,202, 44, 42, 65, 66,241,254, 90,125,106, 77,135, 19, 64, 67,163,113,114,111, 68, 67,111,162,161,169,239,
+199,128,166, 96,191, 49,250,168, 3,222,226,152,115,227,194,133,114, 87,128, 32,211,171, 89,120,243,160, 38,206,161,180,142, 36,
+243, 52, 50, 72, 54, 31, 8,164, 73, 39,202,144, 70,110, 64,154, 84,180, 25,136,111, 11,211,241,162,172, 12,126,102, 85,247,159,
+178,245, 53,134, 33,109, 76,205,127, 5, 22,252, 38,160, 43,210,226,120, 14, 53,100, 34,143,149, 1,183,139, 27,253,130,156, 6,
+ 60, 20,219,196,128, 45, 65, 80, 2, 41, 15,133,189,252, 63,150,164,176,175,231, 56, 30,238, 38,140, 18,254, 28,111, 98, 77, 16,
+ 68, 0, 55,225,106,162,160, 82, 56,135,230,179, 31,105,176, 63,142,136, 44,132,104,141, 86,198,230,227, 81, 31, 75, 94,164, 12,
+ 42, 6,183, 23,246,154,139,102, 98,198, 44, 46,199,194,194,160, 36,194, 70,248,152,146,181, 14,159,144,231,202,245, 19,184, 6,
+ 0, 36,124, 7,153,170,242,230,206,120, 11, 47,184, 85, 33,116, 66, 72,227,244,210,126,146, 11,187,143,109,205,103,135,154, 65,
+114,196,253, 53, 6,141,139, 88,248, 80,180, 47,140,140,116, 6,198,254,225, 80,125,192, 45,130, 71,245,208, 98,135,224,213, 79,
+ 36, 26,108,222, 28,168, 6,245,147,181,200,178,251,168,114, 75, 59,252,206, 79,211, 83, 8, 17,110,124,120,213,136,162, 89,192,
+ 85,176,241, 38,161,170,104, 82, 72,216,176,246,213,159, 76,126,190, 53,100,194, 49,238,206, 65,225,194,213, 88,101, 93,249,112,
+228, 42,153, 43,152,237,194,220,104,226, 61, 42, 1,171, 3, 77,245,145,241, 30, 32,213, 73,139, 51,149, 28,133, 67, 75, 77, 67,
+ 8, 58,150, 43,225, 86, 18, 22,128,221,184, 55,128,246, 80,112,216,131,165,188, 42,212,236, 76,108,192, 88,208,141,213,212,174,
+243,194,135, 72,107, 31,101, 69,204,110, 0, 13,123,254,117, 85,100, 0, 95,196,212,161, 4, 95,202,140, 71,142,166,135, 75,252,
+175,204, 45,233,173,227,255, 0,153,189, 42,157,135,166,211,225,233,255, 0,249,138, 85, 13,233,241, 44,143,154, 59,248, 71, 31,
+236, 45, 18,226,153, 22,250, 79,252, 56,255, 0, 97,106,102, 32,124, 43, 71, 34,188,214,212, 61,212, 3, 86, 38,138,237,244, 80,
+ 76, 70,212, 33, 16,105,245,120,211, 24, 72,241, 53, 33, 23, 14,116, 3, 95,198,244,181,120,211,136, 72,241,164, 81,173,194,128,
+107,154,119, 98, 17,136, 60, 64, 36,125, 84,214, 97,225, 66,154,253, 50, 60,237,106, 2,184,224, 41,137, 23,247, 82,211,231, 78,
+ 5, 66,141,198,168, 79,187,226, 68,250, 6,169, 72,230, 86,214,250,205, 95,149,117,163, 32, 54, 44, 10,131,229,113, 92,203,237,
+217,145,177, 83, 17, 54,241, 94, 34,190,127,112,200,201,180,160,177,224,222,234,214, 73,110,167,129,238,193,177,143,117,203,215,
+157, 41, 74, 70,187,107,226,105,141,247, 28,127,116,255, 0,130,159,248,238, 63,253, 83,254, 10,201,244, 25,159,245, 15,245, 82,
+ 56, 57, 96, 18, 97, 96, 7, 18, 72,229, 95, 51,253,254,227,253, 47,254,191,228,125, 15,244,176, 63,169,126,255, 0,230,107,255,
+ 0, 30,130,223,217, 63,224,166, 27,252, 35,251,167,252, 21,131, 74,185,255, 0,235,101,255, 0, 82,253,168,233,255, 0,153,139,
+253, 47,247, 50,230,108,248,153, 7,169, 4, 77, 20,159,157,203, 73,246,251,234,157, 88,199,193,204,202,255, 0,195, 99,201, 40,
+243, 69, 36,125, 98,142,251, 46,237, 26,234,124, 41,128,243, 8, 79,242, 87,150,106,237,214,238,250,111, 93, 91,140,105, 31,129,
+233,131,181,105, 43,123,214,156, 20,165, 87,241, 11,182,239, 50,225,145, 20,215,146, 14, 67,244,151,221, 93, 20, 89, 80, 76,169,
+ 36,110, 25, 15, 27,215, 20,202,202, 74,176, 42,195,129, 7,129, 21, 99, 11, 58,124, 25, 53,196,110,167,230,140,252,166,189,184,
+ 93,206,118,105,110,245,101, 14, 21,253, 81,249,163,199,153,219,161,118,183, 45, 82, 51,227, 79,211, 47,230,118,183,140,252,173,
+123,212, 69,175,196,251,135,133, 3, 11, 51, 27,113,139,169, 24,248,199,207, 25,181,212,209,210, 40,155, 87,195,106,253, 12, 39,
+ 25,197, 78, 13, 74, 47, 84,209,240,167, 9, 66, 78, 19, 78, 45,113, 76,123, 17,196, 26,167, 60,167,140,106,127,164,107, 51,112,
+238,222,222,218,183, 70,218,179,231,147, 30,100, 10,218,217, 88,199,103, 26,135, 21,213,248, 69, 88,199,204,195,207, 86,159, 7,
+ 33, 50, 33, 44, 64,146, 54, 12, 56,120,112,241,174,190,156,210, 82,113,105, 61, 83,166,135, 40,220,132,155,140,100,155, 92, 85,
+117, 94,192,129, 84,240, 60,106, 93, 52, 94, 52,246, 35,143, 0, 42, 12, 67, 31, 96,229, 80,216,236,234,163,206,145,102, 43,240,
+240,243,160,205, 52, 80, 33,154,119, 88,163, 95,154, 71, 33, 84, 95,135, 51, 85,227,221,118,217, 92, 69, 14,108, 18, 72,230,202,
+139, 42, 49, 39,200, 0,111, 85, 38,245, 73,145,180,157, 27, 72,182, 45,201,154,230,151, 16,108,171, 97,226,105,128,241, 28,232,
+168,186,172, 88,123,133, 66,144, 96, 26,220, 79,184, 84,214, 57, 72,176, 75,123,255, 0, 45, 29, 85,185, 14, 22,169,232, 60, 9,
+ 54,160, 43,116, 79,231, 48,254, 90,113, 26, 15,109, 21,204, 75,114, 88, 90,161,215,132,114,187, 80, 8, 40, 6,192,123,168,129,
+ 9, 31,203, 85,253, 93,219,225, 90,140,153, 51,242, 83,167,221, 64, 92,142, 62, 23,229,195,232,167,253,202,233,212,226,254,250,
+206, 38, 86, 6,236, 77, 74, 40, 73, 60,121, 84, 43, 45,190, 86, 50,147,205,143,128, 3,237,168, 28,209,205, 19,143,133,232, 18,
+ 67, 98, 44, 47,126, 85, 9,230,197,194,136,205,153, 50, 67, 18,124,210, 72,193, 84,120,115, 53,124, 16, 92,219,209, 46,161, 61,
+ 94, 68,134,192,216,123, 5, 52,166, 98, 46,204, 77, 99,225,247,119,111,207,184,195,182, 98,100, 28,137,230, 37, 85,163, 67,160,
+ 16, 11, 27,187,105,240, 30, 21,188,206,146, 2, 1,171, 56,202, 52,223, 23, 26,170,235,161,152, 78, 19,174,201, 41, 81,211, 71,
+ 82,162, 33, 36,212,218, 18, 8,189, 77,237, 24, 26,120,154, 36,110, 28, 93,150,252,107, 38,221, 22,132, 99,137, 85, 56,248,158,
+ 20,165,140,150,224, 47,194,163, 51,187, 53,129,176, 28,109, 82, 71, 61, 62, 60,239, 70, 34,170,197,113, 18,233, 60,232,202,136,
+227, 81, 54,247, 85,102, 82,206, 73,240,163, 70,116, 32,225, 64,223, 34, 18,200,200, 66,175, 33,203,221, 68,138, 70,117,185,240,
+225,106,140,202,215,189,185,242,167,141, 25, 69,173,239,163, 44,122,178, 19,130,196, 1,192, 26,150, 61,208,176,246,126, 58, 56,
+135,169,236, 35,145, 52, 97, 10, 34,128, 88, 22,183, 26, 34, 73,213,129,158,230, 50, 7, 30, 21, 76, 38,162, 0,173, 5, 88,199,
+ 6,107,147,194,162, 68, 41,193, 23,159,141, 8, 5,143,230,223,143, 42, 71, 29,205,221, 69,193,242,162,248,240, 94, 60,233,195,
+203, 99, 99,111,203, 64,216,209,167, 73, 77,248,177,169,135, 12,182, 32,123,141, 67, 75, 95,226, 54,185,181,233,116,195, 29, 55,
+189,207, 58,180, 37, 65, 54, 48, 36,126,241,109,227,115,202,138, 32,141, 80, 1, 42,223,196,241,227, 72,198,131,133,206,190, 76,
+ 60, 61,149, 49, 2,233, 23, 35,135, 19, 80,181, 15,165,125, 61,186,131,255, 0, 15,107,216,242,235,243,165, 74,195,211,223, 65,
+183,167,183,254,255, 0,253,141, 42, 10,151,163, 0, 34, 31, 52,143,246, 22,164,196, 84, 7, 4, 75,255, 0,213,167,236,138,112,
+ 65, 23,170,100, 12,164,131,244, 80,239,122,124,134,248,199,135, 10, 21,237, 64, 19,133, 56, 32, 80, 67, 3,227, 83,189, 1, 45,
+ 64,251, 41, 84, 41,193, 2,128,127, 27,145, 85,242,152,104, 10, 60,239,245, 81,153,170,158, 73, 37,213,124, 45, 70, 16, 32, 77,
+172, 41, 11,158, 52,227,128,167, 4, 1, 80,163, 91,198,154,215,106,123,155, 85, 44,204,248,176,198,155,235,152,242, 65,225,253,
+ 42,231,118,236, 45, 65,206,228,148, 98,185,179,118,237,206,228,148, 45,197,201,190, 72,181, 54, 68, 56,177,235,149,172, 60, 7,
+137,246, 1, 92,246,110,227, 46, 89, 42, 62, 8,175,193, 7,143,244,170,188,249, 18,228,191, 82, 86,185,240, 30, 0,123, 40, 85,
+249,220,222,229, 59,245,133,186,194,223, 78,114,254,239,145,247,176,251,124, 44,210,115,164,231,240,143,151,204, 85,218,236, 61,
+169, 18,198,153,155,162,107,145,172,201,142,126, 85, 30, 26,252,207,178,176,251, 95, 9, 51,119,120,132,130,241,194, 12,204, 60,
+244,219, 79,253, 34, 43,161,251,192,238, 41,123,107,182,178, 51,113, 72, 25,115, 50,227,226,177,252,215,146,255, 0, 31,245, 85,
+ 73, 30,218,245,118,108, 8,222,126,172,210,151,213,182, 17,124, 43,206, 76,243,119,108,231,102, 46,220, 91,141, 35,186,109,113,
+167, 68, 79,125,239,126,216,237,114, 49,179,114, 71,168, 81,195, 19, 29,117,186,143,231, 42,240, 95,235, 17, 88, 56,255, 0,124,
+189,165, 52,154, 37,143, 47, 29,111,253,164,145, 41, 95,167,166,238,223,130,188, 22, 89,100,154, 71,154,103,105, 37,144,150,119,
+ 98, 75, 51, 30, 36,146,121,147, 80,175,217,199,183,218, 81,164,155,111,170,211,220,143,199, 79,185, 94,114,172, 84, 82,232,245,
+247,179,234,126,150,195,221, 88, 67, 43, 26, 72,242,162,126, 17,229, 66, 70,165, 62, 87,230, 8,253, 22,174, 23,119,218,103,218,
+ 50,140, 18,252, 72,223, 20, 82,142, 76,191,104,241,175, 61,251,191,238,124,174,220,223,241,173, 33,244, 57,146, 36, 25,144,147,
+240,149,115,164, 73,111,210, 66,111,127,162,189,239,186,112,151, 47,104,149,237,251,204,127,222,161,247,124,195,245,107,243,253,
+239,181, 65, 70, 83,138,250,146,114, 82, 90, 57, 37,198, 50, 63, 65,217,187,164,164,227, 9,125,173,168,202, 60, 84, 91,225, 40,
+158,125,135,149, 38, 28,235, 60,103,151,204,190, 12, 60, 65,174,211, 27, 38, 57, 98, 89,149,134,153, 62, 32, 79, 10,225, 43,165,
+237,217,217,241,228,128,255, 0,116,193,151,220,223,148, 87,199,236,249, 14, 55, 93,134,254,153,166,215,132,151,205, 31, 87,186,
+216, 82,182,175, 37,245, 65,164,252, 98,254, 76,242,175,188,162, 15,117,228, 21, 32,142,148, 60, 71,244, 5,116,191,119,217,152,
+152, 61,183, 52,249,115, 36, 17,174, 75,221,228, 96,163,228, 79, 19, 92,215,222, 80,183,117,228, 15,248, 80,254,192,172, 61,171,
+107,220,247,201, 6, 14, 16, 46,145,221,219, 83, 90, 56,245, 88, 22, 62,251,123,235,247, 62,156,110, 98, 91,140,165,181, 40,197,
+183,224,145,248,133,118, 86,243, 46, 74, 49,223, 39, 41, 36,188, 91, 61, 94, 78,247,237,130,253, 51,184, 15,105, 17,200, 87,235,
+ 9,106,211,193,220,182,237,205, 11,224,100, 71,144, 23,152, 70, 4,143,120,230, 43,206, 37,251,181,222, 22, 3, 36, 57, 16, 77,
+ 32, 23,233, 2,202, 79,176, 22, 22,250,235,149, 73, 51,246,124,210, 81,159, 23, 51, 29,136, 54,248, 89, 88,115, 6,184,172, 75,
+ 23, 19,244,110,182,215, 95,225, 30,135,155,145,105,175, 94,210, 73,244,211,230,122,207,123, 2, 59,103, 63, 87,148,124, 63,230,
+165,121,159,106,255, 0,234, 45,186,223,245,195,241,215,107,184,111, 75,191,118, 30, 94, 99, 0,185, 41,211,139, 37, 71, 32,226,
+ 72,248,129,228,192,222,184,190,212, 23,238, 45,184,127,198, 31,200,107,166, 52, 92,113,239, 70, 90, 52,228,159,237, 57,229, 78,
+ 51,201,177, 56,186,169, 40, 53,251,143,108,186,170,150,119, 10,170, 46,196,144, 0, 3,204,154,195,204,239,206,220,193,144,198,
+ 50,122,238, 56, 30,138,151, 3,250,223, 47,225,174, 43,191, 59,134,124,156,233, 54,108,103, 41,137,140,116,206, 1,183, 82, 65,
+207, 87,177,121, 91,206,170,246,175,103, 54,255, 0, 19,230,100,204,113,240,209,186,106, 84, 93,221,128,185,211,126, 0, 11,243,
+174, 16,196,183, 27,106,237,249, 56,167,170, 75,199,129,222,230,101,201, 93,118,113,226,164,214,141,191, 14, 39,109, 31,222, 54,
+197, 51,233, 51, 73, 8, 60, 53, 60,102,223,244,117, 86,238, 54,116, 59,140, 98,124, 60,133,158, 35,249,241,176, 97,127, 35,106,
+225,247,127,187,104, 97,197,121,246,172,153, 30,100, 5,132, 19,105, 58,236, 47,101,101, 11, 99,229,194,184,253,135,124,203,216,
+115,211, 46, 6, 38, 59,129,145, 13,254, 23, 79, 16, 71,159,145,240,170,177,108,221,131,150, 60,157, 87, 41, 7,151,126,204,212,
+ 50, 96,169, 47,213, 19,220, 94, 59, 45, 48, 84, 68, 37,200, 0, 2, 73, 60, 0, 2,188,223,239, 15, 62, 71,147,108,155, 26,103,
+ 88,230,133,228, 82,140, 86,225,138,144,120,123, 43,151,219,155,123,221, 36, 59, 78, 20,178,202,114,136,234, 70, 92,216,132,185,
+187,146,120, 40,191, 26,197,188, 39, 59,106,227,154,138,124,106,184, 81,234,110,230,122,133,215,105, 91,114,107,133, 31, 26,173,
+ 52, 61, 79, 35,189, 59,103, 6, 83, 19,230, 9, 92,112, 61, 21,105, 0,254,178,141, 63,134,173,237,221,205,176,111, 14, 35,194,
+204, 83, 49,229, 12,128,198,231,250, 33,192,191,209, 92, 43,125,216,238,171, 14,191, 89, 1,150,223,217,217,237,127, 45, 86,252,
+ 85,198, 79, 6, 70, 14, 76,152,243, 3, 22, 68, 14, 85,135,138,178,159, 2, 43,172, 49, 49,174, 38,173,220,110, 75,248,224,113,
+158,110, 85,166,165,118,210, 81,124,191,157, 79,161, 32,117, 50,105, 97,116, 52, 45,211,113,193,219, 99, 15,145, 60,120,200,222,
+ 50, 48, 4,251,175,206,185,156, 14,229, 56,253,149, 30,255, 0,148, 58,153, 17,131, 2,131,253,228,193,138, 45,253,224,106, 53,
+229,185,185,219,134,245,156,114, 50,157,242, 50,167, 96,170, 57,241, 38,202,136,190, 3,200, 10,227, 99, 10, 83,148,183, 61,177,
+131,113,111,171, 93, 14,249, 25,241,132, 97,177,110,148,210,146, 93, 19,234,122,250,119,223,108, 2, 17,179,198,174, 87,233,201,
+111,175, 69,171, 47,188,179,112,247, 30,214,202,200,194,157, 50, 35,215, 16,213, 27, 6,183,239, 23,129,183, 42,231,113, 62,236,
+183,185,224, 18,228, 79, 6, 51,176,191, 73,139, 51, 15,233,104, 4,126, 26,193,222,118, 61,223,183, 36, 56,217,156, 33,200, 22,
+ 18, 68,196,197, 40, 83,127,103, 35,198,196, 87,123,120,248,254,164,125, 43,181,148, 90,116,122,214,157, 15, 61,220,172,175, 74,
+ 74,237,154, 70, 81,106,171, 74, 87,175, 16,221,155,255, 0,169,182,255, 0,233,183,255, 0, 13,171,218, 1, 72,149,230,145,130,
+ 70,162,236,236,108,160, 15, 50,107,198, 59, 43,255, 0, 84,237,188, 47,241,183, 15,249,109, 90,125,251,220,147,238, 27,140,187,
+ 78, 59,116,240, 48,219, 67, 34,155,117, 37, 95,153,159,207, 73,224, 5, 92,171, 18,189,145, 24,167, 68,161, 86,252, 42,204,226,
+100, 70,198, 52,230,213, 91,157, 18,234,232,142,207, 55,190,123,111, 22, 66,158,168,206,194,247,232,161,113,250,220, 20,253, 6,
+161,139,247,131,219, 50, 48, 71,154, 72,117, 31,154, 72,205,133,255, 0,161,170,184,254,209,236, 86,238, 28,118,220, 51, 39, 56,
+216, 97,138, 71,160, 2,242, 21,249,136, 45,192, 11,240,173,125,247,238,198, 44, 92, 41,114,246,140,153, 36,146, 21, 46,113,230,
+ 10, 75,128, 46, 66,178, 5,227,229,194,185,187, 56,113,151,167, 41,203,119, 6,249, 87,220,117, 87,243,167, 31, 86, 48,134,222,
+ 41,115,107,222,119,216,242,226,238, 17, 46, 86, 20,241,207, 11,114,120,216, 48,191,209, 86, 12, 74, 56,106,225, 94, 19,219, 93,
+193,147,219,251,140,121, 40, 75, 99, 49, 11,149, 5,248, 58,120,240,253, 33,224,107,167,251,204,202,149, 55, 44, 9, 49,102,116,
+138, 92, 80,234, 81,138,134, 5,218,205,195,217, 88,150, 11, 87,163,111,118,146, 77,169, 83,167, 35,112,238, 9,217,149,205,191,
+ 84, 90, 78, 53,235,205, 51,211, 50, 50,112,241, 49,218,124,151, 88,161,140, 93,229,114, 20, 1,237, 38,176,240,123,207, 97,221,
+ 55, 20,219, 48, 93,228,154, 66,221, 54,208, 66, 29, 10, 92,241,107, 30, 75,229, 94, 67,132,155,206,245, 42,109, 56,143, 46, 75,
+ 76,193,196, 37,201, 91,168, 63, 27,106, 54, 0, 3,204,215,160,246,199,221,254,227,178,110,248,187,166,110, 94, 57, 88, 67,235,
+134, 50,204,223, 28,109, 31, 3,164, 14, 5,171, 83,197,179,106, 18,245, 46, 86, 84,110, 41,105,228,102,222,101,235,211,143,167,
+110,144,170, 83,111, 95, 61,116, 59,237, 82, 95,135,251, 90,164, 21,207,143,151,225,167, 89, 49,215,135, 82,246,231, 97,122, 94,
+163, 29, 15, 5,102,252, 21,225, 62,128,180,147,113,171,226, 30, 20,226, 62, 31, 23, 51, 96, 13, 67,213, 0, 78,152,199,210,105,
+122,201,185, 40, 85, 30,234,133, 12, 33, 55, 12, 5,207, 48, 40,166, 2, 5,244,155,145,207,194,169, 28,172,131,253,225, 3,200,
+112,160,201, 36,172, 9, 46, 79,211, 66, 26, 38, 38,183,198,202, 7, 1,123,142, 66,163,254, 93, 78,166,148, 27,120, 10,205, 13,
+195,143, 62, 20, 80, 56, 80, 23, 12,248,160,113, 37,207,186,132,114,224, 65,240,196, 77,188,205, 86,123, 0,125,148, 34,218,191,
+ 5, 90,130,240,205, 65,109, 48, 1,239, 98,105,206,107, 19,113, 18, 2,124,120,159,199, 84, 75, 16,120, 11,220, 88, 84,212,240,
+ 23,231,227, 80, 26,190,166, 79, 79,125, 43,253,134,171, 91,133,253, 70,159, 58, 84, 27,255, 0,150,255, 0,242,223,252,205, 42,
+ 3, 80,142, 9,253, 4,253,145, 74,145, 63, 39,244, 19,246, 69, 43,213, 33, 95, 35,230, 23,242,160, 17,126, 20,105,219,227, 3,
+217, 67, 23,191, 1, 64, 64, 42,169, 62,102,165,164,248, 26,144,181, 53,184,208, 12, 1,177, 6,155, 65, 6,247,231,225, 69, 2,
+244,228, 80, 2,227,227, 84,166, 26,165, 98, 57,125,130,175,176,181,103, 23, 5,139,121,241,181, 25, 80,225, 71, 35, 82, 32, 15,
+ 96, 21, 16,213,129,186,231,201, 36,175,140,135, 76,104,116,181,191, 56,142,119,175, 46, 94, 84, 49,173,239,146,171,110,145, 75,
+155, 61, 24,216,211,200,185,178, 58, 37,171,111,146, 44,103,238,225,111, 22, 33,185,228,101,240, 31,209,172, 82, 75, 18,204,110,
+ 79, 18, 79, 58,106,209,219,246,169, 50,136,150, 91,164, 62, 30,109,238,175,206,206,230, 78,117,228,190,231,202, 43,237,138,254,
+ 57,159,122, 48,199,195,180,223, 5,206, 79,238,147, 43, 99, 97,203,149,168,160,180,104, 9,103, 60,133,170,189,118, 75, 12,113,
+199,209, 69, 10,150,176, 3,219, 92,132,177,152,164,120,219,154, 18,167,232,174,153,216, 43, 26, 22,181,220,229, 93,207,149,116,
+162, 71, 60, 60,199,145, 59,186,109, 81,166,213,206,154,213,179,161,236,169, 85, 55, 89, 35, 60,228,133,130,251,193, 86,254, 65,
+ 82,251,220,219, 39,220, 59, 73,166,129, 75,182, 12,233,146,234, 57,244,192,104,220,253, 26,239, 88, 24,121, 82,224,229, 69,151,
+ 15,207, 19, 6, 30,223, 48,125,226,189, 63, 7, 59, 19,118,195, 19, 69,103,142, 65,166, 88,154,198,196,143,137, 28, 87,211,236,
+ 89, 81,140,125, 63,213,110, 91,146,235, 22,124,238,245,138,230,220,191, 77,200,237,111,164,145,242, 93, 42,246,142,229,251,154,
+139, 38,119,203,237,188,148,198, 14, 75, 28, 44,139,244,212,159,250,183, 80,196, 15, 97, 7,223, 92,238, 63,220,207,116,201, 40,
+ 92,137,177, 32,143,198, 78,163, 57,183,177, 85, 43,246, 17,203,177, 40,215,122, 94, 15,137,248,249, 97,100, 70, 91,118, 55,226,
+184, 28,111,110,109,147,239, 27,238, 6,221,142,165,154,105,144, 49, 31,154,128,234,119, 63,209, 80, 77,125, 57,190,202,176,236,
+249,174,230,192,196,200, 61,238, 52, 15,194,107, 23,179,251, 19,106,237, 8,218, 72, 9,201,207,149,116,205,153, 32, 0,233,231,
+162, 53,227,165,106,143,119,111,113,229, 48,219,113, 91, 84,113,182,169,220,114, 44, 57, 40,247,120,215,196,239, 57,246,213,169,
+ 52,244,218,227, 10,241,148,164,125,222,205,129,113, 77, 39,197,201, 74,116,225, 24,196,229,107,107,183, 89,132,211,128, 9, 5,
+ 69,192,247,214, 45,116,125,185, 1, 88,101,156,143,237, 24, 42,251,151,242,154,252,167,108,139,150, 93,186,126,154,183,229, 67,
+244,221,198, 74, 56,183, 43,206,137,121,212,242,191,188,131,126,234,200, 54, 35,247, 80,243,254,128,174,147,238,209, 97, 27, 70,
+ 73, 81,121,155, 32,137, 15,142,144,139,167,249, 77,115,159,121, 60,123,175, 35,252, 56,191, 96, 86, 70,197,191,231,246,252,237,
+ 62, 40, 13, 20,195, 76,176,189,244,190,159,119,136,191, 58,254,132,237, 74,230, 28, 33, 30, 59, 98,252,232,126, 6, 55, 99,107,
+ 54,115,146,211,116,147,240,175, 51,219,129, 40,223,205, 53,228,255, 0,120,171, 8,238, 50, 98,182,182,130, 51, 53,191, 79,136,
+253,144, 43, 70,111,188,201,154, 43, 67,183,170,203,111,153,228, 44,160,255, 0, 68, 42,147,245,215, 25, 52,217,187,190,115, 75,
+ 38,172,140,188,151,228,162,229,152,240, 10,160,126, 10,231,135,141,114,220,220,238, 45,170,141,113, 58,230,229, 90,187,109, 91,
+182,247, 54,211,225,243, 54,246, 98,255, 0,233, 78,226, 31,221,143, 75,111,233,117, 56,213, 62,211,255, 0,212,155,111,248,195,
+241,215, 99,151,177, 29,135,176, 51, 96,154,222,170,110,156,217, 54,240, 99, 34, 0,159,213, 31,134,184,222,211,255, 0,212,155,
+111,248,195,249, 13,118,140,212,237,228, 74, 60, 27,151,194, 41, 28, 39, 9, 66,230, 52, 37,197, 40,215,219, 54,202,155,206,191,
+226,251,135, 83,231,245, 51,106,191,158,182,171,219,102,203,220,249,152,139, 62,215, 20,205,138,197,130,152,229, 10,183, 6,205,
+195, 88,173,174,254,237,201,241,115,164,222,113,144,190, 38, 73,213, 57, 2,253, 57, 57, 29, 94,198,231,127, 58,167,218,157,231,
+ 55,110,163,226, 75, 15,168,195,145,181,233, 7, 75,163, 17, 98, 86,252, 8, 54,229, 90,245, 37, 59, 17,157,149, 25, 58, 45, 31,
+197,121,153,118,227, 12,137, 66,251,148, 21, 95,212,190, 15,200, 97,219, 61,244,127,184,201, 63,243,199,253,229, 86, 61,145,221,
+ 92,206,220,255, 0,175, 31,251,245,209,238,255, 0,121,141, 62, 36,152,251, 78, 51,193, 44,160,169,200,149,133,208, 30, 23, 69,
+ 75,241,242, 55,171, 61,139,221, 59,238,229,146,187,110, 84, 39, 54, 5, 31, 30,105, 58, 90, 33,224,100,110, 77,252,181,203,212,
+202,141,183,113,194,220,105,197,112,116,247,157,125, 44, 73, 92, 86,213,203,146,175, 6,181, 85,247, 24, 29,225,141,147,135,183,
+236, 24,249,138, 83, 34, 60, 86, 73, 16,144, 72, 42,202, 0,225,127, 10,212,251,172,137, 27, 43,114,148,139,186,199, 26,169,242,
+ 12, 88,159,217, 21, 47,189, 96,163, 47,109,177,191,238,164,253,165,169,125,213, 50, 44,187,161,111,209,134,223, 92,149,153, 74,
+184, 46, 92, 43,175,190,102,163, 20,187,130,143, 26,105,175,132, 15, 72, 28,173,107,215,137,247,202,132,238,157,192, 1,111,137,
+ 9,247,152,210,245,237,162,120,193,176, 91,249,215,138,119,209, 13,221, 89,228, 11, 11,199,195,254, 82, 87, 14,221,254,105,127,
+ 99,252, 81,232,238,127,225,143,247,175,193,135,204, 50,255, 0,160,118,208, 9,233, 28,233,110, 60, 47,165,173,248,232,125,131,
+ 20, 18,247, 78, 18,207,107, 14,163, 71,127,211, 17,177, 90,233,118, 45,168,239,189,130,118,208, 66,201,214,146, 88, 24,248, 72,
+173,194,231,200,242,175, 62, 43,157,180,103, 13, 65,241,115,113, 92, 48,191, 6, 86, 83,112,107,217, 6,167, 27,246,147,164,183,
+ 77,126,238,103,134,226,118,229, 98,243, 85,142,216, 63,219,200,250, 47,162,223,163,107,120,154,228, 62,242, 98,135,253, 48,237,
+ 54,158,170,205, 17,135,136,190,162,108,109,253, 91,215, 51,141,247,161,148,176,133,204,193, 19, 74, 7,246,137, 33, 64, 79,153,
+ 82,175,252,181,206,119, 15,115,110, 29,198,234,103, 81, 22, 52, 63, 20,112, 71,114, 1, 60, 53, 49, 60,207,133,121, 44, 97,222,
+141,216,202, 75,106,139,173,107,198,135,179, 35, 54,196,172,202, 48,110, 78, 74,148,167, 10,245, 39,217, 36, 14,233,219, 75, 27,
+ 13,109,115,255, 0, 45,235, 31, 63, 87,174,201,215,243,245,100,213,126,119,212,111, 90,189,157,255, 0,169,118,255, 0,233,183,
+236, 53,105,247,207,110,228, 96,231,203,186,193, 25,108, 44,182,214,229, 71,246,114, 55,204, 27,216,199,136, 53,238,119, 35, 28,
+157,175, 77,208, 84,243, 77,232,120, 21,185, 75, 23,122,213, 66,227,175,147, 75, 83, 55,110,217,187,171, 43, 14, 57,246,212,156,
+226, 61,250,102, 57, 66,175, 2, 65,178,235, 30, 34,173,127,167,251,220,220,116,242, 79,159,239,199,253,229, 75,182, 59,206,109,
+134, 19,133, 60, 71, 35, 16,177,100, 10,108,232, 79,205,166,252, 8, 62, 85,163,188,125,226,190, 78, 43,227,109, 80, 62, 59, 74,
+ 10,182, 67,176,212,160,254,128, 95, 31,109,235,156,229,147,234, 56,198,220, 28,107,164,159, 79, 29, 78,176,142, 47,164,165, 43,
+183, 20,146,214, 43,175,134,134, 31,250, 47,185,207,255, 0,167,191,235,199,254,253, 93,239,100,202,137, 54, 56, 51, 65, 92,136,
+118,248,227,145, 73,185, 5, 9, 91, 92, 95,202,186, 30,200,238,109,251,116,155,208,228,192,114,225,140,124,121,163,225,100,242,
+ 14,121, 53,254,186,202,251,205,212,119, 76, 34,194,223,229,205,191, 93,171, 49,187,117,228,198,221,197, 31,165, 55,244,249, 26,
+149,171, 75, 22, 87,109, 57,253, 77, 38,165,224,203,191,117,184,241,150,220,114,200,253,234,136,226, 86,242, 86,212,205,245,149,
+ 21,232, 78,108,121,251,171,130,251,172, 70,120, 55, 61, 54,224,241, 94,254,231,175, 65, 56,199,243,156,125, 2,188, 57,191,253,
+ 19,246,126, 7,191, 6,139, 26, 30,223,197,130, 78, 28,124,205, 26,215,168, 34,120, 14, 53, 97, 99, 38,188,199,168, 22,154, 68,
+ 90,140,176,233, 26,126,154,118,138,224,128,104, 64, 58, 65, 91,138,131,139, 3, 86, 85, 2,173,175,202,129, 38,146, 56, 30, 38,
+247,161, 65, 44, 50,177, 4, 33,250,104,139, 20,173,228, 62,154, 34, 72, 20, 1,227,192, 1,239,166, 87, 9,241, 17,194,252,104,
+ 4, 49, 93,175,119, 3,232,164, 49, 71,139,159,160, 85,152,110, 80, 19,192,154,150,154, 16,173,233, 80,115,103,255, 0,111,162,
+159,211, 69,230,231,233,171, 36, 83, 90,128, 39, 66, 63, 77,107, 31,252, 61,175,126, 54,245, 26,169, 81,173,254, 95,217,209,255,
+ 0,182,165, 84, 6, 98,192,160,183,230, 39,236,138,125, 71,202,164,127, 52,255, 0, 49, 63,100, 84,117, 80, 21,231,249,193,177,
+229, 66, 50, 91,192,213,137, 79, 27,143, 42, 13,181, 30, 52, 4,117, 27,114,250,169,150, 66, 79, 17,106, 48, 22,247, 82,160, 35,
+170,194,159, 80, 62, 52,228, 14, 70,163,164, 2,111, 64, 66, 70,178,146,166,246, 4,253, 85, 72, 10,181, 56, 2, 38, 35,129,224,
+ 7,215, 85,116,155,115,168,202,132,109, 88,121,219, 84,239, 59,203, 5,157,100, 58,136,189,136, 39,159, 58,218, 35,198,151, 32,
+ 43,207,147,139,111, 34, 10, 23, 43,163,170,107, 70,142,248,249, 55, 44, 73,202,221, 53, 84,105,234,140,156, 45,160, 35,117, 50,
+172,196,114,140,113, 31,214,173,158, 32,112, 22,183, 42, 96, 56,209,121, 10,184,248,214,172, 71,101,168,211,171,124, 95,155, 37,
+252,139,151,165,186,227,175, 69,201,121, 32, 68,177,172, 77,227, 12,134,245, 72, 46, 15, 9, 63, 17,173,202,137, 10,192,134, 23,
+ 7,129, 6,166, 86, 60,114, 45, 74,220,180,230,159, 73,114,101,198,191, 43, 23, 85,200,235,201,174,171,161,199, 85,172, 29,195,
+ 47,110,155,173,137, 41,141,185, 48,230,172, 60,152, 30, 6,172,231,109, 79, 17, 50,227, 13,113,243, 41,226,191,104,172,202,252,
+189,219, 55,177,174, 82, 73,194, 75,132,151,227, 22,126,142,221,219, 89, 22,235, 26, 74, 47,138,127,131, 71,101,139,223, 35, 72,
+ 25,184,167, 87,139,196,120, 31,234,183,219, 86, 31,190, 48, 0,253,222, 52,204,222, 77,165, 71,215,118,174, 22,149,122, 35,221,
+115, 18,166,244,252, 92, 85, 78, 15,182,226,183, 93,141,120, 38,232,110,238,125,213,184,231,169,134, 59, 99, 66,220, 25, 99, 55,
+ 98, 60,139,253,149,133, 74,143,141,135, 62, 91,232,133,110, 60, 92,240, 81,239, 53,230,157,203,249, 23, 22,231, 43,146,122, 37,
+199,220,143, 68, 97,102,196, 30,213, 27,113, 90,183,243,100,113,177,228,202,153, 96,136, 93,152,243,240, 3,196,154,236, 97,137,
+177,160, 72, 34,182,148, 22, 30,103,204,208,176, 54,248,182,248,236,191, 20,140, 62, 57, 15, 51,236, 30,202,178, 79, 59,120,215,
+232, 59,118, 23,250,240,114,159,249, 39,199,254, 43,167,204,248, 89,249,158,188,148, 97,246, 67,135,252,159, 83, 3,119,237,189,
+159,114,202,245,121,216, 41, 38, 67,128, 26, 66,207,114, 20, 0, 57, 17, 85,135,107,108,103, 12,224, 54, 26,122,109, 70, 64,156,
+120, 57, 0, 22, 86, 39, 80,224, 60, 13,110,228,187, 7, 85, 2,246, 20, 3,241, 14,126,251, 87,213, 87, 46, 81, 45,242,162,225,
+171,208,249,222,149,186,183,178, 53,124,116, 90,156,179,125,222,246,216,125, 90, 38, 11,250, 34, 67,111,182,182,118,173,139,102,
+218, 62, 45,191, 21, 98,114, 44,101, 55,103, 35,250,111,115, 87,199,149,184,121,154, 99,240,158,100,251, 5, 89, 94,187, 37, 73,
+ 78, 77,116,108,145,177,106, 46,177,183, 20,250,164, 67, 51, 19, 19,113,199,124, 60,180, 19, 65, 37,181,198,110, 1,177, 12, 57,
+ 88,243, 21,159,139,218,189,191,135,147, 30, 86, 46, 10, 71, 52, 71, 84,110, 25,201, 7,207,139, 86,153,186,157, 67,135,157, 16,
+ 27,241,243,172,169,205, 42, 41, 52,159, 20,158,134,157,184, 73,169, 74, 41,181,193,181, 86, 59, 42,178,149,112, 25, 72,177, 83,
+196, 16,107,155,204,236,174,219,204,145,156,226,116, 88,243, 48,179, 32,253, 80,116,254, 10,233, 41,116, 46,111,126,124,105, 27,
+147,134,176,147,143,147,160,157,184, 79, 73,197, 75,205, 84,229, 35,236, 30,219,133,131, 52, 50, 75,111, 9, 36,107,127,209,211,
+ 93, 14, 22, 54, 46, 12, 35, 31, 14, 36,130, 37,228,136, 2,143,193, 87, 6, 58,158,102,156,197, 26,142, 34,147,187,114,127,124,
+165, 47, 54,102, 22,173,195,236,132, 99,228,140,189,199,101,218,119,102,141,247, 28,101,157,162, 4, 70, 88,176,176, 60,254, 82,
+ 41,182,253,155,107,218,122,135,109,198, 88, 12,182, 18, 21, 44,111,166,246,249,137,243,168,111,251,254, 23,110,225,250,156,132,
+ 50,203, 33, 43, 4, 10,108, 93,135, 62, 62, 0,120,154,226,225,238,238,243,222,157,206,207,134,189, 53, 60,122, 49,107, 11,236,
+103,144,145,122,155,231,183,110,231,183,165,116,247, 26,244,225,187,126,216,238,235, 77,125,231,162,160, 36,214,118,103,107,236,
+ 59,134, 75,229,230, 97, 44,185, 18,216,188,132,184, 39, 72, 10, 57, 48, 28,133,113,113,119,215,112,237, 25,131, 31,126,194, 86,
+228, 93, 10, 24,164,183, 45, 74,126, 83,245, 87, 77,220,189,210,216, 61,191,135,188,236,173, 28,131, 42,100, 64,100, 82,195, 67,
+ 36,140, 69,129, 22, 96,201, 99, 72,202, 81,117,139,113,126, 14,130, 81,140,149, 37, 21, 37,226,170,109,225,109,216,123, 94, 58,
+226,224,194, 33,128, 18, 68, 96,147,197,185,159,136,154, 14,235,177,237, 91,178,129,184, 98,164,197, 69,149,248,135, 3,216,203,
+ 99, 92, 64,251,201,207,109,177, 17, 32,142, 93,214, 73, 24, 92, 35, 8,210, 48, 6,159,134,228,179, 30, 62, 53,167,218,189,203,
+187,231, 54,224,119,214, 17,199,143, 26,200, 11, 71,210,210,191, 22,163,200,112,248,105,186, 73,238, 77,215,173,117,247,141,145,
+113,218,226,182,244,166,158,226,192,251,185,237,211,251,194, 37,183,232,117, 13,190,218,216,131,180,118, 8,176,223, 5, 49, 23,
+211,203, 99, 42,241,187,105, 55, 93, 79,125, 70,199,219, 92,118, 79,126,238,251,142, 96,193,237,204, 48,192,155, 70, 93, 75,200,
+224,126,118,144, 66,168,247,212,178, 55,207,188, 77,142, 47, 89,184,226,163, 99, 11,106, 44,145,186,129,203,226, 56,237,117,231,
+227, 91,119,174,202,149,156,157, 60, 76, 43, 22, 99, 93,182,226,171,167, 4,118, 24,157,161,219,216, 57, 9,149,139,132,177,207,
+ 17,186, 62,167,184, 36, 91,197,188,171, 93,177,160,145, 74, 60,106,200,194,204,172, 46, 8, 62, 96,214, 55,106,247, 86, 47,114,
+227,189,147,161,153, 13,186,240, 94,226,199,147,161,241, 95,228,172, 30,233,239,220,157,191,113,125,159,101,129,101,200,140,136,
+228,154, 64, 91,247,135,243, 35, 69, 34,228, 94,220,124,124, 43, 18,148,164,235, 41, 54,252, 93, 77, 70, 17,138,164, 98,162,159,
+ 36,168,107,229,246, 7,108,101,185,127, 71,208, 99,204,192,236,131,245,110, 87,240, 80,224,251,186,237,120, 92, 57,199,146,107,
+120, 73, 35, 17,245, 46,154,202, 51,125,233,170, 28,142,140, 68, 1,171,162, 4, 26,173,229,109, 87,252, 55,163,118,143,126,228,
+238,251,130,237, 27,172, 9, 30, 68,129,132, 51, 71,117, 5,144, 22, 40,232,196,216,144, 15, 27,251, 45, 93, 61,123,212,167,169,
+ 42,121,179, 31,235,217,173,125, 56, 87,201, 26,187,198,251,179,246,124, 56,184,173,138,233, 12,193,250, 49,226,162,105, 26, 52,
+234,213,169,147,244,170, 16, 98,108, 29,221,137,139,186,228, 97, 25, 67,171, 36, 38,107,171, 42,164,140,172, 8,141,237,204, 26,
+243,206,241,207,238, 28,233,113,198,251,137,233,150, 38,148, 98,158,155, 71,172, 18,154,190, 98,111,107, 45,109,246, 86,231,221,
+ 40,155,110, 22, 62, 22,189,156,200, 85,178,122, 76,126, 6,145,140,135, 93,237,193,137,240,174,106, 82, 79,114,147, 79,170,122,
+157, 28, 98,227,181,197, 53,209,173, 15, 65,218,246, 77,175,103, 89, 23,109,198, 92,113, 49, 6, 64,165,141,202,222,223, 49, 62,
+117,160, 86,245,195,119, 87,222, 18,237, 25, 79,182,237, 80,172,249, 81,124, 51,205, 37,250,104,223,160, 21,108, 88,143, 30, 60,
+ 43, 32,119, 15,222, 75,197,235, 87, 13,250, 22,213,164, 99, 14, 94,122, 79,199,106, 54,219,172,155,109,243, 98, 49, 81, 84,138,
+ 73, 46, 75, 67,209, 24,178, 18, 7, 11,240, 52, 95, 80,162,184,126,218,251,196,143,112,204,143,111,223, 49, 99,134,105, 88, 36,
+121, 81,130, 20,185,224, 22, 68, 98,116,223,206,244,253,225,222, 91,175,110,110,177,225,237,241,227,152,164,129,102, 61, 88,203,
+ 29, 69,228, 78, 4, 48,225,100, 21, 10,118,199, 36,147,193, 73,247, 80,245,229, 57,248, 85,173,229,106,243,253,195,239, 43,120,
+201, 49,227,236, 24,234, 93, 99, 67,145, 56,136,187, 25, 10,141,122, 19,146,168,107,243,189,118,221,161,187,238, 59,166,199, 6,
+ 94,230,223,230,153,228, 89, 62, 29, 31, 35,149, 23, 81,107, 80, 22,140, 25,175,199, 67, 83,166, 30, 69,238,203, 96, 57,220,214,
+145,118, 62, 60, 40, 76, 73,241,168, 42, 9, 98, 23,189,174, 64,231, 81,133, 67, 2, 8,241,171, 3,130,159,170,131,143,192,146,
+ 60, 13, 0,117, 26, 69, 61,169, 15, 58,112,124, 13, 80, 70,220,105,237, 72,248, 82, 30,202, 2,207,247, 31,242,127,237,169, 82,
+254,230,255, 0,240,127,237,169, 80, 7, 99,193,109,250, 9,251, 34,160,215,224,109, 78, 75, 89, 47,207, 66, 95,245, 69, 49,227,
+225, 64, 6, 91,223,151, 27, 83, 1,244,121,211,202, 78,176, 60,133, 13, 89,174,111,202,128, 37,239,225, 72,240,240,168,131,231,
+ 78, 79, 10, 1,115,226,105,137,189, 32,199, 81, 4, 88, 83, 49,183, 42, 2,182, 75,130,170, 61,183, 31, 69, 8,176, 2,165,148,
+110,234,190, 0, 94,254,255, 0,254,202, 15,182,163, 40,137,184,165,199,202,157, 71, 11,211,248, 80, 12, 27,141, 72,177, 60, 5,
+ 12, 30,102,164, 8, 2,128, 64, 94,156, 40,164,164, 83,223,141, 0,232,128,184, 30, 23,226, 15,149, 71, 39,107,194,200,248,158,
+ 32, 63,156,188, 15,224,162, 70, 70,176, 73,181,184,209, 67, 45,185,254, 74,196,225, 9,173,179,138,146,232,213, 77, 66,115,131,
+221, 9, 56,190,169,208,195,151,183,225,215,166, 41,153,111,224,202, 27,240,252, 52,227,182,150,246,245, 71,245, 63,252, 85,180,
+192,107, 94, 63, 64,162,106,191,202,120,138,242, 62,219,134,221,125, 37,236,148,151,230,122, 87,112,203, 74,158,171,247, 69,254,
+ 70,108, 29,189,131, 29,139,234,149,191,156,108, 62,161, 87, 4, 9, 24, 9, 31,194,163,192, 90,194,172,107,241,231, 80, 33,124,
+121,215,162,213,139, 86,149, 45,194, 49,242, 90,251,206, 23, 47, 93,184,235,114,110, 94,111, 79,112, 62,155, 51,104, 46,108, 7,
+178,145,137,199,231,146, 61,194,166,135,226, 53, 49, 96,124,197,117, 57,153,185, 28, 37, 40,198,246,183, 31,162,244, 11,233, 60,
+ 57,120,154, 54, 75,106,153,216,114,189,184,251, 56, 80, 65,191, 42,208, 28,216,241,231,236,167, 6,226,199,129,168, 19, 99, 79,
+239,160, 23, 1,195,159,153, 52, 65,206,212, 16, 65, 54, 30, 52,117, 28,111, 70, 7, 85,185, 21, 98,212, 52, 28, 69, 26,161, 4,
+ 5, 66, 69,184,181, 76, 83, 61,172,106,131,202,254,243,132,163, 55, 0,159,236,140, 79,163,250, 90,190, 47,193,166,187, 62,198,
+ 56,199,182, 48,125, 53,184, 6, 19, 91,159, 83, 81,215,171,219,248,170,206,253,219,184,157,197,130, 49,114, 73,142, 68, 58,224,
+157, 64, 44,141,238, 60,193,241, 21,195,199,216,157,225,180,202,199,105,207, 69, 70,230,208,204,241, 19,253, 53, 34,223,132,208,
+ 29,103,116,207,218,152,205,142,123,133, 22, 73, 92, 63,167, 82,133,200, 3, 78,175,148, 27, 10,230,251,201,182,105,123, 55, 6,
+125,142, 51, 30, 19,102,142,152,179, 40,224,147,134,178,183,243,129,161, 67,247,117,190,110, 25, 35, 39,126,207, 91, 18, 3,176,
+118,154, 98, 47,200, 23, 1, 71,214,125,213,211,247, 63,106,201,185,236, 56,155, 46,208, 98,129,113,101, 71, 81, 49, 96,186, 18,
+ 57, 19,154, 43,146,196,189,232, 12,159,186,204, 12, 51,182,229,238, 50, 68,175,146,103, 48, 7, 97,114,168,168,143,101,242,185,
+126, 53,191,222,234,195,181,183, 31, 78,128, 62,132,189,135,230,245, 19, 95,253, 27,212,123, 47, 97,204,237,221,174,108, 44,215,
+138, 73,100,200,105,149,161, 44,203,165,146, 52,177,214,168,111,116,173,233,162,143, 34, 39,130,101, 15, 20,170, 82, 68,110, 32,
+171, 11, 16,125,244, 7,137,246,148,125,193, 38, 84,235,219,211, 71, 14, 70,133,234,117, 4,100,148,191,230,245, 21,248, 95,157,
+171,173,200,193,251,204,155, 30, 88,178,115,113,206, 59,163, 44,193,198, 56, 82,132, 89,174,122, 94, 84, 28,223,187,157,199, 7,
+ 52,102,118,230,112,139,226, 45, 18, 72,204,142,159,205, 18, 32,109, 67,223,106,108,142,216,251,193,221,163,244,123,142,225, 31,
+166, 54,214,173, 37,148,129,250, 75, 18,124, 95, 77, 10, 63,100,246,214,233,179,239,139,149, 52,184,239, 11, 68,241,202,176,204,
+174,214, 32, 17,240,175,243,128,170,121,157,239,189,110,251,184,193,237,248,161,131,169, 46,140,105, 12,104,210, 55, 30, 14,205,
+ 32, 42, 60,249,112,174,215,181,187, 75, 15,182, 99,118, 87, 57, 25,179, 0,179,100, 17, 97,164,113,208,131,141,135,159,157,114,
+123,159,221,198,235,143,184,156,238,223,201, 64,130, 78,172, 40,204, 99,146, 35,125, 64, 41, 0,130, 7,135, 42, 16,211, 93,143,
+239, 19, 32, 19,149,190,195, 10,158, 45,211,224,195,207,228,138, 49,245, 26,226,187, 57, 66,119,142, 10, 43,245, 85,102,144, 9,
+ 7, 38, 1, 31,226,250,107,177,255, 0, 78,247,238,235, 31,166,222, 55,132,131, 16,252, 50, 44, 90,117,178,248,143,221, 36,119,
+250, 90,129,178,253,223,110,219, 62,255, 0,143,185, 44,248,242, 98, 99,202,197, 84,187,245, 76,100, 50,139,142,144, 93, 90, 79,
+157,175, 64, 67,239,107,255, 0,209,255, 0,252,207,253,141,116,127,119,255, 0,250, 79,111,255, 0,157,255, 0,199,146,131,222,
+253,181, 55,113,227, 99,156, 89, 18, 60,140, 70,114,130, 75,133, 97, 32, 26,150,234, 13,143,192, 43, 7,183,251, 95,189,118,220,
+156, 53,245, 98, 45,186, 41,227,146,108,117,157,180,152,245,134,145, 66, 1,111,136, 95,133, 1,201,237,134, 37,239, 8, 78,231,
+109, 35, 56,245,245,242,215,212, 63, 54,175, 13, 92,239, 94,239,106,226, 59,163,238,254, 29,235, 37,247, 29,186,101,197,203,147,
+140,209,184, 38, 55,111,210,186,220,169, 62, 60, 13, 97,175,105,125,224,164, 94,137, 55, 34, 49,128,210, 20,101, 72, 19, 79,144,
+225,123,123, 40, 14,119,188,122, 45,221,123,135,160,226, 12,203,167,167,255, 0, 91,165,122,150,183,143, 82,245,167,247,151,171,
+248,238, 54,187,107,244,105,170,220,175,213,150,245,211,118,215,221,194,109,121,113,238, 27,188,233,147, 60, 39, 92, 80,196, 15,
+ 77, 92,113, 14,204,192, 22,183,135, 1, 77,221,221,151,186,247, 38,231, 30,118, 12,216,241,197, 28, 34, 18, 38,103, 86,212,175,
+ 35,220,104,141,197,172,254,116, 7, 71,218, 24, 56,216, 29,185,183, 12,116, 8,103,199,142,121,152, 14, 44,242,168,144,150, 62,
+ 60,237, 91,158, 53, 83,104,196,147, 7,107,193,193,152,171, 73,139,143, 20, 50, 20,185, 82,209,162,161,211,112, 13,174, 60,170,
+223, 1, 64, 34,106, 52,244,136,242,160, 23,133,168,112, 14, 13,239, 52, 91,112,161, 64, 46, 27,222,104, 3, 45,199,141, 63,133,
+ 66,245, 32,124, 40, 5,237,167,191, 11, 83, 91,143,182,149,135, 42, 2,213,191,113,255, 0, 39,254,218,149, 53,191,113,111,248,
+ 63,246,212,168, 3, 57,249,127,160,159,178, 41,129,252, 52,158,255, 0, 15,244, 19,246, 69, 66,255, 0, 93, 1, 9,109,168,123,
+184,154,129, 3,207,157, 52,199,227, 30,234,134,174, 55,160, 9,123, 10, 90,133,114, 57,127,121, 29,147,131,151, 62, 30, 94,241,
+ 28, 89, 56,210, 60, 51,198, 82, 82, 86, 72,201, 71, 94, 8, 71, 2, 41,247,175,188, 30,218,217, 54,140,125,246, 76,131,153,131,
+149, 33,139, 30, 76, 48, 37,212,224, 18, 87,230, 80, 8,177,230,104, 14,178,230,154,215,230,106,166, 14,100,123,134, 22, 54,124,
+ 33,150, 44,168,146,116, 87, 0, 48, 89, 20, 58,134,177, 34,246, 62,117,102,246,160, 41, 79,115, 51, 1,198,214, 3,234,168, 89,
+185, 84,201, 13, 33,111, 2,111, 89, 93,193,220, 59,119,108,237,175,187,110,101,198, 50, 50,161,233, 46,182,212,223, 40, 2,226,
+161, 77, 64,167,149, 62,159, 10,169,180,110,152,251,198,219,139,186,227, 43,164, 25,113,172,209, 44,128, 7, 10,194,227, 80, 82,
+194,255, 0, 77, 91,213, 64, 69, 82,252, 41,244, 11,211,171, 0, 77, 87,200,220,182,252, 39, 84,204,203,135, 29,228, 35,166,179,
+ 72,168, 90,255, 0,162, 24,139,208, 22,130,129,106,123, 0, 41,181,131, 98, 56,131,196, 26,173,151,185,237,248,110,145,229,229,
+ 67,142,207,242, 44,178, 42, 22,191, 15,132, 49, 23,160, 46, 34,130,192, 31, 11,154,150,149,253, 17,245, 80, 61, 86, 52, 8,102,
+200,149, 34,140, 91,247,142,193, 87,143, 46, 45,194,148, 59,150,221,146,230, 60,124,184,101,107, 95, 76,114, 43, 27, 14,102,192,
+212, 5,160,145,159,204, 4,210, 17, 39,151, 58, 98,227, 69,213,197, 50,200,190, 7,143,141, 0,229, 19, 87,209,202,145,141, 56,
+ 91,249, 77, 46,160, 26,189,166,164, 25, 73,247,113, 6,128,128,140, 92,243, 31, 77, 51, 71,252,230,250,205, 76,145,196,130, 5,
+ 69,136,177, 36,248,114,240,160, 51, 24,252,108,109,192,146,110,106, 36,129,198,247,246, 84,250,100,143,140,210,248, 23,144,227,
+ 90, 4,126, 34, 62, 17,111,109, 56, 65,249,198,244,236,237,238, 21, 6, 32,241,230,104, 9, 13, 33,130,168,231, 86, 20, 85,104,
+238, 88, 19,225, 86, 65,168,192, 69,240,169,138,130,243,169,213, 32,168,114,181,172, 60,232,134,162,224, 90,244, 3,175, 5, 21,
+ 32,120,212, 11, 1, 96, 77, 61,252,111, 64, 41, 60, 7,155, 10, 32,160,187,128,203,115,227,115, 79,215, 79, 14, 52, 1, 9,240,
+165, 81, 46, 45,198,162,210,162,159, 31,174,165, 69, 9, 55,206,131,223, 83,170,230, 97,168, 17,225,127,195, 69, 15, 74,138, 4,
+231, 78, 5, 4,202,160, 94,194,134,217, 32, 14, 85, 69, 11,118, 54,229, 81, 38,220,248, 80, 35,201, 46,214,181,135,157, 16,189,
+133,234, 54,139, 70, 14, 72,248,179,223,221, 70, 75, 5, 81,127, 10, 4,211,128, 52,142, 55,231, 80,245, 76, 0, 22,229, 68, 11,
+124, 5, 32, 69,255, 0, 37, 6, 25, 89,248,158, 84, 91,240,184,231, 81,201, 33,181,147, 38,135, 13,180,146, 13,248,154,132,147,
+133, 22,241, 52, 37,152,168,178,213, 78,164,161,112, 94,252,143,224,167, 98, 9,170,177,100, 22, 32, 53, 28, 27,213, 4,214,222,
+127,130,152,243,225, 72, 82, 52, 3,248, 80,160, 97,102,225,110, 52,111, 11,208,113,248,134, 30,218, 0,162,244,246,243,165,200,
+210, 54, 2,230,132, 28,138, 64,208,250,171,107, 95,149, 46,170,208,165,219,254,227,151,247, 63,246,212,170, 29, 81,208,191,252,
+ 27,255, 0,239,173, 74,128,103,150, 75, 39, 31,238,227, 39,128,241, 69,168,117, 31,206,147,143,236,255, 0,195,143,246, 22,161,
+ 66,130,200,146, 77, 96, 6,225,111, 33, 66, 18,201, 99,198,231,218, 41,100,147,172,123,191, 25,160,113,170, 15,154,179,114, 38,
+139,187, 59,216, 69,181, 13,212,207,252, 78, 39,186,234,244,170,217, 55, 57,128,105,110, 49, 91,129,225,107,243,166,205,151,111,
+255, 0,246,199, 7, 27, 14,119,150,101,221,158, 92,196,145,116,152,228,124,114,161, 83,139, 93, 52,160,177,243,189,118,217, 63,
+118,189,237, 30,251,190,238,155, 70,225,129,143, 22,242,249, 81,190,182,144,201,233,178,165,234,148, 35,160,193, 90,192,114, 62,
+227, 79,147,247, 57,184,167,108, 69,180,224,102,227,201,184, 62, 88,203,203,154, 98,241,197,165, 99,104,214, 56,244, 36,140,109,
+170,247, 32, 84, 0,123,151,190,247, 92, 7,237,222,219,195,221, 63,130, 97, 13,187, 22, 92,221,197, 98, 51, 56, 47, 23,194, 52,
+168,102,210, 52,143,151,206,177,223,239, 71,188,102,236,245,145,119, 3, 30,118, 62,106,227,201,148,177,197,174, 72,100,137,164,
+ 64,196,161,179, 43, 70,120,139, 19, 93,143,113,125,220,111, 89, 51,236,219,206,195,151, 4, 59,198,217,139, 6, 52,201, 53,204,
+ 78, 96, 93, 58,208,148,107,243, 43,102, 91, 17, 66,223,187, 19,189,123,155, 96,143, 15,114,201,219,151, 61, 51, 6, 64, 17, 6,
+138, 20,132, 68, 99,209,120,225, 36,190,182, 39,136,250,104, 12,110,222,239, 14,238,194,239, 92, 13,183,126,220, 70, 86, 30, 78,
+ 42, 75, 44, 72,163, 64,141,241,125, 82, 48,248, 85,181,173,133,207,143, 26,230,187,139,185,187,171,187,182, 77,195,118,203,202,
+ 72,182, 88,179, 34,130, 61,185, 85, 69,153,195,200,159, 16, 93, 71, 64, 94, 36,158, 55,175, 66,143,238,223,120,255, 0, 87,237,
+219,228,243, 98,182, 6, 54, 44, 24,185, 17, 7,147,170,221, 60, 95, 74,250, 7, 75, 77,175,202,237,202,185,255, 0,255, 0,104,
+123,194, 60, 28,237,155, 27,114,195, 27,108,185, 9,145, 18, 72, 94,242, 52,122,145, 25,200,137,138, 29, 15,196, 11,241,250,232,
+ 10,217,189,235,184,224, 97,118,191,110, 98,110,159,193, 48,191,135, 99,205,155,184,172, 70,103, 5,212,149, 26, 20, 51,105, 26,
+ 71,203,231,236,170,173,247,153,221,146,246,112,149,115,204,121,208,102,174, 60,153, 75, 28, 90,164,134, 72,157,212, 53,208,217,
+149,163, 63, 16,177,174,175,116,251,178,223, 66,108, 59,158,201,153,143, 14,245,180,226,195,139, 58,201,168,195, 33,132, 27, 58,
+ 22,141,175,193,138,144,203, 98, 40,187,255, 0, 98,247,183,115,108, 17, 97,110,121, 59,114,231,174, 96,200, 81, 16,120,161, 72,
+ 68, 70, 61, 23,142, 18, 75,235, 98,120,143,166,160, 58, 30,192,255, 0, 87,101, 46, 94,235,220,210,127,150,206,143, 26, 93,174,
+ 5,101, 97, 28,101, 92,182,160,188,117, 21,208, 77,235,153,251,208,236,206,219,196,219,183,126,234,206,200,152,110,121, 79, 24,
+196, 82,224, 39, 82,202,139, 18, 38,158, 55, 85, 36,220,215,166,237, 56,242, 96,109,120, 56, 51, 16,210, 99, 99,197, 12,140,151,
+ 42, 90, 52, 84, 37, 73, 0,218,227,202,188,235,239, 3,177,187,203,188,119,104,230,131, 43, 6, 29,179, 16, 91, 11, 30, 89, 37,
+189,205,139,201, 34,136, 25,117, 49, 28,184,139,125, 52, 7, 67,247, 92,187,146,246, 70,219,252, 72,177,114, 28,227,137, 47,168,
+ 64, 92,244,175,127, 13, 63, 47,243,109, 92,183,222,135,102,118,222, 46,221,187,119, 94,118, 68,195,116,202,120,198, 34,151, 1,
+ 58,150, 84, 88,145, 52,241,186,169, 38,230,181,165,237,255, 0,188,166,237,168, 48, 34,222,241,211,120,143, 41,164,147, 41, 89,
+150, 51,141,211,210,145, 46,156,127, 6,227,109, 31, 77,103,247,215, 98,119,183,120,110, 16, 72,153,152, 17,224, 97,160, 92, 88,
+ 36,146, 98, 75,216,117, 37,145, 70, 59, 46,166, 35,234,250,104, 10, 47,183,247, 6,127,220,158, 22, 8,197,159, 51, 55, 38,116,
+ 24,209, 34, 52,146,250, 97, 43, 73, 29,192, 4,133, 10,156, 9,225,166,212,190,231,242, 59, 95, 31,125,125,184,237,121, 59,119,
+114,199,138,216,243,156,137, 12,137, 33, 66,134,123, 70,202,134, 39,212,151,211, 99, 97,113,122,236, 32,217,126,242, 32,237, 56,
+113, 32,222,240,255, 0,212, 16,102,117,186,231,251, 6,196,233, 24,198, 57, 6, 1,199, 83, 95,228,240,231, 84,123, 27,238,251,
+118,218,251,135, 43,187,251,171, 58, 12,173,214,112,250, 18, 3,240,134,151,131,187, 29, 49,139,233,248, 64, 81,106, 3,210, 0,
+ 5,245, 34, 11, 19, 99,127, 33, 82, 17, 41, 60, 84,113,161, 2,164, 31,222, 5, 4,254, 15, 42, 47, 82, 59,243, 22,247,138,128,
+ 99, 26, 95, 78,129,111, 58,115, 20, 97,117,104, 31, 85, 49,149, 73,210, 10,251,110,124, 61,148,158, 84, 11,240,176, 55, 28,174,
+ 40, 8,172, 72, 84, 53,135,183,133, 69,226, 65, 27, 54,144, 8, 7,240, 84,186,136, 0,187, 15,117,232, 83,186, 52, 68, 6, 6,
+246,225,244,213, 5, 38, 55, 55,231, 76, 77,253,254,202, 71,129,243,166, 60, 56,255, 0, 37, 80, 43,218,157, 16,185,225, 81, 0,
+187, 0, 5,201,228, 42,242, 70,177,141, 35,233, 52, 0,244,104, 81,237,231, 72, 84,229, 60, 20,125, 53, 17, 80, 15,114, 57, 11,
+210, 13, 35,114, 90,139,177, 94, 94, 84, 72,217,180, 19, 84,131,161,107,217,133,169,228, 54, 90, 26, 73,198,237,206,162,242,106,
+ 36, 14, 94, 20, 2, 23,102,213, 69, 98, 21, 73, 60,170, 3,225, 80, 60,106, 46,192,139, 30, 53,142, 44,215, 0, 26,153,137, 52,
+ 72,148,146, 88,210, 80, 13, 78,224, 30, 28,171, 79,128, 68,216,133, 66, 72,170,186,137,185,162,200, 67, 0, 56,251,104, 97, 69,
+ 68,168, 25, 56,151, 81,187,114, 21,101, 57, 94,132,186, 84, 1,106, 76,192, 39, 11,234, 63,101, 71, 86,202, 10, 89, 9,126, 28,
+133, 68,150, 60, 60,234, 6,141, 18,168,248,143,209, 90,224,136, 22, 53,208,162,166,237,161,110,109, 67,212, 63, 37, 10,103, 86,
+109, 35,144,254, 90,197, 42,202, 66,250,137, 38,157, 87, 83, 5,168, 10,179, 2,128, 11, 17,196,158, 21,182,232,136, 25, 64, 80,
+ 2,248, 81, 89,180, 45,201,224, 5, 6,235,229,195,141, 15, 34, 69, 63, 2,253, 38,185,165, 86, 80, 46,197,220,177,165,200, 14,
+ 53, 19,236, 20,104, 81, 73, 12,195,128,174,156, 17,144,144, 69, 97,115,204,209,148,216,218,163,169,124, 56, 15, 26, 76, 80, 2,
+199,152, 21,132,221,124,205, 53,160,117, 35,133, 73,173,107,147,202,170,166, 66, 0,111,196,249, 80,222,102,144,241,224,190, 85,
+208,197, 3,174, 72,107,171, 11, 15, 3, 90, 24,219,111,238, 86, 94,175,246,128, 61,180,242,184,191,157, 98,151, 26, 74, 91,230,
+ 35,141,117,144, 41,142, 8,162,110,104,138,166,220,184, 11, 82, 58,135,162, 40,182, 13,184,245, 63,232,254, 90,207,155, 87, 77,
+173,227,194,183,102,226, 56, 87, 59, 46, 66, 94, 72,127, 57, 88,175,212,109, 85,170, 80,139,130, 24,194,162, 61,125,102, 39, 77,
+213, 71, 59,212, 63,115,162,226, 73, 11,248,175, 15,178,152, 72,209,178,200, 99,248, 84,105,185,228,106, 17, 49,107,155,113, 38,
+245,154,154,161,163,211, 95, 65,212,214,218,250, 22,183,179,175,170,244,169,238,125, 22,155,255, 0,113,207,254,125,169, 85,168,
+161, 41, 7,246,127,225,199,251, 11, 67,169,201,253,223,248,113,254,194,212, 40, 10,185, 54,214, 61,223,140,208, 15, 42, 62, 79,
+246,131,221,248,205, 7,149, 80,114, 35,191,182,229, 68,105, 32,117, 45,131,149,184, 63, 16, 66,250, 70,145, 30, 18,127, 72,152,
+ 94,222,234,218,143,127,219,164,127, 74,101, 11,156,177,117,100,196,227,117, 97, 24,153,163,213, 96,165,194,181,202,243,183, 27,
+ 90,184,252,191,187,237,194,121,115, 89, 50, 32, 84,200,220, 68,209, 41, 47,240,224, 72,114, 91, 35, 29,128, 79,152,182,100,133,
+ 84,112,229,198,180,215,181, 51, 7,112,228,110, 4, 35,227,188,243,229,195, 51,228,100, 93, 90,124,111, 75,211, 24,128,244, 21,
+129, 45,121, 56,146,188, 45,228, 6,198, 23,116,237, 25, 49,109,198, 73,215, 31, 35,114,199,131, 42, 28,119,189,213,114, 23, 84,
+106,236, 6,144, 91,136, 91,159,136,142, 20, 72,123,163,183,231,199,147, 46, 45,194, 54,130, 38,141, 30, 79,136, 11,206,116,195,
+107,139,145, 33,249, 72,224,124, 43,157,195,237, 77,227, 14, 24, 48, 63,202, 75,143, 62, 22,221,139,157, 59,150,102,137,176, 99,
+104,228, 48, 35, 39,198, 90,227,166,196,174,147,198,212,161,237, 61,222, 65,141, 38, 75, 99,197, 46, 32,218, 49,213, 99,119,100,
+120,118,188,131,145, 36,166,241,130, 30, 64,196, 42,120,120,181, 1,208,227,119, 70,193,149,212, 48,103,163, 44, 48,190, 76,165,
+131, 32, 88,163, 58,100,114, 93, 87,228, 60, 24,115, 95, 26,187,139,185,237,249,152,146,103, 99, 76, 31, 30, 45, 66, 86,179, 2,
+133, 5,217, 89, 24, 6, 4, 14, 54, 34,184,233, 59, 39,114,151, 22, 76,115, 60, 10, 95, 19,116,199, 86, 13, 39,246,153,185,233,
+157, 7, 37, 7, 72, 84,179,145,196, 30, 87,174,139,182,118,169,246,172,108,175, 81, 26,195, 46, 94, 75,100,180, 99, 34,124,182,
+ 23, 72,226, 29, 73,242,137,119,107, 70, 60,135,135,182,163, 0,246,206,242,216, 55, 72,118,249, 23, 32, 65, 54,226,145,201, 14,
+ 60,160,135, 29, 86, 40,138,228, 2,160,179, 41, 85,227,241, 30, 87,167,238, 78,238,219,251,110, 65, 6, 76,111, 44,205,137,145,
+154,170,131,129, 92,109, 55, 91,159, 22,212,109,238,227,225, 92,238,217,217,155,214, 38, 38, 62,221, 59, 99, 24, 92,109,169,149,
+ 60,114,185,100, 27, 92,253,101, 49,171, 68,186,186,202, 20,113, 35, 73,191,205, 90,189,235,219,219,151,112,116,255, 0,135, 60,
+ 11,254, 75, 63, 10, 79, 80,238,150,245, 98, 29, 14,186, 35,146,250, 90, 30, 35,135, 3,244, 84, 6,178,119, 22,217,145, 38, 56,
+196,158, 57, 34,150,121,113,165,145,152,198, 81,225,133,178, 88,105,117, 26,190, 21, 7,195,225, 58,185, 85,141,191,121,218,247,
+ 72,165,159, 3, 37,102,142, 27, 25, 77,153, 74,134, 93,106,214,112, 14,150, 94, 42,121, 17,202,185,249, 59, 99,114,109,202, 76,
+228,124,118, 70,220,178, 51,213, 36,214,192,199, 54,217,252, 61, 85,212, 40,185,234,113, 97,127,151,198,252, 40,221,183,178,110,
+ 91,110, 30,126, 62, 80,142, 36,157, 82, 60, 92,100,154, 76,133,136, 44,101, 24, 9,166, 69,147,167,171,228, 67,125, 43,245, 80,
+ 26, 43,221, 93,186,240, 67, 58,231,198, 98,200, 36, 67, 32, 13,165,128,209,169,175,110, 8, 58,139,118, 63, 8, 38,215,164,157,
+203,182, 69,235,206, 99,250,101,194,204, 56, 23,107,177,146, 65, 4,121, 68,162,160, 45, 96,146,113,225,194,196,242,174,103, 63,
+178,115,242, 54,237,159, 8,244,167, 56,219, 82,109, 57,137,234,114,113,226, 4, 8,181, 75,254, 91, 67, 78,159, 3,126,237,237,
+126, 21, 99,114,237, 45,202,121,178,179, 34,104,229, 50,110, 82,230,199, 0,202,159, 16,180, 83, 97, 69,133,103,159, 24, 7, 86,
+ 87,143, 81, 81,112,203,194,254, 20, 7, 82, 55,221,149, 50,177,240, 78,100,126,171, 37, 81,162, 85, 37,129, 18,130,209, 93,212,
+ 21, 29, 64,167, 77,207,197,225, 85,207,116,118,254,172,139,102,199,254, 90,203, 45,131,113, 38, 78,143,238,254, 31,222,126,243,
+224,248, 47,241,112,231, 92,244,157,167,187,174,102,214, 33,124,127, 67,182,174,219,210, 65, 60,209, 42,156, 43,172,203,210, 9,
+ 39, 80,178,219, 67, 72,196,139, 91,133,239, 85,165,236,221,226,102,157,175,141, 4,107, 44, 89, 17,226, 99,229, 78,137, 44,137,
+147,234, 36,104,100,211,213,195, 18, 33,249, 99, 98, 53,241,246,208, 29,202,110, 59,123,109,255, 0,197, 70, 68,127,195,214, 54,
+153,178,137,248, 21, 18,250,203, 19,203, 77,141,252,171, 27, 51,188,182,152, 83,111,244,108, 51, 27,112,204, 24, 49, 1,170, 62,
+155,132, 50, 72,210, 6, 77, 67, 74,219,225, 34,230,227,195,141, 69, 59,117,191,209,179,118,222,184,160,200,153, 39, 35, 76,146,
+205, 18,203, 52,175,144, 53, 73, 57, 50,184,212,223, 19, 30, 39,137,176,229, 85,211, 96,220, 39,207,139,118,201,104, 33,200,147,
+120, 77,207, 35, 25, 36,105, 17, 34,139, 1,182,245, 68,126,154,106,114,108,198,224, 15,171,136, 23,119, 94,245,218,182,141,205,
+246,156,148,115, 60, 67, 12,200,225,108,161,115, 39,244,192,159,232,124,199,216,120,113,171,239,220,253,187,208,198,203, 25,136,
+144,230, 23,244,238, 67, 11,136,216, 69, 33, 96, 69,208, 43,252, 44, 90,214, 60, 13, 99,239,221,189,159,185,119, 4, 91,158, 44,
+152,227, 22,219,103, 88, 72,238,178, 41,219,243,155, 53,180,170,198,234,218,210, 66, 5,216,113, 30,219,140,108,206,197,207,154,
+ 8, 96,102,135, 32, 58,238, 16, 79, 31,170,202,199,141, 83, 55, 53,179, 35,145,134, 54,134,152, 8,219, 75, 70,214, 26,173,199,
+198,128,236, 55,173,225,182,201, 48, 49,161,196, 57, 89, 59,140,175, 4, 40,174,177,128, 99,134, 76,134, 44,207,195,229,140,214,
+ 70, 63,121,237,185,240, 75, 51,198,248,145,227,195,139, 60,141, 41, 7,142, 75,207, 10,196,130, 61, 90,142,184, 8, 26,111,170,
+226,213,103,186,246,105, 55,183,218,165,135, 19, 15,112,143, 3, 34, 73,178, 48,119, 6,100,134, 85,120, 37,129,120,136, 50, 69,
+213,164, 13,197, 60, 43,154, 94,194,220,227,196,154, 51,145, 28,164,122, 7,130, 24,230,154, 15,252, 38, 78, 84,237,142,179, 42,
+245, 35, 85,143, 33, 99,137,215,143,195,196, 10, 3,160,159,185,246, 28,104, 33,200,159, 54, 53,138,116,105, 98,111,136,221, 17,
+130, 59,124, 32,144, 21,152, 6,191, 47, 26, 28,253,197,183,199,188, 99,108,145,191, 87, 42,121, 94, 25, 21,121, 68, 83, 29,242,
+254, 50, 69,190, 69, 28, 1,225,113,122,198,159,177,115,228,219, 78, 28, 45,143, 11,190,215,184,225, 21, 50,207, 34,140,140,236,
+152,242,148,245, 37, 87,145,212,105,109, 76,120,147,249,190, 87, 37,237, 77,202, 77,228,200,173,142,187,105,205,201,206, 51,235,
+126,191,249,172, 23,194,233,136,180,105,186, 59,106,190,190, 35,219, 84, 27, 24,253,199,219,195, 18, 76,229,207,139,161, 27, 34,
+ 73, 49,184, 0,202,109, 21,174, 1, 42,255, 0,154,195,131,120, 81,247, 13,225,177,162,196,147, 11, 18, 92,231,205, 63,185, 72,
+237, 26,132,208,101, 47, 43,203,165, 80,105, 22,227,198,230,213,202,237,157,151,184,227,226,199, 20,162, 24,231, 73,246,150,119,
+ 57, 89, 57, 70, 72,182,217,186,174,218,178, 1,209,170,237,211,141, 84, 1,226,124,186, 30,232,192,221,247, 44, 72,176,246,206,
+145,130, 73, 63,250,140, 82,207, 38, 51, 75, 6,147,120, 82,104, 98,157,151, 91, 91, 81, 2,250,110, 1,227, 80, 18,110,224,138,
+125,155, 15,121,193,198,155, 41,115,150, 22,198,199, 85, 2, 66,114, 10,233,214, 73,210,129,111,118, 98,108, 7,157, 79, 3,125,
+195,202,218,230,221,167,255, 0, 39, 14, 51, 77, 22, 80,152,143,221,190, 60,141, 12,163, 82,146,172, 53, 33,177, 28,234,158,227,
+139,220,146,109,143,133,181,199,135,129, 39, 75, 30, 56, 68,115, 72, 4,106, 24,140,136,227,127, 79,240,218, 48, 22, 38,233,251,
+108, 44, 42, 67,104,159,253, 47, 46,207, 30, 6, 28, 47,211, 49, 38, 19, 75, 44,248,197,111,115,174,110,156, 50,150,113,114, 91,
+ 77,245,113,227, 64, 29,187,155, 96,209, 12,173,156,138,179, 23, 69, 12, 25, 88, 50, 21, 87,234, 43, 40,104,244,151, 91,151, 2,
+215, 30,117, 57,123,143,108,134,118,193,138,120,229,203,142,120,113,231,132,177, 77, 6,121, 35,140, 93,180,145,171,247,160,170,
+254,117,113,249, 61,141,188,100,170,140,150,142,113, 52,121, 24,239, 4,185,185, 75,210,138,105, 35,116,235, 77, 0,137,242,244,
+170, 48,101,146,215,225,199,133,235,126,110,218,206,127, 93,166, 72, 71,169,223, 48,247,100,185,110, 16, 99,250, 77,104,223, 7,
+206,125, 59, 88,114,229,198,169, 13, 47,245, 22,197,124,192,217,145,223, 8, 51,100, 18, 72, 10,177,182,135, 32,145,102,210,195,
+ 73,211,123, 30, 28,232,219,126,126, 38,229, 9,202,194,144, 75, 16, 98,135,129, 82,174,191, 50,186,184, 12,164,121, 17, 92,110,
+ 63,102,231,227,156,244,104,113,178, 75,195,147,143,142,217, 57, 57, 82,164,201,147,146, 50,116,180, 55, 9,142, 52,168, 7,166,
+ 9,213,241,123,247,251,127, 3,121,218,177,189, 62,113,137,224,145,166,151,140,175, 52,232, 89,147,163, 27, 74,241,167, 86,201,
+171, 83,183,197,123, 14, 35,141, 71,208,168,216,146, 70,191, 10, 17,145,252,232,202,188, 56,208,221, 46,228, 94,192, 80,164, 68,
+174, 60,105,117, 95,206,159,166, 63, 72, 83,244, 71,233,138,164, 33,212,127, 58,113, 35,143, 26,159, 64, 18, 70,161,236,168,152,
+136,241, 31, 93, 0,186,210,121,210, 18,185, 54, 39,133, 71,166,212,197, 72,230, 40, 2, 59, 5,182,151,213,126,124, 45, 77,214,
+126, 94, 84,209,128,206, 1,228,106,200,199,140,208, 21,186,175, 77,173,141, 91,244,169,111,109, 47, 72,190,116, 5, 93,109, 83,
+ 19,201,107, 10,178,112,208,114, 52,222,144,121,212, 0, 58,242,123, 42, 61, 71, 60,192,163, 8, 65, 82, 60,174,111, 75,160, 45,
+127, 42, 80, 3,214,213, 49, 51,129,164, 1, 79, 38, 57, 60, 84,219,194,171,184,116,109, 45,206,148, 5,245,109, 64, 95,253,189,
+148, 9,100, 36,233, 28,133, 13, 36, 40,182, 39,230,229, 74,162,142,165,168,124,116, 73, 90,206,197,124,173, 86,198, 4, 39,143,
+ 89,190,161, 89,200,197, 88, 88,214,148, 47,169,125,181,163, 44,201,155,121,237, 44,105,228,199,200,238, 28, 24,103,137,140,114,
+ 69, 38, 76, 8,202,234,108,202,234,206, 10,144,121,222,182,207,122,246, 93,135,255, 0,244,123, 95,255, 0,222,227,255, 0,222,
+ 87,207,216,221,191,181,231,111, 93,245,190,229,237, 51,119, 30, 86,219,185,188,120,251, 30, 60,146, 70,204,179,228, 74, 31, 33,
+250, 23,148,170,105,183,195,244,215, 59,221,125,169,180,109,189,243,137,177, 98,179,225, 97,102,174, 36,179, 99, 76,225,229,195,
+108,149, 86,147, 25,223,197,146,252,205, 71, 37, 24,185, 62, 9, 85,251, 10,162,228,212, 87, 22,232,189,167,211,207,222,189,155,
+126, 29,197,182, 91,255, 0,235,113,255, 0,239, 43, 3, 47,184,251, 64,203, 44,171,220, 91,113, 44,197,128, 25,112, 30,102,255,
+ 0,167, 95, 62,119, 22,199,183, 67,180,101,230,197,181,205,179, 77,131,150,184,176,137,164,103, 25, 72,218,174,192, 73,249,203,
+166,228,175, 10,235,251, 91,177,123,123, 51,107,237,216, 39,216,178,183,111,245, 12, 82,201,157,220, 48, 78,233, 30,220,200,204,
+154, 2, 32, 49,254,239, 77,223,169,207,195,202,179,106,252,111, 67,116, 83, 84,116,214,159,149, 81,210,237,169, 90,146,139,105,
+213, 87, 74,254,116,103,176,109,187,158,217,188, 66, 78,221,155, 14,100, 80,217,100, 24,242,164,182, 99,196,106, 49,179, 90,174,
+ 44, 96, 46,168,238, 9,240, 53,228,223,114, 30,159, 15, 27,184, 33,235,163,198,153,113,199, 28,215, 0, 56, 85,113,168, 95,204,
+113,175, 93, 86, 89, 34, 12,140, 24, 56,186,176, 55, 4, 30, 68, 17, 90, 57,150, 47,254, 75,249,221, 31,254, 98,149, 63, 76,250,
+109, 54, 23,232, 91,255, 0,127,122, 84, 3,184,225, 31,248,113,254,194,212,106, 79,249,159,225,199,251, 11, 80,173, 2,174, 79,
+206, 61,223,140,208, 13,239, 71,201, 31, 24,247,126, 51, 66,181, 1,230,178,247,142,253, 30, 6,118,102, 60,169,144,240, 38,230,
+210,199,233,216, 38, 47,164,150, 72,241,216,202, 62, 6,215,160, 2,167,137,240,228,107,164, 29,231,128,219,251,236, 10,129,231,
+ 87,146, 4, 9, 42, 52,205, 44, 80,122,166,255, 0, 47,125, 97, 52,130,161,207, 2,194,222,218,188,221,181,130,219, 14, 87,111,
+ 25, 38,244,153,126,167,169, 38,165,234, 15, 87, 44,147,201,164,233,211,193,164, 58,126, 30, 94,116,223,233,204,113,159,147,151,
+234,242, 86, 12,150,146, 89, 48,149,148, 69,214,154, 33,143, 36,151, 11,172,221, 7, 5, 45, 96,120,218,128,200,143,190,241,219,
+ 7, 51, 41,177, 66,201,135, 38, 52, 82, 40,158, 54,137, 61, 87, 5,105,231, 75,172,125, 51,113, 39, 3,164,143, 26,144,239,220,
+ 5,207,194,192,158, 1, 12,217,126,157, 90, 55,154, 62,160,124,183,104,162,233, 70, 13,229, 91,128, 89,151,128, 82, 15,186,198,
+ 31,102,197,131,142,241, 99,110,121,137, 33, 76,120,196,160,194, 62, 28, 64,201, 18,148, 88,130, 50,148,125, 46,172, 8, 60,249,
+241,162, 97,118,118, 22,221, 46, 59, 97,101,229, 69, 20, 66, 30,180, 10,241,133,157,177,221,228,137,165, 34, 48, 71,197, 33,186,
+161, 85, 60, 5,173, 64, 88,221,183,217, 54,252,216,176,113,112, 37,207,152,194,249,115,164, 68, 6, 72, 99,116,140,148, 82, 63,
+120,228,191, 5, 30, 92,235, 23,111,239,137, 34,197,201,125,223, 24,129, 4, 91,134, 84,121, 17,178,129, 36,120, 89,167, 19,167,
+160,219, 73,248,144, 92,158, 60, 79, 10,221,221,187,126, 45,215, 34, 44,161,149, 62, 28,171, 19, 99, 76,216,204,170,100,129,217,
+ 36,104,201,101, 98,191, 20, 98,204,150, 60,248,213, 79,244, 94,210,208,188, 45, 36,236,143, 6,110, 49,248,214,225,115,242, 6,
+108,140, 8, 79,153, 36, 81,163,217,206,245, 24, 1,143,222,209,103, 99, 68,118,220, 65,155,155, 38, 84,184, 98, 24, 39, 71,132,
+180, 48, 12,167,116,200, 80, 85,151,166,194,214, 31, 49,183,153,168,236, 93,216,251,166,243,153,179,188, 45,234, 35,152,200, 33,
+ 96, 35,124,108, 79, 79,141, 32, 51,131,115,172,203, 49, 64, 7,183,202,174,205,218,221,104, 35,213,185,229,250,248,167,147, 33,
+119, 11,197,212, 13, 44, 71, 30, 68, 84,233,244,149, 52, 30, 0, 47, 3,199,157, 44, 46,206,219,112, 50,227,207,198,146,113,149,
+ 28,221,126,187, 50,179,178,156,120,241, 26, 25, 25,144,150,141,150, 37, 99,126, 58,184,222,160, 51,119,254,231,222,182,237,245,
+182,204, 76,100,108,117, 27, 89, 70, 36,106,115,153,152,216,210, 47, 19,195, 82,174,145,228, 69,252,105,178,126,241,182,236, 28,
+ 44,108,172,200, 4, 45, 40,201,121,225,121,227, 82,163, 18,115,137, 42,195,175, 79, 89,203,169, 42,170, 56,129,225, 91, 59,151,
+108, 98,110,123,164,123,172,211,207, 28,177,140, 80,209, 70, 80, 70,254,143, 35,214, 66, 91, 92,108,220, 28,144,108,194,224,251,
+141, 87, 61,155,136,137, 10,227,102,101, 99, 20,245, 43, 43,196,200, 30, 88,178,242, 14,100,177, 51, 24,254, 16, 36, 63, 11, 37,
+152, 14, 23,241,160, 23,117,238,249, 59, 92,187, 76, 80,100,122, 88,179, 50, 36,139, 34,117,129,178, 89, 85, 49,229,153,116,196,
+128,147,118,140,114, 28,171, 27,183,187,159,118,221,183, 28,108,124,172,150,137, 31, 27, 14,117,244,152, 50,100,164,135, 34, 73,
+208,180,210, 68,178, 46, 56,101,137, 79,198, 70,155,159,209, 54,236,114,246,232, 51, 51,112, 51,101,103, 18,109,210,188,208, 5,
+ 32, 41,105, 33,147, 24,135,184, 36,141, 50,158, 86,227, 89,123,103,104, 67,181,229,156,157,183,116,205,197,214,168,147,196,190,
+153,210, 85, 73,102,157, 85,186,184,206,192, 94,119, 31, 1, 28, 61,188,104, 12, 44,238,247,220,160,147,185, 26, 22,131,161,143,
+141,151, 46,202, 52, 92,135,219,153,113,242, 53,155,252, 90,164,123,143,101, 27,184, 59,139,185, 54,152, 55, 93,183, 26, 88,114,
+119, 60, 89,118,223, 69,146, 97, 10, 25, 55, 9, 94, 13, 18, 70, 24,130,202,209, 30, 34,220, 8,173, 57,254,238,187,118,109,190,
+ 28, 16,210,194,209, 71, 60, 50,230, 69,209, 92,137,215, 37, 26, 57, 78, 68,157, 35,172,157, 90,185,124,192,123,170,232,237, 92,
+ 6,102,147, 47, 55, 35, 43, 46, 92,172, 92,201,115, 38,104,132,140,216, 46, 37,130, 61, 48,197, 28,107, 24, 35,136, 84, 7,137,
+227,126, 52, 7, 41,157,223,251,156,185, 59,174, 70,214, 98, 59,118, 62,200,249,248,132,166,163,234,145, 49, 39,185,111,206, 80,
+153,138, 45,231, 93,190,203,149, 36,248, 83,228, 75, 54, 78, 89, 70,109, 34,124, 41, 48,101,248, 84, 54,148,135, 33, 34,102,189,
+248, 53,173,126, 23,225, 88,137,247,127,219,176, 98, 77,133, 20,243, 36, 83,227,102, 97,184, 87,142,253, 60,217, 99,158, 66, 63,
+119,107,167, 73, 85, 60,148,113, 7,157,111,193,136,209,225,207,139,151,185, 79,184,245,195, 43, 75,144, 49,209,213, 89,116,149,
+ 95, 73, 12, 11,245,130,104, 12, 44,110,252,199,201,198,158, 69,193, 39, 38, 12,156, 44, 79, 79, 20,241, 74, 53,231,186,197, 18,
+180,139,240,171,163, 18, 29,127, 52,142,102,168,238,221,253,150,155, 36,217,123,102, 6,156,248,241, 51,242,165, 14,234,201, 1,
+194,156,225,177,226, 7, 86,242,142, 3,135,194, 62,138,209,195,236,189,183, 18, 20,137,179,114,167,233,182, 3,169,110,144, 23,
+219, 31,169,140, 45, 28, 43,195,128, 15,231,236, 60,105,178,187, 23,107,203,197,108, 36,205,203,199,138, 72,243, 32,200,104,140,
+101,228,135, 58,115,153, 44, 68,188, 46, 6,153, 79,194, 64,189,184,113,160, 54,183,205,230, 77,173,176,241,177,112,219, 55, 55,
+ 58, 71, 72, 32, 87, 17,139, 69, 27, 79, 35, 51,176,107,124, 41, 96, 45,196,145,239,172,101,239, 88,231,203,142, 39,219,102,135,
+ 17,229, 56,107,145, 49, 85,113,148, 49,125,115, 66,240,252,203,101, 82,183,253, 33,229,198,181,247,173,170, 29,223,211, 72,185,
+ 83,225,101, 98, 59, 62, 62, 86, 50,174,181,234, 70,208, 72,182,149, 29, 72,100,115,225,192,216,138,202, 61,163,131, 28,226, 88,
+ 50, 39,104,163, 38,104,113,102, 96,209,250,175, 77,232,189, 75, 49, 78,161, 99, 31, 59,181,174, 75, 90,244, 64,171,135,223, 16,
+ 78,152,173, 62,222,248,254,176,109,243, 71,119, 87,182, 62,230,207, 20, 19, 49, 94, 86,145, 52,178,251, 69, 83,155,190,142, 86,
+217,159,151,135,131, 44, 49, 98,224, 13,193,242,195, 68, 74, 71, 47, 95,160, 81, 28,124,108,253, 11,242,183, 26, 9,236,124,216,
+187, 94, 77,181,103, 25, 91,182, 78, 14, 22,220,102,150, 77, 49, 99,174, 32,212,173, 1,142, 37, 98,177,202,204,235,168,106, 60,
+ 56,240,173,215,236,237,169,240,243,176,117,202,144,231,224,227,237,146,132,101, 26, 33,198, 89, 18, 51, 21,208,217,173, 41,189,
+238, 57,112,170, 10,217,125,222,209,110, 15,135, 22, 11,250,113,148,251,114,102,151, 91,122,148,199,108,182, 29, 47,155, 72, 85,
+181,252,255, 0, 14, 52, 93,241,187,201,219,241,228,140, 21,254, 36,145,108,243, 74,197,215,167, 36,123,156,139, 25,117, 81,109,
+ 36,149, 96, 5,248, 92, 31, 49, 87,178, 59, 83, 55, 39,185, 6, 88,144, 69,181, 46, 81,207,100, 89,175,170, 70,197,124, 70,180,
+ 6, 31,133,201,107,150,234,149,176,224,160,147, 87,135,100,237,131, 9,240, 83, 35, 37, 21,241,182,252, 65, 40,104,245,170,237,
+110,100,198,145,111, 25, 93,122,141,218,234, 65,242, 21, 0,221,197,221, 35, 97,144,175,162,108,146,184,146,238, 19,105,145, 80,
+ 36, 56,239, 18, 73,243, 3,169,191,123,192,120,211,158,233, 35,115,124, 4,193,119,132,229, 62,223, 14, 81,145, 84, 62, 90, 99,
+156,190,150,131,196, 41, 85, 43,175,207,194,220,104,251,191,109, 97,111, 79, 41,203,150, 96,101,194,159,109,115, 25, 65,251,172,
+134,141,221,248,161,248,239, 8,183,135, 62, 21, 52,237,188, 65,186, 13,207,173, 41, 65,144,115, 87, 12,232,232,140,166,135,210,
+153,199,195,174,253, 59,240,213,107,155,218,244, 7, 51,179,119,190,118, 78, 28,121, 89,152,230, 92,217,177,246,211, 22, 36,101,
+ 18, 38,151, 57,230,141, 89, 95,226,101, 7,167,169,181, 94,192,112,227, 87,228,239,236,104,183, 12, 93,175, 47, 21,177,114,166,
+120, 97,150, 9,165, 69,153,101,200,149,160,140, 69, 17,248,165, 77, 73,114,227,243, 72, 62,227, 98,118, 62,221,133, 3, 98,227,
+229,229,107, 85,196, 92,105,220,196,207, 15,160,146, 73,177,244, 1, 18,169,183, 84,169,214, 13,215,219,198,172,197,218,176, 97,
+228, 69,146,155,134, 97, 55,137,178,213,157, 15,169,146, 23,146,104,222,102,209,168,124, 82,155,170, 21, 82, 44, 45, 97, 84, 1,
+222,187,137,118, 76,201, 36,149,100,146, 40, 54,220,173,193,224, 64,128, 55, 66, 72, 19,230,111,136, 55,239, 56,120, 80,223,187,
+103,114,113, 35,219, 25,247, 37,205,151, 4, 98,117, 86,199,165,142,185,141, 39, 87, 77,191,179,112, 45,111,155,135, 46, 53,123,
+118,237,188, 29,237,230,124,185, 37, 67, 54, 20,251,115,116,138,139, 69,144,209,200,236, 53, 35,124, 96,196, 45,225,236,160,100,
+118,182, 46, 68,243,228, 99,229,228, 98,101, 75,148,249,195, 38, 35, 25,100,121, 49,215, 10, 68, 64,232,203,164,198,131,152, 36,
+ 55, 27,214,121,148,165,183,119,100,146,100, 77, 22, 92, 14,189,108,249, 49,113, 99,101, 17,188, 73, 30,221, 30,226, 86,101, 63,
+157,125, 74,125,181, 86,126,242,159, 44,109,237,182,226,149,143, 37,246,151,201,154, 82,167,166,155,156,170, 4, 65,127, 56,244,
+239,118, 28,137, 31, 69,233,123, 59, 10, 36, 79, 79,151,147, 20,139,146,114,214,109, 72,238, 25,177, 70,222,235,121, 99,123,134,
+137,121,155,157, 92,111, 77,143,217,120, 0,225,244,178,178, 99,135, 13,112, 85,162, 6, 50, 38,109,181,131,227, 60,165,163, 38,
+254, 13,163, 77,254,138,160,166,157,253,181,187,238, 42,145,245, 14, 12, 51,228, 36,113, 74,143, 35,174, 60,163, 28,172,136,166,
+241, 51,187, 46,128,220,212,222,181,123,123,112,206,220,159,117, 92,248,150, 23,195,206, 56,201, 18,144,218, 80, 99,193, 45,181,
+143,155,226,148,241,242,168,175,103, 97,152,115,113, 31, 43, 37,240,242, 82,104,163,198,214,170,144, 46, 68,134,119,233,105, 64,
+ 75, 7,226,165,245, 88,112,243,189,237,163,104,109,168,101,152,167,151, 46, 92,201,253, 86, 84,211,244,193, 50,152,227,132,233,
+ 17, 36,106, 22,209, 14, 22,160, 47,232,248,173,106,131, 1,126, 28, 42,210, 47, 81, 11,218,204, 57,138, 3, 1, 98,104, 6,143,
+128,163, 69,140,217, 74,120,133,183,137,160,170, 18, 11, 6,211, 73, 6, 64, 23,138,246,246, 85, 33,100,109,210,197,251,210,192,
+132,226,104,192,199,122,166, 95, 44, 45,155, 86,147,192,222,172, 1,126, 92, 61,180, 5,133, 49,241,189, 54,168,249,208,244,105,
+ 22,190,163,206,158,220, 40, 2,218, 51,204,253, 53, 61, 49,223,159, 42,174,110,126,142, 84,196,243,189, 1, 99,165, 29,188, 41,
+ 24, 19,149,232, 23, 32,243,167,214,111, 64, 77,227, 85, 22, 6,169,102, 71,240,134,241, 20,118,185,107, 10,110,152,157,213, 15,
+203,205,189,194,136, 21, 6, 60,172, 35, 33, 24,131,226, 1,169,116, 39,255, 0,170,127,213, 53,180,160, 0, 20, 11, 1,192, 1,
+ 82, 0,121, 86,246,120,146,166, 68, 88,178,147,169,162,107, 15, 13, 38,172,193, 12,203,113,210, 96, 47,226,166,180,144, 85,132,
+ 22,246,212, 80, 85,226, 55, 46, 7,207, 93,187, 28, 11,222, 29,225,153, 54,214,132,225,238, 89, 6,109,247, 35,118,159,104,139,
+ 25,100,153,209, 96,103,199, 4,177,145,135, 42,226,123,227,105,158,126,243, 77,163,111,217, 27,110,205,200,233, 34, 98,166,100,
+153,254,166, 89,152,178,100, 38, 76,220, 88, 74, 29,127,218,245,173,185,247, 62, 62,205,220,189,231,181,111, 91, 79,241,125,135,
+114,221,178, 30,104, 58,175,142,203, 60, 19,202,209,188, 83,160,107, 27, 55, 17,110, 34,169, 79,189,239,251,159,222, 6,209,185,
+250,120, 59,127, 39, 28, 99, 13,166, 12,242,240,226,193,141,142,191,184, 89, 36,148, 6, 49,149, 83,118,241,189,100,165, 94,235,
+236,238,231,218, 54,244,220, 55, 45,203, 31,118,196,197,148, 98,100, 54, 38, 89,202,244,147,145,126,132,192,252,135,135,135, 10,
+239,251, 59, 11, 30, 94,210,197,129, 59,110, 61, 91,140, 71,167,133, 39,112,101, 97, 77,186,180, 67, 76,178,195,134,131, 65,185,
+ 94, 71,249, 43, 63,191, 35,198,197,237, 93,194, 45,145,182, 28, 72, 51,178, 98,204,222, 34,219,247, 83,159,147,145, 40, 98, 17,
+ 97,141,145, 52, 70,141, 33,107, 10,196,237,254,251,124,120,182,108, 89,251,103,248,183,113,108,209,152,251,123, 48, 73, 50,178,
+163,106,150, 62,166, 52,106,122,218, 53, 22, 78, 35,241,212, 73, 37, 68,168,188, 10,219,110,173,215,204,221,251,177, 92, 89,112,
+ 55,160,216,146,197, 12,155,148,105, 6, 36,110, 11, 70,204,146,232,132,153, 69,220,143,151,149,239, 94,229,135,135,144,152,176,
+ 33,199,149, 52,198,163, 67,130, 88, 88, 14, 12, 71, 2,107,199,126,230,167,200, 56, 27,180,153, 44,203,151, 38,239,138,210,198,
+ 85,181, 60,150,145,153, 25, 84,174,159,139,244,184, 3, 95, 67,141, 76,170,204, 10,177, 0,178, 92, 27, 31, 43,138,180, 33,149,
+209,151,163,110,155, 95,165,107, 88,243,234,222,223, 85, 42,213,240,250, 63, 29, 42,180, 33,134,255, 0,153,254, 28,127,176,181,
+ 26,147,255, 0,119,254, 28,127,176,181, 31, 26, 20,173,146, 62, 49,238,252,116, 31,101, 27, 35,231, 30,239,199, 65, 60, 79, 10,
+ 3,205,159,188,183,232,242,159, 7, 84, 70, 69,118,219, 53,104, 23,254, 32,249,175, 12, 38,220, 56,122,116, 15,111,231, 95,194,
+178,247,204,237,197,246,164,158, 28,163,139, 25,195,238, 61, 80, 66, 10, 41,108,124,193, 26,189,245, 95, 87, 16,111,225,198,220,
+235,212,191,133,109,189, 67, 33,195,131,168,102, 25, 69,250, 73,171,174, 23, 64,158,246,191, 80, 47, 13, 92,237, 80,155,100,217,
+178, 97, 72,178, 54,236,105, 99,136,202,209,163,193, 27, 42,153,201, 51, 21, 82,166,198, 77, 71, 87,157,248,208, 25,219, 14,102,
+227,150, 55,172, 76,172,145, 36,216, 89,175,139, 6, 72,141, 84,133, 56,240, 78,164,160,224,116,180,199,232,231, 92, 31,109,110,
+187,222, 58, 96,229,122,246,152, 73, 14,193, 22, 66, 74,161,245,174,102, 70, 68, 13,241, 49, 36, 50,171,124,195,137, 32, 94,189,
+ 86, 60,120, 33,105, 30, 24,150, 54,153,250,147, 50, 40, 82,239,164, 38,183, 35,230,109, 42, 5,207,128,170,176,236,187, 54, 48,
+ 43,143,183, 99, 68,165,146, 66, 18, 24,212,107,137,204,177,183,194,188,209,216,178,159, 2,111, 64,113, 11,191,238,216,216, 88,
+179, 99, 73, 22, 62, 34,207,156,114,186, 72,146, 50, 21,220,100,130, 55,158, 38,110,168,133,128, 96, 94, 49,125,126,202,189,247,
+129,184,238, 49,227,103,237,248,153, 62,150, 20,218,114,179,100, 96,160,188,140,175, 28, 74,129,184, 21,182,178,110,188,110, 71,
+211,212, 54,197,179, 76,208,188,155,126, 51,182, 59, 52,144, 19, 18, 93, 25,223,170,236,191, 15, 2, 95,227, 63,206,227,206,139,
+159,180,237,123,160,143,248,150, 20, 25,130, 45, 93, 49,145, 26,200, 23, 80,179, 0, 28, 30,118,227, 64,113,185,219,214,235,139,
+ 38,239,252, 57,146, 46,142,233, 42,207,209, 88,223, 37,161,143, 7, 30, 94,162, 69, 59, 1, 32, 87,113,212,211,241,104,229,198,
+171,237,251,174,251, 47,112, 75,139,143,185,169, 77,207, 62, 24,250,157, 45, 73, 28,103,105, 92,239,220, 36,135,225, 4,128, 5,
+253,231,137, 53,220,101,108,123, 54,104,101,203,192,199,157, 94, 78,187,137, 34, 70,213, 46,145, 25,145,174, 56,177, 69, 10, 73,
+240,225,202,166, 54,157,181,114,198,122,225, 64, 51, 5,173,146, 34, 78,168,210,141, 18,254,242,218,184, 35, 21, 28,121, 27, 86,
+ 88, 60,237,247,125,202, 4,254, 37,133,144,152,114, 97,237,219,254, 80,140, 32,104,164, 56,155,138,233, 66,142,109,119,211,197,
+185,241, 54,181,235,161,143,184,247, 92,173,217, 54,245,116,133, 37,221, 39,192, 91,160, 44,145, 38,214,185,201,207,155, 44,205,
+199,217,194,186, 9,118, 45,146, 97, 23, 95,109,197,147,162,204,240,234,134, 51,161,164,126,179,149,248,120,106,127,137,188,207,
+ 19, 68, 59, 86,214, 51,206,232, 48, 96,245,228,131,235, 58, 73,213,190,131, 21,250,150,213,125, 7, 79,187,133, 1,230,253,183,
+188,238,241,237,176, 70,153, 10,217, 89, 56,219, 20, 39,112,145, 53,200,131, 50,108,152,216,190,162, 67,149, 3, 74,234,252,227,
+198,252,170,230,111,117,119, 4, 88,115,180,121, 17,172,184, 24,155,182, 67,205,209, 82, 50, 27,109,205,143, 22, 50, 3,112, 85,
+145, 73,213,111,162,213,219,166,203,178, 69, 4,216,209,109,184,177,193,144, 2,207, 18, 67, 26,171,133,102,117, 14, 21, 69,236,
+206,204, 61,164,154,179, 14,207,180, 52, 2, 3,129,142, 98, 88, 91, 21, 99, 49, 33, 81, 3,144,207, 13,136,249, 24,168, 37,121,
+ 27, 80, 23,211,160,218,194, 21,109, 7, 75,133,177,179, 88, 27, 27,114, 54, 53, 48,128,240, 3,129, 20, 56,224,199,133,165,104,
+ 34, 72,154,119,234,206, 81, 66,151,147, 74,166,183,183,204,218, 80, 11,159, 1, 68, 14,171,204,251, 42, 1,244,175, 1,111,193,
+ 76,169,169,141,252, 60,105,204,145,158,108, 62,186,138,202,151, 99,170,128, 38,158, 36,120, 82, 43,194,202, 61,244, 54,156, 27,
+216,125, 54, 52,194, 96, 69,248,223,149,172,104, 2, 40, 30, 60, 77, 86,116,187, 27, 18, 7,128,169,245,124,129,191,186,212, 61,
+ 76, 71,219, 85, 2, 58, 72,225,170,164,169,126, 36,211,124,100, 95,144, 52,131, 58,242,250,234,130, 62, 45, 82, 21, 17,114, 73,
+243,167, 6,220,234, 0, 87,185,191,157, 17,104, 98,166, 13,168, 4,163,137, 62,211, 79, 37,136,167, 65,195,223, 73,249, 26,164,
+ 43, 51,217, 72, 28,205, 52, 62, 38,160,255, 0, 49,162, 67,200,212, 52,136,207,196,139,211,192,108,191, 93, 59, 33,119,224, 64,
+176,241,165, 24,178,253, 38,156,129,105, 82,209,168,241, 98, 77,207,144, 21, 93, 4,132, 29, 15,164, 33,184,250,120,209,165,111,
+236,208,126,141,207,211,194,160, 47,165,200, 31, 48,225,244, 84, 41, 44, 91,221,139,120,243,247,208,228, 80, 46, 7,157, 58,200,
+ 47,195,198,220, 42, 46,220, 56,248,154, 2, 22, 26, 8,255, 0,110, 21, 56,115, 94, 5,208,160, 16, 77, 67,154, 31,166,141,142,
+112,244, 1, 40, 58,189,246,173, 25, 38,251,137,146, 62,145, 64, 11,240,189,169,215,196,251,106, 83, 38, 9,140, 52, 71,247,151,
+ 26, 71,211, 77, 97,107, 80, 18, 39,203,240, 83,128, 10,143, 19,227, 81,183,157, 98,109,253,219,181,231,239,249,157,185, 16,150,
+ 60,236, 48, 75, 25, 21, 68,114,105,211,171,164,193,152,155,106, 28,192,160, 55,121,211, 1,115,236,242,172,248,119,156, 89,183,
+140,157,141, 86, 65,149,139, 10,100, 73, 33, 3,166, 86, 66, 66,133, 58,181, 95,135,149,104,219,233, 52, 2, 35,128,166,181,137,
+170,147,238,216, 88,251,150, 38,211, 43,145,151,154,178, 62, 60,122, 73, 5, 98, 26,156,150,228, 45, 87, 72, 38,128, 29,190, 48,
+124,174,127, 5, 90,198,136,170,252, 95, 49,226,104, 81, 45,222,254, 2,141, 60,233,139,143, 46, 67,130, 82, 20,105, 24, 47, 59,
+ 40,212,109,123, 86,163,212,141,135, 11,237,169,128,195,149, 96,118,199,117,237,157,219,130,249,251,104,145, 22, 57, 12, 82, 67,
+ 58,170,200,166,193,129, 33, 25,197,152, 30, 6,245,115, 98,223,113, 55,236, 71,204,196, 89, 18, 56,230,151, 29,150, 96,161,181,
+ 66,218, 24,141, 44,194,215, 28, 43,123,136,245,224,106,134,183,133, 17, 28,248, 10,128,101,169,171, 45, 69,212,180,234,120,142,
+ 6, 79,110,227, 96,253,228, 75,221, 88,103, 55,105,110,225, 49,206,169,110,164, 93, 89,164,140, 79, 23,136,100,213,126, 21,205,
+125,226, 77,178,231,253,226,118,235,225,110, 56,255, 0,194, 14, 30,222,145,238, 57, 10,179,192,177,163,186,235,158, 51, 96,214,
+183,196,173,111,109,171,220,166,251,182,236, 93,195, 43, 35, 51, 51,102,134,105,242,164,105,178, 28,153, 6,185, 29,139,179,176,
+ 14, 5,201, 55,174,123, 51,177,123, 15, 27,188,118,238,220, 94,218,195, 56,217,184,147,229, 60,197,166,234, 6,133,130,133, 31,
+188,211, 99,122,195, 84, 98,180, 60,203,239, 49,182, 60,206,213,193,108, 76,253,191, 47,116,219,243,167,130,105,161,151, 12,228,
+205,142,120, 68,250, 48, 99,137, 52, 31,152, 45,142,145,194,247,189,118,221,191,184,246, 94, 22, 55,221,210,247, 12,126,151,116,
+ 24, 41, 54,217,187,220, 42,134, 23,139,211, 78,223,160,218,248,106,224, 15,151,142,148,127,117,219, 26,103, 24,114,187,107, 12,
+ 98,117,228,117,200, 12,111,209,185,233,199,164, 75,123,218,222, 31,101, 8,253,220,108,239, 54, 28,139,218,184,178, 71,166,101,
+202,195, 50,241, 4, 55,238, 89, 28,203,111,148, 92,139,213,218,233, 81, 83,154,251,181, 68,105,251,134, 77, 43,172,119, 4, 33,
+101, 42,173, 96, 94, 91,142, 36,112, 53,244, 17, 4,242, 21,231,187, 79,107,207,178, 9, 49,118,190,222,199,196,199,200,120,229,
+151,211,206, 81, 67,198, 95, 75,221,165, 47,123, 53,122, 12,107,161, 21,110, 78,144, 5,201, 36,240, 30, 36,241, 53, 10, 63, 31,
+ 46, 54,165, 79,227, 74,128,192,126, 81,255, 0,135, 31,236, 45, 71,219,122,155,254, 96,255, 0,135, 31,236, 45, 67,143, 42, 2,
+182, 65,248,199,187,241,208,175, 68,201, 7, 88,225,225,246,208,104, 9,220, 92, 19, 76, 24, 3, 92,252, 29,209,141, 58,109,206,
+ 98, 49,166,225,149,153,134,172,236, 45, 25,194,245, 26,221,207,232,183,166, 54,247,209,227,238,109,134, 92, 87,205, 76,216,206,
+ 60, 79, 28,110,228, 48,248,166,183, 74,192,128, 72,147, 80,210, 71, 3,225, 66, 27, 5,135, 17, 81,230, 57, 86, 68,157,209,176,
+195, 28, 19, 73,157, 26,199,144,172,241, 49, 13,242,198,226, 57, 25,133,174,161, 24,217,181, 91, 79,141, 91,139,119,219,101,157,
+113, 99,201, 86,153,229,151, 29, 99, 23,185,150, 1,170, 84,229,249,162,133, 47, 1,111,166,144,246,214, 36, 61,213,182,203,157,
+155,181,179, 24,179, 49, 38,120, 18, 38,254,244,199, 2,101, 49, 67,109, 35,225,115,192,155,252, 38,167,133,220,219, 86,108, 27,
+107, 60,194, 12,141,207, 30, 12,152,113,159,139, 42,228, 46,184,213,216, 13, 32,183, 16,183, 63, 17, 6,212, 33,178, 13, 76, 90,
+177, 83,185,182, 7,108,149, 92,232,201,196,142, 89,242, 24,234, 1, 99,129,186,114,182,162, 44,116, 55, 6,183, 42,173,133,221,
+120, 91,132,197, 49,192, 88,151, 50, 76, 19, 36,141,160,177,139, 20,102,179,164,108,186,143, 6,177, 83, 98, 44, 77, 70, 83,162,
+ 54,165,107,138,195,143,186,246, 9,113,167,204,143, 62, 54,131, 28, 68,101,112, 27,150, 71, 8,116,141, 55,126,161,224,186,111,
+115,195,157, 79, 27,185,118,252,204,204, 28, 76, 22,245, 41,157, 30, 84,137,144,135,225, 83,134,209, 71, 34, 48, 54, 55,213, 55,
+224,168, 13,114, 40,177, 70,150,212,220, 73,161,220, 85,144, 52,168,176, 0, 84, 3, 44,113, 3,196, 15,101, 18, 36,142,196,233,
+ 28,234, 60, 45,127, 46, 85, 56,192, 10, 13,253,188,104, 9,170,174,174, 64, 83, 27,234, 0, 1,167,196,211,135, 91,113,112,191,
+ 77, 69,229,128,114,113,245,208, 18, 42, 0,231,196, 10,174,165, 72, 60, 47, 99, 83, 51, 37,142,147,115,245,208,250,170, 7,202,
+110, 61,134,128,145, 35,149, 0,241, 28, 20,223,149, 73,165, 6,215, 6,213, 18,227,219,245, 85, 64, 64,176,240,229,237,166, 37,
+173, 97, 77,168, 88,240, 52,197,188,135, 10,160, 96,105,201,248, 79,186,162, 79, 10,102, 39, 77, 64, 48,169,120, 83, 10,149,184,
+ 80, 19, 28, 0,168,202,108,132,212,237, 67,152, 93, 44,106,144,168, 1,118,225,227, 86, 21, 64,184,168, 66,156,111,245, 83,220,
+137, 9,246,214,120,179, 68,138,241,189, 13, 57,113,169,130, 75, 27,253, 21, 15, 42,160, 60,150, 36,183,146, 47,242,209, 18, 88,
+213,132,103,196,218,254,223, 42, 25, 54, 81, 33, 31, 9, 26, 26,132, 75,232, 1, 84, 88,252, 90,252,170, 20,147, 42,130,204,162,
+214,125, 32,143, 96,185,161,185,213,106, 40, 42,108,169,197, 99, 82, 75,121,179,115,161, 53,173, 84,130, 32,232,229,206,134,201,
+196, 27, 85,227,112,128, 16, 8,181, 68,233, 54,248,106,144,168, 0, 18,165,185,112,254, 90,186, 15,215,231, 85, 9,188,227,195,
+202,173,167, 27, 10, 2, 87, 21,230,114,109, 89, 25,153, 61,195,186,109, 67,255, 0,173,108,251,169,202,194, 0,113,117,232, 70,
+ 37,128,255, 0, 54, 85, 22,183,137,175, 77,210, 56, 15, 26,207,219,182,108, 93,179, 47,112,203,129,228,105, 55, 41,134, 68,225,
+200, 42, 24, 40, 75, 38,149, 91, 11, 15, 27,208, 51,139,198,238, 8,179,119, 61,231,184,182,223,138,219, 4,121, 49, 33,177, 43,
+ 36,102,118, 49,183,181, 89,116,154,175, 38,201, 20, 61,140,189,212,153,121, 31,199,134, 34,110, 63,196,140,242,107,234, 48, 18,
+152,244,235,209,167,142,141, 58,109, 93, 94, 7,106,236,155, 46,231,184,238, 56,218,245,110,128,140,140, 87, 42, 97, 80,196,179,
+ 8,215, 72, 32, 49, 39,133,205, 81, 94,200,219, 78, 58,237,199,115,206, 59, 48,109, 95,194, 76,171,209,176,109,125, 50,250, 58,
+166, 59,254,110,170, 16,197,220,246,172, 61,243,187,187,107, 35, 48, 76,141,186, 96,203, 54, 74,199, 52,145,217,210, 20, 32, 38,
+150, 26, 61,182,231,227, 94,135,184,229, 99,237,248, 25, 57,185,110, 83, 30, 8,158, 89, 89,121,133, 80, 73,211,111, 31, 42,202,
+222, 59,115,110,222,103,193,202,108,140,140, 44,140, 13, 99, 30,124, 41, 58, 46, 18, 64, 21,227,190,150,248, 72, 21,177,149,135,
+143,184,226,207,133,148,189, 76,108,152,218, 41, 80,240,186, 56, 42,194,227,216,104,138,121,107, 46, 70, 38,103,108,111, 91,118,
+215, 62,213,141,153,185,226,227, 12,204,140,233, 38,200,201,135, 38,252, 38,128,151, 85, 12,130,252, 90,226,189, 83,118,255, 0,
+253,102,111,248, 18,254,193,174,118, 15,187,220, 40,198,222, 50, 55,109,203, 38, 29,171, 34, 44,172, 8, 37,153, 12,104, 96, 55,
+ 68, 43,210,248,135,135,157,184, 2, 56,215, 87, 54, 58,100,227,203, 4,132,133,153, 26, 54, 43,204, 6, 26, 77,175,127, 58,220,
+ 81,147,203,182, 97,254,152,193,237,206,238,131,134,217,157,137,141,131,191,133,182,149,224, 18, 12,182,254,131, 29, 12,124,170,
+ 47, 60,208,246,116,207,143, 43, 70, 91,184,157, 75, 70,197,110,173,152,110, 46,190, 6,189, 19, 27,183, 54,220,110,223, 94,218,
+101,105,246,245,128,227, 17, 49, 5,217, 8, 35,137, 80,162,252,121,129, 89,184,221,139,178,193,219, 50,246,167, 83, 34, 76, 25,
+ 28,203,214,119, 94,186,185,113, 32,117,116, 69, 0,171, 14, 31, 13, 90, 63,128, 1,221, 19,207, 31,117,118,124,105, 35, 34, 75,
+145,148, 36, 69, 36, 6, 2, 11,141, 64,115,172,173,179,183,241,123,151,123,238,184,183,108,140,185, 98,131, 48, 69,141, 10,228,
+204,145,199,170, 32,218,213, 17,212, 18, 9,224, 13,192,242,173,236, 94,199,198, 77,199,111,221,115,119, 93,195,112,204,219, 89,
+219, 29,178,102, 70, 75, 58,232, 42, 80, 70, 7, 47, 17,196,248,154,218,218,246, 28, 77,175, 51,114,205,199,121, 30, 77,210, 97,
+145,144,178, 21, 42,174, 20, 37,163,210,170, 64,176,241, 38,174,218,235, 64,121,102, 30,212,185,255, 0,117,159,234,252,172,252,
+231,223,113,162,146, 92, 76,191, 85, 48,233,122,105,222, 20, 72,209, 92, 32, 26, 19,137,181,239,198,245,213,110,248, 24,221,199,
+222,157,175, 6,230,210,180, 83,237, 19, 75, 56,134, 89, 32, 46,127,118,196, 51, 64,200,218, 73, 60,129,174,135, 15,178,182,204,
+126,210,110,205, 73,103, 59,115, 71, 36, 70, 98,201,215,211, 44,141, 51,124, 93, 61, 23,212,220, 62, 10, 54,229,217, 88,123,150,
+ 86,223,157, 22,227,157,183,229,109,184,199, 14, 9,176,228,137, 24,198,214,190,190,164, 50,113, 58,124, 45, 88,104,154, 28,150,
+ 60,179,246,150,243,221,123, 54,213, 52,217, 91,102,221,181,255, 0, 21,197,198,158, 70,152,227, 76, 21,219,160,141, 33,102,210,
+246,213, 98,107, 3, 11,105,238,252,205,147, 3,125,217, 54,124,231,238, 41, 86, 28,196,223, 36,220, 96,209, 54,178, 36,116,120,
+ 27, 32, 14,147, 33, 42, 19, 72,183,143,141,122,214,203,218,187, 78,199, 14, 82, 99, 35,207, 46,121,213,159,151,150,230,121,242,
+ 13,180,254,250, 71,230, 0, 60, 7, 42,199,199,251,184,197,194,255, 0, 45,131,189,110,152,187, 70,173, 99,104,139, 33, 68, 2,
+237,168,198,172, 80,200, 35, 62, 43,171,233,169, 93, 40, 53, 49,101,218,191,212, 63,121, 57,176,110, 89, 25, 49,226,225, 97, 96,
+229,140, 8,166, 34, 38,152, 57, 32, 72, 7, 6, 81, 99,112, 57,215,164,107,111, 10,204,139, 97,196,199,223,178,251,133, 30, 67,
+151,153, 4, 88,210,198,197,122, 65, 33, 36,169, 81,167, 85,248,241,248,171, 70,222,102,170, 20,151, 34,122,155,240, 95,240,210,
+166,176,183, 63, 15,199, 74,169,117,248, 24,207,111,128,255, 0,195,143,246, 22,163, 82,127,238,199,252, 56,255, 0, 97,105,174,
+ 43, 38,138,153, 63, 56,225,225,248,205, 4, 90,254, 20,124,147,241,143,119,219, 64, 34,230,128,226,113,123, 29,177,100,219,243,
+ 33,139, 10, 61,203, 31, 47,113,200,203,204, 84, 29, 73, 35,203, 92,181,129, 75,152,245, 62,158,188,122,149,184,112,225,126, 21,
+153,254,155,238, 29,191, 15,171, 44, 73,147,149, 62, 94,204,197, 18,105,167, 58,241, 50, 23,171, 35,150,139,224,139,243,190, 17,
+100, 95, 14, 21,233, 54,183, 42,110, 23,160, 60,219, 39,182,183,227, 43, 97, 71, 4, 70,109,207,111,222, 19, 42, 86,105, 61, 62,
+ 59,110, 89,145, 75,161,100, 17,157, 76,138,247, 10, 64,213,164,214,182,205,180,186,119,174,231,152,129,255, 0,135,226,198, 4,
+ 44,232,200, 14, 94, 66, 67, 22, 67, 33, 96, 3, 89, 49, 18,228,112,248,205,118,118,242,165, 99,206,128,227,223,182, 55,105,119,
+121,164,102,129,112, 31,113,147,117,142, 85,119, 51, 93,176, 63,135,172, 44,134, 48,163,226, 58,137, 12,120, 85, 76, 62,200,220,
+ 49,242,118,174,183, 74,120,241,160,218,211, 33,253, 78, 76,105, 28,187,104,248,138, 99,199,162, 57,245,144,165, 26, 79,151,143,
+ 15, 10,238,238,105, 95,141,232, 14, 30, 78,199,220,228,197,146, 6,155, 29, 89,177, 55, 72, 20,221,200,234,102,231,166,124, 23,
+ 26, 7,194, 21, 44,254, 71,149,232,240,118,206,241, 46,104,220, 50,253, 52, 47, 38,229,145,158,240,199, 43,201,166, 57,182,223,
+225,232,154,140, 73,118, 18,113, 60, 45,111,170,187, 43,220,210, 28,124,168, 15, 62,151,182,119, 45,155,109,143, 49,204, 83, 73,
+129,141,177,198,177,196, 38,144, 52,187, 99, 72, 38,212, 35,137,164, 17,158,173,195, 42, 49, 28,202,240,173, 62,210,218,243, 2,
+ 99,238,153,152,201, 28,134,109,214, 75,182,184,221, 87, 55, 45,102, 66,144,200,154,172,235, 29,254, 34,164, 11,112,227,195,174,
+226, 5, 43,240,172,129, 31,150,244, 93, 62,108,222,235,154, 24,177, 0,123,168,164,113,225, 80, 13,211, 83,207,143,176,154,152,
+141, 15, 13, 60,233,128, 60,237,111,109, 72,159, 26, 1,155, 66,139, 90,149,134,145,224, 57, 84, 77,152, 11,155,241,169, 51,170,
+242, 34,254, 92, 40, 9,128, 60,120, 82, 38,213, 3, 42, 88, 29, 87, 62, 85, 14,160, 60,193,250,141, 80, 72,183, 11,120, 94,163,
+117,225,198,162,231, 80,249, 72, 30,102,154,195,202,128,123,175,157, 53,213,141,188,105,185, 48,169,112,184, 62, 53, 64,136, 21,
+ 9, 56, 39,188,212,137,227, 80,147,144, 30,218,128, 97,206,164,124,191,219,157, 68,115,169,131,241, 1,238,161, 2, 80,103,229,
+106, 41, 54,170,242, 27,145, 84, 18, 78, 2,133,172,107,177,241,162, 19,101,181, 13, 20, 30, 36, 94,162, 70,153, 43,143,136,138,
+135,128,189, 64, 48, 91,168, 22, 21, 54, 95,134,212, 97, 23, 35, 96, 21,145,184,131,107,211,201, 18, 24,244,139,233,240,170,235,
+ 37,133,173,254,192, 82,235,158, 64,154,148, 41, 38,210,171,161, 56, 10, 9, 55, 62,234,145, 96, 87,157, 51, 88, 11,143, 35, 84,
+132,227,148, 76, 15, 11, 91,157, 44, 56,186,165,245, 19,111, 14, 62,250,134, 48,210,141,127, 31,178,173,225,170, 32,109, 0,241,
+ 2,247,243,170, 66, 45,131,103, 87, 86,189,188,253,212, 67, 3,143, 11,209,217,172,188, 60, 42, 9, 37,198,162, 45,127, 10, 10,
+130, 42,203,206,153,125,156,105,222,112,218, 66,158, 12,108,105,214,195,149, 1,157,151,253,177,160, 14,116,124,145,121,218,220,
+169,149, 13,239, 64, 58,196,229,194,113, 7,135, 47, 42,214,133, 2,128, 7,133, 1, 84, 25, 75,251,135,213, 86,227, 21, 80, 38,
+ 71,133, 61, 56, 23, 54,169,149,173,163, 13,144,226,105,194,211,218,222, 53, 52,189,105, 10,212,136, 4,114,162,169, 62, 53, 32,
+ 9,240,162, 42, 15, 26, 74,188,133,104, 73, 7,141,232,160,218,152, 40,181, 72, 14, 53,128,209, 32,212,204,205,249,181, 43, 82,
+179, 84,208,210, 6, 88,248,138,129,183, 58, 54,155,243,168,148, 21, 83, 69, 33,195, 79,245,127,251,212,170,122, 69,190,143,199,
+ 74,173,127, 16, 98, 73,127,221,255, 0,135, 31,236, 45, 71,202,166,227,130,127,135, 31,236, 45, 68,242,172, 2,174, 79,246,163,
+221,248,232, 86,183,178,139,147,109, 99,221, 66,250, 62,154, 1,136, 38,157,172, 57, 82,168,155,208, 10,252,105,248,211, 10,152,
+ 23, 23,231, 66, 17,229,194,155,223, 83, 35,141,237, 75,199,144,160, 26,222,218,110, 34,158,192,120,210,230,121,240,160, 28,113,
+ 28,105,236, 41,135,143,178,157, 77,239, 89,101, 18, 71,172,233,189,172, 47, 68,232,155,241,115,248, 41,225,252,239,163,141,168,
+166,237,207,194,160, 0, 81, 75, 42,130, 79,152,189, 19,163, 17, 54,177, 62,194,105,180,218, 78, 64,123,104,132,248,139, 92, 26,
+ 1,214, 8,237,193, 64,168, 50,168, 54, 0, 81, 53,248,222,245, 2,202, 56,155,113,160, 35, 96, 89,109,239,162, 17,171,133,168,
+ 34, 68,215,243, 11, 84,218,104,248, 85, 4,103, 94, 10,183, 63, 69, 7, 74,222,215, 52, 71, 99, 39, 17,203,218, 42, 58, 15, 61,
+ 92,104, 6,208,188, 13,170, 54, 0,139, 84,237,252,227,194,162, 64, 4, 90,128,102,168, 63,133, 19,153,161,191,205,244, 80, 12,
+ 62,106,159,247,149, 5,231, 78,198,207,127, 97,161, 2, 57,225, 85,205,181, 15,109, 88, 83,169, 65,160,200, 44,254,234,160, 71,
+198,153, 79, 11, 82,189, 9,195,169, 58,121, 26,134,137, 88, 53,248, 15, 97,169,181,200,250, 5, 2, 57, 26,225,124,205, 90,140,
+160, 36,185,176,224, 56,209,132, 10,252, 62,131, 81, 60, 15, 31, 34, 42,221,161,117,109, 62, 7,249,106, 13,142, 15,178,245, 10,
+ 87, 22,191, 30, 85, 54,182,158, 30, 86,169,188, 4, 14, 7,253,191,216,212, 24, 89, 61,188,168, 9,142, 17,147,254,220,168,155,
+123, 49,141,137,227,241,126, 42,129,225, 11, 95,157,143,242, 84,240, 56, 68,222,214,173, 35, 44,180,124, 41,141, 47,166,149, 8,
+ 86,149, 66,188, 96,114,189,205, 16, 92,159,101, 66,127,237,163, 95,125, 20, 3,110, 28,232, 82,132,214,235, 55,149,255, 0, 21,
+ 78, 53,212,109,238, 38,161, 37,204,173,239,171, 17, 45,184,248,208, 22, 35, 21,109, 5,133, 86,136, 85,181, 28,133,105, 34, 18,
+ 28, 5,252,105,174,124,233,201, 20,173,126, 85,184,163, 60, 69,195,196,212,209,194,242,161,149,164, 5, 86, 97,166,157, 75, 33,
+201,241,162, 41,246,213,117,176,169, 6,227, 87,145,164,215, 50,200, 99, 68, 6,130,188, 71, 58,150,150, 28,107, 45, 34,238,168,
+117, 97, 82,214, 60, 42,182,163, 82, 12,107, 46, 37, 65,175,126,116,223, 8,168,131, 76,199,202,148, 52,210, 37,194,223, 71,227,
+165, 81,185,211,253, 95,199, 74,148,252, 73, 68, 99, 57,224,159,225,199,251, 11, 81,189, 73,199,201,254, 28,118, 63,212, 90,136,
+ 28,252,171, 37, 43,100, 31,140,113,240,160,158, 34,173,188, 61, 67,125, 86,240,183, 63,199, 81, 24,191,207,191,209, 64, 85,177,
+167,183, 11, 94,172,250, 81,111,155,233,181, 33,139,252,239,193,249,104, 10,192,123,105, 10,179,233,136, 63, 63,224,252,180,189,
+ 48,253, 63,193, 64, 87, 44, 8,243, 52,194,252,237, 86, 6, 47, 31,159,240,126, 90,113,142, 57, 22,252, 20, 0, 62,129, 77,198,
+220,232,254,159,249,223,131,242,210,244,198,255, 0, 55,224,252,180, 0, 7, 30, 53, 43, 11, 94,141,233,237,249,255, 0,130,159,
+211,255, 0, 59,240, 84, 96, 18, 7, 0,133,181,185,241,169,252,100,139,176,191,141,133, 26, 60,114, 20,141, 92,205,249,126, 90,
+151,167,254,119, 31,117,100, 0,233,241,212,206,111,244,114,167, 17, 90,255, 0, 17,227,237,163,244,180,143,154,254,241, 78, 34,
+ 35,155, 95,203,133, 80, 86, 49,174,174, 60,173,200,154,114,136, 0,176, 31, 85, 24, 68, 6,171,183, 63,103,229,167,232, 3,195,
+ 87,183,149, 0, 13, 34,246,176,164,193,121, 27, 81,154, 37,241,113,127,119,229,168,116,211,135,197,171,203,135, 26, 2,185,123,
+ 49,225,122,142,178,220, 0,250,232,230, 0, 73, 58,255, 0, 5, 68, 64, 0,249,191, 7,229,160, 2, 3,113, 23, 28,106, 60,117,
+121,213,161,142, 79, 38,252, 31,150,155,211,113, 63, 23,224,160, 43,220,131, 80, 98, 73,227, 86,253, 53,255, 0, 59,240,126, 90,
+131, 99, 92,159,139,240,126, 90, 2,186,243,168, 76, 72, 97, 97,194,223,203, 87, 6, 53,191, 59,240,126, 90,113, 0, 13, 98,220,
+199,149, 1, 70, 57,116,130, 41, 51,234,227,231, 87,219, 14, 35,196,159,193, 85,155, 12,107,178,191, 15,119,229,160, 2, 1, 35,
+233,169, 63, 20,107,120, 3, 86,125, 37,128,248,252,124,191, 45, 52,152,191, 3,124,118,184,242,252,180, 41,155, 23, 23, 23,163,
+184,248, 73,246,209,163,194,211, 32,248,252, 47,203,217,239,162,182, 30,165, 54,107, 11,249,126, 90, 48,138,216,205,102, 32,242,
+ 35,249, 42,209, 38,212,240,225,105, 23, 47,199,221,249,104,190,155,143,207,127,163,242,212,101, 42,200, 79,133, 6, 78, 11,111,
+119,242,213,247,199,254,117,175,195,151,229,170,242, 98, 94,195, 95,143,151,229,160, 4,126, 36,208, 57,159, 26, 44, 3,163, 3,
+ 22,227, 99,200, 84,198, 45,191, 63,240,126, 90,103,130,224,168,126,126,207,203, 90, 50, 68,102,192,120, 88,131,237,169, 28,172,
+114,164, 18, 69,252,106,175,163, 55, 54,127,193,249,105,122, 54,253, 63,193,249,104, 7, 71, 15, 50, 11,234,176, 55, 53,117, 79,
+219, 64,197,194, 33,245,234,229,236,252,181,115,211,241,190,175,193, 66,153,197, 63,124,215,240, 63,203, 71, 81,202,140,216,250,
+152,177,110,126,207,203, 83,143, 27,143,205,248, 40, 66, 81,175, 10, 56,224,180,233, 0, 3,139,112, 28,233,139, 37,237,196,129,
+236, 31,109,105, 52,184,146,143,144,173,194,144, 54,167, 5,125,191, 80,251,105, 89, 79,159,212, 62,218,187,215, 83, 31, 95, 66,
+ 65,133, 72,113,229, 81, 10, 61,191, 80,251,104,128,168,240, 63, 80,251,106,239,143, 84, 90, 75,160,214,106,112,188,121, 83,134,
+ 3,192,253, 67,237,169, 9, 71,232,159,168,125,181,119,199,168,113,125, 2, 37,133, 28, 63, 11, 85, 81, 34,254,139,125, 67,237,
+169,137,208,126,107,125, 67,237,168,229, 30,165, 81,240, 15,196,248, 83,133, 52, 31, 84,159,162,223, 80,251,105,122,181,253, 22,
+250,135,219, 89,220,186,136,169, 46, 40, 61,175, 77,166,132, 50,208,126,107,125, 67,237,164,114,227,253, 6,250,135,219, 83,114,
+234, 89, 38,248, 6,211,252,159,142,149, 11,212, 46,157, 86,111,151, 87,135,233,105,243,165, 87,114,234, 74, 63,129,150,224,124,
+ 23,230, 99,143,246, 22,161,196, 30, 20, 83, 19,176,141,129, 91,116,227,230,234, 15,200,190, 4,138,110,139,255, 0, 51,245,211,
+253,234,134,129,243,227, 74,227,143,242, 81, 58, 47,126,105,250,233,246,211,244, 30,255, 0, 50,114,227,241,175,251,212, 7,152,
+108, 43,151,151,189,246,219, 77,148,207, 10, 63,112,200, 33,113,171,227,135,112,233, 43,106, 39,158,137, 52,175,232,129,195,157,
+ 27,119,238,253,255, 0, 3, 59,120,219,161, 49,153,182,181,204,203,102,116,186,140, 83, 22, 49,195,102,247, 62, 75, 95,207,166,
+107,183,197,135, 99,235, 65,232,142, 15, 87,252,215,164,232,190, 62,191,237, 71,173,233,104,107,255, 0,107,110,173,191, 59,230,
+227, 85, 32,218,182,156,125,227,120,206,201,205,131, 35, 59, 42, 8,134, 94, 60,242,227,218, 28, 52, 18,104, 86,140, 88,136,201,
+103,187, 63, 63,162,128,231, 87,184,247,188, 77,204,109, 25, 19,166, 80,135,112,155, 17,243, 12, 74,157, 88,215,106, 59,146,139,
+ 39,194, 25, 36,176, 54,240,171,178,111,155,164,189,163,219,251,140,114,164, 57,219,199,240,200,230,200, 8, 10,198,115, 58,125,
+ 87, 68,111,134,255, 0, 17, 10, 15,137,171,237,141,217, 35,106,129, 92,237, 63,194, 4,228,227, 22,151, 20,227,250,139, 49, 58,
+ 11, 62,142,165,181, 95,198,215,171,217, 16,108,109,177,170,228,122, 31,224, 38, 40,194, 23,151, 28, 98,116, 78,158,142,147,171,
+166, 23,229,209,111,101,170, 3,207, 49,119,253,251, 11, 99, 99,139,154,170,216, 88,219,222,233, 36,178,198, 36,245, 47,137,184,
+ 73, 26, 64, 53,183,194,150, 54,248, 77,197,214,222,221,188, 78,226,222,167,238,104,177,164,149, 87, 6, 77,206,109,184,226,116,
+134,160,137,182, 46,226, 24,201,243,106, 18,112,247, 86,211,193,217,205,135,183,220,109, 3, 4, 74,231,108,253,238, 40,135,173,
+212, 61, 79, 79,102, 11,171,169,243,105,252,238,124,106,240,135,103, 57,163, 71,160, 25,222,165,237,165,241,250,222,175,160, 53,
+254,118,174,175,167,231,249,218, 63,155, 64,115,155, 6, 38,225,182,247, 81,218,103,220, 95, 46, 12, 45,143,111, 77, 46,182, 14,
+235, 38, 68, 13, 53,139, 53,153,140, 90,137,185, 60,109,126, 2,177, 31,189,187,133, 50,223, 3, 84, 70, 69,118,218,131,104, 23,
+254, 35, 38,116,144, 64,109,195,135,166, 69,123,127, 58,252,133,122, 11,193,183, 29,218, 62,161,195,254, 51,208,110,149,222, 1,
+149,233,245,124, 90,126, 46,167, 79, 95, 63, 11,213, 67,143,219,190,160,234, 59,111,168,245,171,170,242, 99,107,245,253, 51,162,
+255, 0, 21,253, 71, 78,246,252,237, 62,202, 3,140,151,188,247,200, 97,223, 39, 73, 86,100,199,219,242,243,176,165,104, 81, 34,
+ 18, 99,100, 54, 56, 17, 40,115, 35, 71,224,122,160, 18,192,219,133, 30,125,199,123,200,220,112,113,102,220,191,240,125,200,112,
+ 90, 68,141, 83,171, 9,219,142, 88, 87, 85, 54, 32, 23,101,183,184,243, 21,190,152,221,144,173,151,161,182,109, 69,103, 57,223,
+189,195, 39, 70,161,234,122,223, 23,203,170,221, 75,240,191, 58,187,147,143,219,182,127, 88,118,219,122,196,234,117,100,198,255,
+ 0,199,232, 78,158,173, 77,253,190,141, 58,127, 58,214,160, 57,157,239,115,222,240,187,190,120,112, 51, 76,113,100,227,109, 88,
+232,140,129,210, 15, 85,155, 60, 13, 40, 82,108, 95,225,176, 39,153, 96, 15, 32, 43, 99, 23,120,222,230,237, 28,252,213,147, 28,
+110,120,147,102, 97,193,149, 57, 88, 97,149,241,242,100,197,142, 79,136,132, 26,244, 15, 29, 58,189,149,115,116,198,237,179,144,
+195,121, 59,111,170, 56,228, 55,170,151, 24, 75,233,181,139,255, 0,104,218,186,122,237,236,213,237,171,139, 30,210,187, 33, 86,
+ 24, 45,176,244, 72,185,146, 15, 73,208,247,234,233,232,252, 21, 1,192,100,119,167,116, 44, 71, 31, 16, 60,249, 24,113,229,207,
+144,179, 71,139, 3,131,143, 36, 81,172, 57,173, 52,241, 68,170,189, 67,169,160, 45,205, 72,241,173,204, 46,224,223,178,123,189,
+246,254,153, 27, 88,205,159, 0,179,250,117, 64, 33,196, 25, 33,146,242,250,135,148,191, 49,211,211,160,251, 47, 90,190,159,176,
+198, 46,223,212, 59, 63,167, 73, 95,248,118,169,113, 58,125,109, 74, 36,232,252, 86,103,215,167, 85,184,234,181,248,214,140,112,
+246,224,223,221,227, 59,127,250,131, 69,164, 1,224, 57,154, 2,175,204, 47,212,182,141, 63, 69,188, 45, 64,112,125,220,251,154,
+247,107, 65, 6,227, 36, 80,176,216,122,112,129,240,163, 75,185,201, 19, 53,131, 11,252,159, 23,233, 3, 99,192, 83,227,239,219,
+196,171, 20,226, 76, 87,220,215,109,222, 18, 44,188,157, 49, 43, 75,139,185,195,131, 14,162, 74,198,186,197,184,114, 45,111, 10,
+238,183, 24,187,103,248,158, 63,241, 83,183,127, 22,180,126,147,212,182, 63,169,183, 89,122, 93, 46,161,215,110,190,157, 54,252,
+251, 91,141, 14, 72,187, 75,160,226, 67,181,244, 12, 57, 93, 77, 79,141,163,161,214, 30,183, 85,205,180,117,237,213,240,215,243,
+113,160, 57,225,220, 59,148, 61,143,189,239, 29, 66,219,142,216, 50, 66, 12,136, 86, 57, 99,120, 87, 82,199,144,145,147, 17, 97,
+126, 38, 51,164,139, 80, 19,121,238, 25,179,100,217, 61,122, 69, 47,241,108,140, 47,226, 70, 4,184,134, 28, 4,220, 21, 4,103,
+224,185,119, 34,231,243, 71,159, 26,234,113,160,237,165,216,165, 92,115,183,127, 0, 11, 32,200,210,248,231, 19, 77,207, 87,170,
+117, 24,249,223, 86,175,166,161,184,193,218,173,139,150, 55, 67,182,250,111, 82, 61,111, 94, 76,112,158,171,166,182,235, 23,107,
+117,122, 90,126,111,139, 77,188, 40, 15, 60, 27,230,237,157,185,237,155,158, 84,131, 70,126, 39,110,206,248, 12,135,164,143,149,
+158,241,188,145,139,240, 60, 11, 3,237, 30, 66,175,203,221, 93,192,152,145,102, 71,151, 20,210,110,121, 15, 6, 62,221, 18, 69,
+234,113,213,115,253, 16, 48,245,154, 56,223,224,248, 73,149,173,212, 35,195,133,118, 89, 80,246,183,173,196,245,167,108,245,250,
+ 34,244, 29,103,198,235,116,250,171,209,232,107,109, 90,122,218,116,105,252,235, 91,141, 86,124, 94,200, 45,186,117, 27,105,214,
+228,127, 24,188,184,183,191, 82,195,212,252, 95, 9,234,254,151,231,251,106,130,164, 27,246,226,189,147, 62,243,156,241, 98,103,
+194,153, 1,164,101, 89,213, 76, 51, 60, 8,236,152,174,232, 92,133, 4,170,189,131,112,172, 21,221,183,205,198, 77,152, 79,149,
+ 38, 52,152,253,195, 38, 4,193,146, 37,146, 72,215, 18,105,149,103, 16, 59, 69,113,197, 72, 83,110, 71,152,174,227,211,236, 39,
+ 99, 35, 86, 15,240, 30,137, 6,210, 65,232,250, 22,227,199, 87, 79, 69,190,138,163, 22, 63,102, 46, 42,136,142,209,233, 6, 76,
+ 65,109, 38, 33,143,213,233, 29, 30, 58,173,214,211,109, 63,157,110, 84, 6, 94,239,188,111, 56,253,203, 22, 12, 57, 73, 6,223,
+ 43, 65,140,142,145,199, 58,172,211, 9, 9, 76,161,171,173, 28,141,240,152,184,104, 63,157, 92,191,109,119, 54,247, 14, 47,110,
+227,156,198,204,142, 68,219,162,203, 13, 26,157, 35, 55,168, 63,127, 52,143,212,105, 62, 31,131, 64, 63, 41,215,206,189, 22,108,
+126,218,254, 55, 11,100,182,221,252,116, 0, 32,234, 73,143,234,236, 67,105,208, 25,186,156,181, 90,222, 23,246,214,102, 54, 55,
+221,247, 94, 54,198,109,143,175,117, 17,116,228,194,213,171,172,116,105, 10,220,250,215,181,191, 58,254, 52, 7, 53,147,185,247,
+ 6, 94, 62,203,186,201,185,116,214, 93,239, 47, 25, 49,226,136, 42,136,241, 87,112,141, 85,219, 85,223, 80,131,136, 60, 57, 30,
+ 98,167, 7,119,239,121, 56,152,236, 38,138, 41,103,199,237,199, 50,244,193, 8,251,180,175, 22, 75,105, 38,220,128, 42, 60, 43,
+180,158, 14,218,244, 48,250,131,182,250, 15, 84,125, 55, 81,241,186, 62,179,170,247,233,234,109, 61,110,174,190, 95, 22,171,248,
+214, 43,237,157,135,149,130,241,226,228,109, 80, 96,199, 62, 28,249, 45,137, 62, 26,163, 24,166, 50,227, 71, 57, 4,169, 71,112,
+202, 20,243,226, 22,128,210,237,189,210,125,203,110, 97,155, 42,201,149, 14, 78,102, 47, 81, 64, 94,178, 98,100,201,140, 38, 8,
+ 60,194,139,219,133,235,139,155,188,119,252, 92, 28,204,238,188,115, 51,226,111, 51,193, 31, 72, 1, 3,237,153,107,141, 17,107,
+ 27,176,117,127,138,254, 54,181,119, 88, 24, 59, 7, 95, 6,109,166, 76, 59,199,139, 52, 88, 49,226,205, 6,147,140,210,196,102,
+104,196,109,241, 40,145, 18,228,112, 7,218,107, 51,107,218,251, 43, 6, 29,194, 24,242, 54,220,146, 70, 67,238,114,205, 62, 36,
+143,210,146,121, 38,153,114, 72, 35,247,105, 35,149,248,135, 11, 0,121, 84, 97, 25,153, 59,239,114, 97,247, 4, 59, 80,111, 85,
+ 6, 52,152, 17,229,206, 87, 30, 24,152,103, 75, 34,187, 55, 82,101,148, 21, 65,104,150, 53,107,149, 58,175,122,162,253,201,220,
+204,249, 88,163, 38, 38,201,149,213,241, 98,140, 99,145, 44, 7, 36,199,171,108,152,201,210,149,186, 66,218, 38, 58,181,223,194,
+187,124,188,126,223, 59,214, 35,103,157,191,248,192, 91, 97,117,164,199,245, 58, 73,107,116,131,182,190,122,173,111,111,182,179,
+164,196,236, 51, 30, 96,213,179,104,121, 80,238, 31,189,196, 22,125,109,167,170,117,240,110,165,237,127,206,191,141,232,138,100,
+230,238, 18,110,125,175,179,205,145,145,212,143, 63, 55, 15, 31, 54, 84, 86,199,213, 19,101, 8,158, 55, 91,221, 53,105, 8,224,
+ 27,113, 32,112,170,219,142,211,177,171,224, 99, 96, 60,178,164,123,210,225,228, 70,207, 42,172, 65,226,121,223, 18, 59,104, 6,
+ 48, 88, 48,181,236,120, 95,133,135, 94,248,251, 17,217,173, 57,192,254, 2, 97, 80, 47, 38, 56,195,232,254,109,190, 46,158,139,
+218,222, 20,248, 24,221,180,152, 56,137,183,182,220,112, 68,246,194, 48,201,142, 98,245, 63, 23,246, 37, 90,221, 95,155,151,197,
+206,128,243,125,211,212,227,238, 59,166, 68,104,241,193, 6,240, 49, 23,113, 76,135,215, 26, 29,190, 29, 56,190,159,130,152,221,
+154,197,181,112,213,123, 87, 95, 46,253, 62,199,216, 88,219,164, 48, 73,149,147, 22,212, 39, 67,160,200,130, 72,241,132,129,167,
+179, 43, 4,212, 56,155,214,214, 76, 29,188, 98,159,213, 29,191,165,234, 87,213,117, 31, 31, 79,172,208,154, 58,186,154,221,109,
+ 26, 45,127,138,214,246, 85, 13,179, 31,177,189, 38,227,252, 13,182, 83,131,211,255, 0,234,199, 14, 76, 62,151, 75, 75,255, 0,
+226,186, 77,167, 70,157,127, 63, 11, 95,219, 64,101,238,155,148,153, 59,226,203,162,124, 72,142,199,185,183, 70,112, 99, 58,227,
+151, 18,207,166,228, 92, 6, 54, 53, 75,116,202,220,113,182, 62,202,201,199,200,116,110,164, 29,120,128,185,152,141,190,121,116,
+ 57,230,110, 82,214,243, 55,230, 5,117, 91,254, 47,110, 52,112, 14,230,109,187,166, 25,142, 55,241, 9,113,192,184, 31, 30,142,
+187,121,124,214,240,231, 71,220,241,246,159, 79,143,252, 84,225,122,126,180,126,151,213, 73, 6,142,191,247, 61, 46,171, 91, 95,
+232,219,143,149, 1,207,246,150,247,186,230,206,216,251,158, 66,102, 9,118,236, 29,205, 38,142, 49, 24,141,179, 58,193,224,248,
+ 73, 5, 71, 72, 21, 39,141,188,235, 11, 35,188,247,168,240, 50,114, 81,162,234,197,183,239, 89,107,116,225,212,192,207, 92, 72,
+ 56, 95,151, 76,241,243, 53,219,108,248,155, 24, 92,143,224, 45,129,164,201,124,159, 69, 46, 57, 29, 66, 63,188,233, 55, 59,121,
+214, 70,110,213,217,153,176,238,248, 99, 39,108,198,159, 34, 28,132,220,242, 49,178, 48,211, 34, 56,217,148,100,180,143,168,149,
+179,233,215,168, 91, 85,175,198,169, 12,201,247,157,237,115,178, 59,127,214,198, 26, 60,217,160,109,200, 68,191, 28, 73,182,141,
+196, 70, 18,250, 65,214,246, 36, 27,233, 30,124,106,174,211,220,123,172, 16,118,190, 44, 83,117,160,124, 93,154, 44,200,204,106,
+ 64,245,177, 16,205, 60,210, 56,145,164,109, 58,147,166, 8,224,117,115,174,177,113,187, 47,248, 81, 19, 29,163,248, 95,169, 45,
+198, 92, 95, 79,234,172, 88,241,213,163,169,107,240,231,110, 28,168,141,143,217, 30,163, 21,152,236,254,163,163,140, 48,111, 38,
+ 38,174,134,161,233, 58, 35, 87,201,170,221, 45, 60, 63, 70,128,224,225,238, 78,232,219, 23, 55, 27, 14, 86,206,120, 50, 55,124,
+166,103,244,232,182,198,206,244,235, 28,175,149, 52, 90, 33,226,111,162,236, 46,160,112, 28,123, 30,247,238, 12,238,218,197,198,
+220, 96,210,113, 91,212,195, 50, 21,212,198,115,141, 36,184,150,247,203, 16, 79,235, 10,181,145,143,216,135, 39,252,217,217,189,
+ 82,229, 49,110,164,152,130, 79, 87,240, 7,213,118,185,151,228,189,248,252,190,202,179,220,155, 86, 14,124, 24,127,197,179, 99,
+197,194,199,202,134,102, 71,150, 4,142,105, 81,195, 65, 27,188,167,198, 64, 56, 41, 26,185, 80, 28,172, 61,193,220,112,231, 71,
+234,167,142, 69, 25,207,180,203,132,177, 0, 67, 69,183, 28,211,149,172,124, 92,100, 91,219,229,210, 71,190,133,143,222, 27,254,
+ 78, 22, 63, 74, 88, 99,200,200,199,237,182, 18, 24,131, 5,147,119,149,226,201,109, 58,133,197,128,210, 47,194,187, 53,199,216,
+ 63,141,179,106,192,254, 57,211,179,254,242, 15, 85,211,176,230, 53,117, 52,233,183,209, 85,246,200,123, 21, 98, 97,180,157,156,
+199,212,198, 45,233,159, 16,142,169,145,189, 29,244, 55,205,213,191, 75,249,223, 45, 0,219,246,235,159,180,207,177, 97, 71, 42,
+200,115, 30,120,179, 37,116, 0,191, 71, 10,124,128,192, 14, 11,121, 34, 4,219,221, 92,156, 61,223,191,105,217,247, 9,230,140,
+226,229, 97, 96,203, 42, 66,137, 34, 28,156,140,118,158, 88,114, 2,183, 90, 23,127,135,162, 66,232,243,174,235,123,131, 98,120,
+ 34,255, 0, 82, 54, 8,199,234,169,135,215,188, 33, 58,193, 91, 78,142,179, 91, 86,157, 95, 69,234,156, 56,253,155,252, 67, 5,
+177,219,106,254, 32, 33,140,109,189, 57, 49,122,189, 2,135,163,233,194,182,173, 29, 59,232,211,249,183,183, 10,203,117,124, 10,
+142, 71, 3,186,251,170,125,176, 60,197, 32,159, 38,109,152, 99, 79, 50,227,177, 11,186, 77,210,150,208,226,207, 39,238,212, 88,
+198,100, 33,141,248,242,174,163,185,115, 55, 60, 53,218, 54,204,108,197,134, 76,222,186,229,102,180,106, 75, 12,124, 73, 39, 33,
+ 83,130,175, 81,146,230,220,133,237,231, 86,118,232, 59, 49,113,152,109,103,106,244,199, 38, 18,222,157,241,140,126,172,186,156,
+127,145,173,213,215,167,167,227,123,105,171,251,236, 59, 27, 97,160,238, 51,133,232,250,170, 99,245,239, 8,143,170, 3, 21,211,
+214, 58,117,105,213,244, 95,194,158,192,121,238,201,221,155,244, 81,246,238, 30, 60,102, 92, 72,176,118, 52,203,146, 67, 0, 71,
+245,201,162, 89, 37,146,121,146, 98,224, 11,198, 35, 70,187, 3,126,117,157, 7,114,111, 59, 4, 27,140,152,217,158,167, 35,215,
+238, 89, 89, 41,208, 66, 93, 96,207, 24,129,167,146, 71, 93, 49,105,248, 66,199,241,130, 64, 31, 8,174,249,241,251, 77,179, 54,
+198, 67,181,250,177, 12, 99,103,180,152,162, 79, 78, 65,233,122, 81,170,250, 45,125, 26, 56, 90,246,160,102, 99,118, 65, 96,119,
+ 38,217,245, 6,201,183, 94, 92, 79,155, 95,249,203,135,110, 39,169,253,175,243,190,110, 53,125,128,161, 63,119,238, 45,186,205,
+183, 18,130, 3,186,229,224,112, 91, 55, 66, 45,164,103, 37,141,254,110,177,231,229,194,185,173,187,122,238, 12,113,183, 62, 6,
+123, 59,203,219,219, 17, 24,174, 99, 50, 49,145,166, 19,156,111, 82,203, 27,228, 21,141,136,213,243,114, 60,133,119,126,155,180,
+127,139,146, 91,106,254, 50,121,222, 76, 95, 85,194, 19,225,171, 95,246, 23,254,167,178,129,155,141,216,205, 30, 50,231,182,205,
+160,226,198, 48,186,178, 98, 15,242,154,151,165,208, 44,223,217,106,211,167, 79,195,123, 90,167,176, 26, 93,181,191, 46,231,179,
+226,228,205, 50,100,100,178, 94,102, 84, 49, 31,153,144, 23,136,146, 80,252, 4, 31, 11,131,110, 21,175,235, 99,242,172,141,179,
+ 31, 99,185,254, 12,216, 55,232,195,127, 73, 36, 31,248,127,143,211,255, 0,100,223,217,252,250, 60, 57,219,198,180,125, 57,253,
+ 36,255, 0,218, 39,251,212,167,128,168,111, 91, 31,149, 47, 91, 23,149, 3,211,159,210, 79,253,162,127,189, 75,211,159,210, 79,
+253,162,127,189, 74, 10,150, 61,108,127,163, 75,214, 71,229, 64,232, 31,210, 79,215, 79,247,170, 66, 15,231, 39,235,167,219, 74,
+120, 2,215,168, 78,158,171,127,119,127,163,169,166,149, 15, 64,211,211,184,191, 71,157,198,159,237,127, 75,149, 42, 3,255,217,
+};
+
+#endif
diff --git a/source/blender/src/usiblender.c b/source/blender/src/usiblender.c
new file mode 100644
index 00000000000..41f1f5f0a43
--- /dev/null
+++ b/source/blender/src/usiblender.c
@@ -0,0 +1,533 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+ /* placed up here because of crappy
+ * winsock stuff.
+ */
+#include "BLO_signer_info.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#else
+#include <unistd.h> /* getpid */
+#endif
+#include "MEM_guardedalloc.h"
+
+#include "BMF_Api.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+#include "BLI_linklist.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "DNA_object_types.h"
+#include "DNA_space_types.h"
+#include "DNA_userdef_types.h"
+
+#include "BKE_blender.h"
+#include "BKE_curve.h"
+#include "BKE_displist.h"
+#include "BKE_exotic.h"
+#include "BKE_font.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_mball.h"
+#include "BKE_packedFile.h"
+
+#include "BIF_fsmenu.h"
+#include "BIF_gl.h"
+#include "BIF_interface.h"
+#include "BIF_usiblender.h"
+#include "BIF_drawtext.h"
+#include "BIF_editarmature.h"
+#include "BIF_editlattice.h"
+#include "BIF_editfont.h"
+#include "BIF_editmesh.h"
+#include "BIF_editsound.h"
+#include "BIF_renderwin.h"
+#include "BIF_resources.h"
+#include "BIF_screen.h"
+#include "BIF_space.h"
+#include "BIF_toolbox.h"
+
+#include "BSE_drawview.h"
+#include "BSE_headerbuttons.h"
+#include "BSE_editipo.h"
+#include "BSE_editaction.h"
+#include "BSE_filesel.h"
+
+#include "BLO_readfile.h"
+#include "BLO_writefile.h"
+
+#include "BDR_drawobject.h"
+#include "BDR_editobject.h"
+#include "BDR_vpaint.h"
+
+#include "BPY_extern.h"
+#include "blendef.h"
+
+#include "interface.h"
+#include "radio.h"
+#include "render.h"
+#include "license_key.h"
+#include "datatoc.h"
+
+#include "SYS_System.h"
+
+#include "PIL_time.h"
+
+/***/
+
+void BIF_read_file(char *name)
+{
+ extern short winqueue_break; /* editscreen.c */
+ struct BLO_SignerInfo *info;
+ extern char datatoc_ton[];
+ extern int datatoc_tonize;
+ extern char datatoc_splash_jpg[];
+ extern int datatoc_splash_jpg_size;
+ char infostring[400];
+ //hier misschien?
+ //sound_end_all_sounds();
+
+ // first try to read exotic file formats...
+ if (BKE_read_exotic(name) == 0) { /* throws first error box */
+ // we didn't succeed, now try to read Blender file
+ BKE_read_file(name, NULL); /* calls readfile, calls toolbox, throws one more, on failure calls the stream, and that is stubbed.... */
+ }
+ info = BLO_getSignerInfo();
+ if (BLO_isValidSignerInfo(info)) {
+ sprintf(infostring, "File signed by: %s // %s", info->name, info->email);
+ if (LICENSE_KEY_VALID) {
+ splash((void *)datatoc_ton, datatoc_tonize, infostring);
+ } else {
+ splash((void *)datatoc_splash_jpg, datatoc_splash_jpg_size, infostring);
+ }
+ }
+ BLO_clrSignerInfo(info);
+
+ sound_initialize_sounds();
+
+ winqueue_break= 1; /* overal uit queue's gaan */
+
+}
+
+int BIF_read_homefile(void)
+{
+ char tstr[FILE_MAXDIR+FILE_MAXFILE], scestr[FILE_MAXDIR];
+ char *home= BLI_gethome();
+ int success;
+
+ BLI_make_file_string(G.sce, tstr, home, ".B.blend");
+ strcpy(scestr, G.sce); /* even bewaren */
+ if (BLI_exists(tstr)) {
+ success = BKE_read_file(tstr, NULL);
+ } else {
+ success = BKE_read_file_from_memory(datatoc_B_blend, datatoc_B_blend_size, NULL);
+ }
+ strcpy(G.sce, scestr);
+
+ if (success) {
+ G.save_over = 0;
+
+ /* disable autoplay in .B.blend... */
+ G.fileflags &= ~G_FILE_AUTOPLAY;
+
+ /* holobutton */
+ if (strcmp(G.scene->r.ftype, "*@&#")==0) G.special1= G_HOLO;
+
+ if (BLI_streq(U.tempdir, "/")) {
+ char *tmp= getenv("TEMP");
+
+ strcpy(U.tempdir, tmp?tmp:"/tmp/");
+ }
+
+ if (G.main->versionfile <= 191) {
+ strcpy(U.plugtexdir, U.textudir);
+ strcpy(U.sounddir, "/");
+ }
+
+ /* patch to set Dupli Armature */
+ if (G.main->versionfile < 220) {
+ U.dupflag |= DUPARM;
+ }
+
+ /* userdef new option */
+ if (G.main->versionfile <= 222) {
+ U.vrmlflag= USERDEF_VRML_LAYERS;
+ }
+
+ space_set_commmandline_options();
+
+ reset_autosave();
+ }
+
+ return success;
+}
+
+static void get_autosave_location(char buf[FILE_MAXDIR+FILE_MAXFILE])
+{
+ char pidstr[32];
+
+ sprintf(pidstr, "%d.blend", abs(getpid()));
+ BLI_make_file_string("/", buf, U.tempdir, pidstr);
+}
+
+void BIF_read_autosavefile(void)
+{
+ char tstr[FILE_MAXDIR+FILE_MAXFILE], scestr[FILE_MAXDIR];
+ int save_over;
+
+ strcpy(scestr, G.sce); /* even bewaren */
+
+ get_autosave_location(tstr);
+
+ save_over = G.save_over;
+ BKE_read_file(tstr, NULL);
+ G.save_over = save_over;
+ strcpy(G.sce, scestr);
+}
+
+/***/
+
+static void readBlog(void)
+{
+ char name[FILE_MAXDIR+FILE_MAXFILE];
+ LinkNode *l, *lines;
+
+ BLI_make_file_string("/", name, BLI_gethome(), ".Blog");
+ lines= BLI_read_file_as_lines(name);
+
+ if (lines && !BLI_streq(lines->link, "")) {
+ strcpy(G.sce, lines->link);
+ } else {
+ BLI_make_file_string("/", G.sce, BLI_gethome(), "untitled.blend");
+ }
+
+ BLI_free_file_lines(lines);
+
+#ifdef WIN32
+ /* Add the drive names to the listing */
+ {
+ __int64 tmp;
+ char tmps[4];
+ int i;
+
+ tmp= GetLogicalDrives();
+
+ for (i=2; i < 26; i++) {
+ if ((tmp>>i) & 1) {
+ tmps[0]='a'+i;
+ tmps[1]=':';
+ tmps[2]='\\';
+ tmps[3]=0;
+
+ fsmenu_insert_entry(tmps, 0);
+ }
+ }
+
+ fsmenu_append_seperator();
+ }
+#endif
+
+ BLI_make_file_string(G.sce, name, BLI_gethome(), ".Bfs");
+ lines= BLI_read_file_as_lines(name);
+
+ for (l= lines; l; l= l->next) {
+ char *line= l->link;
+
+ if (!BLI_streq(line, "")) {
+ fsmenu_insert_entry(line, 0);
+ }
+ }
+
+ fsmenu_append_seperator();
+ BLI_free_file_lines(lines);
+}
+
+
+static void writeBlog(void)
+{
+ char name[FILE_MAXDIR+FILE_MAXFILE];
+ FILE *fp;
+
+ BLI_make_file_string("/", name, BLI_gethome(), ".Blog");
+
+ fp= fopen(name, "w");
+ if (fp) {
+ fprintf(fp, G.sce);
+ fclose(fp);
+ }
+}
+
+static void do_history(char *name)
+{
+ char tempname1[FILE_MAXDIR+FILE_MAXFILE], tempname2[FILE_MAXDIR+FILE_MAXFILE];
+ int hisnr= U.versions;
+
+ if(U.versions==0) return;
+ if(strlen(name)<2) return;
+
+ while( hisnr > 1) {
+ sprintf(tempname1, "%s%d", name, hisnr-1);
+ sprintf(tempname2, "%s%d", name, hisnr);
+
+ if(BLI_rename(tempname1, tempname2))
+ error("Unable to make version backup");
+
+ hisnr--;
+ }
+
+ /* lijkt dubbelop: maar deze is nodig als hisnr==1 */
+ sprintf(tempname1, "%s%d", name, hisnr);
+
+ if(BLI_rename(name, tempname1))
+ error("Unable to make version backup");
+}
+
+void BIF_write_file(char *target)
+{
+ Library *li;
+ char di[FILE_MAXDIR];
+ char *err;
+
+ if (BLI_streq(target, "")) return;
+
+ for (li= G.main->library.first; li; li= li->id.next) {
+ if (BLI_streq(li->name, target)) {
+ error("Cannot overwrite used library");
+ return;
+ }
+ }
+
+ if (!BLO_has_bfile_extension(target)) {
+ sprintf(di, "%s.blend", target);
+ } else {
+ strcpy(di, target);
+ }
+
+ if (BLI_exists(di)) {
+ if(!saveover(di))
+ return;
+ }
+
+ waitcursor(1);
+
+ if(G.obedit) {
+ exit_editmode(0); /* 0 = geen freedata */
+ }
+ if (G.fileflags & G_AUTOPACK) {
+ packAll();
+ }
+
+ do_history(di);
+
+ if (BLO_write_file(di, G.fileflags, &err)) {
+ strcpy(G.sce, di);
+ strcpy(G.main->name, di); /* is gegarandeerd current file */
+
+ G.save_over = 1;
+
+ writeBlog();
+ } else {
+ error("%s", err);
+ }
+
+ waitcursor(0);
+}
+
+void BIF_write_homefile(void)
+{
+ char *err, tstr[FILE_MAXDIR+FILE_MAXFILE];
+ int write_flags;
+
+ BLI_make_file_string("/", tstr, BLI_gethome(), ".B.blend");
+
+ /* force save as regular blend file */
+ write_flags = G.fileflags & ~(G_FILE_COMPRESS | G_FILE_LOCK | G_FILE_SIGN);
+ BLO_write_file(tstr, write_flags, &err);
+}
+
+void BIF_write_autosave(void)
+{
+ char *err, tstr[FILE_MAXDIR+FILE_MAXFILE];
+ int write_flags;
+
+ get_autosave_location(tstr);
+
+ /* force save as regular blend file */
+ write_flags = G.fileflags & ~(G_FILE_COMPRESS | G_FILE_LOCK | G_FILE_SIGN);
+ BLO_write_file(tstr, write_flags, &err);
+}
+
+static void delete_autosave(void)
+{
+ char tstr[FILE_MAXDIR+FILE_MAXFILE], pidstr[FILE_MAXFILE];
+
+ sprintf(pidstr, "%d", abs(getpid()));
+ BLI_make_file_string("/", tstr, U.tempdir, pidstr);
+
+ if (BLI_exists(tstr)) {
+ char str[FILE_MAXDIR+FILE_MAXFILE];
+ BLI_make_file_string("/", str, U.tempdir, "quit.blend");
+ BLI_rename(tstr, str);
+ }
+}
+
+/***/
+
+static void initbuttons(void)
+{
+ uiDefFont(UI_HELVB,
+ BMF_GetFont(BMF_kHelveticaBold14),
+ BMF_GetFont(BMF_kHelveticaBold12),
+ BMF_GetFont(BMF_kHelveticaBold10),
+ BMF_GetFont(BMF_kHelveticaBold8));
+ uiDefFont(UI_HELV,
+ BMF_GetFont(BMF_kHelvetica12),
+ BMF_GetFont(BMF_kHelvetica12),
+ BMF_GetFont(BMF_kHelvetica10),
+ BMF_GetFont(BMF_kHelveticaBold8));
+
+ BIF_resources_init();
+
+ glClearColor(.7, .7, .6, 0.0);
+
+ G.font= BMF_GetFont(BMF_kHelvetica12);
+ G.fonts= BMF_GetFont(BMF_kHelvetica10);
+ G.fontss= BMF_GetFont(BMF_kHelveticaBold8);
+
+ /* IKONEN INLADEN */
+
+ clear_matcopybuf();
+}
+
+void BIF_init(void)
+{
+ BKE_font_register_builtin(datatoc_Bfont, datatoc_Bfont_size);
+
+ initscreen(); /* voor (visuele) snelheid, dit eerst, dan setscreen */
+ initbuttons();
+ init_draw_rects(); /* drawobject.c */
+ init_gl_stuff(); /* drawview.c */
+
+ if (I_AM_PUBLISHER) checkhome();
+
+ BIF_read_homefile();
+
+ readBlog();
+ strcpy(G.lib, G.sce);
+}
+
+/***/
+
+extern unsigned short fullscreen;
+extern unsigned short borderless;
+extern ListBase editNurb;
+extern ListBase editelems;
+
+void exit_usiblender(void)
+{
+ extern char *fsmenu; /* filesel.c */
+
+ freeAllRad();
+ BKE_freecubetable();
+
+ if (G.background == 0)
+ sound_end_all_sounds();
+
+ if(G.obedit) {
+ if(G.obedit->type==OB_FONT) {
+ free_editText();
+ }
+ else if(G.obedit->type==OB_MBALL) BLI_freelistN(&editelems);
+ free_editMesh();
+ }
+
+ free_editLatt();
+ free_editArmature();
+ free_posebuf();
+
+ free_blender(); /* blender.c, doet hele library */
+ free_hashedgetab();
+ free_matcopybuf();
+ free_ipocopybuf();
+ freefastshade();
+ free_vertexpaint();
+
+ /* editnurb kan blijven bestaan buiten editmode */
+ freeNurblist(&editNurb);
+
+ fsmenu_free();
+
+ RE_free_render_data();
+ RE_free_filt_mask();
+
+ free_txt_data();
+
+ sound_exit_audio();
+
+ BPY_end_python();
+
+ if (!G.background) {
+ BIF_resources_free();
+
+ BIF_close_render_display();
+ mainwindow_close();
+ }
+
+ if(totblock!=0) {
+ printf("Error Totblck: %d\n",totblock);
+ MEM_printmemlist();
+ }
+ delete_autosave();
+
+ printf("\nBlender quit\n");
+
+#ifdef WIN32
+ // when debugging enter infinite loop to enable
+ // reading the printouts...
+ while(G.f & G_DEBUG) {PIL_sleep_ms(10);}
+#endif
+
+
+ SYS_DeleteSystem(SYS_GetSystem());
+
+ exit(G.afbreek==1);
+}
diff --git a/source/blender/src/view.c b/source/blender/src/view.c
new file mode 100644
index 00000000000..05a9de22620
--- /dev/null
+++ b/source/blender/src/view.c
@@ -0,0 +1,1095 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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>
+
+#ifdef WIN32
+#include <io.h>
+#include "BLI_winstuff.h"
+#else
+#include <unistd.h>
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+
+#include "DNA_object_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_space_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_userdef_types.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_object.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+
+#include "BIF_gl.h"
+#include "BIF_space.h"
+#include "BIF_mywindow.h"
+#include "BIF_screen.h"
+#include "BIF_toolbox.h"
+
+#include "BSE_view.h"
+#include "BSE_edit.h" /* For countall */
+#include "BSE_drawview.h" /* For inner_play_anim_loop */
+
+#include "BDR_drawobject.h" /* For draw_object */
+
+#include "mydevice.h"
+#include "blendef.h"
+
+/* Modules used */
+#include "render.h"
+
+#define TRACKBALLSIZE (1.1)
+
+void persp3d(View3D *v3d, int a)
+{
+ ScrArea *area= v3d->area;
+
+ /* oppasen met optimaliseren: dan laatste mode in area bewaren */
+ /* only 3D windows */
+ if(a== 0) {
+ bwin_get_winmatrix(area->win, area->winmat);
+ glMatrixMode(GL_MODELVIEW);
+ bwin_ortho2(area->win, -0.5, (float)(area->winx)-.05, -0.5, (float)(area->winy)-0.5);
+ glLoadIdentity();
+ }
+ else if(a== 1) {
+ glMatrixMode(GL_PROJECTION);
+ bwin_load_winmatrix(area->win, area->winmat);
+ glMatrixMode(GL_MODELVIEW);
+ bwin_load_viewmatrix(area->win, v3d->viewmat);
+ }
+}
+
+void persp_general(int a)
+{
+ /* for all window types, not 3D */
+
+ if(a== 0) {
+ glPushMatrix();
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glMatrixMode(GL_MODELVIEW);
+
+ myortho2(-0.5, ((float)(curarea->winx))-0.5, -0.5, ((float)(curarea->winy))-0.5);
+ glLoadIdentity();
+ }
+ else if(a== 1) {
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+ }
+}
+
+void persp(int a)
+{
+ /* oppasen met optimaliseren: dan laatste mode in area bewaren */
+ /* only 3D windows */
+
+ if(curarea->spacetype!=SPACE_VIEW3D) persp_general(a);
+ else if(a== 0) {
+ glMatrixMode(GL_PROJECTION);
+ mygetmatrix(curarea->winmat);
+ glMatrixMode(GL_MODELVIEW);
+ myortho2(-0.5, (float)(curarea->winx)-.05, -0.5, (float)(curarea->winy)-0.5);
+ glLoadIdentity();
+ }
+ else if(a== 1) {
+ glMatrixMode(GL_PROJECTION);
+ myloadmatrix(curarea->winmat);
+ glMatrixMode(GL_MODELVIEW);
+ myloadmatrix(G.vd->viewmat);
+ }
+}
+
+
+float zfac=1.0;
+
+void initgrabz(float x, float y, float z)
+{
+ if(G.vd==0) return;
+ zfac= G.vd->persmat[0][3]*x+ G.vd->persmat[1][3]*y+ G.vd->persmat[2][3]*z+ G.vd->persmat[3][3];
+}
+
+void window_to_3d(float *vec, short mx, short my)
+{
+ /* altijd initzgrab aanroepen */
+ float dx, dy;
+ float fmx, fmy, winx, winy;
+
+ /* stupid! */
+ winx= curarea->winx;
+ winy= curarea->winy;
+ fmx= mx;
+ fmy= my;
+
+ dx= (2.0*fmx)/winx;
+ dx*= zfac;
+ dy= (2.0*fmy)/winy;
+ dy*= zfac;
+
+ vec[0]= (G.vd->persinv[0][0]*dx + G.vd->persinv[1][0]*dy);
+ vec[1]= (G.vd->persinv[0][1]*dx + G.vd->persinv[1][1]*dy);
+ vec[2]= (G.vd->persinv[0][2]*dx + G.vd->persinv[1][2]*dy);
+}
+
+void project_short(float *vec, short *adr) /* clipt */
+{
+ float fx, fy, vec4[4];
+
+ adr[0]= 3200;
+ VECCOPY(vec4, vec);
+ vec4[3]= 1.0;
+
+ Mat4MulVec4fl(G.vd->persmat, vec4);
+
+ if( vec4[3]>0.1 ) {
+ fx= (curarea->winx/2)+(curarea->winx/2)*vec4[0]/vec4[3];
+
+ if( fx>0 && fx<curarea->winx) {
+
+ fy= (curarea->winy/2)+(curarea->winy/2)*vec4[1]/vec4[3];
+
+ if(fy>0.0 && fy< (float)curarea->winy) {
+ adr[0]= floor(fx+0.5);
+ adr[1]= floor(fy+0.5);
+ }
+ }
+ }
+}
+
+void project_short_noclip(float *vec, short *adr)
+{
+ float fx, fy, vec4[4];
+
+ adr[0]= 3200;
+ VECCOPY(vec4, vec);
+ vec4[3]= 1.0;
+
+ Mat4MulVec4fl(G.vd->persmat, vec4);
+
+ if( vec4[3]>0.1 ) {
+ fx= (curarea->winx/2)+(curarea->winx/2)*vec4[0]/vec4[3];
+
+ if( fx>-32700 && fx<32700) {
+
+ fy= (curarea->winy/2)+(curarea->winy/2)*vec4[1]/vec4[3];
+
+ if(fy>-32700.0 && fy<32700.0) {
+ adr[0]= floor(fx+0.5);
+ adr[1]= floor(fy+0.5);
+ }
+ }
+ }
+}
+
+int boundbox_clip(float obmat[][4], BoundBox *bb)
+{
+ /* return 1: afbeelden */
+
+ float mat[4][4];
+ float vec[4], min, max;
+ int a, flag= -1, fl;
+
+ if(bb==0) return 1;
+
+ Mat4MulMat4(mat, obmat, G.vd->persmat);
+
+ for(a=0; a<8; a++) {
+ VECCOPY(vec, bb->vec[a]);
+ vec[3]= 1.0;
+ Mat4MulVec4fl(mat, vec);
+ max= vec[3];
+ min= -vec[3];
+
+ fl= 0;
+ if(vec[0] < min) fl+= 1;
+ if(vec[0] > max) fl+= 2;
+ if(vec[1] < min) fl+= 4;
+ if(vec[1] > max) fl+= 8;
+ if(vec[2] < min) fl+= 16;
+ if(vec[2] > max) fl+= 32;
+
+ flag &= fl;
+ if(flag==0) return 1;
+ }
+
+ return 0;
+
+}
+
+void fdrawline(float x1, float y1, float x2, float y2)
+{
+ float v[2];
+
+ glBegin(GL_LINE_STRIP);
+ v[0] = x1; v[1] = y1;
+ glVertex2fv(v);
+ v[0] = x2; v[1] = y2;
+ glVertex2fv(v);
+ glEnd();
+}
+
+void fdrawbox(float x1, float y1, float x2, float y2)
+{
+ float v[2];
+
+ glBegin(GL_LINE_STRIP);
+
+ v[0] = x1; v[1] = y1;
+ glVertex2fv(v);
+ v[0] = x1; v[1] = y2;
+ glVertex2fv(v);
+ v[0] = x2; v[1] = y2;
+ glVertex2fv(v);
+ v[0] = x2; v[1] = y1;
+ glVertex2fv(v);
+ v[0] = x1; v[1] = y1;
+ glVertex2fv(v);
+
+ glEnd();
+}
+
+void sdrawline(short x1, short y1, short x2, short y2)
+{
+ short v[2];
+
+ glBegin(GL_LINE_STRIP);
+ v[0] = x1; v[1] = y1;
+ glVertex2sv(v);
+ v[0] = x2; v[1] = y2;
+ glVertex2sv(v);
+ glEnd();
+}
+
+void sdrawbox(short x1, short y1, short x2, short y2)
+{
+ short v[2];
+
+ glBegin(GL_LINE_STRIP);
+
+ v[0] = x1; v[1] = y1;
+ glVertex2sv(v);
+ v[0] = x1; v[1] = y2;
+ glVertex2sv(v);
+ v[0] = x2; v[1] = y2;
+ glVertex2sv(v);
+ v[0] = x2; v[1] = y1;
+ glVertex2sv(v);
+ v[0] = x1; v[1] = y1;
+ glVertex2sv(v);
+
+ glEnd();
+}
+
+/* trackball: deze is t.o.v. een 100% bol formule wel zo mooi */
+
+void calctrackballvecfirst(rcti *area, short *mval, float *vec)
+{
+ float x, y, radius, d, z, t;
+
+ radius= TRACKBALLSIZE;
+
+ /* x en y normaliseren */
+ x= (area->xmax + area->xmin)/2 -mval[0];
+ x/= (float)((area->xmax - area->xmin)/2);
+ y= (area->ymax + area->ymin)/2 -mval[1];
+ y/= (float)((area->ymax - area->ymin)/2);
+
+ d = sqrt(x*x + y*y);
+ if (d < radius*M_SQRT1_2) /* Inside sphere */
+ z = sqrt(radius*radius - d*d);
+ else
+ { /* On hyperbola */
+ t = radius / M_SQRT2;
+ z = t*t / d;
+ }
+
+ vec[0]= x;
+ vec[1]= y;
+ vec[2]= -z; /* jawel! */
+
+ if( fabs(vec[2])>fabs(vec[1]) && fabs(vec[2])>fabs(vec[0]) ) {
+ vec[0]= 0.0;
+ vec[1]= 0.0;
+ if(vec[2]>0.0) vec[2]= 1.0; else vec[2]= -1.0;
+ }
+ else if( fabs(vec[1])>fabs(vec[0]) && fabs(vec[1])>fabs(vec[2]) ) {
+ vec[0]= 0.0;
+ vec[2]= 0.0;
+ if(vec[1]>0.0) vec[1]= 1.0; else vec[1]= -1.0;
+ }
+ else {
+ vec[1]= 0.0;
+ vec[2]= 0.0;
+ if(vec[0]>0.0) vec[0]= 1.0; else vec[0]= -1.0;
+ }
+}
+
+void calctrackballvec(rcti *area, short *mval, float *vec)
+{
+ float x, y, radius, d, z, t;
+
+ radius= TRACKBALLSIZE;
+
+ /* x en y normaliseren */
+ x= (area->xmax + area->xmin)/2 -mval[0];
+ x/= (float)((area->xmax - area->xmin)/4);
+ y= (area->ymax + area->ymin)/2 -mval[1];
+ y/= (float)((area->ymax - area->ymin)/2);
+
+ d = sqrt(x*x + y*y);
+ if (d < radius*M_SQRT1_2) /* Inside sphere */
+ z = sqrt(radius*radius - d*d);
+ else
+ { /* On hyperbola */
+ t = radius / M_SQRT2;
+ z = t*t / d;
+ }
+
+ vec[0]= x;
+ vec[1]= y;
+ vec[2]= -z; /* jawel! */
+
+}
+
+void viewmove(int mode)
+{
+ float firstvec[3], newvec[3], dvec[3];
+ float oldquat[4], q1[4], q2[4], si, phi;
+ int firsttime=1;
+ short mval[2], mvalo[2];
+
+ /* sometimes this routine is called from headerbuttons */
+ areawinset(curarea->win);
+ curarea->head_swap= 0;
+
+ initgrabz(-G.vd->ofs[0], -G.vd->ofs[1], -G.vd->ofs[2]);
+
+ QUATCOPY(oldquat, G.vd->viewquat);
+ getmouseco_sc(mvalo); /* werk met screencoordinaten ivm trackball functie */
+ calctrackballvec(&curarea->winrct, mvalo, firstvec);
+
+ /* cumultime(0); */
+
+ while(TRUE) {
+ getmouseco_sc(mval);
+
+ if(mval[0]!=mvalo[0] || mval[1]!=mvalo[1] || (G.f & G_PLAYANIM)) {
+
+ if(firsttime) {
+ firsttime= 0;
+ /* wordt hier geroteerd, gezoomd of transleerd */
+ if(mode==0) {
+ if(G.vd->view!=0) scrarea_queue_headredraw(curarea); /* voor button */
+ G.vd->view= 0;
+ }
+
+ if(G.vd->persp==2 || (G.vd->persp==3 && mode!=1)) {
+ G.vd->persp= 1;
+ scrarea_do_windraw(curarea);
+ scrarea_queue_headredraw(curarea);
+ }
+ }
+
+
+ if(mode==0) { /* viewroteer */
+
+ if(U.flag & TRACKBALL) {
+ calctrackballvec(&curarea->winrct, mval, newvec);
+
+ VecSubf(dvec, newvec, firstvec);
+
+ si= sqrt(dvec[0]*dvec[0]+ dvec[1]*dvec[1]+ dvec[2]*dvec[2]);
+ si/= (2.0*TRACKBALLSIZE);
+
+ if(si<1.0) {
+ Crossf(q1+1, firstvec, newvec);
+
+ Normalise(q1+1);
+
+ phi= asin(si);
+
+ si= sin(phi);
+ q1[0]= cos(phi);
+ q1[1]*= si;
+ q1[2]*= si;
+ q1[3]*= si;
+
+ QuatMul(G.vd->viewquat, q1, oldquat);
+ }
+ }
+ else {
+ /* roteren om z-as (x beweging) en liggende as (y) */
+
+ phi= 2*(mval[0]-mvalo[0]);
+ phi/= (float)curarea->winx;
+ si= sin(phi);
+ q1[0]= cos(phi);
+ q1[1]= q1[2]= 0.0;
+ q1[3]= si;
+
+ /* liggende as */
+ VECCOPY(q2+1, G.vd->viewinv[0]);
+ Normalise(q2+1);
+ phi= (mvalo[1]-mval[1]);
+ phi/= (float)curarea->winy;
+ si= sin(phi);
+ q2[0]= cos(phi);
+ q2[1]*= si;
+ q2[2]*= si;
+ q2[3]*= si;
+
+ QuatMul(q1, q1, q2);
+ QuatMul(G.vd->viewquat, G.vd->viewquat, q1);
+ }
+ }
+ else if(mode==1) { /* translate */
+ if(G.vd->persp==3) {
+ /* zoom= 0.5+0.5*(float)(2<<G.vd->rt1); */
+ /* dx-= (mval[0]-mvalo[0])/zoom; */
+ /* dy-= (mval[1]-mvalo[1])/zoom; */
+ /* G.vd->rt2= dx; */
+ /* G.vd->rt3= dy; */
+ /* if(G.vd->rt2<-320) G.vd->rt2= -320; */
+ /* if(G.vd->rt2> 320) G.vd->rt2= 320; */
+ /* if(G.vd->rt3<-250) G.vd->rt3= -250; */
+ /* if(G.vd->rt3> 250) G.vd->rt3= 250; */
+ }
+ else {
+ window_to_3d(dvec, mval[0]-mvalo[0], mval[1]-mvalo[1]);
+ VecAddf(G.vd->ofs, G.vd->ofs, dvec);
+ }
+ }
+ else if(mode==2) {
+ G.vd->dist*= 1.0+(float)(mvalo[0]-mval[0]+mvalo[1]-mval[1])/1000.0;
+
+ /* deze limits ook in toets.c */
+ if(G.vd->dist<0.001*G.vd->grid) G.vd->dist= 0.001*G.vd->grid;
+ if(G.vd->dist>10.0*G.vd->far) G.vd->dist=10.0*G.vd->far;
+
+ mval[1]= mvalo[1]; /* blijft ie zoomen */
+ mval[0]= mvalo[0];
+ }
+
+ mvalo[0]= mval[0];
+ mvalo[1]= mval[1];
+
+ if(G.f & G_PLAYANIM) inner_play_anim_loop(0, 0);
+ if(G.f & G_SIMULATION) break;
+
+ scrarea_do_windraw(curarea);
+ screen_swapbuffers();
+ }
+ else BIF_wait_for_statechange();
+
+ /* dit moet onderaan, anders pakt de get_mbut het niet op de PC... */
+ if( !(get_mbut() & (L_MOUSE|M_MOUSE))) break;
+ }
+
+ curarea->head_swap= WIN_FRONT_OK;
+}
+
+short v3d_windowmode=0;
+
+void setwinmatrixview3d(rctf *rect) /* rect: voor picking */
+{
+ Camera *cam=0;
+ float d, near, far, winx = 0.0, winy = 0.0;
+ float lens, dfac, tfac, fac, x1, y1, x2, y2;
+ short orth;
+
+ lens= G.vd->lens;
+ near= G.vd->near;
+ far= G.vd->far;
+
+ if(G.vd->persp==2) {
+ if(G.vd->camera) {
+ if(G.vd->camera->type==OB_LAMP ) {
+ Lamp *la;
+
+ la= G.vd->camera->data;
+ fac= cos( M_PI*la->spotsize/360.0);
+
+ x1= saacos(fac);
+ lens= 16.0*fac/sin(x1);
+
+ near= la->clipsta;
+ far= la->clipend;
+ }
+ else if(G.vd->camera->type==OB_CAMERA) {
+ cam= G.vd->camera->data;
+ lens= cam->lens;
+ near= cam->clipsta;
+ far= cam->clipend;
+
+ if(cam->type==CAM_ORTHO) {
+ lens*= 100.0;
+ near= (near+1.0)*100.0; /* otherwise zbuffer troubles. a Patch! */
+ far*= 100.0;
+ }
+ }
+ }
+ }
+
+ if(v3d_windowmode) {
+ winx= R.rectx;
+ winy= R.recty;
+ }
+ else {
+ winx= curarea->winx;
+ winy= curarea->winy;
+ }
+
+ if(winx>winy) d= 0.015625*winx*lens;
+ else d= 0.015625*winy*lens;
+
+ dfac= near/d;
+
+ /* if(G.vd->persp==1 && G.vd->dproj>1.0) far= G.vd->dproj*far; */
+
+ if(G.vd->persp==0) {
+ /* x1= -winx*G.vd->dist/1000.0; */
+ x1= -G.vd->dist;
+ x2= -x1;
+ y1= -winy*G.vd->dist/winx;
+ y2= -y1;
+ orth= 1;
+ }
+ else {
+ if(G.vd->persp==2) {
+ fac= (1.41421+( (float)G.vd->camzoom )/50.0);
+ fac*= fac;
+ }
+ else fac= 2.0;
+
+ x1= -dfac*(winx/fac);
+ x2= -x1;
+ y1= -dfac*(winy/fac);
+ y2= -y1;
+
+ if(G.vd->persp==2 && (G.special1 & G_HOLO)) {
+ if(cam && (cam->flag & CAM_HOLO2)) {
+ tfac= fac/4.0; /* de fac is 1280/640 gecorr voor obszoom */
+
+ if(cam->netend==0.0) cam->netend= EFRA;
+ fac= (G.scene->r.cfra-1.0)/(cam->netend)-0.5;
+
+ fac*= tfac*(x2-x1);
+ fac*= ( cam->hololen1 );
+ x1-= fac;
+ x2-= fac;
+ }
+ }
+
+ orth= 0;
+ }
+
+ if(rect) { /* picking */
+ rect->xmin/= winx;
+ rect->xmin= x1+rect->xmin*(x2-x1);
+ rect->ymin/= winy;
+ rect->ymin= y1+rect->ymin*(y2-y1);
+ rect->xmax/= winx;
+ rect->xmax= x1+rect->xmax*(x2-x1);
+ rect->ymax/= winy;
+ rect->ymax= y1+rect->ymax*(y2-y1);
+
+ if(orth) myortho(rect->xmin, rect->xmax, rect->ymin, rect->ymax, -far, far);
+ else mywindow(rect->xmin, rect->xmax, rect->ymin, rect->ymax, near, far);
+
+ }
+ else {
+ if(v3d_windowmode) {
+ if(orth) i_ortho(x1, x2, y1, y2, -far, far, R.winmat);
+ else {
+ if(cam && cam->type==CAM_ORTHO) i_window(x1, x2, y1, y2, near, far, R.winmat);
+ else i_window(x1, x2, y1, y2, near, far, R.winmat);
+ }
+ }
+ else {
+ if(orth) myortho(x1, x2, y1, y2, -far, far);
+ else {
+ if(cam && cam->type==CAM_ORTHO) mywindow(x1, x2, y1, y2, near, far);
+ else mywindow(x1, x2, y1, y2, near, far);
+ }
+ }
+ }
+
+ if(v3d_windowmode==0) {
+ glMatrixMode(GL_PROJECTION);
+ mygetmatrix(curarea->winmat);
+ glMatrixMode(GL_MODELVIEW);
+ }
+}
+
+
+void obmat_to_viewmat(Object *ob)
+{
+ float bmat[4][4];
+ float tmat[3][3];
+
+ Mat4CpyMat4(bmat, ob->obmat);
+ Mat4Ortho(bmat);
+ Mat4Invert(G.vd->viewmat, bmat);
+
+ /* viewquat berekenen, o.a. voor add object */
+ Mat3CpyMat4(tmat, G.vd->viewmat);
+ Mat3ToQuat(tmat, G.vd->viewquat);
+}
+
+
+void setviewmatrixview3d()
+{
+ Camera *cam;
+/* float bepaalphitheta(); */
+
+ if(G.special1 & G_HOLO) RE_holoview();
+
+ if(G.vd->persp>=2) { /* obs/camera */
+ if(G.vd->camera) {
+
+ where_is_object(G.vd->camera);
+ obmat_to_viewmat(G.vd->camera);
+
+ if(G.vd->camera->type==OB_CAMERA) {
+ cam= G.vd->camera->data;
+ if(cam->type==CAM_ORTHO) G.vd->viewmat[3][2]*= 100.0;
+ }
+ }
+ else {
+ QuatToMat4(G.vd->viewquat, G.vd->viewmat);
+ G.vd->viewmat[3][2]-= G.vd->dist;
+ }
+ }
+ else {
+
+ QuatToMat4(G.vd->viewquat, G.vd->viewmat);
+ if(G.vd->persp==1) G.vd->viewmat[3][2]-= G.vd->dist;
+ i_translate(G.vd->ofs[0], G.vd->ofs[1], G.vd->ofs[2], G.vd->viewmat);
+ }
+}
+
+/* IGLuint-> GLuint*/
+short selectprojektie(unsigned int *buffer, short x1, short y1, short x2, short y2)
+{
+ rctf rect;
+ Base *base;
+ short mval[2], code, hits;
+
+ G.f |= G_PICKSEL;
+
+ if(x1==0 && x2==0 && y1==0 && y2==0) {
+ getmouseco_areawin(mval);
+ rect.xmin= mval[0]-7;
+ rect.xmax= mval[0]+7;
+ rect.ymin= mval[1]-7;
+ rect.ymax= mval[1]+7;
+ }
+ else {
+ rect.xmin= x1;
+ rect.xmax= x2;
+ rect.ymin= y1;
+ rect.ymax= y2;
+ }
+ setwinmatrixview3d(&rect);
+ Mat4MulMat4(G.vd->persmat, G.vd->viewmat, curarea->winmat);
+
+ if(G.vd->drawtype > OB_WIRE) {
+ G.zbuf= TRUE;
+ glEnable(GL_DEPTH_TEST);
+ }
+
+ glSelectBuffer( MAXPICKBUF, buffer);
+ glRenderMode(GL_SELECT);
+ glInitNames(); /* deze twee fies zijn waarvoor? Anders werkt het niet */
+ glPushName(-1);
+ code= 1;
+
+ if(G.obedit && G.obedit->type==OB_MBALL) {
+ draw_object(BASACT);
+ }
+ else if ((G.obedit && G.obedit->type==OB_ARMATURE)||(G.obpose && G.obpose->type==OB_ARMATURE)) {
+ draw_object(BASACT);
+ }
+ else {
+ base= G.scene->base.first;
+ while(base) {
+ if(base->lay & G.vd->lay) {
+ base->selcol= code;
+ glLoadName(code);
+ draw_object(base);
+ code++;
+ }
+ base= base->next;
+ }
+ }
+ glPopName(); /* zie boven (pushname) */
+ hits= glRenderMode(GL_RENDER);
+ if(hits<0) error("Too many objects in selectbuf");
+
+ G.f &= ~G_PICKSEL;
+ setwinmatrixview3d(0);
+ Mat4MulMat4(G.vd->persmat, G.vd->viewmat, curarea->winmat);
+
+ if(G.vd->drawtype > OB_WIRE) {
+ G.zbuf= 0;
+ glDisable(GL_DEPTH_TEST);
+ }
+
+ return hits;
+}
+
+float *give_cursor()
+{
+ if(G.vd && G.vd->localview) return G.vd->cursor;
+ else return G.scene->cursor;
+}
+
+unsigned int free_localbit()
+{
+ unsigned int lay;
+ ScrArea *sa;
+ bScreen *sc;
+
+ lay= 0;
+
+ /* soms kunnen we een localview kwijtrijaken: als een area gesloten wordt */
+ /* alle area's aflopen: welke localviews zijn in gebruik */
+ sc= G.main->screen.first;
+ while(sc) {
+ sa= sc->areabase.first;
+ while(sa) {
+ SpaceLink *sl= sa->spacedata.first;
+ while(sl) {
+ if(sl->spacetype==SPACE_VIEW3D) {
+ View3D *v3d= (View3D*) sl;
+ lay |= v3d->lay;
+ }
+ sl= sl->next;
+ }
+ sa= sa->next;
+ }
+ sc= sc->id.next;
+ }
+
+ if( (lay & 0x01000000)==0) return 0x01000000;
+ if( (lay & 0x02000000)==0) return 0x02000000;
+ if( (lay & 0x04000000)==0) return 0x04000000;
+ if( (lay & 0x08000000)==0) return 0x08000000;
+ if( (lay & 0x10000000)==0) return 0x10000000;
+ if( (lay & 0x20000000)==0) return 0x20000000;
+ if( (lay & 0x40000000)==0) return 0x40000000;
+ if( (lay & 0x80000000)==0) return 0x80000000;
+
+ return 0;
+}
+
+
+void initlocalview()
+{
+ Base *base;
+ float size = 0.0, min[3], max[3], afm[3];
+ unsigned int locallay;
+ int ok=0;
+
+ if(G.vd->localvd) return;
+
+ min[0]= min[1]= min[2]= 1.0e10;
+ max[0]= max[1]= max[2]= -1.0e10;
+
+ locallay= free_localbit();
+
+ if(locallay==0) {
+ error("Sorry, no more than 8 localviews");
+ ok= 0;
+ }
+ else {
+ if(G.obedit) {
+ minmax_object(G.obedit, min, max);
+
+ ok= 1;
+
+ BASACT->lay |= locallay;
+ G.obedit->lay= BASACT->lay;
+ }
+ else {
+ base= FIRSTBASE;
+ while(base) {
+ if TESTBASE(base) {
+ minmax_object(base->object, min, max);
+ base->lay |= locallay;
+ base->object->lay= base->lay;
+ ok= 1;
+ }
+ base= base->next;
+ }
+ }
+
+ afm[0]= (max[0]-min[0]);
+ afm[1]= (max[1]-min[1]);
+ afm[2]= (max[2]-min[2]);
+ size= MAX3(afm[0], afm[1], afm[2]);
+ if(size<=0.01) size= 0.01;
+ }
+
+ if(ok) {
+ G.vd->localvd= MEM_mallocN(sizeof(View3D), "localview");
+ memcpy(G.vd->localvd, G.vd, sizeof(View3D));
+
+ G.vd->ofs[0]= -(min[0]+max[0])/2.0;
+ G.vd->ofs[1]= -(min[1]+max[1])/2.0;
+ G.vd->ofs[2]= -(min[2]+max[2])/2.0;
+
+ G.vd->dist= size;
+
+ if(G.vd->persp>1) {
+ G.vd->persp= 1;
+
+ }
+ G.vd->near= 0.1;
+ G.vd->cursor[0]= -G.vd->ofs[0];
+ G.vd->cursor[1]= -G.vd->ofs[1];
+ G.vd->cursor[2]= -G.vd->ofs[2];
+
+ G.vd->lay= locallay;
+
+ countall();
+ scrarea_queue_winredraw(curarea);
+ }
+ else {
+ /* flags wissen */
+ base= FIRSTBASE;
+ while(base) {
+ if( base->lay & locallay ) {
+ base->lay-= locallay;
+ if(base->lay==0) base->lay= G.vd->layact;
+ if(base->object != G.obedit) base->flag |= SELECT;
+ base->object->lay= base->lay;
+ }
+ base= base->next;
+ }
+ scrarea_queue_headredraw(curarea);
+
+ G.vd->localview= 0;
+ }
+}
+
+void centreview() /* localview zonder local! */
+{
+ Base *base;
+ float size, min[3], max[3], afm[3];
+ int ok=0;
+
+ min[0]= min[1]= min[2]= 1.0e10;
+ max[0]= max[1]= max[2]= -1.0e10;
+
+ if(G.obedit) {
+ minmax_object(G.obedit, min, max);
+
+ ok= 1;
+ }
+ else {
+ base= FIRSTBASE;
+ while(base) {
+ if TESTBASE(base) {
+ minmax_object(base->object, min, max);
+ ok= 1;
+ }
+ base= base->next;
+ }
+ }
+
+ if(ok==0) return;
+
+ afm[0]= (max[0]-min[0]);
+ afm[1]= (max[1]-min[1]);
+ afm[2]= (max[2]-min[2]);
+ size= MAX3(afm[0], afm[1], afm[2]);
+
+ if(size<=0.01) size= 0.01;
+
+
+
+ G.vd->ofs[0]= -(min[0]+max[0])/2.0;
+ G.vd->ofs[1]= -(min[1]+max[1])/2.0;
+ G.vd->ofs[2]= -(min[2]+max[2])/2.0;
+
+ G.vd->dist= size;
+
+ if(G.vd->persp>1) {
+ G.vd->persp= 1;
+
+ }
+ G.vd->near= 0.1;
+ G.vd->cursor[0]= -G.vd->ofs[0];
+ G.vd->cursor[1]= -G.vd->ofs[1];
+ G.vd->cursor[2]= -G.vd->ofs[2];
+
+ scrarea_queue_winredraw(curarea);
+
+}
+
+
+void restore_localviewdata(View3D *vd)
+{
+ if(vd->localvd==0) return;
+
+ VECCOPY(vd->ofs, vd->localvd->ofs);
+ vd->dist= vd->localvd->dist;
+ vd->persp= vd->localvd->persp;
+ vd->view= vd->localvd->view;
+ vd->near= vd->localvd->near;
+ vd->far= vd->localvd->far;
+ vd->lay= vd->localvd->lay;
+ vd->layact= vd->localvd->layact;
+ vd->drawtype= vd->localvd->drawtype;
+ vd->camera= vd->localvd->camera;
+ QUATCOPY(vd->viewquat, vd->localvd->viewquat);
+
+}
+
+void endlocalview(ScrArea *sa)
+{
+ View3D *v3d;
+ struct Base *base;
+ unsigned int locallay;
+
+ if(sa->spacetype!=SPACE_VIEW3D) return;
+ v3d= sa->spacedata.first;
+
+ if(v3d->localvd) {
+
+ locallay= v3d->lay & 0xFF000000;
+
+ restore_localviewdata(v3d);
+
+ MEM_freeN(v3d->localvd);
+ v3d->localvd= 0;
+ v3d->localview= 0;
+
+ /* als in ander window de layers zijn veranderd */
+ if(v3d->scenelock) v3d->lay= G.scene->lay;
+
+ base= FIRSTBASE;
+ while(base) {
+ if( base->lay & locallay ) {
+ base->lay-= locallay;
+ if(base->lay==0) base->lay= v3d->layact;
+ if(base->object != G.obedit) base->flag |= SELECT;
+ base->object->lay= base->lay;
+ }
+ base= base->next;
+ }
+
+ countall();
+ allqueue(REDRAWVIEW3D, 0); /* ivm select */
+
+ }
+}
+
+void view3d_home(int centre)
+{
+ Base *base;
+ float size, min[3], max[3], afm[3];
+ int ok= 1, onedone=0;
+
+ if(centre) {
+ min[0]= min[1]= min[2]= 0.0;
+ max[0]= max[1]= max[2]= 0.0;
+ }
+ else {
+ min[0]= min[1]= min[2]= 1.0e10;
+ max[0]= max[1]= max[2]= -1.0e10;
+ }
+
+ base= FIRSTBASE;
+ if(base==0) return;
+ while(base) {
+ if(base->lay & G.vd->lay) {
+ onedone= 1;
+ minmax_object(base->object, min, max);
+ }
+ base= base->next;
+ }
+ if(!onedone) return;
+
+ afm[0]= (max[0]-min[0]);
+ afm[1]= (max[1]-min[1]);
+ afm[2]= (max[2]-min[2]);
+ size= MAX3(afm[0], afm[1], afm[2]);
+ if(size==0.0) ok= 0;
+
+ if(ok) {
+
+ G.vd->ofs[0]= -(min[0]+max[0])/2.0;
+ G.vd->ofs[1]= -(min[1]+max[1])/2.0;
+ G.vd->ofs[2]= -(min[2]+max[2])/2.0;
+
+ G.vd->dist= size;
+
+ if(G.vd->persp==2) G.vd->persp= 1;
+
+ scrarea_queue_winredraw(curarea);
+ }
+}
+
+
+void view3d_align_axis_to_vector(View3D *v3d, int axisidx, float vec[3])
+{
+ float alignaxis[3];
+ float norm[3], axis[3], angle;
+
+ alignaxis[0]= alignaxis[1]= alignaxis[2]= 0.0;
+ alignaxis[axisidx]= 1.0;
+
+ norm[0]= vec[0], norm[1]= vec[1], norm[2]= vec[2];
+ Normalise(norm);
+
+ angle= acos(Inpf(alignaxis, norm));
+ Crossf(axis, alignaxis, norm);
+ VecRotToQuat(axis, -angle, v3d->viewquat);
+
+ v3d->view= 0;
+ if (v3d->persp>=2) v3d->persp= 0; /* switch out of camera mode */
+}
+
diff --git a/source/blender/src/vpaint.c b/source/blender/src/vpaint.c
new file mode 100644
index 00000000000..d6e8e9b2654
--- /dev/null
+++ b/source/blender/src/vpaint.c
@@ -0,0 +1,1169 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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>
+
+#ifdef WIN32
+#include <io.h>
+#include "BLI_winstuff.h"
+#else
+#include <unistd.h>
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "IMB_imbuf.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+#include "MTC_matrixops.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_view3d_types.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_mesh.h"
+#include "BKE_displist.h"
+#include "BKE_global.h"
+
+#include "BIF_graphics.h"
+#include "BIF_interface.h"
+#include "BIF_mywindow.h"
+#include "BIF_editview.h"
+#include "BIF_space.h"
+#include "BIF_screen.h"
+#include "BIF_toolbox.h"
+#include "BIF_gl.h"
+
+#include "BDR_vpaint.h"
+
+#include "BSE_drawview.h"
+#include "BSE_trans_types.h"
+#include "BSE_view.h"
+
+#include "mydevice.h"
+#include "blendef.h"
+
+#include "BIF_editdeform.h"
+
+ /* Gvp.mode */
+#define VP_MIX 0
+#define VP_ADD 1
+#define VP_SUB 2
+#define VP_MUL 3
+#define VP_FILT 4
+
+ /* Gvp.flag */
+#define VP_COLINDEX 1
+#define VP_AREA 2
+#define VP_SOFT 4
+#define VP_NORMALS 8
+
+#define MAXINDEX 65336
+
+VPaint Gvp= {1.0, 1.0, 1.0, 0.2, 25.0, 1.0, 1.0, 0, VP_AREA+VP_SOFT};
+float vpimat[3][3];
+unsigned int *vpaintundobuf=0;
+int totvpaintundo;
+short *indexar= 0;
+
+int totwpaintundo;
+MDeformVert *wpaintundobuf=NULL;
+
+/* Function prototypes */
+int calc_vp_alpha_dl(DispList *disp, MVert *mvert, int vert, short *mval);
+
+/* in tegenstelling tot cpack teken kleuren, zijn de MCOL kleuren (vpaint kleuren) per byte!
+ en dus endian ongevoelig. Mcol = ABGR!!! Oppassen met cpack functies */
+
+unsigned int rgba_to_mcol(float r, float g, float b, float a)
+{
+ int ir, ig, ib, ia;
+ unsigned int col;
+ char *cp;
+
+ ir= floor(255.0*r);
+ if(ir<0) ir= 0; else if(ir>255) ir= 255;
+ ig= floor(255.0*g);
+ if(ig<0) ig= 0; else if(ig>255) ig= 255;
+ ib= floor(255.0*b);
+ if(ib<0) ib= 0; else if(ib>255) ib= 255;
+ ia= floor(255.0*a);
+ if(ia<0) ia= 0; else if(ia>255) ia= 255;
+
+ cp= (char *)&col;
+ cp[0]= ia;
+ cp[1]= ib;
+ cp[2]= ig;
+ cp[3]= ir;
+
+ return col;
+
+}
+
+unsigned int vpaint_get_current_col(void)
+{
+ return rgba_to_mcol(Gvp.r, Gvp.g, Gvp.b, 1.0);
+}
+
+void do_shared_vertexcol(Mesh *me)
+{
+ /* als geen mcol: niet doen */
+ /* als tface: alleen de betreffende vlakken, anders alles */
+ MFace *mface;
+ TFace *tface;
+ int a;
+ short *scolmain, *scol;
+ char *mcol;
+
+ if(me->mcol==0 || me->totvert==0 || me->totface==0) return;
+
+ scolmain= MEM_callocN(4*sizeof(short)*me->totvert, "colmain");
+
+ tface= me->tface;
+ mface= me->mface;
+ mcol= (char *)me->mcol;
+ for(a=me->totface; a>0; a--, mface++, mcol+=16) {
+ if(mface->v3) {
+ if(tface==0 || (tface->mode & TF_SHAREDCOL) || (G.f & G_FACESELECT)==0) {
+
+ scol= scolmain+4*mface->v1;
+ scol[0]++; scol[1]+= mcol[1]; scol[2]+= mcol[2]; scol[3]+= mcol[3];
+ scol= scolmain+4*mface->v2;
+ scol[0]++; scol[1]+= mcol[5]; scol[2]+= mcol[6]; scol[3]+= mcol[7];
+ scol= scolmain+4*mface->v3;
+ scol[0]++; scol[1]+= mcol[9]; scol[2]+= mcol[10]; scol[3]+= mcol[11];
+ if(mface->v4) {
+ scol= scolmain+4*mface->v4;
+ scol[0]++; scol[1]+= mcol[13]; scol[2]+= mcol[14]; scol[3]+= mcol[15];
+ }
+ }
+ }
+ if(tface) tface++;
+ }
+
+ a= me->totvert;
+ scol= scolmain;
+ while(a--) {
+ if(scol[0]>1) {
+ scol[1]/= scol[0];
+ scol[2]/= scol[0];
+ scol[3]/= scol[0];
+ }
+ scol+= 4;
+ }
+
+ tface= me->tface;
+ mface= me->mface;
+ mcol= (char *)me->mcol;
+ for(a=me->totface; a>0; a--, mface++, mcol+=16) {
+ if(mface->v3) {
+ if(tface==0 || (tface->mode & TF_SHAREDCOL) || (G.f & G_FACESELECT)==0) {
+
+ scol= scolmain+4*mface->v1;
+ mcol[1]= scol[1]; mcol[2]= scol[2]; mcol[3]= scol[3];
+
+ scol= scolmain+4*mface->v2;
+ mcol[5]= scol[1]; mcol[6]= scol[2]; mcol[7]= scol[3];
+
+ scol= scolmain+4*mface->v3;
+ mcol[9]= scol[1]; mcol[10]= scol[2]; mcol[11]= scol[3];
+
+ if(mface->v4) {
+ scol= scolmain+4*mface->v4;
+ mcol[13]= scol[1]; mcol[14]= scol[2]; mcol[15]= scol[3];
+ }
+ }
+ }
+ if(tface) tface++;
+ }
+
+ MEM_freeN(scolmain);
+}
+
+void make_vertexcol() /* single ob */
+{
+ Object *ob;
+ Mesh *me;
+ DispList *dl;
+
+ /*
+ * Always copies from shadedisplist to mcol.
+ * When there are tfaces, it copies the colors and frees mcol
+ */
+
+ if(G.obedit) {
+ error("Unable to perform function in EditMode");
+ return;
+ }
+
+ ob= OBACT;
+ me= get_mesh(ob);
+ if(me==0) return;
+
+ if(me->flag & ME_TWOSIDED) {
+ me->flag &= ~ME_TWOSIDED;
+ }
+
+ dl= ob->disp.first;
+
+ if(dl==0 || dl->col1==NULL) {
+ shadeDispList(ob);
+ dl= ob->disp.first;
+ }
+ if(dl && dl->col1) {
+ int i;
+
+ if(me->mcol) MEM_freeN(me->mcol);
+
+ me->mcol= MEM_dupallocN(dl->col1);
+ if (me->mcol) {
+ for (i=0; i<me->totface*4; i++) {
+ MCol *mcol= &me->mcol[i];
+ mcol->a= 255;
+ }
+ }
+
+ if(me->tface) mcol_to_tface(me, 1);
+ }
+ freedisplist(&(ob->disp));
+
+
+ allqueue(REDRAWBUTSEDIT, 0);
+ allqueue(REDRAWVIEW3D, 0);
+}
+
+
+
+void copy_vpaint_undo(unsigned int *mcol, int tot)
+{
+ if(vpaintundobuf) MEM_freeN(vpaintundobuf);
+ vpaintundobuf= 0;
+
+ if(mcol==0 || tot==0) return;
+
+ vpaintundobuf= MEM_mallocN(4*sizeof(int)*tot, "vpaintundobuf");
+ memcpy(vpaintundobuf, mcol, 4*sizeof(int)*tot);
+ totvpaintundo= tot;
+
+}
+
+void vpaint_undo()
+{
+ Mesh *me;
+ Object *ob;
+ unsigned int temp, *from, *to;
+ int a;
+
+ if((G.f & G_VERTEXPAINT)==0) return;
+ if(vpaintundobuf==0) return;
+
+ ob= OBACT;
+ me= get_mesh(ob);
+ if(me==0 || me->totface==0) return;
+
+ if(me->tface) tface_to_mcol(me);
+ else if(me->mcol==0) return;
+
+ a= MIN2(me->totface, totvpaintundo);
+ from= vpaintundobuf;
+ to= (unsigned int *)me->mcol;
+ a*= 4;
+ while(a--) {
+ temp= *to;
+ *to= *from;
+ *from= temp;
+ to++; from++;
+ }
+ allqueue(REDRAWVIEW3D, 0);
+ if(me->tface) mcol_to_tface(me, 1);
+}
+
+void clear_vpaint()
+{
+ Mesh *me;
+ Object *ob;
+ unsigned int *to, paintcol;
+ int a;
+
+ if((G.f & G_VERTEXPAINT)==0) return;
+
+ ob= OBACT;
+ me= get_mesh(ob);
+ if(me==0 || me->totface==0) return;
+
+ if(me->tface) tface_to_mcol(me);
+ if(me->mcol==0) return;
+
+ paintcol= vpaint_get_current_col();
+
+ to= (unsigned int *)me->mcol;
+ copy_vpaint_undo(to, me->totface);
+ a= 4*me->totface;
+ while(a--) {
+ *to= paintcol;
+ to++;
+ }
+ allqueue(REDRAWVIEW3D, 0);
+ if(me->tface) mcol_to_tface(me, 1);
+}
+
+void clear_vpaint_selectedfaces()
+{
+ Mesh *me;
+ TFace *tf;
+ Object *ob;
+ unsigned int paintcol;
+ int i;
+
+ ob= OBACT;
+
+ me= get_mesh(ob);
+ tf = me->tface;
+ if (!tf) return; /* should not happen, but you never know */
+
+ if(me==0 || me->totface==0) return;
+
+ paintcol= vpaint_get_current_col();
+
+ for (i = 0; i < me->totface; i++) {
+ if (tf[i].flag & TF_SELECT) {
+ tf[i].col[0] = paintcol;
+ tf[i].col[1] = paintcol;
+ tf[i].col[2] = paintcol;
+ tf[i].col[3] = paintcol;
+ }
+ }
+ allqueue(REDRAWVIEW3D, 0);
+}
+
+void vpaint_dogamma()
+{
+ Mesh *me;
+ Object *ob;
+ float igam, fac;
+ int a, temp;
+ char *cp, gamtab[256];
+
+ if((G.f & G_VERTEXPAINT)==0) return;
+
+ ob= OBACT;
+ me= get_mesh(ob);
+ if(me==0 || me->totface==0) return;
+
+ if(me->tface) tface_to_mcol(me);
+ else if(me->mcol==0) return;
+
+ copy_vpaint_undo((unsigned int *)me->mcol, me->totface);
+
+ igam= 1.0/Gvp.gamma;
+ for(a=0; a<256; a++) {
+
+ fac= ((float)a)/255.0;
+ fac= Gvp.mul*pow( fac, igam);
+
+ temp= 255.9*fac;
+
+ if(temp<=0) gamtab[a]= 0;
+ else if(temp>=255) gamtab[a]= 255;
+ else gamtab[a]= temp;
+ }
+
+ a= 4*me->totface;
+ cp= (char *)me->mcol;
+ while(a--) {
+
+ cp[1]= gamtab[ cp[1] ];
+ cp[2]= gamtab[ cp[2] ];
+ cp[3]= gamtab[ cp[3] ];
+
+ cp+= 4;
+ }
+ allqueue(REDRAWVIEW3D, 0);
+
+ if(me->tface) mcol_to_tface(me, 1);
+}
+
+
+void sample_vpaint() /* frontbuf */
+{
+ unsigned int col;
+ int x, y;
+ short mval[2];
+ char *cp;
+
+ getmouseco_areawin(mval);
+ x= mval[0]; y= mval[1];
+
+ if(x<0 || y<0) return;
+ if(x>=curarea->winx || y>=curarea->winy) return;
+
+ x+= curarea->winrct.xmin;
+ y+= curarea->winrct.ymin;
+
+ glReadBuffer(GL_FRONT);
+ glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col);
+ glReadBuffer(GL_BACK);
+
+ cp = (char *)&col;
+
+ Gvp.r= cp[0];
+ Gvp.r /= 255.0;
+
+ Gvp.g= cp[1];
+ Gvp.g /= 255.0;
+
+ Gvp.b= cp[2];
+ Gvp.b /= 255.0;
+
+ allqueue(REDRAWBUTSGAME, 0);
+}
+
+void init_vertexpaint()
+{
+
+ indexar= MEM_mallocN(sizeof(short)*MAXINDEX + 2, "vertexpaint");
+}
+
+
+void free_vertexpaint()
+{
+
+ if(indexar) MEM_freeN(indexar);
+ indexar= NULL;
+ if(vpaintundobuf) MEM_freeN(vpaintundobuf);
+ vpaintundobuf= NULL;
+ if(wpaintundobuf)
+ free_dverts(wpaintundobuf, totwpaintundo);
+ wpaintundobuf= NULL;
+}
+
+
+static unsigned int mcol_blend(unsigned int col1, unsigned int col2, int fac)
+{
+ char *cp1, *cp2, *cp;
+ int mfac;
+ unsigned int col=0;
+
+ if(fac==0) return col1;
+ if(fac>=255) return col2;
+
+ mfac= 255-fac;
+
+ cp1= (char *)&col1;
+ cp2= (char *)&col2;
+ cp= (char *)&col;
+
+ cp[0]= 255;
+ cp[1]= (mfac*cp1[1]+fac*cp2[1])>>8;
+ cp[2]= (mfac*cp1[2]+fac*cp2[2])>>8;
+ cp[3]= (mfac*cp1[3]+fac*cp2[3])>>8;
+
+ return col;
+}
+
+static unsigned int mcol_add(unsigned int col1, unsigned int col2, int fac)
+{
+ char *cp1, *cp2, *cp;
+ int temp;
+ unsigned int col=0;
+
+ if(fac==0) return col1;
+
+ cp1= (char *)&col1;
+ cp2= (char *)&col2;
+ cp= (char *)&col;
+
+ cp[0]= 255;
+ temp= cp1[1] + ((fac*cp2[1])>>8);
+ if(temp>254) cp[1]= 255; else cp[1]= temp;
+ temp= cp1[2] + ((fac*cp2[2])>>8);
+ if(temp>254) cp[2]= 255; else cp[2]= temp;
+ temp= cp1[3] + ((fac*cp2[3])>>8);
+ if(temp>254) cp[3]= 255; else cp[3]= temp;
+
+ return col;
+}
+
+static unsigned int mcol_sub(unsigned int col1, unsigned int col2, int fac)
+{
+ char *cp1, *cp2, *cp;
+ int temp;
+ unsigned int col=0;
+
+ if(fac==0) return col1;
+
+ cp1= (char *)&col1;
+ cp2= (char *)&col2;
+ cp= (char *)&col;
+
+ cp[0]= 255;
+ temp= cp1[1] - ((fac*cp2[1])>>8);
+ if(temp<0) cp[1]= 0; else cp[1]= temp;
+ temp= cp1[2] - ((fac*cp2[2])>>8);
+ if(temp<0) cp[2]= 0; else cp[2]= temp;
+ temp= cp1[3] - ((fac*cp2[3])>>8);
+ if(temp<0) cp[3]= 0; else cp[3]= temp;
+
+ return col;
+}
+
+static unsigned int mcol_mul(unsigned int col1, unsigned int col2, int fac)
+{
+ char *cp1, *cp2, *cp;
+ int mfac;
+ unsigned int col=0;
+
+ if(fac==0) return col1;
+
+ mfac= 255-fac;
+
+ cp1= (char *)&col1;
+ cp2= (char *)&col2;
+ cp= (char *)&col;
+
+ /* eerstmullen, dan fac blenden */
+ cp[0]= 255;
+ cp[1]= (mfac*cp1[1] + fac*((cp2[1]*cp1[1])>>8) )>>8;
+ cp[2]= (mfac*cp1[2] + fac*((cp2[2]*cp1[2])>>8) )>>8;
+ cp[3]= (mfac*cp1[3] + fac*((cp2[3]*cp1[3])>>8) )>>8;
+
+
+ return col;
+}
+
+static void vpaint_blend( unsigned int *col, unsigned int paintcol, int alpha)
+{
+
+ if(Gvp.mode==VP_MIX || Gvp.mode==VP_FILT) *col= mcol_blend( *col, paintcol, alpha);
+ else if(Gvp.mode==VP_ADD) *col= mcol_add( *col, paintcol, alpha);
+ else if(Gvp.mode==VP_SUB) *col= mcol_sub( *col, paintcol, alpha);
+ else if(Gvp.mode==VP_MUL) *col= mcol_mul( *col, paintcol, alpha);
+}
+
+
+static int sample_backbuf_area(int x, int y)
+{
+ unsigned int rect[129*129], *rt;
+ int x1, y1, x2, y2, size, a, tot=0, index;
+
+ if(totvpaintundo>=MAXINDEX) return 0;
+
+ if(Gvp.size>64.0) Gvp.size= 64.0;
+
+ x1= x-Gvp.size;
+ x2= x+Gvp.size;
+ CLAMP(x1, 0, curarea->winx);
+ CLAMP(x2, 0, curarea->winx);
+ y1= y-Gvp.size;
+ y2= y+Gvp.size;
+ CLAMP(y1, 0, curarea->winy);
+ CLAMP(y2, 0, curarea->winy);
+
+ glReadPixels(x1+curarea->winrct.xmin, y1+curarea->winrct.ymin, x2-x1+1, y2-y1+1, GL_RGBA, GL_UNSIGNED_BYTE, rect);
+ if(G.order==B_ENDIAN) IMB_convert_rgba_to_abgr( (int)(4*Gvp.size*Gvp.size), rect);
+
+ rt= rect;
+ size= (y2-y1)*(x2-x1);
+ if(size<=0) return 0;
+
+ memset(indexar, 0, 2*totvpaintundo+2); /* plus 2! first element is total */
+
+ while(size--) {
+
+ if(*rt) {
+ index= framebuffer_to_index(*rt);
+ if(index>0 && index<=totvpaintundo)
+ indexar[index] = 1;
+ }
+
+ rt++;
+ }
+
+ for(a=1; a<=totvpaintundo; a++) {
+ if(indexar[a]) indexar[tot++]= a;
+ }
+
+ return tot;
+}
+
+static unsigned int sample_backbuf(int x, int y)
+{
+ unsigned int col;
+
+ if(x>=curarea->winx || y>=curarea->winy) return 0;
+
+ x+= curarea->winrct.xmin;
+ y+= curarea->winrct.ymin;
+
+ glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col);
+ if(G.order==B_ENDIAN) SWITCH_INT(col);
+
+ return framebuffer_to_index(col);
+}
+
+static int calc_vp_alpha(MVert *mvert, short *mval)
+{
+ float fac, dx, dy, nor[3];
+ int alpha;
+ short vertco[2];
+
+ if(Gvp.flag & VP_SOFT) {
+ project_short_noclip(mvert->co , vertco);
+ dx= mval[0]-vertco[0];
+ dy= mval[1]-vertco[1];
+
+ fac= sqrt(dx*dx + dy*dy);
+ if(fac > Gvp.size) return 0;
+
+ alpha= 255.0*Gvp.a*(1.0-fac/Gvp.size);
+ }
+ else {
+ alpha= 255.0*Gvp.a;
+ }
+ if(Gvp.flag & VP_NORMALS) {
+ VECCOPY(nor, mvert->no);
+
+ /* transpose ! */
+ fac= vpimat[2][0]*nor[0]+vpimat[2][1]*nor[1]+vpimat[2][2]*nor[2];
+ if(fac>0.0) {
+ dx= vpimat[0][0]*nor[0]+vpimat[0][1]*nor[1]+vpimat[0][2]*nor[2];
+ dy= vpimat[1][0]*nor[0]+vpimat[1][1]*nor[1]+vpimat[1][2]*nor[2];
+
+ alpha*= fac/sqrt(dx*dx + dy*dy + fac*fac);
+ }
+ else return 0;
+ }
+
+ return alpha;
+
+}
+
+int calc_vp_alpha_dl(DispList *disp, MVert *mvert, int vert, short *mval)
+/* Lets us do soft vertex painting onto a deformed mesh */
+{
+ float fac, dx, dy, nor[3];
+ int alpha;
+ short vertco[2];
+
+ /* For safety's sake !*/
+ if (!disp || !disp->verts || !disp->nors)
+ return calc_vp_alpha (mvert+vert, mval);
+
+// make display list
+ if(Gvp.flag & VP_SOFT) {
+ project_short_noclip(disp->verts+(vert*3), vertco);
+ dx= mval[0]-vertco[0];
+ dy= mval[1]-vertco[1];
+
+ fac= sqrt(dx*dx + dy*dy);
+ if(fac > Gvp.size) return 0;
+
+ alpha= 255.0*Gvp.a*(1.0-fac/Gvp.size);
+ }
+ else {
+ alpha= 255.0*Gvp.a;
+ }
+
+ if(Gvp.flag & VP_NORMALS) {
+
+ VECCOPY(nor, disp->nors+(vert*3));
+
+// transpose !
+ fac= vpimat[2][0]*nor[0]+vpimat[2][1]*nor[1]+vpimat[2][2]*nor[2];
+ if(fac>0.0) {
+ dx= vpimat[0][0]*nor[0]+vpimat[0][1]*nor[1]+vpimat[0][2]*nor[2];
+ dy= vpimat[1][0]*nor[0]+vpimat[1][1]*nor[1]+vpimat[1][2]*nor[2];
+
+ alpha*= fac/sqrt(dx*dx + dy*dy + fac*fac);
+ }
+ else return 0;
+ }
+
+ return alpha;
+
+}
+
+
+void wpaint_undo (void){
+ Mesh *me;
+
+ me = get_mesh(OBACT);
+ if (!me)
+ return;
+
+ if (!wpaintundobuf)
+ return;
+
+ if (!me->dvert)
+ return;
+
+ if (totwpaintundo != me->totvert)
+ return;
+
+ free_dverts(me->dvert, me->totvert);
+
+ me->dvert= MEM_mallocN(sizeof(MDeformVert)*me->totvert, "deformVert");
+ copy_dverts(me->dvert, wpaintundobuf, totwpaintundo);
+
+ makeDispList(OBACT);
+ scrarea_do_windraw(curarea);
+
+};
+
+void copy_wpaint_undo (MDeformVert *dverts, int dcount){
+ if (wpaintundobuf)
+ free_dverts(wpaintundobuf, totwpaintundo);
+
+ wpaintundobuf = MEM_mallocN (sizeof(MDeformVert)*dcount, "wpaintundo");
+ totwpaintundo = dcount;
+ copy_dverts (wpaintundobuf, dverts, dcount);
+};
+
+void weight_paint(void)
+{
+ Object *ob;
+ Mesh *me;
+ MFace *mface;
+ TFace *tface;
+ float mat[4][4], imat[4][4];
+ int index, totindex;
+ short mval[2], mvalo[2], firsttime=1;
+ MDeformWeight *dw, *uw;
+ extern float editbutvweight;
+ DispList *dl;
+
+
+ if((G.f & G_WEIGHTPAINT)==0) return;
+ if(G.obedit) return;
+ if(G.obpose) return;
+
+ if(indexar==0) init_vertexpaint();
+
+ ob= OBACT;
+ me= get_mesh(ob);
+ if (!me->dvert){
+ return;
+ }
+ if(me==0 || me->totface==0) return;
+ if(ob->lay & G.vd->lay); else error("Active object not in this layer!");
+
+// if(me->tface==NULL && me->mcol==NULL) make_vertexcol();
+
+// if(me->tface==NULL && me->mcol==NULL) return;
+
+ /* imat voor normalen */
+ Mat4MulMat4(mat, ob->obmat, G.vd->viewmat);
+ Mat4Invert(imat, mat);
+ Mat3CpyMat4(vpimat, imat);
+
+ /* projektiematrix laden */
+ mymultmatrix(ob->obmat);
+ mygetsingmatrix(mat);
+ myloadmatrix(G.vd->viewmat);
+
+ getmouseco_areawin(mvalo);
+
+ if(me->tface) tface_to_mcol(me);
+ copy_vpaint_undo( (unsigned int *)me->mcol, me->totface);
+ copy_wpaint_undo(me->dvert, me->totvert);
+
+ getmouseco_areawin(mval);
+ mvalo[0]= mval[0];
+ mvalo[1]= mval[1];
+
+ while (get_mbut() & L_MOUSE) {
+ getmouseco_areawin(mval);
+
+ if(firsttime || mval[0]!=mvalo[0] || mval[1]!=mvalo[1]) {
+
+ if(firsttime) draw_sel_circle(mval, 0, Gvp.size, Gvp.size, 0);
+ else draw_sel_circle(mval, mvalo, Gvp.size, Gvp.size, 0);
+
+ firsttime= 0;
+
+ /* welke vlakken doen mee */
+ if(Gvp.flag & VP_AREA) {
+ totindex= sample_backbuf_area(mval[0], mval[1]);
+ }
+ else {
+ indexar[0]= sample_backbuf(mval[0], mval[1]);
+ if(indexar[0]) totindex= 1;
+ else totindex= 0;
+ }
+
+ MTC_Mat4SwapMat4(G.vd->persmat, mat);
+
+ if(Gvp.flag & VP_COLINDEX) {
+ for(index=0; index<totindex; index++) {
+ if(indexar[index] && indexar[index]<=me->totface) {
+
+ mface= ((MFace *)me->mface) + (indexar[index]-1);
+
+ if(mface->mat_nr!=ob->actcol-1) {
+ indexar[index]= 0;
+ }
+ }
+ }
+ }
+
+ if((G.f & G_FACESELECT) && me->tface) {
+ for(index=0; index<totindex; index++) {
+ if(indexar[index] && indexar[index]<=me->totface) {
+
+ tface= ((TFace *)me->tface) + (indexar[index]-1);
+
+ if((tface->flag & TF_SELECT)==0) {
+ indexar[index]= 0;
+ }
+ }
+ }
+ }
+
+ dl= find_displist(&ob->disp, DL_VERTS);
+ for(index=0; index<totindex; index++) {
+
+ if(indexar[index] && indexar[index]<=me->totface) {
+ mface= ((MFace *)me->mface) + (indexar[index]-1);
+
+
+ if (calc_vp_alpha_dl(dl, me->mvert, mface->v1, mval)){
+ dw= verify_defweight(me->dvert+mface->v1, ob->actdef-1);
+ uw= verify_defweight(wpaintundobuf+mface->v1, ob->actdef-1);
+ if (dw) dw->weight = editbutvweight*Gvp.a + (uw->weight*(1.0-Gvp.a));
+ }
+
+ if (calc_vp_alpha_dl(dl, me->mvert, mface->v2, mval)){
+ dw= verify_defweight(me->dvert+mface->v2, ob->actdef-1);
+ uw= verify_defweight(wpaintundobuf+mface->v2, ob->actdef-1);
+ if (dw) dw->weight = editbutvweight*Gvp.a + (uw->weight*(1.0-Gvp.a));
+ }
+
+ if (calc_vp_alpha_dl(dl, me->mvert, mface->v3, mval)){
+ dw= verify_defweight(me->dvert+mface->v3, ob->actdef-1);
+ uw= verify_defweight(wpaintundobuf+mface->v3, ob->actdef-1);
+ if (dw) dw->weight = editbutvweight*Gvp.a + (uw->weight*(1.0-Gvp.a));
+ }
+
+ if(mface->v4) {
+ if (calc_vp_alpha_dl(dl, me->mvert, mface->v4, mval)){
+ dw= verify_defweight(me->dvert+mface->v4, ob->actdef-1);
+ uw= verify_defweight(wpaintundobuf+mface->v4, ob->actdef-1);
+ if (dw) dw->weight = editbutvweight*Gvp.a + (uw->weight*(1.0-Gvp.a));
+ }
+ }
+ }
+ }
+
+ MTC_Mat4SwapMat4(G.vd->persmat, mat);
+
+ }
+ else BIF_wait_for_statechange();
+
+ if(mval[0]!=mvalo[0] || mval[1]!=mvalo[1]) {
+// makeDispList(ob);
+ scrarea_do_windraw(curarea);
+ screen_swapbuffers();
+ backdrawview3d(0);
+ draw_sel_circle(mval, 0, Gvp.size, Gvp.size, 0);
+
+ mvalo[0]= mval[0];
+ mvalo[1]= mval[1];
+ }
+ }
+
+ if(me->tface) {
+ MEM_freeN(me->mcol);
+ me->mcol= 0;
+ }
+
+ /* cirkel wissen */
+ draw_sel_circle(0, mvalo, 0, Gvp.size, 1);
+
+ makeDispList(ob);
+
+ allqueue(REDRAWVIEW3D, 0);
+
+}
+
+void vertex_paint()
+{
+ Object *ob;
+ Mesh *me;
+ MFace *mface;
+ TFace *tface;
+ float mat[4][4], imat[4][4];
+ unsigned int paintcol=0, *mcol, fcol1, fcol2;
+ int index, alpha, totindex, total;
+ short mval[2], mvalo[2], firsttime=1;
+
+ if((G.f & G_VERTEXPAINT)==0) return;
+ if(G.obedit) return;
+
+ if(indexar==0) init_vertexpaint();
+
+ ob= OBACT;
+ me= get_mesh(ob);
+ if(me==0 || me->totface==0) return;
+ if(ob->lay & G.vd->lay); else error("Active object not in this layer!");
+
+ if(me->tface==NULL && me->mcol==NULL) make_vertexcol();
+
+ if(me->tface==NULL && me->mcol==NULL) return;
+
+ /* imat voor normalen */
+ Mat4MulMat4(mat, ob->obmat, G.vd->viewmat);
+ Mat4Invert(imat, mat);
+ Mat3CpyMat4(vpimat, imat);
+
+ /* projektiematrix laden */
+ mymultmatrix(ob->obmat);
+ mygetsingmatrix(mat);
+ myloadmatrix(G.vd->viewmat);
+
+ paintcol= vpaint_get_current_col();
+
+ getmouseco_areawin(mvalo);
+
+ if(me->tface) tface_to_mcol(me);
+ copy_vpaint_undo( (unsigned int *)me->mcol, me->totface);
+
+ getmouseco_areawin(mval);
+ mvalo[0]= mval[0];
+ mvalo[1]= mval[1];
+
+ while (get_mbut() & L_MOUSE) {
+ getmouseco_areawin(mval);
+
+ if(firsttime || mval[0]!=mvalo[0] || mval[1]!=mvalo[1]) {
+
+ if(firsttime) draw_sel_circle(mval, 0, Gvp.size, Gvp.size, 0);
+ else draw_sel_circle(mval, mvalo, Gvp.size, Gvp.size, 0);
+
+ firsttime= 0;
+
+ /* welke vlakken doen mee */
+ if(Gvp.flag & VP_AREA) {
+ totindex= sample_backbuf_area(mval[0], mval[1]);
+ }
+ else {
+ indexar[0]= sample_backbuf(mval[0], mval[1]);
+ if(indexar[0]) totindex= 1;
+ else totindex= 0;
+ }
+
+ MTC_Mat4SwapMat4(G.vd->persmat, mat);
+
+ if(Gvp.flag & VP_COLINDEX) {
+ for(index=0; index<totindex; index++) {
+ if(indexar[index] && indexar[index]<=me->totface) {
+
+ mface= ((MFace *)me->mface) + (indexar[index]-1);
+
+ if(mface->mat_nr!=ob->actcol-1) {
+ indexar[index]= 0;
+ }
+ }
+ }
+ }
+ if((G.f & G_FACESELECT) && me->tface) {
+ for(index=0; index<totindex; index++) {
+ if(indexar[index] && indexar[index]<=me->totface) {
+
+ tface= ((TFace *)me->tface) + (indexar[index]-1);
+
+ if((tface->flag & TF_SELECT)==0) {
+ indexar[index]= 0;
+ }
+ }
+ }
+ }
+
+ for(index=0; index<totindex; index++) {
+
+ if(indexar[index] && indexar[index]<=me->totface) {
+
+ mface= ((MFace *)me->mface) + (indexar[index]-1);
+ mcol= ( (unsigned int *)me->mcol) + 4*(indexar[index]-1);
+
+ if(Gvp.mode==VP_FILT) {
+ fcol1= mcol_blend( mcol[0], mcol[1], 128);
+ if(mface->v4) {
+ fcol2= mcol_blend( mcol[2], mcol[3], 128);
+ paintcol= mcol_blend( fcol1, fcol2, 128);
+ }
+ else {
+ paintcol= mcol_blend( mcol[2], fcol1, 170);
+ }
+
+ }
+
+ total= 0;
+
+ total+= alpha= calc_vp_alpha(me->mvert+mface->v1, mval);
+ if(alpha) vpaint_blend( mcol, paintcol, alpha);
+
+ total+= alpha= calc_vp_alpha(me->mvert+mface->v2, mval);
+ if(alpha) vpaint_blend( mcol+1, paintcol, alpha);
+
+ total+= alpha= calc_vp_alpha(me->mvert+mface->v3, mval);
+ if(alpha) vpaint_blend( mcol+2, paintcol, alpha);
+
+ if(mface->v4) {
+ total+= alpha= calc_vp_alpha(me->mvert+mface->v4, mval);
+ if(alpha) vpaint_blend( mcol+3, paintcol, alpha);
+ }
+
+ /* if(total==0) { */
+ /* alpha= 25*Gvp.a; */
+ /* vpaint_blend( mcol, paintcol, alpha); */
+ /* vpaint_blend( mcol+1, paintcol, alpha); */
+ /* vpaint_blend( mcol+2, paintcol, alpha); */
+ /* if(mface->v4) vpaint_blend( mcol+3, paintcol, alpha); */
+ /* } */
+ }
+ }
+
+ MTC_Mat4SwapMat4(G.vd->persmat, mat);
+
+ }
+ else BIF_wait_for_statechange();
+
+ if(mval[0]!=mvalo[0] || mval[1]!=mvalo[1]) {
+ do_shared_vertexcol(me);
+ if(me->tface) {
+ mcol_to_tface(me, 0);
+ }
+
+ scrarea_do_windraw(curarea);
+ screen_swapbuffers();
+ backdrawview3d(0);
+ draw_sel_circle(mval, 0, Gvp.size, Gvp.size, 0);
+
+ mvalo[0]= mval[0];
+ mvalo[1]= mval[1];
+ }
+ }
+
+ if(me->tface) {
+ MEM_freeN(me->mcol);
+ me->mcol= 0;
+ }
+
+ /* cirkel wissen */
+ draw_sel_circle(0, mvalo, 0, Gvp.size, 1);
+
+ allqueue(REDRAWVIEW3D, 0);
+}
+
+void set_wpaint(void) /* toggle */
+{
+ Object *ob;
+ Mesh *me;
+
+ scrarea_queue_headredraw(curarea);
+ ob= OBACT;
+ me= get_mesh(ob);
+
+ if(me && me->totface>=MAXINDEX) {
+ error("Maximum number of faces: %d", MAXINDEX-1);
+ G.f &= ~G_WEIGHTPAINT;
+ return;
+ }
+
+// if(me && me->tface==NULL && me->mcol==NULL) make_vertexcol();
+
+ if(G.f & G_WEIGHTPAINT) G.f &= ~G_WEIGHTPAINT;
+ else G.f |= G_WEIGHTPAINT;
+
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWBUTSEDIT, 0);
+ allqueue(REDRAWBUTSGAME, 0);
+
+ if(G.f & G_WEIGHTPAINT) {
+ setcursor_space(SPACE_VIEW3D, CURSOR_VPAINT);
+ }
+ else {
+ freefastshade(); /* voor zekerheid */
+ if (ob)
+ makeDispList(ob);
+ if(!(G.f & G_FACESELECT))
+ setcursor_space(SPACE_VIEW3D, CURSOR_STD);
+ }
+}
+
+
+void set_vpaint(void) /* toggle */
+{
+ Object *ob;
+ Mesh *me;
+
+ scrarea_queue_headredraw(curarea);
+ ob= OBACT;
+ me= get_mesh(ob);
+
+ if(me && me->totface>=MAXINDEX) {
+ error("Maximum number of faces: %d", MAXINDEX-1);
+ G.f &= ~G_VERTEXPAINT;
+ return;
+ }
+
+ if(me && me->tface==NULL && me->mcol==NULL) make_vertexcol();
+
+ if(G.f & G_VERTEXPAINT){
+ G.f &= ~G_VERTEXPAINT;
+ }
+ else {
+ G.f |= G_VERTEXPAINT;
+ /* Turn off weight painting */
+ if (G.f & G_WEIGHTPAINT)
+ set_wpaint();
+ }
+
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWBUTSEDIT, 0);
+ allqueue(REDRAWBUTSGAME, 0);
+
+ if(G.f & G_VERTEXPAINT) {
+ setcursor_space(SPACE_VIEW3D, CURSOR_VPAINT);
+ }
+ else {
+ freefastshade(); /* voor zekerheid */
+ if (ob) makeDispList(ob);
+ if((G.f & G_FACESELECT)==0) setcursor_space(SPACE_VIEW3D, CURSOR_STD);
+ }
+}
+
diff --git a/source/blender/src/windows_creator_splash.jpg.c b/source/blender/src/windows_creator_splash.jpg.c
new file mode 100644
index 00000000000..577ca6b0c83
--- /dev/null
+++ b/source/blender/src/windows_creator_splash.jpg.c
@@ -0,0 +1,989 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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
+/* DataToC output of file <splash_jpg> */
+
+int datatoc_splash_jpg_size= 30379;
+char datatoc_splash_jpg[]= {
+255,216,255,224, 0, 16, 74, 70, 73, 70, 0,
+ 1, 2, 0, 0,100, 0,100, 0, 0,255,236, 0, 17, 68,117, 99,107,121, 0, 1, 0, 4, 0, 0, 0, 50, 0, 0,255,238, 0, 14,
+ 65,100,111, 98,101, 0,100,192, 0, 0, 0, 1,255,219, 0,132, 0, 8, 6, 6, 6, 6, 6, 8, 6, 6, 8, 12, 8, 7, 8, 12,
+ 14, 10, 8, 8, 10, 14, 16, 13, 13, 14, 13, 13, 16, 17, 12, 14, 13, 13, 14, 12, 17, 15, 18, 19, 20, 19, 18, 15, 24, 24, 26, 26,
+ 24, 24, 35, 34, 34, 34, 35, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 1, 9, 8, 8, 9, 10, 9, 11, 9, 9, 11, 14, 11, 13, 11,
+ 14, 17, 14, 14, 14, 14, 17, 19, 13, 13, 14, 13, 13, 19, 24, 17, 15, 15, 15, 15, 17, 24, 22, 23, 20, 20, 20, 23, 22, 26, 26, 24,
+ 24, 26, 26, 33, 33, 32, 33, 33, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,255,192, 0, 17, 8, 1, 15, 1,244, 3, 1, 34, 0, 2,
+ 17, 1, 3, 17, 1,255,196, 0,194, 0, 0, 1, 5, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 2, 4, 5, 6,
+ 0, 7, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 16, 0, 2, 1,
+ 3, 2, 4, 2, 5, 7, 7, 8, 7, 4, 6, 11, 1, 1, 2, 3, 0, 17, 4, 18, 5, 33, 49, 19, 6, 65, 20, 81, 97,113, 34, 50,
+129,145,161,209, 66, 21, 7,193,225, 82,146,178, 35, 51,177, 98,114,130, 67,115, 36, 22,240,210, 83, 99,131,195, 52,162,211, 84,
+ 54,147,163,179,132,196, 37,241,194,226, 68,100,116,148,164, 53, 69, 23, 38, 17, 0, 2, 2, 1, 2, 4, 4, 3, 5, 7, 4, 3,
+ 0, 0, 0, 0, 0, 1, 17, 2, 3, 33, 4, 49, 65, 81, 18, 97,113, 19, 5,129,145, 34,161,177,193,209, 50,240,225, 66, 82, 98,
+146, 20,114, 35, 51, 21,241,147, 52,255,218, 0, 12, 3, 1, 0, 2, 17, 3, 17, 0, 63, 0,246, 67, 44,170,177,170,200,202, 58,
+113,216, 2, 64,248, 22,157, 28,211, 27,222, 70, 63,214, 52, 39,251, 31,221,199,251, 11, 78,136,112,160, 31, 36,211,134, 22,145,
+173,111,210, 52,195,147, 48, 63,196,127,214, 53,210, 94,255, 0, 37, 9,175,107,154, 16, 55,152,154,215, 18, 55,235, 26, 97,159,
+ 32,155,117, 92,127, 88,253,116,197,189,175,110, 52,224, 63, 61, 0, 65, 52,252,140,175,250,199,235,164,234, 77,225, 52,159,172,
+105, 56, 87,112, 20, 2,153,114, 57,137, 95,245,141, 55,204,100,218,253, 86,253, 99, 93,198,247,240,166,158, 30,202, 0,121, 25,
+ 89, 74, 20,117, 93,110,111,112,198,132,217,153, 86,176,158, 75,255, 0, 77,190,186,102, 91, 19, 34,173,248, 1,113,242,159,205,
+ 64,191, 11,212,101, 14, 50,242,207, 60,137, 63, 93,190,186,119,155,202,183,241,228,253,118,250,232, 11,114, 44, 41,116,250,104,
+ 7,140,204,195,202,121, 63, 93,190,186,112,202,204, 60, 60,196,159,174,223, 93, 13, 0, 6,187, 80,185, 52, 4,129,147,148, 0,
+253,252,159,174,223, 93,115,101,228,143,237,228,253, 99,245,212,114,215,181,171,135, 30, 38,128,145, 30,108,250,142,169,220,122,
+ 46,199,235,162,140,169,219,148,237,111, 78,179,245,208,225, 95,112,146, 1, 23, 63, 85,119, 78, 34, 73,208, 56,115, 60, 42, 0,
+167, 43, 33, 64, 61, 71, 35,211,168,253,116,225,149, 63,140,175,234,247,143,215, 81, 66, 33, 54, 26,138,155,145,107,216, 91,217,
+ 74,177, 48,184, 12,126, 95, 69, 1, 32,100,228, 17,126,179,241,240,212,126,186,239, 49,147,199,247,175,250,199,235,168,218, 92,
+ 88,171, 2, 7,170,156, 76,136,190,242,131,236, 60,120,252,148, 1,252,196,246,254, 51,254,177,250,232, 47,147,144,150, 38,121,
+ 63, 93,143,229,166, 23, 60,244,145,235,166, 18, 30,192, 11, 91,159, 10,160, 41,204,200,182,161, 59,129,107,147,169,190,186,140,
+217,217,142,196,137,229, 3,192, 7,111,174,147, 32, 16, 84,125,147, 77, 69,176, 44,220, 7, 59,250, 5, 80, 27,206,101,162,221,
+178, 36, 62,129,173,184,159,158,155,231,115, 87,226,200,144,147,196,251,237, 97,244,208, 12,128,176, 39,151, 36, 20,215, 12,198,
+224,216,122,104, 3, 28,204,208,110,114,165, 3,208, 29,190,186,112,206,203, 97,117,200,151,245,219,235,168,227, 73, 22, 62,245,
+169, 1, 55,176, 22, 20, 1,198,102,117,253,236,153, 7,245,219,235,164,243,249,136,226,249, 50,144,124, 53,183,215, 64,144, 1,
+196,154,116, 49,235, 58,156,112,160, 38,121,252,163,192, 79, 33,191,243,219,235,161,249,172,245,185,108,137,120,242, 29, 70,250,
+235,128, 0,220, 10, 70, 26,143,178,128,107,102,231,248, 79, 47,235,183,215, 74, 50,183, 6, 23,243, 18,175,245,219,235,174, 0,
+ 6,231,242, 83, 76,161,156,170,142, 2,128, 42,207,153,194,249, 51, 31,248,140, 7,242,211,219, 59, 34, 62, 7, 34, 75,255, 0,
+ 77,190,186,134,229,239,197,172, 41, 27, 79,197,107,154, 2, 75,103,102, 91,221,158, 67,127,231,183,215, 76, 57,249,129,108,114,
+ 36,213,234,118,250,232, 58,137, 94, 60, 9,166,132, 0,223,153,160, 12,185,153,195,137,201,151,229,145,190,186, 47,222, 25, 96,
+ 91,175, 33, 62,146,237,245,212,106,235, 84,146,192,111, 61,154,127,251,196,191,174,223, 93,119,157,205,255, 0,196,203,250,237,
+245,208,111,232,164,227, 64, 72,243,185,159,248,153,127, 93,190,186,239, 59,155,255, 0,136,151,245,219,235,160,172,108,223, 10,
+147,110,118, 20, 79, 46,227,226,178,250,201, 31,146,133, 29,231, 51,127,241, 50,254,187,125,116,190,115, 51,255, 0, 17, 47,235,
+183,215, 72, 34,140,115, 98,222,155, 15,202,105,193, 21, 69,194,113,254,113,164, 18, 81,222,115, 55,255, 0, 17, 47,235,183,215,
+ 79, 89,247, 6, 54, 19, 75,242,187, 15,229, 52,128,181,253,211,110, 87,210, 45, 78, 17,234,241, 39,211,122, 9, 30, 38,203, 6,
+207,150,227,210, 3,177, 63,203, 68, 25, 50, 0, 15, 94,119, 60,254, 50, 1,254, 90, 8,143,222, 42, 71,174,244, 97, 21,215,135,
+ 46, 71,215, 64, 59,207,100,169, 10,142,194,231,237, 51, 55,237, 26, 70,200,203, 99,198,105, 7,177,136, 28, 61,149,205,208, 69,
+247,217,111,127, 77, 50, 92,172,100, 85, 0,146, 0,240, 28,232, 65,195, 35, 36,139,137,228,229,250, 77,207,231,167,117,179, 47,
+110,172,150,225,115,169,190,186,132,251,154, 14, 17,197,242,147, 76,243,243, 30, 54, 22,244, 85, 41,102, 95, 42,215, 19,200, 63,
+174,126,186, 67,149, 36,100,106,201,111,149,201,252,181, 75, 36,211, 61,181, 57, 55,245,210, 69, 11, 59,129,233,160,130,236,231,
+ 11, 27,100,200,124, 88,130,198,195,242, 83, 27,118, 85, 28, 38,145,141,173,123,145,249,106,187,203,158, 94, 62, 52, 57, 97, 34,
+192, 14,116, 5,199,222, 11,209,234,234,125, 93, 13, 90,238,111,110,190,142,124,235,170, 22,143,240,182,255, 0,240,182,255, 0,
+247, 85,213, 6,165,131,253,143,238,227,253,133,162, 40, 54,181, 49,184,152,255, 0,161, 31,236, 45, 20,112,170, 64, 50, 41, 4,
+113,240,166, 27,159, 11,218,137, 49, 26,135,178,134, 26,132, 20, 19,202,145, 89,174,111,202,148, 17, 92,109,202,244, 3,129,174,
+ 38,147,128, 28,107,174, 40, 5, 12, 24, 16, 60, 41,141,110, 84,183,183,133, 52,131,122, 2, 12,195, 84,204, 1,245,124,194,144,
+ 40,189,113,107,185,111, 79, 26, 75,159,158,161, 66, 92, 3, 76, 44, 77,112,231, 74,124, 40, 14, 0,215, 17,194,187, 87,133, 33,
+185, 52, 7, 49, 84, 4,158, 0, 14, 53, 75, 38,251, 46,191,220,198,186, 7, 45, 87, 36,252,196, 85,222,128, 65,191, 26,163,207,
+218, 26, 61, 83,226,141, 73,205,163,241, 30,207, 85,124,255, 0,114,123,165,142,182,219, 54,149,101,222, 63, 87,135,192,247,108,
+ 22,217,221,215,112,165,218, 21,103,244,151, 91,102,235,139,149, 24,140,251,147, 11,150, 67,198,255, 0,209,181, 75, 18, 70,110,
+110, 1,245,240,172, 42,179, 35, 6, 82, 85,135, 16, 71, 2, 13, 95, 96,111, 34, 66,176,229,144, 30,218, 86, 94, 64,255, 0, 75,
+215, 92, 54, 94,233, 92,145,143,112,213,109,193, 91,133,109,231,209,157,183,158,218,233, 57, 48, 77,171,206,188,235,229,213, 23,
+ 72,215, 3, 75,128, 9,185,227,225,234,163, 43,113,230,121, 80, 68,122,172, 56, 17,111,116,211, 66,139, 3,192, 88,219,135, 14,
+ 7,217, 95, 88,249, 97,253,210,120, 30, 39,141, 36,159,103,192,131,199,228,174, 88,199, 48,197, 84,241, 60,111,111,146,152,200,
+111,118,114,125,100, 15, 26, 1,204, 65,227,202,144,128,110, 71, 42, 97, 18,223,152, 63, 37, 57,120, 11,183, 51,206,170, 0,166,
+ 82,197,111,198,198,214,168,242, 72, 28,233,251, 10,120,159, 73,165,200,155, 91, 21, 94, 67,133,232, 12,192, 91, 72,170, 7,190,
+163,240,138, 65,196, 88,183,182,144, 51,178,218,213,203, 17,230, 79,205, 64, 38,181, 83,101, 30,218, 86, 12,255, 0, 8,176,167,
+ 5, 11,199,249,105,117,169, 54, 28, 77, 0,206,141,197,201,189, 17, 13,190, 74,102,167,191, 30, 2,145,130,252, 71,230,160, 15,
+123,138, 65,207,143, 10, 21,201, 94, 0,131, 74,173,101,227,206,128,123, 58,134,210, 56,147,204,208,201, 32,216,123,162,184,146,
+ 79,162,184, 35, 55, 32, 77, 36,176, 35, 16,222, 23,165,227, 69, 88, 24,252, 76,171,237, 63, 85,233,235, 12, 66,218,153,154,254,
+ 10, 45,244,154,128,143, 93,196,240, 28,106, 72, 69, 31, 10, 3,111, 22, 55,250,133, 40, 12,120, 41,183,137, 0, 90,130, 64, 8,
+164, 62, 22,246,240,254, 90,114,194,191,105,192,246,113, 52, 96,151,240,227,123, 18,104,130, 32, 1,191, 11, 85, 18, 5, 35,136,
+125,150, 99,235, 54, 7,242,209, 5,144,141, 17,170,216,220,220,106, 35,229,107,211,129,133, 64,214,226,254,179, 77,108,204, 88,
+197,133,216,248, 88, 84, 3,152, 72,222,243, 18, 86,153,211,244, 14,124,175, 77, 59,128, 96, 2, 71,192,122, 77, 71,151, 54,115,
+192, 89,125,130,169, 9,162, 18, 71, 31,150,185,250, 72, 46,238, 61,119, 53, 94, 30,105, 5,203, 19,242,211, 26, 54, 45, 99,225,
+ 66,193, 60,100, 99,160, 54, 55,246, 10, 99,238, 1,108, 18, 63,158,131, 20, 62,230,170, 89, 32,211,102,240,229, 64, 39,156,157,
+174, 69,151,217, 67,146, 89,223,226,114,126, 90,120, 64,139,115,227,198,164, 69, 18,206, 2,173,135,137, 53, 13, 70,132, 36,141,
+139, 15, 93, 73,242,199,231,227, 82, 76, 35, 30,236,228, 30, 28, 45, 81,134, 85,223,151, 14, 66,169,146, 57,142,220, 45,198,142,
+ 35,210,160, 26,144, 52,223, 89, 30,241,226, 13, 68,152,179, 57, 81,200, 84, 52,180,212, 48,131,169, 98,190, 21, 33, 33,104, 13,
+219,131,120, 15, 85, 7, 13,136, 58, 91,194,165, 78,196,198,204, 5,141, 8,220,185, 35,188,240,161,210, 26,199,213, 77,115, 27,
+128, 3, 94,255, 0,106,162,178, 0, 47,226,105,208,130, 47,232,163, 21,227,169, 97,210,255, 0, 11,241, 11,121,107,120,255, 0,
+226,111, 93, 79,176,242,218,124, 60,191,255, 0, 17, 93, 80,222,159,105, 36,124, 81,223,194, 56,255, 0, 97,104,151, 20,136,183,
+210,127,221,199,251, 11, 79, 49, 3,225, 90, 57, 17,230,182,161,236,160, 26,145, 52, 87,111,146,130, 98, 54,161, 6,131, 75,171,
+198,144,194, 71,137,167, 8,184,115,160, 18,254, 55,174,213,227, 74, 33, 35,198,184,163, 91,133, 0,151, 52,174,196, 35, 16,120,
+128, 72,249,169, 44,195,194,133, 53,250,100,122,109,106, 2, 56,224, 41, 9, 23,246, 87,105,244,210,129, 80,162,113,168, 19,238,
+248,145, 62,129,170, 82, 57,149,181,190,115, 83,229, 93,104,200, 13,139, 2,160,250, 46, 43, 50,251,118,100,108, 84,196, 77,188,
+ 87,136,175,159,238, 27,141,206, 37, 69,183,163,125,211, 54, 75,186, 60, 15,118,199, 6,223, 43,183,175,120,136,138,207,108,248,
+150, 99,125,199, 31,217, 63,209, 75,247,238, 63,251, 39,250, 42,167,200,102,127,176,127,154,184,224,229,128, 73,133,128, 28, 73,
+ 35,149,124,207,243,253,199,249, 95,254,191,220,125, 15,240,182, 31,204,191,191,247,150,255, 0,127, 65,111,225, 63,209, 72, 55,
+248, 71,246, 79,244, 85, 13,117,115,255, 0,182,221,255, 0, 50,254,212,116,255, 0,172,218,255, 0, 43,254,230, 76,205,159, 19,
+ 32,245, 32,137,162,147,237,114,210,125,126,218,135, 82, 49,240,115, 50,191,233,177,228,148,122, 81, 73, 31, 56,163,190,203,187,
+ 70,186,159, 10, 96, 61, 33, 9,254, 74,242,221,101,202,222, 95, 77,235,171,117,172, 87,236, 61, 52,120,177, 37,143,189,105,193,
+ 90,210,254,208,187,110,243, 46, 25, 17, 77,121, 32,228, 63, 73,125,149,162,139, 42, 9,149, 36,141,195, 33,227,122,197, 50,178,
+146,172, 10,176,224, 65,224, 69, 72,194,206,159, 6, 77,113, 27,169,248,163, 63, 9,175,110,203,220,239,134, 49,230,155, 83,132,
+255, 0, 21,127, 52,120,247,158,221, 76,179,147, 20, 86,252, 99,248,109,251,205,173,227, 63, 11, 94,244,209,107,241, 62,193,225,
+ 64,194,204,198,220, 98,234, 70, 61,241,241,198,109,117, 52,116,138, 38,213,238,218,191, 67, 75,214,245, 87,163, 86,171,213, 52,
+124, 43,210,212,179,165,211,171, 92, 83, 22,196,113, 6,161,207, 41,227, 26,159,233, 26,172,220, 59,183,183,182,173,209,182,172,
+249,228,199,153, 2,182,182, 86, 49,217,198,161,197,117,125, 34,164, 99,230, 97,231,171, 79,131,144,153, 16,150, 32, 73, 27, 6,
+ 28, 60, 56,120,215, 95, 78,233, 43, 58,180,158,169,198,135, 42,228,165,155,173,108,155, 92, 84,234,190, 1, 2,169,224,120,211,
+186,104,188,105,108, 71, 30, 0, 83, 24,134, 62,161,202,161,177, 89,213, 71,166,184,179, 21,247,120,122,104, 51, 77, 20, 8,102,
+157,214, 40,215,226,145,200, 85, 23,225,204,212,120,247, 93,182, 87, 17, 67,155, 4,146, 57,178,162,202,140, 73,244, 0, 13,234,
+164,222,169, 50, 54,147,134,210, 37,139,114,102,185,174,226, 13,149,108, 60, 77, 32, 30, 35,157, 21, 23, 85,139, 15, 96,168, 81,
+140, 3, 91,137,246, 10,122,199, 41, 22, 9,111,111,231,163,170,183, 33,194,212,253, 7,129, 38,212, 4,110,137,251, 76, 63,150,
+148, 70,131,215, 69,115, 18,220,150, 22,166,117,225, 28,174,212, 7, 5, 0,216, 15,101, 16, 33, 35,249,106, 63,155,187,123,171,
+ 77,147, 38,126, 74,116,251, 40, 9,145,199,194,252,184,124,148,191,185, 93, 58,156, 95,219, 85,196,202,192,221,137,167, 69, 9,
+ 39,143, 42,133,100,183,202,198, 82,121,177,240, 0,125,116,195,154, 57,162,113,240,189, 2, 72,108, 69,133,239,202,153, 60,216,
+184, 81, 25,179, 38, 72, 98, 79,138, 73, 24, 42,143, 14,102,175,130, 11,155,122, 37,212, 39,155,200,144,216, 27, 15, 80,164,148,
+204, 69,217,137,170,124, 62,238,237,249,247, 24,118,204, 76,131,145, 60,196,170,180,104,116, 2, 1, 99,119,109, 62, 3,194,175,
+153,210, 64, 64, 53,111, 91, 86, 59,234,235, 42,117,208,205, 47, 75,207,101,149,161,198,142, 72,136,132,147, 79,104, 72, 34,244,
+247,180, 96,105,226,104,145,184,113,118, 91,241,172,155,112,180, 27, 28, 74,169,199,196,240,174,150, 50, 91,128,191, 10,108,206,
+236,214, 6,192,113,181, 57, 28,244,248,243,189, 24,170,150,117,196, 75,164,243,163, 42, 35,141, 68,219,217, 81,153, 75, 57, 39,
+194,141, 25,208,131,133, 3,124,134, 75, 35, 33, 10,188,135, 47,101, 18, 41, 25,214,231,195,133,169,179, 43, 94,246,231,202,150,
+ 52,101, 22,183,182,140,181,234,198, 78, 11, 16, 7, 0,105,216,247, 66,195,213,249,104,226, 30,167,168,142, 68,209,132, 40,138,
+ 1, 96, 90,220,104,137,103, 44, 12,247, 49,144, 56,240,168, 97, 53, 16, 5, 88, 42,198, 56, 51, 92,158, 20,210, 33, 78, 8,188,
+252,104, 64, 44,126,205,248,242,174, 56,238,110,234, 46, 15,162,139,227,193,120,243,165, 15, 45,141,141,191, 61, 3, 98, 70,157,
+ 37, 55,226,198,158, 28, 50,216,129,236, 52,205, 45,127,120,218,230,215,174,233,134, 58,111,123,158,117, 96,146, 9,177,129, 35,
+247,139,111, 27,158, 84, 81, 4,106,128, 9, 86,254, 39,143, 26,227, 26, 14, 23, 58,249, 48,240,245, 83,196, 11,164, 92,142, 28,
+ 77, 66,200,125, 43,229,237,212, 31,244,246,189,143, 46,191, 58,234,235, 15, 47,125, 6,222, 94,223,250,255, 0,244, 53,212, 18,
+ 78,140, 0,136,125, 41, 31,236, 45, 57,136,166, 14, 8,151,255, 0,102,159,178, 41, 65, 4, 94,169,144, 50,146, 15,201, 67,189,
+233,114, 27,223, 30, 28, 40, 87,181, 0, 78, 20,160,129, 65, 12, 15,141, 62,244, 3,181, 3,234,174,166, 82,130, 5, 0,190, 55,
+ 34,163,229, 48,208, 20,122,111,243, 81,153,170, 30, 73, 37,213,124, 45, 70, 16, 32, 77,172, 43,133,207, 26, 81,192, 82,130, 0,
+168, 81, 45,227, 73,107,181, 45,205,170, 22,102,124, 88, 99, 77,245,204,121, 32,240,254,149,115,203,150,152,168,239,146,202,181,
+ 92,217,188,120,239,146,202,152,234,236,223, 36, 74,155, 34, 28, 88,245,202,214, 30, 3,196,250,128,172,246,110,227, 46, 89, 42,
+ 61,200,175,193, 7,143,244,170, 60,249, 18,228,191, 82, 86,185,240, 30, 0,122,168, 85,249,221,239,185, 95, 60,211, 28,211, 31,
+ 78,118,255, 0, 87,228,125,237,159,183,211, 12, 94,241,123,253,149,242,252,206,173,174,195,218,145, 44,105,153,186, 38,185, 26,
+204,152,231,225, 81,225,175,210,125, 85, 71,218,248, 73,155,187,196, 36, 23,142, 16,102, 97,233,211,109, 63,246,136,173, 15,226,
+ 7,113, 75,219, 93,181,145,155,138, 64,203,153,151, 31, 21,143,217,121, 47,239,255, 0, 85, 84,145,235,175, 87,179,108, 43,153,
+250,183, 74,223, 87,109, 42,248, 79, 59, 51,205,238,219,231,134,175, 29, 91,172, 87,186,237,113,142,136,126,251,222,253,177,218,
+228, 99,102,228,143, 48,163,134, 38, 58,235,117, 31,206, 85,224,191,214, 34,168,113,255, 0, 25,123, 74,105, 52, 75, 30, 94, 58,
+223,248,146, 68,165,126, 94,155,187,125, 21,224,178,203, 36,210, 60,211, 59, 73, 44,132,179,187, 18, 89,152,241, 36,147,204,154,
+101,126,206,190,223,137, 86, 44,219,125, 86,159, 36,126, 58,254,229,153,218,106,170,151, 71,175,205,159, 83,244,182, 30,234,194,
+ 25, 88,210, 71,149, 19,240,143, 42, 18, 53, 41,244, 95,152, 35,244, 90,176,187,190,211, 62,209,148, 96,151,222, 70,247,162,148,
+114,101,250,199,141,121,239,225,255, 0,115,229,118,230,255, 0,141,105, 15,145,204,145, 32,204,132,159,116,171,157, 34, 75,126,
+146, 19,123,252,149,239,125,211,132,185,123, 68,175,111,222, 99,254,245, 15,179,226, 31,171, 95,159,247,191,106,162,173,175, 85,
+245, 36,236,172,180,118, 75,141,108,126,131,217,189,210,214,117,165,191, 75,106,182,175, 21, 86,248, 90,167,159, 97,229, 73,135,
+ 58,207, 25,229,241, 47,131, 15, 16,107,105,141,147, 28,177, 44,202,195, 76,158,240, 39,133, 97, 43, 75,219,179,179,227,201, 1,
+254,201,131, 47,177,191, 56,175,143,236,251,135, 92,175, 3,127, 77,211,107,194,203,243, 71,213,247, 92, 10,216,214,100,190,170,
+ 52,159,141, 95,228,207, 42,252, 74, 32,247, 94, 65, 82, 8,233, 67,196,127, 64, 86,151,240,251, 51, 19, 7,182,230,159, 46,100,
+130, 53,201,123,188,140, 20,124, 9,226,107, 53,248,148, 45,221,121, 3,253,212, 63,176, 42,143,106,218,247, 61,242, 65,131,132,
+ 11,164,119,118,212,214,142, 61, 86, 5,143,182,222,218,253,207,167, 92,155, 76,117,181,187, 82,173, 91,126, 9, 31,136, 89,109,
+143,121,146,213,175,125,157,172,146,241,108,245,121, 59,223,182, 11,244,206,224, 61,100, 71, 33, 95,156, 37,170,207, 7,114,219,
+183, 52, 47,129,145, 30, 64, 94, 97, 24, 18, 61,163,152,175, 56,151,240,215,120, 88, 12,144,228, 65, 52,128, 95,164, 11, 41, 62,
+160, 88, 91,231,172,170, 73,159,179,230,146,140,248,185,152,236, 65,183,186,202,195,152, 53,197,109, 48,100, 79,209,202,219, 93,
+127,100,122, 30,247,113,137,175, 95, 18, 73,244,211,243, 61,103,189,129, 29,179,159,171,209, 31, 15,248,169, 94,103,218,191,249,
+139,110,183,251, 97,249,107,107,184,111, 75,191,118, 30, 94, 99, 0,185, 41,211,139, 37, 71, 32,226, 72,248,129,232, 96,111, 88,
+190,212, 23,238, 45,184,127,190, 31,200,107,166,218,174,187,124,213,182,141, 59, 39,253,167, 61,213,235,125,206, 11,213,202,178,
+163, 95,220,123,101,213, 84,179,184, 85, 81,118, 36,128, 0, 30,146,106,143, 51,191, 59,115, 6, 67, 24,201,235,184,224,122, 42,
+ 92, 15,235,124, 63, 77, 98,187,243,184,103,201,206,147,102,198,114,152,152,199, 76,224, 27,117, 36, 28,245,122,151,149,189, 53,
+ 23,181,123, 57,183,248,159, 51, 38, 99,143,134,141,211, 82,162,238,236, 5,206,155,240, 0, 95,157,112,166,211, 29,113,172,185,
+236,234,158,169, 47, 30, 7,124,155,204,150,202,240,237,234,172,214,141,191, 14, 38,218, 63,196,109,138,103,210,102,146, 16,120,
+106,120,205,191,236,234,171,220,108,232,119, 24,196,248,121, 11, 60, 71,237,198,193,133,253, 6,213,135,221,255, 0, 13,161,135,
+ 21,231,218,178,100,121,144, 22, 16, 77,164,235,176,189,149,148, 45,143,163,133, 99,246, 29,243, 47, 97,207, 76,184, 24,152,238,
+ 6, 68, 55,247, 93, 60, 65, 30,159, 65,240,170,182,184,114,209,219,111,103, 43,149,131,221,231,195,117, 77,205, 20, 91,248,170,
+123,139,199,101,164, 10,136,132,185, 0, 0, 73, 39,128, 0, 87,155,254, 33,231,200,242,109,147, 99, 76,235, 28,208,188,138, 81,
+138,220, 49, 82, 15, 15, 85,101,246,230,222,247, 73, 14,211,133, 44,178,156,162, 58,145,151, 54, 33, 46,110,228,158, 10, 47,198,
+177,143,100,239,141,100,119, 85, 79,140,174, 16,245, 55,147,126,169,149,226, 88,221,154,225, 15,140,173, 52, 61, 79, 35,189, 59,
+103, 6, 83, 19,230, 9, 92,112, 61, 21,105, 0,254,178,141, 63, 77, 75,219,187,155, 96,222, 28, 71,133,152,166, 99,202, 25, 1,
+141,207,244, 67,129,127,146,176,173,248, 99,186,172, 58,252,228, 6, 91,127, 14,207,107,250, 53, 91,242, 86, 50,120, 50, 48,114,
+100,199,152, 24,178, 32,114,172, 60, 85,148,248, 17, 93,105,180,219,100, 77, 99,200,221,151,237,192,227,125,238,235, 19, 86,203,
+137, 42,190, 95,190, 79,161, 32,117, 50,105, 97,116, 52, 45,211,113,193,219, 99, 15,145, 60,120,200,222, 50, 48, 4,251, 47,206,
+179, 56, 29,202,113,251, 42, 61,255, 0, 40,117, 50, 35, 6, 5, 7,251, 73,131, 20, 91,251, 64,212,107,203,115,115,183, 13,235,
+ 56,228,101, 59,228,101, 78,193, 84,115,226, 77,149, 17,124, 7,160, 10,227,131,101,107,218,221,207,182,180,110,173,245,107,161,
+223,113,191,173, 43, 78,197,221,107,165,100,186, 39,212,245,244,239,190,216, 4, 35,103,141, 92,175,211,146,223, 62,139, 85, 95,
+121,102,225,238, 61,173,149,145,133, 58,100, 71,174, 33,170, 54, 13,111,222, 47, 3,110, 85,157,196,252, 50,222,231,128, 75,145,
+ 60, 24,206,194,253, 38, 44,204, 63,165,160, 17,244,213, 14,243,177,238,253,185, 33,198,204,225, 14, 64,176,146, 38, 38, 41, 66,
+155,250,185, 30, 54, 34,187,227,219,237,253, 74,250, 89,102,213,105,195,214, 99,161,231,203,186,221,122, 86, 89,112,197,109, 86,
+165,105, 19,215,136,110,205,255, 0,204,219,127,244,219,255, 0,102,213,237, 0,164, 74,243, 72,193, 35, 81,118,118, 54, 80, 7,
+164,154,241,142,202,255, 0,205, 59,111, 11,251,237,195,254, 27, 85,159,126,247, 36,251,134,227, 46,211,142,221, 60, 12, 54,208,
+200,166,221, 73, 87,226,103,244,233, 60, 0,171,186,193,108,219,138,213, 56, 74,146,223,132,179, 59, 77,197,112,109,175,118,165,
+187,194, 93, 92, 35,103,155,223, 61,183,139, 33, 79, 52,103, 97,123,244, 80,184,253,110, 10,126, 67, 76,197,252, 65,237,153, 24,
+ 35,205, 36, 58,143,197, 36,102,194,255, 0,208,213, 88,254,209,236, 86,238, 28,118,220, 51, 39, 56,216, 97,138, 71,160, 2,242,
+ 21,248,136, 45,192, 11,240,171,125,247,240,198, 44, 92, 41,114,246,140,153, 36,146, 21, 46,113,230, 10, 75,128, 46, 66,178, 5,
+227,232,225, 92,222, 29,157,109,233,218,246,238,224,223, 41,249, 29, 86,125,245,235,234,214,148,237,226,151, 54,190,102,251, 30,
+ 92, 93,194, 37,202,194,158, 57,225,110, 79, 27, 6, 23,249, 42, 65,137, 71, 13, 92, 43,194,123,107,184, 50,123,127,113,143, 37,
+ 9,108,102, 33,114,160,191, 7, 79, 30, 31,164, 60, 13,105,255, 0, 19, 50,165, 77,203, 2, 76, 89,157, 34,151, 20, 58,148, 98,
+161,129,118,179,112,245, 86, 45,177,107, 53,113,247,105,100,218,180,116,228,110,158,224,158, 27,100,237,250,170,210,117,158,188,
+211, 61, 51, 35, 39, 15, 19, 29,167,201,117,138, 24,197,222, 87, 33, 64, 30,178,106,143, 7,188,246, 29,211,113, 77,179, 5,222,
+ 73,164, 45,211,109, 4, 33,208,165,207, 22,177,228,190,138,242, 28, 36,222,119,169, 83,105,196,121,114, 90,102, 14, 33, 46, 74,
+221, 65,247,219, 81,176, 0, 30,102,189, 7,182, 63, 15,247, 29,147,119,197,221, 51,114,241,202,194, 31, 92, 49,150,102,247,227,
+104,248, 29, 32,112, 45, 90,190,215, 14, 42, 91,212,201, 54,134,234,150,158, 70,113,239, 51,102,189,125, 60,113, 73, 74,237,235,
+231,174,134,251, 84,151,225,254,150,167, 5,115,227,232,250,105, 86, 76,117,225,212,189,185,216, 94,187,204, 99,161,224,172,223,
+ 69,120, 79,160,118,146,110, 53,123,195,194,148, 71,195,222,230,108, 1,166,121,160, 9,211, 24,249, 77,119,156,155,146,133, 81,
+236,168, 80,194, 19,112,192, 92,243, 2,138, 96, 32, 95, 73,185, 28,252, 42, 17,202,200, 63,218, 16, 61, 3,133, 6, 73, 37, 96,
+ 73,114,126, 90, 16,177, 49, 53,189,246, 80, 56, 11,220,114, 20,223,240,234,117, 52,160,219,192, 85,104,110, 28,121,240,162,129,
+194,128,152,103,197, 3,137, 46,125,148, 35,151, 2, 15,118, 34,109,233, 53, 25,236, 1,245, 80,139,106,250, 42,200, 39, 12,212,
+ 22,211, 0, 30,214, 38,148,230,177, 55, 17, 32, 39,199,137,252,181, 4,177, 7,128,189,197,133, 61, 79, 1,126,126, 53, 1,107,
+230,100,242,247,210,191,192,213,107,112,191,152,211,233,174,160,223,252, 55,254,237,255, 0,196,215, 80, 22,132,112, 79,232, 39,
+236,138,234,226,126, 15,232, 39,236,138,235,213, 33, 31, 35,226, 23,244, 80, 8,191, 10, 52,237,239,129,234,161,139,223,128,160,
+ 24, 21, 84,159, 73,167,105, 62, 6,156, 45, 73,110, 52, 2, 0,108, 65,164,208, 65,189,249,248, 81, 64,189, 41, 20, 0,184,248,
+212, 41,134,169, 88,142, 95, 80,169,236, 45, 85,197,193, 98,222,158, 54,163, 42, 20, 40,228,105,196, 1,234, 2,154, 26,168, 55,
+ 92,249, 36,149,241,144,233,141, 14,150,183,218, 35,157,235,203,187,221, 83,109,143,190,202, 91,113, 84,185,179,209,182,219, 95,
+113,147,178,186, 37,171,111,146, 36,103,238,225,111, 22, 33,185,228,101,240, 31,209,170, 82, 75, 18,204,110, 79, 18, 79, 58, 74,
+177,219,246,169, 50,136,150, 91,164, 62, 30,150,246, 87,231,111,147,115,190,204,151,234,124,170,191, 77, 87,237,204,251,213,166,
+223,103,137,190, 11,157,159,234,179, 35, 99, 97,203,149,168,160,180,104, 9,103, 60,133,170, 61,108,150, 24,227,143,162,138, 21,
+ 45, 96, 7,174,178, 18,198, 98,145,227,110,104, 74,159,146,186,111,182, 43,109, 76, 90,247, 59, 79,115,229, 58, 66, 71, 61,158,
+241,238, 47,151, 78,213, 88,237, 92,227, 89,108,208,246, 84,170,155,172,145,158,114, 66,193,125,160,171,127, 32,167,126, 46,109,
+147,238, 29,164,211, 64,165,219, 6,116,201,117, 28,250, 96, 52,110,126, 77,119,170, 12, 60,169,112,114,162,203,135,227,137,131,
+ 15, 95,164, 31,104,175, 79,193,206,196,221,176,196,209, 89,227,144,105,150, 38,177,177, 35,222, 71, 21,244,253,139,117, 90,215,
+211,254, 44,118,238, 75,173, 89,243,189,235,106,238,221,191,135, 37,123, 91,233,100,124,151, 93, 94,209,220,191,131, 81,100,206,
+249,125,183,146,152,193,201, 99,133,145,126,154,147,254,205,212, 49, 3,212, 65,246,214,119, 31,240,103,186,100,148, 46, 68,216,
+144, 71,227, 39, 81,156,219,212,170,149,251, 10,238,240, 90,179,222,151,131,226,126, 62,219, 45,197,109,219,216,223,138,224, 99,
+123,115,108,159,120,223,112, 54,236,117, 44,211, 76,129,136,251, 40, 14,167,115,253, 21, 4,215,211,155,236,171, 14,207,154,238,
+108, 12, 76,131,218,227, 64,250, 77, 82,246,127, 98,109, 93,161, 27, 73, 1, 57, 57,242,174,153,179, 36, 0, 29, 60,244, 70,188,
+116,173, 65,238,237,238, 60,166, 27,110, 43,106,142, 54,213, 59,142, 69,135, 37, 30,207, 26,248,158,243,191,198,177, 89,167,167,
+107,173, 39,141,173, 99,238,251, 54,195, 34,186, 79,139,178,181,227,133,107, 83, 43, 87, 93,186,204, 38,156, 0, 72, 42, 46, 7,
+182,169,107, 71,219,144, 21,134, 89,200,254, 35, 5, 95, 98,254,115, 95,148,246,202,187,110,241,199,240,203,126, 80,126,155,220,
+108,171,181,201, 60,225, 47, 57, 60,175,241, 32,223,186,178, 13,136,253,212, 60,255, 0,160, 43, 73,248,104,176,141,163, 36,168,
+188,205,144, 68,135,199, 72, 69,211,252,166,179,159,137, 60,123,175, 35,251,184,191, 96, 85, 70,197,191,231,246,252,237, 62, 40,
+ 13, 20,195, 76,176,189,244,190,159,103,136,191, 58,254,132,241, 91, 38,206,148,175, 30,218,191, 56, 63, 3, 92,181,197,189,189,
+236,180,238,178,126, 19,204,246,224, 74, 55,243, 77,121, 63,226, 42,194, 59,140,152,173,173,160,140,205,111,211,226, 63,100, 10,
+177,155,241, 50,102,138,208,237,234,178,219,226,121, 11, 40, 63,209, 10,164,252,245,140,154,108,221,223, 57,165,147, 86, 70, 94,
+ 75,242, 81,114,204,120, 5, 80, 62,138,231,179,219,100,199,119,124,139,181, 67, 92, 78,187,221,214, 44,184,214, 60,111,185,182,
+159, 15,204,187,217,139,255, 0,149, 59,136,127,102, 60,173,191,165,212,227, 80,251, 79,255, 0, 50,109,191,223, 15,203, 91, 28,
+189,136,236, 61,129,155, 4,214,243, 83,116,230,201,183,131, 25, 16, 4,254,168,250,107, 27,218,127,249,147,109,254,248,127, 33,
+174,213,186,190, 61,197,171,193,187,125,149, 72,225,122, 90,153, 54,212,183, 20,171, 63, 27,182, 68,222,117,253,239,184,117, 62,
+ 63, 51, 54,171,250,117,181, 78,219, 54, 94,231,204,196, 89,246,184,166,108, 86, 44, 20,199, 40, 85,184, 54,110, 26,197, 93,119,
+247,110, 79,139,157, 38,243,140,133,241, 50, 78,169,200, 23,233,201,200,234,245, 55, 59,250,106, 31,106,119,156,221,186,143,137,
+ 44, 62, 99, 14, 70,215,164, 29, 46,140, 69,137, 91,240, 32,219,149,107,212,181,240, 86,248, 85,108,225,104,254,213,230,101,227,
+173, 55, 22,166,119,106, 41,127, 82,251, 31,144,131,182,123,232,255, 0, 97,146,127,227,143,251,202,140,123, 35,186,185,157,185,
+255, 0, 94, 63,245,235, 71,187,254, 38, 52,248,146, 99,237, 56,207, 4,178,130,167, 34, 86, 23, 64,120, 93, 21, 47,199,208,111,
+ 82,123, 23,186,119,221,203, 37,118,220,168, 78,108, 10, 61,252,210,116,180, 67,192,200,220,155,249,107,151,169,186,174, 55,145,
+211, 29, 99,138,224,227,230,117,244,182,150,200,177,172,153, 45, 60, 26,213, 79,200,160,239, 12,108,156, 61,191, 96,199,204, 82,
+153, 17,226,178, 72,132,130, 65, 86, 80, 7, 11,248, 85,167,225,100, 72,217, 91,148,164, 93,214, 56,213, 79,160, 49, 98,127,100,
+ 83,191, 21,130,140,189,182,198,255, 0,186,147,246,150,157,248, 84,200,178,238,133,191, 70, 27,124,242, 86,109,105,216,187,112,
+157,126,119, 53, 90,165,238, 10,188, 99, 77,124, 40,122, 64,229,107, 94,188, 79,190, 84, 39,116,238, 0, 11,123,200, 79,180,198,
+151,175,109, 19,198, 13,130,223,211, 94, 41,223, 68, 55,117,103,144, 44, 47, 31, 15,248, 73, 92, 61,187,254,107,127,161,253,232,
+244,123,159,252, 53,255, 0, 90,251,152,124,195, 47,249, 7,109, 0,158,145,206,150,227,194,250, 90,223,150,135,216, 49, 65, 47,
+116,225, 44,246,176,234, 52,119,253, 49, 27, 21,173, 46,197,181, 29,247,176, 78,218, 8, 89, 58,210, 75, 3, 31, 9, 21,184, 92,
+250, 15, 42,243,226,185,219, 70,112,212, 31, 23, 55, 21,195, 11,240,101,101, 55, 6,189,148,106,245,207,137, 56,183,117,215,247,
+115, 60, 57, 19,199,108, 25,154,154,246,209,255, 0,111, 35,232,190,139,126,141,173,226,107, 33,248,147, 20, 63,229,135,105,180,
+245, 86,104,140, 60, 69,245, 19, 99,111,234,222,179, 56,223,138, 25, 75, 8, 92,204, 17, 52,160,127, 17, 36, 40, 9,244,149, 42,
+255, 0,203, 89,206,225,238,109,195,184,221, 76,234, 34,198,135,222,142, 8,238, 64, 39,134,166, 39,153,240,175, 38, 13,158,106,
+229,173,172,187, 85, 92,204,241,131,217,184,222,224,182, 27, 86,141,217,217, 68, 71, 9,234, 63,178, 72, 29,211,182,150, 54, 26,
+218,231,254, 27,213, 62,126,175, 61,147,175,227,234,201,170,252,239,168,222,173,123, 59,255, 0, 50,237,255, 0,211,111,216,106,
+179,239,158,221,200,193,207,151,117,130, 50,216, 89,109,173,202,143,225,200,223, 16,111, 83, 30, 32,215,185,228,173,119, 61,175,
+ 78,234, 40,243, 77,232,120, 22, 59, 91,107,222,181, 84,200,231,201,165,169, 91,183,108,221,213,149,135, 28,251,106, 78,113, 30,
+253, 51, 28,161, 87,129, 32,217,117,143, 17, 82,191,203,253,238,110, 58,121, 39,211,251,241,255, 0,121, 78,237,142,243,155, 97,
+132,225, 79, 17,200,196, 44, 89, 2,155, 58, 19,241,105,191, 2, 15,162,172,119,143,196, 87,201,197,124,109,170, 7,199,105, 65,
+ 86,200,118, 26,148, 31,208, 11,227,235,189,115,189,183, 62,163,173,113,209,214,116,179,233,227,169,214,149,218,250, 74,214,203,
+145, 89, 45,106,186,248,104, 81,255, 0,146,251,156,255, 0,253,123,254,188,127,235,212,222,246, 76,168,147, 99,131, 52, 21,200,
+135,111,142, 57, 20,155,144, 80,149,181,197,253, 21,161,236,142,230,223,183, 73,188,142, 76, 7, 46, 24,199,191,154, 61,214, 79,
+ 64,115,201,175,243,213, 87,226,110,163,186, 97, 22, 22,255, 0, 14,109,250,237, 89,174, 92,175,115, 92,121, 21,126,148,223,211,
+228,106,216,177, 45,173,178,226,119,250,154, 77, 91,193,147,127, 11,113,227, 45,184,229,145,251,213, 17,196,173,232, 86,212,205,
+243,149, 21,232, 78,108,121,251, 43, 5,248, 88,140,240,110,122,109,193,226,189,253,143, 94,130,113,143,218,113,242, 10,240,239,
+127,250, 47,240,251,143,126,198, 22,218,159, 31,189,130, 78, 28,125, 38,141,107,211, 17, 60, 7, 26,144,177,147, 94, 99,212, 11,
+ 77,113, 22,163, 44, 58, 70,159,150,149,162,184, 32, 26, 16, 14,144, 86,226,152,226,192,212,149, 64,171,107,242,160, 73,164,142,
+ 7,137,189,232, 80, 75, 12,172, 65, 8,126, 90, 34,197, 43,122, 7,203, 68, 73, 2,128, 60,120, 0, 61,180,138,225, 61,226, 56,
+ 95,141, 1,195, 21,218,247,112, 62, 74,225,138, 60, 92,252,130,164,195,114,128,158, 4,211,180,208,132,111, 42,131,155, 63,250,
+124,148,190, 90, 47, 75,159,150,164,145, 73,106, 0,157, 8,252,181,172,127,233,237,123,241,183,152,213, 93, 70,183,248,127, 87,
+ 71,254,117,117, 80, 25,139, 2,130,223, 97, 63,100, 82,234, 62,138,113,251, 39,249,137,251, 34,155,170,128,143, 63,198, 13,143,
+ 42, 17,146,222, 6,164, 74,120,220,122, 40, 54,212,120,208, 13,212,109,203,230,164, 89, 9, 60, 69,168,192, 91,217, 93, 64, 55,
+ 85,133, 46,160,124,105, 72, 28,141, 55, 72, 4,222,128,100,141,101, 37, 77,236, 9,249,170, 16, 21, 42,112, 4, 76, 71, 3,192,
+ 15,158,162,233, 54,231, 81,149, 28,109, 84,121,219, 84,239, 59,203, 5,157,100, 58,136,189,136, 39,159, 58,186, 35,198,187,144,
+ 21,231,220,237,113,238, 40,169,146,116,114,154,209,163,190,223,115,147, 5,157,177,198,170, 26,122,162,167, 11,104, 8,221, 76,
+171, 49, 28,163, 28, 71,245,170,231,136, 28, 5,173,202,144, 14, 52, 94, 66,174,223,109,139, 5,123, 49, 86, 58,183,197,249,178,
+103,220,100,205,110,236,142,122, 46, 75,201, 2, 37,141, 82,111, 24,100, 55,154, 65,112,120, 73,249, 13, 94, 83, 72, 86, 4, 48,
+184, 60, 8, 53, 55, 91,122,238, 49, 91, 29,180,230,159, 75,114,101,219,103,182, 12,171, 37,117,228,215, 85,208,199, 84,172, 29,
+195, 47,110,155,173,137, 41,141,185, 48,230,172, 61, 12, 15, 3, 82,115,182,167,136,153,113,134,184,249,148,241, 95,172, 85,101,
+126, 95, 46, 28,219,108,145,100,233,101,194,203,239,171, 63, 71,143, 46, 45,198, 57,172, 90,175,138,127,115, 70,203, 23,190, 70,
+144, 51,113, 78,175, 23,136,240, 63,213,111,174,164, 63,124, 96, 1,251,188,105,153,189, 13,165, 71,207,118,172, 45,117,122, 43,
+238,187,196,163,189, 63, 23, 85, 39, 7,237,187, 86,231,177,175, 4,220, 23,187,159,117,110, 57,234, 97,142,216,208,183, 6, 88,
+205,216,143, 65,127,170,168,171,168,248,216,115,229,190,136, 86,227,197,207, 5, 30,211, 94,107,228,207,184,200,187,157,178, 89,
+232,151, 31,146, 61, 21,166, 28, 20,125,170,184,234,181,111,243, 99,113,177,228,202,153, 96,136, 93,152,243,240, 3,196,154,216,
+195, 19, 99, 64,144, 69,109, 40, 44, 61, 39,210,104, 88, 27,124, 91,124,118, 95,122, 70, 30,252,135,153,245, 15, 85, 73, 39,157,
+188,107,244, 30,221,178,255, 0, 30,142,215,255, 0,146,252,127,165,116,252,207,133,191,222,122,246, 85,167,232,167, 15,234,125,
+ 74, 13,223,182,246,125,203, 43,205,231, 96,164,153, 14, 0,105, 11, 61,200, 80, 0,228, 69, 70, 29,173,177,156, 51,128,216,105,
+229,181, 25, 2,113,224,228, 0, 89, 88,157, 67,128,240, 53,123,146,236, 29, 84, 11,216, 80, 15,188, 57,251,109, 95, 85,100,201,
+ 9,119,218, 23, 13, 94,135,206,244,177,203,125,149,151,199, 69,169,150,111,195,222,219, 15,171, 68,193,127, 68, 72,109,245,213,
+206,213,177,108,219, 71,189,183,226,172, 78, 69,140,166,236,228,127, 77,238,106,120,244, 91,135,164,210, 31,116,243, 39,212, 42,
+219, 54, 91, 40,181,236,215, 70,201, 92, 24,170,230,184,234,159, 84,134,102, 98, 98,110, 56,239,135,150,130,104, 36,182,184,205,
+192, 54, 33,135, 43, 30, 98,171,241,123, 87,183,240,242, 99,202,197,193, 72,230,136,234,141,195, 57, 32,250,120,181, 89,155,169,
+212, 56,122,104,128,223,143,166,178,175,116,161, 89,164,248,164,244, 52,241,210,205, 90,213, 77,174, 13,169, 98,178,171, 41, 87,
+ 1,148,139, 21, 60, 65, 6,179,121,157,149,219,121,146, 51,156, 78,139, 30,102, 22,100, 31,170, 14,159,162,180,149,221, 11,155,
+223,159, 26, 87, 37,233,173, 44,235,228,224, 95, 29, 47,165,234,173,230,164,202, 71,216, 61,183, 11, 6,104,100,150,222, 18, 72,
+214,255, 0,179,166,180, 56, 88,216,184, 48,140,124, 56,146, 8,151,146, 32, 10, 62,138,152, 49,212,243, 52,166, 40,212,113, 20,
+190, 92,151,253,118,181,188,217,154, 98,199, 79,209, 74,215,201, 21,123,142,203,180,238,205, 27,238, 56,203, 59, 68, 8,140,177,
+ 97, 96,121,252, 36, 82,109,251, 54,215,180,245, 14,219,140,176, 25,108, 36, 42, 88,223, 77,237,241, 19,233,166,111,251,254, 23,
+110,225,249,156,132, 50,203, 33, 43, 4, 10,108, 93,135, 62, 62, 0,120,154,197,195,221,221,231,189, 59,157,159, 13,122,106,120,
+244, 98,214, 23,212,207, 33, 34,245, 59,239,219,219,220,251,122, 78,159, 35, 94,157, 59,187,251,107,221,214, 53,249,158,138,128,
+147, 85,217,157,175,176,238, 25, 47,151,153,132,178,228, 75, 98,242, 18,224,157, 32, 40,228,192,114, 21,139,139,190,187,135,104,
+204, 24,251,246, 18,183, 34,232, 80,197, 37,185,106, 83,240,159,154,180,221,203,221, 45,131,219,248,123,206,202,209,200, 50,166,
+ 68, 6, 69, 44, 52, 50, 72,196, 88, 17,102, 12,150, 52,173,173, 87, 53,110,175,193,192,181,107,101, 22,170,178,241, 82, 93,225,
+109,216,123, 94, 58,226,224,194, 33,128, 18, 68, 96,147,197,185,159,120,154, 14,235,177,237, 91,178,129,184, 98,164,197, 69,149,
+248,135, 3,212,203, 99, 88,129,248,147,158,219, 98, 34, 65, 28,187,172,146, 48,184, 70, 17,164, 96, 13, 62,237,201,102, 60,124,
+106,207,181,123,151,119,206,109,192,239,172, 35,143, 30, 53,144, 22,143,165,165,125,237, 71,144,225,238,211,186,201,247, 38,231,
+172,235,243, 29,149,117,237,117, 93,189, 35, 79,145, 32,126, 28,246,233,253,225, 18,219,244, 58,134,223, 93, 92, 65,218, 59, 4,
+ 88,111,130,152,139,229,229,177,149,120,221,180,155,174,167,190,163, 99,235,172,118, 79,126,238,251,142, 96,193,237,204, 48,192,
+155, 70, 93, 75,200,224,125,173, 32,133, 81,237,167,100,111,159,136,155, 28, 94,115,113,197, 70,198, 22,212, 89, 35,117, 3,151,
+188,113,218,235,207,198,182,243,101,180, 77,236,227,196,194,193,134,179,219,142,170,116,224,141,134, 39,104,118,246, 14, 66,101,
+ 98,225, 44,115,196,110,143,169,238, 9, 22,241,111, 69, 91,182, 52, 18, 41, 71,141, 89, 24, 89,149,133,193, 7,210, 13, 83,118,
+175,117, 98,247, 46, 59,217, 58, 25,144,219,175, 5,238, 44,121, 58, 31, 21,254, 74,161,238,158,253,201,219,247, 23,217,246, 88,
+ 22, 92,136,200,142, 73,164, 5,191,120,126,196,104,164, 92,139,219,143,143,133, 98,214,181,156,218,205,191, 23, 38,171, 74,213,
+ 69,106,170,159, 36,160,183,203,236, 14,216,203,114,254, 79,160,199,153,129,217, 7,234,220,175,209, 67,131,240,235,181,225,112,
+231, 30, 73,173,225, 36,140, 71,204,186,106,168,205,248,166,168,114, 58, 49, 16, 6,174,136, 16,106,183,162,218,175,244,222,141,
+218, 61,251,147,187,238, 11,180,110,176, 36,121, 18, 6, 16,205, 29,212, 22, 64, 88,163,163, 19, 98, 64, 60,111,234,181,116,245,
+243, 68,122,150,143, 54, 99,252,124, 51, 62,157, 39,201, 22,187,198,251,179,246,124, 56,184,173,138,233, 12,193,250, 49,226,162,
+105, 26, 52,234,213,169,147,244,169,144, 98,108, 29,221,137,139,186,228, 97, 25, 67,171, 36, 38,107,171, 42,164,140,172, 8,141,
+237,204, 26,243,206,241,207,238, 28,233,113,198,251,137,229,150, 38,148, 98,158,155, 71,172, 18,154,190, 34,111,107, 45, 93,246,
+ 86,231,221, 40,155,110, 22, 62, 22,189,156,200, 85,178,122, 76,125,198,145,140,135, 93,237,193,137,240,174,106,214, 79,185, 89,
+167,213, 61, 78,142,181,117,237,117, 77,116,107, 67,208,118,189,147,107,217,214, 69,219,113,151, 28, 76, 65,144, 41, 99,114,183,
+183,196, 79,166,172, 10,222,176,221,213,248,132,187, 70, 83,237,187, 84, 43, 62, 84, 94,236,243, 73,126,154, 55,232, 5, 91, 22,
+ 35,199,143, 10,168, 29,195,248,146,241,121,213,195,126,133,181,105, 24,195,151,167, 73,247,237, 70,219,115,102,219,124,216,173,
+ 85, 84, 85, 36,151, 37,161,232,140, 89, 9, 3,133,248, 26, 47,152, 81, 88,126,218,252, 68,143,112,204,143,111,223, 49, 99,134,
+105, 88, 36,121, 81,130, 20,185,224, 22, 68, 98,116,223,211,122, 94,240,239, 45,215,183, 55, 88,240,246,248,241,204, 82, 64,179,
+ 30,172,101,142,162,242, 39, 2, 24,112,178, 10,133, 54,199, 36,147,193, 73,246, 80,245,229, 57,247, 85,173,232,181,121,254,225,
+248,149,188,100,152,241,246, 12,117, 46,177,161,200,156, 68, 93,140,133, 70,189, 9,201, 84, 53,249,222,182,221,161,187,238, 59,
+166,199, 6, 94,230,223,226,153,228, 89, 61,221, 31, 3,149, 23, 81,107, 80, 18,140, 25,175,199, 67, 82,166, 30, 69,238,203, 96,
+ 57,220,213,145,118, 62, 60, 40, 76, 73,241,168, 36, 18,196, 47,123, 92,129,206,155, 10,134, 4, 17,227, 82, 7, 5, 63, 53, 7,
+ 31,129, 36,120, 26, 0,234, 52,138, 91, 87, 15, 77, 40, 62, 6,168, 27,110, 52,182,174, 62, 21,195,213, 64, 73,254,195,254, 15,
+252,234,234,239,236,111,254,231,254,117,117, 0,118, 60, 22,223,160,159,178, 41,141,126, 6,212,164,181,146,252,244, 37,255, 0,
+ 84, 82, 30, 62, 20, 0,101,189,249,113,181, 32, 31, 39,166,150, 82,117,129,232, 20, 53,102,185,191, 42, 0,151,191,133,113,225,
+225, 77, 7,211, 74, 79, 10, 3,185,241, 52,132,222,184, 49,212, 65, 22, 20,140,109,202,128,141,146,224,170,143, 93,199,201, 66,
+ 44, 0,167,101, 27,186,175,128, 23,191,183,255, 0,162,131,235,168,202,113, 55, 21,220,125, 20,170, 56, 94,151,194,128, 64,220,
+105,197,137,224, 40, 96,243, 52,224, 64, 20, 7, 1,122, 80,162,185, 72,165,191, 26, 1, 81, 1,112, 60, 47,196, 31, 69, 55, 39,
+107,194,200,247,158, 32, 63,156,188, 15,209, 68,140,141, 96,147,107,113,162,134, 91,115,252,213,139,210,151, 93,183,170,178,232,
+212,154,165,239, 71,221, 75, 58,190,169,193, 71, 47,111,195,175, 76, 83, 50,223,193,148, 55,211,238,210,142,218, 91,219,205, 31,
+212,255, 0,237, 85,211, 1,173,120,252,130,137,170,255, 0, 9,226, 43,200,253,183,102,220,250, 75,225,107, 47,196,244,175,112,
+221,165, 30,171,249, 85,254, 5,108, 29,189,131, 29,139,234,149,191,156,108, 62, 97, 83, 4, 9, 24, 9, 31,186,163,192, 90,194,
+164,107,241,231, 76, 33,124,121,215,163, 22, 12, 88,148, 99,165,107,228,181,249,156, 50,102,203,145,206, 75,187,121,189, 62, 64,
+250,108,205,160,185,176, 30,170,227, 19,143,182, 72,246, 10,122, 31,120,211,197,129,244,138,234,115, 43,114, 56, 74, 81,141,237,
+110, 63, 37,232, 23,210,120,114,241, 52,108,150,213, 51,176,229,123,113,245,112,160,131,126, 85,160, 41,177,227,207,213, 74, 13,
+197,143, 3, 76, 38,198,151,219, 64,119, 1,195,159,164,154, 32,231,106, 8, 32,155, 15, 26, 58,142, 55,163, 2,170,220,138,145,
+106, 26, 14, 34,141, 80,135, 1, 76,145,110, 45, 79, 20,143,107, 26,160,242,191,196,225, 40,205,192, 39,248, 70, 39,209,253, 45,
+ 94,247,209,166,182,125,140,113,143,108, 96,249,107,112, 12, 38,183, 62,166,163,175, 87,175,242, 84,157,251,183,113, 59,139, 4,
+ 98,228,147, 28,136,117,193, 58,128, 89, 27,216,121,131,226, 43, 15, 31, 98,119,134,211, 43, 29,167, 61, 21, 27,155, 67, 51,196,
+ 79,244,212,139,125, 38,128,214,119, 76,253,169,140,216,231,184, 81,100,149,195,249,117, 40, 92,128, 52,234,248, 65,176,172,223,
+121, 54,205, 47,102,224,207,177,198, 99,194,108,209,211, 22,101, 28, 18,112,214, 86,254,112, 52, 40,127, 14,183,205,195, 36,100,
+239,217,235, 98, 64,118, 14,211, 76, 69,249, 2,224, 40,249,207,178,180,253,207,218,178,110,123, 14, 38,203,180, 24,160, 92, 89,
+ 81,212, 76, 88, 46,132,142, 68,230,138,228,177, 47,122, 2,167,240,179, 3, 12,237,185,123,140,145, 43,228,153,204, 1,216, 92,
+170, 42, 35,217,125, 23, 47,198,175,251,221, 88,118,182,227,229,208, 7,208,151,176,251, 61, 68,215,255, 0,102,244,222,203,216,
+115, 59,119,107,155, 11, 53,226,146, 89, 50, 26,101,104, 75, 50,233,100,141, 44,117,170, 27,221, 42,250,104,163,200,137,224,153,
+ 67,197, 42,148,145, 27,136, 42,194,196, 31,109, 1,226,125,165, 31,112, 73,149, 58,246,244,209,195,145,161,122,157, 65, 25, 37,
+ 47,246,122,138,252, 47,206,213,173,200,193,252, 76,155, 30, 88,178,115,113,206, 59,163, 44,193,198, 56, 82,132, 89,174,122, 94,
+138, 14,111,225,206,227,131,154, 51, 59,115, 56, 69,239, 22,137, 36,102, 71, 79,230,137, 16, 54,161,237,181, 38, 71,108,126, 32,
+238,209,249, 61,199,112,143,203, 27,107, 86,146,202, 64,253, 37,137, 61,239,150,133, 23,178,123,107,116,217,247,197,202,154, 92,
+119,133,162,120,229, 88,102, 87,107, 16, 8,247, 87,249,192, 84, 60,206,247,222,183,125,220, 96,246,252, 80,193,212,151, 70, 52,
+134, 52,105, 27,143, 7,102,144, 21, 30,158, 92, 43,107,218,221,165,135,219, 49,187, 43,156,140,217,128, 89,178, 8,176,210, 56,
+232, 65,198,195,211,233,172,158,231,248,113,186,227,238, 39, 59,183,242, 80, 32,147,171, 10, 51, 24,228,136,223, 80, 10, 64, 32,
+129,225,202,132, 44,215, 99,252, 68,200, 4,229,111,176,194,167,139,116,248, 48,244,252, 17, 70, 62, 99, 88,174,206, 80,157,227,
+130,138,253, 85, 89,164, 2, 65,201,128, 71,247,190, 90,216,255, 0,151,123,247,117,143,203,111, 27,194, 65,136,125,217, 22, 45,
+ 58,217,124, 71,238,146, 59,252,173, 64,217,127, 15,183,109,159,127,199,220,150,124,121, 49, 49,229, 98,170, 93,250,166, 50, 25,
+ 69,199, 72, 46,173, 39,211,107,208, 12,252, 90,255, 0,250,127,253,231,254, 77,104,255, 0, 15,255, 0,242,158,223,255, 0, 27,
+255, 0,111, 37, 7,189,251,106,110,227,198,199, 56,178, 36,121, 24,140,229, 4,151, 10,194, 64, 53, 45,212, 27, 31,112, 85, 15,
+111,246,191,122,237,185, 56,107,230,196, 91,116, 83,199, 36,216,235, 59,105, 49,235, 13, 34,132, 2,222,240,191, 10, 3, 39,182,
+ 24,151,188, 33, 59,157,180,140,227,215,215,203, 95, 80,252, 90,188, 53,115,189,123,189,171, 17,221, 31,135,240,239, 89, 47,184,
+237,211, 46, 46, 92,156,102,141,193, 49,187,126,149,214,229, 73,241,224,106,141,123, 75,241, 5, 34,242, 73,185, 17,140, 6,144,
+163, 42, 64,154,125, 3,133,237,234,160, 51,189,227,209,110,235,220, 60,135, 16,102, 93, 61, 63,246,186, 87,169,107,120,245, 47,
+ 86,127,137,122,190,253,198,215,109,126, 77, 53, 91,149,250,178,222,180,221,181,248,112,155, 94, 92,123,134,239, 58,100,207, 9,
+215, 20, 49, 3,211, 87, 28, 67,179, 48, 5,173,225,192, 82,119,119,101,238,189,201,185,199,157,131, 54, 60,113, 71, 8,132,137,
+153,213,181, 43,200,247, 26, 35,113,107, 63,166,128,209,246,134, 14, 54, 7,110,109,195, 29, 2, 25,241,227,158,102, 3,139, 60,
+170, 36, 37,143,143, 59, 85,231,141, 68,218, 49, 36,193,218,240,112,102, 42,210, 98,227,197, 12,133, 46, 84,180,104,168,116,220,
+ 3,107,143, 69, 75,224, 40, 14, 38,155, 75, 92, 71,162,128,239, 11, 80,224, 28, 27,218,104,182,225, 66,128, 92, 55,180,208, 6,
+ 91,143, 26, 95, 10,101,233,192,248, 80, 29,235,165,191, 11, 82, 91,143,174,186,195,149, 1, 42,223,184,255, 0,131,255, 0, 58,
+186,146,223,184,183,251,159,249,213,212, 1,156,252, 63,208, 79,217, 20,128,253, 53,207,127,119,250, 9,251, 34,153,127,158,128,
+100,182,212, 61,156, 77, 48,129,233,231, 73, 49,247,199,178,153,171,141,232, 2, 94,194,187, 80,172,142, 95,226, 71,100,224,229,
+207,135,151,188, 71, 22, 78, 52,143, 12,241,148,148,149,146, 50, 81,215,130, 17,192,138, 93,235,241, 7,182,182, 77,163, 31,125,
+147, 32,230, 96,229, 72, 98,199,147, 12, 9,117, 56, 4,149,248,148, 2, 44,121,154, 3, 89,115, 73,107,243, 53, 19, 7, 50, 61,
+195, 11, 27, 62, 16,203, 22, 84, 73, 58, 43,128, 24, 44,138, 29, 67, 88,145,123, 31, 77, 73,189,168, 8, 83,220,204,192,113,181,
+128,249,169,150,110, 84,242, 67, 72, 91,192,155,213, 87,112,119, 14,221,219, 59,107,238,219,153,113,140,140,168,122, 75,173,181,
+ 55,194, 0,184,168, 82,208, 41,229, 75,167,194,162,109, 27,166, 62,241,182,226,238,184,202,233, 6, 92,107, 52, 75, 32, 1,194,
+176,184,212, 20,176,191,203, 82,245, 80, 13, 84,191, 10, 93, 2,244,170,192, 19, 81,242, 55, 45,191, 9,213, 51, 50,225,199,121,
+ 8,233,172,210, 42, 22,191,232,134, 34,244, 4,160,160, 90,150,192, 10, 77, 96,216,142, 32,241, 6,163,101,238,123,126, 27,164,
+121,121, 80,227,179,252, 11, 44,138,133,175,195,221, 12, 69,232, 9,136,160,176, 7,194,230,157,165,127, 68,124,212, 15, 53,141,
+ 2, 25,178, 37, 72,163, 22,253,227,176, 85,227,203,139,112,174,135,114,219,178, 92,199,143,151, 12,173,107,233,142, 69, 99, 97,
+204,216, 26,128,148, 18, 51,246, 1, 53,194, 36,244,115,164, 46, 52, 93, 92, 82, 44,139,224,120,248,208, 10, 81, 53,124,156,171,
+140,105,194,223,202,107,186,128,106,245,154,112,101, 39,217,196, 26, 1,130, 49,115,204,124,180,141, 31,243,155,231, 52,242, 71,
+ 18, 8, 20,214, 34,196,147,225,203,194,128,172, 99,239,177,183, 2, 73,185,166,146, 7, 27,223,213, 79,233,146, 61,243, 93,238,
+ 47, 33,198,180, 6,251,196,123,162,222,186, 80,131,237, 27,210,179,183,176, 83, 24,131,199,153,160, 28, 52,134, 10,163,157, 72,
+ 81, 81,163,185, 96, 79,133, 73, 6,163, 1, 23,194,158, 41,139,206,159, 84,135, 80,229,107, 88,122,104,134,154,224, 90,244, 2,
+175, 5, 20,224,120,211, 11, 1, 96, 77, 45,252,111, 64,116,158, 3,210,194,136, 40, 46,224, 50,220,248,220,210,245,211,195,141,
+ 0, 66,124, 43,169,165,197,184,211, 90, 84, 83,227,243,212,145, 3,155,227, 65,237,167,212,115, 48,212, 8,240,191,211, 69, 15,
+ 73, 16, 19,157, 40, 20, 19, 42,129,123, 10, 27,100,128, 57, 85, 16, 75,177,183, 42,105, 54,231,194,129, 30, 73,118,181,172, 61,
+ 52, 66,246, 23,168,218, 44, 48,114, 71,197,158,254,202, 50, 88, 42,139,248, 80, 38,156, 1,164,113,191, 58,103,154, 96, 0,183,
+ 42, 32, 75,224, 43,129, 23,252,212, 24,101,103,226,121, 81,111,194,227,157, 71,100,135,107, 30, 77, 14, 27,105, 36, 27,241, 52,
+201, 39, 10, 45,226,104, 75, 49, 81,101,170,156,146, 9,130,247,228,126,138, 86, 32,154,139, 22, 65, 98, 3, 81,193,189, 80, 61,
+109,233,250, 41, 15, 62, 21,194,184,208, 11,225, 66,129,133,155,133,184,209,188, 47, 65,199,226, 24,122,232, 2,139,210,219,211,
+ 93,200,215, 27, 1,115, 66, 10, 69,112, 52, 62,170,218,215,229, 93,213, 90, 20,155,127,220,114,254,199,254,117,117, 51,170, 58,
+ 23,255, 0,115,127,253,117,171,168, 4,121,100,178,113,254,206, 50,120, 15, 20, 90,103, 81,253, 53,206, 63,135,253,220,127,176,
+180,202, 20, 22, 68,146,107, 0, 55, 11,122, 5, 8, 75, 37,143, 27,159, 88,174,201, 39, 88,246,126, 83, 64,227, 84, 31, 53,102,
+228, 77, 23,118,119,176,139,106, 27,169,159,239, 56,158,235,171,202,171,100,220,230, 1,165,184,197,110, 7,133,175,206,147, 54,
+ 93,191,255, 0,243, 28, 28,108, 57,222, 89,151,118,121,115, 18, 69,210, 99,145,241,202,133, 78, 45,116,210,130,199,211,122,219,
+100,254, 26,247,180,123,238,251,186,109, 27,134, 6, 60, 91,203,229, 70,250,218, 67, 39,150,202,151,170, 80,142,131, 5,107, 1,
+200,251, 13, 46, 79,224,230,226,157,177, 22,211,129,155,143, 38,224,249, 99, 47, 46,105,139,199, 22,149,141,163, 88,227,208,146,
+ 49,182,171,220,129, 80, 1,238, 94,251,221,112, 31,183,123,111, 15,116,251,147, 8,109,216,178,230,238, 43, 17,153,193,120,189,
+209,165, 67, 54,145,164,124, 62,154,167,127,197, 30,241,155,179,214, 69,220, 12,121,216,249,171,143, 38, 82,199, 22,185, 33,146,
+ 38,145, 3, 18,134,204,173, 25,226, 44, 77,108,123,139,240,227,122,201,159,102,222,118, 28,184, 33,222, 54,204, 88, 49,166, 73,
+174, 98,115, 2,233,214,132,163, 95,153, 91, 50,216,138, 22,253,216,157,235,220,219, 4,120,123,150, 78,220,185,233,152, 50, 0,
+136, 52, 80,164, 34, 35, 30,139,199, 9, 37,245,177, 60, 71,203, 64, 83,118,247,120,119,118, 23,122,224,109,187,246,226, 50,176,
+242,113, 82, 89, 98, 69, 26, 4,111,139,230,145,135,186,173,173,108, 46,124,120,214,107,184,187,155,186,187,187,100,220, 55,108,
+188,164,139,101,139, 50, 40, 35,219,149, 84, 89,156, 60,137,239, 5,212,116, 5,226, 73,227,122,244, 40,255, 0, 13,247,143,243,
+126,221,190, 79, 54, 43, 96, 99, 98,193,139,145, 16,121, 58,173,211,197,242,175,160,116,180,218,252,174,220,171, 63,255, 0,249,
+ 15,120, 71,131,157,179, 99,110, 88, 99,109,151, 33, 50, 34, 73, 11,222, 70,143, 82, 35, 57, 17, 49, 67,161,248,129,126, 63, 61,
+ 1, 27, 55,189,119, 28, 12, 46,215,237,204, 77,211,238, 76, 47,187,177,230,205,220, 86, 35, 51,130,234, 74,141, 10, 25,180,141,
+ 35,225,244,250,170, 43,126, 38,119,100,189,156, 37, 92,243, 30,116, 25,171,143, 38, 82,199, 22,169, 33,146, 39,117, 13,116, 54,
+101,104,207,188, 44,107, 87,186,126, 25,111,161, 54, 29,207,100,204,199,135,122,218,113, 97,197,157,100,212, 97,144,194, 13,157,
+ 11, 70,215,224,197, 72,101,177, 20, 93,255, 0,177,123,219,185,182, 8,176,183, 60,157,185,115,215, 48,100, 40,136, 60, 80,164,
+ 34, 35, 30,139,199, 9, 37,245,177, 60, 71,203, 80, 26, 30,192,255, 0, 55,101, 46, 94,235,220,210,127,134,206,143, 26, 93,174,
+ 5,101, 97, 28,101, 92,182,160,188,117, 21,208, 77,235, 51,248,161,217,157,183,137,183,110,253,213,157,145, 48,220,242,158, 49,
+136,165,192, 78,165,149, 22, 36, 77, 60,110,170, 73,185,175, 77,218,113,228,192,218,240,112,102, 33,164,198,199,138, 25, 25, 46,
+ 84,180,104,168, 74,146, 1,181,199,162,188,235,241, 3,177,187,203,188,119,104,230,131, 43, 6, 29,179, 16, 91, 11, 30, 89, 37,
+189,205,139,201, 34,136, 25,117, 49, 28,184,139,124,180, 6,135,240,185,119, 37,236,141,183,239, 34,197,200,115,142, 36,190,161,
+ 1,115,210,189,252, 52,252, 63,205,181,101,191, 20, 59, 51,182,241,118,237,219,186,243,178, 38, 27,166, 83,198, 49, 20,184, 9,
+212,178,162,196,137,167,141,213, 73, 55, 53,109, 47,111,254, 37, 55,109, 65,129, 22,247,142,155,196,121, 77, 36,153, 74,204,177,
+156,110,158,148,137,116,227,248, 55, 27,104,249,106,191,190,187, 19,189,187,195,112,130, 68,204,192,143, 3, 13, 2,226,193, 36,
+147, 18, 94,195,169, 44,138, 49,217,117, 49, 31, 55,203, 64, 65,125,191,184, 51,255, 0, 4,240,176, 70, 44,249,153,185, 51,160,
+198,137, 17,164,151,203, 9, 90, 72,238, 0, 36, 40, 84,224, 79, 13, 54,174,252, 31,200,237,124,125,245,246,227,181,228,237,221,
+203, 30, 43, 99,206,114, 36, 50, 36,133, 10, 25,237, 27, 42, 24,159, 82, 95, 77,141,133,197,235, 97, 6,203,248,145, 7,105,195,
+137, 6,247,135,254, 96,131, 51,173,215, 63,192,108, 78,145,140, 99,144, 96, 28,117, 53,254, 15, 14,117, 7,177,191, 15,183,109,
+175,184,114,187,191,186,179,160,202,221,103, 15,161, 32, 62,232,105,120, 59,177,211, 24,190,159,116, 5, 22,160, 61, 32, 0, 95,
+ 82, 32,177, 54, 55,244, 10,112,137, 73,226,163,141, 8, 21, 32,254,240, 40, 39,232,244, 81,122,145,223,152,183,180, 84, 2, 24,
+210,250,116, 11,122,105, 76, 81,133,213,160,124,212,134, 85, 39, 72, 43,235,185,240,245, 87, 60,168, 23,221, 96,110, 57, 92, 80,
+ 13, 88,144,168,107, 15, 95, 10,107,196,130, 54,109, 32, 16, 15,209, 78,234, 32, 2,236, 61,151,161, 78,232,209, 16, 24, 27,219,
+135,203, 84, 16,152,220,223,157, 33, 55,246,250,171,143, 3,233,164, 60, 56,255, 0, 37, 80,117,237, 74,136, 92,240,166,128, 93,
+128, 2,228,242, 21, 57, 35, 88,198,145,242,154, 0,122, 52, 40,245,243,174, 20,249, 79, 5, 31, 45, 52, 84, 2,220,142, 66,245,
+193,164,110, 75, 77,118, 43,203,209, 68,141,155, 65, 53, 72, 42, 22,189,152, 90,150, 67,101,161,164,156,110,220,233,175, 38,162,
+ 64,229,225, 64,112,187, 54,170, 43, 16,170, 73,229, 76, 30,234,129,227, 77,118, 4, 88,241,172,113,102,184, 0,212,204, 73,162,
+ 68,164,146,198,185, 64, 52,251,128,120,114,173, 62, 1, 15, 98, 21, 9, 34,162,234, 38,230,139, 33, 12, 0,227,235,161,133, 21,
+ 18,128,199,196,186,141,219,144,169, 41,202,244, 37,210,160, 11, 87, 51, 0,156, 47,168,253, 85, 28,182, 80, 82,200, 75,240,228,
+ 41,164,177,225,233,166, 26, 52, 74,163,222, 63, 37,107,130, 32, 88,215, 66,138,123,182,133,185,181, 15, 80,252,212, 41,157, 89,
+180,142, 67,249,107, 17, 44,163, 47,168,146,105, 85,117, 48, 90, 96,169, 48, 40, 0,177, 28, 73,225, 91,110, 17, 3, 40, 10, 0,
+ 95, 10, 43, 54,133,185, 60, 0,160,221,125, 28, 56,208,242, 36, 83,238, 47,202,107,154, 82,202, 5,216,187,150, 53,220,128,227,
+ 77, 62,161, 70,133, 20,144,204, 56, 10,233,193, 25, 9, 4, 86, 23, 60,205, 25, 77,141,169,186,151,195,128,241,174, 98,128, 22,
+ 60,192,172, 38,231,204,211, 90, 7, 82, 56, 83,154,214,185, 60,170, 42,100, 32, 6,252, 79,162,134,243, 52,135,143, 5,244, 87,
+ 67, 16, 29,114, 67, 93, 88, 88,120, 26,176,198,219,127,114,178,245,127,136, 3,219, 79, 43,139,250,106,148,184,210, 82,223, 17,
+ 28,107, 89, 2,152,224,138, 38,230,136,170,109,203,128,181, 43,168,122, 34, 11, 96,219,143, 83,254,207,231,170,249,181,116,218,
+222, 60, 42,246,110, 35,133,103,101,200, 75,201, 15,218, 86, 43,243, 27, 85,106, 32,139,130, 16,194,162, 61,125,102, 39, 77,213,
+ 71, 59,211, 63,115,162,226, 73, 11,248,175, 15,170,144, 72,209,178,200, 99,247, 84,105,185,228,105,145, 49,107,155,113, 38,245,
+153, 53, 5,143, 77,124,135, 83, 91,107,232, 90,222,174,190,171,215, 82,220,249, 45, 55,254,195,159,252,123, 87, 85,145, 3,164,
+ 31,195,254,238, 63,216, 90, 29, 62, 79,236,255, 0,187,143,246, 22,153, 64, 69,201,182,177,236,252,166,128,121, 81,242,127,136,
+ 61,159,148,208,121, 85, 6, 68,119,246,220,168,141, 36, 14,165,176,114,183, 7,226, 8, 95, 40,210, 35,194, 79,233, 19, 11,219,
+217, 87, 81,239,251,116,143,229, 76,161,115,150, 46,172,152,156,110,172, 35, 19, 52,122,172, 20,184, 86,185, 94,118,227,107, 86,
+ 63, 47,240,251,112,158, 92,214, 76,136, 21, 50, 55, 17, 52, 74, 75,251,184, 18, 28,150,200,199, 96, 19,226, 45,153, 33, 85, 28,
+ 57,113,171, 53,237, 76,193,220, 57, 27,129, 8,248,239, 60,249,112,204,249, 25, 23, 86,159, 27,202,244,198, 32, 61, 5, 96, 75,
+ 94, 78, 36,175, 11,122, 0,184,194,238,157,163, 38, 45,184,201, 58,227,228,110, 88,240,101, 67,142,247,186,174, 66,234,141, 93,
+128,210, 11,113, 11,115,239, 17,194,137, 15,116,118,252,248,242,101,197,184, 70,208, 68,209,163,201,239, 1,121,206,152,109,113,
+114, 36, 63, 9, 28, 15,133,103,112,251, 83,120,195,134, 12, 15,240,146,227,207,133,183, 98,231, 78,229,153,162,108, 24,218, 57,
+ 12, 8,201,239,150,184,233,177, 43,164,241,181,116, 61,167,187,200, 49,164,201,108,120,165,196, 27, 70, 58,172,110,236,143, 14,
+215,144,114, 36,148,222, 48, 67,200, 24,133, 79, 15, 22,160, 52, 56,221,209,176,101,117, 12, 25,232,203, 12, 47,147, 41, 96,200,
+ 22, 40,206,153, 28,151, 85,248, 15, 6, 28,215,198,166,226,238,123,126,102, 36,153,216,211, 7,199,139, 80,149,172,192,161, 65,
+118, 86, 70, 1,129, 3,141,136,172,116,157,147,185, 75,139, 38, 57,158, 5, 47,137,186, 99,171, 6,147,248,153,185,233,157, 7,
+ 37, 7, 72, 84,179,145,196, 30, 87,173, 23,108,237, 83,237, 88,217, 94, 98, 53,134, 92,188,150,201,104,198, 68,249,108, 46,145,
+196, 58,147,229, 18,238,214,140,122, 7,135,174,163, 0,246,206,242,216, 55, 72,118,249, 23, 32, 65, 54,226,145,201, 14, 60,160,
+135, 29, 86, 40,138,228, 2,160,179, 41, 85,227,239, 30, 87,165,238, 78,238,219,251,110, 65, 6, 76,111, 44,205,137,145,154,170,
+131,129, 92,109, 55, 91,159, 22,212,109,236,227,225, 89,221,179,179, 55,172, 76, 76,125,186,118,198, 48,184,219, 83, 42,120,229,
+114,200, 54,185,250,202, 99, 86,137,117,117,148, 40,226, 70,147,127,138,173,123,215,183,183, 46,224,233,253,220,240, 47,248, 44,
+252, 41, 60,195,186, 91,205,136,116, 58,232,142, 75,233,104,120,142, 28, 15,201, 80, 22,201,220, 91,102, 68,152,227, 18,120,228,
+138, 89,229,198,150, 70, 99, 25, 71,134, 22,201, 97,165,212,106,247, 84, 31, 15,116,234,229, 82, 54,253,231,107,221, 34,150,124,
+ 12,149,154, 56,108,101, 54,101, 42, 25,117,171, 89,192, 58, 89,120,169,228, 71, 42,207,201,219, 27,147,110, 82,103, 35,227,178,
+ 54,229,145,158,169, 38,182, 6, 57,182,207,187,213, 93, 66,139,158,167, 22, 23,248,124,111,194,141,219,123, 38,229,182,225,231,
+227,229, 8,226, 73,213, 35,197,198, 73,164,200, 88,130,198, 81,128,154,100, 89, 58,122,190, 4, 55,210,191, 53, 1, 98,189,213,
+219,175, 4, 51,174,124,102, 44,130, 68, 50, 0,218, 88, 13, 26,154,246,224,131,168,183, 99,238,130,109,122,228,238, 93,178, 47,
+ 62,115, 31,203, 46, 22, 97,192,187, 93,140,146, 8, 35,202, 37, 21, 1,107, 4,147,143, 14, 22, 39,149,102,115,251, 39, 63, 35,
+110,217,240,143, 74,115,141,181, 38,211,152,158,103, 39, 30, 32, 64,139, 84,191,225,180, 52,233,238, 55,238,222,215,225, 82, 55,
+ 46,210,220,167,155, 43, 50, 38,142, 83, 38,229, 46,108,112, 12,169,241, 11, 69, 54, 20, 88, 86,121,241,128,117,101,120,245, 21,
+ 23, 12,188, 47,225, 64,106, 70,251,178,166, 86, 62, 9,204,143,205,100,170, 52, 74,164,176, 34, 80, 90, 43,186,130,163,168, 20,
+233,185,247,188, 42, 57,238,142,223,213,145,108,216,255, 0,195, 89,101,176,110, 36,201,209,253,223,187,251,207,222,123,158,229,
+253,238, 28,235, 61, 39,105,238,235,153,181,136, 95, 31,200,237,171,182,244,144, 79, 52, 74,167, 10,235, 50,244,130, 73,212, 44,
+182,208,210, 49, 34,214,225,123,212,105,123, 55,120,153,167,107,227, 65, 26,203, 22, 68,120,152,249, 83,162, 75, 34,100,249,137,
+ 26, 25, 52,245,112,196,136,126, 24,216,141,124,125,116, 6,229, 55, 29,189,182,255, 0,189, 70, 68,127,119,172,109, 51,101, 19,
+238, 42, 37,245,150, 39,150,155, 27,250, 42,155, 51,188,182,152, 83,111,242,108, 51, 27,112,204, 24, 49, 1,170, 62,155,132, 50,
+ 72,210, 6, 77, 67, 74,219,221, 34,230,227,195,141, 53, 59,117,191,201,179,118,222,184,160,200,153, 39, 35, 76,146,205, 18,203,
+ 52,175,144, 53, 73, 57, 50,184,212,222,243, 30, 39,137,176,229, 81,211, 96,220, 39,207,139,118,201,104, 33,200,147,120, 77,207,
+ 35, 25, 36,105, 17, 34,139, 1,182,245, 68,126,154,106,114,108,198,224, 15,155,136, 19,119, 94,245,218,182,141,205,246,156,148,
+115, 60, 67, 12,200,225,108,161,115, 39,242,192,159,232,124, 71,212,120,113,169,239,220,253,187,208,198,203, 25,136,144,230, 23,
+242,238, 67, 11,136,216, 69, 33, 96, 69,208, 43,251,172, 90,214, 60, 13, 83,239,221,189,159,185,119, 4, 91,158, 44,152,227, 22,
+219,103, 88, 72,238,178, 41,219,243,155, 53,180,170,198,234,218,210, 66, 5,216,113, 30,187,138,108,206,197,207,154, 8, 96,102,
+135, 32, 58,238, 16, 79, 31,154,202,199,141, 83, 55, 53,179, 35,145,134, 54,134,152, 8,219, 75, 70,214, 26,173,199,198,128,216,
+111, 91,195,109,146, 96, 99, 67,136,114,178,119, 25, 94, 8, 81, 93, 99, 0,199, 12,153, 12, 89,159,135,195, 25,170,140,126,243,
+219,115,224,150,103,141,241, 35,199,135, 22,121, 26, 82, 15, 28,151,158, 21,137, 4,122,181, 29,112, 16, 52,223, 85,197,170, 79,
+117,236,210,111,111,181, 75, 14, 38, 30,225, 30, 6, 68,147,100, 96,238, 12,201, 12,170,240, 75, 2,241, 16,100,139,171, 72, 27,
+138,120, 86,105,123, 11,115,143, 18,104,206, 68,114,145,228, 30, 8, 99,154,104, 63,233, 50,114,167,108,117,153, 87,169, 26,172,
+121, 11, 28, 78,188,125,222, 32, 80, 26, 9,251,159, 97,198,130, 28,137,243, 99, 88,167, 70,150, 38,247,141,209, 24, 35,183,186,
+ 9, 1, 89,128,107,242,241,161,207,220, 91,124,123,198, 54,201, 27,245,114,167,149,225,145, 87,148, 69, 49,223, 47,223, 36, 91,
+224, 81,192, 30, 23, 23,170,105,251, 23, 62, 77,180,225,194,216,240,187,237,123,142, 17, 83, 44,242, 40,200,206,201,143, 41, 79,
+ 82, 85,121, 29, 70,150,212,199,137, 63,103,209, 50, 94,212,220,164,222, 76,138,216,235,182,156,220,156,227, 62,183,235,255, 0,
+138,193,124, 46,152,139, 70,155,163,182,171,235,226, 61,117, 65,113,143,220,125,188, 49, 36,206, 92,248,186, 17,178, 36,147, 27,
+128, 12,166,209, 90,224, 18,175,246, 88,112,111, 10, 62,225,188, 54, 52, 88,146, 97, 98, 75,156,249,167,247, 41, 29,163, 80,154,
+ 12,165,229,121,116,170, 13, 34,220,120,220,218,178,187,103,101,238, 56,248,177,197, 40,134, 57,210,125,165,157,206, 86, 78, 81,
+146, 45,182,110,171,182,172,128,116,106,187,116,227, 85, 0,120,159, 70,135,186, 48, 55,125,203, 18, 44, 61,179,164, 96,146, 79,
+254, 99, 20,179,201,140,210,193,164,222, 20,154, 24,167,101,214,214,212, 64,190,155,128,120,212, 3,155,184, 34,159,102,195,222,
+112,113,166,202, 92,229,133,177,177,213, 64,144,156,130,186,117,146,116,160, 91,221,152,155, 1,233,167,224,111,184,121, 91, 92,
+219,180,255, 0,224,225,198,105,162,202, 19, 17,251,183,199,145,161,148,106, 82, 85,134,164, 54, 35,157, 67,220,113,123,146, 77,
+177,240,182,184,240,240, 36,233, 99,199, 8,142,105, 0,141, 67, 17,145, 28,111,229,253,219, 70, 2,196,221, 63, 93,133,133, 56,
+109, 19,255, 0,149,229,217,227,192,195,133,250,102, 36,194,105,101,159, 24,173,238,117,205,211,134, 82,206, 46, 75,105,190,174,
+ 60,104, 3,183,115,108, 26, 33,149,179,145, 86, 98,232,161,131, 43, 6, 66,170,253, 69,101, 13, 30,146,235,114,224, 90,227,211,
+ 79,151,184,246,200,103,108, 24,167,142, 92,184,231,135, 30,120, 75, 20,208,103,146, 56,197,219, 73, 26,191,122, 10,175,218,172,
+126, 79, 99,111, 25, 42,163, 37,163,156, 77, 30, 70, 59,193, 46,110, 82,244,162,154, 72,221, 58,211, 64, 34,124,189, 42,140, 25,
+100,181,248,113,225,122,191,155,182,179,159,207,105,146, 17,230,119,204, 61,217, 46, 91,132, 24,254, 83, 90, 55,185,241,159, 46,
+214, 28,185,113,170, 66,203,252,197,177, 95, 48, 54,100,119,194, 12,217, 4,146, 2,172,109,161,200, 36, 89,180,176,210,116,222,
+199,135, 58, 54,223,159,137,185, 66,114,176,164, 18,196, 24,161,224, 84,171,175,196,174,174, 3, 41, 30,130, 43, 27,143,217,185,
+248,231, 61, 26, 28,108,146,240,228,227,227,182, 78, 78, 84,169, 50,100,228,140,157, 45, 13,194, 99,141, 42, 1,233,130,117,123,
+222,219,254,223,192,222,118,172,111, 47,156, 98,120, 36,105,165,227, 43,205, 58, 22,100,232,198,210,188,105,213,178,106,212,237,
+239, 94,195,136,227, 81,244, 42, 46, 36,145,175,194,132,100,127, 77, 25, 87,135, 26, 27,165,220,139,216, 10, 20,104,149,199,141,
+119, 85,253, 52,189, 49,250, 66,151,162, 63, 76, 85, 32,206,163,250,105, 68,142, 60,105,253, 0, 73, 26,135,170,154, 98, 35,196,
+124,244, 7,117,164,244,215, 9, 92,155, 19,194,155,211,106, 66,164,115, 20, 1, 29,130,219, 75,234,191, 62, 22,164,235, 63, 47,
+ 69, 36, 96, 51,128,121, 26,146, 49,227, 52, 4,110,171,210,107, 99, 82,252,170, 91,215, 93,229, 23,211, 64, 69,214,212,241, 60,
+150,176,169, 39, 13, 7, 35, 73,229, 7,166,160, 1,215,147,213, 77,234, 57,230, 5, 24, 66, 10,145,232,185,189,119, 64, 90,254,
+138, 64, 7,173,169,226,103, 3, 72, 2,150, 76,114,120,169,183,133, 71,112,232,218, 91,157, 32, 19,213,181, 1,127,244,245, 80,
+ 37,144,147,164,114, 20, 52,144,162,216,159,139,149,117, 69, 93, 75, 33,241,209, 37,107, 59, 21,244, 90,165,140, 8, 79, 30,179,
+124,194,171,145,138,176,177,171, 40, 95, 82,250,235, 70, 89, 83, 54,243,218, 88,211,201,143,145,220, 56, 48,207, 19, 24,228,138,
+ 76,152, 17,149,212,217,149,213,156, 21, 32,243,189, 93,158,245,236,187, 15,255, 0,232,246,191,255, 0, 91,143,255, 0,121, 95,
+ 63, 99,118,254,215,157,189,119,214,251,151,180,205,220,121, 91,110,230,241,227,236,120,242, 73, 27, 50,207,145, 40,124,135,232,
+ 94, 82,169,166,222,239,203, 89,222,235,237, 77,163,109,239,156, 77,139, 21,159, 11, 11, 53,113, 37,155, 26,103, 15, 46, 27,100,
+170,180,152,206,254, 44,151,230,106, 59, 42,213,217,240, 74, 95,192,170,174,205, 85,113,110, 23,196,250,121,251,215,179,111,195,
+184,182,203,127,249,220,127,251,202,160,203,238, 62,208, 50,203, 42,247, 22,220, 75, 49, 96, 6, 92, 7,153,191,233,215,207,157,
+197,177,237,208,237, 25,121,177,109,115,108,211, 96,229,174, 44, 34,105, 25,198, 82, 54,171,176, 18,125,165,211,114, 87,133,107,
+251, 91,177,123,123, 51,107,237,216, 39,216,178,183,111,243, 12, 82,201,157,220, 48, 78,233, 30,220,200,204,154, 2, 32, 49,254,
+239, 77,223,169,207,195,209, 89,197,158,185,169,221, 84,212, 56,214, 63, 9, 71, 76,184,173,138,202,173,167, 42,116,159,198, 25,
+236, 27,110,231,182,111, 16,147,183,102,195,153, 20, 54, 89, 6, 60,169, 45,152,241, 26,140,108,214,169,139, 24, 11,170, 59,130,
+124, 13,121, 55,224,135,151,195,198,238, 8,122,232,241,166, 92,113,199, 53,192, 14, 21, 92,106, 23,244,142, 53,235,170,203, 36,
+ 65,145,131, 7, 23, 86, 6,224,131,200,130, 43, 71, 50, 69,255, 0,193,127, 59,163,255, 0,196, 87, 82,244,207,150,211, 97,126,
+133,191,245,247,174,160, 21,199, 8,255, 0,187,143,246, 22,155, 78,127,177,253,220,127,176,180,202,208, 34,228,252, 99,217,249,
+ 77, 0,222,244,124,145,239,143,103,229, 52, 43, 80, 30,107, 47,120,239,209,224,103,102, 99,202,153, 15, 2,110,109, 44,126, 93,
+130, 98,249, 73,100,143, 29,140,163,220,109,122, 0, 42,120,159, 14, 70,180,131,188,240, 27,127,125,129, 80, 60,234,242, 64,129,
+ 37, 70,153,165,138, 15, 52,223,225,239,172, 38,144, 84, 57,224, 88, 91,215, 83,155,182,176, 91, 97,202,237,227, 36,222, 83, 47,
+204,245, 36,212,189, 65,230,229,146,121, 52,157, 58,120, 52,135, 79,187,203,211, 73,254, 92,199, 25,249, 57,126,111, 37, 96,201,
+105, 37,147, 9, 89, 68, 93,105,162, 24,242, 73,112,186,205,208,112, 82,214, 7,141,168, 10,136,251,239, 29,176,115, 50,155, 20,
+ 44,152,114, 99, 69, 34,137,227,104,147,205,112, 86,158,116,186,199,211, 55, 18,112, 58, 72,241,167, 14,253,192, 92,252, 44, 9,
+224, 16,205,151,229,213,163,121,163,234, 7,203,118,138, 46,148, 96,222, 85,184, 5,153,120, 5, 32,251, 36, 97,246,108, 88, 56,
+239, 22, 54,231,152,146, 20,199,140, 74, 12, 35,221,196, 12,145, 41, 69,136, 35, 41, 71,210,234,192,131,207,159, 26, 38, 23,103,
+ 97,109,210,227,182, 22, 94, 84, 81, 68, 33,235, 64,175, 24, 89,219, 29,222, 72,154, 82, 35, 4,123,210, 27,170, 21, 83,192, 90,
+212, 4,141,219,125,147,111,205,139, 7, 23, 2, 92,249,140, 47,151, 58, 68, 64,100,134, 55, 72,201, 69, 35,247,142, 75,240, 81,
+232,231, 84,187,127,124, 73, 22, 46, 75,238,248,196, 8, 34,220, 50,163,200,141,148, 9, 35,194,205, 56,157, 61, 6,218, 79,188,
+130,228,241,226,120, 85,238,237,219,241,110,185, 17,101, 12,169,240,229, 88,155, 26,102,198,101, 83, 36, 14,201, 35, 70, 75, 43,
+ 21,247,163, 22,100,177,231,198,162,127,146,246,150,133,225,105, 39,100,120, 51,113,143,190,183, 11,159,144, 51,100, 96, 66,124,
+ 73, 34,141, 30,174,119,168,192, 12,126,246,139, 59, 26, 35,182,226, 12,220,217, 50,165,195, 16,193, 58, 60, 37,161,128,101, 59,
+166, 66,130,172,189, 54, 22,176,248,141,189, 38,155,177,119, 99,238,155,206,102,206,240,183,152,142, 99, 32,133,128,141,241,177,
+ 60,190, 52,128,206, 13,206,179, 44,197, 0, 30,191, 69, 77,155,181,186,208, 71,171,115,203,243,241, 79, 38, 66,238, 23,139,168,
+ 26, 88,142, 60,136,169,211,233, 42,104, 60, 0, 94, 7,143, 58,236, 46,206,219,112, 50,227,207,198,146,113,149, 28,221,126,187,
+ 50,179,178,156,120,241, 26, 25, 25,144,150,141,150, 37, 99,126, 58,184,222,160, 43,119,254,231,222,182,237,245,182,204, 76,100,
+108,117, 27, 89, 70, 36,106,115,153,152,216,210, 47, 19,195, 82,174,145,232, 34,254, 52,153, 63,136,219,118, 14, 22, 54, 86,100,
+ 2, 22,148,100,188,240,188,241,169, 81,137, 57,196,149, 97,215,167,172,229,212,149, 85, 28, 64,240,171,157,203,182, 49, 55, 61,
+210, 61,214,105,231,142, 88,198, 40,104,163, 40, 35,127, 39,145,231, 33, 45,174, 54,110, 14, 72, 54, 97,112,125,134,163,158,205,
+196, 68,133,113,179, 50,177,138,121,149,149,226,100, 15, 44, 89,121, 7, 50, 88,153,140,126,232, 18, 31,117,146,204, 7, 11,248,
+208, 29,221,123,190, 78,215, 46,211, 20, 25, 30, 86, 44,204,137, 34,200,157, 96,108,150, 85, 76,121,102, 93, 49, 32, 36,221,163,
+ 28,135, 42,166,237,238,231,221,183,109,199, 27, 31, 43, 37,162, 71,198,195,157,124,166, 12,153, 41, 33,200,146,116, 45, 52,145,
+ 44,139,142, 25, 98, 83,239,145,166,231,244, 77,182, 57,123,116, 25,153,184, 25,178,179,137, 54,233, 94,104, 2,144, 20,180,144,
+201,140, 67,220, 18, 70,153, 79, 43,113,170,189,179,180, 33,218,242,206, 78,219,186,102,226,235, 84, 73,226, 95, 44,233, 42,164,
+179, 78,170,221, 92,103, 96, 47, 59,143,112,142, 30,190, 52, 5, 22,119,123,238, 80, 73,220,141, 11, 65,208,199,198,203,151,101,
+ 26, 46, 67,237,204,184,249, 26,205,253,237, 82, 61,199,170,141,220, 29,197,220,155, 76, 27,174,219,141, 44, 57, 59,158, 44,187,
+111,146,201, 48,133, 12,155,132,175, 6,137, 35, 12, 65,101,104,143, 17,110, 4, 85,156,255, 0,135, 93,187, 54,223, 14, 8,105,
+ 97,104,163,158, 25,115, 34,232,174, 68,235,146,141, 28,167, 34, 78,145,214, 78,173, 92,190, 32, 61,149, 52,118,174, 3, 51, 73,
+151,155,145,149,151, 46, 86, 46,100,185,147, 52, 66, 70,108, 23, 18,193, 30,152, 98,142, 53,140, 17,196, 42, 3,196,241,191, 26,
+ 3, 41,157,223,251,156,185, 59,174, 70,214, 98, 59,118, 62,200,249,248,132,166,163,230,145, 49, 39,185,111,180,161, 51, 20, 91,
+211, 91,125,151, 42, 73,240,167,200,150,108,156,178,140,218, 68,248, 82, 96,203,238,168,109, 41, 14, 66, 68,205,123,240,107, 90,
+252, 47,194,169, 19,240,255, 0,183, 96,196,155, 10, 41,230, 72,167,198,204,195,112,175, 29,250,121,178,199, 60,132,126,238,215,
+ 78,146,170,122, 20,113, 7,157, 95,193,136,209,225,207,139,151,185, 79,184,245,195, 43, 75,144, 49,209,213, 89,116,149, 95, 41,
+ 12, 11,243,130,104, 10, 44,110,252,199,201,198,158, 69,193, 39, 38, 12,156, 44, 79, 47, 20,241, 74, 53,231,186,197, 18,180,139,
+238,171,163, 18, 29,126,201, 28,205, 65,221,187,251, 45, 54, 73,178,246,204, 13, 57,241,226,103,229, 74, 29,213,146, 3,133, 57,
+195, 99,196, 14,173,229, 28, 7, 15,116,124,149, 99,135,217,123,110, 36, 41, 19,102,229, 79,211,108, 7, 82,221, 32, 47,182, 63,
+ 83, 24, 90, 56, 87,135, 0, 31,211,234, 60,105, 50,187, 23,107,203,197,108, 36,205,203,199,138, 72,243, 32,200,104,140,101,228,
+135, 58,115,153, 44, 68,188, 46, 6,153, 79,186, 64,189,184,113,160, 46,183,205,230, 77,173,176,241,177,112,219, 55, 55, 58, 71,
+ 72, 32, 87, 17,139, 69, 27, 79, 35, 51,176,107,123,169, 96, 45,196,145,237,170,101,239, 88,231,203,142, 39,219,102,135, 17,229,
+ 56,107,145, 49, 85,113,148, 49,124,243, 66,240,252, 75,101, 82,183,253, 33,232,227, 86,251,214,213, 14,239,229,164, 92,169,240,
+178,177, 29,159, 31, 43, 25, 87, 90,245, 35,104, 36, 91, 74,142,164, 50, 57,240,224,108, 69, 85, 30,209,193,142,113, 44, 25, 19,
+180, 81,147, 52, 56,179, 48,104,252,215,150,242, 94,101,152,167, 80,177,143,157,218,215, 37,173,122, 32, 69,195,239,136, 39, 76,
+ 86,159,111,124,127, 56, 54,249,163,187,171,219, 31,115,103,138, 9,152,175, 43, 72,154, 89,125, 98,161,205,223, 71, 43,108,207,
+203,195,193,150, 24,177,112, 6,224,249, 97,162, 37, 35,151,175,208, 40,142, 61,246,126,133,249, 91,141, 4,246, 62,108, 93,175,
+ 38,218,179,140,173,219, 39, 7, 11,110, 51, 75, 38,152,177,215, 16,106, 86,128,199, 18,177, 88,229,102,117,212, 53, 30, 28,120,
+ 85,235,246,118,212,248,121,216, 58,229, 72,115,240,113,246,201, 66, 50,141, 16,227, 44,137, 25,138,232,108,214,148,222,247, 28,
+184, 85, 4,108,190,239,104,183, 7,195,139, 5,252,184,202,125,185, 51, 75,173,188,202, 99,182, 91, 14,151,197,164, 42,218,254,
+159,166,154, 46,248,221,228,237,248,242, 70, 10,253,228,145,108,243, 74,197,215,167, 36,123,156,139, 25,117, 81,109, 36,149, 96,
+ 5,248, 92, 31, 72,169,217, 29,169,155,147,220,131, 44, 72, 34,218,151, 40,231,178, 44,215,213, 35, 98,190, 35, 90, 3, 15,186,
+228,181,203,117, 74,216,112, 80, 73,169,195,178,118,193,132,248, 41,145,146,138,248,219,126, 32,148, 52,122,213,118,183, 50, 99,
+ 72,183,140,174,189, 70,237,117, 32,250, 5, 64, 39,113,119, 72,216,100, 43,228,155, 36,174, 36,187,132,218,100, 84, 9, 14, 59,
+196,146,124, 64,234,111,222,240, 30, 52,167,186, 72,220,223, 1, 48, 93,225, 57, 79,183,195,148,100, 85, 15,150,152,231, 47,165,
+160,241, 10, 85, 74,235,244,248, 91,141, 31,119,237,172, 45,233,229, 57,114,204, 12,184, 83,237,174, 99, 40, 63,117,144,209,187,
+191, 20, 62,253,225, 22,240,231,194,158,157,183,136, 55, 65,185,245,165, 40, 50, 14,106,225,157, 29, 17,148,208,249, 83, 56,247,
+117,223,167,126, 26,173,115,123, 94,128,204,236,221,239,157,147,135, 30, 86,102, 57,151, 54,108,125,180,197,137, 25, 68,137,165,
+206,121,163, 86, 87,247,153, 65,233,234,109, 87,176, 28, 56,212,249, 59,251, 26, 45,195, 23,107,203,197,108, 92,169,158, 24,101,
+130,105, 81,102, 89,114, 37,104, 35, 17, 68,125,233, 83, 82, 92,184,251, 36, 31, 97,177, 59, 31,110,194,129,177,113,242,242,181,
+170,226, 46, 52,238, 98,103,135,200, 73, 36,216,250, 0,137, 84,219,170, 84,235, 6,235,235,227, 82, 98,237, 88, 48,242, 34,201,
+ 77,195, 48,155,196,217,106,206,135,204,201, 11,201, 52,111, 51,104,212, 61,233, 77,213, 10,169, 22, 22,176,170, 0,239, 93,196,
+187, 38,100,146, 74,178, 73, 20, 27,110, 86,224,240, 32, 64, 27,161, 36, 9,241, 55,188, 27,247,156, 60, 40,111,221,179,185, 56,
+145,237,140,251,146,230,203,130, 49, 58,171, 99,210,199, 92,198,147,171,166,223,195,112, 45,111,139,135, 46, 53, 59,118,237,188,
+ 29,237,230,124,185, 37, 67, 54, 20,251,115,116,138,139, 69,144,209,200,236, 53, 35,123,224,196, 45,225,234,160,100,118,182, 46,
+ 68,243,228, 99,229,228, 98,101, 75,148,249,195, 38, 35, 25,100,121, 49,215, 10, 68, 64,232,203,164,198,131,152, 36, 55, 27,214,
+121,148,133,183,119,100,146,100, 77, 22, 92, 14,189,108,249, 49,113, 99,101, 17,188, 73, 30,221, 30,226, 86,101, 63,106,250,148,
+250,234, 44,253,229, 62, 88,219,219,109,197, 43, 30, 75,237, 47,147, 52,165, 79, 77, 55, 57, 84, 8,130,253,163,211,189,216,114,
+ 36,124,147,165,236,236, 40,145, 60,190, 94, 76, 82, 46, 73,203, 89,181, 35,184,102,197, 27,123,173,229,141,238, 26, 37,230,110,
+117,113,189, 38, 63,101,224, 3,135,210,202,201,142, 28, 53,193, 86,136, 24,200,153,182,214, 15,140,242,150,140,155,248, 54,141,
+ 55,249, 42,130, 26,119,246,214,239,184,170, 71,212, 56, 48,207,144,145,197, 42, 60,142,184,242,140,114,178, 34,155,196,206,236,
+186, 3,115, 83,122,181,237,237,195, 59,114,125,213,115,226, 88, 95, 15, 56,227, 36, 74, 67,105, 65,143, 4,182,214, 62, 47,122,
+ 83,199,209, 77, 94,206,195, 48,230,226, 62, 86, 75,225,228,164,209, 71,141,173, 85, 32, 92,137, 12,239,210,210,128,150, 15,197,
+ 75,234,176,225,233,188,237,163,104,109,168,101,152,167,151, 46, 92,201,252,214, 84,211,244,193, 50,152,227,132,233, 17, 36,106,
+ 22,209, 14, 22,160, 39,232,247,173,106, 99, 1,126, 28, 42, 82, 47, 81, 11,218,204, 57,138, 3, 1, 98,104, 4,143,128,163, 69,
+140,217, 74,120,133,183,137,160,170, 18, 11, 6,211, 92,131, 32, 11,197,123,122,170,144,146, 54,233, 98,253,233, 96, 66,113, 52,
+ 96, 99,189, 67, 47,150, 22,205,171, 73,224,111, 82, 0,191, 46, 30,186, 2, 66,152,248,222,147, 84,124,232,122, 52,139, 95, 81,
+231, 75,110, 20, 1,109, 25,230,126, 90,126,152,239,207,149, 71, 55, 63, 39, 42, 66,121,222,128,145,210,142,222, 21,198, 4,229,
+122, 5,200, 60,233,117,155,208, 15,120,213, 69,129,168, 89,145,251,161,188, 69, 29,174, 90,194,147,166, 39,117, 67,240,243,111,
+ 96,162, 4, 65,143, 43, 8,200, 70, 32,248,128,105,221, 9,255, 0,217, 63,234,154,186, 80, 0, 10, 5,128,224, 0,167, 0, 61,
+ 21,190,207, 18, 73, 81, 22, 44,164,234,104,154,195,195, 73,169, 48, 67, 50,220,116,152, 11,248,169,171, 36, 21, 33, 5,189,117,
+ 21, 20,241, 29,203,129,243,215,110,199, 2,247,135,120,102, 77,181,161, 56,123,150, 65,155,125,200,221,167,218, 34,198, 89, 38,
+116, 88, 25,241,193, 44,100, 97,202,177, 61,241,180,207, 63,121,166,209,183,236,141,183,102,228,116,145, 49, 83, 50, 76,255, 0,
+ 51, 44,204, 89, 50, 19, 38,110, 44, 37, 14,191,233,122,182,220,251,159, 31,102,238, 94,243,218,183,173,167,239,125,135,114,221,
+178, 30,104, 58,175,142,203, 60, 19,202,209,188, 83,160,107, 27, 55, 17,110, 34,161, 79,189,239,251,159,226, 6,209,185,249,120,
+ 59,127, 39, 28, 99, 13,166, 12,242,240,226,193,141,142,191,184, 89, 36,148, 6, 49,149, 83,118,241,189,100,164, 94,235,236,238,
+231,218, 54,244,220, 55, 45,203, 31,118,196,197,148, 98,100, 54, 38, 89,202,242,147,145,126,132,192,252, 7,135,135, 10,223,246,
+118, 22, 60,189,165,139, 2,118,220,122,183, 24,143, 79, 10, 78,224,202,194,155,117,104,134,153,101,135, 13, 6,131,114,188,143,
+242, 85,127,126, 71,141,139,218,187,132, 91, 35,108, 56,144,103,100,197,153,188, 69,183,238,167, 63, 39, 34, 80,196, 34,195, 27,
+ 34,104,141, 26, 66,214, 21, 73,219,253,246,248,241,108,216,179,246,207,222,221,197,179, 70, 99,237,236,193, 36,202,202,141,170,
+ 88,250,152,209,169,235,104,212, 89, 56,143,203, 81, 36,148, 37, 11,192,173,182,229,185,243, 47,127, 12, 87, 22, 92, 13,232, 54,
+ 36,177, 67, 38,229, 26, 65,137, 27,130,209,179, 36,186, 33, 38, 81,119, 35,225,229,123,215,185, 97,225,228, 38, 44, 8,113,229,
+ 77, 49,168,208,224,150, 22, 3,131, 17,192,154,241,223,193,169,242, 14, 6,237, 38, 75, 50,229,201,187,226,180,177,149,109, 79,
+ 37,164,102, 70, 85, 43,167,222,253, 46, 0,215,208,227, 83, 42,179, 2,172, 64, 44,151, 6,199,209,113, 86, 8, 85,116,101,232,
+219,166,215,233, 90,214, 60,250,183,183,205, 93, 86,190, 31, 39,229,174,171, 4, 40,223,236,127,119, 31,236, 45, 54,156,255, 0,
+217,255, 0,119, 31,236, 45, 55,198,133, 35,100,143,124,123, 63, 45, 7,213, 70,200,248,199,179,242,208, 79, 19,194,128,243,103,
+239, 45,250, 60,167,193,213, 17,145, 93,182,205, 90, 5,254,240,124,215,134, 19,110, 28, 60,186, 7,183,243,175,225, 85,123,230,
+118,226,251, 82, 79, 14, 81,197,140,225,247, 30,168, 33, 5, 20,182, 62, 96,141, 94,250,175,171,136, 55,240,227,110,117,234, 95,
+117,109,189, 67, 33,195,131,168,102, 25, 69,250, 73,171,174, 23, 64,158,246,191, 80, 47, 13, 92,237, 76,155,100,217,178, 97, 72,
+178, 54,236,105, 99,136,202,209,163,193, 27, 42,153,201, 51, 21, 82,166,198, 77, 71, 87,166,252,104, 10,237,135, 51,113,203, 27,
+214, 38, 86, 72,146,108, 44,215,197,131, 36, 70,170, 66,156,120, 39, 82, 80,112, 58, 90, 99,242,115,172, 31,109,110,187,222, 58,
+ 96,229,121,246,152, 73, 14,193, 22, 66, 74,161,245,174,102, 70, 68, 13,239, 49, 36, 50,171,124, 67,137, 32, 94,189, 86, 60,120,
+ 33,105, 30, 24,150, 54,153,250,147, 50, 40, 82,239,164, 38,183, 35,226,109, 42, 5,207,128,168,176,236,187, 54, 48, 43,143,183,
+ 99, 68,165,146, 66, 18, 24,212,107,137,204,177,183,186,188,209,216,178,159, 2,111, 64, 98, 23,127,221,177,176,177,102,198,146,
+ 44,124, 69,159, 56,229,116,145, 36,100, 43,184,201, 4,111, 60, 76,221, 81, 11, 0,192,188, 98,250,253, 85, 59,241, 3,113,220,
+ 99,198,207,219,241, 50,124,172, 41,180,229,102,200,193, 65,121, 25, 94, 56,149, 3,112, 43,109,100,221,120,220,143,151, 80,219,
+ 22,205, 51, 66,242,109,248,206,216,236,210, 64, 76, 73,116,103,126,171,178,251,188, 9,127,124,255, 0, 59,143, 58, 46,126,211,
+181,238,130, 63,188,176,160,204, 17,106,233,140,136,214, 64,186,133,152, 0,224,243,183, 26, 3, 27,157,189,110,184,178,110,255,
+ 0,119, 50, 69,209,221, 37, 89,250, 43, 27,228,180, 49,224,227,203,212, 72,167, 96, 36, 10,238, 58,154,125,237, 28,184,212,125,
+191,117,223,101,238, 9,113,113,247, 53, 41,185,231,195, 31, 83,165,169, 35,140,237, 43,157,251,132,144,251,160,144, 0,191,180,
+241, 38,183, 25, 91, 30,205,154, 25,114,240, 49,231, 87,147,174,226, 72,145,181, 75,164, 70,100,107,142, 44, 81, 66,146,124, 56,
+114,167,141,167,109, 92,177,158,184, 80, 12,193,107,100,136,147,170, 52,163, 68,191,188,182,174, 8,197, 71, 30, 70,213,150, 15,
+ 59,125,223,114,129, 62,242,194,200, 76, 57, 48,246,237,255, 0, 40, 70, 16, 52, 82, 28, 77,197,116,161, 71, 54,187,233,226,220,
+248,155, 90,245,161,143,184,247, 92,173,217, 54,245,116,133, 37,221, 39,192, 91,160, 44,145, 38,214,185,201,207,155, 44,205,199,
+213,194,180, 18,236, 91, 36,194, 46,190,219,139, 39, 69,153,225,213, 12,103, 67, 72,253,103, 43,238,240,212,254,243,122, 79, 19,
+ 68, 59, 86,214, 51,206,232, 48, 96,243,228,131,231, 58, 73,213,190,131, 21,250,150,213,125, 7, 79,179,133, 1,230,253,183,188,
+238,241,237,176, 70,153, 10,217, 89, 56,219, 20, 39,112,145, 53,200,131, 50,108,152,216,190,162, 67,149, 3, 74,234,251, 71,141,
+249, 84,204,222,234,238, 8,176,231,104,242, 35, 89,112, 49, 55,108,135,155,162,164,100, 54,219,155, 30, 44,100, 6,224,171, 34,
+147,170,223, 37,171,110,155, 46,201, 20, 19, 99, 69,182,226,199, 6, 64, 11, 60, 73, 12,106,174, 21,153,212, 56, 85, 23,179, 59,
+ 48,245,146,106, 76, 59, 62,208,208, 8, 14, 6, 57,137, 97,108, 85,140,196,133, 68, 14, 67, 60, 54, 35,224, 98,160,149,228,109,
+ 64, 79, 78,131,107, 8, 85,180, 29, 46, 22,198,205, 96,108,109,200,216,211,194, 3,192, 14, 4, 80,227,131, 30, 22,149,160,137,
+ 34,105,223,171, 57, 69, 10, 94, 77, 42,154,222,223, 19,105, 64, 46,124, 5, 16, 58,175, 51,234,168, 5,210,188, 5,190,138, 69,
+ 77, 76,111,225,227, 74,100,140,243, 97,243,211, 86, 84,187, 29, 84, 1, 52,241, 35,194,184,175, 11, 40,246,208,218,112,111, 97,
+242,216,210, 9,129, 23,227,126, 86,177,160, 8,160,120,241, 53, 25,210,236,108, 72, 30, 2,159,213,244, 3,127,101,168,122,152,
+143,174,170, 3,116,145,195, 85, 57, 82,252, 73,164,247,200,191, 32,107,131, 58,242,249,234,129,190, 45, 78, 20,209,114, 73,244,
+210,131,110,117, 0, 43,220,223,211, 68, 90, 24,167,131,106, 3,148,113, 39,214,105,100,177, 20,168, 56,123,107,159,145,170, 66,
+ 51, 61,148,129,204,210, 67,226,105,143,241, 26, 36, 60,141, 67, 72,108,252, 72,189, 44, 6,203,243,210,178, 23,126, 4, 11, 15,
+ 26,232,197,151,229, 52,228, 9, 74,150,141, 71,139, 18,110,125, 0, 84,116, 18, 16,116, 62,144,134,227,229,227, 70,149,191,134,
+131,244,110,126, 94, 20,193,125, 46, 64,248,135, 15,146,161, 71, 98,222,236, 91,199,159,182,135, 34,129,112, 61, 52,171, 32,191,
+ 15, 27,112,166,187,112,227,226,104, 6, 88,104, 35,253, 56, 83,225,205,120, 23, 66,128, 65, 52,206,104,126, 90, 54, 57,195,208,
+ 4,160,234,246,218,180,100,123,238, 38, 72,250, 69, 0, 47,194,246,165, 95, 19,235,167, 76,152, 38, 48,209, 31,222, 92,105, 31,
+ 45, 37,133,173, 64, 56,159, 71,209, 74, 0, 42, 60, 79,141, 54,222,154,164,219,251,183,107,207,223,243, 59,114, 33, 44,121,216,
+ 96,150, 50, 42,136,228,211,167, 87, 73,131, 49, 54,212, 57,129, 64, 94,243,164, 2,231,213,232,170,248,119,156, 89,183,140,157,
+141, 86, 65,149,139, 10,100, 73, 33, 3,166, 86, 66, 66,133, 58,181, 95,135,162,172,109,242,154, 3,136,224, 41, 45, 98,106, 36,
+251,182, 22, 62,229,137,180,202,228,101,230,172,143,143, 30,146, 65, 88,134,167, 37,185, 11, 84,210, 9,160, 7,111,124, 31, 69,
+207,209, 82,177,162, 42,190,247,196,120,154, 20, 75,119,191,128,163, 79, 58, 98,227,203,144,224,148,133, 26, 70, 11,206,202, 53,
+ 27, 94,213,170,245, 35, 97,194,250,233,224, 48,229, 84, 29,177,221,123,103,118,224,190,126,218, 36, 69,142, 67, 20,144,206,170,
+178, 41,176, 96, 72, 70,113,102, 7,129,189, 76,216,183,220, 77,251, 17,243, 49, 22, 68,142, 57,165,199,101,152, 40,109, 80,182,
+134, 35, 75, 48,181,199, 10,223,113, 30,188, 11, 80,214,240,162, 35,159, 1, 76, 12,180,245,101,168,186,150, 58,158, 35,129,147,
+219,184,216, 63,137, 18,247, 86, 25,205,218, 91,184, 76,115,170, 91,169, 23, 86,105, 35, 19,197,226, 25, 53, 95,133,102,191, 17,
+ 38,217,115,255, 0, 17, 59,117,240,183, 28,127,186, 14, 30,222,145,238, 57, 10,179,192,177,163,186,235,158, 51, 96,214,183,188,
+173,111, 93,171,220,166,252, 54,236, 93,195, 43, 35, 51, 51,102,134,105,242,164,105,178, 28,153, 6,185, 29,139,179,176, 14, 5,
+201, 55,172,246,103, 98,246, 30, 55,120,237,221,184,189,181,134,113,179,113, 39,202,121,139, 77,212, 13, 11, 5, 10, 63,121,166,
+198,245,134,161,137,131,204,191, 19, 27, 99,204,237, 92, 22,196,207,219,242,247, 77,191, 58,120, 38,154, 25,112,206, 76,216,231,
+132, 79,163, 6, 56,147, 65,248,130,216,233, 28, 47,123,214,219,183,247, 30,203,194,198,252, 58, 94,225,143,202,238,131, 5, 38,
+219, 55,123,133, 80,194,241,121,105,219,244, 27, 95, 13, 92, 1,244,120,217, 71,248, 93,177,166,113,135, 43,182,176,198, 39, 94,
+ 71, 92,128,198,253, 27,158,156,122, 68,183,189,173,225,245, 80,143,225,198,206,243, 97,200,189,171,139, 36,122,102, 92,172, 51,
+ 47, 16, 67,126,229,145,204,182,248, 69,200,189, 94,215, 18, 36,205,126, 26,162, 52,253,195, 38,149,214, 59,130, 16,178,149, 86,
+176, 47, 45,199, 18, 56, 26,250, 8,130,121, 10,243,221,167,181,231,217, 4,152,187, 95,111, 99,226, 99,228, 60,114,203,229,231,
+ 40,161,227, 47,165,238,210,151,189,154,189, 6, 53,208,138,183, 39, 72, 2,228,146,120, 15, 18,120,154,133, 23,143,163,141,171,
+169,124,107,168, 10, 7,229, 31,247,113,254,194,211,125,119,167,191,216, 31,238,227,253,133,166,113,229, 64, 70,200, 62,248,246,
+126, 90, 21,232,153, 32,235, 28, 60, 62,186, 13, 0,251,139,130,105, 3, 0,107, 63, 7,116, 99, 78,155,115,152,140,105,184,101,
+102, 97,171, 59, 11, 70,112,188,198,183,115,250, 45,229,141,189,180,120,251,155, 97,151, 21,243, 83, 54, 51,143, 19,199, 27,185,
+ 12, 61,233,173,210,176, 32, 18, 36,212, 52,145,192,248, 80,133,193, 97,196, 83,121,142, 85, 81, 39,116,108, 48,199, 4,210,103,
+ 70,177,228, 43, 60, 76, 67,124, 49,184,142, 70, 97,107,168, 70, 54,109, 86,211,227, 82,226,221,246,217,103, 92, 88,242, 85,166,
+121,101,199, 88,197,238,101,128,106,149, 57,125,145, 66,147,128,183,203, 92, 61,117, 73, 15,117,109,178,231,102,237,108,198, 44,
+204, 73,158, 4,137,191,181, 49,192,153, 76, 80,219, 72,247, 92,240, 38,254,233,167,225,119, 54,213,155, 6,218,207, 48,131, 35,
+115,199,131, 38, 28,103,226,202,185, 11,174, 53,118, 3, 72, 45,196, 45,207,188, 65,181, 8, 92,131, 79, 22,170, 84,238,109,129,
+219, 37, 87, 58, 50,113, 35,150,124,134, 58,128, 88,224,110,156,173,168,139, 29, 13,193,173,202,163, 97,119, 94, 22,225, 49, 76,
+112, 22, 37,204,147, 4,201, 35,104, 44, 98,197, 25,172,233, 27, 46,163,193,172, 84,216,139, 19, 81,148,209, 27, 87, 90,226,168,
+227,238,189,130, 92,105,243, 35,207,141,160,199, 17, 25, 92, 6,229,145,194, 29, 35, 77,223,168,120, 46,155,220,240,231, 79,198,
+238, 93,191, 51, 51, 7, 19, 5,188,202,103, 71,149, 34,100, 33,247, 84,225,180, 81,200,140, 13,141,245, 77,244, 84, 5,185, 20,
+ 88,163, 75,106,110, 36,208,238, 42, 72, 26, 84, 88, 0, 42, 1, 22, 56,129,226, 7,170,137, 18, 71, 98,116,142,116,222, 22,191,
+163,149, 62, 48, 2,131,127, 95, 26, 1,234,171,171,144, 20,134,250,128, 0,105,241, 52,161,214,220, 92, 47,203, 77,121, 96, 28,
+156,124,244, 3,138,128, 57,241, 2,163,169, 82, 15, 11,216,211,204,201, 99,164,220,252,244, 62,170,129,240,155,143, 81,160, 28,
+ 72,229, 64, 60, 71, 5, 55,229, 78,105, 65,181,193,181, 52,184,245,252,213, 80, 56, 22, 30, 28,189,116,132,181,172, 41, 53, 11,
+ 30, 6,144,183,160,112,170, 4, 6,148,159,116,251, 41,164,240,164, 98,116,212, 2, 10,119,133, 32,167, 91,133, 0,241,192, 10,
+108,166,200, 77, 62,212, 57,133,210,198,169, 8,128, 23,110, 30, 53, 33, 84, 11,138,100, 41,198,255, 0, 53, 45,200,144,159, 93,
+103,139, 52, 56,175, 27,208,211,151, 26,120, 36,177,191,201, 76,244, 85, 1,228,177, 37,189, 8,191,203, 68, 73, 99, 86, 17,159,
+ 19,107,250,253, 20, 50,108,162, 66, 61,210, 52, 53, 8,151,208, 2,168,177,247,181,250, 42, 20,115, 42,130,204,162,214,125, 32,
+143, 80,185,161,185,213,106, 40, 42,108,169,197, 99, 82, 75,122, 89,185,208,154,214,170, 67,136, 58, 57,115,161,178,113, 6,213,
+ 56,220, 32, 4, 2, 45, 77, 58, 77,189,218,164, 34, 0, 4,169,110, 92, 63,150,166,131,243,250,106, 33, 55,156,120,122, 42, 90,
+113,176,160, 29,113, 94,103, 38,213,145,153,147,220, 59,166,212, 63,249,214,207,186,156,172, 32, 7, 23, 94,132, 98, 88, 15,243,
+101, 81,107,120,154,244,221, 35,128,241,170,253,187,102,197,219, 50,247, 12,184, 30, 70,147,114,152,100, 78, 28,130,161,130,132,
+178,105, 85,176,176,241,189, 3, 49,120,221,193, 22,110,231,188,247, 22,219,239, 91, 96,143, 38, 36, 54, 37,100,140,206,198, 54,
+245,171, 46,147, 81,228,217, 34,135,177,151,186,147, 47, 35,239,225,136,155,143,222, 70,121, 53,245, 24, 9, 76,122,117,232,211,
+199, 70,157, 54,173, 94, 7,106,236,155, 46,231,184,238, 56,218,245,110,128,140,140, 87, 42, 97, 80,196,179, 8,215, 72, 32, 49,
+ 39,133,205, 65, 94,200,219, 78, 58,237,199,115,206, 59, 48,109, 95,116,153, 87,163, 96,218,250,101,244,117, 76,119,251, 58,168,
+ 66,151,115,218,176,247,206,238,237,172,140,193, 50, 54,233,131, 44,217, 43, 28,210, 71,103, 72, 80,128,154, 88,104,245,219,159,
+141,122, 30,227,149,143,183,224,100,230,229,185, 76,120, 34,121,101,101,230, 21, 65, 39, 77,188,125, 21, 85,188,118,230,221,188,
+207,131,148,217, 25, 24, 89, 24, 26,198, 60,248, 82,116, 92, 36,128, 43,199,125, 45,238,144, 42,227, 43, 15, 31,113,197,159, 11,
+ 41,122,152,217, 49,180, 82,161,225,116,112, 85,133,199,168,209, 20,242,214, 92,140, 76,206,216,222,182,237,174,125,171, 27, 51,
+115,197,198, 25,153, 25,210, 77,145,147, 14, 77,248, 77, 1, 46,170, 25, 5,248,181,197,122,166,237,255, 0,241,153,191,220, 75,
+251, 6,179,176,126, 30,225, 70, 54,241,145,187,110, 89, 48,237, 89, 17,101, 96, 65, 44,200, 99, 67, 1,186, 33, 94,151,188, 60,
+ 61, 54,224, 8,227, 90,185,177,211, 39, 30, 88, 36, 36, 44,200,209,177, 94, 96, 48,210,109,123,250,107,117, 70, 79, 46,217,135,
+249, 99, 7,183, 59,186, 14, 27,102,118, 38, 54, 14,254, 22,218, 87,128, 72, 50,219,250, 12,116, 49,244, 83, 94,121,161,236,233,
+159, 30, 86,140,183,113, 58,150,141,138,221, 91, 48,220, 93,124, 13,122, 38, 55,110,109,184,221,190,189,180,202,211,237,235, 1,
+198, 34, 98, 11,178, 16, 71, 18,161, 69,248,243, 2,171,113,187, 23,101,131,182,101,237, 78,166, 68,152, 50, 57,151,172,238,189,
+117,114,226, 64,234,232,138, 1, 86, 28, 61,218,176,254,192, 3,186, 39,158, 62,234,236,248,210, 70, 68,151, 35, 40, 72,138, 72,
+ 12, 4, 23, 26,128,231, 85, 91,103,111,226,247, 46,247,221,113,110,217, 25,114,197, 6, 96,139, 26, 21,201,153, 35,143, 84, 65,
+181,170, 35,168, 36, 19,192, 27,129,232,171,236, 94,199,198, 77,199,111,221,115,119, 93,195,112,204,219, 89,219, 29,178,102, 70,
+ 75, 58,232, 42, 80, 70, 7, 47, 17,196,248,154,186,218,246, 28, 77,175, 51,114,205,199,121, 30, 77,210, 97,145,144,178, 21, 42,
+174, 20, 37,163,210,170, 64,176,241, 38,175,108,235, 0,242,204, 61,169,115,255, 0, 11, 63,205,249, 89,249,207,190,227, 69, 36,
+184,153,126,106, 97,210,242,211,188, 40,145,162,184, 64, 52, 39, 19,107,223,141,235, 85,187,224, 99,119, 31,122,118,188, 27,155,
+ 74,209, 79,180, 77, 44,226, 25,100,128,185,253,219, 16,205, 3, 35,105, 36,242, 6,180, 56,125,149,182, 99,246,147,118,106, 75,
+ 57,219,154, 57, 34, 51, 22, 78,190,153,100,105,155,222,233,232,190,166,225,238, 81,183, 46,202,195,220,178,182,252,232,183, 28,
+237,191, 43,109,198, 56,112, 77,135, 36, 72,198, 54,181,245,245, 33,147,137,211,225,106,195, 68,208,201, 99,203, 63,105,111, 61,
+215,179,109, 83, 77,149,182,109,219, 95,222,184,184,211,200,211, 28,105,130,187,116, 17,164, 44,218, 94,218,172, 77, 80, 97,109,
+ 61,223,153,178, 96,111,187, 38,207,156,253,197, 42,195,152,155,228,155,140, 26, 38,214, 68,142,143, 3,100, 1,210,100, 37, 66,
+105, 22,241,241,175, 90,217,123, 87,105,216,225,202, 76,100,121,229,207, 58,179,242,242,220,207, 62, 65,182,159,223, 72,252,192,
+ 7,128,229, 84,248,255, 0,135, 24,184, 95,225,176,119,173,211, 23,104,213,172,109, 17,100, 40,128, 93,181, 24,213,138, 25, 4,
+103,197,117,124,181, 39, 72, 26,148,178,237, 95,230, 31,196,156,216, 55, 44,140,152,241,112,176,176,114,198, 4, 83, 17, 19, 76,
+ 28,144, 36, 3,131, 40,177,184, 28,235,210, 53,183,133, 86, 69,176,226, 99,239,217,125,194,143, 33,203,204,130, 44,105, 99, 98,
+189, 32,144,146, 84,168,211,170,252,120,251,213, 99,111, 73,170,132, 91,144,253, 77,244, 95,233,174,164,176,183, 63, 15,203, 93,
+ 84,186,253,133, 51,219,220, 63,238,227,253,133,166,211,159,251, 49,254,238, 63,216, 90, 75,138,201,162, 38, 79,198, 56,120,126,
+ 83, 65, 22,191,133, 31, 36,251,227,217,245,208, 8,185,160, 49, 56,189,142,216,178,109,249,144,197,133, 30,229,143,151,184,228,
+101,230, 42, 14,164,145,229,174, 90,192,165,204,122,159, 79, 94, 61, 74,220, 56,112,191, 10,172,255, 0, 45,247, 14,223,135,213,
+150, 36,201,202,159, 47,102, 98,137, 52,211,157,120,153, 11,213,145,203, 69,238, 69,246,189,209,100, 95, 14, 21,233, 54,183, 42,
+ 78, 23,160, 60,219, 39,182,183,227, 43, 97, 71, 4, 70,109,207,111,222, 19, 42, 86,105, 60,190, 59,110, 89,145, 75,161,100, 17,
+157, 76,138,247, 10, 64,213,164,213,182,205,180,186,119,174,231,152,129,254,239,197,140, 8, 89,209,144, 28,188,132,134, 44,134,
+ 66,192, 6,178, 98, 37,200,225,239,154,217,219,209, 93, 99,206,128,199,191,108,110,210,238,243, 72,205, 2,224, 62,227, 38,235,
+ 28,170,238,102,187, 96,125,222,176,178, 24,194,143,120,234, 36, 49,225, 81, 48,251, 35,112,199,201,218,186,221, 41,227,198,131,
+107, 76,135,243, 57, 49,164,114,237,163,222, 41,143, 30,136,231,214, 66,148,105, 62, 30, 60, 60, 43,119,115, 93,126, 55,160, 48,
+242,118, 62,231, 38, 44,144, 52,216,234,205,137,186, 64,166,238, 71, 83, 55, 61, 51,224,184,208, 61,208,169,103,244, 30, 87,163,
+193,219, 59,196,185,163,112,203,242,208,188,155,150, 70,123,195, 28,175, 38,152,230,219,126,239, 68,212, 98, 75,176,147,137,225,
+107,124,213,178,189,205,112,227,232,160, 60,250, 94,217,220,182,109,182, 60,199, 49, 77, 38, 6, 54,199, 26,199, 16,154, 64,210,
+237,141, 32,155, 80,142, 38,144, 70,122,183, 12,168,196,115, 43,194,172,251, 75,107,204, 9,143,186,102, 99, 36,114, 25,183, 89,
+ 46,218,227,117, 92,220,181,153, 10, 67, 34,106,179,172,119,247,138,144, 45,195,143, 13,119, 16, 43,175,194,178, 14, 63, 13,232,
+186,125, 44,222,203,154, 24,177, 0,123, 40,164,113,225, 80, 9,211, 83,207,143,168,154,120,141, 15, 13, 60,233, 0, 60,237,111,
+ 93, 56,159, 26, 1, 27, 66,139, 90,186,195, 72,240, 28,169,166,204, 5,205,248,211,153,213,121, 17,127, 71, 10, 1,224, 15, 30,
+ 21,196,218,152,101, 75, 3,170,231,209, 76,234, 3,204, 31,152,213, 3,139,112,183,133,233,183, 94, 28,105,174,117, 15,132,129,
+233, 52,150, 30,138, 1,110,190,154, 75,171, 27,120,210,114, 97, 78,225,112,124,106,131,136, 20,201, 56, 39,180,211,137,227, 76,
+147,144, 30,186,128, 65,206,156,125, 31,233,206,154, 57,211,193,247,128,246, 80,129, 40, 51,242,181, 20,155, 84,121, 13,200,170,
+ 7, 39, 1, 66,214, 53,216,248,209, 9,178,218,134,138, 15, 18, 47, 81, 35, 76,117,199,188, 69, 51,192, 94,152, 24, 45,212, 11,
+ 10,123, 47,187,106, 48,137,145,176, 10,200,220, 65,181,233,100,137, 12,122, 69,244,248, 84,117,146,194,214,255, 0, 64, 43,186,
+231,144, 38,164, 20,115,105, 85,208,156, 5, 4,155,159,101, 56,176, 43,206,145,172, 5,199,160,213, 32,248,229, 19, 3,194,214,
+231, 93,135, 23, 84,190,162,109,225,199,219, 76,198, 26, 81,175,227,245, 84,188, 53, 68, 13,160, 30, 32, 94,254,154,164, 26,216,
+ 54,117,117,107,219,211,236,162, 24, 28,120, 94,142,205,101,225,225, 76, 73, 46, 53, 17,107,248, 80, 72, 34,172,188,233, 23,213,
+198,149,231, 13,164, 41,224,198,198,149,108, 57, 80, 21,217,127,198, 52, 1,206,143,146, 47, 59, 91,149, 34,161,189,232, 5, 88,
+156,184, 78, 32,240,229,232,171,104, 80, 40, 0,120, 80, 21, 65,148,191,176,124,213, 46, 49, 85, 1,228,120, 82,210,129,115,106,
+121, 90,218, 48,216,206, 38,148, 45, 45,173,227, 79, 75,214,144,153, 26, 1, 28,168,170, 79,141, 56, 2,124, 40,138,131,198,150,
+158, 66, 96,114, 15, 27,209, 65,181, 32, 81,106,112, 28,107, 1,161,193,169, 25,155,236,211,173, 93,102,169,161,164, 12,177,241,
+ 20,195,110,116,109, 55,231, 77, 40, 42,166,138, 51,134,159,234,255, 0,245,171,169,250, 69,190, 79,203, 93, 86,126,240, 82, 73,
+127,221,255, 0,119, 31,236, 45, 55,209, 79,113,193, 63,187,143,246, 22,154,121, 86, 1, 23, 39,248,163,217,249,104, 86,183,170,
+139,147,109, 99,217, 66,249, 62, 90, 2, 52, 57,216,153, 57, 19,226,193, 50,201, 54, 49, 2,120,212,220,161, 62, 13,235,169, 45,
+ 97,202,188,254, 45,162, 85,203,120,149, 50, 82, 9,247,185, 22,109, 50, 76, 3, 99,172, 90,148,177,213,240,150, 60, 91,199,211,
+ 78,218,176,247, 44,108,157,174,104,188,207, 86, 73,119, 8,166, 51, 60,172,157, 56,209,134, 50,184,114, 64, 91,168,183,166,189,
+ 22,193, 88,109, 95,148,234,188, 27,252, 15, 45,119, 23,148,173, 78,113,163,241, 75,241, 55,151,227, 66, 57, 80, 12,175, 37,212,
+ 30,100,199,214, 17,125,174,152,109, 26,189,151, 54,175, 59, 81,186,249,108,127,186,188,247,223, 30, 95, 43,239,126,175, 90,218,
+180, 54,159,226,123,154,245,255, 0, 15, 69, 91,118,220, 56,199,184,210,108, 20,202, 56,227,108,209, 52,153, 43, 45,186,230, 88,
+217,148, 52,255, 0,106,220,192,225,232,163,219,164,155,118,152, 79,151, 78,190,124,133,119, 46,214,170, 85,137,105,106,250,244,
+242,231,208,218,114,225, 73,237,172,198, 70,223,149, 54, 86, 76,238,153, 36,157,210, 40,227, 42,242,168,242,166, 40,150, 77, 1,
+ 72, 26, 13,219, 81, 31,146,135,143,231, 54,220,214,234, 71,147,228,194,231,195,142,170,146,203,239, 25, 98,120,120, 0,199,138,
+134,208, 77, 99,210, 77,105,109, 99,135,194, 77,250,205, 61,107, 10, 98,103,198, 13,109,189,116, 56,165,142,104,250,144,176,116,
+187, 45,199,165, 88,163, 15,144,138,198,244,179,226, 27,100,178,174, 76,217, 30, 83, 8, 28,118, 89,213,196,138, 7, 80,199, 52,
+100,162,183,251, 69,149,126, 91, 81,213,103,233,193,247,188,121,111,136, 60,249, 11, 16,152,191, 84,228,183, 71, 80,139,222,227,
+ 23,240,201,225,244, 85,120, 87,243, 78,188,191, 2, 44,239,249, 99, 78,111,203,139,228,107,101,154, 44,120, 95, 35, 33,196,113,
+ 68,165,228,118, 54, 1, 71, 50,105,184,185, 88,217,176,245,241, 92, 73, 29,202,147, 98, 8,101,224, 85,131, 88,130, 61, 6,170,
+ 55, 69,200,126,222, 88, 22, 57, 79, 89, 34,139, 36,200,189,105,163,137,244,172,146, 50,167,199, 34, 14, 60, 60,120,208, 59, 74,
+ 76,212,243,120,153,113,200, 99, 86,234, 99,229,188, 82, 33,200, 12,205,170,103,105, 62,217,247, 70,158, 30,145,194,176,241,174,
+203, 94,117, 78, 35,192,223,170,253, 74,210, 52,106,103,196,210, 36,122,206,155,218,194,244, 78,137,191, 23, 63, 69, 98, 18, 61,
+214, 41,119, 4,192, 25, 51,100,180,121, 86,156,137,226,116, 36,234, 69,125,101,224,145,188, 34,100, 35,217,107,212,137,132,203,
+ 47, 95,104,143, 53, 54,232, 78, 20,153, 73, 34,207,172,178,100,169,151, 66, 77,251,198, 34, 43,245, 52,142, 62,219,213,244, 63,
+171,143,135,237,240, 51,235,255, 0, 79, 15, 31,187,241, 53,197, 20,178,168, 36,250, 69,232,157, 24,137,181,137,245, 19, 89, 24,
+225,204,220, 55, 53,234, 71,148,184, 50,238,114,147,168, 77, 16, 56,227, 4, 5,189,244,145, 27, 74, 60,120, 19, 76,130, 57,226,
+ 92, 21,221,147, 49,176,162, 25,177,196,145,137,217,196,131, 36,174, 63, 83,163,251,207,224, 15,221,147,195,229,181, 79, 71,135,
+213,172,112, 75, 94,127,145,125,103,252,186, 76, 75,122,114,251, 53, 54, 24,167, 19, 42, 4,200,198, 42,241, 72, 46,142, 57, 17,
+202,135,153,147,137,131, 24,151, 38, 69,137, 11, 4, 12,124, 89,141,130,128, 56,147, 89,180,139,114,139,179, 48,224,129, 37,142,
+101, 17, 12,152,153, 95,172, 33, 50,254,244, 21,140,172,132,233,230, 20,222,215,181, 69,139, 2,108,152, 49, 58,226,105, 96, 77,
+208, 60, 30,236,208,132,132,197,239,148, 15, 35, 73,211,215,200,189,173,225,194,213, 86, 42,203,110,218, 43, 53,227,161, 30,107,
+ 66, 74,186,186,167,225, 44,214,193,149,139,147, 52,176,227,200,174,248,231, 76,225,126,203, 91,225, 39,211, 82,136,213,194,213,
+131,147, 11, 39, 18, 39, 16,164,137,139, 38,229, 59,101,135, 19,203,120,134,190,139, 20,141,196,134, 61, 86,185, 94,124, 47,194,
+141, 31, 89,113,176, 83,120, 25,147,224,172, 57, 61, 49, 28,115, 44,157, 83, 40, 16,117, 22, 54,121, 47,210,225, 25,115,127,210,
+179, 81,225,175, 21,111,179, 82, 44,214,225,106,235, 19, 51,167, 19, 93, 59,197,212, 24,253, 65,214, 11,172,198, 8,213,164,155,
+ 6,211,206,215, 28,233,154, 86,246,185,172,166,110, 28,146,229,180,225, 51,162,146,109,169, 99, 73,212, 73, 44,171, 42,223, 82,
+191, 76,136,250,154,124, 46, 46,126, 30, 53, 55,183,227,156,227,102,161, 89, 17, 46, 58, 82,168,153, 21,201, 79,120,195, 22, 95,
+190,150, 60,197,200,191,143, 58,143, 18, 85,238, 86,158, 28,141, 87, 43,118,237,117,142, 60,255, 0, 2,255, 0, 66,240, 54,166,
+216, 2, 45, 88,120, 34,207,131, 11, 38, 88, 14, 67, 73,129, 28, 89,125,118, 19,192, 36,120, 28,180,145, 77, 22, 65, 97,212,120,
+238, 24,163, 16,126,106, 73,227,203,155, 22, 13,210, 71,200,145,179,132,249, 49,227,105,200,100, 11, 33, 83,142,145,190, 49, 45,
+ 20,162, 53, 93, 36,169, 28, 79,141,111,208,215,245,115,142, 26,204, 79, 3, 63,228, 56,253, 26,196,241,210, 38, 56,155,110,172,
+110,239, 26, 58,180,145,216, 72,160,130, 84,145,168,106, 30, 23, 21,207,225, 88,252,156, 92,216,228,220,228,199,131, 34, 57,178,
+ 14, 36,146,146, 38,144, 24, 72, 65,144,170,209,144, 25,129,189,194, 29, 86,190,154,118, 46, 38,100,239,135, 12,166,119,193,108,
+217, 73, 1, 38,133, 4, 62, 89,200, 30,251,180,157, 35, 47, 45,118,227,192,112,181,101,225, 81, 61,220,167,135,132,149,102,115,
+ 29,156,227,143,140, 26,209,241, 83,255, 0,180,172,118, 46, 30, 70, 60,120,114,202,185,160, 52, 57,145,229,152,218,102,151, 66,
+176, 16,129,196,144,218, 71,185,110, 53, 43,186,206,225,143,183,225,238, 91, 95, 89,230,195,117,102,132,106, 46,241,200,189, 51,
+173, 71, 22, 96, 72, 60,105,233, 46,234,213, 91,245, 54,167,148,173, 7,172,251,109,103, 95,210,147,133,198, 30,166,165,207, 10,
+142,109,168,122,235, 7,180,109,157,195,152,153,219,126,100,217, 9,228, 49, 36,135, 22, 98,238,189, 73,231, 99, 42, 62,171,251,
+218,109,167,213, 81, 48, 63,204,217,217,248,135, 45,114, 34,131,114,150, 57, 39,191, 81, 4, 73,137,168, 58,248,105,234, 91,229,
+173,255, 0,140,190,175,247, 43,244,255, 0,231,238, 48,183, 79,233,255, 0,110,223, 86,159, 30, 14,126, 58, 30,146,124,104, 51,
+100,193,137, 4,153, 25, 50, 44, 80,196, 53, 73, 35, 27, 0, 61,117,231, 89,223,230,124, 44,188,161,142, 50,101,135,109,146, 81,
+ 5,140,141,213, 76,205, 66, 63, 78,174,157,199,179,213, 86,219,196, 18, 73,218,249,123, 72, 76,137,178,240, 34,131,168,196, 73,
+251,201, 90,197,138, 55,246,131,157,249,138,127,142,147,164,221, 53,102,150,156,147,231,246,162,173,203,106,241, 70,157, 83,106,
+121,181,203,236,102,186, 25, 98,202,137,103,132,135,138, 64, 26, 55, 30, 32,248,209,154,228,124,130,188,251, 43,111,201, 57, 25,
+130, 63, 55,251,188,220, 88, 49,202,203, 63, 8, 25, 85,101,210,117,113, 4, 30, 45, 82,122, 89,120,240, 73, 4,254,105,118,152,
+183,137, 18,112,134, 83, 32,196,208, 10, 89,150,242, 24,181,158, 54,168,240, 39, 13, 95,143, 40,248,252,202,183, 22, 83, 52,225,
+206,116,227, 29, 56,104,109,175,195,228, 52, 12,124,172,124,184, 87, 35, 26, 65, 44, 46, 24, 43,175, 34, 84,149, 63, 49, 21,137,
+135, 81,201, 67,184,121,239,242,224,155, 47,201, 91,175,174,214, 78,142,189, 31,189,211,241,244,245, 85,207,107,179,227,108, 59,
+118,222,240,206,153,153, 11,148,208,245, 99,107, 41, 89,101,117,235, 53,172,183,225,207,157, 75,224,237,172,204,185, 92,180,141,
+103,226,163, 83, 84,220,247, 94, 29,123, 84, 62,122,207,211, 31, 7, 58,117, 52, 66,215,227,202,158,214,211,195,209,106,243,121,
+ 19,112,242, 80,249, 17,159,247,167,151,202,251,228, 72, 39,182,173, 13,163,226,247,117,107,248, 52, 85,158,102, 8,193,251,170,
+ 28,145,153, 46,222,240,201, 38, 64,133,230,121, 91, 41,149, 44,210,116,206,191, 78,159, 0,106,189,186, 77, 46,253, 92,233, 26,
+253, 63, 30,124,140,173,211,105,190,205, 20,107, 58,125, 95, 14, 92,205,192,225, 25, 63,233,202,137,183,179, 24,216,158, 62,247,
+228,172,247,102,203, 36,189,171,139, 36,206,242, 72,122,224,188,164,179,144, 38,144, 13, 68,250,171, 67,129,194, 38,245,181,114,
+181,123,111,106,241,237,109,124,142,212,183,125, 43,120,142,228,156,121,146,143,133, 33,174,249,107,171, 37, 35, 74,161, 94, 48,
+ 57, 94,230,136, 46, 79,170,153, 63,241,163, 95,109, 20, 3,110, 28,232, 82, 4,214,235, 55,162,255, 0,146,159, 26,234, 54,246,
+ 19, 76,146,230, 86,246,212,136,150,220,124,104, 9, 17,138,150,130,194,163, 68, 42, 90,142, 66,180,145, 7, 14, 2,254, 52,151,
+ 62,154, 82, 69,117,175,202,183, 84,103,137,220, 60, 77, 61, 28, 47, 42, 25, 90,224, 42,179, 13, 52,228,146, 28,159, 26, 34,159,
+ 93, 71, 91, 10,112,110, 53,121, 26, 77,115, 36,134, 52, 64,104, 43,196,115,167,105, 97,198,178,210, 47,116,135, 86, 20,237, 99,
+194,163,106, 52,224,198,178,234, 84, 26,247,231, 73,238,138,104, 52,140,125, 20,131, 77, 33,220, 45,242,126, 90,234,109,206,159,
+234,254, 90,234, 71,222, 72, 69, 51,158, 9,253,220,127,176,180,219,211,156,124, 31,221,199, 99,253, 69,166,129,207,209, 89, 41,
+ 27, 32,251,227,143,133, 4,241, 21, 45,225,234, 27,234,183,133,185,254, 90,104,197,254,125,254, 74, 2, 45,141, 45,184, 90,245,
+ 39,202,139,124, 95, 45,171,134, 47,243,190,143,207, 64, 70, 3,215, 92, 42, 79,150, 32,252,127, 71,231,174,242,195,244,254,138,
+ 2, 57, 96, 71,164,210, 11,243,181, 72, 24,188,126, 63,163,243,210,140,113,200,183,209, 64, 3,228, 20,156,109,206,143,229,255,
+ 0,157,244,126,122,239, 44,111,241,125, 31,158,128, 0,227,198,157, 97,107,209,188,189,190,223,209, 75,229,255, 0,157,244, 84,
+ 96, 18, 7, 0,133,181,185,241,167,251,228,139,176,191,141,133, 26, 60,114, 20,141, 92,205,249,126,122,119,151,254,119, 31,101,
+100, 0,233,241,212,206,111,242,114,165, 17, 90,254,241,227,235,163,244,180,143,138,254,209, 74, 34, 35,155, 95,209,194,168, 35,
+ 24,215, 87, 30, 86,228, 77, 41, 68, 0, 88, 15,154,140, 34, 3, 85,219,159,171,243,210,244, 1,225,171,215,202,128, 6,145,123,
+ 88, 87, 48, 94, 70,212,102,137,124, 92, 95,217,249,233,157, 52,225,239,106,244,112,227, 64, 71, 47,102, 60, 47, 77,214, 91,128,
+ 31, 61, 28,192, 9, 39, 95,209, 77, 16, 0, 62, 47,163,243,208, 16,242,176,225,206,129,241,114,148, 60, 50,124,113,220,128, 71,
+160,233, 35,135,170,158, 20, 37,145, 0, 10,160, 40, 0, 88, 0, 60, 0,169, 99, 28,158, 77,244,126,122, 79, 45,196,251,223, 69,
+ 89,113, 4,133, 51, 26,145,238, 65,166, 49, 36,241,169,126, 90,255, 0,107,232,252,244,198,198,185, 62,247,209,249,234, 20,142,
+188,233,147, 18, 24, 88,112,183,242,212,193,141,111,181,244,126,122, 81, 0, 13, 98,220,199,162,128,131, 28,186, 65, 21,204,250,
+184,250,106,123, 97,196,120,147,244, 84,102,195, 26,236,175,195,217,249,232, 0,128, 72,249,105,207,197, 26,222, 0,212,159, 41,
+ 96, 61,255, 0, 31, 71,231,164,147, 23,220,111,126,215, 30,143,207, 66,149,177,113,113,122, 59,143,116,159, 93, 26, 60, 45, 50,
+ 15,127,194,252,189, 94,218, 43, 97,234, 83,102,176,191,163,243,209,132, 70,198,107, 49, 7,145, 31,201, 82,137, 54,165,135, 11,
+ 72,185,126, 62,207,207, 69,242,220,126, 59,252,159,158,163, 41, 22, 66,124, 42,179,114,218,176, 55, 46,147,102, 68, 93,225,191,
+ 74, 69,119,141,151, 85,131, 0,209,178,181,143,141, 94, 62, 63,243,173,126, 28,191, 61, 71,147, 18,246, 26,252,125, 31,158,173,
+ 91, 78, 83,105,245, 68,178, 86, 81,100,154,232,200,184,248,208, 98,226,166, 22, 36, 98, 40, 99, 26, 99, 69,228, 5, 74,128,116,
+ 96, 98,220,108,121, 10,120,197,183,219,250, 63, 61, 35,193,112, 84, 63, 63, 87,231,171, 60,217, 33, 45, 22,144, 52,102,192,120,
+ 88,131,235,167, 28,172,114,164, 18, 69,252,106, 47,147, 55, 54,127,163,243,215,121, 54,253, 63,163,243,208, 10,142, 30,100, 23,
+213, 96,110,106,106,159,174,129,139,132, 67,235,213,203,213,249,234,103,151,227,125, 95, 69, 10, 87, 20,253,243, 95,192,255, 0,
+ 45, 29, 71, 42, 51, 99,234, 98,197,185,250,191, 61, 62, 60,110, 63, 23,209, 66, 14,141,120, 81,199, 5,165, 72, 0, 28, 91,128,
+231, 72, 89, 47,110, 36, 15, 80,250,235, 73,165,196,144,249, 29,110, 21,192,218,148, 21,245,252,195,235,174,178,159, 79,204, 62,
+186,189,235,169,143,175,160,224,194,156, 56,242,166,133, 30,191,152,125,116, 64, 84,120, 31,152,125,117,123,235,213, 22, 45,208,
+ 75, 53, 40, 94, 60,169, 67, 1,224,126, 97,245,211,132,163,244, 79,204, 62,186,189,245,234, 29, 95, 64,137, 97, 71, 15,194,213,
+ 20, 72,191,162,223, 48,250,233,226,116, 31,101,190, 97,245,212,118,175, 82,170,248, 7,226,124, 41, 66,154, 15,154, 79,209,111,
+152,125,117,222,109,127, 69,190, 97,245,214,123,151, 81, 85,101,197, 7,181,233, 52,208,134, 90, 15,178,223, 48,250,235,142, 92,
+127,160,223, 48,250,234,119, 46,165,178,111,128,109, 63,201,249,107,168, 94, 97,116,234,179,124, 58,188, 63, 75, 79,166,186,175,
+114,234, 72,127, 97, 86,224,123,151,230, 99,143,246, 22,153,196, 30, 20, 83, 19,176,141,129, 91,116,227,230,234, 15,192,190, 4,
+138, 78,139,255, 0, 51,245,211,253,106,134,129,243,227, 93,113,199,249, 40,157, 23,191, 52,253,116,250,233,122, 15,127,137, 57,
+113,247,215,253,106, 3,204, 54, 21,203,203,222,251,109,166,202,103,133, 31,184,100, 16,184,213,239,195,184,116,149,181, 19,207,
+ 68,154, 87,244, 64,225,206,141,187,247,126,255, 0,129,157,188,109,208,152,204,219, 90,230,101,179, 58, 93, 70, 41,139, 24,225,
+179,123, 31, 37,175,233,233,154,219,226,195,177,245,160,242, 71, 7,171,254, 43,202,116, 95, 31, 95,241, 71,157,233,104,107,255,
+ 0, 22,221, 91,125,175,139,141, 68,131,106,218,113,247,141,227, 59, 39, 54, 12,140,236,168, 34, 25,120,243,203,143,104,112,208,
+ 73,161, 90, 49, 98, 35, 37,158,236,252,254, 74, 3, 58,189,199,189,226,110, 99,104,200,157, 50,132, 59,132,216,143,152, 98, 84,
+234,198,187, 81,220,148, 89, 61,208,201, 37,129,183,133, 77,147,124,221, 37,237, 30,223,220, 99,149, 33,206,222, 62,236,142,108,
+128,128,172,103, 51,167,213,116, 70,247,111,239, 16,160,248,154,158,216,221,146, 54,168, 21,206,211,247, 64,156,156, 98,210,226,
+156,127, 49,102, 39, 65,103,209,212,182,171,248,218,245, 59, 34, 13,141,182, 53, 92,143, 35,247, 9,138, 48,133,229,199, 24,157,
+ 19,167,163,164,234,233,133,248,116, 91,213,106,128,243,204, 93,255, 0,126,194,216,216,226,230,170,182, 22, 54,247,186, 73, 44,
+177,137, 60,203,226,110, 18, 70,144, 13,109,238,165,141,189,211,113,117,183,174,239, 19,184,183,169,251,154, 44,105, 37, 85,193,
+147,115,155,110, 56,157, 33,168, 34,109,139,184,134, 50,124, 90,132,156, 61,149,116,240,118,115, 97,237,247, 27, 64,193, 18,185,
+219, 63,123,138, 33,235,117, 15, 83,203,217,130,234,234,124, 90,126,215, 62, 53, 56, 67,179,156,209,163,200, 12,239, 50,246,210,
+248,253,111, 55,208, 26,254,214,174,175,151,231,246,180,127, 54,128,206,108, 24,155,134,219,221, 71,105,159,113,124,184, 48,182,
+ 61,189, 52,186,216, 59,172,153, 16, 52,214, 44,214,102, 49,106, 38,228,241,181,248, 10,164,126,246,238, 20,203,124, 13, 81, 25,
+ 21,219,106, 13,160, 95,239, 25, 51,164,130, 3,110, 28, 60,178, 43,219,249,215,228, 43,208, 94, 13,184,238,209,245, 14, 31,223,
+ 61, 6,233, 93,224, 25, 94, 95, 87,189,167,222,234,116,245,243,240,189, 68, 56,253,187,230, 14,163,182,249,143, 58,186,175, 38,
+ 54,191, 63,211, 58, 47,239, 95,204,116,239,111,181,167,213, 64, 99, 37,239, 61,242, 24,119,201,210, 85,153, 49,246,252,188,236,
+ 41, 90, 20, 72,132,152,217, 13,142, 4, 74, 28,200,209,248, 30,168, 4,176, 54,225, 71,159,113,222,242, 55, 28, 28, 89,183, 47,
+250, 62,228, 56, 45, 34, 70,169,213,132,237,199, 44, 43,170,155, 16, 11,178,219,216,121,138,191, 76,110,200, 86,203,208,219, 54,
+162,179,156,239,222,225,147,163, 80,243, 61,111,123,225,213,110,165,248, 95,157, 77,201,199,237,219, 63,156, 59,109,188,226,117,
+ 58,178, 99,127,215,232, 78,158,173, 77,252,125, 26,116,253,171, 90,128,204,239,123,158,247,133,221,243,195,129,154, 99,139, 39,
+ 27,106,199, 68,100, 14,144,121,172,217,224,105, 66,147, 98,254,237,129, 60,203, 0,121, 1, 87, 24,187,198,247, 55,104,231,230,
+172,152,227,115,196,155, 51, 14, 12,169,202,195, 12,175,143,147, 38, 44,114,123,196, 32,215,160,120,233,213,234,169,155,166, 55,
+109,156,134, 27,201,219,124,209,199, 33,188,212,184,194, 95, 45,172, 95,248,141,171,167,174,222,173, 94,186,152,177,237, 43,178,
+ 21, 97,130,219, 15, 68,139,153, 32,242,157, 15,110,174,158,143,162,160, 48, 25, 29,233,221, 11, 17,199,196, 15, 62, 70, 28,121,
+115,228, 44,209,226,192,224,227,201, 20,107, 14,107, 77, 60, 81, 42,175, 80,234,104, 11,115, 82, 60,106,243, 11,184, 55,236,158,
+239,125,191,166, 70,214, 51,103,192, 44,254, 93, 80, 8,113, 6, 72,100,188,190, 97,229, 47,204,116,244,232, 62,171,213,175,151,
+236, 49,139,183,245, 14,207,229,210, 87,251,187, 84,184,157, 62,182,165, 18,116,125,235, 51,235,211,170,220,117, 90,252,106,198,
+ 56,123,112,111,238,241,157,191,252,193,162,210, 0,240, 28,205, 1, 87,226, 23,234, 91, 70,159,146,222, 22,160, 48,125,220,251,
+154,247,107, 65, 6,227, 36, 80,176,216,122,112,129,238,163, 75,185,201, 19, 53,131, 11,252, 30,247,233, 3, 99,192, 82,227,239,
+219,196,171, 20,226, 76, 87,220,215,109,222, 18, 44,188,157, 49, 43, 75,139,185,195,131, 14,162, 74,198,186,197,184,114, 45,111,
+ 10,221,110, 49,118,207,222,120,255, 0,122,157,187,239,107, 71,229, 60,203, 99,249,155,117,151,165,210,234, 29,118,235,233,211,
+111,183,107,113,161,201, 23,105,116, 28, 72,118,190,129,135, 43,169,169,241,180,116, 58,195,206,234,185,182,142,189,186,190, 26,
+254, 46, 52, 6,120,119, 14,229, 15, 99,239,123,199, 80,182,227,182, 12,144,131, 34, 21,142, 88,222, 21,212,177,228, 36,100,196,
+ 88, 95,137,140,233, 34,212, 4,222,123,134,108,217, 54, 79, 62,145, 75,247,182, 70, 23,222, 70, 4,184,134, 28, 4,220, 21, 4,
+103,220,185,119, 34,231,236,143, 79, 26,212,227, 65,219, 75,177, 74,184,231,110,251,128, 44,131, 35, 75,227,156, 77, 55, 61, 94,
+169,212, 99,231,125, 90,190, 90,102,227, 7,106,182, 46, 88,221, 14,219,229,188,200,243,189,121, 49,194,121,174,154,219,172, 93,
+173,213,233,105,248,189,237, 54,240,160, 60,240,111,155,182,118,231,182,110,121, 82, 13, 25,248,157,187, 59,224, 50, 30,146, 62,
+ 86,123,198,242, 70, 47,192,240, 44, 15,172,122, 5, 79,151,186,187,129, 49, 34,204,143, 46, 41,164,220,242, 30, 12,125,186, 36,
+139,204,227,170,231,249, 32, 97,235, 52,113,191,185,238,147, 43, 91,168, 71,135, 10,217,101, 67,218,222,119, 19,206,157,179,207,
+232,139,200,117,159, 27,173,211,234,175, 71,161,173,181,105,235,105,209,167,237, 90,220,106, 51,226,246, 65,109,211,168,219, 78,
+183, 35,239,139,203,139,123,245, 44, 60,207,189,238,158,175,233,125,191, 93, 80, 68,131,126,220, 87,178,103,222,115,158, 44, 76,
+248, 83, 32, 52,140,171, 58,169,134,103,129, 29,147, 21,221, 11,144,160,149, 87,176,110, 21, 66,187,182,249,184,201,179, 9,242,
+164,198,147, 31,184,100,192,152, 50, 68,178, 73, 26,226, 77, 50,172,226, 7,104,174, 56,169, 10,109,200,243, 21,184,242,251, 9,
+216,200,213,131,247, 15, 68,131,105, 32,242,125, 11,113,227,171,167,162,223, 37, 65,139, 31,179, 23, 21, 68, 71,104,242,131, 38,
+ 32,182,147, 16,199,230,244,142,143, 29, 86,235,105,182,159,181,110, 84, 5, 94,239,188,111, 56,253,203, 22, 12, 57, 73, 6,223,
+ 43, 65,140,142,145,199, 58,172,211, 9, 9, 76,161,171,173, 28,141,238,152,184,104, 63,106,178,253,181,220,219,220, 56,189,187,
+142,115, 27, 50, 57, 19,110,139, 44, 52,106,116,140,222,160,253,252,210, 63, 81,164,247,125,205, 0,252, 39, 95, 58,244, 89,177,
+251,107,239,184, 91, 37,182,239,191, 64, 2, 14,164,152,254,110,196, 54,157, 1,155,169,203, 85,173,225,127, 93, 86, 99, 99,126,
+ 31,117,227,108,102,216,250,247, 81, 23, 78, 76, 45, 90,186,199, 70,144,173,207,173,123, 91,237, 95,198,128,205,100,238,125,193,
+151,143,178,238,178,110, 93, 53,151,123,203,198, 76,120,162, 10,162, 60, 85,220, 35, 85,118,213,119,212, 32,226, 15, 14, 71,152,
+167,193,221,251,222, 78, 38, 59, 9,162,138, 89,241,251,113,204,189, 48, 66, 62,237, 43,197,146,218, 73,183, 32, 10,143, 10,218,
+ 79, 7,109,121, 24,124,193,219,124,135,154, 62, 91,168,248,221, 31, 57,213,123,244,245, 54,158,183, 87, 95, 47,123, 85,252,106,
+149,246,206,195,202,193,120,241,114, 54,168, 48, 99,159, 14,124,150,196,159, 13, 81,140, 83, 25,113,163,156,130, 84,163,184,101,
+ 10,121,241, 11, 64, 89,118,222,233, 62,229,183, 48,205,149,100,202,135, 39, 51, 23,168,160, 47, 89, 49, 50,100,198, 19, 4, 30,
+144,162,246,225,122,197,205,222, 59,254, 46, 14,102,119, 94, 57,153,241, 55,153,224,143,164, 0,129,246,204,181,198,136,181,141,
+216, 58,191,189,127, 27, 90,183, 88, 24, 59, 7, 95, 6,109,166, 76, 59,199,139, 52, 88, 49,226,205, 6,147,140,210,196,102,104,
+196,109,239, 40,145, 18,228,112, 7,214,106,179,107,218,251, 43, 6, 29,194, 24,242, 54,220,146, 70, 67,238,114,205, 62, 36,143,
+210,146,121, 38,153,114, 72, 35,247,105, 35,149,247,135, 11, 0,121, 84, 97, 21,153, 59,239,114, 97,247, 4, 59, 80,111, 53, 6,
+ 52,152, 17,229,206, 87, 30, 24,152,103, 75, 34,187, 55, 82,101,148, 21, 65,104,150, 53,107,149, 58,175,122,130,253,201,220,204,
+249, 88,163, 38, 38,201,149,213,241, 98,140, 99,145, 44, 7, 36,199,171,108,152,201,210,149,186, 66,218, 38, 58,181,223,194,182,
+249,120,253,190,119,172, 70,207, 59,127,223, 1,109,133,214,147, 31,204,233, 37,173,210, 14,218,249,234,181,189,126,186,174,147,
+ 19,176,204,121,131, 86,205,161,229, 67,184,126,247, 16, 89,245,182,158,169,215,193,186,151,181,254,213,252,111, 68, 82,167, 55,
+112,147,115,237,125,158,108,140,142,164,121,249,184,120,249,178,162,182, 62,168,155, 40, 68,241,186,222,233,171, 72, 71, 0,219,
+137, 3,133, 70,220,118,157,141, 95, 3, 27, 1,229,149, 35,222,151, 15, 34, 54,121, 85, 98, 15, 19,206,248,145,219, 64, 49,130,
+193,133,175, 99,194,252, 44, 53,239,143,177, 29,154,211,156, 15,184, 76, 42, 5,228,199, 24,125, 31,179,111,123,167,162,246,183,
+133, 46, 6, 55,109, 38, 14, 34,109,237,183, 28, 17, 61,176,140, 50, 99,152,188,207,189,252, 18,173,110,175,197,203,222,231, 64,
+121,190,233,230,113,247, 29,211, 34, 52,120,224,131,120, 24,139,184,166, 67,235,141, 14,223, 14,156, 95, 47,193, 76,110,205, 98,
+218,184,106,189,171, 95, 46,253, 62,199,216, 88,219,164, 48, 73,149,147, 22,212, 39, 67,160,200,130, 72,241,132,129,167,179, 43,
+ 4,212, 56,155,213,214, 76, 29,188, 98,159,205, 29,191,165,230, 87,205,117, 31, 31, 79,156,208,154, 58,186,154,221,109, 26, 45,
+127,122,214,245, 84, 13,179, 31,177,188,166,227,247, 27,108,167, 7,167,255, 0,205,142, 28,152,125, 46,150,151,255, 0,170,233,
+ 54,157, 26,117,252,124, 45,127, 93, 1, 87,186,110, 82,100,239,139, 46,137,241, 34, 59, 30,230,221, 25,193,140,235,142, 92, 75,
+ 62,155,145,112, 24,216,212, 45,211, 43,113,198,216,251, 43, 39, 31, 33,209,186,144,117,226, 2,230, 98, 54,249,229,208,231,153,
+185, 75, 91,210,111,204, 10,213,111,248,189,184,209,192, 59,153,182,238,152,102, 56,223,120, 75,142, 5,192,247,244,117,219,209,
+241, 91,195,157, 31,115,199,218,124,190, 63,222,167, 11,203,245,163,242,190,106, 72, 52,117,255, 0,177,233,117, 90,218,255, 0,
+ 70,220,125, 20, 6,127,180,183,189,215, 54,118,199,220,242, 19, 48, 75,183, 96,238,105, 52,113,136,196,109,153,214, 15, 7,186,
+ 72, 42, 58, 64,169, 60,109,233,170, 44,142,243,222,163,192,201,201, 70,139,171, 22,223,189,101,173,211,135, 83, 3, 61,113, 32,
+225,126, 93, 51,199,210,107,109,179,226,108, 97,114, 62,225,108, 13, 38, 75,228,249, 41,113,200,234, 17,253,167, 73,185,219,211,
+ 85, 25,187, 87,102,102,195,187,225,140,157,179, 26,124,136,114, 19,115,200,198,200,195, 76,136,227,102, 81,146,210, 62,162, 86,
+207,167, 94,161,109, 86,191, 26,164, 43, 39,222,119,181,206,200,237,255, 0, 59, 24,104,243,102,129,183, 33, 18,251,241, 38,218,
+ 55, 17, 24, 75,233, 7, 91,216,144,111,164,122,120,212, 93,167,184,247, 88, 32,237,124, 88,166,235, 64,248,187, 52, 89,145,152,
+212,129,231, 98, 33,154,121,164,113, 35, 72,218,117, 39, 76, 17,192,234,231, 90,197,198,236,191,186,136,152,237, 31,117,249,146,
+220,101,197,242,254,106,197,143, 29, 90, 58,150,191, 14,118,225,202,136,216,253,145,230, 49, 89,142,207,230, 58, 56,195, 6,242,
+ 98,106,232,106, 30, 83,162, 53,124, 26,173,210,211,195,244,104, 12, 28, 61,201,221, 27, 98,230,227, 97,202,217,207, 6, 70,239,
+148,204,254, 93, 22,216,217,222, 93, 99,149,242,166,139, 68, 60, 77,244, 93,133,212, 14, 3,142,199,189,251,131, 59,182,177,113,
+183, 24, 52,156, 86,243, 48,204,133,117, 49,156,227, 73, 46, 37,189,178,196, 19,250,194,165,100, 99,246, 33,201,255, 0, 22,118,
+111, 52,185, 76, 91,169, 38, 32,147,205,251,129,245, 93,174,101,248, 47,126, 63, 15,170,164,247, 38,213,131,159, 6, 31,222,217,
+177,226,225, 99,229, 67, 51, 35,203, 2, 71, 52,168,225,160,141,222, 83,227, 32, 28, 20,141, 92,168, 12,172, 61,193,220,112,231,
+ 71,230,167,142, 69, 25,207,180,203,132,177, 0, 67, 69,183, 28,211,149,172,123,220,100, 91,219,225,210, 71,182,133,143,222, 27,
+254, 78, 22, 63, 74, 88, 99,200,200,199,237,182, 18, 24,131, 5,147,119,149,226,201,109, 58,133,197,128,210, 47,194,182,107,143,
+176,125,246,205,171, 3,239,206,157,159,247,144,121,174,157,135, 49,171,169,167, 77,190, 74,143,182, 67,216,171, 19, 13,164,236,
+230, 62,166, 49,111, 44,248,132,117, 76,141,228,239,161,190, 46,173,250, 95,206,248,104, 4,223,183, 92,253,166,125,139, 10, 57,
+ 86, 67,152,243,197,153, 43,160, 5,250, 56, 83,228, 6, 0,112, 91,201, 16, 38,222,202,201,195,221,251,246,157,159,112,158,104,
+206, 46, 86, 22, 12,178,164, 40,146, 33,201,200,199,105,229,135, 32, 43,117,161,119,247,122, 36, 46,143, 77,110,183,184, 54, 39,
+130, 47,243, 35, 96,140,126,170,152,124,251,194, 19,172, 21,180,232,235, 53,181,105,213,242, 94,161,195,143,217,191,120, 96,182,
+ 59,109, 95,120, 8, 99, 27,111, 78, 76, 94,175, 64,161,232,249,112,173,171, 71, 78,250, 52,253,155,219,133,101,185,124, 10,140,
+142, 7,117,247, 84,251, 96,121,138, 65, 62, 76,219, 48,198,158,101,199, 98, 23,116,155,165, 45,161,197,158, 79,221,168,177,140,
+200, 67, 27,241,229, 90,142,229,204,220,240,215,104,219, 49,179, 22, 25, 51,122,235,149,154,209,169, 44, 49,241, 36,156,133, 78,
+ 10,189, 70, 75,155,114, 23,183,166,164,237,208,118, 98,227, 48,218,206,213,229,142, 76, 37,188,187,227, 24,252,217,117, 56,255,
+ 0, 3, 91,171,175, 79, 79,198,246,211, 83,247,216,118, 54,195, 65,220,103, 11,201,245, 84,199,231,222, 17, 31, 84, 6, 43,167,
+172,116,234,211,171,228,191,133, 62, 0,243,221,147,187, 55,232,163,237,220, 60,120,204,184,145, 96,236,105,151, 36,134, 0,143,
+231,147, 68,178, 75, 36,243, 36,197,192, 23,140, 70,141,118, 6,252,234,186, 14,228,222,118, 8, 55, 25, 49,179, 60,206, 71,159,
+220,178,178, 83,160,132,186,193,158, 49, 3, 79, 36,142,186, 98,211,238,133,143,223, 4,128, 61,209, 91,231,199,237, 54,204,219,
+ 25, 14,215,230,196, 49,141,158,210, 98,137, 60,185, 7,165,229, 70,171,232,181,244,104,225,107,218,129,153,141,217, 5,129,220,
+155,103,212, 27, 38,221,121,113, 62, 45,127,227, 46, 29,184,158,167,241,127,157,241,113,171,240, 4, 9,251,191,113,109,214,109,
+184,148, 16, 29,215, 47, 3,130,217,186, 17,109, 35, 57, 44,111,241,117,143, 63, 71, 10,205,109,219,215,112, 99,141,185,240, 51,
+217,222, 94,222,216,136,197,115, 25,145,140,141, 48,156,227,121,150, 88,223, 32,172,108, 70,175,139,145,228, 43,119,229,187, 71,
+239,114, 75,109, 95,124,158,119,147, 23,205,112,132,248,106,215,252, 11,255, 0, 83,213, 64,205,198,236,102,143, 25,115,219,102,
+208,113, 99, 24, 93, 89, 49, 7,248, 77, 75,210,232, 22,111,225,106,211,167, 79,187,123, 90,167,192, 22, 93,181,191, 46,231,179,
+226,228,205, 50,100,100,178, 94,102, 84, 49, 31,137,144, 23,136,146, 80,251,132, 31, 11,131,110, 21,111,231, 99,244, 85, 70,217,
+143,177,220,253,204,216, 55,232,195,127, 41, 36, 31,244,254,255, 0,151,254, 19,127, 15,227,209,225,206,222, 53, 99,229,207,233,
+ 39,254,145, 63,214,164,120, 9, 13,231, 99,244, 87,121,216,189, 20, 15, 46,127, 73, 63,244,137,254,181,119,151, 63,164,159,250,
+ 68,255, 0, 90,144, 36,145,231, 99,253, 26,239, 57, 31,162,129,208, 63,164,159,174,159,235, 83,132, 31,206, 79,215, 79,174,145,
+224, 9, 94, 97, 58,122,173,253,157,254, 78,166,154,234, 30,129,167,167,113,126,143, 59,141, 63,197,253, 46, 85,212, 7,255,217,
+};
+
+#endif
diff --git a/source/blender/src/winlay.h b/source/blender/src/winlay.h
new file mode 100644
index 00000000000..4cf19bc23cd
--- /dev/null
+++ b/source/blender/src/winlay.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 *****
+ */
+/* Abstract window operations */
+
+typedef struct _Window Window;
+typedef void (*WindowHandlerFP) (Window *win, void *user_data, short evt, short val, char ascii);
+
+Window* window_open (char *title, int x, int y, int width, int height, int start_maximized);
+void window_set_handler (Window *win, WindowHandlerFP handler, void *user_data);
+void window_destroy (Window *win);
+
+void window_set_timer (Window *win, int delay_ms, int event);
+
+void window_make_active (Window *win);
+void window_swap_buffers (Window *win);
+
+void window_raise (Window *win);
+void window_lower (Window *win);
+
+short window_get_qual (Window *win);
+short window_get_mbut (Window *win);
+void window_get_mouse (Window *win, short *mval);
+
+void window_get_position (Window *win, int *posx_r, int *poxy_r);
+
+void window_get_size (Window *win, int *width_r, int *height_r);
+void window_set_size (Window *win, int width, int height);
+
+char* window_get_title (Window *win);
+void window_set_title (Window *win, char *title);
+
+void window_set_cursor (Window *win, int cursor);
+void window_set_custom_cursor (Window *win, unsigned char mask[16][2], unsigned char bitmap[16][2]);
+
+void window_warp_pointer (Window *win, int x, int y);
+
+void window_queue_redraw (Window *win);
+
+ /* Global windowing operations */
+
+Window* winlay_get_active_window(void);
+
+void winlay_process_events (int wait_for_event);
+
+void winlay_get_screensize (int *width_r, int *height_r);
diff --git a/source/blender/src/writeavicodec.c b/source/blender/src/writeavicodec.c
new file mode 100644
index 00000000000..6c19dfaac4e
--- /dev/null
+++ b/source/blender/src/writeavicodec.c
@@ -0,0 +1,799 @@
+/**
+ * Functions for writing windows avi-format files.
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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
+
+#define INC_OLE2
+#include <windows.h>
+#include <windowsx.h>
+#include <memory.h>
+#include <mmsystem.h>
+#include <vfw.h>
+
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+#include "BLI_blenlib.h"
+
+#include "render_types.h"
+#include "render.h"
+
+#include "BKE_global.h"
+#include "BKE_scene.h"
+#include "BKE_writeavi.h"
+
+#include "BIF_toolbox.h"
+
+// this defines the compression type for
+// the output video stream
+
+AVICOMPRESSOPTIONS opts;
+
+static int sframe;
+static PAVIFILE pfile = NULL;
+static int avifileinitdone = 0;
+static PAVISTREAM psUncompressed = NULL, psCompressed = NULL;
+
+// function definitions
+static void init_bmi(BITMAPINFOHEADER *bmi);
+static void opts_to_acd(AviCodecData *acd);
+static void acd_to_opts(AviCodecData *acd);
+static void free_opts_data();
+static int open_avi_codec_file(char * name);
+
+///////////////////////////////////////////////////////////////////////////
+//
+// silly default parameters
+//
+///////////////////////////////////////////////////////////////////////////
+
+#define DEFAULT_WIDTH 240
+#define DEFAULT_HEIGHT 120
+#define DEFAULT_LENGTH 100
+#define DEFAULT_SIZE 6
+#define DEFAULT_COLOR RGB(255,0,0)
+#define XSPEED 7
+#define YSPEED 5
+
+///////////////////////////////////////////////////////////////////////////
+//
+// useful macros
+//
+///////////////////////////////////////////////////////////////////////////
+
+#define ALIGNULONG(i) ((i+3)&(~3)) /* ULONG aligned ! */
+#define WIDTHBYTES(i) ((unsigned)((i+31)&(~31))/8) /* ULONG aligned ! */
+#define DIBWIDTHBYTES(bi) (int)WIDTHBYTES((int)(bi).biWidth * (int)(bi).biBitCount)
+#define DIBPTR(lpbi) ((LPBYTE)(lpbi) + \
+ (int)(lpbi)->biSize + \
+ (int)(lpbi)->biClrUsed * sizeof(RGBQUAD) )
+
+///////////////////////////////////////////////////////////////////////////
+//
+// custom video stream instance structure
+//
+///////////////////////////////////////////////////////////////////////////
+
+typedef struct {
+
+ //
+ // The Vtbl must come first
+ //
+ IAVIStreamVtbl * lpvtbl;
+
+ //
+ // private ball instance data
+ //
+ ULONG ulRefCount;
+
+ DWORD fccType; // is this audio/video
+
+ int width; // size in pixels of each frame
+ int height;
+ int length; // length in frames of the pretend AVI movie
+ int size;
+ COLORREF color; // ball color
+
+} AVIBALL, * PAVIBALL;
+
+///////////////////////////////////////////////////////////////////////////
+//
+// custom stream methods
+//
+///////////////////////////////////////////////////////////////////////////
+
+HRESULT STDMETHODCALLTYPE AVIBallQueryInterface(PAVISTREAM ps, REFIID riid, LPVOID * ppvObj);
+HRESULT STDMETHODCALLTYPE AVIBallCreate (PAVISTREAM ps, LONG lParam1, LONG lParam2);
+ULONG STDMETHODCALLTYPE AVIBallAddRef (PAVISTREAM ps);
+ULONG STDMETHODCALLTYPE AVIBallRelease (PAVISTREAM ps);
+HRESULT STDMETHODCALLTYPE AVIBallInfo (PAVISTREAM ps, AVISTREAMINFOW * psi, LONG lSize);
+LONG STDMETHODCALLTYPE AVIBallFindSample (PAVISTREAM ps, LONG lPos, LONG lFlags);
+HRESULT STDMETHODCALLTYPE AVIBallReadFormat (PAVISTREAM ps, LONG lPos, LPVOID lpFormat, LONG *lpcbFormat);
+HRESULT STDMETHODCALLTYPE AVIBallSetFormat (PAVISTREAM ps, LONG lPos, LPVOID lpFormat, LONG cbFormat);
+HRESULT STDMETHODCALLTYPE AVIBallRead (PAVISTREAM ps, LONG lStart, LONG lSamples, LPVOID lpBuffer, LONG cbBuffer, LONG * plBytes,LONG * plSamples);
+HRESULT STDMETHODCALLTYPE AVIBallWrite (PAVISTREAM ps, LONG lStart, LONG lSamples, LPVOID lpBuffer, LONG cbBuffer, DWORD dwFlags, LONG *plSampWritten, LONG *plBytesWritten);
+HRESULT STDMETHODCALLTYPE AVIBallDelete (PAVISTREAM ps, LONG lStart, LONG lSamples);
+HRESULT STDMETHODCALLTYPE AVIBallReadData (PAVISTREAM ps, DWORD fcc, LPVOID lp,LONG *lpcb);
+HRESULT STDMETHODCALLTYPE AVIBallWriteData (PAVISTREAM ps, DWORD fcc, LPVOID lp,LONG cb);
+
+IAVIStreamVtbl AVIBallHandler = {
+ AVIBallQueryInterface,
+ AVIBallAddRef,
+ AVIBallRelease,
+ AVIBallCreate,
+ AVIBallInfo,
+ AVIBallFindSample,
+ AVIBallReadFormat,
+ AVIBallSetFormat,
+ AVIBallRead,
+ AVIBallWrite,
+ AVIBallDelete,
+ AVIBallReadData,
+ AVIBallWriteData
+};
+
+
+//
+// This is the function an application would call to create a PAVISTREAM to
+// reference the ball. Then the standard AVIStream function calls can be
+// used to work with this stream.
+//
+PAVISTREAM WINAPI NewBall(void)
+{
+ static AVIBALL ball;
+ PAVIBALL pball = &ball;
+
+ //
+ // Fill the function table
+ //
+ pball->lpvtbl = &AVIBallHandler;
+
+ //
+ // Call our own create code to create a new instance (calls AVIBallCreate)
+ // For now, don't use any lParams.
+ //
+ pball->lpvtbl->Create((PAVISTREAM) pball, 0, 0);
+
+ return (PAVISTREAM) pball;
+}
+
+///////////////////////////////////////////////////////////////////////////
+//
+// This function is called to initialize an instance of the bouncing ball.
+//
+// When called, we look at the information possibly passed in <lParam1>,
+// if any, and use it to determine the length of movie they want. (Not
+// supported by NewBall right now, but it could be).
+//
+///////////////////////////////////////////////////////////////////////////
+HRESULT STDMETHODCALLTYPE AVIBallCreate(PAVISTREAM ps, LONG lParam1, LONG lParam2)
+{
+ PAVIBALL pball = (PAVIBALL) ps;
+
+ //
+ // what type of data are we? (audio/video/other stream)
+ //
+ pball->fccType = streamtypeVIDEO;
+
+ //
+ // We define lParam1 as being the length of movie they want us to pretend
+ // to be.
+ //
+ if (lParam1)
+ pball->length = (int) lParam1;
+ else
+ pball->length = DEFAULT_LENGTH;
+
+ switch (pball->fccType) {
+
+ case streamtypeVIDEO:
+ pball->color = DEFAULT_COLOR;
+ pball->width = DEFAULT_WIDTH;
+ pball->height = DEFAULT_HEIGHT;
+ pball->size = DEFAULT_SIZE;
+ pball->ulRefCount = 1; // note that we are opened once
+ return AVIERR_OK; // success
+
+ case streamtypeAUDIO:
+ return ResultFromScode(AVIERR_UNSUPPORTED); // we don't do audio
+
+ default:
+ return ResultFromScode(AVIERR_UNSUPPORTED); // or anything else
+ }
+}
+
+
+//
+// Increment our reference count
+//
+ULONG STDMETHODCALLTYPE AVIBallAddRef(PAVISTREAM ps)
+{
+ PAVIBALL pball = (PAVIBALL) ps;
+ return (++pball->ulRefCount);
+}
+
+
+//
+// Decrement our reference count
+//
+ULONG STDMETHODCALLTYPE AVIBallRelease(PAVISTREAM ps)
+{
+ PAVIBALL pball = (PAVIBALL) ps;
+ if (--pball->ulRefCount)
+ return pball->ulRefCount;
+
+ // Free any data we're keeping around - like our private structure
+ GlobalFreePtr(pball);
+
+ return 0;
+}
+
+
+//
+// Fills an AVISTREAMINFO structure
+//
+HRESULT STDMETHODCALLTYPE AVIBallInfo(PAVISTREAM ps, AVISTREAMINFOW * psi, LONG lSize)
+{
+ PAVIBALL pball = (PAVIBALL) ps;
+
+ if (lSize < sizeof(AVISTREAMINFO))
+ return ResultFromScode(AVIERR_BUFFERTOOSMALL);
+
+ _fmemset(psi, 0, (int)lSize);
+
+ // Fill out a stream header with information about us.
+ psi->fccType = pball->fccType;
+ psi->fccHandler = mmioFOURCC('B','a','l','l');
+ psi->dwScale = 1;
+ psi->dwRate = 15;
+ psi->dwLength = pball->length;
+ psi->dwSuggestedBufferSize = pball->height * ALIGNULONG(pball->width);
+ psi->rcFrame.right = pball->width;
+ psi->rcFrame.bottom = pball->height;
+ CopyMemory((PVOID)psi->szName,
+ (PVOID)L"Bouncing ball video",
+ sizeof(L"Bouncing ball video"));
+
+ return AVIERR_OK;
+}
+
+///////////////////////////////////////////////////////////////////////////
+//
+// AVIBallReadFormat: needs to return the format of our data.
+//
+///////////////////////////////////////////////////////////////////////////
+HRESULT STDMETHODCALLTYPE AVIBallReadFormat (PAVISTREAM ps, LONG lPos,LPVOID lpFormat,LONG *lpcbFormat)
+{
+ PAVIBALL pball = (PAVIBALL) ps;
+ LPBITMAPINFO lpbi = (LPBITMAPINFO) lpFormat;
+
+ if (lpFormat == NULL || *lpcbFormat == 0) {
+ *lpcbFormat = sizeof(BITMAPINFOHEADER);
+ return AVIERR_OK;
+ }
+
+ if (*lpcbFormat < sizeof(BITMAPINFOHEADER))
+ return ResultFromScode(AVIERR_BUFFERTOOSMALL);
+
+ // This is a relatively silly example: we build up our
+ // format from scratch every time.
+
+ /*
+ lpbi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ lpbi->bmiHeader.biCompression = BI_RGB;
+ lpbi->bmiHeader.biWidth = pball->width;
+ lpbi->bmiHeader.biHeight = pball->height;
+ lpbi->bmiHeader.biBitCount = 8;
+ lpbi->bmiHeader.biPlanes = 1;
+ lpbi->bmiHeader.biClrUsed = 2;
+ lpbi->bmiHeader.biSizeImage = pball->height * DIBWIDTHBYTES(lpbi->bmiHeader);
+ */
+
+ //init_bmi(&lpbi->bmiHeader);
+
+ memset(&lpbi->bmiHeader, 0, sizeof(BITMAPINFOHEADER));
+ lpbi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ lpbi->bmiHeader.biWidth = pball->width;
+ lpbi->bmiHeader.biHeight = pball->height;
+ lpbi->bmiHeader.biPlanes = 1;
+ lpbi->bmiHeader.biBitCount = 24;
+ lpbi->bmiHeader.biSizeImage = pball->width * pball->height * sizeof(RGBTRIPLE);
+
+ /*
+ lpbi->bmiColors[0].rgbRed = 0;
+ lpbi->bmiColors[0].rgbGreen = 0;
+ lpbi->bmiColors[0].rgbBlue = 0;
+ lpbi->bmiColors[1].rgbRed = GetRValue(pball->color);
+ lpbi->bmiColors[1].rgbGreen = GetGValue(pball->color);
+ lpbi->bmiColors[1].rgbBlue = GetBValue(pball->color);
+ */
+
+ *lpcbFormat = sizeof(BITMAPINFOHEADER);
+
+ return AVIERR_OK;
+}
+
+///////////////////////////////////////////////////////////////////////////
+//
+// AVIBallRead: needs to return the data for a particular frame.
+//
+///////////////////////////////////////////////////////////////////////////
+HRESULT STDMETHODCALLTYPE AVIBallRead (PAVISTREAM ps, LONG lStart,LONG lSamples,LPVOID lpBuffer,LONG cbBuffer,LONG * plBytes,LONG * plSamples)
+{
+ PAVIBALL pball = (PAVIBALL) ps;
+ LONG lSize = pball->height * ALIGNULONG(pball->width); // size of frame
+ // in bytes
+ int x, y;
+ HPSTR hp = lpBuffer;
+ int xPos, yPos;
+
+ // Reject out of range values
+ if (lStart < 0 || lStart >= pball->length)
+ return ResultFromScode(AVIERR_BADPARAM);
+
+ // Did they just want to know the size of our data?
+ if (lpBuffer == NULL || cbBuffer == 0)
+ goto exit;
+
+ // Will our frame fit in the buffer passed?
+ if (lSize > cbBuffer)
+ return ResultFromScode(AVIERR_BUFFERTOOSMALL);
+
+ // Figure out the position of the ball.
+ // It just bounces back and forth.
+
+ xPos = 5 + XSPEED * (int) lStart; // x = x0 + vt
+ xPos = xPos % ((pball->width - pball->size) * 2); // limit to 2xwidth
+ if (xPos > (pball->width - pball->size)) // reflect if
+ xPos = 2 * (pball->width - pball->size) - xPos; // needed
+
+ yPos = 5 + YSPEED * (int) lStart;
+ yPos = yPos % ((pball->height - pball->size) * 2);
+ if (yPos > (pball->height - pball->size))
+ yPos = 2 * (pball->height - pball->size) - yPos;
+
+ //
+ // Build a DIB from scratch by writing in 1's where the ball is, 0's
+ // where it isn't.
+ //
+ // Notice that we just build it in the buffer we've been passed.
+ //
+ // This is pretty ugly, I have to admit.
+ //
+ for (y = 0; y < pball->height; y++)
+ {
+ if (y >= yPos && y < yPos + pball->size)
+ {
+ for (x = 0; x < pball->width; x++)
+ {
+ *hp++ = (BYTE) ((x >= xPos && x < xPos + pball->size) ? 1 : 0);
+ }
+ }
+ else
+ {
+ for (x = 0; x < pball->width; x++)
+ {
+ *hp++ = 0;
+ }
+ }
+
+ hp += pball->width - ALIGNULONG(pball->width);
+ }
+
+exit:
+ // We always return exactly one frame
+ if (plSamples)
+ *plSamples = 1;
+
+ // Return the size of our frame
+ if (plBytes)
+ *plBytes = lSize;
+
+ return AVIERR_OK;
+}
+
+
+HRESULT STDMETHODCALLTYPE AVIBallQueryInterface(PAVISTREAM ps, REFIID riid, LPVOID * ppvObj)
+{
+ PAVIBALL pball = (PAVIBALL) ps;
+
+ // We support the Unknown interface (everybody does) and our Stream
+ // interface.
+
+ if (_fmemcmp(riid, &IID_IUnknown, sizeof(GUID)) == 0)
+ *ppvObj = (LPVOID)pball;
+
+ else if (_fmemcmp(riid, &IID_IAVIStream, sizeof(GUID)) == 0)
+ *ppvObj = (LPVOID)pball;
+
+ else {
+ *ppvObj = NULL;
+ return ResultFromScode(E_NOINTERFACE);
+ }
+
+ AVIBallAddRef(ps);
+
+ return AVIERR_OK;
+}
+
+LONG STDMETHODCALLTYPE AVIBallFindSample (PAVISTREAM ps, LONG lPos, LONG lFlags)
+{
+ // The only format change is frame 0
+ if ((lFlags & FIND_TYPE) == FIND_FORMAT) {
+ if ((lFlags & FIND_DIR) == FIND_NEXT && lPos > 0)
+ return -1; // no more format changes
+ else
+ return 0;
+
+ // FIND_KEY and FIND_ANY always return the same position because
+ // every frame is non-empty and a key frame
+ } else
+ return lPos;
+}
+
+HRESULT STDMETHODCALLTYPE AVIBallReadData (PAVISTREAM ps, DWORD fcc, LPVOID lp, LONG *lpcb)
+{
+ return ResultFromScode(AVIERR_UNSUPPORTED);
+}
+
+HRESULT STDMETHODCALLTYPE AVIBallSetFormat (PAVISTREAM ps, LONG lPos, LPVOID lpFormat, LONG cbFormat)
+{
+ return ResultFromScode(AVIERR_UNSUPPORTED);
+}
+
+HRESULT STDMETHODCALLTYPE AVIBallWriteData (PAVISTREAM ps, DWORD fcc, LPVOID lp, LONG cb)
+{
+ return ResultFromScode(AVIERR_UNSUPPORTED);
+}
+
+HRESULT STDMETHODCALLTYPE AVIBallWrite (PAVISTREAM ps, LONG lStart, LONG lSamples, LPVOID lpBuffer, LONG cbBuffer, DWORD dwFlags, LONG *plSampWritten, LONG *plBytesWritten)
+{
+ return ResultFromScode(AVIERR_UNSUPPORTED);
+}
+
+HRESULT STDMETHODCALLTYPE AVIBallDelete (PAVISTREAM ps, LONG lStart, LONG lSamples)
+{
+ return ResultFromScode(AVIERR_UNSUPPORTED);
+}
+
+
+//////////////////////////////////////
+static void init_bmi(BITMAPINFOHEADER *bmi)
+{
+ memset(bmi, 0, sizeof(BITMAPINFOHEADER));
+ bmi->biSize = sizeof(BITMAPINFOHEADER);
+ bmi->biWidth = R.rectx;
+ bmi->biHeight = R.recty;
+ bmi->biPlanes = 1;
+ bmi->biBitCount = 24;
+ bmi->biSizeImage = bmi->biWidth * bmi->biHeight * sizeof(RGBTRIPLE);
+}
+
+
+static void opts_to_acd(AviCodecData *acd)
+{
+ acd->fccType = opts.fccType;
+ acd->fccHandler = opts.fccHandler;
+ acd->dwKeyFrameEvery = opts.dwKeyFrameEvery;
+ acd->dwQuality = opts.dwQuality;
+ acd->dwBytesPerSecond = opts.dwBytesPerSecond;
+ acd->dwFlags = opts.dwFlags;
+ acd->dwInterleaveEvery = opts.dwInterleaveEvery;
+ acd->cbFormat = opts.cbFormat;
+ acd->cbParms = opts.cbParms;
+
+ if (opts.lpFormat && opts.cbFormat) {
+ acd->lpFormat = MEM_mallocN(opts.cbFormat, "avi.lpFormat");
+ memcpy(acd->lpFormat, opts.lpFormat, opts.cbFormat);
+ }
+
+ if (opts.lpParms && opts.cbParms) {
+ acd->lpParms = MEM_mallocN(opts.cbParms, "avi.lpParms");
+ memcpy(acd->lpParms, opts.lpParms, opts.cbParms);
+ }
+}
+
+
+static void acd_to_opts(AviCodecData *acd)
+{
+ memset(&opts, 0, sizeof(opts));
+ if (acd) {
+ opts.fccType = acd->fccType;
+ opts.fccHandler = acd->fccHandler;
+ opts.dwKeyFrameEvery = acd->dwKeyFrameEvery;
+ opts.dwQuality = acd->dwQuality;
+ opts.dwBytesPerSecond = acd->dwBytesPerSecond;
+ opts.dwFlags = acd->dwFlags;
+ opts.dwInterleaveEvery = acd->dwInterleaveEvery;
+ opts.cbFormat = acd->cbFormat;
+ opts.cbParms = acd->cbParms;
+
+ if (acd->lpFormat && acd->cbFormat) {
+ opts.lpFormat = malloc(opts.cbFormat);
+ memcpy(opts.lpFormat, acd->lpFormat, opts.cbFormat);
+ }
+
+ if (acd->lpParms && acd->cbParms) {
+ opts.lpParms = malloc(opts.cbParms);
+ memcpy(opts.lpParms, acd->lpParms, opts.cbParms);
+ }
+ }
+}
+
+static void free_opts_data()
+{
+ if (opts.lpFormat) {
+ free(opts.lpFormat);
+ opts.lpFormat = NULL;
+ }
+ if (opts.lpParms) {
+ free(opts.lpParms);
+ opts.lpParms = NULL;
+ }
+}
+
+static int open_avi_codec_file(char * name)
+{
+ HRESULT hr;
+ WORD wVer;
+ BITMAPINFOHEADER bmi;
+ AVISTREAMINFO strhdr;
+ int ret_val = 0;
+
+ wVer = HIWORD(VideoForWindowsVersion());
+ if (wVer < 0x010a){
+ // this is probably an obsolete check...
+ ret_val = 1;
+ } else {
+ AVIFileInit();
+ avifileinitdone++;
+
+ hr = AVIFileOpen(&pfile, // returned file pointer
+ name, // file name
+ OF_WRITE | OF_CREATE, // mode to open file with
+ NULL); // use handler determined
+
+ if (hr != AVIERR_OK) {
+ ret_val = 1;
+ } else {
+ // initialize the BITMAPINFOHEADER
+ init_bmi(&bmi);
+ // and associate a stream with the input images
+ memset(&strhdr, 0, sizeof(strhdr));
+ strhdr.fccType = streamtypeVIDEO; // stream type
+ if (G.scene->r.avicodecdata) {
+ strhdr.fccHandler = G.scene->r.avicodecdata->fccHandler;
+ }
+ strhdr.dwScale = 1;
+ strhdr.dwRate = R.r.frs_sec;
+ strhdr.dwSuggestedBufferSize = bmi.biSizeImage;
+ SetRect(&strhdr.rcFrame, 0, 0, // rectangle for stream
+ (int) bmi.biWidth,
+ (int) bmi.biHeight);
+
+ // And create the stream
+ hr = AVIFileCreateStream(
+ pfile, // file pointer
+ &psUncompressed,// returned stream pointer
+ &strhdr); // stream header
+
+ if (hr != AVIERR_OK) {
+ ret_val = 1;
+ } else {
+ acd_to_opts(G.scene->r.avicodecdata);
+ }
+ }
+ }
+
+ return(ret_val);
+}
+
+
+void end_avi_codec(void)
+{
+ free_opts_data();
+
+ if (psUncompressed) {
+ AVIStreamClose(psUncompressed);
+ psUncompressed = NULL;
+ }
+
+ if (psCompressed) {
+ AVIStreamClose(psCompressed);
+ psCompressed = NULL;
+ }
+
+ if (pfile) {
+ AVIFileClose(pfile);
+ pfile = NULL;
+ }
+
+ if (avifileinitdone > 0) {
+ AVIFileExit();
+ avifileinitdone--;
+ }
+}
+
+
+void start_avi_codec(void)
+{
+ HRESULT hr;
+ BITMAPINFOHEADER bmi;
+ char name[2048];
+ char bakname[2048];
+
+ makeavistring(name);
+ sframe = (G.scene->r.sfra);
+
+ strcpy(bakname, name);
+ strcat(bakname, ".bak");
+
+ if (BLI_exists(name)) {
+ BLI_move(name, bakname);
+ }
+
+ // initialize the BITMAPINFOHEADER
+ init_bmi(&bmi);
+
+ if (open_avi_codec_file(name)) {
+ error("Can not open file %s", name);
+ G.afbreek = 1;
+ } else {
+ // now create a compressed stream from the uncompressed
+ // stream and the compression options
+ hr = AVIMakeCompressedStream(
+ &psCompressed, // returned stream pointer
+ psUncompressed, // uncompressed stream
+ &opts, // compression options
+ NULL); // Unknown...
+ if (hr != AVIERR_OK) {
+ error("Codec is locked or not supported.");
+ G.afbreek = 1;
+ } else {
+ hr = AVIStreamSetFormat(psCompressed, 0,
+ &bmi, // stream format
+ bmi.biSize + // format size
+ bmi.biClrUsed * sizeof(RGBQUAD)); // plus size of colormap
+ if (hr != AVIERR_OK) {
+ error("Codec is locked or not supported.");
+ G.afbreek = 1;
+ }
+ }
+ }
+
+ if (G.afbreek != 1) {
+ printf("Created win avi: %s\n", name);
+ if (BLI_exists(bakname)) {
+ BLI_delete(bakname, 0, 0);
+ }
+ } else {
+ // close the darn thing and remove it.
+ end_avi_codec();
+ if (BLI_exists(name)) {
+ BLI_delete(name, 0, 0);
+ }
+ if (BLI_exists(bakname)) {
+ BLI_move(bakname, name);
+ }
+ }
+}
+
+
+void append_avi_codec(int frame)
+{
+ HRESULT hr;
+ BITMAPINFOHEADER bmi;
+ RGBTRIPLE *buffer, *to;
+ int x, y;
+ unsigned char *from;
+
+ if (psCompressed) {
+ // initialize the BITMAPINFOHEADER
+ init_bmi(&bmi);
+
+ // copy pixels
+ buffer = MEM_mallocN(bmi.biSizeImage, "append_win_avi");
+ to = buffer;
+ from = (unsigned char *) R.rectot;
+ for (y = R.recty; y > 0 ; y--) {
+ for (x = R.rectx; x > 0 ; x--) {
+ to->rgbtRed = from[0];
+ to->rgbtGreen = from[1];
+ to->rgbtBlue = from[2];
+ to++; from += 4;
+ }
+ }
+
+ hr = AVIStreamWrite(
+ psCompressed, // stream pointer
+ frame - sframe, // frame number
+ 1, // number to write
+ (LPBYTE) buffer,// pointer to data
+ bmi.biSizeImage,// size of this frame
+ AVIIF_KEYFRAME, // flags....
+ NULL,
+ NULL);
+
+ MEM_freeN(buffer);
+
+ if (hr != AVIERR_OK) {
+ G.afbreek = 1;
+ } else {
+ printf ("added frame %3d (frame %3d in avi): ", frame, frame-sframe);
+ }
+ }
+}
+
+
+int get_codec_settings(void)
+{
+ char name[2048];
+ int ret_val = 0;
+ AVICOMPRESSOPTIONS *aopts[1] = {&opts};
+ AviCodecData *acd = G.scene->r.avicodecdata;
+ static PAVISTREAM psdummy;
+
+ acd_to_opts(G.scene->r.avicodecdata);
+
+ psdummy = NewBall();
+
+ if (psdummy == NULL) {
+ ret_val = 1;
+ } else {
+ if (!AVISaveOptions(NULL,
+ ICMF_CHOOSE_KEYFRAME | ICMF_CHOOSE_DATARATE,
+ 1,
+ &psdummy,
+ (LPAVICOMPRESSOPTIONS *) &aopts))
+ {
+ ret_val = 1;
+ } else {
+ if (acd) {
+ free_avicodecdata(acd);
+ } else {
+ acd = G.scene->r.avicodecdata = MEM_callocN(sizeof(AviCodecData), "AviCodecData");
+ }
+
+ opts_to_acd(acd);
+
+ AVISaveOptionsFree(1, aopts);
+ memset(&opts, 0, sizeof(opts));
+ }
+ }
+
+ return(ret_val);
+}
+
+#endif // _WIN32
diff --git a/source/blender/src/writeimage.c b/source/blender/src/writeimage.c
new file mode 100644
index 00000000000..d107347598d
--- /dev/null
+++ b/source/blender/src/writeimage.c
@@ -0,0 +1,110 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "IMB_imbuf.h"
+#include "IMB_imbuf_types.h" // ImBuf{}
+#include "DNA_scene_types.h"
+#include "DNA_texture_types.h" // EnvMap{}
+#include "DNA_image_types.h" // Image{}
+#include "render.h"
+#include "license_key.h" // LICENSE_KEY_VALID
+#include "BKE_utildefines.h" // ELEM
+
+#include "BIF_writeimage.h"
+
+int BIF_write_ibuf(ImBuf *ibuf, char *name)
+{
+ int ok;
+
+ /* to be used for e.g. envmap, not rendered images */
+
+ if(R.r.imtype== R_IRIS) ibuf->ftype= IMAGIC;
+ else if ((R.r.imtype==R_PNG) && (LICENSE_KEY_VALID)) {
+ ibuf->ftype= PNG;
+ }
+ else if ((R.r.imtype==R_TARGA) || (R.r.imtype==R_PNG)) {
+ // fall back to Targa if PNG writing is not supported
+ ibuf->ftype= TGA;
+ }
+ else if(R.r.imtype==R_RAWTGA) {
+ ibuf->ftype= RAWTGA;
+ }
+ else if(R.r.imtype==R_HAMX) {
+ ibuf->ftype= AN_hamx;
+ }
+ else if ELEM(R.r.imtype, R_JPEG90, R_MOVIE) {
+ if(R.r.quality < 10) R.r.quality= 90;
+
+ ibuf->ftype= JPG|R.r.quality;
+ }
+ else ibuf->ftype= TGA;
+
+ RE_make_existing_file(name);
+
+ ok = IMB_saveiff(ibuf, name, IB_rect);
+ if (ok == 0) {
+ perror(name);
+ }
+
+ return(ok);
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+void BIF_save_envmap(EnvMap *env, char *str)
+{
+ ImBuf *ibuf;
+/* extern rectcpy(); */
+ int dx;
+
+ /* all interactive stuff is handled in buttons.c */
+
+ dx= env->cuberes;
+ ibuf= IMB_allocImBuf(3*dx, 2*dx, 24, IB_rect, 0);
+
+ IMB_rectop(ibuf, env->cube[0]->ibuf,
+ 0, 0, 0, 0, dx, dx, IMB_rectcpy, 0);
+ IMB_rectop(ibuf, env->cube[1]->ibuf,
+ dx, 0, 0, 0, dx, dx, IMB_rectcpy, 0);
+ IMB_rectop(ibuf, env->cube[2]->ibuf,
+ 2*dx, 0, 0, 0, dx, dx, IMB_rectcpy, 0);
+ IMB_rectop(ibuf, env->cube[3]->ibuf,
+ 0, dx, 0, 0, dx, dx, IMB_rectcpy, 0);
+ IMB_rectop(ibuf, env->cube[4]->ibuf,
+ dx, dx, 0, 0, dx, dx, IMB_rectcpy, 0);
+ IMB_rectop(ibuf, env->cube[5]->ibuf,
+ 2*dx, dx, 0, 0, dx, dx, IMB_rectcpy, 0);
+
+ BIF_write_ibuf(ibuf, str);
+ IMB_freeImBuf(ibuf);
+}
diff --git a/source/blender/src/writemovie.c b/source/blender/src/writemovie.c
new file mode 100644
index 00000000000..f71156f5131
--- /dev/null
+++ b/source/blender/src/writemovie.c
@@ -0,0 +1,514 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 __sgi
+
+#include <unistd.h>
+#include <movie.h>
+#include <cdaudio.h>
+#include <dmedia/cl.h>
+#include <dmedia/cl_cosmo.h>
+#include <sys/file.h> /* flock */
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "BKE_global.h"
+#include "BKE_utildefines.h"
+
+#include "BIF_gl.h"
+#include "BIF_writemovie.h"
+#include "BIF_toolbox.h"
+
+#include "render.h"
+
+#define error(str) {perror(str) ; error("%s", str); G.afbreek= 1;}
+#define QUIT(str) {error(str); return;}
+
+#define DIR_UP 1
+#define DIR_DOWN 2
+#define DIR_BOTH (DIR_UP | DIR_DOWN)
+
+#define MAXQUAL R.r.quality
+#define MINQUAL 30
+
+/* globals */
+
+static CL_Handle compr, soft_compr;
+static MVid movie, image;
+static DMparams *movie_params, *image_params;
+static int compr_params[64];
+static int myindex, qualindex, qualnow, mv_outx, mv_outy, numfields= 2;
+static char *comp_buf;
+static int sfra, efra, first = TRUE, maxbufsize;
+static int ntsc = FALSE;
+
+#define FIRST_IMAGE "FIRST_IMAGE"
+#define BLENDER_FIRST_IMAGE "BLENDER_1ST_IMG"
+
+
+static void report_flock(void)
+{
+ static int flock_reported = FALSE;
+
+ if (flock_reported) return;
+ flock_reported = TRUE;
+
+ error("WriteMovie: couldn't flock() moviefile. Ignoring.");
+}
+
+
+static void make_movie_name(char *string)
+{
+ int len;
+ char txt[64];
+
+ if (string==0) return;
+
+ strcpy(string, G.scene->r.pic);
+ BLI_convertstringcode(string, G.sce, G.scene->r.cfra);
+ len= strlen(string);
+
+ RE_make_existing_file(string);
+
+ if (strcasecmp(string + len - 3, ".mv")) {
+ sprintf(txt, "%04d_%04d.mv", sfra, efra);
+ strcat(string, txt);
+ }
+}
+
+static int my_Compress(uint * rect, int *bufsize)
+{
+ int err = 0;
+
+ compr_params[qualindex] = qualnow;
+ clSetParams(compr, compr_params, myindex);
+
+ while (clCompress(compr, numfields, rect, bufsize, comp_buf) != numfields) {
+ if (compr == soft_compr) {
+ error("clCompress (software)");
+ return 1;
+ }
+
+ /* hardware opnieuw initialiseren */
+ clCloseCompressor(compr);
+ clOpenCompressor(CL_JPEG_COSMO, &compr);
+
+ qualnow--;
+ compr_params[qualindex] = qualnow;
+ clSetParams(compr, compr_params, myindex);
+ printf("retrying at quality %d\n", qualnow);
+
+ err= TRUE;
+ }
+
+ return (err);
+}
+
+static void set_sfra_efra(void)
+{
+ sfra = (G.scene->r.sfra);
+ efra = (G.scene->r.efra);
+}
+
+static void open_compressor(void)
+{
+ int cosmo = FAILURE;
+
+ /* initialiseren van de compressor */
+
+ if (clOpenCompressor(CL_JPEG_SOFTWARE, &soft_compr) != SUCCESS) QUIT("clOpenCompressor");
+
+ if (G.scene->r.mode & R_COSMO) {
+ cosmo = clOpenCompressor(CL_JPEG_COSMO, &compr);
+ if (cosmo != SUCCESS && first) error("warning: using software compression");
+ first = FALSE;
+ }
+
+ if (cosmo != SUCCESS) compr = soft_compr;
+
+ myindex = 0;
+
+ compr_params[myindex++]= CL_IMAGE_WIDTH;
+ compr_params[myindex++]= mv_outx;
+
+ compr_params[myindex++]= CL_IMAGE_HEIGHT;
+ compr_params[myindex++]= mv_outy / numfields;
+
+ compr_params[myindex++]= CL_JPEG_QUALITY_FACTOR;
+ qualindex = myindex;
+ compr_params[myindex++]= R.r.quality;
+
+ compr_params[myindex++]= CL_ORIGINAL_FORMAT;
+ compr_params[myindex++]= CL_RGBX;
+
+ compr_params[myindex++]= CL_ORIENTATION;
+ compr_params[myindex++]= CL_TOP_DOWN;
+
+ compr_params[myindex++]= CL_INTERNAL_FORMAT;
+ compr_params[myindex++]= CL_YUV422;
+
+ /* this parameter must be set for non-queueing mode */
+ compr_params[myindex++]= CL_ENABLE_IMAGEINFO;
+ compr_params[myindex++]= 1;
+
+ /* enable stream headers */
+ compr_params[myindex++]= CL_STREAM_HEADERS;
+ compr_params[myindex++]= TRUE;
+
+ clSetParams(compr, compr_params, myindex);
+ if (compr != soft_compr) clSetParams(soft_compr, compr_params, myindex);
+
+ maxbufsize = 2 * clGetParam(compr, CL_COMPRESSED_BUFFER_SIZE);
+ comp_buf = MEM_mallocN(maxbufsize, "cosmo_buffer");
+}
+
+static void close_compressor(void)
+{
+ MEM_freeN(comp_buf);
+ comp_buf = 0;
+
+ clCloseCompressor(compr);
+ if (soft_compr != compr) clCloseCompressor(soft_compr);
+}
+
+void end_movie(void)
+{
+}
+
+static void new_movie(int fd)
+{
+ char string[120];
+
+ if (dmParamsCreate(&movie_params) != DM_SUCCESS) QUIT("dmParamsCreate");
+ if (dmParamsCreate(&image_params) != DM_SUCCESS) QUIT("dmParamsCreate");
+
+ if (mvSetMovieDefaults(movie_params, MV_FORMAT_SGI_3) != DM_SUCCESS) QUIT("mvSetMovieDefaults");
+ if (dmSetImageDefaults(image_params, mv_outx, mv_outy, DM_PACKING_RGBX) != DM_SUCCESS) QUIT("dmSetImageDefaults");
+
+ mvAddUserParam(BLENDER_FIRST_IMAGE);
+ sprintf(string, "%04d", sfra);
+ dmParamsSetString(image_params, BLENDER_FIRST_IMAGE, string);
+
+ if (ntsc) dmParamsSetFloat(image_params, DM_IMAGE_RATE, 29.97);
+ else dmParamsSetFloat(image_params, DM_IMAGE_RATE, 25.0);
+
+ if (numfields == 2) {
+ if (ntsc) dmParamsSetEnum(image_params, DM_IMAGE_INTERLACING, DM_IMAGE_INTERLACED_ODD);
+ else dmParamsSetEnum(image_params, DM_IMAGE_INTERLACING, DM_IMAGE_INTERLACED_EVEN);
+ } else dmParamsSetEnum(image_params, DM_IMAGE_INTERLACING, DM_IMAGE_NONINTERLACED);
+
+ dmParamsSetEnum(image_params, DM_IMAGE_ORIENTATION, DM_TOP_TO_BOTTOM);
+ dmParamsSetString(image_params, DM_IMAGE_COMPRESSION, DM_IMAGE_JPEG);
+
+ if (mvCreateFD(fd, movie_params, NULL, &movie) != DM_SUCCESS) QUIT("mvCreateFile");
+ if (mvAddTrack(movie, DM_IMAGE, image_params, NULL, &image)) QUIT("mvAddTrack");;
+ if (mvSetLoopMode(movie, MV_LOOP_CONTINUOUSLY) != DM_SUCCESS) QUIT("mvSetMovieDefaults");
+
+ if (mvWrite(movie) != DM_SUCCESS) QUIT("mvWrite");
+ if (mvClose(movie) != DM_SUCCESS) QUIT("mvClose");
+
+ dmParamsDestroy(image_params);
+ dmParamsDestroy(movie_params);
+}
+
+
+void start_movie(void)
+{
+ char name[FILE_MAXDIR+FILE_MAXFILE];
+ char bak[sizeof(name) + 4];
+ int fd;
+
+ first = TRUE;
+
+ set_sfra_efra();
+
+ /* naam bedenken voor de movie */
+ make_movie_name(name);
+
+ ntsc = FALSE;
+
+ switch (R.recty) {
+ case 480: case 360: case 240: case 120:
+ ntsc = TRUE;
+ }
+
+ if (ntsc) {
+ switch (R.rectx) {
+ case 360: case 320: case 720: case 640:
+ mv_outx = R.rectx;
+ break;
+ default:
+ if (R.rectx <= 320) mv_outx = 320;
+ else if (R.rectx <= 640) mv_outx = 640;
+ else mv_outx = 720;
+ }
+ } else {
+ switch (R.rectx) {
+ case 360: case 384: case 720: case 768:
+ mv_outx = R.rectx;
+ break;
+ default:
+ if (R.rectx < 384) mv_outx = 384;
+ else mv_outx = 768;
+ }
+ }
+
+ if (ntsc) {
+ if (R.recty <= 240) {
+ mv_outy = 240;
+ numfields = 1;
+ } else {
+ mv_outy = 480;
+ numfields = 2;
+ }
+ } else {
+ if (R.recty <= 288) {
+ mv_outy = 288;
+ numfields = 1;
+ } else {
+ mv_outy = 576;
+ numfields = 2;
+ }
+ }
+
+ if(R.r.mode & R_MOVIECROP) {
+ if (ntsc) {
+ if (R.rectx > 640) mv_outx = 720;
+ else mv_outx = 640;
+ mv_outy = 480;
+ numfields = 2;
+ } else {
+ if (R.rectx > 720) mv_outx = 768;
+ else mv_outx = 720;
+ mv_outy = 576;
+ numfields = 2;
+ }
+ }
+
+ qualnow = R.r.quality;
+
+
+ fd = open(name, O_BINARY|O_RDWR);
+ if (fd != -1) {
+ if (flock(fd, LOCK_EX) == -1) report_flock();
+
+ if (mvOpenFD(fd, &movie) == DM_SUCCESS) {
+ if (mvFindTrackByMedium(movie, DM_IMAGE, &image) == DM_SUCCESS) {
+ if (mvGetImageWidth(image) == mv_outx) {
+ if (mvGetImageHeight(image) == mv_outy) {
+ mvClose(movie);
+ close(fd);
+ return;
+ }
+ }
+ }
+ strcpy(bak, name);
+ strcat(bak, ".bak");
+ BLI_rename(name, bak);
+ mvClose(movie);
+ }
+
+ close(fd);
+ }
+ fd = open(name, O_BINARY|O_RDWR | O_CREAT | O_EXCL, 0664);
+ if (fd != -1) {
+ if (flock(fd, LOCK_EX) == -1) report_flock();
+ new_movie(fd);
+ printf("Created movie: %s\n", name);
+ close(fd);
+ }
+}
+
+void append_movie(int cfra)
+{
+ ImBuf *ibuf, *tbuf;
+ int err, ofsx, ofsy, bufsize, rate, lastqual, qualstep, direction, first_image, num_images;
+ char name[FILE_MAXDIR+FILE_MAXFILE];
+ const char *string;
+ int fd;
+
+ set_sfra_efra();
+ make_movie_name(name);
+ open_compressor();
+
+ rate = 1024 * R.r.maximsize;
+
+ /* veranderd: kopie van rectot maken */
+ ibuf= IMB_allocImBuf(R.rectx, R.recty, 32, IB_rect, 0);
+ memcpy(ibuf->rect, R.rectot, 4*R.rectx*R.recty);
+
+ if (ibuf->x != mv_outx || ibuf->y != mv_outy) {
+ tbuf = IMB_allocImBuf(mv_outx, mv_outy, 32, IB_rect, 0);
+ IMB_rectoptot(tbuf, 0, IMB_rectfill, 0x00);
+
+ ofsx = (tbuf->x - ibuf->x) / 2;
+ ofsy = (tbuf->y - ibuf->y) / 2;
+ if (numfields == 2) ofsy &= ~1;
+
+ IMB_rectop(tbuf, ibuf, ofsx, ofsy, 0, 0, 32767, 32767, IMB_rectcpy, 0);
+ IMB_freeImBuf(ibuf);
+ strcpy(tbuf->name, ibuf->name);
+ ibuf = tbuf;
+ }
+ IMB_convert_rgba_to_abgr(ibuf->x*ibuf->y, ibuf->rect);
+
+ if (numfields == 2) {
+ if (ntsc) {
+ IMB_rectop(ibuf, ibuf, 0, 0, 0, 1, 32767, 32767, IMB_rectcpy, 0);
+ IMB_flipy(ibuf);
+ IMB_de_interlace(ibuf);
+ if (ntsc) IMB_rectop(ibuf, ibuf, 0, 0, 0, 1, 32767, 32767, IMB_rectcpy, 0);
+ } else {
+ IMB_flipy(ibuf);
+ IMB_rectop(ibuf, ibuf, 0, 0, 0, 1, 32767, 32767, IMB_rectcpy, 0);
+ IMB_de_interlace(ibuf);
+ }
+ }
+ else {
+ /* kleine movies anders op de kop */
+ IMB_flipy(ibuf);
+ }
+
+ if (rate == 0) {
+ qualnow = R.r.quality;
+ my_Compress(ibuf->rect, &bufsize);
+ } else {
+ qualstep = 4;
+ direction = 0;
+
+ do {
+ if (qualnow > MAXQUAL) qualnow = MAXQUAL;
+ if (qualnow < MINQUAL) qualnow = MINQUAL;
+
+ compr_params[qualindex] = qualnow;
+ clSetParams(compr, compr_params, myindex);
+
+ lastqual = qualnow;
+ err = my_Compress(ibuf->rect, &bufsize);
+
+ printf(" tried quality: %d, size %d\n", qualnow, bufsize);
+
+ if (bufsize < 0.9 * rate) {
+ if (err) {
+ /* forget about this frame, retry next frame at old quality settting */
+ qualnow = lastqual;
+ break;
+ }
+ if (qualnow == MAXQUAL) break;
+ direction |= DIR_UP;
+ if (direction == DIR_BOTH) qualstep /= 2;
+ qualnow += qualstep;
+ } else if (bufsize > 1.1 * rate) {
+ if (qualnow == MINQUAL) break;
+ direction |= DIR_DOWN;
+ if (direction == DIR_BOTH) qualstep /= 2;
+ qualnow -= qualstep;
+ } else break;
+
+ if (qualstep == 0) {
+ /* this was the last iteration. Make sure that the buffer isn't to big */
+ if (bufsize < 1.1 * rate) break;
+ else qualnow--;
+ }
+ } while (1);
+
+ printf("used quality: %d\n", qualnow);
+
+ if (bufsize < rate) qualnow++;
+ else qualnow--;
+
+ }
+
+ fd = open(name, O_BINARY|O_RDWR);
+
+ if (fd != -1) {
+ if (flock(fd, LOCK_EX) == -1) report_flock();
+ if (mvOpenFD(fd, &movie) == DM_SUCCESS){
+ if (mvFindTrackByMedium(movie, DM_IMAGE, &image) == DM_SUCCESS) {
+ image_params = mvGetParams(image);
+
+ first_image = 1;
+
+ string = dmParamsGetString(image_params, FIRST_IMAGE);
+ if (string) {
+ first_image = atoi(string);
+ }
+ string = dmParamsGetString(image_params, BLENDER_FIRST_IMAGE);
+ if (string) {
+ first_image = atoi(string);
+ }
+
+ num_images = mvGetTrackLength(image);
+
+ if (cfra >= first_image && cfra <= (first_image + num_images - 1)) {
+ if (mvDeleteFrames(image, cfra - first_image, 1) != DM_SUCCESS) {
+ mvDestroyMovie(movie);
+ error("mvDeleteFrames");
+ G.afbreek = 1;
+ }
+ }
+
+ if (G.afbreek != 1) {
+ if (mvInsertCompressedImage(image, cfra - first_image, bufsize, comp_buf) == DM_SUCCESS) {
+ printf("added frame %3d (frame %3d in movie): length %6d: ", cfra, cfra - first_image + 1, bufsize);
+ mvClose(movie);
+ } else {
+ mvDestroyMovie(movie);
+ error("mvInsertCompressedImage");
+ G.afbreek = 1;
+ }
+ }
+ } else {
+ mvDestroyMovie(movie);
+ error("mvFindTrackByMedium");
+ G.afbreek = 1;
+ }
+ }else {
+ error("mvOpenFD");
+ G.afbreek = 1;
+ }
+ close(fd);
+ } else {
+ error("open movie");
+ G.afbreek = 1;
+ }
+
+ IMB_freeImBuf(ibuf);
+
+ close_compressor();
+}
+
+#endif /* __sgi */
diff --git a/source/blender/verify/BLO_sign_verify_Header.h b/source/blender/verify/BLO_sign_verify_Header.h
new file mode 100644
index 00000000000..18e69986a6d
--- /dev/null
+++ b/source/blender/verify/BLO_sign_verify_Header.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 BLO_SIGN_VERIFY_H
+#define BLO_SIGN_VERIFY_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "BLO_sys_types.h"
+
+#define SIGNVERIFYHEADERSTRUCTSIZE sizeof(struct BLO_sign_verify_HeaderStruct)
+// TODO use reasonable sizes
+// Tests showed: pubKeyLen 64, cryptedKeyLen 64 bytes
+// So we pick 2*64 bytes + tail for now :
+#define MAXPUBKEYLEN 130
+#define MAXSIGNATURELEN 130
+
+struct BLO_sign_verify_HeaderStruct {
+ uint8_t magic; /* poor mans header recognize check */
+ uint32_t length; /* how much signed data is there */
+ uint8_t pubKey[MAXPUBKEYLEN];
+ uint32_t pubKeyLen; /* the actual pubKey length */
+ uint8_t signature[MAXSIGNATURELEN];
+ int32_t signatureLen; /* the actual signature length */
+ uint32_t datacrc; /* data crc checksum */
+ uint32_t headercrc; /* header minus crc itself checksum */
+};
+
+#define SIGNERHEADERSTRUCTSIZE sizeof(struct BLO_SignerHeaderStruct)
+#define MAXSIGNERLEN 100
+
+struct BLO_SignerHeaderStruct {
+ uint8_t name[MAXSIGNERLEN]; // the signers name (from the key)
+ uint8_t email[MAXSIGNERLEN]; // the signers email (from the key)
+ uint8_t homeUrl[MAXSIGNERLEN]; // the signers home page
+ uint8_t text[MAXSIGNERLEN]; // optional additional user text
+ uint8_t pubKeyUrl1[MAXSIGNERLEN]; // the signers pubKey store
+ uint8_t pubKeyUrl2[MAXSIGNERLEN]; // the signers pubKey at NaN
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BLO_SIGN_VERIFY_H */
diff --git a/source/blender/verify/BLO_signer_info.h b/source/blender/verify/BLO_signer_info.h
new file mode 100644
index 00000000000..dbbacdfe502
--- /dev/null
+++ b/source/blender/verify/BLO_signer_info.h
@@ -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 *****
+ *
+ */
+
+#include "BLO_sign_verify_Header.h"
+
+/* external struct for signer info */
+
+struct BLO_SignerInfo {
+ char name[MAXSIGNERLEN];
+ char email[MAXSIGNERLEN];
+ char homeUrl[MAXSIGNERLEN];
+ // more to come...
+};
+
+struct BLO_SignerInfo *BLO_getSignerInfo(void);
+int BLO_isValidSignerInfo(struct BLO_SignerInfo *info);
+void BLO_clrSignerInfo(struct BLO_SignerInfo *info);
diff --git a/source/blender/verify/BLO_verify.h b/source/blender/verify/BLO_verify.h
new file mode 100644
index 00000000000..87b3bdb93db
--- /dev/null
+++ b/source/blender/verify/BLO_verify.h
@@ -0,0 +1,78 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BLO_VERIFY_H
+#define BLO_VERIFY_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define VERIFY_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name
+
+VERIFY_DECLARE_HANDLE(BLO_verifyStructHandle);
+
+/**
+ * openssl verify initializer
+ * @retval pointer to verify control structure
+ */
+ BLO_verifyStructHandle
+BLO_verify_begin(
+ void *endControl);
+
+/**
+ * openssl verify dataprocessor wrapper
+ * @param BLO_verify Pointer to verify control structure
+ * @param data Pointer to new data
+ * @param dataIn New data amount
+ * @retval streamGlueRead return value
+ */
+ int
+BLO_verify_process(
+ BLO_verifyStructHandle BLO_verifyHandle,
+ unsigned char *data,
+ unsigned int dataIn);
+
+/**
+ * openssl verify final call and cleanup
+ * @param BLO_verify Pointer to verify control structure
+ * @retval streamGlueRead return value
+ */
+ int
+BLO_verify_end(
+ BLO_verifyStructHandle BLO_verifyHandle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BLO_VERIFY_H */
diff --git a/source/blender/verify/Makefile b/source/blender/verify/Makefile
new file mode 100644
index 00000000000..73c2c53ad9c
--- /dev/null
+++ b/source/blender/verify/Makefile
@@ -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 *****
+#
+# Bounces make to subdirectories.
+
+SOURCEDIR = source/blender/verify
+DIRS = intern
+
+include nan_subdirs.mk
diff --git a/source/blender/verify/intern/BLO_verify.c b/source/blender/verify/intern/BLO_verify.c
new file mode 100644
index 00000000000..f9c71be1432
--- /dev/null
+++ b/source/blender/verify/intern/BLO_verify.c
@@ -0,0 +1,423 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * openssl verify wrapper library
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "openssl/rsa.h"
+#include "openssl/ripemd.h"
+#include "openssl/objects.h"
+#include "zlib.h"
+
+#include "GEN_messaging.h"
+
+#include "BLO_readStreamGlue.h"
+#include "BLO_verify.h"
+#include "BLO_sign_verify_Header.h" /* used by verify and encrypt */
+
+#include "BLO_signer_info.h" // external signer info struct
+
+static struct BLO_SignerInfo g_SignerInfo = {"", "", ""};
+
+struct verifyStructType {
+ struct readStreamGlueStruct *streamGlue;
+ unsigned int streamDone;
+ unsigned char headerbuffer[SIGNVERIFYHEADERSTRUCTSIZE];
+ uint32_t datacrc;
+ struct BLO_sign_verify_HeaderStruct *streamHeader;
+ RIPEMD160_CTX ripemd160_ctx;
+ struct BLO_SignerHeaderStruct *signerHeader;
+ unsigned char signerHeaderBuffer[SIGNERHEADERSTRUCTSIZE];
+ void *endControl;
+};
+
+ BLO_verifyStructHandle
+BLO_verify_begin(
+ void *endControl)
+{
+ struct verifyStructType *control;
+ control = malloc(sizeof(struct verifyStructType));
+ if (!control) return NULL;
+
+ control->streamGlue = NULL;
+ control->streamDone = 0;
+ memset(control->headerbuffer, 0, SIGNVERIFYHEADERSTRUCTSIZE);
+ control->datacrc = 0;
+
+ control->streamHeader = malloc(SIGNVERIFYHEADERSTRUCTSIZE);
+ if (!control->streamHeader) {
+ free(control);
+ return NULL;
+ }
+ control->streamHeader->magic = 0;
+ control->streamHeader->length = 0;
+ strcpy(control->streamHeader->pubKey, "");
+ control->streamHeader->pubKeyLen = 0;
+ strcpy(control->streamHeader->signature, "");
+ control->streamHeader->signatureLen = 0;
+ control->streamHeader->datacrc = 0;
+ control->streamHeader->headercrc = 0;
+
+ RIPEMD160_Init(&(control->ripemd160_ctx));
+
+ control->signerHeader = malloc(SIGNERHEADERSTRUCTSIZE);
+ if (!control->signerHeader) {
+ free(control->streamHeader);
+ free(control);
+ return NULL;
+ }
+ memset(control->signerHeader->name, 0, MAXSIGNERLEN);
+ memset(control->signerHeader->email, 0, MAXSIGNERLEN);
+ memset(control->signerHeader->homeUrl, 0, MAXSIGNERLEN);
+ memset(control->signerHeader->text, 0, MAXSIGNERLEN);
+ memset(control->signerHeader->pubKeyUrl1, 0, MAXSIGNERLEN);
+ memset(control->signerHeader->pubKeyUrl2, 0, MAXSIGNERLEN);
+
+ control->endControl = endControl;
+ return((BLO_verifyStructHandle) control);
+}
+
+ int
+BLO_verify_process(
+ BLO_verifyStructHandle BLO_verifyHandle,
+ unsigned char *data,
+ unsigned int dataIn)
+{
+ int err = 0;
+ struct verifyStructType *BLO_verify =
+ (struct verifyStructType *) BLO_verifyHandle;
+
+ if (!BLO_verify) {
+ err = BRS_SETFUNCTION(BRS_VERIFY) |
+ BRS_SETGENERR(BRS_NULL);
+ return err;
+ }
+
+ /* First check if we have our header filled in yet */
+ if (BLO_verify->streamHeader->length == 0) {
+ unsigned int processed;
+ if (dataIn == 0) return err; /* really need data to do anything */
+ processed = ((dataIn + BLO_verify->streamDone) <=
+ SIGNVERIFYHEADERSTRUCTSIZE)
+ ? dataIn : SIGNVERIFYHEADERSTRUCTSIZE;
+ memcpy(BLO_verify->headerbuffer + BLO_verify->streamDone,
+ data, processed);
+ BLO_verify->streamDone += processed;
+ dataIn -= processed;
+ data += processed;
+ if (BLO_verify->streamDone == SIGNVERIFYHEADERSTRUCTSIZE) {
+ /* we have the whole header, absorb it */
+ struct BLO_sign_verify_HeaderStruct *header;
+ uint32_t crc;
+
+ header = (struct BLO_sign_verify_HeaderStruct *)
+ BLO_verify->headerbuffer;
+ crc = crc32(0L, (const Bytef *) header,
+ SIGNVERIFYHEADERSTRUCTSIZE - 4);
+
+ if (header->magic == 'A') {
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "BLO_sign_verify_HeaderStruct Magic confirmed\n");
+#endif
+ } else {
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "ERROR BLO_sign_verify_HeaderStruct Magic NOT confirmed\n");
+#endif
+ err = BRS_SETFUNCTION(BRS_VERIFY) |
+ BRS_SETGENERR(BRS_MAGIC);
+ if (BLO_verify->streamGlue) free(BLO_verify->streamGlue);
+ if (BLO_verify->streamHeader) free(BLO_verify->streamHeader);
+ if (BLO_verify->signerHeader) free(BLO_verify->signerHeader);
+ free(BLO_verify);
+ return err;
+ }
+
+ if (crc == ntohl(header->headercrc)) {
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,"BLO_sign_verify_Header CRC correct\n");
+#endif
+ } else {
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,"ERROR BLO_sign_verify_Header CRC NOT correct\n");
+#endif
+ err = BRS_SETFUNCTION(BRS_VERIFY) |
+ BRS_SETGENERR(BRS_CRCHEADER);
+ if (BLO_verify->streamGlue) free(BLO_verify->streamGlue);
+ if (BLO_verify->streamHeader) free(BLO_verify->streamHeader);
+ if (BLO_verify->signerHeader) free(BLO_verify->signerHeader);
+ free(BLO_verify);
+ return err;
+ }
+ BLO_verify->streamHeader->length = ntohl(header->length);
+ BLO_verify->streamHeader->pubKeyLen = ntohl(header->pubKeyLen);
+ memcpy(BLO_verify->streamHeader->pubKey, header->pubKey,
+ BLO_verify->streamHeader->pubKeyLen);
+ BLO_verify->streamHeader->signatureLen =
+ ntohl(header->signatureLen);
+ memcpy(BLO_verify->streamHeader->signature, header->signature,
+ BLO_verify->streamHeader->signatureLen);
+ BLO_verify->streamHeader->datacrc = ntohl(header->datacrc);
+
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "BLO_verify_process gets %u bytes\n",
+ (unsigned int) BLO_verify->streamHeader->length);
+#endif
+
+ }
+ }
+
+ /* Is there really (still) new data available ? */
+ if (dataIn > 0) {
+ // BLO_SignerHeaderStruct
+ if (BLO_verify->signerHeader->name[0] == 0) {
+ // we don't have our signerHeader complete yet
+ unsigned int processed;
+ processed = ((dataIn + BLO_verify->streamDone -
+ SIGNVERIFYHEADERSTRUCTSIZE) <= SIGNERHEADERSTRUCTSIZE)
+ ? dataIn : SIGNERHEADERSTRUCTSIZE;
+ memcpy(BLO_verify->signerHeaderBuffer +
+ BLO_verify->streamDone - SIGNVERIFYHEADERSTRUCTSIZE,
+ data, processed);
+ BLO_verify->streamDone += processed;
+ dataIn -= processed;
+ data += processed;
+ if (BLO_verify->streamDone == SIGNVERIFYHEADERSTRUCTSIZE +
+ SIGNERHEADERSTRUCTSIZE) {
+ // we have the whole header, absorb it
+ struct BLO_SignerHeaderStruct *signerHeader;
+ signerHeader = (struct BLO_SignerHeaderStruct *)
+ BLO_verify->signerHeaderBuffer;
+ strncpy(BLO_verify->signerHeader->name,
+ signerHeader->name, MAXSIGNERLEN-1);
+ strncpy(BLO_verify->signerHeader->email,
+ signerHeader->email, MAXSIGNERLEN-1);
+ strncpy(BLO_verify->signerHeader->homeUrl,
+ signerHeader->homeUrl, MAXSIGNERLEN-1);
+ strncpy(BLO_verify->signerHeader->text,
+ signerHeader->text, MAXSIGNERLEN-1);
+ strncpy(BLO_verify->signerHeader->pubKeyUrl1,
+ signerHeader->pubKeyUrl1, MAXSIGNERLEN-1);
+ strncpy(BLO_verify->signerHeader->pubKeyUrl2,
+ signerHeader->pubKeyUrl2, MAXSIGNERLEN-1);
+
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "name %s\nemail %s\nhomeUrl %s\ntext %s\n",
+ BLO_verify->signerHeader->name,
+ BLO_verify->signerHeader->email,
+ BLO_verify->signerHeader->homeUrl,
+ BLO_verify->signerHeader->text);
+ fprintf(GEN_errorstream,
+ "pubKeyUrl1 %s\npubKeyUrl2 %s\n",
+ BLO_verify->signerHeader->pubKeyUrl1,
+ BLO_verify->signerHeader->pubKeyUrl2);
+#endif
+ // also update the signature and crc checksum
+ RIPEMD160_Update(&(BLO_verify->ripemd160_ctx),
+ BLO_verify->signerHeaderBuffer,
+ SIGNERHEADERSTRUCTSIZE);
+
+ // update datacrc
+ BLO_verify->datacrc = crc32(
+ BLO_verify->datacrc, (const Bytef *)
+ BLO_verify->signerHeaderBuffer,
+ SIGNERHEADERSTRUCTSIZE);
+ }
+ }
+ }
+
+ /* Is there really (still) new data available ? */
+ if (dataIn > 0) {
+ RIPEMD160_Update(&(BLO_verify->ripemd160_ctx), data, dataIn);
+
+ // update datacrc
+ BLO_verify->datacrc = crc32(
+ BLO_verify->datacrc, (const Bytef *) data, dataIn);
+
+ BLO_verify->streamDone += dataIn;
+
+ // give data to streamGlueRead, it will find out what to do next
+ err = readStreamGlue(
+ BLO_verify->endControl,
+ &(BLO_verify->streamGlue),
+ (unsigned char *) data,
+ dataIn);
+ }
+ return err;
+}
+
+/**
+ * openssl verify final call and cleanup
+ * @param BLO_verify Pointer to verify control structure
+ * @retval streamGlueRead return value
+ */
+ int
+BLO_verify_end(
+ BLO_verifyStructHandle BLO_verifyHandle)
+{
+ int err = 0;
+ unsigned char *digest;
+ static unsigned char rsa_e[] = "\x01\x00\x01";
+ RSA *rsa = NULL;
+ int verifySuccess;
+ struct verifyStructType *BLO_verify =
+ (struct verifyStructType *) BLO_verifyHandle;
+
+ if (!BLO_verify) {
+ err = BRS_SETFUNCTION(BRS_VERIFY) |
+ BRS_SETGENERR(BRS_NULL);
+ return err;
+ }
+
+ if (BLO_verify->streamDone == BLO_verify->streamHeader->length +
+ SIGNVERIFYHEADERSTRUCTSIZE) {
+#ifndef NDEBUG
+ fprintf(GEN_errorstream, "Signed data length is correct\n");
+#endif
+ } else {
+#ifndef NDEBUG
+ fprintf(GEN_errorstream, "Signed data length is NOT correct\n");
+#endif
+ err = BRS_SETFUNCTION(BRS_VERIFY) |
+ BRS_SETGENERR(BRS_DATALEN);
+ if (BLO_verify->streamGlue) free(BLO_verify->streamGlue);
+ if (BLO_verify->streamHeader) free(BLO_verify->streamHeader);
+ if (BLO_verify->signerHeader) free(BLO_verify->signerHeader);
+ free(BLO_verify);
+ return err;
+ }
+
+ if (BLO_verify->datacrc == BLO_verify->streamHeader->datacrc) {
+#ifndef NDEBUG
+ fprintf(GEN_errorstream, "Signed data CRC is correct\n");
+#endif
+ } else {
+#ifndef NDEBUG
+ fprintf(GEN_errorstream, "Signed data CRC is NOT correct\n");
+#endif
+ err = BRS_SETFUNCTION(BRS_VERIFY) |
+ BRS_SETGENERR(BRS_CRCDATA);
+ if (BLO_verify->streamGlue) free(BLO_verify->streamGlue);
+ if (BLO_verify->streamHeader) free(BLO_verify->streamHeader);
+ if (BLO_verify->signerHeader) free(BLO_verify->signerHeader);
+ free(BLO_verify);
+ return err;
+ }
+
+ digest = malloc(RIPEMD160_DIGEST_LENGTH);
+ if (!digest) {
+ err = BRS_SETFUNCTION(BRS_VERIFY) |
+ BRS_SETGENERR(BRS_MALLOC);
+ if (BLO_verify->streamGlue) free(BLO_verify->streamGlue);
+ if (BLO_verify->streamHeader) free(BLO_verify->streamHeader);
+ if (BLO_verify->signerHeader) free(BLO_verify->signerHeader);
+ free(BLO_verify);
+ return err;
+ }
+
+ RIPEMD160_Final(digest, &(BLO_verify->ripemd160_ctx));
+
+ rsa = RSA_new();
+ if (rsa == NULL) {
+#ifndef NDEBUG
+ fprintf(GEN_errorstream, "Error in RSA_new\n");
+#endif
+ err = BRS_SETFUNCTION(BRS_VERIFY) |
+ BRS_SETSPECERR(BRS_RSANEWERROR);
+ free(digest);
+ if (BLO_verify->streamGlue) free(BLO_verify->streamGlue);
+ if (BLO_verify->streamHeader) free(BLO_verify->streamHeader);
+ if (BLO_verify->signerHeader) free(BLO_verify->signerHeader);
+ free(BLO_verify);
+ return err;
+ }
+ // static exponent
+ rsa->e = BN_bin2bn(rsa_e, sizeof(rsa_e)-1, rsa->e);
+
+ // public part into rsa->n
+ rsa->n = BN_bin2bn(BLO_verify->streamHeader->pubKey,
+ BLO_verify->streamHeader->pubKeyLen,
+ rsa->n);
+ //DEBUG RSA_print_fp(stdout, rsa, 0);
+
+ // verify the signature
+ verifySuccess = RSA_verify(NID_ripemd160, digest, RIPEMD160_DIGEST_LENGTH,
+ BLO_verify->streamHeader->signature,
+ BLO_verify->streamHeader->signatureLen, rsa);
+ if (verifySuccess == 1) {
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "Signature verified\n");
+#endif
+ } else {
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "Signature INCORRECT\n");
+#endif
+ err = BRS_SETFUNCTION(BRS_VERIFY) |
+ BRS_SETSPECERR(BRS_SIGFAILED);
+ }
+
+// copy signer information to external struct
+
+ strncpy(g_SignerInfo.name, BLO_verify->signerHeader->name, MAXSIGNERLEN-1);
+ strncpy(g_SignerInfo.email, BLO_verify->signerHeader->email, MAXSIGNERLEN-1);
+ strncpy(g_SignerInfo.homeUrl, BLO_verify->signerHeader->homeUrl, MAXSIGNERLEN-1);
+//
+ free(digest);
+ free(BLO_verify->streamGlue);
+ free(BLO_verify->streamHeader);
+ free(BLO_verify->signerHeader);
+ free(BLO_verify);
+ RSA_free(rsa);
+
+ return err;
+}
+
+struct BLO_SignerInfo *BLO_getSignerInfo(){
+ return &g_SignerInfo;
+}
+
+int BLO_isValidSignerInfo(struct BLO_SignerInfo *info){
+ return info->name[0] != 0;
+}
+
+void BLO_clrSignerInfo(struct BLO_SignerInfo *info)
+{
+ info->name[0] = 0;
+}
+
diff --git a/source/blender/verify/intern/Makefile b/source/blender/verify/intern/Makefile
new file mode 100644
index 00000000000..74430193c79
--- /dev/null
+++ b/source/blender/verify/intern/Makefile
@@ -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 *****
+#
+#
+
+LIBNAME = verify
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+ifeq ($(OS),$(findstring $(OS), "beos darwin freebsd linux openbsd solaris windows"))
+ CFLAGS += -funsigned-char
+endif
+
+CFLAGS += $(LEVEL_2_C_WARNINGS)
+
+# path to our own external headerfiles
+CPPFLAGS += -I..
+
+# external modules
+CPPFLAGS += -I../../../kernel/gen_messaging
+CPPFLAGS += -I../../readstreamglue
+
+CPPFLAGS += -I$(NAN_OPENSSL)/include
+
+ifeq ($(OS),$(findstring $(OS), "solaris windows"))
+ CPPFLAGS += -I$(NAN_ZLIB)/include
+endif
+
diff --git a/source/blender/writeblenfile/BLO_writeblenfile.h b/source/blender/writeblenfile/BLO_writeblenfile.h
new file mode 100644
index 00000000000..94c1b691017
--- /dev/null
+++ b/source/blender/writeblenfile/BLO_writeblenfile.h
@@ -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 *****
+ *
+ */
+
+#ifndef BLO_WRITEBLENFILE_H
+#define BLO_WRITEBLENFILE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ /**
+ * Writes a file from memory to disk. The filedescriptor of the
+ * targetfile is taken from mywfile.
+ *
+ * @param data pointer to the datachunk to write
+ * @param dataIn size of the datachunk to write (bytes)
+ * @param streamGlueHeader the eader describing this datachunk
+ * @returns 0 if the file was written correctly, non-0 if an error
+ * occured. */
+ int
+BLO_writeblenfile(
+ unsigned char *data,
+ unsigned int dataIn,
+ struct streamGlueHeaderStruct *streamGlueHeader);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BLO_WRITEBLENFILE_H */
diff --git a/source/blender/writeblenfile/Makefile b/source/blender/writeblenfile/Makefile
new file mode 100644
index 00000000000..2b8539af7c5
--- /dev/null
+++ b/source/blender/writeblenfile/Makefile
@@ -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 *****
+#
+# Bounces make to subdirectories.
+
+SOURCEDIR = source/blender/writeblenfile
+DIRS = intern
+
+include nan_subdirs.mk
diff --git a/source/blender/writeblenfile/intern/BLO_writeblenfile.c b/source/blender/writeblenfile/intern/BLO_writeblenfile.c
new file mode 100644
index 00000000000..f529bc5fa9e
--- /dev/null
+++ b/source/blender/writeblenfile/intern/BLO_writeblenfile.c
@@ -0,0 +1,348 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 <string.h> // strlen
+
+#ifdef _WIN32
+#include <io.h> // open / write
+#else // WIN32
+#include <unistd.h> // write
+#endif // WIN32
+
+#include <fcntl.h> // open
+
+#include "zlib.h"
+
+#include "GEN_messaging.h"
+
+#include "BLO_readfile.h"
+
+#include "BLO_writeStreamGlue.h"
+#include "BLO_writeblenfile.h"
+#include "BLO_readblenfile.h"
+
+// some systems don't have / support O_BINARY
+// on those systems we define it to 0
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+struct BLO_writeblenfileStruct {
+ struct writeStreamGlueStruct **streamGlue;
+ int fileDes;
+ unsigned int bufferSize;
+ unsigned int inBuffer;
+ char *writeBuffer;
+ int filestartoffset;
+ int filesizeoffset;
+};
+
+ int
+BLO_writeblenfile_process(
+ struct BLO_writeblenfileStruct *control,
+ unsigned char *data,
+ unsigned int dataIn);
+
+/**
+ * Flushes buffered data to file
+ * @param control structure holding all variables
+ * @return 0 on success, 1 if write failed
+ */
+
+static int flushbuffer(
+ struct BLO_writeblenfileStruct *control)
+{
+ int err = 0;
+ unsigned int written;
+
+ if (control->inBuffer) {
+ written = write(control->fileDes, control->writeBuffer, control->inBuffer);
+ if (written != control->inBuffer) {
+ err = BWS_SETFUNCTION(BWS_WRITEBLENFILE) |
+ BWS_SETSPECERR(BWS_WRITE);
+ } else {
+ control->inBuffer = 0;
+ }
+ }
+
+ return (err);
+}
+
+
+int BLO_writeblenfile(
+ unsigned char *data,
+ unsigned int dataIn,
+ struct streamGlueHeaderStruct *streamGlueHeader)
+{
+ static char *functionality_check= "\0FUNCTIONALITY_CHECK += BLO_writeblenfile\n";
+ struct BLO_writeblenfileStruct *writeblenfileStruct = 0;
+ int fileDes;
+ extern int mywfile;
+ int err = 0;
+ char minversion[4];
+ char version[4];
+ char flags[4];
+ unsigned int filesize;
+ char reserved[BLO_RESERVEDSIZE];
+
+ fileDes = mywfile;
+
+ if (fileDes == -1) {
+ /* The filedescriptor was bad: this is an internal error */
+ err = BWS_SETFUNCTION(BWS_WRITEBLENFILE) |
+ BWS_SETSPECERR(BWS_FILEDES);
+ return err;
+ }
+
+ writeblenfileStruct = calloc(1, sizeof(struct BLO_writeblenfileStruct));
+ if (!writeblenfileStruct) {
+ err = BWS_SETFUNCTION(BWS_WRITEBLENFILE) |
+ BWS_SETGENERR(BWS_MALLOC);
+ return err;
+ }
+
+ writeblenfileStruct->bufferSize = 100000;
+ writeblenfileStruct->writeBuffer = malloc(writeblenfileStruct->bufferSize);
+ if (!writeblenfileStruct->writeBuffer) {
+ err = BWS_SETFUNCTION(BWS_WRITEBLENFILE) |
+ BWS_SETGENERR(BWS_MALLOC);
+ return err;
+ }
+
+ writeblenfileStruct->fileDes = fileDes;
+ writeblenfileStruct->filestartoffset = lseek(fileDes, 0, SEEK_CUR);
+
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "BLO_writeblenfile writes headerMagic ...\n");
+#endif
+
+ // write our own magic fileheader
+ err = BLO_writeblenfile_process(writeblenfileStruct,
+ headerMagic,
+ strlen(headerMagic));
+ if (err) {
+ free(writeblenfileStruct->writeBuffer);
+ free(writeblenfileStruct);
+ return err;
+ }
+
+ // write out the '\n' that we use for the
+ // cr / nl conversion
+ err = BLO_writeblenfile_process(writeblenfileStruct,
+ "\n",
+ 1);
+ if (err) {
+ free(writeblenfileStruct->writeBuffer);
+ free(writeblenfileStruct);
+ return err;
+ }
+
+ BLO_setversionnumber(minversion, 221);
+ err = BLO_writeblenfile_process(writeblenfileStruct,
+ minversion,
+ sizeof(minversion));
+ if (err) {
+ free(writeblenfileStruct->writeBuffer);
+ free(writeblenfileStruct);
+ return err;
+ }
+
+ BLO_setcurrentversionnumber(version);
+ err = BLO_writeblenfile_process(writeblenfileStruct,
+ version,
+ sizeof(version));
+ if (err) {
+ free(writeblenfileStruct->writeBuffer);
+ free(writeblenfileStruct);
+ return err;
+ }
+
+ memset(flags, 0, sizeof(flags));
+ err = BLO_writeblenfile_process(writeblenfileStruct,
+ flags,
+ sizeof(flags));
+ if (err) {
+ free(writeblenfileStruct->writeBuffer);
+ free(writeblenfileStruct);
+ return err;
+ }
+
+ // we'll have to write out the filesize in the end
+ // remember the location in the file but make sure to
+ // flush all cached data first...
+
+ flushbuffer(writeblenfileStruct);
+ writeblenfileStruct->filesizeoffset = lseek(fileDes, 0, SEEK_CUR);
+ memset(&filesize, 0, sizeof(filesize));
+ err = BLO_writeblenfile_process(writeblenfileStruct,
+ &filesize,
+ sizeof(filesize));
+ if (err) {
+ free(writeblenfileStruct->writeBuffer);
+ free(writeblenfileStruct);
+ return err;
+ }
+
+ memset(reserved, 0, sizeof(reserved));
+ err = BLO_writeblenfile_process(writeblenfileStruct,
+ reserved,
+ sizeof(reserved));
+ if (err) {
+ free(writeblenfileStruct->writeBuffer);
+ free(writeblenfileStruct);
+ return err;
+ }
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "BLO_writeblenfile writes streamGlueHeader of %u bytes\n",
+ STREAMGLUEHEADERSIZE);
+#endif
+
+ // Update streamGlueHeader that initiated us and write it away
+ // Note that streamGlueHeader is *behind* the magic fileheader
+ streamGlueHeader->totalStreamLength = htonl(0 + dataIn);
+ streamGlueHeader->crc = htonl(crc32(0L,
+ (const Bytef *) streamGlueHeader, STREAMGLUEHEADERSIZE - 4));
+ err = BLO_writeblenfile_process(writeblenfileStruct,
+ (unsigned char *) streamGlueHeader,
+ STREAMGLUEHEADERSIZE);
+ if (err) {
+ free(writeblenfileStruct->writeBuffer);
+ free(writeblenfileStruct);
+ return err;
+ }
+
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "BLO_writeblenfile writes %u bytes raw data\n",
+ dataIn);
+#endif
+
+ // write raw data
+ err = BLO_writeblenfile_process(writeblenfileStruct,
+ data,
+ dataIn);
+ if (err) {
+ free(writeblenfileStruct->writeBuffer);
+ free(writeblenfileStruct);
+ return err;
+ }
+
+ err = flushbuffer(writeblenfileStruct);
+ if (err) {
+ free(writeblenfileStruct->writeBuffer);
+ free(writeblenfileStruct);
+ return err;
+ }
+
+ // write filesize in header
+ // calculate filesize
+ filesize = lseek(fileDes, 0, SEEK_CUR);
+ filesize -= writeblenfileStruct->filestartoffset;
+
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "BLO_writeblenfile total file size %u bytes\n",
+ filesize);
+#endif
+
+ // TODO There should be error catching here as well.
+ // goto filesize location in file
+ lseek(fileDes, writeblenfileStruct->filesizeoffset, SEEK_SET);
+ // and write out filesize in network byte order
+ filesize = htonl(filesize);
+ write(fileDes, &filesize, sizeof(filesize));
+ // seek to end of file to cover up our tracks
+ lseek(fileDes, 0, SEEK_END);
+
+ // clean up
+ free(writeblenfileStruct->writeBuffer);
+ free(writeblenfileStruct);
+
+ return (err);
+}
+
+/**
+ * Buffers data and writes it to disk when necessary
+ * @param control structure holding all variables
+ * @param dataIn Length of new chunk of data
+ * @param data Pointer to new chunk of data
+ */
+ int
+BLO_writeblenfile_process(
+ struct BLO_writeblenfileStruct *control,
+ unsigned char *data,
+ unsigned int dataIn)
+{
+ int err = 0;
+ unsigned int written;
+
+ if (control && data) {
+ if (dataIn) {
+ // do we need to flush data ?
+ if ((dataIn + control->inBuffer) > control->bufferSize) {
+ err = flushbuffer(control);
+ }
+
+ if (! err) {
+ // do we now have enough space in the buffer ?
+ if ((dataIn + control->inBuffer) <= control->bufferSize) {
+ // yes, just copy it to the buffer
+ memcpy(control->writeBuffer + control->inBuffer, data, dataIn);
+ control->inBuffer += dataIn;
+ } else {
+ // write data out immediately
+ written = write(control->fileDes, data, dataIn);
+ if (written != dataIn) {
+ err = BWS_SETFUNCTION(BWS_WRITEBLENFILE) |
+ BWS_SETSPECERR(BWS_WRITE);
+ }
+ }
+ }
+ }
+ } else {
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "BLO_writeblenfile_process: invalid parameters\n");
+#endif
+ err = BWS_SETFUNCTION(BWS_WRITEBLENFILE) |
+ BWS_SETSPECERR(BWS_PARAM);
+ }
+
+ return err;
+}
+
diff --git a/source/blender/writeblenfile/intern/Makefile b/source/blender/writeblenfile/intern/Makefile
new file mode 100644
index 00000000000..e5ac144195f
--- /dev/null
+++ b/source/blender/writeblenfile/intern/Makefile
@@ -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 *****
+#
+#
+
+LIBNAME = writeblenfile
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+ifeq ($(OS),$(findstring $(OS), "beos darwin freebsd linux openbsd solaris windows"))
+ CFLAGS += -funsigned-char
+endif
+
+CFLAGS += $(LEVEL_2_C_WARNINGS)
+
+ifeq ($(OS),$(findstring $(OS), "solaris windows"))
+ CPPFLAGS += -I$(NAN_ZLIB)/include
+endif
+
+# path to our own external headerfiles
+CPPFLAGS += -I..
+
+# external modules
+CPPFLAGS += -I../../../kernel/gen_messaging
+CPPFLAGS += -I../../writestreamglue
+CPPFLAGS += -I../../readstreamglue
+CPPFLAGS += -I../../readblenfile
+CPPFLAGS += -I../../blenloader
+
diff --git a/source/blender/writeblenfile/test/Makefile b/source/blender/writeblenfile/test/Makefile
new file mode 100644
index 00000000000..fe07aa8c9b4
--- /dev/null
+++ b/source/blender/writeblenfile/test/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 *****
+#
+#
+
+LIBNAME = writeblenfile
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+ALLTARGETS = $(OBJS) $(DIR)/$(DEBUG_DIR)test$(EXT)
+
+include nan_compile.mk
+
+ifeq ($(OS),$(findstring $(OS), "beos darwin freebsd linux openbsd solaris windows"))
+ CFLAGS += -funsigned-char
+endif
+
+CFLAGS += $(LEVEL_2_C_WARNINGS)
+
+# path to our own external headerfiles
+CPPFLAGS += -I..
+CPPFLAGS += -I../../streamglue
+
+# TODO include right .mk for ldflags
+$(DIR)/$(DEBUG_DIR)test$(EXT): $(OBJS) ../intern/BLO_writeblenfile.c
+ $(CC) $(LDFLAGS) -o $@ $(OBJS) $(OCGDIR)/blender/writeblenfile/$(DEBUG_DIR)libwriteblenfile.a
+ $(DIR)/$(DEBUG_DIR)test$(EXT)
+
diff --git a/source/blender/writeblenfile/test/test.c b/source/blender/writeblenfile/test/test.c
new file mode 100644
index 00000000000..5dd560e0742
--- /dev/null
+++ b/source/blender/writeblenfile/test/test.c
@@ -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 *****
+ */
+#include <string.h> // strlen
+#include "BLO_writeblenfile.h"
+
+main()
+{
+ struct BLO_writeblenfileStruct *control;
+ char *string = "Hello world";
+
+
+ control = BLO_writeblenfile_begin();
+ BLO_writeblenfile_process(control, string, strlen(string));
+ BLO_writeblenfile_end(control);
+}
diff --git a/source/blender/writestreamglue/BLO_getPubKey.h b/source/blender/writestreamglue/BLO_getPubKey.h
new file mode 100644
index 00000000000..5dc0d9e0547
--- /dev/null
+++ b/source/blender/writestreamglue/BLO_getPubKey.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 *****
+ * PUBLISHER: get the public key from the .BPkeyfile
+ * STUB: give back the dataStreamPubKey
+ */
+
+ int
+getPubKey(byte *dataStreamPubKey,
+ int dataStreamPubKeyLen,
+ byte **publisherPubKey,
+ int *publisherPubKeyLen);
+
diff --git a/source/blender/writestreamglue/BLO_writeStreamErrors.h b/source/blender/writestreamglue/BLO_writeStreamErrors.h
new file mode 100644
index 00000000000..ce8464b75ce
--- /dev/null
+++ b/source/blender/writestreamglue/BLO_writeStreamErrors.h
@@ -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 *****
+ * all Blender Write Stream errors
+ * NOTE: adding stuff here means you also have to update the error
+ * messages in writefile.c
+ */
+
+#ifndef BLO_WRITESTREAMERRORS_H
+#define BLO_WRITESTREAMERRORS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define BWS_SETFUNCTION(x) ( (int)(x) << 1)
+#define BWS_GETFUNCTION(x) (( (int)(x) >> 1) & 7)
+#define BWS_SETGENERR(x) ( (int)(x) << 4)
+#define BWS_GETGENERR(x) (( (int)(x) >> 4) & 7)
+#define BWS_SETSPECERR(x) ( (int)(x) << 7)
+#define BWS_GETSPECERR(x) (( (int)(x) >> 7) & 7)
+
+// FUNCTION
+#define BWS_WRITESTREAMGLUE 1
+#define BWS_DEFLATE 2
+#define BWS_ENCRYPT 3
+#define BWS_SIGN 4
+#define BWS_WRITEBLENFILE 5
+
+// GENeric errors
+#define BWS_MALLOC 1
+#define BWS_STUB 2
+#define BWS_RSA 3
+
+// WRITESTREAMGLUE specific
+#define BWS_UNKNOWN 1
+
+// DEFLATE specific
+#define BWS_DEFLATEERROR 1
+
+// ENCRYPT specific
+#define BWS_RSANEWERROR 1
+#define BWS_ENCRYPTERROR 2
+
+// SIGN specific
+#define BWS_RSANEWERROR 1
+#define BWS_SIGNERROR 2
+
+// WRITEBLENFILE specific
+#define BWS_FILEDES 1
+#define BWS_WRITE 2
+#define BWS_PARAM 3
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BLO_WRITESTREAMERRORS_H */
diff --git a/source/blender/writestreamglue/BLO_writeStreamGlue.h b/source/blender/writestreamglue/BLO_writeStreamGlue.h
new file mode 100644
index 00000000000..6a160f3b505
--- /dev/null
+++ b/source/blender/writestreamglue/BLO_writeStreamGlue.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 *****
+ * struct/function that connects the data stream processors
+ */
+
+#ifndef BLO_WRITESTREAMGLUE_H
+#define BLO_WRITESTREAMGLUE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "BLO_readStreamGlue.h"
+#include "BLO_writeStreamErrors.h"
+
+/******************** start BLO_streamGlueControl.c part *****************/
+struct streamGlueControlStruct {
+ int actions;
+ int actionsDone;
+ unsigned char action[MAXSTREAMLENGTH];
+};
+
+ struct streamGlueControlStruct *
+streamGlueControlConstructor(
+ void);
+
+ void
+streamGlueControlDestructor(
+ struct streamGlueControlStruct *streamControl);
+
+ int
+streamGlueControlAppendAction(
+ struct streamGlueControlStruct *streamControl,
+ unsigned char nextAction);
+
+ unsigned char
+streamGlueControlGetNextAction(
+ struct streamGlueControlStruct *streamControl);
+
+// TODO avoid this global variable
+extern struct streamGlueControlStruct *Global_streamGlueControl;
+/******************** end BLO_streamGlueControl.c part *****************/
+
+struct writeStreamGlueStruct {
+ int dataProcessorType;
+ unsigned int streamBufferCount;
+ unsigned char *streamBuffer;
+};
+
+ int
+writeStreamGlue(
+ struct streamGlueControlStruct *streamGlueControl,
+ struct writeStreamGlueStruct **streamGlue,
+ unsigned char *data,
+ unsigned int dataIn,
+ int finishUp);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BLO_WRITESTREAMGLUE_H */
diff --git a/source/blender/writestreamglue/Makefile b/source/blender/writestreamglue/Makefile
new file mode 100644
index 00000000000..22f3adb345e
--- /dev/null
+++ b/source/blender/writestreamglue/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.
+
+SOURCEDIR = source/blender/writestreamglue
+DIRS = intern stub
+TESTDIRS = test
+
+include nan_subdirs.mk
diff --git a/source/blender/writestreamglue/intern/BLO_dumpFromMemory.c b/source/blender/writestreamglue/intern/BLO_dumpFromMemory.c
new file mode 100644
index 00000000000..f132840572a
--- /dev/null
+++ b/source/blender/writestreamglue/intern/BLO_dumpFromMemory.c
@@ -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 *****
+ * streamglue loopback adds a streamGlueHeader to start of the write stream
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "GEN_messaging.h"
+
+#include "zlib.h"
+
+#include "BLO_writeStreamGlue.h"
+
+#include "BLO_dumpFromMemory.h"
+
+ int
+BLO_dumpFromMemory(
+ unsigned char *data,
+ unsigned int dataIn,
+ struct streamGlueHeaderStruct *streamGlueHeader)
+{
+ struct writeStreamGlueStruct *streamGlue = NULL;
+ int err = 0;
+
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "BLO_dumpFromMemory: %u streamGlueHeader + %u data = %u\n",
+ STREAMGLUEHEADERSIZE,
+ dataIn,
+ STREAMGLUEHEADERSIZE + dataIn);
+#endif
+
+ // all data is in. set size in streamGlueHeader and write it out
+ streamGlueHeader->totalStreamLength = htonl(dataIn);
+ streamGlueHeader->crc = htonl(crc32(0L, (const Bytef *) streamGlueHeader,
+ STREAMGLUEHEADERSIZE - 4));
+ err = writeStreamGlue(
+ Global_streamGlueControl,
+ &streamGlue,
+ (unsigned char *)streamGlueHeader,
+ STREAMGLUEHEADERSIZE,
+ 0);
+ if (err) return err;
+
+ // write out data
+ err = writeStreamGlue(
+ Global_streamGlueControl,
+ &streamGlue,
+ data,
+ dataIn,
+ 1);
+
+ return err;
+}
+
diff --git a/source/blender/writestreamglue/intern/BLO_dumpFromMemory.h b/source/blender/writestreamglue/intern/BLO_dumpFromMemory.h
new file mode 100644
index 00000000000..cb418f67f01
--- /dev/null
+++ b/source/blender/writestreamglue/intern/BLO_dumpFromMemory.h
@@ -0,0 +1,39 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * streamglue loopback adds a streamGlueHeader to start of the write stream
+ */
+
+ int
+BLO_dumpFromMemory(
+ unsigned char *data,
+ unsigned int dataIn,
+ struct streamGlueHeaderStruct *streamGlueHeader);
+
diff --git a/source/blender/writestreamglue/intern/BLO_getPubKey.c b/source/blender/writestreamglue/intern/BLO_getPubKey.c
new file mode 100644
index 00000000000..d691c0ae2be
--- /dev/null
+++ b/source/blender/writestreamglue/intern/BLO_getPubKey.c
@@ -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 *****
+ * Publisher only: get the public key from the .BPkeyfile
+ */
+
+#include <stdlib.h>
+
+#include "BLO_keyStore.h"
+#include "BLO_getPubKey.h"
+
+ int
+getPubKey(byte *dataStreamPubKey,
+ int dataStreamPubKeyLen,
+ byte **publisherPubKey,
+ int *publisherPubKeyLen)
+{
+ int err = 0;
+
+ *publisherPubKeyLen = keyStoreGetPubKey(publisherPubKey);
+
+ if (*publisherPubKeyLen == 0) {
+ // we're a publisher without .BPkey
+ *publisherPubKey = NULL;
+ return 1;
+ }
+
+ if (dataStreamPubKeyLen != *publisherPubKeyLen) {
+ // different keys
+ *publisherPubKeyLen = 0;
+ *publisherPubKey = NULL;
+ return 2;
+ }
+
+ if (memcmp(dataStreamPubKey, *publisherPubKey, *publisherPubKeyLen)
+ != 0) {
+ // different keys
+ *publisherPubKeyLen = 0;
+ *publisherPubKey = NULL;
+ return 3;
+ }
+
+ return err;
+}
+
diff --git a/source/blender/writestreamglue/intern/BLO_streamGlueControl.c b/source/blender/writestreamglue/intern/BLO_streamGlueControl.c
new file mode 100644
index 00000000000..fc12738fa35
--- /dev/null
+++ b/source/blender/writestreamglue/intern/BLO_streamGlueControl.c
@@ -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 *****
+ * define what actions a write stream should do
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "BLO_writeStreamGlue.h"
+
+ struct streamGlueControlStruct *
+streamGlueControlConstructor(
+ void)
+{
+ struct streamGlueControlStruct *control;
+ control = malloc(sizeof(struct streamGlueControlStruct));
+ assert(control);
+ // TODO handle malloc errors
+ control->actions = 0;
+ control->actionsDone = 0;
+ memset(control->action, 0, MAXSTREAMLENGTH);
+ return(control);
+}
+
+ void
+streamGlueControlDestructor(
+ struct streamGlueControlStruct *streamControl)
+{
+ free(streamControl);
+}
+
+ int
+streamGlueControlAppendAction(
+ struct streamGlueControlStruct *streamControl,
+ unsigned char nextAction)
+{
+ assert(streamControl);
+ assert(streamControl->actions < MAXSTREAMLENGTH);
+ streamControl->action[streamControl->actions] = nextAction;
+ streamControl->actions++;
+ return(streamControl->actions);
+}
+
+ unsigned char
+streamGlueControlGetNextAction(
+ struct streamGlueControlStruct *streamControl)
+{
+ unsigned char nextAction;
+ assert(streamControl);
+ assert(streamControl->actionsDone < streamControl->actions);
+ if (streamControl->actionsDone >= streamControl->actions) {
+ // the stream should have been terminated by a data
+ // processor, but instead streamGlue is called again ...
+ nextAction = UNKNOWN; // best guess ...
+ } else {
+ nextAction = streamControl->action[streamControl->actionsDone];
+ streamControl->actionsDone++;
+ }
+ return(nextAction);
+}
+
diff --git a/source/blender/writestreamglue/intern/BLO_writeStreamGlue.c b/source/blender/writestreamglue/intern/BLO_writeStreamGlue.c
new file mode 100644
index 00000000000..934cbb91004
--- /dev/null
+++ b/source/blender/writestreamglue/intern/BLO_writeStreamGlue.c
@@ -0,0 +1,170 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * connect the data stream processors
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "zlib.h"
+
+#include "GEN_messaging.h"
+
+#include "BLO_writeStreamGlue.h"
+
+#include "BLO_dumpFromMemory.h"
+
+#include "BLO_writeblenfile.h"
+#include "BLO_deflate.h"
+#include "BLO_encrypt.h"
+#include "BLO_sign.h"
+
+/**
+ * streamGlueWrite does not really stream; it buffers all data it gets
+ * because it needs everything to create the header, which is in front
+ * of the data (to make reading easier, which occurs much more often
+ * than writing and is thus more important to optimize for).
+ * @param streamControl contains a list of Glue actions. Every
+ * streamGlueWrite constructor eats up the next first action.
+ */
+ int
+writeStreamGlue(
+ struct streamGlueControlStruct *streamGlueControl,
+ struct writeStreamGlueStruct **streamGlue,
+ unsigned char *data,
+ unsigned int dataIn,
+ int finishUp)
+{
+ int err = 0;
+
+ if (NULL == *streamGlue) {
+ /* we are called for the first time; play constructor */
+ (*streamGlue) = malloc(sizeof(struct writeStreamGlueStruct));
+
+ if (!(*streamGlue)) {
+ err = BWS_SETFUNCTION(BWS_WRITESTREAMGLUE) |
+ BWS_SETGENERR(BWS_MALLOC);
+ return err;
+ }
+
+ (*streamGlue)->dataProcessorType =
+ streamGlueControlGetNextAction(streamGlueControl);
+ (*streamGlue)->streamBufferCount = 0;
+ (*streamGlue)->streamBuffer = NULL;
+ }
+ if (dataIn > 0) {
+ /* simply buffer it */
+ (*streamGlue)->streamBuffer = realloc((*streamGlue)->streamBuffer,
+ dataIn + (*streamGlue)->streamBufferCount);
+ if (!(*streamGlue)->streamBuffer) {
+ err = BWS_SETFUNCTION(BWS_WRITESTREAMGLUE) |
+ BWS_SETGENERR(BWS_MALLOC);
+ free(*streamGlue);
+ return err;
+ }
+ memcpy((*streamGlue)->streamBuffer + (*streamGlue)->streamBufferCount,
+ data, dataIn);
+ (*streamGlue)->streamBufferCount += dataIn;
+ }
+ if (finishUp) {
+ /* all data is in, create header and call data processor */
+
+ /* first create the streamGlueHeaderStruct */
+ struct streamGlueHeaderStruct *streamGlueHeader;
+ streamGlueHeader = malloc(STREAMGLUEHEADERSIZE);
+ if (!streamGlueHeader) {
+ err = BWS_SETFUNCTION(BWS_WRITESTREAMGLUE) |
+ BWS_SETGENERR(BWS_MALLOC);
+ free((*streamGlue)->streamBuffer);
+ free(*streamGlue);
+ return err;
+ }
+ streamGlueHeader->magic = 'A';
+ streamGlueHeader->totalStreamLength = 0; // set in the actions _end
+ streamGlueHeader->dataProcessorType =
+ htonl((*streamGlue)->dataProcessorType);
+ streamGlueHeader->crc = 0; // set in in the actions _end
+
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "streamGlue: write %d gets %u data + %u streamGlueHeader = %u\n",
+ (*streamGlue)->dataProcessorType,
+ (*streamGlue)->streamBufferCount,
+ STREAMGLUEHEADERSIZE,
+ (*streamGlue)->streamBufferCount + STREAMGLUEHEADERSIZE);
+#endif
+
+ /* all data ready, start the right data processor */
+ switch ((*streamGlue)->dataProcessorType) {
+ case DUMPFROMMEMORY:
+ err = BLO_dumpFromMemory((*streamGlue)->streamBuffer,
+ (*streamGlue)->streamBufferCount,
+ streamGlueHeader);
+ break;
+ case DEFLATE:
+ err = BLO_deflate((*streamGlue)->streamBuffer,
+ (*streamGlue)->streamBufferCount,
+ streamGlueHeader);
+ break;
+ case ENCRYPT:
+ err = BLO_encrypt((*streamGlue)->streamBuffer,
+ (*streamGlue)->streamBufferCount,
+ streamGlueHeader);
+ break;
+ case SIGN:
+ err = BLO_sign((*streamGlue)->streamBuffer,
+ (*streamGlue)->streamBufferCount,
+ streamGlueHeader);
+ break;
+ case WRITEBLENFILE:
+ err = BLO_writeblenfile((*streamGlue)->streamBuffer,
+ (*streamGlue)->streamBufferCount,
+ streamGlueHeader);
+ break;
+ default:
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "unknown dataProcessorType %d\n",
+ (*streamGlue)->dataProcessorType);
+#endif
+ err = BWS_SETFUNCTION(BWS_WRITESTREAMGLUE) |
+ BWS_SETSPECERR(BWS_UNKNOWN);
+ break;
+ }
+
+ free(streamGlueHeader);
+ free((*streamGlue)->streamBuffer);
+ free(*streamGlue);
+ }
+ return err;
+}
+
diff --git a/source/blender/writestreamglue/intern/Makefile b/source/blender/writestreamglue/intern/Makefile
new file mode 100644
index 00000000000..df3f88ea006
--- /dev/null
+++ b/source/blender/writestreamglue/intern/Makefile
@@ -0,0 +1,71 @@
+#
+# $Id$
+#
+# ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version. The Blender
+# Foundation also sells licenses for use in proprietary software under
+# the Blender License. See http://www.blender.org/BL/ for information
+# about this.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2001-2002 by 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 = writestreamglue
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+ifeq ($(OS),$(findstring $(OS), "beos darwin freebsd linux openbsd solaris windows"))
+ CFLAGS += -funsigned-char
+endif
+
+CFLAGS += $(LEVEL_2_C_WARNINGS)
+
+# path to our own private header files
+CPPFLAGS += -I.
+
+# path to our own external header files
+CPPFLAGS += -I..
+
+# path to external modules
+CPPFLAGS += -I../../../kernel/gen_messaging
+
+CPPFLAGS += -I../../readstreamglue
+
+CPPFLAGS += -I../../writeblenfile
+CPPFLAGS += -I../../blenloader
+
+CPPFLAGS += -I../../deflate
+CPPFLAGS += -I../../encrypt
+CPPFLAGS += -I../../sign
+
+CPPFLAGS += -I$(NAN_OPENSSL)/include
+
+#TODO make keystore this a seperate lib
+CPPFLAGS += -I$(NAN_BLENKEY)/include
+
+ifeq ($(OS),$(findstring $(OS), "solaris windows"))
+ CPPFLAGS += -I$(NAN_ZLIB)/include
+endif
+
diff --git a/source/blender/writestreamglue/stub/BLO_getPubKeySTUB.c b/source/blender/writestreamglue/stub/BLO_getPubKeySTUB.c
new file mode 100644
index 00000000000..86cdfdacd69
--- /dev/null
+++ b/source/blender/writestreamglue/stub/BLO_getPubKeySTUB.c
@@ -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 *****
+ * player/plugin only: 'get' the public key from the datastream
+ * note really a STUB eh ...
+ */
+
+#include "blenkey.h" // for byte ... duh this needs change !
+#include "BLO_getPubKey.h"
+
+ int
+getPubKey(byte *dataStreamPubKey,
+ int dataStreamPubKeyLen,
+ byte **publisherPubKey,
+ int *publisherPubKeyLen)
+{
+ int err = 0;
+
+ *publisherPubKeyLen = dataStreamPubKeyLen;
+ *publisherPubKey = dataStreamPubKey;
+
+ return err;
+}
+
diff --git a/source/blender/writestreamglue/stub/BLO_keyStoreSTUB.c b/source/blender/writestreamglue/stub/BLO_keyStoreSTUB.c
new file mode 100644
index 00000000000..2cf118d8e5e
--- /dev/null
+++ b/source/blender/writestreamglue/stub/BLO_keyStoreSTUB.c
@@ -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 *****
+ * keyStore stubs
+ */
+
+#include <stdio.h>
+
+#include "BLO_keyStore.h"
+
+ void
+keyStoreConstructor(
+ UserStruct *keyUserStruct,
+ char *privHexKey,
+ char *pubHexKey,
+ byte *ByteChecks,
+ char *HexPython)
+{
+ keyUserStruct = NULL;
+ privHexKey = NULL;
+ pubHexKey = NULL;
+ ByteChecks = NULL;
+ HexPython = NULL;
+}
+
+ void
+keyStoreDestructor(
+ void)
+{
+}
+
diff --git a/source/blender/writestreamglue/stub/BLO_streamGlueControlSTUB.c b/source/blender/writestreamglue/stub/BLO_streamGlueControlSTUB.c
new file mode 100644
index 00000000000..5c4b5794e76
--- /dev/null
+++ b/source/blender/writestreamglue/stub/BLO_streamGlueControlSTUB.c
@@ -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 *****
+ *
+ */
+
+#include <stdio.h>
+
+#include "GEN_messaging.h"
+
+#include "BLO_writeStreamGlue.h"
+
+ struct streamGlueControlStruct *
+streamGlueControlConstructor(
+ void)
+{
+#ifdef NDEBUG
+ fprintf(GEN_errorstream,
+ "Error streamGlueControlConstructor is a stub\n");
+#endif
+ return(NULL);
+}
+
+ void
+streamGlueControlDestructor(
+ struct streamGlueControlStruct *streamControl)
+{
+ streamControl = NULL;
+#ifdef NDEBUG
+ fprintf(GEN_errorstream,
+ "Error streamGlueControlDestructor is a stub\n");
+#endif
+}
+
+ int
+streamGlueControlAppendAction(
+ struct streamGlueControlStruct *streamControl,
+ unsigned char nextAction)
+{
+ streamControl = NULL;
+ nextAction = 0;
+#ifdef NDEBUG
+ fprintf(GEN_errorstream,
+ "Error streamGlueControlAppendAction is a stub\n");
+#endif
+ return(0);
+}
+
+ unsigned char
+streamGlueControlGetNextAction(
+ struct streamGlueControlStruct *streamControl)
+{
+ streamControl = NULL;
+#ifdef NDEBUG
+ fprintf(GEN_errorstream,
+ "Error streamGlueControlGetNextAction is a stub\n");
+#endif
+ return(0);
+}
+
diff --git a/source/blender/writestreamglue/stub/BLO_writeStreamGlueSTUB.c b/source/blender/writestreamglue/stub/BLO_writeStreamGlueSTUB.c
new file mode 100644
index 00000000000..9b077efbd59
--- /dev/null
+++ b/source/blender/writestreamglue/stub/BLO_writeStreamGlueSTUB.c
@@ -0,0 +1,61 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * streamGlueRead stubs
+ */
+
+#include <stdio.h>
+
+#include "GEN_messaging.h"
+#include "BLO_writeStreamGlue.h"
+
+ int
+writeStreamGlue(
+ struct streamGlueControlStruct *streamGlueControl,
+ struct writeStreamGlueStruct **streamGlue,
+ unsigned char *data,
+ unsigned int dataIn,
+ int finishUp)
+{
+ int err = 0;
+ streamGlueControl = NULL;
+ *streamGlue = NULL;
+ data = NULL;
+ dataIn = 0;
+ finishUp = 0;
+#ifndef NDEBUG
+ fprintf(GEN_errorstream,
+ "Error writeStreamGlue is a stub\n");
+#endif
+ err = BWS_SETFUNCTION(BWS_WRITESTREAMGLUE) |
+ BWS_SETGENERR(BWS_STUB);
+ return err;
+}
+
diff --git a/source/blender/writestreamglue/stub/Makefile b/source/blender/writestreamglue/stub/Makefile
new file mode 100644
index 00000000000..54633d289ad
--- /dev/null
+++ b/source/blender/writestreamglue/stub/Makefile
@@ -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 *****
+#
+#
+
+LIBNAME = writestreamglueSTUB
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+ifeq ($(OS),$(findstring $(OS), "beos darwin freebsd linux openbsd solaris windows"))
+ CFLAGS += -funsigned-char
+endif
+
+CFLAGS += $(LEVEL_2_C_WARNINGS)
+
+# path to our own external headerfiles
+CPPFLAGS += -I..
+
+#
+CPPFLAGS += -I../../../kernel/gen_messaging
+CPPFLAGS += -I../../readstreamglue
+
+#TODO make this a seperate lib
+CPPFLAGS += -I$(NAN_BLENKEY)/include
+
+ifeq ($(OS),$(findstring $(OS), "solaris windows"))
+ CPPFLAGS += -I$(NAN_ZLIB)/include
+endif
+
diff --git a/source/blender/writestreamglue/test/Makefile b/source/blender/writestreamglue/test/Makefile
new file mode 100644
index 00000000000..ee2708e55ff
--- /dev/null
+++ b/source/blender/writestreamglue/test/Makefile
@@ -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 *****
+#
+# Bounces make to subdirectories.
+
+SOURCEDIR = source/blender/writestreamglue/test
+DIRS = typetest #readwritetest
+
+include nan_subdirs.mk
diff --git a/source/blender/writestreamglue/test/readwritetest/Makefile b/source/blender/writestreamglue/test/readwritetest/Makefile
new file mode 100644
index 00000000000..ddd27ba9e18
--- /dev/null
+++ b/source/blender/writestreamglue/test/readwritetest/Makefile
@@ -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 *****
+#
+# Streamglue read/write testing
+#
+
+DIR = $(OCGDIR)/blender/writestreamglue/readwritetest
+ALLTARGETS = $(OBJS) $(DIR)/$(DEBUG_DIR)readwritetest
+
+include nan_compile.mk
+
+CFLAGS += -funsigned-char -g
+
+# includes:
+CPPFLAGS += -I../..
+CPPFLAGS += -I../../../readstreamglue
+
+# libs:
+TESTLIBS += $(OCGDIR)/blender/readstreamglue/$(DEBUG_DIR)libreadstreamglue.a
+TESTLIBS += $(OCGDIR)/blender/writestreamglue/$(DEBUG_DIR)libwritestreamglue.a
+TESTLIBS += $(OCGDIR)/blender/inflate/$(DEBUG_DIR)libinflate.a
+TESTLIBS += $(OCGDIR)/blender/deflate/$(DEBUG_DIR)libdeflate.a
+TESTLIBS += $(OCGDIR)/blender/encrypt/$(DEBUG_DIR)libencrypt.a
+TESTLIBS += $(OCGDIR)/blender/decrypt/$(DEBUG_DIR)libdecrypt.a
+TESTLIBS += $(OCGDIR)/blender/sign/$(DEBUG_DIR)libsign.a
+TESTLIBS += $(OCGDIR)/blender/verify/$(DEBUG_DIR)libverify.a
+TESTLIBS += $(OCGDIR)/blender/writeblenfile/$(DEBUG_DIR)libwriteblenfile.a
+TESTLIBS += $(OCGDIR)/blender/writestreamglue/$(DEBUG_DIR)libwritestreamglue.a
+TESTLIBS += $(OCGDIR)/blender/readstreamglue/$(DEBUG_DIR)libreadstreamglue.a
+TESTLIBS += $(NAN_BLENKEY)/lib/libblenkey.a
+TESTLIBS += $(OCGDIR)/blender/readblenfile/$(DEBUG_DIR)libreadblenfile.a
+
+ifeq ($(OS),$(findstring $(OS), "linux freebsd"))
+ TESTLIBS += -lz
+ TESTLIBS += $(NAN_OPENSSL)/lib/libcrypto.a
+endif
+
+ifeq ($(OS),windows)
+ TESTLIBS += ws2_32.lib
+ TESTLIBS += $(NAN_ZLIB)/lib/libz.a
+ TESTLIBS += $(NAN_OPENSSL)/lib/libeay32.lib
+ TESTLIBS += kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib
+ TESTLIBS += advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib
+ TESTLIBS += winmm.lib opengl32.lib glu32.lib largeint.lib dxguid.lib
+endif
+
+
+$(DIR)/readwritetest: $(OBJS)
+ $(CC) $(LDFLAGS) -o $(DIR)/readwritetest $(OBJS) $(TESTLIBS)
+
+clean::
+ $(RM) $(DIR)/readwritetest
+
+test:: all
+ $(DIR)/readwritetest $(NAN_TEST_VERBOSITY)
diff --git a/source/blender/writestreamglue/test/readwritetest/readwritetest.c b/source/blender/writestreamglue/test/readwritetest/readwritetest.c
new file mode 100644
index 00000000000..9006fe3345a
--- /dev/null
+++ b/source/blender/writestreamglue/test/readwritetest/readwritetest.c
@@ -0,0 +1,188 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 for the streamglue read/write components
+ *
+ * The streamglue functions connect dataprocessors.
+ *
+ * Tested functions
+ *
+ * - streamGlueWrite (from BLO_streamglue.h)
+ * - streamGlueRead (from BLO_streamglue.h)
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <fcntl.h>
+
+#include "BLO_writeStreamGlue.h"
+
+#ifndef _WIN32
+#define O_BINARY 0
+#endif
+
+struct streamGlueControlStruct *Global_streamGlueControl;
+
+/* Some stubs here, because otherwise we have to link all of blender... */
+
+//FILE* mywfile = NULL;
+int mywfile = 0;
+
+ void *
+BLO_readstreamfile_begin(
+ void)
+{
+ fprintf(stderr, "|--> BLO_readstreamfile_begin: local loopback\n");
+ return NULL;
+}
+
+ int
+BLO_readstreamfile_process(
+ void *filedataVoidPtr,
+ unsigned char *data,
+ unsigned int dataIn)
+{
+ fprintf(stderr, "|--> BLO_readstreamfile_process: local loopback\n");
+ return 0;
+}
+
+
+ int
+BLO_readstreamfile_end(
+ void *filedataVoidPtr)
+{
+ fprintf(stderr, "|--> BLO_readstreamfile_end: local loopback\n");
+ return 0;
+}
+
+int main (int argc, char *argv[])
+{
+ int verbose = 0;
+ int error_status = 0;
+ int retval = 0;
+ int i = 0;
+
+ int datachunksize = 12345;
+ char* datachunk = NULL;
+ char* dataptr = NULL;
+ struct writeStreamGlueStruct *sgp = NULL;
+
+ switch (argc) {
+ case 2:
+ verbose = atoi(argv[1]);
+ if (verbose < 0) verbose = 0;
+ break;
+ case 1:
+ default:
+ verbose = 0;
+ }
+
+ /* ----------------------------------------------------------------- */
+
+ if (verbose > 0) {
+ fprintf(stderr,"\n*** Streamglue read/write test\n");
+ }
+
+ Global_streamGlueControl = streamGlueControlConstructor();
+
+// mywfile = fopen("readwritetestdump","wb");
+ mywfile = open("readwritetestdump",O_BINARY+O_WRONLY+O_CREAT+O_TRUNC, 0666);
+
+ error_status = (mywfile == NULL);
+// error_status |= fprintf(mywfile,"|\n|-- Opened file for testing: %d\n|\n", mywfile);
+
+
+ if (verbose > 1) {
+ fprintf(stderr,"|\n|-- Opened file for testing: %d with \n|\n", mywfile);
+ }
+
+/* streamGlueControlAppendAction(Global_streamGlueControl, DUMPFROMMEMORY); */
+/* streamGlueControlAppendAction(Global_streamGlueControl, DEFLATE); */
+/* streamGlueControlAppendAction(Global_streamGlueControl, ENCRYPT); */
+/* streamGlueControlAppendAction(Global_streamGlueControl, SIGN); */
+ streamGlueControlAppendAction(Global_streamGlueControl, WRITEBLENFILE);
+
+ if (verbose >1) {
+ fprintf(stderr,"|\n|-- Created and initialized streamGlueControl thingy \n");
+ fflush(stderr);
+ }
+
+ /* 2: the size */
+ datachunksize = 12345;
+
+ /* 1: a data chunk. We fill it with some numbers */
+ datachunk = (char*) malloc(datachunksize);
+
+ /* an ascending-ish thingy */
+ dataptr = datachunk;
+ for (i = 0 ;
+ i < datachunksize;
+ i++, dataptr++) {
+ *dataptr = (i % 0xFF);
+ }
+
+ if (verbose >1) {
+ fprintf(stderr,"|\n|-- Calling streamGlueWrite\n");
+ fflush(stderr);
+ }
+
+ retval =
+ writeStreamGlue(
+ Global_streamGlueControl, // general controller
+ &sgp, // ie. construct this for me
+ datachunk, // raw data
+ datachunksize, // data size
+ 1); // i.e. finalize this write
+
+ if (verbose >1) {
+ fprintf(stderr,"|\n|-- streamGlueWrite returned with %d\n", retval);
+ }
+
+ /* ----------------------------------------------------------------- */
+
+ if (close(mywfile)) {
+ error_status = 1;
+ if (verbose > 1) {
+ fprintf(stderr,"|\n|-- file close failed.\n");
+ }
+ }
+
+ if (verbose > 0) {
+ fprintf(stderr,"|\n*** Finished test\n\n");
+ }
+ exit(error_status);
+}
+
+
+/* eof */
diff --git a/source/blender/writestreamglue/test/typetest/Makefile b/source/blender/writestreamglue/test/typetest/Makefile
new file mode 100644
index 00000000000..617e358bcce
--- /dev/null
+++ b/source/blender/writestreamglue/test/typetest/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 *****
+#
+# Make a little test for the sys_types replacement.
+#
+
+DIR = $(OCGDIR)/blender/writestreamglue/test
+ALLTARGETS = $(OBJS) $(DIR)/typetest
+
+include nan_compile.mk
+
+$(DIR)/typetest: $(OBJS)
+ $(CC) $(LDFLAGS) -o $(DIR)/typetest $(OBJS)
+
+clean::
+ $(RM) $(DIR)/typetest
+
+test:: $(DIR)/typetest
+ $(DIR)/typetest $(NAN_TEST_VERBOSITY)
+
diff --git a/source/blender/writestreamglue/test/typetest/typetest.c b/source/blender/writestreamglue/test/typetest/typetest.c
new file mode 100644
index 00000000000..447abd9d792
--- /dev/null
+++ b/source/blender/writestreamglue/test/typetest/typetest.c
@@ -0,0 +1,94 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 little test to see how our type defines behave.
+ */
+
+#include "../../../readstreamglue/BLO_sys_types.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+int main (int argc, char *argv[])
+{
+ int verbose = 0;
+ int error_status = 0;
+ int char_size = 0;
+ int short_size = 0;
+ int int_size = 0;
+ int long_size = 0;
+
+ switch (argc) {
+ case 2:
+ verbose = atoi(argv[1]);
+ if (verbose < 0) verbose = 0;
+ break;
+ case 1:
+ default:
+ verbose = 0;
+ }
+
+ /* ----------------------------------------------------------------- */
+ if (verbose > 0) {
+ printf("*** Type define size test\n|\n");
+ }
+ /* Check if these exist, and show their sizes. */
+
+
+ char_size = sizeof(uint8_t);
+ short_size = sizeof(uint16_t);
+ int_size = sizeof(uint32_t);
+ long_size = sizeof(uint64_t);
+
+ if (verbose > 1) {
+ printf("|- uint8_t : \t%4d, expected 1.\n", char_size);
+ printf("|- uint16_t : \t%4d, expected 2.\n", short_size);
+ printf("|- uint32_t : \t%4d, expected 4.\n", int_size);
+ printf("|- uint64_t : \t%4d, expected 8.\n\n", long_size);
+ }
+
+ if ((char_size != 1)
+ || (short_size != 2)
+ || (int_size != 4)
+ || (long_size != 8)
+ ) {
+ error_status = 1;
+ }
+
+ if (verbose > 0) {
+ if (error_status) {
+ printf("|-- Size mismatch detected !!!\n|\n");
+ } else {
+ printf("|-- Sizes are correct.\n");
+ }
+ printf("|\n*** End of type define size test\n");
+ }
+
+ exit(error_status);
+}
diff --git a/source/creator/Makefile b/source/creator/Makefile
new file mode 100644
index 00000000000..c652b0228ad
--- /dev/null
+++ b/source/creator/Makefile
@@ -0,0 +1,63 @@
+#
+# $Id$
+#
+# ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version. The Blender
+# Foundation also sells licenses for use in proprietary software under
+# the Blender License. See http://www.blender.org/BL/ for information
+# about this.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2001-2002 by 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 = creator
+DIR = $(OCGDIR)/creator
+
+# this HAS to go
+CSRCS = creator.c
+
+include nan_compile.mk
+
+ifeq ($(OS),$(findstring $(OS), "beos darwin freebsd linux openbsd solaris windows"))
+ CFLAGS += -funsigned-char
+endif
+
+CFLAGS += $(LEVEL_1_C_WARNINGS)
+
+CPPFLAGS += -I$(OPENGL_HEADERS)
+CPPFLAGS += -I../blender/render/extern/include
+CPPFLAGS += -I../blender/radiosity/extern/include
+CPPFLAGS += -I../blender/misc
+# two needed for the kernel
+CPPFLAGS += -I../blender/imbuf
+CPPFLAGS += -I../blender/makesdna
+CPPFLAGS += -I../blender/blenlib
+CPPFLAGS += -I../blender/include
+CPPFLAGS += -I../blender/renderconverter
+CPPFLAGS += -I../blender/blenkernel
+CPPFLAGS += -I../blender/bpython/include
+CPPFLAGS += -I../blender/blenloader
+CPPFLAGS += -I../kernel/gen_system
+CPPFLAGS += -I../kernel/gen_messaging
+CPPFLAGS += -I$(NAN_BLENKEY)/include
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
diff --git a/source/creator/buildinfo.c b/source/creator/buildinfo.c
new file mode 100644
index 00000000000..f5ba401d23a
--- /dev/null
+++ b/source/creator/buildinfo.c
@@ -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 *****
+ */
+#ifdef BUILD_DATE
+char * build_date=BUILD_DATE;
+char * build_time=BUILD_TIME;
+char * build_platform=BUILD_PLATFORM;
+char * build_type=BUILD_TYPE;
+#endif
diff --git a/source/creator/creator.c b/source/creator/creator.c
new file mode 100644
index 00000000000..e9be9be2579
--- /dev/null
+++ b/source/creator/creator.c
@@ -0,0 +1,515 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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>
+
+/* This little block needed for linking to Blender... */
+
+#include "MEM_guardedalloc.h"
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+#include "GEN_messaging.h"
+
+#include "DNA_ID.h"
+
+#include "BLI_blenlib.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_blender.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_scene.h"
+
+#include "BIF_gl.h"
+#include "BIF_graphics.h"
+#include "BIF_mainqueue.h"
+#include "BIF_graphics.h"
+#include "BIF_editsound.h"
+#include "BIF_usiblender.h"
+#include "BIF_drawscene.h" /* set_scene() */
+#include "BIF_screen.h" /* waitcursor and more */
+#include "BIF_usiblender.h"
+#include "BIF_toolbox.h"
+
+#include "BLO_writefile.h"
+#include "BLO_readfile.h"
+
+#include "BPY_extern.h" // for init of blender python extension
+
+#include "BSE_headerbuttons.h" // for BIF_read_homefile
+
+#include "BDR_drawmesh.h"
+
+#include "RE_renderconverter.h"
+#include "blendertimer.h"
+
+#include "playanim_ext.h"
+#include "mydevice.h"
+#include "render.h"
+#include "nla.h"
+
+#include "license_key.h"
+
+/* for passing information between creator and gameengine */
+#include "SYS_System.h"
+
+#include <signal.h>
+#ifdef __FreeBSD__
+ #ifndef __OpenBSD__
+ #include <floatingpoint.h>
+ #include <sys/rtprio.h>
+ #endif
+#endif
+
+// from buildinfo.c
+extern char * build_date;
+extern char * build_time;
+extern char * build_platform;
+extern char * build_type;
+
+/* Local Function prototypes */
+static void print_help();
+
+/* for the callbacks: */
+
+extern int pluginapi_force_ref(void); /* from blenpluginapi:pluginapi.c */
+
+char bprogname[FILE_MAXDIR+FILE_MAXFILE];
+
+/* Initialise callbacks for the modules that need them */
+void setCallbacks(void);
+
+static void fpe_handler(int sig)
+{
+ // printf("SIGFPE trapped\n");
+}
+
+static void print_help(void)
+{
+ printf ("Blender V %d.%02d\n", G.version/100, G.version%100);
+ printf ("Usage: blender [options ...] [file]\n");
+
+ printf ("\nRender options:\n");
+ printf (" -b <file>\tRender <file> in background\n");
+ printf (" -S <name>\tSet scene <name>\n");
+ printf (" -f <frame>\tRender frame <frame> and save it\n");
+ printf (" -s <frame>\tSet start to frame <frame> (use with -a)\n");
+ printf (" -e <frame>\tSet end to frame (use with -a)<frame>\n");
+ printf (" -a\t\tRender animation\n");
+
+ printf ("\nAnimation options:\n");
+ printf (" -a <file(s)>\tPlayback <file(s)>\n");
+ printf (" -p <sx> <sy>\tOpen with lower left corner at <sx>, <sy>\n");
+ printf (" -m\t\tRead from disk (Don't buffer)\n");
+
+ printf ("\nWindow options:\n");
+ printf (" -w\t\tForce opening with borders\n");
+#ifdef WIN32
+ printf (" -W\t\tForce opening without borders\n");
+#endif
+ printf (" -p <sx> <sy> <w> <h>\tOpen with lower left corner at <sx>, <sy>\n");
+ printf (" \tand width and height <w>, <h>\n");
+ printf ("\nGame Engine specific options:\n");
+ printf (" -g fixedtime\t\tRun on 50 hertz without dropping frames\n");
+ printf (" -g vertexarrays\tUse Vertex Arrays for rendering (usually faster)\n");
+ printf (" -g noaudio\t\tNo audio in Game Engine\n");
+ printf (" -g nomipmap\t\tNo Texture Mipmapping\n");
+ printf (" -g linearmipmap\tLinear Texture Mipmapping instead of Nearest (default)\n");
+
+
+
+
+ printf ("\nMisc options:\n");
+ printf (" -d\t\tTurn debugging on\n");
+ printf (" -noaudio\tDisable audio on systems that support audio\n");
+ printf (" -h\t\tPrint this help text\n");
+ printf (" -y\t\tDisable OnLoad scene scripts, use -Y to find out why its -y\n");
+#ifdef WIN32
+ printf (" -R\t\tRegister .blend extension\n");
+#endif
+}
+double PIL_check_seconds_timer(void);
+int main(int argc, char **argv)
+{
+ int a, i, stax, stay, sizx, sizy;
+ SYS_SystemHandle syshandle;
+ Scene *sce;
+
+#if defined(WIN32) || defined (__linux__)
+ int audio = 1;
+#else
+ int audio = 0;
+#endif
+
+ setCallbacks();
+
+#ifdef __APPLE__
+ /* patch to ignore argument finder gives us (pid?) */
+ if (argc==2 && strncmp(argv[1], "-psn_", 5)==0) {
+ extern int GHOST_HACK_getFirstFile(char buf[]);
+ static char firstfilebuf[512];
+ int scr_x,scr_y;
+
+ argc= 1;
+
+ setprefsize(100, 100, 800, 600);
+
+ winlay_get_screensize(&scr_x, &scr_y);
+ winlay_process_events(0);
+ if (GHOST_HACK_getFirstFile(firstfilebuf)) {
+ argc= 2;
+ argv[1]= firstfilebuf;
+ }
+ }
+#endif
+
+#ifdef __FreeBSD__
+ fpsetmask(0);
+#endif
+#ifdef __linux__
+ #ifdef __alpha__
+ signal (SIGFPE, fpe_handler);
+ #endif
+#endif
+#if defined(__sgi)
+ signal (SIGFPE, fpe_handler);
+#endif
+
+ // copy path to executable in bprogname. playanim and creting runtimes
+ // need this.
+
+ BLI_where_am_i(bprogname, argv[0]);
+
+ /* Hack - force inclusion of the plugin api functions,
+ * see blenpluginapi:pluginapi.c
+ */
+ pluginapi_force_ref();
+
+ initglobals(); /* blender.c */
+
+ syshandle = SYS_GetSystem();
+ GEN_init_messaging_system();
+
+ /* eerste testen op background */
+ G.f |= G_SCENESCRIPT; /* scenescript always set! */
+ for(a=1; a<argc; a++) {
+
+ /* Handle unix and windows style help requests */
+ if ((!strcmp(argv[a], "--help")) || (!strcmp(argv[a], "/?"))){
+ print_help();
+ exit(0);
+ }
+
+ /* Handle -* switches */
+ else if(argv[a][0] == '-') {
+ switch(argv[a][1]) {
+ case 'a':
+ playanim(argc-1, argv+1);
+ exit(0);
+ break;
+ case 'b':
+ case 'B':
+ G.background = 1;
+ a= argc;
+ break;
+
+ case 'm':
+ /* unified render pipeline */
+/* G.magic = 1; has become obsolete */
+ printf("-m: enable unified renderer has become obsolete. Set \n");
+ printf("\tthis option per individual file now.\n");
+ break;
+
+ case 'y':
+ G.f &= ~G_SCENESCRIPT;
+ break;
+
+ case 'Y':
+ printf ("-y was used to disable scene scripts because,\n");
+ printf ("\t-p being taken, Ton was of the opinion that Y\n");
+ printf ("\tlooked like a split (disabled) snake, and also\n");
+ printf ("\twas similar to a python's tongue (unproven).\n\n");
+
+ printf ("\tZr agreed because it gave him a reason to add a\n");
+ printf ("\tcompletely useless text into Blender.\n\n");
+
+ printf ("\tADDENDUM! Ton, in defense, found this picture of\n");
+ printf ("\tan Australian python, exhibiting her (his/its) forked\n");
+ printf ("\tY tongue. It could be part of an H Zr retorted!\n\n");
+ printf ("\thttp://www.users.bigpond.com/snake.man/\n");
+
+ exit(252);
+
+ case 'h':
+ print_help();
+ exit(0);
+
+ default:
+ break;
+ }
+ }
+ }
+
+#ifdef __sgi
+ setuid(getuid()); /* einde superuser */
+#endif
+
+ RE_init_render_data(); /* moet vooraan staan ivm R.winpos uit defaultfile */
+
+ if(G.background==0) {
+ for(a=1; a<argc; a++) {
+ if(argv[a][0] == '-') {
+ switch(argv[a][1]) {
+ case 'p': /* prefsize */
+ if (argc-a < 5) {
+ printf ("-p requires four arguments\n");
+ exit(1);
+ }
+ a++;
+ stax= atoi(argv[a]);
+ a++;
+ stay= atoi(argv[a]);
+ a++;
+ sizx= atoi(argv[a]);
+ a++;
+ sizy= atoi(argv[a]);
+
+ setprefsize(stax, stay, sizx, sizy);
+ break;
+ case 'd':
+ G.f |= G_DEBUG; /* std output printf's */
+ printf ("Blender V %d.%02d\n", G.version/100, G.version%100);
+#ifdef NAN_BUILDINFO
+ printf("Build: %s %s %s %s\n", build_date, build_time, build_platform, build_type);
+
+#endif // NAN_BUILDINFO
+ for (i = 0; i < argc; i++) {
+ printf("argv[%d] = %s\n", i, argv[i]);
+ }
+ break;
+
+ case 'w':
+ /* XXX, fixme zr, with borders */
+ break;
+ case 'W':
+ /* XXX, fixme zr, borderless on win32 */
+ break;
+ case 'n':
+ case 'N':
+ if (strcasecmp(argv[a], "-noaudio") == 0|| strcasecmp(argv[a], "-nosound") == 0) {
+ /**
+ notify the gameengine that no audio is wanted, even if the user didn't give
+ the flag -g noaudio
+ */
+
+ SYS_WriteCommandLineInt(syshandle,"noaudio",1);
+ audio = 0;
+ if (G.f & G_DEBUG) printf("setting audio to: %d\n", audio);
+ }
+ else if (strcasecmp(argv[a], "-nofrozen") == 0) {
+ /* disable initialization of frozen python modules */
+ if (G.f & G_DEBUG) printf("disable frozen modules\n");
+ G.f |= G_NOFROZEN;
+ }
+ break;
+ }
+ }
+ }
+
+ BPY_start_python();
+
+ /* NOTE: initialize_sound *must be* after start_python,
+ * at least on FreeBSD */
+
+ sound_init_audio();
+
+ BIF_init();
+ }
+ else {
+ BPY_start_python();
+ SYS_WriteCommandLineInt(syshandle,"noaudio",1);
+ audio = 0;
+ sound_init_audio();
+ if (G.f & G_DEBUG) printf("setting audio to: %d\n", audio);
+ }
+
+ RE_init_filt_mask();
+
+ /* OK we zijn er klaar voor */
+
+ for(a=1; a<argc; a++) {
+ if (G.afbreek==1) break;
+
+ if(argv[a][0] == '-') {
+ switch(argv[a][1]) {
+ case 'p': /* prefsize */
+ a+= 4;
+ break;
+
+ case 'g':
+ {
+ /**
+ gameengine parameters are automaticly put into system
+ -g [paramname = value]
+ -g [boolparamname]
+ example:
+ -g novertexarrays
+ -g maxvertexarraysize = 512
+ */
+
+ if(++a < argc)
+ {
+ char* paramname = argv[a];
+ /* check for single value versus assignment */
+ if (a+1 < argc && (*(argv[a+1]) == '='))
+ {
+ a++;
+ if (a+1 < argc)
+ {
+ a++;
+ /* assignment */
+ SYS_WriteCommandLineString(syshandle,paramname,argv[a]);
+ } else
+ {
+ printf("error: argument assignment (%s) without value.\n",paramname);
+ }
+ /* name arg eaten */
+
+ } else
+ {
+
+ SYS_WriteCommandLineInt(syshandle,argv[a],1);
+
+ /* doMipMap */
+ if (!strcmp(argv[a],"nomipmap"))
+ {
+ set_mipmap(0); //doMipMap = 0;
+ }
+ /* linearMipMap */
+ if (!strcmp(argv[a],"linearmipmap"))
+ {
+ set_linear_mipmap(1); //linearMipMap = 1;
+ }
+
+
+ } /* if (*(argv[a+1]) == '=') */
+ } /* if(++a < argc) */
+ break;
+ }
+ case 'f':
+ a++;
+ if (G.scene && a < argc) {
+ G.real_sfra = (G.scene->r.sfra);
+ G.real_efra = (G.scene->r.efra);
+ (G.scene->r.sfra) = atoi(argv[a]);
+ (G.scene->r.efra) = (G.scene->r.sfra);
+ RE_animrender(NULL);
+ }
+ break;
+ case 'a':
+ if (G.scene) {
+ G.real_sfra = (G.scene->r.sfra);
+ G.real_efra = (G.scene->r.efra);
+ RE_animrender(NULL);
+ }
+ break;
+ case 'S':
+ if(++a < argc) {
+ set_scene_name(argv[a]);
+ }
+ break;
+ case 's':
+ a++;
+ if(G.scene) {
+ if (a < argc) (G.scene->r.sfra) = atoi(argv[a]);
+ }
+ break;
+ case 'e':
+ a++;
+ if(G.scene) {
+ if (a < argc) (G.scene->r.efra) = atoi(argv[a]);
+ }
+ break;
+ case 'R':
+ /* Registering filetypes only makes sense on windows... */
+#ifdef WIN32
+ RegisterBlendExtension(argv[0]);
+#endif
+ break;
+ }
+ }
+ else {
+ BKE_read_file(argv[a], NULL);
+ sound_initialize_sounds();
+ }
+ }
+
+ if(G.background)
+ {
+ exit_usiblender();
+ }
+
+ setscreen(G.curscreen);
+
+ if(G.main->scene.first==0) {
+ sce= add_scene("1");
+ set_scene(sce);
+ }
+
+ screenmain();
+
+ return 0;
+} /* end of int main(argc,argv) */
+
+static void error_cb(char *err)
+{
+ error("%s", err);
+}
+
+void setCallbacks(void)
+{
+ /* Error output from the alloc routines: */
+ MEM_set_error_stream(stderr);
+
+
+ /* BLI_blenlib: */
+
+ BLI_setErrorCallBack(error_cb); /* */
+ BLI_setInterruptCallBack(MISC_test_break);
+
+ /* render module: execution flow, timers, cursors and display. */
+ RE_set_getrenderdata_callback(RE_rotateBlenderScene);
+ RE_set_freerenderdata_callback(RE_freeRotateBlenderScene);
+}
diff --git a/source/darwin/Makefile b/source/darwin/Makefile
new file mode 100644
index 00000000000..a53af8cb8e2
--- /dev/null
+++ b/source/darwin/Makefile
@@ -0,0 +1,47 @@
+#
+# $Id: Makefile,v 1.1.1.1 2002/10/12 11:37:43 hans Exp $
+#
+# ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version. The Blender
+# Foundation also sells licenses for use in proprietary software under
+# the Blender License. See http://www.blender.org/BL/ for information
+# about this.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2001-2002 by 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
+
+DIR = $(OCGDIR)/$(DEBUG_DIR)
+
+all::
+ @# set up directory structure for the OSX aplication bundle
+ @echo "---> creating directory structure for $(APPLICATION)"
+ @rm -rf $(DIR)/$(APPLICATION).app
+ @cp -R $(APPLICATION).app $(DIR)
+ @#cat $(APPLICATION).app/Contents/Info.plist | sed s/VERSION/`cat ../../VERSION`/ | sed s/DATE/`date +'%Y-%b-%d'`/ > $(DIR)/$(APPLICATION).app/Contents/Info.plist
+ @echo "---> copying binary"
+ @cp $(DIR)/$(APPLICATION) $(DIR)/$(APPLICATION).app/Contents/MacOS/
+ @echo "---> removing CVS directories and Mac hidden files from distribution"
+ @find $(DIR)/$(APPLICATION).app -name CVS -prune -exec rm -rf {} \;
+ @find $(DIR)/$(APPLICATION).app -name .DS_Store -exec rm -f {} \;
diff --git a/source/darwin/blendercreator.app/Contents/Info.plist b/source/darwin/blendercreator.app/Contents/Info.plist
new file mode 100644
index 00000000000..08709cd26e3
--- /dev/null
+++ b/source/darwin/blendercreator.app/Contents/Info.plist
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
+<plist version="0.9">
+<dict>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+
+ <key>CFBundleExecutable</key>
+ <string>blendercreator</string>
+
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+
+ <key>CFBundleIconFile</key>
+ <string>blender creator icon.icns</string>
+
+ <key>CFBundleName</key>
+ <string>BlenderCreator</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.nantechnologies.blendercreator</string>
+
+ <key>CFBundleVersion</key>
+ <string>VERSION, DATE, Copyright NaN Technologies BV</string>
+ <key>CFBundleShortVersionString</key>
+ <string>VERSION</string>
+ <key>CFBundleGetInfoString</key>
+ <string>VERSION, DATE, Copyright NaN Technologies BV</string>
+
+ <key>CFBundleDocumentTypes</key>
+ <array>
+ <dict>
+ <key>CFBundleTypeIconFile</key>
+ <string>blender file icon.icns</string>
+ <key>CFBundleTypeName</key>
+ <string>Blender File</string>
+ <key>CFBundleTypeOSTypes</key>
+ <array>
+ <string>BLND</string>
+ </array>
+ <key>CFBundleTypeExtensions</key>
+ <array>
+ <string>blend</string>
+ </array>
+ <key>CFBundleTypeRole</key>
+ <string>Editor</string>
+ <key>LSIsAppleDefaultForType</key>
+ <true/>
+ </dict>
+ </array>
+</dict>
+</plist>
diff --git a/source/darwin/blendercreator.app/Contents/MacOS/blendercreator b/source/darwin/blendercreator.app/Contents/MacOS/blendercreator
new file mode 100644
index 00000000000..5e05e74a307
--- /dev/null
+++ b/source/darwin/blendercreator.app/Contents/MacOS/blendercreator
@@ -0,0 +1 @@
+placeholder
diff --git a/source/darwin/blendercreator.app/Contents/PkgInfo b/source/darwin/blendercreator.app/Contents/PkgInfo
new file mode 100644
index 00000000000..bd04210fb49
--- /dev/null
+++ b/source/darwin/blendercreator.app/Contents/PkgInfo
@@ -0,0 +1 @@
+APPL???? \ No newline at end of file
diff --git a/source/darwin/blendercreator.app/Contents/Resources/blender creator icon.icns b/source/darwin/blendercreator.app/Contents/Resources/blender creator icon.icns
new file mode 100644
index 00000000000..8b182a682a0
--- /dev/null
+++ b/source/darwin/blendercreator.app/Contents/Resources/blender creator icon.icns
Binary files differ
diff --git a/source/darwin/blendercreator.app/Contents/Resources/blender file icon.icns b/source/darwin/blendercreator.app/Contents/Resources/blender file icon.icns
new file mode 100644
index 00000000000..0d38a7b4215
--- /dev/null
+++ b/source/darwin/blendercreator.app/Contents/Resources/blender file icon.icns
Binary files differ
diff --git a/source/darwin/blenderplayer.app/Contents/Info.plist b/source/darwin/blenderplayer.app/Contents/Info.plist
new file mode 100644
index 00000000000..f46490a40ba
--- /dev/null
+++ b/source/darwin/blenderplayer.app/Contents/Info.plist
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
+<plist version="0.9">
+<dict>
+ <key>CFBundleDocumentTypes</key>
+ <array>
+ <dict>
+ <key>CFBundleTypeExtensions</key>
+ <array>
+ <string>blend</string>
+ </array>
+ <key>CFBundleTypeIconFile</key>
+ <string>blender file icon.icns</string>
+ <key>CFBundleTypeName</key>
+ <string>Blender File</string>
+ <key>CFBundleTypeOSTypes</key>
+ <array>
+ <string>BLND</string>
+ </array>
+ <key>CFBundleTypeRole</key>
+ <string>Viewer</string>
+ <key>LSIsAppleDefaultForType</key>
+ <false/>
+ </dict>
+ </array>
+ <key>CFBundleExecutable</key>
+ <string>blenderplayer</string>
+ <key>CFBundleGetInfoString</key>
+ <string>VERSION, DATE, Copyright NaN Technologies BV</string>
+ <key>CFBundleIconFile</key>
+ <string>blender player icon.icns</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.nantechnologies.blenderplayer</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>BlenderPlayer</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>VERSION</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>VERSION, DATE, Copyright NaN Technologies BV</string>
+</dict>
+</plist>
diff --git a/source/darwin/blenderplayer.app/Contents/MacOS/blenderplayer b/source/darwin/blenderplayer.app/Contents/MacOS/blenderplayer
new file mode 100644
index 00000000000..5e05e74a307
--- /dev/null
+++ b/source/darwin/blenderplayer.app/Contents/MacOS/blenderplayer
@@ -0,0 +1 @@
+placeholder
diff --git a/source/darwin/blenderplayer.app/Contents/PkgInfo b/source/darwin/blenderplayer.app/Contents/PkgInfo
new file mode 100644
index 00000000000..bd04210fb49
--- /dev/null
+++ b/source/darwin/blenderplayer.app/Contents/PkgInfo
@@ -0,0 +1 @@
+APPL???? \ No newline at end of file
diff --git a/source/darwin/blenderplayer.app/Contents/Resources/blender file icon.icns b/source/darwin/blenderplayer.app/Contents/Resources/blender file icon.icns
new file mode 100644
index 00000000000..0d38a7b4215
--- /dev/null
+++ b/source/darwin/blenderplayer.app/Contents/Resources/blender file icon.icns
Binary files differ
diff --git a/source/darwin/blenderplayer.app/Contents/Resources/blender player icon.icns b/source/darwin/blenderplayer.app/Contents/Resources/blender player icon.icns
new file mode 100644
index 00000000000..8b182a682a0
--- /dev/null
+++ b/source/darwin/blenderplayer.app/Contents/Resources/blender player icon.icns
Binary files differ
diff --git a/source/darwin/blenderpublisher.app/Contents/Info.plist b/source/darwin/blenderpublisher.app/Contents/Info.plist
new file mode 100644
index 00000000000..f22de5a4460
--- /dev/null
+++ b/source/darwin/blenderpublisher.app/Contents/Info.plist
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
+<plist version="0.9">
+<dict>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+
+ <key>CFBundleExecutable</key>
+ <string>blenderpublisher</string>
+
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+
+ <key>CFBundleIconFile</key>
+ <string>blender publisher icon.icns</string>
+
+ <key>CFBundleName</key>
+ <string>BlenderPublisher</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.nantechnologies.blenderpublisher</string>
+
+ <key>CFBundleVersion</key>
+ <string>VERSION, DATE, Copyright NaN Technologies BV</string>
+ <key>CFBundleShortVersionString</key>
+ <string>VERSION</string>
+ <key>CFBundleGetInfoString</key>
+ <string>VERSION, DATE, Copyright NaN Technologies BV</string>
+
+ <key>CFBundleDocumentTypes</key>
+ <array>
+ <dict>
+ <key>CFBundleTypeIconFile</key>
+ <string>blender file icon.icns</string>
+ <key>CFBundleTypeName</key>
+ <string>Blender File</string>
+ <key>CFBundleTypeOSTypes</key>
+ <array>
+ <string>BLND</string>
+ </array>
+ <key>CFBundleTypeExtensions</key>
+ <array>
+ <string>blend</string>
+ </array>
+ <key>CFBundleTypeRole</key>
+ <string>Editor</string>
+ <key>LSIsAppleDefaultForType</key>
+ <true/>
+ </dict>
+ </array>
+</dict>
+</plist>
diff --git a/source/darwin/blenderpublisher.app/Contents/MacOS/blenderpublisher b/source/darwin/blenderpublisher.app/Contents/MacOS/blenderpublisher
new file mode 100644
index 00000000000..5e05e74a307
--- /dev/null
+++ b/source/darwin/blenderpublisher.app/Contents/MacOS/blenderpublisher
@@ -0,0 +1 @@
+placeholder
diff --git a/source/darwin/blenderpublisher.app/Contents/PkgInfo b/source/darwin/blenderpublisher.app/Contents/PkgInfo
new file mode 100644
index 00000000000..bd04210fb49
--- /dev/null
+++ b/source/darwin/blenderpublisher.app/Contents/PkgInfo
@@ -0,0 +1 @@
+APPL???? \ No newline at end of file
diff --git a/source/darwin/blenderpublisher.app/Contents/Resources/blender file icon.icns b/source/darwin/blenderpublisher.app/Contents/Resources/blender file icon.icns
new file mode 100644
index 00000000000..0d38a7b4215
--- /dev/null
+++ b/source/darwin/blenderpublisher.app/Contents/Resources/blender file icon.icns
Binary files differ
diff --git a/source/darwin/blenderpublisher.app/Contents/Resources/blender publisher icon.icns b/source/darwin/blenderpublisher.app/Contents/Resources/blender publisher icon.icns
new file mode 100644
index 00000000000..2b166c76d56
--- /dev/null
+++ b/source/darwin/blenderpublisher.app/Contents/Resources/blender publisher icon.icns
Binary files differ
diff --git a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
new file mode 100644
index 00000000000..ba0c7fa3917
--- /dev/null
+++ b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
@@ -0,0 +1,374 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * Blender's Ketsji startpoint
+ */
+
+#ifdef WIN32
+// don't show stl-warnings
+#pragma warning (disable:4786)
+#endif
+
+#include "KX_BlenderGL.h"
+#include "KX_BlenderCanvas.h"
+#include "KX_BlenderKeyboardDevice.h"
+#include "KX_BlenderMouseDevice.h"
+#include "KX_BlenderRenderTools.h"
+#include "KX_BlenderSystem.h"
+
+#include "KX_KetsjiEngine.h"
+#include "KX_BlenderSceneConverter.h"
+#include "KX_PythonInit.h"
+#include "KX_PyConstraintBinding.h"
+
+#include "RAS_OpenGLRasterizer.h"
+#include "RAS_CheckVertexArrays.h"
+
+
+#ifdef WIN32
+#include "RAS_VAOpenGLRasterizer.h"
+#endif
+
+#include "NG_LoopBackNetworkDeviceInterface.h"
+#include "SND_DeviceManager.h"
+
+#include "SYS_System.h"
+
+ /***/
+
+#include "DNA_view3d_types.h"
+#include "DNA_screen_types.h"
+#include "BKE_global.h"
+#include "BIF_screen.h"
+#include "BIF_scrarea.h"
+
+#include "BKE_main.h"
+#include "BLI_blenlib.h"
+#include "BLO_readfile.h"
+#include "DNA_scene_types.h"
+ /***/
+
+static BlendFileData *load_game_data(char *filename) {
+ BlendReadError error;
+ BlendFileData *bfd= BLO_read_from_file(filename, &error);
+
+ if (!bfd) {
+ printf("Loading %s failed: %s\n", filename, BLO_bre_as_string(error));
+ }
+
+ return bfd;
+}
+
+extern "C" void StartKetsjiShell(struct ScrArea *area,
+ char* scenename,
+ struct Main* maggie,
+ int always_use_expand_framing)
+{
+ int exitrequested = KX_EXIT_REQUEST_NO_REQUEST;
+ Main* blenderdata = maggie;
+ char* startscenename = scenename;
+ char pathname[160];
+ strcpy (pathname, maggie->name);
+ STR_String exitstring = "";
+ BlendFileData *bfd= NULL;
+
+ do
+ {
+ View3D *v3d= (View3D*) area->spacedata.first;
+
+ // get some preferences
+ SYS_SystemHandle syshandle = SYS_GetSystem();
+ bool properties = (SYS_GetCommandLineInt(syshandle, "show_properties", 0) != 0);
+ bool usefixed = (SYS_GetCommandLineInt(syshandle, "fixedtime", 0) != 0);
+ bool profile = (SYS_GetCommandLineInt(syshandle, "show_profile", 0) != 0);
+ bool frameRate = (SYS_GetCommandLineInt(syshandle, "show_framerate", 0) != 0);
+
+ // create the canvas, rasterizer and rendertools
+ RAS_ICanvas* canvas = new KX_BlenderCanvas(area);
+ canvas->SetMouseState(RAS_ICanvas::MOUSE_INVISIBLE);
+ RAS_IRenderTools* rendertools = new KX_BlenderRenderTools();
+ RAS_IRasterizer* rasterizer = NULL;
+
+ // let's see if we want to use vertexarrays or not
+#ifdef WIN32
+ int usevta = SYS_GetCommandLineInt(syshandle,"vertexarrays",1);
+ bool useVertexArrays = (usevta > 0);
+
+ if (useVertexArrays && RAS_SystemSupportsVertexArrays())
+ rasterizer = new RAS_VAOpenGLRasterizer(canvas);
+ else
+ rasterizer = new RAS_OpenGLRasterizer(canvas);
+#else
+ rasterizer = new RAS_OpenGLRasterizer(canvas);
+#endif
+
+ // create the inputdevices
+ KX_BlenderKeyboardDevice* keyboarddevice = new KX_BlenderKeyboardDevice();
+ KX_BlenderMouseDevice* mousedevice = new KX_BlenderMouseDevice();
+
+ // create a networkdevice
+ NG_NetworkDeviceInterface* networkdevice = new
+ NG_LoopBackNetworkDeviceInterface();
+
+ // get an audiodevice
+ SND_DeviceManager::Subscribe();
+ SND_IAudioDevice* audiodevice = SND_DeviceManager::Instance();
+ audiodevice->UseCD();
+
+ // create a ketsji/blendersystem (only needed for timing and stuff)
+ KX_BlenderSystem* kxsystem = new KX_BlenderSystem();
+
+ // create the ketsjiengine
+ KX_KetsjiEngine* ketsjiengine = new KX_KetsjiEngine(kxsystem);
+
+ // set the devices
+ ketsjiengine->SetKeyboardDevice(keyboarddevice);
+ ketsjiengine->SetMouseDevice(mousedevice);
+ ketsjiengine->SetNetworkDevice(networkdevice);
+ ketsjiengine->SetCanvas(canvas);
+ ketsjiengine->SetRenderTools(rendertools);
+ ketsjiengine->SetRasterizer(rasterizer);
+ ketsjiengine->SetNetworkDevice(networkdevice);
+ ketsjiengine->SetAudioDevice(audiodevice);
+ ketsjiengine->SetUseFixedTime(usefixed);
+ ketsjiengine->SetTimingDisplay(frameRate, profile, properties);
+
+ // some blender stuff
+ MT_CmMatrix4x4 projmat;
+ MT_CmMatrix4x4 viewmat;
+ int i;
+
+ for (i = 0; i < 16; i++)
+ {
+ float *viewmat_linear= (float*) v3d->viewmat;
+ viewmat.setElem(i, viewmat_linear[i]);
+ }
+ for (i = 0; i < 16; i++)
+ {
+ float *projmat_linear = (float*) area->winmat;
+ projmat.setElem(i, projmat_linear[i]);
+ }
+
+ float camzoom = (1.41421 + (v3d->camzoom / 50.0));
+ camzoom *= camzoom;
+ camzoom = 4.0 / camzoom;
+
+ ketsjiengine->SetDrawType(v3d->drawtype);
+ ketsjiengine->SetCameraZoom(camzoom);
+
+ // if we got an exitcode 3 (KX_EXIT_REQUEST_START_OTHER_GAME) load a different file
+ if (exitrequested == KX_EXIT_REQUEST_START_OTHER_GAME || exitrequested == KX_EXIT_REQUEST_RESTART_GAME)
+ {
+ exitrequested = KX_EXIT_REQUEST_NO_REQUEST;
+ if (bfd) BLO_blendfiledata_free(bfd);
+
+ char basedpath[160];
+ // base the actuator filename with respect
+ // to the original file working directory
+ if (exitstring != "")
+ strcpy(basedpath, exitstring.Ptr());
+
+ BLI_convertstringcode(basedpath, pathname, 0);
+ bfd = load_game_data(basedpath);
+
+ // if it wasn't loaded, try it forced relative
+ if (!bfd)
+ {
+ // just add "//" in front of it
+ char temppath[162];
+ strcpy(temppath, "//");
+ strcat(temppath, basedpath);
+
+ BLI_convertstringcode(temppath, pathname, 0);
+ bfd = load_game_data(temppath);
+ }
+
+ // if we got a loaded blendfile, proceed
+ if (bfd)
+ {
+ blenderdata = bfd->main;
+ startscenename = bfd->curscene->id.name + 2;
+ }
+ // else forget it, we can't find it
+ else
+ {
+ exitrequested = KX_EXIT_REQUEST_QUIT_GAME;
+ }
+ }
+
+ if (exitrequested != KX_EXIT_REQUEST_QUIT_GAME)
+ {
+ if (v3d->persp != 2)
+ {
+ ketsjiengine->EnableCameraOverride(startscenename);
+ ketsjiengine->SetCameraOverrideUseOrtho((v3d->persp == 0));
+ ketsjiengine->SetCameraOverrideProjectionMatrix(projmat);
+ ketsjiengine->SetCameraOverrideViewMatrix(viewmat);
+ }
+
+ // create a scene converter, create and convert the startingscene
+ KX_ISceneConverter* sceneconverter = new KX_BlenderSceneConverter(blenderdata, ketsjiengine);
+ ketsjiengine->SetSceneConverter(sceneconverter);
+
+ if (always_use_expand_framing)
+ sceneconverter->SetAlwaysUseExpandFraming(true);
+
+
+ KX_Scene* startscene = new KX_Scene(keyboarddevice,
+ mousedevice,
+ networkdevice,
+ audiodevice,
+ startscenename);
+
+ // some python things
+ PyObject* dictionaryobject = initGamePythonScripting("Ketsji", psl_Lowest);
+ ketsjiengine->SetPythonDictionary(dictionaryobject);
+ initRasterizer(rasterizer, canvas);
+ initGameLogic(startscene);
+ initGameKeys();
+ initPythonConstraintBinding();
+
+
+ if (sceneconverter)
+ {
+ // convert and add scene
+ sceneconverter->ConvertScene(
+ startscenename,
+ startscene,
+ dictionaryobject,
+ keyboarddevice,
+ rendertools,
+ canvas);
+ ketsjiengine->AddScene(startscene);
+
+ // init the rasterizer
+ rasterizer->Init();
+
+ // start the engine
+ ketsjiengine->StartEngine();
+
+ // the mainloop
+ while (!exitrequested)
+ {
+ // first check if we want to exit
+ exitrequested = ketsjiengine->GetExitCode();
+
+ // kick the engine
+ ketsjiengine->NextFrame();
+
+ // render the frame
+ ketsjiengine->Render();
+
+ // test for the ESC key
+ while (qtest())
+ {
+ short val;
+ unsigned short event = extern_qread(&val);
+
+ if (keyboarddevice->ConvertBlenderEvent(event,val))
+ exitrequested = KX_EXIT_REQUEST_BLENDER_ESC;
+
+ /* Coordinate conversion... where
+ * should this really be?
+ */
+ if (event==MOUSEX) {
+ val = val - scrarea_get_win_x(area);
+ } else if (event==MOUSEY) {
+ val = scrarea_get_win_height(area) - (val - scrarea_get_win_y(area)) - 1;
+ }
+
+ mousedevice->ConvertBlenderEvent(event,val);
+ }
+ }
+ exitstring = ketsjiengine->GetExitString();
+
+ // when exiting the mainloop
+ exitGamePythonScripting();
+ ketsjiengine->StopEngine();
+ networkdevice->Disconnect();
+ }
+
+ if (sceneconverter)
+ {
+ delete sceneconverter;
+ sceneconverter = NULL;
+ }
+ }
+ // set the cursor back to normal
+ canvas->SetMouseState(RAS_ICanvas::MOUSE_NORMAL);
+
+ // clean up some stuff
+ audiodevice->StopCD();
+ SND_DeviceManager::Unsubscribe();
+
+ if (ketsjiengine)
+ {
+ delete ketsjiengine;
+ ketsjiengine = NULL;
+ }
+ if (kxsystem)
+ {
+ delete kxsystem;
+ kxsystem = NULL;
+ }
+ if (networkdevice)
+ {
+ delete networkdevice;
+ networkdevice = NULL;
+ }
+ if (keyboarddevice)
+ {
+ delete keyboarddevice;
+ keyboarddevice = NULL;
+ }
+ if (mousedevice)
+ {
+ delete mousedevice;
+ mousedevice = NULL;
+ }
+ if (rasterizer)
+ {
+ delete rasterizer;
+ rasterizer = NULL;
+ }
+ if (rendertools)
+ {
+ delete rendertools;
+ rendertools = NULL;
+ }
+ if (canvas)
+ {
+ delete canvas;
+ canvas = NULL;
+ }
+ } while (exitrequested == KX_EXIT_REQUEST_RESTART_GAME || exitrequested == KX_EXIT_REQUEST_START_OTHER_GAME);
+
+ if (bfd) BLO_blendfiledata_free(bfd);
+}
diff --git a/source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp b/source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp
new file mode 100644
index 00000000000..3dfae217453
--- /dev/null
+++ b/source/gameengine/BlenderRoutines/KX_BlenderCanvas.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 *****
+ */
+
+#include "BIF_scrarea.h"
+
+
+#include "KX_BlenderCanvas.h"
+
+
+KX_BlenderCanvas::KX_BlenderCanvas(struct ScrArea *area) :
+m_area(area)
+{
+}
+
+KX_BlenderCanvas::~KX_BlenderCanvas()
+{
+}
+
+void KX_BlenderCanvas::Init()
+{
+ glDepthFunc(GL_LEQUAL);
+}
+
+
+void KX_BlenderCanvas::SwapBuffers()
+{
+ BL_SwapBuffers();
+}
+
+void KX_BlenderCanvas::BeginFrame()
+{
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_LEQUAL);
+
+}
+
+
+void KX_BlenderCanvas::EndFrame()
+{
+ // this is needed, else blender distorts a lot
+ glPopAttrib();
+ glPushAttrib(GL_ALL_ATTRIB_BITS);
+
+ glDisable(GL_FOG);
+}
+
+
+
+void KX_BlenderCanvas::ClearColor(float r,float g,float b,float a)
+{
+ glClearColor(r,g,b,a);
+}
+
+
+
+void KX_BlenderCanvas::ClearBuffer(int type)
+{
+ int ogltype = 0;
+
+ if (type & RAS_ICanvas::COLOR_BUFFER )
+ ogltype |= GL_COLOR_BUFFER_BIT;
+
+ if (type & RAS_ICanvas::DEPTH_BUFFER )
+ ogltype |= GL_DEPTH_BUFFER_BIT;
+ glClear(ogltype);
+}
+
+int KX_BlenderCanvas::GetWidth(
+) const {
+ return scrarea_get_win_width(m_area);
+}
+
+int KX_BlenderCanvas::GetHeight(
+) const {
+ return scrarea_get_win_height(m_area);
+}
+
+ void
+KX_BlenderCanvas::
+SetViewPort(
+ int x1, int y1,
+ int x2, int y2
+){
+ int vp_width = (x2 - x1) + 1;
+ int vp_height = (y2 - y1) + 1;
+ int minx = scrarea_get_win_x(m_area);
+ int miny = scrarea_get_win_y(m_area);
+
+ glViewport(minx + x1, miny + y1, vp_width, vp_height);
+ glScissor(minx + x1, miny + y1, vp_width, vp_height);
+}
+
+
+void KX_BlenderCanvas::SetMouseState(RAS_MouseState mousestate)
+{
+ switch (mousestate)
+ {
+ case MOUSE_INVISIBLE:
+ {
+ BL_HideMouse();
+ break;
+ }
+ case MOUSE_WAIT:
+ {
+ BL_WaitMouse();
+ break;
+ }
+ case MOUSE_NORMAL:
+ {
+ BL_NormalMouse();
+ break;
+ }
+ default:
+ {
+ }
+ }
+}
+
+
+
+// (0,0) is top left, (width,height) is bottom right
+void KX_BlenderCanvas::SetMousePosition(int x,int y)
+{
+ int winX = scrarea_get_win_x(m_area);
+ int winY = scrarea_get_win_y(m_area);
+ int winH = scrarea_get_win_height(m_area);
+
+ BL_warp_pointer(winX + x, winY + (winH-y-1));
+}
+
+
+
+void KX_BlenderCanvas::MakeScreenShot(const char* filename)
+{
+ BL_MakeScreenShot(m_area, filename);
+}
diff --git a/source/gameengine/BlenderRoutines/KX_BlenderCanvas.h b/source/gameengine/BlenderRoutines/KX_BlenderCanvas.h
new file mode 100644
index 00000000000..85b41e37f1d
--- /dev/null
+++ b/source/gameengine/BlenderRoutines/KX_BlenderCanvas.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 __KX_BLENDERCANVAS
+#define __KX_BLENDERCANVAS
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+#include <GL/gl.h>
+
+#include "RAS_ICanvas.h"
+#include "RAS_Rect.h"
+
+#include "KX_BlenderGL.h"
+
+struct ScrArea;
+
+/**
+ * 2D Blender device context abstraction.
+ * The connection from 3d rendercontext to 2d Blender surface embedding.
+ */
+
+class KX_BlenderCanvas : public RAS_ICanvas
+{
+private:
+ /** Rect that defines the area used for rendering,
+ relative to the context */
+ RAS_Rect m_displayarea;
+
+public:
+ /* Construct a new canvas.
+ *
+ * @param area The Blender ScrArea to run the game within.
+ */
+ KX_BlenderCanvas(struct ScrArea* area);
+ ~KX_BlenderCanvas();
+
+ void
+ Init(
+ );
+
+ void
+ SwapBuffers(
+ );
+ void
+ Resize(
+ int width,
+ int height
+ );
+
+ void
+ BeginFrame(
+ );
+
+ void
+ EndFrame(
+ );
+
+ void
+ ClearColor(
+ float r,
+ float g,
+ float b,
+ float a
+ );
+
+ void
+ ClearBuffer(
+ int type
+ );
+
+ int
+ GetWidth(
+ ) const ;
+
+ int
+ GetHeight(
+ ) const ;
+
+ const
+ RAS_Rect &
+ GetDisplayArea(
+ ) const {
+ return m_displayarea;
+ };
+
+ RAS_Rect &
+ GetDisplayArea(
+ ) {
+ return m_displayarea;
+ };
+
+ void
+ SetViewPort(
+ int x1, int y1,
+ int x2, int y2
+ );
+
+ void
+ SetMouseState(
+ RAS_MouseState mousestate
+ );
+
+ void
+ SetMousePosition(
+ int x,
+ int y
+ );
+
+ void
+ MakeScreenShot(
+ const char* filename
+ );
+
+ /**
+ * Nothing needs be done for BlenderCanvas
+ * Begin/End Draw, as the game engine GL context
+ * is always current/active.
+ */
+
+ bool
+ BeginDraw(
+ ) {
+ return true;
+ };
+
+ void
+ EndDraw(
+ ) {
+ };
+
+private:
+ /** Blender area the game engine is running within */
+ struct ScrArea* m_area;
+};
+#endif // __KX_BLENDERCANVAS
diff --git a/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp b/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp
new file mode 100644
index 00000000000..c2b4da62ece
--- /dev/null
+++ b/source/gameengine/BlenderRoutines/KX_BlenderGL.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 *****
+ */
+
+#include "KX_BlenderGL.h"
+
+
+/*
+ * This little block needed for linking to Blender...
+ */
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "BMF_Api.h"
+
+
+
+/* Data types encoding the game world: */
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_world_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_image_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_material_types.h"
+
+#include "BKE_global.h"
+#include "BKE_bmfont.h"
+
+#include "BIF_gl.h"
+extern "C" {
+#include "BDR_drawmesh.h"
+#include "BIF_mywindow.h"
+#include "BIF_toolbox.h"
+#include "BIF_graphics.h" /* For CURSOR_NONE CURSOR_WAIT CURSOR_STD */
+
+}
+
+/* end of blender block */
+
+
+#include <GL/gl.h>
+
+
+void BL_warp_pointer(int x,int y)
+{
+ warp_pointer(x,y);
+}
+
+void BL_SwapBuffers()
+{
+ myswapbuffers();
+}
+
+void BL_RenderText(int mode,const char* textstr,int textlen,struct TFace* tface,
+ float v1[3],float v2[3],float v3[3],float v4[3])
+{
+ Image* ima;
+
+ if(mode & TF_BMFONT) {
+ //char string[MAX_PROPSTRING];
+ int characters, index, character;
+ float centerx, centery, sizex, sizey, transx, transy, movex, movey, advance;
+
+// bProperty *prop;
+
+ // string = "Frank van Beek";
+
+ characters = textlen;
+
+ ima = (struct Image*) tface->tpage;
+ if (ima == NULL) {
+ characters = 0;
+ }
+
+ glPushMatrix();
+ for (index = 0; index < characters; index++) {
+ // lets calculate offset stuff
+ character = textstr[index];
+
+ // space starts at offset 1
+ // character = character - ' ' + 1;
+
+ matrixGlyph(ima->ibuf, character, & centerx, &centery, &sizex, &sizey, &transx, &transy, &movex, &movey, &advance);
+
+ glBegin(GL_POLYGON);
+ // printf(" %c %f %f %f %f\n", character, tface->uv[0][0], tface->uv[0][1], );
+ // glTexCoord2f((tface->uv[0][0] - centerx) * sizex + transx, (tface->uv[0][1] - centery) * sizey + transy);
+ glTexCoord2f((tface->uv[0][0] - centerx) * sizex + transx, (tface->uv[0][1] - centery) * sizey + transy);
+
+ spack(tface->col[0]);
+ // glVertex3fv(v1);
+ glVertex3f(sizex * v1[0] + movex, sizey * v1[1] + movey, v1[2]);
+
+ glTexCoord2f((tface->uv[1][0] - centerx) * sizex + transx, (tface->uv[1][1] - centery) * sizey + transy);
+ spack(tface->col[1]);
+ // glVertex3fv(v2);
+ glVertex3f(sizex * v2[0] + movex, sizey * v2[1] + movey, v2[2]);
+
+ glTexCoord2f((tface->uv[2][0] - centerx) * sizex + transx, (tface->uv[2][1] - centery) * sizey + transy);
+ spack(tface->col[2]);
+ // glVertex3fv(v3);
+ glVertex3f(sizex * v3[0] + movex, sizey * v3[1] + movey, v3[2]);
+
+ if(v4) {
+ // glTexCoord2f((tface->uv[3][0] - centerx) * sizex + transx, 1.0 - (1.0 - tface->uv[3][1]) * sizey - transy);
+ glTexCoord2f((tface->uv[3][0] - centerx) * sizex + transx, (tface->uv[3][1] - centery) * sizey + transy);
+ spack(tface->col[3]);
+ // glVertex3fv(v4);
+ glVertex3f(sizex * v4[0] + movex, sizey * v4[1] + movey, v4[2]);
+ }
+ glEnd();
+
+ glTranslatef(advance, 0.0, 0.0);
+ }
+ glPopMatrix();
+
+ }
+}
+
+
+void BL_print_gamedebug_line(char* text, int xco, int yco, int width, int height)
+{
+ /* gl prepping */
+ glDisable(GL_TEXTURE_2D);
+
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+
+ glOrtho(0, width,
+ 0, height, 0, 1);
+
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glLoadIdentity();
+ glMatrixMode(GL_TEXTURE);
+ glPushMatrix();
+ glLoadIdentity();
+
+ /* the actual drawing */
+ glColor3ub(255, 255, 255);
+ glRasterPos2s(xco, height-yco);
+ BMF_DrawString(G.fonts, text);
+
+ glMatrixMode(GL_TEXTURE);
+ glPopMatrix();
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+ glEnable(GL_DEPTH_TEST);
+}
+
+void BL_print_gamedebug_line_padded(char* text, int xco, int yco, int width, int height)
+{
+ /* This is a rather important line :( The gl-mode hasn't been left
+ * behind quite as neatly as we'd have wanted to. I don't know
+ * what cause it, though :/ .*/
+ glDisable(GL_TEXTURE_2D);
+
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+
+ glOrtho(0, width,
+ 0, height, 0, 1);
+
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glLoadIdentity();
+ glMatrixMode(GL_TEXTURE);
+ glPushMatrix();
+ glLoadIdentity();
+
+ /* draw in black first*/
+ glColor3ub(0, 0, 0);
+ glRasterPos2s(xco+1, height-yco-1);
+ BMF_DrawString(G.fonts, text);
+ glColor3ub(255, 255, 255);
+ glRasterPos2s(xco, height-yco);
+ BMF_DrawString(G.fonts, text);
+
+ glMatrixMode(GL_TEXTURE);
+ glPopMatrix();
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+ glEnable(GL_DEPTH_TEST);
+}
+
+void BL_HideMouse()
+{
+ set_cursor(CURSOR_NONE);
+}
+
+
+void BL_WaitMouse()
+{
+ set_cursor(CURSOR_WAIT);
+}
+
+
+void BL_NormalMouse()
+{
+ set_cursor(CURSOR_STD);
+}
+#define MAX_FILE_LENGTH 512
+
+
+void BL_MakeScreenShot(struct ScrArea *area, const char* filename)
+{
+ char copyfilename[MAX_FILE_LENGTH];
+ strcpy(copyfilename,filename);
+
+ // filename read - only
+
+ /* XXX will need to change at some point */
+ BIF_screendump();
+/* BIF_screendump(area); */
+
+ // write+read filename
+ write_screendump((char*) copyfilename);
+}
+
diff --git a/source/gameengine/BlenderRoutines/KX_BlenderGL.h b/source/gameengine/BlenderRoutines/KX_BlenderGL.h
new file mode 100644
index 00000000000..c3648a21810
--- /dev/null
+++ b/source/gameengine/BlenderRoutines/KX_BlenderGL.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 *****
+ */
+#ifndef __BLENDERGL
+#define __BLENDERGL
+
+#ifdef __cplusplus
+extern "C" {
+#endif //__cplusplus
+
+struct ScrArea;
+
+// special swapbuffers, that takes care of which area (viewport) needs to be swapped
+void BL_SwapBuffers();
+
+void BL_warp_pointer(int x,int y);
+
+void BL_MakeScreenShot(struct ScrArea *area, const char* filename);
+
+void BL_HideMouse();
+void BL_NormalMouse();
+void BL_WaitMouse();
+
+void BL_RenderText(int mode,const char* textstr,int textlen,struct TFace* tface,
+ float v1[3],float v2[3],float v3[3],float v4[3]);
+
+void BL_print_gamedebug_line(char* text, int xco, int yco, int width, int height);
+void BL_print_gamedebug_line_padded(char* text, int xco, int yco, int width, int height);
+
+
+
+#ifdef __cplusplus
+}
+#endif //__cplusplus
+
+
+#endif //__BLENDERGL
+
diff --git a/source/gameengine/BlenderRoutines/KX_BlenderInputDevice.cpp b/source/gameengine/BlenderRoutines/KX_BlenderInputDevice.cpp
new file mode 100644
index 00000000000..b364d4d40dd
--- /dev/null
+++ b/source/gameengine/BlenderRoutines/KX_BlenderInputDevice.cpp
@@ -0,0 +1,32 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "KX_BlenderInputDevice.h"
diff --git a/source/gameengine/BlenderRoutines/KX_BlenderInputDevice.h b/source/gameengine/BlenderRoutines/KX_BlenderInputDevice.h
new file mode 100644
index 00000000000..7a2951838fc
--- /dev/null
+++ b/source/gameengine/BlenderRoutines/KX_BlenderInputDevice.h
@@ -0,0 +1,220 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 __KX_BLENDERINPUTDEVICE
+#define __KX_BLENDERINPUTDEVICE
+
+#ifdef WIN32
+#pragma warning(disable : 4786) // shut off 255 char limit debug template warning
+#endif
+
+/* need to be here for conversion purposes */
+#include "mydevice.h"
+#include "SCA_IInputDevice.h"
+
+#include <map>
+/**
+ Base Class for Blender specific inputdevices. Blender specific inputdevices are used when the gameengine is running in embedded mode instead of standalone mode.
+*/
+class BL_BlenderInputDevice : public SCA_IInputDevice
+{
+ // this map is Blender specific: a conversion between blender and ketsji enums
+ std::map<int,KX_EnumInputs> m_reverseKeyTranslateTable;
+public:
+ BL_BlenderInputDevice()
+ {
+
+ /* The reverse table. In order to not confuse ourselves, we */
+ /* immediately convert all events that come in to KX codes. */
+ m_reverseKeyTranslateTable[LEFTMOUSE ] = KX_LEFTMOUSE ;
+ m_reverseKeyTranslateTable[MIDDLEMOUSE ] = KX_MIDDLEMOUSE ;
+ m_reverseKeyTranslateTable[RIGHTMOUSE ] = KX_RIGHTMOUSE ;
+ m_reverseKeyTranslateTable[MOUSEX ] = KX_MOUSEX ;
+ m_reverseKeyTranslateTable[MOUSEY ] = KX_MOUSEY ;
+
+ // TIMERS
+
+ m_reverseKeyTranslateTable[TIMER0 ] = KX_TIMER0 ;
+ m_reverseKeyTranslateTable[TIMER1 ] = KX_TIMER1 ;
+ m_reverseKeyTranslateTable[TIMER2 ] = KX_TIMER2 ;
+ m_reverseKeyTranslateTable[TIMER3 ] = KX_TIMER3 ;
+
+ // SYSTEM
+
+ m_reverseKeyTranslateTable[KEYBD ] = KX_KEYBD ;
+ m_reverseKeyTranslateTable[RAWKEYBD ] = KX_RAWKEYBD ;
+ m_reverseKeyTranslateTable[REDRAW ] = KX_REDRAW ;
+ m_reverseKeyTranslateTable[INPUTCHANGE ] = KX_INPUTCHANGE ;
+ m_reverseKeyTranslateTable[QFULL ] = KX_QFULL ;
+ m_reverseKeyTranslateTable[WINFREEZE ] = KX_WINFREEZE ;
+ m_reverseKeyTranslateTable[WINTHAW ] = KX_WINTHAW ;
+ m_reverseKeyTranslateTable[WINCLOSE ] = KX_WINCLOSE ;
+ m_reverseKeyTranslateTable[WINQUIT ] = KX_WINQUIT ;
+ m_reverseKeyTranslateTable[Q_FIRSTTIME ] = KX_Q_FIRSTTIME ;
+
+ // standard keyboard
+
+ m_reverseKeyTranslateTable[AKEY ] = KX_AKEY ;
+ m_reverseKeyTranslateTable[BKEY ] = KX_BKEY ;
+ m_reverseKeyTranslateTable[CKEY ] = KX_CKEY ;
+ m_reverseKeyTranslateTable[DKEY ] = KX_DKEY ;
+ m_reverseKeyTranslateTable[EKEY ] = KX_EKEY ;
+ m_reverseKeyTranslateTable[FKEY ] = KX_FKEY ;
+ m_reverseKeyTranslateTable[GKEY ] = KX_GKEY ;
+ m_reverseKeyTranslateTable[HKEY ] = KX_HKEY ;
+ m_reverseKeyTranslateTable[IKEY ] = KX_IKEY ;
+ m_reverseKeyTranslateTable[JKEY ] = KX_JKEY ;
+ m_reverseKeyTranslateTable[KKEY ] = KX_KKEY ;
+ m_reverseKeyTranslateTable[LKEY ] = KX_LKEY ;
+ m_reverseKeyTranslateTable[MKEY ] = KX_MKEY ;
+ m_reverseKeyTranslateTable[NKEY ] = KX_NKEY ;
+ m_reverseKeyTranslateTable[OKEY ] = KX_OKEY ;
+ m_reverseKeyTranslateTable[PKEY ] = KX_PKEY ;
+ m_reverseKeyTranslateTable[QKEY ] = KX_QKEY ;
+ m_reverseKeyTranslateTable[RKEY ] = KX_RKEY ;
+ m_reverseKeyTranslateTable[SKEY ] = KX_SKEY ;
+ m_reverseKeyTranslateTable[TKEY ] = KX_TKEY ;
+ m_reverseKeyTranslateTable[UKEY ] = KX_UKEY ;
+ m_reverseKeyTranslateTable[VKEY ] = KX_VKEY ;
+ m_reverseKeyTranslateTable[WKEY ] = KX_WKEY ;
+ m_reverseKeyTranslateTable[XKEY ] = KX_XKEY ;
+ m_reverseKeyTranslateTable[YKEY ] = KX_YKEY ;
+ m_reverseKeyTranslateTable[ZKEY ] = KX_ZKEY ;
+
+ m_reverseKeyTranslateTable[ZEROKEY ] = KX_ZEROKEY ;
+ m_reverseKeyTranslateTable[ONEKEY ] = KX_ONEKEY ;
+ m_reverseKeyTranslateTable[TWOKEY ] = KX_TWOKEY ;
+ m_reverseKeyTranslateTable[THREEKEY ] = KX_THREEKEY ;
+ m_reverseKeyTranslateTable[FOURKEY ] = KX_FOURKEY ;
+ m_reverseKeyTranslateTable[FIVEKEY ] = KX_FIVEKEY ;
+ m_reverseKeyTranslateTable[SIXKEY ] = KX_SIXKEY ;
+ m_reverseKeyTranslateTable[SEVENKEY ] = KX_SEVENKEY ;
+ m_reverseKeyTranslateTable[EIGHTKEY ] = KX_EIGHTKEY ;
+ m_reverseKeyTranslateTable[NINEKEY ] = KX_NINEKEY ;
+
+ m_reverseKeyTranslateTable[CAPSLOCKKEY ] = KX_CAPSLOCKKEY ;
+
+ m_reverseKeyTranslateTable[LEFTCTRLKEY ] = KX_LEFTCTRLKEY ;
+ m_reverseKeyTranslateTable[LEFTALTKEY ] = KX_LEFTALTKEY ;
+ m_reverseKeyTranslateTable[RIGHTALTKEY ] = KX_RIGHTALTKEY ;
+ m_reverseKeyTranslateTable[RIGHTCTRLKEY ] = KX_RIGHTCTRLKEY ;
+ m_reverseKeyTranslateTable[RIGHTSHIFTKEY ] = KX_RIGHTSHIFTKEY ;
+ m_reverseKeyTranslateTable[LEFTSHIFTKEY ] = KX_LEFTSHIFTKEY ;
+
+ m_reverseKeyTranslateTable[ESCKEY ] = KX_ESCKEY ;
+ m_reverseKeyTranslateTable[TABKEY ] = KX_TABKEY ;
+ m_reverseKeyTranslateTable[RETKEY ] = KX_RETKEY ;
+ m_reverseKeyTranslateTable[SPACEKEY ] = KX_SPACEKEY ;
+ m_reverseKeyTranslateTable[LINEFEEDKEY ] = KX_LINEFEEDKEY ;
+ m_reverseKeyTranslateTable[BACKSPACEKEY ] = KX_BACKSPACEKEY ;
+ m_reverseKeyTranslateTable[DELKEY ] = KX_DELKEY ;
+ m_reverseKeyTranslateTable[SEMICOLONKEY ] = KX_SEMICOLONKEY ;
+ m_reverseKeyTranslateTable[PERIODKEY ] = KX_PERIODKEY ;
+ m_reverseKeyTranslateTable[COMMAKEY ] = KX_COMMAKEY ;
+ m_reverseKeyTranslateTable[QUOTEKEY ] = KX_QUOTEKEY ;
+ m_reverseKeyTranslateTable[ACCENTGRAVEKEY ] = KX_ACCENTGRAVEKEY ;
+ m_reverseKeyTranslateTable[MINUSKEY ] = KX_MINUSKEY ;
+ m_reverseKeyTranslateTable[SLASHKEY ] = KX_SLASHKEY ;
+ m_reverseKeyTranslateTable[BACKSLASHKEY ] = KX_BACKSLASHKEY ;
+ m_reverseKeyTranslateTable[EQUALKEY ] = KX_EQUALKEY ;
+ m_reverseKeyTranslateTable[LEFTBRACKETKEY ] = KX_LEFTBRACKETKEY ;
+ m_reverseKeyTranslateTable[RIGHTBRACKETKEY ] = KX_RIGHTBRACKETKEY ;
+
+ m_reverseKeyTranslateTable[LEFTARROWKEY ] = KX_LEFTARROWKEY ;
+ m_reverseKeyTranslateTable[DOWNARROWKEY ] = KX_DOWNARROWKEY ;
+ m_reverseKeyTranslateTable[RIGHTARROWKEY ] = KX_RIGHTARROWKEY ;
+ m_reverseKeyTranslateTable[UPARROWKEY ] = KX_UPARROWKEY ;
+
+ m_reverseKeyTranslateTable[PAD2 ] = KX_PAD2 ;
+ m_reverseKeyTranslateTable[PAD4 ] = KX_PAD4 ;
+ m_reverseKeyTranslateTable[PAD6 ] = KX_PAD6 ;
+ m_reverseKeyTranslateTable[PAD8 ] = KX_PAD8 ;
+
+ m_reverseKeyTranslateTable[PAD1 ] = KX_PAD1 ;
+ m_reverseKeyTranslateTable[PAD3 ] = KX_PAD3 ;
+ m_reverseKeyTranslateTable[PAD5 ] = KX_PAD5 ;
+ m_reverseKeyTranslateTable[PAD7 ] = KX_PAD7 ;
+ m_reverseKeyTranslateTable[PAD9 ] = KX_PAD9 ;
+
+ m_reverseKeyTranslateTable[PADPERIOD ] = KX_PADPERIOD ;
+ m_reverseKeyTranslateTable[PADSLASHKEY ] = KX_PADSLASHKEY ;
+ m_reverseKeyTranslateTable[PADASTERKEY ] = KX_PADASTERKEY ;
+
+
+ m_reverseKeyTranslateTable[PAD0 ] = KX_PAD0 ;
+ m_reverseKeyTranslateTable[PADMINUS ] = KX_PADMINUS ;
+ m_reverseKeyTranslateTable[PADENTER ] = KX_PADENTER ;
+ m_reverseKeyTranslateTable[PADPLUSKEY ] = KX_PADPLUSKEY ;
+
+
+ m_reverseKeyTranslateTable[F1KEY ] = KX_F1KEY ;
+ m_reverseKeyTranslateTable[F2KEY ] = KX_F2KEY ;
+ m_reverseKeyTranslateTable[F3KEY ] = KX_F3KEY ;
+ m_reverseKeyTranslateTable[F4KEY ] = KX_F4KEY ;
+ m_reverseKeyTranslateTable[F5KEY ] = KX_F5KEY ;
+ m_reverseKeyTranslateTable[F6KEY ] = KX_F6KEY ;
+ m_reverseKeyTranslateTable[F7KEY ] = KX_F7KEY ;
+ m_reverseKeyTranslateTable[F8KEY ] = KX_F8KEY ;
+ m_reverseKeyTranslateTable[F9KEY ] = KX_F9KEY ;
+ m_reverseKeyTranslateTable[F10KEY ] = KX_F10KEY ;
+ m_reverseKeyTranslateTable[F11KEY ] = KX_F11KEY ;
+ m_reverseKeyTranslateTable[F12KEY ] = KX_F12KEY ;
+
+ m_reverseKeyTranslateTable[PAUSEKEY ] = KX_PAUSEKEY ;
+ m_reverseKeyTranslateTable[INSERTKEY ] = KX_INSERTKEY ;
+ m_reverseKeyTranslateTable[HOMEKEY ] = KX_HOMEKEY ;
+ m_reverseKeyTranslateTable[PAGEUPKEY ] = KX_PAGEUPKEY ;
+ m_reverseKeyTranslateTable[PAGEDOWNKEY ] = KX_PAGEDOWNKEY ;
+ m_reverseKeyTranslateTable[ENDKEY ] = KX_ENDKEY ;
+
+
+ }
+
+ virtual ~BL_BlenderInputDevice()
+ {
+
+ }
+
+ KX_EnumInputs ToNative(unsigned short incode) {
+ return m_reverseKeyTranslateTable[incode];
+ }
+
+ virtual bool IsPressed(SCA_IInputDevice::KX_EnumInputs inputcode)=0;
+// virtual const SCA_InputEvent& GetEventValue(SCA_IInputDevice::KX_EnumInputs inputcode)=0;
+ virtual bool ConvertBlenderEvent(unsigned short incode,short val)=0;
+
+};
+
+
+
+
+
+#endif //__KX_BLENDERINPUTDEVICE
diff --git a/source/gameengine/BlenderRoutines/KX_BlenderKeyboardDevice.cpp b/source/gameengine/BlenderRoutines/KX_BlenderKeyboardDevice.cpp
new file mode 100644
index 00000000000..81f233d6433
--- /dev/null
+++ b/source/gameengine/BlenderRoutines/KX_BlenderKeyboardDevice.cpp
@@ -0,0 +1,161 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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
+// annoying warnings about truncated STL debug info
+#pragma warning (disable :4786)
+#endif
+
+#include "KX_BlenderKeyboardDevice.h"
+
+KX_BlenderKeyboardDevice::KX_BlenderKeyboardDevice()
+{
+
+}
+KX_BlenderKeyboardDevice::~KX_BlenderKeyboardDevice()
+{
+
+}
+
+/**
+ IsPressed gives boolean information about keyboard status, true if pressed, false if not
+*/
+
+bool KX_BlenderKeyboardDevice::IsPressed(SCA_IInputDevice::KX_EnumInputs inputcode)
+{
+ const SCA_InputEvent & inevent = m_eventStatusTables[m_currentTable][inputcode];
+ bool pressed = (inevent.m_status == SCA_InputEvent::KX_JUSTACTIVATED ||
+ inevent.m_status == SCA_InputEvent::KX_ACTIVE);
+ return pressed;
+}
+/*const SCA_InputEvent& KX_BlenderKeyboardDevice::GetEventValue(SCA_IInputDevice::KX_EnumInputs inputcode)
+{
+ return m_eventStatusTables[m_currentTable][inputcode];
+}
+*/
+/**
+ NextFrame toggles currentTable with previousTable,
+ and copy relevant event information from previous to current
+ (pressed keys need to be remembered)
+*/
+void KX_BlenderKeyboardDevice::NextFrame()
+{
+ SCA_IInputDevice::NextFrame();
+
+ // now convert justpressed keyevents into regular (active) keyevents
+ int previousTable = 1-m_currentTable;
+ for (int keyevent= KX_BEGINKEY; keyevent< KX_ENDKEY;keyevent++)
+ {
+ SCA_InputEvent& oldevent = m_eventStatusTables[previousTable][keyevent];
+ if (oldevent.m_status == SCA_InputEvent::KX_JUSTACTIVATED ||
+ oldevent.m_status == SCA_InputEvent::KX_ACTIVE )
+ {
+ m_eventStatusTables[m_currentTable][keyevent] = oldevent;
+ m_eventStatusTables[m_currentTable][keyevent].m_status = SCA_InputEvent::KX_ACTIVE;
+ }
+ }
+}
+
+/**
+ ConvertBlenderEvent translates blender keyboard events into ketsji kbd events
+ extra event information is stored, like ramp-mode (just released/pressed)
+*/
+
+
+bool KX_BlenderKeyboardDevice::ConvertBlenderEvent(unsigned short incode,short val)
+{
+ bool result = false;
+
+ // convert event
+ KX_EnumInputs kxevent = this->ToNative(incode);
+
+ // only process it, if it's a key
+ if (kxevent >= KX_BEGINKEY && kxevent < KX_ENDKEY)
+ {
+ int previousTable = 1-m_currentTable;
+
+ if (val > 0)
+ {
+ if (kxevent == SCA_IInputDevice::KX_ESCKEY && val != 0)
+ result = true;
+
+ // todo: convert val ??
+ m_eventStatusTables[m_currentTable][kxevent].m_eventval = val ; //???
+
+ switch (m_eventStatusTables[previousTable][kxevent].m_status)
+ {
+ case SCA_InputEvent::KX_JUSTACTIVATED:
+ {
+ m_eventStatusTables[m_currentTable][kxevent].m_status = SCA_InputEvent::KX_ACTIVE;
+ break;
+ }
+ case SCA_InputEvent::KX_ACTIVE:
+
+ {
+ m_eventStatusTables[m_currentTable][kxevent].m_status = SCA_InputEvent::KX_ACTIVE;
+ break;
+ }
+ case SCA_InputEvent::KX_NO_INPUTSTATUS:
+ {
+ m_eventStatusTables[m_currentTable][kxevent].m_status = SCA_InputEvent::KX_JUSTACTIVATED;
+ break;
+ }
+ default:
+ {
+ m_eventStatusTables[m_currentTable][kxevent].m_status = SCA_InputEvent::KX_JUSTACTIVATED;
+ }
+ }
+
+ } else
+ {
+ // blender eventval == 0
+ switch (m_eventStatusTables[previousTable][kxevent].m_status)
+ {
+ case SCA_InputEvent::KX_JUSTACTIVATED:
+ {
+ m_eventStatusTables[m_currentTable][kxevent].m_status = SCA_InputEvent::KX_JUSTRELEASED;
+ break;
+ }
+ case SCA_InputEvent::KX_ACTIVE:
+ {
+ m_eventStatusTables[m_currentTable][kxevent].m_status = SCA_InputEvent::KX_JUSTRELEASED;
+ break;
+ }
+ default:
+ {
+ m_eventStatusTables[m_currentTable][kxevent].m_status = SCA_InputEvent::KX_NO_INPUTSTATUS;
+ }
+ }
+ }
+ }
+ return result;
+}
diff --git a/source/gameengine/BlenderRoutines/KX_BlenderKeyboardDevice.h b/source/gameengine/BlenderRoutines/KX_BlenderKeyboardDevice.h
new file mode 100644
index 00000000000..98791dba95b
--- /dev/null
+++ b/source/gameengine/BlenderRoutines/KX_BlenderKeyboardDevice.h
@@ -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 *****
+ */
+#ifndef __KX_BLENDERKEYBOARDDEVICE
+#define __KX_BLENDERKEYBOARDDEVICE
+
+#include "KX_BlenderInputDevice.h"
+
+class KX_BlenderKeyboardDevice : public BL_BlenderInputDevice
+{
+public:
+ KX_BlenderKeyboardDevice();
+ virtual ~KX_BlenderKeyboardDevice();
+
+ virtual bool IsPressed(SCA_IInputDevice::KX_EnumInputs inputcode);
+// virtual const SCA_InputEvent& GetEventValue(SCA_IInputDevice::KX_EnumInputs inputcode);
+ virtual bool ConvertBlenderEvent(unsigned short incode,short val);
+ virtual void NextFrame();
+};
+#endif //__KX_BLENDERKEYBOARDDEVICE
diff --git a/source/gameengine/BlenderRoutines/KX_BlenderMouseDevice.cpp b/source/gameengine/BlenderRoutines/KX_BlenderMouseDevice.cpp
new file mode 100644
index 00000000000..e3d4f36cc26
--- /dev/null
+++ b/source/gameengine/BlenderRoutines/KX_BlenderMouseDevice.cpp
@@ -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 *****
+ */
+
+
+#ifdef WIN32
+// annoying warnings about truncated STL debug info
+#pragma warning (disable :4786)
+#endif
+
+#include "KX_BlenderMouseDevice.h"
+
+KX_BlenderMouseDevice::KX_BlenderMouseDevice()
+{
+
+}
+KX_BlenderMouseDevice::~KX_BlenderMouseDevice()
+{
+
+}
+
+/**
+ IsPressed gives boolean information about mouse status, true if pressed, false if not
+*/
+
+bool KX_BlenderMouseDevice::IsPressed(SCA_IInputDevice::KX_EnumInputs inputcode)
+{
+ const SCA_InputEvent & inevent = m_eventStatusTables[m_currentTable][inputcode];
+ bool pressed = (inevent.m_status == SCA_InputEvent::KX_JUSTACTIVATED ||
+ inevent.m_status == SCA_InputEvent::KX_ACTIVE);
+ return pressed;
+}
+/*const SCA_InputEvent& KX_BlenderMouseDevice::GetEventValue(SCA_IInputDevice::KX_EnumInputs inputcode)
+{
+ return m_eventStatusTables[m_currentTable][inputcode];
+}
+*/
+
+/**
+ NextFrame toggles currentTable with previousTable,
+ and copy relevant event information from previous to current
+ (pressed keys need to be remembered)
+*/
+void KX_BlenderMouseDevice::NextFrame()
+{
+ SCA_IInputDevice::NextFrame();
+
+ // now convert justpressed keyevents into regular (active) keyevents
+ int previousTable = 1-m_currentTable;
+ for (int mouseevent= KX_BEGINMOUSE; mouseevent< KX_ENDMOUSEBUTTONS;mouseevent++)
+ {
+ SCA_InputEvent& oldevent = m_eventStatusTables[previousTable][mouseevent];
+ if (oldevent.m_status == SCA_InputEvent::KX_JUSTACTIVATED ||
+ oldevent.m_status == SCA_InputEvent::KX_ACTIVE )
+ {
+ m_eventStatusTables[m_currentTable][mouseevent] = oldevent;
+ m_eventStatusTables[m_currentTable][mouseevent].m_status = SCA_InputEvent::KX_ACTIVE;
+ }
+ }
+ for (int mousemove= KX_ENDMOUSEBUTTONS; mousemove< KX_ENDMOUSE;mousemove++)
+ {
+ SCA_InputEvent& oldevent = m_eventStatusTables[previousTable][mousemove];
+ m_eventStatusTables[m_currentTable][mousemove] = oldevent;
+ if (oldevent.m_status == SCA_InputEvent::KX_JUSTACTIVATED ||
+ oldevent.m_status == SCA_InputEvent::KX_ACTIVE )
+ {
+
+ m_eventStatusTables[m_currentTable][mousemove].m_status = SCA_InputEvent::KX_JUSTRELEASED;
+ } else
+ {
+ if (oldevent.m_status == SCA_InputEvent::KX_JUSTRELEASED)
+ {
+
+ m_eventStatusTables[m_currentTable][mousemove].m_status = SCA_InputEvent::KX_NO_INPUTSTATUS ;
+ }
+ }
+ }
+}
+
+
+/**
+ ConvertBlenderEvent translates blender mouse events into ketsji kbd events
+ extra event information is stored, like ramp-mode (just released/pressed)
+*/
+
+
+bool KX_BlenderMouseDevice::ConvertBlenderEvent(unsigned short incode,short val)
+{
+ bool result = false;
+
+ // convert event
+ KX_EnumInputs kxevent = this->ToNative(incode);
+
+ // only process it, if it's a key
+ if (kxevent > KX_BEGINMOUSE && kxevent < KX_ENDMOUSE)
+ {
+ int previousTable = 1-m_currentTable;
+
+
+ if (val > 0)
+ {
+ m_eventStatusTables[m_currentTable][kxevent].m_eventval = val ; //???
+
+ switch (m_eventStatusTables[previousTable][kxevent].m_status)
+ {
+
+ case SCA_InputEvent::KX_ACTIVE:
+ case SCA_InputEvent::KX_JUSTACTIVATED:
+ {
+ m_eventStatusTables[m_currentTable][kxevent].m_status = SCA_InputEvent::KX_ACTIVE;
+ break;
+ }
+ case SCA_InputEvent::KX_JUSTRELEASED:
+ {
+ if ( kxevent > KX_BEGINMOUSEBUTTONS && kxevent < KX_ENDMOUSEBUTTONS)
+ {
+ m_eventStatusTables[m_currentTable][kxevent].m_status = SCA_InputEvent::KX_JUSTACTIVATED;
+ } else
+ {
+ m_eventStatusTables[m_currentTable][kxevent].m_status = SCA_InputEvent::KX_ACTIVE;
+
+ }
+ break;
+ }
+ default:
+ {
+ m_eventStatusTables[m_currentTable][kxevent].m_status = SCA_InputEvent::KX_JUSTACTIVATED;
+ }
+ }
+
+ } else
+ {
+ // blender eventval == 0
+ switch (m_eventStatusTables[previousTable][kxevent].m_status)
+ {
+ case SCA_InputEvent::KX_JUSTACTIVATED:
+ case SCA_InputEvent::KX_ACTIVE:
+ {
+ m_eventStatusTables[m_currentTable][kxevent].m_status = SCA_InputEvent::KX_JUSTRELEASED;
+ break;
+ }
+ default:
+ {
+ m_eventStatusTables[m_currentTable][kxevent].m_status = SCA_InputEvent::KX_NO_INPUTSTATUS;
+ }
+ }
+ }
+ }
+ return result;
+}
diff --git a/source/gameengine/BlenderRoutines/KX_BlenderMouseDevice.h b/source/gameengine/BlenderRoutines/KX_BlenderMouseDevice.h
new file mode 100644
index 00000000000..6eb02622f9b
--- /dev/null
+++ b/source/gameengine/BlenderRoutines/KX_BlenderMouseDevice.h
@@ -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 *****
+ */
+#ifndef __KX_BLENDERMOUSEDEVICE
+#define __KX_BLENDERMOUSEDEVICE
+
+#include "KX_BlenderInputDevice.h"
+
+class KX_BlenderMouseDevice : public BL_BlenderInputDevice
+{
+public:
+ KX_BlenderMouseDevice();
+ virtual ~KX_BlenderMouseDevice();
+
+ virtual bool IsPressed(SCA_IInputDevice::KX_EnumInputs inputcode);
+// virtual const SCA_InputEvent& GetEventValue(SCA_IInputDevice::KX_EnumInputs inputcode);
+ virtual bool ConvertBlenderEvent(unsigned short incode,short val);
+ virtual void NextFrame();
+};
+#endif //__KX_BLENDERMOUSEDEVICE
diff --git a/source/gameengine/BlenderRoutines/KX_BlenderPolyMaterial.cpp b/source/gameengine/BlenderRoutines/KX_BlenderPolyMaterial.cpp
new file mode 100644
index 00000000000..fc7eb3a6c7f
--- /dev/null
+++ b/source/gameengine/BlenderRoutines/KX_BlenderPolyMaterial.cpp
@@ -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 *****
+ */
+
+
+#include "KX_BlenderPolyMaterial.h"
+#include "BKE_mesh.h"
+
+KX_BlenderPolyMaterial::KX_BlenderPolyMaterial(const STR_String &texname,
+ bool ba,
+ const STR_String& matname,
+ int tile,
+ int tilexrep,
+ int tileyrep,
+ int mode,
+ int transparant,
+ int lightlayer,
+ bool bIsTriangle,
+ void* clientobject,
+ struct TFace* tface)
+ : RAS_IPolyMaterial(texname,
+ false,
+ matname,
+ tile,
+ tilexrep,
+ tileyrep,
+ mode,
+ transparant,
+ lightlayer,
+ bIsTriangle,
+ clientobject),
+ m_tface(tface)
+{
+}
+
+
+void KX_BlenderPolyMaterial::Activate(RAS_IRasterizer* rasty, TCachingInfo& cachingInfo) const
+{
+
+
+ if (GetCachingInfo() != cachingInfo)
+ {
+ if (!cachingInfo)
+ {
+ set_tpage(NULL);
+ }
+ cachingInfo = GetCachingInfo();
+
+ if ((m_drawingmode & 4)&& (rasty->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED))
+ {
+ update_realtime_texture((struct TFace*) m_tface, rasty->GetTime());
+ set_tpage(m_tface);
+ rasty->EnableTextures(true);
+ }
+ else
+ {
+ set_tpage(NULL);
+ rasty->EnableTextures(false);
+ }
+
+ //TF_TWOSIDE == 512, todo, make this a ketsji enum
+ if(m_drawingmode & 512)
+ {
+ rasty->SetCullFace(false);
+ }
+ else
+ {
+ rasty->SetCullFace(true);
+ }
+ }
+
+ rasty->SetSpecularity(m_specular[0],m_specular[1],m_specular[2],m_specularity);
+ rasty->SetShinyness(m_shininess);
+ rasty->SetDiffuse(m_diffuse[0], m_diffuse[1],m_diffuse[2], 1.0);
+}
+
+
+
+
diff --git a/source/gameengine/BlenderRoutines/KX_BlenderPolyMaterial.h b/source/gameengine/BlenderRoutines/KX_BlenderPolyMaterial.h
new file mode 100644
index 00000000000..3513765410f
--- /dev/null
+++ b/source/gameengine/BlenderRoutines/KX_BlenderPolyMaterial.h
@@ -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 *****
+ */
+#ifndef __KX_BLENDERPOLYMATERIAL
+#define __KX_BLENDERPOLYMATERIAL
+
+#include "RAS_MaterialBucket.h"
+#include "RAS_IRasterizer.h"
+
+struct TFace;
+extern "C" int set_tpage(TFace* tface); /* Worst hack ever */
+
+
+class KX_BlenderPolyMaterial : public RAS_IPolyMaterial
+{
+ /** Blender texture face structure. */
+ TFace* m_tface;
+
+public:
+
+ KX_BlenderPolyMaterial(const STR_String &texname,
+ bool ba,
+ const STR_String& matname,
+ int tile,
+ int tilexrep,
+ int tileyrep,
+ int mode,
+ int transparant,
+ int lightlayer,
+ bool bIsTriangle,
+ void* clientobject,
+ struct TFace* tface);
+
+ /**
+ * Returns the caching information for this material,
+ * This can be used to speed up the rasterizing process.
+ * @return The caching information.
+ */
+ virtual TCachingInfo GetCachingInfo(void) const;
+
+ /**
+ * Activates the material in the (OpenGL) rasterizer.
+ * On entry, the cachingInfo contains info about the last activated material.
+ * On exit, the cachingInfo should contain updated info about this material.
+ * @param rasty The rasterizer in which the material should be active.
+ * @param cachingInfo The information about the material used to speed up rasterizing.
+ */
+ virtual void Activate(RAS_IRasterizer* rasty, TCachingInfo& cachingInfo) const;
+
+ /**
+ * Returns the Blender texture face structure that is used for this material.
+ * @return The material's texture face.
+ */
+ TFace* GetTFace(void) const;
+protected:
+private:
+};
+
+
+inline TFace* KX_BlenderPolyMaterial::GetTFace(void) const
+{
+ return m_tface;
+}
+
+inline RAS_IPolyMaterial::TCachingInfo KX_BlenderPolyMaterial::GetCachingInfo(void) const
+{
+ return GetTFace();
+}
+
+#endif // __KX_BLENDERPOLYMATERIAL
diff --git a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp
new file mode 100644
index 00000000000..4fdb9aafc33
--- /dev/null
+++ b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp
@@ -0,0 +1,411 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "KX_BlenderRenderTools.h"
+
+#ifdef WIN32
+// OpenGL gl.h needs 'windows.h' on windows platforms
+#include <windows.h>
+#endif //WIN32
+#include "GL/gl.h"
+
+#include "RAS_IRenderTools.h"
+#include "RAS_IRasterizer.h"
+#include "RAS_LightObject.h"
+#include "RAS_ICanvas.h"
+
+
+// next two includes/dependencies come from the shadow feature
+// it needs the gameobject and the sumo physics scene for a raycast
+#include "KX_GameObject.h"
+
+#include "KX_BlenderPolyMaterial.h"
+#include "Value.h"
+
+#include "KX_BlenderGL.h" // for text printing
+#include "STR_String.h"
+#include "RAS_BucketManager.h" // for polymaterial (needed for textprinting)
+
+KX_BlenderRenderTools::KX_BlenderRenderTools()
+{
+}
+
+/**
+ProcessLighting performs lighting on objects. the layer is a bitfield that contains layer information.
+There are 20 'official' layers in blender.
+A light is applied on an object only when they are in the same layer.
+OpenGL has a maximum of 8 lights (simultaneous), so 20 * 8 lights are possible in a scene.
+*/
+
+int KX_BlenderRenderTools::ProcessLighting(int layer)
+{
+
+ int result = false;
+
+ if (layer < 0)
+ {
+ DisableOpenGLLights();
+ result = false;
+ } else
+ {
+ if (m_clientobject)
+ {
+
+
+ if (applyLights(layer))
+ {
+ EnableOpenGLLights();
+ result = true;
+ } else
+ {
+ DisableOpenGLLights();
+ result = false;
+ }
+
+
+ }
+ }
+ return result;
+
+
+}
+
+
+void KX_BlenderRenderTools::BeginFrame(RAS_IRasterizer* rasty)
+{
+ m_clientobject = NULL;
+ m_lastblenderobject = NULL;
+ m_lastblenderlights = false;
+ m_lastlayer = -1;
+ m_lastlighting = false;
+ m_modified = true;
+ DisableOpenGLLights();
+
+
+}
+
+
+void KX_BlenderRenderTools::applyTransform(RAS_IRasterizer* rasty,double* oglmatrix,int objectdrawmode )
+{
+ if (objectdrawmode & RAS_IPolyMaterial::BILLBOARD_SCREENALIGNED ||
+ objectdrawmode & RAS_IPolyMaterial::BILLBOARD_AXISALIGNED)
+ {
+ // rotate the billboard/halo
+ //page 360/361 3D Game Engine Design, David Eberly for a discussion
+ // on screen aligned and axis aligned billboards
+ // assumed is that the preprocessor transformed all billboard polygons
+ // so that their normal points into the positive x direction (1.0 , 0.0 , 0.0)
+ // when new parenting for objects is done, this rotation
+ // will be moved into the object
+
+ MT_Point3 objpos (oglmatrix[12],oglmatrix[13],oglmatrix[14]);
+ MT_Point3 campos = rasty->GetCameraPosition();
+ MT_Vector3 dir = (campos - objpos).safe_normalized();
+ MT_Vector3 up(0,0,1.0);
+
+ KX_GameObject* gameobj = (KX_GameObject*) this->m_clientobject;
+ // get scaling of halo object
+ MT_Vector3 size = gameobj->GetSGNode()->GetLocalScale();
+
+ bool screenaligned = (objectdrawmode & RAS_IPolyMaterial::BILLBOARD_SCREENALIGNED)!=0;//false; //either screen or axisaligned
+ if (screenaligned)
+ {
+ up = (up - up.dot(dir) * dir).safe_normalized();
+ } else
+ {
+ dir = (dir - up.dot(dir)*up).safe_normalized();
+ }
+
+ MT_Vector3 left = dir.normalized();
+ dir = (left.cross(up)).normalized();
+
+ // we have calculated the row vectors, now we keep
+ // local scaling into account:
+
+ left *= size[0];
+ dir *= size[1];
+ up *= size[2];
+ double maat[16]={
+ left[0], left[1],left[2], 0,
+ dir[0], dir[1],dir[2],0,
+ up[0],up[1],up[2],0,
+ 0,0,0,1};
+ glTranslated(objpos[0],objpos[1],objpos[2]);
+ glMultMatrixd(maat);
+
+ } else
+ {
+ if (objectdrawmode & RAS_IPolyMaterial::SHADOW)
+ {
+ // shadow must be cast to the ground, physics system needed here!
+ KX_GameObject* gameobj = (KX_GameObject*) this->m_clientobject;
+ MT_Point3 frompoint(oglmatrix[12],oglmatrix[13],oglmatrix[14]);
+ MT_Vector3 direction = MT_Vector3(0,0,-1);
+
+
+ direction.normalize();
+ direction *= 100000;
+
+ MT_Point3 topoint = frompoint + direction;
+ MT_Point3 resultpoint;
+ MT_Vector3 resultnormal;
+
+ //todo:
+ //use physics abstraction
+
+
+ //SM_Scene* scene = (SM_Scene*) m_auxilaryClientInfo;
+
+ //SM_Object* hitObj = scene->rayTest(gameobj->GetSumoObject(),frompoint,topoint,
+ // resultpoint, resultnormal);
+
+
+ if (0) //hitObj)
+ {
+ MT_Vector3 left(oglmatrix[0],oglmatrix[1],oglmatrix[2]);
+ MT_Vector3 dir = -(left.cross(resultnormal)).normalized();
+ left = (dir.cross(resultnormal)).normalized();
+ // for the up vector, we take the 'resultnormal' returned by the physics
+
+ double maat[16]={
+ left[0], left[1],left[2], 0,
+ dir[0], dir[1],dir[2],0,
+ resultnormal[0],resultnormal[1],resultnormal[2],0,
+ 0,0,0,1};
+ glTranslated(resultpoint[0],resultpoint[1],resultpoint[2]);
+ glMultMatrixd(maat);
+ // glMultMatrixd(oglmatrix);
+ } else
+ {
+ glMultMatrixd(oglmatrix);
+ }
+
+
+ } else
+ {
+
+ // 'normal' object
+ glMultMatrixd(oglmatrix);
+ }
+ }
+}
+
+
+/**
+Render Text renders text into a (series of) polygon, using a texture font,
+Each character consists of one polygon (one quad or two triangles)
+*/
+void KX_BlenderRenderTools::RenderText(int mode,RAS_IPolyMaterial* polymat,float v1[3],float v2[3],float v3[3],float v4[3])
+{
+
+ STR_String mytext = ((CValue*)m_clientobject)->GetPropertyText("Text");
+
+ KX_BlenderPolyMaterial* blenderpoly = (KX_BlenderPolyMaterial*)polymat;
+ struct TFace* tface = blenderpoly->GetTFace();
+
+ BL_RenderText( mode,mytext,mytext.Length(),tface,v1,v2,v3,v4);
+
+}
+
+
+
+KX_BlenderRenderTools::~KX_BlenderRenderTools()
+{
+};
+
+
+void KX_BlenderRenderTools::EndFrame(RAS_IRasterizer* rasty)
+{
+}
+
+
+
+void KX_BlenderRenderTools::DisableOpenGLLights()
+{
+ glDisable(GL_LIGHTING);
+ glDisable(GL_COLOR_MATERIAL);
+#ifndef SLOWPAINT
+ glDisableClientState(GL_NORMAL_ARRAY);
+#endif //SLOWPAINT
+}
+
+
+void KX_BlenderRenderTools::EnableOpenGLLights()
+{
+ glEnable(GL_LIGHTING);
+
+ glColorMaterial(GL_FRONT_AND_BACK,GL_DIFFUSE);
+ glEnable(GL_COLOR_MATERIAL);
+#ifndef SLOWPAINT
+ glEnableClientState(GL_NORMAL_ARRAY);
+#endif //SLOWPAINT
+ glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, false);
+}
+
+
+/**
+ * Rendering text using 2D bitmap functionality.
+ */
+void KX_BlenderRenderTools::RenderText2D(RAS_TEXT_RENDER_MODE mode,
+ const char* text,
+ int xco,
+ int yco,
+ int width,
+ int height)
+{
+ switch (mode) {
+ case RAS_IRenderTools::RAS_TEXT_PADDED: {
+ STR_String tmpstr(text);
+ BL_print_gamedebug_line_padded(tmpstr.Ptr(),xco,yco,width,height);
+ break;
+ }
+ default: {
+ STR_String tmpstr(text);
+ BL_print_gamedebug_line(tmpstr.Ptr(),xco,yco,width,height);
+ }
+ }
+}
+
+
+
+void KX_BlenderRenderTools::PushMatrix()
+{
+ glPushMatrix();
+}
+
+void KX_BlenderRenderTools::PopMatrix()
+{
+ glPopMatrix();
+}
+
+
+
+int KX_BlenderRenderTools::applyLights(int objectlayer)
+{
+// taken from blender source, incompatibility between Blender Object / GameObject
+
+ int count;
+ float vec[4];
+
+ vec[3]= 1.0;
+
+ for(count=0; count<8; count++)
+ glDisable((GLenum)(GL_LIGHT0+count));
+
+ count= 0;
+
+ //std::vector<struct RAS_LightObject*> m_lights;
+ std::vector<struct RAS_LightObject*>::iterator lit = m_lights.begin();
+
+
+ for (lit = m_lights.begin(); !(lit==m_lights.end()); ++lit)
+ {
+ RAS_LightObject* lightdata = (*lit);
+ if (lightdata->m_layer & objectlayer)
+ {
+
+ glPushMatrix();
+ glLoadMatrixf(m_viewmat);
+
+
+ vec[0] = (*(lightdata->m_worldmatrix))(0,3);
+ vec[1] = (*(lightdata->m_worldmatrix))(1,3);
+ vec[2] = (*(lightdata->m_worldmatrix))(2,3);
+ vec[3] = 1;
+
+
+ if(lightdata->m_type==RAS_LightObject::LIGHT_SUN) {
+
+ vec[0] = (*(lightdata->m_worldmatrix))(0,2);
+ vec[1] = (*(lightdata->m_worldmatrix))(1,2);
+ vec[2] = (*(lightdata->m_worldmatrix))(2,2);
+ //vec[0]= base->object->obmat[2][0];
+ //vec[1]= base->object->obmat[2][1];
+ //vec[2]= base->object->obmat[2][2];
+ vec[3]= 0.0;
+ glLightfv((GLenum)(GL_LIGHT0+count), GL_POSITION, vec);
+ }
+ else {
+ //vec[3]= 1.0;
+ glLightfv((GLenum)(GL_LIGHT0+count), GL_POSITION, vec);
+ glLightf((GLenum)(GL_LIGHT0+count), GL_CONSTANT_ATTENUATION, 1.0);
+ glLightf((GLenum)(GL_LIGHT0+count), GL_LINEAR_ATTENUATION, lightdata->m_att1/lightdata->m_distance);
+ // without this next line it looks backward compatible.
+ //attennuation still is acceptable
+ // glLightf((GLenum)(GL_LIGHT0+count), GL_QUADRATIC_ATTENUATION, la->att2/(la->dist*la->dist));
+
+ if(lightdata->m_type==RAS_LightObject::LIGHT_SPOT) {
+ vec[0] = -(*(lightdata->m_worldmatrix))(0,2);
+ vec[1] = -(*(lightdata->m_worldmatrix))(1,2);
+ vec[2] = -(*(lightdata->m_worldmatrix))(2,2);
+ //vec[0]= -base->object->obmat[2][0];
+ //vec[1]= -base->object->obmat[2][1];
+ //vec[2]= -base->object->obmat[2][2];
+ glLightfv((GLenum)(GL_LIGHT0+count), GL_SPOT_DIRECTION, vec);
+ glLightf((GLenum)(GL_LIGHT0+count), GL_SPOT_CUTOFF, lightdata->m_spotsize/2.0);
+ glLightf((GLenum)(GL_LIGHT0+count), GL_SPOT_EXPONENT, 128.0*lightdata->m_spotblend);
+ }
+ else glLightf((GLenum)(GL_LIGHT0+count), GL_SPOT_CUTOFF, 180.0);
+ }
+
+ vec[0]= lightdata->m_energy*lightdata->m_red;
+ vec[1]= lightdata->m_energy*lightdata->m_green;
+ vec[2]= lightdata->m_energy*lightdata->m_blue;
+ vec[3]= 1.0;
+ glLightfv((GLenum)(GL_LIGHT0+count), GL_DIFFUSE, vec);
+ glLightfv((GLenum)(GL_LIGHT0+count), GL_SPECULAR, vec);
+ glEnable((GLenum)(GL_LIGHT0+count));
+
+ glPopMatrix();
+
+ count++;
+ if(count>7)
+ break;
+ }
+ }
+
+ return count;
+
+}
+
+
+
+RAS_IPolyMaterial* KX_BlenderRenderTools::CreateBlenderPolyMaterial(
+ const STR_String &texname,
+ bool ba,const STR_String& matname,int tile,int tilexrep,int tileyrep,int mode,int transparant,int lightlayer
+ ,bool bIsTriangle,void* clientobject,void* tface)
+{
+ return new KX_BlenderPolyMaterial(
+
+ texname,
+ ba,matname,tile,tilexrep,tileyrep,mode,transparant,lightlayer
+ ,bIsTriangle,clientobject,(struct TFace*)tface);
+}
diff --git a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.h b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.h
new file mode 100644
index 00000000000..fb4c5a6f2ba
--- /dev/null
+++ b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.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 __KX_BLENDERRENDERTOOLS
+#define __KX_BLENDERRENDERTOOLS
+
+#ifdef WIN32
+// don't show stl-warnings
+#pragma warning (disable:4786)
+#endif
+
+#include "RAS_IRenderTools.h"
+
+/**
+BlenderRenderTools are a set of tools to apply 2D/3D graphics effects, which are not
+part of the (polygon) Rasterizer.
+Effects like 2D text, 3D (polygon) text, lighting.
+*/
+
+class KX_BlenderRenderTools : public RAS_IRenderTools
+{
+ bool m_lastblenderlights;
+ void* m_lastblenderobject;
+ int m_lastlayer;
+ bool m_lastlighting;
+
+public:
+
+ KX_BlenderRenderTools();
+ virtual ~KX_BlenderRenderTools();
+
+ virtual void EndFrame(class RAS_IRasterizer* rasty);
+ virtual void BeginFrame(class RAS_IRasterizer* rasty);
+ void DisableOpenGLLights();
+ void EnableOpenGLLights();
+ int ProcessLighting(int layer);
+
+ virtual void RenderText2D(RAS_TEXT_RENDER_MODE mode,
+ const char* text,
+ int xco,
+ int yco,
+ int width,
+ int height);
+ virtual void RenderText(int mode,
+ class RAS_IPolyMaterial* polymat,
+ float v1[3],
+ float v2[3],
+ float v3[3],
+ float v4[3]);
+ void applyTransform(class RAS_IRasterizer* rasty,
+ double* oglmatrix,
+ int objectdrawmode );
+ int applyLights(int objectlayer);
+ virtual void PushMatrix();
+ virtual void PopMatrix();
+
+ virtual class RAS_IPolyMaterial* CreateBlenderPolyMaterial(const STR_String &texname,
+ bool ba,
+ const STR_String& matname,
+ int tile,
+ int tilexrep,
+ int tileyrep,
+ int mode,
+ int transparant,
+ int lightlayer,
+ bool bIsTriangle,
+ void* clientobject,
+ void* tface);
+};
+
+
+#endif //__KX_BLENDERRENDERTOOLS
diff --git a/source/gameengine/BlenderRoutines/KX_BlenderSystem.cpp b/source/gameengine/BlenderRoutines/KX_BlenderSystem.cpp
new file mode 100644
index 00000000000..f690f7c74e2
--- /dev/null
+++ b/source/gameengine/BlenderRoutines/KX_BlenderSystem.cpp
@@ -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 *****
+ */
+
+#include "KX_ISystem.h"
+
+
+#ifdef WIN32
+#pragma warning (disable :4786)
+#include <windows.h>
+#endif //WIN32
+
+#include <iostream>
+#include <stdio.h>
+#include "KX_BlenderInputDevice.h"
+#include "KX_BlenderSystem.h"
+
+#include "PIL_time.h"
+
+KX_BlenderSystem::KX_BlenderSystem()
+: KX_ISystem()
+{
+ m_starttime = PIL_check_seconds_timer();
+}
+
+double KX_BlenderSystem::GetTimeInSeconds()
+{
+ return PIL_check_seconds_timer() - m_starttime;
+}
diff --git a/source/gameengine/BlenderRoutines/KX_BlenderSystem.h b/source/gameengine/BlenderRoutines/KX_BlenderSystem.h
new file mode 100644
index 00000000000..68db3194b0a
--- /dev/null
+++ b/source/gameengine/BlenderRoutines/KX_BlenderSystem.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 __KX_BLENDERSYSTEM
+#define __KX_BLENDERSYSTEM
+
+#include "blendertimer.h"
+
+/**
+ * Blender System embedding. Needed when gameengine runs embedded within Blender.
+ */
+#include "KX_ISystem.h"
+
+class KX_BlenderSystem : public KX_ISystem
+{
+ double m_starttime;
+
+public:
+ KX_BlenderSystem();
+ virtual ~KX_BlenderSystem() {};
+ virtual double GetTimeInSeconds();
+};
+#endif //__KX_BLENDERSYSTEM
diff --git a/source/gameengine/BlenderRoutines/Makefile b/source/gameengine/BlenderRoutines/Makefile
new file mode 100644
index 00000000000..9a4ba217ac7
--- /dev/null
+++ b/source/gameengine/BlenderRoutines/Makefile
@@ -0,0 +1,75 @@
+#
+# $Id$
+#
+# ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version. The Blender
+# Foundation also sells licenses for use in proprietary software under
+# the Blender License. See http://www.blender.org/BL/ for information
+# about this.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2001-2002 by 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 = bloutines
+DIR = $(OCGDIR)/gameengine/$(LIBNAME)
+
+include nan_compile.mk
+
+CCFLAGS += $(LEVEL_1_CPP_WARNINGS)
+
+CPPFLAGS += -I$(OPENGL_HEADERS)
+CPPFLAGS += -I$(NAN_SUMO)/include
+CPPFLAGS += -I$(NAN_STRING)/include
+CPPFLAGS += -I$(NAN_MOTO)/include
+CPPFLAGS += -I$(NAN_BMFONT)/include
+CPPFLAGS += -I$(NAN_FUZZICS)/include
+# because of kernel dependency on makesdna
+CPPFLAGS += -I../../blender/makesdna
+CPPFLAGS += -I../../blender/include
+# timer stuff
+CPPFLAGS += -I../../blender/misc
+# because of kernel dependency on imbuf
+CPPFLAGS += -I../../blender/imbuf
+CPPFLAGS += -I../../blender/blenlib
+CPPFLAGS += -I../../blender/blenkernel
+CPPFLAGS += -I../../blender/render/extern/include
+CPPFLAGS += -I../../blender/blenloader
+CPPFLAGS += -I../../blender/blenkernel
+CPPFLAGS += -I../Converter
+CPPFLAGS += -I../Expressions
+CPPFLAGS += -I../GameLogic
+CPPFLAGS += -I../Ketsji
+CPPFLAGS += -I../Rasterizer
+CPPFLAGS += -I../Rasterizer/RAS_OpenGLRasterizer
+CPPFLAGS += -I../SceneGraph
+CPPFLAGS += -I../SoundSystem
+CPPFLAGS += -I../../kernel/gen_system
+CPPFLAGS += -I../Network
+CPPFLAGS += -I../Network/LoopBackNetwork
+ifeq ($(OS),windows)
+ CPPFLAGS += -I../../blender
+endif
+
+CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION)
+
diff --git a/source/gameengine/Converter/BL_ActionActuator.cpp b/source/gameengine/Converter/BL_ActionActuator.cpp
new file mode 100644
index 00000000000..cbe0dd2263c
--- /dev/null
+++ b/source/gameengine/Converter/BL_ActionActuator.cpp
@@ -0,0 +1,805 @@
+/**
+* $Id$
+*
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "SCA_LogicManager.h"
+#include "BL_ActionActuator.h"
+#include "BL_ArmatureObject.h"
+#include "BL_SkinDeformer.h"
+#include "KX_GameObject.h"
+#include "STR_HashedString.h"
+#include "DNA_action_types.h"
+#include "DNA_actuator_types.h"
+#include "BKE_action.h"
+#include "DNA_armature_types.h"
+#include "MEM_guardedalloc.h"
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "MT_Matrix4x4.h"
+#include "BKE_utildefines.h"
+
+BL_ActionActuator::~BL_ActionActuator()
+{
+ if (m_pose) {
+ clear_pose(m_pose);
+ MEM_freeN(m_pose);
+ m_pose = NULL;
+ };
+
+ if (m_userpose){
+ clear_pose(m_userpose);
+ MEM_freeN(m_userpose);
+ m_userpose=NULL;
+ }
+ if (m_blendpose) {
+ clear_pose(m_blendpose);
+ MEM_freeN(m_blendpose);
+ m_blendpose = NULL;
+ };
+
+}
+
+void BL_ActionActuator::ProcessReplica(){
+ bPose *oldpose = m_pose;
+ bPose *oldbpose = m_blendpose;
+
+ m_pose = NULL;
+ m_blendpose = NULL;
+ m_localtime=m_starttime;
+ m_lastUpdate=-1;
+
+}
+
+void BL_ActionActuator::SetBlendTime (float newtime){
+ m_blendframe = newtime;
+}
+
+CValue* BL_ActionActuator::GetReplica() {
+ BL_ActionActuator* replica = new BL_ActionActuator(*this);//m_float,GetName());
+ replica->ProcessReplica();
+
+ // this will copy properties and so on...
+ CValue::AddDataToReplica(replica);
+ return replica;
+};
+
+bool BL_ActionActuator::Update(double curtime,double deltatime)
+{
+ bool bNegativeEvent = false;
+ bool bPositiveEvent = false;
+ int numevents = m_events.size();
+ bool keepgoing = true;
+ bool wrap = false;
+ bool apply=true;
+ int priority;
+ float newweight;
+
+ // result = true if animation has to be continued, false if animation stops
+ // maybe there are events for us in the queue !
+
+ for (vector<CValue*>::iterator i=m_events.end(); !(i==m_events.begin());)
+ {
+ i--;
+ if ((*i)->GetNumber() == 0.0f)
+ {
+ int ka=0;
+ bNegativeEvent = true;
+ }
+ else
+ bPositiveEvent= true;
+ (*i)->Release();
+ m_events.pop_back();
+ }
+
+ /* We know that action actuators have been discarded from all non armature objects:
+ if we're being called, we're attached to a BL_ArmatureObject */
+ BL_ArmatureObject *obj = (BL_ArmatureObject*)GetParent();
+ int length = m_endtime - m_starttime;
+
+ priority = m_priority;
+
+ /* Determine pre-incrementation behaviour and set appropriate flags */
+ switch (m_playtype){
+ case ACT_ACTION_MOTION:
+ if (bNegativeEvent){
+ keepgoing=false;
+ apply=false;
+ };
+ break;
+ case ACT_ACTION_FROM_PROP:
+ if (bNegativeEvent){
+ apply=false;
+ keepgoing=false;
+ }
+ break;
+ case ACT_ACTION_LOOP_END:
+ if (bPositiveEvent){
+ if (!(m_flag & ACT_FLAG_LOCKINPUT)){
+ m_flag &= ~ACT_FLAG_KEYUP;
+ m_flag &= ~ACT_FLAG_REVERSE;
+ m_flag |= ACT_FLAG_LOCKINPUT;
+ m_localtime = m_starttime;
+ }
+ }
+ if (bNegativeEvent){
+ m_flag |= ACT_FLAG_KEYUP;
+ }
+ break;
+ case ACT_ACTION_LOOP_STOP:
+ if (bPositiveEvent){
+ if (!(m_flag & ACT_FLAG_LOCKINPUT)){
+ m_flag &= ~ACT_FLAG_REVERSE;
+ }
+ }
+ if (bNegativeEvent){
+ keepgoing=false;
+ apply=false;
+ }
+ break;
+ case ACT_ACTION_FLIPPER:
+ if (bPositiveEvent){
+ if (!(m_flag & ACT_FLAG_LOCKINPUT)){
+ m_flag &= ~ACT_FLAG_REVERSE;
+ }
+ }
+ else if (bNegativeEvent){
+ m_flag |= ACT_FLAG_REVERSE;
+ }
+ break;
+ case ACT_ACTION_PLAY:
+ if (bPositiveEvent){
+ if (!(m_flag & ACT_FLAG_LOCKINPUT)){
+ m_flag &= ~ACT_FLAG_REVERSE;
+ m_localtime = m_starttime;
+ m_flag |= ACT_FLAG_LOCKINPUT;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ /* Perform increment */
+ if (keepgoing){
+ if (m_playtype == ACT_ACTION_MOTION){
+ MT_Point3 newpos;
+ MT_Point3 deltapos;
+
+ newpos = obj->NodeGetWorldPosition();
+
+ /* Find displacement */
+ deltapos = newpos-m_lastpos;
+ m_localtime += (length/m_stridelength) * deltapos.length();
+ m_lastpos = newpos;
+ }
+ else{
+ if (m_flag & ACT_FLAG_REVERSE)
+ m_localtime -= deltatime* KX_FIXED_FRAME_PER_SEC;
+ else
+ m_localtime += deltatime* KX_FIXED_FRAME_PER_SEC;
+ }
+ }
+
+ /* Check if a wrapping response is needed */
+ if (length){
+ if (m_flag & ACT_FLAG_REVERSE){
+ if (m_localtime < m_starttime){
+ m_localtime = m_endtime+(
+ (int)((m_localtime - m_starttime)/length)
+ *(int)length);
+ wrap = true;
+ }
+ }
+ else{
+ if (m_localtime > m_endtime){
+ m_localtime = m_starttime+(
+ (int)((m_localtime - m_endtime)/length)
+ *(int)length);
+ wrap = true;
+ }
+ }
+
+ }
+ else
+ m_localtime = m_starttime;
+
+ /* Perform post-increment tasks */
+ switch (m_playtype){
+ case ACT_ACTION_FROM_PROP:
+ {
+ CValue* propval = GetParent()->GetProperty(m_propname);
+ if (propval) {
+ m_localtime = propval->GetNumber();
+ };
+
+ if (bNegativeEvent){
+ keepgoing=false;
+ }
+ }
+ break;
+ case ACT_ACTION_MOTION:
+ break;
+ case ACT_ACTION_LOOP_STOP:
+ break;
+ case ACT_ACTION_FLIPPER:
+ if (wrap){
+ if (!(m_flag & ACT_FLAG_REVERSE)){
+ m_localtime=m_endtime;
+ keepgoing = false;
+ }
+ else {
+ m_localtime=m_starttime;
+ keepgoing = false;
+ }
+ }
+ break;
+ case ACT_ACTION_LOOP_END:
+ if (wrap){
+ if (m_flag & ACT_FLAG_KEYUP){
+ keepgoing = false;
+ m_localtime = m_endtime;
+ m_flag &= ~ACT_FLAG_LOCKINPUT;
+ }
+ }
+ break;
+ case ACT_ACTION_PLAY:
+ if (wrap){
+ m_localtime = m_endtime;
+ keepgoing = false;
+ m_flag &= ~ACT_FLAG_LOCKINPUT;
+ }
+ break;
+ default:
+ keepgoing = false;
+ break;
+ }
+
+
+ if (bNegativeEvent){
+ m_blendframe=0.0;
+
+ }
+
+
+ /* Apply the pose if necessary*/
+ if (apply){
+
+ /* Priority test */
+ if (obj->SetActiveAction(this, priority, curtime)){
+
+ /* Get the underlying pose from the armature */
+ obj->GetPose(&m_pose);
+
+ /* Override the necessary channels with ones from the action */
+ get_pose_from_action(&m_pose, m_action, m_localtime);
+
+ /* Perform the user override (if any) */
+ if (m_userpose){
+ get_pose_from_pose(&m_pose, m_userpose);
+ clear_pose(m_userpose);
+ MEM_freeN(m_userpose);
+ m_userpose = NULL;
+ }
+#if 1
+ /* Handle blending */
+ if (m_blendin && (m_blendframe<m_blendin)){
+ /* If this is the start of a blending sequence... */
+ if ((m_blendframe==0.0) || (!m_blendpose)){
+ obj->GetMRDPose(&m_blendpose);
+ }
+
+ /* Find percentages */
+ newweight = (m_blendframe/(float)m_blendin);
+ blend_poses(m_pose, m_blendpose, 1.0 - newweight, POSE_BLEND);
+
+ /* Increment current blending percentage */
+ m_blendframe+=(deltatime*KX_FIXED_FRAME_PER_SEC);
+ if (m_blendframe>m_blendin)
+ m_blendframe = m_blendin;
+
+ }
+#endif
+ m_lastUpdate = m_localtime;
+ obj->SetPose (m_pose);
+ }
+ else{
+ m_blendframe = 0.0;
+ }
+ }
+
+ if (!keepgoing){
+ m_blendframe = 0.0;
+ }
+ return keepgoing;
+};
+
+/* ------------------------------------------------------------------------- */
+/* Python functions */
+/* ------------------------------------------------------------------------- */
+
+/* Integration hooks ------------------------------------------------------- */
+
+PyTypeObject BL_ActionActuator::Type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0,
+ "BL_ActionActuator",
+ sizeof(BL_ActionActuator),
+ 0,
+ PyDestructor,
+ 0,
+ __getattr,
+ __setattr,
+ 0, //&MyPyCompare,
+ __repr,
+ 0, //&cvalue_as_number,
+ 0,
+ 0,
+ 0,
+ 0
+};
+
+PyParentObject BL_ActionActuator::Parents[] = {
+ &BL_ActionActuator::Type,
+ &SCA_IActuator::Type,
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
+};
+
+PyMethodDef BL_ActionActuator::Methods[] = {
+ {"setAction", (PyCFunction) BL_ActionActuator::sPySetAction, METH_VARARGS, SetAction_doc},
+ {"setStart", (PyCFunction) BL_ActionActuator::sPySetStart, METH_VARARGS, SetStart_doc},
+ {"setEnd", (PyCFunction) BL_ActionActuator::sPySetEnd, METH_VARARGS, SetEnd_doc},
+ {"setBlendin", (PyCFunction) BL_ActionActuator::sPySetBlendin, METH_VARARGS, SetBlendin_doc},
+ {"setPriority", (PyCFunction) BL_ActionActuator::sPySetPriority, METH_VARARGS, SetPriority_doc},
+ {"setFrame", (PyCFunction) BL_ActionActuator::sPySetFrame, METH_VARARGS, SetFrame_doc},
+ {"setProperty", (PyCFunction) BL_ActionActuator::sPySetProperty, METH_VARARGS, SetProperty_doc},
+ {"setBlendtime", (PyCFunction) BL_ActionActuator::sPySetBlendtime, METH_VARARGS, SetBlendtime_doc},
+
+ {"getAction", (PyCFunction) BL_ActionActuator::sPyGetAction, METH_VARARGS, GetAction_doc},
+ {"getStart", (PyCFunction) BL_ActionActuator::sPyGetStart, METH_VARARGS, GetStart_doc},
+ {"getEnd", (PyCFunction) BL_ActionActuator::sPyGetEnd, METH_VARARGS, GetEnd_doc},
+ {"getBlendin", (PyCFunction) BL_ActionActuator::sPyGetBlendin, METH_VARARGS, GetBlendin_doc},
+ {"getPriority", (PyCFunction) BL_ActionActuator::sPyGetPriority, METH_VARARGS, GetPriority_doc},
+ {"getFrame", (PyCFunction) BL_ActionActuator::sPyGetFrame, METH_VARARGS, GetFrame_doc},
+ {"getProperty", (PyCFunction) BL_ActionActuator::sPyGetProperty, METH_VARARGS, GetProperty_doc},
+ {"setChannel", (PyCFunction) BL_ActionActuator::sPySetChannel, METH_VARARGS, SetChannel_doc},
+// {"getChannel", (PyCFunction) BL_ActionActuator::sPyGetChannel, METH_VARARGS},
+
+ {NULL,NULL} //Sentinel
+};
+
+PyObject* BL_ActionActuator::_getattr(char* attr) {
+ _getattr_up(SCA_IActuator);
+}
+
+/* setStart */
+char BL_ActionActuator::GetAction_doc[] =
+"getAction()\n"
+"\tReturns a string containing the name of the current action.\n";
+
+PyObject* BL_ActionActuator::PyGetAction(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ PyObject *result;
+
+ if (m_action){
+ result = Py_BuildValue("s", m_action->id.name+2);
+ }
+ else{
+ Py_INCREF(Py_None);
+ result = Py_None;
+ }
+
+ return result;
+}
+
+/* getProperty */
+char BL_ActionActuator::GetProperty_doc[] =
+"getProperty()\n"
+"\tReturns the name of the property to be used in FromProp mode.\n";
+
+PyObject* BL_ActionActuator::PyGetProperty(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ PyObject *result;
+
+ result = Py_BuildValue("s", m_propname);
+
+ return result;
+}
+
+/* getFrame */
+char BL_ActionActuator::GetFrame_doc[] =
+"getFrame()\n"
+"\tReturns the current frame number.\n";
+
+PyObject* BL_ActionActuator::PyGetFrame(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ PyObject *result;
+
+ result = Py_BuildValue("f", m_localtime);
+
+ return result;
+}
+
+/* getEnd */
+char BL_ActionActuator::GetEnd_doc[] =
+"getEnd()\n"
+"\tReturns the last frame of the action.\n";
+
+PyObject* BL_ActionActuator::PyGetEnd(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ PyObject *result;
+
+ result = Py_BuildValue("f", m_endtime);
+
+ return result;
+}
+
+/* getStart */
+char BL_ActionActuator::GetStart_doc[] =
+"getStart()\n"
+"\tReturns the starting frame of the action.\n";
+
+PyObject* BL_ActionActuator::PyGetStart(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ PyObject *result;
+
+ result = Py_BuildValue("f", m_starttime);
+
+ return result;
+}
+
+/* getBlendin */
+char BL_ActionActuator::GetBlendin_doc[] =
+"getBlendin()\n"
+"\tReturns the number of interpolation animation frames to be\n"
+"\tgenerated when this actuator is triggered.\n";
+
+PyObject* BL_ActionActuator::PyGetBlendin(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ PyObject *result;
+
+ result = Py_BuildValue("f", m_blendin);
+
+ return result;
+}
+
+/* getPriority */
+char BL_ActionActuator::GetPriority_doc[] =
+"getPriority()\n"
+"\tReturns the priority for this actuator. Actuators with lower\n"
+"\tPriority numbers will override actuators with higher numbers.\n";
+
+PyObject* BL_ActionActuator::PyGetPriority(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ PyObject *result;
+
+ result = Py_BuildValue("i", m_priority);
+
+ return result;
+}
+
+/* setAction */
+char BL_ActionActuator::SetAction_doc[] =
+"setAction(action, (reset))\n"
+"\t - action : The name of the action to set as the current action.\n"
+"\t - reset : Optional parameter indicating whether to reset the\n"
+"\t blend timer or not. A value of 1 indicates that the\n"
+"\t timer should be reset. A value of 0 will leave it\n"
+"\t unchanged. If reset is not specified, the timer will"
+"\t be reset.\n";
+
+PyObject* BL_ActionActuator::PySetAction(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ char *string;
+ int reset = 1;
+
+ if (PyArg_ParseTuple(args,"s|i",&string, &reset))
+ {
+ bAction *action;
+
+ action = (bAction*)SCA_ILogicBrick::m_sCurrentLogicManager->GetActionByName(STR_String(string));
+
+ if (!action){
+ /* NOTE! Throw an exception or something */
+ // printf ("setAction failed: Action not found\n", string);
+ }
+ else{
+ m_action=action;
+ if (reset)
+ m_blendframe = 0;
+ }
+ }
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+/* setStart */
+char BL_ActionActuator::SetStart_doc[] =
+"setStart(start)\n"
+"\t - start : Specifies the starting frame of the animation.\n";
+
+PyObject* BL_ActionActuator::PySetStart(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ float start;
+
+ if (PyArg_ParseTuple(args,"f",&start))
+ {
+ m_starttime = start;
+ }
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+/* setEnd */
+char BL_ActionActuator::SetEnd_doc[] =
+"setEnd(end)\n"
+"\t - end : Specifies the ending frame of the animation.\n";
+
+PyObject* BL_ActionActuator::PySetEnd(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ float end;
+
+ if (PyArg_ParseTuple(args,"f",&end))
+ {
+ m_endtime = end;
+ }
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+/* setBlendin */
+char BL_ActionActuator::SetBlendin_doc[] =
+"setBlendin(blendin)\n"
+"\t - blendin : Specifies the number of frames of animation to generate\n"
+"\t when making transitions between actions.\n";
+
+PyObject* BL_ActionActuator::PySetBlendin(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ float blendin;
+
+ if (PyArg_ParseTuple(args,"f",&blendin))
+ {
+ m_blendin = blendin;
+ }
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+/* setBlendtime */
+char BL_ActionActuator::SetBlendtime_doc[] =
+"setBlendtime(blendtime)\n"
+"\t - blendtime : Allows the script to directly modify the internal timer\n"
+"\t used when generating transitions between actions. This\n"
+"\t parameter must be in the range from 0.0 to 1.0.\n";
+
+PyObject* BL_ActionActuator::PySetBlendtime(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ float blendframe;
+
+ if (PyArg_ParseTuple(args,"f",&blendframe))
+ {
+ m_blendframe = blendframe * m_blendin;
+ if (m_blendframe<0)
+ m_blendframe = 0;
+ if (m_blendframe>m_blendin)
+ m_blendframe = m_blendin;
+ }
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+/* setPriority */
+char BL_ActionActuator::SetPriority_doc[] =
+"setPriority(priority)\n"
+"\t - priority : Specifies the new priority. Actuators will lower\n"
+"\t priority numbers will override actuators with higher\n"
+"\t numbers.\n";
+
+PyObject* BL_ActionActuator::PySetPriority(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ int priority;
+
+ if (PyArg_ParseTuple(args,"i",&priority))
+ {
+ m_priority = priority;
+ }
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+/* setFrame */
+char BL_ActionActuator::SetFrame_doc[] =
+"setFrame(frame)\n"
+"\t - frame : Specifies the new current frame for the animation\n";
+
+PyObject* BL_ActionActuator::PySetFrame(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ float frame;
+
+ if (PyArg_ParseTuple(args,"f",&frame))
+ {
+ m_localtime = frame;
+ if (m_localtime<m_starttime)
+ m_localtime=m_starttime;
+ else if (m_localtime>m_endtime)
+ m_localtime=m_endtime;
+ }
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+/* setProperty */
+char BL_ActionActuator::SetProperty_doc[] =
+"setProperty(prop)\n"
+"\t - prop : A string specifying the property name to be used in\n"
+"\t FromProp playback mode.\n";
+
+PyObject* BL_ActionActuator::PySetProperty(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ char *string;
+
+ if (PyArg_ParseTuple(args,"s",&string))
+ {
+ m_propname = string;
+ }
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+/*
+PyObject* BL_ActionActuator::PyGetChannel(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ char *string;
+
+ if (PyArg_ParseTuple(args,"s",&string))
+ {
+ m_propname = string;
+ }
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+*/
+
+/* setChannel */
+char BL_ActionActuator::SetChannel_doc[] =
+"setChannel(channel, matrix)\n"
+"\t - channel : A string specifying the name of the bone channel.\n"
+"\t - matrix : A 4x4 matrix specifying the overriding transformation\n"
+"\t as an offset from the bone's rest position.\n";
+
+PyObject* BL_ActionActuator::PySetChannel(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ float matrix[4][4];
+ char *string;
+ PyObject* pylist;
+ bool error = false;
+ int row,col;
+ int mode = 0; /* 0 for bone space, 1 for armature/world space */
+
+ PyArg_ParseTuple(args,"sO|i", &string, &pylist, &mode);
+
+ if (pylist->ob_type == &CListValue::Type)
+ {
+ CListValue* listval = (CListValue*) pylist;
+ if (listval->GetCount() == 4)
+ {
+ for (row=0;row<4;row++) // each row has a 4-vector [x,y,z, w]
+ {
+ CListValue* vecval = (CListValue*)listval->GetValue(row);
+ for (col=0;col<4;col++)
+ {
+ matrix[row][col] = vecval->GetValue(col)->GetNumber();
+
+ }
+ }
+ }
+ else
+ {
+ error = true;
+ }
+ }
+ else
+ {
+ // assert the list is long enough...
+ int numitems = PyList_Size(pylist);
+ if (numitems == 4)
+ {
+ for (row=0;row<4;row++) // each row has a 4-vector [x,y,z, w]
+ {
+
+ PyObject* veclist = PyList_GetItem(pylist,row); // here we have a vector4 list
+ for (col=0;col<4;col++)
+ {
+ matrix[row][col] = PyFloat_AsDouble(PyList_GetItem(veclist,col));
+
+ }
+ }
+ }
+ else
+ {
+ error = true;
+ }
+ }
+
+ if (!error)
+ {
+
+/* DO IT HERE */
+ bPoseChannel *pchan;
+
+ pchan = (bPoseChannel*) MEM_callocN(sizeof(bPoseChannel), "userChannel");
+ strcpy(pchan->name, string);
+ Mat4ToQuat(matrix, pchan->quat);
+ Mat4ToSize(matrix, pchan->size);
+ VECCOPY (pchan->loc, matrix[3]);
+
+ pchan->flag |= POSE_ROT|POSE_LOC|POSE_SIZE;
+
+ if (!m_userpose){
+ m_userpose = (bPose*)MEM_callocN(sizeof(bPose), "userPose");
+ }
+
+ verify_pose_channel(m_userpose, string);
+ set_pose_channel(m_userpose, pchan);
+ }
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
diff --git a/source/gameengine/Converter/BL_ActionActuator.h b/source/gameengine/Converter/BL_ActionActuator.h
new file mode 100644
index 00000000000..49485cb324d
--- /dev/null
+++ b/source/gameengine/Converter/BL_ActionActuator.h
@@ -0,0 +1,126 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BL_ACTIONACTUATOR
+#define BL_ACTIONACTUATOR
+
+#include "SCA_IActuator.h"
+#include "MT_Point3.h"
+
+class BL_ActionActuator : public SCA_IActuator
+{
+public:
+ Py_Header;
+ BL_ActionActuator(SCA_IObject* gameobj,
+ const STR_String& propname,
+ float starttime,
+ float endtime,
+ struct bAction *action,
+ short playtype,
+ short blendin,
+ short priority,
+ float stride,
+ PyTypeObject* T=&Type)
+ : SCA_IActuator(gameobj,T),
+ m_starttime (starttime),
+ m_endtime(endtime) ,
+ m_localtime(starttime),
+ m_lastUpdate(-1),
+ m_propname(propname),
+ m_action(action),
+ m_playtype(playtype),
+ m_flag(0),
+ m_blendin(blendin),
+ m_blendframe(0),
+ m_pose(NULL),
+ m_userpose(NULL),
+ m_blendpose(NULL),
+ m_priority(priority),
+ m_stridelength(stride),
+ m_lastpos(0, 0, 0)
+ {
+ };
+ virtual ~BL_ActionActuator();
+ virtual bool Update(double curtime,double deltatime);
+ CValue* GetReplica();
+ void ProcessReplica();
+
+ KX_PYMETHOD_DOC(BL_ActionActuator,SetAction);
+ KX_PYMETHOD_DOC(BL_ActionActuator,SetBlendin);
+ KX_PYMETHOD_DOC(BL_ActionActuator,SetPriority);
+ KX_PYMETHOD_DOC(BL_ActionActuator,SetStart);
+ KX_PYMETHOD_DOC(BL_ActionActuator,SetEnd);
+ KX_PYMETHOD_DOC(BL_ActionActuator,SetFrame);
+ KX_PYMETHOD_DOC(BL_ActionActuator,SetProperty);
+ KX_PYMETHOD_DOC(BL_ActionActuator,SetBlendtime);
+ KX_PYMETHOD_DOC(BL_ActionActuator,SetChannel);
+
+ KX_PYMETHOD_DOC(BL_ActionActuator,GetAction);
+ KX_PYMETHOD_DOC(BL_ActionActuator,GetBlendin);
+ KX_PYMETHOD_DOC(BL_ActionActuator,GetPriority);
+ KX_PYMETHOD_DOC(BL_ActionActuator,GetStart);
+ KX_PYMETHOD_DOC(BL_ActionActuator,GetEnd);
+ KX_PYMETHOD_DOC(BL_ActionActuator,GetFrame);
+ KX_PYMETHOD_DOC(BL_ActionActuator,GetProperty);
+// KX_PYMETHOD(BL_ActionActuator,GetChannel);
+
+
+ virtual PyObject* _getattr(char* attr);
+ void SetBlendTime (float newtime);
+
+protected:
+ float m_blendframe;
+ MT_Point3 m_lastpos;
+ int m_flag;
+ float m_starttime;
+ float m_endtime;
+ float m_localtime;
+ float m_lastUpdate;
+ short m_playtype;
+ float m_blendin;
+ short m_priority;
+ float m_stridelength;
+ struct bPose* m_pose;
+ struct bPose* m_blendpose;
+ struct bPose* m_userpose;
+ STR_String m_propname;
+ struct bAction *m_action;
+
+};
+
+enum {
+ ACT_FLAG_REVERSE = 0x00000001,
+ ACT_FLAG_LOCKINPUT = 0x00000002,
+ ACT_FLAG_KEYUP = 0x00000004
+};
+#endif
+
diff --git a/source/gameengine/Converter/BL_ArmatureObject.cpp b/source/gameengine/Converter/BL_ArmatureObject.cpp
new file mode 100644
index 00000000000..1668cd522a3
--- /dev/null
+++ b/source/gameengine/Converter/BL_ArmatureObject.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 "BL_ArmatureObject.h"
+#include "BL_ActionActuator.h"
+#include "BLI_blenlib.h"
+#include "BKE_action.h"
+#include "BKE_armature.h"
+#include "GEN_Map.h"
+#include "GEN_HashedPtr.h"
+#include "MEM_guardedalloc.h"
+#include "DNA_action_types.h"
+
+CValue* BL_ArmatureObject::GetReplica()
+{
+ BL_ArmatureObject* replica = new BL_ArmatureObject(*this);
+
+ // this will copy properties and so on...
+ CValue::AddDataToReplica(replica);
+
+ ProcessReplica(replica);
+ return replica;
+}
+
+void BL_ArmatureObject::ProcessReplica(BL_ArmatureObject *replica)
+{
+ KX_GameObject::ProcessReplica(replica);
+
+}
+
+BL_ArmatureObject::~BL_ArmatureObject()
+{
+ if (m_mrdPose){
+ clear_pose(m_mrdPose);
+ MEM_freeN(m_mrdPose);
+ }
+}
+
+void BL_ArmatureObject::ApplyPose()
+{
+ if (m_pose){
+ apply_pose_armature(m_armature, m_pose, 1);
+ if (!m_mrdPose)
+ copy_pose (&m_mrdPose, m_pose, 0);
+ else
+ get_pose_from_pose(&m_mrdPose, m_pose);
+ }
+}
+
+void BL_ArmatureObject::SetPose(bPose *pose)
+{
+ m_pose = pose;
+}
+
+bool BL_ArmatureObject::SetActiveAction(BL_ActionActuator *act, short priority, double curtime)
+{
+ if (curtime != m_lastframe){
+ m_activePriority = 9999;
+ m_lastframe= curtime;
+ m_activeAct = NULL;
+ }
+
+ if (priority<=m_activePriority)
+ {
+ if (m_activeAct && (m_activeAct!=act))
+ m_activeAct->SetBlendTime(0.0); /* Reset the blend timer */
+ m_activeAct = act;
+ m_activePriority = priority;
+ m_lastframe = curtime;
+
+ return true;
+ }
+ else{
+ act->SetBlendTime(0.0);
+ return false;
+ }
+
+}
+
+BL_ActionActuator * BL_ArmatureObject::GetActiveAction()
+{
+ return m_activeAct;
+}
+
+void BL_ArmatureObject::GetPose(bPose **pose)
+{
+ /* If the caller supplies a null pose, create a new one. */
+ /* Otherwise, copy the armature's pose channels into the caller-supplied pose */
+ if (!*pose)
+ copy_pose(pose, m_pose, 0);
+ else
+ get_pose_from_pose(pose, m_pose);
+
+}
+
+void BL_ArmatureObject::GetMRDPose(bPose **pose)
+{
+ /* If the caller supplies a null pose, create a new one. */
+ /* Otherwise, copy the armature's pose channels into the caller-supplied pose */
+
+ if (!m_mrdPose){
+ copy_pose (&m_mrdPose, m_pose, 0);
+ }
+
+ if (!*pose)
+ copy_pose(pose, m_mrdPose, 0);
+ else
+ get_pose_from_pose(pose, m_mrdPose);
+
+}
+
+short BL_ArmatureObject::GetActivePriority()
+{
+ return m_activePriority;
+}
+
+double BL_ArmatureObject::GetLastFrame()
+{
+ return m_lastframe;
+}
diff --git a/source/gameengine/Converter/BL_ArmatureObject.h b/source/gameengine/Converter/BL_ArmatureObject.h
new file mode 100644
index 00000000000..a438eced5d2
--- /dev/null
+++ b/source/gameengine/Converter/BL_ArmatureObject.h
@@ -0,0 +1,79 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 BL_ARMATUREOBJECT
+#define BL_ARMATUREOBJECT
+
+#include "KX_GameObject.h"
+
+#include "SG_IObject.h"
+
+class BL_ActionActuator;
+
+class BL_ArmatureObject : public KX_GameObject
+{
+public:
+ double GetLastFrame ();
+ short GetActivePriority();
+ virtual void ProcessReplica(BL_ArmatureObject *replica);
+ class BL_ActionActuator * GetActiveAction();
+ BL_ArmatureObject(void* sgReplicationInfo, SG_Callbacks callbacks,
+ struct bArmature *arm,
+ struct bPose *pose) :
+ KX_GameObject(sgReplicationInfo,callbacks),
+ m_pose(pose),
+ m_mrdPose(NULL),
+ m_armature(arm),
+ m_activeAct(NULL),
+ m_activePriority(999)
+ {}
+
+ virtual CValue* GetReplica();
+ virtual ~BL_ArmatureObject();
+ void GetMRDPose(bPose **pose);
+ void GetPose(struct bPose **pose);
+ void SetPose (struct bPose *pose);
+ void ApplyPose();
+ bool SetActiveAction(class BL_ActionActuator *act, short priority, double curtime);
+ struct bArmature * GetArmature(){return m_armature;};
+
+protected:
+ struct bArmature *m_armature;
+ struct bPose *m_pose;
+ struct bPose *m_mrdPose;
+ double m_lastframe;
+ class BL_ActionActuator *m_activeAct;
+ short m_activePriority;
+};
+
+#endif
+
diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
new file mode 100644
index 00000000000..68d45044fff
--- /dev/null
+++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
@@ -0,0 +1,1227 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * Convert blender data to ketsji
+ */
+
+#ifdef WIN32
+#pragma warning (disable : 4786)
+#endif
+
+#include "BL_BlenderDataConversion.h"
+#include "KX_BlenderGL.h"
+#include "KX_BlenderScalarInterpolator.h"
+
+#include "RAS_IPolygonMaterial.h"
+
+// Expressions
+#include "ListValue.h"
+#include "IntValue.h"
+// Collision & Fuzzics LTD
+
+#include "PHY_Pro.h"
+
+
+#include "KX_Scene.h"
+#include "KX_GameObject.h"
+#include "RAS_FramingManager.h"
+#include "RAS_MeshObject.h"
+
+#include "KX_ConvertActuators.h"
+#include "KX_ConvertControllers.h"
+#include "KX_ConvertSensors.h"
+
+#include "KX_GameObject.h"
+#include "SCA_LogicManager.h"
+#include "SCA_EventManager.h"
+#include "SCA_TimeEventManager.h"
+#include "KX_Light.h"
+#include "KX_Camera.h"
+#include "KX_EmptyObject.h"
+#include "MT_Point3.h"
+#include "MT_Transform.h"
+#include "SCA_IInputDevice.h"
+#include "RAS_TexMatrix.h"
+#include "RAS_ICanvas.h"
+#include "RAS_MaterialBucket.h"
+//#include "KX_BlenderPolyMaterial.h"
+#include "RAS_Polygon.h"
+#include "RAS_TexVert.h"
+#include "RAS_BucketManager.h"
+#include "RAS_IRenderTools.h"
+
+#include "DNA_action_types.h"
+#include "BKE_main.h"
+#include "BL_SkinMeshObject.h"
+#include "BL_SkinDeformer.h"
+#include "BL_MeshDeformer.h"
+//#include "BL_ArmatureController.h"
+
+#include "BlenderWorldInfo.h"
+
+#include "KX_KetsjiEngine.h"
+#include "KX_BlenderSceneConverter.h"
+
+#include"SND_Scene.h"
+#include "SND_SoundListener.h"
+
+/* This little block needed for linking to Blender... */
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+/* This list includes only data type definitions */
+#include "DNA_object_types.h"
+#include "DNA_material_types.h"
+#include "DNA_image_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_group_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_property_types.h"
+#include "DNA_text_types.h"
+#include "DNA_sensor_types.h"
+#include "DNA_controller_types.h"
+#include "DNA_actuator_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_world_types.h"
+#include "DNA_sound_types.h"
+#include "DNA_key_types.h"
+
+
+#include "MEM_guardedalloc.h"
+#include "BKE_utildefines.h"
+#include "BKE_key.h"
+#include "BKE_mesh.h"
+#include "MT_Point3.h"
+
+
+#include "BKE_material.h" /* give_current_material */
+/* end of blender include block */
+
+#include "KX_BlenderInputDevice.h"
+#include "KX_ConvertProperties.h"
+#include "KX_HashedPtr.h"
+
+
+#include "KX_ScalarInterpolator.h"
+
+#include "KX_IpoConvert.h"
+#include "SYS_System.h"
+
+#include "SG_Node.h"
+
+#include "KX_ConvertPhysicsObject.h"
+
+
+// This file defines relationships between parents and children
+// in the game engine.
+
+#include "KX_SG_NodeRelationships.h"
+
+#include "BL_ArmatureObject.h"
+#include "BL_DeformableGameObject.h"
+
+static unsigned int KX_rgbaint2uint_new(unsigned int icol)
+{
+ unsigned int temp=0;
+ unsigned char *cp= (unsigned char *)&temp;
+ unsigned char *src= (unsigned char *)&icol;
+ cp[3]= src[0];//alpha
+ cp[2]= src[1];//blue
+ cp[1]= src[2];//green
+ cp[0]= src[3];//red
+ return temp;
+}
+
+/* Now the real converting starts... */
+static unsigned int KX_Mcol2uint_new(MCol col)
+{
+ /* color has to be converted without endian sensitivity. So no shifting! */
+ unsigned int temp=0;
+ unsigned char *cp= (unsigned char *)&temp;
+ cp[3]=255;
+ cp[2]= col.r;
+ cp[1]= col.g;
+ cp[0]= col.b;
+ return temp;
+}
+
+RAS_MeshObject* BL_ConvertMesh(Mesh* mesh,Object* blenderobj,RAS_IRenderTools* rendertools,KX_Scene* scene,KX_BlenderSceneConverter *converter)
+{
+ RAS_MeshObject *meshobj;
+ bool skinMesh = false;
+
+ int lightlayer = blenderobj->lay;
+
+ // Determine if we need to make a skinned mesh
+ if (mesh->dvert){
+ meshobj = new BL_SkinMeshObject(lightlayer);
+ skinMesh = true;
+ }
+ else {
+ meshobj = new RAS_MeshObject(lightlayer);
+ }
+
+ meshobj->SetName(mesh->id.name);
+
+
+ MFace* mface = static_cast<MFace*>(mesh->mface);
+ TFace* tface = static_cast<TFace*>(mesh->tface);
+
+
+ MCol* mmcol = mesh->mcol;
+
+
+ meshobj->m_xyz_index_to_vertex_index_mapping.resize(mesh->totvert);
+
+ for (int f=0;f<mesh->totface;f++,mface++,tface++)
+ {
+
+ bool collider = true;
+
+ // only add valid polygons
+ if (mface->v3)
+ {
+
+ MT_Vector3 no0(0.0,0.0,0.0),no1(0.0,0.0,0.0),no2(0.0,0.0,0.0),no3(0.0,0.0,0.0);
+ MT_Point3 pt0,pt1,pt2,pt3;
+
+ MT_Point2 uv0(0.0,0.0),uv1(0.0,0.0),uv2(0.0,0.0),uv3(0.0,0.0);
+ // rgb3 is set from the adjoint face in a square
+ unsigned int rgb0,rgb1,rgb2,rgb3 = 0;
+ pt0 = MT_Point3( mesh->mvert[mface->v1].co[0],
+ mesh->mvert[mface->v1].co[1],
+ mesh->mvert[mface->v1].co[2]);
+ no0 = MT_Vector3(
+ mesh->mvert[mface->v1].no[0]/32767.0,
+ mesh->mvert[mface->v1].no[1]/32767.0,
+ mesh->mvert[mface->v1].no[2]/32767.0
+ );
+
+ pt1 = MT_Point3( mesh->mvert[mface->v2].co[0],
+ mesh->mvert[mface->v2].co[1],
+ mesh->mvert[mface->v2].co[2]);
+
+ no1 = MT_Vector3(
+ mesh->mvert[mface->v2].no[0]/32767.0,
+ mesh->mvert[mface->v2].no[1]/32767.0,
+ mesh->mvert[mface->v2].no[2]/32767.0
+ );
+
+ pt2 = MT_Point3( mesh->mvert[mface->v3].co[0],
+ mesh->mvert[mface->v3].co[1],
+ mesh->mvert[mface->v3].co[2]);
+
+ no2 = MT_Vector3(
+ mesh->mvert[mface->v3].no[0]/32767.0,
+ mesh->mvert[mface->v3].no[1]/32767.0,
+ mesh->mvert[mface->v3].no[2]/32767.0
+ );
+
+ if (mface->v4)
+ {
+ pt3 = MT_Point3( mesh->mvert[mface->v4].co[0],
+ mesh->mvert[mface->v4].co[1],
+ mesh->mvert[mface->v4].co[2]);
+ no3 = MT_Vector3(
+ mesh->mvert[mface->v4].no[0]/32767.0,
+ mesh->mvert[mface->v4].no[1]/32767.0,
+ mesh->mvert[mface->v4].no[2]/32767.0
+ );
+ }
+
+
+
+ if((!mface->flag & ME_SMOOTH))
+ {
+ MT_Vector3 norm = ((pt1-pt0).cross(pt2-pt0)).safe_normalized();
+ norm[0] = ((int) (10*norm[0]))/10.0;
+ norm[1] = ((int) (10*norm[1]))/10.0;
+ norm[2] = ((int) (10*norm[2]))/10.0;
+ no0=no1=no2=no3= norm;
+
+ }
+
+ {
+ Image* bima = ((mesh->tface && tface) ? (Image*) tface->tpage : NULL);
+
+ STR_String imastr =
+ ((mesh->tface && tface) ?
+ (bima? (bima)->id.name : "" ) : "" );
+
+ char transp=0;
+ short mode=0, tile=0;
+ int tilexrep=4,tileyrep = 4;
+
+ if (bima)
+ {
+ tilexrep = bima->xrep;
+ tileyrep = bima->yrep;
+
+ }
+
+
+ bool polyvisible = true;
+ if (mesh->tface && tface)
+ {
+ // Use texface colors if available
+ //TF_DYNAMIC means the polygon is a collision face
+ collider = (tface->mode & TF_DYNAMIC != 0);
+ transp = tface->transp;
+ tile = tface->tile;
+ mode = tface->mode;
+
+ polyvisible = !((tface->flag & TF_HIDE)||(tface->mode & TF_INVISIBLE));
+
+ uv0 = MT_Point2(tface->uv[0]);
+ uv1 = MT_Point2(tface->uv[1]);
+ uv2 = MT_Point2(tface->uv[2]);
+ rgb0 = KX_rgbaint2uint_new(tface->col[0]);
+ rgb1 = KX_rgbaint2uint_new(tface->col[1]);
+ rgb2 = KX_rgbaint2uint_new(tface->col[2]);
+
+ if (mface->v4)
+ {
+ uv3 = MT_Point2(tface->uv[3]);
+ rgb3 = KX_rgbaint2uint_new(tface->col[3]);
+ } else {
+ }
+
+
+ } else
+ {
+ //
+ if (mmcol)
+ {
+ // Use vertex colours
+ rgb0 = KX_Mcol2uint_new(mmcol[0]);
+ rgb1 = KX_Mcol2uint_new(mmcol[1]);
+ rgb2 = KX_Mcol2uint_new(mmcol[2]);
+
+
+ if (mface->v4)
+ {
+ rgb3 = KX_Mcol2uint_new(mmcol[3]);
+
+ }
+
+ mmcol += 4;
+ }
+ else{
+ // If there are no vertex colors OR texfaces,
+ // Initialize face to white and set COLLSION true and everything else FALSE
+ rgb0 = KX_rgbaint2uint_new(0xFFFFFFFF);
+ rgb1 = KX_rgbaint2uint_new(0xFFFFFFFF);
+ rgb2 = KX_rgbaint2uint_new(0xFFFFFFFF);
+
+ if (mface->v4)
+ rgb3 = KX_rgbaint2uint_new(0xFFFFFFFF);
+
+ mode = TF_DYNAMIC;
+ transp = TF_SOLID;
+ tile = 0;
+ }
+ }
+
+
+ Material* ma = give_current_material(blenderobj, 1);
+ const char* matnameptr = (ma ? ma->id.name : "");
+
+
+ bool istriangle = (mface->v4==0);
+
+ RAS_IPolyMaterial* polymat = rendertools->CreateBlenderPolyMaterial(imastr,false,matnameptr,tile,tilexrep,tileyrep,mode,transp, lightlayer,istriangle,blenderobj,tface);
+
+ if (ma)
+ {
+ polymat->m_specular = MT_Vector3(ma->spec * ma->specr,ma->spec * ma->specg,ma->spec * ma->specb);
+ polymat->m_shininess = (float)ma->har;
+
+ } else
+ {
+ polymat->m_specular = MT_Vector3(0.0f,0.0f,0.0f);
+ polymat->m_shininess = 35.0;
+ }
+
+
+ // this is needed to free up memory afterwards
+ converter->RegisterPolyMaterial(polymat);
+
+ RAS_MaterialBucket* bucket = scene->FindBucket(polymat);
+
+ int nverts = mface->v4?4:3;
+ int vtxarray = meshobj->FindVertexArray(nverts,polymat);
+ RAS_Polygon* poly = new RAS_Polygon(bucket,polyvisible,nverts,vtxarray);
+ if (skinMesh) {
+ int d1, d2, d3, d4;
+ bool flat;
+
+ /* If the face is set to solid, all fnors are the same */
+ if (mface->flag & ME_SMOOTH)
+ flat = false;
+ else
+ flat = true;
+
+ d1=((BL_SkinMeshObject*)meshobj)->FindOrAddDeform(vtxarray, mface->v1, &mesh->dvert[mface->v1], polymat);
+ d2=((BL_SkinMeshObject*)meshobj)->FindOrAddDeform(vtxarray, mface->v2, &mesh->dvert[mface->v2], polymat);
+ d3=((BL_SkinMeshObject*)meshobj)->FindOrAddDeform(vtxarray, mface->v3, &mesh->dvert[mface->v3], polymat);
+ if (nverts==4)
+ d4=((BL_SkinMeshObject*)meshobj)->FindOrAddDeform(vtxarray, mface->v4, &mesh->dvert[mface->v4], polymat);
+ poly->SetVertex(0,((BL_SkinMeshObject*)meshobj)->FindOrAddVertex(vtxarray,pt0,uv0,rgb0,no0,d1,flat, polymat));
+ poly->SetVertex(1,((BL_SkinMeshObject*)meshobj)->FindOrAddVertex(vtxarray,pt1,uv1,rgb1,no1,d2,flat, polymat));
+ poly->SetVertex(2,((BL_SkinMeshObject*)meshobj)->FindOrAddVertex(vtxarray,pt2,uv2,rgb2,no2,d3,flat, polymat));
+ if (nverts==4)
+ poly->SetVertex(3,((BL_SkinMeshObject*)meshobj)->FindOrAddVertex(vtxarray,pt3,uv3,rgb3,no3,d4, flat,polymat));
+ }
+ else
+ {
+ poly->SetVertex(0,meshobj->FindOrAddVertex(vtxarray,pt0,uv0,rgb0,no0,polymat,mface->v1));
+ poly->SetVertex(1,meshobj->FindOrAddVertex(vtxarray,pt1,uv1,rgb1,no1,polymat,mface->v2));
+ poly->SetVertex(2,meshobj->FindOrAddVertex(vtxarray,pt2,uv2,rgb2,no2,polymat,mface->v3));
+ if (nverts==4)
+ poly->SetVertex(3,meshobj->FindOrAddVertex(vtxarray,pt3,uv3,rgb3,no3,polymat,mface->v4));
+ }
+ meshobj->AddPolygon(poly);
+ if (poly->IsCollider())
+ {
+ RAS_TriangleIndex idx;
+ idx.m_index[0] = mface->v1;
+ idx.m_index[1] = mface->v2;
+ idx.m_index[2] = mface->v3;
+ idx.m_collider = collider;
+ meshobj->m_triangle_indices.push_back(idx);
+ if (nverts==4)
+ {
+ idx.m_index[0] = mface->v1;
+ idx.m_index[1] = mface->v3;
+ idx.m_index[2] = mface->v4;
+ idx.m_collider = collider;
+ meshobj->m_triangle_indices.push_back(idx);
+ }
+ }
+
+ poly->SetVisibleWireframeEdges(mface->edcode);
+ poly->SetCollider(collider);
+ }
+ }
+ }
+ meshobj->UpdateMaterialList();
+
+ return meshobj;
+}
+
+static PHY_MaterialProps g_materialProps = {
+ 1.0, // restitution
+ 2.0, // friction
+ 0.0, // fh spring constant
+ 0.0, // fh damping
+ 0.0, // fh distance
+ false // sliding material?
+};
+
+
+
+static PHY_MaterialProps *CreateMaterialFromBlenderObject(struct Object* blenderobject,
+ KX_Scene *kxscene)
+{
+ PHY_MaterialProps *materialProps = new PHY_MaterialProps;
+
+ assert(materialProps);
+
+ Material* blendermat = give_current_material(blenderobject, 0);
+
+ if (blendermat)
+ {
+ assert(0.0f <= blendermat->reflect && blendermat->reflect <= 1.0f);
+
+ materialProps->m_restitution = blendermat->reflect;
+ materialProps->m_friction = blendermat->friction;
+ materialProps->m_fh_spring = blendermat->fh;
+ materialProps->m_fh_damping = blendermat->xyfrict;
+ materialProps->m_fh_distance = blendermat->fhdist;
+ materialProps->m_fh_normal = (blendermat->dynamode & MA_FH_NOR) != 0;
+ }
+ else {
+ *materialProps = g_materialProps;
+ }
+
+ return materialProps;
+}
+
+static PHY_ShapeProps *CreateShapePropsFromBlenderObject(struct Object* blenderobject,
+ KX_Scene *kxscene)
+{
+ PHY_ShapeProps *shapeProps = new PHY_ShapeProps;
+
+ assert(shapeProps);
+
+ shapeProps->m_mass = blenderobject->mass;
+
+// This needs to be fixed in blender. For now, we use:
+
+// in Blender, inertia stands for the size value which is equivalent to
+// the sphere radius
+ shapeProps->m_inertia = blenderobject->formfactor * blenderobject->mass * blenderobject->inertia * blenderobject->inertia;
+
+ assert(0.0f <= blenderobject->damping && blenderobject->damping <= 1.0f);
+ assert(0.0f <= blenderobject->rdamping && blenderobject->rdamping <= 1.0f);
+
+ shapeProps->m_lin_drag = 1.0 - blenderobject->damping;
+ shapeProps->m_ang_drag = 1.0 - blenderobject->rdamping;
+
+ shapeProps->m_friction_scaling[0] = blenderobject->anisotropicFriction[0];
+ shapeProps->m_friction_scaling[1] = blenderobject->anisotropicFriction[1];
+ shapeProps->m_friction_scaling[2] = blenderobject->anisotropicFriction[2];
+ shapeProps->m_do_anisotropic = ((blenderobject->gameflag & OB_ANISOTROPIC_FRICTION) != 0);
+
+ shapeProps->m_do_fh = (blenderobject->gameflag & OB_DO_FH) != 0;
+ shapeProps->m_do_rot_fh = (blenderobject->gameflag & OB_ROT_FH) != 0;
+
+ return shapeProps;
+}
+
+
+
+
+
+//////////////////////////////////////////////////////////
+
+
+
+
+void my_boundbox_mesh(Mesh *me, float *loc, float *size)
+ {
+ MVert *mvert;
+ BoundBox *bb;
+ float min[3], max[3];
+ float mloc[3], msize[3];
+ int a;
+
+ if(me->bb==0) me->bb= (struct BoundBox *)MEM_callocN(sizeof(BoundBox), "boundbox");
+ bb= me->bb;
+
+ INIT_MINMAX(min, max);
+
+ if (!loc) loc= mloc;
+ if (!size) size= msize;
+
+ mvert= me->mvert;
+ for(a=0; a<me->totvert; a++, mvert++) {
+ DO_MINMAX(mvert->co, min, max);
+ }
+
+ if(me->totvert) {
+ loc[0]= (min[0]+max[0])/2.0;
+ loc[1]= (min[1]+max[1])/2.0;
+ loc[2]= (min[2]+max[2])/2.0;
+
+ size[0]= (max[0]-min[0])/2.0;
+ size[1]= (max[1]-min[1])/2.0;
+ size[2]= (max[2]-min[2])/2.0;
+ }
+ else {
+ loc[0]= loc[1]= loc[2]= 0.0;
+ size[0]= size[1]= size[2]= 0.0;
+ }
+
+ bb->vec[0][0]=bb->vec[1][0]=bb->vec[2][0]=bb->vec[3][0]= loc[0]-size[0];
+ bb->vec[4][0]=bb->vec[5][0]=bb->vec[6][0]=bb->vec[7][0]= loc[0]+size[0];
+
+ bb->vec[0][1]=bb->vec[1][1]=bb->vec[4][1]=bb->vec[5][1]= loc[1]-size[1];
+ bb->vec[2][1]=bb->vec[3][1]=bb->vec[6][1]=bb->vec[7][1]= loc[1]+size[1];
+
+ bb->vec[0][2]=bb->vec[3][2]=bb->vec[4][2]=bb->vec[7][2]= loc[2]-size[2];
+ bb->vec[1][2]=bb->vec[2][2]=bb->vec[5][2]=bb->vec[6][2]= loc[2]+size[2];
+ }
+
+
+
+
+void my_tex_space_mesh(Mesh *me)
+ {
+ KeyBlock *kb;
+ float *fp, loc[3], size[3], min[3], max[3];
+ int a;
+
+ my_boundbox_mesh(me, loc, size);
+
+ if(me->texflag & AUTOSPACE) {
+ if(me->key) {
+ kb= me->key->refkey;
+ if (kb) {
+
+ INIT_MINMAX(min, max);
+
+ fp= (float *)kb->data;
+ for(a=0; a<kb->totelem; a++, fp+=3) {
+ DO_MINMAX(fp, min, max);
+ }
+ if(kb->totelem) {
+ loc[0]= (min[0]+max[0])/2.0; loc[1]= (min[1]+max[1])/2.0; loc[2]= (min[2]+max[2])/2.0;
+ size[0]= (max[0]-min[0])/2.0; size[1]= (max[1]-min[1])/2.0; size[2]= (max[2]-min[2])/2.0;
+ }
+ else {
+ loc[0]= loc[1]= loc[2]= 0.0;
+ size[0]= size[1]= size[2]= 0.0;
+ }
+
+ }
+ }
+
+ VECCOPY(me->loc, loc);
+ VECCOPY(me->size, size);
+ me->rot[0]= me->rot[1]= me->rot[2]= 0.0;
+
+ if(me->size[0]==0.0) me->size[0]= 1.0;
+ else if(me->size[0]>0.0 && me->size[0]<0.00001) me->size[0]= 0.00001;
+ else if(me->size[0]<0.0 && me->size[0]> -0.00001) me->size[0]= -0.00001;
+
+ if(me->size[1]==0.0) me->size[1]= 1.0;
+ else if(me->size[1]>0.0 && me->size[1]<0.00001) me->size[1]= 0.00001;
+ else if(me->size[1]<0.0 && me->size[1]> -0.00001) me->size[1]= -0.00001;
+
+ if(me->size[2]==0.0) me->size[2]= 1.0;
+ else if(me->size[2]>0.0 && me->size[2]<0.00001) me->size[2]= 0.00001;
+ else if(me->size[2]<0.0 && me->size[2]> -0.00001) me->size[2]= -0.00001;
+ }
+
+}
+
+void my_get_local_bounds(Object *ob, float *centre, float *size)
+ {
+ BoundBox *bb= NULL;
+ /* uses boundbox, function used by Ketsji */
+
+ if(ob->type==OB_MESH) {
+ bb= ( (Mesh *)ob->data )->bb;
+ if(bb==0) {
+ my_tex_space_mesh((struct Mesh *)ob->data);
+ bb= ( (Mesh *)ob->data )->bb;
+ }
+ }
+ else if ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT) {
+ centre[0]= centre[1]= centre[2]= 0.0;
+ size[0] = size[1]=size[2]=0.0;
+ }
+ else if(ob->type==OB_MBALL) {
+ bb= ob->bb;
+ }
+ if(bb==NULL) {
+ centre[0]= centre[1]= centre[2]= 0.0;
+ size[0] = size[1]=size[2]=0.0;
+ }
+ else {
+ size[0]= 0.5*fabs(bb->vec[0][0] - bb->vec[4][0]);
+ size[1]= 0.5*fabs(bb->vec[0][1] - bb->vec[2][1]);
+ size[2]= 0.5*fabs(bb->vec[0][2] - bb->vec[1][2]);
+
+ centre[0]= (bb->vec[0][0] + bb->vec[4][0])/2.0;
+ centre[1]= (bb->vec[0][1] + bb->vec[2][1])/2.0;
+ centre[2]= (bb->vec[0][2] + bb->vec[1][2])/2.0;
+ }
+}
+
+
+
+
+//////////////////////////////////////////////////////
+
+
+
+
+
+void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj,
+ struct Object* blenderobject,
+ RAS_MeshObject* meshobj,
+ KX_Scene* kxscene,
+ int activeLayerBitInfo,
+ e_PhysicsEngine physics_engine,
+ KX_BlenderSceneConverter *converter
+ )
+
+ {
+
+
+ SYS_SystemHandle syshandle = SYS_GetSystem();
+ //int userigidbody = SYS_GetCommandLineInt(syshandle,"norigidbody",0);
+ //bool bRigidBody = (userigidbody == 0);
+
+ PHY_ShapeProps* shapeprops =
+ CreateShapePropsFromBlenderObject(blenderobject,
+ kxscene);
+
+
+ PHY_MaterialProps* smmaterial =
+ CreateMaterialFromBlenderObject(blenderobject, kxscene);
+
+ KX_ObjectProperties objprop;
+ objprop.m_dyna = (blenderobject->gameflag & OB_DYNAMIC) != 0;
+ //mmm, for now, taks this for the size of the dynamicobject
+ // Blender uses inertia for radius of dynamic object
+ objprop.m_radius = blenderobject->inertia;
+ objprop.m_angular_rigidbody = (blenderobject->gameflag & OB_RIGID_BODY) != 0;
+ objprop.m_in_active_layer = (blenderobject->lay & activeLayerBitInfo) != 0;
+ objprop.m_ghost = (blenderobject->gameflag & OB_GHOST) != 0;
+ objprop.m_dynamic_parent=NULL;
+ objprop.m_isdeformable = ((blenderobject->gameflag2 & 2)) != 0;
+ objprop.m_implicitsphere = false;
+ objprop.m_implicitbox = false;
+
+ if (blenderobject->dtx & OB_BOUNDBOX)
+ {
+ objprop.m_implicitsphere = (blenderobject->boundtype == OB_BOUND_SPHERE);
+ objprop.m_implicitbox = (blenderobject->boundtype == OB_BOUND_BOX);
+ }
+
+ // get Root Parent of blenderobject
+ struct Object* parent= blenderobject->parent;
+ while(parent && parent->parent) {
+ parent= parent->parent;
+ }
+
+ if (parent && (parent->gameflag & OB_DYNAMIC)) {
+
+ KX_GameObject *parentgameobject = converter->FindGameObject(parent);
+ objprop.m_dynamic_parent = parentgameobject;
+
+ }
+
+ objprop.m_isactor = (blenderobject->gameflag & OB_ACTOR)!=0;
+ objprop.m_concave = (blenderobject->boundtype & 4) != 0;
+
+
+ my_get_local_bounds(blenderobject,objprop.m_boundingbox.m_center,objprop.m_boundingbox.m_extends);
+ //mmm, has to be divided by 2 to be proper extends
+ objprop.m_boundingbox.m_extends[0]*=2.f;
+ objprop.m_boundingbox.m_extends[1]*=2.f;
+ objprop.m_boundingbox.m_extends[2]*=2.f;
+
+ switch (physics_engine)
+ {
+ case UseSumo:
+ {
+
+#ifdef USE_SUMO_SOLID
+ KX_ConvertSumoObject( gameobj,meshobj,kxscene,shapeprops, smmaterial, &objprop);
+#endif
+ break;
+ }
+ case UseODE:
+ {
+
+#ifdef USE_ODE
+ KX_ConvertODEEngineObject(gameobj,meshobj,kxscene,shapeprops, smmaterial, &objprop);
+#endif //USE_ODE
+
+
+ break;
+ }
+ case UseDynamo:
+ {
+ //KX_ConvertDynamoObject(gameobj,meshobj,kxscene,shapeprops, smmaterial, &objprop);
+ break;
+ }
+ case UseNone:
+ default:
+ {
+ }
+
+}
+
+}
+
+
+
+
+
+static KX_LightObject *gamelight_from_blamp(Lamp *la, unsigned int layerflag, KX_Scene *kxscene, RAS_IRenderTools *rendertools, KX_BlenderSceneConverter *converter) {
+ RAS_LightObject lightobj;
+ KX_LightObject *gamelight;
+
+ lightobj.m_att1 = la->att1;
+ lightobj.m_red = la->r;
+ lightobj.m_green = la->g;
+ lightobj.m_blue = la->b;
+ lightobj.m_distance = la->dist;
+ lightobj.m_energy = la->energy;
+ lightobj.m_layer = layerflag;
+ lightobj.m_spotblend = la->spotblend;
+ lightobj.m_spotsize = la->spotsize;
+
+ if (la->type==LA_SUN) {
+ lightobj.m_type = RAS_LightObject::LIGHT_SUN;
+ } else if (la->type==LA_SPOT) {
+ lightobj.m_type = RAS_LightObject::LIGHT_SPOT;
+ } else {
+ lightobj.m_type = RAS_LightObject::LIGHT_NORMAL;
+ }
+
+ gamelight = new KX_LightObject(kxscene, KX_Scene::m_callbacks, rendertools, lightobj);
+ BL_ConvertLampIpos(la, gamelight, converter);
+
+ return gamelight;
+}
+
+static KX_Camera *gamecamera_from_bcamera(Camera *ca, KX_Scene *kxscene, KX_BlenderSceneConverter *converter) {
+ RAS_CameraData camdata;
+ KX_Camera *gamecamera;
+
+ camdata.m_lens= ca->lens;
+ camdata.m_clipend= ca->clipend;
+ camdata.m_clipstart= ca->clipsta;
+
+ gamecamera= new KX_Camera(kxscene, KX_Scene::m_callbacks, camdata);
+ gamecamera->SetName(ca->id.name + 2);
+
+ BL_ConvertCameraIpos(ca, gamecamera, converter);
+
+ return gamecamera;
+}
+
+static KX_GameObject *gameobject_from_blenderobject(
+ Object *ob,
+ KX_Scene *kxscene,
+ RAS_IRenderTools *rendertools,
+ KX_BlenderSceneConverter *converter,
+ Scene *blenderscene)
+{
+ KX_GameObject *gameobj = NULL;
+
+ switch(ob->type)
+ {
+ case OB_LAMP:
+ {
+ KX_LightObject* gamelight= gamelight_from_blamp(static_cast<Lamp*>(ob->data), ob->lay, kxscene, rendertools, converter);
+ gameobj = gamelight;
+
+ gamelight->AddRef();
+ kxscene->GetLightList()->Add(gamelight);
+
+ break;
+ }
+
+ case OB_CAMERA:
+ {
+ KX_Camera* gamecamera = gamecamera_from_bcamera(static_cast<Camera*>(ob->data), kxscene, converter);
+ gameobj = gamecamera;
+
+ gamecamera->AddRef();
+ kxscene->AddCamera(gamecamera);
+
+ break;
+ }
+
+ case OB_MESH:
+ {
+ Mesh* mesh = static_cast<Mesh*>(ob->data);
+ RAS_MeshObject* meshobj = converter->FindGameMesh(mesh, ob->lay);
+
+ if (!meshobj) {
+ meshobj = BL_ConvertMesh(mesh,ob,rendertools,kxscene,converter);
+ converter->RegisterGameMesh(meshobj, mesh);
+ }
+
+ // needed for python scripting
+ kxscene->GetLogicManager()->RegisterMeshName(meshobj->GetName(),meshobj);
+
+ gameobj = new BL_DeformableGameObject(kxscene,KX_Scene::m_callbacks);
+
+ // set transformation
+ gameobj->AddMesh(meshobj);
+
+ // for all objects: check whether they want to
+ // respond to updates
+ bool ignoreActivityCulling =
+ ((ob->gameflag2 & OB_NEVER_DO_ACTIVITY_CULLING)!=0);
+ gameobj->SetIgnoreActivityCulling(ignoreActivityCulling);
+
+ // If this is a skin object, make Skin Controller
+ if (ob->parent && ob->parent->type == OB_ARMATURE && ob->partype==PARSKEL && ((Mesh*)ob->data)->dvert){
+ BL_SkinDeformer *dcont = new BL_SkinDeformer(ob, (BL_SkinMeshObject*)meshobj);
+ ((BL_DeformableGameObject*)gameobj)->m_pDeformer = dcont;
+ }
+ else if (((Mesh*)ob->data)->dvert){
+ BL_MeshDeformer *dcont = new BL_MeshDeformer(ob, (BL_SkinMeshObject*)meshobj);
+ ((BL_DeformableGameObject*)gameobj)->m_pDeformer = dcont;
+ }
+
+ break;
+ }
+
+ case OB_ARMATURE:
+ {
+ gameobj = new BL_ArmatureObject (kxscene, KX_Scene::m_callbacks,
+ (bArmature*)ob->data,
+ ob->pose);
+
+ /* Get the current pose from the armature object and apply it as the rest pose */
+ break;
+ }
+
+ case OB_EMPTY:
+ {
+ gameobj = new KX_EmptyObject(kxscene,KX_Scene::m_callbacks);
+ // set transformation
+ break;
+ }
+ }
+
+ return gameobj;
+}
+
+struct parentChildLink {
+ struct Object* m_blenderchild;
+ SG_Node* m_gamechildnode;
+};
+
+ /**
+ * Find the specified scene by name, or the first
+ * scene if nothing matches (shouldn't happen).
+ */
+static struct Scene *GetSceneForName(struct Main *maggie, const STR_String& scenename) {
+ Scene *sce;
+
+ for (sce= (Scene*) maggie->scene.first; sce; sce= (Scene*) sce->id.next)
+ if (scenename == (sce->id.name+2))
+ return sce;
+
+ return (Scene*) maggie->scene.first;
+}
+
+// convert blender objects into ketsji gameobjects
+void BL_ConvertBlenderObjects(struct Main* maggie,
+ const STR_String& scenename,
+ KX_Scene* kxscene,
+ KX_KetsjiEngine* ketsjiEngine,
+ e_PhysicsEngine physics_engine,
+ PyObject* pythondictionary,
+ SCA_IInputDevice* keydev,
+ RAS_IRenderTools* rendertools,
+ RAS_ICanvas* canvas,
+ KX_BlenderSceneConverter* converter,
+ bool alwaysUseExpandFraming
+ )
+{
+ Scene *blenderscene = GetSceneForName(maggie, scenename);
+
+ // Get the frame settings of the canvas.
+ // Get the aspect ratio of the canvas as designed by the user.
+
+ RAS_FrameSettings::RAS_FrameType frame_type;
+ int aspect_width;
+ int aspect_height;
+
+ if (alwaysUseExpandFraming) {
+ frame_type = RAS_FrameSettings::e_frame_extend;
+ aspect_width = canvas->GetWidth();
+ aspect_height = canvas->GetHeight();
+ } else {
+ if (blenderscene->framing.type == SCE_GAMEFRAMING_BARS) {
+ frame_type = RAS_FrameSettings::e_frame_bars;
+ } else if (blenderscene->framing.type == SCE_GAMEFRAMING_EXTEND) {
+ frame_type = RAS_FrameSettings::e_frame_extend;
+ } else {
+ frame_type = RAS_FrameSettings::e_frame_scale;
+ }
+
+ aspect_width = blenderscene->r.xsch;
+ aspect_height = blenderscene->r.ysch;
+ }
+
+ RAS_FrameSettings frame_settings(
+ frame_type,
+ blenderscene->framing.col[0],
+ blenderscene->framing.col[1],
+ blenderscene->framing.col[2],
+ aspect_width,
+ aspect_height
+ );
+ kxscene->SetFramingType(frame_settings);
+
+ kxscene->SetGravity(MT_Vector3(0,0,(blenderscene->world != NULL) ? -blenderscene->world->gravity : -9.8));
+
+ /* set activity culling parameters */
+ if (blenderscene->world) {
+ kxscene->SetActivityCulling( (blenderscene->world->mode & WO_ACTIVITY_CULLING) != 0);
+ kxscene->SetActivityCullingRadius(blenderscene->world->activityBoxRadius);
+ } else {
+ kxscene->SetActivityCulling(false);
+ }
+
+ int activeLayerBitInfo = blenderscene->lay;
+
+ // templist to find Root Parents (object with no parents)
+ CListValue* templist = new CListValue();
+ CListValue* sumolist = new CListValue();
+
+ vector<parentChildLink> vec_parent_child;
+
+ CListValue* objectlist = kxscene->GetObjectList();
+ CListValue* parentlist = kxscene->GetRootParentList();
+
+ SCA_LogicManager* logicmgr = kxscene->GetLogicManager();
+ SCA_TimeEventManager* timemgr = kxscene->GetTimeEventManager();
+
+ CListValue* logicbrick_conversionlist = new CListValue();
+
+ // Convert actions to actionmap
+ bAction *curAct;
+ for (curAct = (bAction*)maggie->action.first; curAct; curAct=(bAction*)curAct->id.next)
+ {
+ logicmgr->RegisterActionName(curAct->id.name, curAct);
+ }
+
+ Base *base = static_cast<Base*>(blenderscene->base.first);
+ while(base)
+ {
+ Object* blenderobject = base->object;
+ KX_GameObject* gameobj = gameobject_from_blenderobject(
+ base->object,
+ kxscene,
+ rendertools,
+ converter,
+ blenderscene);
+
+ if (gameobj)
+ {
+ MT_Point3 pos = MT_Point3(
+ blenderobject->loc[0]+blenderobject->dloc[0],
+ blenderobject->loc[1]+blenderobject->dloc[1],
+ blenderobject->loc[2]+blenderobject->dloc[2]
+ );
+ MT_Vector3 eulxyz = MT_Vector3(
+ blenderobject->rot[0],
+ blenderobject->rot[1],
+ blenderobject->rot[2]
+ );
+ MT_Vector3 scale = MT_Vector3(
+ blenderobject->size[0],
+ blenderobject->size[1],
+ blenderobject->size[2]
+ );
+
+ gameobj->NodeSetLocalPosition(pos);
+ gameobj->NodeSetLocalOrientation(MT_Matrix3x3(eulxyz));
+ gameobj->NodeSetLocalScale(scale);
+ gameobj->NodeUpdateGS(0,true);
+
+ BL_ConvertIpos(blenderobject,gameobj,converter);
+
+ bool isInActiveLayer = (blenderobject->lay & activeLayerBitInfo) !=0;
+
+ sumolist->Add(gameobj->AddRef());
+
+ BL_ConvertProperties(blenderobject,gameobj,timemgr,kxscene,isInActiveLayer);
+
+
+ gameobj->SetName(blenderobject->id.name);
+
+ // templist to find Root Parents (object with no parents)
+ templist->Add(gameobj->AddRef());
+
+ // update children/parent hierarchy
+ if (blenderobject->parent != 0)
+ {
+ // blender has an additional 'parentinverse' offset in each object
+ SG_Node* parentinversenode = new SG_Node(NULL,NULL,SG_Callbacks());
+
+ // define a normal parent relationship for this node.
+ KX_NormalParentRelation * parent_relation = KX_NormalParentRelation::New();
+ parentinversenode->SetParentRelation(parent_relation);
+
+ parentChildLink pclink;
+ pclink.m_blenderchild = blenderobject;
+ pclink.m_gamechildnode = parentinversenode;
+ vec_parent_child.push_back(pclink);
+
+ float* fl = (float*) blenderobject->parentinv;
+ MT_Transform parinvtrans(fl);
+ parentinversenode->SetLocalPosition(parinvtrans.getOrigin());
+ parentinversenode->SetLocalOrientation(parinvtrans.getBasis());
+ parentinversenode->AddChild(gameobj->GetSGNode());
+ }
+
+ // needed for python scripting
+ logicmgr->RegisterGameObjectName(gameobj->GetName(),gameobj);
+
+ converter->RegisterGameObject(gameobj, blenderobject);
+
+ // this was put in rapidly, needs to be looked at more closely
+ // only draw/use objects in active 'blender' layers
+
+ logicbrick_conversionlist->Add(gameobj->AddRef());
+
+ if (isInActiveLayer)
+ {
+ objectlist->Add(gameobj->AddRef());
+
+ gameobj->NodeUpdateGS(0,true);
+ gameobj->Bucketize();
+
+ }
+ }
+
+ base = base->next;
+ }
+
+ if (blenderscene->camera) {
+ KX_Camera *gamecamera= (KX_Camera*) converter->FindGameObject(blenderscene->camera);
+
+ kxscene->SetActiveCamera(gamecamera);
+ }
+
+ // Set up armatures
+ for (base = static_cast<Base*>(blenderscene->base.first); base; base=base->next){
+ if (base->object->type==OB_MESH){
+ Mesh *me = (Mesh*)base->object->data;
+
+ if (me->dvert){
+ KX_GameObject *obj = converter->FindGameObject(base->object);
+
+ if (base->object->parent && base->object->parent->type==OB_ARMATURE && base->object->partype==PARSKEL){
+ KX_GameObject *par = converter->FindGameObject(base->object->parent);
+ if (par)
+ ((BL_SkinDeformer*)(((BL_DeformableGameObject*)obj)->m_pDeformer))->SetArmature((BL_ArmatureObject*) par);
+ }
+ }
+ }
+ }
+
+ // create hierarchy information
+ int i;
+ vector<parentChildLink>::iterator pcit;
+
+ for (pcit = vec_parent_child.begin();!(pcit==vec_parent_child.end());++pcit)
+ {
+
+ struct Object* blenderchild = pcit->m_blenderchild;
+ if (blenderchild->partype == PARVERT1)
+ {
+ // creat a new vertex parent relationship for this node.
+ KX_VertexParentRelation * vertex_parent_relation = KX_VertexParentRelation::New();
+ pcit->m_gamechildnode->SetParentRelation(vertex_parent_relation);
+ } else
+ if (blenderchild->partype == PARSLOW)
+ {
+ // creat a new slow parent relationship for this node.
+ KX_SlowParentRelation * slow_parent_relation = KX_SlowParentRelation::New(blenderchild->sf);
+ pcit->m_gamechildnode->SetParentRelation(slow_parent_relation);
+ }
+
+ struct Object* blenderparent = blenderchild->parent;
+ KX_GameObject* parentobj = converter->FindGameObject(blenderparent);
+ if (parentobj)
+ {
+ parentobj-> GetSGNode()->AddChild(pcit->m_gamechildnode);
+ }
+ }
+ vec_parent_child.clear();
+
+ // find 'root' parents (object that has not parents in SceneGraph)
+ for (i=0;i<templist->GetCount();++i)
+ {
+ KX_GameObject* gameobj = (KX_GameObject*) templist->GetValue(i);
+ if (gameobj->GetSGNode()->GetSGParent() == 0)
+ {
+ parentlist->Add(gameobj->AddRef());
+ gameobj->NodeUpdateGS(0,true);
+ }
+ }
+
+ // create physics information
+ for (i=0;i<sumolist->GetCount();i++)
+ {
+ KX_GameObject* gameobj = (KX_GameObject*) sumolist->GetValue(i);
+ struct Object* blenderobject = converter->FindBlenderObject(gameobj);
+ int nummeshes = gameobj->GetMeshCount();
+ RAS_MeshObject* meshobj = 0;
+
+ if (nummeshes > 0)
+ {
+ meshobj = gameobj->GetMesh(0);
+ }
+
+ BL_CreatePhysicsObjectNew(gameobj,blenderobject,meshobj,kxscene,activeLayerBitInfo,physics_engine,converter);
+
+ }
+
+ templist->Release();
+ sumolist->Release();
+
+
+ int executePriority=0; /* incremented by converter routines */
+
+ // convert global sound stuff
+
+ /* XXX, glob is the very very wrong place for this
+ * to be, re-enable once the listener has been moved into
+ * the scene. */
+#if 0
+ SND_Scene* soundscene = kxscene->GetSoundScene();
+ SND_SoundListener* listener = soundscene->GetListener();
+ if (listener && glob->listener)
+ {
+ listener->SetDopplerFactor(glob->listener->dopplerfactor);
+ listener->SetDopplerVelocity(glob->listener->dopplervelocity);
+ listener->SetGain(glob->listener->gain);
+ }
+#endif
+
+ // convert world
+ KX_WorldInfo* worldinfo = new BlenderWorldInfo(blenderscene->world);
+ converter->RegisterWorldInfo(worldinfo);
+ kxscene->SetWorldInfo(worldinfo);
+
+ // convert logic bricks, sensors, controllers and actuators
+ for (i=0;i<logicbrick_conversionlist->GetCount();i++)
+ {
+ KX_GameObject* gameobj = static_cast<KX_GameObject*>(logicbrick_conversionlist->GetValue(i));
+ struct Object* blenderobj = converter->FindBlenderObject(gameobj);
+ bool isInActiveLayer = (blenderobj->lay & activeLayerBitInfo)!=0;
+ BL_ConvertActuators(maggie->name, blenderobj,gameobj,logicmgr,kxscene,ketsjiEngine,executePriority, activeLayerBitInfo,isInActiveLayer,rendertools,converter);
+ }
+ for ( i=0;i<logicbrick_conversionlist->GetCount();i++)
+ {
+ KX_GameObject* gameobj = static_cast<KX_GameObject*>(logicbrick_conversionlist->GetValue(i));
+ struct Object* blenderobj = converter->FindBlenderObject(gameobj);
+ bool isInActiveLayer = (blenderobj->lay & activeLayerBitInfo)!=0;
+ BL_ConvertControllers(blenderobj,gameobj,logicmgr,pythondictionary,executePriority,activeLayerBitInfo,isInActiveLayer,converter);
+ }
+ for ( i=0;i<logicbrick_conversionlist->GetCount();i++)
+ {
+ KX_GameObject* gameobj = static_cast<KX_GameObject*>(logicbrick_conversionlist->GetValue(i));
+ struct Object* blenderobj = converter->FindBlenderObject(gameobj);
+ bool isInActiveLayer = (blenderobj->lay & activeLayerBitInfo)!=0;
+ BL_ConvertSensors(blenderobj,gameobj,logicmgr,kxscene,keydev,executePriority,activeLayerBitInfo,isInActiveLayer,canvas,converter);
+ }
+ logicbrick_conversionlist->Release();
+}
diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.h b/source/gameengine/Converter/BL_BlenderDataConversion.h
new file mode 100644
index 00000000000..1ed6a866269
--- /dev/null
+++ b/source/gameengine/Converter/BL_BlenderDataConversion.h
@@ -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 *****
+ */
+#ifndef __BLENDER_CONVERT
+#define __BLENDER_CONVERT
+
+#include "STR_String.h"
+#include "KX_Python.h"
+#include "KX_PhysicsEngineEnums.h"
+
+class RAS_MeshObject* BL_ConvertMesh(struct Mesh* mesh,struct Object* lightobj,class RAS_IRenderTools* rendertools,class KX_Scene* scene, class KX_BlenderSceneConverter *converter);
+
+void BL_ConvertBlenderObjects(struct Main* maggie,
+ const STR_String& scenename,
+ class KX_Scene* kxscene,
+ class KX_KetsjiEngine* ketsjiEngine,
+ e_PhysicsEngine physics_engine,
+ PyObject* pythondictionary,
+ class SCA_IInputDevice* keydev,
+ class RAS_IRenderTools* rendertools,
+ class RAS_ICanvas* canvas,
+ class KX_BlenderSceneConverter* sceneconverter,
+ bool alwaysUseExpandFraming
+ );
+
+#endif // __BLENDER_CONVERT
diff --git a/source/gameengine/Converter/BL_DeformableGameObject.cpp b/source/gameengine/Converter/BL_DeformableGameObject.cpp
new file mode 100644
index 00000000000..d6830380b00
--- /dev/null
+++ b/source/gameengine/Converter/BL_DeformableGameObject.cpp
@@ -0,0 +1,62 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "BL_DeformableGameObject.h"
+
+BL_DeformableGameObject::~BL_DeformableGameObject()
+{
+ if (m_pDeformer)
+ delete m_pDeformer; // __NLA : Temporary until we decide where to put this
+}
+
+void BL_DeformableGameObject::ProcessReplica(KX_GameObject* replica)
+{
+ KX_GameObject::ProcessReplica(replica);
+
+ if (m_pDeformer){
+ ((BL_DeformableGameObject*)replica)->m_pDeformer = m_pDeformer->GetReplica();
+ }
+
+}
+
+CValue* BL_DeformableGameObject::GetReplica()
+{
+
+ BL_DeformableGameObject* replica = new BL_DeformableGameObject(*this);//m_float,GetName());
+
+ // this will copy properties and so on...
+ CValue::AddDataToReplica(replica);
+
+ ProcessReplica(replica);
+ return replica;
+
+}
diff --git a/source/gameengine/Converter/BL_DeformableGameObject.h b/source/gameengine/Converter/BL_DeformableGameObject.h
new file mode 100644
index 00000000000..1f05d2fcbcc
--- /dev/null
+++ b/source/gameengine/Converter/BL_DeformableGameObject.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 *****
+ */
+
+#ifndef BL_DEFORMABLEGAMEOBJECT
+#define BL_DEFORMABLEGAMEOBJECT
+
+#ifdef WIN32
+#pragma warning (disable:4786) // get rid of stupid stl-visual compiler debug warning
+#endif //WIN32
+
+#include "KX_GameObject.h"
+#include "RAS_Deformer.h"
+
+class BL_DeformableGameObject : public KX_GameObject
+{
+public:
+
+ RAS_Deformer *m_pDeformer;
+ CValue* GetReplica();
+ virtual void Relink(GEN_Map<GEN_HashedPtr, void*>*map)
+ {
+ if (m_pDeformer)
+ m_pDeformer->Relink (map);
+ };
+ void ProcessReplica(KX_GameObject* replica);
+
+ BL_DeformableGameObject(void* sgReplicationInfo, SG_Callbacks callbacks) :
+ KX_GameObject(sgReplicationInfo,callbacks),
+ m_pDeformer(NULL)
+{
+ };
+ virtual ~BL_DeformableGameObject();
+
+};
+
+#endif
+
diff --git a/source/gameengine/Converter/BL_MeshDeformer.cpp b/source/gameengine/Converter/BL_MeshDeformer.cpp
new file mode 100644
index 00000000000..3aa4287478d
--- /dev/null
+++ b/source/gameengine/Converter/BL_MeshDeformer.cpp
@@ -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 *****
+ * Simple deformation controller that restores a mesh to its rest position
+ */
+
+#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
+
+#include "RAS_IPolygonMaterial.h"
+#include "BL_MeshDeformer.h"
+#include "BL_SkinMeshObject.h"
+#include "DNA_mesh_types.h"
+#include "BLI_arithb.h"
+
+#include "GEN_Map.h"
+#include "STR_HashedString.h"
+
+
+bool BL_MeshDeformer::Apply(RAS_IPolyMaterial *mat)
+{
+ int i, j, index;
+ vecVertexArray array;
+ vecIndexArrays mvarray;
+ vecIndexArrays diarray;
+ float co[3];
+
+ RAS_TexVert *tv;
+ MVert *mvert;
+
+ // For each material
+ array = m_pMeshObject->GetVertexCache(mat);
+ mvarray = m_pMeshObject->GetMVertCache(mat);
+ diarray = m_pMeshObject->GetDIndexCache(mat);
+
+ // For each array
+ for (i=0; i<array.size(); i++){
+ // For each vertex
+ for (j=0; j<array[i]->size(); j++){
+ tv = &((*array[i])[j]);
+ MT_Point3 pt = tv->xyz();
+
+ index = ((*diarray[i])[j]);
+
+ mvert = &(m_bmesh->mvert[((*mvarray[i])[index])]);
+ // Do the nasty (in this case, copy the untransformed data from the blender mesh)
+ co[0]=mvert->co[0];
+ co[1]=mvert->co[1];
+ co[2]=mvert->co[2];
+
+ pt[0] = co[0];
+ pt[1] = co[1];
+ pt[2] = co[2];
+
+ tv->SetXYZ(pt);
+ }
+ }
+ return true;
+}
+
+BL_MeshDeformer::~BL_MeshDeformer()
+{
+ if (m_transverts)
+ delete []m_transverts;
+ if (m_transnors)
+ delete []m_transnors;
+};
+
+void BL_MeshDeformer::RecalcNormals()
+{
+ int v, f;
+ float fnor[3], co1[3], co2[3], co3[3], co4[3];
+
+ /* Clear all vertex normal accumulators */
+ for (v =0; v<m_bmesh->totvert; v++){
+ m_transnors[v]=MT_Point3(0,0,0);
+ }
+
+ /* Find the face normals */
+ for (f = 0; f<m_bmesh->totface; f++){
+ // Make new face normal based on the transverts
+ MFace *mf= &((MFace*)m_bmesh->mface)[f];
+
+ if (mf->v3) {
+ for (int vl=0; vl<3; vl++){
+ co1[vl]=m_transverts[mf->v1][vl];
+ co2[vl]=m_transverts[mf->v2][vl];
+ co3[vl]=m_transverts[mf->v3][vl];
+ if (mf->v4)
+ co4[vl]=m_transverts[mf->v4][vl];
+ }
+
+ /* FIXME: Use moto */
+ if (mf->v4)
+ CalcNormFloat4(co1, co2, co3, co4, fnor);
+ else
+ CalcNormFloat(co1, co2, co3, fnor);
+
+ /* Decide which normals are affected by this face's normal */
+ m_transnors[mf->v1]+=MT_Point3(fnor);
+ m_transnors[mf->v2]+=MT_Point3(fnor);
+ m_transnors[mf->v3]+=MT_Point3(fnor);
+ if (mf->v4)
+ m_transnors[mf->v4]+=MT_Point3(fnor);
+
+ }
+
+ }
+
+ for (v =0; v<m_bmesh->totvert; v++){
+ float nor[3];
+
+ m_transnors[v]=m_transnors[v].safe_normalized();
+ nor[0]=m_transnors[v][0];
+ nor[1]=m_transnors[v][1];
+ nor[2]=m_transnors[v][2];
+
+ };
+}
+
+void BL_MeshDeformer::VerifyStorage()
+{
+ /* Ensure that we have the right number of verts assigned */
+ if (m_tvtot!=m_bmesh->totvert+m_bmesh->totface){
+ if (m_transverts)
+ delete []m_transverts;
+ if (m_transnors)
+ delete []m_transnors;
+
+ m_transnors =new MT_Point3[m_bmesh->totvert+m_bmesh->totface];
+ m_transverts=new MT_Point3[m_bmesh->totvert];
+ m_tvtot = m_bmesh->totvert;
+ }
+}
+ \ No newline at end of file
diff --git a/source/gameengine/Converter/BL_MeshDeformer.h b/source/gameengine/Converter/BL_MeshDeformer.h
new file mode 100644
index 00000000000..9880725a2d0
--- /dev/null
+++ b/source/gameengine/Converter/BL_MeshDeformer.h
@@ -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 *****
+ */
+
+#ifndef BL_MESHDEFORMER
+#define BL_MESHDEFORMER
+
+#include "RAS_Deformer.h"
+#include "DNA_object_types.h"
+#include "MT_Point3.h"
+#include <stdlib.h>
+
+#ifdef WIN32
+#pragma warning (disable:4786) // get rid of stupid stl-visual compiler debug warning
+#endif //WIN32
+
+class BL_MeshDeformer : public RAS_Deformer
+{
+public:
+ void VerifyStorage();
+ void RecalcNormals();
+ virtual void Relink(GEN_Map<class GEN_HashedPtr, void*>*map){};
+ BL_MeshDeformer(struct Object* obj, class BL_SkinMeshObject *meshobj):
+ m_transverts(NULL),
+ m_tvtot(0),
+ m_transnors(NULL),
+ m_pMeshObject(meshobj),
+ m_bmesh((struct Mesh*)(obj->data)){};
+ virtual ~BL_MeshDeformer();
+ virtual void SetSimulatedTime(double time){};
+ virtual bool Apply(class RAS_IPolyMaterial *mat);
+ virtual void Update(void){};
+ virtual RAS_Deformer* GetReplica(){return NULL;};
+ // virtual void InitDeform(double time){};
+protected:
+ class BL_SkinMeshObject *m_pMeshObject;
+ struct Mesh *m_bmesh;
+ MT_Point3 *m_transnors;
+ MT_Point3 *m_transverts;
+ int m_tvtot;
+
+};
+
+#endif
diff --git a/source/gameengine/Converter/BL_SkinDeformer.cpp b/source/gameengine/Converter/BL_SkinDeformer.cpp
new file mode 100644
index 00000000000..4eb2b849c3c
--- /dev/null
+++ b/source/gameengine/Converter/BL_SkinDeformer.cpp
@@ -0,0 +1,187 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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)
+#endif //WIN32
+
+#include "GEN_Map.h"
+#include "STR_HashedString.h"
+#include "RAS_IPolygonMaterial.h"
+#include "BL_SkinMeshObject.h"
+
+//#include "BL_ArmatureController.h"
+#include "BL_SkinDeformer.h"
+#include "DNA_armature_types.h"
+#include "DNA_action_types.h"
+#include "DNA_mesh_types.h"
+#include "BKE_armature.h"
+#include "BKE_action.h"
+#include "MT_Point3.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#define __NLA_DEFNORMALS
+//#undef __NLA_DEFNORMALS
+
+BL_SkinDeformer::~BL_SkinDeformer()
+{
+};
+
+bool BL_SkinDeformer::Apply(RAS_IPolyMaterial *mat)
+{
+ int i, j, index;
+ vecVertexArray array;
+#ifdef __NLA_OLDDEFORM
+ vecMVertArray mvarray;
+#else
+ vecIndexArrays mvarray;
+#endif
+ vecMDVertArray dvarray;
+ vecIndexArrays diarray;
+
+ RAS_TexVert *tv;
+#ifdef __NLA_OLDDEFORM
+ MVert *mvert;
+ MDeformVert *dvert;
+#endif
+ MT_Point3 pt;
+// float co[3];
+
+ if (!m_armobj)
+ return false;
+
+ Update();
+
+ array = m_pMeshObject->GetVertexCache(mat);
+#ifdef __NLA_OLDDEFORM
+ dvarray = m_pMeshObject->GetDVertCache(mat);
+#endif
+ mvarray = m_pMeshObject->GetMVertCache(mat);
+ diarray = m_pMeshObject->GetDIndexCache(mat);
+
+
+ // For each array
+ for (i=0; i<array.size(); i++){
+ // For each vertex
+ for (j=0; j<array[i]->size(); j++){
+
+ tv = &((*array[i])[j]);
+
+ index = ((*diarray[i])[j]);
+#ifdef __NLA_OLDDEFORM
+ pt = tv->xyz();
+ mvert = ((*mvarray[i])[index]);
+ dvert = ((*dvarray[i])[index]);
+#endif
+
+ // Copy the untransformed data from the original mvert
+#ifdef __NLA_OLDDEFORM
+ co[0]=mvert->co[0];
+ co[1]=mvert->co[1];
+ co[2]=mvert->co[2];
+
+ // Do the deformation
+ GB_calc_armature_deform(co, dvert);
+ tv->SetXYZ(co);
+#else
+ // Set the data
+ tv->SetXYZ(m_transverts[((*mvarray[i])[index])]);
+#ifdef __NLA_DEFNORMALS
+
+ tv->SetNormal(m_transnors[((*mvarray[i])[index])]);
+#endif
+#endif
+ }
+ }
+
+ return true;
+}
+
+RAS_Deformer *BL_SkinDeformer::GetReplica()
+{
+ BL_SkinDeformer *result;
+
+ result = new BL_SkinDeformer(*this);
+ result->ProcessReplica();
+ return result;
+}
+
+void BL_SkinDeformer::ProcessReplica()
+{
+}
+
+void BL_SkinDeformer::Update(void)
+{
+
+ /* See if the armature has been updated for this frame */
+ if (m_lastUpdate!=m_armobj->GetLastFrame()){
+
+ /* Do all of the posing necessary */
+ GB_init_armature_deform (m_defbase, m_premat, m_postmat);
+ m_armobj->ApplyPose();
+ precalc_armature_posemats (m_armobj->GetArmature());
+ for (Bone *curBone=(Bone*)m_armobj->GetArmature()->bonebase.first; curBone; curBone=(Bone*)curBone->next)
+ precalc_bone_defmat(curBone);
+
+ VerifyStorage();
+
+ /* Transform the verts & store locally */
+ for (int v =0; v<m_bmesh->totvert; v++){
+ float co[3];
+
+ co[0]=m_bmesh->mvert[v].co[0];
+ co[1]=m_bmesh->mvert[v].co[1];
+ co[2]=m_bmesh->mvert[v].co[2];
+ GB_calc_armature_deform(co, &m_bmesh->dvert[v]);
+
+ m_transverts[v]=MT_Point3(co);
+ }
+
+ RecalcNormals();
+
+
+ /* Update the current frame */
+ m_lastUpdate=m_armobj->GetLastFrame();
+ }
+}
+
+void BL_SkinDeformer::SetArmature(BL_ArmatureObject *armobj)
+{
+ m_armobj = armobj;
+
+ for (bDeformGroup *dg=(bDeformGroup*)m_defbase->first; dg; dg=(bDeformGroup*)dg->next)
+ dg->data = (void*)get_named_bone(m_armobj->GetArmature(), dg->name);
+
+ GB_validate_defgroups(m_bmesh, m_defbase);
+}
diff --git a/source/gameengine/Converter/BL_SkinDeformer.h b/source/gameengine/Converter/BL_SkinDeformer.h
new file mode 100644
index 00000000000..25c3654d269
--- /dev/null
+++ b/source/gameengine/Converter/BL_SkinDeformer.h
@@ -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 *****
+ */
+
+#ifndef BL_SKINDEFORMER
+#define BL_SKINDEFORMER
+
+#ifdef WIN32
+#pragma warning (disable:4786) // get rid of stupid stl-visual compiler debug warning
+#endif //WIN32
+
+#include "BL_MeshDeformer.h"
+#include "BL_ArmatureObject.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+#include "BKE_armature.h"
+
+#include "RAS_Deformer.h"
+
+
+class BL_SkinDeformer : public BL_MeshDeformer
+{
+public:
+// void SetArmatureController (BL_ArmatureController *cont);
+ virtual void Relink(GEN_Map<class GEN_HashedPtr, void*>*map)
+ {
+ void **h_obj = (*map)[m_armobj];
+ if (h_obj){
+ SetArmature( (BL_ArmatureObject*)(*h_obj) );
+ }
+ else
+ m_armobj=NULL;
+ }
+ void SetArmature (class BL_ArmatureObject *armobj);
+ BL_SkinDeformer( struct Object *bmeshobj,
+ class BL_SkinMeshObject *mesh)
+ :BL_MeshDeformer(bmeshobj, mesh),
+ m_armobj(NULL),
+ m_defbase(&bmeshobj->defbase),
+ m_lastUpdate(-1)
+ {
+ /* Build all precalculatable matrices for bones */
+
+ GB_build_mats(bmeshobj->parent->obmat, bmeshobj->obmat, m_premat, m_postmat);
+ GB_validate_defgroups((Mesh*)bmeshobj->data, m_defbase);
+ // Validate bone data in bDeformGroups
+/*
+ for (bDeformGroup *dg=(bDeformGroup*)m_defbase->first; dg; dg=(bDeformGroup*)dg->next)
+ dg->data = (void*)get_named_bone(barm, dg->name);
+*/
+ };
+
+ virtual void ProcessReplica();
+ virtual RAS_Deformer *GetReplica();
+ virtual ~BL_SkinDeformer();
+ void Update (void);
+ bool Apply (class RAS_IPolyMaterial *polymat);
+
+protected:
+ BL_ArmatureObject *m_armobj; // Our parent object
+ float m_premat[4][4];
+ float m_postmat[4][4];
+ float m_time;
+ double m_lastUpdate;
+ ListBase *m_defbase;
+};
+
+#endif
+
diff --git a/source/gameengine/Converter/BL_SkinMeshObject.cpp b/source/gameengine/Converter/BL_SkinMeshObject.cpp
new file mode 100644
index 00000000000..859b495b9d5
--- /dev/null
+++ b/source/gameengine/Converter/BL_SkinMeshObject.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 *****
+ * Deformer that supports armature skinning
+ */
+
+#ifdef WIN32
+#pragma warning (disable:4786) // get rid of stupid stl-visual compiler debug warning
+#endif //WIN32
+#include "RAS_IPolygonMaterial.h"
+#include "BL_SkinMeshObject.h"
+#include "BL_DeformableGameObject.h"
+#include "DNA_mesh_types.h"
+#include "KX_GameObject.h"
+#include "RAS_BucketManager.h"
+
+void BL_SkinMeshObject::AddPolygon(RAS_Polygon* poly)
+{
+ /* We're overriding this so that we can eventually associate faces with verts somehow */
+
+ // For vertIndex in poly:
+ // find the appropriate normal
+
+ RAS_MeshObject::AddPolygon(poly);
+}
+
+#ifdef __NLA_OLDDEFORM
+int BL_SkinMeshObject::FindOrAddDeform(int vtxarray, struct MVert *mv, struct MDeformVert *dv, RAS_IPolyMaterial* mat)
+#else
+int BL_SkinMeshObject::FindOrAddDeform(int vtxarray, int mv, struct MDeformVert *dv, RAS_IPolyMaterial* mat)
+#endif
+{
+ BL_SkinArrayOptimizer* ao = (BL_SkinArrayOptimizer*)GetArrayOptimizer(mat);//*(m_matVertexArrays[*mat]);
+ int numvert = ao->m_MvertArrayCache1[vtxarray]->size();
+
+ /* Check to see if this has already been pushed */
+ for (int i=0; i<ao->m_MvertArrayCache1[vtxarray]->size(); i++){
+ if (mv == (*ao->m_MvertArrayCache1[vtxarray])[i])
+ return i;
+ }
+
+ ao->m_MvertArrayCache1[vtxarray]->push_back(mv);
+ ao->m_DvertArrayCache1[vtxarray]->push_back(dv);
+
+ return numvert;
+};
+
+int BL_SkinMeshObject::FindVertexArray(int numverts,RAS_IPolyMaterial* polymat)
+{
+ int array=-1;
+
+ BL_SkinArrayOptimizer* ao = (BL_SkinArrayOptimizer*)GetArrayOptimizer(polymat);
+
+
+ for (int i=0;i<ao->m_VertexArrayCache1.size();i++)
+ {
+ if ( (ao->m_TriangleArrayCount[i] + (numverts-2)) < BUCKET_MAX_TRIANGLES)
+ {
+ if((ao->m_VertexArrayCache1[i]->size()+numverts < BUCKET_MAX_INDICES))
+ {
+ array = i;
+ ao->m_TriangleArrayCount[array]+=numverts-2;
+ break;
+ }
+ }
+ }
+
+
+ if (array == -1)
+ {
+ array = ao->m_VertexArrayCache1.size();
+
+ vector<RAS_TexVert>* va = new vector<RAS_TexVert>;
+ ao->m_VertexArrayCache1.push_back(va);
+
+ KX_IndexArray *ia = new KX_IndexArray();
+ ao->m_IndexArrayCache1.push_back(ia);
+
+#ifdef __NLA_OLDDEFORM
+ BL_MVertArray *bva = new BL_MVertArray();
+#else
+ KX_IndexArray *bva = new KX_IndexArray();
+#endif
+ ao->m_MvertArrayCache1.push_back(bva);
+
+ BL_DeformVertArray *dva = new BL_DeformVertArray();
+ ao->m_DvertArrayCache1.push_back(dva);
+
+ KX_IndexArray *da = new KX_IndexArray();
+ ao->m_DIndexArrayCache1.push_back(da);
+
+ ao->m_TriangleArrayCount.push_back(numverts-2);
+
+ }
+
+
+ return array;
+}
+
+
+//void BL_SkinMeshObject::Bucketize(double* oglmatrix,void* clientobj,bool useObjectColor,const MT_Vector4& rgbavec,RAS_BucketManager* bucketmgr)
+void BL_SkinMeshObject::Bucketize(double* oglmatrix,void* clientobj,bool useObjectColor,const MT_Vector4& rgbavec)
+{
+
+ KX_MeshSlot ms;
+ ms.m_clientObj = clientobj;
+ ms.m_mesh = this;
+ ms.m_OpenGLMatrix = oglmatrix;
+ ms.m_bObjectColor = useObjectColor;
+ ms.m_RGBAcolor = rgbavec;
+ ms.m_pDeformer = ((BL_DeformableGameObject*)clientobj)->m_pDeformer;
+
+ for (BucketMaterialSet::iterator it = m_materials.begin();it!=m_materials.end();it++)
+ {
+
+ RAS_MaterialBucket* materialbucket = (*it);
+
+ KX_ArrayOptimizer* oa = GetArrayOptimizer(materialbucket->GetPolyMaterial());
+ materialbucket->SetMeshSlot(ms);
+ }
+
+}
+
+
+
diff --git a/source/gameengine/Converter/BL_SkinMeshObject.h b/source/gameengine/Converter/BL_SkinMeshObject.h
new file mode 100644
index 00000000000..5ac95b48a35
--- /dev/null
+++ b/source/gameengine/Converter/BL_SkinMeshObject.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 __BL_SKINMESHOBJECT
+#define __BL_SKINMESHOBJECT
+
+#ifdef WIN32
+#pragma warning (disable:4786) // get rid of stupid stl-visual compiler debug warning
+#endif //WIN32
+
+#include "RAS_MeshObject.h"
+#include "RAS_Deformer.h"
+#include "RAS_IPolygonMaterial.h"
+
+#include "BL_MeshDeformer.h"
+
+#include "DNA_mesh_types.h"
+
+typedef vector<struct MVert*> BL_MVertArray;
+typedef vector<struct MDeformVert*> BL_DeformVertArray;
+typedef vector<class BL_TexVert> BL_VertexArray;
+
+
+typedef vector<vector<struct MDeformVert*>*> vecMDVertArray;
+typedef vector<vector<class BL_TexVert>*> vecBVertexArray;
+
+class BL_SkinArrayOptimizer : public KX_ArrayOptimizer
+{
+public:
+ BL_SkinArrayOptimizer(int index)
+ :KX_ArrayOptimizer (index) {};
+ virtual ~BL_SkinArrayOptimizer(){
+
+ for (vector<KX_IndexArray*>::iterator itv = m_MvertArrayCache1.begin();
+ !(itv == m_MvertArrayCache1.end());itv++)
+ {
+ delete (*itv);
+ }
+ for (vector<BL_DeformVertArray*>::iterator itd = m_DvertArrayCache1.begin();
+ !(itd == m_DvertArrayCache1.end());itd++)
+ {
+ delete (*itd);
+ }
+ for (vector<KX_IndexArray*>::iterator iti = m_DIndexArrayCache1.begin();
+ !(iti == m_DIndexArrayCache1.end());iti++)
+ {
+ delete (*iti);
+ }
+
+ m_MvertArrayCache1.clear();
+ m_DvertArrayCache1.clear();
+ m_DIndexArrayCache1.clear();
+ };
+
+ vector<KX_IndexArray*> m_MvertArrayCache1;
+ vector<BL_DeformVertArray*> m_DvertArrayCache1;
+ vector<KX_IndexArray*> m_DIndexArrayCache1;
+
+};
+
+class BL_SkinMeshObject : public RAS_MeshObject
+{
+
+ enum { BUCKET_MAX_INDICES = 2048};//2048};//8192};
+ enum { BUCKET_MAX_TRIANGLES = 1024};
+
+ KX_ArrayOptimizer* GetArrayOptimizer(RAS_IPolyMaterial* polymat)
+ {
+ KX_ArrayOptimizer** aop = (m_matVertexArrayS[*polymat]);
+ if (aop)
+ return *aop;
+ int numelements = m_matVertexArrayS.size();
+ m_sortedMaterials.push_back(polymat);
+
+ BL_SkinArrayOptimizer* ao = new BL_SkinArrayOptimizer(numelements);
+ m_matVertexArrayS.insert(*polymat,ao);
+ return ao;
+ }
+
+protected:
+public:
+ void Bucketize(double* oglmatrix,void* clientobj,bool useObjectColor,const MT_Vector4& rgbavec);
+// void Bucketize(double* oglmatrix,void* clientobj,bool useObjectColor,const MT_Vector4& rgbavec,class RAS_BucketManager* bucketmgr);
+
+ int FindVertexArray(int numverts,RAS_IPolyMaterial* polymat);
+ BL_SkinMeshObject(int lightlayer) : RAS_MeshObject (lightlayer)
+ {};
+
+ virtual ~BL_SkinMeshObject(){
+ };
+
+ const vecIndexArrays& GetDIndexCache (RAS_IPolyMaterial* mat)
+ {
+ BL_SkinArrayOptimizer* ao = (BL_SkinArrayOptimizer*)GetArrayOptimizer(mat);//*(m_matVertexArrays[*mat]);
+ return ao->m_DIndexArrayCache1;
+ }
+ const vecMDVertArray& GetDVertCache (RAS_IPolyMaterial* mat)
+ {
+ BL_SkinArrayOptimizer* ao = (BL_SkinArrayOptimizer*)GetArrayOptimizer(mat);//*(m_matVertexArrays[*mat]);
+ return ao->m_DvertArrayCache1;
+ }
+ const vecIndexArrays& GetMVertCache (RAS_IPolyMaterial* mat)
+ {
+ BL_SkinArrayOptimizer* ao = (BL_SkinArrayOptimizer*)GetArrayOptimizer(mat);//*(m_matVertexArrays[*mat]);
+ return ao->m_MvertArrayCache1;
+ }
+
+ void AddPolygon(RAS_Polygon* poly);
+ int FindOrAddDeform(int vtxarray, int mv, struct MDeformVert *dv, RAS_IPolyMaterial* mat);
+ int FindOrAddVertex(int vtxarray,const MT_Point3& xyz,
+ const MT_Point2& uv,
+ const unsigned int rgbacolor,
+ const MT_Vector3& normal, int defnr, bool flat, RAS_IPolyMaterial* mat)
+ {
+ short newnormal[3];
+ newnormal[0]=(short)(normal[0] * 32767.0);
+ newnormal[1]=(short)(normal[1] * 32767.0);
+ newnormal[2]=(short)(normal[2] * 32767.0);
+
+ RAS_TexVert tempvert(xyz,uv,rgbacolor,newnormal,flat ? TV_CALCFACENORMAL : 0);
+
+ // KX_ArrayOptimizer* ao = GetArrayOptimizer(mat);//*(m_matVertexArrays[*mat]);
+ BL_SkinArrayOptimizer* ao = (BL_SkinArrayOptimizer*)GetArrayOptimizer(mat);//*(m_matVertexArrays[*mat]);
+
+ int numverts = ao->m_VertexArrayCache1[vtxarray]->size();//m_VertexArrayCount[vtxarray];
+
+ int index=-1;
+
+ for (int i=0;i<numverts;i++)
+ {
+ const RAS_TexVert& vtx = (*ao->m_VertexArrayCache1[vtxarray])[i];
+ if (tempvert.closeTo(&vtx))
+ {
+ index = i;
+ break;
+ }
+
+ }
+ if (index >= 0)
+ return index;
+
+ // no vertex found, add one
+ ao->m_VertexArrayCache1[vtxarray]->push_back(tempvert);
+ ao->m_DIndexArrayCache1[vtxarray]->push_back(defnr);
+
+ return numverts;
+
+
+ }
+
+};
+
+
+#endif
+
diff --git a/source/gameengine/Converter/BlenderWorldInfo.cpp b/source/gameengine/Converter/BlenderWorldInfo.cpp
new file mode 100644
index 00000000000..5dd41a317aa
--- /dev/null
+++ b/source/gameengine/Converter/BlenderWorldInfo.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 *****
+ */
+
+#include <stdio.h> // printf()
+
+
+#include "BlenderWorldInfo.h"
+#include "KX_BlenderGL.h"
+
+/* This little block needed for linking to Blender... */
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+/* This list includes only data type definitions */
+#include "DNA_object_types.h"
+#include "DNA_material_types.h"
+#include "DNA_image_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_group_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_property_types.h"
+#include "DNA_text_types.h"
+#include "DNA_sensor_types.h"
+#include "DNA_controller_types.h"
+#include "DNA_actuator_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_world_types.h"
+#include "DNA_screen_types.h"
+
+#include "BKE_global.h"
+/* end of blender include block */
+
+
+BlenderWorldInfo::BlenderWorldInfo(struct World* blenderworld)
+{
+ if (blenderworld)
+ {
+ m_hasworld = true;
+
+ // do we have mist?
+ if ((blenderworld->mode) & WO_MIST)
+ {
+ m_hasmist = true;
+ m_miststart = blenderworld->miststa;
+ m_mistdistance = blenderworld->mistdist;
+ m_mistred = blenderworld->horr;
+ m_mistgreen = blenderworld->horg;
+ m_mistblue = blenderworld->horb;
+ }
+ else
+ {
+ m_hasmist = false;
+ m_miststart = 0.0;
+ m_mistdistance = 0.0;
+ m_mistred = 0.0;
+ m_mistgreen = 0.0;
+ m_mistblue = 0.0;
+ }
+
+ m_backgroundred = blenderworld->horr;
+ m_backgroundgreen = blenderworld->horg;
+ m_backgroundblue = blenderworld->horb;
+ }
+ else
+ {
+ m_hasworld = false;
+ }
+}
+
+
+
+BlenderWorldInfo::~BlenderWorldInfo()
+{
+
+}
+
+
+bool BlenderWorldInfo::hasWorld()
+{
+ return m_hasworld;
+}
+
+
+
+bool BlenderWorldInfo::hasMist()
+{
+ return m_hasmist;
+}
+
+
+
+float BlenderWorldInfo::getBackColorRed()
+{
+ return m_backgroundred;
+}
+
+
+
+float BlenderWorldInfo::getBackColorGreen()
+{
+ return m_backgroundgreen;
+}
+
+
+
+float BlenderWorldInfo::getBackColorBlue()
+{
+ return m_backgroundblue;
+}
+
+
+
+float BlenderWorldInfo::getMistStart()
+{
+ return m_miststart;
+}
+
+
+
+float BlenderWorldInfo::getMistDistance()
+{
+ return m_mistdistance;
+}
+
+
+
+float BlenderWorldInfo::getMistColorRed()
+{
+ return m_mistred;
+}
+
+
+
+float BlenderWorldInfo::getMistColorGreen()
+{
+ return m_mistgreen;
+}
+
+
+
+float BlenderWorldInfo::getMistColorBlue()
+{
+ return m_mistblue;
+}
+
+
+ void
+BlenderWorldInfo::setMistStart(
+ float d
+) {
+ m_miststart = d;
+}
+
+
+ void
+BlenderWorldInfo::setMistDistance(
+ float d
+) {
+ m_mistdistance = d;
+}
+
+
+ void
+BlenderWorldInfo::setMistColorRed(
+ float d
+) {
+ m_mistred = d;
+}
+
+
+ void
+BlenderWorldInfo::setMistColorGreen(
+ float d
+) {
+ m_mistgreen = d;
+}
+
+
+ void
+BlenderWorldInfo::setMistColorBlue(
+ float d
+) {
+ m_mistblue = d;
+}
diff --git a/source/gameengine/Converter/BlenderWorldInfo.h b/source/gameengine/Converter/BlenderWorldInfo.h
new file mode 100644
index 00000000000..1defd41bc72
--- /dev/null
+++ b/source/gameengine/Converter/BlenderWorldInfo.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 __BLENDERWORLDINFO_H
+#define __BLENDERWORLDINFO_H
+#include "MT_CmMatrix4x4.h"
+#include "KX_WorldInfo.h"
+#include "KX_BlenderGL.h"
+
+
+class BlenderWorldInfo : public KX_WorldInfo
+{
+ bool m_hasworld;
+ float m_backgroundred;
+ float m_backgroundgreen;
+ float m_backgroundblue;
+
+ bool m_hasmist;
+ float m_miststart;
+ float m_mistdistance;
+ float m_mistred;
+ float m_mistgreen;
+ float m_mistblue;
+
+public:
+ BlenderWorldInfo(struct World* blenderworld);
+ ~BlenderWorldInfo();
+
+ bool hasWorld();
+ bool hasMist();
+ float getBackColorRed();
+ float getBackColorGreen();
+ float getBackColorBlue();
+
+ float getMistStart();
+ float getMistDistance();
+ float getMistColorRed();
+ float getMistColorGreen();
+ float getMistColorBlue();
+
+ void
+ setMistStart(
+ float d
+ );
+
+ void
+ setMistDistance(
+ float d
+ );
+
+ void
+ setMistColorRed(
+ float d
+ );
+
+ void
+ setMistColorGreen(
+ float d
+ );
+
+ void
+ setMistColorBlue(
+ float d
+ );
+};
+
+#endif //__BLENDERWORLDINFO_H
diff --git a/source/gameengine/Converter/KX_BlenderScalarInterpolator.cpp b/source/gameengine/Converter/KX_BlenderScalarInterpolator.cpp
new file mode 100644
index 00000000000..c75a6e5b4e7
--- /dev/null
+++ b/source/gameengine/Converter/KX_BlenderScalarInterpolator.cpp
@@ -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 *****
+ */
+
+
+#include "KX_BlenderScalarInterpolator.h"
+
+extern "C" int IPO_GetChannels(struct Ipo *ipo, short *channels);
+extern "C" float IPO_GetFloatValue(struct Ipo *ipo, /*IPO_Channel*/ short channel, float ctime);
+
+
+static const int BL_MAX_CHANNELS = 32;
+
+float BL_ScalarInterpolator::GetValue(float currentTime) const {
+ return IPO_GetFloatValue(m_blender_ipo, m_channel, currentTime);
+}
+
+typedef short IPO_Channel;
+
+BL_InterpolatorList::BL_InterpolatorList(struct Ipo *ipo) {
+ IPO_Channel channels[BL_MAX_CHANNELS];
+
+ int num_channels = IPO_GetChannels(ipo, channels);
+
+ int i;
+
+ for (i = 0; i != num_channels; ++i) {
+ BL_ScalarInterpolator *new_ipo =
+ new BL_ScalarInterpolator(ipo, channels[i]);
+
+ //assert(new_ipo);
+ push_back(new_ipo);
+ }
+}
+
+BL_InterpolatorList::~BL_InterpolatorList() {
+ BL_InterpolatorList::iterator i;
+ for (i = begin(); !(i == end()); ++i) {
+ delete *i;
+ }
+}
+
+
+KX_IScalarInterpolator *BL_InterpolatorList::GetScalarInterpolator(BL_IpoChannel channel) {
+ BL_InterpolatorList::iterator i = begin();
+ while (!(i == end()) &&
+ (static_cast<BL_ScalarInterpolator *>(*i))->GetChannel() !=
+ channel) {
+ ++i;
+ }
+
+ return (i == end()) ? 0 : *i;
+}
+
diff --git a/source/gameengine/Converter/KX_BlenderScalarInterpolator.h b/source/gameengine/Converter/KX_BlenderScalarInterpolator.h
new file mode 100644
index 00000000000..6276b286ce4
--- /dev/null
+++ b/source/gameengine/Converter/KX_BlenderScalarInterpolator.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 *****
+ */
+#ifndef __KX_SCALARINTERPOLATOR_H
+#define __KX_SCALARINTERPOLATOR_H
+
+#include <vector>
+
+#include "KX_IScalarInterpolator.h"
+
+typedef unsigned short BL_IpoChannel;
+
+class BL_ScalarInterpolator : public KX_IScalarInterpolator {
+public:
+ BL_ScalarInterpolator() {} // required for use in STL list
+ BL_ScalarInterpolator(struct Ipo *ipo, BL_IpoChannel channel) :
+ m_blender_ipo(ipo),
+ m_channel(channel)
+ {}
+
+ virtual ~BL_ScalarInterpolator() {}
+
+ virtual float GetValue(float currentTime) const;
+
+ BL_IpoChannel GetChannel() const { return m_channel; }
+
+private:
+ struct Ipo *m_blender_ipo;
+ BL_IpoChannel m_channel;
+};
+
+
+class BL_InterpolatorList : public std::vector<KX_IScalarInterpolator *> {
+public:
+ BL_InterpolatorList(struct Ipo *ipo);
+ ~BL_InterpolatorList();
+
+ KX_IScalarInterpolator *GetScalarInterpolator(BL_IpoChannel channel);
+};
+
+
+#endif //__KX_SCALARINTERPOLATOR_H
diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp
new file mode 100644
index 00000000000..fdba851b7a3
--- /dev/null
+++ b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp
@@ -0,0 +1,416 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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) // suppress stl-MSVC debug info warning
+#endif
+
+
+#include "KX_Scene.h"
+#include "KX_GameObject.h"
+#include "KX_IpoConvert.h"
+#include "RAS_MeshObject.h"
+#include "KX_PhysicsEngineEnums.h"
+
+#include "DummyPhysicsEnvironment.h"
+
+#ifdef USE_ODE
+#include "OdePhysicsEnvironment.h"
+#endif //USE_ODE
+
+//to decide to use sumo/ode or dummy physics
+#include "KX_ConvertPhysicsObject.h"
+#ifdef USE_SUMO_SOLID
+#include "SumoPhysicsEnvironment.h"
+#endif
+
+#include "KX_BlenderSceneConverter.h"
+#include "KX_BlenderScalarInterpolator.h"
+#include "BL_BlenderDataConversion.h"
+#include "BlenderWorldInfo.h"
+#include "KX_Scene.h"
+
+/* This little block needed for linking to Blender... */
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+/* This list includes only data type definitions */
+#include "DNA_scene_types.h"
+#include "DNA_world_types.h"
+#include "BKE_main.h"
+
+
+KX_BlenderSceneConverter::KX_BlenderSceneConverter(
+ struct Main* maggie,
+ class KX_KetsjiEngine* engine
+ )
+ : m_maggie(maggie),
+ m_ketsjiEngine(engine),
+ m_alwaysUseExpandFraming(false)
+{
+ m_newfilename = "";
+}
+
+
+KX_BlenderSceneConverter::~KX_BlenderSceneConverter()
+{
+ // clears meshes, and hashmaps from blender to gameengine data
+ int i;
+ // delete sumoshapes
+
+
+ int numipolists = m_map_blender_to_gameipolist.size();
+ for (i=0; i<numipolists; i++) {
+ BL_InterpolatorList *ipoList= *m_map_blender_to_gameipolist.at(i);
+
+ delete (ipoList);
+ }
+
+ vector<KX_WorldInfo*>::iterator itw = m_worldinfos.begin();
+ while (itw != m_worldinfos.end()) {
+ delete (*itw);
+ itw++;
+ }
+
+ vector<RAS_IPolyMaterial*>::iterator itp = m_polymaterials.begin();
+ while (itp != m_polymaterials.end()) {
+ delete (*itp);
+ itp++;
+ }
+
+ vector<RAS_MeshObject*>::iterator itm = m_meshobjects.begin();
+ while (itm != m_meshobjects.end()) {
+ delete (*itm);
+ itm++;
+ }
+}
+
+
+
+void KX_BlenderSceneConverter::SetNewFileName(const STR_String& filename)
+{
+ m_newfilename = filename;
+}
+
+
+
+bool KX_BlenderSceneConverter::TryAndLoadNewFile()
+{
+ bool result = false;
+
+ // find the file
+/* if ()
+ {
+ result = true;
+ }
+ // if not, clear the newfilename
+ else
+ {
+ m_newfilename = "";
+ }
+*/
+ return result;
+}
+
+
+
+ /**
+ * Find the specified scene by name, or the first
+ * scene if nothing matches (shouldn't happen).
+ */
+static struct Scene *GetSceneForName2(struct Main *maggie, const STR_String& scenename) {
+ Scene *sce;
+
+ for (sce= (Scene*) maggie->scene.first; sce; sce= (Scene*) sce->id.next)
+ if (scenename == (sce->id.name+2))
+ return sce;
+
+ return (Scene*) maggie->scene.first;
+}
+
+
+void KX_BlenderSceneConverter::ConvertScene(const STR_String& scenename,
+ class KX_Scene* destinationscene,
+ PyObject* dictobj,
+ class SCA_IInputDevice* keyinputdev,
+ class RAS_IRenderTools* rendertools,
+ class RAS_ICanvas* canvas)
+{
+ //find out which physics engine
+ Scene *blenderscene = GetSceneForName2(m_maggie, scenename);
+
+ e_PhysicsEngine physics_engine = UseSumo;
+
+ if (blenderscene)
+ {
+ int i=0;
+
+ if (blenderscene->world)
+ {
+
+ switch (blenderscene->world->pad1)
+ {
+
+ case 4:
+ {
+ physics_engine = UseODE;
+ break;
+ }
+ case 5:
+ {
+ physics_engine = UseDynamo;
+ break;
+ }
+ case 7:
+ {
+ physics_engine = UseNone;
+ break;
+ };
+ default:
+ {
+ physics_engine = UseSumo;
+ }
+ }
+ }
+ }
+
+ switch (physics_engine)
+ {
+
+ case UseSumo:
+ {
+#ifdef USE_SUMO_SOLID
+
+ PHY_IPhysicsEnvironment* physEnv =
+ new SumoPhysicsEnvironment();
+#else
+ physics_engine = UseNone;
+
+ PHY_IPhysicsEnvironment* physEnv =
+ new DummyPhysicsEnvironment();
+
+#endif
+ destinationscene ->SetPhysicsEnvironment(physEnv);
+ break;
+ }
+ case UseODE:
+ {
+#ifdef USE_ODE
+
+ PHY_IPhysicsEnvironment* physEnv =
+ new ODEPhysicsEnvironment();
+#else
+ PHY_IPhysicsEnvironment* physEnv =
+ new DummyPhysicsEnvironment();
+
+#endif //USE_ODE
+
+ destinationscene ->SetPhysicsEnvironment(physEnv);
+ break;
+ }
+ case UseDynamo:
+ {
+ }
+
+ case UseNone:
+ {
+ };
+ default:
+ {
+ physics_engine = UseNone;
+
+ PHY_IPhysicsEnvironment* physEnv =
+ new DummyPhysicsEnvironment();
+ destinationscene ->SetPhysicsEnvironment(physEnv);
+
+ }
+ }
+
+ BL_ConvertBlenderObjects(m_maggie,
+ scenename,
+ destinationscene,
+ m_ketsjiEngine,
+ physics_engine,
+ dictobj,
+ keyinputdev,
+ rendertools,
+ canvas,
+ this,
+ m_alwaysUseExpandFraming
+ );
+
+ m_map_blender_to_gameactuator.clear();
+ m_map_blender_to_gamecontroller.clear();
+
+ m_map_blender_to_gameobject.clear();
+ m_map_mesh_to_gamemesh.clear();
+ m_map_gameobject_to_blender.clear();
+}
+
+
+
+void KX_BlenderSceneConverter::SetAlwaysUseExpandFraming(
+ bool to_what)
+{
+ m_alwaysUseExpandFraming= to_what;
+}
+
+
+
+void KX_BlenderSceneConverter::RegisterGameObject(
+ KX_GameObject *gameobject,
+ struct Object *for_blenderobject)
+{
+ m_map_gameobject_to_blender.insert(CHashedPtr(gameobject),for_blenderobject);
+ m_map_blender_to_gameobject.insert(CHashedPtr(for_blenderobject),gameobject);
+}
+
+
+
+KX_GameObject *KX_BlenderSceneConverter::FindGameObject(
+ struct Object *for_blenderobject)
+{
+ KX_GameObject **obp= m_map_blender_to_gameobject[CHashedPtr(for_blenderobject)];
+
+ return obp?*obp:NULL;
+}
+
+
+
+struct Object *KX_BlenderSceneConverter::FindBlenderObject(
+ KX_GameObject *for_gameobject)
+{
+ struct Object **obp= m_map_gameobject_to_blender[CHashedPtr(for_gameobject)];
+
+ return obp?*obp:NULL;
+}
+
+
+
+void KX_BlenderSceneConverter::RegisterGameMesh(
+ RAS_MeshObject *gamemesh,
+ struct Mesh *for_blendermesh)
+{
+ m_map_mesh_to_gamemesh.insert(CHashedPtr(for_blendermesh),gamemesh);
+ m_meshobjects.push_back(gamemesh);
+}
+
+
+
+RAS_MeshObject *KX_BlenderSceneConverter::FindGameMesh(
+ struct Mesh *for_blendermesh,
+ unsigned int onlayer)
+{
+ RAS_MeshObject** meshp = m_map_mesh_to_gamemesh[CHashedPtr(for_blendermesh)];
+
+ if (meshp && onlayer==(*meshp)->GetLightLayer()) {
+ return *meshp;
+ } else {
+ return NULL;
+ }
+}
+
+
+
+
+
+
+void KX_BlenderSceneConverter::RegisterPolyMaterial(RAS_IPolyMaterial *polymat)
+{
+ m_polymaterials.push_back(polymat);
+}
+
+
+
+void KX_BlenderSceneConverter::RegisterInterpolatorList(
+ BL_InterpolatorList *ipoList,
+ struct Ipo *for_ipo)
+{
+ m_map_blender_to_gameipolist.insert(CHashedPtr(for_ipo), ipoList);
+}
+
+
+
+BL_InterpolatorList *KX_BlenderSceneConverter::FindInterpolatorList(
+ struct Ipo *for_ipo)
+{
+ BL_InterpolatorList **listp = m_map_blender_to_gameipolist[CHashedPtr(for_ipo)];
+
+ return listp?*listp:NULL;
+}
+
+
+
+void KX_BlenderSceneConverter::RegisterGameActuator(
+ SCA_IActuator *act,
+ struct bActuator *for_actuator)
+{
+ m_map_blender_to_gameactuator.insert(CHashedPtr(for_actuator), act);
+}
+
+
+
+SCA_IActuator *KX_BlenderSceneConverter::FindGameActuator(
+ struct bActuator *for_actuator)
+{
+ SCA_IActuator **actp = m_map_blender_to_gameactuator[CHashedPtr(for_actuator)];
+
+ return actp?*actp:NULL;
+}
+
+
+
+void KX_BlenderSceneConverter::RegisterGameController(
+ SCA_IController *cont,
+ struct bController *for_controller)
+{
+ m_map_blender_to_gamecontroller.insert(CHashedPtr(for_controller), cont);
+}
+
+
+
+SCA_IController *KX_BlenderSceneConverter::FindGameController(
+ struct bController *for_controller)
+{
+ SCA_IController **contp = m_map_blender_to_gamecontroller[CHashedPtr(for_controller)];
+
+ return contp?*contp:NULL;
+}
+
+
+
+void KX_BlenderSceneConverter::RegisterWorldInfo(
+ KX_WorldInfo *worldinfo)
+{
+ m_worldinfos.push_back(worldinfo);
+}
diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.h b/source/gameengine/Converter/KX_BlenderSceneConverter.h
new file mode 100644
index 00000000000..446c238a274
--- /dev/null
+++ b/source/gameengine/Converter/KX_BlenderSceneConverter.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 *****
+ */
+#ifndef __KX_BLENDERSCENECONVERTER_H
+#define __KX_BLENDERSCENECONVERTER_H
+
+#include "GEN_Map.h"
+
+#include "KX_ISceneConverter.h"
+#include "KX_HashedPtr.h"
+#include "KX_IpoConvert.h"
+
+class KX_WorldInfo;
+class SCA_IActuator;
+class SCA_IController;
+class RAS_MeshObject;
+class RAS_IPolyMaterial;
+class BL_InterpolatorList;
+
+class KX_BlenderSceneConverter : public KX_ISceneConverter
+{
+ vector<KX_WorldInfo*> m_worldinfos;
+ vector<RAS_IPolyMaterial*> m_polymaterials;
+ vector<RAS_MeshObject*> m_meshobjects;
+
+ GEN_Map<CHashedPtr,struct Object*> m_map_gameobject_to_blender;
+ GEN_Map<CHashedPtr,KX_GameObject*> m_map_blender_to_gameobject;
+
+ GEN_Map<CHashedPtr,RAS_MeshObject*> m_map_mesh_to_gamemesh;
+// GEN_Map<CHashedPtr,DT_ShapeHandle> m_map_gamemesh_to_sumoshape;
+
+ GEN_Map<CHashedPtr,SCA_IActuator*> m_map_blender_to_gameactuator;
+ GEN_Map<CHashedPtr,SCA_IController*> m_map_blender_to_gamecontroller;
+
+ GEN_Map<CHashedPtr,BL_InterpolatorList*> m_map_blender_to_gameipolist;
+
+ struct Main* m_maggie;
+ STR_String m_newfilename;
+ class KX_KetsjiEngine* m_ketsjiEngine;
+ bool m_alwaysUseExpandFraming;
+
+public:
+ KX_BlenderSceneConverter(
+ struct Main* maggie,
+ class KX_KetsjiEngine* engine
+ );
+
+ virtual ~KX_BlenderSceneConverter();
+
+ /* Scenename: name of the scene to be converted.
+ * destinationscene: pass an empty scene, everything goes into this
+ * dictobj: python dictionary (for pythoncontrollers)
+ */
+ virtual void ConvertScene(
+ const STR_String& scenename,
+ class KX_Scene* destinationscene,
+ PyObject* dictobj,
+ class SCA_IInputDevice* keyinputdev,
+ class RAS_IRenderTools* rendertools,
+ class RAS_ICanvas* canvas
+ );
+
+ void SetNewFileName(const STR_String& filename);
+ bool TryAndLoadNewFile();
+
+ void SetAlwaysUseExpandFraming(bool to_what);
+
+ void RegisterGameObject(KX_GameObject *gameobject, struct Object *for_blenderobject);
+ KX_GameObject *FindGameObject(struct Object *for_blenderobject);
+ struct Object *FindBlenderObject(KX_GameObject *for_gameobject);
+
+ void RegisterGameMesh(RAS_MeshObject *gamemesh, struct Mesh *for_blendermesh);
+ RAS_MeshObject *FindGameMesh(struct Mesh *for_blendermesh, unsigned int onlayer);
+
+// void RegisterSumoShape(DT_ShapeHandle shape, RAS_MeshObject *for_gamemesh);
+// DT_ShapeHandle FindSumoShape(RAS_MeshObject *for_gamemesh);
+
+ void RegisterPolyMaterial(RAS_IPolyMaterial *polymat);
+
+ void RegisterInterpolatorList(BL_InterpolatorList *ipoList, struct Ipo *for_ipo);
+ BL_InterpolatorList *FindInterpolatorList(struct Ipo *for_ipo);
+
+ void RegisterGameActuator(SCA_IActuator *act, struct bActuator *for_actuator);
+ SCA_IActuator *FindGameActuator(struct bActuator *for_actuator);
+
+ void RegisterGameController(SCA_IController *cont, struct bController *for_controller);
+ SCA_IController *FindGameController(struct bController *for_controller);
+
+ void RegisterWorldInfo(KX_WorldInfo *worldinfo);
+};
+
+#endif //__KX_BLENDERSCENECONVERTER_H
diff --git a/source/gameengine/Converter/KX_ConvertActuators.cpp b/source/gameengine/Converter/KX_ConvertActuators.cpp
new file mode 100644
index 00000000000..2628441ba72
--- /dev/null
+++ b/source/gameengine/Converter/KX_ConvertActuators.cpp
@@ -0,0 +1,909 @@
+/**
+* $Id$
+*
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+* Convert Blender actuators for use in the GameEngine
+*/
+
+#ifdef WIN32
+#pragma warning (disable : 4786)
+#endif //WIN32
+
+#define BLENDER_HACK_DTIME 0.02
+
+#include "KX_BlenderSceneConverter.h"
+#include "KX_ConvertActuators.h"
+
+// Actuators
+//SCA logiclibrary native logicbricks
+#include "SCA_PropertyActuator.h"
+#include "SCA_LogicManager.h"
+#include "SCA_RandomActuator.h"
+
+
+// Ketsji specific logicbricks
+#include "KX_SceneActuator.h"
+#include "KX_IpoActuator.h"
+#include "KX_SoundActuator.h"
+#include "KX_CDActuator.h"
+#include "KX_ObjectActuator.h"
+#include "KX_TrackToActuator.h"
+#include "KX_ConstraintActuator.h"
+#include "KX_CameraActuator.h"
+#include "KX_GameActuator.h"
+#include "KX_VisibilityActuator.h"
+#include "KX_SCA_AddObjectActuator.h"
+#include "KX_SCA_EndObjectActuator.h"
+#include "KX_SCA_ReplaceMeshActuator.h"
+
+#include "KX_Scene.h"
+#include "KX_KetsjiEngine.h"
+
+#include "IntValue.h"
+#include "KX_GameObject.h"
+
+/* This little block needed for linking to Blender... */
+
+#include "BLI_blenlib.h"
+
+#include "KX_NetworkMessageActuator.h"
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+#include "DNA_object_types.h"
+#include "DNA_sound_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_actuator_types.h"
+#include "DNA_packedFile_types.h"
+#include "BL_ActionActuator.h"
+/* end of blender include block */
+
+#include "BL_BlenderDataConversion.h"
+
+/**
+KX_BLENDERTRUNC needed to round 'almost' zero values to zero, else velocities etc. are incorrectly set
+*/
+
+#define KX_BLENDERTRUNC(x) (( x < 0.0001 && x > -0.0001 ) ? 0.0 : x)
+
+void BL_ConvertActuators(char* maggiename,
+ struct Object* blenderobject,
+ KX_GameObject* gameobj,
+ SCA_LogicManager* logicmgr,
+ KX_Scene* scene,
+ KX_KetsjiEngine* ketsjiEngine,
+ int & executePriority,
+ int activeLayerBitInfo,
+ bool isInActiveLayer,
+ RAS_IRenderTools* rendertools,
+ KX_BlenderSceneConverter* converter
+ )
+{
+
+ int uniqueint = 0;
+ bActuator* bact = (bActuator*) blenderobject->actuators.first;
+ while(bact)
+ {
+ STR_String uniquename = bact->name;
+ STR_String objectname = gameobj->GetName();
+
+ SCA_IActuator* baseact = NULL;
+ switch (bact->type)
+ {
+ case ACT_OBJECT:
+ {
+ bObjectActuator* obact = (bObjectActuator*) bact->data;
+ MT_Vector3 forcevec(KX_BLENDERTRUNC(obact->forceloc[0]),
+ KX_BLENDERTRUNC(obact->forceloc[1]),
+ KX_BLENDERTRUNC(obact->forceloc[2]));
+ MT_Vector3 torquevec(obact->forcerot[0],obact->forcerot[1],obact->forcerot[2]);
+ MT_Vector3 dlocvec ( KX_BLENDERTRUNC(obact->dloc[0]),
+ KX_BLENDERTRUNC(obact->dloc[1]),
+ KX_BLENDERTRUNC(obact->dloc[2]));
+ MT_Vector3 drotvec ( KX_BLENDERTRUNC(obact->drot[0]),obact->drot[1],obact->drot[2]);
+ MT_Vector3 linvelvec ( KX_BLENDERTRUNC(obact->linearvelocity[0]),
+ KX_BLENDERTRUNC(obact->linearvelocity[1]),
+ KX_BLENDERTRUNC(obact->linearvelocity[2]));
+ MT_Vector3 angvelvec ( KX_BLENDERTRUNC(obact->angularvelocity[0]),
+ KX_BLENDERTRUNC(obact->angularvelocity[1]),
+ KX_BLENDERTRUNC(obact->angularvelocity[2]));
+
+ drotvec /= BLENDER_HACK_DTIME;
+ //drotvec /= BLENDER_HACK_DTIME;
+ drotvec *= MT_2_PI/360.0;
+ //dlocvec /= BLENDER_HACK_DTIME;
+ //linvelvec /= BLENDER_HACK_DTIME;
+ //angvelvec /= BLENDER_HACK_DTIME;
+
+ /* Blender uses a bit vector internally for the local-flags. In */
+ /* KX, we have four bools. The compiler should be smart enough */
+ /* to do the right thing. We need to explicitly convert here! */
+
+ KX_LocalFlags bitLocalFlag;
+
+ bitLocalFlag.Force = bool((obact->flag & ACT_FORCE_LOCAL)!=0);
+ bitLocalFlag.Torque = bool((obact->flag & ACT_TORQUE_LOCAL) !=0);//rlocal;
+ bitLocalFlag.DLoc = bool((obact->flag & ACT_DLOC_LOCAL)!=0);
+ bitLocalFlag.DRot = bool((obact->flag & ACT_DROT_LOCAL)!=0);
+ bitLocalFlag.LinearVelocity = bool((obact->flag & ACT_LIN_VEL_LOCAL)!=0);
+ bitLocalFlag.AngularVelocity = bool((obact->flag & ACT_ANG_VEL_LOCAL)!=0);
+
+ bitLocalFlag.AddOrSetLinV = bool((obact->flag & ACT_ADD_LIN_VEL)!=0);
+
+
+ KX_ObjectActuator* tmpbaseact = new KX_ObjectActuator(gameobj,
+ forcevec.getValue(),
+ torquevec.getValue(),
+ dlocvec.getValue(),
+ drotvec.getValue(),
+ linvelvec.getValue(),
+ angvelvec.getValue(),
+ bitLocalFlag
+ );
+ baseact = tmpbaseact;
+ break;
+ }
+ case ACT_ACTION:
+ {
+ if (blenderobject->type==OB_ARMATURE){
+ bActionActuator* actact = (bActionActuator*) bact->data;
+ STR_String propname = (actact->name ? actact->name : "");
+
+ BL_ActionActuator* tmpbaseact = new BL_ActionActuator(
+ gameobj,
+ propname,
+ actact->sta,
+ actact->end,
+ actact->act,
+ actact->type, // + 1, because Blender starts to count at zero,
+ actact->blendin,
+ actact->priority,
+ actact->stridelength
+ // Ketsji at 1, because zero is reserved for "NoDef"
+ );
+ baseact= tmpbaseact;
+ break;
+ }
+ else
+ printf ("Discarded action actuator from non-armature object [%s]\n", blenderobject->id.name+2);
+ }
+ case ACT_IPO:
+ {
+ bIpoActuator* ipoact = (bIpoActuator*) bact->data;
+ bool ipochild = (ipoact->flag & ACT_IPOCHILD) !=0;
+ STR_String propname = ( ipoact->name ? ipoact->name : "");
+ // first bit?
+ bool ipo_as_force = (ipoact->flag & ACT_IPOFORCE);
+ bool force_local = (ipoact->flag & ACT_IPOFORCE_LOCAL);
+
+ KX_IpoActuator* tmpbaseact = new KX_IpoActuator(
+ gameobj,
+ propname ,
+ ipoact->sta,
+ ipoact->end,
+ ipochild,
+ ipoact->type + 1, // + 1, because Blender starts to count at zero,
+ // Ketsji at 1, because zero is reserved for "NoDef"
+ ipo_as_force,
+ force_local
+ );
+ baseact = tmpbaseact;
+ break;
+ }
+ case ACT_LAMP:
+ {
+ break;
+ }
+ case ACT_CAMERA:
+ {
+ bCameraActuator *camact = (bCameraActuator *) bact->data;
+ if (camact->ob) {
+ KX_GameObject *tmpgob = converter->FindGameObject(camact->ob);
+
+ /* visifac, fac and axis are not copied from the struct... */
+ /* that's some internal state... */
+ KX_CameraActuator *tmpcamact
+ = new KX_CameraActuator(gameobj,
+ tmpgob,
+ camact->height,
+ camact->min,
+ camact->max,
+ camact->axis=='x');
+ baseact = tmpcamact;
+ }
+ break;
+ }
+ case ACT_MESSAGE:
+ {
+ bMessageActuator *msgAct = (bMessageActuator *) bact->data;
+
+ /**
+ * Get the name of the properties that objects must own that
+ * we're sending to, if present
+ */
+ STR_String toPropName = (msgAct->toPropName
+ ? (char*) msgAct->toPropName
+ : "");
+ /**
+ * Get the Message Subject to send.
+ */
+ STR_String subject = (msgAct->subject
+ ? (char*) msgAct->subject
+ : "");
+
+ /**
+ * Get the bodyType
+ */
+ int bodyType = msgAct->bodyType;
+
+ /**
+ * Get the body (text message or property name whose value
+ * we'll be sending, might be empty
+ */
+ STR_String body = (msgAct->body
+ ? (char*) msgAct->body
+ : "");
+
+ KX_NetworkMessageActuator *tmpmsgact =
+ new KX_NetworkMessageActuator(
+ gameobj, // actuator controlling object
+ scene->GetNetworkScene(), // needed for replication
+ toPropName,
+ subject,
+ bodyType,
+ body);
+ baseact = tmpmsgact;
+ break;
+ }
+ case ACT_MATERIAL:
+ {
+ break;
+ }
+ case ACT_SOUND:
+ {
+ bSoundActuator* soundact = (bSoundActuator*) bact->data;
+ /* get type, and possibly a start and end frame */
+ short startFrame = soundact->sta, stopFrame = soundact->end;
+ KX_SoundActuator::KX_SOUNDACT_TYPE
+ soundActuatorType = KX_SoundActuator::KX_SOUNDACT_NODEF;
+
+ switch(soundact->type) {
+ case ACT_SND_PLAY_STOP_SOUND:
+ soundActuatorType = KX_SoundActuator::KX_SOUNDACT_PLAYSTOP;
+ break;
+ case ACT_SND_PLAY_END_SOUND:
+ soundActuatorType = KX_SoundActuator::KX_SOUNDACT_PLAYEND;
+ break;
+ case ACT_SND_LOOP_STOP_SOUND:
+ soundActuatorType = KX_SoundActuator::KX_SOUNDACT_LOOPSTOP;
+ break;
+ case ACT_SND_LOOP_END_SOUND:
+ soundActuatorType = KX_SoundActuator::KX_SOUNDACT_LOOPEND;
+ break;
+ case ACT_SND_LOOP_BIDIRECTIONAL_SOUND:
+ soundActuatorType = KX_SoundActuator::KX_SOUNDACT_LOOPBIDIRECTIONAL;
+ break;
+ case ACT_SND_LOOP_BIDIRECTIONAL_STOP_SOUND:
+ soundActuatorType = KX_SoundActuator::KX_SOUNDACT_LOOPBIDIRECTIONAL_STOP;
+ break;
+
+ default:
+ /* This is an error!!! */
+ soundActuatorType = KX_SoundActuator::KX_SOUNDACT_NODEF;
+ }
+
+ if (soundActuatorType != KX_SoundActuator::KX_SOUNDACT_NODEF)
+ {
+ SND_SoundObject* sndobj = NULL;
+
+ if (soundact->sound)
+ {
+ SND_Scene* soundscene = scene->GetSoundScene();
+ STR_String samplename = soundact->sound->name;
+
+ bool sampleisloaded = false;
+
+ /* let's see if the sample was already loaded */
+ if (soundscene->IsSampleLoaded(samplename))
+ {
+ sampleisloaded = true;
+ }
+ else
+ {
+ /* if not, make it so */
+ PackedFile* pf = soundact->sound->newpackedfile;
+
+ /* but we need a packed file then */
+ if (pf)
+ {
+ if (soundscene->LoadSample(samplename, pf->data, pf->size) > -1)
+ sampleisloaded = true;
+ }
+ /* or else load it from disk */
+ else
+ {
+ /* but we need to convert the samplename into absolute pathname first */
+ BLI_convertstringcode(soundact->sound->name, maggiename, 0);
+ samplename = soundact->sound->name;
+
+ /* and now we can load it */
+ if (soundscene->LoadSample(samplename, NULL, 0) > -1)
+ sampleisloaded = true;
+ }
+ }
+
+ if (sampleisloaded)
+ {
+ sndobj = new SND_SoundObject();
+ sndobj->SetSampleName(samplename.Ptr());
+ sndobj->SetObjectName(bact->name);
+ sndobj->SetRollOffFactor(soundact->sound->attenuation);
+ sndobj->SetGain(soundact->sound->volume);
+ sndobj->SetPitch(exp((soundact->sound->pitch / 12.0) * log(2.0)));
+ // sndobj->SetLoopStart(soundact->sound->loopstart);
+ // sndobj->SetLoopStart(soundact->sound->loopend);
+ if (soundact->sound->flags & SOUND_FLAGS_LOOP)
+ {
+ if (soundact->sound->flags & SOUND_FLAGS_BIDIRECTIONAL_LOOP)
+ sndobj->SetLoopMode(SND_LOOP_BIDIRECTIONAL);
+ else
+ sndobj->SetLoopMode(SND_LOOP_NORMAL);
+ }
+ else
+ sndobj->SetLoopMode(SND_LOOP_OFF);
+
+ if (soundact->sound->flags & SOUND_FLAGS_PRIORITY)
+ sndobj->SetHighPriority(true);
+ else
+ sndobj->SetHighPriority(false);
+
+ if (soundact->sound->flags & SOUND_FLAGS_3D)
+ sndobj->Set3D(true);
+ else
+ sndobj->Set3D(false);
+
+ KX_SoundActuator* tmpsoundact =
+ new KX_SoundActuator(gameobj,
+ sndobj,
+ scene->GetSoundScene(), // needed for replication!
+ soundActuatorType,
+ startFrame,
+ stopFrame);
+
+ tmpsoundact->SetName(bact->name);
+ baseact = tmpsoundact;
+ soundscene->AddObject(sndobj);
+ }
+ }
+ }
+ break;
+ }
+ case ACT_CD:
+ {
+ bCDActuator* cdact = (bCDActuator*) bact->data;
+ /* get type, and possibly a start and end frame */
+ short startFrame = cdact->sta, stopFrame = cdact->end;
+ KX_CDActuator::KX_CDACT_TYPE
+ cdActuatorType = KX_CDActuator::KX_CDACT_NODEF;
+
+ switch(cdact->type)
+ {
+ case ACT_CD_PLAY_ALL:
+ cdActuatorType = KX_CDActuator::KX_CDACT_PLAY_ALL;
+ break;
+ case ACT_CD_PLAY_TRACK:
+ cdActuatorType = KX_CDActuator::KX_CDACT_PLAY_TRACK;
+ break;
+ case ACT_CD_LOOP_TRACK:
+ cdActuatorType = KX_CDActuator::KX_CDACT_LOOP_TRACK;
+ break;
+ case ACT_CD_VOLUME:
+ cdActuatorType = KX_CDActuator::KX_CDACT_VOLUME;
+ break;
+ case ACT_CD_STOP:
+ cdActuatorType = KX_CDActuator::KX_CDACT_STOP;
+ break;
+ case ACT_CD_PAUSE:
+ cdActuatorType = KX_CDActuator::KX_CDACT_PAUSE;
+ break;
+ case ACT_CD_RESUME:
+ cdActuatorType = KX_CDActuator::KX_CDACT_RESUME;
+ break;
+
+ default:
+ /* This is an error!!! */
+ cdActuatorType = KX_CDActuator::KX_CDACT_NODEF;
+ }
+
+ if (cdActuatorType != KX_CDActuator::KX_CDACT_NODEF)
+ {
+ SND_Scene* soundscene = scene->GetSoundScene();
+ SND_CDObject* pCD = SND_CDObject::Instance();
+
+ if (pCD)
+ {
+ pCD->SetGain(cdact->volume);
+
+ KX_CDActuator* tmpcdact =
+ new KX_CDActuator(gameobj,
+ scene->GetSoundScene(), // needed for replication!
+ cdActuatorType,
+ cdact->track,
+ startFrame,
+ stopFrame);
+
+ tmpcdact->SetName(bact->name);
+ baseact = tmpcdact;
+ }
+ }
+ break;
+ }
+ case ACT_PROPERTY:
+ {
+ bPropertyActuator* propact = (bPropertyActuator*) bact->data;
+ CValue* destinationObj = NULL;
+
+ /*
+ here the destinationobject is searched. problem with multiple scenes: other scenes
+ have not been converted yet, so the destobj will not be found, so the prop will
+ not be copied.
+ possible solutions:
+ - convert everything when possible and not realtime only when needed.
+ - let the object-with-property report itself to the act when converted
+ */
+ if (propact->ob)
+ {
+ KX_GameObject* tempObj = converter->FindGameObject(propact->ob);
+ if (tempObj)
+ {
+ destinationObj = tempObj;
+ }
+ }
+
+ SCA_PropertyActuator* tmppropact = new SCA_PropertyActuator(
+ gameobj,
+ destinationObj,
+ propact->name,
+ propact->value,
+ propact->type+1); // + 1 because Ketsji Logic starts
+ // with 0 for KX_ACT_PROP_NODEF
+ baseact = tmppropact;
+ break;
+ }
+ case ACT_EDIT_OBJECT:
+ {
+ bEditObjectActuator *editobact
+ = (bEditObjectActuator *) bact->data;
+ /* There are four different kinds of 'edit object' thingies */
+ /* The alternative to this lengthy conversion is packing */
+ /* several actuators in one, which is not very nice design.. */
+ switch (editobact->type) {
+ case ACT_EDOB_ADD_OBJECT:
+ {
+
+ // does the 'original' for replication exists, and
+ // is it in a non-active layer ?
+ if (editobact->ob && !(editobact->ob->lay & activeLayerBitInfo))
+ {
+ CValue* originalval = converter->FindGameObject(editobact->ob);
+
+ if (originalval)
+ {
+ MT_Vector3 linvelvec ( KX_BLENDERTRUNC(editobact->linVelocity[0]),
+ KX_BLENDERTRUNC(editobact->linVelocity[1]),
+ KX_BLENDERTRUNC(editobact->linVelocity[2]));
+ KX_SCA_AddObjectActuator* tmpaddact =
+ new KX_SCA_AddObjectActuator(
+
+ gameobj,
+ originalval,
+ editobact->time,
+ scene,
+ linvelvec.getValue(),
+ editobact->localflag!=0
+
+ );
+
+ //editobact->ob to gameobj
+ baseact = tmpaddact;
+ }
+ else
+ {
+ // let's pretend this never happened
+ exit(0);
+ }
+ } else
+ {
+ printf ("ERROR: GameObject %s has a AddObjectActuator %s without object (in 'nonactive' layer)\n",
+ objectname.ReadPtr(),
+ uniquename.ReadPtr() );
+ }
+ }
+ break;
+ case ACT_EDOB_END_OBJECT:
+ {
+ KX_SCA_EndObjectActuator* tmpendact
+ = new KX_SCA_EndObjectActuator(gameobj,scene);
+ baseact = tmpendact;
+ }
+ break;
+ case ACT_EDOB_REPLACE_MESH:
+ {
+ if (editobact->me)
+ {
+ RAS_MeshObject *tmpmesh = BL_ConvertMesh(
+ editobact->me,
+ blenderobject,
+ rendertools,
+ scene,
+ converter
+ );
+ KX_SCA_ReplaceMeshActuator* tmpreplaceact
+ = new KX_SCA_ReplaceMeshActuator(
+ gameobj,
+ tmpmesh,
+ scene
+ );
+
+ baseact = tmpreplaceact;
+ }
+ else
+ {
+ printf ("ERROR: GameObject %s ReplaceMeshActuator %s without object\n",
+ objectname.ReadPtr(),
+ uniquename.ReadPtr());
+ }
+ }
+ break;
+ case ACT_EDOB_TRACK_TO:
+ {
+ if (editobact->ob)
+ {
+ SCA_IObject* originalval = converter->FindGameObject(editobact->ob);
+
+ KX_TrackToActuator* tmptrackact
+ = new KX_TrackToActuator(gameobj,
+ originalval,
+ editobact->time,
+ editobact->flag,
+ blenderobject->trackflag,
+ blenderobject->upflag
+ );
+ baseact = tmptrackact;
+ }
+ else
+ {
+ printf("ERROR: GameObject %s no object in EditObjectActuator %s\n",
+ objectname.ReadPtr(),
+ uniquename.ReadPtr() );
+
+
+ }
+ }
+ }
+ break;
+ }
+ case ACT_CONSTRAINT:
+ {
+ float min = 0.0, max = 0.0;
+ int locrot;
+ bConstraintActuator *conact
+ = (bConstraintActuator*) bact->data;
+ /* convert settings... degrees in the ui become radians */
+ /* internally */
+ switch (conact->flag) {
+ case ACT_CONST_LOCX:
+ locrot = KX_ConstraintActuator::KX_ACT_CONSTRAINT_LOCX;
+ min = conact->minloc[0];
+ max = conact->maxloc[0];
+ break;
+ case ACT_CONST_LOCY:
+ locrot = KX_ConstraintActuator::KX_ACT_CONSTRAINT_LOCY;
+ min = conact->minloc[1];
+ max = conact->maxloc[1];
+ break;
+ case ACT_CONST_LOCZ:
+ locrot = KX_ConstraintActuator::KX_ACT_CONSTRAINT_LOCZ;
+ min = conact->minloc[2];
+ max = conact->maxloc[2];
+ break;
+ case ACT_CONST_ROTX:
+ locrot = KX_ConstraintActuator::KX_ACT_CONSTRAINT_ROTX;
+ min = MT_2_PI * conact->minrot[0] / 360.0;
+ max = MT_2_PI * conact->maxrot[0] / 360.0;
+ break;
+ case ACT_CONST_ROTY:
+ locrot = KX_ConstraintActuator::KX_ACT_CONSTRAINT_ROTY;
+ min = MT_2_PI * conact->minrot[1] / 360.0;
+ max = MT_2_PI * conact->maxrot[1] / 360.0;
+ break;
+ case ACT_CONST_ROTZ:
+ locrot = KX_ConstraintActuator::KX_ACT_CONSTRAINT_ROTZ;
+ min = MT_2_PI * conact->minrot[2] / 360.0;
+ max = MT_2_PI * conact->maxrot[2] / 360.0;
+ break;
+ default:
+ ; /* error */
+ }
+ KX_ConstraintActuator *tmpconact
+ = new KX_ConstraintActuator(gameobj,
+ conact->damp,
+ min,
+ max,
+ locrot);
+ baseact = tmpconact;
+ break;
+ }
+ case ACT_GROUP:
+ {
+ // deprecated
+ }
+ break;
+ case ACT_SCENE:
+ {
+ bSceneActuator *sceneact = (bSceneActuator *) bact->data;
+ bool scenevalid = true;
+ STR_String nextSceneName;
+
+ KX_SceneActuator* tmpsceneact;
+ int mode = KX_SceneActuator::KX_SCENE_NODEF;
+ KX_Camera *cam = NULL;
+ //KX_Scene* scene = NULL;
+ switch (sceneact->type)
+ {
+ case ACT_SCENE_RESUME:
+ case ACT_SCENE_SUSPEND:
+ case ACT_SCENE_ADD_FRONT:
+ case ACT_SCENE_ADD_BACK:
+ case ACT_SCENE_REMOVE:
+ case ACT_SCENE_SET:
+ {
+ switch (sceneact->type)
+ {
+ case ACT_SCENE_RESUME:
+ mode = KX_SceneActuator::KX_SCENE_RESUME;
+ break;
+ case ACT_SCENE_SUSPEND:
+ mode = KX_SceneActuator::KX_SCENE_SUSPEND;
+ break;
+ case ACT_SCENE_ADD_FRONT:
+ mode = KX_SceneActuator::KX_SCENE_ADD_FRONT_SCENE;
+ break;
+ case ACT_SCENE_ADD_BACK:
+ mode = KX_SceneActuator::KX_SCENE_ADD_BACK_SCENE;
+ break;
+ case ACT_SCENE_REMOVE:
+ mode = KX_SceneActuator::KX_SCENE_REMOVE_SCENE;
+ break;
+ case ACT_SCENE_SET:
+ default:
+ mode = KX_SceneActuator::KX_SCENE_SET_SCENE;
+ break;
+ };
+
+ if (sceneact->scene)
+ {
+ nextSceneName = sceneact->scene->id.name + 2; // this '2' is necessary to remove prefix 'SC'
+ }
+
+ if (!nextSceneName.Length())
+ {
+ printf ("ERROR: GameObject %s has a SceneActuator %s (SetScene) without scene\n",
+ objectname.ReadPtr(),
+ uniquename.ReadPtr());
+ scenevalid = false;
+
+ }
+ break;
+ }
+ case ACT_SCENE_CAMERA:
+ if (sceneact->camera)
+ {
+ mode = KX_SceneActuator::KX_SCENE_SET_CAMERA;
+ cam = (KX_Camera*) converter->FindGameObject(sceneact->camera);
+ }
+ else
+ {
+ // TODO:warn user
+ }
+ break;
+ case ACT_SCENE_RESTART:
+ {
+
+ mode = KX_SceneActuator::KX_SCENE_RESTART;
+ break;
+ }
+ default:
+ ; /* flag error */
+ }
+ if (scenevalid )
+ {
+ tmpsceneact = new KX_SceneActuator(gameobj,
+ mode,
+ scene,
+ ketsjiEngine,
+ nextSceneName,
+ cam);
+ baseact = tmpsceneact;
+ }
+ break;
+ }
+ case ACT_GAME:
+ {
+ bGameActuator *gameact = (bGameActuator *) bact->data;
+ KX_GameActuator* tmpgameact;
+ STR_String filename = maggiename;
+ STR_String loadinganimationname = "";
+ int mode = KX_GameActuator::KX_GAME_NODEF;
+ switch (gameact->type)
+ {
+ case ACT_GAME_LOAD:
+ {
+ mode = KX_GameActuator::KX_GAME_LOAD;
+ filename = gameact->filename;
+ loadinganimationname = gameact->loadaniname;
+ break;
+ }
+ case ACT_GAME_START:
+ {
+ mode = KX_GameActuator::KX_GAME_START;
+ filename = gameact->filename;
+ loadinganimationname = gameact->loadaniname;
+ break;
+ }
+ case ACT_GAME_RESTART:
+ {
+ mode = KX_GameActuator::KX_GAME_RESTART;
+ break;
+ }
+ case ACT_GAME_QUIT:
+ {
+ mode = KX_GameActuator::KX_GAME_QUIT;
+ break;
+ }
+ default:
+ ; /* flag error */
+ }
+ tmpgameact = new KX_GameActuator(gameobj,
+ mode,
+ filename,
+ loadinganimationname,
+ scene,
+ ketsjiEngine);
+ baseact = tmpgameact;
+
+ break;
+ }
+ case ACT_RANDOM:
+ {
+ bRandomActuator *randAct
+ = (bRandomActuator *) bact->data;
+
+ unsigned long seedArg = randAct->seed;
+ SCA_RandomActuator::KX_RANDOMACT_MODE modeArg
+ = SCA_RandomActuator::KX_RANDOMACT_NODEF;
+ SCA_RandomActuator *tmprandomact;
+ float paraArg1 = 0.0;
+ float paraArg2 = 0.0;
+
+ switch (randAct->distribution) {
+ case ACT_RANDOM_BOOL_CONST:
+ modeArg = SCA_RandomActuator::KX_RANDOMACT_BOOL_CONST;
+ paraArg1 = (float) randAct->int_arg_1;
+ break;
+ case ACT_RANDOM_BOOL_UNIFORM:
+ modeArg = SCA_RandomActuator::KX_RANDOMACT_BOOL_UNIFORM;
+ break;
+ case ACT_RANDOM_BOOL_BERNOUILLI:
+ paraArg1 = randAct->float_arg_1;
+ modeArg = SCA_RandomActuator::KX_RANDOMACT_BOOL_BERNOUILLI;
+ break;
+ case ACT_RANDOM_INT_CONST:
+ modeArg = SCA_RandomActuator::KX_RANDOMACT_INT_CONST;
+ paraArg1 = (float) randAct->int_arg_1;
+ break;
+ case ACT_RANDOM_INT_UNIFORM:
+ paraArg1 = (float) randAct->int_arg_1;
+ paraArg2 = (float) randAct->int_arg_2;
+ modeArg = SCA_RandomActuator::KX_RANDOMACT_INT_UNIFORM;
+ break;
+ case ACT_RANDOM_INT_POISSON:
+ paraArg1 = randAct->float_arg_1;
+ modeArg = SCA_RandomActuator::KX_RANDOMACT_INT_POISSON;
+ break;
+ case ACT_RANDOM_FLOAT_CONST:
+ paraArg1 = randAct->float_arg_1;
+ modeArg = SCA_RandomActuator::KX_RANDOMACT_FLOAT_CONST;
+ break;
+ case ACT_RANDOM_FLOAT_UNIFORM:
+ paraArg1 = randAct->float_arg_1;
+ paraArg2 = randAct->float_arg_2;
+ modeArg = SCA_RandomActuator::KX_RANDOMACT_FLOAT_UNIFORM;
+ break;
+ case ACT_RANDOM_FLOAT_NORMAL:
+ paraArg1 = randAct->float_arg_1;
+ paraArg2 = randAct->float_arg_2;
+ modeArg = SCA_RandomActuator::KX_RANDOMACT_FLOAT_NORMAL;
+ break;
+ case ACT_RANDOM_FLOAT_NEGATIVE_EXPONENTIAL:
+ paraArg1 = randAct->float_arg_1;
+ modeArg = SCA_RandomActuator::KX_RANDOMACT_FLOAT_NEGATIVE_EXPONENTIAL;
+ break;
+ default:
+ ; /* error */
+ }
+ tmprandomact = new SCA_RandomActuator(gameobj,
+ seedArg,
+ modeArg,
+ paraArg1,
+ paraArg2,
+ randAct->propname);
+ baseact = tmprandomact;
+ }
+ break;
+
+ case ACT_VISIBILITY:
+ {
+ bVisibilityActuator *vis_act = (bVisibilityActuator *) bact->data;
+ KX_VisibilityActuator * tmp_vis_act = NULL;
+ bool v = ((vis_act->flag & ACT_VISIBILITY_INVISIBLE) != 0);
+
+ tmp_vis_act =
+ new KX_VisibilityActuator(gameobj,
+ !v);
+
+ baseact = tmp_vis_act;
+ }
+ break;
+
+ default:
+ ; /* generate some error */
+ }
+
+ if (baseact)
+ {
+ baseact->SetExecutePriority(executePriority++);
+ uniquename += "#ACT#";
+ uniqueint++;
+ CIntValue* uniqueval = new CIntValue(uniqueint);
+ uniquename += uniqueval->GetText();
+ uniqueval->Release();
+ baseact->SetName(STR_String(bact->name));
+ //gameobj->SetProperty(uniquename,baseact);
+ gameobj->AddActuator(baseact);
+
+ converter->RegisterGameActuator(baseact, bact);
+ }
+
+ bact = bact->next;
+ }
+}
+
diff --git a/source/gameengine/Converter/KX_ConvertActuators.h b/source/gameengine/Converter/KX_ConvertActuators.h
new file mode 100644
index 00000000000..80aa64a19ef
--- /dev/null
+++ b/source/gameengine/Converter/KX_ConvertActuators.h
@@ -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 *****
+ */
+#ifndef __KX_CONVERTACTUATORS_H
+#define __KX_CONVERTACTUATORS_H
+
+void BL_ConvertActuators(char* maggiename,
+ struct Object* blenderobject,
+ class KX_GameObject* gameobj,
+ class SCA_LogicManager* logicmgr,
+ class KX_Scene* scene,
+ class KX_KetsjiEngine* ketsjiEngine,
+ int & executePriority,
+ int activeLayerBitInfo,
+ bool isInActiveLayer,
+ class RAS_IRenderTools* rendertools,
+ class KX_BlenderSceneConverter* converter);
+
+
+#endif //__KX_CONVERTACTUATORS_H
diff --git a/source/gameengine/Converter/KX_ConvertControllers.cpp b/source/gameengine/Converter/KX_ConvertControllers.cpp
new file mode 100644
index 00000000000..1a958744d70
--- /dev/null
+++ b/source/gameengine/Converter/KX_ConvertControllers.cpp
@@ -0,0 +1,179 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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_guardedalloc.h"
+
+
+#include "KX_BlenderSceneConverter.h"
+#include "KX_ConvertControllers.h"
+#include "KX_Python.h"
+
+// Controller
+#include "SCA_ANDController.h"
+#include "SCA_ORController.h"
+#include "SCA_PythonController.h"
+#include "SCA_ExpressionController.h"
+
+#include "SCA_LogicManager.h"
+#include "KX_GameObject.h"
+#include "IntValue.h"
+
+/* This little block needed for linking to Blender... */
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+#include "DNA_object_types.h"
+#include "DNA_controller_types.h"
+#include "DNA_text_types.h"
+
+#include "BKE_text.h"
+
+#include "BLI_blenlib.h"
+
+/* end of blender include block */
+
+
+ static void
+LinkControllerToActuators(
+ SCA_IController *game_controller,
+ bController* bcontr,
+ SCA_LogicManager* logicmgr,
+ KX_BlenderSceneConverter* converter
+) {
+ // Iterate through the actuators of the game blender
+ // controller and find the corresponding ketsji actuator.
+
+ for (int i=0;i<bcontr->totlinks;i++)
+ {
+ bActuator* bact = (bActuator*) bcontr->links[i];
+ SCA_IActuator *game_actuator = converter->FindGameActuator(bact);
+ if (game_actuator) {
+ logicmgr->RegisterToActuator(game_controller, game_actuator);
+ }
+ }
+}
+
+
+void BL_ConvertControllers(
+ struct Object* blenderobject,
+ class KX_GameObject* gameobj,
+ SCA_LogicManager* logicmgr,
+ PyObject* pythondictionary,
+ int &executePriority,
+ int activeLayerBitInfo,
+ bool isInActiveLayer,
+ KX_BlenderSceneConverter* converter
+) {
+ int uniqueint=0;
+ bController* bcontr = (bController*)blenderobject->controllers.first;
+ while (bcontr)
+ {
+ SCA_IController* gamecontroller = NULL;
+ switch(bcontr->type)
+ {
+ case CONT_LOGIC_AND:
+ {
+ gamecontroller = new SCA_ANDController(gameobj);
+ LinkControllerToActuators(gamecontroller,bcontr,logicmgr,converter);
+ break;
+ }
+ case CONT_LOGIC_OR:
+ {
+ gamecontroller = new SCA_ORController(gameobj);
+ LinkControllerToActuators(gamecontroller,bcontr,logicmgr,converter);
+ break;
+ }
+ case CONT_EXPRESSION:
+ {
+ bExpressionCont* bexpcont = (bExpressionCont*) bcontr->data;
+ STR_String expressiontext = STR_String(bexpcont->str);
+ if (expressiontext.Length() > 0)
+ {
+ gamecontroller = new SCA_ExpressionController(gameobj,expressiontext);
+ LinkControllerToActuators(gamecontroller,bcontr,logicmgr,converter);
+
+ }
+ break;
+ }
+ case CONT_PYTHON:
+ {
+
+ // we should create a Python controller here
+
+ SCA_PythonController* pyctrl = new SCA_PythonController(gameobj);
+ gamecontroller = pyctrl;
+
+ bPythonCont* pycont = (bPythonCont*) bcontr->data;
+ pyctrl->SetDictionary(pythondictionary);
+
+ if (pycont->text)
+ {
+ char *buf;
+ // this is some blender specific code
+ buf= txt_to_buf(pycont->text);
+ if (buf)
+ {
+ pyctrl->SetScriptText(STR_String(buf));
+ pyctrl->SetScriptName(pycont->text->id.name+2);
+ MEM_freeN(buf);
+ }
+
+ }
+
+ LinkControllerToActuators(gamecontroller,bcontr,logicmgr,converter);
+ break;
+ }
+ default:
+ {
+
+ }
+ }
+
+ if (gamecontroller)
+ {
+ gamecontroller->SetExecutePriority(executePriority++);
+ STR_String uniquename = bcontr->name;
+ uniquename += "#CONTR#";
+ uniqueint++;
+ CIntValue* uniqueval = new CIntValue(uniqueint);
+ uniquename += uniqueval->GetText();
+ uniqueval->Release();
+ gamecontroller->SetName(uniquename);
+ gameobj->AddController(gamecontroller);
+
+ converter->RegisterGameController(gamecontroller, bcontr);
+ }
+
+ bcontr = bcontr->next;
+ }
+
+}
diff --git a/source/gameengine/Converter/KX_ConvertControllers.h b/source/gameengine/Converter/KX_ConvertControllers.h
new file mode 100644
index 00000000000..637780a7dbd
--- /dev/null
+++ b/source/gameengine/Converter/KX_ConvertControllers.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 __KX_CONVERTCONTROLLERS_H
+#define __KX_CONVERTCONTROLLERS_H
+
+#include "KX_Python.h"
+
+void BL_ConvertControllers(
+ struct Object* blenderobject,
+ class KX_GameObject* gameobj,
+ class SCA_LogicManager* logicmgr,
+ PyObject* pythondictionary,
+ int & executePriority,
+ int activeLayerBitInfo,
+ bool isInActiveLayer,
+ class KX_BlenderSceneConverter* converter
+);
+
+
+
+
+#endif //__KX_CONVERTCONTROLLERS_H
diff --git a/source/gameengine/Converter/KX_ConvertProperties.cpp b/source/gameengine/Converter/KX_ConvertProperties.cpp
new file mode 100644
index 00000000000..e3cbadc5808
--- /dev/null
+++ b/source/gameengine/Converter/KX_ConvertProperties.cpp
@@ -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 *****
+ */
+
+#include "KX_ConvertProperties.h"
+
+
+/* This little block needed for linking to Blender... */
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+#include "DNA_object_types.h"
+#include "DNA_property_types.h"
+/* end of blender include block */
+
+#include "Value.h"
+#include "VectorValue.h"
+#include "BoolValue.h"
+#include "StringValue.h"
+#include "FloatValue.h"
+#include "KX_GameObject.h"
+//#include "ListValue.h"
+#include "IntValue.h"
+#include "SCA_TimeEventManager.h"
+#include "SCA_IScene.h"
+
+
+void BL_ConvertProperties(Object* object,KX_GameObject* gameobj,SCA_TimeEventManager* timemgr,SCA_IScene* scene, bool isInActiveLayer)
+{
+
+ bProperty* prop = (bProperty*)object->prop.first;
+ CValue* propval;
+ bool show_debug_info;
+ while(prop)
+ {
+
+ propval = NULL;
+ show_debug_info = bool (prop->flag & PROP_DEBUG);
+
+ switch(prop->type) {
+ case PROP_BOOL:
+ {
+ propval = new CBoolValue((bool)(prop->data != 0));
+ gameobj->SetProperty(prop->name,propval);
+ //promp->poin= &prop->data;
+ break;
+ }
+ case PROP_INT:
+ {
+ propval = new CIntValue((int)prop->data);
+ gameobj->SetProperty(prop->name,propval);
+ break;
+ }
+ case PROP_FLOAT:
+ {
+ //prop->poin= &prop->data;
+ float floatprop = *((float*)&prop->data);
+ propval = new CFloatValue(floatprop);
+ gameobj->SetProperty(prop->name,propval);
+ }
+ break;
+ case PROP_STRING:
+ {
+ //prop->poin= callocN(MAX_PROPSTRING, "property string");
+ propval = new CStringValue((char*)prop->poin,"");
+ gameobj->SetProperty(prop->name,propval);
+ break;
+ }
+ case PROP_TIME:
+ {
+ float floatprop = *((float*)&prop->data);
+
+ CValue* timeval = new CFloatValue(floatprop);
+ // set a subproperty called 'timer' so that
+ // we can register the replica of this property
+ // at the time a game object is replicated (AddObjectActuator triggers this)
+
+ timeval->SetProperty("timer",new CBoolValue(true));
+ if (isInActiveLayer)
+ {
+ timemgr->AddTimeProperty(timeval);
+ }
+
+ propval = timeval;
+ gameobj->SetProperty(prop->name,timeval);
+
+ }
+ default:
+ {
+ // todo make an assert etc.
+ }
+ }
+
+ if (propval)
+ {
+ if (show_debug_info)
+ {
+ scene->AddDebugProperty(gameobj,STR_String(prop->name));
+ }
+ }
+
+ prop = prop->next;
+ }
+
+
+}
diff --git a/source/gameengine/Converter/KX_ConvertProperties.h b/source/gameengine/Converter/KX_ConvertProperties.h
new file mode 100644
index 00000000000..7360baa2e47
--- /dev/null
+++ b/source/gameengine/Converter/KX_ConvertProperties.h
@@ -0,0 +1,41 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 __KX_CONVERTPROPERTIES
+#define __KX_CONVERTPROPERTIES
+
+void BL_ConvertProperties(struct Object* object,
+ class KX_GameObject* gameobj,
+ class SCA_TimeEventManager* timemgr,
+ class SCA_IScene* scene,
+ bool isInActiveLayer);
+
+#endif //__KX_CONVERTPROPERTIES
diff --git a/source/gameengine/Converter/KX_ConvertSensors.cpp b/source/gameengine/Converter/KX_ConvertSensors.cpp
new file mode 100644
index 00000000000..42be5354d20
--- /dev/null
+++ b/source/gameengine/Converter/KX_ConvertSensors.cpp
@@ -0,0 +1,658 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * Conversion of Blender data blocks to KX sensor system
+ */
+
+#ifdef WIN32
+#pragma warning (disable : 4786)
+#endif //WIN32
+
+#include "KX_BlenderSceneConverter.h"
+#include "KX_ConvertSensors.h"
+
+/* This little block needed for linking to Blender... */
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+#include "DNA_object_types.h"
+#include "DNA_material_types.h"
+#include "DNA_sensor_types.h"
+#include "DNA_actuator_types.h" /* for SENS_ALL_KEYS ? this define is
+probably misplaced */
+/* end of blender include block */
+
+#include "RAS_IPolygonMaterial.h"
+// Sensors
+#include "KX_GameObject.h"
+#include "RAS_MeshObject.h"
+#include "SCA_KeyboardSensor.h"
+#include "SCA_MouseSensor.h"
+#include "SCA_AlwaysSensor.h"
+#include "KX_TouchSensor.h"
+#include "KX_NearSensor.h"
+#include "KX_RadarSensor.h"
+#include "KX_MouseFocusSensor.h"
+
+#include "KX_NetworkMessageSensor.h"
+
+#include "SCA_PropertySensor.h"
+#include "SCA_RandomSensor.h"
+#include "KX_RaySensor.h"
+#include "SCA_EventManager.h"
+#include "SCA_LogicManager.h"
+#include "KX_BlenderInputDevice.h"
+#include "KX_Scene.h"
+#include "IntValue.h"
+#include "KX_BlenderKeyboardDevice.h"
+#include "KX_BlenderGL.h"
+#include "RAS_ICanvas.h"
+
+#include "KX_KetsjiEngine.h"
+#include "KX_BlenderSceneConverter.h"
+
+// this map is Blender specific: a conversion between blender and ketsji enums
+std::map<int,SCA_IInputDevice::KX_EnumInputs> gReverseKeyTranslateTable;
+
+
+void BL_ConvertSensors(struct Object* blenderobject,
+ class KX_GameObject* gameobj,
+ SCA_LogicManager* logicmgr,
+ KX_Scene* kxscene,
+ SCA_IInputDevice* keydev,
+ int & executePriority,
+ int activeLayerBitInfo,
+ bool isInActiveLayer,
+ RAS_ICanvas* canvas,
+ KX_BlenderSceneConverter* converter
+ )
+{
+
+
+
+ /* The reverse table. In order to not confuse ourselves, we */
+ /* immediately convert all events that come in to KX codes. */
+ gReverseKeyTranslateTable[LEFTMOUSE ] = SCA_IInputDevice::KX_LEFTMOUSE;
+ gReverseKeyTranslateTable[MIDDLEMOUSE ] = SCA_IInputDevice::KX_MIDDLEMOUSE;
+ gReverseKeyTranslateTable[RIGHTMOUSE ] = SCA_IInputDevice::KX_RIGHTMOUSE;
+ gReverseKeyTranslateTable[MOUSEX ] = SCA_IInputDevice::KX_MOUSEX;
+ gReverseKeyTranslateTable[MOUSEY ] = SCA_IInputDevice::KX_MOUSEY;
+
+ // TIMERS
+
+ gReverseKeyTranslateTable[TIMER0 ] = SCA_IInputDevice::KX_TIMER0;
+ gReverseKeyTranslateTable[TIMER1 ] = SCA_IInputDevice::KX_TIMER1;
+ gReverseKeyTranslateTable[TIMER2 ] = SCA_IInputDevice::KX_TIMER2;
+ gReverseKeyTranslateTable[TIMER3 ] = SCA_IInputDevice::KX_TIMER3;
+
+ // SYSTEM
+
+ gReverseKeyTranslateTable[KEYBD ] = SCA_IInputDevice::KX_KEYBD;
+ gReverseKeyTranslateTable[RAWKEYBD ] = SCA_IInputDevice::KX_RAWKEYBD;
+ gReverseKeyTranslateTable[REDRAW ] = SCA_IInputDevice::KX_REDRAW;
+ gReverseKeyTranslateTable[INPUTCHANGE ] = SCA_IInputDevice::KX_INPUTCHANGE;
+ gReverseKeyTranslateTable[QFULL ] = SCA_IInputDevice::KX_QFULL;
+ gReverseKeyTranslateTable[WINFREEZE ] = SCA_IInputDevice::KX_WINFREEZE;
+ gReverseKeyTranslateTable[WINTHAW ] = SCA_IInputDevice::KX_WINTHAW;
+ gReverseKeyTranslateTable[WINCLOSE ] = SCA_IInputDevice::KX_WINCLOSE;
+ gReverseKeyTranslateTable[WINQUIT ] = SCA_IInputDevice::KX_WINQUIT;
+ gReverseKeyTranslateTable[Q_FIRSTTIME ] = SCA_IInputDevice::KX_Q_FIRSTTIME;
+
+ // standard keyboard
+
+ gReverseKeyTranslateTable[AKEY ] = SCA_IInputDevice::KX_AKEY;
+ gReverseKeyTranslateTable[BKEY ] = SCA_IInputDevice::KX_BKEY;
+ gReverseKeyTranslateTable[CKEY ] = SCA_IInputDevice::KX_CKEY;
+ gReverseKeyTranslateTable[DKEY ] = SCA_IInputDevice::KX_DKEY;
+ gReverseKeyTranslateTable[EKEY ] = SCA_IInputDevice::KX_EKEY;
+ gReverseKeyTranslateTable[FKEY ] = SCA_IInputDevice::KX_FKEY;
+ gReverseKeyTranslateTable[GKEY ] = SCA_IInputDevice::KX_GKEY;
+ gReverseKeyTranslateTable[HKEY ] = SCA_IInputDevice::KX_HKEY;
+ gReverseKeyTranslateTable[IKEY ] = SCA_IInputDevice::KX_IKEY;
+ gReverseKeyTranslateTable[JKEY ] = SCA_IInputDevice::KX_JKEY;
+ gReverseKeyTranslateTable[KKEY ] = SCA_IInputDevice::KX_KKEY;
+ gReverseKeyTranslateTable[LKEY ] = SCA_IInputDevice::KX_LKEY;
+ gReverseKeyTranslateTable[MKEY ] = SCA_IInputDevice::KX_MKEY;
+ gReverseKeyTranslateTable[NKEY ] = SCA_IInputDevice::KX_NKEY;
+ gReverseKeyTranslateTable[OKEY ] = SCA_IInputDevice::KX_OKEY;
+ gReverseKeyTranslateTable[PKEY ] = SCA_IInputDevice::KX_PKEY;
+ gReverseKeyTranslateTable[QKEY ] = SCA_IInputDevice::KX_QKEY;
+ gReverseKeyTranslateTable[RKEY ] = SCA_IInputDevice::KX_RKEY;
+ gReverseKeyTranslateTable[SKEY ] = SCA_IInputDevice::KX_SKEY;
+ gReverseKeyTranslateTable[TKEY ] = SCA_IInputDevice::KX_TKEY;
+ gReverseKeyTranslateTable[UKEY ] = SCA_IInputDevice::KX_UKEY;
+ gReverseKeyTranslateTable[VKEY ] = SCA_IInputDevice::KX_VKEY;
+ gReverseKeyTranslateTable[WKEY ] = SCA_IInputDevice::KX_WKEY;
+ gReverseKeyTranslateTable[XKEY ] = SCA_IInputDevice::KX_XKEY;
+ gReverseKeyTranslateTable[YKEY ] = SCA_IInputDevice::KX_YKEY;
+ gReverseKeyTranslateTable[ZKEY ] = SCA_IInputDevice::KX_ZKEY;
+
+ gReverseKeyTranslateTable[ZEROKEY ] = SCA_IInputDevice::KX_ZEROKEY;
+ gReverseKeyTranslateTable[ONEKEY ] = SCA_IInputDevice::KX_ONEKEY;
+ gReverseKeyTranslateTable[TWOKEY ] = SCA_IInputDevice::KX_TWOKEY;
+ gReverseKeyTranslateTable[THREEKEY ] = SCA_IInputDevice::KX_THREEKEY;
+ gReverseKeyTranslateTable[FOURKEY ] = SCA_IInputDevice::KX_FOURKEY;
+ gReverseKeyTranslateTable[FIVEKEY ] = SCA_IInputDevice::KX_FIVEKEY;
+ gReverseKeyTranslateTable[SIXKEY ] = SCA_IInputDevice::KX_SIXKEY;
+ gReverseKeyTranslateTable[SEVENKEY ] = SCA_IInputDevice::KX_SEVENKEY;
+ gReverseKeyTranslateTable[EIGHTKEY ] = SCA_IInputDevice::KX_EIGHTKEY;
+ gReverseKeyTranslateTable[NINEKEY ] = SCA_IInputDevice::KX_NINEKEY;
+
+ gReverseKeyTranslateTable[CAPSLOCKKEY ] = SCA_IInputDevice::KX_CAPSLOCKKEY;
+
+ gReverseKeyTranslateTable[LEFTCTRLKEY ] = SCA_IInputDevice::KX_LEFTCTRLKEY;
+ gReverseKeyTranslateTable[LEFTALTKEY ] = SCA_IInputDevice::KX_LEFTALTKEY;
+ gReverseKeyTranslateTable[RIGHTALTKEY ] = SCA_IInputDevice::KX_RIGHTALTKEY;
+ gReverseKeyTranslateTable[RIGHTCTRLKEY ] = SCA_IInputDevice::KX_RIGHTCTRLKEY;
+ gReverseKeyTranslateTable[RIGHTSHIFTKEY ] = SCA_IInputDevice::KX_RIGHTSHIFTKEY;
+ gReverseKeyTranslateTable[LEFTSHIFTKEY ] = SCA_IInputDevice::KX_LEFTSHIFTKEY;
+
+ gReverseKeyTranslateTable[ESCKEY ] = SCA_IInputDevice::KX_ESCKEY;
+ gReverseKeyTranslateTable[TABKEY ] = SCA_IInputDevice::KX_TABKEY;
+ gReverseKeyTranslateTable[RETKEY ] = SCA_IInputDevice::KX_RETKEY;
+ gReverseKeyTranslateTable[SPACEKEY ] = SCA_IInputDevice::KX_SPACEKEY;
+ gReverseKeyTranslateTable[LINEFEEDKEY ] = SCA_IInputDevice::KX_LINEFEEDKEY;
+ gReverseKeyTranslateTable[BACKSPACEKEY ] = SCA_IInputDevice::KX_BACKSPACEKEY;
+ gReverseKeyTranslateTable[DELKEY ] = SCA_IInputDevice::KX_DELKEY;
+ gReverseKeyTranslateTable[SEMICOLONKEY ] = SCA_IInputDevice::KX_SEMICOLONKEY;
+ gReverseKeyTranslateTable[PERIODKEY ] = SCA_IInputDevice::KX_PERIODKEY;
+ gReverseKeyTranslateTable[COMMAKEY ] = SCA_IInputDevice::KX_COMMAKEY;
+ gReverseKeyTranslateTable[QUOTEKEY ] = SCA_IInputDevice::KX_QUOTEKEY;
+ gReverseKeyTranslateTable[ACCENTGRAVEKEY ] = SCA_IInputDevice::KX_ACCENTGRAVEKEY;
+ gReverseKeyTranslateTable[MINUSKEY ] = SCA_IInputDevice::KX_MINUSKEY;
+ gReverseKeyTranslateTable[SLASHKEY ] = SCA_IInputDevice::KX_SLASHKEY;
+ gReverseKeyTranslateTable[BACKSLASHKEY ] = SCA_IInputDevice::KX_BACKSLASHKEY;
+ gReverseKeyTranslateTable[EQUALKEY ] = SCA_IInputDevice::KX_EQUALKEY;
+ gReverseKeyTranslateTable[LEFTBRACKETKEY ] = SCA_IInputDevice::KX_LEFTBRACKETKEY;
+ gReverseKeyTranslateTable[RIGHTBRACKETKEY ] = SCA_IInputDevice::KX_RIGHTBRACKETKEY;
+
+ gReverseKeyTranslateTable[LEFTARROWKEY ] = SCA_IInputDevice::KX_LEFTARROWKEY;
+ gReverseKeyTranslateTable[DOWNARROWKEY ] = SCA_IInputDevice::KX_DOWNARROWKEY;
+ gReverseKeyTranslateTable[RIGHTARROWKEY ] = SCA_IInputDevice::KX_RIGHTARROWKEY;
+ gReverseKeyTranslateTable[UPARROWKEY ] = SCA_IInputDevice::KX_UPARROWKEY;
+
+ gReverseKeyTranslateTable[PAD2 ] = SCA_IInputDevice::KX_PAD2;
+ gReverseKeyTranslateTable[PAD4 ] = SCA_IInputDevice::KX_PAD4;
+ gReverseKeyTranslateTable[PAD6 ] = SCA_IInputDevice::KX_PAD6;
+ gReverseKeyTranslateTable[PAD8 ] = SCA_IInputDevice::KX_PAD8;
+
+ gReverseKeyTranslateTable[PAD1 ] = SCA_IInputDevice::KX_PAD1;
+ gReverseKeyTranslateTable[PAD3 ] = SCA_IInputDevice::KX_PAD3;
+ gReverseKeyTranslateTable[PAD5 ] = SCA_IInputDevice::KX_PAD5;
+ gReverseKeyTranslateTable[PAD7 ] = SCA_IInputDevice::KX_PAD7;
+ gReverseKeyTranslateTable[PAD9 ] = SCA_IInputDevice::KX_PAD9;
+
+ gReverseKeyTranslateTable[PADPERIOD ] = SCA_IInputDevice::KX_PADPERIOD;
+ gReverseKeyTranslateTable[PADSLASHKEY ] = SCA_IInputDevice::KX_PADSLASHKEY;
+ gReverseKeyTranslateTable[PADASTERKEY ] = SCA_IInputDevice::KX_PADASTERKEY;
+
+ gReverseKeyTranslateTable[PAD0 ] = SCA_IInputDevice::KX_PAD0;
+ gReverseKeyTranslateTable[PADMINUS ] = SCA_IInputDevice::KX_PADMINUS;
+ gReverseKeyTranslateTable[PADENTER ] = SCA_IInputDevice::KX_PADENTER;
+ gReverseKeyTranslateTable[PADPLUSKEY ] = SCA_IInputDevice::KX_PADPLUSKEY;
+
+
+ gReverseKeyTranslateTable[F1KEY ] = SCA_IInputDevice::KX_F1KEY;
+ gReverseKeyTranslateTable[F2KEY ] = SCA_IInputDevice::KX_F2KEY;
+ gReverseKeyTranslateTable[F3KEY ] = SCA_IInputDevice::KX_F3KEY;
+ gReverseKeyTranslateTable[F4KEY ] = SCA_IInputDevice::KX_F4KEY;
+ gReverseKeyTranslateTable[F5KEY ] = SCA_IInputDevice::KX_F5KEY;
+ gReverseKeyTranslateTable[F6KEY ] = SCA_IInputDevice::KX_F6KEY;
+ gReverseKeyTranslateTable[F7KEY ] = SCA_IInputDevice::KX_F7KEY;
+ gReverseKeyTranslateTable[F8KEY ] = SCA_IInputDevice::KX_F8KEY;
+ gReverseKeyTranslateTable[F9KEY ] = SCA_IInputDevice::KX_F9KEY;
+ gReverseKeyTranslateTable[F10KEY ] = SCA_IInputDevice::KX_F10KEY;
+ gReverseKeyTranslateTable[F11KEY ] = SCA_IInputDevice::KX_F11KEY;
+ gReverseKeyTranslateTable[F12KEY ] = SCA_IInputDevice::KX_F12KEY;
+
+ gReverseKeyTranslateTable[PAUSEKEY ] = SCA_IInputDevice::KX_PAUSEKEY;
+ gReverseKeyTranslateTable[INSERTKEY ] = SCA_IInputDevice::KX_INSERTKEY;
+ gReverseKeyTranslateTable[HOMEKEY ] = SCA_IInputDevice::KX_HOMEKEY;
+ gReverseKeyTranslateTable[PAGEUPKEY ] = SCA_IInputDevice::KX_PAGEUPKEY;
+ gReverseKeyTranslateTable[PAGEDOWNKEY ] = SCA_IInputDevice::KX_PAGEDOWNKEY;
+ gReverseKeyTranslateTable[ENDKEY ] = SCA_IInputDevice::KX_ENDKEY;
+
+ int uniqueint = 0;
+ bSensor* sens = (bSensor*)blenderobject->sensors.first;
+ bool pos_pulsemode = false;
+ bool neg_pulsemode = false;
+ int frequency = 0;
+ bool invert = false;
+
+ while(sens)
+ {
+ SCA_ISensor* gamesensor=NULL;
+ /* All sensors have a pulse toggle, frequency, and invert field. */
+ /* These are extracted here, and set when the sensor is added to the */
+ /* list. */
+ pos_pulsemode = (sens->pulse & SENS_PULSE_REPEAT)!=0;
+ neg_pulsemode = (sens->pulse & SENS_NEG_PULSE_MODE)!=0;
+
+ frequency = sens->freq;
+ invert = !(sens->invert == 0);
+
+ switch (sens->type)
+ {
+ case SENS_ALWAYS:
+ {
+
+ SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::ALWAYS_EVENTMGR);
+ if (eventmgr)
+ {
+ gamesensor = new SCA_AlwaysSensor(eventmgr, gameobj);
+ }
+
+ break;
+ }
+
+ case SENS_COLLISION:
+ {
+ SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::TOUCH_EVENTMGR);
+ if (eventmgr)
+ {
+ // collision sensor can sense both materials and properties.
+
+ bool bFindMaterial = false;
+
+ bCollisionSensor* blendertouchsensor = (bCollisionSensor*)sens->data;
+
+ bFindMaterial = (blendertouchsensor->mode
+ & SENS_COLLISION_MATERIAL);
+
+
+ STR_String touchPropOrMatName = ( bFindMaterial ?
+ blendertouchsensor->materialName:
+ (blendertouchsensor->name ? blendertouchsensor->name: ""));
+
+
+ //if (gameobj->GetSumoObject())
+ //{
+ // gamesensor = 0;
+ //new KX_TouchSensor(eventmgr,
+ //gameobj,
+ //gameobj->GetSumoObject(),
+ //bFindMaterial,
+ //touchPropOrMatName);
+ //}
+
+ }
+
+ break;
+ }
+ case SENS_TOUCH:
+ {
+ SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::TOUCH_EVENTMGR);
+ if (eventmgr)
+ {
+ STR_String touchpropertyname;
+ bTouchSensor* blendertouchsensor = (bTouchSensor*)sens->data;
+
+ if (blendertouchsensor->ma)
+ {
+ touchpropertyname = (char*) (blendertouchsensor->ma->id.name+2);
+ }
+ bool bFindMaterial = true;
+ //if (gameobj->GetSumoObject())
+ //{
+ // gamesensor = 0;
+ //new KX_TouchSensor(eventmgr,
+ // gameobj,
+ // gameobj->GetSumoObject(),
+ // bFindMaterial,
+ // touchpropertyname);
+ //}
+ }
+ break;
+ }
+ case SENS_MESSAGE:
+ {
+ KX_NetworkEventManager* eventmgr = (KX_NetworkEventManager*)
+ logicmgr->FindEventManager(SCA_EventManager::NETWORK_EVENTMGR);
+ if (eventmgr) {
+ bMessageSensor* msgSens = (bMessageSensor*) sens->data;
+
+ /* Get our NetworkScene */
+ NG_NetworkScene *NetworkScene = kxscene->GetNetworkScene();
+ /* filter on the incoming subjects, might be empty */
+ STR_String subject = (msgSens->subject
+ ? (char*)msgSens->subject
+ : "");
+
+ gamesensor = new KX_NetworkMessageSensor(
+ eventmgr, // our eventmanager
+ NetworkScene, // our NetworkScene
+ gameobj, // the sensor controlling object
+ subject); // subject to filter on
+ }
+ break;
+ }
+ case SENS_NEAR:
+ {
+
+ SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::TOUCH_EVENTMGR);
+ if (eventmgr)
+ {
+ STR_String nearpropertyname;
+ bNearSensor* blendernearsensor = (bNearSensor*)sens->data;
+ if (blendernearsensor->name)
+ {
+ // only objects that own this property will be taken into account
+ nearpropertyname = (char*) blendernearsensor->name;
+ }
+
+ //DT_ShapeHandle shape = DT_Sphere(0.0);
+
+ // this sumoObject is not deleted by a gameobj, so delete it ourself
+ // later (memleaks)!
+ //SM_Object* sumoObj = new SM_Object(shape,NULL,NULL,NULL);
+ //sumoObj->setMargin(blendernearsensor->dist);
+ //sumoObj->setPosition(gameobj->NodeGetWorldPosition());
+ bool bFindMaterial = false;
+ gamesensor = 0;//new KX_NearSensor(eventmgr,gameobj,blendernearsensor->dist,blendernearsensor->resetdist,bFindMaterial,nearpropertyname,kxscene);
+
+ }
+ break;
+ }
+
+
+ case SENS_KEYBOARD:
+ {
+ /* temporary input device, for converting the code for the keyboard sensor */
+
+ bKeyboardSensor* blenderkeybdsensor = (bKeyboardSensor*)sens->data;
+ SCA_KeyboardManager* eventmgr = (SCA_KeyboardManager*) logicmgr->FindEventManager(SCA_EventManager::KEYBOARD_EVENTMGR);
+ if (eventmgr)
+ {
+ gamesensor = new SCA_KeyboardSensor(eventmgr,
+ gReverseKeyTranslateTable[blenderkeybdsensor->key],
+ blenderkeybdsensor->qual,
+ blenderkeybdsensor->qual2,
+ (blenderkeybdsensor->type == SENS_ALL_KEYS),
+ blenderkeybdsensor->targetName,
+ blenderkeybdsensor->toggleName,
+ gameobj); // blenderkeybdsensor->pad);
+
+ }
+
+ break;
+ }
+ case SENS_MOUSE:
+ {
+ int keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_NODEF;
+ bool trackfocus = false;
+ bMouseSensor *bmouse = (bMouseSensor *)sens->data;
+
+ /* There are two main types of mouse sensors. If there is
+ * no focus-related behaviour requested, we can make do
+ * with a basic sensor. This cuts down memory usage and
+ * gives a slight performance gain. */
+
+ SCA_MouseManager *eventmgr
+ = (SCA_MouseManager*) logicmgr->FindEventManager(SCA_EventManager::MOUSE_EVENTMGR);
+ if (eventmgr) {
+
+ /* Determine key mode. There is at most one active mode. */
+ switch (bmouse->type) {
+ case BL_SENS_MOUSE_LEFT_BUTTON:
+ keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_LEFTBUTTON;
+ break;
+ case BL_SENS_MOUSE_MIDDLE_BUTTON:
+ keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_MIDDLEBUTTON;
+ break;
+ case BL_SENS_MOUSE_RIGHT_BUTTON:
+ keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_RIGHTBUTTON;
+ break;
+ case BL_SENS_MOUSE_MOVEMENT:
+ keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_MOVEMENT;
+ break;
+ case BL_SENS_MOUSE_MOUSEOVER:
+ trackfocus = true;
+ break;
+ default:
+ ; /* error */
+ }
+
+ /* initial mouse position */
+ int startx = canvas->GetWidth()/2;
+ int starty = canvas->GetHeight()/2;
+
+ if (!trackfocus) {
+ /* plain, simple mouse sensor */
+ gamesensor = new SCA_MouseSensor(eventmgr,
+ startx,starty,
+ keytype,
+ gameobj);
+ } else {
+ /* give us a focus-aware sensor */
+ gamesensor = new KX_MouseFocusSensor(eventmgr,
+ startx,
+ starty,
+ keytype,
+ trackfocus,
+ canvas,
+ kxscene,
+ gameobj);
+ }
+ } else {
+ // cout << "\n Could't find mouse event manager..."; - should throw an error here...
+ }
+ break;
+ }
+ case SENS_PROPERTY:
+ {
+ bPropertySensor* blenderpropsensor = (bPropertySensor*) sens->data;
+ SCA_EventManager* eventmgr
+ = logicmgr->FindEventManager(SCA_EventManager::PROPERTY_EVENTMGR);
+ if (eventmgr)
+ {
+ STR_String propname=blenderpropsensor->name;
+ STR_String propval=blenderpropsensor->value;
+ STR_String propmaxval=blenderpropsensor->maxvalue;
+
+ SCA_PropertySensor::KX_PROPSENSOR_TYPE
+ propchecktype = SCA_PropertySensor::KX_PROPSENSOR_NODEF;
+
+ /* Better do an explicit conversion here! (was implicit */
+ /* before...) */
+ switch(blenderpropsensor->type) {
+ case SENS_PROP_EQUAL:
+ propchecktype = SCA_PropertySensor::KX_PROPSENSOR_EQUAL;
+ break;
+ case SENS_PROP_NEQUAL:
+ propchecktype = SCA_PropertySensor::KX_PROPSENSOR_NOTEQUAL;
+ break;
+ case SENS_PROP_INTERVAL:
+ propchecktype = SCA_PropertySensor::KX_PROPSENSOR_INTERVAL;
+ break;
+ case SENS_PROP_CHANGED:
+ propchecktype = SCA_PropertySensor::KX_PROPSENSOR_CHANGED;
+ break;
+ case SENS_PROP_EXPRESSION:
+ propchecktype = SCA_PropertySensor::KX_PROPSENSOR_EXPRESSION;
+ /* error */
+ break;
+ default:
+ ; /* error */
+ }
+ gamesensor = new SCA_PropertySensor(eventmgr,gameobj,propname,propval,propmaxval,propchecktype);
+ }
+
+ break;
+ }
+
+ case SENS_RADAR:
+ {
+ /*
+ SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::TOUCH_EVENTMGR);
+ if (eventmgr)
+ {
+ STR_String radarpropertyname;
+ STR_String touchpropertyname;
+ bRadarSensor* blenderradarsensor = (bRadarSensor*) sens->data;
+
+ int radaraxis = blenderradarsensor->axis;
+
+ if (blenderradarsensor->name)
+ {
+ // only objects that own this property will be taken into account
+ radarpropertyname = (char*) blenderradarsensor->name;
+ }
+
+ MT_Scalar coneheight = blenderradarsensor->range;
+
+ // janco: the angle was doubled, so should I divide the factor in 2
+ // or the blenderradarsensor->angle?
+ // nzc: the angle is the opening angle. We need to init with
+ // the axis-hull angle,so /2.0.
+ MT_Scalar factor = tan(MT_radians((blenderradarsensor->angle)/2.0));
+ //MT_Scalar coneradius = coneheight * (factor / 2);
+ MT_Scalar coneradius = coneheight * factor;
+
+ DT_ShapeHandle shape = DT_Cone(coneradius,coneheight);
+
+ // this sumoObject is not deleted by a gameobj, so delete it ourself
+ // later (memleaks)!
+ SM_Object* sumoObj = new SM_Object(shape,NULL,NULL,NULL);
+ sumoObj->setMargin(0.0);
+
+ sumoObj->setPosition(gameobj->NodeGetWorldPosition());
+ MT_Scalar smallmargin = 0.0;
+ MT_Scalar largemargin = 0.1;
+
+ bool bFindMaterial = false;
+ gamesensor = new KX_RadarSensor(
+ eventmgr,
+ gameobj,
+ coneradius,
+ coneheight,
+ radaraxis,
+ smallmargin,
+ largemargin,
+ sumoObj,
+ bFindMaterial,
+ radarpropertyname,
+ kxscene);
+
+ }
+ */
+ break;
+ }
+ case SENS_RAY:
+ {
+ bRaySensor* blenderraysensor = (bRaySensor*) sens->data;
+
+ //blenderradarsensor->angle;
+ SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::RAY_EVENTMGR);
+ if (eventmgr)
+ {
+ bool bFindMaterial = (blenderraysensor->mode & SENS_COLLISION_MATERIAL);
+
+ STR_String checkname = (bFindMaterial? blenderraysensor->matname : blenderraysensor->propname);
+
+ // don't want to get rays of length 0.0 or so
+ double distance = (blenderraysensor->range < 0.01 ? 0.01 : blenderraysensor->range );
+ int axis = blenderraysensor->axisflag;
+
+
+ gamesensor = 0;
+ /*new KX_RaySensor(eventmgr,
+ gameobj,
+ checkname,
+ bFindMaterial,
+ distance,
+ axis,
+ kxscene->GetSumoScene());
+ */
+
+ }
+ break;
+ }
+
+ case SENS_RANDOM:
+ {
+ bRandomSensor* blenderrndsensor = (bRandomSensor*) sens->data;
+ // some files didn't write randomsensor, avoid crash now for NULL ptr's
+ if (blenderrndsensor)
+ {
+ SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::RANDOM_EVENTMGR);
+ if (eventmgr)
+ {
+ int randomSeed = blenderrndsensor->seed;
+ gamesensor = new SCA_RandomSensor(eventmgr, gameobj, randomSeed);
+ }
+ }
+ break;
+ }
+ default:
+ {
+ }
+ }
+
+ if (gamesensor)
+ {
+ gamesensor->SetExecutePriority(executePriority++);
+ STR_String uniquename = sens->name;
+ uniquename += "#SENS#";
+ uniqueint++;
+ CIntValue* uniqueval = new CIntValue(uniqueint);
+ uniquename += uniqueval->GetText();
+ uniqueval->Release();
+
+ /* Conversion succeeded, so we can set the generic props here. */
+ gamesensor->SetPulseMode(pos_pulsemode,
+ neg_pulsemode,
+ frequency);
+ gamesensor->SetInvert(invert);
+ gamesensor->SetName(STR_String(sens->name));
+
+ gameobj->AddSensor(gamesensor);
+
+ // only register to manager if it's in an active layer
+
+ if (isInActiveLayer)
+ gamesensor->RegisterToManager();
+
+
+ for (int i=0;i<sens->totlinks;i++)
+ {
+ bController* linkedcont = (bController*) sens->links[i];
+ SCA_IController* gamecont = converter->FindGameController(linkedcont);
+
+ if (gamecont) {
+ logicmgr->RegisterToSensor(gamecont,gamesensor);
+ }
+ }
+
+ }
+ sens=sens->next;
+ }
+}
+
diff --git a/source/gameengine/Converter/KX_ConvertSensors.h b/source/gameengine/Converter/KX_ConvertSensors.h
new file mode 100644
index 00000000000..ed7dccf87a9
--- /dev/null
+++ b/source/gameengine/Converter/KX_ConvertSensors.h
@@ -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 *****
+ */
+#ifndef __KX_CONVERTSENSOR_H
+#define __KX_CONVERTSENSOR_H
+
+void BL_ConvertSensors(struct Object* blenderobject,
+ class KX_GameObject* gameobj,
+ class SCA_LogicManager* logicmgr,
+ class KX_Scene* kxscene,
+ class SCA_IInputDevice* keydev,
+ int & executePriority ,
+ int activeLayerBitInfo,
+ bool isInActiveLayer,
+ class RAS_ICanvas* canvas,
+ class KX_BlenderSceneConverter* converter);
+
+
+#endif //__KX_CONVERTSENSOR_H
diff --git a/source/gameengine/Converter/KX_IpoConvert.cpp b/source/gameengine/Converter/KX_IpoConvert.cpp
new file mode 100644
index 00000000000..46c9ef0ef13
--- /dev/null
+++ b/source/gameengine/Converter/KX_IpoConvert.cpp
@@ -0,0 +1,559 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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
+
+// don't show stl-warnings
+#pragma warning (disable:4786)
+#endif
+
+
+#include "KX_GameObject.h"
+#include "KX_IpoConvert.h"
+#include "KX_IInterpolator.h"
+#include "KX_ScalarInterpolator.h"
+
+#include "KX_BlenderScalarInterpolator.h"
+#include "KX_BlenderSceneConverter.h"
+
+
+/* This little block needed for linking to Blender... */
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+#include "DNA_object_types.h"
+#include "DNA_ipo_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_world_types.h"
+#include "DNA_camera_types.h"
+/* end of blender include block */
+
+#include "KX_IPO_SGController.h"
+#include "KX_LightIpoSGController.h"
+#include "KX_CameraIpoSGController.h"
+#include "KX_WorldIpoController.h"
+#include "KX_ObColorIpoSGController.h"
+
+#include "SG_Node.h"
+
+static BL_InterpolatorList *GetIpoList(struct Ipo *for_ipo, KX_BlenderSceneConverter *converter) {
+ BL_InterpolatorList *ipoList= converter->FindInterpolatorList(for_ipo);
+
+ if (!ipoList) {
+ ipoList = new BL_InterpolatorList(for_ipo);
+ converter->RegisterInterpolatorList(ipoList, for_ipo);
+ }
+
+ return ipoList;
+}
+
+void BL_ConvertIpos(struct Object* blenderobject,KX_GameObject* gameobj,KX_BlenderSceneConverter *converter)
+{
+ if (blenderobject->ipo) {
+
+ KX_IpoSGController* ipocontr = new KX_IpoSGController();
+ gameobj->GetSGNode()->AddSGController(ipocontr);
+ ipocontr->SetObject(gameobj->GetSGNode());
+
+ // For ipo_as_force, we need to know which SM object and Scene the
+ // object associated with this ipo is in. Is this already known here?
+ // I think not.... then it must be done later :(
+// ipocontr->SetSumoReference(gameobj->GetSumoScene(),
+// gameobj->GetSumoObject());
+
+ ipocontr->SetGameObject(gameobj);
+
+ ipocontr->GetIPOTransform().SetPosition(
+ MT_Point3(
+ blenderobject->loc[0]+blenderobject->dloc[0],
+ blenderobject->loc[1]+blenderobject->dloc[1],
+ blenderobject->loc[2]+blenderobject->dloc[2]
+ )
+ );
+ ipocontr->GetIPOTransform().SetEulerAngles(
+ MT_Vector3(
+ blenderobject->rot[0],
+ blenderobject->rot[1],
+ blenderobject->rot[2]
+ )
+ );
+ ipocontr->GetIPOTransform().SetScaling(
+ MT_Vector3(
+ blenderobject->size[0],
+ blenderobject->size[1],
+ blenderobject->size[2]
+ )
+ );
+
+ BL_InterpolatorList *ipoList= GetIpoList(blenderobject->ipo, converter);
+
+ // For each active channel in the ipoList add an
+ // interpolator to the game object.
+
+ KX_IScalarInterpolator *ipo;
+
+ ipo = ipoList->GetScalarInterpolator(OB_LOC_X);
+ if (ipo) {
+ KX_IInterpolator *interpolator =
+ new KX_ScalarInterpolator(
+ &(ipocontr->GetIPOTransform().GetPosition()[0]),
+ ipo);
+ ipocontr->AddInterpolator(interpolator);
+ ipocontr->SetModifyPosition(true);
+
+ }
+
+ ipo = ipoList->GetScalarInterpolator(OB_LOC_Y);
+ if (ipo) {
+ KX_IInterpolator *interpolator =
+ new KX_ScalarInterpolator(
+ &(ipocontr->GetIPOTransform().GetPosition()[1]),
+ ipo);
+ ipocontr->AddInterpolator(interpolator);
+ ipocontr->SetModifyPosition(true);
+ }
+
+ ipo = ipoList->GetScalarInterpolator(OB_LOC_Z);
+ if (ipo) {
+ KX_IInterpolator *interpolator =
+ new KX_ScalarInterpolator(
+ &(ipocontr->GetIPOTransform().GetPosition()[2]),
+ ipo);
+ ipocontr->AddInterpolator(interpolator);
+ ipocontr->SetModifyPosition(true);
+ }
+
+ // Master the art of cut & paste programming...
+
+ ipo = ipoList->GetScalarInterpolator(OB_DLOC_X);
+ if (ipo) {
+ KX_IInterpolator *interpolator =
+ new KX_ScalarInterpolator(
+ &(ipocontr->GetIPOTransform().GetDeltaPosition()[0]),
+ ipo);
+ ipocontr->AddInterpolator(interpolator);
+ ipocontr->SetModifyPosition(true);
+ }
+
+ ipo = ipoList->GetScalarInterpolator(OB_DLOC_Y);
+ if (ipo) {
+ KX_IInterpolator *interpolator =
+ new KX_ScalarInterpolator(
+ &(ipocontr->GetIPOTransform().GetDeltaPosition()[1]),
+ ipo);
+ ipocontr->AddInterpolator(interpolator);
+ ipocontr->SetModifyPosition(true);
+ }
+
+ ipo = ipoList->GetScalarInterpolator(OB_DLOC_Z);
+ if (ipo) {
+ KX_IInterpolator *interpolator =
+ new KX_ScalarInterpolator(
+ &(ipocontr->GetIPOTransform().GetDeltaPosition()[2]),
+ ipo);
+ ipocontr->AddInterpolator(interpolator);
+ ipocontr->SetModifyPosition(true);
+ }
+
+ // Explore the finesse of reuse and slight modification
+
+ ipo = ipoList->GetScalarInterpolator(OB_ROT_X);
+ if (ipo) {
+ KX_IInterpolator *interpolator =
+ new KX_ScalarInterpolator(
+ &(ipocontr->GetIPOTransform().GetEulerAngles()[0]),
+ ipo);
+ ipocontr->AddInterpolator(interpolator);
+ ipocontr->SetModifyOrientation(true);
+ }
+ ipo = ipoList->GetScalarInterpolator(OB_ROT_Y);
+ if (ipo) {
+ KX_IInterpolator *interpolator =
+ new KX_ScalarInterpolator(
+ &(ipocontr->GetIPOTransform().GetEulerAngles()[1]),
+ ipo);
+ ipocontr->AddInterpolator(interpolator);
+ ipocontr->SetModifyOrientation(true);
+ }
+ ipo = ipoList->GetScalarInterpolator(OB_ROT_Z);
+ if (ipo) {
+ KX_IInterpolator *interpolator =
+ new KX_ScalarInterpolator(
+ &(ipocontr->GetIPOTransform().GetEulerAngles()[2]),
+ ipo);
+ ipocontr->AddInterpolator(interpolator);
+ ipocontr->SetModifyOrientation(true);
+ }
+
+ // Hmmm, the need for a macro comes to mind...
+
+ ipo = ipoList->GetScalarInterpolator(OB_DROT_X);
+ if (ipo) {
+ KX_IInterpolator *interpolator =
+ new KX_ScalarInterpolator(
+ &(ipocontr->GetIPOTransform().GetDeltaEulerAngles()[0]),
+ ipo);
+ ipocontr->AddInterpolator(interpolator);
+ ipocontr->SetModifyOrientation(true);
+ }
+ ipo = ipoList->GetScalarInterpolator(OB_DROT_Y);
+ if (ipo) {
+ KX_IInterpolator *interpolator =
+ new KX_ScalarInterpolator(
+ &(ipocontr->GetIPOTransform().GetDeltaEulerAngles()[1]),
+ ipo);
+ ipocontr->AddInterpolator(interpolator);
+ ipocontr->SetModifyOrientation(true);
+ }
+ ipo = ipoList->GetScalarInterpolator(OB_DROT_Z);
+ if (ipo) {
+ KX_IInterpolator *interpolator =
+ new KX_ScalarInterpolator(
+ &(ipocontr->GetIPOTransform().GetDeltaEulerAngles()[2]),
+ ipo);
+ ipocontr->AddInterpolator(interpolator);
+ ipocontr->SetModifyOrientation(true);
+ }
+
+ // Hang on, almost there...
+
+ ipo = ipoList->GetScalarInterpolator(OB_SIZE_X);
+ if (ipo) {
+ KX_IInterpolator *interpolator =
+ new KX_ScalarInterpolator(
+ &(ipocontr->GetIPOTransform().GetScaling()[0]),
+ ipo);
+ ipocontr->AddInterpolator(interpolator);
+ ipocontr->SetModifyScaling(true);
+ }
+ ipo = ipoList->GetScalarInterpolator(OB_SIZE_Y);
+ if (ipo) {
+ KX_IInterpolator *interpolator =
+ new KX_ScalarInterpolator(
+ &(ipocontr->GetIPOTransform().GetScaling()[1]),
+ ipo);
+ ipocontr->AddInterpolator(interpolator);
+ ipocontr->SetModifyScaling(true);
+ }
+ ipo = ipoList->GetScalarInterpolator(OB_SIZE_Z);
+ if (ipo) {
+ KX_IInterpolator *interpolator =
+ new KX_ScalarInterpolator(
+ &(ipocontr->GetIPOTransform().GetScaling()[2]),
+ ipo);
+ ipocontr->AddInterpolator(interpolator);
+ ipocontr->SetModifyScaling(true);
+ }
+
+ // The last few...
+
+ ipo = ipoList->GetScalarInterpolator(OB_DSIZE_X);
+ if (ipo) {
+ KX_IInterpolator *interpolator =
+ new KX_ScalarInterpolator(
+ &(ipocontr->GetIPOTransform().GetDeltaScaling()[0]),
+ ipo);
+ ipocontr->AddInterpolator(interpolator);
+ ipocontr->SetModifyScaling(true);
+ }
+ ipo = ipoList->GetScalarInterpolator(OB_DSIZE_Y);
+ if (ipo) {
+ KX_IInterpolator *interpolator =
+ new KX_ScalarInterpolator(
+ &(ipocontr->GetIPOTransform().GetDeltaScaling()[1]),
+ ipo);
+ ipocontr->AddInterpolator(interpolator);
+ ipocontr->SetModifyScaling(true);
+ }
+ ipo = ipoList->GetScalarInterpolator(OB_DSIZE_Z);
+ if (ipo) {
+ KX_IInterpolator *interpolator =
+ new KX_ScalarInterpolator(
+ &(ipocontr->GetIPOTransform().GetDeltaScaling()[2]),
+ ipo);
+ ipocontr->AddInterpolator(interpolator);
+ ipocontr->SetModifyScaling(true);
+ }
+
+ {
+ KX_ObColorIpoSGController* ipocontr=NULL;
+
+ ipo = ipoList->GetScalarInterpolator(OB_COL_R);
+ if (ipo)
+ {
+ if (!ipocontr)
+ {
+ ipocontr = new KX_ObColorIpoSGController();
+ gameobj->GetSGNode()->AddSGController(ipocontr);
+ ipocontr->SetObject(gameobj->GetSGNode());
+ }
+ KX_IInterpolator *interpolator =
+ new KX_ScalarInterpolator(
+ &ipocontr->m_rgba[0],
+ ipo);
+ ipocontr->AddInterpolator(interpolator);
+ }
+ ipo = ipoList->GetScalarInterpolator(OB_COL_G);
+ if (ipo)
+ {
+ if (!ipocontr)
+ {
+ ipocontr = new KX_ObColorIpoSGController();
+ gameobj->GetSGNode()->AddSGController(ipocontr);
+ ipocontr->SetObject(gameobj->GetSGNode());
+ }
+ KX_IInterpolator *interpolator =
+ new KX_ScalarInterpolator(
+ &ipocontr->m_rgba[1],
+ ipo);
+ ipocontr->AddInterpolator(interpolator);
+ }
+ ipo = ipoList->GetScalarInterpolator(OB_COL_B);
+ if (ipo)
+ {
+ if (!ipocontr)
+ {
+ ipocontr = new KX_ObColorIpoSGController();
+ gameobj->GetSGNode()->AddSGController(ipocontr);
+ ipocontr->SetObject(gameobj->GetSGNode());
+ }
+ KX_IInterpolator *interpolator =
+ new KX_ScalarInterpolator(
+ &ipocontr->m_rgba[2],
+ ipo);
+ ipocontr->AddInterpolator(interpolator);
+ }
+ ipo = ipoList->GetScalarInterpolator(OB_COL_A);
+ if (ipo)
+ {
+ if (!ipocontr)
+ {
+ ipocontr = new KX_ObColorIpoSGController();
+ gameobj->GetSGNode()->AddSGController(ipocontr);
+ ipocontr->SetObject(gameobj->GetSGNode());
+ }
+ KX_IInterpolator *interpolator =
+ new KX_ScalarInterpolator(
+ &ipocontr->m_rgba[3],
+ ipo);
+ ipocontr->AddInterpolator(interpolator);
+ }
+ }
+
+
+ }
+
+
+}
+
+void BL_ConvertLampIpos(struct Lamp* blenderlamp, KX_GameObject *lightobj,KX_BlenderSceneConverter *converter)
+{
+
+ if (blenderlamp->ipo) {
+
+ KX_LightIpoSGController* ipocontr = new KX_LightIpoSGController();
+ lightobj->GetSGNode()->AddSGController(ipocontr);
+ ipocontr->SetObject(lightobj->GetSGNode());
+
+ ipocontr->m_energy = blenderlamp->energy;
+ ipocontr->m_col_rgb[0] = blenderlamp->r;
+ ipocontr->m_col_rgb[1] = blenderlamp->g;
+ ipocontr->m_col_rgb[2] = blenderlamp->b;
+ ipocontr->m_dist = blenderlamp->dist;
+
+ BL_InterpolatorList *ipoList= GetIpoList(blenderlamp->ipo, converter);
+
+ // For each active channel in the ipoList add an
+ // interpolator to the game object.
+
+ KX_IScalarInterpolator *ipo;
+
+ ipo = ipoList->GetScalarInterpolator(LA_ENERGY);
+ if (ipo) {
+ KX_IInterpolator *interpolator =
+ new KX_ScalarInterpolator(&ipocontr->m_energy, ipo);
+ ipocontr->AddInterpolator(interpolator);
+ ipocontr->SetModifyEnergy(true);
+ }
+
+ ipo = ipoList->GetScalarInterpolator(LA_DIST);
+ if (ipo) {
+ KX_IInterpolator *interpolator =
+ new KX_ScalarInterpolator(&ipocontr->m_dist, ipo);
+ ipocontr->AddInterpolator(interpolator);
+ ipocontr->SetModifyDist(true);
+ }
+
+ ipo = ipoList->GetScalarInterpolator(LA_COL_R);
+ if (ipo) {
+ KX_IInterpolator *interpolator =
+ new KX_ScalarInterpolator(&ipocontr->m_col_rgb[0], ipo);
+ ipocontr->AddInterpolator(interpolator);
+ ipocontr->SetModifyColor(true);
+ }
+
+ ipo = ipoList->GetScalarInterpolator(LA_COL_G);
+ if (ipo) {
+ KX_IInterpolator *interpolator =
+ new KX_ScalarInterpolator(&ipocontr->m_col_rgb[1], ipo);
+ ipocontr->AddInterpolator(interpolator);
+ ipocontr->SetModifyColor(true);
+ }
+
+ ipo = ipoList->GetScalarInterpolator(LA_COL_B);
+ if (ipo) {
+ KX_IInterpolator *interpolator =
+ new KX_ScalarInterpolator(&ipocontr->m_col_rgb[2], ipo);
+ ipocontr->AddInterpolator(interpolator);
+ ipocontr->SetModifyColor(true);
+ }
+ }
+}
+
+
+
+
+void BL_ConvertCameraIpos(struct Camera* blendercamera, KX_GameObject *cameraobj,KX_BlenderSceneConverter *converter)
+{
+
+ if (blendercamera->ipo) {
+
+ KX_CameraIpoSGController* ipocontr = new KX_CameraIpoSGController();
+ cameraobj->GetSGNode()->AddSGController(ipocontr);
+ ipocontr->SetObject(cameraobj->GetSGNode());
+
+ ipocontr->m_lens = blendercamera->lens;
+ ipocontr->m_clipstart = blendercamera->clipsta;
+ ipocontr->m_clipend = blendercamera->clipend;
+
+ BL_InterpolatorList *ipoList= GetIpoList(blendercamera->ipo, converter);
+
+ // For each active channel in the ipoList add an
+ // interpolator to the game object.
+
+ KX_IScalarInterpolator *ipo;
+
+ ipo = ipoList->GetScalarInterpolator(CAM_LENS);
+ if (ipo) {
+ KX_IInterpolator *interpolator =
+ new KX_ScalarInterpolator(&ipocontr->m_lens, ipo);
+ ipocontr->AddInterpolator(interpolator);
+ ipocontr->SetModifyLens(true);
+ }
+
+ ipo = ipoList->GetScalarInterpolator(CAM_STA);
+ if (ipo) {
+ KX_IInterpolator *interpolator =
+ new KX_ScalarInterpolator(&ipocontr->m_clipstart, ipo);
+ ipocontr->AddInterpolator(interpolator);
+ ipocontr->SetModifyClipStart(true);
+ }
+
+ ipo = ipoList->GetScalarInterpolator(CAM_END);
+ if (ipo) {
+ KX_IInterpolator *interpolator =
+ new KX_ScalarInterpolator(&ipocontr->m_clipend, ipo);
+ ipocontr->AddInterpolator(interpolator);
+ ipocontr->SetModifyClipEnd(true);
+ }
+
+ }
+}
+
+
+void BL_ConvertWorldIpos(struct World* blenderworld,KX_BlenderSceneConverter *converter)
+{
+
+ if (blenderworld->ipo) {
+
+ KX_WorldIpoController* ipocontr = new KX_WorldIpoController();
+
+// Erwin, hook up the world ipo controller here
+// Gino: hook it up to what ?
+// is there a userinterface element for that ?
+// for now, we have some new python hooks to access the data, for a work-around
+
+ ipocontr->m_mist_start = blenderworld->miststa;
+ ipocontr->m_mist_dist = blenderworld->mistdist;
+ ipocontr->m_mist_rgb[0] = blenderworld->horr;
+ ipocontr->m_mist_rgb[1] = blenderworld->horg;
+ ipocontr->m_mist_rgb[2] = blenderworld->horb;
+
+ BL_InterpolatorList *ipoList= GetIpoList(blenderworld->ipo, converter);
+
+ // For each active channel in the ipoList add an
+ // interpolator to the game object.
+
+ KX_IScalarInterpolator *ipo;
+
+ ipo = ipoList->GetScalarInterpolator(WO_HOR_R);
+ if (ipo) {
+ KX_IInterpolator *interpolator =
+ new KX_ScalarInterpolator(&ipocontr->m_mist_rgb[0], ipo);
+ ipocontr->AddInterpolator(interpolator);
+ ipocontr->SetModifyMistColor(true);
+ }
+
+ ipo = ipoList->GetScalarInterpolator(WO_HOR_G);
+ if (ipo) {
+ KX_IInterpolator *interpolator =
+ new KX_ScalarInterpolator(&ipocontr->m_mist_rgb[1], ipo);
+ ipocontr->AddInterpolator(interpolator);
+ ipocontr->SetModifyMistColor(true);
+ }
+
+ ipo = ipoList->GetScalarInterpolator(WO_HOR_B);
+ if (ipo) {
+ KX_IInterpolator *interpolator =
+ new KX_ScalarInterpolator(&ipocontr->m_mist_rgb[2], ipo);
+ ipocontr->AddInterpolator(interpolator);
+ ipocontr->SetModifyMistColor(true);
+ }
+
+ ipo = ipoList->GetScalarInterpolator(WO_MISTDI);
+ if (ipo) {
+ KX_IInterpolator *interpolator =
+ new KX_ScalarInterpolator(&ipocontr->m_mist_dist, ipo);
+ ipocontr->AddInterpolator(interpolator);
+ ipocontr->SetModifyMistDist(true);
+ }
+
+ ipo = ipoList->GetScalarInterpolator(WO_MISTSTA);
+ if (ipo) {
+ KX_IInterpolator *interpolator =
+ new KX_ScalarInterpolator(&ipocontr->m_mist_start, ipo);
+ ipocontr->AddInterpolator(interpolator);
+ ipocontr->SetModifyMistStart(true);
+ }
+ }
+}
+
diff --git a/source/gameengine/Converter/KX_IpoConvert.h b/source/gameengine/Converter/KX_IpoConvert.h
new file mode 100644
index 00000000000..5686ca866eb
--- /dev/null
+++ b/source/gameengine/Converter/KX_IpoConvert.h
@@ -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 *****
+ */
+#ifndef __KX_IPOCONVERT_H
+#define __KX_IPOCONVERT_H
+
+struct Object;
+
+void BL_ConvertIpos(struct Object* blenderobject,
+ class KX_GameObject* gameobj,
+ class KX_BlenderSceneConverter *converter
+ );
+
+void BL_ConvertLampIpos(struct Lamp* blenderlight,
+ class KX_GameObject* lightobj,
+ class KX_BlenderSceneConverter *converter);
+
+void BL_ConvertWorldIpos(struct World* blenderworld,
+ class KX_BlenderSceneConverter *converter);
+
+void BL_ConvertCameraIpos(struct Camera* blendercamera,
+ class KX_GameObject* cameraobj,
+ class KX_BlenderSceneConverter *converter);
+
+
+#endif //__KX_IPOCONVERT_H
diff --git a/source/gameengine/Converter/Makefile b/source/gameengine/Converter/Makefile
new file mode 100644
index 00000000000..8f85e4c1a58
--- /dev/null
+++ b/source/gameengine/Converter/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 *****
+#
+#
+
+LIBNAME = blconverter
+DIR = $(OCGDIR)/gameengine/$(LIBNAME)
+
+include nan_compile.mk
+
+CCFLAGS += $(LEVEL_1_CPP_WARNINGS)
+
+CPPFLAGS += -I$(OPENGL_HEADERS)
+CPPFLAGS += -I$(NAN_STRING)/include
+CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION)
+CPPFLAGS += -I$(NAN_FUZZICS)/include -I$(NAN_SUMO)/include -I$(NAN_MOTO)/include
+CPPFLAGS += -I../../blender
+# these two needed because of blenkernel
+CPPFLAGS += -I../../blender/imbuf
+CPPFLAGS += -I../../blender/makesdna
+CPPFLAGS += -I../../blender/include
+CPPFLAGS += -I../../blender/blenlib
+CPPFLAGS += -I../../blender/blenkernel
+CPPFLAGS += -I../../blender/render/extern/include
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+CPPFLAGS += -I../Expressions -I../Rasterizer -I../GameLogic -I../SoundSystem
+CPPFLAGS += -I../Ketsji -I../BlenderRoutines -I../SceneGraph
+CPPFLAGS += -I../../kernel/gen_system
+CPPFLAGS += -I../Rasterizer/RAS_OpenGLRasterizer
+CPPFLAGS += -I../Network -I../Ketsji/KXNetwork
+CPPFLAGS += -I../Physics/common -I../Physics/Dummy
+
diff --git a/source/gameengine/Expressions/BoolValue.cpp b/source/gameengine/Expressions/BoolValue.cpp
new file mode 100644
index 00000000000..544b760f4e9
--- /dev/null
+++ b/source/gameengine/Expressions/BoolValue.cpp
@@ -0,0 +1,213 @@
+
+// BoolValue.cpp: implementation of the CBoolValue class.
+/*
+ * Copyright (c) 1996-2000 Erwin Coumans <coockie@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. Erwin Coumans makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ */
+
+
+
+#include "BoolValue.h"
+#include "StringValue.h"
+#include "ErrorValue.h"
+#include "VoidValue.h"
+//#include "FactoryManager.h"
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+
+CBoolValue::CBoolValue()
+/*
+pre: false
+effect: constructs a new CBoolValue
+*/
+{
+ trace("Bool constructor error");
+}
+
+
+
+CBoolValue::CBoolValue(bool inBool)
+: m_bool(inBool)
+{
+} // Constructs a new CBoolValue containing <inBool>
+
+
+
+CBoolValue::CBoolValue(bool innie,STR_String name,AllocationTYPE alloctype)
+{
+ m_bool = innie;
+ SetName(name);
+
+ if (alloctype == CValue::STACKVALUE)
+ CValue::DisableRefCount();
+}
+
+
+
+void CBoolValue::SetValue(CValue* newval)
+{
+ m_bool = (newval->GetNumber() != 0);
+ SetModified(true);
+}
+
+
+
+CValue* CBoolValue::Calc(VALUE_OPERATOR op, CValue *val)
+/*
+pre:
+ret: a new object containing the result of applying operator op to this
+object and val
+*/
+{
+ switch (op)
+ {
+ case VALUE_POS_OPERATOR:
+ case VALUE_NEG_OPERATOR:
+ {
+ return new CErrorValue (op2str(op) + GetText());
+ break;
+ }
+ case VALUE_NOT_OPERATOR:
+ {
+ return new CBoolValue (!m_bool);
+ break;
+ }
+ default:
+ {
+ return val->CalcFinal(VALUE_BOOL_TYPE, op, this);
+ break;
+ }
+ }
+}
+
+
+
+CValue* CBoolValue::CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val)
+/*
+pre: the type of val is dtype
+ret: a new object containing the result of applying operator op to val and
+this object
+*/
+{
+ CValue *ret;
+
+ switch(dtype)
+ {
+ case VALUE_EMPTY_TYPE:
+ case VALUE_BOOL_TYPE:
+ {
+ switch(op)
+ {
+ case VALUE_AND_OPERATOR:
+ {
+ ret = new CBoolValue (((CBoolValue *) val)->GetBool() && m_bool);
+ break;
+ }
+ case VALUE_OR_OPERATOR:
+ {
+ ret = new CBoolValue (((CBoolValue *) val)->GetBool() || m_bool);
+ break;
+ }
+ case VALUE_EQL_OPERATOR:
+ {
+ ret = new CBoolValue (((CBoolValue *) val)->GetBool() == m_bool);
+ break;
+ }
+ case VALUE_NEQ_OPERATOR:
+ {
+ ret = new CBoolValue (((CBoolValue *) val)->GetBool() != m_bool);
+ break;
+ }
+ case VALUE_NOT_OPERATOR:
+ {
+ return new CBoolValue (!m_bool);
+ break;
+ }
+ default:
+ {
+ ret = new CErrorValue(val->GetText() + op2str(op) +
+ "[operator not allowed on booleans]");
+ break;
+ }
+ }
+ break;
+ }
+ case VALUE_STRING_TYPE:
+ {
+ switch(op)
+ {
+ case VALUE_ADD_OPERATOR:
+ {
+ ret = new CStringValue(val->GetText() + GetText(),"");
+ break;
+ }
+ default:
+ {
+ ret = new CErrorValue(val->GetText() + op2str(op) + "[Only + allowed on boolean and string]");
+ break;
+ }
+ }
+ break;
+ }
+ default:
+ ret = new CErrorValue("[type mismatch]" + op2str(op) + GetText());
+ }
+
+ return ret;
+}
+
+
+
+bool CBoolValue::GetBool()
+/*
+pre:
+ret: the bool stored in the object
+*/
+{
+ return m_bool;
+}
+
+
+
+float CBoolValue::GetNumber()
+{
+ return (float)m_bool;
+}
+
+
+
+const STR_String& CBoolValue::GetText()
+{
+ static STR_String sTrueString = STR_String("TRUE");
+ static STR_String sFalseString = STR_String("FALSE");
+
+ return m_bool ? sTrueString : sFalseString;
+}
+
+
+
+CValue* CBoolValue::GetReplica()
+{
+ CBoolValue* replica = new CBoolValue(*this);
+ CValue::AddDataToReplica(replica);
+
+ return replica;
+}
+
+
+
+PyObject* CBoolValue::ConvertValueToPython()
+{
+ return PyInt_FromLong(m_bool != 0);
+}
diff --git a/source/gameengine/Expressions/BoolValue.h b/source/gameengine/Expressions/BoolValue.h
new file mode 100644
index 00000000000..e78ff2ef4bf
--- /dev/null
+++ b/source/gameengine/Expressions/BoolValue.h
@@ -0,0 +1,51 @@
+/*
+ * BoolValue.h: interface for the CBoolValue class.
+ * $Id$
+ * Copyright (c) 1996-2000 Erwin Coumans <coockie@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. Erwin Coumans makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ */
+#if !defined _BOOLVALUE_H
+#define _BOOLVALUE_H
+
+#include "Value.h"
+
+/**
+ * Smart Boolean Value class.
+ * Is used by parser when an expression tree is build containing booleans.
+ */
+
+class CBoolValue : public CPropValue
+{
+
+ //PLUGIN_DECLARE_SERIAL(CBoolValue,CValue)
+
+public:
+ CBoolValue();
+ CBoolValue(bool inBool);
+ CBoolValue(bool innie, STR_String name, AllocationTYPE alloctype = CValue::HEAPVALUE);
+
+ virtual const STR_String& GetText();
+ virtual float GetNumber();
+ bool GetBool();
+ virtual void SetValue(CValue* newval);
+
+ virtual CValue* Calc(VALUE_OPERATOR op, CValue *val);
+ virtual CValue* CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val);
+
+ void Configure(CValue* menuvalue);
+ virtual CValue* GetReplica();
+ virtual PyObject* ConvertValueToPython();
+
+private:
+ bool m_bool;
+};
+
+#endif // !defined _BOOLVALUE_H
diff --git a/source/gameengine/Expressions/ConstExpr.cpp b/source/gameengine/Expressions/ConstExpr.cpp
new file mode 100644
index 00000000000..c8b4c311b7c
--- /dev/null
+++ b/source/gameengine/Expressions/ConstExpr.cpp
@@ -0,0 +1,132 @@
+// ConstExpr.cpp: implementation of the CConstExpr class.
+
+/*
+ * Copyright (c) 1996-2000 Erwin Coumans <coockie@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. Erwin Coumans makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ */
+
+
+
+#include "Value.h" // for precompiled header
+
+#include "ConstExpr.h"
+#include "VectorValue.h"
+
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CConstExpr::CConstExpr()
+{
+}
+
+
+
+CConstExpr::CConstExpr(CValue* constval)
+/*
+pre:
+effect: constructs a CConstExpr cointing the value constval
+*/
+{
+ m_value = constval;
+// m_bModified=true;
+}
+
+
+
+CConstExpr::~CConstExpr()
+/*
+pre:
+effect: deletes the object
+*/
+{
+ if (m_value)
+ m_value->Release();
+}
+
+
+
+unsigned char CConstExpr::GetExpressionID()
+{
+ return CCONSTEXPRESSIONID;
+}
+
+
+
+CValue* CConstExpr::Calculate()
+/*
+pre:
+ret: a new object containing the value of the stored CValue
+*/
+{
+ return m_value->AddRef();
+}
+
+
+
+void CConstExpr::ClearModified()
+{
+ if (m_value)
+ {
+ m_value->SetModified(false);
+ m_value->SetAffected(false);
+ }
+}
+
+
+
+float CConstExpr::GetNumber()
+{
+ return -1;
+}
+
+
+
+bool CConstExpr::NeedsRecalculated()
+{
+ return m_value->IsAffected(); // IsAffected is m_bModified OR m_bAffected !!!
+}
+
+
+
+CExpression* CConstExpr::CheckLink(std::vector<CBrokenLinkInfo*>& brokenlinks)
+{
+// parent checks if child is still usefull.
+// When for example it's value it's deleted flag set
+// then release Value, and return NULL in case of constexpression
+// else return this...
+
+ assertd(m_value);
+ if (m_value->IsReleaseRequested())
+ {
+ AddRef(); //numchanges++;
+ return Release();
+ }
+ else
+ return this;
+}
+
+
+
+void CConstExpr::BroadcastOperators(VALUE_OPERATOR op)
+{
+ assertd(m_value);
+ m_value->SetColorOperator(op);
+}
+
+
+
+bool CConstExpr::MergeExpression(CExpression *otherexpr)
+{
+ assertd(false);
+ return false;
+}
diff --git a/source/gameengine/Expressions/ConstExpr.h b/source/gameengine/Expressions/ConstExpr.h
new file mode 100644
index 00000000000..4c01c142d32
--- /dev/null
+++ b/source/gameengine/Expressions/ConstExpr.h
@@ -0,0 +1,46 @@
+/*
+ * ConstExpr.h: interface for the CConstExpr class.
+ * $Id$
+ * Copyright (c) 1996-2000 Erwin Coumans <coockie@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. Erwin Coumans makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ */
+
+#ifndef __CONSTEXPR_H__
+#define __CONSTEXPR_H__
+
+#include "Expression.h"
+#include "Value.h" // Added by ClassView
+
+class CConstExpr : public CExpression
+{
+ //PLUGIN_DECLARE_SERIAL_EXPRESSION (CConstExpr,CExpression)
+public:
+ virtual bool MergeExpression(CExpression* otherexpr);
+
+ void BroadcastOperators(VALUE_OPERATOR op);
+
+ virtual unsigned char GetExpressionID();
+ CExpression* CheckLink(std::vector<CBrokenLinkInfo*>& brokenlinks);
+ //bool IsInside(float x,float y,float z,bool bBorderInclude=true);
+ bool NeedsRecalculated();
+ void ClearModified();
+ virtual float GetNumber();
+ virtual CValue* Calculate();
+ CConstExpr(CValue* constval);
+ CConstExpr();
+ virtual ~CConstExpr();
+
+
+private:
+ CValue* m_value;
+};
+
+#endif // !defined(AFX_CONSTEXPR_H__061ECFC3_BE87_11D1_A51C_00A02472FC58__INCLUDED_)
diff --git a/source/gameengine/Expressions/EXP_C-Api.cpp b/source/gameengine/Expressions/EXP_C-Api.cpp
new file mode 100644
index 00000000000..4d45fd556eb
--- /dev/null
+++ b/source/gameengine/Expressions/EXP_C-Api.cpp
@@ -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 *****
+ */
+#include "EXP_C-Api.h"
+#include "IntValue.h"
+#include "BoolValue.h"
+#include "StringValue.h"
+#include "ErrorValue.h"
+#include "InputParser.h"
+
+
+EXP_ValueHandle EXP_CreateInt(int innie)
+{
+ return (EXP_ValueHandle) new CIntValue(innie);
+}
+
+
+
+EXP_ValueHandle EXP_CreateBool(int innie)
+{
+ return (EXP_ValueHandle) new CBoolValue(innie!=0);
+}
+
+
+
+EXP_ValueHandle EXP_CreateString(const char* str)
+{
+
+ return (EXP_ValueHandle) new CStringValue(str,"");
+}
+
+
+
+void EXP_SetName(EXP_ValueHandle inval,const char* newname)
+{
+ ((CValue*) inval)->SetName(newname);
+}
+
+
+
+/* calculate expression from inputtext */
+EXP_ValueHandle EXP_ParseInput(const char* inputtext)
+{
+ CValue* resultval=NULL;
+ CParser parser;
+ CExpression* expr = parser.ProcessText(inputtext);
+ if (expr)
+ {
+ resultval = expr->Calculate();
+ expr->Release();
+ }
+ else
+ {
+ resultval = new CErrorValue("couldn't parsetext");
+ }
+
+ return (EXP_ValueHandle) resultval;
+}
+
+
+
+void EXP_ReleaseValue(EXP_ValueHandle inval)
+{
+ ((CValue*) inval)->Release();
+}
+
+
+
+int EXP_IsValid(EXP_ValueHandle inval)
+{
+ return !((CValue*) inval)->IsError();
+}
+
+
+
+/* assign property 'propval' to 'destinationval' */
+void EXP_SetProperty(EXP_ValueHandle destinationval,
+ const char* propname,
+ EXP_ValueHandle propval)
+{
+ ((CValue*) destinationval)->SetProperty(propname,(CValue*)propval);
+}
+
+
+
+const char* EXP_GetText(EXP_ValueHandle inval)
+{
+ return ((CValue*) inval)->GetText();
+}
+
+
+
+EXP_ValueHandle EXP_GetProperty(EXP_ValueHandle inval,const char* propname)
+{
+ return (EXP_ValueHandle) ((CValue*)inval)->GetProperty(propname);
+}
diff --git a/source/gameengine/Expressions/EXP_C-Api.h b/source/gameengine/Expressions/EXP_C-Api.h
new file mode 100644
index 00000000000..e99152294f1
--- /dev/null
+++ b/source/gameengine/Expressions/EXP_C-Api.h
@@ -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 *****
+ */
+#ifndef __EXPRESSION_INCLUDE
+#define __EXPRESSION_INCLUDE
+
+
+#define EXP_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name
+
+EXP_DECLARE_HANDLE(EXP_ValueHandle);
+EXP_DECLARE_HANDLE(EXP_ExpressionHandle);
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern EXP_ValueHandle EXP_CreateInt(int innie);
+extern EXP_ValueHandle EXP_CreateBool(int innie);
+extern EXP_ValueHandle EXP_CreateString(const char* str);
+extern void EXP_SetName(EXP_ValueHandle,const char* newname);
+
+/* calculate expression from inputtext */
+extern EXP_ValueHandle EXP_ParseInput(const char* inputtext);
+extern void EXP_ReleaseValue(EXP_ValueHandle);
+extern int EXP_IsValid(EXP_ValueHandle);
+
+/* assign property 'propval' to 'destinationval' */
+extern void EXP_SetProperty(EXP_ValueHandle propval,EXP_ValueHandle destinationval);
+
+/* returns NULL if property doesn't exist */
+extern EXP_ValueHandle EXP_GetProperty(EXP_ValueHandle inval,const char* propname);
+
+const char* EXP_GetText(EXP_ValueHandle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //__EXPRESSION_INCLUDE
diff --git a/source/gameengine/Expressions/EmptyValue.cpp b/source/gameengine/Expressions/EmptyValue.cpp
new file mode 100644
index 00000000000..25c0b6af5d7
--- /dev/null
+++ b/source/gameengine/Expressions/EmptyValue.cpp
@@ -0,0 +1,127 @@
+
+// EmptyValue.cpp: implementation of the CEmptyValue class.
+/*
+ * Copyright (c) 1996-2000 Erwin Coumans <coockie@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. Erwin Coumans makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ */
+
+
+
+
+#include "EmptyValue.h"
+#include "IntValue.h"
+#include "FloatValue.h"
+#include "StringValue.h"
+#include "ErrorValue.h"
+#include "ListValue.h"
+#include "VoidValue.h"
+
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CEmptyValue::CEmptyValue()
+/*
+pre:
+effect: constructs a new CEmptyValue
+*/
+{
+ SetModified(false);
+}
+
+
+
+CEmptyValue::~CEmptyValue()
+/*
+pre:
+effect: deletes the object
+*/
+{
+
+}
+
+
+
+CValue * CEmptyValue::Calc(VALUE_OPERATOR op, CValue * val)
+/*
+pre:
+ret: a new object containing the result of applying operator op to this
+object and val
+*/
+{
+ return val->CalcFinal(VALUE_EMPTY_TYPE, op, this);
+
+}
+
+
+
+CValue * CEmptyValue::CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue * val)
+/*
+pre: the type of val is dtype
+ret: a new object containing the result of applying operator op to val and
+this object
+*/
+{
+ return val->AddRef();
+}
+
+
+
+float CEmptyValue::GetNumber()
+{
+ return 0;
+}
+
+
+
+CListValue* CEmptyValue::GetPolySoup()
+{
+ CListValue* soup = new CListValue();
+ //don't add any poly, while it's an empty value
+ return soup;
+}
+
+
+
+bool CEmptyValue::IsInside(CValue* testpoint,bool bBorderInclude)
+{
+ // empty space is solid, so always inside
+ return true;
+}
+
+
+
+double* CEmptyValue::GetVector3(bool bGetTransformedVec)
+{
+ assertd(false); // don't get vector from me
+ return ZeroVector();
+}
+
+
+
+static STR_String emptyString = STR_String("");
+
+
+const STR_String & CEmptyValue::GetText()
+{
+ return emptyString;
+}
+
+
+
+CValue* CEmptyValue::GetReplica()
+{
+ CEmptyValue* replica = new CEmptyValue(*this);
+ CValue::AddDataToReplica(replica);
+ return replica;
+}
+
diff --git a/source/gameengine/Expressions/EmptyValue.h b/source/gameengine/Expressions/EmptyValue.h
new file mode 100644
index 00000000000..d400cd065f5
--- /dev/null
+++ b/source/gameengine/Expressions/EmptyValue.h
@@ -0,0 +1,39 @@
+/*
+ * EmptyValue.h: interface for the CEmptyValue class.
+ * $Id$
+ * Copyright (c) 1996-2000 Erwin Coumans <coockie@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. Erwin Coumans makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ */
+#if !defined _EMPTYVALUE_H
+#define _EMPTYVALUE_H
+
+#include "Value.h"
+
+class CListValue;
+
+class CEmptyValue : public CPropValue
+{
+ //PLUGIN_DECLARE_SERIAL (CEmptyValue,CValue)
+public:
+ CEmptyValue();
+ virtual ~CEmptyValue();
+
+ virtual const STR_String & GetText();
+ virtual float GetNumber();
+ CListValue* GetPolySoup();
+ virtual double* GetVector3(bool bGetTransformedVec=false);
+ bool IsInside(CValue* testpoint,bool bBorderInclude=true);
+ CValue * Calc(VALUE_OPERATOR op, CValue *val);
+ CValue * CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val);
+ virtual CValue* GetReplica();
+};
+
+#endif // !defined _EMPTYVALUE_H
diff --git a/source/gameengine/Expressions/ErrorValue.cpp b/source/gameengine/Expressions/ErrorValue.cpp
new file mode 100644
index 00000000000..fd1ba7399b3
--- /dev/null
+++ b/source/gameengine/Expressions/ErrorValue.cpp
@@ -0,0 +1,125 @@
+// ErrorValue.cpp: implementation of the CErrorValue class.
+/*
+ * Copyright (c) 1996-2000 Erwin Coumans <coockie@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. Erwin Coumans makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ */
+
+
+
+
+
+
+#include "ErrorValue.h"
+
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CErrorValue::CErrorValue()
+/*
+pre:
+effect: constructs a new CErrorValue containing errormessage "Error"
+*/
+{
+ m_strErrorText = "Error";
+ SetError(true);
+}
+
+
+
+CErrorValue::CErrorValue(STR_String errmsg)
+/*
+pre:
+effect: constructs a new CErrorValue containing errormessage errmsg
+*/
+{
+ m_strErrorText = "[" + errmsg + "]";
+ SetError(true);
+}
+
+
+
+CErrorValue::~CErrorValue()
+/*
+pre:
+effect: deletes the object
+*/
+{
+
+}
+
+
+
+CValue* CErrorValue::Calc(VALUE_OPERATOR op, CValue *val)
+/*
+pre:
+ret: a new object containing the result of applying operator op to this
+ object and val
+*/
+{
+ CValue* errorval;
+
+ switch (op)
+ {
+ case VALUE_POS_OPERATOR:
+ case VALUE_NEG_OPERATOR:
+ case VALUE_NOT_OPERATOR:
+ {
+ errorval = new CErrorValue (op2str(op) + GetText());
+ break;
+ }
+ default:
+ {
+ errorval = val->CalcFinal(VALUE_ERROR_TYPE, op, this);
+ break;
+ }
+ }
+
+ return errorval;
+}
+
+
+
+CValue* CErrorValue::CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val)
+/*
+pre: the type of val is dtype
+ret: a new object containing the result of applying operator op to val and
+ this object
+*/
+{
+ return new CErrorValue (val->GetText() + op2str(op) + GetText());
+}
+
+
+
+float CErrorValue::GetNumber()
+{
+ return -1;
+}
+
+
+
+const STR_String & CErrorValue::GetText()
+{
+ return m_strErrorText;
+}
+
+
+
+CValue* CErrorValue::GetReplica()
+{
+ // who would want a copy of an error ?
+ trace ("Error: ErrorValue::GetReplica() not implemented yet");
+ assertd(false);
+
+ return NULL;
+} \ No newline at end of file
diff --git a/source/gameengine/Expressions/ErrorValue.h b/source/gameengine/Expressions/ErrorValue.h
new file mode 100644
index 00000000000..8a4726e196d
--- /dev/null
+++ b/source/gameengine/Expressions/ErrorValue.h
@@ -0,0 +1,38 @@
+/*
+ * ErrorValue.h: interface for the CErrorValue class.
+ * $Id$
+ * Copyright (c) 1996-2000 Erwin Coumans <coockie@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. Erwin Coumans makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ */
+
+#if !defined _ERRORVALUE_H
+#define _ERRORVALUE_H
+
+#include "Value.h"
+
+class CErrorValue : public CPropValue
+{
+
+public:
+ virtual const STR_String & GetText();
+ virtual float GetNumber();
+ CErrorValue();
+ CErrorValue(STR_String errmsg);
+ virtual ~CErrorValue();
+ virtual CValue* Calc(VALUE_OPERATOR op, CValue* val);
+ virtual CValue* CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val);
+ virtual CValue* GetReplica();
+
+private:
+ STR_String m_strErrorText;
+};
+
+#endif // !defined _ERRORVALUE_H
diff --git a/source/gameengine/Expressions/Expression.cpp b/source/gameengine/Expressions/Expression.cpp
new file mode 100644
index 00000000000..5e7950fbcf0
--- /dev/null
+++ b/source/gameengine/Expressions/Expression.cpp
@@ -0,0 +1,75 @@
+// Expression.cpp: implementation of the CExpression class.
+/*
+ * Copyright (c) 1996-2000 Erwin Coumans <coockie@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. Erwin Coumans makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ */
+
+
+
+#include "Expression.h"
+#include "ErrorValue.h"
+//#include "FactoryManager.h"
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CExpression::CExpression()// : m_cached_calculate(NULL)
+{
+ m_refcount = 1;
+#ifdef _DEBUG
+ //gRefCountExpr++;
+#endif
+}
+
+CExpression::~CExpression()
+{
+ assert (m_refcount == 0);
+}
+
+
+
+// destuctor for CBrokenLinkInfo
+CBrokenLinkInfo::~CBrokenLinkInfo()
+{
+ if (m_pExpr && !m_bRestored)
+ m_pExpr->Release();
+}
+
+
+void CBrokenLinkInfo::RestoreLink()
+{
+
+
+ assertd(m_pExpr);
+
+ if (m_pExpr)
+ {
+ if (!m_bRestored){
+ m_bRestored=true;
+
+ }
+ if (*m_pmemExpr)
+ {
+ (*m_pmemExpr)->Release();
+ }
+ *m_pmemExpr = m_pExpr;
+
+// m_pExpr=NULL;
+ }
+}
+
+void CBrokenLinkInfo::BreakLink()
+{
+ m_bRestored=false;
+ m_pExpr->AddRef();
+}
+
diff --git a/source/gameengine/Expressions/Expression.h b/source/gameengine/Expressions/Expression.h
new file mode 100644
index 00000000000..f48ac7eb160
--- /dev/null
+++ b/source/gameengine/Expressions/Expression.h
@@ -0,0 +1,133 @@
+/*
+ * Expression.h: interface for the CExpression class.
+ * $Id$
+ * Copyright (c) 1996-2000 Erwin Coumans <coockie@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. Erwin Coumans makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ */
+
+#if !defined _EXPRESSION_H
+#define _EXPRESSION_H
+
+#include "Value.h"
+
+//extern int gRefCountExpr; // only for debugging purposes (detect mem.leaks)
+
+
+
+
+#define PLUGIN_DECLARE_SERIAL_EXPRESSION(class_name,base_class_name) \
+public: \
+ virtual base_class_name * Copy() { return new class_name; } \
+ virtual bool EdSerialize(CompressorArchive& arch,class CFactoryManager* facmgr,bool bIsStoring); \
+ virtual bool EdIdSerialize(CompressorArchive& arch,class CFactoryManager* facmgr,bool bIsStoring) \
+{ \
+ if (bIsStoring) \
+ { \
+ unsigned char exprID = GetExpressionID(); \
+ arch << exprID; \
+ } \
+ return true; \
+} \
+
+
+
+class CExpression;
+
+
+// for undo/redo system the deletion in the expressiontree can be restored by replacing broken links 'inplace'
+class CBrokenLinkInfo
+{
+ public:
+ CBrokenLinkInfo(CExpression** pmemexpr,CExpression* expr)
+ :m_pmemExpr(pmemexpr),
+ m_pExpr(expr)
+ {
+ assertd(pmemexpr);
+ m_bRestored=false;
+ };
+
+ virtual ~CBrokenLinkInfo();
+ void RestoreLink();
+ void BreakLink();
+
+
+ // members vars
+ private:
+ CExpression** m_pmemExpr;
+ CExpression* m_pExpr;
+ bool m_bRestored;
+
+};
+
+
+
+
+
+
+
+
+class CExpression
+{
+public:
+ enum {
+ COPERATOR1EXPRESSIONID = 1,
+ COPERATOR2EXPRESSIONID = 2,
+ CCONSTEXPRESSIONID = 3,
+ CIFEXPRESSIONID = 4,
+ COPERATORVAREXPRESSIONID = 5,
+ CIDENTIFIEREXPRESSIONID = 6
+ };
+
+
+protected:
+ virtual ~CExpression() = 0; //pure virtual
+public:
+ virtual bool MergeExpression(CExpression* otherexpr) = 0;
+ CExpression();
+
+
+ virtual CValue* Calculate() = 0; //pure virtual
+ virtual unsigned char GetExpressionID() = 0;
+ //virtual bool IsInside(float x,float y,float z,bool bBorderInclude=true) = 0; //pure virtual
+ virtual bool NeedsRecalculated() = 0; // another pure one
+ virtual CExpression * CheckLink(std::vector<CBrokenLinkInfo*>& brokenlinks) =0; // another pure one
+ virtual void ClearModified() = 0; // another pure one
+ //virtual CExpression * Copy() =0;
+ virtual void BroadcastOperators(VALUE_OPERATOR op) =0;
+
+ virtual CExpression * AddRef() { // please leave multiline, for debugger !!!
+
+#ifdef _DEBUG
+ //gRefCountExpr++;
+ assertd(m_refcount < 255);
+#endif
+ m_refcount++;
+ return this;
+ };
+ virtual CExpression* Release(CExpression* complicatedtrick=NULL) {
+#ifdef _DEBUG
+ //gRefCountExpr--;
+#endif
+ if (--m_refcount < 1)
+ {
+ delete this;
+ } //else
+ // return this;
+ return complicatedtrick;
+ };
+
+
+protected:
+
+ int m_refcount;
+};
+
+#endif // !defined _EXPRESSION_H
diff --git a/source/gameengine/Expressions/FloatValue.cpp b/source/gameengine/Expressions/FloatValue.cpp
new file mode 100644
index 00000000000..78185bbe163
--- /dev/null
+++ b/source/gameengine/Expressions/FloatValue.cpp
@@ -0,0 +1,316 @@
+// FloatValue.cpp: implementation of the CFloatValue class.
+/*
+ * Copyright (c) 1996-2000 Erwin Coumans <coockie@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. Erwin Coumans makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ */
+
+
+#include "FloatValue.h"
+#include "IntValue.h"
+#include "StringValue.h"
+#include "BoolValue.h"
+#include "ErrorValue.h"
+#include "VoidValue.h"
+
+///#include "..\..\menuvalue.h"
+//#include "FactoryManager.h"
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CFloatValue::CFloatValue()
+/*
+pre: false
+effect: constructs a new CFloatValue
+*/
+{
+ m_pstrRep=NULL;
+}
+
+
+
+CFloatValue::CFloatValue(float fl)
+/*
+pre:
+effect: constructs a new CFloatValue containing value fl
+*/
+{
+ m_float = fl;
+ m_pstrRep=NULL;
+}
+
+
+
+CFloatValue::CFloatValue(float fl,STR_String name,AllocationTYPE alloctype)
+/*
+pre:
+effect: constructs a new CFloatValue containing value fl
+*/
+{
+
+ m_float = fl;
+ SetName(name);
+ if (alloctype==CValue::STACKVALUE)
+ {
+ CValue::DisableRefCount();
+
+ }
+ m_pstrRep=NULL;
+}
+
+
+
+CFloatValue::~CFloatValue()
+/*
+pre:
+effect: deletes the object
+*/
+{
+ if (m_pstrRep)
+ delete m_pstrRep;
+}
+
+
+
+CValue* CFloatValue::Calc(VALUE_OPERATOR op, CValue *val)
+/*
+pre:
+ret: a new object containing the result of applying operator op to this
+ object and val
+*/
+{
+ //return val->CalcFloat(op, this);
+ switch (op)
+ {
+ case VALUE_POS_OPERATOR:
+ return new CFloatValue (m_float);
+ break;
+ case VALUE_NEG_OPERATOR:
+ return new CFloatValue (-m_float);
+ break;
+ case VALUE_NOT_OPERATOR:
+ return new CErrorValue (op2str(op) + "only allowed on booleans");
+ break;
+ case VALUE_AND_OPERATOR:
+ case VALUE_OR_OPERATOR:
+ return new CErrorValue(val->GetText() + op2str(op) + "only allowed on booleans");
+ break;
+ default:
+ return val->CalcFinal(VALUE_FLOAT_TYPE, op, this);
+ break;
+ }
+}
+
+
+
+CValue* CFloatValue::CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val)
+/*
+pre: the type of val is dtype
+ret: a new object containing the result of applying operator op to val and
+ this object
+*/
+{
+ CValue *ret;
+
+ switch(dtype)
+ {
+ case VALUE_INT_TYPE:
+ {
+ switch (op)
+ {
+ case VALUE_ADD_OPERATOR:
+ ret = new CFloatValue(((CIntValue *) val)->GetInt() + m_float);
+ break;
+ case VALUE_SUB_OPERATOR:
+ ret = new CFloatValue(((CIntValue *) val)->GetInt() - m_float);
+ break;
+ case VALUE_MUL_OPERATOR:
+ ret = new CFloatValue(((CIntValue *) val)->GetInt() * m_float);
+ break;
+ case VALUE_DIV_OPERATOR:
+ if (m_float == 0)
+ ret = new CErrorValue("Division by zero");
+ else
+ ret = new CFloatValue (((CIntValue *) val)->GetInt() / m_float);
+ break;
+ case VALUE_EQL_OPERATOR:
+ ret = new CBoolValue(((CIntValue *) val)->GetInt() == m_float);
+ break;
+ case VALUE_NEQ_OPERATOR:
+ ret = new CBoolValue(((CIntValue *) val)->GetInt() != m_float);
+ break;
+ case VALUE_GRE_OPERATOR:
+ ret = new CBoolValue(((CIntValue *) val)->GetInt() > m_float);
+ break;
+ case VALUE_LES_OPERATOR:
+ ret = new CBoolValue(((CIntValue *) val)->GetInt() < m_float);
+ break;
+ case VALUE_GEQ_OPERATOR:
+ ret = new CBoolValue(((CIntValue *) val)->GetInt() >= m_float);
+ break;
+ case VALUE_LEQ_OPERATOR:
+ ret = new CBoolValue(((CIntValue *) val)->GetInt() <= m_float);
+ break;
+ default:
+ ret = new CErrorValue("illegal operator. please send a bug report.");
+ break;
+ }
+ break;
+ }
+ case VALUE_EMPTY_TYPE:
+ case VALUE_FLOAT_TYPE:
+ {
+ switch (op)
+ {
+ case VALUE_ADD_OPERATOR:
+ ret = new CFloatValue(((CFloatValue *) val)->GetFloat() + m_float);
+ break;
+ case VALUE_SUB_OPERATOR:
+ ret = new CFloatValue(((CFloatValue *) val)->GetFloat() - m_float);
+ break;
+ case VALUE_MUL_OPERATOR:
+ ret = new CFloatValue(((CFloatValue *) val)->GetFloat() * m_float);
+ break;
+ case VALUE_DIV_OPERATOR:
+ if (m_float == 0)
+ ret = new CErrorValue("Division by zero");
+ else
+ ret = new CFloatValue (((CFloatValue *) val)->GetFloat() / m_float);
+ break;
+ case VALUE_EQL_OPERATOR:
+ ret = new CBoolValue(((CFloatValue *) val)->GetFloat() == m_float);
+ break;
+ case VALUE_NEQ_OPERATOR:
+ ret = new CBoolValue(((CFloatValue *) val)->GetFloat() != m_float);
+ break;
+ case VALUE_GRE_OPERATOR:
+ ret = new CBoolValue(((CFloatValue *) val)->GetFloat() > m_float);
+ break;
+ case VALUE_LES_OPERATOR:
+ ret = new CBoolValue(((CFloatValue *) val)->GetFloat() < m_float);
+ break;
+ case VALUE_GEQ_OPERATOR:
+ ret = new CBoolValue(((CFloatValue *) val)->GetFloat() >= m_float);
+ break;
+ case VALUE_LEQ_OPERATOR:
+ ret = new CBoolValue(((CFloatValue *) val)->GetFloat() <= m_float);
+ break;
+ case VALUE_NEG_OPERATOR:
+ ret = new CFloatValue (-m_float);
+ break;
+ case VALUE_POS_OPERATOR:
+ ret = new CFloatValue (m_float);
+ break;
+
+ default:
+ ret = new CErrorValue("illegal operator. please send a bug report.");
+ break;
+ }
+ break;
+ }
+ case VALUE_STRING_TYPE:
+ {
+ switch(op)
+ {
+ case VALUE_ADD_OPERATOR:
+ ret = new CStringValue(val->GetText() + GetText(),"");
+ break;
+ case VALUE_EQL_OPERATOR:
+ case VALUE_NEQ_OPERATOR:
+ case VALUE_GRE_OPERATOR:
+ case VALUE_LES_OPERATOR:
+ case VALUE_GEQ_OPERATOR:
+ case VALUE_LEQ_OPERATOR:
+ ret = new CErrorValue("[Cannot compare string with float]" + op2str(op) + GetText());
+ break;
+ default:
+ ret = new CErrorValue("[operator not allowed on strings]" + op2str(op) + GetText());
+ break;
+ }
+ break;
+ }
+ case VALUE_BOOL_TYPE:
+ ret = new CErrorValue("[operator not valid on boolean and float]" + op2str(op) + GetText());
+ break;
+ case VALUE_ERROR_TYPE:
+ ret = new CErrorValue(val->GetText() + op2str(op) + GetText());
+ break;
+ default:
+ ret = new CErrorValue("illegal type. contact your dealer (if any)");
+ break;
+ }
+ return ret;
+}
+
+
+
+void CFloatValue::SetFloat(float fl)
+{
+ m_float = fl;
+ SetModified(true);
+}
+
+
+
+float CFloatValue::GetFloat()
+/*
+pre:
+ret: the float stored in the object
+*/
+{
+ return m_float;
+}
+
+
+
+float CFloatValue::GetNumber()
+{
+ return m_float;
+}
+
+
+
+void CFloatValue::SetValue(CValue* newval)
+{
+ m_float = newval->GetNumber();
+ SetModified(true);
+}
+
+
+
+const STR_String & CFloatValue::GetText()
+{
+ if (!m_pstrRep)
+ m_pstrRep = new STR_String();
+
+ m_pstrRep->Format("%f",m_float);
+ return *m_pstrRep;
+}
+
+
+
+CValue* CFloatValue::GetReplica()
+{
+ CFloatValue* replica = new CFloatValue(*this);
+ replica->m_pstrRep = NULL;
+ CValue::AddDataToReplica(replica);
+
+ return replica;
+}
+
+
+
+PyObject* CFloatValue::ConvertValueToPython()
+{
+ return PyFloat_FromDouble(m_float);
+}
+
diff --git a/source/gameengine/Expressions/FloatValue.h b/source/gameengine/Expressions/FloatValue.h
new file mode 100644
index 00000000000..4dce35ebfa0
--- /dev/null
+++ b/source/gameengine/Expressions/FloatValue.h
@@ -0,0 +1,48 @@
+/*
+ * FloatValue.h: interface for the CFloatValue class.
+ * $Id$
+ * Copyright (c) 1996-2000 Erwin Coumans <coockie@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. Erwin Coumans makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ */
+#if !defined _FLOATVALUE_H
+#define _FLOATVALUE_H
+
+#include "Value.h"
+
+
+class CFloatValue : public CPropValue
+{
+ //PLUGIN_DECLARE_SERIAL (CFloatValue,CValue)
+public:
+ CFloatValue();
+ CFloatValue(float fl);
+ CFloatValue(float fl,STR_String name,AllocationTYPE alloctype=CValue::HEAPVALUE);
+
+ virtual const STR_String & GetText();
+
+ void Configure(CValue* menuvalue);
+ virtual float GetNumber();
+ virtual void SetValue(CValue* newval);
+ float GetFloat();
+ void SetFloat(float fl);
+ virtual ~CFloatValue();
+ virtual CValue* GetReplica();
+ virtual CValue* Calc(VALUE_OPERATOR op, CValue *val);
+ virtual CValue* CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val);
+ virtual PyObject* ConvertValueToPython();
+
+protected:
+ float m_float;
+ STR_String* m_pstrRep;
+
+};
+
+#endif // !defined _FLOATVALUE_H
diff --git a/source/gameengine/Expressions/IdentifierExpr.cpp b/source/gameengine/Expressions/IdentifierExpr.cpp
new file mode 100644
index 00000000000..ff517aa7636
--- /dev/null
+++ b/source/gameengine/Expressions/IdentifierExpr.cpp
@@ -0,0 +1,103 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "IdentifierExpr.h"
+
+
+CIdentifierExpr::CIdentifierExpr(const STR_String& identifier,CValue* id_context)
+:m_identifier(identifier)
+{
+ if (id_context)
+ m_idContext = id_context->AddRef();
+ else
+ m_idContext=NULL;
+}
+
+
+CIdentifierExpr::~CIdentifierExpr()
+{
+ if (m_idContext)
+ m_idContext->Release();
+}
+
+
+
+CValue* CIdentifierExpr::Calculate()
+{
+ CValue* result = NULL;
+ if (m_idContext)
+ result = m_idContext->FindIdentifier(m_identifier);
+
+ return result;
+}
+
+
+
+bool CIdentifierExpr::MergeExpression(CExpression* otherexpr)
+{
+ return false;
+}
+
+
+
+unsigned char CIdentifierExpr::GetExpressionID()
+{
+ return CIDENTIFIEREXPRESSIONID;
+}
+
+
+
+bool CIdentifierExpr::NeedsRecalculated()
+{
+ return true;
+}
+
+
+
+CExpression* CIdentifierExpr::CheckLink(std::vector<CBrokenLinkInfo*>& brokenlinks)
+{
+ assertd(false); // not implemented yet
+ return NULL;
+}
+
+
+
+void CIdentifierExpr::ClearModified()
+{
+ assertd(false); // not implemented yet
+}
+
+
+
+void CIdentifierExpr::BroadcastOperators(VALUE_OPERATOR op)
+{
+ assertd(false); // not implemented yet
+} \ No newline at end of file
diff --git a/source/gameengine/Expressions/IdentifierExpr.h b/source/gameengine/Expressions/IdentifierExpr.h
new file mode 100644
index 00000000000..dbffe7c02bc
--- /dev/null
+++ b/source/gameengine/Expressions/IdentifierExpr.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 __IDENTIFIER_EXPR
+#define __IDENTIFIER_EXPR
+
+#include "Expression.h"
+
+class CIdentifierExpr : public CExpression
+{
+ CValue* m_idContext;
+ STR_String m_identifier;
+public:
+ CIdentifierExpr(const STR_String& identifier,CValue* id_context);
+ virtual ~CIdentifierExpr();
+
+ virtual CValue* Calculate();
+ virtual bool MergeExpression(CExpression* otherexpr);
+ virtual unsigned char GetExpressionID();
+ virtual bool NeedsRecalculated();
+ virtual CExpression* CheckLink(std::vector<CBrokenLinkInfo*>& brokenlinks);
+ virtual void ClearModified();
+ virtual void BroadcastOperators(VALUE_OPERATOR op);
+};
+
+#endif //__IDENTIFIER_EXPR
+
diff --git a/source/gameengine/Expressions/IfExpr.cpp b/source/gameengine/Expressions/IfExpr.cpp
new file mode 100644
index 00000000000..bcb365b87cc
--- /dev/null
+++ b/source/gameengine/Expressions/IfExpr.cpp
@@ -0,0 +1,141 @@
+// IfExpr.cpp: implementation of the CIfExpr class.
+/*
+ * Copyright (c) 1996-2000 Erwin Coumans <coockie@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. Erwin Coumans makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ */
+
+#include "IfExpr.h"
+#include "EmptyValue.h"
+#include "ErrorValue.h"
+
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+
+CIfExpr::CIfExpr()
+{
+}
+
+
+
+CIfExpr::CIfExpr(CExpression *guard, CExpression *e1, CExpression *e2)
+/*
+pre:
+effect: constructs an CifExpr-object corresponding to IF(guard, e1, e2)
+*/
+{
+ m_guard = guard;
+ m_e1 = e1;
+ m_e2 = e2;
+}
+
+
+
+CIfExpr::~CIfExpr()
+/*
+pre:
+effect: dereferences the object
+*/
+{
+ if (m_guard)
+ m_guard->Release();
+
+ if (m_e1)
+ m_e1->Release();
+
+ if (m_e2)
+ m_e2->Release();
+}
+
+
+
+CValue* CIfExpr::Calculate()
+/*
+pre:
+ret: a new object containing the value of m_e1 if m_guard is a boolean TRUE
+ a new object containing the value of m_e2 if m_guard is a boolean FALSE
+ an new errorvalue if m_guard is not a boolean
+*/
+{
+ CValue *guardval;
+ guardval = m_guard->Calculate();
+ STR_String text = guardval->GetText();
+ guardval->Release();
+
+ if (text == STR_String("TRUE"))
+ {
+ return m_e1->Calculate();
+ }
+ else if (text == STR_String("FALSE"))
+ {
+ return m_e2->Calculate();
+ }
+ else
+ {
+ return new CErrorValue("Guard should be of boolean type");
+ }
+}
+
+
+
+bool CIfExpr::MergeExpression(CExpression *otherexpr)
+{
+ assertd(false);
+ return false;
+}
+
+
+
+bool CIfExpr::IsInside(float x,float y,float z,bool bBorderInclude)
+{
+ assertd(false);
+ return false;
+}
+
+
+
+bool CIfExpr::NeedsRecalculated()
+{
+ return (m_guard->NeedsRecalculated() ||
+ m_e1->NeedsRecalculated() ||
+ m_e2->NeedsRecalculated());
+}
+
+
+
+CExpression* CIfExpr::CheckLink(std::vector<CBrokenLinkInfo*>& brokenlinks)
+{
+ assertd(false);
+ return NULL;
+}
+
+
+
+void CIfExpr::ClearModified()
+{
+ assertd(false);
+}
+
+
+
+void CIfExpr::BroadcastOperators(VALUE_OPERATOR op)
+{
+ assertd(false);
+}
+
+
+
+unsigned char CIfExpr::GetExpressionID()
+{
+ return CIFEXPRESSIONID;
+} \ No newline at end of file
diff --git a/source/gameengine/Expressions/IfExpr.h b/source/gameengine/Expressions/IfExpr.h
new file mode 100644
index 00000000000..192edfe8fee
--- /dev/null
+++ b/source/gameengine/Expressions/IfExpr.h
@@ -0,0 +1,49 @@
+/*
+ * IfExpr.h: interface for the CIfExpr class.
+ * $Id$
+ * Copyright (c) 1996-2000 Erwin Coumans <coockie@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. Erwin Coumans makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ */
+#if !defined(AFX_IFEXPR_H__1F691841_C5C7_11D1_A863_0000B4542BD8__INCLUDED_)
+#define AFX_IFEXPR_H__1F691841_C5C7_11D1_A863_0000B4542BD8__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+
+#include "Expression.h"
+
+class CIfExpr : public CExpression
+{
+ //PLUGIN_DECLARE_SERIAL_EXPRESSION (CIfExpr,CExpression)
+
+private:
+ CExpression *m_guard, *m_e1, *m_e2;
+
+public:
+ virtual bool MergeExpression(CExpression* otherexpr);
+ CIfExpr(CExpression *guard, CExpression *e1, CExpression *e2);
+ CIfExpr();
+
+ virtual unsigned char GetExpressionID();
+ virtual ~CIfExpr();
+ virtual CValue* Calculate();
+
+ virtual bool IsInside(float x,float y,float z,bool bBorderInclude=true);
+ virtual bool NeedsRecalculated();
+
+
+ virtual CExpression* CheckLink(std::vector<CBrokenLinkInfo*>& brokenlinks);
+ virtual void ClearModified();
+ virtual void BroadcastOperators(VALUE_OPERATOR op);
+};
+
+#endif // !defined(AFX_IFEXPR_H__1F691841_C5C7_11D1_A863_0000B4542BD8__INCLUDED_)
diff --git a/source/gameengine/Expressions/InputParser.cpp b/source/gameengine/Expressions/InputParser.cpp
new file mode 100644
index 00000000000..efb5e277737
--- /dev/null
+++ b/source/gameengine/Expressions/InputParser.cpp
@@ -0,0 +1,648 @@
+// Parser.cpp: implementation of the CParser class.
+/*
+ * Copyright (c) 1996-2000 Erwin Coumans <coockie@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. Erwin Coumans makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ */
+
+#include <stdlib.h>
+
+#include "Value.h"
+#include "InputParser.h"
+#include "ErrorValue.h"
+#include "IntValue.h"
+#include "StringValue.h"
+#include "FloatValue.h"
+#include "BoolValue.h"
+#include "EmptyValue.h"
+#include "ConstExpr.h"
+#include "Operator2Expr.h"
+#include "Operator1Expr.h"
+#include "IdentifierExpr.h"
+
+// this is disable at the moment, I expected a memleak from it, but the error-cleanup was the reason
+// well, looks we don't need it anyway, until maybe the Curved Surfaces are integrated into CSG
+// cool things like (IF(LOD==1,CCurvedValue,IF(LOD==2,CCurvedValue2)) etc...
+#include "IfExpr.h"
+
+
+#define NUM_PRIORITY 6
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CParser::CParser() : m_identifierContext(NULL)
+{
+}
+
+
+
+CParser::~CParser()
+{
+ if (m_identifierContext)
+ m_identifierContext->Release();
+}
+
+
+
+void CParser::ScanError(STR_String str)
+{
+ // sets the global variable errmsg to an errormessage with
+ // contents str, appending if it already exists
+ // AfxMessageBox("Parse Error:"+str,MB_ICONERROR);
+ if (errmsg)
+ errmsg = new COperator2Expr(VALUE_ADD_OPERATOR, errmsg, Error(str));
+ else
+ errmsg = Error(str);
+
+ sym = errorsym;
+}
+
+
+
+CExpression* CParser::Error(STR_String str)
+{
+ // makes and returns a new CConstExpr filled with an CErrorValue
+ // with string str
+ // AfxMessageBox("Error:"+str,MB_ICONERROR);
+ return new CConstExpr(new CErrorValue(str));
+}
+
+
+
+void CParser::NextCh()
+{
+ // sets the global variable ch to the next character, if it exists
+ // and increases the global variable chcount
+ chcount++;
+
+ if (chcount < text.Length())
+ ch = text[chcount];
+ else
+ ch = 0x00;
+}
+
+
+
+void CParser::TermChar(char c)
+{
+ // generates an error if the next char isn't the specified char c,
+ // otherwise, skip the char
+ if(ch == c)
+ {
+ NextCh();
+ }
+ else
+ {
+ STR_String str;
+ str.Format("Warning: %c expected\ncontinuing without it", c);
+ trace(str);
+ }
+}
+
+
+
+void CParser::DigRep()
+{
+ // changes the current character to the first character that
+ // isn't a decimal
+ while ((ch >= '0') && (ch <= '9'))
+ NextCh();
+}
+
+
+
+void CParser::CharRep()
+{
+ // changes the current character to the first character that
+ // isn't an alphanumeric character
+ while (((ch >= '0') && (ch <= '9'))
+ || ((ch >= 'a') && (ch <= 'z'))
+ || ((ch >= 'A') && (ch <= 'Z'))
+ || (ch == '.') || (ch == '_'))
+ NextCh();
+}
+
+
+
+void CParser::GrabString(int start)
+{
+ // puts part of the input string into the global variable
+ // const_as_string, from position start, to position chchount
+ const_as_string = text.Mid(start, chcount-start);
+}
+
+
+
+void CParser::NextSym()
+{
+ // sets the global variable sym to the next symbol, and
+ // if it is an operator
+ // sets the global variable opkind to the kind of operator
+ // if it is a constant
+ // sets the global variable constkind to the kind of operator
+ // if it is a reference to a cell
+ // sets the global variable cellcoord to the kind of operator
+
+ errmsg = NULL;
+ while(ch == ' ' || ch == 0x9)
+ NextCh();
+
+ switch(ch)
+ {
+ case '(':
+ sym = lbracksym; NextCh();
+ break;
+ case ')':
+ sym = rbracksym; NextCh();
+ break;
+ case ',':
+ sym = commasym; NextCh();
+ break;
+ case '+' :
+ sym = opsym; opkind = OPplus; NextCh();
+ break;
+ case '-' :
+ sym = opsym; opkind = OPminus; NextCh();
+ break;
+ case '*' :
+ sym = opsym; opkind = OPtimes; NextCh();
+ break;
+ case '/' :
+ sym = opsym; opkind = OPdivide; NextCh();
+ break;
+ case '&' :
+ sym = opsym; opkind = OPand; NextCh(); TermChar('&');
+ break;
+ case '|' :
+ sym = opsym; opkind = OPor; NextCh(); TermChar('|');
+ break;
+ case '=' :
+ sym = opsym; opkind = OPequal; NextCh(); TermChar('=');
+ break;
+ case '!' :
+ sym = opsym;
+ NextCh();
+ if (ch == '=')
+ {
+ opkind = OPunequal;
+ NextCh();
+ }
+ else
+ {
+ opkind = OPnot;
+ }
+ break;
+ case '>':
+ sym = opsym;
+ NextCh();
+ if (ch == '=')
+ {
+ opkind = OPgreaterequal;
+ NextCh();
+ }
+ else
+ {
+ opkind = OPgreater;
+ }
+ break;
+ case '<':
+ sym = opsym;
+ NextCh();
+ if (ch == '=') {
+ opkind = OPlessequal;
+ NextCh();
+ } else {
+ opkind = OPless;
+ }
+ break;
+ case '\"' : {
+ int start;
+ sym = constsym;
+ constkind = stringtype;
+ NextCh();
+ start = chcount;
+ while ((ch != '\"') && (ch != 0x0))
+ NextCh();
+ GrabString(start);
+ TermChar('\"'); // check for eol before '\"'
+ break;
+ }
+ case 0x0: sym = eolsym; break;
+ default:
+ {
+ int start;
+ start = chcount;
+ DigRep();
+ if ((start != chcount) || (ch == '.')) { // number
+ sym = constsym;
+ if (ch == '.') {
+ constkind = floattype;
+ NextCh();
+ DigRep();
+ }
+ else constkind = inttype;
+ if ((ch == 'e') || (ch == 'E')) {
+ int mark;
+ constkind = floattype;
+ NextCh();
+ if ((ch == '+') || (ch == '-')) NextCh();
+ mark = chcount;
+ DigRep();
+ if (mark == chcount) {
+ ScanError("Number expected after 'E'");
+ return;
+ }
+ }
+ GrabString(start);
+ } else if (((ch >= 'a') && (ch <= 'z'))
+ || ((ch >= 'A') && (ch <= 'Z')))
+ { // reserved word?
+ int start;
+ STR_String funstr;
+ start = chcount;
+ CharRep();
+ GrabString(start);
+ funstr = const_as_string;
+ funstr.Upper();
+ if (funstr == STR_String("SUM")) {
+ sym = sumsym;
+ }
+ else if (funstr == STR_String("NOT")) {
+ sym = opsym;
+ opkind = OPnot;
+ }
+ else if (funstr == STR_String("AND")) {
+ sym = opsym; opkind = OPand;
+ }
+ else if (funstr == STR_String("OR")) {
+ sym = opsym; opkind = OPor;
+ }
+ else if (funstr == STR_String("IF")) {
+ sym = ifsym;
+ } else if (funstr == STR_String("WHOMADE")) {
+ sym = whocodedsym;
+ } else if (funstr == STR_String("FALSE")) {
+ sym = constsym; constkind = booltype; boolvalue = false;
+ } else if (funstr == STR_String("TRUE")) {
+ sym = constsym; constkind = booltype; boolvalue = true;
+ } else {
+ sym = idsym;
+ //STR_String str;
+ //str.Format("'%s' makes no sense here", (const char*)funstr);
+ //ScanError(str);
+ }
+ } else { // unknown symbol
+ STR_String str;
+ str.Format("Unexpected character '%c'", ch);
+ NextCh();
+ ScanError(str);
+ return;
+ }
+ }
+ }
+}
+
+int CParser::MakeInt() {
+ // returns the integer representation of the value in the global
+ // variable const_as_string
+ // pre: const_as_string contains only numercal chars
+ return atoi(const_as_string);
+}
+
+STR_String CParser::Symbol2Str(int s) {
+ // returns a string representation of of symbol s,
+ // for use in Term when generating an error
+ switch(s) {
+ case errorsym: return "error";
+ case lbracksym: return "(";
+ case rbracksym: return ")";
+ case commasym: return ",";
+ case opsym: return "operator";
+ case constsym: return "constant";
+ case sumsym: return "SUM";
+ case ifsym: return "IF";
+ case whocodedsym: return "WHOMADE";
+ case eolsym: return "end of line";
+ case idsym: return "identifier";
+ default: return "unknown"; // should not happen
+ }
+}
+
+void CParser::Term(int s) {
+ // generates an error if the next symbol isn't the specified symbol s
+ // otherwise, skip the symbol
+ if(s == sym) NextSym();
+ else {
+ STR_String msg;
+ msg.Format("Warning: " + Symbol2Str(s) + " expected\ncontinuing without it");
+
+// AfxMessageBox(msg,MB_ICONERROR);
+
+ trace(msg);
+ }
+}
+
+int CParser::Priority(int optorkind) {
+ // returns the priority of an operator
+ // higher number means higher priority
+ switch(optorkind) {
+ case OPor: return 1;
+ case OPand: return 2;
+ case OPgreater:
+ case OPless:
+ case OPgreaterequal:
+ case OPlessequal:
+ case OPequal:
+ case OPunequal: return 3;
+ case OPplus:
+ case OPminus: return 4;
+ case OPtimes:
+ case OPdivide: return 5;
+ }
+ assert(false);
+ return 0; // should not happen
+}
+
+CExpression *CParser::Ex(int i) {
+ // parses an expression in the imput, starting at priority i, and
+ // returns an CExpression, containing the parsed input
+ CExpression *e1 = NULL, *e2 = NULL;
+ int opkind2;
+
+ if (i < NUM_PRIORITY) {
+ e1 = Ex(i + 1);
+ while ((sym == opsym) && (Priority(opkind) == i)) {
+ opkind2 = opkind;
+ NextSym();
+ e2 = Ex(i + 1);
+ switch(opkind2) {
+ case OPplus: e1 = new COperator2Expr(VALUE_ADD_OPERATOR,e1, e2); break;
+ case OPminus: e1 = new COperator2Expr(VALUE_SUB_OPERATOR,e1, e2); break;
+ case OPtimes: e1 = new COperator2Expr(VALUE_MUL_OPERATOR,e1, e2); break;
+ case OPdivide: e1 = new COperator2Expr(VALUE_DIV_OPERATOR,e1, e2); break;
+ case OPand: e1 = new COperator2Expr(VALUE_AND_OPERATOR,e1, e2); break;
+ case OPor: e1 = new COperator2Expr(VALUE_OR_OPERATOR,e1, e2); break;
+ case OPequal: e1 = new COperator2Expr(VALUE_EQL_OPERATOR,e1, e2); break;
+ case OPunequal: e1 = new COperator2Expr(VALUE_NEQ_OPERATOR,e1, e2); break;
+ case OPgreater: e1 = new COperator2Expr(VALUE_GRE_OPERATOR,e1, e2); break;
+ case OPless: e1 = new COperator2Expr(VALUE_LES_OPERATOR,e1, e2); break;
+ case OPgreaterequal: e1 = new COperator2Expr(VALUE_GEQ_OPERATOR,e1, e2); break;
+ case OPlessequal: e1 = new COperator2Expr(VALUE_LEQ_OPERATOR,e1, e2); break;
+ default: assert(false); break; // should not happen
+ }
+ }
+ } else if (i == NUM_PRIORITY) {
+ if ((sym == opsym)
+ && ( (opkind == OPminus) || (opkind == OPnot) || (opkind == OPplus) )
+ )
+ {
+ NextSym();
+ switch(opkind) {
+ /* +1 is also a valid number! */
+ case OPplus: e1 = new COperator1Expr(VALUE_POS_OPERATOR, Ex(NUM_PRIORITY)); break;
+ case OPminus: e1 = new COperator1Expr(VALUE_NEG_OPERATOR, Ex(NUM_PRIORITY)); break;
+ case OPnot: e1 = new COperator1Expr(VALUE_NOT_OPERATOR, Ex(NUM_PRIORITY)); break;
+ default: {
+ // should not happen
+ e1 = Error("operator +, - or ! expected");
+ }
+ }
+ }
+ else {
+ switch(sym) {
+ case constsym: {
+ switch(constkind) {
+ case booltype:
+ e1 = new CConstExpr(new CBoolValue(boolvalue));
+ break;
+ case inttype:
+ {
+ int temp;
+ temp = atoi(const_as_string);
+ e1 = new CConstExpr(new CIntValue(temp));
+ break;
+ }
+ case floattype:
+ {
+ double temp;
+ temp = atof(const_as_string);
+ e1 = new CConstExpr(new CFloatValue(temp));
+ break;
+ }
+ case stringtype:
+ e1 = new CConstExpr(new CStringValue(const_as_string,""));
+ break;
+ default :
+ assert(false);
+ break;
+ }
+ NextSym();
+ break;
+ }
+ case lbracksym:
+ NextSym();
+ e1 = Ex(1);
+ Term(rbracksym);
+ break;
+ case ifsym:
+ {
+ CExpression *e3;
+ NextSym();
+ Term(lbracksym);
+ e1 = Ex(1);
+ Term(commasym);
+ e2 = Ex(1);
+ if (sym == commasym) {
+ NextSym();
+ e3 = Ex(1);
+ } else {
+ e3 = new CConstExpr(new CEmptyValue());
+ }
+ Term(rbracksym);
+ e1 = new CIfExpr(e1, e2, e3);
+ break;
+ }
+ case idsym:
+ {
+ e1 = new CIdentifierExpr(const_as_string,m_identifierContext);
+ NextSym();
+
+ break;
+ }
+ case errorsym:
+ {
+ assert(!e1);
+ STR_String errtext="[no info]";
+ if (errmsg)
+ {
+ CValue* errmsgval = errmsg->Calculate();
+ errtext=errmsgval->GetText();
+ errmsgval->Release();
+
+ //e1 = Error(errmsg->Calculate()->GetText());//new CConstExpr(errmsg->Calculate());
+
+ if ( !(errmsg->Release()) )
+ {
+ errmsg=NULL;
+ } else {
+ // does this happen ?
+ assert ("does this happen");
+ }
+ }
+ e1 = Error(errtext);
+
+ break;
+ }
+ default:
+ NextSym();
+ //return Error("Expression expected");
+ assert(!e1);
+ e1 = Error("Expression expected");
+ }
+ }
+ }
+ return e1;
+}
+
+CExpression *CParser::Expr() {
+ // parses an expression in the imput, and
+ // returns an CExpression, containing the parsed input
+ return Ex(1);
+}
+
+CExpression* CParser::ProcessText
+(STR_String intext) {
+
+ // and parses the string in intext and returns it.
+
+
+ CExpression* expr;
+ text = intext;
+
+
+ chcount = 0;
+ if (text.Length() == 0) {
+ return NULL;
+ }
+
+ ch = text[0];
+ /*if (ch != '=') {
+ expr = new CConstExpr(new CStringValue(text));
+ *dependant = deplist;
+ return expr;
+ } else
+ */
+ // NextCh();
+ NextSym();
+ expr = Expr();
+ if (sym != eolsym) {
+ CExpression* oldexpr = expr;
+ expr = new COperator2Expr(VALUE_ADD_OPERATOR,
+ oldexpr, Error(STR_String("Extra characters after expression")));//new CConstExpr(new CErrorValue("Extra characters after expression")));
+ }
+ if (errmsg)
+ errmsg->Release();
+
+ return expr;
+}
+
+
+
+float CParser::GetFloat(STR_String txt)
+{
+ // returns parsed text into a float
+ // empty string returns -1
+
+// AfxMessageBox("parsed string="+txt);
+ CValue* val=NULL;
+ float result=-1;
+// String tmpstr;
+
+ CExpression* expr = ProcessText(txt);
+ if (expr) {
+ val = expr->Calculate();
+ result=val->GetNumber();
+
+
+
+ val->Release();
+ expr->Release();
+ }
+// tmpstr.Format("parseresult=%g",result);
+// AfxMessageBox(tmpstr);
+ return result;
+}
+
+CValue* CParser::GetValue(STR_String txt, bool bFallbackToText)
+{
+ // returns parsed text into a value,
+ // empty string returns NULL value !
+ // if bFallbackToText then unparsed stuff is put into text
+
+ CValue* result=NULL;
+ CExpression* expr = ProcessText(txt);
+ if (expr) {
+ result = expr->Calculate();
+ expr->Release();
+ }
+ if (result)
+ {
+ // if the parsed stuff lead to an errorvalue, don't return errors, just NULL
+ if (result->IsError()) {
+ result->Release();
+ result=NULL;
+ if (bFallbackToText) {
+ if (txt.Length()>0)
+ {
+ result = new CStringValue(txt,"");
+ }
+ }
+ }
+ }
+ return result;
+}
+
+void CParser::SetContext(CValue* context)
+{
+ if (m_identifierContext)
+ {
+ m_identifierContext->Release();
+ }
+ m_identifierContext = context;
+}
+
+
+
+
+PyObject* CParserPyMake(PyObject* ignored,PyObject* args)
+{
+ char* txt;
+ Py_Try(PyArg_ParseTuple(args,"s",&txt));
+ CParser parser;
+ CExpression* expr = parser.ProcessText(txt);
+ CValue* val = expr->Calculate();
+ expr->Release();
+ return val;
+}
+
+static PyMethodDef CParserMethods[] =
+{
+ { "calc", CParserPyMake , Py_NEWARGS},
+ { NULL,NULL} // Sentinel
+};
+
+extern "C" {
+ void initExpressionModule(void)
+ {
+ Py_InitModule("Expression",CParserMethods);
+ }
+}
+
diff --git a/source/gameengine/Expressions/InputParser.h b/source/gameengine/Expressions/InputParser.h
new file mode 100644
index 00000000000..43832f9c350
--- /dev/null
+++ b/source/gameengine/Expressions/InputParser.h
@@ -0,0 +1,105 @@
+/*
+ * Parser.h: interface for the CParser class.
+ * Eindhoven University of Technology 1997
+ * OOPS team (Serge vd Boom, Erwin Coumans, Tom Geelen, Wynke Stuylemeier)
+ * $Id$
+ * Copyright (c) 1996-2000 Erwin Coumans <coockie@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. Erwin Coumans makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ */
+#ifndef __INPUTPARSER_H__
+#define __INPUTPARSER_H__
+
+class CParser;
+#include "Expression.h"
+
+
+class CParser
+{
+public:
+ CParser();
+ virtual ~CParser();
+
+ float GetFloat(STR_String txt);
+ CValue* GetValue(STR_String txt, bool bFallbackToText=false);
+ CExpression* ProcessText(STR_String intext);
+ void SetContext(CValue* context);
+
+private:
+ enum symbols {
+ errorsym,
+ lbracksym,
+ rbracksym,
+ cellsym,
+ commasym,
+ opsym,
+ constsym,
+ sumsym,
+ ifsym,
+ whocodedsym,
+ eolsym,
+ idsym
+ }; // all kinds of symbols
+
+ enum optype {
+ OPplus,
+ OPminus,
+ OPtimes,
+ OPdivide,
+ OPand,
+ OPor,
+ OPequal,
+ OPunequal,
+ OPgreater,
+ OPless,
+ OPgreaterequal,
+ OPlessequal,
+ OPnot
+ }; // all kinds of operators
+
+ enum consttype {
+ booltype,
+ inttype,
+ floattype,
+ stringtype
+ }; // all kinds of constants
+
+ int sym, // current symbol
+ opkind, // kind of operator, if symbol is an operator
+ constkind; // kind of operator, if symbol is a constant
+
+ char ch; // current character
+ int chcount; // index to character in input string
+ CExpression *errmsg; // contains a errormessage, if scanner error
+
+ STR_String text, // contains a copy of the original text
+ const_as_string; // string representation of the symbol, if symbol is a constant
+ bool boolvalue; // value of the boolean, if symbol is a constant of type boolean
+ CValue* m_identifierContext;// context in which identifiers are looked up
+
+
+ void ScanError(STR_String str);
+ CExpression* Error(STR_String str);
+ void NextCh();
+ void TermChar(char c);
+ void DigRep();
+ void CharRep();
+ void GrabString(int start);
+ void NextSym();
+ int MakeInt();
+ STR_String Symbol2Str(int s);
+ void Term(int s);
+ int Priority(int optor);
+ CExpression *Ex(int i);
+ CExpression *Expr();
+
+};
+
+#endif
diff --git a/source/gameengine/Expressions/IntValue.cpp b/source/gameengine/Expressions/IntValue.cpp
new file mode 100644
index 00000000000..591fe76cd48
--- /dev/null
+++ b/source/gameengine/Expressions/IntValue.cpp
@@ -0,0 +1,325 @@
+// IntValue.cpp: implementation of the CIntValue class.
+/*
+* Copyright (c) 1996-2000 Erwin Coumans <coockie@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. Erwin Coumans makes no
+* representations about the suitability of this software for any
+* purpose. It is provided "as is" without express or implied warranty.
+*
+*/
+
+
+#include "IntValue.h"
+#include "ErrorValue.h"
+#include "FloatValue.h"
+#include "BoolValue.h"
+#include "StringValue.h"
+#include "VoidValue.h"
+//#include "FactoryManager.h"
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CIntValue::CIntValue()
+/*
+pre: false
+effect: constructs a new CIntValue
+*/
+{
+
+#ifdef _DEBUG_
+ m_textval = "Int illegal constructor";
+#endif
+ m_pstrRep=NULL;
+}
+
+
+
+CIntValue::CIntValue(int innie)
+/*
+pre:
+effect: constructs a new CIntValue containing int innie
+*/
+{
+ m_int = innie;
+ m_pstrRep=NULL;
+}
+
+
+
+CIntValue::CIntValue(int innie,STR_String name,AllocationTYPE alloctype)
+{
+ m_int = innie;
+ SetName(name);
+
+ if (alloctype==CValue::STACKVALUE)
+ {
+ CValue::DisableRefCount();
+ }
+ m_pstrRep=NULL;
+
+}
+
+
+
+CIntValue::~CIntValue()
+/*
+pre:
+effect: deletes the object
+*/
+{
+ if (m_pstrRep)
+ delete m_pstrRep;
+}
+
+
+
+CValue* CIntValue::Calc(VALUE_OPERATOR op, CValue *val)
+/*
+pre:
+ret: a new object containing the result of applying operator op to this
+object and val
+*/
+{
+ //return val->CalcInt(op, this);
+ switch (op) {
+ case VALUE_POS_OPERATOR:
+ return new CIntValue (m_int);
+ break;
+ case VALUE_NEG_OPERATOR:
+ return new CIntValue (-m_int);
+ break;
+ case VALUE_NOT_OPERATOR:
+ return new CErrorValue (op2str(op) + "only allowed on booleans");
+ break;
+ case VALUE_AND_OPERATOR:
+ case VALUE_OR_OPERATOR:
+ return new CErrorValue(val->GetText() + op2str(op) + "only allowed on booleans");
+ break;
+ default:
+ return val->CalcFinal(VALUE_INT_TYPE, op, this);
+ break;
+ }
+}
+
+
+
+CValue* CIntValue::CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val)
+/*
+pre: the type of val is dtype
+ret: a new object containing the result of applying operator op to val and
+this object
+*/
+{
+ CValue *ret;
+
+ switch(dtype) {
+ case VALUE_EMPTY_TYPE:
+ case VALUE_INT_TYPE:
+ {
+ switch (op) {
+ case VALUE_ADD_OPERATOR:
+ ret = new CIntValue (((CIntValue *) val)->GetInt() + m_int);
+ break;
+ case VALUE_SUB_OPERATOR:
+ ret = new CIntValue (((CIntValue *) val)->GetInt() - m_int);
+ break;
+ case VALUE_MUL_OPERATOR:
+ ret = new CIntValue (((CIntValue *) val)->GetInt() * m_int);
+ break;
+ case VALUE_DIV_OPERATOR:
+ if (m_int == 0)
+ {
+ if (val->GetNumber() == 0)
+ {
+ ret = new CErrorValue("Not a Number");
+ } else
+ {
+ ret = new CErrorValue("Division by zero");
+ }
+ }
+ else
+ ret = new CIntValue (((CIntValue *) val)->GetInt() / m_int);
+ break;
+ case VALUE_EQL_OPERATOR:
+ ret = new CBoolValue(((CIntValue *) val)->GetInt() == m_int);
+ break;
+ case VALUE_NEQ_OPERATOR:
+ ret = new CBoolValue(((CIntValue *) val)->GetInt() != m_int);
+ break;
+ case VALUE_GRE_OPERATOR:
+ ret = new CBoolValue(((CIntValue *) val)->GetInt() > m_int);
+ break;
+ case VALUE_LES_OPERATOR:
+ ret = new CBoolValue(((CIntValue *) val)->GetInt() < m_int);
+ break;
+ case VALUE_GEQ_OPERATOR:
+ ret = new CBoolValue(((CIntValue *) val)->GetInt() >= m_int);
+ break;
+ case VALUE_LEQ_OPERATOR:
+ ret = new CBoolValue(((CIntValue *) val)->GetInt() <= m_int);
+ break;
+ case VALUE_NEG_OPERATOR:
+ ret = new CIntValue (-m_int);
+ break;
+ case VALUE_POS_OPERATOR:
+ ret = new CIntValue (m_int);
+ break;
+ default:
+ ret = new CErrorValue("illegal operator. please send a bug report.");
+ break;
+ }
+ break;
+ }
+ case VALUE_FLOAT_TYPE:
+ {
+ switch (op) {
+ case VALUE_ADD_OPERATOR:
+ ret = new CFloatValue (((CFloatValue *) val)->GetFloat() + m_int);
+ break;
+ case VALUE_SUB_OPERATOR:
+ ret = new CFloatValue (((CFloatValue *) val)->GetFloat() - m_int);
+ break;
+ case VALUE_MUL_OPERATOR:
+ ret = new CFloatValue (((CFloatValue *) val)->GetFloat() * m_int);
+ break;
+ case VALUE_DIV_OPERATOR:
+ if (m_int == 0)
+ ret = new CErrorValue("Division by zero");
+ else
+ ret = new CFloatValue (((CFloatValue *) val)->GetFloat() / m_int);
+ break;
+ case VALUE_EQL_OPERATOR:
+ ret = new CBoolValue(((CFloatValue *) val)->GetFloat() == m_int);
+ break;
+ case VALUE_NEQ_OPERATOR:
+ ret = new CBoolValue(((CFloatValue *) val)->GetFloat() != m_int);
+ break;
+ case VALUE_GRE_OPERATOR:
+ ret = new CBoolValue(((CFloatValue *) val)->GetFloat() > m_int);
+ break;
+ case VALUE_LES_OPERATOR:
+ ret = new CBoolValue(((CFloatValue *) val)->GetFloat() < m_int);
+ break;
+ case VALUE_GEQ_OPERATOR:
+ ret = new CBoolValue(((CFloatValue *) val)->GetFloat() >= m_int);
+ break;
+ case VALUE_LEQ_OPERATOR:
+ ret = new CBoolValue(((CFloatValue *) val)->GetFloat() <= m_int);
+ break;
+ default:
+ ret = new CErrorValue("illegal operator. please send a bug report.");
+ break;
+ }
+ break;
+ }
+ case VALUE_STRING_TYPE:
+ {
+ switch(op) {
+ case VALUE_ADD_OPERATOR:
+ ret = new CStringValue(val->GetText() + GetText(),"");
+ break;
+ case VALUE_EQL_OPERATOR:
+ case VALUE_NEQ_OPERATOR:
+ case VALUE_GRE_OPERATOR:
+ case VALUE_LES_OPERATOR:
+ case VALUE_GEQ_OPERATOR:
+ case VALUE_LEQ_OPERATOR:
+ ret = new CErrorValue("[Cannot compare string with integer]" + op2str(op) + GetText());
+ break;
+ default:
+ ret = new CErrorValue("[operator not allowed on strings]" + op2str(op) + GetText());
+ break;
+ }
+ break;
+ }
+ case VALUE_BOOL_TYPE:
+ ret = new CErrorValue("[operator not valid on boolean and integer]" + op2str(op) + GetText());
+ break;
+ /*
+ case VALUE_EMPTY_TYPE:
+ {
+ switch(op) {
+
+ case VALUE_ADD_OPERATOR:
+ ret = new CIntValue (m_int);
+ break;
+ case VALUE_SUB_OPERATOR:
+ ret = new CIntValue (-m_int);
+ break;
+ default:
+ {
+ ret = new CErrorValue(op2str(op) + GetText());
+ }
+ }
+ break;
+ }
+ */
+ case VALUE_ERROR_TYPE:
+ ret = new CErrorValue(val->GetText() + op2str(op) + GetText());
+ break;
+ default:
+ ret = new CErrorValue("illegal type. contact your dealer (if any)");
+ break;
+ }
+ return ret;
+}
+
+
+
+int CIntValue::GetInt()
+/*
+pre:
+ret: the int stored in the object
+*/
+{
+ return m_int;
+}
+
+
+
+float CIntValue::GetNumber()
+{
+ return (float) m_int;
+}
+
+
+
+const STR_String & CIntValue::GetText()
+{
+ if (!m_pstrRep)
+ m_pstrRep=new STR_String();
+ m_pstrRep->Format("%d",m_int);
+
+ return *m_pstrRep;
+}
+
+
+
+CValue* CIntValue::GetReplica() {
+ CIntValue* replica = new CIntValue(*this);
+ CValue::AddDataToReplica(replica);
+ replica->m_pstrRep = NULL;
+
+ return replica;
+}
+
+
+
+void CIntValue::SetValue(CValue* newval)
+{
+ m_int = (int)newval->GetNumber();
+ SetModified(true);
+}
+
+
+
+PyObject* CIntValue::ConvertValueToPython()
+{
+ return PyInt_FromLong(m_int);
+} \ No newline at end of file
diff --git a/source/gameengine/Expressions/IntValue.h b/source/gameengine/Expressions/IntValue.h
new file mode 100644
index 00000000000..8174c863895
--- /dev/null
+++ b/source/gameengine/Expressions/IntValue.h
@@ -0,0 +1,60 @@
+/*
+ * IntValue.h: interface for the CIntValue class.
+ * $Id$
+ * Copyright (c) 1996-2000 Erwin Coumans <coockie@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. Erwin Coumans makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ */
+#if !defined _INTVALUE_H
+#define _INTVALUE_H
+
+
+#include "Value.h"
+
+
+class CIntValue : public CPropValue
+{
+ //PLUGIN_DECLARE_SERIAL (CIntValue,CValue)
+
+public:
+ virtual const STR_String& GetText();
+ virtual float GetNumber();
+
+ int GetInt();
+ CIntValue();
+ CIntValue(int innie);
+ CIntValue(int innie,
+ STR_String name,
+ AllocationTYPE alloctype=CValue::HEAPVALUE);
+
+ virtual CValue* Calc(VALUE_OPERATOR op,
+ CValue *val);
+
+ virtual CValue* CalcFinal(VALUE_DATA_TYPE dtype,
+ VALUE_OPERATOR op,
+ CValue *val);
+
+ virtual void SetValue(CValue* newval);
+
+ void Configure(CValue* menuvalue);
+ void AddConfigurationData(CValue* menuvalue);
+ virtual CValue* GetReplica();
+ virtual PyObject* ConvertValueToPython();
+
+protected:
+ virtual ~CIntValue();
+
+private:
+ int m_int;
+ STR_String* m_pstrRep;
+
+};
+
+#endif // !defined _INTVALUE_H
diff --git a/source/gameengine/Expressions/KX_HashedPtr.cpp b/source/gameengine/Expressions/KX_HashedPtr.cpp
new file mode 100644
index 00000000000..7d573ebc37d
--- /dev/null
+++ b/source/gameengine/Expressions/KX_HashedPtr.cpp
@@ -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 *****
+ */
+
+
+#include "KX_HashedPtr.h"
+
+unsigned int KX_Hash(unsigned int inDWord)
+{
+ unsigned int key = inDWord;
+ key += ~(key << 16);
+ key ^= (key >> 5);
+ key += (key << 3);
+ key ^= (key >> 13);
+ key += ~(key << 9);
+ key ^= (key >> 17);
+ return key;
+};
+
+
+
+CHashedPtr::CHashedPtr(void* val) : m_valptr(val)
+{
+}
+
+
+
+unsigned int CHashedPtr::hash() const
+{
+ return KX_Hash((unsigned int) m_valptr);
+}
diff --git a/source/gameengine/Expressions/KX_HashedPtr.h b/source/gameengine/Expressions/KX_HashedPtr.h
new file mode 100644
index 00000000000..eccd23991bc
--- /dev/null
+++ b/source/gameengine/Expressions/KX_HashedPtr.h
@@ -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 *****
+ */
+#ifndef __KX_HASHEDPTR
+#define __KX_HASHEDPTR
+
+unsigned int KX_Hash(unsigned int inDWord);
+
+
+class CHashedPtr
+{
+ void* m_valptr;
+
+public:
+ CHashedPtr(void* val);
+
+ unsigned int hash() const;
+
+ inline friend bool operator ==( const CHashedPtr & rhs,const CHashedPtr & lhs)
+ {
+ return rhs.m_valptr == lhs.m_valptr;
+ }
+};
+
+#endif //__KX_HASHEDPTR
diff --git a/source/gameengine/Expressions/ListValue.cpp b/source/gameengine/Expressions/ListValue.cpp
new file mode 100644
index 00000000000..25723350f36
--- /dev/null
+++ b/source/gameengine/Expressions/ListValue.cpp
@@ -0,0 +1,536 @@
+// ListValue.cpp: implementation of the CListValue class.
+//
+//////////////////////////////////////////////////////////////////////
+/*
+ * Copyright (c) 1996-2000 Erwin Coumans <coockie@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. Erwin Coumans makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ */
+
+
+#include "ListValue.h"
+#include "StringValue.h"
+#include "VoidValue.h"
+#include <algorithm>
+
+int listvalue_bufferlen(PyObject* list)
+{
+ return ( ((CListValue*)list)->GetCount());
+}
+
+
+
+PyObject* listvalue_buffer_item(PyObject* list,int index)
+{
+ if (index >= 0 && index < ((CListValue*) list)->GetCount())
+ {
+ PyObject* pyobj = ((CListValue*) list)->GetValue(index)->ConvertValueToPython();
+ if (pyobj)
+ return pyobj;
+ else
+ return ((CListValue*) list)->GetValue(index)->AddRef();
+
+ }
+ Py_Error(PyExc_IndexError, "Python ListIndex out of range");
+ return NULL;
+}
+
+
+
+/* just slice it into a python list... */
+PyObject* listvalue_buffer_slice(PyObject* list,int ilow, int ihigh)
+{
+ int i, j;
+ PyListObject *newlist;
+
+ if (ilow < 0) ilow = 0;
+
+ int n = ((CListValue*) list)->GetCount();
+
+ if (ihigh >= n)
+ ihigh = n;
+ if (ihigh < ilow)
+ ihigh = ilow;
+
+ newlist = (PyListObject *) PyList_New(ihigh - ilow);
+ if (!newlist)
+ return NULL;
+
+ for (i = ilow, j = 0; i < ihigh; i++, j++)
+ {
+ PyObject* pyobj = ((CListValue*) list)->GetValue(i)->ConvertValueToPython();
+ if (!pyobj)
+ pyobj = ((CListValue*) list)->GetValue(i)->AddRef();
+ newlist->ob_item[j] = pyobj;
+ }
+ return (PyObject *) newlist;
+}
+
+
+
+static PyObject *
+listvalue_buffer_concat(PyObject * self, PyObject * other)
+{
+ // for now, we support CListValue concatenated with items
+ // and CListValue concatenated to Python Lists
+ // and CListValue concatenated with another CListValue
+
+ CListValue* listval = (CListValue*) self;
+ listval->AddRef();
+ if (other->ob_type == &PyList_Type)
+ {
+ bool error = false;
+
+ int i;
+ int numitems = PyList_Size(other);
+ for (i=0;i<numitems;i++)
+ {
+ PyObject* listitem = PyList_GetItem(other,i);
+ CValue* listitemval = listval->ConvertPythonToValue(listitem);
+ if (listitemval)
+ {
+ listval->Add(listitemval);
+ } else
+ {
+ error = true;
+ }
+ }
+
+ if (error)
+ Py_Error(PyExc_SystemError, "Python Error: couldn't add one or more items to a list");
+
+
+ } else
+ {
+ if (other->ob_type == &CListValue::Type)
+ {
+ // add items from otherlist to this list
+ CListValue* otherval = (CListValue*) other;
+
+
+ for (int i=0;i<otherval->GetCount();i++)
+ {
+ otherval->Add(listval->GetValue(i)->AddRef());
+ }
+ }
+ else
+ {
+ CValue* objval = listval->ConvertPythonToValue(other);
+ if (objval)
+ {
+ listval->Add(objval);
+ } else
+ {
+ Py_Error(PyExc_SystemError, "Python Error: couldn't add item to a list");
+ // bad luck
+ }
+ }
+ }
+
+ return self;
+}
+
+
+
+static PySequenceMethods listvalue_as_sequence = {
+ (inquiry)listvalue_bufferlen,//(inquiry)buffer_length, /*sq_length*/
+ (binaryfunc)listvalue_buffer_concat, /*sq_concat*/
+ 0,//(intargfunc)buffer_repeat, /*sq_repeat*/
+ (intargfunc)listvalue_buffer_item, /*sq_item*/
+ (intintargfunc)listvalue_buffer_slice, /*sq_slice*/
+ 0,//(intobjargproc)buffer_ass_item, /*sq_ass_item*/
+ 0,//(intintobjargproc)buffer_ass_slice, /*sq_ass_slice*/
+};
+
+
+
+/* Is this one used ? */
+static PyMappingMethods instance_as_mapping = {
+ (inquiry)listvalue_bufferlen, /*mp_length*/
+ 0,//(binaryfunc)instance_subscript, /*mp_subscript*/
+ 0,//(objobjargproc)instance_ass_subscript, /*mp_ass_subscript*/
+};
+
+
+
+PyTypeObject CListValue::Type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0, /*ob_size*/
+ "CListValue", /*tp_name*/
+ sizeof(CListValue), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ PyDestructor, /*tp_dealloc*/
+ 0, /*tp_print*/
+ __getattr, /*tp_getattr*/
+ __setattr, /*tp_setattr*/
+ 0, /*tp_compare*/
+ __repr, /*tp_repr*/
+ 0, /*tp_as_number*/
+ &listvalue_as_sequence, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash*/
+ 0, /*tp_call */
+};
+
+
+
+PyParentObject CListValue::Parents[] = {
+ &CListValue::Type,
+ &CValue::Type,
+ NULL
+};
+
+
+
+
+PyMethodDef CListValue::Methods[] = {
+ {"append", (PyCFunction)CListValue::sPyappend,METH_VARARGS},
+ {"reverse", (PyCFunction)CListValue::sPyreverse,METH_VARARGS},
+ {"index", (PyCFunction)CListValue::sPyindex,METH_VARARGS},
+ {"count", (PyCFunction)CListValue::sPycount,METH_VARARGS},
+
+ {NULL,NULL} //Sentinel
+};
+
+
+
+PyObject* CListValue::_getattr(char* attr) {
+ _getattr_up(CValue);
+}
+
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CListValue::CListValue(PyTypeObject *T )
+: CPropValue(T)
+{
+ m_bReleaseContents=true;
+}
+
+
+
+CListValue::~CListValue()
+{
+
+ if (m_bReleaseContents) {
+ for (int i=0;i<m_pValueArray.size();i++) {
+ m_pValueArray[i]->Release();
+ }
+ }
+}
+
+
+static STR_String gstrListRep=STR_String("List");
+
+const STR_String & CListValue::GetText()
+{
+ gstrListRep = "[";
+ STR_String commastr = "";
+
+ for (int i=0;i<GetCount();i++)
+ {
+ gstrListRep += commastr;
+ gstrListRep += GetValue(i)->GetText();
+ commastr = ",";
+ }
+ gstrListRep += "]";
+
+ return gstrListRep;
+}
+
+
+
+CValue* CListValue::GetReplica() {
+ CListValue* replica = new CListValue(*this);
+
+ CValue::AddDataToReplica(replica);
+
+ replica->m_bReleaseContents=true; // for copy, complete array is copied for now...
+ // copy all values
+ int numelements = m_pValueArray.size();
+ int i=0;
+ replica->m_pValueArray.resize(numelements);
+ for (i=0;i<m_pValueArray.size();i++)
+ replica->m_pValueArray[i] = m_pValueArray[i]->GetReplica();
+
+
+ return replica;
+};
+
+
+
+void CListValue::SetValue(int i, CValue *val)
+{
+ assertd(i < m_pValueArray.size());
+ m_pValueArray[i]=val;
+}
+
+
+
+void CListValue::Resize(int num)
+{
+ m_pValueArray.resize(num);
+}
+
+
+
+void CListValue::Remove(int i)
+{
+ assertd(i<m_pValueArray.size());
+ m_pValueArray.erase(m_pValueArray.begin()+i);
+}
+
+
+
+void CListValue::ReleaseAndRemoveAll()
+{
+ for (int i=0;i<m_pValueArray.size();i++)
+ m_pValueArray[i]->Release();
+ m_pValueArray.clear();//.Clear();
+}
+
+
+
+CValue* CListValue::FindValue(const STR_String & name)
+{
+ CValue* resultval = NULL;
+ int i=0;
+
+ while (!resultval && i < GetCount())
+ {
+ CValue* myval = GetValue(i);
+
+ if (myval->GetName() == name)
+ resultval = GetValue(i)->AddRef(); // add referencecount
+ else
+ i++;
+
+ }
+ return resultval;
+}
+
+
+
+bool CListValue::SearchValue(CValue *val)
+{
+ for (int i=0;i<GetCount();i++)
+ if (val == GetValue(i))
+ return true;
+ return false;
+}
+
+
+
+void CListValue::SetReleaseOnDestruct(bool bReleaseContents)
+{
+ m_bReleaseContents = bReleaseContents;
+}
+
+
+
+bool CListValue::RemoveValue(CValue *val)
+{
+ bool result=false;
+
+ for (int i=GetCount()-1;i>=0;i--)
+ if (val == GetValue(i))
+ {
+ Remove(i);
+ result=true;
+ }
+ return result;
+}
+
+
+
+void CListValue::MergeList(CListValue *otherlist)
+{
+
+ int numelements = this->GetCount();
+ int numotherelements = otherlist->GetCount();
+
+
+ Resize(numelements+numotherelements);
+
+ for (int i=0;i<numotherelements;i++)
+ {
+ SetValue(i+numelements,otherlist->GetValue(i)->AddRef());
+ }
+
+}
+
+
+
+PyObject* CListValue::Pyappend(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+
+ PyObject* pyobj = NULL;
+ if (PyArg_ParseTuple(args,"O",&pyobj))
+ {
+ return listvalue_buffer_concat(self,pyobj);
+ }
+ else
+ {
+ return NULL;
+ }
+
+
+}
+
+
+
+PyObject* CListValue::Pyreverse(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ std::reverse(m_pValueArray.begin(),m_pValueArray.end());
+
+ Py_Return;
+
+}
+
+
+
+bool CListValue::CheckEqual(CValue* first,CValue* second)
+{
+ bool result = false;
+
+ CValue* eqval = ((CValue*)first)->Calc(VALUE_EQL_OPERATOR,(CValue*)second);
+ STR_String txt = eqval->GetText();
+ eqval->Release();
+ if (txt=="TRUE")
+ {
+ result = true;
+ }
+ return result;
+
+}
+
+
+
+PyObject* CListValue::Pyindex(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ PyObject* result = NULL;
+
+ PyObject* pyobj = NULL;
+ if (PyArg_ParseTuple(args,"O",&pyobj))
+ {
+
+ CValue* checkobj = ConvertPythonToValue(pyobj);
+ int numelem = GetCount();
+ for (int i=0;i<numelem;i++)
+ {
+ CValue* elem = GetValue(i);
+ if (CheckEqual(checkobj,elem))
+ {
+ result = PyInt_FromLong(i);
+ break;
+ }
+ }
+ checkobj->Release();
+ }
+
+ return result;
+
+}
+
+
+
+PyObject* CListValue::Pycount(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+
+ int numfound = 0;
+
+ PyObject* pyobj = NULL;
+ if (PyArg_ParseTuple(args,"O",&pyobj))
+ {
+ CValue* checkobj = ConvertPythonToValue(pyobj);
+ int numelem = GetCount();
+ for (int i=0;i<numelem;i++)
+ {
+ CValue* elem = GetValue(i);
+ if (CheckEqual(checkobj,elem))
+ {
+ numfound ++;
+ }
+ }
+ checkobj->Release();
+ }
+
+ return PyInt_FromLong(numfound);
+}
+
+
+
+/* ---------------------------------------------------------------------
+ * Some stuff taken from the header
+ * --------------------------------------------------------------------- */
+CValue* CListValue::Calc(VALUE_OPERATOR op,CValue *val)
+{
+ assert(false); // todo: implement me!
+ return NULL;
+}
+
+
+
+CValue* CListValue::CalcFinal(VALUE_DATA_TYPE dtype,
+ VALUE_OPERATOR op,
+ CValue* val)
+{
+ assert(false); // todo: implement me!
+ return NULL;
+}
+
+
+
+void CListValue::Add(CValue* value)
+{
+ m_pValueArray.push_back(value);
+}
+
+
+
+float CListValue::GetNumber()
+{
+ return -1;
+}
+
+
+
+void CListValue::SetModified(bool bModified)
+{
+ CValue::SetModified(bModified);
+ int numels = GetCount();
+
+ for (int i=0;i<numels;i++)
+ GetValue(i)->SetModified(bModified);
+}
+
+
+
+bool CListValue::IsModified()
+{
+ bool bmod = CValue::IsModified(); //normal own flag
+ int numels = GetCount();
+
+ for (int i=0;i<numels;i++)
+ bmod = bmod || GetValue(i)->IsModified();
+
+ return bmod;
+} \ No newline at end of file
diff --git a/source/gameengine/Expressions/ListValue.h b/source/gameengine/Expressions/ListValue.h
new file mode 100644
index 00000000000..fce4e9da8c2
--- /dev/null
+++ b/source/gameengine/Expressions/ListValue.h
@@ -0,0 +1,77 @@
+/*
+ * ListValue.h: interface for the CListValue class.
+ * $Id$
+ * Copyright (c) 1996-2000 Erwin Coumans <coockie@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. Erwin Coumans makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ */
+
+#if !defined _LISTVALUE_H
+#define _LISTVALUE_H
+
+
+#include "Value.h"
+
+class CListValue : public CPropValue
+{
+ Py_Header;
+ //PLUGIN_DECLARE_SERIAL (CListValue,CValue)
+
+public:
+ CListValue(PyTypeObject *T = &Type);
+ virtual ~CListValue();
+
+ void AddConfigurationData(CValue* menuvalue);
+ void Configure(CValue* menuvalue);
+ void Add(CValue* value);
+
+ /** @attention not implemented yet :( */
+ virtual CValue* Calc(VALUE_OPERATOR op,CValue *val);
+ virtual CValue* CalcFinal(VALUE_DATA_TYPE dtype,
+ VALUE_OPERATOR op,
+ CValue* val);
+ virtual float GetNumber();
+ virtual CValue* GetReplica();
+
+public:
+ void MergeList(CListValue* otherlist);
+ bool RemoveValue(CValue* val);
+ void SetReleaseOnDestruct(bool bReleaseContents);
+ bool SearchValue(CValue* val);
+
+ CValue* FindValue(const STR_String & name);
+
+ void ReleaseAndRemoveAll();
+ virtual void SetModified(bool bModified);
+ virtual inline bool IsModified();
+ void Remove(int i);
+ void Resize(int num);
+ void SetValue(int i,CValue* val);
+ CValue* GetValue(int i){ assertd(i < m_pValueArray.size()); return m_pValueArray[i];}
+ int GetCount() { return m_pValueArray.size();};
+ virtual const STR_String & GetText();
+
+ bool CheckEqual(CValue* first,CValue* second);
+
+ virtual PyObject* _getattr(char *attr);
+
+ KX_PYMETHOD(CListValue,append);
+ KX_PYMETHOD(CListValue,reverse);
+ KX_PYMETHOD(CListValue,index);
+ KX_PYMETHOD(CListValue,count);
+
+
+private:
+
+ std::vector<CValue*> m_pValueArray;
+ bool m_bReleaseContents;
+};
+
+#endif // !defined _LISTVALUE_H
diff --git a/source/gameengine/Expressions/Makefile b/source/gameengine/Expressions/Makefile
new file mode 100644
index 00000000000..9199698d3e9
--- /dev/null
+++ b/source/gameengine/Expressions/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 *****
+#
+#
+
+LIBNAME = expression
+DIR = $(OCGDIR)/gameengine/$(LIBNAME)
+
+include nan_compile.mk
+
+CCFLAGS += $(LEVEL_1_CPP_WARNINGS)
+
+CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION)
+CPPFLAGS += -I$(NAN_STRING)/include
+CPPFLAGS += -I../../kernel/gen_system
+CPPFLAGS += -I../Ketsji
+
diff --git a/source/gameengine/Expressions/Operator1Expr.cpp b/source/gameengine/Expressions/Operator1Expr.cpp
new file mode 100644
index 00000000000..91a3a02aabe
--- /dev/null
+++ b/source/gameengine/Expressions/Operator1Expr.cpp
@@ -0,0 +1,148 @@
+// Operator1Expr.cpp: implementation of the COperator1Expr class.
+/*
+ * Copyright (c) 1996-2000 Erwin Coumans <coockie@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. Erwin Coumans makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ */
+
+#include "Operator1Expr.h"
+//#include "FactoryManager.h"
+#include "EmptyValue.h"
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+COperator1Expr::COperator1Expr()
+/*
+pre:
+effect: constucts an empty COperator1Expr
+*/
+{
+ m_lhs = NULL;
+}
+
+COperator1Expr::COperator1Expr(VALUE_OPERATOR op, CExpression * lhs)
+/*
+pre:
+effect: constucts a COperator1Expr with op and lhs in it
+*/
+{
+ m_lhs = lhs;
+ m_op = op;
+}
+
+COperator1Expr::~COperator1Expr()
+/*
+pre:
+effect: deletes the object
+*/
+{
+ if (m_lhs) m_lhs->Release();
+}
+
+CValue * COperator1Expr::Calculate()
+/*
+pre:
+ret: a new object containing the result of applying the operator m_op to the
+ value of m_lhs
+*/
+{
+ CValue *ret;
+ CValue *temp = m_lhs->Calculate();
+ CValue* empty = new CEmptyValue();
+ ret = empty->Calc(m_op, temp);
+ empty->Release();
+ temp->Release();
+
+ return ret;
+}
+
+/*
+bool COperator1Expr::IsInside(float x, float y, float z,bool bBorderInclude)
+{
+
+ bool result = true;
+ switch (m_op)
+ {
+
+ case VALUE_ADD_OPERATOR:
+ {
+
+ if (m_lhs)
+ {
+ result = result || m_lhs->IsInside(x,y,z,bBorderInclude);
+ }
+ break;
+ }
+ case VALUE_SUB_OPERATOR:
+ {
+ result = true;
+ if (m_lhs)
+ {
+ result = result && (!m_lhs->IsInside(x,y,z,bBorderInclude));
+ }
+ break;
+ }
+ }
+ return result;
+}
+
+*/
+bool COperator1Expr::NeedsRecalculated() {
+
+ return m_lhs->NeedsRecalculated();
+
+}
+
+CExpression* COperator1Expr::CheckLink(std::vector<CBrokenLinkInfo*>& brokenlinks) {
+
+ CExpression* newlhs = m_lhs->CheckLink(brokenlinks);
+
+ if (newlhs)
+ {
+ if (newlhs==m_lhs) {
+ // not changed
+ } else {
+ // changed
+ //numchanges++;
+ newlhs->AddRef();
+
+ //m_lhs->Release();
+ brokenlinks.push_back(new CBrokenLinkInfo(&m_lhs,m_lhs));
+
+ m_lhs = newlhs;
+ }
+ return this;
+ } else {
+ //numchanges++;
+ AddRef();
+
+ return Release();
+ }
+
+}
+
+void COperator1Expr::BroadcastOperators(VALUE_OPERATOR op)
+{
+ if (m_lhs)
+ m_lhs->BroadcastOperators(m_op);
+}
+
+
+
+
+bool COperator1Expr::MergeExpression(CExpression *otherexpr)
+{
+ if (m_lhs)
+ return m_lhs->MergeExpression(otherexpr);
+
+ assertd(false); // should not get here, expression is not compatible for merge
+ return false;
+}
diff --git a/source/gameengine/Expressions/Operator1Expr.h b/source/gameengine/Expressions/Operator1Expr.h
new file mode 100644
index 00000000000..9362c568dc9
--- /dev/null
+++ b/source/gameengine/Expressions/Operator1Expr.h
@@ -0,0 +1,53 @@
+/*
+ * Operator1Expr.h: interface for the COperator1Expr class.
+ * $Id$
+ * Copyright (c) 1996-2000 Erwin Coumans <coockie@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. Erwin Coumans makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ */
+
+#if !defined(AFX_OPERATOR1EXPR_H__A1653901_BF41_11D1_A51C_00A02472FC58__INCLUDED_)
+#define AFX_OPERATOR1EXPR_H__A1653901_BF41_11D1_A51C_00A02472FC58__INCLUDED_
+
+
+
+#include "Expression.h"
+
+class COperator1Expr : public CExpression
+{
+ //PLUGIN_DECLARE_SERIAL_EXPRESSION (COperator1Expr,CExpression)
+
+
+
+public:
+ virtual bool MergeExpression(CExpression* otherexpr);
+ void virtual BroadcastOperators(VALUE_OPERATOR op);
+
+ virtual unsigned char GetExpressionID() { return COPERATOR1EXPRESSIONID;};
+ CExpression* CheckLink(std::vector<CBrokenLinkInfo*>& brokenlinks);
+ //virtual bool IsInside(float x,float y,float z,bool bBorderInclude = true);
+ virtual bool NeedsRecalculated();
+ void ClearModified() {
+ if (m_lhs)
+ m_lhs->ClearModified();
+ }
+ virtual CValue* Calculate();
+ COperator1Expr(VALUE_OPERATOR op, CExpression *lhs);
+ COperator1Expr();
+ virtual ~COperator1Expr();
+
+
+
+private:
+ VALUE_OPERATOR m_op;
+ CExpression * m_lhs;
+};
+
+#endif // !defined(AFX_OPERATOR1EXPR_H__A1653901_BF41_11D1_A51C_00A02472FC58__INCLUDED_)
diff --git a/source/gameengine/Expressions/Operator2Expr.cpp b/source/gameengine/Expressions/Operator2Expr.cpp
new file mode 100644
index 00000000000..33223b2ae3d
--- /dev/null
+++ b/source/gameengine/Expressions/Operator2Expr.cpp
@@ -0,0 +1,275 @@
+// Operator2Expr.cpp: implementation of the COperator2Expr class.
+/*
+ * Copyright (c) 1996-2000 Erwin Coumans <coockie@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. Erwin Coumans makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ */
+// 31 dec 1998 - big update: try to use the cached data for updating, instead of
+// rebuilding completely it from left and right node. Modified flags and bounding boxes
+// have to do the trick
+// when expression is cached, there will be a call to UpdateCalc() instead of Calc()
+
+
+
+#include "Operator2Expr.h"
+#include "StringValue.h"
+#include "VoidValue.h"
+//#include "FactoryManager.h"
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+COperator2Expr::COperator2Expr(VALUE_OPERATOR op, CExpression *lhs, CExpression *rhs)
+:
+m_cached_calculate(NULL),
+m_op(op),
+m_lhs(lhs),
+m_rhs(rhs)
+/*
+pre:
+effect: constucts a COperator2Expr with op, lhs and rhs in it
+*/
+{
+
+}
+
+COperator2Expr::COperator2Expr():
+m_cached_calculate(NULL),
+m_lhs(NULL),
+m_rhs(NULL)
+
+/*
+pre:
+effect: constucts an empty COperator2Expr
+*/
+{
+
+}
+
+COperator2Expr::~COperator2Expr()
+/*
+pre:
+effect: deletes the object
+*/
+{
+ if (m_lhs)
+ m_lhs->Release();
+ if (m_rhs)
+ m_rhs->Release();
+ if (m_cached_calculate)
+ m_cached_calculate->Release();
+
+}
+CValue* COperator2Expr::Calculate()
+/*
+pre:
+ret: a new object containing the result of applying operator m_op to m_lhs
+and m_rhs
+*/
+{
+
+ bool leftmodified,rightmodified;
+ leftmodified = m_lhs->NeedsRecalculated();
+ rightmodified = m_rhs->NeedsRecalculated();
+
+ // if no modifications on both left and right subtree, and result is already calculated
+ // then just return cached result...
+ if (!leftmodified && !rightmodified && (m_cached_calculate))
+ {
+ // not modified, just return m_cached_calculate
+ } else {
+ // if not yet calculated, or modified...
+
+
+ if (m_cached_calculate) {
+ m_cached_calculate->Release();
+ m_cached_calculate=NULL;
+ }
+
+ CValue* ffleft = m_lhs->Calculate();
+ CValue* ffright = m_rhs->Calculate();
+
+ ffleft->SetOwnerExpression(this);//->m_pOwnerExpression=this;
+ ffright->SetOwnerExpression(this);//->m_pOwnerExpression=this;
+
+ m_cached_calculate = ffleft->Calc(m_op,ffright);
+
+ //if (m_cached_calculate)
+ // m_cached_calculate->Action(CValue::SETOWNEREXPR,&CVoidValue(this,false,CValue::STACKVALUE));
+
+ ffleft->Release();
+ ffright->Release();
+ }
+
+ return m_cached_calculate->AddRef();
+
+}
+
+/*
+bool COperator2Expr::IsInside(float x, float y, float z,bool bBorderInclude)
+{
+ bool inside;
+ inside = false;
+
+ switch (m_op)
+ {
+ case VALUE_ADD_OPERATOR: {
+ // inside = first || second; // optimized with early out if first is inside
+ // todo: calculate smallest leaf first ! is much faster...
+
+ bool second;//first ;//,second;
+
+ //first = m_lhs->IsInside(x,y,z) ;
+ second = m_rhs->IsInside(x,y,z,bBorderInclude) ;
+ if (second)
+ return true; //early out
+
+ // second = m_rhs->IsInside(x,y,z) ;
+
+ return m_lhs->IsInside(x,y,z,bBorderInclude) ;
+
+ break;
+ }
+
+ case VALUE_SUB_OPERATOR: {
+ //inside = first && !second; // optimized with early out
+ // todo: same as with add_operator: calc smallest leaf first
+
+ bool second;//first ;//,second;
+ //first = m_lhs->IsInside(x,y,z) ;
+ second = m_rhs->IsInside(x,y,z,bBorderInclude);
+ if (second)
+ return false;
+
+ // second space get subtracted -> negate!
+ //second = m_rhs->IsInside(x,y,z);
+
+ return (m_lhs->IsInside(x,y,z,bBorderInclude));
+
+
+ break;
+ }
+ default:{
+ assert(false);
+ // not yet implemented, only add or sub csg operations
+ }
+ }
+
+ return inside;
+}
+
+
+
+bool COperator2Expr::IsRightInside(float x, float y, float z,bool bBorderInclude) {
+
+ return m_rhs->IsInside(x,y,z,bBorderInclude) ;
+
+}
+
+bool COperator2Expr::IsLeftInside(float x, float y, float z,bool bBorderInclude) {
+ return m_lhs->IsInside(x,y,z,bBorderInclude);
+}
+*/
+bool COperator2Expr::NeedsRecalculated() {
+ // added some lines, just for debugging purposes, it could be a one-liner :)
+ //bool modleft
+ //bool modright;
+ assertd(m_lhs);
+ assertd(m_rhs);
+
+ //modright = m_rhs->NeedsRecalculated();
+ if (m_rhs->NeedsRecalculated()) // early out
+ return true;
+ return m_lhs->NeedsRecalculated();
+ //modleft = m_lhs->NeedsRecalculated();
+ //return (modleft || modright);
+
+}
+
+
+
+CExpression* COperator2Expr::CheckLink(std::vector<CBrokenLinkInfo*>& brokenlinks) {
+// if both children are 'dead', return NULL
+// if only one child is alive, return that child
+// if both childresn are alive, return this
+
+
+// bool leftalive = true,rightalive=true;
+ /* Does this mean the function will always bomb? */
+ assertd(false);
+ assert(m_lhs);
+ assert(m_rhs);
+/*
+ if (m_cached_calculate)
+ m_cached_calculate->Action(CValue::REFRESH_CACHE);
+
+ CExpression* newlhs = m_lhs->CheckLink(brokenlinks);
+ CExpression* newrhs = m_rhs->CheckLink(brokenlinks);
+
+ if (m_lhs != newlhs)
+ {
+ brokenlinks.push_back(new CBrokenLinkInfo(&m_lhs,m_lhs));
+ }
+
+ if (m_rhs != newrhs)
+ {
+ brokenlinks.push_back(new CBrokenLinkInfo(&m_rhs,m_rhs));
+ }
+
+
+
+ m_lhs = newlhs;
+ m_rhs = newrhs;
+
+ if (m_lhs && m_rhs) {
+ return this;
+ }
+
+ AddRef();
+ if (m_lhs)
+ return Release(m_lhs->AddRef());
+
+ if (m_rhs)
+ return Release(m_rhs->AddRef());
+/
+
+ */
+ return Release();
+
+
+
+}
+
+
+bool COperator2Expr::MergeExpression(CExpression *otherexpr)
+{
+ if (m_lhs)
+ {
+ if (m_lhs->GetExpressionID() == CExpression::CCONSTEXPRESSIONID)
+ {
+ // cross fingers ;) replace constexpr by new tree...
+ m_lhs->Release();
+ m_lhs = otherexpr->AddRef();
+ return true;
+ }
+ }
+
+ assertd(false);
+ return false;
+}
+
+
+void COperator2Expr::BroadcastOperators(VALUE_OPERATOR op)
+{
+ if (m_lhs)
+ m_lhs->BroadcastOperators(m_op);
+ if (m_rhs)
+ m_rhs->BroadcastOperators(m_op);
+}
diff --git a/source/gameengine/Expressions/Operator2Expr.h b/source/gameengine/Expressions/Operator2Expr.h
new file mode 100644
index 00000000000..7e1dc3ed250
--- /dev/null
+++ b/source/gameengine/Expressions/Operator2Expr.h
@@ -0,0 +1,59 @@
+/*
+ * Operator2Expr.h: interface for the COperator2Expr class.
+ * $Id$
+ * Copyright (c) 1996-2000 Erwin Coumans <coockie@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. Erwin Coumans makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ */
+
+#if !defined _OPERATOR2EXPR_H
+#define _OPERATOR2EXPR_H
+
+
+#include "Expression.h"
+#include "Value.h" // Added by ClassView
+
+
+class COperator2Expr : public CExpression
+{
+ //PLUGIN_DECLARE_SERIAL_EXPRESSION (COperator2Expr,CExpression)
+
+public:
+ virtual bool MergeExpression(CExpression* otherexpr);
+ virtual unsigned char GetExpressionID() { return COPERATOR2EXPRESSIONID;};
+ virtual void BroadcastOperators(VALUE_OPERATOR op);
+ CExpression* CheckLink(std::vector<CBrokenLinkInfo*>& brokenlinks);
+ //virtual bool IsInside(float x,float y,float z,bool bBorderInclude=true);
+ //virtual bool IsLeftInside(float x,float y,float z,bool bBorderInclude);
+ //virtual bool IsRightInside(float x,float y,float z,bool bBorderInclude);
+ bool NeedsRecalculated();
+ void ClearModified() {
+ if (m_lhs)
+ m_lhs->ClearModified();
+ if (m_rhs)
+ m_rhs->ClearModified();
+ }
+ virtual CValue* Calculate();
+ COperator2Expr(VALUE_OPERATOR op, CExpression *lhs, CExpression *rhs);
+ COperator2Expr();
+ virtual ~COperator2Expr();
+
+
+protected:
+ CExpression * m_rhs;
+ CExpression * m_lhs;
+ CValue* m_cached_calculate; // cached result
+
+private:
+ VALUE_OPERATOR m_op;
+
+};
+
+#endif // !defined _OPERATOR2EXPR_H
diff --git a/source/gameengine/Expressions/PyObjectPlus.cpp b/source/gameengine/Expressions/PyObjectPlus.cpp
new file mode 100644
index 00000000000..7b93b1d4daa
--- /dev/null
+++ b/source/gameengine/Expressions/PyObjectPlus.cpp
@@ -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 *****
+ */
+
+#ifndef NO_EXP_PYTHON_EMBEDDING
+
+/*------------------------------
+ * PyObjectPlus cpp
+ *
+ * C++ library routines for Crawl 3.2
+ *
+ * Derived from work by
+ * David Redish
+ * graduate student
+ * Computer Science Department
+ * Carnegie Mellon University (CMU)
+ * Center for the Neural Basis of Cognition (CNBC)
+ * http://www.python.org/doc/PyCPP.html
+ *
+------------------------------*/
+#include <assert.h>
+#include "stdlib.h"
+#include "PyObjectPlus.h"
+#include "STR_String.h"
+/*------------------------------
+ * PyObjectPlus Type -- Every class, even the abstract one should have a Type
+------------------------------*/
+
+PyTypeObject PyObjectPlus::Type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0, /*ob_size*/
+ "PyObjectPlus", /*tp_name*/
+ sizeof(PyObjectPlus), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ PyDestructor, /*tp_dealloc*/
+ 0, /*tp_print*/
+ __getattr, /*tp_getattr*/
+ __setattr, /*tp_setattr*/
+ 0, /*tp_compare*/
+ __repr, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash*/
+ 0, /*tp_call */
+};
+
+PyObjectPlus::PyObjectPlus(PyTypeObject *T) // constructor
+{
+ assert(T != NULL);
+ this->ob_type = T;
+ _Py_NewReference(this);
+};
+
+/*------------------------------
+ * PyObjectPlus Methods -- Every class, even the abstract one should have a Methods
+------------------------------*/
+PyMethodDef PyObjectPlus::Methods[] = {
+ {"isA", (PyCFunction) sPy_isA, Py_NEWARGS},
+ {NULL, NULL} /* Sentinel */
+};
+
+/*------------------------------
+ * PyObjectPlus Parents -- Every class, even the abstract one should have parents
+------------------------------*/
+PyParentObject PyObjectPlus::Parents[] = {&PyObjectPlus::Type, NULL};
+
+/*------------------------------
+ * PyObjectPlus attributes -- attributes
+------------------------------*/
+PyObject *PyObjectPlus::_getattr(char *attr)
+{
+ //if (streq(attr, "type"))
+ // return Py_BuildValue("s", (*(GetParents()))->tp_name);
+
+ return Py_FindMethod(Methods, this, attr);
+}
+
+int PyObjectPlus::_setattr(char *attr, PyObject *value)
+{
+ //return PyObject::_setattr(attr,value);
+ //cerr << "Unknown attribute" << endl;
+ return 1;
+}
+
+/*------------------------------
+ * PyObjectPlus repr -- representations
+------------------------------*/
+PyObject *PyObjectPlus::_repr(void)
+{
+ Py_Error(PyExc_SystemError, "Representation not overridden by object.");
+}
+
+/*------------------------------
+ * PyObjectPlus isA -- the isA functions
+------------------------------*/
+bool PyObjectPlus::isA(PyTypeObject *T) // if called with a Type, use "typename"
+{
+ return isA(T->tp_name);
+}
+
+
+bool PyObjectPlus::isA(const char *mytypename) // check typename of each parent
+{
+ int i;
+ PyParentObject P;
+ PyParentObject *Ps = GetParents();
+
+ for (P = Ps[i=0]; P != NULL; P = Ps[i++])
+ {
+ if (STR_String(P->tp_name) == STR_String(mytypename) )
+ return true;
+ }
+
+ return false;
+}
+
+PyObject *PyObjectPlus::Py_isA(PyObject *args) // Python wrapper for isA
+{
+ char *mytypename;
+ Py_Try(PyArg_ParseTuple(args, "s", &mytypename));
+ if(isA(mytypename))
+ {Py_INCREF(Py_True); return Py_True;}
+ else
+ {Py_INCREF(Py_False); return Py_False;};
+}
+
+#endif //NO_EXP_PYTHON_EMBEDDING
+
diff --git a/source/gameengine/Expressions/PyObjectPlus.h b/source/gameengine/Expressions/PyObjectPlus.h
new file mode 100644
index 00000000000..e88ea2b255a
--- /dev/null
+++ b/source/gameengine/Expressions/PyObjectPlus.h
@@ -0,0 +1,135 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 NO_EXP_PYTHON_EMBEDDING
+
+#ifndef _adr_py_lib_h_ // only process once,
+#define _adr_py_lib_h_ // even if multiply included
+
+#ifndef __cplusplus // c++ only
+#error Must be compiled with C++
+#endif
+
+#include "KX_Python.h"
+
+/*------------------------------
+ * Python defines
+------------------------------*/
+
+ // some basic python macros
+#define Py_NEWARGS 1
+#define Py_Return Py_INCREF(Py_None); return Py_None;
+
+#define Py_Error(E, M) {PyErr_SetString(E, M); return NULL;}
+#define Py_Try(F) {if (!(F)) return NULL;}
+#define Py_Assert(A,E,M) {if (!(A)) {PyErr_SetString(E, M); return NULL;}}
+
+inline void Py_Fatal(char *M) {
+ //cout << M << endl;
+ exit(-1);
+};
+
+ // This must be the first line of each
+ // PyC++ class
+#define Py_Header \
+ public: \
+ static PyTypeObject Type; \
+ static PyMethodDef Methods[]; \
+ static PyParentObject Parents[]; \
+ virtual PyTypeObject *GetType(void) {return &Type;}; \
+ virtual PyParentObject *GetParents(void) {return Parents;}
+
+ // This defines the _getattr_up macro
+ // which allows attribute and method calls
+ // to be properly passed up the hierarchy.
+#define _getattr_up(Parent) \
+ PyObject *rvalue = Py_FindMethod(Methods, this, attr); \
+ if (rvalue == NULL) \
+ { \
+ PyErr_Clear(); \
+ return Parent::_getattr(attr); \
+ } \
+ else \
+ return rvalue
+
+
+/*------------------------------
+ * PyObjectPlus
+------------------------------*/
+typedef PyTypeObject * PyParentObject; // Define the PyParent Object
+
+class PyObjectPlus : public PyObject { // The PyObjectPlus abstract class
+
+ Py_Header; // Always start with Py_Header
+
+ public:
+ PyObjectPlus(PyTypeObject *T);
+
+ virtual ~PyObjectPlus() {}; // destructor
+ static void PyDestructor(PyObject *P) // python wrapper
+ {
+ delete ((PyObjectPlus *) P);
+ };
+
+ //void INCREF(void) {
+// Py_INCREF(this);
+// }; // incref method
+ //void DECREF(void) {
+// Py_DECREF(this);
+// }; // decref method
+
+ virtual PyObject *_getattr(char *attr); // _getattr method
+ static PyObject *__getattr(PyObject * PyObj, char *attr) // This should be the entry in Type.
+ { return ((PyObjectPlus*) PyObj)->_getattr(attr); };
+
+ virtual int _setattr(char *attr, PyObject *value); // _setattr method
+ static int __setattr(PyObject *PyObj, // This should be the entry in Type.
+ char *attr,
+ PyObject *value)
+ { return ((PyObjectPlus*) PyObj)->_setattr(attr, value); };
+
+ virtual PyObject *_repr(void); // _repr method
+ static PyObject *__repr(PyObject *PyObj) // This should be the entry in Type.
+ { return ((PyObjectPlus*) PyObj)->_repr(); };
+
+
+ // isA methods
+ bool isA(PyTypeObject *T);
+ bool isA(const char *mytypename);
+ PyObject *Py_isA(PyObject *args);
+ static PyObject *sPy_isA(PyObject *self, PyObject *args, PyObject *kwd)
+ {return ((PyObjectPlus*)self)->Py_isA(args);};
+};
+
+#endif // _adr_py_lib_h_
+
+#endif //NO_EXP_PYTHON_EMBEDDING
+
diff --git a/source/gameengine/Expressions/StringValue.cpp b/source/gameengine/Expressions/StringValue.cpp
new file mode 100644
index 00000000000..7bdb841e1e4
--- /dev/null
+++ b/source/gameengine/Expressions/StringValue.cpp
@@ -0,0 +1,139 @@
+// StringValue.cpp: implementation of the CStringValue class.
+/*
+ * Copyright (c) 1996-2000 Erwin Coumans <coockie@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. Erwin Coumans makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ */
+
+
+#include "StringValue.h"
+#include "BoolValue.h"
+#include "ErrorValue.h"
+#include "VoidValue.h"
+//#include "FactoryManager.h"
+
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CStringValue::CStringValue()
+/*
+pre: false
+effect: constructs a new CStringValue
+*/
+{
+ m_strString = "[Illegal String constructor call]";
+}
+
+CStringValue::CStringValue(STR_String txt,STR_String name,AllocationTYPE alloctype)
+/*
+pre:
+effect: constructs a new CStringValue containing text txt
+*/
+{
+ m_strString = txt;
+ SetName(name);
+
+ if (alloctype==CValue::STACKVALUE)
+ {
+ CValue::DisableRefCount();
+
+ }
+
+
+}
+
+
+CValue* CStringValue::Calc(VALUE_OPERATOR op, CValue *val)
+/*
+pre:
+ret: a new object containing the result of applying operator op to this
+object and val
+*/
+{
+ //return val->CalrcString(op, this);
+ return val->CalcFinal(VALUE_STRING_TYPE, op, this);
+}
+
+CValue* CStringValue::CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val)
+/*
+pre: the type of val is dtype
+ret: a new object containing the result of applying operator op to val and
+this object
+*/
+{
+ CValue *ret;
+
+ if (op == VALUE_ADD_OPERATOR) {
+ if (dtype == VALUE_ERROR_TYPE)
+ ret = new CErrorValue(val->GetText() + op2str(op) + GetText());
+ else
+ ret = new CStringValue(val->GetText() + GetText(),"");
+ } else {
+
+ if (dtype == VALUE_STRING_TYPE || dtype == VALUE_EMPTY_TYPE) {
+ switch(op) {
+ case VALUE_EQL_OPERATOR:
+ ret = new CBoolValue(val->GetText() == GetText());
+ break;
+ case VALUE_NEQ_OPERATOR:
+ ret = new CBoolValue(val->GetText() != GetText());
+ break;
+ case VALUE_GRE_OPERATOR:
+ ret = new CBoolValue(val->GetText() > GetText());
+ break;
+ case VALUE_LES_OPERATOR:
+ ret = new CBoolValue(val->GetText() < GetText());
+ break;
+ case VALUE_GEQ_OPERATOR:
+ ret = new CBoolValue(val->GetText() >= GetText());
+ break;
+ case VALUE_LEQ_OPERATOR:
+ ret = new CBoolValue(val->GetText() <= GetText());
+ break;
+ default:
+ ret = new CErrorValue(val->GetText() + op2str(op) + "[operator not allowed on strings]");
+ break;
+ }
+ } else {
+ ret = new CErrorValue(val->GetText() + op2str(op) + "[operator not allowed on strings]");
+ }
+ }
+ return ret;
+}
+
+
+
+float CStringValue::GetNumber()
+{
+ return -1;
+}
+
+
+
+const STR_String & CStringValue::GetText()
+{
+ return m_strString;
+}
+
+bool CStringValue::IsEqual(const STR_String & other)
+{
+ return (m_strString == other);
+}
+
+CValue* CStringValue::GetReplica()
+{
+ CStringValue* replica = new CStringValue(*this);
+ CValue::AddDataToReplica(replica);
+ return replica;
+};
+
+
diff --git a/source/gameengine/Expressions/StringValue.h b/source/gameengine/Expressions/StringValue.h
new file mode 100644
index 00000000000..6f90536a98b
--- /dev/null
+++ b/source/gameengine/Expressions/StringValue.h
@@ -0,0 +1,51 @@
+/*
+ * StringValue.h: interface for the CStringValue class.
+ * $Id$
+ * Copyright (c) 1996-2000 Erwin Coumans <coockie@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. Erwin Coumans makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ */
+
+#ifndef __STRINGVALUE_H__
+#define __STRINGVALUE_H__
+
+#include "Value.h"
+
+class CStringValue : public CPropValue
+{
+
+
+ //PLUGIN_DECLARE_SERIAL(CStringValue,CValue)
+public:
+ /// Construction / destruction
+ CStringValue();
+ CStringValue (STR_String txt, STR_String name , AllocationTYPE alloctype = CValue::HEAPVALUE);
+
+ virtual ~CStringValue() {
+ };
+ /// CValue implementation
+ virtual bool IsEqual(const STR_String & other);
+ virtual const STR_String & GetText();
+ virtual float GetNumber();
+
+ virtual CValue* Calc(VALUE_OPERATOR op, CValue *val);
+ virtual CValue* CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val);
+ virtual void SetValue(CValue* newval) { m_strString = newval->GetText(); SetModified(true); };
+ virtual CValue* GetReplica();
+ virtual PyObject* ConvertValueToPython() {
+ return PyString_FromString(m_strString.Ptr());
+ }
+
+private:
+ // data member
+ STR_String m_strString;
+};
+
+#endif
diff --git a/source/gameengine/Expressions/Value.cpp b/source/gameengine/Expressions/Value.cpp
new file mode 100644
index 00000000000..e2a7189fb02
--- /dev/null
+++ b/source/gameengine/Expressions/Value.cpp
@@ -0,0 +1,767 @@
+// Value.cpp: implementation of the CValue class.
+// developed at Eindhoven University of Technology, 1997
+// by the OOPS team
+//////////////////////////////////////////////////////////////////////
+/*
+ * Copyright (c) 1996-2000 Erwin Coumans <coockie@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. Erwin Coumans makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ */
+
+
+#include "Value.h"
+#include "FloatValue.h"
+#include "IntValue.h"
+#include "VectorValue.h"
+#include "VoidValue.h"
+#include "StringValue.h"
+#include "ErrorValue.h"
+#include "ListValue.h"
+
+//#include "FactoryManager.h"
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+double CValue::m_sZeroVec[3] = {0.0,0.0,0.0};
+
+#ifndef NO_EXP_PYTHON_EMBEDDING
+
+PyObject* cvalue_add(PyObject*v, PyObject*w)
+{
+ return ((CValue*)v)->Calc(VALUE_ADD_OPERATOR,(CValue*)w);
+}
+PyObject* cvalue_sub(PyObject*v, PyObject*w)
+{
+ return ((CValue*)v)->Calc(VALUE_SUB_OPERATOR,(CValue*)w);
+}
+PyObject* cvalue_mul(PyObject*v, PyObject*w)
+{
+ return ((CValue*)v)->Calc(VALUE_MUL_OPERATOR,(CValue*)w);
+}
+PyObject* cvalue_div(PyObject*v, PyObject*w)
+{
+ return ((CValue*)v)->Calc(VALUE_DIV_OPERATOR,(CValue*)w);
+}
+PyObject* cvalue_neg(PyObject*v)
+{
+ return ((CValue*)v)->Calc(VALUE_NEG_OPERATOR,(CValue*)v);
+}
+PyObject* cvalue_pos(PyObject*v)
+{
+ return ((CValue*)v)->Calc(VALUE_POS_OPERATOR,(CValue*)v);
+}
+
+
+int MyPyCompare (PyObject* v,PyObject* w)
+{
+ CValue* eqval = ((CValue*)v)->Calc(VALUE_EQL_OPERATOR,(CValue*)w);
+ STR_String txt = eqval->GetText();
+ eqval->Release();
+ if (txt=="TRUE")
+ return 0;
+ CValue* lessval = ((CValue*)v)->Calc(VALUE_LES_OPERATOR,(CValue*)w);
+ txt = lessval->GetText();
+ lessval->Release();
+ if (txt=="TRUE")
+ return -1;
+
+ return 1;
+}
+
+
+int cvalue_coerce(PyObject** pv,PyObject** pw)
+{
+ if (PyInt_Check(*pw)) {
+ double db = (double)PyInt_AsLong(*pw);
+ *pw = new CIntValue(db);
+ Py_INCREF(*pv);
+ return 0;
+ }
+ else if (PyLong_Check(*pw)) {
+ double db = PyLong_AsDouble(*pw);
+ *pw = new CFloatValue(db);
+ Py_INCREF(*pv);
+ return 0;
+ }
+ else if (PyFloat_Check(*pw)) {
+ double db = PyFloat_AsDouble(*pw);
+ *pw = new CFloatValue(db);
+ Py_INCREF(*pv);
+ return 0;
+ } else if (PyString_Check(*pw)) {
+ const STR_String str = PyString_AsString(*pw);
+ *pw = new CStringValue(str,"");
+ Py_INCREF(*pv);
+ return 0;
+ }
+ return 1; /* Can't do it */
+
+}
+static PyNumberMethods cvalue_as_number = {
+ (binaryfunc)cvalue_add, /*nb_add*/
+ (binaryfunc)cvalue_sub, /*nb_subtract*/
+ (binaryfunc)cvalue_mul, /*nb_multiply*/
+ (binaryfunc)cvalue_div, /*nb_divide*/
+ 0,//(binaryfunc)cvalue_remainder, /*nb_remainder*/
+ 0,//(binaryfunc)cvalue_divmod, /*nb_divmod*/
+ 0,//0,//0,//0,//(ternaryfunc)cvalue_pow, /*nb_power*/
+ (unaryfunc)cvalue_neg, /*nb_negative*/
+ 0,//(unaryfunc)cvalue_pos, /*nb_positive*/
+ 0,//(unaryfunc)cvalue_abs, /*nb_absolute*/
+ 0,//(inquiry)cvalue_nonzero, /*nb_nonzero*/
+ 0, /*nb_invert*/
+ 0, /*nb_lshift*/
+ 0, /*nb_rshift*/
+ 0, /*nb_and*/
+ 0, /*nb_xor*/
+ 0, /*nb_or*/
+ (coercion)cvalue_coerce, /*nb_coerce*/
+ 0,//(unaryfunc)cvalue_int, /*nb_int*/
+ 0,//(unaryfunc)cvalue_long, /*nb_long*/
+ 0,//(unaryfunc)cvalue_float, /*nb_float*/
+ 0, /*nb_oct*/
+ 0, /*nb_hex*/
+};
+
+
+PyTypeObject CValue::Type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0,
+ "CValue",
+ sizeof(CValue),
+ 0,
+ PyDestructor,
+ 0,
+ __getattr,
+ __setattr,
+ &MyPyCompare,
+ __repr,
+ &cvalue_as_number,
+ 0,
+ 0,
+ 0,
+ 0
+};
+
+PyParentObject CValue::Parents[] = {
+ &CValue::Type,
+ NULL
+};
+
+PyMethodDef CValue::Methods[] = {
+// { "printHello", (PyCFunction) CValue::sPyPrintHello, Py_NEWARGS},
+ { "getName", (PyCFunction) CValue::sPyGetName, Py_NEWARGS},
+ {NULL,NULL} //Sentinel
+};
+
+PyObject* CValue::PyGetName(PyObject* self,PyObject* args,PyObject* kwds)
+{
+ PyObject* pyname = PyString_FromString(this->GetName());
+ return pyname;
+}
+
+
+
+CValue::CValue(PyTypeObject *T)
+ : PyObjectPlus(T),
+#else
+CValue::CValue()
+:
+#endif //NO_EXP_PYTHON_EMBEDDING
+
+m_refcount(1),
+m_pNamedPropertyArray(NULL)
+/*
+pre: false
+effect: constucts a CValue
+*/
+{
+ //debug(gRefCountValue++) // debugging
+}
+
+
+
+CValue::~CValue()
+/*
+pre:
+effect: deletes the object
+*/
+{
+ ClearProperties();
+
+ assertd (m_refcount==0);
+}
+
+
+
+
+#define VALUE_SUB(val1, val2) (val1)->Calc(VALUE_SUB_OPERATOR, val2)
+#define VALUE_MUL(val1, val2) (val1)->Calc(VALUE_MUL_OPERATOR, val2)
+#define VALUE_DIV(val1, val2) (val1)->Calc(VALUE_DIV_OPERATOR, val2)
+#define VALUE_NEG(val1) (val1)->Calc(VALUE_NEG_OPERATOR, val1)
+#define VALUE_POS(val1) (val1)->Calc(VALUE_POS_OPERATOR, val1)
+
+
+STR_String CValue::op2str (VALUE_OPERATOR op)
+{
+ //pre:
+ //ret: the stringrepresentation of operator op
+
+ STR_String opmsg;
+ switch (op) {
+ case VALUE_ADD_OPERATOR:
+ opmsg = " + ";
+ break;
+ case VALUE_SUB_OPERATOR:
+ opmsg = " - ";
+ break;
+ case VALUE_MUL_OPERATOR:
+ opmsg = " * ";
+ break;
+ case VALUE_DIV_OPERATOR:
+ opmsg = " / ";
+ break;
+ case VALUE_NEG_OPERATOR:
+ opmsg = " -";
+ break;
+ case VALUE_POS_OPERATOR:
+ opmsg = " +";
+ break;
+ case VALUE_AND_OPERATOR:
+ opmsg = " & ";
+ break;
+ case VALUE_OR_OPERATOR:
+ opmsg = " | ";
+ break;
+ case VALUE_EQL_OPERATOR:
+ opmsg = " = ";
+ break;
+ case VALUE_NEQ_OPERATOR:
+ opmsg = " != ";
+ break;
+ case VALUE_NOT_OPERATOR:
+ opmsg = " !";
+ break;
+ default:
+ opmsg="Error in Errorhandling routine.";
+ // AfxMessageBox("Invalid operator");
+ break;
+ }
+ return opmsg;
+}
+
+
+
+
+
+//---------------------------------------------------------------------------------------------------------------------
+// Property Management
+//---------------------------------------------------------------------------------------------------------------------
+
+
+
+//
+// Set property <ioProperty>, overwrites and releases a previous property with the same name if needed
+//
+void CValue::SetProperty(const STR_String & name,CValue* ioProperty)
+{
+ // Check if somebody is setting an empty property
+ if (ioProperty==NULL)
+ {
+ trace("Warning:trying to set empty property!");
+ return;
+ }
+
+ // Make sure we have a property array
+ if (m_pNamedPropertyArray == NULL)
+ m_pNamedPropertyArray = new std::map<const STR_String,CValue *>;
+
+ // Try to replace property (if so -> exit as soon as we replaced it)
+ CValue* oldval = (*m_pNamedPropertyArray)[name];
+ if (oldval)
+ {
+ oldval->Release();
+ }
+
+ // Add property at end of array
+ (*m_pNamedPropertyArray)[name] = ioProperty;//->Add(ioProperty);
+}
+
+
+
+//
+// Get pointer to a property with name <inName>, returns NULL if there is no property named <inName>
+//
+CValue* CValue::GetProperty(const STR_String & inName)
+{
+ // Check properties, as soon as we found it -> Return a pointer to the property
+ CValue* result = NULL;
+ if (m_pNamedPropertyArray)
+ {
+ std::map<const STR_String,CValue*>::iterator it = (*m_pNamedPropertyArray).find(inName);
+ if (!( it==m_pNamedPropertyArray->end()))
+ {
+ result = (*it).second;
+ }
+
+ }
+ //for (int i=0; i<m_pValuePropertyArray->size(); i++)
+ // if ((*m_pValuePropertyArray)[i]->GetName() == inName)
+ // return (*m_pValuePropertyArray)[i];
+
+ // Did not find property with name <inName>, return NULL property pointer
+ return result;
+}
+
+
+
+//
+// Get text description of property with name <inName>, returns an empty string if there is no property named <inName>
+//
+STR_String CValue::GetPropertyText(const STR_String & inName,const STR_String& deftext)
+{
+ CValue *property = GetProperty(inName);
+ if (property)
+ return property->GetText();
+ else
+ return deftext;//String::sEmpty;
+}
+
+float CValue::GetPropertyNumber(const STR_String& inName,float defnumber)
+{
+ CValue *property = GetProperty(inName);
+ if (property)
+ return property->GetNumber();
+ else
+ return defnumber;
+}
+
+
+
+//
+// Remove the property named <inName>, returns true if the property was succesfully removed, false if property was not found or could not be removed
+//
+bool CValue::RemoveProperty(const STR_String & inName)
+{
+ // Check if there are properties at all which can be removed
+ if (m_pNamedPropertyArray == NULL)
+ return false;
+
+ // Scan all properties, as soon as we find one with <inName> -> Remove it
+// CValue* val = (*m_pNamedPropertyArray)[inName];
+ if (m_pNamedPropertyArray->erase(inName)) return true;
+
+ return false;
+}
+
+
+
+//
+// Clear all properties
+//
+void CValue::ClearProperties()
+{
+ // Check if we have any properties
+ if (m_pNamedPropertyArray == NULL)
+ return;
+
+ // Remove all properties
+ for ( std::map<const STR_String,CValue*>::iterator it = m_pNamedPropertyArray->begin();
+ !(it == m_pNamedPropertyArray->end());it++)
+ {
+ CValue* tmpval = (*it).second;
+ STR_String name = (*it).first;
+ tmpval->Release();
+ }
+
+ // Delete property array
+ delete m_pNamedPropertyArray;
+ m_pNamedPropertyArray=NULL;
+}
+
+
+
+//
+// Set all properties' modified flag to <inModified>
+//
+void CValue::SetPropertiesModified(bool inModified)
+{
+ int numprops = GetPropertyCount();
+ for (int i=0; i<numprops; i++)
+ GetProperty(i)->SetModified(inModified);
+}
+
+
+
+//
+// Check if any of the properties in this value have been modified
+//
+bool CValue::IsAnyPropertyModified()
+{
+ int numprops = GetPropertyCount();
+ for (int i=0;i<numprops;i++)
+ if (GetProperty(i)->IsModified())
+ return true;
+
+ return false;
+}
+
+
+
+//
+// Get property number <inIndex>
+//
+
+CValue* CValue::GetProperty(int inIndex)
+{
+
+ int count=0;
+ CValue* result = NULL;
+
+ if (m_pNamedPropertyArray)
+ {
+ for ( std::map<const STR_String,CValue*>::iterator it = m_pNamedPropertyArray->begin();
+ !(it == m_pNamedPropertyArray->end());it++)
+ {
+ if (count++==inIndex)
+ {
+ result = (*it).second;
+ break;
+ }
+ }
+
+ }
+ return result;
+}
+
+
+
+//
+// Get the amount of properties assiocated with this value
+//
+int CValue::GetPropertyCount()
+{
+ if (m_pNamedPropertyArray)
+ return m_pNamedPropertyArray->size();
+ else
+ return 0;
+}
+
+
+
+
+
+void CValue::CloneProperties(CValue *replica)
+{
+
+ if (m_pNamedPropertyArray)
+ {
+ replica->m_pNamedPropertyArray=NULL;
+ for ( std::map<const STR_String,CValue*>::iterator it = m_pNamedPropertyArray->begin();
+ !(it == m_pNamedPropertyArray->end());it++)
+ {
+
+ replica->SetProperty((*it).first,(*it).second->GetReplica());
+ }
+ }
+
+
+}
+
+
+
+
+
+
+double* CValue::GetVector3(bool bGetTransformedVec)
+{
+ assertd(false); // don;t get vector from me
+ return m_sZeroVec;//::sZero;
+}
+
+
+
+
+
+
+/*---------------------------------------------------------------------------------------------------------------------
+ Reference Counting
+---------------------------------------------------------------------------------------------------------------------*/
+
+
+
+//
+// Add a reference to this value
+//
+CValue *CValue::AddRef()
+{
+ // Increase global reference count, used to see at the end of the program
+ // if all CValue-derived classes have been dereferenced to 0
+ //debug(gRefCountValue++);
+ m_refcount++;
+ return this;
+}
+
+
+
+//
+// Release a reference to this value (when reference count reaches 0, the value is removed from the heap)
+//
+int CValue::Release()
+{
+ // Decrease global reference count, used to see at the end of the program
+ // if all CValue-derived classes have been dereferenced to 0
+ //debug(gRefCountValue--);
+
+ // Decrease local reference count, if it reaches 0 the object should be freed
+ if (--m_refcount > 0)
+ {
+ // Reference count normal, return new reference count
+ return m_refcount;
+ }
+ else
+ {
+ // Reference count reached 0, delete ourselves and return 0
+// assert(m_refcount==0, "Reference count reached sub-zero, object released too much");
+ delete this;
+ return 0;
+ }
+
+}
+
+
+
+//
+// Disable reference counting for this value
+//
+void CValue::DisableRefCount()
+{
+ assertd(m_refcount == 1);
+ m_refcount--;
+
+ //debug(gRefCountValue--);
+ m_ValFlags.RefCountDisabled=true;
+}
+
+
+
+void CValue::AddDataToReplica(CValue *replica)
+{
+ replica->m_refcount = 1;
+#ifdef _DEBUG
+ //gRefCountValue++;
+#endif
+ replica->m_ValFlags.RefCountDisabled = false;
+
+ replica->ReplicaSetName(GetName());
+
+ //copy all props
+ CloneProperties(replica);
+}
+
+
+
+CValue* CValue::FindIdentifier(const STR_String& identifiername)
+{
+
+ CValue* result = NULL;
+
+ int pos = 0;
+ // if a dot exists, explode the name into pieces to get the subcontext
+ if ((pos=identifiername.Find('.'))>=0)
+ {
+ const STR_String rightstring = identifiername.Right(identifiername.Length() -1 - pos);
+ const STR_String leftstring = identifiername.Left(pos);
+ CValue* tempresult = GetProperty(leftstring);
+ if (tempresult)
+ {
+ result=tempresult->FindIdentifier(rightstring);
+ }
+ } else
+ {
+ result = GetProperty(identifiername);
+ }
+ if (result)
+ return result->AddRef();
+ // warning here !!!
+ result = new CErrorValue(identifiername+" not found");
+ return result;
+}
+
+
+#ifndef NO_EXP_PYTHON_EMBEDDING
+
+
+static PyMethodDef CValueMethods[] =
+{
+ //{ "new", CValue::PyMake , Py_NEWARGS},
+ { NULL,NULL} // Sentinel
+};
+
+
+PyObject* CValue::_getattr(char* attr)
+{
+ CValue* resultattr = FindIdentifier(attr);
+ STR_String text;
+ if (resultattr)
+ {
+ if (resultattr->IsError())
+ {
+ resultattr->Release();
+ } else
+ {
+ // to avoid some compare problems, return a real pythonthing
+ PyObject* pyconvert = resultattr->ConvertValueToPython();
+ if (pyconvert)
+ {
+ resultattr->Release();
+ return pyconvert;
+ } else
+ {
+ // also check if it's already in pythoninterpreter!
+ return resultattr;
+ }
+
+ }
+ }
+ _getattr_up(PyObjectPlus);
+}
+
+CValue* CValue::ConvertPythonToValue(PyObject* pyobj)
+{
+
+ CValue* vallie = NULL;
+
+ PyTypeObject* type = pyobj->ob_type;
+
+ if (type == &PyList_Type)
+ {
+ CListValue* listval = new CListValue();
+ bool error = false;
+
+ int i;
+ int numitems = PyList_Size(pyobj);
+ for (i=0;i<numitems;i++)
+ {
+ PyObject* listitem = PyList_GetItem(pyobj,i);
+ CValue* listitemval = ConvertPythonToValue(listitem);
+ if (listitemval)
+ {
+ listval->Add(listitemval);
+ } else
+ {
+ error = true;
+ }
+ }
+ if (!error)
+ {
+ // jippie! could be converted
+ vallie = listval;
+ } else
+ {
+ // list could not be converted... bad luck
+ listval->Release();
+ }
+
+ } else
+ if (type == &PyFloat_Type)
+ {
+ float fl;
+ PyArg_Parse(pyobj,"f",&fl);
+ vallie = new CFloatValue(fl);
+ } else
+ if (type==&PyInt_Type)
+ {
+ int innie;
+ PyArg_Parse(pyobj,"i",&innie);
+ vallie = new CIntValue(innie);
+ } else
+
+ if (type==&PyString_Type)
+ {
+ vallie = new CStringValue(PyString_AsString(pyobj),"");
+ } else
+ if (type==&CValue::Type || type==&CListValue::Type)
+ {
+ vallie = ((CValue*) pyobj)->AddRef();
+ }
+ return vallie;
+
+}
+int CValue::_setattr(char* attr,PyObject* pyobj)
+{
+
+ if (!pyobj) { // member deletion
+ RemoveProperty(attr);
+ return 0;
+ }
+
+ CValue* vallie = ConvertPythonToValue(pyobj);
+ if (vallie)
+ {
+ CValue* oldprop = GetProperty(attr);
+
+ if (oldprop)
+ {
+ oldprop->SetValue(vallie);
+ } else
+ {
+ SetProperty(attr,vallie->AddRef());
+ }
+ vallie->Release();
+ }
+
+ //PyObjectPlus::_setattr(attr,value);
+ return 0;
+};
+/*
+PyObject* CValue::PyMake(PyObject* ignored,PyObject* args)
+{
+
+ //Py_Try(PyArg_ParseTuple(args,"s",&name));
+ Py_INCREF(Py_None);
+ return Py_None;//new CValue();
+}
+*/
+
+extern "C" {
+ void initCValue(void)
+ {
+ Py_InitModule("CValue",CValueMethods);
+ }
+}
+
+
+
+#endif //NO_EXP_PYTHON_EMBEDDING
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+/* These implementations were moved out of the header */
+
+void CValue::SetOwnerExpression(class CExpression* expr)
+{
+ /* intentionally empty */
+}
+
+void CValue::SetColorOperator(VALUE_OPERATOR op)
+{
+ /* intentionally empty */
+}
+void CValue::SetValue(CValue* newval)
+{
+ // no one should get here
+ assertd(newval->GetNumber() == 10121969);
+}
+///////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+
diff --git a/source/gameengine/Expressions/Value.h b/source/gameengine/Expressions/Value.h
new file mode 100644
index 00000000000..8131cc152bc
--- /dev/null
+++ b/source/gameengine/Expressions/Value.h
@@ -0,0 +1,467 @@
+/*
+ * Value.h: interface for the CValue class.
+ * $Id$
+ * Copyright (c) 1996-2000 Erwin Coumans <coockie@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. Erwin Coumans makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ */
+
+#ifdef WIN32
+#pragma warning (disable:4786)
+#endif //WIN32
+
+/////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////
+////
+//// Baseclass CValue
+//// Together with CExpression, CValue and it's derived classes can be used to
+//// parse expressions into a parsetree with error detecting/correcting capabilities
+//// also expandible by a CFactory pluginsystem
+////
+//// Features:
+//// Reference Counting (AddRef() / Release())
+//// Calculations (Calc() / CalcFinal())
+//// Configuration (Configure())
+//// Serialization (EdSerialize() / EdIdSerialize() / EdPtrSerialize() and macro PLUGIN_DECLARE_SERIAL
+//// Property system (SetProperty() / GetProperty() / FindIdentifier())
+//// Replication (GetReplica())
+//// Flags (IsSelected() / IsModified() / SetSelected()...)
+////
+//// Some small editor-specific things added
+//// A helperclass CompressorArchive handles the serialization
+////
+////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////
+#ifndef __VALUE_H__
+#define __VALUE_H__
+
+#include <map> // array functionality for the propertylist
+#include "STR_String.h" // STR_String class
+
+
+
+
+#ifndef GEN_NO_ASSERT
+#undef assert
+#define assert(exp) ((void)NULL)
+#endif
+
+
+#ifndef GEN_NO_TRACE
+#undef trace
+#define trace(exp) ((void)NULL)
+#endif
+
+#ifndef GEN_NO_DEBUG
+#undef debug
+#define debug(exp) ((void)NULL)
+#endif
+
+
+
+
+#ifndef GEN_NO_ASSERTD
+#undef assertd
+#define assertd(exp) ((void)NULL)
+#endif
+
+
+#ifndef USE_PRAGMA_ONCE
+#ifdef WIN32
+ #pragma once
+
+#endif //WIN32
+#endif
+
+#define EDITOR_LEVEL_VERSION 0x06
+
+enum VALUE_OPERATOR {
+
+ VALUE_ADD_OPERATOR, // +
+ VALUE_SUB_OPERATOR, // -
+ VALUE_MUL_OPERATOR, // *
+ VALUE_DIV_OPERATOR, // /
+ VALUE_NEG_OPERATOR, // -
+ VALUE_POS_OPERATOR, // +
+ VALUE_AND_OPERATOR, // &&
+ VALUE_OR_OPERATOR, // ||
+ VALUE_EQL_OPERATOR, // ==
+ VALUE_NEQ_OPERATOR, // !=
+ VALUE_GRE_OPERATOR, // >
+ VALUE_LES_OPERATOR, // <
+ VALUE_GEQ_OPERATOR, // >=
+ VALUE_LEQ_OPERATOR, // <=
+ VALUE_NOT_OPERATOR, // !
+ VALUE_NO_OPERATOR // no operation at all
+};
+
+enum VALUE_DATA_TYPE {
+ VALUE_NO_TYPE, // abstract baseclass
+ VALUE_INT_TYPE,
+ VALUE_FLOAT_TYPE,
+ VALUE_STRING_TYPE,
+ VALUE_BOOL_TYPE,
+ VALUE_ERROR_TYPE,
+ VALUE_EMPTY_TYPE,
+ VALUE_SOLID_TYPE,
+ VALUE_COMBISOLID_TYPE,
+ VALUE_VECTOR_TYPE,
+ VALUE_MENU_TYPE,
+ VALUE_ACTOR_TYPE,
+ VALUE_MAX_TYPE //only here to provide number of types
+};
+
+
+
+#ifdef _DEBUG
+//extern int gRefCountValue; // debugonly variable to check if all CValue Refences are Dereferenced at programexit
+#endif
+
+struct HashableInt
+{
+ HashableInt(int id) : mData(id) { }
+
+ unsigned long Hash() const { return 0;} ////}gHash(&mData, sizeof(int));}
+
+ bool operator==(HashableInt rhs) { return mData == rhs.mData; }
+
+ int mData;
+};
+
+
+//
+// Bitfield that stores the flags for each CValue derived class
+//
+struct ValueFlags {
+ ValueFlags() :
+ Modified(true),
+ Selected(false),
+ Affected(false),
+ ReleaseRequested(false),
+ Error(false),
+ RefCountDisabled(false),
+ HasProperties(false),
+ HasName(false),
+ Visible(true),
+ CustomFlag1(false),
+ CustomFlag2(false)
+ {
+ }
+
+ unsigned short Modified : 1;
+ unsigned short Selected : 1;
+ unsigned short Affected : 1;
+ unsigned short ReleaseRequested : 1;
+ unsigned short Error : 1;
+ unsigned short RefCountDisabled : 1;
+ unsigned short HasProperties : 1;
+ unsigned short HasName : 1;
+ unsigned short Visible : 1;
+ unsigned short CustomFlag1 : 1;
+ unsigned short CustomFlag2 : 1;
+
+
+};
+
+/**
+ * Base Class for all Actions performed on CValue's. Can be extended for undo/redo system in future.
+*/
+class CAction
+{
+public:
+ CAction() {
+ };
+ virtual ~CAction(){
+ };
+ virtual void Execute() const =0;
+};
+
+//
+// CValue
+//
+// Base class for all editor functionality, flexible object type that allows
+// calculations and uses reference counting for memory management.
+//
+//
+
+/**
+ * These macros are helpfull when embedding Python routines. The second
+ * macro is one that also requires a documentation string
+ */
+#define KX_PYMETHOD(class_name, method_name) \
+ PyObject* Py##method_name(PyObject* self, PyObject* args, PyObject* kwds); \
+ static PyObject* sPy##method_name( PyObject* self, PyObject* args, PyObject* kwds) { \
+ return ((class_name*) self)->Py##method_name(self, args, kwds); \
+ }; \
+
+#define KX_PYMETHOD_DOC(class_name, method_name) \
+ PyObject* Py##method_name(PyObject* self, PyObject* args, PyObject* kwds); \
+ static PyObject* sPy##method_name( PyObject* self, PyObject* args, PyObject* kwds) { \
+ return ((class_name*) self)->Py##method_name(self, args, kwds); \
+ }; \
+ static char method_name##_doc[]; \
+
+/* The line above should remain empty */
+
+#ifndef NO_EXP_PYTHON_EMBEDDING
+#include "PyObjectPlus.h"
+#include "object.h"
+class CValue : public PyObjectPlus
+#else
+class CValue
+#endif //NO_EXP_PYTHON_EMBEDDING
+
+
+{
+#ifndef NO_EXP_PYTHON_EMBEDDING
+Py_Header;
+#endif //NO_EXP_PYTHON_EMBEDDING
+public:
+ enum AllocationTYPE {
+ STACKVALUE = 0,
+ HEAPVALUE = 1
+ };
+
+ enum DrawTYPE {
+ STARTFRAME = 0,
+ ENDFRAME = 1,
+ INTERFRAME = 2
+ };
+
+
+ // Construction / Destruction
+#ifndef NO_EXP_PYTHON_EMBEDDING
+
+ CValue(PyTypeObject *T = &Type);
+ //static PyObject* PyMake(PyObject*,PyObject*);
+ virtual PyObject *_repr(void)
+ {
+ return Py_BuildValue("s",(const char*)GetText());
+ }
+
+
+
+ PyObject* _getattr(char* attr);
+
+ void SpecialRelease()
+ {
+ int i=0;
+ if (ob_refcnt == 0)
+ {
+ _Py_NewReference(this);
+
+ } else
+ {
+ i++;
+ }
+ Release();
+ }
+ static void PyDestructor(PyObject *P) // python wrapper
+ {
+ ((CValue*)P)->SpecialRelease();
+ };
+
+ virtual PyObject* ConvertValueToPython() {
+ return NULL;
+ }
+
+ virtual CValue* ConvertPythonToValue(PyObject* pyobj);
+
+
+ int _setattr(char* attr,PyObject* value);
+
+ KX_PYMETHOD(CValue,GetName);
+
+#else
+ CValue();
+#endif //NO_EXP_PYTHON_EMBEDDING
+
+
+
+ // Expression Calculation
+ virtual CValue* Calc(VALUE_OPERATOR op, CValue *val) = 0;
+ virtual CValue* CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val) = 0;
+ virtual void SetOwnerExpression(class CExpression* expr);
+
+
+
+ void Execute(const CAction& a)
+ {
+ a.Execute();
+ };
+
+ /// Reference Counting
+ int GetRefCount() { return m_refcount; }
+ virtual CValue* AddRef(); // Add a reference to this value
+ virtual int Release(); // Release a reference to this value (when reference count reaches 0, the value is removed from the heap)
+
+ /// Property Management
+ virtual void SetProperty(const STR_String& name,CValue* ioProperty); // Set property <ioProperty>, overwrites and releases a previous property with the same name if needed
+ virtual CValue* GetProperty(const STR_String & inName); // Get pointer to a property with name <inName>, returns NULL if there is no property named <inName>
+ STR_String GetPropertyText(const STR_String & inName,const STR_String& deftext=""); // Get text description of property with name <inName>, returns an empty string if there is no property named <inName>
+ float GetPropertyNumber(const STR_String& inName,float defnumber);
+ virtual bool RemoveProperty(const STR_String & inName); // Remove the property named <inName>, returns true if the property was succesfully removed, false if property was not found or could not be removed
+ virtual void ClearProperties(); // Clear all properties
+
+ virtual void SetPropertiesModified(bool inModified); // Set all properties' modified flag to <inModified>
+ virtual bool IsAnyPropertyModified(); // Check if any of the properties in this value have been modified
+
+ virtual CValue* GetProperty(int inIndex); // Get property number <inIndex>
+ virtual int GetPropertyCount(); // Get the amount of properties assiocated with this value
+
+ virtual void CloneProperties(CValue* replica);
+ virtual CValue* FindIdentifier(const STR_String& identifiername);
+ /** Set the wireframe color of this value depending on the CSG
+ * operator type <op>
+ * @attention: not implemented */
+ virtual void SetColorOperator(VALUE_OPERATOR op);
+
+ virtual const STR_String & GetText() = 0;
+ virtual float GetNumber() = 0;
+ double* ZeroVector() { return m_sZeroVec; };
+ virtual double* GetVector3(bool bGetTransformedVec = false);
+
+ virtual STR_String GetName() = 0; // Retrieve the name of the value
+ virtual void SetName(STR_String name) = 0; // Set the name of the value
+ virtual void ReplicaSetName(STR_String name) = 0;
+ /** Sets the value to this cvalue.
+ * @attention this particular function should never be called. Why not abstract? */
+ virtual void SetValue(CValue* newval);
+ virtual CValue* GetReplica() =0;
+ //virtual CValue* Copy() = 0;
+
+
+ STR_String op2str(VALUE_OPERATOR op);
+
+ // setting / getting flags
+ inline void SetSelected(bool bSelected) { m_ValFlags.Selected = bSelected; }
+ virtual void SetModified(bool bModified) { m_ValFlags.Modified = bModified; }
+ virtual void SetAffected(bool bAffected=true) { m_ValFlags.Affected = bAffected; }
+ inline void SetReleaseRequested(bool bReleaseRequested) { m_ValFlags.ReleaseRequested=bReleaseRequested; }
+ inline void SetError(bool err) { m_ValFlags.Error=err; }
+ inline void SetVisible (bool vis) { m_ValFlags.Visible=vis; }
+
+ virtual bool IsModified() { return m_ValFlags.Modified; }
+ inline bool IsError() { return m_ValFlags.Error; }
+ virtual bool IsAffected() { return m_ValFlags.Affected || m_ValFlags.Modified; }
+ virtual bool IsSelected() { return m_ValFlags.Selected; }
+ inline bool IsReleaseRequested() { return m_ValFlags.ReleaseRequested; }
+ virtual bool IsVisible() { return m_ValFlags.Visible;}
+ virtual void SetCustomFlag1(bool bCustomFlag) { m_ValFlags.CustomFlag1 = bCustomFlag;};
+ virtual bool IsCustomFlag1() { return m_ValFlags.CustomFlag1;};
+
+ virtual void SetCustomFlag2(bool bCustomFlag) { m_ValFlags.CustomFlag2 = bCustomFlag;};
+ virtual bool IsCustomFlag2() { return m_ValFlags.CustomFlag2;};
+
+protected:
+ virtual void DisableRefCount(); // Disable reference counting for this value
+ virtual void AddDataToReplica(CValue* replica);
+ virtual ~CValue();
+private:
+ // Member variables
+ std::map<const STR_String,CValue*>* m_pNamedPropertyArray; // Properties for user/game etc
+ ValueFlags m_ValFlags; // Frequently used flags in a bitfield (low memoryusage)
+ int m_refcount; // Reference Counter
+ static double m_sZeroVec[3];
+
+};
+
+
+
+//
+// Declare a CValue or CExpression or CWhatever to be serialized by the editor.
+//
+// This macro introduces the EdSerialize() function (which must be implemented by
+// the client) and the EdIdSerialize() function (which is implemented by this macro).
+//
+// The generated Copy() function returns a pointer to <root_base_class_name> type
+// of object. So, for *any* CValue-derived object this should be set to CValue,
+// for *any* CExpression-derived object this should be set to CExpression.
+//
+#define PLUGIN_DECLARE_SERIAL(class_name, root_base_class_name) \
+public: \
+ virtual root_base_class_name * Copy() { return new class_name; } \
+ virtual bool EdSerialize(CompressorArchive& arch,class CFactoryManager* facmgr,bool bIsStoring); \
+ virtual bool EdIdSerialize(CompressorArchive& arch,class CFactoryManager* facmgr,bool bIsStoring) \
+{ \
+ if (bIsStoring) \
+ arch.StoreString(#class_name); \
+ \
+ return false; \
+} \
+
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+
+// CPropValue is a CValue derived class, that implements the identification (String name)
+// SetName() / GetName(),
+// normal classes should derive from CPropValue, real lightweight classes straight from CValue
+
+
+class CPropValue : public CValue
+{
+public:
+
+#ifndef NO_EXP_PYTHON_EMBEDDING
+ CPropValue(PyTypeObject* T=&Type) :
+ CValue(T),
+#else
+ CPropValue() :
+#endif //NO_EXP_PYTHON_EMBEDDING
+ m_pstrNewName(NULL)
+
+ {
+ }
+
+ virtual ~CPropValue()
+ {
+ if (m_pstrNewName)
+ {
+ delete m_pstrNewName;
+ m_pstrNewName = NULL;
+ }
+ }
+
+ virtual void SetName(STR_String name) {
+ if (m_pstrNewName)
+ {
+ delete m_pstrNewName;
+ m_pstrNewName = NULL;
+ }
+ if (name.Length())
+ m_pstrNewName = new STR_String(name);
+ }
+ virtual void ReplicaSetName(STR_String name) {
+ m_pstrNewName=NULL;
+ if (name.Length())
+ m_pstrNewName = new STR_String(name);
+ }
+
+ virtual STR_String GetName() {
+ //STR_String namefromprop = GetPropertyText("Name");
+ //if (namefromprop.Length() > 0)
+ // return namefromprop;
+
+ if (m_pstrNewName)
+ {
+ return *m_pstrNewName;
+ }
+ return STR_String("");
+ }; // name of Value
+
+protected:
+ STR_String* m_pstrNewName; // Identification
+};
+
+
+
+#endif // !defined _VALUEBASECLASS_H
diff --git a/source/gameengine/Expressions/VectorValue.cpp b/source/gameengine/Expressions/VectorValue.cpp
new file mode 100644
index 00000000000..6aa7926bfa7
--- /dev/null
+++ b/source/gameengine/Expressions/VectorValue.cpp
@@ -0,0 +1,213 @@
+// VectorValue.cpp: implementation of the CVectorValue class.
+/*
+ * Copyright (c) 1996-2000 Erwin Coumans <coockie@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. Erwin Coumans makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ */
+
+#ifdef WIN32
+#pragma warning (disable:4786)
+#endif
+
+#include "Value.h"
+#include "VectorValue.h"
+#include "ErrorValue.h"
+//#include "MatrixValue.h"
+#include "VoidValue.h"
+#include "StringValue.h"
+//#include "FactoryManager.h"
+
+
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CVectorValue::CVectorValue(float x,float y,float z, AllocationTYPE alloctype)
+{
+ SetCustomFlag1(false);//FancyOutput=false;
+
+ if (alloctype == STACKVALUE)
+ {
+ CValue::DisableRefCount();
+ };
+
+ m_vec[KX_X] = m_transformedvec[KX_X] = x;
+ m_vec[KX_Y] = m_transformedvec[KX_Y] = y;
+ m_vec[KX_Z] = m_transformedvec[KX_Z] = z;
+
+}
+CVectorValue::CVectorValue(double vec[],STR_String name,AllocationTYPE alloctype) {
+
+ SetCustomFlag1(false);//FancyOutput=false;
+
+ m_vec[KX_X] = m_transformedvec[KX_X] = vec[KX_X];
+ m_vec[KX_Y] = m_transformedvec[KX_Y] = vec[KX_Y];
+ m_vec[KX_Z] = m_transformedvec[KX_Z] = vec[KX_Z];
+
+ if (alloctype == STACKVALUE)
+ {
+ CValue::DisableRefCount();
+
+ }
+
+ SetName(name);
+}
+
+CVectorValue::CVectorValue(double vec[],AllocationTYPE alloctype) {
+
+ SetCustomFlag1(false);//FancyOutput=false;
+
+ m_vec[KX_X] = m_transformedvec[KX_X] = vec[KX_X];
+ m_vec[KX_Y] = m_transformedvec[KX_Y] = vec[KX_Y];
+ m_vec[KX_Z] = m_transformedvec[KX_Z] = vec[KX_Z];
+
+ if (alloctype == STACKVALUE)
+ {
+ CValue::DisableRefCount();
+
+ }
+
+
+}
+CVectorValue::~CVectorValue()
+{
+
+}
+
+CValue* CVectorValue::CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val)
+/*
+pre: the type of val is dtype
+ret: a new object containing the result of applying operator op to val and
+this object
+*/
+{
+ CValue *ret = NULL;
+
+ switch(op)
+ {
+ case VALUE_ADD_OPERATOR:
+ {
+ switch (dtype)
+ {
+ case VALUE_EMPTY_TYPE:
+ case VALUE_VECTOR_TYPE:
+ {
+ ret = new CVectorValue(
+ val->GetVector3()[KX_X] + GetVector3()[KX_X],
+ val->GetVector3()[KX_Y] + GetVector3()[KX_Y],
+ val->GetVector3()[KX_Z] + GetVector3()[KX_Z],
+ CValue::HEAPVALUE);
+ ret->SetName(GetName());
+ break;
+ }
+
+ default:
+ ret = new CErrorValue(val->GetText() + op2str(op) + GetText());
+ }
+ break;
+ }
+ case VALUE_MUL_OPERATOR:
+ {
+ switch (dtype)
+ {
+
+ case VALUE_EMPTY_TYPE:
+ case VALUE_VECTOR_TYPE:
+ {
+ //MT_Vector3 supports 'scaling' by another vector, instead of using general transform, Gino?
+ //ret = new CVectorValue(val->GetVector3().Scaled(GetVector3()),GetName());
+ break;
+ }
+ case VALUE_FLOAT_TYPE:
+ {
+ ret = new CVectorValue(
+ val->GetVector3()[KX_X] * GetVector3()[KX_X],
+ val->GetVector3()[KX_Y] * GetVector3()[KX_Y],
+ val->GetVector3()[KX_Z] * GetVector3()[KX_Z],
+ CValue::HEAPVALUE);
+ ret->SetName(GetName());
+ break;
+ }
+
+ default:
+ ret = new CErrorValue(val->GetText() + op2str(op) + GetText());
+ }
+ break;
+
+ }
+
+ default:
+ ret = new CErrorValue(val->GetText() + op2str(op) + GetText());
+ }
+
+
+ return ret;
+}
+
+float CVectorValue::GetNumber()
+{
+ return m_vec[KX_X];
+}
+
+
+double* CVectorValue::GetVector3(bool bGetTransformedVec)
+{
+ if (bGetTransformedVec)
+ return m_transformedvec;
+ // else
+ return m_vec;
+}
+
+
+
+
+
+void CVectorValue::SetVector(double newvec[])
+{
+ m_vec[KX_X] = m_transformedvec[KX_X] = newvec[KX_X];
+ m_vec[KX_Y] = m_transformedvec[KX_Y] = newvec[KX_Y];
+ m_vec[KX_Z] = m_transformedvec[KX_Z] = newvec[KX_Z];
+
+ SetModified(true);
+}
+
+
+void CVectorValue::SetValue(CValue *newval)
+{
+
+ double* newvec = ((CVectorValue*)newval)->GetVector3();
+ m_vec[KX_X] = m_transformedvec[KX_X] = newvec[KX_X];
+ m_vec[KX_Y] = m_transformedvec[KX_Y] = newvec[KX_Y];
+ m_vec[KX_Z] = m_transformedvec[KX_Z] = newvec[KX_Z];
+
+ SetModified(true);
+}
+
+static const STR_String gstrVectorStr=STR_String();
+const STR_String & CVectorValue::GetText()
+{
+ assertd(false);
+ return gstrVectorStr;
+}
+
+CValue* CVectorValue::GetReplica() {
+ CVectorValue* replica = new CVectorValue(*this);
+ CValue::AddDataToReplica(replica);
+ return replica;
+};
+
+/*void CVectorValue::Transform(rcMatrix4x4 mat)
+{
+ m_transformedvec = mat*m_vec;
+}
+*/
+
+
diff --git a/source/gameengine/Expressions/VectorValue.h b/source/gameengine/Expressions/VectorValue.h
new file mode 100644
index 00000000000..8ed671721a3
--- /dev/null
+++ b/source/gameengine/Expressions/VectorValue.h
@@ -0,0 +1,86 @@
+/*
+ * VectorValue.h: interface for the CVectorValue class.
+ * $Id$
+ * Copyright (c) 1996-2000 Erwin Coumans <coockie@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. Erwin Coumans makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ */
+#if !defined _VECTORVALUE_H
+#define _VECTORVALUE_H
+
+
+#include "Value.h"
+
+#define KX_X 0
+#define KX_Y 1
+#define KX_Z 2
+
+
+class CVectorValue : public CPropValue
+{
+ //PLUGIN_DECLARE_SERIAL(CVectorValue,CValue)
+
+public:
+ //void Transform(rcMatrix4x4 mat);
+ virtual void SetValue(CValue* newval);
+ void SetVector(double newvec[]);
+ void Configure(CValue* menuvalue);
+ virtual double* GetVector3(bool bGetTransformedVec=false);
+ virtual float GetNumber();
+
+ CValue* Calc(VALUE_OPERATOR op, CValue *val) {
+ return val->CalcFinal(VALUE_VECTOR_TYPE, op, this);
+ }
+
+ CValue* CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val);
+
+
+ CVectorValue(double vec[],STR_String name,AllocationTYPE alloctype=CValue::HEAPVALUE);
+ CVectorValue() {};
+
+ CVectorValue(double vec[],AllocationTYPE alloctype=CValue::HEAPVALUE);
+ CVectorValue(float x,float y,float z, AllocationTYPE alloctype = CValue::HEAPVALUE);
+ virtual ~CVectorValue();
+ //virtual bool ExportT3D(File *txtfile,bool bNoName=false);
+ void AddConfigurationData(CValue* menuvalue);
+
+
+
+ virtual CValue* GetReplica();
+ virtual const STR_String & GetText();
+
+/*
+ void SnapPoint(float num,int snap)
+ {
+ if (num > 0) num += ((float)snap / 2);
+ else num -= ((float)snap / 2);
+ num = (long)(((long)(num / snap)) * snap);
+ };
+
+ void SnapPosition(const double snapvec[])
+ {
+
+ if (snapvec[KX_X] >= 1)
+ SnapPoint(m_vec[KX_X],snapvec[KX_X]);
+ if (snapvec[KX_Y] >= 1)
+ SnapPoint(m_vec[KX_Y],snapvec[KX_Y]);
+ if (snapvec[KX_Z] >= 1)
+ SnapPoint(m_vec[KX_Z],snapvec[KX_Z]);
+
+ }
+*/
+
+protected:
+ double m_vec[3];
+ double m_transformedvec[3];
+};
+
+#endif // !defined _VECTORVALUE_H
+
diff --git a/source/gameengine/Expressions/VoidValue.h b/source/gameengine/Expressions/VoidValue.h
new file mode 100644
index 00000000000..5cf40268b97
--- /dev/null
+++ b/source/gameengine/Expressions/VoidValue.h
@@ -0,0 +1,68 @@
+/**
+ * VoidValue.h: interface for the CVoidValue class.
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 __VOIDVALUE_H__
+#define __VOIDVALUE_H__
+
+#include "Value.h"
+
+
+//
+// Void value, used to transport *any* type of data
+//
+class CVoidValue : public CPropValue
+{
+ //PLUGIN_DECLARE_SERIAL (CVoidValue,CValue)
+
+public:
+ /// Construction/destruction
+ CVoidValue() : m_pAnything(NULL), m_bDeleteOnDestruct(false) { }
+ CVoidValue(void * voidptr, bool bDeleteOnDestruct, AllocationTYPE alloctype) : m_pAnything(voidptr), m_bDeleteOnDestruct(bDeleteOnDestruct) { if (alloctype == STACKVALUE) CValue::DisableRefCount(); }
+ virtual ~CVoidValue(); // Destruct void value, delete memory if we're owning it
+
+ /// Value -> String or number
+ virtual const STR_String & GetText(); // Get string description of void value (unimplemented)
+ virtual float GetNumber() { return -1; }
+
+ /// Value calculation
+ virtual CValue* Calc(VALUE_OPERATOR op, CValue *val);
+ virtual CValue* CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue* val);
+
+ /// Value replication
+ virtual CValue* GetReplica();
+
+ /// Data members
+ bool m_bDeleteOnDestruct;
+ void* m_pAnything;
+};
+
+#endif // !defined _VOIDVALUE_H
diff --git a/source/gameengine/GameLogic/Makefile b/source/gameengine/GameLogic/Makefile
new file mode 100644
index 00000000000..6de9ba0b145
--- /dev/null
+++ b/source/gameengine/GameLogic/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 = logic
+DIR = $(OCGDIR)/gameengine/$(LIBNAME)
+
+include nan_compile.mk
+
+CCFLAGS += $(LEVEL_1_CPP_WARNINGS)
+
+CPPFLAGS += -I../Expressions
+CPPFLAGS += -I$(NAN_STRING)/include
+CPPFLAGS += -I$(NAN_MOTO)/include
+CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION)
+CPPFLAGS += -I../../kernel/gen_system
+CPPFLAGS += -I../Ketsji
+
diff --git a/source/gameengine/GameLogic/SCA_ANDController.cpp b/source/gameengine/GameLogic/SCA_ANDController.cpp
new file mode 100644
index 00000000000..3dc20490819
--- /dev/null
+++ b/source/gameengine/GameLogic/SCA_ANDController.cpp
@@ -0,0 +1,143 @@
+/**
+ * 'And' together all inputs
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "SCA_ANDController.h"
+#include "SCA_ISensor.h"
+#include "SCA_LogicManager.h"
+#include "BoolValue.h"
+
+/* ------------------------------------------------------------------------- */
+/* Native functions */
+/* ------------------------------------------------------------------------- */
+
+SCA_ANDController::SCA_ANDController(SCA_IObject* gameobj,
+ PyTypeObject* T)
+ :
+ SCA_IController(gameobj,T)
+{
+}
+
+
+
+SCA_ANDController::~SCA_ANDController()
+{
+}
+
+
+
+void SCA_ANDController::Trigger(SCA_LogicManager* logicmgr)
+{
+
+ bool sensorresult = true;
+
+ for (vector<SCA_ISensor*>::const_iterator is=m_linkedsensors.begin();
+ !(is==m_linkedsensors.end());is++)
+ {
+ SCA_ISensor* sensor = *is;
+ if (!sensor->IsPositiveTrigger())
+ {
+ sensorresult = false;
+ break;
+ }
+ }
+
+ CValue* newevent = new CBoolValue(sensorresult);
+
+ for (vector<SCA_IActuator*>::const_iterator i=m_linkedactuators.begin();
+ !(i==m_linkedactuators.end());i++)
+ {
+ SCA_IActuator* actua = *i;//m_linkedactuators.at(i);
+ logicmgr->AddActiveActuator(actua,newevent);
+ }
+
+ // every actuator that needs the event, has a it's own reference to it now so
+ // release it (so to be clear: if there is no actuator, it's deleted right now)
+ newevent->Release();
+
+}
+
+
+
+CValue* SCA_ANDController::GetReplica()
+{
+ CValue* replica = new SCA_ANDController(*this);
+ // this will copy properties and so on...
+ CValue::AddDataToReplica(replica);
+
+ return replica;
+}
+
+
+
+/* ------------------------------------------------------------------------- */
+/* Python functions */
+/* ------------------------------------------------------------------------- */
+
+/* Integration hooks ------------------------------------------------------- */
+PyTypeObject SCA_ANDController::Type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0,
+ "SCA_ANDController",
+ sizeof(SCA_ANDController),
+ 0,
+ PyDestructor,
+ 0,
+ __getattr,
+ __setattr,
+ 0, //&MyPyCompare,
+ __repr,
+ 0, //&cvalue_as_number,
+ 0,
+ 0,
+ 0,
+ 0
+};
+
+PyParentObject SCA_ANDController::Parents[] = {
+ &SCA_ANDController::Type,
+ &SCA_IController::Type,
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
+};
+
+PyMethodDef SCA_ANDController::Methods[] = {
+ {NULL,NULL} //Sentinel
+};
+
+PyObject* SCA_ANDController::_getattr(char* attr) {
+ _getattr_up(SCA_IController);
+}
+
+/* eof */
diff --git a/source/gameengine/GameLogic/SCA_ANDController.h b/source/gameengine/GameLogic/SCA_ANDController.h
new file mode 100644
index 00000000000..a7d54004f90
--- /dev/null
+++ b/source/gameengine/GameLogic/SCA_ANDController.h
@@ -0,0 +1,58 @@
+/**
+ * SCA_ANDController.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 __KX_ANDCONTROLLER
+#define __KX_ANDCONTROLLER
+
+#include "SCA_IController.h"
+
+class SCA_ANDController : public SCA_IController
+{
+ Py_Header;
+ //virtual void Trigger(class SCA_LogicManager* logicmgr);
+public:
+ SCA_ANDController(SCA_IObject* gameobj,PyTypeObject* T=&Type);
+ virtual ~SCA_ANDController();
+ virtual CValue* GetReplica();
+ virtual void Trigger(SCA_LogicManager* logicmgr);
+
+ /* --------------------------------------------------------------------- */
+ /* Python interface ---------------------------------------------------- */
+ /* --------------------------------------------------------------------- */
+
+ virtual PyObject* _getattr(char *attr);
+
+};
+
+#endif //__KX_ANDCONTROLLER
diff --git a/source/gameengine/GameLogic/SCA_AlwaysEventManager.cpp b/source/gameengine/GameLogic/SCA_AlwaysEventManager.cpp
new file mode 100644
index 00000000000..0e2db162ec3
--- /dev/null
+++ b/source/gameengine/GameLogic/SCA_AlwaysEventManager.cpp
@@ -0,0 +1,67 @@
+/**
+ * Manager for 'always' events. Since always sensors can operate in pulse
+ * mode, they need to be activated.
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "SCA_AlwaysEventManager.h"
+#include "SCA_LogicManager.h"
+#include <vector>
+#include "SCA_ISensor.h"
+
+using namespace std;
+
+
+
+SCA_AlwaysEventManager::SCA_AlwaysEventManager(class SCA_LogicManager* logicmgr)
+ : m_logicmgr(logicmgr),
+ SCA_EventManager(ALWAYS_EVENTMGR)
+{
+}
+
+
+
+void SCA_AlwaysEventManager::NextFrame(double curtime,double deltatime)
+{
+ for (vector<class SCA_ISensor*>::const_iterator i= m_sensors.begin();!(i==m_sensors.end());i++)
+ {
+ SCA_ISensor* sensor = *i;
+ sensor->Activate(m_logicmgr, NULL);
+ }
+}
+
+
+
+void SCA_AlwaysEventManager::RegisterSensor(SCA_ISensor* sensor)
+{
+ m_sensors.push_back(sensor);
+}
diff --git a/source/gameengine/GameLogic/SCA_AlwaysEventManager.h b/source/gameengine/GameLogic/SCA_AlwaysEventManager.h
new file mode 100644
index 00000000000..0fbf02c5212
--- /dev/null
+++ b/source/gameengine/GameLogic/SCA_AlwaysEventManager.h
@@ -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 *****
+ */
+#ifndef __KX_ALWAYSEVENTMGR
+#define __KX_ALWAYSEVENTMGR
+#include "SCA_EventManager.h"
+#include <vector>
+using namespace std;
+class SCA_AlwaysEventManager : public SCA_EventManager
+{
+
+ class SCA_LogicManager* m_logicmgr;
+public:
+ SCA_AlwaysEventManager(class SCA_LogicManager* logicmgr);
+ virtual void NextFrame(double curtime,double deltatime);
+ virtual void RegisterSensor(SCA_ISensor* sensor);
+
+
+};
+#endif //__KX_ALWAYSEVENTMGR
diff --git a/source/gameengine/GameLogic/SCA_AlwaysSensor.cpp b/source/gameengine/GameLogic/SCA_AlwaysSensor.cpp
new file mode 100644
index 00000000000..cf78d109e16
--- /dev/null
+++ b/source/gameengine/GameLogic/SCA_AlwaysSensor.cpp
@@ -0,0 +1,138 @@
+/**
+ * Always trigger
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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
+// 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
+
+#include "SCA_AlwaysSensor.h"
+#include "SCA_LogicManager.h"
+#include "SCA_EventManager.h"
+
+/* ------------------------------------------------------------------------- */
+/* Native functions */
+/* ------------------------------------------------------------------------- */
+
+SCA_AlwaysSensor::SCA_AlwaysSensor(class SCA_EventManager* eventmgr,
+ SCA_IObject* gameobj,
+ PyTypeObject* T)
+ : SCA_ISensor(gameobj,eventmgr, T)
+{
+ //SetDrawColor(255,0,0);
+ m_alwaysresult = true;
+}
+
+
+
+SCA_AlwaysSensor::~SCA_AlwaysSensor()
+{
+ /* intentionally empty */
+}
+
+
+
+CValue* SCA_AlwaysSensor::GetReplica()
+{
+ CValue* replica = new SCA_AlwaysSensor(*this);//m_float,GetName());
+ // this will copy properties and so on...
+ CValue::AddDataToReplica(replica);
+
+ return replica;
+}
+
+
+
+bool SCA_AlwaysSensor::IsPositiveTrigger()
+{
+ return (m_invert ? false : true);
+}
+
+
+
+bool SCA_AlwaysSensor::Evaluate(CValue* event)
+{
+ /* Nice! :) */
+ //return true;
+ /* even nicer ;) */
+ //return false;
+
+ /* nicest ! */
+ bool result = m_alwaysresult;
+ m_alwaysresult = false;
+ return result;
+}
+
+/* ------------------------------------------------------------------------- */
+/* Python functions */
+/* ------------------------------------------------------------------------- */
+
+/* Integration hooks ------------------------------------------------------- */
+PyTypeObject SCA_AlwaysSensor::Type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0,
+ "SCA_AlwaysSensor",
+ sizeof(SCA_AlwaysSensor),
+ 0,
+ PyDestructor,
+ 0,
+ __getattr,
+ __setattr,
+ 0, //&MyPyCompare,
+ __repr,
+ 0, //&cvalue_as_number,
+ 0,
+ 0,
+ 0,
+ 0
+};
+
+PyParentObject SCA_AlwaysSensor::Parents[] = {
+ &SCA_AlwaysSensor::Type,
+ &SCA_ISensor::Type,
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
+};
+
+PyMethodDef SCA_AlwaysSensor::Methods[] = {
+ {NULL,NULL} //Sentinel
+};
+
+PyObject* SCA_AlwaysSensor::_getattr(char* attr) {
+ _getattr_up(SCA_ISensor);
+}
+
+/* eof */
diff --git a/source/gameengine/GameLogic/SCA_AlwaysSensor.h b/source/gameengine/GameLogic/SCA_AlwaysSensor.h
new file mode 100644
index 00000000000..c6ff571be8a
--- /dev/null
+++ b/source/gameengine/GameLogic/SCA_AlwaysSensor.h
@@ -0,0 +1,62 @@
+/**
+ * SCA_AlwaysSensor.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 __KX_ALWAYSSENSOR
+#define __KX_ALWAYSSENSOR
+#include "SCA_ISensor.h"
+
+
+class SCA_AlwaysSensor : public SCA_ISensor
+{
+ Py_Header;
+ bool m_alwaysresult;
+public:
+ SCA_AlwaysSensor(class SCA_EventManager* eventmgr,
+ SCA_IObject* gameobj,
+ PyTypeObject* T =&Type);
+ virtual ~SCA_AlwaysSensor();
+ virtual CValue* GetReplica();
+ virtual bool Evaluate(CValue* event);
+ virtual bool IsPositiveTrigger();
+
+ /* --------------------------------------------------------------------- */
+ /* Python interface ---------------------------------------------------- */
+ /* --------------------------------------------------------------------- */
+
+ virtual PyObject* _getattr(char *attr);
+
+
+};
+
+#endif //__KX_ALWAYSSENSOR
diff --git a/source/gameengine/GameLogic/SCA_EventManager.cpp b/source/gameengine/GameLogic/SCA_EventManager.cpp
new file mode 100644
index 00000000000..a6ce3a1af25
--- /dev/null
+++ b/source/gameengine/GameLogic/SCA_EventManager.cpp
@@ -0,0 +1,71 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "SCA_EventManager.h"
+
+
+
+SCA_EventManager::SCA_EventManager(EVENT_MANAGER_TYPE mgrtype)
+ :m_mgrtype(mgrtype)
+{
+}
+
+
+
+SCA_EventManager::~SCA_EventManager()
+{
+}
+
+
+
+void SCA_EventManager::RemoveSensor(class SCA_ISensor* sensor)
+{
+ std::vector<SCA_ISensor*>::iterator i =
+ std::find(m_sensors.begin(), m_sensors.end(), sensor);
+ if (!(i == m_sensors.end()))
+ {
+ std::swap(*i, m_sensors.back());
+ m_sensors.pop_back();
+ }
+}
+
+
+void SCA_EventManager::EndFrame()
+{
+}
+
+
+
+int SCA_EventManager::GetType()
+{
+ return (int) m_mgrtype;
+}
diff --git a/source/gameengine/GameLogic/SCA_EventManager.h b/source/gameengine/GameLogic/SCA_EventManager.h
new file mode 100644
index 00000000000..30928af5354
--- /dev/null
+++ b/source/gameengine/GameLogic/SCA_EventManager.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 *****
+ */
+#ifndef __KX_EVENTMANAGER
+#define __KX_EVENTMANAGER
+
+#include <vector>
+#include <algorithm>
+
+class SCA_EventManager
+{
+protected:
+ std::vector <class SCA_ISensor*> m_sensors;
+
+public:
+ enum EVENT_MANAGER_TYPE {
+ KEYBOARD_EVENTMGR = 0,
+ MOUSE_EVENTMGR,
+ ALWAYS_EVENTMGR,
+ TOUCH_EVENTMGR,
+ PROPERTY_EVENTMGR,
+ TIME_EVENTMGR,
+ RANDOM_EVENTMGR,
+ RAY_EVENTMGR,
+ RADAR_EVENTMGR,
+ NETWORK_EVENTMGR
+ };
+
+ SCA_EventManager(EVENT_MANAGER_TYPE mgrtype);
+ virtual ~SCA_EventManager();
+
+ virtual void RemoveSensor(class SCA_ISensor* sensor);
+ virtual void NextFrame(double curtime,double deltatime)=0;
+ virtual void EndFrame();
+ virtual void RegisterSensor(class SCA_ISensor* sensor)=0;
+ int GetType();
+
+protected:
+ EVENT_MANAGER_TYPE m_mgrtype;
+};
+#endif
diff --git a/source/gameengine/GameLogic/SCA_ExpressionController.cpp b/source/gameengine/GameLogic/SCA_ExpressionController.cpp
new file mode 100644
index 00000000000..56934a695f2
--- /dev/null
+++ b/source/gameengine/GameLogic/SCA_ExpressionController.cpp
@@ -0,0 +1,161 @@
+/**
+ * 'Expression Controller enables to calculate an expression that wires inputs to output
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "SCA_ExpressionController.h"
+#include "SCA_ISensor.h"
+#include "SCA_LogicManager.h"
+#include "BoolValue.h"
+#include "InputParser.h"
+
+#include "MT_Transform.h" // for fuzzyZero
+
+/* ------------------------------------------------------------------------- */
+/* Native functions */
+/* ------------------------------------------------------------------------- */
+
+SCA_ExpressionController::SCA_ExpressionController(SCA_IObject* gameobj,
+ const STR_String& exprtext,
+ PyTypeObject* T)
+ :SCA_IController(gameobj,T),
+ m_exprText(exprtext)
+{
+}
+
+
+
+SCA_ExpressionController::~SCA_ExpressionController()
+{
+}
+
+
+
+CValue* SCA_ExpressionController::GetReplica()
+{
+ SCA_ExpressionController* replica = new SCA_ExpressionController(*this);
+ replica->m_exprText = m_exprText;
+ // this will copy properties and so on...
+ CValue::AddDataToReplica(replica);
+
+ return replica;
+}
+
+
+
+void SCA_ExpressionController::Trigger(SCA_LogicManager* logicmgr)
+{
+
+ bool expressionresult = false;
+
+ CParser parser;
+ parser.SetContext(this->AddRef());
+ CExpression* expr = parser.ProcessText(m_exprText);
+ if (expr)
+ {
+ CValue* value = expr->Calculate();
+ if (value)
+ {
+ if (value->IsError())
+ {
+ printf(value->GetText());
+ } else
+ {
+ float num = value->GetNumber();
+ expressionresult = !MT_fuzzyZero(num);
+ }
+ value->Release();
+
+ }
+ expr->Release();
+ }
+
+ /*
+
+ for (vector<SCA_ISensor*>::const_iterator is=m_linkedsensors.begin();
+ !(is==m_linkedsensors.end());is++)
+ {
+ SCA_ISensor* sensor = *is;
+ if (!sensor->IsPositiveTrigger())
+ {
+ sensorresult = false;
+ break;
+ }
+ }
+
+ */
+
+ CValue* newevent = new CBoolValue(expressionresult);
+
+ for (vector<SCA_IActuator*>::const_iterator i=m_linkedactuators.begin();
+ !(i==m_linkedactuators.end());i++)
+ {
+ SCA_IActuator* actua = *i;
+ logicmgr->AddActiveActuator(actua,newevent);
+ }
+ //printf("expr %d.",expressionresult);
+ // every actuator that needs the event, has a it's own reference to it now so
+ // release it (so to be clear: if there is no actuator, it's deleted right now)
+ newevent->Release();
+}
+
+
+
+CValue* SCA_ExpressionController::FindIdentifier(const STR_String& identifiername)
+{
+
+ CValue* identifierval = NULL;
+
+ for (vector<SCA_ISensor*>::const_iterator is=m_linkedsensors.begin();
+ !(is==m_linkedsensors.end());is++)
+ {
+ SCA_ISensor* sensor = *is;
+ if (sensor->GetName() == identifiername)
+ {
+ identifierval = new CBoolValue(sensor->IsPositiveTrigger());
+ //identifierval = sensor->AddRef();
+ }
+
+ //if (!sensor->IsPositiveTrigger())
+ //{
+ // sensorresult = false;
+ // break;
+ //}
+ }
+
+ if (identifierval)
+ return identifierval;
+
+ return GetParent()->FindIdentifier(identifiername);
+
+}
diff --git a/source/gameengine/GameLogic/SCA_ExpressionController.h b/source/gameengine/GameLogic/SCA_ExpressionController.h
new file mode 100644
index 00000000000..59f8b7a3e04
--- /dev/null
+++ b/source/gameengine/GameLogic/SCA_ExpressionController.h
@@ -0,0 +1,64 @@
+/**
+ * KX_EXPRESSIONController.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 __KX_EXPRESSIONCONTROLLER
+#define __KX_EXPRESSIONCONTROLLER
+
+#include "SCA_IController.h"
+
+
+class SCA_ExpressionController : public SCA_IController
+{
+// Py_Header;
+ STR_String m_exprText;
+
+public:
+ SCA_ExpressionController(SCA_IObject* gameobj,
+ const STR_String& exprtext,
+ PyTypeObject* T=&Type );
+
+ virtual ~SCA_ExpressionController();
+ virtual CValue* GetReplica();
+ virtual void Trigger(SCA_LogicManager* logicmgr);
+ virtual CValue* FindIdentifier(const STR_String& identifiername);
+
+ /* --------------------------------------------------------------------- */
+ /* Python interface ---------------------------------------------------- */
+ /* --------------------------------------------------------------------- */
+
+// virtual PyObject* _getattr(char *attr);
+
+};
+
+#endif //__KX_EXPRESSIONCONTROLLER
diff --git a/source/gameengine/GameLogic/SCA_IActuator.cpp b/source/gameengine/GameLogic/SCA_IActuator.cpp
new file mode 100644
index 00000000000..81efeb6e647
--- /dev/null
+++ b/source/gameengine/GameLogic/SCA_IActuator.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 "SCA_IActuator.h"
+
+
+using namespace std;
+
+SCA_IActuator::SCA_IActuator(SCA_IObject* gameobj,
+ PyTypeObject* T) :
+ SCA_ILogicBrick(gameobj,T)
+{
+ // nothing to do
+}
+
+
+
+void SCA_IActuator::AddEvent(CValue* event)
+{
+ m_events.push_back(event);
+}
+
+
+
+void SCA_IActuator::RemoveAllEvents()
+{ // remove event queue!
+ for (vector<CValue*>::iterator i=m_events.begin(); !(i==m_events.end());i++)
+ {
+ (*i)->Release();
+ }
+ m_events.clear();
+}
+
+
+
+bool SCA_IActuator::Update(double curtime,double deltatime)
+{
+ return true;
+}
+
+
+
+bool SCA_IActuator::IsNegativeEvent() const
+{
+ bool bPositiveEvent(false);
+ bool bNegativeEvent(false);
+
+ for (vector<CValue*>::const_iterator i=m_events.begin(); i!=m_events.end();++i)
+ {
+ if ((*i)->GetNumber() == 0.0f)
+ {
+ bNegativeEvent = true;
+ } else {
+ bPositiveEvent = true;
+ }
+ }
+
+ // if at least 1 positive event, return false
+
+ return !bPositiveEvent && bNegativeEvent;
+}
+
+
+
+void SCA_IActuator::ProcessReplica()
+{
+ m_events.clear();
+}
+
+
+
+SCA_IActuator::~SCA_IActuator()
+{
+ RemoveAllEvents();
+}
+
diff --git a/source/gameengine/GameLogic/SCA_IActuator.h b/source/gameengine/GameLogic/SCA_IActuator.h
new file mode 100644
index 00000000000..67dd374b216
--- /dev/null
+++ b/source/gameengine/GameLogic/SCA_IActuator.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 *****
+ */
+#ifndef __KX_IACTUATOR
+#define __KX_IACTUATOR
+
+#include "SCA_ILogicBrick.h"
+#include <vector>
+
+class SCA_IActuator : public SCA_ILogicBrick
+{
+protected:
+ std::vector<CValue*> m_events;
+ void RemoveAllEvents();
+
+public:
+ /**
+ * This class also inherits the default copy constructors
+ */
+
+ SCA_IActuator(SCA_IObject* gameobj,
+ PyTypeObject* T =&Type);
+
+ /**
+ * Update(...)
+ * Update the actuator based upon the events received since
+ * the last call to Update, the current time and deltatime the
+ * time elapsed in this frame ?
+ * It is the responsibility of concrete Actuators to clear
+ * their event's. This is usually done in the Update() method via
+ * a call to RemoveAllEvents()
+ */
+
+
+ virtual bool Update(double curtime,
+ double deltatime);
+
+ /**
+ * Add an event to an actuator.
+ */
+ void AddEvent(CValue* event);
+ virtual void ProcessReplica();
+
+ /**
+ * Return true iff all the current events
+ * are negative. The definition of negative event is
+ * not immediately clear. But usually refers to key-up events
+ * or events where no action is required.
+ */
+ bool IsNegativeEvent() const;
+ virtual ~SCA_IActuator();
+};
+#endif //__KX_IACTUATOR
diff --git a/source/gameengine/GameLogic/SCA_IController.cpp b/source/gameengine/GameLogic/SCA_IController.cpp
new file mode 100644
index 00000000000..78f1980afde
--- /dev/null
+++ b/source/gameengine/GameLogic/SCA_IController.cpp
@@ -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 *****
+ */
+
+#include "SCA_IController.h"
+
+#include "SCA_LogicManager.h"
+#include "SCA_IActuator.h"
+
+SCA_IController::SCA_IController(SCA_IObject* gameobj,
+ PyTypeObject* T)
+ :
+ SCA_ILogicBrick(gameobj,T)
+{
+}
+
+
+
+SCA_IController::~SCA_IController()
+{
+}
+
+
+
+const std::vector<class SCA_ISensor*>& SCA_IController::GetLinkedSensors()
+{
+ return m_linkedsensors;
+}
+
+
+
+const std::vector<class SCA_IActuator*>& SCA_IController::GetLinkedActuators()
+{
+ return m_linkedactuators;
+}
+
+
+
+void SCA_IController::UnlinkAllSensors()
+{
+ m_linkedsensors.clear();
+}
+
+
+
+void SCA_IController::UnlinkAllActuators()
+{
+ m_linkedactuators.clear();
+}
+
+
+
+/*
+void SCA_IController::Trigger(SCA_LogicManager* logicmgr)
+{
+ //for (int i=0;i<m_linkedactuators.size();i++)
+ for (vector<SCA_IActuator*>::const_iterator i=m_linkedactuators.begin();
+ !(i==m_linkedactuators.end());i++)
+ {
+ SCA_IActuator* actua = *i;//m_linkedactuators.at(i);
+
+ logicmgr->AddActiveActuator(actua);
+ }
+
+}
+*/
+
+void SCA_IController::LinkToActuator(SCA_IActuator* actua)
+{
+ m_linkedactuators.push_back(actua);
+}
+
+void SCA_IController::UnlinkActuator(class SCA_IActuator* actua)
+{
+ std::vector<class SCA_IActuator*>::iterator actit;
+ std::vector<class SCA_IActuator*>::iterator actfound = m_linkedactuators.end();
+ for (actit = m_linkedactuators.begin();!(actit==m_linkedactuators.end());++actit)
+ {
+ if ((*actit) == actua)
+ actfound = actit;
+
+ }
+ if (!(actfound==m_linkedactuators.end()))
+ {
+ m_linkedactuators.erase(actfound);
+ }
+
+}
+
+void SCA_IController::LinkToSensor(SCA_ISensor* sensor)
+{
+ m_linkedsensors.push_back(sensor);
+}
diff --git a/source/gameengine/GameLogic/SCA_IController.h b/source/gameengine/GameLogic/SCA_IController.h
new file mode 100644
index 00000000000..4f30e5ad71d
--- /dev/null
+++ b/source/gameengine/GameLogic/SCA_IController.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 *****
+ */
+#ifndef __KX_ICONTROLLER
+#define __KX_ICONTROLLER
+
+#include "SCA_ILogicBrick.h"
+
+class SCA_IController : public SCA_ILogicBrick
+{
+protected:
+ std::vector<class SCA_ISensor*> m_linkedsensors;
+ std::vector<class SCA_IActuator*> m_linkedactuators;
+public:
+ SCA_IController(SCA_IObject* gameobj,PyTypeObject* T);
+ virtual ~SCA_IController();
+ virtual void Trigger(class SCA_LogicManager* logicmgr)=0;
+ void LinkToSensor(SCA_ISensor* sensor);
+ void LinkToActuator(SCA_IActuator*);
+ const std::vector<class SCA_ISensor*>& GetLinkedSensors();
+ const std::vector<class SCA_IActuator*>& GetLinkedActuators();
+ void UnlinkAllSensors();
+ void UnlinkAllActuators();
+ void UnlinkActuator(class SCA_IActuator* actua);
+
+
+};
+#endif
diff --git a/source/gameengine/GameLogic/SCA_IInputDevice.cpp b/source/gameengine/GameLogic/SCA_IInputDevice.cpp
new file mode 100644
index 00000000000..75a78fe5871
--- /dev/null
+++ b/source/gameengine/GameLogic/SCA_IInputDevice.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 *****
+ */
+
+#include <iostream.h>
+
+#include "SCA_IInputDevice.h"
+
+
+
+SCA_IInputDevice::SCA_IInputDevice()
+ :
+ m_currentTable(0)
+{
+ ClearStatusTable(0);
+ ClearStatusTable(1);
+}
+
+
+
+SCA_IInputDevice::~SCA_IInputDevice()
+{
+}
+
+
+
+void SCA_IInputDevice::ClearStatusTable(int tableid)
+{
+ for (int i=0;i<SCA_IInputDevice::KX_MAX_KEYS;i++)
+ m_eventStatusTables[tableid][i]=SCA_InputEvent(SCA_InputEvent::KX_NO_INPUTSTATUS,0);
+}
+
+
+
+const SCA_InputEvent& SCA_IInputDevice::GetEventValue(SCA_IInputDevice::KX_EnumInputs inputcode)
+{
+ // cerr << "SCA_IInputDevice::GetEventValue" << endl;
+ return m_eventStatusTables[m_currentTable][inputcode];
+}
+
+
+
+int SCA_IInputDevice::GetNumActiveEvents()
+{
+ int num = 0;
+
+ // cerr << "SCA_IInputDevice::GetNumActiveEvents" << endl;
+
+ for (int i=0;i<SCA_IInputDevice::KX_MAX_KEYS;i++)
+ {
+ const SCA_InputEvent& event = m_eventStatusTables[m_currentTable][i];
+ if ((event.m_status == SCA_InputEvent::KX_JUSTACTIVATED)
+ || (event.m_status == SCA_InputEvent::KX_ACTIVE))
+ num++;
+ }
+
+ return num;
+}
+
+
+
+int SCA_IInputDevice::GetNumJustEvents()
+{
+ int num = 0;
+
+ // cerr << "SCA_IInputDevice::GetNumJustEvents" << endl;
+
+ for (int i=0;i<SCA_IInputDevice::KX_MAX_KEYS;i++)
+ {
+ const SCA_InputEvent& event = m_eventStatusTables[m_currentTable][i];
+ if ((event.m_status == SCA_InputEvent::KX_JUSTACTIVATED)
+ || (event.m_status == SCA_InputEvent::KX_JUSTRELEASED))
+ num++;
+ }
+
+ return num;
+}
+
+
+
+void SCA_IInputDevice::NextFrame()
+{
+ m_currentTable = 1 - m_currentTable;
+
+ // cerr << "SCA_IInputDevice::NextFrame " << GetNumActiveEvents() << endl;
+
+ for (int i=0;i<SCA_IInputDevice::KX_MAX_KEYS;i++)
+ {
+ switch (m_eventStatusTables[1 - m_currentTable][i].m_status)
+ {
+ case SCA_InputEvent::KX_NO_INPUTSTATUS:
+ m_eventStatusTables[m_currentTable][i]
+ = SCA_InputEvent(SCA_InputEvent::KX_NO_INPUTSTATUS, 1);
+ break;
+ case SCA_InputEvent::KX_JUSTACTIVATED:
+ m_eventStatusTables[m_currentTable][i]
+ = SCA_InputEvent(SCA_InputEvent::KX_ACTIVE, 1);
+ break;
+ case SCA_InputEvent::KX_ACTIVE:
+ m_eventStatusTables[m_currentTable][i]
+ = SCA_InputEvent(SCA_InputEvent::KX_ACTIVE, 1);
+ break;
+ case SCA_InputEvent::KX_JUSTRELEASED:
+ m_eventStatusTables[m_currentTable][i]
+ = SCA_InputEvent(SCA_InputEvent::KX_NO_INPUTSTATUS, 1);
+ break;
+ default:
+ ; /* error */
+ }
+ }
+}
diff --git a/source/gameengine/GameLogic/SCA_IInputDevice.h b/source/gameengine/GameLogic/SCA_IInputDevice.h
new file mode 100644
index 00000000000..861b4bffb5e
--- /dev/null
+++ b/source/gameengine/GameLogic/SCA_IInputDevice.h
@@ -0,0 +1,307 @@
+/**
+ * Interface for input devices. The defines for keyboard/system/mouse events
+ * here are for internal use in the KX module.
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 KX_INPUTDEVICE_H
+#define KX_INPUTDEVICE_H
+
+
+class SCA_InputEvent
+{
+
+public:
+ enum SCA_EnumInputs {
+
+ KX_NO_INPUTSTATUS = 0,
+ KX_JUSTACTIVATED,
+ KX_ACTIVE,
+ KX_JUSTRELEASED,
+ KX_MAX_INPUTSTATUS
+ };
+
+ SCA_InputEvent(SCA_EnumInputs status=KX_NO_INPUTSTATUS,int eventval=0)
+ : m_status(status),
+ m_eventval(eventval)
+ {
+
+ }
+
+ SCA_EnumInputs m_status;
+ int m_eventval;
+};
+
+class SCA_IInputDevice
+{
+
+
+public:
+
+ SCA_IInputDevice();
+ virtual ~SCA_IInputDevice();
+
+ enum KX_EnumInputs {
+
+ KX_NOKEY = 0,
+
+ // TIMERS
+
+ KX_TIMER0,
+ KX_TIMER1,
+ KX_TIMER2,
+ KX_TIMER3,
+
+ // SYSTEM
+
+ /* Moved to avoid clashes with KX_RETKEY */
+ KX_KEYBD,
+ KX_RAWKEYBD,
+ KX_REDRAW,
+ KX_INPUTCHANGE,
+ KX_QFULL,
+ KX_WINFREEZE,
+ KX_WINTHAW,
+ /* thaw is 11 */
+
+ /* move past retkey*/
+ KX_WINCLOSE = 14,
+ KX_WINQUIT,
+ KX_Q_FIRSTTIME,
+ /* sequence ends on 16 */
+
+ // standard keyboard
+
+ /* Because of the above preamble, KX_BEGINKEY is 15 ! This
+ * means that KX_RETKEY on 13d (0Dh)) will double up with
+ * KX_WINQUIT! Why is it 13? Because ascii 13d is Ctrl-M aka
+ * CR! Its little brother, LF has 10d (0Ah). This is
+ * dangerous, since the keyboards start scanning at
+ * KX_BEGINKEY. I think the keyboard system should push its
+ * key events instead of demanding the user to poll the
+ * table... But that's for another time... The fix for now is
+ * to move the above system events into a 'safe' (ie. unused)
+ * range. I am loathe to move it away from this 'magical'
+ * coincidence.. it's probably exploited somewhere. I hope the
+ * close and quit events don't mess up 'normal' kb code
+ * scanning.
+ * */
+ KX_BEGINKEY = 12,
+
+ KX_RETKEY = 13,
+ KX_SPACEKEY = 32,
+ KX_PADASTERKEY = 42,
+ KX_COMMAKEY = 44,
+ KX_MINUSKEY = 45,
+ KX_PERIODKEY = 46,
+ KX_ZEROKEY = 48,
+
+ KX_ONEKEY, // =49
+ KX_TWOKEY,
+ KX_THREEKEY,
+ KX_FOURKEY,
+ KX_FIVEKEY,
+ KX_SIXKEY,
+ KX_SEVENKEY,
+ KX_EIGHTKEY,
+ KX_NINEKEY, // = 57
+
+ KX_AKEY = 97,
+ KX_BKEY,
+ KX_CKEY,
+ KX_DKEY,
+ KX_EKEY,
+ KX_FKEY,
+ KX_GKEY,
+ KX_HKEY,
+ KX_IKEY,
+ KX_JKEY,
+ KX_KKEY,
+ KX_LKEY,
+ KX_MKEY,
+ KX_NKEY, // =110
+ KX_OKEY,
+ KX_PKEY,
+ KX_QKEY,
+ KX_RKEY,
+ KX_SKEY,
+ KX_TKEY,
+ KX_UKEY,
+ KX_VKEY,
+ KX_WKEY,
+ KX_XKEY, // =120
+ KX_YKEY,
+ KX_ZKEY, // =122
+
+
+
+ KX_CAPSLOCKKEY, // 123
+
+ KX_LEFTCTRLKEY, // 124
+ KX_LEFTALTKEY,
+ KX_RIGHTALTKEY,
+ KX_RIGHTCTRLKEY,
+ KX_RIGHTSHIFTKEY,
+ KX_LEFTSHIFTKEY,// 129
+
+ KX_ESCKEY, // 130
+ KX_TABKEY, //131
+
+
+ KX_LINEFEEDKEY, // 132
+ KX_BACKSPACEKEY,
+ KX_DELKEY,
+ KX_SEMICOLONKEY, // 135
+
+
+ KX_QUOTEKEY, //136
+ KX_ACCENTGRAVEKEY, //137
+
+ KX_SLASHKEY, //138
+ KX_BACKSLASHKEY,
+ KX_EQUALKEY,
+ KX_LEFTBRACKETKEY,
+ KX_RIGHTBRACKETKEY, // 142
+
+ KX_LEFTARROWKEY, // 145
+ KX_DOWNARROWKEY,
+ KX_RIGHTARROWKEY,
+ KX_UPARROWKEY, // 148
+
+ KX_PAD2 ,
+ KX_PAD4 ,
+ KX_PAD6 ,
+ KX_PAD8 ,
+
+ KX_PAD1 ,
+ KX_PAD3 ,
+ KX_PAD5 ,
+ KX_PAD7 ,
+ KX_PAD9 ,
+
+ KX_PADPERIOD,
+ KX_PADSLASHKEY,
+
+
+
+ KX_PAD0 ,
+ KX_PADMINUS,
+ KX_PADENTER,
+ KX_PADPLUSKEY,
+
+
+ KX_F1KEY ,
+ KX_F2KEY ,
+ KX_F3KEY ,
+ KX_F4KEY ,
+ KX_F5KEY ,
+ KX_F6KEY ,
+ KX_F7KEY ,
+ KX_F8KEY ,
+ KX_F9KEY ,
+ KX_F10KEY,
+ KX_F11KEY,
+ KX_F12KEY,
+
+ KX_PAUSEKEY,
+ KX_INSERTKEY,
+ KX_HOMEKEY ,
+ KX_PAGEUPKEY,
+ KX_PAGEDOWNKEY,
+ KX_ENDKEY,
+
+ // MOUSE
+ KX_BEGINMOUSE,
+
+ KX_BEGINMOUSEBUTTONS,
+
+ KX_LEFTMOUSE,
+ KX_MIDDLEMOUSE,
+ KX_RIGHTMOUSE,
+
+ KX_ENDMOUSEBUTTONS,
+
+ KX_MOUSEX,
+ KX_MOUSEY,
+
+ KX_ENDMOUSE,
+
+
+
+ KX_MAX_KEYS
+
+ } ; // enum
+
+
+protected:
+ /**
+ m_eventStatusTables are two tables that contain current and previous
+ status of all events
+ */
+
+ SCA_InputEvent m_eventStatusTables[2][SCA_IInputDevice::KX_MAX_KEYS];
+ /**
+ m_currentTable is index for m_keyStatusTable that toggle between 0 or 1
+ */
+ int m_currentTable;
+ void ClearStatusTable(int tableid);
+
+public:
+ virtual bool IsPressed(SCA_IInputDevice::KX_EnumInputs inputcode)=0;
+ virtual const SCA_InputEvent& GetEventValue(SCA_IInputDevice::KX_EnumInputs inputcode);
+
+ /**
+ * Count active events(active and just_activated)
+ */
+ virtual int GetNumActiveEvents();
+
+ /**
+ * Get the number of ramping events (just_activated, just_released)
+ */
+ virtual int GetNumJustEvents();
+
+ /* Next frame: we calculate the new key states. This goes as follows:
+ *
+ * KX_NO_INPUTSTATUS -> KX_NO_INPUTSTATUS
+ * KX_JUSTACTIVATED -> KX_ACTIVE
+ * KX_ACTIVE -> KX_ACTIVE
+ * KX_JUSTRELEASED -> KX_NO_INPUTSTATUS
+ *
+ * Getting new events provides the
+ * KX_NO_INPUTSTATUS->KX_JUSTACTIVATED and
+ * KX_ACTIVE->KX_JUSTRELEASED transitions.
+ */
+ virtual void NextFrame();
+
+};
+
+#endif //KX_INPUTDEVICE_H
diff --git a/source/gameengine/GameLogic/SCA_ILogicBrick.cpp b/source/gameengine/GameLogic/SCA_ILogicBrick.cpp
new file mode 100644
index 00000000000..ce90a17fe0d
--- /dev/null
+++ b/source/gameengine/GameLogic/SCA_ILogicBrick.cpp
@@ -0,0 +1,325 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "SCA_ILogicBrick.h"
+
+
+
+SCA_LogicManager* SCA_ILogicBrick::m_sCurrentLogicManager = NULL;
+
+SCA_ILogicBrick::SCA_ILogicBrick(SCA_IObject* gameobj,
+ PyTypeObject* T)
+ :
+ CValue(T),
+ m_gameobj(gameobj),
+ m_Execute_Priority(0),
+ m_Execute_Ueber_Priority(0),
+ m_bActive(false),
+ m_eventval(0)
+{
+ m_text = "KX_LogicBrick";
+}
+
+
+
+SCA_ILogicBrick::~SCA_ILogicBrick()
+{
+ RemoveEvent();
+}
+
+
+
+void SCA_ILogicBrick::SetExecutePriority(int execute_Priority)
+{
+ m_Execute_Priority = execute_Priority;
+}
+
+
+
+void SCA_ILogicBrick::SetUeberExecutePriority(int execute_Priority)
+{
+ m_Execute_Ueber_Priority = execute_Priority;
+}
+
+
+
+SCA_IObject* SCA_ILogicBrick::GetParent()
+{
+ return m_gameobj;
+}
+
+
+
+void SCA_ILogicBrick::ReParent(SCA_IObject* parent)
+{
+ m_gameobj = parent;
+}
+
+
+
+CValue* SCA_ILogicBrick::Calc(VALUE_OPERATOR op, CValue *val)
+{
+ CValue* temp = new CBoolValue(false,"");
+ CValue* result = temp->Calc(op,val);
+ temp->Release();
+
+ return result;
+}
+
+
+
+CValue* SCA_ILogicBrick::CalcFinal(VALUE_DATA_TYPE dtype,
+ VALUE_OPERATOR op,
+ CValue *val)
+{
+ // same as bool implementation, so...
+ CValue* temp = new CBoolValue(false,"");
+ CValue* result = temp->CalcFinal(dtype,op,val);
+ temp->Release();
+
+ return result;
+}
+
+
+
+const STR_String& SCA_ILogicBrick::GetText()
+{
+ if (m_name.Length())
+ return m_name;
+
+ return m_text;
+}
+
+
+
+float SCA_ILogicBrick::GetNumber()
+{
+ return -1;
+}
+
+
+
+STR_String SCA_ILogicBrick::GetName()
+{
+ return m_name;
+}
+
+
+
+void SCA_ILogicBrick::SetName(STR_String name)
+{
+ m_name = name;
+}
+
+
+
+void SCA_ILogicBrick::ReplicaSetName(STR_String name)
+{
+ m_name = name;
+}
+
+
+
+bool SCA_ILogicBrick::IsActive()
+{
+ return m_bActive;
+}
+
+
+
+bool SCA_ILogicBrick::LessComparedTo(SCA_ILogicBrick* other)
+{
+ return (this->m_Execute_Ueber_Priority < other->m_Execute_Ueber_Priority)
+ || ((this->m_Execute_Ueber_Priority == other->m_Execute_Ueber_Priority) &&
+ (this->m_Execute_Priority < other->m_Execute_Priority));
+}
+
+
+
+void SCA_ILogicBrick::SetActive(bool active)
+{
+ m_bActive=active;
+ if (active)
+ {
+ //m_gameobj->SetDebugColor(GetDrawColor());
+ } else
+ {
+ //m_gameobj->ResetDebugColor();
+ }
+}
+
+
+
+void SCA_ILogicBrick::RegisterEvent(CValue* eventval)
+{
+ if (m_eventval)
+ m_eventval->Release();
+
+ m_eventval = eventval->AddRef();
+}
+
+
+void SCA_ILogicBrick::RemoveEvent()
+{
+ if (m_eventval)
+ {
+ m_eventval->Release();
+ m_eventval = NULL;
+ }
+}
+
+
+
+CValue* SCA_ILogicBrick::GetEvent()
+{
+ if (m_eventval)
+ {
+ return m_eventval->AddRef();
+ }
+
+ return NULL;
+}
+
+
+
+
+/* python stuff */
+
+PyTypeObject SCA_ILogicBrick::Type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0,
+ "SCA_ILogicBrick",
+ sizeof(SCA_ILogicBrick),
+ 0,
+ PyDestructor,
+ 0,
+ __getattr,
+ __setattr,
+ 0, //&MyPyCompare,
+ __repr,
+ 0, //&cvalue_as_number,
+ 0,
+ 0,
+ 0,
+ 0
+};
+
+
+
+PyParentObject SCA_ILogicBrick::Parents[] = {
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
+};
+
+
+
+PyMethodDef SCA_ILogicBrick::Methods[] = {
+ {"getOwner", (PyCFunction) SCA_ILogicBrick::sPyGetOwner, METH_VARARGS},
+ {"getExecutePriority", (PyCFunction) SCA_ILogicBrick::sPySetExecutePriority, METH_VARARGS},
+ {"setExecutePriority", (PyCFunction) SCA_ILogicBrick::sPySetExecutePriority, METH_VARARGS},
+ {NULL,NULL} //Sentinel
+};
+
+
+
+PyObject*
+SCA_ILogicBrick::_getattr(char* attr)
+{
+ _getattr_up(CValue);
+}
+
+
+
+PyObject* SCA_ILogicBrick::PyGetOwner(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ CValue* parent = GetParent();
+ if (parent)
+ {
+ parent->AddRef();
+ return parent;
+ }
+
+ printf("ERROR: Python scriptblock without owner\n");
+ Py_INCREF(Py_None);
+ return Py_None;//Int_FromLong(IsPositiveTrigger());
+}
+
+
+
+PyObject* SCA_ILogicBrick::PySetExecutePriority(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+
+ int priority=0;
+
+ if (!PyArg_ParseTuple(args, "i", &priority)) {
+ return NULL;
+ }
+
+ m_Execute_Ueber_Priority = priority;
+
+ Py_Return;
+}
+
+
+
+PyObject* SCA_ILogicBrick::PyGetExecutePriority(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ return PyInt_FromLong(m_Execute_Ueber_Priority);
+}
+
+
+
+/* Conversions for making life better. */
+bool SCA_ILogicBrick::PyArgToBool(int boolArg)
+{
+ if (boolArg == KX_TRUE) {
+ return true;
+ } else if (boolArg == KX_FALSE){
+ return false;
+ } else {
+ ; /* error: bad conversion: how to catch this? */
+ return false;
+ }
+}
+
+
+
+PyObject* SCA_ILogicBrick::BoolToPyArg(bool boolarg)
+{
+ return PyInt_FromLong(boolarg? KX_TRUE: KX_FALSE);
+}
diff --git a/source/gameengine/GameLogic/SCA_ILogicBrick.h b/source/gameengine/GameLogic/SCA_ILogicBrick.h
new file mode 100644
index 00000000000..9e293136e21
--- /dev/null
+++ b/source/gameengine/GameLogic/SCA_ILogicBrick.h
@@ -0,0 +1,111 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 __KX_ILOGICBRICK
+#define __KX_ILOGICBRICK
+
+#include "Value.h"
+#include "SCA_IObject.h"
+#include "BoolValue.h"
+class SCA_ILogicBrick : public CValue
+{
+ Py_Header;
+ SCA_IObject* m_gameobj;
+ int m_Execute_Priority;
+ int m_Execute_Ueber_Priority;
+
+ bool m_bActive;
+ CValue* m_eventval;
+ STR_String m_text;
+ STR_String m_name;
+ //unsigned long m_drawcolor;
+protected:
+ void RegisterEvent(CValue* eventval);
+ void RemoveEvent();
+ CValue* GetEvent();
+
+public:
+ SCA_ILogicBrick(SCA_IObject* gameobj,PyTypeObject* T );
+ virtual ~SCA_ILogicBrick();
+
+ void SetExecutePriority(int execute_Priority);
+ void SetUeberExecutePriority(int execute_Priority);
+
+ SCA_IObject* GetParent();
+ virtual void ReParent(SCA_IObject* parent);
+
+ // act as a BoolValue (with value IsPositiveTrigger)
+ virtual CValue* Calc(VALUE_OPERATOR op, CValue *val);
+ virtual CValue* CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val);
+
+ virtual const STR_String & GetText();
+ virtual float GetNumber();
+ virtual STR_String GetName();
+ virtual void SetName(STR_String name);
+ virtual void ReplicaSetName(STR_String name);
+
+ bool IsActive();
+ void SetActive(bool active) ;
+
+ virtual bool LessComparedTo(SCA_ILogicBrick* other);
+
+ virtual PyObject* _getattr(char *attr);
+
+ static class SCA_LogicManager* m_sCurrentLogicManager;
+
+
+ // python methods
+
+ KX_PYMETHOD(SCA_ILogicBrick,GetOwner);
+ KX_PYMETHOD(SCA_ILogicBrick,SetExecutePriority);
+ KX_PYMETHOD(SCA_ILogicBrick,GetExecutePriority);
+
+ enum KX_BOOL_TYPE {
+ KX_BOOL_NODEF = 0,
+ KX_TRUE,
+ KX_FALSE,
+ KX_BOOL_MAX
+ };
+
+
+protected:
+ /* Some conversions to go with the bool type. */
+ /** Convert a KX_TRUE, KX_FALSE in Python to a c++ value. */
+ bool PyArgToBool(int boolArg);
+
+ /** Convert a a c++ value to KX_TRUE, KX_FALSE in Python. */
+ PyObject* BoolToPyArg(bool);
+
+
+};
+
+
+#endif
diff --git a/source/gameengine/GameLogic/SCA_IObject.cpp b/source/gameengine/GameLogic/SCA_IObject.cpp
new file mode 100644
index 00000000000..012479ba2d3
--- /dev/null
+++ b/source/gameengine/GameLogic/SCA_IObject.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 *****
+ */
+
+
+#include "SCA_IObject.h"
+#include "SCA_ISensor.h"
+#include "SCA_IController.h"
+#include "SCA_IActuator.h"
+#include "MT_Point3.h"
+
+#include "ListValue.h"
+
+MT_Point3 SCA_IObject::m_sDummy=MT_Point3(0,0,0);
+
+SCA_IObject::SCA_IObject(PyTypeObject* T): CValue(T)
+{
+ m_suspended = false;
+}
+
+
+
+SCA_IObject::~SCA_IObject()
+{
+ SCA_SensorList::iterator its;
+ for (its = m_sensors.begin(); !(its == m_sensors.end()); ++its)
+ {
+ ((CValue*)(*its))->Release();
+ }
+ SCA_ControllerList::iterator itc;
+ for (itc = m_controllers.begin(); !(itc == m_controllers.end()); ++itc)
+ {
+ ((CValue*)(*itc))->Release();
+ }
+ SCA_ActuatorList::iterator ita;
+ for (ita = m_actuators.begin(); !(ita==m_actuators.end()); ++ita)
+ {
+ ((CValue*)(*ita))->Release();
+ }
+
+ //T_InterpolatorList::iterator i;
+ //for (i = m_interpolators.begin(); !(i == m_interpolators.end()); ++i) {
+ // delete *i;
+ //}
+}
+
+
+
+SCA_ControllerList& SCA_IObject::GetControllers()
+{
+ return m_controllers;
+}
+
+
+
+SCA_SensorList& SCA_IObject::GetSensors()
+{
+ return m_sensors;
+}
+
+
+
+SCA_ActuatorList& SCA_IObject::GetActuators()
+{
+ return m_actuators;
+}
+
+
+
+void SCA_IObject::AddSensor(SCA_ISensor* act)
+{
+ m_sensors.push_back(act);
+}
+
+
+
+void SCA_IObject::AddController(SCA_IController* act)
+{
+ m_controllers.push_back(act);
+}
+
+
+
+void SCA_IObject::AddActuator(SCA_IActuator* act)
+{
+ m_actuators.push_back(act);
+}
+
+
+
+void SCA_IObject::SetIgnoreActivityCulling(bool b)
+{
+ m_ignore_activity_culling = b;
+}
+
+
+
+bool SCA_IObject::GetIgnoreActivityCulling()
+{
+ return m_ignore_activity_culling;
+}
+
+
+
+void SCA_IObject::ReParentLogic()
+{
+ SCA_SensorList& oldsensors = GetSensors();
+
+ int sen = 0;
+ SCA_SensorList::iterator its;
+ for (its = oldsensors.begin(); !(its==oldsensors.end()); ++its)
+ {
+ SCA_ISensor* newsensor = (SCA_ISensor*)(*its)->GetReplica();
+ newsensor->ReParent(this);
+ oldsensors[sen++] = newsensor;
+ }
+
+ SCA_ControllerList& oldcontrollers = GetControllers();
+ int con = 0;
+ SCA_ControllerList::iterator itc;
+ for (itc = oldcontrollers.begin(); !(itc==oldcontrollers.end()); ++itc)
+ {
+ SCA_IController* newcontroller = (SCA_IController*)(*itc)->GetReplica();
+ newcontroller->ReParent(this);
+ oldcontrollers[con++]=newcontroller;
+
+ }
+ SCA_ActuatorList& oldactuators = GetActuators();
+
+ int act = 0;
+ SCA_ActuatorList::iterator ita;
+ for (ita = oldactuators.begin(); !(ita==oldactuators.end()); ++ita)
+ {
+ SCA_IActuator* newactuator = (SCA_IActuator*) (*ita)->GetReplica();
+ newactuator->ReParent(this);
+ newactuator->SetActive(false);
+ oldactuators[act++] = newactuator;
+ }
+
+}
+
+
+
+SCA_ISensor* SCA_IObject::FindSensor(const STR_String& sensorname)
+{
+ SCA_ISensor* foundsensor = NULL;
+
+ for (SCA_SensorList::iterator its = m_sensors.begin();!(its==m_sensors.end());its++)
+ {
+ if ((*its)->GetName() == sensorname)
+ {
+ foundsensor = (*its);
+ break;
+ }
+ }
+ return foundsensor;
+}
+
+
+
+SCA_IController* SCA_IObject::FindController(const STR_String& controllername)
+{
+ SCA_IController* foundcontroller = NULL;
+
+ for (SCA_ControllerList::iterator itc = m_controllers.begin();!(itc==m_controllers.end());itc++)
+ {
+ if ((*itc)->GetName() == controllername)
+ {
+ foundcontroller = (*itc);
+ break;
+ }
+ }
+ return foundcontroller;
+}
+
+
+
+SCA_IActuator* SCA_IObject::FindActuator(const STR_String& actuatorname)
+{
+ SCA_IActuator* foundactuator = NULL;
+
+ for (SCA_ActuatorList::iterator ita = m_actuators.begin();!(ita==m_actuators.end());ita++)
+ {
+ if ((*ita)->GetName() == actuatorname)
+ {
+ foundactuator = (*ita);
+ break;
+ }
+ }
+
+ return foundactuator;
+}
+
+
+
+void SCA_IObject::SetCurrentTime(float currentTime) {
+ //T_InterpolatorList::iterator i;
+ //for (i = m_interpolators.begin(); !(i == m_interpolators.end()); ++i) {
+ // (*i)->Execute(currentTime);
+ //}
+}
+
+
+
+const MT_Point3& SCA_IObject::ConvertPythonPylist(PyObject* pylist)
+{
+ bool error = false;
+ m_sDummy = MT_Vector3(0,0,0);
+ if (pylist->ob_type == &CListValue::Type)
+ {
+ CListValue* listval = (CListValue*) pylist;
+ int numelem = listval->GetCount();
+ if ( numelem <= 3)
+ {
+ int index;
+ for (index = 0;index<numelem;index++)
+ {
+ m_sDummy[index] = listval->GetValue(index)->GetNumber();
+ }
+ } else
+ {
+ error = true;
+ }
+
+ } else
+ {
+
+ // assert the list is long enough...
+ int numitems = PyList_Size(pylist);
+ if (numitems <= 3)
+ {
+ int index;
+ for (index=0;index<numitems;index++)
+ {
+ m_sDummy[index] = PyFloat_AsDouble(PyList_GetItem(pylist,index));
+ }
+ }
+ else
+ {
+ error = true;
+ }
+
+ }
+ return m_sDummy;
+}
+
+
+
+const MT_Point3& SCA_IObject::ConvertPythonVectorArg(PyObject* args)
+{
+
+ PyObject* pylist;
+ PyArg_ParseTuple(args,"O",&pylist);
+ m_sDummy = ConvertPythonPylist(pylist);
+ return m_sDummy;
+}
+
+
+
+void SCA_IObject::Suspend(void)
+{
+ if ((!m_ignore_activity_culling)
+ && (!m_suspended)) {
+ m_suspended = true;
+ /* flag suspend for all sensors */
+ SCA_SensorList::iterator i = m_sensors.begin();
+ while (i != m_sensors.end()) {
+ (*i)->Suspend();
+ i++;
+ }
+ }
+}
+
+
+
+void SCA_IObject::Resume(void)
+{
+ if (m_suspended) {
+ m_suspended = false;
+ /* unflag suspend for all sensors */
+ SCA_SensorList::iterator i = m_sensors.begin();
+ while (i != m_sensors.end()) {
+ (*i)->Resume();
+ i++;
+ }
+ }
+}
+
+
+
+/* ------------------------------------------------------------------------- */
+/* Python functions */
+/* ------------------------------------------------------------------------- */
+
+/* Integration hooks ------------------------------------------------------- */
+PyTypeObject SCA_IObject::Type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0,
+ "SCA_IObject",
+ sizeof(SCA_IObject),
+ 0,
+ PyDestructor,
+ 0,
+ __getattr,
+ __setattr,
+ 0, //&MyPyCompare,
+ __repr,
+ 0, //&cvalue_as_number,
+ 0,
+ 0,
+ 0,
+ 0
+};
+
+
+
+PyParentObject SCA_IObject::Parents[] = {
+ &SCA_IObject::Type,
+ &CValue::Type,
+ NULL
+};
+
+
+
+PyMethodDef SCA_IObject::Methods[] = {
+ //{"setOrientation", (PyCFunction) SCA_IObject::sPySetOrientation, METH_VARARGS},
+ //{"getOrientation", (PyCFunction) SCA_IObject::sPyGetOrientation, METH_VARARGS},
+ {NULL,NULL} //Sentinel
+};
+
+
+
+PyObject* SCA_IObject::_getattr(char* attr) {
+ _getattr_up(CValue);
+}
+
diff --git a/source/gameengine/GameLogic/SCA_IObject.h b/source/gameengine/GameLogic/SCA_IObject.h
new file mode 100644
index 00000000000..e3c06a92b9f
--- /dev/null
+++ b/source/gameengine/GameLogic/SCA_IObject.h
@@ -0,0 +1,126 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * An abstract object that has some logic, python scripting and
+ * reference counting Note: transformation stuff has been moved to
+ * SceneGraph
+ */
+
+#ifndef SCA_IOBJECT_H
+#define SCA_IOBJECT_H
+
+#include "Value.h"
+#include <vector>
+
+class SCA_ISensor;
+class SCA_IController;
+class SCA_IActuator;
+
+
+typedef std::vector<SCA_ISensor *> SCA_SensorList;
+typedef std::vector<SCA_IController *> SCA_ControllerList;
+typedef std::vector<SCA_IActuator *> SCA_ActuatorList;
+
+
+class SCA_IObject : public CValue
+{
+
+ Py_Header;
+
+protected:
+ SCA_SensorList m_sensors;
+ SCA_ControllerList m_controllers;
+ SCA_ActuatorList m_actuators;
+ static class MT_Point3 m_sDummy;
+
+ /**
+ * Ignore activity culling requests?
+ */
+ bool m_ignore_activity_culling;
+
+ /**
+ * Ignore updates?
+ */
+ bool m_suspended;
+
+public:
+
+ SCA_IObject(PyTypeObject* T=&Type);
+ virtual ~SCA_IObject();
+
+ SCA_ControllerList& GetControllers();
+ SCA_SensorList& GetSensors();
+ SCA_ActuatorList& GetActuators();
+
+ void AddSensor(SCA_ISensor* act);
+ void AddController(SCA_IController* act);
+ void AddActuator(SCA_IActuator* act);
+
+ SCA_ISensor* FindSensor(const STR_String& sensorname);
+ SCA_IActuator* FindActuator(const STR_String& actuatorname);
+ SCA_IController* FindController(const STR_String& controllername);
+
+ void SetCurrentTime(float currentTime);
+
+ void ReParentLogic();
+
+ /**
+ * Set whether or not to ignore activity culling requests
+ */
+ void SetIgnoreActivityCulling(bool b);
+
+ /**
+ * Set whether or not this object wants to ignore activity culling
+ * requests
+ */
+ bool GetIgnoreActivityCulling();
+
+ /**
+ * Suspend all progress.
+ */
+ void Suspend(void);
+
+ /**
+ * Resume progress
+ */
+ void Resume(void);
+
+ const class MT_Point3& ConvertPythonPylist(PyObject* pylist);
+ const class MT_Point3& ConvertPythonVectorArg(PyObject* args);
+
+ // here come the python forwarded methods
+ PyObject* _getattr(char* attr);
+
+};
+#endif //SCA_IOBJECT_H
+
+
+
+
diff --git a/source/gameengine/GameLogic/SCA_IScene.cpp b/source/gameengine/GameLogic/SCA_IScene.cpp
new file mode 100644
index 00000000000..e9ed8232824
--- /dev/null
+++ b/source/gameengine/GameLogic/SCA_IScene.cpp
@@ -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 *****
+ */
+
+#include "SCA_IScene.h"
+
+
+
+SCA_IScene::SCA_IScene()
+{
+}
+
+
+
+SCA_IScene::~SCA_IScene()
+{
+ // release debugprop list
+ for (std::vector<SCA_DebugProp*>::iterator it = m_debugList.begin();
+ !(it==m_debugList.end());it++)
+ {
+ delete (*it);
+ }
+}
+
+
+std::vector<SCA_DebugProp*>& SCA_IScene::GetDebugProperties()
+{
+ return m_debugList;
+}
+
+
+
+void SCA_IScene::AddDebugProperty(class CValue* debugprop,
+ const STR_String &name)
+{
+ SCA_DebugProp* dprop = new SCA_DebugProp();
+ dprop->m_obj = debugprop;
+ dprop->m_name = name;
+ m_debugList.push_back(dprop);
+}
diff --git a/source/gameengine/GameLogic/SCA_IScene.h b/source/gameengine/GameLogic/SCA_IScene.h
new file mode 100644
index 00000000000..a8893fe9c59
--- /dev/null
+++ b/source/gameengine/GameLogic/SCA_IScene.h
@@ -0,0 +1,62 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 __KX_ISCENE_H
+#define __KX_ISCENE_H
+
+#include <vector>
+
+#include "STR_String.h"
+
+struct SCA_DebugProp
+{
+ class CValue* m_obj;
+ STR_String m_name;
+};
+
+class SCA_IScene
+{
+ std::vector<SCA_DebugProp*> m_debugList;
+public:
+ SCA_IScene();
+ virtual ~SCA_IScene();
+ virtual class SCA_IObject* AddReplicaObject(class CValue* gameobj,
+ class CValue* locationobj,
+ int lifespan=0)=0;
+ virtual void RemoveObject(class CValue* gameobj)=0;
+ virtual void DelayedRemoveObject(class CValue* gameobj)=0;
+ virtual void ReplaceMesh(class CValue* gameobj,
+ void* meshobj)=0;
+ std::vector<SCA_DebugProp*>& GetDebugProperties();
+ void AddDebugProperty(class CValue* debugprop,
+ const STR_String &name);
+};
+#endif //__KX_ISCENE_H
diff --git a/source/gameengine/GameLogic/SCA_ISensor.cpp b/source/gameengine/GameLogic/SCA_ISensor.cpp
new file mode 100644
index 00000000000..be26f1d503e
--- /dev/null
+++ b/source/gameengine/GameLogic/SCA_ISensor.cpp
@@ -0,0 +1,328 @@
+/**
+ * Abstract class for sensor logic bricks
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "SCA_ISensor.h"
+#include "SCA_EventManager.h"
+#include "SCA_LogicManager.h"
+
+/* Native functions */
+
+
+void SCA_ISensor::ReParent(SCA_IObject* parent)
+{
+ SCA_ILogicBrick::ReParent(parent);
+ m_eventmgr->RegisterSensor(this);
+ this->SetActive(false);
+}
+
+
+SCA_ISensor::SCA_ISensor(SCA_IObject* gameobj,
+ class SCA_EventManager* eventmgr,
+ PyTypeObject* T ) :
+ SCA_ILogicBrick(gameobj,T),
+ m_triggered(false)
+{
+ m_suspended = false;
+ m_invert = false;
+ m_pos_ticks = 0;
+ m_neg_ticks = 0;
+ m_pos_pulsemode = false;
+ m_neg_pulsemode = false;
+ m_pulse_frequency = 0;
+
+ m_eventmgr = eventmgr;
+}
+
+
+SCA_ISensor::~SCA_ISensor()
+{
+ // intentionally empty
+}
+
+bool SCA_ISensor::IsPositiveTrigger() {
+ bool result = false;
+
+ if (m_eventval) {
+ result = (m_eventval->GetNumber() != 0.0);
+ }
+ if (m_invert) {
+ result = !result;
+ }
+
+ return result;
+}
+
+void SCA_ISensor::SetPulseMode(bool posmode,
+ bool negmode,
+ int freq) {
+ m_pos_pulsemode = posmode;
+ m_neg_pulsemode = negmode;
+ m_pulse_frequency = freq;
+}
+
+void SCA_ISensor::SetInvert(bool inv) {
+ m_invert = inv;
+}
+
+
+float SCA_ISensor::GetNumber() {
+ return IsPositiveTrigger();
+}
+
+void SCA_ISensor::Suspend() {
+ m_suspended = true;
+}
+
+bool SCA_ISensor::IsSuspended() {
+ return m_suspended;
+}
+
+void SCA_ISensor::Resume() {
+ m_suspended = false;
+}
+
+/* python integration */
+
+PyTypeObject SCA_ISensor::Type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0,
+ "SCA_ISensor",
+ sizeof(SCA_ISensor),
+ 0,
+ PyDestructor,
+ 0,
+ __getattr,
+ __setattr,
+ 0, //&MyPyCompare,
+ __repr,
+ 0, //&cvalue_as_number,
+ 0,
+ 0,
+ 0,
+ 0
+};
+
+PyParentObject SCA_ISensor::Parents[] = {
+ &SCA_ISensor::Type,
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
+};
+PyMethodDef SCA_ISensor::Methods[] = {
+ {"isPositive", (PyCFunction) SCA_ISensor::sPyIsPositive,
+ METH_VARARGS, IsPositive_doc},
+ {"getUsePosPulseMode", (PyCFunction) SCA_ISensor::sPyGetUsePosPulseMode,
+ METH_VARARGS, GetUsePosPulseMode_doc},
+ {"setUsePosPulseMode", (PyCFunction) SCA_ISensor::sPySetUsePosPulseMode,
+ METH_VARARGS, SetUsePosPulseMode_doc},
+ {"getFrequency", (PyCFunction) SCA_ISensor::sPyGetFrequency,
+ METH_VARARGS, GetFrequency_doc},
+ {"setFrequency", (PyCFunction) SCA_ISensor::sPySetFrequency,
+ METH_VARARGS, SetFrequency_doc},
+ {"getUseNegPulseMode", (PyCFunction) SCA_ISensor::sPyGetUseNegPulseMode,
+ METH_VARARGS, GetUseNegPulseMode_doc},
+ {"setUseNegPulseMode", (PyCFunction) SCA_ISensor::sPySetUseNegPulseMode,
+ METH_VARARGS, SetUseNegPulseMode_doc},
+ {NULL,NULL} //Sentinel
+};
+
+
+PyObject*
+SCA_ISensor::_getattr(char* attr)
+{
+ _getattr_up(SCA_ILogicBrick);
+}
+
+
+void SCA_ISensor::RegisterToManager()
+{
+ m_eventmgr->RegisterSensor(this);
+}
+
+void SCA_ISensor::Activate(class SCA_LogicManager* logicmgr, CValue* event)
+{
+
+ // calculate if a __triggering__ is wanted
+ if (!m_suspended) {
+ bool result = this->Evaluate(event);
+ if (result) {
+ logicmgr->AddActivatedSensor(this);
+ } else
+ {
+ /* First, the pulsing behaviour, if pulse mode is
+ * active. It seems something goes wrong if pulse mode is
+ * not set :( */
+ if (m_pos_pulsemode) {
+ m_pos_ticks++;
+ if (m_pos_ticks > m_pulse_frequency) {
+ if ( this->IsPositiveTrigger() )
+ {
+ logicmgr->AddActivatedSensor(this);
+ }
+ m_pos_ticks = 0;
+ }
+ }
+
+ if (m_neg_pulsemode)
+ {
+ m_neg_ticks++;
+ if (m_neg_ticks > m_pulse_frequency) {
+ if (!this->IsPositiveTrigger() )
+ {
+ logicmgr->AddActivatedSensor(this);
+ }
+ m_neg_ticks = 0;
+ }
+ }
+ }
+ }
+}
+
+/* Python functions: */
+char SCA_ISensor::IsPositive_doc[] =
+"isPositive()\n"
+"\tReturns whether the sensor is registered a positive event.\n";
+PyObject* SCA_ISensor::PyIsPositive(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ int retval = IsPositiveTrigger();
+ return PyInt_FromLong(retval);
+}
+
+/**
+ * getUsePulseMode: getter for the pulse mode (KX_TRUE = on)
+ */
+char SCA_ISensor::GetUsePosPulseMode_doc[] =
+"getUsePosPulseMode()\n"
+"\tReturns whether positive pulse mode is active.\n";
+PyObject* SCA_ISensor::PyGetUsePosPulseMode(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ return BoolToPyArg(m_pos_pulsemode);
+}
+
+/**
+ * setUsePulseMode: setter for the pulse mode (KX_TRUE = on)
+ */
+char SCA_ISensor::SetUsePosPulseMode_doc[] =
+"setUsePosPulseMode(pulse?)\n"
+"\t - pulse? : Pulse when a positive event occurs?\n"
+"\t (KX_TRUE, KX_FALSE)\n"
+"\tSet whether to do pulsing when positive pulses occur.\n";
+PyObject* SCA_ISensor::PySetUsePosPulseMode(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ int pyarg = 0;
+ if(!PyArg_ParseTuple(args, "i", &pyarg)) { return NULL; }
+ m_pos_pulsemode = PyArgToBool(pyarg);
+ Py_Return;
+}
+
+/**
+ * getFrequency: getter for the pulse mode interval
+ */
+char SCA_ISensor::GetFrequency_doc[] =
+"getFrequency()\n"
+"\tReturns the frequency of the updates in pulse mode.\n" ;
+PyObject* SCA_ISensor::PyGetFrequency(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ return PyInt_FromLong(m_pulse_frequency);
+}
+
+/**
+ * setFrequency: setter for the pulse mode (KX_TRUE = on)
+ */
+char SCA_ISensor::SetFrequency_doc[] =
+"setFrequency(pulse_frequency)\n"
+"\t- pulse_frequency: The frequency of the updates in pulse mode (integer)"
+"\tSet the frequency of the updates in pulse mode.\n"
+"\tIf the frequency is negative, it is set to 0.\n" ;
+PyObject* SCA_ISensor::PySetFrequency(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ int pulse_frequencyArg = 0;
+
+ if(!PyArg_ParseTuple(args, "i", &pulse_frequencyArg)) {
+ return NULL;
+ }
+
+ /* We can do three things here: clip, ignore and raise an exception. */
+ /* Exceptions don't work yet, ignoring is not desirable now... */
+ if (pulse_frequencyArg < 0) {
+ pulse_frequencyArg = 0;
+ };
+ m_pulse_frequency = pulse_frequencyArg;
+
+ Py_Return;
+}
+
+
+char SCA_ISensor::GetInvert_doc[] =
+"getInvert()\n"
+"\tReturns whether or not pulses from this sensor are inverted.\n" ;
+PyObject* SCA_ISensor::PyGetInvert(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ return BoolToPyArg(m_invert);
+}
+
+char SCA_ISensor::SetInvert_doc[] =
+"setInvert(invert?)\n"
+"\t- invert?: Invert the event-values? (KX_TRUE, KX_FALSE)\n"
+"\tSet whether to invert pulses.\n";
+PyObject* SCA_ISensor::PySetInvert(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ int pyarg = 0;
+ if(!PyArg_ParseTuple(args, "i", &pyarg)) { return NULL; }
+ m_invert = PyArgToBool(pyarg);
+ Py_Return;
+}
+
+char SCA_ISensor::GetUseNegPulseMode_doc[] =
+"getUseNegPulseMode()\n"
+"\tReturns whether negative pulse mode is active.\n";
+PyObject* SCA_ISensor::PyGetUseNegPulseMode(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ return BoolToPyArg(m_neg_pulsemode);
+}
+
+char SCA_ISensor::SetUseNegPulseMode_doc[] =
+"setUseNegPulseMode(pulse?)\n"
+"\t - pulse? : Pulse when a negative event occurs?\n"
+"\t (KX_TRUE, KX_FALSE)\n"
+"\tSet whether to do pulsing when negative pulses occur.\n";
+PyObject* SCA_ISensor::PySetUseNegPulseMode(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ int pyarg = 0;
+ if(!PyArg_ParseTuple(args, "i", &pyarg)) { return NULL; }
+ m_neg_pulsemode = PyArgToBool(pyarg);
+ Py_Return;
+}
+
+/* eof */
diff --git a/source/gameengine/GameLogic/SCA_ISensor.h b/source/gameengine/GameLogic/SCA_ISensor.h
new file mode 100644
index 00000000000..ef3f037be96
--- /dev/null
+++ b/source/gameengine/GameLogic/SCA_ISensor.h
@@ -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 *****
+ * Interface Class for all logic Sensors. Implements
+ * pulsemode and pulsefrequency, and event suppression.
+ */
+
+#ifndef __SCA_ISENSOR
+#define __SCA_ISENSOR
+
+#include "SCA_ILogicBrick.h"
+
+
+
+/**
+ * Interface Class for all logic Sensors. Implements
+ * pulsemode,pulsefrequency */
+class SCA_ISensor : public SCA_ILogicBrick
+{
+ Py_Header;
+ class SCA_EventManager* m_eventmgr;
+ bool m_triggered;
+
+ /* Pulse positive pulses? */
+ bool m_pos_pulsemode;
+
+ /** Pulse negative pulses? */
+ bool m_neg_pulsemode;
+
+ /** Repeat frequency in pulse mode. */
+ int m_pulse_frequency;
+
+ /** Number of ticks since the last positive pulse. */
+ int m_pos_ticks;
+
+ /** Number of ticks since the last negative pulse. */
+ int m_neg_ticks;
+
+ /* invert the output signal*/
+ bool m_invert;
+
+ /** Sensor must ignore updates? */
+ bool m_suspended;
+
+ /** Pass the activation on to the logic manager.*/
+ void SignalActivation(class SCA_LogicManager* logicmgr);
+
+public:
+ SCA_ISensor(SCA_IObject* gameobj,
+ class SCA_EventManager* eventmgr,
+ PyTypeObject* T );;
+ ~SCA_ISensor();
+ virtual void ReParent(SCA_IObject* parent);
+
+ /* Because we want sensors to share some behaviour, the Activate has */
+ /* an implementation on this level. It requires an evaluate on the lower */
+ /* level of individual sensors. Mapping the old activate()s is easy. */
+ /* The IsPosTrig() also has to change, to keep things consistent. */
+ void Activate(class SCA_LogicManager* logicmgr,CValue* event);
+ virtual bool Evaluate(CValue* event) = 0;
+ virtual bool IsPositiveTrigger();
+
+ virtual PyObject* _getattr(char *attr);
+ virtual CValue* GetReplica()=0;
+
+ /** Set parameters for the pulsing behaviour.
+ * @param posmode Trigger positive pulses?
+ * @param negmode Trigger negative pulses?
+ * @param freq Frequency to use when doing pulsing.
+ */
+ void SetPulseMode(bool posmode,
+ bool negmode,
+ int freq);
+
+ /** Set inversion of pulses on or off. */
+ void SetInvert(bool inv);
+
+ void RegisterToManager();
+ virtual float GetNumber();
+
+ /** Stop sensing for a while. */
+ void Suspend();
+
+ /** Is this sensor switched off? */
+ bool IsSuspended();
+
+ /** Resume sensing. */
+ void Resume();
+
+ /* Python functions: */
+ KX_PYMETHOD_DOC(SCA_ISensor,IsPositive);
+ KX_PYMETHOD_DOC(SCA_ISensor,GetUsePosPulseMode);
+ KX_PYMETHOD_DOC(SCA_ISensor,SetUsePosPulseMode);
+ KX_PYMETHOD_DOC(SCA_ISensor,GetFrequency);
+ KX_PYMETHOD_DOC(SCA_ISensor,SetFrequency);
+ KX_PYMETHOD_DOC(SCA_ISensor,GetUseNegPulseMode);
+ KX_PYMETHOD_DOC(SCA_ISensor,SetUseNegPulseMode);
+ KX_PYMETHOD_DOC(SCA_ISensor,GetInvert);
+ KX_PYMETHOD_DOC(SCA_ISensor,SetInvert);
+
+};
+
+#endif //__SCA_ISENSOR
diff --git a/source/gameengine/GameLogic/SCA_KeyboardManager.cpp b/source/gameengine/GameLogic/SCA_KeyboardManager.cpp
new file mode 100644
index 00000000000..46223aa11af
--- /dev/null
+++ b/source/gameengine/GameLogic/SCA_KeyboardManager.cpp
@@ -0,0 +1,91 @@
+/**
+ * Manager for keyboard events
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 <iostream.h>
+#include "BoolValue.h"
+#include "SCA_KeyboardManager.h"
+#include "SCA_KeyboardSensor.h"
+#include "IntValue.h"
+#include <vector>
+
+SCA_KeyboardManager::SCA_KeyboardManager(SCA_LogicManager* logicmgr,
+ SCA_IInputDevice* inputdev)
+ : SCA_EventManager(KEYBOARD_EVENTMGR),
+ m_logicmanager(logicmgr),
+ m_inputDevice(inputdev)
+{
+}
+
+
+
+SCA_KeyboardManager::~SCA_KeyboardManager()
+{
+}
+
+
+
+SCA_IInputDevice* SCA_KeyboardManager::GetInputDevice()
+{
+ return m_inputDevice;
+}
+
+
+
+void SCA_KeyboardManager::NextFrame(double curtime,double deltatime)
+{
+ //const SCA_InputEvent& event = GetEventValue(SCA_IInputDevice::KX_EnumInputs inputcode)=0;
+ // cerr << "SCA_KeyboardManager::NextFrame"<< endl;
+ for (int i=0;i<m_sensors.size();i++)
+ {
+ SCA_KeyboardSensor* keysensor = (SCA_KeyboardSensor*)m_sensors[i];
+ keysensor->Activate(m_logicmanager,NULL);
+ }
+
+}
+
+
+
+void SCA_KeyboardManager::RegisterSensor(SCA_ISensor* keysensor)
+{
+ m_sensors.push_back(keysensor);
+}
+
+
+
+bool SCA_KeyboardManager::IsPressed(SCA_IInputDevice::KX_EnumInputs inputcode)
+{
+ return false;
+ //return m_kxsystem->IsPressed(inputcode);
+}
+
diff --git a/source/gameengine/GameLogic/SCA_KeyboardManager.h b/source/gameengine/GameLogic/SCA_KeyboardManager.h
new file mode 100644
index 00000000000..1c665ef2b88
--- /dev/null
+++ b/source/gameengine/GameLogic/SCA_KeyboardManager.h
@@ -0,0 +1,66 @@
+/**
+ * Manager for keyboard events
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 __KX_KEYBOARDMANAGER
+#define __KX_KEYBOARDMANAGER
+
+
+#include "SCA_EventManager.h"
+
+#include <vector>
+
+using namespace std;
+
+#include "SCA_IInputDevice.h"
+
+
+class SCA_KeyboardManager : public SCA_EventManager
+{
+ class SCA_IInputDevice* m_inputDevice;
+ class SCA_LogicManager* m_logicmanager;
+
+
+public:
+ SCA_KeyboardManager(class SCA_LogicManager* logicmgr,class SCA_IInputDevice* inputdev);
+ virtual ~SCA_KeyboardManager();
+
+ bool IsPressed(SCA_IInputDevice::KX_EnumInputs inputcode);
+
+
+ virtual void NextFrame(double curtime,double deltatime);
+ virtual void RegisterSensor(class SCA_ISensor* sensor);
+ SCA_IInputDevice* GetInputDevice();
+};
+
+#endif //__KX_KEYBOARDMANAGER
diff --git a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp
new file mode 100644
index 00000000000..834c9254cc0
--- /dev/null
+++ b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp
@@ -0,0 +1,675 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * Sensor for keyboard input
+ */
+#include "SCA_KeyboardSensor.h"
+#include "SCA_KeyboardManager.h"
+#include "SCA_LogicManager.h"
+#include "StringValue.h"
+#include "SCA_IInputDevice.h"
+
+
+
+/* ------------------------------------------------------------------------- */
+/* Native functions */
+/* ------------------------------------------------------------------------- */
+
+SCA_KeyboardSensor::SCA_KeyboardSensor(SCA_KeyboardManager* keybdmgr,
+ short int hotkey,
+ short int qual,
+ short int qual2,
+ bool bAllKeys,
+ const STR_String& targetProp,
+ const STR_String& toggleProp,
+ SCA_IObject* gameobj,
+ PyTypeObject* T )
+ :SCA_ISensor(gameobj,keybdmgr,T),
+ m_pKeyboardMgr(keybdmgr),
+ m_hotkey(hotkey),
+ m_qual(qual),
+ m_qual2(qual2),
+ m_bAllKeys(bAllKeys),
+ m_targetprop(targetProp),
+ m_toggleprop(toggleProp)
+{
+
+// SetDrawColor(0xff0000ff);
+ m_val=0;
+}
+
+
+
+SCA_KeyboardSensor::~SCA_KeyboardSensor()
+{
+}
+
+
+
+CValue* SCA_KeyboardSensor::GetReplica()
+{
+ CValue* replica = new SCA_KeyboardSensor(*this);
+ // this will copy properties and so on...
+ CValue::AddDataToReplica(replica);
+
+ return replica;
+}
+
+
+
+short int SCA_KeyboardSensor::GetHotkey()
+{
+ return m_hotkey;
+}
+
+
+
+bool SCA_KeyboardSensor::IsPositiveTrigger()
+{
+ bool result = (m_val != 0);
+
+ if (m_invert)
+ result = !result;
+
+ return result;
+}
+
+
+
+bool SCA_KeyboardSensor::TriggerOnAllKeys()
+{
+ return m_bAllKeys;
+}
+
+
+
+bool SCA_KeyboardSensor::Evaluate(CValue* eventval)
+{
+ bool result = false;
+ SCA_IInputDevice* inputdev = m_pKeyboardMgr->GetInputDevice();
+
+ // cerr << "SCA_KeyboardSensor::Eval event, sensing for "<< m_hotkey << " at device " << inputdev << "\n";
+
+ /* See if we need to do logging: togPropState exists and is
+ * different from 0 */
+ CValue* myparent = GetParent();
+ CValue* togPropState = myparent->GetProperty(m_toggleprop);
+ if (togPropState &&
+ (((int)togPropState->GetNumber()) != 0) )
+ {
+ LogKeystrokes();
+ }
+
+
+
+ /* Now see whether events must be bounced. */
+ if (m_bAllKeys)
+ {
+ bool justactivated = false;
+ bool justreleased = false;
+
+ for (int i=SCA_IInputDevice::KX_BEGINKEY ; i< SCA_IInputDevice::KX_ENDKEY;i++)
+ {
+ const SCA_InputEvent & inevent = inputdev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) i);
+ if (inevent.m_status == SCA_InputEvent::KX_JUSTACTIVATED)
+ {
+ justactivated = true;
+ }
+ if (inevent.m_status == SCA_InputEvent::KX_JUSTRELEASED)
+ {
+ justreleased = true;
+ }
+ }
+
+ if (justactivated)
+ {
+ m_val=1;
+ result = true;
+ } else
+ {
+ if (justreleased)
+ {
+ m_val=0;
+ result = true;
+ }
+ }
+
+
+ } else
+ {
+
+ // cerr << "======= SCA_KeyboardSensor::Evaluate:: peeking at key status" << endl;
+ const SCA_InputEvent & inevent = inputdev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) m_hotkey);
+
+ // cerr << "======= SCA_KeyboardSensor::Evaluate:: status: " << inevent.m_status << endl;
+
+ if (inevent.m_status == SCA_InputEvent::KX_NO_INPUTSTATUS)
+ {
+ int i=4;
+ } else
+ {
+ if (inevent.m_status == SCA_InputEvent::KX_JUSTACTIVATED)
+ {
+ m_val=1;
+ result = true;
+ } else
+ {
+ if (inevent.m_status == SCA_InputEvent::KX_JUSTRELEASED)
+ {
+ m_val = 0;
+ result = true;
+ }
+ }
+ }
+ }
+
+ return result;
+
+}
+
+void SCA_KeyboardSensor::AddToTargetProp(int keyIndex)
+{
+ if (IsPrintable(keyIndex)) {
+ CValue* tprop = GetParent()->GetProperty(m_targetprop);
+
+ if (tprop) {
+ /* overwrite the old property */
+ if (IsDelete(keyIndex)) {
+ /* strip one char, if possible */
+ STR_String newprop = tprop->GetText();
+ int oldlength = newprop.Length();
+ if (oldlength >= 1 ) {
+ newprop.SetLength(oldlength - 1);
+ CStringValue * newstringprop = new CStringValue(newprop, m_targetprop);
+ GetParent()->SetProperty(m_targetprop, newstringprop);
+ }
+ } else {
+ /* append */
+ char pchar = ToCharacter(keyIndex, IsShifted());
+ STR_String newprop = tprop->GetText() + pchar;
+ CStringValue * newstringprop = new CStringValue(newprop, m_targetprop);
+ GetParent()->SetProperty(m_targetprop, newstringprop);
+ }
+ } else {
+ if (!IsDelete(keyIndex)) {
+ /* Make a new property. Deletes can be ignored. */
+ char pchar = ToCharacter(keyIndex, IsShifted());
+ STR_String newprop = pchar;
+ CStringValue * newstringprop = new CStringValue(newprop, m_targetprop);
+ GetParent()->SetProperty(m_targetprop, newstringprop);
+ }
+ }
+ }
+
+}
+
+/**
+ * Determine whether this character can be printed. We cannot use
+ * the library functions here, because we need to test our own
+ * keycodes. */
+bool SCA_KeyboardSensor::IsPrintable(int keyIndex)
+{
+ /* only print
+ * - numerals: KX_ZEROKEY to KX_NINEKEY
+ * - alphas: KX_AKEY to KX_ZKEY.
+ * - specials: KX_RETKEY, KX_PADASTERKEY, KX_PADCOMMAKEY to KX_PERIODKEY,
+ * KX_TABKEY , KX_SEMICOLONKEY to KX_RIGHTBRACKETKEY,
+ * KX_PAD2 to KX_PADPLUSKEY
+ * - delete and backspace: also printable in the sense that they modify
+ * the string
+ * - retkey: should this be printable?
+ * - virgule: prints a space... don't know which key that's supposed
+ * to be...
+ */
+ if ( ((keyIndex >= SCA_IInputDevice::KX_ZEROKEY)
+ && (keyIndex <= SCA_IInputDevice::KX_NINEKEY))
+ || ((keyIndex >= SCA_IInputDevice::KX_AKEY)
+ && (keyIndex <= SCA_IInputDevice::KX_ZKEY))
+ || (keyIndex == SCA_IInputDevice::KX_SPACEKEY)
+/* || (keyIndex == KX_RETKEY) */
+ || (keyIndex == SCA_IInputDevice::KX_PADASTERKEY)
+ || (keyIndex == SCA_IInputDevice::KX_TABKEY)
+ || ((keyIndex >= SCA_IInputDevice::KX_COMMAKEY)
+ && (keyIndex <= SCA_IInputDevice::KX_PERIODKEY))
+ || ((keyIndex >= SCA_IInputDevice::KX_SEMICOLONKEY)
+ && (keyIndex <= SCA_IInputDevice::KX_RIGHTBRACKETKEY))
+ || ((keyIndex >= SCA_IInputDevice::KX_PAD2)
+ && (keyIndex <= SCA_IInputDevice::KX_PADPLUSKEY))
+ || (keyIndex == SCA_IInputDevice::KX_DELKEY)
+ || (keyIndex == SCA_IInputDevice::KX_BACKSPACEKEY)
+ )
+ {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+// this code looks ugly, please use an ordinary hashtable
+
+char SCA_KeyboardSensor::ToCharacter(int keyIndex, bool shifted)
+{
+ /* numerals */
+ if ( (keyIndex >= SCA_IInputDevice::KX_ZEROKEY)
+ && (keyIndex <= SCA_IInputDevice::KX_NINEKEY) ) {
+ if (shifted) {
+ char numshift[] = ")!@#$%^&*(";
+ return numshift[keyIndex - '0'];
+ } else {
+ return keyIndex - SCA_IInputDevice::KX_ZEROKEY + '0';
+ }
+ }
+
+ /* letters... always lowercase... is that desirable? */
+ if ( (keyIndex >= SCA_IInputDevice::KX_AKEY)
+ && (keyIndex <= SCA_IInputDevice::KX_ZKEY) ) {
+ if (shifted) {
+ return keyIndex - SCA_IInputDevice::KX_AKEY + 'A';
+ } else {
+ return keyIndex - SCA_IInputDevice::KX_AKEY + 'a';
+ }
+ }
+
+ if (keyIndex == SCA_IInputDevice::KX_SPACEKEY) {
+ return ' ';
+ }
+
+/* || (keyIndex == SCA_IInputDevice::KX_RETKEY) */
+
+ if (keyIndex == SCA_IInputDevice::KX_PADASTERKEY) {
+ return '*';
+ }
+
+ if (keyIndex == SCA_IInputDevice::KX_TABKEY) {
+ return '\t';
+ }
+
+ /* comma to period */
+ char commatoperiod[] = ",-.";
+ char commatoperiodshifted[] = "<_>";
+ if (keyIndex == SCA_IInputDevice::KX_COMMAKEY) {
+ if (shifted) {
+ return commatoperiodshifted[0];
+ } else {
+ return commatoperiod[0];
+ }
+ }
+ if (keyIndex == SCA_IInputDevice::KX_MINUSKEY) {
+ if (shifted) {
+ return commatoperiodshifted[1];
+ } else {
+ return commatoperiod[1];
+ }
+ }
+ if (keyIndex == SCA_IInputDevice::KX_PERIODKEY) {
+ if (shifted) {
+ return commatoperiodshifted[2];
+ } else {
+ return commatoperiod[2];
+ }
+ }
+
+ /* semicolon to rightbracket */
+ char semicolontorightbracket[] = ";\'` /\\=[]";
+ char semicolontorightbracketshifted[] = ":\"~ \?|+{}";
+ if ((keyIndex >= SCA_IInputDevice::KX_SEMICOLONKEY)
+ && (keyIndex <= SCA_IInputDevice::KX_RIGHTBRACKETKEY)) {
+ if (shifted) {
+ return semicolontorightbracketshifted[keyIndex - SCA_IInputDevice::KX_SEMICOLONKEY];
+ } else {
+ return semicolontorightbracket[keyIndex - SCA_IInputDevice::KX_SEMICOLONKEY];
+ }
+ }
+
+ /* keypad2 to padplus */
+ char pad2topadplus[] = "246813579. 0- +";
+ if ((keyIndex >= SCA_IInputDevice::KX_PAD2)
+ && (keyIndex <= SCA_IInputDevice::KX_PADPLUSKEY)) {
+ return pad2topadplus[keyIndex - SCA_IInputDevice::KX_PAD2];
+ }
+
+ return '!';
+}
+
+/**
+ * Tests whether this is a delete key.
+ */
+bool SCA_KeyboardSensor::IsDelete(int keyIndex)
+{
+ if ( (keyIndex == SCA_IInputDevice::KX_DELKEY)
+ || (keyIndex == SCA_IInputDevice::KX_BACKSPACEKEY) ) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+/**
+ * Tests whether shift is pressed
+ */
+bool SCA_KeyboardSensor::IsShifted(void)
+{
+ SCA_IInputDevice* inputdev = m_pKeyboardMgr->GetInputDevice();
+
+ if ( (inputdev->GetEventValue(SCA_IInputDevice::KX_RIGHTSHIFTKEY).m_status
+ == SCA_InputEvent::KX_ACTIVE)
+ || (inputdev->GetEventValue(SCA_IInputDevice::KX_RIGHTSHIFTKEY).m_status
+ == SCA_InputEvent::KX_JUSTACTIVATED)
+ || (inputdev->GetEventValue(SCA_IInputDevice::KX_LEFTSHIFTKEY).m_status
+ == SCA_InputEvent::KX_ACTIVE)
+ || (inputdev->GetEventValue(SCA_IInputDevice::KX_LEFTSHIFTKEY).m_status
+ == SCA_InputEvent::KX_JUSTACTIVATED)
+ ) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void SCA_KeyboardSensor::LogKeystrokes(void)
+{
+ SCA_IInputDevice* inputdev = m_pKeyboardMgr->GetInputDevice();
+ int num = inputdev->GetNumActiveEvents();
+
+ /* weird loop, this one... */
+ if (num > 0)
+ {
+
+ int index = 0;
+ /* Check on all keys whether they were pushed. This does not
+ * untangle the ordering, so don't type too fast :) */
+ for (int i=SCA_IInputDevice::KX_BEGINKEY ; i< SCA_IInputDevice::KX_ENDKEY;i++)
+ {
+ const SCA_InputEvent & inevent = inputdev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) i);
+ if (inevent.m_status == SCA_InputEvent::KX_JUSTACTIVATED) //NO_INPUTSTATUS)
+ {
+ if (index < num)
+ {
+ AddToTargetProp(i);
+ index++;
+ }
+ }
+ }
+ }
+}
+
+
+/* ------------------------------------------------------------------------- */
+/* Python functions : specific */
+/* ------------------------------------------------------------------------- */
+
+
+PyObject* SCA_KeyboardSensor::PySetAllMode(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ bool allkeys;
+
+ if (!PyArg_ParseTuple(args, "i", &allkeys))
+ {
+ return NULL;
+ }
+
+ m_bAllKeys = allkeys;
+ Py_Return
+}
+
+
+
+PyObject* SCA_KeyboardSensor::sPySetAllMode(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+// printf("sPyIsPositive\n");
+ return ((SCA_KeyboardSensor*) self)->PyIsPositive(self, args, kwds);
+}
+
+
+/** 1. GetKey : check which key this sensor looks at */
+char SCA_KeyboardSensor::GetKey_doc[] =
+"getKey()\n"
+"\tReturn the code of the key this sensor is listening to.\n" ;
+PyObject* SCA_KeyboardSensor::PyGetKey(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ return PyInt_FromLong(m_hotkey);
+}
+
+/** 2. SetKey: change the key to look at */
+char SCA_KeyboardSensor::SetKey_doc[] =
+"setKey(keycode)\n"
+"\t- keycode: any code from GameKeys\n"
+"\tSet the key this sensor should listen to.\n" ;
+PyObject* SCA_KeyboardSensor::PySetKey(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ int keyCode;
+
+ if(!PyArg_ParseTuple(args, "i", &keyCode)) {
+ return NULL;
+ }
+
+ /* Since we have symbolic constants for this in Python, we don't guard */
+ /* anything. It's up to the user to provide a sensible number. */
+ m_hotkey = keyCode;
+
+ Py_Return;
+}
+
+/** 3. GetHold1 : set the first bucky bit */
+char SCA_KeyboardSensor::GetHold1_doc[] =
+"getHold1()\n"
+"\tReturn the code of the first key modifier to the key this \n"
+"\tsensor is listening to.\n" ;
+PyObject* SCA_KeyboardSensor::PyGetHold1(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ return PyInt_FromLong(m_qual);
+}
+
+/** 4. SetHold1: change the first bucky bit */
+char SCA_KeyboardSensor::SetHold1_doc[] =
+"setHold1(keycode)\n"
+"\t- keycode: any code from GameKeys\n"
+"\tSet the first modifier to the key this sensor should listen to.\n" ;
+PyObject* SCA_KeyboardSensor::PySetHold1(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ int keyCode;
+
+ if(!PyArg_ParseTuple(args, "i", &keyCode)) {
+ return NULL;
+ }
+
+ /* Since we have symbolic constants for this in Python, we don't guard */
+ /* anything. It's up to the user to provide a sensible number. */
+ m_qual = keyCode;
+
+ Py_Return;
+}
+
+/** 5. GetHold2 : get the second bucky bit */
+char SCA_KeyboardSensor::GetHold2_doc[] =
+"getHold2()\n"
+"\tReturn the code of the second key modifier to the key this \n"
+"\tsensor is listening to.\n" ;
+PyObject* SCA_KeyboardSensor::PyGetHold2(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ return PyInt_FromLong(m_qual2);
+}
+
+/** 6. SetHold2: change the second bucky bit */
+char SCA_KeyboardSensor::SetHold2_doc[] =
+"setHold2(keycode)\n"
+"\t- keycode: any code from GameKeys\n"
+"\tSet the first modifier to the key this sensor should listen to.\n" ;
+PyObject* SCA_KeyboardSensor::PySetHold2(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ int keyCode;
+
+ if(!PyArg_ParseTuple(args, "i", &keyCode)) {
+ return NULL;
+ }
+
+ /* Since we have symbolic constants for this in Python, we don't guard */
+ /* anything. It's up to the user to provide a sensible number. */
+ m_qual2 = keyCode;
+
+ Py_Return;
+}
+
+
+char SCA_KeyboardSensor::GetPressedKeys_doc[] =
+"getPressedKeys()\n"
+"\tGet a list of pressed keys that have either been pressed, or just released this frame.\n" ;
+
+PyObject* SCA_KeyboardSensor::PyGetPressedKeys(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ SCA_IInputDevice* inputdev = m_pKeyboardMgr->GetInputDevice();
+
+ int num = inputdev->GetNumJustEvents();
+ PyObject* resultlist = PyList_New(num);
+
+ if (num > 0)
+ {
+
+ int index = 0;
+
+ for (int i=SCA_IInputDevice::KX_BEGINKEY ; i< SCA_IInputDevice::KX_ENDKEY;i++)
+ {
+ const SCA_InputEvent & inevent = inputdev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) i);
+ if ((inevent.m_status == SCA_InputEvent::KX_JUSTACTIVATED)
+ || (inevent.m_status == SCA_InputEvent::KX_JUSTRELEASED))
+ {
+ if (index < num)
+ {
+ PyObject* keypair = PyList_New(2);
+ PyList_SetItem(keypair,0,PyInt_FromLong(i));
+ PyList_SetItem(keypair,1,PyInt_FromLong(inevent.m_status));
+ PyList_SetItem(resultlist,index,keypair);
+ index++;
+ }
+ }
+ }
+ if (index>0) return resultlist;
+ }
+
+ Py_Return;
+}
+
+
+
+char SCA_KeyboardSensor::GetCurrentlyPressedKeys_doc[] =
+"getCurrentlyPressedKeys()\n"
+"\tGet a list of keys that are currently pressed.\n" ;
+
+PyObject* SCA_KeyboardSensor::PyGetCurrentlyPressedKeys(PyObject* self, PyObject* args, PyObject* kwds)
+{
+SCA_IInputDevice* inputdev = m_pKeyboardMgr->GetInputDevice();
+
+ int num = inputdev->GetNumActiveEvents();
+ PyObject* resultlist = PyList_New(num);
+
+ if (num > 0)
+ {
+ int index = 0;
+
+ for (int i=SCA_IInputDevice::KX_BEGINKEY ; i< SCA_IInputDevice::KX_ENDKEY;i++)
+ {
+ const SCA_InputEvent & inevent = inputdev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) i);
+ if ( (inevent.m_status == SCA_InputEvent::KX_ACTIVE)
+ || (inevent.m_status == SCA_InputEvent::KX_JUSTACTIVATED))
+ {
+ if (index < num)
+ {
+ PyObject* keypair = PyList_New(2);
+ PyList_SetItem(keypair,0,PyInt_FromLong(i));
+ PyList_SetItem(keypair,1,PyInt_FromLong(inevent.m_status));
+ PyList_SetItem(resultlist,index,keypair);
+ index++;
+ }
+ }
+ }
+
+ /* why?*/
+ if (index > 0) return resultlist;
+ }
+
+ Py_Return;
+}
+
+/* ------------------------------------------------------------------------- */
+/* Python functions : integration hooks */
+/* ------------------------------------------------------------------------- */
+
+PyTypeObject SCA_KeyboardSensor::Type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0,
+ "SCA_KeyboardSensor",
+ sizeof(SCA_KeyboardSensor),
+ 0,
+ PyDestructor,
+ 0,
+ __getattr,
+ __setattr,
+ 0, //&MyPyCompare,
+ __repr,
+ 0, //&cvalue_as_number,
+ 0,
+ 0,
+ 0,
+ 0
+};
+
+PyParentObject SCA_KeyboardSensor::Parents[] = {
+ &SCA_KeyboardSensor::Type,
+ &SCA_ISensor::Type,
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
+};
+
+PyMethodDef SCA_KeyboardSensor::Methods[] = {
+ {"getKey", (PyCFunction) SCA_KeyboardSensor::sPyGetKey, METH_VARARGS, GetKey_doc},
+ {"setKey", (PyCFunction) SCA_KeyboardSensor::sPySetKey, METH_VARARGS, SetKey_doc},
+ {"getHold1", (PyCFunction) SCA_KeyboardSensor::sPyGetHold1, METH_VARARGS, GetHold1_doc},
+ {"setHold1", (PyCFunction) SCA_KeyboardSensor::sPySetHold1, METH_VARARGS, SetHold1_doc},
+ {"getHold2", (PyCFunction) SCA_KeyboardSensor::sPyGetHold2, METH_VARARGS, GetHold2_doc},
+ {"setHold2", (PyCFunction) SCA_KeyboardSensor::sPySetHold2, METH_VARARGS, SetHold2_doc},
+// {"getUseAllKeys", (PyCFunction) SCA_KeyboardSensor::sPyGetUseAllKeys, METH_VARARGS, GetUseAllKeys_doc},
+// {"setUseAllKeys", (PyCFunction) SCA_KeyboardSensor::sPySetUseAllKeys, METH_VARARGS, SetUseAllKeys_doc},
+ {"getPressedKeys", (PyCFunction) SCA_KeyboardSensor::sPyGetPressedKeys, METH_VARARGS, GetPressedKeys_doc},
+ {"getCurrentlyPressedKeys", (PyCFunction) SCA_KeyboardSensor::sPyGetCurrentlyPressedKeys, METH_VARARGS, GetCurrentlyPressedKeys_doc},
+// {"getKeyEvents", (PyCFunction) SCA_KeyboardSensor::sPyGetKeyEvents, METH_VARARGS, GetKeyEvents_doc},
+ {NULL,NULL} //Sentinel
+};
+
+PyObject*
+SCA_KeyboardSensor::_getattr(char* attr)
+{
+ _getattr_up(SCA_ISensor);
+}
+
diff --git a/source/gameengine/GameLogic/SCA_KeyboardSensor.h b/source/gameengine/GameLogic/SCA_KeyboardSensor.h
new file mode 100644
index 00000000000..f9de2a0e715
--- /dev/null
+++ b/source/gameengine/GameLogic/SCA_KeyboardSensor.h
@@ -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 *****
+ * Sensor for keyboard input
+ */
+
+#ifndef __KX_KEYBOARDSENSOR
+#define __KX_KEYBOARDSENSOR
+
+#include "SCA_ISensor.h"
+#include "BoolValue.h"
+#include <list>
+
+/**
+ * The keyboard sensor listens to the keyboard, and passes on events
+ * on selected keystrokes. It has an alternate mode in which it logs
+ * keypresses to a property. Note that these modes are not mutually
+ * exclusive. */
+class SCA_KeyboardSensor : public SCA_ISensor
+{
+ Py_Header;
+ class SCA_KeyboardManager* m_pKeyboardMgr;
+
+
+ /**
+ * the key this sensor is sensing for
+ */
+ int m_hotkey;
+ short int m_qual,m_qual2;
+ short int m_val;
+ /**
+ * If this toggle is true, all incoming key events generate a
+ * response.
+ */
+ bool m_bAllKeys;
+
+ /**
+ * The name of the property to which logged text is appended. If
+ * this property is not defined, no logging takes place.
+ */
+ STR_String m_targetprop;
+ /**
+ * The property that indicates whether or not to log text when in
+ * loggin mode. If the property equals 0, no loggin is done. For
+ * all other values, logging is active. Logging can only become
+ * active if there is a property to log to. Logging is independant
+ * from hotkey settings. */
+ STR_String m_toggleprop;
+
+ /**
+ * Log the keystrokes from the current input buffer.
+ */
+ void LogKeystrokes(void);
+
+ /**
+ * Adds this key-code to the target prop.
+ */
+ void AddToTargetProp(int keyIndex);
+
+ /**
+ * Determine whether this character can be printed. We cannot use
+ * the library functions here, because we need to test our own
+ * keycodes. */
+ bool IsPrintable(int keyIndex);
+
+ /**
+ * Transform keycodes to something printable.
+ */
+ char ToCharacter(int keyIndex, bool shifted);
+
+ /**
+ * Tests whether this is a delete key.
+ */
+ bool IsDelete(int keyIndex);
+
+ /**
+ * Tests whether shift is pressed.
+ */
+ bool IsShifted(void);
+
+public:
+ SCA_KeyboardSensor(class SCA_KeyboardManager* keybdmgr,
+ short int hotkey,
+ short int qual,
+ short int qual2,
+ bool bAllKeys,
+ const STR_String& targetProp,
+ const STR_String& toggleProp,
+ SCA_IObject* gameobj,
+ PyTypeObject* T=&Type );
+ virtual ~SCA_KeyboardSensor();
+ virtual CValue* GetReplica();
+
+ short int GetHotkey();
+ virtual bool Evaluate(CValue* event);
+ virtual bool IsPositiveTrigger();
+ bool TriggerOnAllKeys();
+
+ /* --------------------------------------------------------------------- */
+ /* Python interface ---------------------------------------------------- */
+ /* --------------------------------------------------------------------- */
+
+ virtual PyObject* _getattr(char *attr);
+
+
+ PyObject* PySetAllMode(PyObject* self,
+ PyObject* args,
+ PyObject* kwds);
+ static PyObject* sPySetAllMode(PyObject* self,
+ PyObject* args,
+ PyObject* kwds);
+
+ /** 1. GetKey : check which key this sensor looks at */
+ KX_PYMETHOD_DOC(SCA_KeyboardSensor,GetKey);
+ /** 2. SetKey: change the key to look at */
+ KX_PYMETHOD_DOC(SCA_KeyboardSensor,SetKey);
+ /** 3. GetHold1 : set the first bucky bit */
+ KX_PYMETHOD_DOC(SCA_KeyboardSensor,GetHold1);
+ /** 4. SetHold1: change the first bucky bit */
+ KX_PYMETHOD_DOC(SCA_KeyboardSensor,SetHold1);
+ /** 5. GetHold2 : set the second bucky bit */
+ KX_PYMETHOD_DOC(SCA_KeyboardSensor,GetHold2);
+ /** 6. SetHold2: change the second bucky bit */
+ KX_PYMETHOD_DOC(SCA_KeyboardSensor,SetHold2);
+ /** 9. GetPressedKeys: */
+ KX_PYMETHOD_DOC(SCA_KeyboardSensor,GetPressedKeys);
+ /** 9. GetCurrrentlyPressedKeys: */
+ KX_PYMETHOD_DOC(SCA_KeyboardSensor,GetCurrentlyPressedKeys);
+};
+
+#endif //__KX_KEYBOARDSENSOR
diff --git a/source/gameengine/GameLogic/SCA_LogicManager.cpp b/source/gameengine/GameLogic/SCA_LogicManager.cpp
new file mode 100644
index 00000000000..a29d6d19729
--- /dev/null
+++ b/source/gameengine/GameLogic/SCA_LogicManager.cpp
@@ -0,0 +1,461 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * Regulates the top-level logic behaviour for one scene.
+ */
+#include "Value.h"
+#include "SCA_LogicManager.h"
+
+#include "SCA_ISensor.h"
+#include "SCA_IController.h"
+#include "SCA_IActuator.h"
+#include "SCA_EventManager.h"
+
+#include <set>
+
+SCA_LogicManager::SCA_LogicManager()
+{
+}
+
+
+
+SCA_LogicManager::~SCA_LogicManager()
+{
+ for (vector<SCA_EventManager*>::iterator it = m_eventmanagers.begin();!(it==m_eventmanagers.end());it++)
+ {
+ delete (*it);
+ }
+ m_eventmanagers.clear();
+ m_sensorcontrollermapje.clear();
+
+ int numgameobj = m_mapStringToGameObjects.size();
+ for (int i = 0; i < numgameobj; i++)
+ {
+ CValue** gameobjptr = m_mapStringToGameObjects.at(i);
+ assert(gameobjptr);
+ if (gameobjptr)
+ (*gameobjptr)->Release();
+
+ }
+
+ /*for (int i=0;i<m_sensorcontrollermap.size();i++)
+ {
+ vector<SCA_IController*>* controllerarray = *(m_sensorcontrollermap[i]);
+ delete controllerarray;
+ }
+ */
+}
+
+
+/*
+// this kind of fixes bug 398 but breakes games, so better leave it out for now.
+// a removed object's gameobject (and logicbricks and stuff) didn't get released
+// because it was still in the m_mapStringToGameObjects map.
+void SCA_LogicManager::RemoveGameObject(const STR_String& gameobjname)
+{
+ int numgameobj = m_mapStringToGameObjects.size();
+ for (int i = 0; i < numgameobj; i++)
+ {
+ CValue** gameobjptr = m_mapStringToGameObjects.at(i);
+ assert(gameobjptr);
+
+ if (gameobjptr)
+ {
+ if ((*gameobjptr)->GetName() == gameobjname)
+ (*gameobjptr)->Release();
+ }
+ }
+
+ m_mapStringToGameObjects.remove(gameobjname);
+}
+*/
+
+
+void SCA_LogicManager::RegisterEventManager(SCA_EventManager* eventmgr)
+{
+ m_eventmanagers.push_back(eventmgr);
+}
+
+
+
+void SCA_LogicManager::RegisterGameObjectName(const STR_String& gameobjname,
+ CValue* gameobj)
+{
+ STR_HashedString mn = gameobjname;
+ m_mapStringToGameObjects.insert(mn,gameobj);
+}
+
+
+
+CValue* SCA_LogicManager::GetGameObjectByName(const STR_String& gameobjname)
+{
+ STR_HashedString mn = "OB"+gameobjname;
+ CValue** gameptr = m_mapStringToGameObjects[mn];
+
+ if (gameptr)
+ return *gameptr;
+
+ return NULL;
+}
+
+
+
+void SCA_LogicManager::RemoveSensor(SCA_ISensor* sensor)
+{
+ m_sensorcontrollermapje.erase(sensor);
+
+ for (vector<SCA_EventManager*>::const_iterator ie=m_eventmanagers.begin();
+ !(ie==m_eventmanagers.end());ie++)
+ {
+ (*ie)->RemoveSensor(sensor);
+ }
+}
+
+
+
+void SCA_LogicManager::RemoveDestroyedActuator(SCA_IActuator* actuator)
+{
+
+ m_removedActuators.push_back(SmartActuatorPtr(actuator,0));
+ // take care that no controller can use this actuator again !
+
+ std::map<SCA_ISensor*,controllerlist>::const_iterator sit;
+ for (sit = m_sensorcontrollermapje.begin();!(sit==m_sensorcontrollermapje.end());++sit)
+ {
+ controllerlist contlist = (*sit).second;
+ for (list<SCA_IController*>::const_iterator c= contlist.begin();!(c==contlist.end());c++)
+ {
+ (*c)->UnlinkActuator(actuator);
+ }
+ }
+}
+
+
+
+void SCA_LogicManager::RegisterToSensor(SCA_IController* controller,SCA_ISensor* sensor)
+{
+ m_sensorcontrollermapje[sensor].push_back(controller);
+ controller->LinkToSensor(sensor);
+}
+
+
+
+void SCA_LogicManager::RegisterToActuator(SCA_IController* controller,SCA_IActuator* actua)
+{
+ controller->LinkToActuator(actua);
+}
+
+
+
+void SCA_LogicManager::BeginFrame(double curtime,double deltatime)
+{
+ for (vector<SCA_EventManager*>::const_iterator ie=m_eventmanagers.begin();
+ !(ie==m_eventmanagers.end());ie++)
+ {
+ (*ie)->NextFrame(curtime,deltatime);
+ }
+
+ // for this frame, look up for activated sensors, and build the collection of triggered controllers
+ int numsensors = this->m_activatedsensors.size();
+
+ set<SmartControllerPtr> triggeredControllerSet;
+
+ for (vector<SCA_ISensor*>::const_iterator is=m_activatedsensors.begin();
+ !(is==m_activatedsensors.end());is++)
+ {
+ SCA_ISensor* sensor = *is;
+ controllerlist contlist = m_sensorcontrollermapje[sensor];
+ for (list<SCA_IController*>::const_iterator c= contlist.begin();
+ !(c==contlist.end());c++)
+ {
+ SCA_IController* contr = *c;//controllerarray->at(c);
+ triggeredControllerSet.insert(SmartControllerPtr(contr,0));
+ }
+ //sensor->SetActive(false);
+ }
+
+
+ int numtriggered = triggeredControllerSet.size();
+ for (set<SmartControllerPtr>::iterator tit=triggeredControllerSet.begin();
+ !(tit==triggeredControllerSet.end());tit++)
+ {
+ (*tit)->Trigger(this);
+ }
+ triggeredControllerSet.clear();
+}
+
+
+
+void SCA_LogicManager::UpdateFrame(double curtime,double deltatime)
+{
+ vector<SmartActuatorPtr>::iterator ra;
+ for (ra = m_removedActuators.begin();
+ !(ra == m_removedActuators.end());ra++)
+ {
+ m_activeActuators.erase(*ra);
+ (*ra)->SetActive(false);
+ }
+ m_removedActuators.clear();
+
+ for (set<SmartActuatorPtr>::iterator ia = m_activeActuators.begin();!(ia==m_activeActuators.end());ia++)
+ {
+ //SCA_IActuator* actua = *ia;
+ if (!(*ia)->Update(curtime,deltatime))
+ {
+ //*ia = m_activeactuators.back();
+ m_removedActuators.push_back(*ia);
+
+ (*ia)->SetActive(false);
+ //m_activeactuators.pop_back();
+ }
+ }
+
+ for ( ra = m_removedActuators.begin();
+ !(ra == m_removedActuators.end());ra++)
+ {
+ m_activeActuators.erase(*ra);
+ (*ra)->SetActive(false);
+ }
+ m_removedActuators.clear();
+}
+
+
+
+void* SCA_LogicManager::GetActionByName (const STR_String& actname)
+{
+ STR_HashedString an = "AC"+actname;
+ void** actptr = m_mapStringToActions[an];
+
+ if (actptr)
+ return *actptr;
+
+ return NULL;
+}
+
+
+
+void* SCA_LogicManager::GetMeshByName(const STR_String& meshname)
+{
+ STR_HashedString mn = "ME"+meshname;
+ void** meshptr = m_mapStringToMeshes[mn];
+
+ if (meshptr)
+ return *meshptr;
+
+ return NULL;
+}
+
+
+
+void SCA_LogicManager::RegisterMeshName(const STR_String& meshname,void* mesh)
+{
+ STR_HashedString mn = meshname;
+ m_mapStringToMeshes.insert(mn,mesh);
+}
+
+
+
+void SCA_LogicManager::RegisterActionName(const STR_String& actname,void* action)
+{
+ STR_HashedString an = actname;
+ m_mapStringToActions.insert(an, action);
+}
+
+
+
+void SCA_LogicManager::EndFrame()
+{
+ for (vector<SCA_ISensor*>::const_iterator is=m_activatedsensors.begin();
+ !(is==m_activatedsensors.end());is++)
+ {
+ SCA_ISensor* sensor = *is;
+ sensor->SetActive(false);
+ }
+ m_activatedsensors.clear();
+
+ for (vector<SCA_EventManager*>::const_iterator ie=m_eventmanagers.begin();
+ !(ie==m_eventmanagers.end());ie++)
+ {
+ (*ie)->EndFrame();
+ }
+
+
+}
+
+
+
+void SCA_LogicManager::AddActivatedSensor(SCA_ISensor* sensor)
+{
+ // each frame, only add sensor once, and to avoid a seek, or bloated container
+ // hold a flag in each sensor, with the 'framenr'
+ if (!sensor->IsActive())
+ {
+ sensor->SetActive(true);
+ m_activatedsensors.push_back(sensor);
+ }
+}
+
+
+
+void SCA_LogicManager::AddActiveActuator(SCA_IActuator* actua,CValue* event)
+{
+ if (!actua->IsActive())
+ {
+ actua->SetActive(true);
+ m_activeActuators.insert(SmartActuatorPtr(actua,0));
+ }
+ actua->AddEvent(event->AddRef());
+}
+
+
+
+SCA_EventManager* SCA_LogicManager::FindEventManager(int eventmgrtype)
+{
+ // find an eventmanager of a certain type
+ SCA_EventManager* eventmgr = NULL;
+
+ for (vector<SCA_EventManager*>::const_iterator i=
+ m_eventmanagers.begin();!(i==m_eventmanagers.end());i++)
+ {
+ SCA_EventManager* emgr = *i;
+ if (emgr->GetType() == eventmgrtype)
+ {
+ eventmgr = emgr;
+ break;
+ }
+ }
+ return eventmgr;
+}
+
+
+
+SmartActuatorPtr::SmartActuatorPtr(const SmartActuatorPtr& other)
+{
+ this->m_actuator = other.m_actuator;
+ this->m_actuator->AddRef();
+}
+
+
+
+SmartActuatorPtr::SmartActuatorPtr(SCA_IActuator* actua,int dummy)
+: m_actuator(actua)
+{
+ actua->AddRef();
+}
+
+
+
+SmartActuatorPtr::~SmartActuatorPtr()
+{
+ m_actuator->Release();
+}
+
+
+
+bool SmartActuatorPtr::operator <(const SmartActuatorPtr& other) const
+{
+
+ return m_actuator->LessComparedTo(*other);
+}
+
+
+
+bool SmartActuatorPtr::operator ==(const SmartActuatorPtr& other) const
+{
+ bool result2 = other->LessComparedTo(m_actuator);
+ return (m_actuator->LessComparedTo(*other) && result2);
+}
+
+
+
+SCA_IActuator* SmartActuatorPtr::operator->() const
+{
+ return m_actuator;
+}
+
+
+
+SCA_IActuator* SmartActuatorPtr::operator*() const
+{
+ return m_actuator;
+}
+
+
+
+SmartControllerPtr::SmartControllerPtr(const SmartControllerPtr& copy)
+{
+ this->m_controller = copy.m_controller;
+ this->m_controller->AddRef();
+}
+
+
+
+SmartControllerPtr::SmartControllerPtr(SCA_IController* contr,int dummy)
+: m_controller(contr)
+{
+ m_controller->AddRef();
+}
+
+
+
+SmartControllerPtr::~SmartControllerPtr()
+{
+ m_controller->Release();
+}
+
+
+
+bool SmartControllerPtr::operator <(const SmartControllerPtr& other) const
+{
+ return m_controller->LessComparedTo(*other);
+}
+
+
+
+bool SmartControllerPtr::operator ==(const SmartControllerPtr& other) const
+{
+ return (m_controller->LessComparedTo(*other) && other->LessComparedTo(m_controller));
+}
+
+
+
+SCA_IController* SmartControllerPtr::operator->() const
+{
+ return m_controller;
+}
+
+
+
+SCA_IController* SmartControllerPtr::operator*() const
+{
+ return m_controller;
+}
+
+
diff --git a/source/gameengine/GameLogic/SCA_LogicManager.h b/source/gameengine/GameLogic/SCA_LogicManager.h
new file mode 100644
index 00000000000..f79b19a0dbf
--- /dev/null
+++ b/source/gameengine/GameLogic/SCA_LogicManager.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 *****
+ * Regulates the top-level logic behaviour for one scene.
+ */
+#ifndef __KX_LOGICMANAGER
+#define __KX_LOGICMANAGER
+
+#ifdef WIN32
+#pragma warning (disable:4786)
+#endif
+
+#include <vector>
+//#include "GEN_Map.h"
+#include <set>
+#include <map>
+#include <list>
+
+#include "GEN_Map.h"
+#include "STR_HashedString.h"
+#include "Value.h"
+
+using namespace std;
+typedef list<class SCA_IController*> controllerlist;
+
+/**
+ * This manager handles sensor, controllers and actuators.
+ * logic executes each frame the following way:
+ * find triggering sensors
+ * build list of controllers that are triggered by these triggering sensors
+ * process all triggered controllers
+ * during this phase actuators can be added to the active actuator list
+ * process all active actuators
+ * clear triggering sensors
+ * clear triggered controllers
+ * (actuators may be active during a longer timeframe)
+*/
+
+#include "SCA_ILogicBrick.h"
+
+// todo: make this into a template, but first I want to think about what exactly to put in
+class SmartActuatorPtr
+{
+ SCA_IActuator* m_actuator;
+public:
+ SmartActuatorPtr(SCA_IActuator* actua,int dummy);
+ SmartActuatorPtr(const SmartActuatorPtr& other);
+ virtual ~SmartActuatorPtr();
+ bool operator <(const SmartActuatorPtr& other) const;
+ bool operator ==(const SmartActuatorPtr& other) const;
+ SCA_IActuator* operator->() const;
+ SCA_IActuator* operator*() const;
+
+};
+
+class SmartControllerPtr
+{
+ SCA_IController* m_controller;
+public:
+ SmartControllerPtr(const SmartControllerPtr& copy);
+ SmartControllerPtr(SCA_IController* contr,int dummy);
+ virtual ~SmartControllerPtr();
+ bool operator <(const SmartControllerPtr& other) const;
+ bool operator ==(const SmartControllerPtr& other) const;
+ SCA_IController* operator->() const;
+ SCA_IController* operator*() const;
+
+};
+
+
+
+class SCA_LogicManager
+{
+ vector<class SCA_EventManager*> m_eventmanagers;
+
+ vector<class SCA_ISensor*> m_activatedsensors;
+ set<class SmartActuatorPtr> m_activeActuators;
+
+ map<SCA_ISensor*,controllerlist > m_sensorcontrollermapje;
+
+ // need to find better way for this
+ // also known as FactoryManager...
+ GEN_Map<STR_HashedString,CValue*> m_mapStringToGameObjects;
+ GEN_Map<STR_HashedString,void*> m_mapStringToMeshes;
+ GEN_Map<STR_HashedString,void*> m_mapStringToActions;
+
+ vector<SmartActuatorPtr> m_removedActuators;
+
+public:
+ SCA_LogicManager();
+ virtual ~SCA_LogicManager();
+ //void SetKeyboardManager(SCA_KeyboardManager* keyboardmgr) { m_keyboardmgr=keyboardmgr;}
+ void RegisterEventManager(SCA_EventManager* eventmgr);
+ void RegisterToSensor(SCA_IController* controller,
+ class SCA_ISensor* sensor);
+ void RegisterToActuator(SCA_IController* controller,
+ class SCA_IActuator* actuator);
+
+ void BeginFrame(double curtime,double deltatime);
+ void UpdateFrame(double curtime,double deltatime);
+ void EndFrame();
+ void AddActivatedSensor(SCA_ISensor* sensor);
+ void AddActiveActuator(SCA_IActuator* sensor,class CValue* event);
+ SCA_EventManager* FindEventManager(int eventmgrtype);
+
+ void RemoveGameObject(const STR_String& gameobjname);
+
+ /**
+ * remove Logic Bricks from the running logicmanager
+ */
+ void RemoveSensor(SCA_ISensor* sensor);
+ void RemoveController(SCA_IController* controller);
+ void RemoveDestroyedActuator(SCA_IActuator* actuator);
+
+
+ // for the scripting... needs a FactoryManager later (if we would have time... ;)
+ void RegisterMeshName(const STR_String& meshname,void* mesh);
+ void RegisterActionName(const STR_String& actname,void* action);
+
+ void* GetActionByName (const STR_String& actname);
+ void* GetMeshByName(const STR_String& meshname);
+
+ void RegisterGameObjectName(const STR_String& gameobjname,CValue* gameobj);
+ class CValue* GetGameObjectByName(const STR_String& gameobjname);
+};
+
+#endif //__KX_LOGICMANAGER
diff --git a/source/gameengine/GameLogic/SCA_MouseManager.cpp b/source/gameengine/GameLogic/SCA_MouseManager.cpp
new file mode 100644
index 00000000000..580c77ee61f
--- /dev/null
+++ b/source/gameengine/GameLogic/SCA_MouseManager.cpp
@@ -0,0 +1,116 @@
+/**
+ * Manager for mouse events
+ *
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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
+// 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
+
+#include "BoolValue.h"
+#include "SCA_MouseManager.h"
+#include "SCA_MouseSensor.h"
+#include "IntValue.h"
+
+
+SCA_MouseManager::SCA_MouseManager(SCA_LogicManager* logicmgr,
+ SCA_IInputDevice* mousedev)
+ : SCA_EventManager(MOUSE_EVENTMGR),
+ m_logicmanager(logicmgr),
+ m_mousedevice (mousedev)
+{
+ m_xpos = 0;
+ m_ypos = 0;
+}
+
+
+
+SCA_MouseManager::~SCA_MouseManager()
+{
+}
+
+
+
+SCA_IInputDevice* SCA_MouseManager::GetInputDevice()
+{
+ return m_mousedevice;
+}
+
+
+
+void SCA_MouseManager::NextFrame(double curtime,double deltatime)
+{
+ if (m_mousedevice)
+ {
+ for (int i = 0; i < m_sensors.size(); i++)
+ {
+ SCA_MouseSensor* mousesensor = (SCA_MouseSensor*) m_sensors[i];
+ // (0,0) is the Upper Left corner in our local window
+ // coordinates
+ if (!mousesensor->IsSuspended())
+ {
+ const SCA_InputEvent& event =
+ m_mousedevice->GetEventValue(SCA_IInputDevice::KX_MOUSEX);
+ int mx = event.m_eventval;
+ const SCA_InputEvent& event2 =
+ m_mousedevice->GetEventValue(SCA_IInputDevice::KX_MOUSEY);
+ int my = event2.m_eventval;
+
+ mousesensor->setX(mx);
+ mousesensor->setY(my);
+
+ mousesensor->Activate(m_logicmanager,NULL);
+ }
+ }
+ }
+}
+
+
+
+void SCA_MouseManager::RegisterSensor(SCA_ISensor* keysensor)
+{
+ m_sensors.push_back(keysensor);
+}
+
+
+
+bool SCA_MouseManager::IsPressed(SCA_IInputDevice::KX_EnumInputs inputcode)
+{
+ /* We should guard for non-mouse events maybe? A rather silly side */
+ /* effect here is that position-change events are considered presses as */
+ /* well. */
+
+ return m_mousedevice->IsPressed(inputcode);
+}
diff --git a/source/gameengine/GameLogic/SCA_MouseManager.h b/source/gameengine/GameLogic/SCA_MouseManager.h
new file mode 100644
index 00000000000..9f26a706c17
--- /dev/null
+++ b/source/gameengine/GameLogic/SCA_MouseManager.h
@@ -0,0 +1,72 @@
+/**
+ * Manager for mouse events
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 __KX_MOUSEMANAGER
+#define __KX_MOUSEMANAGER
+
+
+#include "SCA_EventManager.h"
+
+#include <vector>
+
+using namespace std;
+
+#include "SCA_IInputDevice.h"
+
+
+class SCA_MouseManager : public SCA_EventManager
+{
+
+ class SCA_IInputDevice* m_mousedevice;
+ class SCA_LogicManager* m_logicmanager;
+
+ unsigned short m_xpos; // Cached location of the mouse pointer
+ unsigned short m_ypos;
+
+public:
+ SCA_MouseManager(class SCA_LogicManager* logicmgr,class SCA_IInputDevice* mousedev);
+ virtual ~SCA_MouseManager();
+
+ /**
+ * Checks whether a mouse button is depressed. Ignores requests on non-
+ * mouse related evenst. Can also flag mouse movement.
+ */
+ bool IsPressed(SCA_IInputDevice::KX_EnumInputs inputcode);
+ virtual void NextFrame(double curtime,double deltatime);
+ virtual void RegisterSensor(class SCA_ISensor* sensor);
+ SCA_IInputDevice* GetInputDevice();
+};
+
+#endif //__KX_MOUSEMANAGER
diff --git a/source/gameengine/GameLogic/SCA_MouseSensor.cpp b/source/gameengine/GameLogic/SCA_MouseSensor.cpp
new file mode 100644
index 00000000000..f21e4c1b07e
--- /dev/null
+++ b/source/gameengine/GameLogic/SCA_MouseSensor.cpp
@@ -0,0 +1,273 @@
+/**
+ * Sensor for mouse input
+ *
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "SCA_MouseSensor.h"
+#include "SCA_EventManager.h"
+#include "SCA_MouseManager.h"
+#include "SCA_LogicManager.h"
+#include "SCA_IInputDevice.h"
+#include "ConstExpr.h"
+#include <iostream>
+
+/* ------------------------------------------------------------------------- */
+/* Native functions */
+/* ------------------------------------------------------------------------- */
+
+SCA_MouseSensor::SCA_MouseSensor(SCA_MouseManager* eventmgr,
+ int startx,int starty,
+ short int mousemode,
+ SCA_IObject* gameobj,
+ PyTypeObject* T)
+ : SCA_ISensor(gameobj,eventmgr, T),
+ m_pMouseMgr(eventmgr),
+ m_x(startx),
+ m_y(starty)
+{
+ m_mousemode = mousemode;
+ m_triggermode = true;
+ m_val = 0; /* stores the latest attribute */
+
+ switch (m_mousemode) {
+ case KX_MOUSESENSORMODE_LEFTBUTTON:
+ m_hotkey = SCA_IInputDevice::KX_LEFTMOUSE;
+ break;
+ case KX_MOUSESENSORMODE_MIDDLEBUTTON:
+ m_hotkey = SCA_IInputDevice::KX_MIDDLEMOUSE;
+ break;
+ case KX_MOUSESENSORMODE_RIGHTBUTTON:
+ m_hotkey = SCA_IInputDevice::KX_RIGHTMOUSE;
+ break;
+ default:
+ ; /* ignore, no hotkey */
+ }
+
+}
+
+SCA_MouseSensor::~SCA_MouseSensor()
+{
+ /* Nothing to be done here. */
+}
+
+
+
+CValue* SCA_MouseSensor::GetReplica()
+{
+ CValue* replica = new SCA_MouseSensor(*this);
+ // this will copy properties and so on...
+ CValue::AddDataToReplica(replica);
+
+ return replica;
+}
+
+
+
+bool SCA_MouseSensor::IsPositiveTrigger()
+{
+ bool result = (m_val != 0);
+ if (m_invert)
+ result = !result;
+
+ return result;
+}
+
+
+
+short int SCA_MouseSensor::GetModeKey()
+{
+ return m_mousemode;
+}
+
+
+
+SCA_IInputDevice::KX_EnumInputs SCA_MouseSensor::GetHotKey()
+{
+ return m_hotkey;
+}
+
+
+
+bool SCA_MouseSensor::Evaluate(CValue* event)
+{
+ bool result = false;
+ SCA_IInputDevice* mousedev = m_pMouseMgr->GetInputDevice();
+
+
+
+// SCA_ILogicBrick::RegisterEvent(event);
+// if (m_mousemode == KX_MOUSESENSORMODE_MOVEMENT) cout << "\nChecking for movement...";
+//CValue* val = event->GetProperty("val");
+
+ /* both MOUSEX and MOUSEY. Treat all of these as key-presses. */
+ /* So, treat KX_MOUSESENSORMODE_POSITION as */
+ /* KX_MOUSESENSORMODE_POSITIONX || KX_MOUSESENSORMODE_POSITIONY */
+
+ switch (m_mousemode) {
+ case KX_MOUSESENSORMODE_LEFTBUTTON:
+ case KX_MOUSESENSORMODE_MIDDLEBUTTON:
+ case KX_MOUSESENSORMODE_RIGHTBUTTON:
+ {
+ const SCA_InputEvent& event = mousedev->GetEventValue(m_hotkey);
+ if (event.m_status == SCA_InputEvent::KX_JUSTACTIVATED)
+ {
+ m_val = 1;
+ result = true;
+ } else
+ {
+ if (event.m_status == SCA_InputEvent::KX_JUSTRELEASED)
+ {
+ m_val = 0;
+ result = true;
+ }
+ }
+ break;
+ }
+ case KX_MOUSESENSORMODE_MOVEMENT:
+
+ {
+ const SCA_InputEvent& eventX = mousedev->GetEventValue(SCA_IInputDevice::KX_MOUSEX);
+ const SCA_InputEvent& eventY = mousedev->GetEventValue(SCA_IInputDevice::KX_MOUSEY);
+
+ if (eventX.m_status == SCA_InputEvent::KX_JUSTACTIVATED ||
+ eventY.m_status == SCA_InputEvent::KX_JUSTACTIVATED ||
+ eventX.m_status == SCA_InputEvent::KX_ACTIVE ||
+ eventY.m_status == SCA_InputEvent::KX_ACTIVE)
+
+ {
+ m_val = 1;
+ result = true;
+ } else
+ {
+ if (eventX.m_status == SCA_InputEvent::KX_JUSTRELEASED ||
+ eventY.m_status == SCA_InputEvent::KX_JUSTRELEASED )
+ {
+ m_val = 0;
+ result = true;
+ }
+ }
+ break;
+ }
+ default:
+ ; /* error */
+ }
+
+ return result;
+}
+
+void SCA_MouseSensor::setX(short x)
+{
+ m_x = x;
+}
+
+void SCA_MouseSensor::setY(short y)
+{
+ m_y = y;
+}
+
+bool SCA_MouseSensor::isValid(SCA_MouseSensor::KX_MOUSESENSORMODE m)
+{
+ bool res = false;
+
+ res = ((m > KX_MOUSESENSORMODE_NODEF) && (m < KX_MOUSESENSORMODE_MAX));
+
+ return res;
+}
+
+/* ------------------------------------------------------------------------- */
+/* Python functions */
+/* ------------------------------------------------------------------------- */
+
+/* Integration hooks ------------------------------------------------------- */
+PyTypeObject SCA_MouseSensor::Type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0,
+ "SCA_MouseSensor",
+ sizeof(SCA_MouseSensor),
+ 0,
+ PyDestructor,
+ 0,
+ __getattr,
+ __setattr,
+ 0, //&MyPyCompare,
+ __repr,
+ 0, //&cvalue_as_number,
+ 0,
+ 0,
+ 0,
+ 0
+};
+
+PyParentObject SCA_MouseSensor::Parents[] = {
+ &SCA_MouseSensor::Type,
+ &SCA_ISensor::Type,
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
+};
+
+PyMethodDef SCA_MouseSensor::Methods[] = {
+ {"getXPosition", (PyCFunction) SCA_MouseSensor::sPyGetXPosition, METH_VARARGS, GetXPosition_doc},
+ {"getYPosition", (PyCFunction) SCA_MouseSensor::sPyGetYPosition, METH_VARARGS, GetYPosition_doc},
+ {NULL,NULL} //Sentinel
+};
+
+PyObject* SCA_MouseSensor::_getattr(char* attr) {
+ _getattr_up(SCA_ISensor);
+}
+
+/* get x position ---------------------------------------------------------- */
+char SCA_MouseSensor::GetXPosition_doc[] =
+"getXPosition\n"
+"\tReturns the x-coordinate of the mouse sensor, in frame coordinates.\n"
+"\tThe lower-left corner is the origin. The coordinate is given in\n"
+"\tpixels\n";
+PyObject* SCA_MouseSensor::PyGetXPosition(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ return PyInt_FromLong(m_x);
+}
+
+/* get y position ---------------------------------------------------------- */
+char SCA_MouseSensor::GetYPosition_doc[] =
+"getYPosition\n"
+"\tReturns the y-coordinate of the mouse sensor, in frame coordinates.\n"
+"\tThe lower-left corner is the origin. The coordinate is given in\n"
+"\tpixels\n";
+PyObject* SCA_MouseSensor::PyGetYPosition(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ return PyInt_FromLong(m_y);
+}
+
+/* eof */
diff --git a/source/gameengine/GameLogic/SCA_MouseSensor.h b/source/gameengine/GameLogic/SCA_MouseSensor.h
new file mode 100644
index 00000000000..dd6230f421c
--- /dev/null
+++ b/source/gameengine/GameLogic/SCA_MouseSensor.h
@@ -0,0 +1,120 @@
+/**
+ * Senses mouse events
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 __KX_MOUSESENSOR
+#define __KX_MOUSESENSOR
+
+#include "SCA_ISensor.h"
+#include "BoolValue.h"
+#include "SCA_IInputDevice.h"
+
+class SCA_MouseSensor : public SCA_ISensor
+{
+ Py_Header;
+ class SCA_MouseManager* m_pMouseMgr;
+
+ /**
+ * Use SCA_IInputDevice values to encode the mouse mode for now.
+ */
+ short int m_mousemode;
+ /**
+ * Triggermode true means all mouse events trigger. Useful mainly
+ * for button presses.
+ */
+ bool m_triggermode;
+ /**
+ * Remember the last state update
+ */
+ int m_val;
+
+ SCA_IInputDevice::KX_EnumInputs m_hotkey;
+
+ /**
+ * valid x coordinate
+ */
+ short m_x;
+
+ /**
+ * valid y coordinate
+ */
+ short m_y;
+
+ public:
+ /**
+ * Allowable modes for the trigger status of the mouse sensor.
+ */
+ enum KX_MOUSESENSORMODE {
+ KX_MOUSESENSORMODE_NODEF = 0,
+ KX_MOUSESENSORMODE_LEFTBUTTON,
+ KX_MOUSESENSORMODE_MIDDLEBUTTON,
+ KX_MOUSESENSORMODE_RIGHTBUTTON,
+ KX_MOUSESENSORMODE_POSITION,
+ KX_MOUSESENSORMODE_POSITIONX,
+ KX_MOUSESENSORMODE_POSITIONY,
+ KX_MOUSESENSORMODE_MOVEMENT,
+ KX_MOUSESENSORMODE_MAX
+ };
+
+ bool isValid(KX_MOUSESENSORMODE);
+
+ SCA_MouseSensor(class SCA_MouseManager* keybdmgr,
+ int startx,int starty,
+ short int mousemode,
+ SCA_IObject* gameobj,
+ PyTypeObject* T=&Type );
+
+ virtual ~SCA_MouseSensor();
+ virtual CValue* GetReplica();
+ virtual bool Evaluate(CValue* event);
+
+ virtual bool IsPositiveTrigger();
+ short int GetModeKey();
+ SCA_IInputDevice::KX_EnumInputs GetHotKey();
+ void setX(short x);
+ void setY(short y);
+
+ /* --------------------------------------------------------------------- */
+ /* Python interface ---------------------------------------------------- */
+ /* --------------------------------------------------------------------- */
+
+ virtual PyObject* _getattr(char *attr);
+
+ /* read x-coordinate */
+ KX_PYMETHOD_DOC(SCA_MouseSensor,GetXPosition);
+ /* read y-coordinate */
+ KX_PYMETHOD_DOC(SCA_MouseSensor,GetYPosition);
+
+};
+
+#endif //__KX_MOUSESENSOR
diff --git a/source/gameengine/GameLogic/SCA_ORController.cpp b/source/gameengine/GameLogic/SCA_ORController.cpp
new file mode 100644
index 00000000000..966884da809
--- /dev/null
+++ b/source/gameengine/GameLogic/SCA_ORController.cpp
@@ -0,0 +1,135 @@
+/**
+ * 'Or' together all inputs
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "SCA_ORController.h"
+#include "SCA_ISensor.h"
+#include "SCA_LogicManager.h"
+#include "BoolValue.h"
+
+/* ------------------------------------------------------------------------- */
+/* Native functions */
+/* ------------------------------------------------------------------------- */
+
+SCA_ORController::SCA_ORController(SCA_IObject* gameobj,
+ PyTypeObject* T)
+ :SCA_IController(gameobj, T)
+{
+}
+
+
+
+SCA_ORController::~SCA_ORController()
+{
+}
+
+
+
+CValue* SCA_ORController::GetReplica()
+{
+ CValue* replica = new SCA_ORController(*this);
+ // this will copy properties and so on...
+ CValue::AddDataToReplica(replica);
+
+ return replica;
+}
+
+
+void SCA_ORController::Trigger(SCA_LogicManager* logicmgr)
+{
+
+ bool sensorresult = false;
+ SCA_ISensor* sensor;
+
+ vector<SCA_ISensor*>::const_iterator is=m_linkedsensors.begin();
+ while ( (!sensorresult) && (!(is==m_linkedsensors.end())) )
+ {
+ sensor = *is;
+ if (sensor->IsPositiveTrigger()) sensorresult = true;
+ is++;
+ }
+
+ CValue* newevent = new CBoolValue(sensorresult);
+
+ for (vector<SCA_IActuator*>::const_iterator i=m_linkedactuators.begin();
+ !(i==m_linkedactuators.end());i++)
+ {
+ SCA_IActuator* actua = *i;//m_linkedactuators.at(i);
+ logicmgr->AddActiveActuator(actua,newevent);
+ }
+
+
+ newevent->Release();
+}
+
+/* ------------------------------------------------------------------------- */
+/* Python functions */
+/* ------------------------------------------------------------------------- */
+
+/* Integration hooks ------------------------------------------------------- */
+PyTypeObject SCA_ORController::Type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0,
+ "SCA_ORController",
+ sizeof(SCA_ORController),
+ 0,
+ PyDestructor,
+ 0,
+ __getattr,
+ __setattr,
+ 0, //&MyPyCompare,
+ __repr,
+ 0, //&cvalue_as_number,
+ 0,
+ 0,
+ 0,
+ 0
+};
+
+PyParentObject SCA_ORController::Parents[] = {
+ &SCA_ORController::Type,
+ &SCA_IController::Type,
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
+};
+
+PyMethodDef SCA_ORController::Methods[] = {
+ {NULL,NULL} //Sentinel
+};
+
+PyObject* SCA_ORController::_getattr(char* attr) {
+ _getattr_up(SCA_IController);
+}
+
+/* eof */
diff --git a/source/gameengine/GameLogic/SCA_ORController.h b/source/gameengine/GameLogic/SCA_ORController.h
new file mode 100644
index 00000000000..89dab8731ca
--- /dev/null
+++ b/source/gameengine/GameLogic/SCA_ORController.h
@@ -0,0 +1,58 @@
+/**
+ * SCA_ORController.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 __KX_ORCONTROLLER
+#define __KX_ORCONTROLLER
+
+#include "SCA_IController.h"
+
+class SCA_ORController : public SCA_IController
+{
+ Py_Header;
+ //virtual void Trigger(class SCA_LogicManager* logicmgr);
+public:
+ SCA_ORController(SCA_IObject* gameobj, PyTypeObject* T=&Type);
+
+ virtual ~SCA_ORController();
+ virtual CValue* GetReplica();
+ virtual void Trigger(SCA_LogicManager* logicmgr);
+
+ /* --------------------------------------------------------------------- */
+ /* Python interface ---------------------------------------------------- */
+ /* --------------------------------------------------------------------- */
+
+ virtual PyObject* _getattr(char *attr);
+};
+
+#endif //__KX_ORCONTROLLER
diff --git a/source/gameengine/GameLogic/SCA_PropertyActuator.cpp b/source/gameengine/GameLogic/SCA_PropertyActuator.cpp
new file mode 100644
index 00000000000..893db892ef0
--- /dev/null
+++ b/source/gameengine/GameLogic/SCA_PropertyActuator.cpp
@@ -0,0 +1,285 @@
+/**
+ * Assign, change, copy properties
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "SCA_PropertyActuator.h"
+#include "InputParser.h"
+
+#include "Operator2Expr.h"
+#include "ConstExpr.h"
+
+/* ------------------------------------------------------------------------- */
+/* Native functions */
+/* ------------------------------------------------------------------------- */
+
+SCA_PropertyActuator::SCA_PropertyActuator(SCA_IObject* gameobj,CValue* sourceObj,const STR_String& propname,const STR_String& expr,int acttype,PyTypeObject* T )
+: SCA_IActuator(gameobj,T),
+m_propname(propname),
+m_exprtxt(expr),
+m_type(acttype),
+m_sourceObj(sourceObj)
+{
+}
+
+SCA_PropertyActuator::~SCA_PropertyActuator()
+{
+}
+
+bool SCA_PropertyActuator::Update(double curtime,double deltatime)
+{
+ bool result = false;
+
+ bool bNegativeEvent = IsNegativeEvent();
+ RemoveAllEvents();
+
+
+ if (bNegativeEvent)
+ return false; // do nothing on negative events
+
+
+ CValue* propowner = GetParent();
+ CParser parser;
+ parser.SetContext( propowner->AddRef());
+
+ CExpression* userexpr = parser.ProcessText(m_exprtxt);
+ if (userexpr)
+ {
+
+
+ switch (m_type)
+ {
+
+ case KX_ACT_PROP_ASSIGN:
+ {
+
+ CValue* newval = userexpr->Calculate();
+ CValue* oldprop = propowner->GetProperty(m_propname);
+ if (oldprop)
+ {
+ oldprop->SetValue(newval);
+ newval->Release();
+ } else
+ {
+ propowner->SetProperty(m_propname,newval);
+ }
+
+ break;
+ }
+ case KX_ACT_PROP_ADD:
+ {
+ CValue* oldprop = propowner->GetProperty(m_propname);
+ if (oldprop)
+ {
+ int waarde = (int)oldprop->GetNumber();
+ CExpression* expr = new COperator2Expr(VALUE_ADD_OPERATOR,new CConstExpr(oldprop->AddRef()),
+ userexpr->AddRef());
+
+ CValue* newprop = expr->Calculate();
+ oldprop->SetValue(newprop);
+ newprop->Release();
+ expr->Release();
+
+ }
+
+ break;
+ }
+ case KX_ACT_PROP_COPY:
+ {
+ if (m_sourceObj)
+ {
+ CValue* copyprop = m_sourceObj->GetProperty(m_exprtxt);
+ if (copyprop)
+ {
+ GetParent()->SetProperty(
+ m_propname,
+ copyprop->GetReplica());
+
+ }
+ }
+ break;
+ }
+ default:
+ {
+
+ }
+ }
+
+ userexpr->Release();
+ }
+
+ return result;
+}
+
+ bool
+
+SCA_PropertyActuator::
+
+isValid(
+
+ SCA_PropertyActuator::KX_ACT_PROP_MODE mode
+
+){
+ bool res = false;
+ res = ((mode > KX_ACT_PROP_NODEF) && (mode < KX_ACT_PROP_MAX));
+ return res;
+}
+
+
+ CValue*
+
+SCA_PropertyActuator::
+
+GetReplica() {
+
+ SCA_PropertyActuator* replica = new SCA_PropertyActuator(*this);
+
+ replica->ProcessReplica();
+
+ // this will copy properties and so on...
+
+ CValue::AddDataToReplica(replica);
+
+ return replica;
+
+};
+
+
+
+
+/* ------------------------------------------------------------------------- */
+/* Python functions */
+/* ------------------------------------------------------------------------- */
+
+/* Integration hooks ------------------------------------------------------- */
+PyTypeObject SCA_PropertyActuator::Type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0,
+ "SCA_PropertyActuator",
+ sizeof(SCA_PropertyActuator),
+ 0,
+ PyDestructor,
+ 0,
+ __getattr,
+ __setattr,
+ 0, //&MyPyCompare,
+ __repr,
+ 0, //&cvalue_as_number,
+ 0,
+ 0,
+ 0,
+ 0
+};
+
+PyParentObject SCA_PropertyActuator::Parents[] = {
+ &SCA_PropertyActuator::Type,
+ &SCA_IActuator::Type,
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
+};
+
+PyMethodDef SCA_PropertyActuator::Methods[] = {
+ {"setProperty", (PyCFunction) SCA_PropertyActuator::sPySetProperty, METH_VARARGS, SetProperty_doc},
+ {"getProperty", (PyCFunction) SCA_PropertyActuator::sPyGetProperty, METH_VARARGS, GetProperty_doc},
+ {"setValue", (PyCFunction) SCA_PropertyActuator::sPySetValue, METH_VARARGS, SetValue_doc},
+ {"getValue", (PyCFunction) SCA_PropertyActuator::sPyGetValue, METH_VARARGS, GetValue_doc},
+ {NULL,NULL} //Sentinel
+};
+
+PyObject* SCA_PropertyActuator::_getattr(char* attr) {
+ _getattr_up(SCA_IActuator);
+}
+
+/* 1. setProperty */
+char SCA_PropertyActuator::SetProperty_doc[] =
+"setProperty(name)\n"
+"\t- name: string\n"
+"\tSet the property on which to operate. If there is no property\n"
+"\tof this name, the call is ignored.\n";
+PyObject* SCA_PropertyActuator::PySetProperty(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ /* Check whether the name exists first ! */
+ char *nameArg;
+ if (!PyArg_ParseTuple(args, "s", &nameArg)) {
+ return NULL;
+ }
+
+ CValue* prop = GetParent()->FindIdentifier(nameArg);
+
+ if (prop) {
+ m_propname = nameArg;
+ } else {
+ ; /* not found ... */
+ }
+
+ Py_Return;
+}
+
+/* 2. getProperty */
+char SCA_PropertyActuator::GetProperty_doc[] =
+"getProperty(name)\n"
+"\tReturn the property on which the actuator operates.\n";
+PyObject* SCA_PropertyActuator::PyGetProperty(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ return PyString_FromString(m_propname);
+}
+
+/* 3. setValue */
+char SCA_PropertyActuator::SetValue_doc[] =
+"setValue(value)\n"
+"\t- value: string\n"
+"\tSet the value with which the actuator operates. If the value\n"
+"\tis not compatible with the type of the property, the subsequent\n"
+"\t action is ignored.\n";
+PyObject* SCA_PropertyActuator::PySetValue(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ char *valArg;
+ if(!PyArg_ParseTuple(args, "s", &valArg)) {
+ return NULL;
+ }
+
+ if (valArg) m_exprtxt = valArg;
+
+ Py_Return;
+}
+
+/* 4. getValue */
+char SCA_PropertyActuator::GetValue_doc[] =
+"getValue()\n"
+"\tReturns the value with which the actuator operates.\n";
+PyObject* SCA_PropertyActuator::PyGetValue(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ return PyString_FromString(m_exprtxt);
+}
+
+/* eof */
diff --git a/source/gameengine/GameLogic/SCA_PropertyActuator.h b/source/gameengine/GameLogic/SCA_PropertyActuator.h
new file mode 100644
index 00000000000..7d09a8683cf
--- /dev/null
+++ b/source/gameengine/GameLogic/SCA_PropertyActuator.h
@@ -0,0 +1,116 @@
+/**
+ * SCA_PropertyActuator.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 __KX_PROPERTYACTUATOR
+#define __KX_PROPERTYACTUATOR
+
+#include "SCA_IActuator.h"
+
+class SCA_PropertyActuator : public SCA_IActuator
+{
+ Py_Header;
+
+ enum KX_ACT_PROP_MODE {
+ KX_ACT_PROP_NODEF = 0,
+ KX_ACT_PROP_ASSIGN,
+ KX_ACT_PROP_ADD,
+ KX_ACT_PROP_COPY,
+ KX_ACT_PROP_MAX
+ };
+
+ /**check whether this value is valid */
+ bool isValid(KX_ACT_PROP_MODE mode);
+
+ int m_type;
+ STR_String m_propname;
+ STR_String m_exprtxt;
+ CValue* m_sourceObj; // for copy property actuator
+
+public:
+
+
+
+ SCA_PropertyActuator(
+
+ SCA_IObject* gameobj,
+
+ CValue* sourceObj,
+
+ const STR_String& propname,
+
+ const STR_String& expr,
+
+ int acttype,
+
+ PyTypeObject* T=&Type
+
+ );
+
+
+ ~SCA_PropertyActuator();
+
+
+ CValue*
+
+ GetReplica(
+
+ );
+
+
+ bool
+
+ Update(
+
+ double curtime,
+
+ double deltatime
+
+ );
+
+ /* --------------------------------------------------------------------- */
+ /* Python interface ---------------------------------------------------- */
+ /* --------------------------------------------------------------------- */
+
+ PyObject* _getattr(char *attr);
+
+ // python wrapped methods
+ KX_PYMETHOD_DOC(SCA_PropertyActuator,SetProperty);
+ KX_PYMETHOD_DOC(SCA_PropertyActuator,GetProperty);
+ KX_PYMETHOD_DOC(SCA_PropertyActuator,SetValue);
+ KX_PYMETHOD_DOC(SCA_PropertyActuator,GetValue);
+
+ /* 5. - ... setObject, getObject, setProp2, getProp2, setMode, getMode*/
+
+};
+#endif //__KX_PROPERTYACTUATOR_DOC
diff --git a/source/gameengine/GameLogic/SCA_PropertyEventManager.cpp b/source/gameengine/GameLogic/SCA_PropertyEventManager.cpp
new file mode 100644
index 00000000000..2b3ad1d2c1c
--- /dev/null
+++ b/source/gameengine/GameLogic/SCA_PropertyEventManager.cpp
@@ -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 *****
+ */
+
+#include "SCA_ISensor.h"
+
+#include "SCA_PropertyEventManager.h"
+
+
+
+SCA_PropertyEventManager::SCA_PropertyEventManager(class SCA_LogicManager* logicmgr)
+ : SCA_EventManager(PROPERTY_EVENTMGR),
+ m_logicmgr(logicmgr)
+{
+}
+
+
+
+SCA_PropertyEventManager::~SCA_PropertyEventManager()
+{
+
+}
+
+
+
+void SCA_PropertyEventManager::RegisterSensor(SCA_ISensor* sensor)
+{
+ m_sensors.push_back(sensor);
+}
+
+
+
+void SCA_PropertyEventManager::NextFrame(double curtime,double deltatime)
+{
+ // check for changed properties
+ for (vector<SCA_ISensor*>::const_iterator it = m_sensors.begin();!(it==m_sensors.end());it++)
+ {
+ (*it)->Activate(m_logicmgr,NULL);
+ }
+}
diff --git a/source/gameengine/GameLogic/SCA_PropertyEventManager.h b/source/gameengine/GameLogic/SCA_PropertyEventManager.h
new file mode 100644
index 00000000000..db203b7d92b
--- /dev/null
+++ b/source/gameengine/GameLogic/SCA_PropertyEventManager.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 *****
+ */
+#ifndef __KX_PROPERTYEVENTMANAGER
+#define __KX_PROPERTYEVENTMANAGER
+
+#include "SCA_EventManager.h"
+
+#include <vector>
+using namespace std;
+
+
+class SCA_PropertyEventManager : public SCA_EventManager
+{
+ class SCA_LogicManager* m_logicmgr;
+
+public:
+ SCA_PropertyEventManager(class SCA_LogicManager* logicmgr);
+ virtual ~SCA_PropertyEventManager();
+ virtual void NextFrame(double curtime,double deltatime);
+ virtual void RegisterSensor(SCA_ISensor* sensor);
+ //SCA_LogicManager* GetLogicManager() { return m_logicmgr;}
+};
+#endif //__KX_PROPERTYEVENTMANAGER
diff --git a/source/gameengine/GameLogic/SCA_PropertySensor.cpp b/source/gameengine/GameLogic/SCA_PropertySensor.cpp
new file mode 100644
index 00000000000..52642c6757f
--- /dev/null
+++ b/source/gameengine/GameLogic/SCA_PropertySensor.cpp
@@ -0,0 +1,420 @@
+/**
+ * Property sensor
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 <iostream>
+#include "SCA_PropertySensor.h"
+#include "Operator2Expr.h"
+#include "ConstExpr.h"
+#include "InputParser.h"
+#include "StringValue.h"
+#include "SCA_EventManager.h"
+#include "SCA_LogicManager.h"
+
+SCA_PropertySensor::SCA_PropertySensor(SCA_EventManager* eventmgr,
+ SCA_IObject* gameobj,
+ const STR_String& propname,
+ const STR_String& propval,
+ const STR_String& propmaxval,
+ KX_PROPSENSOR_TYPE checktype,
+ PyTypeObject* T )
+ : SCA_ISensor(gameobj,eventmgr,T),
+ m_checkpropname(propname),
+ m_checkpropval(propval),
+ m_checkpropmaxval(propmaxval),
+ m_checktype(checktype),
+ m_range_expr(NULL),
+ m_lastresult(false)
+{
+ m_recentresult=false;
+ //CParser pars;
+ //pars.SetContext(this->AddRef());
+ //CValue* resultval = m_rightexpr->Calculate();
+
+ CValue* orgprop = GetParent()->FindIdentifier(m_checkpropname);
+ if (orgprop)
+ {
+ m_previoustext = orgprop->GetText();
+ orgprop->Release();
+ }
+
+ if (m_checktype==KX_PROPSENSOR_INTERVAL)
+ {
+ PrecalculateRangeExpression();
+ }
+
+}
+
+void SCA_PropertySensor::PrecalculateRangeExpression()
+{
+ CParser pars;
+ pars.SetContext(this->AddRef());
+ STR_String checkstr = "(" + m_checkpropval + " <= "
+ + m_checkpropname + ") && ( "
+ + m_checkpropname + " <= "
+ + m_checkpropmaxval;
+
+ m_range_expr = pars.ProcessText(checkstr);
+}
+
+
+
+CValue* SCA_PropertySensor::GetReplica()
+{
+ SCA_PropertySensor* replica = new SCA_PropertySensor(*this);
+ // m_range_expr must be recalculated on replica!
+ CValue::AddDataToReplica(replica);
+
+ replica->m_range_expr = NULL;
+ if (replica->m_checktype==KX_PROPSENSOR_INTERVAL)
+ {
+ replica->PrecalculateRangeExpression();
+ }
+
+
+ return replica;
+}
+
+
+
+bool SCA_PropertySensor::IsPositiveTrigger()
+{
+ bool result = m_recentresult;//CheckPropertyCondition();
+ if (m_invert)
+ result = !result;
+
+ return result;
+}
+
+
+
+SCA_PropertySensor::~SCA_PropertySensor()
+{
+ //if (m_rightexpr)
+ // m_rightexpr->Release();
+
+ if (m_range_expr)
+ {
+ m_range_expr->Release();
+ m_range_expr=NULL;
+ }
+
+}
+
+
+
+bool SCA_PropertySensor::Evaluate(CValue* event)
+{
+ bool result = CheckPropertyCondition();
+
+ if (m_lastresult!=result)
+ {
+ m_lastresult = result;
+ return true;
+ }
+
+ return false;
+}
+
+
+bool SCA_PropertySensor::CheckPropertyCondition()
+{
+
+ m_recentresult=false;
+ bool result=false;
+ bool reverse = false;
+ switch (m_checktype)
+ {
+ case KX_PROPSENSOR_NOTEQUAL:
+ reverse = true;
+ case KX_PROPSENSOR_EQUAL:
+ {
+ CValue* orgprop = GetParent()->FindIdentifier(m_checkpropname);
+ if (orgprop)
+ {
+ STR_String testprop = orgprop->GetText();
+ // Force strings to upper case, to avoid confusion in
+ // bool tests. It's stupid the prop's identity is lost
+ // on the way here...
+ if ((testprop == "TRUE") || (testprop == "FALSE")) {
+ STR_String checkprop = m_checkpropval;
+ checkprop.Upper();
+ result = (testprop == checkprop);
+ } else {
+ result = (orgprop->GetText() == m_checkpropval);
+ }
+ orgprop->Release();
+
+ }
+
+ if (reverse)
+ result = !result;
+ break;
+
+ }
+
+ case KX_PROPSENSOR_EXPRESSION:
+ {
+ /*
+ if (m_rightexpr)
+ {
+ CValue* resultval = m_rightexpr->Calculate();
+ if (resultval->IsError())
+ {
+ int i=0;
+ STR_String errortest = resultval->GetText();
+ printf(errortest);
+
+ } else
+ {
+ result = resultval->GetNumber() != 0;
+ }
+ }
+ */
+ break;
+ }
+ case KX_PROPSENSOR_INTERVAL:
+ {
+ //CValue* orgprop = GetParent()->FindIdentifier(m_checkpropname);
+ //if (orgprop)
+ //{
+ if (m_range_expr)
+ {
+ CValue* vallie = m_range_expr->Calculate();
+ if (vallie)
+ {
+ STR_String errtext = vallie->GetText();
+ if (errtext == "TRUE")
+ {
+ result = true;
+ } else
+ {
+ if (vallie->IsError())
+ {
+ //printf (errtext.ReadPtr());
+ }
+ }
+
+ vallie->Release();
+ }
+ }
+
+
+ //}
+
+ //cout << " \nSens:Prop:interval!"; /* need implementation here!!! */
+
+ break;
+ }
+ case KX_PROPSENSOR_CHANGED:
+ {
+ CValue* orgprop = GetParent()->FindIdentifier(m_checkpropname);
+
+ if (orgprop)
+ {
+ if (m_previoustext != orgprop->GetText())
+ {
+ m_previoustext = orgprop->GetText();
+ result = true;
+ }
+ orgprop->Release();
+ }
+
+ //cout << " \nSens:Prop:changed!"; /* need implementation here!!! */
+ break;
+ }
+ default:
+ ; /* error */
+ }
+ m_recentresult=result;
+ return result;
+}
+
+CValue* SCA_PropertySensor::FindIdentifier(const STR_String& identifiername)
+{
+ return GetParent()->FindIdentifier(identifiername);
+}
+
+bool SCA_PropertySensor::validValueForProperty(char *val, STR_String &prop)
+{
+ bool result = true;
+ /* There is no type checking at this moment, unfortunately... */
+ return result;
+}
+
+/* ------------------------------------------------------------------------- */
+/* Python functions */
+/* ------------------------------------------------------------------------- */
+
+/* Integration hooks ------------------------------------------------------- */
+PyTypeObject SCA_PropertySensor::Type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0,
+ "SCA_PropertySensor",
+ sizeof(SCA_PropertySensor),
+ 0,
+ PyDestructor,
+ 0,
+ __getattr,
+ __setattr,
+ 0, //&MyPyCompare,
+ __repr,
+ 0, //&cvalue_as_number,
+ 0,
+ 0,
+ 0,
+ 0
+};
+
+PyParentObject SCA_PropertySensor::Parents[] = {
+ &SCA_PropertySensor::Type,
+ &SCA_ISensor::Type,
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
+};
+
+PyMethodDef SCA_PropertySensor::Methods[] = {
+ {"getType", (PyCFunction) SCA_PropertySensor::sPyGetType, METH_VARARGS, GetType_doc},
+ {"setType", (PyCFunction) SCA_PropertySensor::sPySetType, METH_VARARGS, SetType_doc},
+ {"getProperty", (PyCFunction) SCA_PropertySensor::sPyGetProperty, METH_VARARGS, GetProperty_doc},
+ {"setProperty", (PyCFunction) SCA_PropertySensor::sPySetProperty, METH_VARARGS, SetProperty_doc},
+ {"getValue", (PyCFunction) SCA_PropertySensor::sPyGetValue, METH_VARARGS, GetValue_doc},
+ {"setValue", (PyCFunction) SCA_PropertySensor::sPySetValue, METH_VARARGS, SetValue_doc},
+ {NULL,NULL} //Sentinel
+};
+
+PyObject* SCA_PropertySensor::_getattr(char* attr) {
+ _getattr_up(SCA_ISensor); /* implicit return! */
+}
+
+/* 1. getType */
+char SCA_PropertySensor::GetType_doc[] =
+"getType()\n"
+"\tReturns the type of check this sensor performs.\n";
+PyObject* SCA_PropertySensor::PyGetType(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ return PyInt_FromLong(m_checktype);
+}
+
+/* 2. setType */
+char SCA_PropertySensor::SetType_doc[] =
+"setType(type)\n"
+"\t- type: KX_PROPSENSOR_EQUAL, KX_PROPSENSOR_NOTEQUAL,\n"
+"\t KX_PROPSENSOR_INTERVAL, KX_PROPSENSOR_CHANGED,\n"
+"\t or KX_PROPSENSOR_EXPRESSION.\n"
+"\tSet the type of check to perform.\n";
+PyObject* SCA_PropertySensor::PySetType(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ int typeArg;
+
+ if (!PyArg_ParseTuple(args, "i", &typeArg)) {
+ return NULL;
+ }
+
+ if ( (typeArg > KX_PROPSENSOR_NODEF)
+ && (typeArg < KX_PROPSENSOR_MAX) ) {
+ m_checktype = typeArg;
+ }
+
+ Py_Return;
+}
+
+/* 3. getProperty */
+char SCA_PropertySensor::GetProperty_doc[] =
+"getProperty()\n"
+"\tReturn the property with which the sensor operates.\n";
+PyObject* SCA_PropertySensor::PyGetProperty(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ return PyString_FromString(m_checkpropname);
+}
+
+/* 4. setProperty */
+char SCA_PropertySensor::SetProperty_doc[] =
+"setProperty(name)\n"
+"\t- name: string\n"
+"\tSets the property with which to operate. If there is no property\n"
+"\tof this name, the call is ignored.\n";
+PyObject* SCA_PropertySensor::PySetProperty(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ /* We should query whether the name exists. Or should we create a prop */
+ /* on the fly? */
+ char *propNameArg = NULL;
+
+ if (!PyArg_ParseTuple(args, "s", &propNameArg)) {
+ return NULL;
+ }
+
+ if (FindIdentifier(STR_String(propNameArg))) {
+ m_checkpropname = propNameArg;
+ } else {
+ ; /* error: bad property name */
+ }
+
+ Py_Return;
+}
+
+/* 5. getValue */
+char SCA_PropertySensor::GetValue_doc[] =
+"getValue()\n"
+"\tReturns the value with which the sensor operates.\n";
+PyObject* SCA_PropertySensor::PyGetValue(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ return PyString_FromString(m_checkpropval);
+}
+
+/* 6. setValue */
+char SCA_PropertySensor::SetValue_doc[] =
+"setValue(value)\n"
+"\t- value: string\n"
+"\tSet the value with which the sensor operates. If the value\n"
+"\tis not compatible with the type of the property, the subsequent\n"
+"\t action is ignored.\n";
+PyObject* SCA_PropertySensor::PySetValue(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ /* Here, we need to check whether the value is 'valid' for this property.*/
+ /* We know that the property exists, or is NULL. */
+ char *propValArg = NULL;
+
+ if(!PyArg_ParseTuple(args, "s", &propValArg)) {
+ return NULL;
+ }
+
+ if (validValueForProperty(propValArg, m_checkpropname)) {
+ m_checkpropval = propValArg;
+ }
+
+ Py_Return;
+}
+
+/* eof */
diff --git a/source/gameengine/GameLogic/SCA_PropertySensor.h b/source/gameengine/GameLogic/SCA_PropertySensor.h
new file mode 100644
index 00000000000..89debebda3d
--- /dev/null
+++ b/source/gameengine/GameLogic/SCA_PropertySensor.h
@@ -0,0 +1,109 @@
+/**
+ * Property sensor
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 __KX_PROPERTYSENSOR
+#define __KX_PROPERTYSENSOR
+
+#include "SCA_ISensor.h"
+
+class SCA_PropertySensor : public SCA_ISensor
+{
+ Py_Header;
+ //class CExpression* m_rightexpr;
+ int m_checktype;
+ STR_String m_checkpropval;
+ STR_String m_checkpropmaxval;
+ STR_String m_checkpropname;
+ STR_String m_previoustext;
+ bool m_lastresult;
+ bool m_recentresult;
+ CExpression* m_range_expr;
+
+ /**
+ * Test whether this is a sensible value (type check)
+ */
+ bool validValueForProperty(char *val, STR_String &prop);
+ protected:
+
+public:
+ enum KX_PROPSENSOR_TYPE {
+ KX_PROPSENSOR_NODEF = 0,
+ KX_PROPSENSOR_EQUAL,
+ KX_PROPSENSOR_NOTEQUAL,
+ KX_PROPSENSOR_INTERVAL,
+ KX_PROPSENSOR_CHANGED,
+ KX_PROPSENSOR_EXPRESSION,
+ KX_PROPSENSOR_MAX
+ };
+
+ const STR_String S_KX_PROPSENSOR_EQ_STRING;
+
+ SCA_PropertySensor(class SCA_EventManager* eventmgr,
+ SCA_IObject* gameobj,
+ const STR_String& propname,
+ const STR_String& propval,
+ const STR_String& propmaxval,
+ KX_PROPSENSOR_TYPE checktype,
+ PyTypeObject* T=&Type );
+
+ virtual ~SCA_PropertySensor();
+ virtual CValue* GetReplica();
+ void PrecalculateRangeExpression();
+ bool CheckPropertyCondition();
+
+ virtual bool Evaluate(CValue* event);
+ virtual bool IsPositiveTrigger();
+ virtual CValue* FindIdentifier(const STR_String& identifiername);
+
+ /* --------------------------------------------------------------------- */
+ /* Python interface ---------------------------------------------------- */
+ /* --------------------------------------------------------------------- */
+
+ virtual PyObject* _getattr(char *attr);
+
+ /* 1. getType */
+ KX_PYMETHOD_DOC(SCA_PropertySensor,GetType);
+ /* 2. setType */
+ KX_PYMETHOD_DOC(SCA_PropertySensor,SetType);
+ /* 3. setProperty */
+ KX_PYMETHOD_DOC(SCA_PropertySensor,SetProperty);
+ /* 4. getProperty */
+ KX_PYMETHOD_DOC(SCA_PropertySensor,GetProperty);
+ /* 5. getValue */
+ KX_PYMETHOD_DOC(SCA_PropertySensor,GetValue);
+ /* 6. setValue */
+ KX_PYMETHOD_DOC(SCA_PropertySensor,SetValue);
+
+};
+#endif
diff --git a/source/gameengine/GameLogic/SCA_PythonController.cpp b/source/gameengine/GameLogic/SCA_PythonController.cpp
new file mode 100644
index 00000000000..2d57a5f116d
--- /dev/null
+++ b/source/gameengine/GameLogic/SCA_PythonController.cpp
@@ -0,0 +1,400 @@
+/**
+ * Execute Python scripts
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "SCA_PythonController.h"
+#include "SCA_LogicManager.h"
+#include "SCA_ISensor.h"
+#include "SCA_IActuator.h"
+#include "compile.h"
+#include "eval.h"
+
+
+// initialize static member variables
+SCA_PythonController* SCA_PythonController::m_sCurrentController = NULL;
+
+
+SCA_PythonController::SCA_PythonController(SCA_IObject* gameobj,
+ PyTypeObject* T)
+ : SCA_IController(gameobj, T),
+ m_pythondictionary(NULL),
+ m_bytecode(NULL),
+ m_bModified(true)
+{
+}
+
+
+
+SCA_PythonController::~SCA_PythonController()
+{
+ if (m_bytecode)
+ {
+ //
+ //printf("released python byte script\n");
+ Py_DECREF(m_bytecode);
+ }
+}
+
+
+
+CValue* SCA_PythonController::GetReplica()
+{
+ SCA_PythonController* replica = new SCA_PythonController(*this);
+ replica->m_bytecode = NULL;
+ replica->m_bModified = true;
+ // this will copy properties and so on...
+ CValue::AddDataToReplica(replica);
+
+ return replica;
+}
+
+
+
+void SCA_PythonController::SetScriptText(const STR_String& text)
+{
+ m_scriptText = text;
+ m_bModified = true;
+}
+
+
+
+void SCA_PythonController::SetScriptName(const STR_String& name)
+{
+ m_scriptName = name;
+}
+
+
+
+void SCA_PythonController::SetDictionary(PyObject* pythondictionary)
+{
+ m_pythondictionary = pythondictionary;
+}
+
+
+static char* sPyGetCurrentController__doc__;
+
+
+PyObject* SCA_PythonController::sPyGetCurrentController(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ m_sCurrentController->AddRef();
+ return m_sCurrentController;
+}
+
+
+static char* sPyAddActiveActuator__doc__;
+
+
+PyObject* SCA_PythonController::sPyAddActiveActuator(
+
+ PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+
+ PyObject* ob1;
+ int activate;
+ if (!PyArg_ParseTuple(args, "Oi", &ob1,&activate))
+ {
+ return NULL;
+
+ }
+ // for safety, todo: only allow for registered actuators (pointertable)
+ // we don't want to crash gameengine/blender by python scripts
+
+ CValue* ac = (CValue*)ob1;
+ CValue* boolval = new CBoolValue(activate!=0);
+ m_sCurrentLogicManager->AddActiveActuator((SCA_IActuator*)ac,boolval);
+ boolval->Release();
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+
+char* SCA_PythonController::sPyGetCurrentController__doc__ = "getCurrentController()";
+char* SCA_PythonController::sPyAddActiveActuator__doc__= "addActiveActuator(actuator,bool)";
+char SCA_PythonController::GetActuators_doc[] = "getActuator";
+
+PyTypeObject SCA_PythonController::Type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0,
+ "SCA_PythonController",
+ sizeof(SCA_PythonController),
+ 0,
+ PyDestructor,
+ 0,
+ __getattr,
+ __setattr,
+ 0, //&MyPyCompare,
+ __repr,
+ 0, //&cvalue_as_number,
+ 0,
+ 0,
+ 0,
+ 0
+};
+
+PyParentObject SCA_PythonController::Parents[] = {
+ &SCA_PythonController::Type,
+ &SCA_IController::Type,
+ &CValue::Type,
+ NULL
+};
+PyMethodDef SCA_PythonController::Methods[] = {
+ {"getActuators", (PyCFunction) SCA_PythonController::sPyGetActuators,
+ METH_VARARGS, SCA_PythonController::GetActuators_doc},
+ {"getActuator", (PyCFunction) SCA_PythonController::sPyGetActuator,
+ METH_VARARGS, SCA_PythonController::GetActuator_doc},
+ {"getSensors", (PyCFunction) SCA_PythonController::sPyGetSensors,
+ METH_VARARGS, SCA_PythonController::GetSensors_doc},
+ {"getSensor", (PyCFunction) SCA_PythonController::sPyGetSensor,
+ METH_VARARGS, SCA_PythonController::GetSensor_doc}
+ ,
+ {NULL,NULL} //Sentinel
+};
+
+
+
+ /* XXX, function should be removed and PyDict_Copy used
+ * once we switch to all builds using Python 2.0 - zr */
+static PyObject *myPyDict_Copy(PyObject *odict)
+{
+ PyObject *ndict= PyDict_New();
+ PyObject *key, *val;
+ int ppos= 0;
+
+ while (PyDict_Next(odict, &ppos, &key, &val))
+ PyDict_SetItem(ndict, key, val);
+
+ return ndict;
+}
+
+void SCA_PythonController::Trigger(SCA_LogicManager* logicmgr)
+{
+ m_sCurrentController = this;
+ m_sCurrentLogicManager = logicmgr;
+
+ if (m_bModified)
+ {
+ // if a script already exists, decref it before replace the pointer to a new script
+ if (m_bytecode)
+ {
+ Py_DECREF(m_bytecode);
+ m_bytecode=NULL;
+ }
+ // recompile the scripttext into bytecode
+ m_bytecode = Py_CompileString(m_scriptText.Ptr(), m_scriptName.Ptr(), Py_file_input);
+ if (m_bytecode)
+ {
+ // store the
+ int i=0;
+ i+=2; // so compiler doesn't complain about unused variable
+ PyRun_SimpleString("import GameLogic\n");
+ } else
+ {
+ // didn't compile, so instead of compile, complain
+ int i=0;
+ i++; // so compiler doesn't complain about unused variable
+ }
+ m_bModified=false;
+ }
+
+ /*
+ * This part here with excdict is a temporary patch
+ * to avoid python/gameengine crashes when python
+ * inadvertently holds references to game objects
+ * in global variables.
+ *
+ * The idea is always make a fresh dictionary, and
+ * destroy it right after it is used to make sure
+ * python won't hold any gameobject references.
+ *
+ * Note that the PyDict_Clear _is_ necessary before
+ * the Py_DECREF() because it is possible for the
+ * variables inside the dictionary to hold references
+ * to the dictionary (ie. generate a cycle), so we
+ * break it by hand, then DECREF (which in this case
+ * should always ensure excdict is cleared).
+ */
+ PyObject *excdict= myPyDict_Copy(m_pythondictionary);
+ struct _object* resultobj = PyEval_EvalCode((PyCodeObject*)m_bytecode,
+ excdict,
+ excdict
+ );
+ PyDict_Clear(excdict);
+ Py_DECREF(excdict);
+
+ if (resultobj)
+ {
+ Py_DECREF(resultobj);
+ } else
+ {
+ // something is wrong, tell the user what went wrong
+ printf("PYTHON SCRIPT ERROR:\n");
+ PyRun_SimpleString(m_scriptText.Ptr());
+ }
+
+ m_sCurrentController = NULL;
+}
+
+
+
+PyObject* SCA_PythonController::_getattr(char* attr)
+{
+ _getattr_up(SCA_IController);
+}
+
+
+
+PyObject* SCA_PythonController::PyGetActuators(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ int index;
+
+ PyObject* resultlist = PyList_New(m_linkedactuators.size());
+ for (index=0;index<m_linkedactuators.size();index++)
+ {
+ PyList_SetItem(resultlist,index,m_linkedactuators[index]->AddRef());
+ }
+
+ return resultlist;
+}
+
+char SCA_PythonController::GetSensor_doc[] =
+"GetSensor (char sensorname) return linked sensor that is named [sensorname]\n";
+PyObject*
+SCA_PythonController::PyGetSensor(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+
+ char *scriptArg;
+
+ if (!PyArg_ParseTuple(args, "s", &scriptArg)) {
+ return NULL;
+ }
+
+ int index;
+ for (index=0;index<m_linkedsensors.size();index++)
+ {
+ SCA_ISensor* sensor = m_linkedsensors[index];
+ STR_String realname = sensor->GetName();
+ if (realname == scriptArg)
+ {
+ return sensor->AddRef();
+ }
+ }
+
+ PyErr_SetString(PyExc_AttributeError, "Unable to find requested sensor");
+ return NULL;
+}
+
+
+
+char SCA_PythonController::GetActuator_doc[] =
+"GetActuator (char sensorname) return linked actuator that is named [actuatorname]\n";
+PyObject*
+SCA_PythonController::PyGetActuator(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+
+ char *scriptArg;
+
+ if (!PyArg_ParseTuple(args, "s", &scriptArg)) {
+ return NULL;
+ }
+
+ int index;
+ for (index=0;index<m_linkedactuators.size();index++)
+ {
+ SCA_IActuator* actua = m_linkedactuators[index];
+ STR_String realname = actua->GetName();
+ if (realname == scriptArg)
+ {
+ return actua->AddRef();
+ }
+ }
+
+ PyErr_SetString(PyExc_AttributeError, "Unable to find requested actuator");
+ return NULL;
+}
+
+
+char SCA_PythonController::GetSensors_doc[] = "getSensors returns a list of all attached sensors";
+PyObject*
+SCA_PythonController::PyGetSensors(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ int index;
+
+ PyObject* resultlist = PyList_New(m_linkedsensors.size());
+ for (index=0;index<m_linkedsensors.size();index++)
+ {
+ PyList_SetItem(resultlist,index,m_linkedsensors[index]->AddRef());
+ }
+
+ return resultlist;
+}
+
+/* 1. getScript */
+PyObject* SCA_PythonController::PyGetScript(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ return PyString_FromString(m_scriptText);
+}
+
+/* 2. setScript */
+PyObject* SCA_PythonController::PySetScript(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ char *scriptArg;
+ if (!PyArg_ParseTuple(args, "s", &scriptArg)) {
+ return NULL;
+ }
+
+ /* set scripttext sets m_bModified to true,
+ so next time the script is needed, a reparse into byte code is done */
+
+ this->SetScriptText(scriptArg);
+
+ Py_Return;
+}
+
+/* eof */
diff --git a/source/gameengine/GameLogic/SCA_PythonController.h b/source/gameengine/GameLogic/SCA_PythonController.h
new file mode 100644
index 00000000000..f19fcac72f3
--- /dev/null
+++ b/source/gameengine/GameLogic/SCA_PythonController.h
@@ -0,0 +1,88 @@
+/**
+ * Execute Python scripts
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 KX_PYTHONCONTROLLER_H
+#define KX_PYTHONCONTROLLER_H
+
+#include "SCA_IController.h"
+#include "SCA_LogicManager.h"
+#include "BoolValue.h"
+
+class SCA_IObject;
+class SCA_PythonController : public SCA_IController
+{
+ Py_Header;
+ struct _object * m_bytecode;
+ bool m_bModified;
+
+ protected:
+ STR_String m_scriptText;
+ STR_String m_scriptName;
+ PyObject* m_pythondictionary;
+
+ public:
+ static SCA_PythonController* m_sCurrentController; // protected !!!
+
+ SCA_PythonController(SCA_IObject* gameobj,PyTypeObject* T = &Type);
+ virtual ~SCA_PythonController();
+
+ virtual CValue* GetReplica();
+ virtual void Trigger(class SCA_LogicManager* logicmgr);
+
+ void SetScriptText(const STR_String& text);
+ void SetScriptName(const STR_String& name);
+ void SetDictionary(PyObject* pythondictionary);
+
+ static char* sPyGetCurrentController__doc__;
+ static PyObject* sPyGetCurrentController(PyObject* self,
+ PyObject* args,
+ PyObject* kwds);
+ static char* sPyAddActiveActuator__doc__;
+ static PyObject* sPyAddActiveActuator(PyObject* self,
+ PyObject* args,
+ PyObject* kwds);
+ virtual PyObject* _getattr(char *attr);
+
+ KX_PYMETHOD_DOC(SCA_PythonController,GetSensors);
+ KX_PYMETHOD_DOC(SCA_PythonController,GetSensor);
+ KX_PYMETHOD_DOC(SCA_PythonController,GetActuator);
+ KX_PYMETHOD_DOC(SCA_PythonController,GetActuators);
+ KX_PYMETHOD(SCA_PythonController,SetScript);
+ KX_PYMETHOD(SCA_PythonController,GetScript);
+
+
+};
+
+#endif //KX_PYTHONCONTROLLER_H
+
diff --git a/source/gameengine/GameLogic/SCA_RandomActuator.cpp b/source/gameengine/GameLogic/SCA_RandomActuator.cpp
new file mode 100644
index 00000000000..50acf24251f
--- /dev/null
+++ b/source/gameengine/GameLogic/SCA_RandomActuator.cpp
@@ -0,0 +1,630 @@
+/**
+ * Set random/camera stuff
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "BoolValue.h"
+#include "IntValue.h"
+#include "FloatValue.h"
+#include "SCA_IActuator.h"
+#include "SCA_RandomActuator.h"
+#include "math.h"
+
+#include "MT_Transform.h"
+/* ------------------------------------------------------------------------- */
+/* Native functions */
+/* ------------------------------------------------------------------------- */
+
+SCA_RandomActuator::SCA_RandomActuator(SCA_IObject *gameobj,
+ long seed,
+ SCA_RandomActuator::KX_RANDOMACT_MODE mode,
+ float para1,
+ float para2,
+ const STR_String &propName,
+ PyTypeObject* T)
+ : SCA_IActuator(gameobj, T),
+ m_distribution(mode),
+ m_propname(propName),
+ m_parameter1(para1),
+ m_parameter2(para2)
+{
+ m_base = new SCA_RandomNumberGenerator(seed);
+ m_counter = 0;
+ enforceConstraints();
+}
+
+
+
+SCA_RandomActuator::~SCA_RandomActuator()
+{
+ /* intentionally empty */
+}
+
+
+
+CValue* SCA_RandomActuator::GetReplica()
+{
+ SCA_RandomActuator* replica = new SCA_RandomActuator(*this);
+ replica->ProcessReplica();
+ CValue::AddDataToReplica(replica);
+
+ return replica;
+}
+
+
+
+bool SCA_RandomActuator::Update(double curtime,double deltatime)
+{
+ bool result = false;
+ bool bNegativeEvent = IsNegativeEvent();
+
+ RemoveAllEvents();
+
+
+ CValue *tmpval;
+
+ if (bNegativeEvent)
+ return false; // do nothing on negative events
+
+ switch (m_distribution) {
+ case KX_RANDOMACT_BOOL_CONST: {
+ /* un petit peu filthy */
+ bool res = !(m_parameter1 < 0.5);
+ tmpval = new CBoolValue(res);
+ }
+ break;
+ case KX_RANDOMACT_BOOL_UNIFORM: {
+ /* flip a coin */
+ bool res;
+ if (m_counter > 31) {
+ m_previous = m_base->Draw();
+ res = ((m_previous & 0x1) == 0);
+ m_counter = 1;
+ } else {
+ res = (((m_previous >> m_counter) & 0x1) == 0);
+ m_counter++;
+ }
+ tmpval = new CBoolValue(res);
+ }
+ break;
+ case KX_RANDOMACT_BOOL_BERNOUILLI: {
+ /* 'percentage' */
+ bool res;
+ res = (m_base->DrawFloat() < m_parameter1);
+ tmpval = new CBoolValue(res);
+ }
+ break;
+ case KX_RANDOMACT_INT_CONST: {
+ /* constant */
+ tmpval = new CIntValue((int) floor(m_parameter1));
+ }
+ break;
+ case KX_RANDOMACT_INT_UNIFORM: {
+ /* uniform (toss a die) */
+ int res;
+ /* The [0, 1] interval is projected onto the [min, max+1] domain, */
+ /* and then rounded. */
+ res = (int) floor( ((m_parameter2 - m_parameter1 + 1) * m_base->DrawFloat())
+ + m_parameter1);
+ tmpval = new CIntValue(res);
+ }
+ break;
+ case KX_RANDOMACT_INT_POISSON: {
+ /* poisson (queues) */
+ /* If x_1, x_2, ... is a sequence of random numbers with uniform */
+ /* distribution between zero and one, k is the first integer for */
+ /* which the product x_1*x_2*...*x_k < exp(-\lamba). */
+ float a = 0.0, b = 0.0;
+ int res = 0;
+ /* The - sign is important here! The number to test for, a, must be */
+ /* between 0 and 1. */
+ a = exp(-m_parameter1);
+ /* a quickly reaches 0.... so we guard explicitly for that. */
+ if (a < FLT_MIN) a = FLT_MIN;
+ b = m_base->DrawFloat();
+ while (b >= a) {
+ b = b * m_base->DrawFloat();
+ res++;
+ };
+ tmpval = new CIntValue(res);
+ }
+ break;
+ case KX_RANDOMACT_FLOAT_CONST: {
+ /* constant */
+ tmpval = new CFloatValue(m_parameter1);
+ }
+ break;
+ case KX_RANDOMACT_FLOAT_UNIFORM: {
+ float res = ((m_parameter2 - m_parameter1) * m_base->DrawFloat())
+ + m_parameter1;
+ tmpval = new CFloatValue(res);
+ }
+ break;
+ case KX_RANDOMACT_FLOAT_NORMAL: {
+ /* normal (big numbers): para1 = mean, para2 = std dev */
+
+ /*
+
+ 070301 - nzc - Changed the termination condition. I think I
+ made a small mistake here, but it only affects distro's where
+ the seed equals 0. In that case, the algorithm locks. Let's
+ just guard that case separately.
+
+ */
+
+ float x = 0.0, y = 0.0, s = 0.0, t = 0.0;
+ if (m_base->GetSeed() == 0) {
+ /*
+
+ 070301 - nzc
+ Just taking the mean here seems reasonable.
+
+ */
+ tmpval = new CFloatValue(m_parameter1);
+ } else {
+ /*
+
+ 070301 - nzc
+ Now, with seed != 0, we will most assuredly get some
+ sensible values. The termination condition states two
+ things:
+ 1. s >= 0 is not allowed: to prevent the distro from
+ getting a bias towards high values. This is a small
+ correction, really, and might also be left out.
+ 2. s == 0 is not allowed: to prevent a division by zero
+ when renormalising the drawn value to the desired
+ distribution shape. As a side effect, the distro will
+ never yield the exact mean.
+ I am not sure whether this is consistent, since the error
+ cause by #2 is of the same magnitude as the one
+ prevented by #1. The error introduced into the SD will be
+ improved, though. By how much? Hard to say... If you like
+ the maths, feel free to analyse. Be aware that this is
+ one of the really old standard algorithms. I think the
+ original came in Fortran, was translated to Pascal, and
+ then someone came up with the C code. My guess it that
+ this will be quite sufficient here.
+
+ */
+ do
+ {
+ x = 2.0 * m_base->DrawFloat() - 1.0;
+ y = 2.0 * m_base->DrawFloat() - 1.0;
+ s = x*x + y*y;
+ } while ( (s >= 1.0) || (s == 0.0) );
+ t = x * sqrt( (-2.0 * log(s)) / s);
+ tmpval = new CFloatValue(m_parameter1 + m_parameter2 * t);
+ }
+ }
+ break;
+ case KX_RANDOMACT_FLOAT_NEGATIVE_EXPONENTIAL: {
+ /* 1st order fall-off. I am very partial to using the half-life as */
+ /* controlling parameter. Using the 'normal' exponent is not very */
+ /* intuitive... */
+ /* tmpval = new CFloatValue( (1.0 / m_parameter1) */
+ tmpval = new CFloatValue( (m_parameter1)
+ * (-log(1.0 - m_base->DrawFloat())) );
+
+ }
+ break;
+ default:
+ ; /* unknown distribution... */
+ }
+
+ /* Round up: assign it */
+ CValue *prop = GetParent()->GetProperty(m_propname);
+ if (prop) {
+ prop->SetValue(tmpval);
+ }
+ tmpval->Release();
+
+ return false;
+}
+
+void SCA_RandomActuator::enforceConstraints() {
+ /* The constraints that are checked here are the ones fundamental to */
+ /* the various distributions. Limitations of the algorithms are checked */
+ /* elsewhere (or they should be... ). */
+ switch (m_distribution) {
+ case KX_RANDOMACT_BOOL_CONST:
+ case KX_RANDOMACT_BOOL_UNIFORM:
+ case KX_RANDOMACT_INT_CONST:
+ case KX_RANDOMACT_INT_UNIFORM:
+ case KX_RANDOMACT_FLOAT_UNIFORM:
+ case KX_RANDOMACT_FLOAT_CONST:
+ ; /* Nothing to be done here. We allow uniform distro's to have */
+ /* 'funny' domains, i.e. max < min. This does not give problems. */
+ break;
+ case KX_RANDOMACT_BOOL_BERNOUILLI:
+ /* clamp to [0, 1] */
+ if (m_parameter1 < 0.0) {
+ m_parameter1 = 0.0;
+ } else if (m_parameter1 > 1.0) {
+ m_parameter1 = 1.0;
+ }
+ break;
+ case KX_RANDOMACT_INT_POISSON:
+ /* non-negative */
+ if (m_parameter1 < 0.0) {
+ m_parameter1 = 0.0;
+ }
+ break;
+ case KX_RANDOMACT_FLOAT_NORMAL:
+ /* standard dev. is non-negative */
+ if (m_parameter2 < 0.0) {
+ m_parameter2 = 0.0;
+ }
+ break;
+ case KX_RANDOMACT_FLOAT_NEGATIVE_EXPONENTIAL:
+ /* halflife must be non-negative */
+ if (m_parameter1 < 0.0) {
+ m_parameter1 = 0.0;
+ }
+ break;
+ default:
+ ; /* unknown distribution... */
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+/* Python functions */
+/* ------------------------------------------------------------------------- */
+
+/* Integration hooks ------------------------------------------------------- */
+PyTypeObject SCA_RandomActuator::Type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0,
+ "SCA_RandomActuator",
+ sizeof(SCA_RandomActuator),
+ 0,
+ PyDestructor,
+ 0,
+ __getattr,
+ __setattr,
+ 0, //&MyPyCompare,
+ __repr,
+ 0, //&cvalue_as_number,
+ 0,
+ 0,
+ 0,
+ 0
+};
+
+PyParentObject SCA_RandomActuator::Parents[] = {
+ &SCA_RandomActuator::Type,
+ &SCA_IActuator::Type,
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
+};
+
+PyMethodDef SCA_RandomActuator::Methods[] = {
+ {"setSeed", (PyCFunction) SCA_RandomActuator::sPySetSeed, METH_VARARGS, SetSeed_doc},
+ {"getSeed", (PyCFunction) SCA_RandomActuator::sPyGetSeed, METH_VARARGS, GetSeed_doc},
+ {"getPara1", (PyCFunction) SCA_RandomActuator::sPyGetPara1, METH_VARARGS, GetPara1_doc},
+ {"getPara2", (PyCFunction) SCA_RandomActuator::sPyGetPara2, METH_VARARGS, GetPara2_doc},
+ {"getDistribution", (PyCFunction) SCA_RandomActuator::sPyGetDistribution, METH_VARARGS, GetDistribution_doc},
+ {"setProperty", (PyCFunction) SCA_RandomActuator::sPySetProperty, METH_VARARGS, SetProperty_doc},
+ {"getProperty", (PyCFunction) SCA_RandomActuator::sPyGetProperty, METH_VARARGS, GetProperty_doc},
+ {"setBoolConst", (PyCFunction) SCA_RandomActuator::sPySetBoolConst, METH_VARARGS, SetBoolConst_doc},
+ {"setBoolUniform", (PyCFunction) SCA_RandomActuator::sPySetBoolUniform, METH_VARARGS, SetBoolUniform_doc},
+ {"setBoolBernouilli",(PyCFunction) SCA_RandomActuator::sPySetBoolBernouilli, METH_VARARGS, SetBoolBernouilli_doc},
+ {"setIntConst", (PyCFunction) SCA_RandomActuator::sPySetIntConst, METH_VARARGS, SetIntConst_doc},
+ {"setIntUniform", (PyCFunction) SCA_RandomActuator::sPySetIntUniform, METH_VARARGS, SetIntUniform_doc},
+ {"setIntPoisson", (PyCFunction) SCA_RandomActuator::sPySetIntPoisson, METH_VARARGS, SetIntPoisson_doc},
+ {"setFloatConst", (PyCFunction) SCA_RandomActuator::sPySetFloatConst, METH_VARARGS, SetFloatConst_doc},
+ {"setFloatUniform", (PyCFunction) SCA_RandomActuator::sPySetFloatUniform, METH_VARARGS, SetFloatUniform_doc},
+ {"setFloatNormal", (PyCFunction) SCA_RandomActuator::sPySetFloatNormal, METH_VARARGS, SetFloatNormal_doc},
+ {"setFloatNegativeExponential", (PyCFunction) SCA_RandomActuator::sPySetFloatNegativeExponential, METH_VARARGS, SetFloatNegativeExponential_doc},
+ {NULL,NULL} //Sentinel
+};
+
+PyObject* SCA_RandomActuator::_getattr(char* attr) {
+ _getattr_up(SCA_IActuator);
+}
+
+/* 1. setSeed */
+char SCA_RandomActuator::SetSeed_doc[] =
+"setSeed(seed)\n"
+"\t- seed: integer\n"
+"\tSet the initial seed of the generator. Equal seeds produce\n"
+"\tequal series. If the seed is 0, the generator will produce\n"
+"\tthe same value on every call.\n";
+PyObject* SCA_RandomActuator::PySetSeed(PyObject* self, PyObject* args, PyObject* kwds) {
+ long seedArg;
+ if(!PyArg_ParseTuple(args, "i", &seedArg)) {
+ return NULL;
+ }
+
+ m_base->SetSeed(seedArg);
+
+ Py_Return;
+}
+/* 2. getSeed */
+char SCA_RandomActuator::GetSeed_doc[] =
+"getSeed()\n"
+"\tReturns the initial seed of the generator. Equal seeds produce\n"
+"\tequal series.\n";
+PyObject* SCA_RandomActuator::PyGetSeed(PyObject* self, PyObject* args, PyObject* kwds) {
+ return PyInt_FromLong(m_base->GetSeed());
+}
+
+/* 4. getPara1 */
+char SCA_RandomActuator::GetPara1_doc[] =
+"getPara1()\n"
+"\tReturns the first parameter of the active distribution. Refer\n"
+"\tto the documentation of the generator types for the meaning\n"
+"\tof this value.";
+PyObject* SCA_RandomActuator::PyGetPara1(PyObject* self, PyObject* args, PyObject* kwds) {
+ return PyFloat_FromDouble(m_parameter1);
+}
+
+/* 6. getPara2 */
+char SCA_RandomActuator::GetPara2_doc[] =
+"getPara2()\n"
+"\tReturns the first parameter of the active distribution. Refer\n"
+"\tto the documentation of the generator types for the meaning\n"
+"\tof this value.";
+PyObject* SCA_RandomActuator::PyGetPara2(PyObject* self, PyObject* args, PyObject* kwds) {
+ return PyFloat_FromDouble(m_parameter2);
+}
+
+/* 8. getDistribution */
+char SCA_RandomActuator::GetDistribution_doc[] =
+"getDistribution()\n"
+"\tReturns the type of the active distribution.\n";
+PyObject* SCA_RandomActuator::PyGetDistribution(PyObject* self, PyObject* args, PyObject* kwds) {
+ return PyInt_FromLong(m_distribution);
+}
+
+/* 9. setProperty */
+char SCA_RandomActuator::SetProperty_doc[] =
+"setProperty(name)\n"
+"\t- name: string\n"
+"\tSet the property to which the random value is assigned. If the \n"
+"\tgenerator and property types do not match, the assignment is ignored.\n";
+PyObject* SCA_RandomActuator::PySetProperty(PyObject* self, PyObject* args, PyObject* kwds) {
+ char *nameArg;
+ if (!PyArg_ParseTuple(args, "s", &nameArg)) {
+ return NULL;
+ }
+
+ CValue* prop = GetParent()->FindIdentifier(nameArg);
+
+ if (prop) {
+ m_propname = nameArg;
+ prop->Release();
+ } else {
+ ; /* not found ... */
+ }
+
+ Py_Return;
+}
+/* 10. getProperty */
+char SCA_RandomActuator::GetProperty_doc[] =
+"getProperty(name)\n"
+"\tReturn the property to which the random value is assigned. If the \n"
+"\tgenerator and property types do not match, the assignment is ignored.\n";
+PyObject* SCA_RandomActuator::PyGetProperty(PyObject* self, PyObject* args, PyObject* kwds) {
+ return PyString_FromString(m_propname);
+}
+
+/* 11. setBoolConst */
+char SCA_RandomActuator::SetBoolConst_doc[] =
+"setBoolConst(value)\n"
+"\t- value: 0 or 1\n"
+"\tSet this generator to produce a constant boolean value.\n";
+PyObject* SCA_RandomActuator::PySetBoolConst(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ int paraArg;
+ if(!PyArg_ParseTuple(args, "i", &paraArg)) {
+ return NULL;
+ }
+
+ m_distribution = KX_RANDOMACT_BOOL_CONST;
+ if (paraArg == KX_TRUE) {
+ m_parameter1 = 1;
+ }
+
+ Py_Return;
+}
+/* 12. setBoolUniform, */
+char SCA_RandomActuator::SetBoolUniform_doc[] =
+"setBoolUniform()\n"
+"\tSet this generator to produce true and false, each with 50%% chance of occuring\n";
+PyObject* SCA_RandomActuator::PySetBoolUniform(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ /* no args */
+ m_distribution = KX_RANDOMACT_BOOL_UNIFORM;
+ enforceConstraints();
+ Py_Return;
+}
+/* 13. setBoolBernouilli, */
+char SCA_RandomActuator::SetBoolBernouilli_doc[] =
+"setBoolBernouilli(value)\n"
+"\t- value: a float between 0 and 1\n"
+"\tReturn false value * 100%% of the time.\n";
+PyObject* SCA_RandomActuator::PySetBoolBernouilli(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ float paraArg;
+ if(!PyArg_ParseTuple(args, "f", &paraArg)) {
+ return NULL;
+ }
+
+ m_distribution = KX_RANDOMACT_BOOL_CONST;
+ m_parameter1 = paraArg;
+ enforceConstraints();
+ Py_Return;
+}
+/* 14. setIntConst,*/
+char SCA_RandomActuator::SetIntConst_doc[] =
+"setIntConst(value)\n"
+"\t- value: integer\n"
+"\tAlways return value\n";
+PyObject* SCA_RandomActuator::PySetIntConst(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ int paraArg;
+ if(!PyArg_ParseTuple(args, "i", &paraArg)) {
+ return NULL;
+ }
+
+ m_distribution = KX_RANDOMACT_INT_CONST;
+ m_parameter1 = paraArg;
+ enforceConstraints();
+ Py_Return;
+}
+/* 15. setIntUniform,*/
+char SCA_RandomActuator::SetIntUniform_doc[] =
+"setIntUniform(lower_bound, upper_bound)\n"
+"\t- lower_bound: integer\n"
+"\t- upper_bound: integer\n"
+"\tReturn a random integer between lower_bound and\n"
+"\tupper_bound. The boundaries are included.\n";
+PyObject* SCA_RandomActuator::PySetIntUniform(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ int paraArg1, paraArg2;
+ if(!PyArg_ParseTuple(args, "ii", &paraArg1, &paraArg2)) {
+ return NULL;
+ }
+
+ m_distribution = KX_RANDOMACT_INT_UNIFORM;
+ m_parameter1 = paraArg1;
+ m_parameter2 = paraArg2;
+ enforceConstraints();
+ Py_Return;
+}
+/* 16. setIntPoisson, */
+char SCA_RandomActuator::SetIntPoisson_doc[] =
+"setIntPoisson(value)\n"
+"\t- value: float\n"
+"\tReturn a Poisson-distributed number. This performs a series\n"
+"\tof Bernouilli tests with parameter value. It returns the\n"
+"\tnumber of tries needed to achieve succes.\n";
+PyObject* SCA_RandomActuator::PySetIntPoisson(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ float paraArg;
+ if(!PyArg_ParseTuple(args, "f", &paraArg)) {
+ return NULL;
+ }
+
+ m_distribution = KX_RANDOMACT_INT_POISSON;
+ m_parameter1 = paraArg;
+ enforceConstraints();
+ Py_Return;
+}
+/* 17. setFloatConst,*/
+char SCA_RandomActuator::SetFloatConst_doc[] =
+"setFloatConst(value)\n"
+"\t- value: float\n"
+"\tAlways return value\n";
+PyObject* SCA_RandomActuator::PySetFloatConst(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ float paraArg;
+ if(!PyArg_ParseTuple(args, "f", &paraArg)) {
+ return NULL;
+ }
+
+ m_distribution = KX_RANDOMACT_FLOAT_CONST;
+ m_parameter1 = paraArg;
+ enforceConstraints();
+ Py_Return;
+}
+/* 18. setFloatUniform, */
+char SCA_RandomActuator::SetFloatUniform_doc[] =
+"setFloatUniform(lower_bound, upper_bound)\n"
+"\t- lower_bound: float\n"
+"\t- upper_bound: float\n"
+"\tReturn a random integer between lower_bound and\n"
+"\tupper_bound.\n";
+PyObject* SCA_RandomActuator::PySetFloatUniform(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ float paraArg1, paraArg2;
+ if(!PyArg_ParseTuple(args, "ff", &paraArg1, &paraArg2)) {
+ return NULL;
+ }
+
+ m_distribution = KX_RANDOMACT_FLOAT_UNIFORM;
+ m_parameter1 = paraArg1;
+ m_parameter2 = paraArg2;
+ enforceConstraints();
+ Py_Return;
+}
+/* 19. setFloatNormal, */
+char SCA_RandomActuator::SetFloatNormal_doc[] =
+"setFloatNormal(mean, standard_deviation)\n"
+"\t- mean: float\n"
+"\t- standard_deviation: float\n"
+"\tReturn normal-distributed numbers. The average is mean, and the\n"
+"\tdeviation from the mean is characterized by standard_deviation.\n";
+PyObject* SCA_RandomActuator::PySetFloatNormal(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ float paraArg1, paraArg2;
+ if(!PyArg_ParseTuple(args, "ff", &paraArg1, &paraArg2)) {
+ return NULL;
+ }
+
+ m_distribution = KX_RANDOMACT_FLOAT_NORMAL;
+ m_parameter1 = paraArg1;
+ m_parameter2 = paraArg2;
+ enforceConstraints();
+ Py_Return;
+}
+/* 20. setFloatNegativeExponential, */
+char SCA_RandomActuator::SetFloatNegativeExponential_doc[] =
+"setFloatNegativeExponential(half_life)\n"
+"\t- half_life: float\n"
+"\tReturn negative-exponentially distributed numbers. The half-life 'time'\n"
+"\tis characterized by half_life.\n";
+PyObject* SCA_RandomActuator::PySetFloatNegativeExponential(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ float paraArg;
+ if(!PyArg_ParseTuple(args, "f", &paraArg)) {
+ return NULL;
+ }
+
+ m_distribution = KX_RANDOMACT_FLOAT_NEGATIVE_EXPONENTIAL;
+ m_parameter1 = paraArg;
+ enforceConstraints();
+ Py_Return;
+}
+
+/* eof */
diff --git a/source/gameengine/GameLogic/SCA_RandomActuator.h b/source/gameengine/GameLogic/SCA_RandomActuator.h
new file mode 100644
index 00000000000..236d41c5154
--- /dev/null
+++ b/source/gameengine/GameLogic/SCA_RandomActuator.h
@@ -0,0 +1,144 @@
+/**
+ * Draw a random number, and put it in a property
+ *
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 __KX_RANDOMACTUATOR
+#define __KX_RANDOMACTUATOR
+
+#include "SCA_IActuator.h"
+#include "SCA_RandomNumberGenerator.h"
+
+class SCA_RandomActuator : public SCA_IActuator
+{
+ Py_Header;
+ /** Property to assign to */
+ STR_String m_propname;
+
+ /** First parameter. The meaning of the parameters depends on the
+ * distribution */
+ float m_parameter1;
+ /** Second parameter. The meaning of the parameters depends on the
+ * distribution */
+ float m_parameter2;
+
+ /** The base generator */
+ SCA_RandomNumberGenerator *m_base;
+
+ /** just a generic, persistent counter */
+ int m_counter;
+
+ /** cache for the previous draw */
+ long m_previous;
+
+ /** apply constraints for the chosen distribution to the parameters */
+ void enforceConstraints(void);
+
+ public:
+
+ enum KX_RANDOMACT_MODE {
+ KX_RANDOMACT_NODEF,
+ KX_RANDOMACT_BOOL_CONST,
+ KX_RANDOMACT_BOOL_UNIFORM,
+ KX_RANDOMACT_BOOL_BERNOUILLI,
+ KX_RANDOMACT_INT_CONST,
+ KX_RANDOMACT_INT_UNIFORM,
+ KX_RANDOMACT_INT_POISSON,
+ KX_RANDOMACT_FLOAT_CONST,
+ KX_RANDOMACT_FLOAT_UNIFORM,
+ KX_RANDOMACT_FLOAT_NORMAL,
+ KX_RANDOMACT_FLOAT_NEGATIVE_EXPONENTIAL,
+ KX_RANDOMACT_MAX
+ };
+ /** distribution type */
+ KX_RANDOMACT_MODE m_distribution;
+
+ SCA_RandomActuator(class SCA_IObject* gameobj,
+ long seed,
+ KX_RANDOMACT_MODE mode,
+ float para1,
+ float para2,
+ const STR_String &propName,
+ PyTypeObject* T=&Type);
+ virtual ~SCA_RandomActuator();
+ virtual bool Update(double curtime,double deltatime);
+
+ virtual CValue* GetReplica();
+
+ /* --------------------------------------------------------------------- */
+ /* Python interface ---------------------------------------------------- */
+ /* --------------------------------------------------------------------- */
+
+ virtual PyObject* _getattr(char *attr);
+
+ /* 1. setSeed */
+ KX_PYMETHOD_DOC(SCA_RandomActuator,SetSeed);
+ /* 2. getSeed */
+ KX_PYMETHOD_DOC(SCA_RandomActuator,GetSeed);
+ /* 3. setPara1 -removed- */
+ /* 4. getPara1 */
+ KX_PYMETHOD_DOC(SCA_RandomActuator,GetPara1);
+ /* 5. setPara2 -removed- */
+ /* 6. getPara2 */
+ KX_PYMETHOD_DOC(SCA_RandomActuator,GetPara2);
+ /* 7. setDistribution -removed- */
+ /* 8. getDistribution */
+ KX_PYMETHOD_DOC(SCA_RandomActuator,GetDistribution);
+ /* 9. setProperty */
+ KX_PYMETHOD_DOC(SCA_RandomActuator,SetProperty);
+ /* 10. getProperty */
+ KX_PYMETHOD_DOC(SCA_RandomActuator,GetProperty);
+ /* 11. setBoolConst */
+ KX_PYMETHOD_DOC(SCA_RandomActuator,SetBoolConst);
+ /* 12. setBoolUniform, */
+ KX_PYMETHOD_DOC(SCA_RandomActuator,SetBoolUniform);
+ /* 13. setBoolBernouilli, */
+ KX_PYMETHOD_DOC(SCA_RandomActuator,SetBoolBernouilli);
+ /* 14. setIntConst,*/
+ KX_PYMETHOD_DOC(SCA_RandomActuator,SetIntConst);
+ /* 15. setIntUniform,*/
+ KX_PYMETHOD_DOC(SCA_RandomActuator,SetIntUniform);
+ /* 16. setIntPoisson, */
+ KX_PYMETHOD_DOC(SCA_RandomActuator,SetIntPoisson);
+ /* 17. setFloatConst,*/
+ KX_PYMETHOD_DOC(SCA_RandomActuator,SetFloatConst);
+ /* 18. setFloatUniform, */
+ KX_PYMETHOD_DOC(SCA_RandomActuator,SetFloatUniform);
+ /* 19. setFloatNormal, */
+ KX_PYMETHOD_DOC(SCA_RandomActuator,SetFloatNormal);
+ /* 20. setFloatNegativeExponential, */
+ KX_PYMETHOD_DOC(SCA_RandomActuator,SetFloatNegativeExponential);
+
+}; /* end of class KX_EditObjectActuator : public SCA_PropertyActuator */
+
+#endif
diff --git a/source/gameengine/GameLogic/SCA_RandomEventManager.cpp b/source/gameengine/GameLogic/SCA_RandomEventManager.cpp
new file mode 100644
index 00000000000..12cf78d234a
--- /dev/null
+++ b/source/gameengine/GameLogic/SCA_RandomEventManager.cpp
@@ -0,0 +1,64 @@
+/**
+ * Manager for random events
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "SCA_RandomEventManager.h"
+#include "SCA_LogicManager.h"
+#include "SCA_ISensor.h"
+#include <vector>
+using namespace std;
+
+#include <iostream>
+#include <stdio.h>
+
+SCA_RandomEventManager::SCA_RandomEventManager(class SCA_LogicManager* logicmgr)
+ : m_logicmgr(logicmgr),
+ SCA_EventManager(RANDOM_EVENTMGR)
+{
+}
+
+
+void SCA_RandomEventManager::NextFrame(double curtime,double deltatime)
+{
+ for (vector<class SCA_ISensor*>::const_iterator i= m_sensors.begin();!(i==m_sensors.end());i++)
+ {
+ SCA_ISensor *sensor = *i;
+ sensor->Activate(m_logicmgr, NULL);
+ }
+}
+
+
+
+void SCA_RandomEventManager::RegisterSensor(SCA_ISensor* sensor)
+{
+ m_sensors.push_back(sensor);
+};
diff --git a/source/gameengine/GameLogic/SCA_RandomEventManager.h b/source/gameengine/GameLogic/SCA_RandomEventManager.h
new file mode 100644
index 00000000000..1014bddcd82
--- /dev/null
+++ b/source/gameengine/GameLogic/SCA_RandomEventManager.h
@@ -0,0 +1,53 @@
+/**
+ * Manager for random events
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 __KX_RANDOMEVENTMGR
+#define __KX_RANDOMEVENTMGR
+
+#include "SCA_EventManager.h"
+#include <vector>
+
+using namespace std;
+
+class SCA_RandomEventManager : public SCA_EventManager
+{
+ class SCA_LogicManager* m_logicmgr;
+
+public:
+ SCA_RandomEventManager(class SCA_LogicManager* logicmgr);
+
+ virtual void NextFrame(double curtime,double deltatime);
+ virtual void RegisterSensor(SCA_ISensor* sensor);
+};
+#endif //__KX_RANDOMEVENTMGR
diff --git a/source/gameengine/GameLogic/SCA_RandomNumberGenerator.cpp b/source/gameengine/GameLogic/SCA_RandomNumberGenerator.cpp
new file mode 100644
index 00000000000..7faa76fd01d
--- /dev/null
+++ b/source/gameengine/GameLogic/SCA_RandomNumberGenerator.cpp
@@ -0,0 +1,125 @@
+/**
+ * Generate random numbers that can be used by other components. We
+ * convert to different types/distributions elsewhere. This just
+ * delivers a clean, random bitvector.
+ *
+ * $Id$
+ */
+
+/* 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 <limits.h>
+#include "SCA_RandomNumberGenerator.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)
+
+SCA_RandomNumberGenerator::SCA_RandomNumberGenerator(long seed) {
+ int mti = N + 1;
+ m_seed = seed;
+ SetStartVector();
+}
+
+SCA_RandomNumberGenerator::~SCA_RandomNumberGenerator() {
+ /* intentionally empty */
+}
+
+void SCA_RandomNumberGenerator::SetStartVector(void) {
+ /* 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] = m_seed & 0xffffffff;
+ for (mti = 1; mti < N; mti++)
+ mt[mti] = (69069 * mt[mti-1]) & 0xffffffff;
+}
+
+long SCA_RandomNumberGenerator::GetSeed() { return m_seed; }
+void SCA_RandomNumberGenerator::SetSeed(long newseed)
+{
+ m_seed = newseed;
+ SetStartVector();
+}
+
+/**
+ * This is the important part: copied verbatim :)
+ */
+unsigned long SCA_RandomNumberGenerator::Draw() {
+ 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;
+
+ /* I set this in the constructor, so it is always satisfied ! */
+// if (mti == N+1) /* if sgenrand() has not been called, */
+// GEN_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;
+}
+
+float SCA_RandomNumberGenerator::DrawFloat() {
+ return ( (float) Draw()/ (unsigned long) 0xffffffff );
+}
+
+/* eof */
diff --git a/source/gameengine/GameLogic/SCA_RandomNumberGenerator.h b/source/gameengine/GameLogic/SCA_RandomNumberGenerator.h
new file mode 100644
index 00000000000..c6cd52dd3db
--- /dev/null
+++ b/source/gameengine/GameLogic/SCA_RandomNumberGenerator.h
@@ -0,0 +1,65 @@
+/**
+ * Generate random numbers that can be used by other components. Each
+ * generator needs its own generator, so that the seed can be set
+ * on a per-generator basis.
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 __KX_RANDOMNUMBERGENERATOR
+#define __KX_RANDOMNUMBERGENERATOR
+
+
+class SCA_RandomNumberGenerator {
+
+ /** base seed */
+ long m_seed;
+
+ /* A bit silly.. The N parameter is a define in the .cpp file */
+ /** the array for the state vector */
+ /* unsigned long mt[N]; */
+ unsigned long mt[624];
+
+ /** mti==N+1 means mt[KX_MT_VectorLenght] is not initialized */
+ int mti; /* initialised in the cpp file */
+
+ /** Calculate a start vector */
+ void SetStartVector(void);
+ public:
+ SCA_RandomNumberGenerator(long seed);
+ ~SCA_RandomNumberGenerator();
+ unsigned long Draw();
+ float DrawFloat();
+ long GetSeed();
+ void SetSeed(long newseed);
+};
+
+#endif /* __KX_RANDOMNUMBERGENERATOR */
diff --git a/source/gameengine/GameLogic/SCA_RandomSensor.cpp b/source/gameengine/GameLogic/SCA_RandomSensor.cpp
new file mode 100644
index 00000000000..7f3f2f93315
--- /dev/null
+++ b/source/gameengine/GameLogic/SCA_RandomSensor.cpp
@@ -0,0 +1,191 @@
+/**
+ * Generate random pulses
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "SCA_RandomSensor.h"
+#include "SCA_EventManager.h"
+#include "SCA_RandomEventManager.h"
+#include "SCA_LogicManager.h"
+#include "ConstExpr.h"
+#include <iostream>
+
+/* ------------------------------------------------------------------------- */
+/* Native functions */
+/* ------------------------------------------------------------------------- */
+
+SCA_RandomSensor::SCA_RandomSensor(SCA_EventManager* eventmgr,
+ SCA_IObject* gameobj,
+ int startseed,
+ PyTypeObject* T)
+ : SCA_ISensor(gameobj,eventmgr, T)
+{
+ m_iteration = 0;
+ m_lastdraw = false;
+
+ m_basegenerator = new SCA_RandomNumberGenerator(startseed);
+ m_currentDraw = m_basegenerator->Draw();
+ RegisterToManager();
+}
+
+
+
+SCA_RandomSensor::~SCA_RandomSensor()
+{
+ /* Nothing to be done here. */
+}
+
+
+
+CValue* SCA_RandomSensor::GetReplica()
+{
+ CValue* replica = new SCA_RandomSensor(*this);
+ // this will copy properties and so on...
+ CValue::AddDataToReplica(replica);
+
+ return replica;
+}
+
+
+
+bool SCA_RandomSensor::IsPositiveTrigger()
+{
+ return (m_invert !=m_lastdraw);
+}
+
+
+bool SCA_RandomSensor::Evaluate(CValue* event)
+{
+ /* Random generator is the generator from Line 25 of Table 1 in */
+ /* [KNUTH 1981, The Art of Computer Programming Vol. 2 */
+ /* (2nd Ed.), pp102] */
+ /* It's a very simple max. length sequence generator. We can */
+ /* draw 32 bool values before having to generate the next */
+ /* sequence value. There are some theorems that will tell you */
+ /* this is a reasonable way of generating bools. Check Knuth. */
+ /* Furthermore, we only draw each <delay>-eth frame. */
+
+ bool drawResult = false;
+
+ if (m_iteration > 31) {
+ m_currentDraw = m_basegenerator->Draw();
+ drawResult = (m_currentDraw & 0x1) == 0;
+ m_iteration = 1;
+ } else {
+ drawResult = ((m_currentDraw >> m_iteration) & 0x1) == 0;
+ m_iteration++;
+ }
+
+ /* now pass this result to some controller */
+ m_lastdraw = drawResult;
+ return drawResult;
+}
+
+/* ------------------------------------------------------------------------- */
+/* Python functions */
+/* ------------------------------------------------------------------------- */
+
+/* Integration hooks ------------------------------------------------------- */
+PyTypeObject SCA_RandomSensor::Type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0,
+ "SCA_RandomSensor",
+ sizeof(SCA_RandomSensor),
+ 0,
+ PyDestructor,
+ 0,
+ __getattr,
+ __setattr,
+ 0, //&MyPyCompare,
+ __repr,
+ 0, //&cvalue_as_number,
+ 0,
+ 0,
+ 0,
+ 0
+};
+
+PyParentObject SCA_RandomSensor::Parents[] = {
+ &SCA_RandomSensor::Type,
+ &SCA_ISensor::Type,
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
+};
+
+PyMethodDef SCA_RandomSensor::Methods[] = {
+ {"setSeed", (PyCFunction) SCA_RandomSensor::sPySetSeed, METH_VARARGS, SetSeed_doc},
+ {"getSeed", (PyCFunction) SCA_RandomSensor::sPyGetSeed, METH_VARARGS, GetSeed_doc},
+ {"getLastDraw", (PyCFunction) SCA_RandomSensor::sPyGetLastDraw, METH_VARARGS, GetLastDraw_doc},
+ {NULL,NULL} //Sentinel
+};
+
+PyObject* SCA_RandomSensor::_getattr(char* attr) {
+ _getattr_up(SCA_ISensor);
+}
+
+/* 1. setSeed */
+char SCA_RandomSensor::SetSeed_doc[] =
+"setSeed(seed)\n"
+"\t- seed: integer\n"
+"\tSet the initial seed of the generator. Equal seeds produce\n"
+"\tequal series. If the seed is 0, the generator will produce\n"
+"\tthe same value on every call.\n";
+PyObject* SCA_RandomSensor::PySetSeed(PyObject* self, PyObject* args, PyObject* kwds) {
+ long seedArg;
+ if(!PyArg_ParseTuple(args, "i", &seedArg)) {
+ return NULL;
+ }
+
+ m_basegenerator->SetSeed(seedArg);
+
+ Py_Return;
+}
+
+/* 2. getSeed */
+char SCA_RandomSensor::GetSeed_doc[] =
+"getSeed()\n"
+"\tReturns the initial seed of the generator. Equal seeds produce\n"
+"\tequal series.\n";
+PyObject* SCA_RandomSensor::PyGetSeed(PyObject* self, PyObject* args, PyObject* kwds) {
+ return PyInt_FromLong(m_basegenerator->GetSeed());
+}
+
+/* 3. getLastDraw */
+char SCA_RandomSensor::GetLastDraw_doc[] =
+"getLastDraw()\n"
+"\tReturn the last value that was drawn.\n";
+PyObject* SCA_RandomSensor::PyGetLastDraw(PyObject* self, PyObject* args, PyObject* kwds) {
+ return PyInt_FromLong(m_lastdraw);
+}
+
+/* eof */
diff --git a/source/gameengine/GameLogic/SCA_RandomSensor.h b/source/gameengine/GameLogic/SCA_RandomSensor.h
new file mode 100644
index 00000000000..6a77f289be5
--- /dev/null
+++ b/source/gameengine/GameLogic/SCA_RandomSensor.h
@@ -0,0 +1,75 @@
+/**
+ * Generate random pulses
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 __KX_RANDOMSENSOR
+#define __KX_RANDOMSENSOR
+
+#include "SCA_ISensor.h"
+#include "BoolValue.h"
+#include "SCA_RandomNumberGenerator.h"
+
+class SCA_RandomSensor : public SCA_ISensor
+{
+ Py_Header;
+
+ unsigned int m_currentDraw;
+ int m_iteration;
+ SCA_RandomNumberGenerator *m_basegenerator;
+ bool m_lastdraw;
+public:
+ SCA_RandomSensor(class SCA_EventManager* rndmgr,
+ SCA_IObject* gameobj,
+ int startseed,
+ PyTypeObject* T=&Type);
+ virtual ~SCA_RandomSensor();
+ virtual CValue* GetReplica();
+ virtual bool Evaluate(CValue* event);
+ virtual bool IsPositiveTrigger();
+
+ /* --------------------------------------------------------------------- */
+ /* Python interface ---------------------------------------------------- */
+ /* --------------------------------------------------------------------- */
+
+ virtual PyObject* _getattr(char *attr);
+
+ /* 1. setSeed */
+ KX_PYMETHOD_DOC(SCA_RandomSensor,SetSeed);
+ /* 2. getSeed */
+ KX_PYMETHOD_DOC(SCA_RandomSensor,GetSeed);
+ /* 3. getSeed */
+ KX_PYMETHOD_DOC(SCA_RandomSensor,GetLastDraw);
+
+};
+
+#endif //__KX_RANDOMSENSOR
diff --git a/source/gameengine/GameLogic/SCA_TimeEventManager.cpp b/source/gameengine/GameLogic/SCA_TimeEventManager.cpp
new file mode 100644
index 00000000000..784afcce298
--- /dev/null
+++ b/source/gameengine/GameLogic/SCA_TimeEventManager.cpp
@@ -0,0 +1,110 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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
+
+// 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
+
+#include "SCA_TimeEventManager.h"
+
+#include "SCA_LogicManager.h"
+#include "FloatValue.h"
+
+SCA_TimeEventManager::SCA_TimeEventManager(SCA_LogicManager* logicmgr)
+: SCA_EventManager(TIME_EVENTMGR)
+{
+}
+
+
+
+SCA_TimeEventManager::~SCA_TimeEventManager()
+{
+ for (vector<CValue*>::iterator it = m_timevalues.begin();
+ !(it == m_timevalues.end()); it++)
+ {
+ (*it)->Release();
+ }
+}
+
+
+
+void SCA_TimeEventManager::RegisterSensor(SCA_ISensor* sensor)
+{
+ // not yet
+}
+
+
+
+void SCA_TimeEventManager::NextFrame(double curtime,double deltatime)
+{
+ if (m_timevalues.size() > 0)
+ {
+ CFloatValue* floatval = new CFloatValue(curtime);
+
+ // update sensors, but ... need deltatime !
+ for (vector<CValue*>::iterator it = m_timevalues.begin();
+ !(it == m_timevalues.end()); it++)
+ {
+ float newtime = (*it)->GetNumber() + deltatime;
+ floatval->SetFloat(newtime);
+ (*it)->SetValue(floatval);
+ }
+
+ floatval->Release();
+ }
+}
+
+
+
+void SCA_TimeEventManager::AddTimeProperty(CValue* timeval)
+{
+ timeval->AddRef();
+ m_timevalues.push_back(timeval);
+}
+
+
+
+void SCA_TimeEventManager::RemoveTimeProperty(CValue* timeval)
+{
+ for (vector<CValue*>::iterator it = m_timevalues.begin();
+ !(it == m_timevalues.end()); it++)
+ {
+ if ((*it) == timeval)
+ {
+ this->m_timevalues.erase(it);
+ timeval->Release();
+ break;
+ }
+ }
+}
diff --git a/source/gameengine/GameLogic/SCA_TimeEventManager.h b/source/gameengine/GameLogic/SCA_TimeEventManager.h
new file mode 100644
index 00000000000..880659e1a87
--- /dev/null
+++ b/source/gameengine/GameLogic/SCA_TimeEventManager.h
@@ -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 *****
+ */
+#ifndef __KX_TIMEEVENTMANAGER
+#define __KX_TIMEEVENTMANAGER
+
+#include "SCA_EventManager.h"
+#include "Value.h"
+#include <vector>
+
+using namespace std;
+
+class SCA_TimeEventManager : public SCA_EventManager
+{
+ vector<CValue*> m_timevalues; // values that need their time updated regularly
+
+public:
+ SCA_TimeEventManager(class SCA_LogicManager* logicmgr);
+ virtual ~SCA_TimeEventManager();
+
+ virtual void NextFrame(double curtime,double deltatime);
+ virtual void RegisterSensor(class SCA_ISensor* sensor);
+ void AddTimeProperty(CValue* timeval);
+ void RemoveTimeProperty(CValue* timeval);
+};
+#endif //__KX_TIMEEVENTMANAGER
diff --git a/source/gameengine/GamePlayer/Makefile b/source/gameengine/GamePlayer/Makefile
new file mode 100644
index 00000000000..49f47a4d4a0
--- /dev/null
+++ b/source/gameengine/GamePlayer/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 *****
+#
+# Bounces make to subdirectories.
+
+include nan_definitions.mk
+
+SOURCEDIR = source/gameengine/GamePlayer
+DIR = $(OCGDIR)/gameengine/GamePlayer
+DIRS = common ghost
+
+ifeq ($(OS),$(findstring $(OS), "freebsd irix windows"))
+ DIRS += netscape
+endif
+
+ifeq ($(OS),$(findstring $(OS), "linux"))
+ ifeq ($(CPU),i386)
+ DIRS += netscape
+ endif
+endif
+
+ifeq ($(OS),$(findstring $(OS), "solaris"))
+ ifeq ($(CPU),sparc)
+ DIRS += netscape
+ endif
+endif
+
+include nan_subdirs.mk
diff --git a/source/gameengine/GamePlayer/common/GPC_Canvas.cpp b/source/gameengine/GamePlayer/common/GPC_Canvas.cpp
new file mode 100644
index 00000000000..4e59863f510
--- /dev/null
+++ b/source/gameengine/GamePlayer/common/GPC_Canvas.cpp
@@ -0,0 +1,371 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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
+#include <windows.h>
+#endif
+
+#include "RAS_IPolygonMaterial.h"
+#include "GPC_Canvas.h"
+
+GPC_Canvas::TBannerId GPC_Canvas::s_bannerId = 0;
+
+
+GPC_Canvas::GPC_Canvas(
+ int width,
+ int height
+) :
+ m_width(width),
+ m_height(height),
+ m_bannersEnabled(false)
+{
+}
+
+
+GPC_Canvas::~GPC_Canvas()
+{
+ DisposeAllBanners();
+}
+
+
+// void GPC_Canvas::InitPostRenderingContext(void)
+// {
+// glViewport(0, 0, m_width, m_height);
+// glMatrixMode(GL_PROJECTION);
+// glLoadIdentity();
+
+// glOrtho(-2.0, 2.0, -2.0, 2.0, -20.0, 20.0);
+
+// glMatrixMode(GL_MODELVIEW);
+// glLoadIdentity();
+
+// glEnable(GL_DEPTH_TEST);
+
+// glDepthFunc(GL_LESS);
+
+// glShadeModel(GL_SMOOTH);
+// }
+
+void GPC_Canvas::Resize(int width, int height)
+{
+ m_width = width;
+ m_height = height;
+}
+
+void GPC_Canvas::EndFrame()
+{
+ if (m_bannersEnabled)
+ DrawAllBanners();
+}
+
+
+void GPC_Canvas::ClearColor(float r, float g, float b, float a)
+{
+ ::glClearColor(r,g,b,a);
+}
+
+void GPC_Canvas::SetViewPort(int x1, int y1, int x2, int y2)
+{
+ /* XXX, nasty, this needs to go somewhere else,
+ * but where... definitly need to clean up this
+ * whole canvas/rendertools mess.
+ */
+ glEnable(GL_SCISSOR_TEST);
+
+ glViewport(x1,y1,x2-x1 + 1,y2-y1 + 1);
+ glScissor(x1,y1,x2-x1 + 1,y2-y1 + 1);
+};
+
+
+void GPC_Canvas::ClearBuffer(
+ int type
+){
+
+ int ogltype = 0;
+ if (type & RAS_ICanvas::COLOR_BUFFER )
+ ogltype |= GL_COLOR_BUFFER_BIT;
+ if (type & RAS_ICanvas::DEPTH_BUFFER )
+ ogltype |= GL_DEPTH_BUFFER_BIT;
+
+ ::glClear(ogltype);
+
+}
+
+
+GPC_Canvas::TBannerId GPC_Canvas::AddBanner(
+ unsigned int bannerWidth, unsigned int bannerHeight,
+ unsigned int imageWidth, unsigned int imageHeight,
+ unsigned char* imageData,
+ TBannerAlignment alignment, bool enabled)
+{
+ TBannerData banner;
+
+ banner.alignment = alignment;
+ banner.enabled = enabled;
+ banner.displayWidth = bannerWidth;
+ banner.displayHeight = bannerHeight;
+ banner.imageWidth = imageWidth;
+ banner.imageHeight = imageHeight;
+ unsigned int bannerDataSize = imageWidth*imageHeight*4;
+ banner.imageData = new unsigned char [bannerDataSize];
+ ::memcpy(banner.imageData, imageData, bannerDataSize);
+ banner.textureName = 0;
+
+ m_banners.insert(TBannerMap::value_type(++s_bannerId, banner));
+ return s_bannerId;
+}
+
+
+void GPC_Canvas::DisposeBanner(TBannerId id)
+{
+ TBannerMap::iterator it = m_banners.find(id);
+ if (it != m_banners.end()) {
+ DisposeBanner(it->second);
+ m_banners.erase(it);
+ }
+}
+
+void GPC_Canvas::DisposeAllBanners()
+{
+ TBannerMap::iterator it = m_banners.begin();
+ while (it != m_banners.end()) {
+ DisposeBanner(it->second);
+ it++;
+ }
+}
+
+void GPC_Canvas::SetBannerEnabled(TBannerId id, bool enabled)
+{
+ TBannerMap::iterator it = m_banners.find(id);
+ if (it != m_banners.end()) {
+ it->second.enabled = enabled;
+ }
+}
+
+
+void GPC_Canvas::SetBannerDisplayEnabled(bool enabled)
+{
+ m_bannersEnabled = enabled;
+}
+
+
+void GPC_Canvas::DisposeBanner(TBannerData& banner)
+{
+ if (banner.imageData) {
+ delete [] banner.imageData;
+ banner.imageData = 0;
+ }
+ if (banner.textureName) {
+ ::glDeleteTextures(1, (GLuint*)&banner.textureName);
+ }
+}
+
+void GPC_Canvas::DrawAllBanners(void)
+{
+ if(!m_bannersEnabled || (m_banners.size() < 1))
+ return;
+
+ // Save the old rendering parameters.
+
+ CanvasRenderState render_state;
+ PushRenderState(render_state);
+
+ // Set up everything for banner display.
+
+ // Set up OpenGL matrices
+ SetOrthoProjection();
+ // Activate OpenGL settings needed for display of the texture
+ ::glDisable(GL_LIGHTING);
+ ::glDisable(GL_DEPTH_TEST);
+ ::glDisable(GL_FOG);
+ ::glEnable(GL_TEXTURE_2D);
+ ::glEnable(GL_BLEND);
+ ::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ TBannerMap::iterator it = m_banners.begin();
+ while (it != m_banners.end()) {
+ if (it->second.enabled) {
+ DrawBanner(it->second);
+ }
+ it++;
+ }
+
+ PopRenderState(render_state);
+}
+
+
+void GPC_Canvas::DrawBanner(TBannerData& banner)
+{
+ if(!banner.enabled)
+ return;
+
+ // Set up coordinates
+ int coords[4][2];
+ if (banner.alignment == alignTopLeft) {
+ // Upper left
+ coords[0][0] = 0;
+ coords[0][1] = ((int)m_height)-banner.displayHeight;
+ coords[1][0] = banner.displayWidth;
+ coords[1][1] = ((int)m_height)-banner.displayHeight;
+ coords[2][0] = banner.displayWidth;
+ coords[2][1] = ((int)m_height);
+ coords[3][0] = 0;
+ coords[3][1] = ((int)m_height);
+ }
+ else {
+ // Lower right
+ coords[0][0] = (int)m_width - banner.displayWidth;
+ coords[0][1] = 0;
+ coords[1][0] = m_width;
+ coords[1][1] = 0;
+ coords[2][0] = m_width;
+ coords[2][1] = banner.displayHeight;
+ coords[3][0] = (int)m_width - banner.displayWidth;
+ coords[3][1] = banner.displayHeight;
+ }
+ // Set up uvs
+ int uvs[4][2] = {
+ { 0, 1},
+ { 1, 1},
+ { 1, 0},
+ { 0, 0}
+ };
+
+ if (!banner.textureName) {
+ ::glGenTextures(1, (GLuint*)&banner.textureName);
+ ::glBindTexture(GL_TEXTURE_2D, banner.textureName);
+ ::glTexImage2D(
+ GL_TEXTURE_2D, // target
+ 0, // level
+ 4, // components
+ banner.imageWidth, // width
+ banner.displayHeight, // height
+ 0, // border
+ GL_RGBA, // format
+ GL_UNSIGNED_BYTE, // type
+ banner.imageData); // image data
+ ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ }
+ else {
+ ::glBindTexture(GL_TEXTURE_2D, banner.textureName);
+ }
+
+ // Draw the rectangle with the texture on it
+ ::glBegin(GL_QUADS);
+ ::glColor4f(1.f, 1.f, 1.f, 1.f);
+ ::glTexCoord2iv((GLint*)uvs[0]);
+ ::glVertex2iv((GLint*)coords[0]);
+ ::glTexCoord2iv((GLint*)uvs[1]);
+ ::glVertex2iv((GLint*)coords[1]);
+ ::glTexCoord2iv((GLint*)uvs[2]);
+ ::glVertex2iv((GLint*)coords[2]);
+ ::glTexCoord2iv((GLint*)uvs[3]);
+ ::glVertex2iv((GLint*)coords[3]);
+ ::glEnd();
+}
+
+ void
+GPC_Canvas::
+PushRenderState(
+ CanvasRenderState & render_state
+){
+#if 0
+
+ ::glMatrixMode(GL_PROJECTION);
+ ::glPushMatrix();
+ ::glMatrixMode(GL_MODELVIEW);
+ ::glPushMatrix();
+ ::glMatrixMode(GL_TEXTURE);
+ ::glPushMatrix();
+ // Save old OpenGL settings
+ ::glGetIntegerv(GL_LIGHTING, (GLint*)&(render_state.oldLighting));
+ ::glGetIntegerv(GL_DEPTH_TEST, (GLint*)&(render_state.oldDepthTest));
+ ::glGetIntegerv(GL_FOG, (GLint*)&(render_state.oldFog));
+ ::glGetIntegerv(GL_TEXTURE_2D, (GLint*)&(render_state.oldTexture2D));
+ ::glGetIntegerv(GL_BLEND, (GLint*)&(render_state.oldBlend));
+ ::glGetIntegerv(GL_BLEND_SRC, (GLint*)&(render_state.oldBlendSrc));
+ ::glGetIntegerv(GL_BLEND_DST, (GLint*)&(render_state.oldBlendDst));
+ ::glGetFloatv(GL_CURRENT_COLOR, render_state.oldColor);
+ ::glGetIntegerv(GL_DEPTH_WRITEMASK,(GLint*)&(render_state.oldWriteMask));
+#else
+
+ glPushAttrib(GL_ALL_ATTRIB_BITS);
+
+#endif
+}
+
+ void
+GPC_Canvas::
+PopRenderState(
+ const CanvasRenderState & render_state
+){
+#if 0
+ // Restore OpenGL settings
+ render_state.oldLighting ? ::glEnable(GL_LIGHTING) : glDisable(GL_LIGHTING);
+ render_state.oldDepthTest ? ::glEnable(GL_DEPTH_TEST) : glDisable(GL_DEPTH_TEST);
+ render_state.oldFog ? ::glEnable(GL_FOG) : ::glDisable(GL_FOG);
+ render_state.oldTexture2D ? ::glEnable(GL_TEXTURE_2D) : glDisable(GL_TEXTURE_2D);
+ render_state.oldBlend ? glEnable(GL_BLEND) : ::glDisable(GL_BLEND);
+ ::glBlendFunc((GLenum)render_state.oldBlendSrc, (GLenum)render_state.oldBlendDst);
+ render_state.oldWriteMask ? ::glEnable(GL_DEPTH_WRITEMASK) : glDisable(GL_DEPTH_WRITEMASK);
+
+ ::glColor4fv(render_state.oldColor);
+ // Restore OpenGL matrices
+ ::glMatrixMode(GL_TEXTURE);
+ ::glPopMatrix();
+ ::glMatrixMode(GL_PROJECTION);
+ ::glPopMatrix();
+ ::glMatrixMode(GL_MODELVIEW);
+ ::glPopMatrix();
+
+#else
+
+ glPopAttrib();
+#endif
+}
+
+ void
+GPC_Canvas::
+SetOrthoProjection(
+){
+ // Set up OpenGL matrices
+ ::glViewport(0, 0, m_width, m_height);
+ ::glScissor(0, 0, m_width, m_height);
+ ::glMatrixMode(GL_PROJECTION);
+ ::glLoadIdentity();
+ ::glOrtho(0, m_width, 0, m_height, -1, 1);
+ ::glMatrixMode(GL_MODELVIEW);
+ ::glLoadIdentity();
+ ::glMatrixMode(GL_TEXTURE);
+ ::glLoadIdentity();
+}
diff --git a/source/gameengine/GamePlayer/common/GPC_Canvas.h b/source/gameengine/GamePlayer/common/GPC_Canvas.h
new file mode 100644
index 00000000000..51061301b55
--- /dev/null
+++ b/source/gameengine/GamePlayer/common/GPC_Canvas.h
@@ -0,0 +1,275 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 _GPC_CANVAS_H_
+#define _GPC_CANVAS_H_
+
+#include "RAS_ICanvas.h"
+#include "RAS_Rect.h"
+
+#if defined(WIN32) || defined(__APPLE__)
+ #ifdef WIN32
+ #pragma warning (disable:4786) // suppress stl-MSVC debug info warning
+ #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 <map>
+
+
+class GPC_Canvas : public RAS_ICanvas
+{
+public:
+ /**
+ * Used to position banners in the canvas.
+ */
+ typedef enum {
+ alignTopLeft,
+ alignBottomRight
+ } TBannerAlignment;
+
+ typedef int TBannerId;
+
+protected:
+ /**
+ * Used to store info for banners drawn on top of the canvas.
+ */
+ typedef struct {
+ /** Where the banner will be displayed. */
+ TBannerAlignment alignment;
+ /** Banner display enabled. */
+ bool enabled;
+ /** Banner display width. */
+ unsigned int displayWidth;
+ /** Banner display height. */
+ unsigned int displayHeight;
+ /** Banner image width. */
+ unsigned int imageWidth;
+ /** Banner image height. */
+ unsigned int imageHeight;
+ /** Banner image data. */
+ unsigned char* imageData;
+ /** Banner OpenGL texture name. */
+ unsigned int textureName;
+ } TBannerData;
+ typedef std::map<TBannerId, TBannerData> TBannerMap;
+
+ /** Width of the context. */
+ int m_width;
+ /** Height of the context. */
+ int m_height;
+ /** Rect that defines the area used for rendering,
+ relative to the context */
+ RAS_Rect m_displayarea;
+
+ /** Storage for the banners to display. */
+ TBannerMap m_banners;
+ /** State of banner display. */
+ bool m_bannersEnabled;
+
+public:
+
+ GPC_Canvas(int width, int height);
+
+ virtual ~GPC_Canvas();
+
+ void Resize(int width, int height);
+
+
+ /**
+ * @section Methods inherited from abstract base class RAS_ICanvas.
+ */
+
+ int
+ GetWidth(
+ ) const {
+ return m_width;
+ }
+
+ int
+ GetHeight(
+ ) const {
+ return m_height;
+ }
+
+ const
+ RAS_Rect &
+ GetDisplayArea(
+ ) const {
+ return m_displayarea;
+ };
+
+ RAS_Rect &
+ GetDisplayArea(
+ ) {
+ return m_displayarea;
+ };
+
+ void
+ BeginFrame(
+ ) {};
+
+ /**
+ * Draws overlay banners and progress bars.
+ */
+ void
+ EndFrame(
+ );
+
+ void SetViewPort(int x1, int y1, int x2, int y2);
+
+ void ClearColor(float r, float g, float b, float a);
+
+ /**
+ * @section Methods inherited from abstract base class RAS_ICanvas.
+ * Semantics are not yet honoured.
+ */
+
+ void SetMouseState(RAS_MouseState mousestate)
+ {
+ // not yet
+ }
+
+ void SetMousePosition(int x, int y)
+ {
+ // not yet
+ }
+
+ void MakeScreenShot(const char* filename)
+ {
+ // not yet
+ }
+
+ void ClearBuffer(int type);
+
+ /**
+ * @section Services provided by this class.
+ */
+
+ /**
+ * Enables display of a banner.
+ * The image data is copied inside.
+ * @param bannerWidth Display width of the banner.
+ * @param bannerHeight Display height of the banner.
+ * @param imageWidth Width of the banner image in pixels.
+ * @param imageHeight Height of the banner image in pixels.
+ * @param imageData Pointer to the pixels of the image to display.
+ * @param alignement Where the banner will be positioned on the canvas.
+ * @param enabled Whether the banner will be displayed intiallly.
+ * @return A banner id.
+ */
+ TBannerId AddBanner(
+ unsigned int bannerWidth, unsigned int bannerHeight,
+ unsigned int imageWidth, unsigned int imageHeight,
+ unsigned char* imageData, TBannerAlignment alignment = alignTopLeft,
+ bool enabled = true);
+
+ /**
+ * Disposes a banner.
+ * @param id Bannner to be disposed.
+ */
+ void DisposeBanner(TBannerId id);
+
+ /**
+ * Disposes all the banners.
+ */
+ void DisposeAllBanners();
+
+ /**
+ * Enables or disables display of a banner.
+ * @param id Banner id of the banner to be enabled/disabled.
+ * @param enabled New state of the banner.
+ */
+ void SetBannerEnabled(TBannerId id, bool enabled = true);
+
+ /**
+ * Enables or disables display of all banners.
+ * @param enabled New state of the banners.
+ */
+ void SetBannerDisplayEnabled(bool enabled = true);
+
+protected:
+ /**
+ * Disposes a banner.
+ * @param it Bannner to be disposed.
+ */
+ void DisposeBanner(TBannerData& banner);
+
+ /**
+ * Draws all the banners enabled.
+ */
+ void DrawAllBanners(void);
+
+ /**
+ * Draws a banner.
+ */
+ void DrawBanner(TBannerData& banner);
+
+ struct CanvasRenderState {
+ int oldLighting;
+ int oldDepthTest;
+ int oldFog;
+ int oldTexture2D;
+ int oldBlend;
+ int oldBlendSrc;
+ int oldBlendDst;
+ float oldColor[4];
+ int oldWriteMask;
+ };
+
+ void
+ PushRenderState(
+ CanvasRenderState & render_state
+ );
+ void
+ PopRenderState(
+ const CanvasRenderState & render_state
+ );
+
+ /**
+ * Set up an orthogonal viewing,model and texture matrix
+ * for banners and progress bars.
+ */
+ void
+ SetOrthoProjection(
+ );
+
+ static TBannerId s_bannerId;
+};
+
+#endif // _GPC_CANVAS_H_
diff --git a/source/gameengine/GamePlayer/common/GPC_Engine.cpp b/source/gameengine/GamePlayer/common/GPC_Engine.cpp
new file mode 100644
index 00000000000..8c54362e17a
--- /dev/null
+++ b/source/gameengine/GamePlayer/common/GPC_Engine.cpp
@@ -0,0 +1,337 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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) // suppress stl-MSVC debug info warning
+#endif // WIN32
+
+#include <iostream>
+
+#include "BKE_blender.h" // initglobals()
+#include "BKE_global.h" // Global G
+#include "DNA_scene_types.h"
+#include "DNA_camera_types.h" // Camera
+#include "DNA_object_types.h" // Object
+
+#include "BLO_readfile.h"
+#include "BLI_blenlib.h"
+
+// include files needed by "KX_BlenderSceneConverter.h"
+
+#include "GEN_Map.h"
+#include "SCA_IActuator.h"
+#include "RAS_MeshObject.h"
+
+#include "KX_BlenderSceneConverter.h"
+#include "KX_KetsjiEngine.h"
+#include "NG_LoopBackNetworkDeviceInterface.h"
+
+#include "RAS_IRenderTools.h"
+#include "SND_DeviceManager.h"
+
+#include "GPC_Engine.h"
+#include "GPC_KeyboardDevice.h"
+#include "GPC_MouseDevice.h"
+#include "GPC_RawImage.h"
+#include "GPC_RawLoadDotBlendArray.h"
+
+
+
+GPC_Engine::GPC_Engine(char *customLoadingAnimationURL,
+ int foregroundColor, int backgroundColor, int frameRate) :
+ m_initialized(false), m_running(false), m_loading(false),
+ m_customLoadingAnimation(false), m_previousProgress(0.0),
+ m_system(NULL), m_keyboarddev(NULL),
+ m_mousedev(NULL), m_canvas(NULL), m_rendertools(NULL),
+ m_portal(NULL), m_sceneconverter(NULL), m_networkdev(NULL),
+ m_audiodevice(NULL), m_curarea(NULL),
+ m_customLoadingAnimationURL(NULL),
+ m_foregroundColor(foregroundColor), m_backgroundColor(backgroundColor),
+ m_frameRate(frameRate),
+ m_BlenderLogo(0), m_Blender3DLogo(0)/*, m_NaNLogo(0)*/
+{
+ if(customLoadingAnimationURL[0] != '\0')
+ {
+ m_customLoadingAnimationURL = new char[sizeof(customLoadingAnimationURL)];
+// not yet, need to be implemented first... m_customLoadingAnimation = true;
+ }
+
+ // load the Blender logo into memory
+ m_BlenderLogo = new GPC_RawImage();
+ // blender3d size is 115 x 32 so make resulting texture 128 x 128
+ if(!m_BlenderLogo->Load("BlenderLogo", 128, 128, GPC_RawImage::alignTopLeft, 8, 8))
+ m_BlenderLogo = 0;
+
+ // load the Blender3D logo into memory
+ m_Blender3DLogo = new GPC_RawImage();
+ // blender3d size is 136 x 11 so make resulting texture 256 x 256
+ if(!m_Blender3DLogo->Load("Blender3DLogo", 256, 256, GPC_RawImage::alignBottomRight, 8, 8))
+ m_Blender3DLogo = 0;
+
+#if 0
+ // obsolete logo
+ // load the NaN logo into memory
+ m_NaNLogo = new GPC_RawImage();
+ // blender3d size is 32 x 31 so make resulting texture 64 x 64
+ if(!m_NaNLogo->Load("NaNLogo", 64, 64, GPC_RawImage::alignBottomRight, 8, 8))
+ m_NaNLogo = 0;
+#endif
+}
+
+
+GPC_Engine::~GPC_Engine()
+{
+ // deleting everything in reverse order of creation
+#if 0
+// hmm deleted in Stop() delete m_portal;
+// hmm deleted in Stop() delete m_sceneconverter;
+ delete m_system;
+ delete m_networkdev;
+ delete m_rendertools;
+ delete m_canvas;
+ delete m_mousedev;
+ delete m_keyboarddev;
+// not yet used so be careful and not delete them
+// delete m_WaveCache;
+// delete m_curarea; // for future use, not used yet
+#endif
+ delete m_BlenderLogo;
+ delete m_Blender3DLogo;
+#if 0
+ delete m_NaNLogo;
+#endif
+}
+
+
+bool GPC_Engine::Start(char *filename)
+{
+ BlendReadError error;
+ BlendFileData *bfd= BLO_read_from_file(filename, &error);
+
+ if (!bfd) {
+ // XXX, deal with error here
+ cout << "Unable to load: " << filename << endl;
+ return false;
+ }
+
+ StartKetsji();
+
+ if(bfd->type == BLENFILETYPE_PUB)
+ m_canvas->SetBannerDisplayEnabled(false);
+
+ return true;
+}
+
+
+bool GPC_Engine::Start(unsigned char *blenderDataBuffer,
+ unsigned int blenderDataBufferSize)
+{
+ BlendReadError error;
+ BlendFileData *bfd= BLO_read_from_memory(blenderDataBuffer, blenderDataBufferSize, &error);
+
+ if (!bfd) {
+ // XXX, deal with error here
+ cout << "Unable to load. " << endl;
+ return false;
+ }
+
+ StartKetsji();
+
+ if(bfd->type == BLENFILETYPE_PUB)
+ m_canvas->SetBannerDisplayEnabled(false);
+
+ return true;
+}
+
+
+bool GPC_Engine::StartKetsji(void)
+{
+ STR_String startSceneName = G.scene->id.name + 2;
+/*
+ KX_KetsjiEngine* ketsjieng = new KX_KetsjiEngine(m_system);
+ m_portal = new KetsjiPortal(ketsjieng);
+ m_portal->setSecurity(psl_Highest);
+
+ KX_ISceneConverter *sceneconverter = new KX_BlenderSceneConverter(G.main, ketsjieng);
+
+ m_portal->Enter(
+ startSceneName,
+ sceneconverter,
+ m_canvas,
+ m_rendertools,
+ m_keyboarddev,
+ m_mousedev,
+ m_networkdev,
+ m_audiodevice,
+ m_system);
+
+ m_system->SetMainLoop(m_portal->m_ketsjieng);
+
+ m_running = true;
+ */
+ return true;
+}
+
+
+void GPC_Engine::StartLoadingAnimation()
+{
+ if(m_customLoadingAnimation)
+ {
+ }
+ else
+ {
+ unsigned char *blenderDataBuffer;
+ int blenderDataBufferSize;
+ GetRawLoadingAnimation(&blenderDataBuffer, &blenderDataBufferSize);
+ if(!Start(blenderDataBuffer, blenderDataBufferSize))
+ cout << "something went wrong when starting the engine" << endl;
+ delete blenderDataBuffer; // created with 'new' in GetRawLoadingAnimation()
+ }
+}
+
+
+// will be platform dependant
+float GPC_Engine::DetermineProgress(void)
+{
+#if 0
+ float progress;
+ if ((m_blenderData.m_ulProgress > 0) &&
+ (m_blenderData.m_ulProgressMax != m_blenderData.m_ulProgress)) {
+ progress = (float)m_blenderData.m_ulProgress;
+ progress /= (float)m_blenderData.m_ulProgressMax;
+ }
+ else {
+ progress = 0.f;
+ }
+ progress *= 100.f;
+ return (unsigned int) progress ;
+#endif
+ return m_previousProgress + 0.01; // temporary TODO
+}
+
+
+void GPC_Engine::UpdateLoadingAnimation(void)
+{
+ int delta;
+
+ float progress = DetermineProgress();
+
+ if(progress > m_previousProgress)
+ {
+ delta = progress - m_previousProgress;
+ m_previousProgress = progress;
+ if(m_previousProgress > 1.0)
+ m_previousProgress = 1.0; // limit to 1.0 (has to change !)
+// m_engine->m_previousProgress = 0.0;
+ }
+
+ STR_String to = "";
+ STR_String from = "";
+ STR_String subject = "progress";
+ STR_String body;
+ body.Format("%f", progress); // a number between 0.0 and 1.0
+
+ if(m_networkdev)
+ {
+ // Store a progress message in the network device.
+ NG_NetworkMessage* msg = new NG_NetworkMessage(to, from, subject, body);
+ m_networkdev->SendNetworkMessage(msg);
+ msg->Release();
+ }
+}
+
+
+void GPC_Engine::Stop()
+{
+ // only delete things that are created in StartKetsji()
+/* if(m_portal)
+ {
+ m_portal->Leave();
+ delete m_portal; // also gets rid of KX_KetsjiEngine (says Maarten)
+ m_portal = 0;
+ }
+*/ if(m_sceneconverter)
+ {
+ delete m_sceneconverter;
+ m_sceneconverter = 0;
+ }
+#if 0
+ if(m_frameTimerID)
+ {
+ ::KillTimer(0, m_frameTimerID);
+ m_frameTimerID = 0;
+ }
+ m_engineRunning = false;
+#endif
+
+ m_running = false;
+}
+
+
+void GPC_Engine::Exit()
+{
+ if(m_running)
+ Stop();
+
+ if (m_system) {
+ delete m_system;
+ m_system = 0;
+ }
+ if (m_keyboarddev) {
+ delete m_keyboarddev;
+ m_keyboarddev = 0;
+ }
+ if (m_mousedev) {
+ delete m_mousedev;
+ m_mousedev = 0;
+ }
+ if (m_canvas) {
+ delete m_canvas;
+ m_canvas = 0;
+ }
+ if (m_rendertools) {
+ delete m_rendertools;
+ m_rendertools = 0;
+ }
+ if (m_networkdev) {
+ delete m_networkdev;
+ m_networkdev = 0;
+ }
+
+ if (m_audiodevice)
+ {
+ SND_DeviceManager::Unsubscribe();
+ m_audiodevice = 0;
+ }
+
+ m_initialized = false;
+}
+
diff --git a/source/gameengine/GamePlayer/common/GPC_Engine.h b/source/gameengine/GamePlayer/common/GPC_Engine.h
new file mode 100644
index 00000000000..ccf2997eba6
--- /dev/null
+++ b/source/gameengine/GamePlayer/common/GPC_Engine.h
@@ -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 *****
+ */
+
+#ifndef __GPC_ENGINE_H
+#define __GPC_ENGINE_H
+
+
+#include "GPC_Canvas.h"
+#include "GPC_System.h"
+
+class GPC_KeyboardDevice;
+class GPC_MouseDevice;
+
+class RAS_IRenderTools;
+class KetsjiPortal;
+class KX_ISceneConverter;
+class NG_LoopBackNetworkDeviceInterface;
+class SND_IAudioDevice;
+class GPC_RawImage;
+
+
+class GPC_Engine
+{
+//protected:
+public:
+ /** Engine construction state. */
+ bool m_initialized;
+ /** Engine state. */
+ bool m_running;
+ /** loading state, ie a file is requested and is being loaded. Different
+ * from initialized and/or running */
+ bool m_loading;
+
+ bool m_customLoadingAnimation;
+
+ /** Last file download progress measurement. */
+ float m_previousProgress;
+
+ /** The game engine's system abstraction. */
+ GPC_System* m_system;
+ /** The game engine's keyboard abstraction. */
+ GPC_KeyboardDevice* m_keyboarddev;
+ /** The game engine's mouse abstraction. */
+ GPC_MouseDevice* m_mousedev;
+ /** The game engine's canvas abstraction. */
+ GPC_Canvas* m_canvas;
+ /** The game engine's platform dependent render tools. */
+ RAS_IRenderTools* m_rendertools;
+ /** The portal used to start the engine. */
+ KetsjiPortal* m_portal;
+ /** Converts Blender data files. */
+ KX_ISceneConverter* m_sceneconverter;
+ /** Network interface. */
+ NG_LoopBackNetworkDeviceInterface* m_networkdev;
+ /** Audiodevice interface */
+ SND_IAudioDevice* m_audiodevice;
+
+ struct ScrArea *m_curarea; // for future use, not used yet
+
+ char *m_customLoadingAnimationURL;
+ int m_foregroundColor;
+ int m_backgroundColor;
+ int m_frameRate;
+
+ GPC_RawImage *m_BlenderLogo;
+ GPC_Canvas::TBannerId m_BlenderLogoId;
+ GPC_RawImage *m_Blender3DLogo;
+ GPC_Canvas::TBannerId m_Blender3DLogoId;
+#if 0
+ GPC_RawImage *m_NaNLogo;
+ GPC_Canvas::TBannerId m_NaNLogoId;
+#endif
+
+public:
+ GPC_Engine(char *customLoadingAnimation,
+ int foregroundColor, int backgroundColor, int frameRate);
+ ~GPC_Engine();
+ // Initialize() functions are not put here since they have
+ // different prototypes for Unix and Windows
+ void StartLoadingAnimation();
+ bool Start(char *filename); // file-on-disk starter
+ bool Start(unsigned char *blenderDataBuffer,
+ unsigned int blenderDataBufferSize); // file-in-memory starter
+
+ void Stop();
+ virtual void Exit();
+
+ bool Initialized(void) {return m_initialized;}
+ bool Loading(void) {return m_loading;}
+ bool Running(void) const {return m_running;}
+
+ virtual float DetermineProgress(void); // will be platform dependant
+ void UpdateLoadingAnimation(void);
+
+private:
+ bool StartKetsji(void);
+
+};
+
+
+#endif // __GPC_ENGINE_H
diff --git a/source/gameengine/GamePlayer/common/GPC_KeyboardDevice.cpp b/source/gameengine/GamePlayer/common/GPC_KeyboardDevice.cpp
new file mode 100644
index 00000000000..7cd1e48f9b3
--- /dev/null
+++ b/source/gameengine/GamePlayer/common/GPC_KeyboardDevice.cpp
@@ -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 *****
+ */
+
+#include <iostream.h>
+#include "GPC_KeyboardDevice.h"
+
+
+/**
+ * NextFrame toggles currentTable with previousTable,
+ * and copies relevant event information from previous to current table
+ * (pressed keys need to be remembered).
+ */
+void GPC_KeyboardDevice::NextFrame()
+{
+ SCA_IInputDevice::NextFrame();
+
+ // Now convert justpressed key events into regular (active) keyevents
+ int previousTable = 1-m_currentTable;
+ for (int keyevent= KX_BEGINKEY; keyevent< KX_ENDKEY;keyevent++)
+ {
+ SCA_InputEvent& oldevent = m_eventStatusTables[previousTable][keyevent];
+ if (oldevent.m_status == SCA_InputEvent::KX_JUSTACTIVATED ||
+ oldevent.m_status == SCA_InputEvent::KX_ACTIVE )
+ {
+ m_eventStatusTables[m_currentTable][keyevent] = oldevent;
+ m_eventStatusTables[m_currentTable][keyevent].m_status = SCA_InputEvent::KX_ACTIVE;
+ //m_eventStatusTables[m_currentTable][keyevent].m_status = SCA_InputEvent::KX_JUSTACTIVATED ;
+ }
+ }
+}
+
+
+
+/**
+ * ConvertBPEvent translates Windows keyboard events into ketsji kbd events.
+ * Extra event information is stored, like ramp-mode (just released/pressed)
+ */
+bool GPC_KeyboardDevice::ConvertEvent(int incode, int val)
+{
+ bool result = false;
+
+ // convert event
+ KX_EnumInputs kxevent = this->ToNative(incode);
+
+ // only process it, if it's a key
+ if (kxevent >= KX_BEGINKEY && kxevent < KX_ENDKEY)
+ {
+ int previousTable = 1-m_currentTable;
+
+ if (val > 0)
+ {
+ if (kxevent == SCA_IInputDevice::KX_ESCKEY && val != 0)
+ result = true;
+
+ // todo: convert val ??
+ m_eventStatusTables[m_currentTable][kxevent].m_eventval = val ; //???
+
+ switch (m_eventStatusTables[previousTable][kxevent].m_status)
+ {
+ case SCA_InputEvent::KX_JUSTACTIVATED:
+ case SCA_InputEvent::KX_ACTIVE:
+ {
+ m_eventStatusTables[m_currentTable][kxevent].m_status = SCA_InputEvent::KX_ACTIVE;
+ break;
+ }
+
+ case SCA_InputEvent::KX_NO_INPUTSTATUS:
+ default:
+ {
+ m_eventStatusTables[m_currentTable][kxevent].m_status = SCA_InputEvent::KX_JUSTACTIVATED;
+ }
+ }
+
+ } else
+ {
+
+ switch (m_eventStatusTables[previousTable][kxevent].m_status)
+ {
+ case SCA_InputEvent::KX_JUSTACTIVATED:
+ case SCA_InputEvent::KX_ACTIVE:
+ {
+ m_eventStatusTables[m_currentTable][kxevent].m_status = SCA_InputEvent::KX_JUSTRELEASED;
+ break;
+ }
+ default:
+ {
+ m_eventStatusTables[m_currentTable][kxevent].m_status = SCA_InputEvent::KX_NO_INPUTSTATUS;
+ }
+ }
+ }
+ } else {
+ exit(1);
+ }
+ return result;
+}
diff --git a/source/gameengine/GamePlayer/common/GPC_KeyboardDevice.h b/source/gameengine/GamePlayer/common/GPC_KeyboardDevice.h
new file mode 100644
index 00000000000..a247de301b9
--- /dev/null
+++ b/source/gameengine/GamePlayer/common/GPC_KeyboardDevice.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 *****
+ */
+
+#ifndef __GPC_KEYBOARDDEVICE_H
+#define __GPC_KEYBOARDDEVICE_H
+
+#ifdef WIN32
+#pragma warning (disable : 4786)
+#endif // WIN32
+
+#include "SCA_IInputDevice.h"
+
+#include <map>
+
+
+/**
+ * System independent implementation of SCA_IInputDevice.
+ * System dependent keyboard devices need only to inherit this class
+ * and fill the m_reverseKeyTranslateTable key translation map.
+ * @see SCA_IInputDevice
+ */
+
+class GPC_KeyboardDevice : public SCA_IInputDevice
+{
+protected:
+
+ /**
+ * This map converts system dependent keyboard codes into Ketsji codes.
+ * System dependent keyboard codes are stored as ints.
+ */
+ std::map<int, KX_EnumInputs> m_reverseKeyTranslateTable;
+
+public:
+ GPC_KeyboardDevice()
+ {
+ }
+
+ virtual ~GPC_KeyboardDevice(void)
+ {
+ }
+
+ virtual bool IsPressed(SCA_IInputDevice::KX_EnumInputs inputcode)
+ {
+ return false;
+ }
+
+ virtual void NextFrame();
+
+ virtual KX_EnumInputs ToNative(int incode)
+ {
+ return m_reverseKeyTranslateTable[incode];
+ }
+
+ virtual bool ConvertEvent(int incode, int val);
+};
+
+
+#endif // _GPC_KEYBOARDDEVICE_H
diff --git a/source/gameengine/GamePlayer/common/GPC_MouseDevice.cpp b/source/gameengine/GamePlayer/common/GPC_MouseDevice.cpp
new file mode 100644
index 00000000000..a6ce7b3ae0d
--- /dev/null
+++ b/source/gameengine/GamePlayer/common/GPC_MouseDevice.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 *****
+ */
+
+#include "GPC_MouseDevice.h"
+
+
+GPC_MouseDevice::GPC_MouseDevice()
+{
+
+}
+GPC_MouseDevice::~GPC_MouseDevice()
+{
+
+}
+
+/**
+ * IsPressed gives boolean information about mouse status, true if pressed, false if not.
+ */
+bool GPC_MouseDevice::IsPressed(SCA_IInputDevice::KX_EnumInputs inputcode)
+{
+ const SCA_InputEvent & inevent = m_eventStatusTables[m_currentTable][inputcode];
+ bool pressed = (inevent.m_status == SCA_InputEvent::KX_JUSTACTIVATED ||
+ inevent.m_status == SCA_InputEvent::KX_ACTIVE);
+ return pressed;
+}
+
+
+/**
+ * NextFrame toggles currentTable with previousTable,
+ * and copies relevant event information from previous to current table
+ * (pressed keys need to be remembered).
+ */
+void GPC_MouseDevice::NextFrame()
+{
+ SCA_IInputDevice::NextFrame();
+
+ // Convert just pressed events into regular (active) events
+ int previousTable = 1-m_currentTable;
+ for (int mouseevent= KX_BEGINMOUSE; mouseevent< KX_ENDMOUSEBUTTONS; mouseevent++) {
+ SCA_InputEvent& oldevent = m_eventStatusTables[previousTable][mouseevent];
+ if (oldevent.m_status == SCA_InputEvent::KX_JUSTACTIVATED ||
+ oldevent.m_status == SCA_InputEvent::KX_ACTIVE) {
+ m_eventStatusTables[m_currentTable][mouseevent] = oldevent;
+ m_eventStatusTables[m_currentTable][mouseevent].m_status = SCA_InputEvent::KX_ACTIVE;
+ }
+ }
+ for (int mousemove= KX_ENDMOUSEBUTTONS; mousemove< KX_ENDMOUSE; mousemove++) {
+ SCA_InputEvent& oldevent = m_eventStatusTables[previousTable][mousemove];
+ m_eventStatusTables[m_currentTable][mousemove] = oldevent;
+ if (oldevent.m_status == SCA_InputEvent::KX_JUSTACTIVATED ||
+ oldevent.m_status == SCA_InputEvent::KX_ACTIVE) {
+ m_eventStatusTables[m_currentTable][mousemove].m_status = SCA_InputEvent::KX_JUSTRELEASED;
+ }
+ else {
+ if (oldevent.m_status == SCA_InputEvent::KX_JUSTRELEASED) {
+ m_eventStatusTables[m_currentTable][mousemove].m_status = SCA_InputEvent::KX_NO_INPUTSTATUS ;
+ }
+ }
+ }
+}
+
+
+bool GPC_MouseDevice::ConvertButtonEvent(TButtonId button, bool isDown)
+{
+ bool result = false;
+
+ switch (button)
+ {
+ case buttonLeft:
+ result = ConvertEvent(KX_LEFTMOUSE, isDown);
+ break;
+ case buttonMiddle:
+ result = ConvertEvent(KX_MIDDLEMOUSE, isDown);
+ break;
+ case buttonRight:
+ result = ConvertEvent(KX_RIGHTMOUSE, isDown);
+ break;
+ default:
+ // Should not happen!
+ break;
+ }
+
+ return result;
+}
+
+/**
+ * Splits combined button and x,y cursor move events into separate Ketsji
+ * x and y move and button events.
+ */
+bool GPC_MouseDevice::ConvertButtonEvent(TButtonId button, bool isDown, int x, int y)
+{
+ // First update state tables for cursor move.
+ bool result = ConvertMoveEvent(x, y);
+
+ // Now update for button state.
+ if (result) {
+ result = ConvertButtonEvent(button, isDown);
+ }
+
+ return result;
+}
+
+/**
+ * Splits combined x,y move into separate Ketsji x and y move events.
+ */
+bool GPC_MouseDevice::ConvertMoveEvent(int x, int y)
+{
+ bool result;
+
+ // Convert to local coordinates?
+ result = ConvertEvent(KX_MOUSEX, x);
+ if (result) {
+ result = ConvertEvent(KX_MOUSEY, y);
+ }
+
+ return result;
+}
+
+
+bool GPC_MouseDevice::ConvertEvent(KX_EnumInputs kxevent, int eventval)
+{
+ bool result = true;
+
+ // Only process it, if it's a mouse event
+ if (kxevent > KX_BEGINMOUSE && kxevent < KX_ENDMOUSE) {
+ int previousTable = 1-m_currentTable;
+
+ if (eventval > 0) {
+ m_eventStatusTables[m_currentTable][kxevent].m_eventval = eventval;
+
+ switch (m_eventStatusTables[previousTable][kxevent].m_status)
+ {
+ case SCA_InputEvent::KX_ACTIVE:
+ case SCA_InputEvent::KX_JUSTACTIVATED:
+ {
+ m_eventStatusTables[m_currentTable][kxevent].m_status = SCA_InputEvent::KX_ACTIVE;
+ break;
+ }
+ case SCA_InputEvent::KX_JUSTRELEASED:
+ {
+ if ( kxevent > KX_BEGINMOUSEBUTTONS && kxevent < KX_ENDMOUSEBUTTONS)
+ {
+ m_eventStatusTables[m_currentTable][kxevent].m_status = SCA_InputEvent::KX_JUSTACTIVATED;
+ } else
+ {
+ m_eventStatusTables[m_currentTable][kxevent].m_status = SCA_InputEvent::KX_ACTIVE;
+
+ }
+ break;
+ }
+ default:
+ {
+ m_eventStatusTables[m_currentTable][kxevent].m_status = SCA_InputEvent::KX_JUSTACTIVATED;
+ }
+ }
+
+ }
+ else {
+ switch (m_eventStatusTables[previousTable][kxevent].m_status)
+ {
+ case SCA_InputEvent::KX_JUSTACTIVATED:
+ case SCA_InputEvent::KX_ACTIVE:
+ {
+ m_eventStatusTables[m_currentTable][kxevent].m_status = SCA_InputEvent::KX_JUSTRELEASED;
+ break;
+ }
+ default:
+ {
+ m_eventStatusTables[m_currentTable][kxevent].m_status = SCA_InputEvent::KX_NO_INPUTSTATUS;
+ }
+ }
+ }
+ }
+ else {
+ result = false;
+ }
+ return result;
+}
diff --git a/source/gameengine/GamePlayer/common/GPC_MouseDevice.h b/source/gameengine/GamePlayer/common/GPC_MouseDevice.h
new file mode 100644
index 00000000000..51e3339a063
--- /dev/null
+++ b/source/gameengine/GamePlayer/common/GPC_MouseDevice.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 __GPC_MOUSE_DEVICE_H
+#define __GPC_MOUSE_DEVICE_H
+
+#ifdef WIN32
+#pragma warning (disable : 4786)
+#endif // WIN32
+
+#include "SCA_IInputDevice.h"
+
+
+/**
+ * Generic Ketsji mouse device.
+ * @see SCA_IInputDevice
+ */
+class GPC_MouseDevice : public SCA_IInputDevice
+{
+public:
+ /**
+ * Button identifier.
+ */
+ typedef enum {
+ buttonLeft,
+ buttonMiddle,
+ buttonRight
+ } TButtonId;
+
+ GPC_MouseDevice();
+ virtual ~GPC_MouseDevice(void);
+
+ virtual bool IsPressed(SCA_IInputDevice::KX_EnumInputs inputcode);
+ virtual void NextFrame();
+
+ /**
+ * Call this routine to update the mouse device when a button state changes.
+ * @param button Which button state changes.
+ * @param isDown The new state of the button.
+ * @param x Position x-coordinate of the cursor at the time of the state change.
+ * @param y Position y-coordinate of the cursor at the time of the state change.
+ * @return Indication as to whether the event was processed.
+ */
+ virtual bool ConvertButtonEvent(TButtonId button, bool isDown);
+
+ /**
+ * Call this routine to update the mouse device when a button state and
+ * cursor position changes at the same time (e.g. in Win32 messages).
+ * @param button Which button state changes.
+ * @param isDown The new state of the button.
+ * @param x Position x-coordinate of the cursor at the time of the state change.
+ * @param y Position y-coordinate of the cursor at the time of the state change.
+ * @return Indication as to whether the event was processed.
+ */
+ virtual bool ConvertButtonEvent(TButtonId button, bool isDown, int x, int y);
+
+ /**
+ * Call this routine to update the mouse device when the cursor has moved.
+ * @param x Position x-coordinate of the cursor.
+ * @param y Position y-coordinate of the cursor.
+ * @return Indication as to whether the event was processed.
+ */
+ virtual bool ConvertMoveEvent(int x, int y);
+
+protected:
+ /**
+ * This routine converts a single mouse event to a Ketsji mouse event.
+ * @param kxevent Ketsji event code.
+ * @param eventval Value for this event.
+ * @return Indication as to whether the event was processed.
+ */
+ virtual bool ConvertEvent(KX_EnumInputs kxevent, int eventval);
+};
+
+
+#endif // __GPC_MOUSE_DEVICE_H
diff --git a/source/gameengine/GamePlayer/common/GPC_PolygonMaterial.cpp b/source/gameengine/GamePlayer/common/GPC_PolygonMaterial.cpp
new file mode 100644
index 00000000000..77488597a70
--- /dev/null
+++ b/source/gameengine/GamePlayer/common/GPC_PolygonMaterial.cpp
@@ -0,0 +1,410 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "GPC_PolygonMaterial.h"
+
+#include "MT_Vector3.h"
+
+#include "RAS_IRasterizer.h"
+
+/* This list includes only data type definitions */
+#include "DNA_object_types.h"
+#include "DNA_material_types.h"
+#include "DNA_image_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_group_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_property_types.h"
+#include "DNA_text_types.h"
+#include "DNA_sensor_types.h"
+#include "DNA_controller_types.h"
+#include "DNA_actuator_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_world_types.h"
+
+#include "BKE_global.h"
+#include "BKE_image.h"
+#include "BKE_mesh.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "IMB_imbuf_types.h"
+/* end of blender include block */
+
+#ifdef WIN32
+#include <windows.h>
+#endif // WIN32
+#include "GL/gl.h"
+#include "GL/glu.h"
+
+static Image *fCurpage=0;
+static int fCurtile=0, fCurmode=0, fCurTileXRep=0, fCurTileYRep=0;
+static short fTexWindx, fTexWindy, fTexWinsx, fTexWinsy;
+static int fDoMipMap = 1;
+static int fLinearMipMap=1;
+static int fAlphamode= -1;
+
+ /* (n&(n-1)) zeros the least significant bit of n */
+static int is_pow2(int num) {
+ return ((num)&(num-1))==0;
+}
+static int smaller_pow2(int num) {
+ while (!is_pow2(num))
+ num= num&(num-1);
+ return num;
+}
+
+static void my_make_repbind(Image *ima)
+{
+ if(ima==0 || ima->ibuf==0) return;
+
+ if(ima->repbind) {
+ glDeleteTextures(ima->totbind, (GLuint*)ima->repbind);
+ delete (ima->repbind);
+ ima->repbind= 0;
+ }
+ ima->totbind= ima->xrep*ima->yrep;
+ if(ima->totbind>1) {
+ ima->repbind= (unsigned int *) malloc(sizeof(int)*ima->totbind);
+ for (int i=0;i<ima->totbind;i++)
+ ((int*)ima->repbind)[i] = 0;
+ }
+}
+
+
+int my_set_tpage(TFace *tface)
+{
+ static TFace *lasttface= 0;
+ Image *ima;
+ unsigned int *rect, *bind;
+ int tpx, tpy, tilemode, tileXRep,tileYRep;
+
+ /* afschakelen */
+ if(tface==0) {
+ if(lasttface==0) return 0;
+
+ lasttface= 0;
+ fCurtile= 0;
+ fCurpage= 0;
+ if(fCurmode!=0) {
+ glMatrixMode(GL_TEXTURE);
+ glLoadIdentity();
+ glMatrixMode(GL_MODELVIEW);
+ }
+ fCurmode= 0;
+ fCurTileXRep=0;
+ fCurTileYRep=0;
+ fAlphamode= -1;
+
+ glDisable(GL_BLEND);
+ glDisable(GL_TEXTURE_2D);
+ glDisable(GL_TEXTURE_GEN_S);
+ glDisable(GL_TEXTURE_GEN_T);
+ return 0;
+ }
+ lasttface= tface;
+
+ if( fAlphamode != tface->transp) {
+ fAlphamode= tface->transp;
+
+ if(fAlphamode) {
+ glEnable(GL_BLEND);
+
+ if(fAlphamode==TF_ADD) {
+ glBlendFunc(GL_ONE, GL_ONE);
+ /* glBlendEquationEXT(GL_FUNC_ADD_EXT); */
+ }
+ else if(fAlphamode==TF_ALPHA) {
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ /* glBlendEquationEXT(GL_FUNC_ADD_EXT); */
+ }
+ /* else { */
+ /* glBlendFunc(GL_ONE, GL_ONE); */
+ /* glBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT); */
+ /* } */
+ }
+ else glDisable(GL_BLEND);
+ }
+
+ ima= (struct Image *) tface->tpage;
+
+ /* Enable or disable environment mapping */
+ if (ima && (ima->flag & IMA_REFLECT)){
+
+ glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
+ glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
+
+ glEnable(GL_TEXTURE_GEN_S);
+ glEnable(GL_TEXTURE_GEN_T);
+ }
+ else{
+ glDisable(GL_TEXTURE_GEN_S);
+ glDisable(GL_TEXTURE_GEN_T);
+ }
+
+ tilemode= tface->mode & TF_TILES;
+ tileXRep = 0;
+ tileYRep = 0;
+ if (ima)
+ {
+ tileXRep = ima->xrep;
+ tileYRep = ima->yrep;
+ }
+
+
+ if(ima==fCurpage && fCurtile==tface->tile && tilemode==fCurmode && fCurTileXRep==tileXRep && fCurTileYRep == tileYRep) return ima!=0;
+
+ if(tilemode!=fCurmode || fCurTileXRep!=tileXRep || fCurTileYRep != tileYRep)
+ {
+ glMatrixMode(GL_TEXTURE);
+ glLoadIdentity();
+
+ if(tilemode && ima!=0)
+ glScalef(ima->xrep, ima->yrep, 1.0);
+
+ glMatrixMode(GL_MODELVIEW);
+ }
+
+ if(ima==0 || ima->ok==0) {
+ glDisable(GL_TEXTURE_2D);
+
+ fCurtile= tface->tile;
+ fCurpage= 0;
+ fCurmode= tilemode;
+ fCurTileXRep = tileXRep;
+ fCurTileYRep = tileYRep;
+
+ return 0;
+ }
+
+ if(ima->ibuf==0) {
+ load_image(ima, IB_rect, "", 0);
+
+ if(ima->ibuf==0) {
+ ima->ok= 0;
+
+ fCurtile= tface->tile;
+ fCurpage= 0;
+ fCurmode= tilemode;
+ fCurTileXRep = tileXRep;
+ fCurTileYRep = tileYRep;
+
+ glDisable(GL_TEXTURE_2D);
+ return 0;
+ }
+
+ }
+
+ if(ima->tpageflag & IMA_TWINANIM) fCurtile= ima->lastframe;
+ else fCurtile= tface->tile;
+
+ if(tilemode) {
+
+ if(ima->repbind==0) my_make_repbind(ima);
+
+ if(fCurtile>=ima->totbind) fCurtile= 0;
+
+ /* this happens when you change repeat buttons */
+ if(ima->repbind) bind= ima->repbind+fCurtile;
+ else bind= &ima->bindcode;
+
+ if(*bind==0) {
+
+ fTexWindx= ima->ibuf->x/ima->xrep;
+ fTexWindy= ima->ibuf->y/ima->yrep;
+
+ if(fCurtile>=ima->xrep*ima->yrep) fCurtile= ima->xrep*ima->yrep-1;
+
+ fTexWinsy= fCurtile / ima->xrep;
+ fTexWinsx= fCurtile - fTexWinsy*ima->xrep;
+
+ fTexWinsx*= fTexWindx;
+ fTexWinsy*= fTexWindy;
+
+ tpx= fTexWindx;
+ tpy= fTexWindy;
+
+ rect= ima->ibuf->rect + fTexWinsy*ima->ibuf->x + fTexWinsx;
+ }
+ }
+ else {
+ bind= &ima->bindcode;
+
+ if(*bind==0) {
+ tpx= ima->ibuf->x;
+ tpy= ima->ibuf->y;
+ rect= ima->ibuf->rect;
+ }
+ }
+
+ if(*bind==0) {
+ int rectw= tpx, recth= tpy;
+ unsigned int *tilerect= NULL, *scalerect= NULL;
+
+ /*
+ * Maarten:
+ * According to Ton this code is not needed anymore. It was used only
+ * in really old Blenders.
+ * Reevan:
+ * Actually it is needed for backwards compatibility. Simpledemo 6 does not display correctly without it.
+ */
+#if 1
+ if (tilemode) {
+ int y;
+
+ tilerect= (unsigned int*)MEM_mallocN(rectw*recth*sizeof(*tilerect), "tilerect");
+ for (y=0; y<recth; y++) {
+ unsigned int *rectrow= &rect[y*ima->ibuf->x];
+ unsigned int *tilerectrow= &tilerect[y*rectw];
+
+ memcpy(tilerectrow, rectrow, tpx*sizeof(*rectrow));
+ }
+
+ rect= tilerect;
+ }
+#endif
+ if (!is_pow2(rectw) || !is_pow2(recth)) {
+ rectw= smaller_pow2(rectw);
+ recth= smaller_pow2(recth);
+
+ scalerect= (unsigned int *)MEM_mallocN(rectw*recth*sizeof(*scalerect), "scalerect");
+ gluScaleImage(GL_RGBA, tpx, tpy, GL_UNSIGNED_BYTE, rect, rectw, recth, GL_UNSIGNED_BYTE, scalerect);
+ rect= scalerect;
+ }
+
+ glGenTextures(1, (GLuint*)bind);
+
+ /*
+ if(G.f & G_DEBUG) {
+ printf("var1: %s\n", ima->id.name+2);
+ printf("var1: %d, var2: %d\n", *bind, tpx);
+ printf("var1: %d, var2: %d\n", fCurtile, tilemode);
+ }
+ */
+ glBindTexture( GL_TEXTURE_2D, *bind);
+
+ if (!fDoMipMap)
+ {
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, rect);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ } else
+ {
+ int minfilter= fLinearMipMap?GL_LINEAR_MIPMAP_LINEAR:GL_LINEAR_MIPMAP_NEAREST;
+
+ gluBuild2DMipmaps(GL_TEXTURE_2D, 4, rectw, recth, GL_RGBA, GL_UNSIGNED_BYTE, rect);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minfilter);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ }
+
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+
+ if (tilerect)
+ MEM_freeN(tilerect);
+ if (scalerect)
+ MEM_freeN(scalerect);
+ }
+ else glBindTexture( GL_TEXTURE_2D, *bind);
+
+
+
+ glEnable(GL_TEXTURE_2D);
+
+ fCurpage= ima;
+ fCurmode= tilemode;
+ fCurTileXRep = tileXRep;
+ fCurTileYRep = tileYRep;
+
+ return 1;
+}
+
+
+GPC_PolygonMaterial::GPC_PolygonMaterial(const STR_String& texname, bool ba, const STR_String& matname,
+ int tile, int tileXrep, int tileYrep, int mode, int transparant,
+ int lightlayer, bool bIsTriangle, void* clientobject, void* tpage) :
+ RAS_IPolyMaterial(texname, ba, matname, tile, tileXrep, tileYrep, mode,
+ transparant, lightlayer, bIsTriangle, clientobject), m_tface((struct TFace*)tpage)
+{
+ // clear local caching info
+ my_set_tpage(0);
+}
+
+
+GPC_PolygonMaterial::~GPC_PolygonMaterial(void)
+{
+}
+
+
+void GPC_PolygonMaterial::Activate(RAS_IRasterizer* rasty, TCachingInfo& cachingInfo) const
+{
+ if (GetCachingInfo() != cachingInfo)
+ {
+ if (!cachingInfo)
+ {
+ my_set_tpage(0);
+ }
+ cachingInfo = GetCachingInfo();
+
+ if ((m_drawingmode & 4)&& (rasty->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED) )
+ {
+ update_realtime_texture((struct TFace*) m_tface, rasty->GetTime());
+ my_set_tpage(m_tface);
+ rasty->EnableTextures(true);
+ } else
+ {
+ my_set_tpage(0);
+ rasty->EnableTextures(false);
+ }
+
+ //TF_TWOSIDE == 512, todo, make this a ketsji enum
+ if(m_drawingmode & 512) {
+ rasty->SetCullFace(false);
+ }
+
+ else
+ {
+ rasty->SetCullFace(true);;//glEnable(GL_CULL_FACE);
+ //else glDisable(GL_CULL_FACE);
+ }
+ }
+ rasty->SetSpecularity(m_specular[0],m_specular[1],m_specular[2],m_specularity);
+ rasty->SetShinyness(m_shininess);
+ rasty->SetDiffuse(m_diffuse[0], m_diffuse[1],m_diffuse[2], 1.0);
+}
+
+
+void GPC_PolygonMaterial::SetMipMappingEnabled(bool enabled)
+{
+ fDoMipMap = enabled ? 1 : 0;
+}
diff --git a/source/gameengine/GamePlayer/common/GPC_PolygonMaterial.h b/source/gameengine/GamePlayer/common/GPC_PolygonMaterial.h
new file mode 100644
index 00000000000..392e27209e2
--- /dev/null
+++ b/source/gameengine/GamePlayer/common/GPC_PolygonMaterial.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 *****
+ */
+
+#ifndef __GPC_POLYGONMATERIAL
+#define __GPC_POLYGONMATERIAL
+
+#include "RAS_IPolygonMaterial.h"
+
+
+class GPC_PolygonMaterial : public RAS_IPolyMaterial
+{
+ struct TFace* m_tface;
+
+public:
+ GPC_PolygonMaterial(const STR_String& texname, bool ba, const STR_String& matname,
+ int tile, int tileXrep, int tileYrep, int mode, int transparant,
+ int lightlayer, bool bIsTriangle, void* clientobject, void* tpage);
+
+ virtual ~GPC_PolygonMaterial(void);
+
+ /**
+ * Returns the caching information for this material,
+ * This can be used to speed up the rasterizing process.
+ * @return The caching information.
+ */
+ virtual TCachingInfo GetCachingInfo(void) const;
+
+ /**
+ * Activates the material in the (OpenGL) rasterizer.
+ * On entry, the cachingInfo contains info about the last activated material.
+ * On exit, the cachingInfo should contain updated info about this material.
+ * @param rasty The rasterizer in which the material should be active.
+ * @param cachingInfo The information about the material used to speed up rasterizing.
+ */
+ virtual void Activate(RAS_IRasterizer* rasty, TCachingInfo& cachingInfo) const;
+
+ /**
+ * Returns the Blender texture face structure that is used for this material.
+ * @return The material's texture face.
+ */
+ TFace* GetTFace(void) const;
+
+ static void SetMipMappingEnabled(bool enabled = false);
+};
+
+
+inline TFace* GPC_PolygonMaterial::GetTFace(void) const
+{
+ return m_tface;
+}
+
+inline GPC_PolygonMaterial::TCachingInfo GPC_PolygonMaterial::GetCachingInfo(void) const
+{
+ return GetTFace();
+}
+
+
+#endif // __GPC_POLYGONMATERIAL_H
diff --git a/source/gameengine/GamePlayer/common/GPC_RawImage.cpp b/source/gameengine/GamePlayer/common/GPC_RawImage.cpp
new file mode 100644
index 00000000000..0a4b6ff3df6
--- /dev/null
+++ b/source/gameengine/GamePlayer/common/GPC_RawImage.cpp
@@ -0,0 +1,135 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 <iostream>
+#include <string.h>
+
+#include "GPC_RawImage.h"
+
+#include "GPC_RawLogoArrays.h"
+
+
+GPC_RawImage::GPC_RawImage()
+ : m_data(0), m_dataSize(0), m_width(0), m_height(0)
+{
+}
+
+
+bool GPC_RawImage::Load(
+ char *srcName,
+ int destWidth, int destHeight,
+ TImageAlignment alignment, int offsetX, int offsetY)
+{
+ int srcWidth, srcHeight;
+ bool success = true;
+ if(strcmp(srcName, "BlenderLogo") == 0)
+ GetRawBlenderLogo(&m_data, &srcWidth, &srcHeight);
+ else
+ if(strcmp(srcName, "Blender3DLogo") == 0)
+ GetRawBlender3DLogo(&m_data, &srcWidth, &srcHeight);
+#if 0
+ else
+ if(strcmp(srcName, "NaNLogo") == 0)
+ GetRawNaNLogo(&m_data, &srcWidth, &srcHeight);
+#endif
+ else // unknown image
+ success = false;
+
+ if(success)
+ {
+ unsigned char *tempData = m_data;
+
+ int numBytes = destWidth * destHeight * 4;
+ m_data = new unsigned char[numBytes]; // re-use m_data ('unsigned char' was 'char')
+ if(m_data)
+ {
+ ::memset(m_data, 0x00000000, numBytes);
+ m_width = destWidth;
+ m_height = destHeight;
+
+ int srcBytesWidth = srcWidth * 4;
+ int dstBytesWidth = m_width * 4;
+ int numRows = (srcHeight + offsetY) < m_height ? srcHeight : m_height - offsetY;
+ numBytes = (srcWidth + offsetX) < m_width ? srcBytesWidth : (m_width - offsetX) * 4;
+
+ if((offsetX < m_width) && (offsetY < m_height))
+ {
+ unsigned char* src = (unsigned char*)tempData;
+ unsigned char* dst = (unsigned char*)m_data;
+ if(alignment == alignTopLeft)
+ {
+ // Put original in upper left corner
+
+ // Add vertical offset
+ dst += offsetY * dstBytesWidth;
+ // Add horizontal offset
+ dst += offsetX * 4;
+ for (int row = 0; row < numRows; row++)
+ {
+ ::memcpy(dst, src, numBytes);
+ src += srcBytesWidth;
+ dst += dstBytesWidth;
+ }
+ }
+ else
+ {
+ // Put original in lower right corner
+
+ // Add vertical offset
+ dst += (m_height - (srcHeight + offsetY)) * dstBytesWidth;
+ // Add horizontal offset
+ if (m_width > (srcWidth + offsetX)) {
+ dst += (m_width - (srcWidth + offsetX)) * 4;
+ }
+ else {
+ src += (srcWidth + offsetX - m_width) * 4;
+ }
+ for (int row = 0; row < numRows; row++) {
+ ::memcpy(dst, src, numBytes);
+ src += srcBytesWidth;
+ dst += dstBytesWidth;
+ }
+ }
+ }
+// doesn't compile under Linux delete [] tempData;
+ delete tempData;
+ }
+ else {
+ // Allocation failed, restore old data
+ m_data = tempData;
+ success = false;
+ }
+ }
+
+ return success;
+}
+
diff --git a/source/gameengine/GamePlayer/common/GPC_RawImage.h b/source/gameengine/GamePlayer/common/GPC_RawImage.h
new file mode 100644
index 00000000000..ac9dad77d2f
--- /dev/null
+++ b/source/gameengine/GamePlayer/common/GPC_RawImage.h
@@ -0,0 +1,122 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 __GPC_RAWIMAGE_H__
+#define __GPC_RAWIMAGE_H__
+
+/**
+ * This memory resource reads images from the application resources.
+ * Images are expected to be stored as raw RGBA bytes.
+ * You can generate these images by exporting images with an alpha
+ * channel from Photoshop in RAW format with interleaved channels.
+ */
+
+class GPC_RawImage
+{
+public:
+ GPC_RawImage();
+
+ typedef enum {
+ alignTopLeft,
+ alignBottomRight
+ } TImageAlignment;
+
+ /**
+ * Loads the image form the resource into memory.
+ * Converts size of the image and places it with given alignment.
+ * @param hInstApp The application's instance (location of the resources).
+ * @param lpName Name of the resource.
+ * @param lpType Type of the resource.
+ * @param srcWidth The width of the resource image.
+ * @param srcHeight The height of the resource image.
+ * @param width The width of the image created.
+ * @param height The height of the image created.
+ * @param alignment How the resource image is located in the image created.
+ * @param offsetX Amount of horzontal offset applied to the resource image.
+ * @param offsetY Amount of vertical offset applied to the resource image.
+ */
+ virtual bool Load(char *srcName,
+ int destWidth, int destHeight,
+ TImageAlignment alignment = alignTopLeft,
+ int offsetX = 0, int offsetY = 0);
+
+ /**
+ * Returns the width of the image.
+ * @return The width of the image.
+ */
+ virtual int Width() const
+ {
+ return m_width;
+ }
+
+ /**
+ * Returns the height of the image.
+ * @return The height of the image.
+ */
+ virtual int Height() const
+ {
+ return m_height;
+ }
+
+ /**
+ * Returns a pointer to the data loaded from the resource.
+ * @return A pointer to the data loaded from the resource.
+ */
+ virtual unsigned char *Data() const
+ {
+ return m_data;
+ }
+
+ /**
+ * Returns the size of the data loaded from the resource.
+ * @return The size of the loaded from the resource.
+ */
+ virtual int DataSize() const
+ {
+ return m_dataSize;
+ }
+
+protected:
+ /**
+ * Disposes the data stored at the m_data member.
+ */
+// virtual void disposeData(void);
+
+protected:
+ unsigned char *m_data;
+ int m_dataSize;
+ int m_width;
+ int m_height;
+};
+
+
+#endif // __GPC_RAWIMAGE_H__
diff --git a/source/gameengine/GamePlayer/common/GPC_RawLoadDotBlendArray.cpp b/source/gameengine/GamePlayer/common/GPC_RawLoadDotBlendArray.cpp
new file mode 100644
index 00000000000..6ab2f1220e5
--- /dev/null
+++ b/source/gameengine/GamePlayer/common/GPC_RawLoadDotBlendArray.cpp
@@ -0,0 +1,9312 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+// This file is automatically generated. Do not edit by hand!
+
+
+
+#include "GPC_RawLoadDotBlendArray.h"
+
+
+void GetRawLoadingAnimation(unsigned char **data, int *dataSize)
+{
+ // create an array that will automatically be deleted when)
+ // we're outta this scope
+ static unsigned char load_blend[]= { 66, 76, 69, 78, 68, 70,
+ 73, 10, 0, 2, 21, 0, 0, 2, 22, 0, 0, 0, 0, 0, 0,
+ 2, 30, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 65, 25, 242, 2, 0, 2, 29, 253, 0, 0, 0, 4, 160, 249, 227,
+ 5, 65, 25, 242, 2, 0, 2, 29, 237, 0, 0, 0, 10, 39, 161,
+ 89, 128, 65, 248, 18, 0, 0, 2, 28, 205, 179, 76, 248, 13, 9,
+ 10, 156, 188, 58, 101, 43, 138, 63, 142, 132, 111, 231, 106, 44, 72,
+ 171, 116, 148, 204, 204, 104, 121, 88, 224, 36, 141, 195, 251, 160, 141,
+ 162, 12, 177, 93, 203, 236, 68, 235, 2, 137, 27, 34, 49, 52, 25,
+ 83, 60, 100, 208, 12, 234, 185, 206, 97, 0, 109, 170, 238, 253, 66,
+ 0, 68, 0, 0, 236, 253, 127, 0, 246, 18, 0, 82, 0, 0, 0,
+ 42, 247, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 0, 0,
+ 0, 0, 0, 0, 0, 36, 0, 2, 0, 0, 236, 253, 127, 0, 224,
+ 253, 127, 0, 224, 253, 127, 72, 249, 18, 0, 219, 128, 251, 119, 104,
+ 78, 249, 119, 255, 255, 255, 255, 0, 0, 0, 64, 111, 122, 152, 187,
+ 158, 149, 34, 236, 158, 103, 110, 35, 246, 67, 137, 177, 29, 56, 22,
+ 101, 64, 134, 124, 38, 155, 203, 128, 162, 3, 184, 27, 114, 80, 94,
+ 145, 136, 82, 121, 92, 7, 241, 119, 134, 12, 246, 193, 229, 95, 180,
+ 47, 135, 212, 231, 14, 59, 120, 218, 79, 151, 205, 221, 116, 27, 122,
+ 92, 0, 68, 0, 111, 0, 99, 0, 117, 0, 109, 0, 101, 0, 110,
+ 0, 116, 0, 115, 0, 82, 145, 252, 119, 255, 255, 255, 255, 60, 247,
+ 18, 0, 0, 0, 0, 0, 92, 247, 18, 0, 0, 16, 0, 0, 4,
+ 0, 0, 0, 0, 0, 242, 2, 0, 0, 242, 2, 32, 110, 172, 7,
+ 3, 239, 0, 0, 0, 0, 162, 7, 0, 0, 0, 64, 149, 244, 255,
+ 174, 70, 126, 180, 169, 78, 97, 78, 32, 67, 111, 110, 116, 101, 110,
+ 116, 32, 84, 101, 97, 109, 0, 247, 18, 0, 0, 16, 0, 0, 4,
+ 0, 0, 0, 0, 0, 242, 2, 0, 0, 242, 2, 80, 33, 90, 7,
+ 2, 32, 0, 0, 0, 0, 72, 7, 82, 145, 252, 119, 255, 255, 255,
+ 255, 168, 247, 18, 0, 0, 0, 0, 0, 200, 247, 18, 0, 0, 16,
+ 0, 0, 4, 0, 0, 0, 0, 0, 242, 2, 0, 0, 242, 2, 64,
+ 33, 88, 7, 2, 67, 0, 0, 0, 0, 72, 7, 216, 69, 0, 2,
+ 99, 111, 110, 116, 101, 110, 116, 99, 114, 101, 97, 116, 105, 111, 110,
+ 64, 98, 108, 101, 110, 100, 101, 114, 46, 110, 108, 0, 2, 81, 67,
+ 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 216, 69, 0, 0, 0,
+ 0, 72, 7, 116, 249, 18, 0, 127, 164, 252, 119, 0, 0, 242, 2,
+ 103, 154, 252, 119, 0, 0, 0, 0, 128, 26, 2, 0, 112, 112, 247,
+ 2, 12, 155, 252, 119, 255, 255, 255, 255, 40, 248, 18, 0, 0, 0,
+ 0, 0, 124, 249, 18, 0, 0, 16, 0, 0, 0, 236, 179, 7, 120,
+ 1, 242, 2, 48, 62, 8, 0, 184, 250, 18, 0, 0, 0, 72, 7,
+ 0, 112, 166, 7, 0, 0, 242, 2, 80, 0, 242, 2, 80, 0, 242,
+ 2, 0, 0, 226, 7, 0, 16, 162, 7, 0, 240, 5, 0, 248, 3,
+ 242, 2, 248, 3, 242, 2, 10, 0, 0, 0, 1, 0, 0, 0, 248,
+ 3, 242, 2, 120, 1, 242, 2, 112, 236, 179, 7, 120, 1, 242, 2,
+ 120, 1, 242, 2, 104, 236, 179, 7, 0, 16, 0, 0, 4, 0, 0,
+ 0, 0, 0, 242, 2, 0, 0, 242, 2, 64, 0, 162, 7, 3, 239,
+ 0, 0, 0, 0, 162, 7, 112, 236, 179, 7, 96, 157, 12, 3, 112,
+ 236, 179, 7, 120, 1, 242, 2, 104, 236, 179, 7, 18, 0, 0, 0,
+ 168, 248, 18, 0, 166, 166, 252, 119, 0, 0, 72, 7, 0, 48, 84,
+ 7, 64, 27, 84, 7, 0, 0, 242, 2, 236, 248, 18, 0, 176, 160,
+ 252, 119, 0, 0, 72, 7, 0, 32, 84, 7, 0, 16, 0, 0, 0,
+ 0, 242, 2, 64, 27, 84, 7, 1, 0, 0, 0, 136, 4, 0, 0,
+ 0, 27, 84, 7, 144, 1, 161, 7, 0, 0, 0, 0, 0, 0, 0,
+ 0, 145, 0, 0, 0, 145, 0, 0, 0, 152, 0, 0, 0, 0, 0,
+ 72, 7, 144, 249, 18, 0, 9, 151, 252, 119, 0, 32, 84, 7, 0,
+ 16, 0, 0, 143, 157, 252, 119, 86, 250, 18, 0, 72, 27, 84, 7,
+ 32, 0, 226, 7, 8, 0, 0, 0, 193, 0, 0, 0, 25, 0, 0,
+ 0, 0, 0, 242, 2, 135, 2, 0, 0, 112, 236, 179, 7, 64, 33,
+ 88, 7, 19, 0, 0, 0, 0, 249, 18, 0, 0, 67, 0, 0, 72,
+ 27, 84, 7, 0, 0, 0, 0, 0, 0, 0, 0, 200, 59, 90, 7,
+ 0, 0, 0, 0, 63, 0, 0, 0, 72, 33, 88, 7, 128, 26, 2,
+ 0, 112, 112, 247, 2, 0, 0, 0, 0, 16, 0, 0, 0, 224, 249,
+ 18, 0, 255, 255, 223, 255, 32, 0, 0, 0, 252, 24, 242, 2, 144,
+ 0, 0, 0, 8, 0, 0, 0, 77, 26, 2, 0, 1, 120, 64, 0,
+ 80, 6, 242, 2, 109, 26, 228, 7, 210, 119, 64, 0, 16, 0, 0,
+ 0, 191, 119, 64, 0, 65, 97, 108, 46, 0, 2, 26, 101, 0, 0,
+ 0, 6, 77, 194, 164, 27, 66, 114, 105, 0, 0, 2, 26, 77, 0,
+ 7, 126, 76, 0, 0, 0, 1, 121, 216, 88, 60, 9, 46, 197, 144,
+ 120, 249, 120, 38, 9, 47, 236, 125, 7, 120, 19, 71, 211, 240, 158,
+ 108, 176, 1, 3, 162, 155, 46, 211, 171, 113, 161, 186, 232, 132, 49,
+ 29, 131, 232, 132, 18, 100, 192, 96, 83, 140, 177, 77, 77, 192, 162,
+ 147, 64, 192, 9, 189, 37, 14, 16, 8, 9, 197, 96, 211, 193, 18,
+ 37, 116, 136, 147, 80, 2, 164, 152, 150, 0, 129, 196, 132, 22, 170,
+ 254, 153, 211, 173, 180, 42, 167, 147, 49, 223, 251, 230, 251, 126, 204,
+ 115, 104, 110, 119, 102, 118, 118, 119, 118, 102, 118, 111, 116, 106, 25,
+ 61, 210, 159, 120, 77, 9, 35, 132, 40, 178, 238, 111, 237, 30, 209,
+ 169, 117, 231, 200, 214, 221, 6, 142, 11, 10, 10, 234, 6, 160, 10,
+ 42, 110, 60, 43, 73, 240, 143, 131, 43, 24, 174, 182, 112, 141, 138,
+ 142, 139, 39, 78, 254, 186, 119, 35, 100, 8, 124, 166, 206, 138, 247,
+ 106, 43, 210, 56, 226, 36, 13, 78, 140, 137, 113, 160, 167, 184, 26,
+ 160, 205, 158, 22, 239, 165, 135, 43, 125, 85, 188, 87, 218, 202, 120,
+ 47, 213, 23, 112, 191, 35, 222, 139, 16, 147, 39, 92, 30, 164, 0,
+ 241, 84, 136, 20, 28, 241, 38, 145, 45, 123, 180, 44, 45, 210, 182,
+ 19, 121, 229, 206, 68, 124, 219, 63, 138, 135, 117, 20, 47, 13, 96,
+ 164, 19, 81, 60, 89, 188, 52, 6, 79, 11, 176, 133, 103, 1, 91,
+ 60, 45, 131, 71, 0, 78, 179, 226, 217, 180, 75, 24, 188, 244, 25,
+ 241, 94, 90, 171, 140, 28, 139, 135, 117, 20, 79, 7, 48, 177, 242,
+ 179, 193, 211, 49, 120, 74, 128, 145, 206, 204, 238, 150, 7, 139, 167,
+ 100, 240, 140, 211, 227, 189, 116, 20, 175, 128, 45, 30, 214, 81, 188,
+ 4, 128, 149, 34, 158, 81, 97, 219, 110, 2, 131, 167, 2, 24, 233,
+ 204, 120, 182, 252, 84, 12, 30, 206, 105, 130, 5, 175, 143, 13, 30,
+ 214, 181, 99, 116, 64, 53, 157, 202, 103, 197, 243, 133, 79, 212, 137,
+ 246, 34, 94, 192, 52, 51, 78, 154, 56, 47, 28, 51, 199, 190, 98,
+ 61, 197, 205, 153, 106, 214, 39, 173, 56, 215, 246, 184, 88, 79, 113,
+ 83, 1, 22, 120, 75, 224, 166, 50, 184, 26, 128, 145, 150, 206, 165,
+ 61, 174, 134, 193, 205, 213, 199, 123, 165, 138, 184, 132, 209, 77, 138,
+ 139, 245, 20, 55, 13, 96, 164, 197, 121, 114, 214, 183, 52, 6, 87,
+ 11, 48, 210, 226, 92, 165, 57, 193, 213, 50, 184, 217, 159, 1, 142,
+ 136, 107, 209, 1, 6, 23, 235, 41, 174, 30, 96, 164, 21, 230, 214,
+ 137, 188, 122, 6, 55, 0, 96, 164, 69, 220, 116, 39, 124, 3, 24,
+ 220, 156, 79, 97, 46, 62, 51, 235, 130, 51, 25, 176, 222, 50, 23,
+ 0, 7, 136, 184, 74, 39, 184, 169, 12, 174, 6, 96, 164, 77, 96,
+ 244, 209, 102, 46, 24, 220, 220, 213, 48, 23, 159, 138, 237, 59, 25,
+ 51, 172, 183, 204, 5, 192, 72, 171, 146, 224, 155, 198, 224, 106, 1,
+ 70, 90, 196, 77, 112, 130, 171, 101, 112, 9, 192, 72, 139, 186, 143,
+ 125, 179, 151, 129, 48, 184, 104, 7, 181, 34, 110, 186, 19, 92, 172,
+ 111, 207, 218, 91, 17, 87, 101, 39, 195, 79, 40, 47, 216, 211, 14,
+ 212, 22, 44, 55, 215, 11, 246, 111, 166, 85, 143, 177, 44, 231, 202,
+ 99, 133, 112, 253, 104, 190, 200, 155, 248, 19, 237, 225, 75, 230, 254,
+ 182, 221, 189, 96, 189, 4, 67, 92, 128, 40, 136, 167, 39, 87, 224,
+ 54, 241, 128, 127, 21, 61, 204, 190, 5, 255, 18, 230, 69, 146, 180,
+ 211, 17, 36, 189, 113, 71, 98, 92, 25, 41, 92, 217, 43, 160, 207,
+ 112, 41, 253, 158, 40, 148, 31, 63, 81, 96, 127, 211, 80, 167, 161,
+ 76, 99, 231, 139, 60, 89, 153, 114, 62, 139, 52, 3, 67, 90, 225,
+ 255, 133, 78, 173, 141, 28, 58, 180, 230, 65, 122, 159, 183, 63, 61,
+ 208, 212, 137, 32, 228, 56, 240, 188, 138, 244, 252, 213, 73, 153, 60,
+ 182, 206, 9, 158, 170, 56, 20, 121, 19, 205, 153, 120, 47, 147, 201,
+ 158, 118, 9, 71, 231, 8, 231, 133, 206, 145, 102, 169, 217, 7, 82,
+ 91, 128, 107, 156, 174, 133, 156, 243, 48, 55, 231, 223, 208, 220, 48,
+ 115, 240, 135, 7, 51, 72, 226, 189, 201, 131, 153, 35, 79, 243, 85,
+ 80, 144, 209, 203, 139, 43, 128, 189, 243, 224, 54, 42, 172, 115, 36,
+ 216, 102, 152, 163, 236, 79, 204, 195, 155, 0, 115, 164, 93, 6, 250,
+ 5, 87, 118, 201, 103, 10, 188, 176, 191, 26, 232, 36, 150, 69, 216,
+ 205, 81, 1, 6, 46, 139, 113, 67, 203, 94, 173, 85, 61, 90, 118,
+ 107, 219, 210, 86, 220, 193, 33, 253, 35, 71, 15, 30, 59, 42, 38,
+ 62, 57, 73, 21, 29, 63, 68, 213, 61, 38, 57, 57, 46, 126, 88,
+ 82, 255, 68, 184, 139, 30, 57, 178, 127, 100, 76, 210, 136, 228, 209,
+ 9, 253, 7, 38, 140, 29, 52, 50, 46, 41, 54, 38, 177, 97, 66,
+ 98, 204, 200, 209, 209, 67, 98, 18, 251, 147, 255, 109, 127, 133, 48,
+ 88, 131, 43, 150, 176, 211, 110, 213, 38, 170, 67, 168, 55, 22, 29,
+ 74, 5, 219, 181, 220, 188, 198, 81, 143, 88, 27, 153, 243, 61, 232,
+ 16, 92, 185, 103, 30, 43, 30, 194, 181, 58, 180, 132, 198, 190, 205,
+ 242, 166, 162, 14, 101, 43, 90, 234, 13, 160, 239, 6, 122, 223, 142,
+ 139, 202, 162, 240, 1, 16, 205, 3, 26, 190, 233, 97, 123, 95, 142,
+ 179, 222, 251, 138, 245, 94, 176, 30, 64, 123, 184, 44, 197, 89, 5,
+ 106, 209, 82, 70, 135, 210, 39, 152, 215, 121, 218, 216, 86, 196, 8,
+ 48, 94, 250, 197, 96, 167, 182, 64, 63, 114, 31, 40, 240, 194, 254,
+ 206, 3, 94, 88, 30, 78, 237, 240, 34, 115, 223, 204, 205, 233, 121,
+ 39, 235, 212, 85, 153, 30, 175, 139, 133, 159, 25, 205, 101, 121, 166,
+ 23, 254, 128, 94, 131, 101, 175, 59, 158, 15, 170, 61, 212, 32, 143,
+ 157, 159, 93, 85, 219, 227, 54, 56, 242, 155, 67, 153, 177, 74, 165,
+ 67, 158, 23, 63, 51, 210, 251, 195, 241, 190, 17, 185, 117, 210, 52,
+ 246, 114, 125, 81, 106, 155, 70, 33, 174, 47, 142, 185, 170, 192, 60,
+ 16, 226, 19, 129, 248, 103, 78, 159, 134, 161, 124, 214, 170, 125, 211,
+ 118, 124, 159, 210, 133, 52, 179, 222, 25, 8, 124, 141, 141, 115, 158,
+ 24, 194, 219, 69, 157, 228, 209, 126, 13, 228, 134, 113, 120, 61, 48,
+ 157, 86, 60, 55, 157, 19, 148, 177, 52, 211, 142, 106, 177, 121, 14,
+ 112, 126, 106, 136, 247, 97, 18, 123, 2, 176, 20, 116, 60, 248, 246,
+ 138, 213, 150, 88, 51, 77, 156, 75, 106, 191, 181, 31, 67, 236, 0,
+ 124, 164, 236, 247, 212, 217, 51, 91, 133, 188, 120, 63, 114, 205, 179,
+ 174, 135, 59, 191, 188, 252, 198, 237, 183, 66, 88, 103, 10, 187, 21,
+ 103, 107, 191, 179, 21, 102, 57, 223, 161, 190, 27, 116, 21, 251, 80,
+ 24, 109, 88, 235, 78, 173, 91, 245, 80, 181, 143, 106, 217, 182, 181,
+ 61, 117, 57, 17, 255, 20, 215, 29, 56, 212, 113, 42, 157, 55, 252,
+ 171, 66, 62, 81, 212, 130, 207, 108, 248, 204, 129, 207, 199, 240, 57,
+ 11, 40, 94, 1, 77, 49, 143, 79, 20, 175, 160, 172, 152, 71, 37,
+ 82, 139, 236, 80, 108, 82, 148, 129, 242, 101, 138, 115, 92, 25, 146,
+ 24, 61, 104, 80, 92, 114, 191, 192, 1, 254, 201, 195, 162, 255, 11,
+ 118, 171, 149, 172, 157, 142, 154, 168, 178, 96, 56, 55, 214, 137, 49,
+ 73, 49, 209, 137, 131, 99, 95, 199, 106, 255, 255, 222, 127, 171, 167,
+ 48, 107, 174, 73, 252, 115, 151, 46, 231, 241, 99, 133, 242, 122, 7,
+ 66, 125, 54, 234, 53, 235, 179, 81, 231, 89, 159, 221, 144, 250, 236,
+ 54, 237, 59, 181, 38, 221, 222, 177, 153, 139, 16, 9, 103, 156, 135,
+ 177, 32, 20, 242, 31, 52, 50, 38, 126, 72, 255, 30, 49, 19, 146,
+ 251, 147, 193, 201, 253, 253, 253, 243, 237, 212, 19, 7, 37, 155, 121,
+ 55, 28, 26, 23, 31, 61, 210, 220, 66, 62, 248, 121, 139, 159, 211,
+ 37, 34, 28, 139, 207, 78, 181, 250, 108, 60, 243, 64, 31, 142, 126,
+ 26, 227, 120, 26, 251, 11, 182, 254, 212, 99, 5, 94, 169, 39, 204,
+ 215, 244, 65, 213, 29, 252, 193, 149, 203, 39, 194, 237, 203, 70, 151,
+ 244, 216, 199, 250, 56, 243, 165, 231, 15, 139, 14, 1, 125, 116, 79,
+ 240, 201, 236, 61, 250, 108, 122, 239, 43, 214, 23, 34, 133, 65, 198,
+ 130, 5, 213, 10, 181, 2, 99, 243, 170, 30, 142, 113, 95, 234, 229,
+ 246, 2, 172, 252, 50, 146, 228, 108, 134, 125, 220, 122, 216, 115, 173,
+ 123, 162, 192, 11, 251, 187, 10, 117, 10, 202, 35, 169, 109, 223, 108,
+ 238, 91, 65, 7, 123, 76, 63, 171, 100, 17, 253, 120, 176, 197, 15,
+ 15, 16, 141, 51, 255, 235, 248, 167, 86, 216, 126, 186, 250, 11, 200,
+ 137, 197, 246, 45, 126, 25, 73, 110, 153, 238, 155, 80, 58, 148, 183,
+ 143, 40, 99, 107, 122, 46, 179, 9, 246, 155, 112, 95, 136, 234, 255,
+ 72, 115, 28, 94, 195, 66, 13, 222, 20, 46, 244, 165, 56, 211, 37,
+ 224, 234, 6, 87, 15, 113, 230, 75, 136, 88, 219, 57, 199, 51, 170,
+ 253, 34, 127, 158, 238, 65, 191, 2, 31, 2, 109, 217, 118, 163, 116,
+ 4, 240, 62, 112, 230, 244, 60, 158, 222, 3, 166, 145, 250, 82, 37,
+ 213, 101, 206, 220, 214, 100, 177, 29, 37, 177, 222, 151, 16, 235, 11,
+ 95, 172, 30, 134, 23, 209, 13, 111, 67, 200, 164, 72, 54, 214, 116,
+ 246, 167, 187, 19, 239, 229, 107, 185, 235, 18, 225, 112, 208, 198, 200,
+ 70, 227, 51, 236, 3, 141, 207, 2, 54, 66, 252, 182, 201, 188, 143,
+ 29, 245, 21, 207, 115, 85, 234, 31, 152, 244, 110, 93, 161, 31, 21,
+ 51, 235, 242, 95, 230, 244, 9, 111, 22, 192, 11, 177, 144, 222, 231,
+ 189, 125, 199, 134, 167, 240, 75, 126, 255, 64, 208, 231, 175, 30, 53,
+ 81, 199, 214, 62, 23, 94, 179, 227, 68, 53, 234, 238, 72, 160, 71,
+ 154, 239, 139, 188, 39, 232, 246, 163, 202, 245, 15, 108, 6, 250, 163,
+ 64, 131, 247, 200, 183, 41, 240, 90, 38, 210, 31, 27, 176, 40, 235,
+ 210, 225, 209, 225, 115, 47, 61, 56, 128, 244, 31, 172, 127, 24, 126,
+ 233, 238, 172, 125, 101, 70, 111, 222, 139, 245, 143, 87, 255, 24, 126,
+ 134, 251, 58, 244, 234, 209, 195, 33, 120, 255, 113, 11, 213, 222, 160,
+ 152, 19, 225, 57, 77, 139, 238, 193, 251, 171, 17, 183, 194, 180, 237,
+ 106, 135, 125, 219, 198, 180, 7, 233, 115, 107, 47, 209, 68, 62, 152,
+ 161, 169, 179, 249, 8, 78, 27, 25, 224, 121, 41, 107, 199, 172, 66,
+ 252, 139, 199, 126, 194, 78, 37, 98, 232, 23, 135, 75, 239, 216, 219,
+ 170, 222, 166, 130, 135, 216, 246, 231, 137, 237, 247, 122, 233, 207, 63,
+ 233, 85, 221, 208, 177, 233, 196, 172, 115, 15, 167, 103, 125, 49, 255,
+ 184, 134, 106, 16, 27, 159, 153, 255, 204, 241, 153, 48, 87, 16, 159,
+ 1, 47, 245, 149, 195, 163, 15, 64, 95, 108, 214, 58, 198, 103, 126,
+ 220, 82, 14, 47, 155, 89, 113, 50, 151, 212, 158, 227, 156, 80, 123,
+ 142, 107, 21, 231, 139, 181, 231, 133, 109, 236, 185, 157, 189, 12, 249,
+ 119, 111, 174, 44, 246, 60, 32, 40, 223, 182, 156, 181, 231, 174, 246,
+ 96, 24, 7, 226, 56, 190, 195, 204, 31, 142, 49, 142, 99, 183, 214,
+ 218, 78, 45, 91, 181, 118, 26, 8, 122, 137, 248, 213, 185, 193, 240,
+ 81, 149, 169, 41, 98, 23, 7, 190, 226, 204, 113, 224, 43, 206, 28,
+ 7, 190, 226, 254, 230, 204, 113, 96, 83, 197, 43, 14, 227, 192, 166,
+ 10, 140, 3, 253, 132, 248, 239, 21, 241, 84, 188, 32, 52, 14, 12,
+ 246, 31, 158, 48, 204, 226, 66, 251, 39, 131, 243, 28, 155, 24, 211,
+ 31, 43, 243, 24, 168, 228, 121, 46, 36, 116, 133, 138, 64, 250, 19,
+ 27, 246, 46, 113, 95, 59, 14, 252, 87, 247, 223, 230, 239, 77, 247,
+ 63, 191, 113, 96, 238, 163, 199, 138, 156, 180, 54, 150, 152, 5, 227,
+ 148, 14, 236, 243, 155, 84, 235, 249, 39, 158, 83, 101, 139, 231, 244,
+ 169, 71, 33, 86, 193, 235, 176, 249, 122, 83, 49, 75, 63, 15, 243,
+ 57, 2, 123, 63, 154, 185, 79, 16, 235, 139, 128, 55, 134, 29, 28,
+ 68, 44, 227, 132, 243, 196, 43, 156, 227, 121, 162, 242, 120, 123, 146,
+ 134, 48, 92, 1, 235, 32, 254, 74, 131, 190, 116, 125, 166, 80, 142,
+ 249, 71, 65, 253, 50, 150, 83, 191, 156, 176, 214, 220, 55, 91, 191,
+ 60, 223, 206, 47, 207, 119, 234, 151, 199, 137, 126, 248, 165, 157, 95,
+ 126, 41, 250, 101, 172, 151, 243, 203, 218, 162, 175, 20, 246, 118, 31,
+ 253, 242, 159, 146, 126, 121, 190, 173, 95, 22, 251, 48, 155, 238, 85,
+ 63, 135, 56, 13, 250, 231, 35, 198, 46, 230, 179, 3, 218, 46, 126,
+ 98, 63, 166, 69, 152, 239, 239, 70, 248, 43, 172, 177, 213, 56, 113,
+ 114, 26, 42, 172, 253, 161, 247, 180, 63, 214, 63, 228, 53, 41, 210,
+ 124, 206, 160, 106, 89, 88, 12, 185, 18, 166, 91, 207, 50, 105, 220,
+ 128, 50, 209, 184, 1, 231, 3, 229, 125, 27, 55, 252, 123, 226, 6,
+ 156, 19, 118, 31, 136, 243, 245, 54, 110, 120, 189, 184, 161, 59, 236,
+ 114, 230, 128, 173, 210, 237, 143, 247, 10, 165, 207, 225, 118, 216, 62,
+ 199, 238, 222, 42, 208, 41, 111, 58, 254, 186, 109, 241, 94, 250, 94,
+ 214, 117, 164, 4, 94, 154, 61, 86, 30, 67, 253, 2, 3, 99, 253,
+ 182, 165, 195, 231, 1, 206, 215, 25, 159, 96, 210, 22, 44, 227, 16,
+ 219, 115, 77, 187, 253, 150, 94, 145, 195, 133, 1, 206, 71, 68, 195,
+ 105, 56, 78, 60, 31, 3, 55, 146, 178, 124, 249, 30, 126, 197, 242,
+ 229, 203, 79, 159, 190, 235, 100, 143, 102, 110, 112, 32, 88, 135, 2,
+ 226, 136, 148, 23, 85, 207, 254, 172, 181, 81, 163, 127, 247, 57, 124,
+ 163, 70, 137, 160, 16, 49, 137, 141, 254, 181, 242, 145, 234, 228, 237,
+ 223, 27, 251, 67, 123, 87, 73, 92, 79, 45, 232, 243, 211, 125, 226,
+ 186, 82, 90, 215, 159, 222, 167, 187, 66, 119, 57, 222, 139, 226, 35,
+ 14, 197, 79, 0, 24, 233, 17, 95, 97, 193, 223, 173, 208, 252, 108,
+ 197, 79, 96, 240, 85, 0, 11, 109, 0, 190, 135, 5, 127, 191, 34,
+ 221, 104, 197, 87, 49, 248, 217, 123, 193, 63, 138, 248, 158, 22, 252,
+ 158, 16, 111, 89, 241, 17, 135, 226, 235, 1, 70, 122, 142, 57, 141,
+ 42, 170, 240, 228, 52, 247, 172, 248, 122, 6, 63, 0, 96, 164, 71,
+ 67, 70, 207, 105, 52, 10, 13, 135, 231, 1, 20, 63, 128, 193, 207,
+ 1, 187, 131, 244, 40, 15, 53, 64, 248, 204, 32, 224, 132, 21, 31,
+ 113, 40, 126, 42, 192, 1, 34, 62, 181, 149, 222, 138, 126, 156, 178,
+ 123, 172, 5, 63, 149, 193, 71, 187, 134, 244, 28, 19, 19, 233, 125,
+ 98, 56, 180, 129, 20, 95, 195, 224, 19, 145, 30, 249, 23, 102, 248,
+ 231, 148, 136, 245, 162, 182, 23, 237, 109, 40, 107, 79, 247, 91, 109,
+ 103, 247, 86, 66, 230, 147, 127, 64, 64, 160, 243, 220, 165, 51, 182,
+ 182, 55, 0, 120, 105, 50, 65, 198, 76, 199, 92, 36, 142, 188, 181,
+ 189, 111, 109, 239, 219, 191, 188, 216, 94, 92, 79, 22, 219, 146, 105,
+ 125, 198, 75, 215, 82, 57, 197, 66, 69, 234, 119, 140, 109, 201, 100,
+ 108, 11, 192, 72, 207, 49, 49, 178, 222, 103, 132, 2, 215, 172, 197,
+ 182, 48, 248, 116, 221, 34, 236, 97, 225, 223, 90, 65, 90, 91, 109,
+ 145, 38, 211, 206, 182, 136, 248, 212, 246, 126, 194, 45, 84, 232, 47,
+ 198, 123, 117, 129, 0, 121, 147, 194, 28, 155, 53, 165, 252, 207, 216,
+ 218, 132, 46, 17, 173, 162, 71, 197, 36, 70, 75, 217, 137, 34, 121,
+ 28, 51, 180, 177, 194, 30, 113, 241, 35, 135, 211, 111, 109, 110, 172,
+ 151, 187, 124, 30, 6, 220, 210, 196, 237, 95, 123, 240, 224, 225, 230,
+ 54, 153, 23, 35, 63, 159, 158, 217, 39, 246, 87, 99, 189, 161, 107,
+ 53, 10, 176, 29, 96, 126, 28, 158, 149, 167, 248, 46, 225, 39, 118,
+ 186, 159, 113, 118, 255, 11, 181, 252, 51, 116, 235, 253, 207, 77, 2,
+ 249, 199, 134, 230, 252, 244, 51, 235, 49, 229, 148, 108, 136, 92, 144,
+ 245, 219, 136, 15, 212, 117, 158, 142, 16, 112, 60, 58, 213, 227, 111,
+ 247, 169, 110, 232, 48, 243, 168, 192, 87, 245, 67, 64, 75, 242, 229,
+ 188, 131, 135, 4, 25, 245, 188, 98, 89, 18, 191, 54, 121, 181, 58,
+ 113, 231, 178, 12, 172, 7, 56, 11, 203, 174, 133, 148, 204, 20, 198,
+ 122, 102, 209, 224, 133, 173, 190, 13, 166, 109, 30, 139, 45, 100, 220,
+ 190, 232, 156, 166, 193, 208, 181, 70, 231, 207, 246, 243, 246, 103, 181,
+ 237, 5, 184, 46, 17, 70, 111, 171, 158, 14, 97, 250, 170, 231, 11,
+ 214, 29, 194, 139, 207, 219, 133, 126, 152, 239, 237, 207, 19, 254, 211,
+ 127, 212, 23, 88, 199, 129, 234, 47, 234, 44, 213, 95, 212, 47, 212,
+ 103, 123, 253, 181, 119, 142, 175, 171, 191, 174, 254, 140, 105, 238, 235,
+ 47, 253, 51, 231, 99, 184, 223, 103, 182, 82, 154, 70, 234, 62, 127,
+ 57, 35, 175, 75, 47, 93, 246, 154, 250, 27, 105, 214, 95, 47, 9,
+ 253, 45, 124, 177, 122, 56, 171, 191, 230, 243, 28, 187, 252, 58, 251,
+ 231, 200, 233, 96, 87, 225, 50, 158, 54, 95, 90, 241, 202, 151, 190,
+ 106, 92, 207, 37, 218, 235, 78, 98, 219, 49, 78, 98, 47, 142, 249,
+ 63, 41, 38, 62, 105, 116, 162, 235, 22, 211, 210, 109, 229, 69, 254,
+ 158, 76, 185, 176, 55, 56, 109, 246, 43, 90, 17, 142, 117, 26, 243,
+ 217, 158, 210, 12, 30, 29, 159, 44, 215, 91, 157, 68, 219, 58, 166,
+ 109, 173, 216, 118, 152, 8, 143, 115, 210, 118, 17, 40, 193, 53, 25,
+ 61, 216, 117, 147, 202, 211, 214, 60, 30, 165, 120, 63, 74, 228, 231,
+ 105, 23, 35, 83, 59, 129, 182, 129, 218, 9, 220, 123, 176, 190, 174,
+ 75, 196, 96, 193, 78, 116, 27, 157, 76, 98, 163, 135, 140, 30, 79,
+ 70, 70, 199, 199, 88, 229, 227, 94, 83, 11, 178, 251, 59, 230, 65,
+ 42, 35, 221, 183, 19, 172, 63, 99, 203, 251, 4, 55, 108, 172, 251,
+ 252, 165, 225, 210, 55, 51, 121, 41, 59, 129, 190, 4, 124, 74, 198,
+ 235, 218, 9, 244, 71, 248, 217, 169, 78, 204, 6, 44, 51, 251, 38,
+ 161, 60, 3, 224, 12, 138, 103, 43, 163, 158, 143, 243, 91, 19, 28,
+ 235, 183, 38, 195, 202, 83, 207, 31, 111, 182, 37, 56, 78, 40, 35,
+ 36, 113, 122, 51, 161, 110, 56, 224, 225, 125, 244, 231, 47, 249, 31,
+ 191, 153, 105, 88, 221, 230, 187, 204, 55, 97, 39, 44, 135, 217, 145,
+ 156, 194, 153, 159, 107, 158, 185, 228, 132, 75, 59, 225, 196, 209, 25,
+ 143, 131, 93, 128, 75, 35, 94, 250, 99, 230, 43, 251, 168, 249, 250,
+ 159, 182, 19, 26, 81, 134, 190, 118, 186, 152, 28, 55, 42, 70, 24,
+ 211, 209, 9, 78, 185, 23, 176, 201, 88, 37, 228, 238, 113, 235, 186,
+ 65, 219, 131, 125, 121, 19, 182, 135, 28, 119, 190, 254, 105, 185, 16,
+ 215, 30, 179, 218, 30, 132, 223, 148, 237, 209, 28, 115, 222, 54, 45,
+ 23, 206, 32, 142, 90, 109, 15, 194, 227, 156, 246, 153, 19, 202, 228,
+ 108, 79, 194, 81, 235, 24, 6, 136, 247, 9, 22, 126, 5, 225, 243,
+ 132, 101, 94, 228, 254, 168, 109, 66, 123, 68, 109, 19, 158, 163, 208,
+ 56, 217, 140, 211, 41, 122, 84, 130, 195, 246, 222, 34, 127, 225, 215,
+ 212, 188, 4, 226, 104, 155, 178, 179, 221, 183, 77, 213, 71, 8, 71,
+ 236, 228, 138, 218, 43, 194, 133, 126, 107, 172, 151, 237, 223, 229, 226,
+ 237, 249, 188, 218, 166, 135, 158, 77, 4, 62, 15, 60, 155, 24, 109,
+ 219, 48, 255, 61, 16, 235, 41, 158, 173, 140, 249, 143, 97, 128, 191,
+ 90, 108, 135, 217, 59, 232, 45, 240, 223, 158, 77, 178, 216, 250, 232,
+ 105, 207, 240, 57, 142, 126, 228, 96, 254, 160, 192, 83, 201, 198, 48,
+ 172, 198, 187, 105, 155, 254, 211, 49, 183, 198, 189, 24, 28, 117, 214,
+ 178, 135, 252, 57, 222, 11, 245, 217, 65, 127, 131, 254, 93, 250, 11,
+ 253, 104, 138, 250, 241, 58, 250, 251, 208, 115, 199, 6, 212, 223, 203,
+ 197, 79, 240, 121, 209, 223, 25, 237, 99, 26, 163, 110, 90, 245, 87,
+ 111, 4, 95, 217, 152, 35, 250, 47, 241, 110, 26, 212, 163, 14, 83,
+ 253, 181, 149, 49, 255, 250, 11, 252, 97, 22, 244, 89, 230, 79, 179,
+ 158, 66, 251, 65, 84, 95, 5, 253, 109, 50, 106, 29, 171, 191, 170,
+ 191, 191, 108, 252, 127, 93, 127, 81, 103, 169, 254, 226, 57, 57, 234,
+ 179, 131, 254, 6, 255, 235, 236, 47, 62, 131, 109, 246, 58, 250, 91,
+ 109, 153, 234, 75, 179, 254, 182, 215, 228, 209, 254, 26, 103, 180, 191,
+ 217, 152, 234, 111, 156, 95, 181, 29, 168, 195, 189, 43, 95, 255, 146,
+ 218, 229, 105, 80, 207, 216, 95, 70, 198, 55, 98, 127, 179, 98, 253,
+ 170, 101, 60, 16, 237, 44, 200, 34, 232, 243, 116, 225, 147, 234, 239,
+ 61, 59, 253, 173, 211, 228, 255, 186, 254, 162, 206, 82, 253, 197, 179,
+ 61, 212, 103, 7, 253, 109, 252, 111, 179, 191, 154, 93, 168, 31, 175,
+ 163, 191, 165, 238, 124, 42, 232, 239, 245, 83, 75, 242, 164, 191, 69,
+ 166, 164, 239, 64, 29, 102, 236, 175, 166, 248, 242, 167, 59, 106, 30,
+ 208, 109, 20, 198, 2, 234, 177, 206, 106, 127, 89, 25, 243, 175, 191,
+ 208, 62, 238, 125, 212, 230, 79, 97, 189, 100, 21, 91, 254, 212, 162,
+ 207, 168, 191, 153, 125, 163, 215, 179, 250, 187, 69, 149, 186, 227, 255,
+ 186, 254, 162, 206, 90, 246, 230, 223, 197, 123, 161, 62, 91, 113, 180,
+ 184, 25, 119, 8, 32, 94, 119, 111, 142, 252, 241, 51, 189, 175, 163,
+ 254, 170, 90, 185, 175, 191, 251, 163, 106, 26, 157, 237, 205, 67, 151,
+ 253, 206, 31, 26, 30, 166, 153, 251, 233, 217, 64, 115, 110, 203, 155,
+ 59, 195, 91, 253, 209, 23, 161, 108, 205, 18, 239, 241, 181, 214, 246,
+ 226, 248, 221, 27, 75, 218, 12, 14, 150, 9, 243, 173, 226, 248, 195,
+ 32, 75, 212, 142, 206, 25, 206, 228, 168, 51, 233, 97, 45, 44, 11,
+ 168, 249, 113, 144, 179, 54, 71, 125, 62, 189, 49, 244, 81, 83, 207,
+ 114, 6, 157, 63, 122, 235, 25, 158, 243, 189, 249, 235, 156, 225, 105,
+ 192, 87, 227, 69, 46, 154, 47, 227, 121, 243, 149, 125, 206, 124, 253,
+ 39, 246, 230, 216, 190, 253, 222, 60, 33, 113, 244, 176, 196, 152, 164,
+ 36, 210, 173, 75, 219, 110, 173, 187, 119, 183, 223, 164, 43, 236, 78,
+ 212, 71, 26, 109, 247, 230, 216, 23, 251, 189, 121, 97, 225, 59, 14,
+ 156, 219, 123, 115, 205, 5, 24, 139, 11, 206, 247, 199, 180, 92, 56,
+ 23, 60, 111, 222, 31, 71, 138, 52, 67, 152, 118, 45, 253, 200, 199,
+ 115, 50, 173, 216, 134, 179, 61, 191, 135, 216, 31, 15, 55, 247, 252,
+ 26, 224, 163, 63, 239, 188, 79, 180, 92, 216, 243, 159, 51, 247, 201,
+ 83, 164, 25, 70, 207, 33, 71, 62, 86, 88, 206, 2, 206, 229, 243,
+ 44, 224, 156, 221, 89, 192, 57, 219, 179, 128, 188, 140, 159, 229, 44,
+ 224, 59, 102, 47, 117, 15, 250, 122, 209, 153, 45, 12, 126, 35, 182,
+ 208, 229, 179, 186, 150, 238, 219, 66, 214, 230, 73, 157, 95, 162, 77,
+ 162, 87, 222, 158, 251, 56, 191, 119, 198, 199, 85, 153, 173, 140, 255,
+ 162, 231, 113, 130, 45, 116, 244, 229, 249, 121, 158, 241, 95, 221, 75,
+ 221, 99, 246, 82, 119, 226, 189, 168, 191, 181, 209, 223, 160, 55, 171,
+ 191, 105, 203, 28, 159, 39, 235, 195, 229, 245, 87, 43, 202, 198, 230,
+ 31, 190, 206, 89, 150, 251, 190, 220, 158, 159, 251, 101, 182, 50, 254,
+ 139, 158, 199, 17, 231, 250, 75, 99, 81, 169, 231, 201, 158, 132, 227,
+ 200, 127, 237, 207, 185, 47, 247, 100, 116, 130, 179, 223, 99, 221, 177,
+ 234, 53, 230, 102, 161, 158, 91, 245, 58, 105, 68, 204, 200, 152, 228,
+ 209, 241, 206, 99, 212, 242, 175, 251, 252, 104, 145, 173, 94, 167, 105,
+ 99, 189, 84, 49, 238, 191, 91, 3, 159, 19, 105, 27, 249, 105, 204,
+ 207, 137, 24, 191, 101, 83, 238, 252, 249, 17, 158, 109, 37, 78, 111,
+ 22, 156, 215, 51, 174, 56, 225, 185, 142, 158, 55, 63, 231, 17, 238,
+ 51, 146, 129, 15, 251, 60, 8, 203, 226, 196, 231, 63, 125, 156, 202,
+ 98, 253, 91, 244, 109, 187, 218, 66, 140, 89, 104, 209, 54, 103, 109,
+ 142, 9, 110, 152, 9, 244, 70, 160, 55, 188, 145, 231, 71, 222, 249,
+ 124, 126, 228, 132, 101, 78, 54, 196, 5, 112, 229, 220, 6, 157, 185,
+ 21, 239, 149, 246, 27, 92, 55, 224, 186, 14, 215, 63, 255, 153, 24,
+ 21, 101, 160, 49, 42, 202, 130, 117, 227, 163, 71, 142, 16, 158, 85,
+ 36, 71, 39, 38, 11, 128, 109, 144, 106, 126, 126, 116, 220, 178, 63,
+ 247, 249, 206, 26, 239, 104, 68, 62, 108, 220, 139, 109, 196, 13, 129,
+ 133, 224, 200, 202, 41, 79, 164, 91, 149, 109, 27, 247, 226, 24, 209,
+ 184, 87, 119, 219, 126, 108, 204, 45, 13, 141, 75, 76, 74, 30, 154,
+ 24, 13, 173, 72, 70, 192, 1, 217, 206, 99, 68, 90, 46, 124, 135,
+ 245, 55, 115, 140, 216, 73, 108, 203, 18, 111, 223, 50, 207, 149, 167,
+ 101, 54, 205, 237, 226, 120, 13, 141, 139, 199, 175, 6, 136, 78, 218,
+ 182, 117, 61, 208, 169, 110, 59, 111, 151, 150, 11, 246, 227, 166, 185,
+ 221, 88, 145, 102, 160, 88, 78, 23, 182, 227, 188, 216, 245, 141, 96,
+ 180, 217, 180, 185, 148, 86, 52, 49, 35, 184, 140, 201, 59, 137, 253,
+ 100, 247, 24, 58, 177, 207, 236, 243, 63, 156, 79, 75, 159, 157, 140,
+ 182, 234, 119, 216, 99, 252, 46, 177, 199, 248, 157, 25, 235, 27, 214,
+ 62, 35, 141, 125, 159, 45, 122, 35, 21, 143, 202, 172, 132, 38, 1,
+ 238, 237, 67, 112, 206, 99, 153, 121, 176, 213, 45, 15, 203, 157, 91,
+ 121, 15, 191, 57, 246, 219, 135, 41, 23, 250, 13, 107, 60, 247, 42,
+ 236, 69, 175, 89, 159, 127, 98, 187, 84, 6, 213, 77, 179, 61, 176,
+ 202, 160, 176, 145, 33, 72, 46, 246, 185, 233, 40, 131, 55, 83, 46,
+ 60, 83, 52, 1, 124, 213, 218, 190, 138, 105, 31, 231, 37, 231, 166,
+ 115, 27, 132, 237, 7, 190, 230, 126, 15, 249, 178, 251, 61, 149, 216,
+ 134, 121, 191, 231, 109, 25, 233, 228, 241, 113, 201, 131, 99, 3, 73,
+ 108, 220, 224, 88, 212, 1, 123, 126, 74, 224, 163, 189, 225, 216, 71,
+ 21, 250, 234, 27, 204, 154, 122, 9, 122, 248, 10, 238, 225, 83, 245,
+ 34, 222, 75, 243, 60, 222, 75, 247, 12, 246, 79, 79, 205, 54, 150,
+ 234, 36, 242, 163, 123, 193, 156, 62, 214, 189, 32, 206, 19, 221, 11,
+ 226, 92, 177, 90, 33, 124, 183, 107, 244, 184, 152, 161, 163, 19, 199,
+ 71, 39, 14, 33, 206, 182, 133, 154, 235, 182, 123, 65, 188, 79, 96,
+ 250, 95, 134, 212, 204, 211, 24, 134, 137, 114, 80, 153, 80, 135, 210,
+ 196, 54, 138, 139, 23, 218, 9, 146, 28, 147, 0, 251, 212, 184, 209,
+ 241, 32, 150, 221, 100, 233, 174, 89, 101, 10, 19, 239, 135, 83, 31,
+ 32, 126, 175, 45, 47, 114, 217, 203, 135, 50, 89, 246, 207, 162, 142,
+ 211, 157, 47, 94, 184, 158, 5, 25, 99, 146, 98, 146, 5, 192, 172,
+ 86, 84, 169, 19, 174, 218, 218, 126, 188, 143, 183, 219, 7, 200, 217,
+ 194, 134, 1, 254, 104, 8, 253, 131, 131, 228, 229, 37, 140, 188, 184,
+ 38, 114, 175, 218, 142, 103, 82, 92, 50, 113, 181, 229, 79, 205, 177,
+ 29, 79, 188, 183, 140, 167, 206, 60, 158, 193, 194, 219, 72, 95, 111,
+ 60, 81, 38, 42, 159, 160, 203, 87, 29, 199, 19, 101, 180, 172, 79,
+ 187, 9, 15, 48, 217, 142, 39, 222, 219, 143, 167, 197, 206, 198, 153,
+ 71, 211, 126, 68, 97, 60, 155, 187, 43, 47, 202, 56, 142, 89, 127,
+ 233, 38, 58, 158, 156, 48, 158, 160, 151, 193, 46, 247, 95, 175, 108,
+ 199, 19, 239, 233, 120, 166, 142, 123, 172, 240, 16, 96, 249, 112, 55,
+ 72, 66, 62, 148, 201, 162, 159, 212, 62, 216, 202, 231, 250, 124, 231,
+ 165, 173, 124, 120, 79, 229, 11, 8, 115, 95, 190, 210, 82, 250, 200,
+ 200, 135, 54, 43, 231, 165, 131, 124, 46, 205, 111, 234, 11, 59, 125,
+ 124, 97, 149, 47, 61, 144, 202, 231, 245, 218, 242, 161, 76, 84, 62,
+ 180, 167, 196, 81, 62, 151, 238, 41, 253, 185, 173, 124, 120, 79, 229,
+ 83, 109, 116, 127, 252, 138, 75, 200, 135, 50, 81, 249, 208, 214, 171,
+ 94, 56, 200, 215, 216, 229, 254, 234, 153, 173, 124, 120, 79, 229, 211,
+ 125, 234, 190, 124, 133, 37, 228, 67, 153, 168, 124, 232, 135, 52, 207,
+ 29, 228, 107, 226, 138, 111, 238, 83, 91, 249, 240, 158, 202, 151, 179,
+ 208, 253, 249, 149, 146, 15, 101, 162, 242, 161, 143, 212, 61, 115, 144,
+ 175, 169, 43, 190, 74, 59, 249, 148, 140, 124, 233, 183, 168, 124, 133,
+ 100, 229, 43, 47, 33, 31, 202, 196, 158, 207, 234, 159, 58, 200, 215,
+ 204, 229, 25, 230, 63, 182, 242, 225, 61, 149, 47, 247, 35, 247, 231,
+ 183, 138, 19, 249, 210, 112, 126, 159, 196, 123, 77, 167, 246, 234, 177,
+ 109, 140, 130, 47, 132, 75, 154, 173, 52, 12, 104, 84, 215, 80, 253,
+ 131, 249, 65, 182, 123, 51, 199, 253, 179, 231, 129, 78, 1, 243, 74,
+ 198, 212, 194, 187, 196, 71, 211, 131, 241, 187, 11, 21, 227, 183, 172,
+ 199, 251, 23, 203, 18, 214, 255, 176, 96, 81, 45, 74, 151, 8, 124,
+ 251, 1, 223, 122, 34, 223, 132, 152, 145, 227, 226, 146, 228, 109, 118,
+ 154, 40, 39, 149, 217, 248, 8, 230, 252, 137, 85, 110, 47, 79, 233,
+ 115, 146, 225, 175, 82, 248, 249, 179, 84, 33, 126, 29, 190, 10, 169,
+ 164, 250, 53, 116, 199, 211, 20, 126, 77, 205, 129, 97, 245, 14, 212,
+ 21, 190, 171, 238, 229, 59, 112, 127, 14, 148, 77, 189, 176, 70, 248,
+ 174, 249, 254, 115, 245, 66, 239, 4, 127, 186, 119, 191, 201, 252, 221,
+ 245, 65, 89, 115, 50, 218, 77, 43, 210, 184, 66, 185, 194, 130, 204,
+ 67, 99, 70, 141, 77, 244, 135, 189, 69, 178, 188, 204, 40, 39, 149,
+ 57, 247, 97, 188, 23, 59, 214, 174, 100, 254, 12, 218, 206, 44, 22,
+ 186, 111, 194, 217, 81, 33, 171, 74, 157, 223, 59, 23, 238, 79, 143,
+ 234, 185, 111, 198, 194, 187, 194, 247, 227, 223, 221, 223, 35, 116, 49,
+ 244, 43, 182, 246, 62, 161, 15, 95, 23, 248, 43, 164, 247, 227, 189,
+ 161, 63, 188, 50, 203, 92, 235, 66, 98, 198, 199, 77, 67, 50, 195,
+ 238, 238, 17, 100, 78, 142, 27, 20, 23, 237, 166, 204, 40, 39, 149,
+ 89, 5, 48, 246, 193, 29, 153, 191, 130, 182, 115, 175, 105, 67, 74,
+ 239, 138, 10, 137, 243, 57, 27, 186, 239, 89, 10, 191, 80, 217, 57,
+ 172, 100, 204, 105, 65, 230, 210, 5, 59, 239, 199, 178, 221, 13, 190,
+ 23, 198, 121, 112, 193, 111, 67, 248, 37, 223, 238, 61, 47, 142, 243,
+ 246, 6, 199, 130, 134, 110, 73, 207, 56, 197, 63, 51, 203, 28, 157,
+ 152, 52, 54, 201, 181, 208, 84, 102, 21, 35, 179, 246, 1, 196, 71,
+ 15, 221, 147, 249, 224, 243, 20, 126, 99, 196, 201, 61, 186, 97, 123,
+ 247, 234, 238, 53, 223, 239, 253, 87, 10, 175, 184, 181, 123, 127, 212,
+ 227, 16, 225, 121, 229, 202, 187, 187, 195, 218, 66, 89, 239, 243, 45,
+ 133, 62, 248, 126, 223, 98, 95, 197, 175, 187, 133, 236, 22, 101, 62,
+ 186, 46, 36, 176, 207, 39, 202, 192, 67, 185, 251, 133, 179, 249, 81,
+ 49, 201, 209, 114, 114, 91, 222, 197, 248, 192, 42, 179, 254, 111, 240,
+ 1, 110, 202, 236, 108, 13, 22, 43, 181, 122, 187, 49, 178, 189, 16,
+ 16, 7, 63, 235, 45, 172, 65, 221, 237, 87, 194, 26, 60, 247, 243,
+ 246, 218, 247, 31, 159, 89, 79, 233, 74, 54, 59, 158, 113, 186, 192,
+ 209, 237, 154, 155, 61, 132, 117, 57, 114, 236, 168, 65, 209, 137, 238,
+ 173, 65, 148, 147, 202, 156, 126, 31, 246, 55, 15, 94, 95, 230, 247,
+ 54, 181, 202, 24, 55, 38, 184, 54, 222, 253, 82, 96, 181, 48, 126,
+ 217, 33, 53, 4, 153, 149, 15, 252, 191, 120, 117, 226, 75, 139, 204,
+ 115, 171, 182, 200, 168, 115, 236, 122, 70, 234, 137, 80, 65, 230, 228,
+ 216, 209, 137, 209, 19, 220, 147, 25, 229, 164, 50, 231, 228, 194, 190,
+ 234, 239, 215, 151, 185, 235, 160, 105, 25, 161, 187, 102, 9, 50, 159,
+ 173, 91, 93, 144, 153, 12, 60, 33, 188, 166, 108, 237, 198, 102, 27,
+ 114, 219, 101, 91, 108, 93, 181, 58, 75, 130, 118, 39, 148, 201, 56,
+ 253, 219, 118, 33, 15, 61, 58, 121, 100, 180, 220, 195, 52, 42, 51,
+ 202, 105, 209, 231, 170, 177, 94, 216, 7, 70, 102, 165, 187, 50, 163,
+ 30, 244, 251, 114, 94, 80, 179, 47, 139, 9, 227, 250, 237, 170, 221,
+ 194, 243, 244, 250, 57, 105, 27, 240, 254, 201, 241, 254, 27, 2, 254,
+ 46, 93, 147, 210, 205, 78, 90, 147, 241, 211, 59, 5, 27, 71, 206,
+ 230, 4, 153, 7, 39, 70, 199, 199, 141, 29, 229, 150, 204, 40, 167,
+ 69, 159, 171, 196, 122, 97, 31, 94, 119, 156, 79, 70, 85, 220, 238,
+ 125, 171, 136, 16, 163, 29, 110, 84, 172, 49, 150, 149, 93, 244, 129,
+ 112, 223, 33, 180, 238, 182, 57, 202, 140, 109, 156, 72, 119, 196, 187,
+ 110, 70, 192, 215, 21, 131, 125, 118, 157, 222, 142, 120, 49, 209, 114,
+ 214, 153, 209, 231, 42, 86, 153, 211, 43, 199, 122, 97, 31, 220, 145,
+ 249, 200, 31, 41, 60, 247, 217, 151, 33, 190, 201, 203, 246, 30, 83,
+ 158, 218, 223, 126, 107, 10, 255, 147, 71, 199, 3, 79, 90, 148, 22,
+ 236, 198, 242, 151, 29, 194, 213, 80, 54, 255, 157, 6, 194, 125, 245,
+ 37, 149, 246, 133, 158, 172, 177, 111, 181, 104, 55, 86, 53, 90, 16,
+ 124, 225, 114, 151, 224, 117, 69, 218, 10, 231, 203, 177, 99, 71, 197,
+ 36, 202, 24, 59, 139, 62, 87, 182, 202, 156, 83, 41, 214, 11, 251,
+ 224, 142, 204, 107, 110, 167, 240, 87, 27, 165, 238, 171, 176, 238, 242,
+ 222, 125, 250, 239, 195, 202, 111, 76, 225, 183, 79, 238, 22, 254, 145,
+ 161, 163, 32, 227, 157, 119, 187, 29, 184, 187, 62, 133, 63, 247, 97,
+ 9, 225, 29, 42, 153, 131, 226, 246, 29, 219, 87, 44, 172, 252, 75,
+ 179, 204, 119, 213, 33, 25, 218, 235, 189, 130, 55, 221, 231, 5, 29,
+ 26, 59, 50, 94, 206, 165, 88, 245, 185, 146, 85, 102, 37, 192, 216,
+ 7, 119, 100, 238, 15, 62, 37, 56, 76, 21, 114, 48, 236, 241, 222,
+ 223, 110, 253, 18, 58, 1, 252, 244, 142, 159, 223, 13, 27, 115, 116,
+ 156, 32, 115, 231, 251, 239, 238, 191, 14, 101, 185, 57, 171, 4, 159,
+ 178, 98, 235, 216, 125, 199, 23, 173, 221, 59, 89, 28, 103, 245, 189,
+ 78, 25, 151, 135, 254, 180, 93, 105, 200, 10, 16, 244, 57, 58, 49,
+ 193, 93, 159, 162, 100, 100, 214, 84, 4, 125, 174, 228, 158, 204, 187,
+ 115, 83, 248, 132, 65, 53, 246, 104, 31, 166, 135, 4, 206, 75, 223,
+ 127, 237, 80, 10, 95, 126, 90, 192, 129, 49, 19, 2, 4, 95, 221,
+ 124, 106, 64, 120, 213, 195, 16, 111, 92, 58, 36, 188, 203, 166, 64,
+ 191, 192, 208, 19, 23, 102, 182, 56, 36, 202, 124, 175, 76, 227, 237,
+ 11, 78, 126, 26, 212, 237, 214, 150, 237, 212, 167, 200, 201, 77, 101,
+ 70, 57, 169, 204, 9, 21, 98, 189, 148, 110, 202, 236, 204, 110, 164,
+ 156, 43, 24, 252, 119, 61, 95, 97, 205, 253, 120, 83, 41, 204, 249,
+ 239, 138, 115, 219, 241, 190, 232, 158, 141, 219, 127, 234, 153, 20, 72,
+ 215, 224, 170, 155, 126, 65, 233, 23, 210, 50, 14, 55, 127, 25, 68,
+ 215, 96, 98, 220, 176, 88, 119, 116, 3, 229, 164, 50, 167, 149, 143,
+ 245, 194, 62, 184, 35, 243, 47, 176, 6, 189, 27, 71, 182, 240, 235,
+ 144, 30, 82, 217, 120, 114, 255, 68, 88, 111, 107, 182, 118, 56, 176,
+ 255, 162, 121, 156, 215, 165, 119, 8, 207, 128, 178, 230, 161, 159, 183,
+ 16, 124, 76, 90, 163, 208, 0, 159, 223, 247, 208, 113, 78, 232, 241,
+ 65, 112, 246, 186, 61, 193, 95, 126, 29, 97, 179, 6, 93, 201, 77,
+ 101, 70, 57, 169, 204, 217, 190, 177, 94, 216, 7, 119, 100, 174, 126,
+ 39, 133, 95, 31, 172, 15, 125, 191, 251, 223, 33, 247, 87, 100, 135,
+ 205, 255, 42, 133, 239, 180, 76, 27, 126, 199, 63, 70, 144, 249, 193,
+ 68, 237, 129, 87, 95, 166, 240, 95, 100, 112, 194, 54, 59, 35, 42,
+ 37, 244, 227, 208, 151, 251, 62, 16, 215, 160, 255, 239, 253, 130, 139,
+ 254, 84, 47, 35, 123, 246, 141, 0, 203, 26, 148, 25, 104, 203, 187,
+ 251, 125, 173, 50, 19, 128, 177, 15, 238, 200, 220, 9, 214, 160, 41,
+ 116, 102, 200, 210, 220, 59, 45, 166, 14, 185, 29, 218, 3, 214, 219,
+ 161, 161, 113, 97, 27, 106, 14, 19, 98, 162, 164, 129, 113, 251, 155,
+ 65, 153, 97, 125, 1, 97, 77, 94, 220, 19, 31, 82, 61, 219, 115,
+ 223, 5, 113, 156, 107, 141, 168, 17, 172, 25, 210, 44, 40, 186, 207,
+ 198, 64, 102, 13, 186, 148, 154, 202, 76, 24, 153, 3, 202, 197, 122,
+ 97, 31, 220, 145, 217, 15, 214, 224, 59, 41, 197, 246, 20, 235, 181,
+ 109, 239, 136, 187, 25, 251, 103, 27, 193, 246, 229, 4, 31, 232, 182,
+ 53, 80, 144, 113, 221, 213, 224, 240, 163, 80, 54, 106, 237, 187, 194,
+ 26, 188, 246, 91, 192, 190, 39, 159, 110, 110, 97, 20, 101, 38, 3,
+ 74, 52, 234, 240, 105, 169, 224, 62, 41, 5, 236, 215, 160, 164, 220,
+ 84, 102, 148, 147, 202, 172, 43, 11, 242, 186, 41, 115, 79, 24, 231,
+ 163, 97, 109, 247, 62, 136, 222, 191, 215, 123, 217, 245, 208, 56, 24,
+ 211, 201, 159, 13, 14, 27, 180, 53, 84, 144, 217, 56, 111, 240, 254,
+ 149, 80, 118, 253, 210, 9, 97, 220, 179, 74, 132, 239, 155, 178, 250,
+ 72, 200, 70, 81, 230, 73, 55, 87, 103, 172, 59, 154, 153, 209, 179,
+ 72, 197, 12, 235, 62, 197, 181, 114, 88, 246, 131, 101, 173, 50, 167,
+ 150, 137, 245, 194, 62, 184, 35, 243, 18, 104, 59, 84, 23, 25, 90,
+ 239, 97, 220, 222, 150, 29, 127, 222, 59, 11, 238, 87, 174, 25, 176,
+ 111, 226, 186, 91, 130, 61, 206, 205, 237, 31, 154, 4, 253, 242, 159,
+ 120, 68, 232, 67, 177, 54, 127, 236, 157, 212, 230, 200, 190, 221, 226,
+ 62, 101, 217, 184, 155, 129, 154, 161, 177, 193, 79, 251, 173, 204, 176,
+ 238, 83, 220, 147, 25, 229, 180, 236, 7, 75, 199, 122, 9, 99, 237,
+ 134, 204, 95, 66, 219, 53, 198, 118, 221, 91, 191, 85, 231, 189, 159,
+ 175, 58, 27, 186, 19, 246, 36, 103, 211, 58, 135, 61, 249, 235, 180,
+ 32, 51, 191, 164, 243, 254, 29, 80, 86, 242, 240, 247, 194, 56, 151,
+ 88, 244, 237, 222, 128, 218, 217, 33, 84, 159, 183, 127, 118, 109, 91,
+ 197, 140, 45, 219, 195, 127, 217, 18, 204, 236, 83, 220, 210, 103, 148,
+ 115, 58, 115, 46, 128, 125, 112, 71, 230, 72, 216, 167, 44, 79, 56,
+ 18, 82, 179, 171, 49, 164, 224, 95, 45, 247, 247, 189, 151, 194, 55,
+ 189, 118, 112, 255, 119, 105, 17, 130, 221, 216, 248, 240, 96, 88, 111,
+ 40, 43, 94, 43, 66, 24, 231, 238, 207, 194, 67, 181, 25, 109, 246,
+ 141, 16, 101, 126, 209, 162, 80, 224, 195, 234, 47, 183, 246, 186, 186,
+ 97, 187, 221, 62, 197, 165, 62, 123, 139, 207, 238, 103, 80, 125, 134,
+ 61, 55, 246, 129, 230, 22, 96, 62, 1, 205, 45, 192, 247, 202, 96,
+ 174, 1, 155, 91, 16, 23, 31, 68, 236, 147, 96, 173, 57, 51, 121,
+ 203, 4, 162, 188, 85, 11, 173, 185, 5, 248, 44, 32, 245, 93, 176,
+ 191, 141, 29, 115, 102, 2, 210, 31, 43, 132, 11, 234, 115, 123, 130,
+ 108, 90, 215, 121, 53, 125, 220, 204, 45, 192, 45, 86, 94, 115, 11,
+ 134, 139, 185, 5, 135, 123, 19, 75, 110, 193, 88, 23, 185, 5, 11,
+ 180, 154, 140, 97, 191, 52, 48, 60, 122, 220, 66, 67, 191, 155, 26,
+ 103, 247, 221, 212, 109, 245, 155, 137, 223, 87, 21, 254, 50, 40, 158,
+ 16, 203, 13, 237, 100, 44, 94, 231, 79, 254, 163, 228, 176, 198, 255,
+ 137, 239, 166, 202, 231, 124, 57, 230, 204, 232, 85, 16, 187, 194, 165,
+ 43, 33, 94, 74, 243, 21, 48, 208, 124, 185, 47, 92, 1, 161, 253,
+ 186, 220, 28, 245, 79, 143, 102, 171, 221, 205, 45, 16, 190, 231, 45,
+ 234, 4, 103, 151, 115, 128, 114, 73, 230, 197, 74, 228, 7, 176, 121,
+ 177, 72, 183, 73, 21, 107, 243, 76, 3, 251, 40, 151, 23, 59, 42,
+ 105, 152, 152, 26, 235, 60, 61, 32, 7, 198, 71, 163, 138, 117, 254,
+ 189, 81, 149, 181, 47, 56, 142, 52, 47, 22, 105, 254, 39, 242, 98,
+ 177, 141, 55, 145, 23, 155, 6, 115, 157, 51, 208, 121, 159, 104, 185,
+ 224, 255, 7, 198, 90, 158, 133, 34, 141, 179, 188, 88, 196, 113, 149,
+ 23, 27, 151, 48, 58, 122, 112, 242, 216, 232, 100, 24, 91, 103, 143,
+ 80, 178, 223, 141, 181, 121, 22, 138, 247, 175, 155, 23, 75, 237, 39,
+ 218, 167, 25, 118, 50, 97, 93, 3, 148, 23, 234, 154, 208, 56, 114,
+ 128, 185, 109, 107, 236, 156, 56, 122, 172, 19, 77, 203, 169, 111, 238,
+ 111, 3, 145, 134, 210, 39, 0, 140, 252, 108, 246, 191, 206, 88, 248,
+ 91, 233, 19, 24, 122, 37, 192, 200, 143, 238, 249, 157, 183, 14, 122,
+ 86, 194, 74, 175, 100, 232, 211, 251, 195, 88, 193, 189, 249, 156, 67,
+ 138, 26, 244, 166, 148, 149, 30, 105, 40, 189, 22, 96, 228, 39, 158,
+ 237, 72, 50, 208, 151, 177, 210, 107, 25, 250, 220, 126, 176, 175, 132,
+ 123, 241, 60, 75, 146, 62, 173, 156, 149, 30, 105, 40, 125, 42, 192,
+ 200, 79, 60, 147, 150, 238, 192, 96, 43, 125, 42, 67, 31, 0, 48,
+ 242, 179, 217, 203, 35, 151, 247, 109, 201, 141, 117, 173, 244, 1, 12,
+ 125, 118, 223, 88, 175, 84, 134, 94, 74, 7, 52, 126, 204, 252, 247,
+ 101, 230, 31, 96, 228, 103, 221, 151, 59, 239, 66, 90, 109, 102, 254,
+ 25, 122, 37, 192, 200, 143, 221, 83, 56, 229, 80, 140, 153, 127, 134,
+ 62, 253, 29, 24, 59, 184, 103, 247, 170, 206, 232, 245, 53, 153, 249,
+ 127, 135, 153, 127, 128, 149, 86, 122, 201, 37, 144, 83, 132, 153, 127,
+ 134, 62, 183, 15, 204, 63, 220, 219, 239, 151, 237, 89, 232, 170, 51,
+ 243, 223, 135, 153, 127, 128, 181, 182, 244, 78, 101, 48, 22, 98, 230,
+ 159, 161, 15, 0, 24, 249, 49, 207, 7, 156, 14, 95, 142, 142, 153,
+ 127, 134, 62, 187, 55, 204, 191, 133, 94, 218, 2, 164, 121, 49, 243,
+ 223, 155, 153, 127, 128, 145, 31, 115, 214, 239, 92, 1, 170, 48, 243,
+ 207, 208, 43, 1, 70, 126, 108, 12, 238, 116, 254, 10, 48, 243, 207,
+ 208, 167, 247, 130, 249, 71, 122, 230, 252, 219, 25, 125, 78, 69, 102,
+ 254, 123, 49, 243, 15, 176, 210, 74, 47, 169, 129, 58, 15, 102, 254,
+ 25, 122, 140, 241, 144, 159, 195, 25, 188, 253, 252, 149, 103, 230, 191,
+ 167, 149, 158, 136, 252, 28, 98, 99, 123, 17, 166, 60, 86, 208, 248,
+ 23, 99, 94, 26, 255, 226, 187, 204, 48, 30, 182, 139, 127, 37, 223,
+ 111, 248, 186, 241, 175, 205, 115, 126, 136, 127, 85, 221, 98, 189, 140,
+ 69, 156, 196, 191, 127, 67, 236, 11, 151, 177, 43, 200, 213, 22, 230,
+ 182, 219, 219, 248, 247, 223, 20, 255, 234, 96, 62, 116, 221, 98, 189,
+ 242, 45, 155, 16, 105, 189, 94, 252, 75, 117, 194, 62, 254, 69, 185,
+ 242, 27, 255, 206, 235, 102, 141, 165, 112, 192, 80, 79, 165, 226, 32,
+ 212, 81, 186, 14, 141, 93, 242, 30, 7, 33, 13, 165, 215, 1, 140,
+ 252, 242, 18, 7, 233, 24, 122, 130, 244, 93, 242, 22, 7, 17, 134,
+ 62, 173, 51, 204, 107, 151, 188, 197, 65, 72, 67, 233, 53, 0, 35,
+ 191, 188, 196, 65, 26, 134, 62, 39, 42, 214, 11, 249, 229, 37, 14,
+ 66, 26, 74, 175, 7, 24, 249, 229, 37, 14, 210, 51, 244, 42, 128,
+ 145, 95, 94, 226, 32, 21, 67, 111, 236, 4, 251, 194, 168, 188, 197,
+ 65, 72, 99, 153, 127, 128, 145, 95, 94, 226, 32, 29, 67, 79, 0,
+ 70, 126, 121, 137, 131, 8, 67, 159, 214, 17, 230, 191, 83, 222, 226,
+ 32, 164, 177, 204, 63, 192, 164, 83, 222, 226, 32, 13, 67, 159, 211,
+ 1, 230, 191, 99, 222, 226, 32, 164, 177, 204, 63, 192, 154, 142, 121,
+ 139, 131, 244, 12, 189, 10, 96, 228, 151, 151, 56, 72, 197, 208, 27,
+ 219, 195, 252, 119, 200, 91, 28, 132, 52, 150, 249, 7, 24, 249, 229,
+ 37, 14, 210, 49, 244, 4, 96, 228, 151, 151, 56, 136, 48, 244, 105,
+ 237, 96, 254, 219, 231, 45, 14, 66, 26, 203, 252, 3, 76, 218, 231,
+ 45, 14, 210, 48, 244, 232, 235, 145, 95, 94, 226, 32, 164, 97, 227,
+ 32, 77, 187, 188, 197, 65, 24, 251, 52, 101, 232, 49, 46, 178, 198,
+ 65, 248, 107, 114, 142, 195, 159, 223, 239, 193, 59, 251, 83, 181, 200,
+ 219, 59, 234, 126, 241, 244, 62, 232, 234, 123, 240, 111, 250, 93, 150,
+ 246, 223, 243, 148, 251, 30, 60, 202, 18, 212, 182, 136, 230, 175, 166,
+ 211, 223, 208, 247, 224, 243, 247, 247, 127, 237, 187, 159, 81, 173, 9,
+ 193, 135, 221, 248, 110, 195, 32, 106, 191, 236, 222, 165, 16, 213, 154,
+ 126, 119, 185, 185, 211, 177, 208, 61, 122, 252, 198, 95, 49, 203, 17,
+ 87, 207, 106, 217, 252, 62, 79, 27, 92, 218, 31, 236, 3, 237, 15,
+ 126, 31, 154, 125, 119, 163, 165, 63, 129, 1, 78, 219, 204, 126, 232,
+ 186, 63, 250, 174, 102, 94, 170, 8, 176, 51, 17, 174, 215, 155, 39,
+ 177, 126, 15, 97, 95, 84, 77, 152, 13, 77, 227, 74, 61, 95, 6,
+ 31, 0, 56, 62, 120, 142, 218, 177, 63, 156, 67, 124, 40, 124, 39,
+ 3, 218, 105, 36, 242, 219, 31, 245, 133, 38, 1, 104, 145, 143, 240,
+ 172, 58, 69, 97, 194, 178, 216, 224, 57, 89, 108, 25, 124, 236, 24,
+ 234, 80, 166, 111, 156, 108, 71, 75, 191, 251, 130, 253, 170, 103, 25,
+ 7, 15, 136, 102, 57, 8, 251, 77, 130, 12, 237, 196, 254, 54, 176,
+ 153, 27, 103, 239, 168, 53, 207, 145, 233, 229, 203, 151, 166, 165, 75,
+ 151, 10, 215, 139, 23, 47, 164, 102, 149, 206, 23, 206, 17, 157, 47,
+ 252, 254, 47, 171, 131, 214, 249, 146, 120, 79, 190, 204, 124, 25, 121,
+ 51, 175, 4, 53, 248, 37, 141, 235, 249, 242, 102, 230, 76, 228, 46,
+ 228, 33, 55, 153, 222, 80, 115, 232, 204, 57, 181, 156, 254, 89, 158,
+ 39, 106, 204, 243, 133, 252, 112, 174, 19, 132, 185, 22, 115, 11, 82,
+ 136, 9, 203, 112, 190, 236, 202, 140, 67, 237, 202, 246, 66, 89, 178,
+ 29, 109, 240, 244, 134, 198, 227, 130, 44, 214, 50, 144, 207, 184, 231,
+ 204, 185, 44, 187, 50, 205, 126, 39, 101, 135, 236, 104, 233, 89, 47,
+ 142, 83, 61, 139, 141, 226, 72, 65, 130, 63, 109, 208, 83, 200, 179,
+ 45, 0, 119, 8, 43, 64, 47, 60, 225, 14, 97, 220, 117, 121, 17,
+ 79, 1, 22, 190, 215, 195, 153, 199, 184, 129, 141, 157, 115, 161, 35,
+ 41, 41, 41, 236, 229, 218, 27, 230, 157, 15, 247, 47, 231, 67, 117,
+ 31, 245, 221, 98, 123, 193, 127, 179, 239, 111, 176, 232, 190, 196, 247,
+ 238, 211, 31, 72, 235, 190, 6, 248, 42, 67, 204, 188, 210, 51, 75,
+ 122, 212, 33, 81, 46, 117, 191, 43, 49, 255, 96, 169, 147, 254, 182,
+ 52, 95, 246, 186, 79, 159, 117, 152, 203, 45, 207, 97, 194, 173, 123,
+ 234, 180, 2, 230, 103, 22, 61, 10, 226, 175, 80, 71, 9, 107, 162,
+ 171, 184, 44, 217, 239, 204, 163, 30, 154, 203, 136, 179, 50, 98, 87,
+ 70, 28, 241, 244, 70, 137, 50, 59, 90, 163, 51, 126, 248, 142, 166,
+ 198, 78, 240, 236, 101, 57, 200, 57, 148, 9, 120, 45, 29, 249, 25,
+ 53, 142, 101, 44, 158, 130, 182, 235, 76, 230, 150, 142, 109, 24, 157,
+ 180, 235, 48, 126, 196, 121, 153, 209, 201, 152, 26, 157, 180, 235, 116,
+ 62, 90, 58, 226, 57, 200, 162, 177, 47, 227, 204, 188, 236, 199, 165,
+ 165, 253, 24, 112, 102, 58, 39, 120, 206, 218, 112, 24, 43, 137, 50,
+ 135, 254, 74, 148, 57, 140, 115, 99, 39, 178, 56, 105, 67, 160, 117,
+ 210, 174, 109, 25, 252, 241, 142, 122, 37, 240, 215, 56, 41, 35, 142,
+ 101, 122, 39, 99, 224, 172, 93, 7, 221, 213, 176, 186, 207, 200, 119,
+ 208, 201, 56, 27, 157, 204, 165, 209, 137, 124, 7, 109, 117, 215, 232,
+ 132, 159, 94, 162, 93, 7, 126, 18, 101, 14, 242, 101, 74, 224, 57,
+ 41, 115, 218, 95, 103, 253, 112, 82, 166, 119, 50, 6, 196, 73, 153,
+ 62, 195, 201, 250, 176, 111, 215, 104, 50, 165, 24, 157, 172, 203, 12,
+ 39, 54, 204, 232, 100, 237, 27, 157, 216, 23, 39, 101, 246, 50, 147,
+ 131, 78, 218, 61, 248, 202, 100, 50, 56, 177, 37, 70, 39, 246, 202,
+ 89, 187, 7, 157, 216, 48, 59, 61, 208, 59, 195, 35, 206, 203, 28,
+ 100, 118, 38, 139, 51, 126, 78, 250, 171, 119, 160, 69, 63, 131, 65,
+ 9, 250, 188, 122, 150, 133, 82, 90, 136, 208, 148, 226, 243, 134, 2,
+ 16, 193, 208, 223, 198, 196, 39, 244, 74, 209, 135, 41, 136, 249, 21,
+ 125, 158, 16, 177, 21, 20, 226, 27, 164, 84, 194, 157, 57, 217, 220,
+ 155, 20, 130, 88, 7, 99, 160, 106, 112, 21, 133, 59, 111, 1, 46,
+ 76, 124, 72, 17, 82, 28, 224, 96, 248, 191, 8, 212, 40, 133, 242,
+ 98, 80, 83, 156, 148, 5, 184, 4, 252, 143, 245, 165, 197, 35, 244,
+ 18, 164, 36, 41, 37, 192, 126, 164, 12, 64, 37, 5, 28, 252, 30,
+ 95, 41, 1, 31, 191, 215, 91, 12, 160, 82, 66, 121, 5, 226, 11,
+ 126, 182, 156, 0, 151, 3, 168, 50, 169, 36, 224, 148, 135, 154, 114,
+ 164, 34, 192, 203, 225, 255, 114, 80, 90, 7, 224, 57, 128, 81, 21,
+ 90, 175, 44, 224, 248, 18, 21, 220, 85, 17, 104, 171, 66, 59, 37,
+ 4, 217, 33, 198, 128, 150, 75, 66, 137, 82, 40, 41, 1, 253, 175,
+ 46, 148, 87, 7, 136, 39, 53, 5, 184, 50, 212, 84, 39, 53, 4,
+ 184, 6, 64, 53, 73, 61, 1, 174, 69, 234, 146, 48, 82, 91, 104,
+ 171, 14, 180, 90, 23, 74, 16, 174, 11, 88, 245, 160, 6, 113, 42,
+ 1, 117, 13, 40, 65, 184, 62, 9, 36, 65, 196, 95, 128, 253, 1,
+ 106, 64, 2, 0, 142, 36, 33, 80, 227, 79, 26, 10, 180, 13, 1,
+ 10, 32, 141, 0, 62, 13, 24, 193, 164, 49, 96, 33, 78, 32, 105,
+ 6, 119, 65, 2, 109, 48, 105, 66, 58, 66, 13, 150, 55, 35, 157,
+ 224, 46, 88, 40, 175, 73, 112, 139, 219, 84, 128, 155, 2, 212, 9,
+ 106, 17, 174, 7, 53, 77, 73, 115, 1, 110, 14, 80, 51, 224, 134,
+ 112, 11, 18, 10, 45, 135, 8, 237, 214, 6, 121, 67, 161, 4, 225,
+ 80, 192, 10, 132, 26, 196, 9, 3, 234, 230, 80, 162, 20, 206, 244,
+ 11, 128, 129, 8, 23, 224, 112, 128, 212, 164, 139, 0, 243, 80, 19,
+ 14, 237, 41, 5, 61, 11, 135, 210, 78, 2, 220, 146, 68, 144, 86,
+ 128, 165, 20, 178, 114, 10, 194, 93, 75, 1, 142, 32, 173, 65, 242,
+ 86, 130, 110, 96, 92, 221, 26, 74, 16, 110, 5, 165, 109, 73, 27,
+ 1, 110, 3, 80, 123, 210, 14, 224, 161, 192, 161, 21, 220, 107, 5,
+ 90, 45, 64, 237, 72, 7, 161, 239, 77, 72, 20, 233, 12, 35, 129,
+ 112, 39, 104, 53, 10, 74, 16, 39, 10, 176, 58, 64, 13, 150, 119,
+ 1, 106, 45, 148, 40, 197, 152, 12, 38, 91, 136, 255, 26, 176, 206,
+ 195, 85, 252, 58, 97, 194, 4, 83, 100, 100, 164, 240, 121, 246, 236,
+ 89, 172, 249, 39, 133, 216, 127, 233, 66, 158, 79, 76, 76, 140, 41,
+ 36, 36, 196, 212, 186, 117, 107, 211, 196, 137, 19, 205, 124, 184, 188,
+ 243, 65, 122, 228, 131, 252, 242, 195, 231, 201, 147, 39, 216, 31, 225,
+ 83, 252, 141, 226, 215, 234, 23, 142, 75, 131, 6, 13, 76, 205, 154,
+ 53, 51, 45, 88, 176, 224, 181, 249, 168, 84, 42, 147, 183, 183, 183,
+ 169, 116, 233, 210, 216, 191, 215, 238, 23, 210, 163, 13, 196, 171, 66,
+ 133, 10, 175, 205, 167, 84, 169, 82, 22, 62, 208, 191, 215, 238, 23,
+ 229, 33, 94, 111, 132, 15, 140, 211, 107, 247, 235, 77, 241, 161, 227,
+ 131, 159, 176, 62, 164, 251, 101, 75, 103, 207, 87, 208, 31, 208, 27,
+ 65, 127, 222, 196, 56, 227, 252, 187, 156, 119, 25, 121, 80, 15, 113,
+ 125, 33, 159, 55, 49, 206, 56, 62, 111, 162, 95, 226, 120, 231, 139,
+ 15, 174, 47, 113, 157, 189, 17, 253, 177, 200, 227, 241, 223, 235, 151,
+ 56, 190, 212, 78, 191, 17, 253, 201, 207, 248, 136, 250, 71, 237, 116,
+ 190, 198, 89, 161, 80, 228, 123, 93, 208, 245, 37, 218, 251, 124, 249,
+ 47, 240, 55, 166, 201, 147, 39, 231, 203, 239, 208, 245, 37, 250, 195,
+ 215, 230, 35, 250, 99, 161, 95, 249, 241, 59, 162, 125, 23, 198, 25,
+ 198, 59, 223, 235, 75, 244, 63, 249, 210, 31, 26, 39, 228, 215, 127,
+ 209, 184, 37, 63, 250, 67, 249, 188, 41, 251, 99, 99, 55, 184, 255,
+ 46, 159, 55, 225, 151, 169, 253, 201, 47, 159, 55, 229, 119, 168, 253,
+ 201, 239, 248, 188, 41, 191, 44, 198, 151, 111, 204, 254, 228, 215, 174,
+ 138, 241, 247, 27, 179, 63, 111, 194, 239, 160, 254, 188, 137, 245, 133,
+ 243, 254, 166, 236, 79, 126, 227, 4, 113, 63, 144, 111, 251, 35, 218,
+ 247, 55, 182, 255, 18, 215, 217, 107, 247, 75, 244, 127, 111, 108, 255,
+ 37, 174, 179, 124, 239, 191, 100, 227, 112, 55, 214, 5, 213, 159, 55,
+ 181, 255, 202, 175, 254, 96, 252, 147, 223, 253, 23, 187, 143, 123, 83,
+ 251, 175, 252, 172, 47, 186, 207, 125, 83, 251, 175, 252, 246, 75, 180,
+ 239, 52, 222, 204, 151, 254, 80, 255, 149, 159, 184, 69, 244, 127, 111,
+ 196, 127, 209, 184, 197, 133, 254, 88, 114, 36, 90, 88, 159, 59, 226,
+ 247, 7, 217, 247, 110, 71, 181, 142, 138, 73, 138, 149, 206, 203, 200,
+ 249, 197, 245, 51, 119, 93, 19, 51, 175, 101, 71, 58, 121, 213, 209,
+ 118, 116, 249, 220, 177, 59, 92, 29, 173, 188, 51, 105, 249, 181, 19,
+ 69, 53, 213, 43, 239, 116, 235, 153, 251, 251, 248, 124, 17, 218, 105,
+ 36, 242, 67, 90, 205, 212, 245, 251, 216, 243, 225, 156, 19, 47, 121,
+ 219, 50, 133, 80, 182, 106, 193, 193, 3, 44, 94, 141, 225, 94, 26,
+ 103, 101, 187, 38, 36, 218, 60, 75, 159, 100, 80, 104, 126, 109, 52,
+ 221, 166, 236, 200, 194, 231, 252, 143, 237, 102, 219, 148, 133, 237, 185,
+ 202, 55, 175, 218, 202, 166, 44, 107, 211, 69, 158, 52, 158, 185, 151,
+ 45, 91, 181, 224, 42, 31, 52, 83, 99, 243, 108, 254, 167, 107, 79,
+ 249, 139, 237, 102, 219, 148, 45, 123, 228, 169, 57, 154, 243, 190, 77,
+ 217, 241, 28, 31, 77, 226, 143, 237, 212, 108, 223, 176, 236, 157, 191,
+ 150, 218, 224, 53, 232, 234, 169, 41, 122, 118, 171, 77, 89, 114, 205,
+ 103, 188, 121, 156, 173, 180, 127, 7, 254, 200, 247, 11, 155, 106, 131,
+ 215, 255, 131, 147, 40, 179, 205, 152, 78, 123, 112, 17, 250, 102, 59,
+ 6, 169, 7, 159, 34, 63, 155, 178, 206, 241, 5, 52, 41, 239, 108,
+ 205, 98, 219, 192, 57, 58, 244, 116, 153, 13, 94, 205, 225, 94, 198,
+ 46, 241, 219, 108, 218, 189, 126, 162, 168, 93, 153, 130, 150, 217, 208,
+ 174, 59, 252, 155, 193, 182, 76, 33, 148, 141, 92, 55, 221, 161, 13,
+ 251, 178, 242, 171, 126, 53, 216, 63, 131, 171, 150, 253, 189, 161, 92,
+ 151, 41, 54, 120, 43, 34, 210, 13, 246, 125, 251, 227, 229, 60, 67,
+ 192, 31, 147, 237, 240, 244, 14, 252, 230, 214, 254, 200, 16, 229, 167,
+ 87, 219, 62, 199, 16, 248, 217, 148, 93, 94, 252, 189, 97, 251, 47,
+ 41, 54, 101, 187, 38, 124, 239, 192, 111, 234, 250, 227, 134, 160, 239,
+ 91, 58, 240, 179, 215, 151, 254, 97, 75, 29, 240, 94, 196, 124, 228,
+ 192, 15, 241, 186, 196, 183, 204, 178, 231, 103, 175, 207, 216, 174, 214,
+ 14, 175, 207, 154, 178, 134, 170, 211, 51, 108, 117, 119, 113, 29, 187,
+ 50, 5, 140, 105, 178, 193, 126, 222, 254, 57, 213, 215, 97, 222, 194,
+ 70, 70, 26, 110, 167, 151, 176, 193, 155, 241, 224, 126, 150, 125, 153,
+ 247, 138, 67, 89, 246, 180, 233, 31, 207, 207, 178, 111, 3, 172, 157,
+ 33, 226, 94, 7, 27, 249, 206, 69, 123, 24, 82, 147, 251, 216, 172,
+ 243, 119, 63, 8, 113, 40, 211, 251, 116, 118, 224, 167, 153, 253, 81,
+ 184, 125, 89, 218, 184, 205, 234, 176, 61, 99, 109, 202, 98, 15, 252,
+ 170, 182, 31, 231, 221, 19, 182, 171, 87, 68, 36, 216, 200, 162, 79,
+ 156, 27, 110, 175, 247, 98, 187, 54, 101, 26, 191, 236, 3, 35, 214,
+ 77, 183, 157, 243, 142, 61, 194, 237, 203, 180, 126, 115, 212, 197, 42,
+ 182, 176, 41, 203, 105, 244, 181, 131, 44, 217, 147, 22, 168, 67, 70,
+ 214, 176, 29, 171, 138, 113, 225, 246, 235, 3, 219, 181, 47, 83, 86,
+ 172, 203, 219, 203, 231, 187, 170, 56, 111, 191, 86, 197, 50, 103, 180,
+ 54, 243, 118, 164, 205, 94, 71, 126, 93, 182, 56, 242, 131, 50, 207,
+ 21, 17, 182, 54, 118, 228, 16, 7, 218, 78, 126, 90, 7, 90, 177,
+ 204, 134, 246, 75, 101, 172, 131, 44, 88, 118, 114, 18, 111, 59, 31,
+ 239, 108, 117, 160, 21, 101, 206, 178, 127, 14, 57, 195, 195, 236, 3,
+ 235, 137, 190, 205, 151, 148, 37, 229, 8, 17, 158, 237, 248, 146, 138,
+ 112, 71, 132, 103, 62, 190, 164, 2, 220, 81, 24, 159, 234, 17, 225,
+ 89, 98, 117, 82, 11, 74, 136, 240, 60, 167, 22, 241, 19, 225, 106,
+ 194, 147, 184, 90, 34, 92, 27, 202, 107, 137, 56, 181, 133, 167, 122,
+ 230, 242, 74, 128, 83, 93, 44, 175, 68, 106, 8, 111, 9, 198, 242,
+ 58, 128, 83, 91, 44, 199, 39, 116, 149, 44, 112, 125, 82, 67, 196,
+ 169, 11, 56, 117, 196, 242, 186, 164, 42, 220, 153, 203, 235, 1, 92,
+ 215, 130, 95, 15, 40, 104, 57, 62, 113, 52, 195, 85, 224, 174, 178,
+ 136, 227, 79, 26, 144, 134, 98, 127, 253, 133, 39, 122, 230, 56, 164,
+ 49, 244, 173, 129, 136, 239, 79, 154, 146, 198, 34, 220, 68, 120, 238,
+ 71, 105, 3, 72, 83, 17, 63, 0, 106, 154, 138, 56, 1, 36, 144,
+ 52, 17, 224, 18, 0, 5, 139, 48, 62, 87, 108, 36, 188, 99, 92,
+ 41, 60, 45, 12, 38, 129, 2, 220, 147, 52, 35, 106, 18, 46, 242,
+ 84, 147, 48, 17, 174, 6, 48, 79, 194, 68, 62, 60, 9, 21, 225,
+ 106, 128, 143, 120, 102, 88, 3, 229, 188, 72, 171, 33, 33, 36, 84,
+ 44, 111, 9, 176, 70, 44, 143, 0, 184, 165, 5, 110, 65, 66, 68,
+ 156, 86, 0, 71, 136, 229, 173, 72, 115, 210, 194, 194, 31, 159, 246,
+ 81, 184, 57, 220, 153, 101, 104, 75, 90, 147, 54, 226, 88, 181, 37,
+ 237, 224, 206, 220, 151, 206, 164, 19, 137, 18, 203, 59, 19, 45, 233,
+ 36, 246, 87, 11, 26, 213, 73, 228, 211, 145, 180, 39, 29, 68, 156,
+ 142, 164, 27, 220, 153, 203, 59, 147, 46, 68, 43, 242, 233, 10, 53,
+ 90, 81, 158, 174, 128, 211, 81, 108, 87, 73, 138, 9, 239, 226, 68,
+ 90, 124, 166, 93, 76, 164, 85, 146, 194, 112, 103, 110, 171, 176, 240,
+ 76, 219, 140, 95, 132, 248, 136, 48, 62, 123, 45, 36, 188, 155, 84,
+ 41, 60, 65, 46, 36, 224, 34, 255, 18, 194, 147, 114, 90, 238, 37,
+ 228, 63, 34, 92, 18, 224, 18, 34, 142, 66, 140, 245, 148, 164, 160,
+ 144, 67, 168, 16, 96, 79, 82, 134, 152, 191, 201, 165, 20, 158, 212,
+ 151, 17, 225, 72, 160, 45, 40, 188, 41, 21, 249, 20, 128, 114, 79,
+ 177, 188, 20, 148, 151, 20, 225, 130, 80, 94, 192, 82, 94, 70, 248,
+ 166, 186, 82, 120, 166, 94, 90, 224, 139, 50, 227, 186, 244, 45, 99,
+ 142, 73, 27, 136, 235, 210, 241, 185, 136, 109, 153, 201, 238, 143, 198,
+ 230, 210, 57, 138, 121, 227, 195, 189, 229, 243, 150, 207, 91, 62, 111,
+ 249, 188, 229, 243, 150, 207, 91, 62, 111, 249, 188, 229, 243, 150, 207,
+ 91, 62, 111, 249, 188, 229, 243, 150, 207, 91, 62, 111, 249, 188, 229,
+ 243, 191, 132, 143, 212, 111, 245, 254, 111, 231, 243, 118, 222, 255, 127,
+ 228, 67, 115, 4, 48, 47, 128, 230, 8, 224, 59, 214, 48, 103, 64,
+ 151, 104, 126, 182, 31, 213, 26, 223, 239, 70, 95, 111, 220, 204, 33,
+ 71, 64, 229, 226, 187, 201, 1, 192, 183, 78, 128, 143, 240, 138, 84,
+ 227, 192, 142, 94, 198, 7, 237, 189, 234, 144, 158, 146, 121, 2, 103,
+ 224, 10, 225, 204, 188, 151, 181, 141, 48, 36, 92, 95, 139, 121, 1,
+ 153, 138, 196, 233, 154, 187, 15, 234, 105, 140, 123, 207, 56, 228, 8,
+ 40, 152, 94, 89, 126, 67, 182, 177, 245, 187, 201, 57, 30, 226, 251,
+ 84, 149, 32, 3, 180, 223, 72, 108, 167, 195, 198, 233, 134, 221, 101,
+ 234, 24, 106, 142, 86, 242, 234, 39, 222, 207, 151, 167, 16, 211, 207,
+ 156, 191, 161, 107, 169, 97, 134, 209, 85, 7, 240, 225, 5, 54, 94,
+ 214, 78, 34, 166, 105, 191, 63, 10, 63, 60, 38, 214, 80, 3, 240,
+ 30, 112, 3, 158, 223, 76, 81, 152, 254, 60, 119, 196, 208, 254, 244,
+ 117, 67, 187, 216, 123, 234, 121, 109, 21, 75, 86, 62, 35, 166, 91,
+ 23, 46, 27, 102, 241, 223, 26, 10, 247, 111, 200, 39, 60, 46, 253,
+ 119, 206, 20, 98, 154, 161, 254, 219, 176, 40, 108, 167, 128, 55, 251,
+ 73, 175, 103, 75, 128, 246, 94, 124, 5, 227, 173, 141, 255, 24, 102,
+ 76, 250, 65, 93, 61, 55, 253, 21, 129, 118, 75, 173, 43, 101, 252,
+ 114, 122, 33, 227, 135, 35, 235, 242, 145, 59, 159, 13, 91, 82, 132,
+ 152, 234, 61, 44, 102, 60, 221, 95, 105, 68, 188, 201, 161, 91, 230,
+ 47, 121, 69, 76, 85, 207, 55, 53, 206, 158, 90, 194, 168, 91, 90,
+ 153, 247, 206, 217, 60, 190, 153, 74, 97, 106, 24, 94, 213, 24, 31,
+ 84, 194, 120, 123, 108, 16, 223, 161, 114, 244, 7, 87, 47, 17, 83,
+ 185, 254, 213, 141, 199, 122, 61, 51, 196, 71, 29, 81, 255, 241, 115,
+ 183, 247, 198, 189, 32, 166, 217, 217, 26, 129, 54, 197, 84, 67, 125,
+ 238, 215, 244, 73, 231, 255, 84, 88, 218, 189, 153, 89, 87, 29, 220,
+ 186, 248, 226, 185, 62, 214, 126, 140, 250, 106, 166, 250, 158, 199, 55,
+ 164, 164, 158, 152, 126, 129, 113, 209, 194, 184, 244, 215, 44, 83, 207,
+ 47, 84, 236, 214, 231, 211, 136, 165, 221, 230, 11, 23, 133, 143, 185,
+ 243, 193, 248, 117, 23, 21, 166, 1, 91, 226, 13, 207, 135, 151, 50,
+ 206, 219, 145, 193, 55, 189, 186, 117, 124, 55, 63, 133, 73, 85, 239,
+ 70, 86, 169, 65, 127, 24, 106, 173, 89, 192, 95, 120, 53, 75, 249,
+ 199, 20, 133, 233, 157, 6, 93, 213, 149, 55, 191, 52, 248, 70, 207,
+ 230, 163, 148, 127, 78, 233, 175, 32, 166, 202, 123, 86, 242, 61, 111,
+ 221, 53, 204, 239, 59, 154, 31, 86, 170, 208, 227, 170, 48, 126, 126,
+ 223, 127, 206, 127, 80, 253, 39, 3, 231, 49, 134, 15, 46, 193, 229,
+ 126, 63, 153, 152, 38, 141, 249, 73, 29, 215, 53, 35, 107, 157, 223,
+ 42, 190, 65, 241, 90, 127, 158, 159, 172, 48, 205, 76, 175, 148, 85,
+ 201, 191, 180, 177, 94, 253, 61, 124, 56, 41, 54, 239, 228, 9, 133,
+ 233, 175, 42, 105, 106, 44, 219, 123, 55, 133, 47, 224, 179, 87, 191,
+ 255, 41, 49, 69, 102, 252, 200, 79, 25, 95, 214, 184, 179, 121, 123,
+ 126, 72, 248, 226, 212, 95, 238, 43, 76, 21, 14, 63, 231, 3, 215,
+ 43, 132, 178, 145, 222, 15, 114, 207, 129, 124, 91, 23, 255, 196, 79,
+ 168, 30, 97, 184, 117, 62, 133, 255, 165, 200, 236, 63, 195, 65, 150,
+ 176, 167, 243, 213, 63, 21, 169, 199, 123, 167, 110, 231, 15, 150, 56,
+ 153, 123, 17, 218, 93, 61, 244, 10, 255, 207, 186, 245, 89, 229, 160,
+ 31, 83, 189, 130, 254, 250, 10, 240, 252, 85, 31, 242, 77, 46, 174,
+ 225, 251, 244, 220, 196, 15, 171, 181, 162, 224, 31, 19, 137, 233, 82,
+ 216, 51, 126, 205, 79, 83, 248, 169, 189, 151, 241, 171, 154, 15, 233,
+ 61, 186, 131, 194, 20, 30, 179, 90, 125, 243, 153, 143, 81, 55, 99,
+ 61, 223, 250, 217, 168, 247, 134, 249, 17, 211, 177, 31, 15, 243, 117,
+ 39, 251, 24, 145, 159, 230, 214, 236, 232, 37, 233, 196, 148, 116, 225,
+ 59, 254, 220, 225, 39, 134, 87, 218, 15, 248, 93, 53, 54, 223, 49,
+ 76, 32, 166, 86, 157, 55, 240, 43, 119, 55, 50, 68, 116, 201, 228,
+ 163, 203, 85, 186, 249, 23, 232, 233, 211, 144, 84, 222, 72, 78, 134,
+ 125, 165, 63, 193, 231, 60, 27, 124, 181, 193, 251, 196, 116, 254, 199,
+ 157, 252, 198, 35, 65, 134, 47, 238, 204, 228, 239, 87, 223, 92, 239,
+ 219, 121, 196, 212, 125, 210, 167, 252, 238, 161, 235, 213, 158, 119, 143,
+ 242, 47, 94, 252, 94, 240, 40, 62, 215, 175, 252, 55, 223, 174, 228,
+ 169, 3, 89, 176, 190, 30, 20, 41, 255, 240, 42, 140, 193, 142, 163,
+ 87, 120, 255, 250, 233, 134, 6, 7, 134, 243, 247, 254, 220, 118, 101,
+ 238, 68, 51, 237, 94, 160, 93, 191, 184, 35, 191, 224, 236, 136, 178,
+ 229, 230, 153, 219, 189, 10, 237, 246, 25, 217, 134, 175, 127, 243, 7,
+ 238, 231, 105, 102, 249, 86, 128, 124, 103, 230, 132, 242, 59, 95, 164,
+ 120, 181, 214, 91, 251, 177, 119, 84, 5, 126, 87, 161, 93, 5, 63,
+ 210, 91, 251, 59, 103, 163, 47, 223, 254, 69, 165, 30, 177, 58, 24,
+ 103, 113, 92, 254, 172, 25, 197, 207, 243, 153, 59, 173, 96, 89, 98,
+ 154, 35, 206, 111, 242, 199, 60, 95, 170, 112, 165, 121, 67, 154, 40,
+ 76, 23, 135, 204, 16, 116, 237, 72, 217, 113, 188, 239, 149, 51, 19,
+ 180, 127, 40, 76, 81, 220, 71, 198, 73, 171, 187, 25, 134, 213, 237,
+ 208, 120, 208, 201, 99, 115, 241, 81, 109, 159, 3, 223, 26, 230, 15,
+ 255, 152, 111, 182, 45, 84, 29, 243, 234, 94, 85, 229, 12, 98, 186,
+ 204, 253, 144, 53, 126, 110, 45, 205, 182, 244, 202, 124, 173, 87, 183,
+ 91, 205, 90, 72, 76, 189, 7, 220, 205, 122, 39, 129, 215, 212, 78,
+ 155, 192, 239, 250, 235, 218, 128, 185, 95, 41, 76, 29, 58, 22, 54,
+ 46, 184, 81, 86, 19, 152, 51, 144, 79, 184, 249, 115, 212, 131, 213,
+ 196, 116, 113, 97, 35, 227, 205, 140, 177, 252, 135, 165, 14, 170, 253,
+ 188, 13, 229, 43, 131, 78, 86, 107, 81, 193, 184, 239, 230, 112, 94,
+ 147, 229, 167, 110, 121, 34, 240, 102, 242, 2, 98, 90, 49, 166, 149,
+ 113, 218, 218, 52, 126, 147, 166, 126, 227, 162, 30, 253, 174, 205, 154,
+ 78, 76, 235, 199, 61, 51, 140, 223, 245, 55, 255, 217, 129, 106, 234,
+ 34, 79, 155, 54, 59, 48, 79, 97, 218, 149, 18, 105, 248, 231, 85,
+ 3, 141, 102, 67, 5, 222, 244, 244, 188, 246, 239, 85, 196, 244, 235,
+ 165, 9, 70, 227, 190, 247, 249, 210, 215, 10, 241, 223, 158, 253, 89,
+ 91, 183, 151, 194, 52, 240, 183, 84, 227, 167, 75, 170, 102, 197, 53,
+ 201, 80, 87, 221, 245, 135, 103, 197, 56, 98, 250, 99, 238, 44, 99,
+ 175, 182, 93, 13, 151, 126, 251, 73, 221, 240, 116, 120, 243, 53, 67,
+ 21, 166, 232, 238, 195, 141, 187, 103, 86, 51, 212, 10, 216, 170, 158,
+ 123, 157, 203, 104, 50, 136, 152, 174, 169, 206, 25, 98, 215, 220, 53,
+ 240, 71, 9, 63, 227, 105, 207, 45, 189, 160, 172, 224, 163, 43, 89,
+ 39, 238, 237, 53, 84, 250, 214, 139, 191, 204, 169, 183, 182, 27, 76,
+ 76, 95, 20, 219, 160, 238, 188, 112, 131, 161, 67, 216, 123, 252, 189,
+ 95, 14, 236, 234, 57, 132, 152, 122, 53, 40, 173, 217, 186, 231, 47,
+ 67, 129, 152, 72, 62, 160, 82, 139, 207, 174, 118, 6, 29, 63, 219,
+ 65, 115, 209, 235, 99, 195, 247, 191, 38, 243, 103, 251, 94, 57, 215,
+ 188, 139, 194, 164, 245, 111, 165, 249, 167, 243, 44, 245, 63, 239, 69,
+ 242, 127, 13, 234, 18, 124, 95, 77, 76, 241, 254, 158, 198, 65, 39,
+ 215, 170, 251, 93, 94, 174, 142, 244, 218, 217, 38, 97, 56, 49, 141,
+ 187, 178, 216, 208, 185, 73, 81, 62, 173, 104, 49, 254, 175, 156, 175,
+ 155, 252, 51, 26, 198, 111, 203, 111, 89, 131, 122, 127, 198, 171, 166,
+ 151, 226, 199, 95, 240, 141, 24, 29, 67, 76, 103, 134, 22, 208, 156,
+ 57, 52, 149, 111, 177, 216, 135, 175, 173, 25, 217, 219, 212, 138, 152,
+ 116, 223, 133, 240, 37, 55, 110, 230, 91, 13, 232, 205, 235, 185, 101,
+ 81, 199, 1, 47, 179, 96, 117, 227, 209, 131, 151, 213, 159, 156, 248,
+ 71, 61, 191, 225, 229, 218, 199, 18, 136, 233, 235, 29, 61, 141, 83,
+ 127, 190, 175, 222, 186, 172, 58, 191, 225, 69, 159, 234, 79, 97, 125,
+ 24, 150, 119, 52, 250, 110, 218, 125, 96, 85, 223, 65, 252, 242, 23,
+ 237, 31, 47, 2, 91, 124, 247, 115, 63, 227, 205, 150, 17, 134, 67,
+ 195, 159, 168, 67, 174, 15, 248, 173, 24, 224, 45, 57, 86, 210, 56,
+ 38, 100, 16, 159, 102, 122, 21, 124, 179, 243, 201, 33, 132, 40, 76,
+ 133, 115, 139, 241, 219, 58, 84, 54, 28, 120, 178, 156, 127, 244, 98,
+ 225, 171, 7, 64, 27, 116, 244, 104, 214, 77, 159, 62, 134, 196, 164,
+ 0, 222, 227, 228, 38, 226, 147, 76, 76, 169, 93, 27, 241, 165, 135,
+ 29, 82, 151, 58, 59, 147, 127, 247, 229, 156, 82, 19, 192, 30, 36,
+ 214, 249, 52, 235, 121, 250, 65, 53, 246, 173, 242, 181, 237, 222, 181,
+ 97, 93, 214, 105, 241, 53, 191, 224, 231, 139, 134, 18, 47, 218, 243,
+ 199, 239, 87, 202, 232, 9, 253, 184, 54, 56, 198, 48, 216, 56, 67,
+ 240, 71, 37, 189, 35, 142, 222, 31, 67, 76, 105, 223, 4, 25, 98,
+ 75, 149, 53, 220, 30, 58, 67, 125, 84, 83, 46, 247, 208, 39, 196,
+ 244, 153, 88, 86, 199, 103, 24, 191, 161, 228, 222, 194, 13, 160, 141,
+ 89, 97, 51, 14, 236, 228, 19, 179, 208, 71, 29, 242, 212, 151, 138,
+ 131, 245, 187, 88, 57, 208, 48, 161, 77, 143, 3, 177, 153, 69, 248,
+ 197, 47, 61, 42, 150, 5, 61, 173, 85, 225, 67, 67, 165, 86, 213,
+ 12, 131, 170, 39, 241, 127, 148, 53, 229, 122, 65, 217, 203, 27, 95,
+ 25, 50, 79, 206, 54, 140, 159, 90, 146, 255, 161, 232, 185, 203, 219,
+ 97, 157, 55, 241, 87, 26, 191, 155, 58, 255, 192, 200, 9, 185, 234,
+ 65, 164, 155, 223, 226, 247, 136, 169, 118, 165, 127, 12, 7, 251, 111,
+ 53, 204, 45, 26, 198, 183, 63, 231, 113, 112, 242, 80, 98, 242, 233,
+ 252, 139, 193, 247, 66, 57, 195, 170, 228, 100, 62, 226, 207, 31, 61,
+ 50, 160, 221, 171, 233, 91, 13, 13, 11, 21, 86, 183, 225, 130, 248,
+ 211, 207, 118, 6, 158, 31, 75, 76, 47, 238, 4, 26, 7, 175, 52,
+ 24, 180, 101, 62, 82, 119, 202, 30, 191, 143, 68, 19, 211, 189, 43,
+ 77, 140, 223, 116, 59, 103, 80, 15, 215, 102, 100, 28, 152, 241, 9,
+ 142, 115, 135, 139, 75, 248, 230, 93, 11, 24, 111, 220, 110, 180, 195,
+ 227, 215, 158, 51, 176, 236, 179, 211, 227, 140, 125, 219, 181, 49, 116,
+ 44, 52, 59, 120, 224, 141, 130, 248, 179, 18, 166, 247, 215, 95, 52,
+ 244, 217, 227, 109, 108, 190, 97, 94, 102, 199, 71, 201, 122, 44, 235,
+ 152, 194, 25, 126, 30, 114, 215, 48, 117, 220, 141, 204, 150, 117, 244,
+ 179, 144, 182, 114, 218, 2, 245, 156, 178, 71, 12, 31, 23, 44, 190,
+ 163, 210, 237, 146, 211, 132, 212, 141, 19, 149, 52, 97, 137, 5, 141,
+ 31, 94, 237, 177, 163, 127, 80, 143, 15, 17, 175, 74, 183, 94, 154,
+ 98, 191, 45, 54, 180, 237, 213, 110, 199, 165, 241, 37, 126, 64, 188,
+ 117, 105, 81, 154, 207, 78, 125, 169, 206, 92, 89, 126, 71, 145, 164,
+ 138, 205, 17, 239, 69, 143, 103, 134, 109, 193, 74, 254, 213, 185, 144,
+ 224, 114, 37, 46, 77, 65, 188, 247, 154, 109, 52, 180, 57, 18, 205,
+ 175, 107, 250, 85, 208, 149, 29, 61, 49, 155, 210, 212, 195, 207, 71,
+ 179, 123, 209, 90, 126, 96, 173, 207, 50, 181, 161, 35, 199, 32, 173,
+ 178, 85, 51, 254, 230, 153, 43, 252, 135, 127, 108, 205, 200, 245, 50,
+ 164, 96, 217, 148, 39, 181, 13, 47, 134, 27, 249, 79, 7, 13, 11,
+ 78, 59, 252, 19, 190, 118, 206, 244, 104, 239, 74, 99, 90, 137, 213,
+ 89, 239, 206, 141, 107, 60, 79, 223, 234, 33, 226, 233, 47, 77, 53,
+ 246, 110, 48, 154, 31, 82, 184, 119, 227, 46, 155, 46, 234, 176, 236,
+ 185, 117, 76, 179, 132, 49, 253, 12, 116, 8, 198, 190, 177, 121, 236,
+ 13, 56, 246, 245, 63, 36, 166, 162, 48, 71, 101, 97, 142, 86, 39,
+ 39, 27, 112, 142, 162, 166, 42, 44, 115, 249, 81, 209, 48, 3, 206,
+ 229, 244, 229, 230, 57, 63, 14, 115, 30, 55, 33, 55, 11, 231, 124,
+ 4, 216, 201, 87, 160, 27, 25, 160, 27, 147, 166, 150, 52, 160, 110,
+ 116, 158, 5, 122, 0, 58, 84, 1, 116, 40, 166, 122, 146, 1, 117,
+ 232, 41, 216, 251, 37, 160, 107, 9, 160, 107, 195, 51, 139, 24, 80,
+ 215, 238, 64, 153, 30, 116, 50, 29, 116, 178, 206, 104, 165, 1, 117,
+ 114, 41, 180, 187, 6, 116, 119, 40, 232, 110, 3, 159, 97, 6, 212,
+ 221, 115, 83, 173, 58, 158, 59, 116, 70, 22, 234, 184, 122, 20, 49,
+ 221, 128, 181, 48, 8, 214, 66, 93, 160, 197, 181, 80, 124, 62, 196,
+ 67, 176, 102, 82, 97, 205, 84, 126, 209, 222, 128, 107, 230, 235, 21,
+ 196, 148, 12, 107, 235, 21, 172, 173, 106, 211, 75, 25, 42, 193, 218,
+ 186, 4, 54, 118, 30, 172, 193, 242, 176, 6, 203, 156, 157, 105, 192,
+ 53, 56, 7, 218, 104, 12, 107, 245, 26, 172, 213, 241, 73, 1, 6,
+ 92, 171, 15, 231, 18, 147, 39, 172, 233, 205, 176, 166, 15, 62, 89,
+ 110, 192, 53, 93, 84, 111, 182, 7, 215, 193, 30, 100, 13, 127, 146,
+ 133, 246, 224, 239, 153, 196, 100, 4, 187, 225, 13, 118, 99, 89, 223,
+ 65, 6, 180, 27, 35, 1, 111, 19, 216, 151, 25, 96, 95, 54, 46,
+ 171, 110, 64, 251, 226, 53, 211, 108, 135, 142, 131, 29, 154, 123, 226,
+ 159, 44, 180, 67, 45, 192, 7, 244, 7, 123, 85, 10, 236, 85, 235,
+ 1, 189, 13, 104, 175, 154, 131, 204, 103, 193, 174, 157, 5, 187, 166,
+ 89, 236, 99, 64, 187, 198, 237, 39, 166, 26, 96, 255, 6, 155, 237,
+ 159, 1, 237, 223, 199, 128, 55, 30, 236, 164, 214, 108, 39, 13, 104,
+ 39, 189, 83, 205, 246, 116, 8, 216, 211, 222, 151, 151, 103, 161, 61,
+ 77, 93, 76, 4, 187, 251, 28, 236, 174, 231, 251, 145, 6, 180, 187,
+ 197, 15, 154, 237, 243, 5, 176, 207, 215, 126, 77, 54, 160, 125, 62,
+ 158, 174, 176, 216, 241, 82, 49, 145, 6, 180, 227, 85, 183, 17, 211,
+ 106, 176, 247, 157, 192, 222, 119, 15, 123, 207, 128, 246, 254, 235, 149,
+ 196, 84, 24, 252, 194, 41, 240, 11, 213, 190, 245, 50, 160, 95, 216,
+ 189, 202, 236, 63, 226, 192, 127, 180, 60, 74, 12, 232, 63, 190, 2,
+ 63, 72, 253, 76, 213, 128, 173, 89, 232, 103, 78, 173, 54, 251, 163,
+ 30, 224, 143, 178, 127, 251, 41, 11, 253, 209, 187, 203, 205, 126, 43,
+ 13, 252, 86, 191, 38, 25, 89, 232, 183, 110, 46, 33, 166, 28, 240,
+ 111, 7, 193, 191, 249, 92, 43, 100, 64, 255, 118, 113, 163, 194, 180,
+ 7, 252, 224, 83, 240, 131, 33, 27, 42, 24, 208, 15, 22, 27, 108,
+ 245, 151, 51, 15, 84, 203, 66, 127, 217, 42, 73, 97, 241, 181, 254,
+ 89, 126, 89, 232, 107, 231, 37, 152, 125, 242, 111, 224, 147, 83, 74,
+ 29, 204, 66, 159, 124, 29, 244, 175, 163, 232, 187, 235, 229, 128, 110,
+ 130, 239, 46, 10, 62, 175, 63, 248, 248, 190, 224, 227, 171, 165, 77,
+ 48, 160, 143, 31, 219, 83, 97, 250, 9, 98, 129, 9, 16, 11, 108,
+ 78, 175, 108, 192, 88, 96, 210, 72, 107, 204, 80, 119, 91, 104, 22,
+ 198, 12, 185, 96, 255, 126, 132, 120, 227, 25, 196, 27, 167, 202, 142,
+ 51, 96, 188, 145, 94, 26, 214, 165, 24, 151, 76, 254, 152, 55, 96,
+ 92, 178, 234, 164, 194, 212, 28, 226, 151, 27, 16, 191, 252, 83, 51,
+ 202, 128, 241, 203, 179, 219, 196, 116, 92, 140, 115, 22, 111, 244, 53,
+ 96, 156, 179, 12, 214, 106, 178, 24, 15, 29, 27, 85, 193, 128, 241,
+ 80, 18, 230, 148, 65, 220, 180, 12, 226, 166, 11, 115, 66, 13, 24,
+ 55, 237, 195, 188, 73, 136, 175, 84, 220, 201, 176, 129, 35, 219, 24,
+ 48, 190, 170, 14, 54, 187, 27, 196, 97, 89, 16, 135, 109, 90, 220,
+ 209, 128, 113, 216, 237, 36, 98, 218, 14, 241, 90, 3, 136, 215, 154,
+ 31, 24, 110, 192, 120, 109, 44, 172, 213, 30, 16, 215, 213, 129, 184,
+ 238, 208, 222, 51, 6, 140, 235, 170, 194, 26, 68, 90, 35, 208, 122,
+ 221, 61, 106, 192, 248, 47, 4, 226, 176, 239, 33, 78, 92, 15, 113,
+ 226, 87, 119, 102, 26, 48, 78, 12, 4, 126, 143, 161, 93, 13, 180,
+ 187, 89, 127, 194, 128, 241, 228, 57, 88, 91, 17, 162, 124, 109, 186,
+ 100, 26, 48, 238, 44, 1, 122, 159, 8, 253, 248, 30, 250, 81, 160,
+ 235, 7, 6, 140, 79, 91, 206, 38, 166, 163, 208, 223, 58, 208, 223,
+ 42, 209, 179, 13, 24, 199, 14, 239, 66, 44, 227, 18, 51, 99, 189,
+ 1, 227, 221, 229, 191, 192, 152, 66, 92, 252, 5, 196, 197, 51, 122,
+ 47, 51, 96, 92, 252, 241, 14, 133, 169, 1, 196, 207, 205, 32, 126,
+ 238, 219, 115, 147, 1, 227, 231, 50, 208, 143, 21, 16, 103, 63, 132,
+ 56, 187, 18, 240, 195, 56, 187, 23, 172, 233, 230, 16, 143, 231, 64,
+ 60, 94, 40, 117, 187, 1, 227, 241, 186, 211, 20, 166, 45, 16, 183,
+ 143, 131, 184, 253, 239, 243, 41, 6, 140, 219, 15, 3, 94, 37, 49,
+ 190, 63, 210, 188, 189, 1, 227, 251, 6, 48, 6, 116, 31, 128, 101,
+ 184, 15, 168, 86, 76, 97, 186, 5, 251, 133, 138, 48, 151, 223, 220,
+ 77, 49, 224, 126, 33, 178, 32, 248, 115, 152, 95, 44, 107, 84, 127,
+ 143, 1, 247, 21, 77, 155, 42, 76, 9, 176, 255, 208, 193, 254, 99,
+ 131, 223, 42, 3, 238, 63, 234, 67, 187, 85, 96, 159, 50, 11, 246,
+ 41, 69, 61, 198, 24, 112, 159, 226, 15, 250, 87, 1, 246, 51, 221,
+ 96, 63, 179, 162, 239, 104, 3, 238, 103, 174, 130, 44, 90, 216, 247,
+ 84, 128, 125, 79, 101, 232, 7, 238, 123, 214, 189, 132, 181, 15, 251,
+ 163, 146, 176, 63, 170, 183, 102, 129, 1, 247, 71, 101, 64, 62, 29,
+ 236, 163, 80, 215, 82, 119, 100, 24, 112, 31, 181, 229, 23, 235, 62,
+ 175, 251, 194, 69, 7, 112, 191, 213, 191, 142, 194, 178, 47, 139, 209,
+ 44, 203, 194, 125, 217, 192, 201, 214, 253, 91, 242, 87, 51, 179, 112,
+ 255, 246, 39, 179, 191, 124, 144, 89, 55, 11, 247, 121, 99, 31, 88,
+ 247, 131, 179, 77, 53, 178, 112, 63, 88, 191, 132, 66, 216, 55, 30,
+ 135, 125, 99, 82, 212, 145, 44, 220, 55, 126, 232, 97, 221, 231, 221,
+ 29, 27, 100, 192, 253, 101, 213, 90, 196, 164, 18, 247, 161, 131, 150,
+ 86, 54, 224, 62, 244, 196, 175, 10, 203, 126, 117, 222, 164, 31, 178,
+ 112, 191, 58, 156, 179, 182, 59, 127, 100, 93, 3, 238, 107, 135, 63,
+ 36, 150, 253, 239, 135, 128, 39, 236, 127, 167, 90, 247, 201, 157, 99,
+ 239, 101, 225, 62, 121, 56, 216, 216, 219, 98, 63, 138, 245, 111, 104,
+ 192, 253, 180, 10, 240, 112, 223, 221, 14, 246, 221, 93, 1, 15, 247,
+ 221, 49, 5, 192, 207, 192, 254, 252, 16, 236, 207, 235, 131, 175, 192,
+ 253, 121, 69, 189, 121, 92, 58, 195, 184, 36, 87, 29, 96, 192, 125,
+ 124, 58, 232, 105, 71, 216, 239, 239, 132, 253, 62, 250, 35, 220, 239,
+ 15, 211, 155, 115, 56, 87, 21, 194, 119, 150, 245, 244, 242, 23, 207,
+ 5, 114, 131, 99, 189, 44, 239, 93, 99, 224, 4, 6, 14, 96, 224,
+ 220, 32, 6, 159, 129, 19, 24, 56, 128, 129, 115, 3, 25, 124, 6,
+ 78, 96, 224, 0, 6, 206, 13, 96, 240, 25, 56, 129, 129, 3, 24,
+ 56, 167, 145, 21, 78, 99, 96, 29, 3, 171, 24, 56, 199, 159, 193,
+ 103, 96, 29, 3, 171, 24, 56, 167, 33, 131, 207, 192, 58, 6, 86,
+ 49, 112, 78, 3, 6, 159, 129, 117, 12, 172, 98, 224, 156, 250, 12,
+ 62, 3, 235, 24, 88, 197, 192, 57, 245, 24, 124, 6, 214, 49, 176,
+ 138, 129, 115, 234, 50, 248, 12, 172, 99, 96, 21, 3, 231, 212, 97,
+ 240, 25, 88, 199, 192, 42, 6, 206, 169, 205, 224, 51, 176, 142, 129,
+ 85, 12, 156, 83, 139, 193, 103, 96, 29, 3, 171, 24, 56, 167, 38,
+ 131, 207, 192, 58, 6, 86, 49, 112, 78, 13, 6, 159, 129, 117, 12,
+ 172, 4, 152, 30, 226, 25, 171, 91, 225, 4, 6, 14, 168, 206, 232,
+ 100, 53, 70, 39, 25, 88, 87, 205, 138, 175, 100, 224, 108, 63, 43,
+ 78, 42, 3, 231, 164, 48, 178, 49, 176, 142, 129, 85, 12, 156, 61,
+ 197, 202, 51, 117, 138, 181, 92, 195, 148, 231, 78, 182, 194, 233, 147,
+ 25, 158, 76, 185, 146, 129, 179, 223, 103, 100, 99, 96, 45, 3, 43,
+ 25, 56, 251, 61, 6, 159, 129, 181, 12, 172, 100, 96, 227, 36, 102,
+ 60, 25, 88, 197, 192, 217, 19, 173, 176, 158, 129, 3, 24, 56, 119,
+ 2, 51, 86, 19, 172, 229, 90, 6, 38, 12, 108, 28, 111, 197, 215,
+ 51, 176, 134, 129, 115, 199, 89, 241, 211, 24, 88, 203, 192, 202, 113,
+ 76, 223, 199, 50, 125, 103, 96, 45, 3, 147, 177, 204, 248, 39, 91,
+ 97, 29, 3, 43, 25, 56, 59, 137, 225, 201, 192, 90, 6, 86, 50,
+ 112, 118, 34, 131, 207, 192, 90, 6, 86, 50, 176, 113, 12, 51, 254,
+ 12, 28, 48, 134, 209, 195, 4, 70, 175, 24, 88, 195, 192, 57, 163,
+ 153, 241, 103, 96, 29, 3, 171, 24, 56, 39, 158, 193, 103, 96, 109,
+ 60, 51, 95, 12, 108, 28, 197, 204, 23, 3, 107, 24, 56, 119, 36,
+ 51, 95, 12, 172, 101, 96, 229, 72, 102, 172, 70, 48, 99, 197, 192,
+ 90, 6, 86, 50, 112, 246, 112, 6, 159, 129, 181, 12, 172, 100, 224,
+ 236, 56, 6, 159, 129, 181, 12, 172, 100, 224, 236, 88, 6, 159, 129,
+ 181, 12, 172, 100, 224, 236, 97, 12, 62, 3, 107, 25, 88, 201, 192,
+ 217, 67, 25, 124, 6, 214, 50, 176, 146, 129, 179, 99, 24, 124, 6,
+ 214, 50, 176, 146, 129, 179, 135, 48, 248, 12, 172, 101, 96, 37, 3,
+ 103, 15, 102, 240, 25, 88, 203, 192, 74, 6, 206, 30, 196, 224, 51,
+ 176, 150, 129, 149, 12, 156, 29, 205, 224, 51, 176, 150, 129, 149, 12,
+ 156, 173, 99, 116, 76, 199, 232, 57, 83, 158, 83, 156, 209, 91, 6,
+ 214, 49, 176, 138, 129, 115, 138, 49, 248, 12, 172, 99, 96, 101, 49,
+ 70, 207, 139, 50, 235, 145, 129, 3, 138, 50, 122, 238, 195, 248, 23,
+ 6, 166, 239, 176, 198, 24, 173, 161, 248, 124, 167, 144, 248, 220, 139,
+ 254, 206, 133, 143, 24, 183, 185, 170, 79, 144, 169, 15, 144, 169, 199,
+ 152, 207, 101, 251, 50, 245, 9, 76, 125, 17, 177, 158, 254, 78, 134,
+ 143, 24, 47, 186, 170, 199, 24, 210, 85, 125, 58, 83, 95, 84, 172,
+ 167, 191, 131, 225, 35, 198, 154, 174, 234, 3, 100, 234, 49, 38, 117,
+ 85, 159, 30, 224, 90, 190, 132, 0, 153, 241, 151, 169, 199, 24, 215,
+ 85, 251, 105, 76, 125, 25, 177, 158, 254, 14, 132, 143, 24, 11, 187,
+ 170, 87, 49, 245, 165, 196, 122, 250, 59, 22, 62, 98, 204, 236, 170,
+ 62, 141, 169, 47, 65, 159, 203, 86, 97, 218, 151, 169, 87, 249, 187,
+ 150, 15, 99, 112, 151, 237, 203, 212, 235, 26, 202, 180, 47, 83, 143,
+ 49, 189, 171, 250, 52, 153, 122, 29, 83, 95, 156, 202, 167, 99, 218,
+ 151, 169, 199, 61, 130, 203, 254, 203, 212, 235, 234, 203, 244, 95, 166,
+ 30, 247, 28, 46, 251, 95, 207, 181, 252, 58, 153, 122, 149, 76, 61,
+ 238, 97, 92, 213, 167, 201, 212, 235, 234, 202, 244, 95, 166, 30, 247,
+ 68, 46, 251, 95, 71, 102, 252, 101, 234, 85, 117, 100, 244, 191, 182,
+ 235, 250, 52, 166, 94, 33, 214, 211, 223, 177, 242, 17, 247, 98, 180,
+ 158, 163, 242, 251, 51, 237, 203, 212, 227, 158, 205, 85, 125, 154, 76,
+ 189, 174, 150, 107, 249, 84, 50, 245, 184, 7, 116, 85, 159, 86, 83,
+ 166, 125, 153, 122, 149, 12, 127, 220, 83, 186, 108, 95, 166, 94, 231,
+ 162, 222, 87, 220, 143, 54, 20, 235, 60, 169, 255, 40, 243, 88, 33,
+ 254, 214, 46, 79, 127, 83, 204, 87, 220, 175, 58, 195, 45, 32, 226,
+ 210, 223, 255, 242, 21, 247, 179, 20, 183, 32, 237, 247, 96, 138, 171,
+ 183, 224, 250, 136, 251, 93, 42, 35, 139, 107, 241, 129, 213, 92, 215,
+ 167, 51, 245, 246, 252, 125, 197, 189, 50, 149, 197, 131, 250, 48, 232,
+ 151, 248, 155, 10, 60, 253, 221, 51, 95, 113, 47, 237, 206, 120, 248,
+ 136, 123, 109, 218, 46, 139, 75, 235, 83, 253, 164, 229, 242, 17, 247,
+ 228, 174, 234, 211, 82, 100, 230, 86, 166, 94, 149, 226, 122, 238, 113,
+ 143, 239, 108, 92, 196, 56, 209, 134, 87, 234, 20, 215, 188, 52, 83,
+ 220, 155, 111, 95, 241, 220, 192, 29, 61, 242, 17, 207, 21, 92, 206,
+ 237, 100, 247, 117, 82, 57, 217, 149, 140, 182, 237, 226, 89, 5, 109,
+ 215, 139, 218, 189, 186, 204, 120, 200, 212, 107, 101, 234, 149, 50, 245,
+ 120, 246, 225, 178, 125, 153, 122, 173, 76, 189, 146, 169, 103, 231, 222,
+ 178, 214, 39, 217, 143, 43, 145, 180, 11, 9, 147, 220, 183, 33, 170,
+ 60, 224, 226, 89, 141, 59, 250, 233, 43, 158, 229, 184, 139, 27, 48,
+ 209, 125, 61, 192, 179, 32, 87, 122, 159, 54, 193, 253, 254, 104, 39,
+ 184, 175, 171, 100, 130, 251, 246, 19, 207, 159, 92, 217, 71, 189, 76,
+ 189, 102, 188, 235, 53, 134, 103, 87, 238, 218, 207, 180, 113, 121, 24,
+ 15, 6, 151, 109, 87, 164, 83, 179, 182, 84, 57, 206, 181, 173, 196,
+ 243, 50, 151, 182, 120, 172, 107, 91, 169, 29, 235, 122, 158, 201, 88,
+ 247, 245, 11, 207, 226, 220, 29, 3, 93, 30, 112, 149, 201, 238, 173,
+ 73, 31, 241, 172, 79, 106, 125, 251, 136, 231, 127, 180, 222, 155, 246,
+ 215, 143, 25, 15, 153, 122, 165, 76, 61, 158, 29, 186, 170, 79, 149,
+ 169, 215, 202, 212, 43, 93, 212, 251, 138, 103, 145, 238, 172, 113, 95,
+ 241, 172, 210, 93, 127, 20, 48, 198, 245, 90, 193, 243, 77, 119, 215,
+ 120, 106, 130, 251, 62, 83, 147, 224, 190, 175, 198, 243, 83, 151, 49,
+ 163, 76, 189, 78, 166, 94, 53, 90, 38, 174, 137, 151, 137, 107, 226,
+ 165, 215, 170, 175, 120, 110, 235, 238, 154, 32, 241, 238, 217, 38, 31,
+ 241, 220, 215, 149, 92, 250, 81, 50, 118, 210, 69, 189, 175, 120, 102,
+ 236, 238, 124, 166, 141, 116, 95, 79, 180, 35, 221, 143, 73, 149, 35,
+ 93, 207, 29, 158, 83, 187, 170, 79, 149, 169, 215, 202, 212, 43, 153,
+ 122, 154, 39, 79, 127, 87, 217, 71, 60, 247, 118, 85, 159, 58, 92,
+ 166, 125, 153, 122, 165, 12, 127, 60, 71, 119, 217, 190, 76, 189, 86,
+ 166, 94, 201, 212, 151, 165, 58, 48, 133, 105, 63, 214, 117, 125, 42,
+ 83, 95, 154, 234, 179, 7, 211, 190, 76, 189, 146, 169, 47, 73, 117,
+ 165, 0, 211, 254, 48, 215, 245, 169, 50, 245, 90, 166, 94, 73, 245,
+ 218, 139, 105, 95, 166, 30, 159, 27, 184, 170, 79, 149, 169, 215, 202,
+ 212, 43, 135, 202, 244, 63, 70, 166, 255, 50, 245, 218, 24, 153, 241,
+ 151, 169, 199, 231, 26, 46, 251, 47, 83, 175, 29, 226, 90, 62, 165,
+ 76, 61, 62, 39, 113, 217, 127, 153, 122, 237, 96, 153, 254, 203, 212,
+ 227, 115, 23, 151, 250, 63, 72, 166, 125, 153, 122, 229, 32, 153, 246,
+ 163, 93, 215, 167, 70, 187, 150, 79, 43, 83, 175, 100, 234, 139, 209,
+ 125, 87, 33, 166, 125, 157, 181, 190, 48, 165, 47, 198, 236, 99, 116,
+ 86, 91, 207, 214, 251, 80, 91, 83, 132, 241, 71, 12, 47, 103, 245,
+ 248, 124, 201, 149, 44, 105, 50, 245, 58, 153, 122, 149, 76, 61, 62,
+ 175, 114, 37, 95, 154, 76, 189, 206, 69, 189, 175, 248, 172, 203, 157,
+ 177, 242, 21, 159, 133, 185, 139, 155, 80, 212, 253, 57, 8, 40, 42,
+ 61, 159, 62, 226, 243, 53, 87, 245, 233, 46, 234, 119, 195, 160, 226,
+ 119, 186, 234, 89, 190, 171, 229, 41, 252, 138, 172, 146, 252, 202, 97,
+ 4, 99, 254, 29, 174, 231, 156, 167, 240, 203, 72, 248, 219, 162, 89,
+ 28, 254, 154, 40, 190, 37, 172, 6, 217, 196, 121, 1, 71, 140, 141,
+ 253, 72, 48, 87, 72, 120, 243, 24, 174, 153, 222, 0, 23, 17, 198,
+ 83, 69, 198, 113, 69, 128, 74, 208, 91, 146, 200, 121, 11, 111, 45,
+ 195, 223, 86, 106, 6, 112, 97, 241, 183, 170, 18, 184, 194, 164, 16,
+ 224, 40, 137, 63, 201, 5, 254, 222, 194, 155, 205, 148, 164, 63, 135,
+ 191, 93, 138, 111, 60, 43, 65, 126, 226, 10, 0, 84, 20, 164, 168,
+ 76, 118, 112, 120, 18, 94, 12, 100, 42, 79, 238, 3, 255, 194, 194,
+ 249, 67, 73, 50, 4, 96, 47, 33, 46, 82, 145, 30, 28, 254, 174,
+ 87, 17, 225, 76, 59, 25, 224, 34, 66, 121, 77, 18, 192, 149, 18,
+ 222, 187, 87, 26, 254, 109, 229, 240, 253, 125, 126, 112, 223, 128, 188,
+ 199, 149, 22, 222, 217, 87, 6, 248, 108, 225, 240, 173, 126, 213, 224,
+ 222, 151, 60, 224, 240, 109, 127, 213, 133, 119, 172, 157, 231, 202, 8,
+ 239, 243, 195, 223, 252, 186, 203, 85, 20, 222, 200, 135, 191, 195, 53,
+ 158, 43, 43, 252, 242, 22, 254, 206, 215, 11, 14, 223, 223, 87, 75,
+ 248, 13, 175, 95, 184, 202, 194, 187, 255, 106, 0, 230, 90, 174, 10,
+ 64, 181, 133, 223, 240, 122, 197, 213, 36, 117, 0, 174, 5, 178, 61,
+ 224, 202, 9, 191, 250, 133, 227, 208, 147, 195, 95, 12, 43, 41, 244,
+ 101, 60, 135, 191, 58, 22, 32, 142, 97, 9, 225, 215, 182, 202, 65,
+ 43, 127, 115, 37, 197, 119, 231, 149, 34, 99, 128, 182, 17, 17, 206,
+ 60, 96, 108, 125, 1, 246, 23, 224, 166, 128, 163, 18, 206, 226, 85,
+ 192, 179, 36, 208, 169, 4, 158, 9, 0, 227, 155, 247, 8, 148, 140,
+ 225, 240, 55, 205, 252, 133, 49, 233, 198, 225, 59, 215, 240, 55, 189,
+ 170, 144, 94, 192, 7, 127, 229, 171, 60, 200, 115, 3, 198, 161, 33,
+ 140, 77, 5, 248, 247, 152, 195, 183, 178, 225, 27, 2, 43, 2, 126,
+ 25, 24, 131, 250, 112, 87, 10, 100, 171, 0, 159, 245, 161, 180, 60,
+ 201, 132, 49, 169, 47, 188, 81, 176, 60, 249, 13, 198, 164, 146, 240,
+ 214, 193, 82, 32, 115, 37, 224, 92, 23, 238, 74, 145, 37, 28, 190,
+ 139, 176, 46, 180, 90, 5, 230, 40, 152, 132, 136, 239, 16, 28, 207,
+ 5, 9, 111, 216, 107, 33, 232, 94, 19, 248, 108, 46, 200, 63, 22,
+ 224, 230, 194, 251, 4, 91, 129, 108, 65, 226, 187, 5, 75, 193, 92,
+ 7, 9, 191, 17, 102, 150, 63, 158, 132, 139, 239, 4, 28, 15, 112,
+ 160, 240, 222, 64, 13, 73, 2, 56, 148, 140, 22, 96, 44, 15, 19,
+ 222, 9, 168, 129, 177, 10, 21, 126, 105, 204, 60, 230, 248, 59, 98,
+ 136, 83, 13, 198, 39, 8, 228, 9, 22, 248, 196, 0, 76, 223, 15,
+ 24, 196, 53, 5, 74, 243, 59, 248, 198, 1, 220, 65, 104, 183, 52,
+ 41, 5, 112, 71, 241, 93, 126, 221, 56, 124, 43, 97, 71, 17, 14,
+ 35, 157, 68, 56, 24, 96, 181, 248, 238, 191, 193, 28, 190, 209, 80,
+ 45, 242, 236, 96, 121, 39, 224, 16, 78, 77, 162, 44, 56, 67, 8,
+ 132, 244, 66, 223, 199, 3, 172, 17, 222, 105, 168, 130, 190, 224, 219,
+ 22, 155, 8, 115, 215, 148, 195, 55, 41, 6, 9, 176, 134, 11, 1,
+ 57, 155, 8, 56, 201, 0, 55, 17, 198, 83, 5, 125, 137, 35, 157,
+ 5, 57, 107, 0, 159, 102, 0, 55, 23, 198, 42, 136, 171, 10, 154,
+ 135, 111, 53, 68, 61, 172, 13, 122, 24, 33, 252, 198, 217, 5, 40,
+ 143, 36, 194, 111, 70, 195, 56, 215, 33, 221, 197, 247, 33, 6, 115,
+ 248, 75, 123, 189, 73, 47, 128, 167, 192, 122, 44, 78, 122, 194, 93,
+ 121, 192, 239, 5, 159, 125, 200, 59, 130, 77, 232, 1, 245, 239, 144,
+ 190, 0, 31, 16, 172, 72, 47, 210, 3, 52, 189, 15, 192, 61, 0,
+ 191, 56, 104, 194, 26, 174, 53, 72, 211, 65, 208, 195, 158, 0, 199,
+ 137, 99, 24, 13, 112, 7, 210, 79, 104, 171, 52, 140, 73, 39, 17,
+ 14, 226, 240, 77, 138, 253, 196, 241, 124, 135, 12, 32, 253, 5, 254,
+ 205, 184, 54, 228, 93, 104, 23, 203, 203, 1, 237, 187, 226, 123, 24,
+ 99, 160, 188, 15, 233, 38, 192, 17, 0, 119, 35, 109, 5, 24, 127,
+ 148, 62, 138, 12, 20, 224, 182, 0, 247, 23, 222, 207, 168, 129, 126,
+ 13, 134, 145, 29, 40, 244, 183, 49, 192, 3, 137, 78, 128, 135, 114,
+ 131, 0, 86, 11, 112, 51, 128, 117, 34, 206, 24, 46, 10, 104, 7,
+ 8, 124, 146, 1, 30, 96, 145, 243, 93, 128, 204, 229, 99, 1, 110,
+ 45, 150, 107, 184, 190, 132, 23, 223, 59, 89, 19, 224, 254, 226, 187,
+ 41, 85, 92, 31, 144, 121, 128, 48, 110, 58, 78, 11, 50, 247, 196,
+ 92, 8, 104, 75, 11, 50, 155, 251, 213, 18, 240, 181, 66, 57, 234,
+ 103, 95, 224, 162, 21, 251, 165, 6, 105, 204, 239, 151, 84, 114, 93,
+ 97, 182, 218, 139, 58, 223, 21, 86, 84, 59, 97, 108, 91, 113, 248,
+ 118, 207, 118, 162, 62, 84, 1, 168, 174, 176, 94, 148, 92, 93, 210,
+ 149, 116, 17, 236, 225, 80, 174, 37, 204, 111, 23, 145, 182, 46, 64,
+ 221, 133, 242, 198, 48, 239, 117, 5, 184, 36, 233, 202, 5, 138, 239,
+ 226, 172, 1, 115, 52, 8, 224, 64, 129, 103, 36, 232, 149, 249, 221,
+ 151, 42, 82, 3, 224, 54, 100, 184, 0, 183, 225, 240, 183, 240, 70,
+ 137, 246, 167, 13, 64, 230, 242, 106, 220, 40, 225, 55, 242, 204, 118,
+ 108, 20, 64, 35, 69, 24, 127, 55, 111, 132, 5, 30, 33, 150, 39,
+ 114, 145, 36, 86, 44, 31, 15, 240, 8, 177, 47, 1, 220, 48, 40,
+ 143, 20, 230, 46, 16, 224, 72, 225, 93, 156, 26, 88, 59, 195, 0,
+ 138, 16, 231, 113, 24, 64, 67, 133, 242, 161, 92, 4, 244, 36, 90,
+ 228, 31, 1, 208, 80, 145, 127, 52, 148, 183, 20, 199, 39, 26, 160,
+ 24, 81, 231, 99, 0, 214, 8, 112, 45, 128, 129, 179, 0, 15, 129,
+ 177, 162, 239, 229, 28, 7, 176, 86, 156, 83, 45, 215, 69, 120, 51,
+ 167, 89, 31, 186, 0, 164, 21, 203, 187, 65, 185, 121, 94, 26, 115,
+ 248, 118, 207, 182, 226, 188, 159, 34, 39, 201, 9, 114, 28, 96, 3,
+ 119, 154, 156, 2, 232, 24, 192, 47, 185, 227, 228, 27, 114, 84, 128,
+ 47, 114, 39, 200, 17, 184, 59, 14, 99, 222, 157, 251, 6, 224, 67,
+ 130, 111, 29, 202, 29, 38, 7, 5, 184, 52, 248, 214, 195, 196, 40,
+ 252, 216, 38, 218, 132, 131, 0, 239, 23, 125, 235, 17, 98, 16, 224,
+ 72, 50, 12, 224, 253, 2, 62, 218, 180, 67, 0, 27, 201, 97, 193,
+ 183, 158, 32, 89, 128, 117, 4, 240, 215, 114, 39, 201, 1, 184, 59,
+ 1, 243, 158, 193, 29, 3, 9, 12, 112, 87, 142, 92, 6, 217, 142,
+ 1, 116, 0, 116, 230, 31, 224, 255, 141, 216, 110, 32, 192, 71, 225,
+ 14, 219, 237, 202, 25, 64, 130, 253, 130, 206, 140, 1, 248, 168, 32,
+ 79, 117, 208, 231, 61, 100, 55, 249, 154, 108, 2, 252, 129, 92, 38,
+ 124, 126, 77, 50, 192, 203, 221, 227, 118, 147, 93, 228, 43, 184, 243,
+ 5, 249, 51, 224, 243, 43, 178, 29, 116, 236, 5, 183, 29, 160, 141,
+ 100, 27, 200, 179, 151, 219, 69, 118, 2, 252, 21, 192, 73, 220, 54,
+ 128, 190, 36, 91, 1, 254, 147, 219, 73, 210, 1, 222, 8, 240, 3,
+ 46, 157, 108, 33, 235, 225, 78, 73, 118, 113, 91, 225, 115, 61, 217,
+ 0, 50, 247, 231, 182, 144, 205, 228, 11, 184, 83, 146, 39, 220, 6,
+ 248, 252, 130, 172, 3, 217, 94, 112, 59, 64, 134, 76, 97, 28, 122,
+ 114, 251, 200, 94, 178, 67, 232, 203, 120, 128, 87, 145, 189, 226, 24,
+ 238, 131, 210, 213, 112, 95, 151, 60, 228, 246, 194, 231, 106, 225, 57,
+ 116, 50, 208, 102, 10, 48, 234, 76, 38, 249, 84, 132, 7, 3, 206,
+ 30, 224, 106, 246, 173, 123, 1, 50, 243, 76, 0, 120, 53, 96, 161,
+ 77, 78, 6, 248, 83, 192, 194, 49, 233, 6, 99, 242, 41, 249, 12,
+ 198, 165, 10, 89, 15, 124, 50, 0, 254, 20, 230, 55, 17, 198, 97,
+ 59, 73, 131, 59, 244, 173, 187, 225, 51, 13, 198, 168, 34, 89, 7,
+ 227, 144, 70, 62, 135, 177, 64, 31, 186, 29, 198, 230, 115, 184, 47,
+ 69, 190, 135, 49, 217, 74, 214, 192, 29, 250, 220, 157, 240, 185, 6,
+ 198, 165, 60, 200, 156, 14, 208, 90, 24, 151, 242, 224, 91, 183, 194,
+ 120, 172, 133, 251, 42, 96, 111, 87, 144, 229, 100, 145, 184, 198, 87,
+ 146, 197, 96, 255, 151, 128, 156, 6, 110, 25, 64, 139, 133, 49, 25,
+ 11, 240, 82, 193, 47, 128, 61, 0, 156, 165, 100, 153, 208, 247, 64,
+ 128, 151, 192, 157, 89, 254, 120, 242, 9, 249, 216, 226, 91, 63, 22,
+ 236, 0, 250, 208, 120, 240, 154, 11, 5, 120, 28, 192, 11, 1, 203,
+ 92, 190, 16, 56, 46, 21, 199, 103, 33, 224, 52, 23, 99, 188, 149,
+ 100, 133, 40, 79, 19, 128, 23, 9, 50, 40, 201, 32, 110, 41, 153,
+ 46, 240, 193, 121, 95, 10, 237, 206, 16, 236, 79, 27, 128, 103, 144,
+ 233, 162, 253, 95, 8, 208, 39, 34, 252, 9, 192, 211, 4, 120, 40,
+ 192, 211, 72, 170, 0, 55, 5, 56, 85, 148, 115, 16, 55, 3, 202,
+ 205, 180, 129, 92, 42, 192, 83, 69, 156, 33, 224, 89, 23, 136, 54,
+ 97, 8, 64, 243, 69, 120, 5, 244, 124, 185, 48, 119, 131, 1, 94,
+ 41, 140, 67, 57, 176, 153, 139, 0, 90, 44, 218, 255, 69, 128, 177,
+ 204, 226, 91, 151, 128, 71, 197, 49, 76, 226, 150, 64, 15, 59, 139,
+ 250, 191, 153, 124, 72, 230, 130, 246, 161, 30, 126, 1, 208, 60, 208,
+ 67, 37, 217, 9, 229, 179, 160, 6, 105, 187, 115, 235, 160, 244, 125,
+ 81, 254, 83, 100, 34, 153, 0, 118, 65, 73, 126, 135, 245, 56, 129,
+ 76, 18, 214, 221, 78, 110, 34, 25, 71, 198, 195, 61, 218, 132, 247,
+ 200, 88, 184, 155, 8, 240, 21, 88, 155, 239, 1, 116, 10, 44, 252,
+ 231, 0, 31, 0, 252, 247, 32, 18, 235, 193, 125, 0, 99, 181, 68,
+ 208, 195, 158, 0, 47, 1, 239, 138, 99, 216, 24, 224, 100, 97, 60,
+ 209, 167, 204, 0, 120, 154, 56, 62, 211, 0, 158, 42, 142, 231, 56,
+ 224, 159, 68, 18, 1, 62, 203, 205, 129, 86, 199, 136, 190, 242, 3,
+ 50, 71, 132, 155, 64, 249, 100, 168, 65, 184, 36, 192, 179, 225, 14,
+ 225, 238, 220, 2, 146, 32, 242, 41, 7, 240, 84, 224, 99, 182, 189,
+ 131, 161, 220, 60, 206, 209, 0, 235, 72, 130, 0, 7, 129, 31, 73,
+ 21, 225, 97, 0, 39, 136, 62, 55, 129, 155, 10, 237, 39, 9, 124,
+ 198, 0, 156, 12, 119, 102, 57, 199, 0, 148, 44, 250, 214, 49, 0,
+ 125, 32, 250, 190, 177, 48, 115, 11, 68, 223, 58, 22, 160, 36, 209,
+ 198, 142, 135, 145, 74, 4, 169, 209, 183, 166, 192, 232, 140, 23, 246,
+ 26, 195, 0, 30, 47, 202, 92, 26, 240, 39, 145, 20, 209, 38, 140,
+ 5, 104, 190, 216, 175, 84, 144, 63, 65, 244, 221, 83, 200, 76, 152,
+ 49, 179, 206, 79, 1, 104, 173, 48, 182, 101, 193, 206, 204, 2, 75,
+ 99, 214, 135, 45, 80, 58, 75, 88, 47, 26, 110, 45, 209, 147, 41,
+ 130, 61, 12, 230, 62, 2, 248, 125, 145, 118, 45, 64, 122, 161, 60,
+ 26, 230, 253, 125, 145, 79, 15, 240, 173, 31, 11, 122, 91, 13, 230,
+ 104, 16, 172, 168, 84, 129, 167, 18, 244, 106, 142, 208, 71, 216, 161,
+ 0, 60, 28, 238, 16, 198, 49, 31, 5, 163, 110, 182, 63, 115, 160,
+ 220, 236, 103, 85, 224, 79, 103, 138, 229, 73, 0, 143, 132, 59, 179,
+ 189, 154, 9, 126, 115, 150, 88, 62, 19, 202, 71, 136, 227, 252, 33,
+ 64, 177, 98, 92, 253, 33, 96, 152, 203, 117, 224, 55, 63, 20, 202,
+ 53, 2, 60, 87, 208, 85, 179, 159, 157, 71, 230, 138, 243, 56, 12,
+ 60, 232, 60, 161, 60, 136, 155, 7, 254, 244, 125, 145, 255, 60, 40,
+ 143, 22, 249, 71, 147, 143, 196, 242, 49, 0, 199, 192, 29, 194, 221,
+ 192, 159, 206, 23, 225, 234, 0, 15, 17, 215, 93, 0, 140, 85, 138,
+ 48, 62, 184, 246, 63, 130, 210, 20, 209, 135, 234, 97, 182, 166, 136,
+ 250, 160, 135, 210, 201, 98, 249, 100, 232, 161, 185, 60, 26, 224, 217,
+ 66, 127, 113, 222, 113, 47, 171, 237, 99, 126, 47, 73, 3, 113, 47,
+ 219, 35, 219, 135, 191, 83, 234, 138, 250, 246, 170, 130, 188, 166, 250,
+ 56, 245, 47, 125, 139, 243, 7, 114, 38, 170, 219, 205, 244, 227, 171,
+ 103, 123, 58, 188, 87, 165, 111, 141, 196, 109, 154, 119, 97, 126, 188,
+ 197, 28, 214, 28, 243, 123, 71, 188, 19, 158, 170, 189, 62, 251, 65,
+ 189, 111, 252, 63, 234, 85, 234, 36, 11, 63, 202, 223, 158, 207, 181,
+ 99, 135, 131, 51, 134, 58, 242, 161, 116, 148, 207, 31, 190, 207, 213,
+ 23, 103, 122, 168, 87, 87, 40, 200, 215, 126, 252, 56, 220, 158, 79,
+ 142, 49, 49, 252, 187, 254, 142, 124, 104, 63, 40, 63, 74, 127, 209,
+ 163, 8, 95, 246, 234, 125, 7, 62, 195, 66, 199, 108, 217, 209, 217,
+ 145, 15, 165, 235, 244, 179, 39, 223, 163, 194, 14, 11, 189, 212, 123,
+ 103, 198, 183, 121, 190, 190, 80, 168, 35, 31, 21, 255, 68, 189, 169,
+ 100, 11, 11, 159, 39, 253, 30, 170, 15, 180, 189, 46, 201, 103, 243,
+ 157, 42, 189, 219, 246, 147, 230, 67, 233, 11, 55, 253, 75, 221, 125,
+ 237, 213, 48, 41, 62, 157, 210, 59, 235, 250, 86, 116, 228, 67, 233,
+ 169, 60, 114, 124, 118, 252, 101, 232, 221, 113, 157, 35, 31, 58, 30,
+ 148, 15, 29, 47, 41, 62, 77, 187, 133, 111, 91, 244, 141, 60, 31,
+ 250, 41, 197, 103, 94, 193, 96, 92, 18, 14, 124, 40, 29, 29, 39,
+ 218, 47, 90, 110, 207, 39, 154, 43, 172, 63, 99, 146, 214, 31, 42,
+ 23, 237, 23, 213, 39, 123, 62, 107, 35, 158, 236, 248, 106, 171, 35,
+ 31, 186, 142, 236, 245, 81, 106, 93, 24, 234, 248, 29, 209, 47, 113,
+ 228, 99, 191, 174, 168, 60, 116, 125, 216, 243, 121, 118, 106, 109, 100,
+ 191, 207, 165, 215, 169, 253, 186, 167, 252, 237, 249, 212, 186, 248, 77,
+ 248, 186, 165, 242, 250, 35, 55, 239, 134, 203, 71, 186, 53, 233, 43,
+ 205, 199, 190, 63, 82, 124, 106, 221, 156, 218, 119, 72, 47, 249, 117,
+ 42, 183, 190, 98, 31, 174, 236, 51, 108, 157, 52, 31, 74, 47, 39,
+ 207, 114, 175, 172, 193, 129, 233, 142, 124, 218, 107, 34, 248, 150, 229,
+ 127, 84, 55, 105, 216, 145, 95, 218, 224, 123, 245, 228, 175, 135, 243,
+ 225, 245, 139, 242, 23, 39, 246, 225, 167, 124, 228, 227, 192, 199, 207,
+ 39, 174, 227, 38, 39, 246, 240, 210, 135, 157, 249, 162, 241, 103, 212,
+ 61, 43, 36, 241, 155, 15, 22, 229, 41, 31, 202, 215, 65, 15, 189,
+ 163, 63, 82, 55, 119, 178, 190, 196, 118, 41, 253, 254, 103, 49, 124,
+ 220, 253, 178, 252, 173, 167, 61, 249, 42, 145, 37, 28, 228, 121, 126,
+ 233, 3, 239, 27, 19, 29, 249, 80, 57, 198, 70, 143, 225, 91, 175,
+ 168, 108, 225, 67, 249, 218, 243, 25, 210, 97, 230, 169, 63, 223, 113,
+ 228, 67, 233, 127, 184, 210, 134, 55, 190, 104, 202, 155, 72, 8, 31,
+ 183, 174, 129, 133, 159, 61, 159, 193, 189, 87, 152, 222, 27, 224, 200,
+ 135, 202, 111, 161, 19, 249, 92, 248, 179, 60, 191, 58, 171, 162, 3,
+ 159, 49, 223, 222, 202, 78, 27, 233, 200, 135, 202, 177, 174, 91, 8,
+ 159, 54, 163, 37, 63, 250, 165, 138, 255, 126, 65, 11, 11, 63, 123,
+ 62, 123, 123, 174, 121, 126, 203, 137, 31, 180, 180, 43, 210, 81, 62,
+ 59, 203, 253, 173, 62, 118, 59, 192, 129, 79, 210, 249, 211, 57, 139,
+ 147, 29, 249, 80, 124, 74, 127, 169, 109, 69, 94, 169, 142, 228, 203,
+ 254, 252, 143, 186, 236, 242, 222, 14, 124, 170, 63, 24, 86, 182, 231,
+ 100, 71, 62, 180, 63, 170, 209, 225, 124, 207, 236, 70, 22, 62, 150,
+ 254, 217, 253, 121, 61, 106, 216, 238, 119, 39, 246, 135, 182, 75, 233,
+ 199, 76, 109, 206, 119, 154, 208, 9, 214, 68, 57, 184, 146, 29, 248,
+ 188, 91, 254, 120, 205, 21, 227, 85, 142, 254, 75, 148, 227, 78, 147,
+ 62, 124, 239, 123, 181, 44, 124, 40, 95, 123, 62, 131, 78, 240, 39,
+ 223, 119, 178, 46, 154, 79, 142, 224, 55, 246, 220, 174, 166, 235, 131,
+ 174, 7, 169, 117, 218, 174, 238, 209, 249, 5, 234, 59, 242, 89, 80,
+ 220, 159, 223, 119, 108, 166, 154, 242, 27, 214, 176, 33, 191, 179, 250,
+ 30, 73, 62, 205, 158, 255, 211, 186, 240, 8, 105, 62, 148, 126, 74,
+ 219, 250, 124, 177, 98, 41, 146, 124, 38, 110, 57, 167, 59, 94, 82,
+ 154, 15, 165, 167, 114, 209, 79, 123, 62, 141, 94, 249, 232, 235, 58,
+ 241, 131, 84, 14, 74, 39, 39, 79, 244, 239, 217, 173, 186, 44, 145,
+ 30, 103, 251, 241, 150, 126, 239, 158, 183, 83, 191, 76, 233, 40, 31,
+ 185, 249, 138, 244, 187, 181, 104, 192, 33, 233, 126, 81, 122, 106, 103,
+ 165, 248, 4, 85, 174, 62, 232, 112, 39, 249, 241, 145, 147, 167, 105,
+ 209, 242, 81, 109, 98, 228, 229, 161, 252, 164, 248, 248, 63, 141, 236,
+ 52, 97, 185, 52, 31, 123, 191, 33, 197, 231, 167, 162, 197, 6, 55,
+ 116, 225, 119, 236, 237, 189, 148, 191, 248, 231, 110, 118, 143, 178, 107,
+ 164, 231, 203, 222, 127, 81, 251, 111, 207, 231, 232, 131, 239, 23, 213,
+ 219, 39, 237, 47, 236, 253, 14, 181, 255, 246, 124, 206, 135, 146, 75,
+ 223, 47, 150, 246, 95, 246, 246, 94, 202, 239, 108, 223, 165, 87, 205,
+ 91, 41, 237, 47, 236, 237, 180, 148, 223, 249, 35, 115, 194, 159, 191,
+ 46, 151, 246, 95, 246, 126, 199, 226, 207, 236, 254, 166, 183, 62, 90,
+ 249, 155, 101, 210, 126, 199, 222, 95, 80, 187, 237, 160, 207, 173, 22,
+ 148, 46, 182, 88, 218, 239, 216, 251, 13, 41, 255, 245, 106, 111, 47,
+ 18, 190, 72, 218, 239, 216, 219, 123, 41, 127, 145, 120, 166, 119, 163,
+ 161, 139, 164, 253, 142, 189, 255, 162, 246, 223, 158, 79, 133, 71, 135,
+ 234, 100, 79, 112, 228, 3, 35, 13, 250, 159, 3, 235, 32, 22, 62,
+ 113, 61, 12, 128, 207, 162, 146, 239, 123, 29, 91, 177, 65, 175, 9,
+ 95, 40, 157, 240, 73, 1, 124, 21, 208, 143, 129, 79, 13, 196, 133,
+ 189, 145, 30, 118, 106, 209, 240, 217, 206, 97, 93, 108, 40, 126, 237,
+ 159, 160, 169, 97, 78, 248, 180, 2, 252, 37, 106, 74, 103, 229, 227,
+ 92, 158, 33, 63, 44, 127, 183, 245, 78, 79, 7, 62, 29, 123, 84,
+ 10, 127, 244, 176, 52, 95, 120, 196, 199, 225, 159, 172, 56, 160, 206,
+ 76, 46, 164, 62, 84, 247, 160, 228, 122, 47, 243, 121, 96, 161, 30,
+ 61, 29, 199, 167, 199, 186, 225, 234, 114, 227, 11, 240, 148, 159, 28,
+ 159, 31, 42, 154, 78, 165, 142, 145, 230, 67, 233, 107, 77, 13, 84,
+ 95, 11, 146, 182, 63, 87, 43, 182, 93, 20, 196, 59, 155, 47, 21,
+ 62, 14, 9, 251, 182, 88, 184, 250, 206, 229, 146, 225, 159, 254, 241,
+ 121, 120, 210, 59, 211, 37, 227, 240, 135, 155, 126, 184, 118, 173, 191,
+ 52, 31, 216, 209, 169, 89, 126, 82, 124, 148, 235, 79, 108, 45, 82,
+ 223, 91, 146, 207, 71, 239, 235, 195, 72, 95, 250, 219, 147, 177, 146,
+ 253, 42, 189, 84, 23, 217, 177, 66, 9, 73, 62, 180, 63, 86, 126,
+ 206, 249, 76, 79, 171, 81, 119, 89, 7, 199, 126, 81, 58, 58, 206,
+ 116, 254, 165, 248, 124, 233, 83, 37, 238, 215, 182, 210, 124, 172, 244,
+ 174, 251, 165, 188, 244, 219, 68, 252, 21, 51, 233, 117, 65, 215, 23,
+ 93, 111, 206, 249, 124, 91, 228, 85, 133, 137, 211, 43, 185, 224, 67,
+ 215, 5, 229, 231, 156, 79, 195, 154, 35, 124, 26, 205, 114, 228, 67,
+ 199, 133, 246, 175, 97, 31, 15, 245, 233, 47, 102, 74, 251, 193, 18,
+ 239, 212, 27, 53, 158, 72, 242, 169, 188, 178, 159, 186, 243, 177, 109,
+ 178, 250, 156, 214, 122, 122, 67, 117, 180, 52, 31, 42, 7, 229, 39,
+ 197, 167, 125, 249, 23, 126, 198, 9, 210, 243, 69, 245, 71, 174, 95,
+ 253, 111, 92, 125, 118, 241, 125, 71, 62, 148, 126, 151, 190, 135, 122,
+ 111, 110, 140, 236, 248, 132, 127, 215, 185, 70, 210, 24, 105, 62, 67,
+ 186, 232, 212, 77, 179, 238, 88, 248, 73, 241, 41, 126, 229, 253, 125,
+ 159, 196, 72, 243, 161, 235, 147, 242, 147, 148, 167, 232, 173, 50, 209,
+ 78, 246, 41, 116, 92, 105, 127, 228, 228, 185, 227, 251, 176, 89, 191,
+ 4, 71, 62, 180, 253, 122, 95, 111, 83, 207, 106, 63, 74, 150, 79,
+ 205, 63, 190, 76, 111, 50, 200, 145, 143, 241, 159, 250, 252, 174, 226,
+ 59, 212, 3, 162, 138, 241, 37, 247, 13, 81, 95, 56, 95, 134, 159,
+ 113, 63, 82, 218, 174, 86, 48, 126, 98, 10, 147, 230, 19, 21, 89,
+ 157, 31, 223, 234, 140, 133, 159, 20, 159, 11, 85, 230, 45, 15, 110,
+ 227, 200, 103, 211, 80, 141, 122, 254, 174, 40, 254, 231, 207, 138, 169,
+ 23, 118, 234, 101, 177, 247, 82, 124, 244, 229, 91, 108, 14, 122, 87,
+ 154, 15, 165, 167, 118, 95, 138, 79, 71, 223, 97, 39, 215, 140, 113,
+ 102, 159, 233, 250, 166, 235, 157, 250, 69, 231, 124, 22, 93, 234, 20,
+ 221, 105, 167, 210, 5, 31, 74, 239, 218, 191, 119, 184, 60, 126, 84,
+ 202, 9, 95, 7, 62, 19, 115, 167, 171, 79, 148, 188, 162, 14, 191,
+ 223, 82, 221, 165, 231, 69, 217, 245, 94, 190, 251, 146, 222, 113, 245,
+ 28, 251, 69, 233, 40, 31, 57, 251, 188, 185, 89, 193, 196, 143, 148,
+ 206, 198, 199, 188, 47, 166, 251, 219, 153, 199, 199, 241, 5, 55, 244,
+ 230, 23, 116, 236, 196, 191, 8, 25, 239, 192, 231, 80, 171, 10, 21,
+ 171, 196, 57, 198, 9, 148, 158, 238, 151, 55, 44, 25, 203, 215, 185,
+ 85, 223, 194, 207, 158, 79, 118, 129, 17, 39, 149, 201, 210, 242, 208,
+ 246, 9, 241, 131, 75, 39, 57, 206, 234, 142, 119, 98, 202, 148, 116,
+ 148, 135, 202, 241, 227, 216, 222, 124, 183, 168, 210, 22, 121, 36, 245,
+ 240, 89, 209, 243, 35, 156, 216, 67, 122, 254, 72, 207, 71, 135, 204,
+ 47, 196, 7, 53, 84, 242, 147, 7, 120, 240, 233, 67, 111, 59, 196,
+ 99, 167, 130, 126, 44, 208, 101, 172, 244, 249, 42, 229, 71, 233, 41,
+ 63, 135, 115, 63, 255, 95, 61, 127, 156, 227, 200, 199, 158, 110, 242,
+ 180, 95, 213, 59, 127, 121, 166, 126, 248, 213, 35, 117, 178, 49, 219,
+ 65, 158, 23, 133, 195, 218, 247, 143, 117, 228, 179, 242, 69, 97, 126,
+ 203, 221, 99, 22, 57, 40, 125, 197, 80, 194, 47, 85, 108, 118, 224,
+ 115, 172, 232, 176, 175, 11, 12, 148, 63, 167, 165, 252, 40, 127, 123,
+ 62, 158, 145, 233, 109, 51, 182, 72, 243, 177, 151, 75, 234, 252, 121,
+ 107, 196, 193, 150, 77, 122, 59, 242, 41, 189, 110, 158, 186, 142, 223,
+ 113, 203, 186, 146, 243, 131, 15, 130, 87, 52, 29, 49, 76, 154, 15,
+ 93, 175, 114, 235, 180, 87, 212, 66, 62, 179, 139, 52, 31, 42, 199,
+ 149, 247, 151, 169, 183, 109, 218, 40, 201, 231, 89, 224, 79, 229, 255,
+ 76, 148, 246, 59, 212, 79, 200, 241, 89, 20, 20, 82, 97, 177, 19,
+ 62, 148, 158, 250, 29, 57, 62, 79, 131, 119, 222, 75, 73, 114, 228,
+ 67, 245, 165, 231, 195, 108, 117, 243, 71, 155, 212, 31, 55, 123, 160,
+ 94, 90, 101, 172, 164, 254, 92, 170, 88, 213, 216, 195, 201, 121, 84,
+ 161, 225, 155, 213, 29, 234, 122, 242, 252, 150, 189, 234, 106, 253, 127,
+ 87, 83, 125, 150, 146, 231, 96, 189, 97, 165, 10, 143, 151, 30, 103,
+ 202, 135, 242, 149, 226, 19, 242, 131, 127, 139, 1, 113, 210, 242, 80,
+ 57, 166, 86, 188, 161, 254, 102, 173, 175, 36, 159, 98, 47, 202, 191,
+ 184, 148, 34, 205, 135, 210, 167, 84, 248, 90, 189, 108, 118, 61, 73,
+ 62, 251, 94, 76, 48, 221, 117, 194, 135, 250, 97, 58, 95, 179, 207,
+ 156, 85, 15, 169, 95, 64, 58, 254, 201, 57, 114, 107, 247, 68, 105,
+ 62, 116, 158, 40, 63, 41, 62, 115, 210, 190, 206, 60, 95, 219, 201,
+ 254, 93, 140, 47, 40, 63, 57, 121, 58, 254, 240, 124, 217, 59, 225,
+ 210, 124, 40, 253, 131, 15, 207, 169, 55, 123, 254, 44, 25, 143, 109,
+ 184, 112, 113, 101, 201, 72, 71, 62, 163, 38, 246, 83, 251, 165, 175,
+ 13, 167, 124, 228, 226, 58, 239, 61, 151, 183, 245, 104, 39, 205, 135,
+ 202, 33, 215, 175, 197, 187, 110, 110, 50, 105, 28, 249, 208, 113, 165,
+ 227, 76, 215, 135, 20, 159, 202, 7, 185, 251, 163, 227, 165, 249, 80,
+ 122, 185, 117, 186, 124, 95, 229, 202, 117, 157, 216, 121, 186, 30, 40,
+ 189, 156, 60, 65, 23, 123, 134, 244, 26, 46, 205, 135, 174, 51, 57,
+ 121, 12, 23, 70, 104, 150, 56, 57, 15, 167, 246, 129, 234, 15, 141,
+ 55, 165, 248, 156, 34, 19, 31, 38, 166, 72, 243, 161, 227, 44, 23,
+ 175, 22, 244, 39, 215, 207, 57, 177, 99, 116, 157, 211, 254, 209, 241,
+ 145, 242, 167, 215, 125, 111, 55, 42, 224, 36, 110, 73, 158, 83, 146,
+ 247, 60, 250, 167, 197, 126, 81, 255, 37, 37, 207, 250, 197, 217, 71,
+ 251, 213, 147, 230, 67, 237, 134, 156, 61, 28, 246, 151, 209, 71, 61,
+ 69, 122, 124, 44, 114, 201, 200, 51, 56, 199, 103, 224, 218, 46, 210,
+ 124, 232, 60, 81, 126, 82, 124, 174, 63, 217, 152, 115, 246, 61, 233,
+ 253, 14, 93, 87, 114, 246, 103, 209, 189, 207, 175, 15, 119, 194, 103,
+ 121, 102, 17, 254, 244, 132, 38, 150, 184, 240, 137, 255, 53, 245, 198,
+ 181, 93, 36, 237, 170, 70, 245, 91, 185, 105, 19, 165, 249, 208, 243,
+ 190, 30, 63, 87, 230, 91, 248, 197, 75, 242, 233, 19, 244, 193, 31,
+ 151, 147, 164, 159, 55, 209, 184, 85, 46, 94, 213, 212, 249, 99, 194,
+ 130, 34, 222, 46, 248, 152, 233, 169, 92, 82, 124, 146, 15, 196, 250,
+ 23, 94, 237, 228, 60, 92, 164, 163, 253, 251, 113, 74, 13, 190, 212,
+ 39, 210, 254, 107, 76, 147, 57, 69, 50, 156, 244, 107, 82, 183, 32,
+ 254, 135, 49, 196, 18, 63, 203, 241, 249, 218, 235, 250, 133, 220, 9,
+ 210, 242, 80, 122, 202, 79, 138, 207, 35, 245, 55, 10, 221, 104, 34,
+ 25, 207, 91, 248, 201, 240, 201, 254, 113, 235, 203, 211, 19, 157, 237,
+ 47, 204, 231, 116, 84, 31, 229, 206, 235, 188, 106, 221, 158, 181, 249,
+ 47, 79, 73, 127, 97, 245, 55, 102, 190, 146, 231, 108, 133, 239, 207,
+ 46, 88, 95, 41, 185, 31, 164, 118, 85, 46, 110, 25, 244, 195, 186,
+ 33, 225, 45, 137, 36, 31, 43, 253, 60, 144, 199, 91, 146, 207, 111,
+ 223, 110, 26, 88, 188, 141, 82, 50, 110, 177, 198, 43, 51, 128, 79,
+ 35, 73, 62, 247, 182, 213, 237, 210, 151, 151, 142, 127, 172, 244, 174,
+ 229, 185, 184, 99, 98, 151, 153, 173, 156, 237, 187, 205, 244, 84, 30,
+ 185, 245, 222, 243, 86, 244, 232, 33, 33, 68, 146, 143, 149, 254, 16,
+ 220, 15, 146, 228, 243, 211, 189, 238, 201, 53, 131, 156, 228, 129, 88,
+ 232, 233, 58, 47, 3, 215, 68, 73, 62, 235, 107, 235, 135, 159, 15,
+ 113, 197, 135, 210, 187, 150, 231, 23, 191, 207, 199, 84, 11, 112, 242,
+ 28, 214, 178, 79, 238, 202, 19, 253, 44, 89, 121, 170, 247, 188, 218,
+ 175, 126, 5, 87, 124, 40, 189, 107, 59, 182, 58, 156, 211, 189, 104,
+ 225, 100, 156, 245, 83, 1, 127, 152, 69, 30, 43, 95, 231, 124, 38,
+ 189, 31, 89, 100, 92, 69, 105, 62, 148, 158, 158, 35, 72, 241, 81,
+ 77, 62, 93, 244, 101, 89, 105, 62, 148, 94, 238, 28, 96, 140, 86,
+ 251, 169, 103, 41, 105, 62, 148, 190, 152, 49, 133, 255, 176, 167, 116,
+ 60, 223, 161, 247, 210, 175, 7, 213, 113, 228, 67, 233, 169, 253, 138,
+ 237, 253, 46, 191, 194, 197, 185, 86, 213, 187, 59, 83, 31, 133, 74,
+ 243, 161, 244, 114, 242, 68, 189, 106, 53, 179, 78, 13, 71, 62, 148,
+ 158, 202, 67, 237, 190, 228, 121, 230, 181, 202, 11, 87, 134, 73, 243,
+ 161, 244, 207, 63, 104, 198, 103, 166, 253, 45, 233, 223, 151, 101, 37,
+ 44, 14, 115, 50, 239, 148, 142, 242, 145, 139, 15, 219, 121, 15, 158,
+ 254, 155, 11, 62, 148, 158, 158, 111, 74, 230, 21, 212, 169, 183, 114,
+ 67, 43, 23, 126, 80, 244, 95, 114, 241, 207, 142, 163, 202, 191, 234,
+ 141, 145, 230, 67, 233, 229, 250, 197, 31, 62, 248, 251, 139, 81, 142,
+ 124, 168, 28, 212, 191, 203, 237, 79, 163, 79, 126, 235, 59, 125, 140,
+ 52, 31, 74, 47, 215, 175, 109, 198, 46, 197, 218, 59, 217, 167, 80,
+ 122, 42, 143, 156, 125, 158, 114, 178, 74, 133, 214, 99, 164, 249, 80,
+ 122, 185, 253, 242, 224, 27, 147, 159, 255, 250, 190, 252, 121, 157, 125,
+ 62, 163, 179, 60, 97, 227, 27, 200, 63, 196, 60, 225, 168, 229, 210,
+ 121, 194, 246, 121, 131, 82, 124, 48, 79, 184, 209, 218, 252, 231, 121,
+ 98, 158, 112, 199, 109, 210, 121, 131, 246, 121, 172, 174, 242, 132, 159,
+ 28, 145, 207, 239, 149, 227, 131, 121, 194, 123, 214, 73, 243, 161, 249,
+ 175, 114, 249, 144, 152, 39, 188, 254, 134, 116, 126, 166, 125, 30, 173,
+ 171, 60, 225, 29, 253, 164, 243, 123, 237, 243, 52, 93, 229, 9, 143,
+ 12, 249, 159, 207, 19, 182, 207, 127, 166, 227, 230, 44, 79, 56, 152,
+ 228, 63, 207, 28, 243, 132, 123, 105, 229, 207, 177, 237, 243, 241, 157,
+ 230, 9, 199, 73, 231, 9, 219, 231, 205, 75, 233, 51, 230, 9, 127,
+ 241, 6, 242, 249, 49, 79, 216, 217, 121, 184, 125, 126, 175, 220, 124,
+ 97, 158, 240, 169, 47, 164, 249, 216, 247, 203, 85, 158, 240, 170, 141,
+ 242, 249, 189, 114, 242, 96, 158, 240, 242, 126, 210, 124, 168, 60, 114,
+ 235, 11, 243, 132, 191, 237, 146, 255, 124, 45, 204, 19, 238, 177, 60,
+ 255, 249, 90, 152, 39, 124, 232, 88, 254, 243, 172, 48, 79, 184, 210,
+ 172, 252, 231, 125, 97, 158, 112, 201, 245, 249, 207, 179, 194, 60, 225,
+ 153, 107, 242, 159, 247, 133, 121, 194, 186, 133, 249, 207, 215, 194, 60,
+ 97, 223, 207, 243, 159, 175, 133, 121, 194, 35, 230, 230, 63, 95, 11,
+ 243, 132, 191, 158, 150, 255, 124, 45, 204, 19, 46, 31, 39, 127, 110,
+ 35, 151, 223, 139, 121, 194, 67, 231, 120, 75, 230, 9, 219, 231, 27,
+ 211, 243, 10, 103, 121, 194, 51, 150, 75, 231, 175, 210, 117, 33, 151,
+ 191, 138, 121, 194, 207, 207, 201, 231, 247, 202, 229, 121, 98, 158, 240,
+ 227, 69, 242, 249, 189, 114, 249, 198, 152, 39, 220, 252, 158, 124, 222,
+ 178, 125, 158, 175, 179, 60, 225, 139, 38, 233, 188, 83, 251, 124, 99,
+ 87, 121, 194, 219, 226, 228, 243, 177, 229, 248, 200, 229, 9, 187, 155,
+ 79, 219, 218, 239, 214, 162, 181, 225, 249, 207, 167, 197, 60, 225, 240,
+ 140, 252, 231, 247, 98, 158, 240, 222, 21, 249, 207, 55, 198, 60, 225,
+ 57, 67, 243, 159, 255, 140, 121, 194, 63, 116, 201, 255, 247, 83, 48,
+ 79, 248, 206, 128, 252, 127, 63, 5, 243, 132, 47, 68, 230, 255, 123,
+ 37, 152, 39, 236, 63, 60, 255, 223, 115, 193, 60, 225, 228, 33, 249,
+ 255, 94, 9, 230, 9, 251, 13, 205, 255, 247, 92, 48, 79, 56, 116,
+ 88, 254, 191, 159, 130, 121, 194, 127, 15, 207, 255, 247, 83, 48, 79,
+ 248, 240, 136, 252, 127, 63, 5, 243, 132, 87, 140, 200, 255, 247, 83,
+ 48, 79, 56, 96, 182, 171, 60, 97, 154, 63, 228, 58, 255, 16, 243,
+ 132, 231, 244, 245, 118, 35, 143, 145, 230, 247, 154, 243, 134, 157, 229,
+ 9, 159, 157, 226, 42, 79, 216, 54, 207, 216, 85, 158, 240, 190, 246,
+ 210, 121, 194, 238, 230, 139, 98, 158, 240, 166, 175, 228, 243, 123, 229,
+ 242, 199, 48, 79, 56, 97, 190, 52, 31, 154, 183, 33, 151, 111, 140,
+ 121, 194, 103, 141, 68, 54, 159, 86, 238, 121, 1, 230, 9, 87, 89,
+ 43, 159, 111, 44, 247, 188, 0, 243, 132, 31, 157, 83, 186, 200, 55,
+ 54, 231, 209, 202, 229, 247, 98, 158, 240, 142, 155, 133, 100, 243, 141,
+ 229, 242, 159, 49, 79, 56, 118, 135, 124, 126, 175, 220, 56, 99, 158,
+ 176, 223, 110, 105, 62, 180, 95, 114, 250, 131, 121, 194, 251, 77, 69,
+ 92, 172, 11, 251, 124, 124, 233, 60, 225, 217, 239, 87, 114, 35, 223,
+ 216, 245, 186, 192, 60, 225, 239, 38, 86, 146, 205, 203, 149, 155, 47,
+ 204, 19, 94, 56, 71, 58, 191, 215, 221, 188, 38, 204, 19, 62, 244,
+ 169, 124, 190, 177, 92, 94, 46, 230, 9, 107, 102, 75, 207, 23, 165,
+ 151, 211, 31, 204, 19, 174, 59, 93, 58, 47, 215, 221, 124, 90, 204,
+ 19, 254, 104, 190, 124, 190, 177, 92, 30, 8, 230, 9, 199, 175, 144,
+ 207, 55, 150, 91, 239, 152, 39, 252, 217, 52, 249, 124, 45, 185, 113,
+ 198, 60, 225, 47, 22, 72, 63, 55, 183, 207, 219, 114, 149, 39, 124,
+ 106, 181, 116, 126, 175, 125, 254, 142, 171, 60, 97, 238, 176, 124, 190,
+ 177, 220, 57, 54, 230, 9, 159, 217, 35, 159, 223, 75, 243, 133, 93,
+ 229, 9, 159, 253, 92, 154, 143, 253, 247, 75, 92, 229, 9, 191, 59,
+ 159, 184, 145, 223, 235, 122, 189, 99, 158, 112, 102, 123, 111, 23, 124,
+ 168, 127, 119, 157, 111, 140, 121, 194, 83, 155, 74, 231, 9, 219, 231,
+ 249, 186, 202, 19, 94, 122, 94, 58, 79, 152, 218, 83, 57, 62, 152,
+ 39, 156, 244, 151, 124, 94, 46, 125, 158, 70, 247, 187, 206, 242, 132,
+ 175, 45, 145, 206, 19, 182, 127, 30, 39, 181, 95, 198, 60, 225, 220,
+ 185, 210, 242, 208, 231, 148, 114, 207, 25, 49, 79, 248, 143, 123, 210,
+ 121, 194, 246, 207, 229, 92, 229, 9, 47, 158, 45, 253, 220, 193, 62,
+ 63, 87, 234, 253, 36, 167, 130, 46, 21, 216, 246, 161, 244, 249, 170,
+ 125, 158, 177, 212, 121, 38, 230, 9, 215, 25, 47, 157, 39, 76, 243,
+ 152, 104, 30, 145, 84, 190, 49, 230, 9, 59, 123, 127, 2, 205, 199,
+ 165, 121, 64, 22, 126, 18, 249, 207, 152, 39, 252, 60, 45, 255, 249,
+ 189, 152, 39, 28, 213, 53, 255, 249, 198, 152, 39, 124, 234, 75, 249,
+ 188, 92, 185, 252, 94, 204, 19, 94, 188, 76, 62, 223, 152, 174, 91,
+ 87, 121, 194, 157, 210, 165, 249, 208, 188, 58, 57, 255, 142, 121, 194,
+ 37, 63, 146, 246, 59, 148, 143, 156, 63, 93, 24, 20, 82, 97, 196,
+ 71, 210, 121, 194, 148, 143, 156, 223, 193, 60, 97, 253, 60, 233, 60,
+ 97, 251, 124, 61, 154, 103, 231, 44, 79, 120, 211, 34, 249, 188, 92,
+ 154, 175, 231, 42, 79, 248, 241, 28, 233, 113, 182, 207, 59, 118, 149,
+ 39, 188, 118, 137, 124, 126, 175, 92, 158, 30, 230, 9, 215, 214, 19,
+ 217, 124, 27, 185, 231, 185, 152, 39, 92, 90, 47, 157, 223, 235, 110,
+ 126, 29, 230, 9, 183, 155, 37, 159, 111, 76, 231, 203, 85, 158, 112,
+ 253, 31, 229, 243, 123, 229, 226, 13, 204, 19, 222, 112, 72, 154, 143,
+ 187, 121, 185, 152, 39, 252, 231, 62, 34, 155, 175, 37, 199, 7, 243,
+ 132, 55, 237, 146, 207, 55, 150, 203, 91, 198, 60, 97, 206, 32, 159,
+ 223, 43, 55, 206, 152, 39, 252, 241, 199, 210, 124, 220, 205, 239, 197,
+ 60, 225, 139, 75, 165, 243, 123, 221, 205, 55, 198, 60, 225, 175, 22,
+ 203, 231, 27, 211, 245, 230, 42, 79, 120, 248, 114, 249, 188, 83, 57,
+ 253, 193, 60, 225, 249, 122, 249, 124, 99, 185, 113, 198, 60, 225, 6,
+ 243, 164, 243, 132, 237, 191, 247, 64, 251, 235, 44, 79, 248, 249, 92,
+ 23, 121, 194, 162, 223, 146, 179, 27, 152, 39, 252, 197, 121, 249, 124,
+ 99, 57, 187, 129, 121, 194, 135, 166, 74, 143, 15, 149, 71, 46, 15,
+ 4, 243, 132, 7, 164, 203, 231, 27, 203, 237, 11, 48, 79, 56, 104,
+ 134, 252, 247, 34, 229, 214, 41, 230, 9, 47, 153, 33, 157, 223, 235,
+ 152, 175, 39, 157, 39, 60, 101, 150, 52, 31, 154, 31, 44, 151, 151,
+ 139, 121, 194, 181, 230, 17, 217, 252, 94, 107, 252, 42, 157, 39, 60,
+ 230, 161, 82, 246, 253, 54, 114, 253, 194, 60, 225, 199, 131, 228, 243,
+ 114, 173, 121, 213, 210, 121, 194, 81, 243, 228, 243, 163, 228, 226, 103,
+ 204, 19, 86, 206, 118, 33, 143, 155, 249, 198, 152, 39, 156, 150, 74,
+ 100, 191, 247, 39, 55, 95, 152, 39, 220, 120, 150, 116, 158, 176, 187,
+ 223, 23, 198, 60, 225, 238, 74, 233, 60, 97, 251, 188, 99, 87, 121,
+ 194, 207, 206, 121, 203, 230, 247, 202, 217, 85, 204, 19, 62, 156, 37,
+ 157, 39, 76, 243, 113, 229, 242, 141, 49, 79, 248, 254, 30, 111, 217,
+ 252, 94, 185, 124, 45, 204, 19, 94, 111, 116, 149, 39, 76, 243, 131,
+ 93, 231, 27, 99, 158, 240, 123, 251, 189, 101, 243, 123, 229, 228, 193,
+ 60, 225, 85, 223, 72, 231, 9, 211, 124, 92, 185, 124, 54, 204, 19,
+ 190, 114, 198, 157, 252, 94, 215, 235, 20, 243, 132, 235, 127, 227, 138,
+ 15, 205, 15, 118, 157, 223, 139, 121, 194, 191, 124, 235, 78, 126, 47,
+ 205, 23, 150, 206, 19, 62, 127, 211, 21, 31, 247, 242, 159, 49, 79,
+ 216, 243, 168, 124, 126, 175, 156, 60, 152, 39, 252, 225, 13, 249, 252,
+ 94, 185, 115, 0, 204, 19, 246, 184, 45, 159, 223, 43, 151, 111, 140,
+ 121, 194, 47, 238, 74, 243, 161, 249, 184, 114, 249, 198, 152, 39, 252,
+ 233, 69, 249, 252, 94, 57, 187, 138, 121, 194, 69, 142, 72, 243, 161,
+ 242, 200, 229, 27, 99, 158, 240, 143, 87, 228, 243, 123, 229, 228, 193,
+ 60, 225, 152, 195, 210, 124, 236, 243, 124, 93, 229, 9, 31, 185, 33,
+ 159, 223, 43, 199, 7, 243, 132, 43, 184, 224, 99, 255, 254, 3, 87,
+ 121, 194, 239, 236, 151, 207, 239, 149, 243, 95, 152, 39, 124, 97, 190,
+ 52, 31, 119, 191, 111, 133, 121, 194, 158, 159, 200, 231, 247, 202, 249,
+ 119, 204, 19, 158, 60, 95, 154, 143, 253, 247, 210, 92, 229, 9, 239,
+ 250, 88, 62, 191, 87, 78, 30, 204, 19, 222, 55, 95, 154, 143, 187,
+ 223, 7, 193, 60, 97, 63, 39, 207, 29, 162, 90, 19, 225, 157, 247,
+ 198, 34, 177, 94, 65, 204, 239, 179, 37, 52, 166, 126, 0, 113, 146,
+ 70, 196, 197, 251, 7, 4, 4, 18, 155, 63, 78, 68, 79, 253, 251,
+ 177, 130, 72, 252, 233, 129, 111, 174, 151, 153, 87, 78, 193, 88, 47,
+ 125, 225, 88, 175, 236, 66, 86, 222, 246, 127, 133, 197, 223, 35, 68,
+ 198, 186, 159, 35, 249, 182, 169, 179, 96, 215, 168, 111, 92, 173, 214,
+ 49, 77, 235, 122, 119, 249, 243, 243, 167, 104, 88, 252, 42, 196, 147,
+ 40, 152, 95, 149, 195, 119, 38, 123, 138, 237, 138, 50, 146, 28, 143,
+ 88, 47, 44, 63, 142, 229, 208, 126, 35, 177, 157, 246, 245, 251, 26,
+ 215, 60, 173, 204, 39, 152, 106, 240, 243, 110, 156, 125, 165, 152, 172,
+ 48, 117, 128, 178, 117, 80, 54, 220, 84, 195, 128, 101, 175, 166, 41,
+ 76, 103, 43, 198, 26, 159, 7, 119, 228, 245, 141, 202, 91, 240, 176,
+ 236, 5, 148, 77, 106, 84, 222, 130, 215, 237, 204, 24, 227, 233, 123,
+ 215, 212, 254, 223, 22, 183, 148, 105, 161, 236, 36, 148, 53, 254, 182,
+ 184, 133, 246, 196, 193, 95, 255, 31, 123, 95, 1, 87, 213, 182, 173,
+ 191, 232, 110, 65, 58, 164, 148, 6, 233, 70, 148, 84, 80, 164, 67,
+ 233, 238, 6, 165, 149, 80, 26, 165, 20, 65, 5, 233, 110, 16, 73,
+ 105, 164, 59, 5, 105, 9, 165, 164, 255, 123, 123, 166, 247, 112, 125,
+ 231, 220, 115, 239, 123, 239, 190, 247, 126, 255, 115, 182, 191, 15, 215,
+ 94, 107, 206, 49, 190, 49, 230, 152, 177, 214, 158, 115, 46, 201, 171,
+ 122, 66, 117, 125, 223, 109, 57, 245, 129, 32, 196, 83, 215, 71, 121,
+ 117, 50, 176, 115, 67, 103, 206, 57, 195, 206, 73, 195, 206, 13, 132,
+ 123, 215, 253, 56, 247, 1, 150, 247, 10, 236, 92, 239, 153, 115, 112,
+ 219, 220, 225, 239, 200, 130, 249, 149, 3, 216, 22, 9, 59, 254, 225,
+ 149, 155, 103, 142, 241, 207, 28, 247, 160, 255, 122, 28, 121, 230, 248,
+ 230, 153, 227, 127, 245, 243, 183, 247, 129, 97, 252, 193, 251, 8, 255,
+ 224, 58, 254, 31, 92, 135, 115, 255, 135, 239, 99, 252, 131, 235, 55,
+ 255, 193, 117, 6, 248, 251, 167, 96, 49, 203, 242, 183, 119, 99, 34,
+ 126, 127, 239, 37, 124, 239, 115, 248, 155, 164, 16, 192, 49, 42, 132,
+ 1, 161, 67, 104, 16, 45, 116, 250, 221, 238, 17, 16, 227, 108, 127,
+ 203, 183, 9, 27, 223, 62, 130, 181, 89, 241, 176, 255, 3, 197, 167,
+ 198, 138, 197, 60, 23, 213, 126, 183, 13, 11, 131, 197, 199, 225, 125,
+ 244, 31, 239, 168, 253, 117, 206, 242, 223, 242, 253, 34, 231, 87, 185,
+ 191, 47, 7, 37, 224, 63, 202, 249, 241, 222, 197, 255, 120, 12, 228,
+ 192, 142, 206, 2, 130, 190, 193, 226, 11, 9, 241, 111, 114, 16, 64,
+ 155, 33, 5, 179, 31, 230, 132, 20, 20, 115, 52, 186, 51, 117, 236,
+ 108, 28, 220, 144, 178, 181, 115, 178, 55, 49, 130, 12, 156, 77, 28,
+ 45, 12, 172, 207, 180, 25, 103, 142, 124, 37, 126, 197, 223, 181, 26,
+ 191, 115, 30, 250, 157, 116, 127, 255, 57, 253, 155, 255, 127, 121, 247,
+ 215, 175, 121, 127, 149, 251, 115, 124, 211, 162, 252, 126, 155, 244, 159,
+ 173, 7, 55, 129, 92, 50, 96, 45, 194, 217, 183, 95, 34, 194, 234,
+ 216, 143, 55, 145, 254, 174, 221, 190, 18, 191, 141, 95, 108, 249, 81,
+ 14, 112, 223, 211, 157, 241, 109, 202, 25, 91, 110, 72, 57, 26, 24,
+ 26, 90, 56, 67, 223, 75, 227, 215, 54, 28, 241, 255, 104, 57, 232,
+ 35, 253, 123, 202, 1, 46, 247, 223, 85, 14, 170, 176, 62, 52, 3,
+ 200, 162, 254, 187, 24, 255, 245, 163, 122, 77, 213, 196, 253, 55, 206,
+ 255, 90, 14, 190, 176, 250, 156, 34, 249, 123, 186, 126, 125, 215, 247,
+ 127, 228, 9, 183, 231, 87, 63, 35, 254, 75, 254, 145, 191, 1, 139,
+ 81, 132, 95, 234, 54, 41, 224, 254, 247, 237, 5, 60, 141, 147, 185,
+ 129, 177, 157, 27, 135, 179, 153, 193, 79, 253, 255, 247, 15, 39, 167,
+ 179, 137, 187, 179, 139, 163, 137, 19, 231, 153, 132, 240, 80, 251, 126,
+ 82, 247, 183, 115, 255, 207, 126, 244, 215, 143, 255, 105, 199, 32, 252,
+ 221, 49, 194, 223, 149, 211, 12, 244, 203, 88, 226, 28, 56, 38, 1,
+ 233, 217, 36, 255, 94, 198, 77, 58, 165, 239, 233, 224, 231, 225, 199,
+ 191, 202, 253, 149, 134, 36, 236, 31, 45, 58, 124, 114, 237, 191, 25,
+ 8, 255, 69, 64, 255, 199, 129, 240, 191, 140, 255, 43, 54, 35, 254,
+ 15, 227, 127, 195, 23, 255, 200, 94, 164, 223, 0, 242, 127, 19, 126,
+ 75, 246, 63, 242, 199, 255, 132, 221, 191, 101, 39, 202, 25, 160, 254,
+ 55, 227, 172, 236, 223, 242, 203, 191, 195, 15, 255, 200, 110, 228, 223,
+ 176, 21, 13, 0, 29, 0, 227, 55, 128, 249, 7, 248, 173, 60, 63,
+ 228, 253, 144, 255, 179, 79, 144, 255, 13, 126, 248, 61, 219, 145, 207,
+ 216, 140, 246, 147, 157, 112, 254, 88, 48, 96, 3, 224, 156, 1, 238,
+ 191, 136, 179, 121, 127, 200, 195, 250, 201, 71, 232, 103, 252, 113, 214,
+ 15, 255, 85, 31, 252, 108, 251, 217, 50, 63, 107, 247, 89, 123, 127,
+ 216, 136, 7, 159, 24, 11, 3, 1, 12, 132, 0, 68, 0, 231, 254,
+ 73, 252, 72, 255, 35, 63, 1, 144, 137, 119, 198, 55, 103, 253, 113,
+ 214, 15, 63, 199, 194, 127, 198, 7, 63, 219, 126, 182, 204, 127, 148,
+ 55, 22, 224, 241, 195, 94, 66, 192, 157, 24, 6, 18, 24, 206, 195,
+ 64, 10, 159, 20, 7, 159, 136, 15, 64, 241, 79, 226, 71, 122, 50,
+ 32, 227, 60, 144, 73, 12, 116, 16, 158, 241, 7, 14, 224, 242, 35,
+ 30, 126, 43, 22, 254, 21, 251, 255, 200, 118, 76, 224, 123, 60, 80,
+ 46, 68, 128, 27, 41, 224, 76, 9, 3, 53, 252, 97, 48, 252, 65,
+ 55, 124, 17, 38, 12, 23, 224, 15, 243, 1, 24, 254, 0, 63, 210,
+ 93, 0, 121, 105, 129, 44, 106, 32, 155, 28, 232, 34, 1, 186, 9,
+ 0, 23, 236, 51, 177, 240, 95, 241, 193, 207, 245, 253, 172, 237, 63,
+ 202, 28, 255, 140, 221, 100, 128, 23, 13, 224, 12, 183, 129, 9, 134,
+ 139, 48, 176, 192, 192, 10, 3, 27, 124, 114, 54, 0, 199, 31, 224,
+ 71, 58, 54, 144, 151, 5, 200, 98, 2, 178, 47, 0, 93, 148, 64,
+ 247, 15, 63, 224, 159, 137, 133, 179, 62, 248, 185, 61, 248, 87, 203,
+ 254, 172, 237, 184, 192, 223, 231, 64, 25, 252, 176, 27, 94, 94, 204,
+ 128, 43, 156, 59, 23, 124, 114, 6, 12, 188, 240, 69, 94, 240, 5,
+ 126, 48, 8, 194, 32, 4, 159, 204, 244, 7, 16, 2, 105, 5, 64,
+ 94, 94, 32, 139, 11, 200, 102, 1, 186, 232, 207, 248, 129, 20, 112,
+ 34, 0, 28, 207, 250, 224, 95, 137, 129, 223, 179, 29, 19, 248, 150,
+ 0, 212, 65, 184, 223, 169, 64, 89, 48, 129, 114, 226, 4, 92, 225,
+ 220, 69, 224, 147, 61, 225, 63, 160, 195, 112, 5, 134, 171, 240, 197,
+ 119, 48, 200, 192, 32, 11, 32, 247, 19, 126, 156, 151, 1, 105, 175,
+ 130, 188, 146, 64, 150, 8, 144, 205, 11, 116, 177, 2, 221, 23, 0,
+ 23, 50, 192, 141, 0, 112, 197, 252, 7, 62, 248, 103, 202, 30, 5,
+ 180, 169, 24, 160, 110, 225, 3, 31, 147, 129, 186, 8, 247, 255, 37,
+ 16, 179, 188, 160, 220, 224, 60, 165, 129, 29, 138, 48, 40, 193, 112,
+ 19, 6, 21, 24, 84, 225, 63, 120, 194, 39, 31, 254, 1, 212, 64,
+ 90, 21, 144, 87, 9, 200, 146, 5, 178, 197, 129, 46, 94, 160, 251,
+ 18, 224, 66, 13, 184, 157, 3, 92, 177, 1, 119, 180, 159, 234, 193,
+ 239, 197, 192, 63, 138, 123, 60, 80, 199, 72, 129, 175, 127, 216, 206,
+ 5, 226, 84, 12, 112, 147, 135, 65, 25, 240, 215, 132, 47, 56, 128,
+ 225, 46, 252, 135, 13, 248, 143, 0, 240, 133, 75, 48, 152, 192, 96,
+ 250, 59, 48, 1, 105, 140, 64, 158, 187, 64, 134, 38, 144, 169, 12,
+ 116, 72, 3, 157, 2, 128, 195, 15, 31, 80, 1, 142, 68, 128, 51,
+ 214, 191, 16, 3, 191, 85, 246, 103, 227, 158, 4, 212, 181, 11, 103,
+ 108, 135, 199, 163, 4, 40, 27, 37, 80, 118, 58, 128, 59, 220, 30,
+ 75, 24, 108, 96, 176, 135, 47, 106, 131, 79, 4, 129, 47, 38, 131,
+ 193, 245, 119, 224, 2, 210, 56, 130, 60, 54, 64, 134, 41, 144, 169,
+ 3, 116, 40, 1, 157, 18, 128, 195, 15, 31, 92, 0, 28, 73, 126,
+ 170, 7, 191, 21, 3, 127, 20, 251, 63, 151, 61, 25, 104, 111, 152,
+ 64, 220, 9, 0, 253, 240, 186, 123, 11, 6, 45, 192, 209, 28, 6,
+ 91, 96, 135, 7, 12, 94, 240, 9, 219, 48, 248, 195, 240, 0, 134,
+ 135, 48, 4, 194, 16, 244, 19, 2, 193, 181, 7, 32, 173, 47, 200,
+ 235, 1, 100, 217, 2, 217, 6, 64, 215, 45, 160, 91, 2, 112, 225,
+ 0, 220, 104, 0, 215, 159, 99, 224, 31, 213, 129, 179, 246, 255, 136,
+ 253, 179, 245, 254, 71, 217, 211, 131, 118, 135, 23, 196, 159, 44, 224,
+ 161, 13, 226, 214, 26, 112, 189, 15, 108, 128, 219, 21, 10, 67, 4,
+ 12, 209, 240, 137, 82, 240, 201, 136, 48, 196, 194, 16, 247, 19, 98,
+ 193, 181, 39, 32, 109, 4, 200, 27, 4, 100, 221, 7, 178, 173, 129,
+ 46, 109, 160, 91, 22, 112, 225, 5, 220, 232, 207, 196, 192, 217, 118,
+ 224, 71, 29, 248, 61, 251, 127, 174, 251, 24, 32, 126, 8, 65, 157,
+ 162, 1, 253, 14, 39, 104, 127, 164, 65, 28, 106, 1, 62, 240, 242,
+ 113, 7, 229, 22, 12, 248, 195, 237, 73, 132, 225, 5, 12, 47, 225,
+ 27, 73, 192, 144, 6, 159, 104, 1, 144, 14, 240, 227, 123, 26, 72,
+ 243, 18, 228, 73, 4, 50, 34, 128, 76, 95, 160, 195, 22, 232, 212,
+ 2, 28, 164, 1, 39, 78, 192, 145, 6, 112, 38, 4, 54, 96, 252,
+ 65, 27, 240, 123, 117, 31, 23, 180, 167, 228, 160, 110, 177, 0, 63,
+ 139, 131, 118, 72, 13, 196, 163, 53, 224, 229, 15, 202, 12, 94, 134,
+ 207, 97, 120, 5, 95, 108, 7, 67, 14, 124, 18, 60, 252, 135, 89,
+ 24, 138, 97, 40, 129, 255, 248, 252, 19, 74, 192, 181, 66, 144, 54,
+ 7, 228, 125, 5, 100, 61, 1, 178, 253, 129, 46, 107, 160, 91, 13,
+ 112, 17, 7, 220, 88, 0, 87, 114, 192, 29, 247, 159, 104, 3, 126,
+ 203, 254, 31, 117, 159, 24, 196, 19, 3, 24, 127, 8, 2, 127, 43,
+ 131, 246, 200, 28, 196, 165, 47, 224, 7, 143, 227, 100, 80, 174, 121,
+ 192, 174, 74, 24, 222, 194, 39, 154, 194, 80, 7, 95, 152, 2, 208,
+ 8, 240, 227, 123, 29, 72, 243, 22, 228, 41, 1, 50, 210, 129, 204,
+ 88, 160, 195, 23, 232, 52, 7, 28, 148, 1, 39, 65, 192, 145, 1,
+ 112, 38, 62, 211, 6, 252, 43, 246, 163, 255, 84, 247, 169, 65, 219,
+ 194, 5, 198, 33, 178, 160, 63, 50, 0, 177, 120, 31, 196, 231, 19,
+ 192, 51, 19, 190, 88, 28, 216, 0, 183, 167, 9, 134, 86, 24, 218,
+ 97, 232, 132, 161, 11, 134, 15, 240, 133, 143, 0, 31, 192, 185, 78,
+ 144, 166, 21, 228, 169, 5, 50, 138, 128, 204, 100, 160, 35, 24, 232,
+ 180, 5, 28, 84, 1, 39, 17, 192, 145, 9, 112, 62, 219, 6, 160,
+ 255, 147, 246, 163, 158, 177, 159, 0, 220, 123, 209, 128, 49, 56, 15,
+ 136, 51, 69, 208, 39, 155, 130, 114, 240, 7, 117, 244, 57, 40, 43,
+ 56, 223, 106, 80, 182, 109, 192, 190, 62, 248, 66, 124, 248, 228, 49,
+ 24, 70, 224, 139, 12, 126, 194, 8, 184, 54, 8, 210, 126, 0, 121,
+ 27, 129, 172, 34, 32, 251, 57, 208, 229, 15, 116, 155, 2, 46, 138,
+ 128, 27, 15, 224, 74, 3, 184, 19, 156, 177, 31, 245, 15, 236, 255,
+ 189, 182, 143, 246, 76, 221, 151, 4, 109, 142, 46, 232, 155, 61, 64,
+ 27, 253, 20, 212, 213, 60, 80, 102, 112, 222, 29, 48, 244, 194, 23,
+ 224, 193, 48, 6, 195, 36, 12, 211, 240, 133, 206, 240, 205, 202, 126,
+ 194, 71, 112, 109, 18, 164, 29, 2, 121, 59, 128, 172, 74, 32, 251,
+ 21, 208, 21, 4, 116, 91, 2, 46, 74, 128, 219, 143, 54, 128, 246,
+ 31, 180, 129, 103, 237, 71, 248, 3, 251, 201, 192, 125, 40, 43, 184,
+ 31, 185, 2, 198, 165, 119, 193, 248, 196, 11, 212, 201, 68, 208, 94,
+ 149, 128, 184, 109, 3, 252, 71, 128, 77, 112, 251, 62, 193, 39, 51,
+ 194, 176, 4, 195, 242, 79, 88, 2, 215, 62, 129, 180, 147, 32, 111,
+ 47, 144, 85, 11, 100, 103, 0, 93, 161, 64, 183, 13, 224, 114, 19,
+ 112, 227, 7, 92, 233, 0, 247, 127, 100, 63, 194, 31, 216, 79, 116,
+ 166, 237, 103, 3, 227, 140, 171, 96, 108, 110, 0, 198, 104, 190, 32,
+ 30, 95, 128, 54, 187, 18, 212, 221, 15, 160, 12, 225, 118, 204, 193,
+ 176, 8, 159, 144, 5, 195, 103, 24, 214, 97, 216, 248, 9, 235, 224,
+ 218, 10, 72, 59, 7, 242, 14, 1, 89, 77, 64, 118, 14, 208, 21,
+ 1, 116, 219, 3, 46, 42, 128, 155, 0, 224, 250, 163, 15, 32, 250,
+ 79, 218, 143, 123, 198, 126, 250, 51, 109, 255, 53, 208, 222, 24, 129,
+ 113, 170, 63, 24, 175, 188, 4, 253, 214, 91, 208, 126, 245, 129, 56,
+ 254, 8, 236, 89, 5, 54, 126, 129, 225, 43, 124, 49, 215, 79, 248,
+ 10, 174, 173, 131, 180, 139, 32, 239, 24, 144, 213, 10, 100, 231, 3,
+ 93, 209, 64, 183, 35, 224, 162, 10, 184, 253, 232, 3, 232, 207, 216,
+ 143, 251, 159, 180, 255, 28, 120, 30, 245, 195, 126, 33, 112, 127, 170,
+ 6, 198, 31, 206, 96, 188, 250, 4, 140, 91, 10, 65, 156, 182, 131,
+ 118, 108, 18, 196, 243, 10, 176, 11, 110, 227, 54, 124, 226, 52, 12,
+ 187, 48, 236, 1, 236, 130, 115, 219, 32, 205, 58, 200, 243, 9, 200,
+ 24, 4, 50, 107, 129, 142, 215, 64, 231, 3, 192, 193, 24, 112, 146,
+ 1, 28, 127, 216, 79, 113, 102, 12, 240, 175, 216, 143, 249, 147, 253,
+ 12, 96, 124, 45, 12, 250, 25, 117, 112, 175, 230, 2, 198, 236, 79,
+ 193, 216, 173, 24, 244, 225, 157, 160, 45, 159, 6, 117, 250, 51, 40,
+ 219, 109, 96, 235, 55, 248, 98, 181, 159, 240, 13, 92, 219, 6, 105,
+ 63, 131, 188, 211, 64, 86, 39, 144, 93, 12, 116, 61, 5, 186, 93,
+ 0, 23, 117, 192, 77, 24, 112, 101, 248, 201, 126, 204, 255, 102, 251,
+ 77, 193, 61, 91, 32, 24, 151, 188, 1, 237, 83, 3, 232, 203, 71,
+ 64, 252, 46, 157, 41, 251, 157, 51, 182, 31, 192, 55, 68, 3, 56,
+ 56, 227, 131, 157, 51, 49, 176, 4, 100, 140, 0, 153, 13, 64, 199,
+ 27, 160, 51, 16, 112, 48, 253, 31, 180, 95, 238, 39, 251, 131, 192,
+ 253, 203, 27, 48, 142, 109, 0, 237, 213, 40, 232, 215, 150, 65, 251,
+ 182, 5, 202, 247, 172, 237, 71, 0, 103, 125, 176, 11, 210, 110, 128,
+ 188, 179, 64, 214, 7, 32, 187, 20, 232, 138, 3, 186, 207, 218, 47,
+ 247, 191, 104, 127, 58, 224, 214, 8, 198, 116, 191, 101, 255, 30, 176,
+ 241, 172, 237, 103, 125, 176, 15, 210, 252, 150, 253, 221, 64, 118, 41,
+ 208, 245, 151, 253, 255, 183, 236, 255, 179, 196, 255, 159, 189, 253, 251,
+ 51, 244, 127, 127, 246, 241, 207, 95, 227, 223, 191, 238, 127, 254, 44,
+ 247, 191, 127, 246, 231, 31, 127, 61, 255, 250, 235, 249, 231, 95, 207,
+ 191, 255, 250, 253, 227, 207, 254, 251, 215, 159, 253, 247, 207, 63, 243,
+ 239, 223, 127, 246, 249, 15, 127, 205, 127, 249, 107, 254, 211, 159, 125,
+ 254, 219, 95, 243, 31, 255, 154, 255, 250, 215, 252, 231, 191, 230, 191,
+ 255, 181, 254, 225, 175, 245, 47, 127, 173, 127, 250, 107, 253, 219, 95,
+ 235, 31, 255, 90, 255, 250, 215, 250, 231, 255, 207, 215, 191, 255, 109,
+ 135, 8, 21, 181, 107, 234, 242, 183, 229, 149, 149, 216, 53, 101, 228,
+ 175, 95, 227, 248, 117, 111, 134, 153, 95, 247, 102, 56, 187, 15, 203,
+ 47, 123, 51, 252, 178, 191, 199, 101, 14, 75, 123, 179, 223, 216, 195,
+ 192, 81, 88, 247, 174, 189, 139, 161, 181, 133, 147, 185, 137, 35, 187,
+ 189, 163, 137, 181, 157, 129, 177, 137, 163, 46, 216, 177, 65, 247, 183,
+ 115, 255, 207, 126, 184, 16, 190, 253, 151, 246, 102, 248, 113, 110, 115,
+ 243, 215, 189, 25, 224, 199, 63, 246, 102, 24, 188, 241, 247, 50, 82,
+ 114, 127, 217, 155, 97, 228, 198, 47, 199, 63, 100, 156, 142, 156, 206,
+ 64, 248, 10, 50, 242, 50, 16, 2, 34, 2, 36, 7, 251, 7, 157,
+ 174, 17, 190, 185, 105, 110, 231, 108, 231, 100, 110, 103, 79, 123, 153,
+ 131, 11, 18, 188, 34, 127, 3, 105, 237, 151, 205, 148, 224, 41, 190,
+ 211, 0, 255, 195, 175, 33, 227, 124, 191, 6, 223, 238, 196, 253, 123,
+ 218, 173, 239, 223, 209, 127, 104, 255, 158, 6, 243, 7, 113, 248, 55,
+ 102, 124, 176, 245, 213, 15, 67, 16, 191, 231, 219, 249, 126, 44, 7,
+ 113, 154, 154, 194, 174, 88, 195, 254, 162, 130, 92, 191, 156, 121, 153,
+ 144, 248, 183, 51, 191, 108, 221, 165, 13, 251, 251, 227, 12, 223, 247,
+ 191, 236, 191, 158, 249, 46, 243, 219, 47, 155, 123, 65, 240, 200, 251,
+ 141, 15, 210, 210, 247, 125, 91, 254, 219, 175, 125, 183, 249, 199, 134,
+ 39, 72, 223, 191, 253, 82, 226, 164, 191, 87, 206, 223, 211, 160, 3,
+ 47, 127, 247, 20, 162, 228, 47, 0, 215, 206, 253, 205, 203, 132, 223,
+ 191, 99, 127, 79, 250, 9, 20, 165, 253, 47, 64, 184, 9, 65, 49,
+ 240, 243, 173, 48, 77, 8, 191, 89, 190, 235, 16, 174, 148, 177, 157,
+ 161, 9, 100, 12, 127, 191, 29, 194, 233, 56, 244, 0, 194, 70, 71,
+ 71, 199, 64, 199, 198, 192, 192, 38, 192, 194, 196, 34, 32, 198, 195,
+ 198, 198, 35, 38, 37, 34, 34, 38, 34, 34, 37, 192, 254, 254, 1,
+ 255, 253, 246, 7, 1, 7, 11, 11, 7, 23, 7, 31, 23, 23, 255,
+ 28, 46, 46, 238, 57, 248, 31, 220, 115, 191, 100, 33, 248, 103, 4,
+ 156, 214, 65, 4, 232, 48, 3, 236, 145, 16, 46, 64, 136, 4, 8,
+ 72, 4, 8, 167, 147, 48, 99, 209, 78, 155, 16, 36, 96, 44, 81,
+ 16, 190, 127, 128, 175, 144, 96, 230, 32, 163, 160, 162, 161, 99, 96,
+ 98, 33, 252, 124, 17, 1, 66, 68, 250, 113, 17, 31, 66, 64, 70,
+ 64, 66, 68, 70, 68, 65, 67, 69, 71, 65, 194, 190, 12, 187, 72,
+ 128, 132, 76, 71, 200, 141, 34, 117, 203, 128, 232, 130, 131, 31, 15,
+ 234, 185, 168, 151, 133, 87, 232, 25, 136, 85, 234, 13, 47, 243, 58,
+ 250, 247, 74, 163, 49, 70, 223, 222, 252, 248, 197, 200, 137, 143, 228,
+ 85, 81, 0, 211, 213, 24, 85, 227, 107, 13, 175, 157, 249, 207, 247,
+ 169, 205, 154, 124, 45, 126, 208, 216, 239, 50, 183, 37, 195, 252, 36,
+ 245, 97, 201, 211, 166, 129, 79, 219, 105, 165, 239, 7, 231, 119, 212,
+ 77, 93, 3, 99, 223, 148, 53, 15, 45, 236, 10, 200, 106, 152, 185,
+ 5, 197, 165, 151, 183, 12, 47, 238, 17, 64, 136, 136, 48, 182, 200,
+ 223, 57, 161, 161, 162, 240, 125, 167, 64, 199, 77, 136, 12, 99, 224,
+ 112, 129, 8, 133, 199, 47, 234, 28, 156, 65, 189, 74, 239, 230, 101,
+ 6, 195, 143, 142, 254, 209, 210, 183, 137, 141, 156, 120, 191, 48, 162,
+ 194, 9, 160, 49, 241, 53, 244, 193, 72, 188, 62, 111, 124, 77, 141,
+ 223, 217, 100, 246, 111, 20, 126, 159, 1, 243, 175, 20, 78, 199, 32,
+ 108, 164, 239, 58, 9, 32, 9, 168, 100, 237, 101, 106, 28, 6, 30,
+ 249, 234, 132, 237, 30, 47, 222, 167, 204, 119, 67, 26, 183, 177, 74,
+ 142, 134, 49, 14, 152, 180, 123, 118, 215, 220, 202, 147, 87, 236, 110,
+ 149, 32, 42, 62, 214, 70, 62, 124, 131, 91, 219, 190, 123, 232, 90,
+ 57, 181, 203, 166, 84, 58, 80, 230, 39, 63, 132, 86, 46, 207, 248,
+ 70, 172, 234, 176, 252, 158, 202, 237, 26, 181, 48, 78, 179, 117, 63,
+ 17, 55, 251, 229, 205, 201, 245, 177, 201, 252, 177, 144, 219, 150, 70,
+ 146, 180, 94, 180, 139, 21, 136, 66, 132, 226, 49, 53, 47, 198, 249,
+ 15, 125, 118, 204, 46, 133, 12, 234, 177, 27, 69, 84, 166, 223, 232,
+ 74, 66, 248, 216, 145, 186, 156, 128, 93, 154, 231, 58, 59, 139, 246,
+ 192, 31, 125, 12, 109, 135, 255, 152, 230, 88, 99, 57, 77, 96, 233,
+ 101, 106, 153, 73, 103, 142, 237, 148, 60, 141, 226, 50, 234, 97, 205,
+ 187, 161, 92, 81, 87, 212, 230, 17, 174, 30, 99, 251, 251, 135, 238,
+ 180, 70, 1, 219, 111, 164, 168, 251, 204, 154, 14, 239, 190, 246, 137,
+ 57, 169, 237, 90, 26, 188, 101, 124, 30, 215, 135, 147, 195, 80, 225,
+ 54, 43, 142, 62, 101, 27, 151, 81, 83, 67, 20, 59, 244, 98, 70,
+ 142, 168, 59, 250, 201, 61, 185, 125, 220, 155, 83, 195, 49, 107, 9,
+ 168, 202, 54, 216, 202, 125, 199, 27, 43, 169, 105, 143, 183, 119, 227,
+ 113, 241, 233, 55, 110, 10, 84, 248, 127, 92, 64, 118, 35, 72, 223,
+ 245, 106, 119, 30, 66, 15, 138, 120, 73, 173, 187, 181, 118, 185, 252,
+ 225, 121, 245, 186, 161, 53, 238, 151, 104, 241, 18, 251, 52, 31, 228,
+ 21, 4, 86, 153, 140, 154, 245, 79, 33, 230, 39, 167, 144, 37, 142,
+ 133, 133, 112, 56, 70, 112, 12, 243, 180, 196, 53, 244, 161, 6, 42,
+ 19, 253, 117, 15, 14, 119, 102, 127, 153, 110, 187, 253, 96, 229, 34,
+ 4, 134, 53, 130, 42, 249, 254, 218, 16, 121, 121, 235, 182, 204, 46,
+ 60, 100, 235, 40, 238, 47, 227, 184, 189, 102, 38, 165, 41, 144, 59,
+ 178, 136, 125, 184, 143, 187, 143, 217, 177, 183, 63, 251, 13, 196, 87,
+ 7, 143, 117, 153, 52, 133, 98, 50, 167, 211, 123, 167, 143, 34, 142,
+ 252, 3, 165, 35, 10, 99, 82, 144, 43, 132, 141, 151, 215, 198, 203,
+ 247, 188, 99, 183, 85, 97, 189, 101, 79, 177, 215, 67, 255, 197, 98,
+ 123, 232, 60, 73, 149, 228, 209, 204, 41, 228, 32, 82, 219, 103, 183,
+ 163, 179, 226, 211, 204, 66, 69, 65, 92, 246, 201, 216, 69, 183, 44,
+ 72, 128, 146, 170, 186, 102, 236, 75, 245, 158, 106, 213, 235, 145, 177,
+ 61, 30, 82, 175, 222, 116, 180, 164, 220, 221, 53, 23, 159, 1, 169,
+ 21, 134, 57, 103, 107, 165, 216, 254, 194, 81, 250, 129, 50, 4, 252,
+ 233, 180, 109, 159, 165, 212, 44, 19, 42, 129, 124, 149, 67, 7, 86,
+ 98, 157, 91, 123, 114, 1, 18, 53, 107, 234, 158, 84, 110, 132, 82,
+ 162, 130, 136, 188, 65, 164, 7, 194, 201, 105, 213, 199, 62, 125, 170,
+ 75, 236, 182, 244, 137, 155, 200, 98, 69, 104, 59, 46, 78, 186, 85,
+ 226, 81, 146, 54, 187, 149, 185, 236, 6, 238, 180, 34, 122, 232, 243,
+ 121, 167, 144, 236, 41, 244, 154, 16, 181, 79, 138, 92, 120, 36, 62,
+ 86, 67, 211, 105, 98, 49, 238, 186, 45, 20, 238, 21, 122, 192, 126,
+ 192, 190, 123, 111, 48, 101, 45, 12, 74, 26, 195, 224, 64, 58, 73,
+ 158, 10, 238, 227, 191, 238, 209, 73, 19, 71, 163, 56, 150, 61, 241,
+ 181, 87, 226, 249, 44, 122, 4, 193, 41, 164, 58, 237, 58, 16, 25,
+ 119, 15, 171, 204, 222, 3, 169, 117, 89, 34, 105, 191, 213, 206, 9,
+ 169, 172, 130, 170, 137, 232, 56, 118, 217, 76, 162, 186, 250, 208, 210,
+ 89, 117, 152, 123, 44, 26, 215, 175, 166, 78, 196, 167, 18, 235, 82,
+ 253, 203, 151, 235, 177, 168, 9, 145, 130, 71, 117, 87, 20, 20, 86,
+ 73, 251, 60, 208, 182, 94, 55, 42, 31, 36, 181, 42, 241, 227, 223,
+ 93, 243, 224, 234, 251, 152, 238, 254, 201, 238, 120, 254, 250, 132, 158,
+ 211, 39, 255, 41, 52, 218, 138, 15, 171, 252, 197, 203, 247, 180, 55,
+ 62, 251, 140, 63, 186, 176, 27, 64, 94, 133, 193, 70, 27, 57, 140,
+ 136, 219, 181, 238, 84, 43, 226, 58, 189, 115, 76, 126, 219, 176, 175,
+ 69, 163, 220, 181, 79, 151, 177, 25, 239, 235, 30, 94, 151, 35, 1,
+ 237, 24, 169, 88, 81, 157, 246, 71, 232, 186, 207, 179, 109, 177, 83,
+ 168, 227, 152, 249, 136, 5, 165, 146, 130, 5, 71, 36, 109, 221, 137,
+ 124, 193, 95, 239, 109, 28, 137, 180, 87, 178, 178, 235, 241, 114, 238,
+ 189, 220, 114, 39, 170, 150, 18, 91, 124, 233, 230, 112, 11, 135, 221,
+ 147, 167, 131, 39, 86, 62, 157, 242, 215, 117, 247, 30, 151, 157, 135,
+ 12, 113, 238, 201, 108, 184, 245, 21, 126, 144, 80, 62, 72, 126, 125,
+ 10, 101, 43, 205, 46, 150, 214, 81, 173, 249, 106, 95, 149, 233, 167,
+ 121, 237, 179, 83, 59, 124, 130, 79, 172, 185, 56, 209, 60, 178, 136,
+ 184, 200, 95, 251, 74, 91, 172, 65, 177, 86, 188, 251, 246, 128, 119,
+ 75, 33, 113, 25, 218, 144, 149, 147, 107, 77, 24, 215, 210, 199, 186,
+ 67, 189, 242, 173, 119, 113, 199, 188, 240, 224, 232, 21, 217, 76, 72,
+ 72, 86, 227, 180, 160, 75, 181, 139, 105, 181, 152, 62, 78, 78, 45,
+ 60, 104, 190, 213, 185, 58, 204, 69, 80, 84, 52, 214, 92, 147, 40,
+ 64, 60, 48, 43, 96, 81, 182, 139, 35, 237, 149, 40, 133, 202, 119,
+ 210, 55, 83, 200, 227, 211, 30, 55, 106, 148, 218, 225, 71, 159, 32,
+ 62, 48, 154, 116, 126, 142, 58, 101, 221, 80, 210, 122, 168, 79, 250,
+ 46, 68, 67, 131, 184, 49, 165, 199, 143, 218, 35, 25, 144, 137, 139,
+ 20, 142, 86, 69, 35, 33, 181, 126, 224, 179, 186, 242, 245, 88, 168,
+ 171, 112, 35, 51, 53, 230, 117, 34, 179, 116, 235, 226, 178, 237, 158,
+ 144, 139, 222, 69, 10, 243, 204, 197, 201, 210, 112, 139, 113, 242, 250,
+ 233, 42, 113, 239, 141, 21, 159, 248, 215, 69, 233, 213, 197, 186, 113,
+ 54, 236, 123, 114, 144, 185, 49, 65, 149, 143, 219, 210, 155, 194, 92,
+ 225, 36, 109, 190, 11, 188, 180, 73, 249, 195, 7, 185, 42, 153, 47,
+ 67, 113, 160, 32, 126, 125, 171, 99, 195, 41, 159, 232, 87, 125, 179,
+ 13, 75, 227, 111, 151, 152, 76, 197, 67, 104, 100, 167, 183, 137, 98,
+ 47, 91, 213, 217, 54, 190, 196, 151, 15, 119, 121, 49, 221, 46, 213,
+ 89, 100, 205, 64, 133, 206, 190, 187, 114, 61, 98, 37, 249, 85, 202,
+ 42, 100, 84, 86, 33, 133, 28, 196, 75, 99, 97, 30, 103, 251, 0,
+ 177, 97, 175, 162, 141, 182, 59, 163, 121, 215, 185, 35, 185, 241, 121,
+ 215, 212, 238, 41, 52, 172, 162, 98, 89, 67, 225, 182, 238, 206, 16,
+ 162, 239, 75, 155, 108, 165, 87, 129, 51, 88, 211, 170, 97, 216, 51,
+ 187, 138, 206, 39, 98, 142, 236, 79, 110, 144, 178, 102, 103, 122, 232,
+ 118, 140, 247, 45, 91, 162, 62, 107, 119, 125, 202, 184, 49, 60, 21,
+ 7, 15, 165, 218, 90, 124, 195, 233, 197, 70, 175, 79, 126, 38, 207,
+ 225, 234, 212, 161, 64, 205, 251, 158, 143, 235, 241, 20, 58, 20, 74,
+ 11, 199, 204, 62, 249, 223, 24, 82, 73, 52, 76, 226, 231, 243, 236,
+ 93, 103, 123, 113, 201, 5, 21, 75, 246, 248, 198, 189, 62, 164, 155,
+ 238, 122, 71, 108, 39, 111, 90, 90, 187, 168, 108, 14, 109, 16, 199,
+ 32, 244, 232, 173, 125, 217, 77, 250, 112, 112, 103, 241, 20, 90, 25,
+ 152, 29, 46, 124, 229, 98, 85, 123, 245, 27, 67, 19, 205, 61, 202,
+ 13, 215, 233, 111, 234, 94, 152, 181, 155, 4, 101, 229, 158, 126, 129,
+ 164, 51, 179, 140, 69, 8, 104, 203, 181, 86, 62, 30, 176, 16, 59,
+ 133, 122, 45, 46, 153, 173, 187, 164, 174, 30, 208, 178, 187, 163, 109,
+ 37, 111, 24, 115, 55, 142, 86, 159, 228, 111, 13, 232, 242, 96, 117,
+ 176, 237, 161, 34, 101, 235, 228, 205, 50, 126, 168, 57, 12, 28, 90,
+ 247, 73, 63, 86, 86, 24, 216, 16, 241, 162, 88, 137, 30, 191, 138,
+ 129, 22, 98, 99, 227, 242, 44, 185, 122, 191, 236, 224, 222, 216, 198,
+ 196, 118, 191, 141, 121, 94, 121, 28, 213, 26, 77, 26, 253, 68, 11,
+ 62, 37, 219, 30, 47, 119, 233, 161, 222, 209, 198, 1, 191, 119, 204,
+ 49, 139, 130, 207, 105, 223, 84, 221, 155, 238, 162, 105, 28, 219, 77,
+ 74, 163, 200, 141, 15, 115, 251, 119, 97, 45, 204, 170, 85, 231, 193,
+ 99, 37, 60, 221, 119, 175, 183, 239, 184, 241, 126, 161, 93, 169, 81,
+ 76, 21, 47, 24, 86, 149, 134, 5, 189, 46, 213, 20, 243, 41, 196,
+ 173, 203, 60, 252, 33, 202, 198, 67, 194, 214, 220, 181, 13, 123, 226,
+ 158, 197, 231, 136, 207, 180, 215, 242, 66, 94, 91, 188, 203, 228, 27,
+ 77, 216, 64, 246, 14, 229, 238, 23, 43, 61, 80, 44, 93, 42, 137,
+ 253, 216, 41, 91, 133, 228, 71, 77, 131, 242, 225, 88, 166, 249, 213,
+ 243, 243, 107, 140, 249, 165, 201, 215, 35, 186, 184, 69, 124, 86, 72,
+ 78, 216, 79, 18, 138, 242, 149, 237, 82, 181, 77, 189, 159, 224, 84,
+ 29, 211, 76, 157, 180, 28, 107, 35, 16, 242, 235, 73, 59, 145, 15,
+ 21, 44, 25, 249, 17, 161, 45, 123, 91, 18, 39, 92, 119, 114, 33,
+ 156, 114, 67, 186, 96, 54, 121, 10, 41, 30, 251, 120, 63, 94, 247,
+ 86, 12, 54, 46, 109, 112, 173, 168, 163, 77, 216, 93, 90, 155, 150,
+ 34, 171, 24, 18, 126, 133, 187, 96, 238, 108, 59, 20, 239, 182, 126,
+ 204, 185, 115, 10, 213, 61, 58, 239, 122, 103, 104, 221, 126, 2, 194,
+ 231, 157, 164, 244, 118, 219, 113, 165, 195, 178, 46, 234, 182, 170, 183,
+ 182, 25, 19, 53, 232, 234, 61, 212, 92, 56, 176, 53, 59, 162, 134,
+ 57, 253, 20, 26, 10, 138, 210, 209, 36, 239, 69, 105, 198, 186, 203,
+ 67, 201, 164, 187, 86, 93, 46, 112, 80, 155, 124, 32, 113, 67, 196,
+ 104, 144, 3, 23, 135, 155, 205, 159, 191, 202, 108, 252, 228, 252, 150,
+ 207, 179, 209, 195, 228, 221, 175, 42, 236, 229, 218, 253, 37, 159, 7,
+ 172, 45, 6, 168, 100, 114, 92, 135, 42, 223, 250, 8, 28, 72, 28,
+ 211, 209, 57, 61, 95, 40, 26, 18, 241, 56, 144, 122, 173, 1, 9,
+ 120, 113, 190, 90, 93, 118, 235, 59, 62, 168, 149, 221, 95, 185, 94,
+ 84, 30, 214, 229, 63, 195, 116, 213, 38, 160, 48, 125, 124, 91, 123,
+ 237, 101, 172, 214, 126, 8, 215, 160, 113, 220, 219, 176, 7, 197, 110,
+ 134, 67, 17, 139, 15, 146, 222, 37, 167, 159, 66, 183, 78, 33, 242,
+ 232, 216, 199, 218, 125, 55, 244, 35, 186, 227, 120, 45, 56, 112, 220,
+ 106, 15, 166, 186, 55, 147, 95, 159, 232, 16, 33, 178, 32, 12, 137,
+ 13, 225, 165, 213, 204, 242, 29, 136, 220, 45, 204, 27, 95, 94, 223,
+ 61, 156, 254, 108, 118, 92, 53, 91, 21, 63, 44, 98, 206, 30, 156,
+ 175, 55, 102, 121, 220, 121, 180, 104, 99, 127, 10, 213, 231, 202, 239,
+ 150, 190, 233, 26, 119, 195, 31, 162, 16, 144, 114, 246, 121, 48, 89,
+ 189, 92, 108, 183, 116, 124, 146, 165, 96, 100, 229, 106, 173, 239, 221,
+ 120, 187, 156, 183, 147, 171, 90, 198, 70, 226, 53, 251, 218, 254, 41,
+ 180, 51, 208, 197, 65, 162, 165, 123, 222, 119, 161, 166, 183, 90, 210,
+ 135, 87, 194, 174, 247, 68, 57, 243, 132, 232, 100, 156, 145, 221, 105,
+ 252, 182, 110, 95, 189, 89, 5, 137, 124, 156, 69, 57, 172, 83, 252,
+ 124, 10, 181, 106, 104, 177, 31, 83, 133, 79, 172, 145, 143, 26, 233,
+ 164, 146, 6, 201, 82, 212, 200, 141, 151, 31, 91, 195, 194, 171, 127,
+ 100, 201, 205, 182, 170, 89, 180, 74, 115, 115, 223, 126, 156, 252, 158,
+ 68, 209, 198, 246, 179, 154, 21, 31, 45, 110, 150, 174, 204, 157, 210,
+ 24, 147, 176, 49, 82, 231, 61, 188, 151, 184, 110, 229, 91, 79, 243,
+ 18, 252, 110, 176, 151, 211, 150, 230, 246, 148, 15, 92, 166, 149, 119,
+ 74, 52, 21, 15, 159, 215, 16, 201, 222, 30, 214, 94, 201, 114, 191,
+ 87, 111, 142, 199, 197, 16, 124, 180, 113, 228, 47, 239, 80, 69, 214,
+ 217, 96, 149, 229, 98, 99, 101, 137, 140, 49, 64, 253, 177, 118, 159,
+ 170, 67, 246, 220, 99, 30, 118, 225, 195, 15, 11, 232, 95, 15, 112,
+ 143, 167, 15, 166, 143, 200, 107, 237, 228, 77, 182, 53, 108, 40, 52,
+ 59, 172, 46, 212, 185, 160, 154, 140, 157, 66, 3, 62, 183, 110, 165,
+ 187, 144, 81, 232, 210, 27, 196, 227, 155, 45, 219, 156, 104, 148, 47,
+ 165, 166, 219, 145, 132, 56, 56, 165, 70, 234, 98, 156, 66, 153, 159,
+ 169, 182, 245, 214, 213, 239, 76, 166, 148, 33, 32, 135, 223, 219, 61,
+ 154, 126, 189, 221, 215, 124, 143, 66, 53, 12, 57, 201, 103, 99, 140,
+ 101, 148, 51, 218, 53, 73, 116, 59, 210, 104, 98, 216, 199, 130, 129,
+ 151, 135, 157, 196, 206, 2, 95, 191, 244, 1, 141, 197, 16, 127, 181,
+ 244, 209, 226, 193, 33, 97, 122, 191, 129, 123, 16, 95, 105, 96, 97,
+ 98, 163, 175, 57, 146, 146, 120, 236, 41, 116, 96, 142, 199, 48, 116,
+ 200, 22, 7, 41, 173, 165, 198, 135, 141, 151, 196, 9, 189, 123, 238,
+ 99, 64, 144, 75, 215, 197, 23, 72, 174, 147, 55, 211, 99, 76, 85,
+ 77, 222, 61, 105, 59, 116, 10, 5, 192, 186, 212, 187, 199, 54, 140,
+ 97, 36, 182, 105, 105, 213, 87, 239, 213, 164, 188, 64, 82, 108, 116,
+ 222, 114, 157, 156, 150, 62, 133, 68, 187, 201, 186, 207, 227, 57, 80,
+ 40, 29, 60, 31, 138, 90, 195, 73, 58, 89, 40, 222, 190, 171, 120,
+ 112, 18, 7, 11, 25, 34, 189, 216, 106, 74, 146, 183, 158, 79, 149,
+ 242, 130, 108, 81, 222, 45, 248, 208, 193, 170, 250, 100, 232, 41, 84,
+ 54, 40, 149, 112, 35, 97, 33, 210, 181, 50, 232, 70, 42, 62, 147,
+ 128, 167, 247, 198, 188, 196, 190, 207, 166, 207, 50, 97, 146, 130, 21,
+ 103, 230, 76, 144, 198, 114, 20, 158, 175, 238, 48, 162, 143, 252, 6,
+ 238, 100, 77, 190, 145, 171, 247, 41, 180, 229, 170, 25, 227, 166, 101,
+ 128, 29, 116, 40, 233, 164, 148, 234, 199, 236, 140, 122, 76, 99, 163,
+ 60, 173, 147, 99, 118, 32, 177, 104, 181, 163, 229, 91, 118, 195, 108,
+ 192, 230, 129, 63, 185, 36, 82, 33, 77, 170, 196, 243, 197, 147, 160,
+ 163, 11, 133, 106, 34, 119, 87, 130, 20, 223, 8, 188, 208, 92, 62,
+ 128, 245, 152, 50, 45, 158, 161, 242, 242, 150, 57, 93, 6, 185, 113,
+ 92, 138, 206, 17, 246, 8, 85, 27, 28, 147, 213, 163, 39, 181, 31,
+ 164, 47, 190, 183, 181, 231, 50, 116, 255, 244, 237, 20, 202, 63, 65,
+ 219, 238, 253, 208, 34, 250, 168, 213, 234, 206, 50, 210, 77, 201, 192,
+ 56, 174, 117, 187, 245, 195, 155, 28, 78, 202, 101, 116, 101, 74, 207,
+ 195, 196, 195, 55, 14, 23, 79, 178, 229, 241, 78, 7, 134, 15, 54,
+ 146, 188, 169, 81, 42, 70, 166, 229, 159, 158, 47, 227, 141, 183, 74,
+ 110, 249, 234, 154, 207, 146, 158, 113, 160, 39, 139, 185, 254, 124, 245,
+ 171, 157, 147, 206, 110, 226, 87, 136, 110, 175, 162, 178, 108, 88, 154,
+ 149, 243, 24, 181, 133, 187, 212, 246, 152, 99, 103, 53, 89, 43, 115,
+ 231, 242, 177, 202, 113, 138, 80, 46, 178, 171, 223, 164, 193, 246, 187,
+ 176, 62, 171, 110, 129, 185, 94, 61, 38, 170, 119, 187, 33, 246, 71,
+ 195, 85, 33, 19, 99, 94, 225, 71, 77, 209, 151, 134, 151, 188, 164,
+ 230, 206, 127, 222, 21, 236, 64, 70, 250, 16, 224, 214, 119, 146, 149,
+ 153, 248, 245, 115, 121, 252, 94, 16, 190, 182, 179, 149, 223, 152, 0,
+ 222, 74, 37, 121, 206, 219, 235, 194, 228, 99, 202, 149, 169, 165, 169,
+ 123, 139, 135, 56, 147, 88, 226, 157, 126, 198, 99, 138, 51, 113, 82,
+ 228, 82, 200, 101, 184, 126, 167, 80, 219, 41, 84, 78, 120, 187, 58,
+ 34, 185, 44, 29, 33, 19, 165, 190, 186, 28, 137, 38, 41, 199, 231,
+ 69, 80, 84, 116, 139, 252, 118, 27, 114, 96, 84, 193, 186, 8, 172,
+ 200, 229, 203, 247, 124, 118, 46, 180, 189, 218, 100, 141, 119, 162, 28,
+ 138, 97, 63, 184, 34, 233, 68, 51, 238, 86, 123, 10, 169, 179, 230,
+ 216, 39, 117, 35, 221, 46, 107, 24, 141, 202, 91, 40, 204, 67, 218,
+ 47, 47, 62, 98, 222, 21, 83, 222, 182, 80, 196, 31, 122, 172, 169,
+ 73, 121, 151, 211, 201, 77, 232, 147, 47, 239, 88, 99, 233, 244, 200,
+ 41, 244, 64, 166, 133, 118, 244, 166, 7, 95, 101, 24, 110, 65, 36,
+ 210, 227, 80, 193, 160, 242, 173, 68, 88, 8, 70, 40, 247, 221, 114,
+ 200, 236, 30, 115, 113, 74, 148, 118, 147, 90, 16, 179, 235, 60, 133,
+ 66, 143, 166, 183, 93, 152, 45, 240, 42, 103, 135, 130, 212, 59, 16,
+ 76, 2, 38, 228, 35, 94, 157, 66, 202, 99, 29, 20, 135, 225, 167,
+ 208, 96, 230, 13, 221, 225, 245, 55, 245, 154, 40, 41, 124, 41, 132,
+ 51, 107, 74, 161, 139, 91, 122, 135, 135, 167, 208, 11, 221, 225, 27,
+ 217, 151, 38, 21, 157, 169, 124, 35, 240, 61, 204, 135, 151, 125, 250,
+ 245, 140, 148, 199, 196, 174, 44, 245, 145, 233, 39, 77, 45, 4, 118,
+ 212, 152, 14, 173, 77, 117, 175, 158, 66, 45, 172, 238, 73, 28, 111,
+ 222, 146, 148, 190, 156, 79, 169, 240, 163, 253, 118, 111, 206, 117, 152,
+ 225, 141, 251, 182, 181, 49, 63, 21, 237, 121, 196, 105, 135, 128, 236,
+ 242, 136, 201, 177, 60, 46, 82, 215, 17, 216, 64, 145, 204, 58, 154,
+ 114, 33, 226, 245, 209, 27, 137, 99, 47, 1, 43, 105, 99, 73, 156,
+ 128, 10, 115, 101, 143, 147, 14, 2, 214, 220, 29, 222, 203, 241, 241,
+ 76, 114, 230, 199, 61, 74, 139, 214, 150, 10, 58, 253, 56, 176, 254,
+ 127, 29, 143, 106, 206, 224, 104, 216, 139, 198, 242, 165, 187, 137, 126,
+ 69, 100, 195, 50, 135, 121, 255, 132, 215, 59, 9, 69, 187, 175, 181,
+ 219, 175, 106, 237, 119, 3, 163, 234, 2, 223, 174, 248, 184, 139, 236,
+ 213, 230, 20, 175, 91, 68, 227, 85, 233, 191, 152, 149, 99, 95, 247,
+ 201, 173, 97, 148, 56, 29, 172, 222, 137, 203, 176, 245, 242, 165, 162,
+ 68, 10, 122, 239, 228, 226, 18, 102, 105, 93, 37, 73, 183, 78, 217,
+ 241, 46, 58, 108, 52, 110, 17, 93, 159, 195, 30, 95, 213, 193, 83,
+ 253, 38, 83, 67, 253, 214, 165, 75, 213, 234, 138, 101, 43, 75, 225,
+ 178, 161, 135, 94, 181, 85, 201, 107, 36, 18, 99, 245, 25, 99, 253,
+ 8, 175, 175, 232, 44, 239, 29, 237, 62, 249, 80, 95, 50, 44, 34,
+ 231, 198, 37, 200, 178, 168, 216, 236, 68, 87, 22, 92, 184, 78, 33,
+ 32, 24, 216, 186, 39, 226, 218, 95, 189, 148, 154, 250, 68, 195, 74,
+ 43, 219, 117, 181, 216, 233, 27, 90, 236, 144, 150, 132, 172, 83, 57,
+ 43, 233, 120, 2, 182, 7, 14, 34, 18, 100, 77, 226, 47, 53, 182,
+ 49, 53, 53, 89, 187, 51, 111, 144, 143, 191, 23, 80, 110, 29, 23,
+ 86, 87, 38, 91, 46, 139, 230, 69, 65, 182, 125, 10, 61, 155, 218,
+ 209, 224, 222, 61, 80, 114, 51, 234, 64, 135, 117, 211, 1, 159, 187,
+ 194, 229, 217, 198, 99, 251, 245, 41, 18, 53, 119, 35, 135, 9, 112,
+ 251, 176, 220, 74, 211, 199, 54, 236, 96, 189, 207, 18, 59, 230, 235,
+ 11, 163, 30, 180, 99, 107, 121, 140, 41, 176, 234, 179, 235, 163, 230,
+ 64, 99, 85, 56, 202, 195, 80, 118, 221, 109, 177, 222, 85, 12, 191,
+ 102, 45, 201, 172, 100, 137, 137, 31, 214, 40, 166, 6, 30, 147, 126,
+ 124, 32, 88, 33, 105, 225, 70, 128, 76, 210, 245, 116, 185, 250, 20,
+ 82, 59, 72, 190, 97, 222, 47, 137, 204, 215, 40, 9, 37, 4, 251,
+ 138, 74, 136, 44, 49, 109, 55, 249, 127, 132, 120, 121, 37, 135, 95,
+ 152, 45, 173, 203, 154, 35, 138, 4, 147, 71, 208, 81, 69, 43, 34,
+ 232, 120, 199, 89, 48, 44, 11, 215, 31, 125, 146, 42, 55, 35, 15,
+ 191, 119, 52, 127, 49, 170, 202, 37, 88, 98, 250, 85, 168, 98, 96,
+ 63, 82, 145, 156, 229, 148, 246, 34, 153, 197, 248, 26, 237, 46, 46,
+ 218, 100, 75, 245, 193, 99, 241, 61, 245, 185, 242, 165, 53, 124, 179,
+ 238, 73, 118, 183, 131, 83, 104, 169, 52, 205, 157, 178, 62, 82, 42,
+ 82, 144, 167, 48, 191, 242, 96, 195, 34, 236, 13, 31, 37, 6, 99,
+ 110, 196, 212, 131, 104, 216, 64, 119, 244, 251, 243, 142, 95, 158, 234,
+ 160, 125, 127, 250, 4, 187, 217, 255, 63, 252, 28, 227, 251, 246, 180,
+ 127, 255, 28, 3, 255, 180, 9, 138, 128, 32, 68, 164, 95, 159, 83,
+ 192, 159, 99, 32, 35, 32, 162, 64, 168, 104, 103, 31, 95, 128, 135,
+ 24, 136, 72, 248, 191, 60, 56, 64, 65, 64, 65, 65, 67, 66, 68,
+ 194, 128, 157, 35, 64, 34, 132, 232, 184, 47, 240, 32, 75, 93, 81,
+ 49, 36, 186, 101, 224, 72, 127, 25, 197, 193, 95, 250, 54, 170, 95,
+ 116, 81, 159, 145, 211, 185, 194, 87, 13, 81, 179, 155, 188, 170, 47,
+ 235, 191, 4, 196, 188, 46, 110, 100, 32, 128, 137, 69, 132, 41, 61,
+ 35, 152, 0, 145, 142, 91, 138, 16, 201, 239, 239, 159, 11, 152, 159,
+ 56, 116, 178, 68, 55, 69, 22, 150, 233, 138, 239, 120, 62, 142, 234,
+ 77, 136, 191, 200, 50, 83, 25, 145, 242, 233, 176, 35, 251, 92, 254,
+ 147, 204, 38, 72, 237, 105, 224, 166, 160, 147, 85, 158, 9, 138, 62,
+ 126, 186, 127, 82, 243, 225, 72, 238, 130, 30, 74, 22, 95, 114, 28,
+ 234, 52, 33, 238, 5, 213, 192, 237, 252, 167, 165, 174, 250, 121, 86,
+ 5, 15, 173, 245, 155, 219, 103, 194, 118, 79, 76, 131, 228, 133, 140,
+ 125, 145, 155, 30, 61, 176, 191, 92, 184, 47, 70, 94, 238, 230, 138,
+ 77, 94, 39, 199, 202, 129, 48, 77, 235, 115, 121, 125, 137, 189, 198,
+ 245, 37, 137, 36, 68, 158, 240, 161, 199, 51, 203, 116, 208, 169, 16,
+ 113, 56, 46, 132, 15, 141, 81, 110, 75, 255, 75, 156, 202, 182, 57,
+ 241, 200, 188, 126, 6, 143, 14, 23, 131, 41, 94, 2, 55, 57, 107,
+ 102, 201, 16, 198, 39, 19, 204, 207, 12, 157, 206, 95, 247, 245, 156,
+ 81, 88, 50, 199, 231, 93, 30, 12, 155, 232, 47, 48, 204, 116, 188,
+ 83, 247, 168, 42, 17, 159, 242, 173, 155, 140, 229, 167, 107, 71, 110,
+ 149, 232, 210, 173, 26, 214, 216, 215, 34, 72, 122, 34, 248, 148, 85,
+ 52, 117, 35, 92, 184, 42, 11, 43, 186, 20, 133, 212, 15, 123, 252,
+ 248, 205, 235, 181, 22, 41, 67, 214, 253, 28, 135, 90, 226, 18, 121,
+ 50, 36, 210, 10, 205, 175, 135, 46, 218, 209, 221, 145, 254, 253, 193,
+ 19, 72, 18, 23, 242, 121, 142, 236, 86, 7, 223, 188, 55, 98, 193,
+ 143, 51, 81, 87, 11, 245, 82, 243, 106, 233, 157, 215, 96, 229, 110,
+ 66, 69, 18, 122, 206, 223, 194, 230, 140, 80, 31, 225, 240, 245, 126,
+ 148, 149, 36, 38, 3, 42, 233, 246, 101, 14, 221, 3, 199, 196, 71,
+ 101, 159, 27, 208, 52, 153, 233, 152, 184, 13, 214, 122, 14, 21, 238,
+ 126, 243, 165, 224, 199, 198, 93, 16, 204, 13, 73, 103, 149, 42, 42,
+ 140, 189, 169, 38, 158, 67, 209, 117, 88, 177, 36, 156, 118, 83, 65,
+ 102, 252, 83, 97, 93, 4, 205, 84, 111, 124, 166, 12, 65, 3, 134,
+ 218, 244, 147, 3, 23, 237, 198, 251, 15, 114, 202, 104, 239, 155, 233,
+ 43, 236, 15, 115, 10, 240, 135, 6, 25, 206, 52, 132, 39, 213, 126,
+ 182, 65, 115, 253, 200, 205, 195, 255, 194, 226, 128, 234, 14, 226, 246,
+ 122, 227, 138, 123, 64, 230, 77, 196, 207, 23, 4, 198, 155, 238, 185,
+ 208, 123, 48, 219, 11, 149, 137, 80, 161, 93, 149, 12, 23, 241, 49,
+ 63, 133, 72, 170, 77, 22, 40, 16, 6, 4, 201, 132, 227, 144, 51,
+ 177, 91, 130, 77, 169, 185, 87, 244, 28, 232, 98, 242, 93, 71, 226,
+ 55, 105, 244, 208, 12, 95, 238, 249, 189, 141, 198, 157, 46, 191, 73,
+ 67, 120, 191, 79, 224, 240, 234, 146, 101, 93, 222, 162, 31, 11, 94,
+ 255, 161, 151, 144, 85, 34, 170, 100, 60, 115, 40, 13, 141, 202, 18,
+ 251, 87, 23, 133, 142, 168, 224, 241, 198, 6, 175, 177, 57, 251, 86,
+ 9, 68, 125, 164, 83, 104, 98, 140, 162, 66, 239, 195, 39, 202, 80,
+ 170, 111, 87, 223, 100, 107, 249, 68, 208, 175, 4, 204, 177, 126, 76,
+ 185, 88, 166, 134, 48, 29, 114, 64, 144, 125, 63, 136, 253, 164, 184,
+ 60, 120, 119, 89, 255, 20, 162, 122, 132, 49, 66, 132, 108, 43, 176,
+ 121, 60, 105, 95, 130, 159, 250, 220, 105, 25, 205, 215, 96, 128, 66,
+ 178, 205, 108, 78, 72, 30, 214, 250, 120, 189, 88, 83, 208, 172, 127,
+ 44, 51, 227, 179, 186, 214, 215, 62, 146, 199, 216, 116, 221, 111, 91,
+ 56, 198, 90, 145, 155, 136, 114, 69, 212, 59, 148, 23, 151, 132, 217,
+ 157, 75, 102, 90, 254, 128, 63, 35, 13, 91, 64, 126, 83, 162, 92,
+ 49, 223, 126, 142, 120, 149, 128, 205, 251, 245, 231, 65, 113, 19, 18,
+ 100, 54, 166, 41, 250, 7, 45, 223, 116, 36, 205, 88, 222, 156, 183,
+ 181, 53, 216, 22, 214, 158, 197, 49, 137, 96, 189, 20, 24, 22, 65,
+ 245, 165, 23, 39, 128, 67, 99, 218, 101, 186, 101, 119, 73, 209, 177,
+ 192, 132, 2, 197, 168, 197, 87, 140, 209, 25, 42, 188, 66, 194, 150,
+ 26, 22, 65, 128, 253, 46, 255, 109, 149, 220, 112, 88, 83, 84, 169,
+ 239, 214, 241, 237, 253, 71, 244, 177, 131, 253, 53, 239, 109, 235, 134,
+ 114, 136, 80, 105, 136, 148, 86, 197, 243, 77, 159, 186, 33, 140, 188,
+ 192, 150, 108, 119, 231, 109, 228, 44, 231, 84, 207, 56, 237, 177, 253,
+ 4, 69, 167, 133, 211, 34, 80, 11, 57, 40, 79, 14, 226, 88, 223,
+ 144, 28, 21, 204, 215, 193, 57, 133, 198, 133, 133, 238, 157, 39, 67,
+ 194, 25, 141, 244, 149, 130, 117, 148, 52, 28, 254, 170, 153, 100, 25,
+ 180, 33, 99, 110, 68, 251, 181, 247, 164, 46, 214, 146, 151, 35, 125,
+ 217, 66, 154, 145, 162, 28, 244, 90, 99, 159, 114, 115, 233, 91, 169,
+ 127, 52, 208, 174, 26, 204, 144, 186, 79, 193, 126, 103, 35, 146, 38,
+ 76, 14, 59, 231, 125, 76, 58, 227, 244, 51, 47, 195, 61, 175, 207,
+ 77, 97, 65, 116, 148, 142, 72, 126, 61, 122, 34, 229, 105, 41, 220,
+ 163, 129, 12, 212, 228, 238, 110, 132, 9, 108, 223, 190, 6, 32, 83,
+ 211, 112, 86, 223, 177, 159, 194, 96, 29, 48, 101, 94, 93, 30, 191,
+ 126, 123, 34, 15, 19, 195, 23, 131, 71, 169, 101, 100, 12, 79, 38,
+ 206, 68, 239, 77, 227, 133, 98, 108, 108, 216, 32, 139, 200, 71, 252,
+ 192, 120, 108, 45, 198, 208, 131, 64, 145, 152, 144, 204, 203, 168, 191,
+ 35, 135, 99, 168, 215, 136, 91, 62, 28, 89, 126, 36, 166, 67, 231,
+ 32, 70, 219, 43, 109, 176, 237, 133, 172, 22, 42, 207, 8, 205, 199,
+ 130, 109, 115, 62, 2, 148, 224, 58, 15, 200, 216, 144, 223, 222, 243,
+ 157, 178, 227, 193, 182, 247, 36, 235, 124, 206, 245, 250, 144, 153, 195,
+ 245, 220, 88, 109, 76, 242, 247, 215, 98, 241, 55, 77, 40, 213, 189,
+ 196, 39, 5, 212, 100, 150, 175, 249, 106, 185, 109, 70, 222, 175, 175,
+ 241, 68, 84, 79, 121, 195, 246, 0, 197, 90, 191, 222, 37, 236, 137,
+ 205, 167, 222, 107, 23, 19, 72, 235, 203, 216, 11, 68, 186, 99, 70,
+ 179, 122, 117, 12, 131, 175, 100, 170, 220, 212, 26, 140, 220, 17, 220,
+ 177, 120, 148, 197, 81, 175, 180, 34, 144, 147, 212, 93, 45, 101, 156,
+ 115, 63, 186, 113, 53, 150, 146, 246, 91, 254, 137, 54, 7, 66, 202,
+ 151, 118, 181, 160, 1, 119, 75, 150, 167, 134, 117, 235, 45, 65, 227,
+ 217, 95, 51, 66, 38, 77, 130, 15, 188, 187, 144, 115, 26, 30, 138,
+ 50, 71, 4, 102, 245, 81, 208, 114, 51, 212, 225, 95, 16, 27, 43,
+ 10, 167, 37, 85, 95, 137, 24, 253, 152, 161, 47, 164, 116, 59, 120,
+ 178, 226, 147, 132, 89, 185, 20, 178, 237, 185, 28, 8, 27, 143, 230,
+ 115, 143, 150, 191, 177, 13, 2, 194, 196, 6, 25, 158, 237, 35, 53,
+ 41, 173, 185, 74, 245, 100, 164, 143, 41, 194, 88, 228, 5, 231, 35,
+ 121, 177, 83, 159, 72, 20, 79, 166, 44, 49, 38, 10, 61, 173, 104,
+ 233, 147, 104, 201, 174, 42, 230, 33, 93, 70, 251, 204, 232, 53, 70,
+ 193, 146, 28, 249, 73, 35, 145, 76, 0, 209, 44, 255, 250, 109, 182,
+ 135, 133, 180, 97, 17, 21, 158, 129, 190, 120, 58, 209, 105, 50, 179,
+ 134, 174, 115, 43, 97, 82, 35, 151, 46, 16, 189, 185, 222, 202, 188,
+ 252, 70, 19, 91, 117, 83, 13, 95, 242, 11, 218, 45, 203, 160, 235,
+ 250, 4, 133, 225, 151, 143, 19, 161, 139, 237, 152, 33, 209, 138, 50,
+ 253, 148, 74, 15, 154, 235, 39, 171, 136, 217, 85, 50, 140, 16, 239,
+ 75, 172, 247, 35, 27, 197, 12, 73, 225, 43, 248, 10, 68, 40, 85,
+ 146, 151, 171, 172, 182, 175, 8, 140, 251, 126, 153, 75, 65, 184, 93,
+ 23, 194, 118, 161, 76, 20, 243, 75, 221, 106, 136, 96, 54, 10, 146,
+ 237, 149, 251, 120, 41, 43, 214, 79, 145, 195, 111, 166, 122, 119, 239,
+ 65, 131, 55, 30, 152, 60, 54, 190, 74, 19, 90, 215, 74, 67, 32,
+ 140, 251, 244, 161, 40, 157, 107, 4, 82, 227, 97, 162, 114, 69, 110,
+ 124, 138, 164, 12, 242, 252, 219, 162, 195, 227, 182, 55, 78, 72, 100,
+ 179, 82, 151, 160, 117, 188, 115, 118, 213, 89, 92, 92, 228, 5, 88,
+ 77, 168, 70, 80, 254, 215, 103, 147, 89, 76, 5, 31, 30, 222, 49,
+ 144, 226, 113, 139, 22, 93, 205, 162, 84, 195, 16, 221, 229, 37, 212,
+ 208, 151, 218, 61, 40, 81, 88, 69, 175, 101, 168, 183, 86, 115, 91,
+ 62, 174, 122, 169, 174, 113, 81, 142, 175, 109, 228, 139, 122, 120, 218,
+ 238, 10, 70, 53, 129, 142, 166, 76, 187, 168, 251, 220, 194, 241, 124,
+ 159, 6, 67, 110, 104, 240, 80, 6, 148, 193, 32, 117, 123, 97, 97,
+ 43, 239, 89, 105, 119, 51, 142, 251, 39, 210, 197, 40, 81, 239, 218,
+ 154, 180, 216, 242, 172, 55, 106, 197, 132, 80, 161, 106, 228, 213, 8,
+ 69, 203, 136, 211, 94, 135, 231, 143, 73, 85, 59, 190, 132, 13, 211,
+ 227, 176, 49, 14, 234, 244, 103, 56, 40, 190, 84, 115, 242, 207, 176,
+ 108, 219, 225, 239, 214, 26, 92, 207, 100, 119, 204, 38, 126, 199, 99,
+ 37, 146, 7, 185, 112, 30, 84, 221, 153, 29, 28, 232, 208, 247, 247,
+ 39, 83, 88, 87, 93, 207, 61, 89, 240, 187, 179, 179, 169, 110, 184,
+ 40, 54, 124, 105, 194, 83, 163, 49, 170, 116, 81, 143, 109, 253, 158,
+ 111, 6, 189, 56, 151, 0, 154, 182, 216, 134, 83, 12, 165, 58, 3,
+ 212, 95, 54, 227, 233, 147, 144, 238, 35, 249, 217, 91, 150, 164, 96,
+ 238, 157, 31, 223, 73, 92, 137, 10, 229, 11, 211, 105, 27, 250, 9,
+ 239, 184, 137, 155, 184, 211, 6, 199, 137, 187, 199, 221, 46, 215, 176,
+ 137, 71, 16, 62, 10, 107, 84, 106, 223, 75, 108, 203, 35, 247, 78,
+ 196, 99, 28, 31, 217, 242, 139, 186, 128, 150, 110, 151, 87, 90, 109,
+ 54, 129, 106, 193, 194, 88, 115, 189, 118, 225, 6, 231, 180, 43, 142,
+ 110, 21, 2, 141, 221, 144, 179, 82, 151, 188, 121, 248, 77, 143, 215,
+ 143, 10, 182, 188, 186, 208, 82, 215, 60, 18, 196, 185, 159, 68, 68,
+ 201, 207, 74, 82, 145, 59, 149, 16, 63, 201, 13, 17, 244, 71, 194,
+ 197, 191, 95, 40, 252, 225, 179, 165, 137, 169, 161, 135, 36, 151, 106,
+ 171, 138, 236, 185, 45, 131, 92, 220, 225, 18, 78, 251, 98, 102, 21,
+ 22, 194, 152, 194, 48, 164, 210, 60, 201, 23, 120, 207, 71, 209, 236,
+ 222, 86, 217, 166, 220, 146, 211, 247, 80, 246, 155, 73, 111, 145, 122,
+ 227, 119, 103, 180, 85, 100, 168, 211, 204, 80, 168, 72, 152, 79, 110,
+ 250, 162, 254, 120, 200, 77, 60, 156, 218, 132, 20, 86, 169, 200, 171,
+ 69, 33, 104, 117, 121, 41, 217, 97, 225, 125, 66, 58, 39, 159, 93,
+ 234, 184, 240, 229, 16, 82, 49, 68, 209, 135, 209, 158, 15, 6, 211,
+ 218, 202, 14, 28, 39, 226, 234, 26, 209, 114, 217, 193, 154, 233, 199,
+ 150, 162, 250, 193, 114, 201, 37, 84, 186, 74, 90, 56, 3, 126, 34,
+ 215, 195, 73, 87, 30, 186, 10, 38, 212, 181, 39, 132, 189, 109, 75,
+ 73, 123, 136, 186, 242, 118, 38, 128, 222, 79, 220, 70, 161, 246, 34,
+ 54, 170, 241, 2, 205, 224, 218, 64, 251, 90, 3, 207, 83, 162, 143,
+ 75, 131, 108, 172, 193, 152, 114, 120, 37, 14, 205, 232, 54, 40, 131,
+ 88, 118, 164, 177, 200, 248, 184, 77, 56, 55, 24, 102, 120, 46, 240,
+ 204, 139, 202, 29, 226, 230, 240, 71, 166, 39, 8, 64, 238, 173, 171,
+ 122, 210, 134, 8, 250, 50, 141, 14, 21, 9, 203, 131, 132, 150, 29,
+ 22, 129, 148, 226, 141, 43, 61, 214, 237, 14, 33, 152, 180, 21, 99,
+ 98, 99, 171, 222, 38, 80, 222, 39, 169, 2, 47, 141, 17, 23, 53,
+ 83, 18, 90, 10, 84, 180, 53, 180, 241, 12, 186, 39, 92, 80, 8,
+ 81, 163, 95, 210, 77, 179, 183, 248, 58, 236, 193, 91, 8, 131, 25,
+ 167, 80, 36, 217, 0, 177, 49, 195, 90, 161, 47, 90, 237, 213, 72,
+ 36, 91, 15, 165, 14, 10, 63, 49, 109, 204, 113, 179, 217, 135, 88,
+ 197, 151, 48, 167, 165, 151, 123, 212, 194, 25, 234, 110, 78, 100, 25,
+ 249, 13, 187, 65, 98, 239, 73, 250, 30, 42, 20, 250, 73, 188, 243,
+ 18, 95, 211, 146, 62, 215, 84, 84, 160, 190, 72, 17, 245, 110, 159,
+ 195, 23, 179, 94, 146, 26, 41, 215, 45, 210, 75, 155, 104, 208, 172,
+ 117, 84, 68, 155, 231, 168, 8, 34, 104, 17, 171, 17, 230, 179, 206,
+ 33, 31, 154, 141, 46, 24, 15, 212, 250, 50, 72, 45, 125, 195, 230,
+ 5, 84, 37, 63, 78, 45, 104, 178, 162, 57, 72, 130, 103, 140, 242,
+ 208, 196, 235, 19, 46, 235, 137, 141, 218, 228, 173, 74, 223, 248, 168,
+ 221, 12, 88, 231, 197, 113, 187, 186, 236, 189, 225, 199, 91, 17, 109,
+ 154, 234, 163, 146, 43, 249, 156, 119, 30, 171, 213, 210, 145, 176, 199,
+ 191, 52, 111, 16, 122, 18, 117, 10, 185, 106, 251, 15, 167, 208, 51,
+ 250, 93, 192, 86, 190, 254, 205, 252, 60, 211, 197, 138, 19, 166, 69,
+ 66, 217, 39, 24, 250, 95, 50, 145, 63, 45, 25, 99, 72, 80, 16,
+ 149, 73, 110, 209, 111, 175, 136, 68, 225, 88, 32, 177, 53, 51, 202,
+ 14, 96, 108, 14, 210, 156, 246, 137, 249, 177, 97, 107, 157, 92, 29,
+ 85, 97, 52, 121, 237, 57, 37, 70, 142, 53, 122, 43, 125, 142, 163,
+ 201, 175, 236, 214, 64, 53, 177, 233, 182, 69, 246, 202, 45, 147, 102,
+ 226, 219, 174, 46, 161, 15, 168, 241, 212, 139, 14, 163, 145, 184, 53,
+ 155, 234, 253, 42, 88, 9, 202, 166, 52, 123, 204, 42, 243, 14, 253,
+ 235, 91, 29, 146, 51, 134, 115, 142, 133, 159, 174, 221, 187, 62, 110,
+ 68, 190, 229, 243, 134, 243, 232, 197, 222, 5, 134, 18, 18, 250, 37,
+ 81, 190, 210, 131, 97, 119, 145, 59, 195, 196, 7, 146, 228, 120, 66,
+ 199, 178, 7, 143, 245, 38, 142, 92, 4, 228, 195, 184, 143, 197, 166,
+ 166, 114, 212, 246, 146, 34, 194, 199, 218, 136, 197, 202, 142, 194, 42,
+ 103, 37, 76, 75, 37, 174, 95, 205, 155, 247, 71, 101, 240, 147, 208,
+ 187, 222, 92, 99, 229, 83, 253, 146, 138, 212, 158, 64, 148, 63, 204,
+ 212, 245, 73, 196, 51, 158, 26, 17, 212, 57, 90, 199, 164, 210, 202,
+ 113, 242, 169, 183, 88, 70, 162, 24, 155, 199, 85, 242, 34, 134, 73,
+ 235, 8, 47, 29, 177, 101, 31, 149, 107, 116, 176, 213, 198, 142, 229,
+ 148, 84, 99, 14, 17, 107, 248, 170, 171, 122, 83, 10, 42, 172, 154,
+ 149, 174, 53, 100, 5, 84, 208, 26, 237, 122, 57, 71, 152, 214, 151,
+ 51, 73, 111, 93, 117, 239, 214, 220, 181, 186, 147, 134, 108, 88, 71,
+ 76, 107, 66, 179, 115, 59, 101, 35, 24, 59, 193, 36, 50, 52, 94,
+ 22, 105, 101, 128, 128, 162, 144, 81, 46, 54, 226, 208, 89, 159, 7,
+ 17, 143, 215, 203, 80, 242, 171, 185, 146, 76, 59, 6, 118, 181, 175,
+ 187, 191, 40, 47, 146, 33, 150, 147, 3, 87, 106, 56, 50, 193, 252,
+ 158, 101, 150, 60, 2, 26, 191, 254, 145, 233, 5, 201, 175, 252, 185,
+ 58, 10, 21, 20, 24, 95, 102, 211, 7, 83, 218, 98, 175, 96, 16,
+ 87, 88, 80, 211, 134, 77, 248, 220, 147, 148, 231, 80, 203, 162, 83,
+ 229, 228, 189, 26, 152, 84, 177, 244, 180, 184, 125, 190, 36, 220, 100,
+ 142, 208, 179, 4, 115, 96, 140, 13, 57, 8, 165, 137, 72, 180, 113,
+ 224, 246, 64, 149, 193, 10, 30, 105, 188, 49, 50, 219, 126, 80, 4,
+ 127, 64, 152, 254, 167, 22, 207, 189, 168, 109, 241, 194, 180, 108, 83,
+ 132, 161, 117, 71, 60, 22, 63, 4, 191, 237, 205, 126, 244, 206, 243,
+ 115, 56, 16, 122, 235, 230, 248, 35, 174, 30, 82, 10, 170, 172, 229,
+ 155, 185, 37, 72, 132, 174, 97, 40, 177, 45, 188, 168, 87, 228, 167,
+ 201, 208, 236, 113, 5, 155, 179, 216, 159, 135, 102, 249, 214, 200, 182,
+ 183, 124, 51, 147, 42, 107, 194, 68, 98, 101, 110, 118, 160, 13, 107,
+ 193, 117, 110, 233, 28, 195, 156, 84, 91, 157, 176, 251, 202, 234, 88,
+ 49, 97, 140, 247, 165, 208, 214, 6, 201, 231, 50, 3, 7, 155, 33,
+ 93, 197, 85, 23, 147, 236, 76, 217, 91, 133, 119, 44, 24, 141, 137,
+ 99, 96, 13, 242, 235, 185, 160, 214, 202, 10, 23, 226, 135, 183, 139,
+ 155, 102, 231, 250, 55, 134, 213, 244, 77, 116, 53, 99, 253, 153, 7,
+ 100, 163, 62, 248, 5, 186, 180, 183, 30, 221, 98, 66, 195, 31, 175,
+ 183, 171, 201, 98, 40, 246, 23, 180, 46, 184, 175, 92, 45, 173, 169,
+ 112, 206, 180, 87, 52, 231, 250, 83, 90, 39, 122, 239, 221, 108, 45,
+ 20, 61, 61, 163, 103, 252, 155, 17, 60, 51, 29, 43, 61, 248, 53,
+ 129, 109, 106, 116, 117, 15, 13, 118, 144, 79, 176, 114, 86, 95, 53,
+ 188, 44, 207, 12, 184, 78, 53, 132, 59, 34, 248, 117, 137, 170, 255,
+ 243, 123, 181, 16, 110, 20, 247, 130, 29, 38, 216, 157, 103, 230, 61,
+ 154, 147, 139, 36, 242, 197, 136, 10, 15, 219, 37, 79, 161, 195, 243,
+ 170, 152, 217, 172, 111, 26, 2, 162, 140, 94, 20, 191, 67, 53, 10,
+ 159, 212, 102, 31, 186, 189, 31, 133, 63, 82, 212, 66, 212, 159, 104,
+ 33, 109, 19, 158, 214, 87, 100, 99, 217, 48, 187, 248, 116, 192, 65,
+ 196, 184, 35, 143, 170, 199, 44, 47, 122, 139, 181, 24, 215, 196, 240,
+ 157, 12, 149, 85, 232, 10, 58, 199, 173, 46, 59, 196, 52, 243, 130,
+ 152, 106, 229, 121, 113, 137, 125, 203, 230, 161, 55, 181, 209, 24, 151,
+ 80, 234, 136, 162, 35, 148, 198, 8, 39, 93, 30, 220, 65, 37, 214,
+ 252, 38, 141, 168, 16, 78, 154, 204, 207, 121, 10, 153, 134, 61, 245,
+ 83, 251, 74, 139, 90, 55, 171, 249, 241, 20, 42, 61, 62, 120, 53,
+ 148, 229, 70, 28, 41, 141, 92, 108, 17, 245, 110, 20, 101, 60, 238,
+ 169, 11, 71, 198, 251, 108, 221, 248, 135, 77, 78, 78, 56, 233, 36,
+ 205, 46, 14, 38, 38, 248, 229, 244, 136, 76, 234, 18, 247, 205, 197,
+ 118, 197, 170, 40, 174, 242, 95, 189, 239, 143, 59, 106, 95, 205, 184,
+ 56, 223, 227, 115, 218, 207, 23, 11, 213, 146, 103, 88, 78, 180, 87,
+ 190, 80, 63, 209, 241, 32, 98, 28, 50, 243, 48, 12, 116, 129, 50,
+ 244, 26, 10, 66, 141, 118, 87, 13, 123, 110, 112, 72, 114, 45, 158,
+ 191, 69, 168, 137, 177, 143, 54, 25, 102, 56, 122, 45, 182, 74, 126,
+ 159, 103, 156, 203, 51, 104, 82, 24, 173, 54, 61, 3, 77, 68, 161,
+ 121, 75, 184, 251, 228, 213, 186, 184, 247, 220, 44, 37, 66, 196, 241,
+ 216, 182, 243, 144, 8, 94, 95, 29, 149, 3, 77, 9, 149, 7, 69,
+ 190, 14, 103, 81, 63, 118, 105, 52, 2, 181, 248, 244, 228, 64, 249,
+ 195, 33, 211, 10, 25, 151, 134, 0, 136, 228, 128, 108, 11, 199, 124,
+ 38, 27, 247, 252, 37, 202, 198, 21, 217, 91, 228, 50, 137, 147, 171,
+ 234, 90, 193, 17, 163, 107, 253, 219, 23, 191, 13, 81, 16, 20, 163,
+ 206, 102, 239, 122, 239, 86, 86, 59, 247, 190, 154, 243, 39, 38, 108,
+ 82, 154, 11, 166, 38, 55, 96, 41, 173, 14, 44, 244, 33, 187, 77,
+ 114, 141, 80, 233, 176, 40, 99, 235, 205, 147, 53, 218, 230, 249, 219,
+ 28, 212, 23, 189, 187, 204, 119, 231, 179, 139, 242, 159, 248, 35, 145,
+ 137, 146, 215, 250, 28, 218, 229, 21, 54, 239, 105, 151, 60, 236, 52,
+ 148, 108, 51, 173, 64, 69, 216, 98, 42, 185, 36, 90, 41, 115, 113,
+ 162, 120, 91, 184, 107, 173, 88, 199, 91, 52, 13, 50, 108, 250, 70,
+ 182, 210, 162, 52, 36, 153, 43, 205, 27, 27, 169, 81, 223, 189, 95,
+ 34, 205, 168, 68, 91, 212, 157, 37, 232, 47, 234, 204, 35, 239, 173,
+ 143, 241, 241, 80, 54, 96, 133, 56, 56, 193, 136, 246, 74, 249, 64,
+ 183, 226, 165, 237, 149, 43, 153, 172, 17, 215, 159, 27, 187, 183, 200,
+ 248, 170, 191, 208, 52, 143, 97, 73, 15, 84, 17, 187, 147, 214, 131,
+ 80, 204, 36, 130, 42, 135, 115, 1, 3, 169, 227, 213, 24, 75, 1,
+ 75, 204, 133, 226, 39, 1, 85, 145, 232, 65, 122, 246, 152, 142, 174,
+ 104, 36, 43, 55, 153, 248, 67, 87, 133, 81, 89, 105, 99, 25, 164,
+ 158, 199, 173, 240, 83, 214, 214, 188, 62, 215, 22, 114, 129, 86, 62,
+ 156, 118, 73, 149, 5, 18, 136, 62, 255, 204, 150, 190, 81, 131, 227,
+ 154, 63, 189, 47, 210, 26, 57, 102, 129, 171, 28, 45, 255, 189, 2,
+ 200, 221, 130, 112, 182, 12, 191, 153, 220, 254, 86, 133, 95, 147, 221,
+ 66, 255, 100, 61, 166, 223, 183, 115, 200, 47, 195, 34, 166, 250, 88,
+ 77, 36, 185, 140, 89, 136, 83, 195, 185, 188, 162, 62, 245, 112, 186,
+ 217, 15, 169, 32, 162, 27, 206, 71, 227, 93, 54, 188, 191, 226, 44,
+ 28, 118, 145, 180, 152, 192, 36, 155, 229, 147, 123, 183, 242, 94, 141,
+ 176, 17, 57, 153, 97, 111, 112, 235, 99, 60, 95, 156, 206, 220, 60,
+ 170, 26, 189, 62, 253, 118, 105, 91, 228, 237, 130, 25, 45, 177, 137,
+ 170, 139, 156, 250, 153, 100, 108, 183, 52, 53, 77, 155, 174, 11, 60,
+ 153, 91, 72, 219, 38, 113, 187, 90, 74, 171, 47, 183, 159, 18, 26,
+ 53, 70, 102, 125, 109, 59, 155, 63, 249, 219, 57, 55, 232, 41, 99,
+ 182, 244, 151, 75, 83, 82, 171, 186, 111, 167, 107, 211, 40, 74, 89,
+ 167, 216, 203, 184, 175, 182, 108, 238, 34, 37, 148, 127, 155, 54, 74,
+ 52, 15, 177, 178, 193, 206, 53, 216, 231, 200, 52, 201, 202, 118, 64,
+ 21, 74, 184, 127, 84, 149, 203, 16, 104, 236, 159, 206, 199, 27, 195,
+ 205, 32, 73, 226, 53, 137, 46, 210, 31, 160, 235, 95, 106, 42, 65,
+ 119, 163, 217, 169, 189, 173, 92, 218, 99, 91, 173, 242, 121, 126, 107,
+ 90, 60, 183, 142, 194, 183, 141, 182, 112, 49, 205, 138, 30, 166, 201,
+ 193, 134, 221, 207, 89, 243, 247, 31, 84, 239, 179, 137, 71, 122, 102,
+ 237, 89, 148, 85, 205, 80, 63, 115, 160, 83, 183, 102, 160, 74, 30,
+ 15, 18, 23, 214, 169, 53, 113, 195, 252, 188, 51, 26, 142, 21, 184,
+ 159, 127, 183, 165, 113, 139, 237, 235, 210, 163, 80, 181, 176, 193, 2,
+ 87, 229, 48, 199, 145, 185, 133, 172, 250, 163, 247, 47, 148, 239, 60,
+ 98, 180, 226, 72, 229, 25, 80, 48, 125, 169, 95, 119, 216, 245, 201,
+ 6, 99, 120, 174, 208, 33, 23, 71, 61, 163, 136, 21, 194, 151, 189,
+ 149, 89, 227, 61, 201, 245, 52, 215, 63, 155, 133, 225, 85, 219, 43,
+ 253, 76, 21, 250, 57, 155, 34, 61, 167, 161, 55, 143, 90, 108, 21,
+ 80, 236, 173, 162, 133, 40, 62, 228, 47, 52, 82, 169, 210, 233, 220,
+ 185, 200, 87, 46, 60, 162, 51, 199, 230, 22, 208, 25, 90, 113, 224,
+ 220, 197, 46, 230, 139, 162, 38, 39, 56, 223, 167, 41, 27, 23, 200,
+ 207, 234, 89, 34, 146, 243, 94, 198, 229, 227, 151, 231, 143, 33, 116,
+ 188, 67, 47, 60, 225, 82, 129, 97, 101, 219, 214, 91, 143, 10, 217,
+ 234, 108, 25, 195, 181, 134, 166, 108, 109, 174, 221, 60, 234, 144, 27,
+ 187, 114, 17, 185, 77, 72, 244, 107, 238, 139, 36, 234, 134, 105, 210,
+ 59, 106, 237, 16, 251, 59, 102, 167, 128, 75, 66, 59, 230, 110, 163,
+ 99, 140, 23, 58, 82, 170, 231, 140, 18, 38, 54, 30, 149, 177, 182,
+ 79, 76, 77, 170, 181, 29, 93, 19, 109, 109, 97, 186, 40, 192, 247,
+ 34, 176, 163, 195, 176, 44, 248, 116, 192, 246, 107, 159, 129, 131, 44,
+ 97, 131, 4, 123, 253, 248, 158, 103, 9, 71, 115, 68, 226, 230, 103,
+ 238, 144, 54, 122, 191, 221, 165, 201, 186, 194, 15, 250, 248, 119, 227,
+ 229, 70, 139, 68, 59, 76, 239, 36, 9, 29, 152, 32, 96, 113, 249,
+ 163, 206, 132, 33, 222, 29, 208, 72, 20, 145, 67, 86, 200, 73, 250,
+ 102, 213, 172, 74, 182, 175, 28, 191, 165, 124, 82, 105, 213, 227, 163,
+ 185, 199, 98, 130, 16, 233, 157, 124, 235, 189, 206, 157, 123, 197, 209,
+ 237, 197, 101, 197, 165, 206, 251, 205, 85, 222, 56, 87, 174, 206, 151,
+ 224, 162, 93, 119, 205, 185, 130, 142, 242, 238, 17, 218, 77, 234, 124,
+ 71, 115, 146, 25, 90, 220, 40, 28, 137, 27, 21, 230, 147, 1, 125,
+ 183, 162, 27, 219, 165, 104, 195, 89, 204, 172, 189, 170, 154, 243, 158,
+ 37, 172, 117, 60, 150, 192, 113, 189, 137, 112, 251, 221, 221, 107, 135,
+ 99, 195, 153, 3, 60, 113, 242, 150, 101, 173, 33, 66, 2, 155, 122,
+ 165, 49, 183, 33, 110, 67, 134, 72, 221, 112, 130, 85, 117, 242, 113,
+ 133, 190, 169, 177, 102, 119, 3, 99, 86, 63, 22, 73, 205, 35, 133,
+ 228, 67, 190, 62, 193, 59, 31, 110, 118, 197, 248, 162, 179, 150, 63,
+ 120, 149, 60, 230, 67, 192, 59, 61, 103, 168, 152, 129, 5, 105, 187,
+ 19, 212, 210, 81, 111, 184, 198, 172, 105, 176, 93, 161, 140, 207, 81,
+ 154, 88, 17, 118, 223, 223, 158, 231, 175, 9, 182, 154, 124, 157, 88,
+ 112, 95, 110, 211, 68, 56, 227, 50, 111, 10, 74, 218, 94, 43, 250,
+ 11, 49, 75, 209, 49, 58, 21, 218, 47, 244, 246, 120, 143, 146, 5,
+ 166, 6, 17, 51, 232, 109, 252, 230, 185, 43, 94, 164, 217, 217, 134,
+ 88, 168, 11, 81, 171, 32, 76, 55, 200, 248, 135, 74, 224, 199, 179,
+ 169, 26, 7, 26, 71, 45, 246, 124, 154, 109, 205, 21, 226, 178, 92,
+ 212, 151, 18, 121, 147, 175, 195, 122, 201, 245, 118, 36, 173, 16, 141,
+ 244, 92, 134, 62, 210, 219, 8, 106, 125, 65, 163, 153, 185, 201, 148,
+ 10, 111, 131, 2, 204, 150, 200, 8, 68, 225, 0, 203, 143, 49, 180,
+ 19, 88, 84, 15, 60, 34, 250, 21, 67, 139, 98, 136, 66, 235, 190,
+ 220, 221, 90, 77, 108, 66, 35, 56, 140, 22, 12, 56, 33, 233, 149,
+ 89, 143, 127, 216, 250, 249, 74, 228, 242, 71, 52, 91, 61, 230, 103,
+ 195, 150, 121, 82, 57, 20, 222, 3, 244, 108, 46, 119, 230, 42, 11,
+ 173, 253, 4, 55, 51, 35, 6, 142, 205, 210, 175, 84, 13, 200, 23,
+ 54, 187, 20, 226, 87, 127, 54, 162, 28, 12, 74, 191, 122, 151, 177,
+ 16, 73, 221, 140, 80, 149, 87, 154, 141, 234, 221, 53, 49, 109, 219,
+ 216, 151, 142, 4, 40, 2, 134, 181, 183, 223, 55, 23, 215, 229, 166,
+ 249, 250, 143, 82, 216, 143, 20, 80, 82, 209, 119, 101, 100, 45, 32,
+ 161, 234, 119, 217, 11, 17, 94, 144, 156, 215, 165, 24, 78, 233, 173,
+ 21, 125, 140, 218, 166, 231, 225, 59, 17, 48, 111, 220, 19, 206, 33,
+ 89, 128, 104, 68, 23, 49, 218, 130, 115, 187, 116, 253, 86, 8, 62,
+ 153, 239, 133, 226, 18, 223, 119, 234, 118, 234, 218, 132, 110, 193, 77,
+ 15, 162, 232, 133, 115, 146, 2, 60, 122, 147, 159, 73, 217, 126, 68,
+ 186, 168, 130, 96, 37, 165, 210, 116, 229, 169, 168, 196, 61, 249, 124,
+ 43, 86, 149, 28, 205, 167, 49, 54, 250, 238, 144, 242, 71, 159, 56,
+ 217, 117, 142, 55, 237, 239, 31, 27, 167, 102, 124, 107, 77, 110, 138,
+ 169, 230, 124, 234, 194, 91, 167, 86, 148, 186, 196, 48, 82, 12, 205,
+ 207, 107, 174, 180, 92, 99, 159, 98, 87, 215, 222, 205, 126, 194, 255,
+ 16, 181, 40, 157, 193, 222, 195, 218, 142, 131, 204, 114, 111, 143, 78,
+ 147, 241, 179, 4, 250, 137, 56, 115, 60, 49, 153, 134, 35, 206, 51,
+ 146, 65, 59, 206, 167, 225, 239, 217, 174, 222, 143, 9, 191, 113, 23,
+ 85, 246, 196, 86, 56, 223, 222, 246, 20, 138, 222, 83, 233, 97, 201,
+ 209, 186, 138, 47, 143, 235, 67, 88, 188, 178, 203, 225, 155, 109, 41,
+ 92, 108, 18, 219, 170, 119, 91, 255, 99, 104, 251, 129, 150, 78, 111,
+ 166, 225, 198, 189, 182, 155, 219, 91, 116, 29, 174, 183, 187, 2, 28,
+ 119, 238, 149, 8, 115, 34, 238, 92, 81, 188, 132, 18, 69, 26, 22,
+ 239, 112, 215, 142, 255, 205, 187, 133, 212, 146, 121, 157, 139, 182, 42,
+ 29, 5, 26, 104, 17, 225, 194, 23, 130, 217, 203, 43, 73, 88, 9,
+ 137, 125, 48, 218, 8, 168, 238, 226, 36, 126, 102, 55, 82, 83, 235,
+ 204, 224, 120, 230, 207, 51, 179, 195, 255, 80, 234, 155, 181, 115, 169,
+ 214, 59, 197, 120, 193, 59, 72, 247, 179, 75, 221, 189, 119, 19, 57,
+ 72, 90, 11, 156, 10, 219, 143, 76, 100, 198, 179, 153, 247, 238, 87,
+ 157, 11, 123, 162, 110, 163, 99, 149, 28, 60, 242, 230, 9, 42, 151,
+ 209, 64, 216, 73, 76, 213, 210, 211, 167, 69, 41, 37, 116, 87, 202,
+ 104, 66, 22, 13, 165, 218, 122, 78, 161, 178, 197, 219, 54, 25, 88,
+ 53, 93, 209, 218, 51, 104, 146, 164, 23, 191, 242, 202, 94, 46, 207,
+ 117, 150, 54, 18, 83, 46, 195, 70, 232, 234, 19, 138, 242, 180, 22,
+ 255, 212, 162, 234, 115, 58, 216, 231, 217, 129, 108, 208, 79, 72, 219,
+ 10, 133, 63, 237, 127, 242, 154, 217, 242, 74, 8, 173, 181, 168, 190,
+ 5, 57, 212, 122, 1, 189, 169, 137, 8, 69, 57, 221, 135, 163, 36,
+ 152, 184, 103, 232, 226, 164, 167, 212, 193, 102, 211, 146, 40, 205, 142,
+ 180, 208, 122, 162, 161, 166, 49, 237, 218, 161, 247, 110, 177, 132, 178,
+ 187, 197, 5, 163, 147, 196, 158, 147, 172, 7, 235, 225, 84, 220, 12,
+ 212, 116, 111, 39, 92, 98, 70, 198, 100, 35, 194, 11, 171, 243, 187,
+ 27, 123, 158, 17, 167, 100, 76, 6, 5, 111, 138, 105, 51, 27, 238,
+ 60, 86, 181, 167, 13, 37, 65, 198, 231, 75, 44, 39, 168, 228, 114,
+ 23, 248, 12, 107, 37, 138, 187, 90, 15, 155, 182, 162, 102, 240, 30,
+ 133, 153, 169, 239, 229, 190, 209, 149, 97, 37, 109, 251, 54, 198, 127,
+ 188, 102, 125, 18, 95, 217, 83, 50, 98, 118, 190, 141, 222, 214, 81,
+ 216, 123, 189, 8, 169, 219, 166, 19, 87, 231, 186, 151, 248, 242, 80,
+ 242, 50, 191, 63, 227, 107, 250, 89, 241, 23, 40, 94, 99, 203, 148,
+ 118, 54, 28, 195, 115, 188, 242, 81, 1, 138, 129, 162, 237, 83, 130,
+ 229, 175, 149, 85, 218, 251, 58, 87, 100, 70, 9, 240, 189, 218, 82,
+ 24, 200, 199, 52, 41, 144, 102, 163, 5, 2, 142, 186, 39, 251, 47,
+ 170, 90, 63, 70, 224, 159, 144, 163, 49, 186, 231, 162, 69, 25, 50,
+ 37, 52, 42, 121, 185, 196, 111, 185, 111, 104, 15, 177, 40, 134, 249,
+ 18, 20, 177, 89, 180, 148, 113, 165, 66, 147, 1, 226, 153, 43, 148,
+ 40, 239, 200, 226, 9, 29, 41, 224, 22, 109, 156, 144, 8, 78, 239,
+ 79, 249, 20, 120, 125, 56, 178, 160, 222, 241, 80, 148, 98, 50, 131,
+ 222, 239, 114, 71, 57, 181, 201, 161, 247, 122, 112, 47, 244, 34, 163,
+ 181, 121, 86, 54, 24, 105, 48, 229, 252, 62, 110, 15, 229, 135, 57,
+ 11, 233, 193, 227, 73, 228, 200, 209, 194, 142, 200, 186, 54, 119, 36,
+ 42, 207, 243, 142, 185, 150, 177, 6, 92, 146, 46, 168, 232, 226, 36,
+ 204, 153, 124, 236, 9, 164, 35, 146, 60, 220, 33, 90, 88, 197, 244,
+ 202, 229, 210, 5, 87, 82, 100, 47, 182, 111, 98, 217, 162, 111, 11,
+ 164, 149, 16, 23, 84, 106, 25, 36, 228, 91, 223, 167, 190, 207, 167,
+ 125, 207, 53, 247, 6, 95, 4, 73, 81, 77, 219, 205, 55, 142, 74,
+ 182, 182, 119, 146, 240, 63, 177, 225, 52, 20, 189, 47, 228, 102, 21,
+ 223, 144, 182, 122, 186, 100, 216, 109, 177, 168, 114, 173, 61, 213, 215,
+ 44, 142, 205, 75, 24, 225, 50, 241, 205, 157, 130, 124, 68, 196, 128,
+ 249, 168, 163, 107, 39, 58, 230, 36, 47, 121, 31, 148, 6, 170, 86,
+ 154, 152, 48, 74, 118, 116, 197, 37, 240, 54, 62, 228, 176, 84, 99,
+ 106, 128, 18, 184, 13, 253, 234, 60, 180, 134, 21, 75, 195, 98, 52,
+ 149, 110, 210, 233, 110, 54, 81, 123, 98, 10, 124, 225, 165, 116, 47,
+ 115, 160, 147, 42, 8, 12, 137, 167, 185, 192, 115, 232, 229, 89, 202,
+ 210, 144, 142, 143, 206, 129, 36, 211, 127, 82, 148, 21, 70, 84, 202,
+ 119, 87, 139, 157, 61, 146, 5, 175, 252, 129, 240, 65, 205, 193, 163,
+ 246, 246, 97, 157, 162, 26, 135, 0, 254, 25, 136, 174, 143, 162, 35,
+ 54, 32, 113, 8, 123, 51, 128, 63, 168, 83, 74, 253, 118, 219, 99,
+ 129, 103, 186, 88, 217, 159, 175, 48, 202, 122, 112, 163, 181, 190, 136,
+ 61, 133, 148, 37, 77, 50, 46, 243, 73, 102, 16, 102, 235, 58, 35,
+ 116, 142, 106, 44, 121, 191, 45, 165, 128, 20, 23, 244, 26, 170, 95,
+ 173, 147, 134, 235, 102, 142, 127, 243, 214, 59, 231, 166, 234, 61, 83,
+ 64, 167, 80, 12, 161, 211, 207, 25, 50, 51, 187, 36, 119, 246, 61,
+ 224, 187, 146, 152, 75, 171, 218, 213, 104, 174, 78, 201, 134, 43, 203,
+ 167, 179, 180, 187, 48, 20, 99, 170, 160, 233, 167, 215, 209, 111, 216,
+ 236, 67, 220, 182, 210, 18, 163, 55, 201, 103, 39, 95, 58, 68, 50,
+ 192, 66, 167, 124, 49, 42, 90, 86, 121, 214, 156, 101, 101, 66, 251,
+ 13, 131, 105, 83, 38, 62, 165, 199, 240, 248, 66, 111, 95, 181, 84,
+ 46, 18, 106, 97, 61, 27, 182, 239, 210, 85, 15, 199, 158, 39, 5,
+ 250, 57, 157, 41, 28, 172, 180, 95, 21, 214, 226, 98, 59, 15, 28,
+ 123, 158, 9, 172, 139, 220, 227, 214, 71, 124, 94, 200, 160, 239, 218,
+ 117, 167, 150, 67, 251, 194, 158, 154, 88, 23, 67, 5, 109, 32, 91,
+ 119, 116, 1, 22, 77, 224, 253, 220, 52, 242, 133, 162, 52, 231, 210,
+ 36, 111, 117, 19, 141, 167, 151, 136, 194, 174, 119, 12, 198, 38, 29,
+ 75, 159, 136, 237, 12, 237, 82, 102, 186, 198, 52, 205, 222, 47, 247,
+ 154, 84, 73, 204, 185, 89, 175, 238, 232, 192, 202, 29, 255, 181, 198,
+ 90, 121, 244, 85, 112, 182, 84, 214, 19, 207, 135, 82, 168, 8, 202,
+ 172, 234, 11, 58, 236, 53, 218, 36, 56, 183, 220, 52, 248, 143, 34,
+ 194, 228, 244, 165, 3, 58, 185, 197, 101, 6, 230, 173, 94, 178, 5,
+ 54, 124, 66, 197, 170, 48, 94, 182, 46, 90, 248, 80, 115, 173, 84,
+ 51, 212, 155, 196, 138, 76, 147, 86, 157, 16, 147, 32, 154, 229, 128,
+ 179, 165, 59, 43, 226, 116, 168, 111, 237, 99, 222, 2, 225, 198, 59,
+ 89, 175, 39, 13, 15, 189, 44, 198, 89, 199, 43, 240, 165, 113, 154,
+ 199, 35, 138, 39, 83, 171, 61, 207, 105, 83, 169, 62, 26, 79, 240,
+ 10, 250, 64, 161, 115, 238, 21, 57, 6, 166, 3, 125, 93, 91, 212,
+ 162, 30, 90, 183, 68, 182, 149, 21, 70, 73, 125, 155, 123, 192, 12,
+ 127, 51, 223, 124, 181, 142, 3, 131, 87, 97, 254, 189, 99, 217, 209,
+ 69, 233, 161, 14, 90, 236, 193, 186, 89, 101, 180, 225, 110, 54, 212,
+ 103, 163, 247, 153, 181, 10, 107, 108, 41, 48, 204, 27, 141, 80, 25,
+ 148, 30, 143, 105, 106, 245, 123, 163, 5, 245, 47, 231, 212, 155, 243,
+ 173, 106, 108, 107, 223, 136, 165, 13, 45, 226, 234, 157, 229, 99, 176,
+ 178, 220, 153, 77, 179, 237, 224, 146, 242, 151, 48, 103, 14, 79, 58,
+ 166, 99, 140, 55, 105, 102, 62, 169, 196, 209, 202, 228, 243, 78, 174,
+ 43, 22, 64, 13, 22, 12, 232, 145, 201, 63, 48, 225, 43, 142, 41,
+ 64, 20, 140, 41, 207, 214, 113, 178, 124, 200, 210, 153, 86, 145, 209,
+ 209, 224, 197, 86, 197, 135, 18, 77, 48, 81, 140, 129, 237, 157, 98,
+ 63, 72, 93, 138, 171, 86, 22, 182, 234, 3, 201, 140, 28, 15, 13,
+ 74, 53, 17, 133, 220, 188, 94, 63, 251, 134, 73, 185, 252, 42, 113,
+ 82, 154, 182, 169, 44, 77, 1, 181, 63, 159, 110, 67, 19, 183, 175,
+ 135, 242, 163, 128, 50, 182, 42, 173, 60, 220, 121, 42, 121, 156, 15,
+ 146, 60, 82, 104, 91, 68, 227, 47, 71, 39, 207, 21, 154, 72, 107,
+ 162, 183, 18, 160, 60, 9, 173, 242, 170, 66, 195, 121, 26, 219, 36,
+ 164, 87, 167, 34, 208, 148, 188, 101, 113, 175, 157, 133, 203, 40, 80,
+ 70, 50, 36, 64, 34, 225, 100, 234, 193, 12, 164, 93, 218, 166, 27,
+ 28, 34, 4, 241, 180, 208, 216, 6, 25, 105, 107, 190, 130, 82, 8,
+ 139, 76, 34, 51, 201, 238, 219, 44, 247, 112, 13, 141, 213, 71, 110,
+ 161, 33, 93, 16, 242, 101, 173, 223, 97, 183, 189, 82, 63, 200, 194,
+ 84, 17, 217, 59, 136, 108, 161, 28, 165, 240, 58, 229, 189, 174, 76,
+ 63, 102, 199, 167, 241, 225, 151, 186, 221, 44, 26, 44, 106, 218, 247,
+ 77, 223, 214, 220, 201, 26, 151, 188, 103, 107, 8, 229, 181, 145, 208,
+ 235, 215, 201, 25, 208, 196, 132, 31, 29, 164, 9, 140, 72, 115, 218,
+ 175, 176, 154, 16, 15, 116, 10, 92, 145, 21, 115, 91, 59, 97, 199,
+ 60, 188, 80, 125, 43, 195, 24, 211, 81, 23, 185, 81, 73, 66, 248,
+ 158, 14, 59, 21, 58, 127, 126, 155, 28, 123, 48, 138, 28, 237, 91,
+ 39, 214, 75, 187, 75, 36, 235, 90, 132, 65, 109, 137, 249, 15, 227,
+ 158, 120, 8, 107, 208, 173, 204, 15, 96, 177, 179, 141, 122, 51, 94,
+ 231, 249, 54, 19, 218, 164, 220, 238, 23, 20, 163, 190, 110, 165, 219,
+ 145, 21, 132, 137, 206, 230, 94, 77, 157, 197, 38, 223, 194, 216, 27,
+ 165, 157, 181, 150, 127, 31, 149, 78, 145, 242, 17, 250, 178, 184, 245,
+ 253, 68, 148, 123, 102, 110, 200, 177, 40, 152, 245, 250, 70, 220, 171,
+ 11, 219, 219, 239, 18, 24, 171, 171, 60, 26, 130, 66, 217, 242, 217,
+ 59, 61, 86, 138, 248, 212, 63, 175, 222, 215, 12, 197, 49, 119, 213,
+ 58, 226, 23, 109, 221, 199, 174, 197, 217, 174, 105, 179, 100, 29, 239,
+ 213, 194, 138, 84, 131, 94, 83, 63, 118, 90, 232, 144, 48, 245, 123,
+ 234, 82, 148, 182, 174, 248, 40, 135, 35, 211, 64, 223, 152, 152, 244,
+ 190, 227, 139, 183, 46, 74, 196, 172, 235, 196, 214, 142, 241, 77, 3,
+ 41, 141, 121, 167, 208, 199, 150, 155, 79, 43, 115, 180, 27, 144, 176,
+ 63, 103, 150, 75, 111, 23, 149, 193, 42, 190, 58, 223, 240, 45, 83,
+ 77, 171, 41, 196, 194, 120, 151, 96, 183, 187, 59, 220, 61, 36, 217,
+ 196, 35, 57, 49, 186, 1, 200, 184, 146, 82, 71, 206, 135, 53, 218,
+ 122, 230, 235, 171, 76, 227, 114, 124, 35, 152, 98, 151, 250, 102, 124,
+ 206, 111, 164, 39, 223, 118, 179, 25, 29, 252, 50, 210, 51, 18, 170,
+ 214, 214, 42, 191, 156, 247, 153, 187, 101, 228, 128, 145, 95, 204, 194,
+ 207, 176, 128, 238, 70, 163, 231, 104, 5, 251, 139, 161, 30, 71, 199,
+ 26, 15, 238, 210, 119, 60, 24, 244, 86, 208, 87, 155, 165, 97, 214,
+ 160, 26, 234, 244, 5, 76, 45, 99, 162, 120, 138, 251, 214, 233, 253,
+ 25, 215, 10, 145, 178, 234, 50, 210, 185, 175, 69, 135, 74, 132, 80,
+ 233, 142, 173, 79, 245, 77, 102, 21, 51, 145, 32, 94, 123, 250, 66,
+ 131, 122, 187, 71, 173, 175, 58, 11, 235, 70, 147, 122, 158, 85, 188,
+ 63, 207, 74, 102, 182, 152, 38, 255, 195, 113, 2, 109, 102, 219, 59,
+ 36, 229, 239, 159, 4, 68, 115, 109, 125, 114, 188, 99, 195, 181, 83,
+ 224, 193, 247, 88, 10, 5, 187, 206, 240, 173, 250, 76, 199, 226, 13,
+ 149, 236, 108, 43, 84, 151, 252, 214, 9, 127, 65, 237, 183, 60, 221,
+ 3, 137, 23, 47, 182, 148, 91, 37, 132, 61, 10, 30, 69, 116, 165,
+ 247, 54, 187, 171, 174, 48, 38, 168, 157, 91, 53, 140, 141, 37, 169,
+ 63, 129, 89, 16, 106, 115, 120, 128, 149, 111, 95, 211, 112, 68, 156,
+ 169, 189, 80, 104, 212, 45, 16, 209, 104, 249, 124, 80, 124, 239, 11,
+ 175, 209, 88, 145, 127, 61, 164, 23, 129, 200, 252, 126, 201, 228, 20,
+ 66, 13, 62, 29, 30, 90, 83, 123, 167, 238, 56, 139, 31, 153, 118,
+ 125, 145, 82, 67, 103, 16, 149, 248, 99, 147, 111, 197, 73, 183, 82,
+ 193, 61, 43, 173, 123, 177, 87, 42, 80, 167, 208, 4, 8, 36, 24,
+ 60, 28, 135, 90, 44, 44, 172, 181, 145, 231, 40, 221, 231, 102, 69,
+ 199, 176, 239, 14, 47, 53, 100, 159, 123, 199, 210, 238, 230, 175, 202,
+ 123, 162, 52, 85, 115, 191, 99, 231, 206, 68, 110, 167, 43, 178, 151,
+ 196, 114, 126, 254, 201, 155, 240, 185, 4, 71, 63, 250, 53, 209, 107,
+ 137, 155, 18, 3, 62, 111, 180, 16, 103, 5, 76, 18, 118, 174, 63,
+ 175, 117, 187, 230, 161, 64, 156, 99, 255, 14, 233, 206, 226, 129, 209,
+ 246, 190, 255, 76, 82, 91, 212, 123, 163, 150, 59, 138, 219, 219, 205,
+ 155, 232, 199, 85, 123, 201, 41, 227, 155, 175, 62, 189, 38, 153, 64,
+ 154, 91, 27, 208, 233, 119, 170, 101, 245, 205, 33, 35, 134, 228, 142,
+ 223, 9, 175, 88, 93, 165, 231, 159, 148, 52, 170, 165, 121, 125, 178,
+ 30, 111, 23, 60, 144, 117, 29, 219, 141, 185, 222, 139, 97, 149, 165,
+ 131, 83, 233, 35, 126, 45, 225, 121, 86, 212, 54, 177, 139, 35, 62,
+ 151, 213, 98, 123, 11, 30, 199, 155, 48, 189, 199, 78, 9, 198, 77,
+ 98, 47, 207, 116, 33, 217, 67, 167, 178, 194, 150, 243, 111, 239, 154,
+ 155, 255, 246, 225, 233, 135, 134, 172, 226, 16, 181, 152, 150, 39, 14,
+ 109, 46, 183, 93, 22, 38, 116, 245, 253, 25, 248, 55, 73, 189, 77,
+ 173, 6, 18, 242, 252, 181, 6, 198, 242, 34, 252, 44, 164, 137, 138,
+ 247, 179, 124, 106, 178, 232, 197, 66, 98, 104, 194, 219, 88, 152, 219,
+ 40, 167, 105, 38, 220, 135, 89, 180, 45, 219, 103, 106, 131, 5, 48,
+ 61, 30, 119, 62, 46, 49, 24, 215, 204, 233, 204, 162, 172, 55, 60,
+ 210, 154, 101, 16, 136, 187, 118, 61, 185, 225, 19, 186, 159, 164, 189,
+ 210, 78, 183, 98, 94, 92, 249, 34, 9, 93, 169, 67, 6, 122, 97,
+ 172, 227, 19, 158, 114, 206, 76, 151, 151, 119, 237, 140, 52, 40, 21,
+ 252, 66, 194, 90, 231, 190, 192, 136, 77, 163, 155, 33, 4, 95, 212,
+ 82, 56, 148, 251, 250, 176, 23, 125, 84, 249, 35, 135, 137, 158, 214,
+ 167, 176, 58, 131, 38, 225, 252, 252, 43, 172, 97, 149, 151, 206, 51,
+ 49, 81, 51, 140, 4, 133, 221, 245, 172, 17, 49, 20, 78, 142, 236,
+ 110, 24, 101, 125, 249, 149, 224, 157, 124, 234, 40, 171, 153, 14, 167,
+ 222, 107, 138, 43, 155, 42, 2, 138, 53, 149, 230, 217, 154, 68, 108,
+ 86, 46, 166, 35, 3, 169, 73, 61, 39, 38, 90, 62, 31, 51, 243,
+ 26, 30, 158, 220, 108, 46, 85, 19, 10, 140, 126, 240, 13, 79, 93,
+ 184, 56, 237, 209, 163, 143, 82, 250, 47, 91, 115, 164, 166, 195, 222,
+ 250, 112, 187, 88, 58, 126, 27, 122, 221, 109, 136, 113, 205, 155, 228,
+ 146, 104, 247, 220, 43, 225, 186, 88, 246, 148, 151, 184, 16, 123, 112,
+ 216, 51, 159, 228, 227, 247, 171, 131, 250, 67, 163, 220, 251, 10, 131,
+ 216, 232, 171, 183, 155, 138, 125, 46, 83, 169, 62, 100, 136, 98, 43,
+ 109, 127, 77, 20, 126, 245, 196, 196, 227, 20, 10, 184, 38, 91, 248,
+ 176, 245, 235, 45, 241, 20, 202, 235, 94, 201, 241, 241, 251, 195, 82,
+ 82, 142, 55, 87, 38, 239, 18, 51, 20, 46, 4, 229, 40, 58, 30,
+ 14, 223, 98, 204, 201, 98, 11, 176, 22, 38, 158, 188, 131, 58, 80,
+ 109, 211, 155, 135, 16, 157, 193, 60, 103, 127, 249, 133, 160, 70, 223,
+ 202, 163, 81, 86, 230, 103, 106, 159, 215, 247, 69, 116, 46, 223, 204,
+ 109, 226, 36, 189, 41, 100, 123, 237, 164, 179, 132, 144, 69, 223, 151,
+ 232, 203, 48, 46, 214, 1, 197, 41, 148, 126, 88, 102, 153, 140, 140,
+ 231, 223, 76, 139, 235, 65, 217, 161, 67, 20, 253, 177, 191, 205, 52,
+ 81, 70, 3, 175, 53, 107, 136, 11, 65, 158, 86, 48, 244, 157, 42,
+ 222, 98, 79, 206, 171, 14, 114, 86, 35, 195, 98, 212, 43, 114, 209,
+ 175, 196, 21, 158, 223, 115, 38, 230, 77, 201, 37, 77, 185, 151, 194,
+ 58, 100, 200, 77, 211, 164, 172, 193, 17, 194, 106, 114, 67, 39, 250,
+ 68, 85, 20, 67, 150, 202, 58, 166, 43, 107, 239, 154, 131, 187, 117,
+ 182, 215, 170, 42, 181, 103, 57, 139, 152, 152, 112, 110, 192, 124, 26,
+ 245, 107, 98, 55, 20, 105, 94, 91, 154, 254, 119, 108, 149, 158, 37,
+ 168, 175, 10, 50, 218, 211, 217, 35, 154, 91, 66, 238, 190, 230, 76,
+ 167, 226, 120, 85, 238, 44, 83, 114, 223, 178, 110, 119, 72, 48, 97,
+ 126, 49, 171, 113, 48, 179, 41, 209, 222, 212, 178, 78, 61, 175, 57,
+ 210, 129, 53, 238, 98, 178, 122, 134, 136, 213, 13, 95, 65, 29, 110,
+ 185, 50, 8, 10, 232, 53, 209, 242, 40, 65, 107, 186, 175, 24, 250,
+ 144, 223, 233, 170, 35, 193, 210, 142, 250, 88, 22, 27, 82, 60, 157,
+ 180, 241, 140, 115, 118, 116, 225, 23, 132, 83, 200, 115, 37, 22, 77,
+ 86, 37, 195, 154, 175, 78, 31, 242, 15, 123, 231, 106, 180, 28, 38,
+ 234, 59, 118, 89, 210, 152, 224, 75, 145, 12, 27, 26, 63, 155, 176,
+ 203, 149, 56, 93, 255, 161, 181, 83, 136, 64, 189, 25, 207, 84, 68,
+ 255, 62, 255, 41, 116, 251, 42, 217, 144, 146, 135, 65, 100, 65, 219,
+ 164, 190, 139, 170, 178, 202, 106, 117, 170, 63, 25, 241, 203, 15, 10,
+ 215, 9, 58, 6, 117, 60, 189, 170, 104, 92, 60, 136, 23, 165, 212,
+ 23, 243, 103, 197, 161, 237, 26, 239, 41, 156, 12, 137, 211, 30, 183,
+ 147, 43, 165, 105, 88, 248, 251, 190, 170, 31, 234, 149, 207, 237, 90,
+ 153, 198, 147, 156, 191, 77, 134, 79, 211, 132, 254, 241, 129, 135, 203,
+ 162, 90, 239, 186, 186, 236, 62, 91, 235, 142, 17, 11, 154, 138, 225,
+ 228, 157, 46, 79, 137, 126, 61, 235, 160, 168, 80, 35, 45, 122, 195,
+ 90, 117, 106, 221, 146, 219, 147, 239, 61, 84, 155, 72, 163, 186, 230,
+ 144, 198, 243, 217, 15, 90, 204, 239, 101, 189, 72, 55, 66, 151, 151,
+ 106, 70, 160, 153, 29, 206, 226, 167, 228, 210, 75, 189, 18, 131, 228,
+ 34, 220, 182, 177, 250, 204, 49, 195, 191, 50, 236, 93, 238, 178, 207,
+ 84, 47, 141, 160, 88, 242, 251, 137, 88, 68, 196, 132, 147, 46, 207,
+ 238, 190, 81, 242, 146, 203, 200, 77, 120, 197, 157, 99, 29, 199, 138,
+ 37, 174, 235, 108, 133, 68, 40, 173, 167, 208, 240, 41, 52, 103, 67,
+ 180, 61, 189, 47, 66, 143, 126, 179, 142, 136, 222, 208, 211, 199, 237,
+ 218, 61, 204, 118, 158, 64, 35, 132, 56, 66, 193, 175, 223, 202, 138,
+ 114, 42, 199, 102, 80, 57, 208, 67, 168, 216, 240, 79, 76, 239, 118,
+ 170, 125, 93, 193, 115, 48, 145, 75, 219, 247, 195, 204, 43, 12, 209,
+ 96, 238, 88, 190, 171, 158, 105, 118, 10, 241, 174, 21, 104, 16, 170,
+ 11, 197, 80, 95, 127, 146, 207, 201, 179, 20, 134, 105, 227, 248, 158,
+ 224, 125, 104, 168, 189, 214, 10, 54, 115, 182, 6, 239, 128, 165, 218,
+ 114, 29, 97, 120, 83, 189, 161, 71, 182, 23, 106, 126, 96, 123, 167,
+ 108, 59, 196, 81, 56, 255, 117, 84, 235, 107, 89, 18, 49, 191, 150,
+ 62, 59, 110, 0, 29, 132, 248, 46, 183, 195, 251, 194, 18, 211, 35,
+ 43, 70, 87, 58, 199, 192, 40, 46, 201, 113, 164, 116, 124, 132, 40,
+ 84, 193, 248, 248, 135, 226, 172, 153, 175, 207, 149, 65, 92, 133, 24,
+ 148, 87, 93, 150, 230, 175, 228, 233, 112, 65, 31, 203, 137, 197, 180,
+ 49, 31, 233, 144, 92, 144, 190, 72, 250, 84, 212, 123, 146, 115, 66,
+ 85, 147, 255, 72, 224, 118, 227, 179, 46, 97, 225, 128, 34, 57, 204,
+ 171, 136, 242, 177, 104, 131, 123, 206, 88, 35, 185, 55, 18, 4, 179,
+ 81, 88, 139, 229, 69, 223, 58, 99, 185, 225, 95, 112, 100, 180, 226,
+ 140, 192, 72, 86, 241, 33, 146, 51, 84, 184, 248, 234, 234, 144, 71,
+ 248, 126, 253, 81, 153, 198, 124, 175, 237, 122, 206, 53, 118, 207, 4,
+ 217, 201, 148, 231, 174, 243, 45, 52, 76, 213, 21, 237, 179, 100, 87,
+ 142, 82, 80, 75, 229, 94, 40, 47, 244, 87, 157, 48, 61, 194, 33,
+ 65, 24, 187, 245, 164, 88, 179, 47, 231, 106, 164, 228, 81, 89, 50,
+ 83, 188, 42, 223, 108, 23, 79, 138, 137, 31, 3, 29, 59, 233, 144,
+ 68, 220, 187, 172, 221, 243, 158, 239, 13, 52, 241, 181, 84, 63, 135,
+ 166, 74, 123, 22, 22, 58, 171, 153, 222, 153, 122, 43, 169, 42, 152,
+ 216, 217, 54, 215, 213, 53, 63, 223, 195, 234, 197, 106, 50, 100, 92,
+ 148, 35, 93, 234, 129, 142, 137, 183, 208, 75, 153, 119, 244, 118, 105,
+ 76, 236, 209, 165, 88, 42, 219, 151, 146, 34, 232, 162, 181, 211, 141,
+ 138, 119, 134, 132, 42, 179, 232, 162, 155, 19, 207, 213, 233, 214, 47,
+ 40, 162, 61, 205, 233, 29, 189, 86, 42, 118, 173, 125, 216, 50, 171,
+ 83, 137, 132, 51, 240, 206, 84, 13, 154, 163, 113, 153, 186, 183, 74,
+ 105, 145, 95, 19, 47, 225, 251, 27, 158, 185, 76, 57, 55, 213, 165,
+ 234, 102, 138, 16, 212, 95, 84, 125, 222, 62, 164, 208, 200, 61, 167,
+ 233, 45, 43, 67, 172, 33, 80, 212, 84, 127, 194, 119, 77, 89, 123,
+ 191, 164, 214, 138, 143, 101, 228, 51, 153, 138, 183, 126, 42, 229, 170,
+ 249, 183, 4, 85, 92, 51, 61, 36, 226, 114, 235, 227, 202, 54, 44,
+ 114, 178, 119, 23, 132, 31, 68, 11, 17, 122, 196, 168, 190, 170, 247,
+ 15, 52, 189, 197, 26, 63, 166, 209, 80, 158, 79, 67, 127, 10, 17,
+ 93, 83, 79, 81, 229, 46, 120, 112, 205, 224, 218, 75, 105, 126, 6,
+ 147, 112, 246, 5, 181, 190, 21, 237, 129, 188, 140, 72, 77, 62, 236,
+ 168, 214, 215, 91, 88, 59, 70, 39, 67, 254, 187, 85, 106, 19, 163,
+ 58, 99, 217, 225, 252, 35, 164, 115, 149, 162, 230, 118, 60, 31, 179,
+ 249, 158, 84, 40, 222, 108, 43, 12, 201, 136, 126, 169, 144, 175, 231,
+ 190, 125, 20, 154, 40, 97, 111, 201, 55, 52, 217, 128, 197, 186, 54,
+ 78, 110, 251, 208, 144, 50, 248, 72, 53, 162, 99, 161, 103, 32, 77,
+ 222, 70, 141, 56, 151, 133, 140, 152, 0, 225, 136, 45, 159, 173, 246,
+ 88, 76, 21, 51, 171, 111, 30, 71, 190, 45, 181, 220, 214, 152, 50,
+ 206, 46, 202, 102, 60, 155, 234, 110, 209, 90, 148, 141, 47, 215, 117,
+ 73, 25, 11, 13, 2, 230, 36, 229, 169, 22, 233, 55, 175, 210, 228,
+ 49, 155, 83, 62, 52, 188, 186, 82, 193, 156, 144, 165, 172, 81, 84,
+ 115, 121, 188, 243, 19, 251, 62, 41, 147, 34, 90, 38, 243, 203, 7,
+ 46, 150, 44, 147, 117, 62, 15, 229, 167, 231, 44, 74, 242, 3, 188,
+ 55, 54, 183, 187, 109, 137, 205, 59, 178, 159, 217, 87, 19, 197, 161,
+ 222, 192, 46, 145, 126, 29, 212, 105, 248, 74, 242, 144, 140, 198, 142,
+ 101, 101, 230, 162, 101, 195, 156, 38, 86, 135, 184, 250, 56, 7, 57,
+ 173, 0, 187, 147, 129, 43, 67, 14, 98, 10, 198, 220, 80, 64, 122,
+ 186, 226, 68, 41, 170, 67, 181, 232, 67, 22, 104, 130, 224, 155, 43,
+ 187, 197, 209, 13, 97, 143, 71, 81, 8, 177, 87, 16, 13, 41, 214,
+ 118, 203, 162, 214, 91, 37, 43, 146, 67, 7, 234, 20, 93, 144, 154,
+ 177, 56, 89, 7, 166, 110, 160, 157, 246, 62, 91, 194, 125, 223, 151,
+ 89, 35, 199, 209, 216, 169, 252, 205, 165, 250, 64, 142, 115, 28, 187,
+ 55, 234, 9, 73, 121, 35, 19, 115, 199, 158, 115, 197, 43, 54, 87,
+ 85, 218, 81, 83, 123, 1, 86, 202, 28, 10, 157, 154, 34, 3, 133,
+ 224, 102, 254, 9, 251, 164, 111, 75, 89, 130, 236, 183, 76, 67, 159,
+ 133, 220, 93, 223, 78, 50, 157, 148, 231, 153, 199, 240, 235, 14, 9,
+ 17, 227, 66, 203, 214, 94, 120, 170, 16, 95, 25, 61, 113, 53, 41,
+ 34, 91, 107, 111, 234, 33, 250, 4, 233, 18, 37, 197, 116, 74, 103,
+ 37, 65, 223, 219, 56, 254, 27, 47, 220, 103, 153, 55, 79, 161, 9,
+ 61, 86, 61, 222, 97, 125, 89, 232, 107, 59, 179, 60, 173, 93, 152,
+ 191, 231, 222, 80, 173, 229, 160, 118, 243, 155, 160, 143, 6, 201, 132,
+ 252, 29, 27, 28, 143, 15, 130, 12, 217, 155, 209, 120, 66, 125, 177,
+ 10, 91, 250, 215, 123, 140, 221, 144, 179, 251, 66, 241, 154, 87, 12,
+ 66, 38, 184, 69, 179, 166, 212, 7, 89, 161, 35, 155, 78, 204, 79,
+ 87, 227, 45, 226, 155, 14, 93, 251, 101, 203, 205, 154, 199, 81, 173,
+ 12, 183, 36, 233, 25, 169, 68, 11, 247, 179, 83, 88, 125, 21, 42,
+ 87, 200, 222, 49, 155, 222, 149, 27, 207, 117, 198, 115, 93, 73, 103,
+ 224, 97, 120, 76, 28, 12, 37, 143, 175, 217, 134, 89, 176, 75, 77,
+ 16, 171, 4, 163, 183, 197, 61, 42, 248, 58, 183, 60, 164, 97, 57,
+ 207, 195, 241, 117, 61, 165, 131, 170, 61, 169, 224, 46, 39, 71, 89,
+ 181, 1, 218, 147, 173, 10, 52, 155, 224, 112, 33, 243, 192, 168, 243,
+ 105, 21, 87, 241, 69, 241, 50, 93, 216, 209, 229, 102, 47, 232, 236,
+ 222, 115, 49, 161, 176, 118, 157, 77, 253, 146, 252, 218, 220, 181, 77,
+ 69, 218, 40, 138, 96, 151, 168, 101, 207, 25, 161, 236, 99, 48, 243,
+ 146, 3, 15, 170, 226, 50, 245, 26, 187, 75, 165, 122, 29, 126, 106,
+ 163, 252, 71, 234, 160, 237, 149, 225, 88, 108, 4, 63, 17, 2, 49,
+ 134, 253, 97, 27, 230, 201, 17, 85, 129, 214, 208, 79, 161, 182, 1,
+ 213, 108, 50, 46, 56, 231, 8, 108, 172, 151, 178, 141, 40, 177, 115,
+ 162, 88, 35, 23, 114, 187, 191, 241, 226, 237, 243, 14, 12, 22, 115,
+ 19, 147, 24, 231, 36, 167, 110, 177, 71, 173, 12, 246, 156, 111, 83,
+ 200, 40, 188, 157, 0, 51, 16, 45, 205, 40, 225, 46, 149, 146, 90,
+ 101, 11, 23, 171, 59, 237, 151, 219, 225, 223, 90, 158, 110, 83, 210,
+ 11, 79, 174, 126, 107, 53, 37, 25, 72, 150, 225, 214, 203, 146, 136,
+ 123, 53, 37, 18, 25, 158, 38, 73, 38, 197, 226, 234, 25, 241, 200,
+ 225, 72, 233, 249, 78, 253, 88, 54, 113, 130, 28, 46, 98, 155, 158,
+ 175, 197, 92, 138, 217, 68, 134, 105, 199, 156, 118, 242, 156, 90, 82,
+ 236, 117, 194, 23, 105, 135, 99, 8, 123, 116, 89, 149, 31, 39, 181,
+ 135, 111, 66, 180, 175, 57, 21, 135, 174, 123, 219, 165, 223, 232, 243,
+ 175, 155, 199, 229, 151, 109, 38, 46, 163, 245, 201, 166, 246, 98, 157,
+ 204, 36, 25, 117, 49, 167, 113, 193, 245, 141, 138, 98, 142, 254, 82,
+ 206, 113, 185, 59, 131, 106, 235, 146, 231, 70, 218, 96, 31, 202, 103,
+ 1, 50, 68, 113, 180, 100, 225, 181, 15, 29, 41, 220, 143, 70, 57,
+ 49, 89, 88, 48, 115, 141, 253, 194, 162, 250, 230, 122, 54, 171, 40,
+ 124, 90, 24, 89, 50, 237, 71, 10, 244, 42, 173, 71, 79, 212, 118,
+ 215, 94, 239, 105, 112, 144, 96, 169, 226, 47, 50, 109, 106, 52, 99,
+ 30, 249, 172, 112, 20, 219, 85, 98, 77, 241, 92, 233, 34, 225, 28,
+ 163, 15, 42, 125, 91, 133, 131, 59, 93, 241, 106, 125, 148, 104, 150,
+ 141, 68, 220, 242, 201, 186, 52, 94, 148, 77, 254, 186, 229, 128, 216,
+ 149, 175, 170, 132, 157, 184, 38, 50, 235, 242, 171, 215, 61, 75, 112,
+ 39, 52, 149, 219, 110, 60, 126, 106, 73, 29, 109, 12, 189, 189, 19,
+ 211, 146, 45, 195, 91, 45, 100, 25, 156, 89, 110, 207, 28, 157, 190,
+ 252, 190, 166, 108, 137, 162, 116, 112, 9, 59, 235, 115, 250, 22, 109,
+ 179, 100, 184, 218, 225, 129, 246, 138, 244, 235, 98, 254, 121, 131, 209,
+ 33, 166, 152, 142, 176, 231, 66, 171, 59, 43, 173, 131, 148, 15, 163,
+ 89, 237, 51, 77, 12, 37, 111, 159, 66, 3, 135, 30, 59, 6, 146,
+ 247, 237, 158, 222, 123, 170, 144, 56, 65, 230, 121, 172, 119, 71, 15,
+ 229, 158, 122, 177, 137, 137, 190, 101, 108, 26, 19, 142, 126, 139, 234,
+ 78, 222, 139, 226, 114, 138, 39, 183, 30, 83, 14, 83, 5, 31, 196,
+ 111, 113, 248, 141, 23, 229, 208, 9, 205, 246, 222, 101, 107, 247, 90,
+ 227, 147, 84, 91, 155, 145, 145, 147, 151, 31, 145, 253, 186, 125, 77,
+ 237, 50, 203, 72, 125, 107, 177, 29, 143, 91, 243, 251, 164, 59, 125,
+ 67, 16, 177, 248, 245, 61, 134, 53, 90, 15, 159, 175, 61, 195, 12,
+ 170, 40, 154, 134, 250, 248, 23, 240, 82, 191, 124, 26, 24, 126, 244,
+ 88, 170, 149, 176, 79, 35, 92, 200, 147, 23, 177, 48, 219, 107, 34,
+ 24, 147, 219, 93, 100, 3, 59, 55, 237, 112, 101, 62, 34, 129, 250,
+ 60, 163, 72, 20, 77, 92, 220, 241, 164, 176, 101, 99, 113, 38, 13,
+ 165, 146, 212, 253, 226, 126, 195, 227, 83, 136, 223, 119, 166, 244, 190,
+ 131, 214, 34, 253, 83, 95, 100, 150, 209, 198, 107, 62, 167, 125, 59,
+ 98, 73, 28, 235, 100, 6, 61, 77, 132, 2, 118, 26, 235, 203, 239,
+ 22, 43, 179, 75, 110, 236, 146, 87, 115, 189, 122, 213, 116, 213, 167,
+ 255, 142, 206, 65, 196, 14, 147, 222, 192, 90, 133, 214, 41, 84, 229,
+ 124, 238, 248, 238, 65, 252, 240, 69, 10, 124, 239, 196, 150, 187, 43,
+ 136, 147, 74, 220, 226, 104, 142, 232, 7, 86, 93, 174, 73, 249, 171,
+ 62, 131, 62, 89, 229, 70, 7, 102, 151, 47, 178, 105, 62, 87, 189,
+ 200, 253, 172, 124, 119, 149, 116, 114, 202, 85, 172, 127, 168, 211, 91,
+ 155, 242, 117, 38, 15, 207, 237, 199, 230, 111, 197, 139, 15, 52, 238,
+ 83, 245, 22, 126, 59, 234, 160, 214, 218, 60, 204, 205, 87, 125, 200,
+ 158, 33, 73, 136, 182, 22, 48, 151, 159, 232, 29, 113, 80, 177, 94,
+ 237, 121, 239, 81, 29, 238, 219, 88, 206, 33, 239, 170, 221, 83, 40,
+ 205, 45, 109, 144, 220, 248, 170, 180, 141, 56, 78, 138, 231, 88, 36,
+ 54, 61, 126, 181, 251, 215, 100, 149, 85, 164, 234, 92, 99, 226, 17,
+ 127, 19, 228, 175, 21, 201, 205, 45, 147, 185, 213, 118, 190, 72, 216,
+ 229, 211, 187, 47, 16, 93, 194, 166, 182, 198, 228, 5, 47, 113, 199,
+ 33, 197, 189, 242, 98, 127, 133, 248, 255, 152, 251, 238, 176, 40, 146,
+ 231, 239, 37, 232, 154, 80, 84, 84, 48, 174, 1, 19, 138, 128, 98,
+ 32, 237, 204, 168, 96, 150, 83, 48, 7, 64, 5, 5, 84, 196, 128,
+ 9, 88, 64, 49, 11, 102, 209, 83, 49, 220, 137, 152, 0, 81, 81,
+ 1, 215, 156, 191, 162, 39, 138, 98, 88, 3, 6, 76, 152, 21, 65,
+ 223, 238, 221, 233, 158, 94, 220, 157, 89, 126, 187, 127, 188, 247, 60,
+ 60, 214, 51, 215, 93, 53, 85, 83, 159, 234, 234, 234, 176, 113, 35,
+ 67, 19, 70, 165, 218, 205, 142, 29, 51, 197, 219, 37, 175, 243, 145,
+ 159, 206, 117, 18, 223, 158, 30, 80, 100, 57, 119, 195, 187, 215, 255,
+ 203, 161, 172, 39, 55, 95, 21, 189, 103, 146, 181, 229, 116, 235, 224,
+ 135, 91, 2, 191, 126, 45, 233, 89, 245, 162, 185, 137, 200, 201, 225,
+ 238, 144, 26, 131, 142, 44, 189, 111, 107, 148, 119, 201, 216, 178, 87,
+ 199, 196, 225, 115, 99, 199, 31, 233, 179, 34, 113, 246, 119, 143, 135,
+ 57, 235, 139, 47, 250, 118, 61, 126, 254, 194, 196, 230, 59, 30, 133,
+ 22, 30, 29, 181, 125, 244, 198, 143, 149, 90, 53, 61, 155, 122, 193,
+ 190, 126, 179, 216, 2, 81, 181, 143, 103, 87, 181, 152, 178, 170, 164,
+ 243, 207, 123, 99, 51, 82, 141, 211, 182, 7, 230, 173, 27, 239, 58,
+ 204, 126, 73, 233, 181, 254, 71, 110, 31, 113, 244, 237, 221, 181, 123,
+ 69, 241, 223, 115, 215, 93, 157, 241, 106, 222, 152, 127, 246, 7, 15,
+ 178, 171, 243, 171, 166, 131, 217, 178, 231, 73, 11, 63, 29, 28, 179,
+ 244, 221, 189, 83, 227, 118, 25, 175, 111, 183, 160, 66, 134, 85, 201,
+ 128, 3, 127, 167, 219, 126, 60, 79, 221, 217, 153, 94, 241, 174, 40,
+ 62, 241, 75, 199, 14, 31, 31, 53, 252, 52, 186, 167, 197, 215, 47,
+ 247, 191, 110, 62, 183, 68, 210, 252, 68, 45, 75, 247, 177, 77, 14,
+ 127, 186, 21, 102, 118, 207, 161, 228, 192, 141, 139, 238, 61, 103, 13,
+ 47, 248, 222, 42, 255, 89, 78, 199, 177, 33, 237, 251, 92, 91, 252,
+ 168, 121, 219, 109, 177, 215, 210, 236, 175, 70, 134, 13, 237, 153, 212,
+ 226, 201, 104, 233, 18, 183, 224, 106, 51, 182, 57, 77, 180, 152, 254,
+ 245, 164, 245, 127, 87, 235, 90, 198, 250, 68, 141, 171, 242, 213, 170,
+ 96, 253, 191, 233, 71, 110, 251, 31, 168, 231, 22, 116, 179, 111, 219,
+ 38, 143, 191, 85, 254, 246, 185, 94, 106, 112, 187, 138, 19, 36, 11,
+ 219, 103, 63, 62, 58, 98, 236, 251, 185, 159, 179, 18, 70, 36, 95,
+ 9, 170, 56, 136, 154, 254, 172, 249, 138, 33, 231, 55, 190, 51, 22,
+ 251, 55, 24, 113, 177, 210, 160, 251, 7, 188, 158, 2, 135, 27, 176,
+ 62, 173, 112, 89, 199, 134, 9, 251, 6, 157, 55, 50, 218, 88, 227,
+ 202, 10, 227, 176, 176, 195, 137, 105, 59, 175, 29, 201, 77, 144, 90,
+ 53, 60, 246, 211, 251, 112, 220, 111, 145, 107, 131, 12, 159, 110, 222,
+ 15, 221, 159, 45, 156, 88, 146, 59, 249, 248, 225, 136, 95, 183, 140,
+ 250, 116, 107, 86, 121, 208, 253, 129, 197, 67, 130, 44, 190, 73, 242,
+ 220, 123, 76, 49, 202, 143, 75, 121, 233, 186, 219, 247, 254, 250, 103,
+ 251, 237, 51, 101, 231, 250, 61, 245, 17, 31, 152, 249, 207, 192, 185,
+ 14, 97, 19, 108, 247, 153, 45, 221, 213, 123, 230, 39, 144, 43, 22,
+ 188, 190, 254, 43, 126, 244, 222, 144, 246, 50, 241, 215, 157, 91, 151,
+ 135, 31, 127, 248, 79, 221, 228, 235, 23, 189, 178, 69, 39, 118, 27,
+ 53, 79, 254, 247, 99, 199, 46, 67, 162, 115, 91, 77, 113, 107, 209,
+ 54, 244, 88, 239, 61, 23, 237, 107, 255, 22, 93, 233, 82, 103, 198,
+ 207, 226, 137, 109, 119, 30, 13, 54, 105, 91, 225, 249, 189, 136, 46,
+ 174, 21, 66, 63, 118, 56, 234, 217, 126, 104, 207, 161, 162, 208, 164,
+ 116, 179, 95, 185, 19, 166, 78, 89, 254, 210, 234, 181, 227, 17, 185,
+ 81, 252, 253, 58, 226, 205, 142, 78, 85, 75, 230, 216, 5, 180, 147,
+ 248, 78, 52, 31, 226, 33, 174, 159, 252, 32, 48, 197, 163, 185, 53,
+ 211, 62, 41, 170, 69, 13, 167, 35, 7, 19, 90, 247, 154, 48, 249,
+ 242, 237, 6, 33, 30, 75, 239, 254, 106, 63, 212, 255, 192, 17, 73,
+ 146, 115, 74, 69, 170, 249, 164, 15, 55, 234, 140, 12, 158, 177, 111,
+ 167, 127, 152, 168, 203, 210, 109, 93, 204, 198, 220, 14, 54, 86, 88,
+ 69, 85, 205, 156, 250, 229, 74, 164, 237, 62, 115, 167, 153, 235, 124,
+ 2, 166, 26, 187, 102, 175, 168, 154, 145, 150, 50, 242, 185, 233, 39,
+ 209, 89, 143, 154, 63, 102, 213, 240, 151, 213, 152, 236, 107, 69, 15,
+ 202, 253, 104, 101, 53, 65, 122, 213, 251, 115, 225, 210, 49, 233, 51,
+ 18, 218, 54, 59, 246, 120, 85, 97, 247, 183, 159, 3, 246, 30, 111,
+ 223, 243, 129, 200, 104, 243, 182, 90, 190, 81, 86, 93, 76, 214, 143,
+ 48, 59, 176, 108, 244, 178, 9, 11, 170, 255, 21, 20, 93, 213, 207,
+ 105, 78, 150, 219, 232, 58, 191, 255, 251, 186, 237, 192, 223, 206, 99,
+ 198, 190, 185, 179, 160, 212, 239, 200, 187, 133, 23, 23, 172, 78, 79,
+ 105, 240, 97, 90, 238, 193, 153, 165, 238, 167, 38, 254, 37, 95, 115,
+ 176, 222, 253, 23, 67, 67, 218, 123, 189, 202, 123, 43, 61, 62, 46,
+ 119, 199, 133, 255, 253, 22, 245, 46, 157, 250, 101, 108, 206, 188, 205,
+ 83, 74, 157, 158, 230, 63, 240, 115, 28, 98, 41, 94, 91, 250, 86,
+ 114, 245, 127, 231, 54, 174, 247, 119, 232, 253, 164, 247, 157, 163, 165,
+ 131, 139, 251, 28, 248, 177, 249, 216, 219, 110, 173, 102, 153, 156, 185,
+ 176, 155, 41, 237, 82, 220, 252, 240, 181, 177, 153, 25, 25, 13, 54,
+ 201, 47, 252, 188, 151, 48, 182, 239, 247, 26, 159, 79, 6, 205, 12,
+ 95, 115, 95, 145, 60, 252, 180, 251, 249, 1, 143, 30, 223, 57, 244,
+ 198, 121, 209, 190, 143, 43, 171, 116, 235, 186, 216, 109, 194, 183, 73,
+ 179, 222, 122, 205, 247, 30, 180, 176, 237, 190, 184, 21, 205, 101, 206,
+ 29, 155, 12, 57, 124, 98, 202, 197, 228, 54, 109, 45, 19, 86, 201,
+ 229, 185, 125, 38, 79, 238, 92, 115, 228, 129, 23, 139, 31, 55, 46,
+ 248, 22, 100, 147, 81, 119, 229, 179, 117, 70, 55, 98, 140, 79, 14,
+ 251, 228, 113, 176, 81, 224, 230, 191, 108, 22, 110, 237, 255, 107, 87,
+ 163, 113, 97, 245, 110, 79, 54, 206, 153, 118, 101, 75, 212, 226, 22,
+ 126, 251, 199, 30, 165, 26, 15, 253, 126, 191, 90, 218, 166, 143, 146,
+ 233, 230, 161, 151, 238, 92, 190, 178, 123, 111, 231, 170, 54, 201, 41,
+ 213, 29, 106, 93, 221, 213, 205, 56, 194, 166, 203, 149, 53, 195, 95,
+ 79, 27, 26, 252, 163, 206, 146, 118, 87, 187, 84, 180, 31, 60, 178,
+ 195, 158, 116, 47, 219, 142, 65, 255, 60, 48, 126, 49, 186, 239, 181,
+ 163, 91, 15, 37, 222, 170, 247, 63, 171, 166, 67, 234, 214, 105, 97,
+ 118, 168, 153, 91, 197, 177, 238, 137, 142, 63, 115, 7, 181, 15, 121,
+ 28, 124, 41, 202, 230, 237, 249, 57, 119, 122, 47, 191, 20, 208, 240,
+ 201, 121, 102, 152, 108, 215, 30, 151, 131, 191, 190, 238, 155, 119, 46,
+ 112, 197, 194, 117, 49, 157, 198, 215, 117, 168, 226, 97, 47, 77, 240,
+ 222, 248, 210, 114, 100, 207, 37, 115, 143, 154, 22, 100, 36, 216, 12,
+ 31, 124, 241, 214, 139, 119, 245, 235, 52, 207, 184, 240, 91, 244, 229,
+ 118, 114, 114, 179, 27, 99, 74, 71, 215, 107, 219, 106, 224, 163, 254,
+ 195, 45, 86, 223, 57, 244, 98, 76, 11, 73, 179, 126, 86, 62, 237,
+ 198, 158, 184, 113, 224, 192, 229, 148, 186, 93, 172, 197, 69, 65, 147,
+ 206, 173, 93, 99, 243, 177, 85, 66, 104, 142, 247, 144, 228, 81, 7,
+ 76, 21, 153, 133, 137, 230, 103, 246, 76, 25, 253, 35, 43, 47, 112,
+ 253, 224, 251, 213, 115, 134, 231, 255, 19, 102, 118, 105, 112, 147, 197,
+ 219, 66, 186, 188, 176, 61, 56, 105, 95, 244, 209, 74, 145, 107, 26,
+ 100, 138, 46, 77, 99, 150, 103, 143, 238, 62, 180, 191, 119, 179, 79,
+ 237, 101, 91, 110, 93, 169, 59, 113, 204, 192, 209, 163, 50, 239, 85,
+ 183, 185, 191, 59, 96, 68, 45, 247, 144, 210, 172, 213, 14, 214, 3,
+ 250, 123, 231, 23, 207, 152, 59, 198, 42, 122, 253, 149, 140, 67, 85,
+ 46, 159, 186, 63, 61, 45, 255, 104, 65, 224, 250, 252, 209, 113, 25,
+ 87, 163, 29, 188, 31, 122, 46, 15, 30, 21, 185, 113, 229, 241, 245,
+ 255, 182, 47, 169, 215, 44, 165, 170, 109, 43, 255, 154, 63, 42, 214,
+ 120, 49, 225, 85, 78, 216, 180, 251, 237, 111, 119, 158, 228, 179, 125,
+ 84, 71, 55, 83, 217, 151, 143, 37, 254, 78, 171, 54, 108, 235, 227,
+ 216, 55, 108, 242, 196, 197, 97, 145, 171, 79, 53, 172, 244, 50, 240,
+ 195, 235, 253, 159, 223, 30, 92, 87, 55, 224, 127, 135, 23, 90, 153,
+ 84, 219, 245, 121, 239, 145, 187, 145, 97, 116, 226, 16, 102, 135, 241,
+ 85, 163, 17, 185, 10, 139, 143, 201, 247, 183, 72, 27, 143, 168, 209,
+ 173, 120, 93, 255, 248, 148, 214, 109, 75, 158, 119, 165, 62, 207, 219,
+ 48, 252, 82, 241, 244, 172, 141, 79, 227, 167, 52, 207, 119, 153, 89,
+ 24, 231, 151, 99, 124, 251, 203, 237, 85, 178, 37, 207, 127, 5, 252,
+ 156, 101, 155, 36, 237, 191, 99, 245, 237, 213, 67, 171, 13, 91, 119,
+ 223, 120, 224, 122, 151, 77, 149, 74, 27, 28, 177, 56, 158, 109, 223,
+ 182, 202, 182, 54, 91, 214, 109, 27, 249, 57, 122, 210, 210, 211, 107,
+ 198, 62, 150, 249, 181, 152, 90, 122, 254, 102, 233, 22, 139, 110, 126,
+ 219, 22, 47, 232, 190, 112, 157, 255, 149, 153, 19, 221, 182, 184, 246,
+ 57, 208, 115, 216, 162, 102, 86, 244, 167, 211, 103, 247, 228, 116, 31,
+ 178, 50, 90, 30, 229, 77, 109, 75, 138, 52, 118, 201, 11, 218, 145,
+ 217, 127, 218, 194, 171, 227, 23, 219, 121, 236, 169, 244, 241, 229, 75,
+ 155, 216, 42, 227, 147, 63, 136, 253, 7, 57, 121, 108, 104, 95, 101,
+ 85, 248, 192, 69, 173, 173, 199, 117, 116, 158, 253, 52, 209, 225, 86,
+ 90, 119, 247, 1, 70, 62, 93, 187, 236, 217, 251, 185, 208, 115, 129,
+ 104, 251, 67, 202, 37, 172, 241, 132, 152, 189, 161, 149, 37, 117, 242,
+ 122, 21, 13, 185, 181, 58, 130, 170, 120, 185, 197, 165, 70, 45, 222,
+ 39, 110, 166, 170, 13, 167, 68, 173, 29, 170, 63, 139, 236, 192, 28,
+ 173, 213, 194, 188, 206, 242, 97, 149, 86, 91, 172, 140, 59, 177, 126,
+ 201, 125, 219, 225, 141, 107, 102, 151, 182, 152, 243, 121, 111, 255, 33,
+ 243, 3, 141, 90, 86, 137, 75, 246, 200, 207, 221, 209, 250, 113, 132,
+ 139, 105, 155, 238, 11, 142, 46, 90, 250, 169, 120, 100, 159, 209, 179,
+ 215, 123, 219, 12, 167, 60, 99, 107, 215, 206, 238, 220, 107, 138, 251,
+ 199, 73, 178, 134, 35, 205, 143, 236, 105, 177, 82, 180, 101, 123, 124,
+ 193, 63, 251, 255, 25, 182, 126, 202, 228, 11, 23, 226, 163, 229, 95,
+ 134, 92, 119, 27, 219, 50, 230, 247, 173, 175, 219, 246, 219, 206, 254,
+ 223, 135, 131, 29, 31, 52, 203, 157, 85, 210, 224, 245, 151, 59, 59,
+ 75, 71, 60, 184, 19, 126, 248, 249, 111, 145, 215, 161, 249, 27, 226,
+ 86, 70, 31, 169, 243, 207, 169, 238, 103, 223, 39, 189, 109, 219, 215,
+ 121, 219, 170, 229, 49, 103, 195, 91, 93, 217, 213, 32, 195, 246, 245,
+ 154, 41, 247, 35, 3, 254, 155, 108, 183, 229, 229, 142, 130, 6, 62,
+ 23, 37, 77, 18, 65, 16, 237, 103, 59, 251, 76, 208, 241, 192, 182,
+ 219, 135, 197, 92, 30, 215, 193, 124, 126, 189, 169, 67, 118, 100, 191,
+ 169, 31, 117, 197, 106, 244, 11, 191, 157, 63, 34, 231, 13, 111, 116,
+ 125, 238, 251, 137, 85, 90, 53, 237, 250, 97, 144, 120, 91, 220, 24,
+ 89, 214, 197, 241, 181, 76, 236, 55, 86, 243, 89, 215, 188, 253, 197,
+ 79, 19, 23, 189, 127, 151, 191, 225, 169, 29, 125, 217, 61, 199, 181,
+ 190, 247, 148, 186, 125, 109, 234, 24, 37, 156, 253, 32, 250, 49, 108,
+ 94, 250, 137, 208, 91, 198, 244, 197, 55, 13, 102, 250, 117, 243, 217,
+ 214, 193, 118, 113, 157, 228, 33, 223, 63, 88, 217, 173, 58, 107, 245,
+ 60, 112, 100, 196, 22, 139, 129, 127, 167, 157, 90, 241, 81, 222, 169,
+ 90, 192, 143, 67, 133, 57, 201, 199, 46, 119, 106, 178, 188, 197, 187,
+ 7, 212, 214, 49, 169, 37, 174, 131, 78, 91, 90, 246, 110, 241, 180,
+ 249, 235, 167, 131, 221, 143, 103, 74, 114, 253, 146, 143, 22, 221, 221,
+ 21, 113, 239, 228, 137, 29, 141, 127, 139, 226, 79, 109, 186, 119, 254,
+ 227, 222, 16, 179, 244, 104, 179, 224, 189, 47, 115, 63, 117, 248, 116,
+ 196, 101, 249, 213, 246, 251, 231, 244, 29, 112, 249, 213, 63, 63, 67,
+ 141, 215, 61, 252, 183, 77, 106, 173, 115, 243, 235, 30, 249, 90, 152,
+ 59, 63, 45, 112, 97, 157, 180, 184, 120, 179, 162, 142, 5, 191, 70,
+ 78, 220, 189, 178, 221, 43, 191, 132, 125, 183, 188, 229, 119, 131, 63,
+ 217, 186, 125, 206, 61, 179, 121, 232, 147, 75, 163, 247, 245, 246, 241,
+ 179, 170, 119, 249, 68, 232, 152, 227, 77, 2, 47, 88, 239, 155, 236,
+ 121, 41, 216, 253, 99, 188, 253, 245, 119, 217, 123, 7, 197, 173, 60,
+ 184, 188, 66, 194, 4, 239, 71, 23, 54, 221, 123, 211, 120, 86, 142,
+ 125, 248, 250, 97, 179, 28, 211, 30, 141, 88, 24, 208, 98, 128, 248,
+ 223, 83, 5, 71, 7, 223, 246, 218, 238, 125, 161, 232, 85, 53, 201,
+ 206, 152, 23, 79, 47, 23, 15, 62, 209, 118, 221, 106, 155, 206, 255,
+ 172, 31, 95, 115, 104, 195, 215, 83, 159, 59, 68, 218, 94, 107, 188,
+ 54, 121, 153, 205, 158, 181, 78, 195, 229, 151, 172, 22, 63, 155, 250,
+ 205, 38, 167, 234, 151, 166, 15, 141, 179, 206, 213, 28, 84, 107, 122,
+ 101, 135, 3, 115, 179, 221, 11, 190, 175, 190, 86, 255, 196, 94, 175,
+ 13, 171, 107, 53, 90, 167, 184, 188, 42, 230, 193, 234, 31, 235, 103,
+ 6, 157, 58, 112, 239, 189, 71, 80, 221, 10, 97, 29, 98, 236, 62,
+ 58, 157, 220, 220, 200, 107, 71, 254, 192, 199, 201, 139, 246, 83, 105,
+ 98, 35, 135, 117, 78, 31, 127, 100, 57, 85, 122, 215, 225, 248, 222,
+ 45, 151, 54, 245, 170, 179, 176, 69, 68, 171, 58, 125, 135, 94, 190,
+ 183, 201, 220, 188, 225, 241, 172, 245, 173, 199, 213, 170, 176, 241, 244,
+ 209, 161, 31, 106, 223, 77, 30, 125, 247, 240, 155, 65, 79, 170, 120,
+ 117, 139, 15, 97, 230, 142, 57, 57, 164, 227, 243, 255, 26, 29, 174,
+ 178, 167, 123, 5, 207, 244, 189, 1, 29, 219, 62, 253, 190, 45, 59,
+ 123, 178, 233, 127, 116, 64, 223, 177, 25, 118, 187, 86, 133, 173, 29,
+ 88, 144, 59, 53, 33, 228, 198, 229, 241, 39, 86, 143, 108, 55, 218,
+ 163, 70, 114, 243, 131, 191, 230, 30, 157, 236, 94, 79, 210, 172, 209,
+ 173, 146, 139, 255, 210, 102, 199, 135, 239, 44, 233, 217, 215, 173, 91,
+ 167, 90, 195, 231, 159, 142, 236, 18, 55, 36, 250, 146, 151, 121, 238,
+ 186, 253, 81, 139, 93, 6, 137, 251, 206, 77, 155, 60, 189, 253, 198,
+ 36, 179, 101, 109, 90, 186, 214, 190, 182, 209, 173, 160, 224, 198, 29,
+ 201, 41, 102, 245, 217, 241, 187, 79, 237, 12, 255, 236, 88, 189, 119,
+ 235, 156, 38, 115, 63, 54, 244, 72, 104, 114, 111, 83, 243, 117, 61,
+ 3, 105, 177, 165, 217, 242, 232, 26, 73, 43, 134, 59, 207, 118, 24,
+ 127, 168, 93, 219, 245, 49, 141, 27, 206, 60, 189, 227, 212, 94, 23,
+ 35, 217, 252, 136, 103, 47, 247, 212, 176, 178, 146, 139, 254, 59, 54,
+ 168, 147, 73, 133, 85, 167, 92, 186, 216, 205, 106, 55, 223, 171, 112,
+ 90, 149, 140, 216, 142, 181, 106, 68, 137, 47, 223, 179, 105, 218, 34,
+ 189, 242, 19, 143, 197, 77, 188, 115, 135, 55, 181, 172, 16, 63, 59,
+ 74, 225, 118, 77, 84, 53, 181, 202, 85, 227, 36, 59, 170, 232, 227,
+ 251, 237, 35, 71, 7, 223, 47, 217, 55, 64, 18, 45, 241, 216, 221,
+ 243, 104, 203, 75, 157, 91, 249, 248, 25, 69, 101, 204, 140, 115, 91,
+ 223, 222, 119, 204, 58, 219, 185, 3, 99, 106, 244, 45, 30, 75, 217,
+ 228, 14, 14, 162, 140, 77, 58, 182, 171, 24, 63, 173, 160, 241, 212,
+ 89, 49, 126, 171, 36, 167, 175, 214, 245, 169, 108, 180, 190, 249, 162,
+ 253, 51, 70, 222, 95, 184, 255, 91, 188, 239, 248, 41, 39, 222, 53,
+ 120, 255, 178, 222, 40, 175, 35, 133, 149, 39, 30, 108, 126, 185, 193,
+ 219, 105, 133, 55, 198, 254, 206, 253, 60, 118, 239, 35, 199, 88, 241,
+ 152, 160, 236, 147, 45, 236, 6, 154, 77, 10, 123, 112, 113, 174, 223,
+ 204, 23, 63, 55, 251, 121, 196, 202, 44, 194, 250, 108, 72, 109, 181,
+ 190, 235, 236, 222, 31, 238, 12, 127, 180, 39, 189, 174, 131, 69, 204,
+ 231, 86, 19, 243, 135, 127, 61, 54, 180, 69, 99, 105, 137, 251, 158,
+ 97, 29, 140, 3, 94, 214, 48, 74, 188, 147, 86, 116, 121, 87, 237,
+ 246, 214, 217, 121, 138, 157, 15, 118, 122, 251, 157, 180, 49, 91, 121,
+ 245, 151, 185, 211, 156, 25, 11, 219, 50, 189, 243, 35, 154, 244, 111,
+ 212, 110, 130, 67, 181, 240, 78, 213, 106, 175, 104, 119, 160, 187, 185,
+ 209, 86, 231, 129, 223, 15, 95, 15, 221, 150, 48, 44, 157, 146, 52,
+ 54, 165, 166, 140, 22, 221, 235, 107, 85, 219, 100, 220, 30, 234, 109,
+ 224, 166, 171, 62, 93, 154, 12, 62, 211, 225, 88, 226, 102, 231, 5,
+ 210, 6, 206, 181, 188, 38, 43, 170, 20, 127, 255, 242, 239, 230, 61,
+ 107, 47, 154, 230, 13, 31, 96, 99, 229, 95, 233, 183, 168, 241, 177,
+ 121, 118, 163, 41, 209, 66, 227, 243, 127, 101, 108, 27, 241, 115, 70,
+ 233, 131, 45, 222, 169, 241, 146, 51, 93, 199, 212, 60, 243, 108, 251,
+ 6, 48, 231, 239, 111, 225, 180, 239, 218, 107, 115, 119, 73, 179, 53,
+ 169, 115, 26, 94, 124, 91, 56, 182, 229, 30, 191, 124, 255, 220, 187,
+ 157, 15, 189, 153, 37, 138, 115, 184, 251, 124, 234, 201, 253, 13, 156,
+ 103, 92, 109, 26, 178, 32, 209, 221, 207, 164, 183, 116, 131, 159, 123,
+ 162, 215, 23, 187, 160, 97, 206, 205, 198, 249, 14, 107, 75, 187, 196,
+ 13, 255, 58, 113, 225, 203, 118, 11, 214, 167, 167, 101, 250, 120, 152,
+ 207, 111, 19, 57, 101, 99, 73, 157, 65, 215, 198, 181, 221, 240, 172,
+ 235, 187, 253, 37, 125, 142, 57, 13, 222, 208, 221, 209, 113, 102, 140,
+ 212, 97, 187, 169, 149, 81, 226, 219, 152, 185, 91, 102, 84, 61, 56,
+ 97, 136, 183, 243, 173, 243, 46, 244, 224, 199, 27, 18, 210, 189, 223,
+ 207, 11, 26, 213, 189, 118, 247, 51, 237, 19, 221, 77, 35, 171, 198,
+ 181, 157, 248, 122, 194, 138, 124, 209, 248, 164, 2, 199, 85, 107, 123,
+ 55, 184, 93, 124, 37, 226, 115, 251, 97, 102, 183, 155, 210, 79, 191,
+ 5, 231, 158, 24, 243, 121, 205, 98, 123, 249, 18, 197, 192, 165, 169,
+ 159, 95, 118, 206, 205, 185, 247, 168, 85, 175, 194, 65, 149, 106, 86,
+ 173, 235, 251, 60, 188, 246, 209, 253, 147, 219, 38, 245, 79, 16, 53,
+ 148, 53, 221, 16, 17, 246, 109, 223, 36, 39, 219, 81, 255, 4, 220,
+ 238, 109, 101, 245, 120, 233, 207, 6, 35, 92, 179, 122, 60, 28, 49,
+ 183, 71, 166, 101, 197, 57, 199, 102, 212, 202, 74, 24, 185, 160, 243,
+ 236, 232, 54, 23, 141, 36, 115, 166, 130, 201, 218, 146, 252, 156, 218,
+ 199, 183, 156, 31, 23, 226, 179, 196, 183, 235, 212, 18, 233, 128, 165,
+ 201, 183, 71, 182, 184, 88, 181, 107, 241, 134, 51, 131, 199, 48, 23,
+ 199, 4, 62, 173, 211, 106, 182, 120, 115, 147, 172, 245, 209, 15, 178,
+ 122, 29, 88, 120, 172, 95, 130, 180, 119, 222, 193, 7, 55, 246, 254,
+ 117, 234, 219, 79, 143, 59, 37, 199, 87, 222, 153, 87, 117, 103, 159,
+ 173, 94, 110, 85, 92, 219, 59, 217, 81, 189, 71, 47, 168, 85, 239,
+ 165, 81, 225, 224, 196, 117, 37, 251, 150, 210, 247, 168, 154, 198, 179,
+ 147, 110, 57, 108, 79, 200, 127, 251, 216, 230, 235, 188, 195, 51, 38,
+ 121, 139, 100, 153, 226, 91, 77, 102, 237, 53, 53, 137, 55, 218, 85,
+ 91, 124, 33, 247, 219, 200, 30, 33, 67, 134, 95, 218, 125, 230, 205,
+ 253, 208, 79, 65, 123, 67, 186, 156, 141, 238, 44, 142, 125, 248, 182,
+ 175, 232, 174, 168, 185, 155, 141, 91, 243, 255, 29, 95, 190, 57, 174,
+ 209, 206, 5, 207, 58, 153, 182, 106, 92, 177, 75, 193, 182, 26, 83,
+ 246, 124, 172, 208, 162, 145, 236, 94, 196, 162, 7, 7, 2, 186, 214,
+ 204, 61, 19, 87, 177, 201, 243, 156, 3, 162, 61, 205, 255, 238, 20,
+ 222, 35, 174, 244, 184, 104, 89, 208, 200, 1, 35, 163, 35, 171, 85,
+ 118, 185, 112, 161, 145, 89, 98, 236, 170, 248, 109, 182, 255, 181, 218,
+ 251, 109, 102, 192, 233, 208, 53, 171, 223, 28, 168, 248, 52, 111, 70,
+ 171, 87, 237, 122, 87, 105, 92, 101, 203, 69, 183, 6, 115, 59, 121,
+ 30, 144, 58, 250, 180, 124, 150, 178, 126, 203, 242, 240, 112, 39, 179,
+ 37, 77, 159, 5, 84, 28, 238, 215, 125, 234, 161, 26, 199, 143, 111,
+ 78, 46, 25, 187, 106, 179, 213, 18, 111, 187, 86, 177, 125, 143, 63,
+ 63, 222, 232, 224, 228, 153, 54, 169, 223, 199, 175, 184, 109, 237, 63,
+ 103, 78, 230, 138, 196, 223, 183, 123, 125, 251, 39, 222, 120, 198, 162,
+ 105, 51, 94, 245, 60, 249, 246, 233, 153, 1, 222, 247, 230, 39, 91,
+ 173, 188, 64, 111, 27, 191, 126, 213, 78, 79, 153, 209, 126, 139, 210,
+ 206, 219, 106, 255, 251, 186, 212, 105, 113, 78, 243, 225, 166, 238, 43,
+ 138, 162, 91, 245, 255, 45, 58, 149, 60, 103, 246, 203, 152, 195, 81,
+ 95, 234, 87, 219, 108, 190, 39, 230, 140, 251, 155, 27, 125, 171, 54,
+ 236, 115, 91, 90, 82, 251, 221, 171, 43, 243, 140, 127, 158, 63, 56,
+ 112, 252, 186, 148, 85, 45, 170, 155, 138, 172, 2, 54, 111, 206, 79,
+ 12, 61, 254, 122, 251, 222, 229, 249, 171, 123, 59, 216, 15, 41, 76,
+ 218, 189, 173, 195, 216, 157, 253, 118, 120, 135, 251, 109, 42, 168, 187,
+ 234, 163, 104, 127, 231, 161, 46, 251, 50, 82, 94, 229, 83, 111, 222,
+ 36, 61, 252, 178, 254, 135, 104, 208, 225, 235, 181, 31, 87, 63, 237,
+ 120, 39, 204, 113, 214, 187, 169, 187, 50, 102, 54, 159, 184, 186, 119,
+ 212, 132, 158, 78, 169, 159, 134, 238, 216, 184, 175, 78, 235, 5, 135,
+ 189, 147, 214, 109, 148, 157, 11, 245, 184, 18, 49, 244, 249, 179, 156,
+ 55, 153, 131, 189, 253, 78, 125, 152, 210, 98, 74, 183, 184, 254, 133,
+ 57, 143, 194, 220, 223, 110, 9, 189, 84, 127, 252, 184, 227, 111, 206,
+ 135, 126, 159, 188, 109, 202, 250, 253, 61, 115, 166, 53, 219, 151, 96,
+ 213, 36, 52, 118, 130, 231, 188, 78, 38, 135, 247, 49, 117, 38, 44,
+ 235, 148, 54, 35, 230, 233, 199, 32, 233, 137, 44, 19, 187, 9, 230,
+ 30, 3, 138, 254, 123, 126, 123, 255, 178, 213, 107, 42, 184, 181, 140,
+ 18, 79, 171, 85, 81, 58, 111, 88, 228, 30, 155, 214, 173, 44, 215,
+ 52, 152, 34, 94, 25, 85, 117, 234, 233, 161, 73, 3, 155, 212, 114,
+ 219, 118, 98, 231, 215, 13, 117, 69, 33, 83, 58, 126, 249, 250, 170,
+ 106, 157, 191, 55, 154, 123, 172, 220, 248, 246, 175, 180, 123, 179, 154,
+ 47, 250, 175, 199, 92, 219, 27, 9, 183, 38, 220, 220, 57, 75, 225,
+ 246, 52, 40, 236, 208, 198, 161, 247, 199, 75, 63, 199, 221, 205, 61,
+ 40, 189, 107, 83, 84, 209, 168, 246, 79, 143, 31, 135, 95, 254, 116,
+ 188, 75, 215, 170, 148, 215, 228, 232, 202, 168, 95, 247, 188, 122, 13,
+ 203, 95, 27, 46, 110, 180, 114, 199, 202, 160, 225, 209, 103, 223, 75,
+ 39, 126, 10, 127, 59, 34, 57, 151, 121, 122, 110, 150, 241, 236, 235,
+ 119, 134, 86, 189, 102, 250, 209, 228, 148, 135, 201, 249, 78, 53, 71,
+ 79, 222, 112, 105, 204, 147, 0, 203, 39, 174, 221, 123, 90, 119, 108,
+ 177, 98, 137, 243, 84, 251, 244, 137, 129, 138, 106, 219, 86, 14, 62,
+ 186, 225, 221, 203, 21, 166, 239, 237, 83, 236, 75, 11, 124, 19, 143,
+ 184, 28, 107, 231, 60, 245, 228, 178, 121, 51, 43, 12, 75, 252, 149,
+ 211, 106, 101, 190, 111, 82, 240, 141, 202, 53, 207, 70, 207, 175, 212,
+ 196, 253, 75, 80, 76, 235, 106, 212, 170, 243, 173, 130, 7, 196, 108,
+ 167, 42, 57, 228, 159, 93, 18, 243, 56, 251, 120, 211, 0, 217, 147,
+ 95, 55, 187, 82, 185, 111, 98, 154, 250, 44, 190, 55, 59, 60, 50,
+ 43, 217, 184, 223, 58, 243, 113, 83, 15, 209, 180, 164, 32, 125, 142,
+ 172, 184, 209, 177, 153, 87, 171, 191, 148, 88, 42, 102, 173, 122, 155,
+ 187, 195, 248, 131, 169, 213, 16, 103, 143, 135, 119, 134, 153, 26, 27,
+ 129, 121, 99, 222, 163, 130, 201, 162, 132, 126, 11, 159, 84, 252, 57,
+ 173, 249, 213, 234, 171, 51, 158, 236, 172, 155, 223, 116, 89, 109, 241,
+ 171, 5, 197, 233, 143, 197, 97, 14, 205, 103, 53, 153, 186, 127, 198,
+ 134, 233, 99, 168, 189, 159, 134, 12, 24, 176, 55, 125, 229, 193, 53,
+ 223, 166, 229, 180, 9, 218, 208, 102, 141, 113, 85, 115, 135, 188, 235,
+ 155, 142, 124, 252, 100, 187, 224, 250, 240, 249, 183, 226, 187, 54, 45,
+ 242, 253, 181, 171, 120, 230, 237, 175, 63, 36, 109, 174, 37, 172, 246,
+ 122, 119, 110, 192, 181, 163, 9, 245, 250, 230, 141, 56, 215, 196, 170,
+ 253, 247, 69, 205, 82, 170, 117, 232, 91, 244, 241, 229, 193, 223, 119,
+ 69, 34, 81, 119, 90, 36, 10, 6, 255, 122, 22, 77, 20, 215, 99,
+ 47, 8, 147, 39, 114, 119, 232, 137, 148, 109, 186, 251, 78, 158, 16,
+ 234, 171, 253, 190, 57, 68, 73, 0, 183, 16, 70, 36, 146, 73, 69,
+ 162, 68, 64, 87, 3, 180, 72, 202, 119, 103, 29, 146, 15, 101, 214,
+ 35, 56, 193, 247, 41, 43, 223, 214, 206, 206, 94, 219, 125, 119, 34,
+ 145, 131, 232, 218, 213, 171, 174, 34, 209, 69, 86, 166, 68, 39, 249,
+ 253, 64, 171, 116, 240, 111, 78, 206, 68, 113, 147, 63, 120, 162, 54,
+ 253, 124, 39, 135, 252, 249, 220, 20, 223, 49, 134, 46, 176, 131, 122,
+ 163, 63, 248, 31, 69, 169, 236, 16, 194, 108, 74, 176, 114, 83, 251,
+ 255, 198, 38, 34, 246, 61, 193, 59, 118, 98, 109, 70, 81, 255, 215,
+ 123, 2, 123, 123, 2, 155, 65, 137, 192, 142, 230, 232, 59, 250, 76,
+ 18, 171, 183, 161, 199, 205, 152, 52, 117, 138, 173, 239, 140, 96, 223,
+ 233, 156, 53, 177, 205, 129, 13, 60, 101, 234, 223, 30, 254, 71, 119,
+ 87, 253, 11, 239, 5, 244, 100, 219, 181, 97, 251, 121, 70, 113, 237,
+ 115, 82, 254, 236, 251, 39, 175, 250, 74, 203, 25, 107, 176, 181, 247,
+ 188, 62, 29, 176, 140, 40, 78, 70, 14, 120, 39, 40, 83, 121, 31,
+ 226, 42, 93, 100, 52, 208, 42, 35, 188, 210, 207, 20, 36, 3, 242,
+ 197, 122, 64, 25, 172, 46, 118, 33, 147, 116, 144, 209, 80, 171, 140,
+ 101, 107, 218, 186, 98, 61, 8, 25, 34, 86, 166, 210, 83, 236, 116,
+ 145, 97, 165, 85, 134, 245, 133, 72, 41, 148, 81, 196, 218, 221, 154,
+ 245, 199, 226, 132, 101, 167, 160, 29, 145, 63, 34, 58, 212, 113, 9,
+ 205, 61, 47, 139, 99, 37, 119, 99, 69, 171, 250, 76, 159, 201, 29,
+ 83, 88, 175, 103, 80, 251, 138, 223, 189, 153, 5, 204, 41, 222, 190,
+ 197, 98, 63, 230, 159, 156, 56, 59, 213, 211, 96, 70, 218, 254, 111,
+ 37, 93, 249, 243, 92, 198, 58, 227, 128, 29, 95, 223, 159, 11, 99,
+ 25, 215, 238, 13, 216, 54, 43, 49, 221, 38, 127, 61, 241, 92, 115,
+ 95, 100, 3, 232, 23, 164, 13, 224, 119, 70, 54, 64, 52, 180, 1,
+ 247, 92, 187, 13, 182, 135, 60, 180, 71, 54, 64, 237, 161, 13, 150,
+ 111, 156, 154, 42, 100, 3, 231, 190, 14, 105, 200, 6, 203, 183, 210,
+ 105, 200, 6, 11, 55, 15, 75, 19, 178, 129, 111, 184, 60, 21, 217,
+ 0, 209, 208, 6, 220, 115, 1, 27, 0, 191, 69, 54, 248, 12, 108,
+ 0, 253, 16, 217, 0, 209, 109, 59, 45, 161, 185, 231, 154, 249, 209,
+ 45, 234, 51, 158, 54, 245, 178, 145, 13, 80, 123, 57, 176, 1, 149,
+ 179, 131, 183, 111, 35, 96, 131, 59, 253, 66, 221, 144, 13, 186, 198,
+ 199, 40, 233, 206, 192, 6, 242, 246, 107, 220, 248, 250, 126, 6, 54,
+ 200, 189, 98, 236, 134, 108, 128, 232, 70, 192, 6, 220, 115, 126, 27,
+ 64, 92, 145, 126, 0, 113, 130, 108, 128, 232, 64, 224, 7, 220, 115,
+ 205, 252, 174, 0, 63, 152, 249, 119, 140, 20, 217, 0, 181, 175, 10,
+ 108, 80, 218, 59, 130, 183, 239, 103, 96, 131, 150, 38, 179, 165, 200,
+ 6, 33, 1, 97, 74, 186, 26, 176, 193, 163, 240, 89, 82, 33, 63,
+ 176, 127, 17, 46, 69, 54, 64, 116, 107, 96, 3, 238, 185, 230, 190,
+ 104, 12, 128, 113, 31, 141, 1, 33, 230, 147, 196, 20, 49, 158, 255,
+ 49, 6, 56, 168, 143, 1, 20, 232, 235, 249, 215, 36, 193, 49, 0,
+ 182, 67, 113, 77, 46, 225, 218, 43, 60, 39, 233, 56, 6, 24, 105,
+ 140, 107, 16, 239, 72, 6, 228, 139, 100, 80, 128, 166, 216, 241, 44,
+ 68, 39, 25, 13, 180, 202, 128, 120, 194, 122, 16, 50, 160, 222, 72,
+ 23, 159, 154, 186, 142, 1, 154, 101, 64, 127, 197, 99, 192, 95, 147,
+ 212, 198, 0, 138, 149, 81, 100, 174, 235, 24, 160, 89, 6, 244, 7,
+ 40, 195, 133, 181, 187, 53, 219, 198, 236, 221, 223, 114, 46, 110, 202,
+ 164, 136, 94, 232, 150, 73, 241, 197, 83, 35, 35, 35, 99, 196, 47,
+ 164, 12, 63, 46, 6, 201, 164, 136, 134, 252, 248, 98, 19, 201, 15,
+ 218, 147, 228, 199, 225, 89, 38, 69, 52, 228, 199, 135, 115, 146, 31,
+ 180, 29, 201, 143, 195, 134, 76, 138, 104, 200, 143, 15, 51, 144, 31,
+ 194, 12, 196, 9, 194, 140, 39, 24, 79, 201, 220, 233, 15, 204, 116,
+ 84, 199, 76, 136, 17, 240, 27, 90, 24, 51, 176, 29, 242, 131, 34,
+ 17, 215, 222, 147, 214, 15, 51, 163, 173, 162, 112, 222, 4, 249, 182,
+ 193, 23, 253, 78, 18, 67, 153, 74, 92, 82, 250, 97, 166, 94, 117,
+ 9, 198, 76, 8, 33, 3, 234, 141, 116, 9, 161, 244, 195, 140, 44,
+ 102, 56, 206, 155, 32, 95, 18, 51, 33, 72, 134, 104, 162, 94, 152,
+ 89, 180, 51, 18, 99, 6, 218, 221, 90, 99, 206, 47, 147, 66, 155,
+ 114, 57, 189, 182, 251, 182, 213, 125, 18, 218, 88, 27, 63, 104, 191,
+ 242, 242, 11, 225, 225, 7, 109, 85, 110, 126, 162, 137, 90, 249, 65,
+ 187, 232, 202, 15, 97, 6, 226, 4, 97, 38, 241, 32, 240, 53, 115,
+ 30, 204, 116, 82, 199, 76, 74, 252, 68, 177, 36, 90, 24, 51, 176,
+ 29, 242, 3, 187, 120, 238, 219, 167, 68, 25, 110, 156, 177, 35, 100,
+ 36, 130, 119, 74, 97, 229, 80, 81, 134, 27, 103, 32, 95, 36, 3,
+ 234, 141, 116, 201, 145, 25, 110, 156, 145, 68, 171, 99, 38, 145, 181,
+ 175, 143, 204, 112, 227, 12, 180, 59, 242, 161, 68, 170, 131, 198, 113,
+ 38, 62, 109, 63, 165, 75, 222, 238, 194, 218, 152, 228, 167, 105, 156,
+ 129, 252, 116, 201, 129, 93, 88, 123, 90, 227, 216, 212, 65, 227, 56,
+ 35, 79, 221, 79, 233, 146, 79, 186, 176, 182, 35, 223, 79, 211, 56,
+ 35, 3, 239, 167, 107, 110, 6, 113, 130, 48, 227, 179, 23, 228, 90,
+ 41, 60, 185, 153, 99, 153, 234, 10, 232, 155, 184, 95, 24, 51, 176,
+ 29, 246, 231, 3, 92, 123, 187, 253, 250, 97, 134, 156, 159, 67, 190,
+ 216, 159, 1, 13, 101, 42, 109, 187, 79, 63, 204, 144, 243, 115, 9,
+ 33, 3, 234, 141, 116, 241, 220, 167, 31, 102, 200, 249, 57, 228, 75,
+ 98, 70, 194, 202, 80, 236, 213, 15, 51, 104, 126, 238, 194, 218, 29,
+ 249, 144, 204, 71, 44, 191, 55, 112, 139, 99, 217, 249, 121, 191, 196,
+ 13, 84, 255, 140, 204, 195, 186, 196, 113, 104, 99, 146, 223, 160, 27,
+ 255, 164, 151, 157, 235, 66, 126, 133, 55, 207, 118, 210, 133, 159, 39,
+ 193, 175, 245, 40, 177, 220, 110, 227, 195, 19, 101, 231, 141, 137, 25,
+ 27, 168, 87, 83, 174, 186, 234, 52, 14, 238, 37, 198, 45, 240, 126,
+ 85, 183, 70, 253, 49, 7, 155, 191, 125, 3, 101, 179, 125, 158, 78,
+ 185, 25, 196, 9, 198, 204, 78, 224, 7, 7, 121, 198, 153, 206, 234,
+ 152, 81, 36, 79, 18, 251, 236, 17, 198, 12, 108, 135, 252, 192, 39,
+ 153, 104, 159, 164, 43, 102, 42, 104, 244, 3, 82, 134, 15, 33, 67,
+ 1, 222, 73, 193, 202, 73, 252, 87, 87, 204, 8, 203, 128, 124, 177,
+ 30, 128, 70, 186, 80, 255, 232, 138, 25, 29, 244, 216, 163, 142, 25,
+ 5, 107, 95, 197, 78, 93, 49, 163, 77, 134, 76, 137, 153, 118, 70,
+ 42, 187, 91, 43, 91, 130, 248, 223, 166, 157, 156, 108, 131, 40, 42,
+ 37, 134, 226, 203, 85, 96, 220, 149, 15, 44, 161, 126, 244, 125, 114,
+ 136, 141, 128, 116, 82, 172, 106, 92, 146, 228, 249, 210, 22, 199, 159,
+ 117, 228, 235, 91, 84, 59, 142, 94, 21, 176, 137, 197, 106, 18, 174,
+ 159, 213, 126, 121, 142, 110, 237, 124, 236, 48, 95, 223, 183, 245, 10,
+ 233, 161, 116, 245, 163, 108, 165, 152, 249, 175, 203, 173, 35, 202, 90,
+ 113, 73, 37, 230, 81, 227, 204, 35, 124, 125, 75, 77, 106, 48, 92,
+ 173, 206, 2, 211, 33, 47, 172, 24, 161, 26, 30, 178, 31, 244, 41,
+ 67, 217, 207, 161, 250, 41, 7, 100, 191, 93, 57, 170, 113, 24, 218,
+ 143, 57, 97, 126, 72, 200, 126, 182, 23, 118, 164, 35, 251, 161, 216,
+ 4, 237, 103, 221, 254, 84, 39, 33, 251, 45, 217, 106, 209, 25, 217,
+ 47, 124, 215, 3, 71, 100, 191, 196, 105, 103, 29, 133, 236, 199, 213,
+ 249, 44, 48, 13, 237, 39, 84, 255, 67, 246, 131, 120, 65, 246, 75,
+ 109, 173, 217, 126, 13, 116, 176, 223, 245, 126, 37, 212, 214, 174, 191,
+ 93, 145, 253, 130, 76, 77, 148, 121, 135, 223, 93, 95, 58, 38, 184,
+ 34, 111, 14, 50, 205, 34, 142, 182, 90, 116, 244, 4, 178, 31, 138,
+ 197, 217, 111, 207, 209, 227, 34, 46, 241, 214, 225, 238, 88, 22, 210,
+ 73, 61, 76, 164, 200, 126, 181, 59, 94, 86, 202, 154, 45, 170, 204,
+ 28, 51, 57, 194, 43, 215, 198, 180, 6, 195, 213, 8, 45, 48, 125,
+ 236, 185, 21, 35, 84, 59, 68, 246, 131, 177, 64, 221, 255, 100, 82,
+ 245, 53, 18, 228, 127, 50, 222, 188, 41, 11, 248, 223, 239, 109, 40,
+ 183, 178, 163, 71, 23, 168, 232, 182, 192, 255, 78, 180, 229, 175, 195,
+ 253, 6, 254, 103, 180, 14, 141, 61, 73, 184, 230, 55, 28, 248, 95,
+ 254, 145, 121, 188, 125, 75, 128, 255, 57, 116, 27, 143, 237, 87, 104,
+ 23, 164, 164, 221, 128, 255, 109, 138, 153, 204, 47, 23, 248, 31, 87,
+ 95, 180, 192, 116, 0, 240, 63, 161, 186, 35, 30, 243, 118, 114, 99,
+ 158, 124, 43, 136, 227, 123, 121, 198, 188, 174, 101, 198, 188, 29, 160,
+ 253, 118, 29, 198, 188, 29, 196, 88, 177, 131, 107, 95, 148, 104, 184,
+ 185, 149, 15, 33, 67, 1, 222, 73, 193, 202, 145, 37, 26, 110, 110,
+ 5, 249, 98, 61, 0, 141, 116, 73, 217, 102, 184, 185, 149, 207, 246,
+ 50, 99, 30, 107, 95, 106, 155, 225, 230, 86, 208, 238, 250, 206, 173,
+ 200, 60, 76, 150, 168, 255, 220, 138, 228, 7, 237, 169, 239, 220, 138,
+ 228, 71, 109, 211, 127, 110, 69, 230, 137, 16, 39, 8, 51, 178, 141,
+ 192, 15, 118, 242, 96, 166, 91, 153, 186, 55, 232, 43, 255, 91, 135,
+ 186, 247, 86, 162, 246, 181, 133, 107, 159, 179, 89, 87, 204, 152, 104,
+ 158, 147, 52, 201, 227, 234, 222, 91, 136, 186, 55, 160, 161, 76, 165,
+ 207, 109, 210, 21, 51, 154, 101, 36, 126, 95, 152, 134, 245, 32, 100,
+ 64, 189, 145, 46, 69, 9, 186, 98, 70, 179, 140, 103, 230, 71, 48,
+ 102, 32, 95, 181, 186, 55, 178, 87, 130, 174, 152, 209, 44, 99, 65,
+ 143, 169, 74, 204, 164, 179, 118, 183, 86, 182, 20, 137, 126, 44, 110,
+ 42, 133, 118, 196, 115, 23, 150, 182, 82, 236, 38, 158, 107, 142, 187,
+ 207, 155, 228, 73, 35, 22, 62, 70, 109, 168, 183, 214, 79, 149, 180,
+ 199, 210, 113, 212, 175, 30, 175, 121, 251, 142, 109, 113, 128, 226, 248,
+ 43, 48, 237, 176, 208, 140, 230, 147, 139, 176, 144, 206, 126, 91, 82,
+ 15, 248, 173, 144, 30, 136, 134, 122, 112, 207, 181, 235, 97, 118, 117,
+ 25, 106, 67, 217, 255, 111, 121, 26, 210, 163, 228, 246, 170, 52, 33,
+ 61, 56, 254, 10, 76, 67, 61, 248, 228, 146, 122, 64, 255, 65, 122,
+ 248, 44, 105, 42, 133, 254, 128, 244, 64, 244, 139, 71, 187, 137, 231,
+ 154, 223, 229, 73, 163, 60, 233, 145, 159, 89, 168, 13, 181, 100, 196,
+ 73, 37, 189, 120, 201, 56, 106, 151, 253, 121, 222, 190, 78, 64, 15,
+ 142, 191, 2, 211, 109, 128, 30, 124, 114, 73, 61, 68, 132, 30, 149,
+ 129, 30, 208, 231, 144, 30, 136, 174, 5, 190, 7, 247, 92, 243, 187,
+ 108, 0, 223, 99, 211, 81, 156, 47, 80, 47, 66, 85, 116, 91, 240,
+ 61, 222, 54, 8, 230, 237, 59, 2, 232, 193, 241, 87, 96, 218, 30,
+ 232, 193, 39, 151, 140, 137, 48, 14, 162, 152, 72, 173, 5, 56, 223,
+ 170, 61, 38, 218, 219, 149, 217, 87, 3, 250, 202, 214, 11, 199, 68,
+ 216, 14, 225, 92, 182, 129, 107, 111, 190, 94, 191, 60, 194, 190, 162,
+ 145, 61, 146, 1, 249, 226, 88, 2, 101, 108, 100, 231, 206, 235, 244,
+ 203, 35, 18, 190, 108, 195, 49, 81, 68, 200, 128, 122, 35, 93, 236,
+ 214, 233, 151, 71, 72, 253, 238, 226, 152, 8, 249, 146, 49, 81, 196,
+ 202, 144, 175, 213, 47, 143, 56, 121, 33, 0, 231, 17, 208, 238, 218,
+ 234, 252, 208, 166, 229, 93, 55, 128, 54, 214, 198, 15, 218, 175, 188,
+ 252, 236, 120, 248, 65, 91, 149, 151, 31, 180, 157, 54, 126, 208, 46,
+ 229, 93, 215, 128, 56, 193, 235, 26, 191, 129, 31, 108, 228, 193, 76,
+ 153, 61, 84, 242, 53, 96, 188, 94, 45, 140, 25, 216, 14, 143, 241,
+ 107, 136, 60, 98, 149, 225, 114, 111, 138, 144, 33, 7, 239, 36, 103,
+ 229, 248, 172, 50, 92, 238, 13, 249, 98, 61, 0, 141, 116, 41, 138,
+ 55, 92, 238, 77, 173, 86, 199, 140, 156, 181, 175, 44, 222, 112, 185,
+ 55, 180, 187, 33, 215, 53, 124, 86, 25, 118, 93, 3, 218, 211, 144,
+ 235, 26, 178, 120, 3, 175, 107, 252, 38, 106, 180, 63, 129, 31, 172,
+ 229, 193, 76, 153, 61, 39, 18, 208, 55, 177, 84, 135, 117, 141, 223,
+ 196, 122, 192, 47, 98, 93, 163, 84, 63, 204, 248, 165, 189, 229, 214,
+ 53, 126, 17, 235, 26, 128, 134, 50, 149, 182, 45, 209, 15, 51, 65,
+ 195, 214, 96, 204, 72, 8, 25, 80, 111, 164, 139, 103, 137, 126, 152,
+ 185, 226, 122, 145, 91, 215, 40, 45, 179, 174, 193, 202, 80, 252, 212,
+ 15, 51, 162, 243, 17, 220, 186, 70, 169, 246, 184, 11, 109, 90, 238,
+ 56, 94, 162, 157, 31, 180, 95, 121, 249, 121, 242, 240, 131, 182, 42,
+ 247, 250, 254, 79, 237, 252, 160, 93, 202, 59, 206, 64, 156, 32, 204,
+ 20, 125, 0, 126, 240, 91, 3, 102, 198, 249, 134, 134, 204, 156, 110,
+ 27, 60, 193, 95, 189, 198, 83, 12, 230, 183, 63, 116, 168, 241, 20,
+ 19, 181, 145, 98, 34, 55, 251, 166, 43, 102, 42, 107, 244, 131, 111,
+ 79, 114, 92, 112, 109, 132, 144, 161, 0, 239, 164, 96, 229, 200, 63,
+ 235, 138, 25, 205, 50, 22, 220, 153, 142, 101, 64, 190, 88, 15, 64,
+ 35, 93, 66, 62, 234, 138, 25, 205, 50, 228, 189, 27, 102, 99, 61,
+ 126, 148, 169, 241, 176, 246, 205, 121, 171, 43, 102, 52, 203, 232, 245,
+ 116, 190, 18, 51, 13, 141, 85, 118, 183, 86, 182, 84, 237, 79, 132,
+ 118, 68, 126, 131, 104, 143, 244, 181, 52, 247, 92, 115, 220, 253, 60,
+ 160, 27, 83, 191, 205, 57, 182, 77, 63, 6, 181, 55, 206, 26, 200,
+ 12, 113, 254, 143, 183, 239, 47, 198, 139, 185, 121, 253, 62, 219, 102,
+ 24, 99, 237, 247, 144, 237, 59, 146, 153, 253, 249, 145, 64, 95, 31,
+ 102, 173, 248, 49, 219, 102, 60, 243, 174, 201, 45, 85, 223, 8, 127,
+ 38, 98, 225, 21, 254, 190, 81, 147, 152, 43, 235, 15, 177, 109, 130,
+ 153, 112, 201, 191, 108, 223, 41, 76, 135, 228, 141, 188, 125, 127, 71,
+ 77, 99, 130, 150, 174, 96, 219, 204, 96, 204, 219, 203, 216, 190, 179,
+ 152, 128, 109, 19, 4, 228, 206, 97, 110, 212, 114, 100, 219, 204, 103,
+ 34, 206, 180, 84, 210, 70, 17, 50, 230, 81, 139, 42, 2, 125, 99,
+ 152, 129, 81, 205, 216, 54, 177, 204, 167, 253, 214, 172, 220, 197, 204,
+ 134, 123, 173, 5, 250, 46, 99, 14, 37, 181, 97, 219, 172, 196, 116,
+ 198, 167, 120, 226, 185, 246, 113, 26, 250, 11, 196, 16, 233, 47, 16,
+ 19, 120, 30, 202, 210, 208, 95, 184, 231, 218, 253, 229, 234, 127, 67,
+ 176, 191, 160, 246, 208, 95, 106, 252, 51, 135, 183, 111, 41, 240, 151,
+ 232, 90, 139, 176, 191, 36, 117, 93, 142, 253, 229, 127, 99, 86, 9,
+ 250, 203, 171, 53, 27, 177, 191, 52, 250, 185, 14, 251, 75, 161, 116,
+ 173, 160, 191, 100, 95, 88, 138, 253, 229, 80, 238, 2, 236, 47, 3,
+ 47, 132, 11, 244, 157, 198, 84, 233, 22, 130, 253, 197, 114, 232, 56,
+ 236, 47, 45, 103, 14, 17, 244, 23, 233, 14, 26, 251, 203, 241, 182,
+ 78, 216, 95, 82, 156, 109, 4, 253, 229, 179, 79, 7, 236, 47, 131,
+ 69, 182, 216, 95, 210, 182, 181, 19, 244, 151, 111, 152, 255, 74, 76,
+ 67, 127, 249, 38, 32, 23, 249, 11, 140, 135, 164, 191, 192, 248, 134,
+ 252, 5, 209, 157, 128, 191, 112, 207, 53, 243, 59, 9, 252, 229, 138,
+ 159, 17, 222, 3, 142, 218, 155, 1, 127, 105, 177, 183, 41, 111, 223,
+ 239, 192, 95, 102, 56, 58, 102, 35, 127, 57, 145, 226, 170, 164, 127,
+ 103, 142, 100, 222, 217, 184, 243, 246, 173, 220, 221, 135, 145, 191, 252,
+ 43, 27, 249, 139, 127, 137, 135, 146, 182, 6, 254, 226, 55, 134, 230,
+ 237, 107, 20, 61, 137, 185, 84, 161, 117, 54, 242, 23, 139, 150, 150,
+ 42, 26, 248, 203, 112, 247, 74, 188, 125, 197, 209, 211, 152, 227, 117,
+ 222, 101, 33, 127, 153, 58, 247, 170, 146, 54, 5, 254, 146, 240, 48,
+ 57, 139, 175, 111, 30, 240, 151, 181, 127, 5, 100, 33, 127, 57, 115,
+ 154, 86, 210, 69, 225, 50, 102, 212, 208, 183, 153, 124, 125, 127, 2,
+ 127, 113, 238, 101, 149, 133, 252, 229, 80, 96, 173, 44, 228, 47, 157,
+ 86, 84, 205, 18, 242, 151, 122, 38, 239, 50, 145, 191, 32, 26, 250,
+ 11, 247, 156, 223, 95, 224, 216, 70, 250, 11, 28, 171, 144, 191, 32,
+ 26, 198, 23, 238, 185, 102, 126, 159, 128, 191, 172, 50, 139, 192, 251,
+ 229, 81, 123, 19, 224, 47, 137, 187, 249, 251, 194, 248, 18, 145, 131,
+ 214, 227, 134, 49, 227, 166, 170, 104, 24, 95, 122, 85, 231, 95, 167,
+ 131, 241, 229, 81, 248, 92, 41, 242, 151, 192, 34, 21, 109, 2, 252,
+ 229, 130, 139, 64, 95, 16, 95, 190, 134, 206, 199, 251, 244, 59, 213,
+ 82, 205, 117, 140, 128, 191, 132, 166, 134, 75, 133, 226, 139, 43, 141,
+ 244, 157, 193, 72, 146, 35, 216, 190, 179, 24, 147, 218, 145, 82, 161,
+ 248, 146, 184, 16, 181, 153, 207, 252, 62, 16, 41, 197, 227, 145, 192,
+ 122, 40, 140, 47, 109, 255, 135, 250, 198, 50, 230, 215, 85, 52, 244,
+ 151, 175, 215, 133, 228, 46, 99, 92, 30, 68, 226, 179, 5, 136, 134,
+ 254, 194, 61, 231, 159, 231, 193, 60, 21, 229, 172, 241, 133, 32, 15,
+ 251, 201, 155, 179, 42, 15, 153, 225, 61, 188, 160, 111, 206, 27, 29,
+ 246, 73, 127, 32, 246, 73, 23, 113, 237, 125, 222, 232, 55, 207, 131,
+ 99, 46, 222, 39, 93, 68, 236, 251, 7, 24, 128, 50, 149, 152, 125,
+ 173, 223, 60, 15, 198, 105, 188, 239, 255, 45, 39, 3, 234, 141, 116,
+ 145, 189, 214, 111, 158, 7, 177, 141, 207, 176, 189, 81, 207, 89, 61,
+ 217, 92, 213, 252, 181, 126, 243, 60, 232, 15, 184, 150, 241, 70, 125,
+ 175, 61, 151, 187, 200, 164, 136, 126, 194, 100, 82, 124, 57, 141, 218,
+ 222, 253, 215, 234, 252, 184, 177, 13, 228, 192, 44, 13, 249, 241, 141,
+ 121, 106, 235, 156, 101, 248, 113, 177, 79, 38, 69, 52, 228, 199, 23,
+ 19, 73, 126, 230, 101, 248, 113, 216, 144, 73, 17, 13, 249, 241, 97,
+ 134, 156, 231, 65, 156, 224, 179, 5, 207, 129, 31, 124, 16, 194, 140,
+ 3, 254, 30, 230, 160, 111, 252, 75, 97, 204, 192, 118, 200, 15, 226,
+ 95, 113, 237, 37, 47, 13, 135, 25, 200, 23, 201, 48, 7, 52, 148,
+ 169, 92, 103, 127, 97, 56, 204, 152, 19, 50, 160, 222, 72, 23, 234,
+ 133, 225, 48, 3, 249, 146, 152, 49, 103, 101, 228, 60, 55, 28, 102,
+ 160, 221, 113, 173, 192, 116, 126, 182, 38, 204, 136, 194, 26, 235, 140,
+ 25, 104, 99, 146, 159, 38, 204, 64, 126, 186, 98, 134, 42, 195, 79,
+ 19, 102, 32, 63, 93, 49, 3, 109, 71, 242, 211, 132, 25, 200, 79,
+ 87, 204, 64, 156, 32, 204, 152, 63, 1, 126, 80, 40, 132, 153, 142,
+ 220, 25, 219, 130, 73, 98, 207, 103, 194, 152, 129, 237, 240, 24, 80,
+ 64, 156, 97, 123, 106, 56, 204, 120, 18, 50, 114, 192, 59, 229, 176,
+ 114, 66, 158, 26, 14, 51, 144, 47, 214, 3, 208, 88, 151, 167, 134,
+ 195, 140, 231, 51, 117, 204, 228, 176, 246, 141, 127, 98, 56, 204, 64,
+ 187, 235, 139, 25, 178, 198, 29, 242, 84, 127, 204, 144, 252, 68, 79,
+ 245, 199, 12, 201, 15, 218, 78, 95, 204, 144, 185, 25, 196, 9, 174,
+ 193, 63, 0, 126, 240, 92, 8, 51, 157, 240, 247, 136, 127, 60, 73,
+ 156, 248, 72, 24, 51, 176, 29, 30, 3, 30, 19, 53, 248, 71, 250,
+ 97, 134, 172, 39, 154, 19, 50, 226, 21, 0, 251, 172, 28, 249, 67,
+ 253, 48, 67, 214, 19, 33, 95, 92, 131, 7, 239, 142, 116, 241, 124,
+ 168, 31, 102, 200, 122, 34, 228, 75, 98, 6, 202, 84, 198, 151, 7,
+ 250, 97, 6, 213, 19, 93, 88, 187, 227, 179, 0, 167, 171, 159, 220,
+ 248, 34, 243, 143, 122, 34, 165, 216, 45, 173, 242, 228, 150, 78, 227,
+ 2, 180, 49, 226, 231, 35, 175, 126, 242, 65, 163, 15, 206, 101, 235,
+ 77, 230, 128, 223, 13, 105, 172, 78, 252, 60, 9, 126, 242, 206, 53,
+ 78, 166, 54, 116, 254, 163, 30, 161, 120, 189, 91, 26, 223, 164, 110,
+ 182, 78, 53, 248, 7, 4, 191, 83, 213, 79, 54, 158, 59, 239, 143,
+ 249, 170, 29, 220, 151, 97, 163, 219, 158, 49, 136, 19, 132, 25, 197,
+ 61, 64, 63, 17, 194, 140, 35, 87, 31, 190, 15, 230, 63, 249, 58,
+ 212, 224, 239, 19, 181, 235, 251, 92, 251, 214, 148, 167, 142, 152, 169,
+ 165, 209, 15, 58, 186, 72, 156, 112, 237, 154, 144, 161, 0, 239, 164,
+ 96, 229, 180, 46, 234, 171, 35, 102, 52, 203, 56, 229, 242, 245, 56,
+ 214, 35, 159, 208, 3, 208, 72, 151, 214, 241, 131, 116, 196, 140, 102,
+ 25, 207, 95, 62, 116, 198, 122, 228, 151, 169, 193, 179, 246, 109, 77,
+ 245, 211, 17, 51, 154, 101, 140, 250, 165, 26, 103, 186, 154, 170, 236,
+ 110, 173, 108, 41, 18, 69, 180, 105, 39, 135, 118, 68, 62, 132, 232,
+ 110, 41, 49, 20, 247, 92, 115, 220, 13, 28, 88, 66, 221, 173, 214,
+ 10, 239, 237, 182, 237, 227, 164, 164, 187, 79, 243, 167, 175, 247, 31,
+ 200, 187, 79, 250, 205, 146, 205, 52, 135, 213, 36, 92, 239, 55, 141,
+ 72, 166, 249, 176, 170, 172, 151, 68, 237, 167, 155, 95, 42, 102, 219,
+ 164, 208, 41, 79, 191, 41, 105, 113, 68, 26, 221, 237, 215, 103, 23,
+ 254, 26, 217, 97, 122, 162, 59, 90, 91, 200, 160, 223, 88, 30, 97,
+ 235, 147, 199, 233, 126, 175, 55, 243, 246, 45, 142, 202, 162, 205, 62,
+ 141, 99, 219, 200, 233, 95, 238, 110, 74, 250, 87, 248, 105, 58, 112,
+ 179, 165, 192, 59, 159, 163, 19, 186, 84, 98, 219, 92, 164, 93, 102,
+ 154, 176, 114, 47, 211, 167, 39, 148, 58, 243, 215, 254, 175, 209, 255,
+ 171, 86, 153, 237, 155, 67, 203, 220, 234, 179, 182, 186, 73, 247, 14,
+ 225, 31, 187, 197, 209, 185, 180, 111, 52, 197, 182, 201, 163, 47, 84,
+ 154, 175, 164, 171, 71, 220, 163, 151, 93, 220, 44, 176, 230, 240, 128,
+ 62, 251, 24, 173, 147, 40, 104, 179, 1, 166, 174, 42, 125, 159, 208,
+ 13, 108, 234, 243, 126, 223, 111, 81, 5, 180, 223, 227, 78, 108, 155,
+ 151, 244, 149, 10, 61, 149, 244, 207, 240, 66, 250, 65, 27, 111, 87,
+ 126, 59, 191, 165, 27, 87, 25, 199, 182, 41, 162, 229, 19, 3, 85,
+ 116, 196, 71, 122, 224, 133, 105, 174, 252, 53, 158, 47, 244, 222, 239,
+ 51, 217, 54, 223, 233, 27, 86, 51, 92, 85, 245, 176, 98, 250, 155,
+ 83, 168, 43, 255, 55, 42, 165, 71, 248, 142, 71, 109, 152, 143, 139,
+ 84, 239, 96, 36, 53, 98, 150, 30, 240, 227, 237, 43, 58, 101, 204,
+ 92, 104, 141, 222, 205, 148, 233, 246, 45, 72, 73, 87, 144, 86, 96,
+ 18, 206, 249, 243, 246, 253, 45, 175, 200, 48, 174, 3, 216, 54, 149,
+ 24, 231, 3, 82, 21, 45, 173, 204, 56, 55, 177, 231, 215, 87, 94,
+ 133, 217, 145, 208, 132, 109, 83, 141, 217, 209, 183, 142, 146, 254, 29,
+ 94, 157, 201, 61, 40, 18, 176, 85, 77, 134, 91, 103, 179, 192, 116,
+ 198, 167, 186, 140, 208, 250, 27, 142, 37, 32, 190, 162, 88, 50, 15,
+ 196, 18, 24, 47, 81, 44, 65, 52, 60, 231, 192, 61, 215, 204, 111,
+ 17, 136, 37, 5, 171, 37, 89, 40, 150, 44, 200, 87, 213, 132, 103,
+ 130, 88, 18, 179, 176, 22, 111, 29, 184, 20, 196, 18, 110, 156, 78,
+ 194, 107, 65, 70, 32, 150, 240, 141, 211, 42, 27, 236, 167, 15, 78,
+ 138, 195, 177, 100, 141, 245, 90, 22, 151, 105, 116, 216, 99, 254, 53,
+ 57, 99, 16, 75, 70, 108, 221, 129, 99, 73, 163, 135, 241, 74, 186,
+ 10, 136, 37, 53, 157, 35, 120, 251, 126, 1, 177, 36, 229, 59, 122,
+ 103, 57, 109, 26, 36, 119, 86, 189, 243, 105, 90, 242, 112, 37, 111,
+ 60, 48, 137, 62, 71, 43, 198, 63, 117, 70, 177, 196, 43, 181, 169,
+ 82, 86, 101, 16, 75, 154, 164, 254, 37, 16, 255, 174, 209, 211, 70,
+ 39, 224, 88, 146, 185, 41, 155, 181, 213, 77, 186, 81, 222, 83, 222,
+ 190, 159, 162, 114, 233, 236, 122, 53, 92, 81, 44, 89, 185, 161, 30,
+ 27, 15, 238, 209, 109, 235, 73, 4, 124, 237, 1, 45, 94, 83, 215,
+ 21, 197, 146, 228, 11, 42, 218, 56, 226, 9, 221, 191, 164, 46, 63,
+ 62, 64, 44, 169, 224, 89, 31, 199, 18, 119, 214, 223, 77, 34, 10,
+ 233, 101, 79, 90, 8, 96, 250, 45, 109, 92, 161, 35, 142, 37, 67,
+ 171, 117, 98, 251, 126, 164, 247, 213, 118, 20, 144, 251, 133, 78, 29,
+ 106, 131, 99, 73, 82, 159, 22, 236, 59, 23, 211, 155, 93, 27, 9,
+ 198, 18, 145, 71, 77, 28, 75, 188, 3, 171, 170, 250, 130, 88, 242,
+ 239, 138, 10, 188, 125, 171, 128, 88, 98, 126, 161, 42, 142, 37, 190,
+ 193, 111, 148, 223, 165, 22, 136, 37, 121, 238, 167, 120, 191, 209, 75,
+ 16, 75, 222, 236, 184, 225, 140, 98, 201, 137, 109, 3, 148, 244, 47,
+ 183, 202, 76, 242, 246, 236, 12, 222, 119, 6, 177, 100, 141, 236, 167,
+ 51, 138, 37, 77, 150, 54, 114, 65, 177, 68, 212, 104, 180, 139, 80,
+ 44, 225, 214, 96, 45, 48, 13, 99, 137, 208, 218, 44, 142, 37, 32,
+ 143, 66, 177, 228, 75, 171, 118, 114, 152, 23, 161, 88, 130, 232, 217,
+ 7, 99, 40, 238, 185, 102, 126, 123, 61, 74, 168, 167, 139, 209, 90,
+ 153, 29, 253, 120, 244, 56, 37, 61, 106, 170, 63, 125, 169, 229, 2,
+ 222, 117, 176, 62, 177, 155, 105, 46, 71, 79, 194, 235, 132, 217, 32,
+ 150, 240, 229, 232, 74, 61, 22, 238, 167, 195, 61, 235, 100, 163, 88,
+ 50, 112, 84, 129, 50, 110, 117, 137, 73, 163, 207, 183, 221, 198, 27,
+ 195, 146, 34, 14, 211, 45, 169, 9, 56, 150, 220, 91, 31, 160, 252,
+ 254, 203, 231, 30, 167, 71, 25, 95, 230, 245, 151, 170, 178, 44, 250,
+ 91, 190, 137, 27, 138, 37, 139, 43, 152, 43, 233, 53, 32, 47, 137,
+ 108, 222, 144, 119, 63, 92, 11, 16, 75, 78, 191, 169, 227, 134, 98,
+ 137, 115, 70, 53, 37, 61, 31, 196, 18, 191, 40, 19, 254, 125, 230,
+ 32, 150, 52, 114, 188, 231, 138, 98, 137, 34, 240, 136, 146, 158, 0,
+ 98, 201, 177, 13, 171, 249, 207, 201, 197, 228, 210, 86, 117, 135, 224,
+ 88, 242, 248, 199, 89, 165, 238, 9, 145, 247, 232, 17, 85, 87, 156,
+ 224, 235, 107, 25, 253, 128, 14, 25, 224, 147, 133, 98, 73, 231, 159,
+ 199, 149, 244, 106, 144, 151, 172, 120, 98, 204, 251, 141, 254, 149, 21,
+ 208, 141, 188, 28, 178, 81, 44, 25, 253, 122, 128, 146, 126, 54, 191,
+ 144, 14, 241, 15, 226, 237, 27, 12, 98, 201, 67, 183, 168, 108, 20,
+ 75, 134, 236, 90, 162, 164, 183, 135, 127, 164, 55, 87, 92, 205, 219,
+ 119, 61, 136, 37, 109, 159, 111, 202, 70, 177, 228, 116, 151, 45, 74,
+ 250, 83, 120, 49, 253, 102, 241, 54, 222, 190, 37, 32, 150, 88, 120,
+ 110, 70, 109, 152, 202, 225, 9, 217, 40, 47, 17, 37, 111, 200, 230,
+ 199, 180, 49, 99, 210, 110, 93, 54, 138, 37, 69, 215, 214, 40, 105,
+ 83, 16, 75, 238, 79, 229, 127, 231, 122, 167, 42, 50, 197, 118, 107,
+ 178, 81, 44, 249, 217, 60, 78, 73, 119, 0, 121, 137, 85, 221, 101,
+ 252, 235, 216, 167, 170, 48, 51, 174, 200, 178, 81, 44, 25, 247, 51,
+ 84, 73, 127, 0, 177, 196, 241, 172, 119, 182, 80, 44, 225, 214, 231,
+ 45, 48, 125, 2, 196, 18, 161, 117, 123, 110, 142, 211, 15, 199, 146,
+ 37, 32, 47, 129, 243, 31, 20, 75, 16, 237, 10, 242, 18, 238, 185,
+ 102, 126, 59, 64, 94, 210, 242, 197, 28, 124, 254, 210, 172, 149, 138,
+ 166, 65, 94, 226, 226, 61, 155, 183, 239, 71, 144, 151, 112, 243, 243,
+ 36, 188, 134, 108, 2, 98, 9, 223, 252, 92, 53, 246, 236, 167, 223,
+ 159, 70, 109, 82, 232, 99, 78, 17, 82, 148, 151, 196, 164, 241, 159,
+ 251, 44, 141, 58, 76, 239, 216, 133, 244, 202, 160, 247, 207, 87, 209,
+ 98, 144, 151, 100, 120, 241, 235, 11, 231, 56, 77, 175, 33, 185, 114,
+ 250, 235, 20, 150, 6, 121, 201, 85, 115, 161, 119, 62, 71, 103, 122,
+ 160, 54, 23, 233, 39, 203, 195, 89, 125, 47, 211, 149, 111, 10, 173,
+ 39, 95, 163, 227, 99, 145, 94, 57, 244, 165, 231, 104, 61, 249, 38,
+ 109, 228, 33, 180, 174, 155, 75, 175, 57, 134, 218, 228, 209, 190, 25,
+ 42, 218, 20, 204, 113, 58, 28, 229, 239, 43, 6, 177, 36, 42, 10,
+ 181, 81, 208, 127, 109, 83, 201, 53, 7, 121, 137, 85, 22, 255, 59,
+ 139, 162, 11, 232, 204, 157, 232, 251, 190, 164, 143, 119, 81, 173, 189,
+ 255, 6, 115, 156, 140, 43, 252, 190, 241, 3, 196, 146, 101, 230, 97,
+ 82, 20, 75, 196, 79, 102, 74, 85, 243, 163, 143, 244, 226, 67, 51,
+ 164, 252, 185, 227, 23, 122, 116, 143, 233, 82, 20, 75, 94, 190, 15,
+ 101, 109, 85, 76, 207, 216, 28, 42, 96, 171, 82, 186, 213, 8, 212,
+ 87, 196, 20, 236, 86, 209, 48, 150, 236, 252, 50, 157, 255, 251, 130,
+ 88, 18, 217, 103, 6, 62, 19, 188, 110, 217, 12, 182, 111, 5, 102,
+ 239, 85, 254, 119, 54, 2, 177, 196, 247, 17, 106, 83, 137, 217, 22,
+ 169, 210, 215, 20, 196, 18, 69, 19, 254, 59, 1, 225, 28, 39, 126,
+ 59, 178, 85, 53, 230, 47, 153, 202, 182, 191, 64, 44, 185, 238, 58,
+ 87, 42, 20, 75, 184, 189, 27, 22, 152, 62, 6, 98, 137, 208, 158,
+ 14, 84, 35, 83, 214, 197, 80, 173, 244, 246, 36, 177, 207, 3, 161,
+ 26, 89, 23, 92, 127, 241, 1, 125, 21, 121, 194, 53, 50, 216, 14,
+ 215, 175, 238, 114, 237, 67, 242, 12, 183, 22, 3, 249, 226, 250, 21,
+ 160, 161, 76, 21, 100, 12, 183, 22, 227, 67, 200, 128, 122, 35, 93,
+ 226, 239, 24, 110, 45, 6, 242, 37, 107, 100, 62, 172, 12, 201, 29,
+ 195, 173, 197, 64, 187, 27, 114, 253, 82, 148, 103, 216, 245, 75, 104,
+ 79, 67, 174, 95, 74, 238, 24, 118, 253, 18, 226, 4, 175, 197, 220,
+ 4, 126, 112, 79, 8, 51, 93, 185, 189, 250, 160, 111, 226, 45, 29,
+ 206, 67, 220, 38, 214, 48, 114, 137, 181, 152, 91, 134, 195, 12, 228,
+ 139, 207, 67, 0, 26, 202, 84, 142, 140, 255, 25, 14, 51, 18, 66,
+ 6, 212, 27, 233, 226, 249, 159, 225, 48, 3, 249, 170, 157, 135, 96,
+ 101, 40, 110, 26, 14, 51, 208, 238, 134, 92, 191, 132, 54, 54, 228,
+ 250, 165, 231, 127, 134, 93, 191, 132, 182, 51, 228, 250, 37, 196, 9,
+ 94, 139, 185, 6, 252, 224, 182, 16, 102, 186, 113, 235, 4, 55, 64,
+ 60, 207, 209, 97, 45, 230, 6, 49, 6, 220, 224, 218, 167, 92, 215,
+ 15, 51, 205, 158, 85, 227, 206, 17, 16, 50, 20, 224, 157, 20, 172,
+ 28, 234, 186, 126, 152, 249, 57, 32, 60, 11, 235, 145, 67, 232, 1,
+ 104, 164, 75, 206, 255, 244, 195, 204, 218, 199, 5, 220, 157, 23, 57,
+ 101, 214, 98, 88, 251, 250, 252, 79, 63, 204, 4, 206, 242, 229, 238,
+ 19, 188, 174, 253, 76, 13, 180, 41, 162, 181, 201, 249, 99, 95, 11,
+ 15, 63, 104, 191, 242, 242, 131, 246, 212, 198, 15, 218, 170, 188, 252,
+ 124, 120, 248, 65, 187, 232, 202, 15, 231, 102, 215, 136, 220, 236, 18,
+ 240, 131, 155, 2, 152, 177, 183, 227, 242, 6, 208, 87, 113, 69, 135,
+ 220, 236, 26, 225, 207, 87, 137, 220, 236, 138, 1, 115, 179, 171, 132,
+ 63, 3, 26, 202, 84, 54, 186, 98, 192, 220, 140, 144, 1, 245, 70,
+ 186, 196, 95, 54, 96, 110, 118, 165, 76, 110, 198, 202, 144, 92, 54,
+ 96, 110, 118, 197, 176, 227, 140, 232, 138, 97, 199, 25, 104, 79, 67,
+ 142, 51, 146, 203, 134, 29, 103, 32, 78, 112, 110, 118, 14, 248, 193,
+ 53, 33, 204, 112, 123, 152, 37, 160, 111, 226, 5, 29, 114, 179, 75,
+ 68, 78, 115, 145, 200, 205, 46, 24, 48, 55, 187, 72, 228, 102, 128,
+ 134, 50, 149, 185, 217, 121, 3, 230, 102, 132, 12, 168, 55, 210, 197,
+ 243, 188, 1, 115, 179, 11, 101, 114, 51, 86, 134, 226, 156, 1, 115,
+ 179, 11, 134, 157, 207, 64, 27, 27, 114, 62, 227, 121, 222, 176, 243,
+ 25, 104, 59, 67, 206, 103, 32, 78, 240, 89, 213, 163, 192, 15, 46,
+ 105, 199, 76, 232, 164, 0, 209, 12, 50, 111, 56, 11, 226, 249, 153,
+ 73, 98, 127, 255, 150, 114, 127, 255, 102, 204, 137, 248, 5, 217, 157,
+ 123, 198, 75, 255, 200, 205, 206, 18, 99, 192, 89, 226, 78, 4, 185,
+ 38, 63, 128, 99, 100, 17, 221, 115, 232, 211, 172, 150, 243, 166, 56,
+ 171, 48, 83, 69, 163, 31, 164, 140, 59, 142, 125, 205, 135, 144, 161,
+ 0, 239, 164, 96, 229, 196, 103, 105, 151, 177, 125, 118, 167, 236, 236,
+ 226, 66, 103, 21, 102, 52, 203, 184, 107, 245, 15, 55, 6, 156, 33,
+ 244, 0, 52, 214, 229, 132, 118, 25, 199, 99, 26, 158, 220, 22, 33,
+ 118, 83, 97, 70, 179, 140, 191, 159, 53, 224, 114, 204, 51, 101, 114,
+ 179, 51, 236, 190, 210, 12, 237, 50, 234, 45, 235, 37, 125, 103, 19,
+ 43, 85, 97, 70, 179, 140, 25, 5, 170, 189, 101, 195, 140, 85, 118,
+ 183, 86, 182, 84, 157, 13, 130, 118, 68, 252, 16, 13, 207, 6, 113,
+ 207, 69, 162, 53, 162, 230, 162, 221, 162, 22, 162, 84, 240, 135, 239,
+ 114, 28, 208, 141, 113, 112, 221, 194, 182, 233, 199, 160, 246, 166, 89,
+ 3, 25, 187, 174, 114, 222, 49, 224, 55, 227, 197, 220, 105, 115, 147,
+ 109, 51, 140, 121, 57, 44, 91, 73, 91, 101, 141, 100, 230, 45, 74,
+ 230, 237, 107, 220, 221, 135, 233, 99, 126, 136, 109, 51, 158, 89, 53,
+ 49, 93, 73, 87, 44, 157, 200, 252, 232, 120, 132, 183, 111, 123, 211,
+ 169, 76, 223, 160, 189, 108, 155, 25, 76, 97, 229, 68, 37, 93, 224,
+ 54, 147, 57, 106, 191, 133, 183, 111, 177, 124, 22, 211, 163, 194, 70,
+ 182, 205, 108, 230, 199, 134, 117, 42, 90, 58, 135, 57, 214, 118, 13,
+ 191, 190, 242, 185, 204, 193, 51, 171, 216, 54, 243, 25, 187, 247, 241,
+ 153, 170, 186, 183, 140, 113, 220, 178, 130, 191, 111, 84, 12, 115, 160,
+ 46, 234, 27, 203, 220, 159, 181, 56, 83, 85, 159, 92, 196, 124, 106,
+ 185, 64, 64, 238, 98, 230, 68, 220, 84, 182, 205, 82, 198, 44, 200,
+ 143, 237, 187, 140, 25, 235, 238, 45, 208, 119, 57, 227, 230, 219, 19,
+ 159, 67, 67, 244, 253, 57, 113, 196, 115, 237, 99, 60, 244, 53, 136,
+ 63, 210, 215, 32, 158, 144, 175, 33, 26, 250, 26, 247, 28, 250, 90,
+ 83, 214, 215, 90, 98, 126, 239, 128, 175, 141, 176, 90, 133, 125, 13,
+ 181, 135, 190, 246, 209, 106, 143, 160, 175, 73, 173, 210, 177, 175, 73,
+ 126, 108, 193, 190, 22, 154, 183, 72, 208, 215, 114, 125, 226, 176, 175,
+ 237, 90, 185, 90, 73, 139, 129, 175, 109, 186, 186, 94, 208, 215, 134,
+ 164, 175, 198, 190, 102, 50, 51, 30, 251, 154, 99, 65, 156, 160, 175,
+ 13, 154, 18, 135, 125, 237, 139, 91, 28, 246, 181, 132, 26, 113, 130,
+ 190, 70, 21, 175, 196, 190, 182, 172, 69, 28, 246, 181, 195, 215, 248,
+ 251, 194, 115, 104, 67, 71, 174, 197, 190, 86, 177, 247, 42, 236, 107,
+ 15, 78, 198, 9, 250, 218, 138, 244, 37, 216, 215, 230, 251, 199, 98,
+ 95, 11, 178, 140, 17, 244, 181, 37, 142, 225, 216, 215, 16, 13, 125,
+ 141, 123, 206, 239, 107, 48, 14, 147, 190, 6, 227, 42, 242, 53, 68,
+ 187, 3, 95, 227, 158, 67, 95, 171, 9, 124, 205, 10, 248, 90, 35,
+ 204, 175, 0, 248, 218, 189, 31, 245, 241, 25, 89, 212, 190, 2, 240,
+ 181, 248, 218, 252, 235, 116, 166, 221, 189, 152, 121, 63, 26, 225, 51,
+ 178, 77, 71, 171, 126, 111, 9, 250, 218, 90, 185, 57, 111, 95, 19,
+ 224, 107, 223, 60, 43, 225, 51, 178, 118, 115, 69, 217, 200, 215, 54,
+ 86, 122, 195, 187, 206, 110, 11, 124, 173, 192, 228, 10, 62, 231, 26,
+ 36, 75, 201, 66, 190, 246, 248, 209, 158, 44, 33, 95, 235, 119, 107,
+ 123, 22, 242, 181, 37, 39, 55, 101, 33, 95, 123, 153, 188, 134, 183,
+ 239, 79, 224, 107, 233, 253, 22, 225, 51, 178, 225, 221, 99, 149, 116,
+ 5, 224, 107, 73, 141, 163, 179, 132, 124, 173, 114, 149, 227, 248, 140,
+ 108, 154, 245, 126, 37, 93, 5, 248, 218, 208, 67, 255, 242, 247, 5,
+ 190, 246, 176, 150, 44, 11, 249, 90, 223, 51, 67, 178, 84, 251, 65,
+ 150, 49, 238, 190, 237, 179, 4, 125, 205, 242, 5, 231, 107, 44, 253,
+ 0, 250, 26, 126, 206, 239, 107, 112, 60, 38, 125, 13, 142, 175, 200,
+ 215, 16, 13, 227, 26, 247, 28, 250, 218, 76, 224, 107, 179, 128, 175,
+ 133, 169, 197, 181, 89, 21, 230, 227, 243, 181, 168, 61, 140, 107, 84,
+ 45, 129, 181, 69, 16, 215, 146, 163, 195, 241, 249, 218, 251, 53, 85,
+ 116, 125, 224, 107, 213, 182, 243, 175, 1, 193, 184, 22, 24, 26, 142,
+ 207, 215, 46, 121, 164, 162, 127, 151, 76, 100, 172, 167, 241, 175, 195,
+ 218, 192, 49, 52, 133, 59, 35, 235, 251, 69, 69, 67, 95, 251, 183,
+ 162, 192, 58, 44, 240, 181, 27, 141, 80, 155, 217, 204, 206, 14, 44,
+ 13, 124, 109, 6, 29, 41, 21, 138, 107, 123, 70, 113, 231, 107, 15,
+ 143, 65, 103, 100, 101, 204, 115, 255, 72, 193, 243, 181, 175, 158, 70,
+ 224, 243, 181, 207, 140, 216, 179, 185, 192, 215, 30, 155, 11, 201, 93,
+ 204, 140, 11, 65, 109, 150, 50, 167, 214, 163, 190, 203, 152, 38, 89,
+ 66, 125, 151, 51, 94, 119, 185, 179, 185, 136, 134, 113, 141, 123, 206,
+ 63, 175, 133, 121, 57, 202, 209, 83, 14, 129, 188, 243, 28, 111, 142,
+ 174, 126, 54, 23, 244, 45, 58, 44, 156, 163, 195, 118, 248, 108, 238,
+ 17, 142, 191, 236, 176, 174, 57, 186, 230, 185, 26, 204, 19, 240, 217,
+ 220, 35, 196, 111, 24, 1, 26, 202, 84, 174, 73, 31, 214, 53, 71,
+ 215, 44, 3, 142, 15, 88, 15, 66, 6, 212, 27, 233, 146, 152, 174,
+ 107, 142, 174, 69, 6, 136, 11, 88, 143, 195, 101, 126, 195, 136, 149,
+ 97, 151, 174, 107, 142, 174, 89, 6, 244, 7, 124, 246, 245, 176, 250,
+ 89, 85, 46, 223, 146, 73, 17, 253, 163, 123, 38, 197, 151, 135, 169,
+ 157, 125, 45, 195, 143, 27, 83, 101, 82, 68, 67, 126, 124, 99, 173,
+ 218, 221, 129, 233, 101, 248, 225, 184, 9, 248, 177, 180, 146, 31, 79,
+ 60, 85, 187, 59, 176, 12, 63, 14, 27, 50, 41, 162, 33, 63, 62,
+ 204, 144, 243, 90, 136, 19, 124, 207, 182, 93, 160, 184, 232, 168, 16,
+ 102, 184, 179, 185, 118, 160, 111, 74, 170, 48, 102, 96, 59, 228, 7,
+ 41, 105, 28, 127, 42, 213, 112, 152, 129, 124, 241, 239, 36, 1, 26,
+ 202, 84, 206, 157, 83, 12, 135, 25, 59, 66, 6, 212, 27, 233, 226,
+ 147, 98, 56, 204, 64, 190, 36, 102, 236, 88, 25, 148, 125, 160, 193,
+ 48, 3, 237, 142, 107, 35, 191, 229, 110, 154, 48, 35, 10, 123, 40,
+ 213, 21, 51, 208, 198, 36, 63, 77, 152, 129, 252, 116, 197, 140, 15,
+ 201, 239, 23, 224, 167, 1, 51, 242, 89, 15, 165, 186, 98, 6, 218,
+ 142, 124, 63, 77, 152, 129, 239, 167, 43, 102, 32, 78, 112, 253, 212,
+ 37, 80, 156, 114, 72, 8, 51, 220, 217, 92, 10, 244, 77, 116, 11,
+ 20, 196, 12, 108, 135, 235, 142, 82, 238, 219, 219, 185, 5, 26, 12,
+ 51, 144, 47, 174, 159, 2, 26, 202, 84, 218, 214, 53, 208, 96, 152,
+ 145, 16, 50, 160, 222, 72, 23, 79, 30, 25, 229, 197, 12, 228, 171,
+ 86, 63, 101, 101, 40, 92, 12, 135, 25, 104, 119, 125, 49, 163, 182,
+ 182, 237, 26, 168, 55, 102, 212, 214, 182, 73, 126, 255, 71, 204, 168,
+ 173, 109, 187, 232, 143, 25, 181, 181, 109, 23, 14, 51, 146, 174, 129,
+ 98, 185, 93, 160, 0, 102, 184, 179, 185, 10, 231, 64, 177, 143, 147,
+ 48, 102, 96, 59, 92, 119, 116, 230, 248, 23, 117, 211, 15, 51, 106,
+ 245, 83, 66, 134, 2, 188, 147, 130, 149, 35, 235, 166, 31, 102, 212,
+ 234, 167, 78, 132, 30, 128, 70, 186, 152, 119, 211, 15, 51, 106, 245,
+ 83, 39, 117, 204, 64, 153, 202, 252, 175, 171, 126, 152, 65, 245, 83,
+ 23, 214, 238, 248, 142, 85, 121, 245, 147, 179, 254, 125, 243, 71, 253,
+ 20, 158, 165, 245, 30, 146, 162, 181, 126, 170, 118, 207, 9, 193, 79,
+ 113, 162, 250, 201, 13, 253, 236, 179, 202, 214, 200, 226, 31, 237, 150,
+ 182, 9, 136, 208, 90, 35, 83, 203, 245, 8, 126, 146, 46, 53, 78,
+ 42, 6, 121, 254, 81, 7, 41, 122, 189, 91, 218, 122, 98, 77, 173,
+ 117, 16, 181, 92, 175, 43, 193, 239, 116, 245, 147, 141, 183, 207, 253,
+ 99, 174, 11, 207, 230, 46, 28, 30, 174, 117, 174, 75, 142, 51, 16,
+ 39, 120, 109, 219, 17, 248, 129, 139, 16, 102, 184, 179, 185, 137, 93,
+ 2, 197, 146, 206, 194, 152, 129, 237, 240, 24, 208, 133, 227, 223, 58,
+ 113, 128, 142, 152, 209, 124, 222, 244, 183, 243, 66, 124, 54, 87, 66,
+ 200, 72, 4, 239, 148, 200, 202, 105, 29, 50, 80, 71, 204, 104, 150,
+ 177, 161, 168, 176, 27, 214, 163, 51, 161, 7, 160, 145, 46, 173, 115,
+ 70, 235, 136, 25, 205, 50, 162, 198, 191, 194, 103, 115, 37, 157, 213,
+ 49, 3, 101, 194, 127, 147, 126, 14, 208, 17, 51, 154, 101, 244, 35,
+ 207, 230, 2, 187, 163, 125, 235, 129, 109, 218, 201, 161, 29, 17, 63,
+ 68, 119, 74, 137, 161, 184, 231, 224, 255, 84, 3, 253, 128, 127, 59,
+ 19, 117, 224, 102, 3, 75, 168, 169, 109, 70, 225, 243, 116, 45, 215,
+ 132, 42, 105, 239, 105, 254, 180, 120, 209, 66, 92, 247, 25, 12, 240,
+ 17, 0, 254, 230, 137, 36, 92, 173, 106, 201, 102, 154, 195, 106, 18,
+ 94, 223, 128, 231, 233, 248, 176, 42, 98, 207, 211, 5, 53, 69, 117,
+ 230, 20, 218, 102, 122, 34, 91, 83, 77, 163, 11, 207, 110, 16, 168,
+ 169, 30, 166, 87, 180, 66, 117, 209, 12, 154, 154, 19, 195, 202, 61,
+ 78, 23, 174, 155, 39, 208, 55, 139, 78, 79, 69, 99, 165, 156, 238,
+ 190, 46, 140, 149, 123, 154, 190, 57, 123, 154, 192, 186, 193, 57, 250,
+ 99, 189, 137, 108, 155, 139, 116, 161, 253, 48, 182, 239, 101, 58, 191,
+ 111, 47, 1, 185, 215, 232, 169, 118, 150, 108, 155, 28, 122, 120, 108,
+ 11, 213, 26, 75, 196, 77, 122, 248, 125, 59, 129, 190, 185, 244, 240,
+ 108, 20, 171, 242, 104, 171, 76, 118, 109, 36, 226, 30, 253, 205, 50,
+ 73, 224, 157, 31, 208, 135, 211, 142, 177, 109, 20, 244, 148, 227, 215,
+ 84, 117, 254, 136, 39, 116, 207, 211, 143, 121, 251, 138, 163, 11, 232,
+ 186, 235, 191, 179, 109, 94, 210, 245, 236, 170, 43, 253, 161, 114, 68,
+ 33, 189, 177, 142, 132, 183, 38, 248, 46, 234, 45, 237, 188, 212, 131,
+ 109, 83, 68, 79, 179, 31, 164, 164, 75, 194, 63, 210, 30, 121, 163,
+ 4, 234, 152, 95, 232, 9, 145, 131, 217, 54, 223, 233, 110, 212, 0,
+ 246, 174, 191, 98, 186, 154, 81, 111, 254, 51, 158, 81, 165, 180, 123,
+ 39, 23, 212, 134, 153, 254, 165, 91, 150, 170, 182, 100, 196, 108, 63,
+ 210, 133, 183, 175, 209, 41, 99, 166, 141, 87, 119, 182, 141, 41, 147,
+ 191, 206, 89, 85, 123, 149, 86, 96, 2, 238, 116, 20, 168, 219, 86,
+ 100, 46, 78, 170, 205, 182, 169, 196, 60, 247, 170, 162, 164, 127, 187,
+ 85, 102, 236, 41, 35, 129, 250, 105, 21, 102, 143, 83, 37, 182, 77,
+ 53, 166, 117, 134, 169, 146, 54, 137, 168, 206, 244, 244, 255, 41, 240,
+ 125, 107, 50, 220, 186, 162, 5, 166, 225, 121, 58, 114, 189, 81, 100,
+ 212, 66, 84, 29, 252, 53, 54, 106, 241, 231, 25, 24, 16, 95, 81,
+ 44, 105, 213, 186, 157, 28, 198, 75, 20, 75, 16, 253, 241, 96, 12,
+ 197, 61, 215, 28, 75, 118, 245, 41, 161, 238, 157, 104, 129, 207, 211,
+ 85, 17, 181, 87, 210, 57, 161, 254, 180, 155, 184, 115, 54, 23, 75,
+ 44, 65, 44, 177, 4, 177, 164, 30, 238, 219, 116, 233, 102, 154, 27,
+ 167, 147, 240, 250, 213, 143, 240, 100, 154, 111, 156, 22, 41, 207, 61,
+ 237, 167, 47, 247, 240, 192, 177, 228, 91, 211, 186, 44, 62, 210, 232,
+ 247, 191, 46, 241, 158, 17, 251, 9, 207, 192, 12, 148, 156, 64, 177,
+ 36, 211, 207, 77, 117, 254, 24, 196, 146, 131, 78, 209, 78, 66, 177,
+ 100, 244, 145, 67, 78, 40, 150, 180, 126, 248, 203, 9, 197, 146, 207,
+ 198, 214, 206, 66, 177, 36, 181, 133, 11, 62, 155, 187, 244, 104, 176,
+ 179, 234, 155, 95, 166, 123, 252, 195, 127, 174, 183, 66, 244, 53, 218,
+ 163, 205, 38, 103, 20, 75, 172, 188, 127, 43, 233, 106, 32, 150, 92,
+ 163, 29, 4, 238, 38, 200, 165, 7, 191, 62, 132, 207, 249, 87, 141,
+ 221, 166, 164, 187, 129, 88, 210, 170, 201, 50, 222, 190, 133, 32, 150,
+ 140, 58, 127, 238, 24, 138, 37, 158, 221, 140, 149, 118, 126, 21, 254,
+ 132, 62, 231, 28, 193, 235, 167, 95, 163, 10, 104, 251, 210, 36, 28,
+ 75, 102, 39, 92, 85, 210, 165, 225, 133, 116, 113, 167, 34, 222, 190,
+ 223, 64, 44, 89, 183, 185, 26, 142, 37, 70, 209, 22, 42, 108, 129,
+ 88, 210, 127, 98, 67, 193, 88, 242, 81, 84, 31, 199, 146, 15, 149,
+ 234, 227, 88, 82, 100, 94, 159, 31, 151, 32, 150, 48, 243, 234, 225,
+ 88, 146, 118, 78, 117, 214, 220, 4, 196, 146, 86, 230, 252, 114, 225,
+ 217, 92, 197, 30, 59, 28, 75, 38, 246, 80, 181, 111, 8, 98, 201,
+ 146, 251, 98, 222, 190, 143, 65, 44, 185, 187, 98, 64, 38, 138, 37,
+ 15, 125, 45, 50, 85, 107, 49, 149, 153, 71, 97, 233, 252, 254, 12,
+ 98, 201, 8, 71, 52, 6, 86, 99, 218, 57, 170, 214, 24, 225, 25,
+ 152, 153, 147, 210, 4, 198, 153, 154, 12, 183, 110, 108, 129, 105, 24,
+ 75, 200, 245, 100, 222, 88, 2, 242, 40, 20, 75, 106, 128, 88, 2,
+ 243, 34, 20, 75, 16, 13, 207, 230, 114, 207, 53, 199, 146, 215, 30,
+ 37, 84, 77, 103, 55, 28, 75, 46, 231, 251, 42, 233, 246, 83, 253,
+ 233, 131, 62, 11, 136, 88, 82, 15, 196, 18, 11, 37, 15, 212, 215,
+ 35, 118, 51, 205, 229, 232, 73, 120, 125, 242, 36, 200, 75, 248, 114,
+ 116, 216, 119, 83, 244, 126, 218, 230, 191, 247, 89, 40, 150, 12, 126,
+ 41, 87, 210, 211, 64, 44, 185, 243, 106, 21, 239, 119, 243, 5, 177,
+ 228, 197, 139, 202, 89, 40, 150, 204, 127, 211, 67, 105, 179, 160, 240,
+ 227, 116, 251, 6, 141, 120, 177, 245, 0, 196, 146, 249, 177, 119, 241,
+ 157, 33, 189, 76, 108, 149, 103, 94, 95, 132, 159, 166, 29, 92, 167,
+ 242, 158, 145, 93, 2, 98, 9, 179, 229, 31, 87, 20, 75, 170, 139,
+ 142, 42, 233, 39, 225, 151, 233, 11, 99, 46, 242, 246, 157, 11, 98,
+ 73, 160, 199, 77, 124, 54, 183, 161, 60, 67, 73, 175, 142, 188, 73,
+ 223, 108, 190, 141, 183, 175, 83, 76, 46, 253, 189, 208, 6, 159, 205,
+ 109, 96, 45, 81, 190, 255, 29, 16, 75, 94, 45, 203, 224, 245, 181,
+ 69, 178, 7, 244, 86, 159, 191, 241, 217, 220, 58, 23, 238, 40, 233,
+ 55, 243, 159, 208, 225, 179, 43, 243, 174, 235, 230, 131, 188, 36, 217,
+ 200, 10, 159, 205, 173, 51, 85, 117, 135, 242, 79, 144, 151, 132, 126,
+ 248, 139, 183, 239, 151, 200, 183, 244, 237, 238, 11, 241, 217, 220, 54,
+ 39, 84, 103, 85, 175, 204, 255, 72, 63, 108, 177, 137, 183, 239, 49,
+ 16, 75, 94, 223, 77, 192, 103, 115, 135, 214, 85, 157, 181, 253, 21,
+ 94, 76, 111, 27, 244, 55, 255, 90, 116, 116, 41, 189, 214, 29, 183,
+ 97, 168, 223, 42, 89, 21, 65, 44, 121, 118, 52, 129, 255, 92, 175,
+ 220, 152, 185, 186, 149, 59, 155, 187, 251, 173, 234, 172, 173, 49, 136,
+ 37, 177, 46, 252, 103, 115, 45, 78, 85, 100, 82, 155, 114, 103, 115,
+ 63, 184, 169, 244, 109, 39, 173, 204, 4, 140, 228, 63, 155, 91, 253,
+ 84, 21, 166, 214, 142, 40, 124, 54, 247, 235, 137, 25, 74, 186, 24,
+ 196, 146, 237, 201, 67, 5, 207, 230, 114, 251, 2, 44, 48, 125, 28,
+ 196, 18, 114, 191, 128, 200, 200, 10, 196, 18, 43, 16, 75, 172, 254,
+ 136, 37, 112, 190, 132, 98, 73, 36, 152, 227, 244, 35, 206, 230, 34,
+ 218, 9, 204, 113, 250, 17, 103, 115, 85, 177, 36, 12, 196, 18, 110,
+ 77, 120, 38, 152, 227, 84, 242, 158, 133, 207, 230, 86, 157, 161, 58,
+ 83, 216, 27, 204, 113, 6, 68, 112, 231, 17, 7, 139, 102, 136, 224,
+ 142, 188, 121, 162, 233, 184, 239, 123, 120, 54, 23, 207, 207, 147, 240,
+ 250, 51, 60, 155, 203, 55, 63, 23, 177, 247, 15, 181, 234, 27, 129,
+ 207, 230, 58, 95, 99, 105, 16, 75, 6, 12, 140, 20, 60, 155, 219,
+ 241, 127, 220, 217, 220, 235, 31, 209, 221, 199, 199, 233, 195, 85, 101,
+ 2, 231, 107, 179, 104, 235, 55, 145, 248, 108, 110, 215, 44, 180, 174,
+ 123, 154, 238, 187, 82, 104, 93, 247, 28, 125, 207, 42, 18, 159, 205,
+ 61, 248, 9, 157, 175, 189, 76, 47, 184, 38, 240, 59, 178, 96, 142,
+ 227, 145, 205, 157, 205, 157, 251, 62, 130, 181, 213, 77, 122, 191, 68,
+ 72, 223, 92, 250, 84, 17, 119, 54, 247, 98, 1, 119, 54, 247, 250,
+ 61, 254, 190, 70, 209, 15, 232, 252, 134, 220, 217, 220, 49, 243, 35,
+ 216, 115, 204, 79, 232, 71, 249, 252, 107, 254, 181, 65, 44, 249, 215,
+ 45, 28, 159, 205, 237, 192, 254, 222, 109, 125, 16, 75, 254, 110, 207,
+ 127, 102, 244, 49, 200, 75, 102, 47, 155, 133, 207, 230, 158, 106, 175,
+ 242, 171, 183, 32, 47, 177, 206, 153, 46, 112, 174, 247, 11, 93, 119,
+ 23, 119, 54, 183, 235, 180, 233, 248, 108, 238, 8, 55, 129, 243, 181,
+ 32, 47, 177, 252, 139, 59, 155, 59, 113, 33, 119, 54, 55, 227, 152,
+ 240, 217, 220, 65, 125, 185, 179, 185, 94, 155, 185, 179, 185, 67, 94,
+ 11, 159, 205, 109, 90, 97, 38, 62, 155, 107, 177, 69, 69, 155, 128,
+ 88, 82, 217, 113, 150, 84, 104, 142, 179, 32, 142, 59, 155, 107, 28,
+ 48, 155, 61, 3, 93, 157, 249, 89, 71, 248, 108, 46, 183, 239, 195,
+ 2, 211, 48, 47, 33, 247, 131, 136, 140, 102, 129, 88, 50, 11, 196,
+ 146, 89, 127, 238, 101, 119, 228, 106, 100, 158, 17, 129, 98, 73, 87,
+ 161, 26, 25, 119, 54, 87, 2, 250, 38, 118, 20, 174, 145, 193, 118,
+ 184, 126, 213, 137, 88, 139, 233, 104, 192, 181, 152, 78, 68, 253, 10,
+ 208, 80, 166, 50, 186, 68, 26, 112, 45, 134, 144, 1, 245, 70, 186,
+ 80, 145, 6, 92, 139, 233, 88, 102, 45, 134, 149, 145, 19, 97, 192,
+ 181, 152, 142, 129, 6, 93, 191, 132, 54, 54, 228, 250, 37, 21, 25,
+ 104, 208, 245, 75, 104, 59, 67, 174, 95, 66, 156, 224, 187, 133, 231,
+ 2, 63, 112, 20, 194, 12, 119, 54, 55, 39, 60, 80, 236, 57, 95,
+ 24, 51, 176, 29, 190, 147, 55, 156, 227, 175, 152, 103, 56, 204, 120,
+ 18, 50, 114, 192, 59, 229, 176, 114, 66, 230, 25, 14, 51, 144, 47,
+ 214, 3, 208, 88, 151, 121, 134, 195, 140, 231, 124, 117, 204, 64, 153,
+ 202, 181, 140, 185, 134, 195, 12, 180, 187, 33, 215, 47, 67, 230, 25,
+ 118, 253, 82, 52, 207, 176, 235, 151, 208, 118, 134, 92, 191, 132, 56,
+ 65, 152, 201, 153, 9, 252, 32, 66, 8, 51, 220, 217, 220, 248, 57,
+ 160, 239, 108, 97, 204, 192, 118, 248, 110, 225, 57, 28, 255, 196, 48,
+ 253, 48, 227, 89, 235, 43, 119, 183, 48, 33, 35, 30, 188, 83, 60,
+ 43, 199, 46, 76, 63, 204, 132, 121, 158, 193, 247, 164, 66, 190, 88,
+ 15, 64, 35, 93, 228, 179, 244, 195, 140, 229, 198, 57, 248, 247, 253,
+ 204, 103, 171, 99, 6, 202, 84, 234, 58, 75, 63, 204, 68, 79, 228,
+ 48, 3, 237, 174, 237, 172, 42, 180, 41, 199, 91, 243, 127, 127, 236,
+ 221, 226, 225, 7, 237, 87, 94, 126, 208, 158, 218, 248, 65, 91, 149,
+ 151, 159, 39, 15, 63, 104, 23, 93, 249, 33, 204, 64, 156, 224, 223,
+ 74, 153, 6, 232, 185, 2, 152, 33, 206, 230, 122, 130, 190, 57, 211,
+ 133, 49, 3, 219, 225, 49, 96, 6, 199, 223, 103, 186, 225, 198, 25,
+ 200, 23, 143, 1, 128, 134, 50, 149, 51, 131, 80, 195, 141, 51, 158,
+ 132, 12, 168, 55, 210, 69, 22, 106, 184, 113, 6, 242, 85, 251, 173,
+ 20, 86, 134, 121, 168, 225, 198, 25, 104, 119, 67, 142, 51, 208, 198,
+ 134, 28, 103, 100, 161, 134, 29, 103, 204, 67, 13, 59, 206, 40, 113,
+ 130, 246, 56, 4, 3, 63, 152, 41, 132, 25, 110, 15, 179, 57, 232,
+ 43, 153, 42, 140, 25, 216, 14, 143, 1, 33, 28, 255, 148, 41, 134,
+ 195, 12, 228, 139, 231, 26, 224, 157, 160, 76, 229, 92, 99, 138, 225,
+ 48, 3, 249, 226, 57, 19, 160, 145, 46, 57, 147, 13, 135, 25, 201,
+ 212, 50, 107, 254, 83, 85, 188, 125, 38, 27, 14, 51, 208, 238, 134,
+ 156, 207, 80, 83, 12, 59, 159, 129, 246, 52, 228, 124, 198, 103, 178,
+ 97, 231, 51, 16, 39, 24, 51, 19, 128, 31, 76, 211, 132, 153, 80,
+ 223, 41, 147, 102, 78, 86, 110, 250, 39, 190, 135, 15, 232, 171, 8,
+ 12, 20, 190, 3, 34, 152, 216, 247, 21, 196, 181, 151, 79, 10, 212,
+ 241, 60, 187, 169, 70, 63, 24, 113, 230, 73, 10, 222, 247, 21, 68,
+ 236, 251, 2, 52, 148, 169, 244, 185, 137, 129, 58, 158, 103, 215, 44,
+ 227, 88, 250, 90, 123, 172, 7, 33, 3, 234, 141, 116, 145, 5, 4,
+ 234, 120, 158, 93, 179, 12, 215, 253, 215, 113, 110, 6, 249, 170, 221,
+ 1, 193, 202, 240, 241, 15, 212, 241, 60, 187, 102, 25, 182, 7, 84,
+ 191, 189, 92, 196, 218, 221, 90, 217, 82, 117, 174, 8, 218, 17, 249,
+ 16, 162, 67, 29, 151, 208, 220, 115, 205, 113, 87, 209, 170, 62, 35,
+ 251, 22, 197, 254, 182, 114, 63, 6, 181, 175, 248, 221, 155, 9, 110,
+ 145, 196, 219, 183, 88, 236, 199, 188, 92, 94, 133, 253, 61, 244, 96,
+ 166, 176, 175, 175, 146, 174, 252, 121, 46, 211, 249, 112, 42, 239, 239,
+ 164, 255, 92, 24, 203, 28, 95, 60, 211, 70, 245, 116, 37, 166, 219,
+ 228, 175, 39, 158, 107, 31, 123, 138, 88, 191, 32, 109, 0, 191, 51,
+ 178, 1, 162, 161, 13, 184, 231, 218, 109, 208, 100, 102, 91, 7, 100,
+ 3, 212, 30, 218, 192, 117, 209, 40, 123, 33, 27, 204, 60, 124, 56,
+ 5, 217, 32, 54, 171, 118, 42, 178, 193, 145, 154, 147, 82, 133, 108,
+ 112, 194, 164, 233, 62, 100, 3, 68, 67, 27, 112, 207, 249, 109, 0,
+ 253, 22, 217, 224, 59, 176, 1, 244, 67, 100, 3, 68, 223, 234, 180,
+ 132, 230, 158, 107, 230, 39, 105, 89, 159, 73, 173, 49, 197, 13, 217,
+ 0, 181, 247, 1, 54, 184, 94, 146, 192, 219, 119, 45, 176, 193, 186,
+ 51, 165, 153, 200, 6, 63, 7, 171, 246, 181, 124, 253, 52, 151, 249,
+ 154, 185, 131, 119, 109, 241, 43, 176, 129, 255, 29, 159, 12, 100, 3,
+ 68, 183, 4, 54, 224, 158, 243, 219, 0, 226, 138, 244, 3, 136, 19,
+ 100, 3, 68, 67, 63, 224, 158, 107, 247, 131, 2, 92, 87, 239, 199,
+ 160, 246, 74, 63, 200, 227, 239, 11, 253, 32, 44, 44, 18, 255, 150,
+ 228, 213, 125, 42, 26, 250, 193, 149, 18, 254, 220, 7, 250, 1, 55,
+ 175, 88, 137, 105, 232, 7, 34, 129, 223, 131, 196, 99, 192, 4, 98,
+ 175, 164, 47, 136, 107, 193, 188, 99, 128, 131, 218, 24, 0, 250, 42,
+ 198, 233, 48, 6, 76, 32, 98, 231, 120, 174, 125, 200, 184, 64, 189,
+ 238, 52, 137, 153, 180, 192, 14, 199, 206, 241, 196, 24, 0, 104, 40,
+ 83, 217, 104, 92, 160, 94, 119, 154, 76, 72, 110, 159, 138, 245, 32,
+ 100, 64, 189, 145, 46, 241, 126, 129, 122, 221, 105, 114, 126, 113, 40,
+ 119, 63, 215, 184, 50, 99, 0, 43, 67, 226, 23, 168, 215, 157, 38,
+ 38, 43, 136, 123, 128, 198, 105, 159, 175, 66, 155, 150, 119, 254, 43,
+ 226, 225, 7, 237, 87, 94, 126, 208, 158, 218, 248, 65, 91, 149, 151,
+ 159, 132, 135, 31, 180, 75, 121, 231, 231, 16, 39, 120, 237, 100, 52,
+ 240, 131, 9, 188, 152, 233, 72, 98, 70, 2, 250, 74, 198, 10, 99,
+ 6, 182, 195, 243, 0, 31, 98, 237, 196, 71, 63, 204, 92, 75, 119,
+ 193, 254, 12, 249, 98, 25, 224, 157, 160, 76, 229, 124, 102, 140, 126,
+ 152, 89, 30, 249, 13, 231, 77, 144, 47, 158, 107, 0, 26, 233, 66,
+ 141, 209, 15, 51, 169, 55, 219, 225, 251, 230, 36, 99, 203, 204, 53,
+ 88, 251, 230, 140, 214, 15, 51, 207, 6, 19, 191, 151, 229, 163, 221,
+ 135, 160, 77, 203, 235, 147, 208, 198, 218, 248, 65, 251, 149, 151, 31,
+ 197, 195, 15, 218, 170, 188, 252, 160, 237, 180, 241, 131, 118, 41, 47,
+ 102, 32, 78, 240, 218, 201, 112, 224, 7, 190, 188, 152, 233, 68, 98,
+ 38, 103, 84, 160, 216, 115, 164, 48, 102, 96, 59, 92, 111, 26, 69,
+ 172, 157, 140, 208, 15, 51, 48, 175, 196, 245, 38, 66, 70, 14, 120,
+ 167, 28, 86, 78, 200, 8, 253, 48, 3, 243, 54, 172, 199, 72, 66,
+ 15, 64, 99, 93, 70, 232, 135, 25, 152, 23, 97, 61, 70, 150, 89,
+ 59, 97, 237, 27, 63, 92, 63, 204, 64, 159, 192, 107, 39, 35, 136,
+ 115, 44, 84, 7, 57, 151, 159, 203, 164, 136, 142, 79, 219, 79, 233,
+ 146, 183, 187, 176, 54, 38, 249, 113, 185, 174, 76, 138, 104, 200, 79,
+ 151, 28, 216, 133, 181, 39, 254, 205, 58, 186, 131, 156, 203, 27, 101,
+ 82, 68, 123, 2, 126, 186, 228, 147, 46, 172, 237, 200, 247, 227, 240,
+ 1, 255, 85, 209, 240, 253, 116, 205, 205, 32, 78, 240, 218, 137, 23,
+ 240, 131, 209, 188, 152, 113, 36, 49, 19, 63, 12, 244, 29, 42, 140,
+ 25, 216, 14, 175, 57, 12, 35, 214, 78, 134, 232, 135, 25, 114, 126,
+ 110, 78, 200, 136, 7, 239, 20, 207, 202, 177, 27, 162, 31, 102, 200,
+ 249, 57, 228, 139, 245, 0, 52, 210, 69, 238, 173, 31, 102, 200, 249,
+ 185, 249, 208, 50, 107, 39, 172, 125, 61, 189, 245, 195, 12, 154, 159,
+ 187, 176, 118, 199, 191, 203, 232, 35, 150, 135, 228, 118, 119, 44, 59,
+ 63, 239, 151, 184, 129, 90, 245, 35, 232, 176, 78, 107, 39, 101, 248,
+ 205, 152, 242, 219, 177, 236, 92, 23, 242, 75, 219, 106, 121, 68, 167,
+ 181, 19, 111, 98, 92, 248, 75, 44, 247, 218, 218, 205, 173, 236, 188,
+ 209, 243, 214, 6, 234, 95, 219, 20, 103, 157, 214, 78, 8, 126, 41,
+ 99, 197, 242, 42, 107, 162, 254, 152, 131, 237, 218, 190, 129, 10, 250,
+ 107, 142, 78, 53, 45, 136, 19, 124, 223, 156, 39, 160, 135, 243, 98,
+ 166, 51, 137, 25, 79, 208, 55, 103, 144, 48, 102, 96, 59, 60, 6,
+ 12, 38, 230, 51, 127, 233, 138, 153, 10, 90, 98, 39, 49, 150, 13,
+ 38, 198, 0, 64, 67, 153, 74, 127, 110, 172, 43, 102, 132, 101, 120,
+ 18, 50, 160, 222, 72, 23, 159, 70, 186, 98, 70, 7, 61, 6, 149,
+ 89, 59, 65, 246, 106, 168, 43, 102, 42, 240, 142, 51, 237, 140, 84,
+ 118, 183, 86, 182, 4, 152, 108, 211, 78, 174, 94, 87, 86, 253, 7,
+ 127, 75, 141, 47, 87, 129, 113, 87, 62, 176, 132, 138, 166, 87, 28,
+ 98, 51, 109, 26, 253, 127, 73, 158, 47, 13, 158, 119, 228, 235, 91,
+ 84, 59, 142, 254, 210, 137, 98, 177, 149, 132, 235, 103, 181, 95, 158,
+ 163, 199, 109, 11, 56, 204, 215, 247, 109, 189, 66, 122, 229, 194, 84,
+ 22, 127, 166, 204, 133, 201, 11, 148, 180, 73, 73, 37, 38, 253, 74,
+ 224, 17, 190, 190, 165, 38, 53, 24, 174, 86, 103, 129, 233, 144, 23,
+ 86, 140, 80, 13, 15, 217, 15, 250, 148, 161, 236, 215, 183, 81, 183,
+ 116, 77, 246, 3, 207, 59, 9, 217, 239, 253, 209, 98, 108, 63, 20,
+ 155, 160, 253, 46, 93, 174, 115, 68, 200, 126, 178, 69, 254, 71, 145,
+ 253, 190, 188, 183, 57, 138, 236, 215, 112, 162, 229, 81, 33, 251, 113,
+ 117, 62, 11, 76, 67, 251, 9, 213, 255, 144, 253, 32, 94, 144, 253,
+ 86, 104, 177, 223, 52, 29, 236, 183, 215, 179, 132, 26, 231, 114, 43,
+ 179, 172, 253, 154, 222, 243, 165, 31, 186, 243, 255, 182, 231, 133, 58,
+ 113, 180, 243, 221, 46, 110, 200, 126, 40, 22, 119, 252, 124, 142, 158,
+ 117, 224, 51, 239, 249, 153, 234, 245, 11, 233, 3, 123, 173, 78, 34,
+ 251, 117, 152, 116, 87, 185, 31, 249, 65, 133, 202, 204, 49, 251, 19,
+ 188, 251, 154, 39, 152, 214, 96, 184, 26, 161, 5, 166, 239, 23, 88,
+ 49, 66, 181, 67, 100, 63, 24, 11, 212, 253, 239, 207, 188, 73, 229,
+ 127, 252, 121, 19, 244, 191, 71, 183, 35, 165, 156, 253, 84, 237, 219,
+ 2, 255, 139, 183, 224, 239, 91, 217, 34, 142, 174, 184, 36, 10, 239,
+ 107, 70, 99, 207, 56, 224, 127, 179, 38, 205, 225, 223, 7, 106, 89,
+ 72, 23, 126, 24, 139, 247, 144, 54, 58, 31, 160, 164, 251, 1, 255,
+ 27, 226, 23, 200, 255, 91, 56, 192, 126, 92, 125, 209, 2, 211, 19,
+ 128, 255, 9, 213, 29, 241, 253, 77, 158, 220, 152, 71, 89, 130, 56,
+ 238, 197, 59, 230, 117, 37, 199, 188, 16, 208, 87, 86, 95, 120, 204,
+ 131, 237, 80, 28, 151, 53, 224, 218, 155, 215, 55, 220, 220, 10, 242,
+ 197, 99, 5, 160, 161, 76, 101, 46, 106, 101, 184, 185, 149, 136, 144,
+ 1, 245, 70, 186, 216, 89, 25, 110, 110, 5, 249, 146, 99, 158, 136,
+ 149, 33, 183, 52, 220, 220, 10, 218, 93, 223, 185, 149, 218, 25, 124,
+ 43, 253, 231, 86, 106, 121, 167, 149, 254, 115, 43, 181, 188, 211, 82,
+ 255, 185, 21, 153, 39, 66, 156, 32, 204, 136, 106, 5, 138, 139, 60,
+ 121, 49, 211, 141, 196, 140, 188, 94, 160, 152, 170, 43, 140, 25, 216,
+ 14, 249, 1, 85, 143, 107, 239, 89, 71, 87, 204, 152, 104, 244, 3,
+ 247, 71, 219, 241, 188, 135, 34, 100, 200, 193, 59, 201, 89, 57, 62,
+ 22, 186, 98, 70, 179, 140, 156, 254, 94, 105, 88, 143, 186, 132, 30,
+ 128, 70, 186, 132, 212, 214, 21, 51, 154, 101, 248, 72, 215, 226, 123,
+ 53, 168, 186, 234, 152, 145, 179, 246, 149, 213, 210, 21, 51, 154, 101,
+ 28, 174, 52, 83, 137, 153, 116, 214, 238, 214, 202, 150, 34, 209, 143,
+ 197, 77, 165, 208, 142, 200, 135, 16, 221, 243, 214, 110, 226, 185, 230,
+ 184, 155, 209, 40, 79, 106, 92, 247, 52, 106, 67, 189, 217, 115, 65,
+ 73, 59, 166, 140, 163, 190, 46, 123, 106, 207, 231, 127, 143, 90, 29,
+ 160, 56, 254, 10, 76, 59, 44, 52, 163, 133, 228, 34, 61, 224, 183,
+ 37, 245, 128, 223, 10, 233, 129, 104, 168, 7, 247, 92, 187, 30, 57,
+ 43, 34, 80, 27, 170, 223, 251, 232, 52, 164, 135, 91, 215, 117, 105,
+ 66, 122, 112, 252, 21, 152, 134, 122, 8, 201, 69, 122, 64, 255, 65,
+ 122, 44, 91, 217, 84, 10, 253, 1, 233, 129, 232, 43, 55, 119, 19,
+ 207, 181, 140, 191, 198, 121, 210, 133, 39, 83, 81, 27, 234, 68, 254,
+ 17, 37, 157, 249, 207, 56, 202, 104, 112, 78, 54, 159, 30, 121, 214,
+ 7, 40, 142, 191, 2, 211, 135, 22, 152, 209, 66, 114, 145, 30, 208,
+ 71, 145, 30, 219, 150, 52, 149, 66, 159, 67, 122, 32, 250, 76, 222,
+ 110, 226, 185, 102, 126, 222, 13, 242, 164, 147, 75, 167, 162, 54, 212,
+ 127, 141, 84, 244, 143, 3, 227, 40, 31, 121, 32, 111, 92, 219, 1,
+ 190, 7, 199, 95, 129, 233, 230, 224, 123, 8, 201, 69, 49, 17, 198,
+ 65, 124, 63, 87, 127, 128, 115, 75, 190, 152, 104, 111, 71, 198, 68,
+ 89, 205, 64, 113, 226, 64, 225, 152, 8, 219, 97, 156, 215, 36, 214,
+ 53, 6, 234, 151, 71, 60, 186, 102, 138, 99, 162, 136, 144, 33, 51,
+ 7, 99, 60, 43, 71, 62, 64, 191, 60, 194, 216, 246, 0, 94, 59,
+ 129, 124, 241, 218, 9, 124, 119, 86, 134, 231, 0, 253, 242, 136, 13,
+ 212, 39, 188, 22, 8, 249, 146, 49, 17, 202, 84, 126, 221, 254, 250,
+ 229, 17, 22, 118, 92, 189, 9, 218, 93, 91, 157, 31, 218, 180, 188,
+ 235, 6, 208, 198, 218, 248, 65, 251, 149, 151, 159, 39, 15, 63, 104,
+ 171, 242, 242, 131, 182, 211, 198, 15, 218, 165, 188, 235, 26, 16, 39,
+ 248, 126, 174, 222, 224, 187, 212, 226, 197, 140, 218, 30, 42, 69, 191,
+ 64, 177, 79, 95, 97, 204, 192, 118, 120, 109, 187, 31, 113, 63, 87,
+ 31, 195, 229, 222, 62, 132, 12, 5, 120, 39, 5, 43, 71, 214, 199,
+ 112, 185, 55, 228, 139, 245, 0, 52, 210, 197, 188, 143, 225, 114, 111,
+ 159, 190, 101, 238, 231, 98, 237, 155, 216, 219, 112, 185, 55, 180, 187,
+ 33, 215, 53, 100, 125, 12, 187, 174, 97, 222, 199, 176, 235, 26, 208,
+ 118, 134, 92, 215, 128, 56, 193, 251, 14, 123, 0, 63, 232, 207, 139,
+ 25, 181, 61, 39, 137, 189, 2, 197, 18, 15, 97, 204, 192, 118, 120,
+ 221, 185, 23, 177, 87, 215, 93, 63, 204, 236, 147, 89, 226, 49, 64,
+ 66, 200, 72, 4, 239, 148, 200, 202, 161, 220, 245, 195, 76, 161, 201,
+ 69, 110, 253, 220, 131, 208, 3, 208, 72, 151, 156, 158, 250, 97, 38,
+ 41, 185, 42, 183, 126, 238, 81, 102, 253, 156, 181, 175, 79, 79, 253,
+ 48, 179, 98, 115, 56, 183, 87, 215, 93, 123, 220, 133, 54, 45, 247,
+ 122, 55, 15, 63, 104, 191, 114, 175, 119, 247, 212, 206, 15, 218, 170,
+ 188, 252, 124, 120, 248, 65, 187, 148, 119, 156, 129, 56, 65, 152, 145,
+ 81, 192, 15, 122, 107, 192, 204, 4, 223, 80, 248, 195, 83, 51, 216,
+ 205, 186, 120, 15, 17, 232, 171, 96, 116, 216, 167, 213, 131, 24, 3,
+ 186, 19, 227, 12, 173, 223, 124, 245, 171, 127, 50, 183, 199, 181, 59,
+ 49, 6, 0, 26, 202, 84, 49, 208, 111, 190, 218, 212, 249, 45, 206,
+ 155, 124, 8, 25, 80, 111, 164, 139, 93, 13, 253, 230, 171, 143, 186,
+ 155, 74, 177, 30, 76, 153, 125, 90, 172, 12, 170, 186, 126, 243, 85,
+ 239, 38, 195, 240, 124, 21, 218, 29, 205, 43, 224, 254, 68, 104, 71,
+ 228, 55, 136, 30, 244, 247, 2, 154, 123, 174, 57, 238, 62, 76, 53,
+ 99, 102, 20, 61, 96, 219, 244, 99, 80, 251, 186, 111, 198, 51, 75,
+ 46, 173, 227, 237, 251, 125, 73, 20, 51, 117, 127, 33, 91, 123, 94,
+ 137, 233, 132, 211, 127, 19, 207, 249, 231, 71, 34, 66, 143, 111, 64,
+ 15, 248, 173, 144, 30, 136, 222, 4, 244, 224, 158, 107, 230, 183, 52,
+ 205, 140, 169, 61, 122, 1, 254, 221, 12, 212, 254, 9, 208, 99, 203,
+ 174, 16, 222, 190, 166, 75, 163, 152, 230, 14, 238, 110, 72, 15, 68,
+ 199, 3, 61, 184, 231, 252, 122, 64, 255, 65, 122, 124, 0, 122, 64,
+ 127, 192, 185, 50, 75, 215, 219, 178, 128, 230, 158, 107, 230, 151, 126,
+ 200, 140, 249, 247, 131, 20, 239, 23, 69, 237, 169, 119, 227, 153, 231,
+ 103, 242, 120, 223, 165, 30, 208, 195, 105, 177, 35, 254, 30, 136, 142,
+ 2, 122, 112, 207, 249, 245, 128, 62, 138, 235, 7, 64, 15, 232, 115,
+ 72, 15, 68, 143, 1, 223, 131, 123, 174, 153, 223, 79, 224, 87, 87,
+ 77, 123, 97, 61, 80, 251, 110, 224, 123, 4, 196, 143, 225, 223, 247,
+ 10, 252, 170, 75, 229, 121, 120, 239, 42, 162, 55, 0, 61, 184, 231,
+ 252, 121, 4, 140, 131, 184, 134, 87, 5, 224, 188, 7, 127, 76, 116,
+ 32, 235, 75, 102, 96, 126, 91, 77, 135, 26, 158, 25, 81, 251, 50,
+ 227, 218, 231, 84, 213, 47, 143, 200, 74, 94, 134, 199, 95, 138, 144,
+ 33, 7, 239, 36, 103, 229, 248, 84, 213, 47, 143, 24, 172, 136, 199,
+ 245, 53, 200, 23, 235, 1, 104, 164, 75, 81, 21, 253, 242, 136, 152,
+ 167, 117, 113, 76, 164, 170, 149, 169, 225, 177, 246, 149, 85, 209, 47,
+ 143, 216, 188, 191, 19, 206, 35, 160, 221, 181, 141, 171, 208, 166, 229,
+ 30, 167, 121, 248, 65, 251, 149, 151, 31, 180, 167, 214, 189, 181, 192,
+ 86, 229, 229, 39, 227, 225, 7, 237, 82, 222, 60, 2, 226, 4, 255,
+ 110, 65, 133, 64, 49, 196, 16, 31, 102, 58, 146, 245, 135, 202, 160,
+ 109, 37, 29, 106, 60, 149, 9, 63, 168, 204, 181, 143, 23, 235, 135,
+ 25, 89, 225, 255, 48, 102, 68, 132, 12, 25, 120, 39, 25, 43, 71,
+ 34, 214, 15, 51, 155, 54, 137, 79, 98, 61, 42, 17, 122, 64, 189,
+ 89, 25, 41, 21, 245, 195, 204, 3, 207, 35, 156, 30, 149, 202, 212,
+ 120, 88, 251, 82, 21, 245, 195, 76, 252, 137, 86, 24, 51, 208, 238,
+ 218, 124, 8, 218, 180, 188, 62, 41, 225, 225, 7, 237, 87, 94, 126,
+ 208, 158, 218, 248, 65, 91, 149, 123, 110, 192, 195, 15, 218, 165, 188,
+ 152, 129, 56, 193, 185, 183, 17, 248, 46, 85, 248, 49, 211, 137, 144,
+ 77, 129, 190, 114, 19, 97, 204, 192, 118, 120, 12, 48, 37, 214, 138,
+ 76, 244, 195, 204, 191, 189, 250, 98, 95, 131, 124, 241, 24, 0, 104,
+ 40, 83, 89, 35, 49, 214, 15, 51, 37, 155, 190, 227, 252, 158, 34,
+ 100, 64, 189, 145, 46, 33, 198, 250, 97, 166, 198, 254, 255, 112, 126,
+ 15, 249, 146, 152, 161, 144, 189, 140, 245, 195, 76, 147, 248, 48, 140,
+ 25, 104, 119, 109, 62, 4, 109, 170, 139, 15, 145, 53, 20, 104, 99,
+ 109, 252, 160, 253, 202, 203, 47, 132, 135, 31, 180, 85, 121, 249, 137,
+ 120, 248, 65, 187, 232, 202, 15, 231, 102, 70, 68, 141, 167, 29, 240,
+ 131, 10, 252, 152, 113, 36, 101, 131, 190, 146, 14, 194, 152, 129, 237,
+ 240, 24, 32, 34, 106, 60, 182, 250, 97, 134, 156, 175, 66, 190, 184,
+ 198, 3, 223, 201, 136, 141, 207, 182, 250, 97, 134, 156, 175, 66, 190,
+ 184, 198, 3, 104, 164, 75, 78, 123, 253, 48, 67, 206, 87, 37, 29,
+ 202, 212, 120, 88, 251, 250, 180, 215, 15, 51, 104, 190, 234, 194, 218,
+ 29, 249, 80, 142, 175, 88, 222, 114, 235, 138, 63, 230, 171, 223, 35,
+ 79, 82, 59, 102, 228, 185, 234, 20, 199, 9, 126, 149, 198, 137, 229,
+ 3, 91, 159, 251, 99, 222, 24, 15, 248, 85, 221, 87, 55, 91, 167,
+ 26, 79, 123, 142, 159, 221, 26, 177, 60, 226, 86, 190, 91, 217, 249,
+ 219, 217, 169, 39, 169, 61, 63, 90, 73, 117, 202, 29, 9, 126, 150,
+ 19, 196, 242, 255, 242, 199, 252, 49, 143, 122, 22, 113, 146, 138, 24,
+ 214, 95, 183, 243, 216, 237, 8, 204, 88, 3, 63, 48, 226, 199, 76,
+ 103, 178, 254, 0, 250, 42, 218, 234, 80, 227, 105, 71, 212, 70, 108,
+ 136, 243, 216, 109, 244, 59, 143, 173, 182, 94, 97, 67, 212, 120, 0,
+ 13, 101, 42, 125, 174, 181, 126, 231, 177, 213, 244, 32, 100, 64, 189,
+ 145, 46, 178, 86, 250, 157, 199, 86, 211, 163, 109, 153, 26, 15, 43,
+ 195, 167, 165, 126, 231, 177, 209, 90, 66, 17, 107, 119, 116, 6, 53,
+ 78, 203, 222, 193, 1, 58, 236, 29, 172, 232, 89, 66, 45, 202, 247,
+ 255, 99, 239, 224, 140, 60, 95, 250, 224, 3, 127, 222, 186, 192, 249,
+ 218, 113, 116, 141, 84, 132, 213, 36, 92, 79, 26, 84, 114, 157, 54,
+ 9, 203, 227, 173, 15, 173, 168, 37, 98, 184, 250, 147, 5, 166, 79,
+ 109, 177, 97, 132, 234, 82, 248, 60, 118, 107, 206, 6, 43, 181, 216,
+ 96, 164, 14, 54, 240, 0, 54, 72, 76, 77, 116, 41, 107, 131, 51,
+ 192, 6, 75, 210, 19, 121, 239, 37, 217, 10, 108, 176, 157, 57, 135,
+ 239, 91, 71, 241, 165, 43, 176, 65, 250, 254, 186, 188, 251, 0, 150,
+ 1, 27, 112, 181, 43, 11, 76, 67, 27, 8, 213, 180, 240, 121, 236,
+ 86, 156, 13, 70, 107, 177, 193, 248, 52, 97, 27, 56, 140, 40, 161,
+ 236, 141, 15, 101, 149, 181, 193, 141, 103, 190, 244, 114, 230, 16, 239,
+ 247, 216, 104, 22, 71, 159, 255, 144, 143, 247, 144, 162, 152, 232, 246,
+ 253, 58, 189, 252, 103, 43, 222, 154, 140, 4, 216, 128, 171, 123, 89,
+ 96, 58, 19, 216, 64, 168, 30, 134, 207, 99, 183, 228, 108, 176, 66,
+ 203, 62, 208, 80, 29, 246, 129, 30, 2, 126, 48, 220, 39, 230, 143,
+ 125, 160, 189, 238, 250, 210, 117, 164, 252, 123, 57, 71, 3, 63, 8,
+ 184, 51, 6, 239, 3, 69, 113, 188, 26, 240, 131, 162, 161, 253, 121,
+ 251, 198, 2, 27, 112, 53, 51, 11, 76, 67, 63, 16, 170, 165, 225,
+ 49, 192, 154, 56, 143, 221, 20, 196, 181, 118, 252, 99, 64, 87, 50,
+ 62, 129, 190, 138, 230, 58, 140, 1, 214, 68, 236, 108, 65, 156, 95,
+ 104, 174, 95, 222, 4, 235, 193, 56, 118, 182, 32, 198, 0, 64, 67,
+ 153, 202, 70, 205, 245, 203, 155, 96, 173, 22, 235, 65, 200, 128, 122,
+ 35, 93, 226, 155, 233, 151, 55, 193, 58, 42, 214, 163, 121, 153, 49,
+ 128, 149, 33, 105, 166, 95, 222, 4, 107, 156, 56, 151, 111, 206, 229,
+ 17, 241, 62, 187, 229, 92, 93, 93, 38, 69, 180, 220, 162, 34, 205,
+ 87, 111, 87, 59, 143, 77, 240, 147, 249, 238, 150, 115, 245, 109, 153,
+ 20, 209, 150, 128, 31, 95, 221, 91, 237, 60, 118, 51, 142, 31, 53,
+ 110, 183, 156, 171, 51, 203, 164, 136, 126, 89, 171, 34, 205, 87, 127,
+ 86, 171, 31, 16, 252, 82, 128, 190, 92, 189, 87, 38, 69, 116, 18,
+ 120, 63, 190, 58, 176, 218, 121, 236, 166, 68, 77, 43, 7, 248, 129,
+ 53, 63, 102, 186, 17, 223, 67, 2, 250, 74, 62, 232, 112, 30, 187,
+ 41, 49, 15, 144, 16, 251, 150, 100, 122, 238, 91, 90, 83, 11, 207,
+ 53, 32, 95, 44, 3, 240, 133, 50, 149, 243, 153, 34, 253, 48, 179,
+ 181, 225, 99, 78, 134, 140, 152, 107, 0, 189, 145, 46, 84, 145, 126,
+ 152, 241, 120, 189, 158, 187, 251, 233, 67, 153, 185, 6, 107, 35, 234,
+ 134, 126, 152, 153, 229, 74, 236, 91, 146, 241, 236, 91, 2, 54, 45,
+ 239, 252, 23, 218, 88, 27, 63, 104, 191, 242, 242, 163, 120, 248, 65,
+ 91, 149, 155, 223, 13, 237, 252, 160, 93, 202, 59, 63, 135, 56, 65,
+ 152, 9, 145, 4, 137, 19, 155, 242, 98, 70, 185, 217, 15, 215, 91,
+ 64, 95, 74, 161, 67, 77, 43, 135, 168, 55, 61, 38, 206, 99, 167,
+ 234, 135, 153, 108, 199, 5, 220, 218, 201, 99, 162, 222, 4, 222, 9,
+ 202, 84, 142, 101, 169, 250, 97, 230, 212, 241, 177, 120, 12, 128, 124,
+ 177, 30, 80, 6, 210, 37, 85, 207, 113, 102, 103, 33, 167, 135, 162,
+ 204, 218, 9, 107, 223, 248, 20, 253, 48, 51, 33, 117, 56, 119, 30,
+ 59, 85, 187, 15, 65, 155, 150, 183, 206, 26, 194, 195, 15, 218, 175,
+ 188, 252, 68, 60, 252, 160, 173, 202, 203, 15, 218, 78, 235, 189, 36,
+ 192, 46, 229, 173, 3, 67, 156, 224, 123, 57, 69, 65, 98, 121, 14,
+ 63, 102, 200, 61, 24, 137, 118, 160, 175, 81, 144, 240, 190, 37, 208,
+ 14, 255, 86, 178, 57, 215, 222, 211, 55, 72, 175, 61, 24, 100, 110,
+ 6, 249, 226, 223, 124, 6, 52, 148, 169, 204, 109, 124, 130, 244, 218,
+ 131, 65, 230, 102, 118, 132, 12, 168, 55, 210, 69, 70, 7, 233, 181,
+ 7, 131, 204, 205, 32, 95, 181, 223, 124, 102, 101, 196, 83, 65, 122,
+ 237, 193, 64, 185, 89, 58, 107, 119, 188, 230, 223, 35, 214, 77, 83,
+ 110, 86, 117, 207, 117, 169, 208, 94, 8, 207, 239, 245, 168, 115, 174,
+ 173, 88, 31, 166, 168, 21, 107, 157, 148, 244, 209, 235, 155, 169, 6,
+ 99, 103, 240, 230, 97, 45, 219, 63, 163, 56, 254, 230, 56, 15, 28,
+ 20, 212, 145, 214, 117, 15, 6, 252, 182, 72, 15, 151, 150, 177, 110,
+ 154, 114, 194, 46, 7, 175, 75, 133, 246, 66, 28, 104, 96, 73, 37,
+ 44, 104, 138, 245, 184, 62, 182, 161, 146, 110, 148, 179, 153, 170, 243,
+ 169, 26, 175, 30, 73, 29, 158, 81, 28, 127, 115, 156, 127, 46, 11,
+ 238, 72, 235, 186, 7, 3, 250, 15, 210, 99, 238, 224, 88, 55, 77,
+ 185, 104, 215, 127, 175, 75, 133, 246, 66, 108, 127, 81, 143, 154, 119,
+ 195, 14, 235, 113, 184, 66, 47, 37, 29, 7, 190, 135, 113, 98, 44,
+ 175, 30, 63, 108, 158, 81, 28, 127, 115, 156, 247, 158, 12, 236, 72,
+ 235, 186, 7, 3, 250, 40, 210, 163, 158, 117, 172, 155, 166, 28, 56,
+ 44, 245, 186, 84, 104, 47, 132, 125, 35, 75, 202, 51, 18, 253, 78,
+ 5, 69, 197, 175, 85, 253, 222, 69, 51, 240, 61, 34, 111, 133, 240,
+ 230, 207, 167, 192, 247, 224, 248, 155, 227, 124, 123, 61, 248, 30, 186,
+ 238, 193, 128, 113, 16, 197, 196, 20, 81, 176, 24, 198, 72, 190, 152,
+ 72, 238, 193, 144, 229, 4, 137, 139, 140, 131, 133, 215, 147, 115, 136,
+ 152, 168, 224, 248, 203, 52, 244, 45, 87, 157, 63, 221, 7, 231, 197,
+ 144, 47, 142, 137, 128, 134, 50, 149, 86, 209, 73, 134, 246, 60, 98,
+ 233, 254, 48, 44, 195, 142, 144, 1, 245, 70, 186, 36, 26, 5, 235,
+ 149, 71, 28, 9, 251, 136, 215, 18, 32, 95, 181, 152, 200, 202, 176,
+ 211, 73, 134, 246, 60, 226, 248, 16, 110, 47, 39, 180, 187, 182, 113,
+ 21, 218, 180, 188, 227, 180, 57, 15, 63, 104, 191, 242, 242, 131, 246,
+ 212, 198, 15, 218, 170, 188, 252, 236, 120, 248, 65, 187, 148, 55, 143,
+ 128, 56, 193, 231, 108, 250, 4, 139, 33, 134, 52, 98, 38, 116, 82,
+ 192, 68, 118, 51, 39, 254, 158, 160, 111, 226, 0, 97, 204, 192, 118,
+ 220, 249, 20, 174, 125, 74, 255, 96, 189, 242, 8, 133, 127, 50, 113,
+ 62, 133, 147, 33, 1, 52, 148, 169, 204, 93, 251, 5, 235, 149, 71,
+ 4, 56, 191, 197, 152, 145, 16, 50, 160, 222, 72, 151, 156, 190, 193,
+ 122, 229, 17, 15, 137, 181, 49, 200, 87, 237, 183, 87, 88, 25, 138,
+ 62, 193, 122, 229, 17, 94, 196, 94, 78, 104, 119, 114, 47, 39, 180,
+ 35, 242, 27, 68, 123, 254, 189, 128, 230, 158, 107, 142, 187, 247, 82,
+ 205, 152, 93, 209, 203, 216, 54, 253, 24, 212, 190, 214, 155, 241, 76,
+ 251, 211, 71, 120, 251, 194, 189, 156, 159, 198, 162, 122, 244, 74, 76,
+ 195, 189, 156, 220, 115, 254, 113, 11, 126, 91, 82, 15, 248, 173, 144,
+ 30, 136, 246, 2, 122, 112, 207, 53, 243, 83, 0, 61, 250, 159, 173,
+ 131, 239, 13, 69, 237, 173, 128, 30, 251, 7, 222, 18, 220, 147, 122,
+ 112, 80, 63, 87, 164, 7, 162, 161, 30, 220, 115, 126, 61, 160, 255,
+ 32, 61, 190, 0, 61, 30, 18, 123, 57, 17, 125, 22, 232, 241, 80,
+ 160, 118, 253, 46, 205, 140, 105, 117, 219, 30, 239, 129, 68, 237, 135,
+ 190, 29, 207, 56, 154, 63, 227, 205, 105, 170, 44, 141, 98, 190, 92,
+ 172, 128, 247, 164, 34, 122, 25, 208, 131, 123, 206, 175, 7, 244, 81,
+ 242, 123, 120, 17, 123, 57, 17, 61, 22, 232, 225, 37, 80, 127, 46,
+ 1, 223, 99, 78, 170, 7, 214, 3, 181, 119, 2, 223, 227, 68, 170,
+ 240, 94, 206, 7, 89, 220, 94, 78, 68, 195, 189, 156, 220, 115, 254,
+ 60, 2, 198, 65, 124, 142, 202, 29, 140, 141, 162, 96, 254, 152, 232,
+ 64, 156, 241, 233, 29, 44, 246, 233, 37, 28, 19, 97, 59, 92, 147,
+ 238, 205, 181, 47, 242, 208, 47, 143, 232, 221, 105, 30, 254, 173, 115,
+ 31, 66, 134, 2, 188, 147, 130, 149, 35, 243, 208, 47, 143, 120, 92,
+ 181, 29, 222, 203, 9, 249, 98, 61, 0, 141, 116, 49, 247, 208, 47,
+ 143, 88, 166, 216, 197, 213, 214, 123, 169, 199, 68, 5, 107, 223, 68,
+ 119, 253, 242, 136, 245, 49, 83, 184, 115, 84, 30, 218, 199, 85, 104,
+ 211, 242, 142, 211, 50, 30, 126, 208, 126, 229, 206, 75, 120, 248, 65,
+ 91, 149, 59, 47, 113, 215, 206, 15, 218, 165, 188, 121, 4, 196, 9,
+ 222, 47, 64, 3, 63, 232, 35, 128, 153, 142, 68, 61, 162, 103, 176,
+ 88, 210, 67, 24, 51, 176, 29, 30, 227, 123, 18, 121, 68, 119, 253,
+ 48, 115, 183, 105, 12, 246, 103, 9, 33, 35, 17, 188, 83, 34, 43,
+ 135, 234, 174, 31, 102, 206, 116, 120, 135, 253, 25, 242, 197, 122, 0,
+ 26, 233, 146, 195, 232, 135, 25, 199, 119, 151, 185, 115, 84, 61, 212,
+ 49, 147, 200, 218, 215, 135, 209, 15, 51, 89, 199, 164, 220, 30, 155,
+ 238, 218, 125, 8, 218, 180, 188, 62, 73, 241, 240, 131, 246, 43, 47,
+ 63, 104, 79, 109, 252, 160, 173, 202, 203, 207, 135, 135, 31, 180, 75,
+ 121, 49, 3, 113, 130, 115, 111, 87, 224, 7, 238, 2, 152, 233, 68,
+ 172, 253, 129, 190, 137, 82, 97, 204, 192, 118, 120, 12, 160, 184, 246,
+ 118, 82, 253, 48, 19, 186, 182, 18, 55, 6, 80, 196, 24, 0, 104,
+ 40, 83, 153, 123, 187, 233, 135, 153, 243, 117, 55, 114, 231, 168, 8,
+ 25, 80, 111, 164, 139, 167, 155, 126, 152, 73, 108, 31, 200, 205, 33,
+ 164, 234, 152, 241, 97, 101, 40, 92, 245, 195, 140, 223, 26, 226, 238,
+ 94, 169, 118, 31, 130, 54, 45, 239, 90, 12, 180, 177, 214, 251, 169,
+ 129, 253, 202, 203, 207, 147, 135, 31, 180, 85, 121, 249, 65, 219, 105,
+ 227, 7, 237, 82, 222, 181, 34, 136, 19, 156, 155, 117, 3, 126, 64,
+ 11, 96, 198, 145, 200, 27, 92, 128, 111, 58, 235, 144, 155, 185, 16,
+ 254, 236, 66, 228, 102, 78, 250, 97, 134, 156, 175, 250, 16, 50, 20,
+ 224, 157, 20, 172, 28, 153, 147, 126, 152, 33, 231, 171, 144, 47, 214,
+ 3, 208, 72, 23, 115, 39, 253, 48, 67, 206, 87, 125, 156, 203, 228,
+ 102, 172, 125, 19, 187, 233, 135, 25, 47, 98, 47, 39, 180, 59, 185,
+ 151, 211, 98, 235, 138, 63, 230, 171, 112, 47, 103, 236, 140, 188, 44,
+ 157, 114, 51, 130, 31, 220, 203, 185, 164, 245, 185, 63, 230, 141, 112,
+ 47, 103, 215, 125, 117, 117, 218, 147, 96, 78, 240, 131, 123, 57, 195,
+ 137, 189, 156, 15, 137, 189, 156, 73, 58, 238, 229, 132, 182, 35, 247,
+ 114, 222, 36, 246, 114, 122, 17, 123, 57, 195, 117, 220, 203, 9, 113,
+ 130, 49, 227, 0, 252, 192, 85, 0, 51, 157, 137, 188, 161, 43, 24,
+ 151, 186, 232, 144, 155, 117, 37, 114, 154, 174, 68, 251, 206, 193, 6,
+ 219, 203, 41, 33, 100, 36, 130, 119, 74, 100, 229, 40, 58, 5, 27,
+ 108, 47, 39, 228, 139, 245, 0, 52, 210, 69, 222, 49, 216, 96, 123,
+ 57, 37, 93, 202, 228, 102, 172, 125, 19, 29, 130, 13, 182, 151, 19,
+ 218, 221, 80, 123, 57, 39, 229, 251, 255, 177, 143, 17, 238, 229, 92,
+ 245, 192, 159, 119, 31, 35, 220, 203, 89, 154, 178, 2, 239, 99, 68,
+ 88, 133, 123, 57, 95, 204, 202, 227, 173, 241, 192, 189, 156, 92, 253,
+ 201, 2, 211, 112, 255, 154, 80, 93, 10, 217, 0, 250, 133, 161, 246,
+ 114, 94, 79, 77, 252, 99, 63, 43, 220, 203, 153, 145, 158, 200, 187,
+ 198, 2, 247, 114, 222, 103, 206, 225, 253, 172, 40, 190, 192, 189, 156,
+ 138, 253, 117, 121, 235, 42, 112, 47, 39, 87, 187, 178, 192, 52, 180,
+ 129, 80, 77, 11, 239, 233, 237, 24, 108, 176, 189, 156, 29, 180, 236,
+ 229, 92, 166, 195, 94, 206, 115, 196, 94, 206, 135, 196, 94, 206, 101,
+ 58, 236, 229, 124, 72, 236, 229, 124, 72, 236, 229, 124, 168, 227, 94,
+ 78, 136, 171, 255, 31, 246, 114, 250, 19, 123, 57, 189, 136, 189, 156,
+ 239, 116, 216, 203, 233, 69, 236, 229, 244, 34, 246, 114, 122, 233, 184,
+ 151, 19, 198, 125, 124, 127, 251, 104, 16, 215, 186, 9, 140, 1, 93,
+ 137, 248, 100, 15, 98, 237, 88, 29, 198, 0, 123, 34, 118, 218, 19,
+ 115, 13, 59, 253, 242, 38, 88, 15, 198, 177, 147, 144, 145, 8, 248,
+ 38, 178, 114, 236, 198, 234, 151, 55, 193, 90, 45, 183, 239, 129, 144,
+ 1, 248, 34, 93, 228, 99, 244, 203, 155, 96, 29, 149, 251, 45, 146,
+ 50, 99, 0, 107, 35, 207, 49, 250, 229, 77, 176, 198, 137, 231, 26,
+ 118, 193, 196, 125, 235, 187, 229, 92, 93, 93, 38, 69, 244, 69, 139,
+ 138, 52, 95, 189, 93, 109, 237, 105, 108, 176, 218, 222, 80, 174, 190,
+ 45, 147, 34, 26, 238, 13, 229, 171, 123, 171, 221, 207, 53, 134, 227,
+ 103, 238, 183, 91, 206, 213, 153, 101, 82, 68, 167, 212, 174, 72, 243,
+ 213, 159, 213, 238, 231, 34, 248, 193, 189, 156, 92, 189, 87, 38, 69,
+ 52, 220, 203, 201, 87, 7, 86, 187, 191, 125, 52, 135, 153, 248, 225,
+ 192, 15, 28, 4, 48, 211, 141, 184, 91, 28, 244, 205, 25, 41, 140,
+ 25, 216, 14, 223, 123, 62, 138, 107, 239, 51, 82, 63, 204, 148, 100,
+ 54, 200, 226, 126, 139, 36, 152, 248, 45, 146, 96, 49, 148, 169, 156,
+ 207, 140, 208, 15, 51, 197, 15, 189, 178, 185, 223, 34, 33, 244, 0,
+ 239, 142, 116, 145, 141, 208, 15, 51, 84, 158, 59, 167, 199, 72, 117,
+ 204, 120, 178, 50, 204, 71, 232, 135, 153, 171, 47, 231, 112, 191, 125,
+ 59, 82, 251, 124, 21, 218, 180, 188, 243, 95, 104, 99, 109, 252, 160,
+ 253, 202, 203, 79, 198, 195, 15, 218, 170, 188, 252, 204, 121, 248, 65,
+ 187, 148, 119, 126, 14, 113, 130, 127, 143, 202, 27, 248, 193, 104, 126,
+ 204, 192, 205, 156, 248, 183, 111, 65, 223, 248, 161, 194, 152, 129, 237,
+ 240, 111, 120, 12, 227, 218, 75, 134, 234, 135, 153, 230, 138, 219, 89,
+ 220, 111, 145, 4, 19, 191, 69, 2, 116, 26, 174, 226, 157, 50, 68,
+ 63, 204, 156, 43, 110, 146, 197, 253, 22, 9, 161, 7, 120, 119, 164,
+ 11, 53, 68, 63, 204, 212, 59, 158, 229, 198, 253, 22, 137, 58, 102,
+ 204, 89, 25, 57, 222, 250, 97, 102, 67, 149, 96, 140, 25, 104, 119,
+ 109, 62, 4, 109, 90, 222, 58, 43, 180, 177, 54, 126, 208, 126, 229,
+ 174, 43, 243, 240, 131, 182, 42, 119, 93, 217, 91, 59, 63, 104, 151,
+ 242, 214, 129, 33, 78, 240, 190, 165, 8, 224, 7, 195, 5, 48, 67,
+ 236, 193, 200, 241, 2, 241, 124, 176, 48, 102, 96, 59, 60, 6, 120,
+ 17, 227, 204, 32, 253, 246, 96, 144, 185, 153, 39, 33, 35, 7, 188,
+ 83, 14, 43, 39, 228, 47, 253, 246, 96, 144, 185, 25, 228, 203, 253,
+ 22, 9, 208, 157, 149, 33, 243, 212, 111, 15, 6, 153, 155, 121, 14,
+ 86, 199, 76, 14, 107, 95, 187, 72, 253, 246, 96, 160, 220, 44, 157,
+ 181, 59, 90, 43, 111, 238, 24, 235, 166, 41, 55, 171, 149, 121, 93,
+ 42, 180, 23, 226, 98, 85, 75, 74, 116, 106, 4, 59, 142, 80, 84,
+ 230, 165, 137, 74, 250, 197, 245, 205, 84, 175, 128, 37, 188, 103, 145,
+ 131, 109, 159, 81, 28, 127, 115, 156, 7, 126, 8, 234, 72, 235, 186,
+ 7, 3, 126, 91, 164, 199, 246, 14, 177, 110, 154, 114, 66, 199, 172,
+ 235, 82, 161, 189, 16, 29, 106, 89, 82, 135, 110, 254, 204, 68, 122,
+ 84, 114, 106, 167, 148, 95, 12, 244, 248, 17, 190, 153, 55, 63, 85,
+ 0, 61, 56, 254, 230, 56, 255, 108, 27, 220, 145, 214, 117, 15, 6,
+ 244, 31, 164, 71, 146, 67, 172, 155, 166, 92, 116, 45, 248, 30, 66,
+ 123, 33, 246, 86, 183, 164, 106, 143, 246, 195, 123, 57, 127, 14, 155,
+ 170, 164, 223, 3, 61, 30, 55, 90, 198, 155, 199, 38, 2, 61, 56,
+ 254, 230, 56, 239, 173, 10, 244, 208, 117, 15, 6, 244, 81, 164, 135,
+ 168, 101, 172, 155, 166, 28, 184, 231, 201, 235, 82, 161, 189, 16, 254,
+ 141, 44, 169, 102, 191, 67, 241, 94, 206, 150, 231, 166, 41, 233, 198,
+ 57, 155, 169, 201, 245, 166, 240, 230, 207, 251, 59, 60, 163, 56, 254,
+ 230, 56, 223, 94, 1, 244, 208, 117, 15, 6, 140, 131, 248, 76, 200,
+ 92, 128, 115, 111, 129, 152, 72, 236, 193, 176, 3, 125, 83, 230, 235,
+ 176, 47, 45, 130, 195, 121, 74, 56, 215, 158, 154, 175, 95, 30, 177,
+ 33, 203, 18, 231, 197, 144, 47, 222, 203, 9, 104, 40, 83, 25, 83,
+ 230, 233, 151, 71, 188, 173, 181, 19, 199, 93, 59, 66, 6, 212, 27,
+ 233, 226, 51, 79, 191, 60, 98, 113, 238, 75, 44, 3, 242, 85, 219,
+ 203, 201, 202, 40, 154, 171, 95, 30, 225, 182, 125, 46, 206, 35, 160,
+ 221, 181, 142, 171, 192, 166, 229, 30, 167, 231, 105, 231, 7, 237, 87,
+ 238, 245, 95, 30, 126, 208, 86, 229, 229, 7, 109, 167, 141, 31, 180,
+ 75, 121, 243, 8, 136, 19, 140, 153, 233, 192, 15, 34, 52, 96, 198,
+ 127, 194, 228, 153, 196, 205, 156, 72, 118, 209, 156, 96, 113, 200, 236,
+ 96, 177, 191, 127, 75, 185, 191, 127, 51, 230, 68, 252, 130, 236, 206,
+ 61, 227, 165, 101, 49, 3, 219, 33, 63, 8, 153, 195, 241, 247, 12,
+ 211, 228, 7, 240, 221, 45, 152, 221, 173, 26, 102, 190, 19, 253, 112,
+ 229, 171, 243, 127, 165, 151, 225, 49, 62, 132, 144, 81, 4, 222, 169,
+ 136, 149, 99, 55, 75, 187, 12, 143, 234, 21, 50, 31, 205, 173, 237,
+ 198, 87, 231, 95, 253, 239, 18, 44, 3, 242, 197, 122, 0, 26, 233,
+ 98, 62, 83, 187, 140, 47, 61, 46, 103, 30, 107, 83, 81, 202, 87,
+ 231, 191, 120, 115, 50, 206, 35, 66, 102, 171, 99, 6, 202, 84, 254,
+ 59, 157, 71, 198, 73, 47, 233, 248, 16, 153, 148, 175, 206, 223, 255,
+ 74, 24, 174, 243, 67, 187, 147, 191, 27, 14, 237, 136, 248, 33, 90,
+ 121, 47, 39, 126, 46, 18, 173, 17, 181, 17, 237, 22, 217, 136, 246,
+ 138, 218, 225, 184, 251, 32, 213, 140, 9, 111, 126, 130, 187, 151, 147,
+ 109, 111, 246, 121, 4, 211, 123, 113, 36, 239, 24, 250, 181, 234, 100,
+ 38, 236, 107, 7, 182, 205, 124, 38, 231, 157, 137, 146, 54, 41, 137,
+ 102, 206, 183, 190, 198, 91, 31, 47, 53, 89, 194, 200, 54, 206, 195,
+ 119, 72, 34, 58, 228, 197, 26, 226, 57, 127, 125, 23, 250, 5, 105,
+ 3, 248, 157, 145, 13, 16, 61, 24, 216, 128, 123, 174, 217, 6, 143,
+ 224, 126, 214, 12, 57, 182, 1, 106, 95, 29, 216, 64, 252, 112, 182,
+ 160, 13, 58, 15, 107, 140, 109, 224, 61, 249, 63, 23, 100, 131, 237,
+ 212, 10, 65, 27, 68, 244, 219, 234, 140, 108, 128, 232, 105, 192, 6,
+ 220, 115, 126, 27, 64, 191, 69, 54, 248, 14, 108, 0, 253, 16, 217,
+ 0, 209, 211, 129, 13, 184, 231, 208, 6, 118, 192, 6, 221, 128, 13,
+ 156, 48, 191, 246, 105, 102, 140, 171, 243, 30, 188, 23, 22, 181, 239,
+ 1, 108, 32, 218, 235, 205, 155, 131, 124, 6, 54, 24, 48, 214, 196,
+ 13, 217, 224, 242, 195, 93, 74, 123, 252, 254, 25, 205, 120, 187, 121,
+ 184, 10, 217, 192, 204, 99, 141, 19, 178, 1, 162, 161, 13, 184, 231,
+ 252, 54, 128, 184, 34, 253, 0, 226, 4, 217, 0, 209, 127, 1, 27,
+ 112, 207, 161, 13, 194, 128, 13, 102, 2, 27, 204, 192, 252, 242, 129,
+ 31, 228, 62, 8, 197, 251, 79, 81, 251, 170, 192, 6, 213, 139, 103,
+ 243, 230, 47, 95, 128, 13, 58, 204, 68, 251, 240, 231, 51, 61, 62,
+ 169, 206, 195, 66, 63, 40, 253, 16, 41, 21, 178, 193, 236, 111, 145,
+ 120, 239, 42, 162, 33, 22, 184, 231, 252, 121, 19, 140, 251, 248, 252,
+ 249, 20, 16, 215, 230, 10, 141, 1, 14, 92, 124, 10, 5, 237, 167,
+ 233, 48, 6, 132, 18, 177, 51, 148, 136, 101, 211, 116, 29, 3, 180,
+ 220, 169, 8, 240, 142, 99, 39, 33, 163, 8, 240, 45, 98, 229, 196,
+ 135, 232, 58, 6, 104, 150, 1, 241, 132, 245, 152, 70, 232, 1, 104,
+ 164, 75, 202, 84, 93, 199, 0, 205, 50, 160, 191, 98, 61, 166, 149,
+ 25, 3, 88, 27, 81, 83, 117, 29, 3, 52, 203, 128, 254, 128, 207,
+ 170, 78, 227, 242, 8, 179, 119, 127, 203, 185, 184, 41, 147, 34, 250,
+ 16, 149, 73, 241, 197, 83, 181, 179, 170, 33, 234, 252, 184, 24, 36,
+ 147, 34, 58, 13, 240, 227, 139, 77, 106, 245, 156, 169, 234, 252, 56,
+ 60, 203, 164, 136, 134, 252, 248, 112, 174, 86, 207, 41, 195, 143, 195,
+ 134, 76, 138, 104, 168, 47, 31, 102, 212, 238, 84, 156, 194, 97, 70,
+ 22, 8, 252, 96, 186, 16, 102, 58, 114, 231, 207, 65, 95, 121, 176,
+ 48, 102, 96, 59, 124, 54, 124, 50, 145, 55, 5, 27, 14, 51, 144,
+ 47, 62, 27, 14, 104, 40, 83, 185, 63, 34, 200, 112, 152, 161, 8,
+ 25, 80, 111, 164, 75, 72, 144, 225, 48, 3, 249, 170, 221, 169, 136,
+ 236, 21, 100, 56, 204, 64, 187, 35, 31, 146, 139, 78, 158, 212, 132,
+ 25, 201, 187, 249, 58, 99, 6, 218, 152, 228, 167, 9, 51, 144, 159,
+ 174, 152, 9, 41, 195, 79, 19, 102, 40, 192, 79, 87, 204, 136, 202,
+ 240, 211, 132, 25, 17, 224, 167, 43, 102, 32, 78, 240, 239, 60, 250,
+ 3, 63, 152, 34, 132, 153, 78, 220, 247, 0, 125, 101, 19, 133, 49,
+ 3, 219, 225, 59, 21, 39, 113, 252, 205, 39, 26, 14, 51, 144, 47,
+ 246, 53, 40, 35, 144, 221, 139, 19, 96, 56, 204, 136, 8, 25, 80,
+ 111, 164, 139, 93, 128, 225, 48, 3, 249, 170, 253, 206, 35, 43, 67,
+ 238, 111, 56, 204, 64, 187, 235, 139, 25, 114, 237, 9, 218, 88, 95,
+ 204, 144, 252, 236, 2, 244, 199, 12, 201, 15, 218, 78, 95, 204, 144,
+ 185, 25, 196, 9, 190, 35, 222, 15, 248, 65, 160, 16, 102, 28, 185,
+ 59, 56, 38, 128, 120, 62, 94, 24, 51, 176, 29, 30, 3, 38, 112,
+ 252, 115, 198, 233, 135, 25, 114, 126, 78, 17, 50, 228, 224, 157, 228,
+ 172, 28, 159, 113, 250, 97, 134, 156, 159, 67, 190, 88, 15, 64, 35,
+ 93, 138, 252, 244, 195, 12, 57, 63, 167, 198, 171, 99, 6, 202, 84,
+ 114, 243, 211, 15, 51, 104, 126, 238, 194, 218, 29, 255, 94, 209, 88,
+ 177, 124, 212, 215, 230, 127, 204, 207, 115, 228, 215, 165, 73, 71, 214,
+ 107, 157, 155, 170, 213, 160, 8, 126, 121, 99, 196, 242, 129, 30, 213,
+ 255, 152, 235, 74, 78, 93, 151, 118, 251, 172, 27, 63, 104, 79, 188,
+ 183, 118, 128, 88, 158, 22, 93, 226, 90, 118, 222, 40, 187, 112, 93,
+ 186, 188, 118, 180, 214, 121, 163, 218, 222, 90, 130, 31, 5, 222, 207,
+ 57, 42, 242, 143, 57, 152, 2, 188, 95, 24, 53, 75, 235, 28, 76,
+ 237, 142, 120, 63, 98, 15, 70, 77, 224, 7, 254, 66, 152, 233, 204,
+ 157, 233, 247, 13, 22, 123, 54, 18, 198, 12, 108, 135, 253, 192, 151,
+ 227, 31, 111, 165, 43, 102, 106, 104, 244, 131, 149, 177, 18, 28, 159,
+ 69, 132, 12, 153, 15, 192, 62, 43, 39, 167, 142, 174, 152, 209, 44,
+ 163, 105, 159, 100, 110, 12, 240, 33, 214, 198, 128, 222, 72, 23, 243,
+ 90, 186, 98, 70, 179, 140, 134, 146, 71, 120, 44, 131, 124, 213, 238,
+ 136, 247, 97, 177, 223, 78, 87, 204, 104, 150, 17, 248, 75, 53, 206,
+ 44, 48, 81, 217, 221, 90, 217, 82, 245, 27, 220, 208, 142, 136, 31,
+ 162, 123, 165, 196, 80, 220, 115, 240, 127, 170, 137, 68, 173, 69, 45,
+ 69, 206, 224, 15, 197, 221, 103, 3, 75, 168, 154, 45, 27, 226, 125,
+ 155, 237, 219, 183, 81, 182, 31, 150, 231, 75, 167, 244, 179, 199, 99,
+ 212, 96, 145, 181, 40, 0, 244, 155, 71, 244, 253, 89, 59, 142, 94,
+ 48, 216, 129, 187, 135, 148, 197, 170, 105, 201, 62, 250, 150, 251, 58,
+ 222, 58, 82, 169, 201, 33, 218, 249, 202, 14, 182, 77, 6, 221, 100,
+ 208, 126, 182, 30, 150, 73, 27, 221, 61, 138, 251, 166, 128, 62, 233,
+ 162, 246, 162, 12, 240, 135, 207, 190, 154, 156, 161, 205, 162, 206, 178,
+ 109, 46, 210, 131, 91, 252, 79, 73, 27, 69, 92, 166, 63, 127, 185,
+ 137, 251, 102, 129, 62, 167, 68, 182, 162, 115, 224, 15, 245, 253, 21,
+ 117, 141, 190, 58, 0, 221, 145, 154, 67, 239, 217, 125, 95, 73, 27,
+ 71, 220, 164, 23, 138, 30, 243, 214, 95, 126, 71, 229, 210, 39, 115,
+ 10, 216, 54, 121, 244, 251, 137, 133, 108, 223, 123, 116, 83, 163, 247,
+ 184, 239, 101, 81, 7, 209, 255, 192, 95, 14, 248, 195, 250, 70, 61,
+ 160, 235, 0, 44, 168, 90, 40, 104, 227, 89, 95, 149, 180, 121, 196,
+ 19, 250, 201, 235, 79, 184, 239, 77, 16, 55, 110, 129, 126, 183, 137,
+ 190, 38, 209, 5, 116, 114, 255, 103, 108, 155, 151, 244, 167, 181, 119,
+ 85, 182, 138, 40, 164, 37, 247, 255, 135, 251, 230, 129, 62, 247, 128,
+ 174, 247, 9, 125, 139, 163, 222, 210, 75, 219, 160, 122, 93, 17, 93,
+ 241, 247, 97, 37, 93, 26, 254, 145, 254, 231, 214, 94, 220, 247, 17,
+ 176, 213, 99, 240, 247, 148, 248, 70, 197, 81, 95, 232, 216, 103, 137,
+ 108, 155, 239, 116, 241, 240, 4, 182, 111, 49, 189, 228, 250, 42, 220,
+ 183, 0, 244, 121, 1, 254, 94, 129, 111, 140, 250, 254, 136, 42, 165,
+ 15, 245, 194, 181, 68, 102, 217, 213, 88, 21, 45, 53, 98, 2, 61,
+ 23, 224, 190, 111, 64, 159, 119, 224, 175, 136, 232, 251, 91, 110, 204,
+ 220, 190, 182, 136, 109, 99, 202, 220, 14, 88, 204, 126, 223, 138, 204,
+ 237, 205, 92, 125, 242, 35, 232, 243, 25, 252, 125, 39, 250, 254, 138,
+ 170, 204, 84, 183, 64, 109, 170, 49, 237, 130, 150, 176, 223, 168, 58,
+ 211, 231, 52, 215, 183, 20, 246, 49, 178, 17, 85, 48, 34, 251, 214,
+ 100, 184, 26, 176, 5, 166, 51, 62, 213, 101, 200, 218, 112, 21, 208,
+ 167, 58, 248, 171, 69, 244, 69, 184, 132, 177, 10, 225, 18, 238, 41,
+ 135, 177, 7, 225, 18, 209, 238, 0, 151, 220, 115, 205, 184, 84, 0,
+ 92, 238, 23, 87, 192, 184, 244, 15, 59, 164, 108, 63, 28, 224, 50,
+ 248, 57, 63, 46, 107, 90, 196, 209, 59, 119, 55, 196, 184, 68, 99,
+ 94, 21, 128, 203, 106, 11, 248, 113, 249, 11, 224, 242, 249, 200, 61,
+ 24, 151, 155, 163, 50, 48, 46, 7, 239, 190, 160, 1, 151, 132, 175,
+ 1, 92, 86, 140, 191, 135, 113, 105, 122, 237, 165, 138, 6, 184, 156,
+ 255, 250, 61, 129, 75, 91, 128, 203, 14, 0, 151, 36, 62, 174, 209,
+ 183, 107, 124, 199, 184, 28, 94, 90, 202, 126, 243, 155, 116, 208, 23,
+ 35, 222, 154, 170, 81, 116, 46, 61, 98, 141, 169, 27, 194, 229, 233,
+ 87, 98, 37, 109, 10, 112, 105, 79, 85, 117, 227, 112, 105, 7, 112,
+ 105, 7, 112, 105, 79, 248, 248, 3, 186, 210, 236, 218, 110, 8, 151,
+ 191, 247, 212, 84, 210, 205, 33, 46, 243, 107, 184, 113, 184, 180, 7,
+ 184, 180, 7, 184, 228, 250, 26, 3, 92, 230, 47, 68, 181, 220, 151,
+ 116, 71, 107, 213, 251, 255, 12, 47, 164, 79, 185, 189, 34, 112, 105,
+ 7, 112, 217, 1, 224, 146, 211, 183, 0, 224, 114, 158, 243, 45, 140,
+ 75, 207, 190, 215, 84, 247, 173, 3, 92, 46, 30, 121, 158, 192, 165,
+ 45, 192, 165, 45, 192, 165, 45, 97, 171, 47, 116, 103, 219, 203, 24,
+ 151, 157, 141, 174, 178, 62, 94, 76, 59, 222, 186, 70, 224, 210, 22,
+ 224, 210, 22, 224, 146, 236, 91, 74, 111, 250, 245, 31, 198, 229, 158,
+ 41, 42, 218, 24, 224, 50, 227, 225, 77, 2, 151, 182, 0, 151, 182,
+ 0, 151, 92, 95, 209, 41, 99, 198, 102, 197, 85, 140, 203, 71, 54,
+ 23, 216, 56, 84, 145, 233, 52, 41, 147, 192, 165, 45, 192, 165, 45,
+ 192, 37, 17, 179, 1, 46, 99, 20, 123, 48, 46, 59, 157, 221, 166,
+ 170, 123, 135, 87, 103, 138, 119, 175, 35, 112, 9, 124, 209, 168, 29,
+ 192, 101, 59, 53, 92, 114, 235, 18, 22, 152, 134, 184, 36, 215, 43,
+ 248, 112, 9, 199, 119, 132, 203, 165, 0, 151, 112, 188, 70, 184, 68,
+ 244, 82, 128, 75, 238, 185, 102, 92, 54, 255, 171, 132, 170, 215, 245,
+ 50, 198, 229, 95, 45, 95, 43, 219, 223, 190, 231, 75, 47, 121, 215,
+ 196, 149, 195, 101, 11, 22, 151, 109, 112, 223, 39, 117, 226, 232, 85,
+ 247, 141, 240, 30, 127, 148, 59, 206, 5, 184, 52, 63, 26, 197, 187,
+ 230, 80, 223, 244, 16, 221, 244, 244, 90, 55, 132, 75, 171, 129, 59,
+ 149, 116, 5, 128, 203, 224, 251, 169, 110, 28, 46, 93, 1, 46, 41,
+ 128, 75, 6, 247, 189, 15, 112, 121, 211, 237, 172, 27, 194, 165, 115,
+ 227, 155, 74, 250, 109, 248, 101, 122, 169, 217, 93, 55, 14, 151, 61,
+ 1, 46, 61, 0, 46, 123, 115, 249, 1, 192, 101, 106, 245, 199, 110,
+ 8, 151, 119, 255, 123, 174, 164, 63, 134, 223, 164, 183, 110, 252, 127,
+ 180, 93, 7, 124, 84, 197, 243, 191, 132, 64, 32, 8, 4, 136, 244,
+ 18, 58, 136, 98, 128, 159, 10, 36, 228, 238, 61, 154, 74, 11, 130,
+ 34, 61, 180, 208, 67, 232, 45, 229, 146, 208, 107, 64, 20, 148, 22,
+ 21, 165, 9, 134, 38, 144, 220, 133, 208, 164, 67, 168, 210, 57, 122,
+ 145, 18, 122, 11, 240, 159, 121, 239, 109, 185, 112, 217, 119, 126, 242,
+ 254, 124, 62, 249, 56, 159, 231, 238, 204, 219, 185, 249, 206, 236, 206,
+ 238, 188, 189, 35, 196, 101, 105, 192, 229, 183, 7, 31, 80, 92, 30,
+ 186, 249, 76, 161, 75, 3, 46, 247, 121, 189, 225, 112, 217, 28, 112,
+ 217, 18, 112, 217, 138, 246, 221, 5, 184, 76, 168, 154, 135, 220, 143,
+ 45, 85, 88, 165, 214, 49, 196, 199, 92, 150, 238, 215, 202, 101, 102,
+ 184, 12, 1, 92, 134, 0, 46, 91, 211, 190, 53, 1, 151, 141, 234,
+ 63, 160, 184, 204, 29, 173, 126, 215, 227, 15, 192, 229, 252, 29, 255,
+ 4, 51, 92, 182, 0, 92, 126, 9, 184, 252, 156, 221, 177, 110, 189,
+ 43, 21, 106, 188, 43, 152, 224, 178, 241, 208, 52, 133, 182, 3, 46,
+ 135, 254, 154, 18, 204, 112, 217, 4, 112, 217, 24, 112, 217, 136, 225,
+ 35, 238, 137, 212, 33, 104, 123, 48, 193, 101, 239, 3, 42, 159, 2,
+ 128, 203, 241, 157, 247, 6, 51, 92, 54, 1, 92, 54, 1, 92, 54,
+ 101, 191, 17, 224, 178, 233, 230, 35, 193, 52, 94, 102, 166, 43, 116,
+ 77, 192, 229, 54, 75, 122, 48, 195, 101, 51, 192, 101, 51, 192, 101,
+ 51, 218, 183, 24, 224, 242, 233, 235, 191, 131, 9, 46, 125, 235, 170,
+ 239, 92, 18, 112, 185, 111, 193, 186, 96, 134, 203, 38, 128, 203, 198,
+ 128, 75, 102, 27, 187, 1, 151, 233, 161, 139, 130, 9, 46, 127, 25,
+ 48, 91, 161, 247, 2, 46, 167, 143, 158, 16, 204, 112, 105, 6, 92,
+ 54, 4, 92, 6, 178, 239, 186, 0, 46, 217, 94, 153, 31, 165, 237,
+ 128, 75, 126, 15, 205, 199, 163, 62, 224, 178, 62, 224, 178, 254, 59,
+ 184, 196, 57, 49, 63, 143, 197, 57, 46, 193, 37, 161, 45, 128, 75,
+ 246, 156, 224, 114, 20, 224, 114, 20, 229, 183, 19, 226, 101, 155, 8,
+ 43, 173, 59, 105, 168, 181, 175, 15, 241, 242, 84, 105, 214, 183, 45,
+ 244, 233, 3, 127, 227, 184, 190, 149, 32, 94, 14, 92, 16, 77, 235,
+ 78, 200, 26, 172, 4, 224, 114, 72, 248, 72, 225, 62, 88, 65, 192,
+ 101, 222, 46, 195, 204, 4, 151, 221, 102, 170, 223, 112, 43, 10, 184,
+ 252, 117, 235, 32, 51, 195, 229, 48, 192, 229, 80, 192, 229, 16, 118,
+ 199, 161, 215, 14, 41, 224, 167, 126, 102, 130, 203, 83, 1, 97, 234,
+ 62, 24, 196, 203, 234, 145, 189, 204, 12, 151, 17, 128, 203, 193, 128,
+ 203, 112, 46, 110, 29, 148, 126, 49, 247, 48, 19, 92, 46, 248, 41,
+ 84, 165, 33, 94, 206, 123, 34, 254, 254, 75, 65, 192, 101, 158, 176,
+ 46, 102, 130, 203, 50, 195, 58, 153, 213, 185, 232, 25, 169, 180, 181,
+ 131, 153, 225, 114, 16, 224, 114, 0, 224, 114, 0, 231, 15, 206, 75,
+ 15, 210, 218, 81, 92, 90, 215, 124, 173, 208, 11, 33, 94, 154, 23,
+ 126, 195, 225, 178, 31, 224, 178, 63, 224, 178, 63, 237, 123, 55, 246,
+ 154, 52, 127, 21, 145, 123, 83, 10, 234, 208, 221, 172, 218, 218, 109,
+ 105, 88, 158, 222, 102, 134, 203, 129, 128, 203, 65, 128, 203, 193, 180,
+ 239, 50, 136, 151, 177, 3, 136, 174, 50, 164, 33, 182, 254, 10, 253,
+ 47, 224, 178, 90, 129, 129, 102, 134, 203, 8, 192, 101, 4, 224, 114,
+ 136, 83, 188, 188, 185, 186, 191, 153, 224, 114, 203, 19, 149, 143, 23,
+ 224, 114, 74, 195, 126, 102, 134, 203, 8, 192, 101, 4, 224, 50, 130,
+ 179, 241, 215, 210, 132, 222, 125, 72, 27, 57, 102, 158, 74, 231, 3,
+ 92, 142, 221, 75, 159, 3, 46, 7, 3, 46, 7, 3, 46, 217, 59,
+ 123, 0, 46, 123, 60, 35, 252, 189, 228, 167, 29, 6, 152, 201, 60,
+ 182, 98, 121, 118, 62, 236, 33, 200, 123, 12, 239, 251, 156, 123, 231,
+ 199, 128, 203, 224, 252, 100, 127, 245, 61, 185, 146, 143, 250, 205, 192,
+ 23, 128, 203, 23, 121, 153, 77, 190, 6, 187, 242, 240, 24, 6, 184,
+ 28, 206, 141, 183, 176, 204, 246, 111, 253, 40, 189, 5, 112, 201, 239,
+ 235, 250, 120, 140, 0, 92, 142, 0, 92, 142, 120, 247, 140, 122, 97,
+ 174, 30, 182, 6, 172, 91, 123, 232, 229, 20, 234, 177, 243, 211, 208,
+ 55, 180, 166, 126, 78, 1, 219, 209, 179, 221, 190, 92, 13, 249, 7,
+ 198, 229, 174, 145, 47, 187, 63, 5, 198, 84, 88, 203, 95, 125, 96,
+ 92, 238, 26, 249, 178, 251, 83, 6, 122, 147, 177, 248, 126, 96, 92,
+ 238, 58, 180, 102, 150, 26, 242, 154, 90, 14, 190, 134, 113, 185, 107,
+ 212, 187, 145, 251, 61, 214, 15, 140, 221, 239, 241, 253, 192, 216, 253,
+ 30, 212, 157, 145, 251, 61, 136, 19, 250, 125, 159, 202, 96, 7, 133,
+ 245, 48, 83, 159, 213, 182, 85, 31, 232, 237, 95, 77, 31, 51, 216,
+ 142, 214, 15, 86, 231, 190, 239, 83, 213, 56, 204, 248, 115, 50, 18,
+ 225, 157, 18, 53, 57, 150, 170, 198, 97, 6, 249, 210, 113, 0, 77,
+ 198, 146, 94, 197, 56, 204, 248, 87, 203, 82, 63, 88, 77, 203, 195,
+ 85, 49, 14, 51, 168, 119, 35, 247, 123, 44, 85, 141, 221, 239, 65,
+ 125, 26, 185, 223, 19, 90, 197, 216, 253, 30, 196, 9, 189, 63, 197,
+ 31, 236, 160, 134, 14, 102, 106, 7, 112, 119, 123, 12, 244, 118, 84,
+ 212, 199, 12, 182, 99, 247, 142, 48, 254, 17, 21, 141, 195, 12, 242,
+ 165, 49, 0, 104, 148, 169, 52, 170, 104, 28, 102, 66, 57, 25, 56,
+ 110, 50, 150, 132, 10, 198, 97, 6, 249, 58, 125, 223, 71, 147, 225,
+ 95, 193, 56, 204, 160, 222, 141, 140, 51, 166, 138, 198, 198, 25, 212,
+ 167, 145, 113, 198, 191, 130, 177, 113, 6, 113, 66, 207, 48, 135, 12,
+ 242, 118, 84, 214, 195, 12, 59, 195, 156, 224, 24, 232, 29, 146, 161,
+ 143, 25, 108, 71, 237, 57, 129, 251, 237, 143, 24, 135, 25, 228, 75,
+ 107, 161, 224, 157, 80, 166, 242, 142, 233, 198, 97, 6, 249, 210, 253,
+ 30, 160, 201, 88, 2, 252, 251, 27, 134, 153, 144, 140, 44, 181, 80,
+ 25, 154, 140, 128, 1, 198, 157, 95, 59, 98, 108, 156, 65, 29, 27,
+ 122, 174, 192, 191, 191, 161, 113, 6, 117, 103, 100, 156, 65, 156, 208,
+ 250, 193, 208, 65, 222, 136, 33, 49, 102, 216, 153, 79, 135, 47, 244,
+ 173, 61, 72, 23, 51, 216, 142, 98, 6, 104, 194, 63, 49, 96, 144,
+ 113, 152, 225, 100, 36, 192, 59, 57, 52, 57, 1, 2, 25, 255, 21,
+ 51, 200, 151, 214, 245, 2, 77, 198, 146, 216, 125, 144, 97, 152, 241,
+ 229, 100, 152, 52, 153, 202, 56, 68, 50, 254, 35, 102, 80, 239, 70,
+ 198, 153, 128, 44, 252, 114, 26, 103, 80, 159, 70, 198, 153, 128, 44,
+ 252, 114, 26, 103, 16, 39, 52, 206, 56, 6, 121, 35, 134, 178, 193,
+ 12, 86, 152, 105, 60, 180, 12, 28, 244, 245, 175, 224, 10, 51, 30,
+ 78, 152, 193, 118, 116, 29, 80, 145, 241, 15, 77, 207, 222, 14, 138,
+ 172, 241, 72, 253, 37, 181, 68, 144, 168, 86, 230, 80, 241, 105, 236,
+ 123, 40, 21, 153, 140, 68, 120, 39, 148, 169, 52, 250, 51, 123, 25,
+ 173, 242, 122, 167, 174, 184, 149, 55, 72, 84, 43, 243, 221, 39, 83,
+ 217, 119, 17, 43, 112, 227, 0, 154, 140, 197, 177, 58, 123, 25, 123,
+ 90, 28, 176, 45, 73, 206, 45, 172, 149, 185, 115, 129, 157, 197, 241,
+ 175, 224, 140, 25, 148, 169, 156, 201, 249, 35, 123, 25, 151, 190, 250,
+ 218, 252, 112, 136, 184, 86, 102, 253, 94, 86, 43, 131, 122, 231, 235,
+ 3, 80, 143, 132, 31, 161, 177, 86, 134, 61, 199, 188, 104, 5, 211,
+ 50, 83, 121, 211, 42, 248, 227, 107, 101, 186, 70, 38, 211, 239, 158,
+ 147, 246, 88, 43, 243, 120, 112, 140, 93, 175, 78, 100, 239, 159, 1,
+ 118, 82, 31, 240, 126, 241, 220, 118, 82, 31, 96, 46, 144, 110, 211,
+ 171, 15, 40, 63, 32, 214, 70, 234, 3, 8, 141, 245, 1, 236, 185,
+ 184, 70, 2, 237, 130, 215, 1, 254, 206, 68, 7, 132, 198, 90, 25,
+ 246, 220, 181, 14, 176, 86, 102, 119, 237, 109, 84, 7, 164, 61, 214,
+ 202, 76, 206, 51, 86, 87, 7, 63, 252, 94, 158, 234, 160, 230, 135,
+ 39, 109, 68, 7, 1, 197, 18, 116, 117, 240, 219, 163, 21, 41, 68,
+ 7, 132, 198, 58, 17, 246, 92, 172, 3, 180, 91, 190, 86, 6, 237,
+ 144, 232, 128, 208, 88, 43, 195, 158, 163, 14, 106, 129, 14, 62, 5,
+ 29, 124, 230, 84, 43, 19, 211, 132, 213, 202, 144, 246, 88, 43, 83,
+ 113, 163, 126, 173, 76, 151, 30, 172, 86, 230, 207, 243, 172, 86, 38,
+ 178, 142, 126, 173, 204, 237, 174, 9, 180, 86, 134, 208, 168, 3, 246,
+ 92, 172, 3, 196, 21, 111, 7, 136, 19, 162, 3, 66, 99, 173, 12,
+ 123, 142, 58, 24, 12, 58, 24, 4, 58, 24, 228, 84, 43, 147, 121,
+ 150, 213, 202, 144, 246, 88, 43, 19, 255, 92, 191, 86, 102, 247, 48,
+ 86, 43, 83, 234, 33, 171, 149, 201, 204, 208, 175, 149, 185, 241, 148,
+ 213, 202, 16, 26, 177, 192, 158, 235, 204, 155, 28, 44, 6, 88, 151,
+ 15, 242, 78, 10, 21, 198, 0, 167, 122, 73, 11, 232, 47, 109, 165,
+ 126, 12, 192, 118, 244, 172, 228, 42, 198, 63, 100, 165, 187, 49, 192,
+ 245, 92, 0, 241, 78, 207, 74, 174, 98, 50, 44, 64, 91, 52, 159,
+ 233, 88, 225, 110, 12, 112, 45, 3, 241, 68, 199, 193, 201, 192, 113,
+ 147, 177, 68, 172, 112, 55, 6, 184, 150, 129, 246, 74, 199, 177, 210,
+ 57, 6, 88, 136, 190, 86, 184, 27, 3, 92, 203, 64, 123, 160, 231,
+ 254, 87, 14, 114, 170, 29, 97, 126, 211, 106, 38, 52, 214, 142, 136,
+ 252, 169, 211, 185, 255, 21, 206, 252, 152, 15, 178, 154, 9, 141, 181,
+ 45, 34, 223, 228, 116, 238, 63, 11, 63, 134, 103, 171, 153, 208, 200,
+ 79, 132, 115, 167, 252, 65, 22, 126, 12, 27, 86, 51, 161, 113, 188,
+ 34, 204, 56, 157, 251, 95, 206, 48, 99, 89, 10, 243, 38, 135, 30,
+ 102, 216, 90, 195, 4, 125, 173, 191, 235, 99, 6, 219, 209, 179, 146,
+ 203, 24, 127, 223, 223, 141, 195, 12, 242, 165, 182, 134, 50, 150, 107,
+ 235, 128, 223, 140, 195, 140, 137, 147, 129, 227, 38, 99, 9, 248, 205,
+ 56, 204, 32, 95, 167, 115, 255, 154, 140, 180, 165, 198, 97, 6, 245,
+ 206, 207, 189, 93, 97, 6, 231, 222, 238, 98, 6, 117, 204, 243, 115,
+ 133, 25, 92, 107, 184, 139, 153, 128, 44, 252, 92, 97, 6, 215, 26,
+ 238, 98, 6, 117, 199, 243, 115, 133, 25, 28, 175, 187, 152, 65, 156,
+ 208, 60, 240, 86, 176, 131, 229, 122, 152, 97, 245, 101, 105, 191, 130,
+ 63, 255, 69, 31, 51, 216, 142, 198, 128, 95, 25, 255, 244, 159, 141,
+ 195, 140, 133, 147, 145, 6, 239, 148, 166, 201, 9, 253, 217, 56, 204,
+ 32, 95, 58, 14, 160, 201, 88, 50, 18, 141, 195, 140, 229, 23, 103,
+ 204, 160, 76, 133, 91, 162, 113, 152, 65, 189, 231, 20, 51, 78, 123,
+ 19, 63, 231, 28, 51, 60, 63, 212, 103, 78, 49, 195, 243, 179, 38,
+ 230, 28, 51, 252, 220, 12, 113, 66, 239, 70, 72, 1, 59, 88, 170,
+ 135, 25, 86, 95, 230, 15, 125, 19, 237, 250, 152, 193, 118, 116, 237,
+ 156, 202, 248, 7, 216, 115, 134, 25, 126, 125, 142, 124, 233, 218, 25,
+ 104, 148, 169, 216, 156, 45, 103, 152, 225, 215, 231, 254, 156, 12, 28,
+ 55, 25, 75, 136, 45, 103, 152, 225, 215, 231, 200, 215, 233, 94, 50,
+ 77, 134, 35, 37, 103, 152, 33, 235, 243, 32, 77, 239, 196, 134, 38,
+ 119, 243, 78, 219, 62, 188, 194, 59, 235, 115, 172, 149, 105, 184, 243,
+ 135, 108, 215, 166, 78, 126, 220, 198, 248, 125, 11, 252, 62, 242, 40,
+ 243, 206, 90, 55, 3, 248, 117, 176, 184, 199, 47, 132, 227, 103, 105,
+ 237, 157, 22, 254, 236, 117, 195, 172, 235, 70, 203, 238, 195, 102, 255,
+ 188, 113, 217, 174, 27, 157, 230, 142, 41, 140, 95, 72, 87, 239, 180,
+ 203, 221, 99, 222, 89, 131, 165, 111, 59, 108, 62, 210, 120, 100, 182,
+ 107, 48, 62, 206, 32, 78, 40, 102, 214, 130, 29, 108, 213, 195, 12,
+ 171, 47, 115, 36, 15, 242, 14, 221, 162, 143, 25, 108, 71, 243, 192,
+ 201, 92, 30, 120, 163, 187, 152, 113, 93, 255, 241, 119, 80, 179, 100,
+ 154, 7, 230, 100, 56, 224, 157, 28, 154, 28, 199, 90, 119, 49, 227,
+ 90, 198, 163, 238, 54, 42, 3, 249, 210, 113, 0, 77, 198, 146, 246,
+ 183, 187, 152, 113, 45, 35, 239, 252, 43, 108, 79, 115, 139, 51, 102,
+ 80, 166, 66, 236, 112, 23, 51, 174, 101, 124, 205, 213, 202, 160, 222,
+ 249, 51, 134, 168, 71, 194, 143, 208, 88, 43, 195, 158, 147, 51, 134,
+ 149, 77, 129, 240, 199, 215, 202, 172, 182, 149, 160, 223, 121, 95, 115,
+ 89, 109, 143, 181, 50, 47, 182, 212, 182, 57, 159, 201, 175, 108, 26,
+ 103, 170, 196, 214, 226, 69, 103, 73, 213, 143, 126, 76, 191, 243, 78,
+ 176, 154, 59, 243, 15, 169, 103, 187, 239, 133, 121, 36, 172, 149, 169,
+ 223, 151, 124, 139, 105, 179, 244, 195, 185, 53, 118, 114, 38, 255, 73,
+ 72, 178, 157, 157, 49, 44, 103, 218, 0, 127, 155, 77, 101, 157, 106,
+ 101, 50, 143, 236, 177, 147, 51, 134, 126, 187, 142, 217, 213, 51, 104,
+ 251, 164, 69, 193, 167, 237, 236, 140, 97, 89, 211, 54, 83, 25, 211,
+ 46, 248, 227, 107, 101, 166, 246, 184, 104, 39, 103, 12, 115, 127, 117,
+ 213, 78, 206, 228, 199, 72, 183, 132, 249, 43, 172, 149, 169, 240, 215,
+ 61, 59, 57, 99, 184, 250, 224, 35, 187, 122, 70, 253, 140, 20, 120,
+ 237, 185, 157, 157, 49, 44, 109, 58, 4, 127, 233, 240, 199, 206, 138,
+ 159, 151, 58, 174, 246, 72, 37, 103, 12, 151, 109, 52, 41, 116, 161,
+ 232, 203, 146, 99, 220, 91, 59, 59, 99, 88, 218, 116, 28, 254, 78,
+ 114, 125, 189, 226, 174, 73, 181, 223, 102, 216, 201, 25, 195, 202, 91,
+ 174, 171, 122, 142, 190, 45, 61, 24, 122, 206, 206, 206, 24, 150, 54,
+ 157, 129, 177, 158, 227, 198, 107, 138, 187, 43, 141, 26, 113, 200, 78,
+ 206, 24, 250, 23, 221, 161, 141, 247, 161, 180, 43, 105, 147, 157, 157,
+ 49, 44, 99, 186, 4, 250, 186, 194, 233, 249, 69, 236, 19, 105, 189,
+ 99, 185, 157, 156, 49, 60, 127, 101, 177, 93, 173, 5, 120, 41, 125,
+ 118, 99, 174, 157, 157, 49, 44, 103, 186, 1, 127, 183, 184, 223, 247,
+ 73, 236, 107, 41, 127, 171, 41, 164, 141, 124, 161, 206, 4, 133, 126,
+ 27, 236, 33, 239, 46, 30, 107, 103, 103, 12, 203, 155, 238, 193, 95,
+ 6, 215, 23, 107, 101, 206, 245, 140, 183, 147, 51, 134, 251, 28, 241,
+ 154, 158, 243, 200, 191, 159, 25, 111, 103, 103, 12, 203, 155, 30, 195,
+ 223, 115, 174, 47, 214, 202, 124, 92, 101, 146, 157, 156, 49, 236, 222,
+ 114, 178, 54, 222, 130, 242, 119, 35, 232, 251, 152, 94, 99, 31, 143,
+ 242, 166, 220, 30, 229, 157, 206, 228, 179, 28, 176, 31, 165, 241, 76,
+ 62, 159, 27, 246, 129, 62, 5, 225, 175, 8, 215, 151, 224, 18, 125,
+ 21, 95, 43, 131, 190, 135, 224, 146, 208, 205, 0, 151, 236, 185, 107,
+ 92, 94, 6, 92, 46, 190, 146, 151, 226, 50, 79, 17, 187, 210, 190,
+ 61, 224, 50, 111, 141, 122, 66, 92, 230, 242, 155, 37, 53, 235, 254,
+ 1, 197, 37, 137, 121, 222, 128, 203, 122, 233, 115, 133, 184, 196, 90,
+ 153, 74, 35, 151, 82, 92, 38, 167, 39, 81, 92, 182, 173, 105, 23,
+ 226, 242, 21, 224, 50, 96, 197, 1, 138, 203, 138, 205, 78, 81, 92,
+ 22, 47, 118, 65, 136, 75, 172, 149, 249, 96, 243, 85, 138, 203, 181,
+ 241, 183, 40, 46, 63, 105, 125, 79, 136, 75, 172, 149, 241, 254, 224,
+ 33, 197, 229, 228, 143, 158, 107, 248, 56, 35, 149, 168, 253, 70, 136,
+ 75, 172, 149, 169, 153, 199, 155, 226, 114, 246, 184, 220, 10, 93, 22,
+ 112, 121, 43, 35, 87, 42, 195, 101, 41, 192, 101, 41, 192, 101, 41,
+ 167, 90, 153, 221, 205, 31, 80, 92, 118, 254, 253, 138, 66, 103, 70,
+ 221, 150, 94, 153, 78, 10, 113, 121, 59, 246, 174, 148, 252, 114, 59,
+ 197, 229, 254, 7, 41, 234, 125, 54, 81, 15, 165, 218, 183, 54, 112,
+ 184, 44, 251, 14, 46, 241, 236, 239, 212, 94, 127, 81, 92, 166, 123,
+ 108, 210, 240, 241, 82, 42, 182, 100, 19, 135, 203, 178, 128, 203, 178,
+ 128, 203, 178, 156, 141, 191, 150, 102, 21, 182, 81, 92, 134, 15, 85,
+ 229, 98, 173, 76, 203, 99, 201, 28, 46, 203, 2, 46, 203, 2, 46,
+ 203, 58, 213, 202, 36, 236, 221, 72, 113, 25, 90, 108, 29, 197, 101,
+ 230, 159, 43, 57, 92, 150, 5, 92, 150, 3, 92, 150, 227, 222, 57,
+ 159, 188, 172, 227, 18, 138, 203, 42, 199, 231, 83, 92, 46, 111, 57,
+ 135, 195, 37, 244, 241, 40, 247, 14, 46, 217, 190, 132, 31, 165, 17,
+ 151, 252, 126, 133, 8, 151, 24, 223, 9, 46, 167, 0, 46, 49, 94,
+ 19, 92, 18, 26, 107, 101, 216, 115, 196, 101, 21, 192, 101, 21, 192,
+ 101, 21, 202, 175, 114, 155, 76, 203, 121, 243, 1, 90, 43, 243, 79,
+ 244, 85, 165, 253, 137, 51, 221, 165, 132, 207, 249, 90, 153, 138, 128,
+ 203, 42, 128, 203, 106, 180, 239, 137, 247, 103, 73, 31, 205, 243, 164,
+ 181, 50, 100, 238, 56, 10, 112, 153, 184, 42, 86, 184, 231, 80, 214,
+ 107, 189, 180, 104, 0, 171, 149, 105, 115, 243, 23, 133, 206, 11, 184,
+ 28, 218, 155, 175, 149, 105, 0, 184, 12, 2, 92, 6, 211, 190, 167,
+ 1, 151, 126, 119, 118, 208, 90, 153, 181, 41, 106, 77, 198, 157, 168,
+ 125, 82, 145, 95, 79, 113, 181, 50, 18, 224, 178, 17, 224, 178, 137,
+ 83, 173, 204, 184, 241, 14, 90, 43, 115, 225, 83, 181, 86, 230, 81,
+ 212, 81, 233, 202, 205, 127, 133, 123, 29, 101, 1, 151, 183, 61, 88,
+ 173, 204, 197, 210, 106, 173, 76, 25, 192, 101, 183, 79, 95, 115, 181,
+ 50, 205, 0, 151, 95, 0, 46, 191, 164, 125, 83, 0, 151, 211, 55,
+ 229, 166, 103, 242, 147, 6, 168, 181, 50, 93, 98, 46, 75, 114, 121,
+ 190, 86, 166, 5, 224, 178, 57, 224, 178, 57, 237, 91, 3, 112, 249,
+ 83, 249, 135, 180, 86, 102, 191, 183, 250, 206, 155, 1, 151, 115, 50,
+ 78, 115, 181, 50, 159, 3, 46, 155, 2, 46, 27, 211, 190, 151, 172,
+ 119, 37, 105, 206, 30, 90, 43, 19, 24, 177, 67, 171, 179, 121, 40,
+ 213, 106, 147, 202, 213, 202, 200, 128, 75, 9, 112, 105, 225, 206, 213,
+ 63, 145, 66, 95, 176, 90, 153, 47, 122, 176, 90, 153, 122, 251, 119,
+ 115, 181, 50, 18, 224, 82, 2, 92, 202, 220, 217, 248, 215, 82, 174,
+ 101, 135, 104, 173, 204, 253, 250, 7, 21, 186, 22, 224, 114, 245, 129,
+ 253, 92, 173, 76, 35, 192, 165, 12, 184, 100, 125, 125, 1, 151, 159,
+ 214, 218, 78, 107, 101, 30, 199, 171, 53, 61, 62, 128, 203, 239, 107,
+ 173, 225, 106, 101, 36, 192, 165, 5, 112, 201, 108, 227, 32, 224, 114,
+ 215, 177, 159, 104, 173, 76, 133, 181, 179, 20, 250, 72, 84, 65, 185,
+ 110, 194, 120, 174, 86, 38, 16, 112, 89, 31, 112, 89, 143, 155, 31,
+ 20, 150, 217, 94, 153, 31, 165, 177, 86, 134, 223, 67, 243, 241, 248,
+ 20, 112, 249, 41, 224, 242, 211, 119, 112, 137, 115, 98, 126, 30, 251,
+ 53, 87, 43, 243, 53, 87, 43, 243, 245, 59, 181, 50, 17, 240, 70,
+ 17, 78, 181, 50, 23, 135, 176, 90, 153, 175, 180, 246, 245, 32, 94,
+ 94, 47, 193, 215, 202, 68, 0, 46, 35, 0, 151, 172, 111, 5, 136,
+ 151, 249, 35, 89, 173, 12, 89, 131, 21, 7, 92, 30, 28, 58, 82,
+ 184, 15, 134, 181, 50, 3, 70, 178, 90, 153, 65, 235, 88, 173, 76,
+ 151, 123, 124, 173, 204, 64, 192, 229, 0, 192, 37, 171, 59, 201, 229,
+ 181, 67, 170, 114, 136, 213, 202, 180, 30, 198, 106, 101, 46, 237, 226,
+ 107, 101, 250, 1, 46, 251, 2, 46, 251, 56, 213, 202, 108, 152, 199,
+ 106, 101, 124, 94, 135, 154, 73, 188, 236, 217, 163, 155, 48, 215, 82,
+ 8, 112, 185, 227, 18, 171, 149, 185, 244, 136, 213, 202, 220, 200, 221,
+ 145, 171, 149, 9, 3, 92, 246, 6, 92, 246, 102, 53, 188, 128, 203,
+ 99, 109, 191, 166, 184, 236, 92, 65, 173, 143, 153, 6, 241, 210, 251,
+ 62, 95, 43, 211, 19, 112, 217, 19, 112, 217, 139, 246, 125, 24, 123,
+ 77, 234, 62, 159, 213, 202, 180, 46, 174, 214, 202, 28, 1, 92, 222,
+ 252, 190, 23, 87, 43, 19, 6, 184, 236, 3, 184, 236, 75, 251, 174,
+ 133, 120, 57, 125, 87, 95, 90, 43, 243, 97, 45, 181, 246, 229, 38,
+ 224, 114, 206, 15, 3, 184, 90, 153, 126, 128, 203, 126, 128, 75, 86,
+ 163, 243, 10, 112, 233, 253, 39, 171, 149, 217, 33, 247, 167, 181, 50,
+ 214, 147, 124, 173, 76, 127, 192, 101, 63, 192, 101, 63, 167, 120, 121,
+ 173, 127, 95, 90, 43, 211, 120, 103, 95, 90, 43, 243, 91, 217, 126,
+ 92, 173, 76, 63, 192, 101, 63, 192, 101, 63, 167, 120, 57, 243, 139,
+ 1, 180, 86, 230, 220, 124, 181, 166, 231, 109, 84, 30, 121, 212, 103,
+ 131, 185, 90, 153, 254, 128, 203, 254, 128, 75, 102, 27, 79, 1, 151,
+ 211, 231, 177, 90, 153, 171, 221, 212, 90, 153, 87, 128, 203, 218, 213,
+ 249, 90, 153, 129, 128, 203, 129, 128, 203, 65, 78, 241, 146, 237, 223,
+ 250, 81, 26, 107, 101, 248, 125, 93, 31, 232, 83, 16, 254, 138, 112,
+ 125, 105, 78, 97, 45, 151, 187, 158, 5, 235, 228, 20, 189, 156, 194,
+ 103, 108, 189, 155, 4, 109, 183, 187, 145, 83, 72, 226, 214, 226, 73,
+ 140, 127, 194, 54, 227, 114, 215, 161, 156, 12, 43, 188, 147, 67, 147,
+ 227, 191, 205, 184, 220, 53, 242, 165, 235, 125, 160, 201, 88, 146, 210,
+ 140, 203, 93, 155, 182, 59, 231, 20, 80, 166, 226, 27, 211, 140, 203,
+ 93, 163, 222, 141, 220, 239, 241, 223, 102, 236, 126, 15, 234, 211, 200,
+ 253, 30, 75, 154, 177, 251, 61, 136, 19, 154, 135, 155, 6, 118, 176,
+ 86, 15, 51, 172, 190, 204, 31, 250, 38, 206, 112, 35, 119, 61, 139,
+ 203, 249, 206, 228, 114, 215, 51, 140, 195, 12, 242, 165, 185, 107, 160,
+ 81, 166, 146, 35, 155, 110, 28, 102, 252, 57, 25, 56, 110, 50, 150,
+ 144, 233, 198, 97, 6, 249, 58, 229, 174, 53, 25, 142, 105, 198, 97,
+ 6, 245, 110, 228, 126, 15, 234, 216, 200, 253, 158, 144, 233, 198, 238,
+ 247, 160, 238, 140, 220, 239, 65, 156, 208, 154, 204, 73, 96, 7, 179,
+ 244, 48, 195, 234, 203, 28, 83, 1, 99, 83, 220, 136, 51, 83, 185,
+ 56, 51, 149, 241, 207, 152, 108, 96, 156, 225, 100, 56, 224, 157, 28,
+ 154, 28, 235, 100, 227, 48, 131, 124, 233, 56, 128, 38, 99, 241, 157,
+ 108, 28, 102, 66, 167, 100, 201, 93, 79, 209, 206, 71, 76, 50, 14,
+ 51, 168, 119, 35, 227, 140, 117, 178, 177, 113, 198, 119, 178, 177, 113,
+ 6, 117, 103, 100, 156, 65, 156, 208, 154, 204, 56, 176, 131, 105, 58,
+ 152, 225, 234, 203, 18, 39, 130, 63, 159, 160, 143, 25, 108, 71, 99,
+ 192, 68, 198, 63, 105, 188, 113, 152, 241, 231, 100, 36, 194, 59, 37,
+ 106, 114, 44, 227, 141, 195, 12, 242, 165, 227, 0, 154, 140, 37, 61,
+ 222, 56, 204, 248, 79, 200, 114, 134, 121, 130, 118, 62, 34, 222, 56,
+ 204, 160, 222, 141, 140, 51, 150, 241, 198, 198, 25, 212, 167, 145, 113,
+ 38, 52, 222, 216, 56, 131, 56, 33, 152, 9, 240, 7, 59, 152, 164,
+ 135, 25, 118, 230, 51, 20, 250, 58, 172, 250, 152, 193, 118, 52, 6,
+ 196, 50, 254, 17, 86, 227, 48, 131, 124, 105, 12, 0, 26, 101, 42,
+ 243, 191, 196, 1, 134, 97, 38, 148, 147, 129, 227, 38, 99, 9, 240,
+ 31, 104, 24, 102, 144, 175, 83, 77, 166, 38, 35, 201, 223, 56, 204,
+ 160, 222, 141, 140, 51, 168, 99, 67, 207, 175, 249, 15, 52, 52, 206,
+ 160, 238, 140, 140, 51, 136, 19, 186, 158, 169, 28, 238, 237, 136, 115,
+ 129, 153, 190, 35, 6, 245, 30, 58, 98, 88, 173, 129, 189, 77, 195,
+ 121, 31, 248, 113, 184, 183, 127, 173, 112, 253, 218, 127, 104, 71, 253,
+ 51, 208, 244, 252, 90, 205, 240, 108, 237, 160, 88, 197, 49, 54, 143,
+ 37, 203, 27, 168, 152, 201, 231, 210, 14, 106, 118, 169, 193, 226, 12,
+ 39, 35, 17, 222, 41, 81, 147, 99, 173, 145, 189, 140, 69, 99, 110,
+ 216, 74, 12, 159, 159, 172, 98, 198, 181, 140, 95, 254, 153, 195, 214,
+ 76, 181, 184, 113, 0, 77, 198, 18, 80, 45, 123, 25, 11, 23, 22,
+ 218, 186, 219, 119, 191, 77, 197, 140, 107, 25, 135, 151, 109, 100, 231,
+ 125, 56, 25, 38, 77, 166, 50, 71, 171, 156, 189, 140, 55, 199, 218,
+ 154, 175, 79, 34, 152, 113, 45, 227, 199, 251, 209, 10, 102, 202, 120,
+ 170, 122, 175, 162, 180, 84, 235, 3, 80, 143, 132, 31, 161, 155, 109,
+ 152, 43, 177, 231, 38, 211, 34, 83, 101, 211, 50, 83, 21, 211, 10,
+ 110, 159, 228, 81, 171, 250, 242, 157, 61, 205, 108, 164, 62, 128, 180,
+ 207, 101, 111, 45, 47, 110, 86, 73, 24, 163, 222, 200, 237, 228, 143,
+ 251, 23, 214, 218, 124, 43, 47, 216, 252, 70, 193, 147, 167, 189, 147,
+ 124, 114, 225, 25, 97, 60, 122, 45, 135, 202, 163, 82, 227, 180, 54,
+ 189, 228, 53, 254, 179, 212, 190, 209, 97, 114, 245, 30, 243, 132, 125,
+ 223, 196, 246, 147, 171, 174, 189, 170, 181, 25, 40, 127, 120, 197, 219,
+ 166, 230, 84, 195, 229, 157, 131, 202, 138, 223, 57, 118, 136, 188, 165,
+ 36, 217, 151, 29, 46, 223, 89, 209, 88, 235, 59, 82, 46, 219, 160,
+ 141, 78, 223, 49, 114, 163, 159, 191, 177, 145, 122, 8, 203, 69, 149,
+ 246, 140, 182, 202, 13, 58, 181, 215, 233, 27, 47, 103, 206, 104, 162,
+ 181, 153, 40, 199, 167, 52, 212, 250, 78, 150, 125, 110, 125, 162, 211,
+ 119, 154, 124, 114, 211, 135, 180, 174, 136, 208, 155, 31, 37, 112, 207,
+ 179, 143, 211, 104, 47, 136, 33, 222, 94, 16, 19, 196, 94, 8, 221,
+ 20, 236, 133, 61, 71, 123, 169, 2, 246, 82, 25, 236, 133, 237, 119,
+ 63, 0, 123, 169, 55, 182, 53, 181, 23, 210, 30, 237, 101, 234, 200,
+ 5, 186, 246, 210, 192, 103, 19, 181, 151, 139, 197, 213, 253, 57, 180,
+ 151, 137, 85, 46, 217, 244, 236, 197, 179, 92, 110, 59, 177, 151, 23,
+ 149, 189, 236, 196, 94, 30, 69, 231, 210, 57, 15, 210, 79, 182, 4,
+ 220, 178, 17, 123, 73, 40, 245, 143, 166, 251, 112, 217, 225, 181, 75,
+ 215, 94, 142, 62, 249, 131, 218, 75, 253, 207, 23, 83, 123, 89, 250,
+ 211, 44, 93, 123, 105, 177, 207, 74, 237, 101, 211, 144, 209, 90, 95,
+ 171, 252, 162, 102, 152, 174, 189, 228, 13, 137, 164, 246, 146, 80, 49,
+ 142, 218, 75, 153, 178, 19, 117, 237, 229, 193, 103, 51, 168, 189, 16,
+ 26, 237, 133, 61, 23, 219, 11, 250, 67, 222, 94, 208, 191, 17, 123,
+ 33, 244, 195, 245, 115, 37, 246, 28, 237, 165, 20, 216, 75, 57, 176,
+ 23, 182, 175, 91, 0, 236, 165, 225, 229, 130, 169, 196, 94, 72, 251,
+ 218, 96, 47, 77, 79, 36, 10, 127, 183, 247, 26, 181, 147, 63, 170,
+ 217, 192, 78, 236, 229, 120, 201, 117, 202, 187, 191, 181, 117, 146, 219,
+ 87, 243, 16, 214, 134, 239, 7, 123, 217, 119, 220, 210, 144, 216, 75,
+ 241, 151, 181, 20, 186, 5, 216, 203, 39, 69, 42, 9, 235, 183, 242,
+ 197, 245, 147, 107, 248, 5, 5, 18, 123, 217, 212, 113, 161, 34, 55,
+ 15, 216, 75, 249, 114, 213, 133, 239, 92, 53, 110, 136, 188, 164, 29,
+ 57, 251, 50, 92, 158, 88, 82, 221, 171, 47, 3, 246, 98, 186, 122,
+ 95, 216, 119, 30, 216, 75, 219, 147, 213, 82, 137, 189, 212, 111, 80,
+ 95, 161, 247, 69, 89, 229, 118, 47, 58, 165, 138, 250, 62, 1, 123,
+ 169, 176, 131, 220, 87, 61, 81, 142, 90, 165, 182, 71, 123, 217, 250,
+ 93, 143, 84, 49, 62, 166, 201, 175, 242, 69, 164, 18, 123, 33, 52,
+ 218, 11, 123, 46, 182, 23, 140, 109, 188, 189, 96, 172, 34, 246, 66,
+ 104, 140, 71, 236, 57, 218, 203, 72, 176, 151, 81, 96, 47, 236, 123,
+ 120, 143, 193, 94, 58, 85, 142, 166, 245, 106, 164, 189, 39, 216, 139,
+ 185, 132, 78, 205, 25, 248, 151, 165, 118, 210, 230, 91, 185, 214, 153,
+ 24, 51, 241, 47, 155, 117, 214, 31, 111, 192, 94, 246, 47, 32, 109,
+ 122, 201, 125, 126, 214, 250, 130, 189, 84, 254, 77, 167, 47, 248, 151,
+ 243, 247, 72, 155, 129, 242, 39, 103, 73, 223, 112, 121, 198, 110, 113,
+ 95, 19, 216, 203, 207, 179, 73, 155, 225, 242, 63, 23, 181, 26, 59,
+ 176, 151, 247, 106, 69, 139, 199, 11, 246, 242, 180, 123, 36, 173, 207,
+ 155, 180, 69, 187, 187, 19, 252, 203, 202, 190, 99, 205, 122, 254, 37,
+ 173, 15, 105, 51, 81, 14, 121, 61, 198, 76, 236, 229, 210, 156, 49,
+ 102, 61, 255, 242, 89, 250, 104, 90, 219, 71, 104, 180, 23, 246, 92,
+ 39, 159, 8, 246, 66, 247, 173, 204, 225, 222, 1, 254, 194, 57, 171,
+ 83, 109, 159, 163, 82, 184, 119, 104, 69, 253, 57, 43, 182, 99, 223,
+ 197, 97, 115, 175, 140, 10, 238, 206, 89, 93, 175, 93, 48, 230, 178,
+ 239, 226, 132, 115, 223, 197, 129, 185, 183, 38, 199, 90, 193, 221, 57,
+ 171, 107, 25, 232, 167, 217, 119, 113, 184, 113, 0, 77, 198, 226, 91,
+ 193, 221, 57, 171, 107, 25, 136, 109, 58, 142, 138, 206, 115, 86, 148,
+ 169, 204, 93, 253, 221, 157, 179, 186, 150, 129, 246, 64, 243, 137, 21,
+ 194, 157, 106, 221, 216, 220, 197, 106, 38, 244, 101, 217, 102, 17, 205,
+ 105, 156, 242, 137, 89, 248, 177, 216, 102, 53, 19, 26, 249, 137, 98,
+ 158, 83, 62, 49, 11, 63, 230, 251, 172, 102, 66, 35, 63, 145, 79,
+ 116, 202, 39, 250, 59, 243, 99, 216, 176, 154, 9, 141, 252, 68, 152,
+ 113, 218, 183, 50, 51, 204, 164, 7, 130, 29, 112, 235, 9, 215, 152,
+ 97, 181, 125, 254, 208, 55, 177, 161, 62, 102, 176, 29, 93, 131, 5,
+ 51, 254, 1, 254, 198, 97, 6, 249, 210, 53, 24, 208, 40, 83, 145,
+ 209, 208, 56, 204, 248, 115, 50, 112, 220, 100, 44, 105, 65, 198, 97,
+ 6, 249, 58, 237, 91, 105, 50, 66, 130, 140, 195, 76, 0, 103, 67,
+ 38, 175, 200, 84, 87, 152, 49, 141, 42, 231, 54, 102, 80, 199, 60,
+ 63, 87, 152, 65, 126, 238, 98, 6, 245, 73, 249, 121, 70, 166, 186,
+ 194, 12, 242, 115, 23, 51, 33, 65, 206, 239, 231, 10, 51, 200, 207,
+ 93, 204, 32, 78, 232, 253, 36, 159, 129, 29, 152, 245, 48, 195, 106,
+ 251, 66, 160, 111, 122, 125, 125, 204, 96, 59, 250, 45, 169, 6, 140,
+ 127, 104, 125, 227, 48, 131, 124, 233, 183, 164, 128, 70, 153, 74, 44,
+ 171, 103, 28, 102, 66, 56, 25, 56, 110, 50, 22, 107, 61, 227, 48,
+ 131, 124, 121, 204, 132, 104, 50, 124, 235, 25, 135, 25, 212, 123, 78,
+ 49, 195, 231, 184, 81, 199, 57, 197, 12, 207, 207, 90, 47, 231, 152,
+ 225, 249, 249, 214, 203, 57, 102, 248, 185, 25, 226, 132, 96, 38, 164,
+ 46, 216, 65, 160, 30, 102, 88, 109, 159, 47, 244, 77, 248, 68, 31,
+ 51, 216, 142, 126, 75, 234, 83, 198, 223, 255, 147, 156, 97, 134, 207,
+ 39, 34, 95, 250, 45, 41, 160, 81, 166, 146, 187, 254, 95, 206, 48,
+ 195, 231, 19, 125, 57, 25, 56, 110, 50, 22, 203, 255, 114, 134, 25,
+ 62, 159, 136, 124, 121, 204, 248, 106, 50, 210, 235, 230, 12, 51, 36,
+ 159, 24, 164, 233, 157, 216, 80, 232, 246, 130, 91, 43, 109, 29, 253,
+ 78, 62, 209, 226, 88, 102, 254, 59, 178, 100, 182, 249, 68, 167, 28,
+ 247, 255, 156, 249, 237, 154, 243, 213, 59, 249, 38, 228, 247, 121, 181,
+ 5, 217, 230, 155, 156, 206, 0, 113, 252, 28, 53, 11, 109, 173, 177,
+ 173, 96, 106, 214, 124, 68, 250, 237, 101, 230, 184, 203, 137, 217, 230,
+ 35, 156, 238, 158, 175, 203, 189, 223, 182, 130, 91, 227, 11, 190, 187,
+ 94, 245, 135, 247, 91, 84, 38, 38, 219, 245, 42, 31, 103, 16, 39,
+ 116, 110, 22, 0, 118, 240, 153, 30, 102, 88, 109, 95, 122, 29, 240,
+ 231, 181, 245, 49, 131, 237, 104, 12, 168, 195, 248, 87, 79, 111, 227,
+ 38, 102, 138, 186, 180, 3, 252, 255, 52, 6, 112, 50, 210, 225, 157,
+ 210, 53, 57, 213, 3, 58, 187, 137, 25, 215, 50, 240, 255, 211, 113,
+ 212, 230, 198, 1, 52, 25, 75, 223, 142, 239, 229, 114, 15, 51, 174,
+ 101, 224, 255, 167, 227, 168, 237, 140, 25, 148, 169, 140, 35, 173, 165,
+ 155, 152, 113, 45, 99, 231, 191, 234, 190, 213, 112, 47, 85, 239, 85,
+ 148, 150, 234, 153, 104, 212, 35, 225, 71, 104, 60, 19, 205, 158, 187,
+ 190, 215, 99, 107, 235, 76, 203, 247, 85, 167, 164, 144, 51, 209, 43,
+ 158, 169, 185, 243, 224, 33, 97, 210, 136, 15, 74, 101, 169, 33, 170,
+ 98, 138, 226, 242, 247, 119, 167, 44, 144, 24, 86, 151, 211, 124, 191,
+ 87, 244, 74, 73, 132, 85, 147, 82, 235, 182, 90, 242, 88, 190, 86,
+ 147, 155, 36, 141, 251, 106, 122, 138, 154, 159, 92, 39, 201, 47, 91,
+ 166, 136, 115, 70, 27, 165, 207, 150, 142, 79, 33, 231, 169, 71, 108,
+ 249, 86, 203, 223, 39, 75, 97, 31, 84, 23, 231, 254, 99, 237, 210,
+ 249, 106, 223, 213, 83, 159, 166, 73, 3, 150, 188, 215, 64, 149, 187,
+ 93, 58, 52, 48, 190, 129, 56, 247, 176, 75, 90, 31, 126, 96, 11,
+ 57, 139, 125, 98, 183, 99, 139, 42, 119, 159, 244, 212, 255, 201, 22,
+ 113, 223, 131, 210, 185, 233, 73, 245, 201, 89, 236, 251, 55, 91, 52,
+ 80, 251, 30, 149, 54, 239, 74, 212, 145, 123, 66, 42, 220, 35, 87,
+ 32, 57, 139, 189, 227, 246, 43, 173, 239, 25, 169, 103, 225, 7, 58,
+ 125, 207, 75, 219, 242, 183, 104, 64, 206, 98, 87, 11, 91, 83, 95,
+ 237, 123, 89, 58, 240, 225, 221, 205, 98, 61, 95, 147, 22, 87, 251,
+ 117, 11, 57, 139, 221, 170, 176, 90, 247, 233, 25, 125, 91, 26, 208,
+ 108, 113, 178, 88, 238, 93, 233, 248, 223, 249, 83, 200, 89, 236, 139,
+ 129, 149, 181, 223, 247, 161, 116, 51, 41, 72, 103, 143, 229, 137, 212,
+ 97, 76, 227, 20, 114, 22, 187, 219, 244, 38, 218, 239, 251, 82, 234,
+ 189, 164, 169, 78, 223, 215, 82, 249, 163, 117, 73, 27, 249, 238, 214,
+ 122, 170, 92, 179, 135, 108, 91, 221, 80, 108, 87, 105, 158, 242, 94,
+ 223, 182, 90, 27, 47, 249, 229, 228, 112, 173, 111, 110, 249, 7, 211,
+ 4, 157, 190, 121, 228, 34, 219, 22, 106, 109, 242, 202, 253, 191, 93,
+ 175, 245, 205, 39, 239, 188, 191, 87, 167, 175, 143, 44, 21, 184, 171,
+ 181, 121, 79, 126, 147, 223, 83, 205, 213, 155, 11, 200, 29, 103, 23,
+ 176, 137, 251, 22, 148, 43, 39, 19, 156, 250, 202, 45, 211, 253, 181,
+ 190, 133, 229, 17, 215, 171, 234, 244, 45, 34, 179, 61, 58, 63, 74,
+ 159, 27, 243, 190, 204, 239, 221, 249, 120, 84, 49, 21, 132, 191, 34,
+ 30, 85, 156, 230, 127, 138, 31, 2, 223, 76, 252, 16, 214, 50, 162,
+ 175, 37, 126, 136, 208, 193, 224, 135, 216, 115, 215, 126, 104, 19, 248,
+ 161, 73, 211, 6, 211, 154, 169, 164, 120, 117, 62, 219, 16, 252, 80,
+ 193, 70, 191, 113, 126, 168, 178, 82, 203, 24, 197, 237, 11, 161, 31,
+ 98, 49, 126, 57, 221, 71, 66, 63, 36, 138, 241, 196, 15, 37, 29,
+ 75, 177, 17, 63, 228, 255, 249, 46, 27, 241, 67, 227, 109, 135, 108,
+ 122, 126, 232, 147, 149, 187, 109, 196, 15, 21, 59, 170, 237, 41, 129,
+ 31, 122, 241, 226, 136, 206, 62, 137, 93, 250, 170, 231, 85, 27, 241,
+ 67, 23, 199, 223, 176, 17, 63, 52, 224, 247, 219, 54, 61, 63, 36,
+ 247, 38, 123, 86, 123, 164, 31, 219, 95, 212, 250, 238, 147, 30, 124,
+ 113, 222, 166, 231, 135, 230, 103, 92, 176, 17, 63, 52, 235, 249, 57,
+ 27, 241, 67, 19, 77, 103, 109, 122, 126, 232, 230, 193, 99, 54, 226,
+ 135, 110, 141, 59, 102, 35, 126, 232, 118, 141, 99, 54, 61, 63, 244,
+ 100, 196, 105, 27, 241, 67, 77, 125, 206, 106, 239, 124, 89, 154, 183,
+ 248, 156, 78, 223, 107, 210, 23, 59, 201, 187, 221, 148, 218, 154, 200,
+ 59, 223, 150, 186, 4, 233, 245, 189, 43, 213, 142, 39, 58, 201, 144,
+ 98, 147, 72, 223, 135, 210, 145, 243, 122, 227, 125, 34, 237, 137, 63,
+ 101, 35, 126, 168, 200, 193, 147, 54, 226, 135, 58, 23, 59, 97, 211,
+ 243, 67, 11, 70, 81, 157, 200, 37, 226, 143, 218, 136, 31, 250, 126,
+ 166, 216, 54, 176, 38, 100, 93, 200, 113, 27, 241, 67, 129, 245, 14,
+ 218, 136, 31, 218, 90, 254, 111, 155, 158, 31, 202, 252, 125, 157, 141,
+ 248, 161, 194, 214, 165, 54, 226, 135, 170, 118, 248, 65, 252, 206, 224,
+ 135, 154, 140, 140, 177, 17, 63, 180, 171, 239, 112, 234, 135, 90, 117,
+ 234, 167, 235, 135, 98, 170, 140, 165, 126, 104, 173, 35, 150, 250, 161,
+ 95, 215, 76, 212, 245, 67, 108, 239, 215, 143, 210, 232, 135, 248, 61,
+ 97, 31, 143, 202, 224, 135, 42, 131, 31, 170, 252, 142, 31, 194, 249,
+ 27, 241, 67, 117, 192, 15, 225, 124, 140, 248, 33, 66, 251, 130, 31,
+ 98, 207, 93, 215, 84, 159, 106, 153, 105, 217, 59, 238, 137, 157, 248,
+ 33, 219, 179, 252, 202, 92, 255, 252, 224, 48, 105, 250, 238, 114, 169,
+ 204, 15, 149, 1, 63, 84, 10, 252, 80, 73, 218, 247, 231, 137, 11,
+ 36, 182, 54, 88, 78, 247, 39, 87, 131, 31, 18, 173, 13, 176, 239,
+ 124, 240, 67, 81, 117, 138, 216, 137, 31, 122, 254, 170, 182, 66, 23,
+ 138, 91, 39, 189, 120, 212, 70, 184, 119, 55, 125, 242, 70, 105, 81,
+ 129, 221, 180, 30, 59, 104, 137, 250, 158, 159, 140, 79, 150, 170, 222,
+ 234, 40, 92, 199, 175, 29, 101, 151, 118, 46, 93, 147, 74, 252, 80,
+ 224, 201, 93, 10, 93, 115, 244, 118, 201, 49, 236, 156, 176, 111, 25,
+ 240, 67, 167, 111, 253, 147, 74, 252, 80, 100, 137, 11, 10, 221, 10,
+ 252, 208, 31, 77, 174, 10, 251, 182, 138, 59, 40, 221, 124, 118, 55,
+ 149, 248, 161, 164, 230, 207, 20, 186, 60, 248, 161, 41, 33, 166, 173,
+ 194, 189, 89, 240, 67, 59, 46, 228, 219, 74, 252, 208, 226, 203, 42,
+ 125, 23, 252, 208, 152, 235, 249, 132, 125, 143, 96, 109, 90, 11, 194,
+ 223, 33, 249, 44, 83, 229, 174, 143, 186, 44, 125, 244, 215, 61, 225,
+ 59, 223, 1, 63, 148, 239, 244, 245, 84, 226, 135, 174, 238, 184, 168,
+ 208, 143, 162, 110, 75, 101, 254, 60, 37, 236, 187, 11, 252, 208, 164,
+ 190, 135, 83, 137, 31, 170, 26, 176, 79, 161, 79, 68, 61, 148, 22,
+ 60, 223, 41, 236, 123, 23, 252, 208, 119, 189, 183, 165, 18, 63, 244,
+ 96, 108, 170, 66, 123, 131, 31, 234, 146, 144, 34, 236, 219, 44, 238,
+ 181, 84, 107, 86, 50, 105, 35, 119, 201, 220, 160, 254, 70, 224, 135,
+ 230, 244, 249, 83, 216, 183, 15, 248, 161, 237, 127, 47, 77, 37, 126,
+ 40, 224, 192, 124, 133, 238, 15, 126, 104, 251, 222, 233, 194, 190, 23,
+ 192, 15, 61, 249, 136, 228, 144, 242, 202, 251, 39, 169, 251, 195, 169,
+ 193, 249, 228, 207, 110, 215, 19, 246, 93, 8, 126, 104, 66, 177, 146,
+ 169, 196, 15, 149, 159, 158, 71, 161, 255, 10, 46, 32, 47, 42, 126,
+ 83, 136, 133, 116, 240, 67, 229, 158, 239, 179, 19, 63, 180, 183, 101,
+ 170, 66, 63, 8, 46, 44, 63, 249, 109, 173, 176, 239, 107, 240, 67,
+ 236, 76, 129, 31, 165, 207, 131, 31, 226, 207, 26, 248, 120, 148, 3,
+ 63, 84, 14, 252, 80, 185, 119, 231, 67, 176, 198, 227, 231, 67, 184,
+ 102, 35, 126, 136, 208, 184, 46, 99, 207, 93, 223, 235, 102, 135, 249,
+ 208, 79, 199, 163, 104, 173, 234, 244, 25, 42, 45, 193, 124, 40, 195,
+ 28, 197, 213, 170, 142, 4, 63, 52, 18, 252, 208, 72, 182, 31, 15,
+ 243, 33, 150, 83, 88, 78, 247, 189, 61, 193, 15, 137, 114, 10, 106,
+ 220, 90, 45, 253, 189, 135, 180, 73, 146, 198, 172, 81, 233, 50, 48,
+ 31, 170, 57, 87, 188, 159, 108, 141, 219, 40, 125, 95, 192, 74, 235,
+ 92, 79, 29, 83, 247, 135, 207, 195, 124, 200, 54, 85, 188, 175, 107,
+ 129, 249, 80, 205, 149, 164, 222, 49, 77, 138, 243, 80, 235, 32, 199,
+ 68, 109, 151, 54, 119, 236, 43, 236, 155, 1, 126, 232, 100, 173, 190,
+ 180, 70, 182, 244, 76, 181, 70, 246, 125, 240, 67, 157, 239, 246, 18,
+ 246, 173, 0, 126, 168, 235, 10, 86, 35, 59, 176, 128, 90, 35, 91,
+ 28, 252, 144, 121, 72, 23, 97, 223, 21, 224, 135, 252, 127, 106, 79,
+ 107, 100, 135, 207, 83, 233, 175, 193, 15, 237, 153, 219, 94, 216, 247,
+ 58, 248, 33, 207, 65, 93, 104, 141, 236, 154, 199, 106, 61, 238, 69,
+ 240, 67, 101, 35, 123, 8, 251, 62, 2, 63, 212, 46, 162, 23, 173,
+ 145, 141, 170, 22, 166, 213, 125, 222, 150, 126, 188, 208, 71, 216, 247,
+ 1, 248, 161, 31, 31, 176, 251, 228, 194, 139, 171, 181, 167, 248, 77,
+ 137, 250, 13, 7, 10, 251, 98, 141, 236, 145, 251, 3, 105, 141, 108,
+ 224, 164, 65, 102, 50, 31, 90, 90, 46, 92, 216, 55, 47, 248, 161,
+ 136, 206, 180, 141, 60, 161, 251, 96, 90, 35, 187, 52, 44, 66, 216,
+ 55, 55, 248, 161, 13, 195, 135, 210, 26, 217, 4, 179, 90, 231, 234,
+ 5, 126, 104, 140, 207, 72, 97, 223, 103, 224, 135, 138, 158, 34, 185,
+ 103, 88, 151, 117, 85, 207, 29, 188, 0, 63, 180, 230, 234, 56, 241,
+ 120, 193, 15, 205, 44, 18, 69, 235, 107, 187, 167, 170, 244, 91, 240,
+ 67, 1, 253, 197, 231, 35, 112, 62, 244, 123, 18, 105, 227, 43, 231,
+ 58, 173, 210, 56, 31, 10, 245, 136, 49, 235, 205, 135, 216, 89, 21,
+ 63, 74, 227, 124, 136, 63, 195, 226, 227, 49, 10, 252, 208, 40, 240,
+ 67, 163, 222, 201, 163, 99, 30, 144, 158, 203, 45, 19, 238, 29, 82,
+ 87, 47, 39, 200, 106, 115, 67, 160, 111, 98, 57, 55, 246, 158, 2,
+ 184, 125, 206, 242, 220, 126, 109, 57, 3, 247, 107, 203, 115, 251, 181,
+ 64, 163, 76, 197, 67, 148, 53, 112, 191, 150, 147, 129, 227, 38, 99,
+ 9, 41, 107, 224, 126, 109, 185, 44, 251, 181, 154, 12, 71, 25, 3,
+ 247, 107, 203, 25, 187, 95, 139, 58, 54, 114, 191, 54, 164, 172, 177,
+ 251, 181, 168, 59, 35, 247, 107, 17, 39, 180, 206, 176, 68, 184, 119,
+ 122, 128, 30, 102, 88, 109, 174, 163, 116, 184, 119, 104, 41, 55, 206,
+ 5, 149, 230, 206, 211, 148, 230, 206, 5, 149, 52, 240, 92, 16, 39,
+ 195, 1, 239, 228, 208, 228, 88, 75, 26, 120, 46, 168, 20, 55, 14,
+ 160, 201, 88, 124, 75, 26, 120, 46, 168, 84, 150, 115, 65, 165, 180,
+ 115, 65, 37, 12, 60, 23, 84, 210, 216, 253, 90, 107, 73, 99, 247,
+ 107, 125, 75, 26, 187, 95, 139, 186, 51, 114, 191, 22, 113, 66, 235,
+ 12, 139, 130, 29, 148, 209, 195, 12, 119, 247, 99, 241, 112, 111, 255,
+ 98, 110, 212, 127, 20, 231, 98, 64, 113, 198, 63, 233, 253, 156, 97,
+ 166, 88, 209, 143, 26, 210, 24, 192, 201, 72, 132, 119, 74, 212, 228,
+ 88, 222, 207, 25, 102, 254, 57, 81, 139, 125, 239, 181, 24, 55, 14,
+ 160, 201, 88, 210, 253, 114, 134, 153, 162, 195, 186, 178, 113, 20, 203,
+ 82, 255, 81, 76, 229, 29, 234, 151, 51, 204, 28, 168, 206, 213, 25,
+ 190, 207, 217, 80, 22, 126, 168, 83, 198, 219, 245, 191, 119, 246, 87,
+ 5, 252, 80, 127, 255, 149, 31, 234, 51, 59, 126, 168, 171, 255, 202,
+ 47, 84, 192, 15, 245, 226, 46, 63, 90, 103, 88, 148, 97, 38, 32,
+ 6, 236, 160, 132, 14, 102, 248, 187, 31, 161, 175, 163, 176, 62, 102,
+ 176, 29, 141, 1, 69, 24, 255, 136, 194, 198, 197, 25, 228, 75, 99,
+ 0, 208, 40, 83, 105, 84, 216, 184, 56, 19, 202, 201, 192, 113, 147,
+ 177, 36, 248, 26, 23, 103, 144, 175, 83, 157, 161, 38, 35, 41, 198,
+ 184, 56, 131, 122, 55, 50, 206, 152, 10, 27, 27, 103, 80, 159, 70,
+ 198, 25, 212, 157, 145, 113, 6, 113, 66, 48, 147, 49, 22, 236, 160,
+ 168, 30, 102, 216, 153, 237, 164, 232, 112, 239, 128, 40, 125, 204, 96,
+ 59, 98, 7, 1, 209, 140, 127, 90, 164, 113, 152, 9, 224, 100, 36,
+ 193, 59, 37, 105, 114, 66, 34, 141, 195, 12, 242, 165, 227, 0, 154,
+ 140, 197, 49, 206, 56, 204, 4, 68, 57, 99, 6, 101, 42, 254, 101,
+ 156, 113, 152, 65, 189, 27, 185, 158, 9, 137, 52, 118, 61, 131, 250,
+ 52, 114, 61, 19, 49, 206, 216, 245, 12, 226, 132, 222, 97, 52, 4,
+ 236, 32, 70, 128, 153, 161, 253, 76, 125, 135, 179, 223, 35, 2, 250,
+ 102, 140, 214, 199, 12, 182, 35, 118, 144, 49, 134, 241, 79, 28, 153,
+ 189, 29, 116, 191, 227, 101, 75, 159, 82, 52, 72, 84, 155, 235, 8,
+ 241, 160, 119, 63, 34, 95, 34, 35, 2, 104, 148, 169, 96, 102, 120,
+ 246, 50, 230, 60, 219, 106, 251, 241, 236, 252, 32, 81, 109, 238, 44,
+ 207, 82, 20, 51, 17, 156, 12, 28, 55, 29, 203, 208, 236, 101, 60,
+ 223, 113, 38, 53, 237, 227, 163, 65, 162, 218, 220, 198, 246, 191, 232,
+ 252, 15, 249, 242, 152, 137, 208, 100, 164, 15, 202, 94, 198, 213, 94,
+ 125, 204, 193, 30, 177, 194, 218, 220, 95, 158, 176, 218, 92, 212, 59,
+ 95, 11, 133, 122, 36, 252, 8, 141, 181, 80, 236, 57, 230, 129, 171,
+ 154, 150, 193, 223, 10, 110, 63, 30, 107, 161, 230, 253, 91, 88, 107,
+ 211, 66, 38, 237, 177, 22, 106, 212, 235, 87, 194, 250, 55, 172, 181,
+ 188, 21, 113, 77, 107, 243, 173, 28, 121, 236, 159, 64, 181, 111, 39,
+ 185, 208, 167, 251, 116, 250, 134, 202, 247, 46, 164, 104, 109, 122, 201,
+ 77, 63, 248, 83, 161, 115, 101, 246, 149, 195, 234, 139, 239, 100, 125,
+ 157, 107, 176, 124, 166, 246, 100, 173, 205, 112, 185, 254, 180, 33, 129,
+ 106, 206, 109, 132, 92, 234, 68, 191, 64, 113, 206, 109, 164, 124, 36,
+ 79, 31, 173, 205, 104, 185, 119, 175, 111, 180, 190, 99, 228, 23, 219,
+ 154, 232, 244, 29, 43, 135, 238, 247, 211, 218, 68, 202, 203, 27, 21,
+ 81, 199, 27, 109, 149, 119, 87, 206, 43, 30, 111, 108, 188, 220, 40,
+ 101, 137, 214, 102, 162, 124, 239, 223, 149, 90, 223, 201, 242, 143, 101,
+ 254, 210, 233, 59, 77, 94, 108, 137, 215, 218, 204, 164, 52, 214, 66,
+ 177, 231, 217, 199, 105, 180, 23, 196, 16, 111, 47, 136, 9, 98, 47,
+ 132, 70, 123, 97, 207, 201, 57, 10, 231, 243, 92, 104, 47, 173, 31,
+ 150, 165, 181, 185, 164, 61, 218, 139, 103, 253, 146, 186, 181, 185, 47,
+ 90, 20, 163, 181, 185, 95, 127, 252, 62, 173, 205, 93, 91, 216, 207,
+ 166, 103, 47, 227, 182, 23, 181, 17, 123, 177, 135, 22, 181, 17, 123,
+ 25, 112, 161, 136, 77, 207, 94, 38, 31, 44, 76, 235, 107, 223, 236,
+ 40, 98, 35, 246, 178, 192, 163, 168, 77, 207, 94, 6, 28, 34, 239,
+ 54, 90, 110, 28, 95, 212, 70, 236, 165, 108, 189, 34, 54, 61, 123,
+ 233, 183, 175, 0, 173, 205, 141, 126, 146, 143, 214, 114, 255, 214, 232,
+ 73, 138, 158, 189, 100, 164, 39, 165, 16, 123, 241, 54, 111, 73, 33,
+ 246, 82, 110, 245, 182, 20, 61, 123, 41, 86, 185, 36, 173, 205, 37,
+ 52, 218, 11, 123, 46, 182, 23, 244, 135, 188, 189, 160, 127, 35, 246,
+ 66, 232, 79, 192, 94, 216, 115, 180, 151, 178, 239, 236, 119, 239, 4,
+ 123, 233, 82, 117, 18, 189, 35, 146, 180, 127, 15, 236, 229, 180, 148,
+ 38, 220, 167, 51, 53, 106, 39, 159, 142, 188, 72, 107, 115, 175, 212,
+ 80, 247, 235, 189, 192, 94, 98, 7, 228, 22, 206, 79, 61, 26, 133,
+ 202, 231, 7, 21, 73, 37, 246, 178, 113, 134, 186, 87, 158, 15, 236,
+ 229, 139, 205, 181, 132, 125, 243, 120, 13, 150, 251, 133, 53, 74, 37,
+ 246, 210, 120, 76, 251, 84, 117, 31, 98, 132, 236, 27, 221, 89, 216,
+ 215, 107, 219, 72, 57, 176, 114, 207, 84, 98, 47, 15, 246, 246, 211,
+ 250, 142, 145, 15, 15, 22, 207, 169, 159, 130, 189, 164, 118, 141, 161,
+ 181, 185, 121, 151, 71, 42, 116, 27, 176, 151, 106, 7, 134, 136, 247,
+ 247, 193, 94, 198, 7, 123, 209, 218, 220, 15, 60, 212, 239, 149, 183,
+ 3, 123, 57, 180, 195, 67, 172, 171, 184, 105, 242, 254, 120, 86, 155,
+ 75, 232, 149, 96, 47, 236, 185, 216, 94, 48, 182, 57, 213, 254, 63,
+ 97, 103, 157, 9, 141, 254, 133, 61, 71, 123, 25, 245, 206, 190, 36,
+ 126, 43, 226, 139, 132, 24, 90, 155, 75, 218, 99, 237, 255, 134, 147,
+ 209, 102, 61, 255, 210, 127, 84, 52, 173, 205, 157, 93, 153, 244, 237,
+ 36, 111, 62, 18, 165, 91, 155, 107, 233, 21, 69, 107, 115, 77, 215,
+ 213, 61, 77, 47, 176, 151, 149, 13, 35, 197, 125, 193, 191, 236, 108,
+ 49, 142, 214, 215, 78, 148, 198, 154, 137, 127, 249, 235, 205, 24, 179,
+ 158, 127, 121, 188, 144, 180, 25, 45, 123, 53, 24, 99, 38, 254, 197,
+ 239, 31, 241, 154, 233, 13, 216, 75, 116, 230, 40, 90, 155, 219, 168,
+ 232, 104, 237, 91, 182, 86, 249, 235, 240, 209, 58, 123, 124, 241, 114,
+ 252, 158, 40, 90, 155, 27, 127, 37, 74, 235, 59, 89, 142, 127, 19,
+ 165, 91, 155, 91, 233, 24, 171, 205, 37, 52, 250, 23, 246, 92, 188,
+ 206, 195, 121, 42, 173, 153, 234, 15, 243, 176, 177, 194, 57, 171, 83,
+ 109, 174, 9, 250, 166, 15, 212, 159, 179, 98, 59, 250, 189, 215, 8,
+ 174, 102, 106, 160, 187, 115, 86, 215, 107, 23, 140, 185, 244, 123, 175,
+ 17, 220, 57, 115, 156, 223, 13, 209, 106, 166, 6, 184, 59, 103, 205,
+ 38, 103, 9, 126, 154, 238, 191, 13, 226, 206, 203, 195, 187, 147, 177,
+ 88, 7, 184, 59, 103, 117, 45, 3, 177, 77, 207, 203, 15, 204, 82,
+ 51, 165, 205, 85, 125, 7, 184, 59, 103, 117, 45, 3, 237, 129, 230,
+ 215, 6, 58, 215, 170, 178, 185, 139, 213, 76, 104, 172, 85, 21, 205,
+ 105, 248, 117, 20, 234, 152, 231, 199, 98, 155, 213, 76, 104, 228, 39,
+ 138, 121, 78, 181, 190, 89, 248, 49, 223, 103, 53, 19, 26, 249, 137,
+ 124, 162, 83, 173, 111, 22, 126, 12, 27, 86, 51, 161, 145, 159, 8,
+ 51, 252, 58, 15, 113, 66, 107, 166, 194, 192, 14, 134, 232, 97, 134,
+ 213, 230, 250, 66, 223, 132, 190, 110, 212, 76, 245, 231, 106, 141, 250,
+ 113, 53, 83, 125, 141, 195, 12, 242, 165, 53, 83, 64, 163, 76, 37,
+ 183, 208, 199, 56, 204, 248, 114, 50, 112, 220, 100, 44, 150, 62, 198,
+ 97, 6, 249, 58, 213, 76, 105, 50, 210, 195, 140, 195, 12, 234, 157,
+ 207, 21, 184, 194, 12, 230, 10, 220, 197, 12, 234, 152, 231, 231, 10,
+ 51, 200, 207, 93, 204, 88, 120, 126, 111, 198, 165, 186, 194, 140, 101,
+ 68, 57, 183, 49, 131, 186, 227, 223, 207, 21, 102, 240, 253, 220, 197,
+ 12, 226, 132, 96, 198, 183, 7, 216, 65, 127, 61, 204, 176, 218, 220,
+ 244, 222, 225, 222, 33, 189, 220, 168, 153, 234, 205, 197, 128, 222, 140,
+ 191, 163, 167, 113, 152, 9, 225, 100, 164, 195, 59, 165, 107, 114, 34,
+ 122, 26, 135, 25, 228, 75, 199, 1, 52, 29, 75, 79, 227, 48, 19,
+ 210, 43, 75, 205, 84, 47, 45, 207, 223, 195, 56, 204, 160, 222, 115,
+ 138, 25, 62, 199, 29, 209, 51, 231, 152, 113, 202, 233, 247, 204, 57,
+ 102, 156, 114, 250, 61, 114, 142, 25, 126, 110, 134, 56, 161, 103, 138,
+ 186, 128, 29, 132, 233, 97, 134, 213, 230, 38, 116, 15, 247, 78, 236,
+ 166, 143, 25, 108, 71, 99, 64, 119, 238, 76, 81, 183, 156, 97, 134,
+ 207, 39, 250, 114, 50, 18, 66, 1, 251, 154, 156, 180, 174, 57, 195,
+ 12, 159, 79, 68, 190, 116, 63, 25, 222, 157, 140, 37, 164, 107, 206,
+ 48, 195, 231, 19, 145, 47, 143, 25, 148, 169, 140, 181, 75, 206, 48,
+ 67, 242, 137, 65, 154, 222, 169, 13, 109, 43, 184, 53, 108, 97, 222,
+ 119, 242, 137, 88, 171, 154, 250, 215, 219, 192, 236, 242, 137, 78, 103,
+ 138, 186, 114, 181, 180, 105, 5, 183, 254, 89, 98, 89, 74, 214, 124,
+ 147, 47, 240, 251, 95, 169, 234, 217, 230, 155, 156, 114, 250, 28, 63,
+ 203, 129, 130, 91, 131, 194, 174, 188, 147, 143, 176, 92, 90, 102, 254,
+ 227, 208, 234, 108, 243, 17, 78, 57, 253, 46, 206, 227, 237, 60, 238,
+ 221, 245, 42, 142, 183, 88, 193, 152, 108, 215, 171, 78, 103, 138, 186,
+ 112, 231, 35, 58, 2, 221, 67, 15, 51, 220, 189, 155, 157, 195, 189,
+ 67, 59, 185, 113, 166, 168, 51, 183, 15, 219, 153, 139, 51, 167, 91,
+ 184, 137, 25, 215, 245, 166, 121, 255, 215, 184, 62, 221, 135, 229, 100,
+ 56, 224, 157, 28, 154, 156, 18, 99, 90, 187, 137, 25, 215, 50, 42,
+ 124, 153, 196, 190, 247, 218, 137, 27, 7, 208, 100, 44, 37, 190, 8,
+ 113, 19, 51, 174, 101, 148, 77, 219, 199, 246, 147, 59, 101, 57, 83,
+ 212, 73, 149, 145, 55, 95, 27, 55, 49, 227, 90, 198, 5, 174, 54,
+ 23, 245, 206, 215, 230, 162, 30, 9, 63, 66, 227, 25, 112, 246, 60,
+ 251, 218, 220, 232, 113, 73, 26, 174, 2, 164, 66, 219, 47, 42, 180,
+ 60, 36, 76, 154, 190, 46, 31, 205, 223, 183, 133, 62, 125, 224, 47,
+ 138, 235, 251, 124, 202, 2, 137, 97, 117, 57, 205, 247, 227, 25, 112,
+ 17, 86, 77, 218, 25, 240, 25, 242, 125, 173, 77, 146, 180, 97, 210,
+ 99, 45, 39, 189, 78, 58, 123, 224, 133, 56, 23, 30, 187, 81, 154,
+ 188, 179, 136, 38, 119, 179, 84, 241, 185, 143, 66, 231, 138, 78, 150,
+ 54, 215, 204, 21, 36, 206, 31, 216, 165, 192, 190, 27, 52, 254, 105,
+ 82, 193, 51, 9, 106, 14, 62, 122, 187, 116, 124, 94, 71, 161, 92,
+ 83, 220, 46, 105, 247, 247, 205, 181, 54, 123, 164, 223, 154, 28, 111,
+ 160, 202, 221, 39, 5, 63, 243, 169, 47, 234, 155, 25, 123, 80, 242,
+ 120, 48, 80, 243, 67, 233, 210, 183, 179, 22, 168, 116, 244, 81, 233,
+ 245, 111, 105, 58, 57, 213, 19, 210, 208, 32, 226, 195, 78, 73, 255,
+ 244, 94, 171, 229, 99, 207, 72, 65, 179, 82, 116, 234, 152, 207, 75,
+ 77, 182, 29, 214, 218, 56, 164, 143, 22, 188, 76, 81, 223, 249, 178,
+ 180, 48, 89, 156, 67, 206, 140, 189, 38, 149, 105, 218, 138, 214, 196,
+ 217, 71, 132, 168, 121, 111, 172, 137, 251, 237, 43, 221, 154, 184, 159,
+ 254, 87, 150, 214, 196, 101, 78, 240, 209, 106, 241, 30, 74, 199, 215,
+ 220, 215, 173, 205, 45, 219, 242, 28, 173, 205, 237, 125, 249, 184, 86,
+ 215, 251, 82, 90, 51, 234, 160, 110, 109, 110, 197, 149, 23, 104, 109,
+ 110, 194, 202, 19, 180, 54, 247, 245, 202, 3, 186, 181, 185, 131, 226,
+ 214, 210, 218, 220, 123, 45, 102, 209, 218, 220, 180, 90, 29, 117, 107,
+ 115, 223, 92, 74, 214, 234, 79, 243, 202, 235, 122, 236, 221, 164, 246,
+ 205, 39, 95, 253, 97, 67, 3, 113, 95, 31, 249, 250, 202, 214, 154,
+ 93, 189, 39, 151, 95, 55, 67, 219, 23, 42, 32, 167, 205, 92, 175,
+ 179, 47, 84, 80, 94, 52, 230, 140, 214, 198, 87, 110, 242, 213, 29,
+ 173, 111, 97, 249, 214, 7, 111, 116, 250, 22, 145, 217, 30, 157, 31,
+ 165, 241, 12, 56, 191, 119, 231, 227, 81, 213, 84, 16, 254, 138, 120,
+ 84, 125, 167, 22, 5, 125, 51, 241, 67, 211, 193, 15, 161, 175, 37,
+ 126, 136, 208, 102, 240, 67, 236, 185, 107, 63, 180, 17, 252, 208, 159,
+ 109, 231, 211, 123, 70, 199, 141, 155, 169, 208, 173, 193, 15, 237, 73,
+ 142, 231, 252, 80, 53, 240, 67, 213, 192, 15, 177, 251, 12, 95, 128,
+ 31, 98, 49, 126, 57, 221, 71, 242, 0, 63, 36, 138, 241, 196, 15,
+ 45, 178, 215, 167, 181, 185, 7, 110, 5, 218, 136, 31, 122, 249, 126,
+ 176, 110, 109, 238, 165, 243, 53, 104, 109, 238, 245, 253, 31, 219, 136,
+ 31, 186, 191, 69, 252, 205, 219, 92, 113, 118, 105, 87, 70, 51, 90,
+ 155, 59, 249, 155, 161, 218, 55, 56, 183, 75, 17, 93, 103, 10, 251,
+ 62, 141, 221, 37, 245, 248, 114, 55, 173, 205, 61, 220, 228, 8, 173,
+ 205, 45, 41, 157, 213, 173, 205, 253, 170, 251, 86, 90, 155, 235, 215,
+ 101, 3, 173, 205, 61, 245, 237, 10, 155, 56, 87, 127, 66, 74, 120,
+ 243, 43, 173, 205, 125, 82, 102, 182, 246, 206, 103, 164, 38, 35, 35,
+ 197, 251, 96, 224, 135, 138, 174, 169, 78, 107, 115, 119, 238, 124, 168,
+ 252, 94, 111, 163, 46, 75, 121, 107, 205, 77, 209, 243, 67, 3, 138,
+ 94, 79, 38, 126, 232, 169, 41, 81, 253, 166, 0, 248, 33, 191, 34,
+ 71, 27, 136, 229, 222, 149, 174, 109, 148, 2, 137, 31, 42, 83, 187,
+ 67, 32, 241, 67, 95, 252, 17, 17, 168, 231, 135, 174, 79, 168, 31,
+ 72, 252, 208, 166, 247, 106, 4, 18, 63, 52, 245, 187, 18, 129, 122,
+ 126, 232, 204, 69, 178, 95, 107, 146, 219, 12, 240, 12, 36, 126, 104,
+ 246, 221, 139, 13, 244, 252, 80, 226, 134, 245, 13, 136, 31, 234, 177,
+ 245, 117, 125, 226, 135, 102, 183, 59, 182, 69, 207, 15, 21, 251, 188,
+ 34, 253, 70, 192, 197, 9, 221, 233, 55, 2, 118, 119, 79, 208, 253,
+ 70, 192, 179, 15, 22, 211, 111, 4, 60, 63, 189, 49, 133, 248, 161,
+ 204, 201, 7, 83, 244, 252, 208, 190, 67, 79, 83, 136, 31, 170, 177,
+ 40, 55, 173, 205, 253, 247, 104, 33, 221, 218, 92, 182, 247, 235, 71,
+ 105, 244, 67, 252, 158, 176, 232, 27, 1, 56, 127, 35, 126, 168, 50,
+ 248, 33, 156, 143, 17, 63, 68, 232, 194, 224, 135, 216, 115, 215, 181,
+ 185, 105, 45, 51, 45, 63, 127, 243, 146, 214, 230, 174, 120, 163, 214,
+ 230, 22, 3, 63, 180, 237, 227, 50, 194, 218, 220, 197, 224, 135, 216,
+ 218, 96, 57, 221, 159, 244, 3, 63, 36, 90, 27, 96, 223, 123, 224,
+ 135, 110, 252, 246, 3, 173, 205, 141, 45, 49, 67, 221, 111, 4, 63,
+ 212, 102, 90, 188, 112, 175, 178, 101, 220, 70, 233, 211, 162, 83, 104,
+ 109, 238, 130, 179, 125, 20, 218, 10, 126, 232, 195, 248, 134, 194, 190,
+ 131, 97, 62, 228, 63, 99, 20, 245, 67, 151, 231, 239, 84, 126, 195,
+ 212, 168, 237, 82, 88, 254, 230, 58, 54, 190, 75, 106, 80, 167, 2,
+ 253, 86, 201, 240, 193, 241, 74, 223, 254, 224, 135, 94, 62, 54, 9,
+ 127, 243, 21, 241, 7, 165, 144, 133, 85, 169, 31, 58, 253, 67, 1,
+ 229, 61, 95, 91, 143, 74, 63, 72, 67, 133, 239, 252, 19, 248, 161,
+ 157, 253, 30, 208, 123, 150, 111, 204, 174, 164, 252, 46, 255, 195, 154,
+ 184, 200, 86, 194, 188, 197, 142, 184, 243, 210, 245, 95, 172, 236, 254,
+ 243, 195, 243, 20, 250, 36, 248, 161, 231, 30, 226, 90, 85, 71, 228,
+ 53, 201, 199, 124, 146, 214, 230, 22, 41, 171, 214, 34, 207, 143, 186,
+ 45, 237, 185, 117, 77, 216, 55, 22, 252, 80, 163, 58, 71, 104, 109,
+ 174, 215, 133, 125, 90, 77, 240, 67, 105, 255, 52, 113, 109, 238, 85,
+ 240, 67, 35, 62, 98, 181, 185, 105, 77, 213, 218, 220, 220, 224, 135,
+ 170, 134, 234, 215, 230, 166, 218, 89, 109, 238, 207, 245, 55, 42, 116,
+ 8, 248, 161, 216, 245, 226, 241, 246, 223, 230, 41, 215, 121, 194, 106,
+ 115, 59, 159, 82, 107, 115, 7, 130, 31, 10, 93, 47, 174, 205, 61,
+ 9, 126, 168, 116, 195, 193, 180, 54, 247, 247, 196, 182, 234, 55, 151,
+ 131, 243, 201, 62, 5, 197, 181, 185, 75, 192, 15, 109, 241, 103, 181,
+ 185, 247, 207, 169, 181, 185, 91, 130, 11, 200, 195, 155, 220, 18, 218,
+ 198, 17, 240, 67, 131, 106, 30, 160, 181, 185, 193, 83, 183, 210, 218,
+ 220, 248, 127, 215, 233, 214, 230, 178, 51, 5, 126, 148, 198, 218, 92,
+ 254, 172, 129, 168, 54, 23, 215, 120, 124, 109, 238, 5, 174, 54, 247,
+ 2, 87, 155, 123, 193, 141, 218, 220, 113, 251, 88, 109, 110, 105, 173,
+ 54, 23, 215, 101, 133, 191, 20, 215, 230, 226, 186, 140, 229, 20, 150,
+ 211, 125, 111, 92, 151, 137, 114, 10, 100, 62, 148, 191, 41, 171, 205,
+ 173, 212, 149, 124, 235, 121, 157, 20, 56, 82, 167, 166, 16, 230, 67,
+ 165, 70, 199, 208, 218, 220, 61, 9, 164, 111, 178, 52, 114, 133, 222,
+ 55, 166, 237, 146, 227, 102, 12, 173, 205, 205, 245, 44, 198, 76, 214,
+ 101, 223, 121, 90, 205, 122, 126, 40, 230, 86, 12, 173, 205, 53, 221,
+ 38, 114, 247, 73, 177, 183, 197, 114, 61, 226, 14, 74, 155, 203, 88,
+ 105, 109, 110, 29, 173, 46, 185, 0, 204, 135, 30, 124, 35, 238, 91,
+ 28, 252, 208, 246, 46, 209, 180, 54, 183, 244, 42, 117, 175, 30, 253,
+ 144, 244, 92, 252, 125, 234, 80, 240, 67, 53, 27, 142, 166, 181, 185,
+ 94, 99, 212, 122, 211, 16, 88, 151, 29, 95, 47, 174, 85, 173, 13,
+ 243, 161, 241, 213, 250, 210, 218, 220, 26, 191, 132, 105, 245, 181, 183,
+ 165, 54, 101, 123, 11, 251, 222, 0, 63, 244, 237, 50, 86, 155, 91,
+ 61, 159, 90, 155, 251, 16, 252, 208, 229, 254, 226, 218, 220, 23, 224,
+ 135, 174, 21, 30, 68, 107, 115, 103, 46, 103, 181, 185, 159, 154, 245,
+ 107, 115, 71, 246, 99, 181, 185, 201, 3, 88, 109, 110, 190, 112, 253,
+ 218, 220, 21, 227, 89, 109, 174, 169, 45, 171, 205, 237, 89, 65, 92,
+ 155, 251, 20, 252, 144, 215, 19, 86, 155, 187, 99, 52, 171, 205, 13,
+ 207, 212, 175, 205, 253, 181, 52, 171, 205, 181, 238, 96, 181, 185, 29,
+ 7, 232, 215, 230, 102, 174, 103, 181, 185, 167, 207, 177, 218, 220, 191,
+ 114, 235, 215, 230, 178, 179, 42, 126, 148, 86, 190, 85, 242, 196, 189,
+ 218, 92, 37, 15, 72, 114, 195, 223, 132, 123, 135, 118, 209, 203, 9,
+ 178, 218, 220, 80, 232, 235, 248, 214, 141, 250, 143, 142, 92, 190, 174,
+ 3, 87, 255, 241, 173, 113, 123, 79, 200, 151, 230, 235, 128, 70, 153,
+ 234, 17, 27, 227, 246, 158, 66, 57, 25, 56, 110, 50, 150, 132, 246,
+ 198, 237, 61, 33, 95, 167, 250, 15, 77, 134, 127, 123, 227, 246, 158,
+ 80, 239, 70, 238, 215, 154, 190, 53, 118, 191, 22, 245, 105, 228, 126,
+ 173, 127, 123, 99, 247, 107, 17, 39, 116, 239, 233, 43, 176, 131, 142,
+ 122, 152, 225, 238, 205, 133, 190, 137, 237, 220, 248, 254, 248, 55, 220,
+ 158, 205, 215, 220, 222, 83, 59, 227, 48, 131, 124, 105, 13, 32, 208,
+ 40, 83, 137, 170, 109, 141, 195, 140, 63, 39, 3, 199, 77, 198, 18,
+ 210, 214, 56, 204, 32, 95, 167, 122, 118, 77, 134, 227, 43, 227, 48,
+ 131, 122, 55, 114, 191, 22, 117, 108, 228, 126, 109, 72, 91, 99, 247,
+ 107, 81, 119, 70, 238, 215, 34, 78, 232, 222, 83, 75, 176, 131, 111,
+ 244, 48, 195, 221, 155, 219, 6, 252, 121, 136, 27, 123, 79, 109, 184,
+ 24, 208, 134, 171, 205, 109, 157, 51, 204, 236, 245, 119, 176, 24, 192,
+ 201, 112, 192, 59, 57, 52, 57, 150, 214, 57, 195, 204, 238, 233, 185,
+ 217, 189, 185, 33, 220, 56, 128, 38, 99, 73, 111, 149, 51, 204, 220,
+ 169, 187, 147, 238, 215, 134, 134, 100, 217, 123, 10, 209, 106, 115, 91,
+ 229, 12, 51, 187, 182, 176, 253, 90, 212, 123, 118, 181, 170, 168, 83,
+ 198, 219, 245, 191, 119, 206, 241, 8, 248, 161, 254, 254, 43, 63, 212,
+ 103, 118, 252, 80, 87, 255, 149, 95, 168, 128, 31, 234, 197, 93, 126,
+ 116, 110, 214, 146, 155, 155, 125, 1, 118, 240, 149, 14, 102, 248, 218,
+ 92, 232, 235, 104, 238, 198, 220, 172, 37, 103, 207, 45, 184, 185, 89,
+ 115, 3, 231, 102, 45, 56, 123, 6, 26, 101, 42, 141, 154, 27, 56,
+ 55, 227, 100, 224, 184, 201, 88, 18, 190, 52, 112, 110, 214, 60, 203,
+ 220, 76, 147, 225, 255, 165, 129, 115, 179, 230, 198, 198, 25, 83, 115,
+ 99, 227, 12, 234, 211, 200, 56, 227, 255, 165, 177, 113, 6, 113, 66,
+ 231, 102, 77, 192, 14, 90, 234, 97, 134, 157, 217, 246, 135, 190, 137,
+ 205, 220, 152, 155, 125, 193, 205, 105, 62, 231, 230, 102, 205, 12, 156,
+ 155, 125, 206, 205, 205, 128, 70, 153, 202, 220, 172, 169, 129, 115, 51,
+ 78, 6, 142, 155, 140, 37, 164, 169, 129, 115, 179, 102, 89, 230, 102,
+ 154, 12, 71, 19, 3, 231, 102, 205, 140, 93, 207, 160, 142, 141, 92,
+ 207, 132, 52, 53, 118, 61, 131, 186, 51, 114, 61, 131, 56, 161, 152,
+ 153, 49, 216, 59, 241, 11, 23, 152, 25, 56, 98, 80, 143, 238, 67,
+ 149, 26, 7, 19, 63, 111, 104, 12, 254, 188, 81, 184, 247, 213, 252,
+ 83, 210, 62, 183, 135, 200, 163, 90, 108, 181, 215, 222, 216, 215, 242,
+ 206, 220, 172, 49, 23, 3, 26, 51, 254, 22, 57, 123, 59, 56, 246,
+ 176, 248, 134, 103, 245, 122, 212, 85, 49, 227, 229, 210, 14, 156, 98,
+ 25, 39, 195, 1, 239, 228, 208, 228, 248, 75, 217, 203, 152, 218, 62,
+ 120, 195, 234, 9, 211, 234, 170, 152, 209, 151, 129, 124, 233, 56, 128,
+ 166, 99, 153, 53, 56, 91, 25, 215, 66, 170, 165, 30, 26, 26, 23,
+ 172, 98, 198, 141, 113, 52, 202, 50, 55, 107, 164, 97, 102, 70, 246,
+ 50, 46, 189, 26, 101, 254, 41, 146, 212, 179, 103, 39, 195, 170, 96,
+ 38, 67, 211, 123, 21, 165, 165, 90, 11, 229, 204, 79, 253, 55, 244,
+ 147, 41, 18, 223, 123, 137, 169, 162, 105, 61, 252, 165, 194, 31, 221,
+ 235, 168, 86, 74, 62, 252, 193, 146, 36, 181, 69, 11, 153, 180, 205,
+ 243, 252, 107, 249, 218, 202, 232, 143, 69, 62, 251, 165, 119, 15, 185,
+ 248, 191, 113, 1, 234, 211, 129, 242, 219, 106, 39, 21, 58, 223, 227,
+ 177, 242, 31, 177, 53, 106, 11, 115, 110, 19, 38, 202, 29, 187, 207,
+ 213, 218, 204, 164, 116, 141, 179, 63, 112, 207, 179, 143, 61, 25, 154,
+ 93, 24, 165, 131, 230, 253, 61, 255, 116, 165, 131, 34, 43, 211, 63,
+ 210, 211, 193, 241, 41, 39, 107, 17, 29, 204, 30, 253, 241, 199, 68,
+ 7, 185, 175, 76, 253, 88, 79, 7, 33, 213, 30, 125, 76, 116, 64,
+ 104, 212, 1, 123, 46, 214, 1, 218, 173, 158, 14, 90, 191, 163, 131,
+ 194, 154, 14, 106, 82, 126, 209, 160, 3, 203, 234, 111, 26, 102, 213,
+ 65, 41, 208, 193, 65, 123, 77, 225, 220, 34, 79, 222, 30, 114, 190,
+ 239, 2, 236, 68, 7, 139, 6, 36, 40, 116, 41, 208, 193, 196, 37,
+ 87, 197, 123, 49, 160, 131, 169, 21, 62, 167, 117, 129, 132, 70, 29,
+ 176, 231, 98, 29, 32, 174, 156, 117, 96, 229, 230, 234, 42, 173, 218,
+ 1, 211, 201, 18, 147, 3, 116, 112, 17, 116, 112, 209, 201, 14, 250,
+ 86, 177, 154, 153, 14, 84, 26, 237, 32, 223, 3, 113, 46, 23, 237,
+ 96, 44, 229, 63, 80, 62, 221, 89, 109, 239, 3, 58, 88, 27, 38,
+ 206, 33, 163, 29, 124, 228, 59, 142, 214, 186, 17, 26, 117, 192, 158,
+ 235, 172, 207, 65, 7, 244, 123, 115, 83, 6, 123, 135, 54, 17, 197,
+ 128, 58, 206, 49, 96, 58, 180, 159, 54, 88, 63, 6, 64, 59, 234,
+ 59, 167, 51, 95, 150, 49, 117, 176, 155, 49, 192, 245, 92, 0, 241,
+ 78, 125, 39, 39, 195, 1, 239, 228, 208, 228, 88, 5, 50, 156, 99,
+ 128, 107, 25, 136, 39, 58, 142, 105, 220, 56, 128, 38, 99, 241, 157,
+ 234, 110, 12, 112, 45, 3, 237, 149, 142, 131, 147, 97, 210, 100, 226,
+ 127, 19, 167, 184, 27, 3, 92, 203, 64, 123, 160, 181, 105, 83, 7,
+ 59, 213, 126, 49, 191, 105, 53, 19, 122, 66, 176, 205, 34, 242, 167,
+ 78, 181, 105, 89, 248, 49, 31, 100, 53, 19, 26, 249, 137, 124, 147,
+ 83, 109, 90, 22, 126, 12, 207, 86, 51, 161, 199, 3, 63, 17, 206,
+ 157, 238, 161, 156, 226, 204, 143, 97, 195, 106, 38, 52, 190, 159, 8,
+ 51, 252, 188, 9, 113, 66, 115, 90, 227, 193, 14, 184, 248, 252, 46,
+ 102, 234, 58, 97, 38, 113, 242, 96, 111, 255, 73, 250, 152, 193, 118,
+ 116, 29, 48, 153, 241, 79, 154, 104, 28, 102, 252, 57, 25, 137, 240,
+ 78, 137, 154, 28, 203, 68, 227, 48, 131, 124, 233, 56, 128, 38, 99,
+ 73, 159, 96, 28, 102, 252, 39, 57, 99, 6, 101, 42, 235, 244, 9,
+ 198, 97, 6, 245, 78, 108, 40, 209, 242, 177, 75, 204, 36, 172, 91,
+ 237, 54, 102, 44, 89, 248, 185, 194, 12, 242, 115, 23, 51, 168, 79,
+ 122, 159, 23, 240, 115, 133, 25, 228, 231, 46, 102, 66, 39, 56, 191,
+ 159, 43, 204, 32, 63, 119, 49, 131, 56, 161, 57, 45, 43, 216, 193,
+ 20, 17, 102, 254, 231, 132, 153, 80, 232, 235, 136, 211, 199, 12, 182,
+ 163, 49, 32, 158, 241, 143, 136, 51, 14, 51, 200, 151, 198, 0, 160,
+ 81, 166, 210, 40, 206, 56, 204, 132, 114, 50, 112, 220, 100, 44, 9,
+ 177, 198, 97, 6, 249, 58, 229, 180, 52, 25, 254, 177, 198, 97, 6,
+ 245, 158, 83, 204, 56, 229, 180, 226, 114, 142, 25, 167, 156, 86, 108,
+ 206, 49, 227, 148, 211, 138, 205, 57, 102, 156, 114, 90, 86, 134, 153,
+ 144, 63, 192, 14, 198, 139, 48, 243, 137, 115, 156, 249, 19, 48, 182,
+ 198, 141, 56, 243, 39, 231, 159, 255, 100, 252, 3, 172, 57, 195, 140,
+ 83, 222, 140, 147, 145, 8, 239, 148, 168, 201, 73, 90, 157, 51, 204,
+ 56, 141, 99, 13, 55, 14, 160, 201, 88, 44, 171, 115, 134, 25, 167,
+ 113, 172, 201, 18, 103, 214, 104, 177, 236, 143, 156, 97, 134, 172, 207,
+ 131, 52, 189, 19, 27, 178, 134, 122, 167, 189, 4, 61, 103, 93, 151,
+ 89, 146, 42, 89, 94, 214, 187, 188, 46, 187, 181, 169, 83, 77, 245,
+ 106, 103, 126, 107, 64, 167, 174, 248, 173, 153, 144, 127, 189, 59, 252,
+ 44, 28, 191, 209, 109, 188, 211, 170, 159, 78, 125, 103, 191, 100, 244,
+ 230, 74, 150, 230, 207, 130, 27, 102, 183, 110, 116, 138, 91, 127, 56,
+ 191, 31, 234, 42, 235, 26, 172, 47, 188, 95, 239, 248, 152, 108, 215,
+ 96, 78, 53, 213, 127, 112, 152, 249, 5, 108, 205, 42, 194, 204, 167,
+ 78, 152, 73, 95, 53, 216, 59, 100, 165, 62, 102, 176, 29, 173, 69,
+ 94, 197, 197, 153, 229, 238, 98, 198, 91, 215, 214, 66, 56, 25, 233,
+ 240, 78, 233, 154, 156, 132, 223, 221, 197, 140, 190, 12, 228, 75, 199,
+ 1, 52, 25, 75, 210, 82, 119, 49, 227, 198, 56, 86, 58, 99, 6,
+ 101, 42, 255, 253, 197, 93, 204, 120, 11, 49, 179, 212, 67, 213, 123,
+ 21, 165, 165, 90, 235, 230, 42, 151, 129, 103, 42, 249, 222, 165, 193,
+ 30, 235, 194, 95, 51, 46, 159, 147, 214, 58, 211, 82, 207, 190, 43,
+ 137, 156, 169, 108, 250, 222, 0, 37, 46, 249, 159, 234, 46, 237, 107,
+ 88, 176, 14, 233, 219, 13, 250, 12, 131, 191, 73, 92, 223, 140, 162,
+ 179, 164, 101, 13, 8, 86, 151, 211, 188, 73, 222, 145, 27, 224, 121,
+ 246, 88, 85, 207, 99, 238, 144, 74, 62, 41, 190, 129, 156, 49, 148,
+ 90, 250, 109, 80, 243, 7, 167, 165, 185, 161, 133, 55, 144, 190, 251,
+ 160, 207, 113, 248, 59, 199, 245, 125, 233, 125, 93, 234, 151, 92, 103,
+ 61, 57, 175, 183, 238, 253, 117, 107, 145, 202, 61, 246, 153, 84, 169,
+ 86, 42, 125, 231, 107, 208, 231, 46, 252, 61, 230, 250, 190, 145, 77,
+ 114, 7, 107, 96, 93, 114, 110, 238, 78, 13, 139, 66, 231, 202, 204,
+ 43, 119, 236, 222, 180, 46, 233, 251, 10, 251, 120, 84, 52, 229, 243,
+ 168, 200, 125, 183, 172, 144, 204, 180, 233, 71, 233, 136, 27, 37, 101,
+ 94, 207, 69, 161, 79, 105, 248, 171, 204, 245, 37, 191, 27, 218, 178,
+ 81, 191, 219, 129, 27, 219, 214, 146, 223, 237, 242, 15, 105, 31, 147,
+ 223, 109, 249, 203, 211, 181, 245, 126, 183, 95, 38, 78, 115, 249, 187,
+ 253, 50, 49, 123, 159, 72, 127, 183, 142, 193, 244, 119, 107, 95, 179,
+ 30, 253, 221, 42, 214, 175, 171, 251, 187, 249, 207, 109, 72, 127, 183,
+ 79, 174, 22, 78, 34, 191, 219, 185, 218, 62, 117, 245, 126, 55, 159,
+ 200, 246, 244, 119, 43, 187, 170, 61, 253, 221, 46, 221, 106, 255, 255,
+ 254, 187, 161, 127, 32, 191, 219, 160, 234, 174, 127, 183, 204, 63, 245,
+ 127, 183, 184, 230, 153, 150, 61, 27, 223, 79, 37, 191, 91, 72, 188,
+ 250, 29, 180, 35, 167, 187, 75, 187, 192, 207, 80, 174, 239, 177, 63,
+ 122, 142, 251, 253, 89, 82, 200, 201, 84, 123, 214, 223, 173, 208, 168,
+ 13, 210, 176, 199, 217, 199, 30, 236, 187, 125, 242, 14, 233, 151, 50,
+ 165, 131, 201, 239, 214, 246, 235, 102, 10, 221, 233, 217, 105, 201, 55,
+ 169, 127, 48, 251, 221, 204, 240, 187, 53, 131, 223, 173, 37, 237, 91,
+ 49, 239, 117, 41, 215, 248, 184, 96, 242, 187, 101, 212, 142, 80, 232,
+ 79, 199, 61, 147, 126, 153, 25, 26, 204, 126, 183, 175, 224, 119, 107,
+ 5, 191, 91, 11, 218, 247, 10, 252, 110, 77, 203, 149, 9, 38, 191,
+ 91, 155, 127, 238, 43, 239, 249, 231, 171, 188, 114, 120, 135, 89, 13,
+ 217, 239, 102, 134, 223, 173, 30, 252, 110, 31, 179, 251, 148, 178, 249,
+ 221, 198, 252, 135, 223, 13, 125, 46, 249, 221, 102, 41, 120, 123, 55,
+ 214, 170, 120, 99, 191, 99, 105, 136, 177, 117, 225, 175, 25, 151, 239,
+ 220, 2, 120, 43, 112, 44, 146, 158, 61, 247, 185, 173, 210, 149, 1,
+ 111, 222, 30, 236, 236, 121, 55, 211, 121, 192, 219, 121, 192, 219, 121,
+ 39, 188, 45, 160, 49, 126, 57, 205, 173, 22, 0, 188, 137, 98, 60,
+ 246, 125, 6, 120, 179, 206, 141, 164, 103, 177, 191, 46, 165, 206, 163,
+ 115, 3, 222, 14, 254, 203, 190, 101, 182, 15, 228, 29, 135, 95, 237,
+ 156, 233, 44, 203, 149, 2, 222, 162, 94, 141, 162, 231, 154, 103, 159,
+ 85, 247, 200, 10, 1, 222, 126, 142, 103, 125, 175, 153, 78, 195, 239,
+ 118, 6, 126, 183, 51, 12, 171, 240, 187, 253, 86, 52, 138, 158, 47,
+ 206, 223, 80, 203, 203, 2, 222, 102, 239, 101, 239, 252, 10, 199, 233,
+ 113, 1, 126, 55, 246, 206, 153, 202, 239, 102, 53, 179, 223, 77, 165,
+ 135, 40, 191, 27, 211, 115, 81, 232, 83, 26, 254, 42, 115, 125, 233,
+ 156, 230, 23, 46, 223, 180, 8, 226, 244, 31, 162, 57, 77, 61, 231,
+ 57, 205, 207, 208, 62, 209, 141, 57, 205, 207, 220, 92, 224, 103, 46,
+ 223, 180, 196, 184, 181, 115, 8, 39, 35, 29, 222, 41, 93, 147, 99,
+ 89, 98, 220, 218, 25, 249, 210, 113, 0, 77, 198, 146, 190, 216, 184,
+ 181, 115, 72, 98, 150, 57, 77, 162, 150, 111, 90, 108, 96, 190, 105,
+ 137, 193, 249, 166, 37, 6, 231, 155, 22, 27, 156, 111, 90, 108, 112,
+ 190, 105, 17, 151, 111, 250, 17, 236, 224, 23, 17, 102, 234, 59, 231,
+ 155, 160, 175, 99, 129, 27, 249, 166, 69, 92, 158, 102, 33, 183, 14,
+ 88, 96, 96, 190, 105, 33, 151, 111, 2, 26, 101, 42, 141, 22, 24,
+ 152, 111, 226, 100, 224, 184, 201, 88, 18, 126, 50, 48, 223, 180, 32,
+ 75, 190, 73, 147, 225, 255, 147, 129, 249, 166, 5, 6, 231, 155, 22,
+ 24, 156, 111, 250, 201, 224, 124, 211, 79, 6, 231, 155, 126, 100, 152,
+ 9, 253, 30, 236, 96, 145, 0, 51, 181, 3, 156, 48, 227, 15, 125,
+ 19, 231, 233, 99, 6, 219, 209, 92, 208, 124, 46, 223, 52, 47, 103,
+ 152, 57, 219, 173, 100, 29, 154, 11, 154, 207, 229, 130, 128, 70, 153,
+ 202, 25, 170, 31, 114, 134, 153, 201, 223, 140, 11, 160, 227, 224, 100,
+ 224, 184, 201, 88, 66, 126, 200, 25, 102, 30, 157, 63, 196, 206, 80,
+ 205, 115, 198, 140, 191, 38, 195, 241, 125, 206, 48, 51, 231, 195, 254,
+ 44, 223, 52, 111, 112, 182, 103, 87, 81, 167, 255, 245, 44, 44, 234,
+ 56, 59, 126, 168, 191, 255, 202, 47, 68, 192, 15, 117, 245, 95, 249,
+ 161, 238, 178, 227, 135, 122, 249, 175, 103, 117, 17, 39, 116, 255, 124,
+ 54, 216, 193, 143, 34, 204, 100, 57, 67, 53, 23, 252, 249, 119, 110,
+ 236, 159, 207, 229, 98, 192, 92, 110, 255, 124, 142, 129, 251, 231, 156,
+ 12, 7, 188, 147, 67, 147, 99, 157, 99, 224, 254, 249, 119, 220, 56,
+ 128, 38, 99, 241, 157, 99, 224, 254, 249, 119, 89, 246, 207, 191, 211,
+ 246, 207, 103, 27, 184, 127, 62, 199, 216, 56, 99, 157, 99, 108, 156,
+ 241, 157, 99, 108, 156, 65, 221, 25, 25, 103, 16, 39, 4, 51, 233,
+ 153, 96, 7, 223, 139, 48, 227, 124, 230, 36, 49, 1, 48, 246, 198,
+ 141, 125, 141, 4, 206, 63, 191, 229, 226, 76, 130, 113, 152, 65, 190,
+ 52, 206, 0, 157, 168, 241, 14, 120, 99, 28, 102, 252, 57, 25, 56,
+ 110, 50, 150, 180, 215, 198, 97, 6, 249, 58, 197, 25, 77, 70, 200,
+ 107, 227, 48, 131, 122, 55, 114, 61, 131, 58, 54, 114, 61, 131, 250,
+ 52, 114, 61, 19, 242, 218, 216, 245, 12, 226, 132, 126, 43, 246, 1,
+ 204, 105, 102, 187, 192, 204, 160, 222, 195, 187, 247, 236, 62, 52, 98,
+ 196, 48, 211, 192, 222, 97, 236, 123, 217, 208, 55, 253, 229, 96, 239,
+ 176, 176, 48, 115, 88, 88, 30, 203, 154, 102, 151, 236, 159, 95, 250,
+ 233, 221, 187, 116, 51, 185, 245, 249, 43, 198, 223, 250, 60, 123, 59,
+ 152, 112, 102, 146, 253, 113, 225, 47, 27, 138, 238, 209, 249, 169, 204,
+ 109, 250, 221, 75, 228, 75, 215, 231, 64, 163, 76, 5, 51, 79, 179,
+ 151, 177, 183, 247, 123, 182, 85, 61, 31, 11, 239, 209, 185, 121, 98,
+ 62, 149, 17, 194, 201, 192, 113, 147, 177, 56, 30, 101, 47, 227, 243,
+ 97, 37, 182, 126, 187, 196, 203, 44, 186, 71, 167, 242, 161, 85, 236,
+ 155, 228, 47, 157, 49, 19, 162, 201, 72, 120, 144, 189, 140, 82, 126,
+ 157, 204, 147, 14, 91, 133, 247, 232, 36, 189, 141, 160, 247, 232, 160,
+ 222, 249, 123, 11, 80, 143, 132, 31, 161, 27, 111, 152, 43, 177, 231,
+ 174, 115, 165, 255, 182, 170, 47, 223, 170, 116, 147, 222, 163, 67, 218,
+ 123, 217, 91, 203, 83, 99, 111, 11, 191, 135, 231, 221, 168, 157, 156,
+ 80, 207, 91, 203, 77, 126, 43, 155, 11, 238, 83, 218, 23, 179, 119,
+ 146, 155, 172, 152, 32, 236, 123, 71, 14, 149, 187, 228, 253, 137, 222,
+ 139, 210, 106, 240, 32, 133, 174, 26, 29, 38, 87, 111, 47, 254, 118,
+ 214, 213, 216, 126, 242, 145, 25, 191, 4, 145, 115, 145, 53, 186, 223,
+ 85, 232, 7, 81, 225, 178, 189, 120, 153, 134, 194, 115, 145, 177, 67,
+ 228, 33, 94, 126, 90, 155, 225, 114, 231, 153, 197, 20, 218, 35, 122,
+ 164, 220, 184, 68, 73, 97, 223, 55, 177, 99, 228, 252, 65, 37, 180,
+ 54, 145, 114, 175, 194, 106, 95, 188, 23, 165, 184, 173, 176, 78, 223,
+ 120, 185, 250, 180, 92, 90, 155, 137, 114, 212, 239, 38, 77, 238, 100,
+ 121, 105, 252, 43, 157, 239, 14, 78, 147, 67, 234, 121, 53, 164, 103,
+ 122, 53, 26, 239, 45, 96, 207, 179, 143, 211, 104, 47, 136, 33, 222,
+ 94, 16, 19, 196, 94, 8, 253, 1, 216, 11, 123, 238, 218, 94, 150,
+ 130, 189, 148, 108, 204, 206, 244, 146, 246, 69, 192, 94, 172, 189, 26,
+ 9, 199, 113, 87, 110, 39, 143, 250, 59, 130, 222, 163, 179, 241, 151,
+ 85, 42, 13, 246, 82, 237, 210, 5, 225, 111, 94, 160, 81, 168, 60,
+ 122, 243, 110, 106, 47, 141, 38, 170, 223, 16, 44, 10, 246, 114, 188,
+ 236, 10, 225, 247, 165, 238, 128, 189, 132, 109, 79, 160, 246, 146, 59,
+ 237, 128, 66, 63, 3, 123, 137, 232, 34, 214, 95, 38, 216, 203, 210,
+ 145, 175, 131, 136, 189, 52, 145, 94, 104, 223, 169, 28, 41, 223, 202,
+ 255, 36, 72, 207, 94, 6, 109, 62, 19, 68, 236, 229, 121, 165, 131,
+ 65, 234, 111, 110, 149, 139, 188, 90, 27, 164, 103, 47, 207, 58, 206,
+ 10, 34, 246, 242, 116, 198, 116, 77, 238, 100, 249, 73, 218, 20, 93,
+ 123, 233, 208, 61, 41, 136, 216, 11, 161, 209, 94, 216, 115, 177, 189,
+ 160, 63, 36, 246, 242, 20, 236, 5, 253, 27, 177, 23, 66, 183, 254,
+ 115, 174, 196, 158, 187, 182, 151, 118, 82, 125, 249, 178, 119, 222, 173,
+ 196, 94, 72, 123, 219, 214, 214, 178, 215, 182, 121, 194, 57, 102, 181,
+ 198, 237, 228, 184, 106, 31, 167, 18, 123, 57, 59, 106, 129, 178, 167,
+ 147, 23, 236, 165, 220, 240, 197, 194, 113, 52, 50, 135, 202, 215, 35,
+ 66, 130, 137, 189, 60, 171, 242, 133, 66, 15, 141, 13, 147, 35, 155,
+ 53, 14, 22, 245, 45, 26, 215, 79, 78, 255, 170, 127, 67, 98, 47,
+ 143, 182, 91, 21, 91, 27, 7, 246, 210, 52, 98, 163, 240, 236, 249,
+ 11, 176, 151, 191, 31, 125, 64, 239, 224, 73, 63, 170, 214, 239, 44,
+ 142, 26, 41, 215, 105, 187, 64, 56, 222, 17, 49, 99, 228, 227, 215,
+ 211, 233, 61, 58, 169, 239, 95, 84, 232, 208, 40, 171, 188, 178, 245,
+ 43, 97, 223, 253, 96, 47, 133, 139, 31, 165, 247, 232, 120, 14, 82,
+ 191, 17, 245, 44, 106, 178, 188, 110, 199, 118, 97, 223, 215, 96, 47,
+ 157, 87, 236, 160, 231, 229, 9, 189, 5, 236, 133, 61, 23, 219, 11,
+ 198, 54, 222, 191, 96, 172, 34, 246, 66, 232, 2, 224, 95, 216, 243,
+ 108, 236, 5, 252, 203, 194, 164, 94, 244, 188, 60, 105, 95, 17, 252,
+ 203, 141, 17, 195, 132, 107, 136, 83, 224, 95, 252, 102, 70, 209, 123,
+ 116, 70, 251, 107, 223, 1, 2, 123, 9, 235, 32, 254, 14, 208, 51,
+ 136, 71, 39, 38, 143, 165, 247, 232, 252, 252, 84, 165, 125, 208, 191,
+ 152, 197, 107, 151, 167, 224, 95, 106, 159, 138, 161, 231, 244, 175, 237,
+ 86, 233, 247, 163, 195, 229, 249, 155, 196, 103, 252, 63, 140, 27, 34,
+ 207, 49, 69, 209, 59, 120, 124, 38, 168, 123, 79, 181, 193, 191, 156,
+ 203, 59, 92, 216, 119, 21, 248, 151, 19, 91, 251, 210, 123, 116, 62,
+ 175, 172, 126, 203, 231, 14, 216, 139, 207, 189, 80, 241, 120, 193, 94,
+ 174, 127, 221, 143, 222, 163, 99, 127, 170, 229, 55, 192, 191, 204, 152,
+ 55, 80, 247, 30, 157, 158, 157, 7, 210, 218, 2, 66, 163, 127, 97,
+ 207, 197, 235, 60, 156, 167, 210, 125, 171, 43, 48, 15, 203, 20, 206,
+ 89, 157, 238, 209, 73, 200, 128, 181, 206, 61, 253, 57, 43, 182, 163,
+ 235, 163, 251, 140, 191, 239, 157, 236, 231, 97, 101, 194, 174, 219, 251,
+ 87, 92, 162, 205, 89, 125, 92, 206, 195, 70, 221, 236, 72, 235, 37,
+ 145, 47, 93, 231, 1, 141, 50, 21, 110, 183, 178, 151, 113, 164, 198,
+ 14, 219, 249, 182, 185, 181, 57, 171, 107, 25, 119, 30, 70, 179, 154,
+ 76, 78, 6, 142, 155, 140, 37, 227, 122, 246, 50, 26, 46, 121, 158,
+ 250, 252, 211, 66, 218, 156, 213, 181, 140, 67, 121, 87, 179, 117, 222,
+ 189, 44, 235, 60, 77, 70, 232, 213, 236, 101, 124, 17, 217, 217, 252,
+ 73, 53, 50, 103, 117, 45, 163, 229, 37, 117, 206, 250, 173, 167, 170,
+ 247, 42, 74, 75, 213, 71, 160, 30, 9, 63, 66, 55, 5, 31, 193,
+ 158, 187, 246, 17, 15, 193, 71, 212, 26, 58, 135, 222, 229, 71, 218,
+ 227, 93, 91, 145, 101, 90, 136, 191, 23, 9, 62, 226, 117, 211, 175,
+ 82, 136, 143, 104, 118, 234, 134, 66, 207, 7, 31, 49, 33, 164, 174,
+ 176, 239, 16, 152, 131, 172, 9, 78, 166, 115, 144, 106, 107, 213, 111,
+ 122, 158, 43, 217, 79, 46, 249, 105, 9, 225, 60, 34, 58, 223, 96,
+ 249, 155, 55, 63, 208, 187, 31, 115, 159, 235, 167, 126, 43, 49, 112,
+ 132, 220, 56, 126, 147, 112, 254, 210, 59, 109, 164, 188, 254, 228, 66,
+ 173, 205, 104, 121, 164, 237, 119, 133, 190, 16, 60, 70, 238, 185, 48,
+ 73, 216, 247, 69, 218, 88, 185, 227, 123, 151, 82, 136, 143, 88, 18,
+ 121, 88, 251, 134, 179, 85, 126, 17, 60, 37, 69, 28, 23, 226, 229,
+ 146, 77, 170, 211, 57, 136, 169, 127, 73, 117, 14, 98, 158, 36, 15,
+ 206, 44, 44, 140, 191, 111, 211, 38, 203, 249, 239, 221, 214, 190, 67,
+ 58, 85, 254, 242, 135, 154, 218, 247, 64, 167, 201, 15, 219, 92, 215,
+ 249, 30, 232, 116, 185, 195, 179, 33, 244, 30, 64, 66, 159, 27, 51,
+ 139, 123, 158, 125, 60, 66, 91, 67, 252, 241, 182, 134, 120, 34, 182,
+ 70, 104, 92, 31, 177, 231, 174, 109, 237, 14, 216, 90, 239, 173, 54,
+ 106, 107, 164, 61, 174, 143, 102, 68, 132, 137, 191, 129, 13, 182, 86,
+ 38, 113, 52, 181, 181, 60, 221, 230, 40, 116, 2, 216, 90, 253, 33,
+ 203, 133, 58, 24, 0, 182, 38, 255, 251, 34, 133, 216, 218, 230, 146,
+ 223, 43, 250, 158, 14, 182, 118, 230, 94, 71, 161, 173, 13, 6, 91,
+ 91, 85, 176, 1, 157, 179, 94, 217, 84, 87, 225, 147, 6, 182, 22,
+ 168, 243, 29, 107, 180, 181, 223, 87, 63, 165, 182, 182, 97, 134, 122,
+ 239, 37, 218, 218, 212, 13, 181, 133, 227, 125, 14, 182, 214, 43, 45,
+ 148, 222, 27, 249, 143, 173, 55, 189, 55, 242, 227, 53, 99, 108, 122,
+ 243, 221, 158, 61, 167, 179, 123, 35, 15, 253, 160, 217, 203, 36, 185,
+ 99, 174, 133, 41, 122, 182, 54, 232, 48, 185, 159, 115, 170, 252, 253,
+ 46, 139, 141, 216, 90, 74, 74, 127, 155, 158, 173, 245, 45, 60, 159,
+ 218, 26, 161, 209, 214, 216, 115, 177, 173, 161, 31, 230, 109, 13, 253,
+ 42, 177, 53, 66, 127, 6, 182, 198, 158, 187, 182, 181, 221, 96, 107,
+ 109, 98, 182, 164, 18, 91, 35, 237, 243, 227, 29, 130, 83, 87, 166,
+ 138, 215, 71, 237, 228, 129, 167, 151, 210, 185, 114, 249, 197, 139, 82,
+ 137, 173, 45, 237, 254, 131, 176, 111, 39, 176, 181, 133, 62, 211, 232,
+ 157, 147, 99, 91, 171, 237, 159, 23, 239, 39, 167, 172, 250, 77, 216,
+ 183, 58, 216, 218, 155, 58, 243, 232, 124, 247, 7, 191, 57, 10, 125,
+ 28, 108, 237, 238, 161, 4, 97, 223, 126, 96, 107, 117, 75, 37, 208,
+ 59, 39, 107, 254, 79, 165, 255, 5, 91, 123, 191, 149, 184, 111, 221,
+ 109, 99, 229, 204, 148, 185, 116, 174, 188, 249, 196, 76, 133, 126, 5,
+ 182, 86, 175, 91, 184, 176, 239, 75, 107, 188, 60, 111, 144, 143, 157,
+ 216, 218, 141, 165, 234, 119, 110, 75, 91, 38, 201, 182, 22, 237, 133,
+ 243, 251, 122, 219, 38, 203, 55, 254, 45, 155, 74, 108, 173, 119, 195,
+ 46, 10, 237, 13, 182, 182, 185, 229, 76, 161, 92, 159, 109, 211, 229,
+ 127, 159, 237, 164, 243, 108, 66, 223, 0, 91, 99, 207, 197, 182, 134,
+ 241, 152, 183, 53, 140, 175, 196, 214, 8, 221, 4, 108, 141, 61, 119,
+ 109, 107, 247, 192, 214, 2, 54, 132, 211, 121, 54, 105, 143, 49, 116,
+ 75, 200, 16, 221, 251, 42, 87, 44, 25, 78, 231, 217, 87, 103, 170,
+ 243, 242, 197, 96, 107, 143, 162, 134, 10, 251, 14, 199, 24, 90, 51,
+ 156, 206, 179, 151, 254, 161, 242, 49, 131, 95, 155, 54, 93, 124, 127,
+ 99, 119, 176, 181, 34, 139, 70, 210, 185, 114, 163, 78, 35, 20, 122,
+ 39, 216, 218, 151, 249, 71, 8, 251, 134, 129, 173, 181, 152, 50, 130,
+ 222, 87, 89, 103, 137, 74, 163, 95, 203, 191, 81, 220, 247, 37, 248,
+ 181, 220, 237, 70, 208, 121, 118, 129, 67, 42, 237, 13, 182, 86, 243,
+ 175, 81, 186, 243, 236, 57, 19, 99, 232, 60, 187, 202, 95, 42, 237,
+ 13, 126, 237, 254, 65, 241, 218, 160, 32, 216, 218, 209, 41, 68, 39,
+ 83, 101, 243, 125, 245, 44, 90, 49, 176, 181, 166, 237, 196, 223, 174,
+ 244, 4, 91, 235, 86, 143, 205, 209, 9, 125, 22, 108, 141, 61, 23,
+ 207, 209, 113, 94, 78, 230, 232, 1, 23, 129, 126, 160, 55, 71, 103,
+ 247, 246, 133, 66, 95, 199, 37, 253, 57, 58, 182, 163, 123, 139, 151,
+ 185, 115, 50, 151, 220, 205, 43, 103, 179, 79, 82, 207, 171, 33, 221,
+ 91, 188, 204, 237, 45, 2, 141, 50, 149, 70, 151, 220, 205, 43, 187,
+ 150, 129, 185, 20, 58, 14, 78, 6, 142, 155, 140, 37, 193, 225, 110,
+ 94, 217, 181, 12, 92, 127, 211, 113, 92, 202, 114, 78, 70, 147, 145,
+ 116, 209, 221, 188, 178, 107, 25, 184, 102, 163, 231, 100, 46, 101, 169,
+ 215, 165, 249, 69, 171, 153, 208, 120, 247, 163, 40, 239, 232, 244, 29,
+ 200, 44, 252, 88, 254, 201, 106, 38, 52, 242, 19, 229, 165, 156, 190,
+ 3, 233, 112, 230, 199, 242, 19, 86, 51, 161, 145, 159, 40, 111, 225,
+ 84, 3, 115, 209, 153, 31, 91, 191, 90, 205, 132, 70, 126, 162, 117,
+ 45, 191, 23, 163, 224, 68, 227, 151, 113, 6, 236, 224, 138, 30, 102,
+ 216, 189, 125, 73, 23, 6, 123, 7, 156, 215, 199, 12, 182, 35, 118,
+ 16, 112, 129, 241, 79, 59, 231, 238, 186, 54, 27, 123, 134, 185, 53,
+ 145, 17, 192, 201, 72, 130, 119, 74, 210, 228, 132, 156, 115, 119, 93,
+ 235, 90, 6, 206, 169, 232, 56, 206, 115, 227, 0, 154, 140, 197, 113,
+ 214, 221, 117, 173, 107, 25, 24, 75, 233, 56, 206, 59, 99, 6, 101,
+ 42, 254, 229, 172, 187, 235, 90, 215, 50, 208, 135, 210, 253, 193, 115,
+ 89, 108, 156, 174, 81, 192, 198, 53, 250, 69, 35, 176, 113, 193, 218,
+ 197, 105, 127, 48, 11, 63, 54, 15, 181, 154, 9, 141, 252, 68, 243,
+ 83, 167, 115, 45, 103, 157, 249, 177, 185, 134, 213, 76, 104, 228, 39,
+ 154, 131, 240, 252, 34, 178, 240, 99, 241, 196, 106, 38, 52, 242, 19,
+ 197, 25, 30, 51, 136, 19, 130, 153, 164, 147, 96, 7, 23, 245, 48,
+ 195, 238, 237, 139, 128, 190, 25, 167, 244, 49, 131, 237, 136, 29, 100,
+ 156, 230, 246, 47, 79, 25, 23, 103, 144, 47, 145, 17, 1, 52, 202,
+ 84, 242, 77, 167, 140, 139, 51, 17, 156, 12, 28, 55, 25, 75, 226,
+ 63, 198, 197, 25, 228, 203, 99, 38, 66, 147, 17, 240, 143, 113, 113,
+ 6, 245, 206, 127, 175, 202, 85, 156, 193, 239, 85, 185, 27, 103, 124,
+ 179, 240, 115, 21, 103, 144, 159, 187, 113, 6, 245, 73, 249, 229, 137,
+ 76, 117, 21, 103, 252, 129, 159, 187, 113, 38, 224, 31, 231, 247, 115,
+ 21, 103, 240, 253, 220, 141, 51, 136, 19, 130, 153, 136, 163, 96, 7,
+ 103, 244, 48, 195, 238, 237, 11, 128, 190, 73, 199, 245, 49, 131, 237,
+ 104, 12, 56, 193, 248, 91, 142, 27, 23, 103, 144, 47, 141, 1, 64,
+ 163, 76, 108, 147, 126, 204, 184, 56, 19, 192, 201, 192, 113, 147, 177,
+ 132, 30, 51, 46, 206, 32, 95, 30, 51, 1, 154, 140, 140, 163, 198,
+ 197, 25, 212, 59, 181, 161, 183, 105, 193, 174, 226, 140, 105, 212, 5,
+ 179, 187, 113, 6, 117, 204, 243, 115, 21, 103, 144, 159, 187, 113, 38,
+ 148, 231, 119, 40, 45, 216, 85, 156, 177, 134, 93, 48, 187, 27, 103,
+ 80, 119, 148, 223, 203, 180, 96, 87, 113, 198, 50, 226, 130, 217, 221,
+ 56, 131, 56, 161, 123, 14, 7, 193, 14, 78, 234, 97, 230, 83, 250,
+ 123, 100, 28, 1, 127, 158, 174, 143, 25, 108, 71, 99, 192, 17, 174,
+ 86, 230, 176, 113, 113, 38, 130, 147, 145, 1, 239, 148, 161, 201, 177,
+ 28, 54, 46, 206, 32, 95, 58, 14, 160, 201, 88, 210, 15, 25, 23,
+ 103, 34, 210, 157, 49, 131, 50, 21, 92, 30, 50, 46, 206, 160, 222,
+ 115, 26, 103, 248, 243, 142, 150, 195, 57, 143, 51, 60, 63, 212, 103,
+ 78, 227, 12, 207, 47, 244, 80, 206, 227, 140, 83, 14, 224, 32, 87,
+ 43, 179, 23, 236, 224, 168, 30, 102, 184, 187, 32, 160, 175, 99, 191,
+ 27, 57, 128, 131, 220, 218, 249, 0, 151, 3, 216, 111, 92, 156, 65,
+ 190, 52, 7, 0, 52, 202, 84, 26, 237, 55, 46, 206, 132, 114, 50,
+ 112, 220, 100, 44, 9, 251, 140, 139, 51, 200, 215, 41, 7, 160, 201,
+ 240, 223, 103, 92, 156, 65, 189, 231, 52, 206, 240, 54, 105, 218, 159,
+ 243, 56, 195, 243, 67, 125, 230, 52, 206, 240, 252, 252, 247, 229, 60,
+ 206, 240, 152, 65, 156, 208, 90, 153, 93, 96, 7, 7, 245, 48, 195,
+ 221, 5, 1, 125, 19, 119, 235, 99, 6, 219, 209, 61, 225, 61, 220,
+ 25, 230, 221, 57, 139, 51, 252, 121, 76, 228, 75, 247, 182, 129, 70,
+ 153, 74, 158, 225, 239, 156, 197, 25, 254, 60, 166, 63, 39, 3, 199,
+ 77, 198, 18, 242, 119, 206, 226, 12, 127, 30, 19, 249, 58, 237, 109,
+ 107, 50, 28, 187, 114, 22, 103, 200, 121, 204, 32, 77, 239, 244, 158,
+ 239, 139, 5, 183, 162, 158, 179, 158, 199, 244, 191, 178, 204, 92, 185,
+ 244, 158, 108, 207, 215, 57, 157, 57, 254, 155, 227, 183, 183, 224, 86,
+ 212, 105, 214, 243, 122, 25, 142, 101, 230, 78, 19, 39, 186, 197, 47,
+ 132, 227, 151, 56, 162, 252, 86, 212, 97, 214, 243, 92, 105, 211, 86,
+ 152, 151, 127, 60, 59, 213, 29, 126, 168, 59, 138, 153, 214, 133, 182,
+ 166, 219, 122, 189, 115, 222, 39, 228, 222, 50, 243, 200, 97, 195, 204,
+ 34, 126, 180, 86, 102, 23, 87, 43, 179, 13, 236, 96, 175, 30, 102,
+ 184, 187, 32, 118, 130, 63, 223, 161, 143, 25, 108, 71, 99, 192, 78,
+ 174, 86, 102, 123, 206, 226, 12, 127, 30, 36, 148, 147, 225, 128, 119,
+ 114, 104, 114, 172, 219, 115, 22, 103, 248, 243, 32, 200, 151, 142, 3,
+ 104, 50, 22, 223, 237, 57, 139, 51, 252, 121, 144, 208, 29, 89, 106,
+ 101, 118, 104, 121, 134, 109, 57, 139, 51, 228, 60, 72, 144, 166, 119,
+ 250, 125, 159, 212, 130, 91, 215, 108, 59, 242, 206, 121, 16, 199, 197,
+ 101, 230, 168, 189, 117, 108, 238, 216, 164, 149, 227, 103, 217, 86, 112,
+ 107, 207, 197, 97, 239, 236, 249, 251, 3, 102, 218, 220, 140, 117, 139,
+ 159, 47, 199, 47, 241, 203, 66, 91, 23, 95, 158, 241, 206, 190, 174,
+ 227, 238, 50, 243, 210, 70, 235, 221, 194, 12, 234, 142, 242, 59, 83,
+ 112, 107, 80, 167, 145, 239, 236, 221, 37, 93, 94, 102, 190, 189, 103,
+ 176, 91, 152, 65, 156, 80, 204, 164, 130, 29, 236, 210, 193, 12, 119,
+ 23, 68, 98, 26, 96, 44, 85, 31, 51, 216, 142, 250, 231, 173, 140,
+ 255, 158, 201, 159, 187, 25, 103, 138, 184, 180, 131, 136, 30, 149, 183,
+ 80, 25, 91, 185, 56, 3, 52, 202, 84, 226, 196, 223, 69, 114, 185,
+ 23, 103, 92, 203, 8, 121, 156, 212, 128, 198, 25, 78, 6, 142, 155,
+ 140, 229, 243, 205, 205, 221, 140, 51, 174, 101, 212, 158, 158, 196, 206,
+ 130, 165, 102, 137, 51, 68, 198, 169, 236, 199, 225, 28, 103, 92, 203,
+ 216, 156, 17, 163, 96, 166, 158, 151, 170, 247, 42, 74, 75, 147, 105,
+ 118, 141, 15, 211, 80, 143, 132, 31, 161, 241, 59, 29, 236, 185, 106,
+ 59, 13, 76, 37, 157, 246, 127, 119, 180, 206, 180, 200, 95, 84, 165,
+ 119, 102, 159, 27, 49, 77, 161, 111, 71, 132, 73, 127, 61, 223, 35,
+ 60, 3, 158, 103, 202, 2, 137, 197, 183, 229, 180, 198, 160, 78, 244,
+ 74, 73, 20, 223, 148, 125, 201, 184, 213, 82, 242, 163, 10, 90, 155,
+ 36, 105, 127, 254, 79, 26, 168, 231, 145, 214, 73, 93, 218, 230, 23,
+ 158, 197, 41, 31, 183, 81, 10, 89, 58, 155, 222, 153, 93, 225, 167,
+ 59, 54, 245, 156, 101, 178, 180, 97, 127, 37, 187, 168, 239, 79, 177,
+ 118, 105, 79, 106, 172, 214, 38, 77, 218, 125, 96, 188, 93, 61, 103,
+ 185, 93, 66, 123, 21, 245, 61, 17, 187, 75, 90, 178, 184, 190, 214,
+ 102, 143, 180, 54, 185, 162, 93, 61, 103, 185, 79, 242, 57, 157, 95,
+ 216, 215, 39, 238, 160, 212, 254, 223, 146, 90, 155, 116, 233, 155, 47,
+ 189, 213, 179, 6, 209, 71, 165, 216, 144, 91, 194, 241, 158, 141, 61,
+ 33, 5, 214, 251, 134, 222, 153, 61, 165, 126, 144, 66, 231, 143, 62,
+ 35, 221, 14, 172, 40, 236, 251, 52, 246, 188, 212, 182, 219, 50, 122,
+ 103, 246, 217, 37, 59, 20, 250, 85, 212, 101, 105, 211, 197, 139, 194,
+ 190, 120, 103, 182, 229, 147, 123, 90, 155, 155, 210, 135, 141, 30, 105,
+ 231, 120, 110, 75, 69, 218, 60, 23, 246, 53, 197, 221, 149, 174, 36,
+ 60, 210, 218, 100, 72, 251, 54, 95, 87, 207, 75, 69, 63, 148, 22,
+ 56, 78, 235, 200, 125, 34, 157, 136, 252, 75, 107, 243, 92, 58, 125,
+ 86, 187, 83, 60, 250, 165, 148, 209, 96, 145, 176, 175, 71, 220, 107,
+ 201, 81, 105, 41, 105, 35, 55, 79, 248, 78, 61, 19, 104, 246, 144,
+ 39, 100, 198, 137, 229, 166, 121, 202, 213, 126, 39, 119, 69, 123, 201,
+ 27, 43, 189, 167, 142, 215, 156, 91, 222, 34, 191, 74, 17, 218, 243,
+ 182, 60, 114, 173, 182, 221, 180, 190, 121, 229, 82, 109, 2, 20, 186,
+ 144, 57, 159, 60, 172, 133, 135, 80, 238, 243, 52, 31, 185, 111, 224,
+ 34, 237, 76, 224, 123, 242, 255, 164, 42, 10, 46, 30, 71, 21, 148,
+ 205, 150, 21, 66, 28, 189, 142, 45, 44, 179, 218, 30, 63, 74, 111,
+ 121, 84, 76, 214, 171, 249, 33, 190, 4, 253, 43, 239, 75, 208, 95,
+ 210, 220, 136, 70, 163, 47, 97, 207, 93, 251, 146, 237, 224, 75, 122,
+ 6, 29, 14, 36, 190, 164, 72, 211, 26, 138, 252, 154, 67, 194, 164,
+ 208, 204, 8, 225, 187, 252, 5, 190, 132, 205, 109, 151, 211, 250, 147,
+ 66, 224, 75, 68, 115, 91, 69, 127, 177, 171, 165, 71, 55, 223, 6,
+ 18, 95, 242, 253, 93, 245, 46, 143, 87, 81, 235, 164, 152, 31, 163,
+ 235, 139, 109, 109, 163, 84, 179, 177, 103, 10, 241, 37, 81, 237, 99,
+ 85, 26, 124, 201, 204, 233, 219, 82, 196, 186, 183, 75, 87, 190, 243,
+ 161, 247, 94, 159, 140, 204, 175, 217, 248, 118, 9, 227, 146, 168, 175,
+ 87, 220, 46, 233, 246, 194, 11, 41, 196, 151, 68, 122, 70, 164, 168,
+ 231, 204, 247, 73, 95, 150, 202, 159, 44, 150, 123, 80, 250, 227, 220,
+ 161, 64, 226, 75, 58, 158, 254, 80, 209, 207, 155, 168, 163, 82, 106,
+ 163, 161, 58, 186, 58, 33, 213, 172, 65, 106, 166, 78, 73, 111, 146,
+ 215, 107, 125, 207, 72, 83, 91, 236, 18, 246, 125, 3, 190, 164, 106,
+ 229, 191, 131, 136, 47, 217, 123, 126, 183, 86, 199, 114, 89, 26, 48,
+ 111, 175, 78, 223, 107, 210, 225, 26, 187, 131, 136, 47, 41, 56, 123,
+ 103, 16, 241, 37, 45, 159, 111, 211, 233, 123, 87, 106, 184, 52, 37,
+ 136, 248, 18, 239, 85, 91, 52, 185, 15, 165, 163, 107, 55, 233, 244,
+ 125, 34, 213, 140, 39, 109, 158, 75, 91, 126, 222, 162, 201, 125, 41,
+ 53, 75, 75, 17, 246, 125, 27, 251, 90, 122, 85, 147, 198, 49, 185,
+ 234, 7, 105, 218, 185, 87, 15, 185, 73, 245, 205, 98, 185, 224, 75,
+ 236, 210, 119, 65, 196, 151, 36, 183, 85, 227, 170, 9, 124, 201, 142,
+ 222, 241, 98, 185, 105, 121, 228, 79, 190, 39, 117, 74, 121, 229, 225,
+ 251, 102, 171, 227, 5, 95, 178, 254, 237, 28, 157, 190, 62, 242, 140,
+ 244, 25, 65, 196, 151, 60, 49, 205, 212, 198, 91, 80, 222, 217, 125,
+ 166, 142, 174, 10, 203, 172, 238, 203, 143, 210, 155, 193, 151, 232, 213,
+ 131, 17, 95, 130, 243, 40, 226, 75, 58, 124, 240, 97, 26, 206, 139,
+ 136, 47, 33, 244, 124, 240, 37, 236, 57, 241, 37, 197, 157, 248, 133,
+ 180, 205, 180, 132, 22, 61, 108, 39, 190, 164, 166, 199, 103, 202, 220,
+ 186, 183, 28, 38, 93, 216, 62, 81, 120, 126, 178, 173, 215, 2, 137,
+ 173, 107, 151, 211, 218, 36, 219, 252, 149, 146, 104, 93, 139, 125, 63,
+ 30, 187, 90, 234, 153, 158, 102, 39, 190, 228, 200, 212, 122, 10, 206,
+ 154, 14, 95, 39, 249, 62, 254, 187, 161, 168, 239, 150, 241, 27, 165,
+ 15, 255, 173, 25, 76, 124, 73, 174, 80, 171, 66, 143, 141, 73, 150,
+ 234, 21, 89, 21, 44, 234, 59, 37, 220, 46, 21, 169, 243, 58, 152,
+ 248, 146, 54, 191, 120, 40, 115, 255, 146, 147, 182, 75, 56, 247, 20,
+ 245, 237, 99, 221, 37, 253, 240, 227, 223, 193, 196, 151, 196, 253, 182,
+ 76, 161, 3, 199, 237, 147, 102, 220, 152, 44, 148, 59, 16, 230, 37,
+ 125, 147, 58, 208, 239, 220, 245, 31, 93, 81, 161, 127, 6, 95, 178,
+ 40, 250, 164, 112, 188, 115, 198, 158, 144, 130, 71, 215, 165, 190, 228,
+ 158, 79, 128, 226, 183, 226, 98, 206, 72, 141, 146, 155, 9, 253, 223,
+ 45, 235, 121, 41, 170, 81, 239, 134, 196, 151, 204, 190, 241, 155, 122,
+ 166, 40, 242, 178, 228, 99, 58, 45, 148, 219, 27, 124, 73, 191, 93,
+ 175, 27, 18, 95, 82, 98, 80, 62, 229, 157, 183, 70, 221, 150, 206,
+ 60, 42, 42, 28, 239, 93, 240, 37, 35, 110, 151, 164, 223, 230, 187,
+ 100, 47, 174, 208, 18, 248, 146, 42, 179, 223, 23, 246, 237, 23, 247,
+ 68, 234, 218, 210, 39, 152, 248, 146, 78, 166, 103, 202, 59, 76, 6,
+ 95, 178, 163, 163, 248, 157, 243, 195, 188, 228, 147, 7, 137, 164, 141,
+ 252, 145, 105, 136, 66, 191, 13, 246, 144, 79, 149, 241, 23, 246, 45,
+ 182, 205, 83, 190, 122, 118, 10, 245, 37, 205, 62, 154, 172, 196, 138,
+ 218, 224, 75, 110, 148, 56, 36, 212, 243, 40, 152, 151, 244, 249, 169,
+ 149, 157, 248, 146, 66, 125, 127, 81, 232, 209, 224, 75, 58, 254, 121,
+ 94, 56, 103, 221, 12, 190, 164, 213, 130, 242, 169, 196, 151, 220, 146,
+ 205, 10, 221, 17, 230, 37, 95, 12, 139, 22, 226, 232, 37, 248, 18,
+ 86, 19, 232, 71, 233, 83, 224, 75, 244, 106, 5, 169, 47, 57, 197,
+ 230, 37, 243, 97, 94, 130, 235, 31, 226, 75, 8, 253, 57, 248, 18,
+ 246, 156, 248, 146, 30, 78, 252, 94, 192, 188, 100, 224, 176, 24, 250,
+ 45, 194, 77, 199, 212, 58, 174, 147, 131, 195, 164, 9, 23, 70, 9,
+ 177, 53, 121, 194, 2, 137, 229, 180, 150, 211, 186, 181, 107, 48, 47,
+ 17, 229, 180, 20, 95, 108, 93, 45, 221, 234, 74, 238, 103, 73, 146,
+ 106, 191, 85, 223, 161, 51, 172, 113, 112, 173, 39, 234, 187, 41, 126,
+ 163, 84, 167, 51, 233, 187, 89, 250, 123, 163, 250, 158, 165, 173, 201,
+ 146, 127, 238, 33, 194, 190, 225, 209, 118, 41, 166, 90, 23, 51, 241,
+ 37, 209, 101, 59, 43, 116, 9, 235, 118, 9, 215, 153, 162, 190, 135,
+ 192, 151, 140, 218, 49, 192, 76, 124, 73, 158, 63, 84, 89, 103, 35,
+ 247, 73, 249, 103, 137, 117, 53, 11, 230, 37, 91, 166, 142, 165, 223,
+ 94, 188, 255, 163, 250, 29, 198, 51, 224, 75, 150, 47, 143, 22, 246,
+ 189, 15, 243, 146, 207, 19, 201, 111, 116, 74, 186, 242, 175, 86, 179,
+ 7, 107, 156, 212, 210, 98, 93, 189, 133, 121, 201, 5, 250, 251, 58,
+ 164, 207, 61, 99, 180, 59, 229, 47, 75, 235, 18, 196, 114, 95, 131,
+ 47, 9, 56, 65, 206, 214, 222, 148, 110, 71, 71, 105, 114, 111, 75,
+ 191, 85, 143, 50, 235, 205, 75, 126, 191, 29, 73, 191, 23, 89, 89,
+ 251, 174, 101, 46, 240, 37, 191, 20, 143, 210, 121, 231, 39, 210, 237,
+ 249, 164, 205, 115, 105, 180, 103, 180, 153, 204, 75, 242, 12, 212, 123,
+ 231, 215, 82, 80, 121, 106, 243, 114, 234, 16, 141, 134, 121, 137, 101,
+ 103, 140, 88, 46, 204, 75, 90, 190, 136, 161, 223, 169, 156, 245, 72,
+ 211, 21, 248, 146, 35, 119, 197, 125, 113, 141, 51, 246, 40, 105, 147,
+ 87, 14, 171, 164, 210, 121, 192, 151, 180, 26, 46, 126, 231, 60, 219,
+ 124, 228, 230, 121, 200, 120, 223, 147, 191, 24, 162, 98, 176, 8, 204,
+ 75, 202, 55, 27, 109, 22, 175, 233, 10, 203, 172, 94, 212, 143, 210,
+ 56, 47, 209, 171, 35, 165, 57, 178, 84, 110, 255, 50, 101, 176, 183,
+ 255, 54, 189, 28, 25, 171, 51, 76, 180, 67, 123, 155, 27, 57, 50,
+ 59, 151, 191, 178, 51, 254, 155, 63, 127, 47, 151, 123, 121, 101, 215,
+ 121, 159, 14, 49, 5, 105, 142, 204, 159, 147, 145, 8, 239, 148, 168,
+ 201, 241, 111, 153, 189, 12, 231, 188, 178, 107, 25, 5, 191, 89, 155,
+ 76, 199, 97, 227, 198, 1, 52, 25, 75, 117, 255, 174, 110, 230, 149,
+ 93, 203, 24, 112, 103, 61, 171, 101, 180, 101, 249, 78, 190, 77, 219,
+ 35, 173, 220, 213, 205, 188, 178, 107, 25, 21, 184, 28, 25, 234, 157,
+ 196, 15, 19, 196, 15, 212, 35, 221, 191, 212, 232, 10, 16, 63, 216,
+ 115, 213, 118, 170, 155, 74, 57, 251, 226, 150, 153, 150, 27, 101, 143,
+ 208, 185, 232, 175, 245, 206, 42, 244, 117, 88, 215, 222, 148, 174, 11,
+ 99, 232, 123, 83, 23, 72, 44, 159, 189, 156, 214, 52, 190, 137, 90,
+ 41, 137, 242, 217, 42, 206, 87, 75, 190, 82, 21, 27, 137, 31, 62,
+ 55, 203, 105, 249, 151, 117, 146, 247, 172, 18, 226, 122, 38, 88, 215,
+ 190, 191, 176, 60, 205, 145, 45, 106, 90, 67, 235, 155, 44, 85, 123,
+ 80, 71, 167, 6, 203, 46, 229, 58, 255, 5, 93, 215, 230, 233, 161,
+ 230, 158, 252, 96, 93, 27, 118, 163, 135, 176, 111, 47, 88, 215, 142,
+ 77, 251, 205, 70, 226, 135, 61, 92, 125, 207, 125, 176, 174, 45, 189,
+ 227, 159, 6, 194, 119, 182, 30, 148, 230, 95, 168, 219, 144, 196, 143,
+ 3, 27, 26, 41, 116, 203, 232, 163, 210, 228, 137, 109, 133, 231, 50,
+ 190, 131, 248, 49, 242, 248, 18, 58, 23, 173, 125, 102, 136, 66, 63,
+ 133, 117, 237, 171, 146, 149, 133, 103, 48, 238, 67, 252, 184, 179, 118,
+ 11, 93, 215, 62, 120, 255, 176, 66, 103, 70, 93, 150, 164, 49, 87,
+ 117, 190, 177, 112, 77, 42, 222, 246, 31, 186, 174, 189, 63, 254, 44,
+ 93, 215, 254, 253, 215, 69, 157, 190, 119, 37, 71, 220, 3, 186, 174,
+ 221, 62, 254, 126, 16, 201, 145, 253, 58, 241, 174, 176, 175, 39, 204,
+ 69, 131, 71, 159, 167, 235, 218, 181, 53, 212, 117, 106, 30, 136, 31,
+ 151, 206, 172, 19, 246, 197, 248, 209, 181, 251, 100, 186, 174, 173, 210,
+ 163, 83, 16, 137, 31, 39, 61, 170, 138, 223, 25, 226, 135, 207, 149,
+ 196, 64, 18, 63, 82, 95, 239, 10, 84, 235, 88, 114, 203, 94, 37,
+ 255, 21, 222, 59, 252, 2, 214, 181, 79, 204, 108, 93, 187, 247, 214,
+ 92, 133, 206, 13, 241, 99, 238, 119, 63, 234, 212, 145, 250, 200, 71,
+ 46, 53, 164, 235, 218, 213, 155, 212, 124, 207, 91, 152, 139, 134, 22,
+ 24, 94, 95, 172, 231, 194, 50, 171, 37, 246, 163, 52, 230, 200, 244,
+ 106, 140, 137, 47, 65, 255, 74, 124, 9, 126, 135, 30, 253, 37, 241,
+ 37, 132, 54, 131, 47, 97, 207, 179, 241, 37, 48, 23, 141, 29, 58,
+ 208, 70, 124, 137, 247, 233, 169, 10, 109, 1, 95, 114, 182, 219, 207,
+ 226, 92, 238, 148, 5, 18, 219, 203, 90, 78, 107, 86, 61, 97, 46,
+ 42, 218, 203, 82, 253, 193, 106, 233, 198, 192, 41, 212, 151, 28, 177,
+ 206, 85, 232, 220, 224, 75, 14, 206, 93, 34, 196, 116, 190, 184, 141,
+ 210, 237, 192, 253, 212, 151, 252, 30, 184, 70, 251, 70, 79, 178, 20,
+ 88, 127, 182, 176, 239, 57, 240, 37, 3, 109, 177, 13, 136, 47, 105,
+ 82, 33, 116, 139, 186, 222, 218, 46, 93, 217, 191, 37, 89, 212, 55,
+ 45, 118, 151, 84, 245, 135, 189, 212, 151, 36, 237, 113, 104, 121, 239,
+ 125, 82, 243, 23, 207, 132, 114, 243, 194, 186, 246, 203, 37, 100, 92,
+ 233, 82, 187, 222, 95, 105, 227, 61, 42, 173, 41, 186, 95, 88, 71,
+ 122, 5, 124, 137, 231, 189, 55, 129, 196, 151, 60, 127, 113, 66, 161,
+ 63, 133, 185, 232, 55, 94, 171, 133, 54, 126, 1, 124, 201, 163, 126,
+ 29, 104, 190, 189, 123, 147, 197, 10, 125, 19, 124, 73, 211, 35, 135,
+ 133, 239, 252, 12, 124, 201, 200, 181, 103, 104, 190, 125, 228, 246, 243,
+ 52, 223, 30, 126, 204, 97, 211, 243, 37, 103, 222, 238, 163, 249, 246,
+ 57, 237, 118, 218, 72, 142, 172, 229, 10, 187, 78, 223, 39, 82, 235,
+ 219, 54, 154, 111, 223, 16, 186, 197, 70, 230, 162, 37, 254, 217, 40,
+ 236, 107, 130, 117, 109, 141, 101, 235, 105, 190, 253, 222, 235, 101, 54,
+ 146, 35, 251, 173, 221, 66, 155, 158, 47, 41, 244, 225, 24, 154, 111,
+ 127, 61, 180, 175, 141, 228, 200, 76, 201, 237, 117, 234, 117, 243, 200,
+ 189, 34, 251, 210, 124, 251, 139, 203, 253, 109, 36, 71, 54, 243, 139,
+ 65, 54, 61, 95, 114, 250, 127, 4, 131, 239, 201, 5, 222, 14, 178,
+ 145, 28, 217, 136, 239, 134, 216, 244, 124, 9, 171, 21, 247, 163, 52,
+ 206, 69, 245, 106, 200, 137, 47, 193, 121, 20, 241, 37, 54, 240, 37,
+ 56, 47, 34, 190, 132, 208, 85, 193, 151, 176, 231, 196, 151, 148, 112,
+ 226, 55, 31, 124, 137, 87, 239, 43, 116, 94, 178, 254, 171, 42, 202,
+ 186, 250, 71, 88, 215, 126, 177, 161, 139, 112, 141, 189, 10, 214, 181,
+ 108, 31, 123, 57, 173, 73, 190, 0, 190, 68, 180, 143, 141, 125, 11,
+ 196, 175, 150, 182, 21, 77, 75, 37, 190, 164, 215, 147, 131, 10, 253,
+ 101, 204, 58, 169, 228, 213, 179, 194, 179, 86, 119, 193, 151, 180, 14,
+ 242, 216, 74, 124, 201, 216, 133, 143, 149, 246, 111, 103, 37, 75, 143,
+ 190, 185, 46, 236, 187, 111, 188, 93, 186, 209, 99, 113, 42, 241, 37,
+ 59, 54, 116, 87, 232, 74, 224, 75, 154, 213, 203, 35, 236, 59, 126,
+ 194, 46, 41, 169, 201, 77, 234, 75, 166, 191, 63, 69, 153, 79, 44,
+ 137, 218, 39, 173, 253, 177, 170, 240, 59, 64, 107, 6, 28, 148, 130,
+ 207, 255, 70, 115, 100, 99, 218, 109, 86, 232, 123, 99, 143, 74, 183,
+ 223, 223, 39, 236, 59, 215, 122, 66, 58, 112, 116, 105, 48, 241, 37,
+ 230, 66, 243, 21, 122, 18, 204, 75, 186, 124, 61, 77, 216, 55, 32,
+ 254, 188, 36, 143, 142, 15, 38, 190, 100, 223, 228, 126, 10, 93, 53,
+ 230, 178, 52, 44, 119, 11, 97, 223, 55, 209, 215, 164, 99, 126, 36,
+ 87, 117, 83, 74, 90, 252, 82, 25, 239, 202, 168, 219, 82, 250, 39,
+ 151, 132, 115, 169, 137, 224, 75, 78, 7, 189, 79, 115, 100, 7, 51,
+ 84, 186, 11, 248, 146, 45, 75, 139, 9, 229, 214, 135, 121, 73, 159,
+ 106, 158, 52, 71, 118, 111, 215, 117, 69, 86, 67, 240, 37, 243, 62,
+ 219, 43, 148, 27, 12, 190, 164, 102, 202, 18, 154, 35, 123, 47, 100,
+ 168, 66, 251, 131, 47, 25, 94, 170, 138, 176, 239, 123, 219, 60, 229,
+ 110, 7, 194, 104, 142, 108, 253, 237, 135, 138, 143, 47, 7, 190, 164,
+ 230, 163, 59, 66, 76, 143, 134, 117, 237, 151, 109, 218, 211, 28, 89,
+ 245, 124, 191, 43, 244, 56, 240, 37, 150, 31, 28, 194, 58, 240, 95,
+ 113, 239, 238, 64, 5, 154, 35, 43, 218, 215, 162, 214, 159, 71, 22,
+ 148, 231, 15, 143, 18, 218, 228, 85, 240, 37, 236, 91, 0, 126, 148,
+ 62, 14, 190, 68, 239, 27, 1, 196, 151, 224, 122, 137, 248, 146, 185,
+ 224, 75, 42, 112, 57, 50, 66, 227, 222, 93, 133, 44, 57, 178, 234,
+ 166, 8, 39, 126, 123, 192, 151, 248, 53, 137, 162, 57, 50, 191, 178,
+ 234, 250, 252, 85, 68, 152, 84, 115, 187, 120, 125, 94, 19, 230, 37,
+ 236, 12, 203, 114, 90, 115, 94, 19, 124, 137, 232, 12, 11, 246, 149,
+ 227, 86, 75, 147, 251, 15, 162, 57, 178, 85, 33, 234, 247, 135, 66,
+ 96, 94, 82, 226, 211, 62, 194, 115, 150, 79, 96, 141, 211, 170, 94,
+ 87, 154, 35, 203, 157, 174, 126, 235, 104, 149, 53, 89, 26, 217, 191,
+ 167, 176, 111, 51, 171, 93, 122, 94, 104, 56, 205, 145, 13, 91, 163,
+ 214, 84, 111, 139, 220, 46, 201, 77, 197, 245, 216, 111, 97, 94, 82,
+ 249, 172, 149, 230, 200, 134, 182, 81, 219, 215, 141, 217, 39, 141, 250,
+ 55, 82, 216, 119, 43, 172, 113, 254, 55, 38, 130, 230, 200, 34, 98,
+ 212, 26, 248, 199, 81, 71, 165, 13, 19, 197, 231, 74, 207, 193, 188,
+ 228, 219, 126, 67, 105, 142, 172, 88, 127, 245, 253, 111, 131, 47, 249,
+ 173, 255, 72, 157, 119, 62, 47, 205, 90, 56, 138, 230, 200, 78, 149,
+ 27, 163, 229, 170, 46, 75, 21, 127, 30, 43, 236, 123, 3, 230, 37,
+ 51, 90, 176, 28, 217, 196, 43, 42, 253, 6, 124, 201, 232, 177, 226,
+ 251, 167, 51, 193, 151, 124, 86, 44, 138, 230, 200, 26, 21, 100, 57,
+ 178, 214, 121, 162, 116, 222, 249, 137, 148, 118, 144, 229, 200, 242, 52,
+ 136, 214, 114, 115, 47, 165, 22, 191, 139, 229, 226, 26, 39, 53, 128,
+ 229, 200, 38, 141, 97, 57, 178, 144, 237, 58, 191, 47, 204, 75, 174,
+ 189, 97, 57, 178, 190, 79, 89, 142, 236, 223, 187, 49, 58, 245, 246,
+ 121, 228, 126, 123, 89, 142, 236, 247, 98, 44, 71, 118, 177, 167, 248,
+ 157, 115, 111, 243, 145, 7, 222, 138, 164, 57, 178, 223, 251, 168, 24,
+ 204, 7, 243, 18, 175, 94, 163, 117, 116, 85, 88, 102, 223, 122, 240,
+ 163, 52, 206, 75, 244, 190, 1, 65, 207, 43, 167, 112, 223, 92, 222,
+ 52, 216, 27, 115, 102, 226, 28, 25, 171, 191, 244, 135, 190, 137, 91,
+ 220, 56, 175, 156, 194, 229, 175, 146, 185, 243, 202, 105, 198, 213, 197,
+ 32, 95, 154, 191, 2, 26, 101, 42, 50, 182, 24, 87, 23, 227, 207,
+ 201, 192, 113, 147, 177, 164, 109, 54, 174, 46, 6, 249, 58, 157, 35,
+ 211, 100, 132, 108, 54, 174, 46, 6, 245, 110, 100, 253, 37, 234, 216,
+ 200, 250, 75, 212, 167, 145, 245, 151, 33, 155, 141, 173, 191, 68, 156,
+ 16, 204, 36, 172, 7, 59, 72, 209, 195, 12, 171, 191, 12, 129, 190,
+ 233, 27, 221, 248, 230, 242, 38, 238, 91, 197, 127, 49, 254, 161, 27,
+ 141, 171, 139, 65, 190, 244, 155, 203, 64, 163, 76, 197, 99, 111, 48,
+ 174, 46, 38, 132, 147, 129, 227, 38, 99, 177, 110, 48, 174, 46, 6,
+ 249, 58, 125, 115, 89, 147, 225, 187, 193, 184, 186, 24, 212, 187, 145,
+ 245, 151, 168, 99, 35, 235, 47, 173, 27, 140, 173, 191, 244, 221, 96,
+ 108, 253, 37, 226, 132, 126, 79, 198, 18, 238, 157, 190, 73, 15, 51,
+ 172, 254, 210, 23, 250, 38, 172, 213, 199, 12, 182, 35, 118, 144, 176,
+ 142, 241, 247, 95, 107, 92, 156, 65, 190, 68, 134, 47, 208, 40, 83,
+ 153, 197, 38, 25, 23, 103, 124, 57, 25, 56, 110, 50, 22, 75, 146,
+ 113, 113, 6, 249, 242, 152, 241, 213, 100, 36, 193, 111, 99, 84, 156,
+ 65, 189, 27, 89, 127, 137, 58, 54, 178, 254, 210, 146, 100, 108, 253,
+ 37, 234, 206, 200, 250, 75, 196, 9, 253, 182, 127, 227, 71, 158, 9,
+ 235, 245, 48, 195, 213, 95, 102, 132, 123, 103, 124, 245, 200, 83, 183,
+ 254, 18, 218, 209, 26, 252, 144, 55, 158, 244, 23, 135, 190, 70, 197,
+ 25, 228, 75, 109, 173, 199, 35, 79, 148, 169, 216, 156, 64, 198, 127,
+ 141, 51, 200, 151, 214, 69, 3, 95, 50, 150, 196, 54, 217, 203, 248,
+ 175, 113, 6, 249, 242, 152, 65, 153, 202, 254, 101, 227, 236, 101, 252,
+ 215, 56, 131, 122, 55, 178, 254, 210, 55, 11, 191, 156, 214, 95, 162,
+ 62, 141, 172, 191, 68, 221, 25, 89, 127, 137, 56, 161, 223, 147, 233,
+ 11, 118, 192, 249, 51, 215, 152, 97, 245, 151, 9, 141, 160, 175, 172,
+ 143, 25, 108, 71, 99, 64, 35, 246, 219, 39, 74, 217, 219, 129, 59,
+ 113, 102, 210, 194, 8, 59, 141, 1, 156, 140, 4, 120, 167, 4, 77,
+ 142, 111, 255, 236, 101, 184, 19, 103, 22, 116, 98, 53, 43, 200, 151,
+ 142, 3, 104, 50, 150, 196, 126, 217, 203, 112, 39, 206, 216, 46, 60,
+ 11, 166, 227, 144, 157, 49, 131, 50, 149, 117, 153, 64, 134, 59, 113,
+ 166, 249, 160, 110, 20, 51, 168, 247, 236, 238, 238, 66, 157, 50, 222,
+ 174, 255, 189, 51, 247, 233, 159, 61, 63, 212, 223, 127, 229, 135, 250,
+ 204, 142, 31, 234, 234, 191, 242, 11, 16, 240, 67, 189, 184, 203, 143,
+ 126, 79, 166, 47, 195, 76, 68, 47, 160, 57, 127, 230, 26, 51, 172,
+ 254, 50, 0, 250, 38, 133, 233, 99, 6, 219, 209, 239, 176, 244, 97,
+ 252, 45, 97, 57, 139, 51, 163, 63, 107, 79, 231, 102, 200, 151, 198,
+ 50, 160, 81, 166, 146, 113, 235, 157, 179, 56, 147, 158, 60, 138, 206,
+ 205, 2, 56, 25, 56, 110, 50, 150, 208, 222, 57, 139, 51, 127, 124,
+ 249, 47, 197, 12, 242, 117, 250, 158, 140, 38, 35, 163, 87, 206, 226,
+ 76, 207, 251, 61, 216, 247, 100, 194, 178, 183, 33, 212, 233, 127, 181,
+ 73, 212, 113, 118, 252, 80, 127, 255, 149, 95, 168, 128, 31, 234, 234,
+ 191, 242, 67, 221, 101, 199, 15, 245, 242, 95, 49, 163, 224, 132, 172,
+ 107, 35, 193, 14, 250, 234, 96, 166, 14, 171, 191, 204, 232, 249, 200,
+ 51, 49, 90, 31, 51, 216, 142, 230, 155, 98, 24, 127, 107, 207, 156,
+ 197, 25, 167, 188, 89, 12, 147, 225, 15, 116, 134, 198, 59, 32, 58,
+ 103, 113, 198, 41, 111, 198, 201, 192, 113, 147, 177, 164, 69, 229, 44,
+ 206, 56, 229, 205, 162, 157, 49, 227, 175, 201, 8, 137, 202, 89, 156,
+ 113, 250, 110, 89, 79, 206, 134, 12, 88, 207, 160, 142, 141, 92, 207,
+ 160, 62, 141, 92, 207, 132, 68, 57, 191, 95, 78, 215, 51, 136, 19,
+ 154, 55, 27, 253, 200, 51, 162, 151, 30, 102, 216, 121, 204, 16, 232,
+ 155, 62, 86, 31, 51, 216, 142, 230, 155, 198, 49, 254, 161, 99, 141,
+ 91, 207, 32, 95, 154, 55, 3, 26, 101, 42, 184, 30, 99, 220, 122,
+ 38, 132, 147, 129, 227, 38, 99, 177, 142, 49, 110, 61, 131, 124, 157,
+ 242, 102, 154, 12, 223, 49, 198, 173, 103, 80, 239, 70, 174, 103, 80,
+ 199, 70, 174, 103, 172, 99, 140, 93, 207, 248, 142, 49, 118, 61, 131,
+ 56, 33, 152, 9, 25, 14, 118, 16, 169, 135, 25, 246, 29, 102, 95,
+ 232, 155, 48, 82, 31, 51, 216, 142, 174, 53, 70, 49, 254, 254, 35,
+ 141, 139, 51, 200, 151, 174, 53, 128, 70, 153, 74, 190, 105, 132, 113,
+ 113, 198, 151, 147, 129, 227, 38, 99, 177, 140, 48, 46, 206, 32, 95,
+ 167, 188, 153, 38, 35, 125, 184, 113, 113, 6, 245, 110, 228, 254, 12,
+ 234, 216, 200, 253, 25, 203, 136, 156, 199, 25, 167, 185, 227, 240, 156,
+ 199, 25, 126, 110, 134, 56, 161, 152, 233, 2, 118, 48, 90, 15, 51,
+ 236, 59, 204, 233, 195, 30, 121, 250, 119, 211, 199, 12, 182, 163, 49,
+ 96, 24, 227, 239, 24, 106, 92, 156, 9, 225, 100, 36, 194, 59, 165,
+ 107, 114, 146, 186, 26, 23, 103, 144, 47, 157, 255, 1, 77, 198, 98,
+ 233, 106, 92, 156, 241, 239, 230, 140, 25, 148, 169, 232, 186, 139, 113,
+ 113, 6, 245, 110, 228, 254, 12, 234, 216, 200, 253, 25, 75, 215, 156,
+ 199, 25, 39, 204, 116, 201, 121, 156, 113, 194, 76, 23, 134, 25, 107,
+ 42, 216, 193, 240, 108, 48, 51, 188, 251, 208, 97, 89, 238, 145, 77,
+ 239, 12, 237, 59, 185, 129, 153, 206, 28, 102, 58, 51, 254, 1, 29,
+ 179, 183, 131, 216, 214, 211, 236, 7, 10, 52, 212, 48, 227, 229, 58,
+ 7, 208, 39, 15, 187, 227, 149, 147, 145, 14, 239, 148, 174, 201, 241,
+ 237, 32, 144, 177, 176, 76, 234, 189, 220, 165, 131, 85, 204, 184, 150,
+ 113, 115, 116, 5, 54, 255, 235, 196, 141, 3, 104, 50, 150, 140, 246,
+ 217, 203, 24, 155, 249, 40, 245, 232, 192, 175, 181, 187, 151, 93, 203,
+ 8, 253, 242, 61, 154, 255, 11, 233, 228, 140, 25, 148, 169, 16, 91,
+ 179, 151, 209, 236, 239, 174, 230, 253, 251, 8, 102, 92, 203, 168, 126,
+ 92, 173, 149, 201, 208, 244, 94, 69, 105, 169, 222, 39, 130, 122, 164,
+ 57, 0, 141, 14, 89, 56, 94, 98, 207, 93, 159, 37, 57, 181, 182,
+ 128, 92, 108, 72, 43, 237, 188, 119, 11, 153, 180, 247, 121, 220, 81,
+ 158, 148, 80, 73, 184, 118, 121, 154, 127, 144, 188, 251, 205, 4, 122,
+ 79, 102, 171, 17, 234, 221, 142, 185, 50, 227, 228, 182, 59, 215, 136,
+ 107, 26, 114, 77, 145, 55, 92, 76, 165, 119, 93, 18, 58, 226, 198,
+ 119, 220, 243, 236, 231, 107, 25, 154, 93, 240, 58, 192, 223, 153, 232,
+ 128, 208, 168, 3, 246, 60, 123, 29, 172, 152, 18, 78, 239, 138, 34,
+ 237, 81, 7, 30, 47, 11, 218, 244, 116, 176, 237, 230, 28, 122, 79,
+ 215, 160, 204, 70, 41, 68, 7, 27, 118, 120, 166, 232, 233, 224, 250,
+ 248, 127, 147, 137, 14, 8, 141, 58, 96, 207, 197, 58, 64, 187, 229,
+ 117, 128, 118, 72, 116, 64, 232, 54, 160, 3, 246, 60, 155, 111, 214,
+ 128, 14, 46, 151, 252, 202, 78, 116, 64, 218, 231, 7, 29, 244, 45,
+ 34, 62, 187, 255, 4, 116, 112, 114, 219, 80, 122, 127, 212, 161, 98,
+ 37, 109, 68, 7, 79, 23, 39, 235, 234, 96, 226, 252, 69, 41, 68,
+ 7, 132, 70, 29, 176, 231, 98, 29, 32, 174, 120, 29, 32, 78, 136,
+ 14, 8, 141, 118, 192, 158, 103, 111, 7, 7, 183, 198, 208, 187, 117,
+ 72, 251, 124, 160, 131, 252, 167, 197, 231, 200, 208, 14, 254, 188, 19,
+ 67, 239, 154, 249, 94, 59, 191, 137, 58, 168, 245, 72, 220, 23, 117,
+ 208, 129, 158, 83, 155, 73, 105, 212, 65, 7, 157, 243, 107, 36, 6,
+ 160, 223, 167, 49, 96, 19, 248, 181, 46, 194, 24, 224, 116, 47, 163,
+ 9, 250, 90, 109, 24, 3, 170, 166, 133, 133, 85, 148, 55, 148, 158,
+ 187, 181, 195, 166, 222, 22, 169, 145, 135, 83, 12, 192, 118, 196, 175,
+ 89, 237, 220, 250, 60, 37, 123, 191, 182, 96, 84, 160, 189, 66, 169,
+ 239, 133, 49, 224, 92, 196, 253, 20, 34, 3, 249, 82, 223, 137, 50,
+ 82, 181, 57, 77, 114, 246, 50, 194, 62, 44, 159, 218, 98, 252, 246,
+ 134, 162, 24, 208, 170, 194, 192, 64, 58, 14, 78, 6, 142, 155, 140,
+ 197, 127, 75, 246, 50, 28, 233, 143, 82, 27, 253, 220, 77, 24, 3,
+ 222, 126, 146, 143, 198, 0, 228, 235, 180, 223, 72, 244, 181, 57, 123,
+ 25, 219, 7, 132, 154, 167, 108, 21, 199, 0, 180, 67, 98, 247, 168,
+ 119, 222, 238, 81, 143, 132, 31, 161, 209, 238, 217, 115, 147, 233, 59,
+ 83, 77, 211, 50, 211, 135, 166, 85, 240, 71, 108, 232, 52, 216, 253,
+ 149, 219, 201, 245, 137, 221, 147, 246, 232, 255, 50, 206, 188, 175, 235,
+ 255, 254, 90, 97, 165, 216, 239, 208, 243, 39, 138, 253, 191, 167, 172,
+ 178, 233, 217, 253, 208, 111, 237, 244, 14, 55, 66, 163, 221, 179, 231,
+ 98, 236, 163, 93, 240, 58, 192, 223, 153, 232, 128, 208, 168, 3, 246,
+ 28, 117, 240, 225, 59, 58, 64, 236, 183, 237, 227, 77, 239, 83, 39,
+ 237, 81, 7, 223, 166, 87, 12, 212, 211, 193, 235, 179, 151, 146, 137,
+ 14, 110, 207, 108, 67, 99, 64, 201, 215, 147, 117, 253, 223, 45, 207,
+ 89, 212, 255, 17, 26, 117, 192, 158, 139, 117, 128, 118, 203, 235, 0,
+ 237, 144, 232, 128, 208, 24, 3, 216, 115, 212, 193, 71, 160, 131, 154,
+ 160, 131, 154, 78, 49, 224, 196, 208, 214, 52, 6, 144, 246, 24, 3,
+ 62, 220, 152, 161, 27, 3, 186, 79, 235, 69, 237, 96, 124, 61, 31,
+ 106, 7, 11, 60, 23, 234, 234, 224, 74, 116, 36, 213, 1, 161, 81,
+ 7, 236, 185, 78, 12, 216, 236, 172, 3, 230, 175, 173, 102, 66, 163,
+ 29, 240, 126, 252, 59, 83, 99, 208, 65, 99, 208, 65, 99, 39, 59,
+ 8, 220, 205, 98, 0, 105, 143, 49, 160, 205, 121, 253, 24, 144, 114,
+ 143, 197, 128, 181, 15, 88, 12, 88, 233, 70, 12, 232, 193, 197, 128,
+ 30, 92, 12, 232, 225, 110, 12, 216, 196, 98, 128, 101, 61, 248, 181,
+ 84, 189, 24, 192, 242, 77, 38, 232, 107, 221, 168, 191, 14, 192, 118,
+ 212, 119, 254, 197, 248, 251, 110, 116, 119, 29, 224, 122, 61, 136, 115,
+ 62, 234, 59, 255, 226, 124, 39, 202, 216, 164, 237, 109, 111, 112, 119,
+ 29, 224, 90, 6, 206, 169, 232, 56, 56, 25, 56, 110, 50, 150, 128,
+ 13, 238, 174, 3, 92, 203, 192, 57, 11, 29, 199, 198, 44, 49, 64,
+ 147, 145, 182, 222, 221, 117, 64, 54, 121, 134, 187, 49, 116, 237, 140,
+ 122, 231, 239, 244, 97, 115, 103, 171, 153, 208, 235, 44, 54, 139, 104,
+ 78, 237, 180, 223, 189, 193, 153, 31, 155, 135, 90, 205, 132, 94, 15,
+ 252, 68, 243, 83, 167, 253, 238, 44, 252, 216, 156, 206, 106, 38, 52,
+ 242, 19, 205, 245, 156, 206, 23, 175, 119, 230, 199, 230, 71, 86, 51,
+ 161, 145, 159, 104, 222, 196, 175, 157, 17, 39, 4, 51, 105, 127, 131,
+ 29, 108, 210, 195, 12, 203, 55, 165, 173, 123, 228, 105, 89, 171, 63,
+ 111, 194, 118, 196, 14, 44, 235, 24, 255, 244, 36, 119, 231, 77, 174,
+ 237, 0, 99, 36, 145, 97, 225, 100, 164, 193, 59, 165, 105, 114, 66,
+ 147, 220, 157, 55, 185, 150, 129, 49, 136, 142, 99, 45, 55, 14, 160,
+ 201, 88, 146, 118, 187, 59, 111, 114, 45, 3, 125, 60, 29, 199, 90,
+ 103, 204, 160, 76, 101, 254, 183, 219, 221, 121, 147, 107, 25, 61, 56,
+ 204, 160, 222, 121, 27, 98, 115, 13, 171, 153, 208, 104, 67, 162, 57,
+ 136, 211, 126, 119, 22, 126, 44, 110, 91, 205, 132, 70, 126, 162, 120,
+ 238, 148, 191, 218, 237, 204, 143, 197, 64, 171, 153, 208, 200, 79, 20,
+ 27, 157, 242, 87, 89, 248, 245, 224, 48, 211, 131, 195, 76, 15, 55,
+ 49, 131, 56, 161, 107, 141, 237, 96, 7, 235, 245, 48, 195, 234, 78,
+ 44, 208, 55, 109, 167, 126, 156, 193, 118, 212, 158, 119, 49, 254, 33,
+ 59, 141, 139, 51, 200, 151, 218, 51, 208, 40, 83, 201, 3, 239, 48,
+ 46, 206, 88, 56, 25, 56, 110, 50, 150, 136, 29, 198, 197, 25, 228,
+ 203, 99, 198, 66, 244, 181, 195, 184, 56, 131, 122, 39, 54, 148, 102,
+ 218, 186, 213, 85, 156, 49, 221, 139, 116, 59, 206, 160, 142, 121, 126,
+ 174, 226, 12, 242, 115, 55, 206, 68, 100, 225, 231, 42, 206, 32, 63,
+ 119, 227, 140, 41, 11, 63, 87, 113, 6, 249, 185, 27, 103, 16, 39,
+ 236, 14, 35, 176, 131, 191, 245, 48, 195, 234, 78, 76, 208, 215, 154,
+ 230, 198, 250, 124, 59, 55, 167, 217, 198, 248, 39, 29, 54, 46, 206,
+ 32, 95, 106, 107, 40, 99, 187, 230, 159, 15, 27, 23, 103, 76, 156,
+ 12, 28, 55, 25, 75, 250, 33, 227, 226, 12, 242, 117, 154, 155, 105,
+ 50, 66, 15, 25, 23, 103, 80, 239, 188, 13, 185, 138, 51, 104, 67,
+ 238, 198, 25, 75, 22, 126, 174, 226, 12, 242, 115, 55, 206, 160, 62,
+ 121, 126, 174, 226, 12, 242, 115, 55, 206, 132, 102, 225, 231, 42, 206,
+ 32, 63, 119, 227, 12, 226, 132, 221, 97, 4, 118, 176, 93, 15, 51,
+ 159, 114, 119, 24, 61, 242, 116, 236, 119, 227, 12, 253, 65, 102, 7,
+ 142, 3, 140, 127, 196, 126, 227, 226, 12, 242, 101, 119, 24, 61, 242,
+ 68, 153, 74, 163, 253, 198, 197, 153, 80, 78, 6, 142, 155, 140, 37,
+ 97, 159, 113, 113, 6, 249, 58, 223, 97, 164, 229, 205, 246, 25, 23,
+ 103, 80, 239, 57, 141, 51, 38, 167, 59, 140, 114, 30, 103, 76, 78,
+ 119, 24, 229, 60, 206, 152, 156, 238, 48, 202, 121, 156, 49, 57, 221,
+ 97, 196, 48, 19, 122, 14, 236, 224, 160, 30, 102, 62, 227, 238, 48,
+ 122, 228, 153, 120, 65, 63, 206, 96, 59, 186, 183, 125, 145, 219, 11,
+ 188, 96, 92, 156, 65, 190, 116, 111, 27, 104, 148, 169, 172, 7, 206,
+ 27, 23, 103, 252, 57, 25, 56, 110, 50, 150, 144, 243, 198, 197, 25,
+ 228, 235, 116, 182, 81, 147, 225, 56, 103, 92, 156, 65, 189, 231, 52,
+ 206, 56, 157, 69, 60, 159, 243, 56, 227, 116, 22, 241, 124, 206, 227,
+ 12, 207, 15, 117, 151, 211, 56, 195, 99, 6, 113, 66, 239, 99, 57,
+ 5, 118, 176, 87, 15, 51, 172, 238, 196, 113, 22, 252, 249, 25, 253,
+ 56, 131, 237, 104, 12, 56, 203, 248, 103, 156, 206, 89, 156, 225, 247,
+ 207, 67, 57, 25, 14, 120, 39, 135, 38, 199, 122, 58, 103, 113, 134,
+ 223, 63, 71, 190, 116, 28, 64, 147, 177, 248, 158, 206, 89, 156, 225,
+ 247, 207, 67, 207, 56, 99, 6, 101, 42, 249, 191, 83, 57, 139, 51,
+ 100, 255, 60, 72, 211, 59, 189, 211, 167, 155, 119, 218, 232, 3, 207,
+ 222, 217, 63, 79, 74, 59, 108, 158, 248, 251, 232, 192, 236, 246, 12,
+ 157, 106, 120, 57, 126, 37, 186, 122, 167, 205, 47, 253, 107, 80, 214,
+ 189, 104, 199, 246, 195, 230, 209, 241, 110, 222, 97, 196, 241, 75, 107,
+ 225, 157, 86, 108, 72, 155, 134, 89, 247, 117, 67, 79, 30, 54, 23,
+ 110, 255, 149, 221, 29, 126, 168, 59, 194, 47, 52, 212, 59, 13, 117,
+ 149, 117, 143, 212, 10, 227, 109, 50, 54, 198, 189, 59, 140, 78, 113,
+ 235, 153, 99, 96, 7, 231, 244, 48, 195, 234, 78, 18, 255, 1, 127,
+ 126, 82, 63, 206, 96, 59, 26, 3, 254, 225, 214, 51, 39, 114, 22,
+ 103, 248, 253, 70, 127, 78, 70, 34, 188, 83, 162, 38, 199, 114, 34,
+ 103, 113, 134, 223, 111, 68, 190, 116, 28, 64, 147, 177, 164, 31, 207,
+ 89, 156, 225, 247, 27, 253, 79, 102, 57, 167, 117, 82, 91, 207, 28,
+ 207, 89, 156, 33, 251, 141, 65, 154, 222, 137, 13, 205, 7, 204, 92,
+ 26, 243, 216, 150, 117, 191, 49, 13, 108, 104, 229, 184, 207, 178, 221,
+ 111, 116, 90, 207, 112, 252, 38, 3, 191, 6, 107, 199, 217, 222, 217,
+ 187, 219, 118, 216, 28, 212, 229, 97, 182, 123, 119, 78, 235, 153, 227,
+ 140, 223, 104, 192, 76, 205, 125, 223, 52, 204, 186, 15, 150, 4, 152,
+ 233, 180, 169, 117, 182, 251, 96, 78, 235, 153, 227, 206, 152, 65, 93,
+ 101, 221, 83, 66, 204, 252, 58, 62, 251, 61, 37, 167, 245, 204, 49,
+ 110, 61, 115, 9, 236, 224, 148, 14, 102, 184, 123, 191, 66, 161, 175,
+ 227, 136, 27, 235, 153, 99, 92, 12, 56, 202, 213, 55, 222, 113, 55,
+ 206, 20, 116, 105, 7, 43, 228, 125, 244, 155, 198, 200, 151, 198, 0,
+ 160, 81, 166, 50, 183, 185, 229, 110, 156, 113, 45, 35, 180, 79, 50,
+ 91, 207, 112, 50, 112, 220, 100, 44, 137, 215, 220, 141, 51, 217, 200,
+ 184, 91, 143, 197, 178, 35, 89, 214, 51, 154, 12, 255, 203, 238, 198,
+ 25, 215, 50, 182, 189, 82, 49, 243, 121, 46, 85, 239, 85, 148, 150,
+ 38, 83, 116, 141, 15, 211, 80, 143, 132, 31, 161, 27, 36, 197, 91,
+ 216, 115, 215, 223, 33, 29, 220, 58, 211, 210, 191, 95, 121, 205, 158,
+ 3, 164, 197, 129, 181, 20, 250, 127, 167, 186, 75, 248, 219, 137, 206,
+ 181, 188, 231, 55, 75, 98, 241, 109, 57, 61, 19, 150, 63, 243, 15,
+ 73, 20, 223, 176, 111, 102, 174, 245, 210, 189, 184, 181, 244, 190, 157,
+ 193, 203, 212, 187, 172, 60, 50, 109, 210, 143, 77, 19, 132, 231, 170,
+ 94, 229, 218, 33, 133, 140, 220, 77, 191, 225, 103, 93, 175, 221, 71,
+ 149, 121, 64, 106, 241, 188, 144, 240, 60, 210, 203, 92, 199, 164, 246,
+ 123, 63, 208, 218, 156, 146, 138, 127, 25, 164, 210, 209, 103, 164, 65,
+ 62, 77, 132, 125, 95, 199, 158, 151, 102, 31, 108, 169, 181, 113, 72,
+ 158, 141, 212, 24, 137, 223, 151, 31, 178, 249, 27, 97, 223, 92, 113,
+ 215, 164, 239, 31, 182, 213, 218, 220, 148, 202, 111, 234, 162, 208, 190,
+ 209, 183, 165, 135, 227, 250, 8, 251, 150, 143, 187, 43, 33, 150, 180,
+ 153, 157, 100, 181, 68, 42, 244, 252, 232, 135, 82, 159, 51, 221, 133,
+ 125, 15, 199, 62, 145, 26, 77, 190, 64, 191, 233, 233, 223, 82, 189,
+ 155, 106, 75, 212, 75, 233, 235, 53, 167, 55, 139, 250, 218, 98, 95,
+ 75, 79, 99, 190, 161, 223, 7, 222, 95, 98, 170, 66, 191, 10, 246,
+ 144, 207, 223, 93, 46, 190, 143, 42, 205, 83, 30, 177, 176, 15, 253,
+ 14, 223, 155, 15, 219, 169, 116, 116, 30, 121, 112, 171, 143, 116, 238,
+ 159, 201, 39, 159, 121, 213, 136, 126, 227, 247, 217, 167, 13, 232, 221,
+ 53, 126, 67, 3, 116, 239, 174, 97, 103, 19, 253, 40, 141, 223, 191,
+ 210, 59, 179, 72, 176, 133, 254, 134, 96, 11, 239, 193, 66, 255, 65,
+ 231, 72, 26, 45, 1, 182, 216, 115, 215, 216, 218, 6, 216, 202, 95,
+ 109, 90, 10, 193, 86, 82, 155, 207, 21, 58, 24, 176, 245, 217, 202,
+ 199, 194, 187, 157, 26, 2, 182, 216, 92, 111, 57, 61, 107, 88, 11,
+ 176, 37, 154, 235, 97, 223, 2, 94, 235, 165, 60, 39, 124, 236, 4,
+ 91, 219, 171, 202, 10, 157, 15, 176, 21, 62, 102, 140, 208, 94, 254,
+ 5, 108, 45, 155, 246, 43, 189, 219, 110, 198, 89, 155, 66, 63, 126,
+ 117, 64, 58, 248, 193, 73, 97, 95, 47, 175, 99, 210, 218, 186, 119,
+ 40, 182, 22, 188, 246, 80, 206, 45, 215, 3, 108, 229, 205, 240, 22,
+ 126, 199, 208, 39, 254, 188, 132, 190, 156, 96, 171, 240, 60, 31, 133,
+ 246, 138, 187, 44, 229, 63, 147, 33, 148, 219, 127, 252, 53, 233, 88,
+ 68, 56, 197, 214, 149, 184, 210, 138, 126, 126, 6, 108, 85, 92, 90,
+ 65, 232, 195, 74, 143, 187, 43, 69, 22, 205, 71, 191, 113, 217, 223,
+ 175, 136, 66, 127, 111, 125, 40, 221, 133, 184, 34, 234, 123, 9, 176,
+ 213, 120, 246, 210, 134, 4, 91, 123, 199, 215, 87, 104, 63, 192, 214,
+ 197, 233, 213, 133, 182, 246, 32, 230, 181, 36, 207, 43, 64, 198, 37,
+ 247, 75, 104, 163, 208, 179, 1, 91, 185, 23, 77, 21, 142, 247, 14,
+ 96, 171, 89, 46, 114, 119, 161, 151, 252, 123, 165, 177, 10, 93, 8,
+ 176, 53, 178, 107, 127, 29, 31, 150, 79, 126, 83, 169, 134, 157, 96,
+ 107, 206, 7, 185, 21, 58, 51, 170, 160, 92, 184, 231, 118, 155, 30,
+ 182, 216, 153, 87, 63, 74, 227, 247, 179, 245, 206, 194, 210, 184, 117,
+ 141, 97, 107, 22, 98, 11, 226, 38, 197, 150, 70, 43, 216, 162, 207,
+ 9, 182, 222, 189, 175, 242, 104, 183, 149, 244, 251, 217, 197, 103, 77,
+ 87, 232, 98, 167, 187, 75, 9, 227, 186, 8, 223, 165, 111, 177, 89,
+ 18, 91, 247, 44, 167, 103, 88, 195, 94, 255, 33, 137, 214, 61, 216,
+ 119, 50, 96, 235, 11, 223, 227, 20, 91, 255, 171, 80, 68, 177, 83,
+ 11, 96, 107, 154, 165, 129, 208, 198, 127, 6, 108, 181, 92, 62, 36,
+ 149, 96, 171, 121, 216, 116, 133, 62, 6, 216, 250, 242, 233, 18, 97,
+ 223, 23, 128, 173, 118, 215, 215, 166, 18, 108, 149, 239, 189, 71, 161,
+ 243, 198, 156, 145, 186, 175, 58, 38, 236, 107, 25, 127, 94, 194, 57,
+ 12, 193, 214, 221, 63, 174, 42, 116, 163, 217, 151, 37, 251, 169, 227,
+ 194, 190, 227, 18, 174, 73, 109, 27, 206, 77, 37, 216, 178, 125, 92,
+ 95, 161, 235, 143, 191, 45, 13, 238, 61, 93, 168, 171, 69, 157, 239,
+ 74, 127, 125, 82, 142, 98, 171, 118, 68, 3, 133, 94, 51, 225, 161,
+ 116, 4, 230, 83, 162, 190, 243, 162, 158, 72, 201, 103, 250, 80, 108,
+ 45, 238, 222, 89, 241, 157, 211, 70, 191, 148, 74, 255, 28, 35, 148,
+ 251, 89, 212, 107, 169, 72, 255, 71, 20, 91, 17, 113, 249, 149, 119,
+ 158, 0, 216, 42, 91, 173, 108, 170, 30, 182, 70, 143, 32, 223, 16,
+ 246, 146, 171, 52, 120, 165, 240, 241, 2, 108, 205, 61, 243, 143, 80,
+ 238, 77, 192, 86, 205, 87, 75, 41, 182, 34, 214, 170, 247, 136, 222,
+ 5, 108, 125, 123, 172, 157, 176, 111, 38, 96, 139, 157, 165, 246, 163,
+ 116, 50, 96, 75, 239, 140, 53, 141, 91, 151, 25, 182, 240, 219, 244,
+ 56, 95, 36, 216, 34, 52, 126, 3, 150, 61, 119, 253, 13, 216, 52,
+ 192, 86, 194, 124, 118, 79, 210, 230, 100, 149, 174, 8, 113, 203, 113,
+ 78, 124, 214, 249, 113, 209, 89, 18, 203, 1, 44, 167, 103, 163, 243,
+ 66, 220, 18, 229, 0, 148, 24, 0, 216, 170, 190, 147, 221, 117, 20,
+ 81, 68, 253, 230, 103, 41, 192, 214, 31, 161, 227, 132, 125, 11, 121,
+ 237, 144, 198, 121, 140, 166, 223, 98, 45, 127, 95, 253, 38, 106, 69,
+ 152, 19, 254, 118, 78, 124, 79, 82, 115, 192, 86, 157, 242, 225, 244,
+ 123, 170, 69, 188, 251, 41, 180, 4, 113, 235, 199, 177, 97, 194, 190,
+ 29, 226, 206, 75, 56, 119, 39, 216, 218, 237, 173, 126, 55, 192, 110,
+ 189, 44, 181, 110, 217, 91, 216, 183, 119, 204, 53, 105, 40, 189, 75,
+ 233, 166, 180, 161, 135, 58, 198, 47, 163, 110, 75, 87, 3, 196, 186,
+ 218, 20, 123, 87, 42, 91, 123, 52, 253, 158, 234, 147, 153, 42, 221,
+ 8, 230, 132, 7, 238, 136, 191, 211, 187, 21, 226, 86, 169, 147, 209,
+ 244, 123, 170, 159, 255, 21, 163, 125, 199, 245, 165, 244, 113, 115, 241,
+ 29, 75, 15, 97, 78, 120, 195, 70, 191, 215, 42, 95, 14, 82, 105,
+ 188, 191, 204, 97, 139, 212, 189, 115, 104, 83, 72, 20, 253, 158, 106,
+ 112, 66, 148, 118, 215, 81, 30, 185, 69, 161, 104, 179, 222, 156, 240,
+ 219, 127, 163, 233, 55, 81, 189, 191, 32, 247, 66, 21, 148, 55, 254,
+ 30, 99, 214, 139, 91, 236, 140, 190, 31, 165, 113, 78, 168, 119, 118,
+ 159, 238, 127, 92, 226, 114, 185, 177, 176, 110, 60, 166, 183, 198, 102,
+ 231, 224, 67, 97, 61, 152, 56, 75, 63, 47, 21, 202, 173, 27, 29,
+ 233, 92, 205, 237, 116, 119, 243, 82, 174, 215, 141, 63, 70, 236, 164,
+ 247, 94, 35, 95, 186, 198, 6, 26, 101, 42, 235, 223, 201, 238, 230,
+ 165, 92, 203, 168, 210, 38, 141, 202, 8, 229, 100, 224, 184, 201, 88,
+ 252, 39, 184, 155, 151, 114, 45, 35, 207, 125, 137, 237, 227, 204, 202,
+ 178, 198, 214, 100, 36, 198, 186, 155, 151, 114, 45, 163, 49, 183, 198,
+ 70, 189, 19, 127, 26, 9, 254, 20, 245, 72, 248, 17, 26, 215, 216,
+ 236, 57, 241, 167, 31, 154, 2, 185, 51, 224, 3, 193, 159, 14, 247,
+ 47, 75, 191, 207, 255, 127, 228, 125, 119, 116, 20, 85, 244, 255, 38,
+ 244, 30, 32, 116, 132, 208, 73, 1, 150, 42, 66, 96, 119, 134, 162,
+ 244, 80, 20, 172, 132, 14, 210, 130, 244, 146, 176, 9, 32, 82, 132,
+ 40, 8, 34, 136, 1, 21, 34, 2, 198, 0, 138, 144, 132, 13, 77,
+ 164, 70, 138, 70, 138, 44, 189, 72, 9, 33, 129, 16, 8, 252, 238,
+ 157, 153, 87, 38, 108, 102, 246, 251, 203, 251, 227, 123, 206, 55, 231,
+ 236, 225, 158, 225, 221, 123, 231, 221, 185, 159, 119, 95, 187, 239, 149,
+ 232, 30, 164, 208, 45, 161, 61, 197, 239, 71, 120, 251, 90, 2, 45,
+ 35, 224, 55, 147, 219, 59, 93, 10, 198, 1, 108, 62, 44, 150, 238,
+ 185, 47, 9, 237, 169, 209, 124, 24, 242, 90, 160, 61, 13, 47, 122,
+ 172, 45, 105, 79, 227, 214, 191, 163, 222, 179, 2, 237, 105, 74, 232,
+ 70, 218, 63, 141, 3, 158, 237, 240, 219, 105, 105, 196, 48, 3, 125,
+ 149, 132, 116, 114, 39, 205, 33, 169, 126, 72, 101, 37, 22, 23, 132,
+ 246, 52, 103, 195, 171, 180, 79, 157, 8, 60, 201, 240, 59, 192, 241,
+ 230, 192, 24, 123, 114, 249, 129, 237, 72, 123, 122, 227, 89, 68, 59,
+ 50, 198, 62, 60, 109, 62, 229, 61, 12, 60, 199, 45, 141, 45, 41,
+ 240, 227, 239, 169, 70, 127, 38, 237, 169, 245, 194, 114, 133, 46, 14,
+ 99, 108, 91, 204, 114, 202, 123, 18, 120, 78, 195, 239, 47, 142, 55,
+ 59, 242, 154, 180, 225, 206, 92, 122, 31, 100, 161, 59, 170, 94, 188,
+ 55, 35, 229, 249, 68, 202, 155, 10, 60, 103, 225, 119, 158, 123, 231,
+ 202, 48, 198, 190, 208, 115, 70, 59, 210, 158, 222, 122, 109, 176, 66,
+ 55, 135, 246, 180, 70, 237, 174, 148, 247, 34, 240, 93, 2, 190, 43,
+ 28, 47, 158, 79, 237, 10, 46, 65, 251, 42, 133, 171, 169, 247, 231,
+ 166, 65, 123, 122, 110, 214, 8, 106, 231, 107, 192, 115, 3, 126, 183,
+ 184, 111, 116, 24, 218, 211, 137, 67, 206, 145, 113, 184, 92, 51, 76,
+ 205, 243, 194, 246, 180, 79, 246, 30, 250, 125, 239, 0, 207, 61, 248,
+ 165, 113, 188, 79, 161, 61, 205, 217, 96, 163, 119, 240, 84, 236, 59,
+ 175, 173, 218, 38, 22, 150, 223, 232, 157, 66, 231, 95, 210, 129, 39,
+ 3, 126, 89, 28, 47, 182, 167, 117, 35, 106, 183, 33, 237, 233, 142,
+ 35, 167, 119, 145, 246, 212, 119, 116, 56, 213, 155, 131, 60, 94, 65,
+ 150, 66, 94, 65, 186, 246, 148, 229, 126, 248, 82, 26, 219, 83, 62,
+ 39, 164, 56, 240, 148, 134, 95, 57, 142, 151, 142, 3, 62, 209, 143,
+ 177, 177, 253, 32, 216, 34, 52, 142, 3, 216, 115, 247, 216, 194, 49,
+ 246, 249, 83, 75, 232, 93, 211, 227, 78, 118, 84, 232, 70, 128, 173,
+ 202, 217, 236, 158, 169, 190, 192, 51, 2, 126, 51, 57, 222, 50, 128,
+ 45, 54, 55, 28, 75, 115, 57, 42, 0, 182, 140, 230, 134, 149, 111,
+ 94, 96, 155, 244, 236, 55, 114, 127, 242, 78, 233, 159, 71, 218, 253,
+ 80, 128, 173, 147, 171, 202, 183, 99, 216, 106, 4, 216, 106, 164, 195,
+ 86, 58, 96, 107, 244, 170, 246, 237, 8, 182, 250, 78, 121, 179, 157,
+ 186, 159, 255, 168, 84, 180, 239, 24, 67, 108, 213, 130, 190, 74, 175,
+ 117, 163, 40, 182, 90, 215, 93, 168, 249, 233, 89, 169, 214, 137, 229,
+ 134, 216, 122, 7, 250, 42, 216, 142, 19, 108, 189, 253, 243, 143, 10,
+ 61, 22, 250, 42, 247, 247, 27, 99, 235, 222, 156, 107, 210, 235, 147,
+ 239, 208, 251, 173, 146, 34, 235, 42, 118, 251, 15, 176, 213, 177, 89,
+ 151, 68, 134, 173, 70, 128, 173, 32, 192, 22, 107, 195, 134, 133, 223,
+ 149, 18, 55, 91, 146, 8, 182, 182, 62, 45, 163, 208, 27, 194, 211,
+ 165, 17, 65, 53, 147, 24, 182, 252, 1, 91, 254, 128, 173, 134, 28,
+ 62, 50, 165, 183, 26, 164, 39, 18, 108, 109, 219, 118, 82, 161, 255,
+ 4, 108, 21, 237, 180, 45, 145, 97, 203, 31, 176, 21, 0, 216, 10,
+ 160, 188, 223, 1, 182, 14, 223, 161, 99, 20, 185, 74, 85, 117, 238,
+ 227, 54, 96, 235, 139, 65, 3, 18, 25, 182, 2, 0, 91, 129, 128,
+ 173, 64, 221, 157, 52, 47, 122, 189, 71, 199, 216, 183, 19, 187, 39,
+ 170, 237, 80, 97, 121, 196, 170, 70, 137, 12, 91, 129, 128, 173, 64,
+ 192, 86, 32, 215, 14, 21, 147, 187, 119, 56, 79, 239, 149, 153, 61,
+ 70, 189, 123, 254, 41, 140, 3, 238, 55, 98, 121, 79, 57, 200, 227,
+ 6, 91, 44, 167, 200, 151, 210, 56, 198, 230, 115, 141, 140, 176, 133,
+ 113, 150, 96, 107, 9, 96, 11, 227, 38, 193, 22, 161, 17, 91, 236,
+ 57, 98, 203, 255, 37, 108, 237, 7, 108, 149, 61, 203, 198, 216, 107,
+ 55, 168, 119, 84, 85, 133, 49, 118, 217, 107, 253, 18, 140, 176, 53,
+ 1, 198, 216, 108, 157, 36, 150, 230, 8, 141, 134, 49, 182, 209, 58,
+ 9, 242, 206, 131, 184, 181, 114, 255, 41, 58, 198, 62, 89, 83, 29,
+ 99, 183, 1, 108, 189, 63, 132, 141, 177, 227, 224, 187, 109, 135, 239,
+ 190, 147, 243, 151, 207, 1, 91, 247, 158, 179, 49, 246, 128, 46, 234,
+ 24, 251, 56, 140, 177, 143, 71, 179, 49, 118, 162, 165, 62, 96, 171,
+ 62, 96, 171, 30, 229, 173, 94, 232, 148, 212, 169, 111, 28, 29, 99,
+ 55, 206, 58, 168, 208, 1, 48, 198, 158, 210, 231, 100, 18, 195, 86,
+ 93, 192, 86, 29, 192, 86, 109, 202, 59, 26, 198, 216, 216, 135, 33,
+ 216, 10, 125, 113, 69, 161, 7, 125, 126, 89, 90, 187, 134, 141, 207,
+ 79, 90, 106, 1, 182, 106, 1, 182, 24, 239, 8, 24, 99, 63, 29,
+ 20, 77, 199, 216, 203, 6, 55, 81, 232, 213, 115, 110, 75, 155, 167,
+ 142, 226, 176, 85, 15, 176, 213, 80, 135, 173, 75, 239, 222, 149, 238,
+ 183, 12, 162, 99, 108, 215, 244, 206, 10, 29, 53, 63, 93, 146, 161,
+ 63, 197, 176, 101, 5, 108, 53, 5, 108, 53, 165, 188, 205, 97, 140,
+ 109, 153, 57, 129, 198, 45, 223, 231, 95, 41, 109, 247, 197, 169, 217,
+ 210, 168, 107, 11, 18, 245, 113, 43, 72, 135, 173, 117, 179, 114, 164,
+ 230, 109, 188, 73, 189, 228, 173, 77, 43, 40, 244, 100, 192, 214, 168,
+ 172, 6, 73, 12, 91, 254, 128, 45, 127, 192, 86, 67, 221, 24, 123,
+ 86, 168, 15, 29, 99, 187, 182, 169, 227, 109, 196, 86, 221, 95, 175,
+ 115, 216, 242, 7, 108, 249, 3, 182, 252, 185, 57, 183, 98, 114, 213,
+ 233, 63, 210, 49, 118, 194, 13, 117, 174, 236, 58, 96, 107, 85, 60,
+ 27, 99, 231, 224, 187, 122, 5, 0, 182, 152, 173, 158, 2, 182, 88,
+ 174, 154, 47, 165, 119, 3, 182, 248, 28, 182, 226, 192, 83, 26, 126,
+ 229, 56, 94, 26, 183, 34, 245, 99, 236, 142, 220, 24, 187, 35, 55,
+ 198, 238, 248, 210, 24, 187, 35, 96, 171, 163, 110, 140, 253, 211, 106,
+ 54, 198, 238, 145, 192, 198, 216, 255, 113, 99, 236, 190, 192, 51, 2,
+ 126, 51, 57, 94, 28, 99, 179, 53, 195, 88, 154, 123, 134, 99, 108,
+ 163, 53, 67, 228, 45, 6, 216, 90, 149, 202, 198, 216, 139, 36, 117,
+ 12, 86, 9, 176, 53, 113, 19, 27, 99, 199, 1, 207, 118, 248, 237,
+ 180, 116, 96, 119, 87, 195, 24, 251, 240, 52, 54, 198, 14, 140, 157,
+ 172, 208, 53, 33, 110, 77, 250, 251, 35, 27, 195, 86, 7, 192, 86,
+ 7, 192, 86, 7, 238, 46, 246, 83, 82, 191, 109, 227, 233, 24, 123,
+ 197, 118, 245, 126, 151, 142, 216, 39, 108, 49, 210, 198, 176, 37, 3,
+ 182, 100, 192, 150, 76, 121, 37, 136, 91, 216, 119, 39, 216, 106, 48,
+ 81, 189, 211, 101, 17, 196, 173, 135, 225, 108, 124, 126, 210, 34, 1,
+ 182, 36, 192, 150, 68, 121, 163, 97, 140, 61, 35, 112, 26, 29, 99,
+ 191, 177, 77, 173, 227, 24, 24, 99, 159, 105, 197, 108, 149, 10, 239,
+ 122, 22, 126, 231, 57, 91, 197, 195, 24, 123, 99, 97, 54, 198, 126,
+ 175, 190, 74, 183, 130, 62, 161, 79, 103, 54, 198, 190, 8, 124, 151,
+ 224, 119, 133, 171, 239, 17, 136, 91, 103, 226, 216, 157, 37, 227, 180,
+ 251, 135, 159, 66, 220, 122, 56, 158, 233, 189, 6, 250, 110, 192, 239,
+ 22, 167, 247, 17, 196, 173, 126, 85, 217, 24, 123, 255, 31, 179, 232,
+ 157, 37, 173, 166, 179, 49, 246, 29, 224, 185, 7, 191, 52, 142, 23,
+ 199, 216, 127, 212, 97, 99, 236, 94, 19, 217, 24, 251, 157, 114, 108,
+ 140, 157, 14, 60, 25, 240, 203, 226, 120, 177, 79, 88, 33, 135, 141,
+ 177, 223, 255, 128, 141, 177, 191, 223, 195, 222, 57, 7, 121, 188, 58,
+ 2, 182, 58, 234, 226, 22, 203, 129, 244, 165, 52, 246, 9, 249, 220,
+ 200, 226, 192, 83, 26, 126, 229, 56, 94, 186, 247, 35, 146, 141, 177,
+ 45, 107, 96, 204, 124, 201, 108, 140, 205, 242, 63, 98, 28, 15, 189,
+ 237, 107, 205, 215, 177, 177, 28, 205, 205, 248, 134, 203, 153, 250, 90,
+ 220, 190, 92, 148, 75, 115, 51, 224, 157, 80, 167, 50, 70, 253, 90,
+ 220, 190, 92, 148, 75, 235, 1, 52, 169, 75, 218, 26, 113, 251, 114,
+ 237, 107, 115, 229, 76, 173, 213, 246, 125, 173, 17, 183, 47, 23, 237,
+ 46, 50, 255, 35, 244, 107, 177, 249, 31, 104, 79, 145, 249, 31, 142,
+ 53, 98, 243, 63, 16, 39, 52, 207, 112, 229, 67, 111, 191, 72, 51,
+ 204, 176, 252, 15, 199, 106, 40, 251, 149, 249, 188, 20, 150, 163, 126,
+ 176, 154, 201, 143, 94, 37, 110, 95, 174, 133, 211, 225, 128, 119, 114,
+ 104, 122, 252, 86, 137, 219, 151, 139, 114, 105, 61, 128, 38, 117, 137,
+ 251, 82, 220, 190, 92, 203, 87, 122, 204, 160, 78, 165, 79, 240, 165,
+ 184, 125, 185, 104, 119, 145, 249, 31, 126, 171, 196, 230, 127, 160, 61,
+ 69, 230, 127, 216, 191, 20, 155, 255, 129, 56, 161, 121, 134, 203, 224,
+ 187, 172, 49, 195, 12, 203, 255, 176, 3, 175, 243, 11, 15, 242, 12,
+ 87, 114, 49, 96, 5, 151, 103, 248, 133, 192, 60, 195, 21, 92, 12,
+ 0, 26, 117, 42, 61, 164, 229, 2, 243, 12, 57, 29, 88, 111, 82,
+ 151, 176, 229, 2, 243, 12, 191, 200, 149, 103, 72, 236, 181, 92, 96,
+ 158, 225, 23, 98, 243, 63, 208, 198, 34, 243, 63, 194, 150, 139, 205,
+ 255, 176, 44, 23, 155, 255, 129, 56, 161, 231, 39, 110, 5, 63, 88,
+ 105, 134, 25, 150, 255, 97, 1, 94, 199, 103, 30, 228, 25, 46, 227,
+ 98, 192, 231, 220, 25, 16, 159, 9, 204, 51, 252, 156, 243, 53, 212,
+ 177, 76, 139, 1, 63, 9, 204, 51, 228, 116, 96, 189, 73, 93, 236,
+ 63, 9, 204, 51, 252, 44, 87, 158, 161, 166, 35, 101, 171, 184, 56,
+ 131, 118, 23, 153, 255, 129, 54, 22, 153, 255, 97, 255, 73, 108, 254,
+ 7, 218, 78, 100, 254, 7, 226, 132, 222, 213, 179, 9, 252, 96, 153,
+ 25, 102, 88, 254, 71, 202, 150, 135, 222, 33, 155, 61, 56, 63, 113,
+ 11, 119, 238, 224, 22, 238, 204, 209, 31, 197, 197, 153, 16, 78, 71,
+ 10, 188, 83, 138, 166, 39, 236, 71, 113, 113, 6, 229, 210, 122, 0,
+ 77, 235, 242, 163, 184, 56, 19, 178, 57, 215, 249, 137, 155, 181, 92,
+ 198, 77, 226, 226, 12, 218, 93, 228, 120, 38, 236, 71, 177, 227, 25,
+ 203, 143, 98, 199, 51, 104, 59, 145, 227, 25, 196, 9, 189, 67, 225,
+ 123, 240, 131, 173, 102, 152, 97, 249, 31, 209, 63, 0, 111, 172, 121,
+ 156, 193, 114, 244, 220, 233, 31, 184, 189, 236, 27, 197, 197, 25, 31,
+ 78, 71, 52, 188, 83, 180, 166, 199, 186, 81, 92, 156, 65, 185, 180,
+ 30, 64, 147, 186, 56, 55, 136, 139, 51, 62, 177, 185, 238, 234, 137,
+ 213, 114, 25, 55, 136, 139, 51, 104, 119, 145, 227, 25, 235, 70, 177,
+ 227, 25, 180, 167, 200, 241, 76, 200, 6, 177, 227, 25, 196, 9, 189,
+ 71, 241, 5, 208, 155, 76, 48, 195, 221, 59, 18, 2, 188, 41, 223,
+ 122, 112, 135, 194, 247, 92, 12, 248, 142, 59, 163, 241, 91, 113, 113,
+ 6, 229, 210, 24, 0, 52, 234, 84, 230, 180, 214, 139, 139, 51, 33,
+ 156, 14, 172, 55, 169, 139, 99, 189, 184, 56, 131, 114, 117, 119, 40,
+ 104, 58, 226, 94, 136, 139, 51, 104, 119, 145, 227, 25, 180, 177, 200,
+ 241, 140, 99, 189, 216, 241, 12, 218, 78, 228, 120, 70, 193, 137, 38,
+ 47, 45, 27, 252, 224, 123, 51, 204, 176, 253, 92, 113, 207, 31, 122,
+ 91, 115, 204, 227, 12, 150, 163, 119, 79, 61, 103, 242, 157, 207, 196,
+ 197, 25, 43, 167, 35, 14, 222, 41, 78, 211, 19, 242, 76, 92, 156,
+ 65, 185, 180, 30, 64, 147, 186, 184, 158, 138, 139, 51, 214, 28, 61,
+ 102, 80, 167, 210, 199, 124, 42, 46, 206, 160, 221, 69, 142, 103, 66,
+ 158, 137, 29, 207, 160, 61, 69, 142, 103, 194, 158, 138, 29, 207, 32,
+ 78, 232, 61, 138, 143, 192, 15, 94, 152, 97, 134, 157, 3, 25, 6,
+ 188, 105, 89, 230, 113, 6, 203, 209, 59, 59, 159, 112, 247, 91, 101,
+ 137, 139, 51, 40, 151, 232, 8, 3, 26, 117, 42, 243, 12, 89, 226,
+ 226, 76, 24, 167, 3, 235, 77, 234, 18, 243, 88, 92, 156, 65, 185,
+ 60, 102, 194, 52, 29, 214, 199, 226, 226, 12, 218, 93, 228, 120, 198,
+ 39, 75, 236, 120, 6, 237, 41, 114, 60, 99, 125, 44, 118, 60, 131,
+ 56, 161, 247, 40, 166, 131, 31, 100, 155, 97, 134, 157, 3, 105, 5,
+ 222, 184, 12, 243, 56, 131, 229, 104, 12, 200, 228, 238, 81, 204, 16,
+ 23, 103, 80, 46, 141, 1, 64, 163, 78, 101, 12, 253, 80, 92, 156,
+ 177, 114, 58, 176, 222, 164, 46, 161, 15, 197, 197, 25, 148, 171, 187,
+ 71, 81, 211, 145, 150, 46, 46, 206, 160, 221, 69, 142, 103, 208, 198,
+ 34, 199, 51, 161, 15, 197, 142, 103, 208, 118, 34, 199, 51, 136, 19,
+ 122, 222, 112, 161, 12, 239, 184, 71, 110, 48, 19, 54, 108, 204, 148,
+ 81, 234, 121, 243, 22, 238, 123, 164, 61, 120, 232, 237, 87, 58, 3,
+ 48, 83, 88, 26, 62, 188, 134, 188, 102, 73, 216, 158, 10, 217, 85,
+ 236, 47, 221, 163, 248, 128, 139, 1, 15, 184, 243, 185, 74, 101, 228,
+ 233, 7, 72, 29, 59, 122, 84, 195, 140, 183, 197, 219, 226, 254, 143,
+ 198, 0, 94, 71, 127, 192, 190, 166, 199, 89, 210, 19, 29, 213, 60,
+ 211, 209, 159, 219, 107, 95, 38, 195, 155, 212, 197, 199, 35, 29, 213,
+ 61, 210, 129, 114, 233, 57, 19, 168, 67, 187, 211, 36, 180, 132, 145,
+ 14, 135, 237, 216, 209, 197, 26, 102, 242, 210, 225, 176, 209, 115, 38,
+ 56, 29, 49, 240, 253, 80, 167, 82, 162, 152, 59, 29, 86, 9, 117,
+ 76, 156, 239, 179, 167, 83, 237, 162, 90, 123, 88, 196, 45, 46, 117,
+ 245, 40, 205, 213, 3, 104, 63, 77, 71, 76, 145, 188, 117, 188, 223,
+ 196, 127, 79, 15, 239, 251, 208, 190, 120, 83, 29, 5, 12, 116, 248,
+ 113, 58, 44, 154, 78, 229, 155, 23, 202, 91, 71, 219, 125, 243, 183,
+ 213, 89, 176, 164, 153, 212, 161, 128, 105, 61, 166, 105, 62, 90, 79,
+ 177, 170, 122, 38, 185, 222, 246, 218, 152, 115, 205, 92, 73, 103, 233,
+ 60, 238, 165, 96, 37, 186, 83, 122, 246, 245, 133, 114, 30, 46, 161,
+ 235, 99, 78, 211, 124, 249, 127, 203, 187, 248, 252, 47, 122, 23, 196,
+ 134, 254, 93, 28, 220, 125, 178, 14, 27, 123, 23, 135, 205, 252, 93,
+ 28, 54, 246, 46, 42, 173, 190, 139, 195, 102, 246, 46, 223, 121, 169,
+ 24, 170, 167, 120, 86, 222, 118, 25, 217, 99, 149, 206, 46, 195, 44,
+ 175, 88, 28, 150, 38, 150, 37, 150, 214, 44, 7, 117, 127, 39, 249,
+ 243, 246, 101, 219, 230, 182, 139, 151, 173, 135, 252, 202, 208, 155, 191,
+ 25, 189, 139, 87, 114, 79, 121, 236, 137, 47, 180, 62, 93, 136, 92,
+ 240, 217, 120, 37, 182, 20, 182, 245, 150, 111, 45, 56, 108, 56, 158,
+ 41, 146, 220, 71, 110, 148, 213, 76, 139, 149, 253, 228, 55, 254, 94,
+ 160, 208, 245, 18, 251, 203, 206, 105, 52, 135, 218, 45, 111, 147, 14,
+ 239, 201, 101, 10, 70, 104, 101, 66, 229, 133, 41, 106, 62, 251, 91,
+ 109, 135, 203, 94, 247, 203, 26, 222, 223, 120, 113, 255, 88, 185, 145,
+ 125, 132, 86, 102, 146, 60, 54, 92, 221, 163, 123, 190, 141, 67, 254,
+ 178, 229, 97, 67, 222, 156, 253, 243, 229, 194, 157, 125, 246, 168, 79,
+ 151, 80, 250, 173, 65, 95, 112, 207, 141, 191, 27, 182, 75, 228, 187,
+ 133, 142, 157, 97, 75, 88, 152, 216, 58, 247, 119, 11, 253, 98, 129,
+ 109, 84, 246, 122, 118, 198, 7, 124, 51, 252, 69, 194, 175, 128, 218,
+ 82, 121, 47, 216, 215, 73, 238, 59, 183, 122, 187, 220, 223, 173, 27,
+ 124, 183, 222, 99, 179, 13, 109, 239, 13, 223, 45, 248, 80, 209, 68,
+ 242, 221, 66, 166, 118, 85, 232, 204, 246, 189, 229, 30, 229, 62, 54,
+ 180, 125, 182, 179, 143, 156, 146, 180, 41, 145, 124, 183, 211, 87, 15,
+ 41, 244, 195, 132, 254, 242, 221, 31, 140, 109, 127, 69, 126, 79, 78,
+ 187, 244, 122, 18, 249, 110, 77, 166, 169, 123, 186, 143, 180, 25, 46,
+ 59, 7, 173, 54, 228, 253, 2, 190, 219, 216, 173, 251, 233, 119, 59,
+ 95, 234, 162, 66, 255, 2, 223, 109, 208, 149, 98, 134, 182, 127, 4,
+ 223, 109, 230, 4, 127, 250, 221, 8, 221, 31, 190, 27, 123, 110, 252,
+ 221, 176, 173, 55, 195, 219, 168, 92, 120, 27, 170, 125, 183, 37, 240,
+ 163, 57, 193, 128, 183, 148, 204, 38, 187, 220, 225, 109, 195, 254, 146,
+ 175, 25, 189, 203, 11, 103, 79, 121, 226, 224, 166, 109, 200, 119, 187,
+ 80, 185, 123, 27, 149, 183, 183, 252, 250, 137, 225, 109, 140, 121, 251,
+ 200, 53, 83, 3, 218, 144, 239, 54, 229, 86, 21, 133, 246, 6, 188,
+ 221, 111, 115, 220, 80, 239, 115, 248, 110, 227, 223, 248, 250, 53, 242,
+ 221, 86, 6, 141, 87, 232, 130, 128, 183, 140, 226, 87, 90, 27, 241,
+ 62, 131, 239, 86, 184, 190, 119, 107, 242, 221, 42, 117, 252, 202, 170,
+ 242, 58, 228, 87, 235, 70, 237, 52, 230, 157, 47, 191, 17, 176, 178,
+ 41, 249, 110, 132, 238, 1, 223, 141, 61, 55, 158, 223, 192, 190, 38,
+ 157, 19, 244, 130, 126, 78, 186, 81, 191, 179, 153, 174, 223, 233, 44,
+ 152, 225, 237, 44, 96, 222, 239, 196, 114, 116, 207, 78, 65, 214, 39,
+ 8, 41, 224, 105, 63, 199, 253, 248, 3, 219, 20, 186, 103, 135, 211,
+ 129, 239, 228, 212, 244, 184, 188, 61, 237, 231, 120, 185, 237, 231, 160,
+ 255, 211, 122, 20, 208, 247, 115, 72, 93, 194, 188, 61, 237, 231, 184,
+ 175, 7, 126, 43, 58, 191, 86, 32, 67, 119, 190, 60, 107, 55, 29,
+ 54, 66, 175, 178, 37, 216, 141, 218, 83, 221, 217, 224, 222, 122, 121,
+ 12, 207, 14, 27, 161, 151, 133, 236, 182, 27, 225, 92, 183, 54, 155,
+ 75, 30, 243, 51, 135, 141, 208, 171, 225, 253, 140, 252, 143, 31, 247,
+ 160, 207, 209, 61, 54, 17, 25, 222, 118, 174, 207, 248, 178, 255, 53,
+ 215, 249, 95, 24, 250, 171, 197, 220, 255, 176, 28, 157, 151, 178, 48,
+ 249, 113, 179, 197, 249, 31, 202, 165, 227, 30, 160, 81, 167, 226, 35,
+ 179, 197, 249, 95, 152, 69, 239, 127, 164, 46, 41, 17, 226, 252, 15,
+ 109, 194, 159, 211, 230, 206, 255, 66, 43, 172, 240, 216, 255, 236, 156,
+ 60, 251, 160, 34, 110, 253, 47, 12, 228, 121, 234, 127, 88, 87, 34,
+ 207, 1, 239, 231, 206, 255, 82, 124, 87, 120, 236, 127, 232, 115, 116,
+ 255, 253, 204, 12, 239, 52, 47, 35, 255, 107, 161, 243, 191, 148, 240,
+ 12, 239, 148, 89, 230, 254, 135, 229, 232, 26, 95, 56, 147, 31, 58,
+ 75, 156, 255, 133, 112, 58, 240, 157, 82, 52, 61, 105, 51, 197, 249,
+ 31, 202, 213, 173, 241, 105, 58, 28, 51, 197, 249, 31, 218, 36, 191,
+ 254, 167, 91, 227, 155, 153, 127, 255, 211, 173, 241, 205, 204, 191, 255,
+ 241, 241, 23, 125, 142, 198, 223, 137, 25, 222, 33, 17, 70, 254, 215,
+ 82, 231, 127, 142, 25, 25, 222, 142, 169, 230, 254, 135, 229, 232, 119,
+ 155, 193, 228, 251, 76, 245, 116, 222, 199, 203, 116, 190, 196, 194, 233,
+ 112, 76, 135, 247, 210, 244, 196, 76, 241, 116, 222, 199, 92, 7, 202,
+ 165, 245, 0, 154, 212, 197, 58, 197, 211, 121, 31, 15, 234, 193, 233,
+ 112, 76, 131, 122, 76, 215, 230, 50, 38, 123, 58, 239, 227, 101, 58,
+ 239, 131, 114, 105, 61, 128, 182, 104, 58, 66, 38, 231, 175, 61, 208,
+ 213, 131, 211, 129, 62, 130, 58, 149, 254, 208, 164, 252, 181, 7, 186,
+ 239, 49, 85, 223, 30, 88, 52, 29, 97, 147, 242, 215, 30, 16, 29,
+ 193, 154, 143, 242, 120, 115, 55, 174, 24, 234, 216, 99, 55, 154, 223,
+ 208, 173, 157, 76, 17, 43, 207, 42, 88, 30, 250, 153, 94, 222, 203,
+ 115, 40, 170, 60, 135, 205, 19, 121, 33, 188, 188, 111, 11, 58, 167,
+ 125, 80, 114, 79, 238, 247, 75, 123, 88, 207, 62, 115, 201, 103, 237,
+ 243, 154, 7, 209, 245, 39, 39, 113, 237, 243, 255, 231, 248, 92, 215,
+ 159, 156, 164, 175, 111, 244, 161, 79, 155, 229, 150, 103, 143, 171, 99,
+ 143, 62, 84, 42, 62, 175, 113, 163, 174, 63, 57, 145, 139, 231, 149,
+ 192, 15, 103, 26, 181, 167, 173, 244, 253, 73, 224, 13, 11, 243, 160,
+ 63, 57, 145, 235, 79, 126, 196, 249, 122, 77, 79, 219, 211, 130, 166,
+ 237, 16, 202, 165, 253, 73, 160, 81, 167, 130, 223, 87, 60, 109, 79,
+ 205, 117, 132, 113, 58, 210, 38, 64, 223, 71, 171, 139, 179, 186, 167,
+ 237, 169, 7, 245, 152, 192, 213, 3, 232, 48, 77, 71, 76, 53, 79,
+ 219, 211, 130, 166, 237, 105, 24, 167, 35, 13, 190, 31, 234, 84, 252,
+ 166, 170, 167, 237, 105, 33, 183, 237, 16, 150, 161, 245, 8, 227, 234,
+ 1, 116, 152, 166, 195, 85, 217, 211, 246, 180, 144, 219, 246, 20, 203,
+ 208, 122, 132, 229, 234, 223, 135, 105, 253, 171, 74, 158, 182, 167, 238,
+ 235, 129, 255, 79, 239, 246, 172, 153, 65, 239, 246, 196, 92, 110, 119,
+ 237, 21, 230, 114, 231, 110, 175, 154, 88, 2, 94, 58, 47, 77, 255,
+ 46, 234, 159, 95, 234, 32, 211, 185, 230, 180, 242, 75, 185, 50, 177,
+ 148, 30, 247, 236, 132, 41, 111, 116, 57, 11, 55, 31, 237, 75, 233,
+ 189, 95, 7, 202, 102, 188, 196, 6, 136, 161, 255, 235, 54, 64, 140,
+ 255, 95, 183, 1, 182, 65, 122, 27, 188, 28, 107, 85, 27, 232, 99,
+ 109, 19, 139, 175, 215, 203, 54, 112, 216, 152, 13, 84, 90, 181, 129,
+ 241, 90, 135, 106, 3, 118, 174, 1, 161, 85, 27, 24, 243, 170, 54,
+ 112, 216, 152, 13, 84, 90, 181, 129, 49, 47, 218, 32, 200, 75, 109,
+ 35, 235, 41, 45, 7, 188, 249, 217, 91, 118, 108, 243, 72, 61, 8,
+ 125, 37, 125, 144, 196, 158, 147, 179, 29, 94, 177, 116, 128, 31, 145,
+ 183, 115, 244, 82, 169, 219, 116, 210, 183, 96, 223, 114, 118, 210, 118,
+ 201, 246, 99, 222, 125, 11, 197, 126, 61, 246, 73, 115, 27, 47, 212,
+ 222, 55, 69, 58, 219, 104, 155, 66, 103, 31, 248, 87, 106, 114, 249,
+ 50, 173, 199, 90, 75, 31, 203, 102, 203, 251, 150, 68, 203, 40, 202,
+ 59, 184, 229, 3, 41, 115, 70, 97, 226, 131, 242, 230, 86, 215, 148,
+ 242, 203, 23, 22, 150, 51, 75, 239, 165, 188, 127, 90, 38, 89, 46,
+ 1, 95, 154, 37, 148, 157, 117, 240, 71, 41, 185, 204, 7, 229, 119,
+ 17, 251, 17, 186, 240, 91, 213, 184, 231, 216, 160, 54, 177, 148, 134,
+ 95, 13, 175, 38, 47, 217, 15, 219, 127, 98, 191, 110, 255, 221, 178,
+ 99, 123, 78, 236, 71, 232, 42, 155, 103, 72, 236, 57, 218, 175, 153,
+ 114, 110, 114, 111, 248, 145, 245, 138, 209, 167, 54, 74, 172, 47, 197,
+ 236, 247, 214, 170, 88, 201, 108, 173, 99, 109, 145, 157, 82, 135, 83,
+ 123, 146, 136, 253, 98, 254, 78, 80, 232, 70, 79, 92, 210, 181, 93,
+ 187, 232, 186, 193, 231, 150, 58, 96, 191, 58, 150, 61, 240, 35, 188,
+ 222, 33, 233, 82, 249, 213, 123, 216, 185, 161, 45, 39, 43, 107, 38,
+ 213, 27, 148, 147, 49, 118, 17, 222, 147, 150, 32, 229, 44, 149, 98,
+ 94, 237, 41, 239, 251, 203, 202, 203, 246, 97, 51, 127, 35, 246, 35,
+ 116, 147, 65, 213, 184, 231, 22, 75, 41, 206, 126, 132, 151, 216, 15,
+ 99, 27, 177, 95, 107, 176, 31, 198, 42, 98, 63, 66, 35, 142, 216,
+ 115, 180, 95, 45, 176, 95, 19, 240, 191, 38, 58, 28, 157, 250, 143,
+ 244, 29, 153, 253, 138, 78, 217, 14, 207, 243, 238, 59, 34, 111, 214,
+ 130, 125, 210, 180, 232, 162, 219, 136, 253, 138, 252, 108, 85, 232, 226,
+ 25, 255, 74, 85, 82, 67, 183, 49, 255, 107, 2, 246, 107, 2, 254,
+ 199, 120, 31, 151, 120, 32, 253, 178, 126, 30, 41, 35, 143, 174, 56,
+ 120, 155, 58, 127, 95, 88, 254, 98, 191, 109, 27, 243, 191, 38, 96,
+ 191, 38, 150, 251, 186, 181, 142, 82, 242, 200, 42, 206, 70, 196, 126,
+ 132, 238, 1, 246, 99, 207, 221, 251, 31, 157, 63, 168, 196, 250, 187,
+ 113, 229, 161, 239, 51, 209, 168, 191, 219, 90, 63, 127, 80, 17, 198,
+ 133, 21, 60, 152, 63, 168, 200, 245, 75, 42, 114, 243, 7, 21, 196,
+ 205, 95, 89, 56, 29, 248, 78, 14, 77, 79, 140, 175, 184, 249, 43,
+ 148, 171, 27, 175, 106, 58, 172, 190, 226, 230, 175, 208, 38, 34, 231,
+ 79, 177, 254, 34, 231, 79, 173, 190, 98, 231, 79, 209, 231, 232, 61,
+ 28, 189, 192, 142, 149, 140, 252, 239, 53, 157, 255, 89, 129, 215, 90,
+ 206, 220, 255, 176, 28, 221, 35, 87, 142, 201, 119, 150, 21, 231, 127,
+ 40, 151, 238, 245, 3, 26, 117, 42, 115, 50, 101, 197, 249, 159, 181,
+ 156, 222, 255, 72, 93, 92, 62, 226, 252, 15, 109, 34, 114, 254, 52,
+ 164, 172, 216, 249, 83, 172, 171, 200, 249, 83, 244, 57, 186, 126, 212,
+ 61, 195, 59, 174, 188, 129, 255, 53, 181, 234, 252, 207, 15, 120, 253,
+ 122, 154, 251, 31, 150, 163, 251, 180, 122, 114, 235, 71, 61, 196, 249,
+ 31, 202, 165, 251, 180, 128, 70, 157, 74, 255, 179, 135, 56, 255, 243,
+ 235, 153, 107, 159, 150, 86, 151, 148, 238, 2, 215, 143, 122, 8, 94,
+ 63, 234, 33, 120, 253, 168, 187, 224, 245, 163, 238, 220, 124, 83, 151,
+ 12, 239, 152, 94, 70, 254, 167, 223, 183, 153, 210, 45, 195, 59, 165,
+ 171, 7, 235, 71, 221, 184, 245, 163, 110, 220, 250, 81, 87, 129, 235,
+ 71, 156, 14, 124, 167, 20, 77, 79, 90, 23, 129, 235, 71, 93, 115,
+ 173, 31, 105, 58, 28, 93, 4, 174, 31, 117, 21, 188, 126, 212, 69,
+ 240, 250, 81, 23, 193, 235, 71, 93, 184, 254, 95, 167, 12, 239, 144,
+ 238, 70, 254, 167, 223, 191, 225, 120, 3, 250, 89, 175, 123, 208, 255,
+ 123, 131, 251, 110, 111, 112, 253, 191, 215, 5, 246, 255, 56, 29, 248,
+ 78, 14, 77, 79, 76, 103, 129, 253, 191, 215, 115, 245, 255, 52, 29,
+ 214, 206, 2, 251, 127, 175, 11, 238, 255, 117, 22, 220, 255, 235, 44,
+ 184, 255, 215, 137, 249, 159, 143, 12, 118, 236, 226, 198, 255, 180, 60,
+ 143, 49, 195, 134, 235, 251, 127, 192, 27, 215, 33, 195, 52, 63, 10,
+ 203, 209, 254, 95, 71, 38, 63, 90, 206, 107, 14, 217, 98, 119, 55,
+ 223, 158, 251, 187, 61, 250, 47, 188, 29, 237, 255, 117, 228, 250, 127,
+ 64, 163, 78, 165, 208, 120, 79, 116, 84, 203, 83, 199, 245, 153, 237,
+ 232, 189, 130, 86, 78, 7, 214, 155, 212, 197, 53, 214, 19, 29, 213,
+ 243, 212, 177, 180, 109, 203, 36, 90, 143, 14, 122, 31, 183, 106, 58,
+ 156, 99, 140, 116, 188, 60, 223, 254, 82, 206, 74, 163, 153, 54, 50,
+ 111, 134, 118, 39, 243, 102, 184, 215, 15, 237, 72, 228, 17, 186, 247,
+ 154, 185, 18, 123, 238, 190, 13, 59, 255, 115, 41, 249, 68, 90, 61,
+ 186, 71, 147, 148, 47, 153, 241, 142, 124, 96, 238, 2, 67, 222, 71,
+ 37, 198, 202, 55, 27, 111, 213, 202, 204, 146, 165, 38, 123, 181, 243,
+ 164, 163, 228, 148, 185, 39, 12, 121, 115, 10, 44, 144, 255, 110, 120,
+ 169, 29, 217, 55, 71, 232, 176, 27, 203, 184, 231, 121, 183, 227, 105,
+ 154, 95, 240, 54, 192, 239, 76, 108, 64, 104, 220, 235, 204, 158, 187,
+ 151, 247, 15, 216, 32, 34, 120, 96, 34, 177, 1, 41, 95, 28, 108,
+ 208, 112, 112, 75, 67, 222, 199, 96, 131, 118, 195, 171, 38, 18, 27,
+ 52, 218, 171, 238, 89, 69, 27, 220, 123, 254, 36, 193, 204, 6, 187,
+ 238, 157, 76, 32, 54, 32, 52, 218, 128, 61, 55, 182, 1, 250, 45,
+ 111, 3, 244, 67, 98, 3, 66, 15, 7, 27, 176, 231, 238, 229, 149,
+ 140, 47, 37, 23, 252, 37, 50, 137, 216, 128, 148, 111, 4, 54, 24,
+ 56, 181, 118, 146, 153, 31, 148, 143, 59, 64, 109, 208, 239, 143, 48,
+ 133, 246, 2, 27, 116, 221, 85, 44, 209, 204, 6, 129, 99, 98, 218,
+ 18, 27, 16, 122, 2, 216, 128, 61, 55, 182, 1, 226, 138, 183, 1,
+ 226, 132, 216, 128, 208, 232, 7, 236, 121, 222, 126, 112, 183, 208, 116,
+ 186, 231, 157, 148, 71, 63, 24, 18, 111, 204, 139, 54, 72, 220, 65,
+ 206, 63, 157, 37, 251, 201, 234, 121, 166, 232, 7, 191, 126, 19, 97,
+ 51, 179, 65, 249, 247, 72, 153, 37, 148, 70, 63, 96, 207, 141, 251,
+ 32, 216, 238, 211, 179, 229, 70, 66, 187, 214, 201, 48, 6, 40, 249,
+ 75, 116, 15, 37, 216, 207, 249, 161, 121, 12, 192, 114, 116, 127, 231,
+ 104, 110, 15, 233, 135, 158, 198, 0, 247, 177, 27, 241, 78, 247, 119,
+ 142, 230, 246, 169, 2, 109, 215, 218, 76, 215, 40, 79, 99, 128, 123,
+ 29, 136, 39, 90, 15, 78, 7, 214, 155, 212, 37, 108, 148, 167, 49,
+ 192, 189, 14, 244, 87, 90, 143, 15, 115, 237, 83, 37, 246, 26, 229,
+ 105, 12, 112, 175, 3, 253, 129, 206, 11, 124, 168, 223, 7, 202, 218,
+ 77, 135, 141, 208, 219, 236, 9, 118, 163, 246, 84, 183, 175, 96, 148,
+ 94, 30, 107, 131, 28, 54, 66, 163, 60, 163, 182, 73, 183, 175, 32,
+ 151, 60, 134, 103, 135, 141, 208, 241, 32, 207, 8, 231, 186, 51, 132,
+ 114, 201, 99, 216, 112, 216, 8, 141, 239, 103, 132, 25, 190, 223, 132,
+ 56, 161, 249, 126, 67, 129, 150, 205, 48, 195, 242, 202, 45, 192, 235,
+ 24, 110, 142, 25, 44, 71, 251, 212, 35, 184, 126, 251, 112, 113, 152,
+ 65, 185, 212, 215, 80, 199, 72, 173, 223, 62, 76, 28, 102, 44, 156,
+ 14, 172, 55, 169, 139, 117, 152, 56, 204, 160, 92, 221, 216, 64, 211,
+ 225, 28, 42, 14, 51, 104, 119, 62, 103, 212, 29, 102, 48, 103, 212,
+ 83, 204, 160, 141, 121, 121, 238, 48, 131, 242, 60, 197, 140, 53, 151,
+ 60, 119, 152, 241, 3, 121, 158, 98, 6, 109, 199, 203, 115, 135, 25,
+ 124, 63, 79, 49, 163, 224, 132, 200, 27, 4, 126, 48, 210, 12, 51,
+ 44, 175, 220, 57, 4, 218, 243, 193, 230, 152, 193, 114, 52, 6, 12,
+ 97, 242, 173, 54, 79, 49, 83, 192, 20, 51, 118, 78, 135, 19, 222,
+ 201, 169, 233, 177, 183, 247, 20, 51, 5, 76, 49, 131, 114, 105, 61,
+ 128, 38, 117, 9, 105, 231, 41, 102, 10, 152, 98, 198, 62, 88, 143,
+ 25, 212, 169, 140, 111, 131, 61, 197, 76, 1, 67, 204, 108, 215, 236,
+ 94, 79, 27, 215, 123, 239, 124, 152, 228, 14, 51, 23, 198, 150, 183,
+ 155, 245, 219, 135, 223, 13, 179, 63, 255, 120, 151, 86, 38, 198, 126,
+ 114, 82, 178, 66, 191, 82, 37, 222, 126, 60, 102, 191, 33, 222, 74,
+ 252, 118, 132, 147, 239, 162, 116, 226, 215, 143, 237, 158, 140, 23, 182,
+ 107, 223, 150, 212, 227, 246, 175, 15, 147, 220, 97, 245, 44, 212, 195,
+ 172, 239, 61, 0, 234, 145, 232, 53, 108, 55, 169, 199, 187, 221, 50,
+ 21, 186, 57, 212, 195, 254, 69, 101, 67, 156, 151, 130, 122, 48, 249,
+ 46, 74, 239, 134, 122, 120, 210, 231, 223, 174, 249, 15, 169, 199, 181,
+ 239, 31, 38, 185, 107, 35, 26, 140, 46, 111, 55, 235, 63, 23, 114,
+ 133, 217, 167, 142, 105, 145, 68, 234, 113, 227, 245, 242, 10, 221, 160,
+ 81, 188, 253, 104, 169, 130, 73, 70, 245, 168, 182, 251, 8, 39, 223,
+ 69, 233, 123, 171, 31, 219, 61, 233, 183, 111, 215, 124, 148, 212, 163,
+ 30, 248, 149, 187, 182, 233, 10, 124, 15, 179, 62, 176, 3, 190, 71,
+ 47, 218, 63, 143, 177, 127, 25, 164, 222, 85, 240, 168, 114, 188, 253,
+ 243, 161, 179, 12, 219, 181, 34, 240, 61, 152, 124, 23, 165, 157, 240,
+ 61, 60, 237, 123, 99, 59, 72, 239, 232, 107, 13, 56, 31, 106, 214,
+ 38, 178, 251, 3, 92, 109, 51, 188, 67, 219, 152, 183, 137, 88, 142,
+ 222, 159, 215, 150, 201, 79, 123, 45, 127, 253, 8, 126, 254, 37, 148,
+ 211, 225, 130, 119, 114, 105, 122, 28, 175, 229, 175, 31, 193, 207, 191,
+ 160, 92, 90, 15, 160, 73, 93, 124, 94, 203, 95, 63, 130, 159, 127,
+ 9, 109, 163, 111, 19, 81, 167, 226, 25, 173, 243, 215, 143, 32, 243,
+ 47, 193, 154, 221, 73, 92, 109, 24, 90, 196, 249, 124, 80, 151, 151,
+ 230, 95, 124, 156, 39, 108, 217, 173, 230, 122, 212, 143, 112, 112, 242,
+ 156, 32, 111, 70, 252, 240, 151, 230, 50, 162, 147, 79, 216, 54, 182,
+ 203, 123, 62, 66, 119, 222, 13, 39, 47, 109, 36, 200, 43, 212, 250,
+ 165, 121, 1, 215, 129, 19, 182, 189, 155, 91, 36, 121, 212, 207, 105,
+ 205, 228, 69, 195, 251, 245, 253, 112, 198, 75, 99, 236, 80, 168, 111,
+ 145, 55, 103, 122, 212, 143, 64, 156, 16, 204, 184, 154, 66, 252, 29,
+ 100, 134, 25, 118, 127, 64, 204, 171, 25, 222, 126, 173, 204, 49, 131,
+ 229, 232, 122, 222, 171, 220, 154, 77, 51, 79, 49, 83, 198, 173, 31,
+ 164, 93, 14, 161, 119, 78, 250, 113, 58, 98, 224, 157, 98, 52, 61,
+ 161, 239, 121, 138, 25, 247, 58, 124, 127, 237, 65, 117, 160, 92, 90,
+ 15, 160, 73, 93, 98, 6, 120, 138, 25, 247, 58, 70, 149, 60, 78,
+ 251, 17, 126, 173, 114, 173, 75, 182, 210, 198, 221, 253, 60, 197, 140,
+ 123, 29, 155, 158, 171, 231, 211, 204, 45, 160, 218, 189, 158, 82, 82,
+ 221, 235, 135, 118, 36, 242, 8, 253, 70, 220, 28, 59, 123, 238, 190,
+ 221, 189, 218, 235, 153, 253, 76, 219, 42, 244, 126, 176, 95, 255, 236,
+ 164, 148, 31, 144, 58, 72, 242, 122, 220, 212, 240, 220, 193, 167, 229,
+ 151, 74, 12, 171, 177, 116, 126, 212, 235, 217, 102, 201, 8, 171, 22,
+ 229, 110, 202, 109, 82, 141, 113, 81, 90, 153, 157, 82, 249, 209, 31,
+ 43, 52, 222, 107, 89, 98, 228, 66, 147, 249, 206, 125, 210, 130, 107,
+ 203, 232, 221, 123, 155, 162, 190, 162, 247, 90, 30, 173, 185, 206, 144,
+ 215, 82, 240, 148, 84, 233, 242, 70, 122, 247, 222, 231, 235, 227, 212,
+ 121, 214, 136, 179, 210, 25, 239, 29, 198, 122, 35, 47, 72, 181, 247,
+ 36, 208, 187, 247, 90, 212, 85, 251, 92, 94, 17, 151, 37, 121, 193,
+ 1, 67, 94, 175, 168, 107, 82, 86, 193, 67, 244, 94, 203, 26, 29,
+ 143, 169, 115, 195, 17, 183, 165, 129, 115, 78, 26, 242, 214, 138, 186,
+ 43, 69, 251, 166, 210, 123, 45, 251, 79, 191, 161, 208, 221, 34, 210,
+ 165, 93, 174, 71, 134, 188, 225, 81, 153, 210, 202, 187, 69, 181, 125,
+ 111, 89, 82, 237, 113, 85, 21, 122, 72, 68, 182, 116, 58, 35, 176,
+ 189, 17, 239, 127, 142, 28, 105, 228, 67, 122, 199, 183, 236, 172, 212,
+ 95, 161, 71, 219, 188, 228, 167, 109, 7, 24, 242, 166, 58, 189, 229,
+ 22, 161, 77, 181, 50, 5, 101, 231, 136, 90, 10, 189, 54, 188, 176,
+ 188, 123, 182, 151, 33, 239, 209, 200, 98, 242, 107, 235, 137, 77, 74,
+ 202, 242, 37, 245, 27, 61, 108, 95, 74, 254, 219, 59, 198, 120, 30,
+ 221, 89, 90, 110, 255, 234, 231, 90, 25, 31, 57, 120, 139, 234, 75,
+ 57, 237, 203, 202, 11, 235, 204, 49, 228, 125, 225, 44, 39, 179, 57,
+ 126, 95, 74, 159, 159, 94, 65, 54, 155, 251, 167, 184, 124, 79, 143,
+ 75, 108, 123, 8, 46, 9, 253, 58, 224, 146, 61, 119, 47, 239, 18,
+ 224, 178, 204, 124, 255, 96, 130, 75, 239, 61, 146, 82, 190, 27, 222,
+ 45, 214, 171, 172, 97, 223, 246, 38, 224, 146, 197, 188, 88, 58, 103,
+ 95, 5, 112, 105, 20, 243, 144, 183, 72, 193, 109, 82, 114, 15, 47,
+ 122, 111, 95, 145, 183, 127, 81, 116, 21, 3, 92, 190, 26, 216, 207,
+ 80, 239, 35, 192, 101, 220, 165, 154, 109, 8, 46, 79, 76, 246, 83,
+ 222, 255, 217, 211, 163, 82, 250, 228, 213, 134, 109, 73, 118, 129, 83,
+ 210, 43, 247, 110, 4, 19, 92, 222, 93, 86, 158, 222, 55, 219, 101,
+ 112, 29, 67, 219, 63, 5, 92, 246, 216, 100, 167, 184, 60, 18, 244,
+ 154, 66, 215, 6, 92, 62, 216, 218, 212, 144, 183, 24, 224, 242, 183,
+ 20, 111, 138, 203, 35, 255, 170, 247, 190, 122, 1, 46, 253, 170, 125,
+ 108, 248, 206, 87, 34, 239, 74, 251, 31, 173, 108, 75, 112, 249, 247,
+ 187, 23, 148, 61, 162, 15, 194, 211, 165, 253, 43, 182, 237, 54, 110,
+ 75, 50, 165, 216, 175, 246, 237, 38, 184, 188, 115, 168, 104, 130, 218,
+ 14, 101, 75, 243, 247, 55, 49, 180, 243, 139, 200, 28, 233, 210, 221,
+ 209, 164, 140, 188, 114, 203, 167, 10, 237, 5, 184, 180, 13, 253, 222,
+ 144, 23, 239, 196, 108, 244, 233, 254, 4, 130, 203, 255, 126, 79, 85,
+ 233, 136, 194, 242, 170, 181, 22, 67, 223, 192, 187, 197, 46, 220, 47,
+ 71, 239, 237, 107, 240, 101, 109, 149, 182, 149, 146, 223, 24, 19, 96,
+ 204, 11, 184, 44, 115, 187, 69, 34, 193, 229, 46, 223, 215, 52, 222,
+ 178, 242, 32, 155, 241, 154, 18, 226, 146, 173, 59, 249, 82, 26, 113,
+ 105, 182, 30, 69, 112, 137, 241, 157, 224, 114, 1, 224, 18, 227, 53,
+ 193, 37, 161, 151, 3, 46, 217, 115, 247, 242, 222, 234, 253, 204, 238,
+ 119, 147, 248, 163, 85, 10, 12, 216, 167, 148, 47, 112, 118, 144, 20,
+ 212, 245, 186, 161, 237, 47, 151, 3, 92, 210, 190, 99, 44, 93, 71,
+ 250, 0, 112, 105, 212, 119, 84, 244, 226, 157, 127, 125, 171, 37, 17,
+ 92, 118, 169, 85, 72, 161, 223, 6, 92, 158, 251, 251, 130, 161, 13,
+ 110, 2, 46, 219, 95, 251, 60, 145, 224, 114, 76, 117, 155, 66, 223,
+ 4, 92, 70, 92, 141, 51, 124, 231, 58, 16, 47, 119, 15, 113, 180,
+ 37, 184, 252, 115, 172, 122, 159, 116, 81, 192, 101, 211, 210, 141, 12,
+ 177, 181, 14, 112, 185, 224, 239, 69, 20, 151, 39, 187, 170, 49, 62,
+ 21, 112, 89, 38, 209, 97, 200, 123, 41, 242, 154, 116, 125, 241, 3,
+ 122, 87, 109, 131, 170, 125, 20, 122, 95, 248, 109, 105, 195, 227, 25,
+ 134, 216, 186, 7, 184, 140, 158, 251, 52, 129, 224, 50, 112, 205, 79,
+ 10, 61, 221, 145, 46, 85, 59, 211, 217, 176, 190, 71, 33, 94, 150,
+ 95, 84, 149, 222, 167, 233, 31, 171, 246, 51, 240, 174, 218, 87, 170,
+ 159, 53, 238, 91, 204, 206, 145, 46, 23, 10, 162, 241, 178, 92, 231,
+ 38, 10, 157, 6, 184, 60, 60, 183, 153, 97, 204, 171, 152, 236, 45,
+ 91, 143, 61, 110, 71, 112, 57, 229, 59, 181, 159, 177, 15, 226, 165,
+ 99, 115, 73, 67, 189, 159, 2, 46, 165, 14, 165, 41, 46, 67, 135,
+ 111, 81, 232, 61, 16, 47, 27, 76, 118, 25, 250, 198, 74, 192, 101,
+ 249, 138, 165, 147, 8, 46, 123, 156, 175, 174, 208, 201, 16, 47, 247,
+ 125, 21, 104, 232, 147, 143, 1, 151, 108, 45, 212, 151, 210, 151, 0,
+ 151, 102, 107, 164, 4, 151, 216, 39, 230, 227, 37, 246, 113, 9, 46,
+ 9, 141, 57, 43, 236, 185, 123, 121, 7, 32, 94, 214, 155, 193, 114,
+ 86, 142, 105, 229, 235, 67, 188, 12, 41, 102, 204, 123, 15, 226, 37,
+ 27, 131, 197, 210, 181, 205, 194, 128, 75, 163, 49, 152, 218, 23, 221,
+ 6, 254, 50, 139, 222, 197, 249, 119, 11, 237, 174, 70, 192, 229, 234,
+ 127, 195, 13, 121, 159, 2, 46, 183, 239, 140, 160, 119, 113, 70, 100,
+ 147, 117, 206, 163, 210, 27, 193, 179, 77, 244, 158, 146, 170, 84, 158,
+ 77, 239, 226, 140, 216, 31, 161, 221, 17, 121, 86, 138, 251, 202, 120,
+ 174, 229, 57, 224, 242, 65, 25, 58, 79, 35, 253, 81, 156, 240, 94,
+ 150, 214, 21, 50, 227, 189, 38, 221, 93, 16, 65, 239, 226, 124, 255,
+ 107, 194, 123, 91, 58, 22, 103, 204, 251, 2, 112, 217, 122, 69, 4,
+ 189, 139, 243, 122, 119, 149, 46, 2, 253, 216, 229, 5, 140, 121, 125,
+ 1, 151, 7, 78, 176, 187, 56, 87, 13, 81, 109, 254, 10, 196, 203,
+ 222, 143, 103, 24, 242, 158, 130, 120, 153, 29, 57, 133, 222, 197, 217,
+ 112, 176, 74, 151, 5, 92, 246, 151, 167, 24, 242, 62, 132, 120, 185,
+ 113, 248, 12, 122, 23, 103, 167, 213, 170, 63, 60, 0, 92, 190, 83,
+ 208, 248, 157, 159, 2, 46, 203, 116, 101, 119, 113, 254, 123, 91, 243,
+ 13, 136, 151, 157, 119, 27, 251, 6, 198, 203, 82, 95, 18, 191, 242,
+ 145, 71, 214, 32, 247, 135, 150, 149, 247, 127, 103, 236, 147, 24, 47,
+ 217, 250, 188, 47, 165, 49, 94, 154, 173, 219, 147, 57, 5, 156, 71,
+ 160, 243, 112, 189, 97, 156, 220, 218, 108, 78, 129, 221, 21, 21, 10,
+ 188, 161, 125, 205, 231, 20, 176, 28, 157, 191, 226, 198, 198, 105, 125,
+ 196, 173, 231, 161, 92, 58, 15, 7, 239, 132, 58, 21, 105, 125, 196,
+ 173, 231, 161, 92, 90, 15, 212, 161, 213, 197, 167, 143, 184, 245, 188,
+ 208, 190, 185, 230, 225, 250, 106, 243, 22, 189, 197, 173, 231, 161, 221,
+ 69, 174, 231, 57, 250, 136, 93, 207, 243, 233, 35, 118, 61, 15, 109,
+ 39, 114, 61, 15, 113, 66, 231, 225, 2, 51, 188, 93, 77, 205, 48,
+ 195, 238, 138, 138, 105, 2, 24, 107, 236, 193, 60, 92, 19, 110, 254,
+ 170, 9, 183, 119, 191, 145, 56, 204, 248, 113, 58, 98, 224, 157, 98,
+ 52, 61, 246, 70, 226, 48, 131, 114, 105, 61, 128, 38, 117, 73, 9,
+ 18, 135, 25, 191, 198, 185, 230, 225, 26, 107, 243, 137, 65, 226, 48,
+ 131, 118, 207, 47, 102, 44, 252, 125, 104, 141, 242, 143, 25, 94, 30,
+ 218, 51, 191, 152, 225, 229, 133, 6, 229, 31, 51, 186, 56, 19, 200,
+ 229, 91, 53, 0, 63, 232, 109, 134, 25, 118, 87, 84, 40, 98, 204,
+ 223, 131, 56, 19, 200, 197, 128, 0, 38, 63, 204, 95, 28, 102, 80,
+ 46, 141, 1, 64, 163, 78, 165, 144, 191, 56, 204, 132, 114, 58, 176,
+ 222, 164, 46, 209, 13, 197, 97, 6, 229, 242, 152, 9, 213, 116, 248,
+ 53, 20, 135, 25, 180, 187, 200, 56, 99, 241, 23, 27, 103, 208, 158,
+ 34, 227, 140, 95, 67, 177, 113, 6, 113, 66, 48, 19, 90, 7, 252,
+ 32, 208, 4, 51, 77, 217, 93, 81, 126, 192, 27, 83, 207, 28, 51,
+ 88, 142, 198, 128, 250, 220, 190, 145, 122, 226, 48, 131, 114, 105, 12,
+ 0, 26, 117, 42, 235, 197, 117, 197, 97, 198, 143, 211, 129, 245, 38,
+ 117, 9, 169, 43, 14, 51, 40, 151, 199, 140, 159, 166, 195, 85, 71,
+ 28, 102, 208, 238, 34, 227, 12, 218, 88, 100, 156, 9, 169, 43, 54,
+ 206, 160, 237, 68, 198, 25, 196, 9, 221, 107, 245, 28, 252, 160, 129,
+ 25, 102, 216, 158, 94, 87, 109, 104, 207, 107, 121, 176, 175, 160, 54,
+ 23, 3, 106, 115, 227, 25, 63, 129, 227, 25, 78, 135, 11, 222, 201,
+ 165, 233, 113, 248, 9, 28, 207, 212, 226, 234, 1, 52, 169, 75, 220,
+ 11, 129, 227, 153, 90, 185, 198, 51, 181, 180, 62, 230, 11, 129, 227,
+ 25, 63, 193, 227, 25, 63, 177, 113, 6, 237, 41, 50, 206, 216, 95,
+ 136, 141, 51, 136, 19, 138, 153, 199, 224, 7, 117, 242, 198, 204, 71,
+ 163, 70, 88, 38, 113, 223, 195, 14, 188, 206, 103, 238, 48, 163, 191,
+ 247, 6, 203, 209, 189, 131, 57, 76, 126, 204, 211, 188, 207, 211, 146,
+ 239, 183, 76, 250, 240, 120, 169, 96, 163, 92, 168, 155, 73, 195, 233,
+ 62, 25, 148, 75, 247, 14, 2, 141, 58, 21, 105, 217, 121, 235, 72,
+ 191, 87, 60, 97, 210, 238, 38, 134, 185, 80, 43, 39, 5, 177, 61,
+ 144, 156, 14, 172, 55, 169, 75, 232, 147, 188, 117, 188, 83, 229, 213,
+ 164, 184, 244, 118, 237, 141, 114, 161, 106, 206, 108, 65, 247, 226, 160,
+ 92, 221, 62, 120, 77, 135, 61, 43, 111, 29, 65, 83, 166, 218, 250,
+ 79, 118, 24, 230, 66, 53, 121, 155, 229, 66, 161, 221, 249, 252, 15,
+ 180, 35, 145, 71, 104, 204, 133, 98, 207, 45, 150, 101, 150, 122, 150,
+ 141, 150, 186, 150, 31, 225, 71, 218, 221, 115, 63, 151, 146, 253, 251,
+ 251, 210, 60, 32, 82, 30, 115, 161, 110, 204, 155, 97, 56, 39, 141,
+ 249, 31, 242, 154, 111, 104, 14, 140, 79, 191, 120, 154, 7, 244, 229,
+ 241, 36, 211, 28, 152, 11, 93, 78, 104, 101, 150, 80, 26, 243, 63,
+ 216, 243, 188, 99, 79, 154, 230, 23, 188, 13, 240, 59, 19, 27, 16,
+ 26, 115, 96, 216, 115, 180, 65, 32, 216, 32, 8, 108, 16, 164, 203,
+ 129, 201, 118, 244, 166, 249, 96, 164, 60, 230, 192, 188, 21, 93, 199,
+ 52, 31, 236, 207, 243, 133, 104, 62, 216, 167, 125, 175, 5, 19, 27,
+ 248, 239, 58, 18, 108, 102, 131, 202, 59, 214, 5, 19, 27, 16, 26,
+ 109, 192, 158, 27, 219, 0, 253, 150, 183, 1, 250, 33, 177, 1, 161,
+ 49, 23, 138, 61, 71, 27, 84, 7, 27, 84, 7, 27, 84, 215, 229,
+ 66, 221, 27, 205, 114, 161, 72, 121, 204, 133, 234, 181, 185, 150, 105,
+ 46, 212, 238, 227, 251, 168, 31, 236, 217, 61, 134, 230, 66, 29, 154,
+ 81, 200, 212, 15, 214, 7, 236, 167, 185, 80, 132, 198, 92, 40, 246,
+ 220, 216, 6, 136, 43, 222, 6, 136, 19, 98, 3, 66, 163, 31, 176,
+ 231, 104, 131, 241, 96, 131, 241, 96, 131, 241, 58, 63, 8, 175, 199,
+ 114, 161, 72, 121, 244, 131, 105, 46, 243, 92, 168, 149, 119, 89, 46,
+ 84, 151, 217, 44, 23, 106, 180, 203, 60, 23, 106, 220, 58, 150, 11,
+ 69, 104, 244, 3, 246, 220, 100, 63, 230, 99, 46, 23, 234, 33, 180,
+ 107, 207, 13, 99, 128, 62, 23, 10, 120, 157, 153, 30, 196, 128, 199,
+ 92, 219, 249, 136, 203, 133, 202, 244, 52, 6, 184, 239, 11, 32, 222,
+ 105, 219, 249, 136, 139, 1, 64, 163, 78, 165, 223, 145, 225, 105, 12,
+ 112, 175, 3, 241, 68, 235, 193, 233, 192, 122, 147, 186, 132, 101, 120,
+ 26, 3, 220, 235, 64, 127, 165, 245, 200, 204, 21, 3, 136, 189, 50,
+ 60, 141, 1, 238, 117, 160, 63, 208, 190, 124, 166, 62, 55, 136, 181,
+ 155, 14, 27, 161, 49, 215, 200, 168, 61, 213, 229, 66, 101, 232, 229,
+ 177, 54, 200, 97, 35, 52, 230, 26, 25, 181, 77, 186, 92, 168, 92,
+ 242, 24, 158, 29, 54, 66, 227, 251, 25, 225, 92, 55, 127, 144, 75,
+ 30, 195, 134, 195, 70, 104, 124, 63, 35, 204, 232, 114, 161, 30, 114,
+ 243, 192, 119, 192, 15, 30, 155, 97, 134, 203, 133, 2, 94, 191, 251,
+ 230, 152, 193, 114, 52, 135, 40, 157, 155, 7, 190, 39, 14, 51, 40,
+ 151, 142, 157, 225, 157, 80, 167, 226, 115, 247, 196, 97, 6, 229, 210,
+ 57, 0, 160, 73, 93, 82, 238, 138, 195, 140, 223, 253, 92, 243, 192,
+ 247, 181, 190, 217, 93, 113, 152, 65, 187, 243, 125, 111, 119, 152, 193,
+ 190, 183, 167, 152, 177, 231, 146, 231, 14, 51, 40, 207, 83, 204, 160,
+ 61, 121, 121, 238, 48, 131, 99, 13, 79, 49, 19, 154, 75, 158, 59,
+ 204, 224, 251, 121, 138, 25, 196, 9, 157, 7, 190, 9, 126, 240, 208,
+ 12, 51, 44, 23, 42, 20, 120, 93, 183, 205, 49, 131, 229, 232, 216,
+ 249, 63, 110, 30, 248, 182, 56, 204, 160, 92, 58, 118, 6, 26, 117,
+ 42, 133, 110, 139, 195, 76, 40, 167, 3, 235, 77, 234, 18, 125, 75,
+ 28, 102, 80, 174, 110, 30, 88, 211, 225, 119, 75, 28, 102, 208, 238,
+ 249, 197, 12, 63, 103, 100, 185, 157, 127, 204, 240, 242, 208, 158, 249,
+ 197, 12, 47, 207, 239, 86, 254, 49, 195, 247, 205, 16, 39, 116, 30,
+ 248, 42, 248, 193, 29, 51, 204, 176, 92, 25, 63, 224, 141, 185, 110,
+ 142, 25, 44, 71, 99, 192, 13, 110, 30, 248, 122, 254, 48, 195, 143,
+ 207, 81, 46, 141, 1, 64, 163, 78, 101, 30, 248, 90, 254, 48, 195,
+ 143, 207, 253, 56, 29, 88, 111, 82, 151, 144, 107, 249, 195, 12, 63,
+ 62, 71, 185, 186, 121, 96, 77, 135, 235, 106, 254, 48, 67, 198, 231,
+ 193, 154, 221, 137, 15, 133, 132, 22, 113, 230, 92, 144, 95, 26, 159,
+ 251, 57, 79, 216, 174, 254, 55, 54, 207, 241, 185, 46, 167, 245, 154,
+ 62, 87, 198, 59, 180, 206, 203, 99, 93, 144, 23, 213, 169, 113, 158,
+ 99, 93, 221, 249, 252, 156, 188, 155, 35, 139, 56, 135, 128, 13, 115,
+ 143, 27, 157, 7, 78, 216, 74, 103, 54, 207, 115, 220, 168, 235, 59,
+ 94, 213, 231, 202, 216, 54, 204, 120, 121, 12, 6, 239, 247, 100, 86,
+ 222, 99, 48, 62, 206, 32, 78, 104, 223, 236, 18, 248, 193, 77, 51,
+ 204, 176, 92, 25, 215, 21, 104, 207, 47, 155, 99, 6, 203, 209, 24,
+ 112, 133, 203, 149, 57, 239, 41, 102, 220, 231, 127, 212, 157, 220, 155,
+ 222, 77, 30, 202, 233, 112, 193, 59, 185, 52, 61, 49, 169, 158, 98,
+ 198, 189, 142, 192, 14, 61, 169, 14, 148, 75, 235, 1, 52, 169, 139,
+ 235, 180, 167, 152, 113, 175, 99, 221, 26, 150, 43, 19, 122, 57, 215,
+ 60, 240, 101, 173, 111, 118, 212, 83, 204, 184, 215, 17, 203, 231, 202,
+ 156, 103, 123, 12, 151, 250, 7, 57, 209, 142, 68, 30, 161, 59, 199,
+ 205, 177, 179, 231, 228, 76, 232, 134, 150, 182, 240, 35, 237, 174, 171,
+ 215, 51, 251, 124, 248, 70, 100, 143, 225, 125, 123, 15, 165, 124, 175,
+ 212, 65, 210, 168, 169, 13, 232, 156, 111, 95, 139, 191, 101, 4, 240,
+ 205, 228, 120, 31, 149, 95, 42, 49, 172, 198, 210, 249, 51, 239, 103,
+ 155, 37, 35, 172, 146, 61, 134, 78, 199, 96, 186, 39, 255, 203, 240,
+ 97, 10, 141, 185, 50, 97, 51, 70, 82, 222, 56, 224, 221, 14, 124,
+ 59, 57, 222, 231, 5, 246, 73, 31, 72, 147, 233, 222, 223, 119, 142,
+ 206, 86, 104, 204, 149, 217, 18, 56, 143, 242, 38, 2, 79, 50, 252,
+ 14, 232, 120, 79, 73, 31, 255, 180, 56, 145, 236, 49, 44, 49, 97,
+ 89, 34, 217, 99, 120, 252, 207, 21, 148, 247, 48, 240, 28, 183, 212,
+ 177, 164, 192, 143, 223, 99, 88, 117, 216, 218, 68, 178, 199, 240, 114,
+ 179, 53, 10, 93, 44, 226, 178, 244, 173, 229, 43, 202, 123, 18, 120,
+ 78, 195, 47, 149, 227, 125, 18, 121, 77, 250, 126, 242, 162, 68, 178,
+ 199, 112, 198, 115, 245, 142, 202, 130, 17, 183, 165, 55, 231, 71, 25,
+ 246, 5, 106, 68, 221, 149, 134, 7, 76, 79, 36, 123, 12, 23, 182,
+ 90, 160, 208, 99, 34, 210, 165, 152, 179, 95, 80, 222, 11, 240, 206,
+ 151, 224, 119, 133, 211, 27, 29, 149, 41, 101, 13, 254, 37, 145, 236,
+ 49, 188, 90, 251, 188, 66, 143, 138, 200, 150, 126, 207, 178, 208, 246,
+ 234, 154, 165, 182, 229, 134, 165, 150, 229, 150, 165, 38, 229, 221, 235,
+ 200, 145, 18, 151, 208, 253, 178, 242, 76, 167, 85, 161, 107, 219, 188,
+ 228, 38, 105, 108, 47, 236, 29, 104, 227, 238, 193, 47, 141, 155, 35,
+ 75, 119, 122, 203, 151, 127, 171, 146, 68, 246, 24, 30, 252, 182, 148,
+ 66, 159, 11, 47, 44, 23, 204, 184, 77, 223, 57, 221, 82, 195, 146,
+ 1, 58, 179, 44, 126, 148, 247, 66, 100, 49, 57, 61, 115, 23, 221,
+ 251, 219, 214, 246, 181, 118, 183, 103, 41, 185, 217, 176, 37, 148, 55,
+ 7, 222, 217, 203, 171, 142, 165, 144, 23, 251, 190, 89, 206, 210, 114,
+ 221, 148, 40, 186, 39, 255, 213, 10, 170, 221, 158, 183, 47, 43, 47,
+ 94, 56, 198, 116, 79, 62, 155, 3, 246, 165, 52, 238, 49, 228, 231,
+ 134, 139, 131, 190, 210, 240, 43, 199, 233, 165, 123, 242, 83, 25, 46,
+ 63, 3, 92, 98, 219, 67, 215, 63, 52, 186, 35, 224, 146, 61, 119,
+ 143, 203, 51, 128, 203, 18, 247, 139, 211, 28, 182, 176, 58, 93, 149,
+ 242, 109, 1, 151, 143, 222, 188, 210, 150, 225, 178, 161, 134, 75, 127,
+ 93, 174, 12, 139, 121, 177, 116, 78, 183, 16, 224, 210, 40, 230, 17,
+ 92, 254, 147, 89, 141, 230, 176, 157, 223, 238, 163, 157, 217, 149, 32,
+ 93, 152, 88, 168, 29, 195, 101, 32, 224, 50, 16, 112, 25, 168, 219,
+ 251, 187, 176, 254, 173, 96, 130, 203, 164, 222, 169, 193, 100, 239, 111,
+ 214, 172, 223, 131, 25, 46, 3, 1, 151, 1, 128, 203, 0, 150, 75,
+ 86, 240, 148, 52, 41, 253, 16, 205, 149, 217, 243, 223, 230, 96, 21,
+ 31, 103, 165, 110, 55, 215, 6, 51, 92, 6, 0, 46, 3, 0, 151,
+ 140, 55, 27, 112, 121, 123, 237, 176, 96, 130, 203, 6, 173, 135, 42,
+ 116, 97, 192, 229, 144, 63, 7, 7, 51, 92, 250, 3, 46, 3, 0,
+ 151, 140, 215, 18, 117, 77, 186, 242, 252, 11, 186, 39, 127, 103, 240,
+ 214, 96, 178, 247, 119, 221, 140, 131, 134, 125, 234, 39, 145, 119, 165,
+ 147, 235, 238, 7, 19, 92, 174, 222, 148, 173, 210, 128, 203, 245, 255,
+ 120, 183, 99, 184, 12, 4, 92, 6, 2, 46, 3, 185, 182, 36, 83,
+ 122, 45, 248, 81, 48, 193, 165, 163, 210, 35, 77, 47, 224, 50, 61,
+ 51, 152, 225, 50, 16, 112, 25, 8, 184, 12, 228, 222, 57, 71, 58,
+ 246, 40, 139, 148, 145, 35, 239, 168, 186, 188, 1, 151, 27, 222, 47,
+ 214, 142, 225, 50, 16, 112, 25, 8, 184, 12, 212, 229, 202, 172, 186,
+ 84, 149, 238, 201, 239, 151, 229, 167, 229, 36, 21, 150, 183, 215, 99,
+ 185, 15, 233, 192, 147, 1, 191, 44, 206, 55, 48, 87, 230, 208, 63,
+ 129, 52, 135, 109, 171, 83, 245, 37, 47, 91, 41, 185, 86, 11, 107,
+ 59, 134, 75, 224, 241, 10, 2, 92, 6, 113, 216, 42, 45, 159, 40,
+ 220, 156, 230, 176, 213, 89, 216, 76, 227, 45, 43, 79, 45, 213, 204,
+ 52, 135, 141, 173, 75, 248, 82, 26, 113, 201, 175, 87, 20, 7, 125,
+ 165, 225, 87, 142, 211, 75, 247, 228, 159, 102, 184, 252, 4, 112, 137,
+ 241, 154, 224, 146, 208, 203, 0, 151, 236, 57, 226, 210, 31, 144, 229,
+ 15, 184, 100, 216, 234, 219, 251, 153, 253, 69, 171, 186, 52, 87, 166,
+ 242, 212, 195, 106, 249, 179, 131, 164, 110, 210, 21, 46, 94, 6, 2,
+ 46, 253, 1, 151, 13, 88, 110, 85, 185, 165, 18, 235, 59, 198, 210,
+ 117, 134, 247, 0, 151, 70, 125, 71, 228, 237, 93, 112, 155, 180, 100,
+ 99, 85, 154, 43, 83, 230, 31, 245, 252, 133, 190, 128, 203, 121, 101,
+ 254, 229, 226, 101, 13, 192, 101, 77, 192, 101, 45, 93, 174, 76, 219,
+ 23, 203, 105, 188, 244, 122, 212, 73, 161, 111, 61, 61, 42, 69, 94,
+ 222, 151, 192, 112, 89, 7, 112, 89, 15, 112, 201, 222, 185, 46, 224,
+ 114, 201, 183, 111, 180, 33, 184, 236, 216, 241, 148, 226, 119, 37, 0,
+ 151, 175, 93, 173, 222, 142, 225, 210, 95, 195, 37, 243, 181, 173, 128,
+ 75, 185, 237, 92, 154, 43, 19, 116, 98, 154, 154, 211, 58, 251, 178,
+ 52, 185, 206, 168, 118, 12, 151, 141, 0, 151, 141, 0, 151, 236, 187,
+ 29, 135, 120, 89, 229, 206, 247, 20, 151, 101, 47, 87, 81, 231, 64,
+ 195, 111, 75, 51, 55, 71, 24, 238, 223, 40, 2, 241, 242, 210, 249,
+ 102, 52, 94, 62, 190, 175, 174, 171, 148, 138, 76, 151, 106, 173, 252,
+ 57, 129, 225, 178, 30, 224, 178, 62, 224, 146, 213, 247, 52, 196, 203,
+ 26, 35, 75, 210, 92, 153, 97, 99, 212, 92, 153, 111, 195, 179, 165,
+ 154, 219, 92, 237, 244, 184, 108, 12, 184, 180, 82, 222, 25, 17, 57,
+ 210, 153, 45, 52, 39, 70, 174, 217, 183, 181, 66, 31, 4, 92, 102,
+ 62, 108, 215, 158, 225, 178, 37, 224, 178, 37, 224, 178, 21, 229, 109,
+ 150, 236, 45, 23, 155, 80, 156, 230, 150, 134, 222, 254, 167, 157, 218,
+ 183, 40, 44, 7, 28, 123, 157, 195, 101, 51, 192, 165, 85, 135, 203,
+ 121, 128, 203, 94, 242, 185, 4, 130, 203, 160, 173, 235, 149, 250, 238,
+ 128, 120, 121, 102, 94, 42, 23, 47, 235, 107, 241, 146, 197, 248, 79,
+ 1, 151, 233, 29, 74, 208, 92, 153, 7, 73, 170, 143, 37, 64, 188,
+ 44, 221, 52, 192, 120, 45, 11, 112, 201, 214, 202, 124, 41, 141, 185,
+ 50, 252, 26, 90, 113, 175, 234, 128, 203, 234, 128, 203, 234, 47, 231,
+ 150, 30, 213, 231, 202, 196, 114, 185, 50, 177, 92, 174, 76, 44, 151,
+ 43, 163, 198, 203, 9, 128, 203, 9, 186, 92, 25, 236, 63, 19, 92,
+ 254, 194, 229, 202, 36, 149, 99, 188, 125, 129, 103, 4, 252, 102, 90,
+ 194, 116, 185, 50, 108, 12, 22, 75, 215, 190, 48, 94, 26, 141, 193,
+ 72, 188, 188, 247, 53, 203, 149, 121, 222, 49, 220, 70, 226, 101, 233,
+ 59, 44, 31, 34, 14, 244, 109, 135, 223, 78, 78, 47, 198, 203, 173,
+ 71, 89, 174, 204, 232, 234, 179, 105, 174, 76, 195, 49, 236, 157, 19,
+ 129, 39, 25, 126, 7, 56, 94, 204, 149, 201, 28, 200, 114, 101, 62,
+ 106, 58, 155, 230, 202, 52, 173, 202, 120, 15, 3, 207, 113, 248, 165,
+ 112, 188, 216, 143, 237, 177, 147, 229, 202, 188, 157, 204, 114, 101, 134,
+ 29, 102, 243, 52, 39, 129, 231, 52, 252, 82, 117, 188, 215, 164, 215,
+ 187, 205, 166, 185, 50, 227, 7, 207, 166, 185, 50, 43, 167, 207, 54,
+ 205, 149, 185, 251, 238, 108, 154, 43, 243, 79, 128, 74, 23, 134, 120,
+ 121, 224, 9, 211, 123, 1, 244, 93, 130, 223, 21, 78, 111, 57, 192,
+ 229, 39, 37, 103, 211, 92, 153, 105, 90, 174, 73, 13, 136, 151, 61,
+ 63, 100, 103, 184, 92, 3, 158, 27, 240, 187, 197, 241, 158, 142, 204,
+ 145, 166, 87, 154, 70, 115, 101, 182, 30, 156, 170, 174, 85, 2, 46,
+ 175, 79, 158, 106, 99, 184, 28, 7, 184, 28, 7, 184, 28, 199, 245,
+ 39, 189, 229, 123, 103, 89, 174, 204, 131, 127, 85, 127, 120, 12, 253,
+ 216, 203, 215, 217, 247, 77, 7, 159, 200, 128, 95, 22, 167, 247, 25,
+ 224, 114, 242, 167, 44, 87, 230, 104, 51, 109, 157, 19, 226, 229, 84,
+ 46, 39, 41, 7, 121, 188, 194, 0, 151, 97, 186, 92, 153, 57, 167,
+ 89, 174, 204, 199, 111, 178, 92, 153, 5, 127, 153, 231, 202, 176, 245,
+ 91, 95, 74, 99, 188, 228, 215, 117, 139, 123, 141, 7, 92, 142, 7,
+ 92, 142, 127, 121, 15, 243, 37, 46, 87, 230, 36, 140, 147, 175, 154,
+ 205, 41, 112, 185, 50, 192, 27, 122, 218, 131, 185, 235, 75, 220, 120,
+ 223, 197, 237, 45, 59, 37, 112, 238, 218, 197, 141, 247, 129, 70, 157,
+ 138, 180, 83, 2, 231, 174, 121, 29, 80, 111, 82, 23, 159, 83, 226,
+ 230, 174, 81, 174, 110, 238, 90, 211, 17, 115, 82, 220, 220, 53, 218,
+ 93, 228, 122, 143, 227, 148, 216, 245, 30, 159, 83, 98, 215, 123, 208,
+ 118, 34, 215, 123, 16, 39, 116, 189, 231, 16, 248, 193, 37, 51, 204,
+ 112, 185, 50, 127, 66, 249, 195, 230, 152, 193, 114, 20, 51, 71, 184,
+ 245, 158, 195, 2, 49, 115, 132, 243, 103, 160, 81, 167, 26, 76, 4,
+ 98, 134, 211, 129, 245, 38, 117, 137, 254, 67, 224, 122, 207, 225, 92,
+ 152, 209, 116, 248, 253, 33, 112, 189, 231, 176, 224, 245, 158, 195, 130,
+ 215, 123, 254, 16, 188, 222, 243, 135, 224, 245, 158, 67, 220, 122, 207,
+ 254, 12, 111, 191, 147, 102, 152, 97, 185, 50, 126, 192, 27, 115, 208,
+ 131, 245, 158, 67, 220, 58, 201, 239, 220, 122, 207, 65, 113, 152, 65,
+ 185, 116, 189, 7, 104, 212, 169, 174, 11, 136, 195, 140, 31, 167, 3,
+ 235, 77, 234, 18, 114, 64, 28, 102, 80, 174, 110, 189, 71, 211, 225,
+ 218, 47, 14, 51, 104, 119, 145, 113, 6, 109, 44, 50, 206, 132, 28,
+ 16, 27, 103, 208, 118, 34, 227, 12, 226, 132, 198, 153, 61, 224, 7,
+ 135, 76, 48, 195, 229, 202, 184, 246, 65, 31, 104, 175, 7, 235, 61,
+ 251, 184, 24, 176, 143, 235, 155, 37, 139, 195, 76, 40, 167, 195, 5,
+ 239, 228, 210, 244, 56, 146, 197, 97, 6, 229, 210, 122, 0, 77, 234,
+ 226, 147, 44, 176, 111, 182, 55, 215, 122, 207, 94, 173, 111, 230, 20,
+ 216, 55, 75, 22, 27, 103, 28, 201, 98, 227, 140, 79, 178, 216, 56,
+ 131, 182, 19, 26, 103, 246, 112, 113, 102, 55, 248, 193, 126, 51, 204,
+ 176, 61, 159, 126, 136, 177, 68, 15, 226, 204, 30, 174, 125, 78, 226,
+ 226, 76, 162, 192, 56, 147, 196, 197, 25, 160, 81, 167, 18, 103, 18,
+ 4, 198, 25, 78, 7, 214, 155, 212, 37, 36, 65, 96, 156, 73, 204,
+ 21, 103, 52, 29, 174, 221, 2, 227, 76, 162, 224, 56, 147, 32, 56,
+ 206, 36, 8, 142, 51, 187, 5, 199, 153, 221, 28, 102, 182, 131, 31,
+ 236, 113, 135, 153, 145, 227, 63, 26, 52, 77, 217, 35, 109, 225, 219,
+ 192, 93, 128, 177, 223, 60, 200, 47, 219, 197, 181, 207, 187, 152, 124,
+ 251, 206, 252, 221, 27, 84, 179, 91, 249, 166, 180, 125, 230, 116, 184,
+ 224, 157, 92, 154, 30, 191, 95, 243, 119, 111, 144, 37, 118, 94, 60,
+ 173, 199, 111, 92, 61, 128, 166, 117, 249, 37, 127, 247, 6, 253, 52,
+ 124, 49, 59, 183, 246, 183, 92, 113, 230, 55, 13, 51, 219, 243, 119,
+ 111, 208, 225, 38, 83, 104, 174, 12, 218, 93, 151, 35, 1, 118, 164,
+ 123, 93, 52, 250, 163, 150, 11, 36, 246, 220, 125, 187, 235, 106, 80,
+ 85, 46, 111, 209, 46, 211, 195, 28, 9, 173, 124, 225, 172, 55, 229,
+ 90, 239, 148, 50, 228, 205, 46, 50, 88, 182, 219, 30, 169, 23, 65,
+ 90, 198, 200, 13, 106, 252, 165, 208, 197, 50, 102, 200, 145, 119, 190,
+ 183, 26, 241, 62, 157, 247, 177, 60, 123, 152, 151, 149, 228, 7, 16,
+ 218, 255, 220, 10, 238, 185, 113, 142, 4, 250, 5, 111, 3, 252, 206,
+ 212, 166, 26, 141, 54, 96, 207, 243, 182, 65, 153, 175, 99, 226, 137,
+ 13, 72, 121, 180, 193, 225, 14, 142, 120, 51, 27, 244, 248, 104, 96,
+ 60, 177, 193, 142, 174, 114, 60, 177, 65, 159, 165, 21, 227, 205, 108,
+ 208, 227, 204, 135, 63, 19, 27, 16, 26, 109, 192, 158, 27, 219, 0,
+ 253, 150, 183, 1, 250, 33, 177, 1, 161, 187, 128, 13, 216, 115, 247,
+ 242, 194, 192, 6, 103, 127, 141, 165, 185, 50, 164, 252, 43, 96, 131,
+ 179, 9, 31, 27, 242, 22, 47, 58, 88, 238, 251, 219, 135, 73, 196,
+ 6, 253, 170, 116, 87, 104, 63, 176, 193, 222, 134, 53, 12, 121, 159,
+ 131, 13, 42, 253, 52, 133, 230, 76, 17, 26, 109, 192, 158, 27, 219,
+ 0, 113, 197, 219, 0, 113, 66, 108, 64, 232, 241, 96, 3, 246, 220,
+ 189, 188, 179, 96, 131, 162, 145, 31, 209, 92, 25, 82, 190, 40, 216,
+ 160, 255, 29, 99, 222, 39, 224, 7, 227, 35, 72, 158, 205, 24, 185,
+ 196, 5, 117, 46, 26, 253, 32, 243, 246, 44, 155, 153, 31, 20, 91,
+ 48, 155, 230, 202, 16, 26, 109, 192, 158, 27, 247, 155, 176, 221, 167,
+ 119, 183, 174, 133, 118, 109, 183, 81, 12, 208, 223, 93, 232, 218, 6,
+ 229, 227, 61, 136, 1, 219, 184, 182, 115, 27, 55, 214, 248, 57, 127,
+ 57, 198, 136, 119, 218, 118, 114, 58, 92, 240, 78, 46, 77, 79, 220,
+ 55, 249, 203, 49, 70, 60, 209, 122, 196, 115, 245, 0, 154, 212, 197,
+ 254, 77, 254, 114, 140, 209, 95, 105, 61, 226, 115, 197, 128, 120, 45,
+ 183, 96, 109, 254, 114, 140, 209, 31, 232, 88, 227, 103, 125, 238, 8,
+ 107, 55, 29, 54, 66, 207, 107, 159, 96, 55, 106, 79, 117, 57, 193,
+ 223, 232, 229, 177, 54, 200, 97, 35, 52, 202, 51, 106, 155, 116, 121,
+ 4, 185, 228, 49, 60, 59, 108, 132, 158, 11, 242, 140, 112, 174, 203,
+ 35, 88, 171, 151, 199, 176, 225, 176, 17, 26, 223, 207, 8, 51, 186,
+ 251, 102, 215, 114, 247, 45, 126, 5, 126, 176, 221, 8, 51, 205, 117,
+ 152, 73, 249, 58, 195, 59, 100, 141, 57, 102, 176, 28, 189, 111, 246,
+ 107, 38, 223, 181, 90, 28, 102, 66, 56, 29, 41, 240, 78, 41, 154,
+ 158, 176, 213, 226, 48, 131, 114, 105, 61, 128, 166, 117, 89, 45, 14,
+ 51, 33, 107, 244, 152, 65, 157, 202, 92, 243, 87, 226, 48, 131, 118,
+ 39, 62, 20, 99, 111, 226, 22, 51, 209, 241, 91, 60, 198, 76, 88,
+ 46, 121, 238, 48, 131, 242, 60, 197, 140, 133, 147, 23, 10, 242, 220,
+ 97, 6, 229, 121, 138, 25, 180, 29, 255, 126, 238, 48, 131, 242, 60,
+ 197, 12, 226, 132, 96, 38, 229, 11, 240, 131, 181, 70, 152, 105, 161,
+ 195, 76, 244, 42, 224, 253, 210, 28, 51, 88, 142, 248, 129, 207, 42,
+ 46, 47, 127, 165, 56, 204, 248, 112, 58, 162, 225, 157, 162, 53, 61,
+ 214, 149, 226, 48, 131, 114, 105, 61, 128, 38, 117, 113, 174, 16, 135,
+ 25, 159, 47, 245, 152, 65, 157, 202, 28, 192, 10, 113, 152, 65, 187,
+ 231, 23, 51, 252, 156, 145, 117, 101, 254, 49, 195, 203, 67, 123, 230,
+ 23, 51, 188, 188, 144, 21, 249, 199, 12, 223, 55, 67, 156, 16, 204,
+ 68, 127, 6, 244, 87, 70, 152, 105, 169, 195, 76, 8, 240, 166, 44,
+ 51, 199, 12, 150, 163, 49, 96, 57, 183, 239, 127, 89, 254, 48, 195,
+ 143, 207, 81, 46, 141, 1, 64, 163, 78, 165, 255, 247, 121, 254, 48,
+ 195, 143, 207, 67, 56, 29, 88, 111, 82, 23, 199, 231, 249, 195, 12,
+ 63, 62, 71, 185, 186, 187, 211, 53, 29, 62, 159, 231, 15, 51, 100,
+ 124, 30, 172, 217, 157, 191, 27, 58, 232, 113, 177, 151, 198, 231, 97,
+ 97, 19, 237, 157, 227, 170, 53, 245, 164, 29, 71, 27, 243, 242, 190,
+ 29, 243, 238, 75, 99, 93, 148, 247, 107, 139, 213, 241, 30, 173, 249,
+ 115, 242, 222, 24, 81, 196, 217, 109, 251, 232, 151, 198, 141, 149, 199,
+ 79, 180, 251, 253, 28, 227, 209, 189, 50, 62, 156, 188, 56, 120, 191,
+ 218, 221, 167, 189, 52, 6, 155, 6, 239, 55, 179, 203, 36, 143, 226,
+ 140, 130, 19, 50, 127, 186, 17, 252, 224, 11, 35, 204, 180, 210, 97,
+ 38, 230, 167, 12, 111, 191, 173, 30, 156, 103, 249, 19, 55, 71, 251,
+ 19, 147, 239, 216, 236, 41, 102, 10, 187, 247, 103, 126, 174, 153, 211,
+ 17, 3, 239, 20, 163, 233, 113, 109, 242, 20, 51, 230, 58, 80, 46,
+ 173, 7, 208, 164, 46, 246, 31, 60, 197, 140, 7, 245, 216, 154, 43,
+ 143, 121, 171, 182, 118, 178, 209, 83, 204, 228, 165, 195, 161, 96, 102,
+ 164, 151, 106, 247, 122, 74, 73, 117, 143, 97, 46, 121, 22, 178, 199,
+ 80, 199, 93, 178, 190, 165, 153, 69, 253, 145, 118, 215, 217, 235, 153,
+ 189, 208, 159, 73, 141, 201, 30, 195, 41, 213, 212, 184, 228, 151, 58,
+ 72, 58, 242, 222, 135, 134, 49, 42, 173, 252, 82, 41, 32, 131, 96,
+ 53, 150, 206, 159, 149, 30, 151, 36, 61, 141, 175, 102, 56, 31, 150,
+ 254, 217, 63, 146, 227, 83, 167, 149, 236, 155, 203, 185, 125, 74, 161,
+ 11, 205, 120, 44, 205, 26, 120, 214, 80, 239, 115, 217, 34, 255, 85,
+ 171, 72, 83, 178, 127, 237, 102, 195, 210, 77, 213, 61, 134, 69, 229,
+ 77, 243, 43, 25, 234, 205, 41, 80, 70, 102, 243, 124, 190, 148, 14,
+ 187, 81, 69, 54, 155, 255, 35, 182, 71, 127, 20, 101, 251, 223, 19,
+ 223, 137, 35, 182, 63, 212, 83, 141, 225, 104, 251, 50, 143, 143, 255,
+ 108, 102, 251, 9, 211, 73, 187, 22, 75, 231, 237, 208, 246, 15, 27,
+ 175, 142, 55, 179, 125, 212, 234, 228, 120, 98, 251, 1, 125, 23, 197,
+ 19, 219, 47, 159, 242, 81, 188, 153, 237, 235, 22, 255, 229, 103, 98,
+ 251, 128, 38, 235, 127, 38, 182, 191, 176, 99, 254, 207, 102, 182, 103,
+ 243, 139, 190, 148, 70, 219, 155, 205, 59, 18, 219, 35, 78, 137, 237,
+ 83, 243, 176, 253, 103, 30, 216, 222, 187, 207, 51, 251, 221, 224, 15,
+ 104, 46, 74, 82, 45, 181, 191, 243, 243, 63, 131, 164, 55, 6, 158,
+ 53, 236, 251, 84, 2, 219, 151, 218, 53, 154, 238, 121, 39, 49, 224,
+ 202, 216, 36, 233, 147, 173, 49, 134, 115, 120, 49, 203, 254, 145, 46,
+ 94, 221, 150, 68, 108, 127, 240, 96, 180, 66, 247, 154, 249, 88, 106,
+ 84, 102, 158, 33, 111, 115, 176, 253, 103, 71, 253, 105, 254, 209, 16,
+ 91, 29, 133, 14, 7, 219, 7, 204, 173, 106, 200, 123, 31, 108, 207,
+ 230, 53, 125, 41, 221, 21, 108, 111, 54, 223, 73, 108, 143, 237, 151,
+ 222, 239, 29, 54, 102, 123, 149, 238, 160, 216, 222, 97, 211, 219, 254,
+ 154, 206, 246, 199, 193, 239, 215, 45, 99, 251, 154, 63, 215, 250, 134,
+ 77, 192, 239, 47, 255, 103, 124, 222, 250, 109, 176, 125, 66, 183, 105,
+ 116, 95, 51, 137, 151, 101, 192, 239, 255, 54, 136, 151, 200, 91, 244,
+ 243, 127, 164, 140, 152, 9, 116, 175, 238, 176, 79, 39, 43, 116, 69,
+ 240, 251, 54, 231, 77, 206, 151, 7, 219, 63, 34, 251, 85, 193, 246,
+ 127, 253, 166, 210, 197, 192, 246, 22, 155, 241, 59, 63, 3, 219, 179,
+ 249, 84, 95, 74, 143, 3, 219, 155, 205, 179, 210, 125, 120, 27, 185,
+ 57, 203, 111, 97, 12, 246, 153, 81, 140, 111, 173, 143, 241, 27, 32,
+ 206, 125, 239, 65, 140, 223, 192, 197, 198, 13, 76, 190, 223, 103, 226,
+ 198, 146, 126, 156, 142, 24, 120, 167, 24, 77, 79, 220, 119, 226, 198,
+ 146, 40, 151, 214, 3, 104, 82, 23, 251, 119, 226, 198, 146, 126, 223,
+ 231, 138, 241, 223, 107, 115, 150, 223, 138, 27, 75, 162, 221, 69, 206,
+ 191, 160, 141, 69, 206, 191, 216, 191, 19, 59, 255, 130, 182, 19, 57,
+ 255, 130, 56, 161, 231, 34, 46, 1, 63, 216, 104, 132, 153, 215, 244,
+ 115, 150, 235, 97, 204, 182, 206, 131, 57, 203, 245, 220, 56, 111, 61,
+ 55, 103, 25, 35, 112, 206, 146, 211, 145, 2, 239, 148, 162, 233, 9,
+ 139, 17, 56, 103, 185, 142, 171, 7, 208, 164, 46, 113, 75, 5, 206,
+ 89, 174, 203, 53, 103, 185, 78, 195, 229, 82, 129, 115, 150, 49, 98,
+ 231, 95, 194, 98, 196, 206, 191, 160, 61, 69, 206, 191, 216, 151, 138,
+ 157, 127, 65, 156, 208, 115, 228, 22, 130, 31, 124, 107, 128, 153, 166,
+ 86, 29, 102, 236, 192, 235, 92, 108, 142, 25, 44, 71, 207, 95, 251,
+ 148, 59, 71, 110, 113, 254, 48, 115, 234, 226, 56, 138, 25, 148, 75,
+ 207, 145, 3, 26, 117, 42, 184, 92, 148, 63, 204, 248, 237, 77, 165,
+ 152, 177, 115, 58, 176, 222, 164, 46, 97, 139, 242, 135, 153, 161, 241,
+ 87, 216, 121, 120, 139, 115, 157, 35, 71, 236, 181, 40, 127, 152, 249,
+ 121, 20, 119, 142, 220, 98, 230, 67, 185, 229, 161, 77, 115, 247, 175,
+ 77, 247, 236, 44, 202, 91, 30, 218, 239, 127, 42, 47, 204, 64, 30,
+ 218, 234, 127, 42, 207, 98, 32, 15, 237, 226, 169, 60, 122, 142, 220,
+ 66, 134, 25, 251, 199, 224, 7, 75, 140, 48, 163, 223, 83, 100, 1,
+ 94, 199, 39, 230, 152, 193, 114, 244, 28, 185, 5, 76, 190, 207, 39,
+ 226, 226, 12, 202, 165, 190, 134, 58, 22, 106, 243, 22, 243, 197, 197,
+ 25, 11, 167, 3, 235, 77, 234, 98, 157, 47, 46, 206, 160, 92, 30,
+ 51, 22, 77, 135, 243, 99, 113, 113, 6, 237, 46, 50, 206, 160, 141,
+ 69, 198, 25, 235, 124, 177, 113, 6, 109, 39, 50, 206, 32, 78, 8,
+ 102, 44, 81, 224, 7, 11, 141, 48, 163, 223, 131, 225, 156, 7, 237,
+ 249, 92, 115, 204, 96, 57, 26, 3, 230, 49, 249, 41, 115, 196, 97,
+ 198, 206, 233, 112, 194, 59, 57, 53, 61, 161, 115, 196, 97, 6, 229,
+ 210, 122, 0, 77, 234, 146, 22, 37, 14, 51, 246, 185, 122, 204, 160,
+ 78, 69, 90, 148, 56, 204, 160, 221, 69, 142, 103, 66, 231, 136, 29,
+ 207, 160, 61, 69, 142, 103, 28, 81, 98, 199, 51, 136, 19, 58, 207,
+ 255, 97, 166, 183, 253, 99, 119, 152, 25, 53, 120, 212, 32, 188, 26,
+ 97, 146, 238, 140, 95, 71, 36, 140, 127, 198, 103, 190, 244, 45, 115,
+ 99, 6, 203, 17, 63, 136, 179, 112, 229, 199, 101, 122, 91, 76, 254,
+ 140, 246, 174, 182, 238, 48, 141, 222, 91, 128, 114, 233, 28, 0, 188,
+ 19, 234, 84, 250, 102, 99, 60, 209, 145, 247, 222, 213, 237, 91, 199,
+ 178, 59, 75, 198, 51, 29, 88, 111, 82, 23, 231, 104, 79, 116, 228,
+ 189, 119, 117, 218, 233, 222, 108, 14, 128, 211, 97, 209, 116, 42, 255,
+ 126, 232, 137, 142, 188, 247, 174, 158, 110, 62, 155, 238, 93, 69, 187,
+ 243, 251, 245, 208, 142, 196, 135, 8, 141, 103, 91, 179, 231, 238, 219,
+ 93, 60, 219, 186, 94, 121, 114, 46, 70, 119, 153, 148, 199, 179, 173,
+ 183, 180, 124, 203, 144, 247, 113, 137, 177, 242, 215, 191, 221, 214, 238,
+ 114, 157, 37, 175, 158, 234, 183, 75, 157, 243, 141, 146, 171, 85, 155,
+ 210, 214, 120, 206, 119, 129, 188, 187, 223, 112, 122, 198, 57, 161, 241,
+ 108, 107, 246, 220, 100, 207, 226, 24, 189, 13, 240, 59, 19, 27, 16,
+ 26, 109, 192, 158, 187, 151, 151, 10, 54, 200, 241, 157, 74, 207, 121,
+ 39, 229, 139, 129, 13, 154, 141, 29, 109, 122, 206, 123, 244, 180, 161,
+ 244, 156, 247, 13, 97, 31, 180, 35, 54, 8, 29, 253, 78, 59, 51,
+ 27, 164, 150, 238, 211, 142, 216, 128, 208, 104, 3, 246, 220, 216, 6,
+ 232, 183, 188, 13, 208, 15, 137, 13, 8, 141, 54, 96, 207, 243, 182,
+ 193, 199, 139, 122, 209, 243, 254, 73, 121, 180, 193, 185, 208, 62, 166,
+ 231, 253, 255, 214, 189, 63, 61, 231, 189, 64, 207, 62, 244, 188, 255,
+ 133, 79, 122, 154, 158, 243, 30, 90, 211, 78, 247, 174, 18, 26, 109,
+ 192, 158, 27, 219, 0, 113, 197, 219, 0, 113, 66, 108, 64, 104, 180,
+ 1, 123, 158, 183, 13, 170, 52, 152, 77, 247, 174, 146, 242, 104, 131,
+ 203, 173, 102, 155, 158, 243, 94, 214, 62, 155, 158, 243, 254, 203, 27,
+ 179, 233, 57, 239, 211, 123, 206, 54, 61, 231, 189, 196, 187, 108, 239,
+ 42, 161, 209, 6, 236, 185, 201, 60, 48, 216, 128, 158, 139, 56, 12,
+ 218, 153, 40, 179, 24, 192, 206, 172, 142, 25, 149, 233, 237, 55, 210,
+ 60, 6, 96, 57, 218, 118, 142, 98, 229, 227, 70, 120, 26, 3, 220,
+ 247, 5, 16, 239, 180, 237, 228, 116, 196, 192, 59, 197, 104, 122, 236,
+ 35, 60, 141, 1, 238, 117, 32, 158, 104, 61, 70, 114, 245, 0, 154,
+ 212, 37, 101, 184, 167, 49, 192, 189, 14, 244, 87, 90, 143, 145, 185,
+ 98, 128, 102, 223, 208, 225, 158, 198, 0, 247, 58, 208, 31, 232, 156,
+ 209, 136, 76, 221, 94, 78, 214, 110, 58, 108, 132, 198, 115, 207, 141,
+ 218, 83, 221, 188, 109, 46, 121, 172, 13, 114, 216, 8, 141, 242, 140,
+ 218, 38, 221, 188, 237, 112, 189, 60, 134, 103, 135, 141, 208, 40, 207,
+ 8, 231, 186, 126, 93, 46, 121, 12, 27, 14, 27, 161, 81, 158, 17,
+ 102, 116, 103, 86, 15, 99, 152, 137, 25, 4, 126, 192, 197, 103, 247,
+ 152, 225, 206, 172, 6, 94, 215, 16, 115, 204, 96, 57, 186, 23, 123,
+ 40, 43, 31, 54, 68, 28, 102, 80, 46, 221, 139, 13, 52, 234, 84,
+ 10, 13, 17, 135, 153, 80, 78, 7, 214, 155, 212, 37, 122, 176, 56,
+ 204, 160, 92, 221, 25, 6, 154, 14, 191, 193, 226, 48, 131, 118, 231,
+ 243, 198, 220, 97, 6, 243, 198, 60, 197, 140, 37, 151, 60, 119, 152,
+ 65, 121, 158, 98, 6, 237, 201, 203, 115, 135, 25, 148, 231, 41, 102,
+ 252, 114, 201, 115, 135, 25, 148, 231, 41, 102, 16, 39, 116, 189, 49,
+ 28, 252, 96, 152, 25, 102, 184, 51, 171, 17, 99, 179, 205, 49, 131,
+ 229, 104, 12, 8, 101, 229, 173, 161, 226, 48, 131, 114, 169, 14, 120,
+ 39, 212, 169, 196, 178, 8, 129, 113, 102, 54, 23, 103, 128, 38, 117,
+ 177, 71, 8, 140, 51, 179, 115, 197, 25, 205, 190, 41, 225, 226, 48,
+ 131, 118, 207, 47, 102, 116, 107, 29, 17, 249, 199, 140, 110, 173, 35,
+ 34, 255, 152, 225, 229, 161, 237, 242, 139, 25, 190, 111, 134, 56, 161,
+ 57, 18, 211, 193, 15, 6, 153, 97, 134, 157, 89, 157, 50, 43, 211,
+ 59, 100, 166, 57, 102, 176, 28, 93, 167, 155, 197, 202, 187, 102, 228,
+ 15, 51, 252, 248, 60, 132, 211, 145, 2, 239, 148, 162, 233, 9, 155,
+ 145, 63, 204, 240, 227, 115, 148, 75, 235, 1, 52, 173, 203, 140, 252,
+ 97, 134, 31, 159, 135, 204, 212, 99, 38, 69, 179, 111, 244, 244, 252,
+ 97, 134, 140, 207, 131, 53, 187, 19, 31, 114, 189, 91, 196, 249, 113,
+ 133, 243, 193, 185, 199, 231, 209, 71, 78, 216, 206, 22, 76, 246, 232,
+ 174, 193, 48, 78, 222, 161, 247, 139, 56, 39, 166, 110, 9, 206, 61,
+ 214, 117, 130, 188, 166, 119, 231, 121, 118, 231, 46, 39, 239, 13, 144,
+ 183, 123, 111, 159, 132, 220, 227, 198, 80, 144, 119, 183, 243, 4, 207,
+ 114, 36, 166, 51, 121, 150, 129, 69, 156, 127, 111, 140, 122, 105, 12,
+ 22, 119, 244, 132, 237, 92, 118, 184, 103, 57, 18, 211, 25, 102, 82,
+ 154, 131, 31, 132, 155, 97, 166, 21, 219, 191, 63, 13, 120, 167, 154,
+ 99, 6, 203, 209, 220, 130, 105, 172, 188, 223, 68, 79, 49, 227, 227,
+ 222, 159, 75, 183, 221, 77, 115, 11, 56, 29, 209, 240, 78, 209, 154,
+ 30, 107, 176, 167, 152, 113, 175, 99, 218, 241, 177, 109, 104, 61, 166,
+ 114, 245, 0, 154, 212, 197, 222, 218, 83, 204, 184, 215, 177, 166, 252,
+ 25, 122, 150, 188, 207, 84, 61, 102, 162, 53, 251, 134, 180, 240, 20,
+ 51, 238, 117, 124, 243, 66, 197, 140, 179, 128, 106, 247, 122, 74, 73,
+ 117, 31, 25, 218, 145, 250, 184, 70, 227, 254, 73, 246, 220, 125, 187,
+ 139, 251, 39, 251, 37, 52, 218, 77, 246, 145, 125, 147, 220, 85, 161,
+ 131, 82, 7, 73, 15, 14, 142, 48, 228, 245, 241, 93, 42, 157, 10,
+ 250, 178, 45, 217, 71, 70, 176, 90, 241, 217, 102, 105, 245, 103, 107,
+ 12, 231, 195, 202, 23, 220, 38, 245, 61, 119, 71, 43, 179, 83, 138,
+ 125, 165, 182, 130, 157, 170, 207, 18, 164, 230, 39, 122, 24, 198, 158,
+ 199, 5, 246, 73, 63, 237, 88, 76, 207, 173, 45, 211, 105, 131, 66,
+ 63, 13, 63, 44, 69, 151, 220, 102, 200, 155, 25, 121, 76, 114, 30,
+ 76, 214, 202, 164, 72, 63, 120, 29, 209, 120, 79, 74, 253, 131, 79,
+ 27, 242, 62, 143, 60, 35, 21, 105, 126, 142, 158, 17, 63, 49, 240,
+ 178, 122, 71, 95, 196, 89, 233, 108, 157, 91, 198, 239, 28, 121, 65,
+ 122, 107, 98, 6, 61, 35, 126, 219, 219, 143, 180, 243, 229, 47, 75,
+ 37, 236, 89, 198, 243, 62, 145, 215, 164, 240, 185, 247, 233, 25, 241,
+ 69, 134, 164, 41, 116, 199, 136, 219, 82, 172, 244, 192, 144, 183, 223,
+ 156, 187, 82, 224, 205, 235, 244, 204, 219, 218, 209, 69, 149, 125, 138,
+ 127, 58, 210, 165, 247, 79, 188, 98, 184, 103, 241, 189, 168, 76, 41,
+ 116, 127, 127, 173, 76, 150, 116, 244, 122, 132, 66, 219, 194, 179, 165,
+ 249, 94, 203, 12, 121, 227, 34, 114, 164, 236, 10, 241, 244, 140, 248,
+ 242, 245, 118, 40, 244, 215, 54, 47, 57, 166, 233, 78, 67, 222, 198,
+ 201, 222, 242, 170, 175, 99, 232, 30, 77, 223, 178, 170, 174, 202, 17,
+ 133, 229, 55, 174, 143, 55, 228, 221, 22, 89, 76, 238, 191, 180, 161,
+ 86, 166, 164, 124, 225, 7, 245, 187, 252, 209, 190, 148, 188, 229, 249,
+ 14, 67, 91, 173, 112, 150, 150, 75, 180, 28, 79, 207, 136, 63, 215,
+ 163, 137, 66, 239, 110, 95, 86, 14, 40, 127, 209, 208, 159, 241, 204,
+ 91, 54, 127, 236, 75, 105, 60, 243, 214, 108, 94, 153, 96, 26, 219,
+ 57, 130, 105, 188, 187, 1, 219, 45, 26, 103, 52, 26, 239, 110, 96,
+ 207, 221, 203, 251, 23, 48, 157, 250, 93, 17, 186, 47, 119, 210, 218,
+ 113, 74, 249, 158, 128, 233, 15, 166, 215, 51, 236, 119, 102, 149, 95,
+ 42, 249, 238, 111, 74, 207, 136, 39, 241, 18, 239, 110, 24, 183, 105,
+ 186, 241, 121, 220, 5, 182, 73, 213, 215, 134, 211, 51, 226, 51, 143,
+ 168, 103, 60, 23, 6, 76, 95, 58, 180, 208, 144, 247, 25, 96, 122,
+ 254, 196, 21, 237, 8, 166, 255, 170, 181, 86, 61, 7, 60, 226, 176,
+ 148, 147, 181, 174, 157, 49, 46, 143, 73, 71, 131, 55, 180, 35, 152,
+ 62, 19, 242, 131, 198, 123, 82, 186, 48, 116, 179, 241, 59, 3, 166,
+ 119, 63, 220, 218, 142, 96, 250, 131, 121, 241, 234, 156, 52, 96, 186,
+ 96, 165, 95, 12, 121, 45, 81, 23, 164, 111, 198, 236, 166, 231, 88,
+ 63, 206, 114, 170, 231, 233, 3, 166, 223, 157, 119, 208, 144, 183, 64,
+ 212, 53, 105, 137, 245, 120, 59, 130, 233, 117, 209, 127, 41, 180, 15,
+ 96, 250, 113, 218, 191, 134, 188, 205, 162, 238, 74, 143, 222, 188, 209,
+ 142, 96, 122, 231, 195, 108, 133, 238, 31, 145, 46, 253, 211, 181, 72,
+ 123, 35, 222, 14, 128, 233, 228, 130, 85, 219, 19, 76, 223, 172, 22,
+ 216, 94, 197, 86, 182, 228, 104, 25, 108, 200, 219, 52, 50, 71, 106,
+ 191, 234, 3, 122, 142, 245, 227, 153, 3, 21, 186, 55, 98, 250, 131,
+ 80, 67, 222, 7, 78, 111, 185, 113, 41, 59, 61, 199, 122, 149, 203,
+ 170, 208, 127, 132, 23, 150, 39, 46, 42, 103, 200, 123, 6, 48, 189,
+ 251, 226, 45, 122, 190, 188, 207, 171, 170, 157, 31, 0, 166, 43, 12,
+ 251, 177, 157, 177, 222, 210, 242, 149, 239, 86, 208, 243, 229, 223, 148,
+ 23, 41, 116, 22, 96, 186, 77, 242, 108, 99, 191, 2, 76, 179, 245,
+ 16, 95, 74, 95, 0, 76, 155, 173, 147, 16, 76, 99, 191, 130, 96,
+ 26, 239, 125, 192, 126, 2, 193, 52, 161, 241, 222, 7, 246, 220, 189,
+ 188, 211, 128, 233, 107, 79, 147, 219, 18, 76, 119, 45, 122, 85, 41,
+ 223, 30, 48, 253, 161, 165, 170, 97, 251, 242, 0, 48, 253, 211, 23,
+ 101, 232, 125, 44, 164, 207, 90, 16, 48, 29, 236, 59, 208, 176, 77,
+ 44, 0, 113, 186, 207, 175, 163, 232, 125, 44, 199, 146, 35, 212, 187,
+ 141, 1, 211, 29, 174, 47, 72, 52, 195, 116, 229, 217, 107, 105, 156,
+ 118, 90, 54, 171, 52, 96, 122, 73, 114, 188, 49, 47, 96, 218, 235,
+ 195, 93, 52, 78, 255, 60, 110, 143, 198, 123, 82, 122, 123, 226, 126,
+ 211, 56, 61, 213, 113, 136, 198, 233, 109, 27, 143, 210, 56, 125, 255,
+ 120, 138, 137, 222, 11, 82, 157, 15, 254, 166, 113, 250, 221, 5, 255,
+ 104, 188, 151, 165, 232, 237, 231, 18, 141, 219, 131, 107, 210, 188, 123,
+ 169, 52, 78, 127, 87, 92, 189, 83, 165, 1, 96, 58, 163, 254, 69,
+ 67, 222, 56, 192, 244, 152, 27, 231, 104, 156, 238, 80, 250, 169, 66,
+ 79, 159, 157, 46, 85, 108, 88, 202, 48, 230, 165, 0, 166, 223, 250,
+ 178, 57, 141, 211, 221, 218, 246, 85, 232, 154, 128, 233, 202, 183, 63,
+ 50, 228, 29, 48, 59, 71, 154, 57, 114, 37, 141, 211, 219, 63, 89,
+ 165, 208, 223, 3, 166, 247, 111, 92, 109, 200, 123, 21, 48, 189, 233,
+ 124, 20, 141, 211, 13, 215, 140, 83, 232, 197, 128, 233, 222, 227, 236,
+ 134, 188, 177, 128, 233, 173, 101, 202, 209, 56, 221, 166, 213, 37, 165,
+ 190, 23, 0, 211, 247, 254, 216, 99, 104, 171, 191, 1, 211, 201, 182,
+ 53, 52, 78, 71, 206, 81, 253, 240, 38, 96, 186, 226, 138, 177, 198,
+ 223, 23, 48, 205, 214, 247, 124, 41, 253, 47, 96, 218, 108, 221, 143,
+ 96, 26, 251, 241, 124, 223, 27, 251, 229, 4, 211, 132, 198, 190, 55,
+ 123, 158, 119, 223, 251, 251, 82, 44, 135, 99, 169, 86, 30, 115, 151,
+ 206, 92, 49, 230, 197, 220, 165, 115, 107, 103, 211, 28, 14, 50, 110,
+ 44, 0, 152, 30, 83, 195, 108, 13, 109, 155, 212, 172, 232, 108, 122,
+ 54, 253, 192, 125, 234, 126, 189, 130, 128, 233, 197, 17, 102, 247, 44,
+ 239, 147, 206, 209, 59, 154, 15, 73, 239, 204, 8, 215, 206, 121, 63,
+ 44, 173, 178, 27, 231, 112, 96, 156, 62, 127, 143, 228, 127, 164, 72,
+ 31, 238, 82, 105, 140, 211, 89, 243, 102, 217, 204, 48, 253, 221, 219,
+ 179, 232, 185, 246, 71, 26, 206, 162, 231, 218, 167, 63, 158, 105, 194,
+ 123, 65, 218, 176, 113, 38, 61, 215, 222, 54, 127, 166, 141, 96, 58,
+ 117, 184, 25, 239, 53, 233, 234, 132, 153, 244, 92, 251, 175, 123, 105,
+ 247, 89, 3, 166, 223, 106, 100, 204, 235, 15, 152, 126, 176, 121, 38,
+ 205, 149, 249, 226, 152, 122, 94, 79, 56, 196, 233, 196, 187, 83, 13,
+ 121, 147, 0, 211, 187, 119, 77, 164, 231, 218, 55, 254, 104, 156, 66,
+ 47, 7, 76, 159, 174, 63, 202, 144, 119, 136, 35, 71, 90, 178, 252,
+ 61, 122, 174, 125, 171, 148, 119, 213, 92, 25, 192, 116, 149, 146, 239,
+ 26, 242, 158, 0, 76, 23, 93, 54, 140, 230, 232, 92, 136, 87, 117,
+ 45, 1, 76, 31, 188, 63, 193, 248, 157, 1, 211, 157, 202, 78, 163,
+ 231, 218, 63, 94, 171, 214, 61, 29, 48, 189, 100, 152, 177, 111, 100,
+ 3, 166, 43, 84, 141, 160, 231, 218, 39, 173, 140, 160, 231, 218, 15,
+ 171, 48, 219, 244, 92, 123, 182, 94, 237, 75, 105, 60, 215, 222, 108,
+ 29, 155, 230, 204, 55, 103, 115, 40, 214, 129, 64, 79, 55, 155, 67,
+ 97, 103, 116, 135, 0, 111, 74, 83, 243, 57, 20, 44, 71, 231, 4,
+ 155, 177, 242, 161, 77, 197, 205, 213, 163, 92, 58, 39, 8, 52, 234,
+ 84, 188, 207, 42, 110, 174, 62, 132, 211, 129, 245, 38, 117, 113, 88,
+ 197, 205, 213, 163, 92, 93, 206, 188, 166, 35, 110, 160, 184, 185, 122,
+ 180, 187, 200, 245, 45, 180, 177, 200, 245, 45, 135, 85, 236, 250, 22,
+ 218, 78, 228, 250, 150, 130, 19, 77, 94, 218, 59, 224, 7, 205, 205,
+ 48, 195, 206, 232, 142, 251, 32, 211, 219, 250, 190, 57, 102, 176, 28,
+ 241, 3, 235, 7, 172, 188, 243, 61, 113, 152, 177, 114, 58, 226, 224,
+ 157, 226, 52, 61, 33, 239, 137, 195, 12, 202, 165, 245, 0, 154, 212,
+ 197, 245, 174, 56, 204, 88, 223, 215, 99, 38, 78, 179, 111, 216, 187,
+ 226, 48, 131, 118, 23, 185, 190, 21, 242, 158, 216, 245, 45, 180, 167,
+ 200, 245, 173, 176, 119, 197, 174, 111, 33, 78, 8, 102, 226, 222, 2,
+ 63, 24, 104, 130, 25, 238, 140, 238, 48, 224, 77, 27, 96, 142, 25,
+ 44, 71, 252, 32, 237, 109, 86, 222, 49, 64, 28, 102, 80, 46, 209,
+ 17, 6, 52, 234, 84, 34, 247, 0, 113, 152, 9, 227, 116, 96, 189,
+ 73, 93, 98, 250, 139, 195, 12, 202, 229, 49, 19, 166, 233, 176, 246,
+ 23, 135, 25, 180, 187, 200, 56, 227, 51, 64, 108, 156, 65, 123, 138,
+ 140, 51, 214, 254, 98, 227, 12, 226, 132, 96, 38, 172, 15, 248, 193,
+ 59, 102, 152, 97, 123, 182, 173, 192, 27, 215, 207, 28, 51, 88, 142,
+ 198, 128, 55, 89, 121, 123, 63, 113, 152, 65, 185, 52, 6, 0, 141,
+ 58, 149, 145, 80, 95, 113, 152, 177, 114, 58, 176, 222, 164, 46, 161,
+ 125, 197, 97, 6, 229, 242, 152, 177, 106, 58, 210, 250, 136, 195, 12,
+ 218, 93, 100, 156, 65, 27, 139, 140, 51, 161, 125, 197, 198, 25, 180,
+ 157, 200, 56, 131, 56, 161, 103, 116, 119, 7, 63, 120, 203, 12, 51,
+ 108, 143, 107, 90, 239, 76, 239, 152, 158, 230, 152, 193, 114, 116, 95,
+ 80, 47, 110, 239, 81, 79, 129, 123, 143, 122, 113, 251, 130, 128, 70,
+ 157, 74, 255, 175, 135, 56, 204, 248, 113, 58, 176, 222, 164, 46, 33,
+ 61, 196, 97, 6, 229, 234, 206, 181, 215, 116, 184, 186, 11, 220, 123,
+ 212, 83, 108, 156, 65, 27, 139, 140, 51, 33, 61, 196, 198, 25, 180,
+ 157, 200, 56, 131, 56, 161, 152, 233, 4, 125, 154, 62, 121, 98, 230,
+ 163, 81, 35, 70, 106, 50, 180, 89, 165, 110, 153, 222, 161, 93, 73,
+ 121, 95, 25, 111, 170, 192, 140, 165, 151, 238, 79, 233, 198, 237, 63,
+ 237, 198, 197, 153, 46, 153, 121, 222, 111, 240, 101, 74, 243, 221, 181,
+ 188, 146, 218, 27, 229, 6, 37, 255, 23, 201, 238, 208, 226, 116, 184,
+ 224, 157, 92, 154, 30, 191, 55, 242, 214, 113, 124, 70, 221, 36, 203,
+ 148, 27, 109, 141, 114, 131, 78, 245, 237, 206, 246, 159, 118, 229, 234,
+ 1, 52, 173, 203, 235, 121, 235, 240, 143, 94, 148, 20, 245, 209, 174,
+ 182, 70, 185, 65, 203, 198, 244, 98, 103, 26, 119, 213, 99, 198, 165,
+ 217, 215, 213, 41, 111, 29, 255, 38, 15, 180, 253, 94, 194, 97, 120,
+ 174, 125, 70, 111, 150, 27, 132, 118, 231, 243, 33, 208, 142, 68, 30,
+ 161, 49, 31, 130, 61, 199, 251, 62, 155, 88, 54, 90, 172, 150, 31,
+ 185, 59, 94, 49, 55, 168, 236, 152, 63, 180, 50, 221, 101, 82, 30,
+ 115, 131, 198, 207, 27, 100, 24, 163, 48, 55, 168, 85, 220, 11, 109,
+ 109, 103, 150, 156, 54, 110, 109, 27, 117, 46, 55, 74, 206, 184, 18,
+ 178, 219, 120, 62, 118, 129, 124, 239, 249, 251, 218, 250, 207, 18, 74,
+ 99, 62, 4, 123, 158, 119, 236, 73, 211, 252, 130, 183, 1, 126, 103,
+ 98, 3, 66, 163, 13, 216, 115, 180, 65, 16, 216, 32, 16, 108, 16,
+ 168, 203, 9, 73, 123, 240, 38, 205, 139, 33, 229, 49, 39, 228, 191,
+ 130, 93, 77, 243, 98, 130, 47, 203, 52, 47, 230, 217, 158, 96, 154,
+ 23, 211, 224, 135, 214, 166, 121, 49, 137, 205, 173, 52, 47, 134, 208,
+ 104, 3, 246, 220, 216, 6, 232, 183, 188, 13, 208, 15, 137, 13, 8,
+ 141, 54, 96, 207, 209, 6, 141, 220, 218, 224, 148, 181, 59, 181, 1,
+ 41, 143, 54, 8, 110, 30, 98, 106, 131, 39, 23, 222, 164, 54, 216,
+ 48, 180, 55, 181, 65, 213, 81, 230, 185, 65, 67, 130, 88, 110, 16,
+ 161, 209, 6, 236, 185, 177, 13, 16, 87, 188, 13, 16, 39, 196, 6,
+ 132, 70, 27, 176, 231, 104, 131, 105, 96, 131, 105, 96, 131, 105, 58,
+ 27, 124, 215, 153, 229, 6, 145, 242, 104, 131, 31, 251, 153, 231, 6,
+ 29, 121, 143, 229, 6, 45, 30, 202, 114, 131, 126, 29, 101, 158, 27,
+ 84, 118, 50, 203, 13, 34, 52, 218, 128, 61, 55, 238, 55, 97, 187,
+ 79, 243, 67, 37, 104, 215, 186, 27, 198, 0, 93, 126, 168, 171, 35,
+ 148, 239, 224, 65, 12, 232, 200, 181, 157, 29, 153, 252, 52, 217, 211,
+ 24, 224, 190, 47, 128, 120, 167, 109, 39, 167, 195, 5, 239, 228, 210,
+ 244, 56, 100, 79, 99, 128, 123, 29, 136, 39, 90, 143, 14, 92, 61,
+ 128, 38, 117, 241, 145, 61, 141, 1, 238, 117, 160, 191, 210, 122, 116,
+ 200, 21, 3, 52, 251, 198, 72, 158, 198, 0, 247, 58, 208, 31, 104,
+ 223, 91, 214, 231, 202, 176, 118, 211, 97, 35, 52, 230, 202, 24, 181,
+ 167, 186, 121, 219, 92, 242, 88, 27, 228, 176, 17, 26, 229, 25, 181,
+ 77, 186, 241, 126, 46, 121, 12, 207, 14, 27, 161, 81, 158, 17, 206,
+ 117, 227, 125, 73, 47, 143, 97, 195, 97, 35, 52, 202, 51, 194, 140,
+ 238, 126, 83, 137, 235, 55, 5, 129, 31, 116, 50, 195, 12, 151, 79,
+ 103, 135, 254, 118, 99, 115, 204, 96, 57, 218, 71, 111, 194, 141, 53,
+ 26, 139, 195, 12, 202, 165, 99, 13, 160, 81, 167, 50, 214, 104, 36,
+ 14, 51, 126, 156, 14, 172, 55, 169, 75, 72, 35, 113, 152, 65, 185,
+ 186, 177, 134, 166, 195, 21, 36, 14, 51, 104, 119, 190, 239, 237, 14,
+ 51, 216, 247, 246, 20, 51, 104, 99, 94, 158, 59, 204, 160, 60, 79,
+ 49, 19, 146, 75, 158, 59, 204, 160, 60, 79, 49, 131, 182, 227, 229,
+ 185, 195, 12, 202, 243, 20, 51, 136, 19, 26, 103, 26, 102, 122, 251,
+ 73, 102, 152, 97, 249, 116, 174, 64, 192, 88, 128, 7, 113, 38, 144,
+ 107, 159, 3, 185, 56, 227, 47, 48, 206, 112, 58, 92, 240, 78, 46,
+ 77, 143, 195, 95, 96, 156, 9, 224, 234, 1, 52, 169, 139, 143, 191,
+ 192, 56, 19, 144, 43, 206, 104, 246, 141, 105, 40, 48, 206, 248, 231,
+ 31, 51, 252, 156, 145, 195, 63, 255, 152, 225, 229, 249, 248, 231, 31,
+ 51, 188, 60, 180, 93, 126, 49, 195, 247, 205, 16, 39, 52, 111, 187,
+ 14, 248, 65, 144, 25, 102, 88, 62, 93, 76, 3, 192, 88, 125, 15,
+ 226, 76, 3, 46, 6, 52, 224, 242, 182, 235, 229, 15, 51, 252, 248,
+ 220, 143, 211, 17, 3, 239, 20, 163, 233, 177, 215, 203, 31, 102, 248,
+ 241, 57, 202, 165, 245, 0, 154, 212, 37, 165, 110, 254, 48, 195, 143,
+ 207, 253, 234, 231, 202, 167, 211, 236, 27, 90, 55, 127, 152, 33, 227,
+ 243, 96, 205, 238, 196, 135, 252, 222, 43, 226, 252, 44, 235, 104, 66,
+ 238, 241, 185, 227, 200, 9, 91, 192, 131, 253, 121, 142, 207, 117, 121,
+ 219, 156, 188, 79, 62, 40, 226, 28, 89, 249, 203, 132, 220, 99, 93,
+ 235, 209, 19, 182, 11, 47, 134, 229, 57, 214, 213, 229, 109, 215, 101,
+ 242, 124, 222, 47, 226, 76, 92, 243, 106, 66, 238, 113, 35, 230, 6,
+ 205, 223, 51, 62, 207, 113, 163, 46, 111, 155, 147, 87, 116, 96, 17,
+ 103, 203, 45, 81, 47, 141, 193, 156, 248, 126, 213, 35, 242, 28, 131,
+ 233, 242, 182, 235, 112, 125, 179, 90, 224, 7, 13, 205, 48, 195, 242,
+ 233, 66, 129, 215, 85, 203, 28, 51, 88, 142, 198, 128, 218, 92, 223,
+ 172, 186, 167, 152, 113, 159, 239, 210, 54, 180, 35, 187, 179, 189, 54,
+ 23, 3, 128, 70, 157, 10, 102, 42, 123, 138, 25, 247, 58, 2, 50,
+ 70, 209, 188, 157, 80, 78, 7, 214, 155, 212, 37, 196, 215, 83, 204,
+ 184, 215, 33, 117, 187, 64, 117, 160, 92, 93, 222, 182, 166, 195, 90,
+ 210, 83, 204, 184, 215, 177, 130, 203, 13, 66, 187, 243, 251, 19, 209,
+ 142, 68, 30, 161, 113, 127, 34, 123, 142, 103, 76, 55, 177, 52, 4,
+ 220, 180, 133, 31, 191, 63, 113, 76, 199, 202, 116, 207, 241, 134, 226,
+ 29, 20, 58, 48, 117, 144, 116, 43, 101, 44, 229, 237, 11, 60, 35,
+ 224, 55, 147, 227, 45, 229, 187, 84, 74, 76, 107, 181, 155, 236, 79,
+ 36, 88, 45, 255, 108, 179, 84, 98, 102, 140, 225, 92, 90, 185, 130,
+ 219, 164, 87, 187, 223, 10, 38, 251, 19, 187, 246, 171, 161, 204, 47,
+ 87, 121, 150, 32, 93, 45, 240, 6, 157, 107, 142, 179, 52, 181, 108,
+ 183, 52, 179, 236, 180, 52, 103, 249, 61, 5, 246, 73, 187, 253, 23,
+ 208, 60, 130, 173, 239, 169, 185, 3, 152, 27, 148, 49, 121, 11, 229,
+ 77, 180, 180, 176, 36, 91, 90, 90, 14, 88, 90, 177, 185, 135, 200,
+ 99, 210, 188, 51, 187, 104, 30, 193, 145, 142, 251, 20, 250, 89, 248,
+ 73, 233, 234, 182, 35, 38, 185, 0, 103, 164, 17, 11, 254, 164, 121,
+ 4, 183, 127, 73, 165, 121, 4, 19, 175, 94, 164, 188, 135, 65, 223,
+ 113, 203, 171, 150, 20, 248, 49, 189, 23, 164, 249, 235, 238, 208, 60,
+ 130, 155, 245, 210, 84, 58, 226, 178, 212, 118, 211, 67, 202, 123, 18,
+ 120, 78, 91, 90, 91, 254, 178, 180, 166, 188, 94, 81, 215, 164, 83,
+ 115, 238, 210, 60, 130, 168, 87, 31, 40, 116, 175, 136, 219, 210, 198,
+ 255, 50, 40, 111, 42, 240, 158, 5, 190, 243, 28, 239, 71, 115, 238,
+ 74, 242, 226, 251, 52, 143, 224, 82, 139, 210, 202, 62, 252, 139, 142,
+ 116, 41, 250, 112, 93, 186, 39, 255, 34, 240, 92, 178, 188, 102, 185,
+ 2, 222, 65, 120, 135, 69, 101, 74, 239, 47, 31, 72, 243, 8, 190,
+ 191, 52, 71, 161, 131, 195, 179, 165, 170, 143, 86, 82, 222, 107, 22,
+ 155, 229, 134, 69, 182, 220, 178, 116, 162, 188, 225, 17, 57, 82, 102,
+ 253, 157, 52, 143, 96, 111, 249, 221, 10, 253, 139, 205, 75, 174, 241,
+ 60, 145, 242, 222, 177, 116, 177, 220, 179, 116, 181, 164, 193, 143, 238,
+ 169, 76, 246, 150, 35, 46, 125, 71, 243, 8, 70, 39, 173, 80, 232,
+ 130, 17, 133, 229, 43, 55, 39, 81, 222, 116, 203, 235, 150, 12, 208,
+ 153, 101, 177, 83, 222, 31, 35, 139, 201, 19, 195, 131, 218, 147, 253,
+ 137, 27, 250, 169, 117, 63, 216, 190, 148, 108, 251, 124, 23, 181, 85,
+ 14, 214, 211, 171, 181, 165, 144, 87, 11, 202, 251, 185, 179, 180, 188,
+ 168, 196, 20, 154, 71, 112, 57, 165, 133, 66, 255, 214, 190, 172, 60,
+ 99, 202, 13, 195, 249, 93, 204, 13, 98, 243, 199, 190, 148, 190, 60,
+ 189, 130, 204, 207, 43, 23, 247, 178, 90, 74, 195, 175, 156, 151, 245,
+ 229, 60, 130, 202, 250, 60, 2, 108, 183, 8, 166, 9, 221, 9, 48,
+ 205, 158, 35, 166, 45, 47, 97, 250, 111, 192, 244, 206, 177, 55, 40,
+ 166, 23, 140, 89, 174, 230, 32, 0, 166, 103, 159, 172, 156, 192, 48,
+ 109, 213, 48, 221, 152, 205, 83, 151, 95, 42, 189, 114, 182, 62, 205,
+ 35, 32, 241, 18, 115, 131, 62, 59, 217, 215, 112, 110, 24, 247, 28,
+ 87, 28, 217, 147, 230, 17, 188, 255, 102, 31, 45, 7, 33, 65, 250,
+ 94, 126, 43, 145, 97, 58, 16, 48, 29, 8, 152, 14, 212, 237, 57,
+ 62, 241, 247, 32, 154, 71, 112, 252, 226, 72, 109, 79, 254, 97, 233,
+ 216, 144, 49, 137, 12, 211, 129, 128, 233, 64, 192, 116, 160, 110, 207,
+ 113, 141, 197, 97, 44, 223, 111, 247, 71, 26, 239, 73, 169, 249, 127,
+ 147, 76, 243, 8, 254, 120, 103, 50, 205, 35, 176, 125, 53, 85, 203,
+ 217, 59, 43, 237, 248, 103, 122, 34, 195, 116, 32, 96, 58, 16, 48,
+ 29, 168, 219, 115, 60, 175, 231, 108, 154, 71, 16, 248, 174, 131, 230,
+ 251, 149, 47, 19, 153, 200, 48, 29, 0, 152, 14, 0, 76, 7, 112,
+ 57, 73, 215, 164, 114, 21, 34, 104, 30, 193, 183, 61, 212, 242, 37,
+ 0, 211, 7, 163, 231, 36, 50, 76, 7, 0, 166, 3, 0, 211, 140,
+ 183, 86, 212, 93, 105, 224, 190, 121, 52, 143, 96, 115, 208, 114, 133,
+ 238, 18, 145, 46, 13, 252, 114, 125, 34, 195, 116, 0, 96, 58, 0,
+ 48, 237, 79, 121, 95, 7, 76, 59, 187, 144, 220, 200, 44, 41, 241,
+ 194, 69, 45, 127, 33, 91, 122, 54, 229, 121, 34, 195, 116, 67, 192,
+ 116, 3, 192, 52, 187, 143, 224, 245, 200, 28, 201, 175, 91, 77, 154,
+ 71, 48, 224, 114, 45, 133, 110, 8, 152, 174, 51, 189, 110, 18, 195,
+ 116, 93, 192, 116, 29, 192, 116, 29, 202, 155, 225, 244, 150, 171, 188,
+ 82, 130, 230, 17, 60, 173, 103, 81, 232, 127, 195, 11, 203, 159, 76,
+ 100, 57, 153, 233, 150, 122, 128, 233, 250, 128, 233, 6, 148, 247, 6,
+ 96, 186, 247, 48, 45, 175, 4, 48, 61, 187, 248, 103, 10, 253, 4,
+ 48, 125, 255, 125, 102, 171, 28, 172, 167, 87, 0, 96, 154, 125, 163,
+ 39, 128, 233, 253, 187, 198, 210, 60, 130, 140, 117, 161, 10, 253, 28,
+ 48, 253, 201, 130, 190, 134, 190, 129, 123, 142, 217, 122, 136, 47, 165,
+ 113, 207, 49, 191, 78, 82, 28, 244, 149, 134, 95, 57, 78, 47, 205,
+ 35, 240, 213, 99, 26, 251, 9, 4, 211, 132, 198, 220, 32, 246, 220,
+ 61, 166, 79, 1, 166, 255, 25, 180, 139, 98, 250, 251, 132, 107, 74,
+ 249, 118, 128, 233, 41, 49, 21, 19, 94, 142, 211, 12, 211, 25, 128,
+ 233, 244, 223, 139, 82, 76, 147, 62, 107, 33, 192, 244, 252, 79, 223,
+ 55, 92, 235, 40, 8, 113, 250, 175, 133, 163, 41, 166, 99, 219, 68,
+ 210, 220, 160, 98, 113, 139, 115, 97, 58, 0, 48, 29, 160, 203, 13,
+ 122, 163, 216, 122, 138, 233, 251, 177, 113, 52, 55, 40, 49, 235, 87,
+ 14, 211, 254, 128, 105, 127, 192, 116, 67, 93, 110, 208, 95, 139, 156,
+ 20, 211, 255, 245, 59, 72, 115, 131, 30, 189, 114, 212, 20, 211, 243,
+ 154, 254, 73, 49, 125, 165, 254, 95, 52, 55, 200, 94, 253, 28, 135,
+ 233, 134, 128, 233, 6, 128, 105, 230, 107, 79, 1, 211, 9, 21, 175,
+ 80, 76, 251, 84, 191, 70, 115, 131, 6, 213, 186, 193, 97, 186, 1,
+ 96, 186, 1, 96, 186, 129, 46, 55, 104, 181, 237, 50, 197, 244, 128,
+ 255, 174, 42, 244, 43, 128, 233, 230, 43, 111, 112, 152, 110, 0, 152,
+ 110, 0, 152, 102, 188, 147, 1, 211, 133, 182, 221, 160, 152, 222, 185,
+ 71, 197, 71, 58, 96, 186, 241, 22, 150, 27, 116, 17, 120, 46, 1,
+ 62, 174, 0, 78, 8, 111, 52, 96, 186, 122, 231, 32, 154, 27, 52,
+ 189, 64, 103, 245, 158, 101, 192, 116, 202, 239, 3, 147, 24, 166, 235,
+ 0, 166, 107, 1, 166, 107, 82, 222, 214, 142, 28, 233, 249, 150, 79,
+ 40, 166, 199, 215, 88, 168, 208, 145, 128, 233, 113, 75, 22, 113, 152,
+ 174, 14, 152, 174, 6, 152, 174, 70, 121, 239, 1, 166, 75, 198, 142,
+ 161, 152, 246, 31, 58, 64, 161, 183, 0, 166, 93, 87, 154, 36, 49,
+ 76, 215, 0, 76, 251, 1, 166, 89, 123, 176, 11, 48, 189, 186, 69,
+ 97, 154, 27, 84, 199, 91, 253, 94, 87, 1, 211, 19, 250, 109, 227,
+ 48, 13, 237, 143, 87, 67, 192, 52, 107, 195, 46, 2, 166, 11, 221,
+ 90, 70, 49, 29, 189, 64, 109, 3, 238, 1, 166, 195, 222, 30, 110,
+ 188, 134, 6, 152, 102, 235, 123, 190, 148, 198, 220, 32, 126, 221, 207,
+ 8, 211, 216, 143, 231, 251, 222, 43, 184, 220, 160, 21, 92, 110, 208,
+ 10, 46, 55, 72, 197, 244, 52, 192, 244, 52, 93, 223, 123, 95, 9,
+ 150, 27, 244, 25, 151, 27, 244, 245, 13, 198, 219, 23, 120, 70, 192,
+ 111, 38, 199, 139, 185, 65, 209, 63, 176, 220, 32, 50, 110, 196, 220,
+ 160, 113, 118, 227, 181, 59, 140, 211, 150, 166, 44, 55, 232, 155, 76,
+ 150, 27, 212, 126, 23, 27, 115, 198, 1, 207, 118, 248, 237, 212, 241,
+ 238, 147, 90, 182, 137, 160, 185, 65, 225, 167, 89, 110, 208, 186, 117,
+ 44, 255, 35, 209, 50, 21, 48, 61, 21, 48, 61, 85, 23, 167, 7,
+ 191, 29, 78, 115, 131, 126, 11, 12, 167, 185, 65, 62, 207, 205, 115,
+ 131, 86, 255, 195, 114, 131, 22, 110, 97, 185, 65, 211, 35, 25, 239,
+ 97, 208, 119, 28, 126, 41, 58, 189, 23, 164, 146, 77, 103, 209, 220,
+ 32, 159, 106, 179, 104, 110, 144, 111, 33, 198, 123, 18, 120, 78, 195,
+ 239, 47, 29, 239, 53, 41, 35, 96, 22, 205, 13, 74, 168, 160, 210,
+ 69, 1, 211, 115, 44, 140, 55, 21, 120, 206, 194, 239, 60, 199, 235,
+ 7, 152, 110, 62, 97, 22, 205, 13, 186, 113, 72, 189, 191, 123, 48,
+ 96, 186, 147, 223, 116, 27, 195, 244, 84, 192, 244, 84, 192, 244, 20,
+ 29, 166, 127, 24, 56, 153, 230, 6, 125, 149, 16, 166, 222, 57, 14,
+ 152, 142, 175, 52, 198, 198, 48, 61, 25, 48, 61, 9, 48, 253, 17,
+ 229, 221, 15, 152, 110, 90, 127, 16, 205, 13, 170, 57, 41, 84, 161,
+ 251, 0, 166, 95, 221, 59, 208, 198, 48, 61, 30, 48, 61, 30, 48,
+ 61, 158, 242, 158, 7, 76, 79, 79, 29, 73, 115, 131, 126, 30, 175,
+ 234, 218, 12, 152, 30, 184, 102, 162, 141, 97, 122, 2, 96, 250, 35,
+ 192, 244, 36, 202, 123, 12, 48, 189, 235, 149, 233, 52, 55, 232, 47,
+ 155, 90, 247, 76, 192, 244, 47, 41, 204, 55, 114, 176, 158, 94, 83,
+ 1, 211, 204, 175, 158, 2, 166, 207, 127, 200, 114, 131, 18, 206, 176,
+ 220, 160, 175, 236, 230, 185, 65, 108, 189, 218, 151, 210, 24, 167, 249,
+ 117, 236, 226, 160, 175, 52, 252, 202, 113, 122, 233, 92, 125, 45, 110,
+ 207, 118, 137, 76, 111, 87, 29, 179, 57, 148, 87, 217, 121, 57, 229,
+ 51, 189, 67, 202, 153, 207, 161, 96, 57, 154, 183, 83, 158, 59, 147,
+ 168, 172, 184, 185, 250, 16, 78, 71, 10, 188, 83, 138, 166, 39, 172,
+ 172, 184, 185, 122, 148, 75, 235, 1, 52, 173, 75, 89, 113, 115, 245,
+ 33, 229, 114, 157, 73, 164, 217, 55, 218, 71, 220, 92, 61, 218, 93,
+ 228, 250, 86, 88, 89, 177, 235, 91, 150, 178, 98, 215, 183, 208, 118,
+ 34, 215, 183, 16, 39, 116, 207, 118, 145, 76, 239, 208, 90, 102, 152,
+ 97, 249, 116, 86, 224, 141, 43, 102, 142, 25, 44, 71, 247, 58, 23,
+ 231, 246, 210, 21, 19, 135, 25, 148, 75, 247, 108, 3, 141, 58, 21,
+ 159, 43, 42, 14, 51, 86, 78, 7, 214, 155, 212, 37, 180, 168, 56,
+ 204, 160, 92, 221, 158, 109, 77, 71, 90, 17, 113, 152, 65, 187, 139,
+ 92, 223, 66, 27, 139, 92, 223, 10, 45, 42, 118, 125, 11, 109, 39,
+ 114, 125, 11, 113, 66, 115, 80, 11, 128, 31, 148, 48, 195, 12, 203,
+ 167, 75, 43, 156, 233, 29, 86, 200, 28, 51, 88, 142, 230, 237, 20,
+ 230, 190, 125, 33, 113, 152, 9, 227, 116, 164, 129, 220, 52, 77, 79,
+ 116, 65, 113, 152, 65, 185, 180, 30, 64, 147, 186, 248, 21, 20, 135,
+ 153, 176, 66, 122, 204, 164, 105, 54, 138, 43, 32, 14, 51, 104, 119,
+ 145, 113, 6, 109, 44, 50, 206, 248, 21, 20, 27, 103, 208, 118, 34,
+ 227, 12, 226, 132, 174, 111, 125, 10, 126, 80, 196, 4, 51, 92, 62,
+ 93, 156, 119, 166, 119, 204, 82, 115, 204, 96, 57, 26, 3, 188, 185,
+ 245, 173, 165, 226, 48, 99, 229, 116, 196, 121, 1, 246, 53, 61, 206,
+ 37, 226, 48, 131, 114, 233, 186, 51, 188, 59, 169, 75, 200, 18, 129,
+ 123, 143, 150, 230, 202, 65, 245, 210, 246, 30, 125, 42, 112, 239, 209,
+ 82, 177, 113, 6, 109, 44, 50, 206, 132, 44, 17, 27, 103, 208, 118,
+ 34, 227, 12, 226, 132, 238, 61, 90, 0, 126, 80, 192, 12, 51, 220,
+ 30, 215, 197, 208, 151, 91, 228, 193, 222, 163, 197, 220, 122, 237, 98,
+ 110, 239, 209, 66, 129, 123, 143, 56, 29, 46, 120, 39, 151, 166, 199,
+ 177, 80, 224, 222, 163, 69, 92, 61, 128, 38, 117, 241, 89, 40, 112,
+ 239, 209, 162, 92, 123, 143, 52, 251, 198, 44, 16, 184, 247, 104, 161,
+ 216, 56, 227, 88, 40, 54, 206, 248, 44, 20, 27, 103, 208, 118, 34,
+ 227, 12, 226, 132, 158, 229, 157, 3, 126, 240, 169, 27, 204, 76, 30,
+ 51, 142, 187, 54, 136, 237, 139, 249, 36, 211, 219, 111, 190, 7, 119,
+ 70, 124, 194, 237, 217, 249, 132, 149, 79, 153, 235, 105, 62, 93, 49,
+ 183, 126, 176, 235, 102, 54, 219, 179, 195, 233, 136, 129, 119, 138, 209,
+ 244, 56, 162, 60, 205, 167, 115, 175, 99, 94, 197, 74, 44, 6, 204,
+ 231, 234, 1, 52, 169, 139, 213, 225, 105, 62, 157, 123, 29, 190, 127,
+ 180, 179, 209, 122, 204, 207, 181, 247, 72, 179, 111, 74, 142, 167, 249,
+ 116, 238, 117, 28, 220, 216, 80, 209, 81, 221, 91, 181, 123, 61, 165,
+ 164, 154, 15, 129, 118, 36, 62, 68, 232, 215, 183, 47, 151, 216, 115,
+ 247, 237, 238, 195, 158, 175, 201, 223, 214, 201, 164, 57, 33, 164, 124,
+ 129, 196, 94, 114, 61, 159, 103, 198, 235, 21, 114, 63, 249, 250, 145,
+ 23, 90, 153, 1, 242, 131, 14, 94, 202, 188, 184, 119, 226, 187, 242,
+ 253, 117, 222, 134, 103, 108, 229, 200, 161, 242, 193, 33, 133, 180, 50,
+ 67, 229, 207, 111, 23, 84, 121, 35, 134, 203, 7, 86, 21, 76, 50,
+ 158, 83, 29, 37, 251, 61, 246, 210, 202, 140, 145, 187, 132, 171, 107,
+ 14, 94, 17, 227, 228, 107, 133, 159, 155, 172, 177, 76, 144, 119, 63,
+ 121, 162, 149, 153, 36, 143, 44, 243, 68, 91, 39, 153, 34, 87, 168,
+ 151, 101, 194, 59, 93, 14, 153, 151, 77, 115, 96, 124, 163, 179, 181,
+ 117, 83, 135, 188, 250, 251, 108, 19, 222, 57, 242, 209, 247, 30, 107,
+ 101, 62, 150, 135, 159, 33, 103, 172, 126, 34, 91, 122, 62, 50, 225,
+ 93, 36, 63, 75, 120, 76, 243, 103, 8, 189, 243, 97, 52, 247, 60,
+ 239, 56, 141, 254, 130, 24, 226, 253, 5, 49, 65, 252, 133, 208, 157,
+ 193, 95, 216, 115, 247, 242, 210, 192, 95, 130, 94, 121, 66, 239, 153,
+ 34, 229, 209, 95, 110, 14, 173, 110, 234, 47, 11, 22, 52, 162, 254,
+ 50, 162, 97, 155, 68, 226, 47, 157, 127, 239, 156, 104, 230, 47, 5,
+ 63, 36, 231, 1, 14, 149, 139, 186, 222, 83, 245, 130, 191, 236, 104,
+ 252, 174, 241, 122, 40, 248, 203, 249, 186, 175, 39, 18, 127, 137, 31,
+ 164, 233, 5, 127, 249, 120, 109, 35, 83, 127, 57, 220, 181, 58, 245,
+ 151, 212, 209, 101, 169, 191, 220, 94, 92, 216, 212, 95, 202, 191, 250,
+ 40, 129, 248, 139, 189, 218, 189, 4, 149, 215, 33, 199, 92, 185, 144,
+ 96, 230, 47, 101, 74, 222, 74, 32, 254, 178, 233, 244, 237, 4, 226,
+ 47, 157, 190, 190, 147, 96, 230, 47, 237, 55, 221, 167, 121, 119, 132,
+ 70, 127, 97, 207, 141, 253, 5, 219, 67, 222, 95, 176, 125, 35, 254,
+ 66, 232, 150, 224, 47, 236, 185, 123, 121, 201, 224, 47, 177, 155, 58,
+ 208, 124, 43, 82, 190, 20, 248, 203, 163, 213, 193, 134, 188, 133, 58,
+ 244, 147, 7, 100, 183, 182, 17, 127, 217, 247, 119, 75, 133, 46, 4,
+ 254, 82, 127, 71, 51, 67, 222, 59, 224, 47, 173, 74, 5, 217, 136,
+ 191, 196, 190, 171, 210, 190, 224, 47, 153, 75, 131, 12, 121, 11, 68,
+ 141, 146, 191, 233, 216, 212, 70, 252, 165, 66, 235, 22, 10, 93, 4,
+ 252, 101, 101, 224, 171, 134, 188, 229, 162, 38, 200, 93, 198, 181, 177,
+ 17, 127, 249, 99, 70, 123, 133, 246, 1, 127, 113, 204, 151, 13, 121,
+ 143, 129, 191, 180, 216, 222, 149, 230, 151, 13, 91, 222, 93, 161, 31,
+ 135, 59, 228, 49, 253, 66, 140, 207, 40, 3, 127, 185, 48, 187, 139,
+ 141, 248, 203, 137, 66, 111, 168, 52, 248, 203, 129, 69, 157, 109, 102,
+ 254, 50, 120, 98, 103, 154, 155, 70, 104, 244, 23, 246, 220, 216, 95,
+ 48, 182, 241, 254, 130, 177, 138, 248, 11, 161, 155, 131, 191, 176, 231,
+ 238, 229, 37, 129, 191, 220, 154, 81, 155, 250, 11, 41, 143, 254, 146,
+ 126, 197, 223, 248, 187, 129, 191, 140, 56, 209, 136, 250, 203, 168, 43,
+ 86, 117, 109, 17, 252, 37, 236, 113, 115, 67, 222, 123, 224, 47, 159,
+ 250, 182, 161, 254, 210, 245, 204, 107, 10, 93, 14, 252, 229, 149, 31,
+ 95, 51, 246, 83, 240, 151, 172, 177, 45, 169, 191, 124, 182, 76, 245,
+ 205, 146, 224, 47, 149, 126, 107, 98, 200, 91, 27, 252, 101, 220, 183,
+ 65, 212, 95, 158, 221, 107, 160, 174, 165, 130, 191, 148, 108, 83, 199,
+ 144, 55, 30, 252, 101, 196, 209, 202, 212, 95, 42, 134, 87, 84, 207,
+ 180, 3, 127, 169, 121, 177, 172, 33, 239, 99, 240, 151, 189, 91, 170,
+ 82, 127, 89, 177, 178, 186, 66, 191, 8, 255, 68, 30, 28, 89, 195,
+ 212, 95, 238, 44, 174, 65, 253, 133, 208, 232, 47, 236, 185, 241, 56,
+ 15, 251, 169, 244, 46, 141, 39, 208, 15, 91, 96, 210, 103, 109, 198,
+ 173, 169, 60, 203, 244, 14, 121, 234, 193, 93, 26, 207, 184, 245, 158,
+ 103, 220, 186, 85, 118, 254, 206, 128, 192, 152, 75, 215, 123, 56, 29,
+ 41, 240, 78, 41, 154, 158, 176, 236, 252, 157, 1, 129, 237, 52, 173,
+ 199, 83, 174, 30, 64, 211, 186, 100, 231, 239, 12, 8, 196, 54, 173,
+ 199, 211, 92, 235, 86, 154, 125, 163, 159, 228, 239, 12, 8, 244, 7,
+ 58, 87, 144, 173, 207, 237, 99, 125, 23, 135, 141, 208, 151, 229, 4,
+ 187, 81, 159, 70, 183, 110, 149, 75, 30, 139, 109, 14, 27, 161, 81,
+ 158, 81, 204, 211, 173, 91, 229, 146, 199, 218, 62, 135, 141, 208, 40,
+ 207, 168, 77, 212, 205, 119, 62, 209, 203, 99, 216, 112, 216, 8, 141,
+ 242, 140, 48, 163, 187, 75, 227, 9, 119, 151, 70, 6, 248, 65, 142,
+ 9, 102, 154, 115, 247, 60, 100, 1, 239, 99, 15, 238, 210, 200, 226,
+ 238, 160, 200, 98, 229, 99, 30, 137, 195, 140, 15, 167, 35, 26, 222,
+ 41, 90, 211, 99, 125, 36, 14, 51, 40, 151, 214, 3, 104, 82, 23,
+ 103, 166, 56, 204, 248, 60, 206, 117, 151, 134, 102, 223, 144, 76, 113,
+ 152, 65, 187, 211, 251, 88, 10, 206, 74, 114, 135, 25, 203, 212, 26,
+ 30, 99, 198, 154, 75, 158, 59, 204, 160, 60, 79, 49, 131, 246, 228,
+ 229, 185, 195, 12, 202, 243, 20, 51, 33, 185, 228, 185, 195, 12, 202,
+ 243, 20, 51, 136, 19, 130, 25, 231, 191, 64, 63, 49, 193, 76, 11,
+ 238, 92, 79, 224, 77, 73, 247, 224, 236, 212, 12, 46, 6, 60, 228,
+ 206, 78, 77, 23, 135, 25, 148, 75, 99, 0, 208, 168, 83, 153, 179,
+ 124, 32, 14, 51, 33, 156, 14, 172, 55, 169, 75, 220, 69, 113, 152,
+ 65, 185, 186, 179, 83, 53, 29, 246, 139, 226, 48, 131, 118, 207, 47,
+ 102, 116, 107, 169, 15, 242, 143, 25, 94, 30, 218, 51, 191, 152, 225,
+ 229, 217, 47, 230, 31, 51, 124, 223, 76, 193, 137, 38, 207, 113, 22,
+ 252, 32, 195, 4, 51, 45, 217, 247, 176, 3, 175, 243, 188, 57, 102,
+ 176, 28, 241, 3, 231, 5, 86, 62, 228, 124, 254, 48, 195, 207, 39,
+ 162, 92, 162, 195, 14, 52, 234, 84, 250, 127, 231, 242, 135, 25, 126,
+ 62, 209, 206, 233, 192, 122, 147, 186, 132, 157, 203, 31, 102, 248, 249,
+ 68, 148, 203, 99, 198, 78, 236, 117, 46, 127, 152, 33, 243, 137, 193,
+ 154, 221, 105, 46, 227, 197, 210, 123, 214, 14, 169, 146, 148, 123, 62,
+ 209, 239, 202, 70, 91, 155, 132, 251, 158, 229, 164, 159, 99, 242, 98,
+ 14, 149, 222, 147, 24, 255, 85, 66, 238, 249, 38, 151, 107, 163, 237,
+ 225, 153, 122, 158, 245, 245, 56, 121, 161, 115, 42, 237, 249, 189, 124,
+ 216, 75, 243, 17, 33, 206, 88, 91, 157, 93, 205, 61, 138, 51, 22,
+ 254, 253, 82, 124, 247, 52, 140, 207, 105, 159, 123, 188, 106, 159, 25,
+ 107, 11, 41, 216, 212, 163, 56, 131, 56, 33, 152, 177, 164, 130, 31,
+ 252, 107, 130, 153, 86, 220, 247, 0, 94, 71, 170, 57, 102, 176, 28,
+ 241, 3, 199, 63, 172, 124, 195, 144, 30, 69, 60, 195, 76, 57, 183,
+ 126, 112, 169, 73, 52, 189, 231, 12, 229, 82, 95, 67, 29, 103, 181,
+ 113, 64, 63, 79, 116, 84, 203, 83, 71, 213, 239, 206, 210, 60, 67,
+ 11, 167, 3, 235, 77, 234, 210, 208, 81, 178, 128, 103, 152, 113, 175,
+ 99, 183, 227, 36, 205, 99, 70, 185, 60, 102, 44, 154, 142, 232, 185,
+ 158, 232, 168, 146, 167, 142, 245, 183, 212, 117, 171, 214, 5, 85, 187,
+ 215, 83, 74, 194, 159, 127, 144, 19, 237, 72, 124, 136, 208, 119, 126,
+ 154, 99, 103, 207, 221, 183, 187, 49, 221, 159, 217, 135, 255, 68, 230,
+ 179, 173, 210, 200, 63, 171, 42, 244, 236, 176, 225, 210, 47, 29, 90,
+ 25, 206, 133, 23, 89, 176, 90, 98, 88, 141, 165, 243, 253, 205, 34,
+ 54, 73, 70, 88, 85, 199, 241, 91, 164, 82, 255, 144, 59, 71, 226,
+ 164, 1, 195, 18, 19, 213, 249, 131, 120, 201, 47, 253, 7, 67, 222,
+ 115, 145, 59, 164, 105, 111, 126, 70, 243, 43, 138, 77, 249, 88, 221,
+ 203, 30, 190, 75, 42, 219, 100, 170, 33, 239, 147, 200, 68, 233, 163,
+ 195, 36, 239, 201, 41, 93, 108, 166, 230, 61, 21, 142, 216, 43, 117,
+ 91, 61, 209, 144, 215, 43, 234, 128, 244, 222, 161, 72, 154, 155, 241,
+ 253, 245, 249, 106, 174, 86, 196, 97, 233, 105, 193, 37, 38, 188, 199,
+ 164, 144, 85, 43, 104, 110, 198, 234, 152, 181, 218, 60, 240, 73, 233,
+ 193, 198, 13, 134, 188, 25, 145, 103, 164, 212, 61, 219, 105, 110, 198,
+ 176, 230, 59, 19, 213, 249, 146, 179, 146, 107, 195, 110, 147, 59, 210,
+ 46, 72, 95, 29, 216, 65, 115, 51, 102, 223, 217, 78, 243, 173, 134,
+ 149, 223, 110, 50, 119, 125, 77, 250, 248, 234, 118, 154, 155, 209, 127,
+ 255, 14, 141, 247, 182, 212, 240, 187, 95, 76, 120, 239, 74, 51, 165,
+ 157, 52, 55, 227, 203, 214, 187, 52, 222, 116, 233, 151, 38, 9, 38,
+ 190, 145, 41, 189, 159, 177, 135, 230, 91, 93, 79, 78, 214, 230, 189,
+ 179, 165, 113, 75, 247, 153, 232, 205, 145, 58, 151, 164, 247, 224, 200,
+ 165, 110, 28, 80, 121, 109, 94, 242, 233, 228, 223, 77, 114, 151, 188,
+ 229, 25, 91, 142, 104, 101, 10, 202, 239, 37, 29, 211, 120, 11, 201,
+ 237, 78, 156, 48, 225, 45, 44, 127, 240, 132, 248, 115, 81, 121, 118,
+ 197, 83, 26, 111, 49, 121, 93, 243, 51, 198, 247, 227, 36, 23, 151,
+ 43, 54, 78, 165, 185, 90, 141, 186, 158, 215, 214, 23, 74, 203, 195,
+ 162, 174, 154, 212, 183, 172, 204, 214, 217, 124, 41, 189, 243, 97, 69,
+ 217, 108, 253, 141, 180, 37, 216, 190, 146, 182, 228, 83, 104, 75, 176,
+ 189, 36, 109, 9, 161, 59, 196, 205, 177, 179, 231, 238, 229, 237, 237,
+ 245, 204, 126, 252, 139, 158, 193, 164, 45, 57, 176, 188, 168, 66, 119,
+ 156, 48, 92, 74, 159, 30, 214, 214, 136, 119, 55, 180, 37, 44, 78,
+ 199, 210, 181, 160, 210, 208, 150, 24, 197, 105, 228, 189, 11, 109, 73,
+ 124, 106, 8, 109, 75, 126, 156, 240, 182, 134, 143, 120, 233, 131, 226,
+ 131, 77, 124, 109, 135, 52, 107, 109, 8, 109, 75, 202, 58, 186, 104,
+ 190, 182, 75, 250, 97, 144, 108, 194, 155, 40, 77, 43, 222, 134, 182,
+ 37, 171, 59, 183, 208, 120, 247, 74, 206, 168, 198, 38, 188, 7, 164,
+ 227, 15, 26, 210, 182, 228, 171, 9, 117, 105, 238, 230, 136, 7, 53,
+ 77, 120, 143, 73, 175, 12, 172, 74, 219, 146, 161, 49, 149, 104, 238,
+ 230, 230, 75, 190, 166, 121, 94, 231, 173, 190, 180, 45, 249, 62, 172,
+ 28, 205, 221, 28, 23, 231, 99, 194, 123, 65, 90, 50, 189, 20, 109,
+ 75, 92, 165, 74, 210, 182, 164, 233, 250, 226, 166, 109, 201, 129, 2,
+ 37, 104, 91, 242, 226, 151, 162, 180, 45, 121, 237, 67, 179, 181, 172,
+ 187, 210, 241, 172, 23, 9, 164, 45, 217, 182, 240, 169, 182, 150, 149,
+ 46, 173, 170, 254, 56, 193, 172, 45, 121, 113, 144, 148, 201, 146, 246,
+ 78, 126, 164, 173, 101, 101, 75, 243, 234, 102, 38, 152, 181, 37, 75,
+ 207, 166, 145, 50, 114, 165, 121, 15, 19, 72, 91, 18, 211, 228, 81,
+ 130, 89, 91, 98, 77, 240, 162, 109, 201, 188, 185, 222, 180, 45, 57,
+ 219, 189, 128, 105, 91, 210, 179, 49, 169, 111, 81, 121, 228, 68, 173,
+ 190, 208, 150, 68, 237, 124, 108, 162, 183, 184, 60, 106, 47, 25, 11,
+ 150, 148, 151, 206, 85, 223, 25, 219, 146, 127, 139, 62, 77, 48, 107,
+ 75, 216, 26, 172, 47, 165, 177, 45, 49, 91, 155, 165, 253, 18, 232,
+ 71, 145, 182, 36, 182, 78, 144, 19, 251, 69, 164, 45, 33, 244, 244,
+ 77, 115, 236, 236, 121, 30, 253, 146, 218, 207, 236, 21, 178, 11, 208,
+ 60, 175, 45, 251, 212, 245, 151, 209, 93, 135, 75, 223, 252, 211, 199,
+ 112, 44, 121, 173, 195, 106, 137, 245, 209, 99, 233, 58, 97, 161, 197,
+ 155, 36, 163, 62, 58, 242, 214, 141, 216, 34, 141, 248, 203, 199, 70,
+ 218, 146, 33, 146, 218, 55, 143, 152, 26, 47, 45, 31, 243, 143, 225,
+ 125, 124, 161, 51, 119, 72, 133, 238, 110, 111, 79, 218, 146, 8, 251,
+ 6, 133, 94, 56, 115, 151, 116, 251, 208, 74, 67, 222, 59, 208, 150,
+ 164, 126, 176, 170, 61, 105, 75, 174, 94, 93, 171, 208, 242, 236, 189,
+ 210, 226, 177, 223, 25, 242, 78, 135, 126, 201, 167, 111, 253, 210, 158,
+ 180, 37, 141, 55, 236, 83, 232, 25, 208, 150, 92, 205, 78, 49, 228,
+ 173, 62, 231, 152, 228, 19, 120, 169, 61, 105, 75, 14, 44, 73, 87,
+ 232, 165, 208, 150, 148, 125, 225, 101, 104, 171, 249, 17, 103, 164, 118,
+ 153, 229, 104, 126, 217, 166, 132, 10, 218, 58, 231, 89, 169, 175, 163,
+ 178, 33, 239, 120, 104, 75, 126, 241, 41, 77, 243, 203, 126, 237, 95,
+ 66, 161, 127, 10, 191, 44, 197, 125, 83, 212, 120, 125, 21, 218, 146,
+ 58, 43, 138, 210, 252, 178, 42, 13, 84, 186, 0, 180, 37, 229, 118,
+ 22, 49, 228, 45, 29, 117, 87, 202, 172, 88, 132, 230, 151, 253, 25,
+ 164, 242, 250, 67, 91, 178, 95, 46, 102, 200, 155, 5, 109, 201, 193,
+ 147, 37, 105, 126, 89, 245, 63, 213, 247, 127, 16, 158, 45, 133, 158,
+ 240, 49, 228, 189, 14, 109, 201, 200, 26, 229, 105, 126, 217, 249, 59,
+ 42, 157, 211, 222, 75, 238, 188, 219, 215, 120, 109, 49, 217, 91, 254,
+ 99, 79, 121, 154, 95, 22, 189, 86, 45, 95, 30, 218, 146, 225, 225,
+ 21, 140, 215, 248, 146, 11, 203, 83, 23, 85, 178, 145, 182, 228, 135,
+ 69, 234, 186, 91, 16, 180, 37, 95, 46, 126, 197, 120, 173, 13, 218,
+ 146, 208, 183, 234, 208, 220, 52, 185, 159, 186, 62, 120, 46, 188, 180,
+ 60, 175, 151, 241, 218, 226, 83, 104, 75, 216, 250, 188, 47, 165, 19,
+ 161, 45, 49, 91, 183, 167, 253, 146, 185, 172, 45, 105, 1, 253, 18,
+ 28, 255, 144, 182, 132, 208, 163, 96, 140, 195, 158, 231, 129, 203, 174,
+ 207, 236, 75, 94, 244, 164, 109, 73, 137, 141, 109, 21, 186, 227, 251,
+ 195, 165, 37, 75, 234, 27, 242, 206, 124, 123, 181, 196, 198, 231, 177,
+ 116, 13, 121, 251, 252, 77, 146, 209, 248, 28, 121, 83, 103, 110, 145,
+ 118, 132, 134, 208, 182, 228, 234, 113, 245, 238, 177, 47, 167, 197, 75,
+ 233, 5, 140, 239, 42, 43, 229, 216, 33, 121, 183, 30, 71, 243, 77,
+ 91, 188, 170, 222, 49, 182, 28, 198, 56, 75, 154, 79, 50, 241, 211,
+ 68, 105, 209, 70, 146, 119, 232, 148, 98, 98, 62, 82, 104, 43, 244,
+ 75, 190, 91, 101, 124, 87, 89, 61, 104, 75, 166, 45, 26, 71, 115,
+ 85, 15, 37, 140, 86, 232, 14, 208, 150, 124, 123, 119, 164, 33, 239,
+ 183, 48, 198, 217, 51, 114, 24, 205, 85, 181, 134, 170, 57, 148, 31,
+ 67, 91, 210, 237, 77, 227, 251, 213, 150, 58, 206, 72, 101, 175, 246,
+ 162, 109, 73, 223, 134, 61, 105, 91, 50, 127, 108, 119, 67, 222, 221,
+ 208, 150, 148, 94, 208, 151, 182, 37, 171, 6, 189, 169, 249, 233, 101,
+ 233, 204, 107, 253, 141, 207, 213, 133, 182, 196, 225, 223, 159, 182, 37,
+ 139, 199, 246, 183, 145, 126, 201, 202, 159, 251, 155, 172, 189, 223, 149,
+ 54, 86, 27, 64, 219, 146, 65, 131, 212, 242, 229, 161, 45, 241, 221,
+ 248, 150, 33, 239, 51, 104, 75, 198, 119, 239, 71, 219, 146, 215, 239,
+ 171, 49, 237, 41, 180, 37, 117, 63, 239, 109, 200, 251, 16, 218, 146,
+ 90, 119, 122, 209, 182, 228, 243, 190, 42, 253, 2, 218, 146, 194, 187,
+ 123, 26, 242, 122, 67, 91, 18, 242, 110, 47, 218, 150, 12, 140, 83,
+ 203, 151, 132, 182, 100, 68, 33, 99, 222, 74, 208, 150, 252, 247, 101,
+ 119, 218, 150, 252, 217, 90, 221, 47, 82, 7, 218, 146, 174, 169, 175,
+ 27, 242, 150, 129, 49, 78, 70, 175, 14, 180, 45, 249, 40, 198, 166,
+ 237, 17, 41, 45, 151, 149, 90, 219, 204, 250, 37, 108, 239, 134, 47,
+ 165, 127, 131, 182, 196, 108, 79, 7, 153, 35, 195, 121, 49, 186, 22,
+ 115, 42, 211, 219, 113, 214, 100, 142, 172, 53, 155, 127, 113, 252, 13,
+ 101, 255, 50, 159, 35, 195, 114, 116, 222, 231, 111, 86, 62, 250, 140,
+ 184, 181, 24, 11, 167, 195, 1, 239, 228, 208, 244, 248, 157, 17, 183,
+ 22, 131, 114, 105, 61, 176, 222, 154, 142, 184, 211, 226, 214, 98, 44,
+ 127, 233, 231, 200, 28, 154, 125, 237, 167, 197, 173, 197, 160, 221, 69,
+ 174, 95, 250, 157, 17, 187, 126, 137, 246, 20, 185, 126, 105, 63, 45,
+ 118, 253, 18, 113, 66, 243, 238, 238, 195, 119, 73, 53, 193, 204, 107,
+ 220, 58, 1, 240, 58, 255, 244, 96, 45, 230, 20, 183, 134, 113, 146,
+ 91, 139, 249, 83, 28, 102, 80, 46, 93, 139, 1, 26, 117, 42, 145,
+ 34, 69, 28, 102, 236, 156, 14, 172, 55, 169, 75, 88, 138, 56, 204,
+ 160, 92, 221, 90, 140, 166, 35, 238, 190, 56, 204, 160, 221, 69, 174,
+ 95, 162, 141, 69, 174, 95, 134, 165, 136, 93, 191, 68, 219, 137, 92,
+ 191, 68, 156, 208, 187, 31, 111, 131, 31, 156, 50, 198, 76, 83, 43,
+ 151, 19, 118, 47, 211, 219, 122, 215, 131, 187, 31, 239, 113, 121, 119,
+ 247, 184, 187, 31, 239, 228, 15, 51, 55, 35, 70, 179, 220, 107, 78,
+ 71, 28, 188, 83, 156, 166, 39, 228, 78, 254, 48, 83, 48, 229, 14,
+ 93, 239, 65, 185, 180, 30, 64, 147, 186, 184, 254, 203, 31, 102, 90,
+ 54, 255, 182, 61, 173, 199, 221, 92, 121, 119, 154, 125, 195, 254, 203,
+ 31, 102, 66, 155, 126, 196, 238, 126, 188, 195, 249, 144, 238, 207, 97,
+ 67, 155, 18, 58, 47, 61, 47, 237, 67, 49, 144, 135, 246, 251, 159,
+ 202, 67, 123, 230, 37, 15, 109, 245, 63, 149, 23, 102, 32, 15, 237,
+ 226, 169, 60, 122, 247, 227, 109, 238, 28, 145, 235, 224, 7, 247, 77,
+ 48, 195, 229, 16, 133, 1, 111, 218, 77, 15, 238, 126, 188, 205, 229,
+ 94, 223, 226, 238, 126, 188, 41, 46, 206, 160, 92, 154, 123, 13, 52,
+ 234, 196, 50, 62, 55, 197, 197, 153, 48, 78, 7, 214, 155, 212, 37,
+ 230, 134, 184, 56, 131, 114, 117, 119, 63, 106, 58, 172, 55, 196, 197,
+ 25, 180, 187, 200, 56, 227, 115, 83, 108, 156, 65, 123, 138, 140, 51,
+ 214, 27, 98, 227, 12, 226, 132, 158, 35, 114, 25, 252, 224, 182, 9,
+ 102, 184, 61, 204, 86, 224, 141, 187, 234, 193, 221, 143, 215, 185, 24,
+ 112, 141, 59, 71, 228, 170, 56, 204, 160, 92, 26, 3, 128, 70, 157,
+ 202, 236, 193, 21, 113, 152, 177, 114, 58, 176, 222, 164, 46, 161, 87,
+ 196, 97, 6, 229, 234, 206, 17, 209, 116, 164, 93, 22, 135, 25, 180,
+ 187, 200, 241, 12, 218, 88, 228, 120, 38, 244, 138, 216, 241, 12, 218,
+ 78, 228, 120, 6, 113, 66, 207, 201, 223, 14, 126, 112, 61, 47, 204,
+ 96, 122, 247, 36, 221, 29, 70, 105, 151, 50, 189, 99, 246, 120, 112,
+ 247, 227, 37, 46, 6, 92, 98, 229, 125, 18, 61, 197, 76, 113, 183,
+ 126, 112, 241, 200, 183, 236, 254, 95, 78, 71, 154, 11, 176, 175, 233,
+ 113, 236, 242, 20, 51, 238, 117, 212, 72, 232, 69, 117, 160, 92, 154,
+ 15, 11, 245, 38, 117, 73, 251, 213, 83, 204, 184, 215, 145, 22, 104,
+ 163, 152, 65, 185, 186, 115, 68, 92, 26, 46, 119, 120, 138, 25, 247,
+ 58, 106, 206, 87, 247, 150, 13, 240, 86, 237, 94, 79, 41, 169, 230,
+ 6, 161, 29, 137, 15, 17, 26, 115, 85, 217, 243, 60, 246, 96, 244,
+ 124, 77, 110, 182, 245, 59, 173, 76, 119, 153, 148, 247, 78, 236, 37,
+ 175, 94, 107, 204, 139, 185, 135, 255, 6, 146, 50, 3, 100, 111, 199,
+ 122, 141, 247, 93, 185, 254, 233, 117, 38, 188, 161, 242, 133, 229, 49,
+ 90, 153, 161, 242, 157, 37, 223, 168, 231, 103, 63, 27, 41, 255, 216,
+ 116, 173, 33, 111, 78, 129, 241, 242, 204, 97, 107, 180, 50, 147, 228,
+ 137, 151, 190, 106, 167, 174, 35, 78, 150, 39, 56, 190, 106, 103, 188,
+ 142, 56, 69, 94, 113, 118, 149, 86, 102, 154, 220, 232, 232, 42, 141,
+ 119, 186, 188, 63, 113, 149, 9, 239, 12, 121, 247, 8, 34, 127, 150,
+ 156, 241, 190, 74, 99, 174, 106, 106, 43, 99, 189, 152, 123, 88, 188,
+ 225, 74, 173, 204, 199, 114, 249, 186, 43, 53, 189, 243, 229, 74, 181,
+ 87, 154, 232, 253, 68, 62, 148, 78, 202, 44, 148, 155, 13, 39, 239,
+ 188, 72, 94, 243, 143, 89, 125, 23, 203, 245, 45, 223, 104, 101, 150,
+ 80, 250, 252, 244, 165, 220, 243, 188, 99, 60, 250, 26, 226, 143, 247,
+ 53, 196, 19, 241, 53, 66, 163, 175, 177, 231, 121, 251, 218, 241, 211,
+ 125, 169, 175, 145, 242, 232, 107, 131, 110, 247, 52, 245, 53, 235, 244,
+ 238, 212, 215, 42, 87, 235, 74, 125, 205, 146, 248, 186, 169, 175, 157,
+ 121, 210, 129, 250, 90, 253, 2, 18, 245, 181, 101, 101, 218, 153, 250,
+ 90, 215, 203, 173, 169, 175, 213, 28, 222, 156, 250, 154, 111, 145, 102,
+ 166, 190, 246, 188, 105, 19, 234, 107, 203, 150, 52, 166, 190, 214, 240,
+ 191, 70, 166, 190, 118, 119, 112, 99, 234, 107, 199, 107, 88, 169, 175,
+ 245, 41, 253, 170, 169, 175, 157, 146, 122, 82, 95, 251, 171, 106, 79,
+ 234, 107, 3, 138, 244, 52, 245, 181, 234, 150, 14, 212, 215, 158, 92,
+ 104, 71, 125, 237, 239, 221, 173, 77, 125, 109, 102, 251, 102, 212, 215,
+ 8, 141, 190, 198, 158, 27, 251, 26, 182, 195, 188, 175, 97, 187, 74,
+ 124, 141, 208, 232, 107, 236, 121, 222, 190, 246, 90, 57, 27, 205, 121,
+ 36, 229, 209, 215, 42, 52, 53, 230, 69, 95, 251, 118, 128, 141, 230,
+ 60, 254, 213, 202, 70, 115, 30, 139, 85, 48, 227, 13, 149, 71, 174,
+ 104, 79, 115, 30, 219, 13, 104, 111, 35, 190, 246, 118, 161, 246, 54,
+ 51, 95, 203, 153, 210, 142, 230, 45, 206, 58, 167, 210, 232, 107, 107,
+ 50, 140, 215, 22, 45, 201, 83, 228, 31, 187, 18, 249, 211, 228, 158,
+ 27, 84, 218, 27, 124, 45, 221, 203, 248, 157, 189, 146, 103, 200, 195,
+ 234, 216, 105, 206, 99, 153, 37, 54, 109, 141, 202, 33, 175, 107, 221,
+ 206, 100, 205, 122, 142, 188, 243, 68, 19, 154, 243, 248, 196, 170, 230,
+ 135, 150, 5, 95, 91, 61, 200, 106, 200, 91, 60, 249, 19, 185, 120,
+ 253, 86, 54, 226, 107, 91, 195, 213, 92, 209, 226, 224, 107, 43, 206,
+ 180, 55, 121, 231, 197, 114, 131, 83, 175, 211, 124, 73, 66, 163, 175,
+ 177, 231, 198, 190, 134, 241, 152, 247, 53, 140, 175, 196, 215, 8, 141,
+ 190, 198, 158, 231, 237, 107, 43, 86, 55, 164, 190, 70, 202, 163, 175,
+ 21, 153, 211, 208, 212, 215, 42, 191, 219, 144, 250, 218, 250, 143, 27,
+ 82, 95, 11, 138, 111, 104, 234, 107, 17, 93, 253, 89, 62, 246, 74,
+ 127, 234, 107, 11, 159, 251, 155, 250, 90, 181, 31, 2, 168, 175, 77,
+ 234, 16, 64, 125, 173, 120, 64, 128, 169, 175, 21, 62, 238, 79, 125,
+ 173, 205, 40, 127, 234, 107, 227, 10, 250, 155, 250, 218, 210, 63, 26,
+ 80, 95, 235, 57, 80, 173, 99, 69, 240, 181, 208, 95, 140, 245, 222,
+ 6, 95, 155, 181, 160, 53, 245, 53, 223, 94, 42, 93, 14, 124, 237,
+ 98, 83, 227, 181, 54, 31, 240, 181, 198, 63, 55, 163, 190, 246, 239,
+ 127, 141, 52, 63, 93, 36, 151, 169, 239, 111, 178, 182, 184, 88, 158,
+ 50, 132, 229, 230, 18, 26, 125, 141, 61, 55, 30, 215, 98, 191, 156,
+ 244, 209, 99, 78, 64, 191, 243, 178, 89, 31, 157, 221, 153, 24, 10,
+ 188, 174, 120, 243, 62, 58, 150, 163, 231, 35, 109, 99, 229, 195, 226,
+ 243, 55, 174, 197, 126, 2, 61, 31, 105, 27, 119, 62, 18, 208, 168,
+ 83, 41, 20, 159, 191, 113, 45, 198, 7, 90, 15, 78, 7, 214, 155,
+ 212, 37, 250, 231, 252, 141, 107, 177, 93, 160, 245, 136, 207, 117, 47,
+ 143, 166, 195, 239, 231, 252, 141, 107, 209, 31, 232, 124, 98, 188, 62,
+ 87, 149, 245, 183, 28, 54, 66, 63, 233, 144, 96, 55, 234, 135, 233,
+ 242, 43, 114, 201, 99, 49, 213, 97, 35, 52, 202, 51, 138, 181, 186,
+ 92, 218, 159, 245, 242, 88, 187, 233, 176, 17, 26, 229, 25, 181, 167,
+ 186, 117, 196, 92, 242, 24, 54, 28, 54, 66, 163, 60, 35, 204, 240,
+ 227, 90, 196, 9, 61, 235, 239, 8, 248, 193, 118, 51, 204, 176, 59,
+ 19, 253, 128, 55, 230, 152, 57, 102, 176, 28, 29, 15, 30, 231, 206,
+ 250, 59, 38, 14, 51, 40, 151, 158, 143, 4, 52, 234, 84, 214, 53,
+ 142, 138, 195, 140, 31, 167, 3, 235, 77, 234, 18, 114, 84, 28, 102,
+ 80, 174, 238, 158, 81, 77, 135, 235, 136, 56, 204, 160, 221, 233, 220,
+ 200, 11, 103, 123, 119, 152, 177, 76, 253, 215, 230, 41, 102, 208, 198,
+ 188, 60, 119, 152, 65, 121, 158, 98, 38, 132, 151, 247, 212, 217, 222,
+ 29, 102, 28, 147, 255, 181, 121, 138, 25, 180, 29, 149, 247, 196, 217,
+ 222, 29, 102, 44, 32, 207, 83, 204, 32, 78, 232, 89, 127, 191, 131,
+ 31, 156, 48, 195, 12, 187, 51, 209, 117, 24, 218, 243, 63, 204, 49,
+ 131, 229, 104, 12, 56, 204, 157, 245, 119, 72, 28, 102, 66, 57, 29,
+ 46, 120, 39, 151, 166, 199, 113, 72, 28, 102, 80, 46, 173, 7, 208,
+ 164, 46, 62, 135, 196, 97, 38, 244, 143, 92, 103, 253, 105, 246, 141,
+ 249, 93, 28, 102, 208, 238, 249, 197, 12, 63, 167, 239, 56, 148, 127,
+ 204, 232, 214, 48, 14, 229, 31, 51, 186, 53, 140, 223, 243, 143, 25,
+ 190, 111, 134, 56, 161, 243, 167, 123, 193, 15, 142, 152, 97, 134, 221,
+ 153, 24, 115, 16, 218, 243, 3, 30, 156, 245, 119, 144, 139, 1, 7,
+ 185, 123, 70, 247, 231, 15, 51, 252, 252, 169, 31, 167, 35, 6, 222,
+ 41, 70, 211, 99, 223, 159, 63, 204, 240, 243, 167, 40, 151, 214, 3,
+ 104, 82, 151, 148, 125, 249, 195, 12, 63, 127, 234, 119, 32, 215, 89,
+ 127, 154, 125, 67, 247, 229, 15, 51, 100, 254, 52, 88, 179, 59, 241,
+ 33, 151, 179, 244, 158, 11, 15, 55, 188, 52, 127, 234, 227, 218, 104,
+ 235, 28, 240, 173, 71, 113, 193, 158, 75, 158, 213, 58, 224, 165, 57,
+ 50, 148, 215, 179, 68, 79, 143, 228, 161, 61, 169, 188, 51, 165, 247,
+ 76, 170, 213, 241, 165, 121, 16, 235, 229, 141, 182, 98, 141, 219, 123,
+ 20, 103, 66, 57, 121, 150, 11, 165, 247, 140, 247, 169, 251, 210, 88,
+ 215, 5, 242, 126, 24, 237, 239, 81, 156, 65, 156, 208, 190, 153, 19,
+ 252, 224, 119, 51, 204, 180, 98, 125, 109, 224, 117, 57, 61, 24, 207,
+ 236, 229, 98, 64, 50, 135, 153, 237, 111, 228, 43, 55, 119, 67, 115,
+ 7, 187, 103, 52, 153, 139, 1, 64, 163, 78, 44, 83, 249, 183, 55,
+ 242, 149, 155, 59, 171, 111, 122, 27, 90, 15, 78, 7, 214, 155, 212,
+ 37, 174, 69, 191, 34, 158, 97, 198, 189, 142, 7, 95, 165, 208, 220,
+ 92, 148, 171, 27, 207, 104, 58, 42, 191, 230, 137, 142, 188, 115, 115,
+ 235, 220, 102, 185, 185, 104, 119, 178, 111, 125, 140, 127, 144, 19, 237,
+ 72, 124, 136, 208, 13, 227, 230, 216, 217, 115, 247, 237, 238, 245, 158,
+ 207, 236, 163, 250, 44, 210, 112, 96, 149, 252, 71, 196, 42, 244, 43,
+ 19, 134, 75, 253, 3, 14, 25, 198, 148, 39, 11, 86, 75, 12, 171,
+ 177, 116, 125, 195, 43, 98, 147, 100, 132, 85, 139, 150, 155, 187, 241,
+ 147, 245, 90, 153, 56, 201, 49, 120, 189, 118, 103, 103, 188, 244, 118,
+ 240, 122, 67, 222, 130, 81, 59, 164, 6, 161, 223, 107, 101, 118, 74,
+ 227, 178, 212, 88, 90, 46, 98, 151, 52, 55, 218, 120, 14, 190, 100,
+ 84, 162, 20, 252, 39, 169, 175, 83, 170, 58, 106, 150, 66, 151, 136,
+ 216, 43, 37, 53, 30, 100, 200, 123, 55, 242, 128, 244, 251, 169, 102,
+ 244, 126, 211, 33, 213, 171, 41, 244, 131, 240, 195, 82, 167, 225, 5,
+ 140, 231, 219, 35, 143, 73, 207, 236, 46, 45, 31, 41, 69, 250, 233,
+ 120, 106, 176, 90, 223, 147, 210, 236, 247, 254, 52, 204, 83, 194, 251,
+ 77, 99, 122, 220, 209, 202, 164, 74, 37, 94, 188, 80, 232, 130, 17,
+ 103, 165, 158, 169, 197, 12, 245, 122, 71, 93, 144, 122, 44, 173, 76,
+ 239, 55, 109, 211, 161, 65, 59, 149, 247, 178, 212, 229, 113, 75, 67,
+ 222, 167, 145, 215, 164, 202, 75, 122, 208, 251, 77, 39, 253, 248, 174,
+ 66, 63, 15, 191, 45, 109, 56, 52, 202, 144, 55, 59, 242, 174, 212,
+ 220, 54, 141, 222, 111, 218, 247, 105, 184, 118, 175, 106, 186, 180, 237,
+ 92, 164, 137, 111, 100, 74, 33, 187, 29, 90, 153, 44, 233, 122, 249,
+ 72, 109, 190, 61, 91, 154, 53, 198, 140, 55, 71, 106, 84, 51, 138,
+ 148, 145, 103, 204, 136, 210, 230, 204, 189, 228, 223, 207, 68, 153, 204,
+ 153, 123, 203, 62, 79, 72, 153, 130, 114, 177, 97, 115, 52, 222, 66,
+ 114, 129, 63, 231, 24, 223, 65, 155, 92, 88, 94, 244, 23, 41, 83,
+ 84, 254, 176, 228, 199, 234, 59, 219, 138, 201, 221, 228, 79, 76, 244,
+ 22, 151, 11, 93, 248, 84, 43, 83, 82, 94, 21, 242, 153, 134, 163,
+ 210, 114, 210, 171, 95, 154, 212, 183, 172, 204, 214, 21, 125, 41, 141,
+ 249, 116, 102, 235, 141, 164, 45, 193, 246, 149, 180, 37, 227, 160, 45,
+ 193, 246, 146, 180, 37, 132, 182, 66, 91, 194, 158, 187, 151, 87, 165,
+ 215, 51, 123, 175, 13, 163, 105, 91, 50, 45, 64, 189, 11, 248, 85,
+ 104, 75, 134, 118, 93, 107, 218, 150, 176, 56, 29, 75, 215, 175, 176,
+ 45, 49, 138, 211, 164, 45, 249, 75, 238, 69, 219, 146, 35, 187, 180,
+ 181, 44, 104, 75, 156, 205, 66, 76, 238, 14, 222, 33, 149, 217, 223,
+ 151, 182, 37, 191, 84, 82, 121, 139, 64, 91, 210, 103, 116, 87, 67,
+ 222, 98, 208, 150, 92, 94, 101, 163, 109, 201, 133, 77, 234, 58, 82,
+ 41, 104, 75, 218, 236, 174, 102, 200, 155, 14, 109, 73, 151, 198, 55,
+ 131, 73, 91, 178, 222, 251, 160, 66, 103, 65, 91, 210, 48, 245, 91,
+ 195, 246, 0, 243, 252, 111, 102, 174, 161, 109, 201, 205, 143, 230, 40,
+ 116, 97, 104, 75, 250, 92, 236, 107, 200, 251, 56, 242, 140, 148, 253,
+ 243, 218, 182, 164, 45, 233, 52, 231, 23, 133, 46, 15, 109, 201, 157,
+ 126, 199, 13, 99, 197, 147, 200, 11, 82, 192, 189, 185, 193, 164, 45,
+ 185, 228, 245, 131, 122, 172, 92, 248, 101, 233, 156, 239, 49, 67, 189,
+ 89, 120, 95, 91, 208, 189, 96, 210, 150, 196, 84, 206, 86, 105, 204,
+ 167, 243, 46, 96, 242, 125, 239, 74, 25, 201, 207, 130, 73, 91, 50,
+ 127, 177, 202, 139, 121, 254, 85, 251, 103, 25, 234, 125, 1, 109, 73,
+ 235, 110, 15, 130, 73, 91, 210, 219, 245, 72, 107, 119, 179, 165, 113,
+ 147, 159, 5, 155, 181, 37, 251, 211, 139, 210, 182, 228, 148, 179, 52,
+ 109, 75, 46, 45, 241, 53, 109, 75, 234, 204, 170, 74, 219, 146, 200,
+ 106, 53, 104, 91, 242, 239, 174, 90, 166, 109, 73, 163, 243, 181, 105,
+ 91, 210, 108, 87, 3, 141, 183, 152, 220, 230, 203, 32, 211, 182, 100,
+ 119, 242, 171, 180, 45, 137, 255, 43, 152, 182, 37, 171, 44, 175, 155,
+ 182, 37, 108, 221, 216, 151, 210, 216, 150, 152, 173, 39, 211, 126, 9,
+ 244, 163, 104, 91, 82, 43, 200, 137, 253, 34, 210, 150, 16, 58, 251,
+ 135, 57, 118, 246, 220, 189, 188, 229, 85, 159, 217, 83, 215, 22, 167,
+ 249, 116, 111, 157, 85, 207, 16, 61, 60, 116, 184, 116, 178, 150, 113,
+ 110, 110, 111, 104, 75, 88, 31, 61, 150, 174, 79, 214, 129, 182, 196,
+ 168, 143, 174, 174, 107, 108, 145, 58, 124, 222, 134, 230, 211, 181, 169,
+ 168, 158, 141, 186, 0, 218, 146, 59, 171, 140, 207, 198, 13, 158, 183,
+ 67, 250, 127, 180, 93, 7, 96, 83, 213, 215, 191, 73, 10, 5, 25,
+ 22, 68, 134, 50, 202, 134, 50, 236, 96, 183, 205, 107, 203, 222, 5,
+ 10, 20, 16, 218, 180, 73, 219, 208, 54, 9, 73, 186, 24, 109, 5,
+ 100, 201, 222, 178, 172, 34, 75, 65, 202, 80, 144, 182, 73, 4, 65,
+ 28, 104, 21, 197, 173, 117, 15, 80, 64, 101, 202, 248, 126, 231, 190,
+ 151, 151, 87, 90, 192, 127, 202, 39, 158, 247, 206, 189, 239, 222, 223,
+ 29, 231, 220, 115, 206, 125, 35, 29, 254, 122, 31, 249, 123, 186, 17,
+ 11, 196, 103, 28, 123, 230, 30, 137, 92, 217, 227, 222, 207, 83, 246,
+ 228, 151, 68, 254, 56, 180, 190, 252, 61, 93, 181, 29, 62, 156, 159,
+ 63, 227, 104, 228, 219, 93, 254, 188, 231, 247, 181, 219, 242, 143, 71,
+ 118, 218, 125, 90, 254, 54, 183, 223, 23, 14, 206, 175, 157, 249, 78,
+ 100, 78, 139, 151, 238, 89, 215, 153, 123, 42, 178, 235, 147, 75, 228,
+ 111, 115, 127, 253, 105, 129, 86, 28, 239, 71, 145, 51, 236, 115, 239,
+ 89, 247, 16, 226, 146, 226, 186, 107, 181, 110, 91, 210, 98, 206, 11,
+ 156, 255, 3, 182, 228, 224, 237, 87, 238, 89, 247, 2, 226, 146, 209,
+ 139, 223, 208, 186, 109, 73, 75, 149, 216, 127, 29, 226, 146, 174, 121,
+ 63, 222, 179, 110, 108, 222, 79, 145, 51, 252, 85, 242, 247, 116, 23,
+ 198, 87, 231, 252, 161, 153, 191, 71, 118, 157, 95, 235, 158, 243, 252,
+ 14, 108, 201, 190, 149, 53, 229, 239, 233, 178, 54, 139, 58, 86, 15,
+ 182, 164, 203, 206, 123, 215, 125, 104, 246, 165, 72, 221, 222, 58, 242,
+ 247, 116, 117, 103, 60, 44, 126, 243, 13, 91, 114, 124, 192, 189, 127,
+ 143, 246, 91, 216, 18, 125, 138, 252, 13, 110, 212, 147, 49, 226, 55,
+ 181, 55, 180, 170, 168, 254, 17, 13, 239, 251, 61, 157, 254, 90, 3,
+ 249, 123, 186, 174, 39, 164, 111, 160, 97, 75, 124, 87, 221, 187, 110,
+ 27, 216, 18, 231, 134, 198, 242, 247, 116, 23, 183, 61, 206, 249, 39,
+ 96, 75, 206, 239, 187, 247, 61, 153, 27, 176, 37, 27, 95, 106, 227,
+ 249, 187, 145, 7, 197, 189, 233, 153, 89, 117, 163, 118, 159, 12, 188,
+ 239, 183, 185, 158, 247, 2, 26, 200, 60, 125, 155, 123, 191, 247, 5,
+ 228, 184, 164, 183, 199, 150, 44, 233, 208, 217, 69, 251, 31, 183, 45,
+ 113, 243, 189, 246, 206, 137, 240, 228, 87, 142, 247, 225, 192, 27, 17,
+ 139, 26, 14, 149, 109, 201, 141, 111, 196, 53, 186, 214, 148, 20, 249,
+ 122, 192, 189, 159, 55, 54, 134, 45, 241, 236, 207, 119, 202, 207, 159,
+ 187, 194, 150, 220, 107, 127, 238, 182, 37, 221, 236, 93, 100, 91, 178,
+ 166, 187, 248, 108, 62, 6, 182, 164, 213, 149, 123, 207, 223, 19, 115,
+ 95, 141, 108, 241, 240, 19, 178, 45, 177, 159, 21, 127, 127, 249, 218,
+ 83, 71, 34, 223, 253, 236, 222, 191, 43, 190, 43, 175, 36, 242, 229,
+ 95, 163, 101, 91, 178, 180, 233, 68, 206, 111, 134, 45, 169, 43, 36,
+ 222, 179, 110, 45, 196, 37, 246, 243, 41, 242, 183, 185, 250, 254, 233,
+ 156, 95, 128, 184, 228, 139, 245, 247, 254, 174, 119, 29, 246, 56, 199,
+ 143, 102, 200, 223, 230, 198, 46, 201, 20, 127, 219, 26, 182, 228, 253,
+ 241, 89, 247, 172, 219, 28, 182, 164, 217, 71, 118, 249, 219, 220, 129,
+ 210, 247, 196, 97, 176, 37, 173, 76, 150, 123, 214, 157, 10, 91, 18,
+ 215, 38, 93, 254, 54, 247, 233, 127, 196, 254, 79, 132, 45, 73, 56,
+ 166, 191, 103, 93, 1, 113, 73, 217, 208, 39, 101, 91, 114, 121, 252,
+ 4, 206, 111, 192, 30, 39, 197, 112, 239, 239, 107, 207, 195, 150, 20,
+ 133, 142, 151, 109, 9, 203, 27, 39, 253, 13, 218, 191, 34, 7, 30,
+ 29, 123, 159, 239, 122, 47, 69, 126, 49, 203, 243, 109, 174, 35, 114,
+ 140, 108, 75, 182, 84, 27, 125, 159, 118, 111, 70, 46, 125, 211, 243,
+ 109, 174, 230, 49, 145, 191, 5, 91, 146, 107, 30, 113, 159, 103, 254,
+ 234, 40, 123, 140, 231, 219, 220, 126, 71, 60, 223, 230, 214, 241, 191,
+ 119, 221, 198, 176, 37, 166, 215, 61, 223, 230, 126, 48, 72, 252, 54,
+ 183, 45, 108, 201, 161, 79, 239, 125, 191, 184, 246, 27, 15, 69, 109,
+ 174, 235, 249, 54, 247, 234, 104, 209, 6, 92, 131, 45, 201, 250, 178,
+ 167, 112, 191, 184, 196, 243, 222, 71, 3, 153, 63, 2, 91, 114, 191,
+ 247, 65, 228, 103, 49, 46, 197, 125, 229, 151, 47, 169, 203, 142, 222,
+ 239, 30, 153, 231, 111, 98, 22, 236, 189, 164, 246, 127, 229, 63, 220,
+ 87, 222, 171, 184, 31, 187, 87, 113, 143, 108, 207, 131, 123, 22, 227,
+ 175, 104, 163, 0, 125, 42, 144, 218, 137, 216, 243, 224, 158, 197, 16,
+ 174, 60, 14, 240, 238, 177, 148, 238, 126, 112, 207, 98, 252, 95, 185,
+ 227, 190, 178, 52, 191, 241, 187, 31, 220, 179, 24, 154, 247, 7, 249,
+ 252, 50, 98, 207, 131, 125, 126, 73, 243, 249, 32, 159, 95, 198, 239,
+ 126, 176, 207, 47, 105, 157, 200, 239, 201, 236, 184, 164, 142, 119, 221,
+ 111, 205, 120, 254, 38, 102, 60, 173, 177, 93, 255, 225, 190, 242, 203,
+ 138, 251, 177, 47, 41, 222, 147, 217, 245, 0, 223, 147, 121, 73, 113,
+ 95, 25, 60, 181, 201, 11, 237, 122, 128, 239, 201, 40, 218, 160, 113,
+ 187, 199, 178, 124, 231, 3, 124, 79, 102, 215, 29, 247, 149, 165, 54,
+ 252, 119, 62, 192, 247, 100, 118, 61, 216, 231, 151, 108, 215, 131, 125,
+ 126, 73, 243, 249, 32, 159, 95, 250, 239, 124, 176, 207, 47, 105, 157,
+ 200, 207, 98, 182, 66, 15, 94, 190, 207, 154, 81, 252, 77, 76, 127,
+ 212, 45, 216, 246, 31, 222, 147, 217, 161, 240, 1, 219, 21, 239, 201,
+ 108, 171, 218, 154, 169, 187, 245, 5, 143, 15, 216, 174, 240, 1, 224,
+ 169, 77, 30, 77, 190, 88, 181, 53, 115, 230, 141, 30, 30, 95, 166,
+ 104, 131, 198, 237, 30, 75, 244, 139, 85, 91, 51, 175, 124, 50, 212,
+ 243, 158, 204, 182, 59, 222, 147, 145, 218, 40, 219, 90, 181, 53, 115,
+ 179, 105, 19, 207, 123, 50, 219, 238, 254, 173, 42, 205, 169, 155, 191,
+ 91, 59, 21, 222, 147, 121, 241, 238, 120, 52, 127, 255, 43, 94, 244,
+ 61, 240, 104, 174, 254, 87, 60, 154, 187, 187, 225, 209, 188, 252, 87,
+ 60, 57, 54, 219, 170, 136, 205, 54, 65, 15, 118, 220, 111, 205, 40,
+ 254, 38, 230, 11, 208, 205, 231, 254, 195, 123, 50, 47, 40, 124, 192,
+ 11, 138, 216, 108, 203, 3, 124, 79, 70, 209, 70, 1, 250, 84, 38,
+ 181, 19, 177, 229, 1, 198, 102, 207, 41, 214, 37, 120, 247, 88, 74,
+ 55, 63, 192, 216, 236, 185, 59, 98, 51, 105, 126, 227, 55, 63, 192,
+ 216, 108, 203, 131, 245, 51, 17, 91, 30, 172, 159, 161, 249, 124, 144,
+ 126, 38, 126, 243, 131, 245, 51, 180, 78, 228, 216, 108, 61, 244, 96,
+ 235, 253, 214, 140, 226, 29, 102, 212, 45, 219, 240, 31, 98, 179, 77,
+ 138, 152, 102, 163, 34, 54, 219, 240, 0, 99, 179, 141, 138, 117, 9,
+ 158, 218, 228, 133, 54, 60, 192, 216, 76, 209, 6, 141, 219, 61, 150,
+ 229, 207, 62, 192, 216, 108, 195, 29, 177, 153, 212, 134, 255, 179, 15,
+ 48, 54, 219, 240, 96, 247, 51, 108, 195, 131, 221, 207, 208, 124, 62,
+ 200, 253, 140, 255, 179, 15, 118, 63, 67, 235, 68, 254, 59, 178, 107,
+ 160, 7, 155, 148, 107, 102, 100, 194, 96, 139, 89, 252, 163, 66, 229,
+ 48, 164, 184, 1, 117, 253, 215, 93, 82, 135, 132, 236, 136, 60, 245,
+ 94, 97, 228, 160, 200, 22, 111, 164, 188, 59, 61, 114, 100, 212, 29,
+ 177, 217, 122, 133, 15, 88, 167, 240, 51, 107, 43, 211, 131, 157, 145,
+ 116, 95, 16, 227, 137, 8, 9, 153, 19, 49, 50, 170, 206, 93, 245,
+ 128, 202, 200, 62, 96, 157, 194, 7, 128, 167, 54, 185, 159, 249, 79,
+ 109, 212, 253, 79, 109, 248, 175, 187, 195, 7, 72, 99, 41, 93, 243,
+ 95, 218, 120, 248, 190, 109, 132, 73, 115, 82, 121, 28, 177, 147, 99,
+ 121, 120, 69, 237, 218, 140, 245, 97, 3, 65, 189, 42, 238, 207, 31,
+ 48, 30, 141, 245, 65, 224, 201, 127, 19, 110, 141, 226, 239, 91, 173,
+ 70, 156, 179, 190, 50, 253, 235, 86, 169, 254, 185, 255, 59, 245, 94,
+ 154, 235, 212, 123, 173, 162, 94, 25, 168, 115, 92, 238, 176, 73, 112,
+ 235, 159, 252, 247, 128, 86, 43, 222, 57, 94, 117, 73, 29, 189, 166,
+ 178, 54, 186, 87, 218, 70, 52, 234, 18, 133, 132, 108, 140, 76, 74,
+ 122, 44, 106, 214, 230, 199, 93, 205, 110, 132, 71, 220, 169, 227, 84,
+ 166, 99, 37, 125, 43, 88, 117, 55, 221, 104, 16, 21, 255, 252, 77,
+ 103, 244, 19, 45, 129, 165, 230, 143, 56, 169, 238, 157, 127, 168, 128,
+ 174, 83, 27, 217, 18, 86, 91, 94, 146, 177, 17, 193, 214, 72, 186,
+ 230, 198, 115, 243, 61, 90, 149, 42, 242, 105, 238, 77, 152, 247, 116,
+ 118, 4, 36, 63, 239, 249, 250, 118, 36, 181, 237, 190, 119, 232, 230,
+ 211, 108, 157, 162, 60, 249, 140, 141, 81, 53, 97, 31, 131, 242, 107,
+ 215, 171, 248, 247, 167, 87, 41, 126, 7, 131, 93, 86, 211, 28, 87,
+ 156, 211, 30, 149, 206, 105, 193, 74, 200, 121, 197, 37, 245, 245, 219,
+ 125, 143, 222, 186, 221, 176, 111, 243, 211, 239, 149, 140, 57, 181, 88,
+ 184, 115, 78, 169, 156, 188, 166, 87, 42, 236, 198, 242, 138, 115, 26,
+ 15, 251, 167, 102, 239, 68, 141, 238, 189, 108, 63, 217, 194, 145, 81,
+ 143, 242, 217, 84, 87, 50, 167, 116, 93, 94, 211, 138, 54, 168, 79,
+ 5, 82, 59, 5, 145, 151, 43, 180, 113, 245, 229, 233, 111, 196, 140,
+ 173, 222, 247, 135, 207, 91, 29, 178, 241, 54, 26, 210, 253, 226, 74,
+ 219, 232, 168, 90, 32, 255, 22, 18, 225, 150, 219, 111, 73, 109, 228,
+ 71, 84, 108, 35, 122, 172, 234, 232, 164, 177, 103, 163, 14, 127, 192,
+ 14, 69, 241, 54, 26, 221, 181, 141, 175, 46, 205, 231, 109, 28, 148,
+ 230, 164, 173, 84, 38, 111, 253, 51, 111, 184, 247, 26, 241, 252, 44,
+ 242, 154, 77, 115, 35, 149, 123, 144, 41, 208, 137, 197, 160, 253, 10,
+ 221, 152, 184, 167, 78, 212, 168, 222, 203, 130, 121, 121, 54, 44, 202,
+ 93, 118, 92, 199, 167, 165, 185, 149, 246, 24, 172, 9, 243, 133, 110,
+ 116, 1, 185, 117, 67, 243, 249, 75, 81, 110, 124, 146, 133, 155, 111,
+ 253, 243, 159, 81, 202, 118, 39, 169, 210, 217, 108, 208, 94, 85, 122,
+ 185, 152, 240, 130, 52, 239, 109, 249, 136, 193, 103, 213, 56, 170, 156,
+ 123, 55, 255, 217, 147, 175, 151, 251, 157, 141, 238, 232, 75, 2, 104,
+ 33, 243, 244, 165, 113, 245, 181, 145, 54, 169, 205, 234, 227, 106, 202,
+ 237, 23, 239, 24, 24, 245, 216, 109, 207, 179, 177, 67, 24, 251, 55,
+ 32, 31, 69, 95, 78, 61, 181, 48, 42, 229, 211, 86, 61, 249, 202,
+ 122, 105, 167, 60, 7, 55, 79, 191, 21, 69, 178, 119, 167, 131, 49,
+ 246, 88, 80, 158, 98, 14, 118, 205, 249, 67, 110, 139, 116, 197, 205,
+ 27, 78, 54, 238, 171, 156, 131, 61, 104, 239, 99, 80, 126, 237, 205,
+ 154, 59, 231, 128, 244, 194, 61, 7, 43, 90, 14, 61, 234, 174, 71,
+ 186, 225, 230, 183, 213, 157, 247, 134, 18, 47, 191, 118, 38, 95, 231,
+ 241, 10, 89, 142, 204, 175, 22, 65, 122, 196, 159, 251, 140, 93, 34,
+ 219, 228, 141, 55, 124, 162, 122, 189, 207, 122, 186, 211, 75, 49, 111,
+ 175, 130, 190, 84, 204, 95, 113, 108, 116, 212, 12, 105, 158, 198, 142,
+ 157, 47, 143, 233, 229, 220, 237, 81, 81, 138, 118, 107, 98, 12, 129,
+ 160, 113, 138, 249, 155, 216, 245, 61, 121, 206, 72, 151, 221, 188, 179,
+ 89, 141, 190, 74, 185, 205, 197, 188, 189, 12, 250, 76, 49, 127, 242,
+ 111, 134, 192, 166, 200, 126, 225, 201, 203, 106, 255, 85, 149, 217, 151,
+ 94, 229, 214, 131, 143, 219, 190, 196, 93, 86, 23, 76, 185, 124, 223,
+ 184, 132, 202, 201, 246, 37, 206, 179, 22, 3, 167, 92, 126, 96, 113,
+ 137, 191, 162, 13, 234, 83, 129, 212, 142, 107, 242, 229, 7, 22, 151,
+ 16, 110, 57, 251, 34, 181, 17, 253, 159, 218, 248, 111, 113, 9, 205,
+ 137, 55, 126, 191, 51, 187, 8, 218, 87, 241, 126, 206, 228, 7, 139,
+ 23, 253, 128, 240, 228, 152, 225, 73, 143, 254, 21, 78, 188, 172, 38,
+ 125, 172, 168, 127, 189, 43, 245, 111, 101, 147, 46, 171, 137, 244, 97,
+ 31, 189, 81, 248, 193, 180, 190, 47, 233, 222, 61, 90, 250, 217, 236,
+ 10, 49, 3, 149, 169, 44, 102, 8, 156, 84, 153, 220, 104, 205, 13,
+ 193, 250, 241, 59, 70, 169, 145, 81, 53, 165, 152, 65, 197, 42, 123,
+ 129, 218, 29, 51, 16, 150, 59, 102, 248, 117, 220, 202, 163, 31, 60,
+ 19, 19, 117, 231, 189, 168, 231, 179, 114, 163, 108, 150, 144, 163, 158,
+ 121, 121, 218, 167, 11, 203, 128, 37, 25, 236, 121, 206, 153, 80, 171,
+ 239, 91, 3, 79, 72, 101, 60, 253, 56, 242, 232, 162, 190, 127, 183,
+ 234, 127, 204, 93, 183, 136, 61, 130, 250, 77, 84, 249, 181, 59, 87,
+ 152, 83, 154, 71, 63, 197, 120, 105, 142, 43, 204, 41, 253, 48, 99,
+ 37, 115, 26, 136, 186, 68, 73, 73, 117, 223, 56, 245, 222, 151, 81,
+ 115, 92, 239, 148, 204, 113, 109, 168, 16, 51, 80, 153, 202, 230, 52,
+ 127, 194, 221, 230, 244, 100, 212, 67, 159, 182, 14, 19, 99, 134, 58,
+ 119, 141, 195, 168, 140, 123, 78, 9, 203, 61, 167, 71, 91, 212, 61,
+ 42, 214, 23, 241, 220, 124, 151, 162, 91, 145, 158, 124, 81, 215, 218,
+ 195, 190, 154, 21, 54, 182, 251, 168, 69, 10, 191, 120, 82, 230, 47,
+ 204, 175, 81, 206, 87, 156, 96, 70, 86, 71, 101, 228, 24, 110, 121,
+ 140, 31, 201, 216, 57, 194, 29, 119, 89, 221, 179, 82, 189, 103, 108,
+ 252, 200, 241, 102, 107, 154, 190, 66, 254, 125, 55, 223, 149, 206, 147,
+ 39, 142, 112, 231, 157, 122, 175, 105, 228, 255, 0, 34, 173, 65, 75,
+ 36, 123, 0, 255, 197, 196, 50, 70, 35, 43, 139, 189, 172, 126, 212,
+ 189, 127, 77, 43, 47, 227, 152, 88, 147, 33, 219, 46, 221, 247, 177,
+ 228, 192, 9, 103, 219, 69, 157, 242, 151, 203, 104, 164, 186, 129, 152,
+ 199, 210, 81, 240, 51, 163, 69, 162, 200, 142, 168, 195, 143, 122, 223,
+ 219, 248, 207, 237, 92, 72, 7, 26, 72, 229, 27, 184, 239, 159, 140,
+ 21, 219, 181, 160, 126, 23, 156, 237, 125, 205, 38, 119, 57, 186, 230,
+ 46, 183, 28, 60, 213, 243, 71, 185, 230, 20, 111, 27, 172, 93, 221,
+ 229, 150, 43, 202, 69, 128, 167, 122, 5, 177, 146, 175, 200, 191, 170,
+ 118, 151, 139, 80, 148, 187, 16, 115, 89, 77, 245, 10, 163, 47, 171,
+ 123, 73, 114, 117, 151, 163, 107, 238, 114, 5, 224, 169, 158, 37, 90,
+ 196, 43, 240, 187, 46, 227, 21, 40, 202, 69, 131, 167, 122, 133, 102,
+ 248, 78, 242, 237, 58, 15, 94, 180, 162, 28, 3, 79, 245, 162, 205,
+ 226, 90, 75, 31, 144, 102, 118, 151, 99, 138, 114, 133, 99, 80, 6,
+ 233, 50, 211, 101, 181, 192, 241, 18, 237, 238, 114, 116, 205, 93, 46,
+ 30, 60, 213, 179, 160, 92, 232, 29, 227, 136, 87, 148, 243, 3, 79,
+ 245, 2, 165, 113, 216, 141, 153, 6, 119, 57, 63, 69, 57, 23, 228,
+ 71, 245, 252, 129, 71, 119, 145, 202, 246, 223, 144, 199, 75, 215, 220,
+ 229, 44, 224, 169, 158, 43, 93, 92, 207, 86, 131, 65, 150, 155, 69,
+ 81, 142, 244, 129, 234, 229, 167, 139, 237, 234, 236, 102, 171, 187, 156,
+ 191, 162, 28, 233, 15, 213, 11, 76, 23, 245, 39, 3, 5, 221, 229,
+ 232, 90, 3, 165, 143, 70, 185, 11, 146, 190, 54, 104, 249, 23, 239,
+ 95, 160, 164, 67, 110, 187, 151, 104, 54, 217, 173, 230, 52, 168, 137,
+ 127, 184, 255, 64, 93, 186, 97, 152, 57, 217, 152, 216, 53, 217, 96,
+ 239, 155, 97, 181, 26, 76, 164, 103, 82, 129, 14, 29, 217, 53, 142,
+ 65, 154, 237, 175, 192, 48, 39, 76, 53, 36, 218, 81, 223, 3, 70,
+ 0, 35, 179, 76, 188, 18, 159, 103, 30, 107, 199, 122, 234, 176, 70,
+ 183, 60, 191, 211, 27, 237, 201, 55, 38, 249, 119, 48, 153, 237, 254,
+ 34, 102, 87, 163, 62, 205, 96, 55, 166, 27, 252, 195, 252, 3, 59,
+ 250, 235, 76, 122, 255, 14, 21, 175, 116, 15, 236, 216, 135, 5, 121,
+ 218, 177, 40, 240, 152, 164, 135, 180, 187, 39, 157, 115, 231, 183, 174,
+ 153, 102, 48, 37, 219, 83, 208, 107, 163, 201, 222, 161, 220, 200, 71,
+ 163, 29, 51, 41, 156, 206, 222, 161, 163, 127, 128, 127, 183, 238, 29,
+ 253, 59, 249, 119, 231, 248, 157, 73, 79, 21, 56, 164, 111, 36, 3,
+ 235, 48, 163, 173, 226, 20, 68, 74, 23, 109, 52, 13, 188, 62, 25,
+ 40, 210, 213, 10, 245, 255, 75, 71, 208, 229, 14, 202, 246, 58, 118,
+ 100, 242, 61, 74, 37, 166, 7, 68, 167, 215, 147, 109, 202, 52, 184,
+ 123, 82, 174, 126, 87, 139, 217, 34, 103, 116, 236, 236, 31, 212, 81,
+ 158, 195, 64, 229, 28, 214, 172, 57, 144, 242, 233, 142, 172, 191, 178,
+ 157, 36, 116, 27, 213, 209, 113, 127, 37, 108, 31, 198, 124, 169, 124,
+ 7, 90, 11, 233, 138, 242, 247, 235, 88, 103, 8, 153, 121, 228, 152,
+ 175, 168, 203, 126, 183, 112, 204, 198, 212, 55, 37, 230, 157, 234, 16,
+ 238, 223, 165, 107, 47, 15, 134, 91, 255, 57, 6, 214, 158, 219, 166,
+ 147, 29, 127, 84, 25, 79, 197, 122, 236, 122, 76, 172, 197, 106, 78,
+ 182, 26, 108, 54, 110, 209, 249, 127, 134, 236, 202, 109, 58, 3, 78,
+ 160, 17, 235, 86, 34, 249, 94, 193, 175, 149, 219, 116, 42, 47, 219,
+ 174, 84, 177, 124, 105, 138, 104, 211, 7, 140, 238, 223, 95, 182, 93,
+ 169, 10, 219, 69, 229, 80, 207, 130, 114, 237, 72, 119, 109, 25, 9,
+ 178, 237, 82, 148, 243, 3, 79, 245, 2, 83, 68, 92, 37, 158, 159,
+ 162, 156, 107, 42, 108, 23, 210, 101, 201, 151, 213, 244, 180, 160, 215,
+ 142, 243, 30, 219, 53, 85, 97, 187, 192, 83, 189, 124, 148, 107, 195,
+ 202, 143, 195, 162, 40, 231, 15, 158, 234, 249, 163, 92, 39, 242, 51,
+ 71, 254, 146, 241, 252, 21, 229, 74, 49, 63, 84, 207, 149, 116, 89,
+ 221, 146, 48, 166, 37, 200, 120, 116, 205, 93, 142, 230, 145, 234, 69,
+ 160, 92, 228, 29, 237, 230, 43, 202, 209, 188, 83, 189, 50, 195, 101,
+ 53, 173, 203, 252, 79, 47, 202, 237, 6, 26, 203, 219, 66, 170, 87,
+ 96, 16, 231, 197, 208, 145, 245, 119, 219, 194, 210, 20, 111, 109, 161,
+ 216, 39, 210, 113, 139, 2, 35, 221, 150, 108, 51, 152, 108, 124, 61,
+ 151, 183, 5, 99, 120, 54, 44, 193, 164, 192, 201, 30, 253, 12, 84,
+ 212, 101, 9, 105, 6, 247, 58, 35, 217, 40, 108, 162, 12, 219, 213,
+ 104, 139, 54, 219, 140, 180, 114, 58, 192, 234, 245, 113, 247, 33, 95,
+ 81, 190, 166, 91, 125, 19, 116, 214, 187, 90, 101, 51, 147, 237, 153,
+ 191, 178, 174, 209, 98, 86, 152, 164, 187, 154, 51, 26, 4, 213, 39,
+ 189, 32, 121, 202, 245, 211, 209, 174, 46, 217, 96, 67, 101, 79, 167,
+ 81, 55, 202, 172, 55, 26, 200, 14, 218, 184, 191, 234, 71, 113, 70,
+ 82, 229, 125, 238, 234, 230, 129, 97, 200, 212, 165, 117, 112, 99, 78,
+ 34, 3, 232, 78, 116, 244, 239, 226, 31, 52, 153, 204, 98, 80, 96,
+ 96, 215, 64, 22, 18, 236, 150, 105, 153, 225, 63, 218, 66, 197, 88,
+ 185, 241, 243, 23, 49, 184, 175, 50, 40, 237, 223, 64, 93, 228, 104,
+ 233, 158, 36, 242, 103, 223, 37, 22, 142, 28, 29, 105, 77, 215, 217,
+ 51, 172, 6, 86, 249, 189, 228, 68, 96, 38, 122, 108, 68, 141, 74,
+ 246, 83, 231, 84, 98, 185, 167, 42, 105, 163, 44, 30, 58, 236, 139,
+ 53, 100, 72, 203, 52, 218, 238, 30, 183, 6, 238, 90, 223, 54, 117,
+ 109, 168, 179, 179, 230, 82, 120, 209, 245, 70, 33, 174, 83, 59, 157,
+ 29, 213, 159, 134, 127, 119, 107, 110, 136, 191, 34, 214, 174, 62, 192,
+ 207, 57, 99, 90, 71, 231, 160, 128, 117, 65, 119, 143, 197, 239, 164,
+ 251, 197, 240, 255, 61, 175, 124, 251, 119, 195, 255, 95, 242, 64, 249,
+ 141, 118, 172, 90, 180, 112, 135, 152, 213, 104, 7, 255, 182, 123, 119,
+ 173, 246, 92, 140, 51, 223, 219, 182, 232, 102, 189, 246, 238, 250, 183,
+ 111, 117, 22, 244, 183, 106, 57, 207, 245, 154, 114, 128, 255, 142, 109,
+ 241, 123, 197, 11, 206, 230, 57, 247, 77, 29, 200, 31, 70, 129, 231,
+ 121, 241, 185, 81, 7, 40, 189, 31, 249, 224, 67, 220, 245, 231, 247,
+ 170, 227, 200, 62, 214, 199, 57, 57, 250, 153, 32, 69, 125, 65, 81,
+ 223, 73, 121, 58, 94, 135, 49, 202, 215, 113, 44, 177, 254, 219, 153,
+ 198, 146, 155, 69, 95, 56, 116, 51, 23, 239, 119, 223, 47, 38, 249,
+ 147, 156, 221, 242, 47, 104, 36, 233, 11, 233, 77, 115, 145, 146, 12,
+ 233, 25, 86, 254, 219, 207, 149, 75, 225, 169, 179, 173, 28, 134, 195,
+ 9, 66, 187, 227, 9, 206, 55, 162, 38, 10, 79, 47, 109, 20, 177,
+ 224, 239, 9, 66, 255, 87, 94, 20, 252, 203, 201, 247, 191, 236, 197,
+ 60, 148, 117, 37, 79, 200, 91, 63, 35, 44, 119, 216, 150, 208, 58,
+ 3, 87, 85, 248, 38, 241, 173, 27, 121, 66, 236, 191, 77, 67, 115,
+ 94, 107, 198, 127, 83, 248, 252, 130, 154, 69, 127, 148, 229, 9, 223,
+ 110, 255, 151, 239, 81, 47, 125, 218, 60, 108, 124, 206, 191, 197, 53,
+ 190, 201, 187, 171, 252, 124, 74, 134, 5, 46, 174, 111, 32, 55, 199,
+ 172, 151, 230, 132, 220, 190, 157, 39, 60, 110, 122, 101, 59, 165, 111,
+ 172, 183, 108, 63, 189, 108, 117, 59, 119, 223, 173, 243, 253, 156, 147,
+ 158, 232, 232, 12, 88, 184, 52, 152, 255, 78, 242, 247, 121, 194, 251,
+ 207, 125, 23, 186, 183, 245, 31, 188, 253, 53, 174, 79, 138, 82, 175,
+ 229, 9, 91, 34, 196, 191, 91, 58, 229, 244, 31, 97, 117, 235, 13,
+ 45, 30, 247, 173, 216, 254, 204, 97, 29, 132, 195, 25, 53, 156, 151,
+ 126, 47, 45, 166, 250, 41, 231, 91, 11, 179, 98, 250, 58, 223, 233,
+ 126, 144, 63, 119, 157, 25, 211, 87, 72, 78, 107, 46, 68, 119, 22,
+ 248, 223, 65, 14, 236, 113, 48, 188, 119, 103, 65, 123, 107, 230, 116,
+ 241, 91, 132, 209, 117, 157, 181, 107, 175, 112, 54, 254, 253, 49, 39,
+ 127, 231, 72, 219, 90, 248, 167, 67, 63, 33, 76, 250, 221, 215, 87,
+ 127, 136, 114, 234, 178, 155, 10, 13, 119, 79, 230, 223, 213, 168, 78,
+ 93, 8, 47, 252, 123, 136, 227, 209, 166, 57, 188, 254, 233, 189, 58,
+ 109, 205, 164, 63, 181, 36, 35, 165, 252, 73, 198, 119, 174, 127, 210,
+ 137, 178, 199, 69, 178, 27, 19, 140, 186, 123, 200, 127, 212, 190, 20,
+ 167, 50, 61, 200, 254, 137, 243, 85, 91, 35, 87, 201, 71, 26, 109,
+ 96, 21, 228, 95, 107, 82, 158, 80, 20, 147, 20, 246, 89, 221, 209,
+ 225, 241, 45, 34, 42, 252, 14, 245, 111, 243, 102, 9, 207, 238, 45,
+ 46, 249, 163, 207, 199, 252, 218, 242, 117, 71, 195, 143, 28, 207, 21,
+ 26, 143, 119, 240, 249, 127, 248, 227, 247, 195, 223, 92, 93, 189, 36,
+ 126, 73, 110, 165, 242, 127, 21, 178, 122, 161, 109, 92, 88, 64, 73,
+ 71, 254, 119, 16, 142, 55, 138, 43, 254, 22, 121, 79, 157, 121, 129,
+ 235, 90, 241, 199, 1, 161, 191, 133, 108, 57, 82, 44, 221, 51, 182,
+ 65, 254, 19, 32, 255, 67, 171, 79, 115, 249, 231, 159, 201, 21, 190,
+ 251, 250, 195, 226, 243, 175, 23, 241, 249, 47, 219, 114, 61, 172, 235,
+ 220, 60, 97, 93, 196, 68, 222, 159, 212, 85, 135, 75, 166, 59, 245,
+ 225, 27, 150, 138, 237, 151, 254, 222, 93, 120, 234, 201, 64, 231, 245,
+ 23, 63, 210, 82, 253, 219, 39, 78, 59, 110, 142, 159, 171, 61, 49,
+ 35, 142, 95, 247, 141, 157, 235, 200, 251, 217, 230, 188, 101, 111, 205,
+ 229, 247, 22, 242, 27, 102, 180, 118, 104, 174, 159, 229, 233, 216, 189,
+ 7, 157, 135, 178, 7, 70, 244, 8, 201, 228, 243, 243, 126, 219, 219,
+ 142, 47, 141, 67, 29, 1, 181, 196, 191, 27, 86, 54, 37, 91, 91,
+ 52, 53, 203, 25, 187, 122, 55, 111, 255, 135, 71, 199, 10, 27, 54,
+ 180, 211, 46, 126, 94, 252, 27, 133, 243, 71, 158, 112, 142, 207, 186,
+ 40, 60, 252, 204, 158, 114, 242, 39, 25, 87, 176, 255, 208, 9, 87,
+ 19, 145, 236, 58, 171, 45, 195, 118, 119, 5, 120, 183, 172, 188, 108,
+ 51, 191, 73, 20, 246, 143, 252, 218, 17, 252, 79, 161, 179, 42, 242,
+ 127, 228, 201, 92, 225, 211, 14, 223, 133, 31, 249, 243, 163, 226, 78,
+ 105, 5, 21, 190, 89, 189, 188, 45, 79, 88, 217, 239, 233, 208, 252,
+ 155, 99, 249, 252, 31, 109, 63, 179, 120, 205, 123, 57, 194, 212, 140,
+ 56, 62, 95, 151, 59, 13, 47, 89, 127, 45, 206, 113, 58, 59, 167,
+ 82, 249, 127, 254, 111, 158, 16, 242, 113, 199, 176, 192, 182, 226, 223,
+ 53, 15, 110, 31, 80, 124, 10, 121, 227, 15, 175, 228, 233, 238, 91,
+ 150, 134, 78, 237, 190, 58, 244, 208, 45, 81, 254, 118, 200, 255, 73,
+ 200, 63, 215, 62, 128, 219, 228, 169, 103, 103, 9, 62, 207, 44, 60,
+ 242, 203, 0, 53, 95, 175, 103, 38, 143, 236, 243, 41, 116, 37, 39,
+ 189, 6, 175, 111, 30, 168, 214, 142, 59, 194, 66, 71, 160, 28, 165,
+ 243, 98, 125, 4, 253, 194, 199, 157, 77, 62, 248, 52, 156, 234, 127,
+ 220, 249, 159, 162, 134, 183, 102, 57, 35, 231, 222, 230, 253, 111, 124,
+ 107, 150, 208, 107, 75, 81, 241, 184, 173, 255, 114, 249, 69, 35, 127,
+ 228, 214, 127, 195, 147, 107, 205, 20, 255, 78, 96, 239, 1, 218, 14,
+ 167, 223, 118, 46, 233, 16, 192, 215, 127, 191, 143, 27, 133, 205, 169,
+ 155, 43, 188, 215, 238, 95, 94, 127, 234, 159, 89, 206, 233, 77, 247,
+ 21, 23, 53, 201, 21, 191, 171, 251, 33, 87, 251, 231, 197, 43, 37,
+ 89, 183, 197, 111, 117, 246, 236, 141, 117, 198, 214, 154, 234, 140, 30,
+ 188, 180, 156, 252, 73, 198, 21, 214, 255, 227, 158, 184, 33, 221, 96,
+ 215, 221, 75, 7, 198, 76, 31, 95, 206, 54, 135, 60, 187, 175, 232,
+ 106, 114, 154, 112, 173, 112, 227, 225, 170, 200, 63, 246, 143, 60, 225,
+ 192, 183, 142, 176, 159, 230, 158, 61, 242, 244, 250, 205, 21, 254, 246,
+ 252, 98, 216, 127, 237, 185, 230, 197, 91, 142, 61, 201, 117, 227, 227,
+ 46, 77, 195, 62, 120, 53, 79, 248, 237, 7, 45, 159, 143, 207, 90,
+ 79, 47, 218, 229, 212, 150, 164, 30, 174, 220, 254, 175, 2, 126, 135,
+ 178, 162, 176, 173, 143, 28, 231, 216, 171, 125, 138, 139, 179, 254, 204,
+ 19, 222, 60, 216, 139, 167, 63, 251, 245, 104, 232, 143, 7, 34, 67,
+ 151, 42, 228, 63, 25, 242, 143, 121, 242, 5, 46, 127, 225, 209, 153,
+ 66, 167, 201, 47, 21, 13, 153, 28, 204, 229, 63, 122, 194, 142, 208,
+ 166, 144, 191, 186, 78, 62, 255, 219, 214, 53, 167, 4, 107, 223, 250,
+ 119, 93, 175, 230, 13, 69, 249, 189, 122, 235, 71, 237, 135, 73, 205,
+ 157, 154, 109, 245, 74, 168, 126, 157, 78, 147, 138, 223, 184, 62, 203,
+ 185, 59, 70, 148, 255, 209, 235, 179, 132, 126, 97, 103, 139, 127, 188,
+ 122, 141, 203, 255, 125, 228, 159, 186, 122, 45, 252, 237, 250, 98, 253,
+ 29, 13, 67, 180, 7, 79, 142, 114, 77, 13, 20, 229, 111, 99, 113,
+ 97, 181, 110, 207, 18, 52, 61, 111, 137, 223, 223, 23, 218, 157, 155,
+ 126, 113, 21, 31, 243, 21, 191, 213, 28, 56, 113, 173, 54, 171, 221,
+ 191, 37, 191, 21, 138, 223, 88, 69, 47, 110, 225, 10, 180, 219, 156,
+ 173, 6, 191, 89, 78, 254, 228, 243, 101, 255, 143, 120, 143, 108, 63,
+ 249, 255, 252, 71, 69, 74, 203, 72, 71, 148, 124, 119, 233, 149, 212,
+ 83, 239, 223, 51, 254, 160, 176, 114, 197, 51, 206, 153, 191, 6, 29,
+ 200, 107, 60, 34, 98, 241, 212, 83, 66, 88, 244, 187, 7, 170, 226,
+ 255, 87, 118, 158, 42, 124, 25, 215, 36, 120, 193, 184, 25, 129, 127,
+ 127, 253, 190, 227, 206, 90, 213, 83, 59, 11, 63, 246, 9, 119, 246,
+ 220, 211, 152, 63, 195, 5, 47, 80, 222, 188, 191, 159, 230, 207, 122,
+ 89, 146, 99, 95, 243, 109, 43, 247, 223, 43, 126, 171, 138, 255, 175,
+ 38, 181, 255, 113, 168, 150, 199, 107, 63, 160, 125, 202, 91, 60, 198,
+ 143, 167, 55, 189, 63, 53, 228, 231, 109, 93, 228, 246, 143, 109, 174,
+ 237, 124, 111, 167, 221, 241, 89, 255, 65, 60, 239, 37, 75, 77, 33,
+ 228, 250, 120, 231, 230, 106, 223, 240, 254, 6, 95, 31, 207, 243, 28,
+ 189, 135, 240, 250, 43, 144, 239, 236, 61, 68, 142, 255, 190, 14, 95,
+ 237, 252, 66, 55, 207, 153, 241, 115, 79, 158, 183, 188, 199, 76, 33,
+ 105, 250, 19, 218, 41, 111, 126, 199, 199, 15, 222, 65, 121, 95, 108,
+ 94, 202, 227, 63, 87, 35, 255, 144, 87, 63, 153, 45, 199, 127, 35,
+ 62, 255, 72, 27, 109, 202, 21, 126, 202, 157, 93, 46, 254, 35, 25,
+ 223, 185, 254, 73, 39, 226, 31, 193, 158, 184, 37, 236, 127, 138, 217,
+ 170, 203, 190, 187, 244, 156, 198, 191, 130, 149, 233, 182, 157, 71, 185,
+ 242, 190, 31, 37, 36, 58, 84, 221, 170, 178, 254, 247, 27, 115, 133,
+ 143, 191, 53, 5, 182, 60, 250, 217, 62, 195, 254, 31, 42, 248, 255,
+ 15, 95, 206, 17, 52, 131, 19, 28, 66, 227, 24, 241, 217, 254, 224,
+ 4, 45, 229, 253, 213, 104, 60, 223, 95, 92, 41, 154, 184, 223, 47,
+ 105, 255, 222, 123, 201, 191, 237, 158, 181, 251, 191, 217, 247, 12, 151,
+ 255, 51, 127, 157, 15, 185, 5, 249, 151, 188, 60, 142, 199, 243, 7,
+ 223, 89, 221, 62, 99, 211, 79, 219, 220, 245, 237, 119, 200, 127, 215,
+ 158, 27, 218, 144, 29, 83, 156, 95, 204, 24, 207, 229, 21, 188, 99,
+ 138, 176, 3, 121, 143, 221, 28, 198, 211, 175, 69, 47, 13, 105, 156,
+ 191, 91, 150, 127, 55, 253, 81, 231, 130, 103, 91, 151, 172, 47, 88,
+ 201, 235, 151, 212, 10, 116, 62, 246, 85, 111, 103, 151, 199, 167, 112,
+ 121, 53, 249, 170, 55, 207, 251, 163, 145, 147, 203, 179, 3, 242, 47,
+ 53, 114, 6, 187, 235, 127, 174, 95, 234, 234, 49, 244, 185, 240, 131,
+ 97, 237, 185, 252, 23, 45, 92, 163, 93, 112, 198, 46, 212, 206, 154,
+ 44, 198, 255, 103, 236, 78, 202, 91, 59, 253, 77, 158, 238, 188, 114,
+ 99, 200, 191, 131, 183, 202, 242, 63, 211, 178, 129, 163, 125, 215, 121,
+ 17, 227, 132, 241, 221, 148, 242, 39, 57, 187, 229, 239, 234, 40, 218,
+ 125, 210, 137, 136, 122, 34, 233, 236, 105, 186, 123, 108, 255, 216, 83,
+ 155, 26, 29, 80, 166, 187, 12, 91, 44, 52, 125, 183, 179, 179, 253,
+ 137, 54, 251, 171, 34, 255, 146, 183, 146, 133, 192, 234, 170, 160, 245,
+ 151, 158, 219, 31, 158, 80, 241, 239, 101, 183, 63, 216, 90, 136, 252,
+ 176, 159, 144, 180, 187, 17, 31, 47, 120, 103, 7, 228, 229, 71, 140,
+ 229, 243, 103, 186, 94, 243, 64, 89, 141, 109, 247, 92, 255, 243, 158,
+ 154, 127, 32, 105, 72, 14, 223, 175, 253, 118, 244, 26, 151, 255, 180,
+ 35, 121, 92, 254, 143, 143, 89, 214, 254, 177, 160, 239, 183, 187, 235,
+ 103, 72, 246, 223, 45, 255, 224, 171, 51, 132, 53, 55, 187, 57, 222,
+ 188, 50, 128, 183, 183, 238, 102, 55, 109, 8, 242, 22, 22, 205, 221,
+ 71, 233, 15, 150, 143, 12, 62, 19, 122, 49, 80, 126, 111, 229, 208,
+ 111, 194, 194, 183, 163, 35, 150, 111, 28, 192, 231, 191, 218, 202, 233,
+ 194, 198, 183, 70, 57, 90, 14, 12, 226, 250, 10, 94, 75, 121, 125,
+ 30, 58, 195, 241, 26, 15, 8, 10, 138, 124, 232, 140, 44, 255, 190,
+ 79, 190, 24, 177, 167, 186, 143, 235, 250, 121, 235, 65, 254, 27, 103,
+ 63, 229, 9, 199, 159, 253, 61, 108, 105, 245, 54, 188, 252, 158, 103,
+ 127, 47, 110, 129, 188, 203, 23, 222, 230, 235, 97, 196, 188, 39, 130,
+ 243, 102, 191, 37, 143, 63, 108, 246, 120, 87, 183, 221, 219, 34, 102,
+ 173, 168, 209, 93, 41, 127, 146, 241, 157, 235, 159, 116, 130, 117, 133,
+ 47, 232, 116, 89, 157, 104, 213, 153, 140, 25, 233, 119, 149, 222, 199,
+ 95, 110, 47, 183, 254, 87, 92, 171, 235, 154, 122, 161, 141, 163, 81,
+ 204, 233, 144, 160, 42, 200, 191, 65, 96, 174, 240, 237, 41, 159, 32,
+ 117, 215, 87, 246, 173, 139, 248, 187, 194, 250, 255, 225, 68, 182, 112,
+ 124, 254, 52, 199, 240, 135, 219, 242, 246, 193, 107, 41, 111, 83, 248,
+ 30, 222, 108, 234, 39, 221, 246, 63, 123, 173, 219, 190, 123, 201, 255,
+ 236, 69, 159, 131, 61, 95, 81, 117, 224, 254, 243, 171, 91, 92, 254,
+ 57, 230, 28, 46, 255, 14, 215, 78, 181, 27, 21, 249, 240, 54, 165,
+ 252, 167, 64, 254, 237, 37, 249, 251, 6, 78, 21, 6, 190, 255, 190,
+ 99, 97, 193, 87, 124, 254, 7, 191, 255, 190, 182, 6, 242, 22, 12,
+ 136, 230, 233, 254, 63, 254, 29, 60, 224, 157, 126, 178, 252, 141, 49,
+ 105, 194, 213, 205, 190, 17, 99, 206, 104, 184, 252, 227, 119, 46, 118,
+ 76, 109, 151, 233, 28, 58, 74, 199, 245, 23, 188, 160, 67, 222, 47,
+ 255, 116, 228, 235, 169, 43, 242, 235, 95, 234, 40, 219, 255, 228, 220,
+ 116, 215, 75, 189, 55, 185, 244, 225, 111, 242, 188, 63, 38, 212, 214,
+ 62, 181, 102, 150, 176, 117, 233, 112, 94, 31, 188, 243, 119, 228, 77,
+ 12, 88, 193, 211, 19, 95, 125, 42, 228, 81, 163, 77, 94, 255, 221,
+ 191, 153, 224, 250, 233, 179, 247, 35, 234, 236, 243, 43, 39, 127, 146,
+ 179, 91, 254, 36, 111, 254, 96, 179, 158, 39, 254, 51, 232, 238, 181,
+ 251, 135, 93, 58, 107, 117, 142, 239, 151, 42, 248, 133, 62, 234, 26,
+ 54, 113, 154, 246, 242, 51, 231, 132, 13, 213, 159, 117, 77, 157, 60,
+ 188, 74, 251, 127, 253, 190, 9, 130, 163, 251, 92, 173, 235, 72, 92,
+ 88, 239, 173, 191, 87, 88, 255, 29, 227, 27, 8, 45, 198, 14, 22,
+ 222, 95, 57, 145, 95, 59, 126, 184, 191, 179, 120, 23, 98, 172, 168,
+ 95, 120, 122, 90, 189, 167, 181, 95, 78, 251, 194, 113, 250, 216, 228,
+ 74, 229, 79, 190, 222, 241, 250, 207, 7, 146, 230, 95, 228, 235, 191,
+ 52, 183, 54, 151, 255, 63, 239, 214, 221, 201, 159, 81, 175, 63, 187,
+ 61, 186, 197, 107, 173, 220, 125, 207, 148, 226, 255, 118, 146, 252, 135,
+ 180, 15, 22, 186, 133, 191, 167, 205, 252, 70, 252, 221, 133, 191, 67,
+ 46, 58, 182, 172, 209, 9, 218, 113, 173, 74, 196, 87, 163, 31, 114,
+ 198, 254, 246, 148, 35, 189, 241, 112, 209, 254, 206, 243, 143, 232, 209,
+ 184, 44, 98, 212, 154, 212, 8, 170, 191, 239, 100, 83, 225, 208, 250,
+ 65, 194, 178, 154, 103, 120, 249, 215, 215, 15, 114, 30, 89, 241, 168,
+ 16, 17, 23, 203, 99, 157, 213, 200, 143, 140, 139, 213, 214, 122, 59,
+ 155, 215, 95, 180, 241, 104, 68, 151, 209, 93, 35, 6, 60, 218, 219,
+ 65, 245, 59, 52, 157, 40, 156, 248, 250, 140, 227, 131, 1, 5, 124,
+ 188, 113, 253, 90, 104, 95, 105, 52, 64, 40, 12, 18, 255, 22, 251,
+ 200, 75, 183, 29, 115, 254, 248, 203, 177, 126, 134, 248, 219, 38, 193,
+ 215, 135, 186, 218, 174, 58, 27, 97, 131, 140, 202, 237, 255, 58, 221,
+ 177, 254, 187, 138, 118, 95, 41, 127, 254, 117, 193, 93, 164, 183, 240,
+ 172, 85, 24, 35, 201, 191, 197, 196, 105, 142, 127, 32, 255, 141, 144,
+ 127, 167, 201, 195, 157, 85, 145, 255, 218, 135, 210, 132, 86, 101, 103,
+ 74, 142, 95, 111, 81, 210, 240, 72, 73, 5, 249, 255, 242, 91, 47,
+ 97, 110, 141, 32, 129, 125, 83, 196, 227, 245, 1, 103, 58, 59, 111,
+ 213, 237, 38, 108, 62, 150, 200, 231, 175, 40, 190, 137, 35, 121, 70,
+ 7, 109, 208, 154, 156, 255, 23, 249, 159, 242, 77, 17, 54, 140, 217,
+ 168, 93, 182, 120, 45, 111, 239, 235, 126, 91, 29, 251, 158, 183, 10,
+ 134, 79, 183, 243, 254, 204, 254, 105, 137, 118, 222, 140, 183, 195, 47,
+ 238, 17, 127, 239, 224, 243, 118, 195, 35, 142, 245, 63, 17, 241, 221,
+ 236, 175, 156, 110, 249, 67, 230, 66, 147, 154, 103, 194, 221, 242, 119,
+ 66, 254, 117, 33, 115, 73, 254, 225, 127, 79, 137, 117, 60, 44, 201,
+ 127, 161, 36, 255, 160, 6, 189, 185, 252, 108, 51, 199, 10, 223, 159,
+ 171, 229, 156, 230, 183, 137, 235, 143, 61, 242, 79, 237, 207, 67, 250,
+ 11, 195, 126, 252, 134, 247, 231, 237, 159, 214, 105, 83, 15, 239, 208,
+ 134, 189, 40, 254, 29, 245, 16, 73, 254, 87, 39, 76, 115, 148, 219,
+ 255, 117, 244, 200, 159, 226, 61, 178, 253, 228, 255, 11, 218, 139, 148,
+ 146, 145, 110, 176, 222, 227, 6, 192, 243, 75, 155, 105, 219, 212, 140,
+ 208, 126, 54, 251, 140, 227, 215, 69, 42, 33, 254, 212, 10, 103, 173,
+ 183, 222, 114, 54, 94, 212, 176, 74, 235, 255, 221, 14, 121, 194, 163,
+ 143, 116, 9, 63, 243, 73, 215, 146, 250, 182, 41, 21, 190, 77, 216,
+ 176, 116, 150, 240, 121, 204, 153, 240, 86, 187, 14, 241, 107, 67, 30,
+ 255, 169, 36, 113, 213, 44, 225, 140, 90, 252, 61, 180, 181, 95, 189,
+ 88, 50, 142, 189, 86, 210, 185, 125, 238, 255, 139, 255, 31, 16, 215,
+ 64, 88, 116, 100, 164, 51, 237, 134, 248, 183, 129, 198, 78, 142, 22,
+ 206, 235, 235, 11, 62, 215, 63, 228, 242, 184, 181, 189, 77, 248, 57,
+ 223, 43, 225, 109, 206, 137, 251, 127, 219, 95, 249, 206, 122, 199, 223,
+ 10, 79, 109, 92, 139, 183, 93, 237, 246, 59, 37, 127, 233, 115, 5,
+ 237, 195, 49, 188, 252, 69, 125, 174, 115, 217, 205, 15, 74, 86, 188,
+ 46, 240, 180, 6, 249, 167, 95, 23, 194, 159, 136, 23, 247, 159, 253,
+ 78, 36, 8, 231, 114, 95, 142, 24, 155, 213, 131, 235, 79, 205, 97,
+ 83, 156, 218, 171, 55, 28, 219, 236, 226, 223, 169, 9, 155, 119, 83,
+ 251, 240, 231, 147, 156, 53, 14, 85, 231, 250, 99, 76, 249, 169, 248,
+ 213, 143, 30, 210, 86, 91, 40, 182, 255, 246, 164, 62, 174, 134, 121,
+ 59, 34, 46, 44, 82, 149, 223, 255, 181, 175, 232, 255, 73, 39, 242,
+ 219, 138, 36, 255, 233, 191, 187, 72, 239, 155, 243, 189, 202, 173, 205,
+ 167, 223, 93, 34, 124, 121, 125, 155, 243, 165, 182, 230, 226, 170, 196,
+ 127, 113, 65, 86, 225, 151, 220, 212, 18, 77, 233, 185, 34, 207, 223,
+ 22, 245, 252, 231, 251, 207, 80, 33, 118, 211, 99, 194, 174, 176, 98,
+ 126, 255, 53, 237, 137, 199, 156, 155, 6, 15, 17, 190, 233, 243, 43,
+ 159, 191, 153, 173, 71, 148, 252, 56, 233, 147, 240, 31, 6, 86, 46,
+ 255, 193, 123, 243, 132, 179, 154, 161, 37, 87, 122, 55, 224, 247, 15,
+ 14, 223, 28, 18, 30, 134, 188, 165, 19, 58, 243, 116, 155, 181, 77,
+ 139, 122, 191, 211, 166, 104, 243, 237, 242, 247, 127, 154, 117, 152, 207,
+ 253, 239, 129, 134, 25, 194, 128, 177, 171, 28, 131, 227, 223, 227, 247,
+ 27, 99, 102, 172, 210, 14, 251, 118, 154, 112, 234, 84, 11, 190, 254,
+ 222, 61, 249, 74, 216, 141, 9, 254, 218, 196, 147, 226, 254, 125, 123,
+ 181, 233, 66, 204, 107, 197, 130, 240, 227, 215, 124, 253, 38, 159, 172,
+ 227, 220, 120, 114, 148, 243, 234, 149, 134, 188, 60, 120, 161, 245, 228,
+ 122, 206, 129, 97, 226, 119, 61, 223, 35, 127, 107, 216, 115, 37, 145,
+ 169, 98, 253, 239, 198, 244, 116, 125, 58, 236, 33, 215, 187, 87, 215,
+ 115, 249, 191, 17, 186, 222, 145, 219, 216, 40, 12, 104, 184, 138, 215,
+ 95, 222, 218, 230, 60, 214, 181, 192, 241, 237, 141, 218, 124, 62, 158,
+ 110, 118, 178, 164, 87, 226, 34, 237, 185, 96, 241, 254, 207, 224, 143,
+ 213, 174, 55, 246, 154, 34, 134, 44, 13, 43, 39, 127, 146, 113, 133,
+ 253, 31, 116, 34, 190, 181, 72, 137, 58, 171, 229, 94, 247, 255, 22,
+ 213, 74, 40, 247, 55, 253, 74, 130, 190, 42, 73, 77, 154, 44, 236,
+ 122, 101, 93, 81, 85, 228, 159, 154, 169, 19, 90, 255, 88, 219, 113,
+ 99, 196, 172, 146, 53, 223, 253, 84, 65, 254, 53, 62, 110, 40, 124,
+ 87, 58, 66, 248, 108, 158, 153, 183, 63, 250, 177, 1, 206, 26, 141,
+ 31, 22, 22, 205, 93, 207, 231, 163, 186, 159, 201, 177, 125, 184, 160,
+ 77, 157, 96, 175, 84, 254, 191, 221, 202, 19, 78, 207, 254, 179, 79,
+ 235, 81, 7, 185, 188, 63, 252, 229, 183, 35, 203, 144, 247, 221, 199,
+ 165, 220, 126, 63, 180, 239, 96, 209, 149, 167, 74, 67, 247, 222, 204,
+ 147, 215, 63, 237, 255, 38, 249, 110, 230, 235, 127, 238, 182, 1, 194,
+ 236, 204, 150, 194, 249, 159, 235, 115, 249, 191, 100, 110, 233, 28, 191,
+ 115, 128, 240, 183, 185, 63, 239, 207, 67, 243, 76, 197, 135, 250, 90,
+ 67, 55, 95, 117, 235, 207, 54, 237, 249, 157, 199, 34, 86, 175, 45,
+ 224, 242, 143, 107, 216, 222, 153, 51, 83, 235, 60, 236, 91, 159, 247,
+ 55, 123, 166, 86, 56, 29, 22, 224, 236, 149, 43, 254, 190, 228, 243,
+ 200, 223, 156, 59, 167, 100, 249, 231, 162, 252, 173, 51, 198, 186, 182,
+ 47, 156, 226, 186, 249, 236, 26, 46, 255, 157, 218, 28, 167, 16, 220,
+ 81, 251, 72, 96, 75, 94, 127, 199, 55, 254, 142, 219, 35, 102, 58,
+ 7, 21, 229, 115, 253, 223, 157, 215, 209, 241, 176, 238, 209, 18, 215,
+ 80, 177, 254, 197, 188, 169, 174, 105, 11, 135, 69, 216, 222, 235, 85,
+ 78, 254, 36, 227, 59, 229, 79, 58, 161, 188, 255, 119, 47, 29, 48,
+ 15, 105, 85, 46, 54, 111, 38, 172, 211, 94, 57, 244, 169, 54, 243,
+ 183, 86, 225, 85, 145, 255, 208, 244, 56, 97, 254, 38, 75, 201, 198,
+ 73, 133, 197, 197, 223, 92, 169, 32, 255, 236, 99, 190, 194, 134, 235,
+ 177, 194, 210, 199, 182, 240, 249, 110, 180, 119, 188, 243, 92, 104, 117,
+ 97, 254, 222, 27, 188, 63, 71, 166, 189, 81, 178, 121, 196, 142, 240,
+ 75, 183, 102, 85, 42, 255, 244, 75, 121, 194, 51, 126, 179, 194, 14,
+ 165, 54, 228, 242, 27, 53, 104, 102, 241, 232, 43, 121, 66, 219, 218,
+ 187, 185, 252, 183, 30, 105, 84, 252, 100, 226, 142, 208, 241, 55, 242,
+ 100, 255, 79, 242, 79, 110, 178, 147, 203, 127, 195, 19, 213, 29, 147,
+ 215, 205, 18, 84, 133, 226, 239, 252, 249, 174, 152, 229, 212, 135, 251,
+ 56, 246, 86, 143, 226, 237, 255, 58, 170, 83, 73, 220, 170, 222, 37,
+ 131, 231, 136, 245, 55, 60, 182, 209, 53, 242, 179, 235, 17, 93, 234,
+ 254, 197, 229, 223, 102, 255, 215, 37, 175, 255, 51, 203, 121, 113, 222,
+ 92, 94, 254, 240, 63, 179, 132, 78, 230, 159, 74, 34, 34, 211, 57,
+ 222, 5, 228, 15, 139, 76, 47, 137, 171, 33, 233, 207, 165, 25, 14,
+ 199, 234, 125, 174, 175, 98, 195, 185, 252, 15, 246, 204, 114, 110, 190,
+ 145, 238, 112, 245, 253, 131, 215, 255, 176, 87, 142, 246, 187, 192, 44,
+ 103, 108, 81, 17, 79, 107, 179, 95, 47, 153, 81, 243, 124, 201, 239,
+ 129, 226, 248, 219, 246, 181, 185, 236, 203, 31, 141, 24, 115, 34, 160,
+ 156, 252, 201, 231, 43, 229, 207, 109, 63, 252, 63, 171, 43, 146, 219,
+ 255, 223, 45, 6, 12, 92, 218, 204, 209, 14, 254, 255, 75, 248, 255,
+ 111, 23, 169, 156, 211, 225, 255, 175, 158, 120, 203, 121, 125, 97, 195,
+ 42, 197, 127, 111, 189, 158, 43, 188, 235, 95, 86, 124, 114, 113, 181,
+ 162, 63, 67, 222, 172, 176, 255, 203, 30, 54, 67, 216, 221, 180, 175,
+ 99, 109, 76, 99, 46, 191, 214, 227, 251, 106, 127, 249, 125, 186, 240,
+ 166, 113, 50, 47, 251, 227, 178, 141, 125, 54, 108, 138, 15, 143, 221,
+ 156, 247, 255, 226, 255, 19, 14, 63, 175, 221, 247, 156, 213, 25, 61,
+ 169, 39, 111, 239, 157, 247, 172, 194, 138, 118, 47, 104, 125, 30, 142,
+ 225, 250, 184, 163, 224, 179, 176, 30, 29, 154, 149, 148, 74, 247, 159,
+ 215, 143, 106, 237, 10, 142, 74, 114, 148, 254, 22, 199, 227, 175, 193,
+ 236, 221, 146, 63, 224, 255, 247, 213, 141, 225, 242, 254, 19, 254, 255,
+ 244, 173, 15, 74, 246, 189, 46, 254, 214, 104, 208, 195, 49, 225, 109,
+ 16, 11, 184, 253, 255, 212, 227, 9, 194, 69, 248, 255, 71, 178, 122,
+ 240, 190, 215, 184, 152, 237, 220, 253, 152, 222, 113, 114, 188, 248, 155,
+ 178, 195, 103, 79, 214, 142, 41, 203, 118, 118, 237, 116, 152, 247, 103,
+ 152, 121, 127, 120, 237, 185, 171, 75, 86, 79, 200, 45, 231, 255, 63,
+ 133, 140, 202, 237, 255, 234, 86, 92, 255, 164, 19, 101, 181, 68, 242,
+ 124, 94, 92, 185, 244, 126, 56, 223, 171, 220, 189, 217, 121, 240, 255,
+ 191, 193, 255, 191, 208, 198, 28, 86, 149, 245, 79, 191, 49, 64, 191,
+ 171, 64, 191, 133, 176, 71, 254, 253, 2, 197, 254, 47, 236, 25, 199,
+ 173, 173, 25, 194, 51, 123, 215, 240, 241, 183, 211, 88, 157, 246, 29,
+ 203, 28, 183, 124, 3, 184, 173, 136, 110, 215, 75, 251, 79, 179, 55,
+ 139, 115, 92, 51, 42, 149, 127, 14, 124, 253, 190, 189, 67, 74, 138,
+ 63, 13, 228, 235, 253, 88, 225, 144, 240, 125, 200, 235, 21, 250, 60,
+ 127, 9, 254, 155, 130, 39, 66, 187, 213, 254, 229, 245, 163, 119, 248,
+ 255, 230, 87, 231, 114, 255, 255, 254, 135, 163, 132, 184, 106, 245, 132,
+ 38, 250, 189, 188, 253, 147, 49, 245, 157, 41, 171, 71, 9, 173, 84,
+ 9, 60, 109, 110, 219, 162, 36, 242, 91, 87, 137, 207, 203, 226, 252,
+ 127, 60, 110, 174, 176, 117, 198, 178, 136, 192, 143, 252, 249, 250, 15,
+ 135, 255, 63, 12, 255, 127, 252, 74, 67, 222, 95, 240, 194, 213, 39,
+ 235, 57, 11, 224, 243, 249, 243, 7, 228, 79, 68, 44, 16, 37, 249,
+ 255, 195, 240, 255, 53, 134, 63, 228, 218, 113, 117, 61, 159, 31, 223,
+ 181, 233, 206, 88, 199, 94, 109, 171, 223, 31, 225, 245, 181, 194, 1,
+ 71, 187, 195, 102, 231, 228, 139, 199, 185, 254, 189, 173, 81, 107, 19,
+ 114, 215, 148, 76, 8, 23, 215, 255, 166, 38, 173, 92, 198, 171, 186,
+ 136, 172, 239, 58, 150, 147, 63, 201, 184, 194, 243, 63, 232, 132, 171,
+ 166, 72, 146, 237, 191, 171, 6, 188, 241, 80, 66, 185, 223, 248, 60,
+ 6, 255, 63, 13, 254, 63, 106, 239, 186, 208, 170, 200, 127, 78, 74,
+ 158, 48, 170, 254, 229, 176, 236, 232, 99, 71, 154, 172, 207, 169, 16,
+ 255, 107, 154, 228, 10, 89, 159, 92, 13, 183, 39, 126, 206, 253, 247,
+ 216, 144, 107, 37, 15, 109, 157, 37, 12, 60, 106, 231, 101, 179, 187,
+ 117, 235, 211, 82, 200, 44, 177, 46, 172, 124, 253, 239, 129, 175, 255,
+ 125, 73, 73, 159, 152, 132, 119, 184, 252, 155, 156, 124, 237, 200, 115,
+ 240, 245, 135, 254, 173, 193, 199, 51, 244, 196, 59, 161, 191, 159, 169,
+ 81, 108, 187, 225, 121, 254, 75, 235, 127, 89, 207, 5, 92, 254, 198,
+ 213, 225, 194, 165, 57, 157, 132, 214, 22, 241, 249, 227, 222, 191, 59,
+ 57, 63, 156, 31, 46, 52, 123, 237, 11, 94, 255, 197, 167, 118, 21,
+ 151, 196, 198, 151, 172, 88, 38, 214, 15, 233, 219, 69, 72, 101, 207,
+ 71, 212, 46, 91, 212, 155, 234, 247, 134, 255, 223, 8, 255, 191, 202,
+ 183, 62, 151, 31, 120, 225, 37, 248, 255, 2, 248, 124, 30, 131, 33,
+ 95, 143, 88, 96, 153, 228, 255, 135, 195, 255, 127, 7, 255, 95, 246,
+ 236, 26, 62, 63, 61, 45, 51, 157, 51, 119, 125, 22, 62, 127, 168,
+ 134, 215, 79, 202, 250, 172, 68, 181, 44, 215, 217, 242, 214, 21, 62,
+ 31, 1, 241, 26, 109, 143, 133, 111, 21, 117, 254, 78, 148, 191, 49,
+ 122, 144, 235, 214, 156, 43, 66, 164, 169, 91, 57, 249, 147, 140, 43,
+ 60, 255, 171, 85, 169, 255, 175, 84, 7, 94, 30, 210, 170, 156, 108,
+ 90, 194, 255, 255, 9, 255, 63, 250, 183, 86, 37, 85, 145, 127, 226,
+ 249, 4, 33, 187, 231, 248, 240, 210, 35, 89, 97, 187, 135, 156, 173,
+ 224, 255, 255, 114, 61, 34, 60, 114, 35, 90, 40, 85, 23, 242, 249,
+ 254, 160, 83, 180, 179, 78, 70, 125, 33, 90, 251, 37, 239, 207, 205,
+ 83, 207, 134, 251, 143, 126, 161, 164, 115, 118, 229, 241, 127, 236, 229,
+ 60, 97, 248, 134, 252, 176, 208, 137, 63, 112, 249, 127, 197, 242, 139,
+ 227, 254, 65, 222, 71, 157, 56, 222, 95, 7, 127, 13, 245, 173, 22,
+ 80, 252, 254, 245, 60, 249, 249, 15, 201, 191, 218, 204, 149, 92, 254,
+ 157, 51, 85, 142, 197, 191, 204, 18, 150, 46, 90, 201, 203, 31, 62,
+ 55, 203, 121, 243, 37, 149, 163, 227, 167, 93, 120, 250, 181, 249, 163,
+ 194, 34, 39, 207, 43, 62, 125, 81, 172, 255, 113, 235, 5, 46, 215,
+ 75, 31, 70, 76, 104, 55, 72, 180, 255, 133, 95, 151, 56, 224, 255,
+ 223, 157, 55, 151, 247, 215, 9, 255, 223, 47, 253, 167, 146, 169, 240,
+ 249, 60, 222, 71, 126, 119, 196, 2, 9, 146, 255, 63, 113, 97, 134,
+ 227, 93, 248, 255, 67, 177, 225, 124, 126, 214, 117, 205, 118, 214, 217,
+ 105, 118, 148, 54, 92, 203, 235, 143, 186, 106, 213, 118, 153, 149, 237,
+ 12, 217, 222, 130, 167, 75, 84, 185, 225, 155, 110, 235, 194, 63, 105,
+ 38, 214, 223, 218, 125, 132, 75, 181, 110, 129, 112, 187, 36, 184, 156,
+ 252, 233, 153, 159, 82, 254, 252, 29, 32, 122, 254, 87, 77, 36, 241,
+ 253, 159, 187, 59, 128, 220, 179, 173, 180, 19, 15, 39, 8, 141, 142,
+ 39, 56, 157, 81, 19, 157, 179, 150, 54, 138, 120, 230, 239, 9, 194,
+ 176, 87, 94, 172, 146, 255, 255, 25, 242, 105, 145, 250, 84, 241, 182,
+ 191, 119, 21, 253, 62, 101, 121, 133, 247, 127, 70, 97, 93, 182, 105,
+ 244, 120, 232, 11, 147, 58, 242, 249, 78, 221, 84, 173, 168, 229, 183,
+ 121, 66, 190, 85, 197, 231, 111, 101, 94, 64, 241, 162, 137, 170, 240,
+ 99, 95, 254, 255, 188, 255, 83, 92, 150, 39, 188, 51, 246, 151, 208,
+ 113, 99, 196, 223, 154, 126, 237, 198, 23, 69, 163, 175, 229, 9, 62,
+ 187, 71, 112, 251, 187, 199, 247, 74, 241, 175, 3, 135, 134, 181, 251,
+ 90, 108, 127, 112, 163, 14, 194, 94, 115, 13, 231, 192, 6, 159, 240,
+ 111, 115, 12, 231, 91, 11, 121, 49, 125, 157, 117, 122, 28, 228, 253,
+ 5, 47, 232, 210, 154, 11, 99, 58, 11, 92, 215, 31, 69, 254, 168,
+ 206, 130, 195, 253, 254, 79, 211, 209, 117, 157, 15, 215, 94, 225, 244,
+ 251, 253, 49, 222, 247, 134, 161, 173, 133, 86, 129, 253, 132, 88, 125,
+ 1, 175, 95, 244, 69, 148, 211, 100, 110, 42, 176, 101, 83, 184, 63,
+ 222, 247, 248, 223, 37, 151, 255, 26, 162, 109, 255, 136, 120, 255, 107,
+ 213, 94, 157, 246, 146, 225, 79, 45, 201, 168, 220, 254, 175, 90, 37,
+ 251, 63, 232, 68, 188, 70, 36, 241, 253, 159, 187, 203, 191, 254, 190,
+ 148, 114, 243, 59, 208, 254, 137, 211, 97, 107, 228, 234, 112, 90, 227,
+ 168, 202, 250, 175, 151, 145, 39, 252, 121, 107, 114, 113, 73, 72, 96,
+ 73, 98, 231, 138, 239, 255, 156, 59, 55, 75, 248, 37, 190, 164, 228,
+ 160, 105, 63, 215, 247, 65, 237, 143, 134, 167, 190, 149, 43, 52, 205,
+ 16, 239, 7, 204, 235, 189, 167, 228, 157, 117, 183, 194, 116, 151, 42,
+ 95, 255, 70, 200, 106, 214, 115, 137, 97, 9, 123, 67, 185, 189, 204,
+ 93, 156, 88, 188, 1, 121, 63, 124, 254, 54, 127, 126, 239, 168, 23,
+ 94, 52, 107, 243, 155, 125, 118, 41, 222, 255, 33, 255, 159, 191, 100,
+ 7, 127, 166, 242, 122, 143, 60, 225, 93, 221, 177, 226, 129, 199, 215,
+ 243, 190, 253, 125, 250, 231, 176, 188, 156, 60, 161, 201, 124, 241, 183,
+ 241, 255, 222, 182, 38, 252, 130, 209, 86, 178, 251, 43, 177, 253, 161,
+ 197, 193, 66, 225, 236, 64, 231, 217, 3, 111, 242, 245, 255, 196, 91,
+ 167, 29, 141, 99, 231, 106, 143, 204, 136, 227, 239, 79, 213, 143, 157,
+ 235, 152, 241, 179, 205, 249, 88, 70, 107, 46, 63, 202, 87, 101, 180,
+ 214, 246, 146, 222, 255, 49, 238, 61, 232, 60, 144, 61, 48, 226, 108,
+ 112, 38, 151, 223, 160, 185, 87, 28, 97, 103, 7, 57, 18, 13, 19,
+ 121, 253, 216, 152, 108, 109, 157, 148, 44, 103, 224, 137, 61, 188, 253,
+ 151, 199, 140, 119, 182, 251, 188, 163, 227, 246, 73, 13, 111, 191, 113,
+ 255, 19, 206, 159, 210, 46, 10, 255, 190, 183, 167, 156, 252, 73, 198,
+ 21, 246, 127, 208, 9, 150, 43, 146, 244, 238, 199, 93, 21, 224, 88,
+ 89, 126, 185, 247, 191, 108, 223, 36, 10, 93, 162, 191, 118, 212, 253,
+ 167, 80, 168, 138, 252, 77, 207, 231, 10, 95, 15, 254, 160, 164, 241,
+ 171, 207, 135, 189, 16, 240, 102, 133, 247, 127, 66, 79, 230, 9, 151,
+ 182, 169, 194, 226, 222, 111, 203, 231, 191, 250, 208, 217, 197, 11, 139,
+ 167, 11, 15, 93, 24, 206, 231, 239, 143, 178, 199, 195, 255, 73, 29,
+ 161, 237, 184, 116, 122, 229, 254, 255, 223, 60, 225, 74, 84, 231, 48,
+ 161, 243, 122, 142, 253, 229, 250, 206, 197, 175, 33, 207, 49, 102, 37,
+ 79, 47, 217, 178, 182, 232, 197, 179, 171, 138, 182, 223, 242, 200, 159,
+ 214, 191, 37, 225, 56, 127, 166, 242, 217, 249, 89, 66, 195, 167, 123,
+ 247, 121, 180, 68, 197, 229, 83, 125, 125, 100, 209, 243, 216, 83, 94,
+ 56, 176, 140, 219, 131, 245, 7, 85, 142, 201, 155, 86, 20, 239, 251,
+ 73, 244, 191, 177, 90, 31, 225, 82, 191, 230, 206, 247, 244, 165, 252,
+ 253, 143, 115, 205, 254, 41, 106, 114, 107, 150, 179, 241, 220, 219, 188,
+ 255, 224, 133, 190, 27, 138, 138, 235, 110, 21, 223, 231, 249, 122, 206,
+ 237, 146, 144, 173, 255, 150, 164, 74, 239, 255, 36, 134, 14, 208, 62,
+ 124, 250, 109, 231, 238, 14, 226, 254, 109, 246, 246, 3, 161, 31, 204,
+ 205, 21, 54, 31, 252, 146, 215, 223, 127, 49, 203, 121, 217, 180, 183,
+ 216, 231, 236, 44, 62, 254, 182, 167, 114, 29, 150, 85, 159, 134, 23,
+ 77, 23, 127, 159, 55, 229, 133, 88, 231, 186, 198, 83, 157, 103, 198,
+ 44, 45, 31, 255, 231, 86, 242, 252, 79, 83, 233, 251, 63, 149, 234,
+ 192, 171, 9, 227, 143, 40, 211, 239, 172, 223, 87, 244, 65, 114, 154,
+ 112, 102, 214, 198, 94, 85, 145, 127, 194, 31, 121, 130, 53, 182, 164,
+ 248, 55, 245, 178, 162, 31, 114, 103, 86, 120, 255, 103, 25, 100, 213,
+ 172, 244, 82, 209, 188, 31, 234, 241, 249, 206, 154, 171, 10, 171, 129,
+ 189, 214, 212, 246, 225, 124, 62, 114, 235, 212, 46, 190, 144, 30, 30,
+ 62, 227, 80, 229, 246, 191, 7, 240, 87, 197, 149, 132, 69, 132, 159,
+ 226, 242, 126, 122, 110, 73, 113, 247, 63, 243, 132, 58, 83, 123, 242,
+ 244, 249, 186, 239, 22, 61, 251, 85, 68, 81, 246, 29, 242, 111, 46,
+ 244, 224, 235, 127, 104, 251, 153, 66, 116, 226, 202, 35, 237, 63, 13,
+ 228, 242, 239, 255, 189, 189, 40, 226, 231, 60, 225, 219, 69, 63, 240,
+ 254, 60, 117, 42, 208, 241, 121, 202, 79, 197, 187, 234, 136, 242, 91,
+ 113, 228, 71, 109, 90, 78, 43, 103, 63, 85, 27, 254, 254, 87, 76,
+ 235, 73, 197, 39, 174, 207, 114, 174, 138, 17, 229, 255, 230, 245, 89,
+ 66, 108, 175, 179, 197, 239, 93, 189, 198, 229, 191, 4, 249, 199, 174,
+ 94, 43, 121, 95, 122, 255, 103, 88, 227, 16, 237, 150, 147, 163, 92,
+ 243, 3, 69, 249, 39, 7, 173, 15, 173, 6, 123, 215, 162, 240, 45,
+ 94, 191, 176, 196, 238, 124, 182, 246, 137, 226, 234, 187, 214, 112, 249,
+ 251, 180, 95, 235, 216, 180, 247, 141, 240, 199, 159, 177, 241, 250, 19,
+ 22, 181, 112, 109, 154, 106, 115, 190, 58, 248, 77, 46, 127, 250, 29,
+ 40, 250, 62, 200, 18, 127, 89, 61, 207, 253, 61, 95, 102, 249, 239,
+ 13, 35, 251, 218, 140, 118, 166, 75, 53, 232, 153, 248, 205, 97, 96,
+ 96, 144, 244, 142, 185, 248, 45, 137, 63, 202, 103, 137, 84, 122, 242,
+ 166, 231, 55, 85, 144, 255, 180, 251, 123, 18, 127, 233, 91, 194, 191,
+ 254, 46, 135, 125, 191, 247, 202, 221, 239, 168, 135, 73, 24, 110, 188,
+ 82, 63, 180, 133, 180, 101, 122, 90, 185, 207, 132, 239, 247, 158, 178,
+ 18, 143, 48, 228, 254, 129, 231, 125, 156, 253, 79, 185, 254, 221, 239,
+ 189, 215, 114, 253, 83, 224, 93, 80, 163, 127, 72, 23, 246, 191, 3,
+ 239, 62, 239, 81, 42, 241, 8, 195, 141, 151, 15, 158, 240, 163, 39,
+ 151, 159, 191, 251, 189, 151, 167, 196, 203, 87, 224, 249, 129, 39, 252,
+ 248, 254, 166, 114, 243, 119, 191, 247, 188, 148, 120, 126, 10, 188, 229,
+ 179, 16, 39, 18, 94, 209, 29, 227, 189, 207, 123, 67, 74, 60, 194,
+ 112, 227, 249, 131, 39, 252, 136, 130, 148, 114, 253, 187, 223, 123, 40,
+ 74, 60, 127, 5, 94, 225, 204, 203, 106, 194, 47, 75, 155, 90, 14,
+ 239, 126, 239, 53, 40, 241, 8, 195, 141, 23, 1, 158, 240, 203, 250,
+ 149, 199, 187, 223, 115, 114, 37, 94, 132, 2, 175, 116, 6, 116, 5,
+ 233, 64, 255, 244, 114, 120, 247, 123, 238, 86, 78, 159, 103, 40, 244,
+ 25, 60, 239, 227, 194, 242, 191, 41, 115, 191, 231, 56, 229, 244, 89,
+ 129, 119, 97, 58, 244, 25, 233, 248, 127, 141, 229, 231, 239, 62, 207,
+ 5, 202, 233, 243, 116, 133, 62, 131, 39, 252, 210, 27, 102, 223, 59,
+ 245, 249, 126, 152, 178, 62, 43, 240, 252, 192, 19, 126, 33, 75, 171,
+ 32, 143, 123, 61, 183, 46, 167, 207, 10, 188, 130, 28, 232, 51, 199,
+ 52, 85, 42, 143, 123, 97, 202, 127, 47, 51, 199, 131, 23, 8, 158,
+ 240, 149, 127, 127, 92, 150, 199, 125, 58, 40, 255, 86, 133, 2, 207,
+ 149, 125, 89, 77, 248, 241, 199, 43, 149, 199, 61, 17, 229, 223, 170,
+ 200, 246, 224, 69, 131, 231, 125, 188, 232, 145, 135, 230, 63, 236, 251,
+ 149, 120, 209, 10, 188, 50, 248, 2, 194, 47, 140, 79, 175, 196, 62,
+ 223, 123, 192, 242, 111, 143, 102, 121, 240, 44, 224, 9, 63, 126, 216,
+ 165, 74, 236, 243, 127, 195, 179, 40, 240, 200, 87, 241, 62, 222, 170,
+ 212, 62, 255, 167, 249, 99, 74, 60, 9, 63, 223, 113, 87, 251, 124,
+ 87, 76, 183, 15, 38, 191, 235, 246, 193, 101, 67, 160, 43, 241, 30,
+ 63, 204, 125, 176, 221, 104, 74, 70, 171, 70, 123, 98, 74, 176, 228,
+ 132, 221, 62, 216, 31, 117, 163, 135, 98, 61, 69, 167, 251, 150, 30,
+ 78, 241, 149, 109, 96, 166, 194, 6, 102, 72, 120, 141, 254, 241, 218,
+ 7, 19, 134, 108, 3, 193, 19, 254, 242, 122, 222, 251, 224, 8, 5,
+ 94, 169, 29, 250, 130, 116, 105, 200, 37, 175, 125, 48, 97, 200, 54,
+ 16, 60, 225, 151, 5, 121, 239, 131, 227, 21, 120, 23, 108, 232, 27,
+ 210, 254, 79, 121, 239, 131, 9, 67, 182, 129, 224, 9, 63, 250, 5,
+ 179, 215, 62, 56, 95, 129, 231, 7, 158, 240, 253, 119, 120, 239, 131,
+ 253, 20, 120, 5, 86, 232, 51, 245, 113, 171, 209, 107, 31, 76, 24,
+ 178, 13, 4, 207, 251, 24, 237, 189, 15, 14, 84, 224, 185, 166, 193,
+ 6, 34, 93, 214, 214, 123, 31, 76, 24, 178, 13, 4, 79, 248, 165,
+ 129, 38, 175, 125, 112, 180, 2, 175, 112, 36, 236, 11, 210, 236, 51,
+ 239, 125, 48, 97, 200, 235, 13, 60, 225, 151, 125, 225, 189, 15, 142,
+ 80, 224, 149, 142, 192, 122, 67, 186, 160, 200, 123, 31, 76, 24, 242,
+ 122, 3, 79, 248, 254, 193, 222, 251, 224, 120, 5, 222, 133, 225, 144,
+ 5, 210, 101, 19, 189, 247, 193, 132, 33, 175, 55, 240, 132, 31, 239,
+ 242, 222, 7, 231, 43, 240, 252, 192, 19, 126, 65, 247, 169, 94, 251,
+ 96, 63, 5, 94, 193, 48, 172, 55, 26, 243, 33, 239, 125, 48, 97,
+ 200, 235, 13, 60, 225, 199, 239, 243, 222, 7, 7, 42, 240, 92, 240,
+ 47, 132, 31, 223, 210, 123, 31, 76, 24, 242, 122, 3, 79, 248, 101,
+ 223, 121, 239, 131, 163, 135, 150, 247, 193, 132, 207, 54, 121, 239, 131,
+ 201, 239, 186, 125, 112, 96, 24, 124, 91, 102, 57, 31, 108, 215, 153,
+ 244, 228, 132, 105, 51, 236, 222, 6, 203, 62, 216, 130, 186, 5, 168,
+ 19, 93, 116, 75, 109, 241, 59, 83, 83, 142, 59, 134, 40, 250, 56,
+ 68, 194, 155, 225, 189, 15, 102, 10, 188, 229, 131, 17, 39, 12, 161,
+ 223, 45, 240, 222, 7, 19, 134, 188, 239, 2, 79, 248, 209, 179, 188,
+ 247, 193, 254, 10, 188, 194, 65, 152, 67, 164, 93, 58, 239, 125, 48,
+ 97, 200, 54, 16, 60, 225, 199, 127, 229, 189, 15, 142, 80, 224, 149,
+ 14, 132, 13, 68, 186, 32, 223, 123, 31, 76, 24, 178, 13, 4, 79,
+ 248, 165, 107, 188, 247, 193, 241, 10, 188, 11, 3, 128, 133, 116, 193,
+ 94, 239, 125, 48, 97, 200, 54, 16, 60, 225, 251, 77, 240, 222, 7,
+ 231, 43, 240, 252, 192, 19, 126, 190, 202, 123, 31, 236, 167, 192, 43,
+ 232, 15, 44, 164, 151, 247, 244, 222, 7, 19, 134, 108, 3, 193, 19,
+ 190, 235, 27, 239, 125, 112, 160, 2, 207, 213, 15, 178, 32, 204, 239,
+ 189, 247, 193, 132, 33, 219, 64, 240, 132, 95, 240, 246, 93, 109, 254,
+ 125, 245, 57, 90, 129, 87, 40, 96, 172, 72, 199, 135, 123, 239, 131,
+ 9, 67, 94, 111, 224, 9, 223, 47, 193, 123, 31, 28, 161, 192, 43,
+ 213, 98, 189, 33, 173, 252, 187, 245, 255, 171, 15, 38, 12, 121, 189,
+ 129, 39, 252, 248, 48, 239, 125, 112, 188, 2, 239, 66, 56, 214, 155,
+ 150, 246, 213, 119, 141, 137, 238, 235, 131, 9, 67, 94, 111, 224, 9,
+ 191, 192, 233, 189, 15, 206, 87, 224, 249, 129, 39, 124, 255, 14, 222,
+ 251, 96, 63, 5, 30, 249, 43, 194, 47, 248, 213, 123, 31, 76, 24,
+ 74, 31, 76, 248, 254, 159, 121, 239, 131, 201, 239, 186, 125, 112, 97,
+ 16, 226, 131, 33, 74, 31, 108, 231, 251, 95, 120, 94, 163, 93, 246,
+ 192, 30, 31, 236, 10, 165, 248, 19, 250, 90, 221, 228, 91, 86, 236,
+ 217, 7, 83, 190, 188, 230, 66, 165, 239, 91, 170, 121, 239, 131, 163,
+ 21, 120, 101, 125, 176, 230, 144, 182, 216, 188, 247, 193, 132, 33, 223,
+ 235, 0, 79, 248, 254, 83, 189, 247, 193, 22, 5, 30, 3, 79, 248,
+ 126, 81, 222, 251, 96, 166, 192, 91, 222, 27, 99, 69, 58, 255, 144,
+ 247, 62, 152, 48, 228, 152, 3, 60, 225, 199, 47, 241, 222, 7, 251,
+ 43, 240, 10, 123, 193, 127, 32, 29, 127, 208, 123, 31, 76, 24, 178,
+ 13, 4, 79, 248, 174, 120, 239, 125, 112, 132, 2, 175, 180, 39, 108,
+ 96, 47, 250, 13, 169, 169, 229, 108, 254, 255, 226, 131, 9, 67, 182,
+ 129, 224, 9, 63, 63, 194, 123, 31, 28, 175, 192, 187, 208, 3, 54,
+ 16, 233, 248, 54, 222, 251, 96, 194, 144, 109, 32, 120, 194, 143, 190,
+ 233, 189, 15, 206, 87, 224, 249, 129, 39, 252, 11, 23, 189, 247, 193,
+ 126, 10, 188, 130, 238, 152, 59, 164, 203, 126, 240, 126, 31, 76, 24,
+ 114, 204, 1, 158, 240, 227, 135, 120, 239, 131, 3, 21, 120, 174, 110,
+ 180, 199, 68, 31, 167, 121, 239, 131, 9, 67, 182, 127, 224, 9, 191,
+ 236, 160, 247, 62, 56, 90, 129, 87, 22, 130, 181, 129, 244, 133, 67,
+ 222, 223, 139, 38, 12, 217, 254, 129, 231, 125, 252, 214, 123, 31, 108,
+ 81, 224, 49, 240, 132, 111, 41, 243, 222, 7, 51, 5, 222, 114, 248,
+ 23, 194, 143, 239, 239, 189, 15, 38, 12, 217, 254, 129, 39, 124, 215,
+ 21, 239, 125, 176, 127, 112, 121, 31, 76, 248, 17, 7, 188, 247, 193,
+ 228, 119, 221, 62, 216, 127, 23, 100, 17, 86, 209, 7, 243, 15, 110,
+ 197, 187, 210, 240, 196, 30, 31, 28, 129, 186, 203, 81, 39, 250, 113,
+ 147, 111, 126, 174, 199, 7, 83, 190, 108, 3, 3, 69, 188, 194, 71,
+ 188, 247, 193, 132, 33, 219, 64, 240, 132, 239, 223, 209, 123, 31, 28,
+ 175, 192, 179, 92, 160, 251, 128, 24, 119, 92, 21, 124, 240, 5, 197,
+ 120, 243, 161, 47, 129, 244, 27, 185, 222, 251, 96, 194, 144, 251, 183,
+ 15, 58, 8, 124, 215, 58, 239, 125, 48, 97, 200, 58, 3, 158, 240,
+ 203, 54, 123, 239, 131, 153, 2, 111, 121, 33, 250, 135, 116, 244, 214,
+ 42, 60, 15, 46, 84, 248, 244, 189, 208, 23, 224, 185, 182, 120, 239,
+ 131, 9, 67, 246, 233, 224, 9, 63, 162, 177, 247, 62, 56, 66, 129,
+ 87, 250, 10, 124, 58, 210, 5, 45, 189, 247, 193, 132, 33, 235, 51,
+ 120, 194, 143, 111, 234, 189, 15, 142, 87, 224, 93, 216, 3, 249, 34,
+ 237, 58, 237, 189, 15, 38, 12, 217, 167, 131, 39, 252, 130, 51, 222,
+ 251, 224, 124, 5, 158, 31, 120, 194, 95, 126, 192, 123, 31, 236, 167,
+ 192, 43, 216, 13, 127, 73, 99, 158, 236, 189, 15, 38, 12, 217, 167,
+ 131, 39, 252, 130, 113, 222, 251, 224, 64, 5, 158, 235, 101, 96, 33,
+ 173, 252, 155, 161, 255, 171, 15, 38, 12, 217, 167, 131, 39, 252, 232,
+ 92, 239, 247, 193, 209, 10, 188, 178, 151, 160, 43, 132, 25, 97, 242,
+ 218, 7, 19, 134, 108, 175, 192, 19, 126, 193, 50, 239, 125, 176, 69,
+ 129, 199, 192, 19, 126, 97, 45, 239, 125, 48, 83, 224, 145, 191, 34,
+ 124, 255, 143, 188, 247, 193, 132, 161, 244, 193, 132, 159, 191, 202, 123,
+ 31, 76, 126, 215, 237, 131, 227, 183, 96, 172, 65, 21, 125, 112, 136,
+ 199, 1, 151, 123, 39, 171, 112, 39, 116, 127, 11, 189, 131, 100, 242,
+ 141, 31, 224, 241, 193, 148, 47, 219, 192, 157, 34, 222, 5, 149, 247,
+ 62, 56, 66, 129, 87, 186, 3, 125, 68, 218, 101, 170, 194, 59, 89,
+ 59, 20, 54, 16, 60, 225, 151, 25, 188, 247, 193, 241, 10, 188, 11,
+ 219, 49, 31, 72, 231, 167, 84, 225, 157, 172, 237, 10, 27, 8, 158,
+ 240, 93, 39, 170, 240, 78, 150, 2, 207, 15, 60, 225, 251, 47, 244,
+ 222, 7, 251, 41, 240, 10, 182, 97, 172, 72, 71, 111, 241, 222, 7,
+ 19, 134, 108, 3, 193, 19, 190, 197, 207, 123, 31, 28, 168, 192, 115,
+ 189, 8, 123, 128, 116, 129, 206, 123, 31, 76, 24, 178, 13, 4, 79,
+ 248, 236, 33, 239, 125, 112, 180, 2, 175, 108, 43, 100, 75, 125, 20,
+ 188, 247, 193, 132, 33, 219, 64, 240, 132, 239, 119, 205, 123, 31, 108,
+ 81, 224, 49, 240, 132, 191, 252, 119, 239, 125, 48, 83, 224, 45, 127,
+ 1, 178, 69, 250, 194, 23, 222, 251, 96, 194, 144, 247, 53, 224, 9,
+ 223, 127, 128, 247, 62, 216, 95, 129, 87, 248, 60, 198, 138, 244, 242,
+ 169, 222, 251, 96, 194, 144, 237, 31, 120, 194, 47, 248, 192, 123, 31,
+ 28, 161, 192, 43, 45, 128, 253, 67, 186, 240, 128, 247, 251, 96, 194,
+ 144, 237, 31, 120, 194, 47, 60, 227, 253, 62, 56, 94, 129, 87, 248,
+ 28, 236, 31, 210, 249, 59, 189, 247, 193, 132, 33, 207, 31, 120, 194,
+ 247, 143, 244, 222, 7, 71, 40, 240, 200, 95, 17, 126, 254, 223, 222,
+ 251, 96, 194, 80, 250, 96, 194, 207, 63, 234, 189, 15, 38, 191, 43,
+ 191, 147, 181, 10, 99, 221, 85, 209, 7, 119, 187, 139, 15, 190, 176,
+ 25, 235, 125, 181, 68, 35, 61, 127, 123, 130, 242, 101, 31, 178, 89,
+ 250, 219, 37, 35, 189, 247, 193, 249, 10, 60, 63, 240, 132, 95, 214,
+ 198, 123, 31, 236, 167, 192, 43, 216, 132, 249, 35, 204, 137, 222, 251,
+ 96, 194, 144, 125, 8, 120, 194, 47, 235, 228, 189, 15, 14, 84, 224,
+ 185, 54, 98, 253, 34, 29, 253, 138, 247, 62, 152, 48, 100, 31, 2,
+ 158, 240, 11, 158, 245, 222, 7, 71, 43, 240, 202, 54, 192, 135, 32,
+ 237, 90, 234, 189, 15, 38, 12, 217, 135, 128, 39, 252, 252, 245, 222,
+ 251, 96, 139, 2, 143, 129, 39, 124, 86, 223, 251, 231, 193, 76, 129,
+ 183, 252, 89, 248, 16, 26, 115, 105, 121, 159, 254, 191, 248, 96, 194,
+ 144, 125, 8, 120, 194, 247, 111, 236, 189, 15, 246, 87, 224, 21, 174,
+ 135, 255, 64, 58, 240, 124, 21, 222, 201, 90, 175, 176, 129, 224, 9,
+ 63, 254, 163, 42, 188, 147, 165, 192, 43, 93, 7, 27, 136, 180, 95,
+ 191, 138, 250, 252, 159, 223, 201, 90, 167, 240, 33, 224, 9, 127, 249,
+ 132, 42, 188, 147, 165, 192, 187, 176, 22, 62, 4, 233, 248, 209, 85,
+ 120, 39, 107, 173, 194, 254, 129, 39, 252, 130, 29, 85, 120, 39, 75,
+ 129, 231, 7, 158, 240, 253, 166, 87, 225, 157, 44, 5, 94, 193, 26,
+ 172, 53, 164, 11, 83, 238, 42, 143, 251, 191, 147, 181, 70, 97, 255,
+ 192, 19, 126, 252, 51, 85, 120, 39, 75, 129, 231, 130, 111, 33, 124,
+ 139, 111, 21, 222, 201, 90, 173, 176, 127, 224, 9, 191, 224, 100, 21,
+ 222, 201, 90, 125, 199, 59, 89, 72, 251, 189, 84, 133, 119, 178, 86,
+ 41, 158, 7, 255, 138, 185, 219, 82, 209, 7, 119, 191, 139, 15, 182,
+ 144, 207, 254, 141, 158, 167, 154, 124, 3, 179, 60, 251, 96, 202, 151,
+ 251, 184, 74, 250, 187, 146, 185, 85, 120, 39, 75, 129, 183, 124, 37,
+ 228, 129, 116, 254, 212, 42, 188, 147, 181, 82, 97, 3, 193, 19, 126,
+ 129, 174, 10, 239, 100, 41, 240, 10, 87, 192, 30, 32, 29, 161, 247,
+ 140, 87, 243, 63, 250, 96, 194, 144, 109, 32, 120, 194, 47, 59, 85,
+ 133, 119, 178, 20, 120, 165, 203, 177, 222, 144, 46, 155, 91, 133, 119,
+ 178, 150, 43, 198, 123, 30, 99, 5, 158, 223, 134, 42, 60, 15, 62,
+ 175, 24, 47, 120, 194, 143, 46, 244, 254, 219, 164, 8, 5, 94, 233,
+ 159, 24, 239, 121, 250, 182, 203, 123, 31, 76, 24, 178, 205, 7, 79,
+ 248, 174, 106, 85, 120, 30, 172, 192, 187, 240, 7, 198, 139, 116, 105,
+ 104, 21, 158, 7, 255, 161, 176, 249, 224, 9, 191, 244, 159, 42, 60,
+ 15, 86, 224, 249, 129, 39, 252, 232, 159, 171, 240, 60, 88, 129, 87,
+ 112, 14, 107, 23, 105, 203, 71, 85, 120, 30, 124, 78, 97, 243, 193,
+ 19, 126, 89, 100, 21, 158, 7, 43, 240, 92, 103, 97, 11, 144, 142,
+ 78, 170, 194, 243, 224, 179, 10, 155, 15, 158, 240, 227, 223, 173, 194,
+ 243, 96, 5, 94, 217, 239, 208, 61, 164, 93, 129, 222, 251, 96, 194,
+ 144, 99, 94, 240, 132, 95, 118, 170, 10, 207, 131, 21, 120, 12, 60,
+ 225, 71, 188, 88, 133, 231, 193, 10, 188, 229, 240, 47, 132, 31, 223,
+ 185, 10, 207, 131, 127, 83, 216, 123, 240, 188, 143, 231, 170, 240, 60,
+ 248, 183, 59, 158, 7, 255, 70, 239, 24, 86, 225, 121, 240, 175, 30,
+ 31, 124, 97, 9, 250, 182, 170, 162, 15, 238, 113, 23, 31, 28, 65,
+ 62, 123, 41, 202, 211, 111, 9, 86, 247, 236, 131, 41, 95, 182, 129,
+ 191, 72, 62, 120, 88, 21, 158, 7, 255, 162, 176, 129, 224, 9, 191,
+ 192, 191, 10, 207, 131, 21, 120, 23, 126, 134, 189, 66, 186, 112, 156,
+ 247, 62, 152, 48, 100, 27, 8, 158, 240, 11, 218, 123, 191, 15, 206,
+ 87, 224, 249, 129, 231, 125, 220, 230, 189, 15, 246, 83, 224, 21, 252,
+ 4, 27, 72, 125, 92, 227, 189, 15, 38, 12, 217, 6, 130, 39, 252,
+ 252, 69, 222, 251, 224, 64, 5, 158, 235, 71, 204, 29, 210, 17, 171,
+ 189, 223, 7, 19, 134, 108, 3, 193, 19, 126, 252, 112, 239, 125, 112,
+ 180, 2, 175, 236, 7, 216, 63, 164, 45, 254, 169, 94, 239, 131, 9,
+ 67, 182, 129, 224, 9, 191, 236, 17, 239, 125, 176, 69, 129, 199, 126,
+ 160, 247, 157, 160, 51, 191, 123, 239, 131, 153, 2, 111, 249, 247, 24,
+ 43, 97, 158, 242, 222, 7, 19, 134, 108, 3, 193, 19, 190, 69, 239,
+ 253, 62, 216, 95, 129, 87, 248, 29, 98, 94, 164, 163, 199, 86, 225,
+ 189, 232, 239, 20, 49, 32, 120, 194, 47, 27, 94, 133, 247, 162, 21,
+ 120, 165, 101, 176, 45, 223, 209, 183, 118, 85, 120, 47, 186, 76, 97,
+ 255, 192, 19, 126, 105, 70, 21, 222, 139, 86, 224, 21, 46, 3, 22,
+ 210, 165, 51, 189, 223, 7, 19, 134, 60, 127, 224, 9, 223, 127, 190,
+ 247, 62, 56, 66, 129, 87, 10, 255, 66, 248, 129, 26, 239, 125, 48,
+ 97, 200, 243, 7, 158, 247, 241, 77, 239, 125, 112, 252, 210, 242, 62,
+ 152, 240, 3, 111, 123, 239, 131, 201, 239, 186, 125, 176, 101, 14, 198,
+ 251, 107, 69, 31, 220, 243, 46, 62, 56, 159, 124, 246, 28, 241, 61,
+ 209, 192, 111, 60, 62, 152, 242, 101, 31, 178, 68, 194, 27, 236, 189,
+ 15, 246, 83, 224, 21, 44, 134, 189, 95, 66, 127, 159, 59, 221, 107,
+ 31, 76, 24, 178, 15, 1, 79, 248, 150, 209, 222, 251, 224, 64, 5,
+ 158, 235, 25, 248, 144, 197, 244, 251, 198, 222, 251, 96, 194, 144, 125,
+ 8, 120, 194, 191, 112, 221, 123, 31, 28, 173, 192, 43, 91, 4, 31,
+ 130, 180, 255, 10, 239, 125, 48, 97, 200, 62, 4, 60, 225, 71, 204,
+ 243, 222, 7, 91, 20, 120, 12, 60, 225, 23, 220, 246, 222, 7, 51,
+ 5, 222, 242, 133, 144, 237, 34, 250, 190, 203, 251, 231, 193, 132, 33,
+ 251, 16, 240, 132, 191, 156, 165, 122, 189, 15, 246, 87, 224, 21, 46,
+ 0, 22, 210, 129, 121, 222, 251, 96, 194, 144, 109, 224, 2, 122, 214,
+ 143, 117, 252, 179, 247, 62, 56, 66, 129, 87, 58, 31, 88, 11, 40,
+ 206, 247, 222, 7, 19, 134, 108, 3, 193, 19, 254, 242, 108, 239, 125,
+ 112, 188, 2, 239, 194, 60, 248, 15, 234, 99, 174, 247, 62, 152, 48,
+ 228, 24, 26, 60, 225, 23, 12, 246, 222, 7, 231, 43, 240, 252, 192,
+ 19, 126, 217, 38, 239, 125, 176, 159, 2, 175, 224, 105, 216, 63, 164,
+ 151, 79, 243, 222, 7, 19, 134, 108, 255, 192, 19, 126, 180, 221, 123,
+ 31, 28, 168, 192, 115, 205, 197, 220, 33, 93, 54, 219, 123, 31, 76,
+ 24, 178, 253, 3, 79, 248, 241, 75, 188, 247, 193, 209, 10, 60, 242,
+ 87, 188, 143, 78, 239, 125, 48, 97, 40, 125, 48, 225, 23, 94, 246,
+ 222, 7, 147, 223, 157, 167, 192, 187, 176, 68, 233, 131, 179, 116, 105,
+ 169, 156, 85, 124, 153, 196, 109, 152, 88, 6, 117, 75, 175, 136, 84,
+ 152, 228, 241, 193, 76, 209, 199, 229, 179, 165, 119, 178, 108, 222, 251,
+ 96, 194, 144, 109, 32, 225, 1, 159, 37, 120, 191, 15, 246, 87, 224,
+ 21, 62, 5, 125, 70, 218, 47, 199, 123, 31, 76, 24, 50, 222, 109,
+ 216, 64, 224, 249, 247, 170, 194, 247, 193, 183, 21, 54, 21, 60, 225,
+ 151, 157, 174, 194, 189, 104, 5, 94, 233, 45, 224, 33, 29, 189, 187,
+ 10, 247, 162, 111, 41, 108, 42, 120, 194, 95, 190, 162, 10, 223, 7,
+ 43, 240, 46, 220, 132, 62, 33, 29, 255, 114, 21, 190, 15, 190, 169,
+ 176, 169, 224, 9, 191, 52, 166, 10, 223, 7, 43, 240, 252, 192, 19,
+ 126, 89, 231, 42, 124, 31, 172, 192, 43, 184, 1, 155, 138, 116, 116,
+ 72, 21, 190, 15, 190, 161, 176, 169, 224, 9, 63, 255, 139, 42, 124,
+ 31, 172, 192, 115, 253, 11, 123, 133, 116, 252, 215, 85, 248, 62, 248,
+ 95, 133, 77, 5, 79, 248, 254, 111, 84, 225, 251, 96, 5, 94, 217,
+ 117, 216, 212, 127, 233, 123, 54, 239, 125, 48, 97, 200, 49, 37, 120,
+ 194, 143, 159, 236, 189, 15, 182, 40, 240, 24, 120, 194, 47, 59, 234,
+ 189, 15, 102, 10, 188, 229, 215, 16, 83, 94, 39, 251, 226, 189, 15,
+ 38, 12, 217, 158, 130, 39, 124, 127, 135, 247, 247, 162, 253, 21, 120,
+ 133, 87, 97, 11, 174, 209, 239, 230, 85, 225, 157, 172, 171, 10, 251,
+ 7, 158, 240, 203, 90, 87, 225, 157, 44, 5, 30, 247, 85, 72, 199,
+ 255, 88, 133, 119, 178, 174, 220, 241, 78, 22, 240, 10, 190, 251, 223,
+ 125, 240, 192, 97, 35, 163, 106, 227, 252, 213, 245, 250, 108, 168, 91,
+ 190, 243, 76, 190, 42, 150, 207, 52, 72, 244, 27, 17, 25, 116, 35,
+ 138, 177, 65, 77, 69, 39, 76, 215, 199, 32, 115, 68, 228, 240, 254,
+ 191, 96, 209, 4, 152, 12, 217, 118, 22, 96, 177, 26, 50, 89, 64,
+ 146, 209, 106, 67, 2, 86, 210, 206, 178, 89, 14, 155, 206, 178, 88,
+ 118, 186, 209, 132, 3, 236, 112, 14, 113, 57, 196, 161, 82, 150, 81,
+ 143, 130, 198, 4, 102, 210, 165, 27, 38, 5, 119, 155, 204, 50, 108,
+ 44, 41, 77, 151, 204, 44, 58, 61, 163, 139, 70, 125, 66, 154, 57,
+ 49, 149, 80, 211, 12, 122, 12, 68, 44, 26, 212, 35, 112, 50, 179,
+ 155, 237, 44, 49, 195, 154, 105, 160, 35, 227, 229, 236, 57, 22, 3,
+ 179, 165, 152, 179, 82, 13, 57, 204, 98, 182, 81, 25, 67, 154, 33,
+ 157, 241, 11, 86, 116, 139, 99, 4, 88, 13, 73, 84, 130, 46, 217,
+ 236, 214, 73, 33, 193, 147, 69, 222, 56, 157, 131, 101, 234, 210, 152,
+ 212, 174, 209, 98, 70, 227, 86, 115, 58, 65, 81, 29, 91, 90, 134,
+ 213, 146, 194, 116, 137, 60, 21, 16, 96, 75, 180, 26, 45, 118, 27,
+ 10, 81, 191, 145, 45, 102, 80, 113, 137, 195, 8, 77, 6, 150, 102,
+ 48, 1, 19, 135, 0, 26, 1, 31, 165, 141, 153, 232, 146, 141, 137,
+ 199, 0, 180, 156, 198, 2, 108, 134, 180, 52, 234, 68, 34, 3, 151,
+ 200, 2, 50, 76, 122, 115, 92, 66, 70, 18, 227, 12, 13, 138, 51,
+ 28, 42, 209, 156, 110, 161, 137, 97, 188, 231, 54, 131, 33, 149, 233,
+ 173, 186, 172, 233, 102, 244, 55, 197, 156, 166, 103, 137, 105, 70, 139,
+ 13, 35, 166, 179, 193, 164, 103, 38, 131, 157, 146, 56, 81, 10, 24,
+ 54, 94, 129, 87, 71, 5, 51, 161, 74, 231, 32, 38, 246, 31, 157,
+ 195, 60, 192, 73, 165, 99, 54, 168, 31, 1, 233, 70, 75, 186, 206,
+ 50, 41, 8, 50, 48, 167, 50, 18, 116, 146, 149, 198, 68, 220, 180,
+ 12, 93, 154, 209, 158, 195, 236, 22, 93, 178, 129, 79, 9, 38, 34,
+ 193, 136, 198, 178, 173, 6, 11, 203, 161, 131, 61, 139, 250, 96, 207,
+ 162, 46, 208, 165, 68, 179, 222, 64, 50, 177, 240, 114, 1, 22, 93,
+ 98, 170, 65, 79, 2, 103, 118, 67, 118, 162, 153, 161, 49, 187, 116,
+ 52, 25, 146, 249, 44, 234, 185, 64, 3, 204, 9, 83, 13, 137, 152,
+ 97, 148, 99, 22, 171, 121, 170, 120, 204, 225, 199, 233, 84, 195, 66,
+ 191, 41, 99, 78, 178, 77, 10, 153, 204, 231, 136, 206, 40, 204, 59,
+ 150, 136, 113, 90, 211, 209, 118, 26, 179, 50, 192, 50, 76, 158, 33,
+ 41, 46, 19, 209, 7, 46, 37, 233, 18, 153, 201, 108, 165, 19, 114,
+ 232, 20, 144, 162, 51, 233, 209, 169, 0, 11, 151, 96, 128, 205, 78,
+ 103, 27, 179, 81, 95, 108, 84, 10, 50, 164, 163, 221, 74, 163, 177,
+ 101, 164, 161, 103, 137, 152, 26, 70, 74, 199, 149, 172, 67, 128, 222,
+ 108, 180, 119, 236, 208, 17, 92, 162, 46, 45, 45, 1, 67, 165, 84,
+ 166, 193, 106, 51, 154, 77, 76, 199, 160, 111, 124, 104, 188, 74, 80,
+ 143, 201, 152, 243, 116, 29, 169, 70, 130, 97, 18, 82, 72, 216, 39,
+ 117, 155, 140, 255, 197, 102, 209, 69, 196, 35, 57, 140, 174, 163, 73,
+ 36, 141, 54, 3, 151, 166, 61, 195, 154, 144, 1, 53, 22, 23, 125,
+ 162, 217, 100, 183, 210, 138, 228, 35, 73, 166, 67, 2, 29, 48, 203,
+ 118, 106, 123, 186, 65, 172, 170, 55, 88, 236, 41, 34, 203, 225, 209,
+ 158, 56, 87, 86, 179, 133, 47, 98, 98, 114, 220, 12, 95, 209, 98,
+ 14, 24, 18, 176, 65, 103, 231, 50, 166, 51, 108, 2, 73, 152, 235,
+ 134, 13, 66, 72, 2, 38, 179, 209, 124, 36, 25, 13, 113, 124, 88,
+ 152, 96, 76, 103, 90, 70, 178, 145, 43, 115, 2, 178, 12, 166, 76,
+ 170, 162, 207, 176, 210, 56, 49, 103, 36, 33, 190, 142, 179, 153, 193,
+ 100, 176, 38, 231, 48, 189, 17, 3, 177, 97, 162, 68, 173, 7, 195,
+ 85, 130, 165, 232, 140, 38, 59, 2, 52, 123, 16, 29, 130, 25, 148,
+ 85, 44, 161, 75, 183, 192, 42, 232, 244, 114, 29, 152, 108, 200, 205,
+ 12, 247, 14, 88, 172, 89, 126, 53, 69, 151, 102, 182, 217, 161, 159,
+ 1, 233, 200, 157, 212, 107, 50, 163, 153, 181, 89, 12, 137, 86, 126,
+ 76, 230, 199, 4, 150, 110, 180, 90, 233, 144, 76, 135, 4, 166, 75,
+ 79, 176, 210, 129, 115, 201, 116, 96, 134, 116, 250, 89, 95, 147, 88,
+ 1, 243, 206, 116, 105, 150, 20, 29, 131, 213, 225, 57, 108, 58, 77,
+ 6, 211, 233, 245, 44, 149, 132, 144, 2, 141, 195, 218, 213, 7, 241,
+ 99, 48, 31, 113, 48, 89, 8, 43, 202, 98, 169, 192, 20, 144, 133,
+ 72, 100, 86, 104, 51, 21, 231, 99, 224, 215, 197, 241, 101, 36, 120,
+ 114, 18, 204, 102, 18, 115, 114, 2, 172, 7, 214, 65, 156, 104, 18,
+ 33, 86, 190, 68, 226, 72, 227, 232, 156, 70, 115, 2, 43, 27, 68,
+ 170, 106, 194, 140, 27, 249, 47, 16, 179, 164, 20, 234, 102, 26, 173,
+ 170, 164, 20, 62, 209, 217, 57, 252, 34, 211, 231, 64, 221, 73, 22,
+ 162, 177, 238, 222, 125, 50, 231, 76, 25, 48, 87, 54, 40, 179, 129,
+ 219, 43, 115, 26, 228, 110, 201, 166, 67, 14, 29, 166, 51, 200, 146,
+ 40, 152, 217, 176, 32, 179, 57, 23, 0, 45, 230, 138, 141, 35, 230,
+ 141, 155, 94, 146, 42, 166, 158, 95, 130, 180, 9, 8, 22, 152, 214,
+ 171, 213, 108, 167, 83, 150, 81, 26, 46, 250, 171, 151, 116, 214, 158,
+ 130, 188, 20, 44, 31, 42, 72, 133, 116, 88, 183, 140, 86, 59, 105,
+ 78, 74, 16, 75, 193, 60, 6, 177, 36, 28, 67, 88, 138, 17, 157,
+ 167, 162, 180, 120, 184, 102, 233, 236, 113, 38, 43, 179, 152, 236, 182,
+ 12, 126, 204, 4, 182, 205, 156, 150, 33, 158, 50, 153, 217, 138, 134,
+ 50, 196, 83, 38, 55, 217, 25, 252, 8, 47, 151, 138, 133, 135, 90,
+ 226, 25, 233, 4, 244, 61, 193, 48, 221, 206, 76, 88, 119, 196, 102,
+ 194, 54, 113, 195, 4, 163, 37, 122, 41, 24, 54, 172, 173, 0, 114,
+ 27, 9, 228, 40, 205, 86, 216, 54, 202, 227, 174, 193, 144, 201, 27,
+ 197, 48, 245, 40, 133, 106, 65, 116, 192, 172, 193, 28, 26, 248, 188,
+ 19, 71, 230, 140, 116, 65, 92, 2, 41, 8, 46, 153, 168, 227, 217,
+ 230, 36, 150, 3, 10, 32, 235, 147, 164, 75, 55, 166, 229, 112, 135,
+ 26, 144, 153, 132, 165, 207, 103, 62, 145, 79, 44, 157, 116, 122, 43,
+ 183, 185, 48, 86, 92, 61, 144, 13, 11, 100, 39, 227, 67, 141, 90,
+ 117, 22, 172, 16, 123, 186, 206, 150, 202, 50, 131, 88, 102, 48, 203,
+ 12, 97, 153, 221, 152, 37, 195, 132, 235, 162, 185, 206, 200, 148, 150,
+ 39, 4, 69, 19, 106, 50, 115, 211, 138, 205, 12, 164, 104, 39, 219,
+ 29, 192, 93, 0, 150, 117, 90, 134, 157, 27, 86, 76, 117, 150, 129,
+ 91, 163, 0, 125, 22, 181, 41, 165, 48, 110, 76, 47, 169, 127, 34,
+ 7, 193, 145, 252, 113, 82, 18, 55, 237, 233, 88, 33, 64, 209, 139,
+ 39, 187, 120, 74, 231, 221, 13, 208, 139, 167, 116, 82, 150, 0, 120,
+ 114, 99, 98, 106, 14, 159, 115, 248, 69, 210, 139, 0, 51, 172, 182,
+ 45, 35, 221, 44, 89, 110, 180, 201, 235, 219, 210, 205, 102, 73, 117,
+ 176, 118, 244, 198, 76, 110, 63, 225, 46, 68, 253, 178, 39, 113, 109,
+ 200, 226, 81, 67, 6, 63, 102, 242, 99, 22, 154, 196, 26, 230, 209,
+ 11, 124, 143, 184, 18, 200, 174, 91, 164, 137, 196, 57, 136, 14, 193,
+ 116, 8, 161, 3, 173, 77, 41, 194, 128, 252, 161, 186, 228, 173, 172,
+ 180, 8, 3, 116, 226, 138, 11, 128, 75, 55, 144, 71, 206, 50, 91,
+ 185, 7, 74, 208, 33, 141, 160, 33, 9, 94, 64, 90, 2, 102, 88,
+ 113, 58, 235, 221, 62, 76, 47, 45, 10, 184, 91, 242, 7, 76, 239,
+ 102, 204, 9, 30, 15, 33, 182, 103, 52, 101, 74, 105, 76, 19, 196,
+ 106, 19, 165, 196, 205, 58, 4, 46, 250, 104, 234, 17, 231, 50, 44,
+ 238, 11, 89, 176, 201, 88, 215, 60, 137, 115, 166, 81, 172, 146, 96,
+ 206, 144, 188, 175, 62, 195, 130, 238, 211, 49, 41, 137, 78, 228, 212,
+ 113, 34, 75, 108, 75, 162, 31, 52, 135, 147, 132, 14, 97, 101, 195,
+ 214, 144, 226, 66, 111, 173, 118, 35, 204, 63, 220, 46, 228, 96, 135,
+ 241, 215, 103, 164, 167, 231, 196, 5, 49, 171, 187, 12, 13, 144, 108,
+ 162, 30, 58, 99, 207, 166, 120, 138, 132, 11, 127, 14, 11, 142, 104,
+ 197, 12, 31, 203, 125, 153, 57, 45, 13, 54, 128, 174, 99, 224, 148,
+ 155, 70, 161, 137, 197, 12, 125, 72, 72, 144, 103, 9, 142, 132, 151,
+ 33, 169, 37, 67, 88, 124, 4, 110, 38, 24, 38, 218, 104, 195, 138,
+ 48, 91, 140, 137, 3, 36, 3, 40, 42, 160, 9, 50, 35, 103, 2,
+ 147, 101, 20, 253, 108, 138, 25, 70, 31, 135, 100, 58, 36, 208, 33,
+ 149, 77, 55, 64, 165, 113, 72, 166, 67, 2, 29, 82, 201, 252, 167,
+ 98, 253, 217, 236, 146, 37, 52, 219, 50, 172, 6, 150, 108, 197, 252,
+ 33, 42, 34, 145, 19, 19, 101, 206, 30, 173, 211, 27, 17, 237, 218,
+ 82, 115, 56, 62, 218, 49, 242, 198, 104, 22, 233, 204, 87, 56, 49,
+ 41, 70, 238, 3, 172, 252, 152, 204, 143, 9, 252, 152, 202, 143, 162,
+ 7, 0, 3, 167, 44, 90, 5, 240, 50, 131, 94, 112, 103, 206, 244,
+ 8, 130, 72, 62, 230, 36, 146, 15, 78, 228, 195, 233, 4, 93, 78,
+ 129, 191, 162, 224, 1, 188, 17, 209, 0, 143, 8, 69, 183, 1, 229,
+ 77, 193, 82, 177, 200, 28, 133, 9, 8, 152, 16, 11, 162, 48, 50,
+ 37, 55, 2, 95, 142, 131, 17, 150, 28, 28, 14, 70, 186, 76, 37,
+ 105, 46, 177, 72, 147, 13, 38, 44, 59, 216, 126, 30, 125, 232, 210,
+ 81, 202, 150, 205, 108, 136, 91, 40, 28, 48, 208, 1, 222, 32, 25,
+ 125, 160, 104, 129, 135, 123, 60, 108, 16, 131, 230, 12, 30, 180, 24,
+ 244, 201, 134, 209, 252, 56, 144, 31, 163, 88, 18, 92, 15, 98, 84,
+ 3, 10, 101, 91, 200, 87, 231, 240, 99, 146, 213, 48, 141, 51, 52,
+ 30, 49, 166, 207, 182, 37, 166, 176, 28, 58, 100, 235, 96, 159, 114,
+ 232, 144, 77, 139, 214, 134, 58, 252, 100, 211, 37, 33, 226, 129, 118,
+ 147, 173, 135, 17, 54, 81, 160, 13, 20, 10, 204, 141, 233, 124, 54,
+ 160, 96, 92, 127, 220, 33, 174, 77, 178, 203, 220, 185, 115, 78, 111,
+ 22, 199, 102, 182, 65, 201, 173, 182, 56, 155, 65, 236, 54, 133, 37,
+ 192, 179, 167, 35, 32, 163, 179, 88, 138, 56, 138, 1, 232, 108, 20,
+ 179, 200, 59, 163, 25, 113, 127, 3, 173, 20, 153, 36, 106, 94, 100,
+ 211, 205, 153, 70, 137, 69, 0, 153, 110, 192, 196, 5, 192, 110, 32,
+ 210, 15, 160, 232, 74, 52, 29, 56, 82, 76, 19, 144, 108, 53, 103,
+ 88, 104, 43, 129, 101, 67, 122, 29, 144, 132, 42, 136, 176, 80, 24,
+ 162, 48, 154, 25, 223, 39, 136, 177, 19, 102, 138, 229, 80, 136, 111,
+ 37, 171, 203, 157, 14, 31, 52, 154, 203, 242, 88, 20, 74, 121, 236,
+ 137, 5, 43, 80, 97, 109, 200, 39, 203, 215, 168, 164, 219, 38, 209,
+ 21, 11, 207, 33, 151, 174, 75, 19, 57, 93, 14, 15, 188, 18, 17,
+ 212, 241, 173, 150, 206, 74, 150, 133, 161, 139, 188, 91, 201, 86, 35,
+ 109, 87, 200, 193, 129, 210, 179, 89, 58, 4, 154, 141, 109, 64, 142,
+ 153, 226, 23, 30, 140, 242, 179, 142, 199, 53, 57, 82, 58, 71, 74,
+ 147, 216, 101, 38, 135, 163, 137, 187, 44, 106, 60, 1, 30, 9, 151,
+ 160, 85, 217, 210, 25, 110, 35, 33, 25, 19, 14, 187, 203, 123, 168,
+ 103, 220, 181, 96, 153, 51, 238, 6, 129, 46, 70, 12, 217, 252, 100,
+ 52, 241, 62, 34, 201, 207, 80, 66, 216, 35, 150, 106, 64, 152, 133,
+ 77, 41, 157, 117, 60, 244, 227, 44, 47, 98, 53, 243, 86, 51, 131,
+ 245, 36, 0, 163, 157, 92, 45, 136, 130, 1, 84, 161, 20, 204, 31,
+ 84, 204, 142, 117, 202, 18, 225, 175, 48, 43, 140, 162, 43, 152, 24,
+ 62, 61, 36, 70, 218, 174, 225, 76, 243, 150, 14, 243, 148, 32, 30,
+ 205, 188, 211, 169, 22, 51, 0, 224, 251, 80, 129, 118, 56, 180, 101,
+ 165, 157, 176, 168, 4, 36, 213, 108, 126, 164, 189, 130, 53, 135, 199,
+ 152, 105, 226, 34, 231, 187, 60, 113, 187, 107, 225, 209, 25, 109, 189,
+ 210, 200, 130, 144, 191, 228, 219, 48, 163, 61, 77, 220, 159, 235, 141,
+ 86, 73, 39, 145, 63, 169, 23, 237, 0, 147, 40, 146, 182, 242, 16,
+ 195, 36, 45, 89, 88, 157, 180, 12, 132, 116, 180, 183, 151, 55, 238,
+ 86, 131, 157, 246, 213, 52, 38, 178, 131, 216, 1, 33, 39, 195, 106,
+ 74, 202, 48, 37, 210, 30, 40, 128, 174, 88, 152, 217, 108, 33, 33,
+ 217, 140, 124, 173, 5, 112, 179, 64, 198, 1, 195, 66, 199, 121, 100,
+ 193, 239, 203, 241, 208, 10, 61, 20, 21, 75, 148, 45, 133, 58, 113,
+ 80, 155, 180, 20, 49, 178, 176, 24, 179, 227, 160, 124, 113, 124, 3,
+ 110, 207, 182, 75, 114, 2, 71, 183, 152, 3, 44, 57, 113, 100, 234,
+ 56, 99, 200, 228, 174, 25, 28, 100, 96, 23, 253, 154, 232, 250, 116,
+ 153, 6, 238, 202, 236, 134, 116, 11, 13, 191, 7, 166, 129, 26, 114,
+ 243, 98, 56, 234, 78, 81, 175, 50, 220, 9, 218, 217, 32, 67, 153,
+ 180, 25, 166, 201, 201, 28, 123, 138, 217, 228, 78, 217, 72, 251, 221,
+ 9, 105, 63, 104, 147, 125, 149, 141, 235, 35, 95, 222, 100, 80, 56,
+ 3, 239, 174, 19, 23, 60, 95, 68, 220, 222, 219, 105, 147, 164, 207,
+ 22, 249, 28, 226, 115, 152, 184, 20, 196, 117, 192, 75, 98, 42, 69,
+ 179, 9, 134, 108, 40, 87, 35, 114, 247, 32, 93, 170, 157, 223, 153,
+ 201, 164, 72, 25, 209, 35, 246, 7, 136, 255, 2, 16, 0, 6, 32,
+ 2, 12, 224, 197, 3, 16, 119, 34, 224, 48, 100, 160, 233, 148, 105,
+ 48, 64, 70, 147, 148, 202, 154, 70, 24, 30, 155, 64, 5, 41, 224,
+ 68, 38, 157, 40, 41, 181, 195, 121, 131, 85, 50, 172, 118, 143, 193,
+ 193, 181, 108, 58, 228, 240, 18, 113, 182, 44, 4, 163, 156, 51, 144,
+ 221, 165, 43, 98, 30, 49, 98, 22, 93, 5, 4, 191, 117, 33, 178,
+ 124, 13, 113, 179, 7, 45, 163, 60, 90, 80, 201, 6, 113, 223, 141,
+ 138, 202, 36, 93, 38, 45, 232, 216, 33, 211, 108, 212, 75, 5, 202,
+ 103, 240, 225, 98, 178, 245, 50, 128, 156, 226, 253, 230, 234, 157, 97,
+ 228, 75, 72, 188, 141, 35, 121, 37, 218, 210, 192, 206, 113, 223, 64,
+ 235, 64, 186, 233, 67, 81, 99, 55, 178, 224, 54, 67, 16, 29, 130,
+ 233, 16, 194, 32, 13, 189, 217, 196, 111, 44, 96, 69, 114, 80, 210,
+ 7, 190, 200, 172, 217, 160, 28, 177, 42, 101, 144, 136, 160, 74, 162,
+ 156, 197, 35, 13, 26, 242, 230, 235, 145, 210, 112, 42, 144, 21, 114,
+ 68, 38, 93, 151, 152, 66, 203, 64, 220, 225, 243, 18, 124, 199, 101,
+ 32, 173, 195, 153, 124, 19, 133, 201, 220, 95, 138, 93, 224, 67, 225,
+ 183, 207, 96, 33, 147, 2, 249, 145, 119, 120, 154, 120, 228, 253, 158,
+ 22, 130, 192, 108, 154, 164, 135, 34, 99, 225, 55, 29, 209, 4, 44,
+ 10, 173, 38, 110, 101, 48, 26, 126, 203, 9, 97, 173, 184, 156, 16,
+ 86, 240, 190, 99, 203, 75, 55, 90, 40, 34, 68, 244, 74, 71, 132,
+ 167, 60, 80, 32, 51, 38, 37, 121, 52, 140, 184, 49, 81, 140, 235,
+ 40, 234, 48, 233, 16, 125, 144, 150, 138, 91, 122, 132, 120, 226, 54,
+ 144, 70, 194, 221, 14, 213, 225, 97, 111, 138, 49, 77, 79, 140, 168,
+ 151, 4, 139, 16, 131, 20, 132, 74, 82, 207, 176, 113, 16, 55, 254,
+ 48, 199, 54, 38, 25, 15, 19, 98, 46, 115, 22, 109, 216, 209, 65,
+ 88, 124, 222, 35, 244, 156, 239, 221, 41, 250, 183, 88, 13, 10, 239,
+ 71, 238, 221, 227, 39, 197, 158, 80, 21, 168, 165, 89, 12, 17, 204,
+ 180, 167, 33, 247, 193, 131, 44, 233, 182, 25, 122, 153, 158, 32, 174,
+ 107, 92, 12, 225, 251, 158, 100, 233, 204, 131, 209, 116, 76, 191, 45,
+ 205, 204, 55, 76, 220, 87, 100, 99, 71, 238, 137, 80, 41, 135, 162,
+ 91, 218, 96, 73, 230, 141, 16, 221, 60, 76, 1, 44, 64, 0, 217,
+ 68, 186, 141, 151, 68, 13, 33, 108, 227, 231, 116, 115, 134, 205, 16,
+ 135, 136, 194, 16, 103, 53, 112, 67, 72, 119, 123, 232, 10, 212, 206,
+ 150, 102, 148, 78, 113, 162, 109, 149, 18, 8, 219, 36, 206, 144, 35,
+ 115, 114, 94, 10, 65, 80, 85, 210, 118, 27, 2, 65, 152, 116, 140,
+ 54, 93, 202, 166, 218, 18, 135, 218, 110, 78, 206, 75, 193, 254, 134,
+ 240, 109, 8, 12, 245, 54, 66, 181, 81, 35, 6, 202, 51, 80, 158,
+ 129, 242, 12, 200, 75, 162, 114, 73, 84, 46, 137, 202, 37, 241, 114,
+ 54, 125, 10, 56, 58, 80, 141, 36, 170, 145, 68, 53, 146, 168, 6,
+ 228, 71, 141, 227, 200, 121, 3, 231, 169, 150, 137, 208, 77, 132, 110,
+ 202, 2, 161, 54, 229, 36, 81, 78, 18, 114, 146, 40, 199, 12, 95,
+ 23, 20, 220, 11, 138, 135, 64, 138, 51, 220, 253, 137, 89, 70, 41,
+ 75, 188, 241, 141, 164, 196, 137, 158, 211, 76, 62, 131, 132, 164, 75,
+ 163, 57, 98, 208, 69, 76, 8, 229, 75, 215, 113, 129, 79, 150, 24,
+ 0, 199, 97, 30, 40, 0, 21, 79, 113, 146, 42, 74, 41, 110, 108,
+ 168, 42, 221, 59, 227, 53, 137, 129, 30, 27, 249, 125, 56, 126, 206,
+ 145, 90, 71, 236, 153, 38, 222, 99, 19, 91, 140, 147, 235, 208, 21,
+ 44, 26, 40, 53, 178, 220, 146, 15, 72, 164, 37, 225, 185, 245, 200,
+ 232, 230, 113, 0, 15, 41, 2, 192, 114, 134, 246, 233, 226, 182, 132,
+ 116, 151, 124, 121, 0, 48, 41, 130, 225, 102, 152, 14, 193, 244, 248,
+ 34, 217, 96, 31, 225, 222, 24, 219, 205, 201, 201, 105, 6, 57, 137,
+ 74, 25, 34, 135, 30, 43, 19, 88, 17, 70, 93, 154, 92, 142, 22,
+ 56, 173, 53, 43, 221, 69, 75, 163, 157, 3, 236, 53, 67, 56, 15,
+ 61, 52, 80, 104, 79, 27, 66, 121, 247, 141, 234, 50, 79, 101, 196,
+ 200, 129, 34, 160, 145, 226, 253, 97, 104, 60, 157, 121, 129, 4, 179,
+ 62, 71, 220, 179, 103, 164, 65, 213, 105, 179, 64, 243, 66, 203, 3,
+ 203, 58, 64, 60, 27, 77, 60, 252, 163, 139, 193, 140, 246, 239, 162,
+ 132, 211, 115, 96, 118, 113, 209, 146, 97, 231, 143, 22, 108, 98, 105,
+ 68, 77, 33, 244, 36, 64, 76, 209, 196, 128, 232, 214, 142, 190, 59,
+ 183, 24, 124, 171, 47, 198, 217, 60, 72, 53, 98, 59, 79, 251, 7,
+ 216, 88, 61, 197, 75, 201, 220, 32, 83, 130, 143, 208, 125, 63, 36,
+ 88, 230, 96, 98, 77, 122, 184, 135, 0, 30, 36, 96, 188, 169, 134,
+ 68, 179, 5, 145, 28, 191, 243, 170, 167, 251, 14, 250, 73, 65, 212,
+ 65, 3, 173, 243, 113, 20, 80, 163, 5, 50, 31, 60, 156, 229, 19,
+ 194, 173, 167, 116, 63, 129, 243, 210, 45, 4, 90, 222, 58, 180, 226,
+ 169, 131, 201, 206, 72, 187, 35, 75, 175, 55, 232, 43, 43, 105, 182,
+ 167, 24, 172, 212, 60, 172, 30, 249, 113, 168, 14, 78, 100, 233, 41,
+ 32, 231, 113, 28, 140, 32, 120, 169, 101, 200, 221, 205, 33, 38, 16,
+ 123, 64, 55, 167, 68, 142, 180, 203, 106, 4, 0, 221, 24, 129, 117,
+ 139, 131, 54, 197, 5, 201, 28, 221, 20, 53, 235, 220, 185, 30, 30,
+ 106, 103, 142, 134, 70, 200, 250, 19, 96, 55, 75, 162, 39, 113, 199,
+ 144, 86, 39, 195, 10, 39, 98, 2, 210, 176, 103, 226, 240, 180, 129,
+ 21, 109, 59, 111, 94, 230, 225, 45, 165, 4, 114, 185, 167, 161, 28,
+ 206, 240, 108, 49, 11, 222, 139, 130, 94, 8, 150, 159, 3, 232, 168,
+ 75, 179, 241, 93, 25, 109, 29, 233, 44, 62, 21, 9, 224, 55, 78,
+ 249, 237, 40, 242, 60, 196, 208, 253, 77, 29, 127, 162, 68, 30, 0,
+ 110, 147, 223, 11, 193, 58, 147, 166, 134, 183, 195, 239, 251, 240, 172,
+ 32, 73, 144, 65, 242, 53, 145, 35, 31, 238, 174, 65, 188, 52, 137,
+ 238, 193, 72, 0, 138, 71, 6, 226, 141, 92, 43, 53, 75, 12, 38,
+ 128, 223, 54, 166, 4, 73, 73, 7, 149, 32, 85, 162, 187, 136, 210,
+ 189, 150, 0, 186, 217, 194, 55, 147, 20, 211, 27, 249, 67, 138, 0,
+ 76, 60, 221, 183, 7, 182, 123, 52, 124, 103, 66, 207, 190, 232, 44,
+ 46, 92, 189, 24, 61, 195, 185, 26, 164, 123, 79, 110, 221, 163, 218,
+ 18, 47, 173, 58, 186, 65, 79, 119, 12, 161, 229, 113, 162, 138, 103,
+ 154, 177, 129, 32, 189, 54, 153, 248, 95, 5, 176, 67, 165, 50, 68,
+ 185, 89, 232, 109, 92, 210, 158, 184, 100, 56, 64, 146, 152, 200, 144,
+ 238, 232, 232, 54, 131, 180, 123, 226, 235, 114, 82, 207, 201, 76, 188,
+ 106, 182, 160, 9, 171, 251, 182, 147, 152, 114, 171, 50, 51, 97, 183,
+ 66, 237, 218, 248, 34, 69, 239, 229, 12, 10, 192, 177, 66, 41, 114,
+ 10, 72, 38, 91, 199, 183, 108, 201, 210, 131, 39, 158, 195, 111, 228,
+ 209, 83, 72, 138, 51, 184, 43, 231, 174, 151, 162, 70, 126, 79, 84,
+ 103, 76, 163, 51, 162, 29, 143, 36, 224, 174, 61, 9, 186, 249, 98,
+ 47, 23, 74, 40, 2, 139, 4, 132, 132, 28, 52, 145, 30, 111, 136,
+ 240, 6, 91, 16, 29, 184, 129, 8, 225, 227, 21, 227, 47, 29, 177,
+ 208, 69, 126, 66, 175, 96, 50, 12, 38, 190, 214, 165, 199, 47, 210,
+ 189, 68, 108, 117, 68, 69, 73, 227, 61, 11, 128, 242, 64, 138, 180,
+ 50, 104, 254, 40, 60, 225, 83, 109, 35, 195, 41, 26, 116, 190, 170,
+ 166, 211, 146, 158, 158, 46, 190, 77, 19, 51, 33, 186, 255, 139, 244,
+ 188, 159, 158, 94, 100, 240, 35, 182, 155, 88, 10, 25, 226, 137, 98,
+ 147, 52, 51, 100, 151, 193, 143, 124, 177, 98, 222, 51, 48, 195, 140,
+ 2, 107, 54, 140, 2, 146, 97, 16, 90, 20, 245, 29, 17, 83, 176,
+ 141, 31, 141, 252, 152, 196, 143, 180, 13, 79, 12, 225, 57, 33, 60,
+ 39, 132, 231, 116, 227, 57, 221, 120, 78, 55, 172, 83, 204, 63, 29,
+ 146, 216, 224, 126, 64, 76, 176, 234, 16, 42, 15, 198, 150, 122, 168,
+ 33, 39, 138, 239, 107, 193, 176, 49, 124, 159, 203, 91, 141, 193, 38,
+ 109, 24, 137, 148, 24, 22, 205, 159, 55, 14, 32, 119, 220, 87, 188,
+ 165, 50, 152, 111, 58, 249, 35, 207, 193, 233, 81, 25, 73, 108, 56,
+ 10, 50, 201, 162, 16, 27, 205, 31, 89, 17, 215, 55, 170, 31, 185,
+ 203, 190, 244, 44, 49, 10, 129, 42, 235, 111, 202, 28, 14, 87, 58,
+ 140, 172, 196, 120, 236, 29, 217, 112, 201, 185, 177, 113, 3, 232, 78,
+ 60, 63, 242, 58, 195, 17, 36, 247, 167, 232, 154, 152, 40, 29, 84,
+ 38, 138, 84, 46, 202, 156, 205, 162, 12, 211, 99, 208, 91, 244, 40,
+ 42, 218, 76, 51, 57, 130, 158, 42, 244, 229, 143, 17, 162, 233, 41,
+ 2, 70, 39, 166, 134, 15, 160, 152, 128, 31, 7, 163, 92, 140, 152,
+ 236, 103, 160, 123, 172, 227, 197, 232, 33, 138, 54, 21, 82, 214, 56,
+ 114, 107, 195, 197, 35, 250, 204, 134, 143, 17, 111, 154, 15, 167, 133,
+ 60, 50, 113, 48, 180, 5, 93, 183, 35, 211, 192, 134, 209, 200, 19,
+ 196, 122, 3, 249, 93, 132, 132, 72, 241, 150, 117, 66, 52, 221, 178,
+ 30, 70, 49, 249, 120, 126, 243, 105, 52, 191, 157, 196, 5, 57, 154,
+ 47, 32, 62, 192, 49, 124, 91, 42, 86, 29, 128, 13, 145, 52, 187,
+ 81, 3, 233, 70, 203, 56, 236, 218, 67, 250, 241, 83, 112, 63, 54,
+ 134, 66, 27, 18, 25, 103, 162, 200, 191, 114, 110, 12, 188, 51, 103,
+ 184, 120, 16, 65, 65, 117, 33, 92, 158, 53, 146, 238, 20, 136, 21,
+ 185, 188, 56, 203, 37, 58, 22, 110, 19, 253, 102, 9, 99, 196, 125,
+ 24, 78, 124, 200, 56, 247, 215, 83, 201, 68, 107, 36, 118, 112, 140,
+ 64, 7, 166, 153, 19, 32, 156, 49, 180, 225, 225, 210, 224, 156, 36,
+ 97, 222, 60, 118, 153, 252, 246, 101, 127, 186, 109, 3, 85, 238, 47,
+ 62, 153, 136, 202, 192, 114, 7, 15, 129, 88, 237, 238, 179, 49, 17,
+ 221, 36, 177, 83, 134, 56, 117, 152, 167, 244, 4, 54, 56, 85, 199,
+ 202, 117, 120, 140, 33, 141, 244, 172, 31, 162, 195, 145, 38, 140, 147,
+ 98, 50, 236, 104, 232, 18, 230, 23, 206, 140, 54, 199, 44, 97, 4,
+ 60, 238, 24, 110, 140, 89, 194, 112, 10, 216, 221, 137, 24, 51, 22,
+ 157, 59, 1, 253, 78, 48, 235, 172, 122, 119, 218, 93, 223, 157, 238,
+ 235, 54, 222, 238, 12, 8, 204, 131, 59, 26, 122, 107, 78, 247, 164,
+ 228, 106, 208, 10, 27, 102, 214, 157, 244, 160, 185, 111, 192, 179, 132,
+ 254, 217, 216, 6, 217, 8, 154, 114, 209, 50, 191, 169, 33, 242, 145,
+ 210, 205, 121, 112, 122, 189, 184, 122, 20, 89, 92, 149, 60, 233, 49,
+ 164, 251, 119, 36, 1, 143, 57, 191, 179, 38, 87, 43, 79, 210, 61,
+ 86, 79, 206, 157, 21, 160, 87, 158, 132, 168, 132, 138, 180, 188, 149,
+ 242, 228, 113, 149, 245, 36, 197, 249, 241, 164, 165, 105, 145, 51, 198,
+ 136, 254, 59, 97, 140, 232, 198, 196, 190, 147, 101, 163, 231, 213, 146,
+ 30, 243, 225, 112, 92, 178, 69, 98, 15, 137, 227, 89, 238, 88, 37,
+ 146, 60, 4, 61, 47, 224, 11, 172, 175, 116, 23, 80, 154, 42, 119,
+ 146, 227, 185, 23, 162, 167, 247, 80, 2, 88, 180, 116, 218, 203, 42,
+ 51, 99, 232, 201, 78, 140, 89, 153, 53, 218, 76, 78, 121, 152, 49,
+ 213, 160, 204, 29, 134, 64, 177, 98, 238, 0, 114, 219, 89, 100, 114,
+ 42, 32, 136, 34, 119, 231, 177, 152, 97, 253, 71, 168, 152, 138, 169,
+ 241, 207, 71, 250, 87, 3, 254, 161, 6, 254, 249, 240, 163, 31, 171,
+ 141, 127, 141, 113, 246, 99, 254, 252, 24, 200, 202, 88, 52, 107, 202,
+ 236, 224, 27, 48, 61, 40, 141, 249, 243, 151, 153, 162, 217, 110, 245,
+ 78, 22, 173, 106, 204, 22, 168, 178, 217, 65, 214, 141, 249, 169, 34,
+ 112, 101, 16, 155, 139, 171, 97, 168, 19, 200, 126, 229, 229, 106, 163,
+ 214, 32, 28, 207, 169, 136, 163, 150, 232, 207, 147, 15, 67, 78, 103,
+ 22, 129, 84, 182, 234, 28, 235, 128, 242, 53, 52, 11, 52, 253, 192,
+ 181, 97, 139, 85, 22, 148, 41, 96, 11, 24, 33, 174, 102, 155, 88,
+ 44, 107, 160, 166, 214, 27, 179, 175, 80, 47, 2, 189, 184, 128, 252,
+ 166, 232, 85, 99, 92, 101, 172, 23, 35, 140, 77, 64, 44, 21, 191,
+ 187, 69, 235, 53, 144, 26, 196, 82, 64, 157, 113, 45, 141, 193, 243,
+ 160, 55, 249, 232, 65, 24, 48, 194, 128, 86, 67, 21, 1, 132, 97,
+ 44, 27, 165, 155, 2, 163, 27, 40, 13, 184, 84, 127, 53, 242, 44,
+ 170, 6, 168, 81, 128, 178, 139, 89, 60, 80, 196, 127, 62, 104, 115,
+ 76, 204, 232, 190, 203, 80, 238, 33, 204, 229, 67, 252, 172, 98, 181,
+ 192, 215, 228, 164, 1, 190, 56, 203, 106, 86, 141, 213, 145, 231, 187,
+ 26, 171, 11, 222, 23, 156, 47, 248, 135, 193, 139, 51, 95, 13, 189,
+ 208, 200, 101, 124, 88, 117, 86, 15, 105, 119, 57, 95, 164, 235, 35,
+ 237, 46, 91, 3, 233, 71, 100, 9, 138, 229, 169, 100, 3, 126, 244,
+ 212, 241, 197, 191, 71, 121, 29, 79, 189, 26, 200, 107, 40, 73, 222,
+ 7, 61, 245, 65, 207, 125, 208, 243, 70, 188, 30, 93, 173, 9, 122,
+ 8, 84, 11, 163, 172, 129, 20, 3, 169, 192, 215, 102, 77, 48, 18,
+ 198, 71, 64, 61, 247, 67, 141, 122, 200, 171, 142, 107, 245, 65, 143,
+ 224, 90, 3, 16, 181, 216, 144, 95, 123, 76, 186, 70, 232, 141, 192,
+ 169, 81, 90, 141, 92, 186, 246, 56, 80, 31, 71, 233, 199, 129, 237,
+ 139, 35, 225, 169, 33, 3, 53, 107, 6, 106, 206, 203, 212, 100, 45,
+ 144, 83, 155, 99, 60, 14, 125, 100, 172, 37, 242, 91, 161, 124, 107,
+ 96, 182, 1, 82, 91, 92, 107, 39, 213, 105, 15, 234, 0, 234, 136,
+ 84, 53, 228, 7, 128, 239, 4, 234, 12, 234, 194, 241, 154, 35, 191,
+ 57, 80, 154, 243, 183, 227, 186, 34, 239, 9, 80, 32, 90, 169, 195,
+ 219, 96, 44, 8, 233, 96, 80, 8, 240, 187, 161, 92, 119, 80, 15,
+ 164, 123, 130, 122, 225, 122, 111, 156, 251, 128, 66, 209, 183, 48, 244,
+ 136, 230, 62, 28, 164, 149, 234, 137, 125, 110, 137, 249, 33, 60, 177,
+ 95, 52, 46, 1, 20, 129, 126, 71, 130, 162, 64, 125, 65, 253, 64,
+ 253, 65, 3, 64, 3, 65, 131, 248, 120, 154, 177, 193, 24, 97, 125,
+ 169, 63, 143, 98, 164, 67, 48, 210, 161, 160, 97, 192, 24, 46, 225,
+ 141, 0, 141, 4, 69, 131, 70, 129, 70, 131, 198, 128, 98, 64, 99,
+ 209, 143, 113, 160, 241, 232, 95, 44, 16, 27, 34, 111, 2, 104, 34,
+ 104, 18, 232, 73, 204, 216, 100, 204, 214, 20, 224, 199, 209, 27, 213,
+ 244, 198, 52, 40, 1, 125, 72, 4, 233, 81, 198, 0, 74, 2, 159,
+ 12, 74, 1, 25, 65, 83, 65, 169, 160, 52, 80, 58, 200, 132, 217,
+ 174, 203, 251, 88, 147, 153, 233, 77, 86, 208, 52, 180, 107, 5, 217,
+ 144, 103, 71, 153, 12, 80, 38, 40, 11, 121, 217, 200, 203, 193, 121,
+ 58, 159, 167, 142, 92, 63, 149, 248, 51, 184, 30, 248, 112, 201, 85,
+ 147, 198, 73, 125, 39, 189, 153, 137, 242, 179, 32, 205, 218, 188, 239,
+ 173, 88, 46, 40, 15, 229, 243, 165, 57, 126, 74, 158, 91, 31, 54,
+ 27, 52, 71, 154, 171, 17, 24, 103, 107, 62, 151, 190, 176, 74, 190,
+ 236, 105, 208, 60, 208, 124, 208, 2, 208, 66, 208, 34, 208, 51, 40,
+ 187, 24, 180, 4, 180, 84, 106, 219, 141, 187, 12, 180, 28, 180, 2,
+ 180, 18, 121, 171, 64, 171, 65, 107, 64, 79, 128, 214, 130, 214, 129,
+ 214, 131, 158, 149, 230, 102, 3, 151, 37, 245, 179, 3, 219, 136, 241,
+ 108, 66, 223, 55, 227, 250, 22, 104, 99, 83, 133, 110, 60, 199, 231,
+ 89, 13, 11, 83, 113, 174, 159, 7, 189, 0, 218, 10, 122, 17, 180,
+ 13, 180, 29, 180, 3, 229, 119, 130, 118, 41, 244, 233, 37, 208, 203,
+ 160, 221, 200, 223, 3, 122, 5, 173, 239, 149, 245, 169, 11, 159, 197,
+ 250, 60, 221, 21, 250, 43, 182, 79, 237, 22, 222, 209, 238, 62, 208,
+ 126, 208, 1, 208, 65, 208, 171, 160, 215, 64, 135, 64, 135, 65, 175,
+ 131, 142, 128, 138, 64, 197, 160, 18, 144, 3, 228, 4, 185, 64, 111,
+ 128, 142, 130, 142, 1, 251, 77, 232, 195, 113, 208, 9, 200, 227, 57,
+ 208, 91, 200, 59, 9, 122, 27, 244, 14, 232, 93, 148, 123, 15, 116,
+ 10, 244, 62, 232, 3, 122, 91, 22, 180, 7, 244, 33, 232, 35, 148,
+ 57, 13, 250, 24, 117, 63, 145, 117, 216, 61, 174, 174, 236, 12, 234,
+ 124, 10, 250, 12, 244, 57, 232, 11, 208, 151, 40, 243, 21, 168, 30,
+ 31, 247, 19, 176, 95, 226, 58, 250, 26, 244, 13, 174, 127, 43, 201,
+ 182, 57, 95, 245, 180, 62, 130, 96, 179, 130, 248, 202, 87, 73, 50,
+ 41, 148, 202, 148, 221, 97, 75, 191, 3, 125, 15, 250, 1, 244, 35,
+ 232, 39, 208, 207, 160, 39, 64, 191, 112, 157, 246, 133, 191, 243, 101,
+ 191, 193, 18, 136, 235, 63, 132, 253, 14, 59, 114, 22, 116, 78, 234,
+ 243, 31, 18, 246, 159, 40, 111, 64, 217, 243, 124, 189, 249, 194, 151,
+ 249, 178, 139, 160, 191, 64, 127, 195, 242, 144, 13, 254, 7, 116, 9,
+ 101, 47, 131, 174, 128, 174, 162, 151, 215, 232, 5, 111, 208, 191, 160,
+ 27, 176, 78, 212, 183, 155, 82, 185, 91, 160, 107, 160, 27, 176, 88,
+ 245, 65, 12, 228, 30, 211, 109, 158, 47, 182, 205, 84, 106, 166, 2,
+ 169, 65, 26, 144, 15, 168, 26, 168, 58, 200, 87, 5, 31, 0, 170,
+ 169, 234, 206, 30, 82, 117, 99, 181, 84, 61, 177, 226, 60, 99, 169,
+ 173, 162, 177, 180, 99, 117, 84, 237, 88, 93, 21, 141, 169, 23, 123,
+ 88, 5, 47, 172, 162, 177, 213, 98, 245, 80, 183, 190, 74, 57, 46,
+ 31, 110, 75, 30, 81, 209, 152, 197, 246, 27, 224, 250, 163, 160, 134,
+ 160, 70, 138, 126, 208, 90, 234, 6, 34, 95, 208, 24, 215, 154, 128,
+ 30, 3, 61, 14, 106, 10, 106, 6, 106, 14, 195, 221, 2, 228, 175,
+ 122, 130, 181, 84, 245, 70, 191, 122, 115, 171, 172, 98, 238, 254, 54,
+ 98, 173, 64, 173, 85, 162, 175, 105, 131, 115, 91, 80, 59, 80, 123,
+ 80, 7, 149, 91, 254, 110, 31, 231, 195, 58, 170, 200, 159, 244, 129,
+ 174, 104, 88, 128, 74, 195, 58, 129, 58, 131, 186, 160, 157, 174, 160,
+ 219, 104, 225, 9, 156, 253, 96, 245, 201, 103, 6, 168, 124, 80, 198,
+ 7, 101, 124, 42, 41, 19, 198, 113, 3, 113, 45, 8, 109, 5, 243,
+ 60, 198, 66, 84, 226, 90, 239, 166, 18, 125, 68, 119, 85, 77, 214,
+ 67, 21, 206, 125, 126, 79, 180, 223, 75, 165, 133, 62, 10, 72, 135,
+ 179, 222, 40, 211, 7, 20, 138, 216, 132, 244, 47, 76, 129, 115, 27,
+ 43, 222, 7, 231, 25, 160, 100, 250, 210, 0, 100, 132, 5, 32, 31,
+ 26, 174, 234, 139, 113, 121, 100, 165, 85, 185, 245, 206, 45, 159, 154,
+ 76, 64, 187, 17, 160, 72, 96, 71, 169, 4, 214, 87, 21, 201, 250,
+ 169, 162, 88, 127, 212, 29, 192, 101, 215, 143, 13, 196, 245, 65, 104,
+ 191, 29, 104, 176, 234, 78, 61, 85, 179, 33, 210, 28, 14, 229, 50,
+ 245, 101, 195, 80, 111, 184, 170, 191, 228, 67, 61, 250, 53, 130, 151,
+ 99, 108, 36, 250, 30, 13, 26, 5, 106, 198, 215, 73, 119, 54, 90,
+ 229, 238, 215, 0, 30, 35, 145, 157, 31, 195, 231, 166, 29, 139, 81,
+ 13, 68, 222, 64, 122, 231, 157, 251, 233, 177, 42, 242, 169, 237, 96,
+ 203, 61, 118, 115, 28, 202, 142, 7, 197, 130, 38, 160, 208, 68, 232,
+ 227, 36, 208, 147, 178, 78, 210, 28, 12, 98, 147, 85, 131, 217, 20,
+ 94, 95, 156, 143, 56, 62, 39, 181, 88, 60, 159, 143, 33, 76, 39,
+ 233, 106, 2, 206, 137, 42, 113, 140, 122, 149, 184, 30, 13, 56, 39,
+ 129, 146, 65, 41, 32, 163, 202, 151, 199, 142, 110, 251, 48, 21, 237,
+ 166, 130, 210, 64, 233, 32, 19, 198, 107, 6, 89, 64, 211, 64, 86,
+ 144, 13, 100, 7, 101, 128, 50, 81, 63, 11, 148, 13, 202, 1, 77,
+ 7, 205, 0, 205, 4, 205, 2, 229, 130, 242, 128, 147, 15, 122, 10,
+ 244, 39, 198, 62, 91, 69, 118, 172, 22, 155, 131, 126, 207, 5, 61,
+ 13, 154, 199, 229, 51, 128, 205, 7, 45, 64, 157, 133, 192, 94, 4,
+ 122, 6, 124, 16, 230, 99, 49, 104, 137, 74, 180, 71, 75, 81, 126,
+ 153, 106, 40, 188, 143, 199, 230, 23, 72, 62, 98, 57, 202, 175, 0,
+ 173, 4, 173, 2, 173, 6, 173, 1, 173, 5, 173, 3, 173, 87, 137,
+ 118, 255, 117, 201, 246, 63, 11, 204, 13, 200, 219, 8, 218, 4, 218,
+ 140, 54, 183, 112, 189, 246, 101, 207, 33, 93, 0, 122, 30, 244, 2,
+ 104, 43, 232, 69, 208, 54, 208, 118, 208, 14, 208, 78, 208, 46, 208,
+ 75, 168, 243, 50, 104, 55, 104, 15, 232, 21, 21, 217, 119, 146, 27,
+ 217, 118, 26, 239, 48, 62, 191, 123, 113, 173, 16, 180, 79, 210, 183,
+ 253, 56, 31, 0, 29, 4, 189, 10, 122, 13, 116, 8, 116, 24, 244,
+ 58, 48, 142, 0, 187, 8, 84, 12, 42, 81, 13, 199, 90, 29, 142,
+ 25, 28, 14, 29, 34, 153, 249, 192, 158, 251, 112, 28, 7, 202, 59,
+ 85, 20, 71, 140, 224, 54, 199, 165, 18, 125, 247, 27, 56, 31, 5,
+ 29, 227, 237, 137, 114, 122, 19, 116, 28, 116, 2, 244, 22, 232, 36,
+ 174, 189, 13, 122, 7, 244, 46, 232, 61, 80, 56, 234, 158, 194, 249,
+ 125, 208, 7, 160, 82, 208, 135, 160, 143, 64, 167, 97, 139, 62, 6,
+ 125, 2, 254, 12, 232, 83, 208, 103, 160, 207, 65, 95, 128, 190, 148,
+ 236, 194, 87, 56, 127, 13, 250, 6, 244, 45, 168, 140, 143, 1, 62,
+ 7, 244, 61, 232, 7, 208, 143, 208, 137, 159, 64, 63, 131, 126, 1,
+ 253, 170, 26, 201, 119, 63, 245, 177, 54, 126, 131, 140, 127, 71, 250,
+ 172, 138, 98, 14, 232, 56, 198, 255, 135, 42, 154, 253, 73, 250, 173,
+ 162, 241, 143, 98, 23, 160, 55, 23, 85, 195, 216, 95, 92, 127, 70,
+ 192, 126, 208, 92, 143, 134, 189, 162, 58, 20, 15, 186, 109, 44, 108,
+ 9, 249, 33, 156, 255, 65, 95, 46, 129, 46, 3, 227, 138, 106, 12,
+ 34, 153, 49, 244, 93, 9, 159, 211, 171, 184, 126, 13, 116, 29, 244,
+ 47, 232, 6, 232, 38, 201, 159, 124, 17, 234, 220, 150, 100, 199, 212,
+ 226, 252, 171, 212, 176, 245, 32, 13, 200, 71, 45, 206, 49, 197, 191,
+ 213, 212, 240, 175, 32, 95, 181, 24, 127, 158, 87, 209, 120, 176, 51,
+ 66, 153, 154, 160, 135, 64, 181, 64, 181, 65, 117, 64, 117, 65, 15,
+ 83, 125, 80, 61, 80, 125, 208, 35, 168, 219, 0, 244, 168, 122, 52,
+ 107, 168, 30, 195, 26, 169, 99, 96, 143, 26, 193, 174, 208, 190, 163,
+ 33, 107, 172, 110, 200, 154, 128, 30, 67, 153, 199, 65, 77, 65, 205,
+ 64, 205, 81, 183, 5, 200, 31, 212, 18, 212, 74, 61, 22, 241, 192,
+ 88, 178, 58, 210, 24, 125, 88, 107, 96, 181, 81, 215, 100, 109, 213,
+ 181, 88, 59, 181, 103, 207, 209, 30, 229, 59, 128, 58, 130, 2, 212,
+ 180, 175, 17, 125, 78, 39, 240, 157, 213, 62, 124, 127, 20, 170, 162,
+ 62, 140, 67, 140, 60, 14, 152, 227, 36, 76, 236, 71, 80, 166, 43,
+ 199, 133, 223, 83, 139, 117, 8, 43, 16, 237, 4, 225, 28, 140, 105,
+ 11, 1, 117, 3, 223, 29, 212, 67, 77, 243, 175, 102, 61, 193, 247,
+ 2, 245, 86, 147, 157, 25, 15, 29, 31, 15, 220, 241, 114, 95, 63,
+ 97, 30, 204, 191, 201, 143, 168, 99, 209, 126, 44, 202, 196, 202, 101,
+ 234, 33, 146, 10, 5, 94, 24, 240, 195, 65, 90, 144, 160, 22, 237,
+ 106, 132, 90, 92, 107, 145, 56, 71, 129, 250, 226, 90, 63, 156, 251,
+ 171, 41, 6, 87, 179, 1, 56, 15, 68, 31, 7, 225, 60, 88, 61,
+ 17, 154, 54, 17, 216, 19, 21, 216, 212, 126, 45, 54, 68, 26, 207,
+ 80, 181, 219, 223, 210, 184, 38, 129, 159, 132, 242, 147, 238, 40, 223,
+ 138, 13, 83, 139, 250, 214, 71, 45, 174, 7, 170, 59, 28, 52, 130,
+ 250, 133, 113, 55, 151, 108, 64, 103, 245, 147, 168, 243, 36, 48, 158,
+ 148, 49, 70, 170, 91, 176, 104, 140, 103, 20, 104, 52, 205, 29, 151,
+ 129, 15, 27, 3, 138, 1, 238, 88, 200, 125, 28, 104, 60, 250, 29,
+ 11, 154, 0, 154, 168, 158, 44, 237, 97, 177, 39, 66, 185, 39, 49,
+ 206, 201, 160, 41, 160, 56, 80, 60, 72, 7, 74, 0, 37, 130, 244,
+ 192, 53, 168, 197, 125, 105, 18, 202, 207, 82, 77, 65, 63, 196, 189,
+ 109, 50, 198, 155, 2, 50, 170, 71, 178, 169, 40, 147, 10, 74, 3,
+ 165, 131, 76, 32, 51, 201, 10, 52, 13, 100, 5, 217, 56, 14, 252,
+ 2, 206, 25, 234, 56, 196, 112, 113, 124, 39, 166, 2, 101, 170, 107,
+ 179, 44, 174, 59, 241, 88, 9, 241, 124, 119, 70, 249, 217, 40, 151,
+ 131, 242, 159, 168, 220, 251, 110, 29, 116, 80, 199, 119, 110, 158, 235,
+ 113, 108, 58, 104, 134, 122, 10, 155, 137, 178, 179, 64, 185, 160, 60,
+ 80, 62, 230, 225, 41, 204, 65, 107, 85, 67, 54, 27, 231, 57, 200,
+ 155, 11, 122, 26, 52, 15, 227, 187, 10, 123, 50, 31, 252, 2, 208,
+ 66, 164, 23, 129, 158, 1, 45, 6, 45, 65, 222, 82, 208, 50, 208,
+ 114, 181, 40, 203, 21, 152, 195, 149, 160, 85, 160, 213, 160, 53, 160,
+ 181, 152, 131, 117, 160, 245, 234, 4, 126, 103, 225, 89, 148, 221, 160,
+ 38, 187, 231, 195, 54, 170, 19, 249, 157, 166, 77, 106, 218, 203, 38,
+ 178, 205, 72, 111, 1, 61, 167, 22, 247, 105, 5, 106, 26, 147, 30,
+ 179, 169, 71, 41, 61, 143, 91, 155, 75, 251, 43, 146, 211, 243, 40,
+ 251, 2, 250, 178, 21, 229, 95, 4, 109, 227, 229, 13, 252, 206, 203,
+ 118, 181, 123, 255, 73, 251, 78, 218, 95, 138, 123, 79, 113, 223, 89,
+ 83, 218, 119, 38, 33, 218, 79, 162, 111, 11, 129, 157, 196, 118, 160,
+ 142, 251, 94, 134, 184, 215, 19, 239, 5, 236, 4, 238, 46, 208, 75,
+ 160, 151, 65, 187, 65, 123, 64, 175, 128, 246, 146, 29, 195, 60, 238,
+ 3, 237, 7, 191, 30, 253, 60, 128, 126, 29, 228, 54, 129, 100, 79,
+ 123, 117, 236, 153, 112, 253, 53, 181, 1, 251, 190, 36, 118, 72, 157,
+ 196, 14, 131, 94, 199, 188, 28, 81, 39, 99, 31, 81, 139, 21, 113,
+ 190, 22, 43, 150, 215, 6, 141, 37, 5, 215, 82, 120, 68, 167, 82,
+ 220, 55, 40, 225, 243, 109, 196, 220, 25, 121, 164, 87, 241, 154, 184,
+ 255, 88, 143, 29, 99, 11, 16, 3, 221, 89, 134, 246, 176, 14, 244,
+ 201, 9, 114, 161, 223, 111, 128, 218, 163, 205, 163, 72, 31, 3, 189,
+ 9, 58, 14, 58, 1, 122, 11, 116, 18, 244, 54, 232, 29, 208, 187,
+ 160, 247, 64, 167, 64, 239, 3, 235, 3, 80, 41, 232, 67, 208, 71,
+ 160, 211, 100, 131, 89, 42, 251, 88, 157, 134, 246, 210, 232, 219, 240,
+ 74, 219, 79, 69, 253, 116, 208, 39, 106, 49, 246, 63, 131, 243, 167,
+ 160, 207, 164, 182, 62, 231, 125, 75, 135, 76, 218, 177, 47, 164, 121,
+ 41, 31, 227, 81, 236, 133, 253, 29, 202, 125, 5, 250, 26, 244, 141,
+ 90, 220, 31, 215, 99, 38, 72, 216, 132, 182, 77, 60, 14, 166, 249,
+ 248, 86, 186, 78, 123, 211, 50, 181, 47, 143, 133, 190, 83, 155, 185,
+ 55, 168, 207, 177, 197, 54, 190, 71, 91, 63, 64, 22, 63, 162, 204,
+ 79, 160, 159, 65, 191, 128, 126, 5, 253, 6, 250, 29, 116, 22, 116,
+ 142, 203, 152, 98, 76, 101, 159, 124, 216, 31, 232, 243, 104, 156, 255,
+ 196, 156, 158, 87, 91, 88, 109, 126, 23, 196, 82, 110, 14, 242, 85,
+ 180, 247, 242, 236, 37, 47, 0, 239, 162, 186, 49, 251, 11, 237, 254,
+ 173, 158, 134, 40, 100, 26, 191, 115, 34, 218, 51, 178, 201, 62, 236,
+ 31, 201, 14, 94, 194, 249, 50, 232, 138, 218, 227, 15, 175, 130, 174,
+ 129, 174, 131, 254, 5, 221, 0, 221, 4, 221, 2, 221, 6, 193, 193,
+ 50, 21, 72, 13, 210, 128, 124, 64, 213, 64, 213, 65, 190, 160, 26,
+ 160, 154, 160, 135, 64, 181, 64, 181, 65, 117, 64, 117, 65, 15, 131,
+ 252, 64, 245, 64, 245, 65, 143, 128, 26, 128, 30, 5, 53, 4, 53,
+ 2, 53, 6, 53, 1, 61, 6, 122, 28, 212, 20, 212, 12, 212, 28,
+ 212, 2, 228, 15, 106, 169, 97, 172, 21, 168, 53, 168, 13, 168, 173,
+ 198, 202, 218, 129, 218, 107, 124, 88, 7, 80, 71, 80, 0, 168, 19,
+ 168, 179, 198, 151, 117, 1, 117, 5, 61, 129, 186, 129, 160, 32, 80,
+ 48, 40, 68, 99, 99, 221, 64, 221, 193, 247, 0, 245, 212, 208, 90,
+ 105, 195, 122, 105, 200, 7, 217, 177, 154, 232, 99, 89, 187, 180, 79,
+ 16, 231, 188, 55, 202, 244, 1, 133, 106, 196, 249, 167, 253, 86, 24,
+ 202, 135, 107, 50, 48, 255, 84, 78, 212, 27, 45, 202, 8, 28, 47,
+ 147, 239, 65, 220, 242, 162, 123, 13, 125, 212, 89, 124, 159, 53, 22,
+ 251, 132, 8, 141, 91, 207, 178, 177, 70, 225, 27, 129, 27, 165, 17,
+ 203, 247, 197, 216, 250, 129, 250, 107, 114, 248, 189, 64, 113, 127, 67,
+ 245, 24, 27, 128, 252, 129, 154, 233, 168, 35, 166, 7, 161, 206, 96,
+ 208, 219, 146, 108, 251, 168, 103, 200, 253, 25, 130, 54, 134, 74, 253,
+ 29, 166, 153, 201, 191, 114, 31, 171, 162, 53, 234, 195, 134, 107, 102,
+ 49, 95, 169, 220, 80, 92, 24, 1, 26, 169, 17, 49, 62, 65, 123,
+ 209, 154, 92, 148, 111, 199, 70, 33, 127, 52, 104, 140, 38, 15, 125,
+ 200, 67, 141, 60, 89, 15, 123, 75, 216, 49, 56, 143, 5, 141, 211,
+ 184, 199, 233, 222, 95, 229, 179, 241, 26, 113, 237, 197, 226, 218, 4,
+ 62, 47, 79, 241, 121, 157, 168, 153, 141, 51, 249, 216, 124, 172, 157,
+ 124, 250, 141, 3, 70, 95, 29, 79, 210, 120, 230, 236, 73, 9, 147,
+ 218, 153, 172, 81, 115, 63, 62, 69, 227, 198, 158, 3, 236, 60, 22,
+ 135, 252, 120, 144, 14, 216, 9, 154, 185, 124, 239, 155, 168, 17, 247,
+ 124, 95, 168, 159, 198, 218, 31, 196, 244, 10, 76, 7, 48, 156, 106,
+ 81, 174, 6, 228, 39, 97, 142, 146, 113, 78, 1, 133, 34, 207, 136,
+ 243, 84, 205, 60, 126, 199, 157, 202, 167, 106, 220, 117, 230, 179, 52,
+ 9, 39, 29, 103, 19, 200, 172, 89, 192, 239, 117, 39, 202, 248, 212,
+ 102, 95, 102, 209, 136, 243, 58, 13, 249, 86, 210, 123, 182, 144, 223,
+ 123, 108, 38, 223, 223, 38, 187, 78, 241, 232, 34, 46, 95, 63, 46,
+ 99, 183, 124, 9, 227, 25, 172, 121, 119, 190, 47, 179, 161, 143, 118,
+ 141, 184, 167, 188, 32, 237, 43, 105, 31, 153, 129, 188, 76, 80, 22,
+ 218, 203, 214, 44, 150, 251, 220, 236, 142, 113, 126, 34, 221, 239, 204,
+ 65, 95, 166, 107, 150, 192, 238, 83, 27, 162, 221, 156, 129, 250, 99,
+ 84, 100, 215, 220, 122, 130, 189, 163, 102, 41, 90, 17, 211, 111, 75,
+ 54, 107, 22, 242, 115, 65, 121, 160, 124, 205, 50, 254, 132, 226, 254,
+ 109, 209, 94, 97, 57, 183, 82, 164, 115, 79, 65, 46, 179, 65, 115,
+ 128, 49, 23, 244, 52, 215, 187, 21, 92, 15, 231, 97, 220, 243, 185,
+ 174, 33, 94, 208, 136, 58, 72, 122, 52, 70, 51, 7, 109, 205, 161,
+ 159, 116, 129, 126, 204, 41, 167, 31, 164, 23, 11, 53, 158, 189, 252,
+ 23, 234, 81, 252, 62, 9, 237, 131, 23, 1, 255, 25, 208, 98, 208,
+ 18, 141, 15, 223, 23, 44, 5, 191, 12, 180, 92, 67, 235, 110, 37,
+ 250, 41, 238, 115, 190, 80, 123, 48, 87, 0, 115, 37, 214, 245, 42,
+ 13, 237, 133, 17, 135, 128, 95, 163, 169, 197, 218, 171, 250, 178, 181,
+ 154, 190, 108, 29, 174, 175, 215, 136, 251, 187, 103, 53, 226, 30, 239,
+ 21, 201, 103, 210, 62, 127, 161, 74, 121, 239, 115, 8, 235, 194, 219,
+ 168, 201, 54, 160, 205, 141, 146, 12, 55, 225, 188, 25, 180, 5, 244,
+ 28, 168, 0, 244, 188, 70, 148, 237, 11, 56, 111, 213, 136, 99, 120,
+ 17, 231, 109, 160, 237, 160, 29, 154, 242, 247, 84, 119, 34, 189, 11,
+ 125, 123, 73, 211, 149, 189, 140, 185, 219, 13, 106, 135, 118, 246, 104,
+ 220, 253, 236, 203, 94, 65, 255, 246, 130, 10, 53, 140, 235, 151, 251,
+ 30, 195, 62, 169, 223, 52, 134, 253, 224, 15, 0, 235, 32, 232, 85,
+ 140, 249, 53, 62, 214, 249, 210, 30, 144, 238, 195, 175, 98, 135, 52,
+ 116, 79, 179, 38, 59, 172, 33, 127, 133, 189, 59, 202, 30, 1, 21,
+ 129, 138, 65, 37, 32, 7, 200, 169, 161, 231, 21, 140, 185, 208, 222,
+ 27, 154, 213, 210, 115, 26, 95, 118, 20, 215, 142, 129, 222, 68, 91,
+ 199, 65, 39, 52, 107, 176, 46, 215, 160, 228, 154, 59, 98, 118, 113,
+ 141, 61, 39, 173, 187, 242, 49, 58, 233, 195, 90, 96, 174, 69, 189,
+ 181, 220, 6, 137, 251, 107, 248, 120, 21, 233, 192, 186, 255, 235, 236,
+ 92, 114, 26, 134, 129, 48, 236, 104, 186, 235, 138, 75, 112, 6, 164,
+ 74, 89, 32, 144, 96, 211, 75, 32, 245, 58, 221, 181, 168, 105, 120,
+ 174, 56, 73, 161, 45, 239, 247, 155, 2, 226, 28, 124, 191, 39, 9,
+ 1, 177, 234, 98, 148, 100, 60, 246, 216, 227, 177, 199, 254, 103, 17,
+ 124, 160, 79, 89, 159, 178, 94, 24, 153, 199, 227, 133, 80, 143, 173,
+ 117, 60, 103, 30, 140, 230, 47, 54, 243, 131, 189, 28, 216, 102, 208,
+ 233, 45, 64, 73, 244, 169, 102, 56, 196, 255, 27, 197, 121, 254, 8,
+ 187, 142, 173, 23, 38, 150, 114, 119, 74, 145, 75, 145, 75, 233, 79,
+ 51, 76, 139, 253, 226, 24, 27, 157, 64, 167, 133, 191, 42, 62, 44,
+ 213, 176, 164, 178, 143, 245, 190, 157, 33, 127, 14, 93, 64, 151, 166,
+ 76, 129, 235, 187, 66, 223, 181, 249, 30, 114, 195, 243, 22, 186, 179,
+ 1, 235, 99, 160, 223, 139, 196, 188, 98, 55, 113, 61, 37, 14, 215,
+ 137, 109, 122, 140, 104, 37, 235, 81, 230, 222, 50, 74, 50, 234, 100,
+ 124, 203, 110, 101, 189, 82, 110, 173, 26, 163, 100, 31, 208, 241, 104,
+ 67, 244, 40, 127, 58, 172, 238, 166, 79, 166, 57, 212, 28, 11, 63,
+ 115, 204, 68, 247, 177, 86, 146, 227, 11, 57, 178, 57, 178, 90, 199,
+ 210, 225, 254, 234, 241, 197, 109, 243, 204, 248, 54, 160, 23, 232, 21,
+ 122, 179, 45, 90, 94, 12, 51, 222, 223, 25, 219, 7, 54, 252, 180,
+ 237, 130, 167, 126, 53, 216, 203, 197, 219, 169, 120, 126, 119, 22, 111,
+ 247, 31, 222, 94, 156, 183, 153, 237, 71, 92, 254, 119, 206, 146, 115,
+ 28, 122, 190, 108, 181, 189, 178, 172, 60, 240, 55, 121, 216, 88, 60, };
+
+ *dataSize = 138801;
+
+ // allocate a new array
+ *data = new unsigned char[138801];
+ // and copy it. Now we are certain that the calling function
+ // can control the memory location
+ for(int i = 0; i < 138801 /* tmp array size */; i++)
+ {
+ (*data)[i] = load_blend[i];
+ }
+
+}
+
+
+
diff --git a/source/gameengine/GamePlayer/common/GPC_RawLoadDotBlendArray.h b/source/gameengine/GamePlayer/common/GPC_RawLoadDotBlendArray.h
new file mode 100644
index 00000000000..b82d24c5705
--- /dev/null
+++ b/source/gameengine/GamePlayer/common/GPC_RawLoadDotBlendArray.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 *****
+ */
+
+#ifndef __GPC_RAWLOADDOTBLENDARRAY_H
+#define __GPC_RAWLOADDOTBLENDARRAY_H
+
+
+void GetRawLoadingAnimation(unsigned char **data, int *dataSize);
+
+
+#endif // __GPC_RAWLOADDOTBLENDARRAY_H
diff --git a/source/gameengine/GamePlayer/common/GPC_RawLogoArrays.cpp b/source/gameengine/GamePlayer/common/GPC_RawLogoArrays.cpp
new file mode 100644
index 00000000000..0afb241408e
--- /dev/null
+++ b/source/gameengine/GamePlayer/common/GPC_RawLogoArrays.cpp
@@ -0,0 +1,1462 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+// This file is automatically generated. Do not edit by hand!
+
+
+
+#include "GPC_RawLogoArrays.h"
+
+
+void GetRawBlenderLogo(unsigned char **data, int *width, int *height)
+{
+ // create an array that will automatically be deleted when)
+ // we're outta this scope
+ static unsigned char logo_blender_raw[]= { 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 20, 20, 20, 21, 44, 44, 44,
+ 45, 26, 26, 26, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 12, 12, 12, 124,
+ 124, 124, 124, 232, 232, 232, 232, 248, 248, 248, 248, 243, 243, 243, 243,
+ 160, 160, 160, 160, 44, 44, 44, 44, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 13, 13, 13, 13, 172, 172, 172, 173, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 235,
+ 235, 235, 235, 95, 95, 95, 95, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 88, 88, 88,
+ 255, 255, 255, 255, 255, 255, 255, 255, 254, 235, 217, 255, 253, 202, 152,
+ 255, 253, 216, 183, 255, 255, 250, 246, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 155, 155, 155, 155, 20, 20, 20, 20, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, 255, 255, 255, 255, 255,
+ 249, 245, 255, 250, 162, 78, 255, 250, 145, 40, 255, 250, 149, 49, 255,
+ 251, 175, 104, 255, 254, 236, 219, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 202, 202, 202, 203, 53, 53, 53, 53, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 113, 113, 113, 113, 255, 255, 255, 255, 255, 253, 253, 255, 251, 196,
+ 147, 255, 249, 150, 51, 255, 249, 152, 55, 255, 248, 149, 50, 255, 249,
+ 160, 74, 255, 253, 219, 192, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 236, 236, 236, 236, 90, 90, 90, 90, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 11, 11, 11, 76, 76,
+ 76, 76, 120, 120, 120, 120, 138, 138, 138, 138, 167, 167, 167, 167, 167,
+ 167, 167, 167, 167, 167, 167, 167, 163, 163, 163, 164, 196, 196, 196, 198,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 252, 206, 166,
+ 255, 248, 153, 61, 255, 247, 149, 52, 255, 247, 150, 53, 255, 247, 150,
+ 54, 255, 251, 196, 150, 255, 255, 249, 246, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 143, 143, 143, 143, 14, 14, 14, 14, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 43, 43, 43, 42, 198, 198, 198, 199, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 226, 203, 255,
+ 248, 165, 85, 255, 246, 150, 53, 255, 246, 151, 55, 255, 246, 145, 46,
+ 255, 248, 175, 106, 255, 253, 238, 226, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 189, 189, 189, 189, 39, 39, 39, 39, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 22, 22, 22, 22, 214, 214, 214, 216, 255,
+ 255, 255, 255, 255, 255, 255, 255, 252, 245, 238, 255, 251, 233, 218, 255,
+ 251, 231, 215, 255, 251, 232, 216, 255, 251, 232, 216, 255, 252, 232, 216,
+ 255, 252, 232, 216, 255, 252, 232, 216, 255, 252, 232, 216, 255, 252, 232,
+ 216, 255, 252, 232, 217, 255, 252, 236, 223, 255, 251, 214, 186, 255, 245,
+ 156, 72, 255, 245, 150, 54, 255, 245, 151, 56, 255, 245, 146, 48, 255,
+ 246, 159, 76, 255, 252, 223, 198, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 226, 226, 226, 226, 71, 71, 71, 71, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 93, 93, 93, 93, 255, 255, 255, 255, 253, 253, 252, 255, 248, 209,
+ 173, 255, 244, 155, 66, 255, 244, 152, 62, 255, 245, 152, 62, 255, 245,
+ 153, 62, 255, 245, 153, 62, 255, 245, 152, 62, 255, 245, 152, 62, 255,
+ 245, 152, 62, 255, 245, 152, 62, 255, 245, 152, 62, 255, 245, 152, 62,
+ 255, 245, 153, 62, 255, 245, 155, 66, 255, 244, 152, 62, 255, 244, 150,
+ 56, 255, 244, 150, 57, 255, 244, 150, 56, 255, 243, 146, 49, 255, 243,
+ 147, 54, 255, 249, 203, 162, 255, 254, 253, 254, 255, 255, 255, 255, 255,
+ 248, 248, 248, 248, 143, 143, 143, 143, 120, 120, 120, 120, 120, 120, 120,
+ 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120,
+ 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120,
+ 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120,
+ 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120,
+ 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120,
+ 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120,
+ 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120,
+ 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120,
+ 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120,
+ 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 119, 119, 119, 120, 119,
+ 119, 119, 120, 119, 119, 119, 120, 119, 119, 119, 120, 119, 119, 119, 120,
+ 119, 119, 119, 120, 119, 119, 119, 120, 119, 119, 119, 120, 119, 119, 119,
+ 120, 119, 119, 119, 120, 119, 119, 119, 120, 119, 119, 119, 120, 119, 119,
+ 119, 120, 119, 119, 119, 120, 119, 119, 119, 120, 119, 119, 119, 120, 119,
+ 119, 119, 120, 119, 119, 119, 120, 119, 119, 119, 120, 118, 118, 118, 120,
+ 118, 118, 118, 120, 118, 118, 118, 120, 118, 118, 118, 120, 118, 118, 118,
+ 120, 118, 118, 118, 119, 118, 118, 118, 119, 118, 118, 118, 120, 118, 118,
+ 118, 119, 111, 111, 111, 112, 75, 75, 75, 75, 20, 20, 20, 20, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 125, 125, 125, 126,
+ 255, 255, 255, 255, 250, 242, 234, 255, 242, 149, 57, 255, 242, 142, 42,
+ 255, 243, 146, 48, 255, 243, 146, 48, 255, 243, 146, 48, 255, 243, 145,
+ 48, 255, 243, 145, 48, 255, 243, 147, 51, 255, 244, 149, 55, 255, 244,
+ 149, 55, 255, 243, 149, 54, 255, 243, 149, 54, 255, 243, 149, 55, 255,
+ 243, 148, 52, 255, 243, 146, 49, 255, 243, 146, 49, 255, 243, 146, 49,
+ 255, 243, 147, 52, 255, 242, 149, 55, 255, 242, 147, 52, 255, 241, 142,
+ 45, 255, 246, 181, 122, 255, 252, 244, 238, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 223, 223, 223, 223, 102, 102, 102, 102, 12, 12,
+ 12, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 109, 109, 109, 110, 255, 255, 255, 255, 251,
+ 251, 250, 255, 245, 194, 149, 255, 243, 166, 90, 255, 243, 167, 95, 255,
+ 243, 168, 96, 255, 243, 168, 96, 255, 244, 168, 96, 255, 244, 173, 105,
+ 255, 244, 164, 89, 255, 242, 148, 55, 255, 242, 149, 56, 255, 242, 149,
+ 56, 255, 242, 148, 54, 255, 241, 143, 46, 255, 242, 149, 58, 255, 244,
+ 165, 90, 255, 244, 172, 102, 255, 244, 169, 96, 255, 242, 154, 69, 255,
+ 241, 142, 45, 255, 241, 146, 50, 255, 241, 147, 54, 255, 240, 141, 42,
+ 255, 243, 166, 94, 255, 251, 237, 226, 255, 254, 255, 255, 255, 253, 253,
+ 253, 255, 253, 253, 253, 255, 254, 254, 254, 255, 225, 232, 238, 255, 215,
+ 224, 231, 255, 246, 247, 249, 255, 255, 254, 254, 255, 253, 253, 253, 255,
+ 253, 253, 253, 255, 253, 253, 253, 255, 253, 253, 253, 255, 253, 253, 253,
+ 255, 253, 253, 253, 255, 253, 253, 253, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 254, 254, 254, 255, 253, 253, 253, 255, 253,
+ 253, 253, 255, 253, 253, 253, 255, 253, 253, 253, 255, 253, 253, 253, 255,
+ 253, 253, 253, 255, 253, 253, 253, 255, 253, 253, 253, 255, 253, 253, 253,
+ 255, 253, 253, 253, 255, 253, 253, 253, 255, 253, 253, 253, 255, 253, 253,
+ 253, 255, 253, 253, 253, 255, 253, 253, 253, 255, 253, 253, 253, 255, 253,
+ 253, 253, 255, 253, 253, 253, 255, 253, 253, 253, 255, 253, 253, 253, 255,
+ 253, 253, 253, 255, 253, 253, 253, 255, 253, 253, 253, 255, 253, 253, 253,
+ 255, 252, 252, 252, 255, 252, 252, 252, 255, 252, 252, 252, 255, 253, 253,
+ 253, 255, 255, 254, 253, 255, 244, 246, 247, 255, 208, 220, 229, 255, 234,
+ 238, 241, 255, 253, 253, 253, 255, 252, 252, 252, 255, 251, 251, 251, 255,
+ 251, 251, 251, 255, 251, 251, 251, 255, 251, 251, 251, 255, 251, 251, 251,
+ 255, 251, 251, 251, 255, 251, 251, 251, 255, 250, 250, 250, 255, 250, 250,
+ 250, 255, 250, 250, 250, 255, 250, 250, 250, 255, 250, 250, 250, 255, 250,
+ 250, 250, 255, 249, 249, 249, 255, 249, 249, 249, 255, 253, 253, 252, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 184, 183, 183, 182, 25, 25, 25,
+ 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 45, 45, 45, 45, 244, 244, 244, 248, 255, 255, 255, 255, 250, 252,
+ 254, 255, 250, 247, 246, 255, 250, 248, 246, 255, 250, 248, 246, 255, 250,
+ 249, 248, 255, 251, 254, 255, 255, 249, 230, 214, 255, 243, 167, 95, 255,
+ 241, 145, 50, 255, 241, 148, 56, 255, 241, 145, 51, 255, 241, 148, 56,
+ 255, 245, 182, 123, 255, 249, 227, 209, 255, 255, 253, 250, 255, 255, 255,
+ 254, 255, 255, 255, 254, 255, 253, 241, 232, 255, 246, 195, 152, 255, 241,
+ 155, 72, 255, 240, 142, 45, 255, 240, 147, 54, 255, 240, 141, 43, 255,
+ 242, 161, 86, 255, 250, 233, 222, 255, 252, 255, 255, 255, 252, 252, 253,
+ 255, 255, 255, 255, 255, 154, 181, 201, 255, 8, 78, 129, 255, 70, 124,
+ 161, 255, 249, 249, 250, 255, 255, 255, 254, 255, 253, 253, 253, 255, 253,
+ 253, 253, 255, 253, 253, 253, 255, 253, 253, 253, 255, 253, 253, 253, 255,
+ 254, 254, 254, 255, 213, 226, 233, 255, 119, 159, 186, 255, 127, 167, 191,
+ 255, 245, 247, 249, 255, 254, 254, 254, 255, 252, 252, 253, 255, 252, 252,
+ 252, 255, 253, 253, 253, 255, 255, 255, 254, 255, 255, 254, 254, 255, 253,
+ 253, 253, 255, 252, 252, 252, 255, 253, 253, 253, 255, 253, 253, 253, 255,
+ 253, 253, 253, 255, 252, 252, 252, 255, 252, 252, 252, 255, 252, 252, 252,
+ 255, 252, 252, 252, 255, 252, 252, 252, 255, 253, 253, 253, 255, 252, 252,
+ 252, 255, 252, 252, 252, 255, 252, 252, 252, 255, 252, 252, 252, 255, 252,
+ 252, 252, 255, 252, 252, 252, 255, 252, 252, 252, 255, 252, 252, 252, 255,
+ 252, 252, 252, 255, 252, 252, 252, 255, 255, 255, 255, 255, 206, 218, 228,
+ 255, 38, 105, 148, 255, 13, 91, 139, 255, 202, 213, 222, 255, 255, 255,
+ 255, 255, 251, 251, 251, 255, 251, 251, 251, 255, 251, 251, 251, 255, 253,
+ 252, 252, 255, 253, 252, 252, 255, 251, 251, 251, 255, 250, 250, 250, 255,
+ 250, 250, 250, 255, 250, 250, 250, 255, 250, 250, 250, 255, 249, 249, 249,
+ 255, 249, 249, 249, 255, 249, 249, 249, 255, 249, 249, 249, 255, 250, 250,
+ 249, 255, 252, 252, 251, 255, 228, 232, 236, 255, 198, 210, 220, 255, 226,
+ 229, 234, 255, 239, 244, 249, 255, 179, 181, 183, 190, 15, 15, 14, 13,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 94, 94, 94, 94, 220, 220, 220, 220, 250, 251, 251, 254, 250, 251, 252,
+ 255, 250, 251, 252, 255, 250, 253, 255, 255, 250, 255, 255, 255, 246, 216,
+ 188, 255, 241, 151, 62, 255, 240, 144, 49, 255, 240, 148, 56, 255, 240,
+ 145, 50, 255, 240, 149, 59, 255, 247, 214, 184, 255, 254, 255, 255, 255,
+ 255, 255, 255, 255, 238, 241, 245, 255, 210, 220, 230, 255, 215, 224, 232,
+ 255, 249, 252, 254, 255, 255, 255, 255, 255, 249, 234, 222, 255, 241, 165,
+ 94, 255, 239, 142, 44, 255, 239, 146, 53, 255, 238, 141, 44, 255, 240,
+ 156, 78, 255, 250, 237, 226, 255, 252, 255, 255, 255, 255, 255, 255, 255,
+ 154, 181, 201, 255, 0, 71, 125, 255, 29, 98, 142, 255, 246, 246, 248,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 252, 252, 252, 255, 255, 255, 255, 255, 173,
+ 199, 214, 255, 0, 68, 122, 255, 0, 83, 132, 255, 236, 241, 244, 255,
+ 255, 255, 254, 255, 255, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 251, 248, 248, 255, 254, 250, 250, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 254, 253, 255, 252, 252, 252, 255, 253, 253, 253, 255, 255,
+ 255, 254, 255, 255, 255, 254, 255, 253, 253, 252, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 253, 253, 252, 255, 251, 251, 251, 255, 251, 251, 251, 255, 253, 252,
+ 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 177, 201, 216, 255, 0, 81, 132, 255,
+ 7, 86, 136, 255, 203, 213, 222, 255, 255, 255, 255, 255, 251, 251, 251,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 249, 247, 247, 255, 248, 246,
+ 246, 255, 255, 255, 253, 255, 255, 255, 255, 255, 252, 251, 251, 255, 249,
+ 249, 249, 255, 249, 249, 249, 255, 251, 251, 250, 255, 251, 250, 250, 255,
+ 251, 250, 249, 255, 255, 255, 254, 255, 255, 251, 250, 255, 253, 251, 249,
+ 255, 218, 225, 231, 255, 155, 174, 193, 255, 175, 186, 200, 255, 170, 184,
+ 200, 255, 240, 244, 248, 255, 134, 133, 133, 133, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56,
+ 56, 56, 57, 237, 237, 237, 239, 252, 252, 252, 255, 249, 254, 255, 255,
+ 249, 247, 246, 255, 243, 191, 141, 255, 239, 144, 50, 255, 239, 144, 50,
+ 255, 239, 147, 55, 255, 239, 146, 52, 255, 239, 146, 55, 255, 246, 214,
+ 185, 255, 253, 255, 255, 255, 252, 253, 254, 255, 156, 184, 203, 255, 38,
+ 103, 146, 255, 11, 89, 137, 255, 11, 87, 136, 255, 65, 123, 160, 255,
+ 199, 214, 225, 255, 255, 255, 255, 255, 250, 238, 229, 255, 239, 159, 82,
+ 255, 237, 142, 47, 255, 238, 145, 52, 255, 236, 137, 37, 255, 244, 193,
+ 145, 255, 251, 255, 255, 255, 255, 255, 255, 255, 154, 181, 201, 255, 0,
+ 73, 126, 255, 41, 105, 147, 255, 227, 231, 236, 255, 176, 198, 212, 255,
+ 134, 170, 194, 255, 120, 161, 187, 255, 151, 178, 198, 255, 203, 217, 226,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 178, 201, 215, 255, 0, 79,
+ 130, 255, 15, 93, 139, 255, 235, 241, 244, 255, 255, 255, 255, 255, 244,
+ 246, 247, 255, 163, 190, 207, 255, 101, 144, 174, 255, 54, 109, 148, 255,
+ 65, 116, 153, 255, 114, 154, 181, 255, 175, 198, 212, 255, 245, 246, 247,
+ 255, 253, 253, 253, 255, 246, 247, 248, 255, 236, 240, 244, 255, 238, 242,
+ 245, 255, 255, 254, 252, 255, 200, 215, 225, 255, 128, 164, 188, 255, 104,
+ 147, 177, 255, 128, 165, 189, 255, 186, 202, 216, 255, 248, 247, 248, 255,
+ 252, 252, 252, 255, 254, 254, 253, 255, 252, 251, 251, 255, 186, 203, 216,
+ 255, 135, 171, 194, 255, 121, 162, 188, 255, 140, 174, 196, 255, 191, 209,
+ 221, 255, 171, 196, 212, 255, 3, 86, 135, 255, 9, 87, 136, 255, 202,
+ 212, 221, 255, 255, 255, 255, 255, 254, 252, 251, 255, 186, 204, 217, 255,
+ 115, 157, 184, 255, 61, 116, 154, 255, 56, 111, 151, 255, 101, 146, 175,
+ 255, 169, 191, 208, 255, 240, 242, 243, 255, 254, 253, 252, 255, 247, 247,
+ 247, 255, 244, 243, 244, 255, 246, 243, 244, 255, 246, 247, 246, 255, 163,
+ 190, 206, 255, 90, 132, 165, 255, 139, 167, 189, 255, 236, 237, 239, 255,
+ 198, 206, 217, 255, 198, 205, 215, 255, 181, 193, 206, 255, 246, 247, 248,
+ 255, 229, 228, 228, 233, 24, 24, 24, 24, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 62, 62, 62, 63, 209, 209, 209, 212, 250, 251,
+ 251, 253, 249, 254, 255, 255, 247, 235, 223, 255, 240, 170, 103, 255, 237,
+ 139, 41, 255, 237, 144, 52, 255, 238, 146, 54, 255, 238, 145, 54, 255,
+ 238, 140, 44, 255, 242, 181, 123, 255, 251, 255, 255, 255, 253, 253, 253,
+ 255, 133, 169, 192, 255, 0, 78, 130, 255, 0, 82, 132, 255, 2, 85,
+ 134, 255, 2, 85, 134, 255, 0, 78, 129, 255, 23, 92, 138, 255, 196,
+ 210, 221, 255, 255, 255, 255, 255, 245, 212, 185, 255, 236, 141, 46, 255,
+ 237, 144, 51, 255, 236, 141, 45, 255, 239, 163, 90, 255, 250, 248, 247,
+ 255, 255, 255, 255, 255, 153, 181, 200, 255, 0, 75, 127, 255, 22, 93,
+ 139, 255, 42, 106, 148, 255, 0, 69, 122, 255, 0, 63, 118, 255, 0,
+ 62, 117, 255, 0, 70, 123, 255, 9, 84, 133, 255, 150, 179, 199, 255,
+ 255, 255, 255, 255, 178, 201, 215, 255, 0, 78, 129, 255, 14, 92, 138,
+ 255, 241, 245, 247, 255, 234, 240, 243, 255, 69, 126, 163, 255, 0, 70,
+ 123, 255, 0, 72, 124, 255, 43, 109, 150, 255, 39, 106, 147, 255, 0,
+ 74, 126, 255, 0, 72, 125, 255, 107, 149, 177, 255, 255, 255, 255, 255,
+ 176, 199, 213, 255, 15, 89, 136, 255, 28, 101, 145, 255, 101, 145, 174,
+ 255, 0, 79, 129, 255, 0, 70, 122, 255, 0, 69, 122, 255, 0, 71,
+ 124, 255, 0, 78, 128, 255, 125, 162, 186, 255, 255, 255, 254, 255, 246,
+ 247, 248, 255, 107, 151, 179, 255, 1, 80, 130, 255, 0, 69, 123, 255,
+ 0, 65, 120, 255, 0, 67, 121, 255, 0, 77, 128, 255, 30, 102, 146,
+ 255, 8, 88, 136, 255, 10, 88, 136, 255, 204, 213, 222, 255, 248, 250,
+ 250, 255, 111, 154, 182, 255, 0, 81, 131, 255, 0, 73, 126, 255, 37,
+ 105, 148, 255, 52, 115, 154, 255, 4, 83, 132, 255, 0, 74, 126, 255,
+ 74, 128, 163, 255, 236, 239, 242, 255, 223, 228, 232, 255, 61, 114, 152,
+ 255, 63, 114, 152, 255, 89, 137, 168, 255, 0, 76, 127, 255, 0, 57,
+ 114, 255, 73, 125, 161, 255, 255, 250, 248, 255, 249, 248, 248, 255, 247,
+ 247, 247, 255, 247, 247, 246, 255, 245, 245, 245, 255, 255, 255, 255, 255,
+ 112, 112, 112, 113, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 107, 107, 107, 108,
+ 246, 246, 246, 249, 255, 255, 255, 255, 247, 252, 255, 255, 243, 215, 190,
+ 255, 237, 151, 69, 255, 236, 139, 43, 255, 236, 144, 53, 255, 236, 145,
+ 53, 255, 237, 145, 53, 255, 237, 144, 52, 255, 236, 143, 53, 255, 245,
+ 217, 197, 255, 255, 255, 255, 255, 206, 218, 227, 255, 8, 87, 135, 255,
+ 0, 83, 132, 255, 5, 86, 135, 255, 5, 86, 135, 255, 5, 86, 135,
+ 255, 5, 86, 134, 255, 0, 76, 127, 255, 73, 128, 162, 255, 251, 252,
+ 253, 255, 250, 241, 234, 255, 237, 151, 69, 255, 236, 141, 48, 255, 236,
+ 142, 49, 255, 236, 145, 57, 255, 247, 230, 219, 255, 255, 255, 255, 255,
+ 153, 180, 200, 255, 0, 76, 127, 255, 0, 79, 129, 255, 8, 87, 134,
+ 255, 100, 146, 176, 255, 144, 174, 196, 255, 123, 163, 188, 255, 36, 104,
+ 147, 255, 0, 75, 126, 255, 10, 82, 130, 255, 202, 214, 223, 255, 186,
+ 206, 219, 255, 0, 78, 128, 255, 15, 93, 138, 255, 243, 245, 246, 255,
+ 113, 152, 179, 255, 0, 68, 120, 255, 7, 82, 131, 255, 154, 181, 201,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 163, 186, 203, 255, 2, 79,
+ 129, 255, 0, 75, 126, 255, 167, 188, 204, 255, 177, 199, 212, 255, 0,
+ 77, 127, 255, 0, 79, 129, 255, 0, 80, 129, 255, 90, 140, 171, 255,
+ 185, 197, 211, 255, 158, 181, 200, 255, 28, 100, 144, 255, 0, 75, 126,
+ 255, 34, 102, 145, 255, 252, 251, 249, 255, 147, 178, 197, 255, 0, 73,
+ 125, 255, 0, 79, 130, 255, 60, 120, 158, 255, 139, 173, 195, 255, 147,
+ 175, 196, 255, 83, 135, 167, 255, 0, 81, 130, 255, 1, 83, 133, 255,
+ 11, 88, 136, 255, 214, 219, 226, 255, 167, 192, 207, 255, 0, 75, 127,
+ 255, 0, 79, 129, 255, 116, 156, 182, 255, 255, 254, 252, 255, 255, 255,
+ 254, 255, 196, 208, 219, 255, 25, 96, 140, 255, 0, 71, 124, 255, 110,
+ 153, 180, 255, 219, 224, 229, 255, 7, 87, 134, 255, 0, 79, 130, 255,
+ 0, 80, 129, 255, 72, 126, 161, 255, 124, 161, 187, 255, 168, 191, 207,
+ 255, 249, 247, 246, 255, 246, 246, 246, 255, 245, 245, 245, 255, 245, 245,
+ 244, 255, 244, 244, 244, 255, 255, 255, 255, 255, 166, 166, 166, 171, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 22,
+ 22, 22, 157, 157, 157, 158, 255, 255, 255, 255, 250, 254, 255, 255, 246,
+ 247, 248, 255, 240, 196, 154, 255, 234, 141, 50, 255, 235, 141, 47, 255,
+ 235, 144, 53, 255, 235, 141, 48, 255, 235, 143, 52, 255, 235, 144, 53,
+ 255, 235, 142, 50, 255, 236, 149, 63, 255, 246, 237, 230, 255, 255, 255,
+ 255, 255, 167, 192, 208, 255, 0, 81, 131, 255, 3, 85, 133, 255, 5,
+ 86, 134, 255, 5, 85, 134, 255, 5, 85, 134, 255, 4, 85, 134, 255,
+ 0, 81, 131, 255, 40, 104, 146, 255, 240, 243, 245, 255, 251, 249, 250,
+ 255, 237, 163, 99, 255, 235, 139, 43, 255, 235, 142, 50, 255, 234, 139,
+ 47, 255, 243, 209, 184, 255, 255, 255, 255, 255, 152, 180, 199, 255, 0,
+ 75, 126, 255, 2, 76, 127, 255, 143, 172, 193, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 191, 207, 218, 255, 4, 83, 131,
+ 255, 0, 70, 122, 255, 107, 150, 178, 255, 186, 205, 217, 255, 0, 79,
+ 128, 255, 20, 95, 141, 255, 207, 218, 226, 255, 15, 90, 136, 255, 0,
+ 76, 127, 255, 33, 101, 144, 255, 170, 193, 208, 255, 172, 195, 210, 255,
+ 173, 197, 211, 255, 157, 185, 203, 255, 8, 88, 135, 255, 0, 75, 126,
+ 255, 40, 105, 146, 255, 155, 181, 200, 255, 1, 83, 131, 255, 0, 74,
+ 125, 255, 92, 140, 172, 255, 255, 255, 254, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 137, 171, 192, 255, 0, 73, 124, 255, 20, 95, 141, 255,
+ 223, 229, 235, 255, 39, 104, 145, 255, 0, 75, 126, 255, 50, 112, 151,
+ 255, 243, 242, 243, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253,
+ 252, 255, 101, 144, 173, 255, 0, 76, 127, 255, 12, 89, 135, 255, 200,
+ 208, 218, 255, 71, 125, 160, 255, 0, 77, 128, 255, 12, 89, 136, 255,
+ 152, 180, 198, 255, 174, 197, 211, 255, 170, 194, 209, 255, 177, 197, 210,
+ 255, 61, 118, 155, 255, 0, 75, 126, 255, 44, 110, 150, 255, 202, 212,
+ 221, 255, 17, 92, 137, 255, 0, 75, 126, 255, 76, 130, 164, 255, 251,
+ 248, 246, 255, 255, 255, 254, 255, 255, 252, 250, 255, 244, 244, 244, 255,
+ 244, 244, 244, 255, 244, 244, 244, 255, 244, 244, 244, 255, 243, 243, 243,
+ 255, 254, 254, 254, 255, 172, 172, 172, 179, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 31, 31, 31, 31, 199, 199, 199, 202, 255, 255, 255,
+ 255, 247, 252, 255, 255, 244, 235, 228, 255, 237, 175, 114, 255, 232, 137,
+ 42, 255, 233, 141, 49, 255, 234, 142, 51, 255, 233, 138, 44, 255, 235,
+ 156, 79, 255, 234, 146, 59, 255, 234, 142, 51, 255, 234, 142, 50, 255,
+ 235, 146, 59, 255, 245, 229, 219, 255, 255, 255, 255, 255, 192, 208, 219,
+ 255, 0, 81, 130, 255, 1, 83, 132, 255, 4, 85, 133, 255, 4, 85,
+ 133, 255, 4, 85, 133, 255, 4, 85, 133, 255, 0, 78, 128, 255, 53,
+ 115, 153, 255, 245, 247, 249, 255, 250, 246, 244, 255, 236, 155, 80, 255,
+ 234, 139, 45, 255, 233, 142, 50, 255, 232, 137, 42, 255, 241, 201, 169,
+ 255, 255, 255, 255, 255, 152, 179, 198, 255, 0, 73, 123, 255, 15, 92,
+ 137, 255, 235, 238, 240, 255, 254, 252, 251, 255, 248, 248, 248, 255, 252,
+ 251, 250, 255, 242, 243, 244, 255, 33, 99, 142, 255, 0, 71, 124, 255,
+ 76, 131, 165, 255, 175, 198, 213, 255, 0, 79, 128, 255, 22, 97, 142,
+ 255, 182, 198, 211, 255, 9, 85, 133, 255, 0, 81, 129, 255, 0, 81,
+ 129, 255, 0, 72, 123, 255, 0, 71, 122, 255, 0, 71, 122, 255, 0,
+ 72, 123, 255, 0, 75, 125, 255, 0, 73, 124, 255, 14, 88, 134, 255,
+ 134, 166, 187, 255, 1, 83, 131, 255, 2, 79, 128, 255, 185, 198, 210,
+ 255, 255, 255, 255, 255, 248, 248, 248, 255, 255, 255, 255, 255, 161, 186,
+ 202, 255, 0, 74, 125, 255, 23, 97, 141, 255, 204, 216, 225, 255, 14,
+ 91, 137, 255, 0, 72, 124, 255, 103, 147, 175, 255, 255, 255, 252, 255,
+ 248, 248, 248, 255, 247, 247, 247, 255, 255, 255, 255, 255, 174, 196, 211,
+ 255, 0, 79, 129, 255, 12, 89, 135, 255, 179, 194, 207, 255, 20, 95,
+ 141, 255, 1, 82, 131, 255, 4, 84, 133, 255, 0, 77, 127, 255, 0,
+ 74, 124, 255, 0, 74, 125, 255, 0, 74, 125, 255, 0, 77, 127, 255,
+ 0, 76, 125, 255, 15, 89, 135, 255, 184, 198, 210, 255, 18, 93, 138,
+ 255, 0, 72, 123, 255, 136, 169, 191, 255, 255, 255, 253, 255, 244, 244,
+ 244, 255, 244, 244, 244, 255, 244, 244, 244, 255, 243, 243, 243, 255, 243,
+ 243, 243, 255, 243, 243, 243, 255, 242, 242, 242, 255, 255, 255, 255, 255,
+ 165, 165, 165, 171, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 21, 21, 21, 198,
+ 198, 198, 203, 255, 255, 255, 255, 244, 249, 253, 255, 241, 219, 201, 255,
+ 233, 154, 79, 255, 231, 135, 38, 255, 232, 141, 51, 255, 232, 140, 48,
+ 255, 232, 137, 42, 255, 237, 176, 119, 255, 243, 230, 220, 255, 234, 149,
+ 67, 255, 233, 140, 49, 255, 233, 142, 51, 255, 232, 138, 45, 255, 240,
+ 201, 168, 255, 249, 254, 255, 255, 243, 243, 244, 255, 72, 126, 160, 255,
+ 0, 73, 124, 255, 2, 83, 131, 255, 4, 84, 132, 255, 4, 84, 132,
+ 255, 0, 80, 130, 255, 0, 74, 125, 255, 147, 175, 195, 255, 255, 255,
+ 255, 255, 245, 229, 216, 255, 233, 144, 55, 255, 233, 140, 48, 255, 233,
+ 140, 49, 255, 232, 138, 47, 255, 241, 210, 186, 255, 255, 255, 255, 255,
+ 151, 178, 197, 255, 0, 73, 123, 255, 11, 88, 134, 255, 218, 225, 231,
+ 255, 255, 255, 253, 255, 247, 247, 247, 255, 255, 253, 252, 255, 232, 236,
+ 239, 255, 18, 92, 137, 255, 0, 71, 123, 255, 83, 136, 167, 255, 178,
+ 199, 213, 255, 0, 79, 128, 255, 22, 96, 140, 255, 189, 204, 215, 255,
+ 6, 84, 132, 255, 0, 76, 126, 255, 45, 108, 148, 255, 166, 183, 200,
+ 255, 162, 179, 197, 255, 160, 179, 197, 255, 168, 184, 200, 255, 175, 189,
+ 204, 255, 167, 183, 200, 255, 175, 190, 205, 255, 154, 180, 198, 255, 0,
+ 78, 128, 255, 7, 84, 132, 255, 206, 214, 222, 255, 254, 253, 251, 255,
+ 247, 247, 247, 255, 255, 255, 254, 255, 157, 183, 200, 255, 0, 74, 124,
+ 255, 22, 96, 141, 255, 210, 220, 227, 255, 20, 93, 138, 255, 0, 72,
+ 124, 255, 88, 136, 168, 255, 255, 255, 252, 255, 249, 249, 248, 255, 247,
+ 247, 247, 255, 255, 255, 255, 255, 164, 188, 204, 255, 0, 77, 127, 255,
+ 12, 88, 134, 255, 186, 198, 210, 255, 38, 104, 146, 255, 0, 78, 128,
+ 255, 22, 93, 138, 255, 159, 177, 196, 255, 162, 181, 198, 255, 159, 178,
+ 196, 255, 164, 182, 199, 255, 173, 187, 203, 255, 165, 182, 199, 255, 171,
+ 186, 202, 255, 199, 209, 218, 255, 12, 89, 134, 255, 0, 77, 126, 255,
+ 175, 189, 202, 255, 254, 251, 249, 255, 243, 243, 243, 255, 243, 243, 243,
+ 255, 243, 243, 243, 255, 243, 243, 243, 255, 242, 242, 242, 255, 242, 242,
+ 242, 255, 242, 242, 242, 255, 255, 255, 255, 255, 127, 127, 127, 127, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 123, 123, 123, 126, 255, 255, 255, 255, 244, 247,
+ 250, 255, 237, 204, 174, 255, 230, 140, 50, 255, 230, 136, 43, 255, 231,
+ 141, 52, 255, 231, 138, 45, 255, 231, 138, 48, 255, 237, 190, 146, 255,
+ 245, 246, 249, 255, 245, 247, 251, 255, 235, 164, 103, 255, 231, 137, 42,
+ 255, 232, 141, 51, 255, 231, 137, 43, 255, 235, 163, 95, 255, 244, 243,
+ 244, 255, 252, 253, 254, 255, 228, 230, 234, 255, 79, 129, 162, 255, 0,
+ 79, 128, 255, 0, 72, 123, 255, 0, 73, 124, 255, 17, 88, 134, 255,
+ 128, 164, 186, 255, 251, 249, 248, 255, 249, 253, 255, 255, 238, 189, 144,
+ 255, 231, 137, 42, 255, 232, 141, 50, 255, 232, 139, 47, 255, 232, 144,
+ 57, 255, 244, 231, 221, 255, 255, 255, 255, 255, 151, 177, 196, 255, 0,
+ 74, 124, 255, 0, 74, 125, 255, 91, 138, 169, 255, 244, 244, 245, 255,
+ 255, 255, 253, 255, 251, 250, 248, 255, 128, 163, 187, 255, 0, 77, 127,
+ 255, 0, 69, 121, 255, 136, 167, 190, 255, 187, 206, 217, 255, 0, 77,
+ 127, 255, 18, 92, 137, 255, 226, 231, 235, 255, 51, 111, 149, 255, 0,
+ 69, 121, 255, 38, 103, 143, 255, 227, 231, 234, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 206, 217, 225, 255, 145, 173, 193, 255, 229, 234, 237,
+ 255, 255, 255, 255, 255, 169, 192, 207, 255, 0, 76, 126, 255, 7, 85,
+ 132, 255, 210, 217, 224, 255, 253, 251, 250, 255, 246, 246, 246, 255, 255,
+ 255, 253, 255, 157, 182, 200, 255, 0, 74, 124, 255, 17, 93, 138, 255,
+ 238, 239, 241, 255, 89, 135, 165, 255, 0, 72, 123, 255, 19, 90, 135,
+ 255, 180, 197, 211, 255, 255, 251, 249, 255, 255, 254, 251, 255, 220, 226,
+ 231, 255, 52, 112, 150, 255, 0, 77, 126, 255, 10, 86, 132, 255, 209,
+ 214, 221, 255, 121, 157, 182, 255, 0, 70, 122, 255, 12, 86, 133, 255,
+ 188, 202, 214, 255, 255, 255, 255, 255, 255, 255, 255, 255, 227, 232, 235,
+ 255, 142, 173, 194, 255, 222, 227, 231, 255, 255, 255, 254, 255, 210, 218,
+ 224, 255, 10, 86, 132, 255, 0, 77, 125, 255, 175, 189, 202, 255, 254,
+ 250, 248, 255, 242, 242, 242, 255, 242, 242, 242, 255, 242, 242, 242, 255,
+ 242, 242, 242, 255, 242, 242, 242, 255, 241, 241, 241, 255, 246, 246, 246,
+ 255, 231, 231, 231, 241, 39, 39, 39, 38, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 10, 9,
+ 215, 215, 215, 222, 249, 253, 255, 255, 239, 219, 201, 255, 229, 139, 51,
+ 255, 229, 137, 45, 255, 229, 140, 50, 255, 229, 135, 41, 255, 230, 143,
+ 57, 255, 238, 204, 173, 255, 244, 249, 253, 255, 245, 246, 248, 255, 244,
+ 250, 255, 255, 237, 194, 154, 255, 230, 135, 40, 255, 231, 141, 50, 255,
+ 231, 140, 50, 255, 231, 136, 44, 255, 237, 185, 141, 255, 245, 248, 253,
+ 255, 251, 252, 254, 255, 251, 248, 246, 255, 175, 193, 207, 255, 113, 152,
+ 179, 255, 128, 162, 186, 255, 210, 217, 224, 255, 255, 253, 252, 255, 248,
+ 254, 255, 255, 240, 211, 185, 255, 230, 139, 49, 255, 231, 139, 47, 255,
+ 231, 140, 50, 255, 230, 136, 42, 255, 233, 158, 87, 255, 245, 244, 243,
+ 255, 255, 255, 255, 255, 148, 175, 194, 255, 0, 69, 121, 255, 0, 78,
+ 127, 255, 0, 74, 124, 255, 41, 104, 144, 255, 109, 149, 176, 255, 65,
+ 120, 156, 255, 0, 75, 124, 255, 0, 69, 121, 255, 36, 100, 141, 255,
+ 239, 240, 241, 255, 177, 199, 212, 255, 0, 71, 123, 255, 6, 86, 132,
+ 255, 241, 244, 244, 255, 190, 203, 214, 255, 13, 83, 129, 255, 0, 68,
+ 119, 255, 24, 94, 138, 255, 119, 160, 185, 255, 107, 151, 178, 255, 4,
+ 82, 129, 255, 0, 57, 112, 255, 70, 120, 155, 255, 254, 253, 252, 255,
+ 166, 190, 205, 255, 0, 70, 122, 255, 0, 80, 128, 255, 207, 215, 222,
+ 255, 253, 251, 250, 255, 246, 246, 246, 255, 255, 255, 253, 255, 154, 180,
+ 198, 255, 0, 68, 120, 255, 8, 87, 134, 255, 240, 243, 243, 255, 192,
+ 207, 217, 255, 4, 80, 128, 255, 0, 73, 124, 255, 3, 82, 129, 255,
+ 82, 130, 162, 255, 101, 143, 171, 255, 21, 90, 135, 255, 0, 72, 123,
+ 255, 0, 78, 127, 255, 1, 80, 128, 255, 204, 212, 219, 255, 222, 228,
+ 233, 255, 36, 101, 143, 255, 0, 70, 121, 255, 11, 85, 131, 255, 104,
+ 147, 174, 255, 119, 158, 183, 255, 35, 100, 141, 255, 0, 62, 116, 255,
+ 34, 98, 140, 255, 232, 233, 235, 255, 211, 218, 224, 255, 2, 81, 129,
+ 255, 0, 72, 121, 255, 172, 186, 200, 255, 253, 250, 248, 255, 242, 242,
+ 242, 255, 241, 241, 241, 255, 241, 241, 241, 255, 241, 241, 241, 255, 240,
+ 240, 240, 255, 241, 241, 241, 255, 255, 255, 255, 255, 140, 140, 140, 145,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 19, 19, 19, 19, 231, 231, 231, 238, 245,
+ 251, 255, 255, 236, 199, 168, 255, 227, 130, 35, 255, 228, 136, 45, 255,
+ 227, 132, 37, 255, 230, 152, 77, 255, 239, 219, 202, 255, 244, 250, 255,
+ 255, 251, 251, 252, 255, 245, 245, 245, 255, 244, 248, 251, 255, 240, 221,
+ 204, 255, 230, 140, 52, 255, 230, 138, 47, 255, 230, 140, 50, 255, 230,
+ 139, 48, 255, 229, 136, 44, 255, 235, 180, 132, 255, 243, 235, 230, 255,
+ 246, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 252, 255, 255, 255, 244, 244, 245, 255, 238, 198, 161, 255, 230, 141,
+ 53, 255, 230, 138, 45, 255, 230, 139, 49, 255, 230, 139, 49, 255, 229,
+ 132, 36, 255, 236, 184, 136, 255, 245, 250, 254, 255, 254, 253, 252, 255,
+ 164, 185, 201, 255, 39, 95, 137, 255, 72, 121, 155, 255, 141, 170, 190,
+ 255, 31, 96, 139, 255, 0, 70, 120, 255, 0, 70, 120, 255, 5, 81,
+ 128, 255, 62, 115, 151, 255, 201, 211, 219, 255, 255, 255, 254, 255, 185,
+ 203, 214, 255, 41, 100, 141, 255, 52, 112, 149, 255, 233, 237, 239, 255,
+ 255, 254, 252, 255, 187, 202, 213, 255, 74, 123, 157, 255, 17, 88, 133,
+ 255, 0, 70, 120, 255, 0, 72, 122, 255, 20, 92, 136, 255, 75, 124,
+ 158, 255, 183, 200, 212, 255, 253, 253, 252, 255, 179, 197, 210, 255, 41,
+ 99, 141, 255, 47, 107, 146, 255, 213, 219, 225, 255, 251, 249, 248, 255,
+ 245, 245, 245, 255, 253, 252, 251, 255, 170, 190, 204, 255, 40, 97, 138,
+ 255, 54, 113, 150, 255, 232, 236, 239, 255, 254, 252, 249, 255, 165, 186,
+ 201, 255, 39, 101, 142, 255, 2, 79, 127, 255, 0, 71, 121, 255, 0,
+ 73, 123, 255, 52, 111, 150, 255, 113, 152, 178, 255, 46, 107, 146, 255,
+ 46, 106, 145, 255, 203, 211, 218, 255, 255, 254, 252, 255, 213, 219, 226,
+ 255, 90, 136, 166, 255, 21, 91, 136, 255, 0, 74, 124, 255, 0, 72,
+ 122, 255, 14, 87, 133, 255, 65, 118, 154, 255, 166, 190, 205, 255, 249,
+ 249, 247, 255, 212, 219, 224, 255, 48, 107, 145, 255, 40, 99, 139, 255,
+ 181, 193, 205, 255, 250, 248, 246, 255, 241, 241, 241, 255, 241, 241, 241,
+ 255, 240, 240, 240, 255, 240, 240, 240, 255, 240, 240, 240, 255, 255, 255,
+ 255, 255, 199, 199, 199, 205, 10, 10, 10, 9, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 8, 8, 8, 7, 194, 194, 194, 202, 250, 253, 254, 255, 238, 227,
+ 219, 255, 230, 161, 95, 255, 228, 143, 60, 255, 231, 170, 111, 255, 239,
+ 231, 224, 255, 245, 250, 254, 255, 255, 255, 255, 255, 159, 159, 159, 163,
+ 136, 136, 136, 139, 253, 253, 254, 255, 243, 246, 250, 255, 234, 179, 130,
+ 255, 228, 132, 36, 255, 229, 139, 50, 255, 229, 139, 50, 255, 229, 138,
+ 48, 255, 229, 134, 41, 255, 230, 150, 72, 255, 236, 193, 154, 255, 239,
+ 216, 194, 255, 240, 223, 211, 255, 240, 220, 203, 255, 238, 204, 172, 255,
+ 232, 163, 97, 255, 228, 135, 42, 255, 229, 137, 46, 255, 229, 139, 49,
+ 255, 229, 139, 49, 255, 229, 135, 43, 255, 229, 140, 54, 255, 241, 223,
+ 207, 255, 245, 248, 251, 255, 244, 244, 244, 255, 241, 241, 242, 255, 236,
+ 237, 239, 255, 239, 239, 240, 255, 253, 250, 248, 255, 233, 235, 237, 255,
+ 190, 200, 211, 255, 173, 187, 200, 255, 201, 210, 218, 255, 244, 244, 244,
+ 255, 252, 251, 248, 255, 245, 245, 244, 255, 242, 242, 243, 255, 237, 238,
+ 239, 255, 238, 239, 240, 255, 244, 244, 244, 255, 245, 245, 244, 255, 253,
+ 250, 248, 255, 248, 246, 245, 255, 224, 228, 232, 255, 197, 206, 215, 255,
+ 201, 209, 217, 255, 228, 231, 235, 255, 248, 247, 245, 255, 252, 249, 248,
+ 255, 244, 244, 244, 255, 242, 242, 242, 255, 237, 238, 239, 255, 237, 238,
+ 239, 255, 243, 243, 243, 255, 244, 244, 244, 255, 244, 244, 244, 255, 244,
+ 244, 244, 255, 241, 242, 242, 255, 237, 238, 239, 255, 237, 238, 239, 255,
+ 243, 243, 243, 255, 244, 244, 244, 255, 252, 249, 247, 255, 232, 234, 236,
+ 255, 192, 201, 212, 255, 173, 187, 200, 255, 198, 207, 216, 255, 241, 241,
+ 241, 255, 250, 247, 246, 255, 236, 237, 238, 255, 236, 237, 238, 255, 241,
+ 241, 241, 255, 243, 243, 243, 255, 249, 247, 246, 255, 250, 246, 245, 255,
+ 227, 230, 233, 255, 199, 208, 216, 255, 193, 203, 212, 255, 220, 225, 229,
+ 255, 243, 242, 242, 255, 251, 248, 246, 255, 241, 241, 241, 255, 240, 240,
+ 240, 255, 234, 235, 237, 255, 233, 234, 236, 255, 237, 238, 238, 255, 240,
+ 240, 240, 255, 240, 240, 240, 255, 240, 240, 240, 255, 240, 240, 240, 255,
+ 244, 244, 244, 255, 254, 254, 254, 255, 194, 194, 194, 199, 43, 43, 43,
+ 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 84, 84, 84, 87, 253, 253, 252, 255, 246, 247, 248, 255, 240, 238, 238,
+ 255, 239, 234, 229, 255, 240, 242, 243, 255, 250, 252, 254, 255, 247, 247,
+ 246, 252, 134, 134, 134, 134, 0, 0, 0, 0, 30, 30, 30, 31, 226,
+ 226, 225, 235, 248, 250, 253, 255, 240, 231, 225, 255, 230, 154, 83, 255,
+ 227, 133, 39, 255, 228, 138, 49, 255, 228, 138, 49, 255, 228, 138, 49,
+ 255, 228, 135, 44, 255, 227, 133, 39, 255, 228, 138, 49, 255, 228, 140,
+ 55, 255, 228, 139, 52, 255, 227, 134, 42, 255, 227, 134, 41, 255, 228,
+ 138, 48, 255, 228, 138, 49, 255, 228, 138, 49, 255, 228, 135, 43, 255,
+ 228, 137, 47, 255, 237, 205, 176, 255, 245, 248, 252, 255, 253, 253, 253,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 255, 253, 253,
+ 253, 255, 253, 253, 253, 255, 254, 254, 254, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 253, 255,
+ 252, 252, 252, 255, 252, 252, 252, 255, 252, 252, 252, 255, 255, 254, 253,
+ 255, 255, 254, 253, 255, 252, 252, 252, 255, 251, 251, 251, 255, 251, 251,
+ 251, 255, 252, 252, 252, 255, 254, 254, 254, 255, 225, 225, 225, 232, 141,
+ 141, 141, 145, 8, 8, 8, 7, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 124,
+ 124, 124, 127, 236, 236, 236, 242, 255, 255, 255, 255, 254, 255, 255, 255,
+ 254, 255, 255, 255, 215, 215, 215, 219, 98, 98, 98, 99, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 90, 90, 92, 255, 255,
+ 255, 255, 244, 247, 250, 255, 238, 224, 214, 255, 229, 152, 81, 255, 226,
+ 131, 36, 255, 227, 137, 47, 255, 227, 138, 49, 255, 227, 138, 49, 255,
+ 227, 137, 48, 255, 227, 137, 47, 255, 227, 136, 46, 255, 227, 136, 46,
+ 255, 227, 137, 48, 255, 227, 138, 48, 255, 227, 138, 48, 255, 227, 137,
+ 48, 255, 226, 133, 39, 255, 227, 137, 48, 255, 235, 196, 160, 255, 244,
+ 249, 254, 255, 247, 248, 248, 255, 183, 183, 183, 190, 162, 162, 162, 169,
+ 163, 163, 163, 170, 164, 164, 164, 170, 164, 164, 164, 170, 164, 164, 164,
+ 170, 164, 164, 164, 170, 164, 164, 164, 170, 164, 164, 164, 170, 164, 164,
+ 164, 170, 164, 164, 164, 170, 164, 164, 164, 170, 164, 164, 164, 170, 164,
+ 164, 164, 170, 164, 164, 164, 170, 164, 164, 164, 170, 164, 164, 164, 170,
+ 164, 164, 164, 170, 164, 164, 164, 170, 164, 164, 164, 170, 164, 164, 164,
+ 170, 164, 164, 164, 170, 164, 164, 164, 170, 164, 164, 164, 170, 164, 164,
+ 164, 170, 164, 164, 164, 170, 164, 164, 164, 170, 164, 164, 164, 170, 164,
+ 164, 164, 170, 163, 163, 163, 170, 163, 163, 163, 170, 163, 163, 163, 170,
+ 163, 163, 163, 170, 163, 163, 163, 170, 163, 163, 163, 170, 163, 163, 163,
+ 170, 163, 163, 163, 170, 163, 163, 163, 170, 163, 163, 163, 170, 163, 163,
+ 163, 170, 163, 163, 163, 170, 163, 163, 163, 170, 163, 163, 163, 170, 163,
+ 163, 163, 170, 163, 163, 163, 170, 163, 163, 163, 170, 162, 162, 162, 170,
+ 162, 162, 162, 170, 162, 162, 162, 170, 162, 162, 162, 170, 162, 162, 162,
+ 170, 162, 162, 162, 170, 162, 162, 162, 170, 162, 162, 162, 170, 162, 162,
+ 162, 170, 162, 162, 162, 169, 162, 162, 162, 169, 162, 162, 162, 169, 162,
+ 162, 162, 169, 161, 161, 161, 169, 161, 161, 161, 169, 161, 161, 161, 169,
+ 161, 161, 161, 169, 161, 161, 161, 169, 162, 162, 162, 171, 156, 156, 156,
+ 162, 112, 112, 112, 112, 32, 32, 32, 32, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 47,
+ 47, 46, 131, 131, 131, 134, 147, 147, 147, 152, 105, 105, 105, 106, 12,
+ 12, 12, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 2, 2, 2, 2, 144, 144, 144, 147, 254, 254, 254,
+ 255, 243, 246, 250, 255, 238, 228, 221, 255, 230, 168, 111, 255, 225, 134,
+ 45, 255, 225, 131, 37, 255, 226, 135, 43, 255, 226, 136, 46, 255, 226,
+ 137, 48, 255, 226, 137, 48, 255, 226, 137, 48, 255, 226, 137, 47, 255,
+ 226, 135, 45, 255, 225, 133, 40, 255, 225, 130, 36, 255, 228, 152, 76,
+ 255, 237, 209, 184, 255, 244, 248, 253, 255, 255, 255, 255, 255, 167, 167,
+ 167, 172, 5, 5, 5, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 9, 9, 9, 8, 153, 153, 153, 158, 249, 249, 249, 255,
+ 246, 248, 251, 255, 239, 242, 246, 255, 235, 207, 184, 255, 229, 165, 105,
+ 255, 226, 146, 70, 255, 225, 135, 48, 255, 224, 130, 38, 255, 224, 129,
+ 34, 255, 224, 129, 34, 255, 224, 131, 40, 255, 226, 141, 58, 255, 228,
+ 158, 91, 255, 233, 190, 151, 255, 240, 237, 235, 255, 247, 251, 255, 255,
+ 250, 250, 251, 255, 177, 177, 177, 180, 23, 23, 23, 22, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 113, 113, 113, 115, 225, 225, 225, 233, 253,
+ 254, 254, 255, 244, 248, 252, 255, 239, 241, 244, 255, 238, 232, 228, 255,
+ 235, 209, 191, 255, 232, 190, 152, 255, 231, 184, 138, 255, 232, 185, 138,
+ 255, 232, 196, 164, 255, 237, 225, 217, 255, 240, 240, 240, 255, 246, 250,
+ 255, 255, 255, 255, 255, 255, 230, 230, 230, 235, 110, 110, 110, 111, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 40, 40, 40, 40, 149, 149, 149, 153, 220, 220,
+ 220, 229, 251, 252, 252, 255, 252, 254, 255, 255, 249, 253, 255, 255, 246,
+ 252, 255, 255, 245, 251, 255, 255, 246, 252, 255, 255, 248, 254, 255, 255,
+ 253, 255, 255, 255, 250, 251, 252, 255, 217, 218, 218, 226, 153, 153, 153,
+ 157, 45, 45, 45, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 25, 25, 25, 25, 102, 102, 102,
+ 102, 152, 152, 152, 157, 175, 175, 175, 185, 197, 197, 197, 210, 202, 203,
+ 203, 215, 197, 197, 197, 209, 180, 180, 180, 188, 155, 155, 155, 160, 97,
+ 97, 97, 98, 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 7, 7, 7, 7, 8, 8, 8, 8, 7, 7, 7,
+ 6, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, };
+
+ *width = 115;
+ *height = 32;
+
+ // only load the requested logo
+ // allocate a new array
+ *data = new unsigned char[14720];
+ // and copy it. Now we are certain that the calling function
+ // can control the memory location
+ for(int i = 0; i < 14720 /* tmp array size */; i++)
+ {
+ (*data)[i] = logo_blender_raw[i];
+ }
+
+}
+
+
+void GetRawBlender3DLogo(unsigned char **data, int *width, int *height)
+{
+ // create an array that will automatically be deleted when)
+ // we're outta this scope
+ static unsigned char logo_blender3d_raw[]= {255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255,
+ 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255,
+ 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0,
+ 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255,
+ 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255,
+ 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255,
+ 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0,
+ 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255,
+ 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 57, 255, 255,
+ 255, 243, 255, 255, 255, 252, 255, 255, 255, 251, 255, 255, 255, 200, 255,
+ 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0,
+ 255, 255, 255, 57, 255, 255, 255, 243, 255, 255, 255, 252, 255, 255, 255,
+ 251, 255, 255, 255, 200, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255,
+ 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255,
+ 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0,
+ 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255,
+ 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255,
+ 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255,
+ 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 141, 255, 255, 255, 248,
+ 255, 255, 255, 253, 255, 255, 255, 248, 255, 255, 255, 141, 255, 255, 255,
+ 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255,
+ 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255,
+ 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0,
+ 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255,
+ 17, 255, 255, 255, 159, 255, 255, 255, 231, 255, 255, 255, 247, 255, 255,
+ 255, 247, 255, 255, 255, 234, 255, 255, 255, 176, 255, 255, 255, 36, 255,
+ 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0,
+ 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 141, 255, 255, 255,
+ 248, 255, 255, 255, 253, 255, 255, 255, 248, 255, 255, 255, 141, 255, 255,
+ 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255,
+ 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0,
+ 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255,
+ 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255,
+ 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255,
+ 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0,
+ 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255,
+ 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255,
+ 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255,
+ 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0,
+ 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255,
+ 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255,
+ 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255,
+ 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0,
+ 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255,
+ 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255,
+ 255, 86, 207, 207, 207, 255, 70, 70, 70, 255, 118, 118, 118, 255, 255,
+ 255, 255, 236, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0,
+ 255, 255, 255, 0, 255, 255, 255, 86, 207, 207, 207, 255, 70, 70, 70,
+ 255, 118, 118, 118, 255, 255, 255, 255, 236, 255, 255, 255, 0, 255, 255,
+ 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255,
+ 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0,
+ 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255,
+ 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255,
+ 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255,
+ 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 170,
+ 153, 153, 153, 255, 70, 70, 70, 255, 153, 153, 153, 255, 255, 255, 255,
+ 170, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255,
+ 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255,
+ 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0,
+ 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255,
+ 141, 255, 255, 255, 255, 239, 239, 239, 255, 153, 153, 153, 255, 137, 137,
+ 137, 255, 137, 137, 137, 255, 153, 153, 153, 255, 223, 223, 223, 255, 255,
+ 255, 255, 255, 255, 255, 255, 141, 255, 255, 255, 0, 255, 255, 255, 0,
+ 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255,
+ 170, 153, 153, 153, 255, 70, 70, 70, 255, 153, 153, 153, 255, 255, 255,
+ 255, 170, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255,
+ 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0,
+ 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255,
+ 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255,
+ 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255,
+ 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0,
+ 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255,
+ 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 86, 255, 255,
+ 255, 172, 255, 255, 255, 172, 255, 255, 255, 86, 255, 255, 255, 86, 255,
+ 255, 255, 144, 255, 255, 255, 144, 255, 255, 255, 57, 255, 255, 255, 86,
+ 255, 255, 255, 144, 255, 255, 255, 207, 255, 255, 255, 207, 255, 255, 255,
+ 172, 255, 255, 255, 86, 255, 255, 255, 86, 255, 255, 255, 144, 255, 255,
+ 255, 144, 255, 255, 255, 57, 255, 255, 255, 86, 255, 255, 255, 144, 255,
+ 255, 255, 207, 255, 255, 255, 207, 255, 255, 255, 172, 255, 255, 255, 86,
+ 255, 255, 255, 86, 255, 255, 255, 144, 255, 255, 255, 144, 255, 255, 255,
+ 57, 255, 255, 255, 86, 255, 255, 255, 144, 255, 255, 255, 144, 255, 255,
+ 255, 57, 255, 255, 255, 144, 187, 187, 187, 255, 0, 0, 0, 253, 70,
+ 70, 70, 255, 255, 255, 255, 255, 255, 255, 255, 254, 255, 255, 255, 255,
+ 255, 255, 255, 251, 255, 255, 255, 207, 255, 255, 255, 163, 187, 187, 187,
+ 255, 0, 0, 0, 253, 70, 70, 70, 255, 255, 255, 255, 251, 255, 255,
+ 255, 0, 255, 255, 255, 141, 255, 255, 255, 235, 255, 255, 255, 254, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 250, 255, 255, 255, 188,
+ 255, 255, 255, 54, 255, 255, 255, 198, 255, 255, 255, 234, 255, 255, 255,
+ 243, 255, 255, 255, 248, 255, 255, 255, 254, 255, 255, 255, 254, 255, 255,
+ 255, 251, 255, 255, 255, 207, 255, 255, 255, 17, 255, 255, 255, 0, 255,
+ 255, 255, 170, 255, 255, 255, 250, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 137, 137, 137, 255, 0, 0, 0, 253, 137, 137, 137,
+ 255, 255, 255, 255, 228, 255, 255, 255, 141, 255, 255, 255, 235, 255, 255,
+ 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 250, 255,
+ 255, 255, 188, 255, 255, 255, 54, 255, 255, 255, 198, 255, 255, 255, 234,
+ 255, 255, 255, 237, 255, 255, 255, 248, 255, 255, 255, 254, 255, 255, 255,
+ 253, 255, 255, 255, 255, 153, 153, 153, 255, 0, 0, 0, 253, 0, 0,
+ 0, 253, 0, 0, 0, 253, 0, 0, 0, 253, 0, 0, 0, 253, 0,
+ 0, 0, 253, 153, 153, 153, 255, 255, 255, 255, 251, 255, 255, 255, 0,
+ 255, 255, 255, 170, 255, 255, 255, 250, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 137, 137, 137, 255, 0, 0, 0, 253, 137, 137,
+ 137, 255, 255, 255, 255, 228, 255, 255, 255, 0, 255, 255, 255, 0, 255,
+ 255, 255, 0, 255, 255, 255, 86, 255, 255, 255, 215, 255, 255, 255, 240,
+ 255, 255, 255, 231, 255, 255, 255, 159, 255, 255, 255, 17, 255, 255, 255,
+ 0, 255, 255, 255, 57, 255, 255, 255, 206, 255, 255, 255, 237, 255, 255,
+ 255, 231, 255, 255, 255, 159, 255, 255, 255, 35, 255, 255, 255, 105, 255,
+ 255, 255, 142, 255, 255, 255, 208, 255, 255, 255, 229, 255, 255, 255, 237,
+ 255, 255, 255, 215, 255, 255, 255, 205, 255, 255, 255, 228, 255, 255, 255,
+ 234, 255, 255, 255, 198, 255, 255, 255, 36, 255, 255, 255, 0, 255, 255,
+ 255, 227, 187, 187, 187, 255, 187, 187, 187, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 187, 187, 187, 255, 207, 207, 207, 255, 255, 255, 255, 254,
+ 255, 255, 255, 255, 187, 187, 187, 255, 207, 207, 207, 255, 187, 187, 187,
+ 255, 187, 187, 187, 255, 255, 255, 255, 255, 255, 255, 255, 255, 187, 187,
+ 187, 255, 207, 207, 207, 255, 255, 255, 255, 254, 255, 255, 255, 255, 187,
+ 187, 187, 255, 207, 207, 207, 255, 187, 187, 187, 255, 187, 187, 187, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 187, 187, 187, 255, 207, 207, 207,
+ 255, 255, 255, 255, 254, 255, 255, 255, 255, 187, 187, 187, 255, 207, 207,
+ 207, 255, 255, 255, 255, 170, 255, 255, 255, 172, 187, 187, 187, 255, 0,
+ 0, 0, 253, 70, 70, 70, 255, 153, 153, 153, 255, 86, 86, 86, 255,
+ 70, 70, 70, 255, 118, 118, 118, 255, 239, 239, 239, 255, 255, 255, 255,
+ 255, 187, 187, 187, 255, 0, 0, 0, 253, 70, 70, 70, 255, 255, 255,
+ 255, 254, 255, 255, 255, 246, 255, 255, 255, 255, 153, 153, 153, 255, 118,
+ 118, 118, 255, 69, 69, 69, 254, 70, 70, 70, 255, 137, 137, 137, 255,
+ 239, 239, 239, 255, 255, 255, 255, 254, 223, 223, 223, 255, 137, 137, 137,
+ 255, 153, 153, 153, 255, 169, 169, 169, 255, 102, 102, 102, 255, 70, 70,
+ 70, 255, 118, 118, 118, 255, 239, 239, 239, 255, 255, 255, 255, 236, 255,
+ 255, 255, 236, 255, 255, 255, 255, 137, 137, 137, 255, 70, 70, 70, 255,
+ 70, 70, 70, 255, 137, 137, 137, 255, 118, 118, 118, 255, 0, 0, 0,
+ 253, 137, 137, 137, 255, 255, 255, 255, 254, 255, 255, 255, 255, 153, 153,
+ 153, 255, 118, 118, 118, 255, 69, 69, 69, 254, 70, 70, 70, 255, 137,
+ 137, 137, 255, 239, 239, 239, 255, 255, 255, 255, 254, 223, 223, 223, 255,
+ 137, 137, 137, 255, 153, 153, 153, 255, 207, 207, 207, 255, 86, 86, 86,
+ 255, 70, 70, 70, 255, 223, 223, 223, 255, 0, 0, 0, 253, 0, 0,
+ 0, 253, 137, 137, 137, 255, 255, 255, 255, 255, 239, 239, 239, 255, 86,
+ 86, 86, 255, 0, 0, 0, 253, 34, 34, 34, 255, 255, 255, 255, 253,
+ 255, 255, 255, 236, 255, 255, 255, 255, 137, 137, 137, 255, 70, 70, 70,
+ 255, 70, 70, 70, 255, 137, 137, 137, 255, 118, 118, 118, 255, 0, 0,
+ 0, 253, 137, 137, 137, 255, 255, 255, 255, 233, 255, 255, 255, 0, 255,
+ 255, 255, 0, 255, 255, 255, 214, 255, 255, 255, 255, 187, 187, 187, 255,
+ 137, 137, 137, 255, 153, 153, 153, 255, 239, 239, 239, 255, 255, 255, 255,
+ 254, 255, 255, 255, 224, 255, 255, 255, 255, 207, 207, 207, 255, 137, 137,
+ 137, 255, 153, 153, 153, 255, 239, 239, 239, 255, 255, 255, 255, 255, 239,
+ 239, 239, 255, 187, 187, 187, 255, 223, 223, 223, 255, 169, 169, 169, 255,
+ 137, 137, 137, 255, 187, 187, 187, 255, 255, 255, 255, 255, 153, 153, 153,
+ 255, 137, 137, 137, 255, 223, 223, 223, 255, 255, 255, 255, 255, 255, 255,
+ 255, 36, 255, 255, 255, 205, 86, 86, 86, 255, 0, 0, 0, 253, 239,
+ 239, 239, 255, 222, 222, 222, 255, 0, 0, 0, 253, 18, 18, 18, 255,
+ 255, 255, 255, 255, 207, 207, 207, 255, 0, 0, 0, 253, 137, 137, 137,
+ 255, 86, 86, 86, 255, 0, 0, 0, 253, 239, 239, 239, 255, 222, 222,
+ 222, 255, 0, 0, 0, 253, 18, 18, 18, 255, 255, 255, 255, 255, 207,
+ 207, 207, 255, 0, 0, 0, 253, 137, 137, 137, 255, 86, 86, 86, 255,
+ 0, 0, 0, 253, 239, 239, 239, 255, 222, 222, 222, 255, 0, 0, 0,
+ 253, 18, 18, 18, 255, 255, 255, 255, 255, 207, 207, 207, 255, 0, 0,
+ 0, 253, 137, 137, 137, 255, 255, 255, 255, 116, 255, 255, 255, 172, 187,
+ 187, 187, 255, 0, 0, 0, 253, 0, 0, 0, 253, 0, 0, 0, 253,
+ 70, 70, 70, 254, 33, 33, 33, 255, 0, 0, 0, 253, 18, 18, 18,
+ 255, 239, 239, 239, 255, 187, 187, 187, 255, 0, 0, 0, 253, 70, 70,
+ 70, 255, 255, 255, 255, 254, 255, 255, 255, 255, 50, 50, 50, 255, 0,
+ 0, 0, 253, 69, 69, 69, 254, 137, 137, 137, 254, 103, 103, 103, 254,
+ 0, 0, 0, 253, 18, 18, 18, 255, 239, 239, 239, 255, 187, 187, 187,
+ 255, 0, 0, 0, 253, 0, 0, 0, 253, 18, 18, 18, 255, 69, 69,
+ 69, 254, 18, 18, 18, 255, 0, 0, 0, 253, 70, 70, 70, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 70, 70, 70, 255, 0, 0, 0, 253,
+ 18, 18, 18, 255, 69, 69, 69, 254, 18, 18, 18, 255, 0, 0, 0,
+ 253, 0, 0, 0, 253, 137, 137, 137, 255, 255, 255, 255, 255, 50, 50,
+ 50, 255, 0, 0, 0, 253, 69, 69, 69, 254, 137, 137, 137, 254, 103,
+ 103, 103, 254, 0, 0, 0, 253, 18, 18, 18, 255, 239, 239, 239, 255,
+ 187, 187, 187, 255, 0, 0, 0, 253, 34, 34, 34, 255, 18, 18, 18,
+ 255, 0, 0, 0, 253, 0, 0, 0, 253, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 86, 86, 86, 255, 0, 0, 0, 253, 34, 34, 34, 255,
+ 255, 255, 255, 253, 255, 255, 255, 255, 70, 70, 70, 255, 0, 0, 0,
+ 253, 18, 18, 18, 255, 69, 69, 69, 254, 18, 18, 18, 255, 0, 0,
+ 0, 253, 0, 0, 0, 253, 137, 137, 137, 255, 255, 255, 255, 233, 255,
+ 255, 255, 0, 255, 255, 255, 57, 255, 255, 255, 255, 102, 102, 102, 255,
+ 0, 0, 0, 253, 49, 49, 49, 253, 18, 18, 18, 255, 18, 18, 18,
+ 255, 223, 223, 223, 255, 255, 255, 255, 255, 102, 102, 102, 255, 0, 0,
+ 0, 253, 49, 49, 49, 253, 18, 18, 18, 255, 18, 18, 18, 255, 207,
+ 207, 207, 255, 187, 187, 187, 255, 0, 0, 0, 253, 18, 18, 18, 255,
+ 50, 50, 50, 254, 18, 18, 18, 255, 0, 0, 0, 253, 34, 34, 34,
+ 255, 70, 70, 70, 253, 18, 18, 18, 255, 0, 0, 0, 253, 223, 223,
+ 223, 255, 255, 255, 255, 170, 255, 255, 255, 230, 153, 153, 153, 255, 0,
+ 0, 0, 253, 169, 169, 169, 255, 153, 153, 153, 255, 18, 18, 18, 255,
+ 0, 0, 0, 253, 207, 207, 207, 255, 137, 137, 137, 255, 0, 0, 0,
+ 253, 207, 207, 207, 255, 153, 153, 153, 255, 0, 0, 0, 253, 169, 169,
+ 169, 255, 153, 153, 153, 255, 18, 18, 18, 255, 0, 0, 0, 253, 207,
+ 207, 207, 255, 137, 137, 137, 255, 0, 0, 0, 253, 207, 207, 207, 255,
+ 153, 153, 153, 255, 0, 0, 0, 253, 169, 169, 169, 255, 153, 153, 153,
+ 255, 18, 18, 18, 255, 0, 0, 0, 253, 207, 207, 207, 255, 137, 137,
+ 137, 255, 0, 0, 0, 253, 207, 207, 207, 255, 255, 255, 255, 170, 255,
+ 255, 255, 172, 187, 187, 187, 255, 0, 0, 0, 253, 18, 18, 18, 255,
+ 207, 207, 207, 255, 255, 255, 255, 255, 255, 255, 255, 255, 86, 86, 86,
+ 255, 0, 0, 0, 253, 137, 137, 137, 255, 187, 187, 187, 255, 0, 0,
+ 0, 253, 70, 70, 70, 255, 255, 255, 255, 255, 169, 169, 169, 255, 0,
+ 0, 0, 253, 86, 86, 86, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 137, 137, 137, 255, 0, 0, 0, 253, 137, 137, 137,
+ 255, 187, 187, 187, 255, 0, 0, 0, 253, 0, 0, 0, 253, 207, 207,
+ 207, 255, 255, 255, 255, 255, 223, 223, 223, 255, 0, 0, 0, 253, 0,
+ 0, 0, 253, 255, 255, 255, 255, 187, 187, 187, 255, 0, 0, 0, 253,
+ 34, 34, 34, 255, 239, 239, 239, 255, 255, 255, 255, 255, 239, 239, 239,
+ 255, 50, 50, 50, 255, 0, 0, 0, 253, 137, 137, 137, 255, 169, 169,
+ 169, 255, 0, 0, 0, 253, 86, 86, 86, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 137, 137, 137, 255, 0, 0, 0, 253,
+ 137, 137, 137, 255, 187, 187, 187, 255, 0, 0, 0, 253, 0, 0, 0,
+ 253, 137, 137, 137, 255, 255, 255, 255, 255, 169, 169, 169, 255, 255, 255,
+ 255, 255, 255, 255, 255, 0, 255, 255, 255, 86, 138, 138, 138, 236, 0,
+ 0, 0, 253, 0, 0, 0, 253, 0, 0, 0, 253, 18, 18, 18, 255,
+ 223, 223, 223, 255, 255, 255, 255, 255, 187, 187, 187, 255, 0, 0, 0,
+ 253, 34, 34, 34, 255, 239, 239, 239, 255, 255, 255, 255, 255, 239, 239,
+ 239, 255, 50, 50, 50, 255, 0, 0, 0, 253, 137, 137, 137, 255, 255,
+ 255, 255, 233, 255, 255, 255, 0, 255, 255, 255, 170, 207, 207, 207, 255,
+ 0, 0, 0, 253, 118, 118, 118, 255, 255, 255, 255, 255, 187, 187, 187,
+ 255, 0, 0, 0, 253, 137, 137, 137, 254, 207, 207, 207, 255, 0, 0,
+ 0, 253, 118, 118, 118, 255, 255, 255, 255, 255, 239, 239, 239, 255, 0,
+ 0, 0, 253, 86, 86, 86, 255, 187, 187, 187, 255, 0, 0, 0, 253,
+ 86, 86, 86, 255, 255, 255, 255, 255, 169, 169, 169, 255, 0, 0, 0,
+ 253, 102, 102, 102, 255, 255, 255, 255, 255, 169, 169, 169, 255, 0, 0,
+ 0, 253, 137, 137, 137, 255, 255, 255, 255, 198, 255, 255, 255, 141, 239,
+ 239, 239, 255, 0, 0, 0, 253, 102, 102, 102, 255, 102, 102, 102, 255,
+ 86, 86, 86, 255, 18, 18, 18, 255, 137, 137, 137, 255, 86, 86, 86,
+ 255, 34, 34, 34, 255, 255, 255, 255, 255, 239, 239, 239, 255, 0, 0,
+ 0, 253, 102, 102, 102, 255, 102, 102, 102, 255, 86, 86, 86, 255, 18,
+ 18, 18, 255, 137, 137, 137, 255, 86, 86, 86, 255, 34, 34, 34, 255,
+ 255, 255, 255, 255, 239, 239, 239, 255, 0, 0, 0, 253, 102, 102, 102,
+ 255, 102, 102, 102, 255, 86, 86, 86, 255, 18, 18, 18, 255, 137, 137,
+ 137, 255, 86, 86, 86, 255, 34, 34, 34, 255, 255, 255, 255, 255, 255,
+ 255, 255, 57, 255, 255, 255, 172, 187, 187, 187, 255, 0, 0, 0, 253,
+ 70, 70, 70, 255, 255, 255, 255, 255, 255, 255, 255, 57, 255, 255, 255,
+ 245, 187, 187, 187, 255, 0, 0, 0, 253, 70, 70, 70, 255, 187, 187,
+ 187, 255, 0, 0, 0, 253, 70, 70, 70, 255, 255, 255, 255, 255, 137,
+ 137, 137, 255, 0, 0, 0, 253, 0, 0, 0, 253, 0, 0, 0, 253,
+ 0, 0, 0, 253, 0, 0, 0, 253, 0, 0, 0, 253, 0, 0, 0,
+ 253, 70, 70, 70, 255, 187, 187, 187, 255, 0, 0, 0, 253, 70, 70,
+ 70, 255, 255, 255, 255, 255, 255, 255, 255, 95, 255, 255, 255, 255, 0,
+ 0, 0, 253, 0, 0, 0, 253, 255, 255, 255, 255, 137, 137, 137, 255,
+ 0, 0, 0, 253, 137, 137, 137, 255, 255, 255, 255, 254, 255, 255, 255,
+ 35, 255, 255, 255, 253, 137, 137, 137, 255, 0, 0, 0, 253, 137, 137,
+ 137, 255, 137, 137, 137, 255, 0, 0, 0, 253, 0, 0, 0, 253, 0,
+ 0, 0, 253, 0, 0, 0, 253, 0, 0, 0, 253, 0, 0, 0, 253,
+ 0, 0, 0, 253, 70, 70, 70, 255, 187, 187, 187, 255, 0, 0, 0,
+ 253, 50, 50, 50, 255, 255, 255, 255, 255, 255, 255, 255, 222, 255, 255,
+ 255, 213, 255, 255, 255, 252, 255, 255, 255, 254, 255, 255, 255, 254, 187,
+ 187, 187, 255, 137, 137, 137, 255, 137, 137, 137, 255, 34, 34, 34, 255,
+ 0, 0, 0, 253, 34, 34, 34, 255, 255, 255, 255, 255, 137, 137, 137,
+ 255, 0, 0, 0, 253, 137, 137, 137, 255, 255, 255, 255, 254, 255, 255,
+ 255, 35, 255, 255, 255, 253, 137, 137, 137, 255, 0, 0, 0, 253, 137,
+ 137, 137, 255, 255, 255, 255, 233, 255, 255, 255, 0, 255, 255, 255, 194,
+ 137, 137, 137, 255, 0, 0, 0, 253, 187, 187, 187, 255, 255, 255, 255,
+ 242, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 137, 137,
+ 137, 255, 0, 0, 0, 253, 187, 187, 187, 255, 255, 255, 255, 234, 255,
+ 255, 255, 255, 70, 70, 70, 255, 18, 18, 18, 255, 187, 187, 187, 255,
+ 0, 0, 0, 253, 137, 137, 137, 255, 255, 255, 255, 253, 187, 187, 187,
+ 255, 0, 0, 0, 253, 137, 137, 137, 255, 255, 255, 255, 252, 187, 187,
+ 187, 255, 0, 0, 0, 253, 137, 137, 137, 255, 255, 255, 255, 233, 255,
+ 255, 255, 17, 255, 255, 255, 255, 70, 70, 70, 255, 34, 34, 34, 255,
+ 50, 50, 50, 255, 137, 137, 137, 255, 86, 86, 86, 255, 70, 70, 70,
+ 255, 0, 0, 0, 253, 118, 118, 118, 255, 255, 255, 255, 253, 255, 255,
+ 255, 255, 70, 70, 70, 255, 34, 34, 34, 255, 50, 50, 50, 255, 137,
+ 137, 137, 255, 86, 86, 86, 255, 70, 70, 70, 255, 0, 0, 0, 253,
+ 118, 118, 118, 255, 255, 255, 255, 253, 255, 255, 255, 255, 70, 70, 70,
+ 255, 34, 34, 34, 255, 50, 50, 50, 255, 137, 137, 137, 255, 86, 86,
+ 86, 255, 70, 70, 70, 255, 0, 0, 0, 253, 118, 118, 118, 255, 255,
+ 255, 255, 255, 255, 255, 255, 252, 255, 255, 255, 254, 187, 187, 187, 255,
+ 0, 0, 0, 253, 50, 50, 50, 255, 255, 255, 255, 255, 255, 255, 255,
+ 250, 255, 255, 255, 255, 153, 153, 153, 255, 0, 0, 0, 253, 86, 86,
+ 86, 255, 187, 187, 187, 255, 0, 0, 0, 253, 70, 70, 70, 255, 255,
+ 255, 255, 255, 137, 137, 137, 255, 0, 0, 0, 253, 86, 86, 86, 255,
+ 187, 187, 187, 255, 187, 187, 187, 255, 187, 187, 187, 255, 187, 187, 187,
+ 255, 187, 187, 187, 255, 207, 207, 207, 255, 187, 187, 187, 255, 0, 0,
+ 0, 253, 70, 70, 70, 255, 255, 255, 255, 254, 255, 255, 255, 0, 255,
+ 255, 255, 255, 0, 0, 0, 253, 0, 0, 0, 253, 255, 255, 255, 255,
+ 137, 137, 137, 255, 0, 0, 0, 253, 102, 102, 102, 255, 255, 255, 255,
+ 255, 255, 255, 255, 243, 255, 255, 255, 255, 118, 118, 118, 255, 0, 0,
+ 0, 253, 137, 137, 137, 255, 137, 137, 137, 255, 0, 0, 0, 253, 86,
+ 86, 86, 255, 187, 187, 187, 255, 187, 187, 187, 255, 187, 187, 187, 255,
+ 187, 187, 187, 255, 187, 187, 187, 255, 207, 207, 207, 255, 187, 187, 187,
+ 255, 0, 0, 0, 253, 70, 70, 70, 255, 255, 255, 255, 254, 255, 255,
+ 255, 0, 255, 255, 255, 86, 153, 153, 153, 255, 70, 70, 70, 255, 102,
+ 102, 102, 255, 255, 255, 255, 255, 255, 255, 255, 254, 255, 255, 255, 255,
+ 187, 187, 187, 255, 0, 0, 0, 253, 0, 0, 0, 253, 187, 187, 187,
+ 255, 137, 137, 137, 255, 0, 0, 0, 253, 102, 102, 102, 255, 255, 255,
+ 255, 255, 255, 255, 255, 243, 255, 255, 255, 255, 118, 118, 118, 255, 0,
+ 0, 0, 253, 137, 137, 137, 255, 255, 255, 255, 254, 255, 255, 255, 252,
+ 255, 255, 255, 254, 153, 153, 153, 255, 0, 0, 0, 253, 169, 169, 169,
+ 255, 255, 255, 255, 251, 255, 255, 255, 255, 187, 187, 187, 255, 207, 207,
+ 207, 255, 153, 153, 153, 255, 0, 0, 0, 253, 169, 169, 169, 255, 255,
+ 255, 255, 248, 255, 255, 255, 255, 50, 50, 50, 255, 34, 34, 34, 255,
+ 187, 187, 187, 255, 0, 0, 0, 253, 137, 137, 137, 255, 255, 255, 255,
+ 249, 187, 187, 187, 255, 0, 0, 0, 253, 137, 137, 137, 255, 255, 255,
+ 255, 249, 187, 187, 187, 255, 0, 0, 0, 253, 137, 137, 137, 255, 255,
+ 255, 255, 233, 255, 255, 255, 0, 255, 255, 255, 241, 137, 137, 137, 255,
+ 0, 0, 0, 253, 0, 0, 0, 253, 207, 207, 207, 255, 153, 153, 153,
+ 255, 0, 0, 0, 253, 0, 0, 0, 253, 207, 207, 207, 255, 255, 255,
+ 255, 200, 255, 255, 255, 241, 137, 137, 137, 255, 0, 0, 0, 253, 0,
+ 0, 0, 253, 207, 207, 207, 255, 153, 153, 153, 255, 0, 0, 0, 253,
+ 0, 0, 0, 253, 207, 207, 207, 255, 255, 255, 255, 200, 255, 255, 255,
+ 241, 137, 137, 137, 255, 0, 0, 0, 253, 0, 0, 0, 253, 207, 207,
+ 207, 255, 153, 153, 153, 255, 0, 0, 0, 253, 0, 0, 0, 253, 207,
+ 207, 207, 255, 207, 207, 207, 255, 70, 70, 70, 255, 118, 118, 118, 255,
+ 187, 187, 187, 255, 0, 0, 0, 253, 0, 0, 0, 253, 86, 86, 86,
+ 255, 187, 187, 187, 255, 153, 153, 153, 255, 18, 18, 18, 255, 0, 0,
+ 0, 253, 169, 169, 169, 255, 187, 187, 187, 255, 0, 0, 0, 253, 70,
+ 70, 70, 255, 255, 255, 255, 255, 223, 223, 223, 255, 0, 0, 0, 253,
+ 18, 18, 18, 255, 169, 169, 169, 255, 255, 255, 255, 255, 223, 223, 223,
+ 255, 50, 50, 50, 255, 0, 0, 0, 253, 138, 138, 138, 248, 187, 187,
+ 187, 255, 0, 0, 0, 253, 70, 70, 70, 255, 255, 255, 255, 254, 255,
+ 255, 255, 0, 255, 255, 255, 255, 0, 0, 0, 253, 0, 0, 0, 253,
+ 255, 255, 255, 255, 223, 223, 223, 255, 18, 18, 18, 255, 0, 0, 0,
+ 253, 137, 137, 137, 255, 187, 187, 187, 255, 137, 137, 137, 255, 0, 0,
+ 0, 253, 0, 0, 0, 253, 137, 137, 137, 255, 223, 223, 223, 255, 0,
+ 0, 0, 253, 18, 18, 18, 255, 169, 169, 169, 255, 255, 255, 255, 255,
+ 223, 223, 223, 255, 50, 50, 50, 255, 0, 0, 0, 253, 138, 138, 138,
+ 248, 187, 187, 187, 255, 0, 0, 0, 253, 70, 70, 70, 255, 255, 255,
+ 255, 254, 255, 255, 255, 0, 255, 255, 255, 141, 186, 186, 186, 252, 0,
+ 0, 0, 253, 0, 0, 0, 253, 118, 118, 118, 255, 187, 187, 187, 255,
+ 169, 169, 169, 255, 50, 50, 50, 255, 0, 0, 0, 253, 18, 18, 18,
+ 255, 255, 255, 255, 255, 223, 223, 223, 255, 18, 18, 18, 255, 0, 0,
+ 0, 253, 137, 137, 137, 255, 187, 187, 187, 255, 137, 137, 137, 255, 0,
+ 0, 0, 253, 0, 0, 0, 253, 137, 137, 137, 255, 207, 207, 207, 255,
+ 70, 70, 70, 255, 118, 118, 118, 255, 223, 223, 223, 255, 0, 0, 0,
+ 253, 86, 86, 86, 255, 239, 239, 239, 255, 137, 137, 137, 255, 0, 0,
+ 0, 253, 153, 153, 153, 249, 223, 223, 223, 255, 0, 0, 0, 253, 86,
+ 86, 86, 255, 239, 239, 239, 255, 187, 187, 187, 255, 0, 0, 0, 253,
+ 102, 102, 102, 255, 187, 187, 187, 255, 0, 0, 0, 253, 137, 137, 137,
+ 255, 255, 255, 255, 249, 187, 187, 187, 255, 0, 0, 0, 253, 137, 137,
+ 137, 255, 255, 255, 255, 249, 187, 187, 187, 255, 0, 0, 0, 253, 137,
+ 137, 137, 255, 255, 255, 255, 233, 255, 255, 255, 0, 255, 255, 255, 170,
+ 223, 223, 223, 255, 0, 0, 0, 253, 18, 18, 18, 255, 255, 255, 255,
+ 255, 223, 223, 223, 255, 0, 0, 0, 253, 34, 34, 34, 255, 255, 255,
+ 255, 255, 255, 255, 255, 57, 255, 255, 255, 170, 223, 223, 223, 255, 0,
+ 0, 0, 253, 18, 18, 18, 255, 255, 255, 255, 255, 223, 223, 223, 255,
+ 0, 0, 0, 253, 34, 34, 34, 255, 255, 255, 255, 255, 255, 255, 255,
+ 57, 255, 255, 255, 170, 223, 223, 223, 255, 0, 0, 0, 253, 18, 18,
+ 18, 255, 255, 255, 255, 255, 223, 223, 223, 255, 0, 0, 0, 253, 34,
+ 34, 34, 255, 255, 255, 255, 255, 187, 187, 187, 247, 0, 0, 0, 253,
+ 70, 70, 70, 253, 187, 187, 187, 255, 0, 0, 0, 253, 34, 34, 34,
+ 255, 50, 50, 50, 255, 0, 0, 0, 253, 0, 0, 0, 253, 0, 0,
+ 0, 253, 137, 137, 137, 255, 255, 255, 255, 255, 187, 187, 187, 255, 0,
+ 0, 0, 253, 70, 70, 70, 255, 255, 255, 255, 241, 255, 255, 255, 255,
+ 169, 169, 169, 255, 34, 34, 34, 255, 0, 0, 0, 253, 0, 0, 0,
+ 253, 0, 0, 0, 253, 18, 18, 18, 255, 137, 137, 137, 255, 255, 255,
+ 255, 255, 187, 187, 187, 255, 0, 0, 0, 253, 70, 70, 70, 255, 255,
+ 255, 255, 236, 255, 255, 255, 0, 255, 255, 255, 255, 0, 0, 0, 253,
+ 0, 0, 0, 253, 255, 255, 255, 255, 255, 255, 255, 254, 153, 153, 153,
+ 255, 18, 18, 18, 255, 0, 0, 0, 253, 0, 0, 0, 253, 18, 18,
+ 18, 255, 70, 70, 70, 255, 0, 0, 0, 253, 137, 137, 137, 255, 255,
+ 255, 255, 255, 169, 169, 169, 255, 34, 34, 34, 255, 0, 0, 0, 253,
+ 0, 0, 0, 253, 0, 0, 0, 253, 18, 18, 18, 255, 137, 137, 137,
+ 255, 255, 255, 255, 255, 187, 187, 187, 255, 0, 0, 0, 253, 70, 70,
+ 70, 255, 255, 255, 255, 236, 255, 255, 255, 0, 255, 255, 255, 86, 255,
+ 255, 255, 255, 153, 153, 153, 255, 34, 34, 34, 255, 0, 0, 0, 253,
+ 0, 0, 0, 253, 0, 0, 0, 253, 0, 0, 0, 253, 50, 50, 50,
+ 255, 187, 187, 187, 255, 255, 255, 255, 254, 255, 255, 255, 254, 153, 153,
+ 153, 255, 18, 18, 18, 255, 0, 0, 0, 253, 0, 0, 0, 253, 18,
+ 18, 18, 255, 70, 70, 70, 255, 0, 0, 0, 253, 137, 137, 137, 255,
+ 187, 187, 187, 251, 0, 0, 0, 253, 70, 70, 70, 252, 255, 255, 255,
+ 255, 153, 153, 153, 255, 18, 18, 18, 255, 0, 0, 0, 253, 0, 0,
+ 0, 253, 102, 102, 102, 255, 255, 255, 255, 255, 255, 255, 255, 255, 153,
+ 153, 153, 255, 18, 18, 18, 255, 0, 0, 0, 253, 0, 0, 0, 253,
+ 70, 70, 70, 255, 239, 239, 239, 255, 187, 187, 187, 255, 0, 0, 0,
+ 253, 137, 137, 137, 255, 255, 255, 255, 215, 187, 187, 187, 255, 0, 0,
+ 0, 253, 137, 137, 137, 255, 255, 255, 255, 215, 187, 187, 187, 255, 0,
+ 0, 0, 253, 137, 137, 137, 255, 255, 255, 255, 170, 255, 255, 255, 0,
+ 255, 255, 255, 36, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 251, 255, 255, 255, 0, 255, 255, 255, 36, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 251, 255, 255, 255, 0, 255, 255, 255, 36, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 215, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 236,
+ 255, 255, 255, 113, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 215, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 236, 255, 255, 255, 0, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 141, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 222, 255, 255, 255, 253, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 215, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 236, 255, 255, 255, 0, 255,
+ 255, 255, 0, 255, 255, 255, 141, 255, 255, 255, 253, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 250, 255, 255, 255, 86, 255, 255,
+ 255, 141, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 248, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 214, 255,
+ 255, 255, 141, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 246, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 215, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 215, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 170, };
+
+ *width = 136;
+ *height = 11;
+
+ // only load the requested logo
+ // allocate a new array
+ *data = new unsigned char[5984];
+ // and copy it. Now we are certain that the calling function
+ // can control the memory location
+ for(int i = 0; i < 5984 /* tmp array size */; i++)
+ {
+ (*data)[i] = logo_blender3d_raw[i];
+ }
+
+}
+
+
+
diff --git a/source/gameengine/GamePlayer/common/GPC_RawLogoArrays.h b/source/gameengine/GamePlayer/common/GPC_RawLogoArrays.h
new file mode 100644
index 00000000000..84598f7bfe8
--- /dev/null
+++ b/source/gameengine/GamePlayer/common/GPC_RawLogoArrays.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 __GPC_RAWLOGOARRAYS_H
+#define __GPC_RAWLOGOARRAYS_H
+
+
+void GetRawBlenderLogo(unsigned char **data, int *width, int *height);
+void GetRawBlender3DLogo(unsigned char **data, int *width, int *height);
+#if 0
+void GetRawNaNLogo(unsigned char **data, int *width, int *height);
+#endif
+
+#endif // __GPC_RAWLOGOARRAYS_H
+
diff --git a/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp b/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp
new file mode 100644
index 00000000000..329cf1c4bad
--- /dev/null
+++ b/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp
@@ -0,0 +1,498 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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)
+#include <windows.h>
+#endif
+
+#include <GL/gl.h>
+#include <iostream>
+
+#include "GPC_RenderTools.h"
+
+#include "RAS_IRenderTools.h"
+#include "RAS_IRasterizer.h"
+#include "RAS_LightObject.h"
+#include "RAS_ICanvas.h"
+
+// next two includes/dependencies come from the shadow feature
+// it needs the gameobject and the sumo physics scene for a raycast
+#include "KX_GameObject.h"
+
+#include "GPC_PolygonMaterial.h"
+#include "Value.h"
+
+//#include "KX_BlenderGL.h" // for text printing
+//#include "KX_BlenderClientObject.h"
+#include "STR_String.h"
+#include "RAS_BucketManager.h" // for polymaterial (needed for textprinting)
+
+
+// Blender includes
+/* This list includes only data type definitions */
+#include "DNA_object_types.h"
+#include "DNA_material_types.h"
+#include "DNA_image_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_group_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_property_types.h"
+#include "DNA_text_types.h"
+#include "DNA_sensor_types.h"
+#include "DNA_controller_types.h"
+#include "DNA_actuator_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_world_types.h"
+
+#include "BKE_global.h"
+#include "BKE_image.h"
+#include "BKE_bmfont.h"
+#include "BKE_bmfont_types.h"
+#include "BKE_main.h"
+
+#include "IMB_imbuf_types.h"
+// End of Blender includes
+
+
+GPC_RenderTools::GPC_RenderTools()
+{
+ m_font = BMF_GetFont(BMF_kHelvetica10);
+}
+
+
+GPC_RenderTools::~GPC_RenderTools()
+{
+}
+
+
+void GPC_RenderTools::EndFrame(RAS_IRasterizer* rasty)
+{
+}
+
+
+void GPC_RenderTools::BeginFrame(RAS_IRasterizer* rasty)
+{
+ m_clientobject=NULL;
+ m_modified=true;
+ DisableOpenGLLights();
+
+}
+
+int GPC_RenderTools::ProcessLighting(int layer)
+{
+ int result = false;
+
+ if (layer < 0)
+ {
+ DisableOpenGLLights();
+ result = false;
+ } else
+ {
+ if (m_clientobject)
+ {
+ if (applyLights(layer))
+ {
+ EnableOpenGLLights();
+ result = true;
+ } else
+ {
+ DisableOpenGLLights();
+ result = false;
+ }
+ }
+ }
+ return result;
+}
+
+
+void GPC_RenderTools::RenderText2D(RAS_TEXT_RENDER_MODE mode,
+ const char* text,
+ int xco,
+ int yco,
+ int width,
+ int height)
+{
+ STR_String tmpstr(text);
+ int lines;
+ char* s = tmpstr.Ptr();
+ char* p;
+
+ // Save and change OpenGL settings
+ int texture2D;
+ glGetIntegerv(GL_TEXTURE_2D, (GLint*)&texture2D);
+ glDisable(GL_TEXTURE_2D);
+ int fog;
+ glGetIntegerv(GL_FOG, (GLint*)&fog);
+ glDisable(GL_FOG);
+
+ // Set up viewing settings
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+ glOrtho(0, width, 0, height, -1, 1);
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glLoadIdentity();
+
+ // Actual drawing
+ unsigned char colors[2][3] = {
+ {0x00, 0x00, 0x00},
+ {0xFF, 0xFF, 0xFF}
+ };
+ int numTimes = mode == RAS_TEXT_PADDED ? 2 : 1;
+ for (int i = 0; i < numTimes; i++) {
+ glColor3ub(colors[i][0], colors[i][1], colors[i][2]);
+ glRasterPos2i(xco, yco);
+ for (p = s, lines = 0; *p; p++) {
+ if (*p == '\n')
+ {
+ lines++;
+ glRasterPos2i(xco, yco-(lines*18));
+ }
+ BMF_DrawCharacter(m_font, *p);
+ }
+ xco += 1;
+ yco += 1;
+ }
+
+ // Restore view settings
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+
+ // Restore OpenGL Settings
+ fog ? ::glEnable(GL_FOG) : ::glDisable(GL_FOG);
+ texture2D ? ::glEnable(GL_TEXTURE_2D) : ::glDisable(GL_TEXTURE_2D);
+}
+
+/**
+ * Copied from KX_BlenderRenderTools.cpp in KX_blenderhook
+ * Renders text into a (series of) polygon(s), using a texture font,
+ * Each character consists of one polygon (one quad or two triangles)
+ */
+void GPC_RenderTools::RenderText(
+ int mode,
+ RAS_IPolyMaterial* polymat,
+ float v1[3], float v2[3], float v3[3], float v4[3])
+{
+ STR_String mytext = ((CValue*)m_clientobject)->GetPropertyText("Text");
+
+ GPC_PolygonMaterial* blenderpoly = (GPC_PolygonMaterial*)polymat;
+ struct TFace* tface = blenderpoly->GetTFace();
+
+ BL_RenderText(mode, mytext, mytext.Length(), tface, v1, v2, v3, v4);
+}
+
+
+
+/**
+ * Copied from KX_BlenderGL.cpp in KX_blenderhook
+ */
+void GPC_RenderTools::BL_RenderText(
+ int mode,
+ const char* textstr,
+ int textlen,
+ struct TFace* tface,
+ float v1[3],float v2[3],float v3[3],float v4[3])
+{
+ struct Image* ima;
+
+ if (mode & TF_BMFONT) {
+ //char string[MAX_PROPSTRING];
+// float tmat[4][4];
+ int characters, index, character;
+ float centerx, centery, sizex, sizey, transx, transy, movex, movey, advance;
+
+// bProperty *prop;
+
+ // string = "Frank van Beek";
+
+ characters = textlen;
+
+ ima = (struct Image*) tface->tpage;
+ if (ima == NULL) {
+ characters = 0;
+ }
+
+ glPushMatrix();
+ for (index = 0; index < characters; index++) {
+ // lets calculate offset stuff
+ character = textstr[index];
+
+ // space starts at offset 1
+ // character = character - ' ' + 1;
+
+ matrixGlyph(ima->ibuf, character, & centerx, &centery, &sizex, &sizey, &transx, &transy, &movex, &movey, &advance);
+
+ glBegin(GL_POLYGON);
+ // printf(" %c %f %f %f %f\n", character, tface->uv[0][0], tface->uv[0][1], );
+ // glTexCoord2f((tface->uv[0][0] - centerx) * sizex + transx, (tface->uv[0][1] - centery) * sizey + transy);
+ glTexCoord2f((tface->uv[0][0] - centerx) * sizex + transx, (tface->uv[0][1] - centery) * sizey + transy);
+
+ BL_spack(tface->col[0]);
+ // glVertex3fv(v1);
+ glVertex3f(sizex * v1[0] + movex, sizey * v1[1] + movey, v1[2]);
+
+ glTexCoord2f((tface->uv[1][0] - centerx) * sizex + transx, (tface->uv[1][1] - centery) * sizey + transy);
+ BL_spack(tface->col[1]);
+ // glVertex3fv(v2);
+ glVertex3f(sizex * v2[0] + movex, sizey * v2[1] + movey, v2[2]);
+
+ glTexCoord2f((tface->uv[2][0] - centerx) * sizex + transx, (tface->uv[2][1] - centery) * sizey + transy);
+ BL_spack(tface->col[2]);
+ // glVertex3fv(v3);
+ glVertex3f(sizex * v3[0] + movex, sizey * v3[1] + movey, v3[2]);
+
+ if(v4) {
+ // glTexCoord2f((tface->uv[3][0] - centerx) * sizex + transx, 1.0 - (1.0 - tface->uv[3][1]) * sizey - transy);
+ glTexCoord2f((tface->uv[3][0] - centerx) * sizex + transx, (tface->uv[3][1] - centery) * sizey + transy);
+ BL_spack(tface->col[3]);
+ // glVertex3fv(v4);
+ glVertex3f(sizex * v4[0] + movex, sizey * v4[1] + movey, v4[2]);
+ }
+ glEnd();
+
+ glTranslatef(advance, 0.0, 0.0);
+ }
+ glPopMatrix();
+
+ }
+}
+
+
+RAS_IPolyMaterial* GPC_RenderTools::CreateBlenderPolyMaterial(
+ const STR_String &texname,
+ bool ba,const STR_String& matname,int tile,int tilexrep,int tileyrep,int mode,int transparant,int lightlayer
+ ,bool bIsTriangle,void* clientobject,void* tface)
+{
+ return new GPC_PolygonMaterial(texname, ba,matname,tile,tilexrep,tileyrep,
+ mode,transparant,lightlayer,bIsTriangle,clientobject,tface);
+}
+
+
+int GPC_RenderTools::applyLights(int objectlayer)
+{
+// taken from blender source, incompatibility between Blender Object / GameObject
+
+ int count;
+ float vec[4];
+
+ vec[3]= 1.0;
+
+ for(count=0; count<8; count++)
+ glDisable((GLenum)(GL_LIGHT0+count));
+
+ count= 0;
+
+ //std::vector<struct RAS_LightObject*> m_lights;
+ std::vector<struct RAS_LightObject*>::iterator lit = m_lights.begin();
+
+
+ for (lit = m_lights.begin(); !(lit==m_lights.end()); ++lit)
+ {
+ RAS_LightObject* lightdata = (*lit);
+ if (lightdata->m_layer & objectlayer)
+ {
+
+ glPushMatrix();
+ glLoadMatrixf(m_viewmat);
+
+
+ vec[0] = (*(lightdata->m_worldmatrix))(0,3);
+ vec[1] = (*(lightdata->m_worldmatrix))(1,3);
+ vec[2] = (*(lightdata->m_worldmatrix))(2,3);
+ vec[3] = 1;
+
+
+ if(lightdata->m_type==RAS_LightObject::LIGHT_SUN) {
+
+ vec[0] = (*(lightdata->m_worldmatrix))(0,2);
+ vec[1] = (*(lightdata->m_worldmatrix))(1,2);
+ vec[2] = (*(lightdata->m_worldmatrix))(2,2);
+ //vec[0]= base->object->obmat[2][0];
+ //vec[1]= base->object->obmat[2][1];
+ //vec[2]= base->object->obmat[2][2];
+ vec[3]= 0.0;
+ glLightfv((GLenum)(GL_LIGHT0+count), GL_POSITION, vec);
+ }
+ else {
+ //vec[3]= 1.0;
+ glLightfv((GLenum)(GL_LIGHT0+count), GL_POSITION, vec);
+ glLightf((GLenum)(GL_LIGHT0+count), GL_CONSTANT_ATTENUATION, 1.0);
+ glLightf((GLenum)(GL_LIGHT0+count), GL_LINEAR_ATTENUATION, lightdata->m_att1/lightdata->m_distance);
+ // without this next line it looks backward compatible.
+ //attennuation still is acceptable
+ // glLightf((GLenum)(GL_LIGHT0+count), GL_QUADRATIC_ATTENUATION, la->att2/(la->dist*la->dist));
+
+ if(lightdata->m_type==RAS_LightObject::LIGHT_SPOT) {
+ vec[0] = -(*(lightdata->m_worldmatrix))(0,2);
+ vec[1] = -(*(lightdata->m_worldmatrix))(1,2);
+ vec[2] = -(*(lightdata->m_worldmatrix))(2,2);
+ //vec[0]= -base->object->obmat[2][0];
+ //vec[1]= -base->object->obmat[2][1];
+ //vec[2]= -base->object->obmat[2][2];
+ glLightfv((GLenum)(GL_LIGHT0+count), GL_SPOT_DIRECTION, vec);
+ glLightf((GLenum)(GL_LIGHT0+count), GL_SPOT_CUTOFF, lightdata->m_spotsize/2.0);
+ glLightf((GLenum)(GL_LIGHT0+count), GL_SPOT_EXPONENT, 128.0*lightdata->m_spotblend);
+ }
+ else glLightf((GLenum)(GL_LIGHT0+count), GL_SPOT_CUTOFF, 180.0);
+ }
+
+ vec[0]= lightdata->m_energy*lightdata->m_red;
+ vec[1]= lightdata->m_energy*lightdata->m_green;
+ vec[2]= lightdata->m_energy*lightdata->m_blue;
+ vec[3]= 1.0;
+ glLightfv((GLenum)(GL_LIGHT0+count), GL_DIFFUSE, vec);
+ glLightfv((GLenum)(GL_LIGHT0+count), GL_SPECULAR, vec);
+ glEnable((GLenum)(GL_LIGHT0+count));
+
+ glPopMatrix();
+
+ count++;
+ if(count>7)
+ break;
+ }
+ }
+
+ return count;
+
+}
+
+
+void GPC_RenderTools::applyTransform(RAS_IRasterizer* rasty,double* oglmatrix,int objectdrawmode )
+{
+ if (objectdrawmode & RAS_IPolyMaterial::BILLBOARD_SCREENALIGNED ||
+ objectdrawmode & RAS_IPolyMaterial::BILLBOARD_AXISALIGNED)
+ {
+ // rotate the billboard/halo
+ //page 360/361 3D Game Engine Design, David Eberly for a discussion
+ // on screen aligned and axis aligned billboards
+ // assumed is that the preprocessor transformed all billboard polygons
+ // so that their normal points into the positive x direction (1.0 , 0.0 , 0.0)
+ // when new parenting for objects is done, this rotation
+ // will be moved into the object
+
+ MT_Point3 objpos (oglmatrix[12],oglmatrix[13],oglmatrix[14]);
+ MT_Point3 campos = rasty->GetCameraPosition();
+ MT_Vector3 dir = (campos - objpos).safe_normalized();
+ MT_Vector3 up(0,0,1.0);
+
+ KX_GameObject* gameobj = (KX_GameObject*) this->m_clientobject;
+ // get scaling of halo object
+ MT_Vector3 size = gameobj->GetSGNode()->GetLocalScale();
+
+ bool screenaligned = (objectdrawmode & RAS_IPolyMaterial::BILLBOARD_SCREENALIGNED)!=0;//false; //either screen or axisaligned
+ if (screenaligned)
+ {
+ up = (up - up.dot(dir) * dir).safe_normalized();
+ } else
+ {
+ dir = (dir - up.dot(dir)*up).safe_normalized();
+ }
+
+ MT_Vector3 left = dir.normalized();
+ dir = (left.cross(up)).normalized();
+
+ // we have calculated the row vectors, now we keep
+ // local scaling into account:
+
+ left *= size[0];
+ dir *= size[1];
+ up *= size[2];
+ double maat[16]={
+ left[0], left[1],left[2], 0,
+ dir[0], dir[1],dir[2],0,
+ up[0],up[1],up[2],0,
+ 0,0,0,1};
+ glTranslated(objpos[0],objpos[1],objpos[2]);
+ glMultMatrixd(maat);
+
+ } else
+ {
+ if (objectdrawmode & RAS_IPolyMaterial::SHADOW)
+ {
+ // shadow must be cast to the ground, physics system needed here!
+ KX_GameObject* gameobj = (KX_GameObject*) this->m_clientobject;
+ MT_Point3 frompoint(oglmatrix[12],oglmatrix[13],oglmatrix[14]);
+ MT_Vector3 direction = MT_Vector3(0,0,-1);
+
+
+ direction.normalize();
+ direction *= 100000;
+
+ MT_Point3 topoint = frompoint + direction;
+ MT_Point3 resultpoint;
+ MT_Vector3 resultnormal;
+
+ //todo: replace by physicsenvironment raycast
+
+ //SM_Scene* scene = (SM_Scene*) m_auxilaryClientInfo;
+
+ SM_Object* hitObj = 0;
+ //scene->rayTest(gameobj->GetSumoObject(),frompoint,topoint,
+ // resultpoint, resultnormal);
+
+
+ if (hitObj)
+ {
+ MT_Vector3 left(oglmatrix[0],oglmatrix[1],oglmatrix[2]);
+ MT_Vector3 dir = -(left.cross(resultnormal)).normalized();
+ left = (dir.cross(resultnormal)).normalized();
+ // for the up vector, we take the 'resultnormal' returned by the physics
+
+ double maat[16]={
+ left[0], left[1],left[2], 0,
+ dir[0], dir[1],dir[2],0,
+ resultnormal[0],resultnormal[1],resultnormal[2],0,
+ 0,0,0,1};
+ glTranslated(resultpoint[0],resultpoint[1],resultpoint[2]);
+ glMultMatrixd(maat);
+ // glMultMatrixd(oglmatrix);
+ } else
+ {
+ glMultMatrixd(oglmatrix);
+ }
+
+
+ } else
+ {
+
+ // 'normal' object
+ glMultMatrixd(oglmatrix);
+ }
+ }
+}
diff --git a/source/gameengine/GamePlayer/common/GPC_RenderTools.h b/source/gameengine/GamePlayer/common/GPC_RenderTools.h
new file mode 100644
index 00000000000..7021e7a4a43
--- /dev/null
+++ b/source/gameengine/GamePlayer/common/GPC_RenderTools.h
@@ -0,0 +1,176 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 __GPC_RENDERTOOLS_H
+#define __GPC_RENDERTOOLS_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__)
+
+
+#include "RAS_IRenderTools.h"
+
+#include "BMF_Api.h"
+
+
+class GPC_RenderTools : public RAS_IRenderTools
+{
+public:
+ GPC_RenderTools();
+ virtual ~GPC_RenderTools();
+
+ virtual void EndFrame(RAS_IRasterizer* rasty);
+ virtual void BeginFrame(RAS_IRasterizer* rasty);
+
+ void DisableOpenGLLights()
+ {
+ glDisable(GL_LIGHTING);
+ glDisable(GL_COLOR_MATERIAL);
+ glDisableClientState(GL_NORMAL_ARRAY);
+ }
+
+ void EnableOpenGLLights()
+ {
+ glEnable(GL_LIGHTING);
+ glColorMaterial(GL_FRONT_AND_BACK,GL_DIFFUSE);
+ glEnable(GL_COLOR_MATERIAL);
+ glEnableClientState(GL_NORMAL_ARRAY);
+ }
+
+ int ProcessLighting(int layer);
+
+ void Perspective(int a, int width, int height, float mat[4][4], float viewmat[4][4])
+ {
+ if(a== 0)
+ {
+ glMatrixMode(GL_PROJECTION);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ }
+ else
+ {
+ if(a== 1)
+ {
+ glMatrixMode(GL_PROJECTION);
+ glMatrixMode(GL_MODELVIEW);
+ }
+ }
+ }
+
+ /**
+ * @attention mode is ignored here
+ */
+ virtual void RenderText2D(
+ RAS_TEXT_RENDER_MODE mode,
+ const char* text,
+ int xco,
+ int yco,
+ int width,
+ int height);
+
+ /**
+ * Renders text into a (series of) polygon(s), using a texture font,
+ * Each character consists of one polygon (one quad or two triangles)
+ */
+ virtual void RenderText(
+ int mode,
+ RAS_IPolyMaterial* polymat,
+ float v1[3],
+ float v2[3],
+ float v3[3],
+ float v4[3]);
+
+ void Render(RAS_IRasterizer* rasty,double* oglmatrix,int objectdrawmode)
+ {
+ glPopMatrix();
+ glPushMatrix();
+ glMultMatrixd(oglmatrix);
+ }
+
+ void applyTransform(RAS_IRasterizer* rasty, double* oglmatrix, int objectdrawmode);
+
+ virtual void PushMatrix()
+ {
+ glPushMatrix();
+ }
+
+ virtual void PopMatrix()
+ {
+ glPopMatrix();
+ }
+
+ virtual class RAS_IPolyMaterial* CreateBlenderPolyMaterial(
+ const STR_String &texname,
+ bool ba,
+ const STR_String& matname,
+ int tile,
+ int tilexrep,int tileyrep,
+ int mode,
+ int transparant,
+ int lightlayer,
+ bool bIsTriangle,
+ void* clientobject,
+ void* tface);
+
+ int applyLights(int objectlayer);
+
+protected:
+ /**
+ * Copied from KX_BlenderGL.cpp in KX_blenderhook
+ */
+ void BL_RenderText(
+ int mode,
+ const char* textstr,
+ int textlen,
+ struct TFace* tface,
+ float v1[3],float v2[3],float v3[3],float v4[3]);
+ void BL_spack(unsigned int ucol)
+ {
+ char *cp = (char *)&ucol;
+ glColor3ub(cp[3], cp[2], cp[1]);
+ }
+
+
+ BMF_Font* m_font;
+};
+
+
+#endif // __GPC_RENDERTOOLS_H
diff --git a/source/gameengine/GamePlayer/common/GPC_System.cpp b/source/gameengine/GamePlayer/common/GPC_System.cpp
new file mode 100644
index 00000000000..7c5c16a0b48
--- /dev/null
+++ b/source/gameengine/GamePlayer/common/GPC_System.cpp
@@ -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 *****
+ */
+
+#include "GPC_System.h"
+
+#include "GPC_KeyboardDevice.h"
+#include "NG_NetworkDeviceInterface.h"
+
+
+GPC_System::GPC_System()
+// : m_ndi(0)
+{
+}
+
+/*
+void GPC_System::NextFrame()
+{
+ // Have the imput devices proceed
+ std::vector<SCA_IInputDevice*>::iterator idev;
+ for (idev = m_inputDevices.begin(); !(idev == m_inputDevices.end()); idev++) {
+ (*idev)->NextFrame();
+ }
+
+ // Have the network device proceed
+ if (m_ndi) {
+ m_ndi->NextFrame();
+ }
+}
+
+void GPC_System::StartMainLoop()
+{
+}
+
+
+void GPC_System::Sleep(int millisec)
+{
+ // do nothing for now ;)
+}
+
+
+void GPC_System::AddKey(unsigned char key, bool down)
+{
+ GPC_KeyboardDevice* keydev = (GPC_KeyboardDevice*) this->GetKeyboardDevice();
+ if (keydev) {
+ //SCA_IInputDevice::KX_EnumInputs inp = keydev->ToNative(key);
+ keydev->ConvertEvent(key, down);
+ }
+}
+
+
+void GPC_System::SetNetworkDevice(NG_NetworkDeviceInterface* ndi)
+{
+ m_ndi = ndi;
+}
+
+
+NG_NetworkDeviceInterface* GPC_System::GetNetworkDevice() const
+{
+ return m_ndi;
+}
+*/ \ No newline at end of file
diff --git a/source/gameengine/GamePlayer/common/GPC_System.h b/source/gameengine/GamePlayer/common/GPC_System.h
new file mode 100644
index 00000000000..00720f13072
--- /dev/null
+++ b/source/gameengine/GamePlayer/common/GPC_System.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 __GPC_SYSTEM_H
+#define __GPC_SYSTEM_H
+
+#if defined(WIN32)
+#pragma warning (disable:4786) // suppress stl-MSVC debug info warning
+#endif /* WIN32 */
+
+#include "KX_ISystem.h"
+
+//class NG_NetworkDeviceInterface;
+
+class GPC_System : public KX_ISystem
+{
+public:
+ GPC_System();
+
+// virtual void NextFrame();
+// virtual void StartMainLoop();
+ virtual double GetTimeInSeconds() = 0;
+// virtual void Sleep(int millisec);
+ //virtual bool IsPressed(SCA_IInputDevice::KX_EnumInputs inputcode);
+// void AddKey(unsigned char key, bool down);
+
+// virtual void SetNetworkDevice(NG_NetworkDeviceInterface* ndi);
+// virtual NG_NetworkDeviceInterface* GetNetworkDevice() const;
+
+//protected:
+// NG_NetworkDeviceInterface* m_ndi;
+};
+
+
+#endif // __GPC_SYSTEM_H
diff --git a/source/gameengine/GamePlayer/common/Makefile b/source/gameengine/GamePlayer/common/Makefile
new file mode 100644
index 00000000000..f55b1198c63
--- /dev/null
+++ b/source/gameengine/GamePlayer/common/Makefile
@@ -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 *****
+#
+#
+
+LIBNAME = common
+DIR = $(OCGDIR)/gameengine/GamePlayer/$(LIBNAME)
+
+include nan_compile.mk
+
+CCFLAGS += $(LEVEL_1_CPP_WARNINGS)
+
+CPPFLAGS += -I$(OPENGL_HEADERS)
+
+CPPFLAGS += -I../../../blender/blenkernel
+CPPFLAGS += -I../../../blender/blenloader
+CPPFLAGS += -I../../../blender/blenlib
+CPPFLAGS += -I../../../blender/imbuf
+CPPFLAGS += -I../../../blender/makesdna
+CPPFLAGS += -I../../../kernel/gen_system
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+
+CPPFLAGS += -I$(NAN_FUZZICS)/include
+CPPFLAGS += -I$(NAN_STRING)/include
+CPPFLAGS += -I$(NAN_MOTO)/include
+CPPFLAGS += -I$(NAN_SUMO)/include
+CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION)
+CPPFLAGS += -I$(NAN_BMFONT)/include
+CPPFLAGS += -I../../../gameengine/Converter
+CPPFLAGS += -I../../../gameengine/Expressions
+CPPFLAGS += -I../../../gameengine/GameLogic
+CPPFLAGS += -I../../../gameengine/Converter
+CPPFLAGS += -I../../../gameengine/Ketsji
+CPPFLAGS += -I../../../gameengine/Ketsji/KXNetwork
+CPPFLAGS += -I../../../gameengine/Network
+CPPFLAGS += -I../../../gameengine/Network/LoopBackNetwork
+CPPFLAGS += -I../../../gameengine/Rasterizer
+CPPFLAGS += -I../../../gameengine/SceneGraph
+CPPFLAGS += -I../../../gameengine/SoundSystem
+CPPFLAGS += -I../../../gameengine/Rasterizer/RAS_OpenGLRasterizer
+
+###############################
+
+SOURCEDIR = source/gameengine/GamePlayer/common
+DIRS =
+ifeq ($(OS),windows)
+# Still
+ DIRS = windows
+else
+ ifneq ($(OS),darwin)
+ DIRS = unix
+ endif
+endif
+
+include nan_subdirs.mk
diff --git a/source/gameengine/GamePlayer/common/bmfont.cpp b/source/gameengine/GamePlayer/common/bmfont.cpp
new file mode 100644
index 00000000000..752f2017c94
--- /dev/null
+++ b/source/gameengine/GamePlayer/common/bmfont.cpp
@@ -0,0 +1,301 @@
+/**
+ * bmfont.c
+ *
+ * 04-10-2000 frank
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ *
+ */
+
+/**
+ * Two external functions:
+ *
+ * void detectBitmapFont(ImBuf *ibuf)
+ * detects if an image buffer contains a bitmap font. It makes the
+ * specific bitmap data which is stored in the bitmap invisible to blender.
+ *
+ * void matrixGlyph(ImBuf * ibuf, unsigned short unicode, *float x 7)
+ * returns all the information about the character (unicode) in the floats
+ *
+ * Room for improvement:
+ * add kerning data in the bitmap
+ * all calculations in matrixGlyph() are static and could be done during
+ * initialization
+ */
+
+#include <stdio.h>
+
+#include "MEM_guardedalloc.h"
+#include "BLI_blenlib.h"
+#include "BKE_global.h"
+#include "IMB_imbuf_types.h"
+
+#include "BKE_bmfont.h"
+#include "BKE_bmfont_types.h"
+
+/*MAART:
+void printfGlyph(bmGlyph * glyph)
+{
+ printf("unicode: %d '%c'\n", glyph->unicode, glyph->unicode);
+ printf(" locx: %4d locy: %4d\n", glyph->locx, glyph->locy);
+ printf(" sizex: %3d sizey: %3d\n", glyph->sizex, glyph->sizey);
+ printf(" ofsx: %3d ofsy: %3d\n", glyph->ofsx, glyph->ofsy);
+ printf(" advan: %3d reser: %3d\n", glyph->advance, glyph->reserved);
+}
+*/
+
+#define MAX2(x,y) ( (x)>(y) ? (x) : (y) )
+#define MAX3(x,y,z) MAX2( MAX2((x),(y)) , (z) )
+
+void calcAlpha(ImBuf * ibuf)
+{
+ int i;
+ char * rect;
+
+ if (ibuf) {
+ rect = (char *) ibuf->rect;
+ for (i = ibuf->x * ibuf->y ; i > 0 ; i--) {
+ rect[3] = MAX3(rect[0], rect[1], rect[2]);
+ rect += 4;
+ }
+ }
+}
+
+void readBitmapFontVersion0(ImBuf * ibuf, unsigned char * rect, int step)
+{
+ int glyphcount, bytes, i, index, linelength, ysize;
+ unsigned char * buffer;
+ bmFont * bmfont;
+
+ linelength = ibuf->x * step;
+
+ glyphcount = (rect[6 * step] << 8) | rect[7 * step];
+ bytes = ((glyphcount - 1) * sizeof(bmGlyph)) + sizeof(bmFont);
+
+ ysize = (bytes + (ibuf->x - 1)) / ibuf->x;
+
+ if (ysize < ibuf->y) {
+ // we're first going to copy all data into a liniar buffer.
+ // step can be 4 or 1 bytes, and the data is not sequential because
+ // the bitmap was flipped vertically.
+
+ buffer = (unsigned char*)MEM_mallocN(bytes, "readBitmapFontVersion0:buffer");
+
+ index = 0;
+ for (i = 0; i < bytes; i++) {
+ buffer[i] = rect[index];
+ index += step;
+ if (index >= linelength) {
+ // we've read one line, no skip to the line *before* that
+ rect -= linelength;
+ index -= linelength;
+ }
+ }
+
+ // we're now going to endian convert the data
+
+ bmfont = (bmFont*)MEM_mallocN(bytes, "readBitmapFontVersion0:bmfont");
+ index = 0;
+
+ // first read the header
+ bmfont->magic[0] = buffer[index++];
+ bmfont->magic[1] = buffer[index++];
+ bmfont->magic[2] = buffer[index++];
+ bmfont->magic[3] = buffer[index++];
+ bmfont->version = (buffer[index] << 8) | buffer[index + 1]; index += 2;
+ bmfont->glyphcount = (buffer[index] << 8) | buffer[index + 1]; index += 2;
+ bmfont->xsize = (buffer[index] << 8) | buffer[index + 1]; index += 2;
+ bmfont->ysize = (buffer[index] << 8) | buffer[index + 1]; index += 2;
+
+ for (i = 0; i < bmfont->glyphcount; i++) {
+ bmfont->glyphs[i].unicode = (buffer[index] << 8) | buffer[index + 1]; index += 2;
+ bmfont->glyphs[i].locx = (buffer[index] << 8) | buffer[index + 1]; index += 2;
+ bmfont->glyphs[i].locy = (buffer[index] << 8) | buffer[index + 1]; index += 2;
+ bmfont->glyphs[i].ofsx = buffer[index++];
+ bmfont->glyphs[i].ofsy = buffer[index++];
+ bmfont->glyphs[i].sizex = buffer[index++];
+ bmfont->glyphs[i].sizey = buffer[index++];
+ bmfont->glyphs[i].advance = buffer[index++];
+ bmfont->glyphs[i].reserved = buffer[index++];
+ /* MAART:
+ if (G.f & G_DEBUG) {
+ printfGlyph(&bmfont->glyphs[i]);
+ }
+ */
+ }
+
+ MEM_freeN(buffer);
+
+ /* MAART:
+ if (G.f & G_DEBUG) {
+ printf("Oldy = %d Newy = %d\n", ibuf->y, ibuf->y - ysize);
+ printf("glyphcount = %d\n", glyphcount);
+ printf("bytes = %d\n", bytes);
+ }
+ */
+
+ // we've read the data from the image. Now we're going
+ // to crop the image vertically so only the bitmap data
+ // remains visible
+
+ ibuf->y -= ysize;
+ ibuf->userdata = bmfont;
+ ibuf->userflags |= IB_BITMAPFONT;
+
+ if (ibuf->depth < 32) {
+ // we're going to fake alpha here:
+ calcAlpha(ibuf);
+ }
+ } else {
+ /* MAART:
+ printf("readBitmapFontVersion0: corrupted bitmapfont\n");
+ */
+ }
+}
+
+void detectBitmapFont(ImBuf *ibuf)
+{
+ unsigned char * rect;
+ unsigned short version;
+ long i;
+
+ if (ibuf != NULL) {
+ // bitmap must have an x size that is a power of two
+ if (is_power_of_two(ibuf->x)) {
+ rect = (unsigned char *) (ibuf->rect + (ibuf->x * (ibuf->y - 1)));
+ // printf ("starts with: %s %c %c %c %c\n", rect, rect[0], rect[1], rect[2], rect[3]);
+ if (rect[0] == 'B' && rect[1] == 'F' && rect[2] == 'N' && rect[3] == 'T') {
+ // printf("found 8bit font !\n");
+ // round y size down
+ // do the 8 bit font stuff. (not yet)
+ } else {
+ // we try all 4 possible combinations
+ for (i = 0; i < 4; i++) {
+ if (rect[0] == 'B' && rect[4] == 'F' && rect[8] == 'N' && rect[12] == 'T') {
+ // printf("found 24bit font !\n");
+ // We're going to parse the file:
+
+ version = (rect[16] << 8) | rect[20];
+
+ if (version == 0) {
+ readBitmapFontVersion0(ibuf, rect, 4);
+ } else {
+ //printf("detectBitmapFont :Unsupported version %d\n", version);
+ }
+
+ // on succes ibuf->userdata points to the bitmapfont
+ if (ibuf->userdata) {
+ break;
+ }
+ }
+ rect++;
+ }
+ }
+ }
+ }
+}
+
+int locateGlyph(bmFont *bmfont, unsigned short unicode)
+{
+ int min, max, current = 0;
+
+ if (bmfont) {
+ min = 0;
+ max = bmfont->glyphcount;
+ while (1) {
+ // look halfway for glyph
+ current = (min + max) >> 1;
+
+ if (bmfont->glyphs[current].unicode == unicode) {
+ break;
+ } else if (bmfont->glyphs[current].unicode < unicode) {
+ // have to move up
+ min = current;
+ } else {
+ // have to move down
+ max = current;
+ }
+
+ if (max - min <= 1) {
+ // unable to locate glyph
+ current = 0;
+ break;
+ }
+ }
+ }
+
+ return(current);
+}
+
+void matrixGlyph(ImBuf * ibuf, unsigned short unicode,
+ float *centerx, float *centery,
+ float *sizex, float *sizey,
+ float *transx, float *transy,
+ float *movex, float *movey,
+ float *advance)
+{
+ int index;
+ bmFont *bmfont;
+
+ *centerx = *centery = 0.0;
+ *sizex = *sizey = 1.0;
+ *transx = *transy = 0.0;
+ *movex = *movey = 0.0;
+ *advance = 1.0;
+
+ if (ibuf) {
+ bmfont = (bmFont*)ibuf->userdata;
+ if (bmfont && (ibuf->userflags & IB_BITMAPFONT)) {
+ index = locateGlyph(bmfont, unicode);
+ if (index) {
+
+ *sizex = (bmfont->glyphs[index].sizex) / (float) (bmfont->glyphs[0].sizex);
+ *sizey = (bmfont->glyphs[index].sizey) / (float) (bmfont->glyphs[0].sizey);
+
+ *transx = bmfont->glyphs[index].locx / (float) ibuf->x;
+ *transy = (ibuf->y - bmfont->glyphs[index].locy) / (float) ibuf->y;
+
+ *centerx = bmfont->glyphs[0].locx / (float) ibuf->x;
+ *centery = (ibuf->y - bmfont->glyphs[0].locy) / (float) ibuf->y;
+
+ // 2.0 units is the default size of an object
+
+ *movey = (float)(1.0 - *sizey + 2.0 * (bmfont->glyphs[index].ofsy - bmfont->glyphs[0].ofsy) / (float) bmfont->glyphs[0].sizey);
+ *movex = (float)(*sizex - 1.0 + 2.0 * (bmfont->glyphs[index].ofsx - bmfont->glyphs[0].ofsx) / (float) bmfont->glyphs[0].sizex);
+
+ *advance = (float)(2.0 * bmfont->glyphs[index].advance / (float) bmfont->glyphs[0].advance);
+
+ // printfGlyph(&bmfont->glyphs[index]);
+ // printf("%c %d %0.5f %0.5f %0.5f %0.5f %0.5f \n", unicode, index, *sizex, *sizey, *transx, *transy, *advance);
+ }
+ }
+ }
+}
diff --git a/source/gameengine/GamePlayer/common/load.blend b/source/gameengine/GamePlayer/common/load.blend
new file mode 100644
index 00000000000..1490fba6108
--- /dev/null
+++ b/source/gameengine/GamePlayer/common/load.blend
Binary files differ
diff --git a/source/gameengine/GamePlayer/common/logo_blender.raw b/source/gameengine/GamePlayer/common/logo_blender.raw
new file mode 100644
index 00000000000..82bf25a2c6e
--- /dev/null
+++ b/source/gameengine/GamePlayer/common/logo_blender.raw
Binary files differ
diff --git a/source/gameengine/GamePlayer/common/logo_blender3d.raw b/source/gameengine/GamePlayer/common/logo_blender3d.raw
new file mode 100644
index 00000000000..6a86626bb10
--- /dev/null
+++ b/source/gameengine/GamePlayer/common/logo_blender3d.raw
Binary files differ
diff --git a/source/gameengine/GamePlayer/common/logo_nan.raw b/source/gameengine/GamePlayer/common/logo_nan.raw
new file mode 100644
index 00000000000..b86308bd017
--- /dev/null
+++ b/source/gameengine/GamePlayer/common/logo_nan.raw
Binary files differ
diff --git a/source/gameengine/GamePlayer/common/unix/GPU_Canvas.cpp b/source/gameengine/GamePlayer/common/unix/GPU_Canvas.cpp
new file mode 100644
index 00000000000..29f0bffe1c5
--- /dev/null
+++ b/source/gameengine/GamePlayer/common/unix/GPU_Canvas.cpp
@@ -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 *****
+ */
+
+//#include <iostream>
+
+#include "GPU_Canvas.h"
+
+GPU_Canvas::GPU_Canvas(KXH_plugin_handle p, int width, int height)
+ : GPC_Canvas(width, height), m_plugin(p)
+{
+ /* intentionally empty */
+}
+
+
+GPU_Canvas::~GPU_Canvas(void)
+{
+ /* intentionally empty */
+}
+
+void GPU_Canvas::Init(void)
+{
+ /* intentionally empty */
+}
+
+void GPU_Canvas::SwapBuffers(void)
+{
+ if (m_plugin) KXH_swap_buffers(m_plugin);
+}
+
+bool
+GPU_Canvas::BeginDraw(void)
+{
+ if (m_plugin) {
+ return KXH_begin_draw(m_plugin);
+ } else {
+ return false;
+ }
+}
+
+void GPU_Canvas::EndDraw(void)
+{
+ if (m_plugin) KXH_end_draw(m_plugin);
+}
diff --git a/source/gameengine/GamePlayer/common/unix/GPU_Canvas.h b/source/gameengine/GamePlayer/common/unix/GPU_Canvas.h
new file mode 100644
index 00000000000..5b3309a83bf
--- /dev/null
+++ b/source/gameengine/GamePlayer/common/unix/GPU_Canvas.h
@@ -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 *****
+ */
+
+#ifndef __GPU_CANVAS_H
+#define __GPU_CANVAS_H
+
+#include <iostream>
+
+#include "KXH_ketsji_hooks.h"
+#include "GPC_Canvas.h"
+
+class GPU_Canvas : public GPC_Canvas
+{
+private:
+
+ /** Handle to the drawing resource. */
+ KXH_plugin_handle m_plugin;
+
+public:
+ GPU_Canvas(KXH_plugin_handle display, int width, int height);
+ virtual ~GPU_Canvas();
+
+ virtual void Init(void);
+
+ bool BeginDraw(void);
+ void EndDraw(void);
+ virtual void SwapBuffers(void);
+
+};
+
+#endif // __GPU_CANVAS_H
diff --git a/source/gameengine/GamePlayer/common/unix/GPU_Engine.cpp b/source/gameengine/GamePlayer/common/unix/GPU_Engine.cpp
new file mode 100644
index 00000000000..56b1340eb92
--- /dev/null
+++ b/source/gameengine/GamePlayer/common/unix/GPU_Engine.cpp
@@ -0,0 +1,307 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 <assert.h>
+#include <unistd.h>
+
+#include "GPU_Engine.h"
+
+#include "GPC_MouseDevice.h"
+
+#include "GPU_Canvas.h"
+#include "GPU_KeyboardDevice.h"
+#include "GPU_System.h"
+
+#include "BLI_blenlib.h"
+#include "BLO_readfile.h"
+
+#include "SND_DeviceManager.h"
+
+#include "NG_NetworkScene.h"
+#include "NG_LoopBackNetworkDeviceInterface.h"
+#include "SND_DeviceManager.h"
+#include "KX_BlenderSceneConverter.h"
+#include "SM_Scene.h"
+#include "KX_KetsjiEngine.h"
+
+#include "GPC_RenderTools.h"
+#include "GPC_RawImage.h"
+
+
+void Redraw(GPU_Engine *engine); // -the- redraw function
+
+// callback functions
+/*
+void RedrawCallback(Widget, XtPointer closure, XEvent *, Boolean *continue_to_dispatch);
+
+void KeyDownCallback(Widget w, XtPointer closure, XEvent *event, Boolean *continue_to_dispatch);
+void KeyUpCallback(Widget w, XtPointer closure, XEvent *event, Boolean *continue_to_dispatch);
+
+void ButtonPressReleaseCallback(Widget w, XtPointer closure, XEvent *event, Boolean *continue_to_dispatch);
+void PointerMotionCallback(Widget w, XtPointer closure, XEvent *event, Boolean *continue_to_dispatch);
+
+void TimeOutCallback(XtPointer closure, XtIntervalId *id);
+*/
+
+GPU_Engine::GPU_Engine(char *customLoadingAnimationURL,
+ int foregroundColor, int backgroundColor, int frameRate) :
+ GPC_Engine(customLoadingAnimationURL, foregroundColor, backgroundColor,
+ frameRate), m_timerTimeOutMsecs(10)
+{
+}
+
+
+GPU_Engine::~GPU_Engine()
+{
+}
+
+/*
+bool GPU_Engine::Initialize(Display *display, Window window, int width, int height)
+{
+ SND_DeviceManager::Subscribe();
+ m_audiodevice = SND_DeviceManager::Instance();
+
+ m_keyboarddev = new GPU_KeyboardDevice();
+ m_mousedev = new GPC_MouseDevice();
+
+ // constructor only initializes data
+ // m_canvas = new GPU_Canvas(display, window, width, height);
+ //m_canvas->Init(); // create the actual visual and rendering context
+ //cout << "GPU_Canvas created and initialized, m_canvas " << m_canvas << endl;
+ //AddEventHandlers(); // done here (in GPU_Engine) since the event handlers need access to 'this', ie the engine
+
+ // put the Blender logo in the topleft corner
+ if(m_BlenderLogo != 0)
+ // adding a banner automatically enables them
+ m_BlenderLogoId = m_canvas->AddBanner(m_BlenderLogo->Width(), m_BlenderLogo->Height(),
+ m_BlenderLogo->Width(), m_BlenderLogo->Height(),
+ m_BlenderLogo->Data(), GPC_Canvas::alignTopLeft);
+
+ // put the Blender3D logo in the bottom right corner
+ if(m_Blender3DLogo != 0)
+ // adding a banner automatically enables them
+ m_Blender3DLogoId = m_canvas->AddBanner(m_Blender3DLogo->Width(), m_Blender3DLogo->Height(),
+ m_Blender3DLogo->Width(), m_Blender3DLogo->Height(),
+ m_Blender3DLogo->Data(), GPC_Canvas::alignTopLeft);
+
+#if 0
+ // put the NaN logo in the bottom right corner
+ if(m_NaNLogo != 0)
+ // adding a banner automatically enables them
+ m_NaNLogoId = m_canvas->AddBanner(m_NaNLogo->Width(), m_NaNLogo->Height(),
+ m_NaNLogo->Width(), m_NaNLogo->Height(),
+ m_NaNLogo->Data(), GPC_Canvas::alignBottomRight);
+#endif
+ // enable the display of all banners
+ m_canvas->SetBannerDisplayEnabled(true);
+
+ m_rendertools = new GPC_RenderTools();
+
+ m_networkdev = new NG_LoopBackNetworkDeviceInterface();
+ assert(m_networkdev);
+
+ // creation of system needs 'current rendering context', this is taken care
+ // of by the GPU_Canvas::Init()
+ m_system = new GPU_System();
+
+ m_system->SetKeyboardDevice((GPU_KeyboardDevice *)m_keyboarddev);
+ m_system->SetMouseDevice(m_mousedev);
+ m_system->SetNetworkDevice(m_networkdev);
+
+ m_initialized = true;
+
+ return m_initialized;
+}
+*/
+
+/*
+void GPU_Engine::HandleNewWindow(Window window)
+{
+ // everything only if it's really a new window
+ if(window != ((GPU_Canvas *)m_canvas)->GetWindow())
+ {
+ cout << "GPU_Engine::HandleNewWindow(), new window so calling SetNewWindowMakeNewWidgetAndMakeCurrent()" << endl;
+ // We don't have to remove the event handlers ourselves, they are destroyed by X11
+
+ // make canvas aware of new window, and make it current
+ ((GPU_Canvas *)m_canvas)->SetNewWindowMakeNewWidgetAndMakeCurrent(window);
+
+ // and add event handlers to new widget
+ AddEventHandlers();
+ cout << "GPU_Engine::HandleNewWindow(), event handlers added" << endl;
+ }
+}
+*/
+/*
+void GPU_Engine::AddEventHandlers(void)
+{
+ Widget widget = ((GPU_Canvas *)m_canvas)->GetWidget();
+
+ // redraw
+ // MUST be the *Raw* event handler, the normal one doesn't work!
+ XtAddRawEventHandler(widget, ExposureMask, FALSE, RedrawCallback, this);
+#if 0
+ // key down
+ XtAddRawEventHandler(widget, KeyPressMask, FALSE, KeyDownCallback, this);
+ // key up
+ XtAddRawEventHandler(widget, KeyReleaseMask, FALSE, KeyUpCallback, this);
+
+ // mouse button press
+ XtAddRawEventHandler(widget, ButtonPressMask, FALSE, ButtonPressReleaseCallback, this);
+ // mouse button release
+ XtAddRawEventHandler(widget, ButtonReleaseMask, FALSE, ButtonPressReleaseCallback, this);
+ // mouse motion
+ XtAddRawEventHandler(widget, PointerMotionMask, FALSE, PointerMotionCallback, this);
+#endif
+#if 0
+ // time out, not a real timer. New time out will be set in callback
+ m_timerId = XtAppAddTimeOut(XtWidgetToApplicationContext(widget),
+ m_timerTimeOutMsecs, TimeOutCallback, this);
+#endif
+}
+*/
+
+void Redraw(GPU_Engine *engine)
+{
+/* if(engine->Running())
+ {
+ if(engine->Loading())
+ {
+ engine->UpdateLoadingAnimation();
+ }
+
+ engine->m_system->DoMainLoopCallback();
+ }*/
+}
+
+
+/*+++++++++++++++++++++++++++++++++++++++++++++++++
+ * Callback functions
+ +++++++++++++++++++++++++++++++++++++++++++++++++*/
+void RedrawCallback(Widget, XtPointer closure, XEvent *, Boolean *continue_to_dispatch)
+{
+ GPU_Engine *engine = (GPU_Engine *)closure;
+
+ Redraw(engine);
+
+ *continue_to_dispatch = True;
+}
+
+
+void KeyDownCallback(Widget, XtPointer closure, XEvent *event, Boolean *continue_to_dispatch)
+{
+/* GPU_Engine *engine = (GPU_Engine *)closure;
+ XKeyEvent *keyEvent = (XKeyEvent *)event;
+
+ if(engine->Running())
+ engine->m_system->AddKey(int(keyEvent->keycode), 1);
+
+ *continue_to_dispatch = True;*/
+}
+
+
+void KeyUpCallback(Widget, XtPointer closure, XEvent *event, Boolean *continue_to_dispatch)
+{
+/* GPU_Engine *engine = (GPU_Engine *)closure;
+ XKeyEvent *keyEvent = (XKeyEvent *)event;
+
+ if(engine->Running())
+ engine->m_system->AddKey(int(keyEvent->keycode), 0);
+
+ *continue_to_dispatch = True;*/
+}
+
+
+void ButtonPressReleaseCallback(Widget, XtPointer closure, XEvent *event, Boolean *continue_to_dispatch)
+{
+ GPU_Engine *engine = (GPU_Engine *)closure;
+ XButtonEvent *buttonEvent = (XButtonEvent *)event;
+ bool isDown;
+ GPC_MouseDevice::TButtonId button;
+
+ if(engine->Running())
+ {
+ // determine type of event, press or release
+ isDown = false;
+ if(buttonEvent->type == ButtonPress)
+ isDown = true;
+ // determine which button exactly generated this event
+ switch(buttonEvent->button)
+ {
+ case 1:
+ button = GPC_MouseDevice::buttonLeft;
+ break;
+ case 2:
+ button = GPC_MouseDevice::buttonMiddle;
+ break;
+ case 3:
+ button = GPC_MouseDevice::buttonRight;
+ break;
+ }
+ engine->m_mousedev->ConvertButtonEvent(button,
+ isDown, buttonEvent->x, buttonEvent->y);
+ }
+
+ *continue_to_dispatch = True;
+}
+
+
+void PointerMotionCallback(Widget w, XtPointer closure, XEvent *event, Boolean *continue_to_dispatch)
+{
+ GPU_Engine *engine = (GPU_Engine *)closure;
+ XButtonEvent *buttonEvent = (XButtonEvent *)event;
+
+ if(engine->Running())
+ {
+ engine->m_mousedev->ConvertMoveEvent(buttonEvent->x, buttonEvent->y);
+ }
+
+ *continue_to_dispatch = True;
+}
+
+/*
+void TimeOutCallback(XtPointer closure, XtIntervalId *id)
+{
+ GPU_Engine *engine = (GPU_Engine *)closure;
+
+ Redraw(engine);
+ // add a new time out since there is no real timer for X (not a simple one like under windows)
+ // TODO Have to get faster timer !
+
+ if(engine->Running())
+ engine->m_timerId = XtAppAddTimeOut(XtWidgetToApplicationContext(
+ ((GPU_Canvas *)engine->m_canvas)->GetWidget()),
+ engine->m_timerTimeOutMsecs, TimeOutCallback,
+ closure);
+}
+
+*/
diff --git a/source/gameengine/GamePlayer/common/unix/GPU_Engine.h b/source/gameengine/GamePlayer/common/unix/GPU_Engine.h
new file mode 100644
index 00000000000..fe8743f7695
--- /dev/null
+++ b/source/gameengine/GamePlayer/common/unix/GPU_Engine.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 *****
+ */
+
+#ifndef __GPU_ENGINE_H
+#define __GPU_ENGINE_H
+
+
+#include <X11/Xlib.h>
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+
+#define Object DNA_Object // tricky stuff !!! but without it it doesn't compile...
+
+#include "GPC_Engine.h"
+
+
+class GPU_Engine : public GPC_Engine
+{
+public:
+ XtIntervalId m_timerId;
+ unsigned long m_timerTimeOutMsecs;
+
+public:
+ GPU_Engine(char *customLoadingAnimation,
+ int foregroundColor, int backgroundColor, int frameRate);
+ virtual ~GPU_Engine();
+ bool Initialize(Display *display, Window window, int width, int height);
+
+ void HandleNewWindow(Window window);
+
+private:
+ void AddEventHandlers();
+};
+
+
+#endif // __GPU_ENGINE_H
diff --git a/source/gameengine/GamePlayer/common/unix/GPU_KeyboardDevice.cpp b/source/gameengine/GamePlayer/common/unix/GPU_KeyboardDevice.cpp
new file mode 100644
index 00000000000..125adcc4b7b
--- /dev/null
+++ b/source/gameengine/GamePlayer/common/unix/GPU_KeyboardDevice.cpp
@@ -0,0 +1,137 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 <iostream.h>
+#include "GPU_KeyboardDevice.h"
+
+void GPU_KeyboardDevice::register_X_key_down_event(KeySym k)
+{
+ ConvertEvent(k, 1);
+}
+
+void GPU_KeyboardDevice::register_X_key_up_event(KeySym k)
+{
+ ConvertEvent(k, 0);
+}
+
+
+#define map_x_key_to_kx_key(x,y) m_reverseKeyTranslateTable[x] = y;
+
+GPU_KeyboardDevice::GPU_KeyboardDevice(void)
+{
+ unsigned int i = 0;
+
+ // Needed?
+ m_reverseKeyTranslateTable.clear();
+
+ for (i = XK_A; i< XK_Z; i++) {
+ m_reverseKeyTranslateTable[i]
+ = (SCA_IInputDevice::KX_EnumInputs)
+ (((unsigned int)SCA_IInputDevice::KX_AKEY) + i - XK_A);
+ }
+
+ // Shifted versions: should not occur: KX doesn't distinguish
+ for (i = XK_a; i< XK_z; i++) {
+ m_reverseKeyTranslateTable[i]
+ = (SCA_IInputDevice::KX_EnumInputs)
+ (((int)SCA_IInputDevice::KX_AKEY) + i - XK_a);
+ }
+
+ for (i = XK_0; i< XK_9; i++) {
+ m_reverseKeyTranslateTable[i]
+ = (SCA_IInputDevice::KX_EnumInputs)
+ (((int)SCA_IInputDevice::KX_ZEROKEY) + i - XK_0);
+ }
+
+ for (i = XK_F1; i< XK_F12; i++) {
+ m_reverseKeyTranslateTable[i]
+ = (SCA_IInputDevice::KX_EnumInputs)
+ (((int)SCA_IInputDevice::KX_F1KEY) + i - XK_F1);
+ }
+
+ // the remainder:
+ map_x_key_to_kx_key(XK_BackSpace, SCA_IInputDevice::KX_BACKSPACEKEY);
+ map_x_key_to_kx_key(XK_Tab, SCA_IInputDevice::KX_TABKEY);
+ map_x_key_to_kx_key(XK_Return, SCA_IInputDevice::KX_RETKEY);
+ map_x_key_to_kx_key(XK_Escape, SCA_IInputDevice::KX_ESCKEY);
+ map_x_key_to_kx_key(XK_space, SCA_IInputDevice::KX_SPACEKEY);
+
+ map_x_key_to_kx_key(XK_Shift_L, SCA_IInputDevice::KX_LEFTSHIFTKEY);
+ map_x_key_to_kx_key(XK_Shift_R, SCA_IInputDevice::KX_RIGHTSHIFTKEY);
+ map_x_key_to_kx_key(XK_Control_L, SCA_IInputDevice::KX_LEFTCTRLKEY);
+ map_x_key_to_kx_key(XK_Control_R, SCA_IInputDevice::KX_RIGHTCTRLKEY);
+ map_x_key_to_kx_key(XK_Alt_L, SCA_IInputDevice::KX_LEFTALTKEY);
+ map_x_key_to_kx_key(XK_Alt_R, SCA_IInputDevice::KX_RIGHTALTKEY);
+
+ map_x_key_to_kx_key(XK_Insert, SCA_IInputDevice::KX_INSERTKEY);
+ map_x_key_to_kx_key(XK_Delete, SCA_IInputDevice::KX_DELKEY);
+ map_x_key_to_kx_key(XK_Home, SCA_IInputDevice::KX_HOMEKEY);
+ map_x_key_to_kx_key(XK_End, SCA_IInputDevice::KX_ENDKEY);
+ map_x_key_to_kx_key(XK_Page_Up, SCA_IInputDevice::KX_PAGEUPKEY);
+ map_x_key_to_kx_key(XK_Page_Down, SCA_IInputDevice::KX_PAGEDOWNKEY);
+
+ map_x_key_to_kx_key(XK_Left, SCA_IInputDevice::KX_LEFTARROWKEY);
+ map_x_key_to_kx_key(XK_Right, SCA_IInputDevice::KX_RIGHTARROWKEY);
+ map_x_key_to_kx_key(XK_Up, SCA_IInputDevice::KX_UPARROWKEY);
+ map_x_key_to_kx_key(XK_Down, SCA_IInputDevice::KX_DOWNARROWKEY);
+
+ map_x_key_to_kx_key(XK_KP_0, SCA_IInputDevice::KX_PAD0);
+ map_x_key_to_kx_key(XK_KP_1, SCA_IInputDevice::KX_PAD1);
+ map_x_key_to_kx_key(XK_KP_2, SCA_IInputDevice::KX_PAD2);
+ map_x_key_to_kx_key(XK_KP_3, SCA_IInputDevice::KX_PAD3);
+ map_x_key_to_kx_key(XK_KP_4, SCA_IInputDevice::KX_PAD4);
+ map_x_key_to_kx_key(XK_KP_5, SCA_IInputDevice::KX_PAD5);
+ map_x_key_to_kx_key(XK_KP_6, SCA_IInputDevice::KX_PAD6);
+ map_x_key_to_kx_key(XK_KP_7, SCA_IInputDevice::KX_PAD7);
+ map_x_key_to_kx_key(XK_KP_8, SCA_IInputDevice::KX_PAD8);
+ map_x_key_to_kx_key(XK_KP_9, SCA_IInputDevice::KX_PAD9);
+ map_x_key_to_kx_key(XK_KP_Decimal, SCA_IInputDevice::KX_PADPERIOD);
+
+ map_x_key_to_kx_key(XK_KP_Insert, SCA_IInputDevice::KX_INSERTKEY);
+ map_x_key_to_kx_key(XK_KP_End, SCA_IInputDevice::KX_ENDKEY);
+ map_x_key_to_kx_key(XK_KP_Down, SCA_IInputDevice::KX_DOWNARROWKEY);
+ map_x_key_to_kx_key(XK_KP_Page_Down,SCA_IInputDevice::KX_PAGEDOWNKEY);
+ map_x_key_to_kx_key(XK_KP_Left, SCA_IInputDevice::KX_LEFTARROWKEY);
+ map_x_key_to_kx_key(XK_KP_Right, SCA_IInputDevice::KX_RIGHTARROWKEY);
+ map_x_key_to_kx_key(XK_KP_Home, SCA_IInputDevice::KX_HOMEKEY);
+ map_x_key_to_kx_key(XK_KP_Up, SCA_IInputDevice::KX_UPARROWKEY);
+ map_x_key_to_kx_key(XK_KP_Page_Up, SCA_IInputDevice::KX_PAGEUPKEY);
+ map_x_key_to_kx_key(XK_KP_Delete, SCA_IInputDevice::KX_DELKEY);
+
+ map_x_key_to_kx_key(XK_KP_Enter, SCA_IInputDevice::KX_PADENTER);
+ map_x_key_to_kx_key(XK_KP_Add, SCA_IInputDevice::KX_PADPLUSKEY);
+ map_x_key_to_kx_key(XK_KP_Subtract, SCA_IInputDevice::KX_PADMINUS);
+ map_x_key_to_kx_key(XK_KP_Multiply, SCA_IInputDevice::KX_PADASTERKEY);
+ map_x_key_to_kx_key(XK_KP_Divide, SCA_IInputDevice::KX_PADSLASHKEY);
+
+ map_x_key_to_kx_key(XK_Caps_Lock, SCA_IInputDevice::KX_CAPSLOCKKEY);
+
+}
diff --git a/source/gameengine/GamePlayer/common/unix/GPU_KeyboardDevice.h b/source/gameengine/GamePlayer/common/unix/GPU_KeyboardDevice.h
new file mode 100644
index 00000000000..24226bf6bfd
--- /dev/null
+++ b/source/gameengine/GamePlayer/common/unix/GPU_KeyboardDevice.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 __GPU_KEYBOARDDEVICE_H
+#define __GPU_KEYBOARDDEVICE_H
+
+#include <X11/keysym.h>
+#include <X11/X.h> // Brilliant name, eh? Stupid !@#!$!@#@@% This is
+ // actually needed so as not to get name clashes between Object from
+ // blender and Object from X11... The proper include would be
+ // Intrinsic.h . Yes, we are a bunch of sado-masochists. Let's hurt
+ // ourselves!
+
+#include "GPC_KeyboardDevice.h"
+
+class GPU_KeyboardDevice : public GPC_KeyboardDevice
+{
+public:
+
+ void register_X_key_down_event(KeySym k);
+ void register_X_key_up_event(KeySym k);
+
+ GPU_KeyboardDevice(void);
+ virtual ~GPU_KeyboardDevice()
+ {
+ /* intentionally empty */
+ }
+
+ private:
+ SCA_IInputDevice::KX_EnumInputs
+ convert_x_keycode_to_kx_keycode(unsigned int key);
+};
+
+
+#endif // _GPU_KEYBOARDDEVICE_H
diff --git a/source/gameengine/GamePlayer/common/unix/GPU_PolygonMaterial.h b/source/gameengine/GamePlayer/common/unix/GPU_PolygonMaterial.h
new file mode 100644
index 00000000000..a0629c14158
--- /dev/null
+++ b/source/gameengine/GamePlayer/common/unix/GPU_PolygonMaterial.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 *****
+ */
+
+#ifndef __GPU_POLYGONMATERIAL_H
+#define __GPU_POLYGONMATERIAL_H
+
+
+#include "BP_PolygonMaterial.h"
+
+
+class GPU_PolygonMaterial : public BP_PolygonMaterial
+{
+public:
+ GPUPolygonMaterial(const STR_String& texname, bool ba,const STR_String& matname,
+ int tile, int tileXrep, int tileYrep, int mode, int transparant,
+ int lightlayer,bool bIsTriangle,void* clientobject,void* tpage) :
+ BP_PolygonMaterial(texname, ba,matname, tile, tileXrep, tileYrep,
+ mode, transparant, lightlayer, bIsTriangle, clientobject),
+ m_tface(tpage)
+ {
+ }
+
+ virtual ~GPU_PolygonMaterial()
+ {
+ }
+};
+
+#endif // __GPU_POLYGONMATERIAL_H
diff --git a/source/gameengine/GamePlayer/common/unix/GPU_System.cpp b/source/gameengine/GamePlayer/common/unix/GPU_System.cpp
new file mode 100644
index 00000000000..d7484c97dc2
--- /dev/null
+++ b/source/gameengine/GamePlayer/common/unix/GPU_System.cpp
@@ -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 *****
+ */
+
+#include <sys/time.h>
+
+#include "GPU_System.h"
+
+
+static struct timeval startTime;
+static int startTimeDone = 0;
+
+
+double GPU_System::GetTimeInSeconds()
+{
+ if(!startTimeDone)
+ {
+ gettimeofday(&startTime, NULL);
+ startTimeDone = 1;
+ }
+
+ struct timeval now;
+ gettimeofday(&now, NULL);
+ // next '1000' are used for precision
+ long ticks = (now.tv_sec - startTime.tv_sec) * 1000 + (now.tv_usec - startTime.tv_usec) / 1000;
+ double secs = (double)ticks / 1000.0;
+ return secs;
+}
diff --git a/source/gameengine/GamePlayer/common/unix/GPU_System.h b/source/gameengine/GamePlayer/common/unix/GPU_System.h
new file mode 100644
index 00000000000..7a578fb75ad
--- /dev/null
+++ b/source/gameengine/GamePlayer/common/unix/GPU_System.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 __GPU_SYSTEM_H
+#define __GPU_SYSTEM_H
+
+
+#include "GPC_System.h"
+
+
+class GPU_System : public GPC_System
+{
+public:
+ GPU_System()
+ {
+ }
+
+ virtual double GetTimeInSeconds();
+};
+
+
+#endif // __GPU_SYSTEM_H
diff --git a/source/gameengine/GamePlayer/common/unix/Makefile b/source/gameengine/GamePlayer/common/unix/Makefile
new file mode 100644
index 00000000000..5f6a52ded9a
--- /dev/null
+++ b/source/gameengine/GamePlayer/common/unix/Makefile
@@ -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 *****
+#
+#
+
+LIBNAME = unix
+DIR = $(OCGDIR)/gameengine/GamePlayer/common/$(LIBNAME)
+
+include nan_compile.mk
+
+CCFLAGS += $(LEVEL_1_CPP_WARNINGS)
+
+CPPFLAGS += -I$(OPENGL_HEADERS)
+CPPFLAGS += -I$(NAN_STRING)/include
+
+CPPFLAGS += -I..
+CPPFLAGS += -I../../netscape/src/ketsji
+CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION)
+
+# Game Engine
+CPPFLAGS += -I../../../../gameengine/Converter
+CPPFLAGS += -I../../../../gameengine/Expressions
+CPPFLAGS += -I../../../../gameengine/GameLogic
+CPPFLAGS += -I../../../../gameengine/Ketsji
+CPPFLAGS += -I../../../../gameengine/Ketsji/KXNetwork
+CPPFLAGS += -I../../../../gameengine/Network
+CPPFLAGS += -I../../../../gameengine/Network/LoopBackNetwork
+CPPFLAGS += -I../../../../gameengine/Rasterizer
+CPPFLAGS += -I../../../../gameengine/Rasterizer/RAS_OpenGLRasterizer
+CPPFLAGS += -I../../../../gameengine/SceneGraph
+ifeq ($(NAN_SND), OPENAL)
+ CPPFLAGS += -I../../../../gameengine/SoundSystem
+ CPPFLAGS += -I../../../../gameengine/SoundSystem/SND_OpenAL
+else
+ CPPFLAGS += -I../../../../gameengine/SoundSystem
+ CPPFLAGS += -I../../../../gameengine/SoundSystem/SND_Dummy
+endif
+
+CPPFLAGS += -I../../../../sumo/Fuzzics/include
+CPPFLAGS += -I../../../../sumo/include
+CPPFLAGS += -I$(NAN_MOTO)/include
+CPPFLAGS += -I$(NAN_BMFONT)/include
+
+# Blender stuff
+CPPFLAGS += -I../../../../blender/blenkernel
+CPPFLAGS += -I../../../../blender/blenlib
+CPPFLAGS += -I../../../../blender/blenloader
+CPPFLAGS += -I../../../../blender/imbuf
+CPPFLAGS += -I../../../../blender/makesdna
+CPPFLAGS += -I../../../../kernel/gen_system
+
+CPPFLAGS += -I../../kernel/gen_system
+
diff --git a/source/gameengine/GamePlayer/common/windows/GPW_Canvas.cpp b/source/gameengine/GamePlayer/common/windows/GPW_Canvas.cpp
new file mode 100644
index 00000000000..de3f49e867e
--- /dev/null
+++ b/source/gameengine/GamePlayer/common/windows/GPW_Canvas.cpp
@@ -0,0 +1,174 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "GPW_Canvas.h"
+
+GPW_Canvas::GPW_Canvas(HWND hWnd, HDC hDC, int width, int height)
+ : GPC_Canvas(width, height), m_hWnd(hWnd), m_hRC(0), m_hDC(hDC)
+{
+}
+
+
+GPW_Canvas::~GPW_Canvas()
+{
+ if (m_hRC) {
+ ::wglDeleteContext(m_hRC);
+ }
+ //if (m_hDC) {
+ // ::ReleaseDC(m_hWnd, m_hDC);
+ //}
+}
+
+
+void GPW_Canvas::Init()
+{
+
+// log_entry("GPW_Canvas::Init");
+
+ /*
+ * 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 quality settings.
+ */
+ PIXELFORMATDESCRIPTOR pfd =
+ {
+ sizeof(PIXELFORMATDESCRIPTOR), // iSize
+ 1, // iVersion
+ PFD_DRAW_TO_WINDOW |
+ PFD_SUPPORT_OPENGL |
+// PFD_STEREO |
+ PFD_DOUBLEBUFFER, // dwFlags
+ PFD_TYPE_RGBA, // iPixelType
+ 32, // cColorBits
+ 0, 0, // cRedBits, cRedShift (ignored)
+ 0, 0, // cGreenBits, cGreenShift (ignored)
+ 0, 0, // cBlueBits, cBlueShift (ignored)
+ 0, 0, // cAlphaBits, cAlphaShift (ignored)
+ 0, 0, 0, 0, 0, // cAccum_X_Bits
+ 32, // cDepthBits
+ 0, // cStencilBits
+ 0, // cAuxBuffers
+ PFD_MAIN_PLANE, // iLayerType
+ 0, // bReserved
+ 0, // dwLayerMask
+ 0, // dwVisibleMask
+ 0 // dwDamageMask
+ };
+ PIXELFORMATDESCRIPTOR match;
+
+ // Look what we get back for this pixel format
+ int pixelFormat = ::ChoosePixelFormat(m_hDC, &pfd);
+ if (!pixelFormat) {
+ DWORD error = ::GetLastError();
+ }
+ ::DescribePixelFormat(m_hDC, pixelFormat, sizeof(match), &match);
+
+ // Activate the pixel format for this context
+ ::SetPixelFormat(m_hDC, ::ChoosePixelFormat(m_hDC, &match), &match);
+
+ // Create the OpenGL context and make it current
+ m_hRC = ::wglCreateContext(m_hDC);
+ ::wglMakeCurrent(m_hDC, m_hRC);
+
+}
+
+void GPW_Canvas::SetMousePosition(int x, int y)
+{
+ POINT point = { x, y };
+ if (m_hWnd)
+ {
+ ::ClientToScreen(m_hWnd, &point);
+ ::SetCursorPos(point.x, point.y);
+ }
+}
+
+
+void GPW_Canvas::SetMouseState(RAS_MouseState mousestate)
+{
+ LPCSTR id;
+ switch (mousestate)
+ {
+ case MOUSE_INVISIBLE:
+ HideCursor();
+ break;
+ case MOUSE_WAIT:
+ ::SetCursor(::LoadCursor(0, IDC_WAIT));
+ ShowCursor();
+ break;
+ case MOUSE_NORMAL:
+ ::SetCursor(::LoadCursor(0, IDC_ARROW));
+ ShowCursor();
+ break;
+ }
+}
+
+
+bool GPW_Canvas::BeginDraw(void)
+{
+ ::wglMakeCurrent(m_hDC, m_hRC);
+ // check errors, anyone?
+ return true;
+}
+
+
+void GPW_Canvas::EndDraw(void)
+{
+ ::wglMakeCurrent(NULL, NULL);
+}
+
+void GPW_Canvas::SwapBuffers(void)
+{
+ if (m_hDC) {
+ ::SwapBuffers(m_hDC);
+ }
+}
+
+
+void GPW_Canvas::HideCursor(void)
+{
+ int count = ::ShowCursor(FALSE);
+ while (count >= 0)
+ {
+ count = ::ShowCursor(FALSE);
+ }
+}
+
+
+void GPW_Canvas::ShowCursor(void)
+{
+ ::ShowCursor(TRUE);
+}
+
diff --git a/source/gameengine/GamePlayer/common/windows/GPW_Canvas.h b/source/gameengine/GamePlayer/common/windows/GPW_Canvas.h
new file mode 100644
index 00000000000..59e3eef5b10
--- /dev/null
+++ b/source/gameengine/GamePlayer/common/windows/GPW_Canvas.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 _GPW_CANVAS_H_
+#define _GPW_CANVAS_H_
+
+#ifdef WIN32
+#pragma warning (disable:4786) // suppress stl-MSVC debug info warning
+#endif
+
+#include <iostream>
+#include <windows.h>
+#include <gl/gl.h>
+
+#include "GPC_Canvas.h"
+
+
+class GPW_Canvas : public GPC_Canvas
+{
+protected:
+ /** The window handle. */
+ HWND m_hWnd;
+ /** Rendering context. */
+ HGLRC m_hRC;
+ /** Device Context. */
+ HDC m_hDC;
+
+public:
+ /**
+ * Constructor.
+ */
+ GPW_Canvas(HWND hWnd, HDC hDC, int width, int height);
+
+ /**
+ * Destructor.
+ */
+ virtual ~GPW_Canvas(void);
+
+ virtual void Init(void);
+
+ /**
+ * Moves the cursor to a new location.
+ * @param x The x-coordinate of the new location.
+ * @param x The y-coordinate of the new location.
+ */
+ virtual void SetMousePosition(int x, int y);
+
+ /**
+ * Sets the cursor shape and/or visibility.
+ * @param mousestate The new state ofthe cursor.
+ */
+ virtual void SetMouseState(RAS_MouseState mousestate);
+
+ bool BeginDraw(void);
+ void EndDraw(void);
+
+ virtual void SwapBuffers(void);
+
+ virtual HDC GetHDC(void)
+ {
+ return m_hDC;
+ }
+
+ virtual void SetHDC(HDC hDC)
+ {
+ if (hDC != m_hDC) {
+ m_hDC = hDC;
+ }
+ }
+
+ virtual HGLRC GetHGLRC(void)
+ {
+ return m_hRC;
+ }
+
+protected:
+ /**
+ * Hides the mouse cursor.
+ */
+ void HideCursor(void);
+
+ /**
+ * Shows the mouse cursor.
+ */
+ void ShowCursor(void);
+};
+
+
+
+#endif // _GPW_CANVAS_H_
diff --git a/source/gameengine/GamePlayer/common/windows/GPW_Engine.cpp b/source/gameengine/GamePlayer/common/windows/GPW_Engine.cpp
new file mode 100644
index 00000000000..ff4dca9c50e
--- /dev/null
+++ b/source/gameengine/GamePlayer/common/windows/GPW_Engine.cpp
@@ -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 *****
+ */
+
+#pragma warning (disable : 4786)
+
+#include <assert.h>
+
+#include "GPC_MouseDevice.h"
+#include "GPC_RenderTools.h"
+#include "GPC_RawImage.h"
+
+#include "GPW_Canvas.h"
+#include "GPW_Engine.h"
+#include "GPW_KeyboardDevice.h"
+#include "GPW_System.h"
+
+#include "SND_DeviceManager.h"
+
+#include "NG_NetworkScene.h"
+#include "NG_LoopBackNetworkDeviceInterface.h"
+
+
+GPW_Engine::GPW_Engine(char *customLoadingAnimationURL,
+ int foregroundColor, int backgroundColor, int frameRate) :
+ GPC_Engine(customLoadingAnimationURL, foregroundColor, backgroundColor,
+ frameRate)
+{
+}
+
+
+GPW_Engine::~GPW_Engine()
+{
+}
+
+
+bool GPW_Engine::Initialize(HDC hdc, int width, int height)
+{
+ SND_DeviceManager::Subscribe();
+ m_audiodevice = SND_DeviceManager::Instance();
+
+ m_keyboarddev = new GPW_KeyboardDevice();
+ m_mousedev = new GPC_MouseDevice();
+
+ // constructor only initializes data
+ m_canvas = new GPW_Canvas(0, hdc, width, height);
+ m_canvas->Init(); // create the actual visual and rendering context
+
+ // put the Blender logo in the topleft corner
+ if(m_BlenderLogo != 0)
+ // adding a banner automatically enables them
+ m_BlenderLogoId = m_canvas->AddBanner(m_BlenderLogo->Width(), m_BlenderLogo->Height(),
+ m_BlenderLogo->Width(), m_BlenderLogo->Height(),
+ m_BlenderLogo->Data(), GPC_Canvas::alignTopLeft);
+
+ // put the Blender3D logo in the bottom right corner
+ if(m_Blender3DLogo != 0)
+ // adding a banner automatically enables them
+ m_Blender3DLogoId = m_canvas->AddBanner(m_Blender3DLogo->Width(), m_Blender3DLogo->Height(),
+ m_Blender3DLogo->Width(), m_Blender3DLogo->Height(),
+ m_Blender3DLogo->Data(), GPC_Canvas::alignBottomRight);
+#if 0
+ // put the NaN logo in the bottom right corner
+ if(m_NaNLogo != 0)
+ // adding a banner automatically enables them
+ m_NaNLogoId = m_canvas->AddBanner(m_NaNLogo->Width(), m_NaNLogo->Height(),
+ m_NaNLogo->Width(), m_NaNLogo->Height(),
+ m_NaNLogo->Data(), GPC_Canvas::alignBottomRight);
+#endif
+ // enable the display of all banners
+ m_canvas->SetBannerDisplayEnabled(true);
+
+ // stuff that must be done after creation of a rendering context
+ //m_canvas->InitPostRenderingContext();
+
+ m_rendertools = new GPC_RenderTools();
+
+ m_networkdev = new NG_LoopBackNetworkDeviceInterface();
+ assert(m_networkdev);
+
+ // creation of system needs 'current rendering context', this is taken care
+ // of by the GPW_Canvas
+ m_system = new GPW_System();
+
+// m_system->SetKeyboardDevice((GPW_KeyboardDevice *)m_keyboarddev);
+// m_system->SetMouseDevice(m_mousedev);
+// m_system->SetNetworkDevice(m_networkdev);
+
+ m_initialized = true;
+
+ return m_initialized;
+}
diff --git a/source/gameengine/GamePlayer/common/windows/GPW_Engine.h b/source/gameengine/GamePlayer/common/windows/GPW_Engine.h
new file mode 100644
index 00000000000..7fcd6413e1e
--- /dev/null
+++ b/source/gameengine/GamePlayer/common/windows/GPW_Engine.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 *****
+ */
+
+#ifndef __GPW_ENGINE_H
+#define __GPW_ENGINE_H
+
+
+#include "GPC_Engine.h"
+
+
+class GPW_Engine : public GPC_Engine
+{
+public:
+ GPW_Engine(char *customLoadingAnimation,
+ int foregroundColor, int backgroundColor, int frameRate);
+ virtual ~GPW_Engine();
+ bool Initialize(HDC hdc, int width, int height);
+};
+
+
+#endif // __GPW_ENGINE_H
diff --git a/source/gameengine/GamePlayer/common/windows/GPW_KeyboardDevice.cpp b/source/gameengine/GamePlayer/common/windows/GPW_KeyboardDevice.cpp
new file mode 100644
index 00000000000..b9c884af525
--- /dev/null
+++ b/source/gameengine/GamePlayer/common/windows/GPW_KeyboardDevice.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 *****
+ */
+
+#include "GPW_KeyboardDevice.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
+
+
+
+GPW_KeyboardDevice::GPW_KeyboardDevice(void)
+{
+ m_seperateLeftRight = false;
+ m_seperateLeftRightInitialized = false;
+
+ m_reverseKeyTranslateTable['A' ] = KX_AKEY ;
+ m_reverseKeyTranslateTable['B' ] = KX_BKEY ;
+ m_reverseKeyTranslateTable['C' ] = KX_CKEY ;
+ m_reverseKeyTranslateTable['D' ] = KX_DKEY ;
+ m_reverseKeyTranslateTable['E' ] = KX_EKEY ;
+ m_reverseKeyTranslateTable['F' ] = KX_FKEY ;
+ m_reverseKeyTranslateTable['G' ] = KX_GKEY ;
+ m_reverseKeyTranslateTable['H' ] = KX_HKEY ;
+ m_reverseKeyTranslateTable['I' ] = KX_IKEY ;
+ m_reverseKeyTranslateTable['J' ] = KX_JKEY ;
+ m_reverseKeyTranslateTable['K' ] = KX_KKEY ;
+ m_reverseKeyTranslateTable['L' ] = KX_LKEY ;
+ m_reverseKeyTranslateTable['M' ] = KX_MKEY ;
+ m_reverseKeyTranslateTable['N' ] = KX_NKEY ;
+ m_reverseKeyTranslateTable['O' ] = KX_OKEY ;
+ m_reverseKeyTranslateTable['P' ] = KX_PKEY ;
+ m_reverseKeyTranslateTable['Q' ] = KX_QKEY ;
+ m_reverseKeyTranslateTable['R' ] = KX_RKEY ;
+ m_reverseKeyTranslateTable['S' ] = KX_SKEY ;
+ m_reverseKeyTranslateTable['T' ] = KX_TKEY ;
+ m_reverseKeyTranslateTable['U' ] = KX_UKEY ;
+ m_reverseKeyTranslateTable['V' ] = KX_VKEY ;
+ m_reverseKeyTranslateTable['W' ] = KX_WKEY ;
+ m_reverseKeyTranslateTable['X' ] = KX_XKEY ;
+ m_reverseKeyTranslateTable['Y' ] = KX_YKEY ;
+ m_reverseKeyTranslateTable['Z' ] = KX_ZKEY ;
+
+ m_reverseKeyTranslateTable['0' ] = KX_ZEROKEY ;
+ m_reverseKeyTranslateTable['1' ] = KX_ONEKEY ;
+ m_reverseKeyTranslateTable['2' ] = KX_TWOKEY ;
+ m_reverseKeyTranslateTable['3' ] = KX_THREEKEY ;
+ m_reverseKeyTranslateTable['4' ] = KX_FOURKEY ;
+ m_reverseKeyTranslateTable['5' ] = KX_FIVEKEY ;
+ m_reverseKeyTranslateTable['6' ] = KX_SIXKEY ;
+ m_reverseKeyTranslateTable['7' ] = KX_SEVENKEY ;
+ m_reverseKeyTranslateTable['8' ] = KX_EIGHTKEY ;
+ m_reverseKeyTranslateTable['9' ] = KX_NINEKEY ;
+
+ // Middle keyboard area keys
+ m_reverseKeyTranslateTable[VK_PAUSE ] = KX_PAUSEKEY ;
+ m_reverseKeyTranslateTable[VK_INSERT ] = KX_INSERTKEY ;
+ m_reverseKeyTranslateTable[VK_DELETE ] = KX_DELKEY ;
+ m_reverseKeyTranslateTable[VK_HOME ] = KX_HOMEKEY ;
+ m_reverseKeyTranslateTable[VK_END ] = KX_ENDKEY ;
+ m_reverseKeyTranslateTable[VK_PRIOR ] = KX_PAGEUPKEY ;
+ m_reverseKeyTranslateTable[VK_NEXT ] = KX_PAGEDOWNKEY ;
+
+ // Arrow keys
+ m_reverseKeyTranslateTable[VK_UP ] = KX_UPARROWKEY ;
+ m_reverseKeyTranslateTable[VK_DOWN ] = KX_DOWNARROWKEY ;
+ m_reverseKeyTranslateTable[VK_LEFT ] = KX_LEFTARROWKEY ;
+ m_reverseKeyTranslateTable[VK_RIGHT ] = KX_RIGHTARROWKEY ;
+
+ // Function keys
+ m_reverseKeyTranslateTable[VK_F1 ] = KX_F1KEY ;
+ m_reverseKeyTranslateTable[VK_F2 ] = KX_F2KEY ;
+ m_reverseKeyTranslateTable[VK_F3 ] = KX_F3KEY ;
+ m_reverseKeyTranslateTable[VK_F4 ] = KX_F4KEY ;
+ m_reverseKeyTranslateTable[VK_F5 ] = KX_F5KEY ;
+ m_reverseKeyTranslateTable[VK_F6 ] = KX_F6KEY ;
+ m_reverseKeyTranslateTable[VK_F7 ] = KX_F7KEY ;
+ m_reverseKeyTranslateTable[VK_F8 ] = KX_F8KEY ;
+ m_reverseKeyTranslateTable[VK_F9 ] = KX_F9KEY ;
+ m_reverseKeyTranslateTable[VK_F10 ] = KX_F10KEY ;
+ m_reverseKeyTranslateTable[VK_F11 ] = KX_F11KEY ;
+ m_reverseKeyTranslateTable[VK_F12 ] = KX_F12KEY ;
+
+ // Numpad keys
+ m_reverseKeyTranslateTable[VK_NUMPAD0 ] = KX_PAD0 ;
+ m_reverseKeyTranslateTable[VK_NUMPAD1 ] = KX_PAD1 ;
+ m_reverseKeyTranslateTable[VK_NUMPAD2 ] = KX_PAD2 ;
+ m_reverseKeyTranslateTable[VK_NUMPAD3 ] = KX_PAD3 ;
+ m_reverseKeyTranslateTable[VK_NUMPAD4 ] = KX_PAD4 ;
+ m_reverseKeyTranslateTable[VK_NUMPAD5 ] = KX_PAD5 ;
+ m_reverseKeyTranslateTable[VK_NUMPAD6 ] = KX_PAD6 ;
+ m_reverseKeyTranslateTable[VK_NUMPAD7 ] = KX_PAD7 ;
+ m_reverseKeyTranslateTable[VK_NUMPAD8 ] = KX_PAD8 ;
+ m_reverseKeyTranslateTable[VK_NUMPAD9 ] = KX_PAD9 ;
+ m_reverseKeyTranslateTable[VK_MULTIPLY ] = KX_PADASTERKEY ;
+ m_reverseKeyTranslateTable[VK_ADD ] = KX_PADPLUSKEY ;
+ m_reverseKeyTranslateTable[VK_DECIMAL ] = KX_PADPERIOD ;
+ m_reverseKeyTranslateTable[VK_SUBTRACT ] = KX_PADMINUS ;
+ m_reverseKeyTranslateTable[VK_DIVIDE ] = KX_PADSLASHKEY ;
+ m_reverseKeyTranslateTable[VK_SEPARATOR ] = KX_PADENTER ;
+
+ // Other keys
+ m_reverseKeyTranslateTable[VK_CAPITAL ] = KX_CAPSLOCKKEY ;
+ m_reverseKeyTranslateTable[VK_ESCAPE ] = KX_ESCKEY ;
+ m_reverseKeyTranslateTable[VK_TAB ] = KX_TABKEY ;
+ //m_reverseKeyTranslateTable[VK_RETURN ] = KX_RETKEY ;
+ m_reverseKeyTranslateTable[VK_SPACE ] = KX_SPACEKEY ;
+ m_reverseKeyTranslateTable[VK_RETURN ] = KX_LINEFEEDKEY ;
+ m_reverseKeyTranslateTable[VK_BACK ] = KX_BACKSPACEKEY ;
+ m_reverseKeyTranslateTable[VK_SEMICOLON ] = KX_SEMICOLONKEY ;
+ m_reverseKeyTranslateTable[VK_PERIOD ] = KX_PERIODKEY ;
+ m_reverseKeyTranslateTable[VK_COMMA ] = KX_COMMAKEY ;
+ m_reverseKeyTranslateTable[VK_QUOTE ] = KX_QUOTEKEY ;
+ m_reverseKeyTranslateTable[VK_BACK_QUOTE ] = KX_ACCENTGRAVEKEY ;
+ m_reverseKeyTranslateTable[VK_MINUS ] = KX_MINUSKEY ;
+ m_reverseKeyTranslateTable[VK_SLASH ] = KX_SLASHKEY ;
+ m_reverseKeyTranslateTable[VK_BACK_SLASH ] = KX_BACKSLASHKEY ;
+ m_reverseKeyTranslateTable[VK_EQUALS ] = KX_EQUALKEY ;
+ m_reverseKeyTranslateTable[VK_OPEN_BRACKET ] = KX_LEFTBRACKETKEY ;
+ m_reverseKeyTranslateTable[VK_CLOSE_BRACKET ] = KX_RIGHTBRACKETKEY ;
+
+ /*
+ * Need to handle Ctrl, Alt and Shift keys differently.
+ * Win32 messages do not discriminate left and right keys.
+ */
+ m_reverseKeyTranslateTable[VK_LCONTROL ] = KX_LEFTCTRLKEY ;
+ m_reverseKeyTranslateTable[VK_RCONTROL ] = KX_RIGHTCTRLKEY ;
+ m_reverseKeyTranslateTable[VK_LMENU ] = KX_LEFTALTKEY ;
+ m_reverseKeyTranslateTable[VK_RMENU ] = KX_RIGHTALTKEY ;
+ m_reverseKeyTranslateTable[VK_RSHIFT ] = KX_RIGHTSHIFTKEY ;
+ m_reverseKeyTranslateTable[VK_LSHIFT ] = KX_LEFTSHIFTKEY ;
+}
+
+
+GPW_KeyboardDevice::~GPW_KeyboardDevice(void)
+{
+}
+
+
+void GPW_KeyboardDevice::ConvertWinEvent(WPARAM wParam, bool isDown)
+{
+ if ((wParam == VK_SHIFT) || (wParam == VK_MENU) || (wParam == VK_CONTROL)) {
+ ConvertModifierKey(wParam, isDown);
+ }
+ else {
+ ConvertEvent(wParam, isDown);
+ }
+}
+
+
+void GPW_KeyboardDevice::ConvertModifierKey(WPARAM wParam, bool isDown)
+{
+ /*
+ 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_seperateLeftRightInitialized && isDown) {
+ CheckForSeperateLeftRight(wParam);
+ }
+ if (m_seperateLeftRight) {
+ bool down = HIBYTE(::GetKeyState(VK_LSHIFT)) != 0;
+ ConvertEvent(VK_LSHIFT, down);
+ down = HIBYTE(::GetKeyState(VK_RSHIFT)) != 0;
+ ConvertEvent(VK_RSHIFT, down);
+ down = HIBYTE(::GetKeyState(VK_LMENU)) != 0;
+ ConvertEvent(VK_LMENU, down);
+ down = HIBYTE(::GetKeyState(VK_RMENU)) != 0;
+ ConvertEvent(VK_RMENU, down);
+ down = HIBYTE(::GetKeyState(VK_LCONTROL)) != 0;
+ ConvertEvent(VK_LCONTROL, down);
+ down = HIBYTE(::GetKeyState(VK_RCONTROL)) != 0;
+ ConvertEvent(VK_RCONTROL, down);
+ }
+ else {
+ bool down = HIBYTE(::GetKeyState(VK_SHIFT)) != 0;
+ ConvertEvent(VK_LSHIFT, down);
+ ConvertEvent(VK_RSHIFT, down);
+ down = HIBYTE(::GetKeyState(VK_MENU)) != 0;
+ ConvertEvent(VK_LMENU, down);
+ ConvertEvent(VK_RMENU, down);
+ down = HIBYTE(::GetKeyState(VK_CONTROL)) != 0;
+ ConvertEvent(VK_LCONTROL, down);
+ ConvertEvent(VK_RCONTROL, down);
+ }
+}
+
+
+void GPW_KeyboardDevice::CheckForSeperateLeftRight(WPARAM wParam)
+{
+ // Check whether this system supports seperate left and right keys
+ switch (wParam) {
+ case VK_SHIFT:
+ m_seperateLeftRight =
+ (HIBYTE(::GetKeyState(VK_LSHIFT)) != 0) ||
+ (HIBYTE(::GetKeyState(VK_RSHIFT)) != 0) ?
+ true : false;
+ break;
+ case VK_CONTROL:
+ m_seperateLeftRight =
+ (HIBYTE(::GetKeyState(VK_LCONTROL)) != 0) ||
+ (HIBYTE(::GetKeyState(VK_RCONTROL)) != 0) ?
+ true : false;
+ break;
+ case VK_MENU:
+ m_seperateLeftRight =
+ (HIBYTE(::GetKeyState(VK_LMENU)) != 0) ||
+ (HIBYTE(::GetKeyState(VK_RMENU)) != 0) ?
+ true : false;
+ break;
+ }
+ m_seperateLeftRightInitialized = true;
+}
diff --git a/source/gameengine/GamePlayer/common/windows/GPW_KeyboardDevice.h b/source/gameengine/GamePlayer/common/windows/GPW_KeyboardDevice.h
new file mode 100644
index 00000000000..663c0ee2563
--- /dev/null
+++ b/source/gameengine/GamePlayer/common/windows/GPW_KeyboardDevice.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 *****
+ */
+
+#ifndef _GPW_KEYBOARDDEVICE_H_
+#define _GPW_KEYBOARDDEVICE_H_
+
+#pragma warning (disable : 4786)
+
+#include <windows.h>
+
+#include "GPC_KeyboardDevice.h"
+
+/**
+ * Win32 implementation of GPC_KeyboardDevice.
+ * The contructor fills the keyboard code translation map.
+ * Base class GPC_KeyboardDevice does the rest.
+ * @see SCA_IInputDevice
+ */
+class GPW_KeyboardDevice : public GPC_KeyboardDevice
+{
+public:
+ GPW_KeyboardDevice(void);
+
+ virtual ~GPW_KeyboardDevice(void);
+
+ void ConvertWinEvent(WPARAM wParam, bool isDown);
+
+protected:
+
+ void ConvertModifierKey(WPARAM wParam, bool isDown);
+
+ void CheckForSeperateLeftRight(WPARAM wParam);
+
+ /** 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;
+};
+
+#endif //_GPW_KEYBOARDDEVICE_H_
diff --git a/source/gameengine/GamePlayer/common/windows/GPW_System.cpp b/source/gameengine/GamePlayer/common/windows/GPW_System.cpp
new file mode 100644
index 00000000000..ba71e036fc4
--- /dev/null
+++ b/source/gameengine/GamePlayer/common/windows/GPW_System.cpp
@@ -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 *****
+ * Timing routine taken and modified from KX_BlenderSystem.cpp
+ */
+
+#include <windows.h>
+
+#include "GPW_System.h"
+
+
+GPW_System::GPW_System(void)
+{
+ m_freq = 0;
+ m_lastCount = 0;
+ m_lastRest = 0;
+ m_lastTime = 0;
+}
+
+
+double GPW_System::GetTimeInSeconds()
+{
+#if 0
+ double secs = ::GetTickCount();
+ secs /= 1000.;
+ return secs;
+#else
+
+ // 03/20/1999 Thomas Hieber: completely redone to get true Millisecond
+ // accuracy instead of very rough ticks. This routine will also provide
+ // correct wrap around at the end of "long"
+
+ // m_freq was set to -1, if the current Hardware does not support
+ // high resolution timers. We will use GetTickCount instead then.
+ if (m_freq < 0) {
+ return ::GetTickCount();
+ }
+
+ // m_freq is 0, the first time this function is being called.
+ if (m_freq == 0) {
+ // Try to determine the frequency of the high resulution timer
+ if (!::QueryPerformanceFrequency((LARGE_INTEGER*)&m_freq)) {
+ // There is no such timer....
+ m_freq = -1;
+ return 0;
+ }
+ }
+
+ // Retrieve current count
+ __int64 count = 0;
+ ::QueryPerformanceCounter((LARGE_INTEGER*)&count);
+
+ // Calculate the time passed since last call, and add the rest of
+ // those tics that didn't make it into the last reported time.
+ __int64 delta = 1000*(count-m_lastCount) + m_lastRest;
+
+ m_lastTime += (long)(delta/m_freq); // Save the new value
+ m_lastRest = delta%m_freq; // Save those ticks not being counted
+ m_lastCount = count; // Save last count
+
+ // Return a high quality measurement of time
+ return m_lastTime/1000.0;
+#endif
+}
+
+
diff --git a/source/gameengine/GamePlayer/common/windows/GPW_System.h b/source/gameengine/GamePlayer/common/windows/GPW_System.h
new file mode 100644
index 00000000000..50b005d8342
--- /dev/null
+++ b/source/gameengine/GamePlayer/common/windows/GPW_System.h
@@ -0,0 +1,62 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * Timing routine taken and modified from KX_BlenderSystem.cpp
+ */
+
+#ifndef _GPW_SYSTEM_H_
+#define _GPW_SYSTEM_H_
+
+#pragma warning (disable:4786) // suppress stl-MSVC debug info warning
+
+#include "GPC_System.h"
+
+#if defined(__CYGWIN32__)
+# define __int64 long long
+#endif
+
+
+class GPW_System : public GPC_System
+{
+public:
+ GPW_System();
+
+ virtual double GetTimeInSeconds();
+protected:
+
+ __int64 m_freq;
+ __int64 m_lastCount;
+ __int64 m_lastRest;
+ long m_lastTime;
+
+};
+
+
+#endif //_GPW_SYSTEM_H_
diff --git a/source/gameengine/GamePlayer/common/windows/Makefile b/source/gameengine/GamePlayer/common/windows/Makefile
new file mode 100644
index 00000000000..bc8d1da6f9a
--- /dev/null
+++ b/source/gameengine/GamePlayer/common/windows/Makefile
@@ -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 *****
+#
+#
+# ATTENTION: this Makefile is only used for win builds!
+
+LIBNAME = windows
+DIR = $(OCGDIR)/gameengine/GamePlayer/common/$(LIBNAME)
+
+include nan_compile.mk
+
+CPPFLAGS += -I..
+CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION)
+
+CPPFLAGS += -I$(SRCHOME)/gameengine/GameLogic
+CPPFLAGS += -I$(SRCHOME)/gameengine/Rasterizer
+CPPFLAGS += -I$(SRCHOME)/gameengine/Ketsji
+CPPFLAGS += -I$(SRCHOME)/gameengine/SoundSystem
+CPPFLAGS += -I$(SRCHOME)/gameengine/Network
+CPPFLAGS += -I$(SRCHOME)/gameengine/Network/LoopBackNetwork
+
+CPPFLAGS += -I$(SRCHOME)/sumo/Fuzzics/include
+CPPFLAGS += -I$(SRCHOME)/sumo/include
+
+CPPFLAGS += -I$(NAN_MOTO)/include
+CPPFLAGS += -I$(NAN_STRING)/include
+CPPFLAGS += -I$(NAN_BMFONT)/include
+
+# Blender stuff
+CPPFLAGS += -I$(SRCHOME)/blender/blenkernel
+CPPFLAGS += -I$(SRCHOME)/blender/blenlib
+CPPFLAGS += -I$(SRCHOME)/blender/blenloader
+CPPFLAGS += -I$(SRCHOME)/blender/imbuf
+CPPFLAGS += -I$(SRCHOME)/blender/makesdna
+CPPFLAGS += -I$(SRCHOME)/kernel/gen_system
+
+CPPFLAGS += -I../../kernel/gen_system
+
diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp
new file mode 100644
index 00000000000..07ed803b205
--- /dev/null
+++ b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp
@@ -0,0 +1,607 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 Blender Player application implementation file.
+ */
+
+#ifdef WIN32
+ #pragma warning (disable:4786) // suppress stl-MSVC debug info warning
+#endif
+
+#include "GPG_Application.h"
+
+#include <iostream>
+#include <assert.h>
+
+/**********************************
+ * Begin Blender include block
+ **********************************/
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+#include "BLI_blenlib.h"
+#include "BLO_readfile.h"
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+/**********************************
+ * End Blender include block
+ **********************************/
+
+
+#include "SYS_System.h"
+#include "KX_KetsjiEngine.h"
+
+// include files needed by "KX_BlenderSceneConverter.h"
+#include "GEN_Map.h"
+#include "SCA_IActuator.h"
+#include "RAS_MeshObject.h"
+#include "RAS_OpenGLRasterizer.h"
+#include "KX_PythonInit.h"
+#include "KX_PyConstraintBinding.h"
+
+#include "KX_BlenderSceneConverter.h"
+#include "NG_LoopBackNetworkDeviceInterface.h"
+#include "SND_DeviceManager.h"
+
+#include "GPC_MouseDevice.h"
+#include "GPC_RenderTools.h"
+#include "GPG_Canvas.h"
+#include "GPG_KeyboardDevice.h"
+#include "GPG_System.h"
+
+#include "STR_String.h"
+
+#include "GHOST_ISystem.h"
+#include "GHOST_IEvent.h"
+#include "GHOST_IEventConsumer.h"
+#include "GHOST_IWindow.h"
+#include "GHOST_Rect.h"
+
+
+static void frameTimerProc(GHOST_ITimerTask* task, GHOST_TUns64 time);
+
+static GHOST_ISystem* fSystem = 0;
+static const int kTimerFreq = 10;
+
+GPG_Application::GPG_Application(GHOST_ISystem* system, struct Main *maggie, STR_String startSceneName)
+ : m_maggie(maggie), m_startSceneName(startSceneName), m_exitRequested(0),
+ m_system(system), m_mainWindow(0), m_frameTimer(0), m_cursor(GHOST_kStandardCursorFirstCursor),
+ m_mouse(0), m_keyboard(0), m_rasterizer(0), m_canvas(0), m_rendertools(0), m_kxsystem(0), m_networkdevice(0), m_audiodevice(0), m_sceneconverter(0),
+ m_engineInitialized(0), m_engineRunning(0), m_ketsjiengine(0)
+{
+ fSystem = system;
+}
+
+
+
+GPG_Application::~GPG_Application(void)
+{
+ exitEngine();
+ fSystem->disposeWindow(m_mainWindow);
+}
+
+
+
+bool GPG_Application::SetGameEngineData(struct Main *maggie, STR_String startSceneName)
+{
+ bool result = false;
+
+ if (maggie != NULL && startSceneName != "")
+ {
+ m_maggie = maggie;
+ m_startSceneName = startSceneName;
+ result = true;
+ }
+
+ return result;
+}
+
+
+
+bool GPG_Application::startWindow(STR_String& title,
+ int windowLeft,
+ int windowTop,
+ int windowWidth,
+ int windowHeight,
+ const bool stereoVisual,
+ const int stereoMode)
+{
+ bool success;
+ // Create the main window
+ //STR_String title ("Blender Player - GHOST");
+ m_mainWindow = fSystem->createWindow(title, windowLeft, windowTop, windowWidth, windowHeight, GHOST_kWindowStateNormal,
+ GHOST_kDrawingContextTypeOpenGL, stereoVisual);
+ if (!m_mainWindow) {
+ printf("error: could not create main window\n");
+ exit(-1);
+ }
+
+ /* Check the size of the client rectangle of the window and resize the window
+ * so that the client rectangle has the size requested.
+ */
+ m_mainWindow->setClientSize(windowWidth, windowHeight);
+
+ success = initEngine(m_mainWindow, stereoMode);
+ if (success) {
+ success = startEngine();
+ }
+ return success;
+}
+
+
+
+bool GPG_Application::startFullScreen(
+ int width,
+ int height,
+ int bpp,int frequency,
+ const bool stereoVisual,
+ const int stereoMode)
+{
+ bool success;
+ // Create the main window
+ GHOST_DisplaySetting setting;
+ setting.xPixels = width;
+ setting.yPixels = height;
+ setting.bpp = bpp;
+ setting.frequency = frequency;
+
+ fSystem->beginFullScreen(setting, &m_mainWindow, stereoVisual);
+
+ success = initEngine(m_mainWindow, stereoMode);
+ if (success) {
+ success = startEngine();
+ }
+ return success;
+}
+
+
+
+bool GPG_Application::StartGameEngine(int stereoMode)
+{
+ bool success = initEngine(m_mainWindow, stereoMode);
+
+ if (success)
+ success = startEngine();
+
+ return success;
+}
+
+
+
+void GPG_Application::StopGameEngine()
+{
+ exitEngine();
+}
+
+
+
+bool GPG_Application::processEvent(GHOST_IEvent* event)
+{
+ bool handled = true;
+
+ switch (event->getType())
+ {
+ case GHOST_kEventUnknown:
+ break;
+
+ case GHOST_kEventButtonDown:
+ handled = handleButton(event, true);
+ break;
+
+ case GHOST_kEventButtonUp:
+ handled = handleButton(event, false);
+ break;
+
+ case GHOST_kEventCursorMove:
+ handled = handleCursorMove(event);
+ break;
+
+ case GHOST_kEventKeyDown:
+ handleKey(event, true);
+ break;
+
+ case GHOST_kEventKeyUp:
+ handleKey(event, false);
+ break;
+
+
+ case GHOST_kEventWindowClose:
+ m_exitRequested = KX_EXIT_REQUEST_OUTSIDE;
+ 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;
+ // Update the state of the game engine
+ if (m_kxsystem && !m_exitRequested)
+ {
+ // Proceed to next frame
+ window->activateDrawingContext();
+
+ // first check if we want to exit
+ m_exitRequested = m_ketsjiengine->GetExitCode();
+
+ // kick the engine
+ m_ketsjiengine->NextFrame();
+
+ // render the frame
+ m_ketsjiengine->Render();
+ }
+ m_exitString = m_ketsjiengine->GetExitString();
+ }
+ break;
+
+ case GHOST_kEventWindowSize:
+ {
+ GHOST_IWindow* window = event->getWindow();
+ if (!m_system->validWindow(window)) break;
+ if (m_canvas) {
+ GHOST_Rect bnds;
+ window->getClientBounds(bnds);
+ m_canvas->Resize(bnds.getWidth(), bnds.getHeight());
+ }
+ }
+ break;
+
+ default:
+ handled = false;
+ break;
+ }
+ return handled;
+}
+
+
+
+int GPG_Application::getExitRequested(void)
+{
+ return m_exitRequested;
+}
+
+
+
+const STR_String& GPG_Application::getExitString(void)
+{
+ return m_exitString;
+}
+
+
+
+bool GPG_Application::initEngine(GHOST_IWindow* window, const int stereoMode)
+{
+ if (!m_engineInitialized)
+ {
+ // get and set the preferences
+ SYS_SystemHandle syshandle = SYS_GetSystem();
+ if (syshandle)
+ {
+ // SYS_WriteCommandLineInt(syshandle, "fixedtime", 0);
+ SYS_WriteCommandLineInt(syshandle, "vertexarrays",1);
+ //bool properties = (SYS_GetCommandLineInt(syshandle, "show_properties", 0) != 0);
+ //bool profile = (SYS_GetCommandLineInt(syshandle, "show_profile", 0) != 0);
+ //bool frameRate = (SYS_GetCommandLineInt(syshandle, "show_framerate", 0) != 0);
+
+ // create the canvas, rasterizer and rendertools
+ m_canvas = new GPG_Canvas(window);
+ if (m_canvas)
+ {
+ m_canvas->Init();
+ m_rendertools = new GPC_RenderTools();
+ if (m_rendertools)
+ {
+ m_rasterizer = new RAS_OpenGLRasterizer(m_canvas);
+ m_rasterizer->SetStereoMode(stereoMode);
+ if (m_rasterizer)
+ {
+ // create the inputdevices
+ m_keyboard = new GPG_KeyboardDevice();
+ if (m_keyboard)
+ {
+ m_mouse = new GPC_MouseDevice();
+ if (m_mouse)
+ {
+ // create a networkdevice
+ m_networkdevice = new NG_LoopBackNetworkDeviceInterface();
+ if (m_networkdevice)
+ {
+ // get an audiodevice
+ SND_DeviceManager::Subscribe();
+ m_audiodevice = SND_DeviceManager::Instance();
+ if (m_audiodevice)
+ {
+ m_audiodevice->UseCD();
+ // create a ketsjisystem (only needed for timing and stuff)
+ m_kxsystem = new GPG_System (m_system);
+ if (m_kxsystem)
+ {
+ // create the ketsjiengine
+ m_ketsjiengine = new KX_KetsjiEngine(m_kxsystem);
+
+ // set the devices
+ m_ketsjiengine->SetKeyboardDevice(m_keyboard);
+ m_ketsjiengine->SetMouseDevice(m_mouse);
+ m_ketsjiengine->SetNetworkDevice(m_networkdevice);
+ m_ketsjiengine->SetCanvas(m_canvas);
+ m_ketsjiengine->SetRenderTools(m_rendertools);
+ m_ketsjiengine->SetRasterizer(m_rasterizer);
+ m_ketsjiengine->SetNetworkDevice(m_networkdevice);
+ m_ketsjiengine->SetAudioDevice(m_audiodevice);
+
+ m_ketsjiengine->SetUseFixedTime(false);
+ //m_ketsjiengine->SetTimingDisplay(frameRate, profile, properties);
+
+ m_engineInitialized = true;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return m_engineInitialized;
+}
+
+
+
+bool GPG_Application::startEngine(void)
+{
+ if (m_engineRunning) {
+ return false;
+ }
+
+ // Temporary hack to disable banner display for NaN approved content.
+ /*
+ m_canvas->SetBannerDisplayEnabled(true);
+ Camera* cam;
+ cam = (Camera*)G.scene->camera->data;
+ if (cam) {
+ if (((cam->flag) & 48)==48) {
+ m_canvas->SetBannerDisplayEnabled(false);
+ }
+ }
+ else {
+ showError(CString("Camera data invalid."));
+ return false;
+ }
+ */
+
+ // create a scene converter, create and convert the stratingscene
+ m_sceneconverter = new KX_BlenderSceneConverter(m_maggie, m_ketsjiengine);
+ if (m_sceneconverter)
+ {
+ STR_String startscenename = m_startSceneName.Ptr();
+ m_ketsjiengine->SetSceneConverter(m_sceneconverter);
+
+ // if (always_use_expand_framing)
+ // sceneconverter->SetAlwaysUseExpandFraming(true);
+
+
+ KX_Scene* startscene = new KX_Scene(m_keyboard,
+ m_mouse,
+ m_networkdevice,
+ m_audiodevice,
+ startscenename);
+
+ // some python things
+ PyObject* m_dictionaryobject = initGamePythonScripting("Ketsji", psl_Lowest);
+ m_ketsjiengine->SetPythonDictionary(m_dictionaryobject);
+ initRasterizer(m_rasterizer, m_canvas);
+ initGameLogic(startscene);
+ initGameKeys();
+ initPythonConstraintBinding();
+
+ m_sceneconverter->ConvertScene(
+ startscenename,
+ startscene,
+ m_dictionaryobject,
+ m_keyboard,
+ m_rendertools,
+ m_canvas);
+ m_ketsjiengine->AddScene(startscene);
+
+ // Create a timer that is used to kick the engine
+ if (!m_frameTimer) {
+ m_frameTimer = m_system->installTimer(0, kTimerFreq, frameTimerProc, m_mainWindow);
+ }
+ m_rasterizer->Init();
+ m_ketsjiengine->StartEngine();
+ m_engineRunning = true;
+
+ }
+
+ if (!m_engineRunning)
+ {
+ stopEngine();
+ }
+
+ return m_engineRunning;
+}
+
+
+void GPG_Application::stopEngine()
+{
+ // when exiting the mainloop
+ exitGamePythonScripting();
+ m_ketsjiengine->StopEngine();
+ m_networkdevice->Disconnect();
+
+ if (m_sceneconverter) {
+ delete m_sceneconverter;
+ m_sceneconverter = 0;
+ }
+ if (m_system && m_frameTimer) {
+ m_system->removeTimer(m_frameTimer);
+ m_frameTimer = 0;
+ }
+ m_engineRunning = false;
+}
+
+
+void GPG_Application::exitEngine()
+{
+ if (m_ketsjiengine)
+ {
+ stopEngine();
+ delete m_ketsjiengine;
+ m_ketsjiengine = 0;
+ }
+ if (m_kxsystem)
+ {
+ delete m_kxsystem;
+ m_kxsystem = 0;
+ }
+ if (m_audiodevice)
+ {
+ SND_DeviceManager::Unsubscribe();
+ m_audiodevice = 0;
+ }
+ if (m_networkdevice)
+ {
+ delete m_networkdevice;
+ m_networkdevice = 0;
+ }
+ if (m_mouse)
+ {
+ delete m_mouse;
+ m_mouse = 0;
+ }
+ if (m_keyboard)
+ {
+ delete m_keyboard;
+ m_keyboard = 0;
+ }
+ if (m_rasterizer)
+ {
+ delete m_rasterizer;
+ m_rasterizer = 0;
+ }
+ if (m_rendertools)
+ {
+ delete m_rendertools;
+ m_rendertools = 0;
+ }
+ if (m_canvas)
+ {
+ delete m_canvas;
+ m_canvas = 0;
+ }
+
+ m_exitRequested = 0;
+ m_engineInitialized = false;
+}
+
+
+bool GPG_Application::handleButton(GHOST_IEvent* event, bool isDown)
+{
+ bool handled = false;
+ assert(event);
+ if (m_mouse)
+ {
+ GHOST_TEventDataPtr eventData = ((GHOST_IEvent*)event)->getData();
+ GHOST_TEventButtonData* buttonData = static_cast<GHOST_TEventButtonData*>(eventData);
+ GPC_MouseDevice::TButtonId button;
+ switch (buttonData->button)
+ {
+ case GHOST_kButtonMaskMiddle:
+ button = GPC_MouseDevice::buttonMiddle;
+ break;
+ case GHOST_kButtonMaskRight:
+ button = GPC_MouseDevice::buttonRight;
+ break;
+ case GHOST_kButtonMaskLeft:
+ default:
+ button = GPC_MouseDevice::buttonLeft;
+ break;
+ }
+ m_mouse->ConvertButtonEvent(button, isDown);
+ handled = true;
+ }
+ return handled;
+}
+
+
+bool GPG_Application::handleCursorMove(GHOST_IEvent* event)
+{
+ bool handled = false;
+ assert(event);
+ if (m_mouse && m_mainWindow)
+ {
+ GHOST_TEventDataPtr eventData = ((GHOST_IEvent*)event)->getData();
+ GHOST_TEventCursorData* cursorData = static_cast<GHOST_TEventCursorData*>(eventData);
+ GHOST_TInt32 x, y;
+ m_mainWindow->screenToClient(cursorData->x, cursorData->y, x, y);
+ m_mouse->ConvertMoveEvent(x, y);
+ handled = true;
+ }
+ return handled;
+}
+
+
+bool GPG_Application::handleKey(GHOST_IEvent* event, bool isDown)
+{
+ bool handled = false;
+ assert(event);
+ if (m_keyboard)
+ {
+ GHOST_TEventDataPtr eventData = ((GHOST_IEvent*)event)->getData();
+ GHOST_TEventKeyData* keyData = static_cast<GHOST_TEventKeyData*>(eventData);
+ if (fSystem->getFullScreen()) {
+ if (keyData->key == GHOST_kKeyEsc) {
+ m_exitRequested = KX_EXIT_REQUEST_OUTSIDE;
+ }
+ }
+ m_keyboard->ConvertEvent(keyData->key, isDown);
+ handled = true;
+ }
+ return handled;
+}
+
+
+
+static void frameTimerProc(GHOST_ITimerTask* task, GHOST_TUns64 time)
+{
+ GHOST_IWindow* window = (GHOST_IWindow*)task->getUserData();
+ if (fSystem->validWindow(window)) {
+ window->invalidate();
+ }
+}
diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.h b/source/gameengine/GamePlayer/ghost/GPG_Application.h
new file mode 100644
index 00000000000..ac502630440
--- /dev/null
+++ b/source/gameengine/GamePlayer/ghost/GPG_Application.h
@@ -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 *****
+ * GHOST Blender Player application declaration file.
+ */
+
+#include "GHOST_IEventConsumer.h"
+
+#include "STR_String.h"
+
+class KX_KetsjiEngine;
+class KX_ISceneConverter;
+class NG_LoopBackNetworkDeviceInterface;
+class SND_IAudioDevice;
+class RAS_IRasterizer;
+class GHOST_IEvent;
+class GHOST_ISystem;
+class GHOST_ITimerTask;
+class GHOST_IWindow;
+class GPC_MouseDevice;
+class GPC_RenderTools;
+class GPG_Canvas;
+class GPG_KeyboardDevice;
+class GPG_System;
+struct Main;
+
+class GPG_Application : public GHOST_IEventConsumer
+{
+public:
+ GPG_Application(GHOST_ISystem* system, struct Main *maggie, STR_String startSceneName);
+ ~GPG_Application(void);
+
+ bool SetGameEngineData(struct Main *maggie, STR_String startSceneName);
+ bool startWindow(STR_String& title, int windowLeft, int windowTop, int windowWidth, int windowHeight,
+ const bool stereoVisual, const int stereoMode);
+ bool startFullScreen(int width, int height, int bpp, int frequency, const bool stereoVisual, const int stereoMode);
+ virtual bool processEvent(GHOST_IEvent* event);
+ int getExitRequested(void);
+ const STR_String& getExitString(void);
+ bool StartGameEngine(int stereoMode);
+ void StopGameEngine();
+
+protected:
+ bool handleButton(GHOST_IEvent* event, bool isDown);
+ bool handleCursorMove(GHOST_IEvent* event);
+ bool handleKey(GHOST_IEvent* event, bool isDown);
+
+ /**
+ * Initializes the game engine.
+ */
+ bool initEngine(GHOST_IWindow* window, int stereoMode);
+
+ /**
+ * Starts the game engine.
+ */
+ bool startEngine(void);
+
+ /**
+ * Stop the game engine.
+ */
+ void stopEngine(void);
+
+ /**
+ * Shuts the game engine down.
+ */
+ void exitEngine(void);
+
+ /* The game data */
+ STR_String m_startSceneName;
+ struct Main* m_maggie;
+
+ /* Exit state. */
+ int m_exitRequested;
+ STR_String m_exitString;
+ /* GHOST system abstraction. */
+ GHOST_ISystem* m_system;
+ /* Main window. */
+ GHOST_IWindow* m_mainWindow;
+ /* Timer to advance frames. */
+ GHOST_ITimerTask* m_frameTimer;
+ /* The cursor shape displayed. */
+ GHOST_TStandardCursor m_cursor;
+
+ /** Engine construction state. */
+ bool m_engineInitialized;
+ /** Engine state. */
+ bool m_engineRunning;
+
+ /** the gameengine itself */
+ KX_KetsjiEngine* m_ketsjiengine;
+ /** The game engine's system abstraction. */
+ GPG_System* m_kxsystem;
+ /** The game engine's keyboard abstraction. */
+ GPG_KeyboardDevice* m_keyboard;
+ /** The game engine's mouse abstraction. */
+ GPC_MouseDevice* m_mouse;
+ /** The game engine's canvas abstraction. */
+ GPG_Canvas* m_canvas;
+ /** The game engine's platform dependent render tools. */
+ GPC_RenderTools* m_rendertools;
+ /** the rasterizer */
+ RAS_IRasterizer* m_rasterizer;
+ /** Converts Blender data files. */
+ KX_ISceneConverter* m_sceneconverter;
+ /** Network interface. */
+ NG_LoopBackNetworkDeviceInterface* m_networkdevice;
+ /** Sound device. */
+ SND_IAudioDevice* m_audiodevice;
+};
+
+
diff --git a/source/gameengine/GamePlayer/ghost/GPG_Canvas.cpp b/source/gameengine/GamePlayer/ghost/GPG_Canvas.cpp
new file mode 100644
index 00000000000..da71d40acc0
--- /dev/null
+++ b/source/gameengine/GamePlayer/ghost/GPG_Canvas.cpp
@@ -0,0 +1,110 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "GPG_Canvas.h"
+
+#include <assert.h>
+
+#include "GHOST_ISystem.h"
+
+
+GPG_Canvas::GPG_Canvas(GHOST_IWindow* window)
+: GPC_Canvas(0, 0), m_window(window)
+{
+ if (m_window)
+ {
+ GHOST_Rect bnds;
+ m_window->getClientBounds(bnds);
+ this->Resize(bnds.getWidth(), bnds.getHeight());
+ }
+}
+
+
+GPG_Canvas::~GPG_Canvas(void)
+{
+}
+
+
+void GPG_Canvas::Init()
+{
+ if (m_window)
+ {
+ GHOST_TSuccess success;
+ success = m_window->setDrawingContextType(GHOST_kDrawingContextTypeOpenGL);
+ assert(success == GHOST_kSuccess);
+ }
+}
+
+void GPG_Canvas::SetMousePosition(int x, int y)
+{
+ GHOST_ISystem* system = GHOST_ISystem::getSystem();
+ if (system && m_window)
+ {
+ GHOST_TInt32 gx = (GHOST_TInt32)x;
+ GHOST_TInt32 gy = (GHOST_TInt32)y;
+ GHOST_TInt32 cx;
+ GHOST_TInt32 cy;
+ m_window->clientToScreen(gx, gy, cx, cy);
+ system->setCursorPosition(cx, cy);
+ }
+}
+
+
+void GPG_Canvas::SetMouseState(RAS_MouseState mousestate)
+{
+ if (m_window)
+ {
+ switch (mousestate)
+ {
+ case MOUSE_INVISIBLE:
+ m_window->setCursorVisibility(false);
+ break;
+ case MOUSE_WAIT:
+ m_window->setCursorShape(GHOST_kStandardCursorWait);
+ m_window->setCursorVisibility(true);
+ break;
+ case MOUSE_NORMAL:
+ m_window->setCursorShape(GHOST_kStandardCursorRightArrow);
+ m_window->setCursorVisibility(true);
+ break;
+ }
+ }
+}
+
+
+void GPG_Canvas::SwapBuffers()
+{
+ if (m_window)
+ {
+ m_window->swapBuffers();
+ }
+}
diff --git a/source/gameengine/GamePlayer/ghost/GPG_Canvas.h b/source/gameengine/GamePlayer/ghost/GPG_Canvas.h
new file mode 100644
index 00000000000..12ac3701be8
--- /dev/null
+++ b/source/gameengine/GamePlayer/ghost/GPG_Canvas.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 _GPG_CANVAS_H_
+#define _GPG_CANVAS_H_
+
+#ifdef WIN32
+#pragma warning (disable : 4786)
+#endif // WIN32
+
+#include "GPC_Canvas.h"
+
+#include "GHOST_IWindow.h"
+
+
+class GPG_Canvas : public GPC_Canvas
+{
+protected:
+ /** GHOST window. */
+ GHOST_IWindow* m_window;
+
+public:
+ GPG_Canvas(GHOST_IWindow* window);
+ virtual ~GPG_Canvas(void);
+
+ virtual void Init(void);
+ virtual void SetMousePosition(int x, int y);
+ virtual void SetMouseState(RAS_MouseState mousestate);
+ virtual void SwapBuffers();
+
+ bool BeginDraw() { return true;};
+ void EndDraw() {};
+};
+
+#endif // _GPG_CANVAS_H_
diff --git a/source/gameengine/GamePlayer/ghost/GPG_KeyboardDevice.cpp b/source/gameengine/GamePlayer/ghost/GPG_KeyboardDevice.cpp
new file mode 100644
index 00000000000..7971a86bcbc
--- /dev/null
+++ b/source/gameengine/GamePlayer/ghost/GPG_KeyboardDevice.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 *****
+ * GHOST Blender Player keyboard device implementation.
+ */
+
+
+#include "GPG_KeyboardDevice.h"
+
+
+GPG_KeyboardDevice::GPG_KeyboardDevice(void)
+{
+ m_reverseKeyTranslateTable[GHOST_kKeyA ] = KX_AKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyB ] = KX_BKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyC ] = KX_CKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyD ] = KX_DKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyE ] = KX_EKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyF ] = KX_FKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyG ] = KX_GKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyH ] = KX_HKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyI ] = KX_IKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyJ ] = KX_JKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyK ] = KX_KKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyL ] = KX_LKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyM ] = KX_MKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyN ] = KX_NKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyO ] = KX_OKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyP ] = KX_PKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyQ ] = KX_QKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyR ] = KX_RKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyS ] = KX_SKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyT ] = KX_TKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyU ] = KX_UKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyV ] = KX_VKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyW ] = KX_WKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyX ] = KX_XKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyY ] = KX_YKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyZ ] = KX_ZKEY ;
+
+ m_reverseKeyTranslateTable[GHOST_kKey0 ] = KX_ZEROKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKey1 ] = KX_ONEKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKey2 ] = KX_TWOKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKey3 ] = KX_THREEKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKey4 ] = KX_FOURKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKey5 ] = KX_FIVEKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKey6 ] = KX_SIXKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKey7 ] = KX_SEVENKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKey8 ] = KX_EIGHTKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKey9 ] = KX_NINEKEY ;
+
+ // Middle keyboard area keys
+ m_reverseKeyTranslateTable[GHOST_kKeyPause ] = KX_PAUSEKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyInsert ] = KX_INSERTKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyDelete ] = KX_DELKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyHome ] = KX_HOMEKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyEnd ] = KX_ENDKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyUpPage ] = KX_PAGEUPKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyDownPage ] = KX_PAGEDOWNKEY ;
+
+ // Arrow keys
+ m_reverseKeyTranslateTable[GHOST_kKeyUpArrow ] = KX_UPARROWKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyDownArrow ] = KX_DOWNARROWKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyLeftArrow ] = KX_LEFTARROWKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyRightArrow ] = KX_RIGHTARROWKEY ;
+
+ // Function keys
+ m_reverseKeyTranslateTable[GHOST_kKeyF1 ] = KX_F1KEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyF2 ] = KX_F2KEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyF3 ] = KX_F3KEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyF4 ] = KX_F4KEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyF5 ] = KX_F5KEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyF6 ] = KX_F6KEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyF7 ] = KX_F7KEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyF8 ] = KX_F8KEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyF9 ] = KX_F9KEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyF10 ] = KX_F10KEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyF11 ] = KX_F11KEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyF12 ] = KX_F12KEY ;
+
+ // Numpad keys
+ m_reverseKeyTranslateTable[GHOST_kKeyNumpad0 ] = KX_PAD0 ;
+ m_reverseKeyTranslateTable[GHOST_kKeyNumpad1 ] = KX_PAD1 ;
+ m_reverseKeyTranslateTable[GHOST_kKeyNumpad2 ] = KX_PAD2 ;
+ m_reverseKeyTranslateTable[GHOST_kKeyNumpad3 ] = KX_PAD3 ;
+ m_reverseKeyTranslateTable[GHOST_kKeyNumpad4 ] = KX_PAD4 ;
+ m_reverseKeyTranslateTable[GHOST_kKeyNumpad5 ] = KX_PAD5 ;
+ m_reverseKeyTranslateTable[GHOST_kKeyNumpad6 ] = KX_PAD6 ;
+ m_reverseKeyTranslateTable[GHOST_kKeyNumpad7 ] = KX_PAD7 ;
+ m_reverseKeyTranslateTable[GHOST_kKeyNumpad8 ] = KX_PAD8 ;
+ m_reverseKeyTranslateTable[GHOST_kKeyNumpad9 ] = KX_PAD9 ;
+ m_reverseKeyTranslateTable[GHOST_kKeyNumpadAsterisk ] = KX_PADASTERKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyNumpadPlus ] = KX_PADPLUSKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyNumpadPeriod ] = KX_PADPERIOD ;
+ m_reverseKeyTranslateTable[GHOST_kKeyNumpadMinus ] = KX_PADMINUS ;
+ m_reverseKeyTranslateTable[GHOST_kKeyNumpadSlash ] = KX_PADSLASHKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyNumpadEnter ] = KX_PADENTER ;
+
+ // Other keys
+ m_reverseKeyTranslateTable[GHOST_kKeyCapsLock ] = KX_CAPSLOCKKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyEsc ] = KX_ESCKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyTab ] = KX_TABKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeySpace ] = KX_SPACEKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyEnter ] = KX_RETKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyBackSpace ] = KX_BACKSPACEKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeySemicolon ] = KX_SEMICOLONKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyPeriod ] = KX_PERIODKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyComma ] = KX_COMMAKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyQuote ] = KX_QUOTEKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyAccentGrave ] = KX_ACCENTGRAVEKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyMinus ] = KX_MINUSKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeySlash ] = KX_SLASHKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyBackslash ] = KX_BACKSLASHKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyEqual ] = KX_EQUALKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyLeftBracket ] = KX_LEFTBRACKETKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyRightBracket ] = KX_RIGHTBRACKETKEY ;
+
+ // Modifier keys.
+ m_reverseKeyTranslateTable[GHOST_kKeyLeftControl ] = KX_LEFTCTRLKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyRightControl ] = KX_RIGHTCTRLKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyLeftAlt ] = KX_LEFTALTKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyRightAlt ] = KX_RIGHTALTKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyLeftShift ] = KX_LEFTSHIFTKEY ;
+ m_reverseKeyTranslateTable[GHOST_kKeyRightShift ] = KX_RIGHTSHIFTKEY ;
+}
+
+
+GPG_KeyboardDevice::~GPG_KeyboardDevice(void)
+{
+}
diff --git a/source/gameengine/GamePlayer/ghost/GPG_KeyboardDevice.h b/source/gameengine/GamePlayer/ghost/GPG_KeyboardDevice.h
new file mode 100644
index 00000000000..0b77664f4e5
--- /dev/null
+++ b/source/gameengine/GamePlayer/ghost/GPG_KeyboardDevice.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 *****
+ * GHOST Blender Player keyboard device.
+ */
+
+#ifndef _GPG_KEYBOARDDEVICE_H_
+#define _GPG_KEYBOARDDEVICE_H_
+
+#ifdef WIN32
+#pragma warning (disable : 4786)
+#endif // WIN32
+
+#include "GHOST_Types.h"
+#include "GPC_KeyboardDevice.h"
+
+/**
+ * GHOST implementation of GPC_KeyboardDevice.
+ * The contructor fills the keyboard code translation map.
+ * Base class GPC_KeyboardDevice does the rest.
+ * @see SCA_IInputDevice
+ */
+class GPG_KeyboardDevice : public GPC_KeyboardDevice
+{
+public:
+ GPG_KeyboardDevice(void);
+ virtual ~GPG_KeyboardDevice(void);
+};
+
+#endif //_GPG_KEYBOARDDEVICE_H_
diff --git a/source/gameengine/GamePlayer/ghost/GPG_System.cpp b/source/gameengine/GamePlayer/ghost/GPG_System.cpp
new file mode 100644
index 00000000000..6084505bbba
--- /dev/null
+++ b/source/gameengine/GamePlayer/ghost/GPG_System.cpp
@@ -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 *****
+ * Blender Player system on GHOST.
+ */
+
+#include "GPG_System.h"
+
+#include <assert.h>
+
+#include "GHOST_ISystem.h"
+
+
+GPG_System::GPG_System(GHOST_ISystem* system)
+: m_system(system)
+{
+ assert(m_system);
+}
+
+
+double GPG_System::GetTimeInSeconds()
+{
+ GHOST_TInt64 millis = (GHOST_TInt64)m_system->getMilliSeconds();
+ double time = (double)millis;
+ time /= 1000.;
+ return time;
+}
+
+
diff --git a/source/gameengine/GamePlayer/ghost/GPG_System.h b/source/gameengine/GamePlayer/ghost/GPG_System.h
new file mode 100644
index 00000000000..f0bb186d370
--- /dev/null
+++ b/source/gameengine/GamePlayer/ghost/GPG_System.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 *****
+ * Blender Player system on GHOST.
+ */
+
+#ifndef _GPG_SYSTEM_H_
+#define _GPG_SYSTEM_H_
+
+#ifdef WIN32
+#pragma warning (disable:4786) // suppress stl-MSVC debug info warning
+#endif // WIN32
+
+#include "GPC_System.h"
+
+class GHOST_ISystem;
+
+class GPG_System : public GPC_System
+{
+ GHOST_ISystem* m_system;
+
+public:
+ GPG_System(GHOST_ISystem* system);
+
+ virtual double GetTimeInSeconds();
+};
+
+
+#endif // _GPG_SYSTEM_H_
diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
new file mode 100644
index 00000000000..df683cb91cf
--- /dev/null
+++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
@@ -0,0 +1,597 @@
+/**
+* $Id$
+*
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+* Start up of the Blender Player on GHOST.
+*/
+
+#include <iostream>
+#include <math.h>
+
+#ifdef __linux__
+#ifdef __alpha__
+#include <signal.h>
+#endif /* __alpha__ */
+#endif /* __linux__ */
+
+#ifdef __APPLE__
+// Can't use Carbon right now because of double defined type ID (In Carbon.h and DNA_ID.h, sigh)
+//#include <Carbon/Carbon.h>
+//#include <CFBundle.h>
+#endif // __APPLE__
+#include "GEN_messaging.h"
+#include "KX_KetsjiEngine.h"
+
+/**********************************
+* Begin Blender include block
+**********************************/
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+#include "BLI_blenlib.h"
+#include "DNA_scene_types.h"
+#include "BLO_readfile.h"
+
+ int GHOST_HACK_getFirstFile(char buf[]);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+/**********************************
+* End Blender include block
+**********************************/
+
+#include "SYS_System.h"
+#include "GPG_Application.h"
+#include "GPC_PolygonMaterial.h"
+
+#include "GHOST_ISystem.h"
+#include "RAS_IRasterizer.h"
+
+#include "BKE_main.h"
+
+#ifdef WIN32
+#ifdef NDEBUG
+#include <windows.h>
+#include <wincon.h>
+#endif // NDEBUG
+#endif // WIN32
+
+const int kMinWindowWidth = 100;
+const int kMinWindowHeight = 100;
+
+void usage(char* program)
+{
+ char * consoleoption;
+#ifdef _WIN32
+ consoleoption = "-c ";
+#else
+ consoleoption = "";
+#endif
+
+ printf("usage: %s [-p l t w h] [-f fw fh fb ff] %s[-g gamengineoptions] "
+ "-s stereomode filename.blend\n", program, consoleoption);
+ printf(" -p: specify window position\n");
+ printf(" l = window left coordinate\n");
+ printf(" t = window top coordinate\n");
+ printf(" w = window width\n");
+ printf(" h = window height\n");
+ printf(" -f: start game in full screen mode\n");
+ printf(" fw = full screen mode pixel width\n");
+ printf(" fh = full screen mode pixel height\n");
+ printf(" fb = full screen mode bits per pixel\n");
+ printf(" ff = full screen mode frequency\n");
+ printf(" -s: start player in stereo\n");
+ printf(" stereomode = hwpageflip or syncdoubling depending on the type of stereo you want\n");
+#ifdef _WIN32
+ printf(" -c: keep console window open\n");
+#endif
+ printf("\n");
+ printf("example: %s -p 10 10 320 200 -g noaudio c:\\loadtest.blend\n", program);
+}
+
+char *get_filename(int argc, char **argv) {
+#ifdef __APPLE__
+/* On Mac we park the game file (called game.blend) in the application bundle.
+* The executable is located in the bundle as well.
+* Therefore, we can locate the game relative to the executable.
+ */
+ int srclen = ::strlen(argv[0]);
+ int len = 0;
+ char *filename = NULL;
+
+ if (argc > 1) {
+ if (BLI_exists(argv[argc-1])) {
+ len = ::strlen(argv[argc-1]);
+ filename = new char [len + 1];
+ ::strcpy(filename, argv[argc-1]);
+ return(filename);
+ }
+ if (::strncmp(argv[argc-1], "-psn_", 5)==0) {
+ static char firstfilebuf[512];
+ if (GHOST_HACK_getFirstFile(firstfilebuf)) {
+ len = ::strlen(firstfilebuf);
+ filename = new char [len + 1];
+ ::strcpy(filename, firstfilebuf);
+ return(filename);
+ }
+ }
+ }
+
+ srclen -= ::strlen("MacOS/blenderplayer");
+ if (srclen > 0) {
+ len = srclen + ::strlen("Resources/game.blend");
+ filename = new char [len + 1];
+ ::strcpy(filename, argv[0]);
+ ::strcpy(filename + srclen, "Resources/game.blend");
+ //::printf("looking for file: %s\n", filename);
+
+ if (BLI_exists(filename)) {
+ return (filename);
+ }
+ }
+
+ return(NULL);
+#else
+ return (argc>1)?argv[argc-1]:NULL;
+#endif // !_APPLE
+}
+
+BlendFileData *load_game_data(char *progname, char *filename) {
+ BlendReadError error;
+ BlendFileData *bfd;
+
+ /* try to load ourself, will only work if we are a runtime */
+ bfd= BLO_read_from_file(progname, &error);
+
+ if (!bfd) {
+ if (filename) {
+ bfd= BLO_read_from_file(filename, &error);
+ }
+ }
+
+ if (bfd && bfd->type == BLENFILETYPE_BLEND) {
+ BLO_blendfiledata_free(bfd);
+ bfd = NULL;
+ error = BRE_NOT_A_PUBFILE;
+ }
+
+ if (!bfd) {
+ if (filename) {
+ printf("Loading %s failed: %s\n", filename, BLO_bre_as_string(error));
+ }
+ }
+
+ return bfd;
+}
+
+int main(int argc, char** argv)
+{
+ int i;
+ bool error = false;
+ SYS_SystemHandle syshandle = SYS_GetSystem();
+ bool fullScreen = false;
+ bool fullScreenParFound = false;
+ bool windowParFound = false;
+ bool closeConsole = true;
+ int stereomode = RAS_IRasterizer::RAS_STEREO_NOSTEREO;
+ bool stereoWindow = false;
+ bool stereoParFound = false;
+ int windowLeft = 100;
+ int windowTop = 100;
+ int windowWidth = 640;
+ int windowHeight = 480;
+ int fullScreenWidth = 640;
+ int fullScreenHeight= 480;
+ int fullScreenBpp = 16;
+ int fullScreenFrequency = 60;
+
+#ifdef __linux__
+#ifdef __alpha__
+ signal (SIGFPE, SIG_IGN);
+#endif /* __alpha__ */
+#endif /* __linux__ */
+
+#ifdef __APPLE__
+ // Can't use Carbon right now because of double defined type ID (In Carbon.h and DNA_ID.h, sigh)
+ /*
+ IBNibRef nibRef;
+ WindowRef window;
+ OSStatus err;
+
+ // Create a Nib reference passing the name of the nib file (without the .nib extension)
+ // CreateNibReference only searches into the application bundle.
+ err = ::CreateNibReference(CFSTR("main"), &nibRef);
+ if (err) return -1;
+
+ // Once the nib reference is created, set the menu bar. "MainMenu" is the name of the menu bar
+ // object. This name is set in InterfaceBuilder when the nib is created.
+ err = ::SetMenuBarFromNib(nibRef, CFSTR("MenuBar"));
+ if (err) return -1;
+
+ // We don't need the nib reference anymore.
+ ::DisposeNibReference(nibRef);
+ */
+#endif // __APPLE__
+
+ GEN_init_messaging_system();
+
+ // Parse command line options
+#ifndef NDEBUG
+ printf("argv[0] = '%s'\n", argv[0]);
+#endif
+ for (i = 1; (i < argc) && !error; i++)
+ {
+#ifndef NDEBUG
+ printf("argv[%d] = '%s'\n", i, argv[i]);
+#endif
+
+ if (argv[i][0] == '-')
+ {
+ switch (argv[i][1])
+ {
+ case 'g':
+ // Parse game options
+ {
+ i++;
+ if (i < argc)
+ {
+ char* paramname = argv[i];
+ // Check for single value versus assignment
+ if (i+1 < argc && (*(argv[i+1]) == '='))
+ {
+ i++;
+ if (i + 1 < argc)
+ {
+ i++;
+ // Assignment
+ SYS_WriteCommandLineString(syshandle, paramname, argv[i]);
+ }
+ else
+ {
+ error = true;
+ printf("error: argument assignment %s without value.\n", paramname);
+ }
+ }
+ else
+ {
+ SYS_WriteCommandLineInt(syshandle, argv[i], 1);
+ }
+ }
+ }
+ break;
+
+ case 'p':
+ // Parse window position and size options
+ if (argv[i][2] == 0) {
+ i++;
+ if ((i + 4) < argc)
+ {
+ windowLeft = atoi(argv[i++]);
+ windowTop = atoi(argv[i++]);
+ windowWidth = atoi(argv[i++]);
+ windowHeight = atoi(argv[i]);
+ windowParFound = true;
+ }
+ else
+ {
+ error = true;
+ printf("error: too few options for window argument.\n");
+ }
+ }
+ break;
+
+ case 'f':
+ // Parse window position and size options
+ {
+ fullScreen = true;
+ i++;
+ if ((i + 4) < argc)
+ {
+ fullScreenWidth = atoi(argv[i++]);
+ fullScreenHeight = atoi(argv[i++]);
+ fullScreenBpp = atoi(argv[i++]);
+ fullScreenFrequency = atoi(argv[i]);
+ fullScreenParFound = true;
+ }
+ else
+ {
+ error = true;
+ printf("error: too few options for fullscreen argument.\n");
+ }
+ }
+ break;
+ case 'c':
+ i++;
+ closeConsole = false;
+ break;
+ case 's': // stereo
+ i++;
+ if ((i + 1) < argc)
+ {
+ if(!strcmp(argv[i], "nostereo")) // ok, redundant but clear
+ stereomode = RAS_IRasterizer::RAS_STEREO_NOSTEREO;
+
+ // only the hardware pageflip method needs a stereo window
+ if(!strcmp(argv[i], "hwpageflip")) {
+ stereomode = RAS_IRasterizer::RAS_STEREO_QUADBUFFERED;
+ stereoWindow = true;
+ }
+ if(!strcmp(argv[i], "syncdoubling"))
+ stereomode = RAS_IRasterizer::RAS_STEREO_ABOVEBELOW;
+#if 0
+ // future stuff
+ if(strcmp(argv[i], "stencil")
+ stereomode = RAS_STEREO_STENCIL;
+#endif
+
+ i++;
+ stereoParFound = true;
+ }
+ else
+ {
+ error = true;
+ printf("error: too few options for stereo argument.\n");
+ }
+ break;
+ }
+ }
+ else
+ {
+ }
+ }
+
+ if ((windowWidth < kMinWindowWidth) || (windowHeight < kMinWindowHeight))
+ {
+ error = true;
+ printf("error: window size too small.\n");
+ }
+
+ if (error)
+ {
+ usage(argv[0]);
+ }
+ else
+ {
+#ifdef __APPLE__
+ //SYS_WriteCommandLineInt(syshandle, "show_framerate", 1);
+ SYS_WriteCommandLineInt(syshandle, "nomipmap", 1);
+ //fullScreen = false; // Can't use full screen
+#endif
+ if (SYS_GetCommandLineInt(syshandle, "nomipmap", 0))
+ {
+ GPC_PolygonMaterial::SetMipMappingEnabled(0);
+ }
+
+ // Create the system
+ if (GHOST_ISystem::createSystem() == GHOST_kSuccess)
+ {
+ GHOST_ISystem* system = GHOST_ISystem::getSystem();
+ assertd(system);
+
+ // process first batch of events. If the user
+ // drops a file on top off the blenderplayer icon, we
+ // recieve an event with the filename
+
+ system->processEvents(0);
+
+ // this bracket is needed for app (see below) to get out
+ // of scope before GHOST_ISystem::disposeSystem() is called.
+ {
+ int exitcode = KX_EXIT_REQUEST_NO_REQUEST;
+ STR_String exitstring = "";
+ GPG_Application app(system, NULL, exitstring);
+ bool firstTimeRunning = true;
+
+ do
+ {
+ // Read the Blender file
+ char *filename = get_filename(argc, argv);
+ char *titlename;
+ char pathname[160];
+ BlendFileData *bfd;
+
+ // if we got an exitcode 3 (KX_EXIT_REQUEST_START_OTHER_GAME) load a different file
+ if (exitcode == KX_EXIT_REQUEST_START_OTHER_GAME)
+ {
+ char basedpath[160];
+
+ // base the actuator filename with respect
+ // to the original file working directory
+ strcpy(basedpath, exitstring.Ptr());
+ BLI_convertstringcode(basedpath, pathname, 0);
+
+ bfd = load_game_data(NULL, basedpath);
+ }
+ else
+ {
+ bfd = load_game_data(argv[0], filename);
+ }
+
+ //::printf("game data loaded from %s\n", filename);
+
+ if (!bfd) {
+ usage(argv[0]);
+ error = true;
+ exitcode = KX_EXIT_REQUEST_QUIT_GAME;
+ }
+ else
+ {
+#ifdef WIN32
+#ifdef NDEBUG
+ if (closeConsole)
+ {
+ ::FreeConsole(); // Close a console window
+ }
+#endif // NDEBUG
+#endif // WIN32
+ Main *maggie = bfd->main;
+ Scene *scene = bfd->curscene;
+ strcpy (pathname, maggie->name);
+ char *startscenename = scene->id.name + 2;
+
+ titlename = maggie->name;
+
+ // Check whether the game should be displayed full-screen
+ if ((!fullScreenParFound) && (!windowParFound))
+ {
+ // Only use file settings when command line did not override
+ if (scene->r.fullscreen) {
+ //printf("fullscreen option found in Blender file\n");
+ fullScreen = true;
+ fullScreenWidth= scene->r.xplay;
+ fullScreenHeight= scene->r.yplay;
+ fullScreenFrequency= scene->r.freqplay;
+ fullScreenBpp = scene->r.depth;
+ }
+ else
+ {
+ fullScreen = false;
+ windowWidth = scene->r.xplay;
+ windowHeight = scene->r.yplay;
+ }
+ }
+
+
+ // Check whether the game should be displayed in stereo
+ if (!stereoParFound)
+ {
+ if(scene->r.stereomode == RAS_IRasterizer::RAS_STEREO_NOSTEREO) // ok, redundant but clear
+ stereomode = RAS_IRasterizer::RAS_STEREO_NOSTEREO;
+
+ // only the hardware pageflip method needs a stereo window
+ if(scene->r.stereomode == RAS_IRasterizer::RAS_STEREO_QUADBUFFERED) {
+ stereomode = RAS_IRasterizer::RAS_STEREO_QUADBUFFERED;
+ stereoWindow = true;
+ }
+ if(scene->r.stereomode == RAS_IRasterizer::RAS_STEREO_ABOVEBELOW)
+ stereomode = RAS_IRasterizer::RAS_STEREO_ABOVEBELOW;
+#if 0
+ // future stuff
+ if(scene->r.stereomode == RAS_IRasterizer::RAS_STEREO_STENCIL)
+ stereomode = RAS_STEREO_STENCIL;
+#endif
+ }
+
+ // GPG_Application app (system, maggie, startscenename);
+ app.SetGameEngineData(maggie, startscenename);
+
+ if (firstTimeRunning)
+ {
+ firstTimeRunning = false;
+
+ if (fullScreen)
+ {
+ app.startFullScreen(fullScreenWidth, fullScreenHeight, fullScreenBpp, fullScreenFrequency,
+ stereoWindow, stereomode);
+ }
+ else
+ {
+#ifdef __APPLE__
+ // on Mac's we'll show the executable name instead of the 'game.blend' name
+ char tempname[1024], *appstring;
+ ::strcpy(tempname, titlename);
+
+ appstring = strstr(tempname, ".app/");
+ if (appstring) {
+ appstring[2] = 0;
+ titlename = &tempname[0];
+ }
+#endif
+ // Strip the path so that we have the name of the game file
+ STR_String path = titlename;
+#ifndef WIN32
+ vector<STR_String> parts = path.Explode('/');
+#else // WIN32
+ vector<STR_String> parts = path.Explode('\\');
+#endif // WIN32
+ STR_String title;
+ if (parts.size())
+ {
+ title = parts[parts.size()-1];
+ parts = title.Explode('.');
+ if (parts.size() > 1)
+ {
+ title = parts[0];
+ }
+ }
+ else
+ {
+ title = "blenderplayer";
+ }
+ app.startWindow(title, windowLeft, windowTop, windowWidth, windowHeight,
+ stereoWindow, stereomode);
+ }
+ }
+ else
+ {
+ app.StartGameEngine(stereomode);
+ exitcode = KX_EXIT_REQUEST_NO_REQUEST;
+ }
+
+ // Add the application as event consumer
+ system->addEventConsumer(&app);
+
+ // Enter main loop
+ bool run = true;
+ while (run)
+ {
+ system->processEvents(true);
+ system->dispatchEvents();
+ if (exitcode = app.getExitRequested())
+ {
+ run = false;
+ exitstring = app.getExitString();
+ }
+ }
+ app.StopGameEngine();
+ BLO_blendfiledata_free(bfd);
+
+#ifdef __APPLE__
+ if (filename) {
+ delete [] filename;
+ }
+#endif // __APPLE__
+ }
+ } while (exitcode == KX_EXIT_REQUEST_RESTART_GAME || exitcode == KX_EXIT_REQUEST_START_OTHER_GAME);
+ }
+ // Dispose the system
+ GHOST_ISystem::disposeSystem();
+ } else {
+ error = true;
+ printf("error: couldn't create a system.\n");
+ }
+ }
+
+ return error ? -1 : 0;
+}
+
+
diff --git a/source/gameengine/GamePlayer/ghost/Makefile b/source/gameengine/GamePlayer/ghost/Makefile
new file mode 100644
index 00000000000..7e9735a4bd8
--- /dev/null
+++ b/source/gameengine/GamePlayer/ghost/Makefile
@@ -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 *****
+#
+# Makefile for GHOST game player
+
+LIBNAME = ghost
+DIR = $(OCGDIR)/gameengine/GamePlayer/ghost
+
+include nan_compile.mk
+
+CCFLAGS += $(LEVEL_1_CPP_WARNINGS)
+
+# OpenGL header files
+CPPFLAGS += -I$(OPENGL_HEADERS)
+CPPFLAGS += -I$(NAN_STRING)/include
+CPPFLAGS += -I$(NAN_BMFONT)/include
+
+CPPFLAGS += -I../../GamePlayer/common
+
+# Game Engine includes
+CPPFLAGS += -I../../Converter
+CPPFLAGS += -I../../Expressions
+CPPFLAGS += -I../../GameLogic
+CPPFLAGS += -I../../Ketsji
+CPPFLAGS += -I../../Ketsji/KXNetwork
+CPPFLAGS += -I../../Network
+CPPFLAGS += -I../../Network/LoopBackNetwork
+CPPFLAGS += -I../../Rasterizer
+CPPFLAGS += -I../../Rasterizer/RAS_OpenGLRasterizer
+CPPFLAGS += -I../../SceneGraph
+CPPFLAGS += -I../../SoundSystem
+CPPFLAGS += -I../../SoundSystem/SND_OpenAL
+
+# Sumo
+CPPFLAGS += -I../../../sumo/Fuzzics/include
+CPPFLAGS += -I../../../sumo/include
+CPPFLAGS += -I$(NAN_MOTO)/include
+
+# Blender includes
+CPPFLAGS += -I../../../blender/blenkernel
+CPPFLAGS += -I../../../blender/blenlib
+CPPFLAGS += -I../../../blender/blenloader
+CPPFLAGS += -I../../../blender/imbuf
+CPPFLAGS += -I../../../blender/makesdna
+CPPFLAGS += -I../../../blender/readblenfile
+
+# kernel? GEN? stuff
+CPPFLAGS += -I../../../kernel/gen_system
+CPPFLAGS += -I../../../kernel/gen_messaging
+
+CPPFLAGS += -I$(NAN_STRING)/include
+CPPFLAGS += -I$(NAN_GHOST)/include
+CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION)
+
diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkEventManager.cpp b/source/gameengine/Ketsji/KXNetwork/KX_NetworkEventManager.cpp
new file mode 100644
index 00000000000..99aa798cfa5
--- /dev/null
+++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkEventManager.cpp
@@ -0,0 +1,92 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * Ketsji Logic Extenstion: Network Event Manager generic implementation
+ */
+
+// Ketsji specific sensor part
+#include "SCA_ISensor.h"
+
+// Ketsji specific network part
+#include "KX_NetworkEventManager.h"
+
+// Network module specific
+#include "NG_NetworkDeviceInterface.h"
+#include "NG_NetworkMessage.h"
+#include "NG_NetworkObject.h"
+
+KX_NetworkEventManager::KX_NetworkEventManager(class SCA_LogicManager*
+logicmgr, class NG_NetworkDeviceInterface *ndi) :
+SCA_EventManager(NETWORK_EVENTMGR), m_logicmgr(logicmgr), m_ndi(ndi)
+{
+ //printf("KX_NetworkEventManager constructor\n");
+}
+
+KX_NetworkEventManager::~KX_NetworkEventManager()
+{
+ //printf("KX_NetworkEventManager destructor\n");
+}
+
+void KX_NetworkEventManager::RegisterSensor(class SCA_ISensor* sensor)
+{
+ //printf("KX_NetworkEventManager RegisterSensor\n");
+ m_sensors.push_back(sensor);
+}
+
+void KX_NetworkEventManager::RemoveSensor(class SCA_ISensor* sensor)
+{
+ //printf("KX_NetworkEventManager RemoveSensor\n");
+ // Network specific RemoveSensor stuff goes here
+
+ // parent
+ SCA_EventManager::RemoveSensor(sensor);
+}
+
+void KX_NetworkEventManager::NextFrame(double curtime, double deltatime)
+{
+// printf("KX_NetworkEventManager::proceed %.2f - %.2f\n", curtime, deltatime);
+ // each frame, the logicmanager will call the network
+ // eventmanager to look for network events, and process it's
+ // 'network' sensors
+ vector<class SCA_ISensor*>::iterator it;
+
+ for (it = m_sensors.begin(); !(it==m_sensors.end()); it++) {
+// printf("KX_NetworkEventManager::proceed sensor %.2f\n", curtime);
+ // process queue
+ (*it)->Activate(m_logicmgr, NULL);
+ }
+
+ // now a list of triggerer sensors has been built
+}
+
+void KX_NetworkEventManager::EndFrame()
+{
+}
+
diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkEventManager.h b/source/gameengine/Ketsji/KXNetwork/KX_NetworkEventManager.h
new file mode 100644
index 00000000000..521a3b4d030
--- /dev/null
+++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkEventManager.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 *****
+ * Ketsji Logic Extenstion: Network Event Manager class
+ */
+#ifndef KX_NETWORK_EVENTMANAGER_H
+#define KX_NETWORK_EVENTMANAGER_H
+
+#include "SCA_EventManager.h"
+
+class KX_NetworkEventManager : public SCA_EventManager
+{
+ class SCA_LogicManager* m_logicmgr;
+ class NG_NetworkDeviceInterface* m_ndi;
+
+public:
+ KX_NetworkEventManager(class SCA_LogicManager* logicmgr,
+ class NG_NetworkDeviceInterface *ndi);
+ virtual ~KX_NetworkEventManager ();
+
+ virtual void RegisterSensor(class SCA_ISensor* sensor);
+ virtual void RemoveSensor(class SCA_ISensor* sensor);
+
+ virtual void NextFrame(double curtime, double deltatime);
+ virtual void EndFrame();
+
+ SCA_LogicManager* GetLogicManager() { return m_logicmgr; }
+ class NG_NetworkDeviceInterface* GetNetworkDevice() {
+ return m_ndi; }
+};
+
+#endif //KX_NETWORK_EVENTMANAGER_H
diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.cpp b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.cpp
new file mode 100644
index 00000000000..1eb85d60b29
--- /dev/null
+++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.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 *****
+ * Ketsji Logic Extenstion: Network Message Actuator generic implementation
+ */
+
+#include "NG_NetworkScene.h"
+#include "KX_NetworkMessageActuator.h"
+
+KX_NetworkMessageActuator::KX_NetworkMessageActuator(
+ SCA_IObject* gameobj, // the actuator controlling object
+ NG_NetworkScene* networkscene, // needed for replication
+ const STR_String &toPropName,
+ const STR_String &subject,
+ int bodyType,
+ const STR_String &body,
+ PyTypeObject* T) :
+ SCA_IActuator(gameobj,T),
+ m_networkscene(networkscene),
+ m_toPropName(toPropName),
+ m_subject(subject),
+ m_bodyType(bodyType),
+ m_body(body)
+{
+}
+
+KX_NetworkMessageActuator::~KX_NetworkMessageActuator()
+{
+}
+
+// returns true if the actuators needs to be running over several frames
+bool KX_NetworkMessageActuator::Update(double curtime, double deltatime)
+{
+ //printf("update messageactuator\n");
+ bool bNegativeEvent = IsNegativeEvent();
+ RemoveAllEvents();
+
+ if (bNegativeEvent) {
+ return false; // do nothing on negative events
+ //printf("messageactuator false event\n");
+ }
+ //printf("messageactuator true event\n");
+
+ if (m_bodyType == 1) // ACT_MESG_PROP in DNA_actuator_types.h
+ {
+ m_networkscene->SendMessage(
+ m_toPropName,
+ GetParent()->GetName(),
+ m_subject,
+ GetParent()->GetPropertyText(m_body,""));
+ } else
+ {
+ m_networkscene->SendMessage(
+ m_toPropName,
+ GetParent()->GetName(),
+ m_subject,
+ m_body);
+ }
+ return false;
+}
+
+CValue* KX_NetworkMessageActuator::GetReplica()
+{
+ KX_NetworkMessageActuator* replica =
+ new KX_NetworkMessageActuator(*this);
+ replica->ProcessReplica();
+
+ // this will copy properties and so on...
+ CValue::AddDataToReplica(replica);
+
+ return replica;
+}
+
+/* -------------------------------------------------------------------- */
+/* Python interface --------------------------------------------------- */
+/* -------------------------------------------------------------------- */
+
+/* Integration hooks -------------------------------------------------- */
+PyTypeObject KX_NetworkMessageActuator::Type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0,
+ "KX_NetworkMessageActuator",
+ sizeof(KX_NetworkMessageActuator),
+ 0,
+ PyDestructor,
+ 0,
+ __getattr,
+ __setattr,
+ 0, //&MyPyCompare,
+ __repr,
+ 0, //&cvalue_as_number,
+ 0,
+ 0,
+ 0,
+ 0
+};
+
+PyParentObject KX_NetworkMessageActuator::Parents[] = {
+ &KX_NetworkMessageActuator::Type,
+ &SCA_IActuator::Type,
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
+};
+
+PyMethodDef KX_NetworkMessageActuator::Methods[] = {
+ {"setToPropName", (PyCFunction)
+ KX_NetworkMessageActuator::sPySetToPropName, METH_VARARGS},
+ {"setSubject", (PyCFunction)
+ KX_NetworkMessageActuator::sPySetSubject, METH_VARARGS},
+ {"setBodyType", (PyCFunction)
+ KX_NetworkMessageActuator::sPySetBodyType, METH_VARARGS},
+ {"setBody", (PyCFunction)
+ KX_NetworkMessageActuator::sPySetBody, METH_VARARGS},
+ {NULL,NULL} // Sentinel
+};
+
+PyObject* KX_NetworkMessageActuator::_getattr(char* attr) {
+ _getattr_up(SCA_IActuator);
+}
+
+// 1. SetToPropName
+PyObject* KX_NetworkMessageActuator::PySetToPropName(
+ PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ char* ToPropName;
+
+ if (PyArg_ParseTuple(args, "s", &ToPropName)) {
+ m_toPropName = ToPropName;
+ }
+
+ Py_Return;
+}
+
+// 2. SetSubject
+PyObject* KX_NetworkMessageActuator::PySetSubject(
+ PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ char* Subject;
+
+ if (PyArg_ParseTuple(args, "s", &Subject)) {
+ m_subject = Subject;
+ }
+
+ Py_Return;
+}
+
+// 3. SetBodyType
+PyObject* KX_NetworkMessageActuator::PySetBodyType(
+ PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ int BodyType;
+
+ if (PyArg_ParseTuple(args, "i", &BodyType)) {
+ m_bodyType = BodyType;
+ }
+
+ Py_Return;
+}
+
+// 4. SetBody
+PyObject* KX_NetworkMessageActuator::PySetBody(
+ PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ char* Body;
+
+ if (PyArg_ParseTuple(args, "s", &Body)) {
+ m_body = Body;
+ }
+
+ Py_Return;
+}
+
diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.h b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.h
new file mode 100644
index 00000000000..2ab4319821c
--- /dev/null
+++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.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 *****
+ * Ketsji Logic Extenstion: Network Message Actuator class
+ */
+#ifndef __KX_NETWORKMESSAGEACTUATOR_H
+#define __KX_NETWORKMESSAGEACTUATOR_H
+
+#include "STR_String.h"
+
+#include "SCA_IActuator.h"
+
+#include "NG_NetworkMessage.h"
+
+class KX_NetworkMessageActuator : public SCA_IActuator
+{
+ Py_Header;
+ bool m_lastEvent;
+ class NG_NetworkScene* m_networkscene; // needed for replication
+ STR_String m_toPropName;
+ STR_String m_subject;
+ int m_bodyType;
+ STR_String m_body;
+public:
+ KX_NetworkMessageActuator(
+ SCA_IObject* gameobj,
+ NG_NetworkScene* networkscene,
+ const STR_String &toPropName,
+ const STR_String &subject,
+ int bodyType,
+ const STR_String &body,
+ PyTypeObject* T=&Type);
+ virtual ~KX_NetworkMessageActuator();
+
+ virtual bool Update(double curtime, double deltatime);
+ virtual CValue* GetReplica();
+
+ /* ------------------------------------------------------------ */
+ /* Python interface ------------------------------------------- */
+ /* ------------------------------------------------------------ */
+
+ virtual PyObject* _getattr(char *attr);
+
+ KX_PYMETHOD(KX_NetworkMessageActuator, SetToPropName);
+ KX_PYMETHOD(KX_NetworkMessageActuator, SetSubject);
+ KX_PYMETHOD(KX_NetworkMessageActuator, SetBodyType);
+ KX_PYMETHOD(KX_NetworkMessageActuator, SetBody);
+
+};
+#endif //__KX_NETWORKMESSAGEACTUATOR_H
diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp
new file mode 100644
index 00000000000..1eeceb55469
--- /dev/null
+++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp
@@ -0,0 +1,258 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * Ketsji Logic Extenstion: Network Message Sensor generic implementation
+ */
+
+#include "KX_NetworkMessageSensor.h"
+#include "KX_NetworkEventManager.h"
+#include "NG_NetworkMessage.h"
+#include "NG_NetworkScene.h"
+#include "NG_NetworkObject.h"
+#include "SCA_IObject.h"
+#include "InputParser.h"
+#include "ListValue.h"
+#include "StringValue.h"
+
+#ifdef NAN_NET_DEBUG
+ #include <iostream>
+#endif
+
+KX_NetworkMessageSensor::KX_NetworkMessageSensor(
+ class KX_NetworkEventManager* eventmgr, // our eventmanager
+ class NG_NetworkScene *NetworkScene, // our scene
+ SCA_IObject* gameobj, // the sensor controlling object
+ const STR_String &subject,
+ PyTypeObject* T
+) :
+ SCA_ISensor(gameobj,eventmgr,T),
+ m_Networkeventmgr(eventmgr),
+ m_NetworkScene(NetworkScene),
+ m_subject(subject),
+ m_frame_message_count (0),
+ m_IsUp(false),
+ m_BodyList(NULL)
+{
+}
+
+KX_NetworkMessageSensor::~KX_NetworkMessageSensor()
+{
+}
+
+CValue* KX_NetworkMessageSensor::GetReplica() {
+ // This is the standard sensor implementation of GetReplica
+ // There may be more network message sensor specific stuff to do here.
+ CValue* replica = new KX_NetworkMessageSensor(*this);
+
+ if (replica == NULL) return NULL;
+
+ // this will copy properties and so on...
+ CValue::AddDataToReplica(replica);
+
+ return replica;
+}
+
+// Return true only for flank (UP and DOWN)
+bool KX_NetworkMessageSensor::Evaluate(CValue* event)
+{
+ bool result = false;
+ bool WasUp = m_IsUp;
+
+ m_IsUp = false;
+ if (m_BodyList) {
+ m_BodyList->Release();
+ m_BodyList = NULL;
+ }
+
+ STR_String toname=GetParent()->GetName();
+ STR_String subject = this->m_subject;
+
+ vector<NG_NetworkMessage*> messages =
+ m_NetworkScene->FindMessages(toname,"",subject,true);
+
+ m_frame_message_count = messages.size();
+
+ if (!messages.empty()) {
+#ifdef NAN_NET_DEBUG
+ printf("KX_NetworkMessageSensor found one or more messages\n");
+#endif
+ m_IsUp = true;
+ m_BodyList = new CListValue();
+ }
+
+ vector<NG_NetworkMessage*>::iterator mesit;
+ for (mesit=messages.begin();mesit!=messages.end();mesit++)
+ {
+ // save the body
+ STR_String body = (*mesit)->GetMessageText();
+#ifdef NAN_NET_DEBUG
+ if (body) {
+ cout << "body [" << body << "]\n";
+ }
+#endif
+ m_BodyList->Add(new CStringValue(body,"body"));
+
+ // free the message
+ (*mesit)->Release();
+ }
+ messages.clear();
+
+ result = (WasUp != m_IsUp);
+
+ // Return true if the message received state has changed.
+ return result;
+}
+
+// return true for being up (no flank needed)
+bool KX_NetworkMessageSensor::IsPositiveTrigger()
+{
+// printf("KX_NetworkMessageSensor IsPositiveTrigger\n");
+ return m_IsUp;
+}
+
+/* --------------------------------------------------------------------- */
+/* Python interface ---------------------------------------------------- */
+/* --------------------------------------------------------------------- */
+
+/* Integration hooks --------------------------------------------------- */
+PyTypeObject KX_NetworkMessageSensor::Type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0,
+ "KX_NetworkMessageSensor",
+ sizeof(KX_NetworkMessageSensor),
+ 0,
+ PyDestructor,
+ 0,
+ __getattr,
+ __setattr,
+ 0, //&MyPyCompare,
+ __repr,
+ 0, //&cvalue_as_number,
+ 0,
+ 0,
+ 0,
+ 0
+};
+
+PyParentObject KX_NetworkMessageSensor::Parents[] = {
+ &KX_NetworkMessageSensor::Type,
+ &SCA_ISensor::Type,
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
+};
+
+PyMethodDef KX_NetworkMessageSensor::Methods[] = {
+ {"setSubjectFilterText", (PyCFunction)
+ KX_NetworkMessageSensor::sPySetSubjectFilterText, METH_VARARGS,
+ SetSubjectFilterText_doc},
+ {"getFrameMessageCount", (PyCFunction)
+ KX_NetworkMessageSensor::sPyGetFrameMessageCount, METH_VARARGS,
+ GetFrameMessageCount_doc},
+ {"getBodies", (PyCFunction)
+ KX_NetworkMessageSensor::sPyGetBodies, METH_VARARGS,
+ GetBodies_doc},
+ {"getSubject", (PyCFunction)
+ KX_NetworkMessageSensor::sPyGetSubject, METH_VARARGS,
+ GetSubject_doc},
+ {NULL,NULL} //Sentinel
+};
+
+PyObject* KX_NetworkMessageSensor::_getattr(char* attr) {
+ _getattr_up(SCA_ISensor); // implicit return!
+}
+
+// 1. Set the message subject that this sensor listens for
+char KX_NetworkMessageSensor::SetSubjectFilterText_doc[] =
+"\tsetSubjectFilterText(value)\n"
+"\tChange the message subject text that this sensor is listening to.\n";
+
+PyObject* KX_NetworkMessageSensor::PySetSubjectFilterText(
+ PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ char* Subject;
+
+ if (PyArg_ParseTuple(args, "s", &Subject))
+ {
+ m_subject = Subject;
+ }
+
+ Py_Return;
+}
+
+// 2. Get the number of messages received since the last frame
+char KX_NetworkMessageSensor::GetFrameMessageCount_doc[] =
+"\tgetFrameMessageCount()\n"
+"\tGet the number of messages received since the last frame.\n";
+
+PyObject* KX_NetworkMessageSensor::PyGetFrameMessageCount(
+ PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ return PyInt_FromLong(long(m_frame_message_count));
+}
+
+// 3. Get the message bodies
+char KX_NetworkMessageSensor::GetBodies_doc[] =
+"\tgetBodies()\n"
+"\tGet the list of message bodies.\n";
+
+PyObject* KX_NetworkMessageSensor::PyGetBodies(
+ PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ if (m_BodyList) {
+ return ((PyObject*) m_BodyList->AddRef());
+ }
+
+ Py_Return;
+}
+
+// 4. Get the message subject
+char KX_NetworkMessageSensor::GetSubject_doc[] =
+"\tgetSubject()\n"
+"\tGet the subject of the message.\n";
+
+PyObject* KX_NetworkMessageSensor::PyGetSubject(
+ PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ if (m_subject) {
+ return PyString_FromString(m_subject);
+ }
+
+ Py_Return;
+}
+
diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h
new file mode 100644
index 00000000000..2c30befd883
--- /dev/null
+++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h
@@ -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 *****
+ * Ketsji Logic Extenstion: Network Message Sensor class
+ */
+#ifndef __KX_NETWORKMESSAGE_SENSOR_H
+#define __KX_NETWORKMESSAGE_SENSOR_H
+
+#include "SCA_ISensor.h"
+
+class KX_NetworkEventManager;
+class NG_NetworkScene;
+
+class KX_NetworkMessageSensor : public SCA_ISensor
+{
+ // note: Py_Header MUST BE the first listed here
+ Py_Header;
+ KX_NetworkEventManager *m_Networkeventmgr;
+ NG_NetworkScene *m_NetworkScene;
+
+ // The subject we filter on.
+ STR_String m_subject;
+
+ // The number of messages caught since the last frame.
+ int m_frame_message_count;
+
+ bool m_IsUp;
+
+ class CListValue* m_BodyList;
+public:
+ KX_NetworkMessageSensor(
+ KX_NetworkEventManager* eventmgr, // our eventmanager
+ NG_NetworkScene *NetworkScene, // our scene
+ SCA_IObject* gameobj, // the sensor controlling object
+ const STR_String &subject,
+ PyTypeObject* T=&Type
+ );
+ virtual ~KX_NetworkMessageSensor();
+
+ virtual CValue* GetReplica();
+ virtual bool Evaluate(CValue* event);
+ virtual bool IsPositiveTrigger();
+ void EndFrame();
+
+ /* ------------------------------------------------------------- */
+ /* Python interface -------------------------------------------- */
+ /* ------------------------------------------------------------- */
+
+ virtual PyObject* _getattr(char *attr);
+
+ KX_PYMETHOD_DOC(KX_NetworkMessageSensor, SetSubjectFilterText);
+ KX_PYMETHOD_DOC(KX_NetworkMessageSensor, GetFrameMessageCount);
+ KX_PYMETHOD_DOC(KX_NetworkMessageSensor, GetBodies);
+ KX_PYMETHOD_DOC(KX_NetworkMessageSensor, GetSubject);
+
+
+};
+#endif //__KX_NETWORKMESSAGE_SENSOR_H
diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkObjectActuator.cpp b/source/gameengine/Ketsji/KXNetwork/KX_NetworkObjectActuator.cpp
new file mode 100644
index 00000000000..a7800aea8c8
--- /dev/null
+++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkObjectActuator.cpp
@@ -0,0 +1,31 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkObjectActuator.h b/source/gameengine/Ketsji/KXNetwork/KX_NetworkObjectActuator.h
new file mode 100644
index 00000000000..a7800aea8c8
--- /dev/null
+++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkObjectActuator.h
@@ -0,0 +1,31 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkObjectSensor.cpp b/source/gameengine/Ketsji/KXNetwork/KX_NetworkObjectSensor.cpp
new file mode 100644
index 00000000000..a7800aea8c8
--- /dev/null
+++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkObjectSensor.cpp
@@ -0,0 +1,31 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkObjectSensor.h b/source/gameengine/Ketsji/KXNetwork/KX_NetworkObjectSensor.h
new file mode 100644
index 00000000000..a7800aea8c8
--- /dev/null
+++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkObjectSensor.h
@@ -0,0 +1,31 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
diff --git a/source/gameengine/Ketsji/KXNetwork/Makefile b/source/gameengine/Ketsji/KXNetwork/Makefile
new file mode 100644
index 00000000000..bce2cbc29a3
--- /dev/null
+++ b/source/gameengine/Ketsji/KXNetwork/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 *****
+#
+#
+
+LIBNAME = KXNetwork
+DIR = $(OCGDIR)/gameengine/ketsji/$(LIBNAME)
+
+include nan_compile.mk
+
+CCFLAGS += $(LEVEL_1_CPP_WARNINGS)
+
+CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION)
+CPPFLAGS += -I$(NAN_STRING)/include
+CPPFLAGS += -I../../Expressions
+CPPFLAGS += -I../../GameLogic
+CPPFLAGS += -I../../Network
+CPPFLAGS += -I../../../kernel/gen_system
+CPPFLAGS += -I..
+
diff --git a/source/gameengine/Ketsji/KX_CDActuator.cpp b/source/gameengine/Ketsji/KX_CDActuator.cpp
new file mode 100644
index 00000000000..e69e0e98960
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_CDActuator.cpp
@@ -0,0 +1,252 @@
+/**
+ * KX_CDActuator.cpp
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "KX_CDActuator.h"
+#include "SND_CDObject.h"
+#include "KX_GameObject.h"
+#include "SND_Scene.h" // needed for replication
+#include <iostream>
+
+/* ------------------------------------------------------------------------- */
+/* Native functions */
+/* ------------------------------------------------------------------------- */
+KX_CDActuator::KX_CDActuator(SCA_IObject* gameobject,
+ SND_Scene* soundscene,
+ KX_CDACT_TYPE type,
+ int track,
+ short start,
+ short end,
+ PyTypeObject* T)
+ : SCA_IActuator(gameobject,T)
+{
+ m_soundscene = soundscene;
+ m_type = type;
+ m_track = track;
+ m_lastEvent = true;
+ m_isplaying = false;
+ m_startFrame = start;
+ m_endFrame = end;
+ m_gain = SND_CDObject::Instance()->GetGain();
+}
+
+
+
+KX_CDActuator::~KX_CDActuator()
+{
+}
+
+
+/* hmmm, do we want this? */
+CValue* KX_CDActuator::GetReplica()
+{
+ KX_CDActuator* replica = new KX_CDActuator(*this);
+ replica->ProcessReplica();
+
+ // this will copy properties and so on...
+ CValue::AddDataToReplica(replica);
+ return replica;
+};
+
+
+
+bool KX_CDActuator::Update(double curtime,double deltatime)
+{
+ bool result = false;
+ bool bNegativeEvent = IsNegativeEvent();
+
+ RemoveAllEvents();
+
+ if (!bNegativeEvent)
+ {
+ switch (m_type)
+ {
+ case KX_CDACT_PLAY_ALL:
+ {
+ SND_CDObject::Instance()->SetPlaymode(SND_CD_ALL);
+ SND_CDObject::Instance()->SetTrack(1);
+ SND_CDObject::Instance()->SetPlaystate(SND_MUST_PLAY);
+ result = true;
+ break;
+ }
+ case KX_CDACT_PLAY_TRACK:
+ {
+ SND_CDObject::Instance()->SetPlaymode(SND_CD_TRACK);
+ SND_CDObject::Instance()->SetTrack(m_track);
+ SND_CDObject::Instance()->SetPlaystate(SND_MUST_PLAY);
+ result = true;
+ break;
+ }
+ case KX_CDACT_LOOP_TRACK:
+ {
+ SND_CDObject::Instance()->SetPlaymode(SND_CD_ALL);
+ SND_CDObject::Instance()->SetTrack(m_track);
+ SND_CDObject::Instance()->SetPlaystate(SND_MUST_PLAY);
+ result = true;
+ break;
+ }
+ case KX_CDACT_STOP:
+ {
+ SND_CDObject::Instance()->SetPlaystate(SND_MUST_STOP);
+ break;
+ }
+ case KX_CDACT_PAUSE:
+ {
+ SND_CDObject::Instance()->SetPlaystate(SND_MUST_PAUSE);
+ result = true;
+ break;
+ }
+ case KX_CDACT_RESUME:
+ {
+ SND_CDObject::Instance()->SetPlaystate(SND_MUST_RESUME);
+ result = true;
+ break;
+ }
+ case KX_CDACT_VOLUME:
+ {
+ SND_CDObject::Instance()->SetGain(m_gain);
+ result = true;
+ break;
+ }
+ default:
+ // implement me !!
+ break;
+ }
+ }
+ return result;
+}
+
+
+
+/* ------------------------------------------------------------------------- */
+/* Python functions */
+/* ------------------------------------------------------------------------- */
+
+
+
+/* Integration hooks ------------------------------------------------------- */
+PyTypeObject KX_CDActuator::Type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0,
+ "KX_SoundActuator",
+ sizeof(KX_CDActuator),
+ 0,
+ PyDestructor,
+ 0,
+ __getattr,
+ __setattr,
+ 0, //&MyPyCompare,
+ __repr,
+ 0, //&cvalue_as_number,
+ 0,
+ 0,
+ 0,
+ 0
+};
+
+
+
+PyParentObject KX_CDActuator::Parents[] = {
+ &KX_CDActuator::Type,
+ &SCA_IActuator::Type,
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
+};
+
+
+
+PyMethodDef KX_CDActuator::Methods[] = {
+ {"startCD",(PyCFunction) KX_CDActuator::sPyStartCD,METH_VARARGS,NULL},
+ {"pauseCD",(PyCFunction) KX_CDActuator::sPyPauseCD,METH_VARARGS,NULL},
+ {"stopCD",(PyCFunction) KX_CDActuator::sPyStopCD,METH_VARARGS,NULL},
+ {"setGain",(PyCFunction) KX_CDActuator::sPySetGain,METH_VARARGS,NULL},
+ {"getGain",(PyCFunction) KX_CDActuator::sPyGetGain,METH_VARARGS,NULL},
+ {NULL,NULL,NULL,NULL} //Sentinel
+};
+
+
+
+PyObject* KX_CDActuator::_getattr(char* attr)
+{
+ _getattr_up(SCA_IActuator);
+}
+
+
+
+
+PyObject* KX_CDActuator::PyStartCD(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ SND_CDObject::Instance()->SetPlaystate(SND_MUST_PLAY);
+ Py_Return;
+}
+
+
+
+PyObject* KX_CDActuator::PyPauseCD(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ SND_CDObject::Instance()->SetPlaystate(SND_MUST_PAUSE);
+ Py_Return;
+}
+
+
+
+PyObject* KX_CDActuator::PyStopCD(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ SND_CDObject::Instance()->SetPlaystate(SND_MUST_STOP);
+ Py_Return;
+}
+
+
+
+PyObject* KX_CDActuator::PySetGain(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ float gain = 1.0;
+ if (!PyArg_ParseTuple(args, "f", &gain))
+ return NULL;
+
+ SND_CDObject::Instance()->SetGain(gain);
+
+ Py_Return;
+}
+
+
+
+PyObject* KX_CDActuator::PyGetGain(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ float gain = SND_CDObject::Instance()->GetGain();
+ PyObject* result = PyFloat_FromDouble(gain);
+
+ return result;
+} \ No newline at end of file
diff --git a/source/gameengine/Ketsji/KX_CDActuator.h b/source/gameengine/Ketsji/KX_CDActuator.h
new file mode 100644
index 00000000000..48570523f51
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_CDActuator.h
@@ -0,0 +1,97 @@
+/**
+ * KX_CDActuator.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 __KX_CDACTUATOR
+#define __KX_CDACTUATOR
+
+#include "SCA_IActuator.h"
+#include "SND_CDObject.h"
+
+
+class KX_CDActuator : public SCA_IActuator
+{
+ Py_Header;
+ bool m_lastEvent;
+ bool m_isplaying;
+ /* just some handles to the audio-data... */
+ class SND_Scene* m_soundscene;
+ int m_track;
+ float m_gain;
+ short m_startFrame;
+ short m_endFrame;
+
+public:
+ enum KX_CDACT_TYPE
+ {
+ KX_CDACT_NODEF = 0,
+ KX_CDACT_PLAY_ALL,
+ KX_CDACT_PLAY_TRACK,
+ KX_CDACT_LOOP_TRACK,
+ KX_CDACT_VOLUME,
+ KX_CDACT_STOP,
+ KX_CDACT_PAUSE,
+ KX_CDACT_RESUME,
+ KX_SOUNDACT_MAX
+ };
+
+ KX_CDACT_TYPE m_type;
+
+ KX_CDActuator(SCA_IObject* gameobject,
+ SND_Scene* soundscene,
+ KX_CDACT_TYPE type,
+ int track,
+ short start,
+ short end,
+ PyTypeObject* T=&Type);
+
+ ~KX_CDActuator();
+
+ bool Update(double curtime,double deltatime);
+
+ CValue* GetReplica();
+
+ /* -------------------------------------------------------------------- */
+ /* Python interface --------------------------------------------------- */
+ /* -------------------------------------------------------------------- */
+
+ PyObject* _getattr(char *attr);
+
+ KX_PYMETHOD(KX_CDActuator,StartCD);
+ KX_PYMETHOD(KX_CDActuator,PauseCD);
+ KX_PYMETHOD(KX_CDActuator,StopCD);
+ KX_PYMETHOD(KX_CDActuator,SetGain);
+ KX_PYMETHOD(KX_CDActuator,GetGain);
+};
+#endif //__KX_CDACTUATOR
+
diff --git a/source/gameengine/Ketsji/KX_Camera.cpp b/source/gameengine/Ketsji/KX_Camera.cpp
new file mode 100644
index 00000000000..919355d411a
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_Camera.cpp
@@ -0,0 +1,181 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * Camera in the gameengine. Cameras are also used for views.
+ */
+
+#include "KX_Camera.h"
+
+KX_Camera::KX_Camera(void* sgReplicationInfo,
+ SG_Callbacks callbacks,
+ const RAS_CameraData& camdata)
+ :
+ KX_GameObject(sgReplicationInfo,callbacks)
+{
+ // setting a name would be nice...
+ m_name = "cam";
+ m_camdata = camdata;
+ SetProperty("camera",new CIntValue(1));
+}
+
+
+
+KX_Camera::~KX_Camera()
+{
+}
+
+
+
+MT_Transform KX_Camera::GetWorldToCamera() const
+{
+ MT_Transform camtrans;
+ MT_Transform trans;
+
+ trans.setBasis(NodeGetWorldOrientation());
+ trans.setOrigin(NodeGetWorldPosition());
+
+ camtrans.invert(trans);
+
+ return camtrans;
+}
+
+
+
+MT_Transform KX_Camera::GetCameraToWorld() const
+{
+ MT_Transform trans;
+ trans.setBasis(NodeGetWorldOrientation());
+ trans.setOrigin(NodeGetWorldPosition());
+
+ return trans;
+}
+
+
+
+void KX_Camera::CorrectLookUp(MT_Scalar speed)
+{
+}
+
+
+
+const MT_Point3 KX_Camera::GetCameraLocation()
+{
+ /* this is the camera locatio in cam coords... */
+ //return m_trans1.getOrigin();
+ //return MT_Point3(0,0,0); <-----
+ /* .... I want it in world coords */
+ MT_Transform trans;
+ trans.setBasis(NodeGetWorldOrientation());
+
+ return NodeGetWorldPosition();
+}
+
+
+
+/* I want the camera orientation as well. */
+const MT_Quaternion KX_Camera::GetCameraOrientation()
+{
+ MT_Transform trans;
+ trans.setBasis(NodeGetWorldOrientation());
+ trans.setOrigin(NodeGetWorldPosition());
+
+ return trans.getRotation();
+}
+
+
+
+/**
+* Sets the projection matrix that is used by the rasterizer.
+*/
+void KX_Camera::SetProjectionMatrix(const MT_Matrix4x4 & mat)
+{
+ m_projection_matrix = mat;
+}
+
+
+
+/**
+* Sets the modelview matrix that is used by the rasterizer.
+*/
+void KX_Camera::SetModelviewMatrix(const MT_Matrix4x4 & mat)
+{
+ m_modelview_matrix = mat;
+}
+
+
+
+/**
+* Gets the projection matrix that is used by the rasterizer.
+*/
+void KX_Camera::GetProjectionMatrix(MT_Matrix4x4 & mat)
+{
+ mat = m_projection_matrix;
+}
+
+
+
+/**
+* Gets the modelview matrix that is used by the rasterizer.
+*/
+void KX_Camera::GetModelviewMatrix(MT_Matrix4x4 & mat)
+{
+ mat = m_modelview_matrix;
+}
+
+
+
+/*
+* These getters retrieve the clip data and the focal length
+*/
+float KX_Camera::GetLens()
+{
+ return m_camdata.m_lens;
+}
+
+
+
+float KX_Camera::GetCameraNear()
+{
+ return m_camdata.m_clipstart;
+}
+
+
+
+float KX_Camera::GetCameraFar()
+{
+ return m_camdata.m_clipend;
+}
+
+
+
+RAS_CameraData* KX_Camera::GetCameraData()
+{
+ return &m_camdata;
+}
diff --git a/source/gameengine/Ketsji/KX_Camera.h b/source/gameengine/Ketsji/KX_Camera.h
new file mode 100644
index 00000000000..0bc80102e45
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_Camera.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 *****
+ * Camera in the gameengine. Cameras are also used for views.
+ */
+
+#ifndef __KX_CAMERA
+#define __KX_CAMERA
+
+
+#include "MT_Transform.h"
+#include "MT_Matrix3x3.h"
+#include "MT_Matrix4x4.h"
+#include "MT_Vector3.h"
+#include "MT_Point3.h"
+#include "KX_GameObject.h"
+#include "IntValue.h"
+#include "RAS_CameraData.h"
+
+
+class KX_Camera : public KX_GameObject
+{
+
+ /** Camera parameters (clips distances, focal lenght). These
+ * params are closely tied to BLender. In the gameengine, only the
+ * projection and modelview matrices are relevant. There's a
+ * conversion being done in the engine class. Why is it stored
+ * here? It doesn't really have a function here. */
+ RAS_CameraData m_camdata;
+
+ // Never used, I think...
+// void MoveTo(const MT_Point3& movevec)
+// {
+ /*MT_Transform camtrans;
+ camtrans.invert(m_trans1);
+ MT_Matrix3x3 camorient = camtrans.getBasis();
+ camtrans.translate(camorient.inverse()*movevec);
+ m_trans1.invert(camtrans);
+ */
+// }
+
+ /**
+ * Storage for the projection matrix that is passed to the
+ * rasterizer. */
+ MT_Matrix4x4 m_projection_matrix;
+
+ /**
+ * Storage for the modelview matrix that is passed to the
+ * rasterizer. */
+ MT_Matrix4x4 m_modelview_matrix;
+
+public:
+
+ KX_Camera(void* sgReplicationInfo,SG_Callbacks callbacks,const RAS_CameraData& camdata);
+ virtual ~KX_Camera();
+
+ MT_Transform GetWorldToCamera() const;
+ MT_Transform GetCameraToWorld() const;
+
+ void CorrectLookUp(MT_Scalar speed);
+ const MT_Point3 GetCameraLocation();
+
+ /* I want the camera orientation as well. */
+ const MT_Quaternion GetCameraOrientation();
+
+ /** Sets the projection matrix that is used by the rasterizer. */
+ void SetProjectionMatrix(const MT_Matrix4x4 & mat);
+
+ /** Sets the modelview matrix that is used by the rasterizer. */
+ void SetModelviewMatrix(const MT_Matrix4x4 & mat);
+
+ /** Gets the projection matrix that is used by the rasterizer. */
+ void GetProjectionMatrix(MT_Matrix4x4 & mat);
+
+ /** Gets the modelview matrix that is used by the rasterizer. */
+ void GetModelviewMatrix(MT_Matrix4x4 & mat);
+
+ /** Gets the focal lenght. */
+ float GetLens();
+ /** Gets the near clip distance. */
+ float GetCameraNear();
+ /** Gets the far clip distance. */
+ float GetCameraFar();
+ /** Gets all camera data. */
+ RAS_CameraData* GetCameraData();
+};
+#endif //__KX_CAMERA
diff --git a/source/gameengine/Ketsji/KX_CameraActuator.cpp b/source/gameengine/Ketsji/KX_CameraActuator.cpp
new file mode 100644
index 00000000000..8a6ed0106f5
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_CameraActuator.cpp
@@ -0,0 +1,368 @@
+/**
+ * KX_CameraActuator.cpp
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "KX_CameraActuator.h"
+#include <iostream>
+#include <math.h>
+#include "KX_GameObject.h"
+
+STR_String KX_CameraActuator::X_AXIS_STRING = "x";
+STR_String KX_CameraActuator::Y_AXIS_STRING = "y";
+
+
+/* ------------------------------------------------------------------------- */
+/* Native functions */
+/* ------------------------------------------------------------------------- */
+
+KX_CameraActuator::KX_CameraActuator(
+ SCA_IObject* gameobj,
+ const CValue *obj,
+ MT_Scalar hght,
+ MT_Scalar minhght,
+ MT_Scalar maxhght,
+ bool xytog,
+ PyTypeObject* T
+):
+ SCA_IActuator(gameobj, T),
+ m_ob (obj),
+ m_height (hght),
+ m_minHeight (minhght),
+ m_maxHeight (maxhght),
+ m_x (xytog)
+{
+ // nothing to do
+}
+
+KX_CameraActuator::~KX_CameraActuator()
+{
+ //nothing to do
+}
+
+ CValue*
+KX_CameraActuator::
+GetReplica(
+) {
+ KX_CameraActuator* replica = new KX_CameraActuator(*this);
+ replica->ProcessReplica();
+ // this will copy properties and so on...
+ CValue::AddDataToReplica(replica);
+ return replica;
+};
+
+
+
+
+/* three functions copied from blender arith... don't know if there's an equivalent */
+
+float Normalise(float *n)
+{
+ float d;
+
+ d= n[0]*n[0]+n[1]*n[1]+n[2]*n[2];
+ /* FLT_EPSILON is too large! A larger value causes normalise errors in a scaled down utah teapot */
+ if(d>0.0000000000001) {
+ d= sqrt(d);
+
+ n[0]/=d;
+ n[1]/=d;
+ n[2]/=d;
+ } else {
+ n[0]=n[1]=n[2]= 0.0;
+ d= 0.0;
+ }
+ return d;
+}
+
+void Crossf(float *c, float *a, float *b)
+{
+ c[0] = a[1] * b[2] - a[2] * b[1];
+ c[1] = a[2] * b[0] - a[0] * b[2];
+ c[2] = a[0] * b[1] - a[1] * b[0];
+}
+
+
+void VecUpMat3(float *vec, float mat[][3], short axis)
+{
+
+ // Construct a camera matrix s.t. the specified axis
+
+ // maps to the given vector (*vec). Also defines the rotation
+
+ // about this axis by mapping one of the other axis to the y-axis.
+
+
+ float inp;
+ short cox = 0, coy = 0, coz = 0;
+
+ /* up varieeren heeft geen zin, is eigenlijk helemaal geen up!
+ * zie VecUpMat3old
+ */
+
+ if(axis==0) {
+ cox= 0; coy= 1; coz= 2; /* Y up Z tr */
+ }
+ if(axis==1) {
+ cox= 1; coy= 2; coz= 0; /* Z up X tr */
+ }
+ if(axis==2) {
+ cox= 2; coy= 0; coz= 1; /* X up Y tr */
+ }
+ if(axis==3) {
+ cox= 0; coy= 1; coz= 2; /* Y op -Z tr */
+ vec[0]= -vec[0];
+ vec[1]= -vec[1];
+ vec[2]= -vec[2];
+ }
+ if(axis==4) {
+ cox= 1; coy= 0; coz= 2; /* */
+ }
+ if(axis==5) {
+ cox= 2; coy= 1; coz= 0; /* Y up X tr */
+ }
+
+ mat[coz][0]= vec[0];
+ mat[coz][1]= vec[1];
+ mat[coz][2]= vec[2];
+ Normalise((float *)mat[coz]);
+
+ inp= mat[coz][2];
+ mat[coy][0]= - inp*mat[coz][0];
+ mat[coy][1]= - inp*mat[coz][1];
+ mat[coy][2]= 1.0 - inp*mat[coz][2];
+
+ Normalise((float *)mat[coy]);
+
+ Crossf(mat[cox], mat[coy], mat[coz]);
+
+}
+
+bool KX_CameraActuator::Update(double curtime,double deltatime)
+{
+ bool result = true;
+
+ KX_GameObject *obj = (KX_GameObject*) GetParent();
+ MT_Point3 from = obj->NodeGetWorldPosition();
+ MT_Matrix3x3 frommat = obj->NodeGetWorldOrientation();
+ /* These casts are _very_ dangerous!!! */
+ MT_Point3 lookat = ((KX_GameObject*)m_ob)->NodeGetWorldPosition();
+ MT_Matrix3x3 actormat = ((KX_GameObject*)m_ob)->NodeGetWorldOrientation();
+
+
+
+ float fp1[3], fp2[3], rc[3];
+ float inp, fac; //, factor = 0.0; /* some factor... */
+ float mindistsq, maxdistsq, distsq;
+ float mat[3][3];
+
+ /* wondering... is it really neccesary/desirable to suppress negative */
+ /* events here? */
+ bool bNegativeEvent = IsNegativeEvent();
+ RemoveAllEvents();
+
+ if (bNegativeEvent) return false;
+
+ /* The rules: */
+ /* CONSTRAINT 1: not implemented */
+ /* CONSTRAINT 2: can camera see actor? */
+ /* CONSTRAINT 3: fixed height relative to floor below actor. */
+ /* CONSTRAINT 4: camera rotates behind actor */
+ /* CONSTRAINT 5: minimum / maximum distance */
+ /* CONSTRAINT 6: again: fixed height relative to floor below actor */
+ /* CONSTRAINT 7: track to floor below actor */
+ /* CONSTRAINT 8: look a little bit left or right, depending on how the
+
+ character is looking (horizontal x)
+ */
+
+ /* ...and then set the camera position. Since we assume the parent of */
+ /* this actuator is always a camera, just set the parent position and */
+ /* rotation. We do not check whether we really have a camera as parent. */
+ /* It may be better to turn this into a general tracking actuator later */
+ /* on, since lots of plausible relations can be filled in here. */
+
+ /* ... set up some parameters ... */
+ /* missing here: the 'floorloc' of the actor's shadow */
+
+ mindistsq= m_minHeight*m_minHeight;
+ maxdistsq= m_maxHeight*m_maxHeight;
+
+ /* C1: not checked... is a future option */
+
+ /* C2: blender test_visibility function. Can this be a ray-test? */
+
+ /* C3: fixed height */
+ from[2] = (15.0*from[2] + lookat[2] + m_height)/16.0;
+
+
+ /* C4: camera behind actor */
+ if (m_x) {
+ fp1[0] = actormat[0][0];
+ fp1[1] = actormat[1][0];
+ fp1[2] = actormat[2][0];
+
+ fp2[0] = frommat[0][0];
+ fp2[1] = frommat[1][0];
+ fp2[2] = frommat[2][0];
+ }
+ else {
+ fp1[0] = actormat[0][1];
+ fp1[1] = actormat[1][1];
+ fp1[2] = actormat[2][1];
+
+ fp2[0] = frommat[0][1];
+ fp2[1] = frommat[1][1];
+ fp2[2] = frommat[2][1];
+ }
+
+ inp= fp1[0]*fp2[0] + fp1[1]*fp2[1] + fp1[2]*fp2[2];
+ fac= (-1.0 + inp)/32.0;
+
+ from[0]+= fac*fp1[0];
+ from[1]+= fac*fp1[1];
+ from[2]+= fac*fp1[2];
+
+ /* alleen alstie ervoor ligt: cross testen en loodrechte bijtellen */
+ if(inp<0.0) {
+ if(fp1[0]*fp2[1] - fp1[1]*fp2[0] > 0.0) {
+ from[0]-= fac*fp1[1];
+ from[1]+= fac*fp1[0];
+ }
+ else {
+ from[0]+= fac*fp1[1];
+ from[1]-= fac*fp1[0];
+ }
+ }
+
+ /* CONSTRAINT 5: minimum / maximum afstand */
+
+ rc[0]= (lookat[0]-from[0]);
+ rc[1]= (lookat[1]-from[1]);
+ rc[2]= (lookat[2]-from[2]);
+ distsq= rc[0]*rc[0] + rc[1]*rc[1] + rc[2]*rc[2];
+
+ if(distsq > maxdistsq) {
+ distsq = 0.15*(distsq-maxdistsq)/distsq;
+
+ from[0] += distsq*rc[0];
+ from[1] += distsq*rc[1];
+ from[2] += distsq*rc[2];
+ }
+ else if(distsq < mindistsq) {
+ distsq = 0.15*(mindistsq-distsq)/mindistsq;
+
+ from[0] -= distsq*rc[0];
+ from[1] -= distsq*rc[1];
+ from[2] -= distsq*rc[2];
+ }
+
+
+ /* CONSTRAINT 7: track to schaduw */
+ rc[0]= (lookat[0]-from[0]);
+ rc[1]= (lookat[1]-from[1]);
+ rc[2]= (lookat[2]-from[2]);
+ VecUpMat3(rc, mat, 3); /* y up Track -z */
+
+
+
+
+ /* now set the camera position and rotation */
+
+ obj->NodeSetLocalPosition(from);
+
+ actormat[0][0]= mat[0][0]; actormat[0][1]= mat[1][0]; actormat[0][2]= mat[2][0];
+ actormat[1][0]= mat[0][1]; actormat[1][1]= mat[1][1]; actormat[1][2]= mat[2][1];
+ actormat[2][0]= mat[0][2]; actormat[2][1]= mat[1][2]; actormat[2][2]= mat[2][2];
+ obj->NodeSetLocalOrientation(actormat);
+
+ return result;
+}
+
+CValue *KX_CameraActuator::findObject(char *obName)
+{
+ /* hook to object system */
+ return NULL;
+}
+
+bool KX_CameraActuator::string2axischoice(const char *axisString)
+{
+ bool res = true;
+
+ res = !(axisString == Y_AXIS_STRING);
+
+ return res;
+}
+
+/* ------------------------------------------------------------------------- */
+/* Python functions */
+/* ------------------------------------------------------------------------- */
+
+/* Integration hooks ------------------------------------------------------- */
+PyTypeObject KX_CameraActuator::Type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0,
+ "KX_CameraActuator",
+ sizeof(KX_CameraActuator),
+ 0,
+ PyDestructor,
+ 0,
+ __getattr,
+ __setattr,
+ 0, //&MyPyCompare,
+ __repr,
+ 0, //&cvalue_as_number,
+ 0,
+ 0,
+ 0,
+ 0
+};
+
+PyParentObject KX_CameraActuator::Parents[] = {
+ &KX_CameraActuator::Type,
+ &SCA_IActuator::Type,
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
+};
+
+PyMethodDef KX_CameraActuator::Methods[] = {
+ {NULL,NULL,NULL,NULL} //Sentinel
+};
+
+PyObject* KX_CameraActuator::_getattr(char* attr) {
+ _getattr_up(SCA_IActuator);
+}
+
+
+/* eof */
diff --git a/source/gameengine/Ketsji/KX_CameraActuator.h b/source/gameengine/Ketsji/KX_CameraActuator.h
new file mode 100644
index 00000000000..1d819864cff
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_CameraActuator.h
@@ -0,0 +1,128 @@
+/**
+ * KX_CameraActuator.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 __KX_CAMERAACTUATOR
+#define __KX_CAMERAACTUATOR
+
+#include "SCA_IActuator.h"
+#include "MT_Scalar.h"
+
+
+/**
+ * The camera actuator does a Robbie Muller prespective for you. This is a
+ * weird set of rules that positions the camera sort of behind the object,
+ * tracking, while avoiding any objects between the 'ideal' position and the
+ * actor being tracked.
+ */
+
+
+class KX_CameraActuator : public SCA_IActuator
+{
+
+private :
+ Py_Header;
+
+ /** Object that will be tracked. */
+ const CValue *m_ob;
+
+ /** height (float), */
+ const MT_Scalar m_height;
+
+ /** min (float), */
+ const MT_Scalar m_minHeight;
+
+ /** max (float), */
+ const MT_Scalar m_maxHeight;
+
+ /** xy toggle (pick one): true == x, false == y */
+ bool m_x;
+
+ /* get the KX_IGameObject with this name */
+ CValue *findObject(char *obName);
+
+ /* parse x or y to a toggle pick */
+ bool string2axischoice(const char *axisString);
+
+ public:
+ static STR_String X_AXIS_STRING;
+ static STR_String Y_AXIS_STRING;
+
+ /**
+ * Set the bool toggle to true to use x lock, false for y lock
+ */
+ KX_CameraActuator(
+
+ SCA_IObject *gameobj,
+ const CValue *ob,
+ MT_Scalar hght,
+ MT_Scalar minhght,
+ MT_Scalar maxhght,
+ bool xytog,
+ PyTypeObject* T=&Type
+
+ );
+
+
+ ~KX_CameraActuator();
+
+
+
+ /** Methods Inherited from CValue */
+
+
+ CValue* GetReplica();
+
+
+ /** Methods inherited from SCA_IActuator */
+
+
+ bool Update(
+
+ double curtime,
+
+ double deltatime
+
+ );
+
+
+ /* --------------------------------------------------------------------- */
+ /* Python interface ---------------------------------------------------- */
+ /* --------------------------------------------------------------------- */
+
+ virtual PyObject* _getattr(char *attr);
+
+
+
+};
+#endif //__KX_CAMERAACTUATOR
diff --git a/source/gameengine/Ketsji/KX_CameraIpoSGController.cpp b/source/gameengine/Ketsji/KX_CameraIpoSGController.cpp
new file mode 100644
index 00000000000..2e736864a44
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_CameraIpoSGController.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 "KX_CameraIpoSGController.h"
+
+#include "KX_ScalarInterpolator.h"
+#include "KX_Camera.h"
+
+#include "RAS_CameraData.h"
+
+
+bool KX_CameraIpoSGController::Update(double currentTime)
+{
+ if (m_modified)
+ {
+ T_InterpolatorList::iterator i;
+ for (i = m_interpolators.begin(); !(i == m_interpolators.end()); ++i) {
+ (*i)->Execute(m_ipotime);
+ }
+
+ RAS_CameraData* camdata;
+
+ SG_Spatial* ob = (SG_Spatial*)m_pObject;
+ KX_Camera* kxcamera = (KX_Camera*) ob->GetSGClientObject();
+ camdata = kxcamera->GetCameraData();
+
+
+ if (m_modify_lens) {
+ camdata->m_lens = m_lens;
+ }
+
+ if (m_modify_clipstart ) {
+ camdata->m_clipstart = m_clipstart;
+ }
+
+ if (m_modify_clipend) {
+ camdata->m_clipend = m_clipend;
+ }
+
+ m_modified=false;
+ }
+ return false;
+}
+
+
+void KX_CameraIpoSGController::AddInterpolator(KX_IInterpolator* interp)
+{
+ this->m_interpolators.push_back(interp);
+}
+
+SG_Controller* KX_CameraIpoSGController::GetReplica(class SG_Node* destnode)
+{
+ KX_CameraIpoSGController* iporeplica = new KX_CameraIpoSGController(*this);
+ // clear object that ipo acts on
+ iporeplica->ClearObject();
+
+ // dirty hack, ask Gino for a better solution in the ipo implementation
+ // hacken en zagen, in what we call datahiding, not written for replication :(
+
+ T_InterpolatorList oldlist = m_interpolators;
+ iporeplica->m_interpolators.clear();
+
+ T_InterpolatorList::iterator i;
+ for (i = oldlist.begin(); !(i == oldlist.end()); ++i) {
+ KX_ScalarInterpolator* copyipo = new KX_ScalarInterpolator(*((KX_ScalarInterpolator*)*i));
+ iporeplica->AddInterpolator(copyipo);
+
+ MT_Scalar* scaal = ((KX_ScalarInterpolator*)*i)->GetTarget();
+ int orgbase = (int)this;
+ int orgloc = (int)scaal;
+ int offset = orgloc-orgbase;
+ int newaddrbase = (int)iporeplica + offset;
+ MT_Scalar* blaptr = (MT_Scalar*) newaddrbase;
+ copyipo->SetNewTarget((MT_Scalar*)blaptr);
+ }
+
+ return iporeplica;
+}
+
+KX_CameraIpoSGController::~KX_CameraIpoSGController()
+{
+
+ T_InterpolatorList::iterator i;
+ for (i = m_interpolators.begin(); !(i == m_interpolators.end()); ++i) {
+ delete (*i);
+ }
+
+}
+
+ void
+KX_CameraIpoSGController::SetOption(
+ int option,
+ int value)
+{
+ /* Setting options */
+
+}
diff --git a/source/gameengine/Ketsji/KX_CameraIpoSGController.h b/source/gameengine/Ketsji/KX_CameraIpoSGController.h
new file mode 100644
index 00000000000..3ebbcc343d4
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_CameraIpoSGController.h
@@ -0,0 +1,91 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 KX_CAMERAIPOSGCONTROLLER_H
+#define KX_CAMERAIPOSGCONTROLLER_H
+
+#include "SG_Controller.h"
+#include "SG_Spatial.h"
+
+#include "KX_IInterpolator.h"
+
+struct RAS_CameraData;
+
+class KX_CameraIpoSGController : public SG_Controller
+{
+public:
+ MT_Scalar m_lens;
+ MT_Scalar m_clipstart;
+ MT_Scalar m_clipend;
+
+private:
+ T_InterpolatorList m_interpolators;
+ unsigned short m_modify_lens : 1;
+ unsigned short m_modify_clipstart : 1;
+ unsigned short m_modify_clipend : 1;
+ bool m_modified;
+
+ double m_ipotime;
+public:
+ KX_CameraIpoSGController() : m_ipotime(0.0),
+ m_modify_lens(false),
+ m_modify_clipstart(false),
+ m_modify_clipend(false),
+ m_modified(true)
+ {}
+
+ ~KX_CameraIpoSGController();
+ SG_Controller* GetReplica(class SG_Node* destnode);
+ bool Update(double time);
+
+ void
+ SetOption(
+ int option,
+ int value
+ );
+
+ void SetSimulatedTime(double time) {
+ m_ipotime = time;
+ m_modified = true;
+ }
+ void SetModifyLens(bool modify) {
+ m_modify_lens = modify;
+ }
+ void SetModifyClipEnd(bool modify) {
+ m_modify_clipend = modify;
+ }
+ void SetModifyClipStart(bool modify) {
+ m_modify_clipstart = modify;
+ }
+ void AddInterpolator(KX_IInterpolator* interp);
+};
+
+#endif // KX_CAMERAIPOSGCONTROLLER_H
diff --git a/source/gameengine/Ketsji/KX_ClientObjectInfo.h b/source/gameengine/Ketsji/KX_ClientObjectInfo.h
new file mode 100644
index 00000000000..8aec115e44d
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_ClientObjectInfo.h
@@ -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 *****
+ */
+#ifndef __KX_CLIENTOBJECT_INFO_H
+#define __KX_CLIENTOBJECT_INFO_H
+
+/**
+ * Client Type and Additional Info. This structure can be use instead of a bare void* pointer, for safeness, and additional info for callbacks
+ */
+
+struct KX_ClientObjectInfo
+{
+ int m_type;
+ void* m_clientobject;
+ void* m_auxilary_info;
+};
+
+#endif //__KX_CLIENTOBJECT_INFO_H
diff --git a/source/gameengine/Ketsji/KX_ConstraintActuator.cpp b/source/gameengine/Ketsji/KX_ConstraintActuator.cpp
new file mode 100644
index 00000000000..8aab3e7648d
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_ConstraintActuator.cpp
@@ -0,0 +1,369 @@
+/**
+ * Apply a constraint to a position or rotation value
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "SCA_IActuator.h"
+#include "KX_ConstraintActuator.h"
+#include "SCA_IObject.h"
+#include "MT_Point3.h"
+#include "MT_Matrix3x3.h"
+#include "KX_GameObject.h"
+/* ------------------------------------------------------------------------- */
+/* Native functions */
+/* ------------------------------------------------------------------------- */
+
+KX_ConstraintActuator::KX_ConstraintActuator(SCA_IObject *gameobj,
+ int dampTime,
+ float minBound,
+ float maxBound,
+ int locrotxyz,
+ PyTypeObject* T)
+ : SCA_IActuator(gameobj, T)
+{
+ m_dampTime = dampTime;
+ m_locrot = locrotxyz;
+ /* The units of bounds are determined by the type of constraint. To */
+ /* make the constraint application easier and more transparent later on, */
+ /* I think converting the bounds to the applicable domain makes more */
+ /* sense. */
+ switch (m_locrot) {
+ case KX_ACT_CONSTRAINT_LOCX:
+ case KX_ACT_CONSTRAINT_LOCY:
+ case KX_ACT_CONSTRAINT_LOCZ:
+ m_minimumBound = minBound;
+ m_maximumBound = maxBound;
+ break;
+ case KX_ACT_CONSTRAINT_ROTX:
+ case KX_ACT_CONSTRAINT_ROTY:
+ case KX_ACT_CONSTRAINT_ROTZ:
+ /* The user interface asks for degrees, we are radian. */
+ m_minimumBound = MT_radians(minBound);
+ m_maximumBound = MT_radians(maxBound);
+ break;
+ default:
+ ; /* error */
+ }
+
+} /* End of constructor */
+
+KX_ConstraintActuator::~KX_ConstraintActuator()
+{
+ // there's nothing to be done here, really....
+} /* end of destructor */
+
+bool KX_ConstraintActuator::Update(double curtime,double deltatime)
+{
+
+ bool result = false;
+ bool bNegativeEvent = IsNegativeEvent();
+ RemoveAllEvents();
+
+ if (bNegativeEvent)
+ return false; // do nothing on negative events
+
+ /* Constraint clamps the values to the specified range, with a sort of */
+ /* low-pass filtered time response, if the damp time is unequal to 0. */
+
+ /* Having to retrieve location/rotation and setting it afterwards may not */
+ /* be efficient enough... Somthing to look at later. */
+ KX_GameObject *parent = (KX_GameObject*) GetParent();
+ MT_Point3 position = parent->NodeGetWorldPosition();
+ MT_Matrix3x3 rotation = parent->NodeGetWorldOrientation();
+// MT_Vector3 eulerrot = rotation.getEuler();
+
+ switch (m_locrot) {
+ case KX_ACT_CONSTRAINT_LOCX:
+ Clamp(position[0], m_minimumBound, m_maximumBound);
+ break;
+ case KX_ACT_CONSTRAINT_LOCY:
+ Clamp(position[1], m_minimumBound, m_maximumBound);
+ break;
+ case KX_ACT_CONSTRAINT_LOCZ:
+ Clamp(position[2], m_minimumBound, m_maximumBound);
+ break;
+
+// case KX_ACT_CONSTRAINT_ROTX:
+// /* The angles are Euler angles (I think that's what they are called) */
+// /* but we need to convert from/to the MT_Matrix3x3. */
+// Clamp(eulerrot[0], m_minimumBound, m_maximumBound);
+// break;
+// case KX_ACT_CONSTRAINT_ROTY:
+// Clamp(eulerrot[1], m_minimumBound, m_maximumBound);
+// break;
+// case KX_ACT_CONSTRAINT_ROTZ:
+// Clamp(eulerrot[2], m_minimumBound, m_maximumBound);
+// break;
+// default:
+// ; /* error */
+ }
+
+ /* Will be replaced by a filtered clamp. */
+
+
+ switch (m_locrot) {
+ case KX_ACT_CONSTRAINT_LOCX:
+ case KX_ACT_CONSTRAINT_LOCY:
+ case KX_ACT_CONSTRAINT_LOCZ:
+ parent->NodeSetLocalPosition(position);
+ break;
+
+
+// case KX_ACT_CONSTRAINT_ROTX:
+// case KX_ACT_CONSTRAINT_ROTY:
+// case KX_ACT_CONSTRAINT_ROTZ:
+// rotation.setEuler(eulerrot);
+// parent->NodeSetLocalOrientation(rotation);
+ break;
+
+ default:
+ ; /* error */
+ }
+
+ return false;
+} /* end of KX_ConstraintActuator::Update(double curtime,double deltatime) */
+
+void KX_ConstraintActuator::Clamp(MT_Scalar &var,
+ float min,
+ float max) {
+ if (var < min) {
+ var = min;
+ } else if (var > max) {
+ var = max;
+ }
+}
+
+
+bool KX_ConstraintActuator::IsValidMode(KX_ConstraintActuator::KX_CONSTRAINTTYPE m)
+{
+ bool res = false;
+
+ if ( (m > KX_ACT_CONSTRAINT_NODEF) && (m < KX_ACT_CONSTRAINT_MAX)) {
+ res = true;
+ }
+
+ return res;
+}
+
+/* ------------------------------------------------------------------------- */
+/* Python functions */
+/* ------------------------------------------------------------------------- */
+
+/* Integration hooks ------------------------------------------------------- */
+PyTypeObject KX_ConstraintActuator::Type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0,
+ "KX_ConstraintActuator",
+ sizeof(KX_ConstraintActuator),
+ 0,
+ PyDestructor,
+ 0,
+ __getattr,
+ __setattr,
+ 0, //&MyPyCompare,
+ __repr,
+ 0, //&cvalue_as_number,
+ 0,
+ 0,
+ 0,
+ 0
+};
+
+PyParentObject KX_ConstraintActuator::Parents[] = {
+ &KX_ConstraintActuator::Type,
+ &SCA_IActuator::Type,
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
+};
+
+PyMethodDef KX_ConstraintActuator::Methods[] = {
+ {"setDamp", (PyCFunction) KX_ConstraintActuator::sPySetDamp, METH_VARARGS, SetDamp_doc},
+ {"getDamp", (PyCFunction) KX_ConstraintActuator::sPyGetDamp, METH_VARARGS, GetDamp_doc},
+ {"setMin", (PyCFunction) KX_ConstraintActuator::sPySetMin, METH_VARARGS, SetMin_doc},
+ {"getMin", (PyCFunction) KX_ConstraintActuator::sPyGetMin, METH_VARARGS, GetMin_doc},
+ {"setMax", (PyCFunction) KX_ConstraintActuator::sPySetMax, METH_VARARGS, SetMax_doc},
+ {"getMax", (PyCFunction) KX_ConstraintActuator::sPyGetMax, METH_VARARGS, GetMax_doc},
+ {"setLimit", (PyCFunction) KX_ConstraintActuator::sPySetLimit, METH_VARARGS, SetLimit_doc},
+ {"getLimit", (PyCFunction) KX_ConstraintActuator::sPyGetLimit, METH_VARARGS, GetLimit_doc},
+ {NULL,NULL} //Sentinel
+};
+
+PyObject* KX_ConstraintActuator::_getattr(char* attr) {
+ _getattr_up(SCA_IActuator);
+}
+
+/* 2. setDamp */
+char KX_ConstraintActuator::SetDamp_doc[] =
+"setDamp(duration)\n"
+"\t- duration: integer\n"
+"\tSets the time with which the constraint application is delayed.\n"
+"\tIf the duration is negative, it is set to 0.\n";
+PyObject* KX_ConstraintActuator::PySetDamp(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ int dampArg;
+ if(!PyArg_ParseTuple(args, "i", &dampArg)) {
+ return NULL;
+ }
+
+ m_dampTime = dampArg;
+ if (m_dampTime < 0) m_dampTime = 0;
+
+ Py_Return;
+}
+/* 3. getDamp */
+char KX_ConstraintActuator::GetDamp_doc[] =
+"GetDamp()\n"
+"\tReturns the damping time for application of the constraint.\n";
+PyObject* KX_ConstraintActuator::PyGetDamp(PyObject* self,
+ PyObject* args,
+ PyObject* kwds){
+ return PyInt_FromLong(m_dampTime);
+}
+
+/* 4. setMin */
+char KX_ConstraintActuator::SetMin_doc[] =
+"setMin(lower_bound)\n"
+"\t- lower_bound: float\n"
+"\tSets the lower value of the interval to which the value\n"
+"\tis clipped.\n";
+PyObject* KX_ConstraintActuator::PySetMin(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ float minArg;
+ if(!PyArg_ParseTuple(args, "f", &minArg)) {
+ return NULL;
+ }
+
+ switch (m_locrot) {
+ case KX_ACT_CONSTRAINT_LOCX:
+ case KX_ACT_CONSTRAINT_LOCY:
+ case KX_ACT_CONSTRAINT_LOCZ:
+ m_minimumBound = minArg;
+ break;
+ case KX_ACT_CONSTRAINT_ROTX:
+ case KX_ACT_CONSTRAINT_ROTY:
+ case KX_ACT_CONSTRAINT_ROTZ:
+ m_minimumBound = MT_radians(minArg);
+ break;
+ default:
+ ; /* error */
+ }
+
+ Py_Return;
+}
+/* 5. getMin */
+char KX_ConstraintActuator::GetMin_doc[] =
+"getMin()\n"
+"\tReturns the lower value of the interval to which the value\n"
+"\tis clipped.\n";
+PyObject* KX_ConstraintActuator::PyGetMin(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ return PyFloat_FromDouble(m_minimumBound);
+}
+
+/* 6. setMax */
+char KX_ConstraintActuator::SetMax_doc[] =
+"setMax(upper_bound)\n"
+"\t- upper_bound: float\n"
+"\tSets the upper value of the interval to which the value\n"
+"\tis clipped.\n";
+PyObject* KX_ConstraintActuator::PySetMax(PyObject* self,
+ PyObject* args,
+ PyObject* kwds){
+ float maxArg;
+ if(!PyArg_ParseTuple(args, "f", &maxArg)) {
+ return NULL;
+ }
+
+ switch (m_locrot) {
+ case KX_ACT_CONSTRAINT_LOCX:
+ case KX_ACT_CONSTRAINT_LOCY:
+ case KX_ACT_CONSTRAINT_LOCZ:
+ m_maximumBound = maxArg;
+ break;
+ case KX_ACT_CONSTRAINT_ROTX:
+ case KX_ACT_CONSTRAINT_ROTY:
+ case KX_ACT_CONSTRAINT_ROTZ:
+ m_maximumBound = MT_radians(maxArg);
+ break;
+ default:
+ ; /* error */
+ }
+
+ Py_Return;
+}
+/* 7. getMax */
+char KX_ConstraintActuator::GetMax_doc[] =
+"getMax()\n"
+"\tReturns the upper value of the interval to which the value\n"
+"\tis clipped.\n";
+PyObject* KX_ConstraintActuator::PyGetMax(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ return PyFloat_FromDouble(m_maximumBound);
+}
+
+
+/* This setter/getter probably for the constraint type */
+/* 8. setLimit */
+char KX_ConstraintActuator::SetLimit_doc[] =
+"setLimit(type)\n"
+"\t- type: KX_CONSTRAINTACT_LOCX, KX_CONSTRAINTACT_LOCY,\n"
+"\t KX_CONSTRAINTACT_LOCZ, KX_CONSTRAINTACT_ROTX,\n"
+"\t KX_CONSTRAINTACT_ROTY, or KX_CONSTRAINTACT_ROTZ.\n"
+"\tSets the type of constraint.\n";
+PyObject* KX_ConstraintActuator::PySetLimit(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ int locrotArg;
+ if(!PyArg_ParseTuple(args, "i", &locrotArg)) {
+ return NULL;
+ }
+
+ if (IsValidMode((KX_CONSTRAINTTYPE)locrotArg)) m_locrot = locrotArg;
+
+ Py_Return;
+}
+/* 9. getLimit */
+char KX_ConstraintActuator::GetLimit_doc[] =
+"getLimit(type)\n"
+"\tReturns the type of constraint.\n";
+PyObject* KX_ConstraintActuator::PyGetLimit(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ return PyInt_FromLong(m_locrot);
+}
+
+/* eof */
diff --git a/source/gameengine/Ketsji/KX_ConstraintActuator.h b/source/gameengine/Ketsji/KX_ConstraintActuator.h
new file mode 100644
index 00000000000..247e7ea55f9
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_ConstraintActuator.h
@@ -0,0 +1,109 @@
+/**
+ * KX_ConstraintActuator.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 __KX_CONSTRAINTACTUATOR
+#define __KX_CONSTRAINTACTUATOR
+
+#include "SCA_IActuator.h"
+#include "MT_Scalar.h"
+
+
+class KX_ConstraintActuator : public SCA_IActuator
+{
+ Py_Header;
+
+ // Damp time (int),
+ int m_dampTime;
+ // min (float),
+ float m_minimumBound;
+ // max (float),
+ float m_maximumBound;
+ // locrotxyz choice (pick one): only one choice allowed at a time!
+ int m_locrot;
+
+ /**
+ * Clamp <var> to <min>, <max>. Borders are included (in as far as
+ * float comparisons are good for equality...).
+ */
+ void Clamp(MT_Scalar &var, float min, float max);
+
+
+ public:
+ enum KX_CONSTRAINTTYPE {
+ KX_ACT_CONSTRAINT_NODEF = 0,
+ KX_ACT_CONSTRAINT_LOCX,
+ KX_ACT_CONSTRAINT_LOCY,
+ KX_ACT_CONSTRAINT_LOCZ,
+ KX_ACT_CONSTRAINT_ROTX,
+ KX_ACT_CONSTRAINT_ROTY,
+ KX_ACT_CONSTRAINT_ROTZ,
+ KX_ACT_CONSTRAINT_MAX
+ };
+
+ bool IsValidMode(KX_CONSTRAINTTYPE m);
+
+ KX_ConstraintActuator(SCA_IObject* gameobj,
+ int damptime,
+ float min,
+ float max,
+ int locrot,
+ PyTypeObject* T=&Type);
+ virtual ~KX_ConstraintActuator();
+ virtual CValue* GetReplica() {
+ KX_ConstraintActuator* replica = new KX_ConstraintActuator(*this);
+ replica->ProcessReplica();
+ // this will copy properties and so on...
+ CValue::AddDataToReplica(replica);
+ return replica;
+ };
+
+ virtual bool Update(double curtime,double deltatime);
+
+ /* --------------------------------------------------------------------- */
+ /* Python interface ---------------------------------------------------- */
+ /* --------------------------------------------------------------------- */
+
+ virtual PyObject* _getattr(char *attr);
+
+ KX_PYMETHOD_DOC(KX_ConstraintActuator,SetDamp);
+ KX_PYMETHOD_DOC(KX_ConstraintActuator,GetDamp);
+ KX_PYMETHOD_DOC(KX_ConstraintActuator,SetMin);
+ KX_PYMETHOD_DOC(KX_ConstraintActuator,GetMin);
+ KX_PYMETHOD_DOC(KX_ConstraintActuator,SetMax);
+ KX_PYMETHOD_DOC(KX_ConstraintActuator,GetMax);
+ KX_PYMETHOD_DOC(KX_ConstraintActuator,SetLimit);
+ KX_PYMETHOD_DOC(KX_ConstraintActuator,GetLimit);
+
+};
+#endif //__KX_CONSTRAINTACTUATOR
diff --git a/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp b/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp
new file mode 100644
index 00000000000..0a741aa55ac
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp
@@ -0,0 +1,131 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 <Python.h>
+
+#include "KX_ConstraintWrapper.h"
+#include "PHY_IPhysicsEnvironment.h"
+
+KX_ConstraintWrapper::KX_ConstraintWrapper(
+ PHY_ConstraintType ctype,
+ int constraintId,
+ PHY_IPhysicsEnvironment* physenv,PyTypeObject *T)
+: m_constraintType(ctype),m_constraintId(constraintId),m_physenv(physenv),PyObjectPlus(T)
+{
+}
+KX_ConstraintWrapper::~KX_ConstraintWrapper()
+{
+}
+//python integration methods
+PyObject* KX_ConstraintWrapper::PyTestMethod(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+PyObject* KX_ConstraintWrapper::PyGetConstraintId(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ return PyInt_FromLong(m_constraintId);
+}
+
+
+
+
+//python specific stuff
+PyTypeObject KX_ConstraintWrapper::Type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0,
+ "KX_ConstraintWrapper",
+ sizeof(KX_ConstraintWrapper),
+ 0,
+ PyDestructor,
+ 0,
+ __getattr,
+ __setattr,
+ 0, //&MyPyCompare,
+ __repr,
+ 0, //&cvalue_as_number,
+ 0,
+ 0,
+ 0,
+ 0
+};
+
+PyParentObject KX_ConstraintWrapper::Parents[] = {
+ &KX_ConstraintWrapper::Type,
+ NULL
+};
+
+PyObject* KX_ConstraintWrapper::_getattr(char* attr)
+{
+ //here you can search for existing data members (like mass,friction etc.)
+ _getattr_up(PyObjectPlus);
+}
+
+int KX_ConstraintWrapper::_setattr(char* attr,PyObject* pyobj)
+{
+
+ PyTypeObject* type = pyobj->ob_type;
+ int result = 1;
+
+ if (type == &PyList_Type)
+ {
+ result = 0;
+ }
+ if (type == &PyFloat_Type)
+ {
+ result = 0;
+
+ }
+ if (type == &PyInt_Type)
+ {
+ result = 0;
+ }
+ if (type == &PyString_Type)
+ {
+ result = 0;
+ }
+ if (result)
+ result = PyObjectPlus::_setattr(attr,pyobj);
+ return result;
+};
+
+
+PyMethodDef KX_ConstraintWrapper::Methods[] = {
+ {"testMethod",(PyCFunction) KX_ConstraintWrapper::sPyTestMethod, METH_VARARGS},
+ {"getConstraintId",(PyCFunction) KX_ConstraintWrapper::sPyGetConstraintId, METH_VARARGS},
+ {NULL,NULL} //Sentinel
+};
diff --git a/source/gameengine/Ketsji/KX_ConstraintWrapper.h b/source/gameengine/Ketsji/KX_ConstraintWrapper.h
new file mode 100644
index 00000000000..3211a74192f
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_ConstraintWrapper.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 *****
+ */
+#ifndef KX_CONSTRAINT_WRAPPER
+#define KX_CONSTRAINT_WRAPPER
+
+#include "Value.h"
+#include "PHY_DynamicTypes.h"
+
+class KX_ConstraintWrapper : public PyObjectPlus
+{
+ Py_Header;
+ PyObject* _getattr(char* attr);
+ virtual int _setattr(char *attr, PyObject *value);
+public:
+ KX_ConstraintWrapper(PHY_ConstraintType ctype,int constraintId,class PHY_IPhysicsEnvironment* physenv,PyTypeObject *T = &Type);
+ virtual ~KX_ConstraintWrapper ();
+ int getConstraintId() { return m_constraintId;};
+
+ KX_PYMETHOD(KX_ConstraintWrapper,TestMethod);
+ KX_PYMETHOD(KX_ConstraintWrapper,GetConstraintId);
+
+private:
+ int m_constraintId;
+ PHY_ConstraintType m_constraintType;
+ PHY_IPhysicsEnvironment* m_physenv;
+};
+
+#endif //KX_CONSTRAINT_WRAPPER
diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h b/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h
new file mode 100644
index 00000000000..f74349a3e1a
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h
@@ -0,0 +1,110 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 KX_CONVERTPHYSICSOBJECTS
+#define KX_CONVERTPHYSICSOBJECTS
+
+
+
+
+//#define USE_SUMO_SOLID
+//solid is not available yet
+
+//#define USE_ODE
+//ode is not available yet
+
+
+class RAS_MeshObject;
+class KX_Scene;
+
+
+struct KX_Bounds
+{
+ float m_center[3];
+ float m_extends[3];
+};
+
+struct KX_ObjectProperties
+{
+ bool m_dyna;
+ double m_radius;
+ bool m_angular_rigidbody;
+ bool m_in_active_layer;
+ bool m_ghost;
+ class KX_GameObject* m_dynamic_parent;
+ bool m_isactor;
+ bool m_concave;
+ bool m_isdeformable;
+ bool m_implicitsphere ;
+ bool m_implicitbox;
+ KX_Bounds m_boundingbox;
+};
+
+#ifdef USE_ODE
+
+
+void KX_ConvertODEEngineObject(KX_GameObject* gameobj,
+ RAS_MeshObject* meshobj,
+ KX_Scene* kxscene,
+ struct PHY_ShapeProps* shapeprops,
+ struct PHY_MaterialProps* smmaterial,
+ struct KX_ObjectProperties* objprop);
+
+
+#endif //USE_ODE
+
+
+void KX_ConvertDynamoObject(KX_GameObject* gameobj,
+ RAS_MeshObject* meshobj,
+ KX_Scene* kxscene,
+ struct PHY_ShapeProps* shapeprops,
+ struct PHY_MaterialProps* smmaterial,
+ struct KX_ObjectProperties* objprop);
+
+
+
+#ifdef USE_SUMO_SOLID
+
+
+
+
+
+void KX_ConvertSumoObject( class KX_GameObject* gameobj,
+ class RAS_MeshObject* meshobj,
+ class KX_Scene* kxscene,
+ struct PHY_ShapeProps* shapeprops,
+ struct PHY_MaterialProps* smmaterial,
+ struct KX_ObjectProperties* objprop);
+#endif
+
+
+
+#endif //KX_CONVERTPHYSICSOBJECTS
diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp
new file mode 100644
index 00000000000..01d02b58132
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp
@@ -0,0 +1,427 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+#pragma warning (disable : 4786)
+
+#include "KX_ConvertPhysicsObject.h"
+#include "KX_GameObject.h"
+#include "RAS_MeshObject.h"
+#include "KX_Scene.h"
+#include "SYS_System.h"
+
+#include "PHY_Pro.h" //todo cleanup
+#include "KX_ClientObjectInfo.h"
+
+#include "GEN_Map.h"
+#include "GEN_HashedPtr.h"
+
+#include "KX_PhysicsEngineEnums.h"
+#include "PHY_Pro.h"
+
+#include "KX_MotionState.h" // bridge between motionstate and scenegraph node
+#ifdef USE_ODE
+
+#include "KX_OdePhysicsController.h"
+#include "odephysicsenvironment.h"
+#endif //USE_ODE
+
+
+// USE_SUMO_SOLID is defined in headerfile KX_ConvertPhysicsObjects.h
+#ifdef USE_SUMO_SOLID
+
+
+#include "SumoPhysicsEnvironment.h"
+#include "KX_SumoPhysicsController.h"
+
+
+// sumo physics specific
+#include "SM_Object.h"
+#include "SM_FhObject.h"
+#include "SM_Scene.h"
+#include "SM_ClientObjectInfo.h"
+
+#include "KX_SumoPhysicsController.h"
+
+GEN_Map<GEN_HashedPtr,DT_ShapeHandle> map_gamemesh_to_sumoshape;
+
+// forward declarations
+void BL_RegisterSumoObject(KX_GameObject* gameobj,class SM_Scene* sumoScene,DT_SceneHandle solidscene,class SM_Object* sumoObj,const char* matname,bool isDynamic,bool isActor);
+DT_ShapeHandle CreateShapeFromMesh(RAS_MeshObject* meshobj);
+
+
+void KX_ConvertSumoObject( class KX_GameObject* gameobj,
+ class RAS_MeshObject* meshobj,
+ class KX_Scene* kxscene,
+ PHY_ShapeProps* kxshapeprops,
+ PHY_MaterialProps* kxmaterial,
+ struct KX_ObjectProperties* objprop)
+
+
+{
+
+ SM_ShapeProps* smprop = new SM_ShapeProps;
+
+ smprop->m_ang_drag = kxshapeprops->m_ang_drag;
+ smprop->m_do_anisotropic = kxshapeprops->m_do_anisotropic;
+ smprop->m_do_fh = kxshapeprops->m_do_fh;
+ smprop->m_do_rot_fh = kxshapeprops->m_do_rot_fh ;
+ smprop->m_friction_scaling[0] = kxshapeprops->m_friction_scaling[0];
+ smprop->m_friction_scaling[1] = kxshapeprops->m_friction_scaling[1];
+ smprop->m_friction_scaling[2] = kxshapeprops->m_friction_scaling[2];
+ smprop->m_inertia = kxshapeprops->m_inertia;
+ smprop->m_lin_drag = kxshapeprops->m_lin_drag;
+ smprop->m_mass = kxshapeprops->m_mass;
+
+
+ SM_MaterialProps* smmaterial = new SM_MaterialProps;
+
+ smmaterial->m_fh_damping = kxmaterial->m_fh_damping;
+ smmaterial->m_fh_distance = kxmaterial->m_fh_distance;
+ smmaterial->m_fh_normal = kxmaterial->m_fh_normal;
+ smmaterial->m_fh_spring = kxmaterial->m_fh_spring;
+ smmaterial->m_friction = kxmaterial->m_friction;
+ smmaterial->m_restitution = kxmaterial->m_restitution;
+
+ class SumoPhysicsEnvironment* sumoEnv =
+ (SumoPhysicsEnvironment*)kxscene->GetPhysicsEnvironment();
+
+ SM_Scene* sceneptr = sumoEnv->GetSumoScene();
+
+
+
+ SM_Object* sumoObj=NULL;
+
+ if (objprop->m_dyna)
+ {
+
+ DT_ShapeHandle shape = DT_Sphere(0.0);
+
+ if (objprop->m_ghost)
+ {
+
+ sumoObj = new SM_Object(shape,NULL,smprop,NULL);
+ } else
+ {
+ sumoObj = new SM_Object(shape,smmaterial,smprop,NULL);
+ }
+
+ double radius = objprop->m_radius;
+
+ MT_Scalar margin = radius;//0.5;
+ sumoObj->setMargin(margin);
+
+ //if (bRigidBody)
+ //{
+ if (objprop->m_in_active_layer)
+ {
+ DT_AddObject(sumoEnv->GetSolidScene(),
+ sumoObj->getObjectHandle());
+ }
+ //}
+
+ if (objprop->m_angular_rigidbody)
+ {
+ sumoObj->setRigidBody(true);
+ } else
+ {
+ sumoObj->setRigidBody(false);
+ }
+
+ bool isDynamic = true;
+ bool isActor = true;
+
+ BL_RegisterSumoObject(gameobj,sceneptr,sumoEnv->GetSolidScene(),sumoObj,NULL,isDynamic,isActor);
+
+ }
+ else {
+ // non physics object
+ if (meshobj)
+ {
+ int numpolys = meshobj->NumPolygons();
+
+ {
+
+ DT_ShapeHandle complexshape=0;
+
+ if (objprop->m_implicitbox)
+ {
+ complexshape = DT_Box(objprop->m_boundingbox.m_extends[0],objprop->m_boundingbox.m_extends[1],objprop->m_boundingbox.m_extends[2]);
+ } else
+ {
+ if (numpolys>0)
+ {
+ complexshape = CreateShapeFromMesh(meshobj);
+ }
+ }
+
+ if (complexshape)
+ {
+ SM_Object *dynamicParent = NULL;
+
+ if (objprop->m_dynamic_parent)
+ {
+ // problem is how to find the dynamic parent
+ // in the scenegraph
+ KX_SumoPhysicsController* sumoctrl =
+ (KX_SumoPhysicsController*)
+ objprop->m_dynamic_parent->GetPhysicsController();
+
+ if (sumoctrl)
+ {
+ dynamicParent = sumoctrl->GetSumoObject();
+ }
+
+ assert(dynamicParent);
+ }
+
+
+ if (objprop->m_ghost)
+ {
+ sumoObj = new SM_Object(complexshape,NULL,NULL, dynamicParent);
+ } else
+ {
+ sumoObj = new SM_Object(complexshape,smmaterial,NULL, dynamicParent);
+ }
+
+ if (objprop->m_in_active_layer)
+ {
+ DT_AddObject(sumoEnv->GetSolidScene(),
+ sumoObj->getObjectHandle());
+ }
+
+
+ const STR_String& matname=meshobj->GetMaterialName(0);
+
+
+ BL_RegisterSumoObject(gameobj,sceneptr,
+ sumoEnv->GetSolidScene(),sumoObj,
+ matname.ReadPtr(),
+ objprop->m_dyna,
+ objprop->m_isactor);
+
+ }
+ }
+ }
+ }
+
+ // physics object get updated here !
+
+
+ // lazy evaluation because Havok doesn't support scaling !gameobj->UpdateTransform();
+
+ if (objprop->m_in_active_layer && sumoObj)
+ {
+ sceneptr->add(*sumoObj);
+ }
+
+}
+
+
+
+void BL_RegisterSumoObject(KX_GameObject* gameobj,class SM_Scene* sumoScene,DT_SceneHandle solidscene,class SM_Object* sumoObj,const char* matname,bool isDynamic,bool isActor) {
+
+
+
+ //gameobj->SetDynamic(isDynamic);
+
+ PHY_IMotionState* motionstate = new KX_MotionState(gameobj->GetSGNode());
+
+ // need easy access, not via 'node' etc.
+ KX_SumoPhysicsController* physicscontroller = new KX_SumoPhysicsController(sumoScene,solidscene,sumoObj,motionstate,isDynamic);
+ gameobj->SetPhysicsController(physicscontroller);
+ physicscontroller->setClientInfo(gameobj);
+
+ gameobj->GetSGNode()->AddSGController(physicscontroller);
+
+ //gameobj->GetClientInfo()->m_type = (isActor ? 1 : 0);
+ //gameobj->GetClientInfo()->m_clientobject = gameobj;
+
+ // store materialname in auxinfo, needed for touchsensors
+ //gameobj->GetClientInfo()->m_auxilary_info = (matname? (void*)(matname+2) : NULL);
+
+ physicscontroller->SetObject(gameobj->GetSGNode());
+
+ //gameobj->SetDynamicsScaling(MT_Vector3(1.0, 1.0, 1.0));
+
+};
+
+
+
+DT_ShapeHandle CreateShapeFromMesh(RAS_MeshObject* meshobj)
+{
+
+ DT_ShapeHandle* shapeptr = map_gamemesh_to_sumoshape[GEN_HashedPtr(meshobj)];
+ if (shapeptr)
+ {
+ return *shapeptr;
+ }
+
+ // todo: shared meshes
+ DT_ShapeHandle shape = DT_NewComplexShape();
+ int p=0;
+ int numpolys = meshobj->NumPolygons();
+ if (!numpolys)
+ {
+ return NULL;
+ }
+ int numvalidpolys = 0;
+
+
+
+ for (p=0;p<meshobj->m_triangle_indices.size();p++)
+ {
+ RAS_TriangleIndex& idx = meshobj->m_triangle_indices[p];
+
+ // only add polygons that have the collisionflag set
+ if (idx.m_collider)
+ {
+ DT_Begin();
+ for (int v=0;v<3;v++)
+ {
+ int num = meshobj->m_xyz_index_to_vertex_index_mapping[idx.m_index[v]].size();
+ if (num != 1)
+ {
+ int i=0;
+ }
+ RAS_MatArrayIndex& vertindex = meshobj->m_xyz_index_to_vertex_index_mapping[idx.m_index[v]][0];
+
+ numvalidpolys++;
+
+ {
+ const MT_Point3& pt = meshobj->GetVertex(vertindex.m_array,
+ vertindex.m_index,
+ (RAS_IPolyMaterial*)vertindex.m_matid)->xyz();
+ DT_Vertex(pt[0],pt[1],pt[2]);
+ }
+ }
+ DT_End();
+ }
+ }
+
+ DT_EndComplexShape();
+
+ if (numvalidpolys > 0)
+ {
+ map_gamemesh_to_sumoshape.insert(GEN_HashedPtr(meshobj),shape);
+ return shape;
+ }
+
+ // memleak... todo: delete shape
+ return NULL;
+}
+
+
+void KX_ClearSumoSharedShapes()
+{
+ int numshapes = map_gamemesh_to_sumoshape.size();
+ for (int i=0;i<numshapes ;i++)
+ {
+ DT_ShapeHandle shape = *map_gamemesh_to_sumoshape.at(i);
+ DT_DeleteShape(shape);
+ }
+
+ map_gamemesh_to_sumoshape.clear();
+}
+
+
+
+
+
+#endif //USE_SUMO_SOLID
+
+
+#ifdef USE_ODE
+
+void KX_ConvertODEEngineObject(KX_GameObject* gameobj,
+ RAS_MeshObject* meshobj,
+ KX_Scene* kxscene,
+ struct PHY_ShapeProps* shapeprops,
+ struct PHY_MaterialProps* smmaterial,
+ struct KX_ObjectProperties* objprop)
+{
+ // not yet, future extension :)
+ bool dyna=objprop->m_dyna;
+ bool fullRigidBody= ( objprop->m_dyna && objprop->m_angular_rigidbody) != 0;
+ bool phantom = objprop->m_ghost;
+ class PHY_IMotionState* motionstate = new KX_MotionState(gameobj->GetSGNode());
+
+ class ODEPhysicsEnvironment* odeEnv =
+ (ODEPhysicsEnvironment*)kxscene->GetPhysicsEnvironment();
+
+ dxSpace* space = odeEnv->GetOdeSpace();
+ dxWorld* world = odeEnv->GetOdeWorld();
+
+ if (!objprop->m_implicitsphere &&
+ MT_fuzzyZero(objprop->m_boundingbox.m_extends[0]) ||
+ MT_fuzzyZero(objprop->m_boundingbox.m_extends[1]) ||
+ MT_fuzzyZero(objprop->m_boundingbox.m_extends[2])
+ )
+ {
+
+ } else
+ {
+
+ KX_OdePhysicsController* physicscontroller =
+ new KX_OdePhysicsController(
+ dyna,
+ fullRigidBody,
+ phantom,
+ motionstate,
+ space,
+ world,
+ shapeprops->m_mass,
+ smmaterial->m_friction,
+ smmaterial->m_restitution,
+ objprop->m_implicitsphere,
+ objprop->m_boundingbox.m_center,
+ objprop->m_boundingbox.m_extends,
+ objprop->m_radius
+ );
+
+ gameobj->SetPhysicsController(physicscontroller);
+ physicscontroller->setClientInfo(gameobj);
+ gameobj->GetSGNode()->AddSGController(physicscontroller);
+
+ bool isActor = objprop->m_isactor;
+ STR_String materialname;
+ if (meshobj)
+ materialname = meshobj->GetMaterialName(0);
+
+ const char* matname = materialname.ReadPtr();
+
+
+ physicscontroller->SetObject(gameobj->GetSGNode());
+
+ }
+}
+
+
+#endif // USE_ODE
diff --git a/source/gameengine/Ketsji/KX_EmptyObject.cpp b/source/gameengine/Ketsji/KX_EmptyObject.cpp
new file mode 100644
index 00000000000..d3b120066d9
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_EmptyObject.cpp
@@ -0,0 +1,32 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "KX_EmptyObject.h"
diff --git a/source/gameengine/Ketsji/KX_EmptyObject.h b/source/gameengine/Ketsji/KX_EmptyObject.h
new file mode 100644
index 00000000000..472cabe047e
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_EmptyObject.h
@@ -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 *****
+ */
+#ifndef __KX_EMPTYOBJECT
+#define __KX_EMPTYOBJECT
+#include "KX_GameObject.h"
+
+class KX_EmptyObject : public KX_GameObject
+{
+public:
+ KX_EmptyObject(void* sgReplicationInfo,SG_Callbacks callbacks) :
+ KX_GameObject(sgReplicationInfo,callbacks)
+ {};
+ virtual ~KX_EmptyObject() {};
+
+};
+#endif //__KX_EMPTYOBJECT
diff --git a/source/gameengine/Ketsji/KX_GameActuator.cpp b/source/gameengine/Ketsji/KX_GameActuator.cpp
new file mode 100644
index 00000000000..240cef164a3
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_GameActuator.cpp
@@ -0,0 +1,186 @@
+/**
+* global game stuff
+*
+* $Id$
+*
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "SCA_IActuator.h"
+#include "KX_GameActuator.h"
+//#include <iostream>
+#include "KX_Scene.h"
+#include "KX_KetsjiEngine.h"
+
+/* ------------------------------------------------------------------------- */
+/* Native functions */
+/* ------------------------------------------------------------------------- */
+
+KX_GameActuator::KX_GameActuator(SCA_IObject *gameobj,
+ int mode,
+ const STR_String& filename,
+ const STR_String& loadinganimationname,
+ KX_Scene* scene,
+ KX_KetsjiEngine* ketsjiengine,
+ PyTypeObject* T)
+ : SCA_IActuator(gameobj, T)
+{
+ m_mode = mode;
+ m_filename = filename;
+ m_loadinganimationname = loadinganimationname;
+ m_scene = scene;
+ m_ketsjiengine = ketsjiengine;
+} /* End of constructor */
+
+
+
+KX_GameActuator::~KX_GameActuator()
+{
+ // there's nothing to be done here, really....
+} /* end of destructor */
+
+
+
+CValue* KX_GameActuator::GetReplica()
+{
+ KX_GameActuator* replica = new KX_GameActuator(*this);
+ replica->ProcessReplica();
+ // this will copy properties and so on...
+ CValue::AddDataToReplica(replica);
+
+ return replica;
+}
+
+
+
+bool KX_GameActuator::Update(double curtime, double deltatime)
+{
+ bool result = false;
+ bool bNegativeEvent = IsNegativeEvent();
+ RemoveAllEvents();
+
+ if (bNegativeEvent)
+ return false; // do nothing on negative events
+
+ switch (m_mode)
+ {
+ case KX_GAME_LOAD:
+ case KX_GAME_START:
+ {
+ if (m_ketsjiengine)
+ {
+ STR_String exitstring = "start other game";
+ m_ketsjiengine->RequestExit(KX_EXIT_REQUEST_START_OTHER_GAME);
+ m_ketsjiengine->SetNameNextGame(m_filename);
+ m_scene->AddDebugProperty((this)->GetParent(), exitstring);
+ }
+
+ break;
+ }
+ case KX_GAME_RESTART:
+ {
+ if (m_ketsjiengine)
+ {
+ STR_String exitstring = "restarting game";
+ m_ketsjiengine->RequestExit(KX_EXIT_REQUEST_RESTART_GAME);
+ m_scene->AddDebugProperty((this)->GetParent(), exitstring);
+ }
+ break;
+ }
+ case KX_GAME_QUIT:
+ {
+ if (m_ketsjiengine)
+ {
+ STR_String exitstring = "quiting game";
+ m_ketsjiengine->RequestExit(KX_EXIT_REQUEST_QUIT_GAME);
+ m_scene->AddDebugProperty((this)->GetParent(), exitstring);
+ }
+ break;
+ }
+ default:
+ ; /* do nothing? this is an internal error !!! */
+ }
+
+ return false;
+}
+
+
+
+
+
+/* ------------------------------------------------------------------------- */
+/* Python functions */
+/* ------------------------------------------------------------------------- */
+
+/* Integration hooks ------------------------------------------------------- */
+PyTypeObject KX_GameActuator::Type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0,
+ "KX_SceneActuator",
+ sizeof(KX_GameActuator),
+ 0,
+ PyDestructor,
+ 0,
+ __getattr,
+ __setattr,
+ 0, //&MyPyCompare,
+ __repr,
+ 0, //&cvalue_as_number,
+ 0,
+ 0,
+ 0,
+ 0
+};
+
+
+
+PyParentObject KX_GameActuator::Parents[] =
+{
+ &KX_GameActuator::Type,
+ &SCA_IActuator::Type,
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
+};
+
+
+
+PyMethodDef KX_GameActuator::Methods[] =
+{
+ {NULL,NULL} //Sentinel
+};
+
+
+
+PyObject* KX_GameActuator::_getattr(char* attr)
+{
+ _getattr_up(SCA_IActuator);
+}
+
+
diff --git a/source/gameengine/Ketsji/KX_GameActuator.h b/source/gameengine/Ketsji/KX_GameActuator.h
new file mode 100644
index 00000000000..7f2af86db42
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_GameActuator.h
@@ -0,0 +1,86 @@
+
+//
+// actuator for global game stuff
+//
+// $Id$
+//
+// ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version. The Blender
+// Foundation also sells licenses for use in proprietary software under
+// the Blender License. See http://www.blender.org/BL/ for information
+// about this.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// The Original Code is Copyright (C) 2001-2002 by 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 __KX_GAMEACTUATOR
+#define __KX_GAMEACTUATOR
+
+#include "SCA_IActuator.h"
+
+class KX_GameActuator : public SCA_IActuator
+{
+ Py_Header;
+ int m_mode;
+ bool m_restart;
+ STR_String m_filename;
+ STR_String m_loadinganimationname;
+ class KX_Scene* m_scene;
+ class KX_KetsjiEngine* m_ketsjiengine;
+
+ public:
+ enum KX_GameActuatorMode
+ {
+ KX_GAME_NODEF = 0,
+ KX_GAME_LOAD,
+ KX_GAME_START,
+ KX_GAME_RESTART,
+ KX_GAME_QUIT,
+ KX_GAME_MAX
+
+ };
+
+ KX_GameActuator(SCA_IObject* gameobj,
+ int mode,
+ const STR_String& filename,
+ const STR_String& loadinganimationname,
+ KX_Scene* scene,
+ KX_KetsjiEngine* ketsjiEngine,
+ PyTypeObject* T=&Type);
+ virtual ~KX_GameActuator();
+
+ virtual CValue* GetReplica();
+
+ virtual bool Update(double curtime,double deltatime);
+
+ /* --------------------------------------------------------------------- */
+ /* Python interface ---------------------------------------------------- */
+ /* --------------------------------------------------------------------- */
+
+ virtual PyObject* _getattr(char *attr);
+
+
+}; /* end of class KX_GameActuator */
+
+#endif
+
diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp
new file mode 100644
index 00000000000..1f8b3a8e1ac
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_GameObject.cpp
@@ -0,0 +1,1096 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * Game object wrapper
+ */
+
+#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
+
+
+#define KX_INERTIA_INFINITE 10000
+#include "RAS_IPolygonMaterial.h"
+#include "KX_GameObject.h"
+#include "RAS_MeshObject.h"
+#include "KX_MeshProxy.h"
+#include <stdio.h> // printf
+#include "SG_Controller.h"
+#include "KX_IPhysicsController.h"
+#include "SG_Node.h"
+#include "SG_Controller.h"
+#include "KX_ClientObjectInfo.h"
+#include "RAS_BucketManager.h"
+
+// This file defines relationships between parents and children
+// in the game engine.
+
+#include "KX_SG_NodeRelationships.h"
+
+KX_GameObject::KX_GameObject(
+ void* sgReplicationInfo,
+ SG_Callbacks callbacks,
+ PyTypeObject* T
+) :
+ SCA_IObject(T),
+ m_bUseObjectColor(false),
+ m_bDyna(false),
+ m_bSuspendDynamics(false),
+ m_pPhysicsController1(NULL),
+ m_bVisible(true)
+{
+ m_ignore_activity_culling = false;
+ m_pClient_info = new KX_ClientObjectInfo();
+ m_pSGNode = new SG_Node(this,sgReplicationInfo,callbacks);
+
+ // define the relationship between this node and it's parent.
+
+ KX_NormalParentRelation * parent_relation =
+ KX_NormalParentRelation::New();
+ m_pSGNode->SetParentRelation(parent_relation);
+
+
+};
+
+
+
+KX_GameObject::~KX_GameObject()
+{
+ // is this delete somewhere ?
+ //if (m_sumoObj)
+ // delete m_sumoObj;
+ delete m_pClient_info;
+ //if (m_pSGNode)
+ // delete m_pSGNode;
+
+}
+
+
+
+CValue* KX_GameObject:: Calc(VALUE_OPERATOR op, CValue *val)
+{
+ return NULL;
+}
+
+
+
+CValue* KX_GameObject::CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val)
+{
+ return NULL;
+}
+
+
+
+const STR_String & KX_GameObject::GetText()
+{
+ return m_text;
+}
+
+
+
+float KX_GameObject::GetNumber()
+{
+ return 0;
+}
+
+
+
+STR_String KX_GameObject::GetName()
+{
+ return m_name;
+}
+
+
+
+void KX_GameObject::SetName(STR_String name)
+{
+ m_name = name;
+}; // Set the name of the value
+
+
+
+void KX_GameObject::ReplicaSetName(STR_String name)
+{
+}
+
+
+
+
+
+
+KX_IPhysicsController* KX_GameObject::GetPhysicsController()
+{
+ return m_pPhysicsController1;
+}
+
+
+
+
+
+KX_GameObject* KX_GameObject::GetParent()
+{
+ KX_GameObject* result = NULL;
+ SG_Node* node = m_pSGNode;
+
+ while (node && !result)
+ {
+ node = node->GetSGParent();
+ if (node)
+ result = (KX_GameObject*)node->GetSGClientObject();
+ }
+
+ if (result)
+ result->AddRef();
+
+ return result;
+
+}
+
+
+
+void KX_GameObject::ProcessReplica(KX_GameObject* replica)
+{
+ replica->m_pPhysicsController1 = NULL;
+ replica->m_pSGNode = NULL;
+ replica->m_pClient_info = new KX_ClientObjectInfo(*m_pClient_info);
+ replica->m_pClient_info->m_clientobject = replica;
+}
+
+
+
+CValue* KX_GameObject::GetReplica()
+{
+ KX_GameObject* replica = new KX_GameObject(*this);
+
+ // this will copy properties and so on...
+ CValue::AddDataToReplica(replica);
+ ProcessReplica(replica);
+
+ return replica;
+}
+
+
+
+void KX_GameObject::ApplyForce(const MT_Vector3& force,bool local)
+{
+ if (m_pPhysicsController1)
+ m_pPhysicsController1->ApplyForce(force,local);
+}
+
+
+
+void KX_GameObject::ApplyTorque(const MT_Vector3& torque,bool local)
+{
+ if (m_pPhysicsController1)
+ m_pPhysicsController1->ApplyTorque(torque,local);
+}
+
+
+
+void KX_GameObject::ApplyMovement(const MT_Vector3& dloc,bool local)
+{
+ if (this->IsDynamic())
+ {
+ m_pPhysicsController1->RelativeTranslate(dloc,local);
+ }
+ else
+ {
+ GetSGNode()->RelativeTranslate(dloc,GetSGNode()->GetSGParent(),local);
+ }
+}
+
+
+
+void KX_GameObject::ApplyRotation(const MT_Vector3& drot,bool local)
+{
+ MT_Matrix3x3 rotmat(drot);
+
+ if (this->IsDynamic()) //m_pPhysicsController)
+ m_pPhysicsController1->RelativeRotate(rotmat.transposed(),local);
+ else
+ // in worldspace
+ GetSGNode()->RelativeRotate(rotmat.transposed(),local);
+}
+
+
+
+/**
+GetOpenGL Matrix, returns an OpenGL 'compatible' matrix
+*/
+double* KX_GameObject::GetOpenGLMatrix()
+{
+ // todo: optimize and only update if necessary
+ double* fl = m_OpenGL_4x4Matrix.getPointer();
+ MT_Transform trans;
+
+ trans.setOrigin(GetSGNode()->GetWorldPosition());
+ trans.setBasis(GetSGNode()->GetWorldOrientation());
+
+ MT_Vector3 scaling = GetSGNode()->GetWorldScaling();
+
+ trans.scale(scaling[0], scaling[1], scaling[2]);
+ trans.getValue(fl);
+
+ return fl;
+}
+
+
+
+void KX_GameObject::Bucketize()
+{
+ double* fl = GetOpenGLMatrix();
+
+ for (int i=0;i<m_meshes.size();i++)
+ m_meshes[i]->Bucketize(fl, this, m_bUseObjectColor, m_objectColor);
+}
+
+
+
+void KX_GameObject::RemoveMeshes()
+{
+ double* fl = GetOpenGLMatrix();
+
+ for (int i=0;i<m_meshes.size();i++)
+ m_meshes[i]->RemoveFromBuckets(fl, this);
+
+ //note: meshes can be shared, and are deleted by KX_BlenderSceneConverter
+
+ m_meshes.clear();
+}
+
+
+
+void KX_GameObject::UpdateNonDynas()
+{
+ if (m_pPhysicsController1)
+ {
+ m_pPhysicsController1->SetSumoTransform(true);
+ }
+}
+
+
+
+void KX_GameObject::UpdateTransform()
+{
+ if (m_pPhysicsController1)
+ {
+ m_pPhysicsController1->SetSumoTransform(false);
+ }
+}
+
+
+
+void KX_GameObject::SetDebugColor(unsigned int bgra)
+{
+ for (int i=0;i<m_meshes.size();i++)
+ m_meshes[i]->DebugColor(bgra);
+}
+
+
+
+void KX_GameObject::ResetDebugColor()
+{
+ SetDebugColor(0xff000000);
+}
+
+
+
+void KX_GameObject::UpdateIPO(float curframetime,
+ bool recurse,
+ bool ipo_as_force,
+ bool force_local)
+{
+
+ // The ipo-actuator needs a sumo reference... this is retrieved (unfortunately)
+ // by the iposgcontr itself...
+// ipocontr->SetSumoReference(gameobj->GetSumoScene(),
+// gameobj->GetSumoObject());
+
+
+ // The ipo has to be treated as a force, and not a displacement!
+ // For this case, we send some settings to the controller. This
+ // may need some caching...
+ if (ipo_as_force) {
+ SGControllerList::iterator it = GetSGNode()->GetSGControllerList().begin();
+
+ while (it != GetSGNode()->GetSGControllerList().end()) {
+ (*it)->SetOption(SG_Controller::SG_CONTR_IPO_IPO_AS_FORCE, ipo_as_force);
+ (*it)->SetOption(SG_Controller::SG_CONTR_IPO_FORCES_ACT_LOCAL, force_local);
+ it++;
+ }
+ }
+
+ // The rest is the 'normal' update procedure.
+ GetSGNode()->SetSimulatedTime(curframetime,recurse);
+ GetSGNode()->UpdateWorldData(curframetime);
+ UpdateTransform();
+}
+
+
+/*
+void KX_GameObject::RegisterSumoObject(class SM_Scene* sumoScene,
+ DT_SceneHandle solidscene,
+ class SM_Object* sumoObj,
+ const char* matname,
+ bool isDynamic,
+ bool isActor)
+{
+ m_bDyna = isDynamic;
+
+ // need easy access, not via 'node' etc.
+ m_pPhysicsController = new KX_PhysicsController(sumoScene,solidscene,sumoObj,isDynamic);
+
+ GetSGNode()->AddSGController(m_pPhysicsController);
+
+ m_pClient_info->m_type = (isActor ? 1 : 0);
+ m_pClient_info->m_clientobject = this;
+
+ // store materialname in auxinfo, needed for touchsensors
+ m_pClient_info->m_auxilary_info = (matname? (void*)(matname+2) : NULL);
+ m_pPhysicsController->SetObject(this->GetSGNode());
+}
+*/
+
+bool
+KX_GameObject::GetVisible(
+ void
+ )
+{
+ return m_bVisible;
+}
+
+void
+KX_GameObject::SetVisible(
+ bool v
+ )
+{
+ m_bVisible = v;
+}
+
+// used by Python, and the actuatorshould _not_ be misused by the
+// scene!
+void
+KX_GameObject::MarkVisible(
+ bool visible
+ )
+{
+ /* If explicit visibility settings are used, this is
+ * determined on this level. Maybe change this to mesh level
+ * later on? */
+
+ for (int i=0;i<m_meshes.size();i++)
+ {
+ double* fl = GetOpenGLMatrix();
+ m_meshes[i]->MarkVisible(fl,this,visible,m_bUseObjectColor,m_objectColor);
+ }
+}
+
+
+// Always use the flag?
+void
+KX_GameObject::MarkVisible(
+ void
+ )
+{
+ for (int i=0;i<m_meshes.size();i++)
+ {
+ double* fl = GetOpenGLMatrix();
+ m_meshes[i]->MarkVisible(fl,
+ this,
+ m_bVisible,
+ m_bUseObjectColor,
+ m_objectColor
+ );
+ }
+}
+
+void KX_GameObject::addLinearVelocity(const MT_Vector3& lin_vel,bool local)
+{
+// if (m_pPhysicsController1)
+// m_pPhysicsController1->AddLinearVelocity(lin_vel,local);
+}
+
+
+
+void KX_GameObject::setLinearVelocity(const MT_Vector3& lin_vel,bool local)
+{
+ if (m_pPhysicsController1)
+ m_pPhysicsController1->SetLinearVelocity(lin_vel,local);
+}
+
+
+
+void KX_GameObject::setAngularVelocity(const MT_Vector3& ang_vel,bool local)
+{
+ if (m_pPhysicsController1)
+ m_pPhysicsController1->SetAngularVelocity(ang_vel,local);
+}
+
+
+
+void KX_GameObject::SetObjectColor(const MT_Vector4& rgbavec)
+{
+ m_bUseObjectColor = true;
+ m_objectColor = rgbavec;
+}
+
+
+
+MT_Vector3 KX_GameObject::GetLinearVelocity()
+{
+ MT_Vector3 velocity(0.0,0.0,0.0);
+
+ if (m_pPhysicsController1)
+ {
+ velocity = m_pPhysicsController1->GetLinearVelocity();
+ }
+ return velocity;
+
+}
+
+
+// scenegraph node stuff
+
+void KX_GameObject::NodeSetLocalPosition(const MT_Point3& trans)
+{
+ if (m_pPhysicsController1)
+ {
+ m_pPhysicsController1->setPosition(trans);
+ }
+
+ GetSGNode()->SetLocalPosition(trans);
+}
+
+
+
+void KX_GameObject::NodeSetLocalOrientation(const MT_Matrix3x3& rot)
+{
+ if (m_pPhysicsController1)
+ {
+ m_pPhysicsController1->setOrientation(rot.getRotation());
+ }
+
+ GetSGNode()->SetLocalOrientation(rot);
+}
+
+
+
+void KX_GameObject::NodeSetLocalScale(const MT_Vector3& scale)
+{
+ if (m_pPhysicsController1)
+ {
+ m_pPhysicsController1->setScaling(scale);
+ }
+
+ GetSGNode()->SetLocalScale(scale);
+}
+
+
+
+void KX_GameObject::NodeSetRelativeScale(const MT_Vector3& scale)
+{
+ GetSGNode()->RelativeScale(scale);
+}
+
+
+
+void KX_GameObject::NodeUpdateGS(double time,bool bInitiator)
+{
+ GetSGNode()->UpdateWorldData(time);
+}
+
+
+
+const MT_Matrix3x3& KX_GameObject::NodeGetWorldOrientation() const
+{
+ return GetSGNode()->GetWorldOrientation();
+}
+
+
+
+const MT_Vector3& KX_GameObject::NodeGetWorldScaling() const
+{
+ return GetSGNode()->GetWorldScaling();
+}
+
+
+
+const MT_Point3& KX_GameObject::NodeGetWorldPosition() const
+{
+ return GetSGNode()->GetWorldPosition();
+}
+
+/* Suspend/ resume: for the dynamic behaviour, there is a simple
+ * method. For the residual motion, there is not. I wonder what the
+ * correct solution is for Sumo. Remove from the motion-update tree?
+ *
+ * So far, only switch the physics and logic.
+ * */
+
+void KX_GameObject::Resume(void)
+{
+ if (m_suspended) {
+ SCA_IObject::Resume();
+ GetPhysicsController()->RestoreDynamics();
+
+ m_suspended = false;
+ }
+}
+
+void KX_GameObject::Suspend(void)
+{
+ if ((!m_ignore_activity_culling)
+ && (!m_suspended)) {
+ SCA_IObject::Suspend();
+ GetPhysicsController()->SuspendDynamics();
+ m_suspended = true;
+ }
+}
+
+
+
+
+/* ------- python stuff ---------------------------------------------------*/
+
+
+
+
+PyMethodDef KX_GameObject::Methods[] = {
+ {"setVisible",(PyCFunction) KX_GameObject::sPySetVisible, METH_VARARGS},
+ {"setPosition", (PyCFunction) KX_GameObject::sPySetPosition, METH_VARARGS},
+ {"getPosition", (PyCFunction) KX_GameObject::sPyGetPosition, METH_VARARGS},
+ {"getLinearVelocity", (PyCFunction) KX_GameObject::sPyGetLinearVelocity, METH_VARARGS},
+ {"getVelocity", (PyCFunction) KX_GameObject::sPyGetVelocity, METH_VARARGS},
+ {"getOrientation", (PyCFunction) KX_GameObject::sPyGetOrientation, METH_VARARGS},
+ {"setOrientation", (PyCFunction) KX_GameObject::sPySetOrientation, METH_VARARGS},
+ {"getMass", (PyCFunction) KX_GameObject::sPyGetMass, METH_VARARGS},
+ {"getReactionForce", (PyCFunction) KX_GameObject::sPyGetReactionForce, METH_VARARGS},
+ {"applyImpulse", (PyCFunction) KX_GameObject::sPyApplyImpulse, METH_VARARGS},
+ {"suspendDynamics", (PyCFunction)KX_GameObject::sPySuspendDynamics,METH_VARARGS},
+ {"restoreDynamics", (PyCFunction)KX_GameObject::sPyRestoreDynamics,METH_VARARGS},
+ {"enableRigidBody", (PyCFunction)KX_GameObject::sPyEnableRigidBody,METH_VARARGS},
+ {"disableRigidBody", (PyCFunction)KX_GameObject::sPyDisableRigidBody,METH_VARARGS},
+ {"getParent", (PyCFunction)KX_GameObject::sPyGetParent,METH_VARARGS},
+ {"getMesh", (PyCFunction)KX_GameObject::sPyGetMesh,METH_VARARGS},
+ {"getPhysicsId", (PyCFunction)KX_GameObject::sPyGetPhysicsId,METH_VARARGS},
+
+
+ {NULL,NULL} //Sentinel
+};
+
+
+
+
+bool KX_GameObject::ConvertPythonVectorArgs(PyObject* args,
+ MT_Vector3& pos,
+ MT_Vector3& pos2)
+{
+ PyObject* pylist;
+ PyObject* pylist2;
+ bool error = (PyArg_ParseTuple(args,"OO",&pylist,&pylist2)) != 0;
+
+ pos = ConvertPythonPylist(pylist);
+ pos2 = ConvertPythonPylist(pylist2);
+
+ return error;
+}
+
+
+
+PyObject* KX_GameObject::sPySetPosition(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ return ((KX_GameObject*) self)->PySetPosition(self, args, kwds);
+}
+
+
+
+PyObject* KX_GameObject::PyGetPosition(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ MT_Point3 pos = NodeGetWorldPosition();
+
+ PyObject* resultlist = PyList_New(3);
+ int index;
+ for (index=0;index<3;index++)
+ {
+ PyList_SetItem(resultlist,index,PyFloat_FromDouble(pos[index]));
+ }
+
+ return resultlist;
+
+}
+
+
+
+PyTypeObject KX_GameObject::Type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0,
+ "KX_GameObject",
+ sizeof(KX_GameObject),
+ 0,
+ PyDestructor,
+ 0,
+ __getattr,
+ __setattr,
+ 0, //&MyPyCompare,
+ __repr,
+ 0, //&cvalue_as_number,
+ 0,
+ 0,
+ 0,
+ 0
+};
+
+
+
+PyParentObject KX_GameObject::Parents[] = {
+ &KX_GameObject::Type,
+ &SCA_IObject::Type,
+ &CValue::Type,
+ NULL
+};
+
+
+
+
+PyObject* KX_GameObject::_getattr(char* attr)
+{
+ _getattr_up(SCA_IObject);
+}
+
+
+
+PyObject* KX_GameObject::PyGetLinearVelocity(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ // only can get the velocity if we have a physics object connected to us...
+ MT_Vector3 velocity = GetLinearVelocity();
+
+ PyObject* resultlist = PyList_New(3);
+ int index;
+ for (index=0;index<3;index++)
+ {
+ PyList_SetItem(resultlist,index,PyFloat_FromDouble(velocity[index]));
+ }
+
+ return resultlist;
+}
+
+
+
+PyObject* KX_GameObject::PySetVisible(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ int visible = 1;
+
+ if (PyArg_ParseTuple(args,"i",&visible))
+ {
+ MarkVisible(visible!=0);
+ m_bVisible = (visible!=0);
+ }
+ else
+ {
+ return NULL;
+ }
+ Py_Return;
+
+}
+
+
+
+PyObject* KX_GameObject::PyGetVelocity(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ // only can get the velocity if we have a physics object connected to us...
+ MT_Vector3 velocity(0.0,0.0,0.0);
+ MT_Point3 point(0.0,0.0,0.0);
+
+
+ MT_Point3 pos;
+ PyObject* pylist;
+ bool error = false;
+
+ int len = PyTuple_Size(args);
+
+ if ((len > 0) && PyArg_ParseTuple(args,"O",&pylist))
+ {
+ if (pylist->ob_type == &CListValue::Type)
+ {
+ CListValue* listval = (CListValue*) pylist;
+ if (listval->GetCount() == 3)
+ {
+ int index;
+ for (index=0;index<3;index++)
+ {
+ pos[index] = listval->GetValue(index)->GetNumber();
+ }
+ } else
+ {
+ error = true;
+ }
+
+ } else
+ {
+
+ // assert the list is long enough...
+ int numitems = PyList_Size(pylist);
+ if (numitems == 3)
+ {
+ int index;
+ for (index=0;index<3;index++)
+ {
+ pos[index] = PyFloat_AsDouble(PyList_GetItem(pylist,index));
+ }
+ }
+ else
+ {
+ error = true;
+ }
+ }
+
+ if (!error)
+ point = pos;
+ }
+
+
+ if (m_pPhysicsController1)
+ {
+ velocity = m_pPhysicsController1->GetVelocity(point);
+ }
+
+ PyObject* resultlist = PyList_New(3);
+ int index;
+ for (index=0;index<3;index++)
+ {
+ PyList_SetItem(resultlist,index,PyFloat_FromDouble(velocity[index]));
+ }
+
+ return resultlist;
+}
+
+
+
+PyObject* KX_GameObject::PyGetMass(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ PyObject* pymass = NULL;
+
+ float mass = GetPhysicsController()->GetMass();
+ pymass = PyFloat_FromDouble(mass);
+
+ if (pymass)
+ return pymass;
+
+ Py_Return;
+}
+
+
+
+PyObject* KX_GameObject::PyGetReactionForce(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ // only can get the velocity if we have a physics object connected to us...
+
+ MT_Vector3 reaction_force = GetPhysicsController()->getReactionForce();
+
+ PyObject* resultlist = PyList_New(3);
+ int index;
+ for (index=0;index<3;index++)
+ {
+ PyList_SetItem(resultlist,index,
+ PyFloat_FromDouble(reaction_force[index]));
+ }
+
+ return resultlist;
+}
+
+
+
+PyObject* KX_GameObject::PyEnableRigidBody(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+
+ GetPhysicsController()->setRigidBody(true);
+
+ Py_Return;
+}
+
+
+
+PyObject* KX_GameObject::PyDisableRigidBody(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ GetPhysicsController()->setRigidBody(false);
+
+ Py_Return;
+}
+
+
+
+PyObject* KX_GameObject::PyGetParent(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ KX_GameObject* parent = this->GetParent();
+ if (parent)
+ return parent;
+ Py_Return;
+}
+
+
+
+PyObject* KX_GameObject::PyGetMesh(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ if (m_meshes.size() > 0)
+ {
+ KX_MeshProxy* meshproxy = new KX_MeshProxy(m_meshes[0]);
+ return meshproxy;
+ }
+
+ Py_Return;
+}
+
+
+
+PyObject* KX_GameObject::PyApplyImpulse(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+
+ MT_Point3 attach(0, 1, 0);
+ MT_Vector3 impulse(1, 0, 0);
+
+ if (ConvertPythonVectorArgs(args,attach,impulse))
+ {
+ if (m_pPhysicsController1)
+ {
+ m_pPhysicsController1->applyImpulse(attach, impulse);
+ }
+
+ }
+
+ Py_Return;
+}
+
+
+
+PyObject* KX_GameObject::PySuspendDynamics(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ if (m_bSuspendDynamics)
+ {
+ Py_Return;
+ }
+
+ if (m_pPhysicsController1)
+ {
+ m_pPhysicsController1->SuspendDynamics();
+ }
+ m_bSuspendDynamics = true;
+
+ Py_Return;
+}
+
+
+
+PyObject* KX_GameObject::PyRestoreDynamics(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+
+ if (!m_bSuspendDynamics)
+ {
+ Py_Return;
+ }
+
+ if (m_pPhysicsController1)
+ {
+ m_pPhysicsController1->RestoreDynamics();
+ }
+ m_bSuspendDynamics = false;
+
+ Py_Return;
+}
+
+
+
+PyObject* KX_GameObject::PyGetOrientation(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) //keywords
+{
+ // do the conversion of a C++ matrix to a python list
+
+ PyObject* resultlist = PyList_New(3);
+
+
+ int row,col;
+ const MT_Matrix3x3& orient = NodeGetWorldOrientation();
+
+ int index = 0;
+ for (row=0;row<3;row++)
+ {
+ PyObject* veclist = PyList_New(3);
+
+ for (col=0;col<3;col++)
+ {
+ const MT_Scalar fl = orient[row][col];
+ PyList_SetItem(veclist,col,PyFloat_FromDouble(fl));
+ }
+ PyList_SetItem(resultlist,row,veclist);
+
+ }
+ return resultlist;
+}
+
+
+
+PyObject* KX_GameObject::PySetOrientation(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ MT_Matrix3x3 matrix;
+
+ PyObject* pylist;
+ bool error = false;
+ int row,col;
+
+ PyArg_ParseTuple(args,"O",&pylist);
+
+ if (pylist->ob_type == &CListValue::Type)
+ {
+ CListValue* listval = (CListValue*) pylist;
+ if (listval->GetCount() == 3)
+ {
+ for (row=0;row<3;row++) // each row has a 3-vector [x,y,z]
+ {
+ CListValue* vecval = (CListValue*)listval->GetValue(row);
+ for (col=0;col<3;col++)
+ {
+ matrix[row][col] = vecval->GetValue(col)->GetNumber();
+
+ }
+ }
+ }
+ else
+ {
+ error = true;
+ }
+ }
+ else
+ {
+ // assert the list is long enough...
+ int numitems = PyList_Size(pylist);
+ if (numitems == 3)
+ {
+ for (row=0;row<3;row++) // each row has a 3-vector [x,y,z]
+ {
+
+ PyObject* veclist = PyList_GetItem(pylist,row); // here we have a vector3 list
+ for (col=0;col<3;col++)
+ {
+ matrix[row][col] = PyFloat_AsDouble(PyList_GetItem(veclist,col));
+
+ }
+ }
+ }
+ else
+ {
+ error = true;
+ }
+ }
+
+ if (!error)
+ {
+ if (m_pPhysicsController1)
+ {
+ m_pPhysicsController1->setOrientation(matrix.getRotation());
+ }
+ NodeSetLocalOrientation(matrix);
+ }
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+
+
+PyObject* KX_GameObject::PySetPosition(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ // make a general function for this, it's needed many times
+
+ MT_Point3 pos = ConvertPythonVectorArg(args);
+ if (this->m_pPhysicsController1)
+ {
+ this->m_pPhysicsController1->setPosition(pos);
+ }
+ NodeSetLocalPosition(pos);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+PyObject* KX_GameObject::PyGetPhysicsId(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ KX_IPhysicsController* ctrl = GetPhysicsController();
+ int physid=0;
+ if (ctrl)
+ {
+ physid= (int)ctrl->GetUserData();
+ }
+ return PyInt_FromLong(physid);
+}
+
+/* ---------------------------------------------------------------------
+ * Some stuff taken from the header
+ * --------------------------------------------------------------------- */
+void KX_GameObject::Relink(GEN_Map<GEN_HashedPtr, void*> *map_parameter)
+{
+ /* intentionally empty ? */
+}
+
diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h
new file mode 100644
index 00000000000..c9c9ccafd0d
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_GameObject.h
@@ -0,0 +1,614 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * General KX game object.
+ */
+
+#ifndef __KX_GAMEOBJECT
+#define __KX_GAMEOBJECT
+
+
+#ifdef WIN32
+// get rid of this stupid "warning 'this' used in initialiser list", generated by VC when including Solid/Sumo
+#pragma warning (disable : 4355)
+#endif
+
+
+#include "ListValue.h"
+#include "SCA_IObject.h"
+#include "SG_Node.h"
+#include "MT_Transform.h"
+#include "MT_CmMatrix4x4.h"
+#include "GEN_Map.h"
+#include "GEN_HashedPtr.h"
+
+#define KX_FIXED_FRAME_PER_SEC 25.0f
+#define KX_FIXED_SEC_PER_FRAME (1.0f / KX_FIXED_FRAME_PER_SEC)
+#define KX_OB_DYNAMIC 1
+
+
+//Forward declarations.
+struct KX_ClientObjectInfo;
+class RAS_MeshObject;
+class KX_IPhysicsController;
+class SM_Object;
+
+class KX_GameObject : public SCA_IObject
+{
+ Py_Header;
+
+ bool m_bDyna;
+ KX_ClientObjectInfo* m_pClient_info;
+ STR_String m_name;
+ STR_String m_text;
+ std::vector<RAS_MeshObject*> m_meshes;
+
+ bool m_bSuspendDynamics;
+ bool m_bUseObjectColor;
+ MT_Vector4 m_objectColor;
+
+ // Is this object set to be visible? Only useful for the
+ // visibility subsystem right now.
+ bool m_bVisible;
+
+ KX_IPhysicsController* m_pPhysicsController1;
+ SG_Node* m_pSGNode;
+
+protected:
+ MT_CmMatrix4x4 m_OpenGL_4x4Matrix;
+
+public:
+ virtual void /* This function should be virtual - derived classed override it */
+ Relink(
+ GEN_Map<GEN_HashedPtr, void*> *map
+ );
+
+ /**
+ * Compute an OpenGl compatable 4x4 matrix. Has the
+ * side effect of storing the result internally. The
+ * memory for the matrix remains the property of this class.
+ */
+ double*
+ GetOpenGLMatrix(
+ );
+
+ /**
+ * Return a pointer to a MT_CmMatrix4x4 storing the
+ * opengl transformation for this object. This is updated
+ * by a call to GetOpenGLMatrix(). This class owns the
+ * memory for the returned matrix.
+ */
+
+ MT_CmMatrix4x4*
+ GetOpenGLMatrixPtr(
+ ) {
+ return &m_OpenGL_4x4Matrix;
+ };
+
+ /**
+ * Get a pointer to the game object that is the parent of
+ * this object. Or NULL if there is no parent. The returned
+ * object is part of a reference counting scheme. Calling
+ * this function ups the reference count on the returned
+ * object. It is the responsibility of the caller to decrement
+ * the reference count when you have finished with it.
+ */
+ KX_GameObject*
+ GetParent(
+ );
+
+
+ /**
+ * Construct a game object. This class also inherits the
+ * default constructors - use those with care!
+ */
+
+ KX_GameObject(
+ void* sgReplicationInfo,
+ SG_Callbacks callbacks,
+ PyTypeObject* T=&Type
+ );
+
+ virtual
+ ~KX_GameObject(
+ );
+
+ CValue*
+ AddRef() {
+ /* temporarily to find memleaks */ return CValue::AddRef();
+ }
+
+ /**
+ * @section Stuff which is here due to poor design.
+ * Inherited from CValue and needs an implementation.
+ * Do not expect these functions do to anything sensible.
+ */
+
+ /**
+ * Inherited from CValue -- does nothing!
+ */
+ CValue*
+ Calc(
+ VALUE_OPERATOR op,
+ CValue *val
+ );
+
+ /**
+ * Inherited from CValue -- does nothing!
+ */
+ CValue*
+ CalcFinal(
+ VALUE_DATA_TYPE dtype,
+ VALUE_OPERATOR op,
+ CValue *val
+ );
+
+ /**
+ * Inherited from CValue -- does nothing!
+ */
+ const
+ STR_String &
+ GetText(
+ );
+
+ /**
+ * Inherited from CValue -- does nothing!
+ */
+ float
+ GetNumber(
+ );
+
+ /**
+ * @section Inherited from CValue. These are the useful
+ * part of the CValue interface that this class implements.
+ */
+
+ /**
+ * Inherited from CValue -- returns the name of this object.
+ */
+ STR_String
+ GetName(
+ );
+
+ /**
+ * Inherited from CValue -- set the name of this object.
+ */
+ void
+ SetName(
+ STR_String name
+ );
+
+ /**
+ * Inherited from CValue -- does nothing.
+ */
+ void
+ ReplicaSetName(
+ STR_String name
+ );
+
+ /**
+ * Inherited from CValue -- return a new copy of this
+ * instance allocated on the heap. Ownership of the new
+ * object belongs with the caller.
+ */
+ CValue*
+ GetReplica(
+ );
+
+ /**
+ * Inherited from CValue -- Makes sure any internal
+ * data owned by this class is deep copied. Called internally
+ */
+ void
+ ProcessReplica(
+ KX_GameObject* replica
+ );
+
+ /**
+ * Return the linear velocity of the game object.
+ */
+ MT_Vector3
+ GetLinearVelocity(
+ );
+
+ /**
+ * Quick'n'dirty obcolor ipo stuff
+ */
+
+ void
+ SetObjectColor(
+ const MT_Vector4& rgbavec
+ );
+
+
+
+
+ /**
+ * @return a pointer to the physics controller owned by this class.
+ */
+
+ KX_IPhysicsController*
+ GetPhysicsController(
+ ) ;
+
+ void SetPhysicsController
+ (KX_IPhysicsController* physicscontroller)
+ { m_pPhysicsController1 = physicscontroller;};
+
+
+ /**
+ * @section Coordinate system manipulation functions
+ */
+
+ void
+ NodeSetLocalPosition(
+ const MT_Point3& trans
+ );
+
+ void
+ NodeSetLocalOrientation(
+ const MT_Matrix3x3& rot
+ );
+
+ void
+ NodeSetLocalScale(
+ const MT_Vector3& scale
+ );
+
+ void
+ NodeSetRelativeScale(
+ const MT_Vector3& scale
+ );
+
+ void
+ NodeUpdateGS(
+ double time,
+ bool bInitiator
+ );
+
+ const
+ MT_Matrix3x3&
+ NodeGetWorldOrientation(
+ ) const;
+
+ const
+ MT_Vector3&
+ NodeGetWorldScaling(
+ ) const;
+
+ const
+ MT_Point3&
+ NodeGetWorldPosition(
+ ) const;
+
+
+ /**
+ * @section scene graph node accessor functions.
+ */
+
+ SG_Node*
+ GetSGNode(
+ ) {
+ return m_pSGNode;
+ }
+
+ const
+ SG_Node*
+ GetSGNode(
+ ) const {
+ return m_pSGNode;
+ }
+
+ /**
+ * Set the Scene graph node for this game object.
+ * warning - it is your responsibility to make sure
+ * all controllers look at this new node. You must
+ * also take care of the memory associated with the
+ * old node. This class takes ownership of the new
+ * node.
+ */
+ void
+ SetSGNode(
+ SG_Node* node
+ ){
+ m_pSGNode = node;
+ }
+
+ bool
+ IsDynamic(
+ ) const {
+ return m_bDyna;
+ }
+
+
+ /**
+ * @section Physics accessors for this node.
+ *
+ * All these calls get passed directly to the physics controller
+ * owned by this object.
+ * This is real interface bloat. Why not just use the physics controller
+ * directly? I think this is because the python interface is in the wrong
+ * place.
+ */
+
+ void
+ ApplyForce(
+ const MT_Vector3& force, bool local
+ );
+
+ void
+ ApplyTorque(
+ const MT_Vector3& torque,
+ bool local
+ );
+
+ void
+ ApplyRotation(
+ const MT_Vector3& drot,
+ bool local
+ );
+
+ void
+ ApplyMovement(
+ const MT_Vector3& dloc,
+ bool local
+ );
+
+ void
+ addLinearVelocity(
+ const MT_Vector3& lin_vel,
+ bool local
+ );
+
+ void
+ setLinearVelocity(
+ const MT_Vector3& lin_vel,
+ bool local
+ );
+
+ void
+ setAngularVelocity(
+ const MT_Vector3& ang_vel,
+ bool local
+ );
+
+ /**
+ * Update the physics object transform based upon the current SG_Node
+ * position.
+ */
+ void
+ UpdateTransform(
+ );
+
+ /**
+ * Only update the transform if it's a non-dynamic object
+ */
+ void
+ UpdateNonDynas(
+ );
+
+ /**
+ * Odd function to update an ipo. ???
+ */
+ void
+ UpdateIPO(
+ float curframetime,
+ bool resurse,
+ bool ipo_as_force,
+ bool force_ipo_local
+ );
+
+ /**
+ * @section Mesh accessor functions.
+ */
+
+ /**
+ * Run through the meshes associated with this
+ * object and bucketize them. See RAS_Mesh for
+ * more details on this function. Interesting to
+ * note that polygon bucketizing seems to happen on a per
+ * object basis. Which may explain why there is such
+ * a big performance gain when all static objects
+ * are joined into 1.
+ */
+ void
+ Bucketize(
+ );
+
+ /**
+ * Clear the meshes associated with this class
+ * and remove from the bucketing system.
+ * Don't think this actually deletes any of the meshes.
+ */
+ void
+ RemoveMeshes(
+ );
+
+ /**
+ * Add a mesh to the set of meshes associated with this
+ * node. Meshes added in this way are not deleted by this class.
+ * Make sure you call RemoveMeshes() before deleting the
+ * mesh though,
+ */
+ void
+ AddMesh(
+ RAS_MeshObject* mesh
+ ){
+ m_meshes.push_back(mesh);
+ }
+
+ /**
+ * Pick out a mesh associated with the integer 'num'.
+ */
+ RAS_MeshObject*
+ GetMesh(
+ int num
+ ) const {
+ return m_meshes[num];
+ }
+
+ /**
+ * Return the number of meshes currently associated with this
+ * game object.
+ */
+ int
+ GetMeshCount(
+ ) const {
+ return m_meshes.size();
+ }
+
+ /**
+ * Set the debug color of the meshes associated with this
+ * class. Does this still work?
+ */
+ void
+ SetDebugColor(
+ unsigned int bgra
+ );
+
+ /**
+ * Reset the debug color of meshes associated with this class.
+ */
+ void
+ ResetDebugColor(
+ );
+
+ /**
+ * Set the visibility of the meshes associated with this
+ * object.
+ */
+ void
+ MarkVisible(
+ bool visible
+ );
+
+ /**
+ * Set the visibility according to the visibility flag.
+ */
+ void
+ MarkVisible(
+ void
+ );
+
+
+ /**
+ * Was this object marked visible? (only for the ewxplicit
+ * visibility system).
+ */
+ bool
+ GetVisible(
+ void
+ );
+
+ /**
+ * Set visibility flag of this object
+ */
+ void
+ SetVisible(
+ bool b
+ );
+
+
+ /**
+ * @section Logic bubbling methods.
+ */
+
+ /**
+ * Stop making progress
+ */
+ void Suspend(void);
+
+ /**
+ * Resume making progress
+ */
+ void Resume(void);
+
+ /**
+ * @section Python interface functions.
+ */
+
+ virtual
+ PyObject*
+ _getattr(
+ char *attr
+ );
+
+ PyObject*
+ PySetPosition(
+ PyObject* self,
+ PyObject* args,
+ PyObject* kwds
+ );
+
+ static
+ PyObject*
+ sPySetPosition(
+ PyObject* self,
+ PyObject* args,
+ PyObject* kwds
+ );
+
+ KX_PYMETHOD(KX_GameObject,GetPosition);
+ KX_PYMETHOD(KX_GameObject,GetLinearVelocity);
+ KX_PYMETHOD(KX_GameObject,GetVelocity);
+ KX_PYMETHOD(KX_GameObject,GetMass);
+ KX_PYMETHOD(KX_GameObject,GetReactionForce);
+ KX_PYMETHOD(KX_GameObject,GetOrientation);
+ KX_PYMETHOD(KX_GameObject,SetOrientation);
+ KX_PYMETHOD(KX_GameObject,SetVisible);
+ KX_PYMETHOD(KX_GameObject,SuspendDynamics);
+ KX_PYMETHOD(KX_GameObject,RestoreDynamics);
+ KX_PYMETHOD(KX_GameObject,EnableRigidBody);
+ KX_PYMETHOD(KX_GameObject,DisableRigidBody);
+ KX_PYMETHOD(KX_GameObject,ApplyImpulse);
+ KX_PYMETHOD(KX_GameObject,GetMesh);
+ KX_PYMETHOD(KX_GameObject,GetParent);
+ KX_PYMETHOD(KX_GameObject,GetPhysicsId);
+
+private :
+
+ /**
+ * Random internal function to convert python function arguments
+ * to 2 vectors.
+ * @return true if conversion was possible.
+ */
+
+ bool
+ ConvertPythonVectorArgs(
+ PyObject* args,
+ MT_Vector3& pos,
+ MT_Vector3& pos2
+ );
+
+};
+
+
+#endif //__KX_GAMEOBJECT
+
diff --git a/source/gameengine/Ketsji/KX_IInterpolator.h b/source/gameengine/Ketsji/KX_IInterpolator.h
new file mode 100644
index 00000000000..974f458681b
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_IInterpolator.h
@@ -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 *****
+ */
+#ifndef KX_IINTERPOLATOR_H
+#define KX_IINTERPOLATOR_H
+
+#include <vector>
+
+class KX_IInterpolator {
+public:
+ virtual ~KX_IInterpolator() {}
+
+ virtual void Execute(float currentTime) const = 0;
+};
+
+typedef std::vector<KX_IInterpolator *> T_InterpolatorList;
+
+#endif
diff --git a/source/gameengine/Ketsji/KX_IPOTransform.h b/source/gameengine/Ketsji/KX_IPOTransform.h
new file mode 100644
index 00000000000..9f9f4a92602
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_IPOTransform.h
@@ -0,0 +1,92 @@
+/**
+ * An abstract object you can move around in a 3d world, and has some logic
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 KX_IPOTRANSFORM_H
+#define KX_IPOTRANSFORM_H
+
+#include "MT_Transform.h"
+
+class KX_IPOTransform {
+public:
+ KX_IPOTransform() :
+ m_position(0.0, 0.0, 0.0),
+ m_eulerAngles(0.0, 0.0, 0.0),
+ m_scaling(1.0, 1.0, 1.0),
+ m_deltaPosition(0.0, 0.0, 0.0),
+ m_deltaEulerAngles(0.0, 0.0, 0.0),
+ m_deltaScaling(0.0, 0.0, 0.0)
+ {}
+
+ MT_Transform GetTransform() const {
+ return MT_Transform(m_position + m_deltaPosition,
+ MT_Matrix3x3(m_eulerAngles + m_deltaEulerAngles,
+ m_scaling + m_deltaScaling));
+ }
+
+ MT_Point3& GetPosition() { return m_position; }
+ MT_Vector3& GetEulerAngles() { return m_eulerAngles; }
+ MT_Vector3& GetScaling() { return m_scaling; }
+
+ const MT_Point3& GetPosition() const { return m_position; }
+ const MT_Vector3& GetEulerAngles() const { return m_eulerAngles; }
+ const MT_Vector3& GetScaling() const { return m_scaling; }
+
+ MT_Vector3& GetDeltaPosition() { return m_deltaPosition; }
+ MT_Vector3& GetDeltaEulerAngles() { return m_deltaEulerAngles; }
+ MT_Vector3& GetDeltaScaling() { return m_deltaScaling; }
+
+ void SetPosition(const MT_Point3& pos) { m_position = pos; }
+ void SetEulerAngles(const MT_Vector3& eul) { m_eulerAngles = eul; }
+ void SetScaling(const MT_Vector3& scaling) { m_scaling = scaling; }
+
+ void ClearDeltaStuff() {
+ m_deltaPosition.setValue(0.0, 0.0, 0.0);
+ m_deltaEulerAngles.setValue(0.0, 0.0, 0.0);
+ m_deltaScaling.setValue(0.0, 0.0, 0.0);
+ }
+
+protected:
+ MT_Point3 m_position;
+ MT_Vector3 m_eulerAngles;
+ MT_Vector3 m_scaling;
+ MT_Vector3 m_deltaPosition;
+ MT_Vector3 m_deltaEulerAngles;
+ MT_Vector3 m_deltaScaling;
+};
+
+#endif
+
+
+
+
diff --git a/source/gameengine/Ketsji/KX_IPO_SGController.cpp b/source/gameengine/Ketsji/KX_IPO_SGController.cpp
new file mode 100644
index 00000000000..ea5617b017a
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_IPO_SGController.cpp
@@ -0,0 +1,193 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * Scenegraph controller for ipos.
+ */
+
+#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
+
+#include "KX_IPO_SGController.h"
+#include "KX_ScalarInterpolator.h"
+#include "KX_GameObject.h"
+
+// All objects should start on frame 1! Will we ever need an object to
+// start on another frame, the 1.0 should change.
+KX_IpoSGController::KX_IpoSGController()
+: m_ipotime(1.0),
+ m_modify_position(false),
+ m_modify_orientation(false),
+ m_modify_scaling(false),
+ m_modified(true),
+ m_ipo_as_force(false),
+ m_force_ipo_acts_local(false)
+{
+ m_sumo_object = NULL;
+ m_game_object = NULL;
+
+}
+
+
+void KX_IpoSGController::SetOption(
+ int option,
+ int value)
+{
+ switch (option) {
+ case SG_CONTR_IPO_IPO_AS_FORCE:
+ m_ipo_as_force = (value != 0);
+ m_modified = true;
+ break;
+ case SG_CONTR_IPO_FORCES_ACT_LOCAL:
+ m_force_ipo_acts_local = (value != 0);
+ m_modified = true;
+ break;
+ default:
+ ; /* just ignore the rest */
+ }
+}
+
+ void
+KX_IpoSGController::UpdateSumoReference(
+ )
+{
+ if (m_game_object) {
+ m_sumo_object = 0;//m_game_object->GetSumoObject();
+ }
+}
+
+ void
+KX_IpoSGController::SetGameObject(
+ KX_GameObject* go
+ )
+{
+ m_game_object = go;
+}
+
+
+
+bool KX_IpoSGController::Update(double currentTime)
+{
+ if (m_modified)
+ {
+ T_InterpolatorList::iterator i;
+ for (i = m_interpolators.begin(); !(i == m_interpolators.end()); ++i) {
+ (*i)->Execute(m_ipotime);//currentTime);
+ }
+
+ SG_Spatial* ob = (SG_Spatial*)m_pObject;
+
+ if (m_modify_position) {
+ if (m_ipo_as_force) {
+ /*
+ UpdateSumoReference();
+ if (m_sumo_object && ob) {
+ m_sumo_object->applyCenterForce(m_force_ipo_acts_local ?
+ ob->GetWorldOrientation() * m_ipo_xform.GetPosition() :
+ m_ipo_xform.GetPosition());
+ m_sumo_object->calcXform();
+ }
+ */
+
+ } else {
+ ob->SetLocalPosition(m_ipo_xform.GetPosition());
+ }
+ }
+ if (m_modify_orientation) {
+ if (m_ipo_as_force) {
+ /*
+ UpdateSumoReference();
+ if (m_sumo_object && ob) {
+ m_sumo_object->applyTorque(m_force_ipo_acts_local ?
+ ob->GetWorldOrientation() * m_ipo_xform.GetEulerAngles() :
+ m_ipo_xform.GetEulerAngles());
+ m_sumo_object->calcXform();
+ }
+ */
+
+ } else {
+ ob->SetLocalOrientation(MT_Matrix3x3(m_ipo_xform.GetEulerAngles()));
+ }
+ }
+ if (m_modify_scaling)
+ ob->SetLocalScale(m_ipo_xform.GetScaling());
+
+ m_modified=false;
+ }
+ return false;
+}
+
+
+void KX_IpoSGController::AddInterpolator(KX_IInterpolator* interp)
+{
+ this->m_interpolators.push_back(interp);
+}
+
+SG_Controller* KX_IpoSGController::GetReplica(class SG_Node* destnode)
+{
+ KX_IpoSGController* iporeplica = new KX_IpoSGController(*this);
+ // clear object that ipo acts on in the replica.
+ iporeplica->ClearObject();
+
+ // dirty hack, ask Gino for a better solution in the ipo implementation
+ // hacken en zagen, in what we call datahiding, not written for replication :(
+
+ T_InterpolatorList oldlist = m_interpolators;
+ iporeplica->m_interpolators.clear();
+
+ T_InterpolatorList::iterator i;
+ for (i = oldlist.begin(); !(i == oldlist.end()); ++i) {
+ KX_ScalarInterpolator* copyipo = new KX_ScalarInterpolator(*((KX_ScalarInterpolator*)*i));
+ iporeplica->AddInterpolator(copyipo);
+
+ MT_Scalar* scaal = ((KX_ScalarInterpolator*)*i)->GetTarget();
+ int orgbase = (int)&m_ipo_xform;
+ int orgloc = (int)scaal;
+ int offset = orgloc-orgbase;
+ int newaddrbase = (int)&iporeplica->m_ipo_xform;
+ newaddrbase += offset;
+ MT_Scalar* blaptr = (MT_Scalar*) newaddrbase;
+ copyipo->SetNewTarget((MT_Scalar*)blaptr);
+ }
+
+ return iporeplica;
+}
+
+KX_IpoSGController::~KX_IpoSGController()
+{
+
+ T_InterpolatorList::iterator i;
+ for (i = m_interpolators.begin(); !(i == m_interpolators.end()); ++i) {
+ delete (*i);
+ }
+
+}
diff --git a/source/gameengine/Ketsji/KX_IPO_SGController.h b/source/gameengine/Ketsji/KX_IPO_SGController.h
new file mode 100644
index 00000000000..201a0051881
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_IPO_SGController.h
@@ -0,0 +1,111 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 __IPO_SGCONTROLLER_H
+#define __IPO_SGCONTROLLER_H
+
+#include "SG_Controller.h"
+#include "SG_Spatial.h"
+
+#include "KX_IPOTransform.h"
+#include "KX_IInterpolator.h"
+
+class KX_IpoSGController : public SG_Controller
+{
+ KX_IPOTransform m_ipo_xform;
+ T_InterpolatorList m_interpolators;
+ /* Why not bools? */
+ short m_modify_position : 1;
+ short m_modify_orientation : 1;
+ short m_modify_scaling : 1;
+
+ /** Interpret the ipo as a force rather than a displacement? */
+ bool m_ipo_as_force;
+
+ /** Ipo-as-force acts in local rather than in global coordinates? */
+ bool m_force_ipo_acts_local;
+
+ /** Were settings altered since the last update? */
+ bool m_modified;
+
+ /** Local time of this ipo.*/
+ double m_ipotime;
+
+ /** A reference to the sm scene an eventually associated physics object is in. */
+// class SM_Scene* m_sumo_scene;
+
+ /** A reference an eventually associated physics object is in. */
+ class SM_Object* m_sumo_object;
+
+ /** A reference to the original game object. */
+ class KX_GameObject* m_game_object;
+
+public:
+ KX_IpoSGController();
+
+ virtual ~KX_IpoSGController();
+
+ virtual SG_Controller* GetReplica(class SG_Node* destnode);
+
+ void
+ SetOption(
+ int option,
+ int value
+ );
+
+ /** Set sumo data. */
+ void UpdateSumoReference();
+ /** Set reference to the corresponding game object. */
+ void SetGameObject(class KX_GameObject*);
+
+ void SetModifyPosition(bool modifypos) {
+ m_modify_position=modifypos;
+ }
+ void SetModifyOrientation(bool modifyorient) {
+ m_modify_orientation=modifyorient;
+ }
+ void SetModifyScaling(bool modifyscale) {
+ m_modify_scaling=modifyscale;
+ }
+
+ KX_IPOTransform& GetIPOTransform()
+ {
+ return m_ipo_xform;
+ }
+ void AddInterpolator(KX_IInterpolator* interp);
+ virtual bool Update(double time);
+ virtual void SetSimulatedTime(double time)
+ {
+ m_ipotime = time;
+ m_modified = true;
+ }
+};
+#endif //__IPO_SGCONTROLLER_H
diff --git a/source/gameengine/Ketsji/KX_IPhysicsController.cpp b/source/gameengine/Ketsji/KX_IPhysicsController.cpp
new file mode 100644
index 00000000000..5ef22dd4f74
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_IPhysicsController.cpp
@@ -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 *****
+ */
+#include "KX_IPhysicsController.h"
+
+
+KX_IPhysicsController::KX_IPhysicsController(bool dyna,void* userdata)
+
+: m_bDyna(dyna),
+ m_userdata(userdata),
+ m_suspendDynamics(false)
+{
+};
+
+KX_IPhysicsController::~KX_IPhysicsController()
+{
+}
diff --git a/source/gameengine/Ketsji/KX_IPhysicsController.h b/source/gameengine/Ketsji/KX_IPhysicsController.h
new file mode 100644
index 00000000000..997317c0df5
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_IPhysicsController.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 __KX_IPHYSICSCONTROLLER_H
+#define __KX_IPHYSICSCONTROLLER_H
+
+#include "SG_Controller.h"
+#include "MT_Vector3.h"
+#include "MT_Point3.h"
+#include "MT_Matrix3x3.h"
+
+/**
+ Physics Controller, a special kind of Scene Graph Transformation Controller.
+ It get's callbacks from Physics in case a transformation change took place.
+ Each time the scene graph get's updated, the controller get's a chance
+ in the 'Update' method to reflect changed.
+*/
+
+class KX_IPhysicsController : public SG_Controller
+
+{
+
+protected:
+ bool m_bDyna;
+ bool m_suspendDynamics;
+ void* m_userdata;
+public:
+ KX_IPhysicsController(bool dyna,void* userdata);
+ virtual ~KX_IPhysicsController();
+
+
+ virtual void applyImpulse(const MT_Point3& attach, const MT_Vector3& impulse)=0;
+ virtual void SetObject (SG_IObject* object)=0;
+
+ virtual void RelativeTranslate(const MT_Vector3& dloc,bool local)=0;
+ virtual void RelativeRotate(const MT_Matrix3x3& drot,bool local)=0;
+ virtual void ApplyTorque(const MT_Vector3& torque,bool local)=0;
+ virtual void ApplyForce(const MT_Vector3& force,bool local)=0;
+ virtual MT_Vector3 GetLinearVelocity()=0;
+ virtual MT_Vector3 GetVelocity(const MT_Point3& pos)=0;
+ virtual void SetAngularVelocity(const MT_Vector3& ang_vel,bool local)=0;
+ virtual void SetLinearVelocity(const MT_Vector3& lin_vel,bool local)=0;
+ virtual void getOrientation(MT_Quaternion& orn)=0;
+ virtual void setOrientation(const MT_Quaternion& orn)=0;
+ virtual void setPosition(const MT_Point3& pos)=0;
+ virtual void setScaling(const MT_Vector3& scaling)=0;
+ virtual MT_Scalar GetMass()=0;
+ virtual MT_Vector3 getReactionForce()=0;
+ virtual void setRigidBody(bool rigid)=0;
+
+ virtual void SuspendDynamics()=0;
+ virtual void RestoreDynamics()=0;
+
+ virtual SG_Controller* GetReplica(class SG_Node* destnode)=0;
+
+ void SetDyna(bool isDynamic) {
+ m_bDyna = isDynamic;
+ }
+
+
+ virtual void SetSumoTransform(bool nondynaonly)=0;
+ // todo: remove next line !
+ virtual void SetSimulatedTime(double time)=0;
+
+ // call from scene graph to update
+ virtual bool Update(double time)=0;
+ void* GetUserData() { return m_userdata;}
+
+
+};
+#endif //__KX_IPHYSICSCONTROLLER_H
diff --git a/source/gameengine/Ketsji/KX_IScalarInterpolator.h b/source/gameengine/Ketsji/KX_IScalarInterpolator.h
new file mode 100644
index 00000000000..dd153f77205
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_IScalarInterpolator.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 KX_ISCALARINTERPOLATOR_H
+#define KX_ISCALARINTERPOLATOR_H
+
+class KX_IScalarInterpolator {
+public:
+ virtual ~KX_IScalarInterpolator() {}
+
+ virtual float GetValue(float currentTime) const = 0;
+};
+
+#endif
diff --git a/source/gameengine/Ketsji/KX_ISceneConverter.h b/source/gameengine/Ketsji/KX_ISceneConverter.h
new file mode 100644
index 00000000000..fcb73fa8872
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_ISceneConverter.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 __KX_ISCENECONVERTER_H
+#define __KX_ISCENECONVERTER_H
+
+#include "STR_String.h"
+
+#include "KX_Python.h"
+
+class KX_ISceneConverter
+{
+
+public:
+ KX_ISceneConverter() {}
+ virtual ~KX_ISceneConverter () {};
+
+ /*
+ scenename: name of the scene to be converted,
+ if the scenename is empty, convert the 'default' scene (whatever this means)
+ destinationscene: pass an empty scene, everything goes into this
+ dictobj: python dictionary (for pythoncontrollers)
+ */
+ virtual void ConvertScene(const STR_String& scenename,
+ class KX_Scene* destinationscene,
+ PyObject* dictobj,
+ class SCA_IInputDevice* keyinputdev,
+ class RAS_IRenderTools* rendertools,
+ class RAS_ICanvas* canvas)=0;
+
+ virtual void SetAlwaysUseExpandFraming(bool to_what) = 0;
+
+ virtual void SetNewFileName(const STR_String& filename) = 0;
+ virtual bool TryAndLoadNewFile() = 0;
+};
+#endif //__KX_ISCENECONVERTER_H
diff --git a/source/gameengine/Ketsji/KX_ISystem.h b/source/gameengine/Ketsji/KX_ISystem.h
new file mode 100644
index 00000000000..1ab3e521418
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_ISystem.h
@@ -0,0 +1,55 @@
+/**
+* Abstract system
+*
+* $Id$
+*
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 __KX_ISYSTEM
+#define __KX_ISYSTEM
+
+#include <vector>
+using namespace std;
+
+#include "STR_String.h"
+
+/**
+ * System Abstraction, needed only for getting some timing stuff from the host.
+ */
+class KX_ISystem
+{
+public:
+ KX_ISystem() {};
+ virtual ~KX_ISystem() {};
+
+ virtual double GetTimeInSeconds()=0;
+};
+
+#endif
diff --git a/source/gameengine/Ketsji/KX_IpoActuator.cpp b/source/gameengine/Ketsji/KX_IpoActuator.cpp
new file mode 100644
index 00000000000..1e351834822
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_IpoActuator.cpp
@@ -0,0 +1,643 @@
+/**
+ * Do Ipo stuff
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "KX_IpoActuator.h"
+#include "KX_GameObject.h"
+
+
+/* ------------------------------------------------------------------------- */
+/* Type strings */
+/* ------------------------------------------------------------------------- */
+
+STR_String KX_IpoActuator::S_KX_ACT_IPO_PLAY_STRING = "Play";
+STR_String KX_IpoActuator::S_KX_ACT_IPO_PINGPONG_STRING = "PingPong";
+STR_String KX_IpoActuator::S_KX_ACT_IPO_FLIPPER_STRING = "Flipper";
+STR_String KX_IpoActuator::S_KX_ACT_IPO_LOOPSTOP_STRING = "LoopStop";
+STR_String KX_IpoActuator::S_KX_ACT_IPO_LOOPEND_STRING = "LoopEnd";
+STR_String KX_IpoActuator::S_KX_ACT_IPO_KEY2KEY_STRING = "Key2key";
+STR_String KX_IpoActuator::S_KX_ACT_IPO_FROM_PROP_STRING = "FromProp";
+
+/* ------------------------------------------------------------------------- */
+/* Native functions */
+/* ------------------------------------------------------------------------- */
+/** Another poltergeist? This seems to be a very transient class... */
+class CIpoAction : public CAction
+{
+ float m_curtime;
+ bool m_resurse;
+ KX_GameObject* m_gameobj;
+ bool m_ipo_as_force;
+ bool m_force_ipo_local;
+
+public:
+ CIpoAction(KX_GameObject* gameobj,
+ float curtime,
+ bool recurse,
+ bool ipo_as_force,
+ bool force_ipo_local) :
+ m_curtime(curtime) ,
+ m_resurse(recurse),
+ m_gameobj(gameobj),
+ m_ipo_as_force(ipo_as_force),
+ m_force_ipo_local(force_ipo_local)
+ {
+ /* intentionally empty */
+ };
+
+ virtual void Execute() const
+ {
+ m_gameobj->UpdateIPO(
+ m_curtime,
+ m_resurse,
+ m_ipo_as_force,
+ m_force_ipo_local);
+ };
+
+};
+
+
+KX_IpoActuator::KX_IpoActuator(SCA_IObject* gameobj,
+ const STR_String& propname,
+ float starttime,
+ float endtime,
+ bool recurse,
+ int acttype,
+ bool ipo_as_force,
+ bool force_ipo_local,
+ PyTypeObject* T)
+ : SCA_IActuator(gameobj,T),
+ m_starttime (starttime),
+ m_endtime(endtime) ,
+ m_localtime(starttime),
+ m_recurse(recurse),
+ m_type((IpoActType)acttype) ,
+ m_direction(1),
+ m_bNegativeEvent(false),
+ m_propname(propname),
+ m_ipo_as_force(ipo_as_force),
+ m_force_ipo_local(force_ipo_local)
+{
+ // intentionally empty
+}
+
+void KX_IpoActuator::SetStart(float starttime)
+{
+ m_starttime=starttime;
+}
+
+void KX_IpoActuator::SetEnd(float endtime)
+{
+ m_endtime=endtime;
+}
+
+
+bool KX_IpoActuator::Update(double curtime,double delta_time)
+{
+ SCA_IActuator::Update(curtime,delta_time);
+ // result = true if animation has to be continued, false if animation stops
+ // maybe there are events for us in the queue !
+
+
+ bool bNegativeEvent = false;
+ int numevents = m_events.size();
+
+ for (vector<CValue*>::iterator i=m_events.end(); !(i==m_events.begin());)
+ {
+ i--;
+ if ((*i)->GetNumber() == 0.0f)
+ {
+ int ka=0;
+ bNegativeEvent = true;
+ }
+ (*i)->Release();
+ m_events.pop_back();
+ }
+
+ if (bNegativeEvent)
+ {
+ RemoveAllEvents();
+ }
+
+
+ double start_smaller_then_end = ( m_starttime < m_endtime ? 1.0 : -1.0);
+
+ double deltaframetime = start_smaller_then_end * delta_time * KX_FIXED_FRAME_PER_SEC;
+
+ bool result=true;
+
+ switch (m_type)
+ {
+
+ case KX_ACT_IPO_PLAY:
+ {
+
+ if (start_smaller_then_end > 0.0)
+ result = (m_localtime < m_endtime && !(m_localtime == m_starttime && bNegativeEvent));
+ else
+ result = (m_localtime > m_endtime && !(m_localtime == m_starttime && bNegativeEvent));
+ if (result)
+ {
+ m_localtime += m_direction * deltaframetime;
+
+ /* Perform clamping */
+ if ((m_localtime*start_smaller_then_end)>(m_endtime*start_smaller_then_end))
+ m_localtime=m_endtime;
+
+ CIpoAction ipoaction(
+ (KX_GameObject*)GetParent(),
+ m_localtime,
+ m_recurse,
+ m_ipo_as_force,
+ m_force_ipo_local);
+ GetParent()->Execute(ipoaction);
+ } else
+ {
+ m_localtime=m_starttime;
+ m_direction=1;
+ }
+ break;
+ }
+ case KX_ACT_IPO_PINGPONG:
+ {
+ result = true;
+ if (bNegativeEvent && ((m_localtime == m_starttime )|| (m_localtime == m_endtime)))
+ {
+ result = false;
+ } else
+ {
+ m_localtime += m_direction * deltaframetime;
+ }
+
+ if (m_localtime*start_smaller_then_end < m_starttime*start_smaller_then_end)
+ {
+ m_localtime = m_starttime;
+ result = false;
+ m_direction = 1;
+ }else
+ if (m_localtime*start_smaller_then_end > m_endtime*start_smaller_then_end)
+ {
+ m_localtime = m_endtime;
+ result = false;
+ m_direction = -1;
+ }
+
+ CIpoAction ipoaction(
+ (KX_GameObject*) GetParent(),
+ m_localtime,
+ m_recurse,
+ m_ipo_as_force,
+ m_force_ipo_local);
+ GetParent()->Execute(ipoaction);
+ break;
+ }
+
+ case KX_ACT_IPO_FLIPPER:
+ {
+ result = true;
+ if (numevents)
+ {
+ if (bNegativeEvent)
+ m_direction = -1;
+ else
+ m_direction = 1;
+ }
+
+ m_localtime += m_direction * deltaframetime;
+
+ if (m_localtime*start_smaller_then_end > m_endtime*start_smaller_then_end)
+ {
+ m_localtime = m_endtime;
+ } else
+ if (m_localtime*start_smaller_then_end < m_starttime*start_smaller_then_end)
+ {
+ m_localtime = m_starttime;
+ result = false;
+ }
+
+ CIpoAction ipoaction(
+ (KX_GameObject*) GetParent(),
+ m_localtime,
+ m_recurse,
+ m_ipo_as_force,
+ m_force_ipo_local);
+ GetParent()->Execute(ipoaction);
+ break;
+ }
+
+ case KX_ACT_IPO_LOOPSTOP:
+ {
+ if (numevents)
+ {
+ if (bNegativeEvent)
+ {
+ result = false;
+ m_bNegativeEvent = false;
+ numevents = 0;
+ }
+ } // fall through to loopend, and quit the ipo animation immediatly
+ }
+
+ case KX_ACT_IPO_LOOPEND:
+ {
+ if (numevents){
+ if (bNegativeEvent){
+ m_bNegativeEvent = true;
+ }
+ }
+
+ if (bNegativeEvent && m_localtime == m_starttime){
+ result = false;
+ }
+ else{
+ if (m_localtime*start_smaller_then_end < m_endtime*start_smaller_then_end){
+ m_localtime += m_direction * deltaframetime;
+ }
+ else{
+ if (!m_bNegativeEvent){
+ /* Perform wraparound */
+ float slop = m_localtime-m_endtime;
+ float length = fabs(m_starttime-m_endtime);
+ m_localtime = m_starttime + (slop - (int(slop/length)*(int(length))));
+
+ }
+ else
+ {
+ /* Perform clamping */
+ if ((m_localtime*start_smaller_then_end)>(m_endtime*start_smaller_then_end))
+ m_localtime=m_endtime;
+
+ result = false;
+ m_bNegativeEvent = false;
+ }
+ }
+ }
+ CIpoAction ipoaction(
+ (KX_GameObject*) GetParent(),
+ m_localtime,
+ m_recurse,
+ m_ipo_as_force,
+ m_force_ipo_local);
+ GetParent()->Execute(ipoaction);
+ break;
+ }
+ case KX_ACT_IPO_KEY2KEY:
+ {
+ // not implemented yet
+ result = false;
+ break;
+ }
+ case KX_ACT_IPO_FROM_PROP:
+ {
+ result = !bNegativeEvent;
+
+ CValue* propval = GetParent()->GetProperty(m_propname);
+ if (propval)
+ {
+ m_localtime = propval->GetNumber();
+ CIpoAction ipoaction(
+ (KX_GameObject*) GetParent(),
+ m_localtime,
+ m_recurse,
+ m_ipo_as_force,
+ m_force_ipo_local);
+ GetParent()->Execute(ipoaction);
+
+ } else
+ {
+ result = false;
+ }
+ break;
+ }
+
+ default:
+ {
+ result = false;
+ }
+ }
+
+ return result;
+}
+
+KX_IpoActuator::IpoActType KX_IpoActuator::string2mode(char* modename) {
+ IpoActType res = KX_ACT_IPO_NODEF;
+
+ if (modename == S_KX_ACT_IPO_PLAY_STRING) {
+ res = KX_ACT_IPO_PLAY;
+ } else if (modename == S_KX_ACT_IPO_PINGPONG_STRING) {
+ res = KX_ACT_IPO_PINGPONG;
+ } else if (modename == S_KX_ACT_IPO_FLIPPER_STRING) {
+ res = KX_ACT_IPO_FLIPPER;
+ } else if (modename == S_KX_ACT_IPO_LOOPSTOP_STRING) {
+ res = KX_ACT_IPO_LOOPSTOP;
+ } else if (modename == S_KX_ACT_IPO_LOOPEND_STRING) {
+ res = KX_ACT_IPO_LOOPEND;
+ } else if (modename == S_KX_ACT_IPO_KEY2KEY_STRING) {
+ res = KX_ACT_IPO_KEY2KEY;
+ } else if (modename == S_KX_ACT_IPO_FROM_PROP_STRING) {
+ res = KX_ACT_IPO_FROM_PROP;
+ }
+
+ return res;
+}
+
+/* ------------------------------------------------------------------------- */
+/* Python functions */
+/* ------------------------------------------------------------------------- */
+
+
+
+/* Integration hooks ------------------------------------------------------- */
+PyTypeObject KX_IpoActuator::Type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0,
+ "KX_IpoActuator",
+ sizeof(KX_IpoActuator),
+ 0,
+ PyDestructor,
+ 0,
+ __getattr,
+ __setattr,
+ 0, //&MyPyCompare,
+ __repr,
+ 0, //&cvalue_as_number,
+ 0,
+ 0,
+ 0,
+ 0
+};
+
+PyParentObject KX_IpoActuator::Parents[] = {
+ &KX_IpoActuator::Type,
+ &SCA_IActuator::Type,
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
+};
+
+PyMethodDef KX_IpoActuator::Methods[] = {
+ {"set", (PyCFunction) KX_IpoActuator::sPySet,
+ METH_VARARGS, Set_doc},
+ {"setProperty", (PyCFunction) KX_IpoActuator::sPySetProperty,
+ METH_VARARGS, SetProperty_doc},
+ {"setStart", (PyCFunction) KX_IpoActuator::sPySetStart,
+ METH_VARARGS, SetStart_doc},
+ {"getStart", (PyCFunction) KX_IpoActuator::sPyGetStart,
+ METH_VARARGS, GetStart_doc},
+ {"setEnd", (PyCFunction) KX_IpoActuator::sPySetEnd,
+ METH_VARARGS, SetEnd_doc},
+ {"getEnd", (PyCFunction) KX_IpoActuator::sPyGetEnd,
+ METH_VARARGS, GetEnd_doc},
+ {"setIpoAsForce", (PyCFunction) KX_IpoActuator::sPySetIpoAsForce,
+ METH_VARARGS, SetIpoAsForce_doc},
+ {"getIpoAsForce", (PyCFunction) KX_IpoActuator::sPyGetIpoAsForce,
+ METH_VARARGS, GetIpoAsForce_doc},
+ {"setType", (PyCFunction) KX_IpoActuator::sPySetType,
+ METH_VARARGS, SetType_doc},
+ {"getType", (PyCFunction) KX_IpoActuator::sPyGetType,
+ METH_VARARGS, GetType_doc},
+ {NULL,NULL} //Sentinel
+};
+
+PyObject* KX_IpoActuator::_getattr(char* attr) {
+ _getattr_up(SCA_IActuator);
+}
+
+
+
+/* set --------------------------------------------------------------------- */
+char KX_IpoActuator::Set_doc[] =
+"set(mode, startframe, endframe, force?)\n"
+"\t - mode: Play, PingPong, Flipper, LoopStop, LoopEnd or FromProp (string)\n"
+"\t - startframe: first frame to use (int)\n"
+"\t - endframe : last frame to use (int)\n"
+"\t - force? : interpret this ipo as a force? (KX_TRUE, KX_FALSE)"
+"\tSet the properties of the actuator.\n";
+PyObject* KX_IpoActuator::PySet(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ /* sets modes PLAY, PINGPONG, FLIPPER, LOOPSTOP, LOOPEND */
+ /* arg 1 = mode string, arg 2 = startframe, arg3 = stopframe, */
+ /* arg4 = force toggle */
+ char* mode;
+ int forceToggle;
+ IpoActType modenum;
+ int startFrame, stopFrame;
+ if(!PyArg_ParseTuple(args, "siii", &mode, &startFrame,
+ &stopFrame, &forceToggle)) {
+ return NULL;
+ }
+ modenum = string2mode(mode);
+
+ switch (modenum) {
+ case KX_ACT_IPO_PLAY:
+ case KX_ACT_IPO_PINGPONG:
+ case KX_ACT_IPO_FLIPPER:
+ case KX_ACT_IPO_LOOPSTOP:
+ case KX_ACT_IPO_LOOPEND:
+ m_type = modenum;
+ m_starttime = startFrame;
+ m_endtime = stopFrame;
+ m_ipo_as_force = PyArgToBool(forceToggle);
+ break;
+ default:
+ ; /* error */
+ }
+
+ Py_Return;
+}
+
+/* set property ----------------------------------------------------------- */
+char KX_IpoActuator::SetProperty_doc[] =
+"setProperty(propname)\n"
+"\t - propname: name of the property (string)\n"
+"\tSet the property to be used in FromProp mode.\n";
+PyObject* KX_IpoActuator::PySetProperty(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ /* mode is implicit here, but not supported yet... */
+ /* args: property */
+ char *propertyName;
+ if(!PyArg_ParseTuple(args, "s", &propertyName)) {
+ return NULL;
+ }
+
+ Py_Return;
+}
+
+/* 4. setStart: */
+char KX_IpoActuator::SetStart_doc[] =
+"setStart(frame)\n"
+"\t - frame: first frame to use (int)\n"
+"\tSet the frame from which the ipo starts playing.\n";
+PyObject* KX_IpoActuator::PySetStart(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ float startArg;
+ if(!PyArg_ParseTuple(args, "f", &startArg)) {
+ return NULL;
+ }
+
+ m_starttime = startArg;
+
+ Py_Return;
+}
+/* 5. getStart: */
+char KX_IpoActuator::GetStart_doc[] =
+"getStart()\n"
+"\tReturns the frame from which the ipo starts playing.\n";
+PyObject* KX_IpoActuator::PyGetStart(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ return PyFloat_FromDouble(m_starttime);
+}
+
+/* 6. setEnd: */
+char KX_IpoActuator::SetEnd_doc[] =
+"setEnd(frame)\n"
+"\t - frame: last frame to use (int)\n"
+"\tSet the frame at which the ipo stops playing.\n";
+PyObject* KX_IpoActuator::PySetEnd(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ float endArg;
+ if(!PyArg_ParseTuple(args, "f", &endArg)) {
+ return NULL;
+ }
+
+ m_endtime = endArg;
+
+ Py_Return;
+}
+/* 7. getEnd: */
+char KX_IpoActuator::GetEnd_doc[] =
+"getEnd()\n"
+"\tReturns the frame at which the ipo stops playing.\n";
+PyObject* KX_IpoActuator::PyGetEnd(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ return PyFloat_FromDouble(m_endtime);
+}
+
+/* 6. setIpoAsForce: */
+char KX_IpoActuator::SetIpoAsForce_doc[] =
+"setIpoAsForce(force?)\n"
+"\t - force? : interpret this ipo as a force? (KX_TRUE, KX_FALSE)\n"
+"\tSet whether to interpret the ipo as a force rather than a displacement.\n";
+PyObject* KX_IpoActuator::PySetIpoAsForce(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ int boolArg;
+
+ if (!PyArg_ParseTuple(args, "i", &boolArg)) {
+ return NULL;
+ }
+
+ m_ipo_as_force = PyArgToBool(boolArg);
+
+ Py_Return;
+}
+/* 7. getIpoAsForce: */
+char KX_IpoActuator::GetIpoAsForce_doc[] =
+"getIpoAsForce()\n"
+"\tReturns whether to interpret the ipo as a force rather than a displacement.\n";
+PyObject* KX_IpoActuator::PyGetIpoAsForce(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ return BoolToPyArg(m_ipo_as_force);
+}
+
+/* 8. setType: */
+char KX_IpoActuator::SetType_doc[] =
+"setType(mode)\n"
+"\t - mode: Play, PingPong, Flipper, LoopStop, LoopEnd or FromProp (string)\n"
+"\tSet the operation mode of the actuator.\n";
+PyObject* KX_IpoActuator::PySetType(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ int typeArg;
+
+ if (!PyArg_ParseTuple(args, "i", &typeArg)) {
+ return NULL;
+ }
+
+ if ( (typeArg > KX_ACT_IPO_NODEF)
+ && (typeArg < KX_ACT_IPO_KEY2KEY) ) {
+ m_type = (IpoActType) typeArg;
+ }
+
+ Py_Return;
+}
+/* 9. getType: */
+char KX_IpoActuator::GetType_doc[] =
+"getType()\n"
+"\tReturns the operation mode of the actuator.\n";
+PyObject* KX_IpoActuator::PyGetType(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ return PyInt_FromLong(m_type);
+}
+
+/* 10. setForceIpoActsLocal: */
+char KX_IpoActuator::SetForceIpoActsLocal_doc[] =
+"setForceIpoActsLocal(local?)\n"
+"\t - local? : Apply the ipo-as-force in the object's local\n"
+"\t coordinates? (KX_TRUE, KX_FALSE)\n"
+"\tSet whether to apply the force in the object's local\n"
+"\tcoordinates rather than the world global coordinates.\n";
+PyObject* KX_IpoActuator::PySetForceIpoActsLocal(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ int boolArg;
+
+ if (!PyArg_ParseTuple(args, "i", &boolArg)) {
+ return NULL;
+ }
+
+ m_force_ipo_local = PyArgToBool(boolArg);
+
+ Py_Return;
+}
+/* 11. getForceIpoActsLocal: */
+char KX_IpoActuator::GetForceIpoActsLocal_doc[] =
+"getForceIpoActsLocal()\n"
+"\tReturn whether to apply the force in the object's local\n"
+"\tcoordinates rather than the world global coordinates.\n";
+PyObject* KX_IpoActuator::PyGetForceIpoActsLocal(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ return BoolToPyArg(m_force_ipo_local);
+}
+
+
+/* eof */
diff --git a/source/gameengine/Ketsji/KX_IpoActuator.h b/source/gameengine/Ketsji/KX_IpoActuator.h
new file mode 100644
index 00000000000..134de3817b4
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_IpoActuator.h
@@ -0,0 +1,141 @@
+/**
+ * Do an object ipo
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 __KX_IPOACTUATOR
+#define __KX_IPOACTUATOR
+
+#include "SCA_IActuator.h"
+
+class KX_IpoActuator : public SCA_IActuator
+{
+ Py_Header;
+
+ bool m_bNegativeEvent;
+
+ /** Begin frame of the ipo. */
+ float m_starttime;
+
+ /** End frame of the ipo. */
+ float m_endtime;
+
+ /** Include children in the transforms? */
+ bool m_recurse;
+
+ /** Current active frame of the ipo. */
+ float m_localtime;
+
+ /** play backwards or forwards? (positive means forward). */
+ float m_direction;
+
+ /** Name of the property (only used in from_prop mode). */
+ STR_String m_propname;
+
+ /** Interpret the ipo as a force? */
+ bool m_ipo_as_force;
+
+ /** Apply a force-ipo locally? */
+ bool m_force_ipo_local;
+
+public:
+ enum IpoActType
+ {
+ KX_ACT_IPO_NODEF = 0,
+ KX_ACT_IPO_PLAY,
+ KX_ACT_IPO_PINGPONG,
+ KX_ACT_IPO_FLIPPER,
+ KX_ACT_IPO_LOOPSTOP,
+ KX_ACT_IPO_LOOPEND,
+ KX_ACT_IPO_KEY2KEY,
+ KX_ACT_IPO_FROM_PROP,
+ KX_ACT_IPO_MAX
+ };
+
+ static STR_String S_KX_ACT_IPO_PLAY_STRING;
+ static STR_String S_KX_ACT_IPO_PINGPONG_STRING;
+ static STR_String S_KX_ACT_IPO_FLIPPER_STRING;
+ static STR_String S_KX_ACT_IPO_LOOPSTOP_STRING;
+ static STR_String S_KX_ACT_IPO_LOOPEND_STRING;
+ static STR_String S_KX_ACT_IPO_KEY2KEY_STRING;
+ static STR_String S_KX_ACT_IPO_FROM_PROP_STRING;
+
+ IpoActType string2mode(char* modename);
+
+ IpoActType m_type;
+
+ KX_IpoActuator(SCA_IObject* gameobj,
+ const STR_String& propname,
+ float starttime,
+ float endtime,
+ bool recurse,
+ int acttype,
+ bool ipo_as_force,
+ bool force_ipo_local,
+ PyTypeObject* T=&Type);
+ virtual ~KX_IpoActuator() {};
+
+ virtual CValue* GetReplica() {
+ KX_IpoActuator* replica = new KX_IpoActuator(*this);//m_float,GetName());
+ replica->ProcessReplica();
+ // this will copy properties and so on...
+ CValue::AddDataToReplica(replica);
+ return replica;
+ };
+
+ void SetStart(float starttime);
+ void SetEnd(float endtime);
+ virtual bool Update(double curtime,double deltatime);
+
+ /* --------------------------------------------------------------------- */
+ /* Python interface ---------------------------------------------------- */
+ /* --------------------------------------------------------------------- */
+
+ virtual PyObject* _getattr(char *attr);
+ //KX_PYMETHOD_DOC
+ KX_PYMETHOD_DOC(KX_IpoActuator,Set);
+ KX_PYMETHOD_DOC(KX_IpoActuator,SetProperty);
+/* KX_PYMETHOD_DOC(KX_IpoActuator,SetKey2Key); */
+ KX_PYMETHOD_DOC(KX_IpoActuator,SetStart);
+ KX_PYMETHOD_DOC(KX_IpoActuator,GetStart);
+ KX_PYMETHOD_DOC(KX_IpoActuator,SetEnd);
+ KX_PYMETHOD_DOC(KX_IpoActuator,GetEnd);
+ KX_PYMETHOD_DOC(KX_IpoActuator,SetIpoAsForce);
+ KX_PYMETHOD_DOC(KX_IpoActuator,GetIpoAsForce);
+ KX_PYMETHOD_DOC(KX_IpoActuator,SetType);
+ KX_PYMETHOD_DOC(KX_IpoActuator,GetType);
+ KX_PYMETHOD_DOC(KX_IpoActuator,SetForceIpoActsLocal);
+ KX_PYMETHOD_DOC(KX_IpoActuator,GetForceIpoActsLocal);
+
+};
+
+#endif //__KX_IPOACTUATOR
diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
new file mode 100644
index 00000000000..c03e4e3d964
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
@@ -0,0 +1,1250 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 engine ties all game modules together.
+ */
+#ifdef WIN32
+#pragma warning (disable : 4786)
+#endif //WIN32
+
+#include <iostream>
+
+#include "KX_KetsjiEngine.h"
+
+#include "ListValue.h"
+#include "IntValue.h"
+#include "VectorValue.h"
+#include "BoolValue.h"
+#include "FloatValue.h"
+
+#define KX_NUM_ITERATIONS 4
+#include "RAS_BucketManager.h"
+#include "RAS_Rect.h"
+#include "RAS_IRasterizer.h"
+#include "RAS_IRenderTools.h"
+#include "RAS_ICanvas.h"
+#include "STR_String.h"
+#include "MT_Vector3.h"
+#include "MT_Transform.h"
+#include "SCA_IInputDevice.h"
+#include "KX_Scene.h"
+#include "MT_CmMatrix4x4.h"
+#include "KX_Camera.h"
+#include "KX_PythonInit.h"
+#include "KX_PyConstraintBinding.h"
+#include "PHY_IPhysicsEnvironment.h"
+
+#include "SND_Scene.h"
+#include "SND_IAudioDevice.h"
+
+#include "NG_NetworkScene.h"
+#include "NG_NetworkDeviceInterface.h"
+
+#include "KX_WorldInfo.h"
+#include "KX_ISceneConverter.h"
+#include "KX_TimeCategoryLogger.h"
+
+#include "RAS_FramingManager.h"
+
+// If define: little test for Nzc: guarded drawing. If the canvas is
+// not valid, skip rendering this frame.
+//#define NZC_GUARDED_OUTPUT
+
+
+const char KX_KetsjiEngine::m_profileLabels[tc_numCategories][15] = {
+ "Physics:", // tc_physics
+ "Logic", // tc_logic
+ "Network:", // tc_network
+ "Scenegraph:", // tc_scenegraph
+ "Sound:", // tc_sound
+ "Rasterizer:", // tc_rasterizer
+ "Services:", // tc_services
+ "Overhead:", // tc_overhead
+ "Outside:" // tc_outside
+};
+
+
+
+
+/**
+ * Constructor of the Ketsji Engine
+ */
+KX_KetsjiEngine::KX_KetsjiEngine(KX_ISystem* system)
+: m_bInitialized(false),
+ m_activecam(0),
+ m_rasterizer(NULL)
+{
+ m_kxsystem = system;
+ m_bFixedTime = false;
+
+ // Initialize the time logger
+ m_logger = new KX_TimeCategoryLogger (25);
+
+ for (int i = tc_first; i < tc_numCategories; i++)
+ m_logger->AddCategory((KX_TimeCategory)i);
+
+ // Set up timing info display variables
+ m_show_framerate = false;
+ m_show_profile = false;
+ m_show_debug_properties = false;
+ m_propertiesPresent = false;
+
+ // Default behavior is to hide the cursor every frame.
+ m_hideCursor = false;
+
+ m_overrideFrameColor = false;
+ m_overrideFrameColorR = (float)0;
+ m_overrideFrameColorG = (float)0;
+ m_overrideFrameColorB = (float)0;
+
+ m_cameraZoom = 1.0;
+ m_drawingmode = 5; /* textured drawing mode */
+ m_overrideCam = false;
+
+ m_exitcode = KX_EXIT_REQUEST_NO_REQUEST;
+ m_exitstring = "";
+}
+
+
+
+/**
+ * Destructor of the Ketsji Engine, release all memory
+ */
+KX_KetsjiEngine::~KX_KetsjiEngine()
+{
+ if (m_logger)
+ delete m_logger;
+}
+
+
+
+void KX_KetsjiEngine::SetKeyboardDevice(SCA_IInputDevice* keyboarddevice)
+{
+ assert(keyboarddevice);
+ m_keyboarddevice = keyboarddevice;
+}
+
+
+
+void KX_KetsjiEngine::SetMouseDevice(SCA_IInputDevice* mousedevice)
+{
+ assert(mousedevice);
+ m_mousedevice = mousedevice;
+}
+
+
+
+void KX_KetsjiEngine::SetNetworkDevice(NG_NetworkDeviceInterface* networkdevice)
+{
+ assert(networkdevice);
+ m_networkdevice = networkdevice;
+}
+
+
+
+void KX_KetsjiEngine::SetAudioDevice(SND_IAudioDevice* audiodevice)
+{
+ assert(audiodevice);
+ m_audiodevice = audiodevice;
+}
+
+
+
+void KX_KetsjiEngine::SetCanvas(RAS_ICanvas* canvas)
+{
+ assert(canvas);
+ m_canvas = canvas;
+}
+
+
+
+void KX_KetsjiEngine::SetRenderTools(RAS_IRenderTools* rendertools)
+{
+ assert(rendertools);
+ m_rendertools = rendertools;
+}
+
+
+
+void KX_KetsjiEngine::SetRasterizer(RAS_IRasterizer* rasterizer)
+{
+ assert(rasterizer);
+ m_rasterizer = rasterizer;
+}
+
+
+
+void KX_KetsjiEngine::SetPythonDictionary(PyObject* pythondictionary)
+{
+ assert(pythondictionary);
+ m_pythondictionary = pythondictionary;
+}
+
+
+
+void KX_KetsjiEngine::SetSceneConverter(KX_ISceneConverter* sceneconverter)
+{
+ assert(sceneconverter);
+ m_sceneconverter = sceneconverter;
+}
+
+
+
+/**
+ * Ketsji Init(), Initializes datastructures and converts data from
+ * Blender into Ketsji native (realtime) format also sets up the
+ * graphics context
+ */
+void KX_KetsjiEngine::StartEngine()
+{
+ m_previoustime = 0.0;
+ m_missedtime = 0.0;
+ m_firstframe = true;
+
+ // for all scenes, initialize the scenegraph for the first time
+ m_lasttime = m_kxsystem->GetTimeInSeconds()*100.0;
+
+ m_bInitialized = true;
+}
+
+
+
+#define DELTALENGTH 25
+
+double KX_KetsjiEngine::CalculateAverage(double newdelta)
+{
+ if (m_deltatimes.size() < DELTALENGTH)
+ {
+ m_deltatimes.push_back(newdelta);
+ } else
+ {
+ //
+ double totaltime = 0.0;
+ double newlasttime,lasttime = newdelta;
+ double peakmin = 10000;
+ double peakmax = -10000;
+
+ for (int i=m_deltatimes.size()-1;i>=0;i--)
+ { newlasttime = m_deltatimes[i];
+ totaltime += newlasttime;
+ if (peakmin > newlasttime)
+ peakmin = newlasttime;
+ if (peakmax < newlasttime)
+ peakmax = newlasttime;
+
+ m_deltatimes[i] = lasttime;
+ lasttime = newlasttime;
+ };
+ double averagetime;
+
+ if (peakmin < peakmax)
+ {
+ averagetime = ((totaltime - peakmin) - peakmax) / (double) (m_deltatimes.size()-2);
+ } else
+ {
+ averagetime = totaltime / (double) m_deltatimes.size();
+ }
+ return averagetime;
+ }
+
+ return newdelta;
+}
+
+
+
+bool KX_KetsjiEngine::BeginFrame()
+{
+ bool result = false;
+
+ RAS_Rect vp;
+ KX_Scene* firstscene = *m_scenes.begin();
+ const RAS_FrameSettings &framesettings = firstscene->GetFramingType();
+
+ // set the area used for rendering
+ m_rasterizer->SetRenderArea();
+
+ RAS_FramingManager::ComputeViewport(framesettings, m_canvas->GetDisplayArea(), vp);
+
+ if (m_canvas->BeginDraw())
+ {
+ result = true;
+
+ m_canvas->SetViewPort(vp.GetLeft(), vp.GetBottom(), vp.GetRight(), vp.GetTop());
+ SetBackGround( firstscene->GetWorldInfo() );
+ m_rasterizer->BeginFrame( m_drawingmode , m_kxsystem->GetTimeInSeconds());
+ m_rendertools->BeginFrame( m_rasterizer);
+ }
+
+ return result;
+}
+
+
+void KX_KetsjiEngine::EndFrame()
+{
+ // Show profiling info
+ m_logger->StartLog(tc_overhead, m_kxsystem->GetTimeInSeconds(), true);
+ if (m_show_framerate || m_show_profile || (m_show_debug_properties && m_propertiesPresent))
+ {
+ RenderDebugProperties();
+ }
+ // Go to next profiling measurement, time spend after this call is shown in the next frame.
+ m_logger->NextMeasurement(m_kxsystem->GetTimeInSeconds());
+
+ m_logger->StartLog(tc_rasterizer, m_kxsystem->GetTimeInSeconds(), true);
+ m_rasterizer->EndFrame();
+ // swap backbuffer (drawing into this buffer) <-> front/visible buffer
+ m_rasterizer->SwapBuffers();
+ m_rendertools->EndFrame(m_rasterizer);
+
+ m_canvas->EndDraw();
+}
+
+
+
+void KX_KetsjiEngine::NextFrame()
+{
+ m_logger->StartLog(tc_services, m_kxsystem->GetTimeInSeconds(), true);
+
+ double deltatime = 0.02;
+ double curtime;
+
+ if (m_bFixedTime)
+ {
+ curtime = m_previoustime + deltatime;
+ }
+ else
+ {
+ curtime = m_kxsystem->GetTimeInSeconds();
+ if (m_previoustime)
+ deltatime = curtime - m_previoustime;
+
+ if (deltatime > 0.1)
+ deltatime = 0.1;
+
+ deltatime = CalculateAverage(deltatime);
+ }
+
+ m_previoustime = curtime;
+
+ KX_SceneList::iterator sceneit;
+ for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); sceneit++)
+ // for each scene, call the proceed functions
+ {
+ KX_Scene* scene = *sceneit;
+
+
+
+ /* Suspension holds the physics and logic processing for an
+ * entire scene. Objects can be suspended individually, and
+ * the settings for that preceed the logic and physics
+ * update. */
+ m_logger->StartLog(tc_logic, m_kxsystem->GetTimeInSeconds(), true);
+ scene->UpdateObjectActivity();
+
+ if (!scene->IsSuspended())
+ {
+ m_logger->StartLog(tc_network, m_kxsystem->GetTimeInSeconds(), true);
+ scene->GetNetworkScene()->proceed(curtime, deltatime);
+
+ // set Python hooks for each scene
+ PHY_SetActiveEnvironment(scene->GetPhysicsEnvironment());
+ PHY_SetActiveScene(scene);
+
+ // Process sensors, and controllers
+ m_logger->StartLog(tc_logic, m_kxsystem->GetTimeInSeconds(), true);
+ scene->LogicBeginFrame(curtime,deltatime);
+
+ // Scenegraph needs to be updated again, because Logic Controllers
+ // can affect the local matrices.
+ m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
+ scene->UpdateParents(curtime);
+
+ // Process actuators
+
+ // Do some cleanup work for this logic frame
+ m_logger->StartLog(tc_logic, m_kxsystem->GetTimeInSeconds(), true);
+ scene->LogicUpdateFrame(curtime,deltatime);
+ scene->LogicEndFrame();
+
+ // Actuators can affect the scenegraph
+ m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
+ scene->UpdateParents(curtime);
+
+ // Perform physics calculations on the scene. This can involve
+ // many iterations of the physics solver.
+ m_logger->StartLog(tc_physics, m_kxsystem->GetTimeInSeconds(), true);
+ scene->GetPhysicsEnvironment()->proceed(deltatime);
+
+ // Update scenegraph after physics step. This maps physics calculations
+ // into node positions.
+ m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
+ scene->UpdateParents(curtime);
+
+ } // suspended
+
+ DoSound(scene);
+
+ m_logger->StartLog(tc_services, m_kxsystem->GetTimeInSeconds(), true);
+ }
+
+ // update system devices
+ m_logger->StartLog(tc_logic, m_kxsystem->GetTimeInSeconds(), true);
+
+ if (m_keyboarddevice)
+ m_keyboarddevice->NextFrame();
+
+ if (m_mousedevice)
+ m_mousedevice->NextFrame();
+
+ if (m_networkdevice)
+ m_networkdevice->NextFrame();
+
+ if (m_audiodevice)
+ m_audiodevice->NextFrame();
+
+ // scene management
+ ProcessScheduledScenes();
+
+ // Start logging time spend outside main loop
+ m_logger->StartLog(tc_outside, m_kxsystem->GetTimeInSeconds(), true);
+}
+
+
+
+void KX_KetsjiEngine::Render()
+{
+ KX_Scene* firstscene = *m_scenes.begin();
+ const RAS_FrameSettings &framesettings = firstscene->GetFramingType();
+
+ m_logger->StartLog(tc_rasterizer, m_kxsystem->GetTimeInSeconds(), true);
+
+ // hiding mouse cursor each frame
+ // (came back when going out of focus and then back in again)
+ if (m_hideCursor)
+ m_canvas->SetMouseState(RAS_ICanvas::MOUSE_INVISIBLE);
+
+ // clear the entire game screen with the border color
+ // only once per frame
+ m_canvas->BeginDraw();
+ if (m_drawingmode == RAS_IRasterizer::KX_TEXTURED) {
+ m_canvas->SetViewPort(0, 0, m_canvas->GetWidth(), m_canvas->GetHeight());
+ if (m_overrideFrameColor)
+ {
+ // Do not use the framing bar color set in the Blender scenes
+ m_canvas->ClearColor(
+ m_overrideFrameColorR,
+ m_overrideFrameColorG,
+ m_overrideFrameColorB,
+ 1.0
+ );
+ }
+ else
+ {
+ // Use the framing bar color set in the Blender scenes
+ m_canvas->ClearColor(
+ framesettings.BarRed(),
+ framesettings.BarGreen(),
+ framesettings.BarBlue(),
+ 1.0
+ );
+ }
+ // clear the -whole- viewport
+ m_canvas->ClearBuffer(RAS_ICanvas::COLOR_BUFFER);
+ }
+
+ m_rasterizer->SetEye(RAS_IRasterizer::RAS_STEREO_LEFTEYE);
+
+ // BeginFrame() sets the actual drawing area. You can use a part of the window
+ if (!BeginFrame())
+ return;
+
+ KX_SceneList::iterator sceneit;
+ for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); sceneit++)
+ // for each scene, call the proceed functions
+ {
+ KX_Scene* scene = *sceneit;
+
+ // pass the scene's worldsettings to the rasterizer
+ SetWorldSettings(scene->GetWorldInfo());
+
+ if (scene->IsClearingZBuffer())
+ m_rasterizer->ClearDepthBuffer();
+
+ m_rendertools->SetAuxilaryClientInfo(scene);
+
+ //Initialize scene viewport.
+ SetupRenderFrame(scene);
+
+ // do the rendering
+ RenderFrame(scene);
+ }
+
+ // only one place that checks for stereo
+ if(m_rasterizer->Stereo())
+ {
+ m_rasterizer->SetEye(RAS_IRasterizer::RAS_STEREO_RIGHTEYE);
+
+ if (!BeginFrame())
+ return;
+
+ KX_SceneList::iterator sceneit;
+ for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); sceneit++)
+ // for each scene, call the proceed functions
+ {
+ KX_Scene* scene = *sceneit;
+
+ // pass the scene's worldsettings to the rasterizer
+ SetWorldSettings(scene->GetWorldInfo());
+
+ if (scene->IsClearingZBuffer())
+ m_rasterizer->ClearDepthBuffer();
+
+ //pass the scene, for picking and raycasting (shadows)
+ m_rendertools->SetAuxilaryClientInfo(scene);
+
+ //Initialize scene viewport.
+ SetupRenderFrame(scene);
+
+ // do the rendering
+ RenderFrame(scene);
+ }
+ } // if(m_rasterizer->Stereo())
+
+ EndFrame();
+}
+
+
+
+void KX_KetsjiEngine::RequestExit(int exitrequestmode)
+{
+ m_exitcode = exitrequestmode;
+}
+
+
+
+void KX_KetsjiEngine::SetNameNextGame(const STR_String& nextgame)
+{
+ m_exitstring = nextgame;
+}
+
+
+
+int KX_KetsjiEngine::GetExitCode()
+{
+ // if a gameactuator has set an exitcode or if there are no scenes left
+ if (!m_exitcode)
+ {
+ if (m_scenes.begin()==m_scenes.end())
+ m_exitcode = KX_EXIT_REQUEST_NO_SCENES_LEFT;
+ }
+
+ return m_exitcode;
+}
+
+
+
+const STR_String& KX_KetsjiEngine::GetExitString()
+{
+ return m_exitstring;
+}
+
+
+
+void KX_KetsjiEngine::DoSound(KX_Scene* scene)
+{
+ m_logger->StartLog(tc_sound, m_kxsystem->GetTimeInSeconds(), true);
+
+ KX_Camera* cam = scene->GetActiveCamera();
+ MT_Point3 listenerposition = cam->NodeGetWorldPosition();
+ MT_Vector3 listenervelocity = cam->GetLinearVelocity();
+ MT_Matrix3x3 listenerorientation = cam->NodeGetWorldOrientation();
+
+ SND_Scene* soundscene = scene->GetSoundScene();
+ soundscene->SetListenerTransform(
+ listenerposition,
+ listenervelocity,
+ listenerorientation);
+
+ soundscene->Proceed();
+}
+
+
+
+void KX_KetsjiEngine::SetBackGround(KX_WorldInfo* wi)
+{
+ if (wi->hasWorld())
+ {
+ if (m_drawingmode == RAS_IRasterizer::KX_TEXTURED)
+ {
+ m_rasterizer->SetBackColor(
+ wi->getBackColorRed(),
+ wi->getBackColorGreen(),
+ wi->getBackColorBlue(),
+ 0.0
+ );
+ }
+ }
+}
+
+
+
+void KX_KetsjiEngine::SetWorldSettings(KX_WorldInfo* wi)
+{
+ if (wi->hasWorld())
+ {
+ if (m_drawingmode == RAS_IRasterizer::KX_TEXTURED)
+ {
+ if (wi->hasMist())
+ {
+ m_rasterizer->SetFog(
+ wi->getMistStart(),
+ wi->getMistDistance(),
+ wi->getMistColorRed(),
+ wi->getMistColorGreen(),
+ wi->getMistColorBlue()
+ );
+ }
+ else
+ {
+ m_rasterizer->DisableFog();
+ }
+ }
+ }
+}
+
+
+
+void KX_KetsjiEngine::SetDrawType(int drawingmode)
+{
+ m_drawingmode = drawingmode;
+}
+
+
+
+void KX_KetsjiEngine::EnableCameraOverride(const STR_String& forscene)
+{
+ m_overrideCam = true;
+ m_overrideSceneName = forscene;
+}
+
+
+
+void KX_KetsjiEngine::SetCameraZoom(float camzoom)
+{
+ m_cameraZoom = camzoom;
+}
+
+
+
+void KX_KetsjiEngine::SetCameraOverrideUseOrtho(bool useOrtho)
+{
+ m_overrideCamUseOrtho = useOrtho;
+}
+
+
+
+void KX_KetsjiEngine::SetCameraOverrideProjectionMatrix(const MT_CmMatrix4x4& mat)
+{
+ m_overrideCamProjMat = mat;
+}
+
+
+void KX_KetsjiEngine::SetCameraOverrideViewMatrix(const MT_CmMatrix4x4& mat)
+{
+ m_overrideCamViewMat = mat;
+}
+
+
+void KX_KetsjiEngine::SetupRenderFrame(KX_Scene *scene)
+{
+ // In this function we make sure the rasterizer settings are upto
+ // date. We compute the viewport so that logic
+ // using this information is upto date.
+
+ // Note we postpone computation of the projection matrix
+ // so that we are using the latest camera position.
+
+ RAS_Rect viewport;
+
+ if (
+ m_overrideCam ||
+ (scene->GetName() != m_overrideSceneName) ||
+ m_overrideCamUseOrtho
+ ) {
+ RAS_FramingManager::ComputeViewport(
+ scene->GetFramingType(),
+ m_canvas->GetDisplayArea(),
+ viewport
+ );
+ } else {
+ viewport.SetLeft(0);
+ viewport.SetBottom(0);
+ viewport.SetRight(int(m_canvas->GetWidth()));
+ viewport.SetTop(int(m_canvas->GetHeight()));
+ }
+ // store the computed viewport in the scene
+
+ scene->SetSceneViewport(viewport);
+
+ // set the viewport for this frame and scene
+ m_canvas->SetViewPort(
+ viewport.GetLeft(),
+ viewport.GetBottom(),
+ viewport.GetRight(),
+ viewport.GetTop()
+ );
+
+}
+
+
+// update graphics
+void KX_KetsjiEngine::RenderFrame(KX_Scene* scene)
+{
+ float left, right, bottom, top, nearfrust, farfrust;
+ KX_Camera* cam = scene->GetActiveCamera();
+
+ m_rasterizer->DisplayFog();
+
+ if (m_overrideCam && (scene->GetName() == m_overrideSceneName) && m_overrideCamUseOrtho) {
+ MT_CmMatrix4x4 projmat = m_overrideCamProjMat;
+ m_rasterizer->SetProjectionMatrix(projmat);
+ } else {
+ RAS_FrameFrustum frustum;
+
+ RAS_FramingManager::ComputeFrustum(
+ scene->GetFramingType(),
+ m_canvas->GetDisplayArea(),
+ scene->GetSceneViewport(),
+ cam->GetLens(),
+ cam->GetCameraNear(),
+ cam->GetCameraFar(),
+ frustum
+ );
+
+ left = frustum.x1 * m_cameraZoom;
+ right = frustum.x2 * m_cameraZoom;
+ bottom = frustum.y1 * m_cameraZoom;
+ top = frustum.y2 * m_cameraZoom;
+ nearfrust = frustum.camnear;
+ farfrust = frustum.camfar;
+
+ MT_Matrix4x4 projmat = m_rasterizer->GetFrustumMatrix(
+ left, right, bottom, top, nearfrust, farfrust);
+
+ m_rasterizer->SetProjectionMatrix(projmat);
+ cam->SetProjectionMatrix(projmat);
+ }
+
+ MT_Scalar cammat[16];
+ cam->GetWorldToCamera().getValue(cammat);
+ MT_Matrix4x4 viewmat;
+ viewmat.setValue(cammat); // this _should transpose ...
+ // if finally transposed take care of correct usage
+ // in RAS_OpenGLRasterizer ! (row major vs column major)
+
+ m_rasterizer->SetViewMatrix(viewmat, cam->NodeGetWorldPosition(),
+ cam->GetCameraLocation(), cam->GetCameraOrientation());
+ cam->SetModelviewMatrix(viewmat);
+
+ scene->UpdateMeshTransformations();
+
+ // The following actually reschedules all vertices to be
+ // redrawn. There is a cache between the actual rescheduling
+ // and this call though. Visibility is imparted when this call
+ // runs through the individual objects.
+ scene->CalculateVisibleMeshes(m_rasterizer);
+
+ scene->RenderBuckets(cam->GetWorldToCamera(), m_rasterizer, m_rendertools);
+}
+
+
+
+void KX_KetsjiEngine::StopEngine()
+{
+ if (m_bInitialized)
+ {
+ KX_SceneList::iterator sceneit;
+ for (sceneit = m_scenes.begin();sceneit != m_scenes.end() ; sceneit++)
+ {
+ KX_Scene* scene = *sceneit;
+ delete scene;
+ }
+ m_scenes.clear();
+
+ // cleanup all the stuff
+ m_rasterizer->Exit();
+ }
+}
+
+// Scene Management is able to switch between scenes
+// and have several scene's running in parallel
+void KX_KetsjiEngine::AddScene(KX_Scene* scene)
+{
+ m_scenes.push_back(scene);
+ PostProcessScene(scene);
+ SceneListsChanged();
+}
+
+
+
+void KX_KetsjiEngine::PostProcessScene(KX_Scene* scene)
+{
+ bool override_camera = (m_overrideCam && (scene->GetName() == m_overrideSceneName));
+
+ // if there is no activecamera, or the camera is being
+ // overridden we need to construct a temporarily camera
+ if (!scene->GetActiveCamera() || override_camera)
+ {
+ KX_Camera* activecam = NULL;
+
+ RAS_CameraData camdata;
+ camdata.m_lens = 35.0f;
+ camdata.m_clipstart = 0.1f;
+ camdata.m_clipend = 100.0f;
+ activecam = new KX_Camera(scene,KX_Scene::m_callbacks,camdata);
+ activecam->SetName("__default__cam__");
+
+ // set transformation
+ if (override_camera) {
+ const MT_CmMatrix4x4& cammatdata = m_overrideCamViewMat;
+ MT_Transform trans = MT_Transform(cammatdata.getPointer());
+ MT_Transform camtrans;
+ camtrans.invert(trans);
+
+ activecam->NodeSetLocalPosition(camtrans.getOrigin());
+ activecam->NodeSetLocalOrientation(camtrans.getBasis());
+ activecam->NodeUpdateGS(0,true);
+ } else {
+ activecam->NodeSetLocalPosition(MT_Point3(0.0, 0.0, 0.0));
+ activecam->NodeSetLocalOrientation(MT_Vector3(0.0, 0.0, 0.0));
+ activecam->NodeUpdateGS(0,true);
+ }
+
+ scene->AddCamera(activecam);
+ scene->SetActiveCamera(activecam);
+ scene->GetObjectList()->Add(activecam->AddRef());
+ scene->GetRootParentList()->Add(activecam->AddRef());
+ }
+
+ scene->UpdateParents(0.0);
+}
+
+
+
+void KX_KetsjiEngine::RenderDebugProperties()
+{
+ STR_String debugtxt;
+ int xcoord = 10; // mmmm, these constants were taken from blender source
+ int ycoord = 14; // to 'mimic' behaviour
+
+ float tottime = m_logger->GetAverage();
+ if (tottime < 1e-6f) {
+ tottime = 1e-6f;
+ }
+
+ /* Framerate display */
+ if (m_show_framerate) {
+ debugtxt.Format("swap : %.3f (%.3f frames per second)", tottime, 1.0/tottime);
+ m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED,
+ debugtxt.Ptr(),
+ xcoord,
+ ycoord,
+ m_canvas->GetWidth() /* RdV, TODO ?? */,
+ m_canvas->GetHeight() /* RdV, TODO ?? */);
+ ycoord += 14;
+ }
+
+ /* Profile and framerate display */
+ if (m_show_profile)
+ {
+ for (int j = tc_first; j < tc_numCategories; j++)
+ {
+ debugtxt.Format(m_profileLabels[j]);
+ m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED,
+ debugtxt.Ptr(),
+ xcoord,ycoord,
+ m_canvas->GetWidth(),
+ m_canvas->GetHeight());
+ double time = m_logger->GetAverage((KX_TimeCategory)j);
+ debugtxt.Format("%2.2f %%", time/tottime * 100.f);
+ m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED,
+ debugtxt.Ptr(),
+ xcoord + 60 ,ycoord,
+ m_canvas->GetWidth(),
+ m_canvas->GetHeight());
+ ycoord += 14;
+ }
+ }
+
+ /* Property display*/
+ if (m_show_debug_properties && m_propertiesPresent)
+ {
+ KX_SceneList::iterator sceneit;
+ for (sceneit = m_scenes.begin();sceneit != m_scenes.end() ; sceneit++)
+ {
+ KX_Scene* scene = *sceneit;
+ /* the 'normal' debug props */
+ vector<SCA_DebugProp*>& debugproplist = scene->GetDebugProperties();
+
+ for (vector<SCA_DebugProp*>::iterator it = debugproplist.begin();
+ !(it==debugproplist.end());it++)
+ {
+ CValue* propobj = (*it)->m_obj;
+ STR_String objname = propobj->GetName();
+ STR_String propname = (*it)->m_name;
+ CValue* propval = propobj->GetProperty(propname);
+ if (propval)
+ {
+ STR_String text = propval->GetText();
+ debugtxt = objname + "." + propname + " = " + text;
+ m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED,
+ debugtxt.Ptr(),
+ xcoord,
+ ycoord,
+ m_canvas->GetWidth(),
+ m_canvas->GetHeight());
+ ycoord += 14;
+ }
+ }
+ }
+ }
+}
+
+
+KX_SceneList* KX_KetsjiEngine::CurrentScenes()
+{
+ return &m_scenes;
+}
+
+
+
+KX_Scene* KX_KetsjiEngine::FindScene(const STR_String& scenename)
+{
+ KX_SceneList::iterator sceneit = m_scenes.begin();
+
+ // bit risky :) better to split the second clause
+ while ( (sceneit != m_scenes.end())
+ && ((*sceneit)->GetName() != scenename))
+ {
+ sceneit++;
+ }
+
+ return ((sceneit == m_scenes.end()) ? NULL : *sceneit);
+}
+
+
+
+void KX_KetsjiEngine::ConvertAndAddScene(const STR_String& scenename,bool overlay)
+{
+ // only add scene when it doesn't exist!
+ if (FindScene(scenename))
+ {
+ STR_String tmpname = scenename;
+ printf("warning: scene %s already exists, not added!\n",tmpname.Ptr());
+ }
+ else
+ {
+ if (overlay)
+ {
+ m_addingOverlayScenes.insert(scenename);
+ }
+ else
+ {
+ m_addingBackgroundScenes.insert(scenename);
+ }
+ }
+}
+
+
+
+
+void KX_KetsjiEngine::RemoveScene(const STR_String& scenename)
+{
+ if (FindScene(scenename))
+ {
+ m_removingScenes.insert(scenename);
+ }
+ else
+ {
+ STR_String tmpname = scenename;
+ printf("warning: scene %s does not exist, not removed!\n",tmpname.Ptr());
+ }
+}
+
+
+
+void KX_KetsjiEngine::RemoveScheduledScenes()
+{
+ if (m_removingScenes.size())
+ {
+ set<STR_String>::iterator scenenameit;
+ for (scenenameit=m_removingScenes.begin();scenenameit != m_removingScenes.end();scenenameit++)
+ {
+ STR_String scenename = *scenenameit;
+
+ KX_SceneList::iterator sceneit;
+ for (sceneit = m_scenes.begin();sceneit != m_scenes.end() ; sceneit++)
+ {
+ KX_Scene* scene = *sceneit;
+ if (scene->GetName()==scenename)
+ {
+ delete scene;
+ m_scenes.erase(sceneit);
+ break;
+ }
+ }
+ }
+ m_removingScenes.clear();
+ }
+}
+
+
+
+KX_Scene* KX_KetsjiEngine::CreateScene(const STR_String& scenename)
+{
+
+ KX_Scene* tmpscene = new KX_Scene(m_keyboarddevice,
+ m_mousedevice,
+ m_networkdevice,
+ m_audiodevice,
+ scenename);
+
+ m_sceneconverter->ConvertScene(scenename,
+ tmpscene,
+ m_pythondictionary,
+ m_keyboarddevice,
+ m_rendertools,
+ m_canvas);
+
+ return tmpscene;
+}
+
+
+
+void KX_KetsjiEngine::AddScheduledScenes()
+{
+ set<STR_String>::iterator scenenameit;
+
+ if (m_addingOverlayScenes.size())
+ {
+ for (scenenameit = m_addingOverlayScenes.begin();
+ scenenameit != m_addingOverlayScenes.end();
+ scenenameit++)
+ {
+ STR_String scenename = *scenenameit;
+ KX_Scene* tmpscene = CreateScene(scenename);
+ m_scenes.push_back(tmpscene);
+ PostProcessScene(tmpscene);
+ }
+ m_addingOverlayScenes.clear();
+ }
+
+ if (m_addingBackgroundScenes.size())
+ {
+ for (scenenameit = m_addingBackgroundScenes.begin();
+ scenenameit != m_addingBackgroundScenes.end();
+ scenenameit++)
+ {
+ STR_String scenename = *scenenameit;
+ KX_Scene* tmpscene = CreateScene(scenename);
+ m_scenes.insert(m_scenes.begin(),tmpscene);
+ PostProcessScene(tmpscene);
+
+ }
+ m_addingBackgroundScenes.clear();
+ }
+}
+
+
+
+void KX_KetsjiEngine::ReplaceScene(const STR_String& oldscene,const STR_String& newscene)
+{
+ m_replace_scenes.insert(std::make_pair(oldscene,newscene));
+}
+
+// replace scene is not the same as removing and adding because the
+// scene must be in exact the same place (to maintain drawingorder)
+// (nzc) - should that not be done with a scene-display list? It seems
+// stupid to rely on the mem allocation order...
+void KX_KetsjiEngine::ReplaceScheduledScenes()
+{
+ if (m_replace_scenes.size())
+ {
+ set<pair<STR_String,STR_String> >::iterator scenenameit;
+
+ for (scenenameit = m_replace_scenes.begin();
+ scenenameit != m_replace_scenes.end();
+ scenenameit++)
+ {
+ STR_String oldscenename = (*scenenameit).first;
+ STR_String newscenename = (*scenenameit).second;
+ int i=0;
+ /* Scenes are not supposed to be included twice... I think */
+ KX_SceneList::iterator sceneit;
+ for (sceneit = m_scenes.begin();sceneit != m_scenes.end() ; sceneit++)
+ {
+ KX_Scene* scene = *sceneit;
+ if (scene->GetName() == oldscenename)
+ {
+ delete scene;
+ KX_Scene* tmpscene = CreateScene(newscenename);
+ m_scenes[i]=tmpscene;
+ PostProcessScene(tmpscene);
+ }
+ i++;
+ }
+ }
+ m_replace_scenes.clear();
+ }
+}
+
+
+
+void KX_KetsjiEngine::SuspendScene(const STR_String& scenename)
+{
+ KX_Scene* scene = FindScene(scenename);
+ if (scene) scene->Suspend();
+}
+
+
+
+void KX_KetsjiEngine::ResumeScene(const STR_String& scenename)
+{
+ KX_Scene* scene = FindScene(scenename);
+ if (scene) scene->Resume();
+}
+
+
+
+void KX_KetsjiEngine::SetUseFixedTime(bool bUseFixedTime)
+{
+ m_bFixedTime = bUseFixedTime;
+}
+
+
+
+bool KX_KetsjiEngine::GetUseFixedTime(void) const
+{
+ return m_bFixedTime;
+}
+
+
+
+void KX_KetsjiEngine::SetTimingDisplay(bool frameRate, bool profile, bool properties)
+{
+ m_show_framerate = frameRate;
+ m_show_profile = profile;
+ m_show_debug_properties = properties;
+}
+
+
+
+void KX_KetsjiEngine::GetTimingDisplay(bool& frameRate, bool& profile, bool& properties) const
+{
+ frameRate = m_show_framerate;
+ profile = m_show_profile;
+ properties = m_show_debug_properties;
+}
+
+
+
+void KX_KetsjiEngine::ProcessScheduledScenes(void)
+{
+ // Check whether there will be changes to the list of scenes
+ if (m_addingOverlayScenes.size() ||
+ m_addingBackgroundScenes.size() ||
+ m_replace_scenes.size() ||
+ m_removingScenes.size()) {
+
+ // Change the scene list
+ ReplaceScheduledScenes();
+ RemoveScheduledScenes();
+ AddScheduledScenes();
+
+ // Notify
+ SceneListsChanged();
+ }
+}
+
+
+
+void KX_KetsjiEngine::SceneListsChanged(void)
+{
+ m_propertiesPresent = false;
+ KX_SceneList::iterator sceneit = m_scenes.begin();
+ while ((sceneit != m_scenes.end()) && (!m_propertiesPresent))
+ {
+ KX_Scene* scene = *sceneit;
+ vector<SCA_DebugProp*>& debugproplist = scene->GetDebugProperties();
+ m_propertiesPresent = !debugproplist.empty();
+ sceneit++;
+ }
+}
+
+
+void KX_KetsjiEngine::SetHideCursor(bool hideCursor)
+{
+ m_hideCursor = hideCursor;
+}
+
+
+bool KX_KetsjiEngine::GetHideCursor(void) const
+{
+ return m_hideCursor;
+}
+
+
+void KX_KetsjiEngine::SetUseOverrideFrameColor(bool overrideFrameColor)
+{
+ m_overrideFrameColor = overrideFrameColor;
+}
+
+
+bool KX_KetsjiEngine::GetUseOverrideFrameColor(void) const
+{
+ return m_overrideFrameColor;
+}
+
+
+void KX_KetsjiEngine::SetOverrideFrameColor(float r, float g, float b)
+{
+ m_overrideFrameColorR = r;
+ m_overrideFrameColorG = g;
+ m_overrideFrameColorB = b;
+}
+
+
+void KX_KetsjiEngine::GetOverrideFrameColor(float& r, float& g, float& b) const
+{
+ r = m_overrideFrameColorR;
+ g = m_overrideFrameColorG;
+ b = m_overrideFrameColorB;
+}
+
diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.h b/source/gameengine/Ketsji/KX_KetsjiEngine.h
new file mode 100644
index 00000000000..4246bc28b50
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_KetsjiEngine.h
@@ -0,0 +1,316 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 __KX_KETSJI_ENGINE
+#define __KX_KETSJI_ENGINE
+
+#include "MT_CmMatrix4x4.h"
+#include "MT_Matrix4x4.h"
+#include "STR_String.h"
+#include "KX_ISystem.h"
+#include "KX_Scene.h"
+#include "KX_Python.h"
+#include "KX_WorldInfo.h"
+#include <vector>
+#include <set>
+
+class KX_TimeCategoryLogger;
+
+#define LEFT_EYE 1
+#define RIGHT_EYE 2
+
+enum KX_ExitRequestMode
+{
+ KX_EXIT_REQUEST_NO_REQUEST = 0,
+ KX_EXIT_REQUEST_QUIT_GAME,
+ KX_EXIT_REQUEST_RESTART_GAME,
+ KX_EXIT_REQUEST_START_OTHER_GAME,
+ KX_EXIT_REQUEST_NO_SCENES_LEFT,
+ KX_EXIT_REQUEST_BLENDER_ESC,
+ KX_EXIT_REQUEST_OUTSIDE,
+ KX_EXIT_REQUEST_MAX
+};
+
+class KX_KetsjiEngine
+{
+
+private:
+ class RAS_ICanvas* m_canvas; // 2D Canvas (2D Rendering Device Context)
+ class RAS_IRasterizer* m_rasterizer; // 3D Rasterizer (3D Rendering)
+ class KX_ISystem* m_kxsystem;
+ class RAS_IRenderTools* m_rendertools;
+ class KX_ISceneConverter* m_sceneconverter;
+ class NG_NetworkDeviceInterface* m_networkdevice;
+ class SND_IAudioDevice* m_audiodevice;
+ PyObject* m_pythondictionary;
+ class SCA_IInputDevice* m_keyboarddevice;
+ class SCA_IInputDevice* m_mousedevice;
+
+ /** Lists of scenes scheduled to be removed at the end of the frame. */
+ std::set<STR_String> m_removingScenes;
+ /** Lists of overley scenes scheduled to be added at the end of the frame. */
+ std::set<STR_String> m_addingOverlayScenes;
+ /** Lists of background scenes scheduled to be added at the end of the frame. */
+ std::set<STR_String> m_addingBackgroundScenes;
+ /** Lists of scenes scheduled to be replaced at the end of the frame. */
+ std::set<std::pair<STR_String,STR_String> > m_replace_scenes;
+
+ /* The current list of scenes. */
+ KX_SceneList m_scenes;
+ /* State variable recording the presence of object debug info in the current scene list. */
+ bool m_propertiesPresent;
+
+ bool m_bInitialized;
+ int m_activecam;
+ bool m_bFixedTime;
+
+ bool m_firstframe;
+ double m_previoustime;
+ double m_missedtime;
+ double m_lasttime; // old style time
+ double m_dtime;
+ std::vector<double> m_deltatimes;
+
+ int m_exitcode;
+ STR_String m_exitstring;
+ /**
+ * Some drawing parameters, the drawing mode
+ * (wire/flat/texture), and the camera zoom
+ * factor.
+ */
+ int m_drawingmode;
+ float m_cameraZoom;
+
+ bool m_overrideCam;
+ STR_String m_overrideSceneName;
+
+ bool m_overrideCamUseOrtho;
+ MT_CmMatrix4x4 m_overrideCamProjMat;
+ MT_CmMatrix4x4 m_overrideCamViewMat;
+
+ bool m_stereo;
+ int m_curreye;
+
+ /** Categories for profiling display. */
+ typedef enum
+ {
+ tc_first = 0,
+ tc_physics = 0,
+ tc_logic,
+ tc_network,
+ tc_scenegraph,
+ tc_sound,
+ tc_rasterizer,
+ tc_services, // time spend in miscelaneous activities
+ tc_overhead, // profile info drawing overhead
+ tc_outside, // time spend outside main loop
+ tc_numCategories
+ } KX_TimeCategory;
+
+ /** Time logger. */
+ KX_TimeCategoryLogger* m_logger;
+
+ /** Labels for profiling display. */
+ static const char m_profileLabels[tc_numCategories][15];
+ /** Show the framerate on the game display? */
+ bool m_show_framerate;
+ /** Show profiling info on the game display? */
+ bool m_show_profile;
+ /** Show any debug (scene) object properties on the game display? */
+ bool m_showProperties;
+ /** Show background behind text for readability? */
+ bool m_showBackground;
+
+ bool m_show_debug_properties;
+
+ /** Hide cursor every frame? */
+ bool m_hideCursor;
+
+ /** Override framing bars color? */
+ bool m_overrideFrameColor;
+ /** Red component of framing bar color. */
+ float m_overrideFrameColorR;
+ /** Green component of framing bar color. */
+ float m_overrideFrameColorG;
+ /** Blue component of framing bar color. */
+ float m_overrideFrameColorB;
+
+ double CalculateAverage(double newdeltatime);
+
+ void SetupRenderFrame(KX_Scene *scene);
+ void RenderFrame(KX_Scene* scene);
+ void RenderDebugProperties();
+ void SetBackGround(KX_WorldInfo* worldinfo);
+ void SetWorldSettings(KX_WorldInfo* worldinfo);
+ void DoSound(KX_Scene* scene);
+
+public:
+
+ KX_KetsjiEngine(class KX_ISystem* system);
+ virtual ~KX_KetsjiEngine();
+
+ // set the devices and stuff. the client must take care of creating these
+ void SetKeyboardDevice(SCA_IInputDevice* keyboarddevice);
+ void SetMouseDevice(SCA_IInputDevice* mousedevice);
+ void SetNetworkDevice(NG_NetworkDeviceInterface* networkdevice);
+ void SetAudioDevice(SND_IAudioDevice* audiodevice);
+ void SetCanvas(RAS_ICanvas* canvas);
+ void SetRenderTools(RAS_IRenderTools* rendertools);
+ void SetRasterizer(RAS_IRasterizer* rasterizer);
+ void SetPythonDictionary(PyObject* pythondictionary);
+ void SetSceneConverter(KX_ISceneConverter* sceneconverter);
+
+ void NextFrame();
+ void Render();
+
+ void StartEngine();
+ void StopEngine();
+ void Export(const STR_String& filename);
+
+ void RequestExit(int exitrequestmode);
+ void SetNameNextGame(const STR_String& nextgame);
+ int GetExitCode();
+ const STR_String& GetExitString();
+
+ KX_SceneList* CurrentScenes();
+ KX_Scene* FindScene(const STR_String& scenename);
+ void AddScene(class KX_Scene* scene);
+ void ConvertAndAddScene(const STR_String& scenename,bool overlay);
+
+ void RemoveScene(const STR_String& scenename);
+ void ReplaceScene(const STR_String& oldscene,const STR_String& newscene);
+ void SuspendScene(const STR_String& scenename);
+ void ResumeScene(const STR_String& scenename);
+
+ void SetDrawType(int drawingtype);
+ void SetCameraZoom(float camzoom);
+
+ void EnableCameraOverride(const STR_String& forscene);
+
+ void SetCameraOverrideUseOrtho(bool useOrtho);
+ void SetCameraOverrideProjectionMatrix(const MT_CmMatrix4x4& mat);
+ void SetCameraOverrideViewMatrix(const MT_CmMatrix4x4& mat);
+
+ /**
+ * Sets display of all frames.
+ * @param bUseFixedTime New setting for display all frames.
+ */
+ void SetUseFixedTime(bool bUseFixedTime);
+
+ /**
+ * Returns display of all frames.
+ * @return Current setting for display all frames.
+ */
+ bool GetUseFixedTime(void) const;
+
+ /**
+ * Activates or deactivates timing information display.
+ * @param frameRate Display for frame rate on or off.
+ * @param profile Display for individual components on or off.
+ * @param properties Display of scene object debug properties on or off.
+ */
+ void SetTimingDisplay(bool frameRate, bool profile, bool properties);
+
+ /**
+ * Returns status of timing information display.
+ * @param frameRate Display for frame rate on or off.
+ * @param profile Display for individual components on or off.
+ * @param properties Display of scene object debug properties on or off.
+ */
+ void GetTimingDisplay(bool& frameRate, bool& profile, bool& properties) const;
+
+ /**
+ * Sets cursor hiding on every frame.
+ * @param hideCursor Turns hiding on or off.
+ */
+ void SetHideCursor(bool hideCursor);
+
+ /**
+ * Returns the current setting for cursor hiding.
+ * @return The current setting for cursor hiding.
+ */
+ bool GetHideCursor(void) const;
+
+ /**
+ * Enables/disables the use of the framing bar color of the Blender file's scenes.
+ * @param overrideFrameColor The new setting.
+ */
+ void SetUseOverrideFrameColor(bool overrideFrameColor);
+
+ /**
+ * Enables/disables the use of the framing bar color of the Blender file's scenes.
+ * @param useSceneFrameColor The new setting.
+ */
+ bool GetUseOverrideFrameColor(void) const;
+
+ /**
+ * Set the color used for framing bar color instead of the one in the Blender file's scenes.
+ * @param r Red component of the override color.
+ * @param g Green component of the override color.
+ * @param b Blue component of the override color.
+ */
+ void SetOverrideFrameColor(float r, float g, float b);
+
+ /**
+ * Returns the color used for framing bar color instead of the one in the Blender file's scenes.
+ * @param r Red component of the override color.
+ * @param g Green component of the override color.
+ * @param b Blue component of the override color.
+ */
+ void GetOverrideFrameColor(float& r, float& g, float& b) const;
+
+protected:
+ /**
+ * Processes all scheduled scene activity.
+ * At the end, if the scene lists have changed,
+ * SceneListsChanged(void) is called.
+ * @see SceneListsChanged(void).
+ */
+ void ProcessScheduledScenes(void);
+
+ /**
+ * This method is invoked when the scene lists have changed.
+ */
+ void SceneListsChanged(void);
+
+ void RemoveScheduledScenes(void);
+ void AddScheduledScenes(void);
+ void ReplaceScheduledScenes(void);
+ void PostProcessScene(class KX_Scene* scene);
+ KX_Scene* CreateScene(const STR_String& scenename);
+
+ bool BeginFrame();
+ void EndFrame();
+};
+
+#endif //__KX_KETSJI_ENGINE
+
diff --git a/source/gameengine/Ketsji/KX_Light.cpp b/source/gameengine/Ketsji/KX_Light.cpp
new file mode 100644
index 00000000000..25e756ae66c
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_Light.cpp
@@ -0,0 +1,75 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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)
+#endif
+
+#include "KX_Light.h"
+#include "RAS_IRenderTools.h"
+
+
+KX_LightObject::KX_LightObject(void* sgReplicationInfo,SG_Callbacks callbacks,
+ class RAS_IRenderTools* rendertools,
+ const RAS_LightObject& lightobj
+ )
+ :
+ KX_GameObject(sgReplicationInfo,callbacks),
+ m_rendertools(rendertools)
+{
+ m_lightobj = lightobj;
+ m_lightobj.m_worldmatrix = GetOpenGLMatrixPtr();
+ m_rendertools->AddLight(&m_lightobj);
+};
+
+
+KX_LightObject::~KX_LightObject()
+{
+
+ m_rendertools->RemoveLight(&m_lightobj);
+}
+
+
+CValue* KX_LightObject::GetReplica()
+{
+
+ KX_LightObject* replica = new KX_LightObject(*this);
+
+ // this will copy properties and so on...
+ CValue::AddDataToReplica(replica);
+
+ ProcessReplica(replica);
+
+ replica->m_lightobj.m_worldmatrix = replica->GetOpenGLMatrixPtr();
+ m_rendertools->AddLight(&replica->m_lightobj);
+ return replica;
+}
diff --git a/source/gameengine/Ketsji/KX_Light.h b/source/gameengine/Ketsji/KX_Light.h
new file mode 100644
index 00000000000..0ee91040c84
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_Light.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 *****
+ */
+#ifndef __KX_LIGHT
+#define __KX_LIGHT
+
+#include "RAS_LightObject.h"
+#include "KX_GameObject.h"
+
+class KX_LightObject : public KX_GameObject
+{
+ RAS_LightObject m_lightobj;
+ class RAS_IRenderTools* m_rendertools; //needed for registering and replication of lightobj
+
+public:
+ KX_LightObject(void* sgReplicationInfo,SG_Callbacks callbacks,class RAS_IRenderTools* rendertools,const struct RAS_LightObject& lightobj);
+ virtual ~KX_LightObject();
+ virtual CValue* GetReplica();
+ RAS_LightObject* GetLightData() { return &m_lightobj;}
+};
+
+#endif //__KX_LIGHT
diff --git a/source/gameengine/Ketsji/KX_LightIpoSGController.cpp b/source/gameengine/Ketsji/KX_LightIpoSGController.cpp
new file mode 100644
index 00000000000..3dd26947a79
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_LightIpoSGController.cpp
@@ -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 *****
+ */
+
+#include "KX_LightIpoSGController.h"
+
+#include "KX_ScalarInterpolator.h"
+#include "KX_Light.h"
+
+#include "RAS_LightObject.h"
+
+
+bool KX_LightIpoSGController::Update(double currentTime)
+{
+ if (m_modified)
+ {
+ T_InterpolatorList::iterator i;
+ for (i = m_interpolators.begin(); !(i == m_interpolators.end()); ++i) {
+ (*i)->Execute(m_ipotime);//currentTime);
+ }
+
+ RAS_LightObject *lightobj;
+
+ SG_Spatial* ob = (SG_Spatial*)m_pObject;
+ KX_LightObject* kxlight = (KX_LightObject*) ob->GetSGClientObject();
+ lightobj = kxlight->GetLightData();
+ //lightobj = (KX_Light*)
+
+ if (m_modify_energy) {
+ lightobj->m_energy = m_energy;
+ }
+
+ if (m_modify_color) {
+ lightobj->m_red = m_col_rgb[0];
+ lightobj->m_green = m_col_rgb[1];
+ lightobj->m_blue = m_col_rgb[2];
+ }
+
+ if (m_modify_dist) {
+ lightobj->m_distance = m_dist;
+ }
+
+ m_modified=false;
+ }
+ return false;
+}
+
+
+void KX_LightIpoSGController::AddInterpolator(KX_IInterpolator* interp)
+{
+ this->m_interpolators.push_back(interp);
+}
+
+SG_Controller* KX_LightIpoSGController::GetReplica(class SG_Node* destnode)
+{
+ KX_LightIpoSGController* iporeplica = new KX_LightIpoSGController(*this);
+ // clear object that ipo acts on
+ iporeplica->ClearObject();
+
+ // dirty hack, ask Gino for a better solution in the ipo implementation
+ // hacken en zagen, in what we call datahiding, not written for replication :(
+
+ T_InterpolatorList oldlist = m_interpolators;
+ iporeplica->m_interpolators.clear();
+
+ T_InterpolatorList::iterator i;
+ for (i = oldlist.begin(); !(i == oldlist.end()); ++i) {
+ KX_ScalarInterpolator* copyipo = new KX_ScalarInterpolator(*((KX_ScalarInterpolator*)*i));
+ iporeplica->AddInterpolator(copyipo);
+
+ MT_Scalar* scaal = ((KX_ScalarInterpolator*)*i)->GetTarget();
+ int orgbase = (int)this;
+ int orgloc = (int)scaal;
+ int offset = orgloc-orgbase;
+ int newaddrbase = (int)iporeplica + offset;
+ MT_Scalar* blaptr = (MT_Scalar*) newaddrbase;
+ copyipo->SetNewTarget((MT_Scalar*)blaptr);
+ }
+
+ return iporeplica;
+}
+
+KX_LightIpoSGController::~KX_LightIpoSGController()
+{
+
+ T_InterpolatorList::iterator i;
+ for (i = m_interpolators.begin(); !(i == m_interpolators.end()); ++i) {
+ delete (*i);
+ }
+
+}
diff --git a/source/gameengine/Ketsji/KX_LightIpoSGController.h b/source/gameengine/Ketsji/KX_LightIpoSGController.h
new file mode 100644
index 00000000000..2b115fcc00f
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_LightIpoSGController.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 KX_LIGHTIPOSGCONTROLLER_H
+#define KX_LIGHTIPOSGCONTROLLER_H
+
+#include "SG_Controller.h"
+#include "SG_Spatial.h"
+
+#include "KX_IInterpolator.h"
+
+struct RAS_LightObject;
+
+class KX_LightIpoSGController : public SG_Controller
+{
+public:
+ MT_Scalar m_energy;
+ MT_Scalar m_col_rgb[3];
+ MT_Scalar m_dist;
+
+private:
+ T_InterpolatorList m_interpolators;
+ unsigned short m_modify_energy : 1;
+ unsigned short m_modify_color : 1;
+ unsigned short m_modify_dist : 1;
+ bool m_modified;
+
+ double m_ipotime;
+public:
+ KX_LightIpoSGController() : m_ipotime(0.0),
+ m_modify_energy(false),
+ m_modify_color(false),
+ m_modify_dist(false),
+ m_modified(true)
+ {}
+
+ virtual ~KX_LightIpoSGController();
+
+ virtual SG_Controller* GetReplica(class SG_Node* destnode);
+
+ virtual bool Update(double time);
+
+ virtual void SetSimulatedTime(double time) {
+ m_ipotime = time;
+ m_modified = true;
+ }
+
+ void SetModifyEnergy(bool modify) {
+ m_modify_energy = modify;
+ }
+
+ void SetModifyColor(bool modify) {
+ m_modify_color = modify;
+ }
+
+ void SetModifyDist(bool modify) {
+ m_modify_dist = modify;
+ }
+
+ void
+ SetOption(
+ int option,
+ int value
+ ){
+ // intentionally empty
+ };
+
+ void AddInterpolator(KX_IInterpolator* interp);
+};
+
+#endif // KX_LIGHTIPOSGCONTROLLER_H
diff --git a/source/gameengine/Ketsji/KX_MeshProxy.cpp b/source/gameengine/Ketsji/KX_MeshProxy.cpp
new file mode 100644
index 00000000000..f17e5820d52
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_MeshProxy.cpp
@@ -0,0 +1,193 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "KX_MeshProxy.h"
+
+#include "RAS_IPolygonMaterial.h"
+#include "RAS_MeshObject.h"
+#include "KX_VertexProxy.h"
+
+
+PyTypeObject KX_MeshProxy::Type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0,
+ "KX_MeshProxy",
+ sizeof(KX_MeshProxy),
+ 0,
+ PyDestructor,
+ 0,
+ __getattr,
+ __setattr,
+ 0, //&MyPyCompare,
+ __repr,
+ 0, //&cvalue_as_number,
+ 0,
+ 0,
+ 0,
+ 0
+};
+
+PyParentObject KX_MeshProxy::Parents[] = {
+ &KX_MeshProxy::Type,
+ &SCA_IObject::Type,
+ &CValue::Type,
+ NULL
+};
+
+PyMethodDef KX_MeshProxy::Methods[] = {
+{"getNumMaterials", (PyCFunction)KX_MeshProxy::sPyGetNumMaterials,METH_VARARGS},
+{"getMaterialName", (PyCFunction)KX_MeshProxy::sPyGetMaterialName,METH_VARARGS},
+{"getTextureName", (PyCFunction)KX_MeshProxy::sPyGetTextureName,METH_VARARGS},
+{"getVertexArrayLength", (PyCFunction)KX_MeshProxy::sPyGetVertexArrayLength,METH_VARARGS},
+{"getVertex", (PyCFunction)KX_MeshProxy::sPyGetVertex,METH_VARARGS},
+//{"getIndexArrayLength", (PyCFunction)KX_MeshProxy::sPyGetIndexArrayLength,METH_VARARGS},
+
+ {NULL,NULL} //Sentinel
+};
+
+PyObject*
+KX_MeshProxy::_getattr(char* attr)
+{
+ _getattr_up(SCA_IObject);
+}
+
+
+
+KX_MeshProxy::KX_MeshProxy(RAS_MeshObject* mesh)
+ : m_meshobj(mesh)
+{
+
+}
+
+KX_MeshProxy::~KX_MeshProxy()
+{
+
+}
+
+
+
+// stuff for cvalue related things
+CValue* KX_MeshProxy::Calc(VALUE_OPERATOR op, CValue *val) { return NULL;}
+CValue* KX_MeshProxy::CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val) { return NULL;}
+
+const STR_String & KX_MeshProxy::GetText() {return m_meshobj->GetName();};
+float KX_MeshProxy::GetNumber() { return -1;}
+STR_String KX_MeshProxy::GetName() { return m_meshobj->GetName();}
+void KX_MeshProxy::SetName(STR_String name) { };
+CValue* KX_MeshProxy::GetReplica() { return NULL;}
+void KX_MeshProxy::ReplicaSetName(STR_String name) {};
+
+
+// stuff for python integration
+
+PyObject* KX_MeshProxy::PyGetNumMaterials(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ int num = m_meshobj->NumMaterials();
+ return PyInt_FromLong(num);
+}
+
+PyObject* KX_MeshProxy::PyGetMaterialName(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ int matid= 1;
+ STR_String matname;
+
+ if (PyArg_ParseTuple(args,"i",&matid))
+ {
+ matname = m_meshobj->GetMaterialName(matid);
+ }
+
+ return PyString_FromString(matname.Ptr());
+
+}
+
+
+PyObject* KX_MeshProxy::PyGetTextureName(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ int matid= 1;
+ STR_String matname;
+
+ if (PyArg_ParseTuple(args,"i",&matid))
+ {
+ matname = m_meshobj->GetTextureName(matid);
+ }
+
+ return PyString_FromString(matname.Ptr());
+
+}
+
+PyObject* KX_MeshProxy::PyGetVertexArrayLength(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ int matid= -1;
+ int length = -1;
+
+
+ if (PyArg_ParseTuple(args,"i",&matid))
+ {
+ RAS_IPolyMaterial* mat = m_meshobj->GetMaterialBucket(matid)->GetPolyMaterial();
+ if (mat)
+ {
+ length = m_meshobj->GetVertexArrayLength(mat);
+ }
+ }
+
+ return PyInt_FromLong(length);
+
+}
+
+
+PyObject* KX_MeshProxy::PyGetVertex(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ int vertexindex= 1;
+ int matindex= 1;
+ PyObject* vertexob = NULL;
+
+ if (PyArg_ParseTuple(args,"ii",&matindex,&vertexindex))
+ {
+ RAS_TexVert* vertex = m_meshobj->GetVertex(matindex,vertexindex);
+ if (vertex)
+ {
+ vertexob = new KX_VertexProxy(vertex);
+ }
+ }
+
+ return vertexob;
+
+}
diff --git a/source/gameengine/Ketsji/KX_MeshProxy.h b/source/gameengine/Ketsji/KX_MeshProxy.h
new file mode 100644
index 00000000000..a6c5b7558a2
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_MeshProxy.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 *****
+ */
+#ifndef __KX_MESHPROXY
+#define __KX_MESHPROXY
+
+#include "SCA_IObject.h"
+
+class KX_MeshProxy : public SCA_IObject
+{
+ Py_Header;
+
+ class RAS_MeshObject* m_meshobj;
+public:
+ KX_MeshProxy(class RAS_MeshObject* mesh);
+ virtual ~KX_MeshProxy();
+
+ // stuff for cvalue related things
+ virtual CValue* Calc(VALUE_OPERATOR op, CValue *val) ;
+ virtual CValue* CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val);
+ virtual const STR_String & GetText();
+ virtual float GetNumber();
+ virtual STR_String GetName();
+ virtual void SetName(STR_String name); // Set the name of the value
+ virtual void ReplicaSetName(STR_String name);
+ virtual CValue* GetReplica();
+
+// stuff for python integration
+ virtual PyObject* _getattr(char *attr);
+ KX_PYMETHOD(KX_MeshProxy,GetNumMaterials);
+ KX_PYMETHOD(KX_MeshProxy,GetMaterialName);
+ KX_PYMETHOD(KX_MeshProxy,GetTextureName);
+
+ // both take materialid (int)
+ KX_PYMETHOD(KX_MeshProxy,GetVertexArrayLength);
+ KX_PYMETHOD(KX_MeshProxy,GetVertex);
+};
+#endif //__KX_MESHPROXY
diff --git a/source/gameengine/Ketsji/KX_MotionState.cpp b/source/gameengine/Ketsji/KX_MotionState.cpp
new file mode 100644
index 00000000000..50b1943e5f0
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_MotionState.cpp
@@ -0,0 +1,91 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "KX_MotionState.h"
+#include "SG_Spatial.h"
+
+KX_MotionState::KX_MotionState(SG_Spatial* node) : m_node(node)
+{
+
+}
+
+KX_MotionState::~KX_MotionState()
+{
+}
+
+void KX_MotionState::getWorldPosition(float& posX,float& posY,float& posZ)
+{
+ MT_Point3 pos = m_node->GetWorldPosition();
+ posX = pos[0];
+ posY = pos[1];
+ posZ = pos[2];
+}
+
+void KX_MotionState::getWorldScaling(float& scaleX,float& scaleY,float& scaleZ)
+{
+ MT_Vector3 scale = m_node->GetWorldScaling();
+ scaleX = scale[0];
+ scaleY = scale[1];
+ scaleZ = scale[2];
+}
+
+void KX_MotionState::getWorldOrientation(float& quatIma0,float& quatIma1,float& quatIma2,float& quatReal)
+{
+ MT_Quaternion orn = m_node->GetWorldOrientation().getRotation();
+ quatIma0 = orn[0];
+ quatIma1 = orn[1];
+ quatIma2 = orn[2];
+ quatReal = orn[3];
+}
+
+void KX_MotionState::setWorldPosition(float posX,float posY,float posZ)
+{
+ m_node->SetLocalPosition(MT_Point3(posX,posY,posZ));
+
+}
+
+void KX_MotionState::setWorldOrientation(float quatIma0,float quatIma1,float quatIma2,float quatReal)
+{
+ MT_Quaternion orn;
+ orn[0] = quatIma0;
+ orn[1] = quatIma1;
+ orn[2] = quatIma2;
+ orn[3] = quatReal;
+
+ m_node->SetLocalOrientation(orn);
+}
+
+void KX_MotionState::calculateWorldTransformations()
+{
+ m_node->ComputeWorldTransforms(NULL);
+}
+
+
diff --git a/source/gameengine/Ketsji/KX_MotionState.h b/source/gameengine/Ketsji/KX_MotionState.h
new file mode 100644
index 00000000000..3d0f9bd40be
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_MotionState.h
@@ -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 *****
+ */
+#ifndef __KX_MOTIONSTATE
+#define __KX_MOTIONSTATE
+
+#include "PHY_IMotionState.h"
+
+class KX_MotionState : public PHY_IMotionState
+{
+ class SG_Spatial* m_node;
+
+public:
+ KX_MotionState(class SG_Spatial* spatial);
+ virtual ~KX_MotionState();
+
+ virtual void getWorldPosition(float& posX,float& posY,float& posZ);
+ virtual void getWorldScaling(float& scaleX,float& scaleY,float& scaleZ);
+ virtual void getWorldOrientation(float& quatIma0,float& quatIma1,float& quatIma2,float& quatReal);
+ virtual void setWorldPosition(float posX,float posY,float posZ);
+ virtual void setWorldOrientation(float quatIma0,float quatIma1,float quatIma2,float quatReal);
+
+ virtual void calculateWorldTransformations();
+};
+
+#endif //__KX_MOTIONSTATE
diff --git a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp
new file mode 100644
index 00000000000..006215b9fe8
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp
@@ -0,0 +1,353 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * KX_MouseFocusSensor determines mouse in/out/over events.
+ */
+
+#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
+
+#include "MT_Point3.h"
+
+#include "KX_ClientObjectInfo.h"
+
+
+#include "RAS_FramingManager.h"
+#include "RAS_ICanvas.h"
+#include "RAS_IRasterizer.h"
+
+#include "SCA_IScene.h"
+
+#include "KX_Scene.h"
+#include "KX_Camera.h"
+
+#include "KX_MouseFocusSensor.h"
+
+/* ------------------------------------------------------------------------- */
+/* Native functions */
+/* ------------------------------------------------------------------------- */
+
+KX_MouseFocusSensor::KX_MouseFocusSensor(SCA_MouseManager* eventmgr,
+ int startx,
+ int starty,
+ short int mousemode,
+ bool focusmode,
+ RAS_ICanvas* canvas,
+ KX_Scene* kxscene,
+ SCA_IObject* gameobj,
+ PyTypeObject* T)
+ : SCA_MouseSensor(eventmgr, startx, starty, mousemode, gameobj, T),
+ m_focusmode(focusmode),
+ m_gp_canvas(canvas),
+ m_kxscene(kxscene)
+{
+ /* Or postpone? I think a sumo scene and kx scene go pretty much
+ * together, so it should be safe to do it here. */
+ m_mouse_over_in_previous_frame = false;
+ m_positive_event = false;
+}
+
+bool KX_MouseFocusSensor::Evaluate(CValue* event)
+{
+ bool result = false;
+ bool obHasFocus = false;
+
+// cout << "evaluate focus mouse sensor "<<endl;
+
+ if (m_focusmode) {
+ /* Focus behaviour required. Test mouse-on. The rest is
+ * equivalent to handling a key. */
+ obHasFocus = ParentObjectHasFocus();
+
+ if (!obHasFocus) {
+ if (m_mouse_over_in_previous_frame) {
+ m_positive_event = false;
+ result = true;
+ }
+ } else {
+ if (!m_mouse_over_in_previous_frame) {
+ m_positive_event = true;
+ result = true;
+ }
+ }
+ } else {
+ /* No focus behaviour required: revert to the basic mode. This
+ * mode is never used, because the converter never makes this
+ * sensor for a mouse-key event. It is here for
+ * completeness. */
+ result = SCA_MouseSensor::Evaluate(event);
+ m_positive_event = (m_val!=0);
+ }
+
+ m_mouse_over_in_previous_frame = obHasFocus;
+
+ return result;
+}
+
+bool KX_MouseFocusSensor::ParentObjectHasFocus(void)
+{
+
+ bool res = false;
+ m_hitPosition = MT_Vector3(0,0,0);
+ m_hitNormal = MT_Vector3(1,0,0);
+ MT_Point3 resultpoint;
+ MT_Vector3 resultnormal;
+
+ /* All screen handling in the gameengine is done by GL,
+ * specifically the model/view and projection parts. The viewport
+ * part is in the creator.
+ *
+ * The theory is this:
+ * WCS - world coordinates
+ * -> wcs_camcs_trafo ->
+ * camCS - camera coordinates
+ * -> camcs_clip_trafo ->
+ * clipCS - normalised device coordinates?
+ * -> normview_win_trafo
+ * winCS - window coordinates
+ *
+ * The first two transforms are respectively the model/view and
+ * the projection matrix. These are passed to the rasterizer, and
+ * we store them in the camera for easy access.
+ *
+ * For normalised device coords (xn = x/w, yn = y/w/zw) the
+ * windows coords become (lb = left bottom)
+ *
+ * xwin = [(xn + 1.0) * width]/2 + x_lb
+ * ywin = [(yn + 1.0) * height]/2 + y_lb
+ *
+ * Inverting (blender y is flipped!):
+ *
+ * xn = 2(xwin - x_lb)/width - 1.0
+ * yn = 2(ywin - y_lb)/height - 1.0
+ * = 2(height - y_blender - y_lb)/height - 1.0
+ * = 1.0 - 2(y_blender - y_lb)/height
+ *
+ * */
+
+ /* Because we don't want to worry about resize events, camera
+ * changes and all that crap, we just determine this over and
+ * over. Stop whining. We have lots of other calculations to do
+ * here as well. These reads are not the main cost. If there is no
+ * canvas, the test is irrelevant. The 1.0 makes sure the
+ * calculations don't bomb. Maybe we should explicitly guard for
+ * division by 0.0...*/
+
+ /**
+ * Get the scenes current viewport.
+ */
+
+ const RAS_Rect & viewport = m_kxscene->GetSceneViewport();
+
+ float height = float(viewport.m_y2 - viewport.m_y1 + 1);
+ float width = float(viewport.m_x2 - viewport.m_x1 + 1);
+
+ float x_lb = float(viewport.m_x1);
+ float y_lb = float(viewport.m_y1);
+
+ KX_Camera* cam = m_kxscene->GetActiveCamera();
+ /* There's some strangeness I don't fully get here... These values
+ * _should_ be wrong! */
+
+ /* old: */
+ float nearclip = 0.0;
+ float farclip = -1.0;
+
+ /* build the from and to point in normalised device coordinates
+ * Looks like normailized device coordinates are [-1,1] in x [-1,1] in y
+ * [0,-1] in z
+ *
+ * The actual z coordinates used don't have to be exact just infront and
+ * behind of the near and far clip planes.
+ */
+
+ MT_Vector4 frompoint = MT_Vector4(
+ (2 * (m_x-x_lb) / width) - 1.0,
+ 1.0 - (2 * (m_y - y_lb) / height),
+ (nearclip + 3 * farclip) / (farclip - nearclip),
+ 1.0
+ );
+ MT_Vector4 topoint = MT_Vector4(
+ (2 * (m_x-x_lb) / width) - 1.0,
+ 1.0 - (2 * (m_y-y_lb) / height),
+ (3 * nearclip + farclip) / (farclip - nearclip),
+ 1.0
+ );
+
+ /* camera to world */
+ MT_Matrix4x4 camcs_wcs_matrix;
+ cam->GetModelviewMatrix(camcs_wcs_matrix);
+ camcs_wcs_matrix.invert();
+
+ MT_Matrix4x4 clip_camcs_matrix;
+ /* badly defined, the first time round.... I wonder why... I might
+ * want to guard against floating point errors here.*/
+ cam->GetProjectionMatrix(clip_camcs_matrix);
+ clip_camcs_matrix.invert();
+
+ /* shoot-points: clip to cam to wcs . win to clip was already done.*/
+ frompoint = clip_camcs_matrix * frompoint;
+ topoint = clip_camcs_matrix * topoint;
+ frompoint = camcs_wcs_matrix * frompoint;
+ topoint = camcs_wcs_matrix * topoint;
+
+ /* from hom wcs to 3d wcs: */
+ MT_Point3 frompoint3 = MT_Point3(frompoint[0]/frompoint[3],
+ frompoint[1]/frompoint[3],
+ frompoint[2]/frompoint[3]);
+ MT_Point3 topoint3 = MT_Point3(topoint[0]/topoint[3],
+ topoint[1]/topoint[3],
+ topoint[2]/topoint[3]);
+ m_prevTargetPoint = topoint3;
+
+ /* 2. Get the object from SuMO*/
+ /* Shoot! Beware that the first argument here is an
+ * ignore-object. We don't ignore anything... */
+ KX_GameObject* thisObj = (KX_GameObject*) GetParent();
+
+
+ //SM_Object* hitSMObj = m_sumoScene->rayTest(NULL,
+ // frompoint3,
+ // topoint3,
+ // resultpoint,
+ // resultnormal);
+
+ KX_GameObject* hitKXObj = 0;
+
+ /* all this casting makes me nervous... */
+ //SM_ClientObjectInfo* client_info
+ // = ( hitSMObj ?
+ // (SM_ClientObjectInfo*) ((SM_Object*)hitSMObj)->getClientObject() :
+ // NULL);
+ //KX_GameObject* hitKXObj = ( client_info ?
+ // (KX_GameObject*)client_info->m_clientobject :
+ // NULL);
+
+
+ /* Is this me? In the ray test, there are a lot of extra checks
+ * for aliasing artefacts from self-hits. That doesn't happen
+ * here, so a simple test suffices. Or does the camera also get
+ * self-hits? (No, and the raysensor shouldn't do it either, since
+ * self-hits are excluded by setting the correct ignore-object.)
+ * Hitspots now become valid. */
+ if (hitKXObj == thisObj)
+ {
+ m_hitPosition = resultpoint;
+ m_hitNormal = resultnormal;
+ res = true;
+ }
+
+ return res;
+}
+
+/* ------------------------------------------------------------------------- */
+/* Python functions */
+/* ------------------------------------------------------------------------- */
+
+/* Integration hooks ------------------------------------------------------- */
+PyTypeObject KX_MouseFocusSensor::Type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0,
+ "KX_MouseFocusSensor",
+ sizeof(KX_MouseFocusSensor),
+ 0,
+ PyDestructor,
+ 0,
+ __getattr,
+ __setattr,
+ 0, //&MyPyCompare,
+ __repr,
+ 0, //&cvalue_as_number,
+ 0,
+ 0,
+ 0,
+ 0
+};
+
+PyParentObject KX_MouseFocusSensor::Parents[] = {
+ &KX_MouseFocusSensor::Type,
+ &SCA_MouseSensor::Type,
+ &SCA_ISensor::Type,
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
+};
+
+PyMethodDef KX_MouseFocusSensor::Methods[] = {
+ {"getRayTarget", (PyCFunction) KX_MouseFocusSensor::sPyGetRayTarget,
+ METH_VARARGS, GetRayTarget_doc},
+ {"getRaySource", (PyCFunction) KX_MouseFocusSensor::sPyGetRaySource,
+ METH_VARARGS, GetRaySource_doc},
+ {NULL,NULL} //Sentinel
+};
+
+PyObject* KX_MouseFocusSensor::_getattr(char* attr) {
+ _getattr_up(SCA_MouseSensor);
+}
+
+/* getRayTarget */
+char KX_MouseFocusSensor::GetRayTarget_doc[] =
+"getRayTarget()\n"
+"\tReturns the target of the ray that seeks the focus object,\n"
+"\tin worldcoordinates.";
+PyObject* KX_MouseFocusSensor::PyGetRayTarget(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ PyObject *retVal = PyList_New(3);
+
+ PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_prevTargetPoint[0]));
+ PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_prevTargetPoint[1]));
+ PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_prevTargetPoint[2]));
+
+ return retVal;
+}
+
+/* getRayTarget */
+char KX_MouseFocusSensor::GetRaySource_doc[] =
+"getRaySource()\n"
+"\tReturns the source of the ray that seeks the focus object,\n"
+"\tin worldcoordinates.";
+PyObject* KX_MouseFocusSensor::PyGetRaySource(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ PyObject *retVal = PyList_New(3);
+
+ PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_prevSourcePoint[0]));
+ PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_prevSourcePoint[1]));
+ PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_prevSourcePoint[2]));
+
+ return retVal;
+}
+
+/* eof */
+
diff --git a/source/gameengine/Ketsji/KX_MouseFocusSensor.h b/source/gameengine/Ketsji/KX_MouseFocusSensor.h
new file mode 100644
index 00000000000..590f69a81b3
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_MouseFocusSensor.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 *****
+ * KX_MouseFocusSensor determines mouse in/out/over events.
+ */
+
+#ifndef __KX_MOUSEFOCUSSENSOR
+#define __KX_MOUSEFOCUSSENSOR
+
+#include "SCA_MouseSensor.h"
+/* #include "SCA_IInputDevice.h" */
+
+/**
+ * The mouse focus sensor extends the basic SCA_MouseSensor. It has
+ * been placed in KX because it needs access to the rasterizer and
+ * SuMO.
+ *
+ * - extend the valid modes?
+ * - */
+class KX_MouseFocusSensor : public SCA_MouseSensor
+{
+
+ Py_Header;
+
+ public:
+
+ KX_MouseFocusSensor(class SCA_MouseManager* keybdmgr,
+ int startx,
+ int starty,
+ short int mousemode,
+ bool focusmode,
+ RAS_ICanvas* canvas,
+ KX_Scene* kxscene,
+ SCA_IObject* gameobj,
+ PyTypeObject* T=&Type );
+
+ virtual ~KX_MouseFocusSensor() { ; };
+ virtual CValue* GetReplica() {
+ CValue* replica = new KX_MouseFocusSensor(*this);
+ // this will copy properties and so on...
+ CValue::AddDataToReplica(replica);
+ return replica;
+ };
+ /**
+ * @attention Overrides default evaluate.
+ */
+ virtual bool Evaluate(CValue* event);
+
+ virtual bool IsPositiveTrigger() {
+ bool result = m_positive_event;
+ if (m_invert) result = !result;
+ return result;
+ };
+
+
+ /* --------------------------------------------------------------------- */
+ /* Python interface ---------------------------------------------------- */
+ /* --------------------------------------------------------------------- */
+ virtual PyObject* _getattr(char *attr);
+
+ KX_PYMETHOD_DOC(KX_MouseFocusSensor,GetRayTarget);
+ KX_PYMETHOD_DOC(KX_MouseFocusSensor,GetRaySource);
+
+ /* --------------------------------------------------------------------- */
+
+ private:
+ /**
+ * The focus mode. True for handling focus, false for not handling
+ * it. */
+ bool m_focusmode;
+
+ /**
+ * Flags whether the previous test showed a mouse-over.
+ */
+ bool m_mouse_over_in_previous_frame;
+
+ /**
+ * Flags whether the previous test evaluated positive.
+ */
+ bool m_positive_event;
+
+
+ /**
+ * Tests whether the object is in mouse focus in this frame.
+ */
+ bool ParentObjectHasFocus(void);
+
+ /**
+ * (in game world coordinates) the place where the object was hit.
+ */
+ MT_Point3 m_hitPosition;
+
+ /**
+ * (in game world coordinates) the position to which to shoot the ray.
+ */
+ MT_Point3 m_prevTargetPoint;
+
+ /**
+ * (in game world coordinates) the position from which to shoot the ray.
+ */
+ MT_Point3 m_prevSourcePoint;
+
+ /**
+ * (in game world coordinates) the face normal of the vertex where
+ * the object was hit. */
+ MT_Vector3 m_hitNormal;
+
+ /**
+ * Ref to the engine, for retrieving a reference to the current
+ * scene. */
+ class KX_KetsjiEngine* m_engine;
+
+ /**
+ * The active canvas. The size of this canvas determines a part of
+ * the start position of the picking ray. */
+ RAS_ICanvas* m_gp_canvas;
+
+ /**
+ * The KX scene that holds the camera. The camera position
+ * determines a part of the start location of the picking ray. */
+ KX_Scene* m_kxscene;
+
+};
+
+#endif //__KX_MOUSESENSOR
diff --git a/source/gameengine/Ketsji/KX_NearSensor.cpp b/source/gameengine/Ketsji/KX_NearSensor.cpp
new file mode 100644
index 00000000000..0388f7cc332
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_NearSensor.cpp
@@ -0,0 +1,262 @@
+/**
+ * Sense if other objects are near
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "KX_NearSensor.h"
+#include "SCA_LogicManager.h"
+#include "KX_GameObject.h"
+#include "KX_TouchEventManager.h"
+#include "KX_Scene.h" // needed to create a replica
+
+
+#ifdef PHYSICS_NOT_YET
+
+KX_NearSensor::KX_NearSensor(SCA_EventManager* eventmgr,
+ KX_GameObject* gameobj,
+ double margin,
+ double resetmargin,
+ bool bFindMaterial,
+ const STR_String& touchedpropname,
+ class KX_Scene* scene,
+ PyTypeObject* T)
+ :KX_TouchSensor(eventmgr,
+ gameobj,
+ bFindMaterial,
+ touchedpropname,
+ scene,
+ T),
+ m_Margin(margin),
+ m_ResetMargin(resetmargin),
+ m_sumoScene(sumoscene)
+
+{
+ m_client_info.m_type = 4;
+ m_client_info.m_clientobject = gameobj;
+ m_client_info.m_auxilary_info = NULL;
+ sumoObj->setClientObject(&m_client_info);
+}
+
+
+
+CValue* KX_NearSensor::GetReplica()
+{
+ KX_NearSensor* replica = new KX_NearSensor(*this);
+ replica->m_colliders = new CListValue();
+ replica->m_bCollision = false;
+ replica->m_bTriggered= false;
+ replica->m_hitObject = NULL;
+ replica->m_bLastTriggered = false;
+ // this will copy properties and so on...
+ CValue::AddDataToReplica(replica);
+
+ return replica;
+}
+
+
+
+void KX_NearSensor::ReParent(SCA_IObject* parent)
+{
+ DT_ShapeHandle shape = DT_Sphere(0.0);
+
+ // this sumoObject is not deleted by a gameobj, so delete it ourself
+ // later (memleaks)!
+
+ SM_Object* sumoObj = new SM_Object(shape,NULL,NULL,NULL);
+ sumoObj->setMargin(m_Margin);
+
+ //sumoObj->setPosition(gameobj->NodeGetWorldPosition());
+ //sumoobj->setPosition(m_sumoObj->getPosition());
+ //sumoobj->setOrientation(m_sumoObj->getOrientation());
+ //newobj->setRigidBody(this->m_sumoObj->isRigidBody());
+
+ m_sumoObj = sumoObj;
+ m_solidHandle = m_sumoObj->getObjectHandle();
+
+ double radius = m_sumoObj->getMargin();
+ sumoObj->setMargin(m_sumoObj->getMargin());
+
+ m_client_info.m_type = 4;
+ m_client_info.m_clientobject = parent;
+ m_client_info.m_auxilary_info = NULL;
+ sumoObj->setClientObject(&m_client_info);
+
+ //m_sumoScene->add(*newobj);
+
+ if (m_sumoObj)
+ {
+ DT_SetObjectResponse(m_resptable,
+ m_sumoObj->getObjectHandle(),
+ collisionResponse,
+ DT_SIMPLE_RESPONSE,
+ this);
+ }
+
+ SCA_ISensor::ReParent(parent);
+}
+
+
+
+KX_NearSensor::~KX_NearSensor()
+{
+ // for nearsensor, the sensor is the 'owner' of sumoobj
+ // for touchsensor, it's the parent
+
+ m_sumoScene->remove(*m_sumoObj);
+
+ if (m_sumoObj)
+ delete m_sumoObj;
+}
+
+
+
+bool KX_NearSensor::Evaluate(CValue* event)
+{
+ bool result = false;
+ KX_GameObject* parent = (KX_GameObject*)GetParent();
+
+ if (m_bTriggered != m_bLastTriggered)
+ {
+ m_bLastTriggered = m_bTriggered;
+ if (m_bTriggered)
+ {
+ if (m_sumoObj)
+ {
+ m_sumoObj->setMargin(m_ResetMargin);
+ }
+ } else
+ {
+ if (m_sumoObj)
+ {
+ m_sumoObj->setMargin(m_Margin);
+ }
+
+ }
+ result = true;
+ }
+
+ return result;
+}
+
+
+
+void KX_NearSensor::HandleCollision(void* obj1,void* obj2,const DT_CollData * coll_data)
+{
+ KX_TouchEventManager* toucheventmgr = (KX_TouchEventManager*)m_eventmgr;
+ KX_GameObject* parent = (KX_GameObject*)GetParent();
+
+ // need the mapping from SM_Objects to gameobjects now
+
+ SM_ClientObjectInfo* client_info =(SM_ClientObjectInfo*) (obj1 == m_sumoObj?
+ ((SM_Object*)obj2)->getClientObject() :
+ ((SM_Object*)obj1)->getClientObject());
+
+ KX_GameObject* gameobj = ( client_info ?
+ (KX_GameObject*)client_info->m_clientobject :
+ NULL);
+
+ if (gameobj && (gameobj != parent))
+ {
+ if (!m_colliders->SearchValue(gameobj))
+ m_colliders->Add(gameobj->AddRef());
+
+ // only take valid colliders
+ if (client_info->m_type == 1)
+ {
+ if ((m_touchedpropname.Length() == 0) ||
+ (gameobj->GetProperty(m_touchedpropname)))
+ {
+ m_bTriggered = true;
+ m_hitObject = gameobj;
+ }
+ }
+ } else
+ {
+
+ }
+}
+
+
+
+// python embedding
+PyTypeObject KX_NearSensor::Type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0,
+ "KX_NearSensor",
+ sizeof(KX_NearSensor),
+ 0,
+ PyDestructor,
+ 0,
+ __getattr,
+ __setattr,
+ 0, //&MyPyCompare,
+ __repr,
+ 0, //&cvalue_as_number,
+ 0,
+ 0,
+ 0,
+ 0
+};
+
+
+
+PyParentObject KX_NearSensor::Parents[] = {
+ &KX_NearSensor::Type,
+ &KX_TouchSensor::Type,
+ &SCA_ISensor::Type,
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
+};
+
+
+
+PyMethodDef KX_NearSensor::Methods[] = {
+ {"setProperty",
+ (PyCFunction) KX_NearSensor::sPySetProperty, METH_VARARGS, SetProperty_doc},
+ {"getProperty",
+ (PyCFunction) KX_NearSensor::sPyGetProperty, METH_VARARGS, GetProperty_doc},
+ {"getHitObject",
+ (PyCFunction) KX_NearSensor::sPyGetHitObject, METH_VARARGS, GetHitObject_doc},
+ {"getHitObjectList",
+ (PyCFunction) KX_NearSensor::sPyGetHitObjectList, METH_VARARGS, GetHitObjectList_doc},
+ {NULL,NULL} //Sentinel
+};
+
+
+PyObject*
+KX_NearSensor::_getattr(char* attr)
+{
+ _getattr_up(KX_TouchSensor);
+}
+
+#endif //PHYSICS_NOT_YET
diff --git a/source/gameengine/Ketsji/KX_NearSensor.h b/source/gameengine/Ketsji/KX_NearSensor.h
new file mode 100644
index 00000000000..c87889f1ab7
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_NearSensor.h
@@ -0,0 +1,61 @@
+/**
+ * Sense if other objects are near
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 KX_NEARSENSOR_H
+#define KX_NEARSENSOR_H
+
+#include "KX_TouchSensor.h"
+class KX_Scene;
+
+class KX_NearSensor : public KX_TouchSensor
+{
+ Py_Header;
+ double m_Margin;
+ double m_ResetMargin;
+ KX_Scene* m_scene;
+
+public:
+ KX_NearSensor(class SCA_EventManager* eventmgr,class KX_GameObject* gameobj,double margin,double resetmargin,bool bFindMaterial,const STR_String& touchedpropname,class KM_Scene* scene,PyTypeObject* T=&Type);
+ virtual ~KX_NearSensor();
+ virtual CValue* GetReplica();
+ virtual bool Evaluate(CValue* event);
+
+ virtual void ReParent(SCA_IObject* parent);
+ //virtual void HandleCollision(void* obj1,void* obj2,
+ // const DT_CollData * coll_data);
+
+ virtual PyObject* _getattr(char *attr);
+
+};
+#endif //KX_NEARSENSOR_H
diff --git a/source/gameengine/Ketsji/KX_ObColorIpoSGController.cpp b/source/gameengine/Ketsji/KX_ObColorIpoSGController.cpp
new file mode 100644
index 00000000000..d4bb714d75d
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_ObColorIpoSGController.cpp
@@ -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 *****
+ */
+
+#include "KX_ObColorIpoSGController.h"
+
+#include "KX_ScalarInterpolator.h"
+#include "KX_GameObject.h"
+
+
+bool KX_ObColorIpoSGController::Update(double currentTime)
+{
+ if (m_modified)
+ {
+ m_rgba[0]=0;
+ m_rgba[1]=0;
+ m_rgba[2]=0;
+ m_rgba[3]=0;
+
+ T_InterpolatorList::iterator i;
+ for (i = m_interpolators.begin(); !(i == m_interpolators.end()); ++i) {
+ (*i)->Execute(m_ipotime);
+ }
+
+
+ SG_Spatial* ob = (SG_Spatial*)m_pObject;
+ KX_GameObject* kxgameobj= (KX_GameObject*) ob->GetSGClientObject();
+
+ kxgameobj->SetObjectColor(m_rgba);
+
+
+ m_modified=false;
+ }
+ return false;
+}
+
+
+void KX_ObColorIpoSGController::AddInterpolator(KX_IInterpolator* interp)
+{
+ this->m_interpolators.push_back(interp);
+}
+
+SG_Controller* KX_ObColorIpoSGController::GetReplica(class SG_Node* destnode)
+{
+ KX_ObColorIpoSGController* iporeplica = new KX_ObColorIpoSGController(*this);
+ // clear object that ipo acts on
+ iporeplica->ClearObject();
+
+ // dirty hack, ask Gino for a better solution in the ipo implementation
+ // hacken en zagen, in what we call datahiding, not written for replication :(
+
+ T_InterpolatorList oldlist = m_interpolators;
+ iporeplica->m_interpolators.clear();
+
+ T_InterpolatorList::iterator i;
+ for (i = oldlist.begin(); !(i == oldlist.end()); ++i) {
+ KX_ScalarInterpolator* copyipo = new KX_ScalarInterpolator(*((KX_ScalarInterpolator*)*i));
+ iporeplica->AddInterpolator(copyipo);
+
+ MT_Scalar* scaal = ((KX_ScalarInterpolator*)*i)->GetTarget();
+ int orgbase = (int)this;
+ int orgloc = (int)scaal;
+ int offset = orgloc-orgbase;
+ int newaddrbase = (int)iporeplica + offset;
+ MT_Scalar* blaptr = (MT_Scalar*) newaddrbase;
+ copyipo->SetNewTarget((MT_Scalar*)blaptr);
+ }
+
+ return iporeplica;
+}
+
+KX_ObColorIpoSGController::~KX_ObColorIpoSGController()
+{
+
+ T_InterpolatorList::iterator i;
+ for (i = m_interpolators.begin(); !(i == m_interpolators.end()); ++i) {
+ delete (*i);
+ }
+
+}
diff --git a/source/gameengine/Ketsji/KX_ObColorIpoSGController.h b/source/gameengine/Ketsji/KX_ObColorIpoSGController.h
new file mode 100644
index 00000000000..df4d8d3bb4f
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_ObColorIpoSGController.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 KX_OBCOLORIPOSGCONTROLLER_H
+#define KX_OBCOLORIPOSGCONTROLLER_H
+
+#include "SG_Controller.h"
+#include "SG_Spatial.h"
+
+#include "KX_IInterpolator.h"
+
+
+class KX_ObColorIpoSGController : public SG_Controller
+{
+public:
+ MT_Vector4 m_rgba;
+
+
+private:
+ T_InterpolatorList m_interpolators;
+ bool m_modified;
+
+ double m_ipotime;
+public:
+ KX_ObColorIpoSGController() : m_ipotime(0.0),
+
+ m_modified(true)
+ {}
+ virtual ~KX_ObColorIpoSGController();
+ virtual SG_Controller* GetReplica(class SG_Node* destnode);
+ virtual bool Update(double time);
+ virtual void SetSimulatedTime(double time) {
+ m_ipotime = time;
+ m_modified = true;
+ }
+
+ void
+ SetOption(
+ int option,
+ int value
+ ){
+ // intentionally empty
+ };
+
+
+ void AddInterpolator(KX_IInterpolator* interp);
+};
+
+#endif // KX_OBCOLORIPOSGCONTROLLER_H
diff --git a/source/gameengine/Ketsji/KX_ObjectActuator.cpp b/source/gameengine/Ketsji/KX_ObjectActuator.cpp
new file mode 100644
index 00000000000..97e167385dc
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_ObjectActuator.cpp
@@ -0,0 +1,400 @@
+/**
+ * Do translation/rotation actions
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "KX_ObjectActuator.h"
+#include "KX_GameObject.h"
+#include "KX_IPhysicsController.h"
+
+
+/* ------------------------------------------------------------------------- */
+/* Native functions */
+/* ------------------------------------------------------------------------- */
+
+
+KX_ObjectActuator::
+KX_ObjectActuator(
+ SCA_IObject* gameobj,
+ const MT_Vector3& force,
+ const MT_Vector3& torque,
+ const MT_Vector3& dloc,
+ const MT_Vector3& drot,
+ const MT_Vector3& linV,
+ const MT_Vector3& angV,
+ const KX_LocalFlags& flag,
+ PyTypeObject* T
+) :
+ SCA_IActuator(gameobj,T),
+ m_force(force),
+ m_torque(torque),
+ m_dloc(dloc),
+ m_drot(drot),
+ m_linear_velocity(linV),
+ m_angular_velocity(angV),
+ m_active_combined_velocity (false),
+ m_bitLocalFlag (flag)
+{
+}
+
+bool KX_ObjectActuator::Update(double curtime,double deltatime)
+{
+
+ bool bNegativeEvent = IsNegativeEvent();
+ RemoveAllEvents();
+
+ KX_GameObject *parent = static_cast<KX_GameObject *>(GetParent());
+
+ if (bNegativeEvent) {
+ // If we previously set the linear velocity we now have to inform
+ // the physics controller that we no longer wish to apply it and that
+ // it should reconcile the externally set velocity with it's
+ // own velocity.
+ if (m_active_combined_velocity) {
+ //if (parent->GetSumoObject()) {
+ //parent->GetPhysicsController()->ResolveCombinedVelocities(
+ // m_linear_velocity,
+ // m_angular_velocity,
+ // (m_bitLocalFlag.LinearVelocity) != 0,
+ // (m_bitLocalFlag.AngularVelocity) != 0
+ //);
+ m_active_combined_velocity = false;
+ //}
+ return false;
+ } else {
+ return false;
+ }
+
+ } else
+ if (parent)
+ {
+ /* Probably better to use some flags, so these MT_zero tests can be */
+ /* skipped. */
+ if (!MT_fuzzyZero(m_force))
+ {
+ parent->ApplyForce(m_force,(m_bitLocalFlag.Force) != 0);
+ }
+ if (!MT_fuzzyZero(m_torque))
+ {
+ parent->ApplyTorque(m_torque,(m_bitLocalFlag.Torque) != 0);
+ }
+ if (!MT_fuzzyZero(m_dloc))
+ {
+ parent->ApplyMovement(m_dloc,(m_bitLocalFlag.DLoc) != 0);
+ }
+ if (!MT_fuzzyZero(m_drot))
+ {
+ parent->ApplyRotation(m_drot,(m_bitLocalFlag.DRot) != 0);
+ }
+ if (!MT_fuzzyZero(m_linear_velocity))
+ {
+ if (m_bitLocalFlag.AddOrSetLinV) {
+ parent->addLinearVelocity(m_linear_velocity,(m_bitLocalFlag.LinearVelocity) != 0);
+ } else {
+ m_active_combined_velocity = true;
+ parent->setLinearVelocity(m_linear_velocity,(m_bitLocalFlag.LinearVelocity) != 0);
+ }
+ }
+ if (!MT_fuzzyZero(m_angular_velocity))
+ {
+ parent->setAngularVelocity(m_angular_velocity,(m_bitLocalFlag.AngularVelocity) != 0);
+ m_active_combined_velocity = true;
+ }
+
+ }
+ return true;
+}
+
+
+
+CValue* KX_ObjectActuator::GetReplica()
+{
+ KX_ObjectActuator* replica = new KX_ObjectActuator(*this);//m_float,GetName());
+ replica->ProcessReplica();
+
+ // this will copy properties and so on...
+ CValue::AddDataToReplica(replica);
+
+ return replica;
+}
+
+
+
+/* some 'standard' utilities... */
+bool KX_ObjectActuator::isValid(KX_ObjectActuator::KX_OBJECT_ACT_VEC_TYPE type)
+{
+ bool res = false;
+ res = (type > KX_OBJECT_ACT_NODEF) && (type < KX_OBJECT_ACT_MAX);
+ return res;
+}
+
+
+
+/* ------------------------------------------------------------------------- */
+/* Python functions */
+/* ------------------------------------------------------------------------- */
+
+/* Integration hooks ------------------------------------------------------- */
+PyTypeObject KX_ObjectActuator::Type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0,
+ "KX_ObjectActuator",
+ sizeof(KX_ObjectActuator),
+ 0,
+ PyDestructor,
+ 0,
+ __getattr,
+ __setattr,
+ 0, //&MyPyCompare,
+ __repr,
+ 0, //&cvalue_as_number,
+ 0,
+ 0,
+ 0,
+ 0
+};
+
+PyParentObject KX_ObjectActuator::Parents[] = {
+ &KX_ObjectActuator::Type,
+ &SCA_IActuator::Type,
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
+};
+
+PyMethodDef KX_ObjectActuator::Methods[] = {
+ {"getForce", (PyCFunction) KX_ObjectActuator::sPyGetForce, METH_VARARGS},
+ {"setForce", (PyCFunction) KX_ObjectActuator::sPySetForce, METH_VARARGS},
+ {"getTorque", (PyCFunction) KX_ObjectActuator::sPyGetTorque, METH_VARARGS},
+ {"setTorque", (PyCFunction) KX_ObjectActuator::sPySetTorque, METH_VARARGS},
+ {"getDLoc", (PyCFunction) KX_ObjectActuator::sPyGetDLoc, METH_VARARGS},
+ {"setDLoc", (PyCFunction) KX_ObjectActuator::sPySetDLoc, METH_VARARGS},
+ {"getDRot", (PyCFunction) KX_ObjectActuator::sPyGetDRot, METH_VARARGS},
+ {"setDRot", (PyCFunction) KX_ObjectActuator::sPySetDRot, METH_VARARGS},
+ {"getLinearVelocity", (PyCFunction) KX_ObjectActuator::sPyGetLinearVelocity, METH_VARARGS},
+ {"setLinearVelocity", (PyCFunction) KX_ObjectActuator::sPySetLinearVelocity, METH_VARARGS},
+ {"getAngularVelocity", (PyCFunction) KX_ObjectActuator::sPyGetAngularVelocity, METH_VARARGS},
+ {"setAngularVelocity", (PyCFunction) KX_ObjectActuator::sPySetAngularVelocity, METH_VARARGS},
+
+
+ {NULL,NULL} //Sentinel
+};
+
+PyObject* KX_ObjectActuator::_getattr(char* attr) {
+ _getattr_up(SCA_IActuator);
+};
+
+/* 1. set ------------------------------------------------------------------ */
+/* Removed! */
+
+/* 2. getForce */
+PyObject* KX_ObjectActuator::PyGetForce(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ PyObject *retVal = PyList_New(4);
+
+ PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_force[0]));
+ PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_force[1]));
+ PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_force[2]));
+ PyList_SetItem(retVal, 3, BoolToPyArg(m_bitLocalFlag.Force));
+
+ return retVal;
+}
+/* 3. setForce */
+PyObject* KX_ObjectActuator::PySetForce(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ float vecArg[3];
+ int bToggle = 0;
+ if (!PyArg_ParseTuple(args, "fffi", &vecArg[0], &vecArg[1],
+ &vecArg[2], &bToggle)) {
+ return NULL;
+ }
+ m_force.setValue(vecArg);
+ m_bitLocalFlag.Force = PyArgToBool(bToggle);
+ Py_Return;
+}
+
+/* 4. getTorque */
+PyObject* KX_ObjectActuator::PyGetTorque(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ PyObject *retVal = PyList_New(4);
+
+ PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_torque[0]));
+ PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_torque[1]));
+ PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_torque[2]));
+ PyList_SetItem(retVal, 3, BoolToPyArg(m_bitLocalFlag.Torque));
+
+ return retVal;
+}
+/* 5. setTorque */
+PyObject* KX_ObjectActuator::PySetTorque(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ float vecArg[3];
+ int bToggle = 0;
+ if (!PyArg_ParseTuple(args, "fffi", &vecArg[0], &vecArg[1],
+ &vecArg[2], &bToggle)) {
+ return NULL;
+ }
+ m_torque.setValue(vecArg);
+ m_bitLocalFlag.Torque = PyArgToBool(bToggle);
+ Py_Return;
+}
+
+/* 6. getDLoc */
+PyObject* KX_ObjectActuator::PyGetDLoc(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ PyObject *retVal = PyList_New(4);
+
+ PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_dloc[0]));
+ PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_dloc[1]));
+ PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_dloc[2]));
+ PyList_SetItem(retVal, 3, BoolToPyArg(m_bitLocalFlag.DLoc));
+
+ return retVal;
+}
+/* 7. setDLoc */
+PyObject* KX_ObjectActuator::PySetDLoc(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ float vecArg[3];
+ int bToggle = 0;
+ if(!PyArg_ParseTuple(args, "fffi", &vecArg[0], &vecArg[1],
+ &vecArg[2], &bToggle)) {
+ return NULL;
+ }
+ m_dloc.setValue(vecArg);
+ m_bitLocalFlag.DLoc = PyArgToBool(bToggle);
+ Py_Return;
+}
+
+/* 8. getDRot */
+PyObject* KX_ObjectActuator::PyGetDRot(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ PyObject *retVal = PyList_New(4);
+
+ PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_drot[0]));
+ PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_drot[1]));
+ PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_drot[2]));
+ PyList_SetItem(retVal, 3, BoolToPyArg(m_bitLocalFlag.DRot));
+
+ return retVal;
+}
+/* 9. setDRot */
+PyObject* KX_ObjectActuator::PySetDRot(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ float vecArg[3];
+ int bToggle = 0;
+ if (!PyArg_ParseTuple(args, "fffi", &vecArg[0], &vecArg[1],
+ &vecArg[2], &bToggle)) {
+ return NULL;
+ }
+ m_drot.setValue(vecArg);
+ m_bitLocalFlag.DRot = PyArgToBool(bToggle);
+ Py_Return;
+}
+
+/* 10. getLinearVelocity */
+PyObject* KX_ObjectActuator::PyGetLinearVelocity(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ PyObject *retVal = PyList_New(4);
+
+ PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_linear_velocity[0]));
+ PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_linear_velocity[1]));
+ PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_linear_velocity[2]));
+ PyList_SetItem(retVal, 3, BoolToPyArg(m_bitLocalFlag.LinearVelocity));
+
+ return retVal;
+}
+
+/* 11. setLinearVelocity */
+PyObject* KX_ObjectActuator::PySetLinearVelocity(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ float vecArg[3];
+ int bToggle = 0;
+ if (!PyArg_ParseTuple(args, "fffi", &vecArg[0], &vecArg[1],
+ &vecArg[2], &bToggle)) {
+ return NULL;
+ }
+ m_linear_velocity.setValue(vecArg);
+ m_bitLocalFlag.LinearVelocity = PyArgToBool(bToggle);
+ Py_Return;
+}
+
+
+/* 12. getAngularVelocity */
+PyObject* KX_ObjectActuator::PyGetAngularVelocity(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ PyObject *retVal = PyList_New(4);
+
+ PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_angular_velocity[0]));
+ PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_angular_velocity[1]));
+ PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_angular_velocity[2]));
+ PyList_SetItem(retVal, 3, BoolToPyArg(m_bitLocalFlag.AngularVelocity));
+
+ return retVal;
+}
+/* 13. setAngularVelocity */
+PyObject* KX_ObjectActuator::PySetAngularVelocity(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ float vecArg[3];
+ int bToggle = 0;
+ if (!PyArg_ParseTuple(args, "fffi", &vecArg[0], &vecArg[1],
+ &vecArg[2], &bToggle)) {
+ return NULL;
+ }
+ m_angular_velocity.setValue(vecArg);
+ m_bitLocalFlag.AngularVelocity = PyArgToBool(bToggle);
+ Py_Return;
+}
+
+
+
+
+/* eof */
diff --git a/source/gameengine/Ketsji/KX_ObjectActuator.h b/source/gameengine/Ketsji/KX_ObjectActuator.h
new file mode 100644
index 00000000000..d7d780d1f3c
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_ObjectActuator.h
@@ -0,0 +1,140 @@
+/**
+ * Do translation/rotation actions
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 __KX_OBJECTACTUATOR
+#define __KX_OBJECTACTUATOR
+
+#include "SCA_IActuator.h"
+#include "MT_Vector3.h"
+
+
+//
+// Bitfield that stores the flags for each CValue derived class
+//
+struct KX_LocalFlags {
+ KX_LocalFlags() :
+ Force(false),
+ Torque(false),
+ DRot(false),
+ DLoc(false),
+ LinearVelocity(false),
+ AngularVelocity(false),
+ AddOrSetLinV(false)
+ {
+ }
+
+ unsigned short Force : 1;
+ unsigned short Torque : 1;
+ unsigned short DRot : 1;
+ unsigned short DLoc : 1;
+ unsigned short LinearVelocity : 1;
+ unsigned short AngularVelocity : 1;
+ unsigned short AddOrSetLinV : 1;
+};
+
+class KX_ObjectActuator : public SCA_IActuator
+{
+ Py_Header;
+
+ MT_Vector3 m_force;
+ MT_Vector3 m_torque;
+ MT_Vector3 m_dloc;
+ MT_Vector3 m_drot;
+ MT_Vector3 m_linear_velocity;
+ MT_Vector3 m_angular_velocity;
+ KX_LocalFlags m_bitLocalFlag;
+
+ // A hack bool -- oh no sorry everyone
+ // This bool is used to check if we have informed
+ // the physics object that we are no longer
+ // setting linear velocity.
+
+ bool m_active_combined_velocity;
+
+public:
+ enum KX_OBJECT_ACT_VEC_TYPE {
+ KX_OBJECT_ACT_NODEF = 0,
+ KX_OBJECT_ACT_FORCE,
+ KX_OBJECT_ACT_TORQUE,
+ KX_OBJECT_ACT_DLOC,
+ KX_OBJECT_ACT_DROT,
+ KX_OBJECT_ACT_LINEAR_VELOCITY,
+ KX_OBJECT_ACT_ANGULAR_VELOCITY,
+ KX_OBJECT_ACT_MAX
+ };
+
+ /**
+ * Check whether this is a valid vector mode
+ */
+ bool isValid(KX_OBJECT_ACT_VEC_TYPE type);
+
+ KX_ObjectActuator(
+ SCA_IObject* gameobj,
+ const MT_Vector3& force,
+ const MT_Vector3& torque,
+ const MT_Vector3& dloc,
+ const MT_Vector3& drot,
+ const MT_Vector3& linV,
+ const MT_Vector3& angV,
+ const KX_LocalFlags& flag,
+ PyTypeObject* T=&Type
+ );
+
+ CValue* GetReplica();
+
+ void SetForceLoc(const double force[3]) { /*m_force=force;*/ }
+ bool Update(double curtime,double deltatime);
+
+
+
+ /* --------------------------------------------------------------------- */
+ /* Python interface ---------------------------------------------------- */
+ /* --------------------------------------------------------------------- */
+
+ virtual PyObject* _getattr(char *attr);
+
+ KX_PYMETHOD(KX_ObjectActuator,GetForce);
+ KX_PYMETHOD(KX_ObjectActuator,SetForce);
+ KX_PYMETHOD(KX_ObjectActuator,GetTorque);
+ KX_PYMETHOD(KX_ObjectActuator,SetTorque);
+ KX_PYMETHOD(KX_ObjectActuator,GetDLoc);
+ KX_PYMETHOD(KX_ObjectActuator,SetDLoc);
+ KX_PYMETHOD(KX_ObjectActuator,GetDRot);
+ KX_PYMETHOD(KX_ObjectActuator,SetDRot);
+ KX_PYMETHOD(KX_ObjectActuator,GetLinearVelocity);
+ KX_PYMETHOD(KX_ObjectActuator,SetLinearVelocity);
+ KX_PYMETHOD(KX_ObjectActuator,GetAngularVelocity);
+ KX_PYMETHOD(KX_ObjectActuator,SetAngularVelocity);
+};
+#endif //__KX_OBJECTACTUATOR
diff --git a/source/gameengine/Ketsji/KX_OrientationInterpolator.cpp b/source/gameengine/Ketsji/KX_OrientationInterpolator.cpp
new file mode 100644
index 00000000000..bead946ab37
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_OrientationInterpolator.cpp
@@ -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 *****
+ */
+
+#include "KX_OrientationInterpolator.h"
+
+
+#include "MT_Matrix3x3.h"
+#include "KX_IScalarInterpolator.h"
+
+void KX_OrientationInterpolator::Execute(float currentTime) const {
+ MT_Vector3 eul(m_ipos[0]->GetValue(currentTime),
+ m_ipos[1]->GetValue(currentTime),
+ m_ipos[2]->GetValue(currentTime));
+ MT_Scalar ci = cos(eul[0]);
+ MT_Scalar cj = cos(eul[1]);
+ MT_Scalar ch = cos(eul[2]);
+ MT_Scalar si = sin(eul[0]);
+ MT_Scalar sj = sin(eul[1]);
+ MT_Scalar sh = sin(eul[2]);
+ MT_Scalar cc = ci*ch;
+ MT_Scalar cs = ci*sh;
+ MT_Scalar sc = si*ch;
+ MT_Scalar ss = si*sh;
+
+ m_target.setValue(cj*ch, sj*sc-cs, sj*cc+ss,
+ cj*sh, sj*ss+cc, sj*cs-sc,
+ -sj, cj*si, cj*ci);
+}
diff --git a/source/gameengine/Ketsji/KX_OrientationInterpolator.h b/source/gameengine/Ketsji/KX_OrientationInterpolator.h
new file mode 100644
index 00000000000..9e65e72b125
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_OrientationInterpolator.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 KX_ORIENTATIONINTERPOLATOR
+#define KX_ORIENTATIONINTERPOLATOR
+
+#include "KX_IInterpolator.h"
+
+class MT_Matrix3x3;
+class KX_IScalarInterpolator;
+
+class KX_OrientationInterpolator : public KX_IInterpolator {
+public:
+ KX_OrientationInterpolator(MT_Matrix3x3& target,
+ KX_IScalarInterpolator **ipos)
+ : m_target(target)
+ {
+ m_ipos[0] = ipos[0];
+ m_ipos[1] = ipos[1];
+ m_ipos[2] = ipos[2];
+ }
+
+ virtual void Execute(float currentTime) const;
+
+private:
+ MT_Matrix3x3& m_target;
+ KX_IScalarInterpolator *m_ipos[3];
+};
+
+#endif
diff --git a/source/gameengine/Ketsji/KX_PhysicsEngineEnums.h b/source/gameengine/Ketsji/KX_PhysicsEngineEnums.h
new file mode 100644
index 00000000000..c9dd613da00
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_PhysicsEngineEnums.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 __KX_PHYSICSENGINEENUMS
+#define __KX_PHYSICSENGINEENUMS
+
+enum e_PhysicsEngine
+{
+ UseNone=1,
+ UseSumo,
+ UseODE,
+ UseDynamo,
+ NoSelection
+};
+
+#endif //__KX_PHYSICSENGINEENUMS
diff --git a/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp b/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp
new file mode 100644
index 00000000000..b14afbdc678
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp
@@ -0,0 +1,161 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 <Python.h>
+#include "KX_PhysicsObjectWrapper.h"
+#include "PHY_IPhysicsEnvironment.h"
+#include "PHY_IPhysicsController.h"
+
+KX_PhysicsObjectWrapper::KX_PhysicsObjectWrapper(
+ PHY_IPhysicsController* ctrl,
+ PHY_IPhysicsEnvironment* physenv,PyTypeObject *T)
+: m_ctrl(ctrl),m_physenv(physenv),PyObjectPlus(T)
+{
+}
+
+KX_PhysicsObjectWrapper::~KX_PhysicsObjectWrapper()
+{
+}
+
+
+PyObject* KX_PhysicsObjectWrapper::PySetPosition(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ float x,y,z;
+ if (PyArg_ParseTuple(args,"fff",&x,&y,&z))
+ {
+ m_ctrl->setPosition(x,y,z);
+ }
+ Py_INCREF(Py_None); return Py_None;
+}
+
+
+PyObject* KX_PhysicsObjectWrapper::PySetLinearVelocity(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ float x,y,z;
+ int local;
+ if (PyArg_ParseTuple(args,"fffi",&x,&y,&z,&local))
+ {
+ m_ctrl->SetLinearVelocity(x,y,z,local != 0);
+ }
+ Py_INCREF(Py_None); return Py_None;
+}
+
+PyObject* KX_PhysicsObjectWrapper::PySetAngularVelocity(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ float x,y,z;
+ int local;
+ if (PyArg_ParseTuple(args,"fffi",&x,&y,&z,&local))
+ {
+ m_ctrl->SetAngularVelocity(x,y,z,local != 0);
+ }
+ Py_INCREF(Py_None); return Py_None;
+}
+
+PyObject* KX_PhysicsObjectWrapper::PySetActive(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ int active;
+ if (PyArg_ParseTuple(args,"i",&active))
+ {
+ m_ctrl->SetActive(active!=0);
+ }
+ Py_INCREF(Py_None); return Py_None;
+}
+
+
+
+
+//python specific stuff
+PyTypeObject KX_PhysicsObjectWrapper::Type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0,
+ "KX_PhysicsObjectWrapper",
+ sizeof(KX_PhysicsObjectWrapper),
+ 0,
+ PyDestructor,
+ 0,
+ __getattr,
+ __setattr,
+ 0, //&MyPyCompare,
+ __repr,
+ 0, //&cvalue_as_number,
+ 0,
+ 0,
+ 0,
+ 0
+};
+
+PyParentObject KX_PhysicsObjectWrapper::Parents[] = {
+ &KX_PhysicsObjectWrapper::Type,
+ NULL
+};
+
+PyObject* KX_PhysicsObjectWrapper::_getattr(char* attr)
+{
+ _getattr_up(PyObjectPlus);
+}
+
+
+int KX_PhysicsObjectWrapper::_setattr(char* attr,PyObject* pyobj)
+{
+
+ PyTypeObject* type = pyobj->ob_type;
+ int result = 1;
+
+
+ if (type == &PyInt_Type)
+ {
+ result = 0;
+ }
+ if (type == &PyString_Type)
+ {
+ result = 0;
+ }
+ if (result)
+ result = PyObjectPlus::_setattr(attr,pyobj);
+ return result;
+};
+
+
+PyMethodDef KX_PhysicsObjectWrapper::Methods[] = {
+ {"setPosition",(PyCFunction) KX_PhysicsObjectWrapper::sPySetPosition, METH_VARARGS},
+ {"setLinearVelocity",(PyCFunction) KX_PhysicsObjectWrapper::sPySetLinearVelocity, METH_VARARGS},
+ {"setAngularVelocity",(PyCFunction) KX_PhysicsObjectWrapper::sPySetAngularVelocity, METH_VARARGS},
+ {"setActive",(PyCFunction) KX_PhysicsObjectWrapper::sPySetActive, METH_VARARGS},
+ {NULL,NULL} //Sentinel
+};
diff --git a/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.h b/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.h
new file mode 100644
index 00000000000..de384cb5932
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.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 PHYP_PHYSICSOBJECT_WRAPPER
+#define PHYP_PHYSICSOBJECT_WRAPPER
+
+#include "Value.h"
+#include "PHY_DynamicTypes.h"
+
+class KX_PhysicsObjectWrapper : public PyObjectPlus
+{
+ Py_Header;
+
+ PyObject* _getattr(char* attr);
+ virtual int _setattr(char *attr, PyObject *value);
+public:
+ KX_PhysicsObjectWrapper(class PHY_IPhysicsController* ctrl,class PHY_IPhysicsEnvironment* physenv,PyTypeObject *T = &Type);
+ virtual ~KX_PhysicsObjectWrapper();
+
+ KX_PYMETHOD(KX_PhysicsObjectWrapper , SetPosition);
+ KX_PYMETHOD(KX_PhysicsObjectWrapper,SetLinearVelocity);
+ KX_PYMETHOD(KX_PhysicsObjectWrapper,SetAngularVelocity);
+ KX_PYMETHOD(KX_PhysicsObjectWrapper,SetActive);
+
+private:
+ class PHY_IPhysicsController* m_ctrl;
+ PHY_IPhysicsEnvironment* m_physenv;
+};
+
+#endif //PHYP_PHYSICSOBJECT_WRAPPER
diff --git a/source/gameengine/Ketsji/KX_PhysicsPropertiesobsolete.h b/source/gameengine/Ketsji/KX_PhysicsPropertiesobsolete.h
new file mode 100644
index 00000000000..84a9133d471
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_PhysicsPropertiesobsolete.h
@@ -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 *****
+ */
+#ifndef KX_PROPSH
+#define KX_PROPSH
+
+#include <MT_Scalar.h>
+
+// Properties of dynamic objects
+struct KX_ShapeProps {
+ MT_Scalar m_mass; // Total mass
+ MT_Scalar m_inertia; // Inertia, should be a tensor some time
+ MT_Scalar m_lin_drag; // Linear drag (air, water) 0 = concrete, 1 = vacuum
+ MT_Scalar m_ang_drag; // Angular drag
+ MT_Scalar m_friction_scaling[3]; // Scaling for anisotropic friction. Component in range [0, 1]
+ bool m_do_anisotropic; // Should I do anisotropic friction?
+ bool m_do_fh; // Should the object have a linear Fh spring?
+ bool m_do_rot_fh; // Should the object have an angular Fh spring?
+};
+
+
+// Properties of collidable objects (non-ghost objects)
+struct KX_MaterialProps {
+ MT_Scalar m_restitution; // restitution of energie after a collision 0 = inelastic, 1 = elastic
+ MT_Scalar m_friction; // Coulomb friction (= ratio between the normal en maximum friction force)
+ MT_Scalar m_fh_spring; // Spring constant (both linear and angular)
+ MT_Scalar m_fh_damping; // Damping factor (linear and angular) in range [0, 1]
+ MT_Scalar m_fh_distance; // The range above the surface where Fh is active.
+ bool m_fh_normal; // Should the object slide off slopes?
+};
+
+#endif //KX_PROPSH
diff --git a/source/gameengine/Ketsji/KX_PositionInterpolator.cpp b/source/gameengine/Ketsji/KX_PositionInterpolator.cpp
new file mode 100644
index 00000000000..96af6e3ccf3
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_PositionInterpolator.cpp
@@ -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 *****
+ */
+
+#include "KX_PositionInterpolator.h"
+
+
+#include "MT_Point3.h"
+#include "KX_IScalarInterpolator.h"
+
+void KX_PositionInterpolator::Execute(float currentTime) const {
+ m_target.setValue(m_ipos[0]->GetValue(currentTime),
+ m_ipos[1]->GetValue(currentTime),
+ m_ipos[2]->GetValue(currentTime));
+}
diff --git a/source/gameengine/Ketsji/KX_PositionInterpolator.h b/source/gameengine/Ketsji/KX_PositionInterpolator.h
new file mode 100644
index 00000000000..cdc8192528a
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_PositionInterpolator.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 KX_POSITIONINTERPOLATOR
+#define KX_POSITIONINTERPOLATOR
+
+#include "KX_IInterpolator.h"
+
+class MT_Point3;
+class KX_IScalarInterpolator;
+
+class KX_PositionInterpolator : public KX_IInterpolator {
+public:
+ KX_PositionInterpolator(MT_Point3& target,
+ KX_IScalarInterpolator *ipos[]) :
+ m_target(target)
+ {
+ m_ipos[0] = ipos[0];
+ m_ipos[1] = ipos[1];
+ m_ipos[2] = ipos[2];
+ }
+
+ virtual void Execute(float currentTime) const;
+
+private:
+ MT_Point3& m_target;
+ KX_IScalarInterpolator *m_ipos[3];
+};
+
+#endif
diff --git a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp
new file mode 100644
index 00000000000..67a40639a13
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp
@@ -0,0 +1,193 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "KX_PyConstraintBinding.h"
+#include "PHY_IPhysicsEnvironment.h"
+#include "KX_ConstraintWrapper.h"
+#include "KX_PhysicsObjectWrapper.h"
+#include "PHY_IPhysicsController.h"
+
+
+// nasty glob variable to connect scripting language
+// if there is a better way (without global), please do so!
+static PHY_IPhysicsEnvironment* g_physics_env = NULL;
+
+static char PhysicsConstraints_module_documentation[] =
+"This is the Python API for the Physics Constraints";
+
+
+static char gPySetGravity__doc__[] = "setGravity(float x,float y,float z)";
+static char gPyCreateConstraint__doc__[] = "createConstraint(ob1,ob2,float restLength,float restitution,float damping)";
+static char gPyRemoveConstraint__doc__[] = "removeConstraint(constraint id)";
+
+static PyObject* gPySetGravity(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ float x,y,z;
+ int len = PyTuple_Size(args);
+ if ((len == 3) && PyArg_ParseTuple(args,"fff",&x,&y,&z))
+ {
+ if (g_physics_env)
+ g_physics_env->setGravity(x,y,z);
+ }
+ Py_INCREF(Py_None); return Py_None;
+}
+
+
+
+
+static PyObject* gPyCreateConstraint(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ int physicsid=0,physicsid2 = 0,constrainttype=0,extrainfo=0;
+ int len = PyTuple_Size(args);
+ int success = 1;
+ float pivotX=1,pivotY=1,pivotZ=1,axisX=0,axisY=0,axisZ=1;
+ if (len == 3)
+ {
+ success = PyArg_ParseTuple(args,"iii",&physicsid,&physicsid2,&constrainttype);
+ }
+ else
+ if (len ==6)
+ {
+ success = PyArg_ParseTuple(args,"iiifff",&physicsid,&physicsid2,&constrainttype,
+ &pivotX,&pivotY,&pivotZ);
+ }
+ else if (len == 9)
+ {
+ success = PyArg_ParseTuple(args,"iiiffffff",&physicsid,&physicsid2,&constrainttype,
+ &pivotX,&pivotY,&pivotZ,&axisX,&axisY,&axisZ);
+ }
+ else if (len==4)
+ {
+ success = PyArg_ParseTuple(args,"iiii",&physicsid,&physicsid2,&constrainttype,&extrainfo);
+ pivotX=extrainfo;
+ }
+
+ if (success)
+ {
+ if (g_physics_env)
+ {
+
+ PHY_IPhysicsController* physctrl = (PHY_IPhysicsController*) physicsid;
+ PHY_IPhysicsController* physctrl2 = (PHY_IPhysicsController*) physicsid2;
+ if (physctrl) //TODO:check for existance of this pointer!
+ {
+ int constraintid = g_physics_env->createConstraint(physctrl,physctrl2,(enum PHY_ConstraintType)constrainttype,pivotX,pivotY,pivotZ,axisX,axisY,axisZ);
+
+ KX_ConstraintWrapper* wrap = new KX_ConstraintWrapper((enum PHY_ConstraintType)constrainttype,constraintid,g_physics_env);
+
+
+ return wrap;
+ }
+
+
+ }
+ }
+
+ Py_INCREF(Py_None); return Py_None;
+}
+
+
+static PyObject* gPyRemoveConstraint(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ int constraintid;
+
+ int len = PyTuple_Size(args);
+ if (PyArg_ParseTuple(args,"i",&constraintid))
+ {
+ if (g_physics_env)
+ {
+ g_physics_env->removeConstraint(constraintid);
+ }
+ }
+ Py_INCREF(Py_None); return Py_None;
+}
+
+
+
+
+
+static struct PyMethodDef physicsconstraints_methods[] = {
+ {"setGravity",(PyCFunction) gPySetGravity,
+ METH_VARARGS, gPySetGravity__doc__},
+
+ {"createConstraint",(PyCFunction) gPyCreateConstraint,
+ METH_VARARGS, gPyCreateConstraint__doc__},
+ {"removeConstraint",(PyCFunction) gPyRemoveConstraint,
+ METH_VARARGS, gPyRemoveConstraint__doc__},
+
+ //sentinel
+ { NULL, (PyCFunction) NULL, 0, NULL }
+};
+
+
+
+PyObject* initPythonConstraintBinding()
+{
+
+ PyObject* ErrorObject;
+ PyObject* m;
+ PyObject* d;
+
+ m = Py_InitModule4("PhysicsConstraints", physicsconstraints_methods,
+ PhysicsConstraints_module_documentation,
+ (PyObject*)NULL,PYTHON_API_VERSION);
+
+ // Add some symbolic constants to the module
+ d = PyModule_GetDict(m);
+ ErrorObject = PyString_FromString("PhysicsConstraints.error");
+ PyDict_SetItemString(d, "error", ErrorObject);
+
+ // XXXX Add constants here
+
+ // Check for errors
+ if (PyErr_Occurred())
+ {
+ Py_FatalError("can't initialize module PhysicsConstraints");
+ }
+
+ return d;
+}
+
+
+void KX_RemovePythonConstraintBinding()
+{
+}
+
+void PHY_SetActiveEnvironment(class PHY_IPhysicsEnvironment* env)
+{
+ g_physics_env = env;
+}
diff --git a/source/gameengine/Ketsji/KX_PyConstraintBinding.h b/source/gameengine/Ketsji/KX_PyConstraintBinding.h
new file mode 100644
index 00000000000..f584649b579
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_PyConstraintBinding.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 *****
+ */
+#ifndef PHY_PYTHON_CONSTRAINTBINDING
+#define PHY_PYTHON_CONSTRAINTBINDING
+
+
+#include <Python.h>
+
+
+PyObject* initPythonConstraintBinding();
+void PHY_RemovePythonConstraintBinding();
+void PHY_SetActiveEnvironment(class PHY_IPhysicsEnvironment* env);
+
+#endif //PHY_PYTHON_CONSTRAINTBINDING
diff --git a/source/gameengine/Ketsji/KX_Python.h b/source/gameengine/Ketsji/KX_Python.h
new file mode 100644
index 00000000000..705b01aa606
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_Python.h
@@ -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 *****
+ */
+#ifndef KX_PYTHON_H
+#define KX_PYTHON_H
+
+//#define USE_DL_EXPORT
+#include "Python.h"
+
+#endif // KX_PYTHON_H
diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp
new file mode 100644
index 00000000000..7b6c3a823ca
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_PythonInit.cpp
@@ -0,0 +1,832 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * Initialize Python thingies.
+ */
+
+#ifdef WIN32
+#pragma warning (disable : 4786)
+#endif //WIN32
+
+#include "KX_PythonInit.h"
+
+#include "SCA_IInputDevice.h"
+#include "SCA_PropertySensor.h"
+#include "SCA_RandomActuator.h"
+#include "KX_ConstraintActuator.h"
+#include "KX_IpoActuator.h"
+#include "RAS_IRasterizer.h"
+#include "RAS_ICanvas.h"
+#include "MT_Vector3.h"
+#include "MT_Point3.h"
+#include "ListValue.h"
+#include "KX_Scene.h"
+#include "SND_DeviceManager.h"
+
+
+static void setSandbox(TPythonSecurityLevel level);
+
+
+// 'local' copy of canvas ptr, for window height/width python scripts
+static RAS_ICanvas* gp_Canvas = NULL;
+static KX_Scene* gp_KetsjiScene = NULL;
+static RAS_IRasterizer* gp_Rasterizer = NULL;
+
+/* Macro for building the keyboard translation */
+//#define KX_MACRO_addToDict(dict, name) PyDict_SetItemString(dict, #name, PyInt_FromLong(SCA_IInputDevice::KX_##name))
+#define KX_MACRO_addToDict(dict, name) PyDict_SetItemString(dict, #name, PyInt_FromLong(name))
+/* For the defines for types from logic bricks, we do stuff explicitly... */
+#define KX_MACRO_addTypesToDict(dict, name, name2) PyDict_SetItemString(dict, #name, PyInt_FromLong(name2))
+
+
+// temporarily python stuff, will be put in another place later !
+#include "KX_Python.h"
+#include "SCA_PythonController.h"
+// List of methods defined in the module
+
+static PyObject* ErrorObject;
+STR_String gPyGetRandomFloat_doc="getRandomFloat returns a random floating point value in the range [0..1)";
+
+static PyObject* gPyGetRandomFloat(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ return PyFloat_FromDouble(MT_random());
+}
+
+
+
+MT_Point3 GlobalConvertPythonPylist(PyObject* pylist)
+{
+ bool error=false;
+ MT_Point3 pos;
+ if (pylist->ob_type == &CListValue::Type)
+ {
+ CListValue* listval = (CListValue*) pylist;
+ if (listval->GetCount() == 3)
+ {
+ int index;
+ for (index=0;index<3;index++)
+ {
+ pos[index] = listval->GetValue(index)->GetNumber();
+ }
+ } else
+ {
+ error = true;
+ }
+
+ } else
+ {
+
+ // assert the list is long enough...
+ int numitems = PyList_Size(pylist);
+ if (numitems == 3)
+ {
+ int index;
+ for (index=0;index<3;index++)
+ {
+ pos[index] = PyFloat_AsDouble(PyList_GetItem(pylist,index));
+ }
+ }
+ else
+ {
+ error = true;
+ }
+
+ }
+ return pos;
+}
+
+
+
+MT_Point3 GlobalConvertPythonVectorArg(PyObject* args)
+{
+ MT_Point3 pos(0,0,0);
+ PyObject* pylist;
+ PyArg_ParseTuple(args,"O",&pylist);
+
+ pos = GlobalConvertPythonPylist(pylist);
+
+ return pos;
+}
+
+
+
+static PyObject* gPySetGravity(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ MT_Vector3 vec = GlobalConvertPythonVectorArg(args);
+
+ if (gp_KetsjiScene)
+ gp_KetsjiScene->SetGravity(vec);
+
+ Py_Return;
+}
+
+
+static bool usedsp = false;
+
+// this gets a pointer to an array filled with floats
+static PyObject* gPyGetSpectrum(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ SND_IAudioDevice* audiodevice = SND_DeviceManager::Instance();
+
+ PyObject* resultlist = PyList_New(512);
+
+ if (audiodevice)
+ {
+ if (!usedsp)
+ {
+ audiodevice->StartUsingDSP();
+ usedsp = true;
+ }
+
+ float* spectrum = audiodevice->GetSpectrum();
+
+ for (int index = 0; index < 512; index++)
+ {
+ PyList_SetItem(resultlist, index, PyFloat_FromDouble(spectrum[index]));
+ }
+ }
+
+ return resultlist;
+}
+
+
+
+static void gPyStartDSP(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ SND_IAudioDevice* audiodevice = SND_DeviceManager::Instance();
+
+ if (audiodevice)
+ {
+ if (!usedsp)
+ {
+ audiodevice->StartUsingDSP();
+ usedsp = true;
+ }
+ }
+}
+
+
+
+static void gPyStopDSP(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ SND_IAudioDevice* audiodevice = SND_DeviceManager::Instance();
+
+ if (audiodevice)
+ {
+ if (usedsp)
+ {
+ audiodevice->StopUsingDSP();
+ usedsp = false;
+ }
+ }
+}
+
+
+
+static struct PyMethodDef game_methods[] = {
+ {"getCurrentController",
+ (PyCFunction) SCA_PythonController::sPyGetCurrentController,
+ METH_VARARGS, SCA_PythonController::sPyGetCurrentController__doc__},
+ {"addActiveActuator",(PyCFunction) SCA_PythonController::sPyAddActiveActuator,
+ METH_VARARGS, SCA_PythonController::sPyAddActiveActuator__doc__},
+ {"getRandomFloat",(PyCFunction) gPyGetRandomFloat,
+ METH_VARARGS,gPyGetRandomFloat_doc.Ptr()},
+ {"setGravity",(PyCFunction) gPySetGravity, METH_VARARGS,"set Gravitation"},
+ {"getSpectrum",(PyCFunction) gPyGetSpectrum, METH_VARARGS,"get audio spectrum"},
+ {"stopDSP",(PyCFunction) gPyStopDSP, METH_VARARGS,"stop using the audio dsp (for performance reasons)"},
+ {NULL, (PyCFunction) NULL, 0, NULL }
+};
+
+
+static PyObject* gPyGetWindowHeight(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ int height = (gp_Canvas ? gp_Canvas->GetHeight() : 0);
+
+ PyObject* heightval = PyInt_FromLong(height);
+ return heightval;
+}
+
+
+
+static PyObject* gPyGetWindowWidth(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+
+
+ int width = (gp_Canvas ? gp_Canvas->GetWidth() : 0);
+
+ PyObject* widthval = PyInt_FromLong(width);
+ return widthval;
+}
+
+
+
+// temporarility visibility thing, will be moved to rasterizer/renderer later
+bool gUseVisibilityTemp = false;
+
+static PyObject* gPyEnableVisibility(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ int visible;
+ if (PyArg_ParseTuple(args,"i",&visible))
+ {
+ gUseVisibilityTemp = (visible != 0);
+ }
+ else
+ {
+ Py_Return;
+ }
+ Py_Return;
+}
+
+
+
+static PyObject* gPyShowMouse(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ int visible;
+ if (PyArg_ParseTuple(args,"i",&visible))
+ {
+ if (visible)
+ {
+ if (gp_Canvas)
+ gp_Canvas->SetMouseState(RAS_ICanvas::MOUSE_NORMAL);
+ } else
+ {
+ if (gp_Canvas)
+ gp_Canvas->SetMouseState(RAS_ICanvas::MOUSE_INVISIBLE);
+ }
+ }
+
+ Py_Return;
+}
+
+
+
+static PyObject* gPySetMousePosition(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ int x,y;
+ if (PyArg_ParseTuple(args,"ii",&x,&y))
+ {
+ if (gp_Canvas)
+ gp_Canvas->SetMousePosition(x,y);
+ }
+
+ Py_Return;
+}
+
+
+
+static PyObject* gPySetBackgroundColor(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+
+ MT_Vector3 vec = GlobalConvertPythonVectorArg(args);
+
+ if (gp_Canvas)
+ {
+ gp_Rasterizer->SetBackColor(vec[0],vec[1],vec[2],0.0);
+ }
+ Py_Return;
+}
+
+
+
+static PyObject* gPySetMistColor(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+
+ MT_Vector3 vec = GlobalConvertPythonVectorArg(args);
+
+ if (gp_Rasterizer)
+ {
+ gp_Rasterizer->SetFogColor(vec[0],vec[1],vec[2]);
+ }
+ Py_Return;
+}
+
+
+
+static PyObject* gPySetMistStart(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+
+ float miststart;
+ if (PyArg_ParseTuple(args,"f",&miststart))
+ {
+ if (gp_Rasterizer)
+ {
+ gp_Rasterizer->SetFogStart(miststart);
+ }
+ }
+ Py_Return;
+}
+
+
+
+static PyObject* gPySetMistEnd(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+
+ float mistend;
+ if (PyArg_ParseTuple(args,"f",&mistend))
+ {
+ if (gp_Rasterizer)
+ {
+ gp_Rasterizer->SetFogEnd(mistend);
+ }
+ }
+ Py_Return;
+}
+
+
+
+static PyObject* gPyMakeScreenshot(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ char* filename;
+ if (PyArg_ParseTuple(args,"s",&filename))
+ {
+ if (gp_Canvas)
+ {
+ gp_Canvas->MakeScreenShot(filename);
+ }
+ }
+ Py_Return;
+}
+
+
+
+STR_String gPyGetWindowHeight__doc__="getWindowHeight doc";
+STR_String gPyGetWindowWidth__doc__="getWindowWidth doc";
+STR_String gPyEnableVisibility__doc__="enableVisibility doc";
+STR_String gPyMakeScreenshot__doc__="make Screenshot doc";
+STR_String gPyShowMouse__doc__="showMouse(bool visible)";
+STR_String gPySetMousePosition__doc__="setMousePosition(int x,int y)";
+
+static struct PyMethodDef rasterizer_methods[] = {
+ {"getWindowWidth",(PyCFunction) gPyGetWindowWidth,
+ METH_VARARGS, gPyGetWindowWidth__doc__.Ptr()},
+ {"getWindowHeight",(PyCFunction) gPyGetWindowHeight,
+ METH_VARARGS, gPyGetWindowHeight__doc__.Ptr()},
+ {"makeScreenshot",(PyCFunction)gPyMakeScreenshot,
+ METH_VARARGS, gPyMakeScreenshot__doc__.Ptr()},
+ {"enableVisibility",(PyCFunction) gPyEnableVisibility,
+ METH_VARARGS, gPyEnableVisibility__doc__.Ptr()},
+ {"showMouse",(PyCFunction) gPyShowMouse,
+ METH_VARARGS, gPyShowMouse__doc__.Ptr()},
+ {"setMousePosition",(PyCFunction) gPySetMousePosition,
+ METH_VARARGS, gPySetMousePosition__doc__.Ptr()},
+ {"setBackgroundColor",(PyCFunction)gPySetBackgroundColor,METH_VARARGS,"set Background Color (rgb)"},
+ {"setMistColor",(PyCFunction)gPySetMistColor,METH_VARARGS,"set Mist Color (rgb)"},
+ {"setMistStart",(PyCFunction)gPySetMistStart,METH_VARARGS,"set Mist Start(rgb)"},
+ {"setMistEnd",(PyCFunction)gPySetMistEnd,METH_VARARGS,"set Mist End(rgb)"},
+
+ { NULL, (PyCFunction) NULL, 0, NULL }
+};
+
+
+
+// Initialization function for the module (*must* be called initGameLogic)
+
+static char GameLogic_module_documentation[] =
+"This is the Python API for the game engine of GameLogic"
+;
+
+static char Rasterizer_module_documentation[] =
+"This is the Python API for the game engine of Rasterizer"
+;
+
+
+
+PyObject* initGameLogic(KX_Scene* scene) // quick hack to get gravity hook
+{
+ PyObject* m;
+ PyObject* d;
+
+ gp_KetsjiScene = scene;
+
+ gUseVisibilityTemp=false;
+
+ // Create the module and add the functions
+ m = Py_InitModule4("GameLogic", game_methods,
+ GameLogic_module_documentation,
+ (PyObject*)NULL,PYTHON_API_VERSION);
+
+ // Add some symbolic constants to the module
+ d = PyModule_GetDict(m);
+
+ ErrorObject = PyString_FromString("GameLogic.error");
+ PyDict_SetItemString(d, "error", ErrorObject);
+
+ // XXXX Add constants here
+ /* To use logic bricks, we need some sort of constants. Here, we associate */
+ /* constants and sumbolic names. Add them to dictionary d. */
+
+ /* 1. true and false: needed for everyone */
+ KX_MACRO_addTypesToDict(d, KX_TRUE, SCA_ILogicBrick::KX_TRUE);
+ KX_MACRO_addTypesToDict(d, KX_FALSE, SCA_ILogicBrick::KX_FALSE);
+
+ /* 2. Property sensor */
+ KX_MACRO_addTypesToDict(d, KX_PROPSENSOR_EQUAL, SCA_PropertySensor::KX_PROPSENSOR_EQUAL);
+ KX_MACRO_addTypesToDict(d, KX_PROPSENSOR_NOTEQUAL, SCA_PropertySensor::KX_PROPSENSOR_NOTEQUAL);
+ KX_MACRO_addTypesToDict(d, KX_PROPSENSOR_INTERVAL, SCA_PropertySensor::KX_PROPSENSOR_INTERVAL);
+ KX_MACRO_addTypesToDict(d, KX_PROPSENSOR_CHANGED, SCA_PropertySensor::KX_PROPSENSOR_CHANGED);
+ KX_MACRO_addTypesToDict(d, KX_PROPSENSOR_EXPRESSION, SCA_PropertySensor::KX_PROPSENSOR_EXPRESSION);
+
+ /* 3. Constraint actuator */
+ KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_LOCX, KX_ConstraintActuator::KX_ACT_CONSTRAINT_LOCX);
+ KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_LOCY, KX_ConstraintActuator::KX_ACT_CONSTRAINT_LOCY);
+ KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_LOCZ, KX_ConstraintActuator::KX_ACT_CONSTRAINT_LOCZ);
+ KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_ROTX, KX_ConstraintActuator::KX_ACT_CONSTRAINT_ROTX);
+ KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_ROTY, KX_ConstraintActuator::KX_ACT_CONSTRAINT_ROTY);
+ KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_ROTZ, KX_ConstraintActuator::KX_ACT_CONSTRAINT_ROTZ);
+
+ /* 4. Ipo actuator, simple part */
+ KX_MACRO_addTypesToDict(d, KX_IPOACT_PLAY, KX_IpoActuator::KX_ACT_IPO_PLAY);
+ KX_MACRO_addTypesToDict(d, KX_IPOACT_PINGPONG, KX_IpoActuator::KX_ACT_IPO_PINGPONG);
+ KX_MACRO_addTypesToDict(d, KX_IPOACT_FLIPPER, KX_IpoActuator::KX_ACT_IPO_FLIPPER);
+ KX_MACRO_addTypesToDict(d, KX_IPOACT_LOOPSTOP, KX_IpoActuator::KX_ACT_IPO_LOOPSTOP);
+ KX_MACRO_addTypesToDict(d, KX_IPOACT_LOOPEND, KX_IpoActuator::KX_ACT_IPO_LOOPEND);
+
+ /* 5. Random distribution types */
+ KX_MACRO_addTypesToDict(d, KX_RANDOMACT_BOOL_CONST, SCA_RandomActuator::KX_RANDOMACT_BOOL_CONST);
+ KX_MACRO_addTypesToDict(d, KX_RANDOMACT_BOOL_UNIFORM, SCA_RandomActuator::KX_RANDOMACT_BOOL_UNIFORM);
+ KX_MACRO_addTypesToDict(d, KX_RANDOMACT_BOOL_BERNOUILLI, SCA_RandomActuator::KX_RANDOMACT_BOOL_BERNOUILLI);
+ KX_MACRO_addTypesToDict(d, KX_RANDOMACT_INT_CONST, SCA_RandomActuator::KX_RANDOMACT_INT_CONST);
+ KX_MACRO_addTypesToDict(d, KX_RANDOMACT_INT_UNIFORM, SCA_RandomActuator::KX_RANDOMACT_INT_UNIFORM);
+ KX_MACRO_addTypesToDict(d, KX_RANDOMACT_INT_POISSON, SCA_RandomActuator::KX_RANDOMACT_INT_POISSON);
+ KX_MACRO_addTypesToDict(d, KX_RANDOMACT_FLOAT_CONST, SCA_RandomActuator::KX_RANDOMACT_FLOAT_CONST);
+ KX_MACRO_addTypesToDict(d, KX_RANDOMACT_FLOAT_UNIFORM, SCA_RandomActuator::KX_RANDOMACT_FLOAT_UNIFORM);
+ KX_MACRO_addTypesToDict(d, KX_RANDOMACT_FLOAT_NORMAL, SCA_RandomActuator::KX_RANDOMACT_FLOAT_NORMAL);
+ KX_MACRO_addTypesToDict(d, KX_RANDOMACT_FLOAT_NEGATIVE_EXPONENTIAL, SCA_RandomActuator::KX_RANDOMACT_FLOAT_NEGATIVE_EXPONENTIAL);
+
+ // Check for errors
+ if (PyErr_Occurred())
+ {
+ Py_FatalError("can't initialize module GameLogic");
+ }
+
+ return d;
+}
+
+
+
+// Python Sandbox code
+// override builtin functions import() and open()
+
+
+PyObject *KXpy_open(PyObject *self, PyObject *args)
+{
+ PyErr_SetString(PyExc_RuntimeError, "Sandbox: open() function disabled!\nGame Scripts should not use this function.");
+ return NULL;
+}
+
+
+
+PyObject *KXpy_import(PyObject *self, PyObject *args)
+{
+ char *name;
+ PyObject *globals = NULL;
+ PyObject *locals = NULL;
+ PyObject *fromlist = NULL;
+ PyObject *l, *m, *n;
+
+ if (!PyArg_ParseTuple(args, "s|OOO:m_import",
+ &name, &globals, &locals, &fromlist))
+ return NULL;
+
+ /* check for builtin modules */
+ m = PyImport_AddModule("sys");
+ l = PyObject_GetAttrString(m, "builtin_module_names");
+ n = PyString_FromString(name);
+
+ if (PySequence_Contains(l, n)) {
+ return PyImport_ImportModuleEx(name, globals, locals, fromlist);
+ }
+
+ /* quick hack for GamePython modules
+ TODO: register builtin modules properly by ExtendInittab */
+ if (!strcmp(name, "GameLogic") || !strcmp(name, "GameKeys") ||
+ !strcmp(name, "Rasterizer")) {
+ return PyImport_ImportModuleEx(name, globals, locals, fromlist);
+ }
+
+ PyErr_Format(PyExc_ImportError,
+ "Import of external Module %.20s not allowed.", name);
+ return NULL;
+
+}
+
+
+
+static PyMethodDef meth_open[] = {
+ { "open", KXpy_open, METH_VARARGS,
+ "(disabled)"}
+};
+
+
+static PyMethodDef meth_import[] = {
+ { "import", KXpy_import, METH_VARARGS,
+ "our own import"}
+};
+
+
+
+//static PyObject *g_oldopen = 0;
+//static PyObject *g_oldimport = 0;
+//static int g_security = 0;
+
+
+void setSandbox(TPythonSecurityLevel level)
+{
+ PyObject *m = PyImport_AddModule("__builtin__");
+ PyObject *d = PyModule_GetDict(m);
+ PyObject *meth = PyCFunction_New(meth_open, NULL);
+
+ switch (level) {
+ case psl_Highest:
+ //if (!g_security) {
+ //g_oldopen = PyDict_GetItemString(d, "open");
+ PyDict_SetItemString(d, "open", meth);
+ meth = PyCFunction_New(meth_import, NULL);
+ PyDict_SetItemString(d, "__import__", meth);
+ //g_security = level;
+ //}
+ break;
+ /*
+ case psl_Lowest:
+ if (g_security) {
+ PyDict_SetItemString(d, "open", g_oldopen);
+ PyDict_SetItemString(d, "__import__", g_oldimport);
+ g_security = level;
+ }
+ */
+ default:
+ break;
+ }
+}
+
+
+
+PyObject* initGamePythonScripting(const STR_String& progname, TPythonSecurityLevel level)
+{
+ STR_String pname = progname;
+ Py_SetProgramName(pname.Ptr());
+ Py_NoSiteFlag=1;
+ Py_FrozenFlag=1;
+ Py_Initialize();
+ setSandbox(level);
+
+ PyObject* moduleobj = PyImport_AddModule("__main__");
+ return PyModule_GetDict(moduleobj);
+}
+
+
+
+void exitGamePythonScripting()
+{
+ Py_Finalize();
+}
+
+
+
+PyObject* initRasterizer(RAS_IRasterizer* rasty,RAS_ICanvas* canvas)
+{
+ gp_Canvas = canvas;
+ gp_Rasterizer = rasty;
+
+
+ PyObject* m;
+ PyObject* d;
+
+ // Create the module and add the functions
+ m = Py_InitModule4("Rasterizer", rasterizer_methods,
+ Rasterizer_module_documentation,
+ (PyObject*)NULL,PYTHON_API_VERSION);
+
+ // Add some symbolic constants to the module
+ d = PyModule_GetDict(m);
+ ErrorObject = PyString_FromString("Rasterizer.error");
+ PyDict_SetItemString(d, "error", ErrorObject);
+
+ // XXXX Add constants here
+
+ // Check for errors
+ if (PyErr_Occurred())
+ {
+ Py_FatalError("can't initialize module Rasterizer");
+ }
+
+ return d;
+}
+
+
+
+/* ------------------------------------------------------------------------- */
+/* GameKeys: symbolic constants for key mapping */
+/* ------------------------------------------------------------------------- */
+
+static char GameKeys_module_documentation[] =
+"This modules provides defines for key-codes"
+;
+
+
+
+static struct PyMethodDef gamekeys_methods[] = {
+ { NULL, (PyCFunction) NULL, 0, NULL }
+};
+
+
+
+PyObject* initGameKeys()
+{
+ PyObject* m;
+ PyObject* d;
+
+ // Create the module and add the functions
+ m = Py_InitModule4("GameKeys", gamekeys_methods,
+ GameKeys_module_documentation,
+ (PyObject*)NULL,PYTHON_API_VERSION);
+
+ // Add some symbolic constants to the module
+ d = PyModule_GetDict(m);
+
+ // XXXX Add constants here
+
+ KX_MACRO_addTypesToDict(d, AKEY, SCA_IInputDevice::KX_AKEY);
+ KX_MACRO_addTypesToDict(d, BKEY, SCA_IInputDevice::KX_BKEY);
+ KX_MACRO_addTypesToDict(d, CKEY, SCA_IInputDevice::KX_CKEY);
+ KX_MACRO_addTypesToDict(d, DKEY, SCA_IInputDevice::KX_DKEY);
+ KX_MACRO_addTypesToDict(d, EKEY, SCA_IInputDevice::KX_EKEY);
+ KX_MACRO_addTypesToDict(d, FKEY, SCA_IInputDevice::KX_FKEY);
+ KX_MACRO_addTypesToDict(d, GKEY, SCA_IInputDevice::KX_GKEY);
+ KX_MACRO_addTypesToDict(d, HKEY, SCA_IInputDevice::KX_HKEY);
+ KX_MACRO_addTypesToDict(d, IKEY, SCA_IInputDevice::KX_IKEY);
+ KX_MACRO_addTypesToDict(d, JKEY, SCA_IInputDevice::KX_JKEY);
+ KX_MACRO_addTypesToDict(d, KKEY, SCA_IInputDevice::KX_KKEY);
+ KX_MACRO_addTypesToDict(d, LKEY, SCA_IInputDevice::KX_LKEY);
+ KX_MACRO_addTypesToDict(d, MKEY, SCA_IInputDevice::KX_MKEY);
+ KX_MACRO_addTypesToDict(d, NKEY, SCA_IInputDevice::KX_NKEY);
+ KX_MACRO_addTypesToDict(d, OKEY, SCA_IInputDevice::KX_OKEY);
+ KX_MACRO_addTypesToDict(d, PKEY, SCA_IInputDevice::KX_PKEY);
+ KX_MACRO_addTypesToDict(d, QKEY, SCA_IInputDevice::KX_QKEY);
+ KX_MACRO_addTypesToDict(d, RKEY, SCA_IInputDevice::KX_RKEY);
+ KX_MACRO_addTypesToDict(d, SKEY, SCA_IInputDevice::KX_SKEY);
+ KX_MACRO_addTypesToDict(d, TKEY, SCA_IInputDevice::KX_TKEY);
+ KX_MACRO_addTypesToDict(d, UKEY, SCA_IInputDevice::KX_UKEY);
+ KX_MACRO_addTypesToDict(d, VKEY, SCA_IInputDevice::KX_VKEY);
+ KX_MACRO_addTypesToDict(d, WKEY, SCA_IInputDevice::KX_WKEY);
+ KX_MACRO_addTypesToDict(d, XKEY, SCA_IInputDevice::KX_XKEY);
+ KX_MACRO_addTypesToDict(d, YKEY, SCA_IInputDevice::KX_YKEY);
+ KX_MACRO_addTypesToDict(d, ZKEY, SCA_IInputDevice::KX_ZKEY);
+
+ KX_MACRO_addTypesToDict(d, ZEROKEY, SCA_IInputDevice::KX_ZEROKEY);
+ KX_MACRO_addTypesToDict(d, ONEKEY, SCA_IInputDevice::KX_ONEKEY);
+ KX_MACRO_addTypesToDict(d, TWOKEY, SCA_IInputDevice::KX_TWOKEY);
+ KX_MACRO_addTypesToDict(d, THREEKEY, SCA_IInputDevice::KX_THREEKEY);
+ KX_MACRO_addTypesToDict(d, FOURKEY, SCA_IInputDevice::KX_FOURKEY);
+ KX_MACRO_addTypesToDict(d, FIVEKEY, SCA_IInputDevice::KX_FIVEKEY);
+ KX_MACRO_addTypesToDict(d, SIXKEY, SCA_IInputDevice::KX_SIXKEY);
+ KX_MACRO_addTypesToDict(d, SEVENKEY, SCA_IInputDevice::KX_SEVENKEY);
+ KX_MACRO_addTypesToDict(d, EIGHTKEY, SCA_IInputDevice::KX_EIGHTKEY);
+ KX_MACRO_addTypesToDict(d, NINEKEY, SCA_IInputDevice::KX_NINEKEY);
+
+ KX_MACRO_addTypesToDict(d, CAPSLOCKKEY, SCA_IInputDevice::KX_CAPSLOCKKEY);
+
+ KX_MACRO_addTypesToDict(d, LEFTCTRLKEY, SCA_IInputDevice::KX_LEFTCTRLKEY);
+ KX_MACRO_addTypesToDict(d, LEFTALTKEY, SCA_IInputDevice::KX_LEFTALTKEY);
+ KX_MACRO_addTypesToDict(d, RIGHTALTKEY, SCA_IInputDevice::KX_RIGHTALTKEY);
+ KX_MACRO_addTypesToDict(d, RIGHTCTRLKEY, SCA_IInputDevice::KX_RIGHTCTRLKEY);
+ KX_MACRO_addTypesToDict(d, RIGHTSHIFTKEY, SCA_IInputDevice::KX_RIGHTSHIFTKEY);
+ KX_MACRO_addTypesToDict(d, LEFTSHIFTKEY, SCA_IInputDevice::KX_LEFTSHIFTKEY);
+
+ KX_MACRO_addTypesToDict(d, ESCKEY, SCA_IInputDevice::KX_ESCKEY);
+ KX_MACRO_addTypesToDict(d, TABKEY, SCA_IInputDevice::KX_TABKEY);
+ KX_MACRO_addTypesToDict(d, RETKEY, SCA_IInputDevice::KX_RETKEY);
+ KX_MACRO_addTypesToDict(d, SPACEKEY, SCA_IInputDevice::KX_SPACEKEY);
+ KX_MACRO_addTypesToDict(d, LINEFEEDKEY, SCA_IInputDevice::KX_LINEFEEDKEY);
+ KX_MACRO_addTypesToDict(d, BACKSPACEKEY, SCA_IInputDevice::KX_BACKSPACEKEY);
+ KX_MACRO_addTypesToDict(d, DELKEY, SCA_IInputDevice::KX_DELKEY);
+ KX_MACRO_addTypesToDict(d, SEMICOLONKEY, SCA_IInputDevice::KX_SEMICOLONKEY);
+ KX_MACRO_addTypesToDict(d, PERIODKEY, SCA_IInputDevice::KX_PERIODKEY);
+ KX_MACRO_addTypesToDict(d, COMMAKEY, SCA_IInputDevice::KX_COMMAKEY);
+ KX_MACRO_addTypesToDict(d, QUOTEKEY, SCA_IInputDevice::KX_QUOTEKEY);
+ KX_MACRO_addTypesToDict(d, ACCENTGRAVEKEY, SCA_IInputDevice::KX_ACCENTGRAVEKEY);
+ KX_MACRO_addTypesToDict(d, MINUSKEY, SCA_IInputDevice::KX_MINUSKEY);
+ KX_MACRO_addTypesToDict(d, SLASHKEY, SCA_IInputDevice::KX_SLASHKEY);
+ KX_MACRO_addTypesToDict(d, BACKSLASHKEY, SCA_IInputDevice::KX_BACKSLASHKEY);
+ KX_MACRO_addTypesToDict(d, EQUALKEY, SCA_IInputDevice::KX_EQUALKEY);
+ KX_MACRO_addTypesToDict(d, LEFTBRACKETKEY, SCA_IInputDevice::KX_LEFTBRACKETKEY);
+ KX_MACRO_addTypesToDict(d, RIGHTBRACKETKEY, SCA_IInputDevice::KX_RIGHTBRACKETKEY);
+
+ KX_MACRO_addTypesToDict(d, LEFTARROWKEY, SCA_IInputDevice::KX_LEFTARROWKEY);
+ KX_MACRO_addTypesToDict(d, DOWNARROWKEY, SCA_IInputDevice::KX_DOWNARROWKEY);
+ KX_MACRO_addTypesToDict(d, RIGHTARROWKEY, SCA_IInputDevice::KX_RIGHTARROWKEY);
+ KX_MACRO_addTypesToDict(d, UPARROWKEY, SCA_IInputDevice::KX_UPARROWKEY);
+
+ KX_MACRO_addTypesToDict(d, PAD2 , SCA_IInputDevice::KX_PAD2);
+ KX_MACRO_addTypesToDict(d, PAD4 , SCA_IInputDevice::KX_PAD4);
+ KX_MACRO_addTypesToDict(d, PAD6 , SCA_IInputDevice::KX_PAD6);
+ KX_MACRO_addTypesToDict(d, PAD8 , SCA_IInputDevice::KX_PAD8);
+
+ KX_MACRO_addTypesToDict(d, PAD1 , SCA_IInputDevice::KX_PAD1);
+ KX_MACRO_addTypesToDict(d, PAD3 , SCA_IInputDevice::KX_PAD3);
+ KX_MACRO_addTypesToDict(d, PAD5 , SCA_IInputDevice::KX_PAD5);
+ KX_MACRO_addTypesToDict(d, PAD7 , SCA_IInputDevice::KX_PAD7);
+ KX_MACRO_addTypesToDict(d, PAD9 , SCA_IInputDevice::KX_PAD9);
+
+ KX_MACRO_addTypesToDict(d, PADPERIOD, SCA_IInputDevice::KX_PADPERIOD);
+ KX_MACRO_addTypesToDict(d, PADSLASHKEY, SCA_IInputDevice::KX_PADSLASHKEY);
+ KX_MACRO_addTypesToDict(d, PADASTERKEY, SCA_IInputDevice::KX_PADASTERKEY);
+
+
+ KX_MACRO_addTypesToDict(d, PAD0, SCA_IInputDevice::KX_PAD0);
+ KX_MACRO_addTypesToDict(d, PADMINUS, SCA_IInputDevice::KX_PADMINUS);
+ KX_MACRO_addTypesToDict(d, PADENTER, SCA_IInputDevice::KX_PADENTER);
+ KX_MACRO_addTypesToDict(d, PADPLUSKEY, SCA_IInputDevice::KX_PADPLUSKEY);
+
+
+ KX_MACRO_addTypesToDict(d, F1KEY , SCA_IInputDevice::KX_F1KEY);
+ KX_MACRO_addTypesToDict(d, F2KEY , SCA_IInputDevice::KX_F2KEY);
+ KX_MACRO_addTypesToDict(d, F3KEY , SCA_IInputDevice::KX_F3KEY);
+ KX_MACRO_addTypesToDict(d, F4KEY , SCA_IInputDevice::KX_F4KEY);
+ KX_MACRO_addTypesToDict(d, F5KEY , SCA_IInputDevice::KX_F5KEY);
+ KX_MACRO_addTypesToDict(d, F6KEY , SCA_IInputDevice::KX_F6KEY);
+ KX_MACRO_addTypesToDict(d, F7KEY , SCA_IInputDevice::KX_F7KEY);
+ KX_MACRO_addTypesToDict(d, F8KEY , SCA_IInputDevice::KX_F8KEY);
+ KX_MACRO_addTypesToDict(d, F9KEY , SCA_IInputDevice::KX_F9KEY);
+ KX_MACRO_addTypesToDict(d, F10KEY, SCA_IInputDevice::KX_F10KEY);
+ KX_MACRO_addTypesToDict(d, F11KEY, SCA_IInputDevice::KX_F11KEY);
+ KX_MACRO_addTypesToDict(d, F12KEY, SCA_IInputDevice::KX_F12KEY);
+
+ KX_MACRO_addTypesToDict(d, PAUSEKEY, SCA_IInputDevice::KX_PAUSEKEY);
+ KX_MACRO_addTypesToDict(d, INSERTKEY, SCA_IInputDevice::KX_INSERTKEY);
+ KX_MACRO_addTypesToDict(d, HOMEKEY , SCA_IInputDevice::KX_HOMEKEY);
+ KX_MACRO_addTypesToDict(d, PAGEUPKEY, SCA_IInputDevice::KX_PAGEUPKEY);
+ KX_MACRO_addTypesToDict(d, PAGEDOWNKEY, SCA_IInputDevice::KX_PAGEDOWNKEY);
+ KX_MACRO_addTypesToDict(d, ENDKEY, SCA_IInputDevice::KX_ENDKEY);
+
+
+ // Check for errors
+ if (PyErr_Occurred())
+ {
+ Py_FatalError("can't initialize module GameKeys");
+ }
+
+ return d;
+}
+
+void PHY_SetActiveScene(class KX_Scene* scene)
+{
+ gp_KetsjiScene = scene;
+}
diff --git a/source/gameengine/Ketsji/KX_PythonInit.h b/source/gameengine/Ketsji/KX_PythonInit.h
new file mode 100644
index 00000000000..f5de003c6a6
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_PythonInit.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 __KX_PYTHON_INIT
+#define __KX_PYTHON_INIT
+
+#include "KX_Python.h"
+#include "STR_String.h"
+
+typedef enum {
+ psl_Lowest = 0,
+ psl_Highest
+} TPythonSecurityLevel;
+
+extern bool gUseVisibilityTemp;
+
+
+PyObject* initGameLogic(class KX_Scene* ketsjiscene);
+PyObject* initGameKeys();
+PyObject* initRasterizer(class RAS_IRasterizer* rasty,class RAS_ICanvas* canvas);
+PyObject* initGamePythonScripting(const STR_String& progname, TPythonSecurityLevel level);
+void exitGamePythonScripting();
+void exitGamePythonScripting();
+void PHY_SetActiveScene(class KX_Scene* scene);
+
+
+#endif //__KX_PYTHON_INIT
diff --git a/source/gameengine/Ketsji/KX_Python_dynamic.h b/source/gameengine/Ketsji/KX_Python_dynamic.h
new file mode 100644
index 00000000000..705b01aa606
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_Python_dynamic.h
@@ -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 *****
+ */
+#ifndef KX_PYTHON_H
+#define KX_PYTHON_H
+
+//#define USE_DL_EXPORT
+#include "Python.h"
+
+#endif // KX_PYTHON_H
diff --git a/source/gameengine/Ketsji/KX_Python_static.h b/source/gameengine/Ketsji/KX_Python_static.h
new file mode 100644
index 00000000000..d147794d8fe
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_Python_static.h
@@ -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 *****
+ */
+#ifndef KX_PYTHON_H
+#define KX_PYTHON_H
+
+#define USE_DL_EXPORT
+#include "Python.h"
+
+#endif // KX_PYTHON_H
diff --git a/source/gameengine/Ketsji/KX_RadarSensor.cpp b/source/gameengine/Ketsji/KX_RadarSensor.cpp
new file mode 100644
index 00000000000..27142987f4f
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_RadarSensor.cpp
@@ -0,0 +1,220 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "KX_RadarSensor.h"
+
+#include "KX_GameObject.h"
+/**
+ * RadarSensor constructor. Creates a near-sensor derived class, with a cone collision shape.
+ */
+
+#ifdef PHYSICS_NOT_YET
+
+KX_RadarSensor::KX_RadarSensor(class SCA_EventManager* eventmgr,
+ class KX_GameObject* gameobj,
+ double coneradius,
+ double coneheight,
+ int axis,
+ double margin,
+ double resetmargin,
+ bool bFindMaterial,
+ const STR_String& touchedpropname,
+ class KX_Scene* kxscene,
+ PyTypeObject* T)
+
+ : KX_NearSensor(
+ eventmgr,
+ gameobj,
+ margin,
+ resetmargin,
+ bFindMaterial,
+ touchedpropname,
+ kxscene,
+ T),
+ m_coneheight(coneheight),
+ m_coneradius(coneradius),
+ m_axis(axis)
+{
+ m_client_info.m_type = 3;
+ m_client_info.m_clientobject = gameobj;
+ m_client_info.m_auxilary_info = NULL;
+ sumoObj->setClientObject(&m_client_info);
+}
+
+
+KX_RadarSensor::~KX_RadarSensor()
+{
+
+}
+
+/**
+ * Transforms the collision object. A cone is not correctly centered
+ * for usage. */
+void KX_RadarSensor::SynchronizeTransform()
+{
+ // Getting the parent location was commented out. Why?
+ MT_Transform trans;
+ trans.setOrigin(((KX_GameObject*)GetParent())->NodeGetWorldPosition());
+ trans.setBasis(((KX_GameObject*)GetParent())->NodeGetWorldOrientation());
+ // What is the default orientation? pointing in the -y direction?
+ // is the geometry correctly converted?
+
+ // a collision cone is oriented
+ // center the cone correctly
+ // depends on the radar 'axis'
+ switch (m_axis)
+ {
+ case 0: // X Axis
+ {
+ MT_Quaternion rotquatje(MT_Vector3(0,0,1),MT_radians(90));
+ trans.rotate(rotquatje);
+ trans.translate(MT_Vector3 (0, -m_coneheight/2.0 ,0));
+ break;
+ };
+ case 1: // Y Axis
+ {
+ MT_Quaternion rotquatje(MT_Vector3(1,0,0),MT_radians(-180));
+ trans.rotate(rotquatje);
+ trans.translate(MT_Vector3 (0, -m_coneheight/2.0 ,0));
+ break;
+ };
+ case 2: // Z Axis
+ {
+ MT_Quaternion rotquatje(MT_Vector3(1,0,0),MT_radians(-90));
+ trans.rotate(rotquatje);
+ trans.translate(MT_Vector3 (0, -m_coneheight/2.0 ,0));
+ break;
+ };
+ default:
+ {
+ }
+ }
+ m_cone_origin = trans.getOrigin();
+ m_cone_target = trans(MT_Point3(0, -m_coneheight/2.0 ,0));
+
+ m_sumoObj->setPosition(trans.getOrigin());
+ m_sumoObj->setOrientation(trans.getRotation());
+ m_sumoObj->calcXform();
+}
+
+/* ------------------------------------------------------------------------- */
+/* Python functions */
+/* ------------------------------------------------------------------------- */
+
+/* Integration hooks ------------------------------------------------------- */
+PyTypeObject KX_RadarSensor::Type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0,
+ "KX_RadarSensor",
+ sizeof(KX_RadarSensor),
+ 0,
+ PyDestructor,
+ 0,
+ __getattr,
+ __setattr,
+ 0, //&MyPyCompare,
+ __repr,
+ 0, //&cvalue_as_number,
+ 0,
+ 0,
+ 0,
+ 0
+};
+
+PyParentObject KX_RadarSensor::Parents[] = {
+ &KX_RadarSensor::Type,
+ &KX_NearSensor::Type,
+ &KX_TouchSensor::Type,
+ &SCA_ISensor::Type,
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
+};
+
+PyMethodDef KX_RadarSensor::Methods[] = {
+ {"getConeOrigin", (PyCFunction) KX_RadarSensor::sPyGetConeOrigin,
+ METH_VARARGS, GetConeOrigin_doc},
+ {"getConeTarget", (PyCFunction) KX_RadarSensor::sPyGetConeTarget,
+ METH_VARARGS, GetConeTarget_doc},
+ {"getConeHeight", (PyCFunction) KX_RadarSensor::sPyGetConeHeight,
+ METH_VARARGS, GetConeHeight_doc},
+ {NULL,NULL,NULL,NULL} //Sentinel
+};
+
+PyObject* KX_RadarSensor::_getattr(char* attr) {
+ _getattr_up(KX_TouchSensor);
+}
+
+/* getConeOrigin */
+char KX_RadarSensor::GetConeOrigin_doc[] =
+"getConeOrigin()\n"
+"\tReturns the origin of the cone with which to test. The origin\n"
+"\tis in the middle of the cone.";
+PyObject* KX_RadarSensor::PyGetConeOrigin(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ PyObject *retVal = PyList_New(3);
+
+ PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_cone_origin[0]));
+ PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_cone_origin[1]));
+ PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_cone_origin[2]));
+
+ return retVal;
+}
+
+/* getConeOrigin */
+char KX_RadarSensor::GetConeTarget_doc[] =
+"getConeTarget()\n"
+"\tReturns the center of the bottom face of the cone with which to test.\n";
+PyObject* KX_RadarSensor::PyGetConeTarget(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ PyObject *retVal = PyList_New(3);
+
+ PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_cone_target[0]));
+ PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_cone_target[1]));
+ PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_cone_target[2]));
+
+ return retVal;
+}
+
+/* getConeOrigin */
+char KX_RadarSensor::GetConeHeight_doc[] =
+"getConeHeight()\n"
+"\tReturns the height of the cone with which to test.\n";
+PyObject* KX_RadarSensor::PyGetConeHeight(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ return PyFloat_FromDouble(m_coneheight);
+}
+
+
+#endif //PHYSICS_NOT_YET
diff --git a/source/gameengine/Ketsji/KX_RadarSensor.h b/source/gameengine/Ketsji/KX_RadarSensor.h
new file mode 100644
index 00000000000..3a69c6565b2
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_RadarSensor.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 __KX_RADAR_SENSOR_H
+#define __KX_RADAR_SENSOR_H
+
+#include "KX_NearSensor.h"
+#include "MT_Point3.h"
+
+/**
+* Radar 'cone' sensor. Very similar to a near-sensor, but instead of a sphere, a cone is used.
+*/
+class KX_RadarSensor : public KX_NearSensor
+{
+ protected:
+ Py_Header;
+
+ MT_Scalar m_coneradius;
+
+ /**
+ * Height of the cone.
+ */
+ MT_Scalar m_coneheight;
+ int m_axis;
+
+ /**
+ * The previous position of the origin of the cone.
+ */
+ MT_Point3 m_cone_origin;
+
+ /**
+ * The previous direction of the cone (origin to bottom plane).
+ */
+ MT_Point3 m_cone_target;
+
+public:
+ KX_RadarSensor(class SCA_EventManager* eventmgr,
+ class KX_GameObject* gameobj,
+ double coneradius,
+ double coneheight,
+ int axis,
+ double margin,
+ double resetmargin,
+ class SM_Object* sumoObj,
+ bool bFindMaterial,
+ const STR_String& touchedpropname,
+ class SM_Scene* sumoscene,
+ PyTypeObject* T=&Type);
+ KX_RadarSensor();
+ virtual ~KX_RadarSensor();
+ virtual void SynchronizeTransform();
+
+ /* --------------------------------------------------------------------- */
+ /* Python interface ---------------------------------------------------- */
+ /* --------------------------------------------------------------------- */
+
+ virtual PyObject* _getattr(char *attr);
+
+ KX_PYMETHOD_DOC(KX_RadarSensor,GetConeOrigin);
+ KX_PYMETHOD_DOC(KX_RadarSensor,GetConeTarget);
+ KX_PYMETHOD_DOC(KX_RadarSensor,GetConeHeight);
+
+};
+
+#endif //__KX_RADAR_SENSOR_H
diff --git a/source/gameengine/Ketsji/KX_RayEventManager.cpp b/source/gameengine/Ketsji/KX_RayEventManager.cpp
new file mode 100644
index 00000000000..d57f97efb44
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_RayEventManager.cpp
@@ -0,0 +1,55 @@
+/**
+ * Manager for ray events
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "KX_RayEventManager.h"
+#include "SCA_LogicManager.h"
+#include "SCA_ISensor.h"
+#include <vector>
+using namespace std;
+
+#include <iostream>
+#include <stdio.h>
+
+void KX_RayEventManager::NextFrame(double curtime,double deltatime)
+{
+ for (vector<class SCA_ISensor*>::const_iterator i= m_sensors.begin();!(i==m_sensors.end());i++)
+ {
+ SCA_ISensor *sensor = *i;
+ sensor->Activate(m_logicmgr, NULL);
+ }
+}
+
+void KX_RayEventManager::RegisterSensor(SCA_ISensor* sensor)
+{
+ m_sensors.push_back(sensor);
+};
diff --git a/source/gameengine/Ketsji/KX_RayEventManager.h b/source/gameengine/Ketsji/KX_RayEventManager.h
new file mode 100644
index 00000000000..abfbf6cb0f8
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_RayEventManager.h
@@ -0,0 +1,52 @@
+/**
+ * Manager for ray events
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 __KX_RAYEVENTMGR
+#define __KX_RAYEVENTMGR
+#include "SCA_EventManager.h"
+#include <vector>
+using namespace std;
+class KX_RayEventManager : public SCA_EventManager
+{
+
+ class SCA_LogicManager* m_logicmgr;
+public:
+ KX_RayEventManager(class SCA_LogicManager* logicmgr)
+ : m_logicmgr(logicmgr),
+ SCA_EventManager(RAY_EVENTMGR)
+ {}
+ virtual void NextFrame(double curtime,double deltatime);
+ virtual void RegisterSensor(SCA_ISensor* sensor);
+};
+#endif //__KX_RAYEVENTMGR
diff --git a/source/gameengine/Ketsji/KX_RaySensor.cpp b/source/gameengine/Ketsji/KX_RaySensor.cpp
new file mode 100644
index 00000000000..eac362a0b1c
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_RaySensor.cpp
@@ -0,0 +1,381 @@
+/**
+ * Cast a ray and feel for objects
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "KX_RaySensor.h"
+#include "SCA_EventManager.h"
+#include "SCA_RandomEventManager.h"
+#include "SCA_LogicManager.h"
+#include "SCA_IObject.h"
+#include "KX_ClientObjectInfo.h"
+#include "KX_GameObject.h"
+#include "KX_Scene.h"
+
+
+KX_RaySensor::KX_RaySensor(class SCA_EventManager* eventmgr,
+ SCA_IObject* gameobj,
+ const STR_String& propname,
+ bool bFindMaterial,
+ double distance,
+ int axis,
+ KX_Scene* ketsjiScene,
+ PyTypeObject* T)
+ : SCA_ISensor(gameobj,eventmgr, T),
+ m_propertyname(propname),
+ m_bFindMaterial(bFindMaterial),
+ m_distance(distance),
+ m_axis(axis),
+ m_ketsjiScene(ketsjiScene),
+ m_rayHit(false),
+ m_bTriggered(false),
+ m_hitObject(NULL)
+
+
+{
+
+}
+
+
+
+KX_RaySensor::~KX_RaySensor()
+{
+ /* Nothing to be done here. */
+}
+
+
+
+CValue* KX_RaySensor::GetReplica()
+{
+ CValue* replica = new KX_RaySensor(*this);
+ // this will copy properties and so on...
+ CValue::AddDataToReplica(replica);
+
+ return replica;
+}
+
+
+
+bool KX_RaySensor::IsPositiveTrigger()
+{
+ bool result = m_rayHit;
+
+ if (m_invert)
+ result = !result;
+
+ return result;
+}
+
+
+
+bool KX_RaySensor::Evaluate(CValue* event)
+{
+ bool result = false;
+ m_rayHit = false;
+ m_hitObject = NULL;
+ m_hitPosition = MT_Vector3(0,0,0);
+ m_hitNormal = MT_Vector3(1,0,0);
+
+ KX_GameObject* obj = (KX_GameObject*)GetParent();
+ MT_Point3 frompoint = obj->NodeGetWorldPosition();
+ MT_Matrix3x3 matje = obj->NodeGetWorldOrientation();
+ MT_Matrix3x3 invmat = matje.inverse();
+
+ MT_Vector3 todir;
+ switch (m_axis)
+ {
+ case 1: // X
+ {
+ todir[0] = invmat[0][0];
+ todir[1] = invmat[0][1];
+ todir[2] = invmat[0][2];
+ break;
+ }
+ case 0: // Y
+ {
+ todir[0] = invmat[1][0];
+ todir[1] = invmat[1][1];
+ todir[2] = invmat[1][2];
+ break;
+ }
+ case 2: // Z
+ {
+ todir[0] = invmat[2][0];
+ todir[1] = invmat[2][1];
+ todir[2] = invmat[2][2];
+ break;
+ }
+ case 3: // -X
+ {
+ todir[0] = invmat[0][0] * -1;
+ todir[1] = invmat[0][1] * -1;
+ todir[2] = invmat[0][2] * -1;
+ break;
+ }
+ case 4: // -Y
+ {
+ todir[0] = invmat[1][0] * -1;
+ todir[1] = invmat[1][1] * -1;
+ todir[2] = invmat[1][2] * -1;
+ break;
+ }
+ case 5: // -Z
+ {
+ todir[0] = invmat[2][0] * -1;
+ todir[1] = invmat[2][1] * -1;
+ todir[2] = invmat[2][2] * -1;
+ break;
+ }
+ }
+ todir.normalize();
+ m_rayDirection = todir;
+
+
+
+ MT_Point3 topoint = frompoint + (m_distance) * todir;
+ MT_Point3 resultpoint;
+ MT_Vector3 resultnormal;
+ bool ready = false;
+ /*
+ do {
+
+
+
+ SM_Object* hitObj = m_sumoScene->rayTest(obj->GetSumoObject(),
+ frompoint,
+ topoint,
+ resultpoint,
+ resultnormal);
+ if (hitObj)
+ {
+ KX_ClientObjectInfo* info = (SM_ClientObjectInfo*)hitObj->getClientObject();
+ SCA_IObject* hitgameobj = (SCA_IObject*)info->m_clientobject;
+ bool bFound = false;
+
+ if (hitgameobj == obj)
+ {
+ // false hit
+ MT_Scalar marg = obj->GetSumoObject()->getMargin() ;
+ frompoint = resultpoint + marg * todir;
+ }
+ else
+ {
+ ready = true;
+ if (m_propertyname.Length() == 0)
+ {
+ bFound = true;
+ }
+ else
+ {
+ if (m_bFindMaterial)
+ {
+ if (info->m_auxilary_info)
+ {
+ bFound = (m_propertyname== ((char*)info->m_auxilary_info));
+ }
+ }
+ else
+ {
+ if (hitgameobj->GetProperty(m_propertyname) != NULL)
+ {
+ bFound = true;
+ }
+ }
+ }
+
+ if (bFound)
+ {
+ m_rayHit = true;
+ m_hitObject = hitgameobj;
+ m_hitPosition = resultpoint;
+ m_hitNormal = resultnormal;
+
+ }
+ }
+ }
+ else
+ {
+ ready = true;
+ }
+ }
+ while (!ready);
+ */
+
+
+ /* now pass this result to some controller */
+ if (m_rayHit)
+ {
+ if (!m_bTriggered)
+ {
+ // notify logicsystem that ray is now hitting
+ result = true;
+ m_bTriggered = true;
+ }
+ else
+ {
+
+ }
+ }
+ else
+ {
+ if (m_bTriggered)
+ {
+ m_bTriggered = false;
+ // notify logicsystem that ray is not hitting anymore
+ result = true;
+ }
+ }
+
+ return result;
+}
+
+
+
+/* ------------------------------------------------------------------------- */
+/* Python functions */
+/* ------------------------------------------------------------------------- */
+
+/* Integration hooks ------------------------------------------------------- */
+PyTypeObject KX_RaySensor::Type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0,
+ "KX_RaySensor",
+ sizeof(KX_RaySensor),
+ 0,
+ PyDestructor,
+ 0,
+ __getattr,
+ __setattr,
+ 0, //&MyPyCompare,
+ __repr,
+ 0, //&cvalue_as_number,
+ 0,
+ 0,
+ 0,
+ 0
+};
+
+PyParentObject KX_RaySensor::Parents[] = {
+ &KX_RaySensor::Type,
+ &SCA_ISensor::Type,
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
+};
+
+PyMethodDef KX_RaySensor::Methods[] = {
+ {"getHitObject",(PyCFunction) KX_RaySensor::sPyGetHitObject,METH_VARARGS, GetHitObject_doc},
+ {"getHitPosition",(PyCFunction) KX_RaySensor::sPyGetHitPosition,METH_VARARGS, GetHitPosition_doc},
+ {"getHitNormal",(PyCFunction) KX_RaySensor::sPyGetHitNormal,METH_VARARGS, GetHitNormal_doc},
+ {"getRayDirection",(PyCFunction) KX_RaySensor::sPyGetRayDirection,METH_VARARGS, GetRayDirection_doc},
+ {NULL,NULL} //Sentinel
+};
+
+char KX_RaySensor::GetHitObject_doc[] =
+"getHitObject()\n"
+"\tReturns the name of the object that was hit by this ray.\n";
+PyObject* KX_RaySensor::PyGetHitObject(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ if (m_hitObject)
+ {
+ return m_hitObject->AddRef();
+ }
+ Py_Return;
+}
+
+
+char KX_RaySensor::GetHitPosition_doc[] =
+"getHitPosition()\n"
+"\tReturns the position (in worldcoordinates) where the object was hit by this ray.\n";
+PyObject* KX_RaySensor::PyGetHitPosition(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+
+ MT_Point3 pos = m_hitPosition;
+
+ PyObject* resultlist = PyList_New(3);
+ int index;
+ for (index=0;index<3;index++)
+ {
+ PyList_SetItem(resultlist,index,PyFloat_FromDouble(pos[index]));
+ }
+ return resultlist;
+
+}
+
+char KX_RaySensor::GetRayDirection_doc[] =
+"getRayDirection()\n"
+"\tReturns the direction from the ray (in worldcoordinates) .\n";
+PyObject* KX_RaySensor::PyGetRayDirection(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+
+ MT_Vector3 dir = m_rayDirection;
+
+ PyObject* resultlist = PyList_New(3);
+ int index;
+ for (index=0;index<3;index++)
+ {
+ PyList_SetItem(resultlist,index,PyFloat_FromDouble(dir[index]));
+ }
+ return resultlist;
+
+}
+
+char KX_RaySensor::GetHitNormal_doc[] =
+"getHitNormal()\n"
+"\tReturns the normal (in worldcoordinates) of the object at the location where the object was hit by this ray.\n";
+PyObject* KX_RaySensor::PyGetHitNormal(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ MT_Vector3 pos = m_hitNormal;
+
+ PyObject* resultlist = PyList_New(3);
+ int index;
+ for (index=0;index<3;index++)
+ {
+ PyList_SetItem(resultlist,index,PyFloat_FromDouble(pos[index]));
+ }
+ return resultlist;
+
+}
+
+
+
+PyObject* KX_RaySensor::_getattr(char* attr) {
+ _getattr_up(SCA_ISensor);
+}
diff --git a/source/gameengine/Ketsji/KX_RaySensor.h b/source/gameengine/Ketsji/KX_RaySensor.h
new file mode 100644
index 00000000000..7eb16bd6d5b
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_RaySensor.h
@@ -0,0 +1,79 @@
+/**
+ * Cast a ray and feel for objects
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 __KX_RAYSENSOR_H
+#define __KX_RAYSENSOR_H
+
+#include "SCA_ISensor.h"
+#include "MT_Point3.h"
+
+class KX_RaySensor : public SCA_ISensor
+{
+ Py_Header;
+ STR_String m_propertyname;
+ bool m_bFindMaterial;
+ double m_distance;
+ class KX_Scene* m_ketsjiScene;
+ bool m_bTriggered;
+ int m_axis;
+ bool m_rayHit;
+ MT_Point3 m_hitPosition;
+ SCA_IObject* m_hitObject;
+ MT_Vector3 m_hitNormal;
+ MT_Vector3 m_rayDirection;
+
+public:
+ KX_RaySensor(class SCA_EventManager* eventmgr,
+ SCA_IObject* gameobj,
+ const STR_String& propname,
+ bool fFindMaterial,
+ double distance,
+ int axis,
+ class KX_Scene* ketsjiScene,
+ PyTypeObject* T = &Type);
+ virtual ~KX_RaySensor();
+ virtual CValue* GetReplica();
+
+ virtual bool Evaluate(CValue* event);
+ virtual bool IsPositiveTrigger();
+
+ KX_PYMETHOD_DOC(KX_RaySensor,GetHitObject);
+ KX_PYMETHOD_DOC(KX_RaySensor,GetHitPosition);
+ KX_PYMETHOD_DOC(KX_RaySensor,GetHitNormal);
+ KX_PYMETHOD_DOC(KX_RaySensor,GetRayDirection);
+
+ virtual PyObject* _getattr(char *attr);
+
+};
+#endif //__KX_RAYSENSOR_H
diff --git a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp
new file mode 100644
index 00000000000..4e73f4e27ca
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp
@@ -0,0 +1,335 @@
+//
+// Add an object when this actuator is triggered
+//
+// $Id$
+//
+// ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version. The Blender
+// Foundation also sells licenses for use in proprietary software under
+// the Blender License. See http://www.blender.org/BL/ for information
+// about this.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+// All rights reserved.
+//
+// The Original Code is: all of this file.
+//
+// Contributor(s): none yet.
+//
+// ***** END GPL/BL DUAL LICENSE BLOCK *****
+// Previously existed as:
+
+// \source\gameengine\GameLogic\SCA_AddObjectActuator.cpp
+
+// Please look here for revision history.
+
+
+#include "KX_SCA_AddObjectActuator.h"
+#include "SCA_IScene.h"
+#include "KX_GameObject.h"
+#include "KX_IPhysicsController.h"
+
+/* ------------------------------------------------------------------------- */
+/* Native functions */
+/* ------------------------------------------------------------------------- */
+
+KX_SCA_AddObjectActuator::KX_SCA_AddObjectActuator(SCA_IObject *gameobj,
+ CValue* original,
+ int time,
+ SCA_IScene* scene,
+ const MT_Vector3& linvel,
+ bool local,
+ PyTypeObject* T)
+ :
+ SCA_IActuator(gameobj, T),
+ m_OriginalObject(original),
+ m_scene(scene),
+ m_linear_velocity(linvel),
+ m_localFlag(local)
+{
+ m_lastCreatedObject = NULL;
+ m_timeProp = time;
+}
+
+
+
+KX_SCA_AddObjectActuator::~KX_SCA_AddObjectActuator()
+{
+ if (m_lastCreatedObject)
+ m_lastCreatedObject->Release();
+}
+
+
+
+bool KX_SCA_AddObjectActuator::Update(double curtime,
+ double deltatime)
+{
+ bool result = false;
+ bool bNegativeEvent = IsNegativeEvent();
+ RemoveAllEvents();
+
+ if (bNegativeEvent) return false; // do nothing on negative events
+ if (m_OriginalObject)
+ {
+ // Add an identical object, with properties inherited from the original object
+ // Now it needs to be added to the current scene.
+ SCA_IObject* replica = m_scene->AddReplicaObject(m_OriginalObject,GetParent(),m_timeProp );
+ KX_GameObject * game_obj = static_cast<KX_GameObject *>(replica);
+ game_obj->setLinearVelocity(m_linear_velocity,m_localFlag);
+
+ //if (game_obj->GetSumoObject())
+ //{
+ // If this is object is also controlled by physics.
+ // we have to inform the physics controller that
+ // we no longer take control of the object.
+ // game_obj->GetPhysicsController()->ResolveCombinedVelocities(m_linear_velocity,
+ // MT_Vector3(0,0,0),
+ // m_localFlag,
+ // false);
+ //}
+
+ // keep a copy of the last object, to allow python scripters to change it
+ if (m_lastCreatedObject)
+ m_lastCreatedObject->Release();
+
+ m_lastCreatedObject = replica;
+ m_lastCreatedObject->AddRef();
+ }
+
+ return false;
+}
+
+
+
+SCA_IObject* KX_SCA_AddObjectActuator::GetLastCreatedObject() const
+{
+ return m_lastCreatedObject;
+}
+
+
+
+CValue* KX_SCA_AddObjectActuator::GetReplica()
+{
+ KX_SCA_AddObjectActuator* replica = new KX_SCA_AddObjectActuator(*this);
+
+ if (replica == NULL)
+ return NULL;
+
+ // this will copy properties and so on...
+ replica->ProcessReplica();
+ replica->m_lastCreatedObject=NULL;
+ CValue::AddDataToReplica(replica);
+
+ return replica;
+}
+
+
+
+/* ------------------------------------------------------------------------- */
+/* Python functions */
+/* ------------------------------------------------------------------------- */
+
+/* Integration hooks ------------------------------------------------------- */
+PyTypeObject KX_SCA_AddObjectActuator::Type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0,
+ "KX_SCA_AddObjectActuator",
+ sizeof(KX_SCA_AddObjectActuator),
+ 0,
+ PyDestructor,
+ 0,
+ __getattr,
+ __setattr,
+ 0,
+ __repr,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+};
+
+PyParentObject KX_SCA_AddObjectActuator::Parents[] = {
+ &SCA_IActuator::Type,
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
+};
+PyMethodDef KX_SCA_AddObjectActuator::Methods[] = {
+ {"setObject", (PyCFunction) KX_SCA_AddObjectActuator::sPySetObject, METH_VARARGS, SetObject_doc},
+ {"setTime", (PyCFunction) KX_SCA_AddObjectActuator::sPySetTime, METH_VARARGS, SetTime_doc},
+ {"getObject", (PyCFunction) KX_SCA_AddObjectActuator::sPyGetObject, METH_VARARGS, GetObject_doc},
+ {"getTime", (PyCFunction) KX_SCA_AddObjectActuator::sPyGetTime, METH_VARARGS, GetTime_doc},
+ {"getLinearVelocity", (PyCFunction) KX_SCA_AddObjectActuator::sPyGetLinearVelocity, METH_VARARGS, GetLinearVelocity_doc},
+ {"setLinearVelocity", (PyCFunction) KX_SCA_AddObjectActuator::sPySetLinearVelocity, METH_VARARGS, SetLinearVelocity_doc},
+ {"getLastCreatedObject", (PyCFunction) KX_SCA_AddObjectActuator::sPyGetLastCreatedObject, METH_VARARGS,"getLastCreatedObject() : get the object handle to the last created object\n"},
+ {NULL,NULL} //Sentinel
+};
+
+
+PyObject* KX_SCA_AddObjectActuator::_getattr(char* attr)
+{
+ _getattr_up(SCA_IActuator);
+}
+
+/* 1. setObject */
+char KX_SCA_AddObjectActuator::SetObject_doc[] =
+"setObject(name)\n"
+"\t- name: string\n"
+"\tSets the object that will be added. There has to be an object\n"
+"\tof this name. If not, this function does nothing.\n";
+
+
+
+PyObject* KX_SCA_AddObjectActuator::PySetObject(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ char* objectname;
+
+ if (!PyArg_ParseTuple(args, "s", &objectname))
+ return NULL;
+
+ CValue* gameobj = SCA_ILogicBrick::m_sCurrentLogicManager->GetGameObjectByName(STR_String(objectname));
+
+ m_OriginalObject= (CValue*)gameobj;
+
+ Py_Return;
+}
+
+
+
+/* 2. setTime */
+char KX_SCA_AddObjectActuator::SetTime_doc[] =
+"setTime(duration)\n"
+"\t- duration: integer\n"
+"\tSets the lifetime of the object that will be added, in frames. \n"
+"\tIf the duration is negative, it is set to 0.\n";
+
+
+PyObject* KX_SCA_AddObjectActuator::PySetTime(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ int deltatime;
+
+ if (!PyArg_ParseTuple(args, "i", &deltatime))
+ return NULL;
+
+ m_timeProp = deltatime;
+ if (m_timeProp < 0) m_timeProp = 0;
+
+ Py_Return;
+}
+
+
+
+/* 3. getTime */
+char KX_SCA_AddObjectActuator::GetTime_doc[] =
+"GetTime()\n"
+"\tReturns the lifetime of the object that will be added.\n";
+
+
+PyObject* KX_SCA_AddObjectActuator::PyGetTime(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ return PyInt_FromLong(m_timeProp);
+}
+
+
+/* 4. getObject */
+char KX_SCA_AddObjectActuator::GetObject_doc[] =
+"getObject()\n"
+"\tReturns the name of the object that will be added.\n";
+
+
+
+PyObject* KX_SCA_AddObjectActuator::PyGetObject(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ return PyString_FromString(m_OriginalObject->GetName());
+}
+
+
+
+/* 5. getLinearVelocity */
+char KX_SCA_AddObjectActuator::GetLinearVelocity_doc[] =
+"GetLinearVelocity()\n"
+"\tReturns the linear velocity that will be assigned to \n"
+"\tthe created object.\n";
+
+
+
+PyObject* KX_SCA_AddObjectActuator::PyGetLinearVelocity(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ PyObject *retVal = PyList_New(3);
+
+ PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_linear_velocity[0]));
+ PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_linear_velocity[1]));
+ PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_linear_velocity[2]));
+
+ return retVal;
+}
+
+
+
+/* 6. setLinearVelocity */
+char KX_SCA_AddObjectActuator::SetLinearVelocity_doc[] =
+"setLinearVelocity(vx, vy, vz)\n"
+"\t- vx: float\n"
+"\t- vy: float\n"
+"\t- vz: float\n"
+"\tAssign this velocity to the created object. \n";
+
+
+PyObject* KX_SCA_AddObjectActuator::PySetLinearVelocity(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+
+ float vecArg[3];
+ if (!PyArg_ParseTuple(args, "fff", &vecArg[0], &vecArg[1], &vecArg[2]))
+ return NULL;
+
+ m_linear_velocity.setValue(vecArg);
+ Py_Return;
+}
+
+
+
+/* 7. GetLastCreatedObject */
+char KX_SCA_AddObjectActuator::GetLastCreatedObject_doc[] =
+"getLastCreatedObject()\n"
+"\tReturn the last created object. \n";
+
+
+PyObject* KX_SCA_AddObjectActuator::PyGetLastCreatedObject(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ SCA_IObject* result = this->GetLastCreatedObject();
+ if (result)
+ {
+ result->AddRef();
+ return result;
+ }
+ // don't return NULL to python anymore, it gives trouble in the scripts
+ Py_Return;
+}
diff --git a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h
new file mode 100644
index 00000000000..9810669034c
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h
@@ -0,0 +1,133 @@
+//
+// Add object to the game world on action of this actuator. A copy is made
+// of a referenced object. The copy inherits some properties from the owner
+// of this actuator.
+//
+// $Id$
+//
+// ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version. The Blender
+// Foundation also sells licenses for use in proprietary software under
+// the Blender License. See http://www.blender.org/BL/ for information
+// about this.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+// All rights reserved.
+//
+// The Original Code is: all of this file.
+//
+// Contributor(s): none yet.
+//
+// ***** END GPL/BL DUAL LICENSE BLOCK *****
+//
+// Previously existed as:
+// \source\gameengine\GameLogic\SCA_AddObjectActuator.h
+// Please look here for revision history.
+
+#ifndef __KX_SCA_AddObjectActuator
+#define __KX_SCA_AddObjectActuator
+
+/* Actuator tree */
+#include "SCA_IActuator.h"
+#include "SCA_LogicManager.h"
+
+#include "MT_Vector3.h"
+
+class SCA_IScene;
+
+class KX_SCA_AddObjectActuator : public SCA_IActuator
+{
+ Py_Header;
+
+ /// Time field: lifetime of the new object
+ int m_timeProp;
+
+ /// Original object reference (object to replicate)
+ CValue* m_OriginalObject;
+
+ /// Object will be added to the following scene
+ SCA_IScene* m_scene;
+
+ /// Linear velocity upon creation of the object.
+ MT_Vector3 m_linear_velocity;
+
+ /// Apply the velocity locally
+ bool m_localFlag;
+
+ SCA_IObject* m_lastCreatedObject;
+
+public:
+
+ /**
+ * This class also has the default constructors
+ * available. Use with care!
+ */
+
+ KX_SCA_AddObjectActuator(
+ SCA_IObject *gameobj,
+ CValue* original,
+ int time,
+ SCA_IScene* scene,
+ const MT_Vector3& linvel,
+ bool local,
+ PyTypeObject* T=&Type
+ );
+
+ ~KX_SCA_AddObjectActuator(void);
+
+ CValue*
+ GetReplica(
+ ) ;
+
+ bool
+ Update(
+ double curtime,
+ double deltatime
+ );
+
+ PyObject*
+ _getattr(
+ char *attr
+ );
+
+ SCA_IObject*
+ GetLastCreatedObject(
+ ) const ;
+
+ /* 1. setObject */
+ KX_PYMETHOD_DOC(KX_SCA_AddObjectActuator,SetObject);
+ /* 2. setTime */
+ KX_PYMETHOD_DOC(KX_SCA_AddObjectActuator,SetTime);
+ /* 3. getTime */
+ KX_PYMETHOD_DOC(KX_SCA_AddObjectActuator,GetTime);
+ /* 4. getObject */
+ KX_PYMETHOD_DOC(KX_SCA_AddObjectActuator,GetObject);
+ /* 5. getLinearVelocity */
+ KX_PYMETHOD_DOC(KX_SCA_AddObjectActuator,GetLinearVelocity);
+ /* 6. setLinearVelocity */
+ KX_PYMETHOD_DOC(KX_SCA_AddObjectActuator,SetLinearVelocity);
+ /* 7. getLastCreatedObject */
+ KX_PYMETHOD_DOC(KX_SCA_AddObjectActuator,GetLastCreatedObject);
+
+
+}; /* end of class KX_SCA_AddObjectActuator : public KX_EditObjectActuator */
+
+#endif
+
+
+
+
+
diff --git a/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp b/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp
new file mode 100644
index 00000000000..ca1c4d04084
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp
@@ -0,0 +1,137 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+//
+
+// Remove the actuator's parent when triggered
+//
+// Previously existed as:
+// \source\gameengine\GameLogic\SCA_EndObjectActuator.cpp
+// Please look here for revision history.
+
+#include "SCA_IActuator.h"
+#include "KX_SCA_EndObjectActuator.h"
+#include "SCA_IScene.h"
+
+KX_SCA_EndObjectActuator::KX_SCA_EndObjectActuator(SCA_IObject *gameobj,
+ SCA_IScene* scene,
+ PyTypeObject* T):
+ SCA_IActuator(gameobj, T),
+ m_scene(scene)
+{
+ // intentionally empty
+} /* End of constructor */
+
+
+
+KX_SCA_EndObjectActuator::~KX_SCA_EndObjectActuator()
+{
+ // there's nothing to be done here, really....
+} /* end of destructor */
+
+
+
+bool KX_SCA_EndObjectActuator::Update(double curtime,
+ double deltatime
+ )
+{
+ bool result = false;
+ bool bNegativeEvent = IsNegativeEvent();
+ RemoveAllEvents();
+
+ if (bNegativeEvent)
+ return false; // do nothing on negative events
+ m_scene->DelayedRemoveObject(GetParent());
+
+ return false;
+}
+
+
+
+CValue* KX_SCA_EndObjectActuator::GetReplica()
+{
+ KX_SCA_EndObjectActuator* replica =
+ new KX_SCA_EndObjectActuator(*this);
+ if (replica == NULL) return NULL;
+
+ replica->ProcessReplica();
+ // this will copy properties and so on...
+ CValue::AddDataToReplica(replica);
+ return replica;
+};
+
+
+
+/* ------------------------------------------------------------------------- */
+/* Python functions : integration hooks */
+/* ------------------------------------------------------------------------- */
+
+PyTypeObject KX_SCA_EndObjectActuator::Type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0,
+ "KX_SCA_EndObjectActuator",
+ sizeof(KX_SCA_EndObjectActuator),
+ 0,
+ PyDestructor,
+ 0,
+ __getattr,
+ __setattr,
+ 0, //&MyPyCompare,
+ __repr,
+ 0, //&cvalue_as_number,
+ 0,
+ 0,
+ 0,
+ 0
+};
+
+
+PyParentObject KX_SCA_EndObjectActuator::Parents[] = {
+ &KX_SCA_EndObjectActuator::Type,
+ &SCA_IActuator::Type,
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
+};
+
+
+
+PyMethodDef KX_SCA_EndObjectActuator::Methods[] = {
+ {NULL,NULL} //Sentinel
+};
+
+
+PyObject* KX_SCA_EndObjectActuator::_getattr(char* attr)
+{
+ _getattr_up(SCA_IActuator);
+}
+
+/* eof */
diff --git a/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.h b/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.h
new file mode 100644
index 00000000000..39ee911b48f
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.h
@@ -0,0 +1,80 @@
+//
+// Add object to the game world on action of this actuator
+//
+// $Id$
+//
+// ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version. The Blender
+// Foundation also sells licenses for use in proprietary software under
+// the Blender License. See http://www.blender.org/BL/ for information
+// about this.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+// All rights reserved.
+//
+// The Original Code is: all of this file.
+//
+// Contributor(s): none yet.
+//
+// ***** END GPL/BL DUAL LICENSE BLOCK *****
+//
+// Previously existed as:
+// \source\gameengine\GameLogic\SCA_EndObjectActuator.h
+// Please look here for revision history.
+
+#ifndef __KX_SCA_ENDOBJECTACTUATOR
+#define __KX_SCA_ENDOBJECTACTUATOR
+
+#include "SCA_IActuator.h"
+
+class SCA_IScene;
+
+class KX_SCA_EndObjectActuator : public SCA_IActuator
+{
+ Py_Header;
+ SCA_IScene* m_scene;
+
+ public:
+ KX_SCA_EndObjectActuator(
+ SCA_IObject* gameobj,
+ SCA_IScene* scene,
+ PyTypeObject* T=&Type
+ );
+
+ ~KX_SCA_EndObjectActuator();
+
+ CValue*
+ GetReplica(
+ );
+
+ bool
+ Update(
+ double curtime,
+ double deltatime
+ );
+
+ /* --------------------------------------------------------------------- */
+ /* Python interface ---------------------------------------------------- */
+ /* --------------------------------------------------------------------- */
+
+ PyObject*
+ _getattr(
+ char *attr
+ );
+
+}; /* end of class KX_EditObjectActuator : public SCA_PropertyActuator */
+
+#endif
diff --git a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp
new file mode 100644
index 00000000000..731ddeff80d
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp
@@ -0,0 +1,182 @@
+//
+// Replace the mesh for this actuator's parent
+//
+// $Id$
+//
+// ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version. The Blender
+// Foundation also sells licenses for use in proprietary software under
+// the Blender License. See http://www.blender.org/BL/ for information
+// about this.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+// All rights reserved.
+//
+// The Original Code is: all of this file.
+//
+// Contributor(s): none yet.
+//
+// ***** END GPL/BL DUAL LICENSE BLOCK *****
+
+//
+// Previously existed as:
+
+// \source\gameengine\GameLogic\SCA_ReplaceMeshActuator.cpp
+
+// Please look here for revision history.
+
+
+#include "KX_SCA_ReplaceMeshActuator.h"
+
+/* ------------------------------------------------------------------------- */
+/* Python functions */
+/* ------------------------------------------------------------------------- */
+
+/* Integration hooks ------------------------------------------------------- */
+
+ PyTypeObject
+
+KX_SCA_ReplaceMeshActuator::
+
+Type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0,
+ "KX_SCA_ReplaceMeshActuator",
+ sizeof(KX_SCA_ReplaceMeshActuator),
+ 0,
+ PyDestructor,
+ 0,
+ __getattr,
+ __setattr,
+ 0,
+ __repr,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+};
+
+PyParentObject KX_SCA_ReplaceMeshActuator::Parents[] = {
+ &SCA_IActuator::Type,
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
+};
+
+
+
+PyMethodDef KX_SCA_ReplaceMeshActuator::Methods[] = {
+ {"setMesh", (PyCFunction) KX_SCA_ReplaceMeshActuator::sPySetMesh, METH_VARARGS, SetMesh_doc},
+ {NULL,NULL} //Sentinel
+};
+
+
+
+PyObject* KX_SCA_ReplaceMeshActuator::_getattr(char* attr)
+{
+ _getattr_up(SCA_IActuator);
+}
+
+
+
+/* 1. setMesh */
+char KX_SCA_ReplaceMeshActuator::SetMesh_doc[] =
+ "setMesh(name)\n"
+ "\t- name: string\n"
+ "\tSet the mesh that will be substituted for the current one.\n";
+
+PyObject* KX_SCA_ReplaceMeshActuator::PySetMesh(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ char* meshname;
+
+ if (!PyArg_ParseTuple(args, "s", &meshname))
+ {
+ return NULL;
+ }
+
+ void* mesh = SCA_ILogicBrick::m_sCurrentLogicManager->GetMeshByName(STR_String(meshname));
+
+ if (m_mesh) {
+ m_mesh= (class RAS_MeshObject*)mesh;
+ Py_Return;
+ }
+
+ return NULL;
+}
+
+
+
+/* ------------------------------------------------------------------------- */
+/* Native functions */
+/* ------------------------------------------------------------------------- */
+
+KX_SCA_ReplaceMeshActuator::KX_SCA_ReplaceMeshActuator(SCA_IObject *gameobj,
+ class RAS_MeshObject *mesh,
+ SCA_IScene* scene,
+ PyTypeObject* T) :
+
+ SCA_IActuator(gameobj, T),
+ m_scene(scene),
+ m_mesh(mesh)
+{
+} /* End of constructor */
+
+
+
+KX_SCA_ReplaceMeshActuator::~KX_SCA_ReplaceMeshActuator()
+{
+ // there's nothing to be done here, really....
+} /* end of destructor */
+
+
+
+bool KX_SCA_ReplaceMeshActuator::Update(double curtime,
+ double deltatime)
+{
+ bool result = false;
+ bool bNegativeEvent = IsNegativeEvent();
+ RemoveAllEvents();
+
+ if (bNegativeEvent)
+ return false; // do nothing on negative events
+
+ if (m_mesh) m_scene->ReplaceMesh(GetParent(),m_mesh);
+
+ return false;
+}
+
+
+
+CValue* KX_SCA_ReplaceMeshActuator::GetReplica()
+{
+ KX_SCA_ReplaceMeshActuator* replica =
+ new KX_SCA_ReplaceMeshActuator(*this);
+
+ if (replica == NULL)
+ return NULL;
+
+ replica->ProcessReplica();
+
+ // this will copy properties and so on...
+ CValue::AddDataToReplica(replica);
+
+ return replica;
+};
+
+/* eof */
diff --git a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h
new file mode 100644
index 00000000000..ada21d06847
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h
@@ -0,0 +1,88 @@
+//
+// Add object to the game world on action of this actuator
+//
+// $Id$
+//
+// ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version. The Blender
+// Foundation also sells licenses for use in proprietary software under
+// the Blender License. See http://www.blender.org/BL/ for information
+// about this.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+// All rights reserved.
+//
+// The Original Code is: all of this file.
+//
+// Contributor(s): none yet.
+//
+// ***** END GPL/BL DUAL LICENSE BLOCK *****
+//
+// Previously existed as:
+// \source\gameengine\GameLogic\SCA_ReplaceMeshActuator.h
+// Please look here for revision history.
+//
+
+#ifndef __KX_SCA_REPLACEMESHACTUATOR
+#define __KX_SCA_REPLACEMESHACTUATOR
+
+#include "SCA_IActuator.h"
+#include "SCA_PropertyActuator.h"
+#include "SCA_LogicManager.h"
+#include "SCA_IScene.h"
+
+#include "RAS_MeshObject.h"
+
+class KX_SCA_ReplaceMeshActuator : public SCA_IActuator
+{
+ Py_Header;
+
+ // mesh reference (mesh to replace)
+ RAS_MeshObject* m_mesh;
+ SCA_IScene* m_scene;
+
+ public:
+ KX_SCA_ReplaceMeshActuator(
+ SCA_IObject* gameobj,
+ RAS_MeshObject *mesh,
+ SCA_IScene* scene,
+ PyTypeObject* T=&Type
+ );
+
+ ~KX_SCA_ReplaceMeshActuator(
+ );
+
+ CValue*
+ GetReplica(
+ );
+
+ bool
+ Update(
+ double curtime,
+ double deltatime
+ );
+
+ PyObject*
+ _getattr(
+ char *attr
+ );
+
+ /* 1. setMesh */
+ KX_PYMETHOD_DOC(KX_SCA_ReplaceMeshActuator,SetMesh);
+
+};
+
+#endif
diff --git a/source/gameengine/Ketsji/KX_SG_NodeRelationships.cpp b/source/gameengine/Ketsji/KX_SG_NodeRelationships.cpp
new file mode 100644
index 00000000000..16529a91471
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_SG_NodeRelationships.cpp
@@ -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 *****
+ */
+
+#include "KX_SG_NodeRelationships.h"
+
+
+/**
+ * Implementation of classes defined in KX_SG_NodeRelationships.h
+ */
+
+/**
+ * first of all KX_NormalParentRelation
+ */
+
+ KX_NormalParentRelation *
+KX_NormalParentRelation::
+New(
+) {
+ return new KX_NormalParentRelation();
+}
+
+ void
+KX_NormalParentRelation::
+UpdateChildCoordinates(
+ SG_Spatial * child,
+ const SG_Spatial * parent
+){
+ assert(child != NULL);
+
+ // This way of accessing child coordinates is a bit cumbersome
+ // be nice to have non constant reference access to these values.
+
+ const MT_Vector3 & child_scale = child->GetLocalScale();
+ const MT_Point3 & child_pos = child->GetLocalPosition();
+ const MT_Matrix3x3 & child_rotation = child->GetLocalOrientation();
+
+ // the childs world locations which we will update.
+
+ MT_Vector3 child_w_scale;
+ MT_Point3 child_w_pos;
+ MT_Matrix3x3 child_w_rotation;
+
+ if (parent) {
+
+ const MT_Vector3 & p_world_scale = parent->GetWorldScaling();
+ const MT_Point3 & p_world_pos = parent->GetWorldPosition();
+ const MT_Matrix3x3 & p_world_rotation = parent->GetWorldOrientation();
+
+ child_w_scale = p_world_scale * child_scale;
+ child_w_rotation = p_world_rotation * child_rotation;
+
+ child_w_pos = p_world_pos + p_world_scale *
+ (p_world_rotation * child_pos);
+ } else {
+
+ child_w_scale = child_scale;
+ child_w_pos = child_pos;
+ child_w_rotation = child_rotation;
+ }
+
+ child->SetWorldScale(child_w_scale);
+ child->SetWorldPosition(child_w_pos);
+ child->SetWorldOrientation(child_w_rotation);
+}
+
+ SG_ParentRelation *
+KX_NormalParentRelation::
+NewCopy(
+){
+ return new KX_NormalParentRelation();
+}
+
+KX_NormalParentRelation::
+~KX_NormalParentRelation(
+){
+ //nothing to do
+}
+
+
+KX_NormalParentRelation::
+KX_NormalParentRelation(
+){
+ // nothing to do
+}
+
+/**
+ * Next KX_VertexParentRelation
+ */
+
+
+ KX_VertexParentRelation *
+KX_VertexParentRelation::
+New(
+){
+ return new KX_VertexParentRelation();
+}
+
+/**
+ * Method inherited from KX_ParentRelation
+ */
+
+ void
+KX_VertexParentRelation::
+UpdateChildCoordinates(
+ SG_Spatial * child,
+ const SG_Spatial * parent
+){
+
+ assert(child != NULL);
+
+ const MT_Vector3 & child_scale = child->GetLocalScale();
+ const MT_Point3 & child_pos = child->GetLocalPosition();
+ const MT_Matrix3x3 & child_rotation = child->GetLocalOrientation();
+
+ // the childs world locations which we will update.
+
+ MT_Vector3 child_w_scale;
+ MT_Point3 child_w_pos;
+ MT_Matrix3x3 child_w_rotation;
+
+ if (parent) {
+
+ // This is a vertex parent so we do not inherit orientation
+ // information.
+
+ const MT_Vector3 & p_world_scale = parent->GetWorldScaling();
+ const MT_Point3 & p_world_pos = parent->GetWorldPosition();
+ const MT_Matrix3x3 & p_world_rotation = parent->GetWorldOrientation();
+
+ child_w_scale = child_scale;
+ child_w_rotation = child_rotation;
+ child_w_pos = p_world_pos + child_pos;
+
+ } else {
+
+ child_w_scale = child_scale;
+ child_w_pos = child_pos;
+ child_w_rotation = child_rotation;
+ }
+
+ child->SetWorldScale(child_w_scale);
+ child->SetWorldPosition(child_w_pos);
+ child->SetWorldOrientation(child_w_rotation);
+}
+
+/**
+ * Method inherited from KX_ParentRelation
+ */
+
+ SG_ParentRelation *
+KX_VertexParentRelation::
+NewCopy(
+){
+ return new KX_VertexParentRelation();
+};
+
+KX_VertexParentRelation::
+~KX_VertexParentRelation(
+){
+ //nothing to do
+}
+
+
+KX_VertexParentRelation::
+KX_VertexParentRelation(
+){
+ //nothing to do
+}
+
+
+/**
+ * Slow parent relationship
+ */
+
+ KX_SlowParentRelation *
+KX_SlowParentRelation::
+New(
+ MT_Scalar relaxation
+){
+ return new KX_SlowParentRelation(relaxation);
+}
+
+/**
+ * Method inherited from KX_ParentRelation
+ */
+
+ void
+KX_SlowParentRelation::
+UpdateChildCoordinates(
+ SG_Spatial * child,
+ const SG_Spatial * parent
+){
+ assert(child != NULL);
+
+ const MT_Vector3 & child_scale = child->GetLocalScale();
+ const MT_Point3 & child_pos = child->GetLocalPosition();
+ const MT_Matrix3x3 & child_rotation = child->GetLocalOrientation();
+
+ // the childs world locations which we will update.
+
+ MT_Vector3 child_w_scale;
+ MT_Point3 child_w_pos;
+ MT_Matrix3x3 child_w_rotation;
+
+ if (parent) {
+
+ // This is a slow parent relation
+ // first compute the normal child world coordinates.
+
+ MT_Vector3 child_n_scale;
+ MT_Point3 child_n_pos;
+ MT_Matrix3x3 child_n_rotation;
+
+ const MT_Vector3 & p_world_scale = parent->GetWorldScaling();
+ const MT_Point3 & p_world_pos = parent->GetWorldPosition();
+ const MT_Matrix3x3 & p_world_rotation = parent->GetWorldOrientation();
+
+ child_n_scale = p_world_scale * child_scale;
+ child_n_rotation = p_world_rotation * child_rotation;
+
+ child_n_pos = p_world_pos + p_world_scale *
+ (p_world_rotation * child_pos);
+
+
+ if (m_initialized) {
+
+ // get the current world positions
+
+ child_w_scale = child->GetWorldScaling();
+ child_w_pos = child->GetWorldPosition();
+ child_w_rotation = child->GetWorldOrientation();
+
+ // now 'interpolate' the normal coordinates with the last
+ // world coordinates to get the new world coordinates.
+
+ // problem 1:
+ // The child world scale needs to be initialized in some way for this
+ // to make sense
+ // problem 2:
+ // This is way of doing interpolation is nonsense
+
+ int i;
+
+ MT_Scalar weight = MT_Scalar(1)/(m_relax + 1);
+ for (i=0;i <3 ;i++) {
+ child_w_scale[i] = (m_relax * child_w_scale[i] + child_n_scale[i]) * weight;
+ child_w_pos[i] = (m_relax * child_w_pos[i] + child_n_pos[i]) * weight;
+ child_w_rotation[0][i] = (m_relax * child_w_rotation[0][i] + child_n_rotation[0][i]) * weight;
+ child_w_rotation[1][i] = (m_relax * child_w_rotation[1][i] + child_n_rotation[1][i]) * weight;
+ child_w_rotation[2][i] = (m_relax * child_w_rotation[2][i] + child_n_rotation[2][i]) * weight;
+ }
+ } else {
+ child_w_scale = child_n_scale;
+ child_w_pos = child_n_pos;
+ child_w_rotation = child_n_rotation;
+ m_initialized = true;
+ }
+
+ } else {
+
+ child_w_scale = child_scale;
+ child_w_pos = child_pos;
+ child_w_rotation = child_rotation;
+ }
+
+ child->SetWorldScale(child_w_scale);
+ child->SetWorldPosition(child_w_pos);
+ child->SetWorldOrientation(child_w_rotation);
+}
+
+/**
+ * Method inherited from KX_ParentRelation
+ */
+
+ SG_ParentRelation *
+KX_SlowParentRelation::
+NewCopy(
+){
+ return new KX_SlowParentRelation(m_relax);
+}
+
+KX_SlowParentRelation::
+KX_SlowParentRelation(
+ MT_Scalar relaxation
+):
+ m_relax(relaxation),
+ m_initialized(false)
+{
+ //nothing to do
+}
+
+KX_SlowParentRelation::
+~KX_SlowParentRelation(
+){
+ //nothing to do
+}
+
+
+
+
diff --git a/source/gameengine/Ketsji/KX_SG_NodeRelationships.h b/source/gameengine/Ketsji/KX_SG_NodeRelationships.h
new file mode 100644
index 00000000000..c6c3dbaf315
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_SG_NodeRelationships.h
@@ -0,0 +1,214 @@
+/**
+ * @mainpage KX_SG_NodeRelationships
+
+ * @section
+ *
+ * This file provides common concrete implementations of
+ * SG_ParentRelation used by the game engine. These are
+ * KX_SlowParentRelation a slow parent relationship.
+ * KX_NormalParentRelation a normal parent relationship where
+ * orientation and position are inherited from the parent by
+ * the child.
+ * KX_VertexParentRelation only location information is
+ * inherited by the child.
+ *
+ * @see SG_ParentRelation for more information about this
+ * interface
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "SG_Spatial.h"
+#include "SG_ParentRelation.h"
+
+
+class KX_NormalParentRelation : public SG_ParentRelation
+{
+
+public :
+
+ /**
+ * Allocate and construct a new KX_NormalParentRelation
+ * on the heap.
+ */
+
+ static
+ KX_NormalParentRelation *
+ New(
+ );
+
+ /**
+ * Method inherited from KX_ParentRelation
+ */
+
+ void
+ UpdateChildCoordinates(
+ SG_Spatial * child,
+ const SG_Spatial * parent
+ );
+
+ /**
+ * Method inherited from KX_ParentRelation
+ */
+
+ SG_ParentRelation *
+ NewCopy(
+ );
+
+ ~KX_NormalParentRelation(
+ );
+
+private :
+
+ KX_NormalParentRelation(
+ );
+
+};
+
+
+class KX_VertexParentRelation : public SG_ParentRelation
+{
+
+public :
+
+ /**
+ * Allocate and construct a new KX_VertexParentRelation
+ * on the heap.
+ */
+
+ static
+ KX_VertexParentRelation *
+ New(
+ );
+
+ /**
+ * Method inherited from KX_ParentRelation
+ */
+
+ void
+ UpdateChildCoordinates(
+ SG_Spatial * child,
+ const SG_Spatial * parent
+ );
+
+ /**
+ * Method inherited from KX_ParentRelation
+ */
+
+ SG_ParentRelation *
+ NewCopy(
+ );
+
+ ~KX_VertexParentRelation(
+ );
+
+private :
+
+ KX_VertexParentRelation(
+ );
+
+};
+
+
+class KX_SlowParentRelation : public SG_ParentRelation
+{
+
+public :
+
+ /**
+ * Allocate and construct a new KX_VertexParentRelation
+ * on the heap.
+ */
+
+ static
+ KX_SlowParentRelation *
+ New(
+ MT_Scalar relaxation
+ );
+
+ /**
+ * Method inherited from KX_ParentRelation
+ */
+
+ void
+ UpdateChildCoordinates(
+ SG_Spatial * child,
+ const SG_Spatial * parent
+ );
+
+ /**
+ * Method inherited from KX_ParentRelation
+ */
+
+ SG_ParentRelation *
+ NewCopy(
+ );
+
+ ~KX_SlowParentRelation(
+ );
+
+private :
+
+ KX_SlowParentRelation(
+ MT_Scalar relaxation
+ );
+
+ // the relaxation coefficient.
+
+ MT_Scalar m_relax;
+
+ /**
+ * Looks like a hack flag to me.
+ * We need to compute valid world coordinates the first
+ * time we update spatial data of the child. This is done
+ * by just doing a normal parent relation the first time
+ * UpdateChildCoordinates is called and then doing the
+ * slow parent relation
+ */
+
+ bool m_initialized;
+
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/source/gameengine/Ketsji/KX_ScalarInterpolator.cpp b/source/gameengine/Ketsji/KX_ScalarInterpolator.cpp
new file mode 100644
index 00000000000..e1c72c74a41
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_ScalarInterpolator.cpp
@@ -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 *****
+ */
+
+#include "KX_ScalarInterpolator.h"
+
+#include "KX_IScalarInterpolator.h"
+
+void KX_ScalarInterpolator::Execute(float currentTime) const {
+ *m_target = m_ipo->GetValue(currentTime);
+}
diff --git a/source/gameengine/Ketsji/KX_ScalarInterpolator.h b/source/gameengine/Ketsji/KX_ScalarInterpolator.h
new file mode 100644
index 00000000000..85c8900e8ab
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_ScalarInterpolator.h
@@ -0,0 +1,63 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 KX_SCALARINTERPOLATOR
+#define KX_SCALARINTERPOLATOR
+
+#include "MT_Scalar.h"
+#include "KX_IInterpolator.h"
+
+class KX_IScalarInterpolator;
+
+class KX_ScalarInterpolator : public KX_IInterpolator {
+public:
+ KX_ScalarInterpolator(MT_Scalar* target,
+ KX_IScalarInterpolator *ipo) :
+ m_target(target),
+ m_ipo(ipo)
+ {}
+
+ virtual ~KX_ScalarInterpolator() {}
+ virtual void Execute(float currentTime) const;
+ void SetNewTarget(MT_Scalar* newtarget)
+ {
+ m_target=newtarget;
+ }
+ MT_Scalar* GetTarget()
+ {
+ return m_target;
+ }
+private:
+ MT_Scalar* m_target;
+ KX_IScalarInterpolator *m_ipo;
+};
+
+#endif
diff --git a/source/gameengine/Ketsji/KX_ScalingInterpolator.cpp b/source/gameengine/Ketsji/KX_ScalingInterpolator.cpp
new file mode 100644
index 00000000000..87bd9455d74
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_ScalingInterpolator.cpp
@@ -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 *****
+ */
+
+#include "KX_ScalingInterpolator.h"
+
+
+#include "MT_Vector3.h"
+#include "KX_IScalarInterpolator.h"
+
+void KX_ScalingInterpolator::Execute(float currentTime) const {
+ m_target.setValue(m_ipos[0]->GetValue(currentTime),
+ m_ipos[1]->GetValue(currentTime),
+ m_ipos[2]->GetValue(currentTime));
+}
diff --git a/source/gameengine/Ketsji/KX_ScalingInterpolator.h b/source/gameengine/Ketsji/KX_ScalingInterpolator.h
new file mode 100644
index 00000000000..fd7e00d7b24
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_ScalingInterpolator.h
@@ -0,0 +1,61 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 KX_SCALINGINTERPOLATOR
+#define KX_SCALINGINTERPOLATOR
+
+#include "KX_IInterpolator.h"
+
+class MT_Vector3;
+class KX_IScalarInterpolator;
+
+class KX_ScalingInterpolator : public KX_IInterpolator {
+public:
+ KX_ScalingInterpolator(MT_Vector3& target,
+ KX_IScalarInterpolator *ipos[])
+ : m_target(target)
+ {
+ m_ipos[0] = ipos[0];
+ m_ipos[1] = ipos[1];
+ m_ipos[2] = ipos[2];
+ }
+
+ virtual void Execute(float currentTime) const;
+
+private:
+ MT_Vector3& m_target;
+ KX_IScalarInterpolator *m_ipos[3];
+};
+
+#endif
+
+
+
diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp
new file mode 100644
index 00000000000..508ada3a5a9
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_Scene.cpp
@@ -0,0 +1,977 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * Ketsji scene. Holds references to all scene data.
+ */
+
+#ifdef WIN32
+#pragma warning (disable : 4786)
+#endif //WIN32
+
+#include "KX_KetsjiEngine.h"
+#include "RAS_IPolygonMaterial.h"
+#include "KX_Scene.h"
+#include "ListValue.h"
+#include "SCA_LogicManager.h"
+#include "SCA_TimeEventManager.h"
+#include "SCA_AlwaysEventManager.h"
+#include "SCA_RandomEventManager.h"
+#include "KX_RayEventManager.h"
+#include "KX_TouchEventManager.h"
+#include "SCA_KeyboardManager.h"
+#include "SCA_MouseManager.h"
+#include "SCA_PropertyEventManager.h"
+#include "KX_Camera.h"
+
+#include "RAS_MeshObject.h"
+#include "RAS_IRasterizer.h"
+#include "RAS_BucketManager.h"
+
+#include "FloatValue.h"
+#include "SCA_IController.h"
+#include "SCA_IActuator.h"
+#include "SG_Node.h"
+#include "SYS_System.h"
+#include "SG_Controller.h"
+#include "SG_IObject.h"
+
+#include "KX_SG_NodeRelationships.h"
+
+#include "KX_NetworkEventManager.h"
+#include "NG_NetworkScene.h"
+#include "PHY_IPhysicsEnvironment.h"
+#include "KX_IPhysicsController.h"
+
+
+void* KX_SceneReplicationFunc(SG_IObject* node,void* gameobj,void* scene)
+{
+ KX_GameObject* replica = ((KX_Scene*)scene)->AddNodeReplicaObject(node,(KX_GameObject*)gameobj);
+
+ return (void*)replica;
+}
+
+void* KX_SceneDestructionFunc(SG_IObject* node,void* gameobj,void* scene)
+{
+ ((KX_Scene*)scene)->RemoveNodeDestructObject(node,(KX_GameObject*)gameobj);
+
+ return NULL;
+};
+
+
+SG_Callbacks KX_Scene::m_callbacks = SG_Callbacks(KX_SceneReplicationFunc,KX_SceneDestructionFunc);
+
+// temporarily var until there is a button in the userinterface
+// (defined in KX_PythonInit.cpp)
+extern bool gUseVisibilityTemp;
+
+
+
+
+KX_Scene::KX_Scene(class SCA_IInputDevice* keyboarddevice,
+ class SCA_IInputDevice* mousedevice,
+ class NG_NetworkDeviceInterface *ndi,
+ class SND_IAudioDevice* adi,
+ const STR_String& sceneName):
+
+ m_mousemgr(NULL),
+ m_keyboardmgr(NULL),
+ m_active_camera(NULL),
+ m_ueberExecutionPriority(0),
+ m_adi(adi),
+ m_sceneName(sceneName),
+ m_networkDeviceInterface(ndi),
+ m_physicsEnvironment(0)
+{
+
+
+ m_activity_culling = false;
+ m_suspend = false;
+ m_isclearingZbuffer = true;
+ m_tempObjectList = new CListValue();
+ m_objectlist = new CListValue();
+ m_parentlist = new CListValue();
+ m_lightlist= new CListValue();
+ m_euthanasyobjects = new CListValue();
+
+ m_logicmgr = new SCA_LogicManager();
+
+ m_timemgr = new SCA_TimeEventManager(m_logicmgr);
+ m_keyboardmgr = new SCA_KeyboardManager(m_logicmgr,keyboarddevice);
+ m_mousemgr = new SCA_MouseManager(m_logicmgr,mousedevice);
+
+// m_solidScene = DT_CreateScene();
+// m_respTable = DT_CreateRespTable();
+
+ SCA_AlwaysEventManager* alwaysmgr = new SCA_AlwaysEventManager(m_logicmgr);
+ //KX_TouchEventManager* touchmgr = new KX_TouchEventManager(m_logicmgr, m_respTable, m_solidScene);
+ SCA_PropertyEventManager* propmgr = new SCA_PropertyEventManager(m_logicmgr);
+ SCA_RandomEventManager* rndmgr = new SCA_RandomEventManager(m_logicmgr);
+ KX_RayEventManager* raymgr = new KX_RayEventManager(m_logicmgr);
+
+ KX_NetworkEventManager* netmgr = new KX_NetworkEventManager(m_logicmgr, ndi);
+
+ m_logicmgr->RegisterEventManager(alwaysmgr);
+ m_logicmgr->RegisterEventManager(propmgr);
+ m_logicmgr->RegisterEventManager(m_keyboardmgr);
+ m_logicmgr->RegisterEventManager(m_mousemgr);
+ //m_logicmgr->RegisterEventManager(touchmgr);
+ m_logicmgr->RegisterEventManager(m_timemgr);
+ m_logicmgr->RegisterEventManager(rndmgr);
+ m_logicmgr->RegisterEventManager(raymgr);
+ m_logicmgr->RegisterEventManager(netmgr);
+
+ //m_sumoScene = new SM_Scene();
+ //m_sumoScene->setSecondaryRespTable(m_respTable);
+ m_soundScene = new SND_Scene(adi);
+ assert (m_networkDeviceInterface != NULL);
+ m_networkScene = new NG_NetworkScene(m_networkDeviceInterface);
+
+ m_rootnode = NULL;
+
+ m_bucketmanager=new RAS_BucketManager();
+
+ m_canvasDesignWidth = 0;
+ m_canvasDesignHeight = 0;
+}
+
+
+
+KX_Scene::~KX_Scene()
+{
+// int numobj = m_objectlist->GetCount();
+
+ //int numrootobjects = GetRootParentList()->GetCount();
+ for (int i = 0; i < GetRootParentList()->GetCount(); i++)
+ {
+ KX_GameObject* parentobj = (KX_GameObject*) GetRootParentList()->GetValue(i);
+ this->RemoveObject(parentobj);
+ }
+
+ if(m_objectlist)
+ m_objectlist->Release();
+
+ if (m_parentlist)
+ m_parentlist->Release();
+
+ if (m_lightlist)
+ m_lightlist->Release();
+
+ if (m_tempObjectList)
+ m_tempObjectList->Release();
+
+ if (m_euthanasyobjects)
+ m_euthanasyobjects->Release();
+
+ if (m_logicmgr)
+ delete m_logicmgr;
+
+ if (m_physicsEnvironment)
+ delete m_physicsEnvironment;
+
+ if (m_soundScene)
+ delete m_soundScene;
+
+ if (m_networkScene)
+ delete m_networkScene;
+
+ if (m_bucketmanager)
+ {
+ delete m_bucketmanager;
+ }
+}
+
+
+
+
+void KX_Scene::SetProjectionMatrix(MT_CmMatrix4x4& pmat)
+{
+ m_projectionmat = pmat;
+}
+
+
+
+RAS_BucketManager* KX_Scene::GetBucketManager()
+{
+ return m_bucketmanager;
+}
+
+
+
+CListValue* KX_Scene::GetObjectList()
+{
+ return m_objectlist;
+}
+
+
+
+CListValue* KX_Scene::GetRootParentList()
+{
+ return m_parentlist;
+}
+
+
+
+CListValue* KX_Scene::GetLightList()
+{
+ return m_lightlist;
+}
+
+SCA_LogicManager* KX_Scene::GetLogicManager()
+{
+ return m_logicmgr;
+}
+
+SCA_TimeEventManager* KX_Scene::GetTimeEventManager()
+{
+ return m_timemgr;
+}
+
+
+
+
+void KX_Scene::SetFramingType(RAS_FrameSettings & frame_settings)
+{
+ m_frame_settings = frame_settings;
+};
+
+/**
+ * Return a const reference to the framing
+ * type set by the above call.
+ * The contents are not guarenteed to be sensible
+ * if you don't call the above function.
+ */
+const RAS_FrameSettings& KX_Scene::GetFramingType() const
+{
+ return m_frame_settings;
+};
+
+
+
+/**
+ * Store the current scene's viewport on the
+ * game engine canvas.
+ */
+void KX_Scene::SetSceneViewport(const RAS_Rect &viewport)
+{
+ m_viewport = viewport;
+}
+
+
+
+const RAS_Rect& KX_Scene::GetSceneViewport() const
+{
+ return m_viewport;
+}
+
+
+
+void KX_Scene::SetWorldInfo(class KX_WorldInfo* worldinfo)
+{
+ m_worldinfo = worldinfo;
+}
+
+
+
+class KX_WorldInfo* KX_Scene::GetWorldInfo()
+{
+ return m_worldinfo;
+}
+
+
+
+SND_Scene* KX_Scene::GetSoundScene()
+{
+ return m_soundScene;
+}
+
+const STR_String& KX_Scene::GetName()
+{
+ return m_sceneName;
+}
+
+
+void KX_Scene::Suspend()
+{
+ m_suspend = true;
+}
+
+void KX_Scene::Resume()
+{
+ m_suspend = false;
+}
+
+void KX_Scene::SetActivityCulling(bool b)
+{
+ m_activity_culling = b;
+}
+
+bool KX_Scene::IsSuspended()
+{
+ return m_suspend;
+}
+
+bool KX_Scene::IsClearingZBuffer()
+{
+ return m_isclearingZbuffer;
+}
+
+void KX_Scene::EnableZBufferClearing(bool isclearingZbuffer)
+{
+ m_isclearingZbuffer = isclearingZbuffer;
+}
+
+void KX_Scene::RemoveNodeDestructObject(class SG_IObject* node,class CValue* gameobj)
+{
+ KX_GameObject* orgobj = (KX_GameObject*)gameobj;
+ NewRemoveObject(orgobj);
+
+ if (node)
+ delete node;
+}
+
+KX_GameObject* KX_Scene::AddNodeReplicaObject(class SG_IObject* node, class CValue* gameobj)
+{
+ KX_GameObject* orgobj = (KX_GameObject*)gameobj;
+ KX_GameObject* newobj = (KX_GameObject*)orgobj->GetReplica();
+ m_map_gameobject_to_replica.insert(orgobj, newobj);
+
+ // also register 'timers' (time properties) of the replica
+ int numprops = newobj->GetPropertyCount();
+
+ for (int i = 0; i < numprops; i++)
+ {
+ CValue* prop = newobj->GetProperty(i);
+
+ if (prop->GetProperty("timer"))
+ this->m_timemgr->AddTimeProperty(prop);
+ }
+
+ if (node)
+ {
+ newobj->SetSGNode((SG_Node*)node);
+ }
+ else
+ {
+ m_rootnode = new SG_Node(newobj,this,KX_Scene::m_callbacks);
+
+ // this fixes part of the scaling-added object bug
+ SG_Node* orgnode = orgobj->GetSGNode();
+ m_rootnode->SetLocalScale(orgnode->GetLocalScale());
+ m_rootnode->SetLocalPosition(orgnode->GetLocalPosition());
+ m_rootnode->SetLocalOrientation(orgnode->GetLocalOrientation());
+
+ // define the relationship between this node and it's parent.
+ KX_NormalParentRelation * parent_relation =
+ KX_NormalParentRelation::New();
+ m_rootnode->SetParentRelation(parent_relation);
+
+ newobj->SetSGNode(m_rootnode);
+ }
+
+ SG_IObject* replicanode = newobj->GetSGNode();
+ SG_Node* rootnode = (replicanode == m_rootnode ? NULL : m_rootnode);
+
+ replicanode->SetSGClientObject(newobj);
+
+ // this is the list of object that are send to the graphics pipeline
+ m_objectlist->Add(newobj);
+ newobj->Bucketize();
+
+ // logic cannot be replicated, until the whole hierarchy is replicated.
+ m_logicHierarchicalGameObjects.push_back(newobj);
+ //replicate controllers of this node
+ SGControllerList scenegraphcontrollers = orgobj->GetSGNode()->GetSGControllerList();
+ replicanode->RemoveAllControllers();
+ SGControllerList::iterator cit;
+ //int numcont = scenegraphcontrollers.size();
+
+ for (cit = scenegraphcontrollers.begin();!(cit==scenegraphcontrollers.end());++cit)
+ {
+ // controller replication is quite complicated
+ // only replicate ipo and physics controller for now
+
+ SG_Controller* replicacontroller = (*cit)->GetReplica((SG_Node*) replicanode);
+ if (replicacontroller)
+ {
+ replicacontroller->SetObject(replicanode);
+ replicanode->AddSGController(replicacontroller);
+ }
+ }
+
+ return newobj;
+}
+
+
+
+// before calling this method KX_Scene::ReplicateLogic(), make sure to
+// have called 'GameObject::ReParentLogic' for each object this
+// hierarchy that's because first ALL bricks must exist in the new
+// replica of the hierarchy in order to make cross-links work properly
+// !
+void KX_Scene::ReplicateLogic(KX_GameObject* newobj)
+{
+ // also relink the controller to sensors/actuators
+ SCA_ControllerList& controllers = newobj->GetControllers();
+ //SCA_SensorList& sensors = newobj->GetSensors();
+ //SCA_ActuatorList& actuators = newobj->GetActuators();
+
+ for (SCA_ControllerList::iterator itc = controllers.begin(); !(itc==controllers.end());itc++)
+ {
+ SCA_IController* cont = (*itc);
+ cont->SetUeberExecutePriority(m_ueberExecutionPriority);
+ vector<SCA_ISensor*> linkedsensors = cont->GetLinkedSensors();
+ vector<SCA_IActuator*> linkedactuators = cont->GetLinkedActuators();
+
+ // disconnect the sensors and actuators
+ cont->UnlinkAllSensors();
+ cont->UnlinkAllActuators();
+
+ // now relink each sensor
+ for (vector<SCA_ISensor*>::iterator its = linkedsensors.begin();!(its==linkedsensors.end());its++)
+ {
+ SCA_ISensor* oldsensor = (*its);
+ STR_String name = oldsensor->GetName();
+ //find this name in the list
+ SCA_ISensor* newsensor = newobj->FindSensor(name);
+
+ if (newsensor)
+ {
+ // relink this newsensor to the controller
+ m_logicmgr->RegisterToSensor(cont,newsensor);
+ }
+ else
+ {
+ // it can be linked somewhere in the hierarchy or...
+ for (vector<KX_GameObject*>::iterator git = m_logicHierarchicalGameObjects.begin();
+ !(git==m_logicHierarchicalGameObjects.end());++git)
+ {
+ newsensor = (*git)->FindSensor(name);
+ if (newsensor)
+ break;
+ }
+
+ if (newsensor)
+ {
+ // relink this newsensor to the controller somewhere else within this
+ // hierarchy
+ m_logicmgr->RegisterToSensor(cont,newsensor);
+ }
+ else
+ {
+ // must be an external sensor, so...
+ m_logicmgr->RegisterToSensor(cont,oldsensor);
+ }
+ }
+ }
+
+ // now relink each actuator
+ for (vector<SCA_IActuator*>::iterator ita = linkedactuators.begin();!(ita==linkedactuators.end());ita++)
+ {
+ SCA_IActuator* oldactuator = (*ita);
+ STR_String name = oldactuator->GetName();
+ //find this name in the list
+ SCA_IActuator* newactuator = newobj->FindActuator(name);
+ if (newactuator)
+ {
+ // relink this newsensor to the controller
+ m_logicmgr->RegisterToActuator(cont,newactuator);
+ newactuator->SetUeberExecutePriority(m_ueberExecutionPriority);
+ }
+ else
+ {
+ // it can be linked somewhere in the hierarchy or...
+ for (vector<KX_GameObject*>::iterator git = m_logicHierarchicalGameObjects.begin();
+ !(git==m_logicHierarchicalGameObjects.end());++git)
+ {
+ newactuator= (*git)->FindActuator(name);
+ if (newactuator)
+ break;
+ }
+
+ if (newactuator)
+ {
+ // relink this actuator to the controller somewhere else within this
+ // hierarchy
+ m_logicmgr->RegisterToActuator(cont,newactuator);
+ newactuator->SetUeberExecutePriority(m_ueberExecutionPriority);
+ }
+ else
+ {
+ // must be an external actuator, so...
+ m_logicmgr->RegisterToActuator(cont,oldactuator);
+ }
+ }
+ }
+ }
+}
+
+
+
+SCA_IObject* KX_Scene::AddReplicaObject(class CValue* originalobject,
+ class CValue* parentobject,
+ int lifespan)
+{
+
+ m_logicHierarchicalGameObjects.clear();
+ m_map_gameobject_to_replica.clear();
+
+ // todo: place a timebomb in the object, for temporarily objects :)
+ // lifespan of zero means 'this object lives forever'
+ KX_GameObject* originalobj = (KX_GameObject*) originalobject;
+ KX_GameObject* parentobj = (KX_GameObject*) parentobject;
+
+ m_ueberExecutionPriority++;
+
+ // lets create a replica
+ KX_GameObject* replica = (KX_GameObject*) AddNodeReplicaObject(NULL,originalobj);
+
+ if (lifespan > 0)
+ {
+ // add a timebomb to this object
+ // for now, convert between so called frames and realtime
+ m_tempObjectList->Add(replica->AddRef());
+ replica->SetProperty("::timebomb",new CFloatValue(lifespan*0.02));
+ }
+
+ // add to 'rootparent' list (this is the list of top hierarchy objects, updated each frame)
+ m_parentlist->Add(replica->AddRef());
+
+ // recurse replication into children nodes
+
+ NodeList& children = originalobj->GetSGNode()->GetSGChildren();
+
+ replica->GetSGNode()->ClearSGChildren();
+ for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit)
+ {
+ SG_Node* orgnode = (*childit);
+ SG_Node* childreplicanode = orgnode->GetSGReplica();
+ replica->GetSGNode()->AddChild(childreplicanode);
+ }
+
+ // relink any pointers as necessary, sort of a temporary solution
+ vector<KX_GameObject*>::iterator git;
+ for (git = m_logicHierarchicalGameObjects.begin();!(git==m_logicHierarchicalGameObjects.end());++git)
+ {
+ (*git)->Relink(&m_map_gameobject_to_replica);
+ }
+
+ // now replicate logic
+ for (git = m_logicHierarchicalGameObjects.begin();!(git==m_logicHierarchicalGameObjects.end());++git)
+ {
+ (*git)->ReParentLogic();
+ }
+
+ // replicate crosslinks etc. between logic bricks
+ for (git = m_logicHierarchicalGameObjects.begin();!(git==m_logicHierarchicalGameObjects.end());++git)
+ {
+ ReplicateLogic((*git));
+ }
+
+ MT_Point3 newpos = ((KX_GameObject*) parentobject)->NodeGetWorldPosition();
+ replica->NodeSetLocalPosition(newpos);
+
+ MT_Matrix3x3 newori = ((KX_GameObject*) parentobject)->NodeGetWorldOrientation();
+ replica->NodeSetLocalOrientation(newori);
+
+ if (replica->GetPhysicsController())
+ {
+ replica->GetPhysicsController()->setPosition(newpos);
+ replica->GetPhysicsController()->setOrientation(newori.getRotation());
+ }
+
+ // here we want to set the relative scale: the rootnode's scale will override all other
+ // scalings, so lets better prepare for it
+
+ // get the rootnode's scale
+ MT_Vector3 newscale = parentobj->GetSGNode()->GetRootSGParent()->GetLocalScale();
+
+ // set the replica's relative scale with the rootnode's scale
+ replica->NodeSetRelativeScale(newscale);
+
+ replica->GetSGNode()->UpdateWorldData(0);
+
+ return replica;
+}
+
+
+
+void KX_Scene::RemoveObject(class CValue* gameobj)
+{
+ KX_GameObject* newobj = (KX_GameObject*) gameobj;
+
+ // first disconnect child from parent
+ SG_Node* node = newobj->GetSGNode();
+
+ if (node)
+ {
+ node->DisconnectFromParent();
+
+ // recursively destruct
+ node->Destruct();
+ }
+}
+
+
+
+void KX_Scene::DelayedRemoveObject(class CValue* gameobj)
+{
+ //KX_GameObject* newobj = (KX_GameObject*) gameobj;
+ if (!m_euthanasyobjects->SearchValue(gameobj))
+ {
+ m_euthanasyobjects->Add(gameobj->AddRef());
+ }
+}
+
+
+
+void KX_Scene::NewRemoveObject(class CValue* gameobj)
+{
+ KX_GameObject* newobj = (KX_GameObject*) gameobj;
+ //SM_Object* sumoObj = newobj->GetSumoObject();
+ //if (sumoObj)
+ //{
+ // this->GetSumoScene()->remove(*sumoObj);
+ //}
+ // remove all sensors/controllers/actuators from logicsystem...
+
+ SCA_SensorList& sensors = newobj->GetSensors();
+ for (SCA_SensorList::iterator its = sensors.begin();
+ !(its==sensors.end());its++)
+ {
+ m_logicmgr->RemoveSensor(*its);
+ }
+
+ SCA_ControllerList& controllers = newobj->GetControllers();
+ for (SCA_ControllerList::iterator itc = controllers.begin();
+ !(itc==controllers.end());itc++)
+ {
+ (*itc)->UnlinkAllSensors();
+ (*itc)->UnlinkAllActuators();
+ }
+
+ SCA_ActuatorList& actuators = newobj->GetActuators();
+ for (SCA_ActuatorList::iterator ita = actuators.begin();
+ !(ita==actuators.end());ita++)
+ {
+ m_logicmgr->RemoveDestroyedActuator(*ita);
+ }
+
+ // now remove the timer properties from the time manager
+ int numprops = newobj->GetPropertyCount();
+
+ for (int i = 0; i < numprops; i++)
+ {
+ CValue* propval = newobj->GetProperty(i);
+ if (propval->GetProperty("timer"))
+ {
+ m_timemgr->RemoveTimeProperty(propval);
+ }
+ }
+
+ newobj->RemoveMeshes();
+ if (m_objectlist->RemoveValue(newobj))
+ newobj->Release();
+ if (m_tempObjectList->RemoveValue(newobj))
+ newobj->Release();
+ if (m_parentlist->RemoveValue(newobj))
+ newobj->Release();
+ if (m_euthanasyobjects->RemoveValue(newobj))
+ newobj->Release();
+}
+
+
+
+void KX_Scene::ReplaceMesh(class CValue* gameobj,void* meshobj)
+{
+ KX_GameObject* newobj = (KX_GameObject*) gameobj;
+ newobj->RemoveMeshes();
+ newobj->AddMesh((RAS_MeshObject*)meshobj);
+ newobj->Bucketize();
+}
+
+
+
+MT_CmMatrix4x4& KX_Scene::GetViewMatrix()
+{
+ MT_Scalar cammat[16];
+ m_active_camera->GetWorldToCamera().getValue(cammat);
+ m_viewmat = cammat;
+ return m_viewmat;
+}
+
+
+
+MT_CmMatrix4x4& KX_Scene::GetProjectionMatrix()
+{
+ return m_projectionmat;
+}
+
+
+KX_Camera* KX_Scene::FindCamera(KX_Camera* cam)
+{
+ set<KX_Camera*>::iterator it = m_cameras.begin();
+
+ while ( (it != m_cameras.end())
+ && ((*it) != cam) ) {
+ it++;
+ }
+
+ return ((it == m_cameras.end()) ? NULL : (*it));
+}
+
+
+KX_Camera* KX_Scene::FindCamera(STR_String& name)
+{
+ set<KX_Camera*>::iterator it = m_cameras.begin();
+
+ while ( (it != m_cameras.end())
+ && ((*it)->GetName() != name) ) {
+ it++;
+ }
+
+ return ((it == m_cameras.end()) ? NULL : (*it));
+}
+
+void KX_Scene::AddCamera(KX_Camera* cam)
+{
+ m_cameras.insert(cam);
+}
+
+
+KX_Camera* KX_Scene::GetActiveCamera()
+{
+ // NULL if not defined
+ return m_active_camera;
+}
+
+
+void KX_Scene::SetActiveCamera(KX_Camera* cam)
+{
+ // only set if the cam is in the active list? Or add it otherwise?
+ if (!FindCamera(cam)){
+ AddCamera(cam);
+ if (cam) std::cout << "Added cam " << cam->GetName() << std::endl;
+ }
+
+ m_active_camera = cam;
+}
+
+
+
+void KX_Scene::UpdateMeshTransformations()
+{
+ // do this incrementally in the future
+ for (int i = 0; i < m_objectlist->GetCount(); i++)
+ {
+ KX_GameObject* gameobj = (KX_GameObject*)m_objectlist->GetValue(i);
+ gameobj->GetOpenGLMatrix();
+ gameobj->UpdateNonDynas();
+ }
+}
+
+void KX_Scene::CalculateVisibleMeshes(RAS_IRasterizer* rasty)
+{
+
+ // do this incrementally in the future
+ for (int i = 0; i < m_objectlist->GetCount(); i++)
+ {
+ KX_GameObject* gameobj = (KX_GameObject*)m_objectlist->GetValue(i);
+
+ int nummeshes = gameobj->GetMeshCount();
+
+ for (int m=0;m<nummeshes;m++)
+ {
+ // this adds the vertices to the display list
+ (gameobj->GetMesh(m))->SchedulePolygons(rasty->GetDrawingMode(),rasty);
+ // Visibility/ non-visibility are marked
+ // elsewhere now.
+ gameobj->MarkVisible();
+ }
+ }
+}
+
+// logic stuff
+void KX_Scene::LogicBeginFrame(double curtime,double deltatime)
+{
+ // have a look at temp objects ...
+ int lastobj = m_tempObjectList->GetCount() - 1;
+
+ for (int i = lastobj; i >= 0; i--)
+ {
+ CValue* objval = m_tempObjectList->GetValue(i);
+ CFloatValue* propval = (CFloatValue*) objval->GetProperty("::timebomb");
+
+ if (propval)
+ {
+ float timeleft = propval->GetNumber() - deltatime;
+
+ if (timeleft > 0)
+ {
+ propval->SetFloat(timeleft);
+ }
+ else
+ {
+ DelayedRemoveObject(objval);
+ // remove obj
+ }
+ }
+ else
+ {
+ // all object is the tempObjectList should have a clock
+ }
+ }
+ m_logicmgr->BeginFrame(curtime,deltatime);
+}
+
+
+
+void KX_Scene::LogicUpdateFrame(double curtime,double deltatime)
+{
+ m_logicmgr->UpdateFrame(curtime,deltatime);
+}
+
+
+
+void KX_Scene::LogicEndFrame()
+{
+ m_logicmgr->EndFrame();
+ int numobj = m_euthanasyobjects->GetCount();
+
+ for (int i = numobj - 1; i >= 0; i--)
+ {
+ KX_GameObject* gameobj = (KX_GameObject*)m_euthanasyobjects->GetValue(i);
+ this->RemoveObject(gameobj);
+ }
+
+ numobj = m_euthanasyobjects->GetCount();
+ if (numobj != 0)
+ {
+ // huh?
+ int ii=0;
+ }
+ // numobj is 0 we hope
+}
+
+
+
+/**
+ * UpdateParents: SceneGraph transformation update.
+ */
+void KX_Scene::UpdateParents(double curtime)
+{
+// int numrootobjects = GetRootParentList()->GetCount();
+
+ for (int i=0; i<GetRootParentList()->GetCount(); i++)
+ {
+ KX_GameObject* parentobj = (KX_GameObject*)GetRootParentList()->GetValue(i);
+ parentobj->NodeUpdateGS(curtime,true);
+ }
+}
+
+
+
+RAS_MaterialBucket* KX_Scene::FindBucket(class RAS_IPolyMaterial* polymat)
+{
+ return m_bucketmanager->RAS_BucketManagerFindBucket(polymat);
+}
+
+
+
+void KX_Scene::RenderBuckets(const MT_Transform & cameratransform,
+ class RAS_IRasterizer* rasty,
+ class RAS_IRenderTools* rendertools)
+{
+ m_bucketmanager->Renderbuckets(cameratransform,rasty,rendertools);
+}
+
+
+
+void KX_Scene::UpdateObjectActivity(void)
+{
+ if (m_activity_culling) {
+ /* determine the activity criterium and set objects accordingly */
+ int i=0;
+
+ MT_Point3 camloc = GetActiveCamera()->NodeGetWorldPosition(); //GetCameraLocation();
+
+ for (i=0;i<GetObjectList()->GetCount();i++)
+ {
+ KX_GameObject* ob = (KX_GameObject*) GetObjectList()->GetValue(i);
+
+ if (!ob->GetIgnoreActivityCulling()) {
+ /* Simple test: more than 10 away from the camera, count
+ * Manhattan distance. */
+ MT_Point3 obpos = ob->NodeGetWorldPosition();
+
+ if ( (fabs(camloc[0] - obpos[0]) > m_activity_box_radius)
+ || (fabs(camloc[1] - obpos[1]) > m_activity_box_radius)
+ || (fabs(camloc[2] - obpos[2]) > m_activity_box_radius) )
+ {
+ ob->Suspend();
+ } else {
+ ob->Resume();
+ }
+ }
+ }
+ }
+}
+
+void KX_Scene::SetActivityCullingRadius(float f)
+{
+ if (f < 0.5)
+ f = 0.5;
+ m_activity_box_radius = f;
+}
+
+NG_NetworkDeviceInterface* KX_Scene::GetNetworkDeviceInterface()
+{
+ return m_networkDeviceInterface;
+}
+
+NG_NetworkScene* KX_Scene::GetNetworkScene()
+{
+ return m_networkScene;
+}
+
+void KX_Scene::SetNetworkDeviceInterface(NG_NetworkDeviceInterface* newInterface)
+{
+ m_networkDeviceInterface = newInterface;
+}
+
+void KX_Scene::SetNetworkScene(NG_NetworkScene *newScene)
+{
+ m_networkScene = newScene;
+}
+
+
+void KX_Scene::SetGravity(const MT_Vector3& gravity)
+{
+ GetPhysicsEnvironment()->setGravity(gravity[0],gravity[1],gravity[2]);
+}
diff --git a/source/gameengine/Ketsji/KX_Scene.h b/source/gameengine/Ketsji/KX_Scene.h
new file mode 100644
index 00000000000..818368561e6
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_Scene.h
@@ -0,0 +1,480 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 __KX_SCENE_H
+#define __KX_SCENE_H
+
+
+#include "KX_PhysicsEngineEnums.h"
+
+#include "MT_CmMatrix4x4.h"
+
+#include <vector>
+#include <set>
+
+#include "GEN_Map.h"
+#include "GEN_HashedPtr.h"
+#include "SG_IObject.h"
+#include "SCA_IScene.h"
+#include "MT_Transform.h"
+#include "SND_Scene.h"
+#include "RAS_FramingManager.h"
+#include "RAS_Rect.h"
+
+/**
+ * @section Forward declarations
+ */
+struct SM_MaterialProps;
+struct SM_ShapeProps;
+
+class CListValue;
+class RAS_BucketManager;
+class KX_Camera;
+class SCA_LogicManager;
+class SCA_KeyboardManager;
+class SCA_TimeEventManager;
+class SCA_MouseManager;
+class KX_WorldInfo;
+class SND_Scene;
+class SND_IAudioDevice;
+class NG_NetworkDeviceInterface;
+class NG_NetworkScene;
+class SG_Node;
+class KX_Camera;
+class GEN_HashedPtr;
+class KX_GameObject;
+class SCA_ISystem;
+class SCA_IInputDevice;
+class RAS_BucketManager;
+class RAS_MaterialBucket;
+class RAS_IPolyMaterial;
+class RAS_IRasterizer;
+class RAS_IRenderTools;
+class CValue;
+class SG_IObject;
+
+/**
+ * The KX_Scene holds all data for an independent scene. It relates
+ * KX_Objects to the specific objects in the modules.
+ * */
+class KX_Scene : public SCA_IScene
+{
+ RAS_BucketManager* m_bucketmanager;
+ CListValue* m_tempObjectList;
+
+ /**
+ * The list of objects which have been removed during the
+ * course of one frame. They are actually destroyed in
+ * LogicEndFrame() via a call to RemoveObject().
+ */
+ CListValue* m_euthanasyobjects;
+
+ CListValue* m_objectlist;
+ CListValue* m_parentlist; // all 'root' parents
+ CListValue* m_lightlist;
+
+ /**
+ * The set of cameras for this scene
+ */
+ set<class KX_Camera*> m_cameras;
+
+ /**
+ * Various SCA managers used by the scene
+ */
+ SCA_LogicManager* m_logicmgr;
+ SCA_KeyboardManager* m_keyboardmgr;
+ SCA_MouseManager* m_mousemgr;
+ SCA_TimeEventManager* m_timemgr;
+
+ /**
+ * physics engine abstraction
+ */
+
+ e_PhysicsEngine m_physicsEngine;
+ class PHY_IPhysicsEnvironment* m_physicsEnvironment;
+
+ /**
+ * Does this scene clear the z-buffer?
+ */
+ bool m_isclearingZbuffer;
+
+ /**
+ * The name of the scene
+ */
+ STR_String m_sceneName;
+
+ /**
+ * stores the worldsettings for a scene
+ */
+ KX_WorldInfo* m_worldinfo;
+
+ /**
+ * @section Different scenes, linked to ketsji scene
+ */
+
+
+ /**
+ * Sound scenes
+ */
+ SND_Scene* m_soundScene;
+ SND_IAudioDevice* m_adi;
+
+ /**
+ * Network scene.
+ */
+ NG_NetworkDeviceInterface* m_networkDeviceInterface;
+ NG_NetworkScene* m_networkScene;
+
+ /**
+ * A temoprary variable used to parent objects together on
+ * replication. Don't get confused by the name it is not
+ * the scene's root node!
+ */
+ SG_Node* m_rootnode;
+
+ /**
+ * The active camera for the scene
+ */
+ KX_Camera* m_active_camera;
+
+ /**
+ * The projection and view matrices of this scene
+ * The projection matrix is computed externally by KX_Engine
+ * The view mat is stored as a side effect of GetViewMatrix()
+ * and is totally unnessary.
+ */
+ MT_CmMatrix4x4 m_projectionmat;
+ MT_CmMatrix4x4 m_viewmat;
+
+ /** Desired canvas width set at design time. */
+ unsigned int m_canvasDesignWidth;
+ /** Desired canvas height set at design time. */
+ unsigned int m_canvasDesignHeight;
+
+ /**
+ * Another temporary variable outstaying its welcome
+ * used in AddReplicaObject to map game objects to their
+ * replicas so pointers can be updated.
+ */
+ GEN_Map <GEN_HashedPtr, void*> m_map_gameobject_to_replica;
+
+ /**
+ * Another temporary variable outstaying its welcome
+ * used in AddReplicaObject to keep a record of all added
+ * objects. Logic can only be updated when all objects
+ * have been updated. This stores a list of the new objects.
+ */
+ std::vector<KX_GameObject*> m_logicHierarchicalGameObjects;
+
+ /**
+ * Pointer to system variable passed in in constructor
+ * only used in constructor so we do not need to keep it
+ * around in this class.
+ */
+
+ SCA_ISystem* m_kxsystem;
+
+ /**
+ * The execution priority of replicated object actuators?
+ */
+ int m_ueberExecutionPriority;
+
+ /**
+ * Activity 'bubble' settings :
+ * Suspend (freeze) the entire scene.
+ */
+ bool m_suspend;
+
+ /**
+ * Radius in Manhattan distance of the box for activity culling.
+ */
+ float m_activity_box_radius;
+
+ /**
+ * Toggle to enable or disable activity culling.
+ */
+ bool m_activity_culling;
+
+ /**
+ * The framing settings used by this scene
+ */
+
+ RAS_FrameSettings m_frame_settings;
+
+ /**
+ * This scenes viewport into the game engine
+ * canvas.Maintained externally, initially [0,0] -> [0,0]
+ */
+ RAS_Rect m_viewport;
+
+public:
+ KX_Scene(class SCA_IInputDevice* keyboarddevice,
+ class SCA_IInputDevice* mousedevice,
+ class NG_NetworkDeviceInterface* ndi,
+ class SND_IAudioDevice* adi,
+ const STR_String& scenename );
+
+ virtual
+ ~KX_Scene();
+
+ RAS_BucketManager* GetBucketManager();
+ RAS_MaterialBucket* FindBucket(RAS_IPolyMaterial* polymat);
+ void RenderBuckets(const MT_Transform& cameratransform,
+ RAS_IRasterizer* rasty,
+ RAS_IRenderTools* rendertools);
+ /**
+ * Update all transforms according to the scenegraph.
+ */
+ void UpdateParents(double curtime);
+ SCA_IObject* AddReplicaObject(CValue* gameobj,
+ CValue* locationobj,
+ int lifespan=0);
+ KX_GameObject* AddNodeReplicaObject(SG_IObject* node,
+ CValue* gameobj);
+ void RemoveNodeDestructObject(SG_IObject* node,
+ CValue* gameobj);
+ void RemoveObject(CValue* gameobj);
+ void DelayedRemoveObject(CValue* gameobj);
+ void NewRemoveObject(CValue* gameobj);
+ void ReplaceMesh(CValue* gameobj,
+ void* meshobj);
+ /**
+ * @section Logic stuff
+ * Initiate an update of the logic system.
+ */
+ void LogicBeginFrame(double curtime,
+ double deltatime);
+ void LogicUpdateFrame(double curtime,
+ double deltatime);
+
+ void
+ LogicEndFrame(
+ );
+
+ CListValue*
+ GetObjectList(
+ );
+
+ CListValue*
+ GetRootParentList(
+ );
+
+ CListValue*
+ GetLightList(
+ );
+
+ SCA_LogicManager*
+ GetLogicManager(
+ );
+
+ SCA_TimeEventManager*
+ GetTimeEventManager(
+ );
+
+
+ /** Find a camera in the scene by pointer. */
+ KX_Camera*
+ FindCamera(
+ KX_Camera*
+ );
+
+ /** Find a scene in the scene by name. */
+ KX_Camera*
+ FindCamera(
+ STR_String&
+ );
+
+ /** Add a camera to this scene. */
+ void
+ AddCamera(
+ KX_Camera*
+ );
+
+ /** Find the currently active camera. */
+ KX_Camera*
+ GetActiveCamera(
+ );
+
+ /**
+ * Set this camera to be the active camera in the scene. If the
+ * camera is not present in the camera list, it will be added
+ */
+
+ void
+ SetActiveCamera(
+ class KX_Camera*
+ );
+
+ /** Return the viewmatrix as used by the last frame. */
+ MT_CmMatrix4x4&
+ GetViewMatrix(
+ );
+
+ /**
+ * Return the projectionmatrix as used by the last frame. This is
+ * set by hand :)
+ */
+ MT_CmMatrix4x4&
+ GetProjectionMatrix(
+ );
+
+ /** Sets the projection matrix. */
+ void
+ SetProjectionMatrix(
+ MT_CmMatrix4x4& pmat
+ );
+
+ /**
+ * Activates new desired canvas width set at design time.
+ * @param width The new desired width.
+ */
+ void
+ SetCanvasDesignWidth(
+ unsigned int width
+ );
+ /**
+ * Activates new desired canvas height set at design time.
+ * @param width The new desired height.
+ */
+ void
+ SetCanvasDesignHeight(
+ unsigned int height
+ );
+ /**
+ * Returns the current desired canvas width set at design time.
+ * @return The desired width.
+ */
+ unsigned int
+ GetCanvasDesignWidth(
+ void
+ ) const;
+
+ /**
+ * Returns the current desired canvas height set at design time.
+ * @return The desired height.
+ */
+ unsigned int
+ GetCanvasDesignHeight(
+ void
+ ) const;
+
+ /**
+ * Set the framing options for this scene
+ */
+
+ void
+ SetFramingType(
+ RAS_FrameSettings & frame_settings
+ );
+
+ /**
+ * Return a const reference to the framing
+ * type set by the above call.
+ * The contents are not guarenteed to be sensible
+ * if you don't call the above function.
+ */
+
+ const
+ RAS_FrameSettings &
+ GetFramingType(
+ ) const;
+
+ /**
+ * Store the current scene's viewport on the
+ * game engine canvas.
+ */
+ void SetSceneViewport(const RAS_Rect &viewport);
+
+ /**
+ * Get the current scene's viewport on the
+ * game engine canvas. This maintained
+ * externally in KX_GameEngine
+ */
+ const RAS_Rect& GetSceneViewport() const;
+
+ /**
+ * @section Accessors to different scenes of this scene
+ */
+ void SetNetworkDeviceInterface(NG_NetworkDeviceInterface* newInterface);
+ void SetNetworkScene(NG_NetworkScene *newScene);
+ void SetWorldInfo(class KX_WorldInfo* wi);
+ KX_WorldInfo* GetWorldInfo();
+ void CalculateVisibleMeshes(RAS_IRasterizer* rasty);
+ void UpdateMeshTransformations();
+ KX_Camera* GetpCamera();
+ SND_Scene* GetSoundScene();
+ NG_NetworkDeviceInterface* GetNetworkDeviceInterface();
+ NG_NetworkScene* GetNetworkScene();
+
+ /**
+ * Replicate the logic bricks associated to this object.
+ */
+
+ void ReplicateLogic(class KX_GameObject* newobj);
+ static SG_Callbacks m_callbacks;
+
+ const STR_String& GetName();
+
+ // Suspend the entire scene.
+ void Suspend();
+
+ // Resume a suspended scene.
+ void Resume();
+
+ // Update the activity box settings for objects in this scene, if needed.
+ void UpdateObjectActivity(void);
+
+ // Enable/disable activity culling.
+ void SetActivityCulling(bool b);
+
+ // Set the radius of the activity culling box.
+ void SetActivityCullingRadius(float f);
+ bool IsSuspended();
+ bool IsClearingZBuffer();
+ void EnableZBufferClearing(bool isclearingZbuffer);
+
+ class PHY_IPhysicsEnvironment* GetPhysicsEnvironment()
+ {
+ return m_physicsEnvironment;
+ }
+
+ void SetPhysicsEnvironment(class PHY_IPhysicsEnvironment* physEnv)
+ {
+ m_physicsEnvironment = physEnv;
+ }
+
+ void SetGravity(const MT_Vector3& gravity);
+};
+
+typedef std::vector<KX_Scene*> KX_SceneList;
+
+#endif //__KX_SCENE_H
+
diff --git a/source/gameengine/Ketsji/KX_SceneActuator.cpp b/source/gameengine/Ketsji/KX_SceneActuator.cpp
new file mode 100644
index 00000000000..7cba1a6ac1e
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_SceneActuator.cpp
@@ -0,0 +1,354 @@
+/**
+* Set scene/camera stuff
+*
+* $Id$
+*
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "SCA_IActuator.h"
+#include "KX_SceneActuator.h"
+#include <iostream>
+#include "KX_Scene.h"
+#include "KX_Camera.h"
+#include "KX_KetsjiEngine.h"
+
+/* ------------------------------------------------------------------------- */
+/* Native functions */
+/* ------------------------------------------------------------------------- */
+
+KX_SceneActuator::KX_SceneActuator(SCA_IObject *gameobj,
+ int mode,
+ KX_Scene *scene,
+ KX_KetsjiEngine* ketsjiEngine,
+ const STR_String& nextSceneName,
+ KX_Camera* camera,
+ PyTypeObject* T)
+ : SCA_IActuator(gameobj, T)
+{
+ m_mode = mode;
+ m_scene = scene;
+ m_KetsjiEngine=ketsjiEngine;
+ m_camera = camera;
+ m_nextSceneName = nextSceneName;
+} /* End of constructor */
+
+
+
+KX_SceneActuator::~KX_SceneActuator()
+{
+ // there's nothing to be done here, really....
+} /* end of destructor */
+
+
+
+CValue* KX_SceneActuator::GetReplica()
+{
+ KX_SceneActuator* replica = new KX_SceneActuator(*this);
+ replica->ProcessReplica();
+ // this will copy properties and so on...
+ CValue::AddDataToReplica(replica);
+
+ return replica;
+}
+
+
+
+bool KX_SceneActuator::Update(double curtime,double deltatime)
+{
+ bool result = false;
+ bool bNegativeEvent = IsNegativeEvent();
+ RemoveAllEvents();
+
+ if (bNegativeEvent)
+ return false; // do nothing on negative events
+
+ switch (m_mode)
+ {
+ case KX_SCENE_RESTART:
+ {
+ m_KetsjiEngine->ReplaceScene(m_scene->GetName(),m_scene->GetName());
+ break;
+ }
+ case KX_SCENE_SET_SCENE:
+ {
+ m_KetsjiEngine->ReplaceScene(m_scene->GetName(),m_nextSceneName);
+ break;
+ }
+ case KX_SCENE_ADD_FRONT_SCENE:
+ {
+ bool overlay=true;
+ m_KetsjiEngine->ConvertAndAddScene(m_nextSceneName,overlay);
+ break;
+ }
+ case KX_SCENE_ADD_BACK_SCENE:
+ {
+ bool overlay=false;
+ m_KetsjiEngine->ConvertAndAddScene(m_nextSceneName,overlay);
+ break;
+ }
+ case KX_SCENE_REMOVE_SCENE:
+ {
+ m_KetsjiEngine->RemoveScene(m_nextSceneName);
+ break;
+ }
+ case KX_SCENE_SUSPEND:
+ {
+ m_KetsjiEngine->SuspendScene(m_nextSceneName);
+ break;
+ }
+ case KX_SCENE_RESUME:
+ {
+ m_KetsjiEngine->ResumeScene(m_nextSceneName);
+ break;
+ }
+ case KX_SCENE_SET_CAMERA:
+ if (m_camera)
+ {
+ m_scene->SetActiveCamera(m_camera);
+ }
+ break;
+ default:
+ ; /* do nothing? this is an internal error !!! */
+ }
+
+ return false;
+}
+
+
+
+/* returns a camera if the name is valid */
+KX_Camera* KX_SceneActuator::FindCamera(char *camName)
+{
+ KX_SceneList* sl = m_KetsjiEngine->CurrentScenes();
+ STR_String name = STR_String(camName);
+ KX_SceneList::iterator it = sl->begin();
+ KX_Camera* cam = NULL;
+
+ while ((it != sl->end()) && (!cam))
+ {
+ cam = (*it)->FindCamera(name);
+ it++;
+ }
+
+ return cam;
+}
+
+
+
+KX_Scene* KX_SceneActuator::FindScene(char * sceneName)
+{
+ return m_KetsjiEngine->FindScene(sceneName);
+}
+
+
+
+
+/* ------------------------------------------------------------------------- */
+/* Python functions */
+/* ------------------------------------------------------------------------- */
+
+/* Integration hooks ------------------------------------------------------- */
+PyTypeObject KX_SceneActuator::Type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0,
+ "KX_SceneActuator",
+ sizeof(KX_SceneActuator),
+ 0,
+ PyDestructor,
+ 0,
+ __getattr,
+ __setattr,
+ 0, //&MyPyCompare,
+ __repr,
+ 0, //&cvalue_as_number,
+ 0,
+ 0,
+ 0,
+ 0
+};
+
+
+
+PyParentObject KX_SceneActuator::Parents[] =
+{
+ &KX_SceneActuator::Type,
+ &SCA_IActuator::Type,
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
+};
+
+
+
+PyMethodDef KX_SceneActuator::Methods[] =
+{
+ {"setUseRestart", (PyCFunction) KX_SceneActuator::sPySetUseRestart, METH_VARARGS, SetUseRestart_doc},
+ {"setScene", (PyCFunction) KX_SceneActuator::sPySetScene, METH_VARARGS, SetScene_doc},
+ {"setCamera", (PyCFunction) KX_SceneActuator::sPySetCamera, METH_VARARGS, SetCamera_doc},
+ {"getUseRestart", (PyCFunction) KX_SceneActuator::sPyGetUseRestart, METH_VARARGS, GetUseRestart_doc},
+ {"getScene", (PyCFunction) KX_SceneActuator::sPyGetScene, METH_VARARGS, GetScene_doc},
+ {"getCamera", (PyCFunction) KX_SceneActuator::sPyGetCamera, METH_VARARGS, GetCamera_doc},
+ {NULL,NULL} //Sentinel
+};
+
+
+
+PyObject* KX_SceneActuator::_getattr(char* attr)
+{
+ _getattr_up(SCA_IActuator);
+}
+
+
+
+/* 2. setUseRestart--------------------------------------------------------- */
+char KX_SceneActuator::SetUseRestart_doc[] =
+"setUseRestart(flag)\n"
+"\t- flag: 0 or 1.\n"
+"\tSet flag to 1 to restart the scene.\n" ;
+PyObject* KX_SceneActuator::PySetUseRestart(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ int boolArg;
+
+ if (!PyArg_ParseTuple(args, "i", &boolArg))
+ {
+ return NULL;
+ }
+
+ if (boolArg == KX_TRUE)
+ {
+ m_restart = true;
+ }
+ else if (boolArg == KX_FALSE)
+ {
+ m_restart = false;
+ }
+ else
+ {
+ ; /* internal error */
+ }
+
+ Py_Return;
+}
+
+
+
+/* 3. getUseRestart: */
+char KX_SceneActuator::GetUseRestart_doc[] =
+"getUseRestart()\n"
+"\tReturn whether the scene will be restarted.\n" ;
+PyObject* KX_SceneActuator::PyGetUseRestart(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ return PyInt_FromLong(!(m_restart == 0));
+}
+
+
+
+/* 4. set scene------------------------------------------------------------- */
+char KX_SceneActuator::SetScene_doc[] =
+"setScene(scene)\n"
+"\t- scene: string\n"
+"\tSet the name of scene the actuator will switch to.\n" ;
+PyObject* KX_SceneActuator::PySetScene(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ /* one argument: a scene, ignore the rest */
+ char *scene_name;
+
+ if(!PyArg_ParseTuple(args, "s", &scene_name))
+ {
+ return NULL;
+ }
+
+ if (m_KetsjiEngine->FindScene(scene_name))
+ {
+ /* Scene switch is done by name. */
+ m_nextSceneName = scene_name;
+ }
+
+ Py_Return;
+}
+
+
+
+/* 5. getScene: */
+char KX_SceneActuator::GetScene_doc[] =
+"getScene()\n"
+"\tReturn the name of the scene the actuator wants to switch to.\n" ;
+PyObject* KX_SceneActuator::PyGetScene(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ return PyString_FromString(m_nextSceneName);
+}
+
+
+
+/* 6. set camera------------------------------------------------------------ */
+char KX_SceneActuator::SetCamera_doc[] =
+"setCamera(camera)\n"
+"\t- camera: string\n"
+"\tSet the camera to switch to.\n" ;
+PyObject* KX_SceneActuator::PySetCamera(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ /* one argument: a scene, ignore the rest */
+ char *camName;
+ KX_Camera *camOb;
+
+ if(!PyArg_ParseTuple(args, "s", &camName))
+ {
+ return NULL;
+ }
+
+ camOb = FindCamera(camName);
+ if (camOb) m_camera = camOb;
+
+ Py_Return;
+}
+
+
+
+/* 7. getCamera: */
+char KX_SceneActuator::GetCamera_doc[] =
+"getCamera()\n"
+"\tReturn the name of the camera to switch to.\n" ;
+PyObject* KX_SceneActuator::PyGetCamera(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ return PyString_FromString(m_camera->GetName());
+}
+/* eof */
diff --git a/source/gameengine/Ketsji/KX_SceneActuator.h b/source/gameengine/Ketsji/KX_SceneActuator.h
new file mode 100644
index 00000000000..a9f3751322e
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_SceneActuator.h
@@ -0,0 +1,115 @@
+
+//
+// Add object to the game world on action of this actuator
+//
+// $Id$
+//
+// ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version. The Blender
+// Foundation also sells licenses for use in proprietary software under
+// the Blender License. See http://www.blender.org/BL/ for information
+// about this.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// The Original Code is Copyright (C) 2001-2002 by 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 __KX_SCENEACTUATOR
+#define __KX_SCENEACTUATOR
+
+#include "SCA_IActuator.h"
+
+class KX_SceneActuator : public SCA_IActuator
+{
+ Py_Header;
+
+ int m_mode;
+ // (restart) has become a toggle internally... not in the interface though
+ bool m_restart;
+ // (set Scene) Scene
+ /** The current scene. */
+ class KX_Scene* m_scene;
+ class KX_KetsjiEngine* m_KetsjiEngine;
+ /** The scene to switch to. */
+ STR_String m_nextSceneName;
+
+ // (Set Camera) Object
+ class KX_Camera* m_camera;
+
+ /** Is this a valid scene? */
+ class KX_Scene* FindScene(char* sceneName);
+ /** Is this a valid camera? */
+ class KX_Camera* FindCamera(char* cameraName);
+
+ public:
+ enum SCA_SceneActuatorMode
+ {
+ KX_SCENE_NODEF = 0,
+ KX_SCENE_RESTART,
+ KX_SCENE_SET_SCENE,
+ KX_SCENE_SET_CAMERA,
+ KX_SCENE_ADD_FRONT_SCENE,
+ KX_SCENE_ADD_BACK_SCENE,
+ KX_SCENE_REMOVE_SCENE,
+ KX_SCENE_SUSPEND,
+ KX_SCENE_RESUME,
+ KX_SCENE_MAX
+ };
+
+ KX_SceneActuator(SCA_IObject* gameobj,
+ int mode,
+ KX_Scene* scene,
+ KX_KetsjiEngine* ketsjiEngine,
+ const STR_String& nextSceneName,
+ KX_Camera* camera,
+ PyTypeObject* T=&Type);
+ virtual ~KX_SceneActuator();
+
+ virtual CValue* GetReplica();
+
+ virtual bool Update(double curtime,double deltatime);
+
+ /* --------------------------------------------------------------------- */
+ /* Python interface ---------------------------------------------------- */
+ /* --------------------------------------------------------------------- */
+
+ virtual PyObject* _getattr(char *attr);
+
+ /* 1. set */
+ /* Removed */
+
+ /* 2. setUseRestart: */
+ KX_PYMETHOD_DOC(KX_SceneActuator,SetUseRestart);
+ /* 3. getUseRestart: */
+ KX_PYMETHOD_DOC(KX_SceneActuator,GetUseRestart);
+ /* 4. setScene: */
+ KX_PYMETHOD_DOC(KX_SceneActuator,SetScene);
+ /* 5. getScene: */
+ KX_PYMETHOD_DOC(KX_SceneActuator,GetScene);
+ /* 6. setCamera: */
+ KX_PYMETHOD_DOC(KX_SceneActuator,SetCamera);
+ /* 7. getCamera: */
+ KX_PYMETHOD_DOC(KX_SceneActuator,GetCamera);
+
+}; /* end of class KXSceneActuator */
+
+#endif
diff --git a/source/gameengine/Ketsji/KX_SoundActuator.cpp b/source/gameengine/Ketsji/KX_SoundActuator.cpp
new file mode 100644
index 00000000000..b36ff5f2c09
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_SoundActuator.cpp
@@ -0,0 +1,466 @@
+/**
+ * KX_SoundActuator.cpp
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "KX_SoundActuator.h"
+#include "SND_SoundObject.h"
+#include "KX_GameObject.h"
+#include "SND_SoundObject.h"
+#include "SND_Scene.h" // needed for replication
+#include <iostream>
+
+/* ------------------------------------------------------------------------- */
+/* Native functions */
+/* ------------------------------------------------------------------------- */
+KX_SoundActuator::KX_SoundActuator(SCA_IObject* gameobj,
+ SND_SoundObject* sndobj,
+ SND_Scene* sndscene,
+ KX_SOUNDACT_TYPE type,
+ short start,
+ short end,
+ PyTypeObject* T)
+ : SCA_IActuator(gameobj,T)
+{
+ m_soundObject = sndobj;
+ m_soundScene = sndscene;
+ m_type = type;
+ m_lastEvent = true;
+ m_isplaying = false;
+ m_startFrame = start;
+ m_endFrame = end;
+ m_pino = false;
+}
+
+
+
+KX_SoundActuator::~KX_SoundActuator()
+{
+ //m_soundScene->RemoveObject(this->m_soundObject);
+ //(this->m_soundObject)->DeleteWhenFinished();
+ m_soundScene->RemoveActiveObject(m_soundObject);
+// m_soundScene->DeleteObjectWhenFinished(m_soundObject);
+ m_soundScene->DeleteObject(m_soundObject);
+}
+
+
+
+CValue* KX_SoundActuator::GetReplica()
+{
+ KX_SoundActuator* replica = new KX_SoundActuator(*this);
+ replica->ProcessReplica();
+ SND_SoundObject* soundobj = new SND_SoundObject(*m_soundObject);
+ replica->setSoundObject(soundobj);
+ m_soundScene->AddObject(soundobj);
+
+ // this will copy properties and so on...
+ CValue::AddDataToReplica(replica);
+ return replica;
+};
+
+
+
+bool KX_SoundActuator::Update(double curtime,double deltatime)
+{
+ bool result = false;
+
+ // do nothing on negative events, otherwise sounds are played twice!
+ bool bNegativeEvent = IsNegativeEvent();
+
+ RemoveAllEvents();
+
+ if (m_pino)
+ {
+ bNegativeEvent = true;
+ m_pino = false;
+ }
+
+ if (bNegativeEvent)
+ {
+ // here must be a check if it is still playing
+ m_isplaying = false;
+
+ switch (m_type)
+ {
+ case KX_SOUNDACT_PLAYSTOP:
+ case KX_SOUNDACT_LOOPSTOP:
+ case KX_SOUNDACT_LOOPBIDIRECTIONAL_STOP:
+ {
+ m_soundScene->RemoveActiveObject(m_soundObject);
+ break;
+ }
+ case KX_SOUNDACT_PLAYEND:
+ {
+ m_soundObject->SetPlaystate(SND_MUST_STOP_WHEN_FINISHED);
+ break;
+ }
+ default:
+ // implement me !!
+ break;
+ }
+ }
+ else
+ {
+ if (m_soundObject && !m_isplaying)
+ {
+ switch (m_type)
+ {
+ case KX_SOUNDACT_LOOPBIDIRECTIONAL:
+ case KX_SOUNDACT_LOOPBIDIRECTIONAL_STOP:
+ {
+ m_soundObject->SetLoopMode(SND_LOOP_BIDIRECTIONAL);
+ m_soundScene->AddActiveObject(m_soundObject, curtime);
+ m_isplaying = true;
+ result = true;
+ break;
+ }
+ case KX_SOUNDACT_LOOPEND:
+ case KX_SOUNDACT_LOOPSTOP:
+ {
+ m_soundObject->SetLoopMode(SND_LOOP_NORMAL);
+ m_soundScene->AddActiveObject(m_soundObject, curtime);
+ m_isplaying = true;
+ result = true;
+ break;
+ }
+ case KX_SOUNDACT_PLAYSTOP:
+ case KX_SOUNDACT_PLAYEND:
+ {
+ m_soundObject->SetLoopMode(SND_LOOP_OFF);
+ m_soundScene->AddActiveObject(m_soundObject, curtime);
+ m_isplaying = true;
+ result = true;
+ break;
+ }
+ default:
+ // implement me !!
+ break;
+ }
+ }
+ }
+
+ if (m_isplaying)
+ {
+ m_soundObject->SetPosition(((KX_GameObject*)this->GetParent())->NodeGetWorldPosition());
+ m_soundObject->SetVelocity(((KX_GameObject*)this->GetParent())->GetLinearVelocity());
+ m_soundObject->SetOrientation(((KX_GameObject*)this->GetParent())->NodeGetWorldOrientation());
+ result = true;
+ }
+ else
+ {
+ result = false;
+ }
+
+ if (result && (m_soundObject->IsLifeSpanOver(curtime)) && ((m_type == KX_SOUNDACT_PLAYEND) || (m_type == KX_SOUNDACT_PLAYSTOP)))
+ {
+ m_pino = true;
+ }
+
+ return result;
+}
+
+
+
+void KX_SoundActuator::setSoundObject(class SND_SoundObject* soundobject)
+{
+ m_soundObject = soundobject;
+}
+
+
+
+/* ------------------------------------------------------------------------- */
+/* Python functions */
+/* ------------------------------------------------------------------------- */
+
+
+
+/* Integration hooks ------------------------------------------------------- */
+PyTypeObject KX_SoundActuator::Type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0,
+ "KX_SoundActuator",
+ sizeof(KX_SoundActuator),
+ 0,
+ PyDestructor,
+ 0,
+ __getattr,
+ __setattr,
+ 0, //&MyPyCompare,
+ __repr,
+ 0, //&cvalue_as_number,
+ 0,
+ 0,
+ 0,
+ 0
+};
+
+
+
+PyParentObject KX_SoundActuator::Parents[] = {
+ &KX_SoundActuator::Type,
+ &SCA_IActuator::Type,
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
+};
+
+
+
+PyMethodDef KX_SoundActuator::Methods[] = {
+ {"setFilename", (PyCFunction) KX_SoundActuator::sPySetFilename, METH_VARARGS,NULL},
+ {"getFilename", (PyCFunction) KX_SoundActuator::sPyGetFilename, METH_VARARGS,NULL},
+ {"startSound",(PyCFunction) KX_SoundActuator::sPyStartSound,METH_VARARGS,NULL},
+ {"pauseSound",(PyCFunction) KX_SoundActuator::sPyPauseSound,METH_VARARGS,NULL},
+ {"stopSound",(PyCFunction) KX_SoundActuator::sPyStopSound,METH_VARARGS,NULL},
+ {"setGain",(PyCFunction) KX_SoundActuator::sPySetGain,METH_VARARGS,NULL},
+ {"getGain",(PyCFunction) KX_SoundActuator::sPyGetGain,METH_VARARGS,NULL},
+ {"setPitch",(PyCFunction) KX_SoundActuator::sPySetPitch,METH_VARARGS,NULL},
+ {"getPitch",(PyCFunction) KX_SoundActuator::sPyGetPitch,METH_VARARGS,NULL},
+ {"setRollOffFactor",(PyCFunction) KX_SoundActuator::sPySetRollOffFactor,METH_VARARGS,NULL},
+ {"getRollOffFactor",(PyCFunction) KX_SoundActuator::sPyGetRollOffFactor,METH_VARARGS,NULL},
+ {"setLooping",(PyCFunction) KX_SoundActuator::sPySetLooping,METH_VARARGS,NULL},
+ {"getLooping",(PyCFunction) KX_SoundActuator::sPyGetLooping,METH_VARARGS,NULL},
+ {"setPosition",(PyCFunction) KX_SoundActuator::sPySetPosition,METH_VARARGS,NULL},
+ {"setVelocity",(PyCFunction) KX_SoundActuator::sPySetVelocity,METH_VARARGS,NULL},
+ {"setOrientation",(PyCFunction) KX_SoundActuator::sPySetOrientation,METH_VARARGS,NULL},
+ {NULL,NULL,NULL,NULL} //Sentinel
+};
+
+
+
+PyObject* KX_SoundActuator::_getattr(char* attr)
+{
+ _getattr_up(SCA_IActuator);
+}
+
+
+
+PyObject* KX_SoundActuator::PySetFilename(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ char *soundName = NULL;
+ void *soundPointer = NULL;
+
+ if (!PyArg_ParseTuple(args, "s", &soundName))
+ return NULL;
+
+ Py_Return;
+}
+
+
+
+PyObject* KX_SoundActuator::PyGetFilename(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ STR_String objectname = m_soundObject->GetObjectName();
+ char* name = objectname.Ptr();
+
+ if (!name) {
+ Py_Return; /* internal error */
+ } else
+ return PyString_FromString(name);
+}
+
+
+
+PyObject* KX_SoundActuator::PyStartSound(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ m_soundObject->StartSound();
+ Py_Return;
+}
+
+
+
+PyObject* KX_SoundActuator::PyPauseSound(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ m_soundObject->PauseSound();
+ Py_Return;
+}
+
+
+
+PyObject* KX_SoundActuator::PyStopSound(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ m_soundObject->StopSound();
+ Py_Return;
+}
+
+
+
+PyObject* KX_SoundActuator::PySetGain(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ float gain = 1.0;
+ if (!PyArg_ParseTuple(args, "f", &gain))
+ return NULL;
+
+ m_soundObject->SetGain(gain);
+
+ Py_Return;
+}
+
+
+
+PyObject* KX_SoundActuator::PyGetGain(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ float gain = m_soundObject->GetGain();
+ PyObject* result = PyFloat_FromDouble(gain);
+
+ return result;
+}
+
+
+
+PyObject* KX_SoundActuator::PySetPitch(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ float pitch = 1.0;
+ if (!PyArg_ParseTuple(args, "f", &pitch))
+ return NULL;
+
+ m_soundObject->SetPitch(pitch);
+
+ Py_Return;
+}
+
+
+
+PyObject* KX_SoundActuator::PyGetPitch(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ float pitch = m_soundObject->GetPitch();
+ PyObject* result = PyFloat_FromDouble(pitch);
+
+ return result;
+}
+
+
+
+PyObject* KX_SoundActuator::PySetRollOffFactor(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ float rollofffactor = 1.0;
+ if (!PyArg_ParseTuple(args, "f", &rollofffactor))
+ return NULL;
+
+ m_soundObject->SetRollOffFactor(rollofffactor);
+
+ Py_Return;
+}
+
+
+
+PyObject* KX_SoundActuator::PyGetRollOffFactor(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ float rollofffactor = m_soundObject->GetRollOffFactor();
+ PyObject* result = PyFloat_FromDouble(rollofffactor);
+
+ return result;
+}
+
+
+
+PyObject* KX_SoundActuator::PySetLooping(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ bool looping = 1;
+ if (!PyArg_ParseTuple(args, "i", &looping))
+ return NULL;
+
+ m_soundObject->SetLoopMode(looping);
+
+ Py_Return;
+}
+
+
+
+PyObject* KX_SoundActuator::PyGetLooping(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ int looping = m_soundObject->GetLoopMode();
+ PyObject* result = PyInt_FromLong(looping);
+
+ return result;
+}
+
+
+
+PyObject* KX_SoundActuator::PySetPosition(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ MT_Point3 pos;
+ pos[0] = 0.0;
+ pos[1] = 0.0;
+ pos[2] = 0.0;
+
+ if (!PyArg_ParseTuple(args, "fff", &pos[0], &pos[1], &pos[2]))
+ return NULL;
+
+ m_soundObject->SetPosition(pos);
+
+ Py_Return;
+}
+
+
+
+PyObject* KX_SoundActuator::PySetVelocity(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ MT_Vector3 vel;
+ vel[0] = 0.0;
+ vel[1] = 0.0;
+ vel[2] = 0.0;
+
+ if (!PyArg_ParseTuple(args, "fff", &vel[0], &vel[1], &vel[2]))
+ return NULL;
+
+ m_soundObject->SetVelocity(vel);
+
+ Py_Return;
+}
+
+
+
+PyObject* KX_SoundActuator::PySetOrientation(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ MT_Matrix3x3 ori;
+ ori[0][0] = 1.0;
+ ori[0][1] = 0.0;
+ ori[0][2] = 0.0;
+ ori[1][0] = 0.0;
+ ori[1][1] = 1.0;
+ ori[1][2] = 0.0;
+ ori[2][0] = 0.0;
+ ori[2][1] = 0.0;
+ ori[2][2] = 1.0;
+
+ if (!PyArg_ParseTuple(args, "fffffffff", &ori[0][0], &ori[0][1], &ori[0][2], &ori[1][0], &ori[1][1], &ori[1][2], &ori[2][0], &ori[2][1], &ori[2][2]))
+ return NULL;
+
+ m_soundObject->SetOrientation(ori);
+
+ Py_Return;
+}
+
+
+
diff --git a/source/gameengine/Ketsji/KX_SoundActuator.h b/source/gameengine/Ketsji/KX_SoundActuator.h
new file mode 100644
index 00000000000..1ebc3ef5250
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_SoundActuator.h
@@ -0,0 +1,106 @@
+/**
+ * KX_SoundActuator.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 __KX_SOUNDACTUATOR
+#define __KX_SOUNDACTUATOR
+
+#include "SCA_IActuator.h"
+
+class KX_SoundActuator : public SCA_IActuator
+{
+ Py_Header;
+ bool m_lastEvent;
+ bool m_isplaying;
+ /* just some handles to the audio-data... */
+ class SND_SoundObject* m_soundObject;
+ class SND_Scene* m_soundScene;
+ short m_startFrame;
+ short m_endFrame;
+ bool m_pino;
+public:
+
+ enum KX_SOUNDACT_TYPE
+ {
+ KX_SOUNDACT_NODEF = 0,
+ KX_SOUNDACT_PLAYSTOP,
+ KX_SOUNDACT_PLAYEND,
+ KX_SOUNDACT_LOOPSTOP,
+ KX_SOUNDACT_LOOPEND,
+ KX_SOUNDACT_LOOPBIDIRECTIONAL,
+ KX_SOUNDACT_LOOPBIDIRECTIONAL_STOP,
+ KX_SOUNDACT_MAX
+ };
+
+ KX_SOUNDACT_TYPE m_type;
+
+ KX_SoundActuator(SCA_IObject* gameobj,
+ class SND_SoundObject* sndobj,
+ class SND_Scene* sndscene,
+ KX_SOUNDACT_TYPE type,
+ short start,
+ short end,
+ PyTypeObject* T=&Type);
+
+ ~KX_SoundActuator();
+
+ void setSoundObject(class SND_SoundObject* soundobject);
+ bool Update(double curtime,double deltatime);
+
+ CValue* GetReplica();
+
+ /* -------------------------------------------------------------------- */
+ /* Python interface --------------------------------------------------- */
+ /* -------------------------------------------------------------------- */
+
+ PyObject* _getattr(char *attr);
+
+ KX_PYMETHOD(KX_SoundActuator,SetFilename);
+ KX_PYMETHOD(KX_SoundActuator,GetFilename);
+ KX_PYMETHOD(KX_SoundActuator,StartSound);
+ KX_PYMETHOD(KX_SoundActuator,PauseSound);
+ KX_PYMETHOD(KX_SoundActuator,StopSound);
+ KX_PYMETHOD(KX_SoundActuator,SetGain);
+ KX_PYMETHOD(KX_SoundActuator,GetGain);
+ KX_PYMETHOD(KX_SoundActuator,SetPitch);
+ KX_PYMETHOD(KX_SoundActuator,GetPitch);
+ KX_PYMETHOD(KX_SoundActuator,SetRollOffFactor);
+ KX_PYMETHOD(KX_SoundActuator,GetRollOffFactor);
+ KX_PYMETHOD(KX_SoundActuator,SetLooping);
+ KX_PYMETHOD(KX_SoundActuator,GetLooping);
+ KX_PYMETHOD(KX_SoundActuator,SetPosition);
+ KX_PYMETHOD(KX_SoundActuator,SetVelocity);
+ KX_PYMETHOD(KX_SoundActuator,SetOrientation);
+};
+#endif //__KX_SOUNDACTUATOR
+
diff --git a/source/gameengine/Ketsji/KX_SumoPhysicsController.cpp b/source/gameengine/Ketsji/KX_SumoPhysicsController.cpp
new file mode 100644
index 00000000000..8b5b9a5d10b
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_SumoPhysicsController.cpp
@@ -0,0 +1,204 @@
+#pragma warning (disable : 4786)
+
+#include "KX_SumoPhysicsController.h"
+#include "SG_Spatial.h"
+#include "SM_Scene.h"
+#include "KX_GameObject.h"
+#include "KX_MotionState.h"
+
+
+
+void KX_SumoPhysicsController::applyImpulse(const MT_Point3& attach, const MT_Vector3& impulse)
+{
+ SumoPhysicsController::applyImpulse(attach[0],attach[1],attach[2],impulse[0],impulse[1],impulse[2]);
+}
+void KX_SumoPhysicsController::RelativeTranslate(const MT_Vector3& dloc,bool local)
+{
+ SumoPhysicsController::RelativeTranslate(dloc[0],dloc[1],dloc[2],local);
+
+}
+void KX_SumoPhysicsController::RelativeRotate(const MT_Matrix3x3& drot,bool local)
+{
+ double oldmat[12];
+ drot.getValue(oldmat);
+ float newmat[9];
+ float *m = &newmat[0];
+ double *orgm = &oldmat[0];
+
+ *m++ = *orgm++;*m++ = *orgm++;*m++ = *orgm++;orgm++;
+ *m++ = *orgm++;*m++ = *orgm++;*m++ = *orgm++;orgm++;
+ *m++ = *orgm++;*m++ = *orgm++;*m++ = *orgm++;orgm++;
+
+ SumoPhysicsController::RelativeRotate(newmat,local);
+}
+
+void KX_SumoPhysicsController::SetLinearVelocity(const MT_Vector3& lin_vel,bool local)
+{
+ SumoPhysicsController::SetLinearVelocity(lin_vel[0],lin_vel[1],lin_vel[2],local);
+
+}
+
+void KX_SumoPhysicsController::SetAngularVelocity(const MT_Vector3& ang_vel,bool local)
+{
+ SumoPhysicsController::SetAngularVelocity(ang_vel[0],ang_vel[1],ang_vel[2],local);
+}
+
+MT_Vector3 KX_SumoPhysicsController::GetVelocity(const MT_Point3& pos)
+{
+
+ float linvel[3];
+ SumoPhysicsController::GetVelocity(pos[0],pos[1],pos[2],linvel[0],linvel[1],linvel[2]);
+
+ return MT_Vector3 (linvel);
+}
+
+MT_Vector3 KX_SumoPhysicsController::GetLinearVelocity()
+{
+ return GetVelocity(MT_Point3(0,0,0));
+
+}
+void KX_SumoPhysicsController::ApplyTorque(const MT_Vector3& torque,bool local)
+{
+ SumoPhysicsController::ApplyTorque(torque[0],torque[1],torque[2],local);
+
+}
+
+void KX_SumoPhysicsController::ApplyForce(const MT_Vector3& force,bool local)
+{
+ SumoPhysicsController::ApplyForce(force[0],force[1],force[2],local);
+}
+
+bool KX_SumoPhysicsController::Update(double time)
+{
+ return SynchronizeMotionStates(time);
+
+}
+
+void KX_SumoPhysicsController::SetSimulatedTime(double time)
+{
+
+}
+
+void KX_SumoPhysicsController::SetSumoTransform(bool nondynaonly)
+{
+ SumoPhysicsController::setSumoTransform(nondynaonly);
+
+}
+
+void KX_SumoPhysicsController::SuspendDynamics()
+{
+ SumoPhysicsController::SuspendDynamics();
+}
+
+void KX_SumoPhysicsController::RestoreDynamics()
+{
+ SumoPhysicsController::RestoreDynamics();
+}
+
+SG_Controller* KX_SumoPhysicsController::GetReplica(SG_Node* destnode)
+{
+
+ PHY_IMotionState* motionstate = new KX_MotionState(destnode);
+
+ KX_SumoPhysicsController* physicsreplica = new KX_SumoPhysicsController(*this);
+
+ //parentcontroller is here be able to avoid collisions between parent/child
+
+ PHY_IPhysicsController* parentctrl = NULL;
+
+ if (destnode != destnode->GetRootSGParent())
+ {
+ KX_GameObject* clientgameobj = (KX_GameObject*) destnode->GetRootSGParent()->GetSGClientObject();
+ if (clientgameobj)
+ {
+ parentctrl = (KX_SumoPhysicsController*)clientgameobj->GetPhysicsController();
+ } else
+ {
+ // it could be a false node, try the children
+ NodeList::const_iterator childit;
+ for (
+ childit = destnode->GetSGChildren().begin();
+ childit!= destnode->GetSGChildren().end();
+ ++childit
+ ) {
+ KX_GameObject* clientgameobj = static_cast<KX_GameObject*>( (*childit)->GetSGClientObject());
+ if (clientgameobj)
+ {
+ parentctrl = (KX_SumoPhysicsController*)clientgameobj->GetPhysicsController();
+ }
+ }
+ }
+ }
+
+ physicsreplica->PostProcessReplica(motionstate,parentctrl);
+
+ return physicsreplica;
+}
+
+
+void KX_SumoPhysicsController::SetObject (SG_IObject* object)
+{
+ SG_Controller::SetObject(object);
+
+ // cheating here...
+ KX_GameObject* gameobj = (KX_GameObject*) object->GetSGClientObject();
+ gameobj->SetPhysicsController(this);
+
+
+}
+
+
+void KX_SumoPhysicsController::setOrientation(const MT_Quaternion& orn)
+{
+ SumoPhysicsController::setOrientation(
+ orn[0],orn[1],orn[2],orn[3]);
+
+}
+void KX_SumoPhysicsController::getOrientation(MT_Quaternion& orn)
+{
+
+ float quat[4];
+
+ SumoPhysicsController::getOrientation(quat[0],quat[1],quat[2],quat[3]);
+
+ orn = MT_Quaternion(quat);
+
+}
+
+void KX_SumoPhysicsController::setPosition(const MT_Point3& pos)
+{
+ SumoPhysicsController::setPosition(pos[0],pos[1],pos[2]);
+
+}
+
+void KX_SumoPhysicsController::setScaling(const MT_Vector3& scaling)
+{
+ SumoPhysicsController::setScaling(scaling[0],scaling[1],scaling[2]);
+
+}
+
+MT_Scalar KX_SumoPhysicsController::GetMass()
+{
+ return SumoPhysicsController::getMass();
+}
+
+MT_Vector3 KX_SumoPhysicsController::getReactionForce()
+{
+ float force[3];
+ SumoPhysicsController::getReactionForce(force[0],force[1],force[2]);
+ return MT_Vector3(force);
+
+}
+
+void KX_SumoPhysicsController::setRigidBody(bool rigid)
+{
+ SumoPhysicsController::setRigidBody(rigid);
+
+}
+
+
+KX_SumoPhysicsController::~KX_SumoPhysicsController()
+{
+
+
+} \ No newline at end of file
diff --git a/source/gameengine/Ketsji/KX_SumoPhysicsController.h b/source/gameengine/Ketsji/KX_SumoPhysicsController.h
new file mode 100644
index 00000000000..b1019b0c19b
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_SumoPhysicsController.h
@@ -0,0 +1,81 @@
+#ifndef __KX_SUMOPHYSICSCONTROLLER_H
+#define __KX_SUMOPHYSICSCONTROLLER_H
+
+#include "PHY_IPhysicsController.h"
+#include "SM_Object.h" // for SM_Callback
+
+/**
+ Physics Controller, a special kind of Scene Graph Transformation Controller.
+ It get's callbacks from Sumo in case a transformation change took place.
+ Each time the scene graph get's updated, the controller get's a chance
+ in the 'Update' method to reflect changed.
+*/
+
+#include "SumoPhysicsController.h"
+#include "KX_IPhysicsController.h"
+
+class KX_SumoPhysicsController : public KX_IPhysicsController,
+ public SumoPhysicsController
+
+{
+
+
+public:
+ KX_SumoPhysicsController(
+ class SM_Scene* sumoScene,
+ DT_SceneHandle solidscene,
+ class SM_Object* sumoObj,
+ class PHY_IMotionState* motionstate
+ ,bool dyna)
+ : SumoPhysicsController(sumoScene,solidscene,sumoObj,motionstate,dyna),
+ KX_IPhysicsController(dyna,NULL)
+ {
+ };
+ virtual ~KX_SumoPhysicsController();
+
+ void applyImpulse(const MT_Point3& attach, const MT_Vector3& impulse);
+ virtual void SetObject (SG_IObject* object);
+
+
+ void RelativeTranslate(const MT_Vector3& dloc,bool local);
+ void RelativeRotate(const MT_Matrix3x3& drot,bool local);
+ void ApplyTorque(const MT_Vector3& torque,bool local);
+ void ApplyForce(const MT_Vector3& force,bool local);
+ MT_Vector3 GetLinearVelocity();
+ MT_Vector3 GetVelocity(const MT_Point3& pos);
+ void SetAngularVelocity(const MT_Vector3& ang_vel,bool local);
+ void SetLinearVelocity(const MT_Vector3& lin_vel,bool local);
+
+ void SuspendDynamics();
+ void RestoreDynamics();
+ virtual void getOrientation(MT_Quaternion& orn);
+ virtual void setOrientation(const MT_Quaternion& orn);
+
+ virtual void setPosition(const MT_Point3& pos);
+ virtual void setScaling(const MT_Vector3& scaling);
+ virtual MT_Scalar GetMass();
+ virtual MT_Vector3 getReactionForce();
+ virtual void setRigidBody(bool rigid);
+
+
+ virtual SG_Controller* GetReplica(class SG_Node* destnode);
+
+
+ void SetSumoTransform(bool nondynaonly);
+ // todo: remove next line !
+ virtual void SetSimulatedTime(double time);
+
+ // call from scene graph to update
+ virtual bool Update(double time);
+
+ void
+ SetOption(
+ int option,
+ int value
+ ){
+ // intentionally empty
+ };
+
+
+};
+#endif //__KX_SUMOPHYSICSCONTROLLER_H
diff --git a/source/gameengine/Ketsji/KX_TimeCategoryLogger.cpp b/source/gameengine/Ketsji/KX_TimeCategoryLogger.cpp
new file mode 100644
index 00000000000..53a47abd77e
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_TimeCategoryLogger.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 *****
+ */
+
+#include "KX_TimeCategoryLogger.h"
+
+
+KX_TimeCategoryLogger::KX_TimeCategoryLogger(unsigned int maxNumMeasurements)
+: m_maxNumMeasurements(maxNumMeasurements)
+{
+}
+
+
+KX_TimeCategoryLogger::~KX_TimeCategoryLogger(void)
+{
+ DisposeLoggers();
+}
+
+
+void KX_TimeCategoryLogger::SetMaxNumMeasurements(unsigned int maxNumMeasurements)
+{
+ KX_TimeLoggerMap::iterator it;
+ for (it = m_loggers.begin(); it != m_loggers.end(); it++) {
+ it->second->SetMaxNumMeasurements(maxNumMeasurements);
+ }
+ m_maxNumMeasurements = maxNumMeasurements;
+}
+
+
+unsigned int KX_TimeCategoryLogger::GetMaxNumMeasurements(void) const
+{
+ return m_maxNumMeasurements;
+}
+
+
+void KX_TimeCategoryLogger::AddCategory(TimeCategory tc)
+{
+ // Only add if not already present
+ if (m_loggers.find(tc) == m_loggers.end()) {
+ KX_TimeLogger* logger = new KX_TimeLogger(m_maxNumMeasurements);
+ //assert(logger);
+ m_loggers.insert(KX_TimeLoggerMap::value_type(tc, logger));
+ }
+}
+
+
+void KX_TimeCategoryLogger::StartLog(TimeCategory tc, double now, bool endOtherCategories)
+{
+ if (endOtherCategories) {
+ KX_TimeLoggerMap::iterator it;
+ for (it = m_loggers.begin(); it != m_loggers.end(); it++) {
+ if (it->first != tc) {
+ it->second->EndLog(now);
+ }
+ }
+ }
+ //assert(m_loggers[tc] != m_loggers.end());
+ m_loggers[tc]->StartLog(now);
+}
+
+
+void KX_TimeCategoryLogger::EndLog(TimeCategory tc, double now)
+{
+ //assert(m_loggers[tc] != m_loggers.end());
+ m_loggers[tc]->EndLog(now);
+}
+
+
+void KX_TimeCategoryLogger::EndLog(double now)
+{
+ KX_TimeLoggerMap::iterator it;
+ for (it = m_loggers.begin(); it != m_loggers.end(); it++) {
+ it->second->EndLog(now);
+ }
+}
+
+
+void KX_TimeCategoryLogger::NextMeasurement(double now)
+{
+ KX_TimeLoggerMap::iterator it;
+ for (it = m_loggers.begin(); it != m_loggers.end(); it++) {
+ it->second->NextMeasurement(now);
+ }
+}
+
+
+double KX_TimeCategoryLogger::GetAverage(TimeCategory tc)
+{
+ //assert(m_loggers[tc] != m_loggers.end());
+ return m_loggers[tc]->GetAverage();
+}
+
+
+double KX_TimeCategoryLogger::GetAverage(void)
+{
+ double time = 0.;
+
+ KX_TimeLoggerMap::iterator it;
+ for (it = m_loggers.begin(); it != m_loggers.end(); it++) {
+ time += it->second->GetAverage();
+ }
+
+ return time;
+}
+
+
+void KX_TimeCategoryLogger::DisposeLoggers(void)
+{
+ KX_TimeLoggerMap::iterator it;
+ for (it = m_loggers.begin(); it != m_loggers.end(); it++) {
+ delete it->second;
+ }
+}
+
diff --git a/source/gameengine/Ketsji/KX_TimeCategoryLogger.h b/source/gameengine/Ketsji/KX_TimeCategoryLogger.h
new file mode 100644
index 00000000000..ce4c7f37c0f
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_TimeCategoryLogger.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 *****
+ */
+
+#ifndef __KX_TIME_CATEGORY_LOGGER_H
+#define __KX_TIME_CATEGORY_LOGGER_H
+
+#ifdef WIN32
+#pragma warning (disable:4786) // suppress stl-MSVC debug info warning
+#endif
+
+#include <map>
+
+#include "KX_TimeLogger.h"
+
+/**
+ * Stores and manages time measurements by category.
+ * Categories can be added dynamically.
+ * Average measurements can be established for each separate category
+ * or for all categories together.
+ */
+class KX_TimeCategoryLogger {
+public:
+ typedef int TimeCategory;
+
+ /**
+ * Constructor.
+ * @param maxNumMesasurements Maximum number of measurements stored (> 1).
+ */
+ KX_TimeCategoryLogger(unsigned int maxNumMeasurements = 10);
+
+ /**
+ * Destructor.
+ */
+ virtual ~KX_TimeCategoryLogger(void);
+
+ /**
+ * Changes the maximum number of measurements that can be stored.
+ */
+ virtual void SetMaxNumMeasurements(unsigned int maxNumMeasurements);
+
+ /**
+ * Changes the maximum number of measurements that can be stored.
+ */
+ virtual unsigned int GetMaxNumMeasurements(void) const;
+
+ /**
+ * Adds a category.
+ * @param category The new category.
+ */
+ virtual void AddCategory(TimeCategory tc);
+
+ /**
+ * Starts logging in current measurement for the given category.
+ * @param tc The category to log to.
+ * @param now The current time.
+ * @param endOtherCategories Whether to stop logging to other categories.
+ */
+ virtual void StartLog(TimeCategory tc, double now, bool endOtherCategories = true);
+
+ /**
+ * End logging in current measurement for the given category.
+ * @param tc The category to log to.
+ * @param now The current time.
+ */
+ virtual void EndLog(TimeCategory tc, double now);
+
+ /**
+ * End logging in current measurement for all categories.
+ * @param now The current time.
+ */
+ virtual void EndLog(double now);
+
+ /**
+ * Logs time in next measurement.
+ * @param now The current time.
+ */
+ virtual void NextMeasurement(double now);
+
+ /**
+ * Returns average of all but the current measurement time.
+ * @return The average of all but the current measurement.
+ */
+ virtual double GetAverage(TimeCategory tc);
+
+ /**
+ * Returns average for grand total.
+ */
+ virtual double GetAverage(void);
+
+protected:
+ /**
+ * Disposes loggers.
+ */
+ virtual void DisposeLoggers(void);
+
+ /** Storage for the loggers. */
+ typedef std::map<TimeCategory, KX_TimeLogger*> KX_TimeLoggerMap;
+ KX_TimeLoggerMap m_loggers;
+ /** Maximum number of measurements. */
+ unsigned int m_maxNumMeasurements;
+
+};
+
+#endif // __KX_TIME_CATEGORY_LOGGER_H
diff --git a/source/gameengine/Ketsji/KX_TimeLogger.cpp b/source/gameengine/Ketsji/KX_TimeLogger.cpp
new file mode 100644
index 00000000000..e2114e8d8d7
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_TimeLogger.cpp
@@ -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 *****
+ */
+
+#include "KX_TimeLogger.h"
+
+
+
+KX_TimeLogger::KX_TimeLogger(unsigned int maxNumMeasurements)
+: m_maxNumMeasurements(maxNumMeasurements), m_logging(false), m_logStart(0)
+{
+}
+
+
+KX_TimeLogger::~KX_TimeLogger(void)
+{
+}
+
+
+void KX_TimeLogger::SetMaxNumMeasurements(unsigned int maxNumMeasurements)
+{
+ if ((m_maxNumMeasurements != maxNumMeasurements) && maxNumMeasurements) {
+ // Actual removing is done in NextMeasurement()
+ m_maxNumMeasurements = maxNumMeasurements;
+ }
+}
+
+
+unsigned int KX_TimeLogger::GetMaxNumMeasurements(void) const
+{
+ return m_maxNumMeasurements;
+}
+
+
+void KX_TimeLogger::StartLog(double now)
+{
+ if (!m_logging) {
+ m_logging = true;
+ m_logStart = now;
+ }
+}
+
+
+void KX_TimeLogger::EndLog(double now)
+{
+ if (m_logging) {
+ m_logging = false;
+ double time = now - m_logStart;
+ if (m_measurements.size() > 0) {
+ m_measurements[0] += time;
+ }
+ }
+}
+
+
+void KX_TimeLogger::NextMeasurement(double now)
+{
+ // End logging to current measurement
+ EndLog(now);
+
+ // Add a new measurement at the front
+ double m = 0.;
+ m_measurements.push_front(m);
+
+ // Remove measurement if we grow beyond the maximum size
+ if ((m_measurements.size()) > m_maxNumMeasurements) {
+ while (m_measurements.size() > m_maxNumMeasurements) {
+ m_measurements.pop_back();
+ }
+ }
+}
+
+
+
+double KX_TimeLogger::GetAverage(void) const
+{
+ double avg = 0.;
+
+ unsigned int numMeasurements = m_measurements.size();
+ if (numMeasurements > 1) {
+ for (int i = 1; i < numMeasurements; i++) {
+ avg += m_measurements[i];
+ }
+ avg /= (float)numMeasurements - 1;
+ }
+
+ return avg;
+}
+
diff --git a/source/gameengine/Ketsji/KX_TimeLogger.h b/source/gameengine/Ketsji/KX_TimeLogger.h
new file mode 100644
index 00000000000..a802ed1a93a
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_TimeLogger.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 *****
+ */
+
+#ifndef __KX_TIME_LOGGER_H
+#define __KX_TIME_LOGGER_H
+
+#ifdef WIN32
+#pragma warning (disable:4786) // suppress stl-MSVC debug info warning
+#endif
+
+
+#include <deque>
+
+/**
+ * Stores and manages time measurements.
+ */
+class KX_TimeLogger {
+public:
+ /**
+ * Constructor.
+ * @param maxNumMesasurements Maximum number of measurements stored (>1).
+ */
+ KX_TimeLogger(unsigned int maxNumMeasurements = 10);
+
+ /**
+ * Destructor.
+ */
+ virtual ~KX_TimeLogger(void);
+
+ /**
+ * Changes the maximum number of measurements that can be stored.
+ */
+ virtual void SetMaxNumMeasurements(unsigned int maxNumMeasurements);
+
+ /**
+ * Changes the maximum number of measurements that can be stored.
+ */
+ virtual unsigned int GetMaxNumMeasurements(void) const;
+
+ /**
+ * Starts logging in current measurement.
+ * @param now The current time.
+ */
+ virtual void StartLog(double now);
+
+ /**
+ * End logging in current measurement.
+ * @param now The current time.
+ */
+ virtual void EndLog(double now);
+
+ /**
+ * Logs time in next measurement.
+ * @param now The current time.
+ */
+ virtual void NextMeasurement(double now);
+
+ /**
+ * Returns average of all but the current measurement.
+ * @return The average of all but the current measurement.
+ */
+ virtual double GetAverage(void) const;
+
+protected:
+ /** Storage for the measurements. */
+ std::deque<double> m_measurements;
+
+ /** Maximum number of measurements. */
+ unsigned int m_maxNumMeasurements;
+
+ /** Time at start of logging. */
+ double m_logStart;
+
+ /** State of logging. */
+ bool m_logging;
+};
+
+#endif // __KX_TIME_LOGGER_H
diff --git a/source/gameengine/Ketsji/KX_TouchEventManager.cpp b/source/gameengine/Ketsji/KX_TouchEventManager.cpp
new file mode 100644
index 00000000000..d9848398900
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_TouchEventManager.cpp
@@ -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 *****
+ */
+
+#include "KX_TouchEventManager.h"
+
+#include "SCA_ISensor.h"
+#include "KX_TouchSensor.h"
+#include "KX_GameObject.h"
+
+#ifdef PHYSICS_NOT_YET
+
+KX_TouchEventManager::KX_TouchEventManager(class SCA_LogicManager* logicmgr,
+ DT_RespTableHandle resphandle,
+ DT_SceneHandle scenehandle)
+ : SCA_EventManager(TOUCH_EVENTMGR),
+ m_resphandle(resphandle),
+ m_scenehandle(scenehandle),
+ m_logicmgr(logicmgr) {}
+
+void KX_TouchEventManager::RegisterSensor(SCA_ISensor* sensor)
+{
+
+
+ KX_TouchSensor* touchsensor = static_cast<KX_TouchSensor*>(sensor);
+ m_sensors.push_back(touchsensor);
+
+ touchsensor->RegisterSumo();//this,m_resphandle);
+
+ //KX_GameObject* gameobj = ((KX_GameObject*)sensor->GetParent());
+// SM_Object* smobj = touchsensor->GetSumoObject();//gameobj->GetSumoObject();
+// if (smobj)
+// {
+// smobj->calcXform();
+// DT_AddObject(m_scenehandle,
+// smobj->getObjectHandle());
+// }
+}
+
+
+
+void KX_TouchEventManager::EndFrame()
+{
+ vector<SCA_ISensor*>::iterator it;
+ for ( it = m_sensors.begin();
+ !(it==m_sensors.end());it++)
+ {
+ ((KX_TouchSensor*)*it)->EndFrame();
+
+ }
+}
+
+
+
+void KX_TouchEventManager::NextFrame(double curtime,double deltatime)
+{
+ if (m_sensors.size() > 0)
+ {
+ vector<SCA_ISensor*>::iterator it;
+
+ for (it = m_sensors.begin();!(it==m_sensors.end());it++)
+ ((KX_TouchSensor*)*it)->SynchronizeTransform();
+
+ if (DT_Test(m_scenehandle,m_resphandle))
+ int i = 0;
+
+ for (it = m_sensors.begin();!(it==m_sensors.end());it++)
+ (*it)->Activate(m_logicmgr,NULL);
+ }
+}
+
+
+
+void KX_TouchEventManager::RemoveSensor(class SCA_ISensor* sensor)
+{
+ std::vector<SCA_ISensor*>::iterator i =
+ std::find(m_sensors.begin(), m_sensors.end(), sensor);
+ if (!(i == m_sensors.end()))
+ {
+ //std::swap(*i, m_sensors.back());
+ //m_sensors.pop_back();
+ //SM_Object* smobj = ((KX_TouchSensor*)*i)->GetSumoObject();
+ //DT_RemoveObject(m_scenehandle,
+ // smobj->getObjectHandle());
+ }
+ // remove the sensor forever :)
+ SCA_EventManager::RemoveSensor(sensor);
+}
+
+#endif
diff --git a/source/gameengine/Ketsji/KX_TouchEventManager.h b/source/gameengine/Ketsji/KX_TouchEventManager.h
new file mode 100644
index 00000000000..4575814986f
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_TouchEventManager.h
@@ -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 *****
+ */
+#ifndef __KX_TOUCHEVENTMANAGER
+#define __KX_TOUCHEVENTMANAGER
+
+#include "SCA_EventManager.h"
+#include "KX_TouchSensor.h"
+#include "KX_GameObject.h"
+
+#include <vector>
+using namespace std;
+
+
+class KX_TouchEventManager : public SCA_EventManager
+{
+ class SCA_LogicManager* m_logicmgr;
+
+public:
+ KX_TouchEventManager(class SCA_LogicManager* logicmgr);
+ virtual void NextFrame(double curtime,double deltatime);
+ virtual void EndFrame();
+ virtual void RemoveSensor(class SCA_ISensor* sensor);
+ virtual void RegisterSensor(SCA_ISensor* sensor);
+ SCA_LogicManager* GetLogicManager() { return m_logicmgr;}
+};
+
+#endif //__KX_TOUCHEVENTMANAGER
+
+
+
+
+
+
+
+
+
+
+
diff --git a/source/gameengine/Ketsji/KX_TouchSensor.cpp b/source/gameengine/Ketsji/KX_TouchSensor.cpp
new file mode 100644
index 00000000000..daf344999fc
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_TouchSensor.cpp
@@ -0,0 +1,393 @@
+/**
+ * Senses touch and collision events
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "KX_TouchSensor.h"
+#include "SCA_EventManager.h"
+#include "SCA_LogicManager.h"
+#include "KX_GameObject.h"
+#include "KX_TouchEventManager.h"
+#include <iostream>
+
+#ifdef PHYSICS_NOT_YET
+
+/* ------------------------------------------------------------------------- */
+/* Native functions */
+/* ------------------------------------------------------------------------- */
+
+void KX_TouchSensor::SynchronizeTransform()
+{
+
+ if (m_sumoObj)
+ {
+ m_sumoObj->setPosition(((KX_GameObject*)GetParent())->NodeGetWorldPosition());
+ m_sumoObj->setOrientation(
+ ((KX_GameObject*)GetParent())->NodeGetWorldOrientation().getRotation()
+ );
+ m_sumoObj->calcXform();
+ }
+
+}
+
+
+void KX_TouchSensor::EndFrame() {
+ m_colliders->ReleaseAndRemoveAll();
+ m_bTriggered = false;
+}
+
+bool KX_TouchSensor::Evaluate(CValue* event)
+{
+ bool result = false;
+
+ if (m_bTriggered != m_bLastTriggered)
+ {
+ m_bLastTriggered = m_bTriggered;
+ if (!m_bTriggered)
+ m_hitObject = NULL;
+ result = true;
+ }
+
+ return result;
+}
+
+KX_TouchSensor::KX_TouchSensor(SCA_EventManager* eventmgr,KX_GameObject* gameobj,SM_Object* sumoObj,bool bFindMaterial,const STR_String& touchedpropname,PyTypeObject* T)
+:SCA_ISensor(gameobj,eventmgr,T),
+m_touchedpropname(touchedpropname),
+m_bFindMaterial(bFindMaterial),
+m_sumoObj(sumoObj),
+m_bCollision(false),
+m_bTriggered(false),
+m_bLastTriggered(false)
+{
+ m_eventmgr = eventmgr;
+ KX_TouchEventManager* touchmgr = (KX_TouchEventManager*) eventmgr;
+
+ m_resptable = touchmgr->GetResponseTable();
+
+ m_solidHandle = m_sumoObj->getObjectHandle();
+
+ m_hitObject = NULL;
+ m_colliders = new CListValue();
+}
+
+
+KX_TouchSensor::~KX_TouchSensor()
+{
+ DT_ClearObjectResponse(m_resptable,m_solidHandle);
+ m_colliders->Release();
+}
+
+void KX_TouchSensor::ReParent(SCA_IObject* parent)
+{
+
+ m_sumoObj = ((KX_GameObject*)parent)->GetSumoObject();
+ m_solidHandle = m_sumoObj->getObjectHandle();
+
+ m_client_info.m_clientobject = NULL;//parent;
+ m_client_info.m_auxilary_info = NULL;
+ SCA_ISensor::ReParent(parent);
+}
+
+
+void KX_TouchSensor::RegisterSumo()
+{
+
+ if (m_sumoObj)
+ {
+ // collision
+ DT_SetObjectResponse(
+ m_resptable,
+ m_solidHandle,
+ collisionResponse,
+ DT_SIMPLE_RESPONSE,
+ this);
+
+ }
+
+}
+
+void KX_TouchSensor::HandleCollision(void* obj1,void* obj2,const DT_CollData * coll_data)
+{
+ KX_TouchEventManager* toucheventmgr = (KX_TouchEventManager*)m_eventmgr;
+ KX_GameObject* parent = (KX_GameObject*)GetParent();
+
+ // need the mapping from SM_Objects to gameobjects now
+
+ SM_ClientObjectInfo* client_info =(SM_ClientObjectInfo*) (obj1 == m_sumoObj?
+ ((SM_Object*)obj2)->getClientObject() :
+ ((SM_Object*)obj1)->getClientObject());
+
+
+ KX_GameObject* gameobj = ( client_info ?
+ (KX_GameObject*)client_info->m_clientobject :
+ NULL);
+
+ if (gameobj && (gameobj != parent))
+ {
+ if (!m_colliders->SearchValue(gameobj))
+ m_colliders->Add(gameobj->AddRef());
+
+ bool found = m_touchedpropname.IsEmpty();
+ if (!found)
+ {
+ if (m_bFindMaterial)
+ {
+ if (client_info->m_auxilary_info)
+ {
+ found = (m_touchedpropname == ((char*)client_info->m_auxilary_info));
+ }
+
+ if (found)
+ {
+ int i=0;
+ }
+
+ } else
+ {
+ found = (gameobj->GetProperty(m_touchedpropname) != NULL);
+ }
+ }
+ if (found)
+ {
+ m_bTriggered = true;
+ m_hitObject = gameobj;
+ }
+
+ }
+
+}
+
+/* ------------------------------------------------------------------------- */
+/* Python functions */
+/* ------------------------------------------------------------------------- */
+/* Integration hooks ------------------------------------------------------- */
+PyTypeObject KX_TouchSensor::Type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0,
+ "KX_TouchSensor",
+ sizeof(KX_TouchSensor),
+ 0,
+ PyDestructor,
+ 0,
+ __getattr,
+ __setattr,
+ 0, //&MyPyCompare,
+ __repr,
+ 0, //&cvalue_as_number,
+ 0,
+ 0,
+ 0,
+ 0
+};
+
+PyParentObject KX_TouchSensor::Parents[] = {
+ &KX_TouchSensor::Type,
+ &SCA_ISensor::Type,
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
+};
+
+PyMethodDef KX_TouchSensor::Methods[] = {
+ {"setProperty",
+ (PyCFunction) KX_TouchSensor::sPySetProperty, METH_VARARGS, SetProperty_doc},
+ {"getProperty",
+ (PyCFunction) KX_TouchSensor::sPyGetProperty, METH_VARARGS, GetProperty_doc},
+ {"getHitObject",
+ (PyCFunction) KX_TouchSensor::sPyGetHitObject, METH_VARARGS, GetHitObject_doc},
+ {"getHitObjectList",
+ (PyCFunction) KX_TouchSensor::sPyGetHitObjectList, METH_VARARGS, GetHitObjectList_doc},
+ {NULL,NULL} //Sentinel
+};
+
+PyObject* KX_TouchSensor::_getattr(char* attr) {
+ _getattr_up(SCA_ISensor);
+}
+
+/* Python API */
+
+/* 1. setProperty */
+char KX_TouchSensor::SetProperty_doc[] =
+"setProperty(name)\n"
+"\t- name: string\n"
+"\tSet the property or material to collide with. Use\n"
+"\tsetTouchMaterial() to switch between properties and\n"
+"\tmaterials.";
+PyObject* KX_TouchSensor::PySetProperty(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ char *nameArg;
+ if (!PyArg_ParseTuple(args, "s", &nameArg)) {
+ return NULL;
+ }
+
+ CValue* prop = GetParent()->FindIdentifier(nameArg);
+
+ if (!prop->IsError()) {
+ m_touchedpropname = nameArg;
+ prop->Release();
+ } else {
+ ; /* not found ... */
+ }
+
+ Py_Return;
+}
+/* 2. getProperty */
+char KX_TouchSensor::GetProperty_doc[] =
+"getProperty(name)\n"
+"\tReturns the property or material to collide with. Use\n"
+"\tgetTouchMaterial() to find out whether this sensor\n"
+"\tlooks for properties or materials.";
+PyObject* KX_TouchSensor::PyGetProperty(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ return PyString_FromString(m_touchedpropname);
+}
+
+char KX_TouchSensor::GetHitObject_doc[] =
+"getHitObject()\n"
+;
+PyObject* KX_TouchSensor::PyGetHitObject(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ /* to do: do Py_IncRef if the object is already known in Python */
+ /* otherwise, this leaks memory */
+ if (m_hitObject)
+ {
+ return m_hitObject->AddRef();
+ }
+ Py_Return;
+}
+
+char KX_TouchSensor::GetHitObjectList_doc[] =
+"getHitObjectList()\n"
+"\tReturn a list of the objects this object collided with,\n"
+"\tbut only those matching the property/material condition.\n";
+PyObject* KX_TouchSensor::PyGetHitObjectList(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+
+ /* to do: do Py_IncRef if the object is already known in Python */
+ /* otherwise, this leaks memory */
+
+ if ( m_touchedpropname.IsEmpty() ) {
+ return m_colliders->AddRef();
+ } else {
+ CListValue* newList = new CListValue();
+ int i = 0;
+ while (i < m_colliders->GetCount()) {
+ if (m_bFindMaterial) {
+ /* need to associate the CValues from the list to material
+ * names. The collider list _should_ contains only
+ * KX_GameObjects. I am loathe to cast them, though... The
+ * material name must be retrieved from Sumo. To a Sumo
+ * object, a client-info block is attached. This block
+ * contains the material name.
+ * - this also doesn't work (obviously) for multi-materials...
+ */
+ KX_GameObject* gameob = (KX_GameObject*) m_colliders->GetValue(i);
+ SM_Object* smob = (SM_Object*) gameob->GetSumoObject();
+
+ if (smob) {
+ SM_ClientObjectInfo* cl_inf = (SM_ClientObjectInfo*) smob->getClientObject();
+
+ if (m_touchedpropname == ((char*)cl_inf->m_auxilary_info)) {
+ newList->Add(m_colliders->GetValue(i)->AddRef());
+ }
+ }
+
+ } else {
+ CValue* val = m_colliders->GetValue(i)->FindIdentifier(m_touchedpropname);
+ if (!val->IsError()) {
+ newList->Add(m_colliders->GetValue(i)->AddRef());
+ val->Release();
+ }
+ }
+
+ i++;
+ }
+ return newList->AddRef();
+ }
+
+}
+
+/* 5. getTouchMaterial */
+char KX_TouchSensor::GetTouchMaterial_doc[] =
+"getTouchMaterial()\n"
+"\tReturns KX_TRUE if this sensor looks for a specific material,\n"
+"\tKX_FALSE if it looks for a specific property.\n" ;
+PyObject* KX_TouchSensor::PyGetTouchMaterial(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ int retval = 0;
+
+ if (m_bFindMaterial) {
+ retval = KX_TRUE;
+ } else {
+ retval = KX_FALSE;
+ }
+
+ return PyInt_FromLong(retval);
+}
+
+/* 6. setTouchMaterial */
+char KX_TouchSensor::SetTouchMaterial_doc[] =
+"setTouchMaterial(flag)\n"
+"\t- flag: KX_TRUE or KX_FALSE.\n"
+"\tSet flag to KX_TRUE to switch on positive pulse mode,\n"
+"\tKX_FALSE to switch off positive pulse mode.\n" ;
+PyObject* KX_TouchSensor::PySetTouchMaterial(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ int pulseArg = 0;
+
+ if(!PyArg_ParseTuple(args, "i", &pulseArg)) {
+ return NULL;
+ }
+
+ if (pulseArg == KX_TRUE) {
+ m_bFindMaterial = true;
+ } else if (pulseArg == KX_FALSE){
+ m_bFindMaterial = false;
+ } else {
+ ; /* internal error */
+ }
+
+ Py_Return;
+}
+
+#endif //#ifdef PHYSICS_NOT_YET
+
+/* eof */
diff --git a/source/gameengine/Ketsji/KX_TouchSensor.h b/source/gameengine/Ketsji/KX_TouchSensor.h
new file mode 100644
index 00000000000..123f7041968
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_TouchSensor.h
@@ -0,0 +1,146 @@
+/**
+ * Senses touch and collision events
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 __KX_TOUCHSENSOR
+#define __KX_TOUCHSENSOR
+
+#include "SCA_ISensor.h"
+#include "ListValue.h"
+
+#include "KX_ClientObjectInfo.h"
+
+class KX_TouchSensor : public SCA_ISensor
+{
+protected:
+ Py_Header;
+
+ /**
+ * The sensor should only look for objects with this property.
+ */
+ STR_String m_touchedpropname;
+ bool m_bFindMaterial;
+ class SCA_EventManager* m_eventmgr;
+
+ //class SM_Object* m_sumoObj;
+ //DT_ObjectHandle m_solidHandle;
+ //SM_ClientObjectInfo m_client_info;
+ //DT_RespTableHandle m_resptable;
+
+
+ bool m_bCollision;
+ bool m_bTriggered;
+ bool m_bLastTriggered;
+ SCA_IObject* m_hitObject;
+ class CListValue* m_colliders;
+
+public:
+ KX_TouchSensor(class SCA_EventManager* eventmgr,
+ class KX_GameObject* gameobj,
+ class SM_Object* sumoObj,
+ bool fFindMaterial,
+ const STR_String& touchedpropname,
+ PyTypeObject* T=&Type) ;
+ virtual ~KX_TouchSensor();
+
+ virtual CValue* GetReplica() {
+ KX_TouchSensor* replica = new KX_TouchSensor(*this);
+ replica->m_colliders = new CListValue();
+ replica->m_bCollision = false;
+ replica->m_bTriggered= false;
+ replica->m_hitObject = NULL;
+ replica->m_bLastTriggered = false;
+ // this will copy properties and so on...
+ CValue::AddDataToReplica(replica);
+ return replica;
+ };
+ virtual void SynchronizeTransform();
+ virtual bool Evaluate(CValue* event);
+ virtual void ReParent(SCA_IObject* parent);
+
+/* static void collisionResponse(void *client_data,
+ void *object1,
+ void *object2,
+ const DT_CollData *coll_data) {
+ class KX_TouchSensor* sensor = (class KX_TouchSensor*) client_data;
+ sensor->HandleCollision(object1,object2,coll_data);
+ }
+
+
+
+ void RegisterSumo();
+
+ virtual void HandleCollision(void* obj1,void* obj2,
+ const DT_CollData * coll_data);
+
+
+ // SM_Object* GetSumoObject() { return m_sumoObj; };
+
+ */
+
+ virtual bool IsPositiveTrigger() {
+ bool result = m_bTriggered;
+ if (m_invert) result = !result;
+ return result;
+ }
+
+
+ void EndFrame();
+
+ // todo: put some info for collision maybe
+
+ /* --------------------------------------------------------------------- */
+ /* Python interface ---------------------------------------------------- */
+ /* --------------------------------------------------------------------- */
+
+ virtual PyObject* _getattr(char *attr);
+
+ /* 1. setProperty */
+ KX_PYMETHOD_DOC(KX_TouchSensor,SetProperty);
+ /* 2. getProperty */
+ KX_PYMETHOD_DOC(KX_TouchSensor,GetProperty);
+ /* 3. getHitObject */
+ KX_PYMETHOD_DOC(KX_TouchSensor,GetHitObject);
+ /* 4. getHitObject */
+ KX_PYMETHOD_DOC(KX_TouchSensor,GetHitObjectList);
+ /* 5. getTouchMaterial */
+ KX_PYMETHOD_DOC(KX_TouchSensor,GetTouchMaterial);
+ /* 6. setTouchMaterial */
+ KX_PYMETHOD_DOC(KX_TouchSensor,SetTouchMaterial);
+
+};
+
+#endif //__KX_TOUCHSENSOR
+
+
+
diff --git a/source/gameengine/Ketsji/KX_TrackToActuator.cpp b/source/gameengine/Ketsji/KX_TrackToActuator.cpp
new file mode 100644
index 00000000000..647ffb447aa
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_TrackToActuator.cpp
@@ -0,0 +1,487 @@
+//
+// Replace the mesh for this actuator's parent
+//
+// $Id$
+//
+// ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version. The Blender
+// Foundation also sells licenses for use in proprietary software under
+// the Blender License. See http://www.blender.org/BL/ for information
+// about this.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+// All rights reserved.
+//
+// The Original Code is: all of this file.
+//
+// Contributor(s): none yet.
+//
+// ***** END GPL/BL DUAL LICENSE BLOCK *****
+
+// todo: not all trackflags / upflags are implemented/tested !
+// m_trackflag is used to determine the forward tracking direction
+// m_upflag for the up direction
+// normal situation is +y for forward, +z for up
+
+#include "MT_Scalar.h"
+#include "SCA_IActuator.h"
+#include "KX_TrackToActuator.h"
+#include "SCA_IScene.h"
+#include "SCA_LogicManager.h"
+#include <math.h>
+#include <iostream>
+#include "KX_GameObject.h"
+
+
+/* ------------------------------------------------------------------------- */
+/* Native functions */
+/* ------------------------------------------------------------------------- */
+
+
+
+KX_TrackToActuator::KX_TrackToActuator(SCA_IObject *gameobj,
+ SCA_IObject *ob,
+ int time,
+ bool allow3D,
+ int trackflag,
+ int upflag,
+ PyTypeObject* T)
+ :
+ SCA_IActuator(gameobj, T)
+{
+ m_time = time;
+ m_allow3D = allow3D;
+ m_object = ob;
+ m_trackflag = trackflag;
+ m_upflag = upflag;
+} /* End of constructor */
+
+
+
+/* old function from Blender */
+MT_Matrix3x3 EulToMat3(float *eul)
+{
+ MT_Matrix3x3 mat;
+ float ci, cj, ch, si, sj, sh, cc, cs, sc, ss;
+
+ ci = cos(eul[0]);
+ cj = cos(eul[1]);
+ ch = cos(eul[2]);
+ si = sin(eul[0]);
+ sj = sin(eul[1]);
+ sh = sin(eul[2]);
+ cc = ci*ch;
+ cs = ci*sh;
+ sc = si*ch;
+ ss = si*sh;
+
+ mat[0][0] = cj*ch;
+ mat[1][0] = sj*sc-cs;
+ mat[2][0] = sj*cc+ss;
+ mat[0][1] = cj*sh;
+ mat[1][1] = sj*ss+cc;
+ mat[2][1] = sj*cs-sc;
+ mat[0][2] = -sj;
+ mat[1][2] = cj*si;
+ mat[2][2] = cj*ci;
+
+ return mat;
+}
+
+
+
+/* old function from Blender */
+void Mat3ToEul(MT_Matrix3x3 mat, float *eul)
+{
+ MT_Scalar cy;
+
+ cy = sqrt(mat[0][0]*mat[0][0] + mat[0][1]*mat[0][1]);
+
+ if (cy > 16.0*FLT_EPSILON) {
+ eul[0] = atan2(mat[1][2], mat[2][2]);
+ eul[1] = atan2(-mat[0][2], cy);
+ eul[2] = atan2(mat[0][1], mat[0][0]);
+ } else {
+ eul[0] = atan2(-mat[2][1], mat[1][1]);
+ eul[1] = atan2(-mat[0][2], cy);
+ eul[2] = 0.0;
+ }
+}
+
+
+
+/* old function from Blender */
+void compatible_eulFast(float *eul, float *oldrot)
+{
+ float dx, dy, dz;
+
+ /* verschillen van ong 360 graden corrigeren */
+
+ dx= eul[0] - oldrot[0];
+ dy= eul[1] - oldrot[1];
+ dz= eul[2] - oldrot[2];
+
+ if( fabs(dx) > 5.1) {
+ if(dx > 0.0) eul[0] -= MT_2_PI; else eul[0]+= MT_2_PI;
+ }
+ if( fabs(dy) > 5.1) {
+ if(dy > 0.0) eul[1] -= MT_2_PI; else eul[1]+= MT_2_PI;
+ }
+ if( fabs(dz) > 5.1 ) {
+ if(dz > 0.0) eul[2] -= MT_2_PI; else eul[2]+= MT_2_PI;
+ }
+}
+
+
+
+MT_Matrix3x3 matrix3x3_interpol(MT_Matrix3x3 oldmat, MT_Matrix3x3 mat, int m_time)
+{
+ float eul[3], oldeul[3];
+
+ Mat3ToEul(oldmat, oldeul);
+ Mat3ToEul(mat, eul);
+ compatible_eulFast(eul, oldeul);
+
+ eul[0]= (m_time*oldeul[0] + eul[0])/(1.0+m_time);
+ eul[1]= (m_time*oldeul[1] + eul[1])/(1.0+m_time);
+ eul[2]= (m_time*oldeul[2] + eul[2])/(1.0+m_time);
+
+ return EulToMat3(eul);
+}
+
+
+
+KX_TrackToActuator::~KX_TrackToActuator()
+{
+ // there's nothing to be done here, really....
+} /* end of destructor */
+
+
+
+bool KX_TrackToActuator::Update(double curtime,double deltatime)
+{
+ bool result = false;
+ bool bNegativeEvent = IsNegativeEvent();
+ RemoveAllEvents();
+
+ if (bNegativeEvent)
+ {
+ // do nothing on negative events
+ }
+ else if (m_object)
+ {
+ KX_GameObject* curobj = (KX_GameObject*) GetParent();
+ MT_Vector3 dir = ((KX_GameObject*)m_object)->NodeGetWorldPosition() - curobj->NodeGetWorldPosition();
+ dir.normalize();
+ MT_Vector3 up(0,0,1);
+
+
+#ifdef DSADSA
+ switch (m_upflag)
+ {
+ case 0:
+ {
+ up = MT_Vector3(1.0,0,0);
+ break;
+ }
+ case 1:
+ {
+ up = MT_Vector3(0,1.0,0);
+ break;
+ }
+ case 2:
+ default:
+ {
+ up = MT_Vector3(0,0,1.0);
+ }
+ }
+#endif
+ if (m_allow3D)
+ {
+ up = (up - up.dot(dir) * dir).normalized();
+
+ }
+ else
+ {
+ dir = (dir - up.dot(dir)*up).normalized();
+ }
+
+ MT_Vector3 left;
+ MT_Matrix3x3 mat;
+
+ switch (m_trackflag)
+ {
+ case 0: // TRACK X
+ {
+ // (1.0 , 0.0 , 0.0 ) x direction is forward, z (0.0 , 0.0 , 1.0 ) up
+ left = dir.normalized();
+ dir = (left.cross(up)).normalized();
+ mat.setValue (
+ left[0], dir[0],up[0],
+ left[1], dir[1],up[1],
+ left[2], dir[2],up[2]
+ );
+
+ break;
+ };
+ case 1: // TRACK Y
+ {
+ // (0.0 , 1.0 , 0.0 ) y direction is forward, z (0.0 , 0.0 , 1.0 ) up
+ left = (dir.cross(up)).normalized();
+ mat.setValue (
+ left[0], dir[0],up[0],
+ left[1], dir[1],up[1],
+ left[2], dir[2],up[2]
+ );
+
+ break;
+ }
+
+ case 2: // track Z
+ {
+ left = up.normalized();
+ up = dir.normalized();
+ dir = left;
+ left = (dir.cross(up)).normalized();
+ mat.setValue (
+ left[0], dir[0],up[0],
+ left[1], dir[1],up[1],
+ left[2], dir[2],up[2]
+ );
+ break;
+ }
+
+ case 3: // TRACK -X
+ {
+ // (1.0 , 0.0 , 0.0 ) x direction is forward, z (0.0 , 0.0 , 1.0 ) up
+ left = -dir.normalized();
+ dir = -(left.cross(up)).normalized();
+ mat.setValue (
+ left[0], dir[0],up[0],
+ left[1], dir[1],up[1],
+ left[2], dir[2],up[2]
+ );
+
+ break;
+ };
+ case 4: // TRACK -Y
+ {
+ // (0.0 , -1.0 , 0.0 ) -y direction is forward, z (0.0 , 0.0 , 1.0 ) up
+ left = (-dir.cross(up)).normalized();
+ mat.setValue (
+ left[0], -dir[0],up[0],
+ left[1], -dir[1],up[1],
+ left[2], -dir[2],up[2]
+ );
+ break;
+ }
+ case 5: // track -Z
+ {
+ left = up.normalized();
+ up = -dir.normalized();
+ dir = left;
+ left = (dir.cross(up)).normalized();
+ mat.setValue (
+ left[0], dir[0],up[0],
+ left[1], dir[1],up[1],
+ left[2], dir[2],up[2]
+ );
+
+ break;
+ }
+
+ default:
+ {
+ // (1.0 , 0.0 , 0.0 ) -x direction is forward, z (0.0 , 0.0 , 1.0 ) up
+ left = -dir.normalized();
+ dir = -(left.cross(up)).normalized();
+ mat.setValue (
+ left[0], dir[0],up[0],
+ left[1], dir[1],up[1],
+ left[2], dir[2],up[2]
+ );
+ }
+ }
+
+ MT_Matrix3x3 oldmat;
+ oldmat= curobj->NodeGetWorldOrientation();
+
+ /* erwin should rewrite this! */
+ mat= matrix3x3_interpol(oldmat, mat, m_time);
+
+ curobj->NodeSetLocalOrientation(mat);
+
+ //cout << "\n TrackTo!";
+ result = true;
+ }
+
+ return result;
+}
+
+
+
+/* ------------------------------------------------------------------------- */
+/* Python functions */
+/* ------------------------------------------------------------------------- */
+
+
+
+/* Integration hooks ------------------------------------------------------- */
+PyTypeObject KX_TrackToActuator::Type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0,
+ "KX_TrackToActuator",
+ sizeof(KX_TrackToActuator),
+ 0,
+ PyDestructor,
+ 0,
+ __getattr,
+ __setattr,
+ 0, //&MyPyCompare,
+ __repr,
+ 0, //&cvalue_as_number,
+ 0,
+ 0,
+ 0,
+ 0
+};
+
+
+
+PyParentObject KX_TrackToActuator::Parents[] = {
+ &KX_TrackToActuator::Type,
+ &SCA_IActuator::Type,
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
+};
+
+
+
+PyMethodDef KX_TrackToActuator::Methods[] = {
+ {"setObject", (PyCFunction) KX_TrackToActuator::sPySetObject, METH_VARARGS, SetObject_doc},
+ {"getObject", (PyCFunction) KX_TrackToActuator::sPyGetObject, METH_VARARGS, GetObject_doc},
+ {"setTime", (PyCFunction) KX_TrackToActuator::sPySetTime, METH_VARARGS, SetTime_doc},
+ {"getTime", (PyCFunction) KX_TrackToActuator::sPyGetTime, METH_VARARGS, GetTime_doc},
+ {"setUse3D", (PyCFunction) KX_TrackToActuator::sPySetUse3D, METH_VARARGS, SetUse3D_doc},
+ {"getUse3D", (PyCFunction) KX_TrackToActuator::sPyGetUse3D, METH_VARARGS, GetUse3D_doc},
+ {NULL,NULL} //Sentinel
+};
+
+
+
+PyObject* KX_TrackToActuator::_getattr(char* attr)
+{
+ _getattr_up(SCA_IActuator);
+}
+
+
+
+/* 1. setObject */
+char KX_TrackToActuator::SetObject_doc[] =
+"setObject(object)\n"
+"\t- object: string\n"
+"\tSet the object to track with the parent of this actuator.\n";
+PyObject* KX_TrackToActuator::PySetObject(PyObject* self, PyObject* args, PyObject* kwds) {
+ char* nameArg;
+
+ if (!PyArg_ParseTuple(args, "s", &nameArg)) {
+ return NULL;
+ }
+ CValue* gameobj = SCA_ILogicBrick::m_sCurrentLogicManager->GetGameObjectByName(STR_String(nameArg));
+
+ m_object= (SCA_IObject*)gameobj;
+
+ Py_Return;
+}
+
+
+
+/* 2. getObject */
+char KX_TrackToActuator::GetObject_doc[] =
+"getObject()\n"
+"\tReturns the object to track with the parent of this actuator.\n";
+PyObject* KX_TrackToActuator::PyGetObject(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ return PyString_FromString(m_object->GetName());
+}
+
+
+
+/* 3. setTime */
+char KX_TrackToActuator::SetTime_doc[] =
+"setTime(time)\n"
+"\t- time: integer\n"
+"\tSet the time in frames with which to delay the tracking motion.\n";
+PyObject* KX_TrackToActuator::PySetTime(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ int timeArg;
+
+ if (!PyArg_ParseTuple(args, "i", &timeArg))
+ {
+ return NULL;
+ }
+
+ m_time= timeArg;
+
+ Py_Return;
+}
+
+
+
+/* 4.getTime */
+char KX_TrackToActuator::GetTime_doc[] =
+"getTime()\n"
+"\t- time: integer\n"
+"\tReturn the time in frames with which the tracking motion is delayed.\n";
+PyObject* KX_TrackToActuator::PyGetTime(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ return PyInt_FromLong(m_time);
+}
+
+
+
+/* 5. getUse3D */
+char KX_TrackToActuator::GetUse3D_doc[] =
+"getUse3D()\n"
+"\tReturns 1 if the motion is allowed to extend in the z-direction.\n";
+PyObject* KX_TrackToActuator::PyGetUse3D(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ return PyInt_FromLong(!(m_allow3D == 0));
+}
+
+
+
+/* 6. setUse3D */
+char KX_TrackToActuator::SetUse3D_doc[] =
+"setUse3D(value)\n"
+"\t- value: 0 or 1\n"
+"\tSet to 1 to allow the tracking motion to extend in the z-direction,\n"
+"\tset to 0 to lock the tracking motion to the x-y plane.\n";
+PyObject* KX_TrackToActuator::PySetUse3D(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ int boolArg;
+
+ if (!PyArg_ParseTuple(args, "i", &boolArg)) {
+ return NULL;
+ }
+
+ m_allow3D = !(boolArg == 0);
+
+ Py_Return;
+}
+
+/* eof */
diff --git a/source/gameengine/Ketsji/KX_TrackToActuator.h b/source/gameengine/Ketsji/KX_TrackToActuator.h
new file mode 100644
index 00000000000..cbb9892706e
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_TrackToActuator.h
@@ -0,0 +1,85 @@
+//
+// Add object to the game world on action of this actuator
+//
+// $Id$
+//
+// ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version. The Blender
+// Foundation also sells licenses for use in proprietary software under
+// the Blender License. See http://www.blender.org/BL/ for information
+// about this.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// The Original Code is Copyright (C) 2001-2002 by 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 __KX_TrackToActuator
+#define __KX_TrackToActuator
+
+#include "SCA_IActuator.h"
+#include "SCA_IObject.h"
+
+class KX_TrackToActuator : public SCA_IActuator
+{
+ Py_Header;
+ // Object reference. Actually, we use the object's 'life'
+ SCA_IObject* m_object;
+ // 3d toggle
+ bool m_allow3D;
+ // time field
+ int m_time;
+ int m_trackTime;
+ int m_trackflag;
+ int m_upflag;
+ public:
+ KX_TrackToActuator(SCA_IObject* gameobj, SCA_IObject *ob, int time,
+ bool threedee,int trackflag,int upflag, PyTypeObject* T=&Type);
+ virtual ~KX_TrackToActuator();
+ virtual CValue* GetReplica() {
+ KX_TrackToActuator* replica = new KX_TrackToActuator(*this);
+ replica->ProcessReplica();
+ // this will copy properties and so on...
+ CValue::AddDataToReplica(replica);
+ return replica;
+ };
+
+ virtual bool Update(double curtime,double deltatime);
+
+ /* Python part */
+ virtual PyObject* _getattr(char *attr);
+
+ /* 1. setObject */
+ KX_PYMETHOD_DOC(KX_TrackToActuator,SetObject);
+ /* 2. getObject */
+ KX_PYMETHOD_DOC(KX_TrackToActuator,GetObject);
+ /* 3. setTime */
+ KX_PYMETHOD_DOC(KX_TrackToActuator,SetTime);
+ /* 4. getTime */
+ KX_PYMETHOD_DOC(KX_TrackToActuator,GetTime);
+ /* 5. getUse3D */
+ KX_PYMETHOD_DOC(KX_TrackToActuator,GetUse3D);
+ /* 6. setUse3D */
+ KX_PYMETHOD_DOC(KX_TrackToActuator,SetUse3D);
+
+}; /* end of class KX_TrackToActuator : public KX_EditObjectActuator */
+
+#endif
diff --git a/source/gameengine/Ketsji/KX_VertexProxy.cpp b/source/gameengine/Ketsji/KX_VertexProxy.cpp
new file mode 100644
index 00000000000..2f61ef7a630
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_VertexProxy.cpp
@@ -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 *****
+ */
+
+#include "KX_VertexProxy.h"
+
+#include "RAS_TexVert.h"
+
+
+PyTypeObject KX_VertexProxy::Type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0,
+ "KX_VertexProxy",
+ sizeof(KX_VertexProxy),
+ 0,
+ PyDestructor,
+ 0,
+ __getattr,
+ __setattr,
+ 0, //&MyPyCompare,
+ __repr,
+ 0, //&cvalue_as_number,
+ 0,
+ 0,
+ 0,
+ 0
+};
+
+PyParentObject KX_VertexProxy::Parents[] = {
+ &KX_VertexProxy::Type,
+ &SCA_IObject::Type,
+ &CValue::Type,
+ NULL
+};
+
+PyMethodDef KX_VertexProxy::Methods[] = {
+{"getXYZ", (PyCFunction)KX_VertexProxy::sPyGetXYZ,METH_VARARGS},
+{"setXYZ", (PyCFunction)KX_VertexProxy::sPySetXYZ,METH_VARARGS},
+{"getUV", (PyCFunction)KX_VertexProxy::sPyGetUV,METH_VARARGS},
+{"setUV", (PyCFunction)KX_VertexProxy::sPySetUV,METH_VARARGS},
+{"getRGBA", (PyCFunction)KX_VertexProxy::sPyGetRGBA,METH_VARARGS},
+{"setRGBA", (PyCFunction)KX_VertexProxy::sPySetRGBA,METH_VARARGS},
+{"getNormal", (PyCFunction)KX_VertexProxy::sPyGetNormal,METH_VARARGS},
+{"setNormal", (PyCFunction)KX_VertexProxy::sPySetNormal,METH_VARARGS},
+ {NULL,NULL} //Sentinel
+};
+
+PyObject*
+KX_VertexProxy::_getattr(char* attr)
+{
+ _getattr_up(SCA_IObject);
+}
+
+
+
+KX_VertexProxy::KX_VertexProxy(RAS_TexVert* vertex)
+:m_vertex(vertex)
+{
+
+}
+
+KX_VertexProxy::~KX_VertexProxy()
+{
+
+}
+
+
+
+// stuff for cvalue related things
+CValue* KX_VertexProxy::Calc(VALUE_OPERATOR op, CValue *val) { return NULL;}
+CValue* KX_VertexProxy::CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val) { return NULL;}
+STR_String sVertexName="vertex";
+const STR_String & KX_VertexProxy::GetText() {return sVertexName;};
+float KX_VertexProxy::GetNumber() { return -1;}
+STR_String KX_VertexProxy::GetName() { return sVertexName;}
+void KX_VertexProxy::SetName(STR_String name) { };
+CValue* KX_VertexProxy::GetReplica() { return NULL;}
+void KX_VertexProxy::ReplicaSetName(STR_String name) {};
+
+
+// stuff for python integration
+
+PyObject* KX_VertexProxy::PyGetXYZ(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+
+ MT_Point3 pos = m_vertex->getLocalXYZ();
+
+ PyObject* resultlist = PyList_New(3);
+ int index;
+ for (index=0;index<3;index++)
+ {
+ PyList_SetItem(resultlist,index,PyFloat_FromDouble(pos[index]));
+ }
+
+ return resultlist;
+
+}
+
+PyObject* KX_VertexProxy::PySetXYZ(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+
+ MT_Point3 pos = ConvertPythonVectorArg(args);
+ m_vertex->SetXYZ(pos);
+
+
+ Py_Return;
+}
+
+PyObject* KX_VertexProxy::PyGetNormal(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+
+ const short* shortnormal = m_vertex->getNormal();
+ MT_Vector3 normal(shortnormal[0],shortnormal[1],shortnormal[2]);
+ normal.normalize();
+
+ PyObject* resultlist = PyList_New(3);
+ int index;
+ for (index=0;index<3;index++)
+ {
+ PyList_SetItem(resultlist,index,PyFloat_FromDouble(normal[index]));
+ }
+
+ return resultlist;
+
+}
+
+PyObject* KX_VertexProxy::PySetNormal(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ MT_Point3 normal = ConvertPythonVectorArg(args);
+ m_vertex->SetNormal(normal);
+ Py_Return;
+}
+
+
+PyObject* KX_VertexProxy::PyGetRGBA(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ int rgba = m_vertex->getRGBA();
+ return PyInt_FromLong(rgba);
+}
+
+PyObject* KX_VertexProxy::PySetRGBA(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ int rgba;
+ if (PyArg_ParseTuple(args,"i",&rgba))
+ {
+ m_vertex->SetRGBA(rgba);
+ }
+ Py_Return;
+}
+
+
+PyObject* KX_VertexProxy::PyGetUV(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ MT_Vector2 uv = m_vertex->getUV1();
+ PyObject* resultlist = PyList_New(2);
+ int index;
+ for (index=0;index<2;index++)
+ {
+ PyList_SetItem(resultlist,index,PyFloat_FromDouble(uv[index]));
+ }
+
+ return resultlist;
+
+}
+
+PyObject* KX_VertexProxy::PySetUV(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ MT_Point3 uv = ConvertPythonVectorArg(args);
+ m_vertex->SetUV(MT_Point2(uv[0],uv[1]));
+ Py_Return;
+}
+
+
+
diff --git a/source/gameengine/Ketsji/KX_VertexProxy.h b/source/gameengine/Ketsji/KX_VertexProxy.h
new file mode 100644
index 00000000000..f23a2d6941c
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_VertexProxy.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 *****
+ */
+#ifndef __KX_VERTEXPROXY
+#define __KX_VERTEXPROXY
+
+#include "SCA_IObject.h"
+
+class KX_VertexProxy : public SCA_IObject
+{
+ Py_Header;
+
+ class RAS_TexVert* m_vertex;
+public:
+ KX_VertexProxy(class RAS_TexVert* vertex);
+ virtual ~KX_VertexProxy();
+
+ // stuff for cvalue related things
+ CValue* Calc(VALUE_OPERATOR op, CValue *val) ;
+ CValue* CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val);
+ const STR_String & GetText();
+ float GetNumber();
+ STR_String GetName();
+ void SetName(STR_String name); // Set the name of the value
+ void ReplicaSetName(STR_String name);
+ CValue* GetReplica();
+
+
+// stuff for python integration
+ virtual PyObject* _getattr(char *attr);
+
+ KX_PYMETHOD(KX_VertexProxy,GetXYZ);
+ KX_PYMETHOD(KX_VertexProxy,SetXYZ);
+ KX_PYMETHOD(KX_VertexProxy,GetUV);
+ KX_PYMETHOD(KX_VertexProxy,SetUV);
+ KX_PYMETHOD(KX_VertexProxy,GetRGBA);
+ KX_PYMETHOD(KX_VertexProxy,SetRGBA);
+ KX_PYMETHOD(KX_VertexProxy,GetNormal);
+ KX_PYMETHOD(KX_VertexProxy,SetNormal);
+
+};
+#endif //__KX_VERTEXPROXY
diff --git a/source/gameengine/Ketsji/KX_VisibilityActuator.cpp b/source/gameengine/Ketsji/KX_VisibilityActuator.cpp
new file mode 100644
index 00000000000..c39775f4391
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_VisibilityActuator.cpp
@@ -0,0 +1,161 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * Actuator to toggle visibility/invisibility of objects
+ */
+
+#include "KX_VisibilityActuator.h"
+#include "KX_GameObject.h"
+
+KX_VisibilityActuator::KX_VisibilityActuator(
+ SCA_IObject* gameobj,
+ bool visible,
+ PyTypeObject* T
+ )
+ : SCA_IActuator(gameobj,T),
+ m_visible(visible)
+{
+ // intentionally empty
+}
+
+KX_VisibilityActuator::~KX_VisibilityActuator(
+ void
+ )
+{
+ // intentionally empty
+}
+
+CValue*
+KX_VisibilityActuator::GetReplica(
+ void
+ )
+{
+ KX_VisibilityActuator* replica = new KX_VisibilityActuator(*this);
+ replica->ProcessReplica();
+ // this will copy properties and so on...
+ CValue::AddDataToReplica(replica);
+ return replica;
+}
+
+bool
+KX_VisibilityActuator::Update(
+ double curtime,
+ double deltatime
+ )
+{
+ bool bNegativeEvent = IsNegativeEvent();
+
+ RemoveAllEvents();
+ if (bNegativeEvent) return false;
+
+ KX_GameObject *obj = (KX_GameObject*) GetParent();
+
+ obj->SetVisible(m_visible);
+ obj->MarkVisible();
+
+ return true;
+}
+
+/* ------------------------------------------------------------------------- */
+/* Python functions */
+/* ------------------------------------------------------------------------- */
+
+
+
+/* Integration hooks ------------------------------------------------------- */
+PyTypeObject
+KX_VisibilityActuator::Type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0,
+ "KX_VisibilityActuator",
+ sizeof(KX_VisibilityActuator),
+ 0,
+ PyDestructor,
+ 0,
+ __getattr,
+ __setattr,
+ 0, //&MyPyCompare,
+ __repr,
+ 0, //&cvalue_as_number,
+ 0,
+ 0,
+ 0,
+ 0
+};
+
+PyParentObject
+KX_VisibilityActuator::Parents[] = {
+ &KX_VisibilityActuator::Type,
+ &SCA_IActuator::Type,
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
+};
+
+PyMethodDef
+KX_VisibilityActuator::Methods[] = {
+ {"set", (PyCFunction) KX_VisibilityActuator::sPySetVisible,
+ METH_VARARGS, SetVisible_doc},
+ {NULL,NULL} //Sentinel
+};
+
+PyObject*
+KX_VisibilityActuator::_getattr(
+ char* attr
+ )
+{
+ _getattr_up(SCA_IActuator);
+};
+
+
+
+/* set visibility ---------------------------------------------------------- */
+char
+KX_VisibilityActuator::SetVisible_doc[] =
+"setVisible(visible?)\n"
+"\t - visible? : Make the object visible? (KX_TRUE, KX_FALSE)"
+"\tSet the properties of the actuator.\n";
+PyObject*
+
+KX_VisibilityActuator::PySetVisible(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ int vis;
+
+ if(!PyArg_ParseTuple(args, "i", &vis)) {
+ return NULL;
+ }
+
+ m_visible = PyArgToBool(vis);
+
+ Py_Return;
+}
+
+
diff --git a/source/gameengine/Ketsji/KX_VisibilityActuator.h b/source/gameengine/Ketsji/KX_VisibilityActuator.h
new file mode 100644
index 00000000000..1c079eee967
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_VisibilityActuator.h
@@ -0,0 +1,80 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * Actuator to toggle visibility/invisibility of objects
+ */
+
+#ifndef __KX_VISIBILITYACTUATOR
+#define __KX_VISIBILITYACTUATOR
+
+#include "SCA_IActuator.h"
+
+class KX_VisibilityActuator : public SCA_IActuator
+{
+ Py_Header;
+
+ /** Make visible? */
+ bool m_visible;
+
+ public:
+
+ KX_VisibilityActuator(
+ SCA_IObject* gameobj,
+ bool visible,
+ PyTypeObject* T=&Type
+ );
+
+ virtual
+ ~KX_VisibilityActuator(
+ void
+ );
+
+ virtual CValue*
+ GetReplica(
+ void
+ );
+
+ virtual bool
+ Update(
+ double curtime,
+ double deltatime
+ );
+
+ /* --------------------------------------------------------------------- */
+ /* Python interface ---------------------------------------------------- */
+ /* --------------------------------------------------------------------- */
+
+ virtual PyObject* _getattr(char *attr);
+ //KX_PYMETHOD_DOC
+ KX_PYMETHOD_DOC(KX_VisibilityActuator,SetVisible);
+
+};
+
+#endif
diff --git a/source/gameengine/Ketsji/KX_WorldInfo.cpp b/source/gameengine/Ketsji/KX_WorldInfo.cpp
new file mode 100644
index 00000000000..4c1884572e5
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_WorldInfo.cpp
@@ -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 *****
+ */
+
+#include "KX_WorldInfo.h"
+
+
+KX_WorldInfo::~KX_WorldInfo()
+{
+}
+
diff --git a/source/gameengine/Ketsji/KX_WorldInfo.h b/source/gameengine/Ketsji/KX_WorldInfo.h
new file mode 100644
index 00000000000..7bcf4bb1589
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_WorldInfo.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 *****
+ */
+#ifndef __KX_WORLDINFO_H
+#define __KX_WORLDINFO_H
+
+#include "MT_Scalar.h"
+
+
+class MT_CmMatrix4x4;
+
+
+class KX_WorldInfo
+{
+public:
+ KX_WorldInfo(){}
+ virtual ~KX_WorldInfo();
+
+ virtual bool hasWorld()=0;
+ virtual bool hasMist()=0;
+ virtual float getBackColorRed()=0;
+ virtual float getBackColorGreen()=0;
+ virtual float getBackColorBlue()=0;
+ virtual float getMistStart()=0;
+ virtual float getMistDistance()=0;
+ virtual float getMistColorRed()=0;
+ virtual float getMistColorGreen()=0;
+ virtual float getMistColorBlue()=0;
+
+ virtual void setMistStart(float)=0;
+ virtual void setMistDistance(float)=0;
+ virtual void setMistColorRed(float)=0;
+ virtual void setMistColorGreen(float)=0;
+ virtual void setMistColorBlue(float)=0;
+};
+
+#endif //__KX_WORLDINFO_H
diff --git a/source/gameengine/Ketsji/KX_WorldIpoController.cpp b/source/gameengine/Ketsji/KX_WorldIpoController.cpp
new file mode 100644
index 00000000000..c4907a29a7a
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_WorldIpoController.cpp
@@ -0,0 +1,111 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "KX_WorldIpoController.h"
+
+#include "KX_ScalarInterpolator.h"
+#include "KX_WorldInfo.h"
+
+bool KX_WorldIpoController::Update(double currentTime)
+{
+ if (m_modified)
+ {
+ T_InterpolatorList::iterator i;
+ for (i = m_interpolators.begin(); !(i == m_interpolators.end()); ++i) {
+ (*i)->Execute(m_ipotime);//currentTime);
+ }
+
+ KX_WorldInfo *world;
+
+ if (m_modify_mist_start) {
+ world->setMistStart(m_mist_start);
+ }
+
+ if (m_modify_mist_color) {
+ world->setMistColorRed(m_mist_rgb[0]);
+ world->setMistColorGreen(m_mist_rgb[1]);
+ world->setMistColorBlue(m_mist_rgb[2]);
+ }
+
+ if (m_modify_mist_dist) {
+ world->setMistDistance(m_mist_dist);
+ }
+
+ m_modified=false;
+ }
+ return false;
+}
+
+
+void KX_WorldIpoController::AddInterpolator(KX_IInterpolator* interp)
+{
+ this->m_interpolators.push_back(interp);
+}
+
+
+SG_Controller* KX_WorldIpoController::GetReplica(class SG_Node* destnode)
+{
+ KX_WorldIpoController* iporeplica = new KX_WorldIpoController(*this);
+ // clear object that ipo acts on
+ iporeplica->ClearObject();
+
+ // dirty hack, ask Gino for a better solution in the ipo implementation
+ // hacken en zagen, in what we call datahiding, not written for replication :(
+
+ T_InterpolatorList oldlist = m_interpolators;
+ iporeplica->m_interpolators.clear();
+
+ T_InterpolatorList::iterator i;
+ for (i = oldlist.begin(); !(i == oldlist.end()); ++i) {
+ KX_ScalarInterpolator* copyipo = new KX_ScalarInterpolator(*((KX_ScalarInterpolator*)*i));
+ iporeplica->AddInterpolator(copyipo);
+
+ MT_Scalar* scaal = ((KX_ScalarInterpolator*)*i)->GetTarget();
+ int orgbase = (int)this;
+ int orgloc = (int)scaal;
+ int offset = orgloc-orgbase;
+ int newaddrbase = (int)iporeplica + offset;
+ MT_Scalar* blaptr = (MT_Scalar*) newaddrbase;
+ copyipo->SetNewTarget((MT_Scalar*)blaptr);
+ }
+
+ return iporeplica;
+}
+
+KX_WorldIpoController::~KX_WorldIpoController()
+{
+
+ T_InterpolatorList::iterator i;
+ for (i = m_interpolators.begin(); !(i == m_interpolators.end()); ++i) {
+ delete (*i);
+ }
+
+}
diff --git a/source/gameengine/Ketsji/KX_WorldIpoController.h b/source/gameengine/Ketsji/KX_WorldIpoController.h
new file mode 100644
index 00000000000..36b457adfda
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_WorldIpoController.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 KX_WORLDIPOCONTROLLER_H
+#define KX_WORLDIPOCONTROLLER_H
+
+#include "SG_Controller.h"
+#include "SG_Spatial.h"
+
+#include "KX_IInterpolator.h"
+
+class KX_WorldIpoController : public SG_Controller
+{
+public:
+ MT_Scalar m_mist_rgb[3];
+ MT_Scalar m_mist_start;
+ MT_Scalar m_mist_dist;
+
+private:
+ T_InterpolatorList m_interpolators;
+ unsigned short m_modify_mist_color : 1;
+ unsigned short m_modify_mist_start : 1;
+ unsigned short m_modify_mist_dist : 1;
+ bool m_modified;
+
+ double m_ipotime;
+
+public:
+ KX_WorldIpoController() : m_ipotime(0.0),
+ m_modify_mist_color(false),
+ m_modify_mist_start(false),
+ m_modify_mist_dist(false),
+ m_modified(true)
+ {}
+
+ virtual ~KX_WorldIpoController();
+
+ virtual SG_Controller* GetReplica(class SG_Node* destnode);
+
+ virtual bool Update(double time);
+
+ virtual void SetSimulatedTime(double time) {
+ m_ipotime = time;
+ m_modified = true;
+ }
+
+ void SetModifyMistStart(bool modify) {
+ m_modify_mist_start = modify;
+ }
+
+ void SetModifyMistColor(bool modify) {
+ m_modify_mist_color = modify;
+ }
+
+ void SetModifyMistDist(bool modify) {
+ m_modify_mist_dist = modify;
+ }
+
+ void
+ SetOption(
+ int option,
+ int value
+ ){
+ // intentionally empty
+ };
+
+ void AddInterpolator(KX_IInterpolator* interp);
+};
+
+#endif // KX_LIGHTIPOSGCONTROLLER_H
+
diff --git a/source/gameengine/Ketsji/Makefile b/source/gameengine/Ketsji/Makefile
new file mode 100644
index 00000000000..4e0ee06fe1a
--- /dev/null
+++ b/source/gameengine/Ketsji/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 *****
+#
+#
+
+LIBNAME = ketsji
+DIR = $(OCGDIR)/gameengine/$(LIBNAME)
+
+include nan_compile.mk
+
+CCFLAGS += $(LEVEL_1_CPP_WARNINGS)
+
+CPPFLAGS += $(OGL_CPPFLAGS)
+CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION)
+CPPFLAGS += -I$(NAN_STRING)/include
+CPPFLAGS += -I$(NAN_FUZZICS)/include -I$(NAN_SUMO)/include -I$(NAN_MOTO)/include
+CPPFLAGS += -I../Rasterizer -I../GameLogic -I../SceneGraph
+CPPFLAGS += -I../BlenderRoutines -I../SoundSystem -I../Expressions
+CPPFLAGS += -I../../kernel/gen_system
+CPPFLAGS += -I../Network -IKXNetwork
+CPPFLAGS += -I../Physics/common
+CPPFLAGS += -I../Physics/Dummy
+CPPFLAGS += -I../Physics/Sumo
+CPPFLAGS += -I.
+
+###########################
+
+SOURCEDIR = source/gameengine/Ketsji
+DIRS = KXNetwork
+
+include nan_subdirs.mk
+
diff --git a/source/gameengine/Makefile b/source/gameengine/Makefile
new file mode 100644
index 00000000000..3111f3afbdd
--- /dev/null
+++ b/source/gameengine/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 *****
+#
+# Bounces make to subdirectories.
+
+include nan_definitions.mk
+
+SOURCEDIR = source/gameengine
+DIR = $(OCGDIR)/gameengine
+DIRS = BlenderRoutines
+DIRS += Converter
+DIRS += Expressions GameLogic Ketsji Rasterizer SceneGraph
+DIRS += SoundSystem Network GamePlayer Physics
+
+include nan_subdirs.mk
diff --git a/source/gameengine/Network/LoopBackNetwork/Makefile b/source/gameengine/Network/LoopBackNetwork/Makefile
new file mode 100644
index 00000000000..19fe362b8f7
--- /dev/null
+++ b/source/gameengine/Network/LoopBackNetwork/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 *****
+#
+#
+
+LIBNAME = LoopBackNetwork
+DIR = $(OCGDIR)/gameengine/Network/$(LIBNAME)
+
+include nan_compile.mk
+
+CCFLAGS += $(LEVEL_1_CPP_WARNINGS)
+
+CPPFLAGS += -I$(NAN_STRING)/include
+CPPFLAGS += -I..
+CPPFLAGS += -I../../../kernel/gen_system
+
diff --git a/source/gameengine/Network/LoopBackNetwork/NG_LoopBackNetworkDeviceInterface.cpp b/source/gameengine/Network/LoopBackNetwork/NG_LoopBackNetworkDeviceInterface.cpp
new file mode 100644
index 00000000000..9d4069bcac6
--- /dev/null
+++ b/source/gameengine/Network/LoopBackNetwork/NG_LoopBackNetworkDeviceInterface.cpp
@@ -0,0 +1,110 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * LoopbackNetworkDeviceInterface derived from NG_NetworkDeviceInterface
+ */
+
+#include "NG_LoopBackNetworkDeviceInterface.h"
+#include "NG_NetworkMessage.h"
+
+// temporary debugging printf's
+#ifdef NAN_NET_DEBUG
+ #include <stdio.h>
+#endif
+
+NG_LoopBackNetworkDeviceInterface::NG_LoopBackNetworkDeviceInterface()
+{
+ m_currentQueue=0;
+ Online(); // LoopBackdevices are 'online' immediately
+}
+
+NG_LoopBackNetworkDeviceInterface::~NG_LoopBackNetworkDeviceInterface()
+{
+}
+
+// perhaps this should go to the shared/common implementation too
+void NG_LoopBackNetworkDeviceInterface::NextFrame()
+{
+ // Release reference to the messages while emptying the queue
+ while (m_messages[m_currentQueue].size() > 0) {
+ // Should do assert(m_events[0]);
+ m_messages[m_currentQueue][0]->Release();
+ m_messages[m_currentQueue].pop_front();
+ }
+ //m_messages[m_currentQueue].clear();
+
+ m_currentQueue=1-m_currentQueue;
+}
+
+STR_String NG_LoopBackNetworkDeviceInterface::GetNetworkVersion()
+{
+ return LOOPBACK_NETWORK_VERSION;
+}
+
+void NG_LoopBackNetworkDeviceInterface::SendNetworkMessage(NG_NetworkMessage* nwmsg)
+{
+#ifdef NAN_NET_DEBUG
+ printf("NG_LBNDI::SendNetworkMessage '%s'->'%s' '%s' '%s'\n",
+ nwmsg->GetDestinationName().ReadPtr(),
+ nwmsg->GetSenderName().ReadPtr(),
+ nwmsg->GetSubject().ReadPtr(),
+ nwmsg->GetMessageText().ReadPtr());
+#endif
+ int backqueue = 1-m_currentQueue;
+
+ nwmsg->AddRef();
+ m_messages[backqueue].push_back(nwmsg);
+}
+
+vector<NG_NetworkMessage*> NG_LoopBackNetworkDeviceInterface::RetrieveNetworkMessages()
+{
+ vector<NG_NetworkMessage*> messages;
+
+ std::deque<NG_NetworkMessage*>::iterator mesit=m_messages[m_currentQueue].begin();
+ for (; !(mesit == m_messages[m_currentQueue].end());mesit++)
+ {
+
+ // We don't increase the reference count for these messages. We
+ // are passing a vector of messages in the interface and not
+ // explicitily storing the messgaes for long term usage
+
+ messages.push_back(*mesit);
+
+#ifdef NAN_NET_DEBUG
+ printf("NG_LBNDI::RetrieveNetworkMessages '%s'->'%s' '%s' '%s'\n",
+ (*mesit)->GetDestinationName().ReadPtr(),
+ (*mesit)->GetSenderName().ReadPtr(),
+ (*mesit)->GetSubject().ReadPtr(),
+ (*mesit)->GetMessageText().ReadPtr());
+#endif
+ }
+ return messages;
+}
+
diff --git a/source/gameengine/Network/LoopBackNetwork/NG_LoopBackNetworkDeviceInterface.h b/source/gameengine/Network/LoopBackNetwork/NG_LoopBackNetworkDeviceInterface.h
new file mode 100644
index 00000000000..ad87b232794
--- /dev/null
+++ b/source/gameengine/Network/LoopBackNetwork/NG_LoopBackNetworkDeviceInterface.h
@@ -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 *****
+ * LoopbackNetworkDeviceInterface derived from NG_NetworkDeviceInterface
+ */
+#ifndef NG_LOOPBACKNETWORKDEVICEINTERFACE_H
+#define NG_LOOPBACKNETWORKDEVICEINTERFACE_H
+
+#include <deque>
+#include "NG_NetworkDeviceInterface.h"
+
+class NG_LoopBackNetworkDeviceInterface : public NG_NetworkDeviceInterface
+{
+ enum {
+ LOOPBACK_NETWORK_VERSION=28022001
+ };
+
+ std::deque<NG_NetworkMessage*> m_messages[2];
+ int m_currentQueue;
+
+public:
+ NG_LoopBackNetworkDeviceInterface();
+ virtual ~NG_LoopBackNetworkDeviceInterface();
+
+ /**
+ * Clear message buffer
+ */
+ virtual void NextFrame();
+
+ bool Connect(char *address, unsigned int port, char *password,
+ unsigned int localport, unsigned int timeout) {
+ return true;}
+ bool Disconnect(void) {return true;}
+
+ virtual void SendNetworkMessage(class NG_NetworkMessage* msg);
+ virtual vector<NG_NetworkMessage*> RetrieveNetworkMessages();
+
+ STR_String GetNetworkVersion();
+};
+
+#endif //NG_LOOPBACKNETWORKDEVICEINTERFACE_H
diff --git a/source/gameengine/Network/Makefile b/source/gameengine/Network/Makefile
new file mode 100644
index 00000000000..3c5ed35e539
--- /dev/null
+++ b/source/gameengine/Network/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 = Network
+DIR = $(OCGDIR)/gameengine/$(LIBNAME)
+
+include nan_compile.mk
+
+CCFLAGS += $(LEVEL_1_CPP_WARNINGS)
+
+CPPFLAGS += -I$(NAN_STRING)/include
+CPPFLAGS += -I../GameLogic
+CPPFLAGS += -I../../kernel/gen_system
+
+##############
+
+DIRS = LoopBackNetwork
+SOURCEDIR = source/gameengine/Network
+
+include nan_subdirs.mk
diff --git a/source/gameengine/Network/NG_NetworkDeviceInterface.h b/source/gameengine/Network/NG_NetworkDeviceInterface.h
new file mode 100644
index 00000000000..f6f8b0e8631
--- /dev/null
+++ b/source/gameengine/Network/NG_NetworkDeviceInterface.h
@@ -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 *****
+ * NetworkGameengine_NetworkDeviceInterface
+ * Functions like (de)initialize network, get library version
+ * To be derived by loopback and network libraries
+ */
+#ifndef NG_NETWORKDEVICEINTERFACE_H
+#define NG_NETWORKDEVICEINTERFACE_H
+
+#include "NG_NetworkMessage.h"
+
+#include <vector>
+
+class NG_NetworkDeviceInterface
+{
+private:
+ // candidates for shared/common implementation class
+ bool m_online;
+public:
+ NG_NetworkDeviceInterface() {};
+ virtual ~NG_NetworkDeviceInterface() {};
+
+ virtual void NextFrame()=0;
+
+ /**
+ * Mark network connection online
+ */
+ void Online(void) { m_online = true; }
+ /**
+ * Mark network connection offline
+ */
+ void Offline(void) { m_online = false; }
+ /**
+ * Is the network connection established ?
+ */
+ bool IsOnline(void) { return m_online; }
+
+ virtual bool Connect(char *address, unsigned int port, char *password,
+ unsigned int localport, unsigned int timeout)=0;
+ virtual bool Disconnect(void)=0;
+
+ virtual void SendNetworkMessage(NG_NetworkMessage* msg)=0;
+ /**
+ * read NG_NetworkMessage from library buffer, may be
+ * irrelevant for loopbackdevices
+ */
+
+ virtual std::vector<NG_NetworkMessage*> RetrieveNetworkMessages()=0;
+
+ /**
+ * number of messages in device hash for this frame
+ */
+
+ virtual STR_String GetNetworkVersion(void)=0;
+};
+
+#endif //NG_NETWORKDEVICEINTERFACE_H
diff --git a/source/gameengine/Network/NG_NetworkMessage.cpp b/source/gameengine/Network/NG_NetworkMessage.cpp
new file mode 100644
index 00000000000..d000dd4b4cc
--- /dev/null
+++ b/source/gameengine/Network/NG_NetworkMessage.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 *****
+ * generic Network Message implementation
+ */
+#include "NG_NetworkMessage.h"
+#include <assert.h>
+
+int NG_NetworkMessage::s_nextID = 3; // just some number to start with
+
+NG_NetworkMessage::NG_NetworkMessage(
+ const STR_String& to,
+ const STR_String& from,
+ const STR_String& subject,
+ const STR_String& body) :
+ m_uniqueMessageID(s_nextID++),
+ m_refcount(1),
+ m_to(to),
+ m_from(from),
+ m_subject(subject),
+ m_message(body)
+{
+}
+
+NG_NetworkMessage::~NG_NetworkMessage()
+{
+ assert(m_refcount==0);
+}
diff --git a/source/gameengine/Network/NG_NetworkMessage.h b/source/gameengine/Network/NG_NetworkMessage.h
new file mode 100644
index 00000000000..72abb3e4a71
--- /dev/null
+++ b/source/gameengine/Network/NG_NetworkMessage.h
@@ -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 *****
+ * NetworkGame_NetworkMessage generic Network Message class
+ */
+#ifndef NG_NETWORKMESSAGE_H
+#define NG_NETWORKMESSAGE_H
+
+#include "STR_HashedString.h"
+
+class NG_NetworkMessage
+{
+ static int s_nextID;
+ int m_uniqueMessageID; // intern counting MessageID
+ unsigned int m_ClientId;
+ int m_refcount;
+
+ STR_String m_to; // receiver
+ STR_String m_from; // sender
+ STR_String m_subject; // empty or propName
+ STR_String m_message; // message or propValue
+
+protected:
+ ~NG_NetworkMessage();
+
+public:
+ NG_NetworkMessage(
+ const STR_String& to,
+ const STR_String& from,
+ const STR_String& subject,
+ const STR_String& body);
+
+ void AddRef() {
+ m_refcount++;
+ }
+
+ // This is not nice code you should'nt need to resort to
+ // delete this.
+ void Release()
+ {
+ if (! --m_refcount)
+ {
+ delete this;
+ }
+ }
+
+ /**
+ * set the content of this message
+ */
+ void SetMessageText(const STR_String& msgtext) {
+ m_message = msgtext;
+ }
+
+ /**
+ * get the (read-only) To part of this message
+ */
+ const STR_String& GetDestinationName() { return m_to;};
+
+ /**
+ * get the (read-only) From part of this message
+ */
+ const STR_String& GetSenderName() { return m_from;};
+
+ /**
+ * get the (read-only) Subject part of this message
+ */
+ const STR_String& GetSubject() { return m_subject;};
+
+ /**
+ * get the (read-only) Body part of this message
+ */
+ const STR_String& GetMessageText() {
+//cout << "GetMessageText " << m_message << "\n";
+ return m_message;
+ }
+ const STR_String& GetMessageText() const {
+//cout << "GetMessageText " << m_message << "\n";
+ return m_message;
+ }
+
+ /**
+ * Set the NetworkMessage sender identifier
+ */
+ void SetSender(unsigned int ClientId) {
+ m_ClientId = ClientId;
+ }
+
+ /**
+ * Get the NetworkMessage sender identifier
+ */
+ unsigned int GetSender(void) {
+ return m_ClientId;
+ }
+
+ /**
+ * get the unique Network Message ID
+ */
+ int GetMessageID() {
+ return m_uniqueMessageID;
+ }
+};
+
+#endif //NG_NETWORKMESSAGE_H
diff --git a/source/gameengine/Network/NG_NetworkObject.cpp b/source/gameengine/Network/NG_NetworkObject.cpp
new file mode 100644
index 00000000000..54db7c4f4b8
--- /dev/null
+++ b/source/gameengine/Network/NG_NetworkObject.cpp
@@ -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 *****
+ * NetworkGame_NetworkObject generic Network Object implementation
+ */
+#include "NG_NetworkObject.h"
+
+NG_NetworkObject::NG_NetworkObject()
+{
+}
+
+NG_NetworkObject::~NG_NetworkObject()
+{
+}
+
+const STR_String& NG_NetworkObject::GetName()
+{
+ return m_name;
+}
diff --git a/source/gameengine/Network/NG_NetworkObject.h b/source/gameengine/Network/NG_NetworkObject.h
new file mode 100644
index 00000000000..d276ab6a25a
--- /dev/null
+++ b/source/gameengine/Network/NG_NetworkObject.h
@@ -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 *****
+ * NetworkGame_NetworkObject generic Network Object class
+ */
+#ifndef NG_NETWORKOBJECT_H
+#define NG_NETWORKOBJECT_H
+
+#include "STR_String.h"
+
+class NG_NetworkObject
+{
+ STR_String m_name;
+public:
+ NG_NetworkObject();
+ ~NG_NetworkObject();
+ const STR_String& GetName();
+};
+
+#endif //NG_NETWORKOBJECT_H
diff --git a/source/gameengine/Network/NG_NetworkScene.cpp b/source/gameengine/Network/NG_NetworkScene.cpp
new file mode 100644
index 00000000000..30bc1aac122
--- /dev/null
+++ b/source/gameengine/Network/NG_NetworkScene.cpp
@@ -0,0 +1,271 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * NetworkSceneManagement generic implementation
+ */
+#include <stdio.h>
+#include <assert.h>
+#include <algorithm>
+
+#include "NG_NetworkScene.h"
+#include "NG_NetworkDeviceInterface.h"
+#include "NG_NetworkMessage.h"
+#include "NG_NetworkObject.h"
+
+NG_NetworkScene::NG_NetworkScene(NG_NetworkDeviceInterface* nic)
+{
+ m_networkdevice = nic;
+}
+
+NG_NetworkScene::~NG_NetworkScene()
+{
+ ClearAllMessageMaps();
+}
+
+/**
+ * progress one frame, handle all network traffic
+ */
+void NG_NetworkScene::proceed(double curtime, double deltatime)
+{
+ if (!m_networkdevice) return;
+ if (!m_networkdevice->IsOnline()) return;
+
+ ClearAllMessageMaps();
+
+ // read all NetworkMessages from the device
+ vector<NG_NetworkMessage*> messages =
+ m_networkdevice->RetrieveNetworkMessages();
+
+ vector<NG_NetworkMessage*>::iterator mesit = messages.begin();
+ for (; !(mesit == messages.end()); mesit++) {
+ NG_NetworkMessage* message = (*mesit);
+ vector<NG_NetworkMessage*>* tmplist=NULL;
+
+ vector<NG_NetworkMessage*>** tmplistptr =
+ m_messagesByDestinationName[message->GetDestinationName()];
+ // if there is already a vector of messages, append, else create
+ // a new vector and insert into map
+ if (!tmplistptr) {
+ tmplist = new vector<NG_NetworkMessage*>;
+ m_messagesByDestinationName.insert(message->GetDestinationName(),
+ tmplist);
+ } else {
+ tmplist = *tmplistptr;
+ }
+ message->AddRef();
+ tmplist->push_back(message);
+ tmplist = NULL;
+
+ tmplistptr = m_messagesBySenderName[message->GetSenderName()];
+ // if there is already a vector of messages, append, else create
+ // a new vector and insert into map
+ if (!tmplistptr) {
+ tmplist = new vector<NG_NetworkMessage*>;
+ m_messagesBySenderName.insert(message->GetSenderName(), tmplist);
+ } else {
+ tmplist = *tmplistptr;
+ }
+ message->AddRef();
+ tmplist->push_back(message);
+ tmplist = NULL;
+
+ tmplistptr = m_messagesBySubject[message->GetSubject()];
+ // if there is already a vector of messages, append, else create
+ // a new vector and insert into map
+ if (!tmplistptr) {
+ tmplist = new vector<NG_NetworkMessage*>;
+ m_messagesBySubject.insert(message->GetSubject(), tmplist);
+ } else {
+ tmplist = *tmplistptr;
+ }
+ message->AddRef();
+ tmplist->push_back(message);
+ tmplist = NULL;
+ }
+}
+
+/**
+ * add a network object to the network scene
+ */
+void NG_NetworkScene::AddObject(NG_NetworkObject* object)
+{
+ if (! m_networkdevice->IsOnline()) return;
+
+ STR_String name = object->GetName();
+ m_networkObjects.insert(name, object);
+}
+
+/**
+ * remove a network object from the network scene
+ */
+void NG_NetworkScene::RemoveObject(NG_NetworkObject* object)
+{
+ if (! m_networkdevice->IsOnline()) return;
+
+ STR_String name = object->GetName();
+ m_networkObjects.remove(name);
+}
+
+/**
+ * remove all network scene objects at once
+ */
+void NG_NetworkScene::RemoveAllObjects()
+{
+ m_networkObjects.clear();
+}
+
+/**
+ * get a single network object given its name
+ */
+NG_NetworkObject* NG_NetworkScene::FindNetworkObject(const STR_String& objname) {
+ NG_NetworkObject *nwobj = NULL;
+ if (! m_networkdevice->IsOnline()) return nwobj;
+
+ NG_NetworkObject **nwobjptr = m_networkObjects[objname];
+ if (nwobjptr) {
+ nwobj = *nwobjptr;
+ }
+
+ return nwobj;
+}
+
+bool NG_NetworkScene::ConstraintsAreValid(
+ const STR_String& from,
+ const STR_String& subject,
+ NG_NetworkMessage* message)
+{
+ vector<NG_NetworkMessage*>** fromlistptr = m_messagesBySenderName[from];
+ vector<NG_NetworkMessage*>** subjectlistptr = m_messagesBySubject[subject];
+
+ vector<NG_NetworkMessage*>* fromlist = (fromlistptr ? *fromlistptr : NULL);
+ vector<NG_NetworkMessage*>* subjectlist = (subjectlistptr ? *subjectlistptr : NULL);
+
+ return (
+ ( from.IsEmpty() || (!fromlist ? false : (!(std::find(fromlist->begin(), fromlist->end(), message) == fromlist->end())))
+ ) &&
+ ( subject.IsEmpty() || (!subjectlist ? false : (!(std::find(subjectlist->begin(), subjectlist->end(), message) == subjectlist->end())))
+ ));
+}
+
+vector<NG_NetworkMessage*> NG_NetworkScene::FindMessages(
+ const STR_String& to,
+ const STR_String& from,
+ const STR_String& subject,
+ bool spamallowed)
+{
+ vector<NG_NetworkMessage*> foundmessages;
+ bool notfound = false;
+
+ // broad phase
+ notfound = ((to.IsEmpty() || spamallowed) ? notfound : m_messagesByDestinationName[to] == NULL);
+ if (!notfound)
+ notfound = (from.IsEmpty() ? notfound : m_messagesBySenderName[from] == NULL);
+ if (!notfound)
+ notfound = (subject.IsEmpty() ? notfound : m_messagesBySubject[subject] == NULL);
+ if (notfound) {
+ // it's definately NOT in the scene, so stop looking
+ } else { // narrow phase
+ // possibly it's there, but maybe not (false hit)
+ if (to.IsEmpty()) {
+ // take all messages, and check other fields
+ assert("objectnames that are empty are not valid, so make it a hobby project :)\n");
+ } else {
+ //todo: find intersection of messages (that are in other 2 maps)
+ vector<NG_NetworkMessage*>** tolistptr = m_messagesByDestinationName[to];
+ if (tolistptr) {
+ vector<NG_NetworkMessage*>* tolist = *tolistptr;
+ vector<NG_NetworkMessage*>::iterator listit;
+ for (listit=tolist->begin();!(listit==tolist->end());listit++) {
+ NG_NetworkMessage* message = *listit;
+ if (ConstraintsAreValid(from, subject, message)) {
+ message->AddRef();
+ foundmessages.push_back(message);
+ }
+ }
+ }
+ // TODO find intersection of messages (that are in other 2 maps)
+ if (spamallowed) {
+ tolistptr = m_messagesByDestinationName[""];
+ if (tolistptr) {
+ vector<NG_NetworkMessage*>* tolist = *tolistptr;
+ vector<NG_NetworkMessage*>::iterator listit;
+ for (listit=tolist->begin();!(listit==tolist->end());listit++) {
+ NG_NetworkMessage* message = *listit;
+ if (ConstraintsAreValid(from, subject, message)) {
+ message->AddRef();
+ foundmessages.push_back(message);
+ }
+ }
+ }
+ }
+ }
+ }
+ return foundmessages;
+}
+
+void NG_NetworkScene::SendMessage(
+ const STR_String& to,
+ const STR_String& from,
+ const STR_String& subject,
+ const STR_String& message)
+{
+ NG_NetworkMessage* msg = new NG_NetworkMessage(to, from, subject, message);
+ m_networkdevice->SendNetworkMessage(msg);
+ msg->Release();
+}
+
+void NG_NetworkScene::ClearAllMessageMaps(void)
+{
+ ClearMessageMap(m_messagesByDestinationName);
+ ClearMessageMap(m_messagesBySenderName);
+ ClearMessageMap(m_messagesBySubject);
+}
+
+void NG_NetworkScene::ClearMessageMap(TMessageMap& map)
+{
+ // Release the messages in the map
+ for (int i = 0; i < map.size(); i++) {
+ vector<NG_NetworkMessage*>* msglist;
+ msglist = *(map.at(i));
+
+ // Iterate through the current vector and release all it's messages
+ vector<NG_NetworkMessage*>::iterator msgit;
+ for (msgit = msglist->begin(); msgit != msglist->end(); msgit++) {
+ (*msgit)->Release();
+ }
+
+ // Delete the actual vector
+ delete (msglist);
+ }
+
+ // Empty the map
+ map.clear();
+}
+
diff --git a/source/gameengine/Network/NG_NetworkScene.h b/source/gameengine/Network/NG_NetworkScene.h
new file mode 100644
index 00000000000..487934205ec
--- /dev/null
+++ b/source/gameengine/Network/NG_NetworkScene.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 *****
+ * NetworkSceneManagement generic class
+ */
+#ifndef __NG_NETWORKSCENE_H
+#define __NG_NETWORKSCENE_H
+
+#include "GEN_Map.h"
+#include "STR_HashedString.h"
+#include <vector>
+class NG_NetworkDeviceInterface;
+
+class NG_NetworkScene
+{
+ class NG_NetworkDeviceInterface *m_networkdevice;
+ GEN_Map<STR_HashedString, class NG_NetworkObject *> m_networkObjects;
+
+ // GEN_Maps used as a 'Bloom' filter
+ typedef GEN_Map<STR_HashedString, std::vector<class NG_NetworkMessage*>* > TMessageMap;
+ TMessageMap m_messagesByDestinationName;
+ TMessageMap m_messagesBySenderName;
+ TMessageMap m_messagesBySubject;
+
+public:
+ NG_NetworkScene(NG_NetworkDeviceInterface *nic);
+ ~NG_NetworkScene();
+
+ /**
+ * progress one frame, handle all network traffic
+ */
+ void proceed(double curtime, double deltatime);
+
+ /**
+ * add a networkobject to the scene
+ */
+ void AddObject(NG_NetworkObject* object);
+
+ /**
+ * remove a networkobject to the scene
+ */
+ void RemoveObject(NG_NetworkObject* object);
+
+ /**
+ * remove all objects at once
+ */
+ void RemoveAllObjects();
+
+ /**
+ * send a message (ascii text) over the network
+ */
+ void SendMessage(const STR_String& to,const STR_String& from,const STR_String& subject,const STR_String& message);
+
+ /**
+ * find an object by name
+ */
+ NG_NetworkObject* FindNetworkObject(const STR_String& objname);
+
+ bool ConstraintsAreValid(const STR_String& from,const STR_String& subject,class NG_NetworkMessage* message);
+ vector<NG_NetworkMessage*> FindMessages(const STR_String& to,const STR_String& from,const STR_String& subject,bool spamallowed);
+
+protected:
+ /**
+ * Releases messages in message map members.
+ */
+ void ClearAllMessageMaps(void);
+
+ /**
+ * Releases messages for the given message map.
+ * @param map Message map with messages.
+ */
+ void ClearMessageMap(TMessageMap& map);
+};
+
+#endif //__NG_NETWORKSCENE_H
diff --git a/source/gameengine/Network/TerraplayNetwork/Makefile b/source/gameengine/Network/TerraplayNetwork/Makefile
new file mode 100644
index 00000000000..6fad0e0ca43
--- /dev/null
+++ b/source/gameengine/Network/TerraplayNetwork/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 *****
+#
+#
+
+LIBNAME = TerraPlayNetwork
+DIR = $(OCGDIR)/gameengine/Network/$(LIBNAME)
+
+include nan_compile.mk
+
+CCFLAGS += $(LEVEL_1_CPP_WARNINGS)
+
+CPPFLAGS += -I$(NAN_STRING)/include
+CPPFLAGS += -I$(LCGDIR)/terraplay/include
+CPPFLAGS += -I../../../kernel/gen_system
+CPPFLAGS += -I..
+
diff --git a/source/gameengine/Network/TerraplayNetwork/NG_TerraplayNetworkDeviceInterface.cpp b/source/gameengine/Network/TerraplayNetwork/NG_TerraplayNetworkDeviceInterface.cpp
new file mode 100644
index 00000000000..55710e0f8ad
--- /dev/null
+++ b/source/gameengine/Network/TerraplayNetwork/NG_TerraplayNetworkDeviceInterface.cpp
@@ -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 *****
+ * TerraplayNetworkDeviceInterface derived from NG_NetworkDeviceInterface
+ */
+
+#include "NG_TerraplayNetworkDeviceInterface.h"
+#include "NG_NetworkMessage.h"
+
+//---- relocate these
+void NG_TerraplayNetworkDeviceInterface::interface_error(char *str, GASResult error) {
+ GASRString err_str = GAS->ErrorTranslate(error);
+ if (err_str.result == GASOK)
+ printf("%s: %s\n",str,err_str.ptr);
+ else
+ printf("%s: UNKNOWN (Error code %d)", error);
+}
+//---- END relocate these
+
+NG_TerraplayNetworkDeviceInterface::NG_TerraplayNetworkDeviceInterface()
+{
+ group_id = GASCLIENTIDNULL;
+ group_id_request_valid = false;
+ this->Offline();
+
+ if ((GAS = new GASInterface()) == NULL) {
+ // terror
+ printf("ERROR GAS Common Network Interface NOT created\n");
+ // do something useful
+ } else {
+ printf("GAS Common Network Interface created\n");
+ }
+}
+
+NG_TerraplayNetworkDeviceInterface::~NG_TerraplayNetworkDeviceInterface()
+{
+ if (GAS != NULL) {
+ delete GAS;
+ printf("GAS Common Network Interface deleted\n");
+ }
+}
+
+bool NG_TerraplayNetworkDeviceInterface::Connect(char *GAS_address,
+ unsigned int GAS_port, char *GAS_password, unsigned int localport,
+ unsigned int timeout)
+{
+ GASResult result;
+ printf("Establishing connection to GAS...\n");
+ result = GAS->ConnectionRequest(GAS_address, GAS_port,
+ GAS_password,localport, timeout);
+ if (result == GASOK) {
+ this->Online();
+ GASRClientId client_id = GAS->Connected();
+ if (client_id.result != GASOK) {
+ printf("... connected, but no client ID\n");
+ return false;
+ } else {
+ printf("Connected with client ID %d\n",
+ client_id.clientid);
+ return true;
+ }
+ } else {
+ interface_error("Connection", result);
+ return false;
+ }
+}
+
+bool NG_TerraplayNetworkDeviceInterface::Disconnect(void)
+{
+ int i = 0;
+ printf("Disconnecting...\n");
+ if (! this->IsOnline()) {
+ printf("ehh... /me was not connected\n");
+ return false;
+ }
+
+ GASRRequestId req = GAS->ConnectionClose();
+ if (req.result != GASWAITING) {
+ interface_error("ConnectionClose",req.result);
+ this->~NG_TerraplayNetworkDeviceInterface();
+ }
+ this->Offline();
+// dit is erg fout :( ik wil helemaal geen ~NG_ hier
+
+ while (true) {
+ GASRMessage gas_message;
+ GASResult result = GAS->GasActivity(GASBLOCK, 100);
+ if (++i>5000) {
+ printf("\nGiving up on waiting for connection close\n");
+ this->~NG_TerraplayNetworkDeviceInterface();
+ }
+ switch (result) {
+ case GASCONNECTIONOK:
+ break;
+ case GASGASMESSAGE:
+ gas_message = GAS->GasMessageGetNext();
+ if (gas_message.type == GASRCONNECTIONCLOSE) {
+ if (gas_message.result == GASOK ||
+ gas_message.result == GASALREADYDONE) {
+ return true;
+ } else {
+ interface_error("GasMessageGetNext",
+ gas_message.result);
+ return false;
+ }
+ }
+ // no break ...
+ default:
+ interface_error("GasActivity",result);
+ }
+ }
+ return true;
+}
+
+STR_String NG_TerraplayNetworkDeviceInterface::GetNetworkVersion()
+{
+ GASRString version = GAS->Version();
+ if (version.result != GASOK) {
+ interface_error("GetNetworkVersion", version.result);
+ return NULL;
+ } else {
+ return version.ptr;
+ }
+}
+
+int NG_TerraplayNetworkDeviceInterface::mytest() {
+ return (3);
+}
+
+void NG_TerraplayNetworkDeviceInterface::SendNetworkMessage(NG_NetworkMessage* nwmsg)
+{
+ GASPayload payload;
+ GASResult result;
+ STR_String mystring;
+
+ if (group_id == GASCLIENTIDNULL) {
+ printf("Oops, no group to send to yet\n");
+ return;
+ }
+
+ mystring = nwmsg->GetMessageText().ReadPtr();
+ payload.ptr = (void *) mystring.Ptr();
+ payload.size = mystring.Length() + 1;
+
+ result = GAS->ClientMessageSend(group_id, payload, GASBESTEFFORT);
+
+ switch (result) {
+ case GASOK:
+ break;
+ default:
+ interface_error("ClientMessageSend",result);
+ }
+ // NOTE. You shall NOT free the payload with PayloadFree().
+ // This is your own payload, allocated and freed by yourself
+ // anyway you want.
+}
+
+vector <NG_NetworkMessage*> NG_TerraplayNetworkDeviceInterface::RetrieveNetworkMessages()
+{
+
+ vector <NG_NetworkMessage*> messages;
+ //todo: spend your expensive time here!
+
+ return messages;
+}
diff --git a/source/gameengine/Network/TerraplayNetwork/NG_TerraplayNetworkDeviceInterface.h b/source/gameengine/Network/TerraplayNetwork/NG_TerraplayNetworkDeviceInterface.h
new file mode 100644
index 00000000000..b430b72d985
--- /dev/null
+++ b/source/gameengine/Network/TerraplayNetwork/NG_TerraplayNetworkDeviceInterface.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 *****
+ * TerraplayNetworkDeviceInterface derived from NG_NetworkDeviceInterface
+ */
+#ifndef NG_TERRAPLAYNETWORKDEVICEINTERFACE_H
+#define NG_TERRAPLAYNETWORKDEVICEINTERFACE_H
+
+#include <deque>
+
+#include "GASInterface.h"
+
+#include "NG_NetworkDeviceInterface.h"
+
+class NG_TerraplayNetworkDeviceInterface : public NG_NetworkDeviceInterface
+{
+ std::deque<NG_NetworkMessage*> m_messages;
+
+ // Terraplay GAS stuff
+ GASInterface *GAS;
+ GASClientId group_id;
+ GASRequestId group_id_request;
+ int group_id_request_valid;
+
+ void interface_error(char *str, GASResult error);
+public:
+ NG_TerraplayNetworkDeviceInterface();
+ ~NG_TerraplayNetworkDeviceInterface();
+
+ bool Connect(char *GAS_address, unsigned int GAS_port,
+ char *GAS_password, unsigned int localport,
+ unsigned int timeout);
+ bool Disconnect(void);
+
+ void SendNetworkMessage(NG_NetworkMessage* nwmsg);
+ vector<NG_NetworkMessage*> RetrieveNetworkMessages(void);
+
+ STR_String GetNetworkVersion(void);
+
+ int mytest(void);
+};
+
+#endif //NG_TERRAPLAYNETWORKDEVICEINTERFACE_H
diff --git a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp
new file mode 100644
index 00000000000..bc88ae7012d
--- /dev/null
+++ b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp
@@ -0,0 +1,91 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "DummyPhysicsEnvironment.h"
+#include "PHY_IMotionState.h"
+
+
+
+DummyPhysicsEnvironment::DummyPhysicsEnvironment()
+{
+ // create physicsengine data
+}
+
+
+
+DummyPhysicsEnvironment::~DummyPhysicsEnvironment()
+{
+ //destroy physicsengine data
+}
+
+void DummyPhysicsEnvironment::proceed(double timeStep)
+{
+ //step physics simulation, typically perform
+
+ //collision detection
+ //solve constraints
+ //integrate solution
+
+}
+
+void DummyPhysicsEnvironment::setGravity(float x,float y,float z)
+{
+}
+
+
+
+
+
+
+
+int DummyPhysicsEnvironment::createConstraint(class PHY_IPhysicsController* ctrl,class PHY_IPhysicsController* ctrl2,PHY_ConstraintType type,
+ float pivotX,float pivotY,float pivotZ,float axisX,float axisY,float axisZ)
+{
+
+ int constraintid = 0;
+ return constraintid;
+
+}
+
+void DummyPhysicsEnvironment::removeConstraint(int constraintid)
+{
+ if (constraintid)
+ {
+ }
+}
+
+PHY_IPhysicsController* DummyPhysicsEnvironment::rayTest(void* ignoreClient,float fromX,float fromY,float fromZ, float toX,float toY,float toZ,
+ float& hitX,float& hitY,float& hitZ,float& normalX,float& normalY,float& normalZ)
+{
+ //collision detection / raytesting
+ return NULL;
+}
+
diff --git a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h
new file mode 100644
index 00000000000..874b747849d
--- /dev/null
+++ b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.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 *****
+ */
+#ifndef _DUMMYPHYSICSENVIRONMENT
+#define _DUMMYPHYSICSENVIRONMENT
+
+
+#include "PHY_IPhysicsEnvironment.h"
+
+/**
+* DummyPhysicsEnvironment is an empty placeholder
+* Alternatives are ODE,Sumo and Dynamo PhysicsEnvironments
+* Use DummyPhysicsEnvironment as a base to integrate your own physics engine
+* Physics Environment takes care of stepping the simulation and is a container for physics entities (rigidbodies,constraints, materials etc.)
+*
+* A derived class may be able to 'construct' entities by loading and/or converting
+*/
+class DummyPhysicsEnvironment : public PHY_IPhysicsEnvironment
+{
+
+public:
+ DummyPhysicsEnvironment ();
+ virtual ~DummyPhysicsEnvironment ();
+// Perform an integration step of duration 'timeStep'.
+ virtual void proceed (double timeStep);
+ virtual void setGravity(float x,float y,float z);
+
+ virtual int createConstraint(class PHY_IPhysicsController* ctrl,class PHY_IPhysicsController* ctrl2,PHY_ConstraintType type,
+ float pivotX,float pivotY,float pivotZ,
+ float axisX,float axisY,float axisZ);
+
+ virtual void removeConstraint(int constraintid);
+ virtual PHY_IPhysicsController* rayTest(void* ignoreClient, float fromX,float fromY,float fromZ, float toX,float toY,float toZ,
+ float& hitX,float& hitY,float& hitZ,float& normalX,float& normalY,float& normalZ);
+
+
+};
+
+#endif //_DUMMYPHYSICSENVIRONMENT
+
+
+
diff --git a/source/gameengine/Physics/Dummy/Makefile b/source/gameengine/Physics/Dummy/Makefile
new file mode 100644
index 00000000000..4ef37cf97ce
--- /dev/null
+++ b/source/gameengine/Physics/Dummy/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 = dummy
+DIR = $(OCGDIR)/gameengine/blphys/$(LIBNAME)
+
+include nan_compile.mk
+
+CCFLAGS += $(LEVEL_1_CPP_WARNINGS)
+
+CPPFLAGS += -I$(OPENGL_HEADERS)
+CPPFLAGS += -I$(NAN_STRING)/include
+CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION)
+CPPFLAGS += -I$(NAN_FUZZICS)/include -I$(NAN_SUMO)/include -I$(NAN_MOTO)/include
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+CPPFLAGS += -I../../Physics/common
+CPPFLAGS += -I../../Physics/Dummy
diff --git a/source/gameengine/Physics/Makefile b/source/gameengine/Physics/Makefile
new file mode 100644
index 00000000000..c04ccb175aa
--- /dev/null
+++ b/source/gameengine/Physics/Makefile
@@ -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 *****
+#
+# Bounces make to subdirectories.
+
+include nan_definitions.mk
+
+SOURCEDIR = source/gameengine/Physics
+DIR = $(OCGDIR)/gameengine/blphys
+DIRS = common Sumo Dummy
+
+include nan_subdirs.mk
diff --git a/source/gameengine/Physics/Sumo/Fuzzics/Makefile b/source/gameengine/Physics/Sumo/Fuzzics/Makefile
new file mode 100644
index 00000000000..d721a416862
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/Fuzzics/Makefile
@@ -0,0 +1,9 @@
+#
+# $Id$
+# Copyright (C) 2001 NaN Technologies B.V.
+# Bounce make to subdirectories.
+
+SOURCEDIR = source/sumo/Fuzzics
+DIRS = src
+
+include nan_subdirs.mk
diff --git a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Callback.h b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Callback.h
new file mode 100644
index 00000000000..a43ddbec483
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Callback.h
@@ -0,0 +1,10 @@
+#ifndef SM_CALLBACK_H
+#define SM_CALLBACK_H
+
+class SM_Callback {
+public:
+ virtual void do_me() = 0;
+};
+
+#endif
+
diff --git a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_ClientObjectInfo.h b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_ClientObjectInfo.h
new file mode 100644
index 00000000000..2063892e671
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_ClientObjectInfo.h
@@ -0,0 +1,15 @@
+#ifndef __SM_CLIENTOBJECT_INFO_H
+#define __SM_CLIENTOBJECT_INFO_H
+
+/**
+ * Client Type and Additional Info. This structure can be use instead of a bare void* pointer, for safeness, and additional info for callbacks
+ */
+
+struct SM_ClientObjectInfo
+{
+ int m_type;
+ void* m_clientobject;
+ void* m_auxilary_info;
+};
+
+#endif //__SM_CLIENTOBJECT_INFO_H
diff --git a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_FhObject.h b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_FhObject.h
new file mode 100644
index 00000000000..4aac43f6712
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_FhObject.h
@@ -0,0 +1,36 @@
+#ifndef SM_FHOBJECT_H
+#define SM_FHOBJECT_H
+
+#include "SM_Object.h"
+
+class SM_FhObject : public SM_Object {
+public:
+ SM_FhObject() {}
+ SM_FhObject(const MT_Vector3& ray, SM_Object *client_object) :
+ SM_Object(DT_Ray(ray[0], ray[1], ray[2]), 0, 0, 0),
+ m_ray(ray),
+ m_ray_direction(ray.normalized()),
+ m_client_object(client_object) {}
+
+ const MT_Vector3& getRay() const { return m_ray; }
+ MT_Point3 getSpot() const { return m_pos + m_ray; }
+ const MT_Vector3& getRayDirection() const { return m_ray_direction; }
+ SM_Object *getClientObject() const { return m_client_object; }
+
+ static void ray_hit(void *client_data,
+ void *object1,
+ void *object2,
+ const DT_CollData *coll_data);
+
+private:
+ MT_Vector3 m_ray;
+ MT_Vector3 m_ray_direction;
+ SM_Object *m_client_object;
+};
+
+#endif
+
+
+
+
+
diff --git a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_MotionState.h b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_MotionState.h
new file mode 100644
index 00000000000..9c6a9ddaec2
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_MotionState.h
@@ -0,0 +1,36 @@
+#ifndef SM_MOTIONSTATE_H
+#define SM_MOTIONSTATE_H
+
+#include "MT_Transform.h"
+
+class SM_MotionState {
+public:
+ SM_MotionState() :
+ m_pos(0.0, 0.0, 0.0),
+ m_orn(0.0, 0.0, 0.0, 1.0),
+ m_lin_vel(0.0, 0.0, 0.0),
+ m_ang_vel(0.0, 0.0, 0.0)
+ {}
+
+ void setPosition(const MT_Point3& pos) { m_pos = pos; }
+ void setOrientation(const MT_Quaternion& orn) { m_orn = orn; }
+ void setLinearVelocity(const MT_Vector3& lin_vel) { m_lin_vel = lin_vel; }
+ void setAngularVelocity(const MT_Vector3& ang_vel) { m_ang_vel = ang_vel; }
+
+ const MT_Point3& getPosition() const { return m_pos; }
+ const MT_Quaternion& getOrientation() const { return m_orn; }
+ const MT_Vector3& getLinearVelocity() const { return m_lin_vel; }
+ const MT_Vector3& getAngularVelocity() const { return m_ang_vel; }
+
+ virtual MT_Transform getTransform() const {
+ return MT_Transform(m_pos, m_orn);
+ }
+
+protected:
+ MT_Point3 m_pos;
+ MT_Quaternion m_orn;
+ MT_Vector3 m_lin_vel;
+ MT_Vector3 m_ang_vel;
+};
+
+#endif
diff --git a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Object.h b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Object.h
new file mode 100644
index 00000000000..670da6e71db
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Object.h
@@ -0,0 +1,280 @@
+#ifndef SM_OBJECT_H
+#define SM_OBJECT_H
+
+#include <vector>
+
+#include "solid.h"
+
+#include "SM_Callback.h"
+#include "SM_MotionState.h"
+#include <stdio.h>
+
+
+class SM_FhObject;
+
+
+// Properties of dynamic objects
+struct SM_ShapeProps {
+ MT_Scalar m_mass; // Total mass
+ MT_Scalar m_inertia; // Inertia, should be a tensor some time
+ MT_Scalar m_lin_drag; // Linear drag (air, water) 0 = concrete, 1 = vacuum
+ MT_Scalar m_ang_drag; // Angular drag
+ MT_Scalar m_friction_scaling[3]; // Scaling for anisotropic friction. Component in range [0, 1]
+ bool m_do_anisotropic; // Should I do anisotropic friction?
+ bool m_do_fh; // Should the object have a linear Fh spring?
+ bool m_do_rot_fh; // Should the object have an angular Fh spring?
+};
+
+
+// Properties of collidable objects (non-ghost objects)
+struct SM_MaterialProps {
+ MT_Scalar m_restitution; // restitution of energie after a collision 0 = inelastic, 1 = elastic
+ MT_Scalar m_friction; // Coulomb friction (= ratio between the normal en maximum friction force)
+ MT_Scalar m_fh_spring; // Spring constant (both linear and angular)
+ MT_Scalar m_fh_damping; // Damping factor (linear and angular) in range [0, 1]
+ MT_Scalar m_fh_distance; // The range above the surface where Fh is active.
+ bool m_fh_normal; // Should the object slide off slopes?
+};
+
+
+class SM_Object : public SM_MotionState {
+public:
+ SM_Object() ;
+ SM_Object(
+ DT_ShapeHandle shape,
+ const SM_MaterialProps *materialProps,
+ const SM_ShapeProps *shapeProps,
+ SM_Object *dynamicParent
+ );
+
+ virtual ~SM_Object();
+
+ bool isDynamic() const;
+
+ /* nzc experimental. There seem to be two places where kinematics
+ * are evaluated: proceedKinematic (called from SM_Scene) and
+ * proceed() in this object. I'll just try and bunge these out for
+ * now. */
+
+ void suspend(void);
+ void resume(void);
+
+ void suspendDynamics();
+
+ void restoreDynamics();
+
+ bool isGhost() const;
+
+ void suspendMaterial();
+
+ void restoreMaterial();
+
+ SM_FhObject *getFhObject() const;
+
+ void registerCallback(SM_Callback& callback);
+
+ void calcXform();
+ void notifyClient();
+
+ // Save the current state information for use in the
+ // velocity computation in the next frame.
+
+ void proceedKinematic(MT_Scalar timeStep);
+
+ void saveReactionForce(MT_Scalar timeStep) ;
+
+ void clearForce() ;
+
+ void clearMomentum() ;
+
+ void setMargin(MT_Scalar margin) ;
+
+ MT_Scalar getMargin() const ;
+
+ const SM_MaterialProps *getMaterialProps() const ;
+
+ const SM_ShapeProps *getShapeProps() const ;
+
+ void setPosition(const MT_Point3& pos);
+ void setOrientation(const MT_Quaternion& orn);
+ void setScaling(const MT_Vector3& scaling);
+
+
+ /**
+ * set an external velocity. This velocity complements
+ * the physics velocity. So setting it does not override the
+ * physics velocity. It is your responsibility to clear
+ * this external velocity. This velocity is not subject to
+ * friction or damping.
+ */
+
+
+ void setExternalLinearVelocity(const MT_Vector3& lin_vel) ;
+ void addExternalLinearVelocity(const MT_Vector3& lin_vel) ;
+
+ /** Override the physics velocity */
+
+ void addLinearVelocity(const MT_Vector3& lin_vel);
+ void setLinearVelocity(const MT_Vector3& lin_vel);
+
+ /**
+ * Set an external angular velocity. This velocity complemetns
+ * the physics angular velocity so does not override it. It is
+ * your responsibility to clear this velocity. This velocity
+ * is not subject to friction or damping.
+ */
+
+ void setExternalAngularVelocity(const MT_Vector3& ang_vel) ;
+ void addExternalAngularVelocity(const MT_Vector3& ang_vel);
+
+ /** Override the physics angular velocity */
+
+ void addAngularVelocity(const MT_Vector3& ang_vel);
+ void setAngularVelocity(const MT_Vector3& ang_vel);
+
+ /** Clear the external velocities */
+
+ void clearCombinedVelocities();
+
+ /**
+ * Tell the physics system to combine the external velocity
+ * with the physics velocity.
+ */
+
+ void resolveCombinedVelocities(
+ const MT_Vector3 & lin_vel,
+ const MT_Vector3 & ang_vel
+ ) ;
+
+
+
+ MT_Scalar getInvMass() const;
+
+ MT_Scalar getInvInertia() const ;
+
+ void applyForceField(const MT_Vector3& accel) ;
+
+ void applyCenterForce(const MT_Vector3& force) ;
+
+ void applyTorque(const MT_Vector3& torque) ;
+
+ void applyImpulse(const MT_Point3& attach, const MT_Vector3& impulse) ;
+
+ void applyCenterImpulse(const MT_Vector3& impulse);
+
+ void applyAngularImpulse(const MT_Vector3& impulse);
+
+ MT_Point3 getWorldCoord(const MT_Point3& local) const;
+
+ MT_Vector3 getVelocity(const MT_Point3& local) const;
+
+
+ const MT_Vector3& getReactionForce() const ;
+
+ void getMatrix(double *m) const ;
+
+ const double *getMatrix() const ;
+
+ // Still need this???
+ const MT_Transform& getScaledTransform() const;
+
+ DT_ObjectHandle getObjectHandle() const ;
+ DT_ShapeHandle getShapeHandle() const ;
+
+ void setClientObject(void *clientobj) ;
+ void *getClientObject() ;
+
+ SM_Object *getDynamicParent() ;
+
+ void integrateForces(MT_Scalar timeStep);
+ void integrateMomentum(MT_Scalar timeSteo);
+
+ void setRigidBody(bool is_rigid_body) ;
+
+ bool isRigidBody() const ;
+
+
+ // This is the callback for handling collisions of dynamic objects
+ static
+ void
+ boing(
+ void *client_data,
+ void *object1,
+ void *object2,
+ const DT_CollData *coll_data
+ );
+
+private:
+
+ // return the actual linear_velocity of this object this
+ // is the addition of m_combined_lin_vel and m_lin_vel.
+
+ const
+ MT_Vector3
+ actualLinVelocity(
+ ) const ;
+
+ const
+ MT_Vector3
+ actualAngVelocity(
+ ) const ;
+
+ typedef std::vector<SM_Callback *> T_CallbackList;
+
+
+ T_CallbackList m_callbackList; // Each object can have multiple callbacks from the client (=game engine)
+ SM_Object *m_dynamicParent; // Collisions between parent and children are ignored
+
+ // as the collision callback now has only information
+ // on an SM_Object, there must be a way that the SM_Object client
+ // can identify it's clientdata after a collision
+ void *m_client_object;
+
+ DT_ShapeHandle m_shape; // Shape for collision detection
+
+ // Material and shape properties are not owned by this class.
+
+ const SM_MaterialProps *m_materialProps;
+ const SM_MaterialProps *m_materialPropsBackup; // Backup in case the object temporarily becomes a ghost.
+ const SM_ShapeProps *m_shapeProps;
+ const SM_ShapeProps *m_shapePropsBackup; // Backup in case the object's dynamics is temporarily suspended
+ DT_ObjectHandle m_object; // A handle to the corresponding object in SOLID.
+ MT_Scalar m_margin; // Offset for the object's shape (also for collision detection)
+ MT_Vector3 m_scaling; // Non-uniform scaling of the object's shape
+
+ double m_ogl_matrix[16]; // An OpenGL-type 4x4 matrix
+ MT_Transform m_xform; // The object's local coordinate system
+ MT_Transform m_prev_xform; // The object's local coordinate system in the previous frame
+ SM_MotionState m_prev_state; // The object's motion state in the previous frame
+ MT_Scalar m_timeStep; // The duration of the last frame
+
+ MT_Vector3 m_reaction_impulse; // The accumulated impulse resulting from collisions
+ MT_Vector3 m_reaction_force; // The reaction force derived from the reaction impulse
+
+ unsigned int m_kinematic : 1; // Have I been displaced (translated, rotated, scaled) in this frame?
+ unsigned int m_prev_kinematic : 1; // Have I been displaced (translated, rotated, scaled) in the previous frame?
+ unsigned int m_is_rigid_body : 1; // Should friction give me a change in angular momentum?
+
+ MT_Vector3 m_lin_mom; // Linear momentum (linear velocity times mass)
+ MT_Vector3 m_ang_mom; // Angular momentum (angualr velocity times inertia)
+ MT_Vector3 m_force; // Force on center of mass (afffects linear momentum)
+ MT_Vector3 m_torque; // Torque around center of mass (affects angualr momentum)
+
+ // Here are the values of externally set linear and angular
+ // velocity. These are updated from the outside
+ // (actuators and python) each frame and combined with the
+ // physics values. At the end of each frame (at the end of a
+ // call to proceed) they are set to zero. This allows the
+ // outside world to contribute to the velocity of an object
+ // but still have it react to physics.
+
+ MT_Vector3 m_combined_lin_vel;
+ MT_Vector3 m_combined_ang_vel;
+
+ // The force and torque are the accumulated forces and torques applied by the client (game logic, python).
+
+ SM_FhObject *m_fh_object; // The ray object used for Fh
+ bool m_suspended; // Is this object frozen?
+};
+
+#endif
diff --git a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Props.h b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Props.h
new file mode 100644
index 00000000000..0b2efacac2a
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Props.h
@@ -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 *****
+ */
+#ifndef SM_PROPSH
+#define SM_PROPSH
+
+#include <MT_Scalar.h>
+
+// Properties of dynamic objects
+struct SM_ShapeProps {
+ MT_Scalar m_mass; // Total mass
+ MT_Scalar m_inertia; // Inertia, should be a tensor some time
+ MT_Scalar m_lin_drag; // Linear drag (air, water) 0 = concrete, 1 = vacuum
+ MT_Scalar m_ang_drag; // Angular drag
+ MT_Scalar m_friction_scaling[3]; // Scaling for anisotropic friction. Component in range [0, 1]
+ bool m_do_anisotropic; // Should I do anisotropic friction?
+ bool m_do_fh; // Should the object have a linear Fh spring?
+ bool m_do_rot_fh; // Should the object have an angular Fh spring?
+};
+
+
+// Properties of collidable objects (non-ghost objects)
+struct SM_MaterialProps {
+ MT_Scalar m_restitution; // restitution of energie after a collision 0 = inelastic, 1 = elastic
+ MT_Scalar m_friction; // Coulomb friction (= ratio between the normal en maximum friction force)
+ MT_Scalar m_fh_spring; // Spring constant (both linear and angular)
+ MT_Scalar m_fh_damping; // Damping factor (linear and angular) in range [0, 1]
+ MT_Scalar m_fh_distance; // The range above the surface where Fh is active.
+ bool m_fh_normal; // Should the object slide off slopes?
+};
+
+#endif //SM_PROPSH
diff --git a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Scene.h b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Scene.h
new file mode 100644
index 00000000000..761e6c7c449
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Scene.h
@@ -0,0 +1,129 @@
+/**
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * The physics scene.
+ */
+
+#ifndef SM_SCENE_H
+#define SM_SCENE_H
+
+#pragma warning (disable : 4786)
+
+#include <vector>
+#include <set>
+#include <utility> //needed for pair
+
+#include "solid.h"
+
+#include "MT_Vector3.h"
+#include "MT_Point3.h"
+
+class SM_Object;
+
+class SM_Scene {
+public:
+ SM_Scene() :
+ m_scene(DT_CreateScene()),
+ m_respTable(DT_CreateRespTable()),
+ m_secondaryRespTable(0),
+ m_forceField(0.0, 0.0, 0.0)
+ {}
+
+ ~SM_Scene() {
+ DT_DeleteRespTable(m_respTable);
+ DT_DeleteScene(m_scene);
+ }
+
+ DT_RespTableHandle getRespTableHandle() const {
+ return m_respTable;
+ }
+
+ const MT_Vector3& getForceField() const {
+ return m_forceField;
+ }
+
+ MT_Vector3& getForceField() {
+ return m_forceField;
+ }
+
+ void setForceField(const MT_Vector3& forceField) {
+ m_forceField = forceField;
+ }
+
+ void add(SM_Object& object);
+ void remove(SM_Object& object);
+
+ void addPair(SM_Object *obj1, SM_Object *obj2) {
+ m_pairList.insert(std::make_pair(obj1, obj2));
+ }
+
+ void clearPairs() {
+ m_pairList.clear();
+ }
+
+ void setSecondaryRespTable(DT_RespTableHandle secondaryRespTable) {
+ m_secondaryRespTable = secondaryRespTable;
+ }
+
+
+ // Perform an integration step of duration 'timeStep'.
+ // 'subSampling' is the maximum duration of a substep, i.e.,
+ // The maximum time interval between two collision checks.
+ // 'subSampling' can be used to control aliasing effects
+ // (fast moving objects traversing through walls and such).
+ void proceed(MT_Scalar timeStep, MT_Scalar subSampling);
+
+ /**
+ * Test whether any objects lie on the line defined by from and
+ * to. The search returns the first such bject starting at from,
+ * or NULL if there was none.
+ * @returns A reference to the object, or NULL if there was none.
+ * @param ignore_client Do not look for collisions with this
+ * object. This can be useful to avoid self-hits if
+ * starting from the location of an object.
+ * @param from The start point, in world coordinates, of the search.
+ * @param to The end point, in world coordinates, of the search.
+ * @param result A store to return the point where intersection
+ * took place (if there was an intersection).
+ * @param normal A store to return the normal of the hit object on
+ * the location of the intersection, if it took place.
+ */
+ SM_Object *rayTest(void *ignore_client,
+ const MT_Point3& from, const MT_Point3& to,
+ MT_Point3& result, MT_Vector3& normal) const;
+
+private:
+
+ // Clear the user set velocities.
+ void clearObjectCombinedVelocities();
+
+ /** internal type */
+ typedef std::vector<SM_Object *> T_ObjectList;
+ /** internal type */
+ typedef std::set<std::pair<SM_Object *, SM_Object *> > T_PairList;
+
+ /** Handle to the scene in SOLID */
+ DT_SceneHandle m_scene;
+ /** Following response table contains the callbacks for the dynmics */
+ DT_RespTableHandle m_respTable;
+ /**
+ * Following response table contains callbacks for the client (=
+ * game engine) */
+ DT_RespTableHandle m_secondaryRespTable; // Handle
+
+ /** The acceleration from the force field */
+ MT_Vector3 m_forceField;
+
+ /**
+ * The list of objects that receive motion updates and do
+ * collision tests. */
+ T_ObjectList m_objectList;
+
+ /**
+ * A list with pairs of objects that collided the previous
+ * timestep. The list is built during the proceed(). During that
+ * time, it is not valid. */
+ T_PairList m_pairList;
+};
+
+#endif
diff --git a/source/gameengine/Physics/Sumo/Fuzzics/sample/Makefile b/source/gameengine/Physics/Sumo/Fuzzics/sample/Makefile
new file mode 100644
index 00000000000..672dff39028
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/Fuzzics/sample/Makefile
@@ -0,0 +1,25 @@
+#
+# $Id$
+# Copyright (C) 2001 NaN Technologies B.V.
+
+DIR = $(OCGDIR)/sumo
+ALLTARGETS = $(OBJS) $(DIR)/$(DEBUG_DIR)particle $(DIR)/$(DEBUG_DIR)particle0
+
+include nan_compile.mk
+
+CPPFLAGS = -I../../include -I../include -I$(NAN_MOTO)/include
+CPPFLAGS += -I$(OPENGL_HEADERS)
+
+clean::
+ @$(RM) $(DIR)/particle $(DIR)/particle0
+ @$(RM) $(DIR)/debug/particle $(DIR)/debug/particle0
+
+LDFLAGS = -L$(DIR) -L/usr/X11R6/lib
+OGL_LDLIBS = -lglut -lGLU -lGL -pthread
+LDLIBS = -lfuzzics -lsolid $(NAN_MOTO)/lib/libmoto.a $(OGL_LDLIBS)
+
+$(DIR)/$(DEBUG_DIR)particle: particle.o $(DIR)/$(DEBUG_DIR)libfuzzics.a $(DIR)/$(DEBUG_DIR)libsolid.a
+ $(CCC) $(CCFLAGS) $(CPPFLAGS) $(LDFLAGS) $< -o $@ $(LDLIBS)
+
+$(DIR)/$(DEBUG_DIR)particle0: particle0.o $(DIR)/$(DEBUG_DIR)libfuzzics.a $(DIR)/$(DEBUG_DIR)libsolid.a
+ $(CCC) $(CCFLAGS) $(CPPFLAGS) $(LDFLAGS) $< -o $@ $(LDLIBS)
diff --git a/source/gameengine/Physics/Sumo/Fuzzics/sample/particle.cpp b/source/gameengine/Physics/Sumo/Fuzzics/sample/particle.cpp
new file mode 100644
index 00000000000..e8e78d89a4e
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/Fuzzics/sample/particle.cpp
@@ -0,0 +1,705 @@
+//#define FAKE_IT
+#define USE_COMPLEX
+#define QUADS
+
+#include <algorithm>
+#include <new>
+#include <GL/glut.h>
+
+#include "MT_MinMax.h"
+#include "MT_Point3.h"
+#include "MT_Vector3.h"
+#include "MT_Quaternion.h"
+#include "MT_Matrix3x3.h"
+#include "MT_Transform.h"
+
+#include "SM_Object.h"
+#include "SM_FhObject.h"
+#include "SM_Scene.h"
+
+#include "solid.h"
+
+const MT_Scalar bowl_curv = 0.10;
+const MT_Scalar timeStep = 0.02;
+const MT_Scalar ground_margin = 0.0;
+const MT_Scalar sphere_radius = 0.5;
+
+const MT_Vector3 gravity(0, -9.8, 0);
+
+static MT_Scalar DISTANCE = 5;
+
+static MT_Scalar ele = 0, azi = 0;
+static MT_Point3 eye(0, 0, DISTANCE);
+static MT_Point3 center(0, 0, 0);
+
+inline double irnd() { return 2 * MT_random() - 1; }
+
+static const double SCALE_BOTTOM = 0.5;
+static const double SCALE_FACTOR = 2.0;
+
+SM_ShapeProps g_shapeProps = {
+ 1.0, // mass
+ 1.0, // inertia
+ 0.1, // linear drag
+ 0.1, // angular drag
+ { 1.0, 0.0, 0.0 }, // anisotropic friction
+ false, // do anisotropic friction?
+ true, // do fh?
+ true // do rot fh?
+};
+
+SM_MaterialProps g_materialProps = {
+ 0.7, // restitution
+ 0.0, // friction
+ 10.0, // Fh spring constant
+ 1.0, // Fh damping
+ 0.5, // Fh distance
+ true // Fh leveling
+};
+
+
+void toggleIdle();
+
+
+void newRandom();
+
+void coordSystem() {
+ glDisable(GL_LIGHTING);
+ glBegin(GL_LINES);
+ glColor3f(1, 0, 0);
+ glVertex3d(0, 0, 0);
+ glVertex3d(10, 0, 0);
+ glColor3f(0, 1, 0);
+ glVertex3d(0, 0, 0);
+ glVertex3d(0, 10, 0);
+ glColor3f(0, 0, 1);
+ glVertex3d(0, 0, 0);
+ glVertex3d(0, 0, 10);
+ glEnd();
+ glEnable(GL_LIGHTING);
+}
+
+
+void display_bbox(const MT_Point3& min, const MT_Point3& max) {
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_LIGHTING);
+ glColor3f(0, 1, 1);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ glBegin(GL_QUAD_STRIP);
+ glVertex3d(min[0], min[1], min[2]);
+ glVertex3d(min[0], min[1], max[2]);
+ glVertex3d(max[0], min[1], min[2]);
+ glVertex3d(max[0], min[1], max[2]);
+ glVertex3d(max[0], max[1], min[2]);
+ glVertex3d(max[0], max[1], max[2]);
+ glVertex3d(min[0], max[1], min[2]);
+ glVertex3d(min[0], max[1], max[2]);
+ glVertex3d(min[0], min[1], min[2]);
+ glVertex3d(min[0], min[1], max[2]);
+ glEnd();
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ glEnable(GL_LIGHTING);
+ glEnable(GL_DEPTH_TEST);
+}
+
+
+
+
+class GLShape {
+public:
+ virtual void paint(GLdouble *m) const = 0;
+};
+
+
+class GLSphere : public GLShape {
+ MT_Scalar radius;
+public:
+ GLSphere(MT_Scalar r) : radius(r) {}
+
+ void paint(GLdouble *m) const {
+ glPushMatrix();
+ glLoadMatrixd(m);
+ coordSystem();
+ glutSolidSphere(radius, 20, 20);
+ glPopMatrix();
+ }
+};
+
+
+class GLBox : public GLShape {
+ MT_Vector3 extent;
+public:
+ GLBox(MT_Scalar x, MT_Scalar y, MT_Scalar z) :
+ extent(x, y, z) {}
+
+ void paint(GLdouble *m) const {
+ glPushMatrix();
+ glLoadMatrixd(m);
+ coordSystem();
+ glPushMatrix();
+ glScaled(extent[0], extent[1], extent[2]);
+ glutSolidCube(1.0);
+ glPopMatrix();
+ glPopMatrix();
+ }
+};
+
+
+class GLCone : public GLShape {
+ MT_Scalar bottomRadius;
+ MT_Scalar height;
+ mutable GLuint displayList;
+
+public:
+ GLCone(MT_Scalar r, MT_Scalar h) :
+ bottomRadius(r),
+ height(h),
+ displayList(0) {}
+
+ void paint(GLdouble *m) const {
+ glPushMatrix();
+ glLoadMatrixd(m);
+ coordSystem();
+ if (displayList) glCallList(displayList);
+ else {
+ GLUquadricObj *quadObj = gluNewQuadric();
+ displayList = glGenLists(1);
+ glNewList(displayList, GL_COMPILE_AND_EXECUTE);
+ glPushMatrix();
+ glRotatef(-90.0, 1.0, 0.0, 0.0);
+ glTranslatef(0.0, 0.0, -1.0);
+ gluQuadricDrawStyle(quadObj, (GLenum)GLU_FILL);
+ gluQuadricNormals(quadObj, (GLenum)GLU_SMOOTH);
+ gluCylinder(quadObj, bottomRadius, 0, height, 15, 10);
+ glPopMatrix();
+ glEndList();
+ }
+ glPopMatrix();
+ }
+};
+
+class GLCylinder : public GLShape {
+ MT_Scalar radius;
+ MT_Scalar height;
+ mutable GLuint displayList;
+
+public:
+ GLCylinder(MT_Scalar r, MT_Scalar h) :
+ radius(r),
+ height(h),
+ displayList(0) {}
+
+ void paint(GLdouble *m) const {
+ glPushMatrix();
+ glLoadMatrixd(m);
+ coordSystem();
+ if (displayList) glCallList(displayList);
+ else {
+ GLUquadricObj *quadObj = gluNewQuadric();
+ displayList = glGenLists(1);
+ glNewList(displayList, GL_COMPILE_AND_EXECUTE);
+ glPushMatrix();
+ glRotatef(-90.0, 1.0, 0.0, 0.0);
+ glTranslatef(0.0, 0.0, -1.0);
+ gluQuadricDrawStyle(quadObj, (GLenum)GLU_FILL);
+ gluQuadricNormals(quadObj, (GLenum)GLU_SMOOTH);
+ gluCylinder(quadObj, radius, radius, height, 15, 10);
+ glPopMatrix ();
+ glEndList();
+ }
+ glPopMatrix();
+ }
+};
+
+class Object;
+
+class Callback : public SM_Callback {
+public:
+ Callback(Object& object) : m_object(object) {}
+
+ virtual void do_me();
+
+private:
+ Object& m_object;
+};
+
+
+class Object {
+public:
+ Object(GLShape *gl_shape, SM_Object& object) :
+ m_gl_shape(gl_shape),
+ m_object(object),
+ m_callback(*this)
+ {
+ m_object.registerCallback(m_callback);
+ }
+
+ ~Object() {}
+
+ void paint() {
+ if (m_gl_shape) {
+ m_gl_shape->paint(m);
+ // display_bbox(m_bbox.lower(), m_bbox.upper());
+ }
+ }
+
+ void print_reaction_force() const {
+ std::cout << m_object.getReactionForce() << std::endl;
+ }
+
+ MT_Vector3 getAhead() {
+ return MT_Vector3(&m[4]);
+ }
+
+ MT_Vector3 getUp() {
+ return MT_Vector3(&m[8]);
+ }
+
+ void clearMomentum() {
+ m_object.clearMomentum();
+ }
+
+ void setMargin(MT_Scalar margin) {
+ m_object.setMargin(margin);
+ }
+
+ void setScaling(const MT_Vector3& scaling) {
+ m_object.setScaling(scaling);
+ }
+
+ const MT_Point3& getPosition() {
+ return m_object.getPosition();
+ }
+
+ void setPosition(const MT_Point3& pos) {
+ m_object.setPosition(pos);
+ }
+
+ void setOrientation(const MT_Quaternion& orn) {
+ m_object.setOrientation(orn);
+ }
+
+ void applyCenterForce(const MT_Vector3& force) {
+ m_object.applyCenterForce(force);
+ }
+
+ void applyTorque(const MT_Vector3& torque) {
+ m_object.applyTorque(torque);
+ }
+
+ MT_Point3 getWorldCoord(const MT_Point3& local) const {
+ return m_object.getWorldCoord(local);
+ }
+
+ MT_Vector3 getLinearVelocity() const {
+ return m_object.getLinearVelocity();
+ }
+
+ MT_Vector3 getAngularVelocity() const {
+ return m_object.getAngularVelocity();
+ }
+
+ void setMatrix() {
+ m_object.calcXform();
+ m_object.getMatrix(m);
+ }
+
+ const double *getMatrix() {
+ m_object.calcXform();
+ return m_object.getMatrix();
+ }
+
+private:
+ GLShape *m_gl_shape;
+ SM_Object& m_object;
+ DT_Scalar m[16];
+ Callback m_callback;
+};
+
+
+
+const MT_Scalar SPACE_SIZE = 2;
+
+static GLSphere gl_sphere(sphere_radius);
+static GLBox gl_ground(50.0, 0.0, 50.0);
+
+
+
+#ifdef USE_COMPLEX
+
+const int GRID_SCALE = 10;
+const MT_Scalar GRID_UNIT = 25.0 / GRID_SCALE;
+
+DT_ShapeHandle createComplex() {
+ DT_ShapeHandle shape = DT_NewComplexShape();
+ for (int i0 = -GRID_SCALE; i0 != GRID_SCALE; ++i0) {
+ for (int j0 = -GRID_SCALE; j0 != GRID_SCALE; ++j0) {
+ int i1 = i0 + 1;
+ int j1 = j0 + 1;
+#ifdef QUADS
+ DT_Begin();
+ DT_Vertex(GRID_UNIT * i0, bowl_curv * i0*i0, GRID_UNIT * j0);
+ DT_Vertex(GRID_UNIT * i0, bowl_curv * i0*i0, GRID_UNIT * j1);
+ DT_Vertex(GRID_UNIT * i1, bowl_curv * i1*i1, GRID_UNIT * j1);
+ DT_Vertex(GRID_UNIT * i1, bowl_curv * i1*i1, GRID_UNIT * j0);
+ DT_End();
+#else
+ DT_Begin();
+ DT_Vertex(GRID_UNIT * i0, 0, GRID_UNIT * j0);
+ DT_Vertex(GRID_UNIT * i0, 0, GRID_UNIT * j1);
+ DT_Vertex(GRID_UNIT * i1, 0, GRID_UNIT * j1);
+ DT_End();
+
+ DT_Begin();
+ DT_Vertex(GRID_UNIT * i0, 0, GRID_UNIT * j1);
+ DT_Vertex(GRID_UNIT * i1, 0, GRID_UNIT * j1);
+ DT_Vertex(GRID_UNIT * i1, 0, GRID_UNIT * j0);
+ DT_End();
+#endif
+
+ }
+ }
+ DT_EndComplexShape();
+ return shape;
+}
+
+
+static DT_ShapeHandle ground_shape = createComplex();
+
+#else
+
+static DT_ShapeHandle ground_shape = DT_Box(50, 0, 50);
+
+#endif
+
+static SM_Object sm_ground(ground_shape, &g_materialProps, 0, 0);
+static Object ground(&gl_ground, sm_ground);
+
+static SM_Object sm_sphere(DT_Sphere(0.0), &g_materialProps, &g_shapeProps, 0);
+static Object object(&gl_sphere, sm_sphere);
+
+
+static SM_Scene g_scene;
+
+
+bool g_hit = false;
+MT_Point3 g_spot;
+MT_Vector3 g_normal;
+
+
+void Callback::do_me()
+{
+ m_object.setMatrix();
+ m_object.print_reaction_force();
+}
+
+void myinit(void) {
+
+ GLfloat light_ambient[] = { 0.0, 0.0, 0.0, 1.0 };
+ GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
+ GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 };
+
+ /* light_position is NOT default value */
+ GLfloat light_position0[] = { 1.0, 1.0, 1.0, 0.0 };
+ GLfloat light_position1[] = { -1.0, -1.0, -1.0, 0.0 };
+
+ glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
+ glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
+ glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
+ glLightfv(GL_LIGHT0, GL_POSITION, light_position0);
+
+ glLightfv(GL_LIGHT1, GL_AMBIENT, light_ambient);
+ glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse);
+ glLightfv(GL_LIGHT1, GL_SPECULAR, light_specular);
+ glLightfv(GL_LIGHT1, GL_POSITION, light_position1);
+
+
+ glEnable(GL_LIGHTING);
+ glEnable(GL_LIGHT0);
+ glEnable(GL_LIGHT1);
+
+ glShadeModel(GL_SMOOTH);
+
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_LESS);
+
+ // glEnable(GL_CULL_FACE);
+ // glCullFace(GL_BACK);
+
+ ground.setPosition(MT_Point3(0, -10, 0));
+ ground.setOrientation(MT_Quaternion(0, 0, 0, 1));
+ ground.setMatrix();
+ center.setValue(0.0, 0.0, 0.0);
+ sm_ground.setMargin(ground_margin);
+
+ g_scene.setForceField(gravity);
+ g_scene.add(sm_ground);
+
+ object.setMargin(sphere_radius);
+
+ g_scene.add(sm_sphere);
+
+
+ newRandom();
+}
+
+
+//MT_Point3 cp1, cp2;
+//bool intersection;
+
+void display(void) {
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ ground.paint();
+ object.paint();
+
+ if (g_hit) {
+ glDisable(GL_LIGHTING);
+ glColor3f(1, 0, 0);
+
+ glPointSize(5);
+ glBegin(GL_POINTS);
+ glVertex3d(g_spot[0], g_spot[1], g_spot[2]);
+ glEnd();
+ glPointSize(1);
+
+ glColor3f(1, 1, 0);
+ glBegin(GL_LINES);
+ glVertex3d(g_spot[0], g_spot[1], g_spot[2]);
+ glVertex3d(g_spot[0] + g_normal[0],
+ g_spot[1] + g_normal[1],
+ g_spot[2] + g_normal[2]);
+ glEnd();
+ glEnable(GL_LIGHTING);
+ }
+
+
+
+#ifdef COLLISION
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_LIGHTING);
+ glColor3f(1, 1, 0);
+ if (intersection) {
+ glPointSize(5);
+ glBegin(GL_POINTS);
+ glVertex3d(cp1[0], cp1[1], cp1[2]);
+ glEnd();
+ glPointSize(1);
+ }
+ else {
+ glBegin(GL_LINES);
+ glVertex3d(cp1[0], cp1[1], cp1[2]);
+ glVertex3d(cp2[0], cp2[1], cp2[2]);
+ glEnd();
+ }
+ glEnable(GL_LIGHTING);
+ glEnable(GL_DEPTH_TEST);
+#endif
+
+ glFlush();
+ glutSwapBuffers();
+}
+
+
+
+
+
+void newRandom() {
+ object.setPosition(MT_Point3(0, 0, 0));
+ object.setOrientation(MT_Quaternion::random());
+ object.clearMomentum();
+ object.setMatrix();
+
+ display();
+}
+
+void moveAndDisplay() {
+ g_scene.proceed(timeStep, 0.01);
+
+ display();
+ g_hit = false;
+}
+
+
+void turn_left() {
+ object.applyTorque(5.0 * object.getUp());
+}
+
+void turn_right() {
+ object.applyTorque(-5.0 * object.getUp());
+}
+
+void forward() {
+ object.applyCenterForce(10.0 * object.getAhead());
+}
+
+void backward() {
+ object.applyCenterForce(-10.0 * object.getAhead());
+}
+
+void jump() {
+ object.applyCenterForce(MT_Vector3(0.0, 200.0, 0.0));
+}
+
+
+void toggleIdle() {
+ static bool idle = true;
+ if (idle) {
+ glutIdleFunc(moveAndDisplay);
+ idle = false;
+ }
+ else {
+ glutIdleFunc(NULL);
+ idle = true;
+ }
+}
+
+
+void setCamera() {
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glFrustum(-1.0, 1.0, -1.0, 1.0, 1.0, 200.0);
+ MT_Scalar rele = MT_radians(ele);
+ MT_Scalar razi = MT_radians(azi);
+ eye.setValue(DISTANCE * sin(razi) * cos(rele),
+ DISTANCE * sin(rele),
+ DISTANCE * cos(razi) * cos(rele));
+ gluLookAt(eye[0], eye[1], eye[2],
+ center[0], center[1], center[2],
+ 0, 1, 0);
+ glMatrixMode(GL_MODELVIEW);
+ display();
+}
+
+const MT_Scalar STEPSIZE = 5;
+
+void stepLeft() { azi -= STEPSIZE; if (azi < 0) azi += 360; setCamera(); }
+void stepRight() { azi += STEPSIZE; if (azi >= 360) azi -= 360; setCamera(); }
+void stepFront() { ele += STEPSIZE; if (azi >= 360) azi -= 360; setCamera(); }
+void stepBack() { ele -= STEPSIZE; if (azi < 0) azi += 360; setCamera(); }
+void zoomIn() { DISTANCE -= 1; setCamera(); }
+void zoomOut() { DISTANCE += 1; setCamera(); }
+
+
+void myReshape(int w, int h) {
+ glViewport(0, 0, w, h);
+ setCamera();
+}
+
+void myKeyboard(unsigned char key, int x, int y)
+{
+ switch (key)
+ {
+ case 'w': forward(); break;
+ case 's': backward(); break;
+ case 'a': turn_left(); break;
+ case 'd': turn_right(); break;
+ case 'e': jump(); break;
+ case 'l' : stepLeft(); break;
+ case 'r' : stepRight(); break;
+ case 'f' : stepFront(); break;
+ case 'b' : stepBack(); break;
+ case 'z' : zoomIn(); break;
+ case 'x' : zoomOut(); break;
+ case 'i' : toggleIdle(); break;
+ case ' ' : newRandom(); break;
+ default:
+// std::cout << "unused key : " << key << std::endl;
+ break;
+ }
+}
+
+void mySpecial(int key, int x, int y)
+{
+ switch (key)
+ {
+ case GLUT_KEY_LEFT : stepLeft(); break;
+ case GLUT_KEY_RIGHT : stepRight(); break;
+ case GLUT_KEY_UP : stepFront(); break;
+ case GLUT_KEY_DOWN : stepBack(); break;
+ case GLUT_KEY_PAGE_UP : zoomIn(); break;
+ case GLUT_KEY_PAGE_DOWN : zoomOut(); break;
+ case GLUT_KEY_HOME : toggleIdle(); break;
+ default:
+// std::cout << "unused (special) key : " << key << std::endl;
+ break;
+ }
+}
+
+void goodbye( void)
+{
+ g_scene.remove(sm_ground);
+ g_scene.remove(sm_sphere);
+
+ std::cout << "goodbye ..." << std::endl;
+ exit(0);
+}
+
+void menu(int choice)
+{
+
+ static int fullScreen = 0;
+ static int px, py, sx, sy;
+
+ switch(choice) {
+ case 1:
+ if (fullScreen == 1) {
+ glutPositionWindow(px,py);
+ glutReshapeWindow(sx,sy);
+ glutChangeToMenuEntry(1,"Full Screen",1);
+ fullScreen = 0;
+ } else {
+ px=glutGet((GLenum)GLUT_WINDOW_X);
+ py=glutGet((GLenum)GLUT_WINDOW_Y);
+ sx=glutGet((GLenum)GLUT_WINDOW_WIDTH);
+ sy=glutGet((GLenum)GLUT_WINDOW_HEIGHT);
+ glutFullScreen();
+ glutChangeToMenuEntry(1,"Close Full Screen",1);
+ fullScreen = 1;
+ }
+ break;
+ case 2:
+ toggleIdle();
+ break;
+ case 3:
+ goodbye();
+ break;
+ default:
+ break;
+ }
+}
+
+void createMenu()
+{
+ glutCreateMenu(menu);
+ glutAddMenuEntry("Full Screen", 1);
+ glutAddMenuEntry("Toggle Idle (Start/Stop)", 2);
+ glutAddMenuEntry("Quit", 3);
+ glutAttachMenu(GLUT_RIGHT_BUTTON);
+}
+
+int main(int argc, char **argv) {
+ glutInit(&argc, argv);
+ glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
+ glutInitWindowPosition(0, 0);
+ glutInitWindowSize(500, 500);
+ glutCreateWindow("Physics demo");
+
+ myinit();
+ glutKeyboardFunc(myKeyboard);
+ glutSpecialFunc(mySpecial);
+ glutReshapeFunc(myReshape);
+ createMenu();
+ glutIdleFunc(NULL);
+
+ glutDisplayFunc(display);
+ glutMainLoop();
+ return 0;
+}
+
+
+
+
+
+
+
diff --git a/source/gameengine/Physics/Sumo/Fuzzics/sample/particle0.cpp b/source/gameengine/Physics/Sumo/Fuzzics/sample/particle0.cpp
new file mode 100644
index 00000000000..1c03621f530
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/Fuzzics/sample/particle0.cpp
@@ -0,0 +1,691 @@
+//#define FAKE_IT
+#define USE_COMPLEX
+#define QUADS
+
+#include <algorithm>
+#include <new>
+#include <GL/glut.h>
+
+#include "MT_MinMax.h"
+#include "MT_Point3.h"
+#include "MT_Vector3.h"
+#include "MT_Quaternion.h"
+#include "MT_Matrix3x3.h"
+#include "MT_Transform.h"
+
+#include "SM_Object.h"
+#include "SM_Scene.h"
+
+#include "solid.h"
+
+const MT_Scalar bowl_curv = 0.10;
+const MT_Scalar timeStep = 0.04;
+const MT_Scalar ground_margin = 0.0;
+const MT_Scalar sphere_radius = 0.5;
+
+const MT_Vector3 gravity(0, -9.8, 0);
+
+static MT_Scalar DISTANCE = 5;
+
+static MT_Scalar ele = 0, azi = 0;
+static MT_Point3 eye(0, 0, DISTANCE);
+static MT_Point3 center(0, 0, 0);
+
+inline double irnd() { return 2 * MT_random() - 1; }
+
+static const double SCALE_BOTTOM = 0.5;
+static const double SCALE_FACTOR = 2.0;
+
+SM_ShapeProps g_shapeProps = {
+ 1.0, // mass
+ 1.0, // inertia
+ 0.9, // linear drag
+ 0.9 // angular drag
+};
+
+SM_MaterialProps g_materialProps = {
+ 0.7, // restitution
+ 0.0, // friction
+ 0.0, // spring constant
+ 0.0 // damping
+};
+
+
+void toggleIdle();
+
+
+void newRandom();
+
+void coordSystem() {
+ glDisable(GL_LIGHTING);
+ glBegin(GL_LINES);
+ glColor3f(1, 0, 0);
+ glVertex3d(0, 0, 0);
+ glVertex3d(10, 0, 0);
+ glColor3f(0, 1, 0);
+ glVertex3d(0, 0, 0);
+ glVertex3d(0, 10, 0);
+ glColor3f(0, 0, 1);
+ glVertex3d(0, 0, 0);
+ glVertex3d(0, 0, 10);
+ glEnd();
+ glEnable(GL_LIGHTING);
+}
+
+
+void display_bbox(const MT_Point3& min, const MT_Point3& max) {
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_LIGHTING);
+ glColor3f(0, 1, 1);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ glBegin(GL_QUAD_STRIP);
+ glVertex3d(min[0], min[1], min[2]);
+ glVertex3d(min[0], min[1], max[2]);
+ glVertex3d(max[0], min[1], min[2]);
+ glVertex3d(max[0], min[1], max[2]);
+ glVertex3d(max[0], max[1], min[2]);
+ glVertex3d(max[0], max[1], max[2]);
+ glVertex3d(min[0], max[1], min[2]);
+ glVertex3d(min[0], max[1], max[2]);
+ glVertex3d(min[0], min[1], min[2]);
+ glVertex3d(min[0], min[1], max[2]);
+ glEnd();
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ glEnable(GL_LIGHTING);
+ glEnable(GL_DEPTH_TEST);
+}
+
+
+
+
+class GLShape {
+public:
+ virtual void paint(GLdouble *m) const = 0;
+};
+
+
+class GLSphere : public GLShape {
+ MT_Scalar radius;
+public:
+ GLSphere(MT_Scalar r) : radius(r) {}
+
+ void paint(GLdouble *m) const {
+ glPushMatrix();
+ glLoadMatrixd(m);
+ coordSystem();
+ glutSolidSphere(radius, 20, 20);
+ glPopMatrix();
+ }
+};
+
+
+class GLBox : public GLShape {
+ MT_Vector3 extent;
+public:
+ GLBox(MT_Scalar x, MT_Scalar y, MT_Scalar z) :
+ extent(x, y, z) {}
+
+ void paint(GLdouble *m) const {
+ glPushMatrix();
+ glLoadMatrixd(m);
+ coordSystem();
+ glPushMatrix();
+ glScaled(extent[0], extent[1], extent[2]);
+ glutSolidCube(1.0);
+ glPopMatrix();
+ glPopMatrix();
+ }
+};
+
+
+class GLCone : public GLShape {
+ MT_Scalar bottomRadius;
+ MT_Scalar height;
+ mutable GLuint displayList;
+
+public:
+ GLCone(MT_Scalar r, MT_Scalar h) :
+ bottomRadius(r),
+ height(h),
+ displayList(0) {}
+
+ void paint(GLdouble *m) const {
+ glPushMatrix();
+ glLoadMatrixd(m);
+ coordSystem();
+ if (displayList) glCallList(displayList);
+ else {
+ GLUquadricObj *quadObj = gluNewQuadric();
+ displayList = glGenLists(1);
+ glNewList(displayList, GL_COMPILE_AND_EXECUTE);
+ glPushMatrix();
+ glRotatef(-90.0, 1.0, 0.0, 0.0);
+ glTranslatef(0.0, 0.0, -1.0);
+ gluQuadricDrawStyle(quadObj, (GLenum)GLU_FILL);
+ gluQuadricNormals(quadObj, (GLenum)GLU_SMOOTH);
+ gluCylinder(quadObj, bottomRadius, 0, height, 15, 10);
+ glPopMatrix();
+ glEndList();
+ }
+ glPopMatrix();
+ }
+};
+
+class GLCylinder : public GLShape {
+ MT_Scalar radius;
+ MT_Scalar height;
+ mutable GLuint displayList;
+
+public:
+ GLCylinder(MT_Scalar r, MT_Scalar h) :
+ radius(r),
+ height(h),
+ displayList(0) {}
+
+ void paint(GLdouble *m) const {
+ glPushMatrix();
+ glLoadMatrixd(m);
+ coordSystem();
+ if (displayList) glCallList(displayList);
+ else {
+ GLUquadricObj *quadObj = gluNewQuadric();
+ displayList = glGenLists(1);
+ glNewList(displayList, GL_COMPILE_AND_EXECUTE);
+ glPushMatrix();
+ glRotatef(-90.0, 1.0, 0.0, 0.0);
+ glTranslatef(0.0, 0.0, -1.0);
+ gluQuadricDrawStyle(quadObj, (GLenum)GLU_FILL);
+ gluQuadricNormals(quadObj, (GLenum)GLU_SMOOTH);
+ gluCylinder(quadObj, radius, radius, height, 15, 10);
+ glPopMatrix ();
+ glEndList();
+ }
+ glPopMatrix();
+ }
+};
+
+class Object;
+
+class Callback : public SM_Callback {
+public:
+ Callback(Object& object) : m_object(object) {}
+
+ virtual void do_me();
+
+private:
+ Object& m_object;
+};
+
+
+class Object {
+public:
+ Object(GLShape *gl_shape, SM_Object& object) :
+ m_gl_shape(gl_shape),
+ m_object(object),
+ m_callback(*this)
+ {
+ m_object.registerCallback(m_callback);
+ }
+
+ ~Object() {}
+
+ void paint() {
+ m_gl_shape->paint(m);
+ // display_bbox(m_bbox.lower(), m_bbox.upper());
+ }
+
+ MT_Vector3 getAhead() {
+ return MT_Vector3(-m[8], -m[9], -m[10]);
+ }
+
+ void clearMomentum() {
+ m_object.clearMomentum();
+ }
+
+ void setMargin(MT_Scalar margin) {
+ m_object.setMargin(margin);
+ }
+
+ void setScaling(const MT_Vector3& scaling) {
+ m_object.setScaling(scaling);
+ }
+
+ void setPosition(const MT_Point3& pos) {
+ m_object.setPosition(pos);
+ }
+
+ void setOrientation(const MT_Quaternion& orn) {
+ m_object.setOrientation(orn);
+ }
+
+ void applyCenterForce(const MT_Vector3& force) {
+ m_object.applyCenterForce(force);
+ }
+
+ void applyTorque(const MT_Vector3& torque) {
+ m_object.applyTorque(torque);
+ }
+
+ MT_Point3 getWorldCoord(const MT_Point3& local) const {
+ return m_object.getWorldCoord(local);
+ }
+
+ MT_Vector3 getLinearVelocity() const {
+ return m_object.getLinearVelocity();
+ }
+
+ void setMatrix() {
+ m_object.getMatrix(m);
+ }
+
+private:
+ GLShape *m_gl_shape;
+ SM_Object& m_object;
+ DT_Scalar m[16];
+ Callback m_callback;
+};
+
+
+void Callback::do_me()
+{
+ m_object.setMatrix();
+}
+
+
+const MT_Scalar SPACE_SIZE = 2;
+
+static GLSphere gl_sphere(sphere_radius);
+static GLBox gl_ground(50.0, 0.0, 50.0);
+
+
+
+#ifdef USE_COMPLEX
+
+const int GRID_SCALE = 10;
+const MT_Scalar GRID_UNIT = 25.0 / GRID_SCALE;
+
+DT_ShapeHandle createComplex() {
+ DT_ShapeHandle shape = DT_NewComplexShape();
+ for (int i0 = -GRID_SCALE; i0 != GRID_SCALE; ++i0) {
+ for (int j0 = -GRID_SCALE; j0 != GRID_SCALE; ++j0) {
+ int i1 = i0 + 1;
+ int j1 = j0 + 1;
+#ifdef QUADS
+ DT_Begin();
+ DT_Vertex(GRID_UNIT * i0, bowl_curv * i0*i0, GRID_UNIT * j0);
+ DT_Vertex(GRID_UNIT * i0, bowl_curv * i0*i0, GRID_UNIT * j1);
+ DT_Vertex(GRID_UNIT * i1, bowl_curv * i1*i1, GRID_UNIT * j1);
+ DT_Vertex(GRID_UNIT * i1, bowl_curv * i1*i1, GRID_UNIT * j0);
+ DT_End();
+#else
+ DT_Begin();
+ DT_Vertex(GRID_UNIT * i0, 0, GRID_UNIT * j0);
+ DT_Vertex(GRID_UNIT * i0, 0, GRID_UNIT * j1);
+ DT_Vertex(GRID_UNIT * i1, 0, GRID_UNIT * j1);
+ DT_End();
+
+ DT_Begin();
+ DT_Vertex(GRID_UNIT * i0, 0, GRID_UNIT * j1);
+ DT_Vertex(GRID_UNIT * i1, 0, GRID_UNIT * j1);
+ DT_Vertex(GRID_UNIT * i1, 0, GRID_UNIT * j0);
+ DT_End();
+#endif
+
+ }
+ }
+ DT_EndComplexShape();
+ return shape;
+}
+
+
+static DT_ShapeHandle ground_shape = createComplex();
+
+#else
+
+static DT_ShapeHandle ground_shape = DT_Box(50, 0, 50);
+
+#endif
+
+static SM_Object sm_ground(ground_shape, &g_materialProps, 0, 0);
+static Object ground(&gl_ground, sm_ground);
+
+static SM_Object sm_sphere(DT_Sphere(0.0), &g_materialProps, &g_shapeProps, 0);
+static Object object(&gl_sphere, sm_sphere);
+
+
+static SM_Object sm_ray(DT_Ray(0.0, -1.0, 0.0), 0, 0, 0);
+
+static SM_Scene g_scene;
+
+
+void myinit(void) {
+
+ GLfloat light_ambient[] = { 0.0, 0.0, 0.0, 1.0 };
+ GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
+ GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 };
+
+ /* light_position is NOT default value */
+ GLfloat light_position0[] = { 1.0, 1.0, 1.0, 0.0 };
+ GLfloat light_position1[] = { -1.0, -1.0, -1.0, 0.0 };
+
+ glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
+ glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
+ glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
+ glLightfv(GL_LIGHT0, GL_POSITION, light_position0);
+
+ glLightfv(GL_LIGHT1, GL_AMBIENT, light_ambient);
+ glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse);
+ glLightfv(GL_LIGHT1, GL_SPECULAR, light_specular);
+ glLightfv(GL_LIGHT1, GL_POSITION, light_position1);
+
+
+ glEnable(GL_LIGHTING);
+ glEnable(GL_LIGHT0);
+ glEnable(GL_LIGHT1);
+
+ glShadeModel(GL_SMOOTH);
+
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_LESS);
+
+ // glEnable(GL_CULL_FACE);
+ // glCullFace(GL_BACK);
+
+ g_scene.setForceField(gravity);
+ g_scene.add(sm_ground);
+ sm_ground.setMargin(ground_margin);
+
+ new(&object) Object(&gl_sphere, sm_sphere);
+
+
+ object.setMargin(sphere_radius);
+
+ g_scene.add(sm_sphere);
+
+ ground.setPosition(MT_Point3(0, -10, 0));
+ ground.setOrientation(MT_Quaternion(0, 0, 0, 1));
+ ground.setMatrix();
+ center.setValue(0.0, 0.0, 0.0);
+
+ newRandom();
+}
+
+
+//MT_Point3 cp1, cp2;
+//bool intersection;
+
+bool g_hit = false;
+MT_Point3 g_spot;
+MT_Vector3 g_normal;
+
+
+void display(void) {
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ ground.paint();
+ object.paint();
+
+ if (g_hit) {
+ glPointSize(5);
+ glBegin(GL_POINTS);
+ glVertex3d(g_spot[0], g_spot[1], g_spot[2]);
+ glEnd();
+ glPointSize(1);
+ }
+
+
+
+#ifdef COLLISION
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_LIGHTING);
+ glColor3f(1, 1, 0);
+ if (intersection) {
+ glPointSize(5);
+ glBegin(GL_POINTS);
+ glVertex3d(cp1[0], cp1[1], cp1[2]);
+ glEnd();
+ glPointSize(1);
+ }
+ else {
+ glBegin(GL_LINES);
+ glVertex3d(cp1[0], cp1[1], cp1[2]);
+ glVertex3d(cp2[0], cp2[1], cp2[2]);
+ glEnd();
+ }
+ glEnable(GL_LIGHTING);
+ glEnable(GL_DEPTH_TEST);
+#endif
+
+ glFlush();
+ glutSwapBuffers();
+}
+
+
+
+
+
+void newRandom() {
+ object.setPosition(MT_Point3(0, 0, 0));
+ object.clearMomentum();
+ object.setMatrix();
+
+ display();
+}
+
+void moveAndDisplay() {
+ g_scene.proceed(timeStep, 0.01);
+
+ MT_Vector3 normal(0, 1, 0);
+
+ MT_Point3 from = object.getWorldCoord(MT_Point3(0, 0, 0));
+ MT_Point3 to = from - normal * 10.0;
+
+ g_hit = DT_ObjectRayTest(sm_ground.getObjectHandle(),
+ from.getValue(),
+ to.getValue(), g_spot.getValue(),
+ g_normal.getValue());
+
+ // Scrap
+#define DO_FH
+#ifdef DO_FH
+ MT_Scalar dist = MT_distance(from, g_spot);
+ if (dist < 5.0) {
+ MT_Vector3 lin_vel = object.getLinearVelocity();
+ MT_Scalar lin_vel_normal = lin_vel.dot(normal);
+
+ MT_Scalar spring_extent = dist + lin_vel_normal * (timeStep * 0.5);
+
+ MT_Scalar f_spring = (5.0 - spring_extent) * 3.0;
+ object.applyCenterForce(normal * f_spring);
+ object.applyCenterForce(-lin_vel_normal * normal);
+ }
+
+#endif
+
+
+ display();
+}
+
+
+void turn_left() {
+ object.applyTorque(MT_Vector3(0.0, 10.0, 0.0));
+}
+
+void turn_right() {
+ object.applyTorque(MT_Vector3(0.0, -10.0, 0.0));
+}
+
+void forward() {
+ object.applyCenterForce(20.0 * object.getAhead());
+}
+
+void backward() {
+ object.applyCenterForce(-20.0 * object.getAhead());
+}
+
+void jump() {
+ object.applyCenterForce(MT_Vector3(0.0, 200.0, 0.0));
+}
+
+
+void toggleIdle() {
+ static bool idle = true;
+ if (idle) {
+ glutIdleFunc(moveAndDisplay);
+ idle = false;
+ }
+ else {
+ glutIdleFunc(NULL);
+ idle = true;
+ }
+}
+
+
+void setCamera() {
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glFrustum(-1.0, 1.0, -1.0, 1.0, 1.0, 200.0);
+ MT_Scalar rele = MT_radians(ele);
+ MT_Scalar razi = MT_radians(azi);
+ eye.setValue(DISTANCE * sin(razi) * cos(rele),
+ DISTANCE * sin(rele),
+ DISTANCE * cos(razi) * cos(rele));
+ gluLookAt(eye[0], eye[1], eye[2],
+ center[0], center[1], center[2],
+ 0, 1, 0);
+ glMatrixMode(GL_MODELVIEW);
+ display();
+}
+
+const MT_Scalar STEPSIZE = 5;
+
+void stepLeft() { azi -= STEPSIZE; if (azi < 0) azi += 360; setCamera(); }
+void stepRight() { azi += STEPSIZE; if (azi >= 360) azi -= 360; setCamera(); }
+void stepFront() { ele += STEPSIZE; if (azi >= 360) azi -= 360; setCamera(); }
+void stepBack() { ele -= STEPSIZE; if (azi < 0) azi += 360; setCamera(); }
+void zoomIn() { DISTANCE -= 1; setCamera(); }
+void zoomOut() { DISTANCE += 1; setCamera(); }
+
+
+void myReshape(int w, int h) {
+ glViewport(0, 0, w, h);
+ setCamera();
+}
+
+void myKeyboard(unsigned char key, int x, int y)
+{
+ switch (key)
+ {
+ case 'w': forward(); break;
+ case 's': backward(); break;
+ case 'a': turn_left(); break;
+ case 'd': turn_right(); break;
+ case 'e': jump(); break;
+ case 'l' : stepLeft(); break;
+ case 'r' : stepRight(); break;
+ case 'f' : stepFront(); break;
+ case 'b' : stepBack(); break;
+ case 'z' : zoomIn(); break;
+ case 'x' : zoomOut(); break;
+ case 'i' : toggleIdle(); break;
+ case ' ' : newRandom(); break;
+ default:
+// std::cout << "unused key : " << key << std::endl;
+ break;
+ }
+}
+
+void mySpecial(int key, int x, int y)
+{
+ switch (key)
+ {
+ case GLUT_KEY_LEFT : stepLeft(); break;
+ case GLUT_KEY_RIGHT : stepRight(); break;
+ case GLUT_KEY_UP : stepFront(); break;
+ case GLUT_KEY_DOWN : stepBack(); break;
+ case GLUT_KEY_PAGE_UP : zoomIn(); break;
+ case GLUT_KEY_PAGE_DOWN : zoomOut(); break;
+ case GLUT_KEY_HOME : toggleIdle(); break;
+ default:
+// std::cout << "unused (special) key : " << key << std::endl;
+ break;
+ }
+}
+
+void goodbye( void)
+{
+ g_scene.remove(sm_ground);
+ g_scene.remove(sm_sphere);
+
+ std::cout << "goodbye ..." << std::endl;
+ exit(0);
+}
+
+void menu(int choice)
+{
+
+ static int fullScreen = 0;
+ static int px, py, sx, sy;
+
+ switch(choice) {
+ case 1:
+ if (fullScreen == 1) {
+ glutPositionWindow(px,py);
+ glutReshapeWindow(sx,sy);
+ glutChangeToMenuEntry(1,"Full Screen",1);
+ fullScreen = 0;
+ } else {
+ px=glutGet((GLenum)GLUT_WINDOW_X);
+ py=glutGet((GLenum)GLUT_WINDOW_Y);
+ sx=glutGet((GLenum)GLUT_WINDOW_WIDTH);
+ sy=glutGet((GLenum)GLUT_WINDOW_HEIGHT);
+ glutFullScreen();
+ glutChangeToMenuEntry(1,"Close Full Screen",1);
+ fullScreen = 1;
+ }
+ break;
+ case 2:
+ toggleIdle();
+ break;
+ case 3:
+ goodbye();
+ break;
+ default:
+ break;
+ }
+}
+
+void createMenu()
+{
+ glutCreateMenu(menu);
+ glutAddMenuEntry("Full Screen", 1);
+ glutAddMenuEntry("Toggle Idle (Start/Stop)", 2);
+ glutAddMenuEntry("Quit", 3);
+ glutAttachMenu(GLUT_RIGHT_BUTTON);
+}
+
+int main(int argc, char **argv) {
+ glutInit(&argc, argv);
+ glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
+ glutInitWindowPosition(0, 0);
+ glutInitWindowSize(500, 500);
+ glutCreateWindow("Physics demo");
+
+ myinit();
+ glutKeyboardFunc(myKeyboard);
+ glutSpecialFunc(mySpecial);
+ glutReshapeFunc(myReshape);
+ createMenu();
+ glutIdleFunc(NULL);
+
+ glutDisplayFunc(display);
+ glutMainLoop();
+ return 0;
+}
+
+
+
+
+
+
+
diff --git a/source/gameengine/Physics/Sumo/Fuzzics/src/Makefile b/source/gameengine/Physics/Sumo/Fuzzics/src/Makefile
new file mode 100644
index 00000000000..5e3b35f6cf4
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/Fuzzics/src/Makefile
@@ -0,0 +1,13 @@
+#
+# $Id$
+# Copyright (C) 2001 NaN Technologies B.V.
+
+LIBNAME = fuzzics
+DIR = $(OCGDIR)/sumo
+
+include nan_compile.mk
+
+CCFLAGS += $(LEVEL_1_CPP_WARNINGS)
+
+CPPFLAGS += -I../include -I$(NAN_MOTO)/include -I../../include
+
diff --git a/source/gameengine/Physics/Sumo/Fuzzics/src/SM_FhObject.cpp b/source/gameengine/Physics/Sumo/Fuzzics/src/SM_FhObject.cpp
new file mode 100644
index 00000000000..f8be49aa126
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/Fuzzics/src/SM_FhObject.cpp
@@ -0,0 +1,115 @@
+#include "SM_FhObject.h"
+#include "MT_MinMax.h"
+
+void SM_FhObject::ray_hit(void *client_data,
+ void *client_object1,
+ void *client_object2,
+ const DT_CollData *coll_data) {
+
+ SM_Object *hit_object = (SM_Object *)client_object1;
+ const SM_MaterialProps *matProps = hit_object->getMaterialProps();
+
+ if ((matProps == 0) || (matProps->m_fh_distance < MT_EPSILON)) {
+ return;
+ }
+
+ SM_FhObject *fh_object = (SM_FhObject *)client_object2;
+ SM_Object *cl_object = fh_object->getClientObject();
+
+ if (hit_object == cl_object) {
+ // Shot myself in the foot...
+ return;
+ }
+
+ const SM_ShapeProps *shapeProps = cl_object->getShapeProps();
+
+ // Exit if the client object is not dynamic.
+ if (shapeProps == 0) {
+ return;
+ }
+
+ MT_Point3 lspot;
+ MT_Vector3 normal;
+
+ if (DT_ObjectRayTest(hit_object->getObjectHandle(),
+ fh_object->getPosition().getValue(),
+ fh_object->getSpot().getValue(),
+ lspot.getValue(), normal.getValue())) {
+
+ const MT_Vector3& ray_dir = fh_object->getRayDirection();
+ MT_Scalar dist = MT_distance(fh_object->getPosition(),
+ hit_object->getWorldCoord(lspot)) -
+ cl_object->getMargin();
+
+ normal.normalize();
+
+ if (dist < matProps->m_fh_distance) {
+
+ if (shapeProps->m_do_fh) {
+ MT_Vector3 rel_vel = cl_object->getLinearVelocity() - hit_object->getVelocity(lspot);
+ MT_Scalar rel_vel_ray = ray_dir.dot(rel_vel);
+ MT_Scalar spring_extent = 1.0 - dist / matProps->m_fh_distance;
+
+ MT_Scalar i_spring = spring_extent * matProps->m_fh_spring;
+ MT_Scalar i_damp = rel_vel_ray * matProps->m_fh_damping;
+
+ cl_object->addLinearVelocity(-(i_spring + i_damp) * ray_dir);
+ if (matProps->m_fh_normal) {
+ cl_object->addLinearVelocity(
+ (i_spring + i_damp) *
+ (normal - normal.dot(ray_dir) * ray_dir));
+ }
+
+ MT_Vector3 lateral = rel_vel - rel_vel_ray * ray_dir;
+ const SM_ShapeProps *shapeProps = cl_object->getShapeProps();
+
+ if (shapeProps->m_do_anisotropic) {
+ MT_Matrix3x3 lcs(cl_object->getOrientation());
+ MT_Vector3 loc_lateral = lateral * lcs;
+ const MT_Vector3& friction_scaling =
+ shapeProps->m_friction_scaling;
+
+ loc_lateral.scale(friction_scaling[0],
+ friction_scaling[1],
+ friction_scaling[2]);
+ lateral = lcs * loc_lateral;
+ }
+
+
+ MT_Scalar rel_vel_lateral = lateral.length();
+
+ if (rel_vel_lateral > MT_EPSILON) {
+ MT_Scalar friction_factor = matProps->m_friction;
+ MT_Scalar max_friction = friction_factor * MT_max(0.0, i_spring);
+
+ MT_Scalar rel_mom_lateral = rel_vel_lateral /
+ cl_object->getInvMass();
+
+ MT_Vector3 friction =
+ (rel_mom_lateral > max_friction) ?
+ -lateral * (max_friction / rel_vel_lateral) :
+ -lateral;
+
+ cl_object->applyCenterImpulse(friction);
+ }
+ }
+
+ if (shapeProps->m_do_rot_fh) {
+ const double *ogl_mat = cl_object->getMatrix();
+ MT_Vector3 up(&ogl_mat[8]);
+ MT_Vector3 t_spring = up.cross(normal) * matProps->m_fh_spring;
+ MT_Vector3 ang_vel = cl_object->getAngularVelocity();
+
+ // only rotations that tilt relative to the normal are damped
+ ang_vel -= ang_vel.dot(normal) * normal;
+
+ MT_Vector3 t_damp = ang_vel * matProps->m_fh_damping;
+
+ cl_object->addAngularVelocity(t_spring - t_damp);
+ }
+ }
+ }
+}
+
+
+
diff --git a/source/gameengine/Physics/Sumo/Fuzzics/src/SM_Object.cpp b/source/gameengine/Physics/Sumo/Fuzzics/src/SM_Object.cpp
new file mode 100644
index 00000000000..655590c2086
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/Fuzzics/src/SM_Object.cpp
@@ -0,0 +1,953 @@
+/**
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * The basic physics object.
+ */
+
+#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
+
+#include "SM_Object.h"
+#include "SM_Scene.h"
+#include "SM_FhObject.h"
+
+#include "MT_MinMax.h"
+
+
+// Tweak parameters
+static MT_Scalar ImpulseThreshold = 0.5;
+
+SM_Object::SM_Object(
+ DT_ShapeHandle shape,
+ const SM_MaterialProps *materialProps,
+ const SM_ShapeProps *shapeProps,
+ SM_Object *dynamicParent
+) :
+ m_shape(shape),
+ m_materialProps(materialProps),
+ m_materialPropsBackup(0),
+ m_shapeProps(shapeProps),
+ m_shapePropsBackup(0),
+ m_dynamicParent(dynamicParent),
+ m_object(DT_CreateObject(this, shape)),
+ m_margin(0.0),
+ m_scaling(1.0, 1.0, 1.0),
+ m_reaction_impulse(0.0, 0.0, 0.0),
+ m_reaction_force(0.0, 0.0, 0.0),
+ m_kinematic(false),
+ m_prev_kinematic(false),
+ m_is_rigid_body(false),
+ m_lin_mom(0.0, 0.0, 0.0),
+ m_ang_mom(0.0, 0.0, 0.0),
+ m_force(0.0, 0.0, 0.0),
+ m_torque(0.0, 0.0, 0.0),
+ m_client_object(0),
+ m_fh_object(0),
+
+ m_combined_lin_vel (0.0, 0.0, 0.0),
+ m_combined_ang_vel (0.0, 0.0, 0.0)
+{
+ m_xform.setIdentity();
+ m_xform.getValue(m_ogl_matrix);
+ if (shapeProps &&
+ (shapeProps->m_do_fh || shapeProps->m_do_rot_fh)) {
+ MT_Vector3 ray(0.0, 0.0, -10.0);
+ m_fh_object = new SM_FhObject(ray, this);
+ }
+ m_suspended = false;
+}
+
+
+ void
+SM_Object::
+integrateForces(
+ MT_Scalar timeStep
+){
+ if (!m_suspended) {
+ m_prev_state = *this;
+ m_prev_state.setLinearVelocity(actualLinVelocity());
+ m_prev_state.setAngularVelocity(actualAngVelocity());
+ if (isDynamic()) {
+ // Integrate momentum (forward Euler)
+ m_lin_mom += m_force * timeStep;
+ m_ang_mom += m_torque * timeStep;
+ // Drain momentum because of air/water resistance
+ m_lin_mom *= pow(m_shapeProps->m_lin_drag, timeStep);
+ m_ang_mom *= pow(m_shapeProps->m_ang_drag, timeStep);
+ // Set velocities according momentum
+ m_lin_vel = m_lin_mom / m_shapeProps->m_mass;
+ m_ang_vel = m_ang_mom / m_shapeProps->m_inertia;
+ }
+ }
+
+};
+
+ void
+SM_Object::
+integrateMomentum(
+ MT_Scalar timeStep
+){
+ // Integrate position and orientation
+
+ // only do it for objects with linear and/or angular velocity
+ // else clients with hierarchies may get into trouble
+ if (!actualLinVelocity().fuzzyZero() || !actualAngVelocity().fuzzyZero())
+ {
+
+ // those MIDPOINT and BACKWARD integration methods are
+ // in this form not ok with some testfiles !
+ // For a release build please use forward euler unless completely tested
+[
+//#define MIDPOINT
+//#define BACKWARD
+#ifdef MIDPOINT
+// Midpoint rule
+ m_pos += (m_prev_state.getLinearVelocity() + actualLinVelocity()) * (timeStep * 0.5);
+ m_orn += (m_prev_state.getAngularVelocity() * m_prev_state.getOrientation() + actualAngVelocity() * m_orn) * (timeStep * 0.25);
+#elif defined BACKWARD
+// Backward Euler
+ m_pos += actualLinVelocity() * timeStep;
+ m_orn += actualAngVelocity() * m_orn * (timeStep * 0.5);
+#else
+// Forward Euler
+
+ m_pos += m_prev_state.getLinearVelocity() * timeStep;
+ m_orn += m_prev_state.getAngularVelocity() * m_orn * (timeStep * 0.5);
+#endif
+ m_orn.normalize(); // I might not be necessary to do this every call
+
+ calcXform();
+ notifyClient();
+
+ }
+}
+
+
+void SM_Object::boing(
+ void *client_data,
+ void *object1,
+ void *object2,
+ const DT_CollData *coll_data
+){
+ SM_Scene *scene = (SM_Scene *)client_data;
+ SM_Object *obj1 = (SM_Object *)object1;
+ SM_Object *obj2 = (SM_Object *)object2;
+
+ scene->addPair(obj1, obj2); // Record this collision for client callbacks
+
+
+ // If one of the objects is a ghost then ignore it for the dynamics
+ if (obj1->isGhost() || obj2->isGhost()) {
+ return;
+ }
+
+
+ if (!obj2->isDynamic()) {
+ std::swap(obj1, obj2);
+ }
+
+ if (!obj2->isDynamic()) {
+ return;
+ }
+
+ // obj1 points to a dynamic object
+
+
+ // This distinction between dynamic and non-dynamic objects should not be
+ // necessary. Non-dynamic objects are assumed to have infinite mass.
+
+ if (obj1->isDynamic()) {
+ // normal to the contact plane
+ MT_Vector3 normal = obj2->m_pos - obj1->m_pos;
+ MT_Scalar dist = normal.length();
+
+ if (MT_EPSILON < dist && dist <= obj1->getMargin() + obj2->getMargin())
+ {
+ normal /= dist;
+ // relative velocity of the contact points
+ MT_Vector3 rel_vel = obj2->actualLinVelocity() - obj1->actualLinVelocity();
+ // relative velocity projected onto the normal
+ MT_Scalar rel_vel_normal = normal.dot(rel_vel);
+
+ // if the objects are approaching eachother...
+ if (rel_vel_normal < 0.0) {
+ MT_Scalar restitution;
+ // ...and the approaching velocity is large enough...
+ if (-rel_vel_normal > ImpulseThreshold) {
+ // ...this must be a true collision.
+ restitution =
+ MT_min(obj1->getMaterialProps()->m_restitution,
+ obj2->getMaterialProps()->m_restitution);
+ }
+ else {
+ // otherwise, it is a resting contact, and thus the
+ // relative velocity must be made zero
+ restitution = 0.0;
+ // We also need to interfere with the positions of the
+ // objects, otherwise they might drift into eachother.
+ MT_Vector3 penalty = normal *
+ (0.5 * (obj1->getMargin() + obj2->getMargin() - dist));
+ obj1->m_pos -= penalty;
+ obj2->m_pos += penalty;
+ }
+
+ // Compute the impulse necessary to yield the desired relative velocity...
+ MT_Scalar impulse = -(1.0 + restitution) * rel_vel_normal /
+ (obj1->getInvMass() + obj2->getInvMass());
+
+ // ... and apply it.
+ obj1->applyCenterImpulse(-impulse * normal);
+ obj2->applyCenterImpulse( impulse * normal);
+ }
+ }
+ }
+ else {
+ // Same again but now obj1 is non-dynamic
+
+ // Compute the point on obj1 closest to obj2 (= sphere with radius = 0)
+ MT_Point3 local1, local2;
+ MT_Scalar dist = DT_GetClosestPair(obj1->m_object, obj2->m_object,
+ local1.getValue(), local2.getValue());
+
+ // local1 is th point closest to obj2
+ // local2 is the local origin of obj2
+
+ if (MT_EPSILON < dist && dist <= obj2->getMargin()) {
+ MT_Point3 world1 = obj1->getWorldCoord(local1);
+ MT_Point3 world2 = obj2->getWorldCoord(local2);
+ MT_Vector3 vel1 = obj1->getVelocity(local1) + obj1->m_combined_lin_vel;
+ MT_Vector3 vel2 = obj2->getVelocity(local2) + obj2->m_combined_lin_vel;
+
+ // the normal to the contact plane
+ MT_Vector3 normal = world2 - world1;
+ normal /= dist;
+
+ // wr2 points from obj2's origin to the global contact point
+ // wr2 is only needed for rigid bodies (objects for which the
+ // friction can change the angular momentum).
+ // vel2 is adapted to denote the velocity of the contact point
+ MT_Vector3 wr2;
+ if (obj2->isRigidBody()) {
+ wr2 = -obj2->getMargin() * normal;
+ vel2 += obj2->actualAngVelocity().cross(wr2);
+ }
+
+
+ // This should look familiar....
+ MT_Vector3 rel_vel = vel2 - vel1;
+ MT_Scalar rel_vel_normal = normal.dot(rel_vel);
+
+ if (rel_vel_normal < 0.0) {
+ MT_Scalar restitution;
+ if (-rel_vel_normal > ImpulseThreshold) {
+ restitution =
+ MT_min(obj1->getMaterialProps()->m_restitution,
+ obj2->getMaterialProps()->m_restitution);
+ }
+ else {
+ restitution = 0.0;
+ // We fix drift by moving obj2 only, since obj1 was
+ // non-dynamic.
+ obj2->m_pos += normal * (obj2->getMargin() - dist);
+
+ }
+
+ MT_Scalar impulse = -(1.0 + restitution) * rel_vel_normal /
+ (obj1->getInvMass() + obj2->getInvMass());
+
+
+ obj2->applyCenterImpulse( impulse * normal);
+
+// The friction part starts here!!!!!!!!
+
+ // Compute the lateral component of the relative velocity
+ // lateral actually points in the opposite direction, i.e.,
+ // into the direction of the friction force.
+
+#if 1
+ // test - only do friction on the physics part of the
+ // velocity.
+ vel1 -= obj1->m_combined_lin_vel;
+ vel2 -= obj2->m_combined_lin_vel;
+
+ // This should look familiar....
+ rel_vel = vel2 - vel1;
+ rel_vel_normal = normal.dot(rel_vel);
+#endif
+
+ MT_Vector3 lateral = normal * rel_vel_normal - rel_vel;
+
+ const SM_ShapeProps *shapeProps = obj2->getShapeProps();
+
+ if (shapeProps->m_do_anisotropic) {
+
+ // For anisotropic friction we scale the lateral component,
+ // rather than compute a direction-dependent fricition
+ // factor. For this the lateral component is transformed to
+ // local coordinates.
+
+ MT_Matrix3x3 lcs(obj2->m_orn);
+ // We cannot use m_xform.getBasis() for the matrix, since
+ // it might contain a non-uniform scaling.
+ // OPT: it's a bit daft to compute the matrix since the
+ // quaternion itself can be used to do the transformation.
+
+ MT_Vector3 loc_lateral = lateral * lcs;
+ // lcs is orthogonal so lcs.inversed() == lcs.transposed(),
+ // and lcs.transposed() * lateral == lateral * lcs.
+
+ const MT_Vector3& friction_scaling =
+ shapeProps->m_friction_scaling;
+
+ // Scale the local lateral...
+ loc_lateral.scale(friction_scaling[0],
+ friction_scaling[1],
+ friction_scaling[2]);
+ // ... and transform it back to global coordinates
+ lateral = lcs * loc_lateral;
+ }
+
+ // A tiny Coulomb friction primer:
+ // The Coulomb friction law states that the magnitude of the
+ // maximum possible friction force depends linearly on the
+ // magnitude of the normal force.
+ //
+ // F_max_friction = friction_factor * F_normal
+ //
+ // (NB: independent of the contact area!!)
+ //
+ // The friction factor depends on the material.
+ // We use impulses rather than forces but let us not be
+ // bothered by this.
+
+
+ MT_Scalar rel_vel_lateral = lateral.length();
+
+ if (rel_vel_lateral > MT_EPSILON) {
+ lateral /= rel_vel_lateral;
+
+ MT_Scalar friction_factor =
+ MT_min(obj1->getMaterialProps()->m_friction,
+ obj2->getMaterialProps()->m_friction);
+
+ // Compute the maximum friction impulse
+
+ MT_Scalar max_friction =
+ friction_factor * MT_max(0.0, impulse);
+
+ // I guess the GEN_max is not necessary, so let's check it
+
+ assert(impulse >= 0.0);
+
+ // Here's the trick. We compute the impulse to make the
+ // lateral velocity zero. (Make the objects stick together
+ // at the contact point. If this impulse is larger than
+ // the maximum possible friction impulse, then shrink its
+ // magnitude to the maximum friction.
+
+ if (obj2->isRigidBody()) {
+
+ // For rigid bodies we take the inertia into account,
+ // since the friciton impulse is going to change the
+ // angular momentum as well.
+ MT_Scalar impulse_lateral = rel_vel_lateral /
+ (obj1->getInvMass() + obj2->getInvMass() +
+ ((obj2->getInvInertia() * wr2.cross(lateral)).cross(wr2)).dot(lateral));
+ MT_Scalar friction = MT_min(impulse_lateral, max_friction);
+ obj2->applyImpulse(world2 + wr2, friction * lateral);
+ }
+ else {
+ MT_Scalar impulse_lateral = rel_vel_lateral /
+ (obj1->getInvMass() + obj2->getInvMass());
+
+ MT_Scalar friction = MT_min(impulse_lateral, max_friction);
+ obj2->applyCenterImpulse( friction * lateral);
+ }
+ }
+
+ obj2->calcXform();
+ obj2->notifyClient();
+ }
+ }
+ }
+}
+
+
+
+SM_Object::SM_Object(
+) {
+ // warning no initialization of variables done by moto.
+}
+
+SM_Object::
+~SM_Object() {
+ delete m_fh_object;
+ DT_DeleteObject(m_object);
+}
+
+ bool
+SM_Object::
+isDynamic(
+) const {
+ return m_shapeProps != 0;
+}
+
+/* nzc experimental. There seem to be two places where kinematics
+ * are evaluated: proceedKinematic (called from SM_Scene) and
+ * proceed() in this object. I'll just try and bunge these out for
+ * now. */
+ void
+SM_Object::
+suspend(
+){
+ if (!m_suspended) {
+ m_suspended = true;
+ suspendDynamics();
+ }
+}
+
+ void
+SM_Object::
+resume(
+) {
+ if (m_suspended) {
+ m_suspended = false;
+ restoreDynamics();
+ }
+}
+
+ void
+SM_Object::
+suspendDynamics(
+) {
+ if (m_shapeProps) {
+ m_shapePropsBackup = m_shapeProps;
+ m_shapeProps = 0;
+ }
+}
+
+ void
+SM_Object::
+restoreDynamics(
+) {
+ if (m_shapePropsBackup) {
+ m_shapeProps = m_shapePropsBackup;
+ m_shapePropsBackup = 0;
+ }
+}
+
+ bool
+SM_Object::
+isGhost(
+) const {
+ return m_materialProps == 0;
+}
+
+ void
+SM_Object::
+suspendMaterial(
+) {
+ if (m_materialProps) {
+ m_materialPropsBackup = m_materialProps;
+ m_materialProps = 0;
+ }
+}
+
+ void
+SM_Object::
+restoreMaterial(
+) {
+ if (m_materialPropsBackup) {
+ m_materialProps = m_materialPropsBackup;
+ m_materialPropsBackup = 0;
+ }
+}
+
+ SM_FhObject *
+SM_Object::
+getFhObject(
+) const {
+ return m_fh_object;
+}
+
+ void
+SM_Object::
+registerCallback(
+ SM_Callback& callback
+) {
+ m_callbackList.push_back(&callback);
+}
+
+// Set the local coordinate system according to the current state
+ void
+SM_Object::
+calcXform() {
+ m_xform.setOrigin(m_pos);
+ m_xform.setBasis(MT_Matrix3x3(m_orn, m_scaling));
+ m_xform.getValue(m_ogl_matrix);
+ DT_SetMatrixd(m_object, m_ogl_matrix);
+ if (m_fh_object) {
+ m_fh_object->setPosition(m_pos);
+ m_fh_object->calcXform();
+ }
+}
+
+// Call callbacks to notify the client of a change of placement
+ void
+SM_Object::
+notifyClient() {
+ T_CallbackList::iterator i;
+ for (i = m_callbackList.begin(); i != m_callbackList.end(); ++i) {
+ (*i)->do_me();
+ }
+}
+
+
+// Save the current state information for use in the velocity computation in the next frame.
+ void
+SM_Object::
+proceedKinematic(
+ MT_Scalar timeStep
+) {
+ /* nzc: need to bunge this for the logic bubbling as well? */
+ if (!m_suspended) {
+ m_prev_kinematic = m_kinematic;
+ if (m_kinematic) {
+ m_prev_xform = m_xform;
+ m_timeStep = timeStep;
+ calcXform();
+ m_kinematic = false;
+ }
+ }
+}
+
+ void
+SM_Object::
+saveReactionForce(
+ MT_Scalar timeStep
+) {
+ if (isDynamic()) {
+ m_reaction_force = m_reaction_impulse / timeStep;
+ m_reaction_impulse.setValue(0.0, 0.0, 0.0);
+ }
+}
+
+ void
+SM_Object::
+clearForce(
+) {
+ m_force.setValue(0.0, 0.0, 0.0);
+ m_torque.setValue(0.0, 0.0, 0.0);
+}
+
+ void
+SM_Object::
+clearMomentum(
+) {
+ m_lin_mom.setValue(0.0, 0.0, 0.0);
+ m_ang_mom.setValue(0.0, 0.0, 0.0);
+}
+
+ void
+SM_Object::
+setMargin(
+ MT_Scalar margin
+) {
+ m_margin = margin;
+ DT_SetMargin(m_object, margin);
+}
+
+ MT_Scalar
+SM_Object::
+getMargin(
+) const {
+ return m_margin;
+}
+
+const
+ SM_MaterialProps *
+SM_Object::
+getMaterialProps(
+) const {
+ return m_materialProps;
+}
+
+const
+ SM_ShapeProps *
+SM_Object::
+getShapeProps(
+) const {
+ return m_shapeProps;
+}
+
+ void
+SM_Object::
+setPosition(
+ const MT_Point3& pos
+){
+ m_kinematic = true;
+ m_pos = pos;
+}
+
+ void
+SM_Object::
+setOrientation(
+ const MT_Quaternion& orn
+){
+ assert(!orn.fuzzyZero());
+ m_kinematic = true;
+ m_orn = orn;
+}
+
+ void
+SM_Object::
+setScaling(
+ const MT_Vector3& scaling
+){
+ m_kinematic = true;
+ m_scaling = scaling;
+}
+
+/**
+ * Functions to handle linear velocity
+ */
+
+ void
+SM_Object::
+setExternalLinearVelocity(
+ const MT_Vector3& lin_vel
+) {
+ m_combined_lin_vel=lin_vel;
+}
+
+ void
+SM_Object::
+addExternalLinearVelocity(
+ const MT_Vector3& lin_vel
+) {
+ m_combined_lin_vel+=lin_vel;
+}
+
+ void
+SM_Object::
+addLinearVelocity(
+ const MT_Vector3& lin_vel
+){
+ m_lin_vel += lin_vel;
+ if (m_shapeProps) {
+ m_lin_mom = m_lin_vel * m_shapeProps->m_mass;
+ }
+}
+
+ void
+SM_Object::
+setLinearVelocity(
+ const MT_Vector3& lin_vel
+){
+ m_lin_vel = lin_vel;
+ if (m_shapeProps) {
+ m_lin_mom = m_lin_vel * m_shapeProps->m_mass;
+ }
+}
+
+/**
+ * Functions to handle angular velocity
+ */
+
+ void
+SM_Object::
+setExternalAngularVelocity(
+ const MT_Vector3& ang_vel
+) {
+ m_combined_ang_vel = ang_vel;
+}
+
+ void
+SM_Object::
+addExternalAngularVelocity(
+ const MT_Vector3& ang_vel
+) {
+ m_combined_ang_vel += ang_vel;
+}
+
+ void
+SM_Object::
+setAngularVelocity(
+ const MT_Vector3& ang_vel
+) {
+ m_ang_vel = ang_vel;
+ if (m_shapeProps) {
+ m_ang_mom = m_ang_vel * m_shapeProps->m_inertia;
+ }
+}
+
+ void
+SM_Object::
+addAngularVelocity(
+ const MT_Vector3& ang_vel
+) {
+ m_ang_vel += ang_vel;
+ if (m_shapeProps) {
+ m_ang_mom = m_ang_vel * m_shapeProps->m_inertia;
+ }
+}
+
+
+ void
+SM_Object::
+clearCombinedVelocities(
+) {
+ m_combined_lin_vel = MT_Vector3(0,0,0);
+ m_combined_ang_vel = MT_Vector3(0,0,0);
+}
+
+ void
+SM_Object::
+resolveCombinedVelocities(
+ const MT_Vector3 & lin_vel,
+ const MT_Vector3 & ang_vel
+) {
+
+ // Different behaviours for dynamic and non-dynamic
+ // objects. For non-dynamic we just set the velocity to
+ // zero. For dynmic the physics velocity has to be
+ // taken into account. We must make an arbitrary decision
+ // on how to resolve the 2 velocities. Choices are
+ // Add the physics velocity to the linear velocity. Objects
+ // will just keep on moving in the direction they were
+ // last set in - untill external forces affect them.
+ // Set the combinbed linear and physics velocity to zero.
+ // Set the physics velocity in the direction of the set velocity
+ // zero.
+ if (isDynamic()) {
+
+#if 1
+ m_lin_vel += lin_vel;
+ m_ang_vel += ang_vel;
+#else
+
+ //compute the component of the physics velocity in the
+ // direction of the set velocity and set it to zero.
+ MT_Vector3 lin_vel_norm = lin_vel.normalized();
+
+ m_lin_vel -= (m_lin_vel.dot(lin_vel_norm) * lin_vel_norm);
+#endif
+ m_lin_mom = m_lin_vel * m_shapeProps->m_mass;
+ m_ang_mom = m_ang_vel * m_shapeProps->m_inertia;
+ clearCombinedVelocities();
+
+ }
+
+}
+
+
+ MT_Scalar
+SM_Object::
+getInvMass(
+) const {
+ return m_shapeProps ? 1.0 / m_shapeProps->m_mass : 0.0;
+ // OPT: cache the result of this division rather than compute it each call
+}
+
+ MT_Scalar
+SM_Object::
+getInvInertia(
+) const {
+ return m_shapeProps ? 1.0 / m_shapeProps->m_inertia : 0.0;
+ // OPT: cache the result of this division rather than compute it each call
+}
+
+ void
+SM_Object::
+applyForceField(
+ const MT_Vector3& accel
+) {
+ if (m_shapeProps) {
+ m_force += m_shapeProps->m_mass * accel; // F = m * a
+ }
+}
+
+ void
+SM_Object::
+applyCenterForce(
+ const MT_Vector3& force
+) {
+ m_force += force;
+}
+
+ void
+SM_Object::
+applyTorque(
+ const MT_Vector3& torque
+) {
+ m_torque += torque;
+}
+
+ void
+SM_Object::
+applyImpulse(
+ const MT_Point3& attach, const MT_Vector3& impulse
+) {
+ applyCenterImpulse(impulse); // Change in linear momentum
+ applyAngularImpulse((attach - m_pos).cross(impulse)); // Change in angular momentump
+}
+
+ void
+SM_Object::
+applyCenterImpulse(
+ const MT_Vector3& impulse
+) {
+ if (m_shapeProps) {
+ m_lin_mom += impulse;
+ m_reaction_impulse += impulse;
+ m_lin_vel = m_lin_mom / m_shapeProps->m_mass;
+
+ // The linear velocity is immedialtely updated since otherwise
+ // simultaneous collisions will get a double impulse.
+ }
+}
+
+ void
+SM_Object::
+applyAngularImpulse(
+ const MT_Vector3& impulse
+) {
+ if (m_shapeProps) {
+ m_ang_mom += impulse;
+ m_ang_vel = m_ang_mom / m_shapeProps->m_inertia;
+ }
+}
+
+ MT_Point3
+SM_Object::
+getWorldCoord(
+ const MT_Point3& local
+) const {
+ return m_xform(local);
+}
+
+ MT_Vector3
+SM_Object::
+getVelocity(
+ const MT_Point3& local
+) const {
+ // For displaced objects the velocity is faked using the previous state.
+ // Dynamic objects get their own velocity, not the faked velocity.
+ // (Dynamic objects shouldn't be displaced in the first place!!)
+
+ return m_prev_kinematic && !isDynamic() ?
+ (m_xform(local) - m_prev_xform(local)) / m_timeStep :
+ m_lin_vel + m_ang_vel.cross(m_xform.getBasis() * local);
+
+ // NB: m_xform.getBasis() * local == m_xform(local) - m_xform.getOrigin()
+
+}
+
+
+const
+ MT_Vector3&
+SM_Object::
+getReactionForce(
+) const {
+ return m_reaction_force;
+}
+
+ void
+SM_Object::
+getMatrix(
+ double *m
+) const {
+ std::copy(&m_ogl_matrix[0], &m_ogl_matrix[16], &m[0]);
+}
+
+const
+ double *
+SM_Object::
+getMatrix(
+) const {
+ return m_ogl_matrix;
+}
+
+// Still need this???
+const
+ MT_Transform&
+SM_Object::
+getScaledTransform(
+) const {
+ return m_xform;
+}
+
+ DT_ObjectHandle
+SM_Object::
+getObjectHandle(
+) const {
+ return m_object;
+}
+
+ DT_ShapeHandle
+SM_Object::
+getShapeHandle(
+) const {
+ return m_shape;
+}
+
+ void
+SM_Object::
+setClientObject(
+ void *clientobj
+) {
+ m_client_object = clientobj;
+}
+
+ void *
+SM_Object::
+getClientObject(
+){
+ return m_client_object;
+}
+
+ SM_Object *
+SM_Object::
+getDynamicParent(
+) {
+ return m_dynamicParent;
+}
+
+ void
+SM_Object::
+setRigidBody(
+ bool is_rigid_body
+) {
+ m_is_rigid_body = is_rigid_body;
+}
+
+ bool
+SM_Object::
+isRigidBody(
+) const {
+ return m_is_rigid_body;
+}
+
+const
+ MT_Vector3
+SM_Object::
+actualLinVelocity(
+) const {
+ return m_combined_lin_vel + m_lin_vel;
+};
+
+const
+ MT_Vector3
+SM_Object::
+actualAngVelocity(
+) const {
+ return m_combined_ang_vel + m_ang_vel;
+};
+
+
+
+
+
diff --git a/source/gameengine/Physics/Sumo/Fuzzics/src/SM_Scene.cpp b/source/gameengine/Physics/Sumo/Fuzzics/src/SM_Scene.cpp
new file mode 100644
index 00000000000..e3eb7e5c5ea
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/Fuzzics/src/SM_Scene.cpp
@@ -0,0 +1,179 @@
+/**
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * The physics scene.
+ */
+
+#ifdef WIN32
+#pragma warning(disable : 4786) // shut off 255 char limit debug template warning
+#endif
+
+#include "SM_Scene.h"
+#include "SM_Object.h"
+#include "SM_FhObject.h"
+
+#include <algorithm>
+
+void SM_Scene::add(SM_Object& object) {
+ object.calcXform();
+ m_objectList.push_back(&object);
+ DT_AddObject(m_scene, object.getObjectHandle());
+ if (object.isDynamic()) {
+ DT_SetObjectResponse(m_respTable, object.getObjectHandle(),
+ SM_Object::boing, DT_SIMPLE_RESPONSE, this);
+ }
+
+ if (object.getDynamicParent()) {
+ DT_SetPairResponse(m_respTable, object.getObjectHandle(),
+ object.getDynamicParent()->getObjectHandle(),
+ 0, DT_NO_RESPONSE, 0);
+ }
+ SM_FhObject *fh_object = object.getFhObject();
+
+ if (fh_object) {
+ DT_AddObject(m_scene, fh_object->getObjectHandle());
+ DT_SetObjectResponse(m_respTable, fh_object->getObjectHandle(),
+ SM_FhObject::ray_hit, DT_SIMPLE_RESPONSE, this);
+ }
+}
+
+void SM_Scene::remove(SM_Object& object) {
+ T_ObjectList::iterator i =
+ std::find(m_objectList.begin(), m_objectList.end(), &object);
+ if (!(i == m_objectList.end()))
+ {
+ std::swap(*i, m_objectList.back());
+ m_objectList.pop_back();
+ DT_RemoveObject(m_scene, object.getObjectHandle());
+ if (object.isDynamic()) {
+ DT_ClearObjectResponse(m_respTable, object.getObjectHandle());
+ }
+
+ if (object.getDynamicParent()) {
+ DT_ClearPairResponse(m_respTable, object.getObjectHandle(),
+ object.getDynamicParent()->getObjectHandle());
+ }
+
+ SM_FhObject *fh_object = object.getFhObject();
+
+ if (fh_object) {
+ DT_RemoveObject(m_scene, fh_object->getObjectHandle());
+ DT_ClearObjectResponse(m_respTable,
+ fh_object->getObjectHandle());
+ }
+ }
+ else {
+ // tried to remove an object that is not in the scene
+ //assert(false);
+ }
+}
+
+void SM_Scene::proceed(MT_Scalar timeStep, MT_Scalar subSampling) {
+ // Don't waste time...but it's OK to spill a little.
+ if (timeStep < 0.001)
+ return;
+
+ // Divide the timeStep into a number of subsamples of size roughly
+ // equal to subSampling (might be a little smaller).
+ int num_samples = (int)ceil(timeStep / subSampling);
+
+
+ MT_Scalar subStep = timeStep / num_samples;
+ T_ObjectList::iterator i;
+
+ // Apply a forcefield (such as gravity)
+ for (i = m_objectList.begin(); i != m_objectList.end(); ++i) {
+ (*i)->applyForceField(m_forceField);
+ }
+
+ // Do the integration steps per object.
+ int step;
+ for (step = 0; step != num_samples; ++step) {
+
+ for (i = m_objectList.begin(); i != m_objectList.end(); ++i) {
+ (*i)->integrateForces(subStep);
+ }
+
+ // And second we update the object positions by performing
+ // an integration step for each object
+ for (i = m_objectList.begin(); i != m_objectList.end(); ++i) {
+ (*i)->integrateMomentum(subStep);
+ }
+#if 0
+ // I changed the order of the next 2 statements.
+ // Originally objects were first integrated with a call
+ // to proceed(). However if external objects were
+ // directly manipulating the velocities etc of physics
+ // objects then the physics environment would not be able
+ // to react before object positions were updated. --- Laurence.
+
+ // So now first we let the physics scene respond to
+ // new forces, velocities set externally.
+#endif
+ // The collsion and friction impulses are computed here.
+ DT_Test(m_scene, m_respTable);
+
+ }
+
+
+ // clear the user set velocities.
+#if 0
+ clearObjectCombinedVelocities();
+#endif
+ // Finish this timestep by saving al state information for the next
+ // timestep and clearing the accumulated forces.
+
+ for (i = m_objectList.begin(); i != m_objectList.end(); ++i) {
+ (*i)->proceedKinematic(timeStep);
+ (*i)->saveReactionForce(timeStep);
+ (*i)->clearForce();
+ }
+
+ // For each pair of object that collided, call the corresponding callback.
+ // Additional collisions of a pair within the same time step are ignored.
+
+ if (m_secondaryRespTable) {
+ T_PairList::iterator p;
+ for (p = m_pairList.begin(); p != m_pairList.end(); ++p) {
+ DT_CallResponse(m_secondaryRespTable,
+ (*p).first->getObjectHandle(),
+ (*p).second->getObjectHandle(),
+ 0);
+ }
+ }
+
+ clearPairs();
+}
+
+SM_Object *SM_Scene::rayTest(void *ignore_client,
+ const MT_Point3& from, const MT_Point3& to,
+ MT_Point3& result, MT_Vector3& normal) const {
+ MT_Point3 local;
+
+ SM_Object *hit_object = (SM_Object *)
+ DT_RayTest(m_scene, ignore_client, from.getValue(), to.getValue(),
+ local.getValue(), normal.getValue());
+
+ if (hit_object) {
+ result = hit_object->getWorldCoord(local);
+ }
+
+ return hit_object;
+}
+
+void SM_Scene::clearObjectCombinedVelocities() {
+
+ T_ObjectList::iterator i;
+
+ for (i = m_objectList.begin(); i != m_objectList.end(); ++i) {
+
+ (*i)->clearCombinedVelocities();
+
+ }
+
+}
+
+
+
+
+
diff --git a/source/gameengine/Physics/Sumo/Makefile b/source/gameengine/Physics/Sumo/Makefile
new file mode 100644
index 00000000000..3e5aca1d577
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/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 = sumo
+DIR = $(OCGDIR)/gameengine/blphys/$(LIBNAME)
+
+include nan_compile.mk
+
+CCFLAGS += $(LEVEL_1_CPP_WARNINGS)
+
+CPPFLAGS += -I$(OPENGL_HEADERS)
+CPPFLAGS += -I$(NAN_STRING)/include
+CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION)
+CPPFLAGS += -I$(NAN_FUZZICS)/include -I$(NAN_SUMO)/include -I$(NAN_MOTO)/include
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+CPPFLAGS += -I../../Physics/common
+CPPFLAGS += -I../../Physics/Dummy
diff --git a/source/gameengine/Physics/Sumo/SumoPhysicsController.cpp b/source/gameengine/Physics/Sumo/SumoPhysicsController.cpp
new file mode 100644
index 00000000000..2b2c5b81856
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/SumoPhysicsController.cpp
@@ -0,0 +1,462 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "SumoPhysicsController.h"
+#include "PHY_IMotionState.h"
+#include "SM_Object.h"
+#include "MT_Quaternion.h"
+
+
+SumoPhysicsController::SumoPhysicsController(
+ class SM_Scene* sumoScene,
+ DT_SceneHandle solidscene,
+ class SM_Object* sumoObj,
+ class PHY_IMotionState* motionstate,
+
+ bool dyna)
+ :
+ m_sumoScene(sumoScene),
+ m_solidscene(solidscene),
+ m_sumoObj(sumoObj) ,
+ m_bFirstTime(true),
+ m_MotionState(motionstate),
+ m_bDyna(dyna)
+{
+ if (m_sumoObj)
+ {
+ m_sumoObj->setClientObject(this);
+ //if it is a dyna, register for a callback
+ m_sumoObj->registerCallback(*this);
+ }
+};
+
+
+
+SumoPhysicsController::~SumoPhysicsController()
+{
+ if (m_sumoObj)
+ {
+ m_sumoScene->remove(*m_sumoObj);
+
+
+ DT_ObjectHandle objhandle = (DT_ObjectHandle) m_sumoObj->getObjectHandle();
+ if (objhandle)
+ {
+ DT_RemoveObject(m_solidscene,objhandle);
+ }
+ delete m_sumoObj;
+ }
+}
+
+float SumoPhysicsController::getMass()
+{
+ if (m_sumoObj)
+ {
+ const SM_ShapeProps *shapeprops = m_sumoObj->getShapeProps();
+ return shapeprops->m_mass;
+ }
+ return 0.f;
+}
+
+bool SumoPhysicsController::SynchronizeMotionStates(float time)
+{
+
+ if (m_bFirstTime)
+ {
+ setSumoTransform(false);
+ m_bFirstTime = false;
+ }
+
+ if (!m_bDyna)
+ {
+ if (m_sumoObj)
+ {
+ MT_Point3 pos;
+ GetWorldPosition(pos);
+
+ m_sumoObj->setPosition(pos);
+ if (m_bDyna)
+ {
+ m_sumoObj->setScaling(MT_Vector3(1,1,1));
+ } else
+ {
+ MT_Vector3 scaling;
+ GetWorldScaling(scaling);
+ m_sumoObj->setScaling(scaling);
+ }
+ MT_Matrix3x3 orn;
+ GetWorldOrientation(orn);
+ m_sumoObj->setOrientation(orn.getRotation());
+ m_sumoObj->calcXform();
+ }
+ }
+ return false; // physics object are not part of
+ // hierarchy, or ignore it ??
+}
+
+
+
+
+void SumoPhysicsController::GetWorldOrientation(MT_Matrix3x3& mat)
+{
+ float orn[4];
+ m_MotionState->getWorldOrientation(orn[0],orn[1],orn[2],orn[3]);
+ MT_Quaternion quat(orn);
+ mat.setRotation(quat);
+
+}
+
+void SumoPhysicsController::GetWorldPosition(MT_Point3& pos)
+{
+ float worldpos[3];
+ m_MotionState->getWorldPosition(worldpos[0],worldpos[1],worldpos[2]);
+ pos[0]=worldpos[0];
+ pos[1]=worldpos[1];
+ pos[2]=worldpos[2];
+}
+
+void SumoPhysicsController::GetWorldScaling(MT_Vector3& scale)
+{
+ float worldscale[3];
+ m_MotionState->getWorldScaling(worldscale[0],worldscale[1],worldscale[2]);
+ scale[0]=worldscale[0];
+ scale[1]=worldscale[1];
+ scale[2]=worldscale[2];
+}
+
+
+ // kinematic methods
+void SumoPhysicsController::RelativeTranslate(float dlocX,float dlocY,float dlocZ,bool local)
+{
+
+
+ if (m_sumoObj)
+ {
+ MT_Matrix3x3 mat;
+ GetWorldOrientation(mat);
+ MT_Vector3 dloc(dlocX,dlocY,dlocZ);
+
+ MT_Point3 newpos = m_sumoObj->getPosition();
+ newpos += (local ? mat * dloc : dloc);
+ m_sumoObj->setPosition(newpos);
+ }
+
+}
+void SumoPhysicsController::RelativeRotate(const float drot[9],bool local)
+{
+
+ if (m_sumoObj )
+ {
+ MT_Matrix3x3 drotmat(drot);
+ MT_Matrix3x3 currentOrn;
+ GetWorldOrientation(currentOrn);
+
+ m_sumoObj->setOrientation(m_sumoObj->getOrientation()*(local ?
+ drotmat.getRotation() : (currentOrn.inverse() * drotmat * currentOrn)).getRotation());
+ }
+
+}
+void SumoPhysicsController::setOrientation(float quatImag0,float quatImag1,float quatImag2,float quatReal)
+{
+ float orn [4]={quatImag0,quatImag1,quatImag2,quatReal};
+ MT_Quaternion quat(orn);
+ m_sumoObj->setOrientation(orn);
+}
+
+void SumoPhysicsController::getOrientation(float &quatImag0,float &quatImag1,float &quatImag2,float &quatReal)
+{
+ const MT_Quaternion& q = m_sumoObj->getOrientation();
+ quatImag0 = q[0];
+ quatImag1 = q[1];
+ quatImag2 = q[2];
+ quatReal = q[3];
+}
+
+void SumoPhysicsController::setPosition(float posX,float posY,float posZ)
+{
+ m_sumoObj->setPosition(MT_Point3(posX,posY,posZ));
+}
+void SumoPhysicsController::setScaling(float scaleX,float scaleY,float scaleZ)
+{
+ m_sumoObj->setScaling(MT_Vector3(scaleX,scaleY,scaleZ));
+}
+
+ // physics methods
+void SumoPhysicsController::ApplyTorque(float torqueX,float torqueY,float torqueZ,bool local)
+{
+ if (m_sumoObj)
+ {
+ MT_Vector3 torque(torqueX,torqueY,torqueZ);
+
+ MT_Matrix3x3 orn;
+ GetWorldOrientation(orn);
+ m_sumoObj->applyTorque(local ?
+ orn * torque :
+ torque);
+ }
+
+}
+
+void SumoPhysicsController::ApplyForce(float forceX,float forceY,float forceZ,bool local)
+{
+ if (m_sumoObj)
+ {
+ MT_Vector3 force(forceX,forceY,forceZ);
+
+ MT_Matrix3x3 orn;
+ GetWorldOrientation(orn);
+
+ m_sumoObj->applyCenterForce(local ?
+ orn * force :
+ force);
+
+ }
+
+}
+
+void SumoPhysicsController::SetAngularVelocity(float ang_velX,float ang_velY,float ang_velZ,bool local)
+{
+ if (m_sumoObj)
+ {
+ MT_Vector3 ang_vel(ang_velX,ang_velY,ang_velZ);
+
+ MT_Matrix3x3 orn;
+ GetWorldOrientation(orn);
+
+ m_sumoObj->setAngularVelocity(local ?
+ orn * ang_vel :
+ ang_vel);
+
+ }
+}
+
+void SumoPhysicsController::SetLinearVelocity(float lin_velX,float lin_velY,float lin_velZ,bool local)
+{
+ if (m_sumoObj )
+ {
+ MT_Matrix3x3 orn;
+ GetWorldOrientation(orn);
+
+ MT_Vector3 lin_vel(lin_velX,lin_velY,lin_velZ);
+ m_sumoObj->setLinearVelocity(local ?
+ orn * lin_vel :
+ lin_vel);
+ }
+}
+
+void SumoPhysicsController::applyImpulse(float attachX,float attachY,float attachZ, float impulseX,float impulseY,float impulseZ)
+{
+ if (m_sumoObj)
+ {
+ MT_Point3 attach(attachX,attachY,attachZ);
+ MT_Vector3 impulse(impulseX,impulseY,impulseZ);
+ m_sumoObj->applyImpulse(attach,impulse);
+ }
+
+}
+
+void SumoPhysicsController::SuspendDynamics()
+{
+ m_suspendDynamics=true;
+
+ if (m_sumoObj)
+ {
+ m_sumoObj->suspendDynamics();
+ m_sumoObj->setLinearVelocity(MT_Vector3(0,0,0));
+ m_sumoObj->setAngularVelocity(MT_Vector3(0,0,0));
+ m_sumoObj->calcXform();
+ }
+}
+
+void SumoPhysicsController::RestoreDynamics()
+{
+ m_suspendDynamics=false;
+
+ if (m_sumoObj)
+ {
+ m_sumoObj->restoreDynamics();
+ }
+
+
+}
+
+
+ /**
+ reading out information from physics
+ */
+void SumoPhysicsController::GetLinearVelocity(float& linvX,float& linvY,float& linvZ)
+{
+ if (m_sumoObj)
+ {
+ // get velocity from the physics object (m_sumoObj)
+ const MT_Vector3& vel = m_sumoObj->getLinearVelocity();
+ linvX = vel[0];
+ linvY = vel[1];
+ linvZ = vel[2];
+ }
+ else
+ {
+ linvX = 0.f;
+ linvY = 0.f;
+ linvZ = 0.f;
+ }
+}
+ /**
+ GetVelocity parameters are in geometric coordinates (Origin is not center of mass!).
+ */
+void SumoPhysicsController::GetVelocity(const float posX,const float posY,const float posZ,float& linvX,float& linvY,float& linvZ)
+{
+ if (m_sumoObj)
+ {
+ MT_Point3 pos(posX,posY,posZ);
+ // get velocity from the physics object (m_sumoObj)
+ const MT_Vector3& vel = m_sumoObj->getVelocity(pos);
+ linvX = vel[0];
+ linvY = vel[1];
+ linvZ = vel[2];
+ }
+ else
+ {
+ linvX = 0.f;
+ linvY = 0.f;
+ linvZ = 0.f;
+
+ }
+}
+
+
+void SumoPhysicsController::getReactionForce(float& forceX,float& forceY,float& forceZ)
+{
+ const MT_Vector3& force = m_sumoObj->getReactionForce();
+ forceX = force[0];
+ forceY = force[1];
+ forceZ = force[2];
+
+
+}
+void SumoPhysicsController::setRigidBody(bool rigid)
+{
+ m_sumoObj->setRigidBody(rigid);
+}
+
+
+void SumoPhysicsController::PostProcessReplica(class PHY_IMotionState* motionstate,class PHY_IPhysicsController* parentctrl)
+{
+ m_MotionState = motionstate;
+
+ SM_Object* dynaparent=0;
+ SumoPhysicsController* sumoparentctrl = (SumoPhysicsController* )parentctrl;
+
+ if (sumoparentctrl)
+ {
+ dynaparent = sumoparentctrl->GetSumoObject();
+ }
+
+ SM_Object* orgsumoobject = m_sumoObj;
+
+
+ m_sumoObj = new SM_Object(
+ orgsumoobject->getShapeHandle(),
+ orgsumoobject->getMaterialProps(),
+ orgsumoobject->getShapeProps(),
+ dynaparent);
+
+ m_sumoObj->setRigidBody(orgsumoobject->isRigidBody());
+
+ double radius = orgsumoobject->getMargin();
+ m_sumoObj->setMargin(orgsumoobject->getMargin());
+ m_sumoObj->setPosition(orgsumoobject->getPosition());
+ m_sumoObj->setOrientation(orgsumoobject->getOrientation());
+ m_sumoScene->add(* (m_sumoObj));
+
+ if (m_sumoObj)
+ {
+ m_sumoObj->setClientObject(this);
+ //if it is a dyna, register for a callback
+ m_sumoObj->registerCallback(*this);
+ }
+
+
+ DT_AddObject(m_solidscene,m_sumoObj->getObjectHandle());
+
+}
+
+void SumoPhysicsController::SetSimulatedTime(float time)
+{
+}
+
+
+void SumoPhysicsController::WriteMotionStateToDynamics(bool nondynaonly)
+{
+
+}
+// this is the actual callback from sumo, and the position/orientation
+//is written to the scenegraph, using the motionstate abstraction
+
+void SumoPhysicsController::do_me()
+{
+
+ const MT_Point3& pos = m_sumoObj->getPosition();
+ const MT_Quaternion& orn = m_sumoObj->getOrientation();
+
+ m_MotionState->setWorldPosition(pos[0],pos[1],pos[2]);
+ m_MotionState->setWorldOrientation(orn[0],orn[1],orn[2],orn[3]);
+
+}
+
+
+void SumoPhysicsController::setSumoTransform(bool nondynaonly)
+{
+ if (!nondynaonly || !m_bDyna)
+ {
+ if (m_sumoObj)
+ {
+ MT_Point3 pos;
+ GetWorldPosition(pos);
+
+ m_sumoObj->setPosition(pos);
+ if (m_bDyna)
+ {
+ m_sumoObj->setScaling(MT_Vector3(1,1,1));
+ } else
+ {
+ MT_Vector3 scale;
+ GetWorldScaling(scale);
+ m_sumoObj->setScaling(scale);
+ }
+ MT_Matrix3x3 orn;
+ GetWorldOrientation(orn);
+ m_sumoObj->setOrientation(orn.getRotation());
+ m_sumoObj->calcXform();
+ }
+ }
+}
diff --git a/source/gameengine/Physics/Sumo/SumoPhysicsController.h b/source/gameengine/Physics/Sumo/SumoPhysicsController.h
new file mode 100644
index 00000000000..d78c21dbd1b
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/SumoPhysicsController.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 __SUMO_PHYSICSCONTROLLER_H
+#define __SUMO_PHYSICSCONTROLLER_H
+
+
+#include "PHY_IPhysicsController.h"
+#include "SM_Scene.h"
+#include "SM_Callback.h"
+
+
+/**
+ Sumo Physics Controller, a special kind of a PhysicsController.
+ A Physics Controller is a special kind of Scene Graph Transformation Controller.
+ Each time the scene graph get's updated, the controller get's a chance
+ in the 'Update' method to reflect changes.
+*/
+
+class SumoPhysicsController : public PHY_IPhysicsController , public SM_Callback
+
+
+{
+
+ class SM_Object* m_sumoObj;
+ class SM_Scene* m_sumoScene; // needed for replication
+ DT_SceneHandle m_solidscene;
+ bool m_bFirstTime;
+ bool m_bDyna;
+
+ float m_friction;
+ float m_restitution;
+
+
+ bool m_suspendDynamics;
+
+public:
+ SumoPhysicsController(
+ class SM_Scene* sumoScene,
+ DT_SceneHandle solidscene,
+ class SM_Object* sumoObj,
+ class PHY_IMotionState* motionstate,
+ bool dyna);
+
+ virtual ~SumoPhysicsController();
+
+ // kinematic methods
+ virtual void RelativeTranslate(float dlocX,float dlocY,float dlocZ,bool local);
+ virtual void RelativeRotate(const float drot[9],bool local);
+ virtual void getOrientation(float &quatImag0,float &quatImag1,float &quatImag2,float &quatReal);
+ virtual void setOrientation(float quatImag0,float quatImag1,float quatImag2,float quatReal);
+ virtual void setPosition(float posX,float posY,float posZ);
+ virtual void setScaling(float scaleX,float scaleY,float scaleZ);
+
+ // physics methods
+ virtual void ApplyTorque(float torqueX,float torqueY,float torqueZ,bool local);
+ virtual void ApplyForce(float forceX,float forceY,float forceZ,bool local);
+ virtual void SetAngularVelocity(float ang_velX,float ang_velY,float ang_velZ,bool local);
+ virtual void SetLinearVelocity(float lin_velX,float lin_velY,float lin_velZ,bool local);
+ virtual void applyImpulse(float attachX,float attachY,float attachZ, float impulseX,float impulseY,float impulseZ);
+ virtual void SetActive(bool active){};
+ virtual void SuspendDynamics();
+ virtual void RestoreDynamics();
+
+
+ /**
+ reading out information from physics
+ */
+ virtual void GetLinearVelocity(float& linvX,float& linvY,float& linvZ);
+ /**
+ GetVelocity parameters are in geometric coordinates (Origin is not center of mass!).
+ */
+ virtual void GetVelocity(const float posX,const float posY,const float posZ,float& linvX,float& linvY,float& linvZ);
+ virtual float getMass();
+ virtual void getReactionForce(float& forceX,float& forceY,float& forceZ);
+ virtual void setRigidBody(bool rigid);
+
+
+ virtual void PostProcessReplica(class PHY_IMotionState* motionstate,class PHY_IPhysicsController* parentctrl);
+
+ // todo: remove next line !
+ virtual void SetSimulatedTime(float time);
+
+
+ virtual void WriteDynamicsToMotionState() {};
+ virtual void WriteMotionStateToDynamics(bool nondynaonly);
+
+ /**
+ call from Scene Graph Node to 'update'.
+ */
+ virtual bool SynchronizeMotionStates(float time);
+
+ // clientinfo for raycasts for example
+ virtual void* getClientInfo() { return m_clientInfo;}
+ virtual void setClientInfo(void* clientinfo) {m_clientInfo = clientinfo;};
+ void* m_clientInfo;
+
+
+ float getFriction() { return m_friction;}
+ float getRestitution() { return m_restitution;}
+
+ // sumo callback
+ virtual void do_me();
+
+ class SM_Object* GetSumoObject ()
+ {
+ return m_sumoObj;
+ };
+
+ void GetWorldOrientation(class MT_Matrix3x3& mat);
+ void GetWorldPosition(MT_Point3& pos);
+ void GetWorldScaling(MT_Vector3& scale);
+
+
+// void SetSumoObject(class SM_Object* sumoObj) {
+// m_sumoObj = sumoObj;
+// }
+// void SetSumoScene(class SM_Scene* sumoScene) {
+// m_sumoScene = sumoScene;
+// }
+
+ void setSumoTransform(bool nondynaonly);
+
+
+private:
+
+ bool m_firstTime;
+ bool m_bFullRigidBody;
+ bool m_bPhantom; // special flag for objects that are not affected by physics 'resolver'
+
+ // data to calculate fake velocities for kinematic objects (non-dynas)
+ bool m_bKinematic;
+ bool m_bPrevKinematic;
+
+ float m_lastTime;
+
+ class PHY_IMotionState* m_MotionState;
+
+};
+
+#endif //__SUMO_PHYSICSCONTROLLER_H
+
+
diff --git a/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.cpp b/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.cpp
new file mode 100644
index 00000000000..05b88fcb06b
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.cpp
@@ -0,0 +1,103 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "SumoPhysicsEnvironment.h"
+#include "PHY_IMotionState.h"
+#include "SumoPhysicsController.h"
+#include "SM_Scene.h"
+
+
+const MT_Scalar UpperBoundForFuzzicsIntegrator = 0.01;
+// At least 100Hz (isn't this CPU hungry ?)
+
+
+SumoPhysicsEnvironment::SumoPhysicsEnvironment()
+{
+ // seperate collision scene for events
+ m_solidScene = DT_CreateScene();
+ m_respTable = DT_CreateRespTable();
+
+ m_sumoScene = new SM_Scene();
+ m_sumoScene->setSecondaryRespTable(m_respTable);
+
+}
+
+
+
+SumoPhysicsEnvironment::~SumoPhysicsEnvironment()
+{
+ delete m_sumoScene;
+
+ DT_DeleteScene(m_solidScene);
+ DT_DeleteRespTable(m_respTable);
+}
+
+void SumoPhysicsEnvironment::proceed(double timeStep)
+{
+ m_sumoScene->proceed(timeStep,UpperBoundForFuzzicsIntegrator);
+}
+
+void SumoPhysicsEnvironment::setGravity(float x,float y,float z)
+{
+ m_sumoScene->setForceField(MT_Vector3(x,y,z));
+
+}
+
+
+
+
+
+int SumoPhysicsEnvironment::createConstraint(class PHY_IPhysicsController* ctrl,class PHY_IPhysicsController* ctrl2,PHY_ConstraintType type,
+ float pivotX,float pivotY,float pivotZ,float axisX,float axisY,float axisZ)
+{
+
+ int constraintid = 0;
+ return constraintid;
+
+}
+
+void SumoPhysicsEnvironment::removeConstraint(int constraintid)
+{
+ if (constraintid)
+ {
+ }
+}
+
+PHY_IPhysicsController* SumoPhysicsEnvironment::rayTest(void* ignoreClient, float fromX,float fromY,float fromZ, float toX,float toY,float toZ,
+ float& hitX,float& hitY,float& hitZ,float& normalX,float& normalY,float& normalZ)
+{
+ //collision detection / raytesting
+ //m_sumoScene->rayTest(ignoreclient,from,to,result,normal);
+
+ return NULL;
+}
+
+
diff --git a/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h b/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h
new file mode 100644
index 00000000000..0e28b855833
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.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 *****
+ */
+#ifndef _SUMOPhysicsEnvironment
+#define _SUMOPhysicsEnvironment
+
+
+#include "PHY_IPhysicsEnvironment.h"
+
+#include "solid.h"
+
+/**
+* Physics Environment takes care of stepping the simulation and is a container for physics entities (rigidbodies,constraints, materials etc.)
+* A derived class may be able to 'construct' entities by loading and/or converting
+*/
+class SumoPhysicsEnvironment : public PHY_IPhysicsEnvironment
+{
+
+ class SM_Scene* m_sumoScene;
+
+ DT_SceneHandle m_solidScene;
+ DT_RespTableHandle m_respTable;
+
+public:
+ SumoPhysicsEnvironment();
+ virtual ~SumoPhysicsEnvironment();
+// Perform an integration step of duration 'timeStep'.
+ virtual void proceed(double timeStep);
+ virtual void setGravity(float x,float y,float z);
+ virtual int createConstraint(class PHY_IPhysicsController* ctrl,class PHY_IPhysicsController* ctrl2,PHY_ConstraintType type,
+ float pivotX,float pivotY,float pivotZ,
+ float axisX,float axisY,float axisZ);
+
+ virtual void removeConstraint(int constraintid);
+ virtual PHY_IPhysicsController* rayTest(void* ignoreClient,float fromX,float fromY,float fromZ, float toX,float toY,float toZ,
+ float& hitX,float& hitY,float& hitZ,float& normalX,float& normalY,float& normalZ);
+
+
+ // sumo specific
+ SM_Scene* GetSumoScene()
+ {
+ return m_sumoScene;
+ }
+
+ DT_SceneHandle GetSolidScene()
+ {
+ return m_solidScene;
+ }
+
+private:
+
+
+
+
+};
+
+#endif //_SUMOPhysicsEnvironment
+
+
+
diff --git a/source/gameengine/Physics/Sumo/convert.txt b/source/gameengine/Physics/Sumo/convert.txt
new file mode 100644
index 00000000000..81f8f602cde
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/convert.txt
@@ -0,0 +1,35 @@
+static DT_ShapeHandle CreateShapeFromMesh(RAS_MeshObject* meshobj)
+{
+ DT_ShapeHandle shape = DT_NewComplexShape();
+ int numpolys = meshobj->NumPolygons();
+ int numvalidpolys = 0;
+
+ for (int p=0; p<numpolys; p++)
+ {
+ RAS_Polygon* poly = meshobj->GetPolygon(p);
+
+ // only add polygons that have the collisionflag set
+ if (poly->IsCollider())
+ {
+ DT_Begin();
+ for (int v=0; v<poly->VertexCount(); v++) {
+ MT_Point3 pt = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray,
+ poly->GetVertexIndexBase().m_indexarray[v],
+ poly->GetMaterial()->GetPolyMaterial())->xyz();
+ DT_Vertex(pt[0],pt[1],pt[2]);
+ }
+ DT_End();
+
+ numvalidpolys++;
+ }
+ }
+
+ DT_EndComplexShape();
+
+ if (numvalidpolys==0) {
+ delete shape;
+ return NULL;
+ } else {
+ return shape;
+ }
+}
diff --git a/source/gameengine/Physics/Sumo/include/interpolator.h b/source/gameengine/Physics/Sumo/include/interpolator.h
new file mode 100644
index 00000000000..055c242edc7
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/include/interpolator.h
@@ -0,0 +1,27 @@
+#ifndef INTERPOLATOR_H
+#define INTERPOLATOR_H
+
+#include "solid_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+DT_DECLARE_HANDLE(IP_IpoHandle);
+
+typedef struct IP_ControlPoint {
+ DT_Scalar m_key;
+ DT_Scalar m_keyValue;
+} IP_ControlPoint;
+
+IP_IpoHandle IP_CreateLinear(const IP_ControlPoint *cpoints, int num_cpoints);
+
+void IP_DeleteInterpolator(IP_IpoHandle ipo);
+
+DT_Scalar IP_GetValue(IP_IpoHandle ipo, DT_Scalar key);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/source/gameengine/Physics/Sumo/include/solid.h b/source/gameengine/Physics/Sumo/include/solid.h
new file mode 100644
index 00000000000..985014a2a46
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/include/solid.h
@@ -0,0 +1,195 @@
+#ifndef SOLID_H
+#define SOLID_H
+
+#include "solid_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+DT_DECLARE_HANDLE(DT_ObjectHandle);
+DT_DECLARE_HANDLE(DT_SceneHandle);
+DT_DECLARE_HANDLE(DT_ShapeHandle);
+DT_DECLARE_HANDLE(DT_RespTableHandle);
+
+typedef enum DT_ScalarType {
+ DT_FLOAT,
+ DT_DOUBLE
+} DT_ScalarType;
+
+typedef enum DT_ResponseType {
+ DT_NO_RESPONSE,
+ DT_SIMPLE_RESPONSE,
+ DT_WITNESSED_RESPONSE,
+ DT_DEPTH_RESPONSE,
+} DT_ResponseType;
+
+typedef struct DT_CollData {
+ DT_Vector3 point1;
+ DT_Vector3 point2;
+ DT_Vector3 normal;
+} DT_CollData;
+
+typedef void (*DT_ResponseCallback)(
+ void *client_data,
+ void *client_object1,
+ void *client_object2,
+ const DT_CollData *coll_data);
+
+/* Shape definition, similar to OpenGL */
+
+extern DT_ShapeHandle DT_Box(DT_Scalar x, DT_Scalar y, DT_Scalar z);
+extern DT_ShapeHandle DT_Cone(DT_Scalar radius, DT_Scalar height);
+extern DT_ShapeHandle DT_Cylinder(DT_Scalar radius, DT_Scalar height);
+extern DT_ShapeHandle DT_Sphere(DT_Scalar radius);
+extern DT_ShapeHandle DT_Ray(DT_Scalar x, DT_Scalar y, DT_Scalar z);
+
+extern DT_ShapeHandle DT_NewComplexShape();
+extern void DT_EndComplexShape();
+
+extern DT_ShapeHandle DT_NewPolyhedron();
+extern void DT_EndPolyhedron();
+
+extern void DT_Begin();
+extern void DT_End();
+
+extern void DT_Vertex(DT_Scalar x, DT_Scalar y, DT_Scalar z);
+
+/* Vertex arrays maintained by the client application can be accessed directly
+ by SUMO. For instance, you have a vertex struct in the client of the form:
+
+ struct Vertex {
+ float xyz[3];
+ float uv[2];
+ float normal[3];
+ };
+
+ And maintain vertex arrays e.g. as
+
+ struct Vertex vertices[328];
+
+ Within a Polyhedron or a ComplexShape you can use this data by specifying
+
+ DT_VertexBase(vertices, DT_FLOAT, sizeof(struct Vertex));
+
+ and refer to vertices in the array using
+
+ DT_VertexIndex(10);
+
+ or
+
+ DT_Index indices[5] = { 6, 4, 8, 1, 3 };
+ DT_VertexIndices(5, indices);
+
+ or even
+
+ DT_VertexRange(8, 4);
+
+ for the range 8, 9, 10, 11.
+*/
+
+
+extern void DT_SetVertexBase(const void *base, DT_ScalarType type,
+ DT_Size stride);
+extern void DT_VertexIndex(DT_Index index);
+extern void DT_VertexIndices(DT_Count count, const DT_Index *indices);
+extern void DT_VertexRange(DT_Index first, DT_Count count);
+
+
+/* currently not implemented */
+extern void DT_ChangeVertexBase(DT_ShapeHandle shape, const void *base);
+
+extern void DT_DeleteShape(DT_ShapeHandle shape);
+
+/* Scene */
+
+extern DT_SceneHandle DT_CreateScene();
+extern void DT_DeleteScene(DT_SceneHandle scene);
+
+extern void DT_AddObject(DT_SceneHandle scene, DT_ObjectHandle object);
+extern void DT_RemoveObject(DT_SceneHandle scene, DT_ObjectHandle object);
+
+
+
+/* Object */
+
+extern DT_ObjectHandle DT_CreateObject(
+ void *client_object, /* pointer to object in client memory */
+ DT_ShapeHandle shape /* the shape or geometry of the object */
+ );
+
+extern void DT_DeleteObject(DT_ObjectHandle object);
+
+extern void DT_SetScaling(DT_ObjectHandle object, const DT_Vector3 scaling);
+extern void DT_SetPosition(DT_ObjectHandle object, const DT_Vector3 position);
+extern void DT_SetOrientation(DT_ObjectHandle object, const DT_Quaternion orientation);
+
+extern void DT_SetMargin(DT_ObjectHandle object, DT_Scalar margin);
+
+extern void DT_SetMatrixf(DT_ObjectHandle object, const float *m);
+extern void DT_GetMatrixf(DT_ObjectHandle object, float *m);
+
+extern void DT_SetMatrixd(DT_ObjectHandle object, const double *m);
+extern void DT_GetMatrixd(DT_ObjectHandle object, double *m);
+
+extern void DT_GetWorldCoord(DT_ObjectHandle object,
+ const DT_Vector3 local,
+ DT_Vector3 world);
+
+extern DT_Scalar DT_GetClosestPair(DT_ObjectHandle object1, DT_ObjectHandle object2,
+ DT_Vector3 point1, DT_Vector3 point2);
+
+
+/* Response, see SOLID user manual */
+
+extern DT_RespTableHandle DT_CreateRespTable();
+extern void DT_DeleteRespTable(DT_RespTableHandle respTable);
+
+extern void DT_CallResponse(DT_RespTableHandle respTable,
+ DT_ObjectHandle object1,
+ DT_ObjectHandle object2,
+ const DT_CollData *coll_data);
+
+extern void DT_SetDefaultResponse(DT_RespTableHandle respTable,
+ DT_ResponseCallback response,
+ DT_ResponseType type,
+ void *client_data);
+
+extern void DT_ClearDefaultResponse(DT_RespTableHandle respTable);
+
+extern void DT_SetObjectResponse(DT_RespTableHandle respTable,
+ DT_ObjectHandle object,
+ DT_ResponseCallback response,
+ DT_ResponseType type, void *client_data);
+extern void DT_ClearObjectResponse(DT_RespTableHandle respTable,
+ DT_ObjectHandle object);
+
+extern void DT_SetPairResponse(DT_RespTableHandle respTable,
+ DT_ObjectHandle object1,
+ DT_ObjectHandle object2,
+ DT_ResponseCallback response,
+ DT_ResponseType type,
+ void *client_data);
+extern void DT_ClearPairResponse(DT_RespTableHandle respTable,
+ DT_ObjectHandle object1,
+ DT_ObjectHandle object2);
+
+
+
+/* Perform a collision test for a given scene, using a response table */
+
+extern DT_Count DT_Test(DT_SceneHandle scene, DT_RespTableHandle respTable);
+
+extern void *DT_RayTest(DT_SceneHandle scene, void *ignore_client,
+ const DT_Vector3 from, const DT_Vector3 to,
+ DT_Vector3 spot, DT_Vector3 normal);
+
+extern int DT_ObjectRayTest(DT_ObjectHandle object,
+ const DT_Vector3 from, const DT_Vector3 to,
+ DT_Vector3 spot, DT_Vector3 normal);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/source/gameengine/Physics/Sumo/include/solid_broadphase.h b/source/gameengine/Physics/Sumo/include/solid_broadphase.h
new file mode 100644
index 00000000000..d5d05e8a243
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/include/solid_broadphase.h
@@ -0,0 +1,38 @@
+#ifndef SOLID_BROADPHASE_H
+#define SOLID_BROADPHASE_H
+
+#include "solid_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+DT_DECLARE_HANDLE(BP_SceneHandle);
+DT_DECLARE_HANDLE(BP_ProxyHandle);
+
+typedef void (*BP_Callback)(void *client_data,
+ void *object1,
+ void *object2);
+
+extern BP_SceneHandle BP_CreateScene(void *client_data,
+ BP_Callback beginOverlap,
+ BP_Callback endOverlap);
+
+extern void BP_DeleteScene(BP_SceneHandle scene);
+
+extern BP_ProxyHandle BP_CreateProxy(BP_SceneHandle scene, void *object,
+ const DT_Vector3 lower,
+ const DT_Vector3 upper);
+
+extern void BP_DeleteProxy(BP_SceneHandle scene,
+ BP_ProxyHandle proxy);
+
+extern void BP_SetBBox(BP_ProxyHandle proxy,
+ const DT_Vector3 lower,
+ const DT_Vector3 upper);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/source/gameengine/Physics/Sumo/include/solid_types.h b/source/gameengine/Physics/Sumo/include/solid_types.h
new file mode 100644
index 00000000000..537bbcb5826
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/include/solid_types.h
@@ -0,0 +1,14 @@
+#ifndef SOLID_TYPES_H
+#define SOLID_TYPES_H
+
+#define DT_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name
+
+typedef double DT_Scalar;
+typedef unsigned int DT_Count;
+typedef unsigned int DT_Index;
+typedef unsigned int DT_Size;
+
+typedef DT_Scalar DT_Vector3[3];
+typedef DT_Scalar DT_Quaternion[4];
+
+#endif
diff --git a/source/gameengine/Physics/common/Makefile b/source/gameengine/Physics/common/Makefile
new file mode 100644
index 00000000000..3783d959e14
--- /dev/null
+++ b/source/gameengine/Physics/common/Makefile
@@ -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 *****
+#
+#
+
+LIBNAME = common
+DIR = $(OCGDIR)/gameengine/blphys/$(LIBNAME)
+
+include nan_compile.mk
+
+CCFLAGS += $(LEVEL_1_CPP_WARNINGS)
+
+CPPFLAGS += -I$(OPENGL_HEADERS)
+CPPFLAGS += -I$(NAN_STRING)/include
+CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION)
+CPPFLAGS += -I$(NAN_FUZZICS)/include -I$(NAN_SUMO)/include -I$(NAN_MOTO)/include
+CPPFLAGS += -I../../blender
+# these two needed because of blenkernel
+CPPFLAGS += -I../../blender/makesdna
+CPPFLAGS += -I../../blender/include
+CPPFLAGS += -I../../blender/blenlib
+CPPFLAGS += -I../../blender/blenkernel
+CPPFLAGS += -I../../blender/render/extern/include
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+CPPFLAGS += -I../Expressions -I../Rasterizer -I../GameLogic -I../SoundSystem
+CPPFLAGS += -I../Ketsji -I../BlenderRoutines -I../SceneGraph
+CPPFLAGS += -I../../kernel/gen_system
+CPPFLAGS += -I../Rasterizer/RAS_OpenGLRasterizer
+CPPFLAGS += -I../Network -I../Ketsji/KXNetwork
+CPPFLAGS += -I../Physics
+CPPFLAGS += -I../Physics/Dummy
diff --git a/source/gameengine/Physics/common/PHY_DynamicTypes.h b/source/gameengine/Physics/common/PHY_DynamicTypes.h
new file mode 100644
index 00000000000..4b10a29e1e7
--- /dev/null
+++ b/source/gameengine/Physics/common/PHY_DynamicTypes.h
@@ -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 *****
+ */
+#ifndef __PHY_DYNAMIC_TYPES
+#define __PHY_DYNAMIC_TYPES
+
+/// PHY_ScalarType enumerates possible scalar types.
+/// See the PHY_IMeshInterface for its use
+typedef enum PHY_ScalarType {
+ PHY_FLOAT,
+ PHY_DOUBLE,
+ PHY_INTEGER,
+ PHY_SHORT,
+ PHY_FIXEDPOINT88
+} PHY_ScalarType;
+
+/// PHY_PhysicsType enumerates all possible Physics Entities.
+/// It is mainly used to create/add Physics Objects
+
+typedef enum PHY_PhysicsType {
+ PHY_CONVEX_RIGIDBODY=16386,
+ PHY_CONCAVE_RIGIDBODY=16399,
+ PHY_CONVEX_FIXEDBODY=16388,//'collision object'
+ PHY_CONCAVE_FIXEDBODY=16401,
+ PHY_CONVEX_KINEMATICBODY=16387,//
+ PHY_CONCAVE_KINEMATICBODY=16400,
+ PHY_CONVEX_PHANTOMBODY=16398,
+ PHY_CONCAVE_PHANTOMBODY=16402
+} PHY_PhysicsType;
+
+/// PHY_ConstraintType enumerates all supported Constraint Types
+typedef enum PHY_ConstraintType {
+ PHY_POINT2POINT_CONSTRAINT=1,
+ PHY_LINEHINGE_CONSTRAINT,
+
+} PHY_ConstraintType;
+
+typedef float PHY_Vector3[3];
+
+#endif //__PHY_DYNAMIC_TYPES
diff --git a/source/gameengine/Physics/common/PHY_IMotionState.cpp b/source/gameengine/Physics/common/PHY_IMotionState.cpp
new file mode 100644
index 00000000000..106f453424d
--- /dev/null
+++ b/source/gameengine/Physics/common/PHY_IMotionState.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 "PHY_IMotionState.h"
+
+PHY_IMotionState::~PHY_IMotionState()
+{
+
+}
diff --git a/source/gameengine/Physics/common/PHY_IMotionState.h b/source/gameengine/Physics/common/PHY_IMotionState.h
new file mode 100644
index 00000000000..6dd97427b59
--- /dev/null
+++ b/source/gameengine/Physics/common/PHY_IMotionState.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 *****
+ */
+#ifndef PHY__MOTIONSTATE_H
+#define PHY__MOTIONSTATE_H
+
+
+/**
+ PHY_IMotionState is the Interface to explicitly synchronize the world transformation.
+ Default implementations for mayor graphics libraries like OpenGL and DirectX can be provided.
+*/
+class PHY_IMotionState
+
+{
+ public:
+
+ virtual ~PHY_IMotionState();
+
+ virtual void getWorldPosition(float& posX,float& posY,float& posZ)=0;
+ virtual void getWorldScaling(float& scaleX,float& scaleY,float& scaleZ)=0;
+ virtual void getWorldOrientation(float& quatIma0,float& quatIma1,float& quatIma2,float& quatReal)=0;
+
+ virtual void setWorldPosition(float posX,float posY,float posZ)=0;
+ virtual void setWorldOrientation(float quatIma0,float quatIma1,float quatIma2,float quatReal)=0;
+
+ virtual void calculateWorldTransformations()=0;
+};
+
+#endif //PHY__MOTIONSTATE_H
diff --git a/source/gameengine/Physics/common/PHY_IPhysicsController.cpp b/source/gameengine/Physics/common/PHY_IPhysicsController.cpp
new file mode 100644
index 00000000000..ec0f7b9df3e
--- /dev/null
+++ b/source/gameengine/Physics/common/PHY_IPhysicsController.cpp
@@ -0,0 +1,39 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "PHY_IPhysicsController.h"
+
+
+PHY_IPhysicsController::~PHY_IPhysicsController()
+{
+
+}
+
diff --git a/source/gameengine/Physics/common/PHY_IPhysicsController.h b/source/gameengine/Physics/common/PHY_IPhysicsController.h
new file mode 100644
index 00000000000..e8309c0ca40
--- /dev/null
+++ b/source/gameengine/Physics/common/PHY_IPhysicsController.h
@@ -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 *****
+ */
+#ifndef PHY_IPHYSICSCONTROLLER_H
+#define PHY_IPHYSICSCONTROLLER_H
+
+/**
+ PHY_IPhysicsController is the abstract simplified Interface to a physical object.
+ It contains the IMotionState and IDeformableMesh Interfaces.
+*/
+
+
+class PHY_IPhysicsController
+{
+
+ public:
+
+ virtual ~PHY_IPhysicsController();
+ /**
+ SynchronizeMotionStates ynchronizes dynas, kinematic and deformable entities (and do 'late binding')
+ */
+ virtual bool SynchronizeMotionStates(float time)=0;
+ /**
+ WriteMotionStateToDynamics ynchronizes dynas, kinematic and deformable entities (and do 'late binding')
+ */
+
+ virtual void WriteMotionStateToDynamics(bool nondynaonly)=0;
+ virtual void WriteDynamicsToMotionState()=0;
+ // controller replication
+ virtual void PostProcessReplica(class PHY_IMotionState* motionstate,class PHY_IPhysicsController* parentctrl)=0;
+
+ // kinematic methods
+ virtual void RelativeTranslate(float dlocX,float dlocY,float dlocZ,bool local)=0;
+ virtual void RelativeRotate(const float drot[9],bool local)=0;
+ virtual void getOrientation(float &quatImag0,float &quatImag1,float &quatImag2,float &quatReal)=0;
+ virtual void setOrientation(float quatImag0,float quatImag1,float quatImag2,float quatReal)=0;
+ virtual void setPosition(float posX,float posY,float posZ)=0;
+ virtual void setScaling(float scaleX,float scaleY,float scaleZ)=0;
+
+ // physics methods
+ virtual void ApplyTorque(float torqueX,float torqueY,float torqueZ,bool local)=0;
+ virtual void ApplyForce(float forceX,float forceY,float forceZ,bool local)=0;
+ virtual void SetAngularVelocity(float ang_velX,float ang_velY,float ang_velZ,bool local)=0;
+ virtual void SetLinearVelocity(float lin_velX,float lin_velY,float lin_velZ,bool local)=0;
+ virtual void applyImpulse(float attachX,float attachY,float attachZ, float impulseX,float impulseY,float impulseZ)=0;
+ virtual void SetActive(bool active)=0;
+
+ // reading out information from physics
+ virtual void GetLinearVelocity(float& linvX,float& linvY,float& linvZ)=0;
+ virtual void GetVelocity(const float posX,const float posY,const float posZ,float& linvX,float& linvY,float& linvZ)=0;
+ virtual void getReactionForce(float& forceX,float& forceY,float& forceZ)=0;
+
+ // dyna's that are rigidbody are free in orientation, dyna's with non-rigidbody are restricted
+ virtual void setRigidBody(bool rigid)=0;
+
+ // clientinfo for raycasts for example
+ virtual void* getClientInfo()=0;
+ virtual void setClientInfo(void* clientinfo)=0;
+};
+
+#endif //PHY_IPHYSICSCONTROLLER_H
diff --git a/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.cpp b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.cpp
new file mode 100644
index 00000000000..7c0660976fb
--- /dev/null
+++ b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.cpp
@@ -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 *****
+ */
+
+#include "PHY_IPhysicsEnvironment.h"
+
+/**
+* Physics Environment takes care of stepping the simulation and is a container for physics entities (rigidbodies,constraints, materials etc.)
+* A derived class may be able to 'construct' entities by loading and/or converting
+*/
+
+
+
+PHY_IPhysicsEnvironment::~PHY_IPhysicsEnvironment()
+{
+
+}
diff --git a/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h
new file mode 100644
index 00000000000..5867e27ce42
--- /dev/null
+++ b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h
@@ -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 *****
+ */
+#ifndef _IPHYSICSENVIRONMENT
+#define _IPHYSICSENVIRONMENT
+
+#include <vector>
+#include "PHY_DynamicTypes.h"
+
+
+/**
+* Physics Environment takes care of stepping the simulation and is a container for physics entities (rigidbodies,constraints, materials etc.)
+* A derived class may be able to 'construct' entities by loading and/or converting
+*/
+class PHY_IPhysicsEnvironment
+{
+ public:
+ virtual ~PHY_IPhysicsEnvironment();
+ /// Perform an integration step of duration 'timeStep'.
+ virtual void proceed(double timeStep)=0;
+ virtual void setGravity(float x,float y,float z)=0;
+
+ virtual int createConstraint(class PHY_IPhysicsController* ctrl,class PHY_IPhysicsController* ctrl2,PHY_ConstraintType type,
+ float pivotX,float pivotY,float pivotZ,
+ float axisX,float axisY,float axisZ)=0;
+ virtual void removeConstraint(int constraintid)=0;
+
+ virtual PHY_IPhysicsController* rayTest(void* ignoreClient, float fromX,float fromY,float fromZ, float toX,float toY,float toZ,
+ float& hitX,float& hitY,float& hitZ,float& normalX,float& normalY,float& normalZ)=0;
+};
+
+#endif //_IPHYSICSENVIRONMENT
diff --git a/source/gameengine/Physics/common/PHY_Pro.h b/source/gameengine/Physics/common/PHY_Pro.h
new file mode 100644
index 00000000000..58f3badaff6
--- /dev/null
+++ b/source/gameengine/Physics/common/PHY_Pro.h
@@ -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 *****
+ */
+#ifndef PHY_PROPSH
+#define PHY_PROPSH
+
+#include <MT_Scalar.h>
+
+// Properties of dynamic objects
+struct PHY_ShapeProps {
+ MT_Scalar m_mass; // Total mass
+ MT_Scalar m_inertia; // Inertia, should be a tensor some time
+ MT_Scalar m_lin_drag; // Linear drag (air, water) 0 = concrete, 1 = vacuum
+ MT_Scalar m_ang_drag; // Angular drag
+ MT_Scalar m_friction_scaling[3]; // Scaling for anisotropic friction. Component in range [0, 1]
+ bool m_do_anisotropic; // Should I do anisotropic friction?
+ bool m_do_fh; // Should the object have a linear Fh spring?
+ bool m_do_rot_fh; // Should the object have an angular Fh spring?
+};
+
+
+// Properties of collidable objects (non-ghost objects)
+struct PHY_MaterialProps {
+ MT_Scalar m_restitution; // restitution of energie after a collision 0 = inelastic, 1 = elastic
+ MT_Scalar m_friction; // Coulomb friction (= ratio between the normal en maximum friction force)
+ MT_Scalar m_fh_spring; // Spring constant (both linear and angular)
+ MT_Scalar m_fh_damping; // Damping factor (linear and angular) in range [0, 1]
+ MT_Scalar m_fh_distance; // The range above the surface where Fh is active.
+ bool m_fh_normal; // Should the object slide off slopes?
+};
+
+#endif //PHY_PROPSH
diff --git a/source/gameengine/Rasterizer/Makefile b/source/gameengine/Rasterizer/Makefile
new file mode 100644
index 00000000000..6a1421ae90b
--- /dev/null
+++ b/source/gameengine/Rasterizer/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 *****
+#
+#
+
+LIBNAME = rasterizer
+DIR = $(OCGDIR)/gameengine/$(LIBNAME)
+
+include nan_compile.mk
+
+CCFLAGS += $(LEVEL_1_CPP_WARNINGS)
+
+CPPFLAGS += -I$(OPENGL_HEADERS)
+CPPFLAGS += -I$(NAN_STRING)/include
+CPPFLAGS += -I$(NAN_MOTO)/include
+CPPFLAGS += -I../../kernel/gen_system
+
+###############
+
+SOURCEDIR = source/gameengine/Rasterizer
+DIRS = RAS_OpenGLRasterizer
+
+include nan_subdirs.mk
diff --git a/source/gameengine/Rasterizer/RAS_BucketManager.cpp b/source/gameengine/Rasterizer/RAS_BucketManager.cpp
new file mode 100644
index 00000000000..39ec523cfa2
--- /dev/null
+++ b/source/gameengine/Rasterizer/RAS_BucketManager.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 *****
+ */
+
+
+#ifdef WIN32
+// don't show these anoying STL warnings
+#pragma warning (disable:4786)
+#endif
+
+#include "GEN_Map.h"
+#include "RAS_MaterialBucket.h"
+#include "STR_HashedString.h"
+#include "RAS_MeshObject.h"
+#define KX_NUM_MATERIALBUCKETS 100
+#include "RAS_IRasterizer.h"
+#include "RAS_IRenderTools.h"
+
+#include "RAS_BucketManager.h"
+
+
+RAS_BucketManager::RAS_BucketManager()
+{
+
+}
+
+RAS_BucketManager::~RAS_BucketManager()
+{
+ RAS_BucketManagerClearAll();
+}
+
+
+void RAS_BucketManager::Renderbuckets(
+ const MT_Transform& cameratrans, RAS_IRasterizer* rasty, RAS_IRenderTools* rendertools)
+{
+ int numbuckets = m_MaterialBuckets.size();
+
+ //default_gl_light();
+
+ int i;
+
+ rasty->EnableTextures(false);
+ rasty->SetDepthMask(RAS_IRasterizer::KX_DEPTHMASK_ENABLED);
+
+ // beginning each frame, clear (texture/material) caching information
+ rasty->ClearCachingInfo();
+
+ RAS_MaterialBucket::StartFrame();
+
+ for (i=0;i<numbuckets;i++)
+ {
+ RAS_MaterialBucket** bucketptr = m_MaterialBuckets.at(i);
+ if (bucketptr)
+ {
+ (*bucketptr)->ClearScheduledPolygons();
+ }
+ }
+
+ vector<RAS_MaterialBucket*> alphabuckets;
+
+ // if no visibility method is define, everything is drawn
+
+ for (i=0;i<numbuckets;i++)
+ {
+ RAS_MaterialBucket** bucketptr = m_MaterialBuckets.at(i);
+ if (bucketptr)
+ {
+ if (!(*bucketptr)->IsTransparant())
+ {
+ (*bucketptr)->Render(cameratrans,rasty,rendertools);
+ } else
+ {
+ alphabuckets.push_back(*bucketptr);
+ }
+ }
+ }
+
+ rasty->SetDepthMask(RAS_IRasterizer::KX_DEPTHMASK_DISABLED);
+
+ int numalphabuckets = alphabuckets.size();
+ for (vector<RAS_MaterialBucket*>::const_iterator it=alphabuckets.begin();
+ !(it==alphabuckets.end());it++)
+ {
+ (*it)->Render(cameratrans,rasty,rendertools);
+ }
+
+ alphabuckets.clear();
+
+
+ RAS_MaterialBucket::EndFrame();
+
+ rasty->SetDepthMask(RAS_IRasterizer::KX_DEPTHMASK_ENABLED);
+}
+
+RAS_MaterialBucket* RAS_BucketManager::RAS_BucketManagerFindBucket(RAS_IPolyMaterial * material)
+{
+
+ RAS_MaterialBucket** bucketptr = m_MaterialBuckets[*material];
+ RAS_MaterialBucket* bucket=NULL;
+ if (!bucketptr)
+ {
+ bucket = new RAS_MaterialBucket(material);
+ m_MaterialBuckets.insert(*material,bucket);
+
+ } else
+ {
+ bucket = *bucketptr;
+ }
+
+ return bucket;
+}
+
+void RAS_BucketManager::RAS_BucketManagerClearAll()
+{
+
+ int numbuckets = m_MaterialBuckets.size();
+ for (int i=0;i<numbuckets;i++)
+ {
+ RAS_MaterialBucket** bucketptr = m_MaterialBuckets.at(i);
+ if (bucketptr)
+ {
+ delete (*bucketptr);
+ *bucketptr=NULL;
+
+ }
+ }
+ m_MaterialBuckets.clear();
+
+}
diff --git a/source/gameengine/Rasterizer/RAS_BucketManager.h b/source/gameengine/Rasterizer/RAS_BucketManager.h
new file mode 100644
index 00000000000..72427473fc1
--- /dev/null
+++ b/source/gameengine/Rasterizer/RAS_BucketManager.h
@@ -0,0 +1,63 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+// this will be put in a class later on
+
+#ifndef __RAS_BUCKETMANAGER
+#define __RAS_BUCKETMANAGER
+
+#include "MT_Transform.h"
+#include "RAS_MaterialBucket.h"
+#include "GEN_Map.h"
+
+class RAS_BucketManager
+{
+
+ GEN_Map<class RAS_IPolyMaterial,class RAS_MaterialBucket*> m_MaterialBuckets;
+
+public:
+ RAS_BucketManager();
+ virtual ~RAS_BucketManager();
+
+ void Renderbuckets(const MT_Transform & cameratrans,
+ RAS_IRasterizer* rasty,
+ class RAS_IRenderTools* rendertools);
+
+ RAS_MaterialBucket* RAS_BucketManagerFindBucket(RAS_IPolyMaterial * material);
+
+
+private:
+ void RAS_BucketManagerClearAll();
+
+};
+
+#endif //__RAS_BUCKETMANAGER
+
diff --git a/source/gameengine/Rasterizer/RAS_CameraData.h b/source/gameengine/Rasterizer/RAS_CameraData.h
new file mode 100644
index 00000000000..5c9b1dd0e88
--- /dev/null
+++ b/source/gameengine/Rasterizer/RAS_CameraData.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 __RAS_CAMERADATA_H
+#define __RAS_CAMERADATA_H
+
+struct RAS_CameraData
+{
+ float m_lens;
+ float m_clipstart;
+ float m_clipend;
+};
+
+#endif //__RAS_CAMERADATA_H
diff --git a/source/gameengine/Rasterizer/RAS_Deformer.h b/source/gameengine/Rasterizer/RAS_Deformer.h
new file mode 100644
index 00000000000..9aeb85c5740
--- /dev/null
+++ b/source/gameengine/Rasterizer/RAS_Deformer.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 *****
+ */
+
+#ifndef RAS_DEFORMER
+#define RAS_DEFORMER
+
+#ifdef WIN32
+#pragma warning (disable:4786) // get rid of stupid stl-visual compiler debug warning
+#endif //WIN32
+
+#include "GEN_Map.h"
+
+class RAS_Deformer
+{
+public:
+ RAS_Deformer(){};
+ virtual ~RAS_Deformer(){};
+ virtual void Relink(GEN_Map<class GEN_HashedPtr, void*>*map)=0;
+ virtual bool Apply(class RAS_IPolyMaterial *polymat)=0;
+ virtual void Update(void)=0;
+ virtual RAS_Deformer *GetReplica()=0;
+protected:
+ class RAS_MeshObject *m_pMesh;
+};
+
+#endif
+
diff --git a/source/gameengine/Rasterizer/RAS_FramingManager.cpp b/source/gameengine/Rasterizer/RAS_FramingManager.cpp
new file mode 100644
index 00000000000..af0499bd348
--- /dev/null
+++ b/source/gameengine/Rasterizer/RAS_FramingManager.cpp
@@ -0,0 +1,234 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "RAS_FramingManager.h"
+
+#include "RAS_Rect.h"
+
+ void
+RAS_FramingManager::
+ComputeDefaultFrustum(
+ const float camnear,
+ const float camfar,
+ const float lens,
+ const float design_aspect_ratio,
+ RAS_FrameFrustum & frustum
+){
+
+ /*
+ * Magic Blender calculation.
+ * Blender does not give a Field of View as lens but a size
+ * at 16 units away from the lens.
+ */
+ float halfSize = 16.f * camnear / lens;
+ float sizeX;
+ float sizeY;
+
+ if (design_aspect_ratio > 1.f) {
+ // halfsize defines the width
+ sizeX = halfSize;
+ sizeY = halfSize/design_aspect_ratio;
+ } else {
+ // halfsize defines the height
+ sizeX = halfSize * design_aspect_ratio;
+ sizeY = halfSize;
+ }
+
+ frustum.x2 = sizeX;
+ frustum.x1 = -frustum.x2;
+ frustum.y2 = sizeY;
+ frustum.y1 = -frustum.y2;
+ frustum.camnear = camnear;
+ frustum.camfar = camfar;
+}
+
+ void
+RAS_FramingManager::
+ComputeBestFitViewRect(
+ const RAS_Rect &availableViewport,
+ const float design_aspect_ratio,
+ RAS_Rect &viewport
+){
+ // try and honour the aspect ratio when setting the
+ // drawable area. If we don't do this we are liable
+ // to get a lot of distortion in the rendered image.
+
+ int width = availableViewport.GetWidth();
+ int height = availableViewport.GetHeight();
+ float window_aspect = float(width)/float(height);
+
+ if (window_aspect < design_aspect_ratio) {
+ int v_height = (int)(width / design_aspect_ratio);
+ int left_over = (height - v_height) / 2;
+
+ viewport.SetLeft(availableViewport.GetLeft());
+ viewport.SetBottom(availableViewport.GetBottom() + left_over);
+ viewport.SetRight(availableViewport.GetLeft() + width);
+ viewport.SetTop(availableViewport.GetBottom() + left_over + v_height);
+
+ } else {
+ int v_width = (int)(height * design_aspect_ratio);
+ int left_over = (width - v_width) / 2;
+
+ viewport.SetLeft(availableViewport.GetLeft() + left_over);
+ viewport.SetBottom(availableViewport.GetBottom());
+ viewport.SetRight(availableViewport.GetLeft() + v_width + left_over);
+ viewport.SetTop(availableViewport.GetBottom() + height);
+ }
+}
+
+ void
+RAS_FramingManager::
+ComputeViewport(
+ const RAS_FrameSettings &settings,
+ const RAS_Rect &availableViewport,
+ RAS_Rect &viewport
+){
+
+ RAS_FrameSettings::RAS_FrameType type = settings.FrameType();
+ const int winx = availableViewport.GetWidth();
+ const int winy = availableViewport.GetHeight();
+
+ const float design_width = float(settings.DesignAspectWidth());
+ const float design_height = float(settings.DesignAspectHeight());
+
+ float design_aspect_ratio = float(1);
+
+ if (design_height == float(0)) {
+ // well this is ill defined
+ // lets just scale the thing
+
+ type = RAS_FrameSettings::e_frame_scale;
+ } else {
+ design_aspect_ratio = design_width/design_height;
+ }
+
+ switch (type) {
+
+ case RAS_FrameSettings::e_frame_scale :
+ case RAS_FrameSettings::e_frame_extend:
+ {
+ viewport.SetLeft(availableViewport.GetLeft());
+ viewport.SetBottom(availableViewport.GetBottom());
+ viewport.SetRight(availableViewport.GetLeft() + int(winx));
+ viewport.SetTop(availableViewport.GetBottom() + int(winy));
+
+ break;
+ }
+
+ case RAS_FrameSettings::e_frame_bars:
+ {
+ ComputeBestFitViewRect(
+ availableViewport,
+ design_aspect_ratio,
+ viewport
+ );
+
+ break;
+ }
+ default :
+ break;
+ }
+}
+
+ void
+RAS_FramingManager::
+ComputeFrustum(
+ const RAS_FrameSettings &settings,
+ const RAS_Rect &availableViewport,
+ const RAS_Rect &viewport,
+ const float lens,
+ const float camnear,
+ const float camfar,
+ RAS_FrameFrustum &frustum
+){
+
+ const int winx = availableViewport.GetWidth();
+ const int winy = availableViewport.GetHeight();
+
+ RAS_FrameSettings::RAS_FrameType type = settings.FrameType();
+
+ const float design_width = float(settings.DesignAspectWidth());
+ const float design_height = float(settings.DesignAspectHeight());
+
+ float design_aspect_ratio = float(1);
+
+ if (design_height == float(0)) {
+ // well this is ill defined
+ // lets just scale the thing
+
+ type = RAS_FrameSettings::e_frame_scale;
+ } else {
+ design_aspect_ratio = design_width/design_height;
+ }
+
+ ComputeDefaultFrustum(
+ camnear,
+ camfar,
+ lens,
+ design_aspect_ratio,
+ frustum
+ );
+
+ switch (type) {
+
+ case RAS_FrameSettings::e_frame_extend:
+ {
+ RAS_Rect vt;
+ ComputeBestFitViewRect(
+ availableViewport,
+ design_aspect_ratio,
+ vt
+ );
+
+ // now scale the calculated frustum by the difference
+ // between vt and the viewport in each axis.
+ // These are always > 1
+
+ float x_scale = float(viewport.GetWidth())/float(vt.GetWidth());
+ float y_scale = float(viewport.GetHeight())/float(vt.GetHeight());
+
+ frustum.x1 *= x_scale;
+ frustum.x2 *= x_scale;
+ frustum.y1 *= y_scale;
+ frustum.y2 *= y_scale;
+
+ break;
+ }
+ case RAS_FrameSettings::e_frame_scale :
+ case RAS_FrameSettings::e_frame_bars:
+ default :
+ break;
+ }
+}
+
+
+
diff --git a/source/gameengine/Rasterizer/RAS_FramingManager.h b/source/gameengine/Rasterizer/RAS_FramingManager.h
new file mode 100644
index 00000000000..581c6b56fc9
--- /dev/null
+++ b/source/gameengine/Rasterizer/RAS_FramingManager.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 *****
+ */
+#ifndef RAS_FRAMINGMANAGER_H
+#define RAS_FRAMINGMANAGER_H
+
+class RAS_Rect;
+
+/**
+ * @section RAS_FrameSettings
+ * This is a value type describing the framing used
+ * by a particular scene in the game engine.
+ * Each KX_Scene contains a RAS_FrameSetting describing
+ * how the frustum and viewport are to be modified
+ * depending on the canvas size.
+ *
+ * e_frame_scale means that the viewport is set to the current
+ * canvas size. If the view frustum aspect ratio is different
+ * to the canvas aspect this will lead to stretching.
+ *
+ * e_frame_extend means that the best fit viewport will be
+ * computed based upon the design aspect ratio
+ * and the view frustum will be adjusted so that
+ * more of the scene is visible.
+ *
+ * e_frame_bars means that the best fit viewport will be
+ * be computed based upon the design aspect ratio.
+ */
+
+class RAS_FrameSettings
+{
+public :
+
+ /**
+ * enum defining the policy to use
+ * in each axis.
+ */
+ enum RAS_FrameType {
+ e_frame_scale,
+ e_frame_extend,
+ e_frame_bars
+ };
+
+ /**
+ * Contructor
+ */
+
+ RAS_FrameSettings(
+ RAS_FrameType frame_type,
+ float bar_r,
+ float bar_g,
+ float bar_b,
+ unsigned int design_aspect_width,
+ unsigned int design_aspect_height
+ ):
+ m_frame_type(frame_type),
+ m_bar_r(bar_r),
+ m_bar_g(bar_g),
+ m_bar_b(bar_b),
+ m_design_aspect_width(design_aspect_width),
+ m_design_aspect_height(design_aspect_height)
+ {
+ };
+
+ RAS_FrameSettings(
+ ):
+ m_frame_type(e_frame_scale),
+ m_bar_r(0),
+ m_bar_g(0),
+ m_bar_b(0),
+ m_design_aspect_width(1),
+ m_design_aspect_height(1)
+ {
+ };
+
+ /**
+ * Accessors
+ */
+
+ const
+ RAS_FrameType &
+ FrameType(
+ ) const {
+ return m_frame_type;
+ };
+
+ float
+ BarRed(
+ ) const {
+ return m_bar_r;
+ };
+
+ float
+ BarGreen(
+ ) const {
+ return m_bar_g;
+ };
+
+ float
+ BarBlue(
+ ) const {
+ return m_bar_b;
+ };
+
+ unsigned int
+ DesignAspectWidth(
+ ) const {
+ return m_design_aspect_width;
+ };
+
+ unsigned int
+ DesignAspectHeight(
+ ) const {
+ return m_design_aspect_height;
+ };
+
+private :
+
+ /**
+ * private to force use of public constructor
+ */
+
+ RAS_FrameSettings(
+ const RAS_FrameSettings &
+ );
+
+ RAS_FrameType m_frame_type;
+ float m_bar_r;
+ float m_bar_g;
+ float m_bar_b;
+ unsigned int m_design_aspect_width;
+ unsigned int m_design_aspect_height;
+};
+
+struct RAS_FrameFrustum
+{
+ float camnear,camfar;
+ float x1,y1;
+ float x2,y2;
+};
+
+
+/**
+ * @section RAS_FramingManager
+ * This class helps to compute a view frustum
+ * and a viewport rectangle given the
+ * above settings and a description of the
+ * current canvas dimensions.
+ *
+ * You do not have to instantiate this class
+ * directly, it only contains static helper functions
+ */
+
+class RAS_FramingManager
+{
+public :
+
+ /**
+ * Compute a viewport given
+ * a RAS_FrameSettings and a description of the
+ * canvas.
+ */
+
+ static
+ void
+ ComputeViewport(
+ const RAS_FrameSettings &settings,
+ const RAS_Rect &availableViewport,
+ RAS_Rect &viewport
+ );
+
+
+ /**
+ * compute a frustrum given a valid viewport,
+ * RAS_FrameSettings, canvas description
+ * and camera description
+ */
+
+ static
+ void
+ ComputeFrustum(
+ const RAS_FrameSettings &settings,
+ const RAS_Rect &availableViewport,
+ const RAS_Rect &viewport,
+ const float lens,
+ const float camnear,
+ const float camfar,
+ RAS_FrameFrustum &frustum
+ );
+
+
+private :
+
+ static
+ void
+ ComputeDefaultFrustum(
+ const float camnear,
+ const float camfar,
+ const float lens,
+ const float design_aspect_ratio,
+ RAS_FrameFrustum & frustum
+ );
+
+ static
+ void
+ ComputeBestFitViewRect(
+ const RAS_Rect &availableViewport,
+ const float design_aspect_ratio,
+ RAS_Rect &viewport
+ );
+
+
+
+ /**
+ * Private constructor - this class is not meant
+ * for instanciation.
+ */
+
+ RAS_FramingManager(
+ );
+
+ RAS_FramingManager(
+ const RAS_FramingManager &
+ );
+};
+
+#endif
diff --git a/source/gameengine/Rasterizer/RAS_ICanvas.h b/source/gameengine/Rasterizer/RAS_ICanvas.h
new file mode 100644
index 00000000000..8060313b4be
--- /dev/null
+++ b/source/gameengine/Rasterizer/RAS_ICanvas.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 *****
+ */
+#ifndef __RAS_ICANVAS
+#define __RAS_ICANVAS
+
+/**
+ * 2D rendering device context. The connection from 3d rendercontext to 2d surface.
+ */
+
+class RAS_Rect;
+
+
+class RAS_ICanvas
+{
+public:
+ enum BufferType {
+ COLOR_BUFFER=1,
+ DEPTH_BUFFER=2
+ };
+
+ enum RAS_MouseState
+ {
+ MOUSE_INVISIBLE=1,
+ MOUSE_WAIT,
+ MOUSE_NORMAL
+ };
+
+ virtual
+ ~RAS_ICanvas(
+ ) {
+ };
+
+ virtual
+ void
+ Init(
+ ) = 0;
+
+ virtual
+ void
+ BeginFrame(
+ )=0;
+
+ virtual
+ void
+ EndFrame(
+ )=0;
+
+ /**
+ * Initializes the canvas for drawing. Drawing to the canvas is
+ * only allowed between BeginDraw() and EndDraw().
+ *
+ * @retval false Acquiring the canvas failed.
+ * @retval true Acquiring the canvas succeeded.
+ *
+ */
+
+ virtual
+ bool
+ BeginDraw(
+ )=0;
+
+ /**
+ * Unitializes the canvas for drawing.
+ */
+
+ virtual
+ void
+ EndDraw(
+ )=0;
+
+
+ /// probably needs some arguments for PS2 in future
+ virtual
+ void
+ SwapBuffers(
+ )=0;
+
+ virtual
+ void
+ ClearBuffer(
+ int type
+ )=0;
+
+ virtual
+ void
+ ClearColor(
+ float r,
+ float g,
+ float b,
+ float a
+ )=0;
+
+ virtual
+ int
+ GetWidth(
+ ) const = 0;
+
+ virtual
+ int
+ GetHeight(
+ ) const = 0;
+
+ virtual
+ const RAS_Rect &
+ GetDisplayArea(
+ ) const = 0;
+
+ virtual
+ RAS_Rect &
+ GetDisplayArea(
+ ) = 0;
+
+ /**
+ * Set the visible vieport
+ */
+
+ virtual
+ void
+ SetViewPort(
+ int x1, int y1,
+ int x2, int y2
+ ) = 0;
+
+ virtual
+ void
+ SetMouseState(
+ RAS_MouseState mousestate
+ )=0;
+
+ virtual
+ void
+ SetMousePosition(
+ int x,
+ int y
+ )=0;
+
+ virtual
+ void
+ MakeScreenShot(
+ const char* filename
+ )=0;
+};
+#endif //__RAS_ICANVAS
diff --git a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp
new file mode 100644
index 00000000000..7e1017b5c39
--- /dev/null
+++ b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.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 "RAS_IPolygonMaterial.h"
+
+
+RAS_IPolyMaterial::RAS_IPolyMaterial(const STR_String& texname,
+ bool ba,
+ const STR_String& matname,
+ int tile,
+ int tilexrep,
+ int tileyrep,
+ int mode,
+ int transparant,
+ int lightlayer,
+ bool bIsTriangle,
+ void* clientobject=NULL) :
+
+ m_texturename(texname),
+ m_materialname(matname),
+ m_tile(tile),
+ m_tilexrep(tilexrep),
+ m_tileyrep(tileyrep),
+ m_drawingmode (mode),
+ m_transparant(transparant),
+ m_lightlayer(lightlayer),
+ m_bIsTriangle(bIsTriangle)
+{
+ m_shininess = 35.0;
+ m_specular = MT_Vector3(0.5,0.5,0.5);
+ m_specularity = 1.0;
+ m_diffuse = MT_Vector3(0.5,0.5,0.5);
+}
+
+
+bool RAS_IPolyMaterial::Equals(const RAS_IPolyMaterial& lhs) const
+{
+ return (
+ this->m_texturename == lhs.m_texturename &&
+ this->m_tile == lhs.m_tile &&
+ this->m_tilexrep == lhs.m_tilexrep &&
+ this->m_tileyrep == lhs.m_tileyrep &&
+ this->m_transparant == lhs.m_transparant &&
+ this->m_drawingmode == lhs.m_drawingmode &&
+ this->m_bIsTriangle == lhs.m_bIsTriangle &&
+ this->m_lightlayer == lhs.m_lightlayer &&
+ this->m_materialname == lhs.m_materialname
+ );
+}
+
+
+
+int RAS_IPolyMaterial::GetLightLayer()
+{
+ return m_lightlayer;
+}
+
+
+
+bool RAS_IPolyMaterial::IsTransparant()
+{
+ return (m_transparant != 0);
+}
+
+
+
+bool RAS_IPolyMaterial::UsesTriangles()
+{
+ return m_bIsTriangle;
+}
+
+
+
+unsigned int RAS_IPolyMaterial::hash() const
+{
+ return m_texturename.hash();
+}
+
+
+
+int RAS_IPolyMaterial::GetDrawingMode()
+{
+ return m_drawingmode;
+}
+
+
+
+const STR_String& RAS_IPolyMaterial::GetMaterialName() const
+{
+ return m_materialname;
+}
+
+
+const STR_String& RAS_IPolyMaterial::GetTextureName() const
+{
+ return m_texturename;
+}
diff --git a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h
new file mode 100644
index 00000000000..dd5fadab008
--- /dev/null
+++ b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h
@@ -0,0 +1,123 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 __RAS_IPOLYGONMATERIAL
+#define __RAS_IPOLYGONMATERIAL
+
+#include "STR_HashedString.h"
+
+
+/**
+ * Polygon Material on which the material buckets are sorted
+ *
+ */
+#include "MT_Vector3.h"
+#include "STR_HashedString.h"
+
+class RAS_IRasterizer;
+
+class RAS_IPolyMaterial
+{
+ //todo: remove these variables from this interface/protocol class
+protected:
+ STR_HashedString m_texturename;
+ STR_String m_materialname; //also needed for touchsensor
+ int m_tile;
+ int m_tilexrep,m_tileyrep;
+ int m_drawingmode; // tface->mode
+ int m_transparant;
+ int m_lightlayer;
+ bool m_bIsTriangle;
+
+public:
+
+ MT_Vector3 m_diffuse;
+ float m_shininess;
+ MT_Vector3 m_specular;
+ float m_specularity;
+
+ /** Used to store caching information for materials. */
+ typedef void* TCachingInfo;
+
+ // care! these are taken from blender polygonflags, see file DNA_mesh_types.h for #define TF_BILLBOARD etc.
+ enum MaterialFlags
+ {
+ BILLBOARD_SCREENALIGNED = 256,
+ BILLBOARD_AXISALIGNED = 4096,
+ SHADOW =8192
+ };
+
+ RAS_IPolyMaterial(const STR_String& texname,
+ bool ba,
+ const STR_String& matname,
+ int tile,
+ int tilexrep,
+ int tileyrep,
+ int mode,
+ int transparant,
+ int lightlayer,
+ bool bIsTriangle,
+ void* clientobject);
+ virtual ~RAS_IPolyMaterial() {};
+
+ /**
+ * Returns the caching information for this material,
+ * This can be used to speed up the rasterizing process.
+ * @return The caching information.
+ */
+ virtual TCachingInfo GetCachingInfo(void) const { return 0; }
+
+ /**
+ * Activates the material in the rasterizer.
+ * On entry, the cachingInfo contains info about the last activated material.
+ * On exit, the cachingInfo should contain updated info about this material.
+ * @param rasty The rasterizer in which the material should be active.
+ * @param cachingInfo The information about the material used to speed up rasterizing.
+ */
+ virtual void Activate(RAS_IRasterizer* rasty, TCachingInfo& cachingInfo) const {}
+
+ bool Equals(const RAS_IPolyMaterial& lhs) const;
+ int GetLightLayer();
+ bool IsTransparant();
+ bool UsesTriangles();
+ unsigned int hash() const;
+ int GetDrawingMode();
+ const STR_String& GetMaterialName() const;
+ const STR_String& GetTextureName() const;
+};
+
+inline bool operator ==( const RAS_IPolyMaterial & rhs,const RAS_IPolyMaterial & lhs)
+{
+ return ( rhs.Equals(lhs));
+}
+
+
+#endif //__RAS_IPOLYGONMATERIAL
diff --git a/source/gameengine/Rasterizer/RAS_IRasterizer.h b/source/gameengine/Rasterizer/RAS_IRasterizer.h
new file mode 100644
index 00000000000..d3a2a74887c
--- /dev/null
+++ b/source/gameengine/Rasterizer/RAS_IRasterizer.h
@@ -0,0 +1,191 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 __RAS_IRASTERIZER
+#define __RAS_IRASTERIZER
+
+#ifdef WIN32
+#pragma warning (disable:4786)
+#endif
+
+#include "MT_CmMatrix4x4.h"
+#include "MT_Matrix4x4.h"
+
+class RAS_ICanvas;
+class RAS_IPolyMaterial;
+#include "RAS_MaterialBucket.h"
+
+/**
+ * 3D rendering device context interface.
+ */
+
+class RAS_IRasterizer
+{
+
+public:
+
+ RAS_IRasterizer(RAS_ICanvas* canv){};
+ virtual ~RAS_IRasterizer(){};
+ enum {
+ RAS_RENDER_3DPOLYGON_TEXT = 16384
+ };
+ enum {
+ KX_BOUNDINGBOX = 1,
+ KX_WIREFRAME,
+ KX_SOLID,
+ KX_SHADED,
+ KX_TEXTURED
+ };
+
+ enum {
+ KX_DEPTHMASK_ENABLED =1,
+ KX_DEPTHMASK_DISABLED,
+ };
+
+ enum {
+ RAS_STEREO_NOSTEREO = 1,
+ RAS_STEREO_QUADBUFFERED,
+ RAS_STEREO_ABOVEBELOW,
+ RAS_STEREO_INTERLACED,
+ };
+ enum {
+ RAS_STEREO_LEFTEYE = 1,
+ RAS_STEREO_RIGHTEYE,
+ };
+
+ virtual void SetDepthMask(int depthmask)=0;
+ virtual void SetMaterial(const RAS_IPolyMaterial& mat)=0;
+ virtual bool Init()=0;
+ virtual void Exit()=0;
+ virtual bool BeginFrame(int drawingmode, double time)=0;
+ virtual void ClearDepthBuffer()=0;
+ virtual void ClearCachingInfo(void)=0;
+ virtual void EndFrame()=0;
+ virtual void SetRenderArea()=0;
+
+ virtual void SetStereoMode(const int stereomode)=0;
+ virtual bool Stereo()=0;
+ virtual void SetEye(const int eye)=0;
+ virtual void SetEyeSeparation(const float eyeseparation)=0;
+ virtual void SetFocalLength(const float focallength)=0;
+
+ virtual void SwapBuffers()=0;
+ virtual void IndexPrimitives( const vecVertexArray& vertexarrays,
+ const vecIndexArrays & indexarrays,
+ int mode,
+ class RAS_IPolyMaterial* polymat,
+ class RAS_IRenderTools* rendertools,
+ bool useObjectColor,
+ const MT_Vector4& rgbacolor)=0;
+ virtual void IndexPrimitives_Ex( const vecVertexArray& vertexarrays,
+ const vecIndexArrays & indexarrays,
+ int mode,
+ class RAS_IPolyMaterial* polymat,
+ class RAS_IRenderTools* rendertools,
+ bool useObjectColor,
+ const MT_Vector4& rgbacolor)=0;
+ virtual void IndexPrimitives_3DText( const vecVertexArray& vertexarrays,
+ const vecIndexArrays & indexarrays,
+ int mode,
+ class RAS_IPolyMaterial* polymat,
+ class RAS_IRenderTools* rendertools,
+ bool useObjectColor,
+ const MT_Vector4& rgbacolor)=0;
+
+ virtual void SetProjectionMatrix(MT_CmMatrix4x4 & mat)=0;
+ /* This one should become our final version, methinks. */
+ /**
+ * Set the projection matrix for the rasterizer. This projects
+ * from camera coordinates to window coordinates.
+ * @param mat The projection matrix.
+ */
+ virtual void SetProjectionMatrix(MT_Matrix4x4 & mat)=0;
+ virtual void SetViewMatrix(const MT_Matrix4x4 & mat,
+ const MT_Vector3& campos,
+ const MT_Point3 &camLoc,
+ const MT_Quaternion &camOrientQuat)=0;
+ virtual const MT_Point3& GetCameraPosition()=0;
+ virtual void LoadViewMatrix()=0;
+
+ virtual void SetFog(float start,
+ float dist,
+ float r,
+ float g,
+ float b)=0;
+
+ virtual void SetFogColor(float r,
+ float g,
+ float b)=0;
+
+ virtual void SetFogStart(float start)=0;
+ virtual void SetFogEnd(float end)=0;
+
+ virtual void DisplayFog()=0;
+ virtual void DisableFog()=0;
+
+ virtual void SetBackColor(float red,
+ float green,
+ float blue,
+ float alpha)=0;
+
+ virtual void SetDrawingMode(int drawingmode)=0;
+ virtual int GetDrawingMode()=0;
+
+ virtual void EnableTextures(bool enable)=0;
+
+ virtual void SetCullFace(bool enable)=0;
+
+ virtual double GetTime()=0;
+
+ virtual MT_Matrix4x4 GetFrustumMatrix(
+ float left,
+ float right,
+ float bottom,
+ float top,
+ float frustnear,
+ float frustfar
+ )=0;
+
+ virtual void SetSpecularity(float specX,
+ float specY,
+ float specZ,
+ float specval)=0;
+
+ virtual void SetShinyness(float shiny)=0;
+ virtual void SetDiffuse(float difX,
+ float difY,
+ float difZ,
+ float diffuse)=0;
+
+};
+
+#endif //__RAS_IRASTERIZER
+
diff --git a/source/gameengine/Rasterizer/RAS_IRenderTools.cpp b/source/gameengine/Rasterizer/RAS_IRenderTools.cpp
new file mode 100644
index 00000000000..d52ba72af40
--- /dev/null
+++ b/source/gameengine/Rasterizer/RAS_IRenderTools.cpp
@@ -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 *****
+ */
+
+#include "RAS_IRenderTools.h"
+
+
+
+void RAS_IRenderTools::SetViewMat(const MT_Transform& trans)
+{
+ trans.getValue(m_viewmat);
+}
+
+
+
+void RAS_IRenderTools::SetClientObject(void* obj)
+{
+ if (m_clientobject != obj)
+ {
+ m_clientobject = obj;
+ m_modified = true;
+ }
+}
+
+
+
+void RAS_IRenderTools::SetAuxilaryClientInfo(void* inf)
+{
+ m_auxilaryClientInfo = inf;
+}
+
+
+
+void RAS_IRenderTools::AddLight(struct RAS_LightObject* lightobject)
+{
+ m_lights.push_back(lightobject);
+}
+
+
+
+void RAS_IRenderTools::RemoveLight(struct RAS_LightObject* lightobject)
+{
+ std::vector<struct RAS_LightObject*>::iterator lit =
+ std::find(m_lights.begin(),m_lights.end(),lightobject);
+
+ if (!(lit==m_lights.end()))
+ m_lights.erase(lit);
+
+}
diff --git a/source/gameengine/Rasterizer/RAS_IRenderTools.h b/source/gameengine/Rasterizer/RAS_IRenderTools.h
new file mode 100644
index 00000000000..ac9033c7186
--- /dev/null
+++ b/source/gameengine/Rasterizer/RAS_IRenderTools.h
@@ -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 *****
+ */
+#ifndef __RAS_IRENDERTOOLS
+#define __RAS_IRENDERTOOLS
+
+#include "MT_Transform.h"
+#include "RAS_IRasterizer.h"
+
+
+#include <vector>
+#include <algorithm>
+
+class RAS_IPolyMaterial;
+struct RAS_LightObject;
+
+class RAS_IRenderTools
+{
+
+protected:
+ float m_viewmat[16];
+ void* m_clientobject;
+ void* m_auxilaryClientInfo;
+
+ bool m_modified;
+
+ std::vector<struct RAS_LightObject*> m_lights;
+
+
+public:
+ enum RAS_TEXT_RENDER_MODE {
+ RAS_TEXT_RENDER_NODEF = 0,
+ RAS_TEXT_NORMAL,
+ RAS_TEXT_PADDED,
+ RAS_TEXT_MAX,
+ };
+
+ RAS_IRenderTools(
+ ) :
+ m_modified(true),
+ m_clientobject(NULL)
+ {
+ };
+
+ virtual
+ ~RAS_IRenderTools(
+ ) {};
+
+ virtual
+ void
+ BeginFrame(
+ RAS_IRasterizer* rasty
+ )=0;
+
+ virtual
+ void
+ EndFrame(
+ RAS_IRasterizer* rasty
+ )=0;
+
+ // the following function was formerly called 'Render'
+ // by it doesn't render anymore
+ // It only sets the transform for the rasterizer
+ // so must be renamed to 'applyTransform' or something
+
+ virtual
+ void
+ applyTransform(
+ class RAS_IRasterizer* rasty,
+ double* oglmatrix,
+ int drawingmode
+ )=0;
+
+ /**
+ * Renders 2D text string.
+ * @param mode The type of text
+ * @param text The string to render.
+ * @param xco Position on the screen (origin in lower left corner).
+ * @param yco Position on the screen (origin in lower left corner).
+ * @param width Width of the canvas to draw to.
+ * @param height Height of the canvas to draw to.
+ */
+ virtual
+ void
+ RenderText2D(
+ RAS_TEXT_RENDER_MODE mode,
+ const char* text,
+ int xco,
+ int yco,
+ int width,
+ int height
+ ) = 0;
+
+ // 3d text, mapped on polygon
+ virtual
+ void
+ RenderText(
+ int mode,
+ RAS_IPolyMaterial* polymat,
+ float v1[3],
+ float v2[3],
+ float v3[3],
+ float v4[3]
+ )=0;
+
+ virtual
+ void
+ SetViewMat(
+ const MT_Transform& trans
+ );
+
+ virtual
+ int
+ ProcessLighting(
+ int layer
+ )=0;
+
+ void
+ SetClientObject(
+ void* obj
+ );
+
+ void
+ SetAuxilaryClientInfo(
+ void* inf
+ );
+
+ virtual
+ void
+ PushMatrix(
+ )=0;
+
+ virtual
+ void
+ PopMatrix(
+ )=0;
+
+ virtual
+ void
+ AddLight(
+ struct RAS_LightObject* lightobject
+ );
+
+ virtual
+ void
+ RemoveLight(
+ struct RAS_LightObject* lightobject
+ );
+
+ virtual
+ class RAS_IPolyMaterial*
+ CreateBlenderPolyMaterial(
+ const STR_String &texname,
+ bool ba,
+ const STR_String& matname,
+ int tile,
+ int tilexrep,
+ int tileyrep,
+ int mode,
+ int transparant,
+ int lightlayer,
+ bool bIsTriangle,
+ void* clientobject,
+ void* tface
+ )=0;
+};
+
+#endif //__RAS_IRENDERTOOLS
diff --git a/source/gameengine/Rasterizer/RAS_LightObject.h b/source/gameengine/Rasterizer/RAS_LightObject.h
new file mode 100644
index 00000000000..cd2014ba678
--- /dev/null
+++ b/source/gameengine/Rasterizer/RAS_LightObject.h
@@ -0,0 +1,63 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 __RAS_LIGHTOBJECT_H
+#define __RAS_LIGHTOBJECT_H
+
+#include "MT_CmMatrix4x4.h"
+
+struct RAS_LightObject
+{
+ enum LightType{
+ LIGHT_SPOT,
+ LIGHT_SUN,
+ LIGHT_NORMAL
+ };
+ bool m_modified;
+ int m_layer;
+
+ float m_energy;
+ float m_distance;
+
+ float m_red;
+ float m_green;
+ float m_blue;
+
+ float m_att1;
+ float m_spotsize;
+ float m_spotblend;
+
+ LightType m_type;
+ MT_CmMatrix4x4* m_worldmatrix;
+
+};
+
+#endif //__RAS_LIGHTOBJECT_H
diff --git a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp
new file mode 100644
index 00000000000..ecb621c0d9d
--- /dev/null
+++ b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp
@@ -0,0 +1,248 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "RAS_MaterialBucket.h"
+
+#ifdef WIN32
+#pragma warning (disable:4786)
+#include <windows.h>
+#endif // WIN32
+
+#include "RAS_Polygon.h"
+#include "RAS_TexVert.h"
+#include "RAS_IRasterizer.h"
+#include "RAS_IRenderTools.h"
+#include "RAS_MeshObject.h"
+#include "RAS_Deformer.h" // __NLA
+
+
+
+KX_VertexIndex::KX_VertexIndex(int size)
+{
+ m_size = size;
+}
+
+
+
+void KX_VertexIndex::SetIndex(short loc,short index)
+{
+ m_indexarray[loc]=index;
+}
+
+
+
+
+bool KX_MeshSlot::Less(const KX_MeshSlot& lhs) const
+{
+ bool result = ((m_mesh < lhs.m_mesh ) ||
+ ((m_mesh == lhs.m_mesh)&&(m_OpenGLMatrix < lhs.m_OpenGLMatrix)));
+
+ return result;
+}
+
+
+
+RAS_MaterialBucket::RAS_MaterialBucket(RAS_IPolyMaterial* mat)
+ :m_bModified(true)
+{
+ m_bScheduled=true;
+ m_material = mat;
+}
+
+
+
+void RAS_MaterialBucket::SchedulePolygons(int drawingmode)
+{
+ m_bScheduled = true;
+}
+
+
+
+void RAS_MaterialBucket::ClearScheduledPolygons()
+{
+ m_bScheduled = false;
+}
+
+
+
+RAS_IPolyMaterial* RAS_MaterialBucket::GetPolyMaterial()
+{
+ return m_material;
+}
+
+
+
+void RAS_MaterialBucket::SetMeshSlot(KX_MeshSlot& ms)
+{
+ m_meshSlots.insert(ms);
+}
+
+
+
+void RAS_MaterialBucket::RemoveMeshSlot(KX_MeshSlot& ms)
+{
+ T_MeshSlotList::iterator it = m_meshSlots.find(ms);
+
+ if (!(it == m_meshSlots.end()))
+ m_meshSlots.erase(it);
+
+}
+
+
+
+void RAS_MaterialBucket::MarkVisibleMeshSlot(KX_MeshSlot& ms,
+ bool visible,
+ bool color,
+ const MT_Vector4& rgbavec)
+{
+ T_MeshSlotList::iterator it = m_meshSlots.find(ms);
+
+ assert (!(it == m_meshSlots.end()));
+ (*it).m_bVisible = visible;
+ (*it).m_bObjectColor = color;
+ (*it).m_RGBAcolor= rgbavec;
+}
+
+
+
+bool RAS_MaterialBucket::IsTransparant()
+{
+ return (m_material->IsTransparant());
+}
+
+
+
+void RAS_MaterialBucket::StartFrame()
+{
+}
+
+
+
+void RAS_MaterialBucket::EndFrame()
+{
+}
+
+
+
+void RAS_MaterialBucket::Render(const MT_Transform& cameratrans,
+ RAS_IRasterizer* rasty,
+ RAS_IRenderTools* rendertools)
+{
+
+ if (m_meshSlots.begin()== m_meshSlots.end())
+ return;
+
+ rendertools->SetViewMat(cameratrans);
+
+ rasty->SetMaterial(*m_material);
+
+ if (m_meshSlots.size() >0)
+ {
+
+ rendertools->SetClientObject((*m_meshSlots.begin()).m_clientObj);
+ }
+
+ bool dolights = m_material->GetDrawingMode()&16;
+
+ if ((rasty->GetDrawingMode() <= RAS_IRasterizer::KX_SOLID) || !dolights)
+ {
+ bool bUseLights = rendertools->ProcessLighting(-1);
+ }
+ else
+ {
+ bool bUseLights = rendertools->ProcessLighting(m_material->GetLightLayer());
+ }
+
+ int drawmode = (rasty->GetDrawingMode() < RAS_IRasterizer::KX_SOLID ?
+ 1: (m_material->UsesTriangles() ? 0 : 2));
+
+ for (T_MeshSlotList::const_iterator it = m_meshSlots.begin();
+ ! (it == m_meshSlots.end());it++)
+ {
+ if ((*it).m_bVisible)
+ {
+ rendertools->SetClientObject((*it).m_clientObj);
+
+ /* __NLA Do the deformation */
+ if ((*it).m_pDeformer)
+ (*it).m_pDeformer->Apply(m_material);
+ /* End __NLA */
+
+ rendertools->PushMatrix();
+ rendertools->applyTransform(rasty,(*it).m_OpenGLMatrix,m_material->GetDrawingMode());
+
+ // Use the text-specific IndexPrimitives for text faces
+ if (m_material->GetDrawingMode() & RAS_IRasterizer::RAS_RENDER_3DPOLYGON_TEXT)
+ {
+ rasty->IndexPrimitives_3DText(
+ (*it).m_mesh->GetVertexCache(m_material),
+ (*it).m_mesh->GetIndexCache(m_material),
+ drawmode,
+ m_material,
+ rendertools, // needed for textprinting on polys
+ (*it).m_bObjectColor,
+ (*it).m_RGBAcolor);
+
+ }
+ // Use the (slower) IndexPrimitives_Ex which can recalc face normals & such
+ // for deformed objects - eventually should be extended to recalc ALL normals
+ else if ((*it).m_pDeformer){
+ rasty->IndexPrimitives_Ex(
+ (*it).m_mesh->GetVertexCache(m_material),
+ (*it).m_mesh->GetIndexCache(m_material),
+ drawmode,
+ m_material,
+ rendertools, // needed for textprinting on polys
+ (*it).m_bObjectColor,
+ (*it).m_RGBAcolor
+ );
+ }
+ // Use the normal IndexPrimitives
+ else
+ {
+ rasty->IndexPrimitives(
+ (*it).m_mesh->GetVertexCache(m_material),
+ (*it).m_mesh->GetIndexCache(m_material),
+ drawmode,
+ m_material,
+ rendertools, // needed for textprinting on polys
+ (*it).m_bObjectColor,
+ (*it).m_RGBAcolor
+ );
+ }
+
+ rendertools->PopMatrix();
+ }
+ }
+}
+
+
diff --git a/source/gameengine/Rasterizer/RAS_MaterialBucket.h b/source/gameengine/Rasterizer/RAS_MaterialBucket.h
new file mode 100644
index 00000000000..06b1261c532
--- /dev/null
+++ b/source/gameengine/Rasterizer/RAS_MaterialBucket.h
@@ -0,0 +1,126 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 __RAS_MATERIALBUCKET
+#define __RAS_MATERIALBUCKET
+
+#include "RAS_TexVert.h"
+#include "GEN_Map.h"
+#include "STR_HashedString.h"
+
+#include "MT_Transform.h"
+#include "RAS_IPolygonMaterial.h"
+#include "RAS_Deformer.h" // __NLA
+#include <vector>
+#include <map>
+#include <set>
+using namespace std;
+
+typedef vector< vector<class RAS_TexVert>* > vecVertexArray;
+typedef vector<unsigned int> KX_IndexArray;
+typedef vector< KX_IndexArray* > vecIndexArrays;
+
+typedef vector<RAS_TexVert> KX_VertexArray;
+
+
+
+struct KX_VertexIndex {
+public:
+ KX_VertexIndex(int size);
+ void SetIndex(short loc,short index);
+ short m_vtxarray;
+ short m_indexarray[4];
+ short m_size;
+};
+
+
+
+class KX_MeshSlot
+{
+public:
+ void* m_clientObj;
+ RAS_Deformer* m_pDeformer; // __NLA
+ double* m_OpenGLMatrix;
+ class RAS_MeshObject* m_mesh;
+ mutable bool m_bVisible; // for visibility
+ mutable bool m_bObjectColor;
+ mutable MT_Vector4 m_RGBAcolor;
+
+ KX_MeshSlot() :m_bVisible(true), m_pDeformer(NULL) {}
+ // KX_MeshSlot() :m_bVisible(true) {}
+
+ bool Less(const KX_MeshSlot& lhs) const;
+};
+
+
+inline bool operator <( const KX_MeshSlot& rhs,const KX_MeshSlot& lhs)
+{
+ return ( rhs.Less(lhs));
+}
+
+
+class RAS_MaterialBucket
+{
+ typedef std::set<KX_MeshSlot> T_MeshSlotList;
+
+ T_MeshSlotList m_meshSlots;
+ bool m_bScheduled;
+ bool m_bModified;
+ RAS_IPolyMaterial* m_material;
+ double* m_pOGLMatrix;
+
+public:
+ RAS_MaterialBucket(RAS_IPolyMaterial* mat);
+ virtual ~RAS_MaterialBucket() {}
+
+ void Render(const MT_Transform& cameratrans,
+ class RAS_IRasterizer* rasty,
+ class RAS_IRenderTools* rendertools);
+
+ void SchedulePolygons(int drawingmode);
+ void ClearScheduledPolygons();
+
+ RAS_IPolyMaterial* GetPolyMaterial();
+ bool IsTransparant();
+
+ static void StartFrame();
+ static void EndFrame();
+
+ void SetMeshSlot(KX_MeshSlot& ms);
+ void RemoveMeshSlot(KX_MeshSlot& ms);
+ void MarkVisibleMeshSlot(KX_MeshSlot& ms,
+ bool visible,
+ bool color,
+ const MT_Vector4& rgbavec);
+};
+
+
+#endif //__KX_BUCKET
diff --git a/source/gameengine/Rasterizer/RAS_MeshObject.cpp b/source/gameengine/Rasterizer/RAS_MeshObject.cpp
new file mode 100644
index 00000000000..3c78b7cf991
--- /dev/null
+++ b/source/gameengine/Rasterizer/RAS_MeshObject.cpp
@@ -0,0 +1,635 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "RAS_MeshObject.h"
+
+#include "RAS_IRasterizer.h"
+#include "MT_MinMax.h"
+
+STR_String RAS_MeshObject::s_emptyname = "";
+
+
+
+KX_ArrayOptimizer::~KX_ArrayOptimizer()
+{
+ int i = 0;
+
+ for (vector<KX_VertexArray*>::iterator itv = m_VertexArrayCache1.begin();
+ !(itv == m_VertexArrayCache1.end());itv++)
+ {
+ delete (*itv);
+ }
+
+ for (vector<KX_IndexArray*>::iterator iti = m_IndexArrayCache1.begin();
+ !(iti == m_IndexArrayCache1.end());iti++)
+ {
+ delete (*iti);
+ }
+
+ m_TriangleArrayCount.clear();
+ m_VertexArrayCache1.clear();
+ m_IndexArrayCache1.clear();
+
+
+}
+
+
+
+RAS_MeshObject::RAS_MeshObject(int lightlayer)
+ : m_bModified(true),
+ m_lightlayer(lightlayer)
+{
+}
+
+
+
+RAS_MeshObject::~RAS_MeshObject()
+{
+ for (vector<RAS_Polygon*>::iterator it=m_Polygons.begin();!(it==m_Polygons.end());it++)
+ {
+ delete (*it);
+ }
+
+ ClearArrayData();
+}
+
+
+
+int RAS_MeshObject::GetLightLayer()
+{
+ return m_lightlayer;
+}
+
+
+
+int RAS_MeshObject::NumMaterials()
+{
+ return m_materials.size();
+}
+
+
+
+const STR_String& RAS_MeshObject::GetMaterialName(int matid)
+{
+ if (m_materials.size() > 0 && (matid < m_materials.size()))
+ {
+ BucketMaterialSet::iterator it = m_materials.begin();
+
+ for (int i = 1; i < m_materials.size(); i++)
+ {
+ it++;
+ }
+ return (*it)->GetPolyMaterial()->GetMaterialName();
+ }
+
+ return s_emptyname;
+}
+
+
+
+RAS_MaterialBucket* RAS_MeshObject::GetMaterialBucket(int matid)
+{
+ RAS_MaterialBucket* bucket = NULL;
+
+ if (m_materials.size() > 0 && (matid < m_materials.size()))
+ {
+ BucketMaterialSet::iterator it = m_materials.begin();
+ int i = matid;
+ while (i > 0)
+ {
+ i--;
+ it++;
+ }
+ bucket = *it;
+ }
+
+ return bucket;
+}
+
+
+
+int RAS_MeshObject::NumPolygons()
+{
+ return m_Polygons.size();
+}
+
+
+
+RAS_Polygon* RAS_MeshObject::GetPolygon(int num)
+{
+ return m_Polygons[num];
+}
+
+
+
+set<RAS_MaterialBucket*>::iterator RAS_MeshObject::GetFirstMaterial()
+{
+ return m_materials.begin();
+}
+
+
+
+set<RAS_MaterialBucket*>::iterator RAS_MeshObject::GetLastMaterial()
+{
+ return m_materials.end();
+}
+
+
+
+void RAS_MeshObject::SetName(STR_String name)
+{
+ m_name = name;
+}
+
+
+
+const STR_String& RAS_MeshObject::GetName()
+{
+ return m_name;
+}
+
+
+
+const STR_String& RAS_MeshObject::GetTextureName(int matid)
+{
+ if (m_materials.size() > 0 && (matid < m_materials.size()))
+ {
+ BucketMaterialSet::iterator it = m_materials.begin();
+ for (int i = 1; i < m_materials.size(); i++)
+ {
+ it++;
+ }
+
+ return (*it)->GetPolyMaterial()->GetTextureName();
+ }
+
+ return s_emptyname;
+}
+
+
+
+void RAS_MeshObject::AddPolygon(RAS_Polygon* poly)
+{
+ m_Polygons.push_back(poly);
+}
+
+
+
+void RAS_MeshObject::DebugColor(unsigned int abgr)
+{
+/*
+ int numpolys = NumPolygons();
+ for (int i=0;i<numpolys;i++)
+ {
+ RAS_Polygon* poly = m_polygons[i];
+ for (int v=0;v<poly->VertexCount();v++)
+ {
+ RAS_TexVert* vtx = poly->GetVertex(v);
+ vtx->setDebugRGBA(abgr);
+ }
+ }
+ */
+
+ m_debugcolor = abgr;
+}
+
+
+
+void RAS_MeshObject::SchedulePoly(const KX_VertexIndex& idx,
+ int numverts,
+ RAS_IPolyMaterial* mat)
+{
+ //int indexpos = m_IndexArrayCount[idx.m_vtxarray];
+ int indexidx = 0;
+ //m_IndexArrayCount[idx.m_vtxarray] = indexpos + 3;
+
+ KX_ArrayOptimizer* ao = GetArrayOptimizer(mat);
+ ao->m_IndexArrayCache1[idx.m_vtxarray]->push_back(idx.m_indexarray[0]);
+ ao->m_IndexArrayCache1[idx.m_vtxarray]->push_back(idx.m_indexarray[1]);
+ ao->m_IndexArrayCache1[idx.m_vtxarray]->push_back(idx.m_indexarray[2]);
+ if (!mat->UsesTriangles()) //if (!m_bUseTriangles)
+ {
+ //m_IndexArrayCount[idx.m_vtxarray] = indexpos+4;
+ ao->m_IndexArrayCache1[idx.m_vtxarray]->push_back(idx.m_indexarray[3]);
+ }
+}
+
+
+
+void RAS_MeshObject::ScheduleWireframePoly(const KX_VertexIndex& idx,
+ int numverts,
+ int edgecode,
+ RAS_IPolyMaterial* mat)
+{
+ //int indexpos = m_IndexArrayCount[idx.m_vtxarray];
+ int edgetrace = 1<<(numverts-1);
+ bool drawedge = (edgecode & edgetrace)!=0;
+ edgetrace = 1;
+ int prevvert = idx.m_indexarray[numverts-1];
+ KX_ArrayOptimizer* ao = GetArrayOptimizer(mat);
+
+ for (int v = 0; v < numverts; v++)
+ {
+ unsigned int curvert = idx.m_indexarray[v];
+ if (drawedge)
+ {
+ ao->m_IndexArrayCache1[idx.m_vtxarray]->push_back(prevvert);
+ ao->m_IndexArrayCache1[idx.m_vtxarray]->push_back(curvert);
+ }
+ prevvert = curvert;
+ drawedge = (edgecode & edgetrace)!=0;
+ edgetrace*=2;
+ }
+ //m_IndexArrayCount[idx.m_vtxarray] = indexpos;
+}
+
+int RAS_MeshObject::FindOrAddVertex(int vtxarray,
+ const MT_Point3& xyz,
+ const MT_Point2& uv,
+ const unsigned int rgbacolor,
+ const MT_Vector3& normal,
+ RAS_IPolyMaterial* mat,
+ int orgindex)
+{
+ short newnormal[3];
+
+ newnormal[0]=(short)((normal[0])*32767.0);
+ newnormal[1]=(short)((normal[1])*32767.0);
+ newnormal[2]=(short)((normal[2])*32767.0);
+
+ KX_ArrayOptimizer* ao = GetArrayOptimizer(mat);//*(m_matVertexArrays[*mat]);
+
+ int numverts = ao->m_VertexArrayCache1[vtxarray]->size();//m_VertexArrayCount[vtxarray];
+
+#define KX_FIND_SHARED_VERTICES
+#ifdef KX_FIND_SHARED_VERTICES
+
+ std::vector<RAS_MatArrayIndex>::iterator it = m_xyz_index_to_vertex_index_mapping[orgindex].begin();
+ int index=-1;
+ while (index < 0 && !(it == m_xyz_index_to_vertex_index_mapping[orgindex].end()))
+ {
+ if ((*it).m_arrayindex1 == ao->m_index1 &&
+ ((*it).m_array == vtxarray) &&
+ (RAS_IPolyMaterial*) (*it).m_matid == mat
+ )
+ {
+ return (*it).m_index;
+ }
+ it++;
+ }
+
+ if (index >= 0)
+ return index;
+#endif // KX_FIND_SHARED_VERTICES
+
+ // no vertex found, add one
+ ao->m_VertexArrayCache1[vtxarray]->push_back(RAS_TexVert (xyz,uv,rgbacolor,newnormal, 0));
+ // printf("(%f,%f,%f) ",xyz[0],xyz[1],xyz[2]);
+ RAS_MatArrayIndex idx;
+ idx.m_arrayindex1 = ao->m_index1;
+ idx.m_array = vtxarray;
+ idx.m_index = numverts;
+ idx.m_matid = (int) mat;
+ m_xyz_index_to_vertex_index_mapping[orgindex].push_back(idx);
+
+ return numverts;
+}
+
+
+
+const vecVertexArray& RAS_MeshObject::GetVertexCache (RAS_IPolyMaterial* mat)
+{
+ KX_ArrayOptimizer* ao = GetArrayOptimizer(mat);//*(m_matVertexArrays[*mat]);
+
+ return ao->m_VertexArrayCache1;
+}
+
+
+
+int RAS_MeshObject::GetVertexArrayLength(RAS_IPolyMaterial* mat)
+{
+ int len = 0;
+
+ const vecVertexArray & vertexvec = GetVertexCache(mat);
+ vector<KX_VertexArray*>::const_iterator it = vertexvec.begin();
+
+ for (; it != vertexvec.end(); it++)
+ {
+ len += (*it)->size();
+ }
+
+ return len;
+}
+
+
+
+RAS_TexVert* RAS_MeshObject::GetVertex(int matid,
+ int index)
+{
+ RAS_TexVert* vertex = NULL;
+
+ RAS_MaterialBucket* bucket = GetMaterialBucket(matid);
+ if (bucket)
+ {
+ RAS_IPolyMaterial* mat = bucket->GetPolyMaterial();
+ if (mat)
+ {
+ const vecVertexArray & vertexvec = GetVertexCache(mat);
+ vector<KX_VertexArray*>::const_iterator it = vertexvec.begin();
+
+ for (int len = 0; it != vertexvec.end(); it++)
+ {
+ if (index < len + (*it)->size())
+ {
+ vertex = &(*(*it))[index-len];
+ break;
+ }
+ else
+ {
+ len += (*it)->size();
+ }
+ }
+ }
+ }
+
+ return vertex;
+}
+
+
+
+const vecIndexArrays& RAS_MeshObject::GetIndexCache (RAS_IPolyMaterial* mat)
+{
+ KX_ArrayOptimizer* ao = GetArrayOptimizer(mat);//*(m_matVertexArrays[*mat]);
+
+ return ao->m_IndexArrayCache1;
+}
+
+
+
+KX_ArrayOptimizer* RAS_MeshObject::GetArrayOptimizer(RAS_IPolyMaterial* polymat)
+{
+ KX_ArrayOptimizer** aop = (m_matVertexArrayS[*polymat]);
+
+ if (aop)
+ return *aop;
+
+ int numelements = m_matVertexArrayS.size();
+ m_sortedMaterials.push_back(polymat);
+
+ KX_ArrayOptimizer* ao = new KX_ArrayOptimizer(numelements);
+ m_matVertexArrayS.insert(*polymat,ao);
+
+ return ao;
+}
+
+
+
+void RAS_MeshObject::Bucketize(double* oglmatrix,
+ void* clientobj,
+ bool useObjectColor,
+ const MT_Vector4& rgbavec)
+{
+ KX_MeshSlot ms;
+ ms.m_clientObj = clientobj;
+ ms.m_mesh = this;
+ ms.m_OpenGLMatrix = oglmatrix;
+ ms.m_bObjectColor = useObjectColor;
+ ms.m_RGBAcolor = rgbavec;
+
+ int i=0;
+ for (BucketMaterialSet::iterator it = m_materials.begin();it!=m_materials.end();it++)
+ {
+ RAS_MaterialBucket* bucket = *it;
+ bucket->SchedulePolygons(0);
+ KX_ArrayOptimizer* oa = GetArrayOptimizer(bucket->GetPolyMaterial());
+ bucket->SetMeshSlot(ms);
+ }
+
+}
+
+
+
+void RAS_MeshObject::MarkVisible(double* oglmatrix,
+ void* clientobj,
+ bool visible,
+ bool useObjectColor,
+ const MT_Vector4& rgbavec)
+{
+ KX_MeshSlot ms;
+ ms.m_clientObj = clientobj;
+ ms.m_mesh = this;
+ ms.m_OpenGLMatrix = oglmatrix;
+ ms.m_RGBAcolor = rgbavec;
+ ms.m_bObjectColor= useObjectColor;
+
+ for (BucketMaterialSet::iterator it = m_materials.begin();it!=m_materials.end();it++)
+ {
+ RAS_MaterialBucket* bucket = *it;
+ bucket->SchedulePolygons(0);
+ KX_ArrayOptimizer* oa = GetArrayOptimizer(bucket->GetPolyMaterial());
+ bucket->MarkVisibleMeshSlot(ms,visible,useObjectColor,rgbavec);
+ }
+}
+
+
+
+void RAS_MeshObject::RemoveFromBuckets(double* oglmatrix,
+ void* clientobj)
+{
+ KX_MeshSlot ms;
+ ms.m_clientObj = clientobj;
+ ms.m_mesh = this;
+ ms.m_OpenGLMatrix = oglmatrix;
+
+ for (BucketMaterialSet::iterator it = m_materials.begin();it!=m_materials.end();it++)
+ {
+ RAS_MaterialBucket* bucket = *it;
+ RAS_IPolyMaterial* polymat = bucket->GetPolyMaterial();
+ bucket->SchedulePolygons(0);
+ //KX_ArrayOptimizer* oa = GetArrayOptimizer(polymat);
+ bucket->RemoveMeshSlot(ms);
+ }
+
+}
+
+
+
+/*
+ * RAS_MeshObject::GetVertex returns the vertex located somewhere in the vertexpool
+ * it is the clients responsibility to make sure the array and index are valid
+ */
+RAS_TexVert* RAS_MeshObject::GetVertex(short array,
+ short index,
+ RAS_IPolyMaterial* polymat)
+{
+ KX_ArrayOptimizer* ao = GetArrayOptimizer(polymat);//*(m_matVertexArrays[*polymat]);
+ return &((*(ao->m_VertexArrayCache1)[array])[index]);
+}
+
+
+
+void RAS_MeshObject::ClearArrayData()
+{
+ for (int i=0;i<m_matVertexArrayS.size();i++)
+ { KX_ArrayOptimizer** ao = m_matVertexArrayS.at(i);
+ if (ao)
+ delete *ao;
+ }
+}
+
+
+
+/**
+ * RAS_MeshObject::CreateNewVertices creates vertices within sorted pools of vertices that share same material
+*/
+int RAS_MeshObject::FindVertexArray(int numverts,
+ RAS_IPolyMaterial* polymat)
+{
+ bool found=false;
+ int array=-1;
+
+ KX_ArrayOptimizer* ao = GetArrayOptimizer(polymat);
+
+ for (int i=0;i<ao->m_VertexArrayCache1.size();i++)
+ {
+ if ( (ao->m_TriangleArrayCount[i] + (numverts-2)) < BUCKET_MAX_TRIANGLES)
+ {
+ if((ao->m_VertexArrayCache1[i]->size()+numverts < BUCKET_MAX_INDICES))
+ {
+ array = i;
+ ao->m_TriangleArrayCount[array]+=numverts-2;
+ break;
+ }
+ }
+ else
+ {
+ int i=0;
+ }
+ }
+
+ if (array == -1)
+ {
+ array = ao->m_VertexArrayCache1.size();
+ vector<RAS_TexVert>* va = new vector<RAS_TexVert>;
+ ao->m_VertexArrayCache1.push_back(va);
+ KX_IndexArray *ia = new KX_IndexArray();
+ ao->m_IndexArrayCache1.push_back(ia);
+ ao->m_TriangleArrayCount.push_back(numverts-2);
+ }
+
+ return array;
+}
+
+
+
+
+//void RAS_MeshObject::Transform(const MT_Transform& trans)
+//{
+ //m_trans.translate(MT_Vector3(0,0,1));//.operator *=(trans);
+
+// for (int i=0;i<m_Polygons.size();i++)
+// {
+// m_Polygons[i]->Transform(trans);
+// }
+//}
+
+
+/*
+void RAS_MeshObject::RelativeTransform(const MT_Vector3& vec)
+{
+ for (int i=0;i<m_Polygons.size();i++)
+ {
+ m_Polygons[i]->RelativeTransform(vec);
+ }
+}
+*/
+
+
+
+void RAS_MeshObject::UpdateMaterialList()
+{
+ m_materials.clear();
+ int numpolys = m_Polygons.size();
+ // for all polygons, find out which material they use, and add it to the set of materials
+ for (int i=0;i<numpolys;i++)
+ {
+ m_materials.insert(m_Polygons[i]->GetMaterial());
+ }
+ int nummaterials = m_materials.size();
+
+}
+
+
+
+void RAS_MeshObject::SchedulePolygons(int drawingmode,RAS_IRasterizer* rasty)
+{
+ int nummaterials = m_materials.size();
+ int i;
+
+ if (m_bModified)
+ {
+ for (BucketMaterialSet::iterator it = m_materials.begin();it!=m_materials.end();it++)
+ {
+ RAS_MaterialBucket* bucket = *it;
+
+ bucket->SchedulePolygons(drawingmode);
+ }
+
+ int numpolys = m_Polygons.size();
+
+ if ((rasty->GetDrawingMode() > RAS_IRasterizer::KX_BOUNDINGBOX) &&
+ (rasty->GetDrawingMode() < RAS_IRasterizer::KX_SOLID))
+ {
+ for (i=0;i<numpolys;i++)
+ {
+ RAS_Polygon* poly = m_Polygons[i];
+ if (poly->IsVisible())
+ ScheduleWireframePoly(poly->GetVertexIndexBase(),poly->VertexCount(),poly->GetEdgeCode()
+ ,poly->GetMaterial()->GetPolyMaterial());
+
+ }
+ }
+ else
+ {
+ for (i=0;i<numpolys;i++)
+ {
+ RAS_Polygon* poly = m_Polygons[i];
+ if (poly->IsVisible())
+ {
+ SchedulePoly(poly->GetVertexIndexBase(),poly->VertexCount(),poly->GetMaterial()->GetPolyMaterial());
+ }
+ }
+ }
+
+ m_bModified = false;
+ }
+ // }
+}
diff --git a/source/gameengine/Rasterizer/RAS_MeshObject.h b/source/gameengine/Rasterizer/RAS_MeshObject.h
new file mode 100644
index 00000000000..95a2858d7bf
--- /dev/null
+++ b/source/gameengine/Rasterizer/RAS_MeshObject.h
@@ -0,0 +1,230 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 __RAS_MESHOBJECT
+#define __RAS_MESHOBJECT
+
+
+#ifdef WIN32
+// disable the STL warnings ("debug information length > 255")
+#pragma warning (disable:4786)
+#endif
+
+#include <vector>
+#include <set>
+
+#include "RAS_Polygon.h"
+#include "MT_Transform.h"
+
+#include "GEN_HashedPtr.h"
+
+class KX_ArrayOptimizer
+{
+public:
+ KX_ArrayOptimizer(int index)
+ : m_index1(index)
+ {};
+ virtual ~KX_ArrayOptimizer();
+
+ vector<KX_VertexArray*> m_VertexArrayCache1;
+ vector<int> m_TriangleArrayCount;
+ vector<KX_IndexArray*> m_IndexArrayCache1;
+
+ /**
+ order in which they are stored into the mesh
+ */
+ int m_index1;
+};
+
+struct RAS_TriangleIndex
+{
+public:
+ int m_index[3];
+ bool m_collider;
+};
+
+class RAS_MatArrayIndex
+{
+public:
+
+ int m_arrayindex1;
+ int m_matid;
+ int m_array;
+ int m_index;
+
+ inline bool Less(const RAS_MatArrayIndex& lhs) const {
+ bool result =
+ ( (m_matid < lhs.m_matid) ||
+ ((m_matid == lhs.m_matid)&&(m_array < lhs.m_array)) ||
+ ((m_matid == lhs.m_matid) && (m_array == lhs.m_array) &&
+ (m_index < lhs.m_index))
+
+ );
+ return result;
+
+ }
+
+
+};
+inline bool operator <( const RAS_MatArrayIndex& rhs,const RAS_MatArrayIndex& lhs)
+{
+ return ( rhs.Less(lhs));
+}
+
+
+class RAS_MeshObject
+{
+
+ enum { BUCKET_MAX_INDICES = 2048 };//2048};//8192};
+ enum { BUCKET_MAX_TRIANGLES = 1024 };
+
+ // GEN_Map<class RAS_IPolyMaterial,KX_ArrayOptimizer*> m_matVertexArrayS;
+ //vector<class RAS_IPolyMaterial*,KX_ArrayOptimizer> m_vertexArrays;
+ virtual KX_ArrayOptimizer* GetArrayOptimizer(RAS_IPolyMaterial* polymat);
+ //vector<RAS_Polygon*> m_polygons;
+
+ unsigned int m_debugcolor;
+ bool m_bModified;
+ int m_lightlayer;
+
+ vector<class RAS_Polygon*> m_Polygons;
+ STR_String m_name;
+ static STR_String s_emptyname;
+
+protected:
+ GEN_Map<class RAS_IPolyMaterial,KX_ArrayOptimizer*> m_matVertexArrayS;
+ typedef set<class RAS_MaterialBucket*> BucketMaterialSet;
+
+ BucketMaterialSet m_materials;
+public:
+ // for now, meshes need to be in a certain layer (to avoid sorting on lights in realtime)
+ RAS_MeshObject(int lightlayer);
+ virtual ~RAS_MeshObject();
+
+ vector<RAS_IPolyMaterial*> m_sortedMaterials;
+ vector<vector<RAS_MatArrayIndex> > m_xyz_index_to_vertex_index_mapping;
+ vector<RAS_TriangleIndex > m_triangle_indices;
+
+ int GetLightLayer();
+ int NumMaterials();
+ const STR_String& GetMaterialName(int matid);
+ RAS_MaterialBucket* GetMaterialBucket(int matid);
+ const STR_String& GetTextureName(int matid);
+ virtual void AddPolygon(RAS_Polygon* poly);
+ void UpdateMaterialList();
+
+ int NumPolygons();
+ RAS_Polygon* GetPolygon(int num);
+
+ virtual void Bucketize(
+ double* oglmatrix,
+ void* clientobj,
+ bool useObjectColor,
+ const MT_Vector4& rgbavec
+ );
+
+ void RemoveFromBuckets(
+ double* oglmatrix,
+ void* clientobj
+ );
+
+ void MarkVisible(
+ double* oglmatrix,
+ void* clientobj,
+ bool visible,
+ bool useObjectColor,
+ const MT_Vector4& rgbavec
+ );
+
+ void DebugColor(unsigned int abgr);
+
+ void SchedulePolygons(
+ int drawingmode,
+ class RAS_IRasterizer* rasty
+ );
+
+ void ClearArrayData();
+
+ set<RAS_MaterialBucket*>::iterator GetFirstMaterial();
+ set<RAS_MaterialBucket*>::iterator GetLastMaterial();
+
+ virtual RAS_TexVert* GetVertex(
+ short array,
+ short index,
+ RAS_IPolyMaterial* polymat
+ );
+
+ virtual int FindVertexArray(
+ int numverts,
+ RAS_IPolyMaterial* polymat
+ );
+
+ void SchedulePoly(
+ const KX_VertexIndex& idx,
+ int numverts,
+ RAS_IPolyMaterial* mat
+ );
+
+ void ScheduleWireframePoly(
+ const KX_VertexIndex& idx,
+ int numverts,
+ int edgecode,
+ RAS_IPolyMaterial* mat
+ );
+
+ // find (and share) or add vertices
+ // for some speedup, only the last 20 added vertices are searched for equality
+
+ virtual int FindOrAddVertex(
+ int vtxarray,
+ const MT_Point3& xyz,
+ const MT_Point2& uv,
+ const unsigned int rgbacolor,
+ const MT_Vector3& normal,
+ RAS_IPolyMaterial* mat,
+ int orgindex
+ );
+
+ const vecVertexArray& GetVertexCache (RAS_IPolyMaterial* mat);
+
+ int GetVertexArrayLength(RAS_IPolyMaterial* mat);
+
+ RAS_TexVert* GetVertex(
+ int matid,
+ int index
+ );
+
+ const vecIndexArrays& GetIndexCache (RAS_IPolyMaterial* mat);
+ void SetName(STR_String name);
+ const STR_String& GetName();
+};
+
+#endif //__RAS_MESHOBJECT
diff --git a/source/gameengine/Rasterizer/RAS_ObjectColor.h b/source/gameengine/Rasterizer/RAS_ObjectColor.h
new file mode 100644
index 00000000000..217ca9c8343
--- /dev/null
+++ b/source/gameengine/Rasterizer/RAS_ObjectColor.h
@@ -0,0 +1,41 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 __RAS_OBJECTCOLOR_H
+#define __RAS_OBJECTCOLOR_H
+
+struct RAS_ObjectColor {
+ float m_red;
+ float m_green;
+ float m_blue;
+};
+
+#endif //__RAS_OBJECTCOLOR_H
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/Makefile b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/Makefile
new file mode 100644
index 00000000000..c03aab3422e
--- /dev/null
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/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 *****
+#
+# Bounce make to subdirectories.
+#
+
+LIBNAME = OpenGLrasterizer
+DIR = $(OCGDIR)/gameengine/$(LIBNAME)
+
+include nan_compile.mk
+
+CCFLAGS += $(LEVEL_1_CPP_WARNINGS)
+
+CPPFLAGS += -I$(OPENGL_HEADERS)
+CPPFLAGS += -I$(NAN_STRING)/include
+CPPFLAGS += -I$(NAN_MOTO)/include
+CPPFLAGS += -I../../../kernel/gen_system
+CPPFLAGS += -I..
+
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_CheckVertexArrays.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_CheckVertexArrays.cpp
new file mode 100644
index 00000000000..ff57e7ab102
--- /dev/null
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_CheckVertexArrays.cpp
@@ -0,0 +1,61 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "RAS_CheckVertexArrays.h"
+
+#ifdef WIN32
+#include <windows.h>
+#endif // WIN32
+#include "GL/gl.h"
+
+#include "STR_String.h"
+
+
+bool RAS_SystemSupportsVertexArrays() {
+
+ bool result = false;
+
+ char* ext = (char*) glGetString(GL_EXTENSIONS);
+ STR_String extensions;
+
+ if (ext)
+ extensions = STR_String(ext);
+
+#ifdef WIN32
+ if (extensions.Find("GL_EXT_compiled_vertex_array") >= 0)
+ {
+ result=true;
+ }
+#endif //WIN32
+
+ return result;
+
+}
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_CheckVertexArrays.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_CheckVertexArrays.h
new file mode 100644
index 00000000000..f9edafb7d2e
--- /dev/null
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_CheckVertexArrays.h
@@ -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 *****
+ */
+#ifndef __RAS_CHECKVERTEXARRAYS
+#define __RAS_CHECKVERTEXARRAYS
+
+bool RAS_SystemSupportsVertexArrays();
+
+#endif //__RAS_CHECKVERTEXARRAYS
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp
new file mode 100644
index 00000000000..32b5852137b
--- /dev/null
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp
@@ -0,0 +1,1226 @@
+#include "RAS_OpenGLRasterizer.h"
+
+#ifdef WIN32
+#include <windows.h>
+#endif // WIN32
+#include "GL/gl.h"
+
+#include "RAS_Rect.h"
+#include "RAS_TexVert.h"
+#include "MT_CmMatrix4x4.h"
+#include "RAS_IRenderTools.h" // rendering text
+
+
+RAS_OpenGLRasterizer::RAS_OpenGLRasterizer(RAS_ICanvas* canvas)
+ :RAS_IRasterizer(canvas),
+ m_2DCanvas(canvas),
+ m_fogenabled(false),
+ m_materialCachingInfo(0),
+ m_noOfScanlines(32)
+{
+ m_viewmatrix.Identity();
+ m_stereomode = RAS_STEREO_NOSTEREO;
+}
+
+
+
+RAS_OpenGLRasterizer::~RAS_OpenGLRasterizer()
+{
+}
+
+
+
+void Myinit_gl_stuff(void)
+{
+ float mat_specular[] = { 0.5, 0.5, 0.5, 1.0 };
+ float mat_shininess[] = { 35.0 };
+/* float one= 1.0; */
+ int a, x, y;
+ GLubyte pat[32*32];
+ const GLubyte *patc= pat;
+
+ glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_specular);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
+
+
+#if defined(__FreeBSD) || defined(__linux__)
+ glDisable(GL_DITHER); /* op sgi/sun hardware && 12 bits */
+#endif
+
+ /* no local viewer, looks ugly in ortho mode */
+ /* glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, &one); */
+
+ glDepthFunc(GL_LEQUAL);
+ /* scaling matrices */
+ glEnable(GL_NORMALIZE);
+
+ glShadeModel(GL_FLAT);
+
+ glDisable(GL_ALPHA_TEST);
+ glDisable(GL_BLEND);
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_FOG);
+ glDisable(GL_LIGHTING);
+ glDisable(GL_LOGIC_OP);
+ glDisable(GL_STENCIL_TEST);
+ glDisable(GL_TEXTURE_1D);
+ glDisable(GL_TEXTURE_2D);
+
+ glPixelTransferi(GL_MAP_COLOR, GL_FALSE);
+ glPixelTransferi(GL_RED_SCALE, 1);
+ glPixelTransferi(GL_RED_BIAS, 0);
+ glPixelTransferi(GL_GREEN_SCALE, 1);
+ glPixelTransferi(GL_GREEN_BIAS, 0);
+ glPixelTransferi(GL_BLUE_SCALE, 1);
+ glPixelTransferi(GL_BLUE_BIAS, 0);
+ glPixelTransferi(GL_ALPHA_SCALE, 1);
+ glPixelTransferi(GL_ALPHA_BIAS, 0);
+
+ a = 0;
+ for(x=0; x<32; x++)
+ {
+ for(y=0; y<4; y++)
+ {
+ if( (x) & 1) pat[a++]= 0x88;
+ else pat[a++]= 0x22;
+ }
+ }
+
+ glPolygonStipple(patc);
+}
+
+
+
+bool RAS_OpenGLRasterizer::Init()
+{
+
+ Myinit_gl_stuff();
+
+ m_redback = 0.4375;
+ m_greenback = 0.4375;
+ m_blueback = 0.4375;
+ m_alphaback = 0.0;
+
+ // enable both vertexcolor AND lighting color
+ glEnable(GL_COLOR_MATERIAL);
+
+ glClearColor(m_redback,m_greenback,m_blueback,m_alphaback);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ glShadeModel(GL_SMOOTH);
+
+ return true;
+}
+
+
+
+void RAS_OpenGLRasterizer::SetBackColor(float red,
+ float green,
+ float blue,
+ float alpha)
+{
+ m_redback = red;
+ m_greenback = green;
+ m_blueback = blue;
+ m_alphaback = alpha;
+}
+
+
+
+void RAS_OpenGLRasterizer::SetFogColor(float r,
+ float g,
+ float b)
+{
+ m_fogr = r;
+ m_fogg = g;
+ m_fogb = b;
+ m_fogenabled = true;
+}
+
+
+
+void RAS_OpenGLRasterizer::SetFogStart(float start)
+{
+ m_fogstart = start;
+ m_fogenabled = true;
+}
+
+
+
+void RAS_OpenGLRasterizer::SetFogEnd(float fogend)
+{
+ m_fogdist = fogend;
+ m_fogenabled = true;
+}
+
+
+
+void RAS_OpenGLRasterizer::SetFog(float start,
+ float dist,
+ float r,
+ float g,
+ float b)
+{
+ m_fogstart = start;
+ m_fogdist = dist;
+ m_fogr = r;
+ m_fogg = g;
+ m_fogb = b;
+ m_fogenabled = true;
+}
+
+
+
+void RAS_OpenGLRasterizer::DisableFog()
+{
+ m_fogenabled = false;
+}
+
+
+
+void RAS_OpenGLRasterizer::DisplayFog()
+{
+ if ((m_drawingmode >= KX_SOLID) && m_fogenabled)
+ {
+ float params[5];
+ glFogi(GL_FOG_MODE, GL_LINEAR);
+ glFogf(GL_FOG_DENSITY, 0.1f);
+ glFogf(GL_FOG_START, m_fogstart);
+ glFogf(GL_FOG_END, m_fogstart + m_fogdist);
+ params[0]= m_fogr;
+ params[1]= m_fogg;
+ params[2]= m_fogb;
+ params[3]= 0.0;
+ glFogfv(GL_FOG_COLOR, params);
+ glEnable(GL_FOG);
+ }
+ else
+ {
+ glDisable(GL_FOG);
+ }
+}
+
+
+
+void RAS_OpenGLRasterizer::SetMaterial(const RAS_IPolyMaterial& mat)
+{
+ if (mat.GetCachingInfo() != m_materialCachingInfo)
+ {
+ mat.Activate(this, m_materialCachingInfo);
+ }
+}
+
+
+
+void RAS_OpenGLRasterizer::Exit()
+{
+
+ glEnable(GL_CULL_FACE);
+ glEnable(GL_DEPTH_TEST);
+ glClearDepth(1.0);
+ glClearColor(m_redback, m_greenback, m_blueback, m_alphaback);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glDepthMask (GL_TRUE);
+ glDepthFunc(GL_LEQUAL);
+ glBlendFunc(GL_ONE, GL_ZERO);
+
+ glDisable(GL_LIGHTING);
+
+ EndFrame();
+}
+
+
+
+bool RAS_OpenGLRasterizer::BeginFrame(int drawingmode, double time)
+{
+ m_time = time;
+ m_drawingmode = drawingmode;
+
+ m_2DCanvas->ClearColor(m_redback,m_greenback,m_blueback,m_alphaback);
+ m_2DCanvas->ClearBuffer(RAS_ICanvas::COLOR_BUFFER);
+
+ // Blender camera routine destroys the settings
+ if (m_drawingmode < KX_SOLID)
+ {
+ glDisable (GL_CULL_FACE);
+ glDisable (GL_DEPTH_TEST);
+ }
+ else
+ {
+ glEnable(GL_DEPTH_TEST);
+ glEnable (GL_CULL_FACE);
+ }
+
+ glShadeModel(GL_SMOOTH);
+
+ m_2DCanvas->BeginFrame();
+
+ return true;
+}
+
+
+
+void RAS_OpenGLRasterizer::SetDrawingMode(int drawingmode)
+{
+ m_drawingmode = drawingmode;
+
+ switch (m_drawingmode)
+ {
+ case KX_BOUNDINGBOX:
+ {
+ }
+ case KX_WIREFRAME:
+ {
+ glDisable (GL_CULL_FACE);
+ break;
+ }
+ case KX_TEXTURED:
+ {
+ }
+ case KX_SHADED:
+ {
+ }
+ case KX_SOLID:
+ {
+ }
+ default:
+ {
+ }
+ }
+}
+
+
+
+int RAS_OpenGLRasterizer::GetDrawingMode()
+{
+ return m_drawingmode;
+}
+
+
+
+void RAS_OpenGLRasterizer::SetDepthMask(int depthmask)
+{
+ switch (depthmask)
+ {
+ case KX_DEPTHMASK_ENABLED:
+ {
+ glDepthMask(GL_TRUE);
+ break;
+ };
+ case KX_DEPTHMASK_DISABLED:
+ {
+ glDepthMask(GL_FALSE);
+ break;
+ };
+ default:
+ {
+ //printf("someone made a mistake, RAS_OpenGLRasterizer::SetDepthMask(int depthmask)\n");
+ exit(0);
+ }
+ }
+}
+
+
+
+void RAS_OpenGLRasterizer::ClearDepthBuffer()
+{
+ m_2DCanvas->ClearBuffer(RAS_ICanvas::DEPTH_BUFFER);
+}
+
+
+void RAS_OpenGLRasterizer::ClearCachingInfo(void)
+{
+ m_materialCachingInfo = 0;
+}
+
+
+void RAS_OpenGLRasterizer::EndFrame()
+{
+ m_2DCanvas->EndFrame();
+}
+
+
+void RAS_OpenGLRasterizer::SetRenderArea()
+{
+ // only above/below stereo method needs viewport adjustment
+ if(m_stereomode == RAS_STEREO_ABOVEBELOW)
+ {
+ switch(m_curreye)
+ {
+ case RAS_STEREO_LEFTEYE:
+ // upper half of window
+ m_2DCanvas->GetDisplayArea().SetLeft(0);
+ m_2DCanvas->GetDisplayArea().SetBottom(m_2DCanvas->GetHeight() -
+ int(m_2DCanvas->GetHeight() - m_noOfScanlines) / 2);
+
+ m_2DCanvas->GetDisplayArea().SetRight(int(m_2DCanvas->GetWidth()));
+ m_2DCanvas->GetDisplayArea().SetTop(int(m_2DCanvas->GetHeight()));
+ break;
+ case RAS_STEREO_RIGHTEYE:
+ // lower half of window
+ m_2DCanvas->GetDisplayArea().SetLeft(0);
+ m_2DCanvas->GetDisplayArea().SetBottom(0);
+ m_2DCanvas->GetDisplayArea().SetRight(int(m_2DCanvas->GetWidth()));
+ m_2DCanvas->GetDisplayArea().SetTop(int(m_2DCanvas->GetHeight() - m_noOfScanlines) / 2);
+ break;
+ }
+ }
+ else
+ {
+ // every available pixel
+ m_2DCanvas->GetDisplayArea().SetLeft(0);
+ m_2DCanvas->GetDisplayArea().SetBottom(0);
+ m_2DCanvas->GetDisplayArea().SetRight(int(m_2DCanvas->GetWidth()));
+ m_2DCanvas->GetDisplayArea().SetTop(int(m_2DCanvas->GetHeight()));
+ }
+}
+
+
+void RAS_OpenGLRasterizer::SetStereoMode(const int stereomode)
+{
+ m_stereomode = stereomode;
+}
+
+
+
+bool RAS_OpenGLRasterizer::Stereo()
+{
+ if(m_stereomode == RAS_STEREO_NOSTEREO)
+ return false;
+ else
+ return true;
+}
+
+
+void RAS_OpenGLRasterizer::SetEye(int eye)
+{
+ m_curreye = eye;
+ if(m_stereomode == RAS_STEREO_QUADBUFFERED) {
+ if(m_curreye == RAS_STEREO_LEFTEYE)
+ glDrawBuffer(GL_BACK_LEFT);
+ else
+ glDrawBuffer(GL_BACK_RIGHT);
+ }
+}
+
+
+void RAS_OpenGLRasterizer::SetEyeSeparation(float eyeseparation)
+{
+ m_eyeseparation = eyeseparation;
+}
+
+
+void RAS_OpenGLRasterizer::SetFocalLength(float focallength)
+{
+ m_focallength = focallength;
+}
+
+
+void RAS_OpenGLRasterizer::SwapBuffers()
+{
+ m_2DCanvas->SwapBuffers();
+}
+
+
+
+void RAS_OpenGLRasterizer::IndexPrimitives(const vecVertexArray & vertexarrays,
+ const vecIndexArrays & indexarrays,
+ int mode,
+ class RAS_IPolyMaterial* polymat,
+ class RAS_IRenderTools* rendertools,
+ bool useObjectColor,
+ const MT_Vector4& rgbacolor
+ )
+{
+ static const GLsizei vtxstride = sizeof(RAS_TexVert);
+ GLenum drawmode;
+ switch (mode)
+ {
+ case 0:
+ drawmode = GL_TRIANGLES;
+ break;
+ case 1:
+ drawmode = GL_LINES;
+ break;
+ case 2:
+ drawmode = GL_QUADS;
+ break;
+ default:
+ drawmode = GL_LINES;
+ break;
+ }
+
+ const RAS_TexVert* vertexarray ;
+ int numindices,vt;
+
+ for (vt=0;vt<vertexarrays.size();vt++)
+ {
+ vertexarray = &((*vertexarrays[vt]) [0]);
+ const KX_IndexArray & indexarray = (*indexarrays[vt]);
+ numindices = indexarray.size();
+
+ int numverts = vertexarrays[vt]->size();
+
+ if (!numindices)
+ break;
+
+ int vindex=0;
+ switch (mode)
+ {
+ case 1:
+ {
+ glBegin(GL_LINES);
+ vindex=0;
+ for (int i=0;i<numindices;i+=2)
+ {
+ glVertex3fv(vertexarray[(indexarray[vindex++])].getLocalXYZ());
+ glVertex3fv(vertexarray[(indexarray[vindex++])].getLocalXYZ());
+ }
+ glEnd();
+ }
+ break;
+ case 2:
+ {
+ glBegin(GL_QUADS);
+ vindex=0;
+ if (useObjectColor)
+ {
+ for (int i=0;i<numindices;i+=4)
+ {
+
+ glColor4d(rgbacolor[0], rgbacolor[1], rgbacolor[2], rgbacolor[3]);
+
+ glNormal3sv(vertexarray[(indexarray[vindex])].getNormal());
+ glTexCoord2fv(vertexarray[(indexarray[vindex])].getUV1());
+ glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ());
+ vindex++;
+
+ glNormal3sv(vertexarray[(indexarray[vindex])].getNormal());
+ glTexCoord2fv(vertexarray[(indexarray[vindex])].getUV1());
+ glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ());
+ vindex++;
+
+ glNormal3sv(vertexarray[(indexarray[vindex])].getNormal());
+ glTexCoord2fv(vertexarray[(indexarray[vindex])].getUV1());
+ glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ());
+ vindex++;
+
+ glNormal3sv(vertexarray[(indexarray[vindex])].getNormal());
+ glTexCoord2fv(vertexarray[(indexarray[vindex])].getUV1());
+ glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ());
+ vindex++;
+ }
+ }
+ else
+ {
+ for (int i=0;i<numindices;i+=4)
+ {
+ char *cp= (char *)&(vertexarray[(indexarray[vindex])].getRGBA());
+ // This looks curiously endian unsafe to me.
+ // However it depends on the way the colors are packed into
+ // the m_rgba field of RAS_TexVert
+
+ glColor4ub(cp[0], cp[1], cp[2], cp[3]);
+ glNormal3sv(vertexarray[(indexarray[vindex])].getNormal());
+ glTexCoord2fv(vertexarray[(indexarray[vindex])].getUV1());
+ glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ());
+ vindex++;
+
+ cp= (char *)&(vertexarray[(indexarray[vindex])].getRGBA());
+ glColor4ub(cp[0], cp[1], cp[2], cp[3]);
+ glNormal3sv(vertexarray[(indexarray[vindex])].getNormal());
+ glTexCoord2fv(vertexarray[(indexarray[vindex])].getUV1());
+ glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ());
+ vindex++;
+
+ cp= (char *)&(vertexarray[(indexarray[vindex])].getRGBA());
+ glColor4ub(cp[0], cp[1], cp[2], cp[3]);
+ glNormal3sv(vertexarray[(indexarray[vindex])].getNormal());
+ glTexCoord2fv(vertexarray[(indexarray[vindex])].getUV1());
+ glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ());
+ vindex++;
+
+ cp= (char *)&(vertexarray[(indexarray[vindex])].getRGBA());
+ glColor4ub(cp[0], cp[1], cp[2], cp[3]);
+ glNormal3sv(vertexarray[(indexarray[vindex])].getNormal());
+ glTexCoord2fv(vertexarray[(indexarray[vindex])].getUV1());
+ glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ());
+ vindex++;
+ }
+ }
+ glEnd();
+ break;
+ }
+ case 0:
+ {
+ glBegin(GL_TRIANGLES);
+ vindex=0;
+ if (useObjectColor)
+ {
+ for (int i=0;i<numindices;i+=3)
+ {
+
+ glColor4d(rgbacolor[0], rgbacolor[1], rgbacolor[2], rgbacolor[3]);
+
+ glNormal3sv(vertexarray[(indexarray[vindex])].getNormal());
+ glTexCoord2fv(vertexarray[(indexarray[vindex])].getUV1());
+ glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ());
+ vindex++;
+
+ glNormal3sv(vertexarray[(indexarray[vindex])].getNormal());
+ glTexCoord2fv(vertexarray[(indexarray[vindex])].getUV1());
+ glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ());
+ vindex++;
+
+ glNormal3sv(vertexarray[(indexarray[vindex])].getNormal());
+ glTexCoord2fv(vertexarray[(indexarray[vindex])].getUV1());
+ glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ());
+ vindex++;
+ }
+ }
+ else
+ {
+ for (int i=0;i<numindices;i+=3)
+ {
+
+ char *cp= (char *)&(vertexarray[(indexarray[vindex])].getRGBA());
+ glColor4ub(cp[0], cp[1], cp[2], cp[3]);
+ glNormal3sv(vertexarray[(indexarray[vindex])].getNormal());
+ glTexCoord2fv(vertexarray[(indexarray[vindex])].getUV1());
+ glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ());
+ vindex++;
+
+ cp= (char *)&(vertexarray[(indexarray[vindex])].getRGBA());
+ glColor4ub(cp[0], cp[1], cp[2], cp[3]);
+ glNormal3sv(vertexarray[(indexarray[vindex])].getNormal());
+ glTexCoord2fv(vertexarray[(indexarray[vindex])].getUV1());
+ glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ());
+ vindex++;
+
+ cp= (char *)&(vertexarray[(indexarray[vindex])].getRGBA());
+ glColor4ub(cp[0], cp[1], cp[2], cp[3]);
+ glNormal3sv(vertexarray[(indexarray[vindex])].getNormal());
+ glTexCoord2fv(vertexarray[(indexarray[vindex])].getUV1());
+ glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ());
+ vindex++;
+ }
+ }
+ glEnd();
+ break;
+ }
+ default:
+ {
+ }
+
+ } // switch
+ } // for each vertexarray
+
+}
+
+void RAS_OpenGLRasterizer::IndexPrimitives_Ex(const vecVertexArray & vertexarrays,
+ const vecIndexArrays & indexarrays,
+ int mode,
+ class RAS_IPolyMaterial* polymat,
+ class RAS_IRenderTools* rendertools,
+ bool useObjectColor,
+ const MT_Vector4& rgbacolor
+ )
+{
+ bool recalc;
+ static const GLsizei vtxstride = sizeof(RAS_TexVert);
+ GLenum drawmode;
+ switch (mode)
+ {
+ case 0:
+ drawmode = GL_TRIANGLES;
+ break;
+ case 1:
+ drawmode = GL_LINES;
+ break;
+ case 2:
+ drawmode = GL_QUADS;
+ break;
+ default:
+ drawmode = GL_LINES;
+ break;
+ }
+
+ const RAS_TexVert* vertexarray ;
+ int numindices,vt;
+
+ for (vt=0;vt<vertexarrays.size();vt++)
+ {
+ vertexarray = &((*vertexarrays[vt]) [0]);
+ const KX_IndexArray & indexarray = (*indexarrays[vt]);
+ numindices = indexarray.size();
+
+ int numverts = vertexarrays[vt]->size();
+
+ if (!numindices)
+ break;
+
+ int vindex=0;
+ switch (mode)
+ {
+ case 1:
+ {
+ glBegin(GL_LINES);
+ vindex=0;
+ for (int i=0;i<numindices;i+=2)
+ {
+ glVertex3fv(vertexarray[(indexarray[vindex++])].getLocalXYZ());
+ glVertex3fv(vertexarray[(indexarray[vindex++])].getLocalXYZ());
+ }
+ glEnd();
+ }
+ break;
+ case 2:
+ {
+ glBegin(GL_QUADS);
+ vindex=0;
+ if (useObjectColor)
+ {
+ for (int i=0;i<numindices;i+=4)
+ {
+ MT_Point3 mv1, mv2, mv3, mv4, fnor;
+ /* Calc a new face normal */
+
+ if (vertexarray[(indexarray[vindex])].getFlag() & TV_CALCFACENORMAL)
+ recalc= true;
+ else
+ recalc=false;
+
+ if (recalc){
+ mv1 = MT_Point3(vertexarray[(indexarray[vindex])].getLocalXYZ());
+ mv2 = MT_Point3(vertexarray[(indexarray[vindex+1])].getLocalXYZ());
+ mv3 = MT_Point3(vertexarray[(indexarray[vindex+2])].getLocalXYZ());
+ mv4 = MT_Point3(vertexarray[(indexarray[vindex+2])].getLocalXYZ());
+
+ fnor = (((mv2-mv1).cross(mv3-mv2))+((mv4-mv3).cross(mv1-mv4))).safe_normalized();
+
+ glNormal3f(fnor[0], fnor[1], fnor[2]);
+ }
+
+ glColor4d(rgbacolor[0], rgbacolor[1], rgbacolor[2], rgbacolor[3]);
+
+ if (!recalc)
+ glNormal3sv(vertexarray[(indexarray[vindex])].getNormal());
+ glTexCoord2fv(vertexarray[(indexarray[vindex])].getUV1());
+ glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ());
+ vindex++;
+
+ if (!recalc)
+ glNormal3sv(vertexarray[(indexarray[vindex])].getNormal());
+ glTexCoord2fv(vertexarray[(indexarray[vindex])].getUV1());
+ glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ());
+ vindex++;
+
+ if (!recalc)
+ glNormal3sv(vertexarray[(indexarray[vindex])].getNormal());
+ glTexCoord2fv(vertexarray[(indexarray[vindex])].getUV1());
+ glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ());
+ vindex++;
+
+ if (!recalc)
+ glNormal3sv(vertexarray[(indexarray[vindex])].getNormal());
+ glTexCoord2fv(vertexarray[(indexarray[vindex])].getUV1());
+ glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ());
+ vindex++;
+ }
+ }
+ else
+ {
+ for (int i=0;i<numindices;i+=4)
+ {
+ char *cp= (char *)&(vertexarray[(indexarray[vindex])].getRGBA());
+ // This looks curiously endian unsafe to me.
+ // However it depends on the way the colors are packed into
+ // the m_rgba field of RAS_TexVert
+ MT_Point3 mv1, mv2, mv3, mv4, fnor;
+ /* Calc a new face normal */
+
+ if (vertexarray[(indexarray[vindex])].getFlag() & TV_CALCFACENORMAL)
+ recalc= true;
+ else
+ recalc=false;
+
+
+ if (recalc){
+ mv1 = MT_Point3(vertexarray[(indexarray[vindex])].getLocalXYZ());
+ mv2 = MT_Point3(vertexarray[(indexarray[vindex+1])].getLocalXYZ());
+ mv3 = MT_Point3(vertexarray[(indexarray[vindex+2])].getLocalXYZ());
+ mv4 = MT_Point3(vertexarray[(indexarray[vindex+2])].getLocalXYZ());
+
+ fnor = (((mv2-mv1).cross(mv3-mv2))+((mv4-mv3).cross(mv1-mv4))).safe_normalized();
+
+ glNormal3f(fnor[0], fnor[1], fnor[2]);
+ }
+
+ glColor4ub(cp[0], cp[1], cp[2], cp[3]);
+ if (!recalc)
+ glNormal3sv(vertexarray[(indexarray[vindex])].getNormal());
+ glTexCoord2fv(vertexarray[(indexarray[vindex])].getUV1());
+ glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ());
+ vindex++;
+
+ cp= (char *)&(vertexarray[(indexarray[vindex])].getRGBA());
+ glColor4ub(cp[0], cp[1], cp[2], cp[3]);
+ if (!recalc)
+ glNormal3sv(vertexarray[(indexarray[vindex])].getNormal());
+ glTexCoord2fv(vertexarray[(indexarray[vindex])].getUV1());
+ glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ());
+ vindex++;
+
+ cp= (char *)&(vertexarray[(indexarray[vindex])].getRGBA());
+ glColor4ub(cp[0], cp[1], cp[2], cp[3]);
+ if (!recalc)
+ glNormal3sv(vertexarray[(indexarray[vindex])].getNormal());
+ glTexCoord2fv(vertexarray[(indexarray[vindex])].getUV1());
+ glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ());
+ vindex++;
+
+ cp= (char *)&(vertexarray[(indexarray[vindex])].getRGBA());
+ glColor4ub(cp[0], cp[1], cp[2], cp[3]);
+ if (!recalc)
+ glNormal3sv(vertexarray[(indexarray[vindex])].getNormal());
+ glTexCoord2fv(vertexarray[(indexarray[vindex])].getUV1());
+ glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ());
+ vindex++;
+ }
+ }
+ glEnd();
+ break;
+ }
+ case 0:
+ {
+ glBegin(GL_TRIANGLES);
+ vindex=0;
+ if (useObjectColor)
+ {
+ for (int i=0;i<numindices;i+=3)
+ {
+ MT_Point3 mv1, mv2, mv3, fnor;
+ /* Calc a new face normal */
+
+ if (vertexarray[(indexarray[vindex])].getFlag() & TV_CALCFACENORMAL)
+ recalc= true;
+ else
+ recalc=false;
+
+ if (recalc){
+ mv1 = MT_Point3(vertexarray[(indexarray[vindex])].getLocalXYZ());
+ mv2 = MT_Point3(vertexarray[(indexarray[vindex+1])].getLocalXYZ());
+ mv3 = MT_Point3(vertexarray[(indexarray[vindex+2])].getLocalXYZ());
+
+ fnor = ((mv2-mv1).cross(mv3-mv2)).safe_normalized();
+ glNormal3f(fnor[0], fnor[1], fnor[2]);
+ }
+
+ glColor4d(rgbacolor[0], rgbacolor[1], rgbacolor[2], rgbacolor[3]);
+
+ if (!recalc)
+ glNormal3sv(vertexarray[(indexarray[vindex])].getNormal());
+ glTexCoord2fv(vertexarray[(indexarray[vindex])].getUV1());
+ glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ());
+ vindex++;
+
+ if (!recalc)
+ glNormal3sv(vertexarray[(indexarray[vindex])].getNormal());
+ glTexCoord2fv(vertexarray[(indexarray[vindex])].getUV1());
+ glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ());
+ vindex++;
+
+ if (!recalc)
+ glNormal3sv(vertexarray[(indexarray[vindex])].getNormal());
+ glTexCoord2fv(vertexarray[(indexarray[vindex])].getUV1());
+ glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ());
+ vindex++;
+ }
+ }
+ else
+ {
+ for (int i=0;i<numindices;i+=3)
+ {
+ MT_Point3 mv1, mv2, mv3, fnor;
+ /* Calc a new face normal */
+
+ if (vertexarray[(indexarray[vindex])].getFlag() & TV_CALCFACENORMAL)
+ recalc= true;
+ else
+ recalc=false;
+
+
+ if (recalc){
+ mv1 = MT_Point3(vertexarray[(indexarray[vindex])].getLocalXYZ());
+ mv2 = MT_Point3(vertexarray[(indexarray[vindex+1])].getLocalXYZ());
+ mv3 = MT_Point3(vertexarray[(indexarray[vindex+2])].getLocalXYZ());
+
+ fnor = ((mv2-mv1).cross(mv3-mv2)).safe_normalized();
+ glNormal3f(fnor[0], fnor[1], fnor[2]);
+ }
+
+ char *cp= (char *)&(vertexarray[(indexarray[vindex])].getRGBA());
+ glColor4ub(cp[0], cp[1], cp[2], cp[3]);
+ if (!recalc)
+ glNormal3sv(vertexarray[(indexarray[vindex])].getNormal());
+ glTexCoord2fv(vertexarray[(indexarray[vindex])].getUV1());
+ glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ());
+ vindex++;
+
+ cp= (char *)&(vertexarray[(indexarray[vindex])].getRGBA());
+ glColor4ub(cp[0], cp[1], cp[2], cp[3]);
+ if (!recalc)
+ glNormal3sv(vertexarray[(indexarray[vindex])].getNormal());
+ glTexCoord2fv(vertexarray[(indexarray[vindex])].getUV1());
+ glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ());
+ vindex++;
+
+ cp= (char *)&(vertexarray[(indexarray[vindex])].getRGBA());
+ glColor4ub(cp[0], cp[1], cp[2], cp[3]);
+ if (!recalc)
+ glNormal3sv(vertexarray[(indexarray[vindex])].getNormal());
+ glTexCoord2fv(vertexarray[(indexarray[vindex])].getUV1());
+ glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ());
+ vindex++;
+ }
+ }
+ glEnd();
+ break;
+ }
+ default:
+ {
+ }
+
+ } // switch
+ } // for each vertexarray
+
+}
+
+
+
+void RAS_OpenGLRasterizer::IndexPrimitives_3DText(const vecVertexArray & vertexarrays,
+ const vecIndexArrays & indexarrays,
+ int mode,
+ class RAS_IPolyMaterial* polymat,
+ class RAS_IRenderTools* rendertools,
+ bool useObjectColor,
+ const MT_Vector4& rgbacolor
+ )
+{
+ unsigned char* mypointer=NULL;
+ static const GLsizei vtxstride = sizeof(RAS_TexVert);
+ GLenum drawmode;
+ switch (mode)
+ {
+ case 0:
+ drawmode = GL_TRIANGLES;
+ break;
+ case 1:
+ drawmode = GL_LINES;
+ break;
+ case 2:
+ drawmode = GL_QUADS;
+ break;
+ default:
+ drawmode = GL_LINES;
+ break;
+ }
+
+ const RAS_TexVert* vertexarray ;
+
+ int numindices ;
+ int vt;
+
+ if (useObjectColor)
+ {
+ glDisableClientState(GL_COLOR_ARRAY);
+ glColor4d(rgbacolor[0], rgbacolor[1], rgbacolor[2], rgbacolor[3]);
+ }
+ else
+ {
+ glEnableClientState(GL_COLOR_ARRAY);
+ }
+
+ for (vt=0;vt<vertexarrays.size();vt++)
+ {
+ vertexarray = &((*vertexarrays[vt]) [0]);
+ const KX_IndexArray & indexarray = (*indexarrays[vt]);
+ numindices = indexarray.size();
+
+ int numverts = vertexarrays[vt]->size();
+
+ if (!numindices)
+ break;
+
+ int vindex=0;
+ switch (mode)
+ {
+ case 1:
+ {
+ glBegin(GL_LINES);
+ vindex=0;
+ for (int i=0;i<numindices;i+=2)
+ {
+ glVertex3fv(vertexarray[(indexarray[vindex++])].getLocalXYZ());
+ glVertex3fv(vertexarray[(indexarray[vindex++])].getLocalXYZ());
+ }
+ glEnd();
+ }
+ break;
+ case 2:
+ {
+ vindex=0;
+ for (int i=0;i<numindices;i+=4)
+ {
+ float v1[3],v2[3],v3[3],v4[3];
+
+ char *cp= (char *)&(vertexarray[(indexarray[vindex])].getRGBA());
+ v1[0] = vertexarray[(indexarray[vindex])].getLocalXYZ()[0];
+ v1[1] = vertexarray[(indexarray[vindex])].getLocalXYZ()[1];
+ v1[2] = vertexarray[(indexarray[vindex])].getLocalXYZ()[2];
+ vindex++;
+
+ cp= (char *)&(vertexarray[(indexarray[vindex])].getRGBA());
+ v2[0] = vertexarray[(indexarray[vindex])].getLocalXYZ()[0];
+ v2[1] = vertexarray[(indexarray[vindex])].getLocalXYZ()[1];
+ v2[2] = vertexarray[(indexarray[vindex])].getLocalXYZ()[2];
+ vindex++;
+
+ cp= (char *)&(vertexarray[(indexarray[vindex])].getRGBA());
+ v3[0] = vertexarray[(indexarray[vindex])].getLocalXYZ()[0];
+ v3[1] = vertexarray[(indexarray[vindex])].getLocalXYZ()[1];
+ v3[2] = vertexarray[(indexarray[vindex])].getLocalXYZ()[2];
+ vindex++;
+
+ cp= (char *)&(vertexarray[(indexarray[vindex])].getRGBA());
+ v4[0] = vertexarray[(indexarray[vindex])].getLocalXYZ()[0];
+ v4[1] = vertexarray[(indexarray[vindex])].getLocalXYZ()[1];
+ v4[2] = vertexarray[(indexarray[vindex])].getLocalXYZ()[2];
+
+ vindex++;
+
+ rendertools->RenderText(polymat->GetDrawingMode(),polymat,v1,v2,v3,v4);
+ ClearCachingInfo();
+ }
+ break;
+ }
+ case 0:
+ {
+ glBegin(GL_TRIANGLES);
+ vindex=0;
+ for (int i=0;i<numindices;i+=3)
+ {
+ float v1[3],v2[3],v3[3];
+
+ v1[0] = vertexarray[(indexarray[vindex])].getLocalXYZ()[0];
+ v1[1] = vertexarray[(indexarray[vindex])].getLocalXYZ()[1];
+ v1[2] = vertexarray[(indexarray[vindex])].getLocalXYZ()[2];
+ vindex++;
+
+ v2[0] = vertexarray[(indexarray[vindex])].getLocalXYZ()[0];
+ v2[1] = vertexarray[(indexarray[vindex])].getLocalXYZ()[1];
+ v2[2] = vertexarray[(indexarray[vindex])].getLocalXYZ()[2];
+ vindex++;
+
+ v3[0] = vertexarray[(indexarray[vindex])].getLocalXYZ()[0];
+ v3[1] = vertexarray[(indexarray[vindex])].getLocalXYZ()[1];
+ v3[2] = vertexarray[(indexarray[vindex])].getLocalXYZ()[2];
+ vindex++;
+
+ rendertools->RenderText(polymat->GetDrawingMode(),polymat,v1,v2,v3,NULL);
+ ClearCachingInfo();
+ }
+ glEnd();
+ break;
+ }
+ default:
+ {
+ }
+ } //switch
+ } //for each vertexarray
+}
+
+
+
+void RAS_OpenGLRasterizer::SetProjectionMatrix(MT_CmMatrix4x4 &mat)
+{
+ glMatrixMode(GL_PROJECTION);
+ double* matrix = &mat(0,0);
+ glLoadMatrixd(matrix);
+}
+
+
+void RAS_OpenGLRasterizer::SetProjectionMatrix(MT_Matrix4x4 & mat)
+{
+ glMatrixMode(GL_PROJECTION);
+ double matrix[16];
+ /* Get into argument. Looks a bit dodgy, but it's ok. */
+ mat.getValue(matrix);
+ /* Internally, MT_Matrix4x4 uses doubles (MT_Scalar). */
+ glLoadMatrixd(matrix);
+}
+
+MT_Matrix4x4 RAS_OpenGLRasterizer::GetFrustumMatrix(
+ float left,
+ float right,
+ float bottom,
+ float top,
+ float frustnear,
+ float frustfar
+){
+ MT_Matrix4x4 result;
+ double mat[16];
+
+ // correction for stereo
+ if(m_stereomode != RAS_STEREO_NOSTEREO)
+ {
+ float near_div_focallength;
+ // next 2 params should be specified on command line and in Blender publisher
+ m_focallength = 1.5 * right; // derived from example
+ m_eyeseparation = 0.18 * right; // just a guess...
+
+ near_div_focallength = frustnear / m_focallength;
+ switch(m_curreye)
+ {
+ case RAS_STEREO_LEFTEYE:
+ left += 0.5 * m_eyeseparation * near_div_focallength;
+ right += 0.5 * m_eyeseparation * near_div_focallength;
+ break;
+ case RAS_STEREO_RIGHTEYE:
+ left -= 0.5 * m_eyeseparation * near_div_focallength;
+ right -= 0.5 * m_eyeseparation * near_div_focallength;
+ break;
+ }
+ // leave bottom, top, bottom and top untouched
+ }
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glFrustum(left, right, bottom, top, frustnear, frustfar);
+ glGetDoublev(GL_PROJECTION_MATRIX, mat);
+ result.setValue(mat);
+
+ return result;
+}
+
+
+// next arguments probably contain redundant info, for later...
+void RAS_OpenGLRasterizer::SetViewMatrix(const MT_Matrix4x4 &mat, const MT_Vector3& campos,
+ const MT_Point3 &camLoc, const MT_Quaternion &camOrientQuat)
+{
+ MT_Matrix4x4 viewMat = mat;
+
+ // correction for stereo
+ if(m_stereomode != RAS_STEREO_NOSTEREO)
+ {
+ MT_Matrix3x3 camOrientMat3x3(camOrientQuat);
+ MT_Vector3 unitViewDir(0.0, -1.0, 0.0); // minus y direction, Blender convention
+ MT_Vector3 unitViewupVec(0.0, 0.0, 1.0);
+ MT_Vector3 viewDir, viewupVec;
+ MT_Vector3 eyeline;
+
+ // actual viewDir
+ viewDir = camOrientMat3x3 * unitViewDir; // this is the moto convention, vector on right hand side
+ // actual viewup vec
+ viewupVec = camOrientMat3x3 * unitViewupVec;
+
+ // vector between eyes
+ eyeline = viewDir.cross(viewupVec);
+
+ switch(m_curreye)
+ {
+ case RAS_STEREO_LEFTEYE:
+ {
+ // translate to left by half the eye distance
+ MT_Transform transform;
+ transform.setIdentity();
+ transform.translate(-(eyeline * m_eyeseparation / 2.0));
+ viewMat *= transform;
+ }
+ break;
+ case RAS_STEREO_RIGHTEYE:
+ {
+ // translate to right by half the eye distance
+ MT_Transform transform;
+ transform.setIdentity();
+ transform.translate(eyeline * m_eyeseparation / 2.0);
+ viewMat *= transform;
+ }
+ break;
+ }
+ }
+
+ // convert row major matrix 'viewMat' to column major for OpenGL
+ MT_Scalar cammat[16];
+ viewMat.getValue(cammat);
+ MT_CmMatrix4x4 viewCmmat = cammat;
+
+ glMatrixMode(GL_MODELVIEW);
+ m_viewmatrix = viewCmmat;
+ glLoadMatrixd(&m_viewmatrix(0,0));
+ m_campos = campos;
+}
+
+
+const MT_Point3& RAS_OpenGLRasterizer::GetCameraPosition()
+{
+ return m_campos;
+}
+
+
+
+void RAS_OpenGLRasterizer::LoadViewMatrix()
+{
+ glLoadMatrixd(&m_viewmatrix(0,0));
+}
+
+
+
+void RAS_OpenGLRasterizer::EnableTextures(bool enable)
+{
+}
+
+
+
+void RAS_OpenGLRasterizer::SetCullFace(bool enable)
+{
+ if (enable)
+ glEnable(GL_CULL_FACE);
+ else
+ glDisable(GL_CULL_FACE);
+}
+
+
+
+void RAS_OpenGLRasterizer::SetSpecularity(float specX,
+ float specY,
+ float specZ,
+ float specval)
+{
+ GLfloat mat_specular[] = {specX, specY, specZ, specval};
+ glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
+}
+
+
+
+void RAS_OpenGLRasterizer::SetShinyness(float shiny)
+{
+ GLfloat mat_shininess[] = { shiny };
+ glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
+}
+
+
+
+void RAS_OpenGLRasterizer::SetDiffuse(float difX,float difY,float difZ,float diffuse)
+{
+ GLfloat mat_diffuse [] = {difX, difY,difZ, diffuse};
+ glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse);
+}
+
+double RAS_OpenGLRasterizer::GetTime()
+{
+ return m_time;
+}
+
+
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h
new file mode 100644
index 00000000000..9bbb19e8aa5
--- /dev/null
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.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 *****
+ */
+#ifndef __RAS_OPENGLRASTERIZER
+#define __RAS_OPENGLRASTERIZER
+
+#ifdef WIN32
+#pragma warning (disable:4786)
+#endif
+
+#include "MT_CmMatrix4x4.h"
+#include <vector>
+using namespace std;
+
+
+#include "RAS_IRasterizer.h"
+#include "RAS_MaterialBucket.h"
+#include "RAS_ICanvas.h"
+
+/**
+ * 3D rendering device context.
+ */
+class RAS_OpenGLRasterizer : public RAS_IRasterizer
+{
+
+ RAS_ICanvas* m_2DCanvas;
+
+ // fogging vars
+ bool m_fogenabled;
+ float m_fogstart;
+ float m_fogdist;
+ float m_fogr;
+ float m_fogg;
+ float m_fogb;
+
+ float m_redback;
+ float m_greenback;
+ float m_blueback;
+ float m_alphaback;
+
+ bool m_bEXT_compiled_vertex_array;
+
+ double m_time;
+ MT_CmMatrix4x4 m_viewmatrix;
+ MT_Point3 m_campos;
+
+ int m_stereomode;
+ int m_curreye;
+ float m_eyeseparation;
+ float m_focallength;
+ int m_noOfScanlines;
+
+protected:
+ int m_drawingmode;
+ /** Stores the caching information for the last material activated. */
+ RAS_IPolyMaterial::TCachingInfo m_materialCachingInfo;
+
+public:
+ double GetTime();
+ RAS_OpenGLRasterizer(RAS_ICanvas* canv);
+ virtual ~RAS_OpenGLRasterizer();
+
+
+
+ enum
+ {
+ KX_BOUNDINGBOX = 1,
+ KX_WIREFRAME,
+ KX_SOLID,
+ KX_SHADED,
+ KX_TEXTURED
+ };
+
+ enum
+ {
+ KX_DEPTHMASK_ENABLED =1,
+ KX_DEPTHMASK_DISABLED,
+ };
+ virtual void SetDepthMask(int depthmask);
+
+ virtual void SetMaterial(const RAS_IPolyMaterial& mat);
+ virtual bool Init();
+ virtual void Exit();
+ virtual bool BeginFrame(int drawingmode, double time);
+ virtual void ClearDepthBuffer();
+ virtual void ClearCachingInfo(void);
+ virtual void EndFrame();
+ virtual void SetRenderArea();
+
+ virtual void SetStereoMode(const int stereomode);
+ virtual bool Stereo();
+ virtual void SetEye(const int eye);
+ virtual void SetEyeSeparation(const float eyeseparation);
+ virtual void SetFocalLength(const float focallength);
+
+ virtual void SwapBuffers();
+ virtual void IndexPrimitives(
+ const vecVertexArray& vertexarrays,
+ const vecIndexArrays & indexarrays,
+ int mode,
+ class RAS_IPolyMaterial* polymat,
+ class RAS_IRenderTools* rendertools,
+ bool useObjectColor,
+ const MT_Vector4& rgbacolor
+ );
+
+ virtual void IndexPrimitives_Ex(
+ const vecVertexArray& vertexarrays,
+ const vecIndexArrays & indexarrays,
+ int mode,
+ class RAS_IPolyMaterial* polymat,
+ class RAS_IRenderTools* rendertools,
+ bool useObjectColor,
+ const MT_Vector4& rgbacolor
+ );
+
+ virtual void IndexPrimitives_3DText(
+ const vecVertexArray& vertexarrays,
+ const vecIndexArrays & indexarrays,
+ int mode,
+ class RAS_IPolyMaterial* polymat,
+ class RAS_IRenderTools* rendertools,
+ bool useObjectColor,
+ const MT_Vector4& rgbacolor
+ );
+
+ virtual void SetProjectionMatrix(MT_CmMatrix4x4 & mat);
+ virtual void SetProjectionMatrix(MT_Matrix4x4 & mat);
+ virtual void SetViewMatrix(
+ const MT_Matrix4x4 & mat,
+ const MT_Vector3& campos,
+ const MT_Point3 &camLoc,
+ const MT_Quaternion &camOrientQuat
+ );
+
+ virtual const MT_Point3& GetCameraPosition();
+ virtual void LoadViewMatrix();
+
+ virtual void SetFog(
+ float start,
+ float dist,
+ float r,
+ float g,
+ float b
+ );
+
+ virtual void SetFogColor(
+ float r,
+ float g,
+ float b
+ );
+
+ virtual void SetFogStart(float fogstart);
+ virtual void SetFogEnd(float fogend);
+
+ void DisableFog();
+ virtual void DisplayFog();
+
+ virtual void SetBackColor(
+ float red,
+ float green,
+ float blue,
+ float alpha
+ );
+
+ virtual void SetDrawingMode(int drawingmode);
+ virtual int GetDrawingMode();
+
+ virtual void EnableTextures(bool enable);
+ virtual void SetCullFace(bool enable);
+
+ virtual MT_Matrix4x4 GetFrustumMatrix(
+ float left,
+ float right,
+ float bottom,
+ float top,
+ float frustnear,
+ float frustfar
+ );
+
+ virtual void SetSpecularity(
+ float specX,
+ float specY,
+ float specZ,
+ float specval
+ );
+
+ virtual void SetShinyness(float shiny);
+ virtual void SetDiffuse(
+ float difX,
+ float difY,
+ float difZ,
+ float diffuse
+ );
+
+};
+
+#endif //__RAS_OPENGLRASTERIZER
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.cpp
new file mode 100644
index 00000000000..fe582a3d2ee
--- /dev/null
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.cpp
@@ -0,0 +1,215 @@
+#ifdef WIN32
+
+
+#include "RAS_VAOpenGLRasterizer.h"
+
+
+#include <windows.h>
+#include "GL/gl.h"
+
+typedef void (APIENTRY *GLLOCKARRAYSEXTPTR)(GLint first,GLsizei count);
+typedef void (APIENTRY *GLUNLOCKARRAYSEXTPTR)(void);
+void APIENTRY RAS_lockfunc(GLint first,GLsizei count) {};
+void APIENTRY RAS_unlockfunc() {};
+GLLOCKARRAYSEXTPTR glLockArraysEXT=RAS_lockfunc;
+GLUNLOCKARRAYSEXTPTR glUnlockArraysEXT=RAS_unlockfunc;
+
+
+
+
+#include "STR_String.h"
+#include "RAS_TexVert.h"
+#include "MT_CmMatrix4x4.h"
+#include "RAS_IRenderTools.h" // rendering text
+
+
+RAS_VAOpenGLRasterizer::RAS_VAOpenGLRasterizer(RAS_ICanvas* canvas)
+:RAS_OpenGLRasterizer(canvas)
+{
+ int i = 0;
+}
+
+
+
+RAS_VAOpenGLRasterizer::~RAS_VAOpenGLRasterizer()
+{
+}
+
+
+
+bool RAS_VAOpenGLRasterizer::Init()
+{
+
+ bool result = RAS_OpenGLRasterizer::Init();
+
+ if (result)
+ {
+ // if possible, add extensions to other platforms too, if this
+ // rasterizer becomes messy just derive one for each platform
+ // (ie. KX_Win32Rasterizer, KX_LinuxRasterizer etc.)
+
+ glUnlockArraysEXT = reinterpret_cast<GLUNLOCKARRAYSEXTPTR>(wglGetProcAddress("glUnlockArraysEXT"));
+ if (!glUnlockArraysEXT)
+ result = false;
+
+ glLockArraysEXT = reinterpret_cast<GLLOCKARRAYSEXTPTR>(wglGetProcAddress("glLockArraysEXT"));
+ if (!glLockArraysEXT)
+ result=false;
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisableClientState(GL_NORMAL_ARRAY);
+ glDisableClientState(GL_COLOR_ARRAY);
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ }
+
+ return result;
+}
+
+
+
+void RAS_VAOpenGLRasterizer::SetDrawingMode(int drawingmode)
+{
+ m_drawingmode = drawingmode;
+
+ switch (m_drawingmode)
+ {
+ case KX_BOUNDINGBOX:
+ {
+ }
+ case KX_WIREFRAME:
+ {
+ glDisable (GL_CULL_FACE);
+ break;
+ }
+ case KX_TEXTURED:
+ {
+ }
+ case KX_SHADED:
+ {
+ glEnableClientState(GL_COLOR_ARRAY);
+ }
+ case KX_SOLID:
+ {
+ break;
+ }
+ default:
+ {
+ }
+ }
+}
+
+
+
+void RAS_VAOpenGLRasterizer::Exit()
+{
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisableClientState(GL_COLOR_ARRAY);
+ glDisableClientState(GL_NORMAL_ARRAY);
+ glDisable(GL_COLOR_MATERIAL);
+
+ RAS_OpenGLRasterizer::Exit();
+}
+
+
+
+void RAS_VAOpenGLRasterizer::IndexPrimitives( const vecVertexArray& vertexarrays,
+ const vecIndexArrays & indexarrays,
+ int mode,
+ class RAS_IPolyMaterial* polymat,
+ class RAS_IRenderTools* rendertools,
+ bool useObjectColor,
+ const MT_Vector4& rgbacolor)
+{
+ unsigned char* mypointer=NULL;
+ static const GLsizei vtxstride = sizeof(RAS_TexVert);
+ GLenum drawmode;
+ switch (mode)
+ {
+ case 0:
+ {
+ drawmode = GL_TRIANGLES;
+ break;
+ }
+ case 2:
+ {
+ drawmode = GL_QUADS;
+ break;
+ }
+ case 1: //lines
+ {
+ }
+ default:
+ {
+ drawmode = GL_LINES;
+ break;
+ }
+ }
+ const RAS_TexVert* vertexarray;
+ int numindices,vt;
+ if (drawmode != GL_LINES)
+ {
+ if (useObjectColor)
+ {
+ glDisableClientState(GL_COLOR_ARRAY);
+ glColor4d(rgbacolor[0], rgbacolor[1], rgbacolor[2], rgbacolor[3]);
+ } else
+ {
+ glColor4d(0,0,0,1.0);
+ glEnableClientState(GL_COLOR_ARRAY);
+ }
+ }
+ else
+ {
+ glColor3d(0,0,0);
+ }
+ // use glDrawElements to draw each vertexarray
+ for (vt=0;vt<vertexarrays.size();vt++)
+ {
+ vertexarray = &((*vertexarrays[vt]) [0]);
+ const KX_IndexArray & indexarray = (*indexarrays[vt]);
+ numindices = indexarray.size();
+ int numverts = vertexarrays[vt]->size();
+
+ if (!numindices)
+ break;
+
+ mypointer = (unsigned char*)(vertexarray);
+ glVertexPointer(3,GL_FLOAT,vtxstride,mypointer);
+ mypointer+= 3*sizeof(float);
+ glTexCoordPointer(2,GL_FLOAT,vtxstride,mypointer);
+ mypointer+= 2*sizeof(float);
+ glColorPointer(4,GL_UNSIGNED_BYTE,vtxstride,mypointer);
+ mypointer += sizeof(int);
+ glNormalPointer(GL_SHORT,vtxstride,mypointer);
+ glLockArraysEXT(0,numverts);
+ // here the actual drawing takes places
+ glDrawElements(drawmode,numindices,GL_UNSIGNED_INT,&(indexarray[0]));
+ glUnlockArraysEXT();
+ }
+}
+
+
+void RAS_VAOpenGLRasterizer::EnableTextures(bool enable)
+{
+ if (enable)
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ else
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+}
+
+bool RAS_VAOpenGLRasterizer::Stereo()
+{
+/*
+ if(m_stereomode == RAS_STEREO_NOSTEREO)
+ return false;
+ else
+ return true;
+*/
+ return false;
+}
+
+
+#endif //WIN32
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.h
new file mode 100644
index 00000000000..f2500e02dde
--- /dev/null
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.h
@@ -0,0 +1,62 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 __KX_VERTEXARRAYOPENGLRASTERIZER
+#define __KX_VERTEXARRAYOPENGLRASTERIZER
+
+#include "RAS_OpenGLRasterizer.h"
+
+class RAS_VAOpenGLRasterizer : public RAS_OpenGLRasterizer
+{
+public:
+ RAS_VAOpenGLRasterizer(RAS_ICanvas* canvas);
+ virtual ~RAS_VAOpenGLRasterizer();
+
+ virtual bool Init();
+ virtual void Exit();
+
+ virtual bool Stereo();
+ virtual void SetDrawingMode(int drawingmode);
+
+ virtual void IndexPrimitives( const vecVertexArray& vertexarrays,
+ const vecIndexArrays & indexarrays,
+ int mode,
+ class RAS_IPolyMaterial* polymat,
+ class RAS_IRenderTools* rendertools,
+ bool useObjectColor,
+ const MT_Vector4& rgbacolor);
+
+
+ virtual void EnableTextures(bool enable);
+
+};
+
+#endif //__KX_VERTEXARRAYOPENGLRASTERIZER
diff --git a/source/gameengine/Rasterizer/RAS_Polygon.cpp b/source/gameengine/Rasterizer/RAS_Polygon.cpp
new file mode 100644
index 00000000000..c495ef9679d
--- /dev/null
+++ b/source/gameengine/Rasterizer/RAS_Polygon.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 *****
+ */
+
+#ifdef WIN32
+
+#pragma warning (disable:4786)
+#endif
+
+#include "RAS_Polygon.h"
+
+/*
+RAS_TexVert* RAS_Polygon::GetVertex(int index)
+{
+ if (m_bucket)
+ return m_bucket->GetVertex(m_vertexindexbase.m_vtxarray, m_vertexindexbase.m_indexarray[index]);
+ else
+ return NULL;
+}
+*/
+
+/*void RAS_Polygon::Bucketize(double* oglmatrix)
+{
+ //Transform(trans);
+ if (m_bucket)
+ m_bucket->AddPolygon(this,oglmatrix);
+}
+*/
+
+RAS_Polygon::RAS_Polygon(RAS_MaterialBucket* bucket,
+ bool visible,
+ int numverts,
+ int vtxarrayindex)
+ :m_bucket(bucket),
+ m_vertexindexbase(numverts),
+ m_numverts(numverts),
+ m_edgecode(0)
+{
+ int size = sizeof(RAS_Polygon);
+ m_vertexindexbase.m_vtxarray = vtxarrayindex ;//m_bucket->FindVertexArray(numverts);
+ m_polyFlags.Visible = visible;
+}
+
+
+
+int RAS_Polygon::VertexCount()
+{
+ return m_numverts;
+}
+
+
+
+void RAS_Polygon::SetVertex(int i,
+ int vertexindex ) //const MT_Point3& xyz,const MT_Point2& uv,const unsigned int rgbacolor,const MT_Vector3& normal)
+{
+ m_vertexindexbase.SetIndex(i,vertexindex); //m_bucket->FindOrAddVertex(m_vertexindexbase.m_vtxarray,
+ //xyz,uv,rgbacolor,normal));
+}
+
+
+
+const KX_VertexIndex& RAS_Polygon::GetIndexBase()
+{
+ return m_vertexindexbase;
+}
+
+
+
+void RAS_Polygon::SetVisibleWireframeEdges(int edgecode)
+{
+ m_edgecode = edgecode;
+}
+
+
+
+// each bit is for a visible edge, starting with bit 1 for the first edge, bit 2 for second etc.
+int RAS_Polygon::GetEdgeCode()
+{
+ return m_edgecode;
+}
+
+
+
+bool RAS_Polygon::IsVisible()
+{
+ return m_polyFlags.Visible;
+}
+
+
+
+bool RAS_Polygon::IsCollider()
+{
+ return m_polyFlags.Collider;
+}
+
+
+
+void RAS_Polygon::SetCollider(bool col)
+{
+ m_polyFlags.Collider = col;
+}
+
+
+
+KX_VertexIndex& RAS_Polygon::GetVertexIndexBase()
+{
+ return m_vertexindexbase;
+}
+
+
+
+RAS_MaterialBucket* RAS_Polygon::GetMaterial()
+{
+ return m_bucket;
+}
diff --git a/source/gameengine/Rasterizer/RAS_Polygon.h b/source/gameengine/Rasterizer/RAS_Polygon.h
new file mode 100644
index 00000000000..d5b6123e153
--- /dev/null
+++ b/source/gameengine/Rasterizer/RAS_Polygon.h
@@ -0,0 +1,92 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 __RAS_POLYGON
+#define __RAS_POLYGON
+
+#include "RAS_TexVert.h"
+//#include "KX_BoundingVolumes.h"
+#include "RAS_MaterialBucket.h"
+
+#include <vector>
+using namespace std;
+
+
+//
+// Bitfield that stores the flags for each CValue derived class
+//
+struct PolygonFlags {
+ PolygonFlags() :
+ Visible(true),
+ Collider(true)
+ {
+ }
+ unsigned char Visible : 1;
+ unsigned char Collider : 1;
+ //int Visible : 1;
+ //int Collider : 1;
+};
+
+class RAS_Polygon
+{
+ RAS_MaterialBucket* m_bucket;
+ KX_VertexIndex m_vertexindexbase;
+ int m_numverts;
+ int m_edgecode;
+ PolygonFlags m_polyFlags;
+
+
+public:
+ RAS_Polygon(RAS_MaterialBucket* bucket,
+ bool visible,
+ int numverts,
+ int vtxarrayindex) ;
+ virtual ~RAS_Polygon() {};
+
+// RAS_TexVert* GetVertex(int index);
+ int VertexCount();
+ void SetVertex(int i,int vertexindex); //const MT_Point3& xyz,const MT_Point2& uv,const unsigned int rgbacolor,const MT_Vector3& normal)
+
+ const KX_VertexIndex& GetIndexBase();
+
+ void SetVisibleWireframeEdges(int edgecode);
+ // each bit is for a visible edge, starting with bit 1 for the first edge, bit 2 for second etc.
+ int GetEdgeCode();
+
+ bool IsVisible();
+ bool IsCollider();
+ void SetCollider(bool col);
+
+ KX_VertexIndex& GetVertexIndexBase();
+ RAS_MaterialBucket* GetMaterial();
+
+};
+#endif
diff --git a/source/gameengine/Rasterizer/RAS_Rect.h b/source/gameengine/Rasterizer/RAS_Rect.h
new file mode 100644
index 00000000000..448a5ec73c1
--- /dev/null
+++ b/source/gameengine/Rasterizer/RAS_Rect.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 _RAS_RECT
+#define _RAS_RECT
+
+
+/**
+ * @section interface class.
+ * RAS_Rect just encodes a simple rectangle.
+ * Should be part of a generic library
+ */
+
+class RAS_Rect
+{
+public: // todo: make a decent class, and make private
+ int m_x1, m_y1;
+ int m_x2, m_y2;
+
+public:
+ RAS_Rect() : m_x1(0), m_y1(0), m_x2(0), m_y2(0) {}
+ int GetWidth(
+ ) const {
+ return m_x2 - m_x1;
+ }
+ int GetHeight(
+ ) const {
+ return m_y2 - m_y1;
+ }
+ int GetLeft(
+ ) const {
+ return m_x1;
+ }
+ int GetRight(
+ ) const {
+ return m_x2;
+ }
+ int GetBottom(
+ ) const {
+ return m_y1;
+ }
+ int GetTop(
+ ) const {
+ return m_y2;
+ }
+
+ void SetLeft(
+ int x1)
+ {
+ m_x1 = x1;
+ }
+ void SetBottom(
+ int y1)
+ {
+ m_y1 = y1;
+ }
+ void SetRight(
+ int x2)
+ {
+ m_x2 = x2;
+ }
+ void SetTop(
+ int y2)
+ {
+ m_y2 = y2;
+ }
+};
+
+
+#endif // _RAS_RECT
diff --git a/source/gameengine/Rasterizer/RAS_TexMatrix.h b/source/gameengine/Rasterizer/RAS_TexMatrix.h
new file mode 100644
index 00000000000..c4d02c49154
--- /dev/null
+++ b/source/gameengine/Rasterizer/RAS_TexMatrix.h
@@ -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 *****
+ */
+#ifndef __RASTEXMATRIX
+#define __RASTEXMATRIX
+
+#include "MT_Matrix3x3.h"
+#include "MT_Point3.h"
+#include "MT_Point2.h"
+
+
+
+#include "RAS_TexVert.h"
+
+void RAS_CalcTexMatrix(RAS_TexVert p[3],MT_Point3& origin,MT_Vector3& udir,MT_Vector3& vdir);
+
+#endif //__RASTEXMATRIX
diff --git a/source/gameengine/Rasterizer/RAS_TexVert.cpp b/source/gameengine/Rasterizer/RAS_TexVert.cpp
new file mode 100644
index 00000000000..20a4f0d2570
--- /dev/null
+++ b/source/gameengine/Rasterizer/RAS_TexVert.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 "RAS_TexVert.h"
+
+
+RAS_TexVert::RAS_TexVert(const MT_Point3& xyz,
+ const MT_Point2& uv,
+ const unsigned int rgba,
+ const short *normal,
+ const short flag)
+{
+ xyz.getValue(m_localxyz);
+ uv.getValue(m_uv1);
+ SetRGBA(rgba);
+ m_normal[0] = normal[0];
+ m_normal[1] = normal[1];
+ m_normal[2] = normal[2];
+ m_flag = flag;
+}
+
+
+
+const float* RAS_TexVert::getUV1 () const
+{
+ return m_uv1;
+}
+
+
+
+const MT_Point3& RAS_TexVert::xyz()
+{
+ g_pt3.setValue(m_localxyz);
+ return g_pt3;
+}
+
+void RAS_TexVert::SetXYZ(const MT_Point3& xyz)
+{
+ xyz.getValue(m_localxyz);
+}
+
+
+
+void RAS_TexVert::SetUV(const MT_Point2& uv)
+{
+ uv.getValue(m_uv1);
+}
+
+
+
+void RAS_TexVert::SetRGBA(const unsigned int rgba)
+{
+ m_rgba = rgba;
+}
+
+
+void RAS_TexVert::SetFlag(const short flag)
+{
+ m_flag = flag;
+}
+void RAS_TexVert::SetNormal(const MT_Vector3& normal)
+{
+ m_normal[0] = short(normal.x()*32767.0);
+ m_normal[1] = short(normal.y()*32767.0);
+ m_normal[2] = short(normal.z()*32767.0);
+}
+
+
+
+// leave multiline for debugging
+const short* RAS_TexVert::getNormal() const
+{
+ return m_normal;
+}
+
+
+
+const float* RAS_TexVert::getLocalXYZ() const
+{
+ return m_localxyz;
+}
+
+
+
+const unsigned int& RAS_TexVert::getRGBA() const
+{
+ return m_rgba;
+}
+
+
+
+// compare two vertices, and return TRUE if both are almost identical (they can be shared)
+bool RAS_TexVert::closeTo(const RAS_TexVert* other)
+{
+ return ((MT_Vector3(m_localxyz) - MT_Vector3(other->m_localxyz)).fuzzyZero() &&
+ (MT_Vector2(m_uv1) - MT_Vector2(other->m_uv1)).fuzzyZero() &&
+ m_normal[0] == other->m_normal[0] &&
+ m_normal[1] == other->m_normal[1] &&
+ m_normal[2] == other->m_normal[2] &&
+ m_flag == other->m_flag &&
+ m_rgba == other->m_rgba) ;
+
+}
+
+
+
+bool RAS_TexVert::closeTo(const MT_Point3& otherxyz,
+ const MT_Point2& otheruv,
+ const unsigned int otherrgba,
+ short othernormal[3]) const
+{
+ return ((MT_Vector3(m_localxyz) - otherxyz).fuzzyZero() &&
+ (MT_Vector2(m_uv1) - otheruv).fuzzyZero() &&
+ m_normal[0] == othernormal[0] &&
+ m_normal[1] == othernormal[1] &&
+ m_normal[2] == othernormal[2] &&
+ m_rgba == otherrgba) ;
+}
+
+
+short RAS_TexVert::getFlag() const
+{
+ return m_flag;
+}
diff --git a/source/gameengine/Rasterizer/RAS_TexVert.h b/source/gameengine/Rasterizer/RAS_TexVert.h
new file mode 100644
index 00000000000..ebbd35fb91c
--- /dev/null
+++ b/source/gameengine/Rasterizer/RAS_TexVert.h
@@ -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 *****
+ */
+#ifndef __RAS_TEXVERT
+#define __RAS_TEXVERT
+
+
+#include "MT_Point3.h"
+#include "MT_Point2.h"
+#include "MT_Transform.h"
+
+
+static MT_Point3 g_pt3;
+static MT_Point2 g_pt2;
+
+#define TV_CALCFACENORMAL 0x0001
+
+class RAS_TexVert
+{
+
+ float m_localxyz[3]; // 3*4=12 = 24
+ float m_uv1[2]; // 2*4=8 = 24 + 16 = 40
+ unsigned int m_rgba; //4 = 40 + 4 = 44
+ short m_normal[3]; //3*2=6 = 50
+ short m_flag; //32 bytes total size, fits nice = 52 = not fit nice
+
+
+public:
+ short getFlag() const;
+ RAS_TexVert()// :m_xyz(0,0,0),m_uv(0,0),m_rgba(0)
+ {}
+ RAS_TexVert(const MT_Point3& xyz,
+ const MT_Point2& uv,
+ const unsigned int rgba,
+ const short *normal,
+ const short flag);
+ ~RAS_TexVert() {};
+
+ // leave multiline for debugging
+ const float* getUV1 () const;
+
+ //const float* getUV1 () const {
+ // return m_uv1;
+ //};
+
+ const MT_Point3& xyz();
+
+ void SetXYZ(const MT_Point3& xyz);
+ void SetUV(const MT_Point2& uv);
+ void SetRGBA(const unsigned int rgba);
+ void SetNormal(const MT_Vector3& normal);
+ void SetFlag(const short flag);
+ // leave multiline for debugging
+ const short* getNormal() const;
+ //const float* getLocalXYZ() const {
+ // return m_localxyz;
+ //};
+
+ const float* getLocalXYZ() const;
+ const unsigned int& getRGBA() const;
+ // compare two vertices, and return TRUE if both are almost identical (they can be shared)
+ bool closeTo(const RAS_TexVert* other);
+
+ bool closeTo(const MT_Point3& otherxyz,
+ const MT_Point2& otheruv,
+ const unsigned int otherrgba,
+ short othernormal[3]) const;
+};
+
+#endif //__RAS_TEXVERT
diff --git a/source/gameengine/Rasterizer/RAS_texmatrix.cpp b/source/gameengine/Rasterizer/RAS_texmatrix.cpp
new file mode 100644
index 00000000000..515f05b8303
--- /dev/null
+++ b/source/gameengine/Rasterizer/RAS_texmatrix.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 "RAS_TexMatrix.h"
+
+
+void RAS_CalcTexMatrix(RAS_TexVert p[3],MT_Point3& origin,MT_Vector3& udir,MT_Vector3& vdir)
+{
+// precondition: 3 vertices are non-colinear
+
+ MT_Vector3 vec1 = p[1].xyz()-p[0].xyz();
+ MT_Vector3 vec2 = p[2].xyz()-p[0].xyz();
+ MT_Vector3 normal = vec1.cross(vec2);
+ normal.normalize();
+
+ // determine which coordinate we drop, ie. max coordinate in the normal
+
+
+ int ZCOORD = normal.closestAxis();
+ int XCOORD = (ZCOORD+1)%3;
+ int YCOORD = (ZCOORD+2)%3;
+
+ // ax+by+cz+d=0
+ MT_Scalar d = -p[0].xyz().dot(normal);
+
+
+ MT_Matrix3x3 mat3( p[0].getUV1()[0],p[0].getUV1()[1], 1,
+ p[1].getUV1()[0],p[1].getUV1()[1], 1,
+ p[2].getUV1()[0],p[2].getUV1()[1], 1);
+
+
+ MT_Matrix3x3 mat3inv = mat3.inverse();
+
+ MT_Vector3 p123x(p[0].xyz()[XCOORD],p[1].xyz()[XCOORD],p[2].xyz()[XCOORD]);
+ MT_Vector3 resultx = mat3inv*p123x;
+ MT_Vector3 p123y(p[0].xyz()[YCOORD],p[1].xyz()[YCOORD],p[2].xyz()[YCOORD]);
+ MT_Vector3 resulty = mat3inv*p123y;
+
+ // normal[ZCOORD] is not zero, because it's chosen to be maximal (absolute), and normal has length 1,
+ // so at least on of the coords is <> 0
+
+ //droppedvalue udir.dot(normal) =0
+ MT_Scalar droppedu = -(resultx.x()*normal[XCOORD]+resulty.x()*normal[YCOORD])/normal[ZCOORD];
+ udir[XCOORD] = resultx.x();
+ udir[YCOORD] = resulty.x();
+ udir[ZCOORD] = droppedu;
+ MT_Scalar droppedv = -(resultx.y()*normal[XCOORD]+resulty.y()*normal[YCOORD])/normal[ZCOORD];
+ vdir[XCOORD] = resultx.y();
+ vdir[YCOORD] = resulty.y();
+ vdir[ZCOORD] = droppedv;
+ // droppedvalue b = -(ax+cz+d)/y;
+ MT_Scalar droppedvalue = -((resultx.z()*normal[XCOORD] + resulty.z()*normal[YCOORD]+d))/normal[ZCOORD];
+ origin[XCOORD] = resultx.z();
+ origin[YCOORD] = resulty.z();
+ origin[ZCOORD] = droppedvalue;
+
+
+}
+
+#ifdef _TEXOWNMAIN
+
+int main()
+{
+
+ MT_Point2 puv0={0,0};
+ MT_Point3 pxyz0 (0,0,128);
+
+ MT_Scalar puv1[2]={1,0};
+ MT_Point3 pxyz1(128,0,128);
+
+ MT_Scalar puv2[2]={1,1};
+ MT_Point3 pxyz2(128,0,0);
+
+ RAS_TexVert p0(pxyz0,puv0);
+ RAS_TexVert p1(pxyz1,puv1);
+ RAS_TexVert p2(pxyz2,puv2);
+
+ RAS_TexVert vertices[3] =
+ {
+ p0,
+ p1,
+ p2
+ };
+
+ MT_Vector3 udir,vdir;
+ MT_Point3 origin;
+ CalcTexMatrix(vertices,origin,udir,vdir);
+
+ MT_Point3 testpoint(128,32,64);
+
+ MT_Scalar lenu = udir.length2();
+ MT_Scalar lenv = vdir.length2();
+
+ MT_Scalar testu=((pxyz2-origin).dot(udir))/lenu;
+ MT_Scalar testv=((pxyz2-origin).dot(vdir))/lenv;
+
+
+
+
+ return 0;
+}
+
+#endif // _TEXOWNMAIN
diff --git a/source/gameengine/SceneGraph/Makefile b/source/gameengine/SceneGraph/Makefile
new file mode 100644
index 00000000000..bc184c8faba
--- /dev/null
+++ b/source/gameengine/SceneGraph/Makefile
@@ -0,0 +1,41 @@
+#
+# $Id$
+#
+# ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version. The Blender
+# Foundation also sells licenses for use in proprietary software under
+# the Blender License. See http://www.blender.org/BL/ for information
+# about this.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2001-2002 by 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 = scenegraph
+DIR = $(OCGDIR)/gameengine/$(LIBNAME)
+
+include nan_compile.mk
+
+CCFLAGS += $(LEVEL_1_CPP_WARNINGS)
+
+CPPFLAGS += -I$(NAN_MOTO)/include
diff --git a/source/gameengine/SceneGraph/SG_Controller.cpp b/source/gameengine/SceneGraph/SG_Controller.cpp
new file mode 100644
index 00000000000..4a5735bb4c0
--- /dev/null
+++ b/source/gameengine/SceneGraph/SG_Controller.cpp
@@ -0,0 +1,49 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "SG_Controller.h"
+
+
+ void
+SG_Controller::
+SetObject(SG_IObject* obj)
+{
+ m_pObject = obj; // no checks yet ?
+}
+
+ void
+SG_Controller::
+ClearObject(
+){
+ m_pObject = NULL;
+}
+
+
diff --git a/source/gameengine/SceneGraph/SG_Controller.h b/source/gameengine/SceneGraph/SG_Controller.h
new file mode 100644
index 00000000000..9753af45a99
--- /dev/null
+++ b/source/gameengine/SceneGraph/SG_Controller.h
@@ -0,0 +1,116 @@
+/**
+ * Implementationclass to derive controllers from
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 __SG_CONTROLLER_H
+#define __SG_CONTROLLER_H
+
+
+#include "SG_IObject.h"
+class SG_Controller
+{
+public:
+ SG_Controller(
+ ) :
+ m_pObject(NULL) {
+ }
+
+ virtual
+ ~SG_Controller(
+ ) {};
+
+ virtual
+ bool
+ Update(
+ double time
+ )=0;
+
+ virtual
+ void
+ SetObject (
+ SG_IObject* object
+ );
+
+ void
+ ClearObject(
+ );
+
+ virtual
+ void
+ SetSimulatedTime(
+ double time
+ )=0;
+
+ virtual
+ SG_Controller*
+ GetReplica(
+ class SG_Node* destnode
+ )=0;
+
+ /**
+ * Hacky way of passing options to specific controllers
+ * @param option An integer identifying the option.
+ * @param value The value of this option.
+ * @attention This has been placed here to give sca-elements
+ * @attention some control over the controllers. This is
+ * @attention necessary because the identity of the controller
+ * @attention is lost on the way here.
+ */
+ virtual
+ void
+ SetOption(
+ int option,
+ int value
+ )=0;
+
+ /**
+ * Option-identifiers: SG_CONTR_<controller-type>_<option>.
+ * Options only apply to a specific controller type. The
+ * semantics are defined by whoever uses the setting.
+ */
+ enum SG_Controller_option {
+ SG_CONTR_NODEF = 0,
+ SG_CONTR_IPO_IPO_AS_FORCE,
+ SG_CONTR_IPO_FORCES_ACT_LOCAL,
+ SG_CONTR_CAMIPO_LENS,
+ SG_CONTR_CAMIPO_CLIPEND,
+ SG_CONTR_CAMIPO_CLIPSTART,
+ SG_CONTR_MAX
+ };
+
+protected:
+ SG_IObject* m_pObject;
+
+};
+
+#endif //__SG_CONTROLLER_H
diff --git a/source/gameengine/SceneGraph/SG_IObject.cpp b/source/gameengine/SceneGraph/SG_IObject.cpp
new file mode 100644
index 00000000000..2561bd0c672
--- /dev/null
+++ b/source/gameengine/SceneGraph/SG_IObject.cpp
@@ -0,0 +1,153 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "SG_IObject.h"
+
+#include "SG_Controller.h"
+
+SG_IObject::
+SG_IObject(
+ void* clientobj,
+ void* clientinfo,
+ SG_Callbacks callbacks
+):
+ m_SGclientObject(clientobj),
+ m_SGclientInfo(clientinfo),
+ m_callbacks(callbacks)
+{
+ //nothing to do
+}
+
+SG_IObject::
+SG_IObject(
+ const SG_IObject &other
+) :
+ m_SGclientObject(other.m_SGclientObject),
+ m_SGclientInfo(other.m_SGclientInfo),
+ m_callbacks(other.m_callbacks)
+{
+ //nothing to do
+}
+
+ void
+SG_IObject::
+AddSGController(
+ SG_Controller* cont
+){
+ m_SGcontrollers.push_back(cont);
+}
+
+ void
+SG_IObject::
+RemoveAllControllers(
+) {
+ m_SGcontrollers.clear();
+}
+
+/// Needed for replication
+ SGControllerList&
+SG_IObject::
+GetSGControllerList(
+){
+ return m_SGcontrollers;
+}
+
+ void*
+SG_IObject::
+GetSGClientObject(
+){
+ return m_SGclientObject;
+}
+
+const
+ void*
+SG_IObject::
+GetSGClientObject(
+) const {
+ return m_SGclientObject;
+}
+
+ void
+SG_IObject::
+SetSGClientObject(
+ void* clientObject
+){
+ m_SGclientObject = clientObject;
+}
+
+
+ void
+SG_IObject::
+ActivateReplicationCallback(
+ SG_IObject *replica
+){
+ if (m_callbacks.m_replicafunc)
+ {
+ // Call client provided replication func
+ m_callbacks.m_replicafunc(replica,m_SGclientObject,m_SGclientInfo);
+ }
+};
+
+ void
+SG_IObject::
+ActivateDestructionCallback(
+){
+ if (m_callbacks.m_destructionfunc)
+ {
+ // Call client provided destruction function on this!
+ m_callbacks.m_destructionfunc(this,m_SGclientObject,m_SGclientInfo);
+ }
+}
+
+ void
+SG_IObject::
+SetControllerTime(
+ double time
+){
+ SGControllerList::iterator contit;
+
+ for (contit = m_SGcontrollers.begin();contit!=m_SGcontrollers.end();++contit)
+ {
+ (*contit)->SetSimulatedTime(time);
+ }
+}
+
+
+SG_IObject::
+~SG_IObject()
+{
+ SGControllerList::iterator contit;
+
+ for (contit = m_SGcontrollers.begin();contit!=m_SGcontrollers.end();++contit)
+ {
+ delete (*contit);
+ }
+}
diff --git a/source/gameengine/SceneGraph/SG_IObject.h b/source/gameengine/SceneGraph/SG_IObject.h
new file mode 100644
index 00000000000..f9066a9b340
--- /dev/null
+++ b/source/gameengine/SceneGraph/SG_IObject.h
@@ -0,0 +1,220 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 __SG_IOBJECT
+#define __SG_IOBJECT
+/**
+base object that can be part of the scenegraph.
+*/
+#include <vector>
+
+
+class SG_Controller;
+class SG_IObject;
+
+typedef std::vector<SG_Controller*> SGControllerList;
+
+typedef void* (*SG_ReplicationNewCallback)(
+ SG_IObject* sgobject,
+ void* clientobj,
+ void* clientinfo
+);
+
+typedef void* (*SG_DestructionNewCallback)(
+ SG_IObject* sgobject,
+ void* clientobj,
+ void* clientinfo
+);
+
+
+/**
+ * SG_Callbacks hold 2 call backs to the outside world.
+ * The first is meant to be called when objects are replicated.
+ * And allows the outside world to syncronise external objects
+ * with replicated nodes and their children.
+ * The second is called when a node is detroyed and again
+ * is their for synconisation purposes
+ * These callbacks may both be NULL.
+ * The efficacy of this approach has not been proved some
+ * alternatives might be to perform all replication and destruction
+ * externally.
+ * To define a class interface rather than a simple function
+ * call back so that replication information can be transmitted from
+ * parent->child.
+ */
+struct SG_Callbacks
+{
+ SG_Callbacks(
+ ):
+ m_replicafunc(NULL),
+ m_destructionfunc(NULL)
+ {
+ };
+
+ SG_Callbacks(
+ SG_ReplicationNewCallback repfunc,
+ SG_DestructionNewCallback destructfunc
+ ):
+ m_replicafunc(repfunc),
+ m_destructionfunc(destructfunc)
+ {
+ };
+
+ SG_ReplicationNewCallback m_replicafunc;
+ SG_DestructionNewCallback m_destructionfunc;
+};
+
+class SG_IObject
+{
+private :
+
+ void* m_SGclientObject;
+ void* m_SGclientInfo;
+ SG_Callbacks m_callbacks;
+ SGControllerList m_SGcontrollers;
+
+public:
+
+
+ virtual ~SG_IObject();
+
+
+ /**
+ * Add a pointer to a controller allocated on the heap, to
+ * this node. This memory for this controller becomes the
+ * responsibility of this class. It will be deleted when
+ * this object is deleted.
+ */
+
+ void
+ AddSGController(
+ SG_Controller* cont
+ );
+
+ /**
+ * Clear the array of pointers to controllers associated with
+ * this node. This does not delete the controllers themselves!
+ * This should be used very carefully to avoid memory
+ * leaks.
+ */
+
+ void
+ RemoveAllControllers(
+ );
+
+ /// Needed for replication
+
+ /**
+ * Return a reference to this node's controller list.
+ * Whilst we don't wish to expose full control of the container
+ * to the user we do allow them to call non_const methods
+ * on pointers in the container. C++ topic: how to do this in
+ * using STL?
+ */
+
+ SGControllerList&
+ GetSGControllerList(
+ );
+
+
+ /**
+ * Get the client object associated with this
+ * node. This interface allows you to associate
+ * arbitray external objects with this node. They are
+ * passed to the callback functions when they are
+ * activated so you can syncronise these external objects
+ * upon replication and destruction
+ * This may be NULL.
+ */
+
+ void*
+ GetSGClientObject(
+ );
+
+ const
+ void*
+ GetSGClientObject(
+ ) const ;
+
+
+ /**
+ * Set the client object for this node. This is just a
+ * pointer to an object allocated that should exist for
+ * the duration of the lifetime of this object, or untill
+ * this function is called again.
+ */
+
+ void
+ SetSGClientObject(
+ void* clientObject
+ );
+
+ /**
+ * Set the current simulation time for this node.
+ * The implementation of this function runs through
+ * the nodes list of controllers and calls their SetSimulatedTime methods
+ */
+
+ void
+ SetControllerTime(
+ double time
+ );
+
+ virtual
+ void
+ Destruct(
+ ) = 0;
+
+protected :
+
+ void
+ ActivateReplicationCallback(
+ SG_IObject *replica
+ );
+
+ void
+ ActivateDestructionCallback(
+ );
+
+ SG_IObject(
+ void* clientobj,
+ void* clientinfo,
+ SG_Callbacks callbacks
+ );
+
+ SG_IObject(
+ const SG_IObject &other
+ );
+
+
+};
+
+#endif //__SG_IOBJECT
diff --git a/source/gameengine/SceneGraph/SG_Node.cpp b/source/gameengine/SceneGraph/SG_Node.cpp
new file mode 100644
index 00000000000..d40cdca0c76
--- /dev/null
+++ b/source/gameengine/SceneGraph/SG_Node.cpp
@@ -0,0 +1,231 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "SG_Node.h"
+
+#include "SG_ParentRelation.h"
+
+#include <algorithm>
+
+using namespace std;
+
+
+SG_Node::SG_Node(
+ void* clientobj,
+ void* clientinfo,
+ SG_Callbacks callbacks
+
+)
+ : SG_Spatial(clientobj,clientinfo,callbacks),
+ m_SGparent(NULL)
+{
+}
+
+SG_Node::SG_Node(
+ const SG_Node & other
+) :
+ SG_Spatial(other),
+ m_SGparent(other.m_SGparent),
+ m_children(other.m_children)
+{
+ // nothing to do
+}
+
+SG_Node::~SG_Node()
+{
+}
+
+
+SG_Node* SG_Node::GetSGReplica()
+{
+ SG_Node* replica = new SG_Node(*this);
+ if (replica == NULL) return NULL;
+
+ ProcessSGReplica(replica);
+
+ return replica;
+}
+
+ void
+SG_Node::
+ProcessSGReplica(
+ SG_Node* replica
+){
+ // Apply the replication call back function.
+ ActivateReplicationCallback(replica);
+
+ // clear the replica node of it's parent.
+ static_cast<SG_Node*>(replica)->m_SGparent = NULL;
+
+ if (m_children.begin() != m_children.end())
+ {
+ // if this node has children, the replica has too, so clear and clone children
+ replica->ClearSGChildren();
+
+ NodeList::iterator childit;
+ for (childit = m_children.begin();childit!=m_children.end();++childit)
+ {
+ replica->AddChild((*childit)->GetSGReplica());
+ }
+ }
+}
+
+
+ void
+SG_Node::
+Destruct()
+{
+ // Not entirely sure what Destruct() expects to happen.
+ // I think it probably means just to call the DestructionCallback
+ // in the right order on all the children - rather than free any memory
+
+ // We'll delete m_parent_relation now anyway.
+
+ delete(m_parent_relation);
+ m_parent_relation = NULL;
+
+ if (m_children.begin() != m_children.end())
+ {
+ NodeList::iterator childit;
+ for (childit = m_children.begin();childit!=m_children.end();++childit)
+ {
+ // call the SG_Node destruct method on each of our children }-)
+ (*childit)->Destruct();
+ }
+ }
+
+ ActivateDestructionCallback();
+}
+
+
+ SG_Node*
+SG_Node::
+GetSGParent(
+) const {
+ return m_SGparent;
+}
+
+ void
+SG_Node::
+SetSGParent(
+ SG_Node* parent
+){
+ m_SGparent = parent;
+}
+
+const
+ SG_Node*
+SG_Node::
+GetRootSGParent(
+) const {
+ return (m_SGparent ? (const SG_Node*) m_SGparent->GetRootSGParent() : (const SG_Node*) this);
+}
+
+
+ void
+SG_Node::
+DisconnectFromParent(
+){
+ if (m_SGparent)
+ {
+ m_SGparent->RemoveChild(this);
+ m_SGparent = NULL;
+ }
+
+}
+
+
+
+void SG_Node::AddChild(SG_Node* child)
+{
+ m_children.push_back(child);
+ child->SetSGParent(this); // this way ?
+}
+
+void SG_Node::RemoveChild(SG_Node* child)
+{
+ NodeList::iterator childfound = find(m_children.begin(),m_children.end(),child);
+
+ if (childfound != m_children.end())
+ {
+ m_children.erase(childfound);
+ }
+}
+
+
+
+void SG_Node::UpdateWorldData(double time)
+{
+ UpdateSpatialData(GetSGParent(),time);
+
+ // update children's worlddata
+ for (NodeList::iterator it = m_children.begin();it!=m_children.end();++it)
+ {
+ (*it)->UpdateWorldData(time);
+ }
+}
+
+
+NodeList& SG_Node::GetSGChildren()
+{
+ return this->m_children;
+}
+
+
+const NodeList& SG_Node::GetSGChildren() const
+{
+ return this->m_children;
+}
+
+
+void SG_Node::ClearSGChildren()
+{
+ m_children.clear();
+}
+
+
+
+void SG_Node::SetSimulatedTime(double time,bool recurse)
+{
+
+ // update the controllers of this node.
+ SetControllerTime(time);
+
+ // update children's simulate time.
+ if (recurse)
+ {
+ for (NodeList::iterator it = m_children.begin();it!=m_children.end();++it)
+ {
+ (*it)->SetSimulatedTime(time,recurse);
+ }
+ }
+}
+
diff --git a/source/gameengine/SceneGraph/SG_Node.h b/source/gameengine/SceneGraph/SG_Node.h
new file mode 100644
index 00000000000..a42afefcf1e
--- /dev/null
+++ b/source/gameengine/SceneGraph/SG_Node.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 __SG_NODE_H
+#define __SG_NODE_H
+
+#include "SG_Spatial.h"
+
+#include <vector>
+
+typedef std::vector<SG_Node*> NodeList;
+
+class SG_Node : public SG_Spatial
+{
+
+public:
+
+ SG_Node(
+ void* clientobj,
+ void* clientinfo,
+ SG_Callbacks callbacks
+ );
+
+ SG_Node(
+ const SG_Node & other
+ );
+
+ virtual ~SG_Node();
+
+
+ /**
+ * Add a child to this object. This also informs the child of
+ * it's parent.
+ * This just stores a pointer to the child and does not
+ * make a deep copy.
+ */
+
+ void
+ AddChild(
+ SG_Node* child
+ );
+
+ /**
+ * Remove a child node from this object. This just removes the child
+ * pointer from the list of children - it does not destroy the child.
+ * This does not inform the child that this node is no longer it's parent.
+ * If the node was not a child of this object no action is performed.
+ */
+
+ void
+ RemoveChild(
+ SG_Node* child
+ );
+
+ /**
+ * Get the current list of children. Do not use this interface for
+ * adding or removing children please use the methods of this class for
+ * that.
+ * @return a reference to the list of children of this node.
+ */
+
+ NodeList&
+ GetSGChildren(
+ );
+
+ /**
+ * Get the current list of children.
+ * @return a const reference to the current list of children of this node.
+ */
+
+ const
+ NodeList&
+ GetSGChildren(
+ ) const;
+
+ /**
+ * Clear the list of children associated with this node
+ */
+
+ void
+ ClearSGChildren(
+ );
+
+ /**
+ * return the parent of this node if it exists.
+ */
+
+ SG_Node*
+ GetSGParent(
+ ) const ;
+
+
+ /**
+ * Set the parent of this node.
+ */
+
+ void
+ SetSGParent(
+ SG_Node* parent
+ );
+
+ /**
+ * Return the top node in this node's Scene graph hierarchy
+ */
+
+ const
+ SG_Node*
+ GetRootSGParent(
+ ) const;
+
+ /**
+ * Disconnect this node from it's parent
+ */
+
+ void
+ DisconnectFromParent(
+ );
+
+ /**
+ * Tell this node to treat it's parent as a vertex parent.
+ */
+
+ void
+ SetVertexParent(
+ bool isvertexparent
+ ) ;
+
+
+ /**
+ * Update the spatial data of this node. Iterate through
+ * the children of this node and update their world data.
+ */
+
+ void
+ UpdateWorldData(
+ double time
+ );
+
+ /**
+ * Update the simulation time of this node. Iterate through
+ * the children nodes and update their simulated time.
+ */
+
+ void
+ SetSimulatedTime(
+ double time,
+ bool resurse
+ );
+
+ /**
+ * Node replication functions.
+ */
+
+ SG_Node*
+ GetSGReplica(
+ );
+
+ void
+ Destruct(
+ );
+
+private:
+
+ void
+ ProcessSGReplica(
+ SG_Node* replica
+ );
+
+ /**
+ * The list of children of this node.
+ */
+ NodeList m_children;
+
+ /**
+ * The parent of this node may be NULL
+ */
+ SG_Node* m_SGparent;
+
+};
+#endif //__SG_NODE_H
diff --git a/source/gameengine/SceneGraph/SG_ParentRelation.h b/source/gameengine/SceneGraph/SG_ParentRelation.h
new file mode 100644
index 00000000000..5df8efe7027
--- /dev/null
+++ b/source/gameengine/SceneGraph/SG_ParentRelation.h
@@ -0,0 +1,116 @@
+/**
+ * @mainpage SG_ParentRelation
+
+ * @section
+ *
+ * This is an abstract interface class to the Scene Graph library.
+ * It allows you to specify how child nodes react to parent nodes.
+ * Normally a child will use it's parent's transforms to compute
+ * it's own global transforms. How this is performed depends on
+ * the type of relation. For example if the parent is a vertex
+ * parent to this child then the child should not inherit any
+ * rotation information from the parent. Or if the parent is a
+ * 'slow parent' to this child then the child should react
+ * slowly to changes in the parent's position. The exact relation
+ * is left for you to implement by filling out this interface
+ * with concrete examples.
+ *
+ * There is exactly one SG_ParentRelation per SG_Node. Subclasses
+ * should not be value types and should be allocated on the heap.
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 __SG_ParentRelation_h
+#define __SG_ParentRelation_h
+
+class SG_Spatial;
+
+class SG_ParentRelation {
+
+public :
+
+ /**
+ * Update the childs local and global coordinates
+ * based upon the parents global coordinates.
+ * You must also handle the case when this node has no
+ * parent (parent == NULL). Usually you should just
+ * copy the local coordinates of the child to the
+ * world coordinates.
+ */
+
+ virtual
+ void
+ UpdateChildCoordinates(
+ SG_Spatial * child,
+ const SG_Spatial * parent
+ ) = 0;
+
+ virtual
+ ~SG_ParentRelation(
+ ){
+ };
+
+ /**
+ * You must provide a way of duplicating an
+ * instance of an SG_ParentRelation. This should
+ * return a pointer to a new duplicate allocated
+ * on the heap. Responsibilty for deleting the
+ * duplicate resides with the caller of this method.
+ */
+
+ virtual
+ SG_ParentRelation *
+ NewCopy(
+ ) = 0;
+
+protected :
+
+ /**
+ * Protected constructors
+ * this class is not meant to be instantiated.
+ */
+
+ SG_ParentRelation(
+ ) {
+ };
+
+ /**
+ * Copy construction should not be implemented
+ */
+
+ SG_ParentRelation(
+ const SG_ParentRelation &
+ );
+};
+
+#endif
diff --git a/source/gameengine/SceneGraph/SG_Spatial.cpp b/source/gameengine/SceneGraph/SG_Spatial.cpp
new file mode 100644
index 00000000000..96370f28ef3
--- /dev/null
+++ b/source/gameengine/SceneGraph/SG_Spatial.cpp
@@ -0,0 +1,283 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 "SG_Node.h"
+#include "SG_Spatial.h"
+#include "SG_Controller.h"
+#include "SG_ParentRelation.h"
+
+SG_Spatial::
+SG_Spatial(
+ void* clientobj,
+ void* clientinfo,
+ SG_Callbacks callbacks
+):
+
+ SG_IObject(clientobj,clientinfo,callbacks),
+ m_localPosition(MT_Point3(0,0,0)),
+ m_localScaling(MT_Vector3(1.f,1.f,1.f)),
+ m_localRotation(1,0,0,0,1,0,0,0,1),
+ m_parent_relation (NULL),
+
+ m_worldPosition(MT_Point3(0,0,0)),
+ m_worldScaling(MT_Vector3(1.f,1.f,1.f)),
+ m_worldRotation(0,0,0,0,0,0,0,0,0)
+
+{
+}
+
+SG_Spatial::
+SG_Spatial(
+ const SG_Spatial& other
+) :
+ SG_IObject(other),
+ m_localPosition(other.m_localPosition),
+ m_localScaling(other.m_localScaling),
+ m_localRotation(other.m_localRotation),
+ m_parent_relation(NULL),
+ m_worldPosition(other.m_worldPosition),
+ m_worldScaling(other.m_worldScaling),
+ m_worldRotation(other.m_worldRotation)
+{
+ // duplicate the parent relation for this object
+ m_parent_relation = other.m_parent_relation->NewCopy();
+}
+
+SG_Spatial::
+~SG_Spatial()
+{
+ delete (m_parent_relation);
+}
+
+ void
+SG_Spatial::
+SetParentRelation(
+ SG_ParentRelation *relation
+){
+ delete (m_parent_relation);
+ m_parent_relation = relation;
+}
+
+
+/**
+ * Update Spatial Data.
+ * Calculates WorldTransform., (either doing itsself or using the linked SGControllers)
+ */
+
+
+ void
+SG_Spatial::
+UpdateSpatialData(
+ const SG_Spatial *parent,
+ double time
+){
+
+ bool bComputesWorldTransform = false;
+
+ // update spatial controllers
+
+ SGControllerList::iterator cit = GetSGControllerList().begin();
+ SGControllerList::const_iterator c_end = GetSGControllerList().end();
+
+ for (;cit!=c_end;++cit)
+ {
+ bComputesWorldTransform = bComputesWorldTransform || (*cit)->Update(time);
+ }
+
+ // If none of the objects updated our values then we ask the
+ // parent_relation object owned by this class to update
+ // our world coordinates.
+
+ if (!bComputesWorldTransform)
+ {
+ ComputeWorldTransforms(parent);
+ }
+}
+
+void SG_Spatial::ComputeWorldTransforms(const SG_Spatial *parent)
+{
+ m_parent_relation->UpdateChildCoordinates(this,parent);
+}
+
+
+/**
+ * Position and translation methods
+ */
+
+
+ void
+SG_Spatial::
+RelativeTranslate(
+ const MT_Vector3& trans,
+ const SG_Spatial *parent,
+ bool local
+){
+ if (local) {
+ m_localPosition += m_localRotation * trans;
+ } else {
+ if (parent) {
+ m_localPosition += trans * parent->GetWorldOrientation();
+ } else {
+ m_localPosition += trans;
+ }
+ }
+}
+
+ void
+SG_Spatial::
+SetLocalPosition(
+ const MT_Point3& trans
+){
+ m_localPosition = trans;
+}
+
+ void
+SG_Spatial::
+SetWorldPosition(
+ const MT_Point3& trans
+) {
+ m_worldPosition = trans;
+}
+
+/**
+ * Scaling methods.
+ */
+
+ void
+SG_Spatial::
+RelativeScale(
+ const MT_Vector3& scale
+){
+ m_localScaling = m_localScaling * scale;
+}
+
+ void
+SG_Spatial::
+SetLocalScale(
+ const MT_Vector3& scale
+){
+ m_localScaling = scale;
+}
+
+
+ void
+SG_Spatial::
+SetWorldScale(
+ const MT_Vector3& scale
+){
+ m_worldScaling = scale;
+}
+
+/**
+ * Orientation and rotation methods.
+ */
+
+
+ void
+SG_Spatial::
+RelativeRotate(
+ const MT_Matrix3x3& rot,
+ bool local
+){
+ m_localRotation = m_localRotation * (
+ local ?
+ rot
+ :
+ (GetWorldOrientation().inverse() * rot * GetWorldOrientation()));
+}
+
+ void
+SG_Spatial::
+SetLocalOrientation(const MT_Matrix3x3& rot)
+{
+ m_localRotation = rot;
+}
+
+
+
+ void
+SG_Spatial::
+SetWorldOrientation(
+ const MT_Matrix3x3& rot
+) {
+ m_worldRotation = rot;
+}
+
+const
+ MT_Point3&
+SG_Spatial::
+GetLocalPosition(
+) const {
+ return m_localPosition;
+}
+
+const
+ MT_Matrix3x3&
+SG_Spatial::
+GetLocalOrientation(
+) const {
+ return m_localRotation;
+}
+
+const
+ MT_Vector3&
+SG_Spatial::
+GetLocalScale(
+) const{
+ return m_localScaling;
+}
+
+
+const
+ MT_Point3&
+SG_Spatial::
+GetWorldPosition(
+) const {
+ return m_worldPosition;
+}
+
+const
+ MT_Matrix3x3&
+SG_Spatial::
+GetWorldOrientation(
+) const {
+ return m_worldRotation;
+}
+
+const
+ MT_Vector3&
+SG_Spatial::
+GetWorldScaling(
+) const {
+ return m_worldScaling;
+}
+
diff --git a/source/gameengine/SceneGraph/SG_Spatial.h b/source/gameengine/SceneGraph/SG_Spatial.h
new file mode 100644
index 00000000000..ff54c4055be
--- /dev/null
+++ b/source/gameengine/SceneGraph/SG_Spatial.h
@@ -0,0 +1,205 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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 __SG_SPATIAL_H
+#define __SG_SPATIAL_H
+
+#include <MT_Vector3.h>
+#include <MT_Point3.h>
+#include <MT_Matrix3x3.h> // or Quaternion later ?
+
+#include "SG_IObject.h"
+
+class SG_Node;
+class SG_ParentRelation;
+
+class SG_Spatial : public SG_IObject
+{
+
+protected:
+ MT_Point3 m_localPosition;
+ MT_Matrix3x3 m_localRotation;
+ MT_Vector3 m_localScaling;
+
+ MT_Point3 m_worldPosition;
+ MT_Matrix3x3 m_worldRotation;
+ MT_Vector3 m_worldScaling;
+
+ SG_ParentRelation * m_parent_relation;
+
+public:
+
+ /**
+ * Define the realtionship this node has with it's parent
+ * node. You should pass an unshared instance of an SG_ParentRelation
+ * allocated on the heap to this method. Ownership of this
+ * instance is assumed by this class.
+ * You may call this function several times in the lifetime
+ * of a node to change the relationship dynamically.
+ * You must call this method before the first call to UpdateSpatialData().
+ * An assertion willl be fired at run-time in debug if this is not
+ * the case.
+ * The relation is activated only if no controllers of this object
+ * updated the coordinates of the child.
+ */
+
+ void
+ SetParentRelation(
+ SG_ParentRelation *relation
+ );
+
+
+ /**
+ * Apply a translation relative to the current position.
+ * if local then the translation is assumed to be in the
+ * local coordinates of this object. If not then the translation
+ * is assumed to be in global coordinates. In this case
+ * you must provide a pointer to the parent of this object if it
+ * exists otherwise if there is no parent set it to NULL
+ */
+
+ void
+ RelativeTranslate(
+ const MT_Vector3& trans,
+ const SG_Spatial *parent,
+ bool local
+ );
+
+ void
+ SetLocalPosition(
+ const MT_Point3& trans
+ );
+
+ void
+ SetWorldPosition(
+ const MT_Point3& trans
+ );
+
+ void
+ RelativeRotate(
+ const MT_Matrix3x3& rot,
+ bool local
+ );
+
+ void
+ SetLocalOrientation(
+ const MT_Matrix3x3& rot
+ );
+
+ void
+ SetWorldOrientation(
+ const MT_Matrix3x3& rot
+ );
+
+ void
+ RelativeScale(
+ const MT_Vector3& scale
+ );
+
+ void
+ SetLocalScale(
+ const MT_Vector3& scale
+ );
+
+ void
+ SetWorldScale(
+ const MT_Vector3& scale
+ );
+
+ const
+ MT_Point3&
+ GetLocalPosition(
+ ) const ;
+
+ const
+ MT_Matrix3x3&
+ GetLocalOrientation(
+ ) const ;
+
+ const
+ MT_Vector3&
+ GetLocalScale(
+ ) const;
+
+ const
+ MT_Point3&
+ GetWorldPosition(
+ ) const ;
+
+ const
+ MT_Matrix3x3&
+ GetWorldOrientation(
+ ) const ;
+
+ const
+ MT_Vector3&
+ GetWorldScaling(
+ ) const ;
+
+
+ void ComputeWorldTransforms( const SG_Spatial *parent);
+
+
+protected:
+ friend SG_Controller;
+
+ /**
+ * Protected constructor this class is not
+ * designed for direct instantiation
+ */
+
+ SG_Spatial(
+ void* clientobj,
+ void* clientinfo,
+ SG_Callbacks callbacks
+ );
+
+ SG_Spatial(
+ const SG_Spatial& other
+ );
+
+
+ virtual ~SG_Spatial();
+
+ /**
+ * Update the world coordinates of this spatial node. This also informs
+ * any controllers to update this object.
+ */
+
+ void
+ UpdateSpatialData(
+ const SG_Spatial *parent,
+ double time
+ );
+
+};
+#endif //__SG_SPATIAL_H
diff --git a/source/icons/Makefile b/source/icons/Makefile
new file mode 100644
index 00000000000..684c2eefb28
--- /dev/null
+++ b/source/icons/Makefile
@@ -0,0 +1,39 @@
+#
+# $Id$
+#
+# ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version. The Blender
+# Foundation also sells licenses for use in proprietary software under
+# the Blender License. See http://www.blender.org/BL/ for information
+# about this.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL/BL DUAL LICENSE BLOCK *****
+#
+#
+
+DIR = $(OCGDIR)/blender/icons
+
+include nan_compile.mk
+
+clean::
+ @$(RM) $(DIR)/*.res $(DIR)/debug/*.res
diff --git a/source/icons/winblender.ico b/source/icons/winblender.ico
new file mode 100644
index 00000000000..45b9ded0aad
--- /dev/null
+++ b/source/icons/winblender.ico
Binary files differ
diff --git a/source/icons/winblender.rc b/source/icons/winblender.rc
new file mode 100644
index 00000000000..77e62111d2d
--- /dev/null
+++ b/source/icons/winblender.rc
@@ -0,0 +1,2 @@
+APPICON ICON "winblender.ico"
+BLENDERFILE ICON "winblenderfile.ico"
diff --git a/source/icons/winblenderfile.ico b/source/icons/winblenderfile.ico
new file mode 100644
index 00000000000..4fc34d53877
--- /dev/null
+++ b/source/icons/winblenderfile.ico
Binary files differ
diff --git a/source/icons/wincreator.ico b/source/icons/wincreator.ico
new file mode 100644
index 00000000000..4fb7be08788
--- /dev/null
+++ b/source/icons/wincreator.ico
Binary files differ
diff --git a/source/icons/wincreator.rc b/source/icons/wincreator.rc
new file mode 100644
index 00000000000..e11bdaf15e3
--- /dev/null
+++ b/source/icons/wincreator.rc
@@ -0,0 +1,2 @@
+APPICON ICON "wincreator.ico"
+BLENDERFILE ICON "winblenderfile.ico"
diff --git a/source/icons/winlockedfile.ico b/source/icons/winlockedfile.ico
new file mode 100644
index 00000000000..8b23d5c3d4d
--- /dev/null
+++ b/source/icons/winlockedfile.ico
Binary files differ
diff --git a/source/icons/winplayer.ico b/source/icons/winplayer.ico
new file mode 100644
index 00000000000..336ff09f94f
--- /dev/null
+++ b/source/icons/winplayer.ico
Binary files differ
diff --git a/source/icons/winplayer.rc b/source/icons/winplayer.rc
new file mode 100644
index 00000000000..e2b255e7280
--- /dev/null
+++ b/source/icons/winplayer.rc
@@ -0,0 +1 @@
+APPICON ICON "winplayer.ico"
diff --git a/source/icons/winpublisher.ico b/source/icons/winpublisher.ico
new file mode 100644
index 00000000000..9a6f4690681
--- /dev/null
+++ b/source/icons/winpublisher.ico
Binary files differ
diff --git a/source/icons/winpublisher.rc b/source/icons/winpublisher.rc
new file mode 100644
index 00000000000..b296c0ffc8f
--- /dev/null
+++ b/source/icons/winpublisher.rc
@@ -0,0 +1,3 @@
+APPICON ICON "winpublisher.ico"
+BLENDERFILE ICON "winblenderfile.ico"
+LOCKEDFILE ICON "winlockedfile.ico"
diff --git a/source/kernel/Makefile b/source/kernel/Makefile
new file mode 100644
index 00000000000..51d31f2f6ac
--- /dev/null
+++ b/source/kernel/Makefile
@@ -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 *****
+#
+# Make module object directory and bounce make to subdirectories.
+
+include nan_definitions.mk
+
+DIR = $(OCGDIR)/kernel
+SOURCEDIR = source/kernel
+DIRS = gen_system gen_messaging
+
+include nan_subdirs.mk
diff --git a/source/kernel/gen_messaging/GEN_messaging.h b/source/kernel/gen_messaging/GEN_messaging.h
new file mode 100644
index 00000000000..c415749a6e3
--- /dev/null
+++ b/source/kernel/gen_messaging/GEN_messaging.h
@@ -0,0 +1,62 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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_MESSAGING_H
+#define GEN_MESSAGING_H
+
+#include <stdio.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ /**
+ * Stream for error messages.
+ */
+ extern FILE* GEN_errorstream;
+
+ /**
+ * Stream for notices to the user.
+ */
+ extern FILE* GEN_userstream;
+
+ /**
+ * Initialise the messaging system. If the system is not
+ * initialised, the streams cannot be used. */
+ void GEN_init_messaging_system(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* GEN_MESSAGING_H */
diff --git a/source/kernel/gen_messaging/Makefile b/source/kernel/gen_messaging/Makefile
new file mode 100644
index 00000000000..d8420531e05
--- /dev/null
+++ b/source/kernel/gen_messaging/Makefile
@@ -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 *****
+#
+# Bounces make to subdirectories.
+
+SOURCEDIR = source/kernel/gen_messaging
+DIRS = intern
+
+include nan_subdirs.mk
diff --git a/source/kernel/gen_messaging/intern/Makefile b/source/kernel/gen_messaging/intern/Makefile
new file mode 100644
index 00000000000..cd6afa19a3f
--- /dev/null
+++ b/source/kernel/gen_messaging/intern/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 = gen_messaging
+DIR = $(OCGDIR)/kernel/$(LIBNAME)
+
+include nan_compile.mk
+
+ifeq ($(OS),$(findstring $(OS), "beos darwin freebsd linux openbsd solaris windows"))
+ CFLAGS += -funsigned-char
+endif
+
+CFLAGS += $(LEVEL_1_C_WARNINGS)
+
+# path to our own external headerfiles
+CPPFLAGS += -I..
+
diff --git a/source/kernel/gen_messaging/intern/messaging.c b/source/kernel/gen_messaging/intern/messaging.c
new file mode 100644
index 00000000000..628c717a879
--- /dev/null
+++ b/source/kernel/gen_messaging/intern/messaging.c
@@ -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 *****
+ * A message and error sink for c and c++
+ */
+
+
+#include "GEN_messaging.h"
+
+
+FILE* GEN_errorstream = NULL;
+FILE* GEN_userstream = NULL;
+
+void GEN_init_messaging_system(void)
+{
+ GEN_errorstream = stderr;
+ GEN_userstream = stdout;
+}
diff --git a/source/kernel/gen_system/GEN_DataCache.h b/source/kernel/gen_system/GEN_DataCache.h
new file mode 100644
index 00000000000..fb3a9ea4a72
--- /dev/null
+++ b/source/kernel/gen_system/GEN_DataCache.h
@@ -0,0 +1,78 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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_DATACACHE_H
+#define __GEN_DATACACHE_H
+
+#include "STR_HashedString.h"
+#include "GEN_Map.h"
+
+template <class T>
+class GEN_DataCache
+{
+ GEN_Map<STR_HashedString,T*> m_dataCache;
+ virtual T* LoadData(const STR_String& name)=0;
+ virtual void FreeCacheObjects()=0;
+
+public:
+ GEN_DataCache() {};
+ virtual ~GEN_DataCache() {};
+
+ T* GetData(const STR_String& paramname)
+ {
+ T* result=NULL;
+
+ T** resultptr = m_dataCache[paramname];
+ if (resultptr)
+ {
+ result = *resultptr;
+ }
+
+ else
+ {
+ result = LoadData(paramname);
+ if (result)
+ {
+ m_dataCache.insert(paramname,result);
+ }
+ }
+
+ return result;
+ }
+
+ virtual void ClearCache()
+ {
+ FreeCacheObjects();
+ m_dataCache.clear();
+ }
+};
+
+#endif //__GEN_DATACACHE_H
diff --git a/source/kernel/gen_system/GEN_HashedPtr.cpp b/source/kernel/gen_system/GEN_HashedPtr.cpp
new file mode 100644
index 00000000000..6163b4a7c64
--- /dev/null
+++ b/source/kernel/gen_system/GEN_HashedPtr.cpp
@@ -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 *****
+ *
+ */
+#include "GEN_HashedPtr.h"
+
+unsigned int GEN_Hash(unsigned int inDWord)
+{
+ unsigned int key = inDWord;
+
+ key += ~(key << 16);
+ key ^= (key >> 5);
+ key += (key << 3);
+ key ^= (key >> 13);
+ key += ~(key << 9);
+ key ^= (key >> 17);
+
+ return key;
+}
diff --git a/source/kernel/gen_system/GEN_HashedPtr.h b/source/kernel/gen_system/GEN_HashedPtr.h
new file mode 100644
index 00000000000..3f4a8370dbe
--- /dev/null
+++ b/source/kernel/gen_system/GEN_HashedPtr.h
@@ -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 *****
+ *
+ */
+#ifndef __GEN_HASHEDPTR
+#define __GEN_HASHEDPTR
+
+unsigned int GEN_Hash(unsigned int inDWord);
+
+class GEN_HashedPtr
+{
+ void* m_valptr;
+public:
+ GEN_HashedPtr(void* val) : m_valptr(val) {};
+ unsigned int hash() const { return GEN_Hash((unsigned int) m_valptr);};
+ inline friend bool operator ==(const GEN_HashedPtr & rhs, const GEN_HashedPtr & lhs) { return rhs.m_valptr == lhs.m_valptr;};
+};
+
+#endif //__GEN_HASHEDPTR
diff --git a/source/kernel/gen_system/GEN_Map.h b/source/kernel/gen_system/GEN_Map.h
new file mode 100644
index 00000000000..bd211a6b043
--- /dev/null
+++ b/source/kernel/gen_system/GEN_Map.h
@@ -0,0 +1,151 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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/source/kernel/gen_system/GEN_Matrix4x4.cpp b/source/kernel/gen_system/GEN_Matrix4x4.cpp
new file mode 100644
index 00000000000..ad250ea9ffc
--- /dev/null
+++ b/source/kernel/gen_system/GEN_Matrix4x4.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 *****
+ */
+
+#include "GEN_Matrix4x4.h"
+
+
+
+GEN_Matrix4x4::GEN_Matrix4x4()
+{
+ Identity();
+}
+
+
+
+GEN_Matrix4x4::GEN_Matrix4x4(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];
+ }
+}
+
+
+
+GEN_Matrix4x4::GEN_Matrix4x4(const double value[16])
+{
+ for (int i=0;i<16;i++)
+ m_Vflat[i] = value[i];
+}
+
+
+
+GEN_Matrix4x4::GEN_Matrix4x4(const GEN_Matrix4x4& other)
+{
+ SetMatrix(other);
+}
+
+
+
+GEN_Matrix4x4::GEN_Matrix4x4(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 GEN_Matrix4x4::GetRight() const
+{
+ return MT_Vector3(m_V[0][0], m_V[0][1], m_V[0][2]);
+}
+
+
+
+MT_Vector3 GEN_Matrix4x4::GetUp() const
+{
+ return MT_Vector3(m_V[1][0], m_V[1][1], m_V[1][2]);
+}
+
+
+
+MT_Vector3 GEN_Matrix4x4::GetDir() const
+{
+ return MT_Vector3(m_V[2][0], m_V[2][1], m_V[2][2]);
+}
+
+
+
+MT_Point3 GEN_Matrix4x4::GetPos() const
+{
+ return MT_Point3(m_V[3][0], m_V[3][1], m_V[3][2]);
+}
+
+
+
+void GEN_Matrix4x4::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 GEN_Matrix4x4::SetMatrix(const GEN_Matrix4x4& other)
+{
+ for (int i=0; i<16; i++)
+ m_Vflat[i] = other.m_Vflat[i];
+}
+
+
+
+double* GEN_Matrix4x4::getPointer()
+{
+ return &m_V[0][0];
+}
+
+
+
+const double* GEN_Matrix4x4::getPointer() const
+{
+ return &m_V[0][0];
+}
+
+
+
+void GEN_Matrix4x4::setElem(int pos,double newvalue)
+{
+ m_Vflat[pos] = newvalue;
+}
+
+
+
+
+
+GEN_Matrix4x4 GEN_Matrix4x4::Perspective(MT_Scalar inLeft,
+MT_Scalar inRight,
+MT_Scalar inBottom,
+MT_Scalar inTop,
+MT_Scalar inNear,
+MT_Scalar inFar)
+{
+
+ GEN_Matrix4x4 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/source/kernel/gen_system/GEN_Matrix4x4.h b/source/kernel/gen_system/GEN_Matrix4x4.h
new file mode 100644
index 00000000000..23a31ecbde1
--- /dev/null
+++ b/source/kernel/gen_system/GEN_Matrix4x4.h
@@ -0,0 +1,78 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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_MATRIX4X4
+#define GEN_MATRIX4X4
+
+#include "MT_Point3.h"
+
+class GEN_Matrix4x4
+{
+public:
+ // creators.
+ GEN_Matrix4x4();
+ GEN_Matrix4x4(const float value[4][4]);
+ GEN_Matrix4x4(const double value[16]);
+ GEN_Matrix4x4(const GEN_Matrix4x4 & other);
+ GEN_Matrix4x4(const MT_Point3& orig,
+ const MT_Vector3& dir,
+ const MT_Vector3 up);
+
+ void Identity();
+ void SetMatrix(const GEN_Matrix4x4 & 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 GEN_Matrix4x4 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 //GEN_MATRIX4X4
diff --git a/source/kernel/gen_system/GEN_SmartPtr.h b/source/kernel/gen_system/GEN_SmartPtr.h
new file mode 100644
index 00000000000..535d066be57
--- /dev/null
+++ b/source/kernel/gen_system/GEN_SmartPtr.h
@@ -0,0 +1,235 @@
+#ifndef NAN_INCLUDED_GEN_SmartPtr_h
+#define NAN_INCLUDED_GEN_SmartPtr_h
+
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by 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
+ */
+
+#include <stdlib.h> // for NULL !
+
+/**
+ * @section GEN_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(
+ * ) {
+ * GEN_SmartPtr<foo> afoo = new foo();
+ * GEN_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 :
+ * GEN_SmartPtr<foo> m_foo;
+ * }
+ *
+ * You my also safely construct vectors of GEN_SmartPtrs and
+ * have the vector own stuff you put into it.
+ *
+ * e.g.
+ * {
+ * std::vector<GEN_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 GEN_SmartPtr {
+
+public :
+
+ /**
+ * Construction from reference - this class
+ * always assumes ownership from the rhs.
+ */
+
+ GEN_SmartPtr(
+ const GEN_SmartPtr &rhs
+ ){
+ m_val = rhs.Release();
+ }
+
+ /**
+ * Construction from ptr - this class always
+ * assumes that it now owns the memory associated with the
+ * ptr.
+ */
+
+ GEN_SmartPtr(
+ T* val
+ ) :
+ m_val (val)
+ {
+ }
+
+ /**
+ * Defalut constructor
+ */
+
+ GEN_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.
+ */
+
+ GEN_SmartPtr & operator=(
+ const GEN_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<GEN_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
+ */
+
+ ~GEN_SmartPtr(
+ ) {
+ delete (m_val);
+ }
+
+private :
+
+ /// The ptr owned by this class.
+ T * m_val;
+};
+
+#endif
diff --git a/source/kernel/gen_system/Makefile b/source/kernel/gen_system/Makefile
new file mode 100644
index 00000000000..cdaf8e8e598
--- /dev/null
+++ b/source/kernel/gen_system/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 *****
+#
+#
+
+LIBNAME = gen_system
+DIR = $(OCGDIR)/kernel/$(LIBNAME)
+
+include nan_compile.mk
+
+CCFLAGS += $(LEVEL_2_CPP_WARNINGS)
+
+CPPFLAGS += -I$(NAN_MOTO)/include
+CPPFLAGS += -I$(NAN_STRING)/include
+
diff --git a/source/kernel/gen_system/SYS_SingletonSystem.cpp b/source/kernel/gen_system/SYS_SingletonSystem.cpp
new file mode 100644
index 00000000000..5692c5348de
--- /dev/null
+++ b/source/kernel/gen_system/SYS_SingletonSystem.cpp
@@ -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 *****
+ * Unique instance of system class for system specific information / access
+ * Used by SYS_System
+ */
+#include "SYS_SingletonSystem.h"
+#include "GEN_DataCache.h"
+
+SYS_SingletonSystem* SYS_SingletonSystem::_instance = 0;
+
+void SYS_SingletonSystem::Destruct()
+{
+ if (_instance) {
+ delete _instance;
+ _instance = NULL;
+ }
+}
+
+SYS_SingletonSystem *SYS_SingletonSystem::Instance()
+{
+ if (!_instance) {
+ _instance = new SYS_SingletonSystem();
+ }
+ return _instance;
+}
+
+int SYS_SingletonSystem::SYS_GetCommandLineInt(const char *paramname, int defaultvalue)
+{
+ int *result = m_int_commandlineparms[paramname];
+ if (result)
+ return *result;
+
+ return defaultvalue;
+}
+
+float SYS_SingletonSystem::SYS_GetCommandLineFloat(const char *paramname, float defaultvalue)
+{
+ float *result = m_float_commandlineparms[paramname];
+ if (result)
+ return *result;
+
+ return defaultvalue;
+}
+
+const char *SYS_SingletonSystem::SYS_GetCommandLineString(const char *paramname, const char *defaultvalue)
+{
+ STR_String *result = m_string_commandlineparms[paramname];
+ if (result)
+ return *result;
+
+ return defaultvalue;
+}
+
+void SYS_SingletonSystem::SYS_WriteCommandLineInt(const char *paramname, int value)
+{
+ m_int_commandlineparms.insert(paramname, value);
+}
+
+void SYS_SingletonSystem::SYS_WriteCommandLineFloat(const char *paramname, float value)
+{
+ m_float_commandlineparms.insert(paramname, value);
+}
+
+void SYS_SingletonSystem::SYS_WriteCommandLineString(const char *paramname, const char *value)
+{
+ m_string_commandlineparms.insert(paramname, value);
+}
+
+SYS_SingletonSystem::SYS_SingletonSystem() : m_soundfilecache(NULL)
+{
+}
diff --git a/source/kernel/gen_system/SYS_SingletonSystem.h b/source/kernel/gen_system/SYS_SingletonSystem.h
new file mode 100644
index 00000000000..c01cb356910
--- /dev/null
+++ b/source/kernel/gen_system/SYS_SingletonSystem.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 *****
+ * Unique instance of system class for system specific information / access
+ * Used by SYS_System
+ */
+#ifndef __SINGLETONSYSTEM_H
+#define __SINGLETONSYSTEM_H
+
+#include "GEN_Map.h"
+#include "STR_HashedString.h"
+#include "GEN_DataCache.h"
+
+class SYS_SingletonSystem
+{
+public:
+ static SYS_SingletonSystem* Instance();
+ static void Destruct();
+
+ int SYS_GetCommandLineInt(const char* paramname,int defaultvalue);
+ float SYS_GetCommandLineFloat(const char* paramname,float defaultvalue);
+ const char* SYS_GetCommandLineString(const char* paramname,const char* defaultvalue);
+
+ void SYS_WriteCommandLineInt(const char* paramname,int value);
+ void SYS_WriteCommandLineFloat(const char* paramname,float value);
+ void SYS_WriteCommandLineString(const char* paramname,const char* value);
+
+ SYS_SingletonSystem();
+
+private:
+ static SYS_SingletonSystem* _instance;
+ GEN_Map<STR_HashedString,int> m_int_commandlineparms;
+ GEN_Map<STR_HashedString,float> m_float_commandlineparms;
+ GEN_Map<STR_HashedString,STR_String> m_string_commandlineparms;
+ void* m_soundfilecache;
+};
+
+#endif //__SINGLETONSYSTEM_H
diff --git a/source/kernel/gen_system/SYS_System.cpp b/source/kernel/gen_system/SYS_System.cpp
new file mode 100644
index 00000000000..48f5b2632fd
--- /dev/null
+++ b/source/kernel/gen_system/SYS_System.cpp
@@ -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 *****
+ * System specific information / access.
+ * Interface to the commandline arguments
+ */
+#include "SYS_System.h"
+#include "SYS_SingletonSystem.h"
+
+SYS_SystemHandle SYS_GetSystem()
+{
+ return (SYS_SystemHandle) SYS_SingletonSystem::Instance();
+}
+
+void SYS_DeleteSystem(SYS_SystemHandle sys)
+{
+ if (sys) {
+ ((SYS_SingletonSystem *) sys)->Destruct();
+ }
+}
+
+int SYS_GetCommandLineInt(SYS_SystemHandle sys, const char *paramname, int defaultvalue)
+{
+ return ((SYS_SingletonSystem *) sys)->SYS_GetCommandLineInt(paramname, defaultvalue);
+}
+
+float SYS_GetCommandLineFloat(SYS_SystemHandle sys, const char *paramname, float defaultvalue)
+{
+ return ((SYS_SingletonSystem *) sys)->SYS_GetCommandLineFloat(paramname, defaultvalue);
+}
+
+const char *SYS_GetCommandLineString(SYS_SystemHandle sys, const char *paramname, const char *defaultvalue)
+{
+ return ((SYS_SingletonSystem *) sys)->SYS_GetCommandLineString(paramname, defaultvalue);
+}
+
+void SYS_WriteCommandLineInt(SYS_SystemHandle sys, const char *paramname, int value)
+{
+ ((SYS_SingletonSystem *) sys)->SYS_WriteCommandLineInt(paramname, value);
+}
+
+void SYS_WriteCommandLineFloat(SYS_SystemHandle sys, const char *paramname, float value)
+{
+ ((SYS_SingletonSystem *) sys)->SYS_WriteCommandLineFloat(paramname, value);
+}
+
+void SYS_WriteCommandLineString(SYS_SystemHandle sys, const char *paramname, const char *value)
+{
+ ((SYS_SingletonSystem *) sys)->SYS_WriteCommandLineString(paramname, value);
+}
diff --git a/source/kernel/gen_system/SYS_System.h b/source/kernel/gen_system/SYS_System.h
new file mode 100644
index 00000000000..2dbd7229612
--- /dev/null
+++ b/source/kernel/gen_system/SYS_System.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 *****
+ * System specific information / access.
+ * Interface to the commandline arguments
+ */
+
+#ifndef __SYSTEM_INCLUDE
+#define __SYSTEM_INCLUDE
+
+#define SYS_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name
+
+SYS_DECLARE_HANDLE(SYS_SystemHandle);
+
+/**
+ System specific information / access.
+ For now, only used for commandline parameters.
+ One of the available implementations must be linked to the application
+ that uses this system routines.
+ Please note that this protocol/interface is just for testing,
+ it needs discussion in the development group for a more final version.
+*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern SYS_SystemHandle SYS_GetSystem(void);
+extern void SYS_DeleteSystem(SYS_SystemHandle sys);
+
+extern int SYS_GetCommandLineInt(SYS_SystemHandle sys, const char *paramname, int defaultvalue);
+extern float SYS_GetCommandLineFloat(SYS_SystemHandle sys, const char *paramname, float defaultvalue);
+extern const char *SYS_GetCommandLineString(SYS_SystemHandle sys, const char *paramname, const char *defaultvalue);
+
+extern void SYS_WriteCommandLineInt(SYS_SystemHandle sys, const char *paramname, int value);
+extern void SYS_WriteCommandLineFloat(SYS_SystemHandle sys, const char *paramname, float value);
+extern void SYS_WriteCommandLineString(SYS_SystemHandle sys, const char *paramname, const char *value);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //__SYSTEM_INCLUDE
diff --git a/source/nan_compile.mk b/source/nan_compile.mk
new file mode 100644
index 00000000000..56f308c63ff
--- /dev/null
+++ b/source/nan_compile.mk
@@ -0,0 +1,337 @@
+#
+# $Id$
+#
+# ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version. The Blender
+# Foundation also sells licenses for use in proprietary software under
+# the Blender License. See http://www.blender.org/BL/ for information
+# about this.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL/BL DUAL LICENSE BLOCK *****
+#
+# Compile and archive
+
+include nan_definitions.mk
+
+CPPFLAGS ?= $(NAN_CPPFLAGS)
+
+# common parts ---------------------------------------------------
+
+ifdef NAN_DEBUG
+ CFLAGS += $(NAN_DEBUG)
+ CCFLAGS += $(NAN_DEBUG)
+endif
+
+REL_CFLAGS += -DNDEBUG
+REL_CCFLAGS += -DNDEBUG
+DBG_CFLAGS += -g
+DBG_CCFLAGS += -g
+
+# OS dependent parts ---------------------------------------------------
+
+ifeq ($(OS),beos)
+ CC = gcc
+ CCC = g++
+ CFLAGS += -pipe -fPIC
+ CFLAGS += -pipe -fPIC
+ REL_CFLAGS += -O2
+ REL_CCFLAGS += -O2
+ NAN_DEPEND = true
+ OPENGL_HEADERS = .
+ CPPFLAGS += -D__BeOS
+ AR = ar
+ ARFLAGS = ruv
+ ARFLAGSQUIET = ru
+endif
+
+ifeq ($(OS),darwin)
+ CC = gcc
+ CCC = g++
+ CFLAGS += -pipe -fPIC
+ CCFLAGS += -pipe -fPIC
+ REL_CFLAGS += -O
+ REL_CCFLAGS += -O
+ CPPFLAGS += -D_THREAD_SAFE
+ NAN_DEPEND = true
+ OPENGL_HEADERS = /System/Library/Frameworks/OpenGL.framework
+ AR = ar
+ ARFLAGS = ruv
+ RANLIB = ranlib
+ ARFLAGSQUIET = ru
+endif
+
+ifeq ($(OS),freebsd)
+ CC = gcc
+ CCC = g++
+ JAVAC = javac
+ JAVAH = javah
+ CFLAGS += -pipe -fPIC
+ CCFLAGS += -pipe -fPIC
+ REL_CFLAGS += -O2
+ REL_CCFLAGS += -O2
+ CPPFLAGS += -D_THREAD_SAFE
+ NAN_DEPEND = true
+ OPENGL_HEADERS = /usr/X11R6/include
+ JAVA_HEADERS = /usr/local/jdk1.3.1/include
+ JAVA_SYSTEM_HEADERS = /usr/local/jdk1.3.1/include/freebsd
+ AR = ar
+ ARFLAGS = ruv
+ ARFLAGSQUIET = ru
+endif
+
+ifeq ($(OS),irix)
+ CC = cc
+ CCC = CC
+ CFLAGS += -n32 -mips3 -Xcpluscomm
+ CCFLAGS += -n32 -mips3 -Xcpluscomm -LANG:std
+ REL_CFLAGS += -O2 -OPT:Olimit=0
+ REL_CCFLAGS += -O2 -OPT:Olimit=0
+ OPENGL_HEADERS = /usr/include
+ NAN_DEPEND = true
+ AR = CC
+ ARFLAGS = -ar -o
+ ARFLAGSQUIET = -ar -o
+endif
+
+ifeq ($(OS),linux)
+ CC = gcc
+ CCC = g++
+# CFLAGS += -pipe
+ CFLAGS += -pipe -fPIC
+ CCFLAGS += -pipe -fPIC
+# CCFLAGS += -pipe
+ REL_CFLAGS += -O3
+ REL_CCFLAGS += -O3
+ NAN_DEPEND = true
+ ifeq ($(CPU),alpha)
+ CFLAGS += -mieee
+ endif
+ OPENGL_HEADERS = /usr/X11R6/include
+ AR = ar
+ ARFLAGS = ruv
+ ARFLAGSQUIET = ru
+endif
+
+ifeq ($(OS),openbsd)
+ CC = gcc
+ CCC = g++
+ CFLAGS += -pipe -fPIC
+ CCFLAGS += -pipe -fPIC
+ REL_CFLAGS += -O2
+ REL_CCFLAGS += -O2
+ NAN_DEPEND = true
+ CPPFLAGS += -D__FreeBSD__
+ OPENGL_HEADERS = /usr/X11R6/include
+ AR = ar
+ ARFLAGS = ruv
+ ARFLAGSQUIET = ru
+endif
+
+ifeq ($(OS),solaris)
+ CC = gcc
+ CCC = g++
+ JAVAC = javac
+ JAVAH = javah
+ CFLAGS += -pipe -fPIC
+ CCFLAGS += -pipe -fPIC
+ REL_CFLAGS += -O2
+ REL_CCFLAGS += -O2
+ NAN_DEPEND = true
+ ifeq ($(CPU),sparc)
+ OPENGL_HEADERS = /usr/openwin/share/include
+ CPPFLAGS += -DSUN_OGL_NO_VERTEX_MACROS
+ JAVA_HEADERS = /usr/java/include
+ JAVA_SYSTEM_HEADERS = /usr/java/include/solaris
+ else
+ OPENGL_HEADERS = /usr/local/include
+ endif
+ AR = ar
+ ARFLAGS = ruv
+ ARFLAGSQUIET = ru
+endif
+
+ifeq ($(OS),windows)
+ CC = $(SRCHOME)/tools/cygwin/cl_wrapper.pl
+ CCC = $(SRCHOME)/tools/cygwin/cl_wrapper.pl
+ JAVAC = $(SRCHOME)/tools/cygwin/java_wrapper.pl -c
+ JAVAH = $(SRCHOME)/tools/cygwin/java_wrapper.pl -h
+ REL_CFLAGS += /O2
+ REL_CCFLAGS += /O2 -GX
+ DBG_CFLAGS += /Fd$(DIR)/debug/
+ DBG_CCFLAGS += /Fd$(DIR)/debug/
+ CFLAGS += /MT
+ CCFLAGS += /MT
+ NAN_DEPEND = true
+ OPENGL_HEADERS = .
+ CPPFLAGS += -DWIN32 -D_WIN32 -D__WIN32
+ CPPFLAGS += -D_M_IX86
+ CPPFLAGS += -I"/cygdrive/c/Program Files/Microsoft Visual Studio/VC98/include"
+ JAVA_HEADERS = /cygdrive/c/j2sdk1.4.0-beta3/include
+ JAVA_SYSTEM_HEADERS = /cygdrive/c/j2sdk1.4.0-beta3/include/win32
+ CPP = $(SRCHOME)/tools/cygwin/cl_wrapper.pl
+ AR = ar
+ ARFLAGS = ruv
+ ARFLAGSQUIET = ru
+ WINRC = $(wildcard *.rc)
+endif
+
+ifeq (debug, $(findstring debug, $(MAKECMDGOALS)))
+ export DEBUG_DIR=debug/
+endif
+
+ifneq (x$(DEBUG_DIR), x)
+ CFLAGS +=$(DBG_CFLAGS)
+ CCFLAGS+=$(DBG_CCFLAGS)
+else
+ CFLAGS +=$(REL_CFLAGS)
+ CCFLAGS+=$(REL_CCFLAGS)
+endif
+
+# Note: include nan_warn's LEVEL_*_WARNINGS after CC/OS have been set.
+include nan_warn.mk
+
+# compile rules
+
+default: all
+
+$(DIR)/$(DEBUG_DIR)%.o: %.c
+ ifdef NAN_DEPEND
+ @set -e; $(CC) -M $(CPPFLAGS) $< 2>/dev/null \
+ | sed 's@\($*\)\.o[ :]*@$(DIR)/$(DEBUG_DIR)\1.o : @g' \
+ > $(DIR)/$(DEBUG_DIR)$*.d; \
+ [ -s $(DIR)/$(DEBUG_DIR)$*.d ] || $(RM) $(DIR)/$(DEBUG_DIR)$*.d
+ endif
+ ifdef NAN_QUIET
+ @echo " -- $< -- "
+ @$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@
+ else
+ $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@
+ endif
+
+$(DIR)/$(DEBUG_DIR)%.o: %.cpp
+ ifdef NAN_DEPEND
+ @set -e; $(CCC) -M $(CPPFLAGS) $< 2>/dev/null \
+ | sed 's@\($*\)\.o[ :]*@$(DIR)/$(DEBUG_DIR)\1.o : @g' \
+ > $(DIR)/$(DEBUG_DIR)$*.d; \
+ [ -s $(DIR)/$(DEBUG_DIR)$*.d ] || $(RM) $(DIR)/$(DEBUG_DIR)$*.d
+ endif
+ ifdef NAN_QUIET
+ @echo " -- $< -- "
+ @$(CCC) -c $(CCFLAGS) $(CPPFLAGS) $< -o $@
+ else
+ $(CCC) -c $(CCFLAGS) $(CPPFLAGS) $< -o $@
+ endif
+
+$(DIR)/$(DEBUG_DIR)%.res: %.rc
+ $(SRCHOME)/tools/cygwin/cl_wrapper.pl - rc /fo$@ $<
+
+$(DIR)/$(DEBUG_DIR)%.class: %.java
+ ifdef JARS
+ $(JAVAC) -verbose -g -deprecation -sourcepath . -classpath "$(JARS)" -d $(DIR)/$(DEBUG_DIR) $<
+ else
+ $(JAVAC) -verbose -g -deprecation -d $(DIR)/$(DEBUG_DIR) $<
+ endif
+
+$(DIR)/$(DEBUG_DIR)%.h: $(DIR)/$(DEBUG_DIR)%.class
+ $(JAVAH) -classpath $(DIR)/$(DEBUG_DIR) -d $(DIR)/$(DEBUG_DIR) -jni $*
+
+%.h:
+ @echo "WARNING: Fake header creation rule used, dependencies will be remade"
+
+CSRCS ?= $(wildcard *.c)
+CCSRCS ?= $(wildcard *.cpp)
+JSRCS ?= $(wildcard *.java)
+
+ifdef NAN_DEPEND
+-include $(CSRCS:%.c=$(DIR)/$(DEBUG_DIR)%.d) $(CCSRCS:%.cpp=$(DIR)/$(DEBUG_DIR)%.d)
+endif
+
+OBJS += $(CSRCS:%.c=$(DIR)/$(DEBUG_DIR)%.o)
+OBJS += $(CCSRCS:%.cpp=$(DIR)/$(DEBUG_DIR)%.o)
+OBJS += $(WINRC:%.rc=$(DIR)/$(DEBUG_DIR)%.res)
+
+JCLASS += $(JSRCS:%.java=$(DIR)/$(DEBUG_DIR)%.class)
+
+LIB_a = $(DIR)/$(DEBUG_DIR)lib$(LIBNAME).a
+
+$(LIB_a): $(OBJS)
+ # $OBJS can be empty except for some spaces
+ ifneq (x, x$(strip $(OBJS)))
+ ifdef NAN_PARANOID
+ @$(RM) $(LIB_a)
+ ifdef NAN_QUIET
+ @echo " -- lib: lib$(LIBNAME).a -- "
+ @$(AR) $(ARFLAGSQUIET) $@ $(OBJS)
+ else
+ $(AR) $(ARFLAGS) $@ $(OBJS)
+ endif
+ else
+ ifdef NAN_QUIET
+ @echo " -- lib: lib$(LIBNAME).a -- "
+ @$(AR) $(ARFLAGSQUIET) $@ $?
+ else
+ $(AR) $(ARFLAGS) $@ $?
+ endif
+ endif
+ ifdef RANLIB
+ $(RANLIB) $@
+ endif
+ endif
+
+ALLTARGETS ?= $(LIB_a)
+
+all debug :: makedir $(ALLTARGETS)
+
+lib: $(LIB_a)
+
+creator: $(OBJS)
+ @echo "====> make creator subtarget in `pwd | sed 's/^.*develop\///'`"
+ @$(MAKE) makedir DIR=$(DIR)/$(DEBUG_DIR)cre
+ @$(MAKE) lib CSRCS="$(CRE_CSRCS)" LIBNAME=$(LIBNAME)$@
+
+publisher: $(OBJS)
+ @echo "====> make publisher subtarget in `pwd | sed 's/^.*develop\///'`"
+ @$(MAKE) makedir DIR=$(DIR)/$(DEBUG_DIR)pub
+ @$(MAKE) lib CSRCS="$(PUB_CSRCS)" LIBNAME=$(LIBNAME)$@
+
+player: $(OBJS)
+ @echo "====> make player subtarget in `pwd | sed 's/^.*develop\///'`"
+ @$(MAKE) makedir DIR=$(DIR)/player/$(DEBUG_DIR)
+ @$(MAKE) lib CSRCS="$(SAP_CSRCS)" LIBNAME=$(LIBNAME)$@
+
+clean:: optclean debugclean
+
+optclean::
+ @-[ ! -d $(DIR) ] || ( cd $(DIR) && \
+ $(RM) *.o *.a *.d *.res ii_files/*.ii *.class *.h )
+
+debugclean::
+ @-[ ! -d $(DIR)/debug ] || ( cd $(DIR)/debug && \
+ $(RM) *.o *.a *.d *.res ii_files/*.ii *.class *.h )
+
+.PHONY: makedir
+makedir::
+ @# don't use mkdir -p. Cygwin will try to make network paths and fail
+ @[ -d $(DIR) ] || mkdir $(DIR)
+ @[ -d $(DIR)/debug ] || mkdir $(DIR)/debug
+
diff --git a/source/nan_definitions.mk b/source/nan_definitions.mk
new file mode 100644
index 00000000000..1034d3253c7
--- /dev/null
+++ b/source/nan_definitions.mk
@@ -0,0 +1,131 @@
+#
+# $Id$
+#
+# ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version. The Blender
+# Foundation also sells licenses for use in proprietary software under
+# the Blender License. See http://www.blender.org/BL/ for information
+# about this.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL/BL DUAL LICENSE BLOCK *****
+#
+# set some defaults when these are not overruled (?=) by environment variables
+#
+
+ifndef CONFIG_GUESS
+ ifeq (debug, $(findstring debug, $(MAKECMDGOALS)))
+ ifeq (all, $(findstring all, $(MAKECMDGOALS)))
+all debug::
+ ERRTXT = "ERROR: all and debug targets cannot be used together anymore"
+ ERRTXT += "Use something like ..make all && make debug.. instead"
+ $(error $(ERRTXT))
+ endif
+ endif
+ export SRCHOME ?= $(HOME)/develop/source
+ export NAN_LIBDIR ?= $(HOME)/develop/lib
+ export NAN_OBJDIR ?= $(HOME)/obj
+ export NAN_PYTHON ?= $(LCGDIR)/python
+ export NAN_PYTHON_VERSION ?= 2.0
+ export NAN_OPENAL ?= $(LCGDIR)/openal
+ export NAN_FMOD ?= $(LCGDIR)/fmod
+ export NAN_JPEG ?= $(LCGDIR)/jpeg
+ export NAN_PNG ?= $(LCGDIR)/png
+ export NAN_SDL ?= $(LCGDIR)/sdl
+ export NAN_TERRAPLAY ?= $(LCGDIR)/terraplay
+ export NAN_MESA ?= /usr/src/Mesa-3.1
+ export NAN_MOTO ?= $(LCGDIR)/moto
+ export NAN_SOLID ?= $(SRCHOME)/sumo/SOLID-3.0
+ export NAN_SUMO ?= $(SRCHOME)/sumo
+ export NAN_FUZZICS ?= $(SRCHOME)/sumo/Fuzzics
+ export NAN_OPENSSL ?= $(LCGDIR)/openssl
+ export NAN_BLENKEY ?= $(LCGDIR)/blenkey
+ export NAN_DECIMATION ?= $(LCGDIR)/decimation
+ export NAN_GUARDEDALLOC ?= $(LCGDIR)/guardedalloc
+ export NAN_IKSOLVER ?= $(LCGDIR)/iksolver
+ export NAN_BSP ?= $(LCGDIR)/bsp
+ export NAN_STRING ?= $(LCGDIR)/string
+ export NAN_MEMUTIL ?= $(LCGDIR)/memutil
+ export NAN_CONTAINER ?= $(LCGDIR)/container
+ export NAN_ACTION ?= $(LCGDIR)/action
+ export NAN_IMG ?= $(LCGDIR)/img
+ export NAN_GHOST ?= $(LCGDIR)/ghost
+ export NAN_TEST_VERBOSITY ?= 1
+ export NAN_ZLIB ?= $(LCGDIR)/zlib
+ export NAN_BMFONT ?= $(LCGDIR)/bmfont
+ export NAN_MOZILLA ?= $(LCGDIR)/mozilla
+ export NAN_NSPR ?= $(LCGDIR)/nspr
+
+ export NAN_BUILDINFO = true
+
+ # Be paranoid regarding library creation (do not update archives)
+ export NAN_PARANOID = true
+
+ # Library Config_Guess DIRectory
+ export LCGDIR = $(NAN_LIBDIR)/$(CONFIG_GUESS)
+
+ # Object Config_Guess DIRectory
+ export OCGDIR = $(NAN_OBJDIR)/$(CONFIG_GUESS)
+
+ export CONFIG_GUESS := $(shell ${SRCHOME}/tools/guess/guessconfig)
+ export OS := $(shell echo ${CONFIG_GUESS} | sed -e 's/-.*//')
+ export OS_VERSION := $(shell echo ${CONFIG_GUESS} | sed -e 's/^[^-]*-//' -e 's/-[^-]*//')
+ export CPU := $(shell echo ${CONFIG_GUESS} | sed -e 's/^[^-]*-[^-]*-//')
+ export MAKE_START := $(shell date "+%H:%M:%S %d-%b-%Y")
+
+ ifeq ($(OS),beos)
+ ID = $(USER)
+ HOST = $(HOSTNAME)
+ endif
+ ifeq ($(OS),darwin)
+ ID = $(shell whoami)
+ HOST = $(shell hostname -s)
+ endif
+ ifeq ($(OS),freebsd)
+ ID = $(shell whoami)
+ HOST = $(shell hostname -s)
+ endif
+ ifeq ($(OS),irix)
+ ID = $(shell whoami)
+ HOST = $(shell /usr/bsd/hostname -s)
+ endif
+ ifeq ($(OS),linux)
+ ID = $(shell whoami)
+ HOST = $(shell hostname -s)
+ endif
+ ifeq ($(OS),openbsd)
+ ID = $(shell whoami)
+ HOST = $(shell hostname -s)
+ endif
+ ifeq ($(OS),solaris)
+ ID = $(shell /usr/ucb/whoami)
+ HOST = $(shell hostname)
+ endif
+ ifeq ($(OS),windows)
+ ID = $(LOGNAME)
+ endif
+ export ID HOST
+
+endif
+
+
+
diff --git a/source/nan_link.mk b/source/nan_link.mk
new file mode 100644
index 00000000000..2b8395badeb
--- /dev/null
+++ b/source/nan_link.mk
@@ -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 *****
+#
+# linking only
+
+include nan_definitions.mk
+
+ifdef NAN_DEBUG
+ LDFLAGS += $(NAN_DEBUG)
+endif
+
+DBG_LDFLAGS += -g
+
+ifneq (x$(DEBUG_DIR), x)
+ LDFLAGS+=$(DBG_LDFLAGS)
+else
+ LDFLAGS+=$(REL_LDFLAGS)
+endif
+
+######################## OS dependencies (alphabetic!) ################
+
+ # default (overriden by windows)
+SOEXT = .so
+
+ifeq ($(OS),beos)
+ LLIBS = -L/boot/develop/lib/x86/ -lGL -lbe -L/boot/home/config/lib/
+ LLIBS += -lpython1.5
+endif
+
+ifeq ($(OS),darwin)
+ LLIBS += -lGLU -lGL
+ LLIBS += -lz -framework Carbon -framework AGL
+ LDFLAGS += -L/System/Library/Frameworks/OpenGL.framework/Libraries
+ DBG_LDFLAGS += -L/System/Library/Frameworks/OpenGL.framework/Libraries
+endif
+
+ifeq ($(OS),freebsd)
+ LLIBS = -L/usr/X11R6/lib -lX11 -lXmu -lm -lutil -lz -pthread -lc_r
+ DADD = -lGL -lGLU
+ DYNLDFLAGS = -shared $(LDFLAGS)
+ ifeq ($(OS_VERSION),$(findstring $(OS_VERSION), "3.4 4.0"))
+ COMMENT = "MESA 3.0"
+ SADD = /usr/X11R6/lib/libGL.a /usr/X11R6/lib/libGLU.a
+ LLIBS += -lc
+ else
+ endif
+endif
+
+ifeq ($(OS),irix)
+ LLIBS = -lmovieGL -lGLU -lGL -lXmu -lXext -lX11 -lc -lm -ldmedia
+ LLIBS += -lcl -laudio -ldb -lCio -lz -woff 84,171
+ DYNLDFLAGS = -shared $(LDFLAGS)
+endif
+
+ifeq ($(OS),linux)
+ ifeq ($(CPU),alpha)
+ COMMENT = "MESA 3.1"
+ LLIBS = -lGL -lGLU -L/usr/X11R6/lib/ -lXmu -lXext -lX11
+ LLIBS += -lc -lm -ldl -lutil
+ LOPTS = -export-dynamic
+ endif
+ ifeq ($(CPU),i386)
+ COMMENT = "MESA 3.1"
+ LLIBS = -L$(NAN_MESA)/lib -L/usr/X11R6/lib -lXmu -lXext -lX11 -lXi
+ LLIBS += -lutil -lc -lm -ldl -lpthread
+ LOPTS = -export-dynamic
+ DADD = -lGL -lGLU
+ SADD = $(NAN_MESA)/lib/libGL.a $(NAN_MESA)/lib/libGLU.a
+ DYNLDFLAGS = -shared $(LDFLAGS)
+ endif
+ ifeq ($(CPU),powerpc)
+ COMMENT = "MESA 3.1"
+ LLIBS = -L/usr/X11R6/lib/ -lXmu -lXext -lX11 -lc -ldl -lm -lutil
+ DADD = -lGL -lGLU
+ SADD = /usr/lib/libGL.a /usr/lib/libGLU.a
+ LOPTS = -export-dynamic
+ endif
+ LLIBS += -lz
+endif
+
+ifeq ($(OS),openbsd)
+ SADD = /usr/local/lib/libGL.a /usr/local/lib/libGLU.a
+ SADD += /usr/X11R6/lib/libXmu.a /usr/X11R6/lib/libXext.a
+ SADD += /usr/X11R6/lib/libX11.a /usr/lib/libm.a -pthread
+endif
+
+ifeq ($(OS),solaris)
+ LLIBS = -lGLU -lGL -lXmu -lXext -lX11 -lc -lm -ldl -lsocket -lnsl
+ DYNLDFLAGS = -shared $(LDFLAGS)
+endif
+
+ifeq ($(OS),windows)
+ EXT = .exe
+ SOEXT = .dll
+ DADD = kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib
+ DADD += advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib
+ DADD += vfw32.lib winmm.lib opengl32.lib glu32.lib largeint.lib dxguid.lib
+ DADD += libcmt.lib
+ LOPTS = /link
+ LOPTS += /NODEFAULTLIB:"libc"
+ LOPTS += /NODEFAULTLIB:"libcd"
+ LOPTS += /NODEFAULTLIB:"libcp"
+ LOPTS += /NODEFAULTLIB:"libcpd"
+ LOPTS += /NODEFAULTLIB:"python20"
+ LOPTS += /NODEFAULTLIB:"msvcrt"
+ LOPTS += /SUBSYSTEM:CONSOLE
+ LDFLAGS += /MT
+ DYNLDFLAGS = /LD
+endif
+
diff --git a/source/nan_subdirs.mk b/source/nan_subdirs.mk
new file mode 100644
index 00000000000..40c7b63347b
--- /dev/null
+++ b/source/nan_subdirs.mk
@@ -0,0 +1,63 @@
+#
+# $Id$
+#
+# ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version. The Blender
+# Foundation also sells licenses for use in proprietary software under
+# the Blender License. See http://www.blender.org/BL/ for information
+# about this.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL/BL DUAL LICENSE BLOCK *****
+#
+# Bounce make to subdirectories.
+# Set DIRS, SOURCEDIR. Optionally also reacts on DIR, TESTDIRS.
+#
+
+default: all
+
+# do not add install here. install target can only be used in intern/
+# top level Makefiles
+all debug clean::
+ ifdef DIR
+ @# Make sure object toplevels are there
+ @[ -d $(NAN_OBJDIR) ] || mkdir $(NAN_OBJDIR)
+ @[ -d $(LCGDIR) ] || mkdir $(LCGDIR)
+ @[ -d $(OCGDIR) ] || mkdir $(OCGDIR)
+ @[ -d $(OCGDIR)/intern ] || mkdir $(OCGDIR)/intern
+ @[ -d $(OCGDIR)/extern ] || mkdir $(OCGDIR)/extern
+ @# Create object directory
+ @[ -d $(DIR) ] || mkdir $(DIR)
+ endif
+ @for i in $(DIRS); do \
+ echo "====> $(MAKE) $@ in $(SOURCEDIR)/$$i" ;\
+ $(MAKE) -C $$i $@ || exit 1; \
+ done
+
+test::
+ ifdef TESTDIRS
+ @for i in $(TESTDIRS); do \
+ echo "====> $(MAKE) $@ in $(SOURCEDIR)/$$i" ;\
+ $(MAKE) -C $$i $@ || exit 1; \
+ done
+ endif
+
diff --git a/source/nan_warn.mk b/source/nan_warn.mk
new file mode 100644
index 00000000000..072620d24ab
--- /dev/null
+++ b/source/nan_warn.mk
@@ -0,0 +1,174 @@
+#
+# $Id$
+#
+# ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version. The Blender
+# Foundation also sells licenses for use in proprietary software under
+# the Blender License. See http://www.blender.org/BL/ for information
+# about this.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL/BL DUAL LICENSE BLOCK *****
+#
+# NaN compiler and linker warning levels
+# On some platforms, you will be flooded with system include file warnings.
+# Use hmake to filter those away.
+#
+
+# Force the correct redefinition
+LEVEL_1_C_WARNINGS = -FIX_NAN_WARN
+LEVEL_1_CPP_WARNINGS = -FIX_NAN_WARN
+LEVEL_2_C_WARNINGS = -FIX_NAN_WARN
+LEVEL_2_CPP_WARNINGS = -FIX_NAN_WARN
+FIX_STUBS_WARNINGS = -FIX_NAN_WARN
+
+########################################################################
+# Level 1: basic C warnings.
+ifeq ($(CC),gcc)
+ LEVEL_1_C_WARNINGS = -Wall
+ LEVEL_1_C_WARNINGS += -Wno-char-subscripts
+else
+ ifeq ($(CC),cc)
+ ifeq ($(OS),irix)
+ # MIPSpro Compilers
+ #
+ # Irix warning info
+ #
+ # 1001 # the source file does not end w/ a newline
+ # 1110 # unreachable statement
+ # 1201 # trailing comma in enums is nonstandard
+ # 1209 # constant controlling expressions
+ # 1355 # extra semicolon is ignored
+ # 1424 # unreferenced template paramaters
+ # 1681 # virtual function override
+ # 3201 # unreferenced formal paramaters
+ #
+
+ LEVEL_1_C_WARNINGS = -fullwarn -woff 1001,1110,1201,1209,1355,1424,1681,3201
+ endif
+ endif
+ ifeq ($(OS),windows)
+ # Microsoft Compilers and cl_wrapper.pl
+ LEVEL_1_C_WARNINGS = -Wall
+ endif
+endif
+
+# Level 1: basic CPP warnings.
+ifeq ($(CCC),g++)
+ LEVEL_1_CPP_WARNINGS = -Wall
+ LEVEL_1_CPP_WARNINGS += -Wno-reorder
+else
+ ifeq ($(CCC),CC)
+ ifeq ($(OS),irix)
+ # MIPSpro Compilers
+ # see warning descriptions above
+ LEVEL_1_CPP_WARNINGS = -woff 1001,1110,1201,1209,1355,1424,1681,3201
+ endif
+ endif
+ ifeq ($(OS),windows)
+ # Microsoft Compilers and cl_wrapper.pl
+ LEVEL_1_CPP_WARNINGS = -Wall
+ endif
+endif
+
+########################################################################
+# Level 2: paranoia level C warnings.
+# DO NOT REUSE LEVEL_1_ DEFINES.
+ifeq ($(CC),gcc)
+ LEVEL_2_C_WARNINGS = -Wall
+ LEVEL_2_C_WARNINGS += -W
+ # deliberately enable char-subscript warnings
+ LEVEL_2_C_WARNINGS += -Wshadow
+ LEVEL_2_C_WARNINGS += -Wpointer-arith
+ LEVEL_2_C_WARNINGS += -Wbad-function-cast
+ LEVEL_2_C_WARNINGS += -Wcast-qual
+ LEVEL_2_C_WARNINGS += -Wcast-align
+ LEVEL_2_C_WARNINGS += -Waggregate-return
+ LEVEL_2_C_WARNINGS += -Wstrict-prototypes
+ LEVEL_2_C_WARNINGS += -Wmissing-prototypes
+ LEVEL_2_C_WARNINGS += -Wmissing-declarations
+ LEVEL_2_C_WARNINGS += -Wnested-externs
+ LEVEL_2_C_WARNINGS += -Wredundant-decls
+else
+ ifeq ($(CC),cc)
+ ifeq ($(OS),irix)
+ # MIPSpro Compilers
+ # see warning descriptions above
+ LEVEL_2_C_WARNINGS = -fullwarn -woff 1001,1209,1424,3201
+ endif
+ ifeq ($(OS),solaris)
+ # Forte / Sun WorkShop Compilers
+ LEVEL_2_C_WARNINGS = -v
+ endif
+ endif
+ ifeq ($(OS),windows)
+ # Microsoft Compilers and cl_wrapper.pl
+ LEVEL_2_C_WARNINGS = -Wall
+ endif
+endif
+
+# Level 2: paranoia level CPP warnings.
+# DO NOT REUSE LEVEL_1_ DEFINES.
+ifeq ($(CCC),g++)
+ LEVEL_2_CPP_WARNINGS = -Wall
+ LEVEL_2_CPP_WARNINGS += -W
+ # deliberately enable char-subscript warnings
+ LEVEL_2_CPP_WARNINGS += -Wshadow
+ LEVEL_2_CPP_WARNINGS += -Wpointer-arith
+ LEVEL_2_CPP_WARNINGS += -Wbad-function-cast
+ LEVEL_2_CPP_WARNINGS += -Wcast-qual
+ LEVEL_2_CPP_WARNINGS += -Wcast-align
+ # deliberately disable aggregate-return warnings
+ LEVEL_2_CPP_WARNINGS += -Wstrict-prototypes
+ LEVEL_2_CPP_WARNINGS += -Wmissing-prototypes
+ LEVEL_2_CPP_WARNINGS += -Wmissing-declarations
+ LEVEL_2_CPP_WARNINGS += -Wnested-externs
+ LEVEL_2_CPP_WARNINGS += -Wredundant-decls
+ LEVEL_2_CPP_WARNINGS += -Wreorder
+ LEVEL_2_CPP_WARNINGS += -Wctor-dtor-privacy
+ LEVEL_2_CPP_WARNINGS += -Wnon-virtual-dtor
+ LEVEL_2_CPP_WARNINGS += -Wold-style-cast
+ LEVEL_2_CPP_WARNINGS += -Woverloaded-virtual
+ LEVEL_2_CPP_WARNINGS += -Wsign-promo
+ LEVEL_2_CPP_WARNINGS += -Wsynth
+else
+ ifeq ($(CCC),CC)
+ ifeq ($(OS),irix)
+ # MIPSpro Compilers
+ # see warning descriptions above
+ LEVEL_2_CPP_WARNINGS = -fullwarn -woff 1209,1424,3201
+ endif
+ endif
+ ifeq ($(OS),windows)
+ # Microsoft Compilers and cl_wrapper.pl
+ LEVEL_2_CPP_WARNINGS = -Wall
+ endif
+endif
+
+########################################################################
+# stubs warning fix
+ifeq ($(CC),gcc)
+ FIX_STUBS_WARNINGS = -Wno-unused
+else
+ FIX_STUBS_WARNINGS =
+endif
+